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);
}