diff options
author | Niklas Halle <niklas@niklashalle.net> | 2020-05-22 09:53:42 +0200 |
---|---|---|
committer | Niklas Halle <niklas@niklashalle.net> | 2020-05-22 09:53:42 +0200 |
commit | 3b7e61eab8ce5d230bc1b172942c1ab9459ed161 (patch) | |
tree | 73da9a772782d7d1504770c8cc7582c03cf41310 /02_exercise/shell.c | |
parent | 68f5ff29c0aae1a176c25996aab0144badd0f092 (diff) | |
parent | 4f80f043aacc568fac0e3681b62aa1971a97291a (diff) | |
download | betriebssysteme-3b7e61eab8ce5d230bc1b172942c1ab9459ed161.tar.gz betriebssysteme-3b7e61eab8ce5d230bc1b172942c1ab9459ed161.zip |
Merge branch 'process_and_pipes' into dev/niklas
Diffstat (limited to '02_exercise/shell.c')
-rw-r--r-- | 02_exercise/shell.c | 140 |
1 files changed, 20 insertions, 120 deletions
diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 7032a99..f456465 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -3,27 +3,23 @@ #include <string.h> #include <unistd.h> #include <stdbool.h> -#include <sys/wait.h> #include "array.h" +#include "process.h" #include "prompt_utils.h" -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[], 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; + __ssize_t length = 0; printf("%s > ", prompt); if ((length = getline(&line, &cap, stdin)) < 0) { @@ -37,29 +33,20 @@ int main(void) { line[length - 1] = '\0'; // cut the line feed - char **arguments = NULL; - size_t argument_count; - parse_line(line, &arguments, &argument_count); - - if (argument_count <= 0) - goto clean; + Process * processes = NULL; + parse_line(line, &processes); - char *command = arguments[0]; - char *last_arg = arguments[argument_count - 2]; + if (strcmp(processes[0].argv[0], "cd") == 0) { - 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) { + if(arrayLen(processes) != 1) { + perror("Can't chain cd with other processes"); + } + if (arrayLen(processes[0].argv) != 3) { fprintf(stderr, "usage: cd <path>"); goto clean; } - int ret = chdir(arguments[1]); + int ret = chdir(processes[0].argv[1]); if (ret) printf("[%i] ", ret); @@ -67,110 +54,23 @@ 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(command, "exit") == 0) { + } else if (strcmp(processes[0].argv[0], "exit") == 0) { done = true; } else { - int ret = exec_command(command, arguments, bg); - if (ret) - printf("[%i] ", ret); + int ret; + for (size_t i = 0; i < arrayLen(processes); ++i) { + ret = exec_command(processes[i]); + if (ret) + printf("[%i] ", ret); + } + } clean: free((void *)line); - while (arrayLen(arguments) > 0) { - char *tmp = arrayPop(arguments); - if (tmp) - arrayRelease(tmp); - } - arrayRelease(arguments); + free_processes(&processes); } free((void *)original_wd); free((void *)prompt); } - -int parse_line(char const *line, char ***parts, size_t *part_count) { - char *part; - char **local_parts; - - if (arrayInit(part) != 0 || arrayInit(local_parts) != 0) { - fprintf(stderr, "Failed to prepare new part / parts array whilst parsing line"); - return -1; - } - - for (size_t i = 0; i < strlen(line) + 1; ++i) { - char c = line[i]; - if (c == ' ' || c == '\0') { - if (arrayLen(part) == 0) - continue; - arrayPush(part) = '\0'; - arrayPush(local_parts) = part; - if (c == '\0') { - arrayPush(local_parts) = NULL; - break; - } else { - arrayInit(part); - } - } else { - arrayPush(part) = c; - } - } - - *part_count = arrayLen(local_parts); - *parts = local_parts; - - return 0; -} - -int exec_command(const char *path, char *const argv[], bool background) { - int pid; - int pipefd[2]; - int status; - char buf[512]; - - pipe(pipefd); - if ((pid = fork()) == 0) { - close(pipefd[0]); - dup2(pipefd[1], 1); - close(pipefd[1]); - execvp(path, argv); - fprintf(stderr, "could not execute \"%s\"\n", path); - fflush(stderr); - exit(-1); - } - - if (pid < 0) { - fprintf(stderr, "no fork\n"); - exit(-2); - } - - close(pipefd[1]); - - int new_pid; - if (background) { - new_pid = fork(); - } - - 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]); - - return WEXITSTATUS(status); -} |