From 68f5ff29c0aae1a176c25996aab0144badd0f092 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 19:46:13 +0200 Subject: you can now put stuff in the background, yay --- 02_exercise/shell.c | 68 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 1bdeab6..7032a99 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -12,19 +11,19 @@ int parse_line(char const *line, char ***parts, size_t *part_count); // returns the return code of the executed program -int exec_command(const char *path, char *const argv[], unsigned timeout); +int exec_command(const char *path, char *const argv[], bool background); int main(void) { - chdir("."); setvbuf(stdout, NULL, _IONBF, 0); char const *const original_wd = get_current_dir_name(); char const *prompt = relative_path(original_wd, original_wd); bool done = false; while (!done) { + bool bg = false; char *line = NULL; size_t cap = 0; - __ssize_t length = 0; + __ssize_t length; printf("%s > ", prompt); if ((length = getline(&line, &cap, stdin)) < 0) { @@ -42,7 +41,19 @@ int main(void) { size_t argument_count; parse_line(line, &arguments, &argument_count); - if (strcmp(arguments[0], "cd") == 0) { + if (argument_count <= 0) + goto clean; + + char *command = arguments[0]; + char *last_arg = arguments[argument_count - 2]; + + if (strcmp(last_arg, "&") == 0) { + bg = true; + arrayRelease(arguments[argument_count - 2]); + arguments[argument_count - 2] = NULL; + } + + if (strcmp(command, "cd") == 0) { if (arrayLen(arguments) != 3) { fprintf(stderr, "usage: cd "); goto clean; @@ -56,10 +67,10 @@ int main(void) { char const *current_wd = get_current_dir_name(); prompt = relative_path(original_wd, current_wd); free((void *)current_wd); - } else if (strcmp(arguments[0], "exit") == 0) { + } else if (strcmp(command, "exit") == 0) { done = true; } else { - int ret = exec_command(arguments[0], arguments, 0); + int ret = exec_command(command, arguments, bg); if (ret) printf("[%i] ", ret); } @@ -111,19 +122,7 @@ int parse_line(char const *line, char ***parts, size_t *part_count) { return 0; } -void print_prompt() { - size_t length = 1024; - char *buffer = malloc(length * sizeof(char)); - getcwd(buffer, length); - if (buffer == NULL) { - printf(".> "); - } else { - printf("%s > ", buffer); - } -} - -int exec_command(const char *path, char *const argv[], unsigned timeout) { - timeout = timeout ^ timeout; +int exec_command(const char *path, char *const argv[], bool background) { int pid; int pipefd[2]; int status; @@ -132,7 +131,7 @@ int exec_command(const char *path, char *const argv[], unsigned timeout) { pipe(pipefd); if ((pid = fork()) == 0) { close(pipefd[0]); - dup2(pipefd[1], 1); // includes close(1); + dup2(pipefd[1], 1); close(pipefd[1]); execvp(path, argv); fprintf(stderr, "could not execute \"%s\"\n", path); @@ -147,14 +146,29 @@ int exec_command(const char *path, char *const argv[], unsigned timeout) { close(pipefd[1]); - __ssize_t length = 0; - while ((length = read(pipefd[0], buf, 10)) > 0) { - buf[length] = '\0'; - fprintf(stdout, "%s", buf); - fflush(stdout); + int new_pid; + if (background) { + new_pid = fork(); } - waitpid(pid, &status, 0); + if (!background || new_pid == 0) { + if (background) + printf("[%i]\n", pid); + + __ssize_t length; + while ((length = read(pipefd[0], buf, 10)) > 0) { + buf[length] = '\0'; + printf("%s", buf); + } + + waitpid(pid, &status, 0); + + if (background) { + printf("[%i] TERMINATED\n", pid); + printf("[%i] EXIT STATUS: %i\n", pid, status); + exit(0); + } + } close(pipefd[0]); -- cgit v1.2.3-54-g00ecf