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.