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

  1. #
  2. /*
  3.  * UNIX shell
  4.  *
  5.  * S. R. Bourne
  6.  * Bell Telephone Laboratories
  7.  *
  8.  */
  9.  
  10. #include    "defs.h"
  11.  
  12.  
  13. PROC VOID    gsort();
  14.  
  15. #define ARGMK    01
  16.  
  17. INT        errno;
  18. STRING        sysmsg[];
  19.  
  20. /* fault handling */
  21. #define ENOMEM    12
  22. #define ENOEXEC 8
  23. #define E2BIG    7
  24. #define ENOENT    2
  25. #define ETXTBSY 26
  26.  
  27.  
  28.  
  29. /* service routines for `execute' */
  30.  
  31. VOID    initio(iop)
  32.     IOPTR        iop;
  33. {
  34.     REG STRING    ion;
  35.     REG INT        iof, fd;
  36.  
  37.     IF iop
  38.     THEN    iof=iop->iofile;
  39.         ion=mactrim(iop->ioname);
  40.         IF *ion ANDF (flags&noexec)==0
  41.         THEN    IF iof&IODOC
  42.             THEN    subst(chkopen(ion),(fd=tmpfil()));
  43.                 close(fd); fd=chkopen(tmpout); unlink(tmpout);
  44.             ELIF iof&IOMOV
  45.             THEN    IF eq(minus,ion)
  46.                 THEN    fd = -1;
  47.                     close(iof&IOUFD);
  48.                 ELIF (fd=stoi(ion))>=USERIO
  49.                 THEN    failed(ion,badfile);
  50.                 ELSE    fd=dup(fd);
  51.                 FI
  52.             ELIF (iof&IOPUT)==0
  53.             THEN    fd=chkopen(ion);
  54.             ELIF flags&rshflg
  55.             THEN    failed(ion,restricted);
  56.             ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0
  57.             THEN    lseek(fd, 0L, 2);
  58.             ELSE    fd=create(ion);
  59.             FI
  60.             IF fd>=0
  61.             THEN    rename(fd,iof&IOUFD);
  62.             FI
  63.         FI
  64.         initio(iop->ionxt);
  65.     FI
  66. }
  67.  
  68. STRING    getpath(s)
  69.     STRING        s;
  70. {
  71.     REG STRING    path;
  72.     IF any('/',s)
  73.     THEN    IF flags&rshflg
  74.         THEN    failed(s, restricted);
  75.         ELSE    return(nullstr);
  76.         FI
  77.     ELIF (path = pathnod.namval)==0
  78.     THEN    return(defpath);
  79.     ELSE    return(cpystak(path));
  80.     FI
  81. }
  82.  
  83. INT    pathopen(path, name)
  84.     REG STRING    path, name;
  85. {
  86.     REG UFD        f;
  87.  
  88.     REP path=catpath(path,name);
  89.     PER (f=open(curstak(),0))<0 ANDF path DONE
  90.     return(f);
  91. }
  92.  
  93. STRING    catpath(path,name)
  94.     REG STRING    path;
  95.     STRING        name;
  96. {
  97.     /* leaves result on top of stack */
  98.     REG STRING    scanp = path,
  99.             argp = locstak();
  100.  
  101.     WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD
  102.     IF scanp!=path THEN *argp++='/' FI
  103.     IF *scanp==COLON THEN scanp++ FI
  104.     path=(*scanp ? scanp : 0); scanp=name;
  105.     WHILE (*argp++ = *scanp++) DONE
  106.     return(path);
  107. }
  108.  
  109. LOCAL STRING    xecmsg;
  110. LOCAL STRING    *xecenv;
  111.  
  112. VOID    execa(at)
  113.     STRING        at[];
  114. {
  115.     REG STRING    path;
  116.     REG STRING    *t = at;
  117.  
  118.     IF (flags&noexec)==0
  119.     THEN    xecmsg=notfound; path=getpath(*t);
  120.         namscan(exname);
  121.         xecenv=setenv();
  122.         WHILE path=execs(path,t) DONE
  123.         failed(*t,xecmsg);
  124.     FI
  125. }
  126.  
  127. LOCAL STRING    execs(ap,t)
  128.     STRING        ap;
  129.     REG STRING    t[];
  130. {
  131.     REG STRING    p, prefix;
  132.  
  133.     prefix=catpath(ap,t[0]);
  134.     trim(p=curstak());
  135.  
  136.     sigchk();
  137.     execve(p, &t[0] ,xecenv);
  138.     SWITCH errno IN
  139.  
  140.         case ENOEXEC:
  141.         flags=0;
  142.         comdiv=0; ioset=0;
  143.         clearup(); /* remove open files and for loop junk */
  144.         IF input THEN close(input) FI
  145.         close(output); output=2;
  146.         input=chkopen(p);
  147.  
  148.         /* set up new args */
  149.         setargs(t);
  150.         longjmp(subshell,1);
  151.  
  152.         case ENOMEM:
  153.         failed(p,toobig);
  154.  
  155.         case E2BIG:
  156.         failed(p,arglist);
  157.  
  158.         case ETXTBSY:
  159.         failed(p,txtbsy);
  160.  
  161.         default:
  162.         xecmsg=badexec;
  163.         case ENOENT:
  164.         return(prefix);
  165.     ENDSW
  166. }
  167.  
  168. /* for processes to be waited for */
  169. #define MAXP 20
  170. LOCAL INT    pwlist[MAXP];
  171. LOCAL INT    pwc;
  172.  
  173. postclr()
  174. {
  175.     REG INT        *pw = pwlist;
  176.  
  177.     WHILE pw <= &pwlist[pwc]
  178.     DO *pw++ = 0 OD
  179.     pwc=0;
  180. }
  181.  
  182. VOID    post(pcsid)
  183.     INT        pcsid;
  184. {
  185.     REG INT        *pw = pwlist;
  186.  
  187.     IF pcsid
  188.     THEN    WHILE *pw DO pw++ OD
  189.         IF pwc >= MAXP-1
  190.         THEN    pw--;
  191.         ELSE    pwc++;
  192.         FI
  193.         *pw = pcsid;
  194.     FI
  195. }
  196.  
  197. VOID    await(i)
  198.     INT        i;
  199. {
  200.     INT        rc=0, wx=0;
  201.     INT        w;
  202.     INT        ipwc = pwc;
  203.  
  204.     post(i);
  205.     WHILE pwc
  206.     DO    REG INT        p;
  207.         REG INT        sig;
  208.         INT        w_hi;
  209.  
  210.         BEGIN
  211.            REG INT    *pw=pwlist;
  212.            p=wait(&w);
  213.            WHILE pw <= &pwlist[ipwc]
  214.            DO IF *pw==p
  215.               THEN *pw=0; pwc--;
  216.               ELSE pw++;
  217.               FI
  218.            OD
  219.         END
  220.  
  221.         IF p == -1 THEN continue FI
  222.  
  223.         w_hi = (w>>8)&LOBYTE;
  224.  
  225.         IF sig = w&0177
  226.         THEN    IF sig == 0177    /* ptrace! return */
  227.             THEN    prs("ptrace: ");
  228.                 sig = w_hi;
  229.             FI
  230.             IF sysmsg[sig]
  231.             THEN    IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI
  232.                 prs(sysmsg[sig]);
  233.                 IF w&0200 THEN prs(coredump) FI
  234.             FI
  235.             newline();
  236.         FI
  237.  
  238.         IF rc==0
  239.         THEN    rc = (sig ? sig|SIGFLG : w_hi);
  240.         FI
  241.         wx |= w;
  242.     OD
  243.  
  244.     IF wx ANDF flags&errflg
  245.     THEN    exitsh(rc);
  246.     FI
  247.     exitval=rc; exitset();
  248. }
  249.  
  250. BOOL        nosubst;
  251.  
  252. trim(at)
  253.     STRING        at;
  254. {
  255.     REG STRING    p;
  256.     REG CHAR    c;
  257.     REG CHAR    q=0;
  258.  
  259.     IF p=at
  260.     THEN    WHILE c = *p
  261.         DO *p++=c&STRIP; q |= c OD
  262.     FI
  263.     nosubst=q"E;
  264. }
  265.  
  266. STRING    mactrim(s)
  267.     STRING        s;
  268. {
  269.     REG STRING    t=macro(s);
  270.     trim(t);
  271.     return(t);
  272. }
  273.  
  274. STRING    *scan(argn)
  275.     INT        argn;
  276. {
  277.     REG ARGPTR    argp = Rcheat(gchain)&~ARGMK;
  278.     REG STRING    *comargn, *comargm;
  279.  
  280.     comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
  281.  
  282.     WHILE argp
  283.     DO    *--comargn = argp->argval;
  284.         IF argp = argp->argnxt
  285.         THEN trim(*comargn);
  286.         FI
  287.         IF argp==0 ORF Rcheat(argp)&ARGMK
  288.         THEN    gsort(comargn,comargm);
  289.             comargm = comargn;
  290.         FI
  291.         /* Lcheat(argp) &= ~ARGMK; */
  292.         argp = Rcheat(argp)&~ARGMK;
  293.     OD
  294.     return(comargn);
  295. }
  296.  
  297. LOCAL VOID    gsort(from,to)
  298.     STRING        from[], to[];
  299. {
  300.     INT        k, m, n;
  301.     REG INT        i, j;
  302.  
  303.     IF (n=to-from)<=1 THEN return FI
  304.  
  305.     FOR j=1; j<=n; j*=2 DONE
  306.  
  307.     FOR m=2*j-1; m/=2;
  308.     DO  k=n-m;
  309.         FOR j=0; j<k; j++
  310.         DO    FOR i=j; i>=0; i-=m
  311.         DO  REG STRING *fromi; fromi = &from[i];
  312.             IF cf(fromi[m],fromi[0])>0
  313.             THEN break;
  314.             ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
  315.             FI
  316.         OD
  317.         OD
  318.     OD
  319. }
  320.  
  321. /* Argument list generation */
  322.  
  323. INT    getarg(ac)
  324.     COMPTR        ac;
  325. {
  326.     REG ARGPTR    argp;
  327.     REG INT        count=0;
  328.     REG COMPTR    c;
  329.  
  330.     IF c=ac
  331.     THEN    argp=c->comarg;
  332.         WHILE argp
  333.         DO    count += split(macro(argp->argval));
  334.             argp=argp->argnxt;
  335.         OD
  336.     FI
  337.     return(count);
  338. }
  339.  
  340. LOCAL INT    split(s)
  341.     REG STRING    s;
  342. {
  343.     REG STRING    argp;
  344.     REG INT        c;
  345.     INT        count=0;
  346.  
  347.     LOOP    sigchk(); argp=locstak()+BYTESPERWORD;
  348.         WHILE (c = *s++, !any(c,ifsnod.namval) && c)
  349.         DO *argp++ = c OD
  350.         IF argp==staktop+BYTESPERWORD
  351.         THEN    IF c
  352.             THEN    continue;
  353.             ELSE    return(count);
  354.             FI
  355.         ELIF c==0
  356.         THEN    s--;
  357.         FI
  358.         IF c=expand((argp=endstak(argp))->argval,0)
  359.         THEN    count += c;
  360.         ELSE    /* assign(&fngnod, argp->argval); */
  361.             makearg(argp); count++;
  362.         FI
  363.         Lcheat(gchain) |= ARGMK;
  364.     POOL
  365. }
  366.