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