|
|
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.5 (Berkeley) 5/19/88"; ! 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: cshputchar(c | QUOTE); ! 753: if (*v) ! 754: cshputchar(sep | QUOTE); ! 755: } ! 756: if (sep && nonl == 0) ! 757: cshputchar('\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: struct limits { ! 872: int limconst; ! 873: char *limname; ! 874: int limdiv; ! 875: char *limscale; ! 876: } limits[] = { ! 877: RLIMIT_CPU, "cputime", 1, "seconds", ! 878: RLIMIT_FSIZE, "filesize", 1024, "kbytes", ! 879: RLIMIT_DATA, "datasize", 1024, "kbytes", ! 880: RLIMIT_STACK, "stacksize", 1024, "kbytes", ! 881: RLIMIT_CORE, "coredumpsize", 1024, "kbytes", ! 882: RLIMIT_RSS, "memoryuse", 1024, "kbytes", ! 883: -1, 0, ! 884: }; ! 885: ! 886: struct limits * ! 887: findlim(cp) ! 888: char *cp; ! 889: { ! 890: register struct limits *lp, *res; ! 891: ! 892: res = 0; ! 893: for (lp = limits; lp->limconst >= 0; lp++) ! 894: if (prefix(cp, lp->limname)) { ! 895: if (res) ! 896: bferr("Ambiguous"); ! 897: res = lp; ! 898: } ! 899: if (res) ! 900: return (res); ! 901: bferr("No such limit"); ! 902: /*NOTREACHED*/ ! 903: } ! 904: ! 905: dolimit(v) ! 906: register char **v; ! 907: { ! 908: register struct limits *lp; ! 909: register int limit; ! 910: char hard = 0; ! 911: ! 912: v++; ! 913: if (*v && eq(*v, "-h")) { ! 914: hard = 1; ! 915: v++; ! 916: } ! 917: if (*v == 0) { ! 918: for (lp = limits; lp->limconst >= 0; lp++) ! 919: plim(lp, hard); ! 920: return; ! 921: } ! 922: lp = findlim(v[0]); ! 923: if (v[1] == 0) { ! 924: plim(lp, hard); ! 925: return; ! 926: } ! 927: limit = getval(lp, v+1); ! 928: if (setlim(lp, hard, limit) < 0) ! 929: error(NOSTR); ! 930: } ! 931: ! 932: getval(lp, v) ! 933: register struct limits *lp; ! 934: char **v; ! 935: { ! 936: register float f; ! 937: double atof(); ! 938: char *cp = *v++; ! 939: ! 940: f = atof(cp); ! 941: while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') ! 942: cp++; ! 943: if (*cp == 0) { ! 944: if (*v == 0) ! 945: return ((int)(f+0.5) * lp->limdiv); ! 946: cp = *v; ! 947: } ! 948: switch (*cp) { ! 949: ! 950: case ':': ! 951: if (lp->limconst != RLIMIT_CPU) ! 952: goto badscal; ! 953: return ((int)(f * 60.0 + atof(cp+1))); ! 954: ! 955: case 'h': ! 956: if (lp->limconst != RLIMIT_CPU) ! 957: goto badscal; ! 958: limtail(cp, "hours"); ! 959: f *= 3600.; ! 960: break; ! 961: ! 962: case 'm': ! 963: if (lp->limconst == RLIMIT_CPU) { ! 964: limtail(cp, "minutes"); ! 965: f *= 60.; ! 966: break; ! 967: } ! 968: case 'M': ! 969: if (lp->limconst == RLIMIT_CPU) ! 970: goto badscal; ! 971: *cp = 'm'; ! 972: limtail(cp, "megabytes"); ! 973: f *= 1024.*1024.; ! 974: break; ! 975: ! 976: case 's': ! 977: if (lp->limconst != RLIMIT_CPU) ! 978: goto badscal; ! 979: limtail(cp, "seconds"); ! 980: break; ! 981: ! 982: case 'k': ! 983: if (lp->limconst == RLIMIT_CPU) ! 984: goto badscal; ! 985: limtail(cp, "kbytes"); ! 986: f *= 1024; ! 987: break; ! 988: ! 989: case 'u': ! 990: limtail(cp, "unlimited"); ! 991: return (RLIM_INFINITY); ! 992: ! 993: default: ! 994: badscal: ! 995: bferr("Improper or unknown scale factor"); ! 996: } ! 997: return ((int)(f+0.5)); ! 998: } ! 999: ! 1000: limtail(cp, str0) ! 1001: char *cp, *str0; ! 1002: { ! 1003: register char *str = str0; ! 1004: ! 1005: while (*cp && *cp == *str) ! 1006: cp++, str++; ! 1007: if (*cp) ! 1008: error("Bad scaling; did you mean ``%s''?", str0); ! 1009: } ! 1010: ! 1011: plim(lp, hard) ! 1012: register struct limits *lp; ! 1013: char hard; ! 1014: { ! 1015: struct rlimit rlim; ! 1016: int limit; ! 1017: ! 1018: printf("%s \t", lp->limname); ! 1019: (void) getrlimit(lp->limconst, &rlim); ! 1020: limit = hard ? rlim.rlim_max : rlim.rlim_cur; ! 1021: if (limit == RLIM_INFINITY) ! 1022: printf("unlimited"); ! 1023: else if (lp->limconst == RLIMIT_CPU) ! 1024: psecs((long)limit); ! 1025: else ! 1026: printf("%d %s", limit / lp->limdiv, lp->limscale); ! 1027: printf("\n"); ! 1028: } ! 1029: ! 1030: dounlimit(v) ! 1031: register char **v; ! 1032: { ! 1033: register struct limits *lp; ! 1034: int err = 0; ! 1035: char hard = 0; ! 1036: ! 1037: v++; ! 1038: if (*v && eq(*v, "-h")) { ! 1039: hard = 1; ! 1040: v++; ! 1041: } ! 1042: if (*v == 0) { ! 1043: for (lp = limits; lp->limconst >= 0; lp++) ! 1044: if (setlim(lp, hard, (int)RLIM_INFINITY) < 0) ! 1045: err++; ! 1046: if (err) ! 1047: error(NOSTR); ! 1048: return; ! 1049: } ! 1050: while (*v) { ! 1051: lp = findlim(*v++); ! 1052: if (setlim(lp, hard, (int)RLIM_INFINITY) < 0) ! 1053: error(NOSTR); ! 1054: } ! 1055: } ! 1056: ! 1057: setlim(lp, hard, limit) ! 1058: register struct limits *lp; ! 1059: char hard; ! 1060: { ! 1061: struct rlimit rlim; ! 1062: ! 1063: (void) getrlimit(lp->limconst, &rlim); ! 1064: if (hard) ! 1065: rlim.rlim_max = limit; ! 1066: else if (limit == RLIM_INFINITY && geteuid() != 0) ! 1067: rlim.rlim_cur = rlim.rlim_max; ! 1068: else ! 1069: rlim.rlim_cur = limit; ! 1070: if (setrlimit(lp->limconst, &rlim) < 0) { ! 1071: printf("%s: %s: Can't %s%s limit\n", bname, lp->limname, ! 1072: limit == RLIM_INFINITY ? "remove" : "set", ! 1073: hard ? " hard" : ""); ! 1074: return (-1); ! 1075: } ! 1076: return (0); ! 1077: } ! 1078: ! 1079: dosuspend() ! 1080: { ! 1081: int ldisc, ctpgrp; ! 1082: int (*old)(); ! 1083: ! 1084: if (loginsh) ! 1085: error("Can't suspend a login shell (yet)"); ! 1086: untty(); ! 1087: old = signal(SIGTSTP, SIG_DFL); ! 1088: (void) kill(0, SIGTSTP); ! 1089: /* the shell stops here */ ! 1090: (void) signal(SIGTSTP, old); ! 1091: if (tpgrp != -1) { ! 1092: retry: ! 1093: (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp); ! 1094: if (ctpgrp != opgrp) { ! 1095: old = signal(SIGTTIN, SIG_DFL); ! 1096: (void) kill(0, SIGTTIN); ! 1097: (void) signal(SIGTTIN, old); ! 1098: goto retry; ! 1099: } ! 1100: (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp); ! 1101: (void) setpgrp(0, shpgrp); ! 1102: } ! 1103: (void) ioctl(FSHTTY, TIOCGETD, (char *)&oldisc); ! 1104: if (oldisc != NTTYDISC) { ! 1105: printf("Switching to new tty driver...\n"); ! 1106: ldisc = NTTYDISC; ! 1107: (void) ioctl(FSHTTY, TIOCSETD, (char *)&ldisc); ! 1108: } ! 1109: } ! 1110: ! 1111: doeval(v) ! 1112: char **v; ! 1113: { ! 1114: char **oevalvec = evalvec; ! 1115: char *oevalp = evalp; ! 1116: jmp_buf osetexit; ! 1117: int reenter; ! 1118: char **gv = 0; ! 1119: ! 1120: v++; ! 1121: if (*v == 0) ! 1122: return; ! 1123: gflag = 0, tglob(v); ! 1124: if (gflag) { ! 1125: gv = v = glob(v); ! 1126: gargv = 0; ! 1127: if (v == 0) ! 1128: error("No match"); ! 1129: v = copyblk(v); ! 1130: } else ! 1131: trim(v); ! 1132: getexit(osetexit); ! 1133: reenter = 0; ! 1134: setexit(); ! 1135: reenter++; ! 1136: if (reenter == 1) { ! 1137: evalvec = v; ! 1138: evalp = 0; ! 1139: process(0); ! 1140: } ! 1141: evalvec = oevalvec; ! 1142: evalp = oevalp; ! 1143: doneinp = 0; ! 1144: if (gv) ! 1145: blkfree(gv); ! 1146: resexit(osetexit); ! 1147: if (reenter >= 2) ! 1148: error(NOSTR); ! 1149: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.