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