int main(int argc, char *argv[]) {
while (true) {
char command[kMaxCommandLength + 1];
readCommand(command, sizeof(command) - 1);
if (feof(stdin)) break;
char *arguments[kMaxArgumentCount + 1];
int count = parseCommandLine(command, arguments,
sizeof(arguments)/sizeof(arguments[0]));
if (count == 0) continue;
bool builtin = handleBuiltin(arguments);
if (builtin) continue; // it's been handled, move on
bool isBackgroundProcess = strcmp(arguments[count - 1], "&") == 0;
if (isBackgroundProcess) arguments[--count] = NULL; // overwrite "&"
pid_t pid = forkProcess(); if (pid == 0) {
if (execvp(arguments[0], arguments) < 0) {
printf("%s: Command not found\n", arguments[0]);
exit(0);
}
}
if (!isBackgroundProcess) {
waitForChildProcess(pid);
} else {
printf("%d %s\n", pid, command);
}
}
printf("\n");
return 0;
}static bool handleBuiltin(char *arguments[]) {
if (strcasecmp(arguments[0], "quit") == 0) exit(0);
return strcmp(arguments[0], "&") == 0;
}
static pid_t forkProcess() {
pid_t pid = fork();
exitIf(pid == -1, kForkFailed, stderr, "fork function failed.\n");
return pid;
}
static void waitForChildProcess(pid_t pid) {
exitUnless(waitpid(pid, NULL, 0) == pid, kWaitFailed,
stderr, "Error waiting in foreground for process %d to exit", pid);
}int pipe(int fds[]); // fds array should be of length 2, return -1 on error, 0 otherwise
typedef struct {
pid_t pid;
int infd;
} subprocess_t;
subprocess_t subprocess(const char *command);
int main(int argc, char *argv[]) {
subprocess_t sp = subprocess("/usr/bin/sort");
const char *words[] = {
"felicity", "umbrage", "susurration", "halcyon",
"pulchritude", "ablution", "somnolent", "indefatigable"
};
for (size_t i = 0; i < sizeof(words)/sizeof(words[0]); i++) {
dprintf(sp.infd, "%s\n", words[i]);
}
close(sp.infd); // effectively sends cntl-D to child process
int status;
pid_t pid = waitpid(sp.pid, &status, 0);
return pid == sp.pid && WIFEXITED(status) ? WEXITSTATUS(status) : -1;
}
myth22> ./subprocess-test
ablution
felicity
halcyon
indefatigable
pulchritude
somnolent
susurration
umbragesubprocess_t subprocess(const char *command) {
int fds[2];
pipe(fds);
subprocess_t process = { fork(), fds[1] };
if (process.pid == 0) {
close(fds[1]);
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
char *argv[] = {"/bin/sh", "-c", (char *) command, NULL};
execvp(argv[0], argv);
}
close(fds[0]);
return process;
}