1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1982-2010 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                  David Korn <dgk@research.att.com>                   *
18*                                                                      *
19***********************************************************************/
20#pragma prototyped
21/*
22 * UNIX shell parse tree executer
23 *
24 *   David Korn
25 *   AT&T Labs
26 *
27 */
28
29#include	"defs.h"
30#include	<fcin.h>
31#include	"variables.h"
32#include	"path.h"
33#include	"name.h"
34#include	"io.h"
35#include	"shnodes.h"
36#include	"jobs.h"
37#include	"test.h"
38#include	"builtins.h"
39#include	"FEATURE/time"
40#include	"FEATURE/externs"
41#include	"FEATURE/locale"
42#include	"streval.h"
43
44#if !_std_malloc
45#   include	<vmalloc.h>
46#endif
47
48#if     _lib_vfork
49#   include     <ast_vfork.h>
50#else
51#   define vfork()      fork()
52#endif
53
54#define SH_NTFORK	SH_TIMING
55
56#if _lib_nice
57    extern int	nice(int);
58#endif /* _lib_nice */
59#if !_lib_spawnveg
60#   define spawnveg(a,b,c,d)    spawnve(a,b,c)
61#endif /* !_lib_spawnveg */
62#if SHOPT_SPAWN
63    static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
64#endif /* SHOPT_SPAWN */
65
66static void	sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
67static int	trim_eq(const char*, const char*);
68static void	coproc_init(Shell_t*, int pipes[]);
69
70static void	*timeout;
71static char	pipejob;
72
73struct funenv
74{
75	Namval_t	*node;
76	struct argnod	*env;
77};
78
79/* ========	command execution	========*/
80
81/*
82 * print time <t> in h:m:s format with precision <p>
83 */
84static void     l_time(Sfio_t *outfile,register clock_t t,int p)
85{
86	register int  min, sec, frac;
87	register int hr;
88	if(p)
89	{
90		frac = t%sh.lim.clk_tck;
91		frac = (frac*100)/sh.lim.clk_tck;
92	}
93	t /= sh.lim.clk_tck;
94	sec = t%60;
95	t /= 60;
96	min = t%60;
97	if(hr=t/60)
98		sfprintf(outfile,"%dh",hr);
99	if(p)
100		sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
101	else
102		sfprintf(outfile,"%dm%ds",min,sec);
103}
104
105static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
106{
107	int		c,p,l,n,offset = staktell();
108	const char	*first;
109	double		d;
110	Stk_t		*stkp = shp->stk;
111	for(first=format ; c= *format; format++)
112	{
113		if(c!='%')
114			continue;
115		sfwrite(stkp, first, format-first);
116		n = l = 0;
117		p = 3;
118		if((c= *++format) == '%')
119		{
120			first = format;
121			continue;
122		}
123		if(c>='0' && c <='9')
124		{
125			p = (c>'3')?3:(c-'0');
126			c = *++format;
127		}
128		else if(c=='P')
129		{
130			if(d=tm[0])
131				d = 100.*(((double)(tm[1]+tm[2]))/d);
132			p = 2;
133			goto skip;
134		}
135		if(c=='l')
136		{
137			l = 1;
138			c = *++format;
139		}
140		if(c=='U')
141			n = 1;
142		else if(c=='S')
143			n = 2;
144		else if(c!='R')
145		{
146			stkseek(stkp,offset);
147			errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
148			return(0);
149		}
150		d = (double)tm[n]/sh.lim.clk_tck;
151	skip:
152		if(l)
153			l_time(stkp, tm[n], p);
154		else
155			sfprintf(stkp,"%.*f",p, d);
156		first = format+1;
157	}
158	if(format>first)
159		sfwrite(stkp,first, format-first);
160	sfputc(stkp,'\n');
161	n = stktell(stkp)-offset;
162	sfwrite(out,stkptr(stkp,offset),n);
163	stkseek(stkp,offset);
164	return(n);
165}
166
167#if SHOPT_OPTIMIZE
168/*
169 * clear argument pointers that point into the stack
170 */
171static int p_arg(struct argnod*,int);
172static int p_switch(struct regnod*);
173static int p_comarg(register struct comnod *com)
174{
175	Namval_t *np=com->comnamp;
176	int n = p_arg(com->comset,ARG_ASSIGN);
177	if(com->comarg && (com->comtyp&COMSCAN))
178		n+= p_arg(com->comarg,0);
179	if(com->comstate  && np)
180	{
181		/* call builtin to cleanup state */
182		Shbltin_t *bp = &sh.bltindata;
183		void  *save_ptr = bp->ptr;
184		void  *save_data = bp->data;
185		bp->bnode = np;
186		bp->vnode = com->comnamq;
187		bp->ptr = nv_context(np);
188		bp->data = com->comstate;
189		bp->flags = SH_END_OPTIM;
190		(*funptr(np))(0,(char**)0, bp);
191		bp->ptr = save_ptr;
192		bp->data = save_data;
193	}
194	com->comstate = 0;
195	if(com->comarg && !np)
196		n++;
197	return(n);
198}
199
200extern void sh_optclear(Shell_t*, void*);
201
202static int sh_tclear(register Shnode_t *t)
203{
204	int n=0;
205	if(!t)
206		return(0);
207	switch(t->tre.tretyp&COMMSK)
208	{
209		case TTIME:
210		case TPAR:
211			return(sh_tclear(t->par.partre));
212		case TCOM:
213			return(p_comarg((struct comnod*)t));
214		case TSETIO:
215		case TFORK:
216			return(sh_tclear(t->fork.forktre));
217		case TIF:
218			n=sh_tclear(t->if_.iftre);
219			n+=sh_tclear(t->if_.thtre);
220			n+=sh_tclear(t->if_.eltre);
221			return(n);
222		case TWH:
223			if(t->wh.whinc)
224				n=sh_tclear((Shnode_t*)(t->wh.whinc));
225			n+=sh_tclear(t->wh.whtre);
226			n+=sh_tclear(t->wh.dotre);
227			return(n);
228		case TLST:
229		case TAND:
230		case TORF:
231		case TFIL:
232			n=sh_tclear(t->lst.lstlef);
233			return(n+sh_tclear(t->lst.lstrit));
234		case TARITH:
235			return(p_arg(t->ar.arexpr,ARG_ARITH));
236		case TFOR:
237			n=sh_tclear(t->for_.fortre);
238			return(n+sh_tclear((Shnode_t*)t->for_.forlst));
239		case TSW:
240			n=p_arg(t->sw.swarg,0);
241			return(n+p_switch(t->sw.swlst));
242		case TFUN:
243			n=sh_tclear(t->funct.functtre);
244			return(n+sh_tclear((Shnode_t*)t->funct.functargs));
245		case TTST:
246			if((t->tre.tretyp&TPAREN)==TPAREN)
247				return(sh_tclear(t->lst.lstlef));
248			else
249			{
250				n=p_arg(&(t->lst.lstlef->arg),0);
251				if(t->tre.tretyp&TBINARY)
252					n+=p_arg(&(t->lst.lstrit->arg),0);
253			}
254	}
255	return(n);
256}
257
258static int p_arg(register struct argnod *arg,int flag)
259{
260	while(arg)
261	{
262		if(strlen(arg->argval) || (arg->argflag==ARG_RAW))
263			arg->argchn.ap = 0;
264		else if(flag==0)
265			sh_tclear((Shnode_t*)arg->argchn.ap);
266		else
267			sh_tclear(((struct fornod*)arg->argchn.ap)->fortre);
268		arg = arg->argnxt.ap;
269	}
270	return(0);
271}
272
273static int p_switch(register struct regnod *reg)
274{
275	int n=0;
276	while(reg)
277	{
278		n+=p_arg(reg->regptr,0);
279		n+=sh_tclear(reg->regcom);
280		reg = reg->regnxt;
281	}
282	return(n);
283}
284#   define OPTIMIZE_FLAG	(ARG_OPTIMIZE)
285#   define OPTIMIZE		(flags&OPTIMIZE_FLAG)
286#else
287#   define OPTIMIZE_FLAG	(0)
288#   define OPTIMIZE		(0)
289#   define sh_tclear(x)
290#endif /* SHOPT_OPTIMIZE */
291
292static void out_pattern(Sfio_t *iop, register const char *cp, int n)
293{
294	register int c;
295	do
296	{
297		switch(c= *cp)
298		{
299		    case 0:
300			if(n<0)
301				return;
302			c = n;
303			break;
304		    case '\n':
305			sfputr(iop,"$'\\n",'\'');
306			continue;
307		    case '\\':
308			if (!(c = *++cp))
309				c = '\\';
310			/*FALLTHROUGH*/
311		    case ' ':
312		    case '<': case '>': case ';':
313		    case '$': case '`': case '\t':
314			sfputc(iop,'\\');
315			break;
316		}
317		sfputc(iop,c);
318	}
319	while(*cp++);
320}
321
322static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
323{
324	if(quoted)
325	{
326		int n = stktell(stkstd);
327		cp = sh_fmtq(cp);
328		if(iop==stkstd && cp==stkptr(stkstd,n))
329		{
330			*stkptr(stkstd,stktell(stkstd)-1) = c;
331			return;
332		}
333	}
334	sfputr(iop,cp,c);
335}
336
337struct Level
338{
339	Namfun_t	hdr;
340	short		maxlevel;
341};
342
343/*
344 * this is for a debugger but it hasn't been tested yet
345 * if a debug script sets .sh.level it should set up the scope
346 *  as if you were executing in that level
347 */
348static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
349{
350	Shscope_t	*sp;
351	struct Level *lp = (struct Level*)fp;
352	int16_t level, oldlevel = (int16_t)nv_getnum(np);
353	nv_putv(np,val,flags,fp);
354	if(!val)
355	{
356		fp = nv_stack(np, NIL(Namfun_t*));
357		if(fp && !fp->nofree)
358			free((void*)fp);
359		return;
360	}
361	level = nv_getnum(np);
362	if(level<0 || level > lp->maxlevel)
363	{
364		nv_putv(np, (char*)&oldlevel, NV_INT16, fp);
365		/* perhaps this should be an error */
366		return;
367	}
368	if(level==oldlevel)
369		return;
370	if(sp = sh_getscope(level,SEEK_SET))
371	{
372		sh_setscope(sp);
373		error_info.id = sp->cmdname;
374
375	}
376}
377
378static const Namdisc_t level_disc = {  sizeof(struct Level), put_level };
379
380static struct Level *init_level(int level)
381{
382	struct Level *lp = newof(NiL,struct Level,1,0);
383	lp->maxlevel = level;
384	_nv_unset(SH_LEVELNOD,0);
385	nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE);
386	nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
387	lp->hdr.disc = &level_disc;
388	nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST);
389	return(lp);
390}
391
392/*
393 * write the current common on the stack and make it available as .sh.command
394 */
395int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
396{
397	Stk_t			*stkp=shp->stk;
398	struct sh_scoped	savst;
399	Namval_t		*np = SH_COMMANDNOD;
400	char			*sav = stkptr(stkp,0);
401	int			n=4, offset=stktell(stkp);
402	const char		*cp = "+=( ";
403	Sfio_t			*iop = stkstd;
404	short			level;
405	if(shp->indebug)
406		return(0);
407	shp->indebug = 1;
408	if(name)
409	{
410		sfputr(iop,name,-1);
411		if(subscript)
412		{
413			sfputc(iop,'[');
414			out_string(iop,subscript,']',1);
415		}
416		if(!(flags&ARG_APPEND))
417			cp+=1, n-=1;
418		if(!(flags&ARG_ASSIGN))
419			n -= 2;
420		sfwrite(iop,cp,n);
421	}
422	if(*argv && !(flags&ARG_RAW))
423		out_string(iop, *argv++,' ', 0);
424	n = (flags&ARG_ARITH);
425	while(cp = *argv++)
426	{
427		if((flags&ARG_EXP) && argv[1]==0)
428			out_pattern(iop, cp,' ');
429		else
430			out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
431	}
432	if(flags&ARG_ASSIGN)
433		sfputc(iop,')');
434	else if(iop==stkstd)
435		*stkptr(stkp,stktell(stkp)-1) = 0;
436	np->nvalue.cp = stkfreeze(stkp,1);
437	/* now setup .sh.level variable */
438	shp->st.lineno = error_info.line;
439	level  = shp->fn_depth+shp->dot_depth;
440	if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
441		init_level(level);
442	else
443		nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
444	savst = shp->st;
445	shp->st.trap[SH_DEBUGTRAP] = 0;
446	n = sh_trap(trap,0);
447	np->nvalue.cp = 0;
448	shp->indebug = 0;
449	if(shp->st.cmdname)
450		error_info.id = shp->st.cmdname;
451	nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
452	nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
453	shp->st = savst;
454	if(sav != stkptr(stkp,0))
455		stkset(stkp,sav,0);
456	else
457		stkseek(stkp,offset);
458	return(n);
459}
460
461/*
462 * Given stream <iop> compile and execute
463 */
464int sh_eval(register Sfio_t *iop, int mode)
465{
466	register Shnode_t *t;
467	Shell_t  *shp = sh_getinterp();
468	struct slnod *saveslp = shp->st.staklist;
469	int jmpval;
470	struct checkpt *pp = (struct checkpt*)shp->jmplist;
471	struct checkpt buff;
472	static Sfio_t *io_save;
473	volatile int traceon=0, lineno=0;
474	int binscript=shp->binscript;
475	io_save = iop; /* preserve correct value across longjmp */
476	shp->binscript = 0;
477#define SH_TOPFUN	0x8000	/* this is a temporary tksh hack */
478	if (mode & SH_TOPFUN)
479	{
480		mode ^= SH_TOPFUN;
481		shp->fn_reset = 1;
482	}
483	sh_pushcontext(&buff,SH_JMPEVAL);
484	buff.olist = pp->olist;
485	jmpval = sigsetjmp(buff.buff,0);
486	while(jmpval==0)
487	{
488		if(mode&SH_READEVAL)
489		{
490			lineno = shp->inlineno;
491			if(traceon=sh_isoption(SH_XTRACE))
492				sh_offoption(SH_XTRACE);
493		}
494		t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
495		if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0))
496		{
497			if(!(mode&SH_READEVAL))
498				sfclose(iop);
499			io_save = 0;
500			mode &= ~SH_FUNEVAL;
501		}
502		mode &= ~SH_READEVAL;
503		if(!sh_isoption(SH_VERBOSE))
504			sh_offstate(SH_VERBOSE);
505		if((mode&~SH_FUNEVAL) && shp->hist_ptr)
506		{
507			hist_flush(shp->hist_ptr);
508			mode = sh_state(SH_INTERACTIVE);
509		}
510		sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
511		if(!(mode&SH_FUNEVAL))
512			break;
513	}
514	sh_popcontext(&buff);
515	shp->binscript = binscript;
516	if(traceon)
517		sh_onoption(SH_XTRACE);
518	if(lineno)
519		shp->inlineno = lineno;
520	if(io_save)
521		sfclose(io_save);
522	sh_freeup(shp);
523	shp->st.staklist = saveslp;
524	shp->fn_reset = 0;
525	if(jmpval>SH_JMPEVAL)
526		siglongjmp(*shp->jmplist,jmpval);
527	return(shp->exitval);
528}
529
530#if SHOPT_FASTPIPE
531static int pipe_exec(Shell_t* shp,int pv[], Shnode_t *t, int errorflg)
532{
533	struct checkpt buff;
534	register Shnode_t *tchild = t->fork.forktre;
535	Namval_t *np;
536	int jmpval;
537	volatile Sfio_t *iop;
538	volatile int r;
539	if((tchild->tre.tretyp&COMMSK)!=TCOM || !(np=(Namval_t*)(tchild->com.comnamp)))
540	{
541		sh_pipe(pv);
542		return(sh_exec(t,errorflg));
543	}
544	pv[0] = shp->lim.open_max;
545	shp->fdstatus[pv[0]] = IOREAD|IODUP|IOSEEK;
546	pv[1] = shp->lim.open_max+1;
547	shp->fdstatus[pv[1]] = IOWRITE|IOSEEK;
548	iop = sftmp(IOBSIZE+1);
549	shp->sftable[shp->lim.open_max+1] = iop;
550	sh_pushcontext(&buff,SH_JMPIO);
551	if(t->tre.tretyp&FPIN)
552		sh_iosave(shp,0,shp->topfd,(char*)0);
553	sh_iosave(shp,1,shp->topfd,(char*)0);
554	jmpval = sigsetjmp(buff.buff,0);
555	if(jmpval==0)
556	{
557		if(t->tre.tretyp&FPIN)
558			sh_iorenumber(shp,shp->inpipe[0],0);
559		sh_iorenumber(shp,shp->lim.open_max+1,1);
560		r = sh_exec(tchild,errorflg);
561		if(sffileno(sfstdout)>=0)
562			pv[0] = sfsetfd(sfstdout,10);
563		iop = sfswap(sfstdout,0);
564	}
565	sh_popcontext(&buff);
566	shp->sftable[pv[0]] = iop;
567	shp->fdstatus[pv[0]] = IOREAD|IODUP|IOSEEK;
568	sfset(iop,SF_WRITE,0);
569	sfseek(iop,0L,SEEK_SET);
570	sh_iorestore(shp,buff.topfd,jmpval);
571	if(jmpval>SH_JMPIO)
572		siglongjmp(*shp->jmplist,jmpval);
573	return(r);
574}
575#endif /* SHOPT_FASTPIPE */
576
577/*
578 * returns 1 when option -<c> is specified
579 */
580static int checkopt(char *argv[], int c)
581{
582	char *cp;
583	while(cp = *++argv)
584	{
585		if(*cp=='+')
586			continue;
587		if(*cp!='-' || cp[1]=='-')
588			break;
589		if(strchr(++cp,c))
590			return(1);
591		if(*cp=='h' && cp[1]==0 && *++argv==0)
592			break;
593	}
594	return(0);
595}
596
597static void free_list(struct openlist *olist)
598{
599	struct openlist *item,*next;
600	for(item=olist;item;item=next)
601	{
602		next = item->next;
603		free((void*)item);
604	}
605}
606
607/*
608 * set ${.sh.name} and ${.sh.subscript}
609 * set _ to reference for ${.sh.name}[$.sh.subscript]
610 */
611static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
612{
613	char		*sp=0,*cp = nv_name(nq);
614	Namarr_t	*ap;
615	memset(nr,0,sizeof(*nr));
616	nr->np = nq;
617	nr->root = sh.var_tree;
618	nr->table = sh.last_table;
619	shp->instance = 1;
620	if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
621		sp = strdup(sp);
622	shp->instance = 0;
623	if(sh.var_tree!=sh.var_base && !nv_open(cp,nr->root,NV_VARNAME|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))
624		nr->root = sh.var_base;
625	nv_putval(SH_NAMENOD, cp, NV_NOFREE);
626	memcpy(node,L_ARGNOD,sizeof(*node));
627	L_ARGNOD->nvalue.nrp = nr;
628	L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
629	L_ARGNOD->nvfun = 0;
630	L_ARGNOD->nvenv = 0;
631	if(sp)
632	{
633		nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE);
634		return(ap->nelem&ARRAY_SCAN);
635	}
636	return(0);
637}
638
639static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
640{
641	L_ARGNOD->nvalue.nrp = node->nvalue.nrp;
642	L_ARGNOD->nvflag = node->nvflag;
643	L_ARGNOD->nvfun = node->nvfun;
644	if(nr->sub)
645	{
646		nv_putsub(nq, nr->sub, mode);
647		free((void*)nr->sub);
648	}
649	nv_unset(SH_NAMENOD);
650	nv_unset(SH_SUBSCRNOD);
651}
652
653int sh_exec(register const Shnode_t *t, int flags)
654{
655	register Shell_t	*shp = &sh;
656	Stk_t			*stkp = shp->stk;
657	sh_sigcheck();
658	if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
659	{
660		register int 	type = flags;
661		register char	*com0 = 0;
662		int 		errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE;
663		int 		execflg = (type&sh_state(SH_NOFORK));
664		int 		execflg2 = (type&sh_state(SH_FORKED));
665		int 		mainloop = (type&sh_state(SH_INTERACTIVE));
666#if SHOPT_AMP || SHOPT_SPAWN
667		int		ntflag = (type&sh_state(SH_NTFORK));
668#else
669		int		ntflag = 0;
670#endif
671		int		topfd = shp->topfd;
672		char 		*sav=stkptr(stkp,0);
673		char		*cp=0, **com=0, *comn;
674		int		argn;
675		int 		skipexitset = 0;
676		int		was_interactive = 0;
677		int		was_errexit = sh_isstate(SH_ERREXIT);
678		int		was_monitor = sh_isstate(SH_MONITOR);
679		int		echeck = 0;
680		if(flags&sh_state(SH_INTERACTIVE))
681		{
682			if(pipejob==2)
683				job_unlock();
684			pipejob = 0;
685			job.curpgid = 0;
686			flags &= ~sh_state(SH_INTERACTIVE);
687		}
688		sh_offstate(SH_ERREXIT);
689		sh_offstate(SH_DEFPATH);
690		if(was_errexit&flags)
691			sh_onstate(SH_ERREXIT);
692		if(was_monitor&flags)
693			sh_onstate(SH_MONITOR);
694		type = t->tre.tretyp;
695		if(!shp->intrap)
696			shp->oldexit=shp->exitval;
697		shp->exitval=0;
698		shp->lastsig = 0;
699		shp->lastpath = 0;
700		switch(type&COMMSK)
701		{
702		    case TCOM:
703		    {
704			register struct argnod	*argp;
705			char		*trap;
706			Namval_t	*np, *nq, *last_table;
707			struct ionod	*io;
708			int		command=0, flgs=NV_ASSIGN;
709			shp->bltindata.invariant = type>>(COMBITS+2);
710			type &= (COMMSK|COMSCAN);
711			sh_stats(STAT_SCMDS);
712			error_info.line = t->com.comline-shp->st.firstline;
713			com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE);
714			echeck = 1;
715			if(t->tre.tretyp&COMSCAN)
716			{
717				argp = t->com.comarg;
718				if(argp && *com && !(argp->argflag&ARG_RAW))
719					sh_sigcheck();
720			}
721			np = (Namval_t*)(t->com.comnamp);
722			nq = (Namval_t*)(t->com.comnamq);
723			com0 = com[0];
724			shp->xargexit = 0;
725			while(np==SYSCOMMAND)
726			{
727				register int n = b_command(0,com,&shp->bltindata);
728				if(n==0)
729					break;
730				command += n;
731				np = 0;
732				if(!(com0= *(com+=n)))
733					break;
734				np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
735			}
736			if(shp->xargexit)
737			{
738				shp->xargmin -= command;
739				shp->xargmax -= command;
740			}
741			else
742				shp->xargmin = 0;
743			argn -= command;
744			if(!command && np && is_abuiltin(np))
745				np = dtsearch(shp->fun_tree,np);
746			if(com0)
747			{
748				if(!np && !strchr(com0,'/'))
749				{
750					Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
751					np = nv_bfsearch(com0, root, &nq, &cp);
752#if SHOPT_NAMESPACE
753					if(shp->namespace && !nq && !cp)
754					{
755						int offset = stktell(stkp);
756						sfputr(stkp,nv_name(shp->namespace),-1);
757						sfputc(stkp,'.');
758						sfputr(stkp,com0,0);
759						stkseek(stkp,offset);
760						np = nv_bfsearch(stkptr(stkp,offset), root, &nq, &cp);
761					}
762#endif /* SHOPT_NAMESPACE */
763				}
764				comn = com[argn-1];
765			}
766			io = t->tre.treio;
767			if(shp->envlist = argp = t->com.comset)
768			{
769				if(argn==0 || (np && nv_isattr(np,BLT_SPC)))
770				{
771					Namval_t *tp=0;
772					if(argn)
773					{
774						if(checkopt(com,'A'))
775							flgs |= NV_ARRAY;
776						else if(checkopt(com,'a'))
777							flgs |= NV_IARRAY;
778					}
779#if SHOPT_BASH
780					if(np==SYSLOCAL)
781					{
782						if(!nv_getval(SH_FUNNAMENOD))
783							errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
784						if(!shp->st.var_local)
785						{
786							sh_scope(shp,(struct argnod*)0,0);
787							shp->st.var_local = shp->var_tree;
788						}
789
790					}
791					if(np==SYSTYPESET || np==SYSLOCAL)
792#else
793					if(np==SYSTYPESET ||  (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
794#endif
795					{
796						if(np!=SYSTYPESET)
797						{
798							shp->typeinit = np;
799							tp = nv_type(np);
800						}
801						if(checkopt(com,'C'))
802							flgs |= NV_COMVAR;
803						if(checkopt(com,'S'))
804							flgs |= NV_STATIC;
805						if(checkopt(com,'n'))
806							flgs |= NV_NOREF;
807						else if(!shp->typeinit && (checkopt(com,'L') || checkopt(com,'R') || checkopt(com,'Z')))
808							flgs |= NV_UNJUST;
809#if SHOPT_TYPEDEF
810						else if(argn>=3 && checkopt(com,'T'))
811						{
812							shp->prefix = NV_CLASS;
813							flgs |= NV_TYPE;
814
815						}
816#endif /* SHOPT_TYPEDEF */
817						if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
818							flgs |= NV_NOSCOPE;
819					}
820					else if(np==SYSEXPORT)
821						flgs |= NV_EXPORT;
822					if(flgs&(NV_EXPORT|NV_NOREF))
823						flgs |= NV_IDENT;
824					else
825						flgs |= NV_VARNAME;
826#if 0
827					if(OPTIMIZE)
828						flgs |= NV_TAGGED;
829#endif
830					nv_setlist(argp,flgs,tp);
831					if(np==shp->typeinit)
832						shp->typeinit = 0;
833					shp->envlist = argp;
834					argp = NULL;
835				}
836			}
837			last_table = shp->last_table;
838			shp->last_table = 0;
839			if((io||argn))
840			{
841				Shbltin_t *bp=0;
842				static char *argv[1];
843				int tflags = 1;
844				if(np &&  nv_isattr(np,BLT_DCL))
845					tflags |= 2;
846				if(argn==0)
847				{
848					/* fake 'true' built-in */
849					np = SYSTRUE;
850					*argv = nv_name(np);
851					com = argv;
852				}
853				/* set +x doesn't echo */
854				else if((np!=SYSSET) && sh_isoption(SH_XTRACE))
855					sh_trace(com-command,tflags);
856				else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
857				{
858					int ison = sh_isoption(SH_XTRACE);
859					if(!ison)
860						sh_onoption(SH_XTRACE);
861					sh_trace(com-command,tflags);
862					if(io)
863						sh_redirect(shp,io,SH_SHOWME);
864					if(!ison)
865						sh_offoption(SH_XTRACE);
866					break;
867				}
868				if(trap=shp->st.trap[SH_DEBUGTRAP])
869				{
870					int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
871					if(n==255 && shp->fn_depth+shp->dot_depth)
872					{
873						np = SYSRETURN;
874						argn = 1;
875						com[0] = np->nvname;
876						com[1] = 0;
877						io = 0;
878						argp = 0;
879					}
880					else if(n==2)
881						break;
882				}
883				if(io)
884					sfsync(shp->outpool);
885				shp->lastpath = 0;
886				if(!np  && !strchr(com0,'/'))
887				{
888					if(path_search(com0,NIL(Pathcomp_t**),1))
889					{
890						error_info.line = t->com.comline-shp->st.firstline;
891						if((np=nv_search(com0,shp->fun_tree,0)) && !np->nvalue.ip)
892						{
893							Namval_t *mp=nv_search(com0,shp->bltin_tree,0);
894							if(mp)
895								np = mp;
896						}
897					}
898					else
899					{
900						if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
901							np=nv_search(nv_getval(np),shp->bltin_tree,0);
902						else
903							np = 0;
904					}
905				}
906				if(np && pipejob==2)
907				{
908					job_unlock();
909					pipejob = 1;
910				}
911				/* check for builtins */
912				if(np && is_abuiltin(np))
913				{
914					volatile int scope=0, share=0;
915					volatile void *save_ptr;
916					volatile void *save_data;
917					int jmpval, save_prompt;
918					int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
919					struct checkpt buff;
920					unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
921					struct stat statb;
922					bp = &shp->bltindata;
923					save_ptr = bp->ptr;
924					save_data = bp->data;
925					memset(&statb, 0, sizeof(struct stat));
926					if(strchr(nv_name(np),'/'))
927					{
928						/*
929						 * disable editors for built-in
930						 * versions of commands on PATH
931						 */
932						was_vi = sh_isoption(SH_VI);
933						was_emacs = sh_isoption(SH_EMACS);
934						was_gmacs = sh_isoption(SH_GMACS);
935						sh_offoption(SH_VI);
936						sh_offoption(SH_EMACS);
937						sh_offoption(SH_GMACS);
938					}
939					if(execflg)
940						sh_onstate(SH_NOFORK);
941					sh_pushcontext(&buff,SH_JMPCMD);
942					jmpval = sigsetjmp(buff.buff,1);
943					if(jmpval == 0)
944					{
945						if(!(nv_isattr(np,BLT_ENV)))
946							error_info.flags |= ERROR_SILENT;
947						errorpush(&buff.err,0);
948						if(io)
949						{
950							struct openlist *item;
951							if(np==SYSLOGIN)
952								type=1;
953							else if(np==SYSEXEC)
954								type=1+!com[1];
955							else
956								type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
957							sh_redirect(shp,io,type);
958							for(item=buff.olist;item;item=item->next)
959								item->strm=0;
960						}
961						if(!(nv_isattr(np,BLT_ENV)))
962						{
963							if(bp->nosfio)
964							{
965								if(!shp->pwd)
966									path_pwd(0);
967								if(shp->pwd)
968									stat(".",&statb);
969							}
970							sfsync(NULL);
971							share = sfset(sfstdin,SF_SHARE,0);
972							sh_onstate(SH_STOPOK);
973							sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
974							sfset(sfstderr,SF_LINE,1);
975							save_prompt = shp->nextprompt;
976							shp->nextprompt = 0;
977						}
978						if(argp)
979						{
980							scope++;
981							sh_scope(shp,argp,0);
982						}
983						opt_info.index = opt_info.offset = 0;
984						opt_info.disc = 0;
985						error_info.id = *com;
986						if(argn)
987							shp->exitval = 0;
988						shp->bltinfun = funptr(np);
989						bp->bnode = np;
990						bp->vnode = nq;
991						bp->ptr = nv_context(np);
992						bp->data = t->com.comstate;
993						bp->sigset = 0;
994						bp->notify = 0;
995						bp->flags = (OPTIMIZE!=0);
996						if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
997							sh_subtmpfile(0);
998						if(execflg && !shp->subshell &&
999							!shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
1000						{
1001							/* do close-on-exec */
1002							int fd;
1003							for(fd=0; fd < shp->lim.open_max; fd++)
1004								if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd)
1005									sh_close(fd);
1006						}
1007						if(argn)
1008							shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
1009						if(error_info.flags&ERROR_INTERACTIVE)
1010							tty_check(ERRIO);
1011						((Shnode_t*)t)->com.comstate = shp->bltindata.data;
1012						bp->data = (void*)save_data;
1013						if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
1014							shp->exitval &= SH_EXITMASK;
1015					}
1016					else
1017					{
1018						struct openlist *item;
1019						for(item=buff.olist;item;item=item->next)
1020						{
1021							if(item->strm)
1022							{
1023								sfclrlock(item->strm);
1024								if(shp->hist_ptr && item->strm == shp->hist_ptr->histfp)
1025									hist_close(shp->hist_ptr);
1026								else
1027									sfclose(item->strm);
1028							}
1029						}
1030						if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
1031							(*shp->bltinfun)(-2,com,(void*)bp);
1032						/* failure on special built-ins fatal */
1033						if(jmpval<=SH_JMPCMD  && (!nv_isattr(np,BLT_SPC) || command))
1034							jmpval=0;
1035					}
1036					if(bp && bp->ptr!= nv_context(np))
1037						np->nvfun = (Namfun_t*)bp->ptr;
1038					if(execflg && !was_nofork)
1039						sh_offstate(SH_NOFORK);
1040					if(!(nv_isattr(np,BLT_ENV)))
1041					{
1042						if(bp->nosfio && shp->pwd)
1043						{
1044							struct stat stata;
1045							stat(".",&stata);
1046							/* restore directory changed */
1047							if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
1048								chdir(shp->pwd);
1049						}
1050						sh_offstate(SH_STOPOK);
1051						if(share&SF_SHARE)
1052							sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
1053						sfset(sfstderr,SF_LINE,0);
1054						sfpool(sfstderr,shp->outpool,SF_WRITE);
1055						sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE);
1056						shp->nextprompt = save_prompt;
1057					}
1058					sh_popcontext(&buff);
1059					errorpop(&buff.err);
1060					error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
1061					shp->bltinfun = 0;
1062					if(buff.olist)
1063						free_list(buff.olist);
1064					if(was_vi)
1065						sh_onoption(SH_VI);
1066					else if(was_emacs)
1067						sh_onoption(SH_EMACS);
1068					else if(was_gmacs)
1069						sh_onoption(SH_GMACS);
1070					if(scope)
1071						sh_unscope(shp);
1072					bp->ptr = (void*)save_ptr;
1073					bp->data = (void*)save_data;
1074					/* don't restore for subshell exec */
1075					if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
1076						sh_iorestore(shp,topfd,jmpval);
1077					if(jmpval)
1078						siglongjmp(*shp->jmplist,jmpval);
1079#if 0
1080					if(flgs&NV_STATIC)
1081						((Shnode_t*)t)->com.comset = 0;
1082#endif
1083					if(shp->exitval >=0)
1084						goto setexit;
1085					np = 0;
1086					type=0;
1087				}
1088				/* check for functions */
1089				if(!command && np && nv_isattr(np,NV_FUNCTION))
1090				{
1091					volatile int indx;
1092					int jmpval=0;
1093					struct checkpt buff;
1094					Namval_t node;
1095					struct Namref	nr;
1096					long		mode;
1097					register struct slnod *slp;
1098					if(!np->nvalue.ip)
1099					{
1100						indx = path_search(com0,NIL(Pathcomp_t**),0);
1101						if(indx==1)
1102							np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE);
1103
1104						if(!np->nvalue.ip)
1105						{
1106							if(indx==1)
1107							{
1108								errormsg(SH_DICT,ERROR_exit(0),e_defined,com0);
1109								shp->exitval = ERROR_NOEXEC;
1110							}
1111							else
1112							{
1113								errormsg(SH_DICT,ERROR_exit(0),e_found,"function");
1114								shp->exitval = ERROR_NOENT;
1115							}
1116							goto setexit;
1117						}
1118					}
1119					/* increase refcnt for unset */
1120					slp = (struct slnod*)np->nvenv;
1121					sh_funstaks(slp->slchild,1);
1122					staklink(slp->slptr);
1123					if(nq)
1124					{
1125						shp->last_table = last_table;
1126						mode = set_instance(shp,nq,&node,&nr);
1127					}
1128					if(io)
1129					{
1130						indx = shp->topfd;
1131						sh_pushcontext(&buff,SH_JMPCMD);
1132						jmpval = sigsetjmp(buff.buff,0);
1133					}
1134					if(jmpval == 0)
1135					{
1136						if(io)
1137							indx = sh_redirect(shp,io,execflg);
1138						sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
1139					}
1140					if(io)
1141					{
1142						if(buff.olist)
1143							free_list(buff.olist);
1144						sh_popcontext(&buff);
1145						sh_iorestore(shp,indx,jmpval);
1146					}
1147					if(nq)
1148						unset_instance(nq,&node,&nr,mode);
1149					sh_funstaks(slp->slchild,-1);
1150					stakdelete(slp->slptr);
1151					if(jmpval > SH_JMPFUN)
1152						siglongjmp(*shp->jmplist,jmpval);
1153					goto setexit;
1154				}
1155			}
1156			else if(!io)
1157			{
1158			setexit:
1159				exitset();
1160				break;
1161			}
1162		    }
1163		    /* FALLTHROUGH */
1164		    case TFORK:
1165		    {
1166			register pid_t parent;
1167			int no_fork,jobid;
1168			int pipes[2];
1169			if(shp->subshell)
1170			{
1171				if(shp->subshare)
1172					sh_subtmpfile(1);
1173				else
1174					sh_subfork();
1175			}
1176			no_fork = !ntflag && !(type&(FAMP|FPOU)) &&
1177			    !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
1178				((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
1179				(execflg2 || (execflg &&
1180				!shp->subshell && shp->fn_depth==0 &&
1181				!(pipejob && sh_isoption(SH_PIPEFAIL))
1182			    ));
1183			if(sh_isstate(SH_PROFILE) || shp->dot_depth)
1184			{
1185				/* disable foreground job monitor */
1186				if(!(type&FAMP))
1187					sh_offstate(SH_MONITOR);
1188#if SHOPT_DEVFD
1189				else if(!(type&FINT))
1190					sh_offstate(SH_MONITOR);
1191#endif /* SHOPT_DEVFD */
1192			}
1193			if(no_fork)
1194				job.parent=parent=0;
1195			else
1196			{
1197#ifdef SHOPT_BGX
1198				int maxjob;
1199				if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
1200				{
1201					while(job.numbjob >= maxjob)
1202					{
1203						job_lock();
1204						job_reap(0);
1205						job_unlock();
1206					}
1207				}
1208#endif /* SHOPT_BGX */
1209				if(type&FCOOP)
1210					coproc_init(shp,pipes);
1211				nv_getval(RANDNOD);
1212#if SHOPT_AMP
1213				if((type&(FAMP|FINT)) == (FAMP|FINT))
1214					parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1215				else
1216					parent = sh_fork(type,&jobid);
1217				if(parent<0)
1218					break;
1219#else
1220#if SHOPT_SPAWN
1221#   ifdef _lib_fork
1222				if(com)
1223					parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1224				else
1225					parent = sh_fork(type,&jobid);
1226#   else
1227				if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
1228					break;
1229#   endif /* _lib_fork */
1230				if(parent<0)
1231					break;
1232#else
1233				parent = sh_fork(type,&jobid);
1234#endif /* SHOPT_SPAWN */
1235#endif
1236			}
1237			if(job.parent=parent)
1238			/* This is the parent branch of fork
1239			 * It may or may not wait for the child
1240			 */
1241			{
1242				if(pipejob==2)
1243				{
1244					pipejob = 1;
1245					job_unlock();
1246				}
1247				if(type&FPCL)
1248					sh_close(shp->inpipe[0]);
1249				if(type&(FCOOP|FAMP))
1250					shp->bckpid = parent;
1251				else if(!(type&(FAMP|FPOU)))
1252				{
1253					if(shp->topfd > topfd)
1254						sh_iorestore(shp,topfd,0);
1255					if(!sh_isoption(SH_MONITOR))
1256					{
1257						if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
1258							sh_sigtrap(SIGINT);
1259						shp->trapnote |= SH_SIGIGNORE;
1260					}
1261					if(execflg && shp->subshell && !shp->subshare)
1262					{
1263						shp->spid = parent;
1264						job.pwlist->p_env--;
1265					}
1266					else if(shp->pipepid)
1267						shp->pipepid = parent;
1268					else
1269						job_wait(parent);
1270					if(!sh_isoption(SH_MONITOR))
1271					{
1272						shp->trapnote &= ~SH_SIGIGNORE;
1273						if(shp->exitval == (SH_EXITSIG|SIGINT))
1274							sh_fault(SIGINT);
1275					}
1276				}
1277				if(type&FAMP)
1278				{
1279					if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
1280					{
1281						/* print job number */
1282#ifdef JOBS
1283						sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent);
1284#else
1285						sfprintf(sfstderr,"%d\n",parent);
1286#endif /* JOBS */
1287					}
1288				}
1289				break;
1290			}
1291			else
1292			/*
1293			 * this is the FORKED branch (child) of execute
1294			 */
1295			{
1296				volatile int jmpval;
1297				struct checkpt buff;
1298				if(no_fork)
1299					sh_sigreset(2);
1300				sh_pushcontext(&buff,SH_JMPEXIT);
1301				jmpval = sigsetjmp(buff.buff,0);
1302				if(jmpval)
1303					goto done;
1304				if((type&FINT) && !sh_isstate(SH_MONITOR))
1305				{
1306					/* default std input for & */
1307					signal(SIGINT,SIG_IGN);
1308					signal(SIGQUIT,SIG_IGN);
1309					if(!shp->st.ioset)
1310					{
1311						if(sh_close(0)>=0)
1312							sh_chkopen(e_devnull);
1313					}
1314				}
1315				sh_offstate(SH_MONITOR);
1316				/* pipe in or out */
1317#ifdef _lib_nice
1318				if((type&FAMP) && sh_isoption(SH_BGNICE))
1319					nice(4);
1320#endif /* _lib_nice */
1321				if(type&FPIN)
1322				{
1323					sh_iorenumber(shp,shp->inpipe[0],0);
1324					if(!(type&FPOU) || (type&FCOOP))
1325						sh_close(shp->inpipe[1]);
1326				}
1327				if(type&FPOU)
1328				{
1329					sh_iorenumber(shp,shp->outpipe[1],1);
1330					sh_pclose(shp->outpipe);
1331				}
1332				if((type&COMMSK)!=TCOM)
1333					error_info.line = t->fork.forkline-shp->st.firstline;
1334				if(shp->topfd)
1335					sh_iounsave(shp);
1336				topfd = shp->topfd;
1337				sh_redirect(shp,t->tre.treio,1);
1338				if(shp->topfd > topfd)
1339				{
1340					job_lock();
1341					while((parent = vfork()) < 0)
1342						_sh_fork(parent, 0, (int*)0);
1343					job_fork(parent);
1344					if(parent)
1345					{
1346						job_clear();
1347						job_post(parent,0);
1348						job_wait(parent);
1349						sh_iorestore(shp,topfd,SH_JMPCMD);
1350						sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
1351
1352					}
1353				}
1354				if((type&COMMSK)!=TCOM)
1355				{
1356					/* don't clear job table for out
1357					   pipes so that jobs comand can
1358					   be used in a pipeline
1359					 */
1360					if(!no_fork && !(type&FPOU))
1361						job_clear();
1362					sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
1363				}
1364				else if(com0)
1365				{
1366					sh_offoption(SH_ERREXIT);
1367					sh_freeup(shp);
1368					path_exec(com0,com,t->com.comset);
1369				}
1370			done:
1371				sh_popcontext(&buff);
1372				if(jmpval>SH_JMPEXIT)
1373					siglongjmp(*shp->jmplist,jmpval);
1374				sh_done(shp,0);
1375			}
1376		    }
1377		    /* FALLTHROUGH */
1378
1379		    case TSETIO:
1380		    {
1381		    /*
1382		     * don't create a new process, just
1383		     * save and restore io-streams
1384		     */
1385			pid_t	pid;
1386			int 	jmpval, waitall;
1387			int 	simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
1388			struct checkpt buff;
1389			if(shp->subshell)
1390				execflg = 0;
1391			sh_pushcontext(&buff,SH_JMPIO);
1392			if(type&FPIN)
1393			{
1394				was_interactive = sh_isstate(SH_INTERACTIVE);
1395				sh_offstate(SH_INTERACTIVE);
1396				sh_iosave(shp,0,shp->topfd,(char*)0);
1397				shp->pipepid = simple;
1398				sh_iorenumber(shp,shp->inpipe[0],0);
1399				/*
1400				 * if read end of pipe is a simple command
1401				 * treat as non-sharable to improve performance
1402				 */
1403				if(simple)
1404					sfset(sfstdin,SF_PUBLIC|SF_SHARE,0);
1405				waitall = job.waitall;
1406				job.waitall = 0;
1407				pid = job.parent;
1408			}
1409			else
1410				error_info.line = t->fork.forkline-shp->st.firstline;
1411			jmpval = sigsetjmp(buff.buff,0);
1412			if(jmpval==0)
1413			{
1414				sh_redirect(shp,t->fork.forkio,execflg);
1415				(t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
1416				sh_exec(t->fork.forktre,flags&~simple);
1417			}
1418			else
1419				sfsync(shp->outpool);
1420			sh_popcontext(&buff);
1421			sh_iorestore(shp,buff.topfd,jmpval);
1422			if(buff.olist)
1423				free_list(buff.olist);
1424			if(type&FPIN)
1425			{
1426				job.waitall = waitall;
1427				type = shp->exitval;
1428				if(!(type&SH_EXITSIG))
1429				{
1430					/* wait for remainder of pipline */
1431					if(shp->pipepid>1)
1432					{
1433						job_wait(shp->pipepid);
1434						type = shp->exitval;
1435					}
1436					else
1437						job_wait(waitall?pid:0);
1438					if(type || !sh_isoption(SH_PIPEFAIL))
1439						shp->exitval = type;
1440				}
1441				shp->pipepid = 0;
1442				shp->st.ioset = 0;
1443				if(simple && was_errexit)
1444				{
1445					echeck = 1;
1446					sh_onstate(SH_ERREXIT);
1447				}
1448			}
1449			if(jmpval>SH_JMPIO)
1450				siglongjmp(*shp->jmplist,jmpval);
1451			break;
1452		    }
1453
1454		    case TPAR:
1455			echeck = 1;
1456			flags &= ~OPTIMIZE_FLAG;
1457			if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
1458			{
1459				char *savsig;
1460				int nsig,jmpval;
1461				struct checkpt buff;
1462				shp->st.otrapcom = 0;
1463				if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
1464				{
1465					nsig += sizeof(char*);
1466					memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
1467					shp->st.otrapcom = (char**)savsig;
1468				}
1469				sh_sigreset(0);
1470				sh_pushcontext(&buff,SH_JMPEXIT);
1471				jmpval = sigsetjmp(buff.buff,0);
1472				if(jmpval==0)
1473					sh_exec(t->par.partre,flags);
1474				sh_popcontext(&buff);
1475				if(jmpval > SH_JMPEXIT)
1476					siglongjmp(*shp->jmplist,jmpval);
1477				sh_done(shp,0);
1478			}
1479			else
1480				sh_subshell(t->par.partre,flags,0);
1481			break;
1482
1483		    case TFIL:
1484		    {
1485		    /*
1486		     * This code sets up a pipe.
1487		     * All elements of the pipe are started by the parent.
1488		     * The last element executes in current environment
1489		     */
1490			int	pvo[2];	/* old pipe for multi-stage */
1491			int	pvn[2];	/* current set up pipe */
1492			int	savepipe = pipejob;
1493			int	showme = t->tre.tretyp&FSHOWME;
1494			pid_t	savepgid = job.curpgid;
1495			job.curpgid = 0;
1496			if(shp->subshell)
1497			{
1498				if(shp->subshare)
1499					sh_subtmpfile(0);
1500				else
1501					sh_subfork();
1502			}
1503			shp->inpipe = pvo;
1504			shp->outpipe = pvn;
1505			pvo[1] = -1;
1506			if(sh_isoption(SH_PIPEFAIL))
1507				job.waitall = 1;
1508			else
1509				job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
1510			job_lock();
1511			do
1512			{
1513#if SHOPT_FASTPIPE
1514				type = pipe_exec(shp,pvn,t->lst.lstlef, errorflg);
1515#else
1516				/* create the pipe */
1517				sh_pipe(pvn);
1518				/* execute out part of pipe no wait */
1519				(t->lst.lstlef)->tre.tretyp |= showme;
1520				type = sh_exec(t->lst.lstlef, errorflg);
1521#endif /* SHOPT_FASTPIPE */
1522				pipejob=1;
1523				/* save the pipe stream-ids */
1524				pvo[0] = pvn[0];
1525				/* close out-part of pipe */
1526				sh_close(pvn[1]);
1527				/* pipeline all in one process group */
1528				t = t->lst.lstrit;
1529			}
1530			/* repeat until end of pipeline */
1531			while(!type && t->tre.tretyp==TFIL);
1532			shp->inpipe = pvn;
1533			shp->outpipe = 0;
1534			pipejob = 2;
1535			if(type == 0)
1536			{
1537				/*
1538				 * execute last element of pipeline
1539				 * in the current process
1540				 */
1541				((Shnode_t*)t)->tre.tretyp |= showme;
1542				sh_exec(t,flags);
1543			}
1544			else
1545				/* execution failure, close pipe */
1546				sh_pclose(pvn);
1547			if(pipejob==2)
1548				job_unlock();
1549			pipejob = savepipe;
1550#ifdef SIGTSTP
1551			if(!pipejob && sh_isstate(SH_MONITOR))
1552				tcsetpgrp(JOBTTY,shp->pid);
1553#endif /*SIGTSTP */
1554			job.curpgid = savepgid;
1555			break;
1556		    }
1557
1558		    case TLST:
1559		    {
1560			/*  a list of commands are executed here */
1561			do
1562			{
1563				sh_exec(t->lst.lstlef,errorflg|OPTIMIZE);
1564				t = t->lst.lstrit;
1565			}
1566			while(t->tre.tretyp == TLST);
1567			sh_exec(t,flags);
1568			break;
1569		    }
1570
1571		    case TAND:
1572			if(type&TTEST)
1573				skipexitset++;
1574			if(sh_exec(t->lst.lstlef,OPTIMIZE)==0)
1575				sh_exec(t->lst.lstrit,flags);
1576			break;
1577
1578		    case TORF:
1579			if(type&TTEST)
1580				skipexitset++;
1581			if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0)
1582				sh_exec(t->lst.lstrit,flags);
1583			break;
1584
1585		    case TFOR: /* for and select */
1586		    {
1587			register char **args;
1588			register int nargs;
1589			register Namval_t *np;
1590			int flag = errorflg|OPTIMIZE_FLAG;
1591			struct dolnod	*argsav=0;
1592			struct comnod	*tp;
1593			char *cp, *trap, *nullptr = 0;
1594			int nameref, refresh=1;
1595			char *av[5];
1596#if SHOPT_OPTIMIZE
1597			int  jmpval = ((struct checkpt*)shp->jmplist)->mode;
1598			struct checkpt buff;
1599			void *optlist = shp->optlist;
1600			shp->optlist = 0;
1601			sh_tclear(t->for_.fortre);
1602			sh_pushcontext(&buff,jmpval);
1603			jmpval = sigsetjmp(buff.buff,0);
1604			if(jmpval)
1605				goto endfor;
1606#endif /* SHOPT_OPTIMIZE */
1607			error_info.line = t->for_.forline-shp->st.firstline;
1608			if(!(tp=t->for_.forlst))
1609			{
1610				args=shp->st.dolv+1;
1611				nargs = shp->st.dolc;
1612				argsav=sh_arguse(shp);
1613			}
1614			else
1615			{
1616				args=sh_argbuild(shp,&argn,tp,0);
1617				nargs = argn;
1618			}
1619			np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
1620			nameref = nv_isref(np)!=0;
1621			shp->st.loopcnt++;
1622			cp = *args;
1623			while(cp && shp->st.execbrk==0)
1624			{
1625				if(t->tre.tretyp&COMSCAN)
1626				{
1627					char *val;
1628					int save_prompt;
1629					/* reuse register */
1630					if(refresh)
1631					{
1632						sh_menu(sfstderr,nargs,args);
1633						refresh = 0;
1634					}
1635					save_prompt = shp->nextprompt;
1636					shp->nextprompt = 3;
1637					shp->timeout = 0;
1638					shp->exitval=sh_readline(shp,&nullptr,0,1,1000*shp->st.tmout);
1639					shp->nextprompt = save_prompt;
1640					if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
1641					{
1642						shp->exitval = 1;
1643						break;
1644					}
1645					if(!(val=nv_getval(sh_scoped(shp,REPLYNOD))))
1646						continue;
1647					else
1648					{
1649						if(*(cp=val) == 0)
1650						{
1651							refresh++;
1652							goto check;
1653						}
1654						while(type = *cp++)
1655							if(type < '0' && type > '9')
1656								break;
1657						if(type!=0)
1658							type = nargs;
1659						else
1660							type = (int)strtol(val, (char**)0, 10)-1;
1661						if(type<0 || type >= nargs)
1662							cp = "";
1663						else
1664							cp = args[type];
1665					}
1666				}
1667				if(nameref)
1668					nv_offattr(np,NV_REF);
1669				else if(nv_isattr(np, NV_ARRAY))
1670					nv_putsub(np,NIL(char*),0L);
1671				nv_putval(np,cp,0);
1672				if(nameref)
1673					nv_setref(np,(Dt_t*)0,NV_VARNAME);
1674				if(trap=shp->st.trap[SH_DEBUGTRAP])
1675				{
1676					av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
1677					av[1] = t->for_.fornam;
1678					av[2] = "in";
1679					av[3] = cp;
1680					av[4] = 0;
1681					sh_debug(shp,trap,(char*)0,(char*)0,av,0);
1682				}
1683				sh_exec(t->for_.fortre,flag);
1684				flag &= ~OPTIMIZE_FLAG;
1685				if(t->tre.tretyp&COMSCAN)
1686				{
1687					if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
1688						refresh++;
1689				}
1690				else
1691					cp = *++args;
1692			check:
1693				if(shp->st.breakcnt<0)
1694					shp->st.execbrk = (++shp->st.breakcnt !=0);
1695			}
1696#if SHOPT_OPTIMIZE
1697		endfor:
1698			sh_popcontext(&buff);
1699			sh_tclear(t->for_.fortre);
1700			sh_optclear(shp,optlist);
1701			if(jmpval)
1702				siglongjmp(*shp->jmplist,jmpval);
1703#endif /*SHOPT_OPTIMIZE */
1704			if(shp->st.breakcnt>0)
1705				shp->st.execbrk = (--shp->st.breakcnt !=0);
1706			shp->st.loopcnt--;
1707			sh_argfree(shp,argsav,0);
1708			nv_close(np);
1709			break;
1710		    }
1711
1712		    case TWH: /* while and until */
1713		    {
1714			volatile int 	r=0;
1715			int first = OPTIMIZE_FLAG;
1716			Shnode_t *tt = t->wh.whtre;
1717#if SHOPT_FILESCAN
1718			Sfio_t *iop=0;
1719			int savein,fd;
1720#endif /*SHOPT_FILESCAN*/
1721#if SHOPT_OPTIMIZE
1722			int  jmpval = ((struct checkpt*)shp->jmplist)->mode;
1723			struct checkpt buff;
1724			void *optlist = shp->optlist;
1725			shp->optlist = 0;
1726			sh_tclear(t->wh.whtre);
1727			sh_tclear(t->wh.dotre);
1728			sh_pushcontext(&buff,jmpval);
1729			jmpval = sigsetjmp(buff.buff,0);
1730			if(jmpval)
1731				goto endwhile;
1732#endif /* SHOPT_OPTIMIZE */
1733#if SHOPT_FILESCAN
1734			if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
1735			{
1736				fd = sh_redirect(shp,tt->com.comio,3);
1737				savein = dup(0);
1738				if(fd==0)
1739					fd = savein;
1740				iop = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
1741				close(0);
1742				open("/dev/null",O_RDONLY);
1743				shp->offsets[0] = -1;
1744				shp->offsets[1] = 0;
1745				if(tt->com.comset)
1746					nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
1747			}
1748#endif /*SHOPT_FILESCAN */
1749			shp->st.loopcnt++;
1750			while(shp->st.execbrk==0)
1751			{
1752#if SHOPT_FILESCAN
1753				if(iop)
1754				{
1755					if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING)))
1756						break;
1757				}
1758				else
1759#endif /*SHOPT_FILESCAN */
1760				if((sh_exec(tt,first)==0)!=(type==TWH))
1761					break;
1762				r = sh_exec(t->wh.dotre,first|errorflg);
1763				if(shp->st.breakcnt<0)
1764					shp->st.execbrk = (++shp->st.breakcnt !=0);
1765				/* This is for the arithmetic for */
1766				if(shp->st.execbrk==0 && t->wh.whinc)
1767					sh_exec((Shnode_t*)t->wh.whinc,first);
1768				first = 0;
1769				errorflg &= ~OPTIMIZE_FLAG;
1770#if SHOPT_FILESCAN
1771				shp->offsets[0] = -1;
1772				shp->offsets[1] = 0;
1773#endif /*SHOPT_FILESCAN */
1774			}
1775#if SHOPT_OPTIMIZE
1776		endwhile:
1777			sh_popcontext(&buff);
1778			sh_tclear(t->wh.whtre);
1779			sh_tclear(t->wh.dotre);
1780			sh_optclear(shp,optlist);
1781			if(jmpval)
1782				siglongjmp(*shp->jmplist,jmpval);
1783#endif /*SHOPT_OPTIMIZE */
1784			if(shp->st.breakcnt>0)
1785				shp->st.execbrk = (--shp->st.breakcnt !=0);
1786			shp->st.loopcnt--;
1787			shp->exitval= r;
1788#if SHOPT_FILESCAN
1789			if(iop)
1790			{
1791				sfclose(iop);
1792				close(0);
1793				dup(savein);
1794				shp->cur_line = 0;
1795			}
1796#endif /*SHOPT_FILESCAN */
1797			break;
1798		    }
1799		    case TARITH: /* (( expression )) */
1800		    {
1801			register char *trap;
1802			char *arg[4];
1803			error_info.line = t->ar.arline-shp->st.firstline;
1804			arg[0] = "((";
1805			if(!(t->ar.arexpr->argflag&ARG_RAW))
1806				arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
1807			else
1808				arg[1] = t->ar.arexpr->argval;
1809			arg[2] = "))";
1810			arg[3] = 0;
1811			if(trap=shp->st.trap[SH_DEBUGTRAP])
1812				sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
1813			if(sh_isoption(SH_XTRACE))
1814			{
1815				sh_trace(NIL(char**),0);
1816				sfprintf(sfstderr,"((%s))\n",arg[1]);
1817			}
1818			if(t->ar.arcomp)
1819				shp->exitval  = !arith_exec((Arith_t*)t->ar.arcomp);
1820			else
1821				shp->exitval = !sh_arith(arg[1]);
1822			break;
1823		    }
1824
1825		    case TIF:
1826			if(sh_exec(t->if_.iftre,OPTIMIZE)==0)
1827				sh_exec(t->if_.thtre,flags);
1828			else if(t->if_.eltre)
1829				sh_exec(t->if_.eltre, flags);
1830			else
1831				shp->exitval=0; /* force zero exit for if-then-fi */
1832			break;
1833
1834		    case TSW:
1835		    {
1836			Shnode_t *tt = (Shnode_t*)t;
1837			char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
1838			error_info.line = t->sw.swline-shp->st.firstline;
1839			t= (Shnode_t*)(tt->sw.swlst);
1840			if(trap=shp->st.trap[SH_DEBUGTRAP])
1841			{
1842				char *av[4];
1843				av[0] = "case";
1844				av[1] = r;
1845				av[2] = "in";
1846				av[3] = 0;
1847				sh_debug(shp,trap, (char*)0, (char*)0, av, 0);
1848			}
1849			while(t)
1850			{
1851				register struct argnod	*rex=(struct argnod*)t->reg.regptr;
1852				while(rex)
1853				{
1854					register char *s;
1855					if(rex->argflag&ARG_MAC)
1856					{
1857						s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP);
1858						while(*s=='\\' && s[1]==0)
1859							s+=2;
1860					}
1861					else
1862						s = rex->argval;
1863					type = (rex->argflag&ARG_RAW);
1864					if((type && strcmp(r,s)==0) ||
1865						(!type && (strmatch(r,s)
1866						|| trim_eq(r,s))))
1867					{
1868						do	sh_exec(t->reg.regcom,(t->reg.regflag?0:flags));
1869						while(t->reg.regflag &&
1870							(t=(Shnode_t*)t->reg.regnxt));
1871						t=0;
1872						break;
1873					}
1874					else
1875						rex=rex->argnxt.ap;
1876				}
1877				if(t)
1878					t=(Shnode_t*)t->reg.regnxt;
1879			}
1880			break;
1881		    }
1882
1883		    case TTIME:
1884		    {
1885			/* time the command */
1886			struct tms before,after;
1887			const char *format = e_timeformat;
1888			clock_t at, tm[3];
1889#ifdef timeofday
1890			struct timeval tb,ta;
1891#else
1892			clock_t bt;
1893#endif	/* timeofday */
1894			if(type!=TTIME)
1895			{
1896				sh_exec(t->par.partre,OPTIMIZE);
1897				shp->exitval = !shp->exitval;
1898				break;
1899			}
1900			if(t->par.partre)
1901			{
1902				long timer_on;
1903				timer_on = sh_isstate(SH_TIMING);
1904#ifdef timeofday
1905				timeofday(&tb);
1906				times(&before);
1907#else
1908				bt = times(&before);
1909#endif	/* timeofday */
1910				job.waitall = 1;
1911				sh_onstate(SH_TIMING);
1912				sh_exec(t->par.partre,OPTIMIZE);
1913				if(!timer_on)
1914					sh_offstate(SH_TIMING);
1915				job.waitall = 0;
1916			}
1917			else
1918			{
1919#ifndef timeofday
1920				bt = 0;
1921#endif	/* timeofday */
1922				before.tms_utime = before.tms_cutime = 0;
1923				before.tms_stime = before.tms_cstime = 0;
1924			}
1925#ifdef timeofday
1926			times(&after);
1927			timeofday(&ta);
1928			at = shp->lim.clk_tck*(ta.tv_sec-tb.tv_sec);
1929			at +=  ((shp->lim.clk_tck*(((1000000L/2)/shp->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
1930#else
1931			at = times(&after) - bt;
1932#endif	/* timeofday */
1933			tm[0] = at;
1934			if(t->par.partre)
1935			{
1936				Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
1937				if(np)
1938				{
1939					format = nv_getval(np);
1940					nv_close(np);
1941				}
1942				if(!format)
1943					format = e_timeformat;
1944			}
1945			else
1946				format = strchr(format+1,'\n')+1;
1947			tm[1] = after.tms_utime - before.tms_utime;
1948			tm[1] += after.tms_cutime - before.tms_cutime;
1949			tm[2] = after.tms_stime - before.tms_stime;
1950			tm[2] += after.tms_cstime - before.tms_cstime;
1951			if(format && *format)
1952				p_time(shp,sfstderr,sh_translate(format),tm);
1953			break;
1954		    }
1955		    case TFUN:
1956		    {
1957			register Namval_t *np;
1958			register struct slnod *slp;
1959			register char *fname = ((struct functnod*)t)->functnam;
1960			register char *cp = strrchr(fname,'.');
1961			register Namval_t *npv=0;
1962#if SHOPT_NAMESPACE
1963			if(t->tre.tretyp==TNSPACE)
1964			{
1965				Dt_t *root,*oldroot, *top=0;
1966				Namval_t *oldnspace = shp->namespace;
1967				int offset = stktell(stkp);
1968				long optindex = shp->st.optindex;
1969				if(cp)
1970					errormsg(SH_DICT,ERROR_exit(1),e_ident,fname);
1971				sfputc(stkp,'.');
1972				sfputr(stkp,fname,0);
1973				np = nv_open(stkptr(stkp,offset),shp->var_base,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
1974				offset = stktell(stkp);
1975				shp->namespace = np;
1976				if(!(root=nv_dict(np)))
1977				{
1978					root = dtopen(&_Nvdisc,Dtoset);
1979					nv_putval(np,(char*)root,NV_TABLE|NV_NOFREE);
1980					shp->st.optindex = 1;
1981				}
1982				if(oldnspace && dtvnext(dtvnext(shp->var_tree)))
1983					top = dtview(shp->var_tree,0);
1984				else if(dtvnext(shp->var_tree))
1985					top = dtview(shp->var_tree,0);
1986				oldroot = shp->var_tree;
1987				dtview(root,shp->var_base);
1988				shp->var_tree = root;
1989				if(top)
1990					dtview(shp->var_tree,top);
1991				sh_exec(t->for_.fortre,flags);
1992				if(dtvnext(shp->var_tree))
1993					top = dtview(shp->var_tree,0);
1994				shp->var_tree = oldroot;
1995				if(top)
1996					dtview(top,shp->var_tree);
1997				shp->namespace = oldnspace;
1998				shp->st.optindex = optindex;
1999				break;
2000			}
2001#endif /* SHOPT_NAMESPACE */
2002			/* look for discipline functions */
2003			error_info.line = t->funct.functline-shp->st.firstline;
2004			/* Function names cannot be special builtin */
2005			if(cp || shp->prefix)
2006			{
2007				int offset = stktell(stkp);
2008				if(shp->prefix)
2009				{
2010					cp = shp->prefix;
2011					shp->prefix = 0;
2012					npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
2013					shp->prefix = cp;
2014					cp = fname;
2015				}
2016				else
2017				{
2018					sfwrite(stkp,fname,cp++-fname);
2019					sfputc(stkp,0);
2020					npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
2021				}
2022				offset = stktell(stkp);
2023				sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0);
2024				fname = stkptr(stkp,offset);
2025			}
2026			else if((np=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))
2027				errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname);
2028#if SHOPT_NAMESPACE
2029			else if(shp->namespace)
2030			{
2031				int offset = stktell(stkp);
2032				sfputr(stkp,nv_name(shp->namespace),-1);
2033				sfputc(stkp,'.');
2034				sfputr(stkp,fname,0);
2035				fname = stkptr(stkp,offset);
2036			}
2037#endif /* SHOPT_NAMESPACE */
2038			np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
2039			if(npv)
2040			{
2041				Namval_t *tp = npv;
2042				if(!shp->mktype)
2043				{
2044					if(shp->typeinit)
2045					{
2046						if(tp=nv_open(shp->typeinit->nvname,shp->typedict,NV_IDENT|NV_NOFAIL))
2047							nv_close(npv);
2048						else
2049							tp = npv;
2050					}
2051					cp = nv_setdisc(tp,cp,np,(Namfun_t*)tp);
2052				}
2053				nv_close(tp);
2054				if(!cp)
2055					errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);
2056			}
2057			if(np->nvalue.rp)
2058			{
2059				slp = (struct slnod*)np->nvenv;
2060				sh_funstaks(slp->slchild,-1);
2061				stakdelete(slp->slptr);
2062				if(shp->funload)
2063				{
2064					free((void*)np->nvalue.rp);
2065					np->nvalue.rp = 0;
2066				}
2067
2068			}
2069			if(!np->nvalue.rp)
2070			{
2071				np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
2072				memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
2073			}
2074			if(t->funct.functstak)
2075			{
2076				static Dtdisc_t		_Rpdisc =
2077				{
2078				        offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
2079				};
2080				struct functnod *fp;
2081				slp = t->funct.functstak;
2082				sh_funstaks(slp->slchild,1);
2083				staklink(slp->slptr);
2084				np->nvenv = (char*)slp;
2085				nv_funtree(np) = (int*)(t->funct.functtre);
2086				np->nvalue.rp->hoffset = t->funct.functloc;
2087				np->nvalue.rp->lineno = t->funct.functline;
2088				np->nvalue.rp->nspace = shp->namespace;
2089				np->nvalue.rp->fname = 0;
2090				np->nvalue.rp->fdict = shp->fun_tree;
2091				fp = (struct functnod*)(slp+1);
2092				if(fp->functtyp==(TFUN|FAMP))
2093					np->nvalue.rp->fname = fp->functnam;
2094				nv_setsize(np,fp->functline);
2095				nv_offattr(np,NV_FPOSIX);
2096				if(shp->funload)
2097				{
2098					struct Ufunction *rp = np->nvalue.rp;
2099					rp->np = np;
2100					if(!shp->fpathdict)
2101						shp->fpathdict = dtopen(&_Rpdisc,Dtbag);
2102					if(shp->fpathdict)
2103						dtinsert(shp->fpathdict,rp);
2104				}
2105			}
2106			else
2107				nv_unset(np);
2108			if(type&FPOSIX)
2109				nv_onattr(np,NV_FUNCTION|NV_FPOSIX);
2110			else
2111				nv_onattr(np,NV_FUNCTION);
2112			if(type&FPIN)
2113				nv_onattr(np,NV_FTMP);
2114			if(type&FOPTGET)
2115				nv_onattr(np,NV_OPTGET);
2116			break;
2117		    }
2118
2119		    /* new test compound command */
2120		    case TTST:
2121		    {
2122			register int n;
2123			register char *left;
2124			int negate = (type&TNEGATE)!=0;
2125			if(type&TTEST)
2126				skipexitset++;
2127			error_info.line = t->tst.tstline-shp->st.firstline;
2128			echeck = 1;
2129			if((type&TPAREN)==TPAREN)
2130			{
2131				sh_exec(t->lst.lstlef,OPTIMIZE);
2132				n = !shp->exitval;
2133			}
2134			else
2135			{
2136				register int traceon=0;
2137				register char *right;
2138				register char *trap;
2139				char *argv[6];
2140				n = type>>TSHIFT;
2141				left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
2142				if(type&TBINARY)
2143					right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
2144				if(trap=shp->st.trap[SH_DEBUGTRAP])
2145					argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[[";
2146				if(sh_isoption(SH_XTRACE))
2147				{
2148					traceon = sh_trace(NIL(char**),0);
2149					sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3));
2150				}
2151				if(type&TUNARY)
2152				{
2153					if(traceon)
2154						sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left));
2155					if(trap)
2156					{
2157						char unop[3];
2158						unop[0] = '-';
2159						unop[1] = n;
2160						unop[2] = 0;
2161						argv[1] = unop;
2162						argv[2] = left;
2163						argv[3] = "]]";
2164						argv[4] = 0;
2165						sh_debug(shp,trap,(char*)0,(char*)0,argv, 0);
2166					}
2167					n = test_unop(n,left);
2168				}
2169				else if(type&TBINARY)
2170				{
2171					char *op;
2172					int pattern = 0;
2173					if(trap || traceon)
2174						op = (char*)(shtab_testops+(n&037)-1)->sh_name;
2175					type >>= TSHIFT;
2176					if(type==TEST_PEQ || type==TEST_PNE)
2177						pattern=ARG_EXP;
2178					if(trap)
2179					{
2180						argv[1] = left;
2181						argv[2] = op;
2182						argv[3] = right;
2183						argv[4] = "]]";
2184						argv[5] = 0;
2185						sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
2186					}
2187					n = test_binop(n,left,right);
2188					if(traceon)
2189					{
2190						sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op);
2191						if(pattern)
2192							out_pattern(sfstderr,right,-1);
2193						else
2194							sfputr(sfstderr,sh_fmtq(right),-1);
2195					}
2196				}
2197				if(traceon)
2198					sfwrite(sfstderr,e_tstend,4);
2199			}
2200			shp->exitval = ((!n)^negate);
2201			if(!skipexitset)
2202				exitset();
2203			break;
2204		    }
2205		}
2206		if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
2207			t && echeck)
2208			sh_chktrap();
2209		/* set $_ */
2210		if(mainloop && com0)
2211		{
2212			/* store last argument here if it fits */
2213			static char	lastarg[32];
2214			if(sh_isstate(SH_FORKED))
2215				sh_done(shp,0);
2216			if(shp->lastarg!= lastarg && shp->lastarg)
2217				free(shp->lastarg);
2218			if(strlen(comn) < sizeof(lastarg))
2219			{
2220				nv_onattr(L_ARGNOD,NV_NOFREE);
2221				shp->lastarg = strcpy(lastarg,comn);
2222			}
2223			else
2224			{
2225				nv_offattr(L_ARGNOD,NV_NOFREE);
2226				shp->lastarg = strdup(comn);
2227			}
2228		}
2229		if(!skipexitset)
2230			exitset();
2231		if(!(OPTIMIZE))
2232		{
2233			if(sav != stkptr(stkp,0))
2234				stkset(stkp,sav,0);
2235			else if(stktell(stkp))
2236				stkseek(stkp,0);
2237		}
2238		if(shp->trapnote&SH_SIGSET)
2239			sh_exit(SH_EXITSIG|shp->lastsig);
2240		if(was_interactive)
2241			sh_onstate(SH_INTERACTIVE);
2242		if(was_monitor && sh_isoption(SH_MONITOR))
2243			sh_onstate(SH_MONITOR);
2244		if(was_errexit)
2245			sh_onstate(SH_ERREXIT);
2246	}
2247	return(shp->exitval);
2248}
2249
2250int sh_run(int argn, char *argv[])
2251{
2252	register struct dolnod	*dp;
2253	register struct comnod	*t = (struct comnod*)stakalloc(sizeof(struct comnod));
2254	int			savtop = staktell();
2255	char			*savptr = stakfreeze(0);
2256	Opt_t			*op, *np = optctx(0, 0);
2257	Shbltin_t		bltindata;
2258	bltindata = sh.bltindata;
2259	op = optctx(np, 0);
2260	memset(t, 0, sizeof(struct comnod));
2261	dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
2262	dp->dolnum = argn;
2263	dp->dolbot = ARG_SPARE;
2264	memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
2265	t->comarg = (struct argnod*)dp;
2266	if(!strchr(argv[0],'/'))
2267		t->comnamp = (void*)nv_bfsearch(argv[0],sh.fun_tree,(Namval_t**)&t->comnamq,(char**)0);
2268	argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
2269	optctx(op,np);
2270	sh.bltindata = bltindata;
2271	if(savptr!=stakptr(0))
2272		stakset(savptr,savtop);
2273	else
2274		stakseek(savtop);
2275	return(argn);
2276}
2277
2278/*
2279 * test for equality with second argument trimmed
2280 * returns 1 if r == trim(s) otherwise 0
2281 */
2282
2283static int trim_eq(register const char *r,register const char *s)
2284{
2285	register char c;
2286	while(c = *s++)
2287	{
2288		if(c=='\\')
2289			c = *s++;
2290		if(c && c != *r++)
2291			return(0);
2292	}
2293	return(*r==0);
2294}
2295
2296/*
2297 * print out the command line if set -x is on
2298 */
2299
2300int sh_trace(register char *argv[], register int nl)
2301{
2302	Shell_t	*shp = &sh;
2303	register char *cp;
2304	register int bracket = 0;
2305	int decl = (nl&2);
2306	nl &= ~2;
2307	if(sh_isoption(SH_XTRACE))
2308	{
2309		/* make this trace atomic */
2310		sfset(sfstderr,SF_SHARE|SF_PUBLIC,0);
2311		if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
2312			cp = "+ ";
2313		else
2314		{
2315			sh_offoption(SH_XTRACE);
2316			cp = sh_mactry(shp,cp);
2317			sh_onoption(SH_XTRACE);
2318		}
2319		if(*cp)
2320			sfputr(sfstderr,cp,-1);
2321		if(argv)
2322		{
2323			char *argv0 = *argv;
2324			nl = (nl?'\n':-1);
2325			/* don't quote [ and [[ */
2326			if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
2327			{
2328				sfputr(sfstderr,cp,*++argv?' ':nl);
2329				bracket = 1;
2330			}
2331			while(cp = *argv++)
2332			{
2333				if(bracket==0 || *argv || *cp!=']')
2334					cp = sh_fmtq(cp);
2335				if(decl && shp->prefix && cp!=argv0 && *cp!='-')
2336				{
2337					if(*cp=='.' && cp[1]==0)
2338						cp = shp->prefix;
2339					else
2340						sfputr(sfstderr,shp->prefix,'.');
2341				}
2342				sfputr(sfstderr,cp,*argv?' ':nl);
2343			}
2344			sfset(sfstderr,SF_SHARE|SF_PUBLIC,1);
2345		}
2346		return(1);
2347	}
2348	return(0);
2349}
2350
2351/*
2352 * This routine creates a subshell by calling fork() or vfork()
2353 * If ((flags&COMASK)==TCOM), then vfork() is permitted
2354 * If fork fails, the shell sleeps for exponentially longer periods
2355 *   and tries again until a limit is reached.
2356 * SH_FORKLIM is the max period between forks - power of 2 usually.
2357 * Currently shell tries after 2,4,8,16, and 32 seconds and then quits
2358 * Failures cause the routine to error exit.
2359 * Parent links to here-documents are removed by the child
2360 * Traps are reset by the child
2361 * The process-id of the child is returned to the parent, 0 to the child.
2362 */
2363
2364static void timed_out(void *handle)
2365{
2366	NOT_USED(handle);
2367	timeout = 0;
2368}
2369
2370
2371/*
2372 * called by parent and child after fork by sh_fork()
2373 */
2374pid_t _sh_fork(register pid_t parent,int flags,int *jobid)
2375{
2376	static long forkcnt = 1000L;
2377	Shell_t	*shp = &sh;
2378	pid_t	curpgid = job.curpgid;
2379	pid_t	postid = (flags&FAMP)?0:curpgid;
2380	int	sig,nochild;
2381	if(parent<0)
2382	{
2383		sh_sigcheck();
2384		if((forkcnt *= 2) > 1000L*SH_FORKLIM)
2385		{
2386			forkcnt=1000L;
2387			errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork);
2388		}
2389		timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
2390		nochild = job_wait((pid_t)1);
2391		if(timeout)
2392		{
2393			if(nochild)
2394				pause();
2395			else if(forkcnt>1000L)
2396				forkcnt /= 2;
2397			timerdel(timeout);
2398			timeout = 0;
2399		}
2400		return(-1);
2401	}
2402	forkcnt = 1000L;
2403	if(parent)
2404	{
2405		int myjob,waitall=job.waitall;
2406		shp->nforks++;
2407		if(job.toclear)
2408			job_clear();
2409		job.waitall = waitall;
2410#ifdef JOBS
2411		/* first process defines process group */
2412		if(sh_isstate(SH_MONITOR))
2413		{
2414			/*
2415			 * errno==EPERM means that an earlier processes
2416			 * completed.  Make parent the job group id.
2417			 */
2418			if(postid==0)
2419				job.curpgid = parent;
2420			if(job.jobcontrol || (flags&FAMP))
2421			{
2422				if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
2423					setpgid(parent,parent);
2424			}
2425		}
2426#endif /* JOBS */
2427		if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
2428			job.curpgid = parent;
2429		if(flags&FCOOP)
2430			shp->cpid = parent;
2431#ifdef SHOPT_BGX
2432		if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
2433			postid = 1;
2434		myjob = job_post(parent,postid);
2435		if(postid==1)
2436			postid = 0;
2437#else
2438		myjob = job_post(parent,postid);
2439#endif /* SHOPT_BGX */
2440		if(flags&FAMP)
2441			job.curpgid = curpgid;
2442		if(jobid)
2443			*jobid = myjob;
2444		return(parent);
2445	}
2446#if !_std_malloc
2447	vmtrace(-1);
2448#endif
2449	/* This is the child process */
2450	if(shp->trapnote&SH_SIGTERM)
2451		sh_exit(SH_EXITSIG|SIGTERM);
2452	shp->nforks=0;
2453	timerdel(NIL(void*));
2454#ifdef JOBS
2455	if(!job.jobcontrol && !(flags&FAMP))
2456		sh_offstate(SH_MONITOR);
2457	if(sh_isstate(SH_MONITOR))
2458	{
2459		parent = getpid();
2460		if(postid==0)
2461			job.curpgid = parent;
2462		while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent)
2463			job.curpgid = parent;
2464#   ifdef SIGTSTP
2465		if(job.curpgid==parent &&  !(flags&FAMP))
2466			tcsetpgrp(job.fd,job.curpgid);
2467#   endif /* SIGTSTP */
2468	}
2469#   ifdef SIGTSTP
2470	if(job.jobcontrol)
2471	{
2472		signal(SIGTTIN,SIG_DFL);
2473		signal(SIGTTOU,SIG_DFL);
2474		signal(SIGTSTP,SIG_DFL);
2475	}
2476#   endif /* SIGTSTP */
2477	job.jobcontrol = 0;
2478#endif /* JOBS */
2479	job.toclear = 1;
2480	shp->login_sh = 0;
2481	sh_offoption(SH_LOGIN_SHELL);
2482	sh_onstate(SH_FORKED);
2483	sh_onstate(SH_NOLOG);
2484	if (shp->fn_reset)
2485		shp->fn_depth = shp->fn_reset = 0;
2486#if SHOPT_ACCT
2487	sh_accsusp();
2488#endif	/* SHOPT_ACCT */
2489	/* Reset remaining signals to parent */
2490	/* except for those `lost' by trap   */
2491	if(!(flags&FSHOWME))
2492		sh_sigreset(2);
2493	shp->subshell = 0;
2494	if((flags&FAMP) && shp->coutpipe>1)
2495		sh_close(shp->coutpipe);
2496	sig = shp->savesig;
2497	shp->savesig = 0;
2498	if(sig>0)
2499		sh_fault(sig);
2500	sh_sigcheck();
2501	return(0);
2502}
2503
2504pid_t sh_fork(int flags, int *jobid)
2505{
2506	register pid_t parent;
2507	register int sig;
2508#if SHOPT_FASTPIPE
2509	if(sffileno(sfstdin)<0)
2510	{
2511		off_t current = sfseek(sfstdin,(off_t)0,SEEK_CUR);
2512		sfseek(sfstdin,(off_t)0,SEEK_END);
2513		sfdisc(sfstdin,SF_POPDISC);
2514		fcntl(sffileno(sfstdin),F_SETFD,0);
2515		sh_iostream(0);
2516		sfseek(sfstdin,current,SEEK_SET);
2517	}
2518#endif /* SHOPT_FASTPIPE */
2519	if(!sh.pathlist)
2520		path_get("");
2521	sfsync(NIL(Sfio_t*));
2522	sh.trapnote &= ~SH_SIGTERM;
2523	job_fork(-1);
2524	sh.savesig = -1;
2525	while(_sh_fork(parent=fork(),flags,jobid) < 0);
2526	sh_stats(STAT_FORKS);
2527	sig = sh.savesig;
2528	sh.savesig = 0;
2529	if(sig>0)
2530		sh_fault(sig);
2531	job_fork(parent);
2532	return(parent);
2533}
2534
2535/*
2536 * add exports from previous scope to the new scope
2537 */
2538static void  local_exports(register Namval_t *np, void *data)
2539{
2540	register Namval_t	*mp;
2541	register char		*cp;
2542	if(nv_isarray(np))
2543		nv_putsub(np,NIL(char*),0);
2544	if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), sh.var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
2545		nv_putval(mp, cp, 0);
2546}
2547
2548/*
2549 * This routine is used to execute the given function <fun> in a new scope
2550 * If <fun> is NULL, then arg points to a structure containing a pointer
2551 *  to a function that will be executed in the current environment.
2552 */
2553int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
2554{
2555	register char		*trap;
2556	register int		nsig;
2557	register Shell_t	*shp =  &sh;
2558	struct dolnod		*argsav=0,*saveargfor;
2559	struct sh_scoped	savst, *prevscope = shp->st.self;
2560	struct argnod		*envlist=0;
2561	int			jmpval;
2562	volatile int		r = 0;
2563	char 			*savstak;
2564	struct funenv		*fp;
2565	struct checkpt		buff;
2566	Namval_t		*nspace = shp->namespace;
2567	Dt_t			*last_root = shp->last_root;
2568	Shopt_t			options = shp->options;
2569	if(shp->fn_depth==0)
2570		shp->glob_options =  shp->options;
2571	else
2572		shp->options = shp->glob_options;
2573#if 0
2574	shp->st.lineno = error_info.line;
2575#endif
2576	*prevscope = shp->st;
2577	sh_offoption(SH_ERREXIT);
2578	shp->st.prevst = prevscope;
2579	shp->st.self = &savst;
2580	shp->topscope = (Shscope_t*)shp->st.self;
2581	shp->st.opterror = shp->st.optchar = 0;
2582	shp->st.optindex = 1;
2583	shp->st.loopcnt = 0;
2584	if(!fun)
2585	{
2586		fp = (struct funenv*)arg;
2587		shp->st.real_fun = (fp->node)->nvalue.rp;
2588		envlist = fp->env;
2589	}
2590	prevscope->save_tree = shp->var_tree;
2591	sh_scope(shp,envlist,1);
2592	if(dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0))
2593	{
2594		/* eliminate parent scope */
2595		nv_scan(prevscope->save_tree, local_exports,(void*)0, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
2596	}
2597	shp->st.save_tree = shp->var_tree;
2598	if(!fun)
2599	{
2600		Namval_t *np;
2601		if(nv_isattr(fp->node,NV_TAGGED))
2602			sh_onoption(SH_XTRACE);
2603		else
2604			sh_offoption(SH_XTRACE);
2605#if SHOPT_NAMESPACE
2606		if((np=(fp->node)->nvalue.rp->nspace) && np!=shp->namespace)
2607		{
2608			Dt_t *dt = shp->var_tree;
2609			dtview(dt,0);
2610			dtview(dt,nv_dict(np));
2611			shp->var_tree = nv_dict(np);
2612			shp->namespace = np;
2613		}
2614#endif /* SHOPT_NAMESPACE */
2615	}
2616	shp->st.cmdname = argv[0];
2617	/* save trap table */
2618	if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
2619	{
2620		nsig += sizeof(char*);
2621		memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
2622	}
2623	sh_sigreset(0);
2624	argsav = sh_argnew(shp,argv,&saveargfor);
2625	sh_pushcontext(&buff,SH_JMPFUN);
2626	errorpush(&buff.err,0);
2627	error_info.id = argv[0];
2628	shp->st.var_local = shp->var_tree;
2629	jmpval = sigsetjmp(buff.buff,0);
2630	if(!fun)
2631	{
2632		shp->st.filename = fp->node->nvalue.rp->fname;
2633		shp->st.funname = nv_name(fp->node);
2634		nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
2635		nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
2636	}
2637	if(jmpval == 0)
2638	{
2639		if(shp->fn_depth++ > MAXDEPTH)
2640		{
2641			shp->toomany = 1;
2642			siglongjmp(*shp->jmplist,SH_JMPERRFN);
2643		}
2644		else if(fun)
2645			r= (*fun)(arg);
2646		else
2647		{
2648			sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
2649			r = shp->exitval;
2650		}
2651	}
2652	if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN)
2653		errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]);
2654	sh_popcontext(&buff);
2655	if (shp->st.self != &savst)
2656		shp->var_tree = (Dt_t*)savst.save_tree;
2657	sh_unscope(shp);
2658	shp->namespace = nspace;
2659	shp->var_tree = (Dt_t*)prevscope->save_tree;
2660	if(shp->topscope != (Shscope_t*)shp->st.self)
2661		sh_setscope(shp->topscope);
2662	sh_argreset(shp,argsav,saveargfor);
2663	trap = shp->st.trapcom[0];
2664	shp->st.trapcom[0] = 0;
2665	sh_sigreset(1);
2666	if (shp->st.self != &savst)
2667		*shp->st.self = shp->st;
2668	shp->st = *prevscope;
2669	shp->topscope = (Shscope_t*)prevscope;
2670	nv_getval(sh_scoped(shp,IFSNOD));
2671	if(nsig)
2672		memcpy((char*)&shp->st.trapcom[0],savstak,nsig);
2673	shp->trapnote=0;
2674	if(nsig)
2675		stakset(savstak,0);
2676	shp->options = options;
2677	shp->last_root = last_root;
2678	if(jmpval == SH_JMPSUB)
2679		siglongjmp(*shp->jmplist,jmpval);
2680	if(trap)
2681	{
2682		sh_trap(trap,0);
2683		free(trap);
2684	}
2685	if(shp->exitval > SH_EXITSIG)
2686		sh_fault(shp->exitval&SH_EXITMASK);
2687	if(jmpval > SH_JMPFUN)
2688	{
2689		sh_chktrap();
2690		siglongjmp(*shp->jmplist,jmpval);
2691	}
2692	return(r);
2693}
2694
2695static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
2696{
2697	struct funenv fun;
2698	char *fname = nv_getval(SH_FUNNAMENOD);
2699	struct Level	*lp =(struct Level*)(SH_LEVELNOD->nvfun);
2700	int		level, pipepid=shp->pipepid;
2701	shp->pipepid = 0;
2702	sh_stats(STAT_FUNCT);
2703	if(!lp->hdr.disc)
2704		lp = init_level(0);
2705	if((struct sh_scoped*)shp->topscope != shp->st.self)
2706		sh_setscope(shp->topscope);
2707	level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
2708	SH_LEVELNOD->nvalue.s = lp->maxlevel;
2709	shp->st.lineno = error_info.line;
2710	if(nv_isattr(np,NV_FPOSIX))
2711	{
2712		char *save;
2713		int loopcnt = shp->st.loopcnt;
2714		shp->posix_fun = np;
2715		save = argv[-1];
2716		argv[-1] = 0;
2717		shp->st.funname = nv_name(np);
2718		nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE);
2719		opt_info.index = opt_info.offset = 0;
2720		error_info.errors = 0;
2721		shp->st.loopcnt = 0;
2722		b_dot_cmd(argn+1,argv-1,&shp->bltindata);
2723		shp->st.loopcnt = loopcnt;
2724		argv[-1] = save;
2725	}
2726	else
2727	{
2728		fun.env = envlist;
2729		fun.node = np;
2730		sh_funscope(argn,argv,0,&fun,execflg);
2731	}
2732	if(level-- != nv_getnum(SH_LEVELNOD))
2733	{
2734		Shscope_t *sp = sh_getscope(0,SEEK_END);
2735		sh_setscope(sp);
2736	}
2737	lp->maxlevel = level;
2738	SH_LEVELNOD->nvalue.s = lp->maxlevel;
2739#if 0
2740	nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
2741#else
2742	nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE);
2743#endif
2744	nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
2745	shp->pipepid = pipepid;
2746}
2747
2748/*
2749 * external interface to execute a function without arguments
2750 * <np> is the function node
2751 * If <nq> is not-null, then sh.name and sh.subscript will be set
2752 */
2753int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
2754{
2755	Shell_t		*shp = &sh;
2756	register int offset;
2757	register char *base;
2758	Namval_t node;
2759	struct Namref	nr;
2760	long		mode;
2761	char		*prefix = shp->prefix;
2762	int n=0;
2763	char *av[2];
2764	Fcin_t save;
2765	fcsave(&save);
2766	if((offset=staktell())>0)
2767		base=stakfreeze(0);
2768	shp->prefix = 0;
2769	if(!argv)
2770	{
2771		argv = av;
2772		argv[1]=0;
2773	}
2774	argv[0] = nv_name(np);
2775	while(argv[n])
2776		n++;
2777	if(nq)
2778		mode = set_instance(shp,nq,&node, &nr);
2779	if(is_abuiltin(np))
2780	{
2781		int jmpval;
2782		struct checkpt buff;
2783		Shbltin_t *bp = &sh.bltindata;
2784		sh_pushcontext(&buff,SH_JMPCMD);
2785		jmpval = sigsetjmp(buff.buff,1);
2786		if(jmpval == 0)
2787		{
2788			bp->bnode = np;
2789			bp->ptr = nv_context(np);
2790			errorpush(&buff.err,0);
2791			error_info.id = argv[0];
2792			opt_info.index = opt_info.offset = 0;
2793			opt_info.disc = 0;
2794			sh.exitval = 0;
2795			sh.exitval = (*funptr(np))(n,argv,(void*)bp);
2796		}
2797		sh_popcontext(&buff);
2798		if(jmpval>SH_JMPCMD)
2799			siglongjmp(*sh.jmplist,jmpval);
2800	}
2801	else
2802		sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
2803	if(nq)
2804		unset_instance(nq, &node, &nr, mode);
2805	fcrestore(&save);
2806	if(offset>0)
2807		stakset(base,offset);
2808	shp->prefix = prefix;
2809	return(sh.exitval);
2810}
2811
2812/*
2813 * This dummy routine is called by built-ins that do recursion
2814 * on the file system (chmod, chgrp, chown).  It causes
2815 * the shell to invoke the non-builtin version in this case
2816 */
2817int cmdrecurse(int argc, char* argv[], int ac, char* av[])
2818{
2819	NOT_USED(argc);
2820	NOT_USED(argv[0]);
2821	NOT_USED(ac);
2822	NOT_USED(av[0]);
2823	return(SH_RUNPROG);
2824}
2825
2826/*
2827 * set up pipe for cooperating process
2828 */
2829static void coproc_init(Shell_t *shp, int pipes[])
2830{
2831	int outfd;
2832	if(shp->coutpipe>=0 && shp->cpid)
2833		errormsg(SH_DICT,ERROR_exit(1),e_pexists);
2834	shp->cpid = 0;
2835	if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0)
2836	{
2837		/* first co-process */
2838		sh_pclose(shp->cpipe);
2839		sh_pipe(shp->cpipe);
2840		if((outfd=shp->cpipe[1]) < 10)
2841		{
2842		        int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
2843			if(fd>=10)
2844			{
2845			        shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
2846				close(outfd);
2847			        shp->fdstatus[outfd] = IOCLOSE;
2848				shp->cpipe[1] = fd;
2849			}
2850		}
2851		if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0)
2852			shp->fdstatus[shp->cpipe[0]] |= IOCLEX;
2853		shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
2854
2855		if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0)
2856			shp->fdstatus[shp->cpipe[1]] |= IOCLEX;
2857	}
2858	shp->outpipe = shp->cpipe;
2859	sh_pipe(shp->inpipe=pipes);
2860	shp->coutpipe = shp->inpipe[1];
2861	shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
2862	if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
2863		shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
2864}
2865
2866#if SHOPT_SPAWN
2867
2868
2869#if SHOPT_AMP || !defined(_lib_fork)
2870/*
2871 * print out function definition
2872 */
2873static void print_fun(register Namval_t* np, void *data)
2874{
2875	register char *format;
2876	NOT_USED(data);
2877	if(!is_afunction(np) || !np->nvalue.ip)
2878		return;
2879	if(nv_isattr(np,NV_FPOSIX))
2880		format="%s()\n{ ";
2881	else
2882		format="function %s\n{ ";
2883	sfprintf(sfstdout,format,nv_name(np));
2884	sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0);
2885	sfwrite(sfstdout,"}\n",2);
2886}
2887
2888/*
2889 * create a shell script consisting of t->fork.forktre and execute it
2890 */
2891static int run_subshell(const Shnode_t *t,pid_t grp)
2892{
2893	static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
2894	register int i, fd, trace = sh_isoption(SH_XTRACE);
2895	int pin,pout;
2896	pid_t pid;
2897	char *arglist[2], *envlist[2], devfd[12], *cp;
2898	Sfio_t *sp = sftmp(0);
2899	envlist[0] = "_=" SH_ID;
2900	envlist[1] = 0;
2901	arglist[0] = error_info.id?error_info.id:sh.shname;
2902	if(*arglist[0]=='-')
2903		arglist[0]++;
2904	arglist[1] = devfd;
2905	strncpy(devfd,e_devfdNN,sizeof(devfd));
2906	arglist[2] = 0;
2907	sfstack(sfstdout,sp);
2908	if(trace)
2909		sh_offoption(SH_XTRACE);
2910	sfwrite(sfstdout,"typeset -A -- ",14);
2911	sh_trap(prolog,0);
2912	nv_scan(sh.fun_tree, print_fun, (void*)0,0, 0);
2913	if(sh.st.dolc>0)
2914	{
2915		/* pass the positional parameters */
2916		char **argv = sh.st.dolv+1;
2917		sfwrite(sfstdout,"set --",6);
2918		while(*argv)
2919			sfprintf(sfstdout," %s",sh_fmtq(*argv++));
2920		sfputc(sfstdout,'\n');
2921	}
2922	pin = (sh.inpipe?sh.inpipe[1]:0);
2923	pout = (sh.outpipe?sh.outpipe[0]:0);
2924	for(i=3; i < 10; i++)
2925	{
2926		if(sh.fdstatus[i]&IOCLEX && i!=pin && i!=pout)
2927		{
2928			sfprintf(sfstdout,"exec %d<&%d\n",i,i);
2929			fcntl(i,F_SETFD,0);
2930		}
2931	}
2932	sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline);
2933	if(trace)
2934	{
2935		sfwrite(sfstdout,"set -x\n",7);
2936		sh_onoption(SH_XTRACE);
2937	}
2938	sfstack(sfstdout,NIL(Sfio_t*));
2939	sh_deparse(sp,t->fork.forktre,0);
2940	sfseek(sp,(Sfoff_t)0,SEEK_SET);
2941	fd = sh_dup(sffileno(sp));
2942	cp = devfd+8;
2943	if(fd>9)
2944		*cp++ = '0' + (fd/10);
2945	*cp++ = '0' + fd%10;
2946	*cp = 0;
2947	sfclose(sp);
2948	sfsync(NIL(Sfio_t*));
2949	if(!sh.shpath)
2950		sh.shpath = pathshell();
2951	pid = spawnveg(sh.shpath,arglist,envlist,grp);
2952	close(fd);
2953	for(i=3; i < 10; i++)
2954	{
2955		if(sh.fdstatus[i]&IOCLEX && i!=pin && i!=pout)
2956			fcntl(i,F_SETFD,FD_CLOEXEC);
2957	}
2958	if(pid <=0)
2959		errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
2960	return(pid);
2961}
2962#endif /* !_lib_fork */
2963
2964static void sigreset(int mode)
2965{
2966	register char   *trap;
2967	register int sig=sh.st.trapmax;
2968	while(sig-- > 0)
2969	{
2970		if((trap=sh.st.trapcom[sig]) && *trap==0)
2971			signal(sig,mode?sh_fault:SIG_IGN);
2972	}
2973}
2974
2975/*
2976 * A combined fork/exec for systems with slow or non-existent fork()
2977 */
2978static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
2979{
2980	static pid_t	spawnpid;
2981	static int	savetype;
2982	static int	savejobid __unused;
2983	struct checkpt	buff;
2984	int		otype=0, jmpval;
2985	volatile int	jobwasset=0, scope=0, sigwasset=0;
2986	char		**arge, *path;
2987	volatile pid_t	grp = 0;
2988	Pathcomp_t	*pp;
2989	if(flag)
2990	{
2991		otype = savetype;
2992		savetype=0;
2993	}
2994#   if SHOPT_AMP || !defined(_lib_fork)
2995	if(!argv)
2996	{
2997		register Shnode_t *tchild = t->fork.forktre;
2998		int optimize=0;
2999		otype = t->tre.tretyp;
3000		savetype = otype;
3001		spawnpid = 0;
3002#	ifndef _lib_fork
3003		if((tchild->tre.tretyp&COMMSK)==TCOM)
3004		{
3005			Namval_t *np = (Namval_t*)(tchild->com.comnamp);
3006			if(np)
3007			{
3008				path = nv_name(np);
3009				if(!nv_isattr(np,BLT_ENV))
3010					np=0;
3011				else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
3012					np=0;
3013			}
3014			else if(!tchild->com.comarg)
3015				optimize=1;
3016			else if(tchild->com.comtyp&COMSCAN)
3017			{
3018				if(tchild->com.comarg->argflag&ARG_RAW)
3019					path = tchild->com.comarg->argval;
3020				else
3021					path = 0;
3022			}
3023			else
3024				path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
3025			if(!np && path && !nv_search(path,shp->fun_tree,0))
3026				optimize=1;
3027		}
3028#	endif
3029		sh_pushcontext(&buff,SH_JMPIO);
3030		jmpval = sigsetjmp(buff.buff,0);
3031		{
3032			if((otype&FINT) && !sh_isstate(SH_MONITOR))
3033			{
3034				signal(SIGQUIT,SIG_IGN);
3035				signal(SIGINT,SIG_IGN);
3036				if(!shp->st.ioset)
3037				{
3038					sh_iosave(shp,0,buff.topfd,(char*)0);
3039					sh_iorenumber(shp,sh_chkopen(e_devnull),0);
3040				}
3041			}
3042			if(otype&FPIN)
3043			{
3044				int fd = shp->inpipe[1];
3045				sh_iosave(shp,0,buff.topfd,(char*)0);
3046				sh_iorenumber(shp,shp->inpipe[0],0);
3047				if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
3048					shp->fdstatus[fd] |= IOCLEX;
3049			}
3050			if(otype&FPOU)
3051			{
3052				sh_iosave(shp,1,buff.topfd,(char*)0);
3053				sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1);
3054				if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
3055					shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
3056			}
3057
3058			if(t->fork.forkio)
3059				sh_redirect(shp,t->fork.forkio,0);
3060			if(optimize==0)
3061			{
3062#ifdef SIGTSTP
3063				if(job.jobcontrol)
3064				{
3065					signal(SIGTTIN,SIG_DFL);
3066					signal(SIGTTOU,SIG_DFL);
3067				}
3068#endif /* SIGTSTP */
3069#ifdef JOBS
3070				if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3071				{
3072					if((otype&FAMP) || job.curpgid==0)
3073						grp = 1;
3074					else
3075						grp = job.curpgid;
3076				}
3077#endif /* JOBS */
3078				spawnpid = run_subshell(t,grp);
3079			}
3080			else
3081			{
3082				sh_exec(tchild,SH_NTFORK);
3083				if(jobid)
3084					*jobid = savejobid;
3085			}
3086		}
3087		sh_popcontext(&buff);
3088		if((otype&FINT) && !sh_isstate(SH_MONITOR))
3089		{
3090			signal(SIGQUIT,sh_fault);
3091			signal(SIGINT,sh_fault);
3092		}
3093		if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
3094			shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX;
3095		if(t->fork.forkio || otype)
3096			sh_iorestore(shp,buff.topfd,jmpval);
3097		if(optimize==0)
3098		{
3099#ifdef SIGTSTP
3100			if(job.jobcontrol)
3101			{
3102				signal(SIGTTIN,SIG_IGN);
3103				signal(SIGTTOU,SIG_IGN);
3104			}
3105#endif /* SIGTSTP */
3106			if(spawnpid>0)
3107				_sh_fork(spawnpid,otype,jobid);
3108			if(grp>0 && !(otype&FAMP))
3109			{
3110				while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
3111					job.curpgid = spawnpid;
3112			}
3113		}
3114		savetype=0;
3115		if(jmpval>SH_JMPIO)
3116			siglongjmp(*shp->jmplist,jmpval);
3117		if(spawnpid<0 && (otype&FCOOP))
3118		{
3119			sh_close(shp->coutpipe);
3120			sh_close(shp->cpipe[1]);
3121			shp->cpipe[1] = -1;
3122			shp->coutpipe = -1;
3123		}
3124		shp->exitval = 0;
3125		return(spawnpid);
3126	}
3127#   endif /* !_lib_fork */
3128	sh_pushcontext(&buff,SH_JMPCMD);
3129	errorpush(&buff.err,ERROR_SILENT);
3130	jmpval = sigsetjmp(buff.buff,0);
3131	if(jmpval == 0)
3132	{
3133		if((otype&FINT) && !sh_isstate(SH_MONITOR))
3134		{
3135			signal(SIGQUIT,SIG_IGN);
3136			signal(SIGINT,SIG_IGN);
3137		}
3138		spawnpid = -1;
3139		if(t->com.comio)
3140			sh_redirect(shp,t->com.comio,0);
3141		error_info.id = *argv;
3142		if(t->com.comset)
3143		{
3144			scope++;
3145			sh_scope(shp,t->com.comset,0);
3146		}
3147		if(!strchr(path=argv[0],'/'))
3148		{
3149			Namval_t *np;
3150			if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
3151				path = nv_getval(np);
3152			else if(path_absolute(path,NIL(Pathcomp_t*)))
3153			{
3154			path = stkptr(shp->stk,PATH_OFFSET);
3155			stkfreeze(shp->stk,0);
3156		}
3157		else
3158		{
3159			pp=path_get(path);
3160			while(pp)
3161			{
3162				if(pp->len==1 && *pp->name=='.')
3163					break;
3164				pp = pp->next;
3165			}
3166			if(!pp)
3167				path = 0;
3168		}
3169	}
3170	else if(sh_isoption(SH_RESTRICTED))
3171		errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
3172	if(!path)
3173	{
3174		spawnpid = -1;
3175		goto fail;
3176	}
3177	arge = sh_envgen();
3178	shp->exitval = 0;
3179#ifdef SIGTSTP
3180		if(job.jobcontrol)
3181		{
3182			signal(SIGTTIN,SIG_DFL);
3183			signal(SIGTTOU,SIG_DFL);
3184			jobwasset++;
3185		}
3186#endif /* SIGTSTP */
3187#ifdef JOBS
3188		if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3189		{
3190			if((otype&FAMP) || job.curpgid==0)
3191				grp = 1;
3192			else
3193				grp = job.curpgid;
3194		}
3195#endif /* JOBS */
3196
3197		sfsync(NIL(Sfio_t*));
3198		sigreset(0);	/* set signals to ignore */
3199		sigwasset++;
3200	        /* find first path that has a library component */
3201		for(pp=path_get(argv[0]); pp && !pp->lib ; pp=pp->next);
3202		spawnpid = path_spawn(path,argv,arge,pp,(grp<<1)|1);
3203		if(spawnpid < 0 && errno==ENOEXEC)
3204		{
3205			char *devfd;
3206			int fd = open(path,O_RDONLY);
3207			argv[-1] = argv[0];
3208			argv[0] = path;
3209			if(fd>=0)
3210			{
3211				struct stat statb;
3212				sfprintf(sh.strbuf,"/dev/fd/%d",fd);
3213				if(stat(devfd=sfstruse(sh.strbuf),&statb)>=0)
3214					argv[0] =  devfd;
3215			}
3216			if(!shp->shpath)
3217				shp->shpath = pathshell();
3218			spawnpid = path_spawn(shp->shpath,&argv[-1],arge,pp,(grp<<1)|1);
3219			if(fd>=0)
3220				close(fd);
3221			argv[0] = argv[-1];
3222		}
3223	fail:
3224		if(spawnpid < 0) switch(errno=shp->path_err)
3225		{
3226		    case ENOENT:
3227			errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4);
3228			/* FALLTHROUGH */
3229		    default:
3230			errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
3231		}
3232	}
3233	else
3234		exitset();
3235	sh_popcontext(&buff);
3236	if(buff.olist)
3237		free_list(buff.olist);
3238#ifdef SIGTSTP
3239	if(jobwasset)
3240	{
3241		signal(SIGTTIN,SIG_IGN);
3242		signal(SIGTTOU,SIG_IGN);
3243	}
3244#endif /* SIGTSTP */
3245	if(sigwasset)
3246		sigreset(1);	/* restore ignored signals */
3247	if(scope)
3248	{
3249		sh_unscope(shp);
3250		if(jmpval==SH_JMPSCRIPT)
3251			nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
3252	}
3253	if(t->com.comio)
3254		sh_iorestore(shp,buff.topfd,jmpval);
3255	if(jmpval>SH_JMPCMD)
3256		siglongjmp(*shp->jmplist,jmpval);
3257	if(spawnpid>0)
3258	{
3259		_sh_fork(spawnpid,otype,jobid);
3260#ifdef JOBS
3261		if(grp==1)
3262			job.curpgid = spawnpid;
3263#   ifdef SIGTSTP
3264		if(grp>0 && !(otype&FAMP))
3265		{
3266			while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
3267				job.curpgid = spawnpid;
3268		}
3269#   endif /* SIGTSTP */
3270#endif /* JOBS */
3271		savejobid = *jobid;
3272		if(otype)
3273			return(0);
3274	}
3275	return(spawnpid);
3276}
3277
3278#   ifdef _was_lib_fork
3279#	define _lib_fork	1
3280#   endif
3281#   ifndef _lib_fork
3282	pid_t fork(void)
3283	{
3284		errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork");
3285		return(-1);
3286	}
3287#   endif /* _lib_fork */
3288#endif /* SHOPT_SPAWN */
3289