X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/2f2a064994b149267b4e6f2e4e3643377de981dc..f52b918007dc218cdf8cd43fe2d631fecebc3bf2:/usr/src/bin/csh/func.c diff --git a/usr/src/bin/csh/func.c b/usr/src/bin/csh/func.c index 15b16af5bf..9011738cbf 100644 --- a/usr/src/bin/csh/func.c +++ b/usr/src/bin/csh/func.c @@ -1,1073 +1,1443 @@ -static char *sccsid = "@(#)func.c 4.10 83/06/11"; +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% + */ -#include "sh.h" -#include +#ifndef lint +static char sccsid[] = "@(#)func.c 5.25 (Berkeley) %G%"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#if __STDC__ +# include +#else +# include +#endif -/* - * C shell - */ +#include "csh.h" +#include "extern.h" +#include "pathnames.h" + +extern char **environ; + +static int zlast = -1; +static void islogin __P((void)); +static void reexecute __P((struct command *)); +static void preread __P((void)); +static void doagain __P((void)); +static int getword __P((Char *)); +static int keyword __P((Char *)); +static void Unsetenv __P((Char *)); +static void toend __P((void)); +static void xecho __P((int, Char **)); struct biltins * isbfunc(t) - register struct command *t; + struct command *t; { - register char *cp = t->t_dcom[0]; - register char *dp; - register struct biltins *bp; - int dolabel(), dofg1(), dobg1(); - static struct biltins label = { "", dolabel, 0, 0 }; - static struct biltins foregnd = { "%job", dofg1, 0, 0 }; - static struct biltins backgnd = { "%job &", dobg1, 0, 0 }; - - if (lastchr(cp) == ':') { - label.bname = cp; - return (&label); - } - if (*cp == '%') { - if (t->t_dflg & FAND) { - t->t_dflg &= ~FAND; - backgnd.bname = cp; - return (&backgnd); - } - foregnd.bname = cp; - return (&foregnd); + register Char *cp = t->t_dcom[0]; + register struct biltins *bp, *bp1, *bp2; + static struct biltins label = {"", dozip, 0, 0}; + static struct biltins foregnd = {"%job", dofg1, 0, 0}; + static struct biltins backgnd = {"%job &", dobg1, 0, 0}; + + if (lastchr(cp) == ':') { + label.bname = short2str(cp); + return (&label); + } + if (*cp == '%') { + if (t->t_dflg & F_AMPERSAND) { + t->t_dflg &= ~F_AMPERSAND; + backgnd.bname = short2str(cp); + return (&backgnd); } - for (bp = bfunc; dp = bp->bname; bp++) { - if (dp[0] == cp[0] && eq(dp, cp)) - return (bp); - if (dp[0] > cp[0]) - break; - } - return (0); + foregnd.bname = short2str(cp); + return (&foregnd); + } + /* + * Binary search Bp1 is the beginning of the current search range. Bp2 is + * one past the end. + */ + for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { + register i; + + bp = bp1 + ((bp2 - bp1) >> 1); + if ((i = *cp - *bp->bname) == 0 && + (i = Strcmp(cp, str2short(bp->bname))) == 0) + return bp; + if (i < 0) + bp2 = bp; + else + bp1 = bp + 1; + } + return (0); } +void func(t, bp) - register struct command *t; - register struct biltins *bp; + register struct command *t; + register struct biltins *bp; { - int i; - - xechoit(t->t_dcom); - setname(bp->bname); - i = blklen(t->t_dcom) - 1; - if (i < bp->minargs) - bferr("Too few arguments"); - if (i > bp->maxargs) - bferr("Too many arguments"); - (*bp->bfunct)(t->t_dcom, t); -} - -dolabel() -{ - + int i; + + xechoit(t->t_dcom); + setname(bp->bname); + i = blklen(t->t_dcom) - 1; + if (i < bp->minargs) + stderror(ERR_NAME | ERR_TOOFEW); + if (i > bp->maxargs) + stderror(ERR_NAME | ERR_TOOMANY); + (*bp->bfunct) (t->t_dcom, t); } -doonintr(v) - char **v; +void +/*ARGSUSED*/ +doonintr(v, t) + Char **v; + struct command *t; { - register char *cp; - register char *vv = v[1]; - - if (parintr == SIG_IGN) - return; - if (setintr && intty) - bferr("Can't from terminal"); - cp = gointr, gointr = 0, xfree(cp); - if (vv == 0) { - if (setintr) - sighold(SIGINT); - else - sigset(SIGINT, SIG_DFL); - gointr = 0; - } else if (eq((vv = strip(vv)), "-")) { - sigset(SIGINT, SIG_IGN); - gointr = "-"; - } else { - gointr = savestr(vv); - sigset(SIGINT, pintr); - } + register Char *cp; + register Char *vv = v[1]; + + if (parintr == SIG_IGN) + return; + if (setintr && intty) + stderror(ERR_NAME | ERR_TERMINAL); + cp = gointr; + gointr = 0; + xfree((ptr_t) cp); + if (vv == 0) { + if (setintr) + (void) sigblock(sigmask(SIGINT)); + else + (void) signal(SIGINT, SIG_DFL); + gointr = 0; + } + else if (eq((vv = strip(vv)), STRminus)) { + (void) signal(SIGINT, SIG_IGN); + gointr = Strsave(STRminus); + } + else { + gointr = Strsave(vv); + (void) signal(SIGINT, pintr); + } } -donohup() +void +/*ARGSUSED*/ +donohup(v, t) + Char **v; + struct command *t; { - - if (intty) - bferr("Can't from terminal"); - if (setintr == 0) { - signal(SIGHUP, SIG_IGN); -#ifdef CC - submit(getpid()); -#endif - } + if (intty) + stderror(ERR_NAME | ERR_TERMINAL); + if (setintr == 0) { + (void) signal(SIGHUP, SIG_IGN); + } } -dozip() +void +/*ARGSUSED*/ +dozip(v, t) + Char **v; + struct command *t; { - - ; + ; } +void prvars() { - - plist(&shvhed); + plist(&shvhed); } -doalias(v) - register char **v; +void +/*ARGSUSED*/ +doalias(v, t) + Char **v; + struct command *t; { - register struct varent *vp; - register char *p; - - v++; - p = *v++; - if (p == 0) - plist(&aliases); - else if (*v == 0) { - vp = adrof1(strip(p), &aliases); - if (vp) - blkpr(vp->vec), printf("\n"); - } else { - if (eq(p, "alias") || eq(p, "unalias")) { - setname(p); - bferr("Too dangerous to alias that"); - } - set1(strip(p), saveblk(v), &aliases); + register struct varent *vp; + register Char *p; + + v++; + p = *v++; + if (p == 0) + plist(&aliases); + else if (*v == 0) { + vp = adrof1(strip(p), &aliases); + if (vp) { + blkpr(cshout, vp->vec); + fputc('\n', cshout); } + } + else { + if (eq(p, STRalias) || eq(p, STRunalias)) { + setname(short2str(p)); + stderror(ERR_NAME | ERR_DANGER); + } + set1(strip(p), saveblk(v), &aliases); + } } -unalias(v) - char **v; +void +/*ARGSUSED*/ +unalias(v, t) + Char **v; + struct command *t; { - - unset1(v, &aliases); + unset1(v, &aliases); } -dologout() +void +/*ARGSUSED*/ +dologout(v, t) + Char **v; + struct command *t; { - - islogin(); - goodbye(); + islogin(); + goodbye(); } -dologin(v) - char **v; +void +/*ARGSUSED*/ +dologin(v, t) + Char **v; + struct command *t; { - - islogin(); - rechist(); - signal(SIGTERM, parterm); - execl("/bin/login", "login", v[1], 0); - untty(); - exit(1); + islogin(); + rechist(); + (void) signal(SIGTERM, parterm); + (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); + untty(); + xexit(1); } -#ifdef NEWGRP -donewgrp(v) - char **v; -{ - - if (chkstop == 0 && setintr) - panystop(0); - signal(SIGTERM, parterm); - execl("/bin/newgrp", "newgrp", v[1], 0); - execl("/usr/bin/newgrp", "newgrp", v[1], 0); - untty(); - exit(1); -} -#endif - +static void islogin() { - - if (chkstop == 0 && setintr) - panystop(0); - if (loginsh) - return; - error("Not login shell"); + if (chkstop == 0 && setintr) + panystop(0); + if (loginsh) + return; + stderror(ERR_NOTLOGIN); } +void doif(v, kp) - char **v; - struct command *kp; + Char **v; + struct command *kp; { - register int i; - register char **vv; - - v++; - i = exp(&v); - vv = v; - if (*vv == NOSTR) - bferr("Empty if"); - if (eq(*vv, "then")) { - if (*++vv) - bferr("Improper then"); - setname("then"); - /* - * If expression was zero, then scan to else, - * otherwise just fall into following code. - */ - if (!i) - search(ZIF, 0); - return; - } + register int i; + register Char **vv; + + v++; + i = exp(&v); + vv = v; + if (*vv == NULL) + stderror(ERR_NAME | ERR_EMPTYIF); + if (eq(*vv, STRthen)) { + if (*++vv) + stderror(ERR_NAME | ERR_IMPRTHEN); + setname(short2str(STRthen)); /* - * Simple command attached to this if. - * Left shift the node in this tree, munging it - * so we can reexecute it. + * If expression was zero, then scan to else, otherwise just fall into + * following code. */ - if (i) { - lshift(kp->t_dcom, vv - kp->t_dcom); - reexecute(kp); - donefds(); - } + if (!i) + search(T_IF, 0, NULL); + return; + } + /* + * Simple command attached to this if. Left shift the node in this tree, + * munging it so we can reexecute it. + */ + if (i) { + lshift(kp->t_dcom, vv - kp->t_dcom); + reexecute(kp); + donefds(); + } } /* * Reexecute a command, being careful not * to redo i/o redirection, which is already set up. */ +static void reexecute(kp) - register struct command *kp; + register struct command *kp; { - - kp->t_dflg &= FSAVE; - kp->t_dflg |= FREDO; - /* - * If tty is still ours to arbitrate, arbitrate it; - * otherwise dont even set pgrp's as the jobs would - * then have no way to get the tty (we can't give it - * to them, and our parent wouldn't know their pgrp, etc. - */ - execute(kp, tpgrp > 0 ? tpgrp : -1); + kp->t_dflg &= F_SAVE; + kp->t_dflg |= F_REPEAT; + /* + * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set + * pgrp's as the jobs would then have no way to get the tty (we can't give + * it to them, and our parent wouldn't know their pgrp, etc. + */ + execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); } -doelse() +void +/*ARGSUSED*/ +doelse(v, t) + Char **v; + struct command *t; { - - search(ZELSE, 0); + search(T_ELSE, 0, NULL); } -dogoto(v) - char **v; +void +/*ARGSUSED*/ +dogoto(v, t) + Char **v; + struct command *t; { - register struct whyle *wp; - char *lp; - - /* - * While we still can, locate any unknown ends of existing loops. - * This obscure code is the WORST result of the fact that we - * don't really parse. - */ - for (wp = whyles; wp; wp = wp->w_next) - if (wp->w_end == 0) { - search(ZBREAK, 0); - wp->w_end = btell(); - } else - bseek(wp->w_end); - search(ZGOTO, 0, lp = globone(v[1])); - xfree(lp); - /* - * Eliminate loops which were exited. - */ - wfree(); + register struct whyle *wp; + Char *lp; + + /* + * While we still can, locate any unknown ends of existing loops. This + * obscure code is the WORST result of the fact that we don't really parse. + */ + zlast = T_GOTO; + for (wp = whyles; wp; wp = wp->w_next) + if (wp->w_end.type == I_SEEK) { + search(T_BREAK, 0, NULL); + btell(&wp->w_end); + } + else + bseek(&wp->w_end); + search(T_GOTO, 0, lp = globone(v[1], G_ERROR)); + xfree((ptr_t) lp); + /* + * Eliminate loops which were exited. + */ + wfree(); } -doswitch(v) - register char **v; +void +/*ARGSUSED*/ +doswitch(v, t) + Char **v; + struct command *t; { - register char *cp, *lp; - - v++; - if (!*v || *(*v++) != '(') - goto syntax; - cp = **v == ')' ? "" : *v++; - if (*(*v++) != ')') - v--; - if (*v) -syntax: - error("Syntax error"); - search(ZSWITCH, 0, lp = globone(cp)); - xfree(lp); + register Char *cp, *lp; + + v++; + if (!*v || *(*v++) != '(') + stderror(ERR_SYNTAX); + cp = **v == ')' ? STRNULL : *v++; + if (*(*v++) != ')') + v--; + if (*v) + stderror(ERR_SYNTAX); + search(T_SWITCH, 0, lp = globone(cp, G_ERROR)); + xfree((ptr_t) lp); } -dobreak() +void +/*ARGSUSED*/ +dobreak(v, t) + Char **v; + struct command *t; { - - if (whyles) - toend(); - else - bferr("Not in while/foreach"); + if (whyles) + toend(); + else + stderror(ERR_NAME | ERR_NOTWHILE); } -doexit(v) - char **v; +void +/*ARGSUSED*/ +doexit(v, t) + Char **v; + struct command *t; { - - if (chkstop == 0) - panystop(0); - /* - * Don't DEMAND parentheses here either. - */ - v++; - if (*v) { - set("status", putn(exp(&v))); - if (*v) - bferr("Expression syntax"); - } - btoeof(); - if (intty) - close(SHIN); + if (chkstop == 0 && (intty || intact) && evalvec == 0) + panystop(0); + /* + * Don't DEMAND parentheses here either. + */ + v++; + if (*v) { + set(STRstatus, putn(exp(&v))); + if (*v) + stderror(ERR_NAME | ERR_EXPRESSION); + } + btoeof(); + if (intty) + (void) close(SHIN); } -doforeach(v) - register char **v; +void +/*ARGSUSED*/ +doforeach(v, t) + Char **v; + struct command *t; { - register char *cp; - register struct whyle *nwp; - - v++; - cp = strip(*v); - while (*cp && letter(*cp)) - cp++; - if (*cp || strlen(*v) >= 20) - bferr("Invalid variable"); - cp = *v++; - if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') - bferr("Words not ()'ed"); - v++; - gflag = 0, rscan(v, tglob); - v = glob(v); - if (v == 0) - bferr("No match"); - nwp = (struct whyle *) calloc(1, sizeof *nwp); - nwp->w_fe = nwp->w_fe0 = v; gargv = 0; - nwp->w_start = btell(); - nwp->w_fename = savestr(cp); - nwp->w_next = whyles; - whyles = nwp; - /* - * Pre-read the loop so as to be more - * comprehensible to a terminal user. - */ - if (intty) - preread(); - doagain(); + register Char *cp, *sp; + register struct whyle *nwp; + + v++; + sp = cp = strip(*v); + if (!letter(*sp)) + stderror(ERR_NAME | ERR_VARBEGIN); + while (*cp && alnum(*cp)) + cp++; + if (*cp) + stderror(ERR_NAME | ERR_VARALNUM); + if ((cp - sp) > MAXVARLEN) + stderror(ERR_NAME | ERR_VARTOOLONG); + cp = *v++; + if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') + stderror(ERR_NAME | ERR_NOPAREN); + v++; + gflag = 0, tglob(v); + v = globall(v); + if (v == 0) + stderror(ERR_NAME | ERR_NOMATCH); + nwp = (struct whyle *) xcalloc(1, sizeof *nwp); + nwp->w_fe = nwp->w_fe0 = v; + gargv = 0; + btell(&nwp->w_start); + nwp->w_fename = Strsave(cp); + nwp->w_next = whyles; + whyles = nwp; + /* + * Pre-read the loop so as to be more comprehensible to a terminal user. + */ + zlast = T_FOREACH; + if (intty) + preread(); + doagain(); } -dowhile(v) - char **v; +void +/*ARGSUSED*/ +dowhile(v, t) + Char **v; + struct command *t; { - register int status; - register bool again = whyles != 0 && whyles->w_start == lineloc && - whyles->w_fename == 0; - - v++; - /* - * Implement prereading here also, taking care not to - * evaluate the expression before the loop has been read up - * from a terminal. - */ - if (intty && !again) - status = !exp0(&v, 1); - else - status = !exp(&v); - if (*v) - bferr("Expression syntax"); - if (!again) { - register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp)); - - nwp->w_start = lineloc; - nwp->w_end = 0; - nwp->w_next = whyles; - whyles = nwp; - if (intty) { - /* - * The tty preread - */ - preread(); - doagain(); - return; - } + register int status; + register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && + whyles->w_fename == 0; + + v++; + /* + * Implement prereading here also, taking care not to evaluate the + * expression before the loop has been read up from a terminal. + */ + if (intty && !again) + status = !exp0(&v, 1); + else + status = !exp(&v); + if (*v) + stderror(ERR_NAME | ERR_EXPRESSION); + if (!again) { + register struct whyle *nwp = + (struct whyle *) xcalloc(1, sizeof(*nwp)); + + nwp->w_start = lineloc; + nwp->w_end.type = I_SEEK; + nwp->w_next = whyles; + whyles = nwp; + zlast = T_WHILE; + if (intty) { + /* + * The tty preread + */ + preread(); + doagain(); + return; } - if (status) - /* We ain't gonna loop no more, no more! */ - toend(); + } + if (status) + /* We ain't gonna loop no more, no more! */ + toend(); } +static void preread() { - - whyles->w_end = -1; - if (setintr) - sigrelse(SIGINT); - search(ZBREAK, 0); - if (setintr) - sighold(SIGINT); - whyles->w_end = btell(); + whyles->w_end.type = I_SEEK; + if (setintr) + (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); + + search(T_BREAK, 0, NULL); /* read the expression in */ + if (setintr) + (void) sigblock(sigmask(SIGINT)); + btell(&whyles->w_end); } -doend() +void +/*ARGSUSED*/ +doend(v, t) + Char **v; + struct command *t; { - - if (!whyles) - bferr("Not in while/foreach"); - whyles->w_end = btell(); - doagain(); + if (!whyles) + stderror(ERR_NAME | ERR_NOTWHILE); + btell(&whyles->w_end); + doagain(); } -docontin() +void +/*ARGSUSED*/ +docontin(v, t) + Char **v; + struct command *t; { - - if (!whyles) - bferr("Not in while/foreach"); - doagain(); + if (!whyles) + stderror(ERR_NAME | ERR_NOTWHILE); + doagain(); } +static void doagain() { - - /* Repeating a while is simple */ - if (whyles->w_fename == 0) { - bseek(whyles->w_start); - return; - } - /* - * The foreach variable list actually has a spurious word - * ")" at the end of the w_fe list. Thus we are at the - * of the list if one word beyond this is 0. - */ - if (!whyles->w_fe[1]) { - dobreak(); - return; - } - set(whyles->w_fename, savestr(*whyles->w_fe++)); - bseek(whyles->w_start); + /* Repeating a while is simple */ + if (whyles->w_fename == 0) { + bseek(&whyles->w_start); + return; + } + /* + * The foreach variable list actually has a spurious word ")" at the end of + * the w_fe list. Thus we are at the of the list if one word beyond this + * is 0. + */ + if (!whyles->w_fe[1]) { + dobreak(NULL, NULL); + return; + } + set(whyles->w_fename, Strsave(*whyles->w_fe++)); + bseek(&whyles->w_start); } +void dorepeat(v, kp) - char **v; - struct command *kp; + Char **v; + struct command *kp; { - register int i; - - i = getn(v[1]); + register int i; + register sigset_t omask = 0; + + i = getn(v[1]); + if (setintr) + omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); + lshift(v, 2); + while (i > 0) { if (setintr) - sighold(SIGINT); - lshift(v, 2); - while (i > 0) { - if (setintr) - sigrelse(SIGINT); - reexecute(kp); - --i; - } - donefds(); - if (setintr) - sigrelse(SIGINT); + (void) sigsetmask(omask); + reexecute(kp); + --i; + } + donefds(); + if (setintr) + (void) sigsetmask(omask); } -doswbrk() +void +/*ARGSUSED*/ +doswbrk(v, t) + Char **v; + struct command *t; { - - search(ZBRKSW, 0); + search(T_BRKSW, 0, NULL); } +int srchx(cp) - register char *cp; + register Char *cp; { - register struct srch *sp; - - for (sp = srchn; sp->s_name; sp++) - if (eq(cp, sp->s_name)) - return (sp->s_value); - return (-1); + register struct srch *sp, *sp1, *sp2; + register i; + + /* + * Binary search Sp1 is the beginning of the current search range. Sp2 is + * one past the end. + */ + for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { + sp = sp1 + ((sp2 - sp1) >> 1); + if ((i = *cp - *sp->s_name) == 0 && + (i = Strcmp(cp, str2short(sp->s_name))) == 0) + return sp->s_value; + if (i < 0) + sp2 = sp; + else + sp1 = sp + 1; + } + return (-1); } -char Stype; -char *Sgoal; +static Char Stype; +static Char *Sgoal; /*VARARGS2*/ +void search(type, level, goal) - int type; - register int level; - char *goal; + int type; + register int level; + Char *goal; { - char wordbuf[BUFSIZ]; - register char *aword = wordbuf; - register char *cp; + Char wordbuf[BUFSIZ]; + register Char *aword = wordbuf; + register Char *cp; + + Stype = type; + Sgoal = goal; + if (type == T_GOTO) { + struct Ain a; + a.type = F_SEEK; + a.f_seek = 0; + bseek(&a); + } + do { + if (intty && fseekp == feobp && aret == F_SEEK) + (void) fprintf(cshout, "? "), (void) fflush(cshout); + aword[0] = 0; + (void) getword(aword); + switch (srchx(aword)) { + + case T_ELSE: + if (level == 0 && type == T_IF) + return; + break; + + case T_IF: + while (getword(aword)) + continue; + if ((type == T_IF || type == T_ELSE) && + eq(aword, STRthen)) + level++; + break; + + case T_ENDIF: + if (type == T_IF || type == T_ELSE) + level--; + break; + + case T_FOREACH: + case T_WHILE: + if (type == T_BREAK) + level++; + break; + + case T_END: + if (type == T_BREAK) + level--; + break; + + case T_SWITCH: + if (type == T_SWITCH || type == T_BRKSW) + level++; + break; + + case T_ENDSW: + if (type == T_SWITCH || type == T_BRKSW) + level--; + break; + + case T_LABEL: + if (type == T_GOTO && getword(aword) && eq(aword, goal)) + level = -1; + break; - Stype = type; Sgoal = goal; - if (type == ZGOTO) - bseek(0l); - do { - if (intty && fseekp == feobp) - printf("? "), flush(); - aword[0] = 0, getword(aword); - switch (srchx(aword)) { - - case ZELSE: - if (level == 0 && type == ZIF) - return; - break; - - case ZIF: - while (getword(aword)) - continue; - if ((type == ZIF || type == ZELSE) && eq(aword, "then")) - level++; - break; - - case ZENDIF: - if (type == ZIF || type == ZELSE) - level--; - break; - - case ZFOREACH: - case ZWHILE: - if (type == ZBREAK) - level++; - break; - - case ZEND: - if (type == ZBREAK) - level--; - break; - - case ZSWITCH: - if (type == ZSWITCH || type == ZBRKSW) - level++; - break; - - case ZENDSW: - if (type == ZSWITCH || type == ZBRKSW) - level--; - break; - - case ZLABEL: - if (type == ZGOTO && getword(aword) && eq(aword, goal)) - level = -1; - break; - - default: - if (type != ZGOTO && (type != ZSWITCH || level != 0)) - break; - if (lastchr(aword) != ':') - break; - aword[strlen(aword) - 1] = 0; - if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default")) - level = -1; - break; - - case ZCASE: - if (type != ZSWITCH || level != 0) - break; - getword(aword); - if (lastchr(aword) == ':') - aword[strlen(aword) - 1] = 0; - cp = strip(Dfix1(aword)); - if (Gmatch(goal, cp)) - level = -1; - xfree(cp); - break; - - case ZDEFAULT: - if (type == ZSWITCH && level == 0) - level = -1; - break; - } - getword(NOSTR); - } while (level >= 0); + default: + if (type != T_GOTO && (type != T_SWITCH || level != 0)) + break; + if (lastchr(aword) != ':') + break; + aword[Strlen(aword) - 1] = 0; + if (type == T_GOTO && eq(aword, goal) || + type == T_SWITCH && eq(aword, STRdefault)) + level = -1; + break; + + case T_CASE: + if (type != T_SWITCH || level != 0) + break; + (void) getword(aword); + if (lastchr(aword) == ':') + aword[Strlen(aword) - 1] = 0; + cp = strip(Dfix1(aword)); + if (Gmatch(goal, cp)) + level = -1; + xfree((ptr_t) cp); + break; + + case T_DEFAULT: + if (type == T_SWITCH && level == 0) + level = -1; + break; + } + (void) getword(NULL); + } while (level >= 0); } +static int getword(wp) - register char *wp; + register Char *wp; { - register int found = 0; - register int c, d; - - c = readc(1); - d = 0; + register int found = 0; + register int c, d; + int kwd = 0; + Char *owp = wp; + + c = readc(1); + d = 0; + do { + while (c == ' ' || c == '\t') + c = readc(1); + if (c == '#') + do + c = readc(1); + while (c >= 0 && c != '\n'); + if (c < 0) + goto past; + if (c == '\n') { + if (wp) + break; + return (0); + } + unreadc(c); + found = 1; do { - while (c == ' ' || c == '\t') - c = readc(1); - if (c == '#') - do - c = readc(1); - while (c >= 0 && c != '\n'); - if (c < 0) - goto past; - if (c == '\n') { - if (wp) - break; - return (0); - } - unreadc(c); - found = 1; - do { - c = readc(1); - if (c == '\\' && (c = readc(1)) == '\n') - c = ' '; - if (any(c, "'\"")) - if (d == 0) - d = c; - else if (d == c) - d = 0; - if (c < 0) - goto past; - if (wp) - *wp++ = c; - } while ((d || c != ' ' && c != '\t') && c != '\n'); - } while (wp == 0); + c = readc(1); + if (c == '\\' && (c = readc(1)) == '\n') + c = ' '; + if (c == '\'' || c == '"') + if (d == 0) + d = c; + else if (d == c) + d = 0; + if (c < 0) + goto past; + if (wp) { + *wp++ = c; + *wp = 0; /* end the string b4 test */ + } + } while ((d || !(kwd = keyword(owp)) && c != ' ' + && c != '\t') && c != '\n'); + } while (wp == 0); + + /* + * if we have read a keyword ( "if", "switch" or "while" ) then we do not + * need to unreadc the look-ahead char + */ + if (!kwd) { unreadc(c); if (found) - *--wp = 0; - return (found); + *--wp = 0; + } + + return (found); past: - switch (Stype) { + switch (Stype) { - case ZIF: - bferr("then/endif not found"); + case T_IF: + stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); - case ZELSE: - bferr("endif not found"); + case T_ELSE: + stderror(ERR_NAME | ERR_NOTFOUND, "endif"); - case ZBRKSW: - case ZSWITCH: - bferr("endsw not found"); + case T_BRKSW: + case T_SWITCH: + stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); - case ZBREAK: - bferr("end not found"); + case T_BREAK: + stderror(ERR_NAME | ERR_NOTFOUND, "end"); - case ZGOTO: - setname(Sgoal); - bferr("label not found"); - } - /*NOTREACHED*/ + case T_GOTO: + setname(short2str(Sgoal)); + stderror(ERR_NAME | ERR_NOTFOUND, "label"); + } + /* NOTREACHED */ + return (0); } -toend() +/* + * keyword(wp) determines if wp is one of the built-n functions if, + * switch or while. It seems that when an if statement looks like + * "if(" then getword above sucks in the '(' and so the search routine + * never finds what it is scanning for. Rather than rewrite doword, I hack + * in a test to see if the string forms a keyword. Then doword stops + * and returns the word "if" -strike + */ + +static int +keyword(wp) + Char *wp; { + static Char STRif[] = {'i', 'f', '\0'}; + static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; + static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; - if (whyles->w_end == 0) { - search(ZBREAK, 0); - whyles->w_end = btell() - 1; - } else - bseek(whyles->w_end); - wfree(); + if (!wp) + return (0); + + if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) + || (Strcmp(wp, STRswitch) == 0)) + return (1); + + return (0); } -wfree() +static void +toend() { - long o = btell(); - - while (whyles) { - register struct whyle *wp = whyles; - register struct whyle *nwp = wp->w_next; - - if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) - break; - if (wp->w_fe0) - blkfree(wp->w_fe0); - if (wp->w_fename) - xfree(wp->w_fename); - xfree((char *)wp); - whyles = nwp; - } + if (whyles->w_end.type == I_SEEK) { + search(T_BREAK, 0, NULL); + btell(&whyles->w_end); + whyles->w_end.f_seek--; + } + else + bseek(&whyles->w_end); + wfree(); } -doecho(v) - char **v; +void +wfree() { - - echo(' ', v); + struct Ain o; + struct whyle *nwp; + btell(&o); + + if (o.type != F_SEEK) + return; + + for (; whyles; whyles = nwp) { + register struct whyle *wp = whyles; + nwp = wp->w_next; + if (wp->w_start.type != F_SEEK || wp->w_end.type != F_SEEK) + continue; + + if (o.f_seek >= wp->w_start.f_seek && + (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) + break; + if (wp->w_fe0) + blkfree(wp->w_fe0); + if (wp->w_fename) + xfree((ptr_t) wp->w_fename); + xfree((ptr_t) wp); + } } -doglob(v) - char **v; +void +/*ARGSUSED*/ +doecho(v, t) + Char **v; + struct command *t; { - - echo(0, v); - flush(); + xecho(' ', v); } -echo(sep, v) - char sep; - register char **v; +void +/*ARGSUSED*/ +doglob(v, t) + Char **v; + struct command *t; { - register char *cp; - int nonl = 0; - - if (setintr) - sigrelse(SIGINT); - v++; - if (*v == 0) - return; - gflag = 0; rscan(v, tglob); - if (gflag) { - v = glob(v); - if (v == 0) - bferr("No match"); - } else - scan(v, trim); - if (sep == ' ' && !strcmp(*v, "-n")) - nonl++, v++; - while (cp = *v++) { - register int c; - - while (c = *cp++) - putchar(c | QUOTE); - if (*v) - putchar(sep | QUOTE); - } - if (sep && nonl == 0) - putchar('\n'); - else - flush(); - if (setintr) - sighold(SIGINT); - if (gargv) - blkfree(gargv), gargv = 0; + xecho(0, v); + (void) fflush(cshout); } -char **environ; - -dosetenv(v) - register char **v; +static void +xecho(sep, v) + int sep; + register Char **v; { - char *lp = globone(v[2]); + register Char *cp; + int nonl = 0; + + if (setintr) + (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); + v++; + if (*v == 0) + return; + gflag = 0, tglob(v); + if (gflag) { + v = globall(v); + if (v == 0) + stderror(ERR_NAME | ERR_NOMATCH); + } + else { + v = gargv = saveblk(v); + trim(v); + } + if (sep == ' ' && *v && eq(*v, STRmn)) + nonl++, v++; + while (cp = *v++) { + register int c; + + while (c = *cp++) + (void) fputc(c | QUOTE, cshout); - setenv(v[1], lp); - if (eq(v[1], "PATH")) { - importpath(lp); - dohash(); - } - xfree(lp); + if (*v) + (void) fputc(sep | QUOTE, cshout); + } + if (sep && nonl == 0) + (void) fputc('\n', cshout); + else + (void) fflush(cshout); + if (setintr) + (void) sigblock(sigmask(SIGINT)); + if (gargv) + blkfree(gargv), gargv = 0; } -dounsetenv(v) - register char **v; +void +/*ARGSUSED*/ +dosetenv(v, t) + Char **v; + struct command *t; { + Char *vp, *lp; - v++; - do - unsetenv(*v++); - while (*v); + v++; + if ((vp = *v++) == 0) { + register Char **ep; + + if (setintr) + (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); + for (ep = STR_environ; *ep; ep++) + (void) fprintf(cshout, "%s\n", short2str(*ep)); + return; + } + if ((lp = *v++) == 0) + lp = STRNULL; + Setenv(vp, lp = globone(lp, G_APPEND)); + if (eq(vp, STRPATH)) { + importpath(lp); + dohash(NULL, NULL); + } + else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { +#ifdef NLS + int k; + + (void) setlocale(LC_ALL, ""); + for (k = 0200; k <= 0377 && !Isprint(k); k++); + AsciiOnly = k > 0377; +#else + AsciiOnly = 0; +#endif /* NLS */ + } + xfree((ptr_t) lp); } -setenv(name, value) - char *name, *value; +void +/*ARGSUSED*/ +dounsetenv(v, t) + Char **v; + struct command *t; { - register char **ep = environ; - register char *cp, *dp; - char *blk[2], **oep = ep; - - for (; *ep; ep++) { - for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) - continue; - if (*cp != 0 || *dp != '=') - continue; - cp = strspl("=", value); - xfree(*ep); - *ep = strspl(name, cp); - xfree(cp); - scan(ep, trim); - return; - } - blk[0] = strspl(name, "="); blk[1] = 0; - environ = blkspl(environ, blk); - xfree((char *)oep); - setenv(name, value); + Char **ep, *p, *n; + int i, maxi; + static Char *name = NULL; + + if (name) + xfree((ptr_t) name); + /* + * Find the longest environment variable + */ + for (maxi = 0, ep = STR_environ; *ep; ep++) { + for (i = 0, p = *ep; *p && *p != '='; p++, i++); + if (i > maxi) + maxi = i; + } + + name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); + + while (++v && *v) + for (maxi = 1; maxi;) + for (maxi = 0, ep = STR_environ; *ep; ep++) { + for (n = name, p = *ep; *p && *p != '='; *n++ = *p++); + *n = '\0'; + if (!Gmatch(name, *v)) + continue; + maxi = 1; + if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { +#ifdef NLS + int k; + + (void) setlocale(LC_ALL, ""); + for (k = 0200; k <= 0377 && !Isprint(k); k++); + AsciiOnly = k > 0377; +#else + AsciiOnly = getenv("LANG") == NULL && + getenv("LC_CTYPE") == NULL; +#endif /* NLS */ + } + /* + * Delete name, and start again cause the environment changes + */ + Unsetenv(name); + break; + } + xfree((ptr_t) name); + name = NULL; } -unsetenv(name) - char *name; +void +Setenv(name, val) + Char *name, *val; { - register char **ep = environ; - register char *cp, *dp; - char **oep = ep; - - for (; *ep; ep++) { - for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) - continue; - if (*cp != 0 || *dp != '=') - continue; - cp = *ep; - *ep = 0; - environ = blkspl(environ, ep+1); - *ep = cp; - xfree(cp); - xfree((char *)oep); - return; - } + register Char **ep = STR_environ; + register Char *cp, *dp; + Char *blk[2]; + Char **oep = ep; + + + for (; *ep; ep++) { + for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) + continue; + if (*cp != 0 || *dp != '=') + continue; + cp = Strspl(STRequal, val); + xfree((ptr_t) * ep); + *ep = strip(Strspl(name, cp)); + xfree((ptr_t) cp); + blkfree((Char **) environ); + environ = short2blk(STR_environ); + return; + } + cp = Strspl(name, STRequal); + blk[0] = strip(Strspl(cp, val)); + xfree((ptr_t) cp); + blk[1] = 0; + STR_environ = blkspl(STR_environ, blk); + blkfree((Char **) environ); + environ = short2blk(STR_environ); + xfree((ptr_t) oep); } -doumask(v) - register char **v; +static void +Unsetenv(name) + Char *name; { - register char *cp = v[1]; - register int i; - - if (cp == 0) { - i = umask(0); - umask(i); - printf("%o\n", i); - return; - } - i = 0; - while (digit(*cp) && *cp != '8' && *cp != '9') - i = i * 8 + *cp++ - '0'; - if (*cp || i < 0 || i > 0777) - bferr("Improper mask"); - umask(i); + register Char **ep = STR_environ; + register Char *cp, *dp; + Char **oep = ep; + + for (; *ep; ep++) { + for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) + continue; + if (*cp != 0 || *dp != '=') + continue; + cp = *ep; + *ep = 0; + STR_environ = blkspl(STR_environ, ep + 1); + environ = short2blk(STR_environ); + *ep = cp; + xfree((ptr_t) cp); + xfree((ptr_t) oep); + return; + } } +void +/*ARGSUSED*/ +doumask(v, t) + Char **v; + struct command *t; +{ + register Char *cp = v[1]; + register int i; + + if (cp == 0) { + i = umask(0); + (void) umask(i); + (void) fprintf(cshout, "%o\n", i); + return; + } + i = 0; + while (Isdigit(*cp) && *cp != '8' && *cp != '9') + i = i * 8 + *cp++ - '0'; + if (*cp || i < 0 || i > 0777) + stderror(ERR_NAME | ERR_MASK); + (void) umask(i); +} -struct limits { - int limconst; - char *limname; - int limdiv; - char *limscale; -} limits[] = { - RLIMIT_CPU, "cputime", 1, "seconds", - RLIMIT_FSIZE, "filesize", 1024, "kbytes", - RLIMIT_DATA, "datasize", 1024, "kbytes", - RLIMIT_STACK, "stacksize", 1024, "kbytes", - RLIMIT_CORE, "coredumpsize", 1024, "kbytes", - RLIMIT_RSS, "memoryuse", 1024, "kbytes", - -1, 0, +typedef int RLIM_TYPE; + +static struct limits { + int limconst; + char *limname; + int limdiv; + char *limscale; +} limits[] = { + RLIMIT_CPU, "cputime", 1, "seconds", + RLIMIT_FSIZE, "filesize", 1024, "kbytes", + RLIMIT_DATA, "datasize", 1024, "kbytes", + RLIMIT_STACK, "stacksize", 1024, "kbytes", + RLIMIT_CORE, "coredumpsize", 1024, "kbytes", + RLIMIT_RSS, "memoryuse", 1024, "kbytes", + RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes", + RLIMIT_NPROC, "maxproc", 1, "", + RLIMIT_OFILE, "openfiles", 1, "", + -1, NULL, 0, NULL }; -struct limits * +static struct limits *findlim(); +static RLIM_TYPE getval(); +static void limtail(); +static void plim(); +static int setlim(); + +static struct limits * findlim(cp) - char *cp; + Char *cp; { - register struct limits *lp, *res; - - res = 0; - for (lp = limits; lp->limconst >= 0; lp++) - if (prefix(cp, lp->limname)) { - if (res) - bferr("Ambiguous"); - res = lp; - } - if (res) - return (res); - bferr("No such limit"); + register struct limits *lp, *res; + + res = (struct limits *) NULL; + for (lp = limits; lp->limconst >= 0; lp++) + if (prefix(cp, str2short(lp->limname))) { + if (res) + stderror(ERR_NAME | ERR_AMBIG); + res = lp; + } + if (res) + return (res); + stderror(ERR_NAME | ERR_LIMIT); + /* NOTREACHED */ + return (0); } -dolimit(v) - register char **v; +void +/*ARGSUSED*/ +dolimit(v, t) + Char **v; + struct command *t; { - register struct limits *lp; - register int limit; + register struct limits *lp; + register RLIM_TYPE limit; + char hard = 0; + v++; + if (*v && eq(*v, STRmh)) { + hard = 1; v++; - if (*v == 0) { - for (lp = limits+1; lp->limconst >= 0; lp++) - plim(lp); - return; - } - lp = findlim(v[0]); - if (v[1] == 0) { - plim(lp); - return; - } - limit = getval(lp, v+1); - setlim(lp, limit); + } + if (*v == 0) { + for (lp = limits; lp->limconst >= 0; lp++) + plim(lp, hard); + return; + } + lp = findlim(v[0]); + if (v[1] == 0) { + plim(lp, hard); + return; + } + limit = getval(lp, v + 1); + if (setlim(lp, hard, limit) < 0) + stderror(ERR_SILENT); } +static RLIM_TYPE getval(lp, v) - register struct limits *lp; - char **v; + register struct limits *lp; + Char **v; { - register float f; - double atof(); - char *cp = *v++; - - f = atof(cp); - while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') - cp++; - if (*cp == 0) { - if (*v == 0) - return ((int)(f+0.5) * lp->limdiv); - cp = *v; - } - switch (*cp) { - - case ':': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - return ((int)(f * 60.0 + atof(cp+1))); - - case 'h': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - limtail(cp, "hours"); - f *= 3600.; - break; + register float f; + double atof(); + Char *cp = *v++; - case 'm': - if (lp->limconst == RLIMIT_CPU) { - limtail(cp, "minutes"); - f *= 60.; - break; - } - case 'M': - if (lp->limconst == RLIMIT_CPU) - goto badscal; - *cp = 'm'; - limtail(cp, "megabytes"); - f *= 1024.*1024.; - break; - - case 's': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - limtail(cp, "seconds"); - break; + f = atof(short2str(cp)); - case 'k': - if (lp->limconst == RLIMIT_CPU) - goto badscal; - limtail(cp, "kbytes"); - f *= 1024; - break; - - case 'u': - limtail(cp, "unlimited"); - return (RLIM_INFINITY); - - default: -badscal: - bferr("Improper or unknown scale factor"); + while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') + cp++; + if (*cp == 0) { + if (*v == 0) + return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv)); + cp = *v; + } + switch (*cp) { + case ':': + if (lp->limconst != RLIMIT_CPU) + goto badscal; + return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1)))); + case 'h': + if (lp->limconst != RLIMIT_CPU) + goto badscal; + limtail(cp, "hours"); + f *= 3600.0; + break; + case 'm': + if (lp->limconst == RLIMIT_CPU) { + limtail(cp, "minutes"); + f *= 60.0; + break; } - return ((int)(f+0.5)); + *cp = 'm'; + limtail(cp, "megabytes"); + f *= 1024.0 * 1024.0; + break; + case 's': + if (lp->limconst != RLIMIT_CPU) + goto badscal; + limtail(cp, "seconds"); + break; + case 'M': + if (lp->limconst == RLIMIT_CPU) + goto badscal; + *cp = 'm'; + limtail(cp, "megabytes"); + f *= 1024.0 * 1024.0; + break; + case 'k': + if (lp->limconst == RLIMIT_CPU) + goto badscal; + limtail(cp, "kbytes"); + f *= 1024.0; + break; + case 'u': + limtail(cp, "unlimited"); + return (RLIM_INFINITY); + default: +badscal: + stderror(ERR_NAME | ERR_SCALEF); + } + if ((f + 0.5) >= (float) 0x7fffffff || (f + 0.5) < (float) 0x80000000) + stderror(ERR_NAME | ERR_SCALEF); + return ((RLIM_TYPE) (f + 0.5)); } -limtail(cp, str0) - char *cp, *str0; +static void +limtail(cp, str) + Char *cp; + char *str; { - register char *str = str0; - - while (*cp && *cp == *str) - cp++, str++; - if (*cp) - error("Bad scaling; did you mean ``%s''?", str0); + while (*cp && *cp == *str) + cp++, str++; + if (*cp) + stderror(ERR_BADSCALE, str); } -plim(lp) - register struct limits *lp; + +/*ARGSUSED*/ +static void +plim(lp, hard) + register struct limits *lp; + Char hard; { - struct rlimit rlim; - - printf("%s \t", lp->limname); - getrlimit(lp->limconst, &rlim); - if (rlim.rlim_cur == RLIM_INFINITY) - printf("unlimited"); - else if (lp->limconst == RLIMIT_CPU) - psecs((long)rlim.rlim_cur); - else - printf("%d %s", rlim.rlim_cur / lp->limdiv, lp->limscale); - printf("\n"); + struct rlimit rlim; + RLIM_TYPE limit; + + (void) fprintf(cshout, "%s \t", lp->limname); + + (void) getrlimit(lp->limconst, &rlim); + limit = hard ? rlim.rlim_max : rlim.rlim_cur; + + if (limit == RLIM_INFINITY) + (void) fprintf(cshout, "unlimited"); + else if (lp->limconst == RLIMIT_CPU) + psecs((long) limit); + else + (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), + lp->limscale); + (void) fputc('\n', cshout); } -dounlimit(v) - register char **v; +void +/*ARGSUSED*/ +dounlimit(v, t) + Char **v; + struct command *t; { - register struct limits *lp; + register struct limits *lp; + int lerr = 0; + Char hard = 0; + v++; + if (*v && eq(*v, STRmh)) { + hard = 1; v++; - if (*v == 0) { - for (lp = limits+1; lp->limconst >= 0; lp++) - setlim(lp, RLIM_INFINITY); - return; - } - while (*v) { - lp = findlim(*v++); - setlim(lp, RLIM_INFINITY); - } + } + if (*v == 0) { + for (lp = limits; lp->limconst >= 0; lp++) + if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) + lerr++; + if (lerr) + stderror(ERR_SILENT); + return; + } + while (*v) { + lp = findlim(*v++); + if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) + stderror(ERR_SILENT); + } } -setlim(lp, limit) - register struct limits *lp; +static int +setlim(lp, hard, limit) + register struct limits *lp; + Char hard; + RLIM_TYPE limit; { - struct rlimit rlim; + struct rlimit rlim; + + (void) getrlimit(lp->limconst, &rlim); - getrlimit(lp->limconst, &rlim); + if (hard) + rlim.rlim_max = limit; + else if (limit == RLIM_INFINITY && geteuid() != 0) + rlim.rlim_cur = rlim.rlim_max; + else rlim.rlim_cur = limit; - if (setrlimit(lp->limconst, &rlim) < 0) - Perror(bname); + + if (setrlimit(lp->limconst, &rlim) < 0) { + (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, + limit == RLIM_INFINITY ? "remove" : "set", + hard ? " hard" : ""); + return (-1); + } + return (0); } -dosuspend() +void +/*ARGSUSED*/ +dosuspend(v, t) + Char **v; + struct command *t; { - int (*old)(), ldisc; - int ctpgrp; - - if (loginsh) - error("Can't suspend a login shell (yet)"); - untty(); - old = sigsys(SIGTSTP, SIG_DFL); - kill(0, SIGTSTP); - /* the shell stops here */ - sigsys(SIGTSTP, old); - if (tpgrp != -1) { -retry: - ioctl(FSHTTY, TIOCGPGRP, &ctpgrp); - if (ctpgrp != opgrp) { - old = sigsys(SIGTTIN, SIG_DFL); - kill(0, SIGTTIN); - sigsys(SIGTTIN, old); - goto retry; - } - ioctl(FSHTTY, TIOCSPGRP, &shpgrp); - setpgrp(0, shpgrp); - } - ioctl(FSHTTY, TIOCGETD, &oldisc); - if (oldisc != NTTYDISC) { - printf("Switching to new tty driver...\n"); - ldisc = NTTYDISC; - ioctl(FSHTTY, TIOCSETD, &ldisc); + int ctpgrp; + + void (*old) (); + + if (loginsh) + stderror(ERR_SUSPLOG); + untty(); + + old = signal(SIGTSTP, SIG_DFL); + (void) kill(0, SIGTSTP); + /* the shell stops here */ + (void) signal(SIGTSTP, old); + + if (tpgrp != -1) { + ctpgrp = tcgetpgrp(FSHTTY); + while (ctpgrp != opgrp) { + old = signal(SIGTTIN, SIG_DFL); + (void) kill(0, SIGTTIN); + (void) signal(SIGTTIN, old); } + (void) setpgid(0, shpgrp); + (void) tcsetpgrp(FSHTTY, shpgrp); + } } -doeval(v) - char **v; +/* This is the dreaded EVAL built-in. + * If you don't fiddle with file descriptors, and reset didfds, + * this command will either ignore redirection inside or outside + * its aguments, e.g. eval "date >x" vs. eval "date" >x + * The stuff here seems to work, but I did it by trial and error rather + * than really knowing what was going on. If tpgrp is zero, we are + * probably a background eval, e.g. "eval date &", and we want to + * make sure that any processes we start stay in our pgrp. + * This is also the case for "time eval date" -- stay in same pgrp. + * Otherwise, under stty tostop, processes will stop in the wrong + * pgrp, with no way for the shell to get them going again. -IAN! + */ +static Char **gv = NULL; +void +/*ARGSUSED*/ +doeval(v, t) + Char **v; + struct command *t; { - char **oevalvec = evalvec; - char *oevalp = evalp; - jmp_buf osetexit; - int reenter; - char **gv = 0; + Char **oevalvec; + Char *oevalp; + int odidfds; + jmp_buf osetexit; + int my_reenter; + Char **savegv = gv; + int saveIN; + int saveOUT; + int saveERR; + int oSHIN; + int oSHOUT; + int oSHERR; + + oevalvec = evalvec; + oevalp = evalp; + odidfds = didfds; + oSHIN = SHIN; + oSHOUT = SHOUT; + oSHERR = SHERR; + + v++; + if (*v == 0) + return; + gflag = 0, tglob(v); + if (gflag) { + gv = v = globall(v); + gargv = 0; + if (v == 0) + stderror(ERR_NOMATCH); + v = copyblk(v); + } + else { + gv = NULL; + v = copyblk(v); + trim(v); + } + + saveIN = dcopy(SHIN, -1); + saveOUT = dcopy(SHOUT, -1); + saveERR = dcopy(SHERR, -1); + + getexit(osetexit); + + if ((my_reenter = setexit()) == 0) { + evalvec = v; + evalp = 0; + SHIN = dcopy(0, -1); + SHOUT = dcopy(1, -1); + SHERR = dcopy(2, -1); + didfds = 0; + process(0); + } + + evalvec = oevalvec; + evalp = oevalp; + doneinp = 0; + didfds = odidfds; + (void) close(SHIN); + (void) close(SHOUT); + (void) close(SHERR); + SHIN = dmove(saveIN, oSHIN); + SHOUT = dmove(saveOUT, oSHOUT); + SHERR = dmove(saveERR, oSHERR); + if (gv) + blkfree(gv), gv = NULL; + resexit(osetexit); + gv = savegv; + if (my_reenter) + stderror(ERR_SILENT); +} - v++; - if (*v == 0) - return; - gflag = 0; rscan(v, tglob); - if (gflag) { - gv = v = glob(v); - gargv = 0; - if (v == 0) - error("No match"); - v = copyblk(v); - } else - scan(v, trim); - getexit(osetexit); - reenter = 0; - setexit(); - reenter++; - if (reenter == 1) { - evalvec = v; - evalp = 0; - process(0); - } - evalvec = oevalvec; - evalp = oevalp; - doneinp = 0; - if (gv) - blkfree(gv); - resexit(osetexit); - if (reenter >= 2) - error(NOSTR); +void +/*ARGSUSED*/ +doprintf(v, t) + Char **v; + struct command *t; +{ + char **c; + extern int progprintf __P((int, char **)); + int ret; + + ret = progprintf(blklen(v), c = short2blk(v)); + + blkfree((Char **) c); + if (ret) + stderror(ERR_SILENT); } +