147823Sbostic /*- 247823Sbostic * Copyright (c) 1980, 1991 The Regents of the University of California. 347823Sbostic * All rights reserved. 447823Sbostic * 547823Sbostic * %sccs.include.redist.c% 621933Sdist */ 721933Sdist 817519Sedward #ifndef lint 9*50639Schristos static char sccsid[] = "@(#)func.c 5.22 (Berkeley) 07/28/91"; 1047413Sbostic #endif /* not lint */ 111294Sbill 1250028Sbostic #include <sys/types.h> 1350028Sbostic #include <sys/stat.h> 1450028Sbostic #include <signal.h> 1550028Sbostic #include <locale.h> 1650028Sbostic #include <stdlib.h> 1750028Sbostic #include <string.h> 1850028Sbostic #include <unistd.h> 1950033Schristos #if __STDC__ 2050033Schristos # include <stdarg.h> 2150033Schristos #else 2250033Schristos # include <varargs.h> 2350033Schristos #endif 2450033Schristos 2550023Sbostic #include "csh.h" 2650023Sbostic #include "extern.h" 2750028Sbostic #include "pathnames.h" 281294Sbill 2949992Sbostic extern char **environ; 301294Sbill 3149992Sbostic static int zlast = -1; 3250024Schristos static void islogin __P((void)); 3350024Schristos static void reexecute __P((struct command *)); 3450024Schristos static void preread __P((void)); 3550024Schristos static void doagain __P((void)); 3650024Schristos static int getword __P((Char *)); 3750024Schristos static int keyword __P((Char *)); 3850024Schristos static void Unsetenv __P((Char *)); 3950024Schristos static void toend __P((void)); 4050024Schristos static void xecho __P((int, Char **)); 4149992Sbostic 421294Sbill struct biltins * 431294Sbill isbfunc(t) 4449992Sbostic struct command *t; 451294Sbill { 4649992Sbostic register Char *cp = t->t_dcom[0]; 4749992Sbostic register struct biltins *bp, *bp1, *bp2; 4849992Sbostic static struct biltins label = {"", dozip, 0, 0}; 4949992Sbostic static struct biltins foregnd = {"%job", dofg1, 0, 0}; 5049992Sbostic static struct biltins backgnd = {"%job &", dobg1, 0, 0}; 511294Sbill 5249992Sbostic if (lastchr(cp) == ':') { 5349992Sbostic label.bname = short2str(cp); 5449992Sbostic return (&label); 5549992Sbostic } 5649992Sbostic if (*cp == '%') { 5749992Sbostic if (t->t_dflg & F_AMPERSAND) { 5849992Sbostic t->t_dflg &= ~F_AMPERSAND; 5949992Sbostic backgnd.bname = short2str(cp); 6049992Sbostic return (&backgnd); 611294Sbill } 6249992Sbostic foregnd.bname = short2str(cp); 6349992Sbostic return (&foregnd); 6449992Sbostic } 6549992Sbostic /* 6649992Sbostic * Binary search Bp1 is the beginning of the current search range. Bp2 is 6749992Sbostic * one past the end. 6849992Sbostic */ 6949992Sbostic for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 7049992Sbostic register i; 7117519Sedward 7249992Sbostic bp = bp1 + ((bp2 - bp1) >> 1); 7349992Sbostic if ((i = *cp - *bp->bname) == 0 && 7449992Sbostic (i = Strcmp(cp, str2short(bp->bname))) == 0) 7549992Sbostic return bp; 7649992Sbostic if (i < 0) 7749992Sbostic bp2 = bp; 7849992Sbostic else 7949992Sbostic bp1 = bp + 1; 8049992Sbostic } 8149992Sbostic return (0); 821294Sbill } 831294Sbill 8449992Sbostic void 851294Sbill func(t, bp) 8649992Sbostic register struct command *t; 8749992Sbostic register struct biltins *bp; 881294Sbill { 8949992Sbostic int i; 901294Sbill 9149992Sbostic xechoit(t->t_dcom); 9249992Sbostic setname(bp->bname); 9349992Sbostic i = blklen(t->t_dcom) - 1; 9449992Sbostic if (i < bp->minargs) 9549992Sbostic stderror(ERR_NAME | ERR_TOOFEW); 9649992Sbostic if (i > bp->maxargs) 9749992Sbostic stderror(ERR_NAME | ERR_TOOMANY); 9849992Sbostic (*bp->bfunct) (t->t_dcom, t); 991294Sbill } 1001294Sbill 10149992Sbostic void 10250439Schristos /*ARGSUSED*/ 10350439Schristos doonintr(v, t) 10450439Schristos Char **v; 10550439Schristos struct command *t; 1061294Sbill { 10749992Sbostic register Char *cp; 10849992Sbostic register Char *vv = v[1]; 1091294Sbill 11049992Sbostic if (parintr == SIG_IGN) 11149992Sbostic return; 11249992Sbostic if (setintr && intty) 11349992Sbostic stderror(ERR_NAME | ERR_TERMINAL); 11449992Sbostic cp = gointr; 11549992Sbostic gointr = 0; 11649992Sbostic xfree((ptr_t) cp); 11749992Sbostic if (vv == 0) { 11849992Sbostic if (setintr) 11949992Sbostic (void) sigblock(sigmask(SIGINT)); 12049992Sbostic else 12149992Sbostic (void) signal(SIGINT, SIG_DFL); 12249992Sbostic gointr = 0; 12349992Sbostic } 12449992Sbostic else if (eq((vv = strip(vv)), STRminus)) { 12549992Sbostic (void) signal(SIGINT, SIG_IGN); 12649992Sbostic gointr = Strsave(STRminus); 12749992Sbostic } 12849992Sbostic else { 12949992Sbostic gointr = Strsave(vv); 13049992Sbostic (void) signal(SIGINT, pintr); 13149992Sbostic } 1321294Sbill } 1331294Sbill 13449992Sbostic void 13550439Schristos /*ARGSUSED*/ 13650439Schristos donohup(v, t) 13750439Schristos Char **v; 13850439Schristos struct command *t; 1391294Sbill { 14049992Sbostic if (intty) 14149992Sbostic stderror(ERR_NAME | ERR_TERMINAL); 14249992Sbostic if (setintr == 0) { 14349992Sbostic (void) signal(SIGHUP, SIG_IGN); 14449992Sbostic } 1451294Sbill } 1461294Sbill 14749992Sbostic void 14850439Schristos /*ARGSUSED*/ 14950439Schristos dozip(v, t) 15050439Schristos Char **v; 15150439Schristos struct command *t; 1521294Sbill { 15349992Sbostic ; 1541294Sbill } 1551294Sbill 15649992Sbostic void 1571294Sbill prvars() 1581294Sbill { 15949992Sbostic plist(&shvhed); 1601294Sbill } 1611294Sbill 16249992Sbostic void 16350439Schristos /*ARGSUSED*/ 16450439Schristos doalias(v, t) 16550439Schristos Char **v; 16650439Schristos struct command *t; 1671294Sbill { 16849992Sbostic register struct varent *vp; 16949992Sbostic register Char *p; 1701294Sbill 17149992Sbostic v++; 17249992Sbostic p = *v++; 17349992Sbostic if (p == 0) 17449992Sbostic plist(&aliases); 17549992Sbostic else if (*v == 0) { 17649992Sbostic vp = adrof1(strip(p), &aliases); 17750439Schristos if (vp) { 17850439Schristos blkpr(cshout, vp->vec); 17950439Schristos fputc('\n', cshout); 18050439Schristos } 18149992Sbostic } 18249992Sbostic else { 18349992Sbostic if (eq(p, STRalias) || eq(p, STRunalias)) { 18449992Sbostic setname(short2str(p)); 18549992Sbostic stderror(ERR_NAME | ERR_DANGER); 1861294Sbill } 18749992Sbostic set1(strip(p), saveblk(v), &aliases); 18849992Sbostic } 1891294Sbill } 1901294Sbill 19149992Sbostic void 19250439Schristos /*ARGSUSED*/ 19350439Schristos unalias(v, t) 19450439Schristos Char **v; 19550439Schristos struct command *t; 1961294Sbill { 19749992Sbostic unset1(v, &aliases); 1981294Sbill } 1991294Sbill 20049992Sbostic void 20150439Schristos /*ARGSUSED*/ 20250439Schristos dologout(v, t) 20350439Schristos Char **v; 20450439Schristos struct command *t; 2051294Sbill { 20649992Sbostic islogin(); 20749992Sbostic goodbye(); 2081294Sbill } 2091294Sbill 21049992Sbostic void 21150439Schristos /*ARGSUSED*/ 21250439Schristos dologin(v, t) 21350439Schristos Char **v; 21450439Schristos struct command *t; 2151294Sbill { 21649992Sbostic islogin(); 21749992Sbostic rechist(); 21849992Sbostic (void) signal(SIGTERM, parterm); 21950024Schristos (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); 22049992Sbostic untty(); 22149992Sbostic xexit(1); 2221294Sbill } 2231294Sbill 22449992Sbostic static void 2251294Sbill islogin() 2261294Sbill { 22749992Sbostic if (chkstop == 0 && setintr) 22849992Sbostic panystop(0); 22949992Sbostic if (loginsh) 23049992Sbostic return; 23149992Sbostic stderror(ERR_NOTLOGIN); 2321294Sbill } 2331294Sbill 23449992Sbostic void 2351294Sbill doif(v, kp) 23649992Sbostic Char **v; 23749992Sbostic struct command *kp; 2381294Sbill { 23949992Sbostic register int i; 24049992Sbostic register Char **vv; 2411294Sbill 24249992Sbostic v++; 24349992Sbostic i = exp(&v); 24449992Sbostic vv = v; 24549992Sbostic if (*vv == NULL) 24649992Sbostic stderror(ERR_NAME | ERR_EMPTYIF); 24749992Sbostic if (eq(*vv, STRthen)) { 24849992Sbostic if (*++vv) 24949992Sbostic stderror(ERR_NAME | ERR_IMPRTHEN); 25049992Sbostic setname(short2str(STRthen)); 2511294Sbill /* 25249992Sbostic * If expression was zero, then scan to else, otherwise just fall into 25349992Sbostic * following code. 2541294Sbill */ 25549992Sbostic if (!i) 25650024Schristos search(T_IF, 0, NULL); 25749992Sbostic return; 25849992Sbostic } 25949992Sbostic /* 26049992Sbostic * Simple command attached to this if. Left shift the node in this tree, 26149992Sbostic * munging it so we can reexecute it. 26249992Sbostic */ 26349992Sbostic if (i) { 26449992Sbostic lshift(kp->t_dcom, vv - kp->t_dcom); 26549992Sbostic reexecute(kp); 26649992Sbostic donefds(); 26749992Sbostic } 2681294Sbill } 2691294Sbill 2701294Sbill /* 2711294Sbill * Reexecute a command, being careful not 2721294Sbill * to redo i/o redirection, which is already set up. 2731294Sbill */ 27449992Sbostic static void 2751294Sbill reexecute(kp) 27649992Sbostic register struct command *kp; 2771294Sbill { 27849992Sbostic kp->t_dflg &= F_SAVE; 27949992Sbostic kp->t_dflg |= F_REPEAT; 28049992Sbostic /* 28149992Sbostic * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set 28249992Sbostic * pgrp's as the jobs would then have no way to get the tty (we can't give 28349992Sbostic * it to them, and our parent wouldn't know their pgrp, etc. 28449992Sbostic */ 28550023Sbostic execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); 2861294Sbill } 2871294Sbill 28849992Sbostic void 28950439Schristos /*ARGSUSED*/ 29050439Schristos doelse(v, t) 29150439Schristos Char **v; 29250439Schristos struct command *t; 2931294Sbill { 29450024Schristos search(T_ELSE, 0, NULL); 2951294Sbill } 2961294Sbill 29749992Sbostic void 29850439Schristos /*ARGSUSED*/ 29950439Schristos dogoto(v, t) 30050439Schristos Char **v; 30150439Schristos struct command *t; 3021294Sbill { 30349992Sbostic register struct whyle *wp; 30449992Sbostic Char *lp; 3051294Sbill 30649992Sbostic /* 30749992Sbostic * While we still can, locate any unknown ends of existing loops. This 30849992Sbostic * obscure code is the WORST result of the fact that we don't really parse. 30949992Sbostic */ 31049992Sbostic zlast = T_GOTO; 31149992Sbostic for (wp = whyles; wp; wp = wp->w_next) 31249992Sbostic if (wp->w_end == 0) { 31350024Schristos search(T_BREAK, 0, NULL); 31450023Sbostic wp->w_end = fseekp; 31549992Sbostic } 31649992Sbostic else 31749992Sbostic bseek(wp->w_end); 31849992Sbostic search(T_GOTO, 0, lp = globone(v[1], G_ERROR)); 31949992Sbostic xfree((ptr_t) lp); 32049992Sbostic /* 32149992Sbostic * Eliminate loops which were exited. 32249992Sbostic */ 32349992Sbostic wfree(); 3241294Sbill } 3251294Sbill 32649992Sbostic void 32750439Schristos /*ARGSUSED*/ 32850439Schristos doswitch(v, t) 32950439Schristos Char **v; 33050439Schristos struct command *t; 3311294Sbill { 33249992Sbostic register Char *cp, *lp; 3331294Sbill 33449992Sbostic v++; 33549992Sbostic if (!*v || *(*v++) != '(') 33649992Sbostic stderror(ERR_SYNTAX); 33749992Sbostic cp = **v == ')' ? STRNULL : *v++; 33849992Sbostic if (*(*v++) != ')') 33949992Sbostic v--; 34049992Sbostic if (*v) 34149992Sbostic stderror(ERR_SYNTAX); 34249992Sbostic search(T_SWITCH, 0, lp = globone(cp, G_ERROR)); 34349992Sbostic xfree((ptr_t) lp); 3441294Sbill } 3451294Sbill 34649992Sbostic void 34750439Schristos /*ARGSUSED*/ 34850439Schristos dobreak(v, t) 34950439Schristos Char **v; 35050439Schristos struct command *t; 3511294Sbill { 35249992Sbostic if (whyles) 35349992Sbostic toend(); 35449992Sbostic else 35549992Sbostic stderror(ERR_NAME | ERR_NOTWHILE); 3561294Sbill } 3571294Sbill 35849992Sbostic void 35950439Schristos /*ARGSUSED*/ 36050439Schristos doexit(v, t) 36150439Schristos Char **v; 36250439Schristos struct command *t; 3631294Sbill { 36449992Sbostic if (chkstop == 0 && (intty || intact) && evalvec == 0) 36549992Sbostic panystop(0); 36649992Sbostic /* 36749992Sbostic * Don't DEMAND parentheses here either. 36849992Sbostic */ 36949992Sbostic v++; 37049992Sbostic if (*v) { 37149992Sbostic set(STRstatus, putn(exp(&v))); 37249992Sbostic if (*v) 37349992Sbostic stderror(ERR_NAME | ERR_EXPRESSION); 37449992Sbostic } 37549992Sbostic btoeof(); 37649992Sbostic if (intty) 37749992Sbostic (void) close(SHIN); 3781294Sbill } 3791294Sbill 38049992Sbostic void 38150439Schristos /*ARGSUSED*/ 38250439Schristos doforeach(v, t) 38350439Schristos Char **v; 38450439Schristos struct command *t; 3851294Sbill { 38649992Sbostic register Char *cp, *sp; 38749992Sbostic register struct whyle *nwp; 3881294Sbill 38949992Sbostic v++; 39049992Sbostic sp = cp = strip(*v); 39149992Sbostic if (!letter(*sp)) 39249992Sbostic stderror(ERR_NAME | ERR_VARBEGIN); 39349992Sbostic while (*cp && alnum(*cp)) 39449992Sbostic cp++; 39549992Sbostic if (*cp) 39649992Sbostic stderror(ERR_NAME | ERR_VARALNUM); 39749992Sbostic if ((cp - sp) > MAXVARLEN) 39849992Sbostic stderror(ERR_NAME | ERR_VARTOOLONG); 39949992Sbostic cp = *v++; 40049992Sbostic if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 40149992Sbostic stderror(ERR_NAME | ERR_NOPAREN); 40249992Sbostic v++; 40349992Sbostic gflag = 0, tglob(v); 40449992Sbostic v = globall(v); 40549992Sbostic if (v == 0) 40649992Sbostic stderror(ERR_NAME | ERR_NOMATCH); 40749992Sbostic nwp = (struct whyle *) xcalloc(1, sizeof *nwp); 40849992Sbostic nwp->w_fe = nwp->w_fe0 = v; 40949992Sbostic gargv = 0; 41050023Sbostic nwp->w_start = fseekp; 41149992Sbostic nwp->w_fename = Strsave(cp); 41249992Sbostic nwp->w_next = whyles; 41349992Sbostic whyles = nwp; 41449992Sbostic /* 41549992Sbostic * Pre-read the loop so as to be more comprehensible to a terminal user. 41649992Sbostic */ 41749992Sbostic zlast = T_FOREACH; 41849992Sbostic if (intty) 41949992Sbostic preread(); 42049992Sbostic doagain(); 4211294Sbill } 4221294Sbill 42349992Sbostic void 42450439Schristos /*ARGSUSED*/ 42550439Schristos dowhile(v, t) 42650439Schristos Char **v; 42750439Schristos struct command *t; 4281294Sbill { 42949992Sbostic register int status; 43049992Sbostic register bool again = whyles != 0 && whyles->w_start == lineloc && 43149992Sbostic whyles->w_fename == 0; 4321294Sbill 43349992Sbostic v++; 43449992Sbostic /* 43549992Sbostic * Implement prereading here also, taking care not to evaluate the 43649992Sbostic * expression before the loop has been read up from a terminal. 43749992Sbostic */ 43849992Sbostic if (intty && !again) 43949992Sbostic status = !exp0(&v, 1); 44049992Sbostic else 44149992Sbostic status = !exp(&v); 44249992Sbostic if (*v) 44349992Sbostic stderror(ERR_NAME | ERR_EXPRESSION); 44449992Sbostic if (!again) { 44549992Sbostic register struct whyle *nwp = 44649992Sbostic (struct whyle *) xcalloc(1, sizeof(*nwp)); 4471294Sbill 44849992Sbostic nwp->w_start = lineloc; 44949992Sbostic nwp->w_end = 0; 45049992Sbostic nwp->w_next = whyles; 45149992Sbostic whyles = nwp; 45249992Sbostic zlast = T_WHILE; 45349992Sbostic if (intty) { 45449992Sbostic /* 45549992Sbostic * The tty preread 45649992Sbostic */ 45749992Sbostic preread(); 45849992Sbostic doagain(); 45949992Sbostic return; 4601294Sbill } 46149992Sbostic } 46249992Sbostic if (status) 46349992Sbostic /* We ain't gonna loop no more, no more! */ 46449992Sbostic toend(); 4651294Sbill } 4661294Sbill 46749992Sbostic static void 4681294Sbill preread() 4691294Sbill { 47049992Sbostic whyles->w_end = -1; 47149992Sbostic if (setintr) 47250028Sbostic (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 4731294Sbill 47450024Schristos search(T_BREAK, 0, NULL); /* read the expression in */ 47549992Sbostic if (setintr) 47649992Sbostic (void) sigblock(sigmask(SIGINT)); 47750023Sbostic whyles->w_end = fseekp; 4781294Sbill } 4791294Sbill 48049992Sbostic void 48150439Schristos /*ARGSUSED*/ 48250439Schristos doend(v, t) 48350439Schristos Char **v; 48450439Schristos struct command *t; 4851294Sbill { 48649992Sbostic if (!whyles) 48749992Sbostic stderror(ERR_NAME | ERR_NOTWHILE); 48850023Sbostic whyles->w_end = fseekp; 48949992Sbostic doagain(); 4901294Sbill } 4911294Sbill 49249992Sbostic void 49350439Schristos /*ARGSUSED*/ 49450439Schristos docontin(v, t) 49550439Schristos Char **v; 49650439Schristos struct command *t; 4971294Sbill { 49849992Sbostic if (!whyles) 49949992Sbostic stderror(ERR_NAME | ERR_NOTWHILE); 50049992Sbostic doagain(); 5011294Sbill } 5021294Sbill 50349992Sbostic static void 5041294Sbill doagain() 5051294Sbill { 50649992Sbostic /* Repeating a while is simple */ 50749992Sbostic if (whyles->w_fename == 0) { 5081294Sbill bseek(whyles->w_start); 50949992Sbostic return; 51049992Sbostic } 51149992Sbostic /* 51249992Sbostic * The foreach variable list actually has a spurious word ")" at the end of 51349992Sbostic * the w_fe list. Thus we are at the of the list if one word beyond this 51449992Sbostic * is 0. 51549992Sbostic */ 51649992Sbostic if (!whyles->w_fe[1]) { 51750439Schristos dobreak(NULL, NULL); 51849992Sbostic return; 51949992Sbostic } 52049992Sbostic set(whyles->w_fename, Strsave(*whyles->w_fe++)); 52149992Sbostic bseek(whyles->w_start); 5221294Sbill } 5231294Sbill 52449992Sbostic void 5251294Sbill dorepeat(v, kp) 52649992Sbostic Char **v; 52749992Sbostic struct command *kp; 5281294Sbill { 52949992Sbostic register int i; 53050028Sbostic register sigset_t omask = 0; 5311294Sbill 53249992Sbostic i = getn(v[1]); 53349992Sbostic if (setintr) 53449992Sbostic omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 53549992Sbostic lshift(v, 2); 53649992Sbostic while (i > 0) { 5371294Sbill if (setintr) 53849992Sbostic (void) sigsetmask(omask); 53949992Sbostic reexecute(kp); 54049992Sbostic --i; 54149992Sbostic } 54249992Sbostic donefds(); 54349992Sbostic if (setintr) 54449992Sbostic (void) sigsetmask(omask); 5451294Sbill } 5461294Sbill 54749992Sbostic void 54850439Schristos /*ARGSUSED*/ 54950439Schristos doswbrk(v, t) 55050439Schristos Char **v; 55150439Schristos struct command *t; 5521294Sbill { 55350024Schristos search(T_BRKSW, 0, NULL); 5541294Sbill } 5551294Sbill 55649992Sbostic int 5571294Sbill srchx(cp) 55849992Sbostic register Char *cp; 5591294Sbill { 56049992Sbostic register struct srch *sp, *sp1, *sp2; 56149992Sbostic register i; 5621294Sbill 56349992Sbostic /* 56449992Sbostic * Binary search Sp1 is the beginning of the current search range. Sp2 is 56549992Sbostic * one past the end. 56649992Sbostic */ 56749992Sbostic for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 56849992Sbostic sp = sp1 + ((sp2 - sp1) >> 1); 56949992Sbostic if ((i = *cp - *sp->s_name) == 0 && 57049992Sbostic (i = Strcmp(cp, str2short(sp->s_name))) == 0) 57149992Sbostic return sp->s_value; 57249992Sbostic if (i < 0) 57349992Sbostic sp2 = sp; 57449992Sbostic else 57549992Sbostic sp1 = sp + 1; 57649992Sbostic } 57749992Sbostic return (-1); 5781294Sbill } 5791294Sbill 58049992Sbostic static Char Stype; 58149992Sbostic static Char *Sgoal; 5821294Sbill 5831294Sbill /*VARARGS2*/ 58449992Sbostic void 5851294Sbill search(type, level, goal) 58649992Sbostic int type; 58749992Sbostic register int level; 58849992Sbostic Char *goal; 5891294Sbill { 59049992Sbostic Char wordbuf[BUFSIZ]; 59149992Sbostic register Char *aword = wordbuf; 59249992Sbostic register Char *cp; 5931294Sbill 59449992Sbostic Stype = type; 59549992Sbostic Sgoal = goal; 59649992Sbostic if (type == T_GOTO) 59749992Sbostic bseek((off_t) 0); 59849992Sbostic do { 59949992Sbostic if (intty && fseekp == feobp) 60050439Schristos (void) fprintf(cshout, "? "), (void) fflush(cshout); 60149992Sbostic aword[0] = 0; 60249992Sbostic (void) getword(aword); 60349992Sbostic switch (srchx(aword)) { 6041294Sbill 60549992Sbostic case T_ELSE: 60649992Sbostic if (level == 0 && type == T_IF) 60749992Sbostic return; 60849992Sbostic break; 6091294Sbill 61049992Sbostic case T_IF: 61149992Sbostic while (getword(aword)) 61249992Sbostic continue; 61349992Sbostic if ((type == T_IF || type == T_ELSE) && 61449992Sbostic eq(aword, STRthen)) 61549992Sbostic level++; 61649992Sbostic break; 6171294Sbill 61849992Sbostic case T_ENDIF: 61949992Sbostic if (type == T_IF || type == T_ELSE) 62049992Sbostic level--; 62149992Sbostic break; 6221294Sbill 62349992Sbostic case T_FOREACH: 62449992Sbostic case T_WHILE: 62549992Sbostic if (type == T_BREAK) 62649992Sbostic level++; 62749992Sbostic break; 6281294Sbill 62949992Sbostic case T_END: 63049992Sbostic if (type == T_BREAK) 63149992Sbostic level--; 63249992Sbostic break; 6331294Sbill 63449992Sbostic case T_SWITCH: 63549992Sbostic if (type == T_SWITCH || type == T_BRKSW) 63649992Sbostic level++; 63749992Sbostic break; 6381294Sbill 63949992Sbostic case T_ENDSW: 64049992Sbostic if (type == T_SWITCH || type == T_BRKSW) 64149992Sbostic level--; 64249992Sbostic break; 6431294Sbill 64449992Sbostic case T_LABEL: 64549992Sbostic if (type == T_GOTO && getword(aword) && eq(aword, goal)) 64649992Sbostic level = -1; 64749992Sbostic break; 6481294Sbill 64949992Sbostic default: 65049992Sbostic if (type != T_GOTO && (type != T_SWITCH || level != 0)) 65149992Sbostic break; 65249992Sbostic if (lastchr(aword) != ':') 65349992Sbostic break; 65449992Sbostic aword[Strlen(aword) - 1] = 0; 65549992Sbostic if (type == T_GOTO && eq(aword, goal) || 65649992Sbostic type == T_SWITCH && eq(aword, STRdefault)) 65749992Sbostic level = -1; 65849992Sbostic break; 6591294Sbill 66049992Sbostic case T_CASE: 66149992Sbostic if (type != T_SWITCH || level != 0) 66249992Sbostic break; 66349992Sbostic (void) getword(aword); 66449992Sbostic if (lastchr(aword) == ':') 66549992Sbostic aword[Strlen(aword) - 1] = 0; 66649992Sbostic cp = strip(Dfix1(aword)); 66749992Sbostic if (Gmatch(goal, cp)) 66849992Sbostic level = -1; 66949992Sbostic xfree((ptr_t) cp); 67049992Sbostic break; 6711294Sbill 67249992Sbostic case T_DEFAULT: 67349992Sbostic if (type == T_SWITCH && level == 0) 67449992Sbostic level = -1; 67549992Sbostic break; 67649992Sbostic } 67749992Sbostic (void) getword(NULL); 67849992Sbostic } while (level >= 0); 6791294Sbill } 6801294Sbill 68149992Sbostic static int 6821294Sbill getword(wp) 68349992Sbostic register Char *wp; 6841294Sbill { 68549992Sbostic register int found = 0; 68649992Sbostic register int c, d; 68749992Sbostic int kwd = 0; 68849992Sbostic Char *owp = wp; 6891294Sbill 69049992Sbostic c = readc(1); 69149992Sbostic d = 0; 69249992Sbostic do { 69349992Sbostic while (c == ' ' || c == '\t') 69449992Sbostic c = readc(1); 69549992Sbostic if (c == '#') 69649992Sbostic do 69749992Sbostic c = readc(1); 69849992Sbostic while (c >= 0 && c != '\n'); 69949992Sbostic if (c < 0) 70049992Sbostic goto past; 70149992Sbostic if (c == '\n') { 70249992Sbostic if (wp) 70349992Sbostic break; 70449992Sbostic return (0); 70549992Sbostic } 70649992Sbostic unreadc(c); 70749992Sbostic found = 1; 7081294Sbill do { 70949992Sbostic c = readc(1); 71049992Sbostic if (c == '\\' && (c = readc(1)) == '\n') 71149992Sbostic c = ' '; 71249992Sbostic if (c == '\'' || c == '"') 71349992Sbostic if (d == 0) 71449992Sbostic d = c; 71549992Sbostic else if (d == c) 71649992Sbostic d = 0; 71749992Sbostic if (c < 0) 71849992Sbostic goto past; 71949992Sbostic if (wp) { 72049992Sbostic *wp++ = c; 72149992Sbostic *wp = 0; /* end the string b4 test */ 72249992Sbostic } 72349992Sbostic } while ((d || !(kwd = keyword(owp)) && c != ' ' 72449992Sbostic && c != '\t') && c != '\n'); 72549992Sbostic } while (wp == 0); 72649992Sbostic 72749992Sbostic /* 72849992Sbostic * if we have read a keyword ( "if", "switch" or "while" ) then we do not 72949992Sbostic * need to unreadc the look-ahead char 73049992Sbostic */ 73149992Sbostic if (!kwd) { 7321294Sbill unreadc(c); 7331294Sbill if (found) 73449992Sbostic *--wp = 0; 73549992Sbostic } 7361294Sbill 73749992Sbostic return (found); 73849992Sbostic 7391294Sbill past: 74049992Sbostic switch (Stype) { 7411294Sbill 74249992Sbostic case T_IF: 74349992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); 7441294Sbill 74549992Sbostic case T_ELSE: 74649992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "endif"); 7471294Sbill 74849992Sbostic case T_BRKSW: 74949992Sbostic case T_SWITCH: 75049992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); 7511294Sbill 75249992Sbostic case T_BREAK: 75349992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "end"); 7541294Sbill 75549992Sbostic case T_GOTO: 75649992Sbostic setname(short2str(Sgoal)); 75749992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "label"); 75849992Sbostic } 75949992Sbostic /* NOTREACHED */ 76049992Sbostic return (0); 7611294Sbill } 7621294Sbill 76349992Sbostic /* 76449992Sbostic * keyword(wp) determines if wp is one of the built-n functions if, 76549992Sbostic * switch or while. It seems that when an if statement looks like 76649992Sbostic * "if(" then getword above sucks in the '(' and so the search routine 76749992Sbostic * never finds what it is scanning for. Rather than rewrite doword, I hack 76849992Sbostic * in a test to see if the string forms a keyword. Then doword stops 76949992Sbostic * and returns the word "if" -strike 77049992Sbostic */ 77149992Sbostic 77249992Sbostic static int 77349992Sbostic keyword(wp) 77449992Sbostic Char *wp; 7751294Sbill { 77649992Sbostic static Char STRif[] = {'i', 'f', '\0'}; 77749992Sbostic static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; 77849992Sbostic static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; 7791294Sbill 78049992Sbostic if (!wp) 78149992Sbostic return (0); 78249992Sbostic 78349992Sbostic if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) 78449992Sbostic || (Strcmp(wp, STRswitch) == 0)) 78549992Sbostic return (1); 78649992Sbostic 78749992Sbostic return (0); 7881294Sbill } 7891294Sbill 79049992Sbostic static void 79149992Sbostic toend() 79249992Sbostic { 79349992Sbostic if (whyles->w_end == 0) { 79449992Sbostic search(T_BREAK, 0, NULL); 79550023Sbostic whyles->w_end = fseekp - 1; 79649992Sbostic } 79749992Sbostic else 79849992Sbostic bseek(whyles->w_end); 79949992Sbostic wfree(); 80049992Sbostic } 80149992Sbostic 80249992Sbostic void 8031294Sbill wfree() 8041294Sbill { 80550023Sbostic long o = fseekp; 8061294Sbill 80749992Sbostic while (whyles) { 80849992Sbostic register struct whyle *wp = whyles; 80949992Sbostic register struct whyle *nwp = wp->w_next; 8101294Sbill 81149992Sbostic if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) 81249992Sbostic break; 81349992Sbostic if (wp->w_fe0) 81449992Sbostic blkfree(wp->w_fe0); 81549992Sbostic if (wp->w_fename) 81649992Sbostic xfree((ptr_t) wp->w_fename); 81749992Sbostic xfree((ptr_t) wp); 81849992Sbostic whyles = nwp; 81949992Sbostic } 8201294Sbill } 8211294Sbill 82249992Sbostic void 82350439Schristos /*ARGSUSED*/ 82450439Schristos doecho(v, t) 82550439Schristos Char **v; 82650439Schristos struct command *t; 8271294Sbill { 82849992Sbostic xecho(' ', v); 8291294Sbill } 8301294Sbill 83149992Sbostic void 83250439Schristos /*ARGSUSED*/ 83350439Schristos doglob(v, t) 83450439Schristos Char **v; 83550439Schristos struct command *t; 8361294Sbill { 83749992Sbostic xecho(0, v); 83850439Schristos (void) fflush(cshout); 8391294Sbill } 8401294Sbill 84149992Sbostic static void 84249992Sbostic xecho(sep, v) 84350024Schristos int sep; 84449992Sbostic register Char **v; 8451294Sbill { 84649992Sbostic register Char *cp; 84749992Sbostic int nonl = 0; 8481294Sbill 84949992Sbostic if (setintr) 85050028Sbostic (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 85149992Sbostic v++; 85249992Sbostic if (*v == 0) 85349992Sbostic return; 85449992Sbostic gflag = 0, tglob(v); 85549992Sbostic if (gflag) { 85649992Sbostic v = globall(v); 85749992Sbostic if (v == 0) 85849992Sbostic stderror(ERR_NAME | ERR_NOMATCH); 85949992Sbostic } 86049992Sbostic else { 86149992Sbostic v = gargv = saveblk(v); 86249992Sbostic trim(v); 86349992Sbostic } 86449992Sbostic if (sep == ' ' && *v && eq(*v, STRmn)) 86549992Sbostic nonl++, v++; 86649992Sbostic while (cp = *v++) { 86749992Sbostic register int c; 8681294Sbill 86949992Sbostic while (c = *cp++) 87050439Schristos (void) fputc(c | QUOTE, cshout); 87149992Sbostic 87249992Sbostic if (*v) 87350439Schristos (void) fputc(sep | QUOTE, cshout); 87449992Sbostic } 87549992Sbostic if (sep && nonl == 0) 87650439Schristos (void) fputc('\n', cshout); 87749992Sbostic else 87850439Schristos (void) fflush(cshout); 87949992Sbostic if (setintr) 88049992Sbostic (void) sigblock(sigmask(SIGINT)); 88149992Sbostic if (gargv) 88249992Sbostic blkfree(gargv), gargv = 0; 8831294Sbill } 8841294Sbill 88549992Sbostic void 88650439Schristos /*ARGSUSED*/ 88750439Schristos dosetenv(v, t) 88850439Schristos Char **v; 88950439Schristos struct command *t; 8901294Sbill { 89149992Sbostic Char *vp, *lp; 8921294Sbill 89349992Sbostic v++; 89449992Sbostic if ((vp = *v++) == 0) { 89549992Sbostic register Char **ep; 89621753Sedward 89749992Sbostic if (setintr) 89850028Sbostic (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 89949992Sbostic for (ep = STR_environ; *ep; ep++) 90050439Schristos (void) fprintf(cshout, "%s\n", short2str(*ep)); 90149992Sbostic return; 90249992Sbostic } 90349992Sbostic if ((lp = *v++) == 0) 90449992Sbostic lp = STRNULL; 90549992Sbostic Setenv(vp, lp = globone(lp, G_ERROR)); 90649992Sbostic if (eq(vp, STRPATH)) { 90749992Sbostic importpath(lp); 90850439Schristos dohash(NULL, NULL); 90949992Sbostic } 91049992Sbostic else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { 91149992Sbostic #ifdef NLS 91249992Sbostic int k; 91349992Sbostic 91449992Sbostic (void) setlocale(LC_ALL, ""); 91549992Sbostic for (k = 0200; k <= 0377 && !Isprint(k); k++); 91649992Sbostic AsciiOnly = k > 0377; 91749992Sbostic #else 91849992Sbostic AsciiOnly = 0; 91949992Sbostic #endif /* NLS */ 92049992Sbostic } 92149992Sbostic xfree((ptr_t) lp); 9221294Sbill } 9231294Sbill 92449992Sbostic void 92550439Schristos /*ARGSUSED*/ 92650439Schristos dounsetenv(v, t) 92750439Schristos Char **v; 92850439Schristos struct command *t; 9291294Sbill { 93049992Sbostic Char **ep, *p, *n; 93149992Sbostic int i, maxi; 93249992Sbostic static Char *name = NULL; 9331294Sbill 93449992Sbostic if (name) 93549992Sbostic xfree((ptr_t) name); 93649992Sbostic /* 93749992Sbostic * Find the longest environment variable 93849992Sbostic */ 93949992Sbostic for (maxi = 0, ep = STR_environ; *ep; ep++) { 94049992Sbostic for (i = 0, p = *ep; *p && *p != '='; p++, i++); 94149992Sbostic if (i > maxi) 94249992Sbostic maxi = i; 94349992Sbostic } 94449992Sbostic 94549992Sbostic name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); 94649992Sbostic 94750160Schristos while (++v && *v) 94850160Schristos for (maxi = 1; maxi;) 94950160Schristos for (maxi = 0, ep = STR_environ; *ep; ep++) { 95050160Schristos for (n = name, p = *ep; *p && *p != '='; *n++ = *p++); 95150160Schristos *n = '\0'; 95250160Schristos if (!Gmatch(name, *v)) 95350160Schristos continue; 95450160Schristos maxi = 1; 95550160Schristos if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { 95649992Sbostic #ifdef NLS 95750160Schristos int k; 95849992Sbostic 95950160Schristos (void) setlocale(LC_ALL, ""); 96050160Schristos for (k = 0200; k <= 0377 && !Isprint(k); k++); 96150160Schristos AsciiOnly = k > 0377; 96249992Sbostic #else 96350160Schristos AsciiOnly = getenv("LANG") == NULL && 96450160Schristos getenv("LC_CTYPE") == NULL; 96549992Sbostic #endif /* NLS */ 96650160Schristos } 96750160Schristos /* 96850160Schristos * Delete name, and start again cause the environment changes 96950160Schristos */ 97050160Schristos Unsetenv(name); 97150160Schristos break; 97249992Sbostic } 97349992Sbostic xfree((ptr_t) name), name = NULL; 9741294Sbill } 9751294Sbill 97649992Sbostic void 97749992Sbostic Setenv(name, val) 97849992Sbostic Char *name, *val; 9791294Sbill { 98049992Sbostic register Char **ep = STR_environ; 98149992Sbostic register Char *cp, *dp; 98249992Sbostic Char *blk[2]; 98349992Sbostic Char **oep = ep; 9841294Sbill 98549992Sbostic 98649992Sbostic for (; *ep; ep++) { 98749992Sbostic for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 98849992Sbostic continue; 98949992Sbostic if (*cp != 0 || *dp != '=') 99049992Sbostic continue; 99149992Sbostic cp = Strspl(STRequal, val); 99249992Sbostic xfree((ptr_t) * ep); 99349992Sbostic *ep = strip(Strspl(name, cp)); 99449992Sbostic xfree((ptr_t) cp); 99549992Sbostic blkfree((Char **) environ); 99649992Sbostic environ = short2blk(STR_environ); 99749992Sbostic return; 99849992Sbostic } 99949992Sbostic cp = Strspl(name, STRequal); 100049992Sbostic blk[0] = strip(Strspl(cp, val)); 100149992Sbostic xfree((ptr_t) cp); 100249992Sbostic blk[1] = 0; 100349992Sbostic STR_environ = blkspl(STR_environ, blk); 100449992Sbostic blkfree((Char **) environ); 100549992Sbostic environ = short2blk(STR_environ); 100649992Sbostic xfree((ptr_t) oep); 10071294Sbill } 10081294Sbill 100949992Sbostic static void 101049992Sbostic Unsetenv(name) 101149992Sbostic Char *name; 10121294Sbill { 101349992Sbostic register Char **ep = STR_environ; 101449992Sbostic register Char *cp, *dp; 101549992Sbostic Char **oep = ep; 10161294Sbill 101749992Sbostic for (; *ep; ep++) { 101849992Sbostic for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 101949992Sbostic continue; 102049992Sbostic if (*cp != 0 || *dp != '=') 102149992Sbostic continue; 102249992Sbostic cp = *ep; 102349992Sbostic *ep = 0; 102449992Sbostic STR_environ = blkspl(STR_environ, ep + 1); 102549992Sbostic environ = short2blk(STR_environ); 102649992Sbostic *ep = cp; 102749992Sbostic xfree((ptr_t) cp); 102849992Sbostic xfree((ptr_t) oep); 102949992Sbostic return; 103049992Sbostic } 10311294Sbill } 10321294Sbill 103349992Sbostic void 103450439Schristos /*ARGSUSED*/ 103550439Schristos doumask(v, t) 103650439Schristos Char **v; 103750439Schristos struct command *t; 10381294Sbill { 103949992Sbostic register Char *cp = v[1]; 104049992Sbostic register int i; 10411294Sbill 104249992Sbostic if (cp == 0) { 104349992Sbostic i = umask(0); 104417519Sedward (void) umask(i); 104550439Schristos (void) fprintf(cshout, "%o\n", i); 104649992Sbostic return; 104749992Sbostic } 104849992Sbostic i = 0; 104949992Sbostic while (Isdigit(*cp) && *cp != '8' && *cp != '9') 105049992Sbostic i = i * 8 + *cp++ - '0'; 105149992Sbostic if (*cp || i < 0 || i > 0777) 105249992Sbostic stderror(ERR_NAME | ERR_MASK); 105349992Sbostic (void) umask(i); 10541294Sbill } 10551294Sbill 105649992Sbostic typedef int RLIM_TYPE; 10571294Sbill 105849992Sbostic static struct limits { 105949992Sbostic int limconst; 106049992Sbostic char *limname; 106149992Sbostic int limdiv; 106249992Sbostic char *limscale; 106349992Sbostic } limits[] = { 106449992Sbostic RLIMIT_CPU, "cputime", 1, "seconds", 106549992Sbostic RLIMIT_FSIZE, "filesize", 1024, "kbytes", 106649992Sbostic RLIMIT_DATA, "datasize", 1024, "kbytes", 106749992Sbostic RLIMIT_STACK, "stacksize", 1024, "kbytes", 106849992Sbostic RLIMIT_CORE, "coredumpsize", 1024, "kbytes", 106949992Sbostic RLIMIT_RSS, "memoryuse", 1024, "kbytes", 107050024Schristos RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes", 107150024Schristos RLIMIT_NPROC, "maxproc", 1, "", 107250024Schristos RLIMIT_OFILE, "openfiles", 1, "", 107350024Schristos -1, NULL, 0, NULL 10741294Sbill }; 10751294Sbill 107649992Sbostic static struct limits *findlim(); 107749992Sbostic static RLIM_TYPE getval(); 107849992Sbostic static void limtail(); 107949992Sbostic static void plim(); 108049992Sbostic static int setlim(); 108149992Sbostic 108249992Sbostic static struct limits * 10831294Sbill findlim(cp) 108449992Sbostic Char *cp; 10851294Sbill { 108649992Sbostic register struct limits *lp, *res; 10871294Sbill 108849992Sbostic res = (struct limits *) NULL; 108949992Sbostic for (lp = limits; lp->limconst >= 0; lp++) 109049992Sbostic if (prefix(cp, str2short(lp->limname))) { 109149992Sbostic if (res) 109249992Sbostic stderror(ERR_NAME | ERR_AMBIG); 109349992Sbostic res = lp; 109449992Sbostic } 109549992Sbostic if (res) 109649992Sbostic return (res); 109749992Sbostic stderror(ERR_NAME | ERR_LIMIT); 109849992Sbostic /* NOTREACHED */ 109949992Sbostic return (0); 11001294Sbill } 11011294Sbill 110249992Sbostic void 110350439Schristos /*ARGSUSED*/ 110450439Schristos dolimit(v, t) 110550439Schristos Char **v; 110650439Schristos struct command *t; 11071294Sbill { 110849992Sbostic register struct limits *lp; 110949992Sbostic register RLIM_TYPE limit; 111049992Sbostic char hard = 0; 11111294Sbill 111249992Sbostic v++; 111349992Sbostic if (*v && eq(*v, STRmh)) { 111449992Sbostic hard = 1; 11151294Sbill v++; 111649992Sbostic } 111749992Sbostic if (*v == 0) { 111849992Sbostic for (lp = limits; lp->limconst >= 0; lp++) 111949992Sbostic plim(lp, hard); 112049992Sbostic return; 112149992Sbostic } 112249992Sbostic lp = findlim(v[0]); 112349992Sbostic if (v[1] == 0) { 112449992Sbostic plim(lp, hard); 112549992Sbostic return; 112649992Sbostic } 112749992Sbostic limit = getval(lp, v + 1); 112849992Sbostic if (setlim(lp, hard, limit) < 0) 112949992Sbostic stderror(ERR_SILENT); 11301294Sbill } 11311294Sbill 113249992Sbostic static RLIM_TYPE 11331294Sbill getval(lp, v) 113449992Sbostic register struct limits *lp; 113549992Sbostic Char **v; 11361294Sbill { 113749992Sbostic register float f; 113849992Sbostic double atof(); 113949992Sbostic Char *cp = *v++; 11401294Sbill 114149992Sbostic f = atof(short2str(cp)); 114249992Sbostic 114349992Sbostic while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 114449992Sbostic cp++; 114549992Sbostic if (*cp == 0) { 114649992Sbostic if (*v == 0) 114749992Sbostic return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv)); 114849992Sbostic cp = *v; 114949992Sbostic } 115049992Sbostic switch (*cp) { 115149992Sbostic case ':': 115249992Sbostic if (lp->limconst != RLIMIT_CPU) 115349992Sbostic goto badscal; 115449992Sbostic return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1)))); 115549992Sbostic case 'h': 115649992Sbostic if (lp->limconst != RLIMIT_CPU) 115749992Sbostic goto badscal; 115849992Sbostic limtail(cp, "hours"); 115949992Sbostic f *= 3600.0; 116049992Sbostic break; 116149992Sbostic case 'm': 116249992Sbostic if (lp->limconst == RLIMIT_CPU) { 116349992Sbostic limtail(cp, "minutes"); 116449992Sbostic f *= 60.0; 116549992Sbostic break; 11661294Sbill } 116749992Sbostic *cp = 'm'; 116849992Sbostic limtail(cp, "megabytes"); 116949992Sbostic f *= 1024.0 * 1024.0; 117049992Sbostic break; 117149992Sbostic case 's': 117249992Sbostic if (lp->limconst != RLIMIT_CPU) 117349992Sbostic goto badscal; 117449992Sbostic limtail(cp, "seconds"); 117549992Sbostic break; 117649992Sbostic case 'M': 117749992Sbostic if (lp->limconst == RLIMIT_CPU) 117849992Sbostic goto badscal; 117949992Sbostic *cp = 'm'; 118049992Sbostic limtail(cp, "megabytes"); 118149992Sbostic f *= 1024.0 * 1024.0; 118249992Sbostic break; 118349992Sbostic case 'k': 118449992Sbostic if (lp->limconst == RLIMIT_CPU) 118549992Sbostic goto badscal; 118649992Sbostic limtail(cp, "kbytes"); 118749992Sbostic f *= 1024.0; 118849992Sbostic break; 118949992Sbostic case 'u': 119049992Sbostic limtail(cp, "unlimited"); 119149992Sbostic return (RLIM_INFINITY); 119249992Sbostic default: 11931294Sbill badscal: 119449992Sbostic stderror(ERR_NAME | ERR_SCALEF); 119549992Sbostic } 119649992Sbostic return ((RLIM_TYPE) (f + 0.5)); 11971294Sbill } 11981294Sbill 119949992Sbostic static void 120049992Sbostic limtail(cp, str) 120149992Sbostic Char *cp; 120249992Sbostic char *str; 12031294Sbill { 120449992Sbostic while (*cp && *cp == *str) 120549992Sbostic cp++, str++; 120649992Sbostic if (*cp) 120749992Sbostic stderror(ERR_BADSCALE, str); 12081294Sbill } 12091294Sbill 121049992Sbostic 121149992Sbostic /*ARGSUSED*/ 121249992Sbostic static void 121318539Sedward plim(lp, hard) 121449992Sbostic register struct limits *lp; 121549992Sbostic Char hard; 12161294Sbill { 121749992Sbostic struct rlimit rlim; 121849992Sbostic RLIM_TYPE limit; 12191294Sbill 122050439Schristos (void) fprintf(cshout, "%s \t", lp->limname); 122149992Sbostic 122249992Sbostic (void) getrlimit(lp->limconst, &rlim); 122349992Sbostic limit = hard ? rlim.rlim_max : rlim.rlim_cur; 122449992Sbostic 122549992Sbostic if (limit == RLIM_INFINITY) 122650439Schristos (void) fprintf(cshout, "unlimited"); 122749992Sbostic else if (lp->limconst == RLIMIT_CPU) 122849992Sbostic psecs((long) limit); 122949992Sbostic else 123050439Schristos (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), 123150439Schristos lp->limscale); 123250439Schristos (void) fputc('\n', cshout); 12331294Sbill } 12341294Sbill 123549992Sbostic void 123650439Schristos /*ARGSUSED*/ 123750439Schristos dounlimit(v, t) 123850439Schristos Char **v; 123950439Schristos struct command *t; 12401294Sbill { 124149992Sbostic register struct limits *lp; 124249992Sbostic int lerr = 0; 124349992Sbostic Char hard = 0; 12441294Sbill 124549992Sbostic v++; 124649992Sbostic if (*v && eq(*v, STRmh)) { 124749992Sbostic hard = 1; 12481294Sbill v++; 124949992Sbostic } 125049992Sbostic if (*v == 0) { 125149992Sbostic for (lp = limits; lp->limconst >= 0; lp++) 125249992Sbostic if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 125349992Sbostic lerr++; 125449992Sbostic if (lerr) 125549992Sbostic stderror(ERR_SILENT); 125649992Sbostic return; 125749992Sbostic } 125849992Sbostic while (*v) { 125949992Sbostic lp = findlim(*v++); 126049992Sbostic if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 126149992Sbostic stderror(ERR_SILENT); 126249992Sbostic } 12631294Sbill } 12641294Sbill 126549992Sbostic static int 126618539Sedward setlim(lp, hard, limit) 126749992Sbostic register struct limits *lp; 126849992Sbostic Char hard; 126949992Sbostic RLIM_TYPE limit; 12701294Sbill { 127149992Sbostic struct rlimit rlim; 12721294Sbill 127349992Sbostic (void) getrlimit(lp->limconst, &rlim); 127449992Sbostic 127549992Sbostic if (hard) 127649992Sbostic rlim.rlim_max = limit; 127749992Sbostic else if (limit == RLIM_INFINITY && geteuid() != 0) 127849992Sbostic rlim.rlim_cur = rlim.rlim_max; 127949992Sbostic else 128049992Sbostic rlim.rlim_cur = limit; 128149992Sbostic 128249992Sbostic if (setrlimit(lp->limconst, &rlim) < 0) { 128350439Schristos (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, 128450439Schristos limit == RLIM_INFINITY ? "remove" : "set", 128550439Schristos hard ? " hard" : ""); 128649992Sbostic return (-1); 128749992Sbostic } 128849992Sbostic return (0); 12891294Sbill } 12901294Sbill 129149992Sbostic void 129250439Schristos /*ARGSUSED*/ 129350439Schristos dosuspend(v, t) 129450439Schristos Char **v; 129550439Schristos struct command *t; 12961294Sbill { 129749992Sbostic int ctpgrp; 12981294Sbill 129949992Sbostic void (*old) (); 130049992Sbostic 130149992Sbostic if (loginsh) 130249992Sbostic stderror(ERR_SUSPLOG); 130349992Sbostic untty(); 130449992Sbostic 130549992Sbostic old = signal(SIGTSTP, SIG_DFL); 130649992Sbostic (void) kill(0, SIGTSTP); 130749992Sbostic /* the shell stops here */ 130849992Sbostic (void) signal(SIGTSTP, old); 130949992Sbostic 131049992Sbostic if (tpgrp != -1) { 131149992Sbostic ctpgrp = tcgetpgrp(FSHTTY); 131250439Schristos while (ctpgrp != opgrp) { 131349992Sbostic old = signal(SIGTTIN, SIG_DFL); 131449992Sbostic (void) kill(0, SIGTTIN); 131549992Sbostic (void) signal(SIGTTIN, old); 13161294Sbill } 131749992Sbostic (void) setpgid(0, shpgrp); 131849992Sbostic (void) tcsetpgrp(FSHTTY, shpgrp); 131949992Sbostic } 13201294Sbill } 13211294Sbill 132249992Sbostic /* This is the dreaded EVAL built-in. 132349992Sbostic * If you don't fiddle with file descriptors, and reset didfds, 132449992Sbostic * this command will either ignore redirection inside or outside 132549992Sbostic * its aguments, e.g. eval "date >x" vs. eval "date" >x 132649992Sbostic * The stuff here seems to work, but I did it by trial and error rather 132749992Sbostic * than really knowing what was going on. If tpgrp is zero, we are 132849992Sbostic * probably a background eval, e.g. "eval date &", and we want to 132949992Sbostic * make sure that any processes we start stay in our pgrp. 133049992Sbostic * This is also the case for "time eval date" -- stay in same pgrp. 133149992Sbostic * Otherwise, under stty tostop, processes will stop in the wrong 133249992Sbostic * pgrp, with no way for the shell to get them going again. -IAN! 133349992Sbostic */ 133450439Schristos static Char **gv = NULL; 133549992Sbostic void 133650439Schristos /*ARGSUSED*/ 133750439Schristos doeval(v, t) 133850439Schristos Char **v; 133950439Schristos struct command *t; 13401294Sbill { 134149992Sbostic Char **oevalvec; 134249992Sbostic Char *oevalp; 134349992Sbostic int odidfds; 134449992Sbostic jmp_buf osetexit; 134549992Sbostic int my_reenter; 134650439Schristos Char **savegv = gv; 134749992Sbostic int saveIN; 134849992Sbostic int saveOUT; 134950439Schristos int saveERR; 135049992Sbostic int oSHIN; 135149992Sbostic int oSHOUT; 135250439Schristos int oSHERR; 13531294Sbill 135449992Sbostic oevalvec = evalvec; 135549992Sbostic oevalp = evalp; 135649992Sbostic odidfds = didfds; 135749992Sbostic oSHIN = SHIN; 135849992Sbostic oSHOUT = SHOUT; 135950439Schristos oSHERR = SHERR; 136049992Sbostic 136149992Sbostic v++; 136249992Sbostic if (*v == 0) 136349992Sbostic return; 136449992Sbostic gflag = 0, tglob(v); 136549992Sbostic if (gflag) { 136649992Sbostic gv = v = globall(v); 136749992Sbostic gargv = 0; 136849992Sbostic if (v == 0) 136949992Sbostic stderror(ERR_NOMATCH); 137049992Sbostic v = copyblk(v); 137149992Sbostic } 137249992Sbostic else { 137350024Schristos gv = NULL; 137449992Sbostic v = copyblk(v); 137549992Sbostic trim(v); 137649992Sbostic } 137749992Sbostic 137849992Sbostic saveIN = dcopy(SHIN, -1); 137949992Sbostic saveOUT = dcopy(SHOUT, -1); 138050439Schristos saveERR = dcopy(SHERR, -1); 138149992Sbostic 138249992Sbostic getexit(osetexit); 138349992Sbostic 138449992Sbostic if ((my_reenter = setexit()) == 0) { 138549992Sbostic evalvec = v; 138649992Sbostic evalp = 0; 138749992Sbostic SHIN = dcopy(0, -1); 138849992Sbostic SHOUT = dcopy(1, -1); 138950439Schristos SHERR = dcopy(2, -1); 139049992Sbostic didfds = 0; 139149992Sbostic process(0); 139249992Sbostic } 139349992Sbostic 139449992Sbostic evalvec = oevalvec; 139549992Sbostic evalp = oevalp; 139649992Sbostic doneinp = 0; 139749992Sbostic didfds = odidfds; 139849992Sbostic (void) close(SHIN); 139949992Sbostic (void) close(SHOUT); 140050439Schristos (void) close(SHERR); 140149992Sbostic SHIN = dmove(saveIN, oSHIN); 140249992Sbostic SHOUT = dmove(saveOUT, oSHOUT); 140350439Schristos SHERR = dmove(saveERR, oSHERR); 140449992Sbostic if (gv) 140550439Schristos blkfree(gv), gv = NULL; 140649992Sbostic resexit(osetexit); 140750439Schristos gv = savegv; 140849992Sbostic if (my_reenter) 140949992Sbostic stderror(ERR_SILENT); 14101294Sbill } 1411*50639Schristos 1412*50639Schristos void 1413*50639Schristos /*ARGSUSED*/ 1414*50639Schristos doprintf(v, t) 1415*50639Schristos Char **v; 1416*50639Schristos struct command *t; 1417*50639Schristos { 1418*50639Schristos char **c; 1419*50639Schristos extern int progprintf __P((int, char **)); 1420*50639Schristos int ret; 1421*50639Schristos 1422*50639Schristos ret = progprintf(blklen(v), c = short2blk(v)); 1423*50639Schristos 1424*50639Schristos blkfree((Char **) c); 1425*50639Schristos if (ret) 1426*50639Schristos stderror(ERR_SILENT); 1427*50639Schristos } 1428*50639Schristos 1429