xref: /csrg-svn/local/toolchest/ksh/sh/xec.c (revision 35176)
1*35176Smarc /*
2*35176Smarc 
3*35176Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35176Smarc  *      All Rights Reserved
5*35176Smarc 
6*35176Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35176Smarc  *      CODE OF AT&T.
8*35176Smarc  *      The copyright notice above does not
9*35176Smarc  *      evidence any actual or intended
10*35176Smarc  *      publication of such source code.
11*35176Smarc 
12*35176Smarc  */
13*35176Smarc /* @(#)xec.c	1.1 */
14*35176Smarc /*
15*35176Smarc  * UNIX shell
16*35176Smarc  *
17*35176Smarc  * S. R. Bourne
18*35176Smarc  * Rewritten by David Korn
19*35176Smarc  * AT&T Bell Laboratories
20*35176Smarc  *
21*35176Smarc  */
22*35176Smarc 
23*35176Smarc #include	<sys/types.h>
24*35176Smarc #include	<sys/times.h>
25*35176Smarc #include	<errno.h>
26*35176Smarc #ifdef SXT
27*35176Smarc #include	<sys/tty.h>
28*35176Smarc #include	<sys/sxt.h>
29*35176Smarc #endif	/* SXT */
30*35176Smarc #include	"defs.h"
31*35176Smarc #include	"sym.h"
32*35176Smarc #include	"mode.h"
33*35176Smarc #include	"flags.h"
34*35176Smarc #include	"name.h"
35*35176Smarc #include	"brkincr.h"
36*35176Smarc #include	"stak.h"
37*35176Smarc #include	"builtins.h"
38*35176Smarc #include	"shtype.h"
39*35176Smarc #include	"jobs.h"
40*35176Smarc #include	"io.h"
41*35176Smarc #ifdef BSD
42*35176Smarc #define TIC_SEC		60
43*35176Smarc #include	<sys/timeb.h>
44*35176Smarc #endif	/* BSD */
45*35176Smarc 
46*35176Smarc /* These routines are defined by this module */
47*35176Smarc int execute();
48*35176Smarc void trace_command();
49*35176Smarc 
50*35176Smarc /* These routines are referenced by this module */
51*35176Smarc extern char	**arg_build();
52*35176Smarc extern DOLPTR	arg_use();
53*35176Smarc extern DOLPTR	arg_free();
54*35176Smarc extern void	assign();
55*35176Smarc extern void	await();
56*35176Smarc extern FILE	*chkopen();
57*35176Smarc extern void	builtin();
58*35176Smarc extern void	chktrap();
59*35176Smarc extern void	chkpipe();
60*35176Smarc extern void	done();
61*35176Smarc extern void	execa();
62*35176Smarc extern void	exfunct();
63*35176Smarc extern void	exitsh();
64*35176Smarc extern void	failed();
65*35176Smarc extern void	free();
66*35176Smarc extern NAMPTR	findnod();
67*35176Smarc extern char	*getpath();
68*35176Smarc extern char	*heap();
69*35176Smarc extern char	*itos();
70*35176Smarc extern NAMPTR	lookup();
71*35176Smarc extern char	*macro();
72*35176Smarc extern char	*mactrim();
73*35176Smarc extern void	mem_scope();
74*35176Smarc extern void	mem_unscope();
75*35176Smarc extern char	*movstr();
76*35176Smarc extern char	*malloc();
77*35176Smarc extern void	oldsigs();
78*35176Smarc extern void	p_sub();
79*35176Smarc extern void	p_num();
80*35176Smarc extern void	p_str();
81*35176Smarc extern void	p_time();
82*35176Smarc extern void	p_flush();
83*35176Smarc extern void	p_setout();
84*35176Smarc extern void	p_list();
85*35176Smarc extern void	pipe_close();
86*35176Smarc extern void	postclr();
87*35176Smarc extern char	*qvalup();
88*35176Smarc extern void	restore();
89*35176Smarc extern void	rmtemp();
90*35176Smarc extern char	*strcpy();
91*35176Smarc extern void	setlist();
92*35176Smarc extern void	swap_iodoc_nm();
93*35176Smarc extern void	sync_io();
94*35176Smarc extern void	tdystak();
95*35176Smarc extern long	times();
96*35176Smarc #ifdef DEVFD
97*35176Smarc extern void	close_pipes();
98*35176Smarc #endif	/* DEVFD */
99*35176Smarc #ifdef VFORK
100*35176Smarc extern int	vfork_check();
101*35176Smarc extern int	vfork_save();
102*35176Smarc extern void	vfork_restore();
103*35176Smarc #endif	/* VFORK */
104*35176Smarc 
105*35176Smarc static int trim_eq();
106*35176Smarc static char locbuf[TMPSIZ]; 	/* store last argument here if it fits */
107*35176Smarc 
108*35176Smarc 
109*35176Smarc /* ========	command execution	========*/
110*35176Smarc 
111*35176Smarc 
112*35176Smarc /* VARARGS */
execute(argt,execflg,apf1,apf2)113*35176Smarc execute(argt, execflg, apf1, apf2)
114*35176Smarc TREPTR 	argt;
115*35176Smarc unsigned execflg;
116*35176Smarc FILE	*apf1[],*apf2[];
117*35176Smarc {
118*35176Smarc 	/* `stakbot' is preserved by this routine */
119*35176Smarc 	register TREPTR t;
120*35176Smarc 	STKPTR 	sav=savstak();
121*35176Smarc 	FILE *inpipe[2],*otpipe[2];
122*35176Smarc 	FILE **pf1 = apf1;
123*35176Smarc 	FILE **pf2 = apf2;
124*35176Smarc 	unsigned errorflg = (execflg&ERRFLG);
125*35176Smarc #ifdef VFORK
126*35176Smarc 	int v_fork;
127*35176Smarc #endif	/* VFORK */
128*35176Smarc 	if(trapnote&SIGSET)
129*35176Smarc 		exitsh(SIGFAIL);
130*35176Smarc 	if(errorflg==0)
131*35176Smarc 		states &= ~ERRFLG;
132*35176Smarc 	if((t=argt) && execbrk==0)
133*35176Smarc 	{
134*35176Smarc 		register int 	type;
135*35176Smarc 		char	**com;
136*35176Smarc 		int	argn;
137*35176Smarc 		char *com0 = NIL;
138*35176Smarc 		type = t->tretyp;
139*35176Smarc 		oldexit=exitval;
140*35176Smarc 		exitval=0;
141*35176Smarc 		switch(type&COMMSK)
142*35176Smarc 		{
143*35176Smarc 			case TCOM:
144*35176Smarc 			{
145*35176Smarc 				register IOPTR		io;
146*35176Smarc 				register ARGPTR		argp;
147*35176Smarc 				NAMPTR np;
148*35176Smarc 				type >>= (COMBITS+1);
149*35176Smarc 				cmdline = ((COMPTR)t)->comline;
150*35176Smarc 				com = arg_build(&argn,((COMPTR)t));
151*35176Smarc 				if(t->tretyp&COMSCAN)
152*35176Smarc 				{
153*35176Smarc 					argp = ((COMPTR)t)->comarg;
154*35176Smarc 					if(argp && (argp->argflag&A_RAW)==0)
155*35176Smarc 						type = syslook(com[0],commands);
156*35176Smarc 					if(trapnote&SIGSET)
157*35176Smarc 						exitsh(SIGFAIL);
158*35176Smarc 				}
159*35176Smarc 				com0 = com[0];
160*35176Smarc 				argp = ((COMPTR)t)->comset;
161*35176Smarc 				io = t->treio;
162*35176Smarc 				if(argn==0 || (type>0 && type<=SYSSPECIAL))
163*35176Smarc 				{
164*35176Smarc 					setlist(argp, 0);
165*35176Smarc 					argp = NULL;
166*35176Smarc 				}
167*35176Smarc 				if((io||argn) && is_option(NOEXEC)==0)
168*35176Smarc 					/* print command if EXECPR */
169*35176Smarc 				{
170*35176Smarc 					if(argn==0)
171*35176Smarc 					{
172*35176Smarc 						/* fake a built-in */
173*35176Smarc 						argn=1;
174*35176Smarc 						type = SYSMAX;
175*35176Smarc 					}
176*35176Smarc 					/* set +x doesn't echo */
177*35176Smarc 					else if(type!=SYSSET)
178*35176Smarc 					{
179*35176Smarc 						trace_command(com);
180*35176Smarc 					}
181*35176Smarc 					if(io)
182*35176Smarc 						p_flush();
183*35176Smarc #ifdef apollo
184*35176Smarc 					if(is_option(INPROC) &&  type==0
185*35176Smarc 						&& (states&FORKED)==0 &&
186*35176Smarc 						!findnod(com0,prnames,CHK_FOR))
187*35176Smarc 					{
188*35176Smarc 						type = SYSINPROCESS;
189*35176Smarc 						com--;
190*35176Smarc 						argn++;
191*35176Smarc 					}
192*35176Smarc #endif	/* apollo */
193*35176Smarc 					/* check for builtins */
194*35176Smarc 					if(type)
195*35176Smarc 					{
196*35176Smarc 						/* failures on built-ins not fatal */
197*35176Smarc 						jmp_buf retbuf;
198*35176Smarc 						jmp_buf *savreturn = freturn;
199*35176Smarc 						int indx = topfd;
200*35176Smarc 						int scope=0;
201*35176Smarc 						if(type>=SYSNULL)
202*35176Smarc 							freturn = (jmp_buf*)retbuf;
203*35176Smarc 						if(setjmp(retbuf) == 0)
204*35176Smarc 						{
205*35176Smarc 							int flag = 1;
206*35176Smarc 							if(type>=SYSNULL)
207*35176Smarc 								states |= BUILTIN;
208*35176Smarc 							else
209*35176Smarc 							{
210*35176Smarc 								flag = (type!=SYSLOGIN);
211*35176Smarc 								if(type==SYSEXEC)
212*35176Smarc 									flag = -(com[1]==0);
213*35176Smarc 							}
214*35176Smarc 							indx = initio(io,flag);
215*35176Smarc 							if(argp)
216*35176Smarc 							{
217*35176Smarc 								mem_scope(argp);
218*35176Smarc 								scope++;
219*35176Smarc 							}
220*35176Smarc 							builtin(type,argn,com,t);
221*35176Smarc 						}
222*35176Smarc 						states &= ~BUILTIN;
223*35176Smarc 						freturn = savreturn;
224*35176Smarc 						if(scope)
225*35176Smarc 							mem_unscope();
226*35176Smarc 						restore(indx);
227*35176Smarc 						goto setexit;
228*35176Smarc 					}
229*35176Smarc 					/* check for functions */
230*35176Smarc 					if((np=findnod(com0,prnames,CHK_FOR))
231*35176Smarc 							 && np->value.namval.ip)
232*35176Smarc 					{
233*35176Smarc 						int indx;
234*35176Smarc 						indx = initio(io,1);
235*35176Smarc 						exfunct((TREPTR)(*funtree(np))
236*35176Smarc 							,com
237*35176Smarc 							,execflg|(attest(np,T_FLAG)?EXECPR:0)
238*35176Smarc 							,((COMPTR)t)->comset);
239*35176Smarc 						restore(indx);
240*35176Smarc 						goto setexit;
241*35176Smarc 					}
242*35176Smarc 					/* track alias if possible */
243*35176Smarc 					getpath(com0);
244*35176Smarc 				}
245*35176Smarc 				else if(io==0)
246*35176Smarc 				{
247*35176Smarc 				setexit:
248*35176Smarc 					exitset();
249*35176Smarc 					chktrap();
250*35176Smarc 					break;
251*35176Smarc 				}
252*35176Smarc 				type = TCOM;
253*35176Smarc 			}
254*35176Smarc 			case TFORK:
255*35176Smarc 			{
256*35176Smarc 				int no_fork;
257*35176Smarc 				sync_io();
258*35176Smarc #ifdef SXT
259*35176Smarc 				/* find job number and create synchronization pipe */
260*35176Smarc 				if((jobstat.cur_job = next_job()) < jobstat.maxjob)
261*35176Smarc 					if(pipe(jobstat.pipe)<0)
262*35176Smarc 						jobstat.maxjob = 0;
263*35176Smarc #endif	/* SXT */
264*35176Smarc 				no_fork = (execflg&1) && (type&(FAMP|FPOU))==0;
265*35176Smarc 				if(no_fork)
266*35176Smarc 					parent=0;
267*35176Smarc 				else
268*35176Smarc 				/* FORKLIM is the max period between forks -
269*35176Smarc 					power of 2 usually.  Currently shell tries after
270*35176Smarc 					2,4,8,16, and 32 seconds and then quits */
271*35176Smarc 				{
272*35176Smarc 					register int forkcnt=1;
273*35176Smarc 					if(type&FTMP)
274*35176Smarc 					{
275*35176Smarc 						link_iodocs(iotemp);
276*35176Smarc 						linked = 1;
277*35176Smarc 					}
278*35176Smarc 					if((type&(FPCL|FPIN|FPOU)) == (FPIN|FPOU))
279*35176Smarc 					/* set up pipe for cooperating process */
280*35176Smarc 					{
281*35176Smarc 						if(cpid)
282*35176Smarc 							failed(cmdadr,pexists);
283*35176Smarc 						chkpipe(pf2=otpipe);
284*35176Smarc 						cpipe[INPIPE] = frenumber(pf2[INPIPE],CINPIPE);
285*35176Smarc 						chkpipe(pf1=inpipe);
286*35176Smarc 						cpipe[OTPIPE] = frenumber(pf1[OTPIPE],COTPIPE);
287*35176Smarc 					}
288*35176Smarc #ifdef VFORK
289*35176Smarc 					if(v_fork=vfork_check(t))
290*35176Smarc 						vfork_save();
291*35176Smarc 					while((parent=(v_fork?vfork():fork())) == -1)
292*35176Smarc #else
293*35176Smarc 					while((parent=fork()) == -1)
294*35176Smarc #endif	/* VFORK */
295*35176Smarc 					{
296*35176Smarc 						if((forkcnt *= 2) > FORKLIM)
297*35176Smarc 						{
298*35176Smarc 							switch(errno)
299*35176Smarc 							{
300*35176Smarc 								case ENOMEM:
301*35176Smarc 									error(noswap);
302*35176Smarc 									 break;
303*35176Smarc 								default:
304*35176Smarc 								case EAGAIN:
305*35176Smarc 									error(nofork);
306*35176Smarc 									break;
307*35176Smarc 							}
308*35176Smarc 						}
309*35176Smarc 						if(trapnote&SIGSET)
310*35176Smarc 							exitsh(SIGFAIL);
311*35176Smarc 						alarm(forkcnt);
312*35176Smarc 						pause();
313*35176Smarc 						alarm(0);
314*35176Smarc 					}
315*35176Smarc 				}
316*35176Smarc 
317*35176Smarc 				if(parent)
318*35176Smarc 					/* This is the parent branch of fork;    */
319*35176Smarc 				/* it may or may not wait for the child. */
320*35176Smarc 				{
321*35176Smarc 					register int pno;
322*35176Smarc #ifdef VFORK
323*35176Smarc 					if(v_fork)
324*35176Smarc 						vfork_restore();
325*35176Smarc #endif	/* VFORK */
326*35176Smarc #ifdef JOBS
327*35176Smarc # ifdef SXT
328*35176Smarc 					if(jobstat.pipe[1] > 0)
329*35176Smarc 						close(jobstat.pipe[1]);
330*35176Smarc # endif /* SXT */
331*35176Smarc 					/* assign each pipeline its own process group */
332*35176Smarc 					if(jobstat.j_flag==0||(states&MONITOR)==0)
333*35176Smarc 						jobstat.cur_pgrp = parent;
334*35176Smarc #endif	/* JOBS */
335*35176Smarc 					if(type&FPCL)
336*35176Smarc 						fclose(pf1[INPIPE]);
337*35176Smarc 					else if((type&FPIN)&&(type&FPOU))
338*35176Smarc 					{
339*35176Smarc 						cpid = parent;
340*35176Smarc 						fclose(pf1[INPIPE]);
341*35176Smarc 						fclose(pf2[OTPIPE]);
342*35176Smarc 					}
343*35176Smarc 					if((type&(FAMP|FPOU))==0)
344*35176Smarc 					{
345*35176Smarc #ifdef DEVFD
346*35176Smarc 						close_pipes();
347*35176Smarc #endif	/* DEVFD */
348*35176Smarc 						await(parent,0);
349*35176Smarc 					}
350*35176Smarc 					else if(type&(FPOU|FPIN))
351*35176Smarc 					{
352*35176Smarc 						int flag;
353*35176Smarc 						if(cpid==parent)
354*35176Smarc 							flag = 0;
355*35176Smarc #ifdef JOBS
356*35176Smarc 						else
357*35176Smarc 							flag = P_PIPEJOB;
358*35176Smarc 						pno = post(parent,flag);
359*35176Smarc #else
360*35176Smarc 						pno = post(parent);
361*35176Smarc #endif	/* JOBS */
362*35176Smarc 					}
363*35176Smarc 					else
364*35176Smarc 					{
365*35176Smarc #ifdef JOBS
366*35176Smarc 						pno = post(parent,0);
367*35176Smarc #else
368*35176Smarc 						pno = post(parent);
369*35176Smarc #endif
370*35176Smarc 						movstr(itos(parent),pcsadr);
371*35176Smarc 					}
372*35176Smarc 					if((type&FPRS) && (states&TTYFLG))
373*35176Smarc 					{
374*35176Smarc 						p_setout(stderr);
375*35176Smarc #ifdef JOBS
376*35176Smarc 						/* print job number */
377*35176Smarc 						p_sub(pno,'\t');
378*35176Smarc #endif	/* JOBS */
379*35176Smarc 						p_num(parent,NL);
380*35176Smarc 					}
381*35176Smarc 					chktrap();
382*35176Smarc 					break;
383*35176Smarc 				}
384*35176Smarc 
385*35176Smarc 				else
386*35176Smarc 				/*
387*35176Smarc 				 * this is the FORKED branch (child) of execute
388*35176Smarc 				 */
389*35176Smarc 				{
390*35176Smarc 					if(standout != stdout)
391*35176Smarc 						standout = frenumber(standout,1);
392*35176Smarc 					states |= FORKED;
393*35176Smarc 					off_option(HASHALL);
394*35176Smarc 					if(no_fork==0)
395*35176Smarc 					{
396*35176Smarc 						states &= ~(RM_TMP|IS_TMP);
397*35176Smarc 						states |= NO_TMP;
398*35176Smarc 						if(linked == 1)
399*35176Smarc 						{
400*35176Smarc 							swap_iodoc_nm(iotemp);
401*35176Smarc 							linked = 2;
402*35176Smarc 						}
403*35176Smarc 						else
404*35176Smarc 							iotemp=0;
405*35176Smarc 					}
406*35176Smarc #ifdef ACCT
407*35176Smarc 					suspacct();
408*35176Smarc #endif	/* ACCT */
409*35176Smarc 					/* child should not unlink the tmpfile */
410*35176Smarc 					cpipe[INPIPE] = cpipe[OTPIPE] = NULL;
411*35176Smarc 					cpid = 0;
412*35176Smarc 					/* Turn off INTR and QUIT if `FINT'  */
413*35176Smarc 					/* Reset remaining signals to parent */
414*35176Smarc 					/* except for those `lost' by trap   */
415*35176Smarc 					oldsigs();
416*35176Smarc #ifdef JOBS
417*35176Smarc 					if(states&MONITOR)
418*35176Smarc 					{
419*35176Smarc # ifdef BSD
420*35176Smarc 						register int pid = getpid();
421*35176Smarc 						int pgrp;
422*35176Smarc 						if(jobstat.j_flag==0)
423*35176Smarc 							pgrp = pid;
424*35176Smarc 						else
425*35176Smarc 							pgrp = jobstat.cur_pgrp;
426*35176Smarc 						setpgrp(pid,pgrp);
427*35176Smarc 						if(states&NONSTOP)
428*35176Smarc 							signal(SIGTSTP,SIG_IGN);
429*35176Smarc 						else
430*35176Smarc 						{
431*35176Smarc 							signal(SIGTTIN,SIG_DFL);
432*35176Smarc 							signal(SIGTTOU,SIG_DFL);
433*35176Smarc 							signal(SIGTSTP,SIG_DFL);
434*35176Smarc 						}
435*35176Smarc #else
436*35176Smarc # ifdef SXT
437*35176Smarc 						if(jobstat.cur_job < jobstat.maxjob
438*35176Smarc 							|| (type&FAMP))
439*35176Smarc # else
440*35176Smarc #  ifdef DEVFD
441*35176Smarc 						if((type&(FINT|FAMP))==(FINT|FAMP))
442*35176Smarc #  else
443*35176Smarc 						if(type&FAMP)
444*35176Smarc #  endif /* DEVFD */
445*35176Smarc # endif /* SXT */
446*35176Smarc 							setpgrp();
447*35176Smarc #endif	/* BSD */
448*35176Smarc 					}
449*35176Smarc 					else
450*35176Smarc #endif	/* JOBS */
451*35176Smarc 					if(type&FINT)
452*35176Smarc 					{
453*35176Smarc 						signal(SIGINT,SIG_IGN);
454*35176Smarc 						signal(SIGQUIT,SIG_IGN);
455*35176Smarc 					}
456*35176Smarc 					/* pipe in or out */
457*35176Smarc 					if((type&FAMP) && is_option(BGNICE))
458*35176Smarc 						nice(4);
459*35176Smarc #if VSH || ESH
460*35176Smarc 					if(type&(FAMP|FPOU))
461*35176Smarc 						off_option(EMACS|EDITVI|GMACS);
462*35176Smarc #endif
463*35176Smarc 					if(type&FPIN)
464*35176Smarc 					{
465*35176Smarc 						frenumber(pf1[INPIPE],0);
466*35176Smarc 						if((type&FPOU)==0)
467*35176Smarc 							fclose(pf1[OTPIPE]);
468*35176Smarc 						setbuf(stdin,NIL);
469*35176Smarc 					}
470*35176Smarc 					if(type&FPOU)
471*35176Smarc 					{
472*35176Smarc 						frenumber(pf2[OTPIPE],1);
473*35176Smarc 						pipe_close(pf2);
474*35176Smarc 					}
475*35176Smarc 					/* default std input for & */
476*35176Smarc #ifdef JOBS
477*35176Smarc # ifdef BSD
478*35176Smarc 					if((states&MONITOR) == 0)
479*35176Smarc # endif /* BSD */
480*35176Smarc # ifdef SXT
481*35176Smarc 					if((states&MONITOR)==0 ||
482*35176Smarc 						jobstat.cur_job >= jobstat.maxjob)
483*35176Smarc 				 	{
484*35176Smarc # endif /* SXT */
485*35176Smarc #endif	/* JOBS */
486*35176Smarc 						if((type&FINT) && ioset==0)
487*35176Smarc 						{
488*35176Smarc 							fclose(stdin);
489*35176Smarc 							chkopen(devnull);
490*35176Smarc 						}
491*35176Smarc 						/* io redirection */
492*35176Smarc #ifdef JOBS
493*35176Smarc # ifdef SXT
494*35176Smarc 					}
495*35176Smarc 					else
496*35176Smarc 						j_new_chan();
497*35176Smarc # endif /* SXT */
498*35176Smarc 					states &= ~MONITOR;
499*35176Smarc #endif	/* JOBS */
500*35176Smarc 					initio(t->treio,0);
501*35176Smarc 					if(type!=TCOM)
502*35176Smarc 					{
503*35176Smarc 						/* don't clear job table for out
504*35176Smarc 						   pipes so that jobs can be
505*35176Smarc 						   piped
506*35176Smarc 						 */
507*35176Smarc 						if(no_fork==0 && (type&FPOU)==0)
508*35176Smarc 							postclr();
509*35176Smarc 						execute(((FORKPTR) t)->forktre,execflg|1);
510*35176Smarc 					}
511*35176Smarc 					else if(com0!=ENDARGS)
512*35176Smarc 					{
513*35176Smarc 						off_option(ERRFLG);
514*35176Smarc 						rmtemp((IOPTR)0);
515*35176Smarc 						execa(com,((COMPTR)t)->comset);
516*35176Smarc 					}
517*35176Smarc 					done(0);
518*35176Smarc 				}
519*35176Smarc 			}
520*35176Smarc 
521*35176Smarc 			case TSETIO:
522*35176Smarc 			{
523*35176Smarc 			/*
524*35176Smarc 			 * don't create a new process, just
525*35176Smarc 			 * save and restore io-streams
526*35176Smarc 			 */
527*35176Smarc 				int indx = initio(((FORKPTR)t)->forkio,1);
528*35176Smarc 				execute(((FORKPTR)t)->forktre,execflg);
529*35176Smarc 				restore(indx);
530*35176Smarc 				break;
531*35176Smarc 			}
532*35176Smarc 
533*35176Smarc 			case TPAR:
534*35176Smarc 				execute(((PARPTR) t)->partre,execflg);
535*35176Smarc 				done(0);
536*35176Smarc 
537*35176Smarc 			case TFIL:
538*35176Smarc 			{
539*35176Smarc 			/*
540*35176Smarc 			 * This code sets up a pipe.
541*35176Smarc 			 * All elements of the pipe are started by the parent.
542*35176Smarc 			 * Only the last one is waited for.
543*35176Smarc 			 */
544*35176Smarc 				register FORKPTR tf;
545*35176Smarc 				FILE *pvo[2];	/* old pipe for multi-pipeline */
546*35176Smarc 				FILE *pvn[2];	/* set up pipe */
547*35176Smarc 				register int rc = 1;
548*35176Smarc 				do
549*35176Smarc 				{
550*35176Smarc 					/* create the pipe */
551*35176Smarc 					chkpipe(pvn);
552*35176Smarc 					tf = (FORKPTR)(((LSTPTR)t)->lstlef);
553*35176Smarc 					/* rc==0 on multi-stage pipe */
554*35176Smarc 					if(rc==0)
555*35176Smarc 						tf->forktyp |= FPCL|FPIN;
556*35176Smarc 					/* execute out part of pipe no wait */
557*35176Smarc 					rc = execute((TREPTR)tf, errorflg, pvo, pvn);
558*35176Smarc 					tf = (FORKPTR)(((LSTPTR)t)->lstrit);
559*35176Smarc 					t = tf->forktre;
560*35176Smarc 					/* save the pipe stream-ids */
561*35176Smarc 					pvo[0] = pvn[0];
562*35176Smarc 					/*close out-part of pipe as soon as possible */
563*35176Smarc 					fclose(pvn[OTPIPE]);
564*35176Smarc #ifdef JOBS
565*35176Smarc 					/* pipeline all in one process group */
566*35176Smarc 					jobstat.j_flag++;
567*35176Smarc #endif	/* JOBS */
568*35176Smarc 				}
569*35176Smarc 				/* repeat until end of pipeline */
570*35176Smarc 				while(rc==0 && tf->forkio==NULL && t->tretyp==TFIL);
571*35176Smarc 				if(rc == 0)
572*35176Smarc 					execute((TREPTR)tf, execflg,pvn,pf2);
573*35176Smarc 				else
574*35176Smarc 					/* execution failure, close pipe */
575*35176Smarc 					pipe_close(pvn);
576*35176Smarc 				break;
577*35176Smarc 			}
578*35176Smarc 
579*35176Smarc 			case TLST:
580*35176Smarc 			{
581*35176Smarc 				/*  a list of commands are executed here */
582*35176Smarc 				do
583*35176Smarc 				{
584*35176Smarc 					execute(((LSTPTR) t)->lstlef,errorflg);
585*35176Smarc 					t = (TREPTR)(((LSTPTR)t)->lstrit);
586*35176Smarc 				}
587*35176Smarc 				while(t->tretyp == TLST);
588*35176Smarc 				execute(t,execflg);
589*35176Smarc 				break;
590*35176Smarc 			}
591*35176Smarc 
592*35176Smarc 			case TAND:
593*35176Smarc #ifdef JOBS
594*35176Smarc 				states |= NONSTOP;
595*35176Smarc #endif	/* JOBS */
596*35176Smarc 				if(execute(((LSTPTR) t)->lstlef,0)==0)
597*35176Smarc 					execute(((LSTPTR) t)->lstrit,execflg);
598*35176Smarc 				break;
599*35176Smarc 
600*35176Smarc 			case TORF:
601*35176Smarc #ifdef JOBS
602*35176Smarc 				states |= NONSTOP;
603*35176Smarc #endif	/* JOBS */
604*35176Smarc 				if(execute(((LSTPTR) t)->lstlef,0)!=0)
605*35176Smarc 					execute(((LSTPTR) t)->lstrit,execflg);
606*35176Smarc 				break;
607*35176Smarc 
608*35176Smarc 			case TFOR:
609*35176Smarc 			case TSELECT:
610*35176Smarc 			{
611*35176Smarc 				register char **args;
612*35176Smarc 				register int nargs;
613*35176Smarc 				NAMPTR n = lookup(((FORPTR) t)->fornam);
614*35176Smarc 				char **arglist;
615*35176Smarc 				DOLPTR	argsav=NULL;
616*35176Smarc 				COMPTR	tp;
617*35176Smarc 				char *nullptr = NULL;
618*35176Smarc #ifdef JOBS
619*35176Smarc 				states |= NONSTOP;
620*35176Smarc #endif	/* JOBS */
621*35176Smarc 				if((tp=((FORPTR)t)->forlst)==NULL)
622*35176Smarc 				{
623*35176Smarc 					args=dolv+1;
624*35176Smarc 					nargs = dolc;
625*35176Smarc 					argsav=arg_use();
626*35176Smarc 				}
627*35176Smarc 				else
628*35176Smarc 				{
629*35176Smarc 					args=arg_build(&argn,tp);
630*35176Smarc 					nargs = argn;
631*35176Smarc 				}
632*35176Smarc 				if(type==TSELECT)
633*35176Smarc 				{
634*35176Smarc 					p_setout(stderr);
635*35176Smarc 					p_list(nargs,arglist=args);
636*35176Smarc 				}
637*35176Smarc 				loopcnt++;
638*35176Smarc 				while(*args !=ENDARGS && execbrk == 0)
639*35176Smarc 				{
640*35176Smarc 					if(t->tretyp==TSELECT)
641*35176Smarc 					{
642*35176Smarc 						char *val,*cp;
643*35176Smarc 						/* reuse register */
644*35176Smarc #define c	type
645*35176Smarc 						chkpr(1);
646*35176Smarc 						if(isatty(0))
647*35176Smarc 							states |= PROMPT;
648*35176Smarc 						readvar(&nullptr,stdin,R_FLAG);
649*35176Smarc 						if(feof(stdin))
650*35176Smarc 						{
651*35176Smarc 							exitval = 1;
652*35176Smarc 							clearerr(stdin);
653*35176Smarc 							break;
654*35176Smarc 						}
655*35176Smarc 						if((val=qvalup(REPLYNOD))==NULL)
656*35176Smarc 							continue;
657*35176Smarc 						else
658*35176Smarc 						{
659*35176Smarc 							if(*(cp=val) == 0)
660*35176Smarc 							{
661*35176Smarc 								p_list(nargs,args);
662*35176Smarc 								continue;
663*35176Smarc 							}
664*35176Smarc 							while(c = *cp++)
665*35176Smarc 							if(c < '0' && c > '9')
666*35176Smarc 								break;
667*35176Smarc 							if(c!=0)
668*35176Smarc 								c = nargs;
669*35176Smarc 							else
670*35176Smarc 								c = atoi(val)-1;
671*35176Smarc 							if(c<0 || c >= nargs)
672*35176Smarc 								c = nargs;
673*35176Smarc 							args += c;
674*35176Smarc 						}
675*35176Smarc 					}
676*35176Smarc #undef c
677*35176Smarc 					assign(n, *args);
678*35176Smarc 					if(t->tretyp != TSELECT)
679*35176Smarc 						args++;
680*35176Smarc 					else
681*35176Smarc 						args = arglist;
682*35176Smarc 					execute(((FORPTR) t)->fortre,errorflg);
683*35176Smarc 					if(breakcnt<0)
684*35176Smarc 						execbrk = (++breakcnt !=0);
685*35176Smarc 					}
686*35176Smarc 				if(breakcnt>0)
687*35176Smarc 					execbrk = (--breakcnt !=0);
688*35176Smarc 				loopcnt--;
689*35176Smarc 				arg_free(argsav,0);
690*35176Smarc 				break;
691*35176Smarc 			}
692*35176Smarc 
693*35176Smarc 			case TWH:
694*35176Smarc 			case TUN:
695*35176Smarc 			{
696*35176Smarc 				register int 	i=0;
697*35176Smarc #ifdef JOBS
698*35176Smarc 				states |= NONSTOP;
699*35176Smarc #endif	/* JOBS */
700*35176Smarc 				loopcnt++;
701*35176Smarc 				while(execbrk==0 && (execute(((WHPTR)t)->whtre,0)==0)==(type==TWH))
702*35176Smarc 				{
703*35176Smarc 					i = execute(((WHPTR) t)->dotre,errorflg);
704*35176Smarc 					if(breakcnt<0)
705*35176Smarc 						execbrk = (++breakcnt !=0);
706*35176Smarc 				}
707*35176Smarc 				if(breakcnt>0)
708*35176Smarc 					execbrk = (--breakcnt !=0);
709*35176Smarc 				loopcnt--;
710*35176Smarc 				exitval= i;
711*35176Smarc 				break;
712*35176Smarc 			}
713*35176Smarc 
714*35176Smarc 			case TIF:
715*35176Smarc #ifdef JOBS
716*35176Smarc 				states |= NONSTOP;
717*35176Smarc #endif	/* JOBS */
718*35176Smarc 				if(execute(((IFPTR) t)->iftre,0)==0)
719*35176Smarc 					execute(((IFPTR) t)->thtre,execflg);
720*35176Smarc 				else if(((IFPTR) t)->eltre)
721*35176Smarc 					execute(((IFPTR) t)->eltre, execflg);
722*35176Smarc 				else
723*35176Smarc 					exitval=0; /* force zero exit for if-then-fi */
724*35176Smarc 				break;
725*35176Smarc 
726*35176Smarc 			case TSW:
727*35176Smarc 			{
728*35176Smarc 				char *r = mactrim(((SWPTR) t)->swarg,0);
729*35176Smarc 				t=(TREPTR)((SWPTR) t)->swlst;
730*35176Smarc 				while(t)
731*35176Smarc 				{
732*35176Smarc 					register ARGPTR	rex=(ARGPTR)((REGPTR)t)->regptr;
733*35176Smarc 					while(rex)
734*35176Smarc 					{
735*35176Smarc 						register char *s;
736*35176Smarc 						if(rex->argflag&A_MAC)
737*35176Smarc 							s = macro(rex->argval);
738*35176Smarc 						else
739*35176Smarc 							s = rex->argval;
740*35176Smarc 						if(((rex->argflag&A_RAW)==0&&gmatch(r,s))
741*35176Smarc 							|| trim_eq(r,s))
742*35176Smarc 						{
743*35176Smarc 							execute(((REGPTR)t)->regcom,errorflg);
744*35176Smarc 							t=0;
745*35176Smarc 							break;
746*35176Smarc 						}
747*35176Smarc 						else
748*35176Smarc 							rex=rex->argnxt;
749*35176Smarc 					}
750*35176Smarc 					if(t)
751*35176Smarc 						t=(TREPTR)((REGPTR)t)->regnxt;
752*35176Smarc 				}
753*35176Smarc 				break;
754*35176Smarc 			}
755*35176Smarc 
756*35176Smarc 			case TTIME:
757*35176Smarc 			{
758*35176Smarc 				/* time the command */
759*35176Smarc 				struct tms before,after;
760*35176Smarc 				long at,bt;
761*35176Smarc #ifdef BSD
762*35176Smarc 				struct timeb tb,ta;
763*35176Smarc 				ftime(&tb);
764*35176Smarc #endif	/* BSD */
765*35176Smarc 				bt = times(&before);
766*35176Smarc 				execute(((PARPTR) t)->partre,0);
767*35176Smarc 				at = times(&after);
768*35176Smarc #ifdef BSD
769*35176Smarc 				ftime(&ta);
770*35176Smarc 				at = TIC_SEC*(ta.time-tb.time);
771*35176Smarc 				at +=  ((TIC_SEC*((long)(ta.millitm-tb.millitm)))/1000);
772*35176Smarc #else
773*35176Smarc 				at -= bt;
774*35176Smarc #endif	/* BSD */
775*35176Smarc 				p_setout(stderr);
776*35176Smarc 				p_str(t_real,'\t');
777*35176Smarc 				p_time(at,NL);
778*35176Smarc 				p_str(t_user,'\t');
779*35176Smarc 				at = after.tms_utime - before.tms_utime;
780*35176Smarc 				at += after.tms_cutime - before.tms_cutime;
781*35176Smarc 				p_time(at,NL);
782*35176Smarc 				p_str(t_sys,'\t');
783*35176Smarc 				at = after.tms_stime - before.tms_stime;
784*35176Smarc 				at += after.tms_cstime - before.tms_cstime;
785*35176Smarc 				p_time(at,NL);
786*35176Smarc 				break;
787*35176Smarc 			}
788*35176Smarc 			case TPROC:
789*35176Smarc 			{
790*35176Smarc 				register NAMPTR np;
791*35176Smarc 				register char *fname = ((PROCPTR)t)->procnam;
792*35176Smarc 				if(!isalpha(*fname))
793*35176Smarc 					failed(fname,notid);
794*35176Smarc 				np = findnod(fname,prnames,1);
795*35176Smarc 				if(np->value.namval.rp)
796*35176Smarc 					free(np->value.namval.rp->ptree);
797*35176Smarc 				else
798*35176Smarc 					np->value.namval.rp = (struct Ufunction*)
799*35176Smarc 						malloc(sizeof(struct Ufunction));
800*35176Smarc 				funtree(np) = (int**)((PROCPTR)t)->proctre;
801*35176Smarc 				np->value.namval.rp->hoffset = ((PROCPTR)t)->procloc;
802*35176Smarc 				sattrib(np,L_FLAG|INT_GER);
803*35176Smarc 				break;
804*35176Smarc 			}
805*35176Smarc 		}
806*35176Smarc #ifdef JOBS
807*35176Smarc 		jobstat.j_flag = 0;
808*35176Smarc #endif	/* JOBS */
809*35176Smarc 		/* set $. */
810*35176Smarc 		if( com0)
811*35176Smarc 		{
812*35176Smarc 			if(lastarg!= locbuf)
813*35176Smarc 				free(lastarg);
814*35176Smarc 			if(strlen(com[argn-1]) < TMPSIZ)
815*35176Smarc 				lastarg = strcpy(locbuf,com[argn-1]);
816*35176Smarc 			else
817*35176Smarc 				lastarg = heap(com[argn-1]);
818*35176Smarc 		}
819*35176Smarc 		exitset();
820*35176Smarc 	}
821*35176Smarc 	if(trapnote&SIGSET)
822*35176Smarc 		exitsh(SIGFAIL|exitval);
823*35176Smarc 	tdystak(sav);
824*35176Smarc 	states |= errorflg;
825*35176Smarc 	linked = 0;
826*35176Smarc 	return(exitval);
827*35176Smarc }
828*35176Smarc 
829*35176Smarc /*
830*35176Smarc  * test for equality with second argument trimmed
831*35176Smarc  * returns 1 if r == trim(s) otherwise 0
832*35176Smarc  */
833*35176Smarc 
trim_eq(r,s)834*35176Smarc static trim_eq(r,s)
835*35176Smarc register char *r,*s;
836*35176Smarc {
837*35176Smarc 	register char c;
838*35176Smarc 	while(c = *s++)
839*35176Smarc 	{
840*35176Smarc 		if(c==ESCAPE)
841*35176Smarc 			c = *s++;
842*35176Smarc 		if(c != *r++)
843*35176Smarc 			return(0);
844*35176Smarc 	}
845*35176Smarc 	return(*r==0);
846*35176Smarc }
847*35176Smarc 
848*35176Smarc /*
849*35176Smarc  * print out the command line if set -x is on
850*35176Smarc  */
851*35176Smarc 
trace_command(com)852*35176Smarc void trace_command(com)
853*35176Smarc char **com;
854*35176Smarc {
855*35176Smarc 	if(is_option(EXECPR))
856*35176Smarc 	{
857*35176Smarc 		p_setout(stderr);
858*35176Smarc 		fputs(execpmsg,output);
859*35176Smarc 		echo_list(1,com,output);
860*35176Smarc 		newline();
861*35176Smarc 	}
862*35176Smarc }
863*35176Smarc 
864