1: /* 2: */ 3: 4: #include <setjmp.h> 5: #define INTR 2 6: #define QUIT 3 7: #define LINSIZ 1000 8: #define ARGSIZ 50 9: #define TRESIZ 100 10: 11: #define QUOTE 0200 12: #define FAND 1 13: #define FCAT 2 14: #define FPIN 4 15: #define FPOU 8 16: #define FPAR 16 17: #define FINT 32 18: #define FPRS 64 19: #define TCOM 1 20: #define TPAR 2 21: #define TFIL 3 22: #define TLST 4 23: #define DTYP 0 24: #define DLEF 1 25: #define DRIT 2 26: #define DFLG 3 27: #define DSPR 4 28: #define DCOM 5 29: #define ENOMEM 12 30: #define ENOEXEC 8 31: 32: int errval; 33: char *dolp; 34: char pidp[6]; 35: char **dolv; 36: jmp_buf jmpbuf; 37: int dolc; 38: char *promp; 39: char *linep; 40: char *elinep; 41: char **argp; 42: char **eargp; 43: int *treep; 44: int *treeend; 45: char peekc; 46: char gflg; 47: char error; 48: char uid; 49: char setintr; 50: char *arginp; 51: int onelflg; 52: int stoperr; 53: 54: #define NSIG 16 55: char *mesg[NSIG] { 56: 0, 57: "Hangup", 58: 0, 59: "Quit", 60: "Illegal instruction", 61: "Trace/BPT trap", 62: "IOT trap", 63: "EMT trap", 64: "Floating exception", 65: "Killed", 66: "Bus error", 67: "Memory fault", 68: "Bad system call", 69: 0, 70: "Alarm clock", 71: "Terminated", 72: }; 73: 74: char line[LINSIZ]; 75: char *args[ARGSIZ]; 76: int trebuf[TRESIZ]; 77: 78: main(c, av) 79: int c; 80: char **av; 81: { 82: register f; 83: register char *acname, **v; 84: 85: for(f=3; f<15; f++) 86: close(f); 87: dolc = getpid(); 88: for(f=4; f>=0; f--) { 89: dolc = dolc/10; 90: pidp[f] = dolc%10 + '0'; 91: } 92: v = av; 93: acname = "<none>"; 94: promp = "% "; 95: if((uid = getuid()) == 0) 96: promp = "# "; 97: if(c>1 && v[1][0]=='-' && v[1][1]=='e') { 98: ++stoperr; 99: v[1] = v[0]; 100: ++v; 101: --c; 102: } 103: if(c > 1) { 104: promp = 0; 105: if (*v[1]=='-') { 106: **v = '-'; 107: if (v[1][1]=='c' && c>2) 108: arginp = v[2]; 109: else if (v[1][1]=='t') 110: onelflg = 2; 111: } else { 112: close(0); 113: f = open(v[1], 0); 114: if(f < 0) { 115: prs(v[1]); 116: err(": cannot open",255); 117: } 118: } 119: } 120: if(**v == '-') { 121: signal(QUIT, 1); 122: f = signal(INTR, 1); 123: if ((arginp==0&&onelflg==0) || (f&01)==0) 124: setintr++; 125: } 126: dolv = v+1; 127: dolc = c-1; 128: 129: loop: 130: if(promp != 0) 131: prs(promp); 132: peekc = getc(); 133: main1(); 134: goto loop; 135: } 136: 137: main1() 138: { 139: register char *cp; 140: register *t; 141: 142: argp = args; 143: eargp = args+ARGSIZ-5; 144: linep = line; 145: elinep = line+LINSIZ-5; 146: error = 0; 147: gflg = 0; 148: do { 149: cp = linep; 150: word(); 151: } while(*cp != '\n'); 152: treep = trebuf; 153: treeend = &trebuf[TRESIZ]; 154: if(gflg == 0) { 155: if(error == 0) { 156: setjmp(jmpbuf); 157: if (error) 158: return; 159: t = syntax(args, argp); 160: } 161: if(error != 0) 162: err("syntax error",255); else 163: execute(t); 164: } 165: } 166: 167: word() 168: { 169: register char c, c1; 170: 171: *argp++ = linep; 172: 173: loop: 174: switch(c = getc()) { 175: 176: case ' ': 177: case '\t': 178: goto loop; 179: 180: case '\'': 181: case '"': 182: c1 = c; 183: while((c=readc()) != c1) { 184: if(c == '\n') { 185: error++; 186: peekc = c; 187: return; 188: } 189: *linep++ = c|QUOTE; 190: } 191: goto pack; 192: 193: case '&': 194: case ';': 195: case '<': 196: case '>': 197: case '(': 198: case ')': 199: case '|': 200: case '^': 201: case '\n': 202: *linep++ = c; 203: *linep++ = '\0'; 204: return; 205: } 206: 207: peekc = c; 208: 209: pack: 210: for(;;) { 211: c = getc(); 212: if(any(c, " '\"\t;&<>()|^\n")) { 213: peekc = c; 214: if(any(c, "\"'")) 215: goto loop; 216: *linep++ = '\0'; 217: return; 218: } 219: *linep++ = c; 220: } 221: } 222: 223: tree(n) 224: int n; 225: { 226: register *t; 227: 228: t = treep; 229: treep =+ n; 230: if (treep>treeend) { 231: prs("Command line overflow\n"); 232: error++; 233: longjmp(jmpbuf, 1); 234: } 235: return(t); 236: } 237: 238: getc() 239: { 240: register char c; 241: 242: if(peekc) { 243: c = peekc; 244: peekc = 0; 245: return(c); 246: } 247: if(argp > eargp) { 248: argp =- 10; 249: while((c=getc()) != '\n'); 250: argp =+ 10; 251: err("Too many args",255); 252: gflg++; 253: return(c); 254: } 255: if(linep > elinep) { 256: linep =- 10; 257: while((c=getc()) != '\n'); 258: linep =+ 10; 259: err("Too many characters",255); 260: gflg++; 261: return(c); 262: } 263: getd: 264: if(dolp) { 265: c = *dolp++; 266: if(c != '\0') 267: return(c); 268: dolp = 0; 269: } 270: c = readc(); 271: if(c == '\\') { 272: c = readc(); 273: if(c == '\n') 274: return(' '); 275: return(c|QUOTE); 276: } 277: if(c == '$') { 278: c = readc(); 279: if(c>='0' && c<='9') { 280: if(c-'0' < dolc) 281: dolp = dolv[c-'0']; 282: goto getd; 283: } 284: if(c == '$') { 285: dolp = pidp; 286: goto getd; 287: } 288: } 289: return(c&0177); 290: } 291: 292: readc() 293: { 294: int rdstat; 295: char cc; 296: register c; 297: 298: if (arginp) { 299: if (arginp == 1) 300: exit(errval); 301: if ((c = *arginp++) == 0) { 302: arginp = 1; 303: c = '\n'; 304: } 305: return(c); 306: } 307: if (onelflg==1) 308: exit(255); 309: if((rdstat = read(0, &cc, 1)) != 1) 310: if(rdstat==0) exit(errval); /* end of file*/ 311: else exit(255); /* error */ 312: if (cc=='\n' && onelflg) 313: onelflg--; 314: return(cc); 315: } 316: 317: /* 318: * syntax 319: * empty 320: * syn1 321: */ 322: 323: syntax(p1, p2) 324: char **p1, **p2; 325: { 326: 327: while(p1 != p2) { 328: if(any(**p1, ";&\n")) 329: p1++; else 330: return(syn1(p1, p2)); 331: } 332: return(0); 333: } 334: 335: /* 336: * syn1 337: * syn2 338: * syn2 & syntax 339: * syn2 ; syntax 340: */ 341: 342: syn1(p1, p2) 343: char **p1, **p2; 344: { 345: register char **p; 346: register *t, *t1; 347: int l; 348: 349: l = 0; 350: for(p=p1; p!=p2; p++) 351: switch(**p) { 352: 353: case '(': 354: l++; 355: continue; 356: 357: case ')': 358: l--; 359: if(l < 0) 360: error++; 361: continue; 362: 363: case '&': 364: case ';': 365: case '\n': 366: if(l == 0) { 367: l = **p; 368: t = tree(4); 369: t[DTYP] = TLST; 370: t[DLEF] = syn2(p1, p); 371: t[DFLG] = 0; 372: if(l == '&') { 373: t1 = t[DLEF]; 374: t1[DFLG] =| FAND|FPRS|FINT; 375: } 376: t[DRIT] = syntax(p+1, p2); 377: return(t); 378: } 379: } 380: if(l == 0) 381: return(syn2(p1, p2)); 382: error++; 383: return(0); 384: } 385: 386: /* 387: * syn2 388: * syn3 389: * syn3 | syn2 390: */ 391: 392: syn2(p1, p2) 393: char **p1, **p2; 394: { 395: register char **p; 396: register int l, *t; 397: 398: l = 0; 399: for(p=p1; p!=p2; p++) 400: switch(**p) { 401: 402: case '(': 403: l++; 404: continue; 405: 406: case ')': 407: l--; 408: continue; 409: 410: case '|': 411: case '^': 412: if(l == 0) { 413: t = tree(4); 414: t[DTYP] = TFIL; 415: t[DLEF] = syn3(p1, p); 416: t[DRIT] = syn2(p+1, p2); 417: t[DFLG] = 0; 418: return(t); 419: } 420: } 421: return(syn3(p1, p2)); 422: } 423: 424: /* 425: * syn3 426: * ( syn1 ) [ < in ] [ > out ] 427: * word word* [ < in ] [ > out ] 428: */ 429: 430: syn3(p1, p2) 431: char **p1, **p2; 432: { 433: register char **p; 434: char **lp, **rp; 435: register *t; 436: int n, l, i, o, c, flg; 437: 438: flg = 0; 439: if(**p2 == ')') 440: flg =| FPAR; 441: lp = 0; 442: rp = 0; 443: i = 0; 444: o = 0; 445: n = 0; 446: l = 0; 447: for(p=p1; p!=p2; p++) 448: switch(c = **p) { 449: 450: case '(': 451: if(l == 0) { 452: if(lp != 0) 453: error++; 454: lp = p+1; 455: } 456: l++; 457: continue; 458: 459: case ')': 460: l--; 461: if(l == 0) 462: rp = p; 463: continue; 464: 465: case '>': 466: p++; 467: if(p!=p2 && **p=='>') 468: flg =| FCAT; else 469: p--; 470: 471: case '<': 472: if(l == 0) { 473: p++; 474: if(p == p2) { 475: error++; 476: p--; 477: } 478: if(any(**p, "<>(")) 479: error++; 480: if(c == '<') { 481: if(i != 0) 482: error++; 483: i = *p; 484: continue; 485: } 486: if(o != 0) 487: error++; 488: o = *p; 489: } 490: continue; 491: 492: default: 493: if(l == 0) 494: p1[n++] = *p; 495: } 496: if(lp != 0) { 497: if(n != 0) 498: error++; 499: t = tree(5); 500: t[DTYP] = TPAR; 501: t[DSPR] = syn1(lp, rp); 502: goto out; 503: } 504: if(n == 0) 505: error++; 506: p1[n++] = 0; 507: t = tree(n+5); 508: t[DTYP] = TCOM; 509: for(l=0; l<n; l++) 510: t[l+DCOM] = p1[l]; 511: out: 512: t[DFLG] = flg; 513: t[DLEF] = i; 514: t[DRIT] = o; 515: return(t); 516: } 517: 518: scan(at, f) 519: int *at; 520: int (*f)(); 521: { 522: register char *p, c; 523: register *t; 524: 525: t = at+DCOM; 526: while(p = *t++) 527: while(c = *p) 528: *p++ = (*f)(c); 529: } 530: 531: tglob(c) 532: int c; 533: { 534: 535: if(any(c, "[?*")) 536: gflg = 1; 537: return(c); 538: } 539: 540: trim(c) 541: int c; 542: { 543: 544: return(c&0177); 545: } 546: 547: execute(t, pf1, pf2) 548: int *t, *pf1, *pf2; 549: { 550: int i, f, pv[2]; 551: register *t1; 552: register char *cp1, *cp2; 553: extern errno; 554: 555: if(t != 0) 556: switch(t[DTYP]) { 557: 558: case TCOM: 559: cp1 = t[DCOM]; 560: if(equal(cp1, "chdir")) { 561: if(t[DCOM+1] != 0) { 562: if(chdir(t[DCOM+1]) < 0) 563: err("chdir: bad directory",255); 564: } else 565: err("chdir: arg count",255); 566: return; 567: } 568: if(equal(cp1, "shift")) { 569: if(dolc < 1) { 570: prs("shift: no args\n"); 571: return; 572: } 573: dolv[1] = dolv[0]; 574: dolv++; 575: dolc--; 576: return; 577: } 578: if(equal(cp1, "login")) { 579: if(promp != 0) { 580: execv("/bin/login", t+DCOM); 581: } 582: prs("login: cannot execute\n"); 583: return; 584: } 585: if(equal(cp1, "newgrp")) { 586: if(promp != 0) { 587: execv("/bin/newgrp", t+DCOM); 588: } 589: prs("newgrp: cannot execute\n"); 590: return; 591: } 592: if(equal(cp1, "wait")) { 593: pwait(-1, 0); 594: return; 595: } 596: if(equal(cp1, ":")) 597: return; 598: 599: case TPAR: 600: f = t[DFLG]; 601: i = 0; 602: if((f&FPAR) == 0) 603: i = fork(); 604: if(i == -1) { 605: err("try again",255); 606: return; 607: } 608: if(i != 0) { 609: if((f&FPIN) != 0) { 610: close(pf1[0]); 611: close(pf1[1]); 612: } 613: if((f&FPRS) != 0) { 614: prn(i); 615: prs("\n"); 616: } 617: if((f&FAND) != 0) 618: return; 619: if((f&FPOU) == 0) 620: pwait(i, t); 621: return; 622: } 623: if(t[DLEF] != 0) { 624: close(0); 625: i = open(t[DLEF], 0); 626: if(i < 0) { 627: prs(t[DLEF]); 628: err(": cannot open",255); 629: exit(255); 630: } 631: } 632: if(t[DRIT] != 0) { 633: if((f&FCAT) != 0) { 634: i = open(t[DRIT], 1); 635: if(i >= 0) { 636: lseek(i, 0L, 2); 637: goto f1; 638: } 639: } 640: i = creat(t[DRIT], 0666); 641: if(i < 0) { 642: prs(t[DRIT]); 643: err(": cannot create",255); 644: exit(255); 645: } 646: f1: 647: close(1); 648: dup(i); 649: close(i); 650: } 651: if((f&FPIN) != 0) { 652: close(0); 653: dup(pf1[0]); 654: close(pf1[0]); 655: close(pf1[1]); 656: } 657: if((f&FPOU) != 0) { 658: close(1); 659: dup(pf2[1]); 660: close(pf2[0]); 661: close(pf2[1]); 662: } 663: if((f&FINT)!=0 && t[DLEF]==0 && (f&FPIN)==0) { 664: close(0); 665: open("/dev/null", 0); 666: } 667: if((f&FINT) == 0 && setintr) { 668: signal(INTR, 0); 669: signal(QUIT, 0); 670: } 671: if(t[DTYP] == TPAR) { 672: if(t1 = t[DSPR]) 673: t1[DFLG] =| f&FINT; 674: execute(t1); 675: exit(255); 676: } 677: gflg = 0; 678: scan(t, tglob); 679: if(gflg) { 680: t[DSPR] = "/etc/glob"; 681: execv(t[DSPR], t+DSPR); 682: prs("glob: cannot execute\n"); 683: exit(255); 684: } 685: scan(t, trim); 686: *linep = 0; 687: texec(t[DCOM], t); 688: cp1 = linep; 689: cp2 = "/usr/bin/"; 690: while(*cp1 = *cp2++) 691: cp1++; 692: cp2 = t[DCOM]; 693: while(*cp1++ = *cp2++); 694: texec(linep+4, t); 695: texec(linep, t); 696: prs(t[DCOM]); 697: err(": not found",255); 698: exit(255); 699: 700: case TFIL: 701: f = t[DFLG]; 702: pipe(pv); 703: t1 = t[DLEF]; 704: t1[DFLG] =| FPOU | (f&(FPIN|FINT|FPRS)); 705: execute(t1, pf1, pv); 706: t1 = t[DRIT]; 707: t1[DFLG] =| FPIN | (f&(FPOU|FINT|FAND|FPRS)); 708: execute(t1, pv, pf2); 709: return; 710: 711: case TLST: 712: f = t[DFLG]&FINT; 713: if(t1 = t[DLEF]) 714: t1[DFLG] =| f; 715: execute(t1); 716: if(t1 = t[DRIT]) 717: t1[DFLG] =| f; 718: execute(t1); 719: return; 720: 721: } 722: } 723: 724: texec(f, at) 725: int *at; 726: { 727: extern errno; 728: register int *t; 729: 730: t = at; 731: execv(f, t+DCOM); 732: if (errno==ENOEXEC) { 733: if (*linep) 734: t[DCOM] = linep; 735: t[DSPR] = "/usr/bin/osh"; 736: execv(t[DSPR], t+DSPR); 737: prs("No shell!\n"); 738: exit(255); 739: } 740: if (errno==ENOMEM) { 741: prs(t[DCOM]); 742: err(": too large",255); 743: exit(255); 744: } 745: } 746: 747: err(s, exitno) 748: char *s; 749: int exitno; 750: { 751: 752: prs(s); 753: prs("\n"); 754: if(promp == 0) { 755: lseek(0, 0L, 2); 756: exit(exitno); 757: } 758: } 759: 760: prs(as) 761: char *as; 762: { 763: register char *s; 764: 765: s = as; 766: while(*s) 767: putc(*s++); 768: } 769: 770: putc(c) 771: { 772: char cc; 773: 774: cc = c; 775: write(2, &cc, 1); 776: } 777: 778: prn(n) 779: int n; 780: { 781: register a; 782: 783: if (a = n/10) 784: prn(a); 785: putc(n%10 + '0'); 786: } 787: 788: any(c, as) 789: int c; 790: char *as; 791: { 792: register char *s; 793: 794: s = as; 795: while(*s) 796: if(*s++ == c) 797: return(1); 798: return(0); 799: } 800: 801: equal(as1, as2) 802: char *as1, *as2; 803: { 804: register char *s1, *s2; 805: 806: s1 = as1; 807: s2 = as2; 808: while(*s1++ == *s2) 809: if(*s2++ == '\0') 810: return(1); 811: return(0); 812: } 813: 814: pwait(i, t) 815: int i, *t; 816: { 817: register p, e; 818: int s; 819: 820: if(i != 0) 821: for(;;) { 822: p = wait(&s); 823: if(p == -1) 824: break; 825: e = s&0177; 826: if (e>=NSIG || mesg[e]) { 827: if(p != i) { 828: prn(p); 829: prs(": "); 830: } 831: if (e < NSIG) 832: prs(mesg[e]); 833: else { 834: prs("Signal "); 835: prn(e); 836: } 837: if(s&0200) 838: prs(" -- Core dumped"); 839: } 840: if (e || s&&stoperr) 841: err("", (s>>8)|e ); 842: errval =| (s>>8); 843: } 844: }