1*1294Sbill static char *sccsid = "@(#)func.c 4.1 10/09/80"; 2*1294Sbill 3*1294Sbill #include "sh.h" 4*1294Sbill #include <sys/ioctl.h> 5*1294Sbill 6*1294Sbill /* 7*1294Sbill * C shell 8*1294Sbill */ 9*1294Sbill 10*1294Sbill struct biltins * 11*1294Sbill isbfunc(t) 12*1294Sbill register struct command *t; 13*1294Sbill { 14*1294Sbill register char *cp = t->t_dcom[0]; 15*1294Sbill register char *dp; 16*1294Sbill register struct biltins *bp; 17*1294Sbill int dolabel(), dofg1(), dobg1(); 18*1294Sbill static struct biltins label = { "", dolabel, 0, 0 }; 19*1294Sbill static struct biltins foregnd = { "%job", dofg1, 0, 0 }; 20*1294Sbill static struct biltins backgnd = { "%job &", dobg1, 0, 0 }; 21*1294Sbill 22*1294Sbill if (lastchr(cp) == ':') { 23*1294Sbill label.bname = cp; 24*1294Sbill return (&label); 25*1294Sbill } 26*1294Sbill if (*cp == '%') { 27*1294Sbill if (t->t_dflg & FAND) { 28*1294Sbill t->t_dflg &= ~FAND; 29*1294Sbill backgnd.bname = cp; 30*1294Sbill return (&backgnd); 31*1294Sbill } 32*1294Sbill foregnd.bname = cp; 33*1294Sbill return (&foregnd); 34*1294Sbill } 35*1294Sbill for (bp = bfunc; dp = bp->bname; bp++) { 36*1294Sbill if (dp[0] == cp[0] && eq(dp, cp)) 37*1294Sbill return (bp); 38*1294Sbill if (dp[0] > cp[0]) 39*1294Sbill break; 40*1294Sbill } 41*1294Sbill return (0); 42*1294Sbill } 43*1294Sbill 44*1294Sbill func(t, bp) 45*1294Sbill register struct command *t; 46*1294Sbill register struct biltins *bp; 47*1294Sbill { 48*1294Sbill int i; 49*1294Sbill 50*1294Sbill xechoit(t->t_dcom); 51*1294Sbill setname(bp->bname); 52*1294Sbill i = blklen(t->t_dcom) - 1; 53*1294Sbill if (i < bp->minargs) 54*1294Sbill bferr("Too few arguments"); 55*1294Sbill if (i > bp->maxargs) 56*1294Sbill bferr("Too many arguments"); 57*1294Sbill (*bp->bfunct)(t->t_dcom, t); 58*1294Sbill } 59*1294Sbill 60*1294Sbill dolabel() 61*1294Sbill { 62*1294Sbill 63*1294Sbill } 64*1294Sbill 65*1294Sbill doonintr(v) 66*1294Sbill char **v; 67*1294Sbill { 68*1294Sbill register char *cp; 69*1294Sbill register char *vv = v[1]; 70*1294Sbill 71*1294Sbill if (parintr == SIG_IGN) 72*1294Sbill return; 73*1294Sbill if (setintr && intty) 74*1294Sbill bferr("Can't from terminal"); 75*1294Sbill cp = gointr, gointr = 0, xfree(cp); 76*1294Sbill if (vv == 0) { 77*1294Sbill if (setintr) 78*1294Sbill sighold(SIGINT); 79*1294Sbill else 80*1294Sbill sigset(SIGINT, SIG_DFL); 81*1294Sbill gointr = 0; 82*1294Sbill } else if (eq((vv = strip(vv)), "-")) { 83*1294Sbill sigset(SIGINT, SIG_IGN); 84*1294Sbill gointr = "-"; 85*1294Sbill } else { 86*1294Sbill gointr = savestr(vv); 87*1294Sbill sigset(SIGINT, pintr); 88*1294Sbill } 89*1294Sbill } 90*1294Sbill 91*1294Sbill donohup() 92*1294Sbill { 93*1294Sbill 94*1294Sbill if (intty) 95*1294Sbill bferr("Can't from terminal"); 96*1294Sbill if (setintr == 0) { 97*1294Sbill signal(SIGHUP, SIG_IGN); 98*1294Sbill #ifdef CC 99*1294Sbill submit(getpid()); 100*1294Sbill #endif 101*1294Sbill } 102*1294Sbill } 103*1294Sbill 104*1294Sbill dozip() 105*1294Sbill { 106*1294Sbill 107*1294Sbill ; 108*1294Sbill } 109*1294Sbill 110*1294Sbill prvars() 111*1294Sbill { 112*1294Sbill 113*1294Sbill plist(&shvhed); 114*1294Sbill } 115*1294Sbill 116*1294Sbill doalias(v) 117*1294Sbill register char **v; 118*1294Sbill { 119*1294Sbill register struct varent *vp; 120*1294Sbill register char *p; 121*1294Sbill 122*1294Sbill v++; 123*1294Sbill p = *v++; 124*1294Sbill if (p == 0) 125*1294Sbill plist(&aliases); 126*1294Sbill else if (*v == 0) { 127*1294Sbill vp = adrof1(strip(p), &aliases); 128*1294Sbill if (vp) 129*1294Sbill blkpr(vp->vec), printf("\n"); 130*1294Sbill } else { 131*1294Sbill if (eq(p, "alias") || eq(p, "unalias")) { 132*1294Sbill setname(p); 133*1294Sbill bferr("Too dangerous to alias that"); 134*1294Sbill } 135*1294Sbill set1(strip(p), saveblk(v), &aliases); 136*1294Sbill } 137*1294Sbill } 138*1294Sbill 139*1294Sbill unalias(v) 140*1294Sbill char **v; 141*1294Sbill { 142*1294Sbill 143*1294Sbill unset1(v, &aliases); 144*1294Sbill } 145*1294Sbill 146*1294Sbill dologout() 147*1294Sbill { 148*1294Sbill 149*1294Sbill islogin(); 150*1294Sbill goodbye(); 151*1294Sbill } 152*1294Sbill 153*1294Sbill dologin(v) 154*1294Sbill char **v; 155*1294Sbill { 156*1294Sbill 157*1294Sbill islogin(); 158*1294Sbill signal(SIGTERM, parterm); 159*1294Sbill execl("/bin/login", "login", v[1], 0); 160*1294Sbill untty(); 161*1294Sbill exit(1); 162*1294Sbill } 163*1294Sbill 164*1294Sbill donewgrp(v) 165*1294Sbill char **v; 166*1294Sbill { 167*1294Sbill 168*1294Sbill signal(SIGTERM, parterm); 169*1294Sbill execl("/bin/newgrp", "newgrp", v[1], 0); 170*1294Sbill execl("/usr/bin/newgrp", "newgrp", v[1], 0); 171*1294Sbill untty(); 172*1294Sbill exit(1); 173*1294Sbill } 174*1294Sbill 175*1294Sbill islogin() 176*1294Sbill { 177*1294Sbill 178*1294Sbill if (chkstop == 0 && setintr) 179*1294Sbill panystop(0); 180*1294Sbill if (loginsh) 181*1294Sbill return; 182*1294Sbill error("Not login shell"); 183*1294Sbill } 184*1294Sbill 185*1294Sbill doif(v, kp) 186*1294Sbill char **v; 187*1294Sbill struct command *kp; 188*1294Sbill { 189*1294Sbill register int i; 190*1294Sbill register char **vv; 191*1294Sbill 192*1294Sbill v++; 193*1294Sbill i = exp(&v); 194*1294Sbill vv = v; 195*1294Sbill if (*vv == NOSTR) 196*1294Sbill bferr("Empty if"); 197*1294Sbill if (eq(*vv, "then")) { 198*1294Sbill if (*++vv) 199*1294Sbill bferr("Improper then"); 200*1294Sbill setname("then"); 201*1294Sbill /* 202*1294Sbill * If expression was zero, then scan to else, 203*1294Sbill * otherwise just fall into following code. 204*1294Sbill */ 205*1294Sbill if (!i) 206*1294Sbill search(ZIF, 0); 207*1294Sbill return; 208*1294Sbill } 209*1294Sbill /* 210*1294Sbill * Simple command attached to this if. 211*1294Sbill * Left shift the node in this tree, munging it 212*1294Sbill * so we can reexecute it. 213*1294Sbill */ 214*1294Sbill if (i) { 215*1294Sbill lshift(kp->t_dcom, vv - kp->t_dcom); 216*1294Sbill reexecute(kp); 217*1294Sbill donefds(); 218*1294Sbill } 219*1294Sbill } 220*1294Sbill 221*1294Sbill /* 222*1294Sbill * Reexecute a command, being careful not 223*1294Sbill * to redo i/o redirection, which is already set up. 224*1294Sbill */ 225*1294Sbill reexecute(kp) 226*1294Sbill register struct command *kp; 227*1294Sbill { 228*1294Sbill 229*1294Sbill kp->t_dflg &= FSAVE; 230*1294Sbill kp->t_dflg |= FREDO; 231*1294Sbill /* 232*1294Sbill * If tty is still ours to arbitrate, arbitrate it; 233*1294Sbill * otherwise dont even set pgrp's as the jobs would 234*1294Sbill * then have no way to get the tty (we can't give it 235*1294Sbill * to them, and our parent wouldn't know their pgrp, etc. 236*1294Sbill */ 237*1294Sbill execute(kp, tpgrp > 0 ? tpgrp : -1); 238*1294Sbill } 239*1294Sbill 240*1294Sbill doelse() 241*1294Sbill { 242*1294Sbill 243*1294Sbill search(ZELSE, 0); 244*1294Sbill } 245*1294Sbill 246*1294Sbill dogoto(v) 247*1294Sbill char **v; 248*1294Sbill { 249*1294Sbill register struct whyle *wp; 250*1294Sbill char *lp; 251*1294Sbill 252*1294Sbill /* 253*1294Sbill * While we still can, locate any unknown ends of existing loops. 254*1294Sbill * This obscure code is the WORST result of the fact that we 255*1294Sbill * don't really parse. 256*1294Sbill */ 257*1294Sbill for (wp = whyles; wp; wp = wp->w_next) 258*1294Sbill if (wp->w_end == 0) { 259*1294Sbill search(ZBREAK, 0); 260*1294Sbill wp->w_end = btell(); 261*1294Sbill } else 262*1294Sbill bseek(wp->w_end); 263*1294Sbill search(ZGOTO, 0, lp = globone(v[1])); 264*1294Sbill xfree(lp); 265*1294Sbill /* 266*1294Sbill * Eliminate loops which were exited. 267*1294Sbill */ 268*1294Sbill wfree(); 269*1294Sbill } 270*1294Sbill 271*1294Sbill doswitch(v) 272*1294Sbill register char **v; 273*1294Sbill { 274*1294Sbill register char *cp, *lp; 275*1294Sbill 276*1294Sbill v++; 277*1294Sbill if (!*v || *(*v++) != '(') 278*1294Sbill goto syntax; 279*1294Sbill cp = **v == ')' ? "" : *v++; 280*1294Sbill if (*(*v++) != ')') 281*1294Sbill v--; 282*1294Sbill if (*v) 283*1294Sbill syntax: 284*1294Sbill error("Syntax error"); 285*1294Sbill search(ZSWITCH, 0, lp = globone(cp)); 286*1294Sbill xfree(lp); 287*1294Sbill } 288*1294Sbill 289*1294Sbill dobreak() 290*1294Sbill { 291*1294Sbill 292*1294Sbill if (whyles) 293*1294Sbill toend(); 294*1294Sbill else 295*1294Sbill bferr("Not in while/foreach"); 296*1294Sbill } 297*1294Sbill 298*1294Sbill doexit(v) 299*1294Sbill char **v; 300*1294Sbill { 301*1294Sbill 302*1294Sbill if (chkstop == 0) 303*1294Sbill panystop(0); 304*1294Sbill /* 305*1294Sbill * Don't DEMAND parentheses here either. 306*1294Sbill */ 307*1294Sbill v++; 308*1294Sbill if (*v) { 309*1294Sbill set("status", putn(exp(&v))); 310*1294Sbill if (*v) 311*1294Sbill bferr("Expression syntax"); 312*1294Sbill } 313*1294Sbill btoeof(); 314*1294Sbill if (intty) 315*1294Sbill close(SHIN); 316*1294Sbill } 317*1294Sbill 318*1294Sbill doforeach(v) 319*1294Sbill register char **v; 320*1294Sbill { 321*1294Sbill register char *cp; 322*1294Sbill register struct whyle *nwp; 323*1294Sbill 324*1294Sbill v++; 325*1294Sbill cp = strip(*v); 326*1294Sbill while (*cp && letter(*cp)) 327*1294Sbill cp++; 328*1294Sbill if (*cp || strlen(*v) >= 20) 329*1294Sbill bferr("Invalid variable"); 330*1294Sbill cp = *v++; 331*1294Sbill if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 332*1294Sbill bferr("Words not ()'ed"); 333*1294Sbill v++; 334*1294Sbill gflag = 0, rscan(v, tglob); 335*1294Sbill v = glob(v); 336*1294Sbill if (v == 0) 337*1294Sbill bferr("No match"); 338*1294Sbill nwp = (struct whyle *) calloc(1, sizeof *nwp); 339*1294Sbill nwp->w_fe = nwp->w_fe0 = v; gargv = 0; 340*1294Sbill nwp->w_start = btell(); 341*1294Sbill nwp->w_fename = savestr(cp); 342*1294Sbill nwp->w_next = whyles; 343*1294Sbill whyles = nwp; 344*1294Sbill /* 345*1294Sbill * Pre-read the loop so as to be more 346*1294Sbill * comprehensible to a terminal user. 347*1294Sbill */ 348*1294Sbill if (intty) 349*1294Sbill preread(); 350*1294Sbill doagain(); 351*1294Sbill } 352*1294Sbill 353*1294Sbill dowhile(v) 354*1294Sbill char **v; 355*1294Sbill { 356*1294Sbill register int status; 357*1294Sbill register bool again = whyles != 0 && whyles->w_start == lineloc && 358*1294Sbill whyles->w_fename == 0; 359*1294Sbill 360*1294Sbill v++; 361*1294Sbill /* 362*1294Sbill * Implement prereading here also, taking care not to 363*1294Sbill * evaluate the expression before the loop has been read up 364*1294Sbill * from a terminal. 365*1294Sbill */ 366*1294Sbill if (intty && !again) 367*1294Sbill status = !exp0(&v, 1); 368*1294Sbill else 369*1294Sbill status = !exp(&v); 370*1294Sbill if (*v) 371*1294Sbill bferr("Expression syntax"); 372*1294Sbill if (!again) { 373*1294Sbill register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp)); 374*1294Sbill 375*1294Sbill nwp->w_start = lineloc; 376*1294Sbill nwp->w_end = 0; 377*1294Sbill nwp->w_next = whyles; 378*1294Sbill whyles = nwp; 379*1294Sbill if (intty) { 380*1294Sbill /* 381*1294Sbill * The tty preread 382*1294Sbill */ 383*1294Sbill preread(); 384*1294Sbill doagain(); 385*1294Sbill return; 386*1294Sbill } 387*1294Sbill } 388*1294Sbill if (status) 389*1294Sbill /* We ain't gonna loop no more, no more! */ 390*1294Sbill toend(); 391*1294Sbill } 392*1294Sbill 393*1294Sbill preread() 394*1294Sbill { 395*1294Sbill 396*1294Sbill whyles->w_end = -1; 397*1294Sbill if (setintr) 398*1294Sbill sigrelse(SIGINT); 399*1294Sbill search(ZBREAK, 0); 400*1294Sbill if (setintr) 401*1294Sbill sighold(SIGINT); 402*1294Sbill whyles->w_end = btell(); 403*1294Sbill } 404*1294Sbill 405*1294Sbill doend() 406*1294Sbill { 407*1294Sbill 408*1294Sbill if (!whyles) 409*1294Sbill bferr("Not in while/foreach"); 410*1294Sbill whyles->w_end = btell(); 411*1294Sbill doagain(); 412*1294Sbill } 413*1294Sbill 414*1294Sbill docontin() 415*1294Sbill { 416*1294Sbill 417*1294Sbill if (!whyles) 418*1294Sbill bferr("Not in while/foreach"); 419*1294Sbill doagain(); 420*1294Sbill } 421*1294Sbill 422*1294Sbill doagain() 423*1294Sbill { 424*1294Sbill 425*1294Sbill /* Repeating a while is simple */ 426*1294Sbill if (whyles->w_fename == 0) { 427*1294Sbill bseek(whyles->w_start); 428*1294Sbill return; 429*1294Sbill } 430*1294Sbill /* 431*1294Sbill * The foreach variable list actually has a spurious word 432*1294Sbill * ")" at the end of the w_fe list. Thus we are at the 433*1294Sbill * of the list if one word beyond this is 0. 434*1294Sbill */ 435*1294Sbill if (!whyles->w_fe[1]) { 436*1294Sbill dobreak(); 437*1294Sbill return; 438*1294Sbill } 439*1294Sbill set(whyles->w_fename, savestr(*whyles->w_fe++)); 440*1294Sbill bseek(whyles->w_start); 441*1294Sbill } 442*1294Sbill 443*1294Sbill dorepeat(v, kp) 444*1294Sbill char **v; 445*1294Sbill struct command *kp; 446*1294Sbill { 447*1294Sbill register int i; 448*1294Sbill 449*1294Sbill i = getn(v[1]); 450*1294Sbill if (setintr) 451*1294Sbill sighold(SIGINT); 452*1294Sbill lshift(v, 2); 453*1294Sbill while (i > 0) { 454*1294Sbill if (setintr) 455*1294Sbill sigrelse(SIGINT); 456*1294Sbill reexecute(kp); 457*1294Sbill --i; 458*1294Sbill } 459*1294Sbill donefds(); 460*1294Sbill if (setintr) 461*1294Sbill sigrelse(SIGINT); 462*1294Sbill } 463*1294Sbill 464*1294Sbill doswbrk() 465*1294Sbill { 466*1294Sbill 467*1294Sbill search(ZBRKSW, 0); 468*1294Sbill } 469*1294Sbill 470*1294Sbill srchx(cp) 471*1294Sbill register char *cp; 472*1294Sbill { 473*1294Sbill register struct srch *sp; 474*1294Sbill 475*1294Sbill for (sp = srchn; sp->s_name; sp++) 476*1294Sbill if (eq(cp, sp->s_name)) 477*1294Sbill return (sp->s_value); 478*1294Sbill return (-1); 479*1294Sbill } 480*1294Sbill 481*1294Sbill char Stype; 482*1294Sbill char *Sgoal; 483*1294Sbill 484*1294Sbill /*VARARGS2*/ 485*1294Sbill search(type, level, goal) 486*1294Sbill int type; 487*1294Sbill register int level; 488*1294Sbill char *goal; 489*1294Sbill { 490*1294Sbill char wordbuf[BUFSIZ]; 491*1294Sbill register char *aword = wordbuf; 492*1294Sbill register char *cp; 493*1294Sbill 494*1294Sbill Stype = type; Sgoal = goal; 495*1294Sbill if (type == ZGOTO) 496*1294Sbill bseek(0l); 497*1294Sbill do { 498*1294Sbill if (intty && fseekp == feobp) 499*1294Sbill printf("? "), flush(); 500*1294Sbill aword[0] = 0, getword(aword); 501*1294Sbill switch (srchx(aword)) { 502*1294Sbill 503*1294Sbill case ZELSE: 504*1294Sbill if (level == 0 && type == ZIF) 505*1294Sbill return; 506*1294Sbill break; 507*1294Sbill 508*1294Sbill case ZIF: 509*1294Sbill while (getword(aword)) 510*1294Sbill continue; 511*1294Sbill if ((type == ZIF || type == ZELSE) && eq(aword, "then")) 512*1294Sbill level++; 513*1294Sbill break; 514*1294Sbill 515*1294Sbill case ZENDIF: 516*1294Sbill if (type == ZIF || type == ZELSE) 517*1294Sbill level--; 518*1294Sbill break; 519*1294Sbill 520*1294Sbill case ZFOREACH: 521*1294Sbill case ZWHILE: 522*1294Sbill if (type == ZBREAK) 523*1294Sbill level++; 524*1294Sbill break; 525*1294Sbill 526*1294Sbill case ZEND: 527*1294Sbill if (type == ZBREAK) 528*1294Sbill level--; 529*1294Sbill break; 530*1294Sbill 531*1294Sbill case ZSWITCH: 532*1294Sbill if (type == ZSWITCH || type == ZBRKSW) 533*1294Sbill level++; 534*1294Sbill break; 535*1294Sbill 536*1294Sbill case ZENDSW: 537*1294Sbill if (type == ZSWITCH || type == ZBRKSW) 538*1294Sbill level--; 539*1294Sbill break; 540*1294Sbill 541*1294Sbill case ZLABEL: 542*1294Sbill if (type == ZGOTO && getword(aword) && eq(aword, goal)) 543*1294Sbill level = -1; 544*1294Sbill break; 545*1294Sbill 546*1294Sbill default: 547*1294Sbill if (type != ZGOTO && (type != ZSWITCH || level != 0)) 548*1294Sbill break; 549*1294Sbill if (lastchr(aword) != ':') 550*1294Sbill break; 551*1294Sbill aword[strlen(aword) - 1] = 0; 552*1294Sbill if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default")) 553*1294Sbill level = -1; 554*1294Sbill break; 555*1294Sbill 556*1294Sbill case ZCASE: 557*1294Sbill if (type != ZSWITCH || level != 0) 558*1294Sbill break; 559*1294Sbill getword(aword); 560*1294Sbill if (lastchr(aword) == ':') 561*1294Sbill aword[strlen(aword) - 1] = 0; 562*1294Sbill cp = strip(Dfix1(aword)); 563*1294Sbill if (Gmatch(goal, cp)) 564*1294Sbill level = -1; 565*1294Sbill xfree(cp); 566*1294Sbill break; 567*1294Sbill 568*1294Sbill case ZDEFAULT: 569*1294Sbill if (type == ZSWITCH && level == 0) 570*1294Sbill level = -1; 571*1294Sbill break; 572*1294Sbill } 573*1294Sbill getword(NOSTR); 574*1294Sbill } while (level >= 0); 575*1294Sbill } 576*1294Sbill 577*1294Sbill getword(wp) 578*1294Sbill register char *wp; 579*1294Sbill { 580*1294Sbill register int found = 0; 581*1294Sbill register int c, d; 582*1294Sbill 583*1294Sbill c = readc(1); 584*1294Sbill d = 0; 585*1294Sbill do { 586*1294Sbill while (c == ' ' || c == '\t') 587*1294Sbill c = readc(1); 588*1294Sbill if (c < 0) 589*1294Sbill goto past; 590*1294Sbill if (c == '\n') { 591*1294Sbill if (wp) 592*1294Sbill break; 593*1294Sbill return (0); 594*1294Sbill } 595*1294Sbill unreadc(c); 596*1294Sbill found = 1; 597*1294Sbill do { 598*1294Sbill c = readc(1); 599*1294Sbill if (c == '\\' && (c = readc(1)) == '\n') 600*1294Sbill c = ' '; 601*1294Sbill if (any(c, "'\"")) 602*1294Sbill if (d == 0) 603*1294Sbill d = c; 604*1294Sbill else if (d == c) 605*1294Sbill d = 0; 606*1294Sbill if (c < 0) 607*1294Sbill goto past; 608*1294Sbill if (wp) 609*1294Sbill *wp++ = c; 610*1294Sbill } while ((d || c != ' ' && c != '\t') && c != '\n'); 611*1294Sbill } while (wp == 0); 612*1294Sbill unreadc(c); 613*1294Sbill if (found) 614*1294Sbill *--wp = 0; 615*1294Sbill return (found); 616*1294Sbill 617*1294Sbill past: 618*1294Sbill switch (Stype) { 619*1294Sbill 620*1294Sbill case ZIF: 621*1294Sbill bferr("then/endif not found"); 622*1294Sbill 623*1294Sbill case ZELSE: 624*1294Sbill bferr("endif not found"); 625*1294Sbill 626*1294Sbill case ZBRKSW: 627*1294Sbill case ZSWITCH: 628*1294Sbill bferr("endsw not found"); 629*1294Sbill 630*1294Sbill case ZBREAK: 631*1294Sbill bferr("end not found"); 632*1294Sbill 633*1294Sbill case ZGOTO: 634*1294Sbill setname(Sgoal); 635*1294Sbill bferr("label not found"); 636*1294Sbill } 637*1294Sbill /*NOTREACHED*/ 638*1294Sbill } 639*1294Sbill 640*1294Sbill toend() 641*1294Sbill { 642*1294Sbill 643*1294Sbill if (whyles->w_end == 0) { 644*1294Sbill search(ZBREAK, 0); 645*1294Sbill whyles->w_end = btell() - 1; 646*1294Sbill } else 647*1294Sbill bseek(whyles->w_end); 648*1294Sbill wfree(); 649*1294Sbill } 650*1294Sbill 651*1294Sbill wfree() 652*1294Sbill { 653*1294Sbill long o = btell(); 654*1294Sbill 655*1294Sbill while (whyles) { 656*1294Sbill register struct whyle *wp = whyles; 657*1294Sbill register struct whyle *nwp = wp->w_next; 658*1294Sbill 659*1294Sbill if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) 660*1294Sbill break; 661*1294Sbill if (wp->w_fe0) 662*1294Sbill blkfree(wp->w_fe0); 663*1294Sbill if (wp->w_fename) 664*1294Sbill xfree(wp->w_fename); 665*1294Sbill xfree((char *)wp); 666*1294Sbill whyles = nwp; 667*1294Sbill } 668*1294Sbill } 669*1294Sbill 670*1294Sbill doecho(v) 671*1294Sbill char **v; 672*1294Sbill { 673*1294Sbill 674*1294Sbill echo(' ', v); 675*1294Sbill } 676*1294Sbill 677*1294Sbill doglob(v) 678*1294Sbill char **v; 679*1294Sbill { 680*1294Sbill 681*1294Sbill echo(0, v); 682*1294Sbill flush(); 683*1294Sbill } 684*1294Sbill 685*1294Sbill echo(sep, v) 686*1294Sbill char sep; 687*1294Sbill register char **v; 688*1294Sbill { 689*1294Sbill register char *cp; 690*1294Sbill int nonl = 0; 691*1294Sbill 692*1294Sbill if (setintr) 693*1294Sbill sigrelse(SIGINT); 694*1294Sbill v++; 695*1294Sbill if (*v == 0) 696*1294Sbill return; 697*1294Sbill gflag = 0; rscan(v, tglob); 698*1294Sbill if (gflag) { 699*1294Sbill v = glob(v); 700*1294Sbill if (v == 0) 701*1294Sbill bferr("No match"); 702*1294Sbill } else 703*1294Sbill scan(v, trim); 704*1294Sbill if (sep == ' ' && !strcmp(*v, "-n")) 705*1294Sbill nonl++, v++; 706*1294Sbill while (cp = *v++) { 707*1294Sbill register int c; 708*1294Sbill 709*1294Sbill while (c = *cp++) 710*1294Sbill putchar(c | QUOTE); 711*1294Sbill if (*v) 712*1294Sbill putchar(sep | QUOTE); 713*1294Sbill } 714*1294Sbill if (sep && nonl == 0) 715*1294Sbill putchar('\n'); 716*1294Sbill else 717*1294Sbill flush(); 718*1294Sbill if (setintr) 719*1294Sbill sighold(SIGINT); 720*1294Sbill if (gargv) 721*1294Sbill blkfree(gargv), gargv = 0; 722*1294Sbill } 723*1294Sbill 724*1294Sbill char **environ; 725*1294Sbill 726*1294Sbill dosetenv(v) 727*1294Sbill register char **v; 728*1294Sbill { 729*1294Sbill char *lp = globone(v[2]); 730*1294Sbill 731*1294Sbill setenv(v[1], lp); 732*1294Sbill if (eq(v[1], "PATH")) { 733*1294Sbill importpath(lp); 734*1294Sbill dohash(); 735*1294Sbill } 736*1294Sbill xfree(lp); 737*1294Sbill } 738*1294Sbill 739*1294Sbill dounsetenv(v) 740*1294Sbill register char **v; 741*1294Sbill { 742*1294Sbill 743*1294Sbill v++; 744*1294Sbill do 745*1294Sbill unsetenv(*v++); 746*1294Sbill while (*v); 747*1294Sbill } 748*1294Sbill 749*1294Sbill setenv(name, value) 750*1294Sbill char *name, *value; 751*1294Sbill { 752*1294Sbill register char **ep = environ; 753*1294Sbill register char *cp, *dp; 754*1294Sbill char *blk[2], **oep = ep; 755*1294Sbill 756*1294Sbill for (; *ep; ep++) { 757*1294Sbill for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 758*1294Sbill continue; 759*1294Sbill if (*cp != 0 || *dp != '=') 760*1294Sbill continue; 761*1294Sbill cp = strspl("=", value); 762*1294Sbill xfree(*ep); 763*1294Sbill *ep = strspl(name, cp); 764*1294Sbill xfree(cp); 765*1294Sbill scan(ep, trim); 766*1294Sbill return; 767*1294Sbill } 768*1294Sbill blk[0] = strspl(name, "="); blk[1] = 0; 769*1294Sbill environ = blkspl(environ, blk); 770*1294Sbill xfree((char *)oep); 771*1294Sbill setenv(name, value); 772*1294Sbill } 773*1294Sbill 774*1294Sbill unsetenv(name) 775*1294Sbill char *name; 776*1294Sbill { 777*1294Sbill register char **ep = environ; 778*1294Sbill register char *cp, *dp; 779*1294Sbill char **oep = ep; 780*1294Sbill 781*1294Sbill for (; *ep; ep++) { 782*1294Sbill for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 783*1294Sbill continue; 784*1294Sbill if (*cp != 0 || *dp != '=') 785*1294Sbill continue; 786*1294Sbill cp = *ep; 787*1294Sbill *ep = 0; 788*1294Sbill environ = blkspl(environ, ep+1); 789*1294Sbill *ep = cp; 790*1294Sbill xfree(cp); 791*1294Sbill xfree((char *)oep); 792*1294Sbill return; 793*1294Sbill } 794*1294Sbill } 795*1294Sbill 796*1294Sbill doumask(v) 797*1294Sbill register char **v; 798*1294Sbill { 799*1294Sbill register char *cp = v[1]; 800*1294Sbill register int i; 801*1294Sbill 802*1294Sbill if (cp == 0) { 803*1294Sbill i = umask(0); 804*1294Sbill umask(i); 805*1294Sbill printf("%o\n", i); 806*1294Sbill return; 807*1294Sbill } 808*1294Sbill i = 0; 809*1294Sbill while (digit(*cp) && *cp != '8' && *cp != '9') 810*1294Sbill i = i * 8 + *cp++ - '0'; 811*1294Sbill if (*cp || i < 0 || i > 0777) 812*1294Sbill bferr("Improper mask"); 813*1294Sbill umask(i); 814*1294Sbill } 815*1294Sbill 816*1294Sbill #include <sys/limit.h> 817*1294Sbill 818*1294Sbill struct limits { 819*1294Sbill int limconst; 820*1294Sbill char *limname; 821*1294Sbill int limdiv; 822*1294Sbill char *limscale; 823*1294Sbill } limits[] = { 824*1294Sbill LIM_NORAISE, "noraise", 1, "", 825*1294Sbill LIM_CPU, "cputime", 1, "seconds", 826*1294Sbill LIM_FSIZE, "filesize", 1024, "kbytes", 827*1294Sbill LIM_DATA, "datasize", 1024, "kbytes", 828*1294Sbill LIM_STACK, "stacksize", 1024, "kbytes", 829*1294Sbill LIM_CORE, "coredumpsize", 1024, "kbytes", 830*1294Sbill -1, 0, 831*1294Sbill }; 832*1294Sbill 833*1294Sbill struct limits * 834*1294Sbill findlim(cp) 835*1294Sbill char *cp; 836*1294Sbill { 837*1294Sbill register struct limits *lp, *res; 838*1294Sbill 839*1294Sbill res = 0; 840*1294Sbill for (lp = limits; lp->limconst >= 0; lp++) 841*1294Sbill if (prefix(cp, lp->limname)) { 842*1294Sbill if (res) 843*1294Sbill bferr("Ambiguous"); 844*1294Sbill res = lp; 845*1294Sbill } 846*1294Sbill if (res) 847*1294Sbill return (res); 848*1294Sbill bferr("No such limit"); 849*1294Sbill } 850*1294Sbill 851*1294Sbill dolimit(v) 852*1294Sbill register char **v; 853*1294Sbill { 854*1294Sbill register struct limits *lp; 855*1294Sbill register int limit; 856*1294Sbill 857*1294Sbill v++; 858*1294Sbill if (*v == 0) { 859*1294Sbill for (lp = limits+1; lp->limconst >= 0; lp++) 860*1294Sbill plim(lp); 861*1294Sbill if (vlimit(LIM_NORAISE, -1) && getuid()) 862*1294Sbill printf("Limits cannot be raised\n"); 863*1294Sbill return; 864*1294Sbill } 865*1294Sbill lp = findlim(v[0]); 866*1294Sbill if (v[1] == 0) { 867*1294Sbill plim(lp); 868*1294Sbill return; 869*1294Sbill } 870*1294Sbill limit = getval(lp, v+1); 871*1294Sbill setlim(lp, limit); 872*1294Sbill } 873*1294Sbill 874*1294Sbill getval(lp, v) 875*1294Sbill register struct limits *lp; 876*1294Sbill char **v; 877*1294Sbill { 878*1294Sbill register float f; 879*1294Sbill double atof(); 880*1294Sbill char *cp = *v++; 881*1294Sbill 882*1294Sbill f = atof(cp); 883*1294Sbill while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 884*1294Sbill cp++; 885*1294Sbill if (*cp == 0) { 886*1294Sbill if (*v == 0) 887*1294Sbill return ((int)(f+0.5) * lp->limdiv); 888*1294Sbill cp = *v; 889*1294Sbill } 890*1294Sbill if (lp->limconst == LIM_NORAISE) 891*1294Sbill goto badscal; 892*1294Sbill switch (*cp) { 893*1294Sbill 894*1294Sbill case ':': 895*1294Sbill if (lp->limconst != LIM_CPU) 896*1294Sbill goto badscal; 897*1294Sbill return ((int)(f * 60.0 + atof(cp+1))); 898*1294Sbill 899*1294Sbill case 'h': 900*1294Sbill if (lp->limconst != LIM_CPU) 901*1294Sbill goto badscal; 902*1294Sbill limtail(cp, "hours"); 903*1294Sbill f *= 3600.; 904*1294Sbill break; 905*1294Sbill 906*1294Sbill case 'm': 907*1294Sbill if (lp->limconst == LIM_CPU) { 908*1294Sbill limtail(cp, "minutes"); 909*1294Sbill f *= 60.; 910*1294Sbill break; 911*1294Sbill } 912*1294Sbill case 'M': 913*1294Sbill if (lp->limconst == LIM_CPU) 914*1294Sbill goto badscal; 915*1294Sbill *cp = 'm'; 916*1294Sbill limtail(cp, "megabytes"); 917*1294Sbill f *= 1024.*1024.; 918*1294Sbill break; 919*1294Sbill 920*1294Sbill case 's': 921*1294Sbill if (lp->limconst != LIM_CPU) 922*1294Sbill goto badscal; 923*1294Sbill limtail(cp, "seconds"); 924*1294Sbill break; 925*1294Sbill 926*1294Sbill case 'k': 927*1294Sbill if (lp->limconst == LIM_CPU) 928*1294Sbill goto badscal; 929*1294Sbill limtail(cp, "kbytes"); 930*1294Sbill f *= 1024; 931*1294Sbill break; 932*1294Sbill 933*1294Sbill case 'u': 934*1294Sbill limtail(cp, "unlimited"); 935*1294Sbill return (INFINITY); 936*1294Sbill 937*1294Sbill default: 938*1294Sbill badscal: 939*1294Sbill bferr("Improper or unknown scale factor"); 940*1294Sbill } 941*1294Sbill return ((int)(f+0.5)); 942*1294Sbill } 943*1294Sbill 944*1294Sbill limtail(cp, str0) 945*1294Sbill char *cp, *str0; 946*1294Sbill { 947*1294Sbill register char *str = str0; 948*1294Sbill 949*1294Sbill while (*cp && *cp == *str) 950*1294Sbill cp++, str++; 951*1294Sbill if (*cp) 952*1294Sbill error("Bad scaling; did you mean ``%s''?", str0); 953*1294Sbill } 954*1294Sbill 955*1294Sbill plim(lp) 956*1294Sbill register struct limits *lp; 957*1294Sbill { 958*1294Sbill register int lim; 959*1294Sbill 960*1294Sbill printf("%s \t", lp->limname); 961*1294Sbill lim = vlimit(lp->limconst, -1); 962*1294Sbill if (lim == INFINITY) 963*1294Sbill printf("unlimited"); 964*1294Sbill else if (lp->limconst == LIM_CPU) 965*1294Sbill psecs((long)lim); 966*1294Sbill else 967*1294Sbill printf("%d %s", lim / lp->limdiv, lp->limscale); 968*1294Sbill printf("\n"); 969*1294Sbill } 970*1294Sbill 971*1294Sbill dounlimit(v) 972*1294Sbill register char **v; 973*1294Sbill { 974*1294Sbill register struct limits *lp; 975*1294Sbill 976*1294Sbill v++; 977*1294Sbill if (*v == 0) { 978*1294Sbill for (lp = limits+1; lp->limconst >= 0; lp++) 979*1294Sbill setlim(lp, INFINITY); 980*1294Sbill return; 981*1294Sbill } 982*1294Sbill while (*v) { 983*1294Sbill lp = findlim(*v++); 984*1294Sbill setlim(lp, INFINITY); 985*1294Sbill } 986*1294Sbill } 987*1294Sbill 988*1294Sbill setlim(lp, limit) 989*1294Sbill register struct limits *lp; 990*1294Sbill { 991*1294Sbill 992*1294Sbill if (vlimit(lp->limconst, limit) < 0) 993*1294Sbill Perror(bname); 994*1294Sbill } 995*1294Sbill 996*1294Sbill dosuspend() 997*1294Sbill { 998*1294Sbill int old, ldisc; 999*1294Sbill short ctpgrp; 1000*1294Sbill 1001*1294Sbill if (loginsh) 1002*1294Sbill error("Can't suspend a login shell (yet)"); 1003*1294Sbill untty(); 1004*1294Sbill old = sigsys(SIGTSTP, SIG_DFL); 1005*1294Sbill kill(0, SIGTSTP); 1006*1294Sbill /* the shell stops here */ 1007*1294Sbill sigsys(SIGTSTP, old); 1008*1294Sbill if (tpgrp != -1) { 1009*1294Sbill retry: 1010*1294Sbill ioctl(FSHTTY, TIOCGPGRP, &ctpgrp); 1011*1294Sbill if (ctpgrp != opgrp) { 1012*1294Sbill old = sigsys(SIGTTIN, SIG_DFL); 1013*1294Sbill kill(0, SIGTTIN); 1014*1294Sbill sigsys(SIGTTIN, old); 1015*1294Sbill goto retry; 1016*1294Sbill } 1017*1294Sbill ioctl(FSHTTY, TIOCSPGRP, &shpgrp); 1018*1294Sbill setpgrp(0, shpgrp); 1019*1294Sbill } 1020*1294Sbill ioctl(FSHTTY, TIOCGETD, &oldisc); 1021*1294Sbill if (oldisc != NTTYDISC) { 1022*1294Sbill printf("Switching to new tty driver...\n"); 1023*1294Sbill ldisc = NTTYDISC; 1024*1294Sbill ioctl(FSHTTY, TIOCSETD, &ldisc); 1025*1294Sbill } 1026*1294Sbill } 1027*1294Sbill 1028*1294Sbill doeval(v) 1029*1294Sbill char **v; 1030*1294Sbill { 1031*1294Sbill char **oevalvec = evalvec; 1032*1294Sbill char *oevalp = evalp; 1033*1294Sbill jmp_buf osetexit; 1034*1294Sbill int reenter; 1035*1294Sbill char **gv = 0; 1036*1294Sbill 1037*1294Sbill v++; 1038*1294Sbill if (*v == 0) 1039*1294Sbill return; 1040*1294Sbill gflag = 0; rscan(v, tglob); 1041*1294Sbill if (gflag) { 1042*1294Sbill gv = v = glob(v); 1043*1294Sbill gargv = 0; 1044*1294Sbill if (v == 0) 1045*1294Sbill error("No match"); 1046*1294Sbill v = copyblk(v); 1047*1294Sbill } else 1048*1294Sbill scan(v, trim); 1049*1294Sbill getexit(osetexit); 1050*1294Sbill reenter = 0; 1051*1294Sbill setexit(); 1052*1294Sbill reenter++; 1053*1294Sbill if (reenter == 1) { 1054*1294Sbill evalvec = v; 1055*1294Sbill evalp = 0; 1056*1294Sbill process(0); 1057*1294Sbill } 1058*1294Sbill evalvec = oevalvec; 1059*1294Sbill evalp = oevalp; 1060*1294Sbill doneinp = 0; 1061*1294Sbill if (gv) 1062*1294Sbill blkfree(gv); 1063*1294Sbill resexit(osetexit); 1064*1294Sbill if (reenter >= 2) 1065*1294Sbill error(NOSTR); 1066*1294Sbill } 1067