diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2021-09-16 23:42:55 +0200 | 
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2021-09-16 23:42:55 +0200 | 
| commit | efaec4509af562d79582dad8017334d778489aaa (patch) | |
| tree | 1654325a7ad571062341553e8518540b82441a3f /Year_2/OS/hw | |
| parent | 79cd77906c3de2a01af9ceb1cb9689b314a970b3 (diff) | |
os: add homework 7
Diffstat (limited to 'Year_2/OS/hw')
| -rw-r--r-- | Year_2/OS/hw/hw7.c | 156 | 
1 files changed, 156 insertions, 0 deletions
| diff --git a/Year_2/OS/hw/hw7.c b/Year_2/OS/hw/hw7.c new file mode 100644 index 0000000..ca51998 --- /dev/null +++ b/Year_2/OS/hw/hw7.c @@ -0,0 +1,156 @@ +/* +    Homework n.7 + +    Modificare l'homework precedente (n.6) facendo in modo che il figlio che +    riceve il comando da eseguire tramite la coda, catturi lo standard output +    e lo standard error del figlio nipote usando la redirezione su pipe tra +    processi. L'output catturato dovrà essere mandato indietro al padre +    tramite un messaggio (per semplicita', assumiamo sufficiente grande). +    Tale contenuto sara' poi visualizzato sul terminale dal padre. + +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define MTYPE 1 +#define MTYPE_EXE 2 + +struct msgbuf { +    long mtype; +    char mtext[1024]; +}; + +void +execute(int qid) +{ +    pid_t pid; +    struct msgbuf msg; +    char command[1024]; +    int n; +    char* p; +    int pipefd[2]; + +    while (1) { +        if (msgrcv(qid, (void*)&msg, 1024, MTYPE, 0) == -1) { +            perror("msgrcv"); +            exit(1); +        } + +        /* The variable `command` will be the substring of the passed string +         * until the first space, ignoring all parameters */ +        n = 0; +        p = msg.mtext; +        while (*p != '\0') { +            if (*p == ' ') +                break; +            n++; +            p++; +        } + +        strncpy(command, msg.mtext, n); +        command[n] = '\0'; + +        if (strcmp(command, "exit") == 0) +            break; + +        if (pipe(pipefd) == -1) { +            perror("pipe"); +            exit(1); +        } + +        pid = fork(); +        if (pid == -1) { +            perror("fork"); +            exit(1); +        } + +        if (pid == 0) { +            dup2(pipefd[1], 1); +            dup2(pipefd[1], 2); +            close(pipefd[0]); +            execlp(command, "", NULL); +            fprintf(stderr, "Error executing '%s'\n", command); +            exit(1); +        } else { +            wait(NULL); + +            close(pipefd[1]); +            n = read(pipefd[0], msg.mtext, 1024); +            msg.mtext[n] = '\0'; +            msg.mtype = MTYPE_EXE; +            close(pipefd[0]); + +            if (msgsnd(qid, (void*)&msg, strlen(msg.mtext) + 1, 0) == -1) { +                perror("msgsnd"); +                exit(1); +            } +        } +    } + +    msgctl(qid, IPC_RMID, NULL); +} + +int +main() +{ +    pid_t pid; +    int qid; +    int n; + +    if ((qid = msgget(IPC_PRIVATE, IPC_CREAT | 0644)) == -1) { +        perror("msgget"); +        exit(1); +    } + +    pid = fork(); +    if (pid == -1) { +        perror("fork"); +        exit(1); +    } + +    if (pid != 0) { +        struct msgbuf msg; +        while (1) { +            printf("Insert a command: "); +            fgets(msg.mtext, 1024, stdin); +            n = strlen(msg.mtext); +            msg.mtext[n - 1] = '\0'; +            msg.mtype = MTYPE; + +            /* Ignore empty string */ +            if (strcmp(msg.mtext, "") == 0) +                continue; + +            if (msgsnd(qid, (void*)&msg, sizeof(msg.mtext), IPC_NOWAIT) == -1) { +                perror("msgsnd"); +                exit(1); +            } + +            /* Check first if the message is exit, because executing this when +             * message is "exit" raises  +             * msgrcv: Identifier removed +             */ +            if (strcmp(msg.mtext, "exit") == 0) { +                break; +            } + +            if (msgrcv(qid, (void*)&msg, 1024, MTYPE_EXE, 0) == -1) { +                perror("msgrcv"); +                exit(1); +            } + +            printf("%s\n", msg.mtext); +            sleep(1); +        } +    } else { +        execute(qid); +    } + +    return 0; +} | 
