From 922b46952d38f51850640a20d7be4747e84e95f4 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Sun, 24 May 2020 17:08:04 +0200 Subject: implemented a basic wait, not much tests yet, some functionality missing --- 02_exercise/process.c | 14 +------------ 02_exercise/shell.c | 56 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/02_exercise/process.c b/02_exercise/process.c index fb55236..95a0600 100644 --- a/02_exercise/process.c +++ b/02_exercise/process.c @@ -107,12 +107,6 @@ int parse_line(char const *const line, process **processes) { int exec_command(process p) { int status; - if (!p.blocking) { - // if the process is to be put in the background let a fork handle it - if (fork() != 0) - return 0; - } - if ((p.pid = fork()) == 0) { if (p.in_fd != 0) { dup2(p.in_fd, 0); @@ -146,16 +140,10 @@ int exec_command(process p) { if (!p.blocking) printf("[%i]\n", p.pid); - if (waitpid(p.pid, &status, 0) < 0) { + if (waitpid(p.pid, &status, p.blocking ? 0 : WNOHANG) < 0) { fprintf(stderr, "wait error'ed out\n"); } - if (!p.blocking) { - printf("[%i] TERMINATED\n", p.pid); - printf("[%i] EXIT STATUS: %i\n", p.pid, status); // TODO: exit status is wrong - exit(0); - } - return WEXITSTATUS(status); } diff --git a/02_exercise/shell.c b/02_exercise/shell.c index ea1b13f..35de455 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -3,14 +3,14 @@ #include #include #include +#include #include "array.h" #include "process.h" #include "prompt_utils.h" - int main(void) { - chdir("."); + setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); char const *const original_wd = get_current_dir_name(); @@ -24,6 +24,7 @@ int main(void) { printf("%s > ", prompt); if ((length = getline(&line, &cap, stdin)) < 0) { fprintf(stderr, "Failed to read from STDIN"); + fflush(stderr); exit(-1); } @@ -41,12 +42,20 @@ int main(void) { perror("Can't chain cd with other processes"); } - if (arrayLen(processes[0].argv) != 3) { - fprintf(stderr, "usage: cd "); - goto clean; + int ret; + switch(arrayLen(processes[0].argv)) { + case 3: + ret = chdir(processes[0].argv[1]); + break; + case 2: + ret = chdir(original_wd); + break; + default: + fprintf(stderr, "usage: cd \n"); + fflush(stderr); + ret = -1; } - int ret = chdir(processes[0].argv[1]); if (ret) printf("[%i] ", ret); @@ -56,6 +65,40 @@ int main(void) { free((void *)current_wd); } else if (strcmp(processes[0].argv[0], "exit") == 0) { done = true; + } else if (strcmp(processes[0].argv[0], "wait") == 0) { + bool error = false; + pid_t *pids; + arrayInit(pids); + size_t i = 1; + while (!error && processes[0].argv[i] != NULL) { + char *end; + pid_t tmp = strtol(processes[0].argv[i], &end, 10); + if (*end != '\0') { + fprintf(stderr, "Not a valid pid: %s", processes[0].argv[i]); + error = true; + break; + } + arrayPush(pids) = tmp; + ++i; + } + + if (!error) { + while (!arrayIsEmpty(pids)) { + int status; + pid_t current_pid = arrayPop(pids); + printf("Waiting for %ld...\n", (long) current_pid); + if (waitpid(current_pid, &status, WUNTRACED) < 0) { + perror("Could not wait on process"); + } else { + printf("[%i] TERMINATED\n", current_pid); + printf("[%i] EXIT STATUS: %i\n", current_pid, status); // TODO: exit status is wrong + } + // TODO: catch ctrl-c + } + } + + arrayRelease(pids); + } else { for (size_t i = 0; i < arrayLen(processes); ++i) { int ret = exec_command(processes[i]); @@ -65,7 +108,6 @@ int main(void) { } - clean: free((void *)line); line = NULL; cap = 0; -- cgit v1.2.3-54-g00ecf