Warning: Undefined array key "view" in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 2

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 47

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 48

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 49

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 50

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 51
/* Sistemi Operativi - prova di laboratorio compito del 01/07/2015 - soluzione */ #include #include #include #include #include #include #include #include #include #define TEXT_DIM 900 #define BUFFER_SIZE 4096 #define DEST_PARENT 1000 /* enumerazione dei possibili payload dei messaggi */ typedef enum { CMD_LIST, CMD_SIZE, CMD_SEARCH, CMD_EXIT, REPLY_ERROR, REPLY_DATA, REPLY_DATA_STOP } type_payload; /* la struttura di un messaggio scambiato tra i processi: */ typedef struct { long type; // indicazione del destinatario: 1...n ai figli, DEST_PARENT=1000 per il padre type_payload payload; // il payload del messaggio: un comando, la risposta/e o una segnalazione di errore char text[TEXT_DIM]; // un stringa o long number; // un numero } msg; /* il generico figlio D-n che gestisce l'esecuzione delle richieste sulla propria directory */ void child_dir(int num, char *dir, int queue) { msg message; struct stat statbuf; DIR *dp; struct dirent *entry; FILE *file; char buffer[BUFFER_SIZE]; int occurrences; char done = 0; printf("figlio D-%d su directory '%s' avviato\n", num, dir); /* si sposta nella directory da gestire */ if (chdir(dir) == -1) { perror(dir); exit(1); } do { /* riceve il messaggio con il comando da eseguire */ if (msgrcv(queue, &message, sizeof(msg) - sizeof(long), num, 0) == -1) { perror("msgrcv"); exit(1); } switch(message.payload) { case CMD_LIST: /* legge il contenuto della directory corrente */ dp = opendir("."); message.type = DEST_PARENT; while ((entry=readdir(dp)) != NULL) { lstat(entry->d_name, &statbuf); if (S_ISREG(statbuf.st_mode)) { /* invia un messaggio per ogni file */ message.payload = REPLY_DATA; strncpy(message.text, entry->d_name, TEXT_DIM); msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); } } /* invia un messaggio finale di tipo REPLY_DATA_STOP per segnalare la fine della lista */ message.payload = REPLY_DATA_STOP; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); closedir(dp); break; case CMD_SIZE: message.type = DEST_PARENT; if ((lstat(message.text, &statbuf) == -1) || (!S_ISREG(statbuf.st_mode))) { message.payload = REPLY_ERROR; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); break; } /* invia un messaggio con la dimensione in byte */ message.payload = REPLY_DATA; message.number = statbuf.st_size; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); break; case CMD_SEARCH: /* si fanno una serie di controlli sul file e poi si tenta di aprirlo in lettura */ if ((lstat(message.text, &statbuf) == -1) || (!S_ISREG(statbuf.st_mode)) || ((file = fopen(message.text, "r")) == NULL)) { /* in caso di problemi si invia un messaggio di tipo REPLY_ERROR */ message.type = DEST_PARENT; message.payload = REPLY_ERROR; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); /* si estrae il secondo messaggio per pulire la coda */ msgrcv(queue, &message, sizeof(msg) - sizeof(long), num, 0); break; } /* riceve il secondo messaggio di tipo CMD_SEARCH con la parola da cercare */ msgrcv(queue, &message, sizeof(msg) - sizeof(long), num, 0); occurrences = 0; while (fgets(buffer, BUFFER_SIZE, file)) if (strstr(buffer, message.text)) occurrences++; /* invia un messaggio con il numero di occorrenze */ message.type = DEST_PARENT; message.payload = REPLY_DATA; message.number = occurrences; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); break; case CMD_EXIT: done = 1; break; } } while (!done); printf("figlio D-%d terminato\n", num); exit(0); } int main(int argc, char **argv) { int queue; int i, len, children; struct stat statbuf; char buffer[BUFFER_SIZE]; msg message; char *token; char done = 0; if (argc <= 1) { fprintf(stderr, "uso: %s ...\n", argv[0]); exit(1); } if ((queue = msgget(IPC_PRIVATE, IPC_CREAT|0600)) == -1) { perror("msgget"); exit(1); } /* crea i processi figli necessari */ children = 0; for (i = 1; i < argc; i++) { if ((stat(argv[i], &statbuf) == -1) || (!S_ISDIR(statbuf.st_mode))) { fprintf(stderr, "sembra esserci qualche problema con il parametro '%s': lo salto!\n", argv[i]); continue; } children++; if (fork() == 0) child_dir(i, argv[i], queue); } if (children == 0) { fprintf(stderr, "nessuno dei parametri passati era valido!\n"); exit(1); } sleep(1); do { printf("file-shell> "); fgets(buffer, BUFFER_SIZE, stdin); len = strlen(buffer); if (buffer[len-1] == '\n') buffer[len-1] = '\0'; if (token = strtok(buffer, " ")) { // estrae il primo token: il comando if (strcmp(token, "list") == 0) { if (token = strtok(NULL, " ")) { // estrae il secondo token: il numero del figlio i = atoi(token); if ((i >= 1) && (i <= children)) { /* invia un messaggio al figlio indicato con la richista CMD_LIST */ message.type = i; message.payload = CMD_LIST; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); /* riceve una serie di messaggi (uno per file) fino a REPLY_DATA_STOP */ while (1){ msgrcv(queue, &message, sizeof(msg) - sizeof(long), DEST_PARENT, 0); if (message.payload == REPLY_ERROR) { fprintf(stderr, "P - errore dal figlio\n"); break; } else if (message.payload == REPLY_DATA_STOP) break; printf("\t%s\n", message.text); } } } } else if (strcmp(token, "size") == 0) { if (token = strtok(NULL, " ")) { // estrae il secondo token: il numero del figlio i = atoi(token); if ((i >= 1) && (i <= children)) { message.type = i; if (token = strtok(NULL, " ")) { // estrae il terzo token: il nome del file /* invia un messaggio al figlio indicato con la richista CMD_SIZE */ strncpy(message.text, token, TEXT_DIM); message.payload = CMD_SIZE; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); /* riceve un messaggio con la risposta */ msgrcv(queue, &message, sizeof(msg) - sizeof(long), DEST_PARENT, 0); if (message.payload == REPLY_ERROR) fprintf(stderr, "P - errore dal figlio\n"); else printf("\t%ld byte\n", message.number); } } } } else if (strcmp(token, "search") == 0) { if (token = strtok(NULL, " ")) { // estrae il secondo token: il numero del figlio i = atoi(token); if ((i >= 1) && (i <= children)) { message.type = i; if (token = strtok(NULL, " ")) { // estrae il terzo token: il nome del file /* invierà due messaggi di tipo CMD_SEARCH: uno con il nome del file e un altro con la parola da cercare qui viene intanto preparato il primo */ strncpy(message.text, token, TEXT_DIM); message.payload = CMD_SEARCH; if (token = strtok(NULL, " ")) { // estrae il quarto token: la parola da cercare /* invia il primo messaggio solo dopo essere sicuri di avere la parola */ msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); /* crea ed invia il secondo messaggio */ strncpy(message.text, token, TEXT_DIM); message.payload = CMD_SEARCH; msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0); /* riceve un messaggio con la risposta */ msgrcv(queue, &message, sizeof(msg) - sizeof(long), DEST_PARENT, 0); if (message.payload == REPLY_ERROR) fprintf(stderr, "P - errore dal figlio\n"); else printf("\t%ld occorrenza/e\n", message.number); } } } } } else if ((strcmp(token, "exit") == 0) || (strcmp(token, "quit") == 0)) { done = 1; } else fprintf(stderr, "P - comando '%s' non riconosciuto!\n", token); } } while (!done); /* invia una serie di messaggi di tipo CMD_EXIT a tutti i figli e ne aspetta la terminazione */ for (i = 1; i <= children; i++) { message.type = i; message.payload = CMD_EXIT; if (msgsnd(queue, &message, sizeof(msg) - sizeof(long), 0) == -1) perror("msgsnd"); } for (i = 1; i <= children; i++) wait(NULL); msgctl(queue, IPC_RMID, NULL); }