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