From 182788482e8bd01c70bbe6af3f7ed79765d4fe53 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Tue, 19 May 2020 19:58:54 +0200 Subject: exec shit works, kinda --- 02_exercise/shell.c | 122 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 42 deletions(-) diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 2594d6b..75e77b7 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -11,72 +11,110 @@ #include "array.h" #include "errno.h" -#include "stdbool.h" +#include -void print_prompt(char const *const original_wd, char const *current_wd); +void print_prompt(); -// Returns the return code of the executed programm -int exec_command(char *command); +// returns the return code of the executed program +int exec_command(const char *path, char *const argv[], unsigned timeout); -int main(void) { - // the directory is specified without a / at the end - char const *const original_wd = get_current_dir_name(); - char const *current_wd = get_current_dir_name(); +int main(int argc, char* argv[]) { + + char *argument; + char **arguments; + if (arrayInit(argument) != 0 || arrayInit(arguments) != 0) { + fprintf(stderr, "Failed to prepare new argument array"); + exit(-1); + } while (true) { char *command = NULL; size_t cap = 0; size_t length = 0; - print_prompt(original_wd, current_wd); + print_prompt(); if ((length = getline(&command, &cap, stdin)) < 0) { fprintf(stderr, "Failed to read from STDIN"); exit(-1); } + + command[length - 1] = '\0'; // cut the line feed +/* + char c; + int i = 0; + while (true) { + c = command[i++]; + if (c == ' ') { + arrayPush(argument) = '\0'; + arrayPush(arguments) = argument; + printf("+ %s\n", argument); + arrayRelease(argument); + arrayInit(argument); + } else if (c == '\0') { + + } else { + arrayPush(argument) = c; + } + } +*/ if (strstr(command, "cd") != NULL) { printf("Changing dirs \n"); chdir("beispiele"); - free((void *) current_wd); - current_wd = get_current_dir_name(); } else if (strcmp(command, "exit\n") == 0) { exit(0); } else { - exec_command(command); + exec_command(command, (char *const []) {command, NULL}, 0); } free((void *)command); } - // Gotta cast to void otherwise we discard qualifiers - free((void *)original_wd); - free((void *)current_wd); } -void print_prompt(char const *const original_wd, char const *const current_wd) { - // easiest case first - { - int result = strcmp(original_wd, current_wd); - if (result == 0) { - printf(".> "); - return; - } - } - printf("%s > ", current_wd); - // Now checking for substrings aka are we in a subdir - { - size_t dirlen = strlen(original_wd); - char *const orig_dir_with_slash = malloc(dirlen + 2); - if (orig_dir_with_slash == NULL) { - fprintf(stderr, "Failed to allocate for prompt"); - exit(ENOMEM); - } - memcpy(orig_dir_with_slash, original_wd, dirlen); - orig_dir_with_slash[dirlen] = '/'; - orig_dir_with_slash[dirlen + 1] = '\0'; - char const *const result = strstr(current_wd, original_wd); - if (result != NULL) { - printf(".%s > ", current_wd + dirlen); - return; - } +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(char *command) { return 0; } +int exec_command(const char *path, char *const argv[], unsigned timeout) { + int pid; + int pipefd[2]; + int status; + char buf[512]; + + pipe(pipefd); + if ((pid = fork()) == 0) { + close(pipefd[0]); + dup2(pipefd[1], 1); // includes close(1); + close(pipefd[1]); + execvp(path, argv); + fprintf(stderr, "no program\n"); + exit(-1); + } + + if (pid < 0) { + fprintf(stderr, "no fork\n"); + exit(-2); + } + + close(pipefd[1]); + + size_t length = 0; + if ((length = read(pipefd[0], buf, 512)) <= 0) { + fprintf(stderr, "error\n"); + exit(-3); + } + + waitpid(pid, &status, 0); + + close(pipefd[0]); + + buf[length] = '\0'; + + printf("%s", buf); + return WEXITSTATUS(status); +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 3d0ae3aaee22bd5e768255f2f519d9e95f517552 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 08:57:02 +0200 Subject: added git ignore --- 02_exercise/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 02_exercise/.gitignore diff --git a/02_exercise/.gitignore b/02_exercise/.gitignore new file mode 100644 index 0000000..acfd225 --- /dev/null +++ b/02_exercise/.gitignore @@ -0,0 +1,3 @@ +CMakeLists.txt +prog +shell -- cgit v1.2.3-54-g00ecf From ddbb47ed661614d768e8ebd3b0a5084ee82b0beb Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 10:25:23 +0200 Subject: ????? --- 02_exercise/shell.c | 103 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 37 deletions(-) diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 75e77b7..84f8aff 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -2,71 +2,100 @@ #include #include -#include -#include -#include -#include #include #include #include "array.h" -#include "errno.h" #include void print_prompt(); +int parse_line(char const *line, char **exe, 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 main(int argc, char* argv[]) { - - char *argument; - char **arguments; - if (arrayInit(argument) != 0 || arrayInit(arguments) != 0) { - fprintf(stderr, "Failed to prepare new argument array"); - exit(-1); - } - while (true) { - char *command = NULL; + char *line = NULL; size_t cap = 0; size_t length = 0; print_prompt(); - if ((length = getline(&command, &cap, stdin)) < 0) { + if ((length = getline(&line, &cap, stdin)) < 0) { fprintf(stderr, "Failed to read from STDIN"); exit(-1); } - command[length - 1] = '\0'; // cut the line feed -/* - char c; - int i = 0; - while (true) { - c = command[i++]; - if (c == ' ') { - arrayPush(argument) = '\0'; - arrayPush(arguments) = argument; - printf("+ %s\n", argument); - arrayRelease(argument); - arrayInit(argument); - } else if (c == '\0') { - - } else { - arrayPush(argument) = c; - } + line[length - 1] = '\0'; // cut the line feed + + char *exe = NULL; + char **arguments = NULL; + size_t argument_count; + parse_line(line, &exe, &arguments, &argument_count); + + for (size_t h = 0; h < argument_count; ++h) { + char *part; + part = arrayPop(arguments); + if (part == NULL) + continue; + printf("%s\n", part); } -*/ - if (strstr(command, "cd") != NULL) { + + exit(0); + + if (strcmp(exe, "cd") == 0) { printf("Changing dirs \n"); chdir("beispiele"); - } else if (strcmp(command, "exit\n") == 0) { + } else if (strcmp(exe, "exit") == 0) { exit(0); } else { - exec_command(command, (char *const []) {command, NULL}, 0); + exec_command(exe, (char *const []) {exe, NULL}, 0); + } + free((void *)line); + // no need to free exe, since it is part of arguments any way + arrayRelease(arguments); + } +} + +int parse_line(char const *line, char **exe, 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 array"); + exit(-1); + } + + bool found_exe = false; + char c; + int i = 0; + while (true) { + c = line[i++]; + if (c == ' ' || c == '\0') { + arrayPush(part) = '\0'; + arrayPush(local_parts) = part; + if (!found_exe) { + // the first is the executable + *exe = malloc(arrayLen(part) * sizeof(char)); + strcpy(*exe, part); + found_exe = true; + } + arrayRelease(part); // TODO: am i supposed/allowed to free it here? + arrayInit(part); + if (c == '\0') { + arrayPush(local_parts) = NULL; + break; + } + } else { + arrayPush(part) = c; } - free((void *)command); } + + *part_count = arrayLen(local_parts); + *parts = local_parts; + + return 0; } void print_prompt() { -- cgit v1.2.3-54-g00ecf From 5a200f8b131917d2e6d51df50b01042ffaafa9a6 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 11:38:10 +0200 Subject: git diffgit diff --- 02_exercise/shell.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 84f8aff..f48819b 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -34,23 +34,13 @@ int main(int argc, char* argv[]) { size_t argument_count; parse_line(line, &exe, &arguments, &argument_count); - for (size_t h = 0; h < argument_count; ++h) { - char *part; - part = arrayPop(arguments); - if (part == NULL) - continue; - printf("%s\n", part); - } - - exit(0); - if (strcmp(exe, "cd") == 0) { printf("Changing dirs \n"); chdir("beispiele"); } else if (strcmp(exe, "exit") == 0) { exit(0); } else { - exec_command(exe, (char *const []) {exe, NULL}, 0); + exec_command(exe, arguments, 0); } free((void *)line); // no need to free exe, since it is part of arguments any way @@ -81,7 +71,6 @@ int parse_line(char const *line, char **exe, char ***parts, size_t *part_count) strcpy(*exe, part); found_exe = true; } - arrayRelease(part); // TODO: am i supposed/allowed to free it here? arrayInit(part); if (c == '\0') { arrayPush(local_parts) = NULL; -- cgit v1.2.3-54-g00ecf From e29af1f554ee40a888689e134e12f8d4a3b24ea1 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 11:49:54 +0200 Subject: cmake --- 02_exercise/.gitignore | 1 - 02_exercise/CMakeLists.txt | 5 +++++ 02_exercise/shell.c | 9 +++------ 3 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 02_exercise/CMakeLists.txt diff --git a/02_exercise/.gitignore b/02_exercise/.gitignore index acfd225..5aacf99 100644 --- a/02_exercise/.gitignore +++ b/02_exercise/.gitignore @@ -1,3 +1,2 @@ -CMakeLists.txt prog shell diff --git a/02_exercise/CMakeLists.txt b/02_exercise/CMakeLists.txt new file mode 100644 index 0000000..0cf7c20 --- /dev/null +++ b/02_exercise/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.5) + +project(shell) + +add_executable(shell array.c shell.c) \ No newline at end of file diff --git a/02_exercise/shell.c b/02_exercise/shell.c index f48819b..5a8d48f 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -122,17 +122,14 @@ int exec_command(const char *path, char *const argv[], unsigned timeout) { close(pipefd[1]); size_t length = 0; - if ((length = read(pipefd[0], buf, 512)) <= 0) { - fprintf(stderr, "error\n"); - exit(-3); + while ((length = read(pipefd[0], buf, 10)) > 0) { + buf[length] = '\0'; + printf("%s", buf); } waitpid(pid, &status, 0); close(pipefd[0]); - buf[length] = '\0'; - - printf("%s", buf); return WEXITSTATUS(status); } \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 6b47ff2690b473e86adf6ded723619b546047d7e Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 12:28:02 +0200 Subject: memory should be fixed? i think --- 02_exercise/shell.c | 55 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 5a8d48f..c960680 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -10,13 +10,14 @@ void print_prompt(); -int parse_line(char const *line, char **exe, char ***parts, size_t *part_count); +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 main(int argc, char* argv[]) { - while (true) { + bool done = false; + while (!done) { char *line = NULL; size_t cap = 0; size_t length = 0; @@ -29,35 +30,48 @@ int main(int argc, char* argv[]) { line[length - 1] = '\0'; // cut the line feed - char *exe = NULL; char **arguments = NULL; size_t argument_count; - parse_line(line, &exe, &arguments, &argument_count); + parse_line(line, &arguments, &argument_count); - if (strcmp(exe, "cd") == 0) { - printf("Changing dirs \n"); - chdir("beispiele"); - } else if (strcmp(exe, "exit") == 0) { - exit(0); + if (strcmp(arguments[0], "cd") == 0) { + if (arrayLen(arguments) != 3) { + fprintf(stderr, "usage: cd "); + goto clean; + } + int ret = chdir(arguments[1]); + if (ret) + printf("[%i] ", ret); + } else if (strcmp(arguments[0], "exit") == 0) { + done = true; } else { - exec_command(exe, arguments, 0); + int ret = exec_command(arguments[0], arguments, 0); + if (ret) + printf("[%i] ", ret); } + + clean: free((void *)line); - // no need to free exe, since it is part of arguments any way + while (arrayLen(arguments) > 0) { + char *tmp = arrayPop(arguments); + if (tmp) + arrayRelease(tmp); + } arrayRelease(arguments); } } -int parse_line(char const *line, char **exe, char ***parts, size_t *part_count) { +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) { + arrayInit(part); + arrayInit(local_parts); +/* if (arrayInit(part) != 0 || arrayInit(local_parts) != 0) { fprintf(stderr, "Failed to prepare new part array"); exit(-1); - } + }*/ - bool found_exe = false; char c; int i = 0; while (true) { @@ -65,16 +79,11 @@ int parse_line(char const *line, char **exe, char ***parts, size_t *part_count) if (c == ' ' || c == '\0') { arrayPush(part) = '\0'; arrayPush(local_parts) = part; - if (!found_exe) { - // the first is the executable - *exe = malloc(arrayLen(part) * sizeof(char)); - strcpy(*exe, part); - found_exe = true; - } - arrayInit(part); if (c == '\0') { arrayPush(local_parts) = NULL; break; + } else { + arrayInit(part); } } else { arrayPush(part) = c; @@ -110,7 +119,7 @@ int exec_command(const char *path, char *const argv[], unsigned timeout) { dup2(pipefd[1], 1); // includes close(1); close(pipefd[1]); execvp(path, argv); - fprintf(stderr, "no program\n"); + fprintf(stderr, "could not execute \"%s\"\n", path); exit(-1); } -- cgit v1.2.3-54-g00ecf From 5e2b718c15087ee3401a6c0e1d80196e92f2aa06 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 21 May 2020 12:32:30 +0200 Subject: re-added error handling --- 02_exercise/shell.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/02_exercise/shell.c b/02_exercise/shell.c index c960680..1c03961 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -65,12 +65,10 @@ int parse_line(char const *line, char ***parts, size_t *part_count) { char *part; char **local_parts; - arrayInit(part); - arrayInit(local_parts); -/* if (arrayInit(part) != 0 || arrayInit(local_parts) != 0) { - fprintf(stderr, "Failed to prepare new part array"); - exit(-1); - }*/ + if (arrayInit(part) != 0 || arrayInit(local_parts) != 0) { + fprintf(stderr, "Failed to prepare new part / parts array whilst parsing line"); + return -1; + } char c; int i = 0; @@ -97,8 +95,8 @@ int parse_line(char const *line, char ***parts, size_t *part_count) { } void print_prompt() { - size_t length = 1024; - char *buffer = malloc(length * sizeof(char)); + size_t length = 1024; + char *buffer = malloc(length * sizeof(char)); getcwd(buffer, length); if (buffer == NULL) { printf(".> "); -- cgit v1.2.3-54-g00ecf