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