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