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: }