home *** CD-ROM | disk | FTP | other *** search
- #
- /*
- */
-
- #define INTR 2
- #define QUIT 3
- #define LINSIZ 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 FPRS 64
- #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 ENOMEM 12
- #define ENOEXEC 8
-
- char *dolp;
- char pidp[6];
- int ldivr;
- 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",
- 0,
- "Sig 14",
- "Sig 15",
- "Sig 16",
- "Sig 17",
- "Sig 18",
- "Sig 19",
- };
-
- struct stime {
- int proct[2];
- int cputim[2];
- int systim[2];
- } timeb;
-
- char line[LINSIZ];
- char *args[ARGSIZ];
- int trebuf[TRESIZ];
-
- main(c, av)
- int c;
- char **av;
- {
- register f;
- register char *acname, **v;
-
- for(f=2; f<15; f++)
- close(f);
- if((f=dup(1)) != 2)
- close(f);
- dolc = getpid();
- for(f=4; f>=0; f--) {
- dolc = ldiv(0, dolc, 10);
- pidp[f] = ldivr+'0';
- }
- v = av;
- acname = "/usr/adm/sha";
- promp = "% ";
- if(((uid = getuid())&0377) == 0)
- promp = "# ";
- acctf = open(acname, 1);
- if(c > 1) {
- promp = 0;
- 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()
- {
- register char c, *cp;
- register *t;
-
- argp = args;
- eargp = args+ARGSIZ-5;
- linep = line;
- elinep = line+LINSIZ-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 = readc();
- if(c>='0' && c<='9') {
- if(c-'0' < dolc)
- dolp = dolv[c-'0'];
- goto getd;
- }
- if(c == '$') {
- dolp = pidp;
- 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) {
- l = **p;
- t = tree(4);
- t[DTYP] = TLST;
- t[DLEF] = syn2(p1, p);
- t[DFLG] = 0;
- if(l == '&') {
- t1 = t[DLEF];
- t1[DFLG] =| FAND|FPRS|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 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)
- p1[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++;
- p1[n++] = 0;
- t = tree(n+5);
- t[DTYP] = TCOM;
- for(l=0; l<n; l++)
- t[l+DCOM] = p1[l];
- out:
- t[DFLG] = flg;
- t[DLEF] = i;
- t[DRIT] = o;
- return(t);
- }
-
- scan(at, f)
- int *at;
- int (*f)();
- {
- register char *p, c;
- register *t;
-
- t = at+DCOM;
- while(p = *t++)
- while(c = *p)
- *p++ = (*f)(c);
- }
-
- tglob(c)
- int c;
- {
-
- if(any(c, "[?*"))
- gflg = 1;
- return(c);
- }
-
- trim(c)
- int c;
- {
-
- return(c&0177);
- }
-
- execute(t, pf1, pf2)
- int *t, *pf1, *pf2;
- {
- int i, f, pv[2];
- register *t1;
- register char *cp1, *cp2;
- extern errno;
-
- if(t != 0)
- switch(t[DTYP]) {
-
- case TCOM:
- cp1 = t[DCOM];
- if(equal(cp1, "chdir")) {
- if(t[DCOM+1] != 0) {
- if(chdir(t[DCOM+1]) < 0)
- err("chdir: bad directory");
- } else
- err("chdir: arg count");
- return;
- }
- if(equal(cp1, "shift")) {
- if(dolc < 1) {
- prs("shift: no args\n");
- return;
- }
- dolv[1] = dolv[0];
- dolv++;
- dolc--;
- return;
- }
- if(equal(cp1, "login")) {
- if(promp != 0) {
- close(acctf);
- execv("/bin/login", t+DCOM);
- }
- prs("login: cannot execute\n");
- return;
- }
- if(equal(cp1, "newgrp")) {
- if(promp != 0) {
- close(acctf);
- execv("/bin/newgrp", t+DCOM);
- }
- prs("newgrp: cannot execute\n");
- return;
- }
- if(equal(cp1, "wait")) {
- pwait(-1, 0);
- return;
- }
- if(equal(cp1, ":"))
- return;
-
- case TPAR:
- f = t[DFLG];
- i = 0;
- if((f&FPAR) == 0)
- i = fork();
- if(i == -1) {
- err("try again");
- return;
- }
- if(i != 0) {
- if((f&FPIN) != 0) {
- close(pf1[0]);
- close(pf1[1]);
- }
- if((f&FPRS) != 0) {
- prn(i);
- prs("\n");
- }
- if((f&FAND) != 0)
- return;
- if((f&FPOU) == 0)
- pwait(i, t);
- return;
- }
- if(t[DLEF] != 0) {
- close(0);
- i = open(t[DLEF], 0);
- if(i < 0) {
- prs(t[DLEF]);
- err(": cannot open");
- exit();
- }
- }
- if(t[DRIT] != 0) {
- if((f&FCAT) != 0) {
- i = open(t[DRIT], 1);
- if(i >= 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;
- texec(t[DCOM], t);
- cp1 = linep;
- cp2 = "/usr/bin/";
- while(*cp1 = *cp2++)
- cp1++;
- cp2 = t[DCOM];
- while(*cp1++ = *cp2++);
- texec(linep+4, t);
- texec(linep, t);
- prs(t[DCOM]);
- err(": not found");
- exit();
-
- case TFIL:
- f = t[DFLG];
- pipe(pv);
- t1 = t[DLEF];
- t1[DFLG] =| FPOU | (f&(FPIN|FINT|FPRS));
- execute(t1, pf1, pv);
- t1 = t[DRIT];
- t1[DFLG] =| FPIN | (f&(FPOU|FINT|FAND|FPRS));
- 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;
-
- }
- }
-
- texec(f, at)
- int *at;
- {
- extern errno;
- register int *t;
-
- t = at;
- execv(f, t+DCOM);
- if (errno==ENOEXEC) {
- if (*linep)
- t[DCOM] = linep;
- t[DSPR] = "/bin/sh";
- execv(t[DSPR], t+DSPR);
- prs("No shell!\n");
- exit();
- }
- if (errno==ENOMEM) {
- prs(t[DCOM]);
- err(": too large");
- exit();
- }
- }
-
- 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 shf;
- 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;
- tbuf.shf = 0;
- if (promp==0)
- tbuf.shf = 1;
- seek(acctf, 0, 2);
- write(acctf, &tbuf, sizeof(tbuf));
- }
-