diff options
author | dzwdz | 2023-08-14 18:51:07 +0200 |
---|---|---|
committer | dzwdz | 2023-08-14 18:51:07 +0200 |
commit | 642b5fb0007b64c77d186fcb018d571152ee1d47 (patch) | |
tree | 1c466461f3602d306be309a053edae558ef2568e /src/user/app/shell | |
parent | 8050069c57b729c18c19b1a03ab6e4bf63b4735e (diff) |
reorganization: first steps
Diffstat (limited to 'src/user/app/shell')
-rw-r--r-- | src/user/app/shell/builtins.c | 254 | ||||
-rw-r--r-- | src/user/app/shell/builtins.h | 10 | ||||
-rw-r--r-- | src/user/app/shell/parser.c | 76 | ||||
-rw-r--r-- | src/user/app/shell/shell.c | 178 | ||||
-rw-r--r-- | src/user/app/shell/shell.h | 11 |
5 files changed, 0 insertions, 529 deletions
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c deleted file mode 100644 index 9c294b2..0000000 --- a/src/user/app/shell/builtins.c +++ /dev/null @@ -1,254 +0,0 @@ -#include "builtins.h" -#include "shell.h" -#include <camellia.h> -#include <camellia/fs/misc.h> -#include <camellia/path.h> -#include <err.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#define DEFAULT_ARGV(...) \ - char *_argv_default[] = {argv[0], __VA_ARGS__}; \ - if (argc <= 1) { \ - argc = sizeof(_argv_default) / sizeof(*_argv_default); \ - argv = _argv_default; \ - } - -static void cmd_cat(int argc, char **argv) { - const size_t buflen = 4096; - char *buf = malloc(buflen); - - DEFAULT_ARGV("!stdin"); - for (int i = 1; i < argc; i++) { - FILE *file = fopen(argv[i], "r"); - if (!file) { - perror(argv[i]); - return; - } - if (!strcmp(argv[i], "!stdin")) fextflags(file, FEXT_NOFILL); - for (;;) { - int len = fread(buf, 1, buflen, file); - if (len <= 0) break; - fwrite(buf, 1, len, stdout); - } - if (ferror(file)) { - perror(argv[i]); - return; - } - fclose(file); - } -} - -static void cmd_echo(int argc, char **argv) { - bool newline = true; - int i = 1; - - if (!strcmp("-n", argv[i])) { - i++; - newline = false; - } - - printf("%s", argv[i++]); - for (; i < argc; i++) - printf(" %s", argv[i]); - if (newline) - printf("\n"); -} - -void cmd_getsize(int argc, char **argv) { - if (argc < 2) errx(1, "no arguments"); - for (int i = 1; i < argc; i++) { - hid_t h = camellia_open(argv[i], OPEN_READ); - if (h < 0) { - warn("error opening %s", argv[i]); - continue; - } - printf("%s: %d\n", argv[i], (int)_sys_getsize(h)); - _sys_close(h); - } -} - -void cmd_hexdump(int argc, char **argv) { - DEFAULT_ARGV("!stdin"); - const size_t buflen = 4096; - uint8_t *buf = malloc(buflen); - FILE *file; - bool canonical = strcmp(argv[0], "hd") == 0; - size_t readlen = ~0; - size_t pos = 0; - bool raw = false; - - int c; - optind = 0; - while ((c = getopt(argc, argv, "Cn:s:r")) != -1) { - switch (c) { - case 'C': - canonical = true; - break; - case 'n': - readlen = strtol(optarg, NULL, 0); - break; - case 's': - pos = strtol(optarg, NULL, 0); - break; - case 'r': /* "raw" mode, print data as soon as it's read without buffering */ - raw = true; - break; - default: - return; - } - } - if (readlen != (size_t)~0) - readlen += pos; - - for (; optind < argc; optind++) { - file = fopen(argv[optind], "r"); - if (!file) { - warn("couldn't open %s", argv[optind]); - continue; - } - if (raw) fextflags(file, FEXT_NOFILL); - fseek(file, pos, SEEK_SET); - bool skipped = false; - while (pos < readlen) { - size_t len = buflen; - if (len > readlen - pos) - len = readlen - pos; - len = fread(buf, 1, len, file); - if (len == 0) break; - - for (size_t i = 0; i < len; i += 16) { - if (i >= 16 && !memcmp(buf + i, buf + i - 16, 16)) { - if (!skipped) { - printf("*\n"); - skipped = true; - } - continue; - } else skipped = false; - printf("%08zx ", pos + i); - - for (size_t j = i; j < i + 8 && j < len; j++) - printf("%02x ", buf[j]); - printf(" "); - for (size_t j = i + 8; j < i + 16 && j < len; j++) - printf("%02x ", buf[j]); - - if (canonical) { - printf(" |"); - - for (size_t j = i; j < i + 16 && j < len; j++) { - char c = '.'; - if (0x20 <= buf[j] && buf[j] < 0x7f) c = buf[j]; - printf("%c", c); - } - printf("|\n"); - } else { - printf("\n"); - } - } - pos += len; - } - printf("%08zx\n", pos); - fclose(file); - } -} - -static void cmd_ls(int argc, char **argv) { - FILE *file; - const size_t buflen = 4096; - char *buf = malloc(buflen); - - DEFAULT_ARGV("."); - for (int i = 1; i < argc; i++) { - char *path = (void*)argv[i]; - int pathlen = strlen(path); - - if (!pathlen || path[pathlen - 1] != '/') { - memcpy(buf, path, pathlen); - buf[pathlen] = '/'; - buf[pathlen+1] = '\0'; - path = buf; - } - - file = fopen(path, "r"); - if (!file) { - warn("couldn't open %s", argv[i]); - continue; - } - for (;;) { - int len = fread(buf, 1, buflen, 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_mkdir(int argc, char **argv) { - // TODO mkdir -p - if (argc < 2) errx(1, "no arguments"); - for (int i = 1; i < argc; i++) { - if (mkdir(argv[i], 0777) < 0) - perror(argv[i]); - } -} - -static void cmd_rm(int argc, char **argv) { - if (argc < 2) errx(1, "no arguments"); - for (int i = 1; i < argc; i++) { - if (unlink(argv[i]) < 0) - perror(argv[i]); - } -} - -static void cmd_sleep(int argc, char **argv) { - if (argc < 2) errx(1, "no arguments"); - _sys_sleep(strtol(argv[1], NULL, 0) * 1000); -} - -static void cmd_touch(int argc, char **argv) { - if (argc < 2) errx(1, "no arguments"); - for (int i = 1; i < argc; i++) { - FILE *f = fopen(argv[i], "a"); - if (!f) perror(argv[i]); - fclose(f); - } -} - -static void cmd_whitelist(int argc, char **argv) { - int split = 1; - for (; split < argc;) { - if (!strcmp("--", argv[split])) break; - split++; - } - argv[split] = NULL; - MOUNT_AT("/") { fs_whitelist((void*)&argv[1]); } - - if (split < argc) { - run_args(argc - split - 1, &argv[split + 1], NULL); - } else { - const char **argv = (const char*[]){"shell", NULL}; - run_args(1, (void*)argv, NULL); - } -} - -struct builtin builtins[] = { - {"cat", cmd_cat}, - {"echo", cmd_echo}, - {"getsize", cmd_getsize}, - {"hd", cmd_hexdump}, - {"hexdump", cmd_hexdump}, - {"ls", cmd_ls}, - {"mkdir", cmd_mkdir}, - {"rm", cmd_rm}, - {"sleep", cmd_sleep}, - {"touch", cmd_touch}, - {"whitelist", cmd_whitelist}, - {NULL, NULL}, -}; diff --git a/src/user/app/shell/builtins.h b/src/user/app/shell/builtins.h deleted file mode 100644 index 1e422bb..0000000 --- a/src/user/app/shell/builtins.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include <camellia/syscalls.h> -#include <stdbool.h> - -struct builtin { - const char *name; - void (*fn)(int argc, char **argv); -}; - -extern struct builtin builtins[]; diff --git a/src/user/app/shell/parser.c b/src/user/app/shell/parser.c deleted file mode 100644 index ad09348..0000000 --- a/src/user/app/shell/parser.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "shell.h" -#include <ctype.h> -#include <stdbool.h> -#include <string.h> - -static char skipspace(char **sp) { - char *s = *sp; - while (*s && isspace(*s)) s++; - *sp = s; - return *s; -} - -static bool isspecial(char c) { - return c == '>' || c == '#'; -} - -static char *parg(char **sp) { - char *s = *sp; - char *res = NULL; - - if (skipspace(&s)) { - // TODO incorrectly handles strings like a"b" - switch (*s) { - case '"': - s++; - res = s; - while (*s && *s != '"') - s++; - break; - default: - res = s; - while (*s && !isspace(*s) && !isspecial(*s)) - s++; - if (*s == '#') { - *s = '\0'; /* end parsing early */ - if (res == s) /* don't output an empty arg */ - res = NULL; - } - break; - } - if (*s) *s++ = '\0'; - } - - *sp = s; - return res; -} - -int parse(char *s, char **argv, size_t argvlen, struct redir *redir) { - if (argvlen == 0) return -1; - size_t argc = 0; - char *arg; - - *argv = NULL; - redir->stdout = NULL; - redir->append = false; - - while (skipspace(&s)) { - switch (*s) { - case '>': - s++; - if (*s == '>') { - s++; - redir->append = true; - } - redir->stdout = parg(&s); - break; - default: - arg = parg(&s); - argv[argc++] = arg; - if (argc >= argvlen) - return -1; - } - } - argv[argc] = NULL; - return argc; -} diff --git a/src/user/app/shell/shell.c b/src/user/app/shell/shell.c deleted file mode 100644 index 185aa7e..0000000 --- a/src/user/app/shell/shell.c +++ /dev/null @@ -1,178 +0,0 @@ -#include "builtins.h" -#include "shell.h" -#include <camellia/flags.h> -#include <camellia/syscalls.h> -#include <err.h> -#include <errno.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <camellia/fs/misc.h> -#include <x86intrin.h> - -int main(); - -static void execp(char **argv) { - if (!argv || !*argv) return; - if (strncmp(argv[0], "/", 1) == 0 || - strncmp(argv[0], "./", 2) == 0 || - strncmp(argv[0], "../", 3) == 0) - { - execv(argv[0], argv); - } else { - size_t cmdlen = strlen(argv[0]); - char *s = malloc(cmdlen + 6); - if (!s) err(1, "malloc"); - memcpy(s, "/bin/", 5); - memcpy(s + 5, argv[0], cmdlen + 1); - execv(s, argv); - free(s); - } -} - -void run_args(int argc, char **argv, struct redir *redir) { - if (!*argv) return; - - /* "special" commands that can't be handled in a subprocess */ - if (!strcmp(argv[0], "mount")) { - if (argc < 3) { - fprintf(stderr, "mount: not enough arguments\n"); - return; - } - MOUNT_AT("/") { - fs_dirinject(argv[1]); - } - MOUNT_AT(argv[1]) { - run_args(argc - 2, argv + 2, redir); - exit(1); - } - return; - } else if (!strcmp(argv[0], "shadow")) { - if (argc < 2) { - fprintf(stderr, "shadow: missing path\n"); - } else { - _sys_mount(HANDLE_NULLFS, argv[1], strlen(argv[1])); - } - } else if (!strcmp(argv[0], "procmnt")) { - if (argc < 2) { - fprintf(stderr, "procmnt: missing mountpoint\n"); - return; - } - _sys_mount(HANDLE_PROCFS, argv[1], strlen(argv[1])); - /* - if (!(3 <= argc && !strcmp(argv[2], "raw"))) { - if (!mount_at("/")) { - fs_dirinject(argv[1]); - exit(1); - } - } - */ - return; - } else if (!strcmp(argv[0], "cd")) { - if (chdir(argc > 1 ? argv[1] : "/") < 0) - perror("cd"); - return; - } else if (!strcmp(argv[0], "time")) { - uint64_t time = __rdtsc(); - uint64_t div = 3000; - run_args(argc - 1, argv + 1, redir); - time = __rdtsc() - time; - printf("%lu ns (assuming 3GHz)\n", time / div); - return; - } else if (!strcmp(argv[0], "exit")) { - exit(0); - } else if (!strcmp(argv[0], "getpid")) { - printf("my\t%d\nparent\t%d\n", getpid(), getppid()); - return; - } - - if (fork()) { - _sys_await(); - return; - } - - if (redir && redir->stdout) { - FILE *f = fopen(redir->stdout, redir->append ? "a" : "w"); - if (!f) { - err(1, "couldn't open %s for redirection", redir->stdout); - } - - /* a workaround for file offsets not being preserved across exec()s. - * TODO document that weird behaviour of exec() */ - hid_t p[2]; - if (_sys_pipe(p, 0) < 0) { - errx(1, "couldn't create redirection pipe"); - } - if (!_sys_fork(FORK_NOREAP, NULL)) { - /* the child forwards data from the pipe to the file */ - const size_t buflen = 512; - char *buf = malloc(buflen); - if (!buf) err(1, "when redirecting"); - close(p[1]); - for (;;) { - long len = _sys_read(p[0], buf, buflen, 0); - if (len < 0) exit(0); - fwrite(buf, 1, len, f); - if (ferror(f)) exit(0); - } - } - - fclose(f); - close(p[0]); - if (_sys_dup(p[1], 1, 0) < 0) { - errx(1, "dup() failed when redirecting"); - } - } - - for (struct builtin *iter = builtins; iter->name; iter++) { - if (!strcmp(argv[0], iter->name)) { - setprogname(argv[0]); - iter->fn(argc, argv); - exit(0); - } - } - - execp(argv); - if (errno == EINVAL) { - errx(1, "%s isn't a valid executable", argv[0]); - } else { - errx(1, "unknown command: %s", argv[0]); - } -} - -static void run(char *cmd) { -#define ARGV_MAX 16 - char *argv[ARGV_MAX]; - struct redir redir; - int argc = parse(cmd, argv, ARGV_MAX, &redir); - if (argc < 0) { - warn("parsing error"); - } else { - run_args(argc, argv, &redir); - } -} - -int main(int argc, char **argv) { - static char buf[256]; - FILE *f = stdin; - - if (argc > 1) { - f = fopen(argv[1], "r"); - if (!f) { - err(1, "couldn't open %s", argv[1]); - return 1; - } - } - - for (;;) { - if (f == stdin) { - printf("%s $ ", getcwd(buf, sizeof buf)); - } - if (!fgets(buf, 256, f)) { - return 0; - } - run(buf); - } -} diff --git a/src/user/app/shell/shell.h b/src/user/app/shell/shell.h deleted file mode 100644 index 050e704..0000000 --- a/src/user/app/shell/shell.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include <stdbool.h> -#include <stddef.h> - -struct redir { - const char *stdout; - bool append; -}; - -int parse(char *s, char **argv, size_t argvlen, struct redir *redir); -void run_args(int argc, char **argv, struct redir *redir); |