/* Soluzione della Prova d'esame del 10 Giugno 2020 - Parte C */ #include #include #include #include #include #include #include #include #define PERM 0644 typedef int pipe_t[2]; int main(int argc, char **argv) { /* -------- Variabili locali ---------- */ int pid; /* process identifier per le fork() */ int Q; /* numero di file passati sulla riga di comando */ int pidFiglio, status; /* variabili per la wait */ pipe_t *p; /* array dinamico di pipe per la comunicazione fra figli e padre */ char linea[250]; /* array per linea, che come indicato nel testo, si puo' supporre di lunghezza 250 char compreso il terminatore di linea */ int fd; /* file descriptor che serve ai figli */ int fdw; /* file descriptor che serve al padre */ int q, k; /* indici per i cicli */ int ritorno=0; /* variabile che viene ritornata da ogni figlio al padre */ /* ------------------------------------ */ /* controllo parametri: almeno due file */ if (argc < 3) /* Meno di due parametri */ { printf("Errore nel numero dei parametri %d\n", argc); exit(1); } /* Calcoliamo il numero di file passati */ Q=argc-1; printf("Numero processi da creare %d\n", Q); /* allocazione dinamica memoria per pipe */ p=(pipe_t*)malloc(Q*sizeof(pipe_t)); if (p==NULL) { printf("Errore nelle malloc\n"); exit(3); } /* creazione pipe */ for (q=0; q < Q; q++) { if(pipe(p[q])!=0) { printf("Errore creazione delle pipe\n"); exit(4); } } /* creazione file prima di creare i figli. NOTA BENE: nei testi, per un mero errore materiale, non era stato riportato che il padre doveva scrivere le linee ricevute sul file. Chiaramente, nella correzione si e' considerato che il file dovesse essere solo creato, ma non usato nel resto del codice! */ fdw=creat("Camilla", PERM); if (fdw < 0) { printf("Errore creazione file Camilla\n"); exit(5); } /* creazione figli */ for (q=0; q < Q; q++) { if((pid=fork())<0) { printf("Errore nella fork %d-esima\n", q); exit(5); } if(pid==0) { printf("Figlio con indice %d e pid %d analizza file %s\n",q,getpid(),argv[q+1]); for (k=0; k < Q; k++) { /* chiudo i lati inutilizzati */ close(p[k][0]); if (k != q) close(p[k][1]); } /* il figlio deve aprire il suo file in lettura */ if((fd=open(argv[q+1],O_RDONLY))<0) { printf("Errore apertura filei %s", argv[q+1]); exit(-1); /* decidiamo di tornare -1 che verra' interpretato dal padre come 255 e quindi un valore non ammissibile! */ } k=0; /* inizializziamo l'indice della linea */ while (read(fd,&(linea[k]),1)) { if (linea[k] == '\n') /* se siamo a fine linea */ { if (isdigit(linea[0]) && (k+1 < 10)) /* se il primo carattere della linea e' un carattere numerico e se la lunghezza delle linea, compreso il terminatore, e' strettamente minore di 10, dobbiamo mandare al padre */ { write(p[q][1],linea,k+1); ritorno++; /* dobbiamo incrementare il conteggio delle linee inviate al padre */ } k=0; /* dobbiamo resettare l'indice della linea per la lettura della prossima linea */ } else k++; /* se non siamo a fine linea, dobbiamo incrementare l'indice della linea */ } /* ritorno al padre */ exit(ritorno); } } /* codice del padre */ /* chiude lati che non usa */ for(q=0;q < Q; q++) close(p[q][1]); /* si legge dalle pipe tutte le linee per ogni figlio: nota bene che la lettura va fatta carattere per carattere fino allo '\n' pari poi da dispari, come specificato dal testo */ for(q=0; q < Q; q++) { k=0; /* inizializziamo l'indice della linea */ while (read(p[q][0],&(linea[k]),1)) { if (linea[k] == '\n') /* se siamo a fine linea */ { linea[k+1]='\0'; /* inseriamo il terminatore di stringa */ /* stampiamo quanto richiesto dal testo */ printf("Il figlio di indice %d ha trovato nel file %s la linea seguente\n%s che inizia con un carattere numerico e che ha una lunghezza, compreso il terminatore di linea, strettamente minore di 10\n", q, argv[q+1],linea); /* ora dobbiamo scriverla sul file, ma senza il terminatore di stringa */ write(fdw, linea, k+1); k=0; /* dobbiamo resettare l'indice della linea per la lettura della prossima linea */ } else k++; /* se non siamo a fine linea, dobbiamo incrementare l'indice della linea */ } } /* Attesa della terminazione dei figli */ for(q=0; q < Q; q++) { pidFiglio = wait(&status); if (pidFiglio < 0) { printf("Errore wait\n"); exit(6); } if ((status & 0xFF) != 0) printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio); else { ritorno=(int)((status >> 8) & 0xFF); if (ritorno==255) printf("Il figlio con pid=%d ha ritornato %d e quindi vuole dire che ci sono stati dei problemi\n", pidFiglio, ritorno); else printf("Il figlio con pid=%d ha ritornato %d\n", pidFiglio, ritorno); } } exit(0); }/* fine del main */