From 8e8998e778408cd42194225ae6fd3c581ac4be5c Mon Sep 17 00:00:00 2001 From: Trent Huber Date: Thu, 20 Nov 2025 00:31:33 -0500 Subject: [PATCH] Fix undefined behavior, more cleaning --- src/builtins/alias.c | 9 ++++----- src/builtins/build.c | 3 +-- src/builtins/builtin.c | 1 - src/builtins/builtin.h | 5 +++++ src/builtins/cd.c | 4 ++-- src/builtins/fg.c | 5 +---- src/builtins/fg.h | 1 - src/builtins/list.h | 6 ------ src/builtins/pwd.c | 7 +++---- src/input.c | 6 +++--- src/parse.c | 10 +++++----- src/signals.c | 20 ++++++++++---------- src/utils.c | 30 ++++++++++++++---------------- tools/install.c | 5 ++--- tools/uninstall.c | 2 +- 15 files changed, 51 insertions(+), 63 deletions(-) delete mode 100644 src/builtins/list.h diff --git a/src/builtins/alias.c b/src/builtins/alias.c index 1f4a21b..42105a8 100644 --- a/src/builtins/alias.c +++ b/src/builtins/alias.c @@ -38,12 +38,11 @@ char **parsealias(char *value) { if (!value) return NULL; + c = (struct context){.b = c.buffer, .alias = 1}; strcpy(c.buffer, value); - l = strlen(value); - c.buffer[l + 1] = '\0'; - c.buffer[l] = ';'; - c.b = c.buffer; - c.alias = 1; + l = strlen(c.buffer); + c.buffer[l++] = ';'; + c.buffer[l] = '\0'; if (!parse(&c)) return NULL; diff --git a/src/builtins/build.c b/src/builtins/build.c index a115a39..30ad344 100644 --- a/src/builtins/build.c +++ b/src/builtins/build.c @@ -21,8 +21,7 @@ int main(void) { if (!(dir = opendir("./"))) err(EXIT_FAILURE, "Unable to open current directory"); - dprintf(listfd, "#include \n\n#include \"builtin.h\"\n" - "#include \"list.h\"\n\n"); + dprintf(listfd, "#include \n\n#include \"builtin.h\"\n\n"); src = srcs; errno = 0; diff --git a/src/builtins/builtin.c b/src/builtins/builtin.c index cf2d914..1e005bf 100644 --- a/src/builtins/builtin.c +++ b/src/builtins/builtin.c @@ -3,7 +3,6 @@ #include #include "builtin.h" -#include "list.h" #include "utils.h" int (*getbuiltin(char *name))(char **args, size_t numargs) { diff --git a/src/builtins/builtin.h b/src/builtins/builtin.h index 768ba7e..0aeaf3a 100644 --- a/src/builtins/builtin.h +++ b/src/builtins/builtin.h @@ -1,2 +1,7 @@ +extern struct builtin { + char *name; + int (*func)(char **args, size_t numargs); +} builtins[]; + int (*getbuiltin(char *name))(char **args, size_t numargs); int usage(char *program, char *options); diff --git a/src/builtins/cd.c b/src/builtins/cd.c index 12451af..acd9c4f 100644 --- a/src/builtins/cd.c +++ b/src/builtins/cd.c @@ -20,8 +20,8 @@ int cd(char **args, size_t numargs) { return EXIT_FAILURE; } l = strlen(buffer); - buffer[l + 1] = '\0'; - buffer[l] = '/'; + buffer[l++] = '/'; + buffer[l] = '\0'; break; default: return usage(args[0], "[directory]"); diff --git a/src/builtins/fg.c b/src/builtins/fg.c index 0812bee..5b94fc8 100644 --- a/src/builtins/fg.c +++ b/src/builtins/fg.c @@ -96,6 +96,7 @@ int runfg(pid_t id) { exit(EXIT_SUCCESS); } if (sigint) sigint = 0; + if (sigwinch) sigwinch = 0; } setsig(SIGCHLD, &defaultaction); fgjob.done = errno = 0; @@ -123,10 +124,6 @@ int runfg(pid_t id) { return 1; } -void deinitfg(void) { - setconfig(&canonical); -} - int fg(char **args, size_t numargs) { struct bgjob job; long l; diff --git a/src/builtins/fg.h b/src/builtins/fg.h index f1dab38..1308bcc 100644 --- a/src/builtins/fg.h +++ b/src/builtins/fg.h @@ -3,4 +3,3 @@ extern struct termios canonical; int setconfig(struct termios *mode); void initfg(void); int runfg(pid_t id); -void deinitfg(void); diff --git a/src/builtins/list.h b/src/builtins/list.h deleted file mode 100644 index 0c4a403..0000000 --- a/src/builtins/list.h +++ /dev/null @@ -1,6 +0,0 @@ -struct builtin { - char *name; - int (*func)(char **args, size_t numargs); -}; - -extern struct builtin builtins[]; diff --git a/src/builtins/pwd.c b/src/builtins/pwd.c index c6a6a28..6c5b9db 100644 --- a/src/builtins/pwd.c +++ b/src/builtins/pwd.c @@ -18,10 +18,9 @@ int pwd(char **args, size_t numargs) { note("Unable to get current working directory"); return EXIT_FAILURE; } - l = strlen(buffer); - if (buffer[l - 1] != '/') { - buffer[l] = '/'; - buffer[l + 1] = '\0'; + if (buffer[(l = strlen(buffer)) - 1] != '/') { + buffer[l++] = '/'; + buffer[l] = '\0'; } if (setenv("PWD", buffer, 1) == -1) { note("Unable to set $PWD$"); diff --git a/src/input.c b/src/input.c index fbf60b4..e6b363d 100644 --- a/src/input.c +++ b/src/input.c @@ -32,15 +32,15 @@ int stringinput(struct context *c) { end = c->string; while (*end && *end != '\n') ++end; l = end - c->string; - while (*end == '\n') ++end; /* `scriptinput()' uses `stringinput()' */ + while (*end == '\n') ++end; if (l > MAXCHARS) { note("Line too long, exceeds %d character limit", MAXCHARS); return 0; } strncpy(c->buffer, c->string, l); - c->buffer[l] = ';'; - c->buffer[l + 1] = '\0'; + c->buffer[l++] = ';'; + c->buffer[l] = '\0'; c->string = end; return 1; diff --git a/src/parse.c b/src/parse.c index b090409..3ed02ca 100644 --- a/src/parse.c +++ b/src/parse.c @@ -129,16 +129,16 @@ int parse(struct context *c) { case '\\': if (!quote) break; switch (*(c->b + 1)) { + default: + memmove(c->b, c->b + 1, end-- - c->b); + --c->b; + *(c->b + 1) = *c->b; case '$': case '~': case '"': case '\\': - break; - default: - memmove(c->b, c->b + 1, end-- - c->b--); - *(c->b + 1) = *c->b; + memmove(c->b, c->b + 1, end-- - c->b); } - memmove(c->b, c->b + 1, end-- - c->b); break; case '*': case '?': diff --git a/src/signals.c b/src/signals.c index 4d65872..3f4318d 100644 --- a/src/signals.c +++ b/src/signals.c @@ -5,7 +5,7 @@ #include "utils.h" -int sigwinch, sigquit, sigint; +int sigquit, sigint, sigwinch; sigset_t shellsigmask, childsigmask; struct sigaction defaultaction; @@ -14,12 +14,6 @@ void setsig(int sig, struct sigaction *act) { fatal("Unable to install %s handler", strsignal(sig)); } -static void sigwinchhandler(int sig) { - (void)sig; - - sigwinch = 1; -} - static void sigquithandler(int sig) { (void)sig; @@ -32,6 +26,12 @@ static void siginthandler(int sig) { sigint = 1; } +static void sigwinchhandler(int sig) { + (void)sig; + + sigwinch = 1; +} + void initsignals(void) { struct sigaction action; @@ -46,9 +46,6 @@ void initsignals(void) { setsig(SIGTTOU, &defaultaction); setsig(SIGTTIN, &defaultaction); - action = (struct sigaction){.sa_handler = sigwinchhandler}; - setsig(SIGWINCH, &action); - action = (struct sigaction){.sa_handler = sigquithandler}; setsig(SIGHUP, &action); setsig(SIGQUIT, &action); @@ -56,4 +53,7 @@ void initsignals(void) { action = (struct sigaction){.sa_handler = siginthandler}; setsig(SIGINT, &action); + + action = (struct sigaction){.sa_handler = sigwinchhandler}; + setsig(SIGWINCH, &action); } diff --git a/src/utils.c b/src/utils.c index f7de714..a59c0b7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -57,19 +57,18 @@ void init(void) { note("Unable to update $SHLVL$ environment variable"); if (!(home = getenv("HOME"))) fatal("Unable to find home directory"); - l = strlen(home); - if (home[l - 1] != '/') { + if (home[(l = strlen(home)) - 1] != '/') { strcpy(buffer, home); - buffer[l] = '/'; - buffer[l + 1] = '\0'; + buffer[l++] = '/'; + buffer[l] = '\0'; if (setenv("HOME", buffer, 1) == -1 || !(home = getenv("HOME"))) note("Unable to append trailing slash to $HOME$"); } if (!getcwd(buffer, PATH_MAX)) fatal("Unable to find current directory"); l = strlen(buffer); - buffer[l] = '/'; - buffer[l + 1] = '\0'; + buffer[l++] = '/'; + buffer[l] = '\0'; if (setenv("PWD", buffer, 1) == -1) note("Unable to append trailing slash to $PWD$"); @@ -90,8 +89,7 @@ char *catpath(char *dir, char *filename, char *buffer) { size_t l; int slash; - l = strlen(dir); - slash = dir[l - 1] == '/'; + slash = dir[(l = strlen(dir)) - 1] == '/'; if (l + slash + strlen(filename) + 1 > PATH_MAX) { note("Path name `%s%s%s' too long", dir, slash ? "/" : "", filename); return NULL; @@ -105,7 +103,7 @@ char *catpath(char *dir, char *filename, char *buffer) { } char *quoted(char *token) { - char *p, *q, quote; + char *p, *end, quote; enum { NONE, DOUBLE, @@ -119,8 +117,8 @@ char *quoted(char *token) { degree = NONE; for (p = token; *p; ++p) switch(*p) { case '[': - for (q = p; *q; ++q) if (*q == ']') break; - if (!*q) continue; + for (end = p; *end; ++end) if (*end == ']') break; + if (!*end) continue; case '>': case '<': case '*': @@ -146,18 +144,18 @@ char *quoted(char *token) { p = buffer; *p++ = quote; strcpy(p, token); - for (q = p; *q; ++q); + for (end = p; *end; ++end); if (degree != SINGLE) for (; *p; ++p) switch (*p) case '$': case '~': case '"': if (degree == ESCAPEDOUBLE) { case '\\': - memmove(p + 1, p, ++q - p); + memmove(p + 1, p, ++end - p); *p++ = '\\'; } - *q++ = quote; - *q++ = '\0'; + *end++ = quote; + *end = '\0'; return buffer; } @@ -165,5 +163,5 @@ char *quoted(char *token) { void deinit(void) { deinithistory(); deinitbg(); - deinitfg(); + setconfig(&canonical); } diff --git a/tools/install.c b/tools/install.c index 883514c..6ceb77f 100644 --- a/tools/install.c +++ b/tools/install.c @@ -23,13 +23,12 @@ int main(int argc, char **argv) { strcat(path, "bin/"); if ((cpid = fork()) == -1) err(EXIT_FAILURE, "Unable to fork"); - else if (cpid == 0) - run("/bin/mkdir", LIST("mkdir", "-p", path), "create", path); + if (!cpid) run("/bin/mkdir", LIST("mkdir", "-p", path), "create", path); await(cpid, "create", path); strcat(path, "thus"); if ((cpid = fork()) == -1) err(EXIT_FAILURE, "Unable to fork"); - else if (cpid == 0) + if (!cpid) run("/bin/cp", LIST("cp", "-f", "bin/thus", path), "copy", "bin/thus"); await(cpid, "copy", "bin/thus"); diff --git a/tools/uninstall.c b/tools/uninstall.c index cca930f..a8b190f 100644 --- a/tools/uninstall.c +++ b/tools/uninstall.c @@ -12,7 +12,7 @@ int main(int argc, char **argv) { if (argc != 1) err(EXIT_FAILURE, "usage: %s\n", argv[0]); if ((cpid = fork()) == -1) err(EXIT_FAILURE, "Unable to fork"); - else if (cpid == 0) + if (!cpid) run("/bin/rm", LIST("rm", STR(PATH), "uninstall"), "remove", STR(PATH)); await(cpid, "remove", STR(PATH)); -- 2.51.0