/* ********************************************* * * Archivo de Codigo Tarea 1 de Seminario I ra.c * * Copyright 2000, por Daniel Durán Fernández * * Universidad Técnica Federico Santa María * * Valparaíso, Chile. * * ********************************************* */ #include #include #include #include #include #include "./ra.h" int expired; int to=0; char *array[5] ={ "2+2\n", "5*2\n", "6*3\n", "12*11\n", "\0" }; int main (int argc, char *argv[]) { FILE *artm; pid_t pid; int timeout=5,status,len; int ra2bc[2],bc2ra[2]; int r_ans,i; char op[32]; val tiempos; val *ptr=&tiempos; /* if ( (argc<3) && (strcmp(argv[1],"--help")==0) { printf ("\nUse:\n"); #ifdef FROMFILE printf ("ra {archivo} [timeout]\n\n"); #else printf ("ra [timeout]\n\n"); #endif }*/ #ifdef FROMFILE if (argc>3) { #else if (argc>2) { #endif printf ("Error: Demasiados parámetros\n\n"); exit(1); } #ifdef FROMFILE if (argc<2) { printf ("Error: indique el archivo de expresiones\n\n"); exit(1); } #endif #ifdef FROMFILE if (argc>2) #else if (argc>1) #endif timeout=atoi(argv[2]); timeout=(timeout==0)?5:timeout; #ifdef FROMFILE if ( (artm=fopen(argv[1],"r")) == NULL) { printf ("Error: No se encuentra el archivo \"%s\"\n\n",argv[1]); exit(1); } #endif printf ("\nRapidez Aritmética. (c)2000 por Daniel Durán\n"); #ifdef FROMFILE printf ("Versión FINAL.\n"); #else printf ("Version BETA de pruebas.\n"); #endif printf ("\n\n Responda antes de %d segundos las operaciones que aparecerán.\n",timeout); printf (" Ingrese su respuesta con ENTER.\n"); printf (" Preparese a partir dentro de 3 segundos!\n\n"); sleep(3); ptr->right=0; ptr->wrong=0; ptr->plus_time=0; ptr->last_time=0; /* Creación de pipes */ if (pipe(ra2bc) < 0) { perror("pipe"); exit(1); } if (pipe(bc2ra) < 0) { perror("pipe"); exit(1); } /* Creación del proceso hijo */ if ((pid = fork()) < 0) { perror("fork"); exit(1); } if (pid == 0) { /* Ingreso a la rutina del HIJO */ dup2(ra2bc[RD],0); /* El hijo anexa standard input a su pipa ra2bc[1]. */ close(ra2bc[WR]); /* No usa escritura del extremo de RA */ dup2(bc2ra[WR],1); /* El hijo anexa standard output a su pipa bc2ra[0]. */ close(bc2ra[RD]); /* No usa lectura del extremo de RA */ execl("/usr/bin/bc","-q",0); /* Ejecuta el programa de matemáticas bc. */ perror("exec"); _exit(127); } /* Fin del HIJO */ /* El padre cierra la pipes que no usará. */ close(ra2bc[RD]); /* No usa lectura del extremo de BC */ close(bc2ra[WR]); /* No usa escritura del extremo de BC */ if (signal(SIGALRM, sig_alrm) == SIG_ERR) perror("signal(SIGALRM) error"); #ifdef FROMFILE while ( len=get_operation(op,artm) ) { #else i=0; while (len=strlen(strcpy(op,array[i++])) ) { #endif write(ra2bc[WR],op,len); r_ans=get_value(bc2ra); op[len-1]='\0'; printf("\n %s = ?\n",op); question(ptr,r_ans,timeout); } write(ra2bc[WR],"quit\n",5); printf("\nTotal de preguntas: %d\n",ptr->right+ptr->wrong); printf("\nPorcentaje de respuestas correctas: %d%%\n",(int)(100*ptr->right)/(ptr->right+ptr->wrong)); printf("\nPreguntas no resueltas dentro de %d segundos: %d\n",timeout,to); printf("\nTiempo promedio : %3.3f segundos\n\n",(ptr->right!=0)?((float)ptr->plus_time)/((float)ptr->right):-1.0); #ifdef FROMFILE fclose(artm); #endif /* Finalización y cierre del programa */ close(ra2bc[WR]); close(bc2ra[RD]); waitpid(pid, &status, 0); dup2(STDIN_FILENO,0); dup2(STDOUT_FILENO,1); _exit(0); } static void sig_alrm(int signo) { expired=1; to++; printf(" : Tiempo Expirado! Oprima ENTER para continuar.\n"); return; } void question(val *pv,int rans,int timeout) { char ins[32]; expired=0; alarm(timeout); if ( read(STDIN_FILENO,ins,32) < 0) perror("read error"); pv->last_time=alarm(0); if (expired) pv->wrong++; else { if (rans==atoi(ins)) { pv->right++; pv->plus_time+=timeout-pv->last_time; } else pv->wrong++; } } int get_value(int *fd) { int len; char value[32]; if ( (len=read(fd[RD], value, 32)) < 0) { perror("read"); printf("\nERROR %d: No se puede leer la respuesta de BC\n"); exit(1); } value[len]='\0'; return(atoi(value)); } int get_operation(char *buff,FILE *stream){ char data; int ptr=0; data=fgetc(stream); while ( (data!=eof) && (data!='\n') && (data!=10) ) { buff[ptr++]=data; data=fgetc(stream); } buff[ptr++]='\n'; buff[ptr]='\0'; return ( ((data==eof)&&(ptr==1))?0:ptr ); }