diff options
author | dzwdz | 2022-07-31 17:09:05 +0200 |
---|---|---|
committer | dzwdz | 2022-07-31 20:56:52 +0200 |
commit | 70948d9a9ec613b17c2cdff9e76b5b35f40565ac (patch) | |
tree | 5c2b0b6444369b8019c34abcae66244589eb6446 /src/user | |
parent | 40674fa5469c7af09095d5dd5cca8eccc728561c (diff) |
user/shell: use an array of function pointers for the builtins
Diffstat (limited to 'src/user')
-rw-r--r-- | src/user/app/shell/builtins.c | 105 | ||||
-rw-r--r-- | src/user/app/shell/builtins.h | 9 | ||||
-rw-r--r-- | src/user/app/shell/shell.c | 45 |
3 files changed, 93 insertions, 66 deletions
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c index 3a19a2f..e272cf3 100644 --- a/src/user/app/shell/builtins.c +++ b/src/user/app/shell/builtins.c @@ -4,54 +4,55 @@ #include <string.h> #include <unistd.h> -void cmd_cat_ls(const char *args, bool ls) { +static void cmd_cat(int argc, const char **argv) { + // TODO loop over argv + FILE *file; static char buf[512]; - int len; // first used for strlen(args), then length of buffer - - if (args) { - len = strlen(args); - memcpy(buf, args, len + 1); // no overflow check - the shell is just a PoC - if (ls) { // paths to directories always have a trailing slash - if (buf[len-1] != '/') { - buf[len] = '/'; - buf[len+1] = '\0'; - } - } - - file = fopen(buf, "r"); - } else if (ls) { /* ls default argument */ - file = fopen("/", "r"); - } else { /* cat default argument */ + if (argv[1]) + file = fopen(argv[1], "r"); + else file = file_clone(stdin); - } if (!file) { eprintf("couldn't open"); return; } - while (!feof(file)) { + for (;;) { int len = fread(buf, 1, sizeof buf, file); if (len <= 0) break; - - if (ls) { - for (int i = 0; i < len; i++) - if (buf[i] == '\0') buf[i] = '\n'; - } fwrite(buf, 1, len, stdout); } fclose(file); } -void cmd_hexdump(const char *args) { +static void cmd_echo(int argc, const char **argv) { + bool newline = true; + int i = 1; + + if (!strcmp("-n", argv[i])) { + i++; + newline = false; + } + + printf("%s", argv[i++]); + for (; argv[i]; i++) + printf(" %s", argv[i]); + if (newline) + printf("\n"); +} + +void cmd_hexdump(int argc, const char **argv) { + // TODO loop over argv + // TODO use fopen/fread static uint8_t buf[512]; int fd, len; - fd = _syscall_open(args, strlen(args), 0); + fd = _syscall_open(argv[1], strlen(argv[1]), 0); if (fd < 0) { - eprintf("couldn't open %s", args); + eprintf("couldn't open %s", argv[1]); return; } @@ -77,11 +78,55 @@ void cmd_hexdump(const char *args) { close(fd); } -void cmd_touch(const char *args) { - int fd = _syscall_open(args, strlen(args), OPEN_CREATE); +static void cmd_ls(int argc, const char **argv) { + // TODO loop over argv + FILE *file; + static char buf[512]; + + if (argv[1]) { + int len = strlen(argv[1]); + memcpy(buf, argv[1], len + 1); // TODO no overflow check + + if (buf[len-1] != '/') { + buf[len] = '/'; + buf[len+1] = '\0'; + } + + file = fopen(buf, "r"); + } else { + file = fopen("/", "r"); + } + + if (!file) { + eprintf("couldn't open"); + return; + } + + for (;;) { + int len = fread(buf, 1, sizeof buf, file); + if (len <= 0) break; + for (int i = 0; i < len; i++) + if (buf[i] == '\0') buf[i] = '\n'; + fwrite(buf, 1, len, stdout); + } + fclose(file); +} + +static void cmd_touch(int argc, const char **argv) { + // TODO loop over argv + int fd = _syscall_open(argv[1], strlen(argv[1]), OPEN_CREATE); if (fd < 0) { - eprintf("couldn't touch %s\n", args); + eprintf("couldn't touch %s\n", argv[1]); return; } close(fd); } + +struct builtin builtins[] = { + {"cat", cmd_cat}, + {"echo", cmd_echo}, + {"hexdump", cmd_hexdump}, + {"ls", cmd_ls}, + {"touch", cmd_touch}, + {NULL, NULL}, +}; diff --git a/src/user/app/shell/builtins.h b/src/user/app/shell/builtins.h index bb52cef..aa2cd8c 100644 --- a/src/user/app/shell/builtins.h +++ b/src/user/app/shell/builtins.h @@ -2,6 +2,9 @@ #include <camellia/syscalls.h> #include <stdbool.h> -void cmd_cat_ls(const char *args, bool ls); -void cmd_hexdump(const char *args); -void cmd_touch(const char *args); +struct builtin { + const char *name; + void (*fn)(int argc, const char **argv); +}; + +extern struct builtin builtins[]; diff --git a/src/user/app/shell/shell.c b/src/user/app/shell/shell.c index 8bfe105..f47dc8d 100644 --- a/src/user/app/shell/shell.c +++ b/src/user/app/shell/shell.c @@ -36,8 +36,8 @@ static void run(char *cmd) { char *argv[ARGV_MAX]; struct redir redir; - int ret = parse(cmd, argv, ARGV_MAX, &redir); - if (ret < 0) { + int argc = parse(cmd, argv, ARGV_MAX, &redir); + if (argc < 0) { eprintf("error parsing command"); return; } @@ -63,39 +63,18 @@ static void run(char *cmd) { exit(0); } - if (!strcmp(argv[0], "echo")) { - printf("%s", argv[1]); - for (int i = 2; argv[i]; i++) - printf(" %s", argv[i]); - printf("\n"); - } else if (!strcmp(argv[0], "fork")) { - main(); - } else if (!strcmp(argv[0], "cat")) { - // TODO better argv handling - cmd_cat_ls(argv[1], false); - } else if (!strcmp(argv[0], "ls")) { - cmd_cat_ls(argv[1], true); - } else if (!strcmp(argv[0], "hexdump")) { - cmd_hexdump(argv[1]); - } else if (!strcmp(argv[0], "catall")) { - const char *files[] = { - "/init/fake.txt", - "/init/1.txt", "/init/2.txt", - "/init/dir/3.txt", NULL}; - for (int i = 0; files[i]; i++) { - printf("%s:\n", files[i]); - cmd_cat_ls(files[i], false); - printf("\n"); + for (struct builtin *iter = builtins; iter->name; iter++) { + if (!strcmp(argv[0], iter->name)) { + iter->fn(argc, argv); + exit(0); } - } else if (!strcmp(argv[0], "touch")) { - cmd_touch(argv[1]); + } + + execp(argv); + if (errno == EINVAL) { + eprintf("%s isn't a valid executable\n", argv[0]); } else { - execp(argv); - if (errno == EINVAL) { - eprintf("%s isn't a valid executable\n", argv[0]); - } else { - eprintf("unknown command: %s\n", argv[0]); - } + eprintf("unknown command: %s\n", argv[0]); } exit(0); /* kills the subprocess */ } |