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