]> Trent Huber's Code - thus.git/commitdiff
History, jobs, and aliases use their own data structures
authorTrent Huber <trentmhuber@gmail.com>
Mon, 11 Aug 2025 03:07:40 +0000 (23:07 -0400)
committerTrent Huber <trentmhuber@gmail.com>
Mon, 11 Aug 2025 03:07:40 +0000 (23:07 -0400)
29 files changed:
src/build.c
src/builtin/alias.c
src/builtin/alias.h
src/builtin/bg.c
src/builtin/builtin.c
src/builtin/builtin.h
src/builtin/cd.c
src/builtin/fg.c
src/builtin/fg.h
src/builtin/source.c
src/builtin/which.c
src/context.h [moved from src/shell.h with 97% similarity]
src/history.c
src/history.h
src/input.c
src/input.h
src/job.c
src/job.h
src/main.c
src/options.c
src/options.h
src/parse.c
src/parse.h
src/run.c
src/run.h
src/stack.c [deleted file]
src/stack.h [deleted file]
src/utils.c
src/utils.h

index 8f2965fa72ea500d0bd8cb3256b79f94d4334849..2f0999e8c85f82ab1672aae60fbd53ecd4e232ab 100644 (file)
@@ -17,8 +17,7 @@ int main(void) {
                                   {"options", NONE},
                                   {"parse", NONE},
                                   {"run", BUILTINS},
-                                  {"stack", NONE},
-                                  {"utils", NONE},
+                                  {"utils", BUILTINS},
 
                                   {"builtin.a"},
 
index 716be35b742ffb61b88f7546c623cb2cdad08b90..22d57234f043ba6242fd068cb2a088848546d3e9 100644 (file)
@@ -1,31 +1,30 @@
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 
 #include "builtin.h"
-#include "utils.h"
-#include "stack.h"
 #include "input.h"
-#include "shell.h"
+#include "context.h"
 #include "parse.h"
+#include "utils.h"
 
 #define MAXALIAS 25
-#define ALIAS ((struct alias *)aliases.c)
 
-struct alias {
-   char lhs[MAXCHARS - 5], *rhs;
-   struct shell shell;
-};
+static struct {
+   struct {
+       char lhs[MAXCHARS - 5], *rhs;
+       struct context context;
+   } entries[MAXALIAS + 1];
+   size_t size;
+} aliases;
 
-static struct alias aliasarr[MAXALIAS + 1];
-static INITSTACK(aliases, aliasarr, 0);
-
-void applyaliases(struct shell *shell) {
-   struct cmd *cmd, *p;
+void applyaliases(struct cmd *cmd) {
+   struct cmd *p;
    char **end;
-   size_t l, a;
+   size_t i, l, a;
+   struct context *context;
 
-   p = cmd = shell->cmds;
+   p = cmd;
 
    end = p->args;
    while ((p = p->next)) if (p->args) end = p->args;
@@ -33,44 +32,53 @@ void applyaliases(struct shell *shell) {
 
    while ((p = cmd = cmd->next)) {
        if (!cmd->args) continue;
-       for (aliases.c = aliases.b; aliases.c != aliases.t; INC(aliases, c))
-           if (strcmp(ALIAS->lhs, *cmd->args) == 0) break;
-       if (aliases.c == aliases.t) continue;
+       for (i = 0; i < aliases.size; ++i)
+           if (strcmp(aliases.entries[i].lhs, *cmd->args) == 0) break;
+       if (i == aliases.size) continue;
+       context = &aliases.entries[i].context;
 
-       strcpy(ALIAS->shell.buffer, ALIAS->rhs);
-       l = strlen(ALIAS->shell.buffer);
-       ALIAS->shell.buffer[l + 1] = '\0';
-       ALIAS->shell.buffer[l] = ';';
+       strcpy(context->buffer, aliases.entries[i].rhs);
+       l = strlen(context->buffer);
+       context->buffer[l + 1] = '\0';
+       context->buffer[l] = ';';
 
-       parse(&ALIAS->shell);
+       parse(context);
 
-       for (a = 0; ALIAS->shell.tokens[a]; ++a);
+       for (a = 0; context->tokens[a]; ++a);
        memmove(cmd->args + a, cmd->args + 1, (end - cmd->args + 1) * sizeof*cmd->args);
-       memcpy(cmd->args, ALIAS->shell.tokens, a * sizeof*cmd->args);
+       memcpy(cmd->args, context->tokens, a * sizeof*cmd->args);
        while ((p = p->next)) p->args += a - 1;
    }
 }
 
 BUILTINSIG(alias) {
+   size_t i;
+   char *lhs;
+
    switch (argc) {
    case 1:
-       for (aliases.c = aliases.b; aliases.c != aliases.t; INC(aliases, c))
-           printf("%s = \"%s\"\r\n", ALIAS->lhs, ALIAS->rhs);
+       for (i = 0; i < aliases.size; ++i)
+           printf("%s = \"%s\"\r\n", aliases.entries[i].lhs, aliases.entries[i].rhs);
        break;
    case 3:
+       if (aliases.size == MAXALIAS) {
+           note("Unable to add alias `%s', maximum reached (%d)", argv[1], MAXALIAS);
+           return EXIT_FAILURE;
+       }
        if (!*argv[2]) {
            note("Cannot add empty alias");
            return EXIT_FAILURE;
        }
-       for (aliases.c = aliases.b; aliases.c != aliases.t; INC(aliases, c))
-           if (strcmp(ALIAS->lhs, argv[1]) == 0) break;
-       if (PLUSONE(aliases, c) == aliases.b) {
-           note("Unable to add alias `%s', maximum reached (%d)", argv[1], MAXALIAS);
-           return EXIT_FAILURE;
+       for (i = 0; i < aliases.size; ++i)
+           if (strcmp(aliases.entries[i].lhs, argv[1]) == 0) break;
+
+       lhs = aliases.entries[i].lhs;
+       if (i == aliases.size) {
+           strcpy(lhs, argv[1]);
+           ++aliases.size;
        }
-       strcpy(ALIAS->lhs, argv[1]);
-       strcpy(ALIAS->rhs = ALIAS->lhs + strlen(ALIAS->lhs) + 1, argv[2]);
-       if (aliases.c == aliases.t) INC(aliases, t);
+       strcpy(aliases.entries[i].rhs = lhs + strlen(lhs) + 1, argv[2]);
+
        break;
    default:
        puts("Usage: alias [lhs rhs]\r");
index 540e9352c9b6bad08ddf6e3d7f060c01bc252ddb..02b4643ae553e990b60996828f205be7d4d4b1ad 100644 (file)
@@ -1 +1 @@
-void applyaliases(struct shell *shell);
+void applyaliases(struct cmd *cmd);
index 8e90c581f933f6766fa7e0c33884d5d90620b517..09c483c24e8f94424b698bad90817973a1491286 100644 (file)
@@ -6,44 +6,34 @@
 
 #include "builtin.h"
 #include "job.h"
-#include "stack.h"
 #include "utils.h"
 
 BUILTINSIG(bg) {
-   long jobid;
+   long l;
+   pid_t id;
    struct job *job;
 
-   if (sigaction(SIGCHLD, &sigdfl, NULL) == -1) {
-       note("Unable to acquire lock on the job stack");
-       return EXIT_FAILURE;
-   }
-
-   if (argv[1]) {
+   if (argc > 1) {
        errno = 0;
-       if ((jobid = strtol(argv[1], NULL, 10)) == LONG_MAX && errno
-           || jobid <= 0) {
-           note("Invalid job id");
+       if ((l = strtol(argv[1], NULL, 10)) == LONG_MAX && errno || l <= 0) {
+           note("Invalid job id %ld", l);
            return EXIT_FAILURE;
        }
-       if (!(job = findjob((pid_t)jobid))) {
-           note("Unable to find job %d", (pid_t)jobid);
+       if (!(job = searchjobid(id = (pid_t)l))) {
+           note("Unable to find job %d", id);
            return EXIT_FAILURE;
        }
        if (job->type == BACKGROUND) {
-           note("Job %d already in background", (pid_t)jobid);
-           return EXIT_FAILURE;
-       }
-   } else {
-       for (jobs.c = MINUSONE(jobs, t); jobs.c != MINUSONE(jobs, b); DEC(jobs, c))
-           if (JOB->type == SUSPENDED) break;
-       if (jobs.c == MINUSONE(jobs, b)) {
-           note("No suspended jobs to run in background");
+           note("Job %d already in background", id);
            return EXIT_FAILURE;
        }
+   } else if (!(job = searchjobtype(SUSPENDED))) {
+       note("No suspended jobs to run in background");
+       return EXIT_FAILURE;
    }
-   job = deletejob();
+   deletejobid(job->id);
 
-   if (!(push(&jobs, job))) {
+   if (!pushjob(job)) {
        note("Unable to add job to background; too many jobs");
        return EXIT_FAILURE;
    }
@@ -53,10 +43,5 @@ BUILTINSIG(bg) {
    }
    job->type = BACKGROUND;
 
-   if (sigaction(SIGCHLD, &sigchld, NULL) == -1) {
-       note("Unable to install SIGCHLD handler");
-       return EXIT_FAILURE;
-   }
-
    return EXIT_SUCCESS;
 }
index 03731af0219a42c3fd91ff21042b39c1a9eb2b3d..08904e023c272e883553b409a9c6be186ddb8391 100644 (file)
@@ -2,15 +2,16 @@
 
 #include "builtin.h"
 #include "list.h"
+#include "utils.h"
 
-int isbuiltin(char **args, int *statusp) {
+int isbuiltin(char **args) {
    struct builtin *builtinp;
    size_t n;
 
    for (builtinp = builtins; builtinp->func; ++builtinp)
        if (strcmp(*args, builtinp->name) == 0) {
            for (n = 0; args[n]; ++n);
-           *statusp = builtinp->func(n, args);
+           status = builtinp->func(n, args);
            return 1;
        }
    return 0;
index cc96b3a1c56f78c5671ee448720cbc31f967ebdb..07fc3872907df5be87ade1304115b16ce151f8db 100644 (file)
@@ -1,3 +1,3 @@
 #define BUILTINSIG(name) int name(int argc, char **argv)
 
-int isbuiltin(char **args, int *statusp);
+int isbuiltin(char **args);
index 4eb01feff5a77f86741107adcd6b37ef0fbe6a99..0986e25464aef984b0015550dce3f77652c39eb9 100644 (file)
@@ -1,7 +1,5 @@
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
-#include <limits.h>
 
 #include "builtin.h"
 #include "utils.h"
index 6a4958c3a6a9fe365e5c9916128b14270434ed07..c471f46691c88f23b44545f796320ccf8f783179 100644 (file)
@@ -1,3 +1,4 @@
+#include <err.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdio.h>
@@ -8,9 +9,47 @@
 
 #include "builtin.h"
 #include "job.h"
-#include "stack.h"
 #include "utils.h"
 
+static int fgstatus;
+struct sigaction sigchld, sigdfl;
+struct termios raw, canonical;
+
+static int setconfig(struct termios *mode) {
+   if (tcsetattr(STDIN_FILENO, TCSANOW, mode) == -1) {
+       note("Unable to set termios config");
+       return 0;
+   }
+   return 1;
+}
+
+static void sigchldhandler(int sig) {
+   pid_t id;
+   struct job *job;
+
+   (void)sig;
+   while ((id = waitpid(-1, &fgstatus, WNOHANG | WUNTRACED)) > 0)
+       if ((job = searchjobid(id))) {
+           if (WIFSTOPPED(fgstatus)) job->type = SUSPENDED; else deletejobid(id);
+       } else if (!WIFSTOPPED(fgstatus)) while (waitpid(-id, NULL, 0) != -1);
+}
+
+void setsigchld(struct sigaction *act) {
+   if (sigaction(SIGCHLD, act, NULL) == -1)
+       fatal("Unable to install SIGCHLD handler");
+}
+
+void initterm(void) {
+   if (tcgetattr(STDIN_FILENO, &canonical) == -1)
+       err(EXIT_FAILURE, "Unable to get default termios config");
+   cfmakeraw(&raw);
+   if (!setconfig(&raw)) exit(EXIT_FAILURE);
+
+   sigchld.sa_handler = sigchldhandler;
+   sigdfl.sa_handler = SIG_DFL;
+   setsigchld(&sigchld);
+}
+
 int setfg(struct job job) {
    if (!setconfig(&job.config)) return 0;
    if (tcsetpgrp(STDIN_FILENO, job.id) == -1) {
@@ -25,11 +64,18 @@ int setfg(struct job job) {
    return 1;
 }
 
-int waitfg(struct job job) {
+void waitfg(struct job job) {
+   struct sigaction sigign;
+
+   /* SIGCHLD handler is really the function that reaps the foreground process,
+    * the waitpid() below is just to block the current thread of execution until
+    * the foreground process has been reaped */
+   setsigchld(&sigchld);
    while (waitpid(job.id, NULL, 0) != -1);
    errno = 0;
+   setsigchld(&sigdfl);
 
-   if (sigaction(SIGTTOU, &sigign, NULL) == -1
+   if (sigaction(SIGTTOU, &(struct sigaction){{SIG_IGN}}, NULL) == -1
        || tcsetpgrp(STDIN_FILENO, getpgrp()) == -1
        || sigaction(SIGTTOU, &sigdfl, NULL) == -1) {
        note("Unable to reclaim foreground; terminating");
@@ -40,52 +86,45 @@ int waitfg(struct job job) {
        note("Unable to save termios config of job %d", job.id);
    setconfig(&raw);
 
-   if (WIFEXITED(fgstatus)) return WEXITSTATUS(fgstatus);
-   else if (WIFSIGNALED(fgstatus)) return WTERMSIG(fgstatus);
-   job.type = SUSPENDED;
-   if (!push(&jobs, &job)) {
-       note("Unable to add job %d to list; too many jobs\r\n"
-            "Press any key to continue", job.id);
-       getchar();
-       if (setfg(job)) return waitfg(job);
-       note("Manual intervention required for job %d", job.id);
+   if (WIFEXITED(fgstatus)) status = WEXITSTATUS(fgstatus);
+   else if (WIFSIGNALED(fgstatus)) status = WTERMSIG(fgstatus);
+   else {
+       status = WSTOPSIG(fgstatus);
+       job.type = SUSPENDED;
+       if (!pushjob(&job)) {
+           note("Unable to add job %d to list; too many jobs\r\n"
+                "Press any key to continue", job.id);
+           getchar();
+           if (setfg(job)) return waitfg(job);
+           note("Manual intervention required for job %d", job.id);
+       }
    }
-   return WSTOPSIG(fgstatus);
+}
+
+void deinitterm(void) {
+   setconfig(&canonical);
 }
 
 BUILTINSIG(fg) {
-   long jobid;
+   long l;
+   pid_t id;
    struct job *job;
 
-   if (sigaction(SIGCHLD, &sigdfl, NULL) == -1) {
-       note("Unable to acquire lock on the job stack");
-       return EXIT_FAILURE;
-   }
-
-   if (argv[1]) {
+   if (argc > 1) {
        errno = 0;
-       if ((jobid = strtol(argv[1], NULL, 10)) == LONG_MAX && errno
-           || jobid <= 0) {
-           note("Invalid process group id");
+       if ((l = strtol(argv[1], NULL, 10)) == LONG_MAX && errno || l <= 0) {
+           note("Invalid process group id %ld", l);
            return EXIT_FAILURE;
        }
-       if (!(job = findjob((pid_t)jobid))) {
-           note("Unable to find process group %d", (pid_t)jobid);
+       if (!(job = searchjobid(id))) {
+           note("Unable to find process group %d", id);
            return EXIT_FAILURE;
        }
-       job = deletejob();
-   } else if (!(job = pull(&jobs))) {
+       deletejobid(id);
+   } else if (!(job = pulljob())) {
        note("No processes to bring into the foreground");
        return EXIT_FAILURE;
    }
 
-   if (sigaction(SIGCHLD, &sigchld, NULL) == -1) {
-       note("Unable to reinstall SIGCHLD handler");
-       return EXIT_FAILURE;
-   }
-
-   if (!setfg(*job)) return EXIT_FAILURE;
-   waitfg(*job);
-
-   return EXIT_SUCCESS;
+   return setfg(*job) ? (waitfg(*job), EXIT_SUCCESS) : EXIT_FAILURE;
 }
index 00b6eaafee26af8c8f3c37941cbda3fed705286b..da4eff73217739bdf58d278f5ad9cd4a8054fcdd 100644 (file)
@@ -1,2 +1,8 @@
+extern struct sigaction sigchld, sigdfl;
+extern struct termios raw, canonical;
+
+void setsigchld(struct sigaction *act);
+void initterm(void);
 int setfg(struct job job);
-int waitfg(struct job job);
+void waitfg(struct job job);
+void deinitterm(void);
index de2f166ed33e96aa463a53b1d6dc1e95175f706c..90f15cc03407d2f02ea8239958298f81f03f9fe4 100644 (file)
@@ -1,23 +1,27 @@
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <limits.h>
 
+#include "builtin.h"
 #include "input.h"
-#include "shell.h"
+#include "context.h"
 #include "parse.h"
 #include "run.h"
 #include "utils.h"
-#include "builtin.h"
 
 BUILTINSIG(source) {
-   struct shell shell;
+   struct context context;
 
-   shell.script = argv[1];
-   shell.input = scriptinput;
+   if (argc != 2) {
+       note("Usage: source file");
+       return EXIT_FAILURE;
+   }
 
-   while (run(parse(shell.input(&shell))));
+   context.script = argv[1];
+   context.input = scriptinput;
+   while (run(parse(context.input(&context))));
 
-   return EXIT_SUCCESS; // TODO: Handle exit status
+   return EXIT_SUCCESS;
 }
 
 void config(char *name) {
index 85d442725ee1d6e0aff32ae3059cd0fadc8e9cb0..4d8c58ad3d978f95c8fcd9436c05e20ece89dd1a 100644 (file)
@@ -1,9 +1,9 @@
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/errno.h>
 #include <sys/stat.h>
-#include <limits.h>
 
 #include "builtin.h"
 #include "list.h"
similarity index 97%
rename from src/shell.h
rename to src/context.h
index a153acdcb35e5b128414d13a32d33a1976f1e0ad..87e9d64c424dbefe63ce608acb904d9062dd2215 100644 (file)
@@ -32,7 +32,7 @@ struct cmd {
    struct cmd *prev, *next;
 };
 
-struct shell {
+struct context {
    char buffer[MAXCHARS + 1 + 1], *tokens[MAXCMDS + 1], *script, *string;
    struct {
        char *m;
index ecba616085794fb48d82494dfbecb626e70aca34..093c95c38a6017455c56923898a5c934f94d5848 100644 (file)
@@ -1,56 +1,66 @@
-#include <stdlib.h>
-#include <stdint.h>
+#include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <limits.h>
 #include <sys/errno.h>
 
 #include "input.h"
-#include "shell.h"
-#include "stack.h"
+#include "context.h"
 #include "utils.h"
 
-#define HISTORYFILE ".ashhistory"
 #define MAXHIST 100
-#define BUFFER ((char *)history.t)
-
-static char historyarr[MAXHIST + 1][MAXCHARS + 1], filepath[PATH_MAX];
-INITSTACK(history, historyarr, 1);
+#define INC(v) (history.v = (history.v + 1) % (MAXHIST + 1))
+#define DEC(v) (history.v = (history.v + MAXHIST) % (MAXHIST + 1))
 
-/* TODO
-   void addhistory(char *buffer);
-   int prevhistory(char *buffer);
-   int nexthistory(char *buffer);
-*/
+static struct {
+   char path[PATH_MAX], entries[MAXHIST + 1][MAXCHARS + 1];
+   size_t b, c, t;
+} history;
 
 void readhistory(void) {
-   char *p;
    FILE *file;
    
-   if (!catpath(home, HISTORYFILE, filepath)) exit(EXIT_FAILURE);
-   if (!(file = fopen(filepath, "r"))) {
+   if (!catpath(home, ".ashhistory", history.path)) exit(EXIT_FAILURE);
+   if (!(file = fopen(history.path, "r"))) {
        if (errno == ENOENT) return;
        fatal("Unable to open history file for reading");
    }
-   while (fgets(BUFFER, history.size, file)) {
-       *(BUFFER + strlen(BUFFER) - 1) = '\0';
-       push(&history, BUFFER);
+   while (fgets(history.entries[history.t], sizeof*history.entries, file)) {
+       history.entries[history.t][strlen(history.entries[history.t]) - 1] = '\0';
+       if ((history.c = INC(t)) == history.b) INC(b);
    }
    if (ferror(file) || !feof(file))
        fatal("Unable to read from history file");
    if (fclose(file) == EOF) fatal("Unable to close history file");
 }
 
+int gethistory(char direction, char *buffer) {
+   if (history.c == (direction == UP ? history.b : history.t)) return 0;
+
+   // Save the most recently modified history entry at the top of the list
+   if (strcmp(history.entries[history.c], buffer) != 0)
+       strcpy(history.entries[history.t], buffer);
+
+   strcpy(buffer, history.entries[direction == UP ? DEC(c) : INC(c)]);
+
+   return 1;
+}
+
+void sethistory(char *buffer) {
+   strcpy(history.entries[history.t], buffer);
+   if ((history.c = INC(t)) == history.b) INC(b);
+   *history.entries[history.t] = '\0';
+}
+
 void writehistory(void) {
-   char *filename;
    FILE *file;
 
-   if (!(file = fopen(filepath, "w"))) {
+   if (!(file = fopen(history.path, "w"))) {
        note("Unable to open history file for writing");
        return;
    }
-   for (history.c = history.b; history.c != history.t; INC(history, c)) {
-       if (fputs((char *)history.c, file) == EOF) {
+   for (history.c = history.b; history.c != history.t; INC(c)) {
+       if (fputs(history.entries[history.c], file) == EOF) {
            note("Unable to write to history file");
            break;
        }
index 22d30e6670579edc67ca2ada903330d1c27ca788..60b4bac9eff0d1ad4a04921c5c461d089d154fad 100644 (file)
@@ -1,5 +1,4 @@
-extern struct stack history;
-
 void readhistory(void);
+int gethistory(char direction, char *buffer);
+void sethistory(char *buffer);
 void writehistory(void);
-
index 78082205355ace2ce0eb189507a42d7e2032d6e4..559053f3a0481d75d7354fec75d9c0e9160b2c81 100644 (file)
@@ -7,89 +7,61 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "input.h"
-#include "shell.h"
 #include "history.h"
-#include "stack.h"
+#include "input.h"
+#include "context.h"
 #include "utils.h"
 
 #define DEFAULTPROMPT ">"
 
-enum {
-   CTRLC = '\003',
-   CTRLD,
-   BACKSPACE = '\010',
-   CLEAR = '\014',
-   ESCAPE = '\033',
-   FORWARD = 'f',
-   BACKWARD = 'b',
-   ARROW = '[',
-   UP = 'A',
-   DOWN,
-   RIGHT,
-   LEFT,
-   DEL = '\177',
-};
-
 INPUT(stringinput) {
    char *start;
    size_t l;
 
-   if (!*shell->string) {
-       if (shell->script && munmap(shell->map.m, shell->map.l) == -1)
-           note("Unable to unmap memory associated with `%s'", shell->script);
+   if (!*context->string) {
+       if (context->script && munmap(context->map.m, context->map.l) == -1)
+           note("Unable to unmap memory associated with `%s'", context->script);
+       return NULL;
+   }
+   start = context->string;
+   while (*context->string && *context->string != '\n') ++context->string;
+   l = context->string - start;
+   if (*context->string == '\n') ++context->string;
+   if (l > MAXCHARS) {
+       note("Line too long, exceeds %d character limit", MAXCHARS);
        return NULL;
    }
-   start = shell->string;
-   while (*shell->string && *shell->string != '\n') ++shell->string;
-   l = shell->string - start;
-   if (*shell->string == '\n') ++shell->string;
-// puts("test\r\n");
-   if (l > MAXCHARS) fatal("Line too long, exceeds %d character limit", MAXCHARS);
-   strncpy(shell->buffer, start, l);
-   shell->buffer[l] = ';';
-   shell->buffer[l + 1] = '\0';
-
-   return shell;
+   strncpy(context->buffer, start, l);
+   context->buffer[l] = ';';
+   context->buffer[l + 1] = '\0';
+
+   return context;
 }
 
 INPUT(scriptinput) {
    int fd;
    struct stat sstat;
 
-   if ((fd = open(shell->script, O_RDONLY)) == -1)
-       fatal("Unable to open `%s'", shell->script);
-   if (stat(shell->script, &sstat) == -1)
-       fatal("Unable to stat `%s'", shell->script);
-   if ((shell->map.l = sstat.st_size) == 0) return NULL;
-   if ((shell->string = shell->map.m = mmap(NULL, shell->map.l, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
-       fatal("Unable to memory map `%s'", shell->script);
-   if (close(fd) == -1) fatal("Unable to close `%s'", shell->script);
-   shell->input = stringinput;
-
-   return shell->input(shell);
-}
-
-static struct shell *config(char *name) {
-   int fd;
-   struct shell *result;
-   static struct shell shell;
-   static char path[PATH_MAX];
-
-   if (!shell.script) {
-       shell.script = catpath(home, name, path);
-       shell.input = scriptinput;
-
-       if ((fd = open(shell.script, O_RDONLY | O_CREAT, 0644)) == -1)
-           fatal("Unable to open `%s'", shell.script);
-       if (close(fd) == -1)
-           fatal("Unable to close `%s'", shell.script);
+   if ((fd = open(context->script, O_RDONLY)) == -1) {
+       note("Unable to open `%s'", context->script);
+       return NULL;
    }
+   if (stat(context->script, &sstat) == -1) {
+       note("Unable to stat `%s'", context->script);
+       return NULL;
+   }
+   if ((context->map.l = sstat.st_size) == 0) return NULL;
+   if ((context->string = context->map.m = mmap(NULL, context->map.l, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+       note("Unable to memory map `%s'", context->script);
+       return NULL;
+   }
+   if (close(fd) == -1) {
+       note("Unable to close `%s'", context->script);
+       return NULL;
+   }
+   context->input = stringinput;
 
-   result = shell.input(&shell);
-   if (result) return result;
-   shell.script = NULL;
-   return NULL;
+   return context->input(context);
 }
 
 static size_t prompt(void) {
@@ -103,15 +75,14 @@ static size_t prompt(void) {
 
 INPUT(userinput) {
    char *start, *cursor, *end;
-   size_t promptlen;
    unsigned int c;
    int i;
+   size_t oldlen, newlen;
 
-   end = cursor = start = shell->buffer;
-   *history.t = *start = '\0';
-   history.c = history.t;
+   end = cursor = start = context->buffer;
+   *start = '\0';
    while (start == end) {
-       promptlen = prompt();
+       prompt();
        while ((c = getchar()) != '\r') switch (c) {
        default:
            if (c >= ' ' && c <= '~') {
@@ -128,7 +99,7 @@ INPUT(userinput) {
        case CTRLC:
            puts("^C\r");
            *start = '\0';
-           return shell;
+           return context;
        case CTRLD:
            puts("^D\r");
            return NULL;
@@ -151,20 +122,16 @@ INPUT(userinput) {
                switch ((c = getchar())) {
                case UP:
                case DOWN:
-                   if (history.c == (c == UP ? history.b : history.t)) continue;
+                   oldlen = strlen(start);
+                   if (!gethistory(c, start)) continue;
+                   newlen = strlen(start);
+                   end = cursor = start + newlen;
 
                    putchar('\r');
-                   for (i = end - start + promptlen; i > 0; --i) putchar(' ');
-                   putchar('\r');
-
-                   if (strcmp((char *)history.c, start) != 0)
-                       strcpy((char *)history.t, start);
-                   if (c == UP) DEC(history, c); else INC(history, c);
-                   strcpy(start, (char *)history.c);
-                   end = cursor = start + strlen(start);
-
                    prompt();
                    fputs(start, stdout);
+                   for (i = oldlen - newlen; i > 0; --i) putchar(' ');
+                   for (i = oldlen - newlen; i > 0; --i) putchar('\b');
                    break;
                case LEFT:
                    if (cursor > start) putchar((--cursor, '\b'));
@@ -194,10 +161,10 @@ INPUT(userinput) {
        }
        puts("\r");
    }
-   push(&history, start);
+   sethistory(start);
 
    *end++ = ';';
    *end = '\0';
 
-   return shell;
+   return context;
 }
index 50dc132be6a75fb9fbae4bc41ce6fdf7873a78ad..0b6dc8ecf03623261db80dc1455fec5c9128b6d7 100644 (file)
@@ -1,8 +1,23 @@
-#define INPUT(name) struct shell *name(struct shell *shell)
+#define INPUT(name) struct context *name(struct context *context)
 
 typedef INPUT((*Input));
 
+enum {
+   CTRLC = '\003',
+   CTRLD,
+   BACKSPACE = '\010',
+   CLEAR = '\014',
+   ESCAPE = '\033',
+   FORWARD = 'f',
+   BACKWARD = 'b',
+   ARROW = '[',
+   UP = 'A',
+   DOWN,
+   RIGHT,
+   LEFT,
+   DEL = '\177',
+};
+
 INPUT(stringinput);
 INPUT(scriptinput);
-// struct shell *config(char *name);
 INPUT(userinput);
index 857dfe4d6f4f27d3a3b64668bd33f113a8599c53..3829255a36556e784c126454cb88d639628a5074 100644 (file)
--- a/src/job.c
+++ b/src/job.c
@@ -1,31 +1,83 @@
-#include <stdint.h>
 #include <string.h>
 #include <termios.h>
+// #include <stdio.h> // XXX
 
 #include "job.h"
-#include "stack.h"
+#include "utils.h"
 
 #define MAXJOBS 100
 
-static struct job jobarr[MAXJOBS + 1];
-INITSTACK(jobs, jobarr, 0);
-int fgstatus;
-
-/* TODO
-   addjob
-   popjob
-   findjob
-*/
-
-void *findjob(pid_t jobid) {
-   if (jobs.b == jobs.t) return NULL;
-   for (jobs.c = jobs.b; JOB->id != jobid; INC(jobs, c))
-       if (jobs.c == jobs.t) return NULL;
-   return jobs.c;
+struct joblink {
+   struct job job;
+   struct joblink *next;
+};
+
+static struct {
+   struct joblink entries[MAXJOBS + 1], *active, *free;
+} jobs;
+
+struct job *pushjob(struct job *job) {
+   struct joblink *p;
+
+   if (!jobs.free) return NULL;
+
+   (p = jobs.free)->job = *job;
+   jobs.free = p->next;
+   p->next = jobs.active;
+   jobs.active = p;
+
+   return &p->job;
+}
+
+struct job *peekjob(void) {
+   return jobs.active ? &jobs.active->job : NULL;
 }
 
-void *deletejob(void) {
-   memcpy(jobs.t, jobs.c, jobs.size);
-   memmove(jobs.c, PLUSONE(jobs, c), jobs.t - jobs.c);
-   return DEC(jobs, t);
+struct job *pulljob(void) {
+   struct joblink *p;
+
+   if (!jobs.active) return NULL;
+
+   p = jobs.active;
+   jobs.active = p->next;
+   p->next = jobs.free;
+   jobs.free = p;
+
+   return &p->job;
+}
+
+struct job *searchjobid(pid_t id) {
+   struct joblink *p;
+
+   for (p = jobs.active; p; p = p->next) if (p->job.id == id) return &p->job;
+
+   return NULL;
+}
+
+struct job *searchjobtype(enum jobtype type) {
+   struct joblink *p;
+
+   for (p = jobs.active; p; p = p->next) if (p->job.type == type) return &p->job;
+
+   return NULL;
+}
+
+struct job *deletejobid(pid_t id) {
+   struct joblink *p, *prev;
+   
+   for (prev = NULL, p = jobs.active; p; prev = p, p = p->next) if (p->job.id == id) break;
+   if (!p) return NULL;
+
+   if (prev) prev->next = p->next; else jobs.active = p->next;
+   p->next = jobs.free;
+   jobs.free = p;
+
+   return &p->job;
+}
+
+void initjobs(void) {
+   size_t i;
+
+   for (i = 0; i < MAXJOBS - 1; ++i) jobs.entries[i].next = &jobs.entries[i + 1];
+   jobs.free = jobs.entries;
 }
index 1a6f2887dc644241de1adc0950add3a258f82ca4..f0432866da0097caada62d9f750e44613e988f56 100644 (file)
--- a/src/job.h
+++ b/src/job.h
@@ -1,5 +1,3 @@
-#define JOB ((struct job *)jobs.c)
-
 enum jobtype {
    BACKGROUND,
    SUSPENDED,
@@ -11,8 +9,10 @@ struct job {
    enum jobtype type;
 };
 
-extern struct stack jobs;
-extern int fgstatus;
-
-void *findjob(pid_t jobid);
-void *deletejob(void);
+struct job *pushjob(struct job *job);
+struct job *peekjob(void);
+struct job *pulljob(void);
+struct job *searchjobid(pid_t id);
+struct job *searchjobtype(enum jobtype);
+struct job *deletejobid(pid_t id);
+void initjobs(void);
index 12b278ebb7f37523ce78a3352e0728d3c81e10c5..982704f3da8acddb5fd02e964084f2035f5a596e 100644 (file)
@@ -1,12 +1,12 @@
 #include <stdlib.h>
 
 #include "input.h"
-#include "shell.h"
+#include "context.h"
 #include "options.h"
 #include "parse.h"
 #include "run.h"
-#include "utils.h"
 #include "source.h"
+#include "utils.h"
 
 int main(int c, char **v) {
    argc = c;
@@ -19,7 +19,7 @@ int main(int c, char **v) {
    if (login) config(".ashlogin");
    if (interactive) config(".ashint");
 
-   while (run(parse(shell.input(&shell))));
+   while (run(parse(context.input(&context))));
 
    deinitialize();
 
index d54ca9bf7fdd89787a7fe7f09bd25510d995f2f6..eb0e6db10353270d8839f09df9cc6fdb3954c53c 100644 (file)
@@ -4,12 +4,12 @@
 #include <unistd.h>
 
 #include "input.h"
-#include "shell.h"
+#include "context.h"
 
 int login, interactive, argc;
 char **argv;
 
-struct shell shell;
+struct context context;
 
 static void usage(char *program, int code) {
    printf("Usage: %s [file] [-c string] [-hl]\n"
@@ -25,14 +25,14 @@ void options(void) {
 
    login = **argv == '-';
    interactive = 1;
-   shell.input = userinput;
+   context.input = userinput;
 
    while ((opt = getopt(argc, argv, ":c:hl")) != -1) {
        switch (opt) {
        case 'c':
            interactive = 0;
-           shell.string = optarg;
-           shell.input = stringinput;
+           context.string = optarg;
+           context.input = stringinput;
            break;
        case 'h':
            usage(*argv, EXIT_SUCCESS);
@@ -49,10 +49,10 @@ void options(void) {
        }
        if (opt == 'c') break;
    }
-   if (!shell.string && argv[optind]) {
+   if (!context.string && argv[optind]) {
        interactive = 0;
-       shell.script = argv[optind];
-       shell.input = scriptinput;
+       context.script = argv[optind];
+       context.input = scriptinput;
    }
    if (!interactive) {
        argc -= optind;
index 3186fadfb0bb3b2461e4c2bb3a682a7ba96e54b8..022538f6e958cbe38ea31df1bff2550a81385524 100644 (file)
@@ -1,5 +1,5 @@
 extern int login, interactive, argc;
 extern char **argv;
-extern struct shell shell;
+extern struct context context;
 
 void options(void);
index 37ad6ebaa4a21f30e417cf561642feb351386d37..10ac748b5bfe7cbbf66acb14cdb816ca5a011b37 100644 (file)
@@ -4,9 +4,8 @@
 #include <string.h>
 
 #include "input.h"
-#include "shell.h"
+#include "context.h"
 #include "options.h"
-#include "run.h"
 #include "utils.h"
 
 static void initcmd(struct cmd *cmd) {
@@ -17,17 +16,17 @@ static void initcmd(struct cmd *cmd) {
    cmd->next = NULL;
 }
 
-struct shell *parse(struct shell *shell) {
+struct context *parse(struct context *context) {
    char *b, **t, *name, *value, *stlend, *p, *end, *env;
    struct cmd *c;
    long l;
    int e, offset;
    
-   if (!shell) return NULL;
-   b = shell->buffer;
-   t = shell->tokens;
-   c = shell->cmds + 1;
-   shell->cmds->next = NULL;
+   if (!context) return NULL;
+   b = context->buffer;
+   t = context->tokens;
+   c = context->cmds + 1;
+   context->cmds->next = NULL;
    *t = value = name = NULL;
    for (initcmd(c); *b; ++b) switch (*b) {
    default:
@@ -41,14 +40,14 @@ struct shell *parse(struct shell *shell) {
    case '>':
        if (c->r->mode) {
            note("File redirections should be separated by spaces");
-           return shell;
+           return context;
        }
        c->r->newfd = *b == '>';
        if (*(b - 1)) {
            if (c->args == --t) c->args = NULL;
            if ((l = strtol(*t, &stlend, 10)) < 0 || l > INT_MAX || stlend != b) {
                note("Invalid value for a file redirection");
-               return shell;
+               return context;
            }
            c->r->newfd = l;
        }
@@ -70,7 +69,7 @@ struct shell *parse(struct shell *shell) {
        }
        if (!b) {
            note("Quote left open-ended");
-           return shell;
+           return context;
        }
        memmove(p, p + 1, end-- - p);
        --b;
@@ -109,21 +108,21 @@ struct shell *parse(struct shell *shell) {
        while (*b && *b != '$') ++b;
        if (!*b) {
            note("Environment variable lacks a terminating `$'");
-           return shell;
+           return context;
        }
        *b++ = '\0';
        for (end = b; *end; ++end);
 
        l = strtol(p + 1, &stlend, 10);
        if (stlend == b - 1) env = l >= 0 && l < argc ? argv[l] : b - 1;
-       else if (strcmp(p + 1, "?") == 0) {
+       else if (strcmp(p + 1, "^") == 0) {
            if (!sprintf(env = (char [12]){0}, "%d", status)) {
                note("Unable to get previous command status");
-               return shell;
+               return context;
            }
        } else if ((env = getenv(p + 1)) == NULL) {
            note("Environment variable does not exist");
-           return shell;
+           return context;
        }
 
        e = strlen(env);
@@ -159,7 +158,7 @@ struct shell *parse(struct shell *shell) {
                if ((l = strtol(++c->r->oldname, &stlend, 10)) < 0
                    || l > INT_MAX || *stlend) {
                    note("Incorrect syntax for file redirection");
-                   return shell;
+                   return context;
                }
                c->r->oldfd = l;
                c->r->oldname = NULL;
@@ -175,7 +174,7 @@ struct shell *parse(struct shell *shell) {
        if (value) {
            if (setenv(name, value, 1) == -1) {
                note("Unable to set environment variable");
-               return shell;
+               return context;
            }
            value = name = NULL;
        }
@@ -188,11 +187,11 @@ struct shell *parse(struct shell *shell) {
    case PIPE:
    case OR:
        note("Expected another command");
-       return shell;
+       return context;
    default:
        break;
    }
 
-   shell->cmds->next = shell->cmds + 1;
-   return shell;
+   context->cmds->next = context->cmds + 1;
+   return context;
 }
index 4053bf5ec90e82b3c9d53ad94fbed4b93c9ffb99..c76ce9fde323f254eb3f2f5e3dbd6a9df2abffd3 100644 (file)
@@ -1 +1 @@
-struct shell *parse(struct shell *shell);
+struct context *parse(struct context *context);
index f66e3edb7ed0b3db5f93e185f789829b1975a7ac..add19cc758f9a1345220d8cd2dea0abb5ff26c64 100644 (file)
--- a/src/run.c
+++ b/src/run.c
@@ -1,23 +1,20 @@
 #include <fcntl.h>
+#include <limits.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <sys/errno.h>
 #include <termios.h>
 #include <unistd.h>
-#include <limits.h>
-#include <stdio.h> // XXX
+// #include <stdio.h> // XXX
 
+#include "builtin.h"
 #include "input.h"
-#include "shell.h"
+#include "context.h"
 #include "alias.h"
-#include "builtin.h"
 #include "job.h"
 #include "fg.h"
-#include "stack.h"
 #include "utils.h"
 
-int status;
-
 static int closepipe(struct cmd *cmd) {
    int result;
 
@@ -61,23 +58,26 @@ static void redirectfiles(struct redirect *r) {
 static void exec(struct cmd *cmd) {
    char cwd[PATH_MAX];
 
+   redirectfiles(cmd->rds);
+   if (isbuiltin(cmd->args)) exit(status);
    execvp(*cmd->args, cmd->args);
    if (!getcwd(cwd, PATH_MAX)) fatal("Unable to check current working directory");
    execvP(*cmd->args, cwd, cmd->args);
    fatal("Couldn't find `%s' command", *cmd->args);
 }
 
-int run(struct shell *shell) {
+int run(struct context *context) {
    struct cmd *cmd;
    int ispipe, ispipestart, ispipeend;
    pid_t cpid, jobid;
    struct job job;
 
-   if (!shell) return 0;
+   if (!context) return 0;
 
-   applyaliases(shell);
+   applyaliases(cmd = context->cmds);
+
+   setsigchld(&sigdfl);
 
-   cmd = shell->cmds;
    while ((cmd = cmd->next)) {
        if (!cmd->args) {
            if (!cmd->r->mode) break;
@@ -115,24 +115,17 @@ int run(struct shell *shell) {
                        fatal("Unable to duplicate write end of `%s' pipe", *cmd->args);
                    if (!closepipe(cmd)) exit(EXIT_FAILURE);
                }
-
-               redirectfiles(cmd->rds);
-               if (isbuiltin(cmd->args, &status)) exit(status);
                exec(cmd);
            }
            if (!ispipestart) {
                closepipe(cmd->prev);
-               jobid = ((struct job *)(ispipeend ? pull : peek)(&jobs))->id;
+               jobid = (ispipeend ? pulljob : peekjob)()->id;
            }
-       } else if (!cmd->rds->mode && isbuiltin(cmd->args, &status)) cpid = 0;
+       } else if (!cmd->rds->mode && isbuiltin(cmd->args)) cpid = 0;
        else if ((jobid = cpid = fork()) == -1) {
            note("Unable to create child process");
            break;
-       } else if (cpid == 0) {
-           redirectfiles(cmd->rds);
-           if (isbuiltin(cmd->args, &status)) exit(status);
-           exec(cmd);
-       }
+       } else if (cpid == 0) exec(cmd);
 
        if (cpid) {
            if (setpgid(cpid, jobid) == -1) {
@@ -145,14 +138,14 @@ int run(struct shell *shell) {
            }
            job = (struct job){.id = jobid, .config = canonical, .type = BACKGROUND};
            if (ispipestart || cmd->term == BG) {
-               if (!push(&jobs, &job)) {
+               if (!pushjob(&job)) {
                    note("Unable to add job to background; too many background jobs");
                    if (ispipestart) closepipe(cmd);
                    break;
                }
            } else if (cmd->term != PIPE) {
                if (!setfg(job)) break;
-               status = waitfg(job);
+               waitfg(job);
            }
        }
 
@@ -160,5 +153,7 @@ int run(struct shell *shell) {
        if (cmd->term == OR && status == EXIT_SUCCESS) break;
    }
 
+   setsigchld(&sigchld);
+
    return 1;
 }
index cebcc90b7f63a66c19aefef3428a824cda5448d9..4f79635c29b61edeb7ebfeeed7edff94c3fa25c0 100644 (file)
--- a/src/run.h
+++ b/src/run.h
@@ -1,3 +1,3 @@
 extern int status;
 
-int run(struct shell *shell);
+int run(struct context *context);
diff --git a/src/stack.c b/src/stack.c
deleted file mode 100644 (file)
index a5df54e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <string.h>
-#include <stdint.h>
-
-#include "stack.h"
-
-int push(struct stack *s, void *d) {
-   if (PLUSONE(*s, t) == s->b) {
-       if (!s->overwrite) return 0;
-       INC(*s, b);
-   }
-   memmove(s->t, d, s->size);
-   INC(*s, t);
-   return 1;
-}
-
-void *peek(struct stack *s) {
-   if (s->t == s->b) return NULL;
-   return MINUSONE(*s, t);
-}
-
-void *pull(struct stack *s) {
-   if (s->t == s->b) return NULL;
-   return DEC(*s, t);
-}
diff --git a/src/stack.h b/src/stack.h
deleted file mode 100644 (file)
index e0dbe60..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#define PLUSONE(s, m) ((s).data + ((s).m - (s).data + (s).size) % (s).cap)
-#define MINUSONE(s, m) \
-   ((s).data + ((s).m - (s).data - (s).size + (s).size * (s).cap) % (s).cap)
-#define INC(s, m) ((s).m = PLUSONE(s, m))
-#define DEC(s, m) ((s).m = MINUSONE(s, m))
-
-#define INITSTACK(s, d, o) \
-   struct stack s = {sizeof*d, sizeof d, (uint8_t *)d, (uint8_t *)d, \
-                     (uint8_t *)d, (uint8_t *)d, o}
-
-struct stack {
-   size_t size, cap;
-   uint8_t *b, *c, *t, *data;
-   int overwrite;
-};
-
-int push(struct stack *s, void *d);
-void *peek(struct stack *s);
-void *pull(struct stack *s);
index 30e379935e268f1a3fc0cf2334b01d4660270dc1..dfcb36f19b476df8039c83608fd05c64ce4cd585 100644 (file)
@@ -1,6 +1,5 @@
 #include <err.h>
 #include <limits.h>
-#include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "history.h"
-#include "input.h"
 #include "job.h"
+#include "fg.h"
 #include "options.h"
-#include "stack.h"
 
-struct termios raw, canonical;
-struct sigaction sigchld, sigdfl, sigign;
 char *home;
+int status;
 
 void note(char *fmt, ...) {
    va_list args;
@@ -37,47 +34,11 @@ void fatal(char *fmt, ...) {
    exit(EXIT_FAILURE);
 }
 
-int setconfig(struct termios *mode) {
-   if (tcsetattr(STDIN_FILENO, TCSANOW, mode) == -1) {
-       note("Unable to set termios config");
-       return 0;
-   }
-   return 1;
-}
-
-static void sigchldhandler(int sig) {
-   int status;
-   pid_t id;
-
-   (void)sig;
-   while ((id = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
-       for (jobs.c = jobs.b; jobs.c != jobs.t; INC(jobs, c))
-           if (JOB->id == id) {
-               if (WIFSTOPPED(status)) JOB->type = SUSPENDED;
-               else deletejob();
-               break;
-           }
-       if (jobs.c == jobs.t) {
-           fgstatus = status;
-           if (!WIFSTOPPED(fgstatus)) while (waitpid(-id, NULL, 0) != -1);
-       }
-   }
-}
-
 void initialize(void) {
    char *shlvlstr, buffer[19 + 1];
    long shlvl;
 
-   if (tcgetattr(STDIN_FILENO, &canonical) == -1)
-       err(EXIT_FAILURE, "Unable to get default termios config");
-   cfmakeraw(&raw);
-   if (!setconfig(&raw)) exit(EXIT_FAILURE);
-
-   sigchld.sa_handler = sigchldhandler;
-   sigdfl.sa_handler = SIG_DFL;
-   sigign.sa_handler = SIG_IGN;
-   if (sigaction(SIGCHLD, &sigchld, NULL) == -1)
-       fatal("Unable to install SIGCHLD handler");
+   initterm();
 
    if (!(home = getenv("HOME")))
        fatal("Unable to locate user's home directory, $HOME$ not set");
@@ -89,6 +50,7 @@ void initialize(void) {
        note("Unable to update $SHLVL$ environment variable");
 
    if (interactive) readhistory();
+   initjobs();
 }
 
 char *catpath(char *dir, char *filename, char *buffer) {
@@ -108,7 +70,7 @@ char *catpath(char *dir, char *filename, char *buffer) {
 }
 
 void deinitialize(void) {
-   if (interactive) writehistory();
+   deinitterm();
 
-   setconfig(&canonical);
+   if (interactive) writehistory();
 }
index 1cbc15e3accefd58f14383a1f2eead90ebc93e7b..38848322665a57d7b0ac62d2bab87a3094bafc08 100644 (file)
@@ -1,10 +1,8 @@
-extern struct termios raw, canonical;
-extern struct sigaction sigchld, sigdfl, sigign;
 extern char *home;
+extern int status;
 
 void note(char *fmt, ...);
 void fatal(char *fmt, ...);
-int setconfig(struct termios *mode);
 void initialize(void);
 char *catpath(char *dir, char *filename, char *buffer);
 void deinitialize(void);