# /* * copyright 1973 bell telephone laboratories inc. */ #define intr 2 #define quit 3 #define linesiz 1000 #define argsiz 50 #define tresiz 100 #define quote 0200 #define fand 1 #define fcat 2 #define fpin 4 #define fpou 8 #define fpar 16 #define fint 32 #define tcom 1 #define tpar 2 #define tfil 3 #define tlst 4 #define dtyp 0 #define dlef 1 #define drit 2 #define dflg 3 #define dspr 4 #define dcom 5 #define ENOEXEC 8 char *dolp; char **dolv; int dolc; char *promp; char *linep; char *elinep; char **argp; char **eargp; int *treep; int *treeend; char peekc; char gflg; char error; char acctf; char uid; char setintr; char *arginp; int onelflg; char *mesg[] { 0, "Hangup", 0, "Quit", "Illegal instruction", "Trace/BPT trap", "IOT trap", "EMT trap", "Floating exception", "Killed", "Bus error", "Memory fault", "Bad system call" }; struct stime { int proct[2]; int cputim[2]; int systim[2]; } timeb; main(c, av) int c; char **av; { register f; register char *acname, **v; close(2); if((f=dup(1)) != 2) close(f); v = av; acname = "/usr/adm/sh_acct"; promp = "% "; if(((uid = getuid())&0377) == 0) { promp = "# "; acname = "/usr/adm/su_acct"; } acctf = open(acname, 1); if(c > 1) { promp = 0; for (f=3; f<=15; f++) close(f); if (*v[1]=='-') { **v = '-'; if (v[1][1]=='c' && c>2) arginp = v[2]; else if (v[1][1]=='t') onelflg = 2; } else { close(0); f = open(v[1], 0); if(f < 0) { prs(v[1]); err(": cannot open"); } } } if(**v == '-') { setintr++; signal(quit, 1); signal(intr, 1); } dolv = v+1; dolc = c-1; loop: if(promp != 0) prs(promp); peekc = getc(); main1(); goto loop; } main1() { char line[linesiz]; char *args[argsiz]; int trebuf[tresiz]; register char c, *cp; register *t; argp = args; eargp = args+argsiz-5; linep = line; elinep = line+linesiz-5; error = 0; gflg = 0; do { cp = linep; word(); } while(*cp != '\n'); treep = trebuf; treeend = &trebuf[tresiz]; if(gflg == 0) { if(error == 0) { setexit(); if (error) return; t = syntax(args, argp); } if(error != 0) err("syntax error"); else execute(t); } } word() { register char c, c1; *argp++ = linep; loop: switch(c = getc()) { case ' ': case '\t': goto loop; case '\'': case '"': c1 = c; while((c=readc()) != c1) { if(c == '\n') { error++; peekc = c; return; } *linep++ = c|quote; } goto pack; case '&': case ';': case '<': case '>': case '(': case ')': case '|': case '^': case '\n': *linep++ = c; *linep++ = '\0'; return; } peekc = c; pack: for(;;) { c = getc(); if(any(c, " '\"\t;&<>()|^\n")) { peekc = c; if(any(c, "\"'")) goto loop; *linep++ = '\0'; return; } *linep++ = c; } } tree(n) int n; { register *t; t = treep; treep =+ n; if (treep>treeend) { prs("Command line overflow\n"); error++; reset(); } return(t); } getc() { register char c; if(peekc) { c = peekc; peekc = 0; return(c); } if(argp > eargp) { argp =- 10; while((c=getc()) != '\n'); argp =+ 10; err("Too many args"); gflg++; return(c); } if(linep > elinep) { linep =- 10; while((c=getc()) != '\n'); linep =+ 10; err("Too many characters"); gflg++; return(c); } getd: if(dolp) { c = *dolp++; if(c != '\0') return(c); dolp = 0; } c = readc(); if(c == '\\') { c = readc(); if(c == '\n') return(' '); return(c|quote); } if(c == '$') { c = getc(); if(c>='0' && c<='9') { if(c-'0' < dolc) dolp = dolv[c-'0']; goto getd; } } return(c&0177); } readc() { char cc; register c; if (arginp) { if (arginp == 1) exit(); if ((c = *arginp++) == 0) { arginp = 1; c = '\n'; } return(c); } if (onelflg==1) exit(); if(read(0, &cc, 1) != 1) exit(); if (cc=='\n' && onelflg) onelflg--; return(cc); } /* * syntax * empty * syn1 */ syntax(p1, p2) char **p1, **p2; { while(p1 != p2) { if(any(**p1, ";&\n")) p1++; else return(syn1(p1, p2)); } return(0); } /* * syn1 * syn2 * syn2 & syntax * syn2 ; syntax */ syn1(p1, p2) char **p1, **p2; { register char **p; register *t, *t1; int l; l = 0; for(p=p1; p!=p2; p++) switch(**p) { case '(': l++; continue; case ')': l--; if(l < 0) error++; continue; case '&': case ';': case '\n': if(l == 0) { t = tree(4); t[dtyp] = tlst; t[dlef] = syn2(p1, p); t[dflg] = 0; if(**p == '&') { t1 = t[dlef]; t1[dflg] =| fand|fint; } t[drit] = syntax(p+1, p2); return(t); } } if(l == 0) return(syn2(p1, p2)); error++; } /* * syn2 * syn3 * syn3 | syn2 */ syn2(p1, p2) char **p1, **p2; { register char **p; register int l, *t; l = 0; for(p=p1; p!=p2; p++) switch(**p) { case '(': l++; continue; case ')': l--; continue; case '|': case '^': if(l == 0) { t = tree(4); t[dtyp] = tfil; t[dlef] = syn3(p1, p); t[drit] = syn2(p+1, p2); t[dflg] = 0; return(t); } } return(syn3(p1, p2)); } /* * syn3 * ( syn1 ) [ < in ] [ > out ] * word word* [ < in ] [ > out ] */ syn3(p1, p2) char **p1, **p2; { register char **p; char **lp, **rp; register *t; int b[100], n, l, i, o, c, flg; flg = 0; if(**p2 == ')') flg =| fpar; lp = 0; rp = 0; i = 0; o = 0; n = 0; l = 0; for(p=p1; p!=p2; p++) switch(c = **p) { case '(': if(l == 0) { if(lp != 0) error++; lp = p+1; } l++; continue; case ')': l--; if(l == 0) rp = p; continue; case '>': p++; if(p!=p2 && **p=='>') flg =| fcat; else p--; case '<': if(l == 0) { p++; if(p == p2) { error++; p--; } if(any(**p, "<>(")) error++; if(c == '<') { if(i != 0) error++; i = *p; continue; } if(o != 0) error++; o = *p; } continue; default: if(l == 0) b[n++] = *p; } if(lp != 0) { if(n != 0) error++; t = tree(5); t[dtyp] = tpar; t[dspr] = syn1(lp, rp); goto out; } if(n == 0) error++; b[n++] = 0; t = tree(n+5); t[dtyp] = tcom; for(l=0; l= 0) { seek(i, 0, 2); goto f1; } } i = creat(t[drit], 0666); if(i < 0) { prs(t[drit]); err(": cannot create"); exit(); } f1: close(1); dup(i); close(i); } if((f&fpin) != 0) { close(0); dup(pf1[0]); close(pf1[0]); close(pf1[1]); } if((f&fpou) != 0) { close(1); dup(pf2[1]); close(pf2[0]); close(pf2[1]); } if((f&fint)!=0 && t[dlef]==0 && (f&fpin)==0) { close(0); open("/dev/null", 0); } if((f&fint) == 0 && setintr) { signal(intr, 0); signal(quit, 0); } if(t[dtyp] == tpar) { if(t1 = t[dspr]) t1[dflg] =| f&fint; execute(t1); exit(); } close(acctf); gflg = 0; scan(t, &tglob); if(gflg) { t[dspr] = "/etc/glob"; execv(t[dspr], t+dspr); prs("glob: cannot execute\n"); exit(); } scan(t, &trim); *linep = 0; execv(t[dcom], t+dcom); if (errno==ENOEXEC) goto runcom; cp1 = linep; cp2 = "/usr/bin/"; while(*cp1 = *cp2++) cp1++; cp2 = t[dcom]; while(*cp1++ = *cp2++); execv(linep+4, t+dcom); if (errno==ENOEXEC) goto runcom; execv(linep, t+dcom); if (errno==ENOEXEC) goto runcom; prs(t[dcom]); err(": not found"); exit(); runcom: if (*linep) t[dcom] = linep; t[dspr] = "/bin/sh"; execv(t[dspr], t+dspr); prs("No shell!\n"); exit(); case tfil: f = t[dflg]; pipe(pv); t1 = t[dlef]; t1[dflg] =| fpou | (f&(fpin|fint)); execute(t1, pf1, pv); t1 = t[drit]; t1[dflg] =| fpin | (f&(fpou|fint|fand)); execute(t1, pv, pf2); return; case tlst: f = t[dflg]&fint; if(t1 = t[dlef]) t1[dflg] =| f; execute(t1); if(t1 = t[drit]) t1[dflg] =| f; execute(t1); return; } } err(s) char *s; { prs(s); prs("\n"); if(promp == 0) { seek(0, 0, 2); exit(); } } prs(as) char *as; { register char *s; s = as; while(*s) putc(*s++); } putc(c) { write(2, &c, 1); } prn(n) int n; { register a; if(a=ldiv(0,n,10)) prn(a); putc(lrem(0,n,10)+'0'); } any(c, as) int c; char *as; { register char *s; s = as; while(*s) if(*s++ == c) return(1); return(0); } equal(as1, as2) char *as1, *as2; { register char *s1, *s2; s1 = as1; s2 = as2; while(*s1++ == *s2) if(*s2++ == '\0') return(1); return(0); } pwait(i, t) int i, *t; { register p, e; int s; if(i != 0) for(;;) { times(&timeb); time(timeb.proct); p = wait(&s); if(p == -1) break; e = s&0177; if(mesg[e] != 0) { if(p != i) { prn(p); prs(": "); } prs(mesg[e]); if(s&0200) prs(" -- Core dumped"); } if(e != 0) err(""); if(i == p) { acct(t); break; } else acct(0); } } acct(t) int *t; { if(t == 0) enacct("**gok"); else if(*t == tpar) enacct("()"); else enacct(t[dcom]); } enacct(as) char *as; { struct stime timbuf; struct { char cname[14]; char fill; char uid; int datet[2]; int realt[2]; int bcput[2]; int bsyst[2]; } tbuf; register i; register char *np, *s; s = as; times(&timbuf); time(timbuf.proct); lsub(tbuf.realt, timbuf.proct, timeb.proct); lsub(tbuf.bcput, timbuf.cputim, timeb.cputim); lsub(tbuf.bsyst, timbuf.systim, timeb.systim); do { np = s; while (*s != '\0' && *s != '/') s++; } while (*s++ != '\0'); for (i=0; i<14; i++) { tbuf.cname[i] = *np; if (*np) np++; } tbuf.datet[0] = timbuf.proct[0]; tbuf.datet[1] = timbuf.proct[1]; tbuf.uid = uid; seek(acctf, 0, 2); write(acctf, &tbuf, sizeof(tbuf)); }