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