From 6f2cac23a7e759c464ef52103fac929e1eeb6b10 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sat, 9 Oct 2021 10:30:50 -0700 Subject: feat(rc): added shell --- sys/cmd/rc/code.dep | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 sys/cmd/rc/code.dep (limited to 'sys/cmd/rc/code.dep') diff --git a/sys/cmd/rc/code.dep b/sys/cmd/rc/code.dep new file mode 100644 index 0000000..7fdd4bc --- /dev/null +++ b/sys/cmd/rc/code.dep @@ -0,0 +1,166 @@ +#if 0 +// simple example code +error +cd(Args args) +{ + switch (args.len) { + case 0: + errorf("reached cd with no arguments!"); + return 1; + case 1: + one: + errorf("sh: expected argument to command 'cd'"); + return 1; + case 2: + if (args.a[1] == nil) + goto one; + break; + default: + errorf("sh: too many arguments to command 'cd'"); + return 1; + } + if (chdir(args.a[1])) + errorf("cd fail: %s", strerror(errno)); + + return 0; +} + +error +quit(Args args) +{ + exit(0); +} + +Builtin builtins[] = { + { "cd", cd }, + { "exit", quit }, +}; + +void +clear(Header *arr) +{ + arr->len = 0; +} + +int +readline(Code *code) +{ + int n, b; + + n = code->len; +getchar: + if (code->len >= code->cap) { + code->cap += 100; + code->s = realloc(code->s, code->cap); + } + /* TODO: unicode? */ + switch ((b = getchar())) { + case EOF: + n = -1; + goto null; + case '\n': + n = code->len - n; + null: + code->s[code->len] = '\0'; + break; + default: + code->s[code->len++] = b; + goto getchar; + } + + return n; +} + +/* TODO: unicode */ +int +readargs(Code code, Args *args) +{ + if (args->a) + clear(&args->hdr); + else { + args->cap += 20; + args->a = realloc(args->a, args->cap); + } + + args->a[args->len++] = code.s; + while (*code.s) { + if (!isspace(*code.s++)) + continue; + + code.s[-1] = '\0'; + /* consume all remaining space */ + while (isspace(*code.s)) + code.s++; + + if (args->len >= args->cap-1) { + args->cap += 20; + args->a = realloc(args->a, args->cap); + } + args->a[args->len++] = code.s; + } + /* nil acts as a sentinel value */ + args->a[args->len] = nil; + + return args->len; +} + +error +execute(Args args) +{ + int i, status; + pid_t cid, wid; + + for (i = 0; i < arrlen(builtins); i++) { + if (strcmp(args.a[0], builtins[i].cmd) == 0) + return builtins[i].func(args); + } + + if ((cid = fork()) == 0) { + if (execvp(args.a[0], args.a) == -1) + errorf("exec failed: %s", strerror(errno)); + exit(1); + } else if (cid > 0) + do + wid = waitpid(cid, &status, WUNTRACED); + while (!WIFEXITED(status) && !WIFSIGNALED(status)); + else + errorf("fork failed: %s", strerror(errno)); + + return status; +} + +static +void +flush(void) +{ + io·flush(stdout); +} + +static +void +prompt(void) +{ + printf(";"); + flush(); +} + +int +main(int argc, char *argv[]) +{ + int i, err, n; + Code code = {0}; + Args args = {0}; + + ARGBEGIN { + } ARGEND; + + do { + clear(&code.hdr); + prompt(); + + n = readline(&code); + readargs(code, &args); + err = execute(args); + } while (!err && n > 0); +} +#endif -- cgit v1.2.1