home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / s2 / sh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-17  |  11.3 KB  |  899 lines

  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. }
  899.