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: #ifndef lint
   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(0) & ~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, omask;
 471: 
 472:     i = getn(v[1]);
 473:     if (setintr)
 474:         omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
 475:     lshift(v, 2);
 476:     while (i > 0) {
 477:         if (setintr)
 478:             (void) sigsetmask(omask);
 479:         reexecute(kp);
 480:         --i;
 481:     }
 482:     donefds();
 483:     if (setintr)
 484:         (void) sigsetmask(omask);
 485: }
 486: 
 487: doswbrk()
 488: {
 489: 
 490:     search(ZBRKSW, 0);
 491: }
 492: 
 493: srchx(cp)
 494:     register char *cp;
 495: {
 496:     register struct srch *sp, *sp1, *sp2;
 497:     register i;
 498: 
 499:     /*
 500: 	 * Binary search
 501: 	 * Sp1 is the beginning of the current search range.
 502: 	 * Sp2 is one past the end.
 503: 	 */
 504:     for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
 505:         sp = sp1 + (sp2 - sp1 >> 1);
 506:         if ((i = *cp - *sp->s_name) == 0 &&
 507:             (i = strcmp(cp, sp->s_name)) == 0)
 508:             return sp->s_value;
 509:         if (i < 0)
 510:             sp2 = sp;
 511:         else
 512:             sp1 = sp + 1;
 513:     }
 514:     return (-1);
 515: }
 516: 
 517: char    Stype;
 518: char    *Sgoal;
 519: 
 520: /*VARARGS2*/
 521: search(type, level, goal)
 522:     int type;
 523:     register int level;
 524:     char *goal;
 525: {
 526:     char wordbuf[BUFSIZ];
 527:     register char *aword = wordbuf;
 528:     register char *cp;
 529: 
 530:     Stype = type; Sgoal = goal;
 531:     if (type == ZGOTO)
 532:         bseek((off_t)0);
 533:     do {
 534:         if (intty && fseekp == feobp)
 535:             printf("? "), flush();
 536:         aword[0] = 0;
 537:         (void) getword(aword);
 538:         switch (srchx(aword)) {
 539: 
 540:         case ZELSE:
 541:             if (level == 0 && type == ZIF)
 542:                 return;
 543:             break;
 544: 
 545:         case ZIF:
 546:             while (getword(aword))
 547:                 continue;
 548:             if ((type == ZIF || type == ZELSE) && eq(aword, "then"))
 549:                 level++;
 550:             break;
 551: 
 552:         case ZENDIF:
 553:             if (type == ZIF || type == ZELSE)
 554:                 level--;
 555:             break;
 556: 
 557:         case ZFOREACH:
 558:         case ZWHILE:
 559:             if (type == ZBREAK)
 560:                 level++;
 561:             break;
 562: 
 563:         case ZEND:
 564:             if (type == ZBREAK)
 565:                 level--;
 566:             break;
 567: 
 568:         case ZSWITCH:
 569:             if (type == ZSWITCH || type == ZBRKSW)
 570:                 level++;
 571:             break;
 572: 
 573:         case ZENDSW:
 574:             if (type == ZSWITCH || type == ZBRKSW)
 575:                 level--;
 576:             break;
 577: 
 578:         case ZLABEL:
 579:             if (type == ZGOTO && getword(aword) && eq(aword, goal))
 580:                 level = -1;
 581:             break;
 582: 
 583:         default:
 584:             if (type != ZGOTO && (type != ZSWITCH || level != 0))
 585:                 break;
 586:             if (lastchr(aword) != ':')
 587:                 break;
 588:             aword[strlen(aword) - 1] = 0;
 589:             if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default"))
 590:                 level = -1;
 591:             break;
 592: 
 593:         case ZCASE:
 594:             if (type != ZSWITCH || level != 0)
 595:                 break;
 596:             (void) getword(aword);
 597:             if (lastchr(aword) == ':')
 598:                 aword[strlen(aword) - 1] = 0;
 599:             cp = strip(Dfix1(aword));
 600:             if (Gmatch(goal, cp))
 601:                 level = -1;
 602:             xfree(cp);
 603:             break;
 604: 
 605:         case ZDEFAULT:
 606:             if (type == ZSWITCH && level == 0)
 607:                 level = -1;
 608:             break;
 609:         }
 610:         (void) getword(NOSTR);
 611:     } while (level >= 0);
 612: }
 613: 
 614: getword(wp)
 615:     register char *wp;
 616: {
 617:     register int found = 0;
 618:     register int c, d;
 619: 
 620:     c = readc(1);
 621:     d = 0;
 622:     do {
 623:         while (c == ' ' || c == '\t')
 624:             c = readc(1);
 625:         if (c == '#')
 626:             do
 627:                 c = readc(1);
 628:             while (c >= 0 && c != '\n');
 629:         if (c < 0)
 630:             goto past;
 631:         if (c == '\n') {
 632:             if (wp)
 633:                 break;
 634:             return (0);
 635:         }
 636:         unreadc(c);
 637:         found = 1;
 638:         do {
 639:             c = readc(1);
 640:             if (c == '\\' && (c = readc(1)) == '\n')
 641:                 c = ' ';
 642:             if (c == '\'' || c == '"')
 643:                 if (d == 0)
 644:                     d = c;
 645:                 else if (d == c)
 646:                     d = 0;
 647:             if (c < 0)
 648:                 goto past;
 649:             if (wp)
 650:                 *wp++ = c;
 651:         } while ((d || c != ' ' && c != '\t') && c != '\n');
 652:     } while (wp == 0);
 653:     unreadc(c);
 654:     if (found)
 655:         *--wp = 0;
 656:     return (found);
 657: 
 658: past:
 659:     switch (Stype) {
 660: 
 661:     case ZIF:
 662:         bferr("then/endif not found");
 663: 
 664:     case ZELSE:
 665:         bferr("endif not found");
 666: 
 667:     case ZBRKSW:
 668:     case ZSWITCH:
 669:         bferr("endsw not found");
 670: 
 671:     case ZBREAK:
 672:         bferr("end not found");
 673: 
 674:     case ZGOTO:
 675:         setname(Sgoal);
 676:         bferr("label not found");
 677:     }
 678:     /*NOTREACHED*/
 679: }
 680: 
 681: toend()
 682: {
 683: 
 684:     if (whyles->w_end == 0) {
 685:         search(ZBREAK, 0);
 686:         whyles->w_end = btell() - 1;
 687:     } else
 688:         bseek(whyles->w_end);
 689:     wfree();
 690: }
 691: 
 692: wfree()
 693: {
 694:     long o = btell();
 695: 
 696:     while (whyles) {
 697:         register struct whyle *wp = whyles;
 698:         register struct whyle *nwp = wp->w_next;
 699: 
 700:         if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end))
 701:             break;
 702:         if (wp->w_fe0)
 703:             blkfree(wp->w_fe0);
 704:         if (wp->w_fename)
 705:             xfree(wp->w_fename);
 706:         xfree((char *)wp);
 707:         whyles = nwp;
 708:     }
 709: }
 710: 
 711: doecho(v)
 712:     char **v;
 713: {
 714: 
 715:     echo(' ', v);
 716: }
 717: 
 718: doglob(v)
 719:     char **v;
 720: {
 721: 
 722:     echo(0, v);
 723:     flush();
 724: }
 725: 
 726: echo(sep, v)
 727:     char sep;
 728:     register char **v;
 729: {
 730:     register char *cp;
 731:     int nonl = 0;
 732: 
 733:     if (setintr)
 734:         (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT));
 735:     v++;
 736:     if (*v == 0)
 737:         return;
 738:     gflag = 0, tglob(v);
 739:     if (gflag) {
 740:         v = glob(v);
 741:         if (v == 0)
 742:             bferr("No match");
 743:     } else
 744:         trim(v);
 745:     if (sep == ' ' && *v && !strcmp(*v, "-n"))
 746:         nonl++, v++;
 747:     while (cp = *v++) {
 748:         register int c;
 749: 
 750:         while (c = *cp++)
 751:             putchar(c | QUOTE);
 752:         if (*v)
 753:             putchar(sep | QUOTE);
 754:     }
 755:     if (sep && nonl == 0)
 756:         putchar('\n');
 757:     else
 758:         flush();
 759:     if (setintr)
 760:         (void) sigblock(sigmask(SIGINT));
 761:     if (gargv)
 762:         blkfree(gargv), gargv = 0;
 763: }
 764: 
 765: char    **environ;
 766: 
 767: dosetenv(v)
 768:     register char **v;
 769: {
 770:     char *vp, *lp;
 771: 
 772:     v++;
 773:     if ((vp = *v++) == 0) {
 774:         register char **ep;
 775: 
 776:         if (setintr)
 777:             (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));
 778:         for (ep = environ; *ep; ep++)
 779:             printf("%s\n", *ep);
 780:         return;
 781:     }
 782:     if ((lp = *v++) == 0)
 783:         lp = "";
 784:     setenv(vp, lp = globone(lp));
 785:     if (eq(vp, "PATH")) {
 786:         importpath(lp);
 787:         dohash();
 788:     }
 789:     xfree(lp);
 790: }
 791: 
 792: dounsetenv(v)
 793:     register char **v;
 794: {
 795: 
 796:     v++;
 797:     do
 798:         unsetenv(*v++);
 799:     while (*v);
 800: }
 801: 
 802: setenv(name, val)
 803:     char *name, *val;
 804: {
 805:     register char **ep = environ;
 806:     register char *cp, *dp;
 807:     char *blk[2], **oep = ep;
 808: 
 809:     for (; *ep; ep++) {
 810:         for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
 811:             continue;
 812:         if (*cp != 0 || *dp != '=')
 813:             continue;
 814:         cp = strspl("=", val);
 815:         xfree(*ep);
 816:         *ep = strspl(name, cp);
 817:         xfree(cp);
 818:         trim(ep);
 819:         return;
 820:     }
 821:     blk[0] = strspl(name, "="); blk[1] = 0;
 822:     environ = blkspl(environ, blk);
 823:     xfree((char *)oep);
 824:     setenv(name, val);
 825: }
 826: 
 827: unsetenv(name)
 828:     char *name;
 829: {
 830:     register char **ep = environ;
 831:     register char *cp, *dp;
 832:     char **oep = ep;
 833: 
 834:     for (; *ep; ep++) {
 835:         for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
 836:             continue;
 837:         if (*cp != 0 || *dp != '=')
 838:             continue;
 839:         cp = *ep;
 840:         *ep = 0;
 841:         environ = blkspl(environ, ep+1);
 842:         *ep = cp;
 843:         xfree(cp);
 844:         xfree((char *)oep);
 845:         return;
 846:     }
 847: }
 848: 
 849: doumask(v)
 850:     register char **v;
 851: {
 852:     register char *cp = v[1];
 853:     register int i;
 854: 
 855:     if (cp == 0) {
 856:         i = umask(0);
 857:         (void) umask(i);
 858:         printf("%o\n", i);
 859:         return;
 860:     }
 861:     i = 0;
 862:     while (digit(*cp) && *cp != '8' && *cp != '9')
 863:         i = i * 8 + *cp++ - '0';
 864:     if (*cp || i < 0 || i > 0777)
 865:         bferr("Improper mask");
 866:     (void) umask(i);
 867: }
 868: 
 869: 
 870: struct limits {
 871:     int limconst;
 872:     char    *limname;
 873:     int limdiv;
 874:     char    *limscale;
 875: } limits[] = {
 876:     RLIMIT_CPU, "cputime",  1,  "seconds",
 877:     RLIMIT_FSIZE,   "filesize", 1024,   "kbytes",
 878:     RLIMIT_DATA,    "datasize", 1024,   "kbytes",
 879:     RLIMIT_STACK,   "stacksize",    1024,   "kbytes",
 880:     RLIMIT_CORE,    "coredumpsize", 1024,   "kbytes",
 881:     RLIMIT_RSS, "memoryuse",    1024,   "kbytes",
 882:     -1,     0,
 883: };
 884: 
 885: struct limits *
 886: findlim(cp)
 887:     char *cp;
 888: {
 889:     register struct limits *lp, *res;
 890: 
 891:     res = 0;
 892:     for (lp = limits; lp->limconst >= 0; lp++)
 893:         if (prefix(cp, lp->limname)) {
 894:             if (res)
 895:                 bferr("Ambiguous");
 896:             res = lp;
 897:         }
 898:     if (res)
 899:         return (res);
 900:     bferr("No such limit");
 901:     /*NOTREACHED*/
 902: }
 903: 
 904: dolimit(v)
 905:     register char **v;
 906: {
 907:     register struct limits *lp;
 908:     register int limit;
 909:     char hard = 0;
 910: 
 911:     v++;
 912:     if (*v && eq(*v, "-h")) {
 913:         hard = 1;
 914:         v++;
 915:     }
 916:     if (*v == 0) {
 917:         for (lp = limits; lp->limconst >= 0; lp++)
 918:             plim(lp, hard);
 919:         return;
 920:     }
 921:     lp = findlim(v[0]);
 922:     if (v[1] == 0) {
 923:         plim(lp,  hard);
 924:         return;
 925:     }
 926:     limit = getval(lp, v+1);
 927:     if (setlim(lp, hard, limit) < 0)
 928:         error(NOSTR);
 929: }
 930: 
 931: getval(lp, v)
 932:     register struct limits *lp;
 933:     char **v;
 934: {
 935:     register float f;
 936:     double atof();
 937:     char *cp = *v++;
 938: 
 939:     f = atof(cp);
 940:     while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
 941:         cp++;
 942:     if (*cp == 0) {
 943:         if (*v == 0)
 944:             return ((int)(f+0.5) * lp->limdiv);
 945:         cp = *v;
 946:     }
 947:     switch (*cp) {
 948: 
 949:     case ':':
 950:         if (lp->limconst != RLIMIT_CPU)
 951:             goto badscal;
 952:         return ((int)(f * 60.0 + atof(cp+1)));
 953: 
 954:     case 'h':
 955:         if (lp->limconst != RLIMIT_CPU)
 956:             goto badscal;
 957:         limtail(cp, "hours");
 958:         f *= 3600.;
 959:         break;
 960: 
 961:     case 'm':
 962:         if (lp->limconst == RLIMIT_CPU) {
 963:             limtail(cp, "minutes");
 964:             f *= 60.;
 965:             break;
 966:         }
 967:     case 'M':
 968:         if (lp->limconst == RLIMIT_CPU)
 969:             goto badscal;
 970:         *cp = 'm';
 971:         limtail(cp, "megabytes");
 972:         f *= 1024.*1024.;
 973:         break;
 974: 
 975:     case 's':
 976:         if (lp->limconst != RLIMIT_CPU)
 977:             goto badscal;
 978:         limtail(cp, "seconds");
 979:         break;
 980: 
 981:     case 'k':
 982:         if (lp->limconst == RLIMIT_CPU)
 983:             goto badscal;
 984:         limtail(cp, "kbytes");
 985:         f *= 1024;
 986:         break;
 987: 
 988:     case 'u':
 989:         limtail(cp, "unlimited");
 990:         return (RLIM_INFINITY);
 991: 
 992:     default:
 993: badscal:
 994:         bferr("Improper or unknown scale factor");
 995:     }
 996:     return ((int)(f+0.5));
 997: }
 998: 
 999: limtail(cp, str0)
1000:     char *cp, *str0;
1001: {
1002:     register char *str = str0;
1003: 
1004:     while (*cp && *cp == *str)
1005:         cp++, str++;
1006:     if (*cp)
1007:         error("Bad scaling; did you mean ``%s''?", str0);
1008: }
1009: 
1010: plim(lp, hard)
1011:     register struct limits *lp;
1012:     char hard;
1013: {
1014:     struct rlimit rlim;
1015:     int limit;
1016: 
1017:     printf("%s \t", lp->limname);
1018:     (void) getrlimit(lp->limconst, &rlim);
1019:     limit = hard ? rlim.rlim_max : rlim.rlim_cur;
1020:     if (limit == RLIM_INFINITY)
1021:         printf("unlimited");
1022:     else if (lp->limconst == RLIMIT_CPU)
1023:         psecs((long)limit);
1024:     else
1025:         printf("%d %s", limit / lp->limdiv, lp->limscale);
1026:     printf("\n");
1027: }
1028: 
1029: dounlimit(v)
1030:     register char **v;
1031: {
1032:     register struct limits *lp;
1033:     int err = 0;
1034:     char hard = 0;
1035: 
1036:     v++;
1037:     if (*v && eq(*v, "-h")) {
1038:         hard = 1;
1039:         v++;
1040:     }
1041:     if (*v == 0) {
1042:         for (lp = limits; lp->limconst >= 0; lp++)
1043:             if (setlim(lp, hard, (int)RLIM_INFINITY) < 0)
1044:                 err++;
1045:         if (err)
1046:             error(NOSTR);
1047:         return;
1048:     }
1049:     while (*v) {
1050:         lp = findlim(*v++);
1051:         if (setlim(lp, hard, (int)RLIM_INFINITY) < 0)
1052:             error(NOSTR);
1053:     }
1054: }
1055: 
1056: setlim(lp, hard, limit)
1057:     register struct limits *lp;
1058:     char hard;
1059: {
1060:     struct rlimit rlim;
1061: 
1062:     (void) getrlimit(lp->limconst, &rlim);
1063:     if (hard)
1064:         rlim.rlim_max = limit;
1065:     else if (limit == RLIM_INFINITY && geteuid() != 0)
1066:         rlim.rlim_cur = rlim.rlim_max;
1067:     else
1068:         rlim.rlim_cur = limit;
1069:     if (setrlimit(lp->limconst, &rlim) < 0) {
1070:         printf("%s: %s: Can't %s%s limit\n", bname, lp->limname,
1071:             limit == RLIM_INFINITY ? "remove" : "set",
1072:             hard ? " hard" : "");
1073:         return (-1);
1074:     }
1075:     return (0);
1076: }
1077: 
1078: dosuspend()
1079: {
1080:     int ldisc, ctpgrp;
1081:     int (*old)();
1082: 
1083:     if (loginsh)
1084:         error("Can't suspend a login shell (yet)");
1085:     untty();
1086:     old = signal(SIGTSTP, SIG_DFL);
1087:     (void) kill(0, SIGTSTP);
1088:     /* the shell stops here */
1089:     (void) signal(SIGTSTP, old);
1090:     if (tpgrp != -1) {
1091: retry:
1092:         (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp);
1093:         if (ctpgrp != opgrp) {
1094:             old = signal(SIGTTIN, SIG_DFL);
1095:             (void) kill(0, SIGTTIN);
1096:             (void) signal(SIGTTIN, old);
1097:             goto retry;
1098:         }
1099:         (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp);
1100:         (void) setpgrp(0, shpgrp);
1101:     }
1102:     (void) ioctl(FSHTTY, TIOCGETD, (char *)&oldisc);
1103:     if (oldisc != NTTYDISC) {
1104:         printf("Switching to new tty driver...\n");
1105:         ldisc = NTTYDISC;
1106:         (void) ioctl(FSHTTY, TIOCSETD, (char *)&ldisc);
1107:     }
1108: }
1109: 
1110: doeval(v)
1111:     char **v;
1112: {
1113:     char **oevalvec = evalvec;
1114:     char *oevalp = evalp;
1115:     jmp_buf osetexit;
1116:     int reenter;
1117:     char **gv = 0;
1118: 
1119:     v++;
1120:     if (*v == 0)
1121:         return;
1122:     gflag = 0, tglob(v);
1123:     if (gflag) {
1124:         gv = v = glob(v);
1125:         gargv = 0;
1126:         if (v == 0)
1127:             error("No match");
1128:         v = copyblk(v);
1129:     } else
1130:         trim(v);
1131:     getexit(osetexit);
1132:     reenter = 0;
1133:     setexit();
1134:     reenter++;
1135:     if (reenter == 1) {
1136:         evalvec = v;
1137:         evalp = 0;
1138:         process(0);
1139:     }
1140:     evalvec = oevalvec;
1141:     evalp = oevalp;
1142:     doneinp = 0;
1143:     if (gv)
1144:         blkfree(gv);
1145:     resexit(osetexit);
1146:     if (reenter >= 2)
1147:         error(NOSTR);
1148: }

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 711; used 2 times
doelse defined in line 263; used 2 times
doend defined in line 428; used 2 times
doeval defined in line 1110; used 2 times
doexit defined in line 321; used 2 times
doforeach defined in line 341; used 2 times
doglob defined in line 718; 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 904; 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 767; used 2 times
dosuspend defined in line 1078; used 2 times
doswbrk defined in line 487; used 2 times
doswitch defined in line 294; used 2 times
doumask defined in line 849; used 2 times
dounlimit defined in line 1029; used 2 times
dounsetenv defined in line 792; used 2 times
dowhile defined in line 376; used 2 times
dozip defined in line 122; used 5 times
echo defined in line 726; used 2 times
findlim defined in line 885; used 2 times
func defined in line 62; used 1 times
getval defined in line 931; used 1 times
getword defined in line 614; used 5 times
isbfunc defined in line 18; used 2 times
islogin defined in line 198; used 2 times
limtail defined in line 999; used 6 times
plim defined in line 1010; 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 521; used 9 times
setenv defined in line 802; used 6 times
setlim defined in line 1056; used 3 times
srchx defined in line 493; used 2 times
toend defined in line 681; used 2 times
unalias defined in line 157; used 2 times
unsetenv defined in line 827; used 1 times
wfree defined in line 692; used 3 times

Defined variables

Sgoal defined in line 518; used 2 times
Stype defined in line 517; used 2 times
environ defined in line 765; used 7 times
limits defined in line 875; used 3 times
sccsid defined in line 8; never used

Defined struct's

limits defined in line 870; used 14 times
Last modified: 1986-05-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3006
Valid CSS Valid XHTML 1.0 Strict