/*esame 15 gennaio 2014*/ #include #include #include #include #include #include #include #include typedef int pipe_t[2]; char msg[256]; /* variabile usata per le scritture su standard output e standard error */ int N; /* numero figli*/ pipe_t *p_fp; /* array dinamico di pipe figlio-padre*/ pipe_t p_nf; /* pipe nipote-figlio*/ int figlio(char *Fi, char *FFi, int indice); /* dichiarazione della funzione figlio */ int nipote(char *FFi, int indice); /* dichiarazione della funzione nipote */ /* in questa soluzione le stampe degli errori le riportiamo sullo standard error usando una write sul file descriptor 2 */ int main (int argc, char **argv) { /* dichiarazione variabili */ int i, pid, status, nr; char ch; /*carattere che riceve padre*/ /* controllo parametri: prima controlliamo che il numero di file sia maggiore o uguale a 2 */ if (argc < 3) { snprintf(msg,sizeof(msg),"Errore numero argomenti non maggiore o uguale a 2\n"); write(2,msg,strlen(msg)); exit(1); } /* controllo parametri: poi controlliamo che il numero di file sia pari */ if ((argc-1)%2) { snprintf(msg,sizeof(msg),"Errore numero argomentii non pari\n"); write(2,msg,strlen(msg)); exit(2); } /* definizione numero figli */ N=(argc-1)/2; /* allocazione: numPipe p_fp: */ p_fp=(pipe_t *)malloc(N*sizeof(pipe_t)); if (p_fp==NULL) { snprintf(msg,sizeof(msg),"Errore allocazione p_fp\n"); write(2,&msg,strlen(msg)); exit(3); } /* creazione delle N pipe */ for (i=0; i < N; i++) if ((pipe(p_fp[i]))!=0) { snprintf(msg,sizeof(msg),"Errore creazione p_fp\n"); write(2,&msg,strlen(msg)); exit(4); } /* creazione N figli */ for (i=0; i < N; i++) { switch (pid=fork()) { case 0: return figlio(argv[i+1],argv[i+1+N],i); case -1: snprintf(msg,sizeof(msg),"Errore fork()\n"); write (2,&msg,strlen(msg)); exit(5); } } /* CODICE PADRE: */ /* chiusura pipes inutilizzate: il padre legge solamente da p_fp */ for (i=0; i < N; i++) close(p_fp[i][1]); /* lettura in ordine dei figli: */ for (i=0; i < N; i++) { if ((nr=read(p_fp[i][0],&ch,sizeof(char))) < 0) { snprintf(msg,sizeof(msg),"Errore lettura da p_fp\n"); write (2,&msg,strlen(msg)); exit(6); } if(ch==-1) { snprintf(msg,sizeof(msg),"Figlio %d ha trovato carattere diverso dal nipote per i file %s e %s\n", i, argv[i+1], argv[i+1+N]); write(1,msg,strlen(msg)); } else { snprintf(msg,sizeof(msg),"Figlio %d ha trovato carattere uguale al nipote, %c per i file %s e %s\n", i, ch, argv[i+1], argv[i+1+N]); write(1,msg,strlen(msg)); } } /* recupero PID e retval: */ for (i=0; i < N; i++) { pid=wait(&status); if (pid < 0) { snprintf(msg,sizeof(msg),"Pid %d negativo\n", pid); write(1,msg,strlen(msg)); } else if (WIFEXITED(status)) { snprintf(msg,sizeof(msg),"Figlio con pid %d ha ritornato %d\n", pid, WEXITSTATUS(status)); write(1,msg,strlen(msg)); } else { snprintf(msg,sizeof(msg),"Figlio con pid %d terminato in modo anomalo\n", pid); write(2,msg,strlen(msg)); } } /* fine main */ exit(0); } int figlio (char *Fi, char *FFi,int indice) { /* definizione variabili */ int i, nw=0; int fd; /* file descriptor del file associato Fi*/ int nr; char ch; /*carattere che leggo*/ char ch_nip; /*carattere che ricevo da nipote*/ int pid;/*pid processo nipote*/ int st; /*per la wait*/ char uguali; /*carattere che invio al padre*/ if ((pipe(p_nf))!=0) { snprintf(msg,sizeof(msg),"Errore creazione p_fp\n"); write (2,&msg,strlen(msg)); return 7; } /*creazione nipote*/ pid=fork(); switch(pid) { case 0: /*nipote*/ return nipote(FFi, indice); case -1: /*errore*/ snprintf(msg,sizeof(msg),"Errore creazione processo nipote %d\n", indice); write(2,msg,strlen(msg)); return 8; } /*codice figlio*/ /* chiusura pipes inutilizzate: leggo da p_nf[0] e scrivo su p_fp[indice][1] */ close(p_nf[1]); for (i=0; i < N; i++) { close(p_fp[i][0]); if (i != indice) close(p_fp[i][1]); } /* apertura file associato Fi */ if ((fd=open(Fi,O_RDONLY)) < 0) { snprintf(msg,sizeof(msg),"Errore apertura file %s\n",Fi); write(2,msg,strlen(msg)); return 9; } /* sposto il mio I/O pointer di "indice" posizioni */ lseek(fd, (long) indice, 0); /*ora leggo il carattere da file associato Fi*/ nr=read(fd, &ch, 1); if (nr == 0) /* non dovrebbe succedere, ma per sicurezza lo controlliamo */ { snprintf(msg,sizeof(msg),"Errore lettura file %s per figlio %d\n",Fi, getpid()); write(2,msg,strlen(msg)); return 10; } /* ora leggo il carattere che mi comunica il nipote */ if (read(p_nf[0],&ch_nip,sizeof(char)) < 0){ snprintf(msg,sizeof(msg),"Errore lettura p_nf per processo di indice %d\n", indice); write(2,msg,strlen(msg)); return 11; } /* confronto caratteri */ if (ch==ch_nip) uguali = ch; else uguali = -1; /* scrittura al padre: */ if ((nw=write(p_fp[indice][1],&uguali,sizeof(char)))<0) { snprintf(msg,sizeof(msg),"Errore scrittura su p_fp %d\n", indice); write (2,&msg,strlen(msg)); return 12; } /*aspetto terminazione nipote*/ pid=wait(&st); if (pid < 0) { snprintf(msg,sizeof(msg),"Figlio ha recuperato un pid negativo\n"); write(1,msg,strlen(msg)); } if (WIFEXITED(st)==0) { snprintf(msg,sizeof(msg),"Nipote con pid %d terminato in modo anomalo\n", pid); write(2,msg,strlen(msg)); } else { snprintf(msg,sizeof(msg),"Nipote con pid %d ha tornato %d\n", pid, WEXITSTATUS(st)); write(1,msg,strlen(msg)); } /* ritorno a padre il valore ritornato dalla read*/ return nr; /* fine figlio */ } int nipote(char *FFi, int indice) { char ch; /*carattere che leggo*/ int nr; int fd; /*file desc file associato*/ int i; long int pos;/*posizione in cui leggere*/ /* chiusura delle pipe */ /* il nipote non legge da nessuna pipe */ /* scrive solo sulla p_nf[1] */ close(p_nf[0]); for(i=0;i < N; i++) { close(p_fp[i][0]); close(p_fp[i][1]); } /*apro file associato FFi*/ fd=open(FFi,O_RDONLY); if((fd=open(FFi,O_RDONLY)) < 0) { snprintf(msg,sizeof(msg),"Errore apertura file %s\n",FFi); write(2,msg,strlen(msg)); return 13; } /*devo partire da EOF e andare indietro di "indice"+1 posizioni*/ pos=(indice+1)*(-1); /*sposto I/O pointer*/ lseek(fd,pos,2); /*lettura su file associato*/ nr=read(fd,&ch,1); if (nr == 0) /* non dovrebbe succedere, ma per sicurezza lo controlliamo */ { snprintf(msg,sizeof(msg),"Errore lettura file %s per nipote %d\n", FFi, getpid()); write(2,msg,strlen(msg)); return 14; } /*ora scrivo il carattere letto sulla p_nf[1]*/ if(write(p_nf[1],&ch,sizeof(char))<0){ snprintf(msg,sizeof(msg),"Errore scrittura p_nf[1]\n"); write(2,msg,strlen(msg)); return 15; } /*ritorno al figlio exit value della read*/ return nr; /*fine nipote*/ }