From 355dd6c32b775af09d9c4a2170b32cbc32de9d6b Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 23 Mar 2023 22:19:54 +0100 Subject: [PATCH] apps: Add sh --- apps/CMakeLists.txt | 2 +- apps/hello.c | 12 ------ apps/init.c | 12 +++--- apps/sh.c | 100 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 18 deletions(-) delete mode 100644 apps/hello.c create mode 100644 apps/sh.c diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 748f3695..85315b27 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -7,4 +7,4 @@ function(luna_app SOURCE_FILE APP_NAME) endfunction() luna_app(init.c init) -luna_app(hello.c hello) +luna_app(sh.c sh) diff --git a/apps/hello.c b/apps/hello.c deleted file mode 100644 index dea0b7e9..00000000 --- a/apps/hello.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -int main(int argc, char** argv) -{ - printf("Hello world! argc=%d, argv[0]=%s, argv[1]=%s, argv[2]=%s\n", argc, argv[0], argv[1], argv[2]); - - char buf[1024]; - char* rc = fgets(buf, sizeof(buf), stdin); - if (!rc) perror("fgets"); - - fputs(buf, stdout); -} diff --git a/apps/init.c b/apps/init.c index fb1d9b67..982af948 100644 --- a/apps/init.c +++ b/apps/init.c @@ -36,14 +36,16 @@ int main() stdout = fopen("/dev/console", "w"); stderr = fopen("/dev/console", "w"); - printf("init is running as PID %d\n", getpid()); - pid_t ret = fork(); if (ret == 0) { - char* argv[] = { "/bin/hello", "--help", NULL }; - execv("/bin/hello", argv); + char* argv[] = { "/bin/sh", NULL }; + execv(argv[0], argv); + perror("execv"); + return 1; } - else { printf("my child is PID %d!\n", ret); } + + while (1) + ; } diff --git a/apps/sh.c b/apps/sh.c new file mode 100644 index 00000000..bafb5477 --- /dev/null +++ b/apps/sh.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include + +static char** split_command_into_argv(const char* cmd) +{ + size_t argc = 1; + char* str = strdup(cmd); + char** arr = calloc(sizeof(char*), argc); + + char* segment = strtok(str, " \n"); + arr[argc - 1] = segment; + if (segment == NULL) return arr; + + argc++; + arr = realloc(arr, sizeof(char*) * argc); + + for (;;) + { + char* segment = strtok(NULL, " \n"); + arr[argc - 1] = segment; + + if (segment == NULL) break; + + argc++; + arr = realloc(arr, sizeof(char*) * argc); + } + + return arr; +} + +static char* join_path(const char* str1, const char* str2) +{ + char* buf = malloc(strlen(str1) + strlen(str2) + 1); + strlcpy(buf, str1, strlen(str1) + 1); + strncat(buf, str2, strlen(str2)); + return buf; +} + +static int execute_in_path(const char* dir, char** argv) +{ + char* path = join_path(dir, argv[0]); + int err = errno; + + int status = execv(path, argv); + free(path); + + if (errno == ENOENT) + { + errno = err; + return 0; + } + + return status; +} + +static int sh_execvp(char** argv) +{ + if (strchr(argv[0], '/')) + { + // Relative paths do not need path resolution. + return execv(argv[0], argv); + } + + if (execute_in_path("/bin/", argv) != 0) return -1; + if (execute_in_path("/sbin/", argv) != 0) return -1; + if (execute_in_path("/usr/bin/", argv) != 0) return -1; + if (execute_in_path("/usr/local/bin/", argv) != 0) return -1; + + errno = ENOENT; + return -1; +} + +int main() +{ + while (1) + { + fputs("sh$ ", stdout); + + char command[4096]; + fgets(command, sizeof(command), stdin); + + pid_t child = fork(); + if (child < 0) { perror("fork"); } + + if (child == 0) + { + char** argv = split_command_into_argv(command); + sh_execvp(argv); + perror(argv[0]); + return 1; + } + + // Don't have sched_yield() or waitpid() yet... + sleep(1); + } +}