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