home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / osh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  10.7 KB  |  845 lines

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