xref: /csrg-svn/old/sh/xec.c (revision 6710)
1*6710Smckusick /*	xec.c	4.1	82/05/07	*/
2*6710Smckusick 
3*6710Smckusick #
4*6710Smckusick /*
5*6710Smckusick  * UNIX shell
6*6710Smckusick  *
7*6710Smckusick  * S. R. Bourne
8*6710Smckusick  * Bell Telephone Laboratories
9*6710Smckusick  *
10*6710Smckusick  */
11*6710Smckusick 
12*6710Smckusick #include	"defs.h"
13*6710Smckusick #include	"sym.h"
14*6710Smckusick 
15*6710Smckusick LOCAL INT	parent;
16*6710Smckusick 
17*6710Smckusick SYSTAB		commands;
18*6710Smckusick 
19*6710Smckusick 
20*6710Smckusick 
21*6710Smckusick /* ========	command execution	========*/
22*6710Smckusick 
23*6710Smckusick 
24*6710Smckusick execute(argt, execflg, pf1, pf2)
25*6710Smckusick 	TREPTR		argt;
26*6710Smckusick 	INT		*pf1, *pf2;
27*6710Smckusick {
28*6710Smckusick 	/* `stakbot' is preserved by this routine */
29*6710Smckusick 	REG TREPTR	t;
30*6710Smckusick 	STKPTR		sav=savstak();
31*6710Smckusick 
32*6710Smckusick 	sigchk();
33*6710Smckusick 
34*6710Smckusick 	IF (t=argt) ANDF execbrk==0
35*6710Smckusick 	THEN	REG INT		treeflgs;
36*6710Smckusick 		INT		oldexit, type;
37*6710Smckusick 		REG STRING	*com;
38*6710Smckusick 
39*6710Smckusick 		treeflgs = t->tretyp; type = treeflgs&COMMSK;
40*6710Smckusick 		oldexit=exitval; exitval=0;
41*6710Smckusick 
42*6710Smckusick 		SWITCH type IN
43*6710Smckusick 
44*6710Smckusick 		case TCOM:
45*6710Smckusick 			BEGIN
46*6710Smckusick 			STRING		a1;
47*6710Smckusick 			INT		argn, internal;
48*6710Smckusick 			ARGPTR		schain=gchain;
49*6710Smckusick 			IOPTR		io=t->treio;
50*6710Smckusick 			gchain=0;
51*6710Smckusick 			argn = getarg(t);
52*6710Smckusick 			com=scan(argn);
53*6710Smckusick 			a1=com[1]; gchain=schain;
54*6710Smckusick 
55*6710Smckusick 			IF (internal=syslook(com[0],commands)) ORF argn==0
56*6710Smckusick 			THEN	setlist(t->comset, 0);
57*6710Smckusick 			FI
58*6710Smckusick 
59*6710Smckusick 			IF argn ANDF (flags&noexec)==0
60*6710Smckusick 			THEN	/* print command if execpr */
61*6710Smckusick 				IF flags&execpr
62*6710Smckusick 				THEN	argn=0;	prs(execpmsg);
63*6710Smckusick 					WHILE com[argn]!=ENDARGS
64*6710Smckusick 					DO prs(com[argn++]); blank() OD
65*6710Smckusick 					newline();
66*6710Smckusick 				FI
67*6710Smckusick 
68*6710Smckusick 				SWITCH internal IN
69*6710Smckusick 
70*6710Smckusick 				case SYSDOT:
71*6710Smckusick 					IF a1
72*6710Smckusick 					THEN	REG INT		f;
73*6710Smckusick 
74*6710Smckusick 						IF (f=pathopen(getpath(a1), a1)) < 0
75*6710Smckusick 						THEN failed(a1,notfound);
76*6710Smckusick 						ELSE execexp(0,f);
77*6710Smckusick 						FI
78*6710Smckusick 					FI
79*6710Smckusick 					break;
80*6710Smckusick 
81*6710Smckusick 				case SYSTIMES:
82*6710Smckusick 					{
83*6710Smckusick 					L_INT	t[4]; times(t);
84*6710Smckusick 					prt(t[2]); blank(); prt(t[3]); newline();
85*6710Smckusick 					}
86*6710Smckusick 					break;
87*6710Smckusick 
88*6710Smckusick 				case SYSEXIT:
89*6710Smckusick 					exitsh(a1?stoi(a1):oldexit);
90*6710Smckusick 
91*6710Smckusick 				case SYSNULL:
92*6710Smckusick 					io=0;
93*6710Smckusick 					break;
94*6710Smckusick 
95*6710Smckusick 				case SYSCONT:
96*6710Smckusick 					execbrk = -loopcnt; break;
97*6710Smckusick 
98*6710Smckusick 				case SYSBREAK:
99*6710Smckusick 					IF (execbrk=loopcnt) ANDF a1
100*6710Smckusick 					THEN breakcnt=stoi(a1);
101*6710Smckusick 					FI
102*6710Smckusick 					break;
103*6710Smckusick 
104*6710Smckusick 				case SYSTRAP:
105*6710Smckusick 					IF a1
106*6710Smckusick 					THEN	BOOL	clear;
107*6710Smckusick 						IF (clear=digit(*a1))==0
108*6710Smckusick 						THEN	++com;
109*6710Smckusick 						FI
110*6710Smckusick 						WHILE *++com
111*6710Smckusick 						DO INT	i;
112*6710Smckusick 						   IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP
113*6710Smckusick 						   THEN	failed(*com,badtrap);
114*6710Smckusick 						   ELIF clear
115*6710Smckusick 						   THEN	clrsig(i);
116*6710Smckusick 						   ELSE	replace(&trapcom[i],a1);
117*6710Smckusick 							IF *a1
118*6710Smckusick 							THEN	getsig(i);
119*6710Smckusick 							ELSE	ignsig(i);
120*6710Smckusick 							FI
121*6710Smckusick 						   FI
122*6710Smckusick 						OD
123*6710Smckusick 					ELSE	/* print out current traps */
124*6710Smckusick 						INT		i;
125*6710Smckusick 
126*6710Smckusick 						FOR i=0; i<MAXTRAP; i++
127*6710Smckusick 						DO IF trapcom[i]
128*6710Smckusick 						   THEN	prn(i); prs(colon); prs(trapcom[i]); newline();
129*6710Smckusick 						   FI
130*6710Smckusick 						OD
131*6710Smckusick 					FI
132*6710Smckusick 					break;
133*6710Smckusick 
134*6710Smckusick 				case SYSEXEC:
135*6710Smckusick 					com++;
136*6710Smckusick 					initio(io); ioset=0; io=0;
137*6710Smckusick 					IF a1==0 THEN break FI
138*6710Smckusick 
139*6710Smckusick 				case SYSLOGIN:
140*6710Smckusick 					flags |= forked;
141*6710Smckusick 					oldsigs(); execa(com); done();
142*6710Smckusick 
143*6710Smckusick 				case SYSCD:
144*6710Smckusick 					IF flags&rshflg
145*6710Smckusick 					THEN	failed(com[0],restricted);
146*6710Smckusick 					ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0
147*6710Smckusick 					THEN	failed(a1,baddir);
148*6710Smckusick 					FI
149*6710Smckusick 					break;
150*6710Smckusick 
151*6710Smckusick 				case SYSSHFT:
152*6710Smckusick 					IF dolc<1
153*6710Smckusick 					THEN	error(badshift);
154*6710Smckusick 					ELSE	dolv++; dolc--;
155*6710Smckusick 					FI
156*6710Smckusick 					assnum(&dolladr, dolc);
157*6710Smckusick 					break;
158*6710Smckusick 
159*6710Smckusick 				case SYSWAIT:
160*6710Smckusick 					await(-1);
161*6710Smckusick 					break;
162*6710Smckusick 
163*6710Smckusick 				case SYSREAD:
164*6710Smckusick 					exitval=readvar(&com[1]);
165*6710Smckusick 					break;
166*6710Smckusick 
167*6710Smckusick /*
168*6710Smckusick 				case SYSTST:
169*6710Smckusick 					exitval=testcmd(com);
170*6710Smckusick 					break;
171*6710Smckusick */
172*6710Smckusick 
173*6710Smckusick 				case SYSSET:
174*6710Smckusick 					IF a1
175*6710Smckusick 					THEN	INT	argc;
176*6710Smckusick 						argc = options(argn,com);
177*6710Smckusick 						IF argc>1
178*6710Smckusick 						THEN	setargs(com+argn-argc);
179*6710Smckusick 						FI
180*6710Smckusick 					ELIF t->comset==0
181*6710Smckusick 					THEN	/*scan name chain and print*/
182*6710Smckusick 						namscan(printnam);
183*6710Smckusick 					FI
184*6710Smckusick 					break;
185*6710Smckusick 
186*6710Smckusick 				case SYSRDONLY:
187*6710Smckusick 					exitval=N_RDONLY;
188*6710Smckusick 				case SYSXPORT:
189*6710Smckusick 					IF exitval==0 THEN exitval=N_EXPORT; FI
190*6710Smckusick 
191*6710Smckusick 					IF a1
192*6710Smckusick 					THEN	WHILE *++com
193*6710Smckusick 						DO attrib(lookup(*com), exitval) OD
194*6710Smckusick 					ELSE	namscan(printflg);
195*6710Smckusick 					FI
196*6710Smckusick 					exitval=0;
197*6710Smckusick 					break;
198*6710Smckusick 
199*6710Smckusick 				case SYSEVAL:
200*6710Smckusick 					IF a1
201*6710Smckusick 					THEN	execexp(a1,&com[2]);
202*6710Smckusick 					FI
203*6710Smckusick 					break;
204*6710Smckusick 
205*6710Smckusick                                 case SYSUMASK:
206*6710Smckusick                                         if (a1) {
207*6710Smckusick                                                 int c, i
208*6710Smckusick                                                 i = 0;
209*6710Smckusick                                                 while ((c = *a1++) >= '0' &&
210*6710Smckusick                                                         c <= '7')
211*6710Smckusick                                                         i = (i << 3) + c - '0';
212*6710Smckusick                                                 umask(i);
213*6710Smckusick                                         } else {
214*6710Smckusick                                                 int i, j;
215*6710Smckusick                                                 umask(i = umask(0));
216*6710Smckusick                                                 prc('0');
217*6710Smckusick                                                 for (j = 6; j >= 0; j -= 3)
218*6710Smckusick                                                         prc(((i>>j)&07) + '0');
219*6710Smckusick                                                 newline();
220*6710Smckusick                                         }
221*6710Smckusick                                         break;
222*6710Smckusick 
223*6710Smckusick 				default:
224*6710Smckusick 					internal=builtin(argn,com);
225*6710Smckusick 
226*6710Smckusick 				ENDSW
227*6710Smckusick 
228*6710Smckusick 				IF internal
229*6710Smckusick 				THEN	IF io THEN error(illegal) FI
230*6710Smckusick 					chktrap();
231*6710Smckusick 					break;
232*6710Smckusick 				FI
233*6710Smckusick 			ELIF t->treio==0
234*6710Smckusick 			THEN	break;
235*6710Smckusick 			FI
236*6710Smckusick 			END
237*6710Smckusick 
238*6710Smckusick 		case TFORK:
239*6710Smckusick 			IF execflg ANDF (treeflgs&(FAMP|FPOU))==0
240*6710Smckusick 			THEN	parent=0;
241*6710Smckusick 			ELSE	WHILE (parent=fork()) == -1
242*6710Smckusick 				DO sigchk(); alarm(10); pause() OD
243*6710Smckusick 			FI
244*6710Smckusick 
245*6710Smckusick 			IF parent
246*6710Smckusick 			THEN	/* This is the parent branch of fork;    */
247*6710Smckusick 				/* it may or may not wait for the child. */
248*6710Smckusick 				IF treeflgs&FPRS ANDF flags&ttyflg
249*6710Smckusick 				THEN	prn(parent); newline();
250*6710Smckusick 				FI
251*6710Smckusick 				IF treeflgs&FPCL THEN closepipe(pf1) FI
252*6710Smckusick 				IF (treeflgs&(FAMP|FPOU))==0
253*6710Smckusick 				THEN	await(parent);
254*6710Smckusick 				ELIF (treeflgs&FAMP)==0
255*6710Smckusick 				THEN	post(parent);
256*6710Smckusick 				ELSE	assnum(&pcsadr, parent);
257*6710Smckusick 				FI
258*6710Smckusick 
259*6710Smckusick 				chktrap();
260*6710Smckusick 				break;
261*6710Smckusick 
262*6710Smckusick 
263*6710Smckusick 			ELSE	/* this is the forked branch (child) of execute */
264*6710Smckusick 				flags |= forked; iotemp=0;
265*6710Smckusick 				postclr();
266*6710Smckusick 				settmp();
267*6710Smckusick 
268*6710Smckusick 				/* Turn off INTR and QUIT if `FINT'  */
269*6710Smckusick 				/* Reset ramaining signals to parent */
270*6710Smckusick 				/* except for those `lost' by trap   */
271*6710Smckusick 				oldsigs();
272*6710Smckusick 				IF treeflgs&FINT
273*6710Smckusick 				THEN	signal(INTR,1); signal(QUIT,1);
274*6710Smckusick 				FI
275*6710Smckusick 
276*6710Smckusick 				/* pipe in or out */
277*6710Smckusick 				IF treeflgs&FPIN
278*6710Smckusick 				THEN	rename(pf1[INPIPE],0);
279*6710Smckusick 					close(pf1[OTPIPE]);
280*6710Smckusick 				FI
281*6710Smckusick 				IF treeflgs&FPOU
282*6710Smckusick 				THEN	rename(pf2[OTPIPE],1);
283*6710Smckusick 					close(pf2[INPIPE]);
284*6710Smckusick 				FI
285*6710Smckusick 
286*6710Smckusick 				/* default std input for & */
287*6710Smckusick 				IF treeflgs&FINT ANDF ioset==0
288*6710Smckusick 				THEN	rename(chkopen(devnull),0);
289*6710Smckusick 				FI
290*6710Smckusick 
291*6710Smckusick 				/* io redirection */
292*6710Smckusick 				initio(t->treio);
293*6710Smckusick 				IF type!=TCOM
294*6710Smckusick 				THEN	execute(t->forktre,1);
295*6710Smckusick 				ELIF com[0]!=ENDARGS
296*6710Smckusick 				THEN	setlist(t->comset,N_EXPORT);
297*6710Smckusick 					execa(com);
298*6710Smckusick 				FI
299*6710Smckusick 				done();
300*6710Smckusick 			FI
301*6710Smckusick 
302*6710Smckusick 		case TPAR:
303*6710Smckusick 			rename(dup(2),output);
304*6710Smckusick 			execute(t->partre,execflg);
305*6710Smckusick 			done();
306*6710Smckusick 
307*6710Smckusick 		case TFIL:
308*6710Smckusick 			BEGIN
309*6710Smckusick 			   INT pv[2]; chkpipe(pv);
310*6710Smckusick 			   IF execute(t->lstlef, 0, pf1, pv)==0
311*6710Smckusick 			   THEN	execute(t->lstrit, execflg, pv, pf2);
312*6710Smckusick 			   ELSE	closepipe(pv);
313*6710Smckusick 			   FI
314*6710Smckusick 			END
315*6710Smckusick 			break;
316*6710Smckusick 
317*6710Smckusick 		case TLST:
318*6710Smckusick 			execute(t->lstlef,0);
319*6710Smckusick 			execute(t->lstrit,execflg);
320*6710Smckusick 			break;
321*6710Smckusick 
322*6710Smckusick 		case TAND:
323*6710Smckusick 			IF execute(t->lstlef,0)==0
324*6710Smckusick 			THEN	execute(t->lstrit,execflg);
325*6710Smckusick 			FI
326*6710Smckusick 			break;
327*6710Smckusick 
328*6710Smckusick 		case TORF:
329*6710Smckusick 			IF execute(t->lstlef,0)!=0
330*6710Smckusick 			THEN	execute(t->lstrit,execflg);
331*6710Smckusick 			FI
332*6710Smckusick 			break;
333*6710Smckusick 
334*6710Smckusick 		case TFOR:
335*6710Smckusick 			BEGIN
336*6710Smckusick 			   NAMPTR	n = lookup(t->fornam);
337*6710Smckusick 			   STRING	*args;
338*6710Smckusick 			   DOLPTR	argsav=0;
339*6710Smckusick 
340*6710Smckusick 			   IF t->forlst==0
341*6710Smckusick 			   THEN    args=dolv+1;
342*6710Smckusick 				   argsav=useargs();
343*6710Smckusick 			   ELSE	   ARGPTR	schain=gchain;
344*6710Smckusick 				   gchain=0;
345*6710Smckusick 				   trim((args=scan(getarg(t->forlst)))[0]);
346*6710Smckusick 				   gchain=schain;
347*6710Smckusick 			   FI
348*6710Smckusick 			   loopcnt++;
349*6710Smckusick 			   WHILE *args!=ENDARGS ANDF execbrk==0
350*6710Smckusick 			   DO	assign(n,*args++);
351*6710Smckusick 				execute(t->fortre,0);
352*6710Smckusick 				IF execbrk<0 THEN execbrk=0 FI
353*6710Smckusick 			   OD
354*6710Smckusick 			   IF breakcnt THEN breakcnt-- FI
355*6710Smckusick 			   execbrk=breakcnt; loopcnt--;
356*6710Smckusick 			   argfor=freeargs(argsav);
357*6710Smckusick 			END
358*6710Smckusick 			break;
359*6710Smckusick 
360*6710Smckusick 		case TWH:
361*6710Smckusick 		case TUN:
362*6710Smckusick 			BEGIN
363*6710Smckusick 			   INT		i=0;
364*6710Smckusick 
365*6710Smckusick 			   loopcnt++;
366*6710Smckusick 			   WHILE execbrk==0 ANDF (execute(t->whtre,0)==0)==(type==TWH)
367*6710Smckusick 			   DO i=execute(t->dotre,0);
368*6710Smckusick 			      IF execbrk<0 THEN execbrk=0 FI
369*6710Smckusick 			   OD
370*6710Smckusick 			   IF breakcnt THEN breakcnt-- FI
371*6710Smckusick 			   execbrk=breakcnt; loopcnt--; exitval=i;
372*6710Smckusick 			END
373*6710Smckusick 			break;
374*6710Smckusick 
375*6710Smckusick 		case TIF:
376*6710Smckusick 			IF execute(t->iftre,0)==0
377*6710Smckusick 			THEN	execute(t->thtre,execflg);
378*6710Smckusick 			ELSE	execute(t->eltre,execflg);
379*6710Smckusick 			FI
380*6710Smckusick 			break;
381*6710Smckusick 
382*6710Smckusick 		case TSW:
383*6710Smckusick 			BEGIN
384*6710Smckusick 			   REG STRING	r = mactrim(t->swarg);
385*6710Smckusick 			   t=t->swlst;
386*6710Smckusick 			   WHILE t
387*6710Smckusick 			   DO	ARGPTR		rex=t->regptr;
388*6710Smckusick 				WHILE rex
389*6710Smckusick 				DO	REG STRING	s;
390*6710Smckusick 					IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s))
391*6710Smckusick 					THEN	execute(t->regcom,0);
392*6710Smckusick 						t=0; break;
393*6710Smckusick 					ELSE	rex=rex->argnxt;
394*6710Smckusick 					FI
395*6710Smckusick 				OD
396*6710Smckusick 				IF t THEN t=t->regnxt FI
397*6710Smckusick 			   OD
398*6710Smckusick 			END
399*6710Smckusick 			break;
400*6710Smckusick 		ENDSW
401*6710Smckusick 		exitset();
402*6710Smckusick 	FI
403*6710Smckusick 
404*6710Smckusick 	sigchk();
405*6710Smckusick 	tdystak(sav);
406*6710Smckusick 	return(exitval);
407*6710Smckusick }
408*6710Smckusick 
409*6710Smckusick 
410*6710Smckusick execexp(s,f)
411*6710Smckusick 	STRING		s;
412*6710Smckusick 	UFD		f;
413*6710Smckusick {
414*6710Smckusick 	FILEBLK		fb;
415*6710Smckusick 	push(&fb);
416*6710Smckusick 	IF s
417*6710Smckusick 	THEN	estabf(s); fb.feval=f;
418*6710Smckusick 	ELIF f>=0
419*6710Smckusick 	THEN	initf(f);
420*6710Smckusick 	FI
421*6710Smckusick 	execute(cmd(NL, NLFLG|MTFLG),0);
422*6710Smckusick 	pop();
423*6710Smckusick }
424