From f5df4b2e38b5fd146c685e507950a722672f6ecc Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Fri, 7 Apr 2017 12:33:41 -0400 Subject: [PATCH] removed print.c and switched some prints over to printf. and.......converted tabs to spaces --- Makefile | 2 +- builtins.c | 650 ++++++++++++++++++++++++------------------------- except.c | 172 ++++++------- exec.c | 216 ++++++++--------- fn.c | 338 +++++++++++++------------- footobar.c | 621 +++++++++++++++++++++++------------------------ glob.c | 392 +++++++++++++++--------------- glom.c | 636 ++++++++++++++++++++++++------------------------ hash.c | 438 ++++++++++++++++----------------- heredoc.c | 238 +++++++++--------- input.c | 410 +++++++++++++++---------------- lex.c | 686 ++++++++++++++++++++++++++-------------------------- list.c | 54 ++--- main.c | 144 +++++++---- match.c | 148 ++++++------ mksignal.c | 130 +++++----- mkstatval.c | 38 +-- nalloc.c | 156 ++++++------ open.c | 64 ++--- print.c | 374 ---------------------------- redir.c | 120 ++++----- signal.c | 100 ++++---- status.c | 178 +++++++------- tree.c | 312 ++++++++++++------------ utils.c | 66 ++--- var.c | 304 +++++++++++------------ wait.c | 192 +++++++-------- walk.c | 606 +++++++++++++++++++++++----------------------- which.c | 160 ++++++------ 29 files changed, 3813 insertions(+), 4132 deletions(-) delete mode 100644 print.c diff --git a/Makefile b/Makefile index 3519ae8..405e182 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = c99 CPPFLAGS = -I. CCCMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS) -RCOBJS = builtins.o except.o exec.o fn.o footobar.o glob.o glom.o hash.o heredoc.o input.o lex.o list.o main.o match.o nalloc.o open.o y.tab.o print.o redir.o signal.o status.o tree.o utils.o var.o wait.o walk.o which.o sigmsgs.o +RCOBJS = builtins.o except.o exec.o fn.o footobar.o glob.o glom.o hash.o heredoc.o input.o lex.o list.o main.o match.o nalloc.o open.o y.tab.o redir.o signal.o status.o tree.o utils.o var.o wait.o walk.o which.o sigmsgs.o all: rc diff --git a/builtins.c b/builtins.c index 8d338a1..f4f6763 100644 --- a/builtins.c +++ b/builtins.c @@ -1,73 +1,73 @@ /* builtins.c: the collection of rc's builtin commands */ /* - NOTE: rc's builtins do not call "rc_error" because they are - commands, and rc errors usually arise from syntax errors. e.g., - you probably don't want interpretation of a shell script to stop - because of a bad umask. + NOTE: rc's builtins do not call "rc_error" because they are + commands, and rc errors usually arise from syntax errors. e.g., + you probably don't want interpretation of a shell script to stop + because of a bad umask. */ #include "rc.h" static void b_break(char **), b_cd(char **), b_eval(char **), b_exit(char **), - b_newpgrp(char **), b_return(char **), b_shift(char **), b_umask(char **), - b_wait(char **), b_limit(char **), b_echo(char **); + b_newpgrp(char **), b_return(char **), b_shift(char **), b_umask(char **), + b_wait(char **), b_limit(char **), b_echo(char **); static struct { - builtin_t *p; - char *name; + builtin_t *p; + char *name; } builtins[] = { - { b_break, "break" }, - { b_builtin, "builtin" }, - { b_cd, "cd" }, - { b_echo, "echo" }, - { b_eval, "eval" }, - { b_exec, "exec" }, - { b_exit, "exit" }, - { b_limit, "limit" }, - { b_newpgrp, "newpgrp" }, - { b_return, "return" }, - { b_shift, "shift" }, - { b_umask, "umask" }, - { b_wait, "wait" }, - { b_dot, "." }, + { b_break, "break" }, + { b_builtin, "builtin" }, + { b_cd, "cd" }, + { b_echo, "echo" }, + { b_eval, "eval" }, + { b_exec, "exec" }, + { b_exit, "exit" }, + { b_limit, "limit" }, + { b_newpgrp, "newpgrp" }, + { b_return, "return" }, + { b_shift, "shift" }, + { b_umask, "umask" }, + { b_wait, "wait" }, + { b_dot, "." }, }; extern builtin_t *isbuiltin(char *s) { - int i; - for (i = 0; i < arraysize(builtins); i++) - if (streq(builtins[i].name, s)) - return builtins[i].p; - return NULL; + int i; + for (i = 0; i < arraysize(builtins); i++) + if (streq(builtins[i].name, s)) + return builtins[i].p; + return NULL; } /* funcall() is the wrapper used to invoke shell functions. pushes $*, and "return" returns here. */ extern void funcall(char **av) { - Jbwrap j; - Estack e1, e2; - Edata jreturn, star; - if (sigsetjmp(j.j, 1)) - return; - starassign(*av, av+1, true); - jreturn.jb = &j; - star.name = "*"; - except(eReturn, jreturn, &e1); - except(eVarstack, star, &e2); - walk(treecpy(fnlookup(*av), nalloc), true); - varrm("*", true); - unexcept(); /* eVarstack */ - unexcept(); /* eReturn */ + Jbwrap j; + Estack e1, e2; + Edata jreturn, star; + if (sigsetjmp(j.j, 1)) + return; + starassign(*av, av+1, true); + jreturn.jb = &j; + star.name = "*"; + except(eReturn, jreturn, &e1); + except(eVarstack, star, &e2); + walk(treecpy(fnlookup(*av), nalloc), true); + varrm("*", true); + unexcept(); /* eVarstack */ + unexcept(); /* eReturn */ } static void arg_count(char *name) { - fprint(2, RC "too many arguments to %s\n", name); - set(false); + fprintf(stderr, RC "too many arguments to %s\n", name); + set(false); } static void badnum(char *num) { - fprint(2, RC "`%s' is a bad number\n", num); - set(false); + fprintf(stderr, RC "`%s' is a bad number\n", num); + set(false); } /* a dummy command. (exec() performs "exec" simply by not forking) */ @@ -78,141 +78,141 @@ extern void b_exec(char **ignore) { /* echo -n omits a newline. echo -- -n echos '-n' */ static void b_echo(char **av) { - char *format = "%A\n"; - if (*++av != NULL) { - if (streq(*av, "-n")) - format = "%A", av++; - else if (streq(*av, "--")) - av++; - } - fprint(1, format, av); - set(true); + char *format = "%A\n"; + if (*++av != NULL) { + if (streq(*av, "-n")) + format = "%A", av++; + else if (streq(*av, "--")) + av++; + } + fprintf(stdout, format, av); + set(true); } /* cd. traverse $cdpath if the directory given is not an absolute pathname */ static void b_cd(char **av) { - List *s, nil; - char *path = NULL; - size_t t, pathlen = 0; - if (*++av == NULL) { - s = varlookup("home"); - *av = (s == NULL) ? "/" : s->w; - } else if (av[1] != NULL) { - arg_count("cd"); - return; - } - if (isabsolute(*av) || streq(*av, ".") || streq(*av, "..")) { /* absolute pathname? */ - if (chdir(*av) < 0) { - set(false); - uerror(*av); - } else - set(true); - } else { - s = varlookup("cdpath"); - if (s == NULL) { - s = &nil; - nil.w = ""; - nil.n = NULL; - } - do { - if (s != &nil && *s->w != '\0') { - t = strlen(*av) + strlen(s->w) + 2; - if (t > pathlen) - path = nalloc(pathlen = t); - strcpy(path, s->w); - if (!streq(s->w, "/")) /* "//" is special to POSIX */ - strcat(path, "/"); - strcat(path, *av); - } else { - pathlen = 0; - path = *av; - } - if (chdir(path) >= 0) { - set(true); - if (interactive && *s->w != '\0' && !streq(s->w, ".")) - fprint(1, "%s\n", path); - return; - } - s = s->n; - } while (s != NULL); - fprint(2, "couldn't cd to %s\n", *av); - set(false); - } + List *s, nil; + char *path = NULL; + size_t t, pathlen = 0; + if (*++av == NULL) { + s = varlookup("home"); + *av = (s == NULL) ? "/" : s->w; + } else if (av[1] != NULL) { + arg_count("cd"); + return; + } + if (isabsolute(*av) || streq(*av, ".") || streq(*av, "..")) { /* absolute pathname? */ + if (chdir(*av) < 0) { + set(false); + uerror(*av); + } else + set(true); + } else { + s = varlookup("cdpath"); + if (s == NULL) { + s = &nil; + nil.w = ""; + nil.n = NULL; + } + do { + if (s != &nil && *s->w != '\0') { + t = strlen(*av) + strlen(s->w) + 2; + if (t > pathlen) + path = nalloc(pathlen = t); + strcpy(path, s->w); + if (!streq(s->w, "/")) /* "//" is special to POSIX */ + strcat(path, "/"); + strcat(path, *av); + } else { + pathlen = 0; + path = *av; + } + if (chdir(path) >= 0) { + set(true); + if (interactive && *s->w != '\0' && !streq(s->w, ".")) + fprintf(stdout, "%s\n", path); + return; + } + s = s->n; + } while (s != NULL); + fprintf(stderr, "couldn't cd to %s\n", *av); + set(false); + } } static void b_umask(char **av) { - int i; - if (*++av == NULL) { - set(true); - i = umask(0); - umask(i); - fprint(1, "0%o\n", i); - } else if (av[1] == NULL) { - i = o2u(*av); - if ((unsigned int) i > 0777) { - fprint(2, "bad umask\n"); - set(false); - } else { - umask(i); - set(true); - } - } else { - arg_count("umask"); - return; - } + int i; + if (*++av == NULL) { + set(true); + i = umask(0); + umask(i); + fprintf(stdout, "0%o\n", i); // OCTAL + } else if (av[1] == NULL) { + i = o2u(*av); + if ((unsigned int) i > 0777) { + fprintf(stderr, "bad umask\n"); + set(false); + } else { + umask(i); + set(true); + } + } else { + arg_count("umask"); + return; + } } static void b_exit(char **av) { - if (*++av != NULL) - ssetstatus(av); - rc_exit(getstatus()); + if (*++av != NULL) + ssetstatus(av); + rc_exit(getstatus()); } /* raise a "return" exception, i.e., return from a function. if an integer argument is present, set $status to it */ static void b_return(char **av) { - if (*++av != NULL) - ssetstatus(av); - rc_raise(eReturn); + if (*++av != NULL) + ssetstatus(av); + rc_raise(eReturn); } /* raise a "break" exception for breaking out of for and while loops */ static void b_break(char **av) { - if (av[1] != NULL) { - arg_count("break"); - return; - } - rc_raise(eBreak); + if (av[1] != NULL) { + arg_count("break"); + return; + } + rc_raise(eBreak); } /* shift $* n places (default 1) */ static void b_shift(char **av) { - int shift = (av[1] == NULL ? 1 : a2u(av[1])); - List *s, *dollarzero; - if (av[1] != NULL && av[2] != NULL) { - arg_count("shift"); - return; - } - if (shift < 0) { - badnum(av[1]); - return; - } - s = varlookup("*")->n; - dollarzero = varlookup("0"); - while (s != NULL && shift != 0) { - s = s->n; - --shift; - } - if (s == NULL && shift != 0) { - fprint(2, "cannot shift\n"); - set(false); - } else { - varassign("*", append(dollarzero, s), false); - set(true); - } + int shift = (av[1] == NULL ? 1 : a2u(av[1])); + List *s, *dollarzero; + if (av[1] != NULL && av[2] != NULL) { + arg_count("shift"); + return; + } + if (shift < 0) { + badnum(av[1]); + return; + } + s = varlookup("*")->n; + dollarzero = varlookup("0"); + while (s != NULL && shift != 0) { + s = s->n; + --shift; + } + if (s == NULL && shift != 0) { + fprintf(stderr, "cannot shift\n"); + set(false); + } else { + varassign("*", append(dollarzero, s), false); + set(true); + } } /* dud function */ @@ -223,25 +223,25 @@ extern void b_builtin(char **ignore) { /* wait for a given process, or all outstanding processes */ static void b_wait(char **av) { - int status; - pid_t pid; - if (av[1] == NULL) { - waitforall(); - return; - } - if (av[2] != NULL) { - arg_count("wait"); - return; - } - if ((pid = a2u(av[1])) < 0) { - badnum(av[1]); - return; - } - if (rc_wait4(pid, &status, false) > 0) - setstatus(pid, status); - else - set(false); - sigchk(); + int status; + pid_t pid; + if (av[1] == NULL) { + waitforall(); + return; + } + if (av[2] != NULL) { + arg_count("wait"); + return; + } + if ((pid = a2u(av[1])) < 0) { + badnum(av[1]); + return; + } + if (rc_wait4(pid, &status, false) > 0) + setstatus(pid, status); + else + set(false); + sigchk(); } /* @@ -249,19 +249,19 @@ static void b_wait(char **av) { is defined as a variable, function or pathname. */ -#define not(b) ((b)^true) -#define show(b) (not(eff|vee|pee|bee|ess)|(b)) +#define not(b) ((b)^true) +#define show(b) (not(eff|vee|pee|bee|ess)|(b)) /* push a string to be eval'ed onto the input stack. evaluate it */ static void b_eval(char **av) { - bool i = interactive; - if (av[1] == NULL) - return; - interactive = false; - pushstring(av + 1, i); /* don't reset line numbers on noninteractive eval */ - doit(true); - interactive = i; + bool i = interactive; + if (av[1] == NULL) + return; + interactive = false; + pushstring(av + 1, i); /* don't reset line numbers on noninteractive eval */ + doit(true); + interactive = i; } /* @@ -270,182 +270,182 @@ static void b_eval(char **av) { */ extern void b_dot(char **av) { - int fd; - bool old_i = interactive, i = false; - Estack e; - Edata star; - av++; - if (*av == NULL) - return; - if (streq(*av, "-i")) { - av++; - i = true; - } - if (*av == NULL) - return; - fd = rc_open(*av, rFrom); - if (fd < 0) { - uerror(*av); - set(false); - return; - } - starassign(*av, av+1, true); - interactive = i; - pushfd(fd); - star.name = "*"; - except(eVarstack, star, &e); - doit(true); - varrm("*", true); - unexcept(); /* eVarstack */ - interactive = old_i; + int fd; + bool old_i = interactive, i = false; + Estack e; + Edata star; + av++; + if (*av == NULL) + return; + if (streq(*av, "-i")) { + av++; + i = true; + } + if (*av == NULL) + return; + fd = rc_open(*av, rFrom); + if (fd < 0) { + uerror(*av); + set(false); + return; + } + starassign(*av, av+1, true); + interactive = i; + pushfd(fd); + star.name = "*"; + except(eVarstack, star, &e); + doit(true); + varrm("*", true); + unexcept(); /* eVarstack */ + interactive = old_i; } /* put rc into a new pgrp. Used on the NeXT where the Terminal program is broken (sigh) */ static void b_newpgrp(char **av) { - if (av[1] != NULL) { - arg_count("newpgrp"); - return; - } - setpgid(rc_pid, rc_pid); /* XXX check return value */ - tcsetpgrp(2, rc_pid); /* XXX check return value */ + if (av[1] != NULL) { + arg_count("newpgrp"); + return; + } + setpgid(rc_pid, rc_pid); /* XXX check return value */ + tcsetpgrp(2, rc_pid); /* XXX check return value */ } /* Berkeley limit support was cleaned up by Paul Haahr. */ static const struct Suffix - kbsuf = { NULL, 1024, "k" }, - mbsuf = { &kbsuf, 1024*1024, "m" }, - gbsuf = { &mbsuf, 1024*1024*1024, "g" }, - stsuf = { NULL, 1, "s" }, - mtsuf = { &stsuf, 60, "m" }, - htsuf = { &mtsuf, 60*60, "h" }; -#define SIZESUF &gbsuf -#define TIMESUF &htsuf -#define NOSUF ((struct Suffix *) NULL) /* for RLIMIT_NOFILE on SunOS 4.1 */ + kbsuf = { NULL, 1024, "k" }, + mbsuf = { &kbsuf, 1024*1024, "m" }, + gbsuf = { &mbsuf, 1024*1024*1024, "g" }, + stsuf = { NULL, 1, "s" }, + mtsuf = { &stsuf, 60, "m" }, + htsuf = { &mtsuf, 60*60, "h" }; +#define SIZESUF &gbsuf +#define TIMESUF &htsuf +#define NOSUF ((struct Suffix *) NULL) /* for RLIMIT_NOFILE on SunOS 4.1 */ static const struct Limit limits[] = { - { "cputime", RLIMIT_CPU, TIMESUF }, - { "filesize", RLIMIT_FSIZE, SIZESUF }, - { "datasize", RLIMIT_DATA, SIZESUF }, - { "stacksize", RLIMIT_STACK, SIZESUF }, - { "coredumpsize", RLIMIT_CORE, SIZESUF }, + { "cputime", RLIMIT_CPU, TIMESUF }, + { "filesize", RLIMIT_FSIZE, SIZESUF }, + { "datasize", RLIMIT_DATA, SIZESUF }, + { "stacksize", RLIMIT_STACK, SIZESUF }, + { "coredumpsize", RLIMIT_CORE, SIZESUF }, #ifdef RLIMIT_NOFILE /* SUSv2, but not universal */ - { "descriptors", RLIMIT_NOFILE, NOSUF }, + { "descriptors", RLIMIT_NOFILE, NOSUF }, #endif #ifdef RLIMIT_AS /* SUSv2, but not universal */ - { "memoryuse", RLIMIT_AS, SIZESUF }, + { "memoryuse", RLIMIT_AS, SIZESUF }, #endif #if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS) /* old name for AS */ - { "memoryuse", RLIMIT_VMEM, SIZESUF }, + { "memoryuse", RLIMIT_VMEM, SIZESUF }, #endif #ifdef RLIMIT_RSS - { "memoryrss", RLIMIT_RSS, SIZESUF }, + { "memoryrss", RLIMIT_RSS, SIZESUF }, #endif #ifdef RLIMIT_NPROC - { "maxproc", RLIMIT_NPROC, NOSUF }, + { "maxproc", RLIMIT_NPROC, NOSUF }, #endif #ifdef RLIMIT_MEMLOCK - { "memorylocked", RLIMIT_MEMLOCK, SIZESUF }, + { "memorylocked", RLIMIT_MEMLOCK, SIZESUF }, #endif #ifdef RLIMIT_LOCKS - { "filelocks", RLIMIT_LOCKS, NOSUF }, + { "filelocks", RLIMIT_LOCKS, NOSUF }, #endif - { NULL, 0, NULL } + { NULL, 0, NULL } }; static void printlimit(const struct Limit *limit, bool hard) { - struct rlimit rlim; - rlim_t lim; - getrlimit(limit->flag, &rlim); - if (hard) - lim = rlim.rlim_max; - else - lim = rlim.rlim_cur; - if (lim == RLIM_INFINITY) - fprint(1, "%s \tunlimited\n", limit->name); - else { - const struct Suffix *suf; - for (suf = limit->suffix; suf != NULL; suf = suf->next) - if (lim % suf->amount == 0 && (lim != 0 || suf->amount > 1)) { - lim /= suf->amount; - break; - } - fprint(1, "%s \t%ld%s\n", limit->name, (long)lim, (suf == NULL || lim == 0) ? "" : suf->name); - } + struct rlimit rlim; + rlim_t lim; + getrlimit(limit->flag, &rlim); + if (hard) + lim = rlim.rlim_max; + else + lim = rlim.rlim_cur; + if (lim == RLIM_INFINITY) + fprintf(stdout, "%s \tunlimited\n", limit->name); + else { + const struct Suffix *suf; + for (suf = limit->suffix; suf != NULL; suf = suf->next) + if (lim % suf->amount == 0 && (lim != 0 || suf->amount > 1)) { + lim /= suf->amount; + break; + } + fprintf(stdout, "%s \t%ld%s\n", limit->name, (long)lim, (suf == NULL || lim == 0) ? "" : suf->name); + } } static bool parselimit(const struct Limit *resource, rlim_t *limit, char *s) { - char *t; - int len = strlen(s); - const struct Suffix *suf = resource->suffix; - - *limit = 1; - if (streq(s, "unlimited")) { - *limit = RLIM_INFINITY; - return true; - } - if (suf == TIMESUF && (t = strchr(s, ':')) != NULL) { - int min, sec; - *t++ = '\0'; - min = a2u(s); sec = a2u(t); - if (min == -1 || sec == -1) return false; - *limit = 60 * min + sec; - } else { - int n; - for (; suf != NULL; suf = suf->next) - if (streq(suf->name, s + len - strlen(suf->name))) { - s[len - strlen(suf->name)] = '\0'; - *limit *= suf->amount; - break; - } - n = a2u(s); - if (n == -1) return false; - *limit *= n; - } - return true; + char *t; + int len = strlen(s); + const struct Suffix *suf = resource->suffix; + + *limit = 1; + if (streq(s, "unlimited")) { + *limit = RLIM_INFINITY; + return true; + } + if (suf == TIMESUF && (t = strchr(s, ':')) != NULL) { + int min, sec; + *t++ = '\0'; + min = a2u(s); sec = a2u(t); + if (min == -1 || sec == -1) return false; + *limit = 60 * min + sec; + } else { + int n; + for (; suf != NULL; suf = suf->next) + if (streq(suf->name, s + len - strlen(suf->name))) { + s[len - strlen(suf->name)] = '\0'; + *limit *= suf->amount; + break; + } + n = a2u(s); + if (n == -1) return false; + *limit *= n; + } + return true; } static void b_limit(char **av) { - const struct Limit *lp = limits; - bool hard = false; - if (*++av != NULL && streq(*av, "-h")) { - av++; - hard = true; - } - if (*av == NULL) { - for (; lp->name != NULL; lp++) - printlimit(lp, hard); - return; - } - for (;; lp++) { - if (lp->name == NULL) { - fprint(2, "no such limit\n"); - set(false); - return; - } - if (streq(*av, lp->name)) - break; - } - if (*++av == NULL) - printlimit(lp, hard); - else { - struct rlimit rlim; - rlim_t pl; - getrlimit(lp->flag, &rlim); - if (!parselimit(lp, &pl, *av)) { - fprint(2, "bad limit\n"); - set(false); - return; - } - if (hard) - rlim.rlim_max = pl; - else - rlim.rlim_cur = pl; - if (setrlimit(lp->flag, &rlim) == -1) { - uerror("setrlimit"); - set(false); - } else - set(true); - } + const struct Limit *lp = limits; + bool hard = false; + if (*++av != NULL && streq(*av, "-h")) { + av++; + hard = true; + } + if (*av == NULL) { + for (; lp->name != NULL; lp++) + printlimit(lp, hard); + return; + } + for (;; lp++) { + if (lp->name == NULL) { + fprintf(stderr, "no such limit\n"); + set(false); + return; + } + if (streq(*av, lp->name)) + break; + } + if (*++av == NULL) + printlimit(lp, hard); + else { + struct rlimit rlim; + rlim_t pl; + getrlimit(lp->flag, &rlim); + if (!parselimit(lp, &pl, *av)) { + fprintf(stderr, "bad limit\n"); + set(false); + return; + } + if (hard) + rlim.rlim_max = pl; + else + rlim.rlim_cur = pl; + if (setrlimit(lp->flag, &rlim) == -1) { + uerror("setrlimit"); + set(false); + } else + set(true); + } } diff --git a/except.c b/except.c index 82d421e..a157f7d 100644 --- a/except.c +++ b/except.c @@ -12,34 +12,34 @@ static Estack *estack; /* add an exception to the input stack. */ extern void except(ecodes e, Edata data, Estack *ex) { - ex->prev = estack; - estack = ex; - estack->e = e; - estack->data = data; - if (e == eError || e == eBreak || e == eReturn) - estack->interactive = interactive; + ex->prev = estack; + estack = ex; + estack->e = e; + estack->data = data; + if (e == eError || e == eBreak || e == eReturn) + estack->interactive = interactive; } /* remove an exception, restore last interactive value */ extern void unexcept() { - switch (estack->e) { - default: - break; - case eError: - interactive = estack->interactive; - break; - case eArena: - restoreblock(estack->data.b); - break; - case eFifo: - unlink(estack->data.name); - break; - case eFd: - close(estack->data.fd); - break; - } - estack = estack->prev; + switch (estack->e) { + default: + break; + case eError: + interactive = estack->interactive; + break; + case eArena: + restoreblock(estack->data.b); + break; + case eFifo: + unlink(estack->data.name); + break; + case eFd: + close(estack->data.fd); + break; + } + estack = estack->prev; } /* @@ -56,82 +56,82 @@ extern void unexcept() { */ extern void rc_raise(ecodes e) { - if (e == eError && rc_pid != getpid()) - exit(1); /* child processes exit on an error/signal */ - for (; estack != NULL; estack = estack->prev) - if (estack->e != e) { - if (e == eBreak && estack->e != eArena) - rc_error("break outside of loop"); - else if (e == eReturn && estack->e == eError) /* can return from loops inside functions */ - rc_error("return outside of function"); - switch (estack->e) { - default: - break; - case eVarstack: - varrm(estack->data.name, true); - break; - case eArena: - restoreblock(estack->data.b); - break; - case eFifo: - unlink(estack->data.name); - break; - case eFd: - close(estack->data.fd); - break; - } - } else { - if (e == eError && !estack->interactive) { - popinput(); - } else { - Jbwrap *j = estack->data.jb; + if (e == eError && rc_pid != getpid()) + exit(1); /* child processes exit on an error/signal */ + for (; estack != NULL; estack = estack->prev) + if (estack->e != e) { + if (e == eBreak && estack->e != eArena) + rc_error("break outside of loop"); + else if (e == eReturn && estack->e == eError) /* can return from loops inside functions */ + rc_error("return outside of function"); + switch (estack->e) { + default: + break; + case eVarstack: + varrm(estack->data.name, true); + break; + case eArena: + restoreblock(estack->data.b); + break; + case eFifo: + unlink(estack->data.name); + break; + case eFd: + close(estack->data.fd); + break; + } + } else { + if (e == eError && !estack->interactive) { + popinput(); + } else { + Jbwrap *j = estack->data.jb; - interactive = estack->interactive; - estack = estack->prev; - siglongjmp(j->j, 1); - } - } - rc_exit(1); /* top of exception stack */ + interactive = estack->interactive; + estack = estack->prev; + siglongjmp(j->j, 1); + } + } + rc_exit(1); /* top of exception stack */ } extern bool outstanding_cmdarg() { - return estack->e == eFifo || estack->e == eFd; + return estack->e == eFifo || estack->e == eFd; } extern void pop_cmdarg(bool remove) { - for (; estack != NULL; estack = estack->prev) - switch (estack->e) { - case eFifo: - if (remove) - unlink(estack->data.name); - break; - case eFd: - if (remove) - close(estack->data.fd); - break; - default: - return; - } + for (; estack != NULL; estack = estack->prev) + switch (estack->e) { + case eFifo: + if (remove) + unlink(estack->data.name); + break; + case eFd: + if (remove) + close(estack->data.fd); + break; + default: + return; + } } /* exception handlers */ extern void rc_error(char *s) { - pr_error(s, -1); - set(false); - redirq = NULL; - cond = false; /* no longer inside conditional */ - rc_raise(eError); + pr_error(s, -1); + set(false); + redirq = NULL; + cond = false; /* no longer inside conditional */ + rc_raise(eError); } extern void sigint(int s) { - if (s != SIGINT) - panic("s != SIGINT in sigint catcher"); - /* this is the newline you see when you hit ^C while typing a command */ - if (interactive && nl_on_intr) - fprint(2, "\n"); - nl_on_intr = true; - redirq = NULL; - cond = false; - rc_raise(eError); + if (s != SIGINT) + panic("s != SIGINT in sigint catcher"); + /* this is the newline you see when you hit ^C while typing a command */ + if (interactive && nl_on_intr) + fprintf(stderr, "\n"); + nl_on_intr = true; + redirq = NULL; + cond = false; + rc_raise(eError); } diff --git a/exec.c b/exec.c index dd25671..ddfd945 100644 --- a/exec.c +++ b/exec.c @@ -8,119 +8,119 @@ */ extern void exec(List *s, bool parent) { - char **av, **ev = NULL; - int stat; - pid_t pid; - builtin_t *b; - char *path = NULL; - bool didfork, returning, saw_exec, saw_builtin; - av = list2array(s, false); - saw_builtin = saw_exec = false; - do { - if (*av == NULL || isabsolute(*av)) - b = NULL; - else if (!saw_builtin && fnlookup(*av) != NULL) - b = funcall; - else - b = isbuiltin(*av); + char **av, **ev = NULL; + int stat; + pid_t pid; + builtin_t *b; + char *path = NULL; + bool didfork, returning, saw_exec, saw_builtin; + av = list2array(s, false); + saw_builtin = saw_exec = false; + do { + if (*av == NULL || isabsolute(*av)) + b = NULL; + else if (!saw_builtin && fnlookup(*av) != NULL) + b = funcall; + else + b = isbuiltin(*av); - /* - a builtin applies only to the immmediately following - command, e.g., builtin exec echo hi - */ - saw_builtin = false; + /* + a builtin applies only to the immmediately following + command, e.g., builtin exec echo hi + */ + saw_builtin = false; - if (b == b_exec) { - av++; - saw_exec = true; - parent = false; - } else if (b == b_builtin) { - av++; - saw_builtin = true; - } - } while (b == b_exec || b == b_builtin); - if (*av == NULL && saw_exec) { /* do redirs and return on a null exec */ - doredirs(); - return; - } - /* force an exit on exec with any rc_error, but not for null commands as above */ - if (saw_exec) - rc_pid = -1; - if (b == NULL) { - path = which(*av, true); - if (path == NULL && *av != NULL) { /* perform null commands for redirections */ - set(false); - redirq = NULL; - if (parent) - return; - rc_exit(1); - } - ev = makeenv(); /* environment only needs to be built for execve() */ - } - /* - If parent & the redirq is nonnull, builtin or not it has to fork. - If the fifoq is nonnull, then it must be emptied at the end so we - must fork no matter what. - */ - if ((parent && (b == NULL || redirq != NULL)) || outstanding_cmdarg()) { - pid = rc_fork(); - didfork = true; - } else { - pid = 0; - didfork = false; - } - returning = (!didfork && parent); - switch (pid) { - case -1: - uerror("fork"); - rc_error(NULL); - /* NOTREACHED */ - case 0: - if (!returning) - setsigdefaults(false); - pop_cmdarg(false); - doredirs(); + if (b == b_exec) { + av++; + saw_exec = true; + parent = false; + } else if (b == b_builtin) { + av++; + saw_builtin = true; + } + } while (b == b_exec || b == b_builtin); + if (*av == NULL && saw_exec) { /* do redirs and return on a null exec */ + doredirs(); + return; + } + /* force an exit on exec with any rc_error, but not for null commands as above */ + if (saw_exec) + rc_pid = -1; + if (b == NULL) { + path = which(*av, true); + if (path == NULL && *av != NULL) { /* perform null commands for redirections */ + set(false); + redirq = NULL; + if (parent) + return; + rc_exit(1); + } + ev = makeenv(); /* environment only needs to be built for execve() */ + } + /* + If parent & the redirq is nonnull, builtin or not it has to fork. + If the fifoq is nonnull, then it must be emptied at the end so we + must fork no matter what. + */ + if ((parent && (b == NULL || redirq != NULL)) || outstanding_cmdarg()) { + pid = rc_fork(); + didfork = true; + } else { + pid = 0; + didfork = false; + } + returning = (!didfork && parent); + switch (pid) { + case -1: + uerror("fork"); + rc_error(NULL); + /* NOTREACHED */ + case 0: + if (!returning) + setsigdefaults(false); + pop_cmdarg(false); + doredirs(); - /* null commands performed for redirections */ - if (*av == NULL || b != NULL) { - if (b != NULL) - (*b)(av); - if (returning) - return; - rc_exit(getstatus()); - } - execve(path, (char * const *) av, (char * const *) ev); + /* null commands performed for redirections */ + if (*av == NULL || b != NULL) { + if (b != NULL) + (*b)(av); + if (returning) + return; + rc_exit(getstatus()); + } + execve(path, (char * const *) av, (char * const *) ev); #ifdef DEFAULTINTERP - if (errno == ENOEXEC) { - *av = path; - *--av = DEFAULTINTERP; - execve(*av, (char * const *) av, (char * const *) ev); - } + if (errno == ENOEXEC) { + *av = path; + *--av = DEFAULTINTERP; + execve(*av, (char * const *) av, (char * const *) ev); + } #endif - uerror(*av); - rc_exit(1); - /* NOTREACHED */ - default: - redirq = NULL; - rc_wait4(pid, &stat, true); - setstatus(-1, stat); - /* - There is a very good reason for having this weird - nl_on_intr variable: when rc and its child both - process a SIGINT, (i.e., the child has a SIGINT - catcher installed) then you don't want rc to print - a newline when the child finally exits. Here's an - example: ed, , . rc does not - and should not print a newline before the next - prompt, even though there's a SIGINT in its signal - vector. - */ - if (WIFEXITED(stat)) - nl_on_intr = false; - sigchk(); - nl_on_intr = true; - pop_cmdarg(true); - } + uerror(*av); + rc_exit(1); + /* NOTREACHED */ + default: + redirq = NULL; + rc_wait4(pid, &stat, true); + setstatus(-1, stat); + /* + There is a very good reason for having this weird + nl_on_intr variable: when rc and its child both + process a SIGINT, (i.e., the child has a SIGINT + catcher installed) then you don't want rc to print + a newline when the child finally exits. Here's an + example: ed, , . rc does not + and should not print a newline before the next + prompt, even though there's a SIGINT in its signal + vector. + */ + if (WIFEXITED(stat)) + nl_on_intr = false; + sigchk(); + nl_on_intr = true; + pop_cmdarg(true); + } } diff --git a/fn.c b/fn.c index 0d73932..8605719 100644 --- a/fn.c +++ b/fn.c @@ -19,110 +19,110 @@ static void (*def_sigterm)(int) = SIG_DFL; */ extern void inithandler() { - int i; - null.type = nBody; - null.u[0].p = null.u[1].p = NULL; - for (i = 1; i < NSIG; i++) - if (sighandlers[i] == SIG_IGN) - fnassign(signals[i].name, NULL); /* ignore incoming ignored signals */ - if (interactive || sighandlers[SIGINT] != SIG_IGN) { - def_sigint = sigint; - fnrm("sigint"); /* installs SIGINT catcher if not inherited ignored */ - } - - if (interactive || sighandlers[SIGQUIT] != SIG_IGN) { - def_sigquit = dud_handler; - fnrm("sigquit"); /* "ignores" SIGQUIT unless inherited ignored */ - } - - if (interactive) { - def_sigterm = dud_handler; - fnrm("sigterm"); /* ditto for SIGTERM */ - } + int i; + null.type = nBody; + null.u[0].p = null.u[1].p = NULL; + for (i = 1; i < NSIG; i++) + if (sighandlers[i] == SIG_IGN) + fnassign(signals[i].name, NULL); /* ignore incoming ignored signals */ + if (interactive || sighandlers[SIGINT] != SIG_IGN) { + def_sigint = sigint; + fnrm("sigint"); /* installs SIGINT catcher if not inherited ignored */ + } + + if (interactive || sighandlers[SIGQUIT] != SIG_IGN) { + def_sigquit = dud_handler; + fnrm("sigquit"); /* "ignores" SIGQUIT unless inherited ignored */ + } + + if (interactive) { + def_sigterm = dud_handler; + fnrm("sigterm"); /* ditto for SIGTERM */ + } } /* only run this in a child process! resets signals to their default values */ extern void setsigdefaults(bool sysvbackground) { - int i; - /* - General housekeeping: setsigdefaults happens after fork(), - so it's a convenient place to clean up open file descriptors. - (history file, scripts, etc.) - */ - closefds(); - /* - Restore signals to SIG_DFL, paying close attention to - a few quirks: SIGINT, SIGQUIT and are treated specially - depending on whether we are doing v7-style backgrounding - or not; the default action for SIGINT, SIGQUIT and SIGTERM - must be set to the appropriate action; finally, care must - be taken not to set to SIG_DFL any signals which are being - ignored. - */ - for (i = 1; i < NSIG; i++) - if (sighandlers[i] != SIG_IGN) { - handlers[i] = NULL; - switch (i) { - case SIGINT: - if (sysvbackground) { - def_sigint = SIG_IGN; - fnassign("sigint", NULL); /* ignore */ - } else { - def_sigint = SIG_DFL; - goto sigcommon; - } - break; - case SIGQUIT: - if (sysvbackground) { - def_sigquit = SIG_IGN; - fnassign("sigquit", NULL); /* ignore */ - } else { - def_sigquit = SIG_DFL; - goto sigcommon; - } - break; - case SIGTERM: - def_sigterm = SIG_DFL; - /* FALLTHROUGH */ - sigcommon: - default: - if (sighandlers[i] != SIG_DFL) { - rc_signal(i, SIG_DFL); - delete_fn(signals[i].name); - } - } - } - delete_fn("sigexit"); - runexit = false; /* No sigexit on subshells */ + int i; + /* + General housekeeping: setsigdefaults happens after fork(), + so it's a convenient place to clean up open file descriptors. + (history file, scripts, etc.) + */ + closefds(); + /* + Restore signals to SIG_DFL, paying close attention to + a few quirks: SIGINT, SIGQUIT and are treated specially + depending on whether we are doing v7-style backgrounding + or not; the default action for SIGINT, SIGQUIT and SIGTERM + must be set to the appropriate action; finally, care must + be taken not to set to SIG_DFL any signals which are being + ignored. + */ + for (i = 1; i < NSIG; i++) + if (sighandlers[i] != SIG_IGN) { + handlers[i] = NULL; + switch (i) { + case SIGINT: + if (sysvbackground) { + def_sigint = SIG_IGN; + fnassign("sigint", NULL); /* ignore */ + } else { + def_sigint = SIG_DFL; + goto sigcommon; + } + break; + case SIGQUIT: + if (sysvbackground) { + def_sigquit = SIG_IGN; + fnassign("sigquit", NULL); /* ignore */ + } else { + def_sigquit = SIG_DFL; + goto sigcommon; + } + break; + case SIGTERM: + def_sigterm = SIG_DFL; + /* FALLTHROUGH */ + sigcommon: + default: + if (sighandlers[i] != SIG_DFL) { + rc_signal(i, SIG_DFL); + delete_fn(signals[i].name); + } + } + } + delete_fn("sigexit"); + runexit = false; /* No sigexit on subshells */ } /* rc's exit. if runexit is set, run the sigexit function. */ extern void rc_exit(int stat) { - if (runexit) { - char *sig[2]; - sig[0] = "sigexit"; - sig[1] = NULL; - runexit = false; - funcall(sig); - stat = getstatus(); - } - exit(stat); + if (runexit) { + char *sig[2]; + sig[0] = "sigexit"; + sig[1] = NULL; + runexit = false; + funcall(sig); + stat = getstatus(); + } + exit(stat); } /* The signal handler for all functions. calls walk() */ static void fn_handler(int s) { - char *sig[2]; - int olderrno; - if (s < 1 || s >= NSIG) - panic("unknown signal"); - olderrno = errno; - sig[0] = signals[s].name; - sig[1] = NULL; - funcall(sig); - errno = olderrno; + char *sig[2]; + int olderrno; + if (s < 1 || s >= NSIG) + panic("unknown signal"); + olderrno = errno; + sig[0] = signals[s].name; + sig[1] = NULL; + funcall(sig); + errno = olderrno; } /* A dud signal handler for SIGQUIT and SIGTERM */ @@ -136,70 +136,70 @@ static void dud_handler(int ignore) { */ extern void fnassign(char *name, Node *def) { - if (!name) return; - Node *newdef = treecpy(def == NULL ? &null : def, ealloc); /* important to do the treecopy first */ - rc_Function *new = get_fn_place(name); - int i; - new->def = newdef; - new->extdef = NULL; - if (strncmp(name, "sig", conststrlen("sig")) == 0) { /* slight optimization */ - if (streq(name, "sigexit")) - runexit = true; - for (i = 1; i < NSIG; i++) /* zero is a bogus signal */ - if (streq(signals[i].name, name)) { - handlers[i] = newdef; - if (def == NULL) - rc_signal(i, SIG_IGN); - else - rc_signal(i, fn_handler); - break; - } - } + if (!name) return; + Node *newdef = treecpy(def == NULL ? &null : def, ealloc); /* important to do the treecopy first */ + rc_Function *new = get_fn_place(name); + int i; + new->def = newdef; + new->extdef = NULL; + if (strncmp(name, "sig", conststrlen("sig")) == 0) { /* slight optimization */ + if (streq(name, "sigexit")) + runexit = true; + for (i = 1; i < NSIG; i++) /* zero is a bogus signal */ + if (streq(signals[i].name, name)) { + handlers[i] = newdef; + if (def == NULL) + rc_signal(i, SIG_IGN); + else + rc_signal(i, fn_handler); + break; + } + } } /* Assign a function from the environment. Store just the external representation */ extern void fnassign_string(char *extdef) { - char *name = get_name(extdef+3); /* +3 to skip over "fn_" */ - rc_Function *new; - if (name == NULL) - return; - new = get_fn_place(name); - new->def = NULL; - new->extdef = ecpy(extdef); + char *name = get_name(extdef+3); /* +3 to skip over "fn_" */ + rc_Function *new; + if (name == NULL) + return; + new = get_fn_place(name); + new->def = NULL; + new->extdef = ecpy(extdef); } /* Return a function in Node form, evaluating an entry from the environment if necessary */ extern Node *fnlookup(char *name) { - rc_Function *look = lookup_fn(name); - Node *ret; - if (look == NULL) - return NULL; /* not found */ - if (look->def != NULL) - return look->def; - if (look->extdef == NULL) /* function was set to null, e.g., fn foo {} */ - return &null; - ret = parse_fn(look->extdef); - if (ret == NULL) { - efree(look->extdef); - look->extdef = NULL; - return &null; - } else { - return look->def = treecpy(ret, ealloc); /* Need to take it out of nalloc space */ - } + rc_Function *look = lookup_fn(name); + Node *ret; + if (look == NULL) + return NULL; /* not found */ + if (look->def != NULL) + return look->def; + if (look->extdef == NULL) /* function was set to null, e.g., fn foo {} */ + return &null; + ret = parse_fn(look->extdef); + if (ret == NULL) { + efree(look->extdef); + look->extdef = NULL; + return &null; + } else { + return look->def = treecpy(ret, ealloc); /* Need to take it out of nalloc space */ + } } /* Return a function in string form (used by makeenv) */ extern char *fnlookup_string(char *name) { - rc_Function *look = lookup_fn(name); + rc_Function *look = lookup_fn(name); - if (look == NULL) - return NULL; - if (look->extdef != NULL) - return look->extdef; - return look->extdef = mprint("fn_%F={%T}", name, look->def); + if (look == NULL) + return NULL; + if (look->extdef != NULL) + return look->extdef; + return look->extdef = mprint("fn_%F={%T}", name, look->def); } /* @@ -208,42 +208,42 @@ extern char *fnlookup_string(char *name) { */ extern void fnrm(char *name) { - int i; - for (i = 1; i < NSIG; i++) - if (signals[i].name && streq(signals[i].name, name)) { - handlers[i] = NULL; - switch (i) { - case SIGINT: - rc_signal(i, def_sigint); - break; - case SIGQUIT: - rc_signal(i, def_sigquit); - break; - case SIGTERM: - rc_signal(i, def_sigterm); - break; - default: - rc_signal(i, SIG_DFL); - } - } - if (streq(name, "sigexit")) - runexit = false; - delete_fn(name); + int i; + for (i = 1; i < NSIG; i++) + if (signals[i].name && streq(signals[i].name, name)) { + handlers[i] = NULL; + switch (i) { + case SIGINT: + rc_signal(i, def_sigint); + break; + case SIGQUIT: + rc_signal(i, def_sigquit); + break; + case SIGTERM: + rc_signal(i, def_sigterm); + break; + default: + rc_signal(i, SIG_DFL); + } + } + if (streq(name, "sigexit")) + runexit = false; + delete_fn(name); } extern void whatare_all_signals() { - int i; - for (i = 1; i < NSIG; i++) - if (signals[i].name && *signals[i].name) { - if (sighandlers[i] == SIG_IGN) - fprint(1, "fn %s {}\n", signals[i].name); - else if (sighandlers[i] == fn_handler) - fprint(1, "fn %S {%T}\n", signals[i].name, handlers[i]); - else - fprint(1, "fn %s\n", signals[i].name); - } + int i; + for (i = 1; i < NSIG; i++) + if (signals[i].name && *signals[i].name) { + if (sighandlers[i] == SIG_IGN) + fprint(1, "fn %s {}\n", signals[i].name); + else if (sighandlers[i] == fn_handler) + fprint(1, "fn %S {%T}\n", signals[i].name, handlers[i]); + else + fprint(1, "fn %s\n", signals[i].name); + } } extern void prettyprint_fn(int fd, char *name, Node *n) { - fprint(fd, "fn %S {%T}\n", name, n); + fprint(fd, "fn %S {%T}\n", name, n); } diff --git a/footobar.c b/footobar.c index 0cf1efd..d48ebde 100644 --- a/footobar.c +++ b/footobar.c @@ -9,221 +9,221 @@ #if PROTECT_ENV static bool Fconv(Format *f, int ignore) { - unsigned const char *s = va_arg(f->args, unsigned const char *); - int c; - - while ((c = *s++) != '\0') - if (dnw[c] || c == '*' || (c == '_' && *s == '_')) - fmtprint(f, "__%02x", c); - else - fmtputc(f, c); - return false; + unsigned const char *s = va_arg(f->args, unsigned const char *); + int c; + + while ((c = *s++) != '\0') + if (dnw[c] || c == '*' || (c == '_' && *s == '_')) + fmtprint(f, "__%02x", c); + else + fmtputc(f, c); + return false; } #endif /* convert a redirection to a printable form */ static bool Dconv(Format *f, int ignore) { - const char *name = "?"; - int n = va_arg(f->args, int); - switch (n) { - case rCreate: name = ">"; break; - case rAppend: name = ">>"; break; - case rFrom: name = "<"; break; - case rHeredoc: name = "<<"; break; - case rHerestring: name = "<<<"; break; - } - fmtcat(f, name); - return false; + const char *name = "?"; + int n = va_arg(f->args, int); + switch (n) { + case rCreate: name = ">"; break; + case rAppend: name = ">>"; break; + case rFrom: name = "<"; break; + case rHeredoc: name = "<<"; break; + case rHerestring: name = "<<<"; break; + } + fmtcat(f, name); + return false; } /* defaultfd -- return the default fd for a given redirection operation */ static int defaultfd(int op) { - return (op == rCreate || op == rAppend) ? 1 : 0; + return (op == rCreate || op == rAppend) ? 1 : 0; } /* convert a function in Node * form into something rc can parse (and humans can read?) */ static bool Tconv(Format *f, int ignore) { - bool dollar = f->flags & FMT_altform; - Node *n = va_arg(f->args, Node *); - - if (n == NULL) { - fmtprint(f, "()"); - return false; - } - switch (n->type) { - case nBang: fmtprint(f, "!%T", n->u[0].p); break; - case nCase: fmtprint(f, "case %T", n->u[0].p); break; - case nNowait: fmtprint(f, "%T&", n->u[0].p); break; - case nRmfn: fmtprint(f, "fn %T", n->u[0].p); break; - case nSubshell: fmtprint(f, "@ %T", n->u[0].p); break; - case nAndalso: fmtprint(f, "%T&&%T", n->u[0].p, n->u[1].p); break; - case nAssign: fmtprint(f, "%T=%T", n->u[0].p, n->u[1].p); break; - case nConcat: fmtprint(f, "%T^%T", n->u[0].p, n->u[1].p); break; - case nElse: fmtprint(f, "{%T}else %T", n->u[0].p, n->u[1].p); break; - case nNewfn: fmtprint(f, "fn %T {%T}", n->u[0].p, n->u[1].p); break; - case nIf: fmtprint(f, "if(%T)%T", n->u[0].p, n->u[1].p); break; - case nOrelse: fmtprint(f, "%T||%T", n->u[0].p, n->u[1].p); break; - case nArgs: fmtprint(f, "%T %T", n->u[0].p, n->u[1].p); break; - case nSwitch: fmtprint(f, "switch(%T){%T}", n->u[0].p, n->u[1].p); break; - case nMatch: fmtprint(f, "~ %T %T", n->u[0].p, n->u[1].p); break; - case nWhile: fmtprint(f, "while(%T)%T", n->u[0].p, n->u[1].p); break; - case nForin: fmtprint(f, "for(%T in %T)%T", n->u[0].p, n->u[1].p, n->u[2].p); break; - case nVarsub: fmtprint(f, "$%T(%T)", n->u[0].p, n->u[1].p); break; - case nWord: - fmtprint(f, n->u[2].i && quotep(n->u[0].s, dollar) ? - "%#S" : "%S", n->u[0].s); - break; - case nLappend: { - static bool inlist; - if (!inlist) { - inlist = true; - fmtprint(f, "(%T %T)", n->u[0].p, n->u[1].p); - inlist = false; - } else { - fmtprint(f, "%T %T", n->u[0].p, n->u[1].p); - } - break; - } - case nCount: case nFlat: case nVar: { - char *lp = "", *rp = ""; - Node *n0 = n->u[0].p; - - if (n0->type != nWord) - lp = "(", rp = ")"; - - switch (n->type) { - default: panic("this can't happen"); break; - case nCount: fmtprint(f, "$#%s%#T%s", lp, n0, rp); break; - case nFlat: fmtprint(f, "$^%s%#T%s", lp, n0, rp); break; - case nVar: fmtprint(f, "$%s%#T%s", lp, n0, rp); break; - } - break; - } - case nDup: - if (n->u[2].i != -1) - fmtprint(f, "%D[%d=%d]", n->u[0].i, n->u[1].i, n->u[2].i); - else - fmtprint(f, "%D[%d=]", n->u[0].i, n->u[1].i); - break; - case nBackq: { - Node *n0 = n->u[0].p, *n00; - if (n0 != NULL && n0->type == nVar - && (n00 = n0->u[0].p) != NULL && n00->type == nWord && streq(n00->u[0].s, "ifs")) - fmtprint(f, "`"); - else - fmtprint(f, "``%T", n0); - fmtprint(f, "{%T}", n->u[1].p); - break; - } - case nCbody: - case nBody: { - Node *n0 = n->u[0].p; - if (n0 != NULL) - fmtprint(f, "%T", n->u[0].p); - if (n->u[1].p != NULL) { - if (n0 != NULL && n0->type != nNowait) - fmtprint(f, ";"); - fmtprint(f, "%T", n->u[1].p); - } - break; - } - case nBrace: - fmtprint(f, "{%T}", n->u[0].p); - if (n->u[1].p != NULL) - fmtprint(f, "%T", n->u[1].p); - break; - case nEpilog: - case nPre: - fmtprint(f, "%T", n->u[0].p); - if (n->u[1].p != NULL) - fmtprint(f, " %T", n->u[1].p); - break; - case nPipe: { - int ofd = n->u[0].i, ifd = n->u[1].i; - fmtprint(f, "%T|", n->u[2].p); - if (ifd != 0) - fmtprint(f, "[%d=%d]", ofd, ifd); - else if (ofd != 1) - fmtprint(f, "[%d]", ofd); - fmtprint(f, "%T", n->u[3].p); - break; - } - case nRedir: { - int op = n->u[0].i; - fmtprint(f, "%D", op); - if (n->u[1].i != defaultfd(op)) - fmtprint(f, "[%d]", n->u[1].i); - fmtprint(f, "%T", n->u[2].p); - break; - } - case nNmpipe: { - int op = n->u[0].i; - fmtprint(f, "%D", op); - if (n->u[1].i != defaultfd(op)) - fmtprint(f, "[%d]", n->u[1].i); - fmtprint(f, "{%T}", n->u[2].p); - break; - } - } - return false; + bool dollar = f->flags & FMT_altform; + Node *n = va_arg(f->args, Node *); + + if (n == NULL) { + fmtprint(f, "()"); + return false; + } + switch (n->type) { + case nBang: fmtprint(f, "!%T", n->u[0].p); break; + case nCase: fmtprint(f, "case %T", n->u[0].p); break; + case nNowait: fmtprint(f, "%T&", n->u[0].p); break; + case nRmfn: fmtprint(f, "fn %T", n->u[0].p); break; + case nSubshell: fmtprint(f, "@ %T", n->u[0].p); break; + case nAndalso: fmtprint(f, "%T&&%T", n->u[0].p, n->u[1].p); break; + case nAssign: fmtprint(f, "%T=%T", n->u[0].p, n->u[1].p); break; + case nConcat: fmtprint(f, "%T^%T", n->u[0].p, n->u[1].p); break; + case nElse: fmtprint(f, "{%T}else %T", n->u[0].p, n->u[1].p); break; + case nNewfn: fmtprint(f, "fn %T {%T}", n->u[0].p, n->u[1].p); break; + case nIf: fmtprint(f, "if(%T)%T", n->u[0].p, n->u[1].p); break; + case nOrelse: fmtprint(f, "%T||%T", n->u[0].p, n->u[1].p); break; + case nArgs: fmtprint(f, "%T %T", n->u[0].p, n->u[1].p); break; + case nSwitch: fmtprint(f, "switch(%T){%T}", n->u[0].p, n->u[1].p); break; + case nMatch: fmtprint(f, "~ %T %T", n->u[0].p, n->u[1].p); break; + case nWhile: fmtprint(f, "while(%T)%T", n->u[0].p, n->u[1].p); break; + case nForin: fmtprint(f, "for(%T in %T)%T", n->u[0].p, n->u[1].p, n->u[2].p); break; + case nVarsub: fmtprint(f, "$%T(%T)", n->u[0].p, n->u[1].p); break; + case nWord: + fmtprint(f, n->u[2].i && quotep(n->u[0].s, dollar) ? + "%#S" : "%S", n->u[0].s); + break; + case nLappend: { + static bool inlist; + if (!inlist) { + inlist = true; + fmtprint(f, "(%T %T)", n->u[0].p, n->u[1].p); + inlist = false; + } else { + fmtprint(f, "%T %T", n->u[0].p, n->u[1].p); + } + break; + } + case nCount: case nFlat: case nVar: { + char *lp = "", *rp = ""; + Node *n0 = n->u[0].p; + + if (n0->type != nWord) + lp = "(", rp = ")"; + + switch (n->type) { + default: panic("this can't happen"); break; + case nCount: fmtprint(f, "$#%s%#T%s", lp, n0, rp); break; + case nFlat: fmtprint(f, "$^%s%#T%s", lp, n0, rp); break; + case nVar: fmtprint(f, "$%s%#T%s", lp, n0, rp); break; + } + break; + } + case nDup: + if (n->u[2].i != -1) + fmtprint(f, "%D[%d=%d]", n->u[0].i, n->u[1].i, n->u[2].i); + else + fmtprint(f, "%D[%d=]", n->u[0].i, n->u[1].i); + break; + case nBackq: { + Node *n0 = n->u[0].p, *n00; + if (n0 != NULL && n0->type == nVar + && (n00 = n0->u[0].p) != NULL && n00->type == nWord && streq(n00->u[0].s, "ifs")) + fmtprint(f, "`"); + else + fmtprint(f, "``%T", n0); + fmtprint(f, "{%T}", n->u[1].p); + break; + } + case nCbody: + case nBody: { + Node *n0 = n->u[0].p; + if (n0 != NULL) + fmtprint(f, "%T", n->u[0].p); + if (n->u[1].p != NULL) { + if (n0 != NULL && n0->type != nNowait) + fmtprint(f, ";"); + fmtprint(f, "%T", n->u[1].p); + } + break; + } + case nBrace: + fmtprint(f, "{%T}", n->u[0].p); + if (n->u[1].p != NULL) + fmtprint(f, "%T", n->u[1].p); + break; + case nEpilog: + case nPre: + fmtprint(f, "%T", n->u[0].p); + if (n->u[1].p != NULL) + fmtprint(f, " %T", n->u[1].p); + break; + case nPipe: { + int ofd = n->u[0].i, ifd = n->u[1].i; + fmtprint(f, "%T|", n->u[2].p); + if (ifd != 0) + fmtprint(f, "[%d=%d]", ofd, ifd); + else if (ofd != 1) + fmtprint(f, "[%d]", ofd); + fmtprint(f, "%T", n->u[3].p); + break; + } + case nRedir: { + int op = n->u[0].i; + fmtprint(f, "%D", op); + if (n->u[1].i != defaultfd(op)) + fmtprint(f, "[%d]", n->u[1].i); + fmtprint(f, "%T", n->u[2].p); + break; + } + case nNmpipe: { + int op = n->u[0].i; + fmtprint(f, "%D", op); + if (n->u[1].i != defaultfd(op)) + fmtprint(f, "[%d]", n->u[1].i); + fmtprint(f, "{%T}", n->u[2].p); + break; + } + } + return false; } /* convert a List to an array, for execve() */ extern char **list2array(List *s, bool print) { - char **argv, **av; - - if (print) - fprint(2, "%L\n", s, " "); - /* - Allocate 3 extra spots (2 for the fake execve & 1 for defaulting to - sh) and hide these from exec(). - */ - argv = av = (char **) nalloc((listnel(s) + 4) * sizeof *av) + 3; - while (s != NULL) { - *av++ = s->w; - s = s->n; - } - *av = NULL; - return argv; + char **argv, **av; + + if (print) + fprint(2, "%L\n", s, " "); + /* + Allocate 3 extra spots (2 for the fake execve & 1 for defaulting to + sh) and hide these from exec(). + */ + argv = av = (char **) nalloc((listnel(s) + 4) * sizeof *av) + 3; + while (s != NULL) { + *av++ = s->w; + s = s->n; + } + *av = NULL; + return argv; } /* figure out the name of a variable given an environment string. */ extern char *get_name(char *s) { - char *eq = strchr(s, '='); - char *r, *result; - int c; - - if (eq == NULL) - return NULL; - r = result = nalloc(eq - s + 1); - while (1) - switch (c = *s++) { - case '=': - *r++ = '\0'; - return result; + char *eq = strchr(s, '='); + char *r, *result; + int c; + + if (eq == NULL) + return NULL; + r = result = nalloc(eq - s + 1); + while (1) + switch (c = *s++) { + case '=': + *r++ = '\0'; + return result; #if PROTECT_ENV - case '_': - if (*s == '_') { - static const char hexchar[] = "0123456789abcdef"; - char *h1 = strchr(hexchar, s[1]); - char *h2 = strchr(hexchar, s[2]); - if (h1 != NULL && h2 != NULL) { - *r++ = ((h1 - hexchar) << 4) | (h2 - hexchar); - s += 3; - break; - } - } - /* FALLTHROUGH */ + case '_': + if (*s == '_') { + static const char hexchar[] = "0123456789abcdef"; + char *h1 = strchr(hexchar, s[1]); + char *h2 = strchr(hexchar, s[2]); + if (h1 != NULL && h2 != NULL) { + *r++ = ((h1 - hexchar) << 4) | (h2 - hexchar); + s += 3; + break; + } + } + /* FALLTHROUGH */ #endif - default: - *r++ = c; - break; - } + default: + *r++ = c; + break; + } } /* interpret a variable from environment. ^A separates list elements; @@ -231,47 +231,47 @@ extern char *get_name(char *s) { by anything other than ^A or ^B is preserved. */ extern List *parse_var(char *extdef) { - char *begin, *end, *from, *to; - int len; - List *first, *last, *new; - - first = last = NULL; - begin = strchr(extdef, '='); - assert(begin); /* guaranteed by initenv() */ - while (*begin) { - ++begin; - end = begin; - len = 0; - while (*end != ENV_SEP && *end != '\0') { - if (*end == ENV_ESC) { - ++end; - if (*end != ENV_SEP && *end != ENV_ESC) --end; - } - ++end; ++len; - } - new = enew(List); - if (last) - last->n = new; - else - first = new; - last = new; - new->w = ealloc(len + 1); - new->m = NULL; - new->n = NULL; - to = new->w; - for (from = begin; from < end; ++from) { - if (*from == ENV_ESC) { - ++from; - if (*from != ENV_SEP && *from != ENV_ESC) - --from; - } - *to = *from; - ++to; - } - *to = '\0'; - begin = end; - } - return first; + char *begin, *end, *from, *to; + int len; + List *first, *last, *new; + + first = last = NULL; + begin = strchr(extdef, '='); + assert(begin); /* guaranteed by initenv() */ + while (*begin) { + ++begin; + end = begin; + len = 0; + while (*end != ENV_SEP && *end != '\0') { + if (*end == ENV_ESC) { + ++end; + if (*end != ENV_SEP && *end != ENV_ESC) --end; + } + ++end; ++len; + } + new = enew(List); + if (last) + last->n = new; + else + first = new; + last = new; + new->w = ealloc(len + 1); + new->m = NULL; + new->n = NULL; + to = new->w; + for (from = begin; from < end; ++from) { + if (*from == ENV_ESC) { + ++from; + if (*from != ENV_SEP && *from != ENV_ESC) + --from; + } + *to = *from; + ++to; + } + *to = '\0'; + begin = end; + } + return first; } /* get an environment entry for a function and have rc parse it. */ @@ -279,107 +279,104 @@ extern List *parse_var(char *extdef) { #define PREFIX "fn x" #define PRELEN conststrlen(PREFIX) extern Node *parse_fn(char *extdef) { - Node *def; - char *s, old[PRELEN]; - if ((s = strchr(extdef, '=')) == NULL) - return NULL; - memcpy(old, s -= (PRELEN-1), PRELEN); - memcpy(s, PREFIX, PRELEN); - def = parseline(s); - memcpy(s, old, PRELEN); - return (def == NULL || def->type != nNewfn) ? NULL : def->u[1].p; + Node *def; + char *s, old[PRELEN]; + if ((s = strchr(extdef, '=')) == NULL) + return NULL; + memcpy(old, s -= (PRELEN-1), PRELEN); + memcpy(s, PREFIX, PRELEN); + def = parseline(s); + memcpy(s, old, PRELEN); + return (def == NULL || def->type != nNewfn) ? NULL : def->u[1].p; } static bool Aconv(Format *f, int ignore) { - char **a = va_arg(f->args, char **); - if (*a != NULL) { - fmtcat(f, *a); - while (*++a != NULL) - fmtprint(f, " %s", *a); - } - return false; + char **a = va_arg(f->args, char **); + if (*a != NULL) { + fmtcat(f, *a); + while (*++a != NULL) + fmtprint(f, " %s", *a); + } + return false; } /* %L -- print a list */ static bool Lconv(Format *f, int ignore) { - bool plain; - char *sep; - List *l, *n; - - plain = f->flags & FMT_leftside; - l = va_arg(f->args, List *); - sep = va_arg(f->args, char *); - if (l == NULL && (f->flags & FMT_leftside) == 0) - fmtprint(f, "()"); - else { - for (; l != NULL; l = n) { - n = l->n; - fmtprint(f, plain ? "%s" : "%-S", l->w); - if (n != NULL) fmtputc(f, *sep); - } - } - return false; + bool plain; + char *sep; + List *l, *n; + + plain = f->flags & FMT_leftside; + l = va_arg(f->args, List *); + sep = va_arg(f->args, char *); + if (l == NULL && (f->flags & FMT_leftside) == 0) + fmtprint(f, "()"); + else { + for (; l != NULL; l = n) { + n = l->n; + fmtprint(f, plain ? "%s" : "%-S", l->w); + if (n != NULL) fmtputc(f, *sep); + } + } + return false; } /* %W -- print a list for exporting */ static bool Wconv(Format *f, int ignore) { - List *l, *n; - - l = va_arg(f->args, List *); - for (; l != NULL; l = n) { - char c, *s; - - for (s = l->w; (c = *s) != '\0'; ++s) { - if (c == ENV_SEP || c == ENV_ESC) - fmtputc(f, ENV_ESC); - fmtputc(f, c); - } - n = l->n; - if (n != NULL) fmtputc(f, ENV_SEP); - } - return false; + List *l, *n; + + l = va_arg(f->args, List *); + for (; l != NULL; l = n) { + char c, *s; + + for (s = l->w; (c = *s) != '\0'; ++s) { + if (c == ENV_SEP || c == ENV_ESC) + fmtputc(f, ENV_ESC); + fmtputc(f, c); + } + n = l->n; + if (n != NULL) fmtputc(f, ENV_SEP); + } + return false; } -#define ISMETA(c) (c == '*' || c == '?' || c == '[') +#define ISMETA(c) (c == '*' || c == '?' || c == '[') static bool Sconv(Format *f, int ignore) { - int c; - unsigned char *s = va_arg(f->args, unsigned char *), *t = s; - bool quoted = (f->flags & FMT_altform) != 0; /* '#' */ - bool metaquote = (f->flags & FMT_leftside) != 0; /* '-' */ - if (*s == '\0') { - fmtprint(f, "''"); - return false; - } - if (!quoted) { - while ((c = *t++) != '\0') - if (nw[c] == 1 || (metaquote && ISMETA(c))) - goto quoteit; - fmtprint(f, "%s", s); - return false; - } + int c; + unsigned char *s = va_arg(f->args, unsigned char *), *t = s; + bool quoted = (f->flags & FMT_altform) != 0; /* '#' */ + bool metaquote = (f->flags & FMT_leftside) != 0; /* '-' */ + if (*s == '\0') { + fmtprint(f, "''"); + return false; + } + if (!quoted) { + while ((c = *t++) != '\0') + if (nw[c] == 1 || (metaquote && ISMETA(c))) + goto quoteit; + fmtprint(f, "%s", s); + return false; + } quoteit: - fmtputc(f, '\''); - while ((c = *s++) != '\0') { - fmtputc(f, c); - if (c == '\'') - fmtputc(f, '\''); - - } - fmtputc(f, '\''); - return false; + fmtputc(f, '\''); + while ((c = *s++) != '\0') { + fmtputc(f, c); + if (c == '\'') + fmtputc(f, '\''); + + } + fmtputc(f, '\''); + return false; } void initprint(void) { - fmtinstall('A', Aconv); - fmtinstall('L', Lconv); - fmtinstall('S', Sconv); - fmtinstall('T', Tconv); - fmtinstall('D', Dconv); - fmtinstall('W', Wconv); -#if PROTECT_ENV - fmtinstall('F', Fconv); -#else - fmtinstall('F', fmtinstall('s', NULL)); -#endif + fmtinstall('A', Aconv); + fmtinstall('L', Lconv); + fmtinstall('S', Sconv); + fmtinstall('T', Tconv); + fmtinstall('D', Dconv); + fmtinstall('W', Wconv); + fmtinstall('F', Fconv); + fmtinstall('F', fmtinstall('s', NULL)); } diff --git a/glob.c b/glob.c index dcb7b2a..821191d 100644 --- a/glob.c +++ b/glob.c @@ -17,21 +17,21 @@ static List *sort(List *); */ extern bool lmatch(List *s, List *p) { - List *q; - if (s == NULL) { - if (p == NULL) /* null matches null */ - return true; - for (; p != NULL; p = p->n) /* one or more stars match null */ - if (strspn(p->w, "*") == strlen(p->w) && - p->m != NULL && strlen(p->m) == strlen(p->w)) - return true; - return false; - } - for (; s != NULL; s = s->n) - for (q = p; q != NULL; q = q->n) - if (match(q->w, q->m, s->w)) - return true; - return false; + List *q; + if (s == NULL) { + if (p == NULL) /* null matches null */ + return true; + for (; p != NULL; p = p->n) /* one or more stars match null */ + if (strspn(p->w, "*") == strlen(p->w) && + p->m != NULL && strlen(p->m) == strlen(p->w)) + return true; + return false; + } + for (; s != NULL; s = s->n) + for (q = p; q != NULL; q = q->n) + if (match(q->w, q->m, s->w)) + return true; + return false; } /* @@ -40,90 +40,90 @@ extern bool lmatch(List *s, List *p) { */ extern List *glob(List *s) { - List *top, *r; - bool meta; - for (r = s, meta = false; r != NULL; r = r->n) - if (r->m != NULL) - meta = true; - if (!meta) - return s; /* don't copy lists with no metacharacters in them */ - for (top = r = NULL; s != NULL; s = s->n) { - if (s->m == NULL) { /* no metacharacters; just tack on to the return list */ - if (top == NULL) - top = r = nnew(List); - else - r = r->n = nnew(List); - r->w = s->w; - } else { - if (top == NULL) - top = r = sort(doglob(s->w, s->m)); - else - r->n = sort(doglob(s->w, s->m)); - while (r->n != NULL) - r = r->n; - } - } - r->n = NULL; - return top; + List *top, *r; + bool meta; + for (r = s, meta = false; r != NULL; r = r->n) + if (r->m != NULL) + meta = true; + if (!meta) + return s; /* don't copy lists with no metacharacters in them */ + for (top = r = NULL; s != NULL; s = s->n) { + if (s->m == NULL) { /* no metacharacters; just tack on to the return list */ + if (top == NULL) + top = r = nnew(List); + else + r = r->n = nnew(List); + r->w = s->w; + } else { + if (top == NULL) + top = r = sort(doglob(s->w, s->m)); + else + r->n = sort(doglob(s->w, s->m)); + while (r->n != NULL) + r = r->n; + } + } + r->n = NULL; + return top; } /* Matches a pattern p against the contents of directory d */ static List *dmatch(char *d, char *p, char *m) { - bool matched; - List *top, *r; - static DIR *dirp; - static struct dirent *dp; - static struct stat s; - int i; - - /* - return a match if there are no metacharacters; allows globbing through - directories with no read permission. make sure the file exists, though. - */ - matched = true; - if (m != NULL) - for (i = 0; p[i] != '\0'; i++) - if (m[i]) { - matched = false; - break; - } - - if (matched) { - char *path = nprint("%s/%s", d, p); - if (lstat(path, &s) < 0) - return NULL; - r = nnew(List); - r->w = ncpy(p); - r->m = NULL; - r->n = NULL; - return r; - } - - top = r = NULL; - if (*d == '\0') d = "/"; - if ((dirp = opendir(d)) == NULL) - return NULL; - /* opendir succeeds on regular files on some systems, so the stat() call is necessary (sigh) */ - if (stat(d, &s) < 0 || (s.st_mode & S_IFMT) != S_IFDIR) { - closedir(dirp); - return NULL; - } - while ((dp = readdir(dirp)) != NULL) - if ((*dp->d_name != '.' || *p == '.') && match(p, m, dp->d_name)) { /* match ^. explicitly */ - matched = true; - if (top == NULL) - top = r = nnew(List); - else - r = r->n = nnew(List); - r->w = ncpy(dp->d_name); - r->m = NULL; - } - closedir(dirp); - if (!matched) - return NULL; - r->n = NULL; - return top; + bool matched; + List *top, *r; + static DIR *dirp; + static struct dirent *dp; + static struct stat s; + int i; + + /* + return a match if there are no metacharacters; allows globbing through + directories with no read permission. make sure the file exists, though. + */ + matched = true; + if (m != NULL) + for (i = 0; p[i] != '\0'; i++) + if (m[i]) { + matched = false; + break; + } + + if (matched) { + char *path = nprint("%s/%s", d, p); + if (lstat(path, &s) < 0) + return NULL; + r = nnew(List); + r->w = ncpy(p); + r->m = NULL; + r->n = NULL; + return r; + } + + top = r = NULL; + if (*d == '\0') d = "/"; + if ((dirp = opendir(d)) == NULL) + return NULL; + /* opendir succeeds on regular files on some systems, so the stat() call is necessary (sigh) */ + if (stat(d, &s) < 0 || (s.st_mode & S_IFMT) != S_IFDIR) { + closedir(dirp); + return NULL; + } + while ((dp = readdir(dirp)) != NULL) + if ((*dp->d_name != '.' || *p == '.') && match(p, m, dp->d_name)) { /* match ^. explicitly */ + matched = true; + if (top == NULL) + top = r = nnew(List); + else + r = r->n = nnew(List); + r->w = ncpy(dp->d_name); + r->m = NULL; + } + closedir(dirp); + if (!matched) + return NULL; + r->n = NULL; + return top; } /* @@ -134,36 +134,36 @@ static List *dmatch(char *d, char *p, char *m) { */ static List *lglob(List *s, char *p, char *m, size_t slashcount) { - List *q, *r, *top, foo; - static struct { - List l; - size_t size; - } slash; - if (slashcount+1 > slash.size) { - slash.size = 2*(slashcount+1); - slash.l.w = erealloc(slash.l.w, slash.size); - } - slash.l.w[slashcount] = '\0'; - while (slashcount > 0) - slash.l.w[--slashcount] = '/'; - for (top = r = NULL; s != NULL; s = s->n) { - q = dmatch(s->w, p, m); - if (q != NULL) { - foo.w = s->w; - foo.m = NULL; - foo.n = NULL; - if (!(s->w[0] == '/' && s->w[1] == '\0')) /* need to separate */ - q = concat(&slash.l, q); /* dir/name with slash */ - q = concat(&foo, q); - if (r == NULL) - top = r = q; - else - r->n = q; - while (r->n != NULL) - r = r->n; - } - } - return top; + List *q, *r, *top, foo; + static struct { + List l; + size_t size; + } slash; + if (slashcount+1 > slash.size) { + slash.size = 2*(slashcount+1); + slash.l.w = erealloc(slash.l.w, slash.size); + } + slash.l.w[slashcount] = '\0'; + while (slashcount > 0) + slash.l.w[--slashcount] = '/'; + for (top = r = NULL; s != NULL; s = s->n) { + q = dmatch(s->w, p, m); + if (q != NULL) { + foo.w = s->w; + foo.m = NULL; + foo.n = NULL; + if (!(s->w[0] == '/' && s->w[1] == '\0')) /* need to separate */ + q = concat(&slash.l, q); /* dir/name with slash */ + q = concat(&foo, q); + if (r == NULL) + top = r = q; + else + r->n = q; + while (r->n != NULL) + r = r->n; + } + } + return top; } /* @@ -172,79 +172,79 @@ static List *lglob(List *s, char *p, char *m, size_t slashcount) { */ static List *doglob(char *w, char *m) { - static char *dir = NULL, *pattern = NULL, *metadir = NULL, *metapattern = NULL; - static size_t dsize = 0; - char *d, *p, *md, *mp; - size_t psize; - char *s = w; - List firstdir; - List *matched; - if ((psize = strlen(w) + 1) > dsize || dir == NULL) { - efree(dir); efree(pattern); efree(metadir); efree(metapattern); - dir = ealloc(psize); - pattern = ealloc(psize); - metadir = ealloc(psize); - metapattern = ealloc(psize); - dsize = psize; - } - d = dir; - p = pattern; - md = metadir; - mp = metapattern; - while (*s != '/' && *s != '\0') { - *d++ = *s++; /* get first directory component */ - *md++ = *m++; - } - *d = '\0'; - /* - Special case: no slashes in the pattern, i.e., open the current directory. - Remember that w cannot consist of slashes alone (the other way *s could be - zero) since doglob gets called iff there's a metacharacter to be matched - */ - if (*s == '\0') { - matched = dmatch(".", dir, metadir); - goto end; - } - if (*w == '/') { - firstdir.w = dir; - firstdir.m = metadir; - firstdir.n = NULL; - matched = &firstdir; - } else { - /* - we must glob against current directory, - since the first character is not a slash. - */ - matched = dmatch(".", dir, metadir); - } - do { - size_t slashcount; - sigchk(); - for (slashcount = 0; *s == '/'; s++, m++) - slashcount++; /* skip slashes */ - while (*s != '/' && *s != '\0') - *p++ = *s++, *mp++ = *m++; /* get pattern */ - *p = '\0'; - matched = lglob(matched, pattern, metapattern, slashcount); - p = pattern, mp = metapattern; - } while (*s != '\0'); -end: if (matched == NULL) { - matched = nnew(List); - matched->w = w; - matched->m = NULL; - matched->n = NULL; - } - return matched; + static char *dir = NULL, *pattern = NULL, *metadir = NULL, *metapattern = NULL; + static size_t dsize = 0; + char *d, *p, *md, *mp; + size_t psize; + char *s = w; + List firstdir; + List *matched; + if ((psize = strlen(w) + 1) > dsize || dir == NULL) { + efree(dir); efree(pattern); efree(metadir); efree(metapattern); + dir = ealloc(psize); + pattern = ealloc(psize); + metadir = ealloc(psize); + metapattern = ealloc(psize); + dsize = psize; + } + d = dir; + p = pattern; + md = metadir; + mp = metapattern; + while (*s != '/' && *s != '\0') { + *d++ = *s++; /* get first directory component */ + *md++ = *m++; + } + *d = '\0'; + /* + Special case: no slashes in the pattern, i.e., open the current directory. + Remember that w cannot consist of slashes alone (the other way *s could be + zero) since doglob gets called iff there's a metacharacter to be matched + */ + if (*s == '\0') { + matched = dmatch(".", dir, metadir); + goto end; + } + if (*w == '/') { + firstdir.w = dir; + firstdir.m = metadir; + firstdir.n = NULL; + matched = &firstdir; + } else { + /* + we must glob against current directory, + since the first character is not a slash. + */ + matched = dmatch(".", dir, metadir); + } + do { + size_t slashcount; + sigchk(); + for (slashcount = 0; *s == '/'; s++, m++) + slashcount++; /* skip slashes */ + while (*s != '/' && *s != '\0') + *p++ = *s++, *mp++ = *m++; /* get pattern */ + *p = '\0'; + matched = lglob(matched, pattern, metapattern, slashcount); + p = pattern, mp = metapattern; + } while (*s != '\0'); +end: if (matched == NULL) { + matched = nnew(List); + matched->w = w; + matched->m = NULL; + matched->n = NULL; + } + return matched; } static List *sort(List *s) { - size_t nel = listnel(s); - if (nel > 1) { - char **a; - List *t; - qsort(a = list2array(s, false), nel, sizeof(char *), starstrcmp); - for (t = s; t != NULL; t = t->n) - t->w = *a++; - } - return s; + size_t nel = listnel(s); + if (nel > 1) { + char **a; + List *t; + qsort(a = list2array(s, false), nel, sizeof(char *), starstrcmp); + for (t = s; t != NULL; t = t->n) + t->w = *a++; + } + return s; } diff --git a/glom.c b/glom.c index 6f3a65c..2c632f1 100644 --- a/glom.c +++ b/glom.c @@ -10,14 +10,14 @@ static List *mkcmdarg(Node *); Rq *redirq = NULL; extern List *word(char *w, char *m) { - List *s = NULL; - if (w != NULL) { - s = nnew(List); - s->w = w; - s->m = m; - s->n = NULL; - } - return s; + List *s = NULL; + if (w != NULL) { + s = nnew(List); + s->w = w; + s->m = m; + s->n = NULL; + } + return s; } /* @@ -26,137 +26,137 @@ extern List *word(char *w, char *m) { */ extern List *append(List *s1, List *s2) { - List *r, *top; - if (s1 == NULL) - return s2; - if (s2 == NULL) - return s1; - for (r = top = nnew(List); 1; r = r->n = nnew(List)) { - r->w = s1->w; - r->m = s1->m; - if ((s1 = s1->n) == NULL) - break; - } - r->n = s2; - return top; + List *r, *top; + if (s1 == NULL) + return s2; + if (s2 == NULL) + return s1; + for (r = top = nnew(List); 1; r = r->n = nnew(List)) { + r->w = s1->w; + r->m = s1->m; + if ((s1 = s1->n) == NULL) + break; + } + r->n = s2; + return top; } extern List *concat(List *s1, List *s2) { - int n1, n2; - List *r, *top; - if (s1 == NULL) - return s2; - if (s2 == NULL) - return s1; - if ((n1 = listnel(s1)) != (n2 = listnel(s2)) && n1 != 1 && n2 != 1) - rc_error("bad concatenation"); - for (r = top = nnew(List); 1; r = r->n = nnew(List)) { - size_t x = strlen(s1->w); - size_t y = strlen(s2->w); - size_t z = x + y + 1; - r->w = nalloc(z); - strcpy(r->w, s1->w); - strcat(r->w, s2->w); - if (s1->m == NULL && s2->m == NULL) { - r->m = NULL; - } else { - r->m = nalloc(z); - if (s1->m == NULL) - memzero(r->m, x); - else - memcpy(r->m, s1->m, x); - if (s2->m == NULL) - memzero(&r->m[x], y); - else - memcpy(&r->m[x], s2->m, y); - r->m[z] = 0; - } - if (n1 > 1) - s1 = s1->n; - if (n2 > 1) - s2 = s2->n; - if (s1 == NULL || s2 == NULL || (n1 == 1 && n2 == 1)) - break; - } - r->n = NULL; - return top; + int n1, n2; + List *r, *top; + if (s1 == NULL) + return s2; + if (s2 == NULL) + return s1; + if ((n1 = listnel(s1)) != (n2 = listnel(s2)) && n1 != 1 && n2 != 1) + rc_error("bad concatenation"); + for (r = top = nnew(List); 1; r = r->n = nnew(List)) { + size_t x = strlen(s1->w); + size_t y = strlen(s2->w); + size_t z = x + y + 1; + r->w = nalloc(z); + strcpy(r->w, s1->w); + strcat(r->w, s2->w); + if (s1->m == NULL && s2->m == NULL) { + r->m = NULL; + } else { + r->m = nalloc(z); + if (s1->m == NULL) + memzero(r->m, x); + else + memcpy(r->m, s1->m, x); + if (s2->m == NULL) + memzero(&r->m[x], y); + else + memcpy(&r->m[x], s2->m, y); + r->m[z] = 0; + } + if (n1 > 1) + s1 = s1->n; + if (n2 > 1) + s2 = s2->n; + if (s1 == NULL || s2 == NULL || (n1 == 1 && n2 == 1)) + break; + } + r->n = NULL; + return top; } extern List *varsub(List *var, List *subs) { - List *r, *top; - int n = listnel(var); - for (top = r = NULL; subs != NULL; subs = subs->n) { - int i = a2u(subs->w); - if (i < 1) - rc_error("bad subscript"); - if (i <= n) { - List *sub = var; - while (--i) - sub = sub->n; /* loop until sub == var(i) */ - if (top == NULL) - top = r = nnew(List); - else - r = r->n = nnew(List); - r->w = sub->w; - r->m = sub->m; - } - } - if (top != NULL) - r->n = NULL; - return top; + List *r, *top; + int n = listnel(var); + for (top = r = NULL; subs != NULL; subs = subs->n) { + int i = a2u(subs->w); + if (i < 1) + rc_error("bad subscript"); + if (i <= n) { + List *sub = var; + while (--i) + sub = sub->n; /* loop until sub == var(i) */ + if (top == NULL) + top = r = nnew(List); + else + r = r->n = nnew(List); + r->w = sub->w; + r->m = sub->m; + } + } + if (top != NULL) + r->n = NULL; + return top; } extern List *flatten(List *s) { - List *r; - size_t step; - char *f; - if (s == NULL || s->n == NULL) - return s; - r = nnew(List); - f = r->w = nalloc(listlen(s) + 1); - r->m = NULL; /* flattened lists come from variables, so no meta */ - r->n = NULL; - strcpy(f, s->w); - f += strlen(s->w); - do { - *f++ = ' '; - s = s->n; - step = strlen(s->w); - memcpy(f, s->w, step); - f += step; - } while (s->n != NULL); - *f = '\0'; - return r; + List *r; + size_t step; + char *f; + if (s == NULL || s->n == NULL) + return s; + r = nnew(List); + f = r->w = nalloc(listlen(s) + 1); + r->m = NULL; /* flattened lists come from variables, so no meta */ + r->n = NULL; + strcpy(f, s->w); + f += strlen(s->w); + do { + *f++ = ' '; + s = s->n; + step = strlen(s->w); + memcpy(f, s->w, step); + f += step; + } while (s->n != NULL); + *f = '\0'; + return r; } static List *count(List *l) { - List *s = nnew(List); - s->w = nprint("%d", listnel(l)); - s->n = NULL; - s->m = NULL; - return s; + List *s = nnew(List); + s->w = nprint("%d", listnel(l)); + s->n = NULL; + s->m = NULL; + return s; } extern void assign(List *s1, List *s2, bool stack) { - List *val = s2; - if (s1 == NULL) - rc_error("null variable name"); - if (s1->n != NULL) - rc_error("multi-word variable name"); - if (*s1->w == '\0') - rc_error("zero-length variable name"); - if (a2u(s1->w) != -1) - rc_error("numeric variable name"); - if (strchr(s1->w, '=') != NULL) - rc_error("'=' in variable name"); - if (*s1->w == '*' && s1->w[1] == '\0') - val = append(varlookup("0"), s2); /* preserve $0 when * is assigned explicitly */ - if (s2 != NULL || stack) { - varassign(s1->w, val, stack); - alias(s1->w, varlookup(s1->w), stack); - } else { - varrm(s1->w, stack); - } + List *val = s2; + if (s1 == NULL) + rc_error("null variable name"); + if (s1->n != NULL) + rc_error("multi-word variable name"); + if (*s1->w == '\0') + rc_error("zero-length variable name"); + if (a2u(s1->w) != -1) + rc_error("numeric variable name"); + if (strchr(s1->w, '=') != NULL) + rc_error("'=' in variable name"); + if (*s1->w == '*' && s1->w[1] == '\0') + val = append(varlookup("0"), s2); /* preserve $0 when * is assigned explicitly */ + if (s2 != NULL || stack) { + varassign(s1->w, val, stack); + alias(s1->w, varlookup(s1->w), stack); + } else { + varrm(s1->w, stack); + } } /* @@ -164,215 +164,215 @@ extern void assign(List *s1, List *s2, bool stack) { who could not stand the incompetence of my own backquote implementation. */ -#define BUFSIZE ((size_t) 1000) +#define BUFSIZE ((size_t) 1000) static List *bqinput(List *ifs, int fd) { - char *end, *bufend, *s; - List *r, *top, *prev; - size_t remain, bufsize; - char isifs[256]; - int n, state; /* a simple FSA is used to read in data */ + char *end, *bufend, *s; + List *r, *top, *prev; + size_t remain, bufsize; + char isifs[256]; + int n, state; /* a simple FSA is used to read in data */ - memzero(isifs, sizeof isifs); - for (isifs['\0'] = true; ifs != NULL; ifs = ifs->n) - for (s = ifs->w; *s != '\0'; s++) - isifs[*(unsigned char *)s] = true; - remain = bufsize = BUFSIZE; - top = r = nnew(List); - r->w = end = nalloc(bufsize + 1); - r->m = NULL; - state = 0; - prev = NULL; + memzero(isifs, sizeof isifs); + for (isifs['\0'] = true; ifs != NULL; ifs = ifs->n) + for (s = ifs->w; *s != '\0'; s++) + isifs[*(unsigned char *)s] = true; + remain = bufsize = BUFSIZE; + top = r = nnew(List); + r->w = end = nalloc(bufsize + 1); + r->m = NULL; + state = 0; + prev = NULL; - while (1) { - if (remain == 0) { /* is the string bigger than the buffer? */ - size_t m = end - r->w; - char *buf; - while (bufsize < m + BUFSIZE) - bufsize *= 2; - buf = nalloc(bufsize + 1); - memcpy(buf, r->w, m); - r->w = buf; - end = &buf[m]; - remain = bufsize - m; - } - if ((n = read(fd, end, remain)) <= 0) { - if (n == 0) - /* break */ break; - else if (errno == EINTR) - return NULL; /* interrupted, wait for subproc */ - else { - uerror("backquote read"); - rc_error(NULL); - } - } - remain -= n; - for (bufend = &end[n]; end < bufend; end++) - if (state == 0) { - if (!isifs[*(unsigned char *)end]) { - state = 1; - r->w = end; - r->m = NULL; - } - } else { - if (isifs[*(unsigned char *)end]) { - state = 0; - *end = '\0'; - prev = r; - r = r->n = nnew(List); - r->w = end+1; - r->m = NULL; - } - } - } - if (state == 1) { /* terminate last string */ - *end = '\0'; - r->n = NULL; - } else { - if (prev == NULL) /* no input at all? */ - top = NULL; - else - prev->n = NULL; /* else terminate list */ - } - return top; + while (1) { + if (remain == 0) { /* is the string bigger than the buffer? */ + size_t m = end - r->w; + char *buf; + while (bufsize < m + BUFSIZE) + bufsize *= 2; + buf = nalloc(bufsize + 1); + memcpy(buf, r->w, m); + r->w = buf; + end = &buf[m]; + remain = bufsize - m; + } + if ((n = read(fd, end, remain)) <= 0) { + if (n == 0) + /* break */ break; + else if (errno == EINTR) + return NULL; /* interrupted, wait for subproc */ + else { + uerror("backquote read"); + rc_error(NULL); + } + } + remain -= n; + for (bufend = &end[n]; end < bufend; end++) + if (state == 0) { + if (!isifs[*(unsigned char *)end]) { + state = 1; + r->w = end; + r->m = NULL; + } + } else { + if (isifs[*(unsigned char *)end]) { + state = 0; + *end = '\0'; + prev = r; + r = r->n = nnew(List); + r->w = end+1; + r->m = NULL; + } + } + } + if (state == 1) { /* terminate last string */ + *end = '\0'; + r->n = NULL; + } else { + if (prev == NULL) /* no input at all? */ + top = NULL; + else + prev->n = NULL; /* else terminate list */ + } + return top; } static List *backq(Node *ifs, Node *n) { - int p[2], sp; - pid_t pid; - List *bq; - if (n == NULL) - return NULL; - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if ((pid = rc_fork()) == 0) { - mvfd(p[1], 1); - close(p[0]); - redirq = NULL; - walk(n, false); - exit(getstatus()); - } - close(p[1]); - bq = bqinput(glom(ifs), p[0]); - close(p[0]); - rc_wait4(pid, &sp, true); - statprint(-1, sp); - varassign("bqstatus", word(strstatus(sp), NULL), false); - sigchk(); - return bq; + int p[2], sp; + pid_t pid; + List *bq; + if (n == NULL) + return NULL; + if (pipe(p) < 0) { + uerror("pipe"); + rc_error(NULL); + } + if ((pid = rc_fork()) == 0) { + mvfd(p[1], 1); + close(p[0]); + redirq = NULL; + walk(n, false); + exit(getstatus()); + } + close(p[1]); + bq = bqinput(glom(ifs), p[0]); + close(p[0]); + rc_wait4(pid, &sp, true); + statprint(-1, sp); + varassign("bqstatus", word(strstatus(sp), NULL), false); + sigchk(); + return bq; } extern void qredir(Node *n) { - Rq *next; - if (redirq == NULL) { - next = redirq = nnew(Rq); - } else { - for (next = redirq; next->n != NULL; next = next->n) - ; - next->n = nnew(Rq); - next = next->n; - } - next->r = n; - next->n = NULL; + Rq *next; + if (redirq == NULL) { + next = redirq = nnew(Rq); + } else { + for (next = redirq; next->n != NULL; next = next->n) + ; + next->n = nnew(Rq); + next = next->n; + } + next->r = n; + next->n = NULL; } static List *mkcmdarg(Node *n) { - int fd; - char *name; - Edata efifo; - Estack *e = enew(Estack); - List *ret = nnew(List); - static int fifonumber = 0; + int fd; + char *name; + Edata efifo; + Estack *e = enew(Estack); + List *ret = nnew(List); + static int fifonumber = 0; - name = nprint("/tmp/rc%d.%d", getpid(), fifonumber++); - if (mkfifo(name, 0666) < 0) { - uerror("mkfifo"); - return NULL; - } - if (rc_fork() == 0) { - setsigdefaults(false); - fd = rc_open(name, (n->u[0].i != rFrom) ? rFrom : rCreate); /* stupid hack */ - if (fd < 0) { - uerror("open"); - exit(1); - } - if (mvfd(fd, (n->u[0].i == rFrom)) < 0) /* same stupid hack */ - exit(1); - redirq = NULL; - walk(n->u[2].p, false); - exit(getstatus()); - } - efifo.name = name; - except(eFifo, efifo, e); - ret->w = name; - ret->m = NULL; - ret->n = NULL; - return ret; + name = nprint("/tmp/rc%d.%d", getpid(), fifonumber++); + if (mkfifo(name, 0666) < 0) { + uerror("mkfifo"); + return NULL; + } + if (rc_fork() == 0) { + setsigdefaults(false); + fd = rc_open(name, (n->u[0].i != rFrom) ? rFrom : rCreate); /* stupid hack */ + if (fd < 0) { + uerror("open"); + exit(1); + } + if (mvfd(fd, (n->u[0].i == rFrom)) < 0) /* same stupid hack */ + exit(1); + redirq = NULL; + walk(n->u[2].p, false); + exit(getstatus()); + } + efifo.name = name; + except(eFifo, efifo, e); + ret->w = name; + ret->m = NULL; + ret->n = NULL; + return ret; } extern List *glom(Node *n) { - List *v, *head, *tail; - Node *words; - if (n == NULL) - return NULL; - switch (n->type) { - case nArgs: - case nLappend: - words = n->u[0].p; - tail = NULL; - while (words != NULL && (words->type == nArgs || words->type == nLappend)) { - if (words->u[1].p != NULL && words->u[1].p->type != nWord) - break; - head = glom(words->u[1].p); - if (head != NULL) { - head->n = tail; - tail = head; - } - words = words->u[0].p; - } - v = append(glom(words), tail); /* force left to right evaluation */ - return append(v, glom(n->u[1].p)); - case nBackq: - return backq(n->u[0].p, n->u[1].p); - case nConcat: - head = glom(n->u[0].p); /* force left-to-right evaluation */ - return concat(head, glom(n->u[1].p)); - case nDup: - case nRedir: - qredir(n); - return NULL; - case nWord: - return word(n->u[0].s, n->u[1].s); - case nNmpipe: - return mkcmdarg(n); - default: - /* - The next four operations depend on the left-child of glom - to be a variable name. Therefore the variable is looked up - here. - */ - if ((v = glom(n->u[0].p)) == NULL) - rc_error("null variable name"); - if (v->n != NULL) - rc_error("multi-word variable name"); - if (*v->w == '\0') - rc_error("zero-length variable name"); - v = (*v->w == '*' && v->w[1] == '\0') ? varlookup(v->w)->n : varlookup(v->w); - switch (n->type) { - default: - panic("unexpected node in glom"); - exit(1); - /* NOTREACHED */ - case nCount: - return count(v); - case nFlat: - return flatten(v); - case nVar: - return v; - case nVarsub: - return varsub(v, glom(n->u[1].p)); - } - } + List *v, *head, *tail; + Node *words; + if (n == NULL) + return NULL; + switch (n->type) { + case nArgs: + case nLappend: + words = n->u[0].p; + tail = NULL; + while (words != NULL && (words->type == nArgs || words->type == nLappend)) { + if (words->u[1].p != NULL && words->u[1].p->type != nWord) + break; + head = glom(words->u[1].p); + if (head != NULL) { + head->n = tail; + tail = head; + } + words = words->u[0].p; + } + v = append(glom(words), tail); /* force left to right evaluation */ + return append(v, glom(n->u[1].p)); + case nBackq: + return backq(n->u[0].p, n->u[1].p); + case nConcat: + head = glom(n->u[0].p); /* force left-to-right evaluation */ + return concat(head, glom(n->u[1].p)); + case nDup: + case nRedir: + qredir(n); + return NULL; + case nWord: + return word(n->u[0].s, n->u[1].s); + case nNmpipe: + return mkcmdarg(n); + default: + /* + The next four operations depend on the left-child of glom + to be a variable name. Therefore the variable is looked up + here. + */ + if ((v = glom(n->u[0].p)) == NULL) + rc_error("null variable name"); + if (v->n != NULL) + rc_error("multi-word variable name"); + if (*v->w == '\0') + rc_error("zero-length variable name"); + v = (*v->w == '*' && v->w[1] == '\0') ? varlookup(v->w)->n : varlookup(v->w); + switch (n->type) { + default: + panic("unexpected node in glom"); + exit(1); + /* NOTREACHED */ + case nCount: + return count(v); + case nFlat: + return flatten(v); + case nVar: + return v; + case nVarsub: + return varsub(v, glom(n->u[1].p)); + } + } } diff --git a/hash.c b/hash.c index 2f3b3b9..ac064ef 100644 --- a/hash.c +++ b/hash.c @@ -28,14 +28,14 @@ static char *dead = ""; #define HASHSIZE 64 /* rc was debugged with HASHSIZE == 2; 64 is about right for normal use */ extern void inithash() { - Htab *fpp, *vpp; - int i; - fp = ealloc(sizeof(Htab) * HASHSIZE); - vp = ealloc(sizeof(Htab) * HASHSIZE); - fused = vused = 0; - fsize = vsize = HASHSIZE; - for (vpp = vp, fpp = fp, i = 0; i < HASHSIZE; i++, vpp++, fpp++) - vpp->name = fpp->name = NULL; + Htab *fpp, *vpp; + int i; + fp = ealloc(sizeof(Htab) * HASHSIZE); + vp = ealloc(sizeof(Htab) * HASHSIZE); + fused = vused = 0; + fsize = vsize = HASHSIZE; + for (vpp = vp, fpp = fp, i = 0; i < HASHSIZE; i++, vpp++, fpp++) + vpp->name = fpp->name = NULL; } #define ADV() {if ((c = *s++) == '\0') break;} @@ -43,273 +43,273 @@ extern void inithash() { /* hash function courtesy of paul haahr */ static int hash(char *s, int size) { - int c, n = 0; - while (1) { - ADV(); - n += (c << 17) ^ (c << 11) ^ (c << 5) ^ (c >> 1); - ADV(); - n ^= (c << 14) + (c << 7) + (c << 4) + c; - ADV(); - n ^= (~c << 11) | ((c << 3) ^ (c >> 1)); - ADV(); - n -= (c << 16) | (c << 9) | (c << 2) | (c & 3); - } - if (n < 0) - n = ~n; - return n & (size - 1); /* need power of 2 size */ + int c, n = 0; + while (1) { + ADV(); + n += (c << 17) ^ (c << 11) ^ (c << 5) ^ (c >> 1); + ADV(); + n ^= (c << 14) + (c << 7) + (c << 4) + c; + ADV(); + n ^= (~c << 11) | ((c << 3) ^ (c >> 1)); + ADV(); + n -= (c << 16) | (c << 9) | (c << 2) | (c & 3); + } + if (n < 0) + n = ~n; + return n & (size - 1); /* need power of 2 size */ } static bool rehash(Htab *ht) { - int i, j, size; - int newsize, newused; - Htab *newhtab; - if (ht == fp) { - if (fsize > 2 * fused) - return false; - size = fsize; - } else { - if (vsize > 2 * vused) - return false; - size = vsize; - } - newsize = 2 * size; - newhtab = ealloc(newsize * sizeof(Htab)); - for (i = 0; i < newsize; i++) - newhtab[i].name = NULL; - for (i = newused = 0; i < size; i++) - if (ht[i].name != NULL && ht[i].name != dead) { - newused++; - j = hash(ht[i].name, newsize); - while (newhtab[j].name != NULL) { - j++; - j &= (newsize - 1); - } - newhtab[j].name = ht[i].name; - newhtab[j].p = ht[i].p; - } - if (ht == fp) { - fused = newused; - fp = newhtab; - fsize = newsize; - } else { - vused = newused; - vp = newhtab; - vsize = newsize; - } - efree(ht); - return true; + int i, j, size; + int newsize, newused; + Htab *newhtab; + if (ht == fp) { + if (fsize > 2 * fused) + return false; + size = fsize; + } else { + if (vsize > 2 * vused) + return false; + size = vsize; + } + newsize = 2 * size; + newhtab = ealloc(newsize * sizeof(Htab)); + for (i = 0; i < newsize; i++) + newhtab[i].name = NULL; + for (i = newused = 0; i < size; i++) + if (ht[i].name != NULL && ht[i].name != dead) { + newused++; + j = hash(ht[i].name, newsize); + while (newhtab[j].name != NULL) { + j++; + j &= (newsize - 1); + } + newhtab[j].name = ht[i].name; + newhtab[j].p = ht[i].p; + } + if (ht == fp) { + fused = newused; + fp = newhtab; + fsize = newsize; + } else { + vused = newused; + vp = newhtab; + vsize = newsize; + } + efree(ht); + return true; } #define varfind(s) find(s, vp, vsize) #define fnfind(s) find(s, fp, fsize) static int find(char *s, Htab *ht, int size) { - int h = hash(s, size); - while (ht[h].name != NULL && !streq(ht[h].name, s)) { - h++; - h &= size - 1; - } - return h; + int h = hash(s, size); + while (ht[h].name != NULL && !streq(ht[h].name, s)) { + h++; + h &= size - 1; + } + return h; } extern void *lookup(char *s, Htab *ht) { - int h = find(s, ht, ht == fp ? fsize : vsize); - return (ht[h].name == NULL) ? NULL : ht[h].p; + int h = find(s, ht, ht == fp ? fsize : vsize); + return (ht[h].name == NULL) ? NULL : ht[h].p; } extern rc_Function *get_fn_place(char *s) { - int h = fnfind(s); - env_dirty = true; - if (fp[h].name == NULL) { - if (rehash(fp)) - h = fnfind(s); - fused++; - fp[h].name = ecpy(s); - fp[h].p = enew(rc_Function); - } else - free_fn(fp[h].p); - return fp[h].p; + int h = fnfind(s); + env_dirty = true; + if (fp[h].name == NULL) { + if (rehash(fp)) + h = fnfind(s); + fused++; + fp[h].name = ecpy(s); + fp[h].p = enew(rc_Function); + } else + free_fn(fp[h].p); + return fp[h].p; } extern Variable *get_var_place(char *s, bool stack) { - Variable *new; - int h = varfind(s); + Variable *new; + int h = varfind(s); - env_dirty = true; + env_dirty = true; - if (vp[h].name == NULL) { - if (rehash(vp)) - h = varfind(s); - vused++; - vp[h].name = ecpy(s); - vp[h].p = enew(Variable); - ((Variable *)vp[h].p)->n = NULL; - return vp[h].p; - } else { - if (stack) { /* increase the stack by 1 */ - new = enew(Variable); - new->n = vp[h].p; - return vp[h].p = new; - } else { /* trample the top of the stack */ - new = vp[h].p; - efree(new->extdef); - listfree(new->def); - return new; - } - } + if (vp[h].name == NULL) { + if (rehash(vp)) + h = varfind(s); + vused++; + vp[h].name = ecpy(s); + vp[h].p = enew(Variable); + ((Variable *)vp[h].p)->n = NULL; + return vp[h].p; + } else { + if (stack) { /* increase the stack by 1 */ + new = enew(Variable); + new->n = vp[h].p; + return vp[h].p = new; + } else { /* trample the top of the stack */ + new = vp[h].p; + efree(new->extdef); + listfree(new->def); + return new; + } + } } extern void delete_fn(char *s) { - int h = fnfind(s); - if (fp[h].name == NULL) - return; /* not found */ - env_dirty = true; - free_fn(fp[h].p); - efree(fp[h].p); - efree(fp[h].name); - if (fp[(h+1)&(fsize-1)].name == NULL) { - --fused; - fp[h].name = NULL; - } else { - fp[h].name = dead; - } + int h = fnfind(s); + if (fp[h].name == NULL) + return; /* not found */ + env_dirty = true; + free_fn(fp[h].p); + efree(fp[h].p); + efree(fp[h].name); + if (fp[(h+1)&(fsize-1)].name == NULL) { + --fused; + fp[h].name = NULL; + } else { + fp[h].name = dead; + } } extern void delete_var(char *s, bool stack) { - int h = varfind(s); - Variable *v; - if (vp[h].name == NULL) - return; /* not found */ - env_dirty = true; - v = vp[h].p; - efree(v->extdef); - listfree(v->def); - if (v->n != NULL) { /* This is the top of a stack */ - if (stack) { /* pop */ - vp[h].p = v->n; - efree(v); - } else { /* else just empty */ - v->extdef = NULL; - v->def = NULL; - } - } else { /* needs to be removed from the hash table */ - efree(v); - efree(vp[h].name); - if (vp[(h+1)&(vsize-1)].name == NULL) { - --vused; - vp[h].name = NULL; - } else { - vp[h].name = dead; - } - } + int h = varfind(s); + Variable *v; + if (vp[h].name == NULL) + return; /* not found */ + env_dirty = true; + v = vp[h].p; + efree(v->extdef); + listfree(v->def); + if (v->n != NULL) { /* This is the top of a stack */ + if (stack) { /* pop */ + vp[h].p = v->n; + efree(v); + } else { /* else just empty */ + v->extdef = NULL; + v->def = NULL; + } + } else { /* needs to be removed from the hash table */ + efree(v); + efree(vp[h].name); + if (vp[(h+1)&(vsize-1)].name == NULL) { + --vused; + vp[h].name = NULL; + } else { + vp[h].name = dead; + } + } } static void free_fn(rc_Function *f) { - treefree(f->def); - efree(f->extdef); + treefree(f->def); + efree(f->extdef); } extern void initenv(char **envp) { - int n; - for (n = 0; envp[n] != NULL; n++) - ; - n++; /* one for the null terminator */ - if (n < HASHSIZE) - n = HASHSIZE; - env = ealloc((envsize = 2 * n) * sizeof (char *)); - for (; *envp != NULL; envp++) - if (strncmp(*envp, "fn_", conststrlen("fn_")) == 0) { - fnassign_string(*envp); - } else { - if (!varassign_string(*envp)) /* add to bozo env */ - env[bozosize++] = *envp; - } + int n; + for (n = 0; envp[n] != NULL; n++) + ; + n++; /* one for the null terminator */ + if (n < HASHSIZE) + n = HASHSIZE; + env = ealloc((envsize = 2 * n) * sizeof (char *)); + for (; *envp != NULL; envp++) + if (strncmp(*envp, "fn_", conststrlen("fn_")) == 0) { + fnassign_string(*envp); + } else { + if (!varassign_string(*envp)) /* add to bozo env */ + env[bozosize++] = *envp; + } } static char *neverexport[] = { - "apid", "apids", "bqstatus", "cdpath", "home", - "ifs", "path", "pid", "status", "*" + "apid", "apids", "bqstatus", "cdpath", "home", + "ifs", "path", "pid", "status", "*" }; /* for a few variables that have default values, we export them only if they've been explicitly set; maybeexport[n].flag is true if this has occurred. */ struct nameflag { - char *name; - bool flag; + char *name; + bool flag; }; static struct nameflag maybeexport[] = { - { "prompt", false }, - { "version", false } + { "prompt", false }, + { "version", false } }; void set_exportable(char *s, bool b) { - int i; - for (i = 0; i < arraysize(maybeexport); ++i) - if (maybeexport[i].flag != b && streq(s, maybeexport[i].name)) - maybeexport[i].flag = b; + int i; + for (i = 0; i < arraysize(maybeexport); ++i) + if (maybeexport[i].flag != b && streq(s, maybeexport[i].name)) + maybeexport[i].flag = b; } static bool var_exportable(char *s) { - int i; - for (i = 0; i < arraysize(neverexport); i++) - if (streq(s, neverexport[i])) - return false; - for (i = 0; i < arraysize(maybeexport); i++) - if (maybeexport[i].flag == false && streq(s, maybeexport[i].name)) - return false; - return true; + int i; + for (i = 0; i < arraysize(neverexport); i++) + if (streq(s, neverexport[i])) + return false; + for (i = 0; i < arraysize(maybeexport); i++) + if (maybeexport[i].flag == false && streq(s, maybeexport[i].name)) + return false; + return true; } static bool fn_exportable(char *s) { - int i; - if (strncmp(s, "sig", conststrlen("sig")) == 0) { /* small speed hack */ - for (i = 0; i < NSIG; i++) - if (streq(s, signals[i].name)) - return false; - if (streq(s, "sigexit")) - return false; - } - return true; + int i; + if (strncmp(s, "sig", conststrlen("sig")) == 0) { /* small speed hack */ + for (i = 0; i < NSIG; i++) + if (streq(s, signals[i].name)) + return false; + if (streq(s, "sigexit")) + return false; + } + return true; } extern char **makeenv() { - int ep, i; - char *v; - if (!env_dirty) - return env; - env_dirty = false; - ep = bozosize; - if (vsize + fsize + 1 + bozosize > envsize) { - envsize = 2 * (bozosize + vsize + fsize + 1); - env = erealloc(env, envsize * sizeof(char *)); - } - for (i = 0; i < vsize; i++) { - if (vp[i].name == NULL || vp[i].name == dead || !var_exportable(vp[i].name)) - continue; - v = varlookup_string(vp[i].name); - if (v != NULL) - env[ep++] = v; - } - for (i = 0; i < fsize; i++) { - if (fp[i].name == NULL || fp[i].name == dead || !fn_exportable(fp[i].name)) - continue; - env[ep++] = fnlookup_string(fp[i].name); - } - env[ep] = NULL; - qsort(env, (size_t) ep, sizeof(char *), starstrcmp); - return env; + int ep, i; + char *v; + if (!env_dirty) + return env; + env_dirty = false; + ep = bozosize; + if (vsize + fsize + 1 + bozosize > envsize) { + envsize = 2 * (bozosize + vsize + fsize + 1); + env = erealloc(env, envsize * sizeof(char *)); + } + for (i = 0; i < vsize; i++) { + if (vp[i].name == NULL || vp[i].name == dead || !var_exportable(vp[i].name)) + continue; + v = varlookup_string(vp[i].name); + if (v != NULL) + env[ep++] = v; + } + for (i = 0; i < fsize; i++) { + if (fp[i].name == NULL || fp[i].name == dead || !fn_exportable(fp[i].name)) + continue; + env[ep++] = fnlookup_string(fp[i].name); + } + env[ep] = NULL; + qsort(env, (size_t) ep, sizeof(char *), starstrcmp); + return env; } extern void whatare_all_vars(bool showfn, bool showvar) { - int i; - List *s; - if (showvar) - for (i = 0; i < vsize; i++) - if (vp[i].name != NULL && (s = varlookup(vp[i].name)) != NULL) - prettyprint_var(1, vp[i].name, s); - if (showfn) - for (i = 0; i < fsize; i++) - if (fp[i].name != NULL && fp[i].name != dead) - prettyprint_fn(1, fp[i].name, fnlookup(fp[i].name)); + int i; + List *s; + if (showvar) + for (i = 0; i < vsize; i++) + if (vp[i].name != NULL && (s = varlookup(vp[i].name)) != NULL) + prettyprint_var(1, vp[i].name, s); + if (showfn) + for (i = 0; i < fsize; i++) + if (fp[i].name != NULL && fp[i].name != dead) + prettyprint_fn(1, fp[i].name, fnlookup(fp[i].name)); } diff --git a/heredoc.c b/heredoc.c index 8fef56d..7ea401f 100644 --- a/heredoc.c +++ b/heredoc.c @@ -3,10 +3,10 @@ #include "rc.h" struct Hq { - Node *doc; - char *name; - Hq *n; - bool quoted; + Node *doc; + char *name; + Hq *n; + bool quoted; } *hq; static bool dead = false; @@ -23,134 +23,134 @@ static bool dead = false; */ static char *readheredoc(char *eof) { - int c; - char *t, *buf, *bufend; - unsigned char *s; - size_t bufsize; - t = buf = nalloc(bufsize = 512); - bufend = &buf[bufsize]; - dead = false; -#define RESIZE(extra) { \ - char *nbuf; \ - bufsize = bufsize * 2 + extra; \ - nbuf = nalloc(bufsize); \ - memcpy(nbuf, buf, (size_t) (t - buf)); \ - t = nbuf + (t - buf); \ - buf = nbuf; \ - bufend = &buf[bufsize]; \ - } - for (;;) { - nextline(); - for (s = (unsigned char *) eof; (c = gchar()) == *s; s++) - ; - if (*s == '\0' && (c == '\n' || c == EOF)) { - *t++ = '\0'; - return buf; - } - if (s != (unsigned char *) eof) { - size_t len = s - (unsigned char *) eof; - if (t + len >= bufend) - RESIZE(len); - memcpy(t, eof, len); - t += len; - } - for (;; c = gchar()) { - if (c == EOF) { - yyerror("heredoc incomplete"); - dead = true; - return NULL; - } - if (t + 1 >= bufend) - RESIZE(0); - *t++ = c; - if (c == '\n') - break; - } - } + int c; + char *t, *buf, *bufend; + unsigned char *s; + size_t bufsize; + t = buf = nalloc(bufsize = 512); + bufend = &buf[bufsize]; + dead = false; +#define RESIZE(extra) { \ + char *nbuf; \ + bufsize = bufsize * 2 + extra; \ + nbuf = nalloc(bufsize); \ + memcpy(nbuf, buf, (size_t) (t - buf)); \ + t = nbuf + (t - buf); \ + buf = nbuf; \ + bufend = &buf[bufsize]; \ + } + for (;;) { + nextline(); + for (s = (unsigned char *) eof; (c = gchar()) == *s; s++) + ; + if (*s == '\0' && (c == '\n' || c == EOF)) { + *t++ = '\0'; + return buf; + } + if (s != (unsigned char *) eof) { + size_t len = s - (unsigned char *) eof; + if (t + len >= bufend) + RESIZE(len); + memcpy(t, eof, len); + t += len; + } + for (;; c = gchar()) { + if (c == EOF) { + yyerror("heredoc incomplete"); + dead = true; + return NULL; + } + if (t + 1 >= bufend) + RESIZE(0); + *t++ = c; + if (c == '\n') + break; + } + } } /* parseheredoc -- turn a heredoc with variable references into a node chain */ static Node *parseheredoc(char *s) { - int c = *s; - Node *result = NULL; - while (true) { - Node *node; - switch (c) { - default: { - char *begin = s; - while ((c = *s++) != '\0' && c != '$') - ; - *--s = '\0'; - node = mk(nWord, begin, NULL); - break; - } - case '$': { - char *begin = ++s, *var; - c = *s++; - if (c == '$') { - node = mk(nWord, "$", NULL); - c = *s; - } else { - size_t len = 0; - do - len++; - while (!dnw[c = *(unsigned char *) s++]); - if (c == '^') - c = *s; - else - s--; - var = nalloc(len + 1); - var[len] = '\0'; - memcpy(var, begin, len); - node = mk(nFlat, mk(nWord, var, NULL)); - } - break; - } - case '\0': - return result; - } - result = (result == NULL) ? node : mk(nConcat, result, node); - } + int c = *s; + Node *result = NULL; + while (true) { + Node *node; + switch (c) { + default: { + char *begin = s; + while ((c = *s++) != '\0' && c != '$') + ; + *--s = '\0'; + node = mk(nWord, begin, NULL); + break; + } + case '$': { + char *begin = ++s, *var; + c = *s++; + if (c == '$') { + node = mk(nWord, "$", NULL); + c = *s; + } else { + size_t len = 0; + do + len++; + while (!dnw[c = *(unsigned char *) s++]); + if (c == '^') + c = *s; + else + s--; + var = nalloc(len + 1); + var[len] = '\0'; + memcpy(var, begin, len); + node = mk(nFlat, mk(nWord, var, NULL)); + } + break; + } + case '\0': + return result; + } + result = (result == NULL) ? node : mk(nConcat, result, node); + } } /* read in heredocs when yyparse hits a newline. called from yyparse */ extern int heredoc(int end) { - Hq *here; - if ((here = hq) != NULL) { - hq = NULL; - if (end) { - yyerror("heredoc incomplete"); - return false; - } - do { - Node *n = here->doc; - char *s = readheredoc(here->name); - if (dead) - return false; - n->u[2].p = here->quoted ? mk(nWord, s, NULL, false) : parseheredoc(s); - n->u[0].i = rHerestring; - } while ((here = here->n) != NULL); - } - return true; + Hq *here; + if ((here = hq) != NULL) { + hq = NULL; + if (end) { + yyerror("heredoc incomplete"); + return false; + } + do { + Node *n = here->doc; + char *s = readheredoc(here->name); + if (dead) + return false; + n->u[2].p = here->quoted ? mk(nWord, s, NULL, false) : parseheredoc(s); + n->u[0].i = rHerestring; + } while ((here = here->n) != NULL); + } + return true; } /* queue pending heredocs into a queue. called from yyparse */ extern int qdoc(Node *name, Node *n) { - Hq *new, **prev; - if (name->type != nWord) { - yyerror("eof-marker not a single literal word"); - skiptonl(); - return false; - } - for (prev = &hq; (new = *prev) != NULL; prev = &new->n) - ; - *prev = new = nnew(Hq); - new->name = name->u[0].s; - new->quoted = name->u[2].i; - new->doc = n; - new->n = NULL; - return true; + Hq *new, **prev; + if (name->type != nWord) { + yyerror("eof-marker not a single literal word"); + skiptonl(); + return false; + } + for (prev = &hq; (new = *prev) != NULL; prev = &new->n) + ; + *prev = new = nnew(Hq); + new->name = name->u[0].s; + new->quoted = name->u[2].i; + new->doc = n; + new->n = NULL; + return true; } diff --git a/input.c b/input.c index ab39582..95dd526 100644 --- a/input.c +++ b/input.c @@ -6,17 +6,17 @@ enum { UNGETSIZE = 2 }; typedef enum inputtype { - iFd, iString, iEdit + iFd, iString, iEdit } inputtype; typedef struct Input { - bool saved; - inputtype t; - int fd, index, read, ungetcount, lineno, last; - char *ibuf; - void *cookie; - int ungetbuf[UNGETSIZE]; - int (*gchar)(void); + bool saved; + inputtype t; + int fd, index, read, ungetcount, lineno, last; + char *ibuf; + void *cookie; + int ungetbuf[UNGETSIZE]; + int (*gchar)(void); } Input; #define BUFSIZE ((size_t) 256) @@ -31,274 +31,274 @@ int lastchar; static char *prompt, *prompt2; extern void ugchar(int c) { - assert(istack->ungetcount < UNGETSIZE); - istack->ungetbuf[istack->ungetcount++] = c; + assert(istack->ungetcount < UNGETSIZE); + istack->ungetbuf[istack->ungetcount++] = c; } extern int gchar() { - int c; + int c; - if (istack->ungetcount) - return lastchar = istack->ungetbuf[--istack->ungetcount]; + if (istack->ungetcount) + return lastchar = istack->ungetbuf[--istack->ungetcount]; - while ((c = (*istack->gchar)()) == '\0') - pr_error("warning: null character ignored", 0); + while ((c = (*istack->gchar)()) == '\0') + pr_error("warning: null character ignored", 0); - return c; + return c; } /* get the next character from a string. */ static int stringgchar() { - return lastchar = (inbuf[chars_out] == '\0' ? EOF : inbuf[chars_out++]); + return lastchar = (inbuf[chars_out] == '\0' ? EOF : inbuf[chars_out++]); } /* write last command out to a file if interactive && $history is set */ static void history() { - List *hist; - size_t a; - - if (!interactive || (hist = varlookup("history")) == NULL) - return; - - for (a = 0; a < chars_in; a++) { - char c = inbuf[a]; - - /* skip empty lines and comments */ - if (c == '#' || c == '\n') - break; - - /* line matches [ \t]*[^#\n] so it's ok to write out */ - if (c != ' ' && c != '\t') { - char *name = hist->w; - int fd = rc_open(name, rAppend); - if (fd < 0) - uerror(name); - else { - writeall(fd, inbuf, chars_in); - close(fd); - } - break; - } - } + List *hist; + size_t a; + + if (!interactive || (hist = varlookup("history")) == NULL) + return; + + for (a = 0; a < chars_in; a++) { + char c = inbuf[a]; + + /* skip empty lines and comments */ + if (c == '#' || c == '\n') + break; + + /* line matches [ \t]*[^#\n] so it's ok to write out */ + if (c != ' ' && c != '\t') { + char *name = hist->w; + int fd = rc_open(name, rAppend); + if (fd < 0) + uerror(name); + else { + writeall(fd, inbuf, chars_in); + close(fd); + } + break; + } + } } /* read a character from a file descriptor */ static int fdgchar() { - if (chars_out >= chars_in) { /* replenish empty buffer */ - ssize_t r; - do { - r = read(istack->fd, inbuf, BUFSIZE); - sigchk(); - if (r == -1) - switch (errno) { - case EAGAIN: - if (!makeblocking(istack->fd)) - panic("not O_NONBLOCK"); - errno = EINTR; - break; - case EIO: - if (makesamepgrp(istack->fd)) - errno = EINTR; - else - errno = EIO; - break; - } - } while (r < 0 && errno == EINTR); - if (r < 0) { - uerror("read"); - rc_raise(eError); - } - chars_in = (size_t) r; - if (chars_in == 0) - return lastchar = EOF; - chars_out = 0; - history(); - } - - return lastchar = inbuf[chars_out++]; + if (chars_out >= chars_in) { /* replenish empty buffer */ + ssize_t r; + do { + r = read(istack->fd, inbuf, BUFSIZE); + sigchk(); + if (r == -1) + switch (errno) { + case EAGAIN: + if (!makeblocking(istack->fd)) + panic("not O_NONBLOCK"); + errno = EINTR; + break; + case EIO: + if (makesamepgrp(istack->fd)) + errno = EINTR; + else + errno = EIO; + break; + } + } while (r < 0 && errno == EINTR); + if (r < 0) { + uerror("read"); + rc_raise(eError); + } + chars_in = (size_t) r; + if (chars_in == 0) + return lastchar = EOF; + chars_out = 0; + history(); + } + + return lastchar = inbuf[chars_out++]; } /* set up the input stack, and put a "dead" input at the bottom, so that yyparse will always read eof */ extern void initinput() { - istack = itop = ealloc(istacksize = 256 * sizeof (Input)); - istack->ungetcount = 0; - ugchar(EOF); + istack = itop = ealloc(istacksize = 256 * sizeof (Input)); + istack->ungetcount = 0; + ugchar(EOF); } /* push an input source onto the stack. set up a new input buffer, and set gchar() */ static void pushcommon() { - size_t idiff; - istack->index = chars_out; - istack->read = chars_in; - istack->ibuf = inbuf; - istack->lineno = lineno; - istack->saved = save_lineno; - istack->last = lastchar; - istack++; - idiff = istack - itop; - if (idiff >= istacksize / sizeof (Input)) { - itop = erealloc(itop, istacksize *= 2); - istack = itop + idiff; - } - chars_out = 0; - chars_in = 0; - istack->ungetcount = 0; + size_t idiff; + istack->index = chars_out; + istack->read = chars_in; + istack->ibuf = inbuf; + istack->lineno = lineno; + istack->saved = save_lineno; + istack->last = lastchar; + istack++; + idiff = istack - itop; + if (idiff >= istacksize / sizeof (Input)) { + itop = erealloc(itop, istacksize *= 2); + istack = itop + idiff; + } + chars_out = 0; + chars_in = 0; + istack->ungetcount = 0; } extern void pushfd(int fd) { - pushcommon(); - save_lineno = true; - istack->fd = fd; - lineno = 1; - istack->t = iFd; - istack->gchar = fdgchar; - inbuf = ealloc(BUFSIZE); + pushcommon(); + save_lineno = true; + istack->fd = fd; + lineno = 1; + istack->t = iFd; + istack->gchar = fdgchar; + inbuf = ealloc(BUFSIZE); } extern void pushstring(char **a, bool save) { - pushcommon(); - istack->t = iString; - save_lineno = save; - inbuf = mprint("%A", a); - istack->gchar = stringgchar; - if (save_lineno) - lineno = 1; - else - --lineno; + pushcommon(); + istack->t = iString; + save_lineno = save; + inbuf = mprint("%A", a); + istack->gchar = stringgchar; + if (save_lineno) + lineno = 1; + else + --lineno; } /* remove an input source from the stack. restore associated variables etc. */ extern void popinput() { - if (istack->t == iFd || istack->t == iEdit) - close(istack->fd); - efree(inbuf); - --istack; - lastchar = istack->last; - inbuf = istack->ibuf; - chars_out = istack->index; - chars_in = istack->read; - if (save_lineno) - lineno = istack->lineno; - else - lineno++; - save_lineno = istack->saved; + if (istack->t == iFd || istack->t == iEdit) + close(istack->fd); + efree(inbuf); + --istack; + lastchar = istack->last; + inbuf = istack->ibuf; + chars_out = istack->index; + chars_in = istack->read; + if (save_lineno) + lineno = istack->lineno; + else + lineno++; + save_lineno = istack->saved; } /* flush input characters up to newline. Used by scanerror() */ extern void skiptonl() { - int c; - if (lastchar == '\n' || lastchar == EOF) - return; - while ((c = gchar()) != '\n' && c != EOF) - ; /* skip to newline */ - if (c == EOF) - ugchar(c); + int c; + if (lastchar == '\n' || lastchar == EOF) + return; + while ((c = gchar()) != '\n' && c != EOF) + ; /* skip to newline */ + if (c == EOF) + ugchar(c); } /* the wrapper loop in rc: prompt for commands until EOF, calling yyparse and walk() */ extern Node *doit(bool clobberexecit) { - bool eof; - bool execit; - Jbwrap j; - Estack e1; - Edata jerror; - - execit = clobberexecit; - sigsetjmp(j.j, 1); - jerror.jb = &j; - except(eError, jerror, &e1); - for (eof = false; !eof;) { - Edata block; - Estack e2; - - block.b = newblock(); - except(eArena, block, &e2); - sigchk(); - - if (interactive) { - List *s; - if (fnlookup("prompt") != NULL) { - static bool died = false; - static char *arglist[] = { "prompt", NULL }; - - if (!died) { - died = true; - funcall(arglist); - } - died = false; - } - s = varlookup("prompt"); - if (s != NULL) { - prompt = s->w; - if (s->n != NULL) - prompt2 = s->n->w; - else - prompt2 = ""; - } else { - prompt = prompt2 = ""; - } - if (istack->t == iFd) - fprint(2, "%s", prompt); - } - inityy(); - if (yyparse() == 1 && execit) - rc_raise(eError); - eof = (lastchar == EOF); /* "lastchar" can be clobbered during a walk() */ - if (parsetree != NULL && execit) - walk(parsetree, true); - unexcept(); /* eArena */ - } - popinput(); - unexcept(); /* eError */ - return parsetree; + bool eof; + bool execit; + Jbwrap j; + Estack e1; + Edata jerror; + + execit = clobberexecit; + sigsetjmp(j.j, 1); + jerror.jb = &j; + except(eError, jerror, &e1); + for (eof = false; !eof;) { + Edata block; + Estack e2; + + block.b = newblock(); + except(eArena, block, &e2); + sigchk(); + + if (interactive) { + List *s; + if (fnlookup("prompt") != NULL) { + static bool died = false; + static char *arglist[] = { "prompt", NULL }; + + if (!died) { + died = true; + funcall(arglist); + } + died = false; + } + s = varlookup("prompt"); + if (s != NULL) { + prompt = s->w; + if (s->n != NULL) + prompt2 = s->n->w; + else + prompt2 = ""; + } else { + prompt = prompt2 = ""; + } + if (istack->t == iFd) + fprintf(stderr, "%s", prompt); + } + inityy(); + if (yyparse() == 1 && execit) + rc_raise(eError); + eof = (lastchar == EOF); /* "lastchar" can be clobbered during a walk() */ + if (parsetree != NULL && execit) + walk(parsetree, true); + unexcept(); /* eArena */ + } + popinput(); + unexcept(); /* eError */ + return parsetree; } /* parse a function imported from the environment */ extern Node *parseline(char *extdef) { - bool i = interactive; - char *in[2]; - Node *fun; - in[0] = extdef; - in[1] = NULL; - interactive = false; - pushstring(in, true); - fun = doit(false); - interactive = i; - return fun; + bool i = interactive; + char *in[2]; + Node *fun; + in[0] = extdef; + in[1] = NULL; + interactive = false; + pushstring(in, true); + fun = doit(false); + interactive = i; + return fun; } /* close file descriptors after a fork() */ extern void closefds() { - Input *i; - for (i = istack; i != itop; --i) /* close open scripts */ - if (i->t == iFd && i->fd > 2) { - close(i->fd); - i->fd = -1; - } + Input *i; + for (i = istack; i != itop; --i) /* close open scripts */ + if (i->t == iFd && i->fd > 2) { + close(i->fd); + i->fd = -1; + } } /* print (or set) prompt(2) */ extern void nextline() { - lineno++; - if (interactive) { - if (istack->t == iFd) - fprint(2, "%s", prompt2); - } + lineno++; + if (interactive) { + if (istack->t == iFd) + fprintf(stderr, "%s", prompt2); + } } diff --git a/lex.c b/lex.c index b682dcc..54bd7f1 100644 --- a/lex.c +++ b/lex.c @@ -4,29 +4,29 @@ #include "y.tab.h" /* - Special characters (i.e., "non-word") in rc: - \t \n # ; & | ^ $ = ~ ` ' { } @ ! ( ) < > \ + Special characters (i.e., "non-word") in rc: + \t \n # ; & | ^ $ = ~ ` ' { } @ ! ( ) < > \ - The lexical analyzer is fairly straightforward. The only really - unclean part concerns backslash continuation and "double - backslashes". A backslash followed by a newline is treated as a - space, otherwise backslash is not a special character (i.e., - it can be part of a word). This introduces a host of unwanted - special cases. In our case, \ cannot be a word character, since - we wish to read in all word characters in a tight loop. + The lexical analyzer is fairly straightforward. The only really + unclean part concerns backslash continuation and "double + backslashes". A backslash followed by a newline is treated as a + space, otherwise backslash is not a special character (i.e., + it can be part of a word). This introduces a host of unwanted + special cases. In our case, \ cannot be a word character, since + we wish to read in all word characters in a tight loop. - Note: to save the trouble of declaring these arrays with trues - and falses, I am assuming that false = 0, true = 1. (and so is - it declared in rc.h) + Note: to save the trouble of declaring these arrays with trues + and falses, I am assuming that false = 0, true = 1. (and so is + it declared in rc.h) */ -#define BUFSIZE ((size_t) 1000) /* malloc hates power of 2 buffers? */ -#define BUFMAX (8 * BUFSIZE) /* How big the buffer can get before we re-allocate the - space at BUFSIZE again. Premature optimization? Maybe. - */ +#define BUFSIZE ((size_t) 1000) /* malloc hates power of 2 buffers? */ +#define BUFMAX (8 * BUFSIZE) /* How big the buffer can get before we re-allocate the + space at BUFSIZE again. Premature optimization? Maybe. + */ typedef enum wordstates { - NW, RW, KW /* "nonword", "realword", "keyword" */ + NW, RW, KW /* "nonword", "realword", "keyword" */ } wordstates; static void getpair(int); @@ -35,38 +35,38 @@ int lineno; /* lookup table for non-word characters */ const char nw[] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* lookup table for non-word characters in variable names */ const char dnw[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /* lookup table for quotable characters: nw + glob metachars */ const char q[] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static size_t bufsize = BUFSIZE; @@ -80,289 +80,289 @@ static int fd_left, fd_right; #define checkfreecaret {if (w != NW) { w = NW; ugchar(c); return '^'; }} enum filedescriptors { - UNSET = -9, CLOSED = -1 + UNSET = -9, CLOSED = -1 }; /* does this string require quoting? */ extern bool quotep(char *s, bool dollar) { - unsigned char c; - const char *meta; + unsigned char c; + const char *meta; - meta = dollar ? dnw : q; - while ((c = *s++)) - if (meta[c]) - return true; - return false; + meta = dollar ? dnw : q; + while ((c = *s++)) + if (meta[c]) + return true; + return false; } extern int yylex() { - static bool dollar = false; - bool saw_meta = false; - int c; - size_t i; /* The purpose of all these local assignments is to */ - const char *meta; /* allow optimizing compilers like gcc to load these */ - char *buf = realbuf; /* values into registers. On a sparc this is a */ - YYSTYPE *y = &yylval; /* win, in code size *and* execution time */ - if (errset) { - errset = false; - return '\n'; - } - /* rc variable-names may contain only alnum, '*' and '_', so use dnw if we are scanning one. */ - meta = (dollar ? dnw : nw); - if (newline) { - --lineno; /* slight space optimization; nextline() always increments lineno */ - nextline(); - newline = false; - } -top: while ((c = gchar()) == ' ' || c == '\t') - w = NW; - if (c != '(') dollar = false; - if (c == EOF) - return END; - if (!meta[(unsigned char) c]) { /* it's a word or keyword. */ - checkfreecaret; - w = RW; - i = 0; - read: do { - buf[i++] = c; - if (c == '?' || c == '[' || c == '*') - saw_meta = true; - if (i >= bufsize) - buf = realbuf = erealloc(buf, bufsize *= 2); - } while ((c = gchar()) != EOF && !meta[(unsigned char) c]); - while (c == '\\') { - if ((c = gchar()) == '\n') { - nextline(); - c = ' '; /* Pretend a space was read */ - break; - } else { - bs: if (meta != dnw) { /* all words but varnames may have a bslash */ - buf[i++] = '\\'; - if (i >= bufsize) - buf = realbuf = erealloc(buf, bufsize *= 2); - if (!meta[(unsigned char) c]) - goto read; - } else { - ugchar(c); - c = '\\'; - break; - } - } - } - ugchar(c); - buf[i] = '\0'; - w = KW; - if (i == 2) { - if (*buf == 'i' && buf[1] == 'f') return IF; - if (*buf == 'f' && buf[1] == 'n') return FN; - if (*buf == 'i' && buf[1] == 'n') return IN; - } - if (streq(buf, "for")) return FOR; - if (streq(buf, "else")) return ELSE; - if (streq(buf, "switch")) return SWITCH; - if (streq(buf, "while")) return WHILE; - if (streq(buf, "case")) return CASE; - w = RW; - y->word.w = ncpy(buf); - if (saw_meta) { - char *r, *s; + static bool dollar = false; + bool saw_meta = false; + int c; + size_t i; /* The purpose of all these local assignments is to */ + const char *meta; /* allow optimizing compilers like gcc to load these */ + char *buf = realbuf; /* values into registers. On a sparc this is a */ + YYSTYPE *y = &yylval; /* win, in code size *and* execution time */ + if (errset) { + errset = false; + return '\n'; + } + /* rc variable-names may contain only alnum, '*' and '_', so use dnw if we are scanning one. */ + meta = (dollar ? dnw : nw); + if (newline) { + --lineno; /* slight space optimization; nextline() always increments lineno */ + nextline(); + newline = false; + } +top: while ((c = gchar()) == ' ' || c == '\t') + w = NW; + if (c != '(') dollar = false; + if (c == EOF) + return END; + if (!meta[(unsigned char) c]) { /* it's a word or keyword. */ + checkfreecaret; + w = RW; + i = 0; + read: do { + buf[i++] = c; + if (c == '?' || c == '[' || c == '*') + saw_meta = true; + if (i >= bufsize) + buf = realbuf = erealloc(buf, bufsize *= 2); + } while ((c = gchar()) != EOF && !meta[(unsigned char) c]); + while (c == '\\') { + if ((c = gchar()) == '\n') { + nextline(); + c = ' '; /* Pretend a space was read */ + break; + } else { + bs: if (meta != dnw) { /* all words but varnames may have a bslash */ + buf[i++] = '\\'; + if (i >= bufsize) + buf = realbuf = erealloc(buf, bufsize *= 2); + if (!meta[(unsigned char) c]) + goto read; + } else { + ugchar(c); + c = '\\'; + break; + } + } + } + ugchar(c); + buf[i] = '\0'; + w = KW; + if (i == 2) { + if (*buf == 'i' && buf[1] == 'f') return IF; + if (*buf == 'f' && buf[1] == 'n') return FN; + if (*buf == 'i' && buf[1] == 'n') return IN; + } + if (streq(buf, "for")) return FOR; + if (streq(buf, "else")) return ELSE; + if (streq(buf, "switch")) return SWITCH; + if (streq(buf, "while")) return WHILE; + if (streq(buf, "case")) return CASE; + w = RW; + y->word.w = ncpy(buf); + if (saw_meta) { + char *r, *s; - y->word.m = nalloc(strlen(buf) + 1); - for (r = buf, s = y->word.m; *r != '\0'; r++, s++) - *s = (*r == '?' || *r == '[' || *r == '*'); - } else { - y->word.m = NULL; - } - y->word.q = false; - return WORD; - } - if (c == '`' || c == '!' || c == '@' || c == '~' || c == '$' || c == '\'') { - checkfreecaret; - if (c == '!' || c == '@' || c == '~') - w = KW; - } - switch (c) { - case '!': - return BANG; - case '@': - return SUBSHELL; - case '~': - return TWIDDLE; - case '`': - c = gchar(); - if (c == '`') - return BACKBACK; - ugchar(c); - return '`'; - case '$': - dollar = true; - c = gchar(); - if (c == '#') - return COUNT; - if (c == '^' || c == '"') - return FLAT; - ugchar(c); - return '$'; - case '\'': - w = RW; - i = 0; - /* double ' to quote it, like this: 'how''s it going?' */ - while ((c = gchar()) != '\'' || (c = gchar()) == '\'') { - buf[i++] = c; - if (c == '\n') - nextline(); - if (c == EOF) { - w = NW; - scanerror("eof in quoted string"); - return HUH; - } - if (i >= bufsize) - buf = realbuf = erealloc(buf, bufsize *= 2); - } - ugchar(c); - buf[i] = '\0'; - y->word.w = ncpy(buf); - y->word.m = NULL; - y->word.q = true; - return WORD; - case '\\': - if ((c = gchar()) == '\n') { - nextline(); - goto top; /* Pretend it was just another space. */ - } - ugchar(c); - c = '\\'; - checkfreecaret; - c = gchar(); - i = 0; - goto bs; - case '(': - if (w == RW) /* SUB's happen only after real words, not keywords, so if () and while () work */ - c = SUB; - w = NW; - return c; - case '#': - while ((c = gchar()) != '\n') /* skip comment until newline */ - if (c == EOF) - return END; - /* FALLTHROUGH */ - case '\n': - lineno++; - newline = true; - /* FALLTHROUGH */ - case ';': - case '^': - case ')': - case '=': - case '{': case '}': - w = NW; - return c; - case '&': - w = NW; - c = gchar(); - if (c == '&') - return ANDAND; - ugchar(c); - return '&'; - case '|': - w = NW; - c = gchar(); - if (c == '|') - return OROR; - getpair(c); - if (errset) - return HUH; - if ((y->pipe.left = fd_left) == UNSET) - y->pipe.left = 1; /* default to fd 1 */ - if ((y->pipe.right = fd_right) == UNSET) - y->pipe.right = 0; /* default to fd 0 */ - if (y->pipe.right == CLOSED) { - scanerror("expected digit after '='"); /* can't close a pipe */ - return HUH; - } - return PIPE; - case '>': - c = gchar(); - if (c == '>') { - c = gchar(); - y->redir.type = rAppend; - } else - y->redir.type = rCreate; - y->redir.fd = 1; - goto common; - case '<': - c = gchar(); - if (c == '<') { - c = gchar(); - if (c == '<') { - c = gchar(); - y->redir.type = rHerestring; - } else { - y->redir.type = rHeredoc; - } - } else - y->redir.type = rFrom; - y->redir.fd = 0; - common: - w = NW; - getpair(c); - if (errset) - return HUH; - if (fd_right == UNSET) { /* redirection, not dup */ - if (fd_left != UNSET) { - y->redir.fd = fd_left; - return SREDIR; - } - return (y->redir.type == rFrom || y->redir.type == rCreate) ? REDIR : SREDIR; - } else { /* dup; recast yylval */ - y->dup.type = y->redir.type; - y->dup.left = fd_left; - y->dup.right = fd_right; - return DUP; - } - default: - w = NW; - return c; /* don't know what it is, let yacc barf on it */ - } + y->word.m = nalloc(strlen(buf) + 1); + for (r = buf, s = y->word.m; *r != '\0'; r++, s++) + *s = (*r == '?' || *r == '[' || *r == '*'); + } else { + y->word.m = NULL; + } + y->word.q = false; + return WORD; + } + if (c == '`' || c == '!' || c == '@' || c == '~' || c == '$' || c == '\'') { + checkfreecaret; + if (c == '!' || c == '@' || c == '~') + w = KW; + } + switch (c) { + case '!': + return BANG; + case '@': + return SUBSHELL; + case '~': + return TWIDDLE; + case '`': + c = gchar(); + if (c == '`') + return BACKBACK; + ugchar(c); + return '`'; + case '$': + dollar = true; + c = gchar(); + if (c == '#') + return COUNT; + if (c == '^' || c == '"') + return FLAT; + ugchar(c); + return '$'; + case '\'': + w = RW; + i = 0; + /* double ' to quote it, like this: 'how''s it going?' */ + while ((c = gchar()) != '\'' || (c = gchar()) == '\'') { + buf[i++] = c; + if (c == '\n') + nextline(); + if (c == EOF) { + w = NW; + scanerror("eof in quoted string"); + return HUH; + } + if (i >= bufsize) + buf = realbuf = erealloc(buf, bufsize *= 2); + } + ugchar(c); + buf[i] = '\0'; + y->word.w = ncpy(buf); + y->word.m = NULL; + y->word.q = true; + return WORD; + case '\\': + if ((c = gchar()) == '\n') { + nextline(); + goto top; /* Pretend it was just another space. */ + } + ugchar(c); + c = '\\'; + checkfreecaret; + c = gchar(); + i = 0; + goto bs; + case '(': + if (w == RW) /* SUB's happen only after real words, not keywords, so if () and while () work */ + c = SUB; + w = NW; + return c; + case '#': + while ((c = gchar()) != '\n') /* skip comment until newline */ + if (c == EOF) + return END; + /* FALLTHROUGH */ + case '\n': + lineno++; + newline = true; + /* FALLTHROUGH */ + case ';': + case '^': + case ')': + case '=': + case '{': case '}': + w = NW; + return c; + case '&': + w = NW; + c = gchar(); + if (c == '&') + return ANDAND; + ugchar(c); + return '&'; + case '|': + w = NW; + c = gchar(); + if (c == '|') + return OROR; + getpair(c); + if (errset) + return HUH; + if ((y->pipe.left = fd_left) == UNSET) + y->pipe.left = 1; /* default to fd 1 */ + if ((y->pipe.right = fd_right) == UNSET) + y->pipe.right = 0; /* default to fd 0 */ + if (y->pipe.right == CLOSED) { + scanerror("expected digit after '='"); /* can't close a pipe */ + return HUH; + } + return PIPE; + case '>': + c = gchar(); + if (c == '>') { + c = gchar(); + y->redir.type = rAppend; + } else + y->redir.type = rCreate; + y->redir.fd = 1; + goto common; + case '<': + c = gchar(); + if (c == '<') { + c = gchar(); + if (c == '<') { + c = gchar(); + y->redir.type = rHerestring; + } else { + y->redir.type = rHeredoc; + } + } else + y->redir.type = rFrom; + y->redir.fd = 0; + common: + w = NW; + getpair(c); + if (errset) + return HUH; + if (fd_right == UNSET) { /* redirection, not dup */ + if (fd_left != UNSET) { + y->redir.fd = fd_left; + return SREDIR; + } + return (y->redir.type == rFrom || y->redir.type == rCreate) ? REDIR : SREDIR; + } else { /* dup; recast yylval */ + y->dup.type = y->redir.type; + y->dup.left = fd_left; + y->dup.right = fd_right; + return DUP; + } + default: + w = NW; + return c; /* don't know what it is, let yacc barf on it */ + } } extern void yyerror(const char *s) { - char *tok; - if (prerror) { /* don't print "syntax error" if there's a more informative scanerror */ - prerror = false; - return; - } - if (!interactive) { - if (w != NW) - tok = realbuf; - else if (lastchar == EOF) - tok = "eof"; - else if (lastchar == '\n') - tok = "end of line"; - else - tok = nprint((lastchar < 32 || lastchar > 126) ? "(decimal %d)" : "'%c'", lastchar); - fprint(2, "rc: line %d: %s near %s\n", lineno - (lastchar == '\n'), s, tok); - } else - fprint(2, "rc: %s\n", s); + char *tok; + if (prerror) { /* don't print "syntax error" if there's a more informative scanerror */ + prerror = false; + return; + } + if (!interactive) { + if (w != NW) + tok = realbuf; + else if (lastchar == EOF) + tok = "eof"; + else if (lastchar == '\n') + tok = "end of line"; + else + tok = nprint((lastchar < 32 || lastchar > 126) ? "(decimal %d)" : "'%c'", lastchar); + fprintf(stderr, "rc: line %d: %s near %s\n", lineno - (lastchar == '\n'), s, tok); + } else + fprintf(stderr, "rc: %s\n", s); } extern void scanerror(char *s) { - skiptonl(); /* flush up to newline */ - yyerror(s); - errset = prerror = true; + skiptonl(); /* flush up to newline */ + yyerror(s); + errset = prerror = true; } extern void inityy() { - newline = false; - w = NW; - hq = NULL; - /* return memory to the system if the buffer got too large */ - if (bufsize > BUFMAX && realbuf != NULL) { - efree(realbuf); - bufsize = BUFSIZE; - realbuf = ealloc(bufsize); - } else if (realbuf == NULL) - realbuf = ealloc(bufsize); + newline = false; + w = NW; + hq = NULL; + /* return memory to the system if the buffer got too large */ + if (bufsize > BUFMAX && realbuf != NULL) { + efree(realbuf); + bufsize = BUFSIZE; + realbuf = ealloc(bufsize); + } else if (realbuf == NULL) + realbuf = ealloc(bufsize); } /* @@ -374,41 +374,41 @@ extern void inityy() { */ static void getpair(int c) { - int n; - fd_left = fd_right = UNSET; - if (c != '[') { - ugchar(c); - return; - } - if ((unsigned int) (n = gchar() - '0') > 9) { - scanerror("expected digit after '['"); - return; - } - while ((unsigned int) (c = gchar() - '0') <= 9) - n = n * 10 + c; - fd_left = n; - c += '0'; - switch (c) { - default: - scanerror("expected '=' or ']' after digit"); - return; - case ']': - return; - case '=': - if ((unsigned int) (n = gchar() - '0') > 9) { - if (n != ']' - '0') { - scanerror("expected digit or ']' after '='"); - return; - } - fd_right = CLOSED; - } else { - while ((unsigned int) (c = gchar() - '0') <= 9) - n = n * 10 + c; - if (c != ']' - '0') { - scanerror("expected ']' after digit"); - return; - } - fd_right = n; - } - } + int n; + fd_left = fd_right = UNSET; + if (c != '[') { + ugchar(c); + return; + } + if ((unsigned int) (n = gchar() - '0') > 9) { + scanerror("expected digit after '['"); + return; + } + while ((unsigned int) (c = gchar() - '0') <= 9) + n = n * 10 + c; + fd_left = n; + c += '0'; + switch (c) { + default: + scanerror("expected '=' or ']' after digit"); + return; + case ']': + return; + case '=': + if ((unsigned int) (n = gchar() - '0') > 9) { + if (n != ']' - '0') { + scanerror("expected digit or ']' after '='"); + return; + } + fd_right = CLOSED; + } else { + while ((unsigned int) (c = gchar() - '0') <= 9) + n = n * 10 + c; + if (c != ']' - '0') { + scanerror("expected ']' after digit"); + return; + } + fd_right = n; + } + } } diff --git a/list.c b/list.c index fba6f6a..9bf1223 100644 --- a/list.c +++ b/list.c @@ -12,46 +12,46 @@ /* free a list from malloc space */ extern void listfree(List *p) { - while (p != NULL) { - List *n = p->n; - efree(p->w); - efree(p); - p = n; - } + while (p != NULL) { + List *n = p->n; + efree(p->w); + efree(p); + p = n; + } } /* Copy list into malloc space (for storing a variable) */ extern List *listcpy(List *s, void *(*alloc)(size_t)) { - List *top, *r; - for (top = r = NULL; s != NULL; s = s->n) { - if (top == NULL) - r = top = (*alloc)(sizeof (List)); - else - r = r->n = (*alloc)(sizeof (List)); - r->w = (*alloc)(strlen(s->w) + 1); - strcpy(r->w, s->w); - r->m = NULL; - } - if (r != NULL) - r->n = NULL; - return top; + List *top, *r; + for (top = r = NULL; s != NULL; s = s->n) { + if (top == NULL) + r = top = (*alloc)(sizeof (List)); + else + r = r->n = (*alloc)(sizeof (List)); + r->w = (*alloc)(strlen(s->w) + 1); + strcpy(r->w, s->w); + r->m = NULL; + } + if (r != NULL) + r->n = NULL; + return top; } /* Length of list */ extern size_t listlen(List *s) { - size_t size; - for (size = 0; s != NULL; s = s->n) - size += strlen(s->w) + 1; - return size; + size_t size; + for (size = 0; s != NULL; s = s->n) + size += strlen(s->w) + 1; + return size; } /* Number of elements in list */ extern int listnel(List *s) { - int nel; - for (nel = 0; s != NULL; s = s->n) - nel++; - return nel; + int nel; + for (nel = 0; s != NULL; s = s->n) + nel++; + return nel; } diff --git a/main.c b/main.c index c188efa..966f003 100644 --- a/main.c +++ b/main.c @@ -3,66 +3,124 @@ #include "rc.h" char* ARGV0; -bool interactive; +bool dashee, dasheye, dashen, dashpee, interactive; pid_t rc_pid; +static bool dashEYE, dashell, dashoh; + static void assigndefault(char *,...); static void checkfd(int, enum redirtype); void usage(void) { - printf("Usage: %s [OPTION...] [FILE [ARG...]]\n", ARGV0); + printf("Usage: %s [OPTION...] [FILE [ARG...]]\n", ARGV0); } extern int main(int argc, char *argv[], char *envp[]) { - char *dollarzero, *null[1]; - initprint(); - ARGV0 = dollarzero = argv[0]; - rc_pid = getpid(); + char *dashsee[2], *dollarzero, *null[1]; + initprint(); + dashsee[0] = dashsee[1] = NULL; + dollarzero = argv[0]; + rc_pid = getpid(); + dashell = (*argv[0] == '-'); /* login shell, per unix tradition */ + + OPTBEGIN { + case 'e': dashee = true; break; + case 'l': dashell = true; break; + case 'n': dashen = true; break; + case 'o': dashoh = true; break; + case 'p': dashpee = true; break; + case 'i': + dasheye = true; + interactive = true; + break; + case 'I': + dashEYE = true; + interactive = false; + break; + case 'c': + dashsee[0] = EOPTARG(usage()); + break; + } OPTEND; + + /* use isatty() iff neither -i nor -I is set, and iff the input is not from a script or -c flags */ + if (!dasheye && !dashEYE && dashsee[0] == NULL && (*argv == NULL)) + interactive = isatty(0); + if (!dashoh) { + checkfd(0, rFrom); + checkfd(1, rCreate); + checkfd(2, rCreate); + } + initsignal(); + inithash(); + initparse(); + assigndefault("ifs", " ", "\t", "\n", (void *)0); +#ifdef DEFAULTPATH + assigndefault("path", DEFAULTPATH, (void *)0); +#endif + assigndefault("pid", nprint("%d", rc_pid), (void *)0); + assigndefault("prompt", "; ", "", (void *)0); + assigndefault("version", VERSION, "$Release: @(#)" PACKAGE " " VERSION " " RELDATE " $", (void *)0); + initenv(envp); + initinput(); + null[0] = NULL; + starassign(dollarzero, null, false); /* assign $0 to $* */ + inithandler(); + + if (dashell) { + char *rcrc; + int fd; + + rcrc = concat(varlookup("home"), word("/.rcrc", NULL))->w; + fd = rc_open(rcrc, rFrom); + if (fd == -1) { + if (errno != ENOENT) + uerror(rcrc); + } else { + bool push_interactive; - /* use isatty() iff neither -i nor -I is set, and iff the input is not from a script or -c flags */ - interactive = isatty(0); - checkfd(0, rFrom); - checkfd(1, rCreate); - checkfd(2, rCreate); - - initsignal(); - inithash(); - initparse(); - assigndefault("ifs", " ", "\t", "\n", (void *)0); - assigndefault("path", DEFAULTPATH, (void *)0); - assigndefault("pid", nprint("%d", rc_pid), (void *)0); - assigndefault("prompt", "; ", "", (void *)0); - assigndefault("version", VERSION, "$Release: @(#)" PACKAGE " " VERSION " " RELDATE " $", (void *)0); - initenv(envp); - initinput(); - null[0] = NULL; - starassign(dollarzero, null, false); /* assign $0 to $* */ - inithandler(); + pushfd(fd); + push_interactive = interactive; + interactive = false; + doit(true); + interactive = push_interactive; + close(fd); + } + } - pushfd(0); // Read stdin - doit(true); - rc_exit(getstatus()); - return 0; /* Never really reached. */ + if (dashsee[0] != NULL) { /* input from -c or -s? */ + if (*argv != NULL) + starassign(dollarzero, argv, false); + pushstring(dashsee, true); + } else if (*argv != NULL) { /* else from a file? */ + b_dot(--argv); + rc_exit(getstatus()); + } else { /* else stdin */ + pushfd(0); + } + dasheye = false; + doit(true); + rc_exit(getstatus()); + return 0; /* Never really reached. */ } static void assigndefault(char *name,...) { - va_list ap; - List *l; - char *v; - va_start(ap, name); - for (l = NULL; (v = va_arg(ap, char *)) != NULL;) - l = append(l, word(v, NULL)); - varassign(name, l, false); - set_exportable(name, false); - if (streq(name, "path")) - alias(name, l, false); - va_end(ap); + va_list ap; + List *l; + char *v; + va_start(ap, name); + for (l = NULL; (v = va_arg(ap, char *)) != NULL;) + l = append(l, word(v, NULL)); + varassign(name, l, false); + set_exportable(name, false); + if (streq(name, "path")) + alias(name, l, false); + va_end(ap); } /* open an fd on /dev/null if it is inherited closed */ static void checkfd(int fd, enum redirtype r) { - int new = rc_open("/dev/null", r); - if (new != fd && new != -1) - close(new); + int new = rc_open("/dev/null", r); + if (new != fd && new != -1) + close(new); } diff --git a/match.c b/match.c index 3713e4a..3d13ace 100644 --- a/match.c +++ b/match.c @@ -9,62 +9,62 @@ enum { RANGE_FAIL = -1, RANGE_ERROR = -2 }; /* match() matches a single pattern against a single string. */ extern bool match(char *p, char *m, char *s) { - int i, j; - if (m == NULL) - return streq(p, s); - i = 0; - while (1) { - if (p[i] == '\0') - return *s == '\0'; - else if (m[i]) { - switch (p[i++]) { - case '?': - if (*s++ == '\0') - return false; - break; - case '*': - while (p[i] == '*' && m[i] == 1) /* collapse multiple stars */ - i++; - if (p[i] == '\0') /* star at end of pattern? */ - return true; - while (*s != '\0') - if (match(p + i, m + i, s++)) - return true; - return false; - case '[': - if (*s == '\0') - return false; - switch (j = rangematch(p + i, *s)) { - default: - i += j; - break; - case RANGE_FAIL: - return false; - case RANGE_ERROR: - if (*s != '[') - return false; - } - s++; - break; - default: - panic("bad metacharacter in match"); - /* NOTREACHED */ - return false; /* hush up gcc -Wall */ - } - } else if (p[i++] != *s++) - return false; - } + int i, j; + if (m == NULL) + return streq(p, s); + i = 0; + while (1) { + if (p[i] == '\0') + return *s == '\0'; + else if (m[i]) { + switch (p[i++]) { + case '?': + if (*s++ == '\0') + return false; + break; + case '*': + while (p[i] == '*' && m[i] == 1) /* collapse multiple stars */ + i++; + if (p[i] == '\0') /* star at end of pattern? */ + return true; + while (*s != '\0') + if (match(p + i, m + i, s++)) + return true; + return false; + case '[': + if (*s == '\0') + return false; + switch (j = rangematch(p + i, *s)) { + default: + i += j; + break; + case RANGE_FAIL: + return false; + case RANGE_ERROR: + if (*s != '[') + return false; + } + s++; + break; + default: + panic("bad metacharacter in match"); + /* NOTREACHED */ + return false; /* hush up gcc -Wall */ + } + } else if (p[i++] != *s++) + return false; + } } /* From the ed(1) man pages (on ranges): - The `-' is treated as an ordinary character if it occurs first - (or first after an initial ^) or last in the string. + The `-' is treated as an ordinary character if it occurs first + (or first after an initial ^) or last in the string. - The right square bracket does not terminate the enclosed string - if it is the first character (after an initial `^', if any), in - the bracketed string. + The right square bracket does not terminate the enclosed string + if it is the first character (after an initial `^', if any), in + the bracketed string. rangematch() matches a single character against a class, and returns an integer offset to the end of the range on success, or -1 on @@ -72,28 +72,28 @@ extern bool match(char *p, char *m, char *s) { */ static int rangematch(char *p, char c) { - char *orig = p; - bool neg = (*p == '~'); - bool matched = false; - if (neg) - p++; - if (*p == ']') { - p++; - matched = (c == ']'); - } - for (; *p != ']'; p++) { - if (*p == '\0') - return RANGE_ERROR; /* bad syntax */ - if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */ - if (c >= *p) - matched |= (c <= p[2]); - p += 2; - } else { - matched |= (*p == c); - } - } - if (matched ^ neg) - return p - orig + 1; /* skip the right-bracket */ - else - return RANGE_FAIL; + char *orig = p; + bool neg = (*p == '~'); + bool matched = false; + if (neg) + p++; + if (*p == ']') { + p++; + matched = (c == ']'); + } + for (; *p != ']'; p++) { + if (*p == '\0') + return RANGE_ERROR; /* bad syntax */ + if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */ + if (c >= *p) + matched |= (c <= p[2]); + p += 2; + } else { + matched |= (*p == c); + } + } + if (matched ^ neg) + return p - orig + 1; /* skip the right-bracket */ + else + return RANGE_FAIL; } diff --git a/mksignal.c b/mksignal.c index c66ad49..5f87a5a 100644 --- a/mksignal.c +++ b/mksignal.c @@ -16,178 +16,178 @@ struct signaming { static struct signaming signamings[] = { #ifdef SIGABRT - { SIGABRT, "sigabrt", "abort"}, + { SIGABRT, "sigabrt", "abort"}, #endif #ifdef SIGALRM - { SIGALRM, "sigalrm", "alarm clock"}, + { SIGALRM, "sigalrm", "alarm clock"}, #endif #ifdef SIGBREAK - { SIGBREAK, "sigbreak", "break"}, + { SIGBREAK, "sigbreak", "break"}, #endif #ifdef SIGBUS - { SIGBUS, "sigbus", "bus error"}, + { SIGBUS, "sigbus", "bus error"}, #endif #ifdef SIGCANCEL - { SIGCANCEL, "sigcancel", "thread cancellation"}, + { SIGCANCEL, "sigcancel", "thread cancellation"}, #endif #ifdef SIGCHLD - { SIGCHLD, "sigchld", "child stop or exit"}, + { SIGCHLD, "sigchld", "child stop or exit"}, #endif #ifdef SIGCLD - { SIGCLD, "sigcld", "child stop or exit"}, + { SIGCLD, "sigcld", "child stop or exit"}, #endif #ifdef SIGCONT - { SIGCONT, "sigcont", "continue"}, + { SIGCONT, "sigcont", "continue"}, #endif #ifdef SIGDIL - { SIGDIL, "sigdil", "dil signal"}, + { SIGDIL, "sigdil", "dil signal"}, #endif #ifdef SIGEMT - { SIGEMT, "sigemt", "emt instruction"}, + { SIGEMT, "sigemt", "emt instruction"}, #endif #ifdef SIGFPE - { SIGFPE, "sigfpe", "floating point error"}, + { SIGFPE, "sigfpe", "floating point error"}, #endif #ifdef SIGFREEZE - { SIGFREEZE, "sigfreeze", "cpr freeze"}, + { SIGFREEZE, "sigfreeze", "cpr freeze"}, #endif #ifdef SIGHUP - { SIGHUP, "sighup", "hangup"}, + { SIGHUP, "sighup", "hangup"}, #endif #ifdef SIGILL - { SIGILL, "sigill", "illegal instruction"}, + { SIGILL, "sigill", "illegal instruction"}, #endif /* We don't want a default message for SIGINT. */ #ifdef SIGINT - { SIGINT, "sigint", ""}, + { SIGINT, "sigint", ""}, #endif #ifdef SIGIO - { SIGIO, "sigio", "socket i/o possible"}, + { SIGIO, "sigio", "socket i/o possible"}, #endif #ifdef SIGIOT - { SIGIOT, "sigiot", "iot instruction"}, + { SIGIOT, "sigiot", "iot instruction"}, #endif #ifdef SIGKILL - { SIGKILL, "sigkill", "killed"}, + { SIGKILL, "sigkill", "killed"}, #endif #ifdef SIGLOST - { SIGLOST, "siglost", "resource lost"}, + { SIGLOST, "siglost", "resource lost"}, #endif #ifdef SIGLWP - { SIGLWP, "siglwp", "thread library signal"}, + { SIGLWP, "siglwp", "thread library signal"}, #endif /* By default, SIGPIPEs are silent. */ #ifdef SIGPIPE - { SIGPIPE, "sigpipe", ""}, + { SIGPIPE, "sigpipe", ""}, #endif #ifdef SIGPOLL - { SIGPOLL, "sigpoll", "pollable event occurred"}, + { SIGPOLL, "sigpoll", "pollable event occurred"}, #endif #ifdef SIGPROF - { SIGPROF, "sigprof", "profiling timer alarm"}, + { SIGPROF, "sigprof", "profiling timer alarm"}, #endif #ifdef SIGPWR - { SIGPWR, "sigpwr", "power-fail restart"}, + { SIGPWR, "sigpwr", "power-fail restart"}, #endif #ifdef SIGQUIT - { SIGQUIT, "sigquit", "quit"}, + { SIGQUIT, "sigquit", "quit"}, #endif #ifdef SIGSEGV - { SIGSEGV, "sigsegv", "segmentation violation"}, + { SIGSEGV, "sigsegv", "segmentation violation"}, #endif #ifdef SIGSTKFLT - { SIGSTKFLT, "sigstkflt", "stack fault"}, + { SIGSTKFLT, "sigstkflt", "stack fault"}, #endif #ifdef SIGSTOP - { SIGSTOP, "sigstop", "stopped by program"}, + { SIGSTOP, "sigstop", "stopped by program"}, #endif #ifdef SIGSYS - { SIGSYS, "sigsys", "invalid argument to system call"}, + { SIGSYS, "sigsys", "invalid argument to system call"}, #endif #ifdef SIGTERM - { SIGTERM, "sigterm", "terminated"}, + { SIGTERM, "sigterm", "terminated"}, #endif #ifdef SIGTHAW - { SIGTHAW, "sigthaw", "cpr thaw"}, + { SIGTHAW, "sigthaw", "cpr thaw"}, #endif #ifdef SIGTRAP - { SIGTRAP, "sigtrap", "trace trap"}, + { SIGTRAP, "sigtrap", "trace trap"}, #endif #ifdef SIGTSTP - { SIGTSTP, "sigtstp", "stopped"}, + { SIGTSTP, "sigtstp", "stopped"}, #endif #ifdef SIGTTIN - { SIGTTIN, "sigttin", "background tty read"}, + { SIGTTIN, "sigttin", "background tty read"}, #endif #ifdef SIGTTOU - { SIGTTOU, "sigttou", "background tty write"}, + { SIGTTOU, "sigttou", "background tty write"}, #endif #ifdef SIGURG - { SIGURG, "sigurg", "urgent condition on i/o channel"}, + { SIGURG, "sigurg", "urgent condition on i/o channel"}, #endif #ifdef SIGUSR1 - { SIGUSR1, "sigusr1", "user defined signal 1"}, + { SIGUSR1, "sigusr1", "user defined signal 1"}, #endif #ifdef SIGUSR2 - { SIGUSR2, "sigusr2", "user defined signal 2"}, + { SIGUSR2, "sigusr2", "user defined signal 2"}, #endif #ifdef SIGVTALRM - { SIGVTALRM, "sigvtalrm", "virtual timer alarm"}, + { SIGVTALRM, "sigvtalrm", "virtual timer alarm"}, #endif #ifdef SIGWAITING - { SIGWAITING, "sigwaiting", "lwps blocked"}, + { SIGWAITING, "sigwaiting", "lwps blocked"}, #endif #ifdef SIGWINCH - { SIGWINCH, "sigwinch", "window size change"}, + { SIGWINCH, "sigwinch", "window size change"}, #endif #ifdef SIGWINDOW - { SIGWINDOW, "sigwindow", "window size change"}, + { SIGWINDOW, "sigwindow", "window size change"}, #endif #ifdef SIGXCPU - { SIGXCPU, "sigxcpu", "exceeded cpu time limit"}, + { SIGXCPU, "sigxcpu", "exceeded cpu time limit"}, #endif #ifdef SIGXFSZ - { SIGXFSZ, "sigxfsz", "exceeded file size limit"}, + { SIGXFSZ, "sigxfsz", "exceeded file size limit"}, #endif #ifdef SIGSAK - { SIGSAK, "sigsak", "secure attention key"}, + { SIGSAK, "sigsak", "secure attention key"}, #endif #ifdef SIGSOUND - { SIGSOUND, "sigsound", "hft sound sequence completed"}, + { SIGSOUND, "sigsound", "hft sound sequence completed"}, #endif #ifdef SIGRETRACT - { SIGRETRACT, "sigretract", "hft monitor mode retracted"}, + { SIGRETRACT, "sigretract", "hft monitor mode retracted"}, #endif #ifdef SIGKAP - { SIGKAP, "sigkap", "keep alive poll"}, + { SIGKAP, "sigkap", "keep alive poll"}, #endif #ifdef SIGGRANT - { SIGGRANT, "siggrant", "hft monitor mode granted"}, + { SIGGRANT, "siggrant", "hft monitor mode granted"}, #endif #ifdef SIGALRM1 - { SIGALRM1, "sigalrm1", "m:n condition alarm"}, + { SIGALRM1, "sigalrm1", "m:n condition alarm"}, #endif #ifdef SIGVIRT - { SIGVIRT, "sigvirt", "virtual time alarm"}, + { SIGVIRT, "sigvirt", "virtual time alarm"}, #endif #ifdef SIGPRE - { SIGPRE, "sigpre", "programming error"}, + { SIGPRE, "sigpre", "programming error"}, #endif #ifdef SIGMIGRATE - { SIGMIGRATE, "sigmigrate", "migrate process"}, + { SIGMIGRATE, "sigmigrate", "migrate process"}, #endif #ifdef SIGDANGER - { SIGDANGER, "sigdanger", "system crash imminent"}, + { SIGDANGER, "sigdanger", "system crash imminent"}, #endif #ifdef SIGMSG - { SIGMSG, "sigmsg", "hft input data pending"}, + { SIGMSG, "sigmsg", "hft input data pending"}, #endif #ifdef SIGINFO - { SIGINFO, "siginfo", "information request"}, + { SIGINFO, "siginfo", "information request"}, #endif { 0, 0, 0} }; @@ -204,8 +204,8 @@ int main(void) { FILE *outf; for (snp = signamings; snp->signo; ++snp) - if (snp->signo > maxsig) - maxsig = snp->signo; + if (snp->signo > maxsig) + maxsig = snp->signo; outf = fopen("sigmsgs.h", "w"); if (!outf) barf("could not open sigmsgs.h for writing"); @@ -225,13 +225,13 @@ int main(void) { /* yes, we could avoid the quadratic searching with an aux array. fap. */ for (s = 1; s <= maxsig; ++s) { for (snp = signamings; snp->signo && snp->signo != s; ++snp) - /* */; - if (snp->signo) - fprintf(outf, "\t{\"%s\",\t\"%s\"},\n", - snp->signame, snp->sigmsg); - else - fprintf(outf, "\t{\"sigunknown%d\",\t\"unknown signal %d\"},\n", - s, s); + /* */; + if (snp->signo) + fprintf(outf, "\t{\"%s\",\t\"%s\"},\n", + snp->signame, snp->sigmsg); + else + fprintf(outf, "\t{\"sigunknown%d\",\t\"unknown signal %d\"},\n", + s, s); } fprintf(outf, "};\n"); if (fclose(outf) == EOF) barf("could not fclose sigmsgs.c after writing"); diff --git a/mkstatval.c b/mkstatval.c index c74ac46..3fdeba5 100644 --- a/mkstatval.c +++ b/mkstatval.c @@ -4,23 +4,23 @@ #include int main(void) { - int cstatus, pstatus; - pid_t pid; - - for (cstatus = 0; cstatus < 2; ++cstatus) { - switch (pid = fork()) { - case -1: - perror("fork"); - return 1; - case 0: - _exit(cstatus); - default: - if (wait(&pstatus) != pid) { - perror("wait"); - return 1; - } - printf("#define STATUS%d %d\n", cstatus, pstatus); - } - } - return 0; + int cstatus, pstatus; + pid_t pid; + + for (cstatus = 0; cstatus < 2; ++cstatus) { + switch (pid = fork()) { + case -1: + perror("fork"); + return 1; + case 0: + _exit(cstatus); + default: + if (wait(&pstatus) != pid) { + perror("wait"); + return 1; + } + printf("#define STATUS%d %d\n", cstatus, pstatus); + } + } + return 0; } diff --git a/nalloc.c b/nalloc.c index 0144b48..b5cc229 100644 --- a/nalloc.c +++ b/nalloc.c @@ -2,9 +2,9 @@ #include "rc.h" static struct Block { - size_t used, size; - char *mem; - Block *n; + size_t used, size; + char *mem; + Block *n; } *fl, *ul; /* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */ @@ -14,22 +14,22 @@ static struct Block { /* Allocate a block from the free list or malloc one if none in the fl fit */ static void getblock(size_t n) { - Block *r, *p; - for (r = fl, p = NULL; r != NULL; p = r, r = r->n) - if (n <= r->size) - break; /* look for a block which fits the request */ - if (r != NULL) { /* if one is found, take it off the free list */ - if (p != NULL) - p->n = r->n; - else - fl = r->n; - } else { /* else allocate a new block */ - r = enew(Block); - r->mem = ealloc(r->size = alignto(n, BLOCKSIZE)); - } - r->used = 0; - r->n = ul; - ul = r; + Block *r, *p; + for (r = fl, p = NULL; r != NULL; p = r, r = r->n) + if (n <= r->size) + break; /* look for a block which fits the request */ + if (r != NULL) { /* if one is found, take it off the free list */ + if (p != NULL) + p->n = r->n; + else + fl = r->n; + } else { /* else allocate a new block */ + r = enew(Block); + r->mem = ealloc(r->size = alignto(n, BLOCKSIZE)); + } + r->used = 0; + r->n = ul; + ul = r; } /* @@ -42,19 +42,19 @@ static void getblock(size_t n) { */ extern void *nalloc(size_t n) { - size_t base; - Block *ulp; - n = alignto(n, sizeof(align_t)); - ulp = ul; - if (ulp != NULL && n + (base = ulp->used) < ulp->size) { - ulp->used = base + n; - return &ulp->mem[base]; - } else { - getblock(n); - assert(ul->used == 0); - (ulp = ul)->used = n; - return &ulp->mem[0]; - } + size_t base; + Block *ulp; + n = alignto(n, sizeof(long)); + ulp = ul; + if (ulp != NULL && n + (base = ulp->used) < ulp->size) { + ulp->used = base + n; + return &ulp->mem[base]; + } else { + getblock(n); + assert(ul->used == 0); + (ulp = ul)->used = n; + return &ulp->mem[0]; + } } /* @@ -66,29 +66,29 @@ extern void *nalloc(size_t n) { #define MAXMEM 500000 extern void nfree() { - size_t count; - Block *r; - if (ul == NULL) - return; - for (r = ul; r->n != NULL; r = r->n) - ; /* get to end of used list */ - r->n = fl; /* tack free list onto it */ - fl = ul; /* and make it the free list */ - ul = NULL; /* finally, zero out the used list */ - for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) { - if (count >= MAXMEM) { - Block *tmp = r; - r = r->n; - tmp->n = NULL; /* terminate the free list */ - while (r != NULL) { /* free memory off the tail of the free list */ - tmp = r->n; - efree(r->mem); - efree(r); - r = tmp; - } - return; - } - } + size_t count; + Block *r; + if (ul == NULL) + return; + for (r = ul; r->n != NULL; r = r->n) + ; /* get to end of used list */ + r->n = fl; /* tack free list onto it */ + fl = ul; /* and make it the free list */ + ul = NULL; /* finally, zero out the used list */ + for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) { + if (count >= MAXMEM) { + Block *tmp = r; + r = r->n; + tmp->n = NULL; /* terminate the free list */ + while (r != NULL) { /* free memory off the tail of the free list */ + tmp = r->n; + efree(r->mem); + efree(r); + r = tmp; + } + return; + } + } } /* @@ -97,43 +97,43 @@ extern void nfree() { */ extern Block *newblock() { - Block *old = ul; - ul = NULL; - return old; + Block *old = ul; + ul = NULL; + return old; } /* "Restores" an arena to its saved value. */ extern void restoreblock(Block *old) { - nfree(); - ul = old; + nfree(); + ul = old; } /* generic memory allocation functions */ extern void *ealloc(size_t n) { - void *p; - - assert(n); - p = malloc(n); - if (p == NULL) { - uerror("malloc"); - rc_exit(1); - } - return p; + void *p; + + assert(n); + p = malloc(n); + if (p == NULL) { + uerror("malloc"); + rc_exit(1); + } + return p; } extern void *erealloc(void *p, size_t n) { - if (p == NULL) /* erealloc() has POSIX realloc() semantics */ - return ealloc(n); - if ((p = realloc(p, n)) == NULL) { - uerror("realloc"); - rc_exit(1); - } - return p; + if (p == NULL) /* erealloc() has POSIX realloc() semantics */ + return ealloc(n); + if ((p = realloc(p, n)) == NULL) { + uerror("realloc"); + rc_exit(1); + } + return p; } extern void efree(void *p) { - if (p != NULL) - free(p); + if (p != NULL) + free(p); } diff --git a/open.c b/open.c index af0f7f1..a932952 100644 --- a/open.c +++ b/open.c @@ -6,57 +6,57 @@ Opens a file with the necessary flags. Assumes the following declaration for redirtype: - enum redirtype { - rFrom, rCreate, rAppend, rHeredoc, rHerestring - }; + enum redirtype { + rFrom, rCreate, rAppend, rHeredoc, rHerestring + }; */ static const int mode_masks[] = { - /* rFrom */ O_RDONLY, - /* rCreate */ O_TRUNC | O_CREAT | O_WRONLY, - /* rAppend */ O_APPEND | O_CREAT | O_WRONLY + /* rFrom */ O_RDONLY, + /* rCreate */ O_TRUNC | O_CREAT | O_WRONLY, + /* rAppend */ O_APPEND | O_CREAT | O_WRONLY }; extern int rc_open(const char *name, redirtype m) { - if ((unsigned) m >= arraysize(mode_masks)) - panic("bad mode passed to rc_open"); - return open(name, mode_masks[m], 0666); + if ((unsigned) m >= arraysize(mode_masks)) + panic("bad mode passed to rc_open"); + return open(name, mode_masks[m], 0666); } /* make a file descriptor blocking. return value indicates whether the desciptor was previously set to non-blocking. */ extern bool makeblocking(int fd) { - int flags; - - if ((flags = fcntl(fd, F_GETFL)) == -1) { - uerror("fcntl"); - rc_error(NULL); - } - if (! (flags & O_NONBLOCK)) - return false; - flags &= ~O_NONBLOCK; - if (fcntl(fd, F_SETFL, (long) flags) == -1) { - uerror("fcntl"); - rc_error(NULL); - } - return true; + int flags; + + if ((flags = fcntl(fd, F_GETFL)) == -1) { + uerror("fcntl"); + rc_error(NULL); + } + if (! (flags & O_NONBLOCK)) + return false; + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, (long) flags) == -1) { + uerror("fcntl"); + rc_error(NULL); + } + return true; } /* make a file descriptor the same pgrp as us. Returns true if it changes anything. */ extern bool makesamepgrp(int fd) { - pid_t grp; + pid_t grp; - grp = getpgrp(); + grp = getpgrp(); - if (tcgetpgrp(fd) == grp) - return false; + if (tcgetpgrp(fd) == grp) + return false; - if (tcsetpgrp(fd, grp) < 0) { - uerror("tcsetgrp"); - return false; - } - return true; + if (tcsetpgrp(fd, grp) < 0) { + uerror("tcsetgrp"); + return false; + } + return true; } diff --git a/print.c b/print.c deleted file mode 100644 index ff8e9e5..0000000 --- a/print.c +++ /dev/null @@ -1,374 +0,0 @@ -/* print.c -- formatted printing routines (Paul Haahr, 12/91) */ - -#include "rc.h" - -#define PRINT_ALLOCSIZE ((size_t)64) -#define SPRINT_BUFSIZ ((size_t)1024) - -#define MAXCONV 256 - -/* - * conversion functions - * true return -> flag changes only, not a conversion - */ - -#define Flag(name, flag) \ -static bool name(Format *format, int ignore) { \ - format->flags |= flag; \ - return true; \ -} - -Flag(uconv, FMT_unsigned) -Flag(rc_lconv, FMT_long) -Flag(altconv, FMT_altform) -Flag(leftconv, FMT_leftside) -Flag(dotconv, FMT_f2set) - -static bool digitconv(Format *format, int c) { - if (format->flags & FMT_f2set) - format->f2 = 10 * format->f2 + c - '0'; - else { - format->flags |= FMT_f1set; - format->f1 = 10 * format->f1 + c - '0'; - } - return true; -} - -static bool zeroconv(Format *format, int ignore) { - if (format->flags & (FMT_f1set | FMT_f2set)) - return digitconv(format, '0'); - format->flags |= FMT_zeropad; - return true; -} - -static void pad(Format *format, size_t len, int c) { - while (len-- != 0) - fmtputc(format, c); -} - -static bool sconv(Format *format, int ignore) { - char *s = va_arg(format->args, char *); - if ((format->flags & FMT_f1set) == 0) - fmtcat(format, s); - else { - size_t len = strlen(s), width = format->f1 - len; - if (format->flags & FMT_leftside) { - fmtappend(format, s, len); - pad(format, width, ' '); - } else { - pad(format, width, ' '); - fmtappend(format, s, len); - } - } - return false; -} - -static char *rc_utoa(unsigned long u, char *t, unsigned int radix, const char *digit) { - if (u >= radix) { - t = rc_utoa(u / radix, t, radix, digit); - u %= radix; - } - *t++ = digit[u]; - return t; -} - -static void intconv(Format *format, unsigned int radix, int upper, const char *altform) { - static const char * const table[] = { - "0123456789abcdefghijklmnopqrstuvwxyz", - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", - }; - char padchar; - size_t len, pre, zeroes, padding, width; - long n, flags; - unsigned long u; - char number[64], prefix[20]; - - if (radix > 36) - return; - - flags = format->flags; - - if (flags & FMT_long) - n = va_arg(format->args, long); - else - n = va_arg(format->args, int); - - pre = 0; - if ((flags & FMT_unsigned) || n >= 0) - u = n; - else { - prefix[pre++] = '-'; - u = -n; - } - - if (flags & FMT_altform) - while (*altform != '\0') - prefix[pre++] = *altform++; - - len = rc_utoa(u, number, radix, table[upper]) - number; - if ((flags & FMT_f2set) && (size_t) format->f2 > len) - zeroes = format->f2 - len; - else - zeroes = 0; - - width = pre + zeroes + len; - if ((flags & FMT_f1set) && (size_t) format->f1 > width) { - padding = format->f1 - width; - } else - padding = 0; - - padchar = ' '; - if (padding > 0 && flags & FMT_zeropad) { - padchar = '0'; - if ((flags & FMT_leftside) == 0) { - zeroes += padding; - padding = 0; - } - } - - - if ((flags & FMT_leftside) == 0) - pad(format, padding, padchar); - fmtappend(format, prefix, pre); - pad(format, zeroes, '0'); - fmtappend(format, number, len); - if (flags & FMT_leftside) - pad(format, padding, padchar); -} - -static bool cconv(Format *format, int ignore) { - fmtputc(format, va_arg(format->args, int)); - return false; -} - -static bool dconv(Format *format, int ignore) { - intconv(format, 10, 0, ""); - return false; -} - -static bool oconv(Format *format, int ignore) { - intconv(format, 8, 0, "0"); - return false; -} - -static bool xconv(Format *format, int ignore) { - intconv(format, 16, 0, "0x"); - return false; -} - -static bool pctconv(Format *format, int ignore) { - fmtputc(format, '%'); - return false; -} - -static bool badconv(Format *ignore, int ign0re) { - panic("bad conversion character in printfmt"); - /* NOTREACHED */ - return false; /* hush up gcc -Wall */ -} - - -/* - * conversion table management - */ - -static Conv fmttab[MAXCONV]; - -static void inittab(void) { - int i; - for (i = 0; i < MAXCONV; i++) - fmttab[i] = badconv; - - fmttab['s'] = sconv; - fmttab['c'] = cconv; - fmttab['d'] = dconv; - fmttab['o'] = oconv; - fmttab['x'] = xconv; - fmttab['%'] = pctconv; - - fmttab['u'] = uconv; - fmttab['l'] = rc_lconv; - fmttab['#'] = altconv; - fmttab['-'] = leftconv; - fmttab['.'] = dotconv; - - fmttab['0'] = zeroconv; - for (i = '1'; i <= '9'; i++) - fmttab[i] = digitconv; -} - -extern bool (*fmtinstall(int c, bool (*f)(Format *, int)))(Format *, int) { -/*Conv fmtinstall(int c, Conv f) {*/ - Conv oldf; - if (fmttab[0] == NULL) - inittab(); - c &= MAXCONV - 1; - oldf = fmttab[c]; - if (f != NULL) - fmttab[c] = f; - return oldf; -} - - -/* - * functions for inserting strings in the format buffer - */ - -extern void fmtappend(Format *format, const char *s, size_t len) { - while (format->buf + len > format->bufend) { - size_t split = format->bufend - format->buf; - memcpy(format->buf, s, split); - format->buf += split; - s += split; - len -= split; - (*format->grow)(format, len); - } - memcpy(format->buf, s, len); - format->buf += len; -} - -extern void fmtcat(Format *format, const char *s) { - fmtappend(format, s, strlen(s)); -} - -/* - * printfmt -- the driver routine - */ - -extern int printfmt(Format *format, const char *fmt) { - unsigned const char *s = (unsigned const char *) fmt; - - if (fmttab[0] == NULL) - inittab(); - - for (;;) { - int c = *s++; - switch (c) { - case '%': - format->flags = format->f1 = format->f2 = 0; - do - c = *s++; - while ((*fmttab[c])(format, c)); - break; - case '\0': - return format->buf - format->bufbegin + format->flushed; - default: - fmtputc(format, c); - break; - } - } -} - - -/* - * the public entry points - */ - -extern int fmtprint(Format *format, const char *fmt,...) { - int n = -format->flushed; - va_list ap, saveargs; - - va_start(ap, fmt); - va_copy(saveargs, format->args); - va_copy(format->args, ap); - n += printfmt(format, fmt); - va_end(format->args); - va_copy(format->args, saveargs); - - return n + format->flushed; -} - -static void fprint_flush(Format *format, size_t ignore) { - size_t n = format->buf - format->bufbegin; - char *buf = format->bufbegin; - - format->flushed += n; - format->buf = format->bufbegin; - writeall(format->u.n, buf, n); -} - -extern int fprint(int fd, const char *fmt,...) { - char buf[1024]; - Format format; - va_list ap; - - format.buf = buf; - format.bufbegin = buf; - format.bufend = buf + sizeof buf; - format.grow = fprint_flush; - format.flushed = 0; - format.u.n = fd; - - va_start(ap, fmt); - va_copy(format.args, ap); - printfmt(&format, fmt); - va_end(format.args); - - fprint_flush(&format, 0); - return format.flushed; -} - -static void memprint_grow(Format *format, size_t more) { - char *buf; - size_t len = format->bufend - format->bufbegin + 1; - size_t used = format->buf - format->bufbegin; - - len = (len >= more) - ? len * 2 - : ((len + more) + PRINT_ALLOCSIZE) &~ (PRINT_ALLOCSIZE - 1); - if (format->u.n) - buf = erealloc(format->bufbegin, len); - else { - buf = nalloc(len); - memcpy(buf, format->bufbegin, used); - } - format->buf = buf + used; - format->bufbegin = buf; - format->bufend = buf + len - 1; -} - -static char *memprint(Format *format, const char *fmt, char *buf, size_t len) { - format->buf = buf; - format->bufbegin = buf; - format->bufend = buf + len - 1; - format->grow = memprint_grow; - format->flushed = 0; - printfmt(format, fmt); - *format->buf = '\0'; - return format->bufbegin; -} - -extern char *mprint(const char *fmt,...) { - Format format; - char *result; - va_list ap; - - format.u.n = 1; - va_start(ap, fmt); - va_copy(format.args, ap); - result = memprint(&format, fmt, ealloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE); - va_end(format.args); - return result; -} - -extern char *nprint(const char *fmt,...) { - Format format; - char *result; - va_list ap; - - format.u.n = 0; - va_start(ap, fmt); - va_copy(format.args, ap); - result = memprint(&format, fmt, nalloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE); - va_end(format.args); - return result; -} - -extern void writeall(int fd, char *buf, size_t remain) { - int i; - - for (i = 0; remain > 0; buf += i, remain -= i) - if ((i = write(fd, buf, remain)) <= 0) - break; /* abort silently on errors in write() */ - sigchk(); -} diff --git a/redir.c b/redir.c index 54e4415..e763809 100644 --- a/redir.c +++ b/redir.c @@ -14,64 +14,64 @@ */ extern void doredirs() { - List *fname; - int fd, p[2]; - Rq *r; - for (r = redirq; r != NULL; r = r->n) { - switch(r->r->type) { - default: - panic("unexpected node in doredirs"); - /* NOTREACHED */ - case nRedir: - if (r->r->u[0].i == rHerestring) { - fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */ - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if (rc_fork() == 0) { /* child writes to pipe */ - setsigdefaults(false); - close(p[0]); - if (fname != NULL) - writeall(p[1], fname->w, strlen(fname->w)); - exit(0); - } else { - close(p[1]); - if (mvfd(p[0], r->r->u[1].i) < 0) - rc_error(NULL); - } - } else { - fname = glob(glom(r->r->u[2].p)); - if (fname == NULL) - rc_error("null filename in redirection"); - if (fname->n != NULL) - rc_error("multi-word filename in redirection"); - switch (r->r->u[0].i) { - default: - panic("unexpected node in doredirs"); - /* NOTREACHED */ - case rCreate: case rAppend: case rFrom: - fd = rc_open(fname->w, r->r->u[0].i); - break; - } - if (fd < 0) { - uerror(fname->w); - rc_error(NULL); - } - if (mvfd(fd, r->r->u[1].i) < 0) - rc_error(NULL); - } - break; - case nDup: - if (r->r->u[2].i == -1) - close(r->r->u[1].i); - else if (r->r->u[2].i != r->r->u[1].i) { - if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) { - uerror("dup2"); - rc_error(NULL); - } - } - } - } - redirq = NULL; + List *fname; + int fd, p[2]; + Rq *r; + for (r = redirq; r != NULL; r = r->n) { + switch(r->r->type) { + default: + panic("unexpected node in doredirs"); + /* NOTREACHED */ + case nRedir: + if (r->r->u[0].i == rHerestring) { + fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */ + if (pipe(p) < 0) { + uerror("pipe"); + rc_error(NULL); + } + if (rc_fork() == 0) { /* child writes to pipe */ + setsigdefaults(false); + close(p[0]); + if (fname != NULL) + writeall(p[1], fname->w, strlen(fname->w)); + exit(0); + } else { + close(p[1]); + if (mvfd(p[0], r->r->u[1].i) < 0) + rc_error(NULL); + } + } else { + fname = glob(glom(r->r->u[2].p)); + if (fname == NULL) + rc_error("null filename in redirection"); + if (fname->n != NULL) + rc_error("multi-word filename in redirection"); + switch (r->r->u[0].i) { + default: + panic("unexpected node in doredirs"); + /* NOTREACHED */ + case rCreate: case rAppend: case rFrom: + fd = rc_open(fname->w, r->r->u[0].i); + break; + } + if (fd < 0) { + uerror(fname->w); + rc_error(NULL); + } + if (mvfd(fd, r->r->u[1].i) < 0) + rc_error(NULL); + } + break; + case nDup: + if (r->r->u[2].i == -1) + close(r->r->u[1].i); + else if (r->r->u[2].i != r->r->u[1].i) { + if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) { + uerror("dup2"); + rc_error(NULL); + } + } + } + } + redirq = NULL; } diff --git a/signal.c b/signal.c index 7131ae6..4cb6364 100644 --- a/signal.c +++ b/signal.c @@ -3,13 +3,13 @@ #include "rc.h" void (*sys_signal(int signum, void (*handler)(int)))(int) { - struct sigaction new, old; + struct sigaction new, old; - new.sa_handler = handler; - new.sa_flags = 0; /* clear SA_RESTART */ - sigfillset(&new.sa_mask); - sigaction(signum, &new, &old); - return old.sa_handler; + new.sa_handler = handler; + new.sa_flags = 0; /* clear SA_RESTART */ + sigfillset(&new.sa_mask); + sigaction(signum, &new, &old); + return old.sa_handler; } void (*sighandlers[NSIG])(int); @@ -17,63 +17,63 @@ void (*sighandlers[NSIG])(int); static volatile sig_atomic_t sigcount, caught[NSIG]; extern void catcher(int s) { - if (caught[s] == 0) { - sigcount++; - caught[s] = 1; - } - sys_signal(s, catcher); + if (caught[s] == 0) { + sigcount++; + caught[s] = 1; + } + sys_signal(s, catcher); } extern void sigchk() { - void (*h)(int); - int s, i; + void (*h)(int); + int s, i; - if (sigcount == 0) - return; /* ho hum; life as usual */ - if (forked) - exit(1); /* exit unconditionally on a signal in a child process */ - for (i = 0, s = -1; i < NSIG; i++) - if (caught[i] != 0) { - s = i; - --sigcount; - caught[s] = 0; - break; - } - if (s == -1) - panic("all-zero sig vector with nonzero sigcount"); - if ((h = sighandlers[s]) == SIG_DFL) - panic("caught signal set to SIG_DFL"); - if (h == SIG_IGN) - panic("caught signal set to SIG_IGN"); - (*h)(s); + if (sigcount == 0) + return; /* ho hum; life as usual */ + if (forked) + exit(1); /* exit unconditionally on a signal in a child process */ + for (i = 0, s = -1; i < NSIG; i++) + if (caught[i] != 0) { + s = i; + --sigcount; + caught[s] = 0; + break; + } + if (s == -1) + panic("all-zero sig vector with nonzero sigcount"); + if ((h = sighandlers[s]) == SIG_DFL) + panic("caught signal set to SIG_DFL"); + if (h == SIG_IGN) + panic("caught signal set to SIG_IGN"); + (*h)(s); } extern void (*rc_signal(int s, void (*h)(int)))(int) { - void (*old)(int); - sigchk(); - old = sighandlers[s]; - sighandlers[s] = h; - if (h == SIG_DFL || h == SIG_IGN) - sys_signal(s, h); - else - sys_signal(s, catcher); - return old; + void (*old)(int); + sigchk(); + old = sighandlers[s]; + sighandlers[s] = h; + if (h == SIG_DFL || h == SIG_IGN) + sys_signal(s, h); + else + sys_signal(s, catcher); + return old; } extern void initsignal() { - void (*h)(int); - int i; + void (*h)(int); + int i; - for (i = 1; i < NSIG; i++) { + for (i = 1; i < NSIG; i++) { #ifdef SIGKILL - if (i == SIGKILL) continue; + if (i == SIGKILL) continue; #endif #ifdef SIGSTOP - if (i == SIGSTOP) continue; + if (i == SIGSTOP) continue; #endif - h = sys_signal(i, SIG_IGN); - if (h != SIG_IGN && h != SIG_ERR) - sys_signal(i, h); - sighandlers[i] = h; - } + h = sys_signal(i, SIG_IGN); + if (h != SIG_IGN && h != SIG_ERR) + sys_signal(i, h); + sighandlers[i] = h; + } } diff --git a/status.c b/status.c index ae4fef5..daac586 100644 --- a/status.c +++ b/status.c @@ -16,11 +16,11 @@ static int pipelength = 1; */ extern int istrue() { - int i; - for (i = 0; i < pipelength; i++) - if (statuses[i] != 0) - return false; - return true; + int i; + for (i = 0; i < pipelength; i++) + if (statuses[i] != 0) + return false; + return true; } /* @@ -31,119 +31,119 @@ extern int istrue() { */ extern int getstatus() { - int s; - if (pipelength > 1) - return !istrue(); - s = statuses[0]; - if (WIFSIGNALED(s)) - return 1; - return WEXITSTATUS(s); + int s; + if (pipelength > 1) + return !istrue(); + s = statuses[0]; + if (WIFSIGNALED(s)) + return 1; + return WEXITSTATUS(s); } extern void set(bool code) { - setstatus(-1, code ? STATUS0 : STATUS1); + setstatus(-1, code ? STATUS0 : STATUS1); } /* take a pipeline and store the exit statuses. Check to see whether any of the children dumped core */ extern void setpipestatus(int stats[], int num) { - int i; - for (i = 0; i < (pipelength = num); i++) { - statprint(-1, stats[i]); - statuses[i] = stats[i]; - } + int i; + for (i = 0; i < (pipelength = num); i++) { + statprint(-1, stats[i]); + statuses[i] = stats[i]; + } } /* set a simple status, as opposed to a pipeline */ extern void setstatus(pid_t pid, int i) { - pipelength = 1; - statuses[0] = i; - statprint(pid, i); + pipelength = 1; + statuses[0] = i; + statprint(pid, i); } /* print a message if termination was with a signal, and if the child dumped core. exit on error if -e is set */ extern void statprint(pid_t pid, int i) { - if (WIFSIGNALED(i)) { - int t = WTERMSIG(i); - char *msg = ((t > 0) && (t < NSIG) ? signals[WTERMSIG(i)].msg : ""); - if (pid != -1) - fprint(2, "%ld: ", (long)pid); - if (myWIFDUMPED(i)) { - if (*msg == '\0') - fprint(2, "core dumped\n"); - else - fprint(2, "%s--core dumped\n", msg); - } else if (*msg != '\0') - fprint(2, "%s\n", msg); - } + if (WIFSIGNALED(i)) { + int t = WTERMSIG(i); + char *msg = ((t > 0) && (t < NSIG) ? signals[WTERMSIG(i)].msg : ""); + if (pid != -1) + fprintf(stderr, "%ld: ", (long)pid); + if (myWIFDUMPED(i)) { + if (*msg == '\0') + fprintf(stderr, "core dumped\n"); + else + fprintf(stderr, "%s--core dumped\n", msg); + } else if (*msg != '\0') + fprintf(stderr, "%s\n", msg); + } } /* prepare a list to be passed back. Used whenever $status is dereferenced */ extern List *sgetstatus() { - List *r = NULL; - int i; - - for (i = 0; i < pipelength; i++) { - List *q = nnew(List); - q->w = strstatus(statuses[i]); - q->m = NULL; - q->n = r; - r = q; - } - - return r; + List *r = NULL; + int i; + + for (i = 0; i < pipelength; i++) { + List *q = nnew(List); + q->w = strstatus(statuses[i]); + q->m = NULL; + q->n = r; + r = q; + } + + return r; } /* return status as a string (used above and for bqstatus) */ extern char *strstatus(int s) { - if (WIFSIGNALED(s)) { - int t = WTERMSIG(s); - const char *core = myWIFDUMPED(s) ? "+core" : ""; - if ((t > 0) && (t < NSIG) && *signals[t].name != '\0') - return nprint("%s%s", signals[t].name, core); - else - return nprint("-%d%s", t, core); /* unknown signals are negated */ - } else - return nprint("%d", WEXITSTATUS(s)); + if (WIFSIGNALED(s)) { + int t = WTERMSIG(s); + const char *core = myWIFDUMPED(s) ? "+core" : ""; + if ((t > 0) && (t < NSIG) && *signals[t].name != '\0') + return nprint("%s%s", signals[t].name, core); + else + return nprint("-%d%s", t, core); /* unknown signals are negated */ + } else + return nprint("%d", WEXITSTATUS(s)); } extern void ssetstatus(char **av) { - int i, j, k, l; - bool found; - for (l = 0; av[l] != NULL; l++) - ; /* count up array length */ - --l; - for (i = 0; av[i] != NULL; i++) { - j = a2u(av[i]); - if (j >= 0) { - statuses[l - i] = j << 8; - continue; - } - found = false; - for (k = 0; k < NSIG; k++) { - if (streq(signals[k].name, av[i])) { - statuses[l - i] = k; - found = true; - break; - } - else { - size_t len = strlen(signals[k].name); - if (strncmp(signals[k].name, av[i], len) == 0 && streq(av[i] + len, "+core")) { - statuses[l - i] = k + 0x80; - found = true; - break; - } - } - } - if (!found) { - fprint(2, "bad status\n"); - set(false); - return; - } - } - pipelength = i; + int i, j, k, l; + bool found; + for (l = 0; av[l] != NULL; l++) + ; /* count up array length */ + --l; + for (i = 0; av[i] != NULL; i++) { + j = a2u(av[i]); + if (j >= 0) { + statuses[l - i] = j << 8; + continue; + } + found = false; + for (k = 0; k < NSIG; k++) { + if (streq(signals[k].name, av[i])) { + statuses[l - i] = k; + found = true; + break; + } + else { + size_t len = strlen(signals[k].name); + if (strncmp(signals[k].name, av[i], len) == 0 && streq(av[i] + len, "+core")) { + statuses[l - i] = k + 0x80; + found = true; + break; + } + } + } + if (!found) { + fprintf(stderr, "bad status\n"); + set(false); + return; + } + } + pipelength = i; } diff --git a/tree.c b/tree.c index 60b42e3..d670b7f 100644 --- a/tree.c +++ b/tree.c @@ -5,170 +5,170 @@ /* make a new node, pass it back to yyparse. Used to generate the parsetree. */ extern Node *mk(int /*nodetype*/ t,...) { - va_list ap; - Node *n; - va_start(ap, t); - switch (t) { - default: - panic("unexpected node in mk"); - /* NOTREACHED */ - case nDup: - n = nalloc(offsetof(Node, u[3])); - n->u[0].i = va_arg(ap, int); - n->u[1].i = va_arg(ap, int); - n->u[2].i = va_arg(ap, int); - break; - case nWord: - n = nalloc(offsetof(Node, u[3])); - n->u[0].s = va_arg(ap, char *); - n->u[1].s = va_arg(ap, char *); - n->u[2].i = va_arg(ap, int); - break; - case nBang: case nNowait: - case nCount: case nFlat: case nRmfn: case nSubshell: - case nVar: case nCase: - n = nalloc(offsetof(Node, u[1])); - n->u[0].p = va_arg(ap, Node *); - break; - case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: - case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: - case nOrelse: case nPre: case nArgs: case nSwitch: - case nMatch: case nVarsub: case nWhile: case nLappend: - n = nalloc(offsetof(Node, u[2])); - n->u[0].p = va_arg(ap, Node *); - n->u[1].p = va_arg(ap, Node *); - break; - case nForin: - n = nalloc(offsetof(Node, u[3])); - n->u[0].p = va_arg(ap, Node *); - n->u[1].p = va_arg(ap, Node *); - n->u[2].p = va_arg(ap, Node *); - break; - case nPipe: - n = nalloc(offsetof(Node, u[4])); - n->u[0].i = va_arg(ap, int); - n->u[1].i = va_arg(ap, int); - n->u[2].p = va_arg(ap, Node *); - n->u[3].p = va_arg(ap, Node *); - break; - case nRedir: - case nNmpipe: - n = nalloc(offsetof(Node, u[3])); - n->u[0].i = va_arg(ap, int); - n->u[1].i = va_arg(ap, int); - n->u[2].p = va_arg(ap, Node *); - break; - } - n->type = t; - va_end(ap); - return n; + va_list ap; + Node *n; + va_start(ap, t); + switch (t) { + default: + panic("unexpected node in mk"); + /* NOTREACHED */ + case nDup: + n = nalloc(offsetof(Node, u[3])); + n->u[0].i = va_arg(ap, int); + n->u[1].i = va_arg(ap, int); + n->u[2].i = va_arg(ap, int); + break; + case nWord: + n = nalloc(offsetof(Node, u[3])); + n->u[0].s = va_arg(ap, char *); + n->u[1].s = va_arg(ap, char *); + n->u[2].i = va_arg(ap, int); + break; + case nBang: case nNowait: + case nCount: case nFlat: case nRmfn: case nSubshell: + case nVar: case nCase: + n = nalloc(offsetof(Node, u[1])); + n->u[0].p = va_arg(ap, Node *); + break; + case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: + case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: + case nOrelse: case nPre: case nArgs: case nSwitch: + case nMatch: case nVarsub: case nWhile: case nLappend: + n = nalloc(offsetof(Node, u[2])); + n->u[0].p = va_arg(ap, Node *); + n->u[1].p = va_arg(ap, Node *); + break; + case nForin: + n = nalloc(offsetof(Node, u[3])); + n->u[0].p = va_arg(ap, Node *); + n->u[1].p = va_arg(ap, Node *); + n->u[2].p = va_arg(ap, Node *); + break; + case nPipe: + n = nalloc(offsetof(Node, u[4])); + n->u[0].i = va_arg(ap, int); + n->u[1].i = va_arg(ap, int); + n->u[2].p = va_arg(ap, Node *); + n->u[3].p = va_arg(ap, Node *); + break; + case nRedir: + case nNmpipe: + n = nalloc(offsetof(Node, u[3])); + n->u[0].i = va_arg(ap, int); + n->u[1].i = va_arg(ap, int); + n->u[2].p = va_arg(ap, Node *); + break; + } + n->type = t; + va_end(ap); + return n; } /* copy a tree to malloc space. Used when storing the definition of a function */ extern Node *treecpy(Node *s, void *(*alloc)(size_t)) { - Node *n; - if (s == NULL) - return NULL; - switch (s->type) { - default: - panic("unexpected node in treecpy"); - /* NOTREACHED */ - case nDup: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].i = s->u[0].i; - n->u[1].i = s->u[1].i; - n->u[2].i = s->u[2].i; - break; - case nWord: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].s = strcpy((char *) (*alloc)(strlen(s->u[0].s) + 1), s->u[0].s); - if (s->u[1].s != NULL) { - size_t i = strlen(s->u[0].s); - n->u[1].s = (*alloc)(i); - memcpy(n->u[1].s, s->u[1].s, i); - } else - n->u[1].s = NULL; - n->u[2].i = s->u[2].i; - break; - case nBang: case nNowait: case nCase: - case nCount: case nFlat: case nRmfn: case nSubshell: case nVar: - n = (*alloc)(offsetof(Node, u[1])); - n->u[0].p = treecpy(s->u[0].p, alloc); - break; - case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: - case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: - case nOrelse: case nPre: case nArgs: case nSwitch: - case nMatch: case nVarsub: case nWhile: case nLappend: - n = (*alloc)(offsetof(Node, u[2])); - n->u[0].p = treecpy(s->u[0].p, alloc); - n->u[1].p = treecpy(s->u[1].p, alloc); - break; - case nForin: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].p = treecpy(s->u[0].p, alloc); - n->u[1].p = treecpy(s->u[1].p, alloc); - n->u[2].p = treecpy(s->u[2].p, alloc); - break; - case nPipe: - n = (*alloc)(offsetof(Node, u[4])); - n->u[0].i = s->u[0].i; - n->u[1].i = s->u[1].i; - n->u[2].p = treecpy(s->u[2].p, alloc); - n->u[3].p = treecpy(s->u[3].p, alloc); - break; - case nRedir: - case nNmpipe: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].i = s->u[0].i; - n->u[1].i = s->u[1].i; - n->u[2].p = treecpy(s->u[2].p, alloc); - break; - } - n->type = s->type; - return n; + Node *n; + if (s == NULL) + return NULL; + switch (s->type) { + default: + panic("unexpected node in treecpy"); + /* NOTREACHED */ + case nDup: + n = (*alloc)(offsetof(Node, u[3])); + n->u[0].i = s->u[0].i; + n->u[1].i = s->u[1].i; + n->u[2].i = s->u[2].i; + break; + case nWord: + n = (*alloc)(offsetof(Node, u[3])); + n->u[0].s = strcpy((char *) (*alloc)(strlen(s->u[0].s) + 1), s->u[0].s); + if (s->u[1].s != NULL) { + size_t i = strlen(s->u[0].s); + n->u[1].s = (*alloc)(i); + memcpy(n->u[1].s, s->u[1].s, i); + } else + n->u[1].s = NULL; + n->u[2].i = s->u[2].i; + break; + case nBang: case nNowait: case nCase: + case nCount: case nFlat: case nRmfn: case nSubshell: case nVar: + n = (*alloc)(offsetof(Node, u[1])); + n->u[0].p = treecpy(s->u[0].p, alloc); + break; + case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: + case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: + case nOrelse: case nPre: case nArgs: case nSwitch: + case nMatch: case nVarsub: case nWhile: case nLappend: + n = (*alloc)(offsetof(Node, u[2])); + n->u[0].p = treecpy(s->u[0].p, alloc); + n->u[1].p = treecpy(s->u[1].p, alloc); + break; + case nForin: + n = (*alloc)(offsetof(Node, u[3])); + n->u[0].p = treecpy(s->u[0].p, alloc); + n->u[1].p = treecpy(s->u[1].p, alloc); + n->u[2].p = treecpy(s->u[2].p, alloc); + break; + case nPipe: + n = (*alloc)(offsetof(Node, u[4])); + n->u[0].i = s->u[0].i; + n->u[1].i = s->u[1].i; + n->u[2].p = treecpy(s->u[2].p, alloc); + n->u[3].p = treecpy(s->u[3].p, alloc); + break; + case nRedir: + case nNmpipe: + n = (*alloc)(offsetof(Node, u[3])); + n->u[0].i = s->u[0].i; + n->u[1].i = s->u[1].i; + n->u[2].p = treecpy(s->u[2].p, alloc); + break; + } + n->type = s->type; + return n; } /* free a function definition that is no longer needed */ extern void treefree(Node *s) { - if (s == NULL) - return; - switch (s->type) { - default: - panic("unexpected node in treefree"); - /* NOTREACHED */ - case nDup: - break; - case nWord: - efree(s->u[0].s); - efree(s->u[1].s); - break; - case nBang: case nNowait: - case nCount: case nFlat: case nRmfn: - case nSubshell: case nVar: case nCase: - treefree(s->u[0].p); - break; - case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: - case nElse: case nEpilog: case nIf: case nNewfn: - case nOrelse: case nPre: case nArgs: case nCbody: - case nSwitch: case nMatch: case nVarsub: case nWhile: - case nLappend: - treefree(s->u[1].p); - treefree(s->u[0].p); - break; - case nForin: - treefree(s->u[2].p); - treefree(s->u[1].p); - treefree(s->u[0].p); - break; - case nPipe: - treefree(s->u[2].p); - treefree(s->u[3].p); - break; - case nRedir: - case nNmpipe: - treefree(s->u[2].p); - } - efree(s); + if (s == NULL) + return; + switch (s->type) { + default: + panic("unexpected node in treefree"); + /* NOTREACHED */ + case nDup: + break; + case nWord: + efree(s->u[0].s); + efree(s->u[1].s); + break; + case nBang: case nNowait: + case nCount: case nFlat: case nRmfn: + case nSubshell: case nVar: case nCase: + treefree(s->u[0].p); + break; + case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: + case nElse: case nEpilog: case nIf: case nNewfn: + case nOrelse: case nPre: case nArgs: case nCbody: + case nSwitch: case nMatch: case nVarsub: case nWhile: + case nLappend: + treefree(s->u[1].p); + treefree(s->u[0].p); + break; + case nForin: + treefree(s->u[2].p); + treefree(s->u[1].p); + treefree(s->u[0].p); + break; + case nPipe: + treefree(s->u[2].p); + treefree(s->u[3].p); + break; + case nRedir: + case nNmpipe: + treefree(s->u[2].p); + } + efree(s); } diff --git a/utils.c b/utils.c index 3747520..aa2697d 100644 --- a/utils.c +++ b/utils.c @@ -5,26 +5,26 @@ /* print error with line number on noninteractive shells (i.e., scripts) */ extern void pr_error(char *s, int offset) { - if (s != NULL) { - if (interactive) - fprint(2, RC "%s\n", s); - else - fprint(2, RC "line %d: %s\n", lineno + offset, s); - } + if (s != NULL) { + if (interactive) + fprintf(stderr, RC "%s\n", s); + else + fprintf(stderr, RC "line %d: %s\n", lineno + offset, s); + } } /* our perror */ extern void uerror(char *s) { - char *err; + char *err; - err = strerror(errno); - if (!err) err = "unknown error"; + err = strerror(errno); + if (!err) err = "unknown error"; - if (s) - fprint(2, RC "%s: %s\n", s, err); - else - fprint(2, RC "%s\n", err); + if (s) + fprintf(stderr, RC "%s: %s\n", s, err); + else + fprintf(stderr, RC "%s\n", err); } /* Die horribly. This should never get called. Please let me know if it does. */ @@ -32,45 +32,45 @@ extern void uerror(char *s) { #define PANICMSG "rc panic: " extern void panic(char *s) { - write(2, PANICMSG, conststrlen(PANICMSG)); - write(2, s, strlen(s)); - write(2, "!\n", 2); - exit(1); + write(2, PANICMSG, conststrlen(PANICMSG)); + write(2, s, strlen(s)); + write(2, "!\n", 2); + exit(1); } /* ascii -> unsigned conversion routines. -1 indicates conversion error. */ extern int n2u(char *s, unsigned int base) { - unsigned int i; - for (i = 0; *s != '\0'; s++) { - unsigned int j = (unsigned int) *s - '0'; - if (j >= base) /* small hack with unsigned ints -- one compare for range test */ - return -1; - i = i * base + j; - } - return (int) i; + unsigned int i; + for (i = 0; *s != '\0'; s++) { + unsigned int j = (unsigned int) *s - '0'; + if (j >= base) /* small hack with unsigned ints -- one compare for range test */ + return -1; + i = i * base + j; + } + return (int) i; } /* The last word in portable ANSI: a strcmp wrapper for qsort */ extern int starstrcmp(const void *s1, const void *s2) { - return strcmp(*(char * const *)s1, *(char * const *)s2); + return strcmp(*(char * const *)s1, *(char * const *)s2); } /* tests to see if pathname begins with "/", "./", or "../" */ extern bool isabsolute(char *path) { - return path[0] == '/' || (path[0] == '.' && (path[1] == '/' || (path[1] == '.' && path[2] == '/'))); + return path[0] == '/' || (path[0] == '.' && (path[1] == '/' || (path[1] == '.' && path[2] == '/'))); } /* duplicate a fd and close the old one only if necessary */ extern int mvfd(int i, int j) { - if (i != j) { - int s = dup2(i, j); - close(i); - return s; - } - return 0; + if (i != j) { + int s = dup2(i, j); + close(i); + return s; + } + return 0; } diff --git a/var.c b/var.c index 6853077..66e049c 100644 --- a/var.c +++ b/var.c @@ -7,45 +7,45 @@ static void listassign(char *, List *, bool); static int hasalias(char *); static char *const aliases[] = { - "home", "HOME", "path", "PATH", "cdpath", "CDPATH" + "home", "HOME", "path", "PATH", "cdpath", "CDPATH" }; /* assign a variable in List form to a name, stacking if appropriate */ extern void varassign(char *name, List *def, bool stack) { - Variable *new; - List *newdef = listcpy(def, ealloc); /* important to do the listcpy first; get_var_place() frees old values */ - new = get_var_place(name, stack); - new->def = newdef; - new->extdef = NULL; - set_exportable(name, true); + Variable *new; + List *newdef = listcpy(def, ealloc); /* important to do the listcpy first; get_var_place() frees old values */ + new = get_var_place(name, stack); + new->def = newdef; + new->extdef = NULL; + set_exportable(name, true); } /* assign a variable in string form. Check to see if it is aliased (e.g., PATH and path) */ extern bool varassign_string(char *extdef) { - static bool aliasset[arraysize(aliases)] = { - false, false, false, false, false, false - }; - char *name = get_name(extdef); - Variable *new; - int i; - if (name == NULL) - return false; /* add it to bozo env */ - if ((i = hasalias(name)) != -1) { - aliasset[i] = true; - i ^= 1; /* set i to the "opposite" case subscript and */ - if (i&1 && aliasset[i]) /* don't alias variables that are already set in upper case */ - return true; - } - new = get_var_place(name, false); - new->def = NULL; - new->extdef = ealloc(strlen(extdef) + 1); - strcpy(new->extdef, extdef); - if (i != -1) - alias(name, varlookup(name), false); - set_exportable(name, true); - return true; + static bool aliasset[arraysize(aliases)] = { + false, false, false, false, false, false + }; + char *name = get_name(extdef); + Variable *new; + int i; + if (name == NULL) + return false; /* add it to bozo env */ + if ((i = hasalias(name)) != -1) { + aliasset[i] = true; + i ^= 1; /* set i to the "opposite" case subscript and */ + if (i&1 && aliasset[i]) /* don't alias variables that are already set in upper case */ + return true; + } + new = get_var_place(name, false); + new->def = NULL; + new->extdef = ealloc(strlen(extdef) + 1); + strcpy(new->extdef, extdef); + if (i != -1) + alias(name, varlookup(name), false); + set_exportable(name, true); + return true; } /* @@ -56,166 +56,166 @@ extern bool varassign_string(char *extdef) { */ extern List *varlookup(char *name) { - Variable *look; - List *ret, *l; - int sub; - if (streq(name, "apids")) - return sgetapids(); - if (streq(name, "status")) - return sgetstatus(); - if (*name != '\0' && (sub = a2u(name)) != -1) { /* handle $1, $2, etc. */ - for (l = varlookup("*"); l != NULL && sub != 0; --sub) - l = l->n; - if (l == NULL) - return NULL; - ret = nnew(List); - ret->w = l->w; - ret->m = NULL; - ret->n = NULL; - return ret; - } - look = lookup_var(name); - if (look == NULL) - return NULL; /* not found */ - if (look->def != NULL) - return look->def; - if (look->extdef == NULL) - return NULL; /* variable was set to null, e.g., a=() echo foo */ - ret = parse_var(look->extdef); - if (ret == NULL) { - look->extdef = NULL; - return NULL; - } - return look->def = ret; + Variable *look; + List *ret, *l; + int sub; + if (streq(name, "apids")) + return sgetapids(); + if (streq(name, "status")) + return sgetstatus(); + if (*name != '\0' && (sub = a2u(name)) != -1) { /* handle $1, $2, etc. */ + for (l = varlookup("*"); l != NULL && sub != 0; --sub) + l = l->n; + if (l == NULL) + return NULL; + ret = nnew(List); + ret->w = l->w; + ret->m = NULL; + ret->n = NULL; + return ret; + } + look = lookup_var(name); + if (look == NULL) + return NULL; /* not found */ + if (look->def != NULL) + return look->def; + if (look->extdef == NULL) + return NULL; /* variable was set to null, e.g., a=() echo foo */ + ret = parse_var(look->extdef); + if (ret == NULL) { + look->extdef = NULL; + return NULL; + } + return look->def = ret; } /* lookup a variable in external (string) form, converting if necessary. Used by makeenv() */ extern char *varlookup_string(char *name) { - Variable *look; - look = lookup_var(name); - if (look == NULL) - return NULL; - if (look->extdef != NULL) - return look->extdef; - if (look->def == NULL) - return NULL; - return look->extdef = mprint("%F=%W", name, look->def); + Variable *look; + look = lookup_var(name); + if (look == NULL) + return NULL; + if (look->extdef != NULL) + return look->extdef; + if (look->def == NULL) + return NULL; + return look->extdef = mprint("%F=%W", name, look->def); } /* remove a variable from the symtab. "stack" determines whether a level of scoping is popped or not */ extern void varrm(char *name, bool stack) { - int i = hasalias(name); - if (streq(name, "*") && !stack) { /* when assigning () to $*, we want to preserve $0 */ - varassign("*", varlookup("0"), false); - return; - } - delete_var(name, stack); - if (i != -1) - delete_var(aliases[i^1], stack); + int i = hasalias(name); + if (streq(name, "*") && !stack) { /* when assigning () to $*, we want to preserve $0 */ + varassign("*", varlookup("0"), false); + return; + } + delete_var(name, stack); + if (i != -1) + delete_var(aliases[i^1], stack); } /* assign a value (List) to a variable, using array "a" as input. Used to assign $* */ extern void starassign(char *dollarzero, char **a, bool stack) { - List *s, *var; - var = nnew(List); - var->w = dollarzero; - if (*a == NULL) { - var->n = NULL; - varassign("*", var, stack); - return; - } - var->n = s = nnew(List); - while (1) { - s->w = *a++; - if (*a == NULL) { - s->n = NULL; - break; - } else - s = s->n = nnew(List); - } - varassign("*", var, stack); + List *s, *var; + var = nnew(List); + var->w = dollarzero; + if (*a == NULL) { + var->n = NULL; + varassign("*", var, stack); + return; + } + var->n = s = nnew(List); + while (1) { + s->w = *a++; + if (*a == NULL) { + s->n = NULL; + break; + } else + s = s->n = nnew(List); + } + varassign("*", var, stack); } /* (ugly name, huh?) assign a colon-separated value to a variable (e.g., PATH) from a List (e.g., path) */ static void colonassign(char *name, List *def, bool stack) { - List dud; - if (def == NULL) { - varassign(name, NULL, stack); - return; - } - dud.w = nprint("%-L", def, ":"); - dud.n = NULL; - varassign(name, &dud, stack); + List dud; + if (def == NULL) { + varassign(name, NULL, stack); + return; + } + dud.w = nprint("%-L", def, ":"); + dud.n = NULL; + varassign(name, &dud, stack); } /* assign a List variable (e.g., path) from a colon-separated string (e.g., PATH) */ static void listassign(char *name, List *def, bool stack) { - List *val, *r; - char *v, *w; - if (def == NULL) { - varassign(name, NULL, stack); - return; - } - v = def->w; - r = val = nnew(List); - while ((w = strchr(v, ':')) != NULL) { - *w = '\0'; - r->w = ncpy(v); - *w = ':'; - v = w + 1; - r = r->n = nnew(List); - } - r->w = ncpy(v); - r->n = NULL; - varassign(name, val, stack); + List *val, *r; + char *v, *w; + if (def == NULL) { + varassign(name, NULL, stack); + return; + } + v = def->w; + r = val = nnew(List); + while ((w = strchr(v, ':')) != NULL) { + *w = '\0'; + r->w = ncpy(v); + *w = ':'; + v = w + 1; + r = r->n = nnew(List); + } + r->w = ncpy(v); + r->n = NULL; + varassign(name, val, stack); } /* check to see if a particular variable is aliased; return -1 on failure, or the index */ static int hasalias(char *name) { - int i; - for (i = 0; i < arraysize(aliases); i++) - if (streq(name, aliases[i])) - return i; - return -1; + int i; + for (i = 0; i < arraysize(aliases); i++) + if (streq(name, aliases[i])) + return i; + return -1; } /* alias a variable to its lowercase equivalent. function pointers are used to specify the conversion function */ extern void alias(char *name, List *s, bool stack) { - static void (*vectors[])(char *, List *, bool) = { - varassign, varassign, colonassign, listassign, colonassign, listassign - }; - int i = hasalias(name); - if (i != -1) - (*vectors[i])(aliases[i^1], s, stack); /* xor hack to reverse case of alias entry */ + static void (*vectors[])(char *, List *, bool) = { + varassign, varassign, colonassign, listassign, colonassign, listassign + }; + int i = hasalias(name); + if (i != -1) + (*vectors[i])(aliases[i^1], s, stack); /* xor hack to reverse case of alias entry */ } extern void prettyprint_var(int fd, char *name, List *s) { - int i; - static const char * const keywords[] = { - "if", "in", "fn", "for", "else", "switch", "while", "case" - }; - if (s == NULL) { - fprint(fd, "%S=()\n", name); - return; - } - if (streq(name, "*")) { - s = s->n; - if (s == NULL) - return; /* Don't print $0, and if $* is not set, skip it */ - } - for (i = 0; i < arraysize(keywords); i++) - if (streq(keywords[i], name)) { - fprint(fd, "%#S=", name); - goto value; - } - fprint(fd, "%S=", name); + int i; + static const char * const keywords[] = { + "if", "in", "fn", "for", "else", "switch", "while", "case" + }; + if (s == NULL) { + fprint(fd, "%S=()\n", name); + return; + } + if (streq(name, "*")) { + s = s->n; + if (s == NULL) + return; /* Don't print $0, and if $* is not set, skip it */ + } + for (i = 0; i < arraysize(keywords); i++) + if (streq(keywords[i], name)) { + fprint(fd, "%#S=", name); + goto value; + } + fprint(fd, "%S=", name); value: - fprint(fd, s->n == NULL ? "%L\n" : "(%L)\n", s, " "); + fprint(fd, s->n == NULL ? "%L\n" : "(%L)\n", s, " "); } diff --git a/wait.c b/wait.c index c93511f..4fa97e0 100644 --- a/wait.c +++ b/wait.c @@ -5,120 +5,120 @@ bool forked = false; typedef struct Pid Pid; static struct Pid { - pid_t pid; - int stat; - bool alive; - Pid *n; + pid_t pid; + int stat; + bool alive; + Pid *n; } *plist = NULL; extern pid_t rc_fork() { - Pid *new; - struct Pid *p, *q; - pid_t pid = fork(); + Pid *new; + struct Pid *p, *q; + pid_t pid = fork(); - switch (pid) { - case -1: - uerror("fork"); - rc_error(NULL); - /* NOTREACHED */ - case 0: - forked = true; - sigchk(); - p = plist; q = 0; - while (p) { - if (q) efree(q); - q = p; - p = p->n; - } - if (q) efree(q); - plist = 0; - return 0; - default: - new = enew(Pid); - new->pid = pid; - new->alive = true; - new->n = plist; - plist = new; - return pid; - } + switch (pid) { + case -1: + uerror("fork"); + rc_error(NULL); + /* NOTREACHED */ + case 0: + forked = true; + sigchk(); + p = plist; q = 0; + while (p) { + if (q) efree(q); + q = p; + p = p->n; + } + if (q) efree(q); + plist = 0; + return 0; + default: + new = enew(Pid); + new->pid = pid; + new->alive = true; + new->n = plist; + plist = new; + return pid; + } } extern pid_t rc_wait4(pid_t pid, int *stat, bool nointr) { - Pid *r, *prev; + Pid *r, *prev; - /* Find the child on the list. */ - for (r = plist, prev = NULL; r != NULL; prev = r, r = r->n) - if (r->pid == pid) - break; + /* Find the child on the list. */ + for (r = plist, prev = NULL; r != NULL; prev = r, r = r->n) + if (r->pid == pid) + break; - /* Uh-oh, not there. */ - if (r == NULL) { - errno = ECHILD; /* no children */ - uerror("wait"); - *stat = 0x100; /* exit(1) */ - return -1; - } + /* Uh-oh, not there. */ + if (r == NULL) { + errno = ECHILD; /* no children */ + uerror("wait"); + *stat = 0x100; /* exit(1) */ + return -1; + } - /* If it's still alive, wait() for it. */ - while (r->alive) { - int ret; - Pid *q; + /* If it's still alive, wait() for it. */ + while (r->alive) { + int ret; + Pid *q; - ret = wait(stat); + ret = wait(stat); - if (ret < 0) { - if (errno == ECHILD) - panic("lost child"); - if (nointr) - continue; - else - return ret; - } + if (ret < 0) { + if (errno == ECHILD) + panic("lost child"); + if (nointr) + continue; + else + return ret; + } - for (q = plist; q != NULL; q = q->n) - if (q->pid == ret) { - q->alive = false; - q->stat = *stat; - break; - } - } - *stat = r->stat; - if (prev == NULL) - plist = r->n; /* remove element from head of list */ - else - prev->n = r->n; - efree(r); - return pid; + for (q = plist; q != NULL; q = q->n) + if (q->pid == ret) { + q->alive = false; + q->stat = *stat; + break; + } + } + *stat = r->stat; + if (prev == NULL) + plist = r->n; /* remove element from head of list */ + else + prev->n = r->n; + efree(r); + return pid; } extern List *sgetapids() { - List *r; - Pid *p; - for (r = NULL, p = plist; p != NULL; p = p->n) { - List *q; - if (!p->alive) - continue; - q = nnew(List); - q->w = nprint("%d", p->pid); - q->m = NULL; - q->n = r; - r = q; - } - return r; + List *r; + Pid *p; + for (r = NULL, p = plist; p != NULL; p = p->n) { + List *q; + if (!p->alive) + continue; + q = nnew(List); + q->w = nprint("%d", p->pid); + q->m = NULL; + q->n = r; + r = q; + } + return r; } extern void waitforall() { - int stat; + int stat; - while (plist != NULL) { - pid_t pid = rc_wait4(plist->pid, &stat, false); - if (pid > 0) - setstatus(pid, stat); - else { - set(false); - if (errno == EINTR) - return; - } - sigchk(); - } + while (plist != NULL) { + pid_t pid = rc_wait4(plist->pid, &stat, false); + if (pid > 0) + setstatus(pid, stat); + else { + set(false); + if (errno == EINTR) + return; + } + sigchk(); + } } diff --git a/walk.c b/walk.c index 1787b1a..9a97926 100644 --- a/walk.c +++ b/walk.c @@ -20,267 +20,267 @@ static void dopipe(Node *); /* walk the parse-tree. "obvious". */ extern bool walk(Node *n, bool parent) { -top: sigchk(); - if (n == NULL) { - if (!parent) - exit(0); - set(true); - return true; - } - switch (n->type) { - case nArgs: case nBackq: case nConcat: case nCount: - case nFlat: case nLappend: case nRedir: case nVar: - case nVarsub: case nWord: - exec(glob(glom(n)), parent); /* simple command */ - break; - case nBody: - walk(n->u[0].p, true); - WALK(n->u[1].p, parent); - /* WALK doesn't fall through */ - case nNowait: { - int pid; - if ((pid = rc_fork()) == 0) { +top: sigchk(); + if (n == NULL) { + if (!parent) + exit(0); + set(true); + return true; + } + switch (n->type) { + case nArgs: case nBackq: case nConcat: case nCount: + case nFlat: case nLappend: case nRedir: case nVar: + case nVarsub: case nWord: + exec(glob(glom(n)), parent); /* simple command */ + break; + case nBody: + walk(n->u[0].p, true); + WALK(n->u[1].p, parent); + /* WALK doesn't fall through */ + case nNowait: { + int pid; + if ((pid = rc_fork()) == 0) { #if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP) - setsigdefaults(false); - rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ - rc_signal(SIGTTIN, SIG_IGN); - rc_signal(SIGTSTP, SIG_IGN); - setpgid(0, getpid()); + setsigdefaults(false); + rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ + rc_signal(SIGTTIN, SIG_IGN); + rc_signal(SIGTSTP, SIG_IGN); + setpgid(0, getpid()); #else - setsigdefaults(true); /* ignore SIGINT, SIGQUIT, SIGTERM */ + setsigdefaults(true); /* ignore SIGINT, SIGQUIT, SIGTERM */ #endif - mvfd(rc_open("/dev/null", rFrom), 0); - walk(n->u[0].p, false); - exit(getstatus()); - } - if (interactive) - fprint(2, "%d\n", pid); - varassign("apid", word(nprint("%d", pid), NULL), false); - redirq = NULL; /* kill pre-redir queue */ - break; - } - case nAndalso: { - bool oldcond = cond; - cond = true; - if (walk(n->u[0].p, true)) { - cond = oldcond; - WALK(n->u[1].p, parent); - } else - cond = oldcond; - break; - } - case nOrelse: { - bool oldcond = cond; - cond = true; - if (!walk(n->u[0].p, true)) { - cond = oldcond; - WALK(n->u[1].p, parent); - } else - cond = oldcond; - break; - } - case nBang: - set(!walk(n->u[0].p, true)); - break; - case nIf: { - bool oldcond = cond; - Node *true_cmd = n->u[1].p, *false_cmd = NULL; - if (true_cmd != NULL && true_cmd->type == nElse) { - false_cmd = true_cmd->u[1].p; - true_cmd = true_cmd->u[0].p; - } - cond = true; - if (!walk(n->u[0].p, true)) - true_cmd = false_cmd; /* run the else clause */ - cond = oldcond; - WALK(true_cmd, parent); - } - case nWhile: { - Jbwrap j; - Edata jbreak; - Estack e1, e2; - bool testtrue, oldcond = cond; - cond = true; - if (!walk(n->u[0].p, true)) { /* prevent spurious breaks inside test */ - cond = oldcond; - break; - } - if (sigsetjmp(j.j, 1)) - break; - jbreak.jb = &j; - except(eBreak, jbreak, &e1); - do { - Edata block; - block.b = newblock(); - cond = oldcond; - except(eArena, block, &e2); - walk(n->u[1].p, true); - testtrue = walk(n->u[0].p, true); - unexcept(); /* eArena */ - cond = true; - } while (testtrue); - cond = oldcond; - unexcept(); /* eBreak */ - break; - } - case nForin: { - List *l, *var = glom(n->u[0].p); - Jbwrap j; - Estack e1, e2; - Edata jbreak; - if (sigsetjmp(j.j, 1)) - break; - jbreak.jb = &j; - except(eBreak, jbreak, &e1); - for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { - Edata block; - assign(var, word(l->w, NULL), false); - block.b = newblock(); - except(eArena, block, &e2); - walk(n->u[2].p, true); - unexcept(); /* eArena */ - } - unexcept(); /* eBreak */ - break; - } - case nSubshell: - if (dofork(true)) { - setsigdefaults(false); - walk(n->u[0].p, false); - rc_exit(getstatus()); - } - break; - case nAssign: - if (n->u[0].p == NULL) - rc_error("null variable name"); - assign(glom(n->u[0].p), glob(glom(n->u[1].p)), false); - set(true); - break; - case nPipe: - dopipe(n); - break; - case nNewfn: { - List *l = glom(n->u[0].p); - if (l == NULL) - rc_error("null function name"); - while (l != NULL) { - fnassign(l->w, n->u[1].p); - l = l->n; - } - set(true); - break; - } - case nRmfn: { - List *l = glom(n->u[0].p); - while (l != NULL) { - fnrm(l->w); - l = l->n; - } - set(true); - break; - } - case nDup: - redirq = NULL; - break; /* Null command */ - case nMatch: { - List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); - set(lmatch(a, b)); - break; - } - case nSwitch: { - List *v = glom(n->u[0].p); - while (1) { - do { - n = n->u[1].p; - if (n == NULL) - return istrue(); - } while (n->u[0].p == NULL || n->u[0].p->type != nCase); - if (lmatch(v, glom(n->u[0].p->u[0].p))) { - for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) - walk(n->u[0].p, true); - break; - } - } - break; - } - case nPre: { - List *v; - if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { - if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ - break; - setsigdefaults(false); - qredir(n->u[0].p); - if (!haspreredir(n->u[1].p)) - doredirs(); /* no more preredirs, empty queue */ - walk(n->u[1].p, false); - rc_exit(getstatus()); - /* NOTREACHED */ - } else if (n->u[0].p->type == nAssign) { - if (isallpre(n->u[1].p)) { - walk(n->u[0].p, true); - WALK(n->u[1].p, parent); - } else { - Estack e; - Edata var; - v = glom(n->u[0].p->u[0].p); - assign(v, glob(glom(n->u[0].p->u[1].p)), true); - var.name = v->w; - except(eVarstack, var, &e); - walk(n->u[1].p, parent); - varrm(v->w, true); - unexcept(); /* eVarstack */ - } - } else - panic("unexpected node in preredir section of walk"); - break; - } - case nBrace: - if (n->u[1].p == NULL) { - WALK(n->u[0].p, parent); - } else if (dofork(parent)) { - setsigdefaults(false); - walk(n->u[1].p, true); /* Do redirections */ - redirq = NULL; /* Reset redirection queue */ - walk(n->u[0].p, false); /* Do commands */ - rc_exit(getstatus()); - /* NOTREACHED */ - } - break; - case nEpilog: - qredir(n->u[0].p); - if (n->u[1].p != NULL) { - WALK(n->u[1].p, parent); /* Do more redirections. */ - } else { - doredirs(); /* Okay, we hit the bottom. */ - } - break; - case nNmpipe: - rc_error("named pipes cannot be executed as commands"); - /* NOTREACHED */ - default: - panic("unknown node in walk"); - /* NOTREACHED */ - } - return istrue(); + mvfd(rc_open("/dev/null", rFrom), 0); + walk(n->u[0].p, false); + exit(getstatus()); + } + if (interactive) + fprintf(stderr, "%d\n", pid); + varassign("apid", word(nprint("%d", pid), NULL), false); + redirq = NULL; /* kill pre-redir queue */ + break; + } + case nAndalso: { + bool oldcond = cond; + cond = true; + if (walk(n->u[0].p, true)) { + cond = oldcond; + WALK(n->u[1].p, parent); + } else + cond = oldcond; + break; + } + case nOrelse: { + bool oldcond = cond; + cond = true; + if (!walk(n->u[0].p, true)) { + cond = oldcond; + WALK(n->u[1].p, parent); + } else + cond = oldcond; + break; + } + case nBang: + set(!walk(n->u[0].p, true)); + break; + case nIf: { + bool oldcond = cond; + Node *true_cmd = n->u[1].p, *false_cmd = NULL; + if (true_cmd != NULL && true_cmd->type == nElse) { + false_cmd = true_cmd->u[1].p; + true_cmd = true_cmd->u[0].p; + } + cond = true; + if (!walk(n->u[0].p, true)) + true_cmd = false_cmd; /* run the else clause */ + cond = oldcond; + WALK(true_cmd, parent); + } + case nWhile: { + Jbwrap j; + Edata jbreak; + Estack e1, e2; + bool testtrue, oldcond = cond; + cond = true; + if (!walk(n->u[0].p, true)) { /* prevent spurious breaks inside test */ + cond = oldcond; + break; + } + if (sigsetjmp(j.j, 1)) + break; + jbreak.jb = &j; + except(eBreak, jbreak, &e1); + do { + Edata block; + block.b = newblock(); + cond = oldcond; + except(eArena, block, &e2); + walk(n->u[1].p, true); + testtrue = walk(n->u[0].p, true); + unexcept(); /* eArena */ + cond = true; + } while (testtrue); + cond = oldcond; + unexcept(); /* eBreak */ + break; + } + case nForin: { + List *l, *var = glom(n->u[0].p); + Jbwrap j; + Estack e1, e2; + Edata jbreak; + if (sigsetjmp(j.j, 1)) + break; + jbreak.jb = &j; + except(eBreak, jbreak, &e1); + for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { + Edata block; + assign(var, word(l->w, NULL), false); + block.b = newblock(); + except(eArena, block, &e2); + walk(n->u[2].p, true); + unexcept(); /* eArena */ + } + unexcept(); /* eBreak */ + break; + } + case nSubshell: + if (dofork(true)) { + setsigdefaults(false); + walk(n->u[0].p, false); + rc_exit(getstatus()); + } + break; + case nAssign: + if (n->u[0].p == NULL) + rc_error("null variable name"); + assign(glom(n->u[0].p), glob(glom(n->u[1].p)), false); + set(true); + break; + case nPipe: + dopipe(n); + break; + case nNewfn: { + List *l = glom(n->u[0].p); + if (l == NULL) + rc_error("null function name"); + while (l != NULL) { + fnassign(l->w, n->u[1].p); + l = l->n; + } + set(true); + break; + } + case nRmfn: { + List *l = glom(n->u[0].p); + while (l != NULL) { + fnrm(l->w); + l = l->n; + } + set(true); + break; + } + case nDup: + redirq = NULL; + break; /* Null command */ + case nMatch: { + List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); + set(lmatch(a, b)); + break; + } + case nSwitch: { + List *v = glom(n->u[0].p); + while (1) { + do { + n = n->u[1].p; + if (n == NULL) + return istrue(); + } while (n->u[0].p == NULL || n->u[0].p->type != nCase); + if (lmatch(v, glom(n->u[0].p->u[0].p))) { + for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) + walk(n->u[0].p, true); + break; + } + } + break; + } + case nPre: { + List *v; + if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { + if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ + break; + setsigdefaults(false); + qredir(n->u[0].p); + if (!haspreredir(n->u[1].p)) + doredirs(); /* no more preredirs, empty queue */ + walk(n->u[1].p, false); + rc_exit(getstatus()); + /* NOTREACHED */ + } else if (n->u[0].p->type == nAssign) { + if (isallpre(n->u[1].p)) { + walk(n->u[0].p, true); + WALK(n->u[1].p, parent); + } else { + Estack e; + Edata var; + v = glom(n->u[0].p->u[0].p); + assign(v, glob(glom(n->u[0].p->u[1].p)), true); + var.name = v->w; + except(eVarstack, var, &e); + walk(n->u[1].p, parent); + varrm(v->w, true); + unexcept(); /* eVarstack */ + } + } else + panic("unexpected node in preredir section of walk"); + break; + } + case nBrace: + if (n->u[1].p == NULL) { + WALK(n->u[0].p, parent); + } else if (dofork(parent)) { + setsigdefaults(false); + walk(n->u[1].p, true); /* Do redirections */ + redirq = NULL; /* Reset redirection queue */ + walk(n->u[0].p, false); /* Do commands */ + rc_exit(getstatus()); + /* NOTREACHED */ + } + break; + case nEpilog: + qredir(n->u[0].p); + if (n->u[1].p != NULL) { + WALK(n->u[1].p, parent); /* Do more redirections. */ + } else { + doredirs(); /* Okay, we hit the bottom. */ + } + break; + case nNmpipe: + rc_error("named pipes cannot be executed as commands"); + /* NOTREACHED */ + default: + panic("unknown node in walk"); + /* NOTREACHED */ + } + return istrue(); } /* checks to see whether there are any pre-redirections left in the tree */ static bool haspreredir(Node *n) { - while (n != NULL && n->type == nPre) { - if (n->u[0].p->type == nDup || n->u[0].p->type == nRedir) - return true; - n = n->u[1].p; - } - return false; + while (n != NULL && n->type == nPre) { + if (n->u[0].p->type == nDup || n->u[0].p->type == nRedir) + return true; + n = n->u[1].p; + } + return false; } /* checks to see whether a subtree is all pre-command directives, i.e., assignments and redirs only */ static bool isallpre(Node *n) { - while (n != NULL && n->type == nPre) - n = n->u[1].p; - return n == NULL || n->type == nRedir || n->type == nAssign || n->type == nDup; + while (n != NULL && n->type == nPre) + n = n->u[1].p; + return n == NULL || n->type == nRedir || n->type == nAssign || n->type == nDup; } /* @@ -289,66 +289,66 @@ static bool isallpre(Node *n) { */ static bool dofork(bool parent) { - int pid, sp; + int pid, sp; - if (!parent || (pid = rc_fork()) == 0) - return true; - redirq = NULL; /* clear out the pre-redirection queue in the parent */ - rc_wait4(pid, &sp, true); - setstatus(-1, sp); - sigchk(); - return false; + if (!parent || (pid = rc_fork()) == 0) + return true; + redirq = NULL; /* clear out the pre-redirection queue in the parent */ + rc_wait4(pid, &sp, true); + setstatus(-1, sp); + sigchk(); + return false; } static void dopipe(Node *n) { - int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2]; - bool intr; - Node *r; + int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2]; + bool intr; + Node *r; - fd_prev = fd_out = 1; - for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) { - if (i > 500) /* the only hard-wired limit in rc? */ - rc_error("pipe too long"); - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if ((pid = rc_fork()) == 0) { - setsigdefaults(false); - redirq = NULL; /* clear preredir queue */ - mvfd(p[0], r->u[1].i); - if (fd_prev != 1) - mvfd(fd_prev, fd_out); - close(p[1]); - walk(r->u[3].p, false); - exit(getstatus()); - } - if (fd_prev != 1) - close(fd_prev); /* parent must close all pipe fd's */ - pids[i] = pid; - fd_prev = p[1]; - fd_out = r->u[0].i; - close(p[0]); - } - if ((pid = rc_fork()) == 0) { - setsigdefaults(false); - mvfd(fd_prev, fd_out); - walk(r, false); - exit(getstatus()); - /* NOTREACHED */ - } - redirq = NULL; /* clear preredir queue */ - close(fd_prev); - pids[i++] = pid; + fd_prev = fd_out = 1; + for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) { + if (i > 500) /* the only hard-wired limit in rc? */ + rc_error("pipe too long"); + if (pipe(p) < 0) { + uerror("pipe"); + rc_error(NULL); + } + if ((pid = rc_fork()) == 0) { + setsigdefaults(false); + redirq = NULL; /* clear preredir queue */ + mvfd(p[0], r->u[1].i); + if (fd_prev != 1) + mvfd(fd_prev, fd_out); + close(p[1]); + walk(r->u[3].p, false); + exit(getstatus()); + } + if (fd_prev != 1) + close(fd_prev); /* parent must close all pipe fd's */ + pids[i] = pid; + fd_prev = p[1]; + fd_out = r->u[0].i; + close(p[0]); + } + if ((pid = rc_fork()) == 0) { + setsigdefaults(false); + mvfd(fd_prev, fd_out); + walk(r, false); + exit(getstatus()); + /* NOTREACHED */ + } + redirq = NULL; /* clear preredir queue */ + close(fd_prev); + pids[i++] = pid; - /* collect statuses */ + /* collect statuses */ - intr = false; - for (j = 0; j < i; j++) { - rc_wait4(pids[j], &sp, true); - stats[j] = sp; - intr |= (sp == SIGINT); - } - setpipestatus(stats, i); - sigchk(); + intr = false; + for (j = 0; j < i; j++) { + rc_wait4(pids[j], &sp, true); + stats[j] = sp; + intr |= (sp == SIGINT); + } + setpipestatus(stats, i); + sigchk(); } diff --git a/which.c b/which.c index 43c9e1d..ef90cea 100644 --- a/which.c +++ b/which.c @@ -25,11 +25,11 @@ static gid_t* gidset; /* determine whether gid lies in gidset */ static int ingidset(gid_t g) { - int i; - for (i = 0; i < ngroups; ++i) - if (g == gidset[i]) - return 1; - return 0; + int i; + for (i = 0; i < ngroups; ++i) + if (g == gidset[i]) + return 1; + return 0; } /* @@ -38,89 +38,89 @@ static int ingidset(gid_t g) { */ static bool rc_access(char *path, bool verbose) { - struct stat st; - int mask; - if (stat(path, &st) != 0) { - if (verbose) /* verbose flag only set for absolute pathname */ - uerror(path); - return false; - } - if (uid == 0) - mask = X_ALL; - else if (uid == st.st_uid) - mask = X_USR; - else if (gid == st.st_gid || ingidset(st.st_gid)) - mask = X_GRP; - else - mask = X_OTH; - if (((st.st_mode & S_IFMT) == S_IFREG) && (st.st_mode & mask)) - return true; - errno = EACCES; - if (verbose) - uerror(path); - return false; + struct stat st; + int mask; + if (stat(path, &st) != 0) { + if (verbose) /* verbose flag only set for absolute pathname */ + uerror(path); + return false; + } + if (uid == 0) + mask = X_ALL; + else if (uid == st.st_uid) + mask = X_USR; + else if (gid == st.st_gid || ingidset(st.st_gid)) + mask = X_GRP; + else + mask = X_OTH; + if (((st.st_mode & S_IFMT) == S_IFREG) && (st.st_mode & mask)) + return true; + errno = EACCES; + if (verbose) + uerror(path); + return false; } /* replace non-printing characters with question marks in a freshly * allocated string */ static char *protect(char *in) { - int l = strlen(in); - char *out = ealloc(l + 1); - int i; + int l = strlen(in); + char *out = ealloc(l + 1); + int i; - for (i = 0; i < l; ++i) - out[i] = isprint(in[i]) ? in[i] : '?'; - out[i] = '\0'; - return out; + for (i = 0; i < l; ++i) + out[i] = isprint(in[i]) ? in[i] : '?'; + out[i] = '\0'; + return out; } - + /* return a full pathname by searching $path, and by checking the status of the file */ extern char *which(char *name, bool verbose) { - static char *test = NULL; - static size_t testlen = 0; - List *path; - int len; - if (name == NULL) /* no filename? can happen with "> foo" as a command */ - return NULL; - if (!initialized) { - initialized = true; - uid = geteuid(); - gid = getegid(); - ngroups = getgroups(0, (gid_t *)0); - if (ngroups < 0) { - uerror("getgroups"); - rc_exit(1); - } - if (ngroups) { - gidset = ealloc(ngroups * sizeof(gid_t)); - getgroups(ngroups, gidset); - } - } - if (isabsolute(name)) /* absolute pathname? */ - return rc_access(name, verbose) ? name : NULL; - len = strlen(name); - for (path = varlookup("path"); path != NULL; path = path->n) { - size_t need = strlen(path->w) + len + 2; /* one for null terminator, one for the '/' */ - if (testlen < need) { - efree(test); - test = ealloc(testlen = need); - } - if (*path->w == '\0') { - strcpy(test, name); - } else { - strcpy(test, path->w); - if (!streq(test, "/")) /* "//" is special to POSIX */ - strcat(test, "/"); - strcat(test, name); - } - if (rc_access(test, false)) - return test; - } - if (verbose) { - char *n = protect(name); - fprint(2, RC "cannot find `%s'\n", n); - efree(n); - } - return NULL; + static char *test = NULL; + static size_t testlen = 0; + List *path; + int len; + if (name == NULL) /* no filename? can happen with "> foo" as a command */ + return NULL; + if (!initialized) { + initialized = true; + uid = geteuid(); + gid = getegid(); + ngroups = getgroups(0, (gid_t *)0); + if (ngroups < 0) { + uerror("getgroups"); + rc_exit(1); + } + if (ngroups) { + gidset = ealloc(ngroups * sizeof(gid_t)); + getgroups(ngroups, gidset); + } + } + if (isabsolute(name)) /* absolute pathname? */ + return rc_access(name, verbose) ? name : NULL; + len = strlen(name); + for (path = varlookup("path"); path != NULL; path = path->n) { + size_t need = strlen(path->w) + len + 2; /* one for null terminator, one for the '/' */ + if (testlen < need) { + efree(test); + test = ealloc(testlen = need); + } + if (*path->w == '\0') { + strcpy(test, name); + } else { + strcpy(test, path->w); + if (!streq(test, "/")) /* "//" is special to POSIX */ + strcat(test, "/"); + strcat(test, name); + } + if (rc_access(test, false)) + return test; + } + if (verbose) { + char *n = protect(name); + fprintf(stderr, RC "cannot find `%s'\n", n); + efree(n); + } + return NULL; } -- 2.49.0