/**************************************************************/ /* */ /* UNIX 1 / WS 92/93 Gruppe ux803 */ /* 5. Uebung - Aufgabe 4 - command.c */ /* */ /* Vorname Name Matrikelnr. */ /* --------- ------- ------------- */ /* Dietmar Dierks 125761 */ /* Roman Czyborra 127221 */ /* Torsten Buller 117894 */ /* Gerasimos Paliatsaras 140956 */ /* */ /**************************************************************/ #include #define MAXPROC 10 /* shell process table, hopefully initialized with zeros */ static struct proc { int pid; char **argv; } ps [MAXPROC]; /* clear a ps entry */ static void clearps (pid, echo) int pid, echo; { char **argv; int i; for (i = 0; i < MAXPROC; ++ i) /* find entry */ if (ps[i].pid == pid) { if (echo) printf ("[%d] %d Done:", i, ps[i].pid); if (argv = ps[i].argv) { while (*argv) { if (echo) printf (" %s", *argv); free (*argv++); } free (ps[i].argv); } if (echo) printf ("\n"); ps[i].pid = 0; break; } } /* excerpt from ~unix1/parser.h (unused): * modes for do_wait() in module command.c: */ #define W_QUIET 1 #define W_ALLBACK 2 #define W_FIRSTBACK 3 #define W_FOR 4 /* do_wait (pid) waits for that process to terminate * do_wait (0) waits for the foreground process if there is any * if there is no foreground process it checks for background zombies only */ #include /* WNOHANG */ #include /* ECHILD */ void do_wait (pid, mode) int pid,mode; { int done; done = 0; if (pid == 0) pid = ps[0].pid; while (pid ? (done=wait(0)) != pid : (done=wait3(0,WNOHANG,0))) { if (done == -1) { if (errno == ECHILD) return; perror ("wait"); exit (0); } clearps (done, 1); /* background process */ } if (pid) clearps (pid, 0); /* foreground process */ } /* copyargs() duplicates an argument vector */ static char ** copyargs (argc, argv) int argc; char ** argv; { char ** copy, ** next; next = copy = (char **) malloc ((argc + 1) * sizeof (char *)); if (next) { while (*argv) *next++ = (char *) strdup (*argv++); *next = 0; } return (copy); } #include /* MAXPATHLEN */ #include "3/parser.h" /* struct kommando */ /* do_command executes a command */ void do_command (kp) struct kommando *kp; { int pid; char chr, *path, *next, *name, **argv, longname [MAXPATHLEN]; argv = kp->token_1; switch (pid = fork ()) { case -1: perror ("fork"); exit (-1); case 0: /* execute command */ if (!argv || !(name = argv [0])) exit (0); if (!strchr (name, '/') && (path = getenv ("PATH"))) /* parse $PATH */ for (chr = *path; chr;) { /* copy path name */ next = longname; while ((chr = *path++) && chr != ':') *next++ = chr; /* append slash */ if (next > longname) *next++ = '/'; /* append command name */ strcpy (next, name); execv (longname, argv); } else execv (name, argv); if (errno == ENOENT) printf ("command %s not found\n", name); else perror ("execv"); exit (0); default: /* parent process has to fill out birth certificate */ if (kp->is_ampersand) { int i; /* find free record for background process */ for (i = 1; (i < MAXPROC) && ps[i].pid; ++i); /* all taken already? */ if (i == MAXPROC) { printf ("ps full! must wait for %s\n", argv[0]); waitpid (pid, 0,0); } else { printf ("[%d] %d\n", i, pid); ps[i].pid = pid; ps[i].argv = copyargs (kp->num_tok1, argv); } } else { /* foreground process */ ps[0].pid = pid; /* unnecessary: ps[0].argv = copyargs (kp->num_tok1, argv) */ do_wait (pid, 0); } } }