Advertisement
Guest User

file-shell

a guest
Jan 26th, 2020
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.48 KB | None | 0 0
  1. /*
  2.  * IPC:      Coda di messaggi, shell interattiva, mappatura in memoria, lista comandi.
  3.  * PADRE:    Creazione di n processi pari alle directory passate,
  4.  *           avvio della shell interattiva.
  5.  * FIGLIO:   accede solo alla propria directory, utilizza la mappatura
  6.  *           dei file in memoria per leggere il contenuto dei file regolari ed effettuare operazioni.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <sys/types.h>
  11. #include <unistd.h>
  12. #include <sys/stat.h>
  13. #include <sys/ipc.h>
  14. #include <sys/msg.h>
  15. #include <sys/mman.h>
  16. #include <dirent.h>
  17. #include <string.h>
  18. #include <fcntl.h>
  19. #define MSGSIZE sizeof(msg)-sizeof(long)
  20. #define BUFFSIZE 1024
  21. #define PARENT 2000
  22. /* elenco dei comandi */
  23. typedef enum{
  24.     CMD_NUM,
  25.     CMD_REPLY,
  26.     CMD_SEARCH,
  27.     CMD_TOTAL,
  28.     CMD_ERR,
  29.     CMD_EXIT
  30. }cmd;
  31.  
  32. /* struttura dei messaggi scambiati*/
  33. typedef struct{
  34.     long mtype;
  35.     unsigned int n;
  36.     char buffer[BUFFSIZE];
  37.     cmd comando;
  38. }msg;
  39.  
  40. /* codice del processo figlio*/
  41. void children(int qid, char * pathfile, int num){
  42.     msg messaggio;
  43.     DIR *dir;
  44.     struct dirent* dp;
  45.     struct stat statfile;
  46.     unsigned int counter;
  47.     int fd;
  48.     char* str;
  49.    
  50.     if(chdir(pathfile) == -1){ //apre la directory passata
  51.         perror("chdir");
  52.         exit(1);
  53.     }
  54.     while(1){
  55.         msgrcv(qid, &messaggio, MSGSIZE, num, 0);
  56.         switch (messaggio.comando){
  57.         /*num-files n: n di file regolari direttamente contenuti nella directory*/
  58.         case CMD_NUM:
  59.             dir = opendir(".");
  60.             counter = 0;
  61.             while((dp = readdir(dir))){
  62.                 if(((stat(dp->d_name, &statfile)) != -1) && S_ISREG(statfile.st_mode))
  63.                     counter++;
  64.             }
  65.             closedir(dir);
  66.             messaggio.mtype = PARENT;
  67.             messaggio.n = counter;
  68.             messaggio.comando = CMD_REPLY;
  69.             msgsnd(qid, &messaggio, MSGSIZE, 0);
  70.             break;
  71.         /*search char n f c: visualizza il numero di occorrenze del carattere <c>
  72.         indicato nel file <f> specificato nella directory <n>.*/
  73.         case CMD_SEARCH:
  74.             if((fd = open(messaggio.buffer, O_RDONLY)) == -1){
  75.                 messaggio.comando = CMD_ERR;
  76.                 messaggio.mtype = PARENT;
  77.                 msgsnd(qid, &messaggio, MSGSIZE, 0);
  78.                 break;
  79.             }
  80.             if((stat(messaggio.buffer, &statfile)) == -1){
  81.                 messaggio.comando = CMD_ERR;
  82.                 messaggio.mtype = PARENT;
  83.                 msgsnd(qid, &messaggio, MSGSIZE, 0);
  84.                 break;
  85.             }
  86.             if((str = mmap(NULL, statfile.st_size, PROT_READ, MAP_SHARED, fd, 0)) == NULL){
  87.                 messaggio.comando = CMD_ERR;
  88.                 messaggio.mtype = PARENT;
  89.                 msgsnd(qid, &messaggio, MSGSIZE, 0);
  90.                 break;
  91.             }
  92.             counter = 0;
  93.             for(int i = 0; str[i] != EOF; i++){
  94.                 if(str[i] == (char)messaggio.n)
  95.                     counter++;
  96.             }
  97.             messaggio.comando = CMD_REPLY;
  98.             messaggio.mtype = PARENT;
  99.             messaggio.n = counter;
  100.             msgsnd(qid, &messaggio, MSGSIZE, 0);
  101.             munmap(str, statfile.st_size);
  102.             close(fd);
  103.             break;
  104.         /*total-size n: dim tot in byte dei file regolari direttamente contenuti nella directory*/
  105.         case CMD_TOTAL:
  106.             dir = opendir(".");
  107.             counter = 0;
  108.             while((dp = readdir(dir))){
  109.                 if(((stat(dp->d_name, &statfile)) != -1) && S_ISREG(statfile.st_mode))
  110.                     counter+=statfile.st_size;
  111.             }
  112.             closedir(dir);
  113.             messaggio.mtype = PARENT;
  114.             messaggio.n = counter;
  115.             messaggio.comando = CMD_REPLY;
  116.             msgsnd(qid, &messaggio, MSGSIZE, 0);
  117.             break;
  118.         /*q: uscita dal programma*/
  119.         case CMD_EXIT:
  120.             exit(0);
  121.             break;
  122.         }
  123.     }
  124. }
  125. /* stampa a video un menu informativo contenente la lista dei comandi disponibili*/
  126. void help(){
  127.     printf("----HELP MENU----\n");
  128.     printf("1) num-files n: visualizza il numero di fle regolari\n\tdirettamente contenuti nella directory <n>.\n");
  129.     printf("2)total-size n: visualizza la dimensione totale (in byte)\n\tdei fle regolari direttamente contenuti nella directory <n>.\n");
  130.     printf("3)search n f c: visualizza il numero di occorrenze\n\tdel carattere <c>indicato nel file <f> specificato nella directory <n>.\n");
  131.     printf("4)           q: uscita.\n");
  132.     printf("5)           h: aiuto.\n");
  133. }
  134.  
  135.  
  136. int main(int argc, char **argv){
  137.     /*dichiarazione variabili*/
  138.     int nchild;//contatore dei figli creati
  139.     int qid; //coda di messaggi
  140.     struct stat statbuf;
  141.     char buffer [BUFFSIZE];
  142.     char quit = 0;
  143.     char *token, *nomefile;
  144.     int len, n;
  145.     msg messaggio;
  146.  
  147.     /*controllo sui parametri*/
  148.     if(argc<2){
  149.         fprintf(stderr, "Utilizzo: %s   <dir-1>   <dir-2>   <...>\n", argv[0]);
  150.         exit(1);
  151.     }
  152.     /*creazione coda di messaggi*/
  153.     if((qid = msgget(IPC_PRIVATE,IPC_CREAT|IPC_EXCL|0660))==-1){
  154.         perror("msgget");
  155.         exit(1);
  156.     }
  157.     /*creazione processi figli*/
  158.     nchild = 0;
  159.     for(int i=1; i<argc; i++){
  160.         //controllo sul parametro passato. Verifica se corrisponde a directory
  161.         if ( (stat(argv[i], &statbuf)==-1) || (!S_ISDIR(statbuf.st_mode)) ){
  162.             fprintf(stderr, "Directory \"%s\" non valida. Salto al prossimo argomento.\n", argv[i]);
  163.             continue;
  164.         }  
  165.         nchild++;
  166.         if(fork()==0)
  167.             children(qid, argv[i], nchild);
  168.     }
  169.     if(nchild == 0){
  170.         fprintf(stderr, "Nessuna cartella valida\n");
  171.         exit(1);
  172.     }
  173.     /*avvia la shell interattiva */
  174.     printf("Benvenuto nella shell interattiva. Digita q per uscire, h per aiuto.\n");
  175.     sleep(1);
  176.     while(1){
  177.         printf("file-shell> ");
  178.         fgets(buffer, BUFFSIZE, stdin);
  179.         len = strlen(buffer);
  180.         if (buffer[len-1] == '\n')
  181.             buffer[len-1] = '\0';
  182.         if((token = strtok(buffer, " "))){ //estrare il primo token, cioè il comando
  183.             if(strcmp(token, "h")==0){
  184.                 help();
  185.             }else if(strcmp(token, "num-files") == 0){
  186.                 if((token = strtok(NULL, " "))){
  187.                     n = atoi(token);
  188.                     if(n > 0 && n <= nchild){
  189.                         messaggio.mtype = n;
  190.                         messaggio.comando = CMD_NUM;
  191.                         msgsnd(qid, &messaggio, MSGSIZE, 0);
  192.                         msgrcv(qid, &messaggio, MSGSIZE, PARENT, 0);
  193.                         if(messaggio.comando == CMD_REPLY)
  194.                             printf("Numero di file regolari: %d\n", messaggio.n);
  195.                     }else
  196.                         fprintf(stderr, "Figlio non esistente\n");
  197.                 }else
  198.                     fprintf(stderr, "USE: list n\n");
  199.             }else if(strcmp(token, "search") == 0){
  200.                 if((token = strtok(NULL, " "))){
  201.                     n = atoi(token);
  202.                     if(n > 0 && n <= nchild){
  203.                         if((token = strtok(NULL, " "))){
  204.                             nomefile = token;
  205.                             if((token = strtok(NULL, " "))){
  206.                                 messaggio.mtype = n;
  207.                                 messaggio.comando = CMD_SEARCH;
  208.                                 strcpy(messaggio.buffer, nomefile);
  209.                                 messaggio.n = token[0];
  210.  
  211.                                 msgsnd(qid, &messaggio, MSGSIZE, 0);
  212.                                 msgrcv(qid, &messaggio, MSGSIZE, PARENT, 0);
  213.  
  214.                                 if(messaggio.comando == CMD_REPLY)
  215.                                     printf("Numero di occorrenze di %c: %d\n", token[0], messaggio.n);
  216.                                 else
  217.                                     fprintf(stderr, "Errore dal figlio %d\n", n);
  218.                             }
  219.                         }
  220.                     }else
  221.                         fprintf(stderr, "Figlio non esistente\n");
  222.                 }else
  223.                     fprintf(stderr, "USE search n nome-file carattere\n");
  224.                
  225.             }else if(strcmp(token, "total-size")==0){
  226.                 if((token = strtok(NULL, " "))){
  227.                     n = atoi(token);
  228.                     if(n > 0 && n <= nchild){
  229.                         messaggio.mtype = n;
  230.                         messaggio.comando = CMD_TOTAL;
  231.                         msgsnd(qid, &messaggio, MSGSIZE, 0);
  232.                         msgrcv(qid, &messaggio, MSGSIZE, PARENT, 0);
  233.                         if(messaggio.comando == CMD_REPLY)
  234.                             printf("Dimensione totale dei file nella cartella: %d bytes.\n", messaggio.n);
  235.                         else
  236.                             fprintf(stderr, "Errore dal figlio %d\n", n);
  237.                     }else
  238.                         fprintf(stderr, "Figlio non esistente\n");
  239.                 }
  240.  
  241.             }else if(strcmp(token, "q") == 0)
  242.                 break;
  243.             else
  244.                 fprintf(stderr, "Comando non riconosciuto.\n");
  245.         }
  246.     }
  247.     messaggio.comando = CMD_EXIT;
  248.     for(int i = 1; i <= nchild; i++){
  249.         messaggio.mtype = i;
  250.         msgsnd(qid, &messaggio, MSGSIZE, 0);
  251.     }
  252.     //chiusura delle strutture
  253.     msgctl(qid, IPC_RMID, NULL);
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement