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

Defined functions

doagain defined in line 445; used 4 times
doalias defined in line 134; used 2 times
dobreak defined in line 312; used 3 times
docontin defined in line 437; used 2 times
doecho defined in line 712; used 2 times
doelse defined in line 263; used 2 times
doend defined in line 428; used 2 times
doeval defined in line 1116; used 2 times
doexit defined in line 321; used 2 times
doforeach defined in line 341; used 2 times
doglob defined in line 719; used 2 times
dogoto defined in line 269; used 2 times
doif defined in line 208; used 2 times
dolabel defined in line 78; used 2 times
dolimit defined in line 906; used 2 times
dologin defined in line 171; used 2 times
dologout defined in line 164; used 2 times
donewgrp defined in line 184; used 2 times
donohup defined in line 109; used 2 times
doonintr defined in line 83; used 2 times
dorepeat defined in line 466; used 2 times
dosetenv defined in line 768; used 2 times
dosuspend defined in line 1084; used 2 times
doswbrk defined in line 488; used 2 times
doswitch defined in line 294; used 2 times
doumask defined in line 850; used 2 times
dounlimit defined in line 1033; used 2 times
dounsetenv defined in line 793; used 2 times
dowhile defined in line 376; used 2 times
dozip defined in line 122; used 5 times
echo defined in line 727; used 2 times
findlim defined in line 887; used 2 times
func defined in line 62; used 1 times
getval defined in line 934; used 2 times
getword defined in line 615; used 5 times
isbfunc defined in line 18; used 2 times
islogin defined in line 198; used 2 times
limtail defined in line 1003; used 6 times
plim defined in line 1014; used 2 times
preread defined in line 416; used 2 times
prvars defined in line 128; used 2 times
reexecute defined in line 248; used 2 times
search defined in line 522; used 9 times
setenv defined in line 803; used 6 times
setlim defined in line 1060; used 3 times
srchx defined in line 494; used 2 times
toend defined in line 682; used 2 times
unalias defined in line 157; used 2 times
unsetenv defined in line 828; used 1 times
wfree defined in line 693; used 3 times

Defined variables

Sgoal defined in line 519; used 2 times
Stype defined in line 518; used 2 times
environ defined in line 766; used 7 times
limits defined in line 877; used 3 times
sccsid defined in line 8; never used

Defined struct's

limits defined in line 872; used 14 times
Last modified: 1991-08-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6881
Valid CSS Valid XHTML 1.0 Strict