-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpsh.c
More file actions
204 lines (171 loc) · 4.49 KB
/
psh.c
File metadata and controls
204 lines (171 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
* psh - A prototype tiny shell program with job control
*
* <Put your name and login ID here>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include "util.h"
/* Global variables */
int verbose = 0; /* if true, print additional output */
extern char **environ; /* defined in libc */
static char prompt[] = "psh> "; /* command line prompt (DO NOT CHANGE) */
/* End global variables */
/* Function prototypes */
/* Here are the functions that you will implement */
void eval(char *cmdline);
int builtin_cmd(char **argv);
/* Here are helper routines that we've provided for you */
void usage(void);
void sigquit_handler(int sig);
/*
* main - The shell's main routine
*/
int main(int argc, char **argv)
{
char c;
char cmdline[MAXLINE];
int emit_prompt = 1; /* emit prompt (default) */
/* Redirect stderr to stdout (so that driver will get all output
* on the pipe connected to stdout) */
dup2(1, 2);
/* Parse the command line */
while ((c = getopt(argc, argv, "hvp")) != EOF) {
switch (c) {
case 'h': /* print help message */
usage();
break;
case 'v': /* emit additional diagnostic info */
verbose = 1;
break;
case 'p': /* don't print a prompt */
emit_prompt = 0; /* handy for automatic testing */
break;
default:
usage();
}
}
/* This one provides a clean way to kill the shell */
Signal(SIGQUIT, sigquit_handler);
/* Execute the shell's read/eval loop */
while (1) {
/* Read command line */
if (emit_prompt) {
printf("%s", prompt);
fflush(stdout);
}
if ((fgets(cmdline, MAXLINE, stdin) == NULL) && ferror(stdin))
app_error("fgets error");
if (feof(stdin)) { /* End of file (ctrl-d) */
fflush(stdout);
exit(0);
}
/* Evaluate the command line */
eval(cmdline);
fflush(stdout);
fflush(stdout);
}
exit(0); /* control never reaches here */
}
/* Fork wrapper - Paul drove here
* Taken from Bryant and O'Hall page 718 */
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
/*
* eval - Evaluate the command line that the user has just typed in
*
* If the user has requested a built-in command (quit)
* then execute it immediately. Otherwise, fork a child process and
* run the job in the context of the child. If the job is running in
* the foreground, wait for it to terminate and then return.
*/
/* Taken from Bryant & O'Hall page 735 */
void eval(char *cmdline) /* Zoe and Paul drove here */
{
char *argv[MAXARGS];
char buf[MAXLINE];
int bg; /* run in bg or fg? */
pid_t pid;
strcpy(buf, cmdline);
bg = parseline(buf, argv);
if (argv[0] == NULL)
return; /* Ignore empty lines */
if (!builtin_cmd(argv))
{
if ((pid = Fork()) == 0)
{
if (execv(argv[0], argv) < 0 )
{
printf("%s: Command not found.\n", argv[0]);
exit(0);
}
}
/* Parent waits for fg job to finish */
if (!bg)
{
int status;
if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error");
}
else
printf("%d Process Running: %s", pid, cmdline);
}
return;
}
/* end code excerpt */
/*
* builtin_cmd - If the user has typed a built-in command then execute
* it immediately.
* Return 1 if a builtin command was executed; return 0
* if the argument passed in is *not* a builtin command.
*/
/* Zoe drove here */
/* Taken from Bryant & O'Hall page 735 */
int builtin_cmd(char **argv)
{
if (!strcmp(argv[0], "quit")) /* quit command */
exit(0);
if (!strcmp(argv[0], "&")) /* Ignore singleton & */
return 1;
return 0; /* not a builtin command */
}
/* end code excerpt */
/***********************
* Other helper routines
***********************/
/*
* usage - print a help message
*/
void usage(void)
{
printf("Usage: shell [-hvp]\n");
printf(" -h print this message\n");
printf(" -v print additional diagnostic information\n");
printf(" -p do not emit a command prompt\n");
exit(1);
}
/*
* sigquit_handler - The driver program can gracefully terminate the
* child shell by sending it a SIGQUIT signal.
*/
void sigquit_handler(int sig)
{
ssize_t bytes;
const int STDOUT = 1;
bytes = write(STDOUT, "Terminating after receipt of SIGQUIT signal\n", 45);
if(bytes != 45)
exit(-999);
exit(1);
}