xref: /csrg-svn/old/sh/service.c (revision 6702)
1*6702Smckusick /*	service.c	4.1	82/05/07	*/
2*6702Smckusick 
3*6702Smckusick #
4*6702Smckusick /*
5*6702Smckusick  * UNIX shell
6*6702Smckusick  *
7*6702Smckusick  * S. R. Bourne
8*6702Smckusick  * Bell Telephone Laboratories
9*6702Smckusick  *
10*6702Smckusick  */
11*6702Smckusick 
12*6702Smckusick #include	"defs.h"
13*6702Smckusick 
14*6702Smckusick 
15*6702Smckusick PROC VOID	gsort();
16*6702Smckusick 
17*6702Smckusick #define ARGMK	01
18*6702Smckusick 
19*6702Smckusick INT		errno;
20*6702Smckusick STRING		sysmsg[];
21*6702Smckusick 
22*6702Smckusick /* fault handling */
23*6702Smckusick #define ENOMEM	12
24*6702Smckusick #define ENOEXEC 8
25*6702Smckusick #define E2BIG	7
26*6702Smckusick #define ENOENT	2
27*6702Smckusick #define ETXTBSY 26
28*6702Smckusick 
29*6702Smckusick 
30*6702Smckusick 
31*6702Smckusick /* service routines for `execute' */
32*6702Smckusick 
33*6702Smckusick VOID	initio(iop)
34*6702Smckusick 	IOPTR		iop;
35*6702Smckusick {
36*6702Smckusick 	REG STRING	ion;
37*6702Smckusick 	REG INT		iof, fd;
38*6702Smckusick 
39*6702Smckusick 	IF iop
40*6702Smckusick 	THEN	iof=iop->iofile;
41*6702Smckusick 		ion=mactrim(iop->ioname);
42*6702Smckusick 		IF *ion ANDF (flags&noexec)==0
43*6702Smckusick 		THEN	IF iof&IODOC
44*6702Smckusick 			THEN	subst(chkopen(ion),(fd=tmpfil()));
45*6702Smckusick 				close(fd); fd=chkopen(tmpout); unlink(tmpout);
46*6702Smckusick 			ELIF iof&IOMOV
47*6702Smckusick 			THEN	IF eq(minus,ion)
48*6702Smckusick 				THEN	fd = -1;
49*6702Smckusick 					close(iof&IOUFD);
50*6702Smckusick 				ELIF (fd=stoi(ion))>=USERIO
51*6702Smckusick 				THEN	failed(ion,badfile);
52*6702Smckusick 				ELSE	fd=dup(fd);
53*6702Smckusick 				FI
54*6702Smckusick 			ELIF (iof&IOPUT)==0
55*6702Smckusick 			THEN	fd=chkopen(ion);
56*6702Smckusick 			ELIF flags&rshflg
57*6702Smckusick 			THEN	failed(ion,restricted);
58*6702Smckusick 			ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0
59*6702Smckusick 			THEN	lseek(fd, 0L, 2);
60*6702Smckusick 			ELSE	fd=create(ion);
61*6702Smckusick 			FI
62*6702Smckusick 			IF fd>=0
63*6702Smckusick 			THEN	rename(fd,iof&IOUFD);
64*6702Smckusick 			FI
65*6702Smckusick 		FI
66*6702Smckusick 		initio(iop->ionxt);
67*6702Smckusick 	FI
68*6702Smckusick }
69*6702Smckusick 
70*6702Smckusick STRING	getpath(s)
71*6702Smckusick 	STRING		s;
72*6702Smckusick {
73*6702Smckusick 	REG STRING	path;
74*6702Smckusick 	IF any('/',s)
75*6702Smckusick 	THEN	IF flags&rshflg
76*6702Smckusick 		THEN	failed(s, restricted);
77*6702Smckusick 		ELSE	return(nullstr);
78*6702Smckusick 		FI
79*6702Smckusick 	ELIF (path = pathnod.namval)==0
80*6702Smckusick 	THEN	return(defpath);
81*6702Smckusick 	ELSE	return(cpystak(path));
82*6702Smckusick 	FI
83*6702Smckusick }
84*6702Smckusick 
85*6702Smckusick INT	pathopen(path, name)
86*6702Smckusick 	REG STRING	path, name;
87*6702Smckusick {
88*6702Smckusick 	REG UFD		f;
89*6702Smckusick 
90*6702Smckusick 	REP path=catpath(path,name);
91*6702Smckusick 	PER (f=open(curstak(),0))<0 ANDF path DONE
92*6702Smckusick 	return(f);
93*6702Smckusick }
94*6702Smckusick 
95*6702Smckusick STRING	catpath(path,name)
96*6702Smckusick 	REG STRING	path;
97*6702Smckusick 	STRING		name;
98*6702Smckusick {
99*6702Smckusick 	/* leaves result on top of stack */
100*6702Smckusick 	REG STRING	scanp = path,
101*6702Smckusick 			argp = locstak();
102*6702Smckusick 
103*6702Smckusick 	WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD
104*6702Smckusick 	IF scanp!=path THEN *argp++='/' FI
105*6702Smckusick 	IF *scanp==COLON THEN scanp++ FI
106*6702Smckusick 	path=(*scanp ? scanp : 0); scanp=name;
107*6702Smckusick 	WHILE (*argp++ = *scanp++) DONE
108*6702Smckusick 	return(path);
109*6702Smckusick }
110*6702Smckusick 
111*6702Smckusick LOCAL STRING	xecmsg;
112*6702Smckusick LOCAL STRING	*xecenv;
113*6702Smckusick 
114*6702Smckusick VOID	execa(at)
115*6702Smckusick 	STRING		at[];
116*6702Smckusick {
117*6702Smckusick 	REG STRING	path;
118*6702Smckusick 	REG STRING	*t = at;
119*6702Smckusick 
120*6702Smckusick 	IF (flags&noexec)==0
121*6702Smckusick 	THEN	xecmsg=notfound; path=getpath(*t);
122*6702Smckusick 		namscan(exname);
123*6702Smckusick 		xecenv=setenv();
124*6702Smckusick 		WHILE path=execs(path,t) DONE
125*6702Smckusick 		failed(*t,xecmsg);
126*6702Smckusick 	FI
127*6702Smckusick }
128*6702Smckusick 
129*6702Smckusick LOCAL STRING	execs(ap,t)
130*6702Smckusick 	STRING		ap;
131*6702Smckusick 	REG STRING	t[];
132*6702Smckusick {
133*6702Smckusick 	REG STRING	p, prefix;
134*6702Smckusick 
135*6702Smckusick 	prefix=catpath(ap,t[0]);
136*6702Smckusick 	trim(p=curstak());
137*6702Smckusick 
138*6702Smckusick 	sigchk();
139*6702Smckusick 	execve(p, &t[0] ,xecenv);
140*6702Smckusick 	SWITCH errno IN
141*6702Smckusick 
142*6702Smckusick 	    case ENOEXEC:
143*6702Smckusick 		flags=0;
144*6702Smckusick 		comdiv=0; ioset=0;
145*6702Smckusick 		clearup(); /* remove open files and for loop junk */
146*6702Smckusick 		IF input THEN close(input) FI
147*6702Smckusick 		close(output); output=2;
148*6702Smckusick 		input=chkopen(p);
149*6702Smckusick 
150*6702Smckusick 		/* band aid to get csh... 2/26/79 */
151*6702Smckusick 		{
152*6702Smckusick 			char c;
153*6702Smckusick 			if (!isatty(input)) {
154*6702Smckusick 				read(input, &c, 1);
155*6702Smckusick 				if (c == '#')
156*6702Smckusick 					gocsh(t, p, xecenv);
157*6702Smckusick 				lseek(input, (long) 0, 0);
158*6702Smckusick 			}
159*6702Smckusick 		}
160*6702Smckusick 
161*6702Smckusick 		/* set up new args */
162*6702Smckusick 		setargs(t);
163*6702Smckusick 		longjmp(subshell,1);
164*6702Smckusick 
165*6702Smckusick 	    case ENOMEM:
166*6702Smckusick 		failed(p,toobig);
167*6702Smckusick 
168*6702Smckusick 	    case E2BIG:
169*6702Smckusick 		failed(p,arglist);
170*6702Smckusick 
171*6702Smckusick 	    case ETXTBSY:
172*6702Smckusick 		failed(p,txtbsy);
173*6702Smckusick 
174*6702Smckusick 	    default:
175*6702Smckusick 		xecmsg=badexec;
176*6702Smckusick 	    case ENOENT:
177*6702Smckusick 		return(prefix);
178*6702Smckusick 	ENDSW
179*6702Smckusick }
180*6702Smckusick 
181*6702Smckusick gocsh(t, cp, xecenv)
182*6702Smckusick 	register char **t, *cp, **xecenv;
183*6702Smckusick {
184*6702Smckusick 	char **newt[1000];
185*6702Smckusick 	register char **p;
186*6702Smckusick 	register int i;
187*6702Smckusick 
188*6702Smckusick 	for (i = 0; t[i]; i++)
189*6702Smckusick 		newt[i+1] = t[i];
190*6702Smckusick 	newt[i+1] = 0;
191*6702Smckusick 	newt[0] = "/bin/csh";
192*6702Smckusick 	newt[1] = cp;
193*6702Smckusick 	execve("/bin/csh", newt, xecenv);
194*6702Smckusick }
195*6702Smckusick 
196*6702Smckusick /* for processes to be waited for */
197*6702Smckusick #define MAXP 20
198*6702Smckusick LOCAL INT	pwlist[MAXP];
199*6702Smckusick LOCAL INT	pwc;
200*6702Smckusick 
201*6702Smckusick postclr()
202*6702Smckusick {
203*6702Smckusick 	REG INT		*pw = pwlist;
204*6702Smckusick 
205*6702Smckusick 	WHILE pw <= &pwlist[pwc]
206*6702Smckusick 	DO *pw++ = 0 OD
207*6702Smckusick 	pwc=0;
208*6702Smckusick }
209*6702Smckusick 
210*6702Smckusick VOID	post(pcsid)
211*6702Smckusick 	INT		pcsid;
212*6702Smckusick {
213*6702Smckusick 	REG INT		*pw = pwlist;
214*6702Smckusick 
215*6702Smckusick 	IF pcsid
216*6702Smckusick 	THEN	WHILE *pw DO pw++ OD
217*6702Smckusick 		IF pwc >= MAXP-1
218*6702Smckusick 		THEN	pw--;
219*6702Smckusick 		ELSE	pwc++;
220*6702Smckusick 		FI
221*6702Smckusick 		*pw = pcsid;
222*6702Smckusick 	FI
223*6702Smckusick }
224*6702Smckusick 
225*6702Smckusick VOID	await(i)
226*6702Smckusick 	INT		i;
227*6702Smckusick {
228*6702Smckusick 	INT		rc=0, wx=0;
229*6702Smckusick 	INT		w;
230*6702Smckusick 	INT		ipwc = pwc;
231*6702Smckusick 
232*6702Smckusick 	post(i);
233*6702Smckusick 	WHILE pwc
234*6702Smckusick 	DO	REG INT		p;
235*6702Smckusick 		REG INT		sig;
236*6702Smckusick 		INT		w_hi;
237*6702Smckusick 
238*6702Smckusick 		BEGIN
239*6702Smckusick 		   REG INT	*pw=pwlist;
240*6702Smckusick 		   p=wait(&w);
241*6702Smckusick 		   WHILE pw <= &pwlist[ipwc]
242*6702Smckusick 		   DO IF *pw==p
243*6702Smckusick 		      THEN *pw=0; pwc--;
244*6702Smckusick 		      ELSE pw++;
245*6702Smckusick 		      FI
246*6702Smckusick 		   OD
247*6702Smckusick 		END
248*6702Smckusick 
249*6702Smckusick 		IF p == -1 THEN continue FI
250*6702Smckusick 
251*6702Smckusick 		w_hi = (w>>8)&LOBYTE;
252*6702Smckusick 
253*6702Smckusick 		IF sig = w&0177
254*6702Smckusick 		THEN	IF sig == 0177	/* ptrace! return */
255*6702Smckusick 			THEN	prs("ptrace: ");
256*6702Smckusick 				sig = w_hi;
257*6702Smckusick 			FI
258*6702Smckusick 			IF sysmsg[sig]
259*6702Smckusick 			THEN	IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI
260*6702Smckusick 				prs(sysmsg[sig]);
261*6702Smckusick 				IF w&0200 THEN prs(coredump) FI
262*6702Smckusick 			FI
263*6702Smckusick 			newline();
264*6702Smckusick 		FI
265*6702Smckusick 
266*6702Smckusick 		IF rc==0
267*6702Smckusick 		THEN	rc = (sig ? sig|SIGFLG : w_hi);
268*6702Smckusick 		FI
269*6702Smckusick 		wx |= w;
270*6702Smckusick 	OD
271*6702Smckusick 
272*6702Smckusick 	IF wx ANDF flags&errflg
273*6702Smckusick 	THEN	exitsh(rc);
274*6702Smckusick 	FI
275*6702Smckusick 	exitval=rc; exitset();
276*6702Smckusick }
277*6702Smckusick 
278*6702Smckusick BOOL		nosubst;
279*6702Smckusick 
280*6702Smckusick trim(at)
281*6702Smckusick 	STRING		at;
282*6702Smckusick {
283*6702Smckusick 	REG STRING	p;
284*6702Smckusick 	REG CHAR	c;
285*6702Smckusick 	REG CHAR	q=0;
286*6702Smckusick 
287*6702Smckusick 	IF p=at
288*6702Smckusick 	THEN	WHILE c = *p
289*6702Smckusick 		DO *p++=c&STRIP; q |= c OD
290*6702Smckusick 	FI
291*6702Smckusick 	nosubst=q&QUOTE;
292*6702Smckusick }
293*6702Smckusick 
294*6702Smckusick STRING	mactrim(s)
295*6702Smckusick 	STRING		s;
296*6702Smckusick {
297*6702Smckusick 	REG STRING	t=macro(s);
298*6702Smckusick 	trim(t);
299*6702Smckusick 	return(t);
300*6702Smckusick }
301*6702Smckusick 
302*6702Smckusick STRING	*scan(argn)
303*6702Smckusick 	INT		argn;
304*6702Smckusick {
305*6702Smckusick 	REG ARGPTR	argp = Rcheat(gchain)&~ARGMK;
306*6702Smckusick 	REG STRING	*comargn, *comargm;
307*6702Smckusick 
308*6702Smckusick 	comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
309*6702Smckusick 
310*6702Smckusick 	WHILE argp
311*6702Smckusick 	DO	*--comargn = argp->argval;
312*6702Smckusick 		IF argp = argp->argnxt
313*6702Smckusick 		THEN trim(*comargn);
314*6702Smckusick 		FI
315*6702Smckusick 		IF argp==0 ORF Rcheat(argp)&ARGMK
316*6702Smckusick 		THEN	gsort(comargn,comargm);
317*6702Smckusick 			comargm = comargn;
318*6702Smckusick 		FI
319*6702Smckusick 		/* Lcheat(argp) &= ~ARGMK; */
320*6702Smckusick 		argp = Rcheat(argp)&~ARGMK;
321*6702Smckusick 	OD
322*6702Smckusick 	return(comargn);
323*6702Smckusick }
324*6702Smckusick 
325*6702Smckusick LOCAL VOID	gsort(from,to)
326*6702Smckusick 	STRING		from[], to[];
327*6702Smckusick {
328*6702Smckusick 	INT		k, m, n;
329*6702Smckusick 	REG INT		i, j;
330*6702Smckusick 
331*6702Smckusick 	IF (n=to-from)<=1 THEN return FI
332*6702Smckusick 
333*6702Smckusick 	FOR j=1; j<=n; j*=2 DONE
334*6702Smckusick 
335*6702Smckusick 	FOR m=2*j-1; m/=2;
336*6702Smckusick 	DO  k=n-m;
337*6702Smckusick 	    FOR j=0; j<k; j++
338*6702Smckusick 	    DO	FOR i=j; i>=0; i-=m
339*6702Smckusick 		DO  REG STRING *fromi; fromi = &from[i];
340*6702Smckusick 		    IF cf(fromi[m],fromi[0])>0
341*6702Smckusick 		    THEN break;
342*6702Smckusick 		    ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
343*6702Smckusick 		    FI
344*6702Smckusick 		OD
345*6702Smckusick 	    OD
346*6702Smckusick 	OD
347*6702Smckusick }
348*6702Smckusick 
349*6702Smckusick /* Argument list generation */
350*6702Smckusick 
351*6702Smckusick INT	getarg(ac)
352*6702Smckusick 	COMPTR		ac;
353*6702Smckusick {
354*6702Smckusick 	REG ARGPTR	argp;
355*6702Smckusick 	REG INT		count=0;
356*6702Smckusick 	REG COMPTR	c;
357*6702Smckusick 
358*6702Smckusick 	IF c=ac
359*6702Smckusick 	THEN	argp=c->comarg;
360*6702Smckusick 		WHILE argp
361*6702Smckusick 		DO	count += split(macro(argp->argval));
362*6702Smckusick 			argp=argp->argnxt;
363*6702Smckusick 		OD
364*6702Smckusick 	FI
365*6702Smckusick 	return(count);
366*6702Smckusick }
367*6702Smckusick 
368*6702Smckusick LOCAL INT	split(s)
369*6702Smckusick 	REG STRING	s;
370*6702Smckusick {
371*6702Smckusick 	REG STRING	argp;
372*6702Smckusick 	REG INT		c;
373*6702Smckusick 	INT		count=0;
374*6702Smckusick 
375*6702Smckusick 	LOOP	sigchk(); argp=locstak()+BYTESPERWORD;
376*6702Smckusick 		WHILE (c = *s++, !any(c,ifsnod.namval) && c)
377*6702Smckusick 		DO *argp++ = c OD
378*6702Smckusick 		IF argp==staktop+BYTESPERWORD
379*6702Smckusick 		THEN	IF c
380*6702Smckusick 			THEN	continue;
381*6702Smckusick 			ELSE	return(count);
382*6702Smckusick 			FI
383*6702Smckusick 		ELIF c==0
384*6702Smckusick 		THEN	s--;
385*6702Smckusick 		FI
386*6702Smckusick 		IF c=expand((argp=endstak(argp))->argval,0)
387*6702Smckusick 		THEN	count += c;
388*6702Smckusick 		ELSE	/* assign(&fngnod, argp->argval); */
389*6702Smckusick 			makearg(argp); count++;
390*6702Smckusick 		FI
391*6702Smckusick 		Lcheat(gchain) |= ARGMK;
392*6702Smckusick 	POOL
393*6702Smckusick }
394