xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/xec.c (revision 6ba75e24)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * UNIX shell parse tree executer
23da2e3ebdSchin  *
24da2e3ebdSchin  *   David Korn
25da2e3ebdSchin  *   AT&T Labs
26da2e3ebdSchin  *
27da2e3ebdSchin  */
28da2e3ebdSchin 
29da2e3ebdSchin #include	"defs.h"
30da2e3ebdSchin #include	<fcin.h>
31da2e3ebdSchin #include	"variables.h"
32da2e3ebdSchin #include	"path.h"
33da2e3ebdSchin #include	"name.h"
34da2e3ebdSchin #include	"io.h"
35da2e3ebdSchin #include	"shnodes.h"
36da2e3ebdSchin #include	"jobs.h"
37da2e3ebdSchin #include	"test.h"
38da2e3ebdSchin #include	"builtins.h"
39da2e3ebdSchin #include	"FEATURE/time"
40da2e3ebdSchin #include	"FEATURE/externs"
41da2e3ebdSchin #include	"FEATURE/locale"
42da2e3ebdSchin #include	"streval.h"
43da2e3ebdSchin 
44da2e3ebdSchin #if !_std_malloc
45da2e3ebdSchin #   include	<vmalloc.h>
46da2e3ebdSchin #endif
47da2e3ebdSchin 
487c2fbfb3SApril Chin #if     _lib_vfork
497c2fbfb3SApril Chin #   include     <ast_vfork.h>
507c2fbfb3SApril Chin #else
517c2fbfb3SApril Chin #   define vfork()      fork()
527c2fbfb3SApril Chin #endif
537c2fbfb3SApril Chin 
54da2e3ebdSchin #define SH_NTFORK	SH_TIMING
55b30d1939SAndy Fiddaman #define NV_BLTPFSH	NV_ARRAY
56da2e3ebdSchin 
57da2e3ebdSchin #if _lib_nice
58da2e3ebdSchin     extern int	nice(int);
59da2e3ebdSchin #endif /* _lib_nice */
60da2e3ebdSchin #if !_lib_spawnveg
61da2e3ebdSchin #   define spawnveg(a,b,c,d)    spawnve(a,b,c)
62da2e3ebdSchin #endif /* !_lib_spawnveg */
63da2e3ebdSchin #if SHOPT_SPAWN
647c2fbfb3SApril Chin     static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
65da2e3ebdSchin #endif /* SHOPT_SPAWN */
66da2e3ebdSchin 
677c2fbfb3SApril Chin static void	sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
68da2e3ebdSchin static int	trim_eq(const char*, const char*);
697c2fbfb3SApril Chin static void	coproc_init(Shell_t*, int pipes[]);
70da2e3ebdSchin 
71da2e3ebdSchin static void	*timeout;
72b30d1939SAndy Fiddaman static char	nlock;
73da2e3ebdSchin static char	pipejob;
74b30d1939SAndy Fiddaman static char	nopost;
75b30d1939SAndy Fiddaman static int	restorefd;
76da2e3ebdSchin 
77da2e3ebdSchin struct funenv
78da2e3ebdSchin {
79da2e3ebdSchin 	Namval_t	*node;
80da2e3ebdSchin 	struct argnod	*env;
81b30d1939SAndy Fiddaman 	Namval_t	**nref;
82da2e3ebdSchin };
83da2e3ebdSchin 
84da2e3ebdSchin /* ========	command execution	========*/
85da2e3ebdSchin 
86b30d1939SAndy Fiddaman #if !SHOPT_DEVFD
fifo_check(void * handle)87b30d1939SAndy Fiddaman     static void fifo_check(void *handle)
88b30d1939SAndy Fiddaman     {
89b30d1939SAndy Fiddaman 	Shell_t	*shp = (Shell_t*)handle;
90b30d1939SAndy Fiddaman 	pid_t pid = getppid();
91b30d1939SAndy Fiddaman 	if(pid==1)
92b30d1939SAndy Fiddaman 	{
93b30d1939SAndy Fiddaman 		unlink(shp->fifo);
94b30d1939SAndy Fiddaman 		sh_done(shp,0);
95b30d1939SAndy Fiddaman 	}
96b30d1939SAndy Fiddaman     }
97b30d1939SAndy Fiddaman #endif /* !SHOPT_DEVFD */
98b30d1939SAndy Fiddaman 
99b30d1939SAndy Fiddaman /*
100b30d1939SAndy Fiddaman  * The following two functions allow command substituion for non-builtins
101b30d1939SAndy Fiddaman  * to use a pipe and to wait for the pipe to close before restoring to a
102b30d1939SAndy Fiddaman  * temp file.
103b30d1939SAndy Fiddaman  */
104b30d1939SAndy Fiddaman static int      subpipe[3],subdup,tsetio,usepipe;
105b30d1939SAndy Fiddaman static void iounpipe(Shell_t*);
106b30d1939SAndy Fiddaman 
iousepipe(Shell_t * shp)107b30d1939SAndy Fiddaman static int iousepipe(Shell_t *shp)
108b30d1939SAndy Fiddaman {
109b30d1939SAndy Fiddaman 	int i;
110b30d1939SAndy Fiddaman 	if(usepipe)
111b30d1939SAndy Fiddaman 	{
112b30d1939SAndy Fiddaman 		usepipe++;
113b30d1939SAndy Fiddaman 		iounpipe(shp);
114b30d1939SAndy Fiddaman 	}
115b30d1939SAndy Fiddaman 	if(sh_rpipe(subpipe) < 0)
116b30d1939SAndy Fiddaman 		return(0);
117b30d1939SAndy Fiddaman 	usepipe++;
118b30d1939SAndy Fiddaman 	fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
119b30d1939SAndy Fiddaman 	subpipe[2] = fcntl(1,F_DUPFD,10);
120b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, subpipe[1]);
121b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, subpipe[2]);
122b30d1939SAndy Fiddaman 	fcntl(subpipe[2],F_SETFD,FD_CLOEXEC);
123b30d1939SAndy Fiddaman 	shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
124b30d1939SAndy Fiddaman 	close(1);
125b30d1939SAndy Fiddaman 	fcntl(subpipe[1],F_DUPFD,1);
126b30d1939SAndy Fiddaman 	shp->fdstatus[1] = shp->fdstatus[subpipe[1]];
127b30d1939SAndy Fiddaman 	sh_close(subpipe[1]);
128b30d1939SAndy Fiddaman 	if(subdup=shp->subdup) for(i=0; i < 10; i++)
129b30d1939SAndy Fiddaman 	{
130b30d1939SAndy Fiddaman 		if(subdup&(1<<i))
131b30d1939SAndy Fiddaman 		{
132b30d1939SAndy Fiddaman 			sh_close(i);
133b30d1939SAndy Fiddaman 			fcntl(1,F_DUPFD,i);
134b30d1939SAndy Fiddaman 			shp->fdstatus[i] = shp->fdstatus[1];
135b30d1939SAndy Fiddaman 		}
136b30d1939SAndy Fiddaman 	}
137b30d1939SAndy Fiddaman 	return(1);
138b30d1939SAndy Fiddaman }
139b30d1939SAndy Fiddaman 
iounpipe(Shell_t * shp)140b30d1939SAndy Fiddaman static void iounpipe(Shell_t *shp)
141b30d1939SAndy Fiddaman {
142b30d1939SAndy Fiddaman 	int n;
143b30d1939SAndy Fiddaman 	char buff[SF_BUFSIZE];
144b30d1939SAndy Fiddaman 	close(1);
145b30d1939SAndy Fiddaman 	fcntl(subpipe[2], F_DUPFD, 1);
146b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, subpipe[2]);
147b30d1939SAndy Fiddaman 	shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
148b30d1939SAndy Fiddaman 	--usepipe;
149b30d1939SAndy Fiddaman 	if(subdup) for(n=0; n < 10; n++)
150b30d1939SAndy Fiddaman 	{
151b30d1939SAndy Fiddaman 		if(subdup&(1<<n))
152b30d1939SAndy Fiddaman 		{
153b30d1939SAndy Fiddaman 			sh_close(n);
154b30d1939SAndy Fiddaman 			fcntl(1, F_DUPFD, n);
155b30d1939SAndy Fiddaman 			shp->fdstatus[n] = shp->fdstatus[1];
156b30d1939SAndy Fiddaman 		}
157b30d1939SAndy Fiddaman 	}
158b30d1939SAndy Fiddaman 	shp->subdup = 0;
159b30d1939SAndy Fiddaman 	sh_close(subpipe[2]);
160b30d1939SAndy Fiddaman 	if(usepipe==0) while(1)
161b30d1939SAndy Fiddaman 	{
162b30d1939SAndy Fiddaman 		while(job.waitsafe && job.savesig==SIGCHLD)
163b30d1939SAndy Fiddaman 		{
164b30d1939SAndy Fiddaman 			if(!vmbusy())
165b30d1939SAndy Fiddaman 			{
166b30d1939SAndy Fiddaman 				job.in_critical++;
167b30d1939SAndy Fiddaman 				job_reap(SIGCHLD);
168b30d1939SAndy Fiddaman 				job.in_critical--;
169b30d1939SAndy Fiddaman 				break;
170b30d1939SAndy Fiddaman 			}
171b30d1939SAndy Fiddaman 			sh_delay(1);
172b30d1939SAndy Fiddaman 		}
173b30d1939SAndy Fiddaman 		if((n = read(subpipe[0],buff,sizeof(buff)))==0)
174b30d1939SAndy Fiddaman 			break;
175b30d1939SAndy Fiddaman 		if(n>0)
176b30d1939SAndy Fiddaman 			sfwrite(sfstdout,buff,n);
177b30d1939SAndy Fiddaman 		else if(errno!=EINTR)
178b30d1939SAndy Fiddaman 			break;
179b30d1939SAndy Fiddaman 	}
180b30d1939SAndy Fiddaman 	sh_close(subpipe[0]);
181b30d1939SAndy Fiddaman 	subpipe[0] = -1;
182b30d1939SAndy Fiddaman 	tsetio = 0;
183b30d1939SAndy Fiddaman 	usepipe = 0;
184b30d1939SAndy Fiddaman }
185b30d1939SAndy Fiddaman 
186da2e3ebdSchin /*
187da2e3ebdSchin  * print time <t> in h:m:s format with precision <p>
188da2e3ebdSchin  */
l_time(Sfio_t * outfile,register clock_t t,int p)189da2e3ebdSchin static void     l_time(Sfio_t *outfile,register clock_t t,int p)
190da2e3ebdSchin {
191da2e3ebdSchin 	register int  min, sec, frac;
192da2e3ebdSchin 	register int hr;
193da2e3ebdSchin 	if(p)
194da2e3ebdSchin 	{
195b30d1939SAndy Fiddaman 		frac = t%shgd->lim.clk_tck;
196b30d1939SAndy Fiddaman 		frac = (frac*100)/shgd->lim.clk_tck;
197da2e3ebdSchin 	}
198b30d1939SAndy Fiddaman 	t /= shgd->lim.clk_tck;
199da2e3ebdSchin 	sec = t%60;
200da2e3ebdSchin 	t /= 60;
201da2e3ebdSchin 	min = t%60;
202da2e3ebdSchin 	if(hr=t/60)
203da2e3ebdSchin 		sfprintf(outfile,"%dh",hr);
204da2e3ebdSchin 	if(p)
205da2e3ebdSchin 		sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
206da2e3ebdSchin 	else
207da2e3ebdSchin 		sfprintf(outfile,"%dm%ds",min,sec);
208da2e3ebdSchin }
209da2e3ebdSchin 
p_time(Shell_t * shp,Sfio_t * out,const char * format,clock_t * tm)2107c2fbfb3SApril Chin static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
211da2e3ebdSchin {
2127c2fbfb3SApril Chin 	int		c,p,l,n,offset = staktell();
2137c2fbfb3SApril Chin 	const char	*first;
2147c2fbfb3SApril Chin 	double		d;
2157c2fbfb3SApril Chin 	Stk_t		*stkp = shp->stk;
216da2e3ebdSchin 	for(first=format ; c= *format; format++)
217da2e3ebdSchin 	{
218da2e3ebdSchin 		if(c!='%')
219da2e3ebdSchin 			continue;
2207c2fbfb3SApril Chin 		sfwrite(stkp, first, format-first);
221da2e3ebdSchin 		n = l = 0;
222da2e3ebdSchin 		p = 3;
223da2e3ebdSchin 		if((c= *++format) == '%')
224da2e3ebdSchin 		{
225da2e3ebdSchin 			first = format;
226da2e3ebdSchin 			continue;
227da2e3ebdSchin 		}
228da2e3ebdSchin 		if(c>='0' && c <='9')
229da2e3ebdSchin 		{
230da2e3ebdSchin 			p = (c>'3')?3:(c-'0');
231da2e3ebdSchin 			c = *++format;
232da2e3ebdSchin 		}
233da2e3ebdSchin 		else if(c=='P')
234da2e3ebdSchin 		{
235da2e3ebdSchin 			if(d=tm[0])
236da2e3ebdSchin 				d = 100.*(((double)(tm[1]+tm[2]))/d);
237da2e3ebdSchin 			p = 2;
238da2e3ebdSchin 			goto skip;
239da2e3ebdSchin 		}
240da2e3ebdSchin 		if(c=='l')
241da2e3ebdSchin 		{
242da2e3ebdSchin 			l = 1;
243da2e3ebdSchin 			c = *++format;
244da2e3ebdSchin 		}
245da2e3ebdSchin 		if(c=='U')
246da2e3ebdSchin 			n = 1;
247da2e3ebdSchin 		else if(c=='S')
248da2e3ebdSchin 			n = 2;
249da2e3ebdSchin 		else if(c!='R')
250da2e3ebdSchin 		{
2517c2fbfb3SApril Chin 			stkseek(stkp,offset);
252da2e3ebdSchin 			errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
253da2e3ebdSchin 			return(0);
254da2e3ebdSchin 		}
255b30d1939SAndy Fiddaman 		d = (double)tm[n]/shp->gd->lim.clk_tck;
256da2e3ebdSchin 	skip:
257da2e3ebdSchin 		if(l)
2587c2fbfb3SApril Chin 			l_time(stkp, tm[n], p);
259da2e3ebdSchin 		else
2607c2fbfb3SApril Chin 			sfprintf(stkp,"%.*f",p, d);
261da2e3ebdSchin 		first = format+1;
262da2e3ebdSchin 	}
263da2e3ebdSchin 	if(format>first)
2647c2fbfb3SApril Chin 		sfwrite(stkp,first, format-first);
2657c2fbfb3SApril Chin 	sfputc(stkp,'\n');
2667c2fbfb3SApril Chin 	n = stktell(stkp)-offset;
2677c2fbfb3SApril Chin 	sfwrite(out,stkptr(stkp,offset),n);
2687c2fbfb3SApril Chin 	stkseek(stkp,offset);
269da2e3ebdSchin 	return(n);
270da2e3ebdSchin }
271da2e3ebdSchin 
272da2e3ebdSchin #if SHOPT_OPTIMIZE
273da2e3ebdSchin /*
274da2e3ebdSchin  * clear argument pointers that point into the stack
275da2e3ebdSchin  */
276da2e3ebdSchin static int p_arg(struct argnod*,int);
277da2e3ebdSchin static int p_switch(struct regnod*);
p_comarg(register struct comnod * com)278da2e3ebdSchin static int p_comarg(register struct comnod *com)
279da2e3ebdSchin {
280da2e3ebdSchin 	Namval_t *np=com->comnamp;
281da2e3ebdSchin 	int n = p_arg(com->comset,ARG_ASSIGN);
282da2e3ebdSchin 	if(com->comarg && (com->comtyp&COMSCAN))
283da2e3ebdSchin 		n+= p_arg(com->comarg,0);
284da2e3ebdSchin 	if(com->comstate  && np)
285da2e3ebdSchin 	{
286da2e3ebdSchin 		/* call builtin to cleanup state */
2877c2fbfb3SApril Chin 		Shbltin_t *bp = &sh.bltindata;
2887c2fbfb3SApril Chin 		void  *save_ptr = bp->ptr;
2897c2fbfb3SApril Chin 		void  *save_data = bp->data;
2907c2fbfb3SApril Chin 		bp->bnode = np;
2917c2fbfb3SApril Chin 		bp->vnode = com->comnamq;
2927c2fbfb3SApril Chin 		bp->ptr = nv_context(np);
2937c2fbfb3SApril Chin 		bp->data = com->comstate;
2947c2fbfb3SApril Chin 		bp->flags = SH_END_OPTIM;
295b30d1939SAndy Fiddaman 		((Shbltin_f)funptr(np))(0,(char**)0, bp);
2967c2fbfb3SApril Chin 		bp->ptr = save_ptr;
2977c2fbfb3SApril Chin 		bp->data = save_data;
298da2e3ebdSchin 	}
299da2e3ebdSchin 	com->comstate = 0;
300da2e3ebdSchin 	if(com->comarg && !np)
301da2e3ebdSchin 		n++;
302da2e3ebdSchin 	return(n);
303da2e3ebdSchin }
304da2e3ebdSchin 
305da2e3ebdSchin extern void sh_optclear(Shell_t*, void*);
306da2e3ebdSchin 
sh_tclear(register Shnode_t * t)307da2e3ebdSchin static int sh_tclear(register Shnode_t *t)
308da2e3ebdSchin {
309da2e3ebdSchin 	int n=0;
310da2e3ebdSchin 	if(!t)
311da2e3ebdSchin 		return(0);
312da2e3ebdSchin 	switch(t->tre.tretyp&COMMSK)
313da2e3ebdSchin 	{
314da2e3ebdSchin 		case TTIME:
315da2e3ebdSchin 		case TPAR:
316da2e3ebdSchin 			return(sh_tclear(t->par.partre));
317da2e3ebdSchin 		case TCOM:
318da2e3ebdSchin 			return(p_comarg((struct comnod*)t));
319da2e3ebdSchin 		case TSETIO:
320da2e3ebdSchin 		case TFORK:
321da2e3ebdSchin 			return(sh_tclear(t->fork.forktre));
322da2e3ebdSchin 		case TIF:
323da2e3ebdSchin 			n=sh_tclear(t->if_.iftre);
324da2e3ebdSchin 			n+=sh_tclear(t->if_.thtre);
325da2e3ebdSchin 			n+=sh_tclear(t->if_.eltre);
326da2e3ebdSchin 			return(n);
327da2e3ebdSchin 		case TWH:
328da2e3ebdSchin 			if(t->wh.whinc)
329da2e3ebdSchin 				n=sh_tclear((Shnode_t*)(t->wh.whinc));
330da2e3ebdSchin 			n+=sh_tclear(t->wh.whtre);
331da2e3ebdSchin 			n+=sh_tclear(t->wh.dotre);
332da2e3ebdSchin 			return(n);
333da2e3ebdSchin 		case TLST:
334da2e3ebdSchin 		case TAND:
335da2e3ebdSchin 		case TORF:
336da2e3ebdSchin 		case TFIL:
337da2e3ebdSchin 			n=sh_tclear(t->lst.lstlef);
338da2e3ebdSchin 			return(n+sh_tclear(t->lst.lstrit));
339da2e3ebdSchin 		case TARITH:
340da2e3ebdSchin 			return(p_arg(t->ar.arexpr,ARG_ARITH));
341da2e3ebdSchin 		case TFOR:
342da2e3ebdSchin 			n=sh_tclear(t->for_.fortre);
343da2e3ebdSchin 			return(n+sh_tclear((Shnode_t*)t->for_.forlst));
344da2e3ebdSchin 		case TSW:
345da2e3ebdSchin 			n=p_arg(t->sw.swarg,0);
346da2e3ebdSchin 			return(n+p_switch(t->sw.swlst));
347da2e3ebdSchin 		case TFUN:
348da2e3ebdSchin 			n=sh_tclear(t->funct.functtre);
349da2e3ebdSchin 			return(n+sh_tclear((Shnode_t*)t->funct.functargs));
350da2e3ebdSchin 		case TTST:
351da2e3ebdSchin 			if((t->tre.tretyp&TPAREN)==TPAREN)
352da2e3ebdSchin 				return(sh_tclear(t->lst.lstlef));
353da2e3ebdSchin 			else
354da2e3ebdSchin 			{
355da2e3ebdSchin 				n=p_arg(&(t->lst.lstlef->arg),0);
356da2e3ebdSchin 				if(t->tre.tretyp&TBINARY)
357da2e3ebdSchin 					n+=p_arg(&(t->lst.lstrit->arg),0);
358da2e3ebdSchin 			}
359da2e3ebdSchin 	}
360da2e3ebdSchin 	return(n);
361da2e3ebdSchin }
362da2e3ebdSchin 
p_arg(register struct argnod * arg,int flag)363da2e3ebdSchin static int p_arg(register struct argnod *arg,int flag)
364da2e3ebdSchin {
365da2e3ebdSchin 	while(arg)
366da2e3ebdSchin 	{
367da2e3ebdSchin 		if(strlen(arg->argval) || (arg->argflag==ARG_RAW))
368da2e3ebdSchin 			arg->argchn.ap = 0;
369da2e3ebdSchin 		else if(flag==0)
370da2e3ebdSchin 			sh_tclear((Shnode_t*)arg->argchn.ap);
371da2e3ebdSchin 		else
372da2e3ebdSchin 			sh_tclear(((struct fornod*)arg->argchn.ap)->fortre);
373da2e3ebdSchin 		arg = arg->argnxt.ap;
374da2e3ebdSchin 	}
375da2e3ebdSchin 	return(0);
376da2e3ebdSchin }
377da2e3ebdSchin 
p_switch(register struct regnod * reg)378da2e3ebdSchin static int p_switch(register struct regnod *reg)
379da2e3ebdSchin {
380da2e3ebdSchin 	int n=0;
381da2e3ebdSchin 	while(reg)
382da2e3ebdSchin 	{
383da2e3ebdSchin 		n+=p_arg(reg->regptr,0);
384da2e3ebdSchin 		n+=sh_tclear(reg->regcom);
385da2e3ebdSchin 		reg = reg->regnxt;
386da2e3ebdSchin 	}
387da2e3ebdSchin 	return(n);
388da2e3ebdSchin }
389da2e3ebdSchin #   define OPTIMIZE_FLAG	(ARG_OPTIMIZE)
390da2e3ebdSchin #   define OPTIMIZE		(flags&OPTIMIZE_FLAG)
391da2e3ebdSchin #else
392da2e3ebdSchin #   define OPTIMIZE_FLAG	(0)
393da2e3ebdSchin #   define OPTIMIZE		(0)
394da2e3ebdSchin #   define sh_tclear(x)
395da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
396da2e3ebdSchin 
out_pattern(Sfio_t * iop,register const char * cp,int n)397da2e3ebdSchin static void out_pattern(Sfio_t *iop, register const char *cp, int n)
398da2e3ebdSchin {
399da2e3ebdSchin 	register int c;
400da2e3ebdSchin 	do
401da2e3ebdSchin 	{
402da2e3ebdSchin 		switch(c= *cp)
403da2e3ebdSchin 		{
404da2e3ebdSchin 		    case 0:
405da2e3ebdSchin 			if(n<0)
406da2e3ebdSchin 				return;
407da2e3ebdSchin 			c = n;
408da2e3ebdSchin 			break;
409da2e3ebdSchin 		    case '\n':
410da2e3ebdSchin 			sfputr(iop,"$'\\n",'\'');
411da2e3ebdSchin 			continue;
412da2e3ebdSchin 		    case '\\':
413da2e3ebdSchin 			if (!(c = *++cp))
414da2e3ebdSchin 				c = '\\';
415da2e3ebdSchin 			/*FALLTHROUGH*/
416da2e3ebdSchin 		    case ' ':
417da2e3ebdSchin 		    case '<': case '>': case ';':
418da2e3ebdSchin 		    case '$': case '`': case '\t':
419da2e3ebdSchin 			sfputc(iop,'\\');
420da2e3ebdSchin 			break;
421da2e3ebdSchin 		}
422da2e3ebdSchin 		sfputc(iop,c);
423da2e3ebdSchin 	}
424da2e3ebdSchin 	while(*cp++);
425da2e3ebdSchin }
426da2e3ebdSchin 
out_string(Sfio_t * iop,register const char * cp,int c,int quoted)427da2e3ebdSchin static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
428da2e3ebdSchin {
429da2e3ebdSchin 	if(quoted)
430da2e3ebdSchin 	{
4317c2fbfb3SApril Chin 		int n = stktell(stkstd);
432da2e3ebdSchin 		cp = sh_fmtq(cp);
433da2e3ebdSchin 		if(iop==stkstd && cp==stkptr(stkstd,n))
434da2e3ebdSchin 		{
435da2e3ebdSchin 			*stkptr(stkstd,stktell(stkstd)-1) = c;
436da2e3ebdSchin 			return;
437da2e3ebdSchin 		}
438da2e3ebdSchin 	}
439da2e3ebdSchin 	sfputr(iop,cp,c);
440da2e3ebdSchin }
441da2e3ebdSchin 
442da2e3ebdSchin struct Level
443da2e3ebdSchin {
444da2e3ebdSchin 	Namfun_t	hdr;
445da2e3ebdSchin 	short		maxlevel;
446da2e3ebdSchin };
447da2e3ebdSchin 
448da2e3ebdSchin /*
449da2e3ebdSchin  * this is for a debugger but it hasn't been tested yet
450da2e3ebdSchin  * if a debug script sets .sh.level it should set up the scope
451da2e3ebdSchin  *  as if you were executing in that level
452da2e3ebdSchin  */
put_level(Namval_t * np,const char * val,int flags,Namfun_t * fp)453da2e3ebdSchin static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
454da2e3ebdSchin {
455da2e3ebdSchin 	Shscope_t	*sp;
456da2e3ebdSchin 	struct Level *lp = (struct Level*)fp;
457da2e3ebdSchin 	int16_t level, oldlevel = (int16_t)nv_getnum(np);
458da2e3ebdSchin 	nv_putv(np,val,flags,fp);
4597c2fbfb3SApril Chin 	if(!val)
46034f9b3eeSRoland Mainz 	{
46134f9b3eeSRoland Mainz 		fp = nv_stack(np, NIL(Namfun_t*));
46234f9b3eeSRoland Mainz 		if(fp && !fp->nofree)
46334f9b3eeSRoland Mainz 			free((void*)fp);
4647c2fbfb3SApril Chin 		return;
46534f9b3eeSRoland Mainz 	}
466da2e3ebdSchin 	level = nv_getnum(np);
467da2e3ebdSchin 	if(level<0 || level > lp->maxlevel)
468da2e3ebdSchin 	{
4697c2fbfb3SApril Chin 		nv_putv(np, (char*)&oldlevel, NV_INT16, fp);
470da2e3ebdSchin 		/* perhaps this should be an error */
471da2e3ebdSchin 		return;
472da2e3ebdSchin 	}
473da2e3ebdSchin 	if(level==oldlevel)
474da2e3ebdSchin 		return;
475da2e3ebdSchin 	if(sp = sh_getscope(level,SEEK_SET))
476da2e3ebdSchin 	{
4777c2fbfb3SApril Chin 		sh_setscope(sp);
4787c2fbfb3SApril Chin 		error_info.id = sp->cmdname;
4797c2fbfb3SApril Chin 
480da2e3ebdSchin 	}
481da2e3ebdSchin }
482da2e3ebdSchin 
4837c2fbfb3SApril Chin static const Namdisc_t level_disc = {  sizeof(struct Level), put_level };
4847c2fbfb3SApril Chin 
init_level(Shell_t * shp,int level)485b30d1939SAndy Fiddaman static struct Level *init_level(Shell_t *shp,int level)
4867c2fbfb3SApril Chin {
4877c2fbfb3SApril Chin 	struct Level *lp = newof(NiL,struct Level,1,0);
4887c2fbfb3SApril Chin 	lp->maxlevel = level;
4897c2fbfb3SApril Chin 	_nv_unset(SH_LEVELNOD,0);
4907c2fbfb3SApril Chin 	nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE);
491b30d1939SAndy Fiddaman 	shp->last_root = nv_dict(DOTSHNOD);
4927c2fbfb3SApril Chin 	nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
4937c2fbfb3SApril Chin 	lp->hdr.disc = &level_disc;
4947c2fbfb3SApril Chin 	nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST);
4957c2fbfb3SApril Chin 	return(lp);
4967c2fbfb3SApril Chin }
497da2e3ebdSchin 
498da2e3ebdSchin /*
499b30d1939SAndy Fiddaman  * write the current command on the stack and make it available as .sh.command
500da2e3ebdSchin  */
sh_debug(Shell_t * shp,const char * trap,const char * name,const char * subscript,char * const argv[],int flags)5017c2fbfb3SApril Chin int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
502da2e3ebdSchin {
5037c2fbfb3SApril Chin 	Stk_t			*stkp=shp->stk;
504da2e3ebdSchin 	struct sh_scoped	savst;
505da2e3ebdSchin 	Namval_t		*np = SH_COMMANDNOD;
5067c2fbfb3SApril Chin 	int			n=4, offset=stktell(stkp);
5073636ae54SAndy Fiddaman 	char			*sav = stkfreeze(stkp,0);
508da2e3ebdSchin 	const char		*cp = "+=( ";
509da2e3ebdSchin 	Sfio_t			*iop = stkstd;
5107c2fbfb3SApril Chin 	short			level;
5117c2fbfb3SApril Chin 	if(shp->indebug)
5127c2fbfb3SApril Chin 		return(0);
5137c2fbfb3SApril Chin 	shp->indebug = 1;
514da2e3ebdSchin 	if(name)
515da2e3ebdSchin 	{
516da2e3ebdSchin 		sfputr(iop,name,-1);
517da2e3ebdSchin 		if(subscript)
518da2e3ebdSchin 		{
519da2e3ebdSchin 			sfputc(iop,'[');
520da2e3ebdSchin 			out_string(iop,subscript,']',1);
521da2e3ebdSchin 		}
522da2e3ebdSchin 		if(!(flags&ARG_APPEND))
523da2e3ebdSchin 			cp+=1, n-=1;
524da2e3ebdSchin 		if(!(flags&ARG_ASSIGN))
525da2e3ebdSchin 			n -= 2;
526da2e3ebdSchin 		sfwrite(iop,cp,n);
527da2e3ebdSchin 	}
52834f9b3eeSRoland Mainz 	if(*argv && !(flags&ARG_RAW))
529da2e3ebdSchin 		out_string(iop, *argv++,' ', 0);
530da2e3ebdSchin 	n = (flags&ARG_ARITH);
531da2e3ebdSchin 	while(cp = *argv++)
532da2e3ebdSchin 	{
533da2e3ebdSchin 		if((flags&ARG_EXP) && argv[1]==0)
534da2e3ebdSchin 			out_pattern(iop, cp,' ');
535da2e3ebdSchin 		else
536da2e3ebdSchin 			out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
537da2e3ebdSchin 	}
538da2e3ebdSchin 	if(flags&ARG_ASSIGN)
539da2e3ebdSchin 		sfputc(iop,')');
540da2e3ebdSchin 	else if(iop==stkstd)
5417c2fbfb3SApril Chin 		*stkptr(stkp,stktell(stkp)-1) = 0;
5427c2fbfb3SApril Chin 	np->nvalue.cp = stkfreeze(stkp,1);
543da2e3ebdSchin 	/* now setup .sh.level variable */
5447c2fbfb3SApril Chin 	shp->st.lineno = error_info.line;
5457c2fbfb3SApril Chin 	level  = shp->fn_depth+shp->dot_depth;
546b30d1939SAndy Fiddaman 	shp->last_root = nv_dict(DOTSHNOD);
5477c2fbfb3SApril Chin 	if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
548b30d1939SAndy Fiddaman 		init_level(shp,level);
5497c2fbfb3SApril Chin 	else
5507c2fbfb3SApril Chin 		nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
5517c2fbfb3SApril Chin 	savst = shp->st;
5527c2fbfb3SApril Chin 	shp->st.trap[SH_DEBUGTRAP] = 0;
553da2e3ebdSchin 	n = sh_trap(trap,0);
554da2e3ebdSchin 	np->nvalue.cp = 0;
5557c2fbfb3SApril Chin 	shp->indebug = 0;
5567c2fbfb3SApril Chin 	if(shp->st.cmdname)
5577c2fbfb3SApril Chin 		error_info.id = shp->st.cmdname;
5587c2fbfb3SApril Chin 	nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
5597c2fbfb3SApril Chin 	nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
5607c2fbfb3SApril Chin 	shp->st = savst;
5617c2fbfb3SApril Chin 	if(sav != stkptr(stkp,0))
5623636ae54SAndy Fiddaman 		stkset(stkp,sav,offset);
563da2e3ebdSchin 	else
5647c2fbfb3SApril Chin 		stkseek(stkp,offset);
565da2e3ebdSchin 	return(n);
566da2e3ebdSchin }
567da2e3ebdSchin 
568da2e3ebdSchin /*
569da2e3ebdSchin  * Given stream <iop> compile and execute
570da2e3ebdSchin  */
sh_eval(register Sfio_t * iop,int mode)571da2e3ebdSchin int sh_eval(register Sfio_t *iop, int mode)
572da2e3ebdSchin {
573da2e3ebdSchin 	register Shnode_t *t;
574da2e3ebdSchin 	Shell_t  *shp = sh_getinterp();
575da2e3ebdSchin 	struct slnod *saveslp = shp->st.staklist;
576da2e3ebdSchin 	int jmpval;
577da2e3ebdSchin 	struct checkpt *pp = (struct checkpt*)shp->jmplist;
578b30d1939SAndy Fiddaman 	struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
579da2e3ebdSchin 	static Sfio_t *io_save;
5807c2fbfb3SApril Chin 	volatile int traceon=0, lineno=0;
58134f9b3eeSRoland Mainz 	int binscript=shp->binscript;
582b30d1939SAndy Fiddaman 	char comsub = shp->comsub;
583da2e3ebdSchin 	io_save = iop; /* preserve correct value across longjmp */
58434f9b3eeSRoland Mainz 	shp->binscript = 0;
585b30d1939SAndy Fiddaman 	shp->comsub = 0;
5867c2fbfb3SApril Chin #define SH_TOPFUN	0x8000	/* this is a temporary tksh hack */
5877c2fbfb3SApril Chin 	if (mode & SH_TOPFUN)
5887c2fbfb3SApril Chin 	{
5897c2fbfb3SApril Chin 		mode ^= SH_TOPFUN;
5907c2fbfb3SApril Chin 		shp->fn_reset = 1;
5917c2fbfb3SApril Chin 	}
592b30d1939SAndy Fiddaman 	sh_pushcontext(shp,buffp,SH_JMPEVAL);
593b30d1939SAndy Fiddaman 	buffp->olist = pp->olist;
594b30d1939SAndy Fiddaman 	jmpval = sigsetjmp(buffp->buff,0);
59534f9b3eeSRoland Mainz 	while(jmpval==0)
596da2e3ebdSchin 	{
5977c2fbfb3SApril Chin 		if(mode&SH_READEVAL)
5987c2fbfb3SApril Chin 		{
5997c2fbfb3SApril Chin 			lineno = shp->inlineno;
6007c2fbfb3SApril Chin 			if(traceon=sh_isoption(SH_XTRACE))
6017c2fbfb3SApril Chin 				sh_offoption(SH_XTRACE);
6027c2fbfb3SApril Chin 		}
60334f9b3eeSRoland Mainz 		t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
60434f9b3eeSRoland Mainz 		if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0))
60534f9b3eeSRoland Mainz 		{
60634f9b3eeSRoland Mainz 			if(!(mode&SH_READEVAL))
60734f9b3eeSRoland Mainz 				sfclose(iop);
60834f9b3eeSRoland Mainz 			io_save = 0;
60934f9b3eeSRoland Mainz 			mode &= ~SH_FUNEVAL;
61034f9b3eeSRoland Mainz 		}
61134f9b3eeSRoland Mainz 		mode &= ~SH_READEVAL;
612da2e3ebdSchin 		if(!sh_isoption(SH_VERBOSE))
613da2e3ebdSchin 			sh_offstate(SH_VERBOSE);
614b30d1939SAndy Fiddaman 		if((mode&~SH_FUNEVAL) && shp->gd->hist_ptr)
615da2e3ebdSchin 		{
616b30d1939SAndy Fiddaman 			hist_flush(shp->gd->hist_ptr);
617da2e3ebdSchin 			mode = sh_state(SH_INTERACTIVE);
618da2e3ebdSchin 		}
61934f9b3eeSRoland Mainz 		sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
62034f9b3eeSRoland Mainz 		if(!(mode&SH_FUNEVAL))
62134f9b3eeSRoland Mainz 			break;
622da2e3ebdSchin 	}
623b30d1939SAndy Fiddaman 	sh_popcontext(shp,buffp);
62434f9b3eeSRoland Mainz 	shp->binscript = binscript;
625b30d1939SAndy Fiddaman 	shp->comsub = comsub;
6267c2fbfb3SApril Chin 	if(traceon)
6277c2fbfb3SApril Chin 		sh_onoption(SH_XTRACE);
6287c2fbfb3SApril Chin 	if(lineno)
6297c2fbfb3SApril Chin 		shp->inlineno = lineno;
630da2e3ebdSchin 	if(io_save)
631b30d1939SAndy Fiddaman 	{
632da2e3ebdSchin 		sfclose(io_save);
633b30d1939SAndy Fiddaman 		io_save = 0;
634b30d1939SAndy Fiddaman 	}
6357c2fbfb3SApril Chin 	sh_freeup(shp);
636da2e3ebdSchin 	shp->st.staklist = saveslp;
6377c2fbfb3SApril Chin 	shp->fn_reset = 0;
638da2e3ebdSchin 	if(jmpval>SH_JMPEVAL)
639da2e3ebdSchin 		siglongjmp(*shp->jmplist,jmpval);
6407c2fbfb3SApril Chin 	return(shp->exitval);
641da2e3ebdSchin }
642da2e3ebdSchin 
643da2e3ebdSchin /*
644da2e3ebdSchin  * returns 1 when option -<c> is specified
645da2e3ebdSchin  */
checkopt(char * argv[],int c)646da2e3ebdSchin static int checkopt(char *argv[], int c)
647da2e3ebdSchin {
648da2e3ebdSchin 	char *cp;
649da2e3ebdSchin 	while(cp = *++argv)
650da2e3ebdSchin 	{
651da2e3ebdSchin 		if(*cp=='+')
652da2e3ebdSchin 			continue;
653da2e3ebdSchin 		if(*cp!='-' || cp[1]=='-')
654da2e3ebdSchin 			break;
6557c2fbfb3SApril Chin 		if(strchr(++cp,c))
656da2e3ebdSchin 			return(1);
6577c2fbfb3SApril Chin 		if(*cp=='h' && cp[1]==0 && *++argv==0)
6587c2fbfb3SApril Chin 			break;
659da2e3ebdSchin 	}
660da2e3ebdSchin 	return(0);
661da2e3ebdSchin }
662da2e3ebdSchin 
free_list(struct openlist * olist)663da2e3ebdSchin static void free_list(struct openlist *olist)
664da2e3ebdSchin {
665da2e3ebdSchin 	struct openlist *item,*next;
666da2e3ebdSchin 	for(item=olist;item;item=next)
667da2e3ebdSchin 	{
668da2e3ebdSchin 		next = item->next;
669da2e3ebdSchin 		free((void*)item);
670da2e3ebdSchin 	}
671da2e3ebdSchin }
672da2e3ebdSchin 
6737c2fbfb3SApril Chin /*
6747c2fbfb3SApril Chin  * set ${.sh.name} and ${.sh.subscript}
6757c2fbfb3SApril Chin  * set _ to reference for ${.sh.name}[$.sh.subscript]
6767c2fbfb3SApril Chin  */
set_instance(Shell_t * shp,Namval_t * nq,Namval_t * node,struct Namref * nr)6773e14f97fSRoger A. Faulkner static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
6787c2fbfb3SApril Chin {
679b30d1939SAndy Fiddaman 	char		*sp=0,*cp;
6807c2fbfb3SApril Chin 	Namarr_t	*ap;
681b30d1939SAndy Fiddaman 	Namval_t	*np;
682b30d1939SAndy Fiddaman 	if(!nv_isattr(nq,NV_MINIMAL|NV_EXPORT|NV_ARRAY) && (np=(Namval_t*)nq->nvenv) && nv_isarray(np))
683b30d1939SAndy Fiddaman 		nq = np;
684b30d1939SAndy Fiddaman 	cp = nv_name(nq);
6857c2fbfb3SApril Chin 	memset(nr,0,sizeof(*nr));
6867c2fbfb3SApril Chin 	nr->np = nq;
687b30d1939SAndy Fiddaman 	nr->root = shp->var_tree;
688b30d1939SAndy Fiddaman 	nr->table = shp->last_table;
689b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
690b30d1939SAndy Fiddaman 	if(!nr->table && shp->namespace)
691b30d1939SAndy Fiddaman 		nr->table = shp->namespace;
692b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
6933e14f97fSRoger A. Faulkner 	shp->instance = 1;
69434f9b3eeSRoland Mainz 	if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
69534f9b3eeSRoland Mainz 		sp = strdup(sp);
6963e14f97fSRoger A. Faulkner 	shp->instance = 0;
697b30d1939SAndy Fiddaman 	if(shp->var_tree!=shp->var_base && !nv_search((char*)nq,nr->root,HASH_BUCKET|HASH_NOSCOPE))
698b30d1939SAndy Fiddaman 	{
699b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
700b30d1939SAndy Fiddaman 		nr->root = shp->namespace?nv_dict(shp->namespace):shp->var_base;
701b30d1939SAndy Fiddaman #else
702b30d1939SAndy Fiddaman 		nr->root = shp->var_base;
703b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
704b30d1939SAndy Fiddaman 	}
7057c2fbfb3SApril Chin 	nv_putval(SH_NAMENOD, cp, NV_NOFREE);
7067c2fbfb3SApril Chin 	memcpy(node,L_ARGNOD,sizeof(*node));
7077c2fbfb3SApril Chin 	L_ARGNOD->nvalue.nrp = nr;
7087c2fbfb3SApril Chin 	L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
7097c2fbfb3SApril Chin 	L_ARGNOD->nvfun = 0;
7107c2fbfb3SApril Chin 	L_ARGNOD->nvenv = 0;
71134f9b3eeSRoland Mainz 	if(sp)
7127c2fbfb3SApril Chin 	{
71334f9b3eeSRoland Mainz 		nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE);
7147c2fbfb3SApril Chin 		return(ap->nelem&ARRAY_SCAN);
7157c2fbfb3SApril Chin 	}
7167c2fbfb3SApril Chin 	return(0);
7177c2fbfb3SApril Chin }
7187c2fbfb3SApril Chin 
unset_instance(Namval_t * nq,Namval_t * node,struct Namref * nr,long mode)7197c2fbfb3SApril Chin static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
7207c2fbfb3SApril Chin {
7217c2fbfb3SApril Chin 	L_ARGNOD->nvalue.nrp = node->nvalue.nrp;
7227c2fbfb3SApril Chin 	L_ARGNOD->nvflag = node->nvflag;
7237c2fbfb3SApril Chin 	L_ARGNOD->nvfun = node->nvfun;
7247c2fbfb3SApril Chin 	if(nr->sub)
7257c2fbfb3SApril Chin 	{
726b30d1939SAndy Fiddaman 		nv_putsub(nr->np, nr->sub, mode);
7277c2fbfb3SApril Chin 		free((void*)nr->sub);
7287c2fbfb3SApril Chin 	}
729b30d1939SAndy Fiddaman 	_nv_unset(SH_NAMENOD,0);
730b30d1939SAndy Fiddaman 	_nv_unset(SH_SUBSCRNOD,0);
731b30d1939SAndy Fiddaman }
732b30d1939SAndy Fiddaman 
733b30d1939SAndy Fiddaman #if SHOPT_COSHELL
734b30d1939SAndy Fiddaman uintmax_t	coused;
735b30d1939SAndy Fiddaman /*
736b30d1939SAndy Fiddaman  * print out function definition
737b30d1939SAndy Fiddaman  */
print_fun(register Namval_t * np,void * data)738b30d1939SAndy Fiddaman static void print_fun(register Namval_t* np, void *data)
739b30d1939SAndy Fiddaman {
740b30d1939SAndy Fiddaman 	register char *format;
741b30d1939SAndy Fiddaman 	NOT_USED(data);
742b30d1939SAndy Fiddaman 	if(!is_afunction(np) || !np->nvalue.ip)
743b30d1939SAndy Fiddaman 		return;
744b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_FPOSIX))
745b30d1939SAndy Fiddaman 		format="%s()\n{ ";
746b30d1939SAndy Fiddaman 	else
747b30d1939SAndy Fiddaman 		format="function %s\n{ ";
748b30d1939SAndy Fiddaman 	sfprintf(sfstdout,format,nv_name(np));
749b30d1939SAndy Fiddaman 	sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0);
750b30d1939SAndy Fiddaman 	sfwrite(sfstdout,"}\n",2);
751b30d1939SAndy Fiddaman }
752b30d1939SAndy Fiddaman 
sh_coinit(Shell_t * shp,char ** argv)753b30d1939SAndy Fiddaman static void *sh_coinit(Shell_t *shp,char **argv)
754b30d1939SAndy Fiddaman {
755b30d1939SAndy Fiddaman 	struct cosh	*csp = job.colist;
756b30d1939SAndy Fiddaman 	const char 	*name = argv?argv[0]:0;
757b30d1939SAndy Fiddaman 	int  		id, open=1;
758b30d1939SAndy Fiddaman 	if(!name)
759b30d1939SAndy Fiddaman 		return(0);
760b30d1939SAndy Fiddaman 	if(*name=='-')
761b30d1939SAndy Fiddaman 	{
762b30d1939SAndy Fiddaman 		name++;
763b30d1939SAndy Fiddaman 		open=0;
764b30d1939SAndy Fiddaman 	}
765b30d1939SAndy Fiddaman 	nv_open(name,shp->var_tree,NV_IDENT|NV_NOADD);
766b30d1939SAndy Fiddaman 	while(csp)
767b30d1939SAndy Fiddaman 	{
768b30d1939SAndy Fiddaman 		if(strcmp(name,csp->name)==0)
769b30d1939SAndy Fiddaman 		{
770b30d1939SAndy Fiddaman 			if(open)
771b30d1939SAndy Fiddaman 			{
772b30d1939SAndy Fiddaman 				coattr(csp->coshell,argv[1]);
773b30d1939SAndy Fiddaman 				return((void*)csp);
774b30d1939SAndy Fiddaman 			}
775b30d1939SAndy Fiddaman 			coclose(csp->coshell);
776b30d1939SAndy Fiddaman 			return(0);
777b30d1939SAndy Fiddaman 		}
778b30d1939SAndy Fiddaman 		csp = csp->next;
779b30d1939SAndy Fiddaman 	}
780b30d1939SAndy Fiddaman 	if(!open)
781b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),"%s: unknown namespace",name);
782b30d1939SAndy Fiddaman 	environ[0][2]=0;
783b30d1939SAndy Fiddaman 	csp = newof(0,struct cosh,1,strlen(name)+1);
784b30d1939SAndy Fiddaman 	if(!(csp->coshell = coopen(NULL,CO_SHELL|CO_SILENT,argv[1])))
785b30d1939SAndy Fiddaman 	{
786b30d1939SAndy Fiddaman 		free((void*)csp);
787b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),"%s: unable to create namespace",name);
788b30d1939SAndy Fiddaman 	}
789b30d1939SAndy Fiddaman 	csp->coshell->data = (void*)csp;
790b30d1939SAndy Fiddaman 	csp->name = (char*)(csp+1);
791b30d1939SAndy Fiddaman 	strcpy(csp->name,name);
792b30d1939SAndy Fiddaman 	for(id=0; coused&(1<<id); id++);
793b30d1939SAndy Fiddaman 	coused |= (1<<id);
794b30d1939SAndy Fiddaman 	csp->id = id;
795b30d1939SAndy Fiddaman 	csp->next = job.colist;
796b30d1939SAndy Fiddaman 	job.colist = csp;
797b30d1939SAndy Fiddaman 	return((void*)csp);
7987c2fbfb3SApril Chin }
799da2e3ebdSchin 
sh_coaddfile(Shell_t * shp,char * name)800b30d1939SAndy Fiddaman int sh_coaddfile(Shell_t *shp, char *name)
801b30d1939SAndy Fiddaman {
802b30d1939SAndy Fiddaman 	Namval_t *np = dtmatch(shp->inpool,name);
803b30d1939SAndy Fiddaman 	if(!np)
804b30d1939SAndy Fiddaman 	{
805b30d1939SAndy Fiddaman 		np = (Namval_t*)stakalloc(sizeof(Dtlink_t)+sizeof(char*));
806b30d1939SAndy Fiddaman 		np->nvname = name;
807b30d1939SAndy Fiddaman 		(Namval_t*)dtinsert(shp->inpool,np);
808b30d1939SAndy Fiddaman 		shp->poolfiles++;
809b30d1939SAndy Fiddaman 		return(1);
810b30d1939SAndy Fiddaman 	}
811b30d1939SAndy Fiddaman 	return(0);
812b30d1939SAndy Fiddaman }
813b30d1939SAndy Fiddaman 
sh_coexec(Shell_t * shp,const Shnode_t * t,int filt)814b30d1939SAndy Fiddaman static int sh_coexec(Shell_t *shp,const Shnode_t *t, int filt)
815b30d1939SAndy Fiddaman {
816b30d1939SAndy Fiddaman 	struct cosh	*csp = ((struct cosh*)shp->coshell);
817b30d1939SAndy Fiddaman 	Cojob_t		*cjp;
818b30d1939SAndy Fiddaman 	char		*str,*trap,host[PATH_MAX];
819b30d1939SAndy Fiddaman 	int		lineno,sig,trace = sh_isoption(SH_XTRACE);
820b30d1939SAndy Fiddaman 	int		verbose = sh_isoption(SH_VERBOSE);
821b30d1939SAndy Fiddaman 	sh_offoption(SH_XTRACE);
822b30d1939SAndy Fiddaman 	sh_offoption(SH_VERBOSE);
823b30d1939SAndy Fiddaman 	if(!shp->strbuf2)
824b30d1939SAndy Fiddaman 		shp->strbuf2 = sfstropen();
825b30d1939SAndy Fiddaman 	sfswap(shp->strbuf2,sfstdout);
826b30d1939SAndy Fiddaman 	sh_trap("typeset -p\nprint cd \"$PWD\"\nprint .sh.dollar=$$\nprint umask $(umask)",0);
827b30d1939SAndy Fiddaman 	for(sig=shp->st.trapmax;--sig>0;)
828b30d1939SAndy Fiddaman 	{
829b30d1939SAndy Fiddaman 		if((trap=shp->st.trapcom[sig]) && *trap==0)
830b30d1939SAndy Fiddaman 			sfprintf(sfstdout,"trap '' %d\n",sig);
831b30d1939SAndy Fiddaman 	}
832b30d1939SAndy Fiddaman 	if(t->tre.tretyp==TFIL)
833b30d1939SAndy Fiddaman 		lineno = ((struct forknod*)t->lst.lstlef)->forkline;
834b30d1939SAndy Fiddaman 	else
835b30d1939SAndy Fiddaman 		lineno = t->fork.forkline;
836b30d1939SAndy Fiddaman 	if(filt)
837b30d1939SAndy Fiddaman 	{
838b30d1939SAndy Fiddaman 		if(gethostname(host,sizeof(host)) < 0)
839b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_system(1),e_pipe);
840b30d1939SAndy Fiddaman 		if(shp->inpipe[2]>=20000)
841b30d1939SAndy Fiddaman 			sfprintf(sfstdout,"command exec < /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->inpipe[2]);
842b30d1939SAndy Fiddaman 		sfprintf(sfstdout,"command exec > /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->outpipe[2]);
843b30d1939SAndy Fiddaman 		if(filt==3)
844b30d1939SAndy Fiddaman 			t = t->fork.forktre;
845b30d1939SAndy Fiddaman 	}
846b30d1939SAndy Fiddaman 	else
847b30d1939SAndy Fiddaman 		t = t->fork.forktre;
848b30d1939SAndy Fiddaman 	nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
849b30d1939SAndy Fiddaman 	if(1)
850b30d1939SAndy Fiddaman 	{
851b30d1939SAndy Fiddaman 		Dt_t *top = shp->var_tree;
852b30d1939SAndy Fiddaman 		sh_scope(shp,(struct argnod*)0,0);
853b30d1939SAndy Fiddaman 		shp->inpool = dtopen(&_Nvdisc,Dtset);
854b30d1939SAndy Fiddaman 		sh_exec(t,filt==1||filt==2?SH_NOFORK:0);
855b30d1939SAndy Fiddaman 		if(shp->poolfiles)
856b30d1939SAndy Fiddaman 		{
857b30d1939SAndy Fiddaman 			Namval_t *np;
858b30d1939SAndy Fiddaman 			sfprintf(sfstdout,"[[ ${.sh} == *pool* ]] && .sh.pool.files=(\n");
859b30d1939SAndy Fiddaman 			for(np=(Namval_t*)dtfirst(shp->inpool);np;np=(Namval_t*)dtnext(shp->inpool,np))
860b30d1939SAndy Fiddaman 			{
861b30d1939SAndy Fiddaman 				sfprintf(sfstdout,"\t%s\n",sh_fmtq(np->nvname));
862b30d1939SAndy Fiddaman 			}
863b30d1939SAndy Fiddaman 			sfputr(sfstdout,")",'\n');
864b30d1939SAndy Fiddaman 			;
865b30d1939SAndy Fiddaman 		}
866b30d1939SAndy Fiddaman 		dtclose(shp->inpool);
867b30d1939SAndy Fiddaman 		shp->inpool = 0;
868b30d1939SAndy Fiddaman 		shp->poolfiles = 0;
869b30d1939SAndy Fiddaman 		sh_unscope(shp);
870b30d1939SAndy Fiddaman 		shp->var_tree = top;
871b30d1939SAndy Fiddaman 	}
872b30d1939SAndy Fiddaman 	sfprintf(sfstdout,"typeset -f .sh.pool.init && .sh.pool.init\n");
873b30d1939SAndy Fiddaman 	sfprintf(sfstdout,"LINENO=%d\n",lineno);
874b30d1939SAndy Fiddaman 	if(trace)
875b30d1939SAndy Fiddaman 		sh_onoption(SH_XTRACE);
876b30d1939SAndy Fiddaman 	if(verbose)
877b30d1939SAndy Fiddaman 		sh_onoption(SH_VERBOSE);
878b30d1939SAndy Fiddaman 	sh_trap("set +o",0);
879b30d1939SAndy Fiddaman 	sh_deparse(sfstdout,t,filt==1||filt==2?FALTPIPE:0);
880b30d1939SAndy Fiddaman 	sfputc(sfstdout,0);
881b30d1939SAndy Fiddaman 	sfswap(shp->strbuf2,sfstdout);
882b30d1939SAndy Fiddaman 	str = sfstruse(shp->strbuf2);
883b30d1939SAndy Fiddaman 	if(cjp=coexec(csp->coshell,str,0,NULL,NULL,NULL))
884b30d1939SAndy Fiddaman 	{
885b30d1939SAndy Fiddaman 		csp->cojob = cjp;
886b30d1939SAndy Fiddaman 		cjp->local = shp->coshell;
887b30d1939SAndy Fiddaman 		if(filt)
888b30d1939SAndy Fiddaman 		{
889b30d1939SAndy Fiddaman 			if(filt>1)
890b30d1939SAndy Fiddaman 				sh_coaccept(shp,shp->inpipe,1);
891b30d1939SAndy Fiddaman 			sh_coaccept(shp,shp->outpipe,0);
892b30d1939SAndy Fiddaman 			if(filt > 2)
893b30d1939SAndy Fiddaman 			{
894b30d1939SAndy Fiddaman 				shp->coutpipe = shp->inpipe[1];
895b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, shp->coutpipe);
896b30d1939SAndy Fiddaman 				shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
897b30d1939SAndy Fiddaman 			}
898b30d1939SAndy Fiddaman 		}
899b30d1939SAndy Fiddaman 		return(sh_copid(csp));
900b30d1939SAndy Fiddaman 	}
901b30d1939SAndy Fiddaman 	return(-1);
902b30d1939SAndy Fiddaman }
903b30d1939SAndy Fiddaman #endif /*SHOPT_COSHELL*/
904b30d1939SAndy Fiddaman 
905b30d1939SAndy Fiddaman #if SHOPT_FILESCAN
openstream(Shell_t * shp,struct ionod * iop,int * save)906b30d1939SAndy Fiddaman     static Sfio_t *openstream(Shell_t *shp, struct ionod *iop, int *save)
907b30d1939SAndy Fiddaman     {
908b30d1939SAndy Fiddaman 	int savein, fd = sh_redirect(shp,iop,3);
909b30d1939SAndy Fiddaman 	Sfio_t	*sp;
910b30d1939SAndy Fiddaman 	savein = dup(0);
911b30d1939SAndy Fiddaman 	if(fd==0)
912b30d1939SAndy Fiddaman 		fd = savein;
913b30d1939SAndy Fiddaman 	sp = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
914b30d1939SAndy Fiddaman 	close(0);
915b30d1939SAndy Fiddaman 	open(e_devnull,O_RDONLY);
916b30d1939SAndy Fiddaman 	shp->offsets[0] = -1;
917b30d1939SAndy Fiddaman 	shp->offsets[1] = 0;
918b30d1939SAndy Fiddaman 	*save = savein;
919b30d1939SAndy Fiddaman 	return(sp);
920b30d1939SAndy Fiddaman     }
921b30d1939SAndy Fiddaman #endif /* SHOPT_FILESCAN */
922b30d1939SAndy Fiddaman 
923b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
enter_namespace(Shell_t * shp,Namval_t * nsp)924b30d1939SAndy Fiddaman static Namval_t *enter_namespace(Shell_t *shp, Namval_t *nsp)
925b30d1939SAndy Fiddaman {
926b30d1939SAndy Fiddaman 	Namval_t	*path=nsp, *fpath=nsp, *onsp=shp->namespace;
927b30d1939SAndy Fiddaman 	Dt_t		*root=0,*oroot=0;
928b30d1939SAndy Fiddaman 	char		*val;
929b30d1939SAndy Fiddaman 	if(nsp)
930b30d1939SAndy Fiddaman 	{
931b30d1939SAndy Fiddaman 		if(!nv_istable(nsp))
932b30d1939SAndy Fiddaman 			nsp = 0;
933b30d1939SAndy Fiddaman 		else if(nv_dict(nsp)->view!=shp->var_base)
934b30d1939SAndy Fiddaman 			return(onsp);
935b30d1939SAndy Fiddaman 	}
936b30d1939SAndy Fiddaman 	if(!nsp && !onsp)
937b30d1939SAndy Fiddaman 		return(0);
938b30d1939SAndy Fiddaman 	if(onsp == nsp)
939b30d1939SAndy Fiddaman 		return(nsp);
940b30d1939SAndy Fiddaman 	if(onsp)
941b30d1939SAndy Fiddaman 	{
942b30d1939SAndy Fiddaman 		oroot = nv_dict(onsp);
943b30d1939SAndy Fiddaman 		if(!nsp)
944b30d1939SAndy Fiddaman 		{
945b30d1939SAndy Fiddaman 			path = nv_search(PATHNOD->nvname,oroot,HASH_NOSCOPE);
946b30d1939SAndy Fiddaman 			fpath = nv_search(FPATHNOD->nvname,oroot,HASH_NOSCOPE);
947b30d1939SAndy Fiddaman 		}
948b30d1939SAndy Fiddaman 		if(shp->var_tree==oroot)
949b30d1939SAndy Fiddaman 		{
950b30d1939SAndy Fiddaman 			shp->var_tree = shp->var_tree->view;
951b30d1939SAndy Fiddaman 			oroot = shp->var_base;
952b30d1939SAndy Fiddaman 		}
953b30d1939SAndy Fiddaman 	}
954b30d1939SAndy Fiddaman 	if(nsp)
955b30d1939SAndy Fiddaman 	{
956b30d1939SAndy Fiddaman 		if(shp->var_tree==shp->var_base)
957b30d1939SAndy Fiddaman 			shp->var_tree = nv_dict(nsp);
958b30d1939SAndy Fiddaman 		else
959b30d1939SAndy Fiddaman 		{
960b30d1939SAndy Fiddaman 			for(root=shp->var_tree; root->view!=oroot;root=root->view);
961b30d1939SAndy Fiddaman 			dtview(root,nv_dict(nsp));
962b30d1939SAndy Fiddaman 		}
963b30d1939SAndy Fiddaman 	}
964b30d1939SAndy Fiddaman 	shp->namespace = nsp;
965b30d1939SAndy Fiddaman 	if(path && (path = nv_search(PATHNOD->nvname,shp->var_tree,HASH_NOSCOPE)) && (val=nv_getval(path)))
966b30d1939SAndy Fiddaman 		nv_putval(path,val,NV_RDONLY);
967b30d1939SAndy Fiddaman 	if(fpath && (fpath = nv_search(FPATHNOD->nvname,shp->var_tree,HASH_NOSCOPE)) && (val=nv_getval(fpath)))
968b30d1939SAndy Fiddaman 		nv_putval(fpath,val,NV_RDONLY);
969b30d1939SAndy Fiddaman 	return(onsp);
970b30d1939SAndy Fiddaman }
971b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
972b30d1939SAndy Fiddaman 
sh_exec(register const Shnode_t * t,int flags)973da2e3ebdSchin int sh_exec(register const Shnode_t *t, int flags)
974da2e3ebdSchin {
975b30d1939SAndy Fiddaman 	register Shell_t	*shp = sh_getinterp();
9767c2fbfb3SApril Chin 	Stk_t			*stkp = shp->stk;
977b30d1939SAndy Fiddaman 	int			unpipe=0;
978b30d1939SAndy Fiddaman 	sh_sigcheck(shp);
9797c2fbfb3SApril Chin 	if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
980da2e3ebdSchin 	{
981da2e3ebdSchin 		register int 	type = flags;
982da2e3ebdSchin 		register char	*com0 = 0;
983da2e3ebdSchin 		int 		errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE;
984da2e3ebdSchin 		int 		execflg = (type&sh_state(SH_NOFORK));
98534f9b3eeSRoland Mainz 		int 		execflg2 = (type&sh_state(SH_FORKED));
986da2e3ebdSchin 		int 		mainloop = (type&sh_state(SH_INTERACTIVE));
9877c2fbfb3SApril Chin #if SHOPT_AMP || SHOPT_SPAWN
988da2e3ebdSchin 		int		ntflag = (type&sh_state(SH_NTFORK));
98934f9b3eeSRoland Mainz #else
99034f9b3eeSRoland Mainz 		int		ntflag = 0;
991da2e3ebdSchin #endif
9927c2fbfb3SApril Chin 		int		topfd = shp->topfd;
9933636ae54SAndy Fiddaman 		char 		*sav=stkfreeze(stkp,0);
9947c2fbfb3SApril Chin 		char		*cp=0, **com=0, *comn;
995da2e3ebdSchin 		int		argn;
996da2e3ebdSchin 		int 		skipexitset = 0;
997b30d1939SAndy Fiddaman 		volatile int	was_interactive = 0;
998b30d1939SAndy Fiddaman 		volatile int	was_errexit = sh_isstate(SH_ERREXIT);
999b30d1939SAndy Fiddaman 		volatile int	was_monitor = sh_isstate(SH_MONITOR);
1000b30d1939SAndy Fiddaman 		volatile int	echeck = 0;
1001da2e3ebdSchin 		if(flags&sh_state(SH_INTERACTIVE))
1002da2e3ebdSchin 		{
100334f9b3eeSRoland Mainz 			if(pipejob==2)
100434f9b3eeSRoland Mainz 				job_unlock();
1005b30d1939SAndy Fiddaman 			nlock = 0;
1006da2e3ebdSchin 			pipejob = 0;
1007da2e3ebdSchin 			job.curpgid = 0;
1008b30d1939SAndy Fiddaman 			job.curjobid = 0;
1009da2e3ebdSchin 			flags &= ~sh_state(SH_INTERACTIVE);
1010da2e3ebdSchin 		}
1011da2e3ebdSchin 		sh_offstate(SH_ERREXIT);
1012da2e3ebdSchin 		sh_offstate(SH_DEFPATH);
1013da2e3ebdSchin 		if(was_errexit&flags)
1014da2e3ebdSchin 			sh_onstate(SH_ERREXIT);
1015da2e3ebdSchin 		if(was_monitor&flags)
1016da2e3ebdSchin 			sh_onstate(SH_MONITOR);
1017da2e3ebdSchin 		type = t->tre.tretyp;
10187c2fbfb3SApril Chin 		if(!shp->intrap)
10197c2fbfb3SApril Chin 			shp->oldexit=shp->exitval;
10207c2fbfb3SApril Chin 		shp->exitval=0;
10217c2fbfb3SApril Chin 		shp->lastsig = 0;
10227c2fbfb3SApril Chin 		shp->lastpath = 0;
1023b30d1939SAndy Fiddaman 		if(shp->exittrap || shp->errtrap)
1024b30d1939SAndy Fiddaman 			execflg = 0;
1025da2e3ebdSchin 		switch(type&COMMSK)
1026da2e3ebdSchin 		{
1027da2e3ebdSchin 		    case TCOM:
1028da2e3ebdSchin 		    {
1029da2e3ebdSchin 			register struct argnod	*argp;
1030da2e3ebdSchin 			char		*trap;
1031da2e3ebdSchin 			Namval_t	*np, *nq, *last_table;
1032da2e3ebdSchin 			struct ionod	*io;
10337c2fbfb3SApril Chin 			int		command=0, flgs=NV_ASSIGN;
10347c2fbfb3SApril Chin 			shp->bltindata.invariant = type>>(COMBITS+2);
10357c2fbfb3SApril Chin 			type &= (COMMSK|COMSCAN);
10367c2fbfb3SApril Chin 			sh_stats(STAT_SCMDS);
10377c2fbfb3SApril Chin 			error_info.line = t->com.comline-shp->st.firstline;
10387c2fbfb3SApril Chin 			com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE);
1039da2e3ebdSchin 			echeck = 1;
1040da2e3ebdSchin 			if(t->tre.tretyp&COMSCAN)
1041da2e3ebdSchin 			{
1042da2e3ebdSchin 				argp = t->com.comarg;
1043da2e3ebdSchin 				if(argp && *com && !(argp->argflag&ARG_RAW))
1044b30d1939SAndy Fiddaman 					sh_sigcheck(shp);
1045da2e3ebdSchin 			}
1046da2e3ebdSchin 			np = (Namval_t*)(t->com.comnamp);
1047da2e3ebdSchin 			nq = (Namval_t*)(t->com.comnamq);
1048b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1049b30d1939SAndy Fiddaman 			if(np && shp->namespace && nq!=shp->namespace && nv_isattr(np,NV_BLTIN|NV_INTEGER|BLT_SPC)!=(NV_BLTIN|BLT_SPC))
1050b30d1939SAndy Fiddaman 			{
1051b30d1939SAndy Fiddaman 				Namval_t *mp;
1052b30d1939SAndy Fiddaman 				if(mp = sh_fsearch(shp,com[0],0))
1053b30d1939SAndy Fiddaman 				{
1054b30d1939SAndy Fiddaman 					nq = shp->namespace;
1055b30d1939SAndy Fiddaman 					np = mp;
1056b30d1939SAndy Fiddaman 				}
1057b30d1939SAndy Fiddaman 			}
1058b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1059da2e3ebdSchin 			com0 = com[0];
10607c2fbfb3SApril Chin 			shp->xargexit = 0;
1061da2e3ebdSchin 			while(np==SYSCOMMAND)
1062da2e3ebdSchin 			{
10637c2fbfb3SApril Chin 				register int n = b_command(0,com,&shp->bltindata);
1064da2e3ebdSchin 				if(n==0)
1065da2e3ebdSchin 					break;
1066da2e3ebdSchin 				command += n;
1067da2e3ebdSchin 				np = 0;
1068da2e3ebdSchin 				if(!(com0= *(com+=n)))
1069da2e3ebdSchin 					break;
10707c2fbfb3SApril Chin 				np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
1071da2e3ebdSchin 			}
10727c2fbfb3SApril Chin 			if(shp->xargexit)
1073da2e3ebdSchin 			{
10747c2fbfb3SApril Chin 				shp->xargmin -= command;
10757c2fbfb3SApril Chin 				shp->xargmax -= command;
1076da2e3ebdSchin 			}
1077da2e3ebdSchin 			else
10787c2fbfb3SApril Chin 				shp->xargmin = 0;
1079da2e3ebdSchin 			argn -= command;
1080b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1081b30d1939SAndy Fiddaman 			if(argn && shp->inpool)
1082b30d1939SAndy Fiddaman 			{
1083b30d1939SAndy Fiddaman 				if(io=t->tre.treio)
1084b30d1939SAndy Fiddaman 					sh_redirect(shp,io,0);
1085b30d1939SAndy Fiddaman 				if(!np || !is_abuiltin(np) || *np->nvname=='/' || np==SYSCD)
1086b30d1939SAndy Fiddaman 				{
1087b30d1939SAndy Fiddaman 					char **argv, *cp;
1088b30d1939SAndy Fiddaman 					for(argv=com+1; cp= *argv; argv++)
1089b30d1939SAndy Fiddaman 					{
1090b30d1939SAndy Fiddaman 						if(cp && *cp && *cp!='-')
1091b30d1939SAndy Fiddaman 							sh_coaddfile(shp,*argv);
1092b30d1939SAndy Fiddaman 					}
1093b30d1939SAndy Fiddaman 					break;
1094b30d1939SAndy Fiddaman 				}
1095b30d1939SAndy Fiddaman 				if(np->nvalue.bfp!=SYSTYPESET->nvalue.bfp)
1096b30d1939SAndy Fiddaman 					break;
1097b30d1939SAndy Fiddaman 			}
1098b30d1939SAndy Fiddaman 			if(t->tre.tretyp&FAMP)
1099b30d1939SAndy Fiddaman 			{
1100b30d1939SAndy Fiddaman 				shp->coshell = sh_coinit(shp,com);
1101b30d1939SAndy Fiddaman 				com0 = 0;
1102b30d1939SAndy Fiddaman 				break;
1103b30d1939SAndy Fiddaman 			}
1104b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1105b30d1939SAndy Fiddaman 			if(np && is_abuiltin(np))
1106b30d1939SAndy Fiddaman 			{
1107b30d1939SAndy Fiddaman 				if(!command)
1108b30d1939SAndy Fiddaman 				{
1109b30d1939SAndy Fiddaman 					Namval_t *mp;
1110b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1111b30d1939SAndy Fiddaman 					if(shp->namespace && (mp=sh_fsearch(shp,np->nvname,0)))
1112b30d1939SAndy Fiddaman 						np = mp;
1113b30d1939SAndy Fiddaman 					else
1114b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1115b30d1939SAndy Fiddaman 					np = dtsearch(shp->fun_tree,np);
1116b30d1939SAndy Fiddaman 				}
1117b30d1939SAndy Fiddaman #if SHOPT_PFSH
1118b30d1939SAndy Fiddaman 				if(sh_isoption(SH_PFSH) && nv_isattr(np,NV_BLTINOPT) && !nv_isattr(np,NV_BLTPFSH))
1119b30d1939SAndy Fiddaman 				{
1120b30d1939SAndy Fiddaman 					if(path_xattr(shp,np->nvname,(char*)0))
1121b30d1939SAndy Fiddaman 					{
1122b30d1939SAndy Fiddaman 						dtdelete(shp->bltin_tree,np);
1123b30d1939SAndy Fiddaman 						np = 0;
1124b30d1939SAndy Fiddaman 					}
1125b30d1939SAndy Fiddaman 					else
1126b30d1939SAndy Fiddaman 						nv_onattr(np,NV_BLTPFSH);
1127b30d1939SAndy Fiddaman 
1128b30d1939SAndy Fiddaman 				}
1129b30d1939SAndy Fiddaman #endif /* SHOPT_PFSH */
1130b30d1939SAndy Fiddaman 			}
11317c2fbfb3SApril Chin 			if(com0)
1132da2e3ebdSchin 			{
11337c2fbfb3SApril Chin 				if(!np && !strchr(com0,'/'))
1134da2e3ebdSchin 				{
11357c2fbfb3SApril Chin 					Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
11367c2fbfb3SApril Chin 					np = nv_bfsearch(com0, root, &nq, &cp);
11377c2fbfb3SApril Chin #if SHOPT_NAMESPACE
11387c2fbfb3SApril Chin 					if(shp->namespace && !nq && !cp)
1139b30d1939SAndy Fiddaman 						np = sh_fsearch(shp,com0,0);
1140da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
11417c2fbfb3SApril Chin 				}
11427c2fbfb3SApril Chin 				comn = com[argn-1];
1143da2e3ebdSchin 			}
1144da2e3ebdSchin 			io = t->tre.treio;
11457c2fbfb3SApril Chin 			if(shp->envlist = argp = t->com.comset)
1146da2e3ebdSchin 			{
1147b30d1939SAndy Fiddaman 				if(argn==0 || (np && nv_isattr(np,(BLT_DCL|BLT_SPC))))
1148da2e3ebdSchin 				{
114934f9b3eeSRoland Mainz 					Namval_t *tp=0;
11507c2fbfb3SApril Chin 					if(argn)
11517c2fbfb3SApril Chin 					{
11527c2fbfb3SApril Chin 						if(checkopt(com,'A'))
11537c2fbfb3SApril Chin 							flgs |= NV_ARRAY;
11547c2fbfb3SApril Chin 						else if(checkopt(com,'a'))
11557c2fbfb3SApril Chin 							flgs |= NV_IARRAY;
11567c2fbfb3SApril Chin 					}
1157b30d1939SAndy Fiddaman 					if(np)
1158b30d1939SAndy Fiddaman 						flgs |= NV_UNJUST;
1159da2e3ebdSchin #if SHOPT_BASH
1160da2e3ebdSchin 					if(np==SYSLOCAL)
1161da2e3ebdSchin 					{
1162da2e3ebdSchin 						if(!nv_getval(SH_FUNNAMENOD))
1163da2e3ebdSchin 							errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
11647c2fbfb3SApril Chin 						if(!shp->st.var_local)
1165da2e3ebdSchin 						{
11667c2fbfb3SApril Chin 							sh_scope(shp,(struct argnod*)0,0);
11677c2fbfb3SApril Chin 							shp->st.var_local = shp->var_tree;
1168da2e3ebdSchin 						}
1169da2e3ebdSchin 
1170da2e3ebdSchin 					}
1171b30d1939SAndy Fiddaman #endif /* SHOPT_BASH */
11727c2fbfb3SApril Chin 					if(np==SYSTYPESET ||  (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
1173da2e3ebdSchin 					{
11747c2fbfb3SApril Chin 						if(np!=SYSTYPESET)
117534f9b3eeSRoland Mainz 						{
11767c2fbfb3SApril Chin 							shp->typeinit = np;
117734f9b3eeSRoland Mainz 							tp = nv_type(np);
117834f9b3eeSRoland Mainz 						}
11797c2fbfb3SApril Chin 						if(checkopt(com,'C'))
11807c2fbfb3SApril Chin 							flgs |= NV_COMVAR;
11817c2fbfb3SApril Chin 						if(checkopt(com,'S'))
11827c2fbfb3SApril Chin 							flgs |= NV_STATIC;
1183b30d1939SAndy Fiddaman 						if(checkopt(com,'m'))
1184b30d1939SAndy Fiddaman 							flgs |= NV_MOVE;
1185da2e3ebdSchin 						if(checkopt(com,'n'))
1186da2e3ebdSchin 							flgs |= NV_NOREF;
1187da2e3ebdSchin #if SHOPT_TYPEDEF
11887c2fbfb3SApril Chin 						else if(argn>=3 && checkopt(com,'T'))
1189da2e3ebdSchin 						{
1190b30d1939SAndy Fiddaman #   if SHOPT_NAMESPACE
1191b30d1939SAndy Fiddaman 							if(shp->namespace)
1192b30d1939SAndy Fiddaman 							{
1193b30d1939SAndy Fiddaman 								if(!shp->strbuf2)
1194b30d1939SAndy Fiddaman 									shp->strbuf2 = sfstropen();
1195b30d1939SAndy Fiddaman 								sfprintf(shp->strbuf2,"%s%s%c",NV_CLASS,nv_name(shp->namespace),0);
1196b30d1939SAndy Fiddaman 								shp->prefix = strdup(sfstruse(shp->strbuf2));
1197b30d1939SAndy Fiddaman 								nv_open(shp->prefix,shp->var_base,NV_VARNAME);
1198b30d1939SAndy Fiddaman 							}
1199b30d1939SAndy Fiddaman 							else
1200b30d1939SAndy Fiddaman #   endif /* SHOPT_NAMESPACE */
12017c2fbfb3SApril Chin 							shp->prefix = NV_CLASS;
1202da2e3ebdSchin 							flgs |= NV_TYPE;
1203da2e3ebdSchin 
1204da2e3ebdSchin 						}
1205da2e3ebdSchin #endif /* SHOPT_TYPEDEF */
12067c2fbfb3SApril Chin 						if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
1207da2e3ebdSchin 							flgs |= NV_NOSCOPE;
1208da2e3ebdSchin 					}
1209da2e3ebdSchin 					else if(np==SYSEXPORT)
1210da2e3ebdSchin 						flgs |= NV_EXPORT;
12117c2fbfb3SApril Chin 					if(flgs&(NV_EXPORT|NV_NOREF))
12127c2fbfb3SApril Chin 						flgs |= NV_IDENT;
12137c2fbfb3SApril Chin 					else
12147c2fbfb3SApril Chin 						flgs |= NV_VARNAME;
1215da2e3ebdSchin #if 0
1216da2e3ebdSchin 					if(OPTIMIZE)
1217da2e3ebdSchin 						flgs |= NV_TAGGED;
1218da2e3ebdSchin #endif
121934f9b3eeSRoland Mainz 					nv_setlist(argp,flgs,tp);
12207c2fbfb3SApril Chin 					if(np==shp->typeinit)
12217c2fbfb3SApril Chin 						shp->typeinit = 0;
12227c2fbfb3SApril Chin 					shp->envlist = argp;
1223da2e3ebdSchin 					argp = NULL;
1224da2e3ebdSchin 				}
1225da2e3ebdSchin 			}
12267c2fbfb3SApril Chin 			last_table = shp->last_table;
12277c2fbfb3SApril Chin 			shp->last_table = 0;
1228da2e3ebdSchin 			if((io||argn))
1229da2e3ebdSchin 			{
12307c2fbfb3SApril Chin 				Shbltin_t *bp=0;
1231da2e3ebdSchin 				static char *argv[1];
12327c2fbfb3SApril Chin 				int tflags = 1;
12337c2fbfb3SApril Chin 				if(np &&  nv_isattr(np,BLT_DCL))
12347c2fbfb3SApril Chin 					tflags |= 2;
1235da2e3ebdSchin 				if(argn==0)
1236da2e3ebdSchin 				{
1237da2e3ebdSchin 					/* fake 'true' built-in */
1238da2e3ebdSchin 					np = SYSTRUE;
1239da2e3ebdSchin 					*argv = nv_name(np);
1240da2e3ebdSchin 					com = argv;
1241da2e3ebdSchin 				}
1242da2e3ebdSchin 				/* set +x doesn't echo */
1243da2e3ebdSchin 				else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
1244da2e3ebdSchin 				{
1245da2e3ebdSchin 					int ison = sh_isoption(SH_XTRACE);
1246da2e3ebdSchin 					if(!ison)
1247da2e3ebdSchin 						sh_onoption(SH_XTRACE);
1248b30d1939SAndy Fiddaman 					sh_trace(shp,com-command,tflags);
1249da2e3ebdSchin 					if(io)
12507c2fbfb3SApril Chin 						sh_redirect(shp,io,SH_SHOWME);
1251da2e3ebdSchin 					if(!ison)
1252da2e3ebdSchin 						sh_offoption(SH_XTRACE);
1253da2e3ebdSchin 					break;
1254da2e3ebdSchin 				}
1255b30d1939SAndy Fiddaman 				else if((np!=SYSSET) && sh_isoption(SH_XTRACE))
1256b30d1939SAndy Fiddaman 					sh_trace(shp,com-command,tflags);
12577c2fbfb3SApril Chin 				if(trap=shp->st.trap[SH_DEBUGTRAP])
12587c2fbfb3SApril Chin 				{
12597c2fbfb3SApril Chin 					int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
12607c2fbfb3SApril Chin 					if(n==255 && shp->fn_depth+shp->dot_depth)
12617c2fbfb3SApril Chin 					{
12627c2fbfb3SApril Chin 						np = SYSRETURN;
12637c2fbfb3SApril Chin 						argn = 1;
12647c2fbfb3SApril Chin 						com[0] = np->nvname;
12657c2fbfb3SApril Chin 						com[1] = 0;
12667c2fbfb3SApril Chin 						io = 0;
12677c2fbfb3SApril Chin 						argp = 0;
12687c2fbfb3SApril Chin 					}
12697c2fbfb3SApril Chin 					else if(n==2)
12707c2fbfb3SApril Chin 						break;
12717c2fbfb3SApril Chin 				}
1272da2e3ebdSchin 				if(io)
12737c2fbfb3SApril Chin 					sfsync(shp->outpool);
12747c2fbfb3SApril Chin 				shp->lastpath = 0;
1275da2e3ebdSchin 				if(!np  && !strchr(com0,'/'))
1276da2e3ebdSchin 				{
1277b30d1939SAndy Fiddaman 					if(path_search(shp,com0,NIL(Pathcomp_t**),1))
12787c2fbfb3SApril Chin 					{
12797c2fbfb3SApril Chin 						error_info.line = t->com.comline-shp->st.firstline;
1280b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1281b30d1939SAndy Fiddaman 						if(!shp->namespace || !(np=sh_fsearch(shp,com0,0)))
1282b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1283b30d1939SAndy Fiddaman 							np=nv_search(com0,shp->fun_tree,0);
1284b30d1939SAndy Fiddaman 						if(!np || !np->nvalue.ip)
12857c2fbfb3SApril Chin 						{
12867c2fbfb3SApril Chin 							Namval_t *mp=nv_search(com0,shp->bltin_tree,0);
12877c2fbfb3SApril Chin 							if(mp)
12887c2fbfb3SApril Chin 								np = mp;
12897c2fbfb3SApril Chin 						}
12907c2fbfb3SApril Chin 					}
1291da2e3ebdSchin 					else
1292da2e3ebdSchin 					{
12937c2fbfb3SApril Chin 						if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
12947c2fbfb3SApril Chin 							np=nv_search(nv_getval(np),shp->bltin_tree,0);
1295da2e3ebdSchin 						else
1296da2e3ebdSchin 							np = 0;
1297da2e3ebdSchin 					}
1298da2e3ebdSchin 				}
129934f9b3eeSRoland Mainz 				if(np && pipejob==2)
130034f9b3eeSRoland Mainz 				{
130134f9b3eeSRoland Mainz 					job_unlock();
1302b30d1939SAndy Fiddaman 					nlock--;
130334f9b3eeSRoland Mainz 					pipejob = 1;
130434f9b3eeSRoland Mainz 				}
1305da2e3ebdSchin 				/* check for builtins */
1306da2e3ebdSchin 				if(np && is_abuiltin(np))
1307da2e3ebdSchin 				{
13087c2fbfb3SApril Chin 					volatile int scope=0, share=0;
13097c2fbfb3SApril Chin 					volatile void *save_ptr;
13107c2fbfb3SApril Chin 					volatile void *save_data;
13117c2fbfb3SApril Chin 					int jmpval, save_prompt;
131234f9b3eeSRoland Mainz 					int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
1313b30d1939SAndy Fiddaman 					struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1314b30d1939SAndy Fiddaman 					volatile unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
1315da2e3ebdSchin 					struct stat statb;
13167c2fbfb3SApril Chin 					bp = &shp->bltindata;
13177c2fbfb3SApril Chin 					save_ptr = bp->ptr;
13187c2fbfb3SApril Chin 					save_data = bp->data;
13197c2fbfb3SApril Chin 					memset(&statb, 0, sizeof(struct stat));
1320da2e3ebdSchin 					if(strchr(nv_name(np),'/'))
1321da2e3ebdSchin 					{
1322da2e3ebdSchin 						/*
1323da2e3ebdSchin 						 * disable editors for built-in
1324da2e3ebdSchin 						 * versions of commands on PATH
1325da2e3ebdSchin 						 */
1326da2e3ebdSchin 						was_vi = sh_isoption(SH_VI);
1327da2e3ebdSchin 						was_emacs = sh_isoption(SH_EMACS);
1328da2e3ebdSchin 						was_gmacs = sh_isoption(SH_GMACS);
1329da2e3ebdSchin 						sh_offoption(SH_VI);
1330da2e3ebdSchin 						sh_offoption(SH_EMACS);
1331da2e3ebdSchin 						sh_offoption(SH_GMACS);
1332da2e3ebdSchin 					}
133334f9b3eeSRoland Mainz 					if(execflg)
133434f9b3eeSRoland Mainz 						sh_onstate(SH_NOFORK);
1335b30d1939SAndy Fiddaman 					sh_pushcontext(shp,buffp,SH_JMPCMD);
1336b30d1939SAndy Fiddaman 					jmpval = sigsetjmp(buffp->buff,1);
1337da2e3ebdSchin 					if(jmpval == 0)
1338da2e3ebdSchin 					{
1339da2e3ebdSchin 						if(!(nv_isattr(np,BLT_ENV)))
1340da2e3ebdSchin 							error_info.flags |= ERROR_SILENT;
1341b30d1939SAndy Fiddaman 						errorpush(&buffp->err,0);
1342da2e3ebdSchin 						if(io)
1343da2e3ebdSchin 						{
1344da2e3ebdSchin 							struct openlist *item;
1345da2e3ebdSchin 							if(np==SYSLOGIN)
1346da2e3ebdSchin 								type=1;
1347da2e3ebdSchin 							else if(np==SYSEXEC)
1348da2e3ebdSchin 								type=1+!com[1];
1349da2e3ebdSchin 							else
13507c2fbfb3SApril Chin 								type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
1351b30d1939SAndy Fiddaman 							shp->redir0 = 1;
13527c2fbfb3SApril Chin 							sh_redirect(shp,io,type);
1353b30d1939SAndy Fiddaman 							for(item=buffp->olist;item;item=item->next)
1354da2e3ebdSchin 								item->strm=0;
1355da2e3ebdSchin 						}
1356da2e3ebdSchin 						if(!(nv_isattr(np,BLT_ENV)))
1357da2e3ebdSchin 						{
1358b30d1939SAndy Fiddaman 							if(!shp->pwd)
1359b30d1939SAndy Fiddaman 								path_pwd(shp,0);
1360b30d1939SAndy Fiddaman 							if(shp->pwd)
1361b30d1939SAndy Fiddaman 								stat(".",&statb);
13627c2fbfb3SApril Chin 							sfsync(NULL);
1363da2e3ebdSchin 							share = sfset(sfstdin,SF_SHARE,0);
1364da2e3ebdSchin 							sh_onstate(SH_STOPOK);
1365da2e3ebdSchin 							sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
1366da2e3ebdSchin 							sfset(sfstderr,SF_LINE,1);
13677c2fbfb3SApril Chin 							save_prompt = shp->nextprompt;
13687c2fbfb3SApril Chin 							shp->nextprompt = 0;
1369da2e3ebdSchin 						}
1370da2e3ebdSchin 						if(argp)
1371da2e3ebdSchin 						{
1372da2e3ebdSchin 							scope++;
13737c2fbfb3SApril Chin 							sh_scope(shp,argp,0);
1374da2e3ebdSchin 						}
1375da2e3ebdSchin 						opt_info.index = opt_info.offset = 0;
1376da2e3ebdSchin 						opt_info.disc = 0;
1377da2e3ebdSchin 						error_info.id = *com;
13787c2fbfb3SApril Chin 						if(argn)
13797c2fbfb3SApril Chin 							shp->exitval = 0;
1380b30d1939SAndy Fiddaman 						shp->bltinfun = (Shbltin_f)funptr(np);
13817c2fbfb3SApril Chin 						bp->bnode = np;
13827c2fbfb3SApril Chin 						bp->vnode = nq;
13837c2fbfb3SApril Chin 						bp->ptr = nv_context(np);
13847c2fbfb3SApril Chin 						bp->data = t->com.comstate;
13857c2fbfb3SApril Chin 						bp->sigset = 0;
13867c2fbfb3SApril Chin 						bp->notify = 0;
13877c2fbfb3SApril Chin 						bp->flags = (OPTIMIZE!=0);
13887c2fbfb3SApril Chin 						if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
1389b30d1939SAndy Fiddaman 							sh_subtmpfile(shp);
13907c2fbfb3SApril Chin 						if(execflg && !shp->subshell &&
13917c2fbfb3SApril Chin 							!shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
1392da2e3ebdSchin 						{
1393da2e3ebdSchin 							/* do close-on-exec */
1394da2e3ebdSchin 							int fd;
1395b30d1939SAndy Fiddaman 							for(fd=0; fd < shp->gd->lim.open_max; fd++)
13967c2fbfb3SApril Chin 								if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd)
1397da2e3ebdSchin 									sh_close(fd);
1398da2e3ebdSchin 						}
13997c2fbfb3SApril Chin 						if(argn)
14007c2fbfb3SApril Chin 							shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
1401da2e3ebdSchin 						if(error_info.flags&ERROR_INTERACTIVE)
1402da2e3ebdSchin 							tty_check(ERRIO);
14037c2fbfb3SApril Chin 						((Shnode_t*)t)->com.comstate = shp->bltindata.data;
14047c2fbfb3SApril Chin 						bp->data = (void*)save_data;
1405b30d1939SAndy Fiddaman 						if(sh.exitval && errno==EINTR && shp->lastsig)
1406b30d1939SAndy Fiddaman 							sh.exitval = SH_EXITSIG|shp->lastsig;
1407b30d1939SAndy Fiddaman 						else if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
14087c2fbfb3SApril Chin 							shp->exitval &= SH_EXITMASK;
1409da2e3ebdSchin 					}
1410da2e3ebdSchin 					else
1411da2e3ebdSchin 					{
1412da2e3ebdSchin 						struct openlist *item;
1413b30d1939SAndy Fiddaman 						for(item=buffp->olist;item;item=item->next)
1414da2e3ebdSchin 						{
1415da2e3ebdSchin 							if(item->strm)
1416da2e3ebdSchin 							{
1417da2e3ebdSchin 								sfclrlock(item->strm);
1418b30d1939SAndy Fiddaman 								if(shp->gd->hist_ptr && item->strm == shp->gd->hist_ptr->histfp)
1419b30d1939SAndy Fiddaman 									hist_close(shp->gd->hist_ptr);
1420da2e3ebdSchin 								else
1421da2e3ebdSchin 									sfclose(item->strm);
1422da2e3ebdSchin 							}
1423da2e3ebdSchin 						}
14247c2fbfb3SApril Chin 						if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
14257c2fbfb3SApril Chin 							(*shp->bltinfun)(-2,com,(void*)bp);
1426da2e3ebdSchin 						/* failure on special built-ins fatal */
1427da2e3ebdSchin 						if(jmpval<=SH_JMPCMD  && (!nv_isattr(np,BLT_SPC) || command))
1428da2e3ebdSchin 							jmpval=0;
1429da2e3ebdSchin 					}
1430b30d1939SAndy Fiddaman 					if(bp)
1431b30d1939SAndy Fiddaman 					{
1432b30d1939SAndy Fiddaman 						bp->bnode = 0;
1433b30d1939SAndy Fiddaman 						if( bp->ptr!= nv_context(np))
1434b30d1939SAndy Fiddaman 							np->nvfun = (Namfun_t*)bp->ptr;
1435b30d1939SAndy Fiddaman 					}
143634f9b3eeSRoland Mainz 					if(execflg && !was_nofork)
143734f9b3eeSRoland Mainz 						sh_offstate(SH_NOFORK);
1438da2e3ebdSchin 					if(!(nv_isattr(np,BLT_ENV)))
1439da2e3ebdSchin 					{
1440b30d1939SAndy Fiddaman 						if(shp->pwd)
1441da2e3ebdSchin 						{
1442da2e3ebdSchin 							struct stat stata;
1443da2e3ebdSchin 							stat(".",&stata);
1444da2e3ebdSchin 							/* restore directory changed */
1445da2e3ebdSchin 							if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
14467c2fbfb3SApril Chin 								chdir(shp->pwd);
1447da2e3ebdSchin 						}
1448da2e3ebdSchin 						sh_offstate(SH_STOPOK);
1449da2e3ebdSchin 						if(share&SF_SHARE)
1450da2e3ebdSchin 							sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
1451da2e3ebdSchin 						sfset(sfstderr,SF_LINE,0);
14527c2fbfb3SApril Chin 						sfpool(sfstderr,shp->outpool,SF_WRITE);
1453da2e3ebdSchin 						sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE);
14547c2fbfb3SApril Chin 						shp->nextprompt = save_prompt;
1455da2e3ebdSchin 					}
1456b30d1939SAndy Fiddaman 					sh_popcontext(shp,buffp);
1457b30d1939SAndy Fiddaman 					errorpop(&buffp->err);
145834f9b3eeSRoland Mainz 					error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
14597c2fbfb3SApril Chin 					shp->bltinfun = 0;
1460b30d1939SAndy Fiddaman 					if(buffp->olist)
1461b30d1939SAndy Fiddaman 						free_list(buffp->olist);
1462da2e3ebdSchin 					if(was_vi)
1463da2e3ebdSchin 						sh_onoption(SH_VI);
1464da2e3ebdSchin 					else if(was_emacs)
1465da2e3ebdSchin 						sh_onoption(SH_EMACS);
1466da2e3ebdSchin 					else if(was_gmacs)
1467da2e3ebdSchin 						sh_onoption(SH_GMACS);
1468da2e3ebdSchin 					if(scope)
14697c2fbfb3SApril Chin 						sh_unscope(shp);
14707c2fbfb3SApril Chin 					bp->ptr = (void*)save_ptr;
14717c2fbfb3SApril Chin 					bp->data = (void*)save_data;
1472da2e3ebdSchin 					/* don't restore for subshell exec */
14737c2fbfb3SApril Chin 					if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
14747c2fbfb3SApril Chin 						sh_iorestore(shp,topfd,jmpval);
1475b30d1939SAndy Fiddaman 
1476b30d1939SAndy Fiddaman 					shp->redir0 = 0;
1477da2e3ebdSchin 					if(jmpval)
14787c2fbfb3SApril Chin 						siglongjmp(*shp->jmplist,jmpval);
14797c2fbfb3SApril Chin #if 0
14807c2fbfb3SApril Chin 					if(flgs&NV_STATIC)
14817c2fbfb3SApril Chin 						((Shnode_t*)t)->com.comset = 0;
14827c2fbfb3SApril Chin #endif
14837c2fbfb3SApril Chin 					if(shp->exitval >=0)
1484da2e3ebdSchin 						goto setexit;
1485da2e3ebdSchin 					np = 0;
1486da2e3ebdSchin 					type=0;
1487da2e3ebdSchin 				}
1488da2e3ebdSchin 				/* check for functions */
1489da2e3ebdSchin 				if(!command && np && nv_isattr(np,NV_FUNCTION))
1490da2e3ebdSchin 				{
14917c2fbfb3SApril Chin 					volatile int indx;
14927c2fbfb3SApril Chin 					int jmpval=0;
1493b30d1939SAndy Fiddaman 					struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1494b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1495b30d1939SAndy Fiddaman 					Namval_t node, *namespace=0;
1496b30d1939SAndy Fiddaman #else
1497da2e3ebdSchin 					Namval_t node;
1498b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
14997c2fbfb3SApril Chin 					struct Namref	nr;
15007c2fbfb3SApril Chin 					long		mode;
1501da2e3ebdSchin 					register struct slnod *slp;
1502da2e3ebdSchin 					if(!np->nvalue.ip)
1503da2e3ebdSchin 					{
1504b30d1939SAndy Fiddaman 						indx = path_search(shp,com0,NIL(Pathcomp_t**),0);
1505da2e3ebdSchin 						if(indx==1)
1506b30d1939SAndy Fiddaman 						{
1507b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1508b30d1939SAndy Fiddaman 							if(shp->namespace)
1509b30d1939SAndy Fiddaman 								np = sh_fsearch(shp,com0,0);
1510b30d1939SAndy Fiddaman 							else
1511b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
15127c2fbfb3SApril Chin 							np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE);
1513b30d1939SAndy Fiddaman 						}
15147c2fbfb3SApril Chin 
1515da2e3ebdSchin 						if(!np->nvalue.ip)
1516da2e3ebdSchin 						{
1517da2e3ebdSchin 							if(indx==1)
1518da2e3ebdSchin 							{
1519da2e3ebdSchin 								errormsg(SH_DICT,ERROR_exit(0),e_defined,com0);
15207c2fbfb3SApril Chin 								shp->exitval = ERROR_NOEXEC;
1521da2e3ebdSchin 							}
1522da2e3ebdSchin 							else
1523da2e3ebdSchin 							{
1524da2e3ebdSchin 								errormsg(SH_DICT,ERROR_exit(0),e_found,"function");
15257c2fbfb3SApril Chin 								shp->exitval = ERROR_NOENT;
1526da2e3ebdSchin 							}
1527da2e3ebdSchin 							goto setexit;
1528da2e3ebdSchin 						}
1529da2e3ebdSchin 					}
1530da2e3ebdSchin 					/* increase refcnt for unset */
1531da2e3ebdSchin 					slp = (struct slnod*)np->nvenv;
1532da2e3ebdSchin 					sh_funstaks(slp->slchild,1);
1533da2e3ebdSchin 					staklink(slp->slptr);
1534da2e3ebdSchin 					if(nq)
1535da2e3ebdSchin 					{
1536b30d1939SAndy Fiddaman 						Namval_t *mp=0;
1537b30d1939SAndy Fiddaman 						if(nv_isattr(np,NV_STATICF) && (mp=nv_type(nq)))
1538b30d1939SAndy Fiddaman 							nq = mp;
15397c2fbfb3SApril Chin 						shp->last_table = last_table;
15403e14f97fSRoger A. Faulkner 						mode = set_instance(shp,nq,&node,&nr);
1541da2e3ebdSchin 					}
1542da2e3ebdSchin 					if(io)
1543da2e3ebdSchin 					{
15447c2fbfb3SApril Chin 						indx = shp->topfd;
1545b30d1939SAndy Fiddaman 						sh_pushcontext(shp,buffp,SH_JMPCMD);
1546b30d1939SAndy Fiddaman 						jmpval = sigsetjmp(buffp->buff,0);
1547da2e3ebdSchin 					}
1548da2e3ebdSchin 					if(jmpval == 0)
1549b30d1939SAndy Fiddaman 
1550da2e3ebdSchin 					{
1551da2e3ebdSchin 						if(io)
15527c2fbfb3SApril Chin 							indx = sh_redirect(shp,io,execflg);
1553b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1554b30d1939SAndy Fiddaman 						if(*np->nvname=='.')
1555b30d1939SAndy Fiddaman 						{
1556b30d1939SAndy Fiddaman 							char *cp = strchr(np->nvname+1,'.');
1557b30d1939SAndy Fiddaman 							if(cp)
1558b30d1939SAndy Fiddaman 							{
1559b30d1939SAndy Fiddaman 								*cp = 0;
1560b30d1939SAndy Fiddaman 								namespace = nv_search(np->nvname,shp->var_base,HASH_NOSCOPE);
1561b30d1939SAndy Fiddaman 								*cp = '.';
1562b30d1939SAndy Fiddaman 							}
1563b30d1939SAndy Fiddaman 						}
1564b30d1939SAndy Fiddaman 						namespace = enter_namespace(shp,namespace);
1565b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
15667c2fbfb3SApril Chin 						sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
1567da2e3ebdSchin 					}
1568b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1569b30d1939SAndy Fiddaman 					enter_namespace(shp,namespace);
1570b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1571da2e3ebdSchin 					if(io)
1572da2e3ebdSchin 					{
1573b30d1939SAndy Fiddaman 						if(buffp->olist)
1574b30d1939SAndy Fiddaman 							free_list(buffp->olist);
1575b30d1939SAndy Fiddaman 						sh_popcontext(shp,buffp);
15767c2fbfb3SApril Chin 						sh_iorestore(shp,indx,jmpval);
1577da2e3ebdSchin 					}
1578da2e3ebdSchin 					if(nq)
15797c2fbfb3SApril Chin 						unset_instance(nq,&node,&nr,mode);
1580da2e3ebdSchin 					sh_funstaks(slp->slchild,-1);
1581da2e3ebdSchin 					stakdelete(slp->slptr);
1582da2e3ebdSchin 					if(jmpval > SH_JMPFUN)
15837c2fbfb3SApril Chin 						siglongjmp(*shp->jmplist,jmpval);
1584da2e3ebdSchin 					goto setexit;
1585da2e3ebdSchin 				}
1586da2e3ebdSchin 			}
1587da2e3ebdSchin 			else if(!io)
1588da2e3ebdSchin 			{
1589da2e3ebdSchin 			setexit:
1590da2e3ebdSchin 				exitset();
1591da2e3ebdSchin 				break;
1592da2e3ebdSchin 			}
1593da2e3ebdSchin 		    }
15945ae8bd53SToomas Soome 		    /* FALLTHROUGH */
1595da2e3ebdSchin 		    case TFORK:
1596da2e3ebdSchin 		    {
1597da2e3ebdSchin 			register pid_t parent;
1598da2e3ebdSchin 			int no_fork,jobid;
1599b30d1939SAndy Fiddaman 			int pipes[3];
1600b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1601b30d1939SAndy Fiddaman 			if(shp->inpool)
1602b30d1939SAndy Fiddaman 			{
1603b30d1939SAndy Fiddaman 				sh_exec(t->fork.forktre,0);
1604b30d1939SAndy Fiddaman 				break;
1605b30d1939SAndy Fiddaman 			}
1606b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
16077c2fbfb3SApril Chin 			if(shp->subshell)
160834f9b3eeSRoland Mainz 			{
1609b30d1939SAndy Fiddaman 				sh_subtmpfile(shp);
1610b30d1939SAndy Fiddaman 				if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
1611b30d1939SAndy Fiddaman 					unpipe=iousepipe(shp);
1612b30d1939SAndy Fiddaman 				if((type&(FAMP|TFORK))==(FAMP|TFORK))
161334f9b3eeSRoland Mainz 					sh_subfork();
161434f9b3eeSRoland Mainz 			}
1615b30d1939SAndy Fiddaman 			no_fork = !ntflag && !(type&(FAMP|FPOU)) && !shp->subshell &&
1616b30d1939SAndy Fiddaman 			    !(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) &&
161734f9b3eeSRoland Mainz 			    !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
16183e14f97fSRoger A. Faulkner 				((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
1619b30d1939SAndy Fiddaman 				(execflg2 || (execflg && shp->fn_depth==0 &&
162034f9b3eeSRoland Mainz 				!(pipejob && sh_isoption(SH_PIPEFAIL))
162134f9b3eeSRoland Mainz 			    ));
16227c2fbfb3SApril Chin 			if(sh_isstate(SH_PROFILE) || shp->dot_depth)
1623da2e3ebdSchin 			{
1624da2e3ebdSchin 				/* disable foreground job monitor */
1625da2e3ebdSchin 				if(!(type&FAMP))
1626da2e3ebdSchin 					sh_offstate(SH_MONITOR);
1627da2e3ebdSchin #if SHOPT_DEVFD
1628da2e3ebdSchin 				else if(!(type&FINT))
1629da2e3ebdSchin 					sh_offstate(SH_MONITOR);
1630da2e3ebdSchin #endif /* SHOPT_DEVFD */
1631da2e3ebdSchin 			}
1632da2e3ebdSchin 			if(no_fork)
1633da2e3ebdSchin 				job.parent=parent=0;
1634da2e3ebdSchin 			else
1635da2e3ebdSchin 			{
163634f9b3eeSRoland Mainz #ifdef SHOPT_BGX
163734f9b3eeSRoland Mainz 				int maxjob;
163834f9b3eeSRoland Mainz 				if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
163934f9b3eeSRoland Mainz 				{
164034f9b3eeSRoland Mainz 					while(job.numbjob >= maxjob)
164134f9b3eeSRoland Mainz 					{
164234f9b3eeSRoland Mainz 						job_lock();
164334f9b3eeSRoland Mainz 						job_reap(0);
164434f9b3eeSRoland Mainz 						job_unlock();
164534f9b3eeSRoland Mainz 					}
164634f9b3eeSRoland Mainz 				}
164734f9b3eeSRoland Mainz #endif /* SHOPT_BGX */
1648b30d1939SAndy Fiddaman 				nv_getval(RANDNOD);
1649b30d1939SAndy Fiddaman 				restorefd = shp->topfd;
1650da2e3ebdSchin 				if(type&FCOOP)
1651b30d1939SAndy Fiddaman 				{
1652b30d1939SAndy Fiddaman 					pipes[2] = 0;
1653b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1654b30d1939SAndy Fiddaman 					if(shp->coshell)
1655b30d1939SAndy Fiddaman 					{
1656b30d1939SAndy Fiddaman 						if(shp->cpipe[0]<0 || shp->cpipe[1] < 0)
1657b30d1939SAndy Fiddaman 						{
1658b30d1939SAndy Fiddaman 							sh_copipe(shp,shp->outpipe=shp->cpipe,0);
1659b30d1939SAndy Fiddaman 							VALIDATE_FD(shp, shp->cpipe[0]);
1660b30d1939SAndy Fiddaman 							shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
1661b30d1939SAndy Fiddaman 						}
1662b30d1939SAndy Fiddaman 						sh_copipe(shp,shp->inpipe=pipes,0);
1663b30d1939SAndy Fiddaman 						parent = sh_coexec(shp,t,3);
1664b30d1939SAndy Fiddaman 						shp->cpid = parent;
1665b30d1939SAndy Fiddaman 						jobid = job_post(shp,parent,0);
1666b30d1939SAndy Fiddaman 						goto skip;
1667b30d1939SAndy Fiddaman 					}
1668b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
16697c2fbfb3SApril Chin 					coproc_init(shp,pipes);
1670b30d1939SAndy Fiddaman 				}
1671b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1672b30d1939SAndy Fiddaman 				if((type&(FAMP|FINT)) == (FAMP|FINT))
1673b30d1939SAndy Fiddaman 				{
1674b30d1939SAndy Fiddaman 					if(shp->coshell)
1675b30d1939SAndy Fiddaman 					{
1676b30d1939SAndy Fiddaman 						parent = sh_coexec(shp,t,0);
1677b30d1939SAndy Fiddaman 						jobid = job_post(shp,parent,0);
1678b30d1939SAndy Fiddaman 						goto skip;
1679b30d1939SAndy Fiddaman 					}
1680b30d1939SAndy Fiddaman 				}
1681b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1682da2e3ebdSchin #if SHOPT_AMP
1683da2e3ebdSchin 				if((type&(FAMP|FINT)) == (FAMP|FINT))
16847c2fbfb3SApril Chin 					parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1685da2e3ebdSchin 				else
1686b30d1939SAndy Fiddaman 					parent = sh_fork(shp,type,&jobid);
1687da2e3ebdSchin 				if(parent<0)
1688b30d1939SAndy Fiddaman 				{
1689b30d1939SAndy Fiddaman 					if(shp->comsub==1 && usepipe && unpipe)
1690b30d1939SAndy Fiddaman 						iounpipe(shp);
1691da2e3ebdSchin 					break;
1692b30d1939SAndy Fiddaman 				}
1693da2e3ebdSchin #else
1694da2e3ebdSchin #if SHOPT_SPAWN
1695da2e3ebdSchin #   ifdef _lib_fork
1696b30d1939SAndy Fiddaman 				if(com && !job.jobcontrol)
16977c2fbfb3SApril Chin 					parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1698da2e3ebdSchin 				else
1699b30d1939SAndy Fiddaman 					parent = sh_fork(shp,type,&jobid);
1700da2e3ebdSchin #   else
17017c2fbfb3SApril Chin 				if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
1702da2e3ebdSchin 					break;
1703da2e3ebdSchin #   endif /* _lib_fork */
1704da2e3ebdSchin 				if(parent<0)
1705b30d1939SAndy Fiddaman 				{
1706b30d1939SAndy Fiddaman 					if(shp->comsub==1 && usepipe && unpipe)
1707b30d1939SAndy Fiddaman 						iounpipe(shp);
1708da2e3ebdSchin 					break;
1709b30d1939SAndy Fiddaman 				}
1710da2e3ebdSchin #else
1711b30d1939SAndy Fiddaman 				parent = sh_fork(shp,type,&jobid);
1712da2e3ebdSchin #endif /* SHOPT_SPAWN */
1713da2e3ebdSchin #endif
1714da2e3ebdSchin 			}
1715b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1716b30d1939SAndy Fiddaman 		skip:
1717b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1718da2e3ebdSchin 			if(job.parent=parent)
1719da2e3ebdSchin 			/* This is the parent branch of fork
1720da2e3ebdSchin 			 * It may or may not wait for the child
1721da2e3ebdSchin 			 */
1722da2e3ebdSchin 			{
172334f9b3eeSRoland Mainz 				if(pipejob==2)
172434f9b3eeSRoland Mainz 				{
172534f9b3eeSRoland Mainz 					pipejob = 1;
1726b30d1939SAndy Fiddaman 					nlock--;
172734f9b3eeSRoland Mainz 					job_unlock();
172834f9b3eeSRoland Mainz 				}
1729da2e3ebdSchin 				if(type&FPCL)
17307c2fbfb3SApril Chin 					sh_close(shp->inpipe[0]);
1731da2e3ebdSchin 				if(type&(FCOOP|FAMP))
17327c2fbfb3SApril Chin 					shp->bckpid = parent;
17337c2fbfb3SApril Chin 				else if(!(type&(FAMP|FPOU)))
1734da2e3ebdSchin 				{
17357c2fbfb3SApril Chin 					if(!sh_isoption(SH_MONITOR))
17367c2fbfb3SApril Chin 					{
17377c2fbfb3SApril Chin 						if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
17387c2fbfb3SApril Chin 							sh_sigtrap(SIGINT);
17397c2fbfb3SApril Chin 						shp->trapnote |= SH_SIGIGNORE;
17407c2fbfb3SApril Chin 					}
1741b30d1939SAndy Fiddaman 					if(shp->pipepid)
174234f9b3eeSRoland Mainz 						shp->pipepid = parent;
17437c2fbfb3SApril Chin 					else
17447c2fbfb3SApril Chin 						job_wait(parent);
1745b30d1939SAndy Fiddaman 					if(shp->topfd > topfd)
1746b30d1939SAndy Fiddaman 						sh_iorestore(shp,topfd,0);
1747b30d1939SAndy Fiddaman 					if(usepipe && tsetio &&  subdup && unpipe)
1748b30d1939SAndy Fiddaman 						iounpipe(shp);
17497c2fbfb3SApril Chin 					if(!sh_isoption(SH_MONITOR))
17507c2fbfb3SApril Chin 					{
17517c2fbfb3SApril Chin 						shp->trapnote &= ~SH_SIGIGNORE;
17527c2fbfb3SApril Chin 						if(shp->exitval == (SH_EXITSIG|SIGINT))
1753b30d1939SAndy Fiddaman 							kill(getpid(),SIGINT);
17547c2fbfb3SApril Chin 					}
1755da2e3ebdSchin 				}
1756da2e3ebdSchin 				if(type&FAMP)
1757da2e3ebdSchin 				{
1758da2e3ebdSchin 					if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
1759da2e3ebdSchin 					{
1760da2e3ebdSchin 						/* print job number */
1761da2e3ebdSchin #ifdef JOBS
1762b30d1939SAndy Fiddaman #   if SHOPT_COSHELL
1763b30d1939SAndy Fiddaman 						sfprintf(sfstderr,"[%d]\t%s\n",jobid,sh_pid2str(shp,parent));
1764b30d1939SAndy Fiddaman #   else
1765da2e3ebdSchin 						sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent);
1766b30d1939SAndy Fiddaman #   endif /* SHOPT_COSHELL */
1767da2e3ebdSchin #else
1768da2e3ebdSchin 						sfprintf(sfstderr,"%d\n",parent);
1769da2e3ebdSchin #endif /* JOBS */
1770da2e3ebdSchin 					}
1771da2e3ebdSchin 				}
1772da2e3ebdSchin 				break;
1773da2e3ebdSchin 			}
1774da2e3ebdSchin 			else
1775da2e3ebdSchin 			/*
1776da2e3ebdSchin 			 * this is the FORKED branch (child) of execute
1777da2e3ebdSchin 			 */
1778da2e3ebdSchin 			{
17797c2fbfb3SApril Chin 				volatile int jmpval;
1780b30d1939SAndy Fiddaman 				struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1781b30d1939SAndy Fiddaman 				struct ionod *iop;
1782b30d1939SAndy Fiddaman 				int	rewrite=0;
1783da2e3ebdSchin 				if(no_fork)
1784da2e3ebdSchin 					sh_sigreset(2);
1785b30d1939SAndy Fiddaman 				sh_pushcontext(shp,buffp,SH_JMPEXIT);
1786b30d1939SAndy Fiddaman 				jmpval = sigsetjmp(buffp->buff,0);
1787da2e3ebdSchin 				if(jmpval)
1788da2e3ebdSchin 					goto done;
1789da2e3ebdSchin 				if((type&FINT) && !sh_isstate(SH_MONITOR))
1790da2e3ebdSchin 				{
1791da2e3ebdSchin 					/* default std input for & */
1792da2e3ebdSchin 					signal(SIGINT,SIG_IGN);
1793da2e3ebdSchin 					signal(SIGQUIT,SIG_IGN);
17947c2fbfb3SApril Chin 					if(!shp->st.ioset)
1795da2e3ebdSchin 					{
1796da2e3ebdSchin 						if(sh_close(0)>=0)
1797da2e3ebdSchin 							sh_chkopen(e_devnull);
1798da2e3ebdSchin 					}
1799da2e3ebdSchin 				}
1800da2e3ebdSchin 				sh_offstate(SH_MONITOR);
1801da2e3ebdSchin 				/* pipe in or out */
1802da2e3ebdSchin #ifdef _lib_nice
1803da2e3ebdSchin 				if((type&FAMP) && sh_isoption(SH_BGNICE))
1804da2e3ebdSchin 					nice(4);
1805da2e3ebdSchin #endif /* _lib_nice */
1806b30d1939SAndy Fiddaman #if !SHOPT_DEVFD
1807b30d1939SAndy Fiddaman 				if(shp->fifo && (type&(FPIN|FPOU)))
1808b30d1939SAndy Fiddaman 				{
1809b30d1939SAndy Fiddaman 					int	fn,fd = (type&FPIN)?0:1;
1810b30d1939SAndy Fiddaman 					void	*fifo_timer=sh_timeradd(500,1,fifo_check,(void*)shp);
1811b30d1939SAndy Fiddaman 					fn = sh_open(shp->fifo,fd?O_WRONLY:O_RDONLY);
1812b30d1939SAndy Fiddaman 					timerdel(fifo_timer);
1813b30d1939SAndy Fiddaman 					sh_iorenumber(shp,fn,fd);
1814b30d1939SAndy Fiddaman 					sh_close(fn);
1815b30d1939SAndy Fiddaman 					sh_delay(.001);
1816b30d1939SAndy Fiddaman 					unlink(shp->fifo);
1817b30d1939SAndy Fiddaman 					free(shp->fifo);
1818b30d1939SAndy Fiddaman 					shp->fifo = 0;
1819b30d1939SAndy Fiddaman 					type &= ~(FPIN|FPOU);
1820b30d1939SAndy Fiddaman 				}
1821b30d1939SAndy Fiddaman #endif /* !SHOPT_DEVFD */
1822da2e3ebdSchin 				if(type&FPIN)
1823da2e3ebdSchin 				{
1824b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1825b30d1939SAndy Fiddaman 					if(shp->inpipe[2]>20000)
1826b30d1939SAndy Fiddaman 						sh_coaccept(shp,shp->inpipe,0);
1827b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
18287c2fbfb3SApril Chin 					sh_iorenumber(shp,shp->inpipe[0],0);
1829da2e3ebdSchin 					if(!(type&FPOU) || (type&FCOOP))
18307c2fbfb3SApril Chin 						sh_close(shp->inpipe[1]);
1831da2e3ebdSchin 				}
1832da2e3ebdSchin 				if(type&FPOU)
1833da2e3ebdSchin 				{
1834b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1835b30d1939SAndy Fiddaman 					if(shp->outpipe[2]>20000)
1836b30d1939SAndy Fiddaman 						sh_coaccept(shp,shp->outpipe,1);
1837b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
18387c2fbfb3SApril Chin 					sh_iorenumber(shp,shp->outpipe[1],1);
18397c2fbfb3SApril Chin 					sh_pclose(shp->outpipe);
1840da2e3ebdSchin 				}
1841da2e3ebdSchin 				if((type&COMMSK)!=TCOM)
18427c2fbfb3SApril Chin 					error_info.line = t->fork.forkline-shp->st.firstline;
18437c2fbfb3SApril Chin 				if(shp->topfd)
18447c2fbfb3SApril Chin 					sh_iounsave(shp);
18457c2fbfb3SApril Chin 				topfd = shp->topfd;
1846b30d1939SAndy Fiddaman 				if(com0 && (iop=t->tre.treio))
1847b30d1939SAndy Fiddaman 				{
1848b30d1939SAndy Fiddaman 					for(;iop;iop=iop->ionxt)
1849b30d1939SAndy Fiddaman 					{
1850b30d1939SAndy Fiddaman 						if(iop->iofile&IOREWRITE)
1851b30d1939SAndy Fiddaman 							rewrite = 1;
1852b30d1939SAndy Fiddaman 					}
1853b30d1939SAndy Fiddaman 				}
18547c2fbfb3SApril Chin 				sh_redirect(shp,t->tre.treio,1);
1855b30d1939SAndy Fiddaman 				if(rewrite)
18567c2fbfb3SApril Chin 				{
18573e14f97fSRoger A. Faulkner 					job_lock();
18587c2fbfb3SApril Chin 					while((parent = vfork()) < 0)
1859b30d1939SAndy Fiddaman 						_sh_fork(shp,parent, 0, (int*)0);
18607c2fbfb3SApril Chin 					if(parent)
18617c2fbfb3SApril Chin 					{
1862b30d1939SAndy Fiddaman 						job.toclear = 0;
1863b30d1939SAndy Fiddaman 						job_post(shp,parent,0);
18647c2fbfb3SApril Chin 						job_wait(parent);
18657c2fbfb3SApril Chin 						sh_iorestore(shp,topfd,SH_JMPCMD);
18667c2fbfb3SApril Chin 						sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
18677c2fbfb3SApril Chin 
18687c2fbfb3SApril Chin 					}
1869b30d1939SAndy Fiddaman 					job_unlock();
18707c2fbfb3SApril Chin 				}
1871da2e3ebdSchin 				if((type&COMMSK)!=TCOM)
1872da2e3ebdSchin 				{
1873da2e3ebdSchin 					/* don't clear job table for out
1874da2e3ebdSchin 					   pipes so that jobs comand can
1875da2e3ebdSchin 					   be used in a pipeline
1876da2e3ebdSchin 					 */
1877da2e3ebdSchin 					if(!no_fork && !(type&FPOU))
1878da2e3ebdSchin 						job_clear();
187934f9b3eeSRoland Mainz 					sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
1880da2e3ebdSchin 				}
1881da2e3ebdSchin 				else if(com0)
1882da2e3ebdSchin 				{
1883da2e3ebdSchin 					sh_offoption(SH_ERREXIT);
18847c2fbfb3SApril Chin 					sh_freeup(shp);
1885b30d1939SAndy Fiddaman 					path_exec(shp,com0,com,t->com.comset);
1886da2e3ebdSchin 				}
1887da2e3ebdSchin 			done:
1888b30d1939SAndy Fiddaman 				sh_popcontext(shp,buffp);
1889da2e3ebdSchin 				if(jmpval>SH_JMPEXIT)
18907c2fbfb3SApril Chin 					siglongjmp(*shp->jmplist,jmpval);
18917c2fbfb3SApril Chin 				sh_done(shp,0);
1892da2e3ebdSchin 			}
1893da2e3ebdSchin 		    }
18945ae8bd53SToomas Soome 		    /* FALLTHROUGH */
1895da2e3ebdSchin 
1896da2e3ebdSchin 		    case TSETIO:
1897da2e3ebdSchin 		    {
1898da2e3ebdSchin 		    /*
1899da2e3ebdSchin 		     * don't create a new process, just
1900da2e3ebdSchin 		     * save and restore io-streams
1901da2e3ebdSchin 		     */
1902da2e3ebdSchin 			pid_t	pid;
190334f9b3eeSRoland Mainz 			int 	jmpval, waitall;
190434f9b3eeSRoland Mainz 			int 	simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
1905b30d1939SAndy Fiddaman 			struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
1906b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1907b30d1939SAndy Fiddaman 			if(shp->inpool)
1908b30d1939SAndy Fiddaman 			{
1909b30d1939SAndy Fiddaman 				sh_redirect(shp,t->fork.forkio,0);
1910b30d1939SAndy Fiddaman 				sh_exec(t->fork.forktre,0);
1911b30d1939SAndy Fiddaman 				break;
1912b30d1939SAndy Fiddaman 			}
1913b30d1939SAndy Fiddaman #endif /*SHOPT_COSHELL */
19147c2fbfb3SApril Chin 			if(shp->subshell)
1915da2e3ebdSchin 				execflg = 0;
1916b30d1939SAndy Fiddaman 			sh_pushcontext(shp,buffp,SH_JMPIO);
1917da2e3ebdSchin 			if(type&FPIN)
1918da2e3ebdSchin 			{
1919da2e3ebdSchin 				was_interactive = sh_isstate(SH_INTERACTIVE);
1920da2e3ebdSchin 				sh_offstate(SH_INTERACTIVE);
192134f9b3eeSRoland Mainz 				sh_iosave(shp,0,shp->topfd,(char*)0);
192234f9b3eeSRoland Mainz 				shp->pipepid = simple;
19237c2fbfb3SApril Chin 				sh_iorenumber(shp,shp->inpipe[0],0);
1924da2e3ebdSchin 				/*
1925da2e3ebdSchin 				 * if read end of pipe is a simple command
1926da2e3ebdSchin 				 * treat as non-sharable to improve performance
1927da2e3ebdSchin 				 */
192834f9b3eeSRoland Mainz 				if(simple)
1929da2e3ebdSchin 					sfset(sfstdin,SF_PUBLIC|SF_SHARE,0);
1930da2e3ebdSchin 				waitall = job.waitall;
1931da2e3ebdSchin 				job.waitall = 0;
1932da2e3ebdSchin 				pid = job.parent;
1933da2e3ebdSchin 			}
1934da2e3ebdSchin 			else
19357c2fbfb3SApril Chin 				error_info.line = t->fork.forkline-shp->st.firstline;
1936b30d1939SAndy Fiddaman 			jmpval = sigsetjmp(buffp->buff,0);
1937da2e3ebdSchin 			if(jmpval==0)
1938da2e3ebdSchin 			{
1939b30d1939SAndy Fiddaman 				if(shp->comsub==1)
1940b30d1939SAndy Fiddaman 					tsetio = 1;
19417c2fbfb3SApril Chin 				sh_redirect(shp,t->fork.forkio,execflg);
1942da2e3ebdSchin 				(t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
194334f9b3eeSRoland Mainz 				sh_exec(t->fork.forktre,flags&~simple);
1944da2e3ebdSchin 			}
19457c2fbfb3SApril Chin 			else
19467c2fbfb3SApril Chin 				sfsync(shp->outpool);
1947b30d1939SAndy Fiddaman 			sh_popcontext(shp,buffp);
1948b30d1939SAndy Fiddaman 			sh_iorestore(shp,buffp->topfd,jmpval);
1949b30d1939SAndy Fiddaman 			if(buffp->olist)
1950b30d1939SAndy Fiddaman 				free_list(buffp->olist);
1951da2e3ebdSchin 			if(type&FPIN)
1952da2e3ebdSchin 			{
1953da2e3ebdSchin 				job.waitall = waitall;
19547c2fbfb3SApril Chin 				type = shp->exitval;
1955da2e3ebdSchin 				if(!(type&SH_EXITSIG))
1956da2e3ebdSchin 				{
1957da2e3ebdSchin 					/* wait for remainder of pipline */
195834f9b3eeSRoland Mainz 					if(shp->pipepid>1)
195934f9b3eeSRoland Mainz 					{
196034f9b3eeSRoland Mainz 						job_wait(shp->pipepid);
196134f9b3eeSRoland Mainz 						type = shp->exitval;
196234f9b3eeSRoland Mainz 					}
196334f9b3eeSRoland Mainz 					else
196434f9b3eeSRoland Mainz 						job_wait(waitall?pid:0);
1965da2e3ebdSchin 					if(type || !sh_isoption(SH_PIPEFAIL))
19667c2fbfb3SApril Chin 						shp->exitval = type;
1967da2e3ebdSchin 				}
1968b30d1939SAndy Fiddaman 				if(shp->comsub==1 && usepipe)
1969b30d1939SAndy Fiddaman 					iounpipe(shp);
197034f9b3eeSRoland Mainz 				shp->pipepid = 0;
19717c2fbfb3SApril Chin 				shp->st.ioset = 0;
197234f9b3eeSRoland Mainz 				if(simple && was_errexit)
197334f9b3eeSRoland Mainz 				{
197434f9b3eeSRoland Mainz 					echeck = 1;
197534f9b3eeSRoland Mainz 					sh_onstate(SH_ERREXIT);
197634f9b3eeSRoland Mainz 				}
1977da2e3ebdSchin 			}
1978da2e3ebdSchin 			if(jmpval>SH_JMPIO)
19797c2fbfb3SApril Chin 				siglongjmp(*shp->jmplist,jmpval);
1980da2e3ebdSchin 			break;
1981da2e3ebdSchin 		    }
1982da2e3ebdSchin 
1983da2e3ebdSchin 		    case TPAR:
1984b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1985b30d1939SAndy Fiddaman 			if(shp->inpool)
1986b30d1939SAndy Fiddaman 			{
1987b30d1939SAndy Fiddaman 				sh_exec(t->par.partre,0);
1988b30d1939SAndy Fiddaman 				break;
1989b30d1939SAndy Fiddaman 			}
1990b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1991da2e3ebdSchin 			echeck = 1;
1992da2e3ebdSchin 			flags &= ~OPTIMIZE_FLAG;
19937c2fbfb3SApril Chin 			if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
1994da2e3ebdSchin 			{
199534f9b3eeSRoland Mainz 				char *savsig;
199634f9b3eeSRoland Mainz 				int nsig,jmpval;
1997b30d1939SAndy Fiddaman 				struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
199834f9b3eeSRoland Mainz 				shp->st.otrapcom = 0;
199934f9b3eeSRoland Mainz 				if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
200034f9b3eeSRoland Mainz 				{
200134f9b3eeSRoland Mainz 					nsig += sizeof(char*);
200234f9b3eeSRoland Mainz 					memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
200334f9b3eeSRoland Mainz 					shp->st.otrapcom = (char**)savsig;
200434f9b3eeSRoland Mainz 				}
200534f9b3eeSRoland Mainz 				sh_sigreset(0);
2006b30d1939SAndy Fiddaman 				sh_pushcontext(shp,buffp,SH_JMPEXIT);
2007b30d1939SAndy Fiddaman 				jmpval = sigsetjmp(buffp->buff,0);
2008da2e3ebdSchin 				if(jmpval==0)
2009da2e3ebdSchin 					sh_exec(t->par.partre,flags);
2010b30d1939SAndy Fiddaman 				sh_popcontext(shp,buffp);
2011da2e3ebdSchin 				if(jmpval > SH_JMPEXIT)
20127c2fbfb3SApril Chin 					siglongjmp(*shp->jmplist,jmpval);
2013b30d1939SAndy Fiddaman 				if(shp->exitval > 256)
2014b30d1939SAndy Fiddaman 					shp->exitval -= 128;
20157c2fbfb3SApril Chin 				sh_done(shp,0);
2016da2e3ebdSchin 			}
2017b30d1939SAndy Fiddaman 			else if(((type=t->par.partre->tre.tretyp)&FAMP) && ((type&COMMSK)==TFORK))
2018b30d1939SAndy Fiddaman 			{
2019b30d1939SAndy Fiddaman 				pid_t	pid;
2020b30d1939SAndy Fiddaman 				sfsync(NIL(Sfio_t*));
2021b30d1939SAndy Fiddaman 				while((pid=fork())< 0)
2022b30d1939SAndy Fiddaman 					_sh_fork(shp,pid,0,0);
2023b30d1939SAndy Fiddaman 				if(pid==0)
2024b30d1939SAndy Fiddaman 				{
2025b30d1939SAndy Fiddaman 					sh_exec(t->par.partre,flags);
2026b30d1939SAndy Fiddaman 					shp->st.trapcom[0]=0;
2027b30d1939SAndy Fiddaman 					sh_done(shp,0);
2028b30d1939SAndy Fiddaman 				}
2029b30d1939SAndy Fiddaman 			}
2030da2e3ebdSchin 			else
2031b30d1939SAndy Fiddaman 				sh_subshell(shp,t->par.partre,flags,0);
2032da2e3ebdSchin 			break;
2033da2e3ebdSchin 
2034da2e3ebdSchin 		    case TFIL:
2035da2e3ebdSchin 		    {
2036da2e3ebdSchin 		    /*
2037da2e3ebdSchin 		     * This code sets up a pipe.
2038da2e3ebdSchin 		     * All elements of the pipe are started by the parent.
2039da2e3ebdSchin 		     * The last element executes in current environment
2040da2e3ebdSchin 		     */
2041b30d1939SAndy Fiddaman 			int	pvo[3];	/* old pipe for multi-stage */
2042b30d1939SAndy Fiddaman 			int	pvn[3];	/* current set up pipe */
2043da2e3ebdSchin 			int	savepipe = pipejob;
2044b30d1939SAndy Fiddaman 			int	savelock = nlock;
2045da2e3ebdSchin 			int	showme = t->tre.tretyp&FSHOWME;
2046b30d1939SAndy Fiddaman 			int	n,waitall,savewaitall=job.waitall;
2047b30d1939SAndy Fiddaman 			int	savejobid = job.curjobid;
2048b30d1939SAndy Fiddaman 			int	*exitval=0,*saveexitval = job.exitval;
2049da2e3ebdSchin 			pid_t	savepgid = job.curpgid;
2050b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2051b30d1939SAndy Fiddaman 			int	copipe=0;
2052b30d1939SAndy Fiddaman 			Shnode_t	*tt;
2053b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2054b30d1939SAndy Fiddaman 			job.exitval = 0;
2055b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2056b30d1939SAndy Fiddaman 			if(shp->inpool)
2057b30d1939SAndy Fiddaman 			{
2058b30d1939SAndy Fiddaman 				do
2059b30d1939SAndy Fiddaman 				{
2060b30d1939SAndy Fiddaman 					sh_exec(t->lst.lstlef, 0);
2061b30d1939SAndy Fiddaman 					t = t->lst.lstrit;
2062b30d1939SAndy Fiddaman 					if(flags && (t->tre.tretyp!=TFIL || !(t->lst.lstlef->tre.tretyp&FALTPIPE)))
2063b30d1939SAndy Fiddaman 						goto coskip1;
2064b30d1939SAndy Fiddaman 				}
2065b30d1939SAndy Fiddaman 				while(t->tre.tretyp==TFIL);
2066b30d1939SAndy Fiddaman 				sh_exec(t,0);
2067b30d1939SAndy Fiddaman 			coskip1:
2068b30d1939SAndy Fiddaman 				break;
2069b30d1939SAndy Fiddaman 			}
2070b30d1939SAndy Fiddaman 			pvo[2] = pvn[2] = 0;
2071b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2072b30d1939SAndy Fiddaman 			job.curjobid = 0;
20737c2fbfb3SApril Chin 			if(shp->subshell)
207481af778eSCasper H.S. Dik 			{
2075b30d1939SAndy Fiddaman 				sh_subtmpfile(shp);
2076b30d1939SAndy Fiddaman 				if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
2077b30d1939SAndy Fiddaman 					iousepipe(shp);
207881af778eSCasper H.S. Dik 			}
20797c2fbfb3SApril Chin 			shp->inpipe = pvo;
20807c2fbfb3SApril Chin 			shp->outpipe = pvn;
2081da2e3ebdSchin 			pvo[1] = -1;
2082da2e3ebdSchin 			if(sh_isoption(SH_PIPEFAIL))
2083b30d1939SAndy Fiddaman 			{
2084b30d1939SAndy Fiddaman 				const Shnode_t* tn=t;
2085b30d1939SAndy Fiddaman 				job.waitall = 2;
2086b30d1939SAndy Fiddaman 				job.curpgid = 0;
2087b30d1939SAndy Fiddaman 				while((tn=tn->lst.lstrit) && tn->tre.tretyp==TFIL)
2088b30d1939SAndy Fiddaman 					job.waitall++;
2089b30d1939SAndy Fiddaman 				exitval = job.exitval = (int*)stakalloc(job.waitall*sizeof(int));
2090b30d1939SAndy Fiddaman 				memset(exitval,0,job.waitall*sizeof(int));
2091b30d1939SAndy Fiddaman 			}
2092da2e3ebdSchin 			else
2093da2e3ebdSchin 				job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
209434f9b3eeSRoland Mainz 			job_lock();
2095b30d1939SAndy Fiddaman 			nlock++;
2096da2e3ebdSchin 			do
2097da2e3ebdSchin 			{
2098da2e3ebdSchin 				/* create the pipe */
2099b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2100b30d1939SAndy Fiddaman 				tt = t->lst.lstrit;
2101b30d1939SAndy Fiddaman 				if(shp->coshell && !showme)
2102b30d1939SAndy Fiddaman 				{
2103b30d1939SAndy Fiddaman 					if(t->lst.lstlef->tre.tretyp&FALTPIPE)
2104b30d1939SAndy Fiddaman 					{
2105b30d1939SAndy Fiddaman 						sh_copipe(shp,pvn,0);
2106b30d1939SAndy Fiddaman 						type = sh_coexec(shp,t,1+copipe);
2107b30d1939SAndy Fiddaman 						pvn[1] = -1;
2108b30d1939SAndy Fiddaman 						pipejob=1;
2109b30d1939SAndy Fiddaman 						if(type>0)
2110b30d1939SAndy Fiddaman 						{
2111b30d1939SAndy Fiddaman 							job_post(shp,type,0);
2112b30d1939SAndy Fiddaman 							type = 0;
2113b30d1939SAndy Fiddaman 						}
2114b30d1939SAndy Fiddaman 						copipe = 1;
2115b30d1939SAndy Fiddaman 						pvo[0] = pvn[0];
2116b30d1939SAndy Fiddaman 						while(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
2117b30d1939SAndy Fiddaman 							tt = tt->lst.lstrit;
2118b30d1939SAndy Fiddaman 						t = tt;
2119b30d1939SAndy Fiddaman 						continue;
2120b30d1939SAndy Fiddaman 					}
2121b30d1939SAndy Fiddaman 					else if(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
2122b30d1939SAndy Fiddaman 					{
2123b30d1939SAndy Fiddaman 						sh_copipe(shp,pvn,0);
2124b30d1939SAndy Fiddaman 						pvo[2] = pvn[2];
2125b30d1939SAndy Fiddaman 						copipe = 0;
2126b30d1939SAndy Fiddaman 						goto coskip2;
2127b30d1939SAndy Fiddaman 					}
2128b30d1939SAndy Fiddaman 				}
2129b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2130da2e3ebdSchin 				sh_pipe(pvn);
2131b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2132b30d1939SAndy Fiddaman 				pvn[2] = 0;
2133b30d1939SAndy Fiddaman 			coskip2:
2134b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2135da2e3ebdSchin 				/* execute out part of pipe no wait */
2136da2e3ebdSchin 				(t->lst.lstlef)->tre.tretyp |= showme;
2137da2e3ebdSchin 				type = sh_exec(t->lst.lstlef, errorflg);
2138b30d1939SAndy Fiddaman 				/* close out-part of pipe */
2139b30d1939SAndy Fiddaman 				sh_close(pvn[1]);
2140da2e3ebdSchin 				pipejob=1;
2141da2e3ebdSchin 				/* save the pipe stream-ids */
2142da2e3ebdSchin 				pvo[0] = pvn[0];
2143da2e3ebdSchin 				/* pipeline all in one process group */
2144da2e3ebdSchin 				t = t->lst.lstrit;
2145da2e3ebdSchin 			}
2146da2e3ebdSchin 			/* repeat until end of pipeline */
2147da2e3ebdSchin 			while(!type && t->tre.tretyp==TFIL);
21487c2fbfb3SApril Chin 			shp->inpipe = pvn;
21497c2fbfb3SApril Chin 			shp->outpipe = 0;
215034f9b3eeSRoland Mainz 			pipejob = 2;
2151b30d1939SAndy Fiddaman 			waitall = job.waitall;
2152b30d1939SAndy Fiddaman 			job.waitall = 0;
2153da2e3ebdSchin 			if(type == 0)
2154da2e3ebdSchin 			{
2155da2e3ebdSchin 				/*
2156da2e3ebdSchin 				 * execute last element of pipeline
2157da2e3ebdSchin 				 * in the current process
2158da2e3ebdSchin 				 */
2159da2e3ebdSchin 				((Shnode_t*)t)->tre.tretyp |= showme;
2160da2e3ebdSchin 				sh_exec(t,flags);
2161da2e3ebdSchin 			}
2162da2e3ebdSchin 			else
2163da2e3ebdSchin 				/* execution failure, close pipe */
2164da2e3ebdSchin 				sh_pclose(pvn);
216534f9b3eeSRoland Mainz 			if(pipejob==2)
216634f9b3eeSRoland Mainz 				job_unlock();
2167b30d1939SAndy Fiddaman 			if((pipejob = savepipe) && nlock<savelock)
2168b30d1939SAndy Fiddaman 				pipejob = 1;
2169b30d1939SAndy Fiddaman 			n = shp->exitval;
2170b30d1939SAndy Fiddaman 			if(job.waitall = waitall)
2171b30d1939SAndy Fiddaman 			{
2172b30d1939SAndy Fiddaman 				if(sh_isstate(SH_MONITOR))
2173b30d1939SAndy Fiddaman 					job_wait(0);
2174b30d1939SAndy Fiddaman 				else
2175b30d1939SAndy Fiddaman 				{
2176b30d1939SAndy Fiddaman 					shp->intrap++;
2177b30d1939SAndy Fiddaman 					job_wait(0);
2178b30d1939SAndy Fiddaman 					shp->intrap--;
2179b30d1939SAndy Fiddaman 				}
2180b30d1939SAndy Fiddaman 			}
2181b30d1939SAndy Fiddaman 			if(n==0 && exitval)
2182b30d1939SAndy Fiddaman 			{
2183b30d1939SAndy Fiddaman 				while(exitval <= --job.exitval)
2184b30d1939SAndy Fiddaman 				{
2185b30d1939SAndy Fiddaman 					if(*job.exitval)
2186b30d1939SAndy Fiddaman 					{
2187b30d1939SAndy Fiddaman 						n = *job.exitval;
2188b30d1939SAndy Fiddaman 						break;
2189b30d1939SAndy Fiddaman 					}
2190b30d1939SAndy Fiddaman 				}
2191b30d1939SAndy Fiddaman 			}
2192b30d1939SAndy Fiddaman 			shp->exitval = n;
2193da2e3ebdSchin #ifdef SIGTSTP
2194da2e3ebdSchin 			if(!pipejob && sh_isstate(SH_MONITOR))
2195b30d1939SAndy Fiddaman 				tcsetpgrp(JOBTTY,shp->gd->pid);
2196da2e3ebdSchin #endif /*SIGTSTP */
2197da2e3ebdSchin 			job.curpgid = savepgid;
2198b30d1939SAndy Fiddaman 			job.exitval = saveexitval;
2199b30d1939SAndy Fiddaman 			job.waitall = savewaitall;
2200b30d1939SAndy Fiddaman 			job.curjobid = savejobid;
2201da2e3ebdSchin 			break;
2202da2e3ebdSchin 		    }
2203da2e3ebdSchin 
2204da2e3ebdSchin 		    case TLST:
2205da2e3ebdSchin 		    {
2206da2e3ebdSchin 			/*  a list of commands are executed here */
2207da2e3ebdSchin 			do
2208da2e3ebdSchin 			{
2209da2e3ebdSchin 				sh_exec(t->lst.lstlef,errorflg|OPTIMIZE);
2210da2e3ebdSchin 				t = t->lst.lstrit;
2211da2e3ebdSchin 			}
2212da2e3ebdSchin 			while(t->tre.tretyp == TLST);
2213da2e3ebdSchin 			sh_exec(t,flags);
2214da2e3ebdSchin 			break;
2215da2e3ebdSchin 		    }
2216da2e3ebdSchin 
2217da2e3ebdSchin 		    case TAND:
2218b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2219b30d1939SAndy Fiddaman 			if(shp->inpool)
2220b30d1939SAndy Fiddaman 			{
2221b30d1939SAndy Fiddaman 			andor:
2222b30d1939SAndy Fiddaman 				sh_exec(t->lst.lstlef,0);
2223b30d1939SAndy Fiddaman 				sh_exec(t->lst.lstrit,0);
2224b30d1939SAndy Fiddaman 				break;
2225b30d1939SAndy Fiddaman 			}
2226b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2227da2e3ebdSchin 			if(type&TTEST)
2228da2e3ebdSchin 				skipexitset++;
2229da2e3ebdSchin 			if(sh_exec(t->lst.lstlef,OPTIMIZE)==0)
2230da2e3ebdSchin 				sh_exec(t->lst.lstrit,flags);
2231da2e3ebdSchin 			break;
2232da2e3ebdSchin 
2233da2e3ebdSchin 		    case TORF:
2234b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2235b30d1939SAndy Fiddaman 			if(shp->inpool)
2236b30d1939SAndy Fiddaman 				goto andor;
2237b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2238da2e3ebdSchin 			if(type&TTEST)
2239da2e3ebdSchin 				skipexitset++;
2240da2e3ebdSchin 			if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0)
2241da2e3ebdSchin 				sh_exec(t->lst.lstrit,flags);
2242da2e3ebdSchin 			break;
2243da2e3ebdSchin 
2244da2e3ebdSchin 		    case TFOR: /* for and select */
2245da2e3ebdSchin 		    {
2246da2e3ebdSchin 			register char **args;
2247da2e3ebdSchin 			register int nargs;
2248da2e3ebdSchin 			register Namval_t *np;
2249da2e3ebdSchin 			int flag = errorflg|OPTIMIZE_FLAG;
2250da2e3ebdSchin 			struct dolnod	*argsav=0;
2251da2e3ebdSchin 			struct comnod	*tp;
2252da2e3ebdSchin 			char *cp, *trap, *nullptr = 0;
2253da2e3ebdSchin 			int nameref, refresh=1;
22547c2fbfb3SApril Chin 			char *av[5];
2255b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2256b30d1939SAndy Fiddaman 			int poolfiles;
2257b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2258da2e3ebdSchin #if SHOPT_OPTIMIZE
22597c2fbfb3SApril Chin 			int  jmpval = ((struct checkpt*)shp->jmplist)->mode;
2260b30d1939SAndy Fiddaman 			struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
22617c2fbfb3SApril Chin 			void *optlist = shp->optlist;
22627c2fbfb3SApril Chin 			shp->optlist = 0;
2263da2e3ebdSchin 			sh_tclear(t->for_.fortre);
2264b30d1939SAndy Fiddaman 			sh_pushcontext(shp,buffp,jmpval);
2265b30d1939SAndy Fiddaman 			jmpval = sigsetjmp(buffp->buff,0);
2266da2e3ebdSchin 			if(jmpval)
2267da2e3ebdSchin 				goto endfor;
2268da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
22697c2fbfb3SApril Chin 			error_info.line = t->for_.forline-shp->st.firstline;
2270da2e3ebdSchin 			if(!(tp=t->for_.forlst))
2271da2e3ebdSchin 			{
22727c2fbfb3SApril Chin 				args=shp->st.dolv+1;
22737c2fbfb3SApril Chin 				nargs = shp->st.dolc;
22747c2fbfb3SApril Chin 				argsav=sh_arguse(shp);
2275da2e3ebdSchin 			}
2276da2e3ebdSchin 			else
2277da2e3ebdSchin 			{
22787c2fbfb3SApril Chin 				args=sh_argbuild(shp,&argn,tp,0);
2279da2e3ebdSchin 				nargs = argn;
2280da2e3ebdSchin 			}
22817c2fbfb3SApril Chin 			np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
2282da2e3ebdSchin 			nameref = nv_isref(np)!=0;
22837c2fbfb3SApril Chin 			shp->st.loopcnt++;
2284da2e3ebdSchin 			cp = *args;
22857c2fbfb3SApril Chin 			while(cp && shp->st.execbrk==0)
2286da2e3ebdSchin 			{
2287da2e3ebdSchin 				if(t->tre.tretyp&COMSCAN)
2288da2e3ebdSchin 				{
2289da2e3ebdSchin 					char *val;
2290da2e3ebdSchin 					int save_prompt;
2291da2e3ebdSchin 					/* reuse register */
2292da2e3ebdSchin 					if(refresh)
2293da2e3ebdSchin 					{
2294da2e3ebdSchin 						sh_menu(sfstderr,nargs,args);
2295da2e3ebdSchin 						refresh = 0;
2296da2e3ebdSchin 					}
22977c2fbfb3SApril Chin 					save_prompt = shp->nextprompt;
22987c2fbfb3SApril Chin 					shp->nextprompt = 3;
22997c2fbfb3SApril Chin 					shp->timeout = 0;
2300b30d1939SAndy Fiddaman 					shp->exitval=sh_readline(shp,&nullptr,0,1,(size_t)0,1000*shp->st.tmout);
23017c2fbfb3SApril Chin 					shp->nextprompt = save_prompt;
23027c2fbfb3SApril Chin 					if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
2303da2e3ebdSchin 					{
23047c2fbfb3SApril Chin 						shp->exitval = 1;
2305da2e3ebdSchin 						break;
2306da2e3ebdSchin 					}
23077c2fbfb3SApril Chin 					if(!(val=nv_getval(sh_scoped(shp,REPLYNOD))))
2308da2e3ebdSchin 						continue;
2309da2e3ebdSchin 					else
2310da2e3ebdSchin 					{
2311da2e3ebdSchin 						if(*(cp=val) == 0)
2312da2e3ebdSchin 						{
2313da2e3ebdSchin 							refresh++;
2314da2e3ebdSchin 							goto check;
2315da2e3ebdSchin 						}
2316da2e3ebdSchin 						while(type = *cp++)
2317da2e3ebdSchin 							if(type < '0' && type > '9')
2318da2e3ebdSchin 								break;
2319da2e3ebdSchin 						if(type!=0)
2320da2e3ebdSchin 							type = nargs;
2321da2e3ebdSchin 						else
2322da2e3ebdSchin 							type = (int)strtol(val, (char**)0, 10)-1;
2323da2e3ebdSchin 						if(type<0 || type >= nargs)
2324da2e3ebdSchin 							cp = "";
2325da2e3ebdSchin 						else
2326da2e3ebdSchin 							cp = args[type];
2327da2e3ebdSchin 					}
2328da2e3ebdSchin 				}
2329da2e3ebdSchin 				if(nameref)
2330da2e3ebdSchin 					nv_offattr(np,NV_REF);
2331da2e3ebdSchin 				else if(nv_isattr(np, NV_ARRAY))
2332da2e3ebdSchin 					nv_putsub(np,NIL(char*),0L);
2333da2e3ebdSchin 				nv_putval(np,cp,0);
2334da2e3ebdSchin 				if(nameref)
2335da2e3ebdSchin 					nv_setref(np,(Dt_t*)0,NV_VARNAME);
23367c2fbfb3SApril Chin 				if(trap=shp->st.trap[SH_DEBUGTRAP])
2337da2e3ebdSchin 				{
2338da2e3ebdSchin 					av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
2339da2e3ebdSchin 					av[1] = t->for_.fornam;
23407c2fbfb3SApril Chin 					av[2] = "in";
2341da2e3ebdSchin 					av[3] = cp;
23427c2fbfb3SApril Chin 					av[4] = 0;
23437c2fbfb3SApril Chin 					sh_debug(shp,trap,(char*)0,(char*)0,av,0);
2344da2e3ebdSchin 				}
2345b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2346b30d1939SAndy Fiddaman 				if(shp->inpool)
2347b30d1939SAndy Fiddaman 				{
2348b30d1939SAndy Fiddaman 					poolfiles = shp->poolfiles;
2349b30d1939SAndy Fiddaman 					sh_exec(t->for_.fortre,0);
2350b30d1939SAndy Fiddaman 					if(poolfiles==shp->poolfiles)
2351b30d1939SAndy Fiddaman 						break;
2352b30d1939SAndy Fiddaman 				}
2353b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2354da2e3ebdSchin 				sh_exec(t->for_.fortre,flag);
2355da2e3ebdSchin 				flag &= ~OPTIMIZE_FLAG;
2356da2e3ebdSchin 				if(t->tre.tretyp&COMSCAN)
2357da2e3ebdSchin 				{
23587c2fbfb3SApril Chin 					if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
2359da2e3ebdSchin 						refresh++;
2360da2e3ebdSchin 				}
2361da2e3ebdSchin 				else
2362da2e3ebdSchin 					cp = *++args;
2363da2e3ebdSchin 			check:
23647c2fbfb3SApril Chin 				if(shp->st.breakcnt<0)
23657c2fbfb3SApril Chin 					shp->st.execbrk = (++shp->st.breakcnt !=0);
2366da2e3ebdSchin 			}
2367da2e3ebdSchin #if SHOPT_OPTIMIZE
2368da2e3ebdSchin 		endfor:
2369b30d1939SAndy Fiddaman 			sh_popcontext(shp,buffp);
2370da2e3ebdSchin 			sh_tclear(t->for_.fortre);
23717c2fbfb3SApril Chin 			sh_optclear(shp,optlist);
2372da2e3ebdSchin 			if(jmpval)
23737c2fbfb3SApril Chin 				siglongjmp(*shp->jmplist,jmpval);
2374da2e3ebdSchin #endif /*SHOPT_OPTIMIZE */
23757c2fbfb3SApril Chin 			if(shp->st.breakcnt>0)
23767c2fbfb3SApril Chin 				shp->st.execbrk = (--shp->st.breakcnt !=0);
23777c2fbfb3SApril Chin 			shp->st.loopcnt--;
23787c2fbfb3SApril Chin 			sh_argfree(shp,argsav,0);
2379da2e3ebdSchin 			nv_close(np);
2380da2e3ebdSchin 			break;
2381da2e3ebdSchin 		    }
2382da2e3ebdSchin 
2383da2e3ebdSchin 		    case TWH: /* while and until */
2384da2e3ebdSchin 		    {
23857c2fbfb3SApril Chin 			volatile int 	r=0;
2386da2e3ebdSchin 			int first = OPTIMIZE_FLAG;
2387da2e3ebdSchin 			Shnode_t *tt = t->wh.whtre;
2388da2e3ebdSchin #if SHOPT_FILESCAN
2389da2e3ebdSchin 			Sfio_t *iop=0;
2390b30d1939SAndy Fiddaman 			int savein;
2391da2e3ebdSchin #endif /*SHOPT_FILESCAN*/
2392da2e3ebdSchin #if SHOPT_OPTIMIZE
23937c2fbfb3SApril Chin 			int  jmpval = ((struct checkpt*)shp->jmplist)->mode;
2394b30d1939SAndy Fiddaman 			struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
23957c2fbfb3SApril Chin 			void *optlist = shp->optlist;
2396b30d1939SAndy Fiddaman #endif /* SHOPT_OPTIMIZE */
2397b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2398b30d1939SAndy Fiddaman 			if(shp->inpool)
2399b30d1939SAndy Fiddaman 			{
2400b30d1939SAndy Fiddaman 				int poolfiles;
2401b30d1939SAndy Fiddaman #   if SHOPT_FILESCAN
2402b30d1939SAndy Fiddaman 				if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
2403b30d1939SAndy Fiddaman 				{
2404b30d1939SAndy Fiddaman 					sh_redirect(shp,tt->com.comio,0);
2405b30d1939SAndy Fiddaman 					break;
2406b30d1939SAndy Fiddaman 				}
2407b30d1939SAndy Fiddaman #   endif /* SHOPT_FILESCAN */
2408b30d1939SAndy Fiddaman 				sh_exec(tt,0);
2409b30d1939SAndy Fiddaman 				do
2410b30d1939SAndy Fiddaman 				{
2411b30d1939SAndy Fiddaman 					if((sh_exec(tt,0)==0)!=(type==TWH))
2412b30d1939SAndy Fiddaman 						break;
2413b30d1939SAndy Fiddaman 					poolfiles = shp->poolfiles;
2414b30d1939SAndy Fiddaman 					sh_exec(t->wh.dotre,0);
2415b30d1939SAndy Fiddaman 					if(t->wh.whinc)
2416b30d1939SAndy Fiddaman 						sh_exec((Shnode_t*)t->wh.whinc,0);
2417b30d1939SAndy Fiddaman 				}
2418b30d1939SAndy Fiddaman 				while(poolfiles != shp->poolfiles);
2419b30d1939SAndy Fiddaman 				break;
2420b30d1939SAndy Fiddaman 			}
2421b30d1939SAndy Fiddaman #endif /*SHOPT_COSHELL */
2422b30d1939SAndy Fiddaman #if SHOPT_OPTIMIZE
24237c2fbfb3SApril Chin 			shp->optlist = 0;
2424da2e3ebdSchin 			sh_tclear(t->wh.whtre);
2425da2e3ebdSchin 			sh_tclear(t->wh.dotre);
2426b30d1939SAndy Fiddaman 			sh_pushcontext(shp,buffp,jmpval);
2427b30d1939SAndy Fiddaman 			jmpval = sigsetjmp(buffp->buff,0);
2428da2e3ebdSchin 			if(jmpval)
2429da2e3ebdSchin 				goto endwhile;
2430da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
2431da2e3ebdSchin #if SHOPT_FILESCAN
2432da2e3ebdSchin 			if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
2433da2e3ebdSchin 			{
2434b30d1939SAndy Fiddaman 				iop = openstream(shp,tt->com.comio,&savein);
2435da2e3ebdSchin 				if(tt->com.comset)
243634f9b3eeSRoland Mainz 					nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
2437da2e3ebdSchin 			}
2438da2e3ebdSchin #endif /*SHOPT_FILESCAN */
24397c2fbfb3SApril Chin 			shp->st.loopcnt++;
24407c2fbfb3SApril Chin 			while(shp->st.execbrk==0)
2441da2e3ebdSchin 			{
2442da2e3ebdSchin #if SHOPT_FILESCAN
2443da2e3ebdSchin 				if(iop)
2444da2e3ebdSchin 				{
24457c2fbfb3SApril Chin 					if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING)))
2446da2e3ebdSchin 						break;
2447da2e3ebdSchin 				}
2448da2e3ebdSchin 				else
2449da2e3ebdSchin #endif /*SHOPT_FILESCAN */
2450da2e3ebdSchin 				if((sh_exec(tt,first)==0)!=(type==TWH))
2451da2e3ebdSchin 					break;
2452da2e3ebdSchin 				r = sh_exec(t->wh.dotre,first|errorflg);
24537c2fbfb3SApril Chin 				if(shp->st.breakcnt<0)
24547c2fbfb3SApril Chin 					shp->st.execbrk = (++shp->st.breakcnt !=0);
2455da2e3ebdSchin 				/* This is for the arithmetic for */
24567c2fbfb3SApril Chin 				if(shp->st.execbrk==0 && t->wh.whinc)
2457da2e3ebdSchin 					sh_exec((Shnode_t*)t->wh.whinc,first);
2458da2e3ebdSchin 				first = 0;
2459da2e3ebdSchin 				errorflg &= ~OPTIMIZE_FLAG;
2460da2e3ebdSchin #if SHOPT_FILESCAN
24617c2fbfb3SApril Chin 				shp->offsets[0] = -1;
24627c2fbfb3SApril Chin 				shp->offsets[1] = 0;
2463da2e3ebdSchin #endif /*SHOPT_FILESCAN */
2464da2e3ebdSchin 			}
2465da2e3ebdSchin #if SHOPT_OPTIMIZE
2466da2e3ebdSchin 		endwhile:
2467b30d1939SAndy Fiddaman 			sh_popcontext(shp,buffp);
2468da2e3ebdSchin 			sh_tclear(t->wh.whtre);
2469da2e3ebdSchin 			sh_tclear(t->wh.dotre);
24707c2fbfb3SApril Chin 			sh_optclear(shp,optlist);
2471da2e3ebdSchin 			if(jmpval)
24727c2fbfb3SApril Chin 				siglongjmp(*shp->jmplist,jmpval);
2473da2e3ebdSchin #endif /*SHOPT_OPTIMIZE */
24747c2fbfb3SApril Chin 			if(shp->st.breakcnt>0)
24757c2fbfb3SApril Chin 				shp->st.execbrk = (--shp->st.breakcnt !=0);
24767c2fbfb3SApril Chin 			shp->st.loopcnt--;
24777c2fbfb3SApril Chin 			shp->exitval= r;
2478da2e3ebdSchin #if SHOPT_FILESCAN
2479da2e3ebdSchin 			if(iop)
2480da2e3ebdSchin 			{
2481da2e3ebdSchin 				sfclose(iop);
2482da2e3ebdSchin 				close(0);
2483da2e3ebdSchin 				dup(savein);
24847c2fbfb3SApril Chin 				shp->cur_line = 0;
2485da2e3ebdSchin 			}
2486da2e3ebdSchin #endif /*SHOPT_FILESCAN */
2487da2e3ebdSchin 			break;
2488da2e3ebdSchin 		    }
2489da2e3ebdSchin 		    case TARITH: /* (( expression )) */
2490da2e3ebdSchin 		    {
2491da2e3ebdSchin 			register char *trap;
24927c2fbfb3SApril Chin 			char *arg[4];
24937c2fbfb3SApril Chin 			error_info.line = t->ar.arline-shp->st.firstline;
24947c2fbfb3SApril Chin 			arg[0] = "((";
2495da2e3ebdSchin 			if(!(t->ar.arexpr->argflag&ARG_RAW))
24967c2fbfb3SApril Chin 				arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
2497da2e3ebdSchin 			else
2498da2e3ebdSchin 				arg[1] = t->ar.arexpr->argval;
24997c2fbfb3SApril Chin 			arg[2] = "))";
25007c2fbfb3SApril Chin 			arg[3] = 0;
25017c2fbfb3SApril Chin 			if(trap=shp->st.trap[SH_DEBUGTRAP])
25027c2fbfb3SApril Chin 				sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
2503da2e3ebdSchin 			if(sh_isoption(SH_XTRACE))
2504da2e3ebdSchin 			{
2505b30d1939SAndy Fiddaman 				sh_trace(shp,NIL(char**),0);
2506da2e3ebdSchin 				sfprintf(sfstderr,"((%s))\n",arg[1]);
2507da2e3ebdSchin 			}
2508da2e3ebdSchin 			if(t->ar.arcomp)
25097c2fbfb3SApril Chin 				shp->exitval  = !arith_exec((Arith_t*)t->ar.arcomp);
2510da2e3ebdSchin 			else
2511b30d1939SAndy Fiddaman 				shp->exitval = !sh_arith(shp,arg[1]);
2512da2e3ebdSchin 			break;
2513da2e3ebdSchin 		    }
2514da2e3ebdSchin 
2515da2e3ebdSchin 		    case TIF:
2516b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2517b30d1939SAndy Fiddaman 			if(shp->inpool)
2518b30d1939SAndy Fiddaman 			{
2519b30d1939SAndy Fiddaman 				sh_exec(t->if_.thtre,0);
2520b30d1939SAndy Fiddaman 				if(t->if_.eltre)
2521b30d1939SAndy Fiddaman 					sh_exec(t->if_.eltre, 0);
2522b30d1939SAndy Fiddaman 				break;
2523b30d1939SAndy Fiddaman 			}
2524b30d1939SAndy Fiddaman #endif /*SHOPT_COSHELL */
2525da2e3ebdSchin 			if(sh_exec(t->if_.iftre,OPTIMIZE)==0)
2526da2e3ebdSchin 				sh_exec(t->if_.thtre,flags);
2527da2e3ebdSchin 			else if(t->if_.eltre)
2528da2e3ebdSchin 				sh_exec(t->if_.eltre, flags);
2529da2e3ebdSchin 			else
25307c2fbfb3SApril Chin 				shp->exitval=0; /* force zero exit for if-then-fi */
2531da2e3ebdSchin 			break;
2532da2e3ebdSchin 
2533da2e3ebdSchin 		    case TSW:
2534da2e3ebdSchin 		    {
2535da2e3ebdSchin 			Shnode_t *tt = (Shnode_t*)t;
25367c2fbfb3SApril Chin 			char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
25377c2fbfb3SApril Chin 			error_info.line = t->sw.swline-shp->st.firstline;
2538da2e3ebdSchin 			t= (Shnode_t*)(tt->sw.swlst);
25397c2fbfb3SApril Chin 			if(trap=shp->st.trap[SH_DEBUGTRAP])
2540da2e3ebdSchin 			{
25417c2fbfb3SApril Chin 				char *av[4];
25427c2fbfb3SApril Chin 				av[0] = "case";
2543da2e3ebdSchin 				av[1] = r;
25447c2fbfb3SApril Chin 				av[2] = "in";
25457c2fbfb3SApril Chin 				av[3] = 0;
25467c2fbfb3SApril Chin 				sh_debug(shp,trap, (char*)0, (char*)0, av, 0);
2547da2e3ebdSchin 			}
2548da2e3ebdSchin 			while(t)
2549da2e3ebdSchin 			{
2550da2e3ebdSchin 				register struct argnod	*rex=(struct argnod*)t->reg.regptr;
2551b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2552b30d1939SAndy Fiddaman 				if(shp->inpool)
2553b30d1939SAndy Fiddaman 				{
2554b30d1939SAndy Fiddaman 					sh_exec(t->reg.regcom,0);
2555b30d1939SAndy Fiddaman 					continue;
2556b30d1939SAndy Fiddaman 				}
2557b30d1939SAndy Fiddaman #endif /*SHOPT_COSHELL */
2558da2e3ebdSchin 				while(rex)
2559da2e3ebdSchin 				{
2560da2e3ebdSchin 					register char *s;
2561da2e3ebdSchin 					if(rex->argflag&ARG_MAC)
2562da2e3ebdSchin 					{
25637c2fbfb3SApril Chin 						s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP);
2564da2e3ebdSchin 						while(*s=='\\' && s[1]==0)
2565da2e3ebdSchin 							s+=2;
2566da2e3ebdSchin 					}
2567da2e3ebdSchin 					else
2568da2e3ebdSchin 						s = rex->argval;
2569da2e3ebdSchin 					type = (rex->argflag&ARG_RAW);
2570da2e3ebdSchin 					if((type && strcmp(r,s)==0) ||
2571da2e3ebdSchin 						(!type && (strmatch(r,s)
2572da2e3ebdSchin 						|| trim_eq(r,s))))
2573da2e3ebdSchin 					{
2574b30d1939SAndy Fiddaman 						do	sh_exec(t->reg.regcom,(t->reg.regflag?(flags&sh_state(SH_ERREXIT)):flags));
2575da2e3ebdSchin 						while(t->reg.regflag &&
2576da2e3ebdSchin 							(t=(Shnode_t*)t->reg.regnxt));
2577da2e3ebdSchin 						t=0;
2578da2e3ebdSchin 						break;
2579da2e3ebdSchin 					}
2580da2e3ebdSchin 					else
2581da2e3ebdSchin 						rex=rex->argnxt.ap;
2582da2e3ebdSchin 				}
2583da2e3ebdSchin 				if(t)
2584da2e3ebdSchin 					t=(Shnode_t*)t->reg.regnxt;
2585da2e3ebdSchin 			}
2586da2e3ebdSchin 			break;
2587da2e3ebdSchin 		    }
2588da2e3ebdSchin 
2589da2e3ebdSchin 		    case TTIME:
2590da2e3ebdSchin 		    {
2591da2e3ebdSchin 			/* time the command */
2592da2e3ebdSchin 			struct tms before,after;
2593da2e3ebdSchin 			const char *format = e_timeformat;
2594da2e3ebdSchin 			clock_t at, tm[3];
2595da2e3ebdSchin #ifdef timeofday
2596da2e3ebdSchin 			struct timeval tb,ta;
2597da2e3ebdSchin #else
2598da2e3ebdSchin 			clock_t bt;
2599da2e3ebdSchin #endif	/* timeofday */
2600b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2601b30d1939SAndy Fiddaman 			if(shp->inpool)
2602b30d1939SAndy Fiddaman 			{
2603b30d1939SAndy Fiddaman 				if(t->par.partre)
2604b30d1939SAndy Fiddaman 					sh_exec(t->par.partre,0);
2605b30d1939SAndy Fiddaman 				break;
2606b30d1939SAndy Fiddaman 			}
2607b30d1939SAndy Fiddaman #endif /*SHOPT_COSHELL */
2608da2e3ebdSchin 			if(type!=TTIME)
2609da2e3ebdSchin 			{
2610da2e3ebdSchin 				sh_exec(t->par.partre,OPTIMIZE);
26117c2fbfb3SApril Chin 				shp->exitval = !shp->exitval;
2612da2e3ebdSchin 				break;
2613da2e3ebdSchin 			}
2614da2e3ebdSchin 			if(t->par.partre)
2615da2e3ebdSchin 			{
2616da2e3ebdSchin 				long timer_on;
2617b30d1939SAndy Fiddaman 				if(shp->subshell && shp->comsub==1)
2618b30d1939SAndy Fiddaman 					sh_subfork();
2619da2e3ebdSchin 				timer_on = sh_isstate(SH_TIMING);
2620da2e3ebdSchin #ifdef timeofday
2621da2e3ebdSchin 				timeofday(&tb);
2622da2e3ebdSchin 				times(&before);
2623da2e3ebdSchin #else
2624da2e3ebdSchin 				bt = times(&before);
2625da2e3ebdSchin #endif	/* timeofday */
2626da2e3ebdSchin 				job.waitall = 1;
2627da2e3ebdSchin 				sh_onstate(SH_TIMING);
2628*6ba75e24SJohnothan King 				sh_exec(t->par.partre,sh_isstate(SH_ERREXIT)|OPTIMIZE);
2629da2e3ebdSchin 				if(!timer_on)
2630da2e3ebdSchin 					sh_offstate(SH_TIMING);
2631da2e3ebdSchin 				job.waitall = 0;
2632da2e3ebdSchin 			}
2633da2e3ebdSchin 			else
2634da2e3ebdSchin 			{
2635da2e3ebdSchin #ifndef timeofday
2636da2e3ebdSchin 				bt = 0;
2637da2e3ebdSchin #endif	/* timeofday */
2638da2e3ebdSchin 				before.tms_utime = before.tms_cutime = 0;
2639da2e3ebdSchin 				before.tms_stime = before.tms_cstime = 0;
2640da2e3ebdSchin 			}
2641da2e3ebdSchin #ifdef timeofday
2642da2e3ebdSchin 			times(&after);
2643da2e3ebdSchin 			timeofday(&ta);
2644b30d1939SAndy Fiddaman 			at = shp->gd->lim.clk_tck*(ta.tv_sec-tb.tv_sec);
2645b30d1939SAndy Fiddaman 			at +=  ((shp->gd->lim.clk_tck*(((1000000L/2)/shp->gd->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
2646da2e3ebdSchin #else
2647da2e3ebdSchin 			at = times(&after) - bt;
2648da2e3ebdSchin #endif	/* timeofday */
2649da2e3ebdSchin 			tm[0] = at;
2650da2e3ebdSchin 			if(t->par.partre)
2651da2e3ebdSchin 			{
26527c2fbfb3SApril Chin 				Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
2653da2e3ebdSchin 				if(np)
2654da2e3ebdSchin 				{
2655da2e3ebdSchin 					format = nv_getval(np);
2656da2e3ebdSchin 					nv_close(np);
2657da2e3ebdSchin 				}
2658da2e3ebdSchin 				if(!format)
2659da2e3ebdSchin 					format = e_timeformat;
2660da2e3ebdSchin 			}
2661da2e3ebdSchin 			else
2662da2e3ebdSchin 				format = strchr(format+1,'\n')+1;
2663da2e3ebdSchin 			tm[1] = after.tms_utime - before.tms_utime;
2664da2e3ebdSchin 			tm[1] += after.tms_cutime - before.tms_cutime;
2665da2e3ebdSchin 			tm[2] = after.tms_stime - before.tms_stime;
2666da2e3ebdSchin 			tm[2] += after.tms_cstime - before.tms_cstime;
2667da2e3ebdSchin 			if(format && *format)
26687c2fbfb3SApril Chin 				p_time(shp,sfstderr,sh_translate(format),tm);
2669da2e3ebdSchin 			break;
2670da2e3ebdSchin 		    }
2671da2e3ebdSchin 		    case TFUN:
2672da2e3ebdSchin 		    {
2673b30d1939SAndy Fiddaman 			register Namval_t *np=0;
2674da2e3ebdSchin 			register struct slnod *slp;
2675da2e3ebdSchin 			register char *fname = ((struct functnod*)t)->functnam;
2676da2e3ebdSchin 			register char *cp = strrchr(fname,'.');
2677b30d1939SAndy Fiddaman 			register Namval_t *npv=0,*mp;
2678b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2679b30d1939SAndy Fiddaman 			if(shp->inpool)
2680b30d1939SAndy Fiddaman 			{
2681b30d1939SAndy Fiddaman 				sh_exec(t->funct.functtre,0);
2682b30d1939SAndy Fiddaman 				break;
2683b30d1939SAndy Fiddaman 			}
2684b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2685da2e3ebdSchin #if SHOPT_NAMESPACE
2686da2e3ebdSchin 			if(t->tre.tretyp==TNSPACE)
2687da2e3ebdSchin 			{
2688b30d1939SAndy Fiddaman 				Dt_t *root;
26897c2fbfb3SApril Chin 				Namval_t *oldnspace = shp->namespace;
26907c2fbfb3SApril Chin 				int offset = stktell(stkp);
2691b30d1939SAndy Fiddaman 				int	flags=NV_NOASSIGN|NV_NOARRAY|NV_VARNAME;
2692da2e3ebdSchin 				if(cp)
2693da2e3ebdSchin 					errormsg(SH_DICT,ERROR_exit(1),e_ident,fname);
26947c2fbfb3SApril Chin 				sfputc(stkp,'.');
26957c2fbfb3SApril Chin 				sfputr(stkp,fname,0);
2696b30d1939SAndy Fiddaman 				np = nv_open(stkptr(stkp,offset),shp->var_tree,flags);
26977c2fbfb3SApril Chin 				offset = stktell(stkp);
2698b30d1939SAndy Fiddaman 				if(nv_istable(np))
2699b30d1939SAndy Fiddaman 					root = nv_dict(np);
2700b30d1939SAndy Fiddaman 				else
2701da2e3ebdSchin 				{
2702da2e3ebdSchin 					root = dtopen(&_Nvdisc,Dtoset);
2703b30d1939SAndy Fiddaman 					nv_mount(np, (char*)0, root);
2704b30d1939SAndy Fiddaman 					np->nvalue.cp = Empty;
2705b30d1939SAndy Fiddaman 					dtview(root,shp->var_base);
2706da2e3ebdSchin 				}
2707b30d1939SAndy Fiddaman 				oldnspace = enter_namespace(shp,np);
2708b30d1939SAndy Fiddaman 				sh_exec(t->for_.fortre,flags|sh_state(SH_ERREXIT));
2709b30d1939SAndy Fiddaman 				enter_namespace(shp,oldnspace);
2710da2e3ebdSchin 				break;
2711da2e3ebdSchin 			}
2712da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
2713da2e3ebdSchin 			/* look for discipline functions */
27147c2fbfb3SApril Chin 			error_info.line = t->funct.functline-shp->st.firstline;
2715da2e3ebdSchin 			/* Function names cannot be special builtin */
27167c2fbfb3SApril Chin 			if(cp || shp->prefix)
2717da2e3ebdSchin 			{
27187c2fbfb3SApril Chin 				int offset = stktell(stkp);
27197c2fbfb3SApril Chin 				if(shp->prefix)
2720da2e3ebdSchin 				{
27217c2fbfb3SApril Chin 					cp = shp->prefix;
27227c2fbfb3SApril Chin 					shp->prefix = 0;
27237c2fbfb3SApril Chin 					npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
27247c2fbfb3SApril Chin 					shp->prefix = cp;
2725da2e3ebdSchin 					cp = fname;
2726da2e3ebdSchin 				}
2727da2e3ebdSchin 				else
2728da2e3ebdSchin 				{
27297c2fbfb3SApril Chin 					sfwrite(stkp,fname,cp++-fname);
27307c2fbfb3SApril Chin 					sfputc(stkp,0);
27317c2fbfb3SApril Chin 					npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
2732da2e3ebdSchin 				}
27337c2fbfb3SApril Chin 				offset = stktell(stkp);
27347c2fbfb3SApril Chin 				sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0);
27357c2fbfb3SApril Chin 				fname = stkptr(stkp,offset);
2736da2e3ebdSchin 			}
2737b30d1939SAndy Fiddaman 			else if((mp=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(mp,BLT_SPC))
2738da2e3ebdSchin 				errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname);
2739da2e3ebdSchin #if SHOPT_NAMESPACE
2740b30d1939SAndy Fiddaman 			if(shp->namespace && !shp->prefix && *fname!='.')
2741b30d1939SAndy Fiddaman 				np = sh_fsearch(shp,fname,NV_ADD|HASH_NOSCOPE);
2742b30d1939SAndy Fiddaman 			if(!np)
2743da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
2744da2e3ebdSchin 			np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
2745da2e3ebdSchin 			if(npv)
2746da2e3ebdSchin 			{
27477c2fbfb3SApril Chin 				if(!shp->mktype)
2748b30d1939SAndy Fiddaman 					cp = nv_setdisc(npv,cp,np,(Namfun_t*)npv);
2749da2e3ebdSchin 				if(!cp)
2750da2e3ebdSchin 					errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);
2751da2e3ebdSchin 			}
2752da2e3ebdSchin 			if(np->nvalue.rp)
2753da2e3ebdSchin 			{
2754b30d1939SAndy Fiddaman 				struct Ufunction *rp = np->nvalue.rp;
2755da2e3ebdSchin 				slp = (struct slnod*)np->nvenv;
2756da2e3ebdSchin 				sh_funstaks(slp->slchild,-1);
2757da2e3ebdSchin 				stakdelete(slp->slptr);
27587c2fbfb3SApril Chin 				if(shp->funload)
27597c2fbfb3SApril Chin 				{
27607c2fbfb3SApril Chin 					free((void*)np->nvalue.rp);
27617c2fbfb3SApril Chin 					np->nvalue.rp = 0;
27627c2fbfb3SApril Chin 				}
2763b30d1939SAndy Fiddaman 				if(rp->sdict)
2764b30d1939SAndy Fiddaman 				{
2765b30d1939SAndy Fiddaman 					Namval_t *mp, *nq;
2766b30d1939SAndy Fiddaman 					shp->last_root = rp->sdict;
2767b30d1939SAndy Fiddaman 					for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
2768b30d1939SAndy Fiddaman 					{
2769b30d1939SAndy Fiddaman 						_nv_unset(mp,NV_RDONLY);
2770b30d1939SAndy Fiddaman 						nq = dtnext(rp->sdict,mp);
2771b30d1939SAndy Fiddaman 						nv_delete(mp,rp->sdict,0);
2772b30d1939SAndy Fiddaman 					}
2773b30d1939SAndy Fiddaman 					dtclose(rp->sdict);
2774b30d1939SAndy Fiddaman 					rp->sdict = 0;
2775b30d1939SAndy Fiddaman 				}
27767c2fbfb3SApril Chin 			}
27777c2fbfb3SApril Chin 			if(!np->nvalue.rp)
27787c2fbfb3SApril Chin 			{
27797c2fbfb3SApril Chin 				np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
27807c2fbfb3SApril Chin 				memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
2781da2e3ebdSchin 			}
2782da2e3ebdSchin 			if(t->funct.functstak)
2783da2e3ebdSchin 			{
27847c2fbfb3SApril Chin 				static Dtdisc_t		_Rpdisc =
27857c2fbfb3SApril Chin 				{
27867c2fbfb3SApril Chin 				        offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
27877c2fbfb3SApril Chin 				};
2788da2e3ebdSchin 				struct functnod *fp;
2789b30d1939SAndy Fiddaman 				struct comnod *ac = t->funct.functargs;
2790da2e3ebdSchin 				slp = t->funct.functstak;
2791da2e3ebdSchin 				sh_funstaks(slp->slchild,1);
2792da2e3ebdSchin 				staklink(slp->slptr);
2793da2e3ebdSchin 				np->nvenv = (char*)slp;
2794da2e3ebdSchin 				nv_funtree(np) = (int*)(t->funct.functtre);
2795da2e3ebdSchin 				np->nvalue.rp->hoffset = t->funct.functloc;
2796da2e3ebdSchin 				np->nvalue.rp->lineno = t->funct.functline;
27977c2fbfb3SApril Chin 				np->nvalue.rp->nspace = shp->namespace;
2798da2e3ebdSchin 				np->nvalue.rp->fname = 0;
2799b30d1939SAndy Fiddaman 				np->nvalue.rp->argv = ac?((struct dolnod*)ac->comarg)->dolval+1:0;
2800b30d1939SAndy Fiddaman 				np->nvalue.rp->argc = ac?((struct dolnod*)ac->comarg)->dolnum:0;
28017c2fbfb3SApril Chin 				np->nvalue.rp->fdict = shp->fun_tree;
2802da2e3ebdSchin 				fp = (struct functnod*)(slp+1);
2803da2e3ebdSchin 				if(fp->functtyp==(TFUN|FAMP))
2804da2e3ebdSchin 					np->nvalue.rp->fname = fp->functnam;
2805da2e3ebdSchin 				nv_setsize(np,fp->functline);
2806da2e3ebdSchin 				nv_offattr(np,NV_FPOSIX);
28077c2fbfb3SApril Chin 				if(shp->funload)
28087c2fbfb3SApril Chin 				{
28097c2fbfb3SApril Chin 					struct Ufunction *rp = np->nvalue.rp;
28107c2fbfb3SApril Chin 					rp->np = np;
28117c2fbfb3SApril Chin 					if(!shp->fpathdict)
2812b30d1939SAndy Fiddaman 						shp->fpathdict = dtopen(&_Rpdisc,Dtobag);
28137c2fbfb3SApril Chin 					if(shp->fpathdict)
28147c2fbfb3SApril Chin 						dtinsert(shp->fpathdict,rp);
28157c2fbfb3SApril Chin 				}
2816da2e3ebdSchin 			}
2817da2e3ebdSchin 			else
2818b30d1939SAndy Fiddaman 				_nv_unset(np,0);
2819da2e3ebdSchin 			if(type&FPOSIX)
2820da2e3ebdSchin 				nv_onattr(np,NV_FUNCTION|NV_FPOSIX);
2821da2e3ebdSchin 			else
2822da2e3ebdSchin 				nv_onattr(np,NV_FUNCTION);
2823da2e3ebdSchin 			if(type&FPIN)
2824da2e3ebdSchin 				nv_onattr(np,NV_FTMP);
28257c2fbfb3SApril Chin 			if(type&FOPTGET)
28267c2fbfb3SApril Chin 				nv_onattr(np,NV_OPTGET);
2827da2e3ebdSchin 			break;
2828da2e3ebdSchin 		    }
2829da2e3ebdSchin 
2830da2e3ebdSchin 		    /* new test compound command */
2831da2e3ebdSchin 		    case TTST:
2832da2e3ebdSchin 		    {
2833da2e3ebdSchin 			register int n;
2834da2e3ebdSchin 			register char *left;
2835da2e3ebdSchin 			int negate = (type&TNEGATE)!=0;
2836b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2837b30d1939SAndy Fiddaman 			if(shp->inpool)
2838b30d1939SAndy Fiddaman 				break;
2839b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2840da2e3ebdSchin 			if(type&TTEST)
2841da2e3ebdSchin 				skipexitset++;
28427c2fbfb3SApril Chin 			error_info.line = t->tst.tstline-shp->st.firstline;
2843da2e3ebdSchin 			echeck = 1;
2844da2e3ebdSchin 			if((type&TPAREN)==TPAREN)
2845da2e3ebdSchin 			{
2846da2e3ebdSchin 				sh_exec(t->lst.lstlef,OPTIMIZE);
28477c2fbfb3SApril Chin 				n = !shp->exitval;
2848da2e3ebdSchin 			}
2849da2e3ebdSchin 			else
2850da2e3ebdSchin 			{
2851da2e3ebdSchin 				register int traceon=0;
2852da2e3ebdSchin 				register char *right;
2853da2e3ebdSchin 				register char *trap;
2854da2e3ebdSchin 				char *argv[6];
2855da2e3ebdSchin 				n = type>>TSHIFT;
28567c2fbfb3SApril Chin 				left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
2857da2e3ebdSchin 				if(type&TBINARY)
28587c2fbfb3SApril Chin 					right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
28597c2fbfb3SApril Chin 				if(trap=shp->st.trap[SH_DEBUGTRAP])
2860da2e3ebdSchin 					argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[[";
2861da2e3ebdSchin 				if(sh_isoption(SH_XTRACE))
2862da2e3ebdSchin 				{
2863b30d1939SAndy Fiddaman 					traceon = sh_trace(shp,NIL(char**),0);
2864da2e3ebdSchin 					sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3));
2865da2e3ebdSchin 				}
2866da2e3ebdSchin 				if(type&TUNARY)
2867da2e3ebdSchin 				{
2868da2e3ebdSchin 					if(traceon)
2869da2e3ebdSchin 						sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left));
2870da2e3ebdSchin 					if(trap)
2871da2e3ebdSchin 					{
2872da2e3ebdSchin 						char unop[3];
2873da2e3ebdSchin 						unop[0] = '-';
2874da2e3ebdSchin 						unop[1] = n;
2875da2e3ebdSchin 						unop[2] = 0;
2876da2e3ebdSchin 						argv[1] = unop;
2877da2e3ebdSchin 						argv[2] = left;
2878da2e3ebdSchin 						argv[3] = "]]";
2879da2e3ebdSchin 						argv[4] = 0;
28807c2fbfb3SApril Chin 						sh_debug(shp,trap,(char*)0,(char*)0,argv, 0);
2881da2e3ebdSchin 					}
2882b30d1939SAndy Fiddaman 					n = test_unop(shp,n,left);
2883da2e3ebdSchin 				}
2884da2e3ebdSchin 				else if(type&TBINARY)
2885da2e3ebdSchin 				{
2886da2e3ebdSchin 					char *op;
2887da2e3ebdSchin 					int pattern = 0;
2888da2e3ebdSchin 					if(trap || traceon)
2889da2e3ebdSchin 						op = (char*)(shtab_testops+(n&037)-1)->sh_name;
2890da2e3ebdSchin 					type >>= TSHIFT;
2891da2e3ebdSchin 					if(type==TEST_PEQ || type==TEST_PNE)
2892da2e3ebdSchin 						pattern=ARG_EXP;
2893da2e3ebdSchin 					if(trap)
2894da2e3ebdSchin 					{
2895da2e3ebdSchin 						argv[1] = left;
2896da2e3ebdSchin 						argv[2] = op;
2897da2e3ebdSchin 						argv[3] = right;
2898da2e3ebdSchin 						argv[4] = "]]";
2899da2e3ebdSchin 						argv[5] = 0;
29007c2fbfb3SApril Chin 						sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
2901da2e3ebdSchin 					}
2902b30d1939SAndy Fiddaman 					n = test_binop(shp,n,left,right);
2903da2e3ebdSchin 					if(traceon)
2904da2e3ebdSchin 					{
2905da2e3ebdSchin 						sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op);
2906da2e3ebdSchin 						if(pattern)
2907da2e3ebdSchin 							out_pattern(sfstderr,right,-1);
2908da2e3ebdSchin 						else
2909da2e3ebdSchin 							sfputr(sfstderr,sh_fmtq(right),-1);
2910da2e3ebdSchin 					}
2911da2e3ebdSchin 				}
2912da2e3ebdSchin 				if(traceon)
2913da2e3ebdSchin 					sfwrite(sfstderr,e_tstend,4);
2914da2e3ebdSchin 			}
29157c2fbfb3SApril Chin 			shp->exitval = ((!n)^negate);
2916da2e3ebdSchin 			if(!skipexitset)
2917da2e3ebdSchin 				exitset();
2918da2e3ebdSchin 			break;
2919da2e3ebdSchin 		    }
2920da2e3ebdSchin 		}
2921b30d1939SAndy Fiddaman 		if(shp->trapnote&SH_SIGALRM)
2922b30d1939SAndy Fiddaman 		{
2923b30d1939SAndy Fiddaman 			shp->trapnote &= ~SH_SIGALRM;
2924b30d1939SAndy Fiddaman 			sh_timetraps(shp);
2925b30d1939SAndy Fiddaman 		}
29267c2fbfb3SApril Chin 		if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
2927da2e3ebdSchin 			t && echeck)
2928b30d1939SAndy Fiddaman 			sh_chktrap(shp);
2929da2e3ebdSchin 		/* set $_ */
2930da2e3ebdSchin 		if(mainloop && com0)
2931da2e3ebdSchin 		{
2932da2e3ebdSchin 			/* store last argument here if it fits */
2933da2e3ebdSchin 			static char	lastarg[32];
2934da2e3ebdSchin 			if(sh_isstate(SH_FORKED))
29357c2fbfb3SApril Chin 				sh_done(shp,0);
29367c2fbfb3SApril Chin 			if(shp->lastarg!= lastarg && shp->lastarg)
29377c2fbfb3SApril Chin 				free(shp->lastarg);
29387c2fbfb3SApril Chin 			if(strlen(comn) < sizeof(lastarg))
2939da2e3ebdSchin 			{
2940da2e3ebdSchin 				nv_onattr(L_ARGNOD,NV_NOFREE);
29417c2fbfb3SApril Chin 				shp->lastarg = strcpy(lastarg,comn);
2942da2e3ebdSchin 			}
2943da2e3ebdSchin 			else
2944da2e3ebdSchin 			{
2945da2e3ebdSchin 				nv_offattr(L_ARGNOD,NV_NOFREE);
29467c2fbfb3SApril Chin 				shp->lastarg = strdup(comn);
2947da2e3ebdSchin 			}
2948da2e3ebdSchin 		}
2949da2e3ebdSchin 		if(!skipexitset)
2950da2e3ebdSchin 			exitset();
2951b30d1939SAndy Fiddaman #if SHOPT_COSHELL
2952b30d1939SAndy Fiddaman 		if(!shp->inpool && !(OPTIMIZE))
2953b30d1939SAndy Fiddaman #else
2954da2e3ebdSchin 		if(!(OPTIMIZE))
2955b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
2956da2e3ebdSchin 		{
29577c2fbfb3SApril Chin 			if(sav != stkptr(stkp,0))
29587c2fbfb3SApril Chin 				stkset(stkp,sav,0);
29597c2fbfb3SApril Chin 			else if(stktell(stkp))
29607c2fbfb3SApril Chin 				stkseek(stkp,0);
2961da2e3ebdSchin 		}
29627c2fbfb3SApril Chin 		if(shp->trapnote&SH_SIGSET)
29637c2fbfb3SApril Chin 			sh_exit(SH_EXITSIG|shp->lastsig);
2964da2e3ebdSchin 		if(was_interactive)
2965da2e3ebdSchin 			sh_onstate(SH_INTERACTIVE);
2966da2e3ebdSchin 		if(was_monitor && sh_isoption(SH_MONITOR))
2967da2e3ebdSchin 			sh_onstate(SH_MONITOR);
2968da2e3ebdSchin 		if(was_errexit)
2969da2e3ebdSchin 			sh_onstate(SH_ERREXIT);
2970da2e3ebdSchin 	}
29717c2fbfb3SApril Chin 	return(shp->exitval);
29727c2fbfb3SApril Chin }
29737c2fbfb3SApril Chin 
sh_run(int argn,char * argv[])29747c2fbfb3SApril Chin int sh_run(int argn, char *argv[])
29757c2fbfb3SApril Chin {
2976b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
29777c2fbfb3SApril Chin 	register struct dolnod	*dp;
29787c2fbfb3SApril Chin 	register struct comnod	*t = (struct comnod*)stakalloc(sizeof(struct comnod));
29797c2fbfb3SApril Chin 	int			savtop = staktell();
29807c2fbfb3SApril Chin 	char			*savptr = stakfreeze(0);
29817c2fbfb3SApril Chin 	Opt_t			*op, *np = optctx(0, 0);
29827c2fbfb3SApril Chin 	Shbltin_t		bltindata;
2983b30d1939SAndy Fiddaman 	bltindata = shp->bltindata;
29847c2fbfb3SApril Chin 	op = optctx(np, 0);
29857c2fbfb3SApril Chin 	memset(t, 0, sizeof(struct comnod));
29867c2fbfb3SApril Chin 	dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
29877c2fbfb3SApril Chin 	dp->dolnum = argn;
29887c2fbfb3SApril Chin 	dp->dolbot = ARG_SPARE;
29897c2fbfb3SApril Chin 	memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
29907c2fbfb3SApril Chin 	t->comarg = (struct argnod*)dp;
29917c2fbfb3SApril Chin 	if(!strchr(argv[0],'/'))
2992b30d1939SAndy Fiddaman 		t->comnamp = (void*)nv_bfsearch(argv[0],shp->fun_tree,(Namval_t**)&t->comnamq,(char**)0);
29937c2fbfb3SApril Chin 	argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
29947c2fbfb3SApril Chin 	optctx(op,np);
2995b30d1939SAndy Fiddaman 	shp->bltindata = bltindata;
29967c2fbfb3SApril Chin 	if(savptr!=stakptr(0))
29977c2fbfb3SApril Chin 		stakset(savptr,savtop);
29987c2fbfb3SApril Chin 	else
29997c2fbfb3SApril Chin 		stakseek(savtop);
30007c2fbfb3SApril Chin 	return(argn);
3001da2e3ebdSchin }
3002da2e3ebdSchin 
3003da2e3ebdSchin /*
3004da2e3ebdSchin  * test for equality with second argument trimmed
3005da2e3ebdSchin  * returns 1 if r == trim(s) otherwise 0
3006da2e3ebdSchin  */
3007da2e3ebdSchin 
trim_eq(register const char * r,register const char * s)3008da2e3ebdSchin static int trim_eq(register const char *r,register const char *s)
3009da2e3ebdSchin {
3010da2e3ebdSchin 	register char c;
3011da2e3ebdSchin 	while(c = *s++)
3012da2e3ebdSchin 	{
3013da2e3ebdSchin 		if(c=='\\')
3014da2e3ebdSchin 			c = *s++;
3015da2e3ebdSchin 		if(c && c != *r++)
3016da2e3ebdSchin 			return(0);
3017da2e3ebdSchin 	}
3018da2e3ebdSchin 	return(*r==0);
3019da2e3ebdSchin }
3020da2e3ebdSchin 
3021da2e3ebdSchin /*
3022da2e3ebdSchin  * print out the command line if set -x is on
3023da2e3ebdSchin  */
3024da2e3ebdSchin 
sh_trace(Shell_t * shp,register char * argv[],register int nl)3025b30d1939SAndy Fiddaman int sh_trace(Shell_t *shp,register char *argv[], register int nl)
3026da2e3ebdSchin {
3027da2e3ebdSchin 	register char *cp;
3028da2e3ebdSchin 	register int bracket = 0;
30297c2fbfb3SApril Chin 	int decl = (nl&2);
30307c2fbfb3SApril Chin 	nl &= ~2;
3031da2e3ebdSchin 	if(sh_isoption(SH_XTRACE))
3032da2e3ebdSchin 	{
3033da2e3ebdSchin 		/* make this trace atomic */
3034da2e3ebdSchin 		sfset(sfstderr,SF_SHARE|SF_PUBLIC,0);
30357c2fbfb3SApril Chin 		if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
3036da2e3ebdSchin 			cp = "+ ";
3037da2e3ebdSchin 		else
3038da2e3ebdSchin 		{
3039da2e3ebdSchin 			sh_offoption(SH_XTRACE);
30407c2fbfb3SApril Chin 			cp = sh_mactry(shp,cp);
3041da2e3ebdSchin 			sh_onoption(SH_XTRACE);
3042da2e3ebdSchin 		}
3043da2e3ebdSchin 		if(*cp)
3044da2e3ebdSchin 			sfputr(sfstderr,cp,-1);
3045da2e3ebdSchin 		if(argv)
3046da2e3ebdSchin 		{
3047da2e3ebdSchin 			char *argv0 = *argv;
3048da2e3ebdSchin 			nl = (nl?'\n':-1);
3049da2e3ebdSchin 			/* don't quote [ and [[ */
3050da2e3ebdSchin 			if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
3051da2e3ebdSchin 			{
3052da2e3ebdSchin 				sfputr(sfstderr,cp,*++argv?' ':nl);
3053da2e3ebdSchin 				bracket = 1;
3054da2e3ebdSchin 			}
3055da2e3ebdSchin 			while(cp = *argv++)
3056da2e3ebdSchin 			{
3057da2e3ebdSchin 				if(bracket==0 || *argv || *cp!=']')
3058da2e3ebdSchin 					cp = sh_fmtq(cp);
30597c2fbfb3SApril Chin 				if(decl && shp->prefix && cp!=argv0 && *cp!='-')
3060da2e3ebdSchin 				{
3061da2e3ebdSchin 					if(*cp=='.' && cp[1]==0)
30627c2fbfb3SApril Chin 						cp = shp->prefix;
3063da2e3ebdSchin 					else
30647c2fbfb3SApril Chin 						sfputr(sfstderr,shp->prefix,'.');
3065da2e3ebdSchin 				}
3066da2e3ebdSchin 				sfputr(sfstderr,cp,*argv?' ':nl);
3067da2e3ebdSchin 			}
3068da2e3ebdSchin 			sfset(sfstderr,SF_SHARE|SF_PUBLIC,1);
3069da2e3ebdSchin 		}
3070da2e3ebdSchin 		return(1);
3071da2e3ebdSchin 	}
3072da2e3ebdSchin 	return(0);
3073da2e3ebdSchin }
3074da2e3ebdSchin 
3075da2e3ebdSchin /*
3076da2e3ebdSchin  * This routine creates a subshell by calling fork() or vfork()
3077da2e3ebdSchin  * If ((flags&COMASK)==TCOM), then vfork() is permitted
3078da2e3ebdSchin  * If fork fails, the shell sleeps for exponentially longer periods
3079da2e3ebdSchin  *   and tries again until a limit is reached.
3080da2e3ebdSchin  * SH_FORKLIM is the max period between forks - power of 2 usually.
3081da2e3ebdSchin  * Currently shell tries after 2,4,8,16, and 32 seconds and then quits
3082da2e3ebdSchin  * Failures cause the routine to error exit.
3083da2e3ebdSchin  * Parent links to here-documents are removed by the child
3084da2e3ebdSchin  * Traps are reset by the child
3085da2e3ebdSchin  * The process-id of the child is returned to the parent, 0 to the child.
3086da2e3ebdSchin  */
3087da2e3ebdSchin 
timed_out(void * handle)3088da2e3ebdSchin static void timed_out(void *handle)
3089da2e3ebdSchin {
3090da2e3ebdSchin 	NOT_USED(handle);
3091da2e3ebdSchin 	timeout = 0;
3092da2e3ebdSchin }
3093da2e3ebdSchin 
3094da2e3ebdSchin 
3095da2e3ebdSchin /*
3096da2e3ebdSchin  * called by parent and child after fork by sh_fork()
3097da2e3ebdSchin  */
_sh_fork(Shell_t * shp,register pid_t parent,int flags,int * jobid)3098b30d1939SAndy Fiddaman pid_t _sh_fork(Shell_t *shp,register pid_t parent,int flags,int *jobid)
3099da2e3ebdSchin {
3100da2e3ebdSchin 	static long forkcnt = 1000L;
3101da2e3ebdSchin 	pid_t	curpgid = job.curpgid;
3102da2e3ebdSchin 	pid_t	postid = (flags&FAMP)?0:curpgid;
31037c2fbfb3SApril Chin 	int	sig,nochild;
3104da2e3ebdSchin 	if(parent<0)
3105da2e3ebdSchin 	{
3106b30d1939SAndy Fiddaman 		sh_sigcheck(shp);
3107da2e3ebdSchin 		if((forkcnt *= 2) > 1000L*SH_FORKLIM)
3108da2e3ebdSchin 		{
3109da2e3ebdSchin 			forkcnt=1000L;
3110da2e3ebdSchin 			errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork);
3111da2e3ebdSchin 		}
3112da2e3ebdSchin 		timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
31137c2fbfb3SApril Chin 		nochild = job_wait((pid_t)1);
3114da2e3ebdSchin 		if(timeout)
3115da2e3ebdSchin 		{
31167c2fbfb3SApril Chin 			if(nochild)
31177c2fbfb3SApril Chin 				pause();
31187c2fbfb3SApril Chin 			else if(forkcnt>1000L)
31197c2fbfb3SApril Chin 				forkcnt /= 2;
3120da2e3ebdSchin 			timerdel(timeout);
31217c2fbfb3SApril Chin 			timeout = 0;
3122da2e3ebdSchin 		}
3123da2e3ebdSchin 		return(-1);
3124da2e3ebdSchin 	}
31257c2fbfb3SApril Chin 	forkcnt = 1000L;
3126da2e3ebdSchin 	if(parent)
3127da2e3ebdSchin 	{
31287c2fbfb3SApril Chin 		int myjob,waitall=job.waitall;
3129b30d1939SAndy Fiddaman 		shp->gd->nforks++;
3130da2e3ebdSchin 		if(job.toclear)
3131da2e3ebdSchin 			job_clear();
31327c2fbfb3SApril Chin 		job.waitall = waitall;
3133da2e3ebdSchin #ifdef JOBS
3134da2e3ebdSchin 		/* first process defines process group */
3135da2e3ebdSchin 		if(sh_isstate(SH_MONITOR))
3136da2e3ebdSchin 		{
3137da2e3ebdSchin 			/*
3138da2e3ebdSchin 			 * errno==EPERM means that an earlier processes
3139da2e3ebdSchin 			 * completed.  Make parent the job group id.
3140da2e3ebdSchin 			 */
3141da2e3ebdSchin 			if(postid==0)
3142da2e3ebdSchin 				job.curpgid = parent;
3143da2e3ebdSchin 			if(job.jobcontrol || (flags&FAMP))
3144da2e3ebdSchin 			{
3145da2e3ebdSchin 				if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
3146da2e3ebdSchin 					setpgid(parent,parent);
3147da2e3ebdSchin 			}
3148da2e3ebdSchin 		}
3149da2e3ebdSchin #endif /* JOBS */
3150da2e3ebdSchin 		if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
3151da2e3ebdSchin 			job.curpgid = parent;
3152da2e3ebdSchin 		if(flags&FCOOP)
31537c2fbfb3SApril Chin 			shp->cpid = parent;
3154b30d1939SAndy Fiddaman 		if(!postid && job.curjobid && (flags&FPOU))
3155b30d1939SAndy Fiddaman 			postid = job.curpgid;
315634f9b3eeSRoland Mainz #ifdef SHOPT_BGX
315734f9b3eeSRoland Mainz 		if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
315834f9b3eeSRoland Mainz 			postid = 1;
3159b30d1939SAndy Fiddaman 		myjob = job_post(shp,parent,postid);
316034f9b3eeSRoland Mainz 		if(postid==1)
316134f9b3eeSRoland Mainz 			postid = 0;
316234f9b3eeSRoland Mainz #else
3163b30d1939SAndy Fiddaman 		myjob = job_post(shp,parent,postid);
316434f9b3eeSRoland Mainz #endif /* SHOPT_BGX */
3165b30d1939SAndy Fiddaman 		if(job.waitall && (flags&FPOU))
3166b30d1939SAndy Fiddaman 		{
3167b30d1939SAndy Fiddaman 			if(!job.curjobid)
3168b30d1939SAndy Fiddaman 				job.curjobid = myjob;
3169b30d1939SAndy Fiddaman 			if(job.exitval)
3170b30d1939SAndy Fiddaman 				job.exitval++;
3171b30d1939SAndy Fiddaman 		}
3172da2e3ebdSchin 		if(flags&FAMP)
3173da2e3ebdSchin 			job.curpgid = curpgid;
3174da2e3ebdSchin 		if(jobid)
3175da2e3ebdSchin 			*jobid = myjob;
3176b30d1939SAndy Fiddaman 		if(shp->comsub==1 && usepipe)
3177b30d1939SAndy Fiddaman 		{
3178b30d1939SAndy Fiddaman 			if(!tsetio || !subdup)
3179b30d1939SAndy Fiddaman 			{
3180b30d1939SAndy Fiddaman 				if(shp->topfd > restorefd)
3181b30d1939SAndy Fiddaman 					sh_iorestore(shp,restorefd,0);
3182b30d1939SAndy Fiddaman 				iounpipe(shp);
3183b30d1939SAndy Fiddaman 			}
3184b30d1939SAndy Fiddaman 		}
3185da2e3ebdSchin 		return(parent);
3186da2e3ebdSchin 	}
3187da2e3ebdSchin #if !_std_malloc
3188da2e3ebdSchin 	vmtrace(-1);
3189da2e3ebdSchin #endif
3190b30d1939SAndy Fiddaman 	shp->outpipepid = ((flags&FPOU)?getpid():0);
3191da2e3ebdSchin 	/* This is the child process */
31927c2fbfb3SApril Chin 	if(shp->trapnote&SH_SIGTERM)
3193da2e3ebdSchin 		sh_exit(SH_EXITSIG|SIGTERM);
3194b30d1939SAndy Fiddaman 	shp->gd->nforks=0;
3195da2e3ebdSchin 	timerdel(NIL(void*));
3196da2e3ebdSchin #ifdef JOBS
3197da2e3ebdSchin 	if(!job.jobcontrol && !(flags&FAMP))
3198da2e3ebdSchin 		sh_offstate(SH_MONITOR);
3199da2e3ebdSchin 	if(sh_isstate(SH_MONITOR))
3200da2e3ebdSchin 	{
3201da2e3ebdSchin 		parent = getpid();
3202da2e3ebdSchin 		if(postid==0)
3203da2e3ebdSchin 			job.curpgid = parent;
3204da2e3ebdSchin 		while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent)
3205da2e3ebdSchin 			job.curpgid = parent;
3206da2e3ebdSchin #   ifdef SIGTSTP
3207da2e3ebdSchin 		if(job.curpgid==parent &&  !(flags&FAMP))
3208da2e3ebdSchin 			tcsetpgrp(job.fd,job.curpgid);
3209da2e3ebdSchin #   endif /* SIGTSTP */
3210da2e3ebdSchin 	}
3211da2e3ebdSchin #   ifdef SIGTSTP
3212da2e3ebdSchin 	if(job.jobcontrol)
3213da2e3ebdSchin 	{
3214da2e3ebdSchin 		signal(SIGTTIN,SIG_DFL);
3215da2e3ebdSchin 		signal(SIGTTOU,SIG_DFL);
3216da2e3ebdSchin 		signal(SIGTSTP,SIG_DFL);
3217da2e3ebdSchin 	}
3218da2e3ebdSchin #   endif /* SIGTSTP */
3219da2e3ebdSchin 	job.jobcontrol = 0;
3220da2e3ebdSchin #endif /* JOBS */
3221da2e3ebdSchin 	job.toclear = 1;
32227c2fbfb3SApril Chin 	shp->login_sh = 0;
3223da2e3ebdSchin 	sh_offoption(SH_LOGIN_SHELL);
3224da2e3ebdSchin 	sh_onstate(SH_FORKED);
3225da2e3ebdSchin 	sh_onstate(SH_NOLOG);
32267c2fbfb3SApril Chin 	if (shp->fn_reset)
32277c2fbfb3SApril Chin 		shp->fn_depth = shp->fn_reset = 0;
3228da2e3ebdSchin #if SHOPT_ACCT
3229da2e3ebdSchin 	sh_accsusp();
3230da2e3ebdSchin #endif	/* SHOPT_ACCT */
3231da2e3ebdSchin 	/* Reset remaining signals to parent */
3232da2e3ebdSchin 	/* except for those `lost' by trap   */
323334f9b3eeSRoland Mainz 	if(!(flags&FSHOWME))
323434f9b3eeSRoland Mainz 		sh_sigreset(2);
32357c2fbfb3SApril Chin 	shp->subshell = 0;
3236b30d1939SAndy Fiddaman 	shp->comsub = 0;
3237b30d1939SAndy Fiddaman 	shp->spid = 0;
32387c2fbfb3SApril Chin 	if((flags&FAMP) && shp->coutpipe>1)
32397c2fbfb3SApril Chin 		sh_close(shp->coutpipe);
32407c2fbfb3SApril Chin 	sig = shp->savesig;
32417c2fbfb3SApril Chin 	shp->savesig = 0;
3242da2e3ebdSchin 	if(sig>0)
3243b30d1939SAndy Fiddaman 		kill(getpid(),sig);
3244b30d1939SAndy Fiddaman 	sh_sigcheck(shp);
3245b30d1939SAndy Fiddaman 	usepipe=0;
3246da2e3ebdSchin 	return(0);
3247da2e3ebdSchin }
3248da2e3ebdSchin 
sh_fork(Shell_t * shp,int flags,int * jobid)3249b30d1939SAndy Fiddaman pid_t sh_fork(Shell_t *shp,int flags, int *jobid)
3250da2e3ebdSchin {
3251da2e3ebdSchin 	register pid_t parent;
3252da2e3ebdSchin 	register int sig;
3253b30d1939SAndy Fiddaman 	if(!shp->pathlist)
3254b30d1939SAndy Fiddaman 		path_get(shp,"");
3255da2e3ebdSchin 	sfsync(NIL(Sfio_t*));
3256b30d1939SAndy Fiddaman 	shp->trapnote &= ~SH_SIGTERM;
3257da2e3ebdSchin 	job_fork(-1);
3258b30d1939SAndy Fiddaman 	shp->savesig = -1;
3259b30d1939SAndy Fiddaman 	while(_sh_fork(shp,parent=fork(),flags,jobid) < 0);
32607c2fbfb3SApril Chin 	sh_stats(STAT_FORKS);
3261b30d1939SAndy Fiddaman 	if(!shp->subshell)
3262b30d1939SAndy Fiddaman 	{
3263b30d1939SAndy Fiddaman 		sig = shp->savesig;
3264b30d1939SAndy Fiddaman 		shp->savesig = 0;
3265b30d1939SAndy Fiddaman 		if(sig>0)
3266b30d1939SAndy Fiddaman 			kill(getpid(),sig);
3267b30d1939SAndy Fiddaman 	}
3268da2e3ebdSchin 	job_fork(parent);
3269da2e3ebdSchin 	return(parent);
3270da2e3ebdSchin }
3271da2e3ebdSchin 
3272b30d1939SAndy Fiddaman struct Tdata
3273b30d1939SAndy Fiddaman {
3274b30d1939SAndy Fiddaman         Shell_t         *sh;
3275b30d1939SAndy Fiddaman         Namval_t        *tp;
3276b30d1939SAndy Fiddaman 	void		*extra[2];
3277b30d1939SAndy Fiddaman };
3278b30d1939SAndy Fiddaman 
3279da2e3ebdSchin /*
3280da2e3ebdSchin  * add exports from previous scope to the new scope
3281da2e3ebdSchin  */
local_exports(register Namval_t * np,void * data)3282da2e3ebdSchin static void  local_exports(register Namval_t *np, void *data)
3283da2e3ebdSchin {
3284b30d1939SAndy Fiddaman 	Shell_t			*shp = ((struct Tdata*)data)->sh;
3285da2e3ebdSchin 	register Namval_t	*mp;
3286da2e3ebdSchin 	register char		*cp;
3287da2e3ebdSchin 	if(nv_isarray(np))
3288da2e3ebdSchin 		nv_putsub(np,NIL(char*),0);
3289b30d1939SAndy Fiddaman 	if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), shp->var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
3290da2e3ebdSchin 		nv_putval(mp, cp, 0);
3291da2e3ebdSchin }
3292da2e3ebdSchin 
3293b30d1939SAndy Fiddaman /*
3294b30d1939SAndy Fiddaman  * This routine executes .sh.math functions from within ((...)))
3295b30d1939SAndy Fiddaman */
sh_mathfun(Shell_t * shp,void * fp,int nargs,Sfdouble_t * arg)3296b30d1939SAndy Fiddaman Sfdouble_t sh_mathfun(Shell_t *shp,void *fp, int nargs, Sfdouble_t *arg)
3297b30d1939SAndy Fiddaman {
3298b30d1939SAndy Fiddaman 	Sfdouble_t	d;
3299b30d1939SAndy Fiddaman 	Namval_t	node,*mp,*np, *nref[9], **nr=nref;
3300b30d1939SAndy Fiddaman 	char		*argv[2];
3301b30d1939SAndy Fiddaman 	struct funenv	funenv;
3302b30d1939SAndy Fiddaman 	int		i;
3303b30d1939SAndy Fiddaman 	np = (Namval_t*)fp;
3304b30d1939SAndy Fiddaman 	funenv.node = np;
3305b30d1939SAndy Fiddaman 	funenv.nref = nref;
3306b30d1939SAndy Fiddaman 	funenv.env = 0;
3307b30d1939SAndy Fiddaman 	memcpy(&node,SH_VALNOD,sizeof(node));
3308b30d1939SAndy Fiddaman 	SH_VALNOD->nvfun = 0;
3309b30d1939SAndy Fiddaman 	SH_VALNOD->nvenv = 0;
3310b30d1939SAndy Fiddaman 	SH_VALNOD->nvflag = NV_LDOUBLE|NV_NOFREE;
3311b30d1939SAndy Fiddaman 	SH_VALNOD->nvalue.ldp = 0;
3312b30d1939SAndy Fiddaman 	for(i=0; i < nargs; i++)
3313b30d1939SAndy Fiddaman 	{
3314b30d1939SAndy Fiddaman 		*nr++ = mp = nv_namptr(shp->mathnodes,i);
3315b30d1939SAndy Fiddaman 		mp->nvalue.ldp = arg++;
3316b30d1939SAndy Fiddaman 	}
3317b30d1939SAndy Fiddaman 	*nr = 0;
3318b30d1939SAndy Fiddaman 	SH_VALNOD->nvalue.ldp = &d;
3319b30d1939SAndy Fiddaman 	argv[0] =  np->nvname;
3320b30d1939SAndy Fiddaman 	argv[1] = 0;
3321b30d1939SAndy Fiddaman 	sh_funscope(1,argv,0,&funenv,0);
3322b30d1939SAndy Fiddaman 	while(mp= *nr++)
3323b30d1939SAndy Fiddaman 		mp->nvalue.ldp = 0;
3324b30d1939SAndy Fiddaman 	SH_VALNOD->nvfun = node.nvfun;
3325b30d1939SAndy Fiddaman 	SH_VALNOD->nvflag = node.nvflag;
3326b30d1939SAndy Fiddaman 	SH_VALNOD->nvenv = node.nvenv;
3327b30d1939SAndy Fiddaman 	SH_VALNOD->nvalue.ldp = node.nvalue.ldp;
3328b30d1939SAndy Fiddaman 	return(d);
3329b30d1939SAndy Fiddaman }
3330b30d1939SAndy Fiddaman 
3331da2e3ebdSchin /*
3332da2e3ebdSchin  * This routine is used to execute the given function <fun> in a new scope
3333da2e3ebdSchin  * If <fun> is NULL, then arg points to a structure containing a pointer
3334da2e3ebdSchin  *  to a function that will be executed in the current environment.
3335da2e3ebdSchin  */
sh_funscope(int argn,char * argv[],int (* fun)(void *),void * arg,int execflg)3336da2e3ebdSchin int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
3337da2e3ebdSchin {
33387c2fbfb3SApril Chin 	register char		*trap;
33397c2fbfb3SApril Chin 	register int		nsig;
3340b30d1939SAndy Fiddaman 	register Shell_t	*shp =  sh_getinterp();
33417c2fbfb3SApril Chin 	struct dolnod		*argsav=0,*saveargfor;
33427c2fbfb3SApril Chin 	struct sh_scoped	savst, *prevscope = shp->st.self;
33437c2fbfb3SApril Chin 	struct argnod		*envlist=0;
33447c2fbfb3SApril Chin 	int			jmpval;
33457c2fbfb3SApril Chin 	volatile int		r = 0;
3346b30d1939SAndy Fiddaman 	int			n;
33477c2fbfb3SApril Chin 	char 			*savstak;
3348b30d1939SAndy Fiddaman 	struct funenv		*fp = 0;
3349b30d1939SAndy Fiddaman 	struct checkpt	*buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
33507c2fbfb3SApril Chin 	Namval_t		*nspace = shp->namespace;
335134f9b3eeSRoland Mainz 	Dt_t			*last_root = shp->last_root;
3352b30d1939SAndy Fiddaman 	Shopt_t			options;
3353b30d1939SAndy Fiddaman 	options = shp->options;
33547c2fbfb3SApril Chin 	if(shp->fn_depth==0)
33557c2fbfb3SApril Chin 		shp->glob_options =  shp->options;
33567c2fbfb3SApril Chin 	else
33577c2fbfb3SApril Chin 		shp->options = shp->glob_options;
33587c2fbfb3SApril Chin #if 0
33597c2fbfb3SApril Chin 	shp->st.lineno = error_info.line;
33607c2fbfb3SApril Chin #endif
33617c2fbfb3SApril Chin 	*prevscope = shp->st;
3362da2e3ebdSchin 	sh_offoption(SH_ERREXIT);
33637c2fbfb3SApril Chin 	shp->st.prevst = prevscope;
33647c2fbfb3SApril Chin 	shp->st.self = &savst;
33657c2fbfb3SApril Chin 	shp->topscope = (Shscope_t*)shp->st.self;
33667c2fbfb3SApril Chin 	shp->st.opterror = shp->st.optchar = 0;
33677c2fbfb3SApril Chin 	shp->st.optindex = 1;
33687c2fbfb3SApril Chin 	shp->st.loopcnt = 0;
3369da2e3ebdSchin 	if(!fun)
3370da2e3ebdSchin 	{
3371da2e3ebdSchin 		fp = (struct funenv*)arg;
33727c2fbfb3SApril Chin 		shp->st.real_fun = (fp->node)->nvalue.rp;
3373da2e3ebdSchin 		envlist = fp->env;
3374da2e3ebdSchin 	}
33757c2fbfb3SApril Chin 	prevscope->save_tree = shp->var_tree;
3376b30d1939SAndy Fiddaman 	n = dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0);
33777c2fbfb3SApril Chin 	sh_scope(shp,envlist,1);
3378b30d1939SAndy Fiddaman 	if(n)
3379da2e3ebdSchin 	{
3380b30d1939SAndy Fiddaman 		struct Tdata tdata;
3381b30d1939SAndy Fiddaman 		memset(&tdata,0,sizeof(tdata));
3382b30d1939SAndy Fiddaman 		tdata.sh = shp;
3383da2e3ebdSchin 		/* eliminate parent scope */
3384b30d1939SAndy Fiddaman 		nv_scan(prevscope->save_tree, local_exports,&tdata, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
3385da2e3ebdSchin 	}
33867c2fbfb3SApril Chin 	shp->st.save_tree = shp->var_tree;
3387da2e3ebdSchin 	if(!fun)
3388da2e3ebdSchin 	{
3389da2e3ebdSchin 		if(nv_isattr(fp->node,NV_TAGGED))
3390da2e3ebdSchin 			sh_onoption(SH_XTRACE);
3391da2e3ebdSchin 		else
3392da2e3ebdSchin 			sh_offoption(SH_XTRACE);
3393da2e3ebdSchin 	}
33947c2fbfb3SApril Chin 	shp->st.cmdname = argv[0];
3395da2e3ebdSchin 	/* save trap table */
33967c2fbfb3SApril Chin 	if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
3397da2e3ebdSchin 	{
3398da2e3ebdSchin 		nsig += sizeof(char*);
33997c2fbfb3SApril Chin 		memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
3400da2e3ebdSchin 	}
3401da2e3ebdSchin 	sh_sigreset(0);
34027c2fbfb3SApril Chin 	argsav = sh_argnew(shp,argv,&saveargfor);
3403b30d1939SAndy Fiddaman 	sh_pushcontext(shp,buffp,SH_JMPFUN);
3404b30d1939SAndy Fiddaman 	errorpush(&buffp->err,0);
3405da2e3ebdSchin 	error_info.id = argv[0];
34067c2fbfb3SApril Chin 	shp->st.var_local = shp->var_tree;
3407da2e3ebdSchin 	if(!fun)
3408da2e3ebdSchin 	{
34097c2fbfb3SApril Chin 		shp->st.filename = fp->node->nvalue.rp->fname;
34107c2fbfb3SApril Chin 		shp->st.funname = nv_name(fp->node);
3411b30d1939SAndy Fiddaman 		shp->last_root = nv_dict(DOTSHNOD);
34127c2fbfb3SApril Chin 		nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
34137c2fbfb3SApril Chin 		nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
3414da2e3ebdSchin 	}
3415b30d1939SAndy Fiddaman 	if((execflg & sh_state(SH_NOFORK)))
3416b30d1939SAndy Fiddaman 		shp->end_fn = 1;
3417b30d1939SAndy Fiddaman 	jmpval = sigsetjmp(buffp->buff,0);
3418da2e3ebdSchin 	if(jmpval == 0)
3419da2e3ebdSchin 	{
34207c2fbfb3SApril Chin 		if(shp->fn_depth++ > MAXDEPTH)
342134f9b3eeSRoland Mainz 		{
342234f9b3eeSRoland Mainz 			shp->toomany = 1;
34237c2fbfb3SApril Chin 			siglongjmp(*shp->jmplist,SH_JMPERRFN);
342434f9b3eeSRoland Mainz 		}
3425da2e3ebdSchin 		else if(fun)
3426da2e3ebdSchin 			r= (*fun)(arg);
3427da2e3ebdSchin 		else
3428da2e3ebdSchin 		{
3429b30d1939SAndy Fiddaman 			char		**arg = shp->st.real_fun->argv;
3430b30d1939SAndy Fiddaman 			Namval_t	*np, *nq, **nref;
3431b30d1939SAndy Fiddaman 			if(nref=fp->nref)
3432b30d1939SAndy Fiddaman 			{
3433b30d1939SAndy Fiddaman 				shp->last_root = 0;
3434b30d1939SAndy Fiddaman 				for(r=0; arg[r]; r++)
3435b30d1939SAndy Fiddaman 				{
3436b30d1939SAndy Fiddaman 					np = nv_search(arg[r],shp->var_tree,HASH_NOSCOPE|NV_ADD);
3437b30d1939SAndy Fiddaman 					if(np && (nq=*nref++))
3438b30d1939SAndy Fiddaman 					{
3439b30d1939SAndy Fiddaman 						np->nvalue.nrp = newof(0,struct Namref,1,0);
3440b30d1939SAndy Fiddaman 						np->nvalue.nrp->np = nq;
3441b30d1939SAndy Fiddaman 						nv_onattr(np,NV_REF|NV_NOFREE);
3442b30d1939SAndy Fiddaman 					}
3443b30d1939SAndy Fiddaman 				}
3444b30d1939SAndy Fiddaman 			}
3445da2e3ebdSchin 			sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
34467c2fbfb3SApril Chin 			r = shp->exitval;
3447da2e3ebdSchin 		}
3448da2e3ebdSchin 	}
3449b30d1939SAndy Fiddaman 	if(shp->topscope != (Shscope_t*)shp->st.self)
3450b30d1939SAndy Fiddaman 		sh_setscope(shp->topscope);
34517c2fbfb3SApril Chin 	if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN)
3452da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]);
3453b30d1939SAndy Fiddaman 	sh_popcontext(shp,buffp);
34547c2fbfb3SApril Chin 	sh_unscope(shp);
34557c2fbfb3SApril Chin 	shp->namespace = nspace;
34567c2fbfb3SApril Chin 	shp->var_tree = (Dt_t*)prevscope->save_tree;
34577c2fbfb3SApril Chin 	sh_argreset(shp,argsav,saveargfor);
34587c2fbfb3SApril Chin 	trap = shp->st.trapcom[0];
34597c2fbfb3SApril Chin 	shp->st.trapcom[0] = 0;
3460da2e3ebdSchin 	sh_sigreset(1);
34617c2fbfb3SApril Chin 	shp->st = *prevscope;
34627c2fbfb3SApril Chin 	shp->topscope = (Shscope_t*)prevscope;
34637c2fbfb3SApril Chin 	nv_getval(sh_scoped(shp,IFSNOD));
3464b30d1939SAndy Fiddaman 	shp->end_fn = 0;
3465da2e3ebdSchin 	if(nsig)
34667c2fbfb3SApril Chin 		memcpy((char*)&shp->st.trapcom[0],savstak,nsig);
34677c2fbfb3SApril Chin 	shp->trapnote=0;
3468da2e3ebdSchin 	if(nsig)
3469da2e3ebdSchin 		stakset(savstak,0);
347034f9b3eeSRoland Mainz 	shp->options = options;
347134f9b3eeSRoland Mainz 	shp->last_root = last_root;
34723e14f97fSRoger A. Faulkner 	if(jmpval == SH_JMPSUB)
34733e14f97fSRoger A. Faulkner 		siglongjmp(*shp->jmplist,jmpval);
3474da2e3ebdSchin 	if(trap)
3475da2e3ebdSchin 	{
3476da2e3ebdSchin 		sh_trap(trap,0);
3477da2e3ebdSchin 		free(trap);
3478da2e3ebdSchin 	}
3479b30d1939SAndy Fiddaman 	if(jmpval)
3480b30d1939SAndy Fiddaman 		r=shp->exitval;
3481b30d1939SAndy Fiddaman 	if(r>SH_EXITSIG && ((r&SH_EXITMASK)==SIGINT || ((r&SH_EXITMASK)==SIGQUIT)))
3482b30d1939SAndy Fiddaman 		kill(getpid(),r&SH_EXITMASK);
3483da2e3ebdSchin 	if(jmpval > SH_JMPFUN)
3484da2e3ebdSchin 	{
3485b30d1939SAndy Fiddaman 		sh_chktrap(shp);
34867c2fbfb3SApril Chin 		siglongjmp(*shp->jmplist,jmpval);
3487da2e3ebdSchin 	}
3488da2e3ebdSchin 	return(r);
3489da2e3ebdSchin }
3490da2e3ebdSchin 
sh_funct(Shell_t * shp,Namval_t * np,int argn,char * argv[],struct argnod * envlist,int execflg)34917c2fbfb3SApril Chin static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
3492da2e3ebdSchin {
3493da2e3ebdSchin 	struct funenv fun;
3494da2e3ebdSchin 	char *fname = nv_getval(SH_FUNNAMENOD);
34957c2fbfb3SApril Chin 	struct Level	*lp =(struct Level*)(SH_LEVELNOD->nvfun);
3496b30d1939SAndy Fiddaman 	int		level, pipepid=shp->pipepid, comsub=shp->comsub;
3497b30d1939SAndy Fiddaman 	shp->comsub = 0;
349834f9b3eeSRoland Mainz 	shp->pipepid = 0;
34997c2fbfb3SApril Chin 	sh_stats(STAT_FUNCT);
35007c2fbfb3SApril Chin 	if(!lp->hdr.disc)
3501b30d1939SAndy Fiddaman 		lp = init_level(shp,0);
35027c2fbfb3SApril Chin 	if((struct sh_scoped*)shp->topscope != shp->st.self)
35037c2fbfb3SApril Chin 		sh_setscope(shp->topscope);
35047c2fbfb3SApril Chin 	level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
35057c2fbfb3SApril Chin 	SH_LEVELNOD->nvalue.s = lp->maxlevel;
35067c2fbfb3SApril Chin 	shp->st.lineno = error_info.line;
3507b30d1939SAndy Fiddaman 	np->nvalue.rp->running  += 2;
3508da2e3ebdSchin 	if(nv_isattr(np,NV_FPOSIX))
3509da2e3ebdSchin 	{
3510da2e3ebdSchin 		char *save;
35117c2fbfb3SApril Chin 		int loopcnt = shp->st.loopcnt;
35127c2fbfb3SApril Chin 		shp->posix_fun = np;
3513da2e3ebdSchin 		save = argv[-1];
3514da2e3ebdSchin 		argv[-1] = 0;
35157c2fbfb3SApril Chin 		shp->st.funname = nv_name(np);
3516b30d1939SAndy Fiddaman 		shp->last_root = nv_dict(DOTSHNOD);
3517da2e3ebdSchin 		nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE);
35187c2fbfb3SApril Chin 		opt_info.index = opt_info.offset = 0;
35197c2fbfb3SApril Chin 		error_info.errors = 0;
35207c2fbfb3SApril Chin 		shp->st.loopcnt = 0;
35217c2fbfb3SApril Chin 		b_dot_cmd(argn+1,argv-1,&shp->bltindata);
35227c2fbfb3SApril Chin 		shp->st.loopcnt = loopcnt;
3523da2e3ebdSchin 		argv[-1] = save;
3524da2e3ebdSchin 	}
3525da2e3ebdSchin 	else
3526da2e3ebdSchin 	{
3527da2e3ebdSchin 		fun.env = envlist;
3528da2e3ebdSchin 		fun.node = np;
3529b30d1939SAndy Fiddaman 		fun.nref = 0;
3530da2e3ebdSchin 		sh_funscope(argn,argv,0,&fun,execflg);
3531da2e3ebdSchin 	}
35327c2fbfb3SApril Chin 	if(level-- != nv_getnum(SH_LEVELNOD))
35337c2fbfb3SApril Chin 	{
35347c2fbfb3SApril Chin 		Shscope_t *sp = sh_getscope(0,SEEK_END);
35357c2fbfb3SApril Chin 		sh_setscope(sp);
35367c2fbfb3SApril Chin 	}
35377c2fbfb3SApril Chin 	lp->maxlevel = level;
35387c2fbfb3SApril Chin 	SH_LEVELNOD->nvalue.s = lp->maxlevel;
3539b30d1939SAndy Fiddaman 	shp->last_root = nv_dict(DOTSHNOD);
3540b30d1939SAndy Fiddaman 	shp->comsub = comsub;
35417c2fbfb3SApril Chin #if 0
35427c2fbfb3SApril Chin 	nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
35437c2fbfb3SApril Chin #else
3544da2e3ebdSchin 	nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE);
35457c2fbfb3SApril Chin #endif
35467c2fbfb3SApril Chin 	nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
354734f9b3eeSRoland Mainz 	shp->pipepid = pipepid;
3548b30d1939SAndy Fiddaman 	np->nvalue.rp->running  -= 2;
3549da2e3ebdSchin }
3550da2e3ebdSchin 
3551da2e3ebdSchin /*
3552da2e3ebdSchin  * external interface to execute a function without arguments
3553da2e3ebdSchin  * <np> is the function node
3554da2e3ebdSchin  * If <nq> is not-null, then sh.name and sh.subscript will be set
3555da2e3ebdSchin  */
sh_fun(Namval_t * np,Namval_t * nq,char * argv[])3556da2e3ebdSchin int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
3557da2e3ebdSchin {
3558b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
3559da2e3ebdSchin 	register int offset;
3560da2e3ebdSchin 	register char *base;
3561da2e3ebdSchin 	Namval_t node;
35627c2fbfb3SApril Chin 	struct Namref	nr;
35637c2fbfb3SApril Chin 	long		mode;
35647c2fbfb3SApril Chin 	char		*prefix = shp->prefix;
3565da2e3ebdSchin 	int n=0;
3566b30d1939SAndy Fiddaman 	char *av[3];
3567da2e3ebdSchin 	Fcin_t save;
3568da2e3ebdSchin 	fcsave(&save);
3569da2e3ebdSchin 	if((offset=staktell())>0)
3570da2e3ebdSchin 		base=stakfreeze(0);
35717c2fbfb3SApril Chin 	shp->prefix = 0;
3572da2e3ebdSchin 	if(!argv)
3573da2e3ebdSchin 	{
3574b30d1939SAndy Fiddaman 		argv = av+1;
3575da2e3ebdSchin 		argv[1]=0;
3576da2e3ebdSchin 	}
3577da2e3ebdSchin 	argv[0] = nv_name(np);
3578da2e3ebdSchin 	while(argv[n])
3579da2e3ebdSchin 		n++;
3580da2e3ebdSchin 	if(nq)
35813e14f97fSRoger A. Faulkner 		mode = set_instance(shp,nq,&node, &nr);
3582da2e3ebdSchin 	if(is_abuiltin(np))
3583da2e3ebdSchin 	{
3584da2e3ebdSchin 		int jmpval;
3585b30d1939SAndy Fiddaman 		struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
3586b30d1939SAndy Fiddaman 		Shbltin_t *bp = &shp->bltindata;
3587b30d1939SAndy Fiddaman 		sh_pushcontext(shp,buffp,SH_JMPCMD);
3588b30d1939SAndy Fiddaman 		jmpval = sigsetjmp(buffp->buff,1);
3589da2e3ebdSchin 		if(jmpval == 0)
3590da2e3ebdSchin 		{
35917c2fbfb3SApril Chin 			bp->bnode = np;
35927c2fbfb3SApril Chin 			bp->ptr = nv_context(np);
3593b30d1939SAndy Fiddaman 			errorpush(&buffp->err,0);
3594da2e3ebdSchin 			error_info.id = argv[0];
3595da2e3ebdSchin 			opt_info.index = opt_info.offset = 0;
3596da2e3ebdSchin 			opt_info.disc = 0;
3597b30d1939SAndy Fiddaman 			shp->exitval = 0;
3598b30d1939SAndy Fiddaman 			shp->exitval = ((Shbltin_f)funptr(np))(n,argv,bp);
3599da2e3ebdSchin 		}
3600b30d1939SAndy Fiddaman 		sh_popcontext(shp,buffp);
3601da2e3ebdSchin 		if(jmpval>SH_JMPCMD)
3602b30d1939SAndy Fiddaman 			siglongjmp(*shp->jmplist,jmpval);
3603da2e3ebdSchin 	}
3604da2e3ebdSchin 	else
36057c2fbfb3SApril Chin 		sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
3606da2e3ebdSchin 	if(nq)
36077c2fbfb3SApril Chin 		unset_instance(nq, &node, &nr, mode);
3608da2e3ebdSchin 	fcrestore(&save);
3609da2e3ebdSchin 	if(offset>0)
3610da2e3ebdSchin 		stakset(base,offset);
36117c2fbfb3SApril Chin 	shp->prefix = prefix;
3612b30d1939SAndy Fiddaman 	return(shp->exitval);
3613da2e3ebdSchin }
3614da2e3ebdSchin 
3615da2e3ebdSchin /*
3616da2e3ebdSchin  * This dummy routine is called by built-ins that do recursion
3617da2e3ebdSchin  * on the file system (chmod, chgrp, chown).  It causes
3618da2e3ebdSchin  * the shell to invoke the non-builtin version in this case
3619da2e3ebdSchin  */
cmdrecurse(int argc,char * argv[],int ac,char * av[])3620da2e3ebdSchin int cmdrecurse(int argc, char* argv[], int ac, char* av[])
3621da2e3ebdSchin {
3622da2e3ebdSchin 	NOT_USED(argc);
3623da2e3ebdSchin 	NOT_USED(argv[0]);
3624da2e3ebdSchin 	NOT_USED(ac);
3625da2e3ebdSchin 	NOT_USED(av[0]);
3626da2e3ebdSchin 	return(SH_RUNPROG);
3627da2e3ebdSchin }
3628da2e3ebdSchin 
3629da2e3ebdSchin /*
3630da2e3ebdSchin  * set up pipe for cooperating process
3631da2e3ebdSchin  */
coproc_init(Shell_t * shp,int pipes[])36327c2fbfb3SApril Chin static void coproc_init(Shell_t *shp, int pipes[])
3633da2e3ebdSchin {
3634da2e3ebdSchin 	int outfd;
36357c2fbfb3SApril Chin 	if(shp->coutpipe>=0 && shp->cpid)
3636da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_pexists);
36377c2fbfb3SApril Chin 	shp->cpid = 0;
36387c2fbfb3SApril Chin 	if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0)
3639da2e3ebdSchin 	{
3640da2e3ebdSchin 		/* first co-process */
36417c2fbfb3SApril Chin 		sh_pclose(shp->cpipe);
36427c2fbfb3SApril Chin 		sh_pipe(shp->cpipe);
36437c2fbfb3SApril Chin 		if((outfd=shp->cpipe[1]) < 10)
3644da2e3ebdSchin 		{
36457c2fbfb3SApril Chin 		        int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
3646b30d1939SAndy Fiddaman 			VALIDATE_FD(shp, outfd);
3647b30d1939SAndy Fiddaman 			VALIDATE_FD(shp, fd);
3648da2e3ebdSchin 			if(fd>=10)
3649da2e3ebdSchin 			{
36507c2fbfb3SApril Chin 			        shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
3651da2e3ebdSchin 				close(outfd);
36527c2fbfb3SApril Chin 			        shp->fdstatus[outfd] = IOCLOSE;
36537c2fbfb3SApril Chin 				shp->cpipe[1] = fd;
3654da2e3ebdSchin 			}
3655da2e3ebdSchin 		}
3656b30d1939SAndy Fiddaman 		VALIDATE_FD(shp, shp->cpipe[0]);
3657b30d1939SAndy Fiddaman 		VALIDATE_FD(shp, shp->cpipe[1]);
3658b30d1939SAndy Fiddaman 
36597c2fbfb3SApril Chin 		if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0)
36607c2fbfb3SApril Chin 			shp->fdstatus[shp->cpipe[0]] |= IOCLEX;
36617c2fbfb3SApril Chin 		shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
3662da2e3ebdSchin 
36637c2fbfb3SApril Chin 		if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0)
36647c2fbfb3SApril Chin 			shp->fdstatus[shp->cpipe[1]] |= IOCLEX;
3665da2e3ebdSchin 	}
36667c2fbfb3SApril Chin 	shp->outpipe = shp->cpipe;
36677c2fbfb3SApril Chin 	sh_pipe(shp->inpipe=pipes);
36687c2fbfb3SApril Chin 	shp->coutpipe = shp->inpipe[1];
3669b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, shp->coutpipe);
36707c2fbfb3SApril Chin 	shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
3671b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, shp->outpipe[0]);
36727c2fbfb3SApril Chin 	if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
36737c2fbfb3SApril Chin 		shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
3674da2e3ebdSchin }
3675da2e3ebdSchin 
3676da2e3ebdSchin #if SHOPT_SPAWN
3677da2e3ebdSchin 
3678da2e3ebdSchin 
3679da2e3ebdSchin #if SHOPT_AMP || !defined(_lib_fork)
3680da2e3ebdSchin 
3681da2e3ebdSchin /*
3682da2e3ebdSchin  * create a shell script consisting of t->fork.forktre and execute it
3683da2e3ebdSchin  */
run_subshell(Shell_t * shp,const Shnode_t * t,pid_t grp)3684b30d1939SAndy Fiddaman static int run_subshell(Shell_t *shp,const Shnode_t *t,pid_t grp)
3685da2e3ebdSchin {
36867c2fbfb3SApril Chin 	static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
3687da2e3ebdSchin 	register int i, fd, trace = sh_isoption(SH_XTRACE);
3688da2e3ebdSchin 	int pin,pout;
3689da2e3ebdSchin 	pid_t pid;
3690b30d1939SAndy Fiddaman 	char *arglist[3], *envlist[2], devfd[12], *cp;
3691da2e3ebdSchin 	Sfio_t *sp = sftmp(0);
3692da2e3ebdSchin 	envlist[0] = "_=" SH_ID;
3693da2e3ebdSchin 	envlist[1] = 0;
3694b30d1939SAndy Fiddaman 	arglist[0] = error_info.id?error_info.id:shp->shname;
3695da2e3ebdSchin 	if(*arglist[0]=='-')
3696da2e3ebdSchin 		arglist[0]++;
3697da2e3ebdSchin 	arglist[1] = devfd;
3698da2e3ebdSchin 	strncpy(devfd,e_devfdNN,sizeof(devfd));
3699da2e3ebdSchin 	arglist[2] = 0;
3700da2e3ebdSchin 	sfstack(sfstdout,sp);
3701da2e3ebdSchin 	if(trace)
3702da2e3ebdSchin 		sh_offoption(SH_XTRACE);
3703da2e3ebdSchin 	sfwrite(sfstdout,"typeset -A -- ",14);
3704da2e3ebdSchin 	sh_trap(prolog,0);
3705b30d1939SAndy Fiddaman 	nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
3706b30d1939SAndy Fiddaman 	if(shp->st.dolc>0)
3707da2e3ebdSchin 	{
3708da2e3ebdSchin 		/* pass the positional parameters */
3709b30d1939SAndy Fiddaman 		char **argv = shp->st.dolv+1;
3710da2e3ebdSchin 		sfwrite(sfstdout,"set --",6);
3711da2e3ebdSchin 		while(*argv)
3712da2e3ebdSchin 			sfprintf(sfstdout," %s",sh_fmtq(*argv++));
3713da2e3ebdSchin 		sfputc(sfstdout,'\n');
3714da2e3ebdSchin 	}
3715b30d1939SAndy Fiddaman 	pin = (shp->inpipe?shp->inpipe[1]:0);
3716b30d1939SAndy Fiddaman 	pout = (shp->outpipe?shp->outpipe[0]:0);
3717da2e3ebdSchin 	for(i=3; i < 10; i++)
3718da2e3ebdSchin 	{
3719b30d1939SAndy Fiddaman 		if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
3720da2e3ebdSchin 		{
3721da2e3ebdSchin 			sfprintf(sfstdout,"exec %d<&%d\n",i,i);
3722da2e3ebdSchin 			fcntl(i,F_SETFD,0);
3723da2e3ebdSchin 		}
3724da2e3ebdSchin 	}
3725da2e3ebdSchin 	sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline);
3726da2e3ebdSchin 	if(trace)
3727da2e3ebdSchin 	{
3728da2e3ebdSchin 		sfwrite(sfstdout,"set -x\n",7);
3729da2e3ebdSchin 		sh_onoption(SH_XTRACE);
3730da2e3ebdSchin 	}
3731da2e3ebdSchin 	sfstack(sfstdout,NIL(Sfio_t*));
3732da2e3ebdSchin 	sh_deparse(sp,t->fork.forktre,0);
3733da2e3ebdSchin 	sfseek(sp,(Sfoff_t)0,SEEK_SET);
3734da2e3ebdSchin 	fd = sh_dup(sffileno(sp));
3735da2e3ebdSchin 	cp = devfd+8;
3736da2e3ebdSchin 	if(fd>9)
3737da2e3ebdSchin 		*cp++ = '0' + (fd/10);
3738da2e3ebdSchin 	*cp++ = '0' + fd%10;
3739da2e3ebdSchin 	*cp = 0;
3740da2e3ebdSchin 	sfclose(sp);
3741da2e3ebdSchin 	sfsync(NIL(Sfio_t*));
3742b30d1939SAndy Fiddaman 	if(!shp->gd->shpath)
3743b30d1939SAndy Fiddaman 		shp->gd->shpath = pathshell();
3744b30d1939SAndy Fiddaman 	pid = spawnveg(shp->shpath,arglist,envlist,grp);
3745da2e3ebdSchin 	close(fd);
3746da2e3ebdSchin 	for(i=3; i < 10; i++)
3747da2e3ebdSchin 	{
3748b30d1939SAndy Fiddaman 		if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
3749da2e3ebdSchin 			fcntl(i,F_SETFD,FD_CLOEXEC);
3750da2e3ebdSchin 	}
3751da2e3ebdSchin 	if(pid <=0)
3752da2e3ebdSchin 		errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
3753da2e3ebdSchin 	return(pid);
3754da2e3ebdSchin }
3755da2e3ebdSchin #endif /* !_lib_fork */
3756da2e3ebdSchin 
sigreset(Shell_t * shp,int mode)3757b30d1939SAndy Fiddaman static void sigreset(Shell_t *shp,int mode)
3758da2e3ebdSchin {
3759da2e3ebdSchin 	register char   *trap;
3760b30d1939SAndy Fiddaman 	register int sig=shp->st.trapmax;
3761da2e3ebdSchin 	while(sig-- > 0)
3762da2e3ebdSchin 	{
3763b30d1939SAndy Fiddaman 		if(sig==SIGCHLD)
3764b30d1939SAndy Fiddaman 			continue;
3765b30d1939SAndy Fiddaman 		if((trap=shp->st.trapcom[sig]) && *trap==0)
3766da2e3ebdSchin 			signal(sig,mode?sh_fault:SIG_IGN);
3767da2e3ebdSchin 	}
3768da2e3ebdSchin }
3769da2e3ebdSchin 
3770da2e3ebdSchin /*
3771da2e3ebdSchin  * A combined fork/exec for systems with slow or non-existent fork()
3772da2e3ebdSchin  */
sh_ntfork(Shell_t * shp,const Shnode_t * t,char * argv[],int * jobid,int flag)37737c2fbfb3SApril Chin static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
3774da2e3ebdSchin {
3775da2e3ebdSchin 	static pid_t	spawnpid;
3776da2e3ebdSchin 	static int	savetype;
377719700af4SToomas Soome 	static int	savejobid __unused;
3778b30d1939SAndy Fiddaman 	struct checkpt	*buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
3779b30d1939SAndy Fiddaman 	int		otype=0, jmpval,jobfork=0;
37807c2fbfb3SApril Chin 	volatile int	jobwasset=0, scope=0, sigwasset=0;
37817c2fbfb3SApril Chin 	char		**arge, *path;
37827c2fbfb3SApril Chin 	volatile pid_t	grp = 0;
37837c2fbfb3SApril Chin 	Pathcomp_t	*pp;
3784da2e3ebdSchin 	if(flag)
3785da2e3ebdSchin 	{
3786da2e3ebdSchin 		otype = savetype;
3787da2e3ebdSchin 		savetype=0;
3788da2e3ebdSchin 	}
3789da2e3ebdSchin #   if SHOPT_AMP || !defined(_lib_fork)
3790da2e3ebdSchin 	if(!argv)
3791da2e3ebdSchin 	{
3792da2e3ebdSchin 		register Shnode_t *tchild = t->fork.forktre;
3793da2e3ebdSchin 		int optimize=0;
3794da2e3ebdSchin 		otype = t->tre.tretyp;
3795da2e3ebdSchin 		savetype = otype;
3796da2e3ebdSchin 		spawnpid = 0;
3797da2e3ebdSchin #	ifndef _lib_fork
3798da2e3ebdSchin 		if((tchild->tre.tretyp&COMMSK)==TCOM)
3799da2e3ebdSchin 		{
3800da2e3ebdSchin 			Namval_t *np = (Namval_t*)(tchild->com.comnamp);
3801da2e3ebdSchin 			if(np)
3802da2e3ebdSchin 			{
3803da2e3ebdSchin 				path = nv_name(np);
3804da2e3ebdSchin 				if(!nv_isattr(np,BLT_ENV))
3805da2e3ebdSchin 					np=0;
3806da2e3ebdSchin 				else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
3807da2e3ebdSchin 					np=0;
3808da2e3ebdSchin 			}
3809da2e3ebdSchin 			else if(!tchild->com.comarg)
3810da2e3ebdSchin 				optimize=1;
3811da2e3ebdSchin 			else if(tchild->com.comtyp&COMSCAN)
3812da2e3ebdSchin 			{
3813da2e3ebdSchin 				if(tchild->com.comarg->argflag&ARG_RAW)
3814da2e3ebdSchin 					path = tchild->com.comarg->argval;
3815da2e3ebdSchin 				else
3816da2e3ebdSchin 					path = 0;
3817da2e3ebdSchin 			}
3818da2e3ebdSchin 			else
3819da2e3ebdSchin 				path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
3820da2e3ebdSchin 			if(!np && path && !nv_search(path,shp->fun_tree,0))
3821da2e3ebdSchin 				optimize=1;
3822da2e3ebdSchin 		}
3823da2e3ebdSchin #	endif
3824b30d1939SAndy Fiddaman 		sh_pushcontext(shp,buffp,SH_JMPIO);
3825b30d1939SAndy Fiddaman 		jmpval = sigsetjmp(buffp->buff,0);
3826da2e3ebdSchin 		{
3827da2e3ebdSchin 			if((otype&FINT) && !sh_isstate(SH_MONITOR))
3828da2e3ebdSchin 			{
3829da2e3ebdSchin 				signal(SIGQUIT,SIG_IGN);
3830da2e3ebdSchin 				signal(SIGINT,SIG_IGN);
3831da2e3ebdSchin 				if(!shp->st.ioset)
3832da2e3ebdSchin 				{
3833b30d1939SAndy Fiddaman 					sh_iosave(shp,0,buffp->topfd,(char*)0);
38347c2fbfb3SApril Chin 					sh_iorenumber(shp,sh_chkopen(e_devnull),0);
3835da2e3ebdSchin 				}
3836da2e3ebdSchin 			}
3837da2e3ebdSchin 			if(otype&FPIN)
3838da2e3ebdSchin 			{
3839da2e3ebdSchin 				int fd = shp->inpipe[1];
3840b30d1939SAndy Fiddaman 				sh_iosave(shp,0,buffp->topfd,(char*)0);
38417c2fbfb3SApril Chin 				sh_iorenumber(shp,shp->inpipe[0],0);
3842b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, fd);
3843da2e3ebdSchin 				if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
3844da2e3ebdSchin 					shp->fdstatus[fd] |= IOCLEX;
3845da2e3ebdSchin 			}
3846da2e3ebdSchin 			if(otype&FPOU)
3847da2e3ebdSchin 			{
3848b30d1939SAndy Fiddaman #if SHOPT_COSHELL
3849b30d1939SAndy Fiddaman 					if(shp->outpipe[2] > 20000)
3850b30d1939SAndy Fiddaman 						sh_coaccept(shp,shp->outpipe,1);
3851b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
3852b30d1939SAndy Fiddaman 				sh_iosave(shp,1,buffp->topfd,(char*)0);
38537c2fbfb3SApril Chin 				sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1);
3854b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, shp->outpipe[0]);
3855da2e3ebdSchin 				if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
3856da2e3ebdSchin 					shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
3857da2e3ebdSchin 			}
3858da2e3ebdSchin 
3859da2e3ebdSchin 			if(t->fork.forkio)
38607c2fbfb3SApril Chin 				sh_redirect(shp,t->fork.forkio,0);
3861da2e3ebdSchin 			if(optimize==0)
3862da2e3ebdSchin 			{
3863da2e3ebdSchin #ifdef SIGTSTP
3864da2e3ebdSchin 				if(job.jobcontrol)
3865da2e3ebdSchin 				{
3866da2e3ebdSchin 					signal(SIGTTIN,SIG_DFL);
3867da2e3ebdSchin 					signal(SIGTTOU,SIG_DFL);
3868da2e3ebdSchin 				}
3869da2e3ebdSchin #endif /* SIGTSTP */
3870da2e3ebdSchin #ifdef JOBS
3871da2e3ebdSchin 				if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3872da2e3ebdSchin 				{
3873da2e3ebdSchin 					if((otype&FAMP) || job.curpgid==0)
3874da2e3ebdSchin 						grp = 1;
3875da2e3ebdSchin 					else
3876da2e3ebdSchin 						grp = job.curpgid;
3877da2e3ebdSchin 				}
3878da2e3ebdSchin #endif /* JOBS */
3879b30d1939SAndy Fiddaman 				spawnpid = run_subshell(shp,t,grp);
3880da2e3ebdSchin 			}
3881da2e3ebdSchin 			else
3882da2e3ebdSchin 			{
3883da2e3ebdSchin 				sh_exec(tchild,SH_NTFORK);
3884da2e3ebdSchin 				if(jobid)
3885da2e3ebdSchin 					*jobid = savejobid;
3886da2e3ebdSchin 			}
3887da2e3ebdSchin 		}
3888b30d1939SAndy Fiddaman 		sh_popcontext(shp,buffp);
3889da2e3ebdSchin 		if((otype&FINT) && !sh_isstate(SH_MONITOR))
3890da2e3ebdSchin 		{
3891da2e3ebdSchin 			signal(SIGQUIT,sh_fault);
3892da2e3ebdSchin 			signal(SIGINT,sh_fault);
3893da2e3ebdSchin 		}
3894b30d1939SAndy Fiddaman 		VALIDATE_FD(shp, shp->inpipe[1]);
3895da2e3ebdSchin 		if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
3896da2e3ebdSchin 			shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX;
3897da2e3ebdSchin 		if(t->fork.forkio || otype)
3898b30d1939SAndy Fiddaman 			sh_iorestore(shp,buffp->topfd,jmpval);
3899da2e3ebdSchin 		if(optimize==0)
3900da2e3ebdSchin 		{
3901da2e3ebdSchin #ifdef SIGTSTP
3902da2e3ebdSchin 			if(job.jobcontrol)
3903da2e3ebdSchin 			{
3904da2e3ebdSchin 				signal(SIGTTIN,SIG_IGN);
3905da2e3ebdSchin 				signal(SIGTTOU,SIG_IGN);
3906da2e3ebdSchin 			}
3907da2e3ebdSchin #endif /* SIGTSTP */
3908da2e3ebdSchin 			if(spawnpid>0)
3909b30d1939SAndy Fiddaman 				_sh_fork(shp,spawnpid,otype,jobid);
3910da2e3ebdSchin 			if(grp>0 && !(otype&FAMP))
3911da2e3ebdSchin 			{
3912da2e3ebdSchin 				while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
3913da2e3ebdSchin 					job.curpgid = spawnpid;
3914da2e3ebdSchin 			}
3915da2e3ebdSchin 		}
3916da2e3ebdSchin 		savetype=0;
3917da2e3ebdSchin 		if(jmpval>SH_JMPIO)
3918da2e3ebdSchin 			siglongjmp(*shp->jmplist,jmpval);
3919da2e3ebdSchin 		if(spawnpid<0 && (otype&FCOOP))
3920da2e3ebdSchin 		{
3921da2e3ebdSchin 			sh_close(shp->coutpipe);
3922da2e3ebdSchin 			sh_close(shp->cpipe[1]);
3923da2e3ebdSchin 			shp->cpipe[1] = -1;
3924da2e3ebdSchin 			shp->coutpipe = -1;
3925da2e3ebdSchin 		}
3926da2e3ebdSchin 		shp->exitval = 0;
3927da2e3ebdSchin 		return(spawnpid);
3928da2e3ebdSchin 	}
3929da2e3ebdSchin #   endif /* !_lib_fork */
3930b30d1939SAndy Fiddaman 	sh_pushcontext(shp,buffp,SH_JMPCMD);
3931b30d1939SAndy Fiddaman 	errorpush(&buffp->err,ERROR_SILENT);
3932b30d1939SAndy Fiddaman 	jmpval = sigsetjmp(buffp->buff,0);
3933da2e3ebdSchin 	if(jmpval == 0)
3934da2e3ebdSchin 	{
3935da2e3ebdSchin 		if((otype&FINT) && !sh_isstate(SH_MONITOR))
3936da2e3ebdSchin 		{
3937da2e3ebdSchin 			signal(SIGQUIT,SIG_IGN);
3938da2e3ebdSchin 			signal(SIGINT,SIG_IGN);
3939da2e3ebdSchin 		}
3940da2e3ebdSchin 		spawnpid = -1;
3941da2e3ebdSchin 		if(t->com.comio)
39427c2fbfb3SApril Chin 			sh_redirect(shp,t->com.comio,0);
3943da2e3ebdSchin 		error_info.id = *argv;
3944da2e3ebdSchin 		if(t->com.comset)
3945da2e3ebdSchin 		{
3946da2e3ebdSchin 			scope++;
39477c2fbfb3SApril Chin 			sh_scope(shp,t->com.comset,0);
3948da2e3ebdSchin 		}
3949da2e3ebdSchin 		if(!strchr(path=argv[0],'/'))
3950da2e3ebdSchin 		{
3951da2e3ebdSchin 			Namval_t *np;
3952da2e3ebdSchin 			if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
3953da2e3ebdSchin 				path = nv_getval(np);
3954b30d1939SAndy Fiddaman 			else if(path_absolute(shp,path,NIL(Pathcomp_t*)))
3955da2e3ebdSchin 			{
3956b30d1939SAndy Fiddaman 				path = stkptr(shp->stk,PATH_OFFSET);
3957b30d1939SAndy Fiddaman 				stkfreeze(shp->stk,0);
3958b30d1939SAndy Fiddaman 			}
3959b30d1939SAndy Fiddaman 			else
39607c2fbfb3SApril Chin 			{
3961b30d1939SAndy Fiddaman 				pp=path_get(shp,path);
3962b30d1939SAndy Fiddaman 				while(pp)
3963b30d1939SAndy Fiddaman 				{
3964b30d1939SAndy Fiddaman 					if(pp->len==1 && *pp->name=='.')
3965b30d1939SAndy Fiddaman 						break;
3966b30d1939SAndy Fiddaman 					pp = pp->next;
3967b30d1939SAndy Fiddaman 				}
3968b30d1939SAndy Fiddaman 				if(!pp)
3969b30d1939SAndy Fiddaman 					path = 0;
39707c2fbfb3SApril Chin 			}
3971da2e3ebdSchin 		}
3972b30d1939SAndy Fiddaman 		else if(sh_isoption(SH_RESTRICTED))
3973b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
3974b30d1939SAndy Fiddaman 		if(!path)
3975b30d1939SAndy Fiddaman 		{
3976b30d1939SAndy Fiddaman 			spawnpid = -1;
3977b30d1939SAndy Fiddaman 			goto fail;
3978b30d1939SAndy Fiddaman 		}
3979b30d1939SAndy Fiddaman 		arge = sh_envgen();
3980b30d1939SAndy Fiddaman 		shp->exitval = 0;
3981da2e3ebdSchin #ifdef SIGTSTP
3982da2e3ebdSchin 		if(job.jobcontrol)
3983da2e3ebdSchin 		{
3984da2e3ebdSchin 			signal(SIGTTIN,SIG_DFL);
3985da2e3ebdSchin 			signal(SIGTTOU,SIG_DFL);
3986da2e3ebdSchin 			jobwasset++;
3987da2e3ebdSchin 		}
3988da2e3ebdSchin #endif /* SIGTSTP */
3989da2e3ebdSchin #ifdef JOBS
3990da2e3ebdSchin 		if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3991da2e3ebdSchin 		{
3992da2e3ebdSchin 			if((otype&FAMP) || job.curpgid==0)
3993da2e3ebdSchin 				grp = 1;
3994da2e3ebdSchin 			else
3995da2e3ebdSchin 				grp = job.curpgid;
3996da2e3ebdSchin 		}
3997da2e3ebdSchin #endif /* JOBS */
3998da2e3ebdSchin 
3999da2e3ebdSchin 		sfsync(NIL(Sfio_t*));
4000b30d1939SAndy Fiddaman 		sigreset(shp,0);	/* set signals to ignore */
4001da2e3ebdSchin 		sigwasset++;
4002da2e3ebdSchin 	        /* find first path that has a library component */
4003b30d1939SAndy Fiddaman 		for(pp=path_get(shp,argv[0]); pp && !pp->lib ; pp=pp->next);
4004b30d1939SAndy Fiddaman 		job_fork(-1);
4005b30d1939SAndy Fiddaman 		jobfork = 1;
4006b30d1939SAndy Fiddaman 		spawnpid = path_spawn(shp,path,argv,arge,pp,(grp<<1)|1);
4007da2e3ebdSchin 		if(spawnpid < 0 && errno==ENOEXEC)
4008da2e3ebdSchin 		{
4009da2e3ebdSchin 			char *devfd;
4010da2e3ebdSchin 			int fd = open(path,O_RDONLY);
4011da2e3ebdSchin 			argv[-1] = argv[0];
4012da2e3ebdSchin 			argv[0] = path;
4013da2e3ebdSchin 			if(fd>=0)
4014da2e3ebdSchin 			{
4015da2e3ebdSchin 				struct stat statb;
4016b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,"/dev/fd/%d",fd);
4017b30d1939SAndy Fiddaman 				if(stat(devfd=sfstruse(shp->strbuf),&statb)>=0)
4018da2e3ebdSchin 					argv[0] =  devfd;
4019da2e3ebdSchin 			}
4020b30d1939SAndy Fiddaman 			if(!shp->gd->shpath)
4021b30d1939SAndy Fiddaman 				shp->gd->shpath = pathshell();
4022b30d1939SAndy Fiddaman 			spawnpid = path_spawn(shp,shp->gd->shpath,&argv[-1],arge,pp,(grp<<1)|1);
4023da2e3ebdSchin 			if(fd>=0)
4024da2e3ebdSchin 				close(fd);
4025da2e3ebdSchin 			argv[0] = argv[-1];
4026da2e3ebdSchin 		}
4027da2e3ebdSchin 	fail:
4028b30d1939SAndy Fiddaman 		if(jobfork && spawnpid<0)
4029b30d1939SAndy Fiddaman 			job_fork(0);
4030da2e3ebdSchin 		if(spawnpid < 0) switch(errno=shp->path_err)
4031da2e3ebdSchin 		{
4032da2e3ebdSchin 		    case ENOENT:
4033da2e3ebdSchin 			errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4);
40345ae8bd53SToomas Soome 			/* FALLTHROUGH */
4035da2e3ebdSchin 		    default:
4036da2e3ebdSchin 			errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
4037da2e3ebdSchin 		}
4038da2e3ebdSchin 	}
4039da2e3ebdSchin 	else
4040da2e3ebdSchin 		exitset();
4041b30d1939SAndy Fiddaman 	sh_popcontext(shp,buffp);
4042b30d1939SAndy Fiddaman 	if(buffp->olist)
4043b30d1939SAndy Fiddaman 		free_list(buffp->olist);
4044da2e3ebdSchin #ifdef SIGTSTP
4045da2e3ebdSchin 	if(jobwasset)
4046da2e3ebdSchin 	{
4047da2e3ebdSchin 		signal(SIGTTIN,SIG_IGN);
4048da2e3ebdSchin 		signal(SIGTTOU,SIG_IGN);
4049da2e3ebdSchin 	}
4050da2e3ebdSchin #endif /* SIGTSTP */
4051da2e3ebdSchin 	if(sigwasset)
4052b30d1939SAndy Fiddaman 		sigreset(shp,1);	/* restore ignored signals */
4053da2e3ebdSchin 	if(scope)
4054da2e3ebdSchin 	{
40557c2fbfb3SApril Chin 		sh_unscope(shp);
4056da2e3ebdSchin 		if(jmpval==SH_JMPSCRIPT)
405734f9b3eeSRoland Mainz 			nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
4058da2e3ebdSchin 	}
4059b30d1939SAndy Fiddaman 	if(t->com.comio && (jmpval || spawnpid<=0))
4060b30d1939SAndy Fiddaman 		sh_iorestore(shp,buffp->topfd,jmpval);
4061da2e3ebdSchin 	if(jmpval>SH_JMPCMD)
4062da2e3ebdSchin 		siglongjmp(*shp->jmplist,jmpval);
4063da2e3ebdSchin 	if(spawnpid>0)
4064da2e3ebdSchin 	{
4065b30d1939SAndy Fiddaman 		_sh_fork(shp,spawnpid,otype,jobid);
4066b30d1939SAndy Fiddaman 		job_fork(spawnpid);
4067da2e3ebdSchin #ifdef JOBS
4068da2e3ebdSchin 		if(grp==1)
4069da2e3ebdSchin 			job.curpgid = spawnpid;
4070da2e3ebdSchin #   ifdef SIGTSTP
4071da2e3ebdSchin 		if(grp>0 && !(otype&FAMP))
4072da2e3ebdSchin 		{
4073da2e3ebdSchin 			while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
4074da2e3ebdSchin 				job.curpgid = spawnpid;
4075da2e3ebdSchin 		}
4076da2e3ebdSchin #   endif /* SIGTSTP */
4077da2e3ebdSchin #endif /* JOBS */
4078da2e3ebdSchin 		savejobid = *jobid;
4079da2e3ebdSchin 		if(otype)
4080da2e3ebdSchin 			return(0);
4081da2e3ebdSchin 	}
4082da2e3ebdSchin 	return(spawnpid);
4083da2e3ebdSchin }
4084da2e3ebdSchin 
4085da2e3ebdSchin #   ifdef _was_lib_fork
4086da2e3ebdSchin #	define _lib_fork	1
4087da2e3ebdSchin #   endif
4088da2e3ebdSchin #   ifndef _lib_fork
fork(void)4089da2e3ebdSchin 	pid_t fork(void)
4090da2e3ebdSchin 	{
4091da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork");
4092da2e3ebdSchin 		return(-1);
4093da2e3ebdSchin 	}
4094da2e3ebdSchin #   endif /* _lib_fork */
4095da2e3ebdSchin #endif /* SHOPT_SPAWN */
4096