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