|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: #include "sh.h" ! 3: ! 4: /* ! 5: * C shell ! 6: */ ! 7: ! 8: struct biltins * ! 9: isbfunc(cp) ! 10: register char *cp; ! 11: { ! 12: register char *dp; ! 13: register struct biltins *bp; ! 14: ! 15: if (lastchr(cp) == ':') ! 16: return ((struct biltins *) 1); ! 17: for (bp = bfunc; dp = bp->bname; bp++) { ! 18: if (dp[0] == cp[0] && eq(dp, cp)) ! 19: return (bp); ! 20: if (dp[0] > cp[0]) ! 21: break; ! 22: } ! 23: return (0); ! 24: } ! 25: ! 26: func(t) ! 27: register struct command *t; ! 28: { ! 29: register struct biltins *bp; ! 30: int i; ! 31: ! 32: bp = bfunc; ! 33: if (lastchr(t->t_dcom[0]) == ':') { ! 34: xechoit(t->t_dcom); ! 35: if (!eq(t->t_dcom[0], ":") && t->t_dcom[1]) ! 36: error("No args on labels"); ! 37: return (1); ! 38: } ! 39: bp = isbfunc(t->t_dcom[0]); ! 40: if (bp == 0) ! 41: return (0); ! 42: /* timed builtins must go in background if output is pipe, or &'ed */ ! 43: if (eq(bp->bname, "time")) ! 44: if ((t->t_dflg & FAND) || (t->t_dflg & FPOU)) ! 45: return (0); ! 46: if (eq(bp->bname, "nohup") && t->t_dcom[1]) ! 47: return (0); ! 48: xechoit(t->t_dcom); ! 49: setname(bp->bname); ! 50: i = blklen(t->t_dcom) - 1; ! 51: if (i < bp->minargs) ! 52: bferr("Too few arguments"); ! 53: if (i > bp->maxargs) ! 54: bferr("Too many arguments"); ! 55: i = (*bp->bfunct)(t->t_dcom, t); ! 56: /* time and nice may not do their deeds, all others guarantee too */ ! 57: return (eq(bp->bname, "time") || eq(bp->bname, "nice") ? i : 1); ! 58: } ! 59: ! 60: doonintr(v) ! 61: char **v; ! 62: { ! 63: register char *cp; ! 64: register char *vv = v[1]; ! 65: ! 66: if (parintr == SIG_IGN) ! 67: return; ! 68: if (setintr && intty) ! 69: bferr("Can't from terminal"); ! 70: cp = gointr, gointr = 0, xfree(cp); ! 71: if (vv == 0) { ! 72: signal(SIGINT, setintr ? SIG_IGN : SIG_DFL); ! 73: gointr = 0; ! 74: } else if (eq((vv = strip(vv)), "-")) { ! 75: signal(SIGINT, SIG_IGN); ! 76: gointr = "-"; ! 77: } else { ! 78: gointr = savestr(vv); ! 79: signal(SIGINT, pintr); ! 80: } ! 81: } ! 82: ! 83: donohup() ! 84: { ! 85: ! 86: if (intty) ! 87: bferr("Can't from terminal"); ! 88: if (setintr == 0) { ! 89: signal(SIGHUP, SIG_IGN); ! 90: #ifdef CC ! 91: submit(getpid()); ! 92: #endif ! 93: } ! 94: } ! 95: ! 96: dozip() ! 97: { ! 98: ! 99: ; ! 100: } ! 101: ! 102: chngd(vp) ! 103: register char **vp; ! 104: { ! 105: register int i; ! 106: register char *dp; ! 107: ! 108: vp++; ! 109: dp = *vp; ! 110: if (dp) ! 111: dp = globone(dp); ! 112: else { ! 113: dp = value("home"); ! 114: if (*dp == 0) ! 115: bferr("No home"); ! 116: } ! 117: i = chdir(dp); ! 118: if (*vp) ! 119: xfree(dp); ! 120: if (i < 0) ! 121: Perror(dp); ! 122: } ! 123: ! 124: prvars() ! 125: { ! 126: ! 127: plist(&shvhed); ! 128: } ! 129: ! 130: doalias(v) ! 131: register char **v; ! 132: { ! 133: register struct varent *vp; ! 134: register char *p; ! 135: ! 136: v++; ! 137: p = *v++; ! 138: if (p == 0) ! 139: plist(&aliases); ! 140: else if (*v == 0) { ! 141: vp = adrof1(strip(p), &aliases); ! 142: if (vp) ! 143: blkpr(vp->vec), printf("\n"); ! 144: } else { ! 145: if (eq(p, "alias") || eq(p, "unalias")) { ! 146: setname(p); ! 147: bferr("Too dangerous to alias that"); ! 148: } ! 149: set1(strip(p), saveblk(v), &aliases); ! 150: } ! 151: } ! 152: ! 153: unalias(v) ! 154: char **v; ! 155: { ! 156: ! 157: unset1(v, &aliases); ! 158: } ! 159: ! 160: dologout() ! 161: { ! 162: ! 163: islogin(); ! 164: goodbye(); ! 165: } ! 166: ! 167: dologin(v) ! 168: char **v; ! 169: { ! 170: ! 171: islogin(); ! 172: execl("/bin/login", "login", v[1], 0); ! 173: exit(1); ! 174: } ! 175: ! 176: donewgrp(v) ! 177: char **v; ! 178: { ! 179: ! 180: execl("/bin/newgrp", "newgrp", v[1], 0); ! 181: execl("/usr/bin/newgrp", "newgrp", v[1], 0); ! 182: } ! 183: ! 184: islogin() ! 185: { ! 186: ! 187: if (loginsh) ! 188: return; ! 189: error("Not login shell"); ! 190: } ! 191: ! 192: doif(v, kp) ! 193: char **v; ! 194: struct command *kp; ! 195: { ! 196: register int i; ! 197: register char **vv; ! 198: ! 199: v++; ! 200: i = exp(&v); ! 201: vv = v; ! 202: if (*vv && eq(*vv, "then")) { ! 203: vv++; ! 204: if (*vv) ! 205: bferr("Improper then"); ! 206: setname("then"); ! 207: /* ! 208: * If expression was zero, then scan to else, ! 209: * otherwise just fall into following code. ! 210: */ ! 211: if (!i) ! 212: search(ZIF, 0); ! 213: return; ! 214: } ! 215: /* ! 216: * Simple command attached to this if. ! 217: * Left shift the node in this tree, munging it ! 218: * so we can reexecute it. ! 219: */ ! 220: if (i) { ! 221: lshift(kp->t_dcom, vv - kp->t_dcom); ! 222: reexecute(kp); ! 223: donefds(); ! 224: } ! 225: } ! 226: ! 227: /* ! 228: * Reexecute a command, being careful not ! 229: * to redo i/o redirection, which is already set up. ! 230: */ ! 231: reexecute(kp) ! 232: register struct command *kp; ! 233: { ! 234: ! 235: kp->t_dflg = FREDO; ! 236: execute(kp); ! 237: } ! 238: ! 239: doelse() ! 240: { ! 241: ! 242: search(ZELSE, 0); ! 243: } ! 244: ! 245: dogoto(v) ! 246: char **v; ! 247: { ! 248: register struct whyle *wp; ! 249: char *lp; ! 250: ! 251: /* ! 252: * While we still can, locate any unknown ends of existing loops. ! 253: * This obscure code is the WORST result of the fact that we ! 254: * don't really parse. ! 255: */ ! 256: for (wp = whyles; wp; wp = wp->w_next) ! 257: if (wp->w_end == 0) ! 258: wp->w_end = search(ZBREAK, 0); ! 259: else ! 260: bseek(wp->w_end); ! 261: search(ZGOTO, 0, lp = globone(v[1])); ! 262: xfree(lp); ! 263: /* ! 264: * Eliminate loops which were exited. ! 265: */ ! 266: wfree(); ! 267: } ! 268: ! 269: doswitch(v) ! 270: register char **v; ! 271: { ! 272: register char *cp, *lp; ! 273: ! 274: v++; ! 275: if (!*v || *(*v++) != '(') ! 276: goto syntax; ! 277: cp = **v == ')' ? "" : *v++; ! 278: if (*(*v++) != ')') ! 279: v--; ! 280: if (*v) ! 281: syntax: ! 282: error("Syntax error"); ! 283: search(ZSWITCH, 0, lp = globone(cp)); ! 284: xfree(lp); ! 285: } ! 286: ! 287: dobreak() ! 288: { ! 289: ! 290: if (whyles) ! 291: toend(); ! 292: else ! 293: bferr("Not in while/foreach"); ! 294: } ! 295: ! 296: doexit(v) ! 297: char **v; ! 298: { ! 299: ! 300: /* ! 301: * Don't DEMAND parentheses here either. ! 302: */ ! 303: v++; ! 304: if (*v) { ! 305: set("status", putn(exp(&v))); ! 306: if (*v) ! 307: bferr("Expression syntax"); ! 308: } ! 309: btoeof(); ! 310: if (intty) ! 311: close(SHIN); ! 312: } ! 313: ! 314: doforeach(v) ! 315: register char **v; ! 316: { ! 317: register char *cp; ! 318: register struct whyle *nwp; ! 319: ! 320: v++; ! 321: cp = strip(*v); ! 322: while (*cp && letter(*cp)) ! 323: cp++; ! 324: if (*cp || strlen(*v) >= 20) ! 325: bferr("Invalid variable"); ! 326: cp = *v++; ! 327: if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') ! 328: bferr("Words not ()'ed"); ! 329: v++; ! 330: gflag = 0, rscan(v, tglob); ! 331: v = glob(v); ! 332: if (v == 0) ! 333: bferr("No match"); ! 334: nwp = (struct whyle *) calloc(1, sizeof *nwp); ! 335: nwp->w_fe = nwp->w_fe0 = v; gargv = 0; ! 336: nwp->w_start = btell(); ! 337: nwp->w_fename = savestr(cp); ! 338: nwp->w_next = whyles; ! 339: whyles = nwp; ! 340: /* ! 341: * Pre-read the loop so as to be more ! 342: * comprehensible to a terminal user. ! 343: */ ! 344: if (intty) ! 345: preread(); ! 346: doagain(); ! 347: } ! 348: ! 349: dowhile(v) ! 350: char **v; ! 351: { ! 352: register int status; ! 353: register bool again = whyles != 0 && whyles->w_start == lineloc; ! 354: ! 355: v++; ! 356: /* ! 357: * Implement prereading here also, taking care not to ! 358: * evaluate the expression before the loop has been read up ! 359: * from a terminal. ! 360: */ ! 361: if (intty && !again) ! 362: status = !exp0(&v, 1); ! 363: else ! 364: status = !exp(&v); ! 365: if (*v) ! 366: bferr("Expression syntax"); ! 367: if (!again) { ! 368: register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp)); ! 369: ! 370: nwp->w_start = lineloc; ! 371: nwp->w_end = 0; ! 372: nwp->w_next = whyles; ! 373: whyles = nwp; ! 374: if (intty) { ! 375: /* ! 376: * The tty preread ! 377: */ ! 378: preread(); ! 379: doagain(); ! 380: return; ! 381: } ! 382: } ! 383: if (status) ! 384: /* We ain't gonna loop no more, no more! */ ! 385: toend(); ! 386: } ! 387: ! 388: preread() ! 389: { ! 390: register int (*oldint)(); ! 391: ! 392: whyles->w_end = -1; ! 393: if (setintr) ! 394: oldint = signal(SIGINT, pintr); ! 395: search(ZBREAK, 0); ! 396: if (setintr) ! 397: signal(SIGINT, oldint); ! 398: whyles->w_end = btell(); ! 399: } ! 400: ! 401: doend() ! 402: { ! 403: ! 404: if (!whyles) ! 405: bferr("Not in while/foreach"); ! 406: whyles->w_end = btell(); ! 407: doagain(); ! 408: } ! 409: ! 410: docontin() ! 411: { ! 412: ! 413: if (!whyles) ! 414: bferr("Not in while/foreach"); ! 415: doagain(); ! 416: } ! 417: ! 418: doagain() ! 419: { ! 420: ! 421: /* Repeating a while is simple */ ! 422: if (whyles->w_fename == 0) { ! 423: bseek(whyles->w_start); ! 424: return; ! 425: } ! 426: /* ! 427: * The foreach variable list actually has a spurious word ! 428: * ")" at the end of the w_fe list. Thus we are at the ! 429: * of the list if one word beyond this is 0. ! 430: */ ! 431: if (!whyles->w_fe[1]) { ! 432: dobreak(); ! 433: return; ! 434: } ! 435: set(whyles->w_fename, savestr(*whyles->w_fe++)); ! 436: bseek(whyles->w_start); ! 437: } ! 438: ! 439: dorepeat(v, kp) ! 440: char **v; ! 441: struct command *kp; ! 442: { ! 443: register int i; ! 444: register int (*saveintr)(); ! 445: ! 446: i = getn(v[1]); ! 447: if (setintr) ! 448: saveintr = signal(SIGINT, SIG_IGN); ! 449: lshift(v, 2); ! 450: while (i > 0) { ! 451: if (setintr) ! 452: signal(SIGINT, pintr); ! 453: reexecute(kp); ! 454: --i; ! 455: } ! 456: donefds(); ! 457: if (setintr) ! 458: signal(SIGINT, saveintr); ! 459: } ! 460: ! 461: doswbrk() ! 462: { ! 463: ! 464: search(ZBRKSW, 0); ! 465: } ! 466: ! 467: srchx(cp) ! 468: register char *cp; ! 469: { ! 470: register struct srch *sp; ! 471: ! 472: for (sp = srchn; sp->s_name; sp++) ! 473: if (eq(cp, sp->s_name)) ! 474: return (sp->s_value); ! 475: return (-1); ! 476: } ! 477: ! 478: char Stype; ! 479: char *Sgoal; ! 480: ! 481: /*VARARGS2*/ ! 482: search(type, level, goal) ! 483: int type; ! 484: register int level; ! 485: char *goal; ! 486: { ! 487: char wordbuf[BUFSIZ]; ! 488: register char *aword = wordbuf; ! 489: register char *cp; ! 490: ! 491: Stype = type; Sgoal = goal; ! 492: if (type == ZGOTO) ! 493: bseek(0l); ! 494: do { ! 495: if (intty && fseekp == feobp) ! 496: printf("? "), flush(); ! 497: aword[0] = 0, getword(aword); ! 498: switch (srchx(aword)) { ! 499: ! 500: case ZELSE: ! 501: if (level == 0 && type == ZIF) ! 502: return; ! 503: break; ! 504: ! 505: case ZIF: ! 506: while (getword(aword)) ! 507: continue; ! 508: if ((type == ZIF || type == ZELSE) && eq(aword, "then")) ! 509: level++; ! 510: break; ! 511: ! 512: case ZENDIF: ! 513: if (type == ZIF || type == ZELSE) ! 514: level--; ! 515: break; ! 516: ! 517: case ZFOREACH: ! 518: case ZWHILE: ! 519: if (type == ZBREAK) ! 520: level++; ! 521: break; ! 522: ! 523: case ZEND: ! 524: if (type == ZBREAK) ! 525: level--; ! 526: break; ! 527: ! 528: case ZSWITCH: ! 529: if (type == ZSWITCH || type == ZBRKSW) ! 530: level++; ! 531: break; ! 532: ! 533: case ZENDSW: ! 534: if (type == ZSWITCH || type == ZBRKSW) ! 535: level--; ! 536: break; ! 537: ! 538: case ZLABEL: ! 539: if (type == ZGOTO && getword(aword) && eq(aword, goal)) ! 540: level = -1; ! 541: break; ! 542: ! 543: default: ! 544: if (type != ZGOTO && (type != ZSWITCH || level != 0)) ! 545: break; ! 546: if (lastchr(aword) != ':') ! 547: break; ! 548: aword[strlen(aword) - 1] = 0; ! 549: if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default")) ! 550: level = -1; ! 551: break; ! 552: ! 553: case ZCASE: ! 554: if (type != ZSWITCH || level != 0) ! 555: break; ! 556: getword(aword); ! 557: if (lastchr(aword) == ':') ! 558: aword[strlen(aword) - 1] = 0; ! 559: cp = strip(Dfix1(aword)); ! 560: if (Gmatch(goal, cp)) ! 561: level = -1; ! 562: xfree(cp); ! 563: break; ! 564: ! 565: case ZDEFAULT: ! 566: if (type == ZSWITCH && level == 0) ! 567: level = -1; ! 568: break; ! 569: } ! 570: getword(0); ! 571: } while (level >= 0); ! 572: } ! 573: ! 574: getword(wp) ! 575: register char *wp; ! 576: { ! 577: register int found = 0; ! 578: register int c, d; ! 579: ! 580: c = readc(1); ! 581: d = 0; ! 582: do { ! 583: while (c == ' ' || c == '\t') ! 584: c = readc(1); ! 585: if (c < 0) ! 586: goto past; ! 587: if (c == '\n') { ! 588: if (wp) ! 589: break; ! 590: return (0); ! 591: } ! 592: unreadc(c); ! 593: found = 1; ! 594: do { ! 595: c = readc(1); ! 596: if (c == '\\' && (c = readc(1)) == '\n') ! 597: c = ' '; ! 598: if (any(c, "'\"")) ! 599: if (d == 0) ! 600: d = c; ! 601: else if (d == c) ! 602: d = 0; ! 603: if (c < 0) ! 604: goto past; ! 605: if (wp) ! 606: *wp++ = c; ! 607: } while ((d || c != ' ' && c != '\t') && c != '\n'); ! 608: } while (wp == 0); ! 609: unreadc(c); ! 610: if (found) ! 611: *--wp = 0; ! 612: return (found); ! 613: ! 614: past: ! 615: switch (Stype) { ! 616: ! 617: case ZIF: ! 618: bferr("then/endif not found"); ! 619: ! 620: case ZELSE: ! 621: bferr("endif not found"); ! 622: ! 623: case ZBRKSW: ! 624: case ZSWITCH: ! 625: bferr("endsw not found"); ! 626: ! 627: case ZBREAK: ! 628: bferr("end not found"); ! 629: ! 630: case ZGOTO: ! 631: setname(Sgoal); ! 632: bferr("label not found"); ! 633: } ! 634: /*NOTREACHED*/ ! 635: } ! 636: ! 637: toend() ! 638: { ! 639: ! 640: if (whyles->w_end == 0) { ! 641: search(ZBREAK, 0); ! 642: whyles->w_end = btell() - 1; ! 643: } else ! 644: bseek(whyles->w_end); ! 645: wfree(); ! 646: } ! 647: ! 648: wfree() ! 649: { ! 650: long o = btell(); ! 651: ! 652: while (whyles) { ! 653: register struct whyle *wp = whyles; ! 654: register struct whyle *nwp = wp->w_next; ! 655: ! 656: if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) ! 657: break; ! 658: if (wp->w_fe0) ! 659: blkfree(wp->w_fe0); ! 660: if (wp->w_fename) ! 661: xfree(wp->w_fename); ! 662: xfree(wp); ! 663: whyles = nwp; ! 664: } ! 665: } ! 666: ! 667: doecho(v) ! 668: char **v; ! 669: { ! 670: ! 671: echo(' ', v); ! 672: } ! 673: ! 674: doglob(v) ! 675: char **v; ! 676: { ! 677: ! 678: echo(0, v); ! 679: flush(); ! 680: } ! 681: ! 682: echo(sep, v) ! 683: char sep; ! 684: register char **v; ! 685: { ! 686: register char *cp; ! 687: int (*saveintr)(); ! 688: if (setintr) ! 689: saveintr = signal(SIGINT, pintr); ! 690: ! 691: v++; ! 692: if (*v == 0) ! 693: return; ! 694: gflag = 0; rscan(v, tglob); ! 695: if (gflag) { ! 696: v = glob(v); ! 697: if (v == 0) ! 698: bferr("No match"); ! 699: } else ! 700: scan(v, trim); ! 701: while (cp = *v++) { ! 702: register int c; ! 703: ! 704: while (c = *cp++) { ! 705: if (sep == ' ' && *cp && c == '\\') { ! 706: c = *cp++; ! 707: if (c == 'c') { ! 708: flush(); ! 709: return; ! 710: } else if (c == 'n') ! 711: c = '\n'; ! 712: else ! 713: putchar('\\'); ! 714: } ! 715: putchar(c | QUOTE); ! 716: } ! 717: if (*v) ! 718: putchar(sep | QUOTE); ! 719: } ! 720: if (sep) ! 721: putchar('\n'); ! 722: if (setintr) ! 723: signal(SIGINT, saveintr); ! 724: if (gargv) ! 725: blkfree(gargv), gargv = 0; ! 726: } ! 727: ! 728: #ifndef V6 ! 729: char **environ; ! 730: ! 731: dosetenv(v) ! 732: register char **v; ! 733: { ! 734: char *lp = globone(v[2]); ! 735: ! 736: setenv(v[1], lp); ! 737: xfree(lp); ! 738: } ! 739: ! 740: setenv(name, value) ! 741: char *name, *value; ! 742: { ! 743: register char **ep = environ; ! 744: register char *cp, *dp; ! 745: char *blk[2], **oep = ep; ! 746: ! 747: for (; *ep; ep++) { ! 748: for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) ! 749: continue; ! 750: if (*cp != 0 || *dp != '=') ! 751: continue; ! 752: cp = strspl("=", value); ! 753: xfree(*ep); ! 754: *ep = strspl(name, cp); ! 755: xfree(cp); ! 756: scan(ep, trim); ! 757: return; ! 758: } ! 759: blk[0] = strspl(name, "="); blk[1] = 0; ! 760: environ = blkspl(environ, blk); ! 761: xfree(oep); ! 762: setenv(name, value); ! 763: } ! 764: ! 765: doumask(v) ! 766: register char **v; ! 767: { ! 768: register char *cp = v[1]; ! 769: register int i; ! 770: ! 771: if (cp == 0) { ! 772: i = umask(0); ! 773: umask(i); ! 774: printf("%o\n", i); ! 775: return; ! 776: } ! 777: i = 0; ! 778: while (digit(*cp) && *cp != '8' && *cp != '9') ! 779: i = i * 8 + *cp++ - '0'; ! 780: if (*cp || i < 0 || i > 0777) ! 781: bferr("Improper mask"); ! 782: umask(i); ! 783: } ! 784: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.