previous | start | next

execvp and execve

shellex.c (from the book)

    1   /* $begin shellmain */
    2   #include "csapp.h"
    3   #define MAXARGS   128
    4   
    5   /* function prototypes */
    6   void eval(char *cmdline);
    7   int parseline(char *buf, char **argv);
    8   int builtin_command(char **argv); 
    9   
   10   int main() 
   11   {
   12       char cmdline[MAXLINE]; /* Command line */
   13   
   14       while (1) {
   15           /* Read */
   16           printf("> ");                   
   17           Fgets(cmdline, MAXLINE, stdin); 
   18           if (feof(stdin))
   19               exit(0);
   20   
   21           /* Evaluate */
   22           eval(cmdline);
   23       } 
   24   }
   25   /* $end shellmain */
   26     
   27   /* $begin eval */
   28   /* eval - Evaluate a command line */
   29   void eval(char *cmdline) 
   30   {
   31       char *argv[MAXARGS]; /* Argument list execve() */
   32       char buf[MAXLINE];   /* Holds modified command line */
   33       int bg;              /* Should the job run in bg or fg? */
   34       pid_t pid;           /* Process id */
   35       
   36       strcpy(buf, cmdline);
   37       bg = parseline(buf, argv); 
   38       if (argv[0] == NULL)  
   39           return;   /* Ignore empty lines */
   40   
   41       if (!builtin_command(argv)) { 
   42           if ((pid = Fork()) == 0) {   /* Child runs user job */
   43               if (execve(argv[0], argv, environ) < 0) {
   44                   printf("%s: Command not found.\n", argv[0]);
   45                   exit(0);
   46               }
   47           }
   48   
   49           /* Parent waits for foreground job to terminate */
   50           if (!bg) {
   51               int status;
   52               if (waitpid(pid, &status, 0) < 0)
   53                   unix_error("waitfg: waitpid error");
   54           }
   55           else
   56               printf("%d %s", pid, cmdline);
   57       }
   58       return;
   59   }
   60   
   61   /* If first arg is a builtin command, run it and return true */
   62   int builtin_command(char **argv) 
   63   {
   64       if (!strcmp(argv[0], "quit")) /* quit command */
   65           exit(0);  
   66       if (!strcmp(argv[0], "&"))    /* Ignore singleton & */
   67           return 1;
   68       return 0;                     /* Not a builtin command */
   69   }
   70   /* $end eval */
   71   
   72   /* $begin parseline */
   73   /* parseline - Parse the command line and build the argv array */
   74   int parseline(char *buf, char **argv) 
   75   {
   76       char *delim;         /* Points to first space delimiter */
   77       int argc;            /* Number of args */
   78       int bg;              /* Background job? */
   79   
   80       buf[strlen(buf)-1] = ' ';  /* Replace trailing '\n' with space */
   81       while (*buf && (*buf == ' ')) /* Ignore leading spaces */
   82           buf++;
   83   
   84       /* Build the argv list */
   85       argc = 0;
   86       while ((delim = strchr(buf, ' '))) {
   87           argv[argc++] = buf;
   88           *delim = '\0';
   89           buf = delim + 1;
   90           while (*buf && (*buf == ' ')) /* Ignore spaces */
   91                  buf++;
   92       }
   93       argv[argc] = NULL;
   94       
   95       if (argc == 0)  /* Ignore blank line */
   96           return 1;
   97   
   98       /* Should the job run in the background? */
   99       if ((bg = (*argv[argc-1] == '&')) != 0)
  100           argv[--argc] = NULL;
  101   
  102       return bg;
  103   }
  104   /* $end parseline */

Calling waitpid from more than one function, not a good idea.

This version doesn't adequately handle children when job control is added.



previous | start | next