Research V5 development
authorKen Thompson <ken@research.uucp>
Tue, 26 Nov 1974 23:13:21 +0000 (18:13 -0500)
committerKen Thompson <ken@research.uucp>
Tue, 26 Nov 1974 23:13:21 +0000 (18:13 -0500)
Work on file usr/source/s2/sh.c

Synthesized-from: v5

usr/source/s2/sh.c [new file with mode: 0644]

diff --git a/usr/source/s2/sh.c b/usr/source/s2/sh.c
new file mode 100644 (file)
index 0000000..12921e9
--- /dev/null
@@ -0,0 +1,858 @@
+#
+/*
+ * 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<n; l++)
+               t[l+dcom] = b[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, "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&fand) != 0) {
+                               prn(i);
+                               prs("\n");
+                               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;
+               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));
+}