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