xref: /csrg-svn/old/sh/service.c (revision 60176)
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&QUOTE;
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