static List *backq(Node *ifs, Node *n) { int p[2], sp; pid_t pid; List *bq; struct termios t; if (n == NULL) return NULL; if (pipe(p) < 0) { uerror("pipe"); rc_error(NULL); } if (interactive) tcgetattr(0, &t); 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); if (interactive && WIFSIGNALED(sp)) tcsetattr(0, TCSANOW, &t); statprint(-1, sp); varassign("bqstatus", word(strstatus(sp), NULL), FALSE); sigchk(); return bq; }
extern void writeall(int fd, const char *buf, size_t remain) { int i = 0; for (; remain > 0; buf += i, remain -= i) if ((i = write(fd, buf, remain)) <= 0) break; /* abort silently on errors in write() */ sigchk(); }
static bool dofork(bool parent) { 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; }
static void dopipe(Node *n) { 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; /* 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(); }
static int readb(void) { register FILE f = standin; register int len; do { if (trapnote & SIGSET) { newline(); sigchk(); } } while ((len = read(f->fdes, f->fbuf, f->fsiz)) < 0 && trapnote); return (len); }
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(); }
void printnam(struct namnod *n) { register unsigned char *s; sigchk(); if (n->namflg & N_FUNCTN) { prs_buff(n->namid); prs_buff("(){\n"); prf((struct trenod *)n->namenv); prs_buff("\n}\n"); } else if (s = n->namval) { prs_buff(n->namid); prc_buff('='); prs_buff(s); prc_buff(NL); } }
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; }
int echo(int argc, unsigned char **argv) { unsigned char *cp; int i, wd; int nflg = 0; int j; int len; wchar_t wc; if (ucb_builtins) { nflg = 0; if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n' && !argv[1][2]) { nflg++; argc--; argv++; } for (i = 1; i < argc; i++) { sigchk(); for (cp = argv[i]; *cp; cp++) { prc_buff(*cp); } if (i < argc-1) prc_buff(' '); } if (nflg == 0) prc_buff('\n'); exit(0); } else { if (--argc == 0) { prc_buff('\n'); exit(0); } for (i = 1; i <= argc; i++) { sigchk(); for (cp = argv[i]; *cp; cp++) { if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) { prc_buff(*cp); continue; } if (wc == '\\') { switch (*++cp) { case 'b': prc_buff('\b'); continue; case 'c': exit(0); case 'f': prc_buff('\f'); continue; case 'n': prc_buff('\n'); continue; case 'r': prc_buff('\r'); continue; case 't': prc_buff('\t'); continue; case 'v': prc_buff('\v'); continue; case '\\': prc_buff('\\'); continue; case '0': j = wd = 0; while ((*++cp >= '0' && *cp <= '7') && j++ < 3) { wd <<= 3; wd |= (*cp - '0'); } prc_buff(wd); --cp; continue; default: cp--; } prc_buff(*cp); continue; } else { for (; len > 0; len--) prc_buff(*cp++); cp--; continue; } } prc_buff(i == argc? '\n': ' '); } exit(0); } }
static int readb(struct fileblk *f, int toread, int rest) { int len; int fflags; if (rest) { /* * copies the remaining 'rest' bytes from f->fnxt * to f->fbuf */ memcpy(f->fbuf, f->fnxt, rest); f->fnxt = f->fbuf; f->fend = f->fnxt + rest; f->nxtoff = 0; f->endoff = rest; if (f->fbuf[rest - 1] == '\n') { /* * if '\n' found, it should be * a bondary of multibyte char. */ return (rest); } } retry: do { if (trapnote & SIGSET) { newline(); sigchk(); } else if ((trapnote & TRAPSET) && (rwait > 0)) { newline(); chktrap(); clearup(); } } while ((len = read(f->fdes, f->fbuf + rest, toread)) < 0 && trapnote); /* * if child sets O_NDELAY or O_NONBLOCK on stdin * and exited then turn the modes off and retry */ if (len == 0) { if (((flags & intflg) || ((flags & oneflg) == 0 && isatty(input) && (flags & stdflg))) && ((fflags = fcntl(f->fdes, F_GETFL, 0)) & O_NDELAY)) { fflags &= ~O_NDELAY; fcntl(f->fdes, F_SETFL, fflags); goto retry; } } else if (len < 0) { if (errno == EAGAIN) { fflags = fcntl(f->fdes, F_GETFL, 0); fflags &= ~O_NONBLOCK; fcntl(f->fdes, F_SETFL, fflags); goto retry; } len = 0; } f->fnxt = f->fbuf; f->fend = f->fnxt + (len + rest); f->nxtoff = 0; f->endoff = len + rest; return (len + rest); }
int execute(TREPTR argt, int execflg, int *pf1, int *pf2) { /* `stakbot' is preserved by this routine */ register TREPTR t; STKPTR sav = savstak(); sigchk(); if ((t = argt) && execbrk == 0) { register int treeflgs; int oldexit, type; register char **com; treeflgs = t->tretyp; type = treeflgs & COMMSK; oldexit = exitval; exitval = 0; switch (type) { case TCOM: { STRING a1; int argn, internal; ARGPTR schain = gchain; IOPTR io = t->treio; gchain = 0; argn = getarg((void *)t);/*FIXME*/ com = scan(argn); a1 = com[1]; gchain = schain; if ((internal = syslook(com[0], commands)) || argn == 0) setlist(((COMPTR) t)->comset, 0); if (argn && (flags & noexec) == 0) { /* print command if execpr */ if (flags & execpr) { argn = 0; prs(execpmsg); while (com[argn] != ENDARGS) { prs(com[argn++]); blank(); } newline(); } switch (internal) { case SYSDOT: if (a1) { register int f; if ((f = pathopen(getpath(a1), a1)) < 0) failed(a1, notfound); else execexp(0, f); } break; case SYSTIMES: { struct tms t; times(&t); prt(t.tms_cutime); blank(); prt(t.tms_cstime); newline(); } break; case SYSEXIT: exitsh(a1 ? stoi(a1) : oldexit); case SYSNULL: io = 0; break; case SYSCONT: execbrk = -loopcnt; break; case SYSBREAK: if ((execbrk = loopcnt) && a1) breakcnt = stoi(a1); break; case SYSTRAP: if (a1) { BOOL clear; if ((clear = digit(*a1)) == 0) ++com; while (*++com) { int i; if ((i = stoi(*com)) >= MAXTRAP || i < MINTRAP) failed(*com, badtrap); else if (clear) clrsig(i); else { replace(&trapcom[i], a1); if (*a1) getsig(i); else ignsig(i); } } } else { /* print out current traps */ int i; for (i = 0; i < MAXTRAP; i++) { if (trapcom[i]) { prn(i); prs(colon); prs(trapcom[i]); newline(); } } } break; case SYSEXEC: com++; initio(io); ioset = 0; io = 0; if (a1 == 0) break; case SYSLOGIN: flags |= forked; oldsigs(); execa((const char **)com); done(); case SYSCD: if (flags & rshflg) failed(com[0], restricted); else if ((a1 == 0 && (a1 = (char *)homenod.namval) == 0) || chdir(a1) < 0) /* FIXME */ failed(a1, baddir); break; case SYSSHFT: if (dolc < 1) error(badshift); else { dolv++; dolc--; } assnum(&dolladr, dolc); break; case SYSWAIT: await(-1); break; case SYSREAD: exitval = readvar(&com[1]); break; /* case SYSTST: exitval=testcmd(com); break; */ case SYSSET: if (a1) { int argc; argc = options(argn, (const char **)com); if (argc > 1) setargs((const char **)com + argn - argc); } else if (((COMPTR) t)->comset == 0) /* Scan name chain and print */ namscan(printnam); break; case SYSRDONLY: exitval = N_RDONLY; case SYSXPORT: if (exitval == 0) exitval = N_EXPORT;; if (a1) { while (*++com) attrib(lookup(*com), exitval); } else { namscan(printflg); } exitval = 0; break; case SYSEVAL: if (a1) execexp(a1, (UFD)&com[2]); /* FIXME */ break; case SYSUMASK: if (a1) { int c, i; i = 0; while ((c = *a1++) >= '0' && c <= '7') i = (i << 3) + c - '0'; umask(i); } else { int i, j; umask(i = umask(0)); prc('0'); for (j = 6; j >= 0; j -= 3) prc(((i >> j) & 07) + '0'); newline(); } break; default: internal = builtin(argn, com); } if (internal) { if (io) error(illegal); chktrap(); break; } } else if (t->treio == 0) break; } case TFORK: if (execflg && (treeflgs & (FAMP | FPOU)) == 0) parent = 0; else { while ((parent = fork()) == -1) { sigchk(); alarm(10); pause(); } } if (parent) { /* This is the parent branch of fork; */ /* it may or may not wait for the child. */ if (treeflgs & FPRS && flags & ttyflg) { prn(parent); newline(); } if (treeflgs & FPCL) closepipe(pf1); if ((treeflgs & (FAMP | FPOU)) == 0) await(parent); else if ((treeflgs & FAMP) == 0) post(parent); else assnum(&pcsadr, parent); chktrap(); break; } else { /* this is the forked branch (child) of execute */ flags |= forked; iotemp = 0; postclr(); settmp(); /* Turn off INTR and QUIT if `FINT' */ /* Reset ramaining signals to parent */ /* except for those `lost' by trap */ oldsigs(); if (treeflgs & FINT) { signal(INTR, SIG_IGN); signal(QUIT, SIG_IGN); } /* pipe in or out */ if (treeflgs & FPIN) { sh_rename(pf1[INPIPE], 0); close(pf1[OTPIPE]); } if (treeflgs & FPOU) { sh_rename(pf2[OTPIPE], 1); close(pf2[INPIPE]); } /* default std input for & */ if (treeflgs & FINT && ioset == 0) sh_rename(chkopen(devnull), 0); /* io redirection */ initio(t->treio); if (type != TCOM) execute(((FORKPTR) t)->forktre, 1, NULL, NULL); else if (com[0] != ENDARGS) { setlist(((COMPTR) t)->comset, N_EXPORT); execa((const char **)com); } done(); } case TPAR: sh_rename(dup(2), output); execute(((PARPTR) t)->partre, execflg, NULL, NULL); done(); case TFIL: { int pv[2]; chkpipe(pv); if (execute(((LSTPTR) t)->lstlef, 0, pf1, pv) == 0) execute(((LSTPTR) t)->lstrit, execflg, pv, pf2); else closepipe(pv); break; } case TLST: execute(((LSTPTR) t)->lstlef, 0, NULL, NULL); execute(((LSTPTR) t)->lstrit, execflg, NULL, NULL); break; case TAND: if (execute(((LSTPTR) t)->lstlef, 0, NULL, NULL) == 0) execute(((LSTPTR) t)->lstrit, execflg, NULL, NULL); break; case TORF: if (execute(((LSTPTR) t)->lstlef, 0, NULL, NULL) != 0) execute(((LSTPTR) t)->lstrit, execflg, NULL, NULL); break; case TFOR: { NAMPTR n = lookup(((FORPTR) t)->fornam); char **args; DOLPTR argsav = 0; if (((FORPTR) t)->forlst == 0) { args = (char **)dolv + 1; argsav = useargs(); } else { ARGPTR schain = gchain; gchain = 0; trim((args = scan(getarg(((FORPTR) t)->forlst)))[0]); gchain = schain; } loopcnt++; while (*args != ENDARGS && execbrk == 0) { assign(n, *args++); execute(((FORPTR) t)->fortre, 0, NULL, NULL); if (execbrk < 0) { execbrk = 0; } } if (breakcnt) breakcnt--; execbrk = breakcnt; loopcnt--; argfor = freeargs(argsav); break; } case TWH: case TUN: { int i = 0; loopcnt++; while (execbrk == 0 && (execute(((WHPTR) t)->whtre, 0, NULL, NULL) == 0) == (type == TWH)) { i = execute(((WHPTR) t)->dotre, 0, NULL, NULL); if (execbrk < 0) execbrk = 0; } if (breakcnt) breakcnt--; execbrk = breakcnt; loopcnt--; exitval = i; break; } case TIF: if (execute(((IFPTR) t)->iftre, 0, NULL, NULL) == 0) execute(((IFPTR) t)->thtre, execflg, NULL, NULL); else execute(((IFPTR) t)->eltre, execflg, NULL, NULL); break; case TSW: { register char *r = mactrim(((SWPTR) t)->swarg); t = (TREPTR) ((SWPTR) t)->swlst; while (t) { ARGPTR rex = ((REGPTR) t)->regptr; while (rex) { register char *s; if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s))) { execute(((REGPTR)t)->regcom, 0, NULL, NULL); t = 0; break; } else rex = ((ARGPTR)rex)->argnxt; } if (t) t = (TREPTR) ((REGPTR) t)->regnxt; } } break; } exitset(); }
void prf(struct trenod *t) { sigchk(); if (t) { int type; type = t->tretyp & COMMSK; switch(type) { case TFND: { struct fndnod *f = (struct fndnod *)t; prs_buff(f->fndnam); prs_buff("(){"); prbgnlst(); prf(f->fndval); prbgnlst(); prs_buff("}"); break; } case TCOM: if (comptr(t)->comset) { prarg(comptr(t)->comset); prc_buff(SPACE); } prarg(comptr(t)->comarg); prio(comptr(t)->comio); break; case TFORK: prf(forkptr(t)->forktre); prio(forkptr(t)->forkio); if (forkptr(t)->forktyp & FAMP) prs_buff(" &"); break; case TPAR: prs_buff("("); prf(parptr(t)->partre); prs_buff(")"); break; case TFIL: prf(lstptr(t)->lstlef); prs_buff(" | "); prf(lstptr(t)->lstrit); break; case TLST: prf(lstptr(t)->lstlef); prendlst(); prf(lstptr(t)->lstrit); break; case TAND: prf(lstptr(t)->lstlef); prs_buff(" && "); prf(lstptr(t)->lstrit); break; case TORF: prf(lstptr(t)->lstlef); prs_buff(" || "); prf(lstptr(t)->lstrit); break; case TFOR: { struct argnod *arg; struct fornod *f = (struct fornod *)t; prs_buff("for "); prs_buff(f->fornam); if (f->forlst) { arg = f->forlst->comarg; prs_buff(" in"); while(arg != ENDARGS) { prc_buff(SPACE); prs_buff(arg->argval); arg = arg->argnxt; } } prendlst(); prs_buff("do"); prbgnlst(); prf(f->fortre); prendlst(); prs_buff("done"); } break; case TWH: case TUN: if (type == TWH) prs_buff("while "); else prs_buff("until "); prf(whptr(t)->whtre); prendlst(); prs_buff("do"); prbgnlst(); prf(whptr(t)->dotre); prendlst(); prs_buff("done"); break; case TIF: { struct ifnod *f = (struct ifnod *)t; prs_buff("if "); prf(f->iftre); prendlst(); prs_buff("then"); prendlst(); prf(f->thtre); if (f->eltre) { prendlst(); prs_buff("else"); prendlst(); prf(f->eltre); } prendlst(); prs_buff("fi"); break; } case TSW: { struct regnod *swl; prs_buff("case "); prs_buff(swptr(t)->swarg); swl = swptr(t)->swlst; while(swl) { struct argnod *arg = swl->regptr; if (arg) { prs_buff(arg->argval); arg = arg->argnxt; } while(arg) { prs_buff(" | "); prs_buff(arg->argval); arg = arg->argnxt; } prs_buff(")"); prf(swl->regcom); prs_buff(";;"); swl = swl->regnxt; } } break; } } sigchk(); }
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) { #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()); #else 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) { if (dashex) prettyprint_fn(2, l->w, n->u[1].p); 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) { if (dashex) fprint(2, "fn %S\n", l->w); 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); if (dashex) fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " "); 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(); }