]> Trent Huber's Code - thus.git/commitdiff
Improve error handling
authorTrent Huber <trentmhuber@gmail.com>
Tue, 6 May 2025 06:44:28 +0000 (02:44 -0400)
committerTrent Huber <trentmhuber@gmail.com>
Tue, 6 May 2025 06:44:28 +0000 (02:44 -0400)
build.c
external/cbs
main.c

diff --git a/build.c b/build.c
index 2ab087785669e42fbb5cd88edbd2594ac2571c3a..bb28a1b32028a6426e092dff40c745e514bd49bf 100644 (file)
--- a/build.c
+++ b/build.c
@@ -4,6 +4,7 @@ int main(void) {
    build(NULL);
 
    compile("main", NULL);
+
    load('x', "ash", "main", NULL);
 
    return EXIT_SUCCESS;
index 47c262dc02e5f6ed3dba9e092a5f750084bfad95..51d2489cfcf1c245db14c3a9e7c9e40e6a550f4c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 47c262dc02e5f6ed3dba9e092a5f750084bfad95
+Subproject commit 51d2489cfcf1c245db14c3a9e7c9e40e6a550f4c
diff --git a/main.c b/main.c
index e707e5572851db300809d2f8fb5f95dee3a784dc..6647dea0288b8bc46f4d0f28685bfefda97a25c9 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,3 +1,4 @@
+#include <err.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,27 +7,30 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#define BUFLEN 1024
-
-void nlprompt(int sig) {
-   (void)sig;
-
-   printf("\n%% ");
+void prompt(int sig) {
+   if (sig == SIGINT) printf("\n");
+   printf("%% ");
    fflush(stdout);
 }
 
+#define BUFLEN 1024
+
 char **tokenize(char *p) {
    size_t i;
    static char *result[BUFLEN / 2];
 
+   while (*p == ' ') ++p;
    for (i = 0; *p != '\n'; ++i) {
        result[i] = p;
        while (*p != ' ' && *p != '\n') ++p;
        *p++ = '\0';
-       if (*p == '\0') break;
+       if (*p == '\0') {
+           ++i;
+           break;
+       }
        while (*p == ' ') ++p;
    }
-   result[i + 1] = NULL;
+   result[i] = NULL;
    return result;
 }
 
@@ -46,44 +50,18 @@ pid_t popbgps(void) {
    return bgps.sp != bgps.bp ? bgps.pgids[bgps.sp--] : -1;
 }
 
+pid_t self;
+
 void await(pid_t cpgid) {
    int status;
-   pid_t pgid;
 
-   if (waitpid(cpgid, &status, WUNTRACED) == -1) {
-       dprintf(STDERR_FILENO, "ash: Unable to await previous command: %s\n",
-               strerror(errno));
-       exit(EXIT_FAILURE);
-   }
-   if (!WIFSTOPPED(status)) { // Reap
+   if (waitpid(cpgid, &status, WUNTRACED) != -1 && !WIFSTOPPED(status)) {
        while (waitpid(-cpgid, NULL, 0) != -1);
-       if (errno != ECHILD) {
-           dprintf(STDERR_FILENO, "ash: Unable to await previous command: %s\n",
-                   strerror(errno));
-           exit(EXIT_FAILURE);
-       }
-       errno = 0;
-   }
-   if ((pgid = getpgid(0)) == -1) {
-       dprintf(STDERR_FILENO, "ash: Unable to get group process id: %s\n",
-               strerror(errno));
-       exit(EXIT_FAILURE);
-   }
-   if (signal(SIGTTOU, SIG_IGN) == SIG_ERR) {
-       dprintf(STDERR_FILENO, "ash: Unable to ignore SIGTTOU signal: %s\n",
-               strerror(errno));
-       exit(EXIT_FAILURE);
-   }
-   if (tcsetpgrp(STDIN_FILENO, pgid) == -1) {
-       dprintf(STDERR_FILENO, "ash: Unable to set tty foreground "
-               "process group: %s\n", strerror(errno));
-       exit(EXIT_FAILURE);
-   }
-   if (signal(SIGTTOU, SIG_DFL) == SIG_ERR) {
-       dprintf(STDERR_FILENO, "ash: Unable to set SIGTTOU signal: %s\n",
-               strerror(errno));
-       exit(EXIT_FAILURE);
+       if (errno != ECHILD && killpg(cpgid, SIGKILL) == -1) exit(EXIT_FAILURE);
    }
+   if (signal(SIGTTOU, SIG_IGN) == SIG_ERR) exit(EXIT_FAILURE);
+   if (tcsetpgrp(STDIN_FILENO, self) == -1) exit(EXIT_FAILURE);
+   if (signal(SIGTTOU, SIG_DFL) == SIG_ERR) warn("Ignoring signal SIGTTOU");
 
    if (WIFSIGNALED(status)) printf("\n");
    if (WIFSTOPPED(status)) pushbgps(cpgid);
@@ -93,21 +71,21 @@ int builtin(char **tokens) {
    pid_t fgpgid;
 
    if (strcmp(tokens[0], "cd") == 0) {
-       if (chdir(tokens[1]) == -1) {
-           dprintf(STDERR_FILENO, "ash: Unable to cd: %s\n", strerror(errno));
-           exit(EXIT_FAILURE);
+       if (chdir(tokens[1]) == -1)
+           warn("Unable to change directory to `%s'", tokens[1]);
+   } else if (strcmp(tokens[0], "fg") == 0) { // TODO: Take an argument
+       if ((fgpgid = popbgps()) == -1) {
+           warnx("No background processes");
+           return 1;
        }
-   } else if (strcmp(tokens[0], "fg") == 0) {
-       if ((fgpgid = popbgps()) == -1) return 1;
        if (tcsetpgrp(STDIN_FILENO, fgpgid) == -1) {
-           dprintf(STDERR_FILENO, "ash: Unable to set tty foreground "
-                   "process group: %s\n", strerror(errno));
-           exit(EXIT_FAILURE);
+           warn("Unable to bring process group %d to foreground", fgpgid);
+           return 1;
        }
        if (killpg(fgpgid, SIGCONT) == -1) {
-           dprintf(STDERR_FILENO, "ash: Unable to wake up process group "
-                   "%d to wake up: %s\n", fgpgid, strerror(errno));
-           exit(EXIT_FAILURE);
+           if (tcsetpgrp(STDIN_FILENO, self) == -1) exit(EXIT_FAILURE);
+           warn("Unable to wake up process group %d", fgpgid);
+           return 1;
        }
        await(fgpgid);
    } else return 0;
@@ -120,44 +98,45 @@ int main(void) {
    char **tokens;
    pid_t cpgid;
 
-   signal(SIGINT, nlprompt);
+   signal(SIGINT, prompt);
+   if ((self = getpgid(0)) == -1)
+       err(EXIT_FAILURE, "Unable to get pgid of self");
    for (;;) {
-       printf("%% ");
+       prompt(0);
        if (fgets(buffer, BUFLEN, stdin) == NULL) {
            if (feof(stdin)) {
                printf("\n");
                exit(EXIT_SUCCESS);
            }
-           dprintf(STDERR_FILENO, "ash: Couldn't read input");
-           if (!ferror(stdin)) dprintf(STDERR_FILENO, ": %s", strerror(errno));
-           dprintf(STDERR_FILENO, "\n");
-           exit(EXIT_FAILURE);
+           warn("Unable to read user input");
+           continue;
        }
        tokens = tokenize(buffer);
 
-       if (builtin(tokens)) continue;
+       if (!*tokens || builtin(tokens)) continue;
 
-       if ((cpgid = fork()) == 0) {
-           if (execvp(tokens[0], tokens) == -1) {
-               dprintf(STDERR_FILENO, "ash: Unable to run command `%s': %s\n",
-                       tokens[0], strerror(errno));
-               exit(EXIT_FAILURE);
-           }
-       }
+       if ((cpgid = fork()) == 0)
+           if (execvp(tokens[0], tokens) == -1)
+               err(EXIT_FAILURE, "Unable to run command `%s'", tokens[0]);
        if (setpgid(cpgid, cpgid) == -1) {
-           dprintf(STDERR_FILENO, "ash: Unable to change child group process id: %s\n",
-                   strerror(errno));
-           exit(EXIT_FAILURE);
+           warn("Unable to set process group of process %d", cpgid);
+           if (kill(cpgid, SIGKILL) == -1)
+               warn("Unable to kill process %d; manual termination required", cpgid);
+           continue;
        }
        if (tcsetpgrp(STDIN_FILENO, cpgid) == -1) {
-           dprintf(STDERR_FILENO, "ash: Unable to set tty foreground "
-                   "process group: %s\n", strerror(errno));
-           exit(EXIT_FAILURE);
+           warn("Unable to bring process group %d to foreground", cpgid);
+           if (killpg(cpgid, SIGKILL) == -1)
+               warn("Unable to kill process group %d; manual termination required", cpgid);
+           continue;
        }
        if (killpg(cpgid, SIGCONT) == -1) {
-           dprintf(STDERR_FILENO, "ash: Unable to signal child to wake up: %s\n",
-                   strerror(errno));
-           exit(EXIT_FAILURE);
+           if (tcsetpgrp(STDIN_FILENO, self) == -1) exit(EXIT_FAILURE);
+           warn("Process group %d may be blocked; killing it", cpgid);
+           if (killpg(cpgid, SIGKILL) == -1)
+               warn("Unable to kill process group %d; manual termination required", cpgid);
+           else warn("Successfully terminated process group %d", cpgid);
+           continue;
        }
        await(cpgid);
    }