1*17519Sedward #ifndef lint 2*17519Sedward static char *sccsid = "@(#)func.c 4.13 (Berkeley) 12/13/84"; 3*17519Sedward #endif 41294Sbill 51294Sbill #include "sh.h" 61294Sbill #include <sys/ioctl.h> 71294Sbill 81294Sbill /* 91294Sbill * C shell 101294Sbill */ 111294Sbill 121294Sbill struct biltins * 131294Sbill isbfunc(t) 14*17519Sedward struct command *t; 151294Sbill { 161294Sbill register char *cp = t->t_dcom[0]; 17*17519Sedward register struct biltins *bp, *bp1, *bp2; 181294Sbill int dolabel(), dofg1(), dobg1(); 191294Sbill static struct biltins label = { "", dolabel, 0, 0 }; 201294Sbill static struct biltins foregnd = { "%job", dofg1, 0, 0 }; 211294Sbill static struct biltins backgnd = { "%job &", dobg1, 0, 0 }; 221294Sbill 231294Sbill if (lastchr(cp) == ':') { 241294Sbill label.bname = cp; 251294Sbill return (&label); 261294Sbill } 271294Sbill if (*cp == '%') { 281294Sbill if (t->t_dflg & FAND) { 291294Sbill t->t_dflg &= ~FAND; 301294Sbill backgnd.bname = cp; 311294Sbill return (&backgnd); 32*17519Sedward } 331294Sbill foregnd.bname = cp; 341294Sbill return (&foregnd); 351294Sbill } 36*17519Sedward /* 37*17519Sedward * Binary search 38*17519Sedward * Bp1 is the beginning of the current search range. 39*17519Sedward * Bp2 is one past the end. 40*17519Sedward */ 41*17519Sedward for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 42*17519Sedward register i; 43*17519Sedward 44*17519Sedward bp = bp1 + (bp2 - bp1 >> 1); 45*17519Sedward if ((i = *cp - *bp->bname) == 0 && 46*17519Sedward (i = strcmp(cp, bp->bname)) == 0) 47*17519Sedward return bp; 48*17519Sedward if (i < 0) 49*17519Sedward bp2 = bp; 50*17519Sedward else 51*17519Sedward bp1 = bp + 1; 521294Sbill } 531294Sbill return (0); 541294Sbill } 551294Sbill 561294Sbill func(t, bp) 571294Sbill register struct command *t; 581294Sbill register struct biltins *bp; 591294Sbill { 601294Sbill int i; 611294Sbill 621294Sbill xechoit(t->t_dcom); 631294Sbill setname(bp->bname); 641294Sbill i = blklen(t->t_dcom) - 1; 651294Sbill if (i < bp->minargs) 661294Sbill bferr("Too few arguments"); 671294Sbill if (i > bp->maxargs) 681294Sbill bferr("Too many arguments"); 691294Sbill (*bp->bfunct)(t->t_dcom, t); 701294Sbill } 711294Sbill 721294Sbill dolabel() 731294Sbill { 741294Sbill 751294Sbill } 761294Sbill 771294Sbill doonintr(v) 781294Sbill char **v; 791294Sbill { 801294Sbill register char *cp; 811294Sbill register char *vv = v[1]; 821294Sbill 831294Sbill if (parintr == SIG_IGN) 841294Sbill return; 851294Sbill if (setintr && intty) 861294Sbill bferr("Can't from terminal"); 871294Sbill cp = gointr, gointr = 0, xfree(cp); 881294Sbill if (vv == 0) { 891294Sbill if (setintr) 90*17519Sedward (void) sigblock(sigmask(SIGINT)); 911294Sbill else 92*17519Sedward (void) signal(SIGINT, SIG_DFL); 931294Sbill gointr = 0; 941294Sbill } else if (eq((vv = strip(vv)), "-")) { 95*17519Sedward (void) signal(SIGINT, SIG_IGN); 961294Sbill gointr = "-"; 971294Sbill } else { 981294Sbill gointr = savestr(vv); 99*17519Sedward (void) signal(SIGINT, pintr); 1001294Sbill } 1011294Sbill } 1021294Sbill 1031294Sbill donohup() 1041294Sbill { 1051294Sbill 1061294Sbill if (intty) 1071294Sbill bferr("Can't from terminal"); 1081294Sbill if (setintr == 0) { 109*17519Sedward (void) signal(SIGHUP, SIG_IGN); 1101294Sbill #ifdef CC 1111294Sbill submit(getpid()); 1121294Sbill #endif 1131294Sbill } 1141294Sbill } 1151294Sbill 1161294Sbill dozip() 1171294Sbill { 1181294Sbill 1191294Sbill ; 1201294Sbill } 1211294Sbill 1221294Sbill prvars() 1231294Sbill { 1241294Sbill 1251294Sbill plist(&shvhed); 1261294Sbill } 1271294Sbill 1281294Sbill doalias(v) 1291294Sbill register char **v; 1301294Sbill { 1311294Sbill register struct varent *vp; 1321294Sbill register char *p; 1331294Sbill 1341294Sbill v++; 1351294Sbill p = *v++; 1361294Sbill if (p == 0) 1371294Sbill plist(&aliases); 1381294Sbill else if (*v == 0) { 1391294Sbill vp = adrof1(strip(p), &aliases); 1401294Sbill if (vp) 1411294Sbill blkpr(vp->vec), printf("\n"); 1421294Sbill } else { 1431294Sbill if (eq(p, "alias") || eq(p, "unalias")) { 1441294Sbill setname(p); 1451294Sbill bferr("Too dangerous to alias that"); 1461294Sbill } 1471294Sbill set1(strip(p), saveblk(v), &aliases); 1481294Sbill } 1491294Sbill } 1501294Sbill 1511294Sbill unalias(v) 1521294Sbill char **v; 1531294Sbill { 1541294Sbill 1551294Sbill unset1(v, &aliases); 1561294Sbill } 1571294Sbill 1581294Sbill dologout() 1591294Sbill { 1601294Sbill 1611294Sbill islogin(); 1621294Sbill goodbye(); 1631294Sbill } 1641294Sbill 1651294Sbill dologin(v) 1661294Sbill char **v; 1671294Sbill { 1681294Sbill 1691294Sbill islogin(); 1704189Smckusic rechist(); 171*17519Sedward (void) signal(SIGTERM, parterm); 1721294Sbill execl("/bin/login", "login", v[1], 0); 1731294Sbill untty(); 1741294Sbill exit(1); 1751294Sbill } 1761294Sbill 17712996Ssam #ifdef NEWGRP 1781294Sbill donewgrp(v) 1791294Sbill char **v; 1801294Sbill { 1811294Sbill 1823908Sroot if (chkstop == 0 && setintr) 1833908Sroot panystop(0); 184*17519Sedward (void) signal(SIGTERM, parterm); 1851294Sbill execl("/bin/newgrp", "newgrp", v[1], 0); 1861294Sbill execl("/usr/bin/newgrp", "newgrp", v[1], 0); 1871294Sbill untty(); 1881294Sbill exit(1); 1891294Sbill } 19012996Ssam #endif 1911294Sbill 1921294Sbill islogin() 1931294Sbill { 1941294Sbill 1951294Sbill if (chkstop == 0 && setintr) 1961294Sbill panystop(0); 1971294Sbill if (loginsh) 1981294Sbill return; 1991294Sbill error("Not login shell"); 2001294Sbill } 2011294Sbill 2021294Sbill doif(v, kp) 2031294Sbill char **v; 2041294Sbill struct command *kp; 2051294Sbill { 2061294Sbill register int i; 2071294Sbill register char **vv; 2081294Sbill 2091294Sbill v++; 2101294Sbill i = exp(&v); 2111294Sbill vv = v; 2121294Sbill if (*vv == NOSTR) 2131294Sbill bferr("Empty if"); 2141294Sbill if (eq(*vv, "then")) { 2151294Sbill if (*++vv) 2161294Sbill bferr("Improper then"); 2171294Sbill setname("then"); 2181294Sbill /* 2191294Sbill * If expression was zero, then scan to else, 2201294Sbill * otherwise just fall into following code. 2211294Sbill */ 2221294Sbill if (!i) 2231294Sbill search(ZIF, 0); 2241294Sbill return; 2251294Sbill } 2261294Sbill /* 2271294Sbill * Simple command attached to this if. 2281294Sbill * Left shift the node in this tree, munging it 2291294Sbill * so we can reexecute it. 2301294Sbill */ 2311294Sbill if (i) { 2321294Sbill lshift(kp->t_dcom, vv - kp->t_dcom); 2331294Sbill reexecute(kp); 2341294Sbill donefds(); 2351294Sbill } 2361294Sbill } 2371294Sbill 2381294Sbill /* 2391294Sbill * Reexecute a command, being careful not 2401294Sbill * to redo i/o redirection, which is already set up. 2411294Sbill */ 2421294Sbill reexecute(kp) 2431294Sbill register struct command *kp; 2441294Sbill { 2451294Sbill 2461294Sbill kp->t_dflg &= FSAVE; 2471294Sbill kp->t_dflg |= FREDO; 2481294Sbill /* 2491294Sbill * If tty is still ours to arbitrate, arbitrate it; 2501294Sbill * otherwise dont even set pgrp's as the jobs would 2511294Sbill * then have no way to get the tty (we can't give it 2521294Sbill * to them, and our parent wouldn't know their pgrp, etc. 2531294Sbill */ 2541294Sbill execute(kp, tpgrp > 0 ? tpgrp : -1); 2551294Sbill } 2561294Sbill 2571294Sbill doelse() 2581294Sbill { 2591294Sbill 2601294Sbill search(ZELSE, 0); 2611294Sbill } 2621294Sbill 2631294Sbill dogoto(v) 2641294Sbill char **v; 2651294Sbill { 2661294Sbill register struct whyle *wp; 2671294Sbill char *lp; 2681294Sbill 2691294Sbill /* 2701294Sbill * While we still can, locate any unknown ends of existing loops. 2711294Sbill * This obscure code is the WORST result of the fact that we 2721294Sbill * don't really parse. 2731294Sbill */ 2741294Sbill for (wp = whyles; wp; wp = wp->w_next) 2751294Sbill if (wp->w_end == 0) { 2761294Sbill search(ZBREAK, 0); 2771294Sbill wp->w_end = btell(); 2781294Sbill } else 2791294Sbill bseek(wp->w_end); 2801294Sbill search(ZGOTO, 0, lp = globone(v[1])); 2811294Sbill xfree(lp); 2821294Sbill /* 2831294Sbill * Eliminate loops which were exited. 2841294Sbill */ 2851294Sbill wfree(); 2861294Sbill } 2871294Sbill 2881294Sbill doswitch(v) 2891294Sbill register char **v; 2901294Sbill { 2911294Sbill register char *cp, *lp; 2921294Sbill 2931294Sbill v++; 2941294Sbill if (!*v || *(*v++) != '(') 2951294Sbill goto syntax; 2961294Sbill cp = **v == ')' ? "" : *v++; 2971294Sbill if (*(*v++) != ')') 2981294Sbill v--; 2991294Sbill if (*v) 3001294Sbill syntax: 3011294Sbill error("Syntax error"); 3021294Sbill search(ZSWITCH, 0, lp = globone(cp)); 3031294Sbill xfree(lp); 3041294Sbill } 3051294Sbill 3061294Sbill dobreak() 3071294Sbill { 3081294Sbill 3091294Sbill if (whyles) 3101294Sbill toend(); 3111294Sbill else 3121294Sbill bferr("Not in while/foreach"); 3131294Sbill } 3141294Sbill 3151294Sbill doexit(v) 3161294Sbill char **v; 3171294Sbill { 3181294Sbill 3191294Sbill if (chkstop == 0) 3201294Sbill panystop(0); 3211294Sbill /* 3221294Sbill * Don't DEMAND parentheses here either. 3231294Sbill */ 3241294Sbill v++; 3251294Sbill if (*v) { 3261294Sbill set("status", putn(exp(&v))); 3271294Sbill if (*v) 3281294Sbill bferr("Expression syntax"); 3291294Sbill } 3301294Sbill btoeof(); 3311294Sbill if (intty) 332*17519Sedward (void) close(SHIN); 3331294Sbill } 3341294Sbill 3351294Sbill doforeach(v) 3361294Sbill register char **v; 3371294Sbill { 3381294Sbill register char *cp; 3391294Sbill register struct whyle *nwp; 3401294Sbill 3411294Sbill v++; 3421294Sbill cp = strip(*v); 3431294Sbill while (*cp && letter(*cp)) 3441294Sbill cp++; 3451294Sbill if (*cp || strlen(*v) >= 20) 3461294Sbill bferr("Invalid variable"); 3471294Sbill cp = *v++; 3481294Sbill if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 3491294Sbill bferr("Words not ()'ed"); 3501294Sbill v++; 351*17519Sedward gflag = 0, tglob(v); 3521294Sbill v = glob(v); 3531294Sbill if (v == 0) 3541294Sbill bferr("No match"); 3551294Sbill nwp = (struct whyle *) calloc(1, sizeof *nwp); 3561294Sbill nwp->w_fe = nwp->w_fe0 = v; gargv = 0; 3571294Sbill nwp->w_start = btell(); 3581294Sbill nwp->w_fename = savestr(cp); 3591294Sbill nwp->w_next = whyles; 3601294Sbill whyles = nwp; 3611294Sbill /* 3621294Sbill * Pre-read the loop so as to be more 3631294Sbill * comprehensible to a terminal user. 3641294Sbill */ 3651294Sbill if (intty) 3661294Sbill preread(); 3671294Sbill doagain(); 3681294Sbill } 3691294Sbill 3701294Sbill dowhile(v) 3711294Sbill char **v; 3721294Sbill { 3731294Sbill register int status; 3741294Sbill register bool again = whyles != 0 && whyles->w_start == lineloc && 3751294Sbill whyles->w_fename == 0; 3761294Sbill 3771294Sbill v++; 3781294Sbill /* 3791294Sbill * Implement prereading here also, taking care not to 3801294Sbill * evaluate the expression before the loop has been read up 3811294Sbill * from a terminal. 3821294Sbill */ 3831294Sbill if (intty && !again) 3841294Sbill status = !exp0(&v, 1); 3851294Sbill else 3861294Sbill status = !exp(&v); 3871294Sbill if (*v) 3881294Sbill bferr("Expression syntax"); 3891294Sbill if (!again) { 3901294Sbill register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp)); 3911294Sbill 3921294Sbill nwp->w_start = lineloc; 3931294Sbill nwp->w_end = 0; 3941294Sbill nwp->w_next = whyles; 3951294Sbill whyles = nwp; 3961294Sbill if (intty) { 3971294Sbill /* 3981294Sbill * The tty preread 3991294Sbill */ 4001294Sbill preread(); 4011294Sbill doagain(); 4021294Sbill return; 4031294Sbill } 4041294Sbill } 4051294Sbill if (status) 4061294Sbill /* We ain't gonna loop no more, no more! */ 4071294Sbill toend(); 4081294Sbill } 4091294Sbill 4101294Sbill preread() 4111294Sbill { 4121294Sbill 4131294Sbill whyles->w_end = -1; 4141294Sbill if (setintr) 415*17519Sedward (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 4161294Sbill search(ZBREAK, 0); 4171294Sbill if (setintr) 418*17519Sedward (void) sigblock(sigmask(SIGINT)); 4191294Sbill whyles->w_end = btell(); 4201294Sbill } 4211294Sbill 4221294Sbill doend() 4231294Sbill { 4241294Sbill 4251294Sbill if (!whyles) 4261294Sbill bferr("Not in while/foreach"); 4271294Sbill whyles->w_end = btell(); 4281294Sbill doagain(); 4291294Sbill } 4301294Sbill 4311294Sbill docontin() 4321294Sbill { 4331294Sbill 4341294Sbill if (!whyles) 4351294Sbill bferr("Not in while/foreach"); 4361294Sbill doagain(); 4371294Sbill } 4381294Sbill 4391294Sbill doagain() 4401294Sbill { 4411294Sbill 4421294Sbill /* Repeating a while is simple */ 4431294Sbill if (whyles->w_fename == 0) { 4441294Sbill bseek(whyles->w_start); 4451294Sbill return; 4461294Sbill } 4471294Sbill /* 4481294Sbill * The foreach variable list actually has a spurious word 4491294Sbill * ")" at the end of the w_fe list. Thus we are at the 4501294Sbill * of the list if one word beyond this is 0. 4511294Sbill */ 4521294Sbill if (!whyles->w_fe[1]) { 4531294Sbill dobreak(); 4541294Sbill return; 4551294Sbill } 4561294Sbill set(whyles->w_fename, savestr(*whyles->w_fe++)); 4571294Sbill bseek(whyles->w_start); 4581294Sbill } 4591294Sbill 4601294Sbill dorepeat(v, kp) 4611294Sbill char **v; 4621294Sbill struct command *kp; 4631294Sbill { 46417138Sralph register int i, omask; 4651294Sbill 4661294Sbill i = getn(v[1]); 4671294Sbill if (setintr) 46817138Sralph omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 4691294Sbill lshift(v, 2); 4701294Sbill while (i > 0) { 4711294Sbill if (setintr) 472*17519Sedward (void) sigsetmask(omask); 4731294Sbill reexecute(kp); 4741294Sbill --i; 4751294Sbill } 4761294Sbill donefds(); 4771294Sbill if (setintr) 478*17519Sedward (void) sigsetmask(omask); 4791294Sbill } 4801294Sbill 4811294Sbill doswbrk() 4821294Sbill { 4831294Sbill 4841294Sbill search(ZBRKSW, 0); 4851294Sbill } 4861294Sbill 4871294Sbill srchx(cp) 4881294Sbill register char *cp; 4891294Sbill { 490*17519Sedward register struct srch *sp, *sp1, *sp2; 491*17519Sedward register i; 4921294Sbill 493*17519Sedward /* 494*17519Sedward * Binary search 495*17519Sedward * Sp1 is the beginning of the current search range. 496*17519Sedward * Sp2 is one past the end. 497*17519Sedward */ 498*17519Sedward for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 499*17519Sedward sp = sp1 + (sp2 - sp1 >> 1); 500*17519Sedward if ((i = *cp - *sp->s_name) == 0 && 501*17519Sedward (i = strcmp(cp, sp->s_name)) == 0) 502*17519Sedward return sp->s_value; 503*17519Sedward if (i < 0) 504*17519Sedward sp2 = sp; 505*17519Sedward else 506*17519Sedward sp1 = sp + 1; 507*17519Sedward } 5081294Sbill return (-1); 5091294Sbill } 5101294Sbill 5111294Sbill char Stype; 5121294Sbill char *Sgoal; 5131294Sbill 5141294Sbill /*VARARGS2*/ 5151294Sbill search(type, level, goal) 5161294Sbill int type; 5171294Sbill register int level; 5181294Sbill char *goal; 5191294Sbill { 5201294Sbill char wordbuf[BUFSIZ]; 5211294Sbill register char *aword = wordbuf; 5221294Sbill register char *cp; 5231294Sbill 5241294Sbill Stype = type; Sgoal = goal; 5251294Sbill if (type == ZGOTO) 526*17519Sedward bseek((off_t)0); 5271294Sbill do { 5281294Sbill if (intty && fseekp == feobp) 5291294Sbill printf("? "), flush(); 530*17519Sedward aword[0] = 0; 531*17519Sedward (void) getword(aword); 5321294Sbill switch (srchx(aword)) { 5331294Sbill 5341294Sbill case ZELSE: 5351294Sbill if (level == 0 && type == ZIF) 5361294Sbill return; 5371294Sbill break; 5381294Sbill 5391294Sbill case ZIF: 5401294Sbill while (getword(aword)) 5411294Sbill continue; 5421294Sbill if ((type == ZIF || type == ZELSE) && eq(aword, "then")) 5431294Sbill level++; 5441294Sbill break; 5451294Sbill 5461294Sbill case ZENDIF: 5471294Sbill if (type == ZIF || type == ZELSE) 5481294Sbill level--; 5491294Sbill break; 5501294Sbill 5511294Sbill case ZFOREACH: 5521294Sbill case ZWHILE: 5531294Sbill if (type == ZBREAK) 5541294Sbill level++; 5551294Sbill break; 5561294Sbill 5571294Sbill case ZEND: 5581294Sbill if (type == ZBREAK) 5591294Sbill level--; 5601294Sbill break; 5611294Sbill 5621294Sbill case ZSWITCH: 5631294Sbill if (type == ZSWITCH || type == ZBRKSW) 5641294Sbill level++; 5651294Sbill break; 5661294Sbill 5671294Sbill case ZENDSW: 5681294Sbill if (type == ZSWITCH || type == ZBRKSW) 5691294Sbill level--; 5701294Sbill break; 5711294Sbill 5721294Sbill case ZLABEL: 5731294Sbill if (type == ZGOTO && getword(aword) && eq(aword, goal)) 5741294Sbill level = -1; 5751294Sbill break; 5761294Sbill 5771294Sbill default: 5781294Sbill if (type != ZGOTO && (type != ZSWITCH || level != 0)) 5791294Sbill break; 5801294Sbill if (lastchr(aword) != ':') 5811294Sbill break; 5821294Sbill aword[strlen(aword) - 1] = 0; 5831294Sbill if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default")) 5841294Sbill level = -1; 5851294Sbill break; 5861294Sbill 5871294Sbill case ZCASE: 5881294Sbill if (type != ZSWITCH || level != 0) 5891294Sbill break; 590*17519Sedward (void) getword(aword); 5911294Sbill if (lastchr(aword) == ':') 5921294Sbill aword[strlen(aword) - 1] = 0; 5931294Sbill cp = strip(Dfix1(aword)); 5941294Sbill if (Gmatch(goal, cp)) 5951294Sbill level = -1; 5961294Sbill xfree(cp); 5971294Sbill break; 5981294Sbill 5991294Sbill case ZDEFAULT: 6001294Sbill if (type == ZSWITCH && level == 0) 6011294Sbill level = -1; 6021294Sbill break; 6031294Sbill } 604*17519Sedward (void) getword(NOSTR); 6051294Sbill } while (level >= 0); 6061294Sbill } 6071294Sbill 6081294Sbill getword(wp) 6091294Sbill register char *wp; 6101294Sbill { 6111294Sbill register int found = 0; 6121294Sbill register int c, d; 6131294Sbill 6141294Sbill c = readc(1); 6151294Sbill d = 0; 6161294Sbill do { 6171294Sbill while (c == ' ' || c == '\t') 6181294Sbill c = readc(1); 6193798Sroot if (c == '#') 6203798Sroot do 6213798Sroot c = readc(1); 6223798Sroot while (c >= 0 && c != '\n'); 6231294Sbill if (c < 0) 6241294Sbill goto past; 6251294Sbill if (c == '\n') { 6261294Sbill if (wp) 6271294Sbill break; 6281294Sbill return (0); 6291294Sbill } 6301294Sbill unreadc(c); 6311294Sbill found = 1; 6321294Sbill do { 6331294Sbill c = readc(1); 6341294Sbill if (c == '\\' && (c = readc(1)) == '\n') 6351294Sbill c = ' '; 636*17519Sedward if (c == '\'' || c == '"') 6371294Sbill if (d == 0) 6381294Sbill d = c; 6391294Sbill else if (d == c) 6401294Sbill d = 0; 6411294Sbill if (c < 0) 6421294Sbill goto past; 6431294Sbill if (wp) 6441294Sbill *wp++ = c; 6451294Sbill } while ((d || c != ' ' && c != '\t') && c != '\n'); 6461294Sbill } while (wp == 0); 6471294Sbill unreadc(c); 6481294Sbill if (found) 6491294Sbill *--wp = 0; 6501294Sbill return (found); 6511294Sbill 6521294Sbill past: 6531294Sbill switch (Stype) { 6541294Sbill 6551294Sbill case ZIF: 6561294Sbill bferr("then/endif not found"); 6571294Sbill 6581294Sbill case ZELSE: 6591294Sbill bferr("endif not found"); 6601294Sbill 6611294Sbill case ZBRKSW: 6621294Sbill case ZSWITCH: 6631294Sbill bferr("endsw not found"); 6641294Sbill 6651294Sbill case ZBREAK: 6661294Sbill bferr("end not found"); 6671294Sbill 6681294Sbill case ZGOTO: 6691294Sbill setname(Sgoal); 6701294Sbill bferr("label not found"); 6711294Sbill } 6721294Sbill /*NOTREACHED*/ 6731294Sbill } 6741294Sbill 6751294Sbill toend() 6761294Sbill { 6771294Sbill 6781294Sbill if (whyles->w_end == 0) { 6791294Sbill search(ZBREAK, 0); 6801294Sbill whyles->w_end = btell() - 1; 6811294Sbill } else 6821294Sbill bseek(whyles->w_end); 6831294Sbill wfree(); 6841294Sbill } 6851294Sbill 6861294Sbill wfree() 6871294Sbill { 6881294Sbill long o = btell(); 6891294Sbill 6901294Sbill while (whyles) { 6911294Sbill register struct whyle *wp = whyles; 6921294Sbill register struct whyle *nwp = wp->w_next; 6931294Sbill 6941294Sbill if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) 6951294Sbill break; 6961294Sbill if (wp->w_fe0) 6971294Sbill blkfree(wp->w_fe0); 6981294Sbill if (wp->w_fename) 6991294Sbill xfree(wp->w_fename); 7001294Sbill xfree((char *)wp); 7011294Sbill whyles = nwp; 7021294Sbill } 7031294Sbill } 7041294Sbill 7051294Sbill doecho(v) 7061294Sbill char **v; 7071294Sbill { 7081294Sbill 7091294Sbill echo(' ', v); 7101294Sbill } 7111294Sbill 7121294Sbill doglob(v) 7131294Sbill char **v; 7141294Sbill { 7151294Sbill 7161294Sbill echo(0, v); 7171294Sbill flush(); 7181294Sbill } 7191294Sbill 7201294Sbill echo(sep, v) 7211294Sbill char sep; 7221294Sbill register char **v; 7231294Sbill { 7241294Sbill register char *cp; 7251294Sbill int nonl = 0; 7261294Sbill 7271294Sbill if (setintr) 728*17519Sedward (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 7291294Sbill v++; 7301294Sbill if (*v == 0) 7311294Sbill return; 732*17519Sedward gflag = 0, tglob(v); 7331294Sbill if (gflag) { 7341294Sbill v = glob(v); 7351294Sbill if (v == 0) 7361294Sbill bferr("No match"); 7371294Sbill } else 738*17519Sedward trim(v); 7391294Sbill if (sep == ' ' && !strcmp(*v, "-n")) 7401294Sbill nonl++, v++; 7411294Sbill while (cp = *v++) { 7421294Sbill register int c; 7431294Sbill 7441294Sbill while (c = *cp++) 7451294Sbill putchar(c | QUOTE); 7461294Sbill if (*v) 7471294Sbill putchar(sep | QUOTE); 7481294Sbill } 7491294Sbill if (sep && nonl == 0) 7501294Sbill putchar('\n'); 7511294Sbill else 7521294Sbill flush(); 7531294Sbill if (setintr) 754*17519Sedward (void) sigblock(sigmask(SIGINT)); 7551294Sbill if (gargv) 7561294Sbill blkfree(gargv), gargv = 0; 7571294Sbill } 7581294Sbill 7591294Sbill char **environ; 7601294Sbill 7611294Sbill dosetenv(v) 7621294Sbill register char **v; 7631294Sbill { 7641294Sbill char *lp = globone(v[2]); 7651294Sbill 7661294Sbill setenv(v[1], lp); 7671294Sbill if (eq(v[1], "PATH")) { 7681294Sbill importpath(lp); 7691294Sbill dohash(); 7701294Sbill } 7711294Sbill xfree(lp); 7721294Sbill } 7731294Sbill 7741294Sbill dounsetenv(v) 7751294Sbill register char **v; 7761294Sbill { 7771294Sbill 7781294Sbill v++; 7791294Sbill do 7801294Sbill unsetenv(*v++); 7811294Sbill while (*v); 7821294Sbill } 7831294Sbill 784*17519Sedward setenv(name, val) 785*17519Sedward char *name, *val; 7861294Sbill { 7871294Sbill register char **ep = environ; 7881294Sbill register char *cp, *dp; 7891294Sbill char *blk[2], **oep = ep; 7901294Sbill 7911294Sbill for (; *ep; ep++) { 7921294Sbill for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 7931294Sbill continue; 7941294Sbill if (*cp != 0 || *dp != '=') 7951294Sbill continue; 796*17519Sedward cp = strspl("=", val); 7971294Sbill xfree(*ep); 7981294Sbill *ep = strspl(name, cp); 7991294Sbill xfree(cp); 800*17519Sedward trim(ep); 8011294Sbill return; 8021294Sbill } 8031294Sbill blk[0] = strspl(name, "="); blk[1] = 0; 8041294Sbill environ = blkspl(environ, blk); 8051294Sbill xfree((char *)oep); 806*17519Sedward setenv(name, val); 8071294Sbill } 8081294Sbill 8091294Sbill unsetenv(name) 8101294Sbill char *name; 8111294Sbill { 8121294Sbill register char **ep = environ; 8131294Sbill register char *cp, *dp; 8141294Sbill char **oep = ep; 8151294Sbill 8161294Sbill for (; *ep; ep++) { 8171294Sbill for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 8181294Sbill continue; 8191294Sbill if (*cp != 0 || *dp != '=') 8201294Sbill continue; 8211294Sbill cp = *ep; 8221294Sbill *ep = 0; 8231294Sbill environ = blkspl(environ, ep+1); 8241294Sbill *ep = cp; 8251294Sbill xfree(cp); 8261294Sbill xfree((char *)oep); 8271294Sbill return; 8281294Sbill } 8291294Sbill } 8301294Sbill 8311294Sbill doumask(v) 8321294Sbill register char **v; 8331294Sbill { 8341294Sbill register char *cp = v[1]; 8351294Sbill register int i; 8361294Sbill 8371294Sbill if (cp == 0) { 8381294Sbill i = umask(0); 839*17519Sedward (void) umask(i); 8401294Sbill printf("%o\n", i); 8411294Sbill return; 8421294Sbill } 8431294Sbill i = 0; 8441294Sbill while (digit(*cp) && *cp != '8' && *cp != '9') 8451294Sbill i = i * 8 + *cp++ - '0'; 8461294Sbill if (*cp || i < 0 || i > 0777) 8471294Sbill bferr("Improper mask"); 848*17519Sedward (void) umask(i); 8491294Sbill } 8501294Sbill 8511294Sbill 8521294Sbill struct limits { 8531294Sbill int limconst; 8541294Sbill char *limname; 8551294Sbill int limdiv; 8561294Sbill char *limscale; 8571294Sbill } limits[] = { 85810032Ssam RLIMIT_CPU, "cputime", 1, "seconds", 85910032Ssam RLIMIT_FSIZE, "filesize", 1024, "kbytes", 86010032Ssam RLIMIT_DATA, "datasize", 1024, "kbytes", 86110032Ssam RLIMIT_STACK, "stacksize", 1024, "kbytes", 86210032Ssam RLIMIT_CORE, "coredumpsize", 1024, "kbytes", 86310032Ssam RLIMIT_RSS, "memoryuse", 1024, "kbytes", 8641294Sbill -1, 0, 8651294Sbill }; 8661294Sbill 8671294Sbill struct limits * 8681294Sbill findlim(cp) 8691294Sbill char *cp; 8701294Sbill { 8711294Sbill register struct limits *lp, *res; 8721294Sbill 8731294Sbill res = 0; 8741294Sbill for (lp = limits; lp->limconst >= 0; lp++) 8751294Sbill if (prefix(cp, lp->limname)) { 8761294Sbill if (res) 8771294Sbill bferr("Ambiguous"); 8781294Sbill res = lp; 8791294Sbill } 8801294Sbill if (res) 8811294Sbill return (res); 8821294Sbill bferr("No such limit"); 883*17519Sedward /*NOTREACHED*/ 8841294Sbill } 8851294Sbill 8861294Sbill dolimit(v) 8871294Sbill register char **v; 8881294Sbill { 8891294Sbill register struct limits *lp; 8901294Sbill register int limit; 8911294Sbill 8921294Sbill v++; 8931294Sbill if (*v == 0) { 8941294Sbill for (lp = limits+1; lp->limconst >= 0; lp++) 8951294Sbill plim(lp); 8961294Sbill return; 8971294Sbill } 8981294Sbill lp = findlim(v[0]); 8991294Sbill if (v[1] == 0) { 9001294Sbill plim(lp); 9011294Sbill return; 9021294Sbill } 9031294Sbill limit = getval(lp, v+1); 9041294Sbill setlim(lp, limit); 9051294Sbill } 9061294Sbill 9071294Sbill getval(lp, v) 9081294Sbill register struct limits *lp; 9091294Sbill char **v; 9101294Sbill { 9111294Sbill register float f; 9121294Sbill double atof(); 9131294Sbill char *cp = *v++; 9141294Sbill 9151294Sbill f = atof(cp); 9161294Sbill while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 9171294Sbill cp++; 9181294Sbill if (*cp == 0) { 9191294Sbill if (*v == 0) 9201294Sbill return ((int)(f+0.5) * lp->limdiv); 9211294Sbill cp = *v; 9221294Sbill } 9231294Sbill switch (*cp) { 9241294Sbill 9251294Sbill case ':': 92610032Ssam if (lp->limconst != RLIMIT_CPU) 9271294Sbill goto badscal; 9281294Sbill return ((int)(f * 60.0 + atof(cp+1))); 9291294Sbill 9301294Sbill case 'h': 93110032Ssam if (lp->limconst != RLIMIT_CPU) 9321294Sbill goto badscal; 9331294Sbill limtail(cp, "hours"); 9341294Sbill f *= 3600.; 9351294Sbill break; 9361294Sbill 9371294Sbill case 'm': 93810032Ssam if (lp->limconst == RLIMIT_CPU) { 9391294Sbill limtail(cp, "minutes"); 9401294Sbill f *= 60.; 9411294Sbill break; 9421294Sbill } 9431294Sbill case 'M': 94410032Ssam if (lp->limconst == RLIMIT_CPU) 9451294Sbill goto badscal; 9461294Sbill *cp = 'm'; 9471294Sbill limtail(cp, "megabytes"); 9481294Sbill f *= 1024.*1024.; 9491294Sbill break; 9501294Sbill 9511294Sbill case 's': 95210032Ssam if (lp->limconst != RLIMIT_CPU) 9531294Sbill goto badscal; 9541294Sbill limtail(cp, "seconds"); 9551294Sbill break; 9561294Sbill 9571294Sbill case 'k': 95810032Ssam if (lp->limconst == RLIMIT_CPU) 9591294Sbill goto badscal; 9601294Sbill limtail(cp, "kbytes"); 9611294Sbill f *= 1024; 9621294Sbill break; 9631294Sbill 9641294Sbill case 'u': 9651294Sbill limtail(cp, "unlimited"); 96610032Ssam return (RLIM_INFINITY); 9671294Sbill 9681294Sbill default: 9691294Sbill badscal: 9701294Sbill bferr("Improper or unknown scale factor"); 9711294Sbill } 9721294Sbill return ((int)(f+0.5)); 9731294Sbill } 9741294Sbill 9751294Sbill limtail(cp, str0) 9761294Sbill char *cp, *str0; 9771294Sbill { 9781294Sbill register char *str = str0; 9791294Sbill 9801294Sbill while (*cp && *cp == *str) 9811294Sbill cp++, str++; 9821294Sbill if (*cp) 9831294Sbill error("Bad scaling; did you mean ``%s''?", str0); 9841294Sbill } 9851294Sbill 9861294Sbill plim(lp) 9871294Sbill register struct limits *lp; 9881294Sbill { 98910032Ssam struct rlimit rlim; 9901294Sbill 9911294Sbill printf("%s \t", lp->limname); 992*17519Sedward (void) getrlimit(lp->limconst, &rlim); 99310032Ssam if (rlim.rlim_cur == RLIM_INFINITY) 9941294Sbill printf("unlimited"); 99510032Ssam else if (lp->limconst == RLIMIT_CPU) 99610032Ssam psecs((long)rlim.rlim_cur); 9971294Sbill else 99810032Ssam printf("%d %s", rlim.rlim_cur / lp->limdiv, lp->limscale); 9991294Sbill printf("\n"); 10001294Sbill } 10011294Sbill 10021294Sbill dounlimit(v) 10031294Sbill register char **v; 10041294Sbill { 10051294Sbill register struct limits *lp; 10061294Sbill 10071294Sbill v++; 10081294Sbill if (*v == 0) { 10091294Sbill for (lp = limits+1; lp->limconst >= 0; lp++) 1010*17519Sedward setlim(lp, (int)RLIM_INFINITY); 10111294Sbill return; 10121294Sbill } 10131294Sbill while (*v) { 10141294Sbill lp = findlim(*v++); 1015*17519Sedward setlim(lp, (int)RLIM_INFINITY); 10161294Sbill } 10171294Sbill } 10181294Sbill 10191294Sbill setlim(lp, limit) 10201294Sbill register struct limits *lp; 10211294Sbill { 102210032Ssam struct rlimit rlim; 10231294Sbill 1024*17519Sedward (void) getrlimit(lp->limconst, &rlim); 102516661Smckusick if(limit == RLIM_INFINITY && geteuid() != 0) 102616661Smckusick rlim.rlim_cur = rlim.rlim_max; 102716661Smckusick else 1028*17519Sedward rlim.rlim_cur = limit; 102910032Ssam if (setrlimit(lp->limconst, &rlim) < 0) 10301294Sbill Perror(bname); 10311294Sbill } 10321294Sbill 10331294Sbill dosuspend() 10341294Sbill { 103517138Sralph int ldisc, ctpgrp; 103617138Sralph int (*old)(); 10371294Sbill 10381294Sbill if (loginsh) 10391294Sbill error("Can't suspend a login shell (yet)"); 10401294Sbill untty(); 104117138Sralph old = signal(SIGTSTP, SIG_DFL); 1042*17519Sedward (void) kill(0, SIGTSTP); 10431294Sbill /* the shell stops here */ 1044*17519Sedward (void) signal(SIGTSTP, old); 10451294Sbill if (tpgrp != -1) { 10461294Sbill retry: 1047*17519Sedward (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp); 10481294Sbill if (ctpgrp != opgrp) { 104917138Sralph old = signal(SIGTTIN, SIG_DFL); 1050*17519Sedward (void) kill(0, SIGTTIN); 1051*17519Sedward (void) signal(SIGTTIN, old); 10521294Sbill goto retry; 10531294Sbill } 1054*17519Sedward (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp); 1055*17519Sedward (void) setpgrp(0, shpgrp); 10561294Sbill } 1057*17519Sedward (void) ioctl(FSHTTY, TIOCGETD, (char *)&oldisc); 10581294Sbill if (oldisc != NTTYDISC) { 10591294Sbill printf("Switching to new tty driver...\n"); 10601294Sbill ldisc = NTTYDISC; 1061*17519Sedward (void) ioctl(FSHTTY, TIOCSETD, (char *)&ldisc); 10621294Sbill } 10631294Sbill } 10641294Sbill 10651294Sbill doeval(v) 10661294Sbill char **v; 10671294Sbill { 10681294Sbill char **oevalvec = evalvec; 10691294Sbill char *oevalp = evalp; 10701294Sbill jmp_buf osetexit; 10711294Sbill int reenter; 10721294Sbill char **gv = 0; 10731294Sbill 10741294Sbill v++; 10751294Sbill if (*v == 0) 10761294Sbill return; 1077*17519Sedward gflag = 0, tglob(v); 10781294Sbill if (gflag) { 10791294Sbill gv = v = glob(v); 10801294Sbill gargv = 0; 10811294Sbill if (v == 0) 10821294Sbill error("No match"); 10831294Sbill v = copyblk(v); 10841294Sbill } else 1085*17519Sedward trim(v); 10861294Sbill getexit(osetexit); 10871294Sbill reenter = 0; 10881294Sbill setexit(); 10891294Sbill reenter++; 10901294Sbill if (reenter == 1) { 10911294Sbill evalvec = v; 10921294Sbill evalp = 0; 10931294Sbill process(0); 10941294Sbill } 10951294Sbill evalvec = oevalvec; 10961294Sbill evalp = oevalp; 10971294Sbill doneinp = 0; 10981294Sbill if (gv) 10991294Sbill blkfree(gv); 11001294Sbill resexit(osetexit); 11011294Sbill if (reenter >= 2) 11021294Sbill error(NOSTR); 11031294Sbill } 1104