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