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