summaryrefslogtreecommitdiff
path: root/Year_2/OS/hw
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2021-09-16 23:42:55 +0200
committerSanto Cariotti <santo@dcariotti.me>2021-09-16 23:42:55 +0200
commitefaec4509af562d79582dad8017334d778489aaa (patch)
tree1654325a7ad571062341553e8518540b82441a3f /Year_2/OS/hw
parent79cd77906c3de2a01af9ceb1cb9689b314a970b3 (diff)
os: add homework 7
Diffstat (limited to 'Year_2/OS/hw')
-rw-r--r--Year_2/OS/hw/hw7.c156
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;
+}