summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2017-10-13 22:05:22 -0400
committerJune McEnroe <june@causal.agency>2017-10-13 22:05:22 -0400
commit2ad5ac43d3941aad6ed56ba8031a2170be9025f2 (patch)
tree33fe1b76d30a17fe28bf483a5e7201f8c3f36232
parentAdd beginning of very basic shell, ish (diff)
downloadsrc-2ad5ac43d3941aad6ed56ba8031a2170be9025f2.tar.gz
src-2ad5ac43d3941aad6ed56ba8031a2170be9025f2.zip
Handle child signals in ish
-rw-r--r--bin/ish.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/bin/ish.c b/bin/ish.c
index 5812e76d..3bb7c08f 100644
--- a/bin/ish.c
+++ b/bin/ish.c
@@ -1,5 +1,6 @@
 #include <err.h>
 #include <histedit.h>
+#include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -9,16 +10,16 @@
 #include <unistd.h>
 
 #define UNUSED __attribute__((unused))
+#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
 
-static int builtinCd(int argc, const char *argv[]) {
-    const char *path = getenv("HOME");
-    if (argc > 1) path = argv[1];
+static int cdBuiltin(int argc, const char *argv[]) {
+    const char *path = (argc > 1) ? argv[1] : getenv("HOME");
     int error = chdir(path);
     if (error) warn("%s", path);
     return error;
 }
 
-static int builtinExec(int argc, const char *argv[]) {
+static int execBuiltin(int argc, const char *argv[]) {
     if (argc < 2) return 0;
     execvp(argv[1], (char *const *)argv + 1);
     err(EX_UNAVAILABLE, "%s", argv[1]);
@@ -26,12 +27,32 @@ static int builtinExec(int argc, const char *argv[]) {
 
 static const struct {
     const char *name;
-    int (*fn)(int argc, const char *argv[]);
+    int (*fn)(int, const char **);
 } BUILTINS[] = {
-    { "cd", builtinCd },
-    { "exec", builtinExec },
+    { "cd", cdBuiltin },
+    { "exec", execBuiltin },
 };
-#define BUILTINS_LEN (sizeof(BUILTINS) / sizeof(BUILTINS[0]))
+
+static int forkExec(int argc UNUSED, const char *argv[]) {
+    pid_t pid = fork();
+    if (pid < 0) err(EX_OSERR, "fork");
+
+    if (!pid) {
+        execvp(argv[0], (char *const *)argv);
+        err(EX_UNAVAILABLE, "%s", argv[0]);
+    }
+
+    int status;
+    pid_t dead = wait(&status);
+    if (dead < 0) err(EX_OSERR, "wait");
+
+    if (WIFEXITED(status)) {
+        return WEXITSTATUS(status);
+    } else {
+        warnx("%s %s", sys_siglist[WTERMSIG(status)], argv[0]);
+        return 128 + WTERMSIG(status);
+    }
+}
 
 static char *prompt(EditLine *editLine UNUSED) {
     return "$ ";
@@ -74,26 +95,13 @@ int main(int argc, const char *argv[]) {
         if (tok > 0) continue; // TODO: Change prompt.
 
         bool builtin = false;
-        for (size_t i = 0; i < BUILTINS_LEN; ++i) {
+        for (size_t i = 0; i < ARRAY_LEN(BUILTINS); ++i) {
             if (strcmp(argv[0], BUILTINS[i].name)) continue;
             builtin = true;
             BUILTINS[i].fn(argc, argv);
             break;
         }
-
-        if (!builtin) {
-            pid_t pid = fork();
-            if (pid < 0) err(EX_OSERR, "fork");
-
-            if (!pid) {
-                execvp(argv[0], (char *const *)argv);
-                err(EX_UNAVAILABLE, "%s", argv[0]);
-            }
-
-            int status;
-            pid_t dead = wait(&status);
-            if (dead < 0) err(EX_OSERR, "wait");
-        }
+        if (!builtin) forkExec(argc, argv);
 
         tok_reset(tokenizer);
     }