From 21a88dd053069c17b619a89bf2c8beefb672fcd5 Mon Sep 17 00:00:00 2001
From: kaashoek <kaashoek>
Date: Wed, 6 Sep 2006 15:32:21 +0000
Subject: [PATCH] some pipe support in sh bug in proc_wait

---
 cat.c  |  20 +++---
 proc.c |   4 +-
 sh.c   | 202 ++++++++++++++++++++++++++++++++++++---------------------
 3 files changed, 141 insertions(+), 85 deletions(-)

diff --git a/cat.c b/cat.c
index 631bd09..9b2ff11 100644
--- a/cat.c
+++ b/cat.c
@@ -27,17 +27,17 @@ main(int argc, char *argv[])
   if (argc <= 1) {
     rfile(0);
   } else {
-  for(i = 1; i < argc; i++){
-    fd = open(argv[i], 0);
-    if(fd < 0){
-      puts("cat: cannot open ");
-      puts(argv[i]);
-      puts("\n");
-      exit();
+    for(i = 1; i < argc; i++){
+      fd = open(argv[i], 0);
+      if(fd < 0){
+	puts("cat: cannot open ");
+	puts(argv[i]);
+	puts("\n");
+	exit();
+      }
+      rfile(fd);
+      close(fd);
     }
-    rfile(fd);
-    close(fd);
-  }
   }
 
   exit();
diff --git a/proc.c b/proc.c
index 80141db..d90b057 100644
--- a/proc.c
+++ b/proc.c
@@ -371,7 +371,7 @@ proc_wait(void)
     havekids = 0;
     for(i = 0; i < NPROC; i++){
       p = &proc[i];
-      if(p->ppid == cp->pid){
+      if(p->state != UNUSED && p->ppid == cp->pid){
         if(p->state == ZOMBIE){
           // Found one.
           kfree(p->mem, p->sz);
@@ -385,7 +385,7 @@ proc_wait(void)
         havekids = 1;
       }
     }
-    
+
     // No point waiting if we don't have any children.
     if(!havekids){
       release(&proc_table_lock);
diff --git a/sh.c b/sh.c
index b2905e7..0c9e7e6 100644
--- a/sh.c
+++ b/sh.c
@@ -7,21 +7,28 @@
 #define BUFSIZ  512
 #define MAXARGS  10
 #define MAXNODE 2
+#define MAXCMD  2
 
-// only allocate nodes for i/o redir; at some point we may have to build a 
-// a real parse tree.
-struct node {
+// an embarrassingly naive shell
+
+// some day a real parse tree; for now ad-hoc
+struct ionode {
   int token;
   char *s;
 };
-struct node list[MAXNODE];
-int nextnode;
+struct ionode iolist[MAXNODE];
+int nextio;
 
-char buf[BUFSIZ];
-char *argv[MAXARGS];
-char argv0buf[BUFSIZ];
-int argc;
+struct cmd {
+  char *argv[MAXARGS];
+  char argv0buf[BUFSIZ];
+  int argc;
+  int token;
+};
+struct cmd cmdlist[MAXCMD]; 
+int nextcmd;
 
+char buf[BUFSIZ];
 int debug = 0;
 
 int parse(char *s);
@@ -29,7 +36,7 @@ void runcmd(void);
 int ioredirection(void);
 int gettoken(char *s, char **token);
 int _gettoken(char *s, char **p1, char **p2);
-void addnode(int token, char *s);
+void addio(int token, char *s);
 
 int
 main(void)
@@ -48,21 +55,25 @@ int
 parse(char *s)
 {
   char *t;
-  int c;
+  int c, i;
 
   gettoken(s, 0);
 
-  argc = 0;
-  nextnode = 0;
+  nextio = 0;
+  nextcmd = 0;
+  for (i = 0; i < MAXCMD; i++) {
+    cmdlist[i].argc = 0;
+    cmdlist[i].token = 0;
+  }
   while (1) {
     switch ((c = gettoken(0, &t))) {
 
     case 'w':	// Add an argument
-      if (argc == MAXARGS) {
+      if (cmdlist[nextcmd].argc >= MAXARGS) {
 	printf(2, "too many arguments\n");
 	return -1;
       }
-      argv[argc++] = t;
+      cmdlist[nextcmd].argv[cmdlist[nextcmd].argc++] = t;
       break;
 			
     case '<':	// Input redirection
@@ -71,7 +82,7 @@ parse(char *s)
 	printf(2, "syntax error: < not followed by word\n");
 	return -1;
       }
-      addnode('<', t);
+      addio('<', t);
       break;
 			
     case '>':	// Output redirection
@@ -80,7 +91,13 @@ parse(char *s)
 	printf(2, "syntax error: > not followed by word\n");
 	return -1;
       }
-      addnode('>', t);
+      addio('>', t);
+      break;
+
+    case ';':  // command sequence
+    case '|':  // pipe
+      cmdlist[nextcmd].token = c;
+      nextcmd++;
       break;
 
     case 0:		// String is complete
@@ -98,88 +115,127 @@ parse(char *s)
 void
 runcmd(void)
 {
-  int i, r, pid;
+  int c, i, r, pid, tfd;
+  int fdarray[2];
 
   // Return immediately if command line was empty.
-  if(argc == 0) {
+  if(cmdlist[0].argc == 0) {
     if (debug)
       printf(2, "EMPTY COMMAND\n");
     return;
   }
 
-  // Clean up command line.
-  // Read all commands from the filesystem: add an initial '/' to
-  // the command name.
-  // This essentially acts like 'PATH=/'.
-  if (argv[0][0] != '/') {
-    argv0buf[0] = '/';
-    strcpy(argv0buf + 1, argv[0]);
-    argv[0] = argv0buf;
-  }
-  argv[argc] = 0;
+  for (c = 0; c <= nextcmd; c++) {
+    // Clean up command line.
+    // Read all commands from the filesystem: add an initial '/' to
+    // the command name.
+    // This essentially acts like 'PATH=/'.
+    if (cmdlist[c].argv[0][0] != '/') {
+      cmdlist[c].argv0buf[0] = '/';
+      strcpy(cmdlist[c].argv0buf + 1, cmdlist[c].argv[0]);
+      cmdlist[c].argv[0] = cmdlist[c].argv0buf;
+    }
+    cmdlist[c].argv[cmdlist[c].argc] = 0;
 	
-  // Print the command.
-  if (debug) {
-    printf(2, "[%d] SPAWN:", getpid());
-    for (i = 0; argv[i]; i++)
-      printf(2, " %s", argv[i]);
-    for (i = 0; i < nextnode; i++) {
-      printf(2, "%c %s", list[i].token, list[i].s);
+    // Print the command.
+    if (debug) {
+      printf(2, "[%d] SPAWN:", getpid());
+      for (i = 0; cmdlist[c].argv[i]; i++)
+	printf(2, " %s", cmdlist[c].argv[i]);
+      for (i = 0; i < nextio; i++) {
+	printf(2, "%c %s", iolist[i].token, iolist[i].s);
+      }
+      printf(2, "\n");
     }
-    printf(2, "\n");
-  }
-
-  if (strcmp(argv[0], "/cd") == 0) {
-    if (debug) printf (2, "/cd %s is build in\n", argv[1]);
-    chdir(argv[1]);
-    return;
-  }
 
-  pid = fork();
-  if (pid == 0) {
-    if (ioredirection() < 0)
-      exit();
-    if ((r = exec(argv0buf, (char**) argv)) < 0) {
-      printf(2, "exec %s: %d\n", argv[0], r);
-      exit();
+    if (strcmp(cmdlist[c].argv[0], "/cd") == 0) {
+      if (debug) printf (2, "/cd %s is build in\n", cmdlist[c].argv[1]);
+      chdir(cmdlist[c].argv[1]);
+      return;
     }
-  }
 
-  if (pid > 0) {
-    if (debug)
-      printf(2, "[%d] WAIT %s\n", getpid(), argv[0]);
-    wait();
-    if (debug)
-      printf(2, "[%d] wait finished\n", getpid());
+    if (cmdlist[c].token == '|')
+      if (pipe(fdarray) < 0)
+	printf(2, "cmd %d pipe failed\n", c);
+
+    pid = fork();
+    if (pid == 0) {
+      if (cmdlist[c].token == '|') {
+	if (close(1) < 0) 
+	  printf(2, "close 1 failed\n");
+	if ((tfd = dup(fdarray[1])) < 0)
+	  printf(2, "dup failed\n");
+	if (close(fdarray[0]) < 0)
+	  printf(2, "close fdarray[0] failed\n");
+	if (close(fdarray[1]) < 0)
+	  printf(2, "close fdarray[1] failed\n");
+      }
+      if (c > 0 && cmdlist[c-1].token == '|') {
+	if (close(0) < 0) 
+	  printf(2, "close 0 failed\n");
+	if ((tfd = dup(fdarray[0])) < 0)
+	  printf(2, "dup failed\n");
+	if (close(fdarray[0]) < 0)
+	  printf(2, "close fdarray[0] failed\n");
+	if (close(fdarray[1]) < 0)
+	  printf(2, "close fdarray[1] failed\n");
+      }
+      if (ioredirection() < 0)
+	exit();
+      if ((r = exec(cmdlist[c].argv0buf, (char**) cmdlist[c].argv)) < 0) {
+	printf(2, "exec %s: %d\n", cmdlist[c].argv[0], r);
+	exit();
+      }
+    } else if (pid > 0) {
+      int p;
+      if (debug)
+	printf(2, "[%d] FORKED child %d\n", getpid(), pid);
+
+      if (c > 0 && cmdlist[c-1].token == '|') {
+	close(fdarray[0]);
+	close(fdarray[1]);
+      }
+      if (cmdlist[c].token != '|') {
+	if (debug)
+	  printf(2, "[%d] WAIT for children\n", getpid());
+	do {
+	  p = wait();
+	  if (debug)
+	    printf(2, "[%d] WAIT child %d finished\n", getpid(), p);
+	} while (p > 0);
+	if (debug)
+	  printf(2, "[%d] wait finished\n", getpid());
+      }
+    }
   }
 }
 
 int
 ioredirection(void)
 {
-  int i, fd, dfd;
+  int i, fd;
 
-  for (i = 0; i < nextnode; i++) {
-    switch (list[i].token) {
+  for (i = 0; i < nextio; i++) {
+    switch (iolist[i].token) {
     case '<':
       if (close(0) < 0)
 	printf(2, "close 0 failed\n");
-      if ((fd = open(list[i].s, O_RDONLY)) < 0) {
-	printf(2, "failed to open %s for read: %d", list[i].s, fd);
+      if ((fd = open(iolist[i].s, O_RDONLY)) < 0) {
+	printf(2, "failed to open %s for read: %d", iolist[i].s, fd);
 	return -1;
       }
       if (debug)
-	printf(2, "redirect 0 from %s\n", list[i].s);
+	printf(2, "redirect 0 from %s\n", iolist[i].s);
       break;
     case '>':
       if (close(1) < 0)
 	printf(2, "close 1 failed\n");
-      if ((fd = open(list[i].s, O_WRONLY|O_CREATE)) < 0) {
-	printf(2, "failed to open %s for write: %d", list[i].s, fd);
+      if ((fd = open(iolist[i].s, O_WRONLY|O_CREATE)) < 0) {
+	printf(2, "failed to open %s for write: %d", iolist[i].s, fd);
 	exit();
       }
       if (debug)
-	printf(2, "redirect 1 to %s\n", list[i].s);
+	printf(2, "redirect 1 to %s\n", iolist[i].s);
       break;
     }
   }
@@ -187,16 +243,16 @@ ioredirection(void)
 }
 
 void
-addnode(int token, char *s)
+addio(int token, char *s)
 {
-  if (nextnode >= MAXNODE) {
-    printf(2, "addnode: ran out of nodes\n");
+  if (nextio >= MAXNODE) {
+    printf(2, "addio: ran out of nodes\n");
     return;
   }
     
-  list[nextnode].token = token;
-  list[nextnode].s = s;
-  nextnode++;
+  iolist[nextio].token = token;
+  iolist[nextio].s = s;
+  nextio++;
 }
 
 
-- 
GitLab