114479Ssam #ifndef lint
2*60176Sbostic static char sccsid[] = "@(#)service.c 4.9 05/21/93";
314479Ssam #endif
46702Smckusick
5*60176Sbostic #include <unistd.h>
6*60176Sbostic
76702Smckusick #
86702Smckusick /*
96702Smckusick * UNIX shell
106702Smckusick *
116702Smckusick * S. R. Bourne
126702Smckusick * Bell Telephone Laboratories
136702Smckusick *
146702Smckusick */
156702Smckusick
166702Smckusick #include "defs.h"
1735773Sbostic #include "errno.h"
1840926Smckusick #include "sys/file.h"
1937678Sbostic #include "pathnames.h"
206702Smckusick
216702Smckusick
226702Smckusick PROC VOID gsort();
236702Smckusick
246702Smckusick #define ARGMK 01
256702Smckusick
266702Smckusick INT errno;
276702Smckusick STRING sysmsg[];
2818430Smckusick INT num_sysmsg;
296702Smckusick
306702Smckusick /* service routines for `execute' */
316702Smckusick
initio(iop)326702Smckusick VOID initio(iop)
336702Smckusick IOPTR iop;
346702Smckusick {
356702Smckusick REG STRING ion;
366702Smckusick REG INT iof, fd;
376702Smckusick
386702Smckusick IF iop
396702Smckusick THEN iof=iop->iofile;
406702Smckusick ion=mactrim(iop->ioname);
416702Smckusick IF *ion ANDF (flags&noexec)==0
426702Smckusick THEN IF iof&IODOC
436702Smckusick THEN subst(chkopen(ion),(fd=tmpfil()));
446702Smckusick close(fd); fd=chkopen(tmpout); unlink(tmpout);
456702Smckusick ELIF iof&IOMOV
466702Smckusick THEN IF eq(minus,ion)
476702Smckusick THEN fd = -1;
486702Smckusick close(iof&IOUFD);
496702Smckusick ELIF (fd=stoi(ion))>=USERIO
506702Smckusick THEN failed(ion,badfile);
516702Smckusick ELSE fd=dup(fd);
526702Smckusick FI
536702Smckusick ELIF (iof&IOPUT)==0
546702Smckusick THEN fd=chkopen(ion);
556702Smckusick ELIF flags&rshflg
566702Smckusick THEN failed(ion,restricted);
5740926Smckusick ELIF (iof&IOAPP)==0 ORF
5840926Smckusick (fd=open(ion,O_WRONLY|O_APPEND))<0
5940926Smckusick THEN fd=create(ion);
606702Smckusick FI
616702Smckusick IF fd>=0
626702Smckusick THEN rename(fd,iof&IOUFD);
636702Smckusick FI
646702Smckusick FI
656702Smckusick initio(iop->ionxt);
666702Smckusick FI
676702Smckusick }
686702Smckusick
getpath(s)696702Smckusick STRING getpath(s)
706702Smckusick STRING s;
716702Smckusick {
726702Smckusick REG STRING path;
736702Smckusick IF any('/',s)
746702Smckusick THEN IF flags&rshflg
756702Smckusick THEN failed(s, restricted);
766702Smckusick ELSE return(nullstr);
776702Smckusick FI
786702Smckusick ELIF (path = pathnod.namval)==0
7937678Sbostic THEN return(_PATH_DEFPATH);
806702Smckusick ELSE return(cpystak(path));
816702Smckusick FI
826702Smckusick }
836702Smckusick
pathopen(path,name)846702Smckusick INT pathopen(path, name)
856702Smckusick REG STRING path, name;
866702Smckusick {
876702Smckusick REG UFD f;
886702Smckusick
896702Smckusick REP path=catpath(path,name);
906702Smckusick PER (f=open(curstak(),0))<0 ANDF path DONE
916702Smckusick return(f);
926702Smckusick }
936702Smckusick
catpath(path,name)946702Smckusick STRING catpath(path,name)
956702Smckusick REG STRING path;
966702Smckusick STRING name;
976702Smckusick {
986702Smckusick /* leaves result on top of stack */
996702Smckusick REG STRING scanp = path,
1006702Smckusick argp = locstak();
1016702Smckusick
1026702Smckusick WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD
1036702Smckusick IF scanp!=path THEN *argp++='/' FI
1046702Smckusick IF *scanp==COLON THEN scanp++ FI
1056702Smckusick path=(*scanp ? scanp : 0); scanp=name;
1066702Smckusick WHILE (*argp++ = *scanp++) DONE
1076702Smckusick return(path);
1086702Smckusick }
1096702Smckusick
1106702Smckusick LOCAL STRING xecmsg;
1116702Smckusick LOCAL STRING *xecenv;
1126702Smckusick
execa(at)1136702Smckusick VOID execa(at)
1146702Smckusick STRING at[];
1156702Smckusick {
1166702Smckusick REG STRING path;
1176702Smckusick REG STRING *t = at;
1186702Smckusick
1196702Smckusick IF (flags&noexec)==0
1206702Smckusick THEN xecmsg=notfound; path=getpath(*t);
1216702Smckusick namscan(exname);
1226702Smckusick xecenv=setenv();
1236702Smckusick WHILE path=execs(path,t) DONE
1246702Smckusick failed(*t,xecmsg);
1256702Smckusick FI
1266702Smckusick }
1276702Smckusick
execs(ap,t)1286702Smckusick LOCAL STRING execs(ap,t)
1296702Smckusick STRING ap;
1306702Smckusick REG STRING t[];
1316702Smckusick {
1326702Smckusick REG STRING p, prefix;
1336702Smckusick
1346702Smckusick prefix=catpath(ap,t[0]);
1356702Smckusick trim(p=curstak());
1366702Smckusick
1376702Smckusick sigchk();
1386702Smckusick execve(p, &t[0] ,xecenv);
1396702Smckusick SWITCH errno IN
1406702Smckusick
1416702Smckusick case ENOEXEC:
1426702Smckusick flags=0;
1436702Smckusick comdiv=0; ioset=0;
1446702Smckusick clearup(); /* remove open files and for loop junk */
1456702Smckusick IF input THEN close(input) FI
1466702Smckusick close(output); output=2;
1476702Smckusick input=chkopen(p);
1486702Smckusick
1496702Smckusick /* band aid to get csh... 2/26/79 */
1506702Smckusick {
1516702Smckusick char c;
1526702Smckusick if (!isatty(input)) {
1536702Smckusick read(input, &c, 1);
1546702Smckusick if (c == '#')
1556702Smckusick gocsh(t, p, xecenv);
1566702Smckusick lseek(input, (long) 0, 0);
1576702Smckusick }
1586702Smckusick }
1596702Smckusick
1606702Smckusick /* set up new args */
1616702Smckusick setargs(t);
1626702Smckusick longjmp(subshell,1);
1636702Smckusick
1646702Smckusick case ENOMEM:
1656702Smckusick failed(p,toobig);
1666702Smckusick
1676702Smckusick case E2BIG:
1686702Smckusick failed(p,arglist);
1696702Smckusick
1706702Smckusick case ETXTBSY:
1716702Smckusick failed(p,txtbsy);
1726702Smckusick
1736702Smckusick default:
1746702Smckusick xecmsg=badexec;
1756702Smckusick case ENOENT:
1766702Smckusick return(prefix);
1776702Smckusick ENDSW
1786702Smckusick }
1796702Smckusick
gocsh(t,cp,xecenv)1806702Smckusick gocsh(t, cp, xecenv)
1816702Smckusick register char **t, *cp, **xecenv;
1826702Smckusick {
1836702Smckusick char **newt[1000];
1846702Smckusick register char **p;
1856702Smckusick register int i;
1866702Smckusick
1876702Smckusick for (i = 0; t[i]; i++)
1886702Smckusick newt[i+1] = t[i];
1896702Smckusick newt[i+1] = 0;
19037678Sbostic newt[0] = _PATH_CSHELL;
1916702Smckusick newt[1] = cp;
19237678Sbostic execve(_PATH_CSHELL, newt, xecenv);
1936702Smckusick }
1946702Smckusick
1956702Smckusick /* for processes to be waited for */
1966702Smckusick #define MAXP 20
1976702Smckusick LOCAL INT pwlist[MAXP];
1986702Smckusick LOCAL INT pwc;
1996702Smckusick
postclr()2006702Smckusick postclr()
2016702Smckusick {
2026702Smckusick REG INT *pw = pwlist;
2036702Smckusick
2046702Smckusick WHILE pw <= &pwlist[pwc]
2056702Smckusick DO *pw++ = 0 OD
2066702Smckusick pwc=0;
2076702Smckusick }
2086702Smckusick
post(pcsid)2096702Smckusick VOID post(pcsid)
2106702Smckusick INT pcsid;
2116702Smckusick {
2126702Smckusick REG INT *pw = pwlist;
2136702Smckusick
2146702Smckusick IF pcsid
2156702Smckusick THEN WHILE *pw DO pw++ OD
2166702Smckusick IF pwc >= MAXP-1
2176702Smckusick THEN pw--;
2186702Smckusick ELSE pwc++;
2196702Smckusick FI
2206702Smckusick *pw = pcsid;
2216702Smckusick FI
2226702Smckusick }
2236702Smckusick
await(i)2246702Smckusick VOID await(i)
2256702Smckusick INT i;
2266702Smckusick {
2276702Smckusick INT rc=0, wx=0;
2286702Smckusick INT w;
2296702Smckusick INT ipwc = pwc;
2306702Smckusick
2316702Smckusick post(i);
2326702Smckusick WHILE pwc
2336702Smckusick DO REG INT p;
2346702Smckusick REG INT sig;
2356702Smckusick INT w_hi;
2366702Smckusick
2376702Smckusick BEGIN
2386702Smckusick REG INT *pw=pwlist;
23914935Smckusick IF setjmp(INTbuf) == 0
24014935Smckusick THEN trapjmp[INTR] = 1; p=wait(&w);
24114935Smckusick ELSE p = -1;
24214935Smckusick FI
24314935Smckusick trapjmp[INTR] = 0;
2446702Smckusick WHILE pw <= &pwlist[ipwc]
2456702Smckusick DO IF *pw==p
2466702Smckusick THEN *pw=0; pwc--;
2476702Smckusick ELSE pw++;
2486702Smckusick FI
2496702Smckusick OD
2506702Smckusick END
2516702Smckusick
2526702Smckusick IF p == -1 THEN continue FI
2536702Smckusick
2546702Smckusick w_hi = (w>>8)&LOBYTE;
2556702Smckusick
2566702Smckusick IF sig = w&0177
2576702Smckusick THEN IF sig == 0177 /* ptrace! return */
2586702Smckusick THEN prs("ptrace: ");
2596702Smckusick sig = w_hi;
2606702Smckusick FI
26118430Smckusick IF sig < num_sysmsg ANDF sysmsg[sig]
26218430Smckusick THEN IF i!=p ORF (flags&prompt)==0
26318430Smckusick THEN prp(); prn(p); blank()
26418430Smckusick FI
2656702Smckusick prs(sysmsg[sig]);
2666702Smckusick IF w&0200 THEN prs(coredump) FI
2676702Smckusick FI
2686702Smckusick newline();
2696702Smckusick FI
2706702Smckusick
2716702Smckusick IF rc==0
2726702Smckusick THEN rc = (sig ? sig|SIGFLG : w_hi);
2736702Smckusick FI
2746702Smckusick wx |= w;
2756702Smckusick OD
2766702Smckusick
2776702Smckusick IF wx ANDF flags&errflg
2786702Smckusick THEN exitsh(rc);
2796702Smckusick FI
2806702Smckusick exitval=rc; exitset();
2816702Smckusick }
2826702Smckusick
2836702Smckusick BOOL nosubst;
2846702Smckusick
trim(at)2856702Smckusick trim(at)
2866702Smckusick STRING at;
2876702Smckusick {
2886702Smckusick REG STRING p;
2896702Smckusick REG CHAR c;
2906702Smckusick REG CHAR q=0;
2916702Smckusick
2926702Smckusick IF p=at
2936702Smckusick THEN WHILE c = *p
2946702Smckusick DO *p++=c&STRIP; q |= c OD
2956702Smckusick FI
2966702Smckusick nosubst=q"E;
2976702Smckusick }
2986702Smckusick
mactrim(s)2996702Smckusick STRING mactrim(s)
3006702Smckusick STRING s;
3016702Smckusick {
3026702Smckusick REG STRING t=macro(s);
3036702Smckusick trim(t);
3046702Smckusick return(t);
3056702Smckusick }
3066702Smckusick
scan(argn)3076702Smckusick STRING *scan(argn)
3086702Smckusick INT argn;
3096702Smckusick {
3106702Smckusick REG ARGPTR argp = Rcheat(gchain)&~ARGMK;
3116702Smckusick REG STRING *comargn, *comargm;
3126702Smckusick
3136702Smckusick comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
3146702Smckusick
3156702Smckusick WHILE argp
3166702Smckusick DO *--comargn = argp->argval;
3176702Smckusick IF argp = argp->argnxt
3186702Smckusick THEN trim(*comargn);
3196702Smckusick FI
3206702Smckusick IF argp==0 ORF Rcheat(argp)&ARGMK
3216702Smckusick THEN gsort(comargn,comargm);
3226702Smckusick comargm = comargn;
3236702Smckusick FI
3246702Smckusick /* Lcheat(argp) &= ~ARGMK; */
3256702Smckusick argp = Rcheat(argp)&~ARGMK;
3266702Smckusick OD
3276702Smckusick return(comargn);
3286702Smckusick }
3296702Smckusick
gsort(from,to)3306702Smckusick LOCAL VOID gsort(from,to)
3316702Smckusick STRING from[], to[];
3326702Smckusick {
3336702Smckusick INT k, m, n;
3346702Smckusick REG INT i, j;
3356702Smckusick
3366702Smckusick IF (n=to-from)<=1 THEN return FI
3376702Smckusick
3386702Smckusick FOR j=1; j<=n; j*=2 DONE
3396702Smckusick
3406702Smckusick FOR m=2*j-1; m/=2;
3416702Smckusick DO k=n-m;
3426702Smckusick FOR j=0; j<k; j++
3436702Smckusick DO FOR i=j; i>=0; i-=m
3446702Smckusick DO REG STRING *fromi; fromi = &from[i];
3456702Smckusick IF cf(fromi[m],fromi[0])>0
3466702Smckusick THEN break;
3476702Smckusick ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
3486702Smckusick FI
3496702Smckusick OD
3506702Smckusick OD
3516702Smckusick OD
3526702Smckusick }
3536702Smckusick
3546702Smckusick /* Argument list generation */
3556702Smckusick
getarg(ac)3566702Smckusick INT getarg(ac)
3576702Smckusick COMPTR ac;
3586702Smckusick {
3596702Smckusick REG ARGPTR argp;
3606702Smckusick REG INT count=0;
3616702Smckusick REG COMPTR c;
3626702Smckusick
3636702Smckusick IF c=ac
3646702Smckusick THEN argp=c->comarg;
3656702Smckusick WHILE argp
3666702Smckusick DO count += split(macro(argp->argval));
3676702Smckusick argp=argp->argnxt;
3686702Smckusick OD
3696702Smckusick FI
3706702Smckusick return(count);
3716702Smckusick }
3726702Smckusick
split(s)3736702Smckusick LOCAL INT split(s)
3746702Smckusick REG STRING s;
3756702Smckusick {
3766702Smckusick REG STRING argp;
3776702Smckusick REG INT c;
3786702Smckusick INT count=0;
3796702Smckusick
3806702Smckusick LOOP sigchk(); argp=locstak()+BYTESPERWORD;
3816702Smckusick WHILE (c = *s++, !any(c,ifsnod.namval) && c)
3826702Smckusick DO *argp++ = c OD
3836702Smckusick IF argp==staktop+BYTESPERWORD
3846702Smckusick THEN IF c
3856702Smckusick THEN continue;
3866702Smckusick ELSE return(count);
3876702Smckusick FI
3886702Smckusick ELIF c==0
3896702Smckusick THEN s--;
3906702Smckusick FI
39134082Sbostic IF c=expand(((ARGPTR)(argp=endstak(argp)))->argval,0)
3926702Smckusick THEN count += c;
3936702Smckusick ELSE /* assign(&fngnod, argp->argval); */
3946702Smckusick makearg(argp); count++;
3956702Smckusick FI
3966702Smckusick Lcheat(gchain) |= ARGMK;
3976702Smckusick POOL
3986702Smckusick }
399