From: Trent Huber Date: Sat, 15 Nov 2025 22:52:36 +0000 (-0500) Subject: More refactoring, minor behavior fixes X-Git-Url: https://trenthuber.com/code?a=commitdiff_plain;h=146187392dd0826e7a69a094748c4ae1434c6d6a;p=thus.git More refactoring, minor behavior fixes --- diff --git a/external/cbs b/external/cbs index e998819..011c66e 160000 --- a/external/cbs +++ b/external/cbs @@ -1 +1 @@ -Subproject commit e998819b1d1e191d035600967abd84e9f2eb9cf8 +Subproject commit 011c66e9c2332506752b701fdfa37739dde67f6a diff --git a/src/builtins/alias.c b/src/builtins/alias.c index 62f3786..1f4a21b 100644 --- a/src/builtins/alias.c +++ b/src/builtins/alias.c @@ -25,19 +25,18 @@ static size_t getindex(char *name) { return i; } -char *getaliasvalue(char *name) { +char *getalias(char *name) { size_t i; if ((i = getindex(name)) == aliases.size) return NULL; return aliases.entries[i].value; } -char **getalias(char *name) { - char *value; +char **parsealias(char *value) { size_t l; static struct context c; - if (!(value = getaliasvalue(name))) return NULL; + if (!value) return NULL; strcpy(c.buffer, value); l = strlen(value); @@ -72,14 +71,16 @@ int alias(char **args, size_t numargs) { switch (numargs) { case 1: for (i = 0; i < aliases.size; ++i) - printf("%s -> %s\n", quoted(aliases.entries[i].name), + printf("%s = %s\n", quoted(aliases.entries[i].name), aliases.entries[i].value); break; case 3: if (aliases.size == MAXALIAS) { - note("Unable to add alias, maximum reached (%d)", MAXALIAS); + note("Unable to add `%s' alias, maximum reached (%d)", args[1], MAXALIAS); return EXIT_FAILURE; } + if (!parsealias(args[2])) return EXIT_FAILURE; + for (i = 1; i <= 2; ++i) { end = args[i] + strlen(args[i]); while (*args[i] == ' ') ++args[i]; diff --git a/src/builtins/alias.h b/src/builtins/alias.h index ba52065..6bf7ccb 100644 --- a/src/builtins/alias.h +++ b/src/builtins/alias.h @@ -1,3 +1,3 @@ -char *getaliasvalue(char *name); -char **getalias(char *name); +char *getalias(char *name); +char **parsealias(char *value); int removealias(char *name); diff --git a/src/builtins/bg.c b/src/builtins/bg.c index c9207ed..028a51f 100644 --- a/src/builtins/bg.c +++ b/src/builtins/bg.c @@ -12,13 +12,11 @@ #define MAXBG 100 -struct bglink { - struct bgjob job; - struct bglink *next; -}; - static struct { - struct bglink entries[MAXBG], *active, *free; + struct bglink { + struct bgjob job; + struct bglink *next; + } entries[MAXBG], *active, *free; } bgjobs; struct sigaction bgaction; diff --git a/src/builtins/build.c b/src/builtins/build.c index 40596af..a115a39 100644 --- a/src/builtins/build.c +++ b/src/builtins/build.c @@ -34,7 +34,7 @@ int main(void) { err(EXIT_FAILURE, "Unable to duplicate directory entry"); (*src)[strlen(*src) - 2] = '\0'; if (src - srcs == 2 + MAXBUILTINS + 1) - errx(EXIT_FAILURE, "Unable to add %s built-in, maximum reached (%d)", + errx(EXIT_FAILURE, "Unable to add `%s' built-in, maximum reached (%d)", *src, MAXBUILTINS); if (strcmp(*src, "builtin") != 0 && strcmp(*src, "list") != 0) dprintf(listfd, "int %s(char **args, size_t numargs);\n", *src); diff --git a/src/builtins/exec.c b/src/builtins/exec.c index e786c96..4976c70 100644 --- a/src/builtins/exec.c +++ b/src/builtins/exec.c @@ -40,5 +40,5 @@ int exec(char **args, size_t numargs) { /* execute() is guaranteed not to return, this statement just appeases the * compiler */ - return EXIT_SUCCESS; + exit(EXIT_SUCCESS); } diff --git a/src/builtins/fg.c b/src/builtins/fg.c index 9af1125..0812bee 100644 --- a/src/builtins/fg.c +++ b/src/builtins/fg.c @@ -60,10 +60,9 @@ void initfg(void) { pgid = getpgrp(); if (login && pid != pgid && setpgid(0, pgid = pid) == -1) exit(errno); - if (tcsetpgrp(STDIN_FILENO, pgid) == -1) + if (tcsetpgrp(STDIN_FILENO, pgid) == -1 + || tcgetattr(STDIN_FILENO, &canonical) == -1) exit(errno); - - if (tcgetattr(STDIN_FILENO, &canonical) == -1) exit(errno); raw = canonical; raw.c_lflag &= ~(ICANON | ECHO); if (!setconfig(&raw)) exit(EXIT_FAILURE); diff --git a/src/builtins/set.c b/src/builtins/set.c index 56f780d..49bdd96 100644 --- a/src/builtins/set.c +++ b/src/builtins/set.c @@ -7,7 +7,7 @@ int set(char **args, size_t numargs) { switch (numargs) { case 3: if (setenv(args[1], args[2], 1) == -1) { - note("Unable to set %s to %s", args[1], args[2]); + note("Unable to set `%s' to `%s'", args[1], args[2]); return EXIT_FAILURE; } case 2: diff --git a/src/builtins/unset.c b/src/builtins/unset.c index af62aeb..9d49f5d 100644 --- a/src/builtins/unset.c +++ b/src/builtins/unset.c @@ -8,6 +8,6 @@ int unset(char **args, size_t numargs) { if (unsetenv(args[1]) != -1) return EXIT_SUCCESS; - note("Unable to unset $%s$", args[1]); + note("Unable to unset `%s'", args[1]); return EXIT_FAILURE; } diff --git a/src/builtins/which.c b/src/builtins/which.c index 234a20c..242659b 100644 --- a/src/builtins/which.c +++ b/src/builtins/which.c @@ -56,8 +56,8 @@ int which(char **args, size_t numargs) { if (numargs != 2) return usage(args[0], "name"); - if ((p = getaliasvalue(args[1]))) puts(p); - else if (getbuiltin(p = args[1])) printf("%s is a built-in\n", p); + if ((p = getalias(args[1]))) puts(p); + else if (getbuiltin(p = args[1])) printf("%s is built-in\n", p); else if ((p = getpath(args[1]))) puts(quoted(p)); else { printf("%s not found\n", quoted(args[1])); diff --git a/src/main.c b/src/main.c index 09d058c..c87dfc7 100644 --- a/src/main.c +++ b/src/main.c @@ -10,16 +10,12 @@ int main(int argc, char **argv) { struct context c; c = (struct context){0}; - options(argc, argv, &c); init(); - if (login) config(".thuslogin"); if (interactive) config(".thusrc"); - while (run(&c)); - deinit(); return EXIT_SUCCESS; diff --git a/src/options.c b/src/options.c index ea305e2..48d3017 100644 --- a/src/options.c +++ b/src/options.c @@ -20,17 +20,16 @@ void options(int argc, char **argv, struct context *c) { int opt; argvector = argv; - if (argvector[0][0] == '-') { ++argvector[0]; login = 1; } if ((p = strrchr(argvector[0], '/'))) argvector[0] = p + 1; - interactive = 1; - c->input = userinput; opt = 0; argcount = argc; + interactive = 1; + c->input = userinput; while (opt != 'c' && (opt = getopt(argcount, argvector, ":c:hl")) != -1) switch (opt) { case 'c': diff --git a/src/parse.c b/src/parse.c index 0ee28c4..b090409 100644 --- a/src/parse.c +++ b/src/parse.c @@ -16,16 +16,16 @@ static void sub(struct context *c, char **tokens, size_t numtokens) { c->t += numtokens - 1; } -static int subalias(struct context *c) { +static void subalias(struct context *c) { char **tokens; size_t numtokens; - if (c->alias || c->t != c->tokens || !(tokens = getalias(c->tokens[0]))) return 0; + if (c->alias || c->t != c->tokens + || !(tokens = parsealias(getalias(c->tokens[0])))) + return; for (numtokens = 0; tokens[numtokens]; ++numtokens); sub(c, tokens, numtokens); - - return 1; } int parse(struct context *c) { @@ -82,12 +82,8 @@ int parse(struct context *c) { errno = 0; if (stlend == c->b - 1) var = l >= 0 && l < argcount ? argvector[l] : c->b - 1; - else if (strcmp(p + 1, "^") == 0) { - if (!sprintf(var = (char [12]){0}, "%d", status)) { - note("Unable to get previous command status"); - return quit(c); - } - } else if (!(var = getenv(p + 1))) var = ""; + else if (strcmp(p + 1, "^") == 0) sprintf(var = (char [12]){0}, "%d", status); + else if (!(var = getenv(p + 1))) var = c->b - 1; v = strlen(var); offset = v - (c->b - p); @@ -110,13 +106,11 @@ int parse(struct context *c) { *c->b = '\0'; if (*c->t != c->b) ++c->t; *c->t = ++c->b; - while (*c->b && *c->b != '\'') ++c->b; if (!*c->b) { note("Quote left open-ended"); return quit(c); } - *c->b = '\0'; subalias(c); ++c->t; @@ -124,13 +118,13 @@ int parse(struct context *c) { break; case '"': + quote = !quote; + *c->b = '\0'; - if (quote) subalias(c); - if (quote || *c->t != c->b) ++c->t; + if (!quote) subalias(c); + if (!quote || *c->t != c->b) ++c->t; *c->t = c->b + 1; - quote = !quote; - break; case '\\': if (!quote) break; @@ -166,6 +160,7 @@ int parse(struct context *c) { case ';': case ' ': if (quote) break; + if (*c->b == '#') *(c->b + 1) = '\0'; term = *c->b; @@ -190,50 +185,53 @@ int parse(struct context *c) { c->r->mode = NONE; } - if (*c->t != c->b) { - if (!subalias(c) && globbing) { - globflags = GLOB_MARK; - if (prevnumglobs) globflags |= GLOB_APPEND; - switch (glob(*c->t, globflags, NULL, &globs)) { - case GLOB_NOMATCH: - note("No matches found for `%s'", *c->t); - return quit(c); - case GLOB_NOSPACE: - fatal("Memory allocation"); - } - - globbing = 0; - sub(c, globs.gl_pathv + prevnumglobs, globs.gl_pathc - prevnumglobs); - prevnumglobs = globs.gl_pathc; + if (globbing) { + globflags = GLOB_MARK; + if (prevnumglobs) globflags |= GLOB_APPEND; + switch (glob(*c->t, globflags, NULL, &globs)) { + case GLOB_NOMATCH: + note("No matches found for `%s'", *c->t); + return quit(c); + case GLOB_NOSPACE: + fatal("Memory allocation"); } + + globbing = 0; + sub(c, globs.gl_pathv + prevnumglobs, globs.gl_pathc - prevnumglobs); + prevnumglobs = globs.gl_pathc; + } + + if (*c->t != c->b) { + subalias(c); ++c->t; } - if (term != ' ') { - *c->t = NULL; - if (c->t != c->tokens) { - c->numtokens = c->t - c->tokens; - strcpy(c->current.name, c->tokens[0]); - } else c->t = NULL; - if (c->r == c->redirects) c->r = NULL; - switch (term) { - case '&': - case '|': - c->current.term = term; - if (*(c->b + 1) == term) { - ++c->current.term; - *++c->b = '\0'; - } - break; - case ';': - c->current.term = SEMI; - } - ++c->b; + if (term == ' ') { + *c->t = c->b + 1; + break; + } - return 1; + *c->t = NULL; + if (c->t != c->tokens) { + c->numtokens = c->t - c->tokens; + strcpy(c->current.name, c->tokens[0]); + } else c->t = NULL; + if (c->r == c->redirects) c->r = NULL; + switch (term) { + case '&': + case '|': + c->current.term = term; + if (*(c->b + 1) == term) { + ++c->current.term; + *++c->b = '\0'; + } + break; + case ';': + c->current.term = SEMI; } + ++c->b; - *c->t = c->b + 1; + return 1; } if (quote) { diff --git a/src/run.c b/src/run.c index 0255cda..b426607 100644 --- a/src/run.c +++ b/src/run.c @@ -79,8 +79,10 @@ int run(struct context *c) { } if (c->r) for (c->r = c->redirects; c->r->mode; ++c->r) { if (c->r != c->redirects) putchar(' '); - printf("%d%.*s", c->r->newfd, (c->r->mode & 1) + 1, &"<>>"[c->r->mode & 2]); - if (c->r->oldname) printf("%s", c->r->oldname); + if (c->r->newfd != c->r->mode >= WRITE) printf("%d", c->r->newfd); + putchar(c->r->mode < WRITE ? READ : WRITE); + if (c->r->mode == READWRITE || c->r->mode == APPEND) putchar(WRITE); + if (c->r->oldname) fputs(c->r->oldname, stdout); else printf("&%d", c->r->oldfd); } switch (c->current.term) { @@ -96,83 +98,8 @@ int run(struct context *c) { } islist = c->previous.term > BG || c->current.term > BG; - if (c->t) { - if (c->current.term == BG && bgfull()) { - note("Unable to place job in background; too many background jobs"); - return quit(c); - } - if (!(c->current.builtin = getbuiltin(c->current.name)) - && !(c->current.path = getpath(c->current.name))) { - note("Couldn't find `%s' command", c->current.name); - if (c->previous.term == PIPE) killpg(pipeid, SIGKILL); - return quit(c); - } - - ispipe = c->previous.term == PIPE || c->current.term == PIPE; - ispipestart = ispipe && c->previous.term != PIPE; - ispipeend = ispipe && c->current.term != PIPE; - - if (ispipe) { - if (!ispipeend && pipe(c->current.pipe) == -1) { - note("Unable to create pipe"); - if (!ispipestart) closepipe(c->previous); - return quit(c); - } - if ((cpid = fork()) == -1) { - note("Unable to fork child process"); - return quit(c); - } else if (cpid == 0) { - if (!ispipestart) { - if (dup2(c->previous.pipe[0], 0) == -1) - fatal("Unable to duplicate read end of `%s' pipe", c->previous.name); - if (!closepipe(c->previous)) exit(EXIT_FAILURE); - } - if (!ispipeend) { - if (dup2(c->current.pipe[1], 1) == -1) - fatal("Unable to duplicate write end of `%s' pipe", c->current.name); - if (!closepipe(c->current)) exit(EXIT_FAILURE); - } - redirectfiles(c->redirects); - execute(c); - } - if (ispipestart) pipeid = cpid; - else if (!closepipe(c->previous)) { - killpg(pipeid, SIGKILL); - return quit(c); - } - jobid = pipeid; - } else if (!c->r && (c->current.builtin = getbuiltin(c->current.name))) { - status = c->current.builtin(c->tokens, c->numtokens); - cpid = 0; - } else if ((jobid = cpid = fork()) == -1) { - note("Unable to fork child process"); - return quit(c); - } else if (cpid == 0) { - redirectfiles(c->redirects); - execute(c); - } - - if (cpid) { - if (setpgid(cpid, jobid) == -1) { - if (errno != ESRCH) { - note("Unable to set pgid of `%s' command to %d", c->current.name, jobid); - if (kill(cpid, SIGKILL) == -1) - note("Unable to kill process %d; may need to manually terminate", cpid); - } - return quit(c); - } - if (ispipestart || c->current.term == BG) { - pushbgid(jobid); - return 1; - } - if (c->current.term != PIPE && !runfg(jobid)) return quit(c); - } - if (status != EXIT_SUCCESS) { - if (!islist) return quit(c); - if (c->current.term == AND) return clear(c); - } else if (c->current.term == OR) return clear(c); - } else { + if (!c->t) { if (islist) { if (c->previous.term == PIPE) { killpg(pipeid, SIGKILL); @@ -186,13 +113,93 @@ int run(struct context *c) { if ((cpid = fork()) == -1) { note("Unable to fork child process"); return quit(c); - } else if (cpid == 0) { + } + if (!cpid) { redirectfiles(c->redirects); exit(EXIT_SUCCESS); } waitpid(cpid, NULL, 0); errno = 0; + + return 1; + } + + if (c->current.term == BG && bgfull()) { + note("Unable to place job in background; too many background jobs"); + return quit(c); + } + if (!(c->current.builtin = getbuiltin(c->current.name)) + && !(c->current.path = getpath(c->current.name))) { + note("Couldn't find `%s' command", c->current.name); + if (c->previous.term == PIPE) killpg(pipeid, SIGKILL); + return quit(c); } + ispipe = c->previous.term == PIPE || c->current.term == PIPE; + ispipestart = ispipe && c->previous.term != PIPE; + ispipeend = ispipe && c->current.term != PIPE; + + if (ispipe) { + if (!ispipeend && pipe(c->current.pipe) == -1) { + note("Unable to create pipe"); + if (!ispipestart) closepipe(c->previous); + return quit(c); + } + if ((cpid = fork()) == -1) { + note("Unable to fork child process"); + return quit(c); + } + if (!cpid) { + if (!ispipestart) { + if (dup2(c->previous.pipe[0], 0) == -1) + fatal("Unable to duplicate read end of `%s' pipe", c->previous.name); + if (!closepipe(c->previous)) exit(EXIT_FAILURE); + } + if (!ispipeend) { + if (dup2(c->current.pipe[1], 1) == -1) + fatal("Unable to duplicate write end of `%s' pipe", c->current.name); + if (!closepipe(c->current)) exit(EXIT_FAILURE); + } + redirectfiles(c->redirects); + execute(c); + } + if (ispipestart) pipeid = cpid; + else if (!closepipe(c->previous)) { + killpg(pipeid, SIGKILL); + return quit(c); + } + jobid = pipeid; + } else if (!c->r && (c->current.builtin = getbuiltin(c->current.name))) { + status = c->current.builtin(c->tokens, c->numtokens); + cpid = 0; + } else if ((jobid = cpid = fork()) == -1) { + note("Unable to fork child process"); + return quit(c); + } else if (!cpid) { + redirectfiles(c->redirects); + execute(c); + } + + if (cpid) { + if (setpgid(cpid, jobid) == -1) { + if (errno != ESRCH) { + note("Unable to set pgid of `%s' command to %d", c->current.name, jobid); + if (kill(cpid, SIGKILL) == -1) + note("Unable to kill process %d; may need to manually terminate", cpid); + } + return quit(c); + } + if (ispipestart || c->current.term == BG) { + pushbgid(jobid); + return 1; + } + if (c->current.term != PIPE && !runfg(jobid)) return quit(c); + } + + if (status != EXIT_SUCCESS) { + if (!islist) return quit(c); + if (c->current.term == AND) return clear(c); + } else if (c->current.term == OR) return clear(c); + return 1; } diff --git a/src/signals.c b/src/signals.c index c1e2b76..4d65872 100644 --- a/src/signals.c +++ b/src/signals.c @@ -39,6 +39,12 @@ void initsignals(void) { sigaddset(&shellsigmask, SIGTSTP); sigaddset(&shellsigmask, SIGTTIN); sigaddset(&shellsigmask, SIGTTOU); + if (sigprocmask(SIG_BLOCK, &shellsigmask, &childsigmask) == -1) exit(errno); + + defaultaction = (struct sigaction){.sa_handler = SIG_DFL}; + setsig(SIGTSTP, &defaultaction); + setsig(SIGTTOU, &defaultaction); + setsig(SIGTTIN, &defaultaction); action = (struct sigaction){.sa_handler = sigwinchhandler}; setsig(SIGWINCH, &action); @@ -50,11 +56,4 @@ void initsignals(void) { action = (struct sigaction){.sa_handler = siginthandler}; setsig(SIGINT, &action); - - defaultaction = (struct sigaction){.sa_handler = SIG_DFL}; - setsig(SIGTSTP, &defaultaction); - setsig(SIGTTOU, &defaultaction); - setsig(SIGTTIN, &defaultaction); - - if (sigprocmask(SIG_BLOCK, &shellsigmask, &childsigmask) == -1) exit(errno); } diff --git a/src/utils.c b/src/utils.c index cc3dc8e..f7de714 100644 --- a/src/utils.c +++ b/src/utils.c @@ -22,16 +22,13 @@ void note(char *fmt, ...) { va_list args; fprintf(stderr, "%s: ", argvector[0]); - va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); - if (errno) { fprintf(stderr, ": %s", strerror(errno)); errno = 0; } - putchar('\n'); } @@ -39,13 +36,10 @@ void fatal(char *fmt, ...) { va_list args; fprintf(stderr, "%s: ", argvector[0]); - va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); - if (errno) fprintf(stderr, ": %s", strerror(errno)); - putchar('\n'); exit(errno); @@ -144,7 +138,7 @@ char *quoted(char *token) { if (degree < SINGLE) degree = SINGLE; break; case '\'': - degree |= DOUBLE; + if (degree == NONE || degree == SINGLE) ++degree; } if (degree == NONE) return token; @@ -153,7 +147,7 @@ char *quoted(char *token) { *p++ = quote; strcpy(p, token); for (q = p; *q; ++q); - if (degree & DOUBLE) for (; *p; ++p) switch (*p) + if (degree != SINGLE) for (; *p; ++p) switch (*p) case '$': case '~': case '"': @@ -162,8 +156,8 @@ char *quoted(char *token) { memmove(p + 1, p, ++q - p); *p++ = '\\'; } - *p++ = quote; - *p++ = '\0'; + *q++ = quote; + *q++ = '\0'; return buffer; }