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*51589Schristos static char sccsid[] = "@(#)func.c 5.32 (Berkeley) 11/06/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)); 3651420Schristos static void search __P((int, int, Char *)); 3750024Schristos static int getword __P((Char *)); 3850024Schristos static int keyword __P((Char *)); 3950024Schristos static void toend __P((void)); 4050024Schristos static void xecho __P((int, Char **)); 4151420Schristos static void Unsetenv __P((Char *)); 4249992Sbostic 431294Sbill struct biltins * 441294Sbill isbfunc(t) 4549992Sbostic struct command *t; 461294Sbill { 4749992Sbostic register Char *cp = t->t_dcom[0]; 4849992Sbostic register struct biltins *bp, *bp1, *bp2; 4949992Sbostic static struct biltins label = {"", dozip, 0, 0}; 5049992Sbostic static struct biltins foregnd = {"%job", dofg1, 0, 0}; 5149992Sbostic static struct biltins backgnd = {"%job &", dobg1, 0, 0}; 521294Sbill 5349992Sbostic if (lastchr(cp) == ':') { 5449992Sbostic label.bname = short2str(cp); 5549992Sbostic return (&label); 5649992Sbostic } 5749992Sbostic if (*cp == '%') { 5849992Sbostic if (t->t_dflg & F_AMPERSAND) { 5949992Sbostic t->t_dflg &= ~F_AMPERSAND; 6049992Sbostic backgnd.bname = short2str(cp); 6149992Sbostic return (&backgnd); 621294Sbill } 6349992Sbostic foregnd.bname = short2str(cp); 6449992Sbostic return (&foregnd); 6549992Sbostic } 6649992Sbostic /* 6749992Sbostic * Binary search Bp1 is the beginning of the current search range. Bp2 is 6849992Sbostic * one past the end. 6949992Sbostic */ 7049992Sbostic for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 7149992Sbostic register i; 7217519Sedward 7349992Sbostic bp = bp1 + ((bp2 - bp1) >> 1); 7449992Sbostic if ((i = *cp - *bp->bname) == 0 && 7549992Sbostic (i = Strcmp(cp, str2short(bp->bname))) == 0) 7649992Sbostic return bp; 7749992Sbostic if (i < 0) 7849992Sbostic bp2 = bp; 7949992Sbostic else 8049992Sbostic bp1 = bp + 1; 8149992Sbostic } 8249992Sbostic return (0); 831294Sbill } 841294Sbill 8549992Sbostic void 861294Sbill func(t, bp) 8749992Sbostic register struct command *t; 8849992Sbostic register struct biltins *bp; 891294Sbill { 9049992Sbostic int i; 911294Sbill 9249992Sbostic xechoit(t->t_dcom); 9349992Sbostic setname(bp->bname); 9449992Sbostic i = blklen(t->t_dcom) - 1; 9549992Sbostic if (i < bp->minargs) 9649992Sbostic stderror(ERR_NAME | ERR_TOOFEW); 9749992Sbostic if (i > bp->maxargs) 9849992Sbostic stderror(ERR_NAME | ERR_TOOMANY); 9949992Sbostic (*bp->bfunct) (t->t_dcom, t); 1001294Sbill } 1011294Sbill 10249992Sbostic void 10350439Schristos /*ARGSUSED*/ 10450439Schristos doonintr(v, t) 10550439Schristos Char **v; 10650439Schristos struct command *t; 1071294Sbill { 10849992Sbostic register Char *cp; 10949992Sbostic register Char *vv = v[1]; 1101294Sbill 11149992Sbostic if (parintr == SIG_IGN) 11249992Sbostic return; 11349992Sbostic if (setintr && intty) 11449992Sbostic stderror(ERR_NAME | ERR_TERMINAL); 11549992Sbostic cp = gointr; 11649992Sbostic gointr = 0; 11749992Sbostic xfree((ptr_t) cp); 11849992Sbostic if (vv == 0) { 11949992Sbostic if (setintr) 12049992Sbostic (void) sigblock(sigmask(SIGINT)); 12149992Sbostic else 12249992Sbostic (void) signal(SIGINT, SIG_DFL); 12349992Sbostic gointr = 0; 12449992Sbostic } 12549992Sbostic else if (eq((vv = strip(vv)), STRminus)) { 12649992Sbostic (void) signal(SIGINT, SIG_IGN); 12749992Sbostic gointr = Strsave(STRminus); 12849992Sbostic } 12949992Sbostic else { 13049992Sbostic gointr = Strsave(vv); 13149992Sbostic (void) signal(SIGINT, pintr); 13249992Sbostic } 1331294Sbill } 1341294Sbill 13549992Sbostic void 13650439Schristos /*ARGSUSED*/ 13750439Schristos donohup(v, t) 13850439Schristos Char **v; 13950439Schristos struct command *t; 1401294Sbill { 14149992Sbostic if (intty) 14249992Sbostic stderror(ERR_NAME | ERR_TERMINAL); 14349992Sbostic if (setintr == 0) { 14449992Sbostic (void) signal(SIGHUP, SIG_IGN); 14549992Sbostic } 1461294Sbill } 1471294Sbill 14849992Sbostic void 14950439Schristos /*ARGSUSED*/ 15050439Schristos dozip(v, t) 15150439Schristos Char **v; 15250439Schristos struct command *t; 1531294Sbill { 15449992Sbostic ; 1551294Sbill } 1561294Sbill 15749992Sbostic void 1581294Sbill prvars() 1591294Sbill { 16049992Sbostic plist(&shvhed); 1611294Sbill } 1621294Sbill 16349992Sbostic void 16450439Schristos /*ARGSUSED*/ 16550439Schristos doalias(v, t) 16650439Schristos Char **v; 16750439Schristos struct command *t; 1681294Sbill { 16949992Sbostic register struct varent *vp; 17049992Sbostic register Char *p; 1711294Sbill 17249992Sbostic v++; 17349992Sbostic p = *v++; 17449992Sbostic if (p == 0) 17549992Sbostic plist(&aliases); 17649992Sbostic else if (*v == 0) { 17749992Sbostic vp = adrof1(strip(p), &aliases); 17850439Schristos if (vp) { 17950439Schristos blkpr(cshout, vp->vec); 18050439Schristos fputc('\n', cshout); 18150439Schristos } 18249992Sbostic } 18349992Sbostic else { 18449992Sbostic if (eq(p, STRalias) || eq(p, STRunalias)) { 185*51589Schristos setname(vis_str(p)); 18649992Sbostic stderror(ERR_NAME | ERR_DANGER); 1871294Sbill } 18849992Sbostic set1(strip(p), saveblk(v), &aliases); 18949992Sbostic } 1901294Sbill } 1911294Sbill 19249992Sbostic void 19350439Schristos /*ARGSUSED*/ 19450439Schristos unalias(v, t) 19550439Schristos Char **v; 19650439Schristos struct command *t; 1971294Sbill { 19849992Sbostic unset1(v, &aliases); 1991294Sbill } 2001294Sbill 20149992Sbostic void 20250439Schristos /*ARGSUSED*/ 20350439Schristos dologout(v, t) 20450439Schristos Char **v; 20550439Schristos struct command *t; 2061294Sbill { 20749992Sbostic islogin(); 20849992Sbostic goodbye(); 2091294Sbill } 2101294Sbill 21149992Sbostic void 21250439Schristos /*ARGSUSED*/ 21350439Schristos dologin(v, t) 21450439Schristos Char **v; 21550439Schristos struct command *t; 2161294Sbill { 21749992Sbostic islogin(); 21849992Sbostic rechist(); 21949992Sbostic (void) signal(SIGTERM, parterm); 22050024Schristos (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); 22149992Sbostic untty(); 22249992Sbostic xexit(1); 2231294Sbill } 2241294Sbill 22549992Sbostic static void 2261294Sbill islogin() 2271294Sbill { 22849992Sbostic if (chkstop == 0 && setintr) 22949992Sbostic panystop(0); 23049992Sbostic if (loginsh) 23149992Sbostic return; 23249992Sbostic stderror(ERR_NOTLOGIN); 2331294Sbill } 2341294Sbill 23549992Sbostic void 2361294Sbill doif(v, kp) 23749992Sbostic Char **v; 23849992Sbostic struct command *kp; 2391294Sbill { 24049992Sbostic register int i; 24149992Sbostic register Char **vv; 2421294Sbill 24349992Sbostic v++; 24451009Schristos i = expr(&v); 24549992Sbostic vv = v; 24649992Sbostic if (*vv == NULL) 24749992Sbostic stderror(ERR_NAME | ERR_EMPTYIF); 24849992Sbostic if (eq(*vv, STRthen)) { 24949992Sbostic if (*++vv) 25049992Sbostic stderror(ERR_NAME | ERR_IMPRTHEN); 251*51589Schristos setname(vis_str(STRthen)); 2521294Sbill /* 25349992Sbostic * If expression was zero, then scan to else, otherwise just fall into 25449992Sbostic * following code. 2551294Sbill */ 25649992Sbostic if (!i) 25750024Schristos search(T_IF, 0, NULL); 25849992Sbostic return; 25949992Sbostic } 26049992Sbostic /* 26149992Sbostic * Simple command attached to this if. Left shift the node in this tree, 26249992Sbostic * munging it so we can reexecute it. 26349992Sbostic */ 26449992Sbostic if (i) { 26549992Sbostic lshift(kp->t_dcom, vv - kp->t_dcom); 26649992Sbostic reexecute(kp); 26749992Sbostic donefds(); 26849992Sbostic } 2691294Sbill } 2701294Sbill 2711294Sbill /* 2721294Sbill * Reexecute a command, being careful not 2731294Sbill * to redo i/o redirection, which is already set up. 2741294Sbill */ 27549992Sbostic static void 2761294Sbill reexecute(kp) 27749992Sbostic register struct command *kp; 2781294Sbill { 27949992Sbostic kp->t_dflg &= F_SAVE; 28049992Sbostic kp->t_dflg |= F_REPEAT; 28149992Sbostic /* 28249992Sbostic * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set 28349992Sbostic * pgrp's as the jobs would then have no way to get the tty (we can't give 28449992Sbostic * it to them, and our parent wouldn't know their pgrp, etc. 28549992Sbostic */ 28650023Sbostic execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); 2871294Sbill } 2881294Sbill 28949992Sbostic void 29050439Schristos /*ARGSUSED*/ 29150439Schristos doelse(v, t) 29250439Schristos Char **v; 29350439Schristos struct command *t; 2941294Sbill { 29550024Schristos search(T_ELSE, 0, NULL); 2961294Sbill } 2971294Sbill 29849992Sbostic void 29950439Schristos /*ARGSUSED*/ 30050439Schristos dogoto(v, t) 30150439Schristos Char **v; 30250439Schristos struct command *t; 3031294Sbill { 30449992Sbostic Char *lp; 3051294Sbill 30651420Schristos gotolab(lp = globone(v[1], G_ERROR)); 30751420Schristos xfree((ptr_t) lp); 30851420Schristos } 30951420Schristos 31051420Schristos void 31151420Schristos gotolab(lab) 31251420Schristos Char *lab; 31351420Schristos { 31451420Schristos register struct whyle *wp; 31549992Sbostic /* 31649992Sbostic * While we still can, locate any unknown ends of existing loops. This 31749992Sbostic * obscure code is the WORST result of the fact that we don't really parse. 31849992Sbostic */ 31949992Sbostic zlast = T_GOTO; 32049992Sbostic for (wp = whyles; wp; wp = wp->w_next) 32151378Schristos if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) { 32250024Schristos search(T_BREAK, 0, NULL); 32350944Schristos btell(&wp->w_end); 32449992Sbostic } 32549992Sbostic else 32650944Schristos bseek(&wp->w_end); 32751420Schristos search(T_GOTO, 0, lab); 32849992Sbostic /* 32949992Sbostic * Eliminate loops which were exited. 33049992Sbostic */ 33149992Sbostic wfree(); 3321294Sbill } 3331294Sbill 33449992Sbostic void 33550439Schristos /*ARGSUSED*/ 33650439Schristos doswitch(v, t) 33750439Schristos Char **v; 33850439Schristos struct command *t; 3391294Sbill { 34049992Sbostic register Char *cp, *lp; 3411294Sbill 34249992Sbostic v++; 34349992Sbostic if (!*v || *(*v++) != '(') 34449992Sbostic stderror(ERR_SYNTAX); 34549992Sbostic cp = **v == ')' ? STRNULL : *v++; 34649992Sbostic if (*(*v++) != ')') 34749992Sbostic v--; 34849992Sbostic if (*v) 34949992Sbostic stderror(ERR_SYNTAX); 35049992Sbostic search(T_SWITCH, 0, lp = globone(cp, G_ERROR)); 35149992Sbostic xfree((ptr_t) lp); 3521294Sbill } 3531294Sbill 35449992Sbostic void 35550439Schristos /*ARGSUSED*/ 35650439Schristos dobreak(v, t) 35750439Schristos Char **v; 35850439Schristos struct command *t; 3591294Sbill { 36049992Sbostic if (whyles) 36149992Sbostic toend(); 36249992Sbostic else 36349992Sbostic stderror(ERR_NAME | ERR_NOTWHILE); 3641294Sbill } 3651294Sbill 36649992Sbostic void 36750439Schristos /*ARGSUSED*/ 36850439Schristos doexit(v, t) 36950439Schristos Char **v; 37050439Schristos struct command *t; 3711294Sbill { 37249992Sbostic if (chkstop == 0 && (intty || intact) && evalvec == 0) 37349992Sbostic panystop(0); 37449992Sbostic /* 37549992Sbostic * Don't DEMAND parentheses here either. 37649992Sbostic */ 37749992Sbostic v++; 37849992Sbostic if (*v) { 37951009Schristos set(STRstatus, putn(expr(&v))); 38049992Sbostic if (*v) 38149992Sbostic stderror(ERR_NAME | ERR_EXPRESSION); 38249992Sbostic } 38349992Sbostic btoeof(); 38449992Sbostic if (intty) 38549992Sbostic (void) close(SHIN); 3861294Sbill } 3871294Sbill 38849992Sbostic void 38950439Schristos /*ARGSUSED*/ 39050439Schristos doforeach(v, t) 39150439Schristos Char **v; 39250439Schristos struct command *t; 3931294Sbill { 39449992Sbostic register Char *cp, *sp; 39549992Sbostic register struct whyle *nwp; 3961294Sbill 39749992Sbostic v++; 39849992Sbostic sp = cp = strip(*v); 39949992Sbostic if (!letter(*sp)) 40049992Sbostic stderror(ERR_NAME | ERR_VARBEGIN); 40149992Sbostic while (*cp && alnum(*cp)) 40249992Sbostic cp++; 40349992Sbostic if (*cp) 40449992Sbostic stderror(ERR_NAME | ERR_VARALNUM); 40549992Sbostic if ((cp - sp) > MAXVARLEN) 40649992Sbostic stderror(ERR_NAME | ERR_VARTOOLONG); 40749992Sbostic cp = *v++; 40849992Sbostic if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 40949992Sbostic stderror(ERR_NAME | ERR_NOPAREN); 41049992Sbostic v++; 41149992Sbostic gflag = 0, tglob(v); 41249992Sbostic v = globall(v); 41349992Sbostic if (v == 0) 41449992Sbostic stderror(ERR_NAME | ERR_NOMATCH); 41549992Sbostic nwp = (struct whyle *) xcalloc(1, sizeof *nwp); 41649992Sbostic nwp->w_fe = nwp->w_fe0 = v; 41749992Sbostic gargv = 0; 41850944Schristos btell(&nwp->w_start); 41949992Sbostic nwp->w_fename = Strsave(cp); 42049992Sbostic nwp->w_next = whyles; 42151378Schristos nwp->w_end.type = F_SEEK; 42249992Sbostic whyles = nwp; 42349992Sbostic /* 42449992Sbostic * Pre-read the loop so as to be more comprehensible to a terminal user. 42549992Sbostic */ 42649992Sbostic zlast = T_FOREACH; 42749992Sbostic if (intty) 42849992Sbostic preread(); 42949992Sbostic doagain(); 4301294Sbill } 4311294Sbill 43249992Sbostic void 43350439Schristos /*ARGSUSED*/ 43450439Schristos dowhile(v, t) 43550439Schristos Char **v; 43650439Schristos struct command *t; 4371294Sbill { 43849992Sbostic register int status; 43950944Schristos register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && 44049992Sbostic whyles->w_fename == 0; 4411294Sbill 44249992Sbostic v++; 44349992Sbostic /* 44449992Sbostic * Implement prereading here also, taking care not to evaluate the 44549992Sbostic * expression before the loop has been read up from a terminal. 44649992Sbostic */ 44749992Sbostic if (intty && !again) 44849992Sbostic status = !exp0(&v, 1); 44949992Sbostic else 45051009Schristos status = !expr(&v); 45149992Sbostic if (*v) 45249992Sbostic stderror(ERR_NAME | ERR_EXPRESSION); 45349992Sbostic if (!again) { 45449992Sbostic register struct whyle *nwp = 45549992Sbostic (struct whyle *) xcalloc(1, sizeof(*nwp)); 4561294Sbill 45749992Sbostic nwp->w_start = lineloc; 45851378Schristos nwp->w_end.type = F_SEEK; 45951378Schristos nwp->w_end.f_seek = 0; 46049992Sbostic nwp->w_next = whyles; 46149992Sbostic whyles = nwp; 46249992Sbostic zlast = T_WHILE; 46349992Sbostic if (intty) { 46449992Sbostic /* 46549992Sbostic * The tty preread 46649992Sbostic */ 46749992Sbostic preread(); 46849992Sbostic doagain(); 46949992Sbostic return; 4701294Sbill } 47149992Sbostic } 47249992Sbostic if (status) 47349992Sbostic /* We ain't gonna loop no more, no more! */ 47449992Sbostic toend(); 4751294Sbill } 4761294Sbill 47749992Sbostic static void 4781294Sbill preread() 4791294Sbill { 48050944Schristos whyles->w_end.type = I_SEEK; 48149992Sbostic if (setintr) 48250028Sbostic (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 4831294Sbill 48450024Schristos search(T_BREAK, 0, NULL); /* read the expression in */ 48549992Sbostic if (setintr) 48649992Sbostic (void) sigblock(sigmask(SIGINT)); 48750944Schristos btell(&whyles->w_end); 4881294Sbill } 4891294Sbill 49049992Sbostic void 49150439Schristos /*ARGSUSED*/ 49250439Schristos doend(v, t) 49350439Schristos Char **v; 49450439Schristos struct command *t; 4951294Sbill { 49649992Sbostic if (!whyles) 49749992Sbostic stderror(ERR_NAME | ERR_NOTWHILE); 49850944Schristos btell(&whyles->w_end); 49949992Sbostic doagain(); 5001294Sbill } 5011294Sbill 50249992Sbostic void 50350439Schristos /*ARGSUSED*/ 50450439Schristos docontin(v, t) 50550439Schristos Char **v; 50650439Schristos struct command *t; 5071294Sbill { 50849992Sbostic if (!whyles) 50949992Sbostic stderror(ERR_NAME | ERR_NOTWHILE); 51049992Sbostic doagain(); 5111294Sbill } 5121294Sbill 51349992Sbostic static void 5141294Sbill doagain() 5151294Sbill { 51649992Sbostic /* Repeating a while is simple */ 51749992Sbostic if (whyles->w_fename == 0) { 51850944Schristos bseek(&whyles->w_start); 51949992Sbostic return; 52049992Sbostic } 52149992Sbostic /* 52249992Sbostic * The foreach variable list actually has a spurious word ")" at the end of 52349992Sbostic * the w_fe list. Thus we are at the of the list if one word beyond this 52449992Sbostic * is 0. 52549992Sbostic */ 52649992Sbostic if (!whyles->w_fe[1]) { 52750439Schristos dobreak(NULL, NULL); 52849992Sbostic return; 52949992Sbostic } 53049992Sbostic set(whyles->w_fename, Strsave(*whyles->w_fe++)); 53150944Schristos bseek(&whyles->w_start); 5321294Sbill } 5331294Sbill 53449992Sbostic void 5351294Sbill dorepeat(v, kp) 53649992Sbostic Char **v; 53749992Sbostic struct command *kp; 5381294Sbill { 53949992Sbostic register int i; 54050028Sbostic register sigset_t omask = 0; 5411294Sbill 54249992Sbostic i = getn(v[1]); 54349992Sbostic if (setintr) 54449992Sbostic omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 54549992Sbostic lshift(v, 2); 54649992Sbostic while (i > 0) { 5471294Sbill if (setintr) 54849992Sbostic (void) sigsetmask(omask); 54949992Sbostic reexecute(kp); 55049992Sbostic --i; 55149992Sbostic } 55249992Sbostic donefds(); 55349992Sbostic if (setintr) 55449992Sbostic (void) sigsetmask(omask); 5551294Sbill } 5561294Sbill 55749992Sbostic void 55850439Schristos /*ARGSUSED*/ 55950439Schristos doswbrk(v, t) 56050439Schristos Char **v; 56150439Schristos struct command *t; 5621294Sbill { 56350024Schristos search(T_BRKSW, 0, NULL); 5641294Sbill } 5651294Sbill 56649992Sbostic int 5671294Sbill srchx(cp) 56849992Sbostic register Char *cp; 5691294Sbill { 57049992Sbostic register struct srch *sp, *sp1, *sp2; 57149992Sbostic register i; 5721294Sbill 57349992Sbostic /* 57449992Sbostic * Binary search Sp1 is the beginning of the current search range. Sp2 is 57549992Sbostic * one past the end. 57649992Sbostic */ 57749992Sbostic for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 57849992Sbostic sp = sp1 + ((sp2 - sp1) >> 1); 57949992Sbostic if ((i = *cp - *sp->s_name) == 0 && 58049992Sbostic (i = Strcmp(cp, str2short(sp->s_name))) == 0) 58149992Sbostic return sp->s_value; 58249992Sbostic if (i < 0) 58349992Sbostic sp2 = sp; 58449992Sbostic else 58549992Sbostic sp1 = sp + 1; 58649992Sbostic } 58749992Sbostic return (-1); 5881294Sbill } 5891294Sbill 59049992Sbostic static Char Stype; 59149992Sbostic static Char *Sgoal; 5921294Sbill 5931294Sbill /*VARARGS2*/ 59449992Sbostic void 5951294Sbill search(type, level, goal) 59649992Sbostic int type; 59749992Sbostic register int level; 59849992Sbostic Char *goal; 5991294Sbill { 60049992Sbostic Char wordbuf[BUFSIZ]; 60149992Sbostic register Char *aword = wordbuf; 60249992Sbostic register Char *cp; 6031294Sbill 60449992Sbostic Stype = type; 60549992Sbostic Sgoal = goal; 60650944Schristos if (type == T_GOTO) { 60750944Schristos struct Ain a; 60850944Schristos a.type = F_SEEK; 60950944Schristos a.f_seek = 0; 61050944Schristos bseek(&a); 61150944Schristos } 61249992Sbostic do { 61350944Schristos if (intty && fseekp == feobp && aret == F_SEEK) 61450439Schristos (void) fprintf(cshout, "? "), (void) fflush(cshout); 61549992Sbostic aword[0] = 0; 61649992Sbostic (void) getword(aword); 61749992Sbostic switch (srchx(aword)) { 6181294Sbill 61949992Sbostic case T_ELSE: 62049992Sbostic if (level == 0 && type == T_IF) 62149992Sbostic return; 62249992Sbostic break; 6231294Sbill 62449992Sbostic case T_IF: 62549992Sbostic while (getword(aword)) 62649992Sbostic continue; 62749992Sbostic if ((type == T_IF || type == T_ELSE) && 62849992Sbostic eq(aword, STRthen)) 62949992Sbostic level++; 63049992Sbostic break; 6311294Sbill 63249992Sbostic case T_ENDIF: 63349992Sbostic if (type == T_IF || type == T_ELSE) 63449992Sbostic level--; 63549992Sbostic break; 6361294Sbill 63749992Sbostic case T_FOREACH: 63849992Sbostic case T_WHILE: 63949992Sbostic if (type == T_BREAK) 64049992Sbostic level++; 64149992Sbostic break; 6421294Sbill 64349992Sbostic case T_END: 64449992Sbostic if (type == T_BREAK) 64549992Sbostic level--; 64649992Sbostic break; 6471294Sbill 64849992Sbostic case T_SWITCH: 64949992Sbostic if (type == T_SWITCH || type == T_BRKSW) 65049992Sbostic level++; 65149992Sbostic break; 6521294Sbill 65349992Sbostic case T_ENDSW: 65449992Sbostic if (type == T_SWITCH || type == T_BRKSW) 65549992Sbostic level--; 65649992Sbostic break; 6571294Sbill 65849992Sbostic case T_LABEL: 65949992Sbostic if (type == T_GOTO && getword(aword) && eq(aword, goal)) 66049992Sbostic level = -1; 66149992Sbostic break; 6621294Sbill 66349992Sbostic default: 66449992Sbostic if (type != T_GOTO && (type != T_SWITCH || level != 0)) 66549992Sbostic break; 66649992Sbostic if (lastchr(aword) != ':') 66749992Sbostic break; 66849992Sbostic aword[Strlen(aword) - 1] = 0; 66949992Sbostic if (type == T_GOTO && eq(aword, goal) || 67049992Sbostic type == T_SWITCH && eq(aword, STRdefault)) 67149992Sbostic level = -1; 67249992Sbostic break; 6731294Sbill 67449992Sbostic case T_CASE: 67549992Sbostic if (type != T_SWITCH || level != 0) 67649992Sbostic break; 67749992Sbostic (void) getword(aword); 67849992Sbostic if (lastchr(aword) == ':') 67949992Sbostic aword[Strlen(aword) - 1] = 0; 68049992Sbostic cp = strip(Dfix1(aword)); 68149992Sbostic if (Gmatch(goal, cp)) 68249992Sbostic level = -1; 68349992Sbostic xfree((ptr_t) cp); 68449992Sbostic break; 6851294Sbill 68649992Sbostic case T_DEFAULT: 68749992Sbostic if (type == T_SWITCH && level == 0) 68849992Sbostic level = -1; 68949992Sbostic break; 69049992Sbostic } 69149992Sbostic (void) getword(NULL); 69249992Sbostic } while (level >= 0); 6931294Sbill } 6941294Sbill 69549992Sbostic static int 6961294Sbill getword(wp) 69749992Sbostic register Char *wp; 6981294Sbill { 69949992Sbostic register int found = 0; 70049992Sbostic register int c, d; 70149992Sbostic int kwd = 0; 70249992Sbostic Char *owp = wp; 7031294Sbill 70449992Sbostic c = readc(1); 70549992Sbostic d = 0; 70649992Sbostic do { 70749992Sbostic while (c == ' ' || c == '\t') 70849992Sbostic c = readc(1); 70949992Sbostic if (c == '#') 71049992Sbostic do 71149992Sbostic c = readc(1); 71249992Sbostic while (c >= 0 && c != '\n'); 71349992Sbostic if (c < 0) 71449992Sbostic goto past; 71549992Sbostic if (c == '\n') { 71649992Sbostic if (wp) 71749992Sbostic break; 71849992Sbostic return (0); 71949992Sbostic } 72049992Sbostic unreadc(c); 72149992Sbostic found = 1; 7221294Sbill do { 72349992Sbostic c = readc(1); 72449992Sbostic if (c == '\\' && (c = readc(1)) == '\n') 72549992Sbostic c = ' '; 72649992Sbostic if (c == '\'' || c == '"') 72749992Sbostic if (d == 0) 72849992Sbostic d = c; 72949992Sbostic else if (d == c) 73049992Sbostic d = 0; 73149992Sbostic if (c < 0) 73249992Sbostic goto past; 73349992Sbostic if (wp) { 73449992Sbostic *wp++ = c; 73549992Sbostic *wp = 0; /* end the string b4 test */ 73649992Sbostic } 73749992Sbostic } while ((d || !(kwd = keyword(owp)) && c != ' ' 73849992Sbostic && c != '\t') && c != '\n'); 73949992Sbostic } while (wp == 0); 74049992Sbostic 74149992Sbostic /* 74249992Sbostic * if we have read a keyword ( "if", "switch" or "while" ) then we do not 74349992Sbostic * need to unreadc the look-ahead char 74449992Sbostic */ 74549992Sbostic if (!kwd) { 7461294Sbill unreadc(c); 7471294Sbill if (found) 74849992Sbostic *--wp = 0; 74949992Sbostic } 7501294Sbill 75149992Sbostic return (found); 75249992Sbostic 7531294Sbill past: 75449992Sbostic switch (Stype) { 7551294Sbill 75649992Sbostic case T_IF: 75749992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); 7581294Sbill 75949992Sbostic case T_ELSE: 76049992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "endif"); 7611294Sbill 76249992Sbostic case T_BRKSW: 76349992Sbostic case T_SWITCH: 76449992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); 7651294Sbill 76649992Sbostic case T_BREAK: 76749992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "end"); 7681294Sbill 76949992Sbostic case T_GOTO: 770*51589Schristos setname(vis_str(Sgoal)); 77149992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "label"); 77249992Sbostic } 77349992Sbostic /* NOTREACHED */ 77449992Sbostic return (0); 7751294Sbill } 7761294Sbill 77749992Sbostic /* 77849992Sbostic * keyword(wp) determines if wp is one of the built-n functions if, 77949992Sbostic * switch or while. It seems that when an if statement looks like 78049992Sbostic * "if(" then getword above sucks in the '(' and so the search routine 78149992Sbostic * never finds what it is scanning for. Rather than rewrite doword, I hack 78249992Sbostic * in a test to see if the string forms a keyword. Then doword stops 78349992Sbostic * and returns the word "if" -strike 78449992Sbostic */ 78549992Sbostic 78649992Sbostic static int 78749992Sbostic keyword(wp) 78849992Sbostic Char *wp; 7891294Sbill { 79049992Sbostic static Char STRif[] = {'i', 'f', '\0'}; 79149992Sbostic static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; 79249992Sbostic static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; 7931294Sbill 79449992Sbostic if (!wp) 79549992Sbostic return (0); 79649992Sbostic 79749992Sbostic if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) 79849992Sbostic || (Strcmp(wp, STRswitch) == 0)) 79949992Sbostic return (1); 80049992Sbostic 80149992Sbostic return (0); 8021294Sbill } 8031294Sbill 80449992Sbostic static void 80549992Sbostic toend() 80649992Sbostic { 80751378Schristos if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) { 80849992Sbostic search(T_BREAK, 0, NULL); 80950944Schristos btell(&whyles->w_end); 81050944Schristos whyles->w_end.f_seek--; 81149992Sbostic } 81249992Sbostic else 81350944Schristos bseek(&whyles->w_end); 81449992Sbostic wfree(); 81549992Sbostic } 81649992Sbostic 81749992Sbostic void 8181294Sbill wfree() 8191294Sbill { 82050944Schristos struct Ain o; 82150944Schristos struct whyle *nwp; 82251527Schristos 82350944Schristos btell(&o); 8241294Sbill 82550944Schristos for (; whyles; whyles = nwp) { 82649992Sbostic register struct whyle *wp = whyles; 82750944Schristos nwp = wp->w_next; 82851527Schristos 82951527Schristos /* 83051527Schristos * We free loops that have different seek types. 83151527Schristos */ 83251527Schristos if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type && 83351527Schristos wp->w_start.type == o.type) { 83451527Schristos if (wp->w_end.type == F_SEEK) { 83551527Schristos if (o.f_seek >= wp->w_start.f_seek && 83651527Schristos (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) 83751527Schristos break; 83851527Schristos } 83951527Schristos else { 84051527Schristos if (o.a_seek >= wp->w_start.a_seek && 84151527Schristos (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek)) 84251527Schristos break; 84351527Schristos } 84451420Schristos } 84551527Schristos 84649992Sbostic if (wp->w_fe0) 84749992Sbostic blkfree(wp->w_fe0); 84849992Sbostic if (wp->w_fename) 84949992Sbostic xfree((ptr_t) wp->w_fename); 85049992Sbostic xfree((ptr_t) wp); 85149992Sbostic } 8521294Sbill } 8531294Sbill 85449992Sbostic void 85550439Schristos /*ARGSUSED*/ 85650439Schristos doecho(v, t) 85750439Schristos Char **v; 85850439Schristos struct command *t; 8591294Sbill { 86049992Sbostic xecho(' ', v); 8611294Sbill } 8621294Sbill 86349992Sbostic void 86450439Schristos /*ARGSUSED*/ 86550439Schristos doglob(v, t) 86650439Schristos Char **v; 86750439Schristos struct command *t; 8681294Sbill { 86949992Sbostic xecho(0, v); 87050439Schristos (void) fflush(cshout); 8711294Sbill } 8721294Sbill 87349992Sbostic static void 87449992Sbostic xecho(sep, v) 87550024Schristos int sep; 87649992Sbostic register Char **v; 8771294Sbill { 87849992Sbostic register Char *cp; 87949992Sbostic int nonl = 0; 8801294Sbill 88149992Sbostic if (setintr) 88250028Sbostic (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 88349992Sbostic v++; 88449992Sbostic if (*v == 0) 88549992Sbostic return; 88649992Sbostic gflag = 0, tglob(v); 88749992Sbostic if (gflag) { 88849992Sbostic v = globall(v); 88949992Sbostic if (v == 0) 89049992Sbostic stderror(ERR_NAME | ERR_NOMATCH); 89149992Sbostic } 89249992Sbostic else { 89349992Sbostic v = gargv = saveblk(v); 89449992Sbostic trim(v); 89549992Sbostic } 89649992Sbostic if (sep == ' ' && *v && eq(*v, STRmn)) 89749992Sbostic nonl++, v++; 89849992Sbostic while (cp = *v++) { 89949992Sbostic register int c; 9001294Sbill 90149992Sbostic while (c = *cp++) 902*51589Schristos (void) vis_fputc(c | QUOTE, cshout); 90349992Sbostic 90449992Sbostic if (*v) 905*51589Schristos (void) vis_fputc(sep | QUOTE, cshout); 90649992Sbostic } 90749992Sbostic if (sep && nonl == 0) 90850439Schristos (void) fputc('\n', cshout); 90949992Sbostic else 91050439Schristos (void) fflush(cshout); 91149992Sbostic if (setintr) 91249992Sbostic (void) sigblock(sigmask(SIGINT)); 91349992Sbostic if (gargv) 91449992Sbostic blkfree(gargv), gargv = 0; 9151294Sbill } 9161294Sbill 91749992Sbostic void 91850439Schristos /*ARGSUSED*/ 91950439Schristos dosetenv(v, t) 92050439Schristos Char **v; 92150439Schristos struct command *t; 9221294Sbill { 92349992Sbostic Char *vp, *lp; 9241294Sbill 92549992Sbostic v++; 92649992Sbostic if ((vp = *v++) == 0) { 92749992Sbostic register Char **ep; 92821753Sedward 92949992Sbostic if (setintr) 93050028Sbostic (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT)); 93149992Sbostic for (ep = STR_environ; *ep; ep++) 932*51589Schristos (void) fprintf(cshout, "%s\n", vis_str(*ep)); 93349992Sbostic return; 93449992Sbostic } 93549992Sbostic if ((lp = *v++) == 0) 93649992Sbostic lp = STRNULL; 93750746Schristos Setenv(vp, lp = globone(lp, G_APPEND)); 93849992Sbostic if (eq(vp, STRPATH)) { 93949992Sbostic importpath(lp); 94050439Schristos dohash(NULL, NULL); 94149992Sbostic } 94249992Sbostic else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { 94349992Sbostic #ifdef NLS 94449992Sbostic int k; 94549992Sbostic 94649992Sbostic (void) setlocale(LC_ALL, ""); 94751437Sleres for (k = 0200; k <= 0377 && !Isprint(k); k++) 94851437Sleres continue; 94949992Sbostic AsciiOnly = k > 0377; 95049992Sbostic #else 95149992Sbostic AsciiOnly = 0; 95249992Sbostic #endif /* NLS */ 95349992Sbostic } 95449992Sbostic xfree((ptr_t) lp); 9551294Sbill } 9561294Sbill 95749992Sbostic void 95850439Schristos /*ARGSUSED*/ 95950439Schristos dounsetenv(v, t) 96050439Schristos Char **v; 96150439Schristos struct command *t; 9621294Sbill { 96349992Sbostic Char **ep, *p, *n; 96449992Sbostic int i, maxi; 96549992Sbostic static Char *name = NULL; 9661294Sbill 96749992Sbostic if (name) 96849992Sbostic xfree((ptr_t) name); 96949992Sbostic /* 97049992Sbostic * Find the longest environment variable 97149992Sbostic */ 97249992Sbostic for (maxi = 0, ep = STR_environ; *ep; ep++) { 97351437Sleres for (i = 0, p = *ep; *p && *p != '='; p++, i++) 97451437Sleres continue; 97549992Sbostic if (i > maxi) 97649992Sbostic maxi = i; 97749992Sbostic } 97849992Sbostic 97949992Sbostic name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); 98049992Sbostic 98150160Schristos while (++v && *v) 98250160Schristos for (maxi = 1; maxi;) 98350160Schristos for (maxi = 0, ep = STR_environ; *ep; ep++) { 98451437Sleres for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) 98551437Sleres continue; 98650160Schristos *n = '\0'; 98750160Schristos if (!Gmatch(name, *v)) 98850160Schristos continue; 98950160Schristos maxi = 1; 99050160Schristos if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { 99149992Sbostic #ifdef NLS 99250160Schristos int k; 99349992Sbostic 99450160Schristos (void) setlocale(LC_ALL, ""); 99551437Sleres for (k = 0200; k <= 0377 && !Isprint(k); k++) 99651437Sleres continue; 99750160Schristos AsciiOnly = k > 0377; 99849992Sbostic #else 99950160Schristos AsciiOnly = getenv("LANG") == NULL && 100050160Schristos getenv("LC_CTYPE") == NULL; 100149992Sbostic #endif /* NLS */ 100250160Schristos } 100350160Schristos /* 100450160Schristos * Delete name, and start again cause the environment changes 100550160Schristos */ 100650160Schristos Unsetenv(name); 100750160Schristos break; 100849992Sbostic } 100950976Schristos xfree((ptr_t) name); 101050976Schristos name = NULL; 10111294Sbill } 10121294Sbill 101349992Sbostic void 101449992Sbostic Setenv(name, val) 101549992Sbostic Char *name, *val; 10161294Sbill { 101749992Sbostic register Char **ep = STR_environ; 101849992Sbostic register Char *cp, *dp; 101949992Sbostic Char *blk[2]; 102049992Sbostic Char **oep = ep; 10211294Sbill 102249992Sbostic 102349992Sbostic for (; *ep; ep++) { 102449992Sbostic for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 102549992Sbostic continue; 102649992Sbostic if (*cp != 0 || *dp != '=') 102749992Sbostic continue; 102849992Sbostic cp = Strspl(STRequal, val); 102949992Sbostic xfree((ptr_t) * ep); 103049992Sbostic *ep = strip(Strspl(name, cp)); 103149992Sbostic xfree((ptr_t) cp); 103249992Sbostic blkfree((Char **) environ); 103349992Sbostic environ = short2blk(STR_environ); 103449992Sbostic return; 103549992Sbostic } 103649992Sbostic cp = Strspl(name, STRequal); 103749992Sbostic blk[0] = strip(Strspl(cp, val)); 103849992Sbostic xfree((ptr_t) cp); 103949992Sbostic blk[1] = 0; 104049992Sbostic STR_environ = blkspl(STR_environ, blk); 104149992Sbostic blkfree((Char **) environ); 104249992Sbostic environ = short2blk(STR_environ); 104349992Sbostic xfree((ptr_t) oep); 10441294Sbill } 10451294Sbill 104649992Sbostic static void 104749992Sbostic Unsetenv(name) 104849992Sbostic Char *name; 10491294Sbill { 105049992Sbostic register Char **ep = STR_environ; 105149992Sbostic register Char *cp, *dp; 105249992Sbostic Char **oep = ep; 10531294Sbill 105449992Sbostic for (; *ep; ep++) { 105549992Sbostic for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 105649992Sbostic continue; 105749992Sbostic if (*cp != 0 || *dp != '=') 105849992Sbostic continue; 105949992Sbostic cp = *ep; 106049992Sbostic *ep = 0; 106149992Sbostic STR_environ = blkspl(STR_environ, ep + 1); 106249992Sbostic environ = short2blk(STR_environ); 106349992Sbostic *ep = cp; 106449992Sbostic xfree((ptr_t) cp); 106549992Sbostic xfree((ptr_t) oep); 106649992Sbostic return; 106749992Sbostic } 10681294Sbill } 10691294Sbill 107049992Sbostic void 107150439Schristos /*ARGSUSED*/ 107250439Schristos doumask(v, t) 107350439Schristos Char **v; 107450439Schristos struct command *t; 10751294Sbill { 107649992Sbostic register Char *cp = v[1]; 107749992Sbostic register int i; 10781294Sbill 107949992Sbostic if (cp == 0) { 108049992Sbostic i = umask(0); 108117519Sedward (void) umask(i); 108250439Schristos (void) fprintf(cshout, "%o\n", i); 108349992Sbostic return; 108449992Sbostic } 108549992Sbostic i = 0; 108649992Sbostic while (Isdigit(*cp) && *cp != '8' && *cp != '9') 108749992Sbostic i = i * 8 + *cp++ - '0'; 108849992Sbostic if (*cp || i < 0 || i > 0777) 108949992Sbostic stderror(ERR_NAME | ERR_MASK); 109049992Sbostic (void) umask(i); 10911294Sbill } 10921294Sbill 109349992Sbostic typedef int RLIM_TYPE; 10941294Sbill 109549992Sbostic static struct limits { 109649992Sbostic int limconst; 109749992Sbostic char *limname; 109849992Sbostic int limdiv; 109949992Sbostic char *limscale; 110049992Sbostic } limits[] = { 110151437Sleres RLIMIT_CPU, "cputime", 1, "seconds", 110249992Sbostic RLIMIT_FSIZE, "filesize", 1024, "kbytes", 110349992Sbostic RLIMIT_DATA, "datasize", 1024, "kbytes", 110449992Sbostic RLIMIT_STACK, "stacksize", 1024, "kbytes", 110549992Sbostic RLIMIT_CORE, "coredumpsize", 1024, "kbytes", 110651437Sleres RLIMIT_RSS, "memoryuse", 1024, "kbytes", 110750024Schristos RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes", 110850024Schristos RLIMIT_NPROC, "maxproc", 1, "", 110950024Schristos RLIMIT_OFILE, "openfiles", 1, "", 111051437Sleres -1, NULL, 0, NULL 11111294Sbill }; 11121294Sbill 111349992Sbostic static struct limits *findlim(); 111449992Sbostic static RLIM_TYPE getval(); 111549992Sbostic static void limtail(); 111649992Sbostic static void plim(); 111749992Sbostic static int setlim(); 111849992Sbostic 111949992Sbostic static struct limits * 11201294Sbill findlim(cp) 112149992Sbostic Char *cp; 11221294Sbill { 112349992Sbostic register struct limits *lp, *res; 11241294Sbill 112549992Sbostic res = (struct limits *) NULL; 112649992Sbostic for (lp = limits; lp->limconst >= 0; lp++) 112749992Sbostic if (prefix(cp, str2short(lp->limname))) { 112849992Sbostic if (res) 112949992Sbostic stderror(ERR_NAME | ERR_AMBIG); 113049992Sbostic res = lp; 113149992Sbostic } 113249992Sbostic if (res) 113349992Sbostic return (res); 113449992Sbostic stderror(ERR_NAME | ERR_LIMIT); 113549992Sbostic /* NOTREACHED */ 113649992Sbostic return (0); 11371294Sbill } 11381294Sbill 113949992Sbostic void 114050439Schristos /*ARGSUSED*/ 114150439Schristos dolimit(v, t) 114250439Schristos Char **v; 114350439Schristos struct command *t; 11441294Sbill { 114549992Sbostic register struct limits *lp; 114649992Sbostic register RLIM_TYPE limit; 114749992Sbostic char hard = 0; 11481294Sbill 114949992Sbostic v++; 115049992Sbostic if (*v && eq(*v, STRmh)) { 115149992Sbostic hard = 1; 11521294Sbill v++; 115349992Sbostic } 115449992Sbostic if (*v == 0) { 115549992Sbostic for (lp = limits; lp->limconst >= 0; lp++) 115649992Sbostic plim(lp, hard); 115749992Sbostic return; 115849992Sbostic } 115949992Sbostic lp = findlim(v[0]); 116049992Sbostic if (v[1] == 0) { 116149992Sbostic plim(lp, hard); 116249992Sbostic return; 116349992Sbostic } 116449992Sbostic limit = getval(lp, v + 1); 116549992Sbostic if (setlim(lp, hard, limit) < 0) 116649992Sbostic stderror(ERR_SILENT); 11671294Sbill } 11681294Sbill 116949992Sbostic static RLIM_TYPE 11701294Sbill getval(lp, v) 117149992Sbostic register struct limits *lp; 117249992Sbostic Char **v; 11731294Sbill { 117449992Sbostic register float f; 117549992Sbostic double atof(); 117649992Sbostic Char *cp = *v++; 11771294Sbill 117849992Sbostic f = atof(short2str(cp)); 117949992Sbostic 118049992Sbostic while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 118149992Sbostic cp++; 118249992Sbostic if (*cp == 0) { 118349992Sbostic if (*v == 0) 118449992Sbostic return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv)); 118549992Sbostic cp = *v; 118649992Sbostic } 118749992Sbostic switch (*cp) { 118849992Sbostic case ':': 118949992Sbostic if (lp->limconst != RLIMIT_CPU) 119049992Sbostic goto badscal; 119149992Sbostic return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1)))); 119249992Sbostic case 'h': 119349992Sbostic if (lp->limconst != RLIMIT_CPU) 119449992Sbostic goto badscal; 119549992Sbostic limtail(cp, "hours"); 119649992Sbostic f *= 3600.0; 119749992Sbostic break; 119849992Sbostic case 'm': 119949992Sbostic if (lp->limconst == RLIMIT_CPU) { 120049992Sbostic limtail(cp, "minutes"); 120149992Sbostic f *= 60.0; 120249992Sbostic break; 12031294Sbill } 120449992Sbostic *cp = 'm'; 120549992Sbostic limtail(cp, "megabytes"); 120649992Sbostic f *= 1024.0 * 1024.0; 120749992Sbostic break; 120849992Sbostic case 's': 120949992Sbostic if (lp->limconst != RLIMIT_CPU) 121049992Sbostic goto badscal; 121149992Sbostic limtail(cp, "seconds"); 121249992Sbostic break; 121349992Sbostic case 'M': 121449992Sbostic if (lp->limconst == RLIMIT_CPU) 121549992Sbostic goto badscal; 121649992Sbostic *cp = 'm'; 121749992Sbostic limtail(cp, "megabytes"); 121849992Sbostic f *= 1024.0 * 1024.0; 121949992Sbostic break; 122049992Sbostic case 'k': 122149992Sbostic if (lp->limconst == RLIMIT_CPU) 122249992Sbostic goto badscal; 122349992Sbostic limtail(cp, "kbytes"); 122449992Sbostic f *= 1024.0; 122549992Sbostic break; 122649992Sbostic case 'u': 122749992Sbostic limtail(cp, "unlimited"); 122849992Sbostic return (RLIM_INFINITY); 122949992Sbostic default: 12301294Sbill badscal: 123149992Sbostic stderror(ERR_NAME | ERR_SCALEF); 123249992Sbostic } 123350944Schristos if ((f + 0.5) >= (float) 0x7fffffff || (f + 0.5) < (float) 0x80000000) 123450944Schristos stderror(ERR_NAME | ERR_SCALEF); 123549992Sbostic return ((RLIM_TYPE) (f + 0.5)); 12361294Sbill } 12371294Sbill 123849992Sbostic static void 123949992Sbostic limtail(cp, str) 124049992Sbostic Char *cp; 124149992Sbostic char *str; 12421294Sbill { 124349992Sbostic while (*cp && *cp == *str) 124449992Sbostic cp++, str++; 124549992Sbostic if (*cp) 124649992Sbostic stderror(ERR_BADSCALE, str); 12471294Sbill } 12481294Sbill 124949992Sbostic 125049992Sbostic /*ARGSUSED*/ 125149992Sbostic static void 125218539Sedward plim(lp, hard) 125349992Sbostic register struct limits *lp; 125449992Sbostic Char hard; 12551294Sbill { 125649992Sbostic struct rlimit rlim; 125749992Sbostic RLIM_TYPE limit; 12581294Sbill 125950439Schristos (void) fprintf(cshout, "%s \t", lp->limname); 126049992Sbostic 126149992Sbostic (void) getrlimit(lp->limconst, &rlim); 126249992Sbostic limit = hard ? rlim.rlim_max : rlim.rlim_cur; 126349992Sbostic 126449992Sbostic if (limit == RLIM_INFINITY) 126550439Schristos (void) fprintf(cshout, "unlimited"); 126649992Sbostic else if (lp->limconst == RLIMIT_CPU) 126749992Sbostic psecs((long) limit); 126849992Sbostic else 126951437Sleres (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), 127050439Schristos lp->limscale); 127150439Schristos (void) fputc('\n', cshout); 12721294Sbill } 12731294Sbill 127449992Sbostic void 127550439Schristos /*ARGSUSED*/ 127650439Schristos dounlimit(v, t) 127750439Schristos Char **v; 127850439Schristos struct command *t; 12791294Sbill { 128049992Sbostic register struct limits *lp; 128149992Sbostic int lerr = 0; 128249992Sbostic Char hard = 0; 12831294Sbill 128449992Sbostic v++; 128549992Sbostic if (*v && eq(*v, STRmh)) { 128649992Sbostic hard = 1; 12871294Sbill v++; 128849992Sbostic } 128949992Sbostic if (*v == 0) { 129049992Sbostic for (lp = limits; lp->limconst >= 0; lp++) 129149992Sbostic if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 129249992Sbostic lerr++; 129349992Sbostic if (lerr) 129449992Sbostic stderror(ERR_SILENT); 129549992Sbostic return; 129649992Sbostic } 129749992Sbostic while (*v) { 129849992Sbostic lp = findlim(*v++); 129949992Sbostic if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 130049992Sbostic stderror(ERR_SILENT); 130149992Sbostic } 13021294Sbill } 13031294Sbill 130449992Sbostic static int 130518539Sedward setlim(lp, hard, limit) 130649992Sbostic register struct limits *lp; 130749992Sbostic Char hard; 130849992Sbostic RLIM_TYPE limit; 13091294Sbill { 131049992Sbostic struct rlimit rlim; 13111294Sbill 131249992Sbostic (void) getrlimit(lp->limconst, &rlim); 131349992Sbostic 131449992Sbostic if (hard) 131549992Sbostic rlim.rlim_max = limit; 131649992Sbostic else if (limit == RLIM_INFINITY && geteuid() != 0) 131749992Sbostic rlim.rlim_cur = rlim.rlim_max; 131849992Sbostic else 131949992Sbostic rlim.rlim_cur = limit; 132049992Sbostic 132149992Sbostic if (setrlimit(lp->limconst, &rlim) < 0) { 132250439Schristos (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, 132350439Schristos limit == RLIM_INFINITY ? "remove" : "set", 132450439Schristos hard ? " hard" : ""); 132549992Sbostic return (-1); 132649992Sbostic } 132749992Sbostic return (0); 13281294Sbill } 13291294Sbill 133049992Sbostic void 133150439Schristos /*ARGSUSED*/ 133250439Schristos dosuspend(v, t) 133350439Schristos Char **v; 133450439Schristos struct command *t; 13351294Sbill { 133649992Sbostic int ctpgrp; 13371294Sbill 133849992Sbostic void (*old) (); 133949992Sbostic 134049992Sbostic if (loginsh) 134149992Sbostic stderror(ERR_SUSPLOG); 134249992Sbostic untty(); 134349992Sbostic 134449992Sbostic old = signal(SIGTSTP, SIG_DFL); 134549992Sbostic (void) kill(0, SIGTSTP); 134649992Sbostic /* the shell stops here */ 134749992Sbostic (void) signal(SIGTSTP, old); 134849992Sbostic 134949992Sbostic if (tpgrp != -1) { 135049992Sbostic ctpgrp = tcgetpgrp(FSHTTY); 135150439Schristos while (ctpgrp != opgrp) { 135249992Sbostic old = signal(SIGTTIN, SIG_DFL); 135349992Sbostic (void) kill(0, SIGTTIN); 135449992Sbostic (void) signal(SIGTTIN, old); 13551294Sbill } 135649992Sbostic (void) setpgid(0, shpgrp); 135749992Sbostic (void) tcsetpgrp(FSHTTY, shpgrp); 135849992Sbostic } 13591294Sbill } 13601294Sbill 136149992Sbostic /* This is the dreaded EVAL built-in. 136249992Sbostic * If you don't fiddle with file descriptors, and reset didfds, 136349992Sbostic * this command will either ignore redirection inside or outside 136449992Sbostic * its aguments, e.g. eval "date >x" vs. eval "date" >x 136549992Sbostic * The stuff here seems to work, but I did it by trial and error rather 136649992Sbostic * than really knowing what was going on. If tpgrp is zero, we are 136749992Sbostic * probably a background eval, e.g. "eval date &", and we want to 136849992Sbostic * make sure that any processes we start stay in our pgrp. 136949992Sbostic * This is also the case for "time eval date" -- stay in same pgrp. 137049992Sbostic * Otherwise, under stty tostop, processes will stop in the wrong 137149992Sbostic * pgrp, with no way for the shell to get them going again. -IAN! 137249992Sbostic */ 137350439Schristos static Char **gv = NULL; 137449992Sbostic void 137550439Schristos /*ARGSUSED*/ 137650439Schristos doeval(v, t) 137750439Schristos Char **v; 137850439Schristos struct command *t; 13791294Sbill { 138049992Sbostic Char **oevalvec; 138149992Sbostic Char *oevalp; 138249992Sbostic int odidfds; 138349992Sbostic jmp_buf osetexit; 138449992Sbostic int my_reenter; 138550439Schristos Char **savegv = gv; 138649992Sbostic int saveIN; 138749992Sbostic int saveOUT; 138850439Schristos int saveERR; 138949992Sbostic int oSHIN; 139049992Sbostic int oSHOUT; 139150439Schristos int oSHERR; 13921294Sbill 139349992Sbostic oevalvec = evalvec; 139449992Sbostic oevalp = evalp; 139549992Sbostic odidfds = didfds; 139649992Sbostic oSHIN = SHIN; 139749992Sbostic oSHOUT = SHOUT; 139850439Schristos oSHERR = SHERR; 139949992Sbostic 140049992Sbostic v++; 140149992Sbostic if (*v == 0) 140249992Sbostic return; 140349992Sbostic gflag = 0, tglob(v); 140449992Sbostic if (gflag) { 140549992Sbostic gv = v = globall(v); 140649992Sbostic gargv = 0; 140749992Sbostic if (v == 0) 140849992Sbostic stderror(ERR_NOMATCH); 140949992Sbostic v = copyblk(v); 141049992Sbostic } 141149992Sbostic else { 141250024Schristos gv = NULL; 141349992Sbostic v = copyblk(v); 141449992Sbostic trim(v); 141549992Sbostic } 141649992Sbostic 141749992Sbostic saveIN = dcopy(SHIN, -1); 141849992Sbostic saveOUT = dcopy(SHOUT, -1); 141950439Schristos saveERR = dcopy(SHERR, -1); 142049992Sbostic 142149992Sbostic getexit(osetexit); 142249992Sbostic 142349992Sbostic if ((my_reenter = setexit()) == 0) { 142449992Sbostic evalvec = v; 142549992Sbostic evalp = 0; 142649992Sbostic SHIN = dcopy(0, -1); 142749992Sbostic SHOUT = dcopy(1, -1); 142850439Schristos SHERR = dcopy(2, -1); 142949992Sbostic didfds = 0; 143049992Sbostic process(0); 143149992Sbostic } 143249992Sbostic 143349992Sbostic evalvec = oevalvec; 143449992Sbostic evalp = oevalp; 143549992Sbostic doneinp = 0; 143649992Sbostic didfds = odidfds; 143749992Sbostic (void) close(SHIN); 143849992Sbostic (void) close(SHOUT); 143950439Schristos (void) close(SHERR); 144049992Sbostic SHIN = dmove(saveIN, oSHIN); 144149992Sbostic SHOUT = dmove(saveOUT, oSHOUT); 144250439Schristos SHERR = dmove(saveERR, oSHERR); 144349992Sbostic if (gv) 144450439Schristos blkfree(gv), gv = NULL; 144549992Sbostic resexit(osetexit); 144650439Schristos gv = savegv; 144749992Sbostic if (my_reenter) 144849992Sbostic stderror(ERR_SILENT); 14491294Sbill } 145050639Schristos 145150639Schristos void 145250639Schristos /*ARGSUSED*/ 145350639Schristos doprintf(v, t) 145450639Schristos Char **v; 145550639Schristos struct command *t; 145650639Schristos { 145750639Schristos char **c; 145850639Schristos extern int progprintf __P((int, char **)); 145950639Schristos int ret; 146051437Sleres 146150639Schristos ret = progprintf(blklen(v), c = short2blk(v)); 146250639Schristos 146350639Schristos blkfree((Char **) c); 146450639Schristos if (ret) 146550639Schristos stderror(ERR_SILENT); 146650639Schristos } 1467