1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * UNIX shell parse tree executer
23da2e3ebdSchin *
24da2e3ebdSchin * David Korn
25da2e3ebdSchin * AT&T Labs
26da2e3ebdSchin *
27da2e3ebdSchin */
28da2e3ebdSchin
29da2e3ebdSchin #include "defs.h"
30da2e3ebdSchin #include <fcin.h>
31da2e3ebdSchin #include "variables.h"
32da2e3ebdSchin #include "path.h"
33da2e3ebdSchin #include "name.h"
34da2e3ebdSchin #include "io.h"
35da2e3ebdSchin #include "shnodes.h"
36da2e3ebdSchin #include "jobs.h"
37da2e3ebdSchin #include "test.h"
38da2e3ebdSchin #include "builtins.h"
39da2e3ebdSchin #include "FEATURE/time"
40da2e3ebdSchin #include "FEATURE/externs"
41da2e3ebdSchin #include "FEATURE/locale"
42da2e3ebdSchin #include "streval.h"
43da2e3ebdSchin
44da2e3ebdSchin #if !_std_malloc
45da2e3ebdSchin # include <vmalloc.h>
46da2e3ebdSchin #endif
47da2e3ebdSchin
487c2fbfb3SApril Chin #if _lib_vfork
497c2fbfb3SApril Chin # include <ast_vfork.h>
507c2fbfb3SApril Chin #else
517c2fbfb3SApril Chin # define vfork() fork()
527c2fbfb3SApril Chin #endif
537c2fbfb3SApril Chin
54da2e3ebdSchin #define SH_NTFORK SH_TIMING
55da2e3ebdSchin
56da2e3ebdSchin #if _lib_nice
57da2e3ebdSchin extern int nice(int);
58da2e3ebdSchin #endif /* _lib_nice */
59da2e3ebdSchin #if !_lib_spawnveg
60da2e3ebdSchin # define spawnveg(a,b,c,d) spawnve(a,b,c)
61da2e3ebdSchin #endif /* !_lib_spawnveg */
62da2e3ebdSchin #if SHOPT_SPAWN
637c2fbfb3SApril Chin static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
64da2e3ebdSchin #endif /* SHOPT_SPAWN */
65da2e3ebdSchin
667c2fbfb3SApril Chin static void sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
67da2e3ebdSchin static int trim_eq(const char*, const char*);
687c2fbfb3SApril Chin static void coproc_init(Shell_t*, int pipes[]);
69da2e3ebdSchin
70da2e3ebdSchin static void *timeout;
71da2e3ebdSchin static char pipejob;
72da2e3ebdSchin
73da2e3ebdSchin struct funenv
74da2e3ebdSchin {
75da2e3ebdSchin Namval_t *node;
76da2e3ebdSchin struct argnod *env;
77da2e3ebdSchin };
78da2e3ebdSchin
79da2e3ebdSchin /* ======== command execution ========*/
80da2e3ebdSchin
81da2e3ebdSchin /*
82da2e3ebdSchin * print time <t> in h:m:s format with precision <p>
83da2e3ebdSchin */
l_time(Sfio_t * outfile,register clock_t t,int p)84da2e3ebdSchin static void l_time(Sfio_t *outfile,register clock_t t,int p)
85da2e3ebdSchin {
86da2e3ebdSchin register int min, sec, frac;
87da2e3ebdSchin register int hr;
88da2e3ebdSchin if(p)
89da2e3ebdSchin {
90da2e3ebdSchin frac = t%sh.lim.clk_tck;
91da2e3ebdSchin frac = (frac*100)/sh.lim.clk_tck;
92da2e3ebdSchin }
93da2e3ebdSchin t /= sh.lim.clk_tck;
94da2e3ebdSchin sec = t%60;
95da2e3ebdSchin t /= 60;
96da2e3ebdSchin min = t%60;
97da2e3ebdSchin if(hr=t/60)
98da2e3ebdSchin sfprintf(outfile,"%dh",hr);
99da2e3ebdSchin if(p)
100da2e3ebdSchin sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
101da2e3ebdSchin else
102da2e3ebdSchin sfprintf(outfile,"%dm%ds",min,sec);
103da2e3ebdSchin }
104da2e3ebdSchin
p_time(Shell_t * shp,Sfio_t * out,const char * format,clock_t * tm)1057c2fbfb3SApril Chin static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
106da2e3ebdSchin {
107da2e3ebdSchin int c,p,l,n,offset = staktell();
108da2e3ebdSchin const char *first;
109da2e3ebdSchin double d;
1107c2fbfb3SApril Chin Stk_t *stkp = shp->stk;
111da2e3ebdSchin for(first=format ; c= *format; format++)
112da2e3ebdSchin {
113da2e3ebdSchin if(c!='%')
114da2e3ebdSchin continue;
1157c2fbfb3SApril Chin sfwrite(stkp, first, format-first);
116da2e3ebdSchin n = l = 0;
117da2e3ebdSchin p = 3;
118da2e3ebdSchin if((c= *++format) == '%')
119da2e3ebdSchin {
120da2e3ebdSchin first = format;
121da2e3ebdSchin continue;
122da2e3ebdSchin }
123da2e3ebdSchin if(c>='0' && c <='9')
124da2e3ebdSchin {
125da2e3ebdSchin p = (c>'3')?3:(c-'0');
126da2e3ebdSchin c = *++format;
127da2e3ebdSchin }
128da2e3ebdSchin else if(c=='P')
129da2e3ebdSchin {
130da2e3ebdSchin if(d=tm[0])
131da2e3ebdSchin d = 100.*(((double)(tm[1]+tm[2]))/d);
132da2e3ebdSchin p = 2;
133da2e3ebdSchin goto skip;
134da2e3ebdSchin }
135da2e3ebdSchin if(c=='l')
136da2e3ebdSchin {
137da2e3ebdSchin l = 1;
138da2e3ebdSchin c = *++format;
139da2e3ebdSchin }
140da2e3ebdSchin if(c=='U')
141da2e3ebdSchin n = 1;
142da2e3ebdSchin else if(c=='S')
143da2e3ebdSchin n = 2;
144da2e3ebdSchin else if(c!='R')
145da2e3ebdSchin {
1467c2fbfb3SApril Chin stkseek(stkp,offset);
147da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
148da2e3ebdSchin return(0);
149da2e3ebdSchin }
150da2e3ebdSchin d = (double)tm[n]/sh.lim.clk_tck;
151da2e3ebdSchin skip:
152da2e3ebdSchin if(l)
1537c2fbfb3SApril Chin l_time(stkp, tm[n], p);
154da2e3ebdSchin else
1557c2fbfb3SApril Chin sfprintf(stkp,"%.*f",p, d);
156da2e3ebdSchin first = format+1;
157da2e3ebdSchin }
158da2e3ebdSchin if(format>first)
1597c2fbfb3SApril Chin sfwrite(stkp,first, format-first);
1607c2fbfb3SApril Chin sfputc(stkp,'\n');
1617c2fbfb3SApril Chin n = stktell(stkp)-offset;
1627c2fbfb3SApril Chin sfwrite(out,stkptr(stkp,offset),n);
1637c2fbfb3SApril Chin stkseek(stkp,offset);
164da2e3ebdSchin return(n);
165da2e3ebdSchin }
166da2e3ebdSchin
167da2e3ebdSchin #if SHOPT_OPTIMIZE
168da2e3ebdSchin /*
169da2e3ebdSchin * clear argument pointers that point into the stack
170da2e3ebdSchin */
171da2e3ebdSchin static int p_arg(struct argnod*,int);
172da2e3ebdSchin static int p_switch(struct regnod*);
p_comarg(register struct comnod * com)173da2e3ebdSchin static int p_comarg(register struct comnod *com)
174da2e3ebdSchin {
175da2e3ebdSchin Namval_t *np=com->comnamp;
176da2e3ebdSchin int n = p_arg(com->comset,ARG_ASSIGN);
177da2e3ebdSchin if(com->comarg && (com->comtyp&COMSCAN))
178da2e3ebdSchin n+= p_arg(com->comarg,0);
179da2e3ebdSchin if(com->comstate && np)
180da2e3ebdSchin {
181da2e3ebdSchin /* call builtin to cleanup state */
1827c2fbfb3SApril Chin Shbltin_t *bp = &sh.bltindata;
1837c2fbfb3SApril Chin void *save_ptr = bp->ptr;
1847c2fbfb3SApril Chin void *save_data = bp->data;
1857c2fbfb3SApril Chin bp->bnode = np;
1867c2fbfb3SApril Chin bp->vnode = com->comnamq;
1877c2fbfb3SApril Chin bp->ptr = nv_context(np);
1887c2fbfb3SApril Chin bp->data = com->comstate;
1897c2fbfb3SApril Chin bp->flags = SH_END_OPTIM;
1907c2fbfb3SApril Chin (*funptr(np))(0,(char**)0, bp);
1917c2fbfb3SApril Chin bp->ptr = save_ptr;
1927c2fbfb3SApril Chin bp->data = save_data;
193da2e3ebdSchin }
194da2e3ebdSchin com->comstate = 0;
195da2e3ebdSchin if(com->comarg && !np)
196da2e3ebdSchin n++;
197da2e3ebdSchin return(n);
198da2e3ebdSchin }
199da2e3ebdSchin
200da2e3ebdSchin extern void sh_optclear(Shell_t*, void*);
201da2e3ebdSchin
sh_tclear(register Shnode_t * t)202da2e3ebdSchin static int sh_tclear(register Shnode_t *t)
203da2e3ebdSchin {
204da2e3ebdSchin int n=0;
205da2e3ebdSchin if(!t)
206da2e3ebdSchin return(0);
207da2e3ebdSchin switch(t->tre.tretyp&COMMSK)
208da2e3ebdSchin {
209da2e3ebdSchin case TTIME:
210da2e3ebdSchin case TPAR:
211da2e3ebdSchin return(sh_tclear(t->par.partre));
212da2e3ebdSchin case TCOM:
213da2e3ebdSchin return(p_comarg((struct comnod*)t));
214da2e3ebdSchin case TSETIO:
215da2e3ebdSchin case TFORK:
216da2e3ebdSchin return(sh_tclear(t->fork.forktre));
217da2e3ebdSchin case TIF:
218da2e3ebdSchin n=sh_tclear(t->if_.iftre);
219da2e3ebdSchin n+=sh_tclear(t->if_.thtre);
220da2e3ebdSchin n+=sh_tclear(t->if_.eltre);
221da2e3ebdSchin return(n);
222da2e3ebdSchin case TWH:
223da2e3ebdSchin if(t->wh.whinc)
224da2e3ebdSchin n=sh_tclear((Shnode_t*)(t->wh.whinc));
225da2e3ebdSchin n+=sh_tclear(t->wh.whtre);
226da2e3ebdSchin n+=sh_tclear(t->wh.dotre);
227da2e3ebdSchin return(n);
228da2e3ebdSchin case TLST:
229da2e3ebdSchin case TAND:
230da2e3ebdSchin case TORF:
231da2e3ebdSchin case TFIL:
232da2e3ebdSchin n=sh_tclear(t->lst.lstlef);
233da2e3ebdSchin return(n+sh_tclear(t->lst.lstrit));
234da2e3ebdSchin case TARITH:
235da2e3ebdSchin return(p_arg(t->ar.arexpr,ARG_ARITH));
236da2e3ebdSchin case TFOR:
237da2e3ebdSchin n=sh_tclear(t->for_.fortre);
238da2e3ebdSchin return(n+sh_tclear((Shnode_t*)t->for_.forlst));
239da2e3ebdSchin case TSW:
240da2e3ebdSchin n=p_arg(t->sw.swarg,0);
241da2e3ebdSchin return(n+p_switch(t->sw.swlst));
242da2e3ebdSchin case TFUN:
243da2e3ebdSchin n=sh_tclear(t->funct.functtre);
244da2e3ebdSchin return(n+sh_tclear((Shnode_t*)t->funct.functargs));
245da2e3ebdSchin case TTST:
246da2e3ebdSchin if((t->tre.tretyp&TPAREN)==TPAREN)
247da2e3ebdSchin return(sh_tclear(t->lst.lstlef));
248da2e3ebdSchin else
249da2e3ebdSchin {
250da2e3ebdSchin n=p_arg(&(t->lst.lstlef->arg),0);
251da2e3ebdSchin if(t->tre.tretyp&TBINARY)
252da2e3ebdSchin n+=p_arg(&(t->lst.lstrit->arg),0);
253da2e3ebdSchin }
254da2e3ebdSchin }
255da2e3ebdSchin return(n);
256da2e3ebdSchin }
257da2e3ebdSchin
p_arg(register struct argnod * arg,int flag)258da2e3ebdSchin static int p_arg(register struct argnod *arg,int flag)
259da2e3ebdSchin {
260da2e3ebdSchin while(arg)
261da2e3ebdSchin {
262da2e3ebdSchin if(strlen(arg->argval) || (arg->argflag==ARG_RAW))
263da2e3ebdSchin arg->argchn.ap = 0;
264da2e3ebdSchin else if(flag==0)
265da2e3ebdSchin sh_tclear((Shnode_t*)arg->argchn.ap);
266da2e3ebdSchin else
267da2e3ebdSchin sh_tclear(((struct fornod*)arg->argchn.ap)->fortre);
268da2e3ebdSchin arg = arg->argnxt.ap;
269da2e3ebdSchin }
270da2e3ebdSchin return(0);
271da2e3ebdSchin }
272da2e3ebdSchin
p_switch(register struct regnod * reg)273da2e3ebdSchin static int p_switch(register struct regnod *reg)
274da2e3ebdSchin {
275da2e3ebdSchin int n=0;
276da2e3ebdSchin while(reg)
277da2e3ebdSchin {
278da2e3ebdSchin n+=p_arg(reg->regptr,0);
279da2e3ebdSchin n+=sh_tclear(reg->regcom);
280da2e3ebdSchin reg = reg->regnxt;
281da2e3ebdSchin }
282da2e3ebdSchin return(n);
283da2e3ebdSchin }
284da2e3ebdSchin # define OPTIMIZE_FLAG (ARG_OPTIMIZE)
285da2e3ebdSchin # define OPTIMIZE (flags&OPTIMIZE_FLAG)
286da2e3ebdSchin #else
287da2e3ebdSchin # define OPTIMIZE_FLAG (0)
288da2e3ebdSchin # define OPTIMIZE (0)
289da2e3ebdSchin # define sh_tclear(x)
290da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
291da2e3ebdSchin
out_pattern(Sfio_t * iop,register const char * cp,int n)292da2e3ebdSchin static void out_pattern(Sfio_t *iop, register const char *cp, int n)
293da2e3ebdSchin {
294da2e3ebdSchin register int c;
295da2e3ebdSchin do
296da2e3ebdSchin {
297da2e3ebdSchin switch(c= *cp)
298da2e3ebdSchin {
299da2e3ebdSchin case 0:
300da2e3ebdSchin if(n<0)
301da2e3ebdSchin return;
302da2e3ebdSchin c = n;
303da2e3ebdSchin break;
304da2e3ebdSchin case '\n':
305da2e3ebdSchin sfputr(iop,"$'\\n",'\'');
306da2e3ebdSchin continue;
307da2e3ebdSchin case '\\':
308da2e3ebdSchin if (!(c = *++cp))
309da2e3ebdSchin c = '\\';
310da2e3ebdSchin /*FALLTHROUGH*/
311da2e3ebdSchin case ' ':
312da2e3ebdSchin case '<': case '>': case ';':
313da2e3ebdSchin case '$': case '`': case '\t':
314da2e3ebdSchin sfputc(iop,'\\');
315da2e3ebdSchin break;
316da2e3ebdSchin }
317da2e3ebdSchin sfputc(iop,c);
318da2e3ebdSchin }
319da2e3ebdSchin while(*cp++);
320da2e3ebdSchin }
321da2e3ebdSchin
out_string(Sfio_t * iop,register const char * cp,int c,int quoted)322da2e3ebdSchin static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
323da2e3ebdSchin {
324da2e3ebdSchin if(quoted)
325da2e3ebdSchin {
3267c2fbfb3SApril Chin int n = stktell(stkstd);
327da2e3ebdSchin cp = sh_fmtq(cp);
328da2e3ebdSchin if(iop==stkstd && cp==stkptr(stkstd,n))
329da2e3ebdSchin {
330da2e3ebdSchin *stkptr(stkstd,stktell(stkstd)-1) = c;
331da2e3ebdSchin return;
332da2e3ebdSchin }
333da2e3ebdSchin }
334da2e3ebdSchin sfputr(iop,cp,c);
335da2e3ebdSchin }
336da2e3ebdSchin
337da2e3ebdSchin struct Level
338da2e3ebdSchin {
339da2e3ebdSchin Namfun_t hdr;
340da2e3ebdSchin short maxlevel;
341da2e3ebdSchin };
342da2e3ebdSchin
343da2e3ebdSchin /*
344da2e3ebdSchin * this is for a debugger but it hasn't been tested yet
345da2e3ebdSchin * if a debug script sets .sh.level it should set up the scope
346da2e3ebdSchin * as if you were executing in that level
347da2e3ebdSchin */
put_level(Namval_t * np,const char * val,int flags,Namfun_t * fp)348da2e3ebdSchin static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
349da2e3ebdSchin {
350da2e3ebdSchin Shscope_t *sp;
351da2e3ebdSchin struct Level *lp = (struct Level*)fp;
352da2e3ebdSchin int16_t level, oldlevel = (int16_t)nv_getnum(np);
353da2e3ebdSchin nv_putv(np,val,flags,fp);
3547c2fbfb3SApril Chin if(!val)
35534f9b3eeSRoland Mainz {
35634f9b3eeSRoland Mainz fp = nv_stack(np, NIL(Namfun_t*));
35734f9b3eeSRoland Mainz if(fp && !fp->nofree)
35834f9b3eeSRoland Mainz free((void*)fp);
3597c2fbfb3SApril Chin return;
36034f9b3eeSRoland Mainz }
361da2e3ebdSchin level = nv_getnum(np);
362da2e3ebdSchin if(level<0 || level > lp->maxlevel)
363da2e3ebdSchin {
3647c2fbfb3SApril Chin nv_putv(np, (char*)&oldlevel, NV_INT16, fp);
365da2e3ebdSchin /* perhaps this should be an error */
366da2e3ebdSchin return;
367da2e3ebdSchin }
368da2e3ebdSchin if(level==oldlevel)
369da2e3ebdSchin return;
370da2e3ebdSchin if(sp = sh_getscope(level,SEEK_SET))
371da2e3ebdSchin {
372da2e3ebdSchin sh_setscope(sp);
3737c2fbfb3SApril Chin error_info.id = sp->cmdname;
3747c2fbfb3SApril Chin
375da2e3ebdSchin }
376da2e3ebdSchin }
377da2e3ebdSchin
3787c2fbfb3SApril Chin static const Namdisc_t level_disc = { sizeof(struct Level), put_level };
3797c2fbfb3SApril Chin
init_level(int level)3807c2fbfb3SApril Chin static struct Level *init_level(int level)
3817c2fbfb3SApril Chin {
3827c2fbfb3SApril Chin struct Level *lp = newof(NiL,struct Level,1,0);
3837c2fbfb3SApril Chin lp->maxlevel = level;
3847c2fbfb3SApril Chin _nv_unset(SH_LEVELNOD,0);
3857c2fbfb3SApril Chin nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE);
3867c2fbfb3SApril Chin nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
3877c2fbfb3SApril Chin lp->hdr.disc = &level_disc;
3887c2fbfb3SApril Chin nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST);
3897c2fbfb3SApril Chin return(lp);
3907c2fbfb3SApril Chin }
391da2e3ebdSchin
392da2e3ebdSchin /*
393da2e3ebdSchin * write the current common on the stack and make it available as .sh.command
394da2e3ebdSchin */
sh_debug(Shell_t * shp,const char * trap,const char * name,const char * subscript,char * const argv[],int flags)3957c2fbfb3SApril Chin int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
396da2e3ebdSchin {
3977c2fbfb3SApril Chin Stk_t *stkp=shp->stk;
398da2e3ebdSchin struct sh_scoped savst;
399da2e3ebdSchin Namval_t *np = SH_COMMANDNOD;
4007c2fbfb3SApril Chin char *sav = stkptr(stkp,0);
4017c2fbfb3SApril Chin int n=4, offset=stktell(stkp);
402da2e3ebdSchin const char *cp = "+=( ";
403da2e3ebdSchin Sfio_t *iop = stkstd;
4047c2fbfb3SApril Chin short level;
4057c2fbfb3SApril Chin if(shp->indebug)
4067c2fbfb3SApril Chin return(0);
4077c2fbfb3SApril Chin shp->indebug = 1;
408da2e3ebdSchin if(name)
409da2e3ebdSchin {
410da2e3ebdSchin sfputr(iop,name,-1);
411da2e3ebdSchin if(subscript)
412da2e3ebdSchin {
413da2e3ebdSchin sfputc(iop,'[');
414da2e3ebdSchin out_string(iop,subscript,']',1);
415da2e3ebdSchin }
416da2e3ebdSchin if(!(flags&ARG_APPEND))
417da2e3ebdSchin cp+=1, n-=1;
418da2e3ebdSchin if(!(flags&ARG_ASSIGN))
419da2e3ebdSchin n -= 2;
420da2e3ebdSchin sfwrite(iop,cp,n);
421da2e3ebdSchin }
42234f9b3eeSRoland Mainz if(*argv && !(flags&ARG_RAW))
423da2e3ebdSchin out_string(iop, *argv++,' ', 0);
424da2e3ebdSchin n = (flags&ARG_ARITH);
425da2e3ebdSchin while(cp = *argv++)
426da2e3ebdSchin {
427da2e3ebdSchin if((flags&ARG_EXP) && argv[1]==0)
428da2e3ebdSchin out_pattern(iop, cp,' ');
429da2e3ebdSchin else
430da2e3ebdSchin out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
431da2e3ebdSchin }
432da2e3ebdSchin if(flags&ARG_ASSIGN)
433da2e3ebdSchin sfputc(iop,')');
434da2e3ebdSchin else if(iop==stkstd)
4357c2fbfb3SApril Chin *stkptr(stkp,stktell(stkp)-1) = 0;
4367c2fbfb3SApril Chin np->nvalue.cp = stkfreeze(stkp,1);
437da2e3ebdSchin /* now setup .sh.level variable */
4387c2fbfb3SApril Chin shp->st.lineno = error_info.line;
4397c2fbfb3SApril Chin level = shp->fn_depth+shp->dot_depth;
4407c2fbfb3SApril Chin if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
4417c2fbfb3SApril Chin init_level(level);
4427c2fbfb3SApril Chin else
443da2e3ebdSchin nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
4447c2fbfb3SApril Chin savst = shp->st;
4457c2fbfb3SApril Chin shp->st.trap[SH_DEBUGTRAP] = 0;
446da2e3ebdSchin n = sh_trap(trap,0);
447da2e3ebdSchin np->nvalue.cp = 0;
4487c2fbfb3SApril Chin shp->indebug = 0;
4497c2fbfb3SApril Chin if(shp->st.cmdname)
4507c2fbfb3SApril Chin error_info.id = shp->st.cmdname;
4517c2fbfb3SApril Chin nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
4527c2fbfb3SApril Chin nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
4537c2fbfb3SApril Chin shp->st = savst;
4547c2fbfb3SApril Chin if(sav != stkptr(stkp,0))
4557c2fbfb3SApril Chin stkset(stkp,sav,0);
456da2e3ebdSchin else
4577c2fbfb3SApril Chin stkseek(stkp,offset);
458da2e3ebdSchin return(n);
459da2e3ebdSchin }
460da2e3ebdSchin
461da2e3ebdSchin /*
462da2e3ebdSchin * Given stream <iop> compile and execute
463da2e3ebdSchin */
sh_eval(register Sfio_t * iop,int mode)464da2e3ebdSchin int sh_eval(register Sfio_t *iop, int mode)
465da2e3ebdSchin {
466da2e3ebdSchin register Shnode_t *t;
467da2e3ebdSchin Shell_t *shp = sh_getinterp();
468da2e3ebdSchin struct slnod *saveslp = shp->st.staklist;
469da2e3ebdSchin int jmpval;
470da2e3ebdSchin struct checkpt *pp = (struct checkpt*)shp->jmplist;
471da2e3ebdSchin struct checkpt buff;
472da2e3ebdSchin static Sfio_t *io_save;
4737c2fbfb3SApril Chin volatile int traceon=0, lineno=0;
47434f9b3eeSRoland Mainz int binscript=shp->binscript;
475da2e3ebdSchin io_save = iop; /* preserve correct value across longjmp */
47634f9b3eeSRoland Mainz shp->binscript = 0;
4777c2fbfb3SApril Chin #define SH_TOPFUN 0x8000 /* this is a temporary tksh hack */
4787c2fbfb3SApril Chin if (mode & SH_TOPFUN)
4797c2fbfb3SApril Chin {
4807c2fbfb3SApril Chin mode ^= SH_TOPFUN;
4817c2fbfb3SApril Chin shp->fn_reset = 1;
4827c2fbfb3SApril Chin }
483da2e3ebdSchin sh_pushcontext(&buff,SH_JMPEVAL);
484da2e3ebdSchin buff.olist = pp->olist;
485da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
48634f9b3eeSRoland Mainz while(jmpval==0)
487da2e3ebdSchin {
4887c2fbfb3SApril Chin if(mode&SH_READEVAL)
4897c2fbfb3SApril Chin {
4907c2fbfb3SApril Chin lineno = shp->inlineno;
4917c2fbfb3SApril Chin if(traceon=sh_isoption(SH_XTRACE))
4927c2fbfb3SApril Chin sh_offoption(SH_XTRACE);
4937c2fbfb3SApril Chin }
49434f9b3eeSRoland Mainz t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
49534f9b3eeSRoland Mainz if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0))
49634f9b3eeSRoland Mainz {
49734f9b3eeSRoland Mainz if(!(mode&SH_READEVAL))
498da2e3ebdSchin sfclose(iop);
499da2e3ebdSchin io_save = 0;
50034f9b3eeSRoland Mainz mode &= ~SH_FUNEVAL;
50134f9b3eeSRoland Mainz }
50234f9b3eeSRoland Mainz mode &= ~SH_READEVAL;
503da2e3ebdSchin if(!sh_isoption(SH_VERBOSE))
504da2e3ebdSchin sh_offstate(SH_VERBOSE);
50534f9b3eeSRoland Mainz if((mode&~SH_FUNEVAL) && shp->hist_ptr)
506da2e3ebdSchin {
507da2e3ebdSchin hist_flush(shp->hist_ptr);
508da2e3ebdSchin mode = sh_state(SH_INTERACTIVE);
509da2e3ebdSchin }
51034f9b3eeSRoland Mainz sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
51134f9b3eeSRoland Mainz if(!(mode&SH_FUNEVAL))
51234f9b3eeSRoland Mainz break;
513da2e3ebdSchin }
514da2e3ebdSchin sh_popcontext(&buff);
51534f9b3eeSRoland Mainz shp->binscript = binscript;
5167c2fbfb3SApril Chin if(traceon)
5177c2fbfb3SApril Chin sh_onoption(SH_XTRACE);
5187c2fbfb3SApril Chin if(lineno)
5197c2fbfb3SApril Chin shp->inlineno = lineno;
520da2e3ebdSchin if(io_save)
521da2e3ebdSchin sfclose(io_save);
5227c2fbfb3SApril Chin sh_freeup(shp);
523da2e3ebdSchin shp->st.staklist = saveslp;
5247c2fbfb3SApril Chin shp->fn_reset = 0;
525da2e3ebdSchin if(jmpval>SH_JMPEVAL)
526da2e3ebdSchin siglongjmp(*shp->jmplist,jmpval);
5277c2fbfb3SApril Chin return(shp->exitval);
528da2e3ebdSchin }
529da2e3ebdSchin
530da2e3ebdSchin #if SHOPT_FASTPIPE
pipe_exec(Shell_t * shp,int pv[],Shnode_t * t,int errorflg)5317c2fbfb3SApril Chin static int pipe_exec(Shell_t* shp,int pv[], Shnode_t *t, int errorflg)
532da2e3ebdSchin {
533da2e3ebdSchin struct checkpt buff;
534da2e3ebdSchin register Shnode_t *tchild = t->fork.forktre;
535da2e3ebdSchin Namval_t *np;
5367c2fbfb3SApril Chin int jmpval;
5377c2fbfb3SApril Chin volatile Sfio_t *iop;
5387c2fbfb3SApril Chin volatile int r;
539da2e3ebdSchin if((tchild->tre.tretyp&COMMSK)!=TCOM || !(np=(Namval_t*)(tchild->com.comnamp)))
540da2e3ebdSchin {
541da2e3ebdSchin sh_pipe(pv);
542da2e3ebdSchin return(sh_exec(t,errorflg));
543da2e3ebdSchin }
5447c2fbfb3SApril Chin pv[0] = shp->lim.open_max;
5457c2fbfb3SApril Chin shp->fdstatus[pv[0]] = IOREAD|IODUP|IOSEEK;
5467c2fbfb3SApril Chin pv[1] = shp->lim.open_max+1;
5477c2fbfb3SApril Chin shp->fdstatus[pv[1]] = IOWRITE|IOSEEK;
548da2e3ebdSchin iop = sftmp(IOBSIZE+1);
5497c2fbfb3SApril Chin shp->sftable[shp->lim.open_max+1] = iop;
550da2e3ebdSchin sh_pushcontext(&buff,SH_JMPIO);
551da2e3ebdSchin if(t->tre.tretyp&FPIN)
5527c2fbfb3SApril Chin sh_iosave(shp,0,shp->topfd,(char*)0);
5537c2fbfb3SApril Chin sh_iosave(shp,1,shp->topfd,(char*)0);
554da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
555da2e3ebdSchin if(jmpval==0)
556da2e3ebdSchin {
557da2e3ebdSchin if(t->tre.tretyp&FPIN)
5587c2fbfb3SApril Chin sh_iorenumber(shp,shp->inpipe[0],0);
5597c2fbfb3SApril Chin sh_iorenumber(shp,shp->lim.open_max+1,1);
560da2e3ebdSchin r = sh_exec(tchild,errorflg);
561da2e3ebdSchin if(sffileno(sfstdout)>=0)
562da2e3ebdSchin pv[0] = sfsetfd(sfstdout,10);
563da2e3ebdSchin iop = sfswap(sfstdout,0);
564da2e3ebdSchin }
565da2e3ebdSchin sh_popcontext(&buff);
5667c2fbfb3SApril Chin shp->sftable[pv[0]] = iop;
5677c2fbfb3SApril Chin shp->fdstatus[pv[0]] = IOREAD|IODUP|IOSEEK;
568da2e3ebdSchin sfset(iop,SF_WRITE,0);
569da2e3ebdSchin sfseek(iop,0L,SEEK_SET);
5707c2fbfb3SApril Chin sh_iorestore(shp,buff.topfd,jmpval);
571da2e3ebdSchin if(jmpval>SH_JMPIO)
5727c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
573da2e3ebdSchin return(r);
574da2e3ebdSchin }
575da2e3ebdSchin #endif /* SHOPT_FASTPIPE */
576da2e3ebdSchin
577da2e3ebdSchin /*
578da2e3ebdSchin * returns 1 when option -<c> is specified
579da2e3ebdSchin */
checkopt(char * argv[],int c)580da2e3ebdSchin static int checkopt(char *argv[], int c)
581da2e3ebdSchin {
582da2e3ebdSchin char *cp;
583da2e3ebdSchin while(cp = *++argv)
584da2e3ebdSchin {
585da2e3ebdSchin if(*cp=='+')
586da2e3ebdSchin continue;
587da2e3ebdSchin if(*cp!='-' || cp[1]=='-')
588da2e3ebdSchin break;
5897c2fbfb3SApril Chin if(strchr(++cp,c))
590da2e3ebdSchin return(1);
5917c2fbfb3SApril Chin if(*cp=='h' && cp[1]==0 && *++argv==0)
5927c2fbfb3SApril Chin break;
593da2e3ebdSchin }
594da2e3ebdSchin return(0);
595da2e3ebdSchin }
596da2e3ebdSchin
free_list(struct openlist * olist)597da2e3ebdSchin static void free_list(struct openlist *olist)
598da2e3ebdSchin {
599da2e3ebdSchin struct openlist *item,*next;
600da2e3ebdSchin for(item=olist;item;item=next)
601da2e3ebdSchin {
602da2e3ebdSchin next = item->next;
603da2e3ebdSchin free((void*)item);
604da2e3ebdSchin }
605da2e3ebdSchin }
606da2e3ebdSchin
6077c2fbfb3SApril Chin /*
6087c2fbfb3SApril Chin * set ${.sh.name} and ${.sh.subscript}
6097c2fbfb3SApril Chin * set _ to reference for ${.sh.name}[$.sh.subscript]
6107c2fbfb3SApril Chin */
set_instance(Shell_t * shp,Namval_t * nq,Namval_t * node,struct Namref * nr)611*3e14f97fSRoger A. Faulkner static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
6127c2fbfb3SApril Chin {
61334f9b3eeSRoland Mainz char *sp=0,*cp = nv_name(nq);
6147c2fbfb3SApril Chin Namarr_t *ap;
6157c2fbfb3SApril Chin memset(nr,0,sizeof(*nr));
6167c2fbfb3SApril Chin nr->np = nq;
6177c2fbfb3SApril Chin nr->root = sh.var_tree;
6187c2fbfb3SApril Chin nr->table = sh.last_table;
619*3e14f97fSRoger A. Faulkner shp->instance = 1;
62034f9b3eeSRoland Mainz if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
62134f9b3eeSRoland Mainz sp = strdup(sp);
622*3e14f97fSRoger A. Faulkner shp->instance = 0;
6237c2fbfb3SApril Chin if(sh.var_tree!=sh.var_base && !nv_open(cp,nr->root,NV_VARNAME|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))
6247c2fbfb3SApril Chin nr->root = sh.var_base;
6257c2fbfb3SApril Chin nv_putval(SH_NAMENOD, cp, NV_NOFREE);
6267c2fbfb3SApril Chin memcpy(node,L_ARGNOD,sizeof(*node));
6277c2fbfb3SApril Chin L_ARGNOD->nvalue.nrp = nr;
6287c2fbfb3SApril Chin L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
6297c2fbfb3SApril Chin L_ARGNOD->nvfun = 0;
6307c2fbfb3SApril Chin L_ARGNOD->nvenv = 0;
63134f9b3eeSRoland Mainz if(sp)
6327c2fbfb3SApril Chin {
63334f9b3eeSRoland Mainz nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE);
6347c2fbfb3SApril Chin return(ap->nelem&ARRAY_SCAN);
6357c2fbfb3SApril Chin }
6367c2fbfb3SApril Chin return(0);
6377c2fbfb3SApril Chin }
6387c2fbfb3SApril Chin
unset_instance(Namval_t * nq,Namval_t * node,struct Namref * nr,long mode)6397c2fbfb3SApril Chin static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
6407c2fbfb3SApril Chin {
6417c2fbfb3SApril Chin L_ARGNOD->nvalue.nrp = node->nvalue.nrp;
6427c2fbfb3SApril Chin L_ARGNOD->nvflag = node->nvflag;
6437c2fbfb3SApril Chin L_ARGNOD->nvfun = node->nvfun;
6447c2fbfb3SApril Chin if(nr->sub)
6457c2fbfb3SApril Chin {
6467c2fbfb3SApril Chin nv_putsub(nq, nr->sub, mode);
6477c2fbfb3SApril Chin free((void*)nr->sub);
6487c2fbfb3SApril Chin }
6497c2fbfb3SApril Chin nv_unset(SH_NAMENOD);
6507c2fbfb3SApril Chin nv_unset(SH_SUBSCRNOD);
6517c2fbfb3SApril Chin }
652da2e3ebdSchin
sh_exec(register const Shnode_t * t,int flags)653da2e3ebdSchin int sh_exec(register const Shnode_t *t, int flags)
654da2e3ebdSchin {
6557c2fbfb3SApril Chin register Shell_t *shp = &sh;
6567c2fbfb3SApril Chin Stk_t *stkp = shp->stk;
657da2e3ebdSchin sh_sigcheck();
6587c2fbfb3SApril Chin if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
659da2e3ebdSchin {
660da2e3ebdSchin register int type = flags;
661da2e3ebdSchin register char *com0 = 0;
662da2e3ebdSchin int errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE;
663da2e3ebdSchin int execflg = (type&sh_state(SH_NOFORK));
66434f9b3eeSRoland Mainz int execflg2 = (type&sh_state(SH_FORKED));
665da2e3ebdSchin int mainloop = (type&sh_state(SH_INTERACTIVE));
6667c2fbfb3SApril Chin #if SHOPT_AMP || SHOPT_SPAWN
667da2e3ebdSchin int ntflag = (type&sh_state(SH_NTFORK));
66834f9b3eeSRoland Mainz #else
66934f9b3eeSRoland Mainz int ntflag = 0;
670da2e3ebdSchin #endif
6717c2fbfb3SApril Chin int topfd = shp->topfd;
6727c2fbfb3SApril Chin char *sav=stkptr(stkp,0);
6737c2fbfb3SApril Chin char *cp=0, **com=0, *comn;
674da2e3ebdSchin int argn;
675da2e3ebdSchin int skipexitset = 0;
676da2e3ebdSchin int was_interactive = 0;
677da2e3ebdSchin int was_errexit = sh_isstate(SH_ERREXIT);
678da2e3ebdSchin int was_monitor = sh_isstate(SH_MONITOR);
679da2e3ebdSchin int echeck = 0;
680da2e3ebdSchin if(flags&sh_state(SH_INTERACTIVE))
681da2e3ebdSchin {
68234f9b3eeSRoland Mainz if(pipejob==2)
68334f9b3eeSRoland Mainz job_unlock();
684da2e3ebdSchin pipejob = 0;
685da2e3ebdSchin job.curpgid = 0;
686da2e3ebdSchin flags &= ~sh_state(SH_INTERACTIVE);
687da2e3ebdSchin }
688da2e3ebdSchin sh_offstate(SH_ERREXIT);
689da2e3ebdSchin sh_offstate(SH_DEFPATH);
690da2e3ebdSchin if(was_errexit&flags)
691da2e3ebdSchin sh_onstate(SH_ERREXIT);
692da2e3ebdSchin if(was_monitor&flags)
693da2e3ebdSchin sh_onstate(SH_MONITOR);
694da2e3ebdSchin type = t->tre.tretyp;
6957c2fbfb3SApril Chin if(!shp->intrap)
6967c2fbfb3SApril Chin shp->oldexit=shp->exitval;
6977c2fbfb3SApril Chin shp->exitval=0;
6987c2fbfb3SApril Chin shp->lastsig = 0;
6997c2fbfb3SApril Chin shp->lastpath = 0;
700da2e3ebdSchin switch(type&COMMSK)
701da2e3ebdSchin {
702da2e3ebdSchin case TCOM:
703da2e3ebdSchin {
704da2e3ebdSchin register struct argnod *argp;
705da2e3ebdSchin char *trap;
706da2e3ebdSchin Namval_t *np, *nq, *last_table;
707da2e3ebdSchin struct ionod *io;
7087c2fbfb3SApril Chin int command=0, flgs=NV_ASSIGN;
7097c2fbfb3SApril Chin shp->bltindata.invariant = type>>(COMBITS+2);
7107c2fbfb3SApril Chin type &= (COMMSK|COMSCAN);
7117c2fbfb3SApril Chin sh_stats(STAT_SCMDS);
7127c2fbfb3SApril Chin error_info.line = t->com.comline-shp->st.firstline;
7137c2fbfb3SApril Chin com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE);
714da2e3ebdSchin echeck = 1;
715da2e3ebdSchin if(t->tre.tretyp&COMSCAN)
716da2e3ebdSchin {
717da2e3ebdSchin argp = t->com.comarg;
718da2e3ebdSchin if(argp && *com && !(argp->argflag&ARG_RAW))
719da2e3ebdSchin sh_sigcheck();
720da2e3ebdSchin }
721da2e3ebdSchin np = (Namval_t*)(t->com.comnamp);
722da2e3ebdSchin nq = (Namval_t*)(t->com.comnamq);
723da2e3ebdSchin com0 = com[0];
7247c2fbfb3SApril Chin shp->xargexit = 0;
725da2e3ebdSchin while(np==SYSCOMMAND)
726da2e3ebdSchin {
7277c2fbfb3SApril Chin register int n = b_command(0,com,&shp->bltindata);
728da2e3ebdSchin if(n==0)
729da2e3ebdSchin break;
730da2e3ebdSchin command += n;
731da2e3ebdSchin np = 0;
732da2e3ebdSchin if(!(com0= *(com+=n)))
733da2e3ebdSchin break;
7347c2fbfb3SApril Chin np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
735da2e3ebdSchin }
7367c2fbfb3SApril Chin if(shp->xargexit)
737da2e3ebdSchin {
7387c2fbfb3SApril Chin shp->xargmin -= command;
7397c2fbfb3SApril Chin shp->xargmax -= command;
740da2e3ebdSchin }
741da2e3ebdSchin else
7427c2fbfb3SApril Chin shp->xargmin = 0;
743da2e3ebdSchin argn -= command;
744da2e3ebdSchin if(!command && np && is_abuiltin(np))
7457c2fbfb3SApril Chin np = dtsearch(shp->fun_tree,np);
7467c2fbfb3SApril Chin if(com0)
747da2e3ebdSchin {
7487c2fbfb3SApril Chin if(!np && !strchr(com0,'/'))
7497c2fbfb3SApril Chin {
7507c2fbfb3SApril Chin Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
751da2e3ebdSchin np = nv_bfsearch(com0, root, &nq, &cp);
752da2e3ebdSchin #if SHOPT_NAMESPACE
7537c2fbfb3SApril Chin if(shp->namespace && !nq && !cp)
754da2e3ebdSchin {
7557c2fbfb3SApril Chin int offset = stktell(stkp);
7567c2fbfb3SApril Chin sfputr(stkp,nv_name(shp->namespace),-1);
7577c2fbfb3SApril Chin sfputc(stkp,'.');
7587c2fbfb3SApril Chin sfputr(stkp,com0,0);
7597c2fbfb3SApril Chin stkseek(stkp,offset);
7607c2fbfb3SApril Chin np = nv_bfsearch(stkptr(stkp,offset), root, &nq, &cp);
761da2e3ebdSchin }
762da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
763da2e3ebdSchin }
7647c2fbfb3SApril Chin comn = com[argn-1];
7657c2fbfb3SApril Chin }
766da2e3ebdSchin io = t->tre.treio;
7677c2fbfb3SApril Chin if(shp->envlist = argp = t->com.comset)
768da2e3ebdSchin {
7697c2fbfb3SApril Chin if(argn==0 || (np && nv_isattr(np,BLT_SPC)))
770da2e3ebdSchin {
77134f9b3eeSRoland Mainz Namval_t *tp=0;
7727c2fbfb3SApril Chin if(argn)
7737c2fbfb3SApril Chin {
7747c2fbfb3SApril Chin if(checkopt(com,'A'))
7757c2fbfb3SApril Chin flgs |= NV_ARRAY;
7767c2fbfb3SApril Chin else if(checkopt(com,'a'))
7777c2fbfb3SApril Chin flgs |= NV_IARRAY;
7787c2fbfb3SApril Chin }
779da2e3ebdSchin #if SHOPT_BASH
780da2e3ebdSchin if(np==SYSLOCAL)
781da2e3ebdSchin {
782da2e3ebdSchin if(!nv_getval(SH_FUNNAMENOD))
783da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
7847c2fbfb3SApril Chin if(!shp->st.var_local)
785da2e3ebdSchin {
7867c2fbfb3SApril Chin sh_scope(shp,(struct argnod*)0,0);
7877c2fbfb3SApril Chin shp->st.var_local = shp->var_tree;
788da2e3ebdSchin }
789da2e3ebdSchin
790da2e3ebdSchin }
791da2e3ebdSchin if(np==SYSTYPESET || np==SYSLOCAL)
792da2e3ebdSchin #else
7937c2fbfb3SApril Chin if(np==SYSTYPESET || (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
794da2e3ebdSchin #endif
795da2e3ebdSchin {
7967c2fbfb3SApril Chin if(np!=SYSTYPESET)
79734f9b3eeSRoland Mainz {
7987c2fbfb3SApril Chin shp->typeinit = np;
79934f9b3eeSRoland Mainz tp = nv_type(np);
80034f9b3eeSRoland Mainz }
8017c2fbfb3SApril Chin if(checkopt(com,'C'))
8027c2fbfb3SApril Chin flgs |= NV_COMVAR;
8037c2fbfb3SApril Chin if(checkopt(com,'S'))
8047c2fbfb3SApril Chin flgs |= NV_STATIC;
805da2e3ebdSchin if(checkopt(com,'n'))
806da2e3ebdSchin flgs |= NV_NOREF;
80734f9b3eeSRoland Mainz else if(!shp->typeinit && (checkopt(com,'L') || checkopt(com,'R') || checkopt(com,'Z')))
80834f9b3eeSRoland Mainz flgs |= NV_UNJUST;
809da2e3ebdSchin #if SHOPT_TYPEDEF
8107c2fbfb3SApril Chin else if(argn>=3 && checkopt(com,'T'))
811da2e3ebdSchin {
8127c2fbfb3SApril Chin shp->prefix = NV_CLASS;
813da2e3ebdSchin flgs |= NV_TYPE;
814da2e3ebdSchin
815da2e3ebdSchin }
816da2e3ebdSchin #endif /* SHOPT_TYPEDEF */
8177c2fbfb3SApril Chin if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
818da2e3ebdSchin flgs |= NV_NOSCOPE;
819da2e3ebdSchin }
820da2e3ebdSchin else if(np==SYSEXPORT)
821da2e3ebdSchin flgs |= NV_EXPORT;
8227c2fbfb3SApril Chin if(flgs&(NV_EXPORT|NV_NOREF))
8237c2fbfb3SApril Chin flgs |= NV_IDENT;
8247c2fbfb3SApril Chin else
8257c2fbfb3SApril Chin flgs |= NV_VARNAME;
826da2e3ebdSchin #if 0
827da2e3ebdSchin if(OPTIMIZE)
828da2e3ebdSchin flgs |= NV_TAGGED;
829da2e3ebdSchin #endif
83034f9b3eeSRoland Mainz nv_setlist(argp,flgs,tp);
8317c2fbfb3SApril Chin if(np==shp->typeinit)
8327c2fbfb3SApril Chin shp->typeinit = 0;
8337c2fbfb3SApril Chin shp->envlist = argp;
834da2e3ebdSchin argp = NULL;
835da2e3ebdSchin }
836da2e3ebdSchin }
8377c2fbfb3SApril Chin last_table = shp->last_table;
8387c2fbfb3SApril Chin shp->last_table = 0;
839da2e3ebdSchin if((io||argn))
840da2e3ebdSchin {
8417c2fbfb3SApril Chin Shbltin_t *bp=0;
842da2e3ebdSchin static char *argv[1];
8437c2fbfb3SApril Chin int tflags = 1;
8447c2fbfb3SApril Chin if(np && nv_isattr(np,BLT_DCL))
8457c2fbfb3SApril Chin tflags |= 2;
846da2e3ebdSchin if(argn==0)
847da2e3ebdSchin {
848da2e3ebdSchin /* fake 'true' built-in */
849da2e3ebdSchin np = SYSTRUE;
850da2e3ebdSchin *argv = nv_name(np);
851da2e3ebdSchin com = argv;
852da2e3ebdSchin }
853da2e3ebdSchin /* set +x doesn't echo */
854da2e3ebdSchin else if((np!=SYSSET) && sh_isoption(SH_XTRACE))
8557c2fbfb3SApril Chin sh_trace(com-command,tflags);
856da2e3ebdSchin else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
857da2e3ebdSchin {
858da2e3ebdSchin int ison = sh_isoption(SH_XTRACE);
859da2e3ebdSchin if(!ison)
860da2e3ebdSchin sh_onoption(SH_XTRACE);
8617c2fbfb3SApril Chin sh_trace(com-command,tflags);
862da2e3ebdSchin if(io)
8637c2fbfb3SApril Chin sh_redirect(shp,io,SH_SHOWME);
864da2e3ebdSchin if(!ison)
865da2e3ebdSchin sh_offoption(SH_XTRACE);
866da2e3ebdSchin break;
867da2e3ebdSchin }
8687c2fbfb3SApril Chin if(trap=shp->st.trap[SH_DEBUGTRAP])
8697c2fbfb3SApril Chin {
8707c2fbfb3SApril Chin int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
8717c2fbfb3SApril Chin if(n==255 && shp->fn_depth+shp->dot_depth)
8727c2fbfb3SApril Chin {
8737c2fbfb3SApril Chin np = SYSRETURN;
8747c2fbfb3SApril Chin argn = 1;
8757c2fbfb3SApril Chin com[0] = np->nvname;
8767c2fbfb3SApril Chin com[1] = 0;
8777c2fbfb3SApril Chin io = 0;
8787c2fbfb3SApril Chin argp = 0;
8797c2fbfb3SApril Chin }
8807c2fbfb3SApril Chin else if(n==2)
8817c2fbfb3SApril Chin break;
8827c2fbfb3SApril Chin }
883da2e3ebdSchin if(io)
8847c2fbfb3SApril Chin sfsync(shp->outpool);
8857c2fbfb3SApril Chin shp->lastpath = 0;
886da2e3ebdSchin if(!np && !strchr(com0,'/'))
887da2e3ebdSchin {
8887c2fbfb3SApril Chin if(path_search(com0,NIL(Pathcomp_t**),1))
8897c2fbfb3SApril Chin {
8907c2fbfb3SApril Chin error_info.line = t->com.comline-shp->st.firstline;
8917c2fbfb3SApril Chin if((np=nv_search(com0,shp->fun_tree,0)) && !np->nvalue.ip)
8927c2fbfb3SApril Chin {
8937c2fbfb3SApril Chin Namval_t *mp=nv_search(com0,shp->bltin_tree,0);
8947c2fbfb3SApril Chin if(mp)
8957c2fbfb3SApril Chin np = mp;
8967c2fbfb3SApril Chin }
8977c2fbfb3SApril Chin }
898da2e3ebdSchin else
899da2e3ebdSchin {
9007c2fbfb3SApril Chin if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
9017c2fbfb3SApril Chin np=nv_search(nv_getval(np),shp->bltin_tree,0);
902da2e3ebdSchin else
903da2e3ebdSchin np = 0;
904da2e3ebdSchin }
905da2e3ebdSchin }
90634f9b3eeSRoland Mainz if(np && pipejob==2)
90734f9b3eeSRoland Mainz {
90834f9b3eeSRoland Mainz job_unlock();
90934f9b3eeSRoland Mainz pipejob = 1;
91034f9b3eeSRoland Mainz }
911da2e3ebdSchin /* check for builtins */
912da2e3ebdSchin if(np && is_abuiltin(np))
913da2e3ebdSchin {
9147c2fbfb3SApril Chin volatile int scope=0, share=0;
9157c2fbfb3SApril Chin volatile void *save_ptr;
9167c2fbfb3SApril Chin volatile void *save_data;
9177c2fbfb3SApril Chin int jmpval, save_prompt;
91834f9b3eeSRoland Mainz int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
919da2e3ebdSchin struct checkpt buff;
920da2e3ebdSchin unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
921da2e3ebdSchin struct stat statb;
9227c2fbfb3SApril Chin bp = &shp->bltindata;
9237c2fbfb3SApril Chin save_ptr = bp->ptr;
9247c2fbfb3SApril Chin save_data = bp->data;
9257c2fbfb3SApril Chin memset(&statb, 0, sizeof(struct stat));
926da2e3ebdSchin if(strchr(nv_name(np),'/'))
927da2e3ebdSchin {
928da2e3ebdSchin /*
929da2e3ebdSchin * disable editors for built-in
930da2e3ebdSchin * versions of commands on PATH
931da2e3ebdSchin */
932da2e3ebdSchin was_vi = sh_isoption(SH_VI);
933da2e3ebdSchin was_emacs = sh_isoption(SH_EMACS);
934da2e3ebdSchin was_gmacs = sh_isoption(SH_GMACS);
935da2e3ebdSchin sh_offoption(SH_VI);
936da2e3ebdSchin sh_offoption(SH_EMACS);
937da2e3ebdSchin sh_offoption(SH_GMACS);
938da2e3ebdSchin }
93934f9b3eeSRoland Mainz if(execflg)
94034f9b3eeSRoland Mainz sh_onstate(SH_NOFORK);
941da2e3ebdSchin sh_pushcontext(&buff,SH_JMPCMD);
942da2e3ebdSchin jmpval = sigsetjmp(buff.buff,1);
943da2e3ebdSchin if(jmpval == 0)
944da2e3ebdSchin {
945da2e3ebdSchin if(!(nv_isattr(np,BLT_ENV)))
946da2e3ebdSchin error_info.flags |= ERROR_SILENT;
947da2e3ebdSchin errorpush(&buff.err,0);
948da2e3ebdSchin if(io)
949da2e3ebdSchin {
950da2e3ebdSchin struct openlist *item;
951da2e3ebdSchin if(np==SYSLOGIN)
952da2e3ebdSchin type=1;
953da2e3ebdSchin else if(np==SYSEXEC)
954da2e3ebdSchin type=1+!com[1];
955da2e3ebdSchin else
9567c2fbfb3SApril Chin type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
9577c2fbfb3SApril Chin sh_redirect(shp,io,type);
958da2e3ebdSchin for(item=buff.olist;item;item=item->next)
959da2e3ebdSchin item->strm=0;
960da2e3ebdSchin }
961da2e3ebdSchin if(!(nv_isattr(np,BLT_ENV)))
962da2e3ebdSchin {
9637c2fbfb3SApril Chin if(bp->nosfio)
9647c2fbfb3SApril Chin {
9657c2fbfb3SApril Chin if(!shp->pwd)
966da2e3ebdSchin path_pwd(0);
9677c2fbfb3SApril Chin if(shp->pwd)
968da2e3ebdSchin stat(".",&statb);
9697c2fbfb3SApril Chin }
9707c2fbfb3SApril Chin sfsync(NULL);
971da2e3ebdSchin share = sfset(sfstdin,SF_SHARE,0);
972da2e3ebdSchin sh_onstate(SH_STOPOK);
973da2e3ebdSchin sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
974da2e3ebdSchin sfset(sfstderr,SF_LINE,1);
9757c2fbfb3SApril Chin save_prompt = shp->nextprompt;
9767c2fbfb3SApril Chin shp->nextprompt = 0;
977da2e3ebdSchin }
978da2e3ebdSchin if(argp)
979da2e3ebdSchin {
980da2e3ebdSchin scope++;
9817c2fbfb3SApril Chin sh_scope(shp,argp,0);
982da2e3ebdSchin }
983da2e3ebdSchin opt_info.index = opt_info.offset = 0;
984da2e3ebdSchin opt_info.disc = 0;
985da2e3ebdSchin error_info.id = *com;
9867c2fbfb3SApril Chin if(argn)
9877c2fbfb3SApril Chin shp->exitval = 0;
9887c2fbfb3SApril Chin shp->bltinfun = funptr(np);
9897c2fbfb3SApril Chin bp->bnode = np;
9907c2fbfb3SApril Chin bp->vnode = nq;
9917c2fbfb3SApril Chin bp->ptr = nv_context(np);
9927c2fbfb3SApril Chin bp->data = t->com.comstate;
9937c2fbfb3SApril Chin bp->sigset = 0;
9947c2fbfb3SApril Chin bp->notify = 0;
9957c2fbfb3SApril Chin bp->flags = (OPTIMIZE!=0);
9967c2fbfb3SApril Chin if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
9977c2fbfb3SApril Chin sh_subtmpfile(0);
9987c2fbfb3SApril Chin if(execflg && !shp->subshell &&
9997c2fbfb3SApril Chin !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
1000da2e3ebdSchin {
1001da2e3ebdSchin /* do close-on-exec */
1002da2e3ebdSchin int fd;
10037c2fbfb3SApril Chin for(fd=0; fd < shp->lim.open_max; fd++)
10047c2fbfb3SApril Chin if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd)
1005da2e3ebdSchin sh_close(fd);
1006da2e3ebdSchin }
10077c2fbfb3SApril Chin if(argn)
10087c2fbfb3SApril Chin shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
1009da2e3ebdSchin if(error_info.flags&ERROR_INTERACTIVE)
1010da2e3ebdSchin tty_check(ERRIO);
10117c2fbfb3SApril Chin ((Shnode_t*)t)->com.comstate = shp->bltindata.data;
10127c2fbfb3SApril Chin bp->data = (void*)save_data;
10137c2fbfb3SApril Chin if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
10147c2fbfb3SApril Chin shp->exitval &= SH_EXITMASK;
1015da2e3ebdSchin }
1016da2e3ebdSchin else
1017da2e3ebdSchin {
1018da2e3ebdSchin struct openlist *item;
1019da2e3ebdSchin for(item=buff.olist;item;item=item->next)
1020da2e3ebdSchin {
1021da2e3ebdSchin if(item->strm)
1022da2e3ebdSchin {
1023da2e3ebdSchin sfclrlock(item->strm);
10247c2fbfb3SApril Chin if(shp->hist_ptr && item->strm == shp->hist_ptr->histfp)
10257c2fbfb3SApril Chin hist_close(shp->hist_ptr);
1026da2e3ebdSchin else
1027da2e3ebdSchin sfclose(item->strm);
1028da2e3ebdSchin }
1029da2e3ebdSchin }
10307c2fbfb3SApril Chin if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
10317c2fbfb3SApril Chin (*shp->bltinfun)(-2,com,(void*)bp);
1032da2e3ebdSchin /* failure on special built-ins fatal */
1033da2e3ebdSchin if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command))
1034da2e3ebdSchin jmpval=0;
1035da2e3ebdSchin }
10367c2fbfb3SApril Chin if(bp && bp->ptr!= nv_context(np))
10377c2fbfb3SApril Chin np->nvfun = (Namfun_t*)bp->ptr;
103834f9b3eeSRoland Mainz if(execflg && !was_nofork)
103934f9b3eeSRoland Mainz sh_offstate(SH_NOFORK);
1040da2e3ebdSchin if(!(nv_isattr(np,BLT_ENV)))
1041da2e3ebdSchin {
10427c2fbfb3SApril Chin if(bp->nosfio && shp->pwd)
1043da2e3ebdSchin {
1044da2e3ebdSchin struct stat stata;
1045da2e3ebdSchin stat(".",&stata);
1046da2e3ebdSchin /* restore directory changed */
1047da2e3ebdSchin if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
10487c2fbfb3SApril Chin chdir(shp->pwd);
1049da2e3ebdSchin }
1050da2e3ebdSchin sh_offstate(SH_STOPOK);
1051da2e3ebdSchin if(share&SF_SHARE)
1052da2e3ebdSchin sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
1053da2e3ebdSchin sfset(sfstderr,SF_LINE,0);
10547c2fbfb3SApril Chin sfpool(sfstderr,shp->outpool,SF_WRITE);
1055da2e3ebdSchin sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE);
10567c2fbfb3SApril Chin shp->nextprompt = save_prompt;
1057da2e3ebdSchin }
1058da2e3ebdSchin sh_popcontext(&buff);
1059da2e3ebdSchin errorpop(&buff.err);
106034f9b3eeSRoland Mainz error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
10617c2fbfb3SApril Chin shp->bltinfun = 0;
1062da2e3ebdSchin if(buff.olist)
1063da2e3ebdSchin free_list(buff.olist);
1064da2e3ebdSchin if(was_vi)
1065da2e3ebdSchin sh_onoption(SH_VI);
1066da2e3ebdSchin else if(was_emacs)
1067da2e3ebdSchin sh_onoption(SH_EMACS);
1068da2e3ebdSchin else if(was_gmacs)
1069da2e3ebdSchin sh_onoption(SH_GMACS);
1070da2e3ebdSchin if(scope)
10717c2fbfb3SApril Chin sh_unscope(shp);
10727c2fbfb3SApril Chin bp->ptr = (void*)save_ptr;
10737c2fbfb3SApril Chin bp->data = (void*)save_data;
1074da2e3ebdSchin /* don't restore for subshell exec */
10757c2fbfb3SApril Chin if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
10767c2fbfb3SApril Chin sh_iorestore(shp,topfd,jmpval);
1077da2e3ebdSchin if(jmpval)
10787c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
10797c2fbfb3SApril Chin #if 0
10807c2fbfb3SApril Chin if(flgs&NV_STATIC)
10817c2fbfb3SApril Chin ((Shnode_t*)t)->com.comset = 0;
10827c2fbfb3SApril Chin #endif
10837c2fbfb3SApril Chin if(shp->exitval >=0)
1084da2e3ebdSchin goto setexit;
1085da2e3ebdSchin np = 0;
1086da2e3ebdSchin type=0;
1087da2e3ebdSchin }
1088da2e3ebdSchin /* check for functions */
1089da2e3ebdSchin if(!command && np && nv_isattr(np,NV_FUNCTION))
1090da2e3ebdSchin {
10917c2fbfb3SApril Chin volatile int indx;
10927c2fbfb3SApril Chin int jmpval=0;
1093da2e3ebdSchin struct checkpt buff;
1094da2e3ebdSchin Namval_t node;
10957c2fbfb3SApril Chin struct Namref nr;
10967c2fbfb3SApril Chin long mode;
1097da2e3ebdSchin register struct slnod *slp;
1098da2e3ebdSchin if(!np->nvalue.ip)
1099da2e3ebdSchin {
11007c2fbfb3SApril Chin indx = path_search(com0,NIL(Pathcomp_t**),0);
1101da2e3ebdSchin if(indx==1)
11027c2fbfb3SApril Chin np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE);
11037c2fbfb3SApril Chin
1104da2e3ebdSchin if(!np->nvalue.ip)
1105da2e3ebdSchin {
1106da2e3ebdSchin if(indx==1)
1107da2e3ebdSchin {
1108da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(0),e_defined,com0);
11097c2fbfb3SApril Chin shp->exitval = ERROR_NOEXEC;
1110da2e3ebdSchin }
1111da2e3ebdSchin else
1112da2e3ebdSchin {
1113da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(0),e_found,"function");
11147c2fbfb3SApril Chin shp->exitval = ERROR_NOENT;
1115da2e3ebdSchin }
1116da2e3ebdSchin goto setexit;
1117da2e3ebdSchin }
1118da2e3ebdSchin }
1119da2e3ebdSchin /* increase refcnt for unset */
1120da2e3ebdSchin slp = (struct slnod*)np->nvenv;
1121da2e3ebdSchin sh_funstaks(slp->slchild,1);
1122da2e3ebdSchin staklink(slp->slptr);
1123da2e3ebdSchin if(nq)
1124da2e3ebdSchin {
11257c2fbfb3SApril Chin shp->last_table = last_table;
1126*3e14f97fSRoger A. Faulkner mode = set_instance(shp,nq,&node,&nr);
1127da2e3ebdSchin }
1128da2e3ebdSchin if(io)
1129da2e3ebdSchin {
11307c2fbfb3SApril Chin indx = shp->topfd;
1131da2e3ebdSchin sh_pushcontext(&buff,SH_JMPCMD);
1132da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
1133da2e3ebdSchin }
1134da2e3ebdSchin if(jmpval == 0)
1135da2e3ebdSchin {
1136da2e3ebdSchin if(io)
11377c2fbfb3SApril Chin indx = sh_redirect(shp,io,execflg);
11387c2fbfb3SApril Chin sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
1139da2e3ebdSchin }
1140da2e3ebdSchin if(io)
1141da2e3ebdSchin {
1142da2e3ebdSchin if(buff.olist)
1143da2e3ebdSchin free_list(buff.olist);
1144da2e3ebdSchin sh_popcontext(&buff);
11457c2fbfb3SApril Chin sh_iorestore(shp,indx,jmpval);
1146da2e3ebdSchin }
1147da2e3ebdSchin if(nq)
11487c2fbfb3SApril Chin unset_instance(nq,&node,&nr,mode);
1149da2e3ebdSchin sh_funstaks(slp->slchild,-1);
1150da2e3ebdSchin stakdelete(slp->slptr);
1151da2e3ebdSchin if(jmpval > SH_JMPFUN)
11527c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
1153da2e3ebdSchin goto setexit;
1154da2e3ebdSchin }
1155da2e3ebdSchin }
1156da2e3ebdSchin else if(!io)
1157da2e3ebdSchin {
1158da2e3ebdSchin setexit:
1159da2e3ebdSchin exitset();
1160da2e3ebdSchin break;
1161da2e3ebdSchin }
1162da2e3ebdSchin }
1163da2e3ebdSchin case TFORK:
1164da2e3ebdSchin {
1165da2e3ebdSchin register pid_t parent;
1166da2e3ebdSchin int no_fork,jobid;
1167da2e3ebdSchin int pipes[2];
11687c2fbfb3SApril Chin if(shp->subshell)
116934f9b3eeSRoland Mainz {
117034f9b3eeSRoland Mainz if(shp->subshare)
11717c2fbfb3SApril Chin sh_subtmpfile(1);
117234f9b3eeSRoland Mainz else
117334f9b3eeSRoland Mainz sh_subfork();
117434f9b3eeSRoland Mainz }
117534f9b3eeSRoland Mainz no_fork = !ntflag && !(type&(FAMP|FPOU)) &&
117634f9b3eeSRoland Mainz !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
1177*3e14f97fSRoger A. Faulkner ((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
117834f9b3eeSRoland Mainz (execflg2 || (execflg &&
117934f9b3eeSRoland Mainz !shp->subshell && shp->fn_depth==0 &&
118034f9b3eeSRoland Mainz !(pipejob && sh_isoption(SH_PIPEFAIL))
118134f9b3eeSRoland Mainz ));
11827c2fbfb3SApril Chin if(sh_isstate(SH_PROFILE) || shp->dot_depth)
1183da2e3ebdSchin {
1184da2e3ebdSchin /* disable foreground job monitor */
1185da2e3ebdSchin if(!(type&FAMP))
1186da2e3ebdSchin sh_offstate(SH_MONITOR);
1187da2e3ebdSchin #if SHOPT_DEVFD
1188da2e3ebdSchin else if(!(type&FINT))
1189da2e3ebdSchin sh_offstate(SH_MONITOR);
1190da2e3ebdSchin #endif /* SHOPT_DEVFD */
1191da2e3ebdSchin }
1192da2e3ebdSchin if(no_fork)
1193da2e3ebdSchin job.parent=parent=0;
1194da2e3ebdSchin else
1195da2e3ebdSchin {
119634f9b3eeSRoland Mainz #ifdef SHOPT_BGX
119734f9b3eeSRoland Mainz int maxjob;
119834f9b3eeSRoland Mainz if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
119934f9b3eeSRoland Mainz {
120034f9b3eeSRoland Mainz while(job.numbjob >= maxjob)
120134f9b3eeSRoland Mainz {
120234f9b3eeSRoland Mainz job_lock();
120334f9b3eeSRoland Mainz job_reap(0);
120434f9b3eeSRoland Mainz job_unlock();
120534f9b3eeSRoland Mainz }
120634f9b3eeSRoland Mainz }
120734f9b3eeSRoland Mainz #endif /* SHOPT_BGX */
1208da2e3ebdSchin if(type&FCOOP)
12097c2fbfb3SApril Chin coproc_init(shp,pipes);
1210da2e3ebdSchin nv_getval(RANDNOD);
1211da2e3ebdSchin #if SHOPT_AMP
1212da2e3ebdSchin if((type&(FAMP|FINT)) == (FAMP|FINT))
12137c2fbfb3SApril Chin parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1214da2e3ebdSchin else
1215da2e3ebdSchin parent = sh_fork(type,&jobid);
1216da2e3ebdSchin if(parent<0)
1217da2e3ebdSchin break;
1218da2e3ebdSchin #else
1219da2e3ebdSchin #if SHOPT_SPAWN
1220da2e3ebdSchin # ifdef _lib_fork
1221da2e3ebdSchin if(com)
12227c2fbfb3SApril Chin parent = sh_ntfork(shp,t,com,&jobid,ntflag);
1223da2e3ebdSchin else
1224da2e3ebdSchin parent = sh_fork(type,&jobid);
1225da2e3ebdSchin # else
12267c2fbfb3SApril Chin if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
1227da2e3ebdSchin break;
1228da2e3ebdSchin # endif /* _lib_fork */
1229da2e3ebdSchin if(parent<0)
1230da2e3ebdSchin break;
1231da2e3ebdSchin #else
1232da2e3ebdSchin parent = sh_fork(type,&jobid);
1233da2e3ebdSchin #endif /* SHOPT_SPAWN */
1234da2e3ebdSchin #endif
1235da2e3ebdSchin }
1236da2e3ebdSchin if(job.parent=parent)
1237da2e3ebdSchin /* This is the parent branch of fork
1238da2e3ebdSchin * It may or may not wait for the child
1239da2e3ebdSchin */
1240da2e3ebdSchin {
124134f9b3eeSRoland Mainz if(pipejob==2)
124234f9b3eeSRoland Mainz {
124334f9b3eeSRoland Mainz pipejob = 1;
124434f9b3eeSRoland Mainz job_unlock();
124534f9b3eeSRoland Mainz }
1246da2e3ebdSchin if(type&FPCL)
12477c2fbfb3SApril Chin sh_close(shp->inpipe[0]);
1248da2e3ebdSchin if(type&(FCOOP|FAMP))
12497c2fbfb3SApril Chin shp->bckpid = parent;
12507c2fbfb3SApril Chin else if(!(type&(FAMP|FPOU)))
1251da2e3ebdSchin {
12527c2fbfb3SApril Chin if(shp->topfd > topfd)
12537c2fbfb3SApril Chin sh_iorestore(shp,topfd,0);
12547c2fbfb3SApril Chin if(!sh_isoption(SH_MONITOR))
12557c2fbfb3SApril Chin {
12567c2fbfb3SApril Chin if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
12577c2fbfb3SApril Chin sh_sigtrap(SIGINT);
12587c2fbfb3SApril Chin shp->trapnote |= SH_SIGIGNORE;
12597c2fbfb3SApril Chin }
126034f9b3eeSRoland Mainz if(execflg && shp->subshell && !shp->subshare)
12617c2fbfb3SApril Chin {
12627c2fbfb3SApril Chin shp->spid = parent;
12637c2fbfb3SApril Chin job.pwlist->p_env--;
12647c2fbfb3SApril Chin }
126534f9b3eeSRoland Mainz else if(shp->pipepid)
126634f9b3eeSRoland Mainz shp->pipepid = parent;
12677c2fbfb3SApril Chin else
1268da2e3ebdSchin job_wait(parent);
12697c2fbfb3SApril Chin if(!sh_isoption(SH_MONITOR))
12707c2fbfb3SApril Chin {
12717c2fbfb3SApril Chin shp->trapnote &= ~SH_SIGIGNORE;
12727c2fbfb3SApril Chin if(shp->exitval == (SH_EXITSIG|SIGINT))
12737c2fbfb3SApril Chin sh_fault(SIGINT);
12747c2fbfb3SApril Chin }
1275da2e3ebdSchin }
1276da2e3ebdSchin if(type&FAMP)
1277da2e3ebdSchin {
1278da2e3ebdSchin if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
1279da2e3ebdSchin {
1280da2e3ebdSchin /* print job number */
1281da2e3ebdSchin #ifdef JOBS
1282da2e3ebdSchin sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent);
1283da2e3ebdSchin #else
1284da2e3ebdSchin sfprintf(sfstderr,"%d\n",parent);
1285da2e3ebdSchin #endif /* JOBS */
1286da2e3ebdSchin }
1287da2e3ebdSchin }
1288da2e3ebdSchin break;
1289da2e3ebdSchin }
1290da2e3ebdSchin else
1291da2e3ebdSchin /*
1292da2e3ebdSchin * this is the FORKED branch (child) of execute
1293da2e3ebdSchin */
1294da2e3ebdSchin {
12957c2fbfb3SApril Chin volatile int jmpval;
1296da2e3ebdSchin struct checkpt buff;
1297da2e3ebdSchin if(no_fork)
1298da2e3ebdSchin sh_sigreset(2);
1299da2e3ebdSchin sh_pushcontext(&buff,SH_JMPEXIT);
1300da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
1301da2e3ebdSchin if(jmpval)
1302da2e3ebdSchin goto done;
1303da2e3ebdSchin if((type&FINT) && !sh_isstate(SH_MONITOR))
1304da2e3ebdSchin {
1305da2e3ebdSchin /* default std input for & */
1306da2e3ebdSchin signal(SIGINT,SIG_IGN);
1307da2e3ebdSchin signal(SIGQUIT,SIG_IGN);
13087c2fbfb3SApril Chin if(!shp->st.ioset)
1309da2e3ebdSchin {
1310da2e3ebdSchin if(sh_close(0)>=0)
1311da2e3ebdSchin sh_chkopen(e_devnull);
1312da2e3ebdSchin }
1313da2e3ebdSchin }
1314da2e3ebdSchin sh_offstate(SH_MONITOR);
1315da2e3ebdSchin /* pipe in or out */
1316da2e3ebdSchin #ifdef _lib_nice
1317da2e3ebdSchin if((type&FAMP) && sh_isoption(SH_BGNICE))
1318da2e3ebdSchin nice(4);
1319da2e3ebdSchin #endif /* _lib_nice */
1320da2e3ebdSchin if(type&FPIN)
1321da2e3ebdSchin {
13227c2fbfb3SApril Chin sh_iorenumber(shp,shp->inpipe[0],0);
1323da2e3ebdSchin if(!(type&FPOU) || (type&FCOOP))
13247c2fbfb3SApril Chin sh_close(shp->inpipe[1]);
1325da2e3ebdSchin }
1326da2e3ebdSchin if(type&FPOU)
1327da2e3ebdSchin {
13287c2fbfb3SApril Chin sh_iorenumber(shp,shp->outpipe[1],1);
13297c2fbfb3SApril Chin sh_pclose(shp->outpipe);
1330da2e3ebdSchin }
1331da2e3ebdSchin if((type&COMMSK)!=TCOM)
13327c2fbfb3SApril Chin error_info.line = t->fork.forkline-shp->st.firstline;
13337c2fbfb3SApril Chin if(shp->topfd)
13347c2fbfb3SApril Chin sh_iounsave(shp);
13357c2fbfb3SApril Chin topfd = shp->topfd;
13367c2fbfb3SApril Chin sh_redirect(shp,t->tre.treio,1);
13377c2fbfb3SApril Chin if(shp->topfd > topfd)
13387c2fbfb3SApril Chin {
1339*3e14f97fSRoger A. Faulkner job_lock();
13407c2fbfb3SApril Chin while((parent = vfork()) < 0)
13417c2fbfb3SApril Chin _sh_fork(parent, 0, (int*)0);
1342*3e14f97fSRoger A. Faulkner job_fork(parent);
13437c2fbfb3SApril Chin if(parent)
13447c2fbfb3SApril Chin {
13457c2fbfb3SApril Chin job_clear();
13467c2fbfb3SApril Chin job_post(parent,0);
13477c2fbfb3SApril Chin job_wait(parent);
13487c2fbfb3SApril Chin sh_iorestore(shp,topfd,SH_JMPCMD);
13497c2fbfb3SApril Chin sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
13507c2fbfb3SApril Chin
13517c2fbfb3SApril Chin }
13527c2fbfb3SApril Chin }
1353da2e3ebdSchin if((type&COMMSK)!=TCOM)
1354da2e3ebdSchin {
1355da2e3ebdSchin /* don't clear job table for out
1356da2e3ebdSchin pipes so that jobs comand can
1357da2e3ebdSchin be used in a pipeline
1358da2e3ebdSchin */
1359da2e3ebdSchin if(!no_fork && !(type&FPOU))
1360da2e3ebdSchin job_clear();
136134f9b3eeSRoland Mainz sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
1362da2e3ebdSchin }
1363da2e3ebdSchin else if(com0)
1364da2e3ebdSchin {
1365da2e3ebdSchin sh_offoption(SH_ERREXIT);
13667c2fbfb3SApril Chin sh_freeup(shp);
1367da2e3ebdSchin path_exec(com0,com,t->com.comset);
1368da2e3ebdSchin }
1369da2e3ebdSchin done:
1370da2e3ebdSchin sh_popcontext(&buff);
1371da2e3ebdSchin if(jmpval>SH_JMPEXIT)
13727c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
13737c2fbfb3SApril Chin sh_done(shp,0);
1374da2e3ebdSchin }
1375da2e3ebdSchin }
1376da2e3ebdSchin
1377da2e3ebdSchin case TSETIO:
1378da2e3ebdSchin {
1379da2e3ebdSchin /*
1380da2e3ebdSchin * don't create a new process, just
1381da2e3ebdSchin * save and restore io-streams
1382da2e3ebdSchin */
1383da2e3ebdSchin pid_t pid;
1384da2e3ebdSchin int jmpval, waitall;
138534f9b3eeSRoland Mainz int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
1386da2e3ebdSchin struct checkpt buff;
13877c2fbfb3SApril Chin if(shp->subshell)
1388da2e3ebdSchin execflg = 0;
1389da2e3ebdSchin sh_pushcontext(&buff,SH_JMPIO);
1390da2e3ebdSchin if(type&FPIN)
1391da2e3ebdSchin {
1392da2e3ebdSchin was_interactive = sh_isstate(SH_INTERACTIVE);
1393da2e3ebdSchin sh_offstate(SH_INTERACTIVE);
13947c2fbfb3SApril Chin sh_iosave(shp,0,shp->topfd,(char*)0);
139534f9b3eeSRoland Mainz shp->pipepid = simple;
13967c2fbfb3SApril Chin sh_iorenumber(shp,shp->inpipe[0],0);
1397da2e3ebdSchin /*
1398da2e3ebdSchin * if read end of pipe is a simple command
1399da2e3ebdSchin * treat as non-sharable to improve performance
1400da2e3ebdSchin */
140134f9b3eeSRoland Mainz if(simple)
1402da2e3ebdSchin sfset(sfstdin,SF_PUBLIC|SF_SHARE,0);
1403da2e3ebdSchin waitall = job.waitall;
1404da2e3ebdSchin job.waitall = 0;
1405da2e3ebdSchin pid = job.parent;
1406da2e3ebdSchin }
1407da2e3ebdSchin else
14087c2fbfb3SApril Chin error_info.line = t->fork.forkline-shp->st.firstline;
1409da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
1410da2e3ebdSchin if(jmpval==0)
1411da2e3ebdSchin {
14127c2fbfb3SApril Chin sh_redirect(shp,t->fork.forkio,execflg);
1413da2e3ebdSchin (t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
141434f9b3eeSRoland Mainz sh_exec(t->fork.forktre,flags&~simple);
1415da2e3ebdSchin }
14167c2fbfb3SApril Chin else
14177c2fbfb3SApril Chin sfsync(shp->outpool);
1418da2e3ebdSchin sh_popcontext(&buff);
14197c2fbfb3SApril Chin sh_iorestore(shp,buff.topfd,jmpval);
1420da2e3ebdSchin if(buff.olist)
1421da2e3ebdSchin free_list(buff.olist);
1422da2e3ebdSchin if(type&FPIN)
1423da2e3ebdSchin {
1424da2e3ebdSchin job.waitall = waitall;
14257c2fbfb3SApril Chin type = shp->exitval;
1426da2e3ebdSchin if(!(type&SH_EXITSIG))
1427da2e3ebdSchin {
1428da2e3ebdSchin /* wait for remainder of pipline */
142934f9b3eeSRoland Mainz if(shp->pipepid>1)
143034f9b3eeSRoland Mainz {
143134f9b3eeSRoland Mainz job_wait(shp->pipepid);
143234f9b3eeSRoland Mainz type = shp->exitval;
143334f9b3eeSRoland Mainz }
143434f9b3eeSRoland Mainz else
1435da2e3ebdSchin job_wait(waitall?pid:0);
1436da2e3ebdSchin if(type || !sh_isoption(SH_PIPEFAIL))
14377c2fbfb3SApril Chin shp->exitval = type;
1438da2e3ebdSchin }
143934f9b3eeSRoland Mainz shp->pipepid = 0;
14407c2fbfb3SApril Chin shp->st.ioset = 0;
144134f9b3eeSRoland Mainz if(simple && was_errexit)
144234f9b3eeSRoland Mainz {
144334f9b3eeSRoland Mainz echeck = 1;
144434f9b3eeSRoland Mainz sh_onstate(SH_ERREXIT);
144534f9b3eeSRoland Mainz }
1446da2e3ebdSchin }
1447da2e3ebdSchin if(jmpval>SH_JMPIO)
14487c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
1449da2e3ebdSchin break;
1450da2e3ebdSchin }
1451da2e3ebdSchin
1452da2e3ebdSchin case TPAR:
1453da2e3ebdSchin echeck = 1;
1454da2e3ebdSchin flags &= ~OPTIMIZE_FLAG;
14557c2fbfb3SApril Chin if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
1456da2e3ebdSchin {
145734f9b3eeSRoland Mainz char *savsig;
145834f9b3eeSRoland Mainz int nsig,jmpval;
1459da2e3ebdSchin struct checkpt buff;
146034f9b3eeSRoland Mainz shp->st.otrapcom = 0;
146134f9b3eeSRoland Mainz if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
146234f9b3eeSRoland Mainz {
146334f9b3eeSRoland Mainz nsig += sizeof(char*);
146434f9b3eeSRoland Mainz memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
146534f9b3eeSRoland Mainz shp->st.otrapcom = (char**)savsig;
146634f9b3eeSRoland Mainz }
146734f9b3eeSRoland Mainz sh_sigreset(0);
1468da2e3ebdSchin sh_pushcontext(&buff,SH_JMPEXIT);
1469da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
1470da2e3ebdSchin if(jmpval==0)
1471da2e3ebdSchin sh_exec(t->par.partre,flags);
1472da2e3ebdSchin sh_popcontext(&buff);
1473da2e3ebdSchin if(jmpval > SH_JMPEXIT)
14747c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
14757c2fbfb3SApril Chin sh_done(shp,0);
1476da2e3ebdSchin }
1477da2e3ebdSchin else
1478da2e3ebdSchin sh_subshell(t->par.partre,flags,0);
1479da2e3ebdSchin break;
1480da2e3ebdSchin
1481da2e3ebdSchin case TFIL:
1482da2e3ebdSchin {
1483da2e3ebdSchin /*
1484da2e3ebdSchin * This code sets up a pipe.
1485da2e3ebdSchin * All elements of the pipe are started by the parent.
1486da2e3ebdSchin * The last element executes in current environment
1487da2e3ebdSchin */
1488da2e3ebdSchin int pvo[2]; /* old pipe for multi-stage */
1489da2e3ebdSchin int pvn[2]; /* current set up pipe */
1490da2e3ebdSchin int savepipe = pipejob;
1491da2e3ebdSchin int showme = t->tre.tretyp&FSHOWME;
1492da2e3ebdSchin pid_t savepgid = job.curpgid;
14937c2fbfb3SApril Chin job.curpgid = 0;
14947c2fbfb3SApril Chin if(shp->subshell)
149581af778eSCasper H.S. Dik {
149681af778eSCasper H.S. Dik if(shp->subshare)
149781af778eSCasper H.S. Dik sh_subtmpfile(0);
149881af778eSCasper H.S. Dik else
149981af778eSCasper H.S. Dik sh_subfork();
150081af778eSCasper H.S. Dik }
15017c2fbfb3SApril Chin shp->inpipe = pvo;
15027c2fbfb3SApril Chin shp->outpipe = pvn;
1503da2e3ebdSchin pvo[1] = -1;
1504da2e3ebdSchin if(sh_isoption(SH_PIPEFAIL))
1505da2e3ebdSchin job.waitall = 1;
1506da2e3ebdSchin else
1507da2e3ebdSchin job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
150834f9b3eeSRoland Mainz job_lock();
1509da2e3ebdSchin do
1510da2e3ebdSchin {
1511da2e3ebdSchin #if SHOPT_FASTPIPE
15127c2fbfb3SApril Chin type = pipe_exec(shp,pvn,t->lst.lstlef, errorflg);
1513da2e3ebdSchin #else
1514da2e3ebdSchin /* create the pipe */
1515da2e3ebdSchin sh_pipe(pvn);
1516da2e3ebdSchin /* execute out part of pipe no wait */
1517da2e3ebdSchin (t->lst.lstlef)->tre.tretyp |= showme;
1518da2e3ebdSchin type = sh_exec(t->lst.lstlef, errorflg);
1519da2e3ebdSchin #endif /* SHOPT_FASTPIPE */
1520da2e3ebdSchin pipejob=1;
1521da2e3ebdSchin /* save the pipe stream-ids */
1522da2e3ebdSchin pvo[0] = pvn[0];
1523da2e3ebdSchin /* close out-part of pipe */
1524da2e3ebdSchin sh_close(pvn[1]);
1525da2e3ebdSchin /* pipeline all in one process group */
1526da2e3ebdSchin t = t->lst.lstrit;
1527da2e3ebdSchin }
1528da2e3ebdSchin /* repeat until end of pipeline */
1529da2e3ebdSchin while(!type && t->tre.tretyp==TFIL);
15307c2fbfb3SApril Chin shp->inpipe = pvn;
15317c2fbfb3SApril Chin shp->outpipe = 0;
153234f9b3eeSRoland Mainz pipejob = 2;
1533da2e3ebdSchin if(type == 0)
1534da2e3ebdSchin {
1535da2e3ebdSchin /*
1536da2e3ebdSchin * execute last element of pipeline
1537da2e3ebdSchin * in the current process
1538da2e3ebdSchin */
1539da2e3ebdSchin ((Shnode_t*)t)->tre.tretyp |= showme;
1540da2e3ebdSchin sh_exec(t,flags);
1541da2e3ebdSchin }
1542da2e3ebdSchin else
1543da2e3ebdSchin /* execution failure, close pipe */
1544da2e3ebdSchin sh_pclose(pvn);
154534f9b3eeSRoland Mainz if(pipejob==2)
154634f9b3eeSRoland Mainz job_unlock();
1547da2e3ebdSchin pipejob = savepipe;
1548da2e3ebdSchin #ifdef SIGTSTP
1549da2e3ebdSchin if(!pipejob && sh_isstate(SH_MONITOR))
15507c2fbfb3SApril Chin tcsetpgrp(JOBTTY,shp->pid);
1551da2e3ebdSchin #endif /*SIGTSTP */
1552da2e3ebdSchin job.curpgid = savepgid;
1553da2e3ebdSchin break;
1554da2e3ebdSchin }
1555da2e3ebdSchin
1556da2e3ebdSchin case TLST:
1557da2e3ebdSchin {
1558da2e3ebdSchin /* a list of commands are executed here */
1559da2e3ebdSchin do
1560da2e3ebdSchin {
1561da2e3ebdSchin sh_exec(t->lst.lstlef,errorflg|OPTIMIZE);
1562da2e3ebdSchin t = t->lst.lstrit;
1563da2e3ebdSchin }
1564da2e3ebdSchin while(t->tre.tretyp == TLST);
1565da2e3ebdSchin sh_exec(t,flags);
1566da2e3ebdSchin break;
1567da2e3ebdSchin }
1568da2e3ebdSchin
1569da2e3ebdSchin case TAND:
1570da2e3ebdSchin if(type&TTEST)
1571da2e3ebdSchin skipexitset++;
1572da2e3ebdSchin if(sh_exec(t->lst.lstlef,OPTIMIZE)==0)
1573da2e3ebdSchin sh_exec(t->lst.lstrit,flags);
1574da2e3ebdSchin break;
1575da2e3ebdSchin
1576da2e3ebdSchin case TORF:
1577da2e3ebdSchin if(type&TTEST)
1578da2e3ebdSchin skipexitset++;
1579da2e3ebdSchin if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0)
1580da2e3ebdSchin sh_exec(t->lst.lstrit,flags);
1581da2e3ebdSchin break;
1582da2e3ebdSchin
1583da2e3ebdSchin case TFOR: /* for and select */
1584da2e3ebdSchin {
1585da2e3ebdSchin register char **args;
1586da2e3ebdSchin register int nargs;
1587da2e3ebdSchin register Namval_t *np;
1588da2e3ebdSchin int flag = errorflg|OPTIMIZE_FLAG;
1589da2e3ebdSchin struct dolnod *argsav=0;
1590da2e3ebdSchin struct comnod *tp;
1591da2e3ebdSchin char *cp, *trap, *nullptr = 0;
1592da2e3ebdSchin int nameref, refresh=1;
15937c2fbfb3SApril Chin char *av[5];
1594da2e3ebdSchin #if SHOPT_OPTIMIZE
15957c2fbfb3SApril Chin int jmpval = ((struct checkpt*)shp->jmplist)->mode;
1596da2e3ebdSchin struct checkpt buff;
15977c2fbfb3SApril Chin void *optlist = shp->optlist;
15987c2fbfb3SApril Chin shp->optlist = 0;
1599da2e3ebdSchin sh_tclear(t->for_.fortre);
1600da2e3ebdSchin sh_pushcontext(&buff,jmpval);
1601da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
1602da2e3ebdSchin if(jmpval)
1603da2e3ebdSchin goto endfor;
1604da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
16057c2fbfb3SApril Chin error_info.line = t->for_.forline-shp->st.firstline;
1606da2e3ebdSchin if(!(tp=t->for_.forlst))
1607da2e3ebdSchin {
16087c2fbfb3SApril Chin args=shp->st.dolv+1;
16097c2fbfb3SApril Chin nargs = shp->st.dolc;
16107c2fbfb3SApril Chin argsav=sh_arguse(shp);
1611da2e3ebdSchin }
1612da2e3ebdSchin else
1613da2e3ebdSchin {
16147c2fbfb3SApril Chin args=sh_argbuild(shp,&argn,tp,0);
1615da2e3ebdSchin nargs = argn;
1616da2e3ebdSchin }
16177c2fbfb3SApril Chin np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
1618da2e3ebdSchin nameref = nv_isref(np)!=0;
16197c2fbfb3SApril Chin shp->st.loopcnt++;
1620da2e3ebdSchin cp = *args;
16217c2fbfb3SApril Chin while(cp && shp->st.execbrk==0)
1622da2e3ebdSchin {
1623da2e3ebdSchin if(t->tre.tretyp&COMSCAN)
1624da2e3ebdSchin {
1625da2e3ebdSchin char *val;
1626da2e3ebdSchin int save_prompt;
1627da2e3ebdSchin /* reuse register */
1628da2e3ebdSchin if(refresh)
1629da2e3ebdSchin {
1630da2e3ebdSchin sh_menu(sfstderr,nargs,args);
1631da2e3ebdSchin refresh = 0;
1632da2e3ebdSchin }
16337c2fbfb3SApril Chin save_prompt = shp->nextprompt;
16347c2fbfb3SApril Chin shp->nextprompt = 3;
16357c2fbfb3SApril Chin shp->timeout = 0;
16367c2fbfb3SApril Chin shp->exitval=sh_readline(shp,&nullptr,0,1,1000*shp->st.tmout);
16377c2fbfb3SApril Chin shp->nextprompt = save_prompt;
16387c2fbfb3SApril Chin if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
1639da2e3ebdSchin {
16407c2fbfb3SApril Chin shp->exitval = 1;
1641da2e3ebdSchin break;
1642da2e3ebdSchin }
16437c2fbfb3SApril Chin if(!(val=nv_getval(sh_scoped(shp,REPLYNOD))))
1644da2e3ebdSchin continue;
1645da2e3ebdSchin else
1646da2e3ebdSchin {
1647da2e3ebdSchin if(*(cp=val) == 0)
1648da2e3ebdSchin {
1649da2e3ebdSchin refresh++;
1650da2e3ebdSchin goto check;
1651da2e3ebdSchin }
1652da2e3ebdSchin while(type = *cp++)
1653da2e3ebdSchin if(type < '0' && type > '9')
1654da2e3ebdSchin break;
1655da2e3ebdSchin if(type!=0)
1656da2e3ebdSchin type = nargs;
1657da2e3ebdSchin else
1658da2e3ebdSchin type = (int)strtol(val, (char**)0, 10)-1;
1659da2e3ebdSchin if(type<0 || type >= nargs)
1660da2e3ebdSchin cp = "";
1661da2e3ebdSchin else
1662da2e3ebdSchin cp = args[type];
1663da2e3ebdSchin }
1664da2e3ebdSchin }
1665da2e3ebdSchin if(nameref)
1666da2e3ebdSchin nv_offattr(np,NV_REF);
1667da2e3ebdSchin else if(nv_isattr(np, NV_ARRAY))
1668da2e3ebdSchin nv_putsub(np,NIL(char*),0L);
1669da2e3ebdSchin nv_putval(np,cp,0);
1670da2e3ebdSchin if(nameref)
1671da2e3ebdSchin nv_setref(np,(Dt_t*)0,NV_VARNAME);
16727c2fbfb3SApril Chin if(trap=shp->st.trap[SH_DEBUGTRAP])
1673da2e3ebdSchin {
1674da2e3ebdSchin av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
1675da2e3ebdSchin av[1] = t->for_.fornam;
16767c2fbfb3SApril Chin av[2] = "in";
1677da2e3ebdSchin av[3] = cp;
16787c2fbfb3SApril Chin av[4] = 0;
16797c2fbfb3SApril Chin sh_debug(shp,trap,(char*)0,(char*)0,av,0);
1680da2e3ebdSchin }
1681da2e3ebdSchin sh_exec(t->for_.fortre,flag);
1682da2e3ebdSchin flag &= ~OPTIMIZE_FLAG;
1683da2e3ebdSchin if(t->tre.tretyp&COMSCAN)
1684da2e3ebdSchin {
16857c2fbfb3SApril Chin if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
1686da2e3ebdSchin refresh++;
1687da2e3ebdSchin }
1688da2e3ebdSchin else
1689da2e3ebdSchin cp = *++args;
1690da2e3ebdSchin check:
16917c2fbfb3SApril Chin if(shp->st.breakcnt<0)
16927c2fbfb3SApril Chin shp->st.execbrk = (++shp->st.breakcnt !=0);
1693da2e3ebdSchin }
1694da2e3ebdSchin #if SHOPT_OPTIMIZE
1695da2e3ebdSchin endfor:
1696da2e3ebdSchin sh_popcontext(&buff);
1697da2e3ebdSchin sh_tclear(t->for_.fortre);
16987c2fbfb3SApril Chin sh_optclear(shp,optlist);
1699da2e3ebdSchin if(jmpval)
17007c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
1701da2e3ebdSchin #endif /*SHOPT_OPTIMIZE */
17027c2fbfb3SApril Chin if(shp->st.breakcnt>0)
17037c2fbfb3SApril Chin shp->st.execbrk = (--shp->st.breakcnt !=0);
17047c2fbfb3SApril Chin shp->st.loopcnt--;
17057c2fbfb3SApril Chin sh_argfree(shp,argsav,0);
1706da2e3ebdSchin nv_close(np);
1707da2e3ebdSchin break;
1708da2e3ebdSchin }
1709da2e3ebdSchin
1710da2e3ebdSchin case TWH: /* while and until */
1711da2e3ebdSchin {
17127c2fbfb3SApril Chin volatile int r=0;
1713da2e3ebdSchin int first = OPTIMIZE_FLAG;
1714da2e3ebdSchin Shnode_t *tt = t->wh.whtre;
1715da2e3ebdSchin #if SHOPT_FILESCAN
1716da2e3ebdSchin Sfio_t *iop=0;
1717da2e3ebdSchin int savein,fd;
1718da2e3ebdSchin #endif /*SHOPT_FILESCAN*/
1719da2e3ebdSchin #if SHOPT_OPTIMIZE
17207c2fbfb3SApril Chin int jmpval = ((struct checkpt*)shp->jmplist)->mode;
1721da2e3ebdSchin struct checkpt buff;
17227c2fbfb3SApril Chin void *optlist = shp->optlist;
17237c2fbfb3SApril Chin shp->optlist = 0;
1724da2e3ebdSchin sh_tclear(t->wh.whtre);
1725da2e3ebdSchin sh_tclear(t->wh.dotre);
1726da2e3ebdSchin sh_pushcontext(&buff,jmpval);
1727da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
1728da2e3ebdSchin if(jmpval)
1729da2e3ebdSchin goto endwhile;
1730da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
1731da2e3ebdSchin #if SHOPT_FILESCAN
1732da2e3ebdSchin if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
1733da2e3ebdSchin {
17347c2fbfb3SApril Chin fd = sh_redirect(shp,tt->com.comio,3);
1735da2e3ebdSchin savein = dup(0);
1736da2e3ebdSchin if(fd==0)
1737da2e3ebdSchin fd = savein;
1738da2e3ebdSchin iop = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
1739da2e3ebdSchin close(0);
1740da2e3ebdSchin open("/dev/null",O_RDONLY);
17417c2fbfb3SApril Chin shp->offsets[0] = -1;
17427c2fbfb3SApril Chin shp->offsets[1] = 0;
1743da2e3ebdSchin if(tt->com.comset)
174434f9b3eeSRoland Mainz nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
1745da2e3ebdSchin }
1746da2e3ebdSchin #endif /*SHOPT_FILESCAN */
17477c2fbfb3SApril Chin shp->st.loopcnt++;
17487c2fbfb3SApril Chin while(shp->st.execbrk==0)
1749da2e3ebdSchin {
1750da2e3ebdSchin #if SHOPT_FILESCAN
1751da2e3ebdSchin if(iop)
1752da2e3ebdSchin {
17537c2fbfb3SApril Chin if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING)))
1754da2e3ebdSchin break;
1755da2e3ebdSchin }
1756da2e3ebdSchin else
1757da2e3ebdSchin #endif /*SHOPT_FILESCAN */
1758da2e3ebdSchin if((sh_exec(tt,first)==0)!=(type==TWH))
1759da2e3ebdSchin break;
1760da2e3ebdSchin r = sh_exec(t->wh.dotre,first|errorflg);
17617c2fbfb3SApril Chin if(shp->st.breakcnt<0)
17627c2fbfb3SApril Chin shp->st.execbrk = (++shp->st.breakcnt !=0);
1763da2e3ebdSchin /* This is for the arithmetic for */
17647c2fbfb3SApril Chin if(shp->st.execbrk==0 && t->wh.whinc)
1765da2e3ebdSchin sh_exec((Shnode_t*)t->wh.whinc,first);
1766da2e3ebdSchin first = 0;
1767da2e3ebdSchin errorflg &= ~OPTIMIZE_FLAG;
1768da2e3ebdSchin #if SHOPT_FILESCAN
17697c2fbfb3SApril Chin shp->offsets[0] = -1;
17707c2fbfb3SApril Chin shp->offsets[1] = 0;
1771da2e3ebdSchin #endif /*SHOPT_FILESCAN */
1772da2e3ebdSchin }
1773da2e3ebdSchin #if SHOPT_OPTIMIZE
1774da2e3ebdSchin endwhile:
1775da2e3ebdSchin sh_popcontext(&buff);
1776da2e3ebdSchin sh_tclear(t->wh.whtre);
1777da2e3ebdSchin sh_tclear(t->wh.dotre);
17787c2fbfb3SApril Chin sh_optclear(shp,optlist);
1779da2e3ebdSchin if(jmpval)
17807c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
1781da2e3ebdSchin #endif /*SHOPT_OPTIMIZE */
17827c2fbfb3SApril Chin if(shp->st.breakcnt>0)
17837c2fbfb3SApril Chin shp->st.execbrk = (--shp->st.breakcnt !=0);
17847c2fbfb3SApril Chin shp->st.loopcnt--;
17857c2fbfb3SApril Chin shp->exitval= r;
1786da2e3ebdSchin #if SHOPT_FILESCAN
1787da2e3ebdSchin if(iop)
1788da2e3ebdSchin {
1789da2e3ebdSchin sfclose(iop);
1790da2e3ebdSchin close(0);
1791da2e3ebdSchin dup(savein);
17927c2fbfb3SApril Chin shp->cur_line = 0;
1793da2e3ebdSchin }
1794da2e3ebdSchin #endif /*SHOPT_FILESCAN */
1795da2e3ebdSchin break;
1796da2e3ebdSchin }
1797da2e3ebdSchin case TARITH: /* (( expression )) */
1798da2e3ebdSchin {
1799da2e3ebdSchin register char *trap;
18007c2fbfb3SApril Chin char *arg[4];
18017c2fbfb3SApril Chin error_info.line = t->ar.arline-shp->st.firstline;
18027c2fbfb3SApril Chin arg[0] = "((";
1803da2e3ebdSchin if(!(t->ar.arexpr->argflag&ARG_RAW))
18047c2fbfb3SApril Chin arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
1805da2e3ebdSchin else
1806da2e3ebdSchin arg[1] = t->ar.arexpr->argval;
18077c2fbfb3SApril Chin arg[2] = "))";
18087c2fbfb3SApril Chin arg[3] = 0;
18097c2fbfb3SApril Chin if(trap=shp->st.trap[SH_DEBUGTRAP])
18107c2fbfb3SApril Chin sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
1811da2e3ebdSchin if(sh_isoption(SH_XTRACE))
1812da2e3ebdSchin {
1813da2e3ebdSchin sh_trace(NIL(char**),0);
1814da2e3ebdSchin sfprintf(sfstderr,"((%s))\n",arg[1]);
1815da2e3ebdSchin }
1816da2e3ebdSchin if(t->ar.arcomp)
18177c2fbfb3SApril Chin shp->exitval = !arith_exec((Arith_t*)t->ar.arcomp);
1818da2e3ebdSchin else
18197c2fbfb3SApril Chin shp->exitval = !sh_arith(arg[1]);
1820da2e3ebdSchin break;
1821da2e3ebdSchin }
1822da2e3ebdSchin
1823da2e3ebdSchin case TIF:
1824da2e3ebdSchin if(sh_exec(t->if_.iftre,OPTIMIZE)==0)
1825da2e3ebdSchin sh_exec(t->if_.thtre,flags);
1826da2e3ebdSchin else if(t->if_.eltre)
1827da2e3ebdSchin sh_exec(t->if_.eltre, flags);
1828da2e3ebdSchin else
18297c2fbfb3SApril Chin shp->exitval=0; /* force zero exit for if-then-fi */
1830da2e3ebdSchin break;
1831da2e3ebdSchin
1832da2e3ebdSchin case TSW:
1833da2e3ebdSchin {
1834da2e3ebdSchin Shnode_t *tt = (Shnode_t*)t;
18357c2fbfb3SApril Chin char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
18367c2fbfb3SApril Chin error_info.line = t->sw.swline-shp->st.firstline;
1837da2e3ebdSchin t= (Shnode_t*)(tt->sw.swlst);
18387c2fbfb3SApril Chin if(trap=shp->st.trap[SH_DEBUGTRAP])
1839da2e3ebdSchin {
18407c2fbfb3SApril Chin char *av[4];
18417c2fbfb3SApril Chin av[0] = "case";
1842da2e3ebdSchin av[1] = r;
18437c2fbfb3SApril Chin av[2] = "in";
18447c2fbfb3SApril Chin av[3] = 0;
18457c2fbfb3SApril Chin sh_debug(shp,trap, (char*)0, (char*)0, av, 0);
1846da2e3ebdSchin }
1847da2e3ebdSchin while(t)
1848da2e3ebdSchin {
1849da2e3ebdSchin register struct argnod *rex=(struct argnod*)t->reg.regptr;
1850da2e3ebdSchin while(rex)
1851da2e3ebdSchin {
1852da2e3ebdSchin register char *s;
1853da2e3ebdSchin if(rex->argflag&ARG_MAC)
1854da2e3ebdSchin {
18557c2fbfb3SApril Chin s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP);
1856da2e3ebdSchin while(*s=='\\' && s[1]==0)
1857da2e3ebdSchin s+=2;
1858da2e3ebdSchin }
1859da2e3ebdSchin else
1860da2e3ebdSchin s = rex->argval;
1861da2e3ebdSchin type = (rex->argflag&ARG_RAW);
1862da2e3ebdSchin if((type && strcmp(r,s)==0) ||
1863da2e3ebdSchin (!type && (strmatch(r,s)
1864da2e3ebdSchin || trim_eq(r,s))))
1865da2e3ebdSchin {
1866da2e3ebdSchin do sh_exec(t->reg.regcom,(t->reg.regflag?0:flags));
1867da2e3ebdSchin while(t->reg.regflag &&
1868da2e3ebdSchin (t=(Shnode_t*)t->reg.regnxt));
1869da2e3ebdSchin t=0;
1870da2e3ebdSchin break;
1871da2e3ebdSchin }
1872da2e3ebdSchin else
1873da2e3ebdSchin rex=rex->argnxt.ap;
1874da2e3ebdSchin }
1875da2e3ebdSchin if(t)
1876da2e3ebdSchin t=(Shnode_t*)t->reg.regnxt;
1877da2e3ebdSchin }
1878da2e3ebdSchin break;
1879da2e3ebdSchin }
1880da2e3ebdSchin
1881da2e3ebdSchin case TTIME:
1882da2e3ebdSchin {
1883da2e3ebdSchin /* time the command */
1884da2e3ebdSchin struct tms before,after;
1885da2e3ebdSchin const char *format = e_timeformat;
1886da2e3ebdSchin clock_t at, tm[3];
1887da2e3ebdSchin #ifdef timeofday
1888da2e3ebdSchin struct timeval tb,ta;
1889da2e3ebdSchin #else
1890da2e3ebdSchin clock_t bt;
1891da2e3ebdSchin #endif /* timeofday */
1892da2e3ebdSchin if(type!=TTIME)
1893da2e3ebdSchin {
1894da2e3ebdSchin sh_exec(t->par.partre,OPTIMIZE);
18957c2fbfb3SApril Chin shp->exitval = !shp->exitval;
1896da2e3ebdSchin break;
1897da2e3ebdSchin }
1898da2e3ebdSchin if(t->par.partre)
1899da2e3ebdSchin {
1900da2e3ebdSchin long timer_on;
1901da2e3ebdSchin timer_on = sh_isstate(SH_TIMING);
1902da2e3ebdSchin #ifdef timeofday
1903da2e3ebdSchin timeofday(&tb);
1904da2e3ebdSchin times(&before);
1905da2e3ebdSchin #else
1906da2e3ebdSchin bt = times(&before);
1907da2e3ebdSchin #endif /* timeofday */
1908da2e3ebdSchin job.waitall = 1;
1909da2e3ebdSchin sh_onstate(SH_TIMING);
1910da2e3ebdSchin sh_exec(t->par.partre,OPTIMIZE);
1911da2e3ebdSchin if(!timer_on)
1912da2e3ebdSchin sh_offstate(SH_TIMING);
1913da2e3ebdSchin job.waitall = 0;
1914da2e3ebdSchin }
1915da2e3ebdSchin else
1916da2e3ebdSchin {
1917da2e3ebdSchin #ifndef timeofday
1918da2e3ebdSchin bt = 0;
1919da2e3ebdSchin #endif /* timeofday */
1920da2e3ebdSchin before.tms_utime = before.tms_cutime = 0;
1921da2e3ebdSchin before.tms_stime = before.tms_cstime = 0;
1922da2e3ebdSchin }
1923da2e3ebdSchin #ifdef timeofday
1924da2e3ebdSchin times(&after);
1925da2e3ebdSchin timeofday(&ta);
19267c2fbfb3SApril Chin at = shp->lim.clk_tck*(ta.tv_sec-tb.tv_sec);
19277c2fbfb3SApril Chin at += ((shp->lim.clk_tck*(((1000000L/2)/shp->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
1928da2e3ebdSchin #else
1929da2e3ebdSchin at = times(&after) - bt;
1930da2e3ebdSchin #endif /* timeofday */
1931da2e3ebdSchin tm[0] = at;
1932da2e3ebdSchin if(t->par.partre)
1933da2e3ebdSchin {
19347c2fbfb3SApril Chin Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
1935da2e3ebdSchin if(np)
1936da2e3ebdSchin {
1937da2e3ebdSchin format = nv_getval(np);
1938da2e3ebdSchin nv_close(np);
1939da2e3ebdSchin }
1940da2e3ebdSchin if(!format)
1941da2e3ebdSchin format = e_timeformat;
1942da2e3ebdSchin }
1943da2e3ebdSchin else
1944da2e3ebdSchin format = strchr(format+1,'\n')+1;
1945da2e3ebdSchin tm[1] = after.tms_utime - before.tms_utime;
1946da2e3ebdSchin tm[1] += after.tms_cutime - before.tms_cutime;
1947da2e3ebdSchin tm[2] = after.tms_stime - before.tms_stime;
1948da2e3ebdSchin tm[2] += after.tms_cstime - before.tms_cstime;
1949da2e3ebdSchin if(format && *format)
19507c2fbfb3SApril Chin p_time(shp,sfstderr,sh_translate(format),tm);
1951da2e3ebdSchin break;
1952da2e3ebdSchin }
1953da2e3ebdSchin case TFUN:
1954da2e3ebdSchin {
1955da2e3ebdSchin register Namval_t *np;
1956da2e3ebdSchin register struct slnod *slp;
1957da2e3ebdSchin register char *fname = ((struct functnod*)t)->functnam;
1958da2e3ebdSchin register char *cp = strrchr(fname,'.');
1959da2e3ebdSchin register Namval_t *npv=0;
1960da2e3ebdSchin #if SHOPT_NAMESPACE
1961da2e3ebdSchin if(t->tre.tretyp==TNSPACE)
1962da2e3ebdSchin {
1963da2e3ebdSchin Dt_t *root,*oldroot, *top=0;
19647c2fbfb3SApril Chin Namval_t *oldnspace = shp->namespace;
19657c2fbfb3SApril Chin int offset = stktell(stkp);
19667c2fbfb3SApril Chin long optindex = shp->st.optindex;
1967da2e3ebdSchin if(cp)
1968da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_ident,fname);
19697c2fbfb3SApril Chin sfputc(stkp,'.');
19707c2fbfb3SApril Chin sfputr(stkp,fname,0);
19717c2fbfb3SApril Chin np = nv_open(stkptr(stkp,offset),shp->var_base,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
19727c2fbfb3SApril Chin offset = stktell(stkp);
19737c2fbfb3SApril Chin shp->namespace = np;
1974da2e3ebdSchin if(!(root=nv_dict(np)))
1975da2e3ebdSchin {
1976da2e3ebdSchin root = dtopen(&_Nvdisc,Dtoset);
1977da2e3ebdSchin nv_putval(np,(char*)root,NV_TABLE|NV_NOFREE);
19787c2fbfb3SApril Chin shp->st.optindex = 1;
1979da2e3ebdSchin }
19807c2fbfb3SApril Chin if(oldnspace && dtvnext(dtvnext(shp->var_tree)))
19817c2fbfb3SApril Chin top = dtview(shp->var_tree,0);
19827c2fbfb3SApril Chin else if(dtvnext(shp->var_tree))
19837c2fbfb3SApril Chin top = dtview(shp->var_tree,0);
19847c2fbfb3SApril Chin oldroot = shp->var_tree;
19857c2fbfb3SApril Chin dtview(root,shp->var_base);
19867c2fbfb3SApril Chin shp->var_tree = root;
1987da2e3ebdSchin if(top)
19887c2fbfb3SApril Chin dtview(shp->var_tree,top);
1989da2e3ebdSchin sh_exec(t->for_.fortre,flags);
19907c2fbfb3SApril Chin if(dtvnext(shp->var_tree))
19917c2fbfb3SApril Chin top = dtview(shp->var_tree,0);
19927c2fbfb3SApril Chin shp->var_tree = oldroot;
1993da2e3ebdSchin if(top)
19947c2fbfb3SApril Chin dtview(top,shp->var_tree);
19957c2fbfb3SApril Chin shp->namespace = oldnspace;
19967c2fbfb3SApril Chin shp->st.optindex = optindex;
1997da2e3ebdSchin break;
1998da2e3ebdSchin }
1999da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
2000da2e3ebdSchin /* look for discipline functions */
20017c2fbfb3SApril Chin error_info.line = t->funct.functline-shp->st.firstline;
2002da2e3ebdSchin /* Function names cannot be special builtin */
20037c2fbfb3SApril Chin if(cp || shp->prefix)
2004da2e3ebdSchin {
20057c2fbfb3SApril Chin int offset = stktell(stkp);
20067c2fbfb3SApril Chin if(shp->prefix)
2007da2e3ebdSchin {
20087c2fbfb3SApril Chin cp = shp->prefix;
20097c2fbfb3SApril Chin shp->prefix = 0;
20107c2fbfb3SApril Chin npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
20117c2fbfb3SApril Chin shp->prefix = cp;
2012da2e3ebdSchin cp = fname;
2013da2e3ebdSchin }
2014da2e3ebdSchin else
2015da2e3ebdSchin {
20167c2fbfb3SApril Chin sfwrite(stkp,fname,cp++-fname);
20177c2fbfb3SApril Chin sfputc(stkp,0);
20187c2fbfb3SApril Chin npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
2019da2e3ebdSchin }
20207c2fbfb3SApril Chin offset = stktell(stkp);
20217c2fbfb3SApril Chin sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0);
20227c2fbfb3SApril Chin fname = stkptr(stkp,offset);
2023da2e3ebdSchin }
20247c2fbfb3SApril Chin else if((np=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))
2025da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname);
2026da2e3ebdSchin #if SHOPT_NAMESPACE
20277c2fbfb3SApril Chin else if(shp->namespace)
2028da2e3ebdSchin {
20297c2fbfb3SApril Chin int offset = stktell(stkp);
20307c2fbfb3SApril Chin sfputr(stkp,nv_name(shp->namespace),-1);
20317c2fbfb3SApril Chin sfputc(stkp,'.');
20327c2fbfb3SApril Chin sfputr(stkp,fname,0);
20337c2fbfb3SApril Chin fname = stkptr(stkp,offset);
2034da2e3ebdSchin }
2035da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
2036da2e3ebdSchin np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
2037da2e3ebdSchin if(npv)
2038da2e3ebdSchin {
20397c2fbfb3SApril Chin Namval_t *tp = npv;
20407c2fbfb3SApril Chin if(!shp->mktype)
20417c2fbfb3SApril Chin {
20427c2fbfb3SApril Chin if(shp->typeinit)
20437c2fbfb3SApril Chin {
20447c2fbfb3SApril Chin if(tp=nv_open(shp->typeinit->nvname,shp->typedict,NV_IDENT|NV_NOFAIL))
2045da2e3ebdSchin nv_close(npv);
20467c2fbfb3SApril Chin else
20477c2fbfb3SApril Chin tp = npv;
20487c2fbfb3SApril Chin }
20497c2fbfb3SApril Chin cp = nv_setdisc(tp,cp,np,(Namfun_t*)tp);
20507c2fbfb3SApril Chin }
20517c2fbfb3SApril Chin nv_close(tp);
2052da2e3ebdSchin if(!cp)
2053da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);
2054da2e3ebdSchin }
2055da2e3ebdSchin if(np->nvalue.rp)
2056da2e3ebdSchin {
2057da2e3ebdSchin slp = (struct slnod*)np->nvenv;
2058da2e3ebdSchin sh_funstaks(slp->slchild,-1);
2059da2e3ebdSchin stakdelete(slp->slptr);
20607c2fbfb3SApril Chin if(shp->funload)
20617c2fbfb3SApril Chin {
20627c2fbfb3SApril Chin free((void*)np->nvalue.rp);
20637c2fbfb3SApril Chin np->nvalue.rp = 0;
2064da2e3ebdSchin }
20657c2fbfb3SApril Chin
20667c2fbfb3SApril Chin }
20677c2fbfb3SApril Chin if(!np->nvalue.rp)
20687c2fbfb3SApril Chin {
20697c2fbfb3SApril Chin np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
20707c2fbfb3SApril Chin memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
20717c2fbfb3SApril Chin }
2072da2e3ebdSchin if(t->funct.functstak)
2073da2e3ebdSchin {
20747c2fbfb3SApril Chin static Dtdisc_t _Rpdisc =
20757c2fbfb3SApril Chin {
20767c2fbfb3SApril Chin offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
20777c2fbfb3SApril Chin };
2078da2e3ebdSchin struct functnod *fp;
2079da2e3ebdSchin slp = t->funct.functstak;
2080da2e3ebdSchin sh_funstaks(slp->slchild,1);
2081da2e3ebdSchin staklink(slp->slptr);
2082da2e3ebdSchin np->nvenv = (char*)slp;
2083da2e3ebdSchin nv_funtree(np) = (int*)(t->funct.functtre);
2084da2e3ebdSchin np->nvalue.rp->hoffset = t->funct.functloc;
2085da2e3ebdSchin np->nvalue.rp->lineno = t->funct.functline;
20867c2fbfb3SApril Chin np->nvalue.rp->nspace = shp->namespace;
2087da2e3ebdSchin np->nvalue.rp->fname = 0;
20887c2fbfb3SApril Chin np->nvalue.rp->fdict = shp->fun_tree;
2089da2e3ebdSchin fp = (struct functnod*)(slp+1);
2090da2e3ebdSchin if(fp->functtyp==(TFUN|FAMP))
2091da2e3ebdSchin np->nvalue.rp->fname = fp->functnam;
2092da2e3ebdSchin nv_setsize(np,fp->functline);
2093da2e3ebdSchin nv_offattr(np,NV_FPOSIX);
20947c2fbfb3SApril Chin if(shp->funload)
20957c2fbfb3SApril Chin {
20967c2fbfb3SApril Chin struct Ufunction *rp = np->nvalue.rp;
20977c2fbfb3SApril Chin rp->np = np;
20987c2fbfb3SApril Chin if(!shp->fpathdict)
20997c2fbfb3SApril Chin shp->fpathdict = dtopen(&_Rpdisc,Dtbag);
21007c2fbfb3SApril Chin if(shp->fpathdict)
21017c2fbfb3SApril Chin dtinsert(shp->fpathdict,rp);
21027c2fbfb3SApril Chin }
2103da2e3ebdSchin }
2104da2e3ebdSchin else
2105da2e3ebdSchin nv_unset(np);
2106da2e3ebdSchin if(type&FPOSIX)
2107da2e3ebdSchin nv_onattr(np,NV_FUNCTION|NV_FPOSIX);
2108da2e3ebdSchin else
2109da2e3ebdSchin nv_onattr(np,NV_FUNCTION);
2110da2e3ebdSchin if(type&FPIN)
2111da2e3ebdSchin nv_onattr(np,NV_FTMP);
21127c2fbfb3SApril Chin if(type&FOPTGET)
21137c2fbfb3SApril Chin nv_onattr(np,NV_OPTGET);
2114da2e3ebdSchin break;
2115da2e3ebdSchin }
2116da2e3ebdSchin
2117da2e3ebdSchin /* new test compound command */
2118da2e3ebdSchin case TTST:
2119da2e3ebdSchin {
2120da2e3ebdSchin register int n;
2121da2e3ebdSchin register char *left;
2122da2e3ebdSchin int negate = (type&TNEGATE)!=0;
2123da2e3ebdSchin if(type&TTEST)
2124da2e3ebdSchin skipexitset++;
21257c2fbfb3SApril Chin error_info.line = t->tst.tstline-shp->st.firstline;
2126da2e3ebdSchin echeck = 1;
2127da2e3ebdSchin if((type&TPAREN)==TPAREN)
2128da2e3ebdSchin {
2129da2e3ebdSchin sh_exec(t->lst.lstlef,OPTIMIZE);
21307c2fbfb3SApril Chin n = !shp->exitval;
2131da2e3ebdSchin }
2132da2e3ebdSchin else
2133da2e3ebdSchin {
2134da2e3ebdSchin register int traceon=0;
2135da2e3ebdSchin register char *right;
2136da2e3ebdSchin register char *trap;
2137da2e3ebdSchin char *argv[6];
2138da2e3ebdSchin n = type>>TSHIFT;
21397c2fbfb3SApril Chin left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
2140da2e3ebdSchin if(type&TBINARY)
21417c2fbfb3SApril Chin right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
21427c2fbfb3SApril Chin if(trap=shp->st.trap[SH_DEBUGTRAP])
2143da2e3ebdSchin argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[[";
2144da2e3ebdSchin if(sh_isoption(SH_XTRACE))
2145da2e3ebdSchin {
2146da2e3ebdSchin traceon = sh_trace(NIL(char**),0);
2147da2e3ebdSchin sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3));
2148da2e3ebdSchin }
2149da2e3ebdSchin if(type&TUNARY)
2150da2e3ebdSchin {
2151da2e3ebdSchin if(traceon)
2152da2e3ebdSchin sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left));
2153da2e3ebdSchin if(trap)
2154da2e3ebdSchin {
2155da2e3ebdSchin char unop[3];
2156da2e3ebdSchin unop[0] = '-';
2157da2e3ebdSchin unop[1] = n;
2158da2e3ebdSchin unop[2] = 0;
2159da2e3ebdSchin argv[1] = unop;
2160da2e3ebdSchin argv[2] = left;
2161da2e3ebdSchin argv[3] = "]]";
2162da2e3ebdSchin argv[4] = 0;
21637c2fbfb3SApril Chin sh_debug(shp,trap,(char*)0,(char*)0,argv, 0);
2164da2e3ebdSchin }
2165da2e3ebdSchin n = test_unop(n,left);
2166da2e3ebdSchin }
2167da2e3ebdSchin else if(type&TBINARY)
2168da2e3ebdSchin {
2169da2e3ebdSchin char *op;
2170da2e3ebdSchin int pattern = 0;
2171da2e3ebdSchin if(trap || traceon)
2172da2e3ebdSchin op = (char*)(shtab_testops+(n&037)-1)->sh_name;
2173da2e3ebdSchin type >>= TSHIFT;
2174da2e3ebdSchin if(type==TEST_PEQ || type==TEST_PNE)
2175da2e3ebdSchin pattern=ARG_EXP;
2176da2e3ebdSchin if(trap)
2177da2e3ebdSchin {
2178da2e3ebdSchin argv[1] = left;
2179da2e3ebdSchin argv[2] = op;
2180da2e3ebdSchin argv[3] = right;
2181da2e3ebdSchin argv[4] = "]]";
2182da2e3ebdSchin argv[5] = 0;
21837c2fbfb3SApril Chin sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
2184da2e3ebdSchin }
2185da2e3ebdSchin n = test_binop(n,left,right);
2186da2e3ebdSchin if(traceon)
2187da2e3ebdSchin {
2188da2e3ebdSchin sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op);
2189da2e3ebdSchin if(pattern)
2190da2e3ebdSchin out_pattern(sfstderr,right,-1);
2191da2e3ebdSchin else
2192da2e3ebdSchin sfputr(sfstderr,sh_fmtq(right),-1);
2193da2e3ebdSchin }
2194da2e3ebdSchin }
2195da2e3ebdSchin if(traceon)
2196da2e3ebdSchin sfwrite(sfstderr,e_tstend,4);
2197da2e3ebdSchin }
21987c2fbfb3SApril Chin shp->exitval = ((!n)^negate);
2199da2e3ebdSchin if(!skipexitset)
2200da2e3ebdSchin exitset();
2201da2e3ebdSchin break;
2202da2e3ebdSchin }
2203da2e3ebdSchin }
22047c2fbfb3SApril Chin if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
2205da2e3ebdSchin t && echeck)
2206da2e3ebdSchin sh_chktrap();
2207da2e3ebdSchin /* set $_ */
2208da2e3ebdSchin if(mainloop && com0)
2209da2e3ebdSchin {
2210da2e3ebdSchin /* store last argument here if it fits */
2211da2e3ebdSchin static char lastarg[32];
2212da2e3ebdSchin if(sh_isstate(SH_FORKED))
22137c2fbfb3SApril Chin sh_done(shp,0);
22147c2fbfb3SApril Chin if(shp->lastarg!= lastarg && shp->lastarg)
22157c2fbfb3SApril Chin free(shp->lastarg);
22167c2fbfb3SApril Chin if(strlen(comn) < sizeof(lastarg))
2217da2e3ebdSchin {
2218da2e3ebdSchin nv_onattr(L_ARGNOD,NV_NOFREE);
22197c2fbfb3SApril Chin shp->lastarg = strcpy(lastarg,comn);
2220da2e3ebdSchin }
2221da2e3ebdSchin else
2222da2e3ebdSchin {
2223da2e3ebdSchin nv_offattr(L_ARGNOD,NV_NOFREE);
22247c2fbfb3SApril Chin shp->lastarg = strdup(comn);
2225da2e3ebdSchin }
2226da2e3ebdSchin }
2227da2e3ebdSchin if(!skipexitset)
2228da2e3ebdSchin exitset();
2229da2e3ebdSchin if(!(OPTIMIZE))
2230da2e3ebdSchin {
22317c2fbfb3SApril Chin if(sav != stkptr(stkp,0))
22327c2fbfb3SApril Chin stkset(stkp,sav,0);
22337c2fbfb3SApril Chin else if(stktell(stkp))
22347c2fbfb3SApril Chin stkseek(stkp,0);
2235da2e3ebdSchin }
22367c2fbfb3SApril Chin if(shp->trapnote&SH_SIGSET)
22377c2fbfb3SApril Chin sh_exit(SH_EXITSIG|shp->lastsig);
2238da2e3ebdSchin if(was_interactive)
2239da2e3ebdSchin sh_onstate(SH_INTERACTIVE);
2240da2e3ebdSchin if(was_monitor && sh_isoption(SH_MONITOR))
2241da2e3ebdSchin sh_onstate(SH_MONITOR);
2242da2e3ebdSchin if(was_errexit)
2243da2e3ebdSchin sh_onstate(SH_ERREXIT);
2244da2e3ebdSchin }
22457c2fbfb3SApril Chin return(shp->exitval);
22467c2fbfb3SApril Chin }
22477c2fbfb3SApril Chin
sh_run(int argn,char * argv[])22487c2fbfb3SApril Chin int sh_run(int argn, char *argv[])
22497c2fbfb3SApril Chin {
22507c2fbfb3SApril Chin register struct dolnod *dp;
22517c2fbfb3SApril Chin register struct comnod *t = (struct comnod*)stakalloc(sizeof(struct comnod));
22527c2fbfb3SApril Chin int savtop = staktell();
22537c2fbfb3SApril Chin char *savptr = stakfreeze(0);
22547c2fbfb3SApril Chin Opt_t *op, *np = optctx(0, 0);
22557c2fbfb3SApril Chin Shbltin_t bltindata;
22567c2fbfb3SApril Chin bltindata = sh.bltindata;
22577c2fbfb3SApril Chin op = optctx(np, 0);
22587c2fbfb3SApril Chin memset(t, 0, sizeof(struct comnod));
22597c2fbfb3SApril Chin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
22607c2fbfb3SApril Chin dp->dolnum = argn;
22617c2fbfb3SApril Chin dp->dolbot = ARG_SPARE;
22627c2fbfb3SApril Chin memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
22637c2fbfb3SApril Chin t->comarg = (struct argnod*)dp;
22647c2fbfb3SApril Chin if(!strchr(argv[0],'/'))
22657c2fbfb3SApril Chin t->comnamp = (void*)nv_bfsearch(argv[0],sh.fun_tree,(Namval_t**)&t->comnamq,(char**)0);
22667c2fbfb3SApril Chin argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
22677c2fbfb3SApril Chin optctx(op,np);
22687c2fbfb3SApril Chin sh.bltindata = bltindata;
22697c2fbfb3SApril Chin if(savptr!=stakptr(0))
22707c2fbfb3SApril Chin stakset(savptr,savtop);
22717c2fbfb3SApril Chin else
22727c2fbfb3SApril Chin stakseek(savtop);
22737c2fbfb3SApril Chin return(argn);
2274da2e3ebdSchin }
2275da2e3ebdSchin
2276da2e3ebdSchin /*
2277da2e3ebdSchin * test for equality with second argument trimmed
2278da2e3ebdSchin * returns 1 if r == trim(s) otherwise 0
2279da2e3ebdSchin */
2280da2e3ebdSchin
trim_eq(register const char * r,register const char * s)2281da2e3ebdSchin static int trim_eq(register const char *r,register const char *s)
2282da2e3ebdSchin {
2283da2e3ebdSchin register char c;
2284da2e3ebdSchin while(c = *s++)
2285da2e3ebdSchin {
2286da2e3ebdSchin if(c=='\\')
2287da2e3ebdSchin c = *s++;
2288da2e3ebdSchin if(c && c != *r++)
2289da2e3ebdSchin return(0);
2290da2e3ebdSchin }
2291da2e3ebdSchin return(*r==0);
2292da2e3ebdSchin }
2293da2e3ebdSchin
2294da2e3ebdSchin /*
2295da2e3ebdSchin * print out the command line if set -x is on
2296da2e3ebdSchin */
2297da2e3ebdSchin
sh_trace(register char * argv[],register int nl)2298da2e3ebdSchin int sh_trace(register char *argv[], register int nl)
2299da2e3ebdSchin {
23007c2fbfb3SApril Chin Shell_t *shp = &sh;
2301da2e3ebdSchin register char *cp;
2302da2e3ebdSchin register int bracket = 0;
23037c2fbfb3SApril Chin int decl = (nl&2);
23047c2fbfb3SApril Chin nl &= ~2;
2305da2e3ebdSchin if(sh_isoption(SH_XTRACE))
2306da2e3ebdSchin {
2307da2e3ebdSchin /* make this trace atomic */
2308da2e3ebdSchin sfset(sfstderr,SF_SHARE|SF_PUBLIC,0);
23097c2fbfb3SApril Chin if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
2310da2e3ebdSchin cp = "+ ";
2311da2e3ebdSchin else
2312da2e3ebdSchin {
2313da2e3ebdSchin sh_offoption(SH_XTRACE);
23147c2fbfb3SApril Chin cp = sh_mactry(shp,cp);
2315da2e3ebdSchin sh_onoption(SH_XTRACE);
2316da2e3ebdSchin }
2317da2e3ebdSchin if(*cp)
2318da2e3ebdSchin sfputr(sfstderr,cp,-1);
2319da2e3ebdSchin if(argv)
2320da2e3ebdSchin {
2321da2e3ebdSchin char *argv0 = *argv;
2322da2e3ebdSchin nl = (nl?'\n':-1);
2323da2e3ebdSchin /* don't quote [ and [[ */
2324da2e3ebdSchin if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
2325da2e3ebdSchin {
2326da2e3ebdSchin sfputr(sfstderr,cp,*++argv?' ':nl);
2327da2e3ebdSchin bracket = 1;
2328da2e3ebdSchin }
2329da2e3ebdSchin while(cp = *argv++)
2330da2e3ebdSchin {
2331da2e3ebdSchin if(bracket==0 || *argv || *cp!=']')
2332da2e3ebdSchin cp = sh_fmtq(cp);
23337c2fbfb3SApril Chin if(decl && shp->prefix && cp!=argv0 && *cp!='-')
2334da2e3ebdSchin {
2335da2e3ebdSchin if(*cp=='.' && cp[1]==0)
23367c2fbfb3SApril Chin cp = shp->prefix;
2337da2e3ebdSchin else
23387c2fbfb3SApril Chin sfputr(sfstderr,shp->prefix,'.');
2339da2e3ebdSchin }
2340da2e3ebdSchin sfputr(sfstderr,cp,*argv?' ':nl);
2341da2e3ebdSchin }
2342da2e3ebdSchin sfset(sfstderr,SF_SHARE|SF_PUBLIC,1);
2343da2e3ebdSchin }
2344da2e3ebdSchin return(1);
2345da2e3ebdSchin }
2346da2e3ebdSchin return(0);
2347da2e3ebdSchin }
2348da2e3ebdSchin
2349da2e3ebdSchin /*
2350da2e3ebdSchin * This routine creates a subshell by calling fork() or vfork()
2351da2e3ebdSchin * If ((flags&COMASK)==TCOM), then vfork() is permitted
2352da2e3ebdSchin * If fork fails, the shell sleeps for exponentially longer periods
2353da2e3ebdSchin * and tries again until a limit is reached.
2354da2e3ebdSchin * SH_FORKLIM is the max period between forks - power of 2 usually.
2355da2e3ebdSchin * Currently shell tries after 2,4,8,16, and 32 seconds and then quits
2356da2e3ebdSchin * Failures cause the routine to error exit.
2357da2e3ebdSchin * Parent links to here-documents are removed by the child
2358da2e3ebdSchin * Traps are reset by the child
2359da2e3ebdSchin * The process-id of the child is returned to the parent, 0 to the child.
2360da2e3ebdSchin */
2361da2e3ebdSchin
timed_out(void * handle)2362da2e3ebdSchin static void timed_out(void *handle)
2363da2e3ebdSchin {
2364da2e3ebdSchin NOT_USED(handle);
2365da2e3ebdSchin timeout = 0;
2366da2e3ebdSchin }
2367da2e3ebdSchin
2368da2e3ebdSchin
2369da2e3ebdSchin /*
2370da2e3ebdSchin * called by parent and child after fork by sh_fork()
2371da2e3ebdSchin */
_sh_fork(register pid_t parent,int flags,int * jobid)2372da2e3ebdSchin pid_t _sh_fork(register pid_t parent,int flags,int *jobid)
2373da2e3ebdSchin {
2374da2e3ebdSchin static long forkcnt = 1000L;
23757c2fbfb3SApril Chin Shell_t *shp = &sh;
2376da2e3ebdSchin pid_t curpgid = job.curpgid;
2377da2e3ebdSchin pid_t postid = (flags&FAMP)?0:curpgid;
23787c2fbfb3SApril Chin int sig,nochild;
2379da2e3ebdSchin if(parent<0)
2380da2e3ebdSchin {
23817c2fbfb3SApril Chin sh_sigcheck();
2382da2e3ebdSchin if((forkcnt *= 2) > 1000L*SH_FORKLIM)
2383da2e3ebdSchin {
2384da2e3ebdSchin forkcnt=1000L;
2385da2e3ebdSchin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork);
2386da2e3ebdSchin }
2387da2e3ebdSchin timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
23887c2fbfb3SApril Chin nochild = job_wait((pid_t)1);
2389da2e3ebdSchin if(timeout)
2390da2e3ebdSchin {
23917c2fbfb3SApril Chin if(nochild)
23927c2fbfb3SApril Chin pause();
23937c2fbfb3SApril Chin else if(forkcnt>1000L)
2394da2e3ebdSchin forkcnt /= 2;
23957c2fbfb3SApril Chin timerdel(timeout);
23967c2fbfb3SApril Chin timeout = 0;
2397da2e3ebdSchin }
2398da2e3ebdSchin return(-1);
2399da2e3ebdSchin }
2400da2e3ebdSchin forkcnt = 1000L;
2401da2e3ebdSchin if(parent)
2402da2e3ebdSchin {
24037c2fbfb3SApril Chin int myjob,waitall=job.waitall;
24047c2fbfb3SApril Chin shp->nforks++;
2405da2e3ebdSchin if(job.toclear)
2406da2e3ebdSchin job_clear();
24077c2fbfb3SApril Chin job.waitall = waitall;
2408da2e3ebdSchin #ifdef JOBS
2409da2e3ebdSchin /* first process defines process group */
2410da2e3ebdSchin if(sh_isstate(SH_MONITOR))
2411da2e3ebdSchin {
2412da2e3ebdSchin /*
2413da2e3ebdSchin * errno==EPERM means that an earlier processes
2414da2e3ebdSchin * completed. Make parent the job group id.
2415da2e3ebdSchin */
2416da2e3ebdSchin if(postid==0)
2417da2e3ebdSchin job.curpgid = parent;
2418da2e3ebdSchin if(job.jobcontrol || (flags&FAMP))
2419da2e3ebdSchin {
2420da2e3ebdSchin if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
2421da2e3ebdSchin setpgid(parent,parent);
2422da2e3ebdSchin }
2423da2e3ebdSchin }
2424da2e3ebdSchin #endif /* JOBS */
2425da2e3ebdSchin if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
2426da2e3ebdSchin job.curpgid = parent;
2427da2e3ebdSchin if(flags&FCOOP)
24287c2fbfb3SApril Chin shp->cpid = parent;
242934f9b3eeSRoland Mainz #ifdef SHOPT_BGX
243034f9b3eeSRoland Mainz if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
243134f9b3eeSRoland Mainz postid = 1;
2432da2e3ebdSchin myjob = job_post(parent,postid);
243334f9b3eeSRoland Mainz if(postid==1)
243434f9b3eeSRoland Mainz postid = 0;
243534f9b3eeSRoland Mainz #else
243634f9b3eeSRoland Mainz myjob = job_post(parent,postid);
243734f9b3eeSRoland Mainz #endif /* SHOPT_BGX */
2438da2e3ebdSchin if(flags&FAMP)
2439da2e3ebdSchin job.curpgid = curpgid;
2440da2e3ebdSchin if(jobid)
2441da2e3ebdSchin *jobid = myjob;
2442da2e3ebdSchin return(parent);
2443da2e3ebdSchin }
2444da2e3ebdSchin #if !_std_malloc
2445da2e3ebdSchin vmtrace(-1);
2446da2e3ebdSchin #endif
2447da2e3ebdSchin /* This is the child process */
24487c2fbfb3SApril Chin if(shp->trapnote&SH_SIGTERM)
2449da2e3ebdSchin sh_exit(SH_EXITSIG|SIGTERM);
24507c2fbfb3SApril Chin shp->nforks=0;
2451da2e3ebdSchin timerdel(NIL(void*));
2452da2e3ebdSchin #ifdef JOBS
2453da2e3ebdSchin if(!job.jobcontrol && !(flags&FAMP))
2454da2e3ebdSchin sh_offstate(SH_MONITOR);
2455da2e3ebdSchin if(sh_isstate(SH_MONITOR))
2456da2e3ebdSchin {
2457da2e3ebdSchin parent = getpid();
2458da2e3ebdSchin if(postid==0)
2459da2e3ebdSchin job.curpgid = parent;
2460da2e3ebdSchin while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent)
2461da2e3ebdSchin job.curpgid = parent;
2462da2e3ebdSchin # ifdef SIGTSTP
2463da2e3ebdSchin if(job.curpgid==parent && !(flags&FAMP))
2464da2e3ebdSchin tcsetpgrp(job.fd,job.curpgid);
2465da2e3ebdSchin # endif /* SIGTSTP */
2466da2e3ebdSchin }
2467da2e3ebdSchin # ifdef SIGTSTP
2468da2e3ebdSchin if(job.jobcontrol)
2469da2e3ebdSchin {
2470da2e3ebdSchin signal(SIGTTIN,SIG_DFL);
2471da2e3ebdSchin signal(SIGTTOU,SIG_DFL);
2472da2e3ebdSchin signal(SIGTSTP,SIG_DFL);
2473da2e3ebdSchin }
2474da2e3ebdSchin # endif /* SIGTSTP */
2475da2e3ebdSchin job.jobcontrol = 0;
2476da2e3ebdSchin #endif /* JOBS */
2477da2e3ebdSchin job.toclear = 1;
24787c2fbfb3SApril Chin shp->login_sh = 0;
2479da2e3ebdSchin sh_offoption(SH_LOGIN_SHELL);
2480da2e3ebdSchin sh_onstate(SH_FORKED);
2481da2e3ebdSchin sh_onstate(SH_NOLOG);
24827c2fbfb3SApril Chin if (shp->fn_reset)
24837c2fbfb3SApril Chin shp->fn_depth = shp->fn_reset = 0;
2484da2e3ebdSchin #if SHOPT_ACCT
2485da2e3ebdSchin sh_accsusp();
2486da2e3ebdSchin #endif /* SHOPT_ACCT */
2487da2e3ebdSchin /* Reset remaining signals to parent */
2488da2e3ebdSchin /* except for those `lost' by trap */
248934f9b3eeSRoland Mainz if(!(flags&FSHOWME))
2490da2e3ebdSchin sh_sigreset(2);
24917c2fbfb3SApril Chin shp->subshell = 0;
24927c2fbfb3SApril Chin if((flags&FAMP) && shp->coutpipe>1)
24937c2fbfb3SApril Chin sh_close(shp->coutpipe);
24947c2fbfb3SApril Chin sig = shp->savesig;
24957c2fbfb3SApril Chin shp->savesig = 0;
2496da2e3ebdSchin if(sig>0)
2497da2e3ebdSchin sh_fault(sig);
2498da2e3ebdSchin sh_sigcheck();
2499da2e3ebdSchin return(0);
2500da2e3ebdSchin }
2501da2e3ebdSchin
sh_fork(int flags,int * jobid)2502da2e3ebdSchin pid_t sh_fork(int flags, int *jobid)
2503da2e3ebdSchin {
2504da2e3ebdSchin register pid_t parent;
2505da2e3ebdSchin register int sig;
2506da2e3ebdSchin #if SHOPT_FASTPIPE
2507da2e3ebdSchin if(sffileno(sfstdin)<0)
2508da2e3ebdSchin {
2509da2e3ebdSchin off_t current = sfseek(sfstdin,(off_t)0,SEEK_CUR);
2510da2e3ebdSchin sfseek(sfstdin,(off_t)0,SEEK_END);
2511da2e3ebdSchin sfdisc(sfstdin,SF_POPDISC);
2512da2e3ebdSchin fcntl(sffileno(sfstdin),F_SETFD,0);
2513da2e3ebdSchin sh_iostream(0);
2514da2e3ebdSchin sfseek(sfstdin,current,SEEK_SET);
2515da2e3ebdSchin }
2516da2e3ebdSchin #endif /* SHOPT_FASTPIPE */
2517da2e3ebdSchin if(!sh.pathlist)
2518da2e3ebdSchin path_get("");
2519da2e3ebdSchin sfsync(NIL(Sfio_t*));
2520da2e3ebdSchin sh.trapnote &= ~SH_SIGTERM;
2521da2e3ebdSchin job_fork(-1);
2522da2e3ebdSchin sh.savesig = -1;
2523da2e3ebdSchin while(_sh_fork(parent=fork(),flags,jobid) < 0);
25247c2fbfb3SApril Chin sh_stats(STAT_FORKS);
2525da2e3ebdSchin sig = sh.savesig;
2526da2e3ebdSchin sh.savesig = 0;
2527da2e3ebdSchin if(sig>0)
2528da2e3ebdSchin sh_fault(sig);
2529da2e3ebdSchin job_fork(parent);
2530da2e3ebdSchin return(parent);
2531da2e3ebdSchin }
2532da2e3ebdSchin
2533da2e3ebdSchin /*
2534da2e3ebdSchin * add exports from previous scope to the new scope
2535da2e3ebdSchin */
local_exports(register Namval_t * np,void * data)2536da2e3ebdSchin static void local_exports(register Namval_t *np, void *data)
2537da2e3ebdSchin {
2538da2e3ebdSchin register Namval_t *mp;
2539da2e3ebdSchin register char *cp;
2540da2e3ebdSchin if(nv_isarray(np))
2541da2e3ebdSchin nv_putsub(np,NIL(char*),0);
2542da2e3ebdSchin if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), sh.var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
2543da2e3ebdSchin nv_putval(mp, cp, 0);
2544da2e3ebdSchin }
2545da2e3ebdSchin
2546da2e3ebdSchin /*
2547da2e3ebdSchin * This routine is used to execute the given function <fun> in a new scope
2548da2e3ebdSchin * If <fun> is NULL, then arg points to a structure containing a pointer
2549da2e3ebdSchin * to a function that will be executed in the current environment.
2550da2e3ebdSchin */
sh_funscope(int argn,char * argv[],int (* fun)(void *),void * arg,int execflg)2551da2e3ebdSchin int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
2552da2e3ebdSchin {
2553da2e3ebdSchin register char *trap;
2554da2e3ebdSchin register int nsig;
25557c2fbfb3SApril Chin register Shell_t *shp = &sh;
2556da2e3ebdSchin struct dolnod *argsav=0,*saveargfor;
25577c2fbfb3SApril Chin struct sh_scoped savst, *prevscope = shp->st.self;
2558da2e3ebdSchin struct argnod *envlist=0;
2559da2e3ebdSchin int jmpval;
25607c2fbfb3SApril Chin volatile int r = 0;
2561da2e3ebdSchin char *savstak;
2562da2e3ebdSchin struct funenv *fp;
2563da2e3ebdSchin struct checkpt buff;
25647c2fbfb3SApril Chin Namval_t *nspace = shp->namespace;
256534f9b3eeSRoland Mainz Dt_t *last_root = shp->last_root;
256634f9b3eeSRoland Mainz Shopt_t options = shp->options;
25677c2fbfb3SApril Chin if(shp->fn_depth==0)
25687c2fbfb3SApril Chin shp->glob_options = shp->options;
25697c2fbfb3SApril Chin else
25707c2fbfb3SApril Chin shp->options = shp->glob_options;
25717c2fbfb3SApril Chin #if 0
25727c2fbfb3SApril Chin shp->st.lineno = error_info.line;
25737c2fbfb3SApril Chin #endif
25747c2fbfb3SApril Chin *prevscope = shp->st;
2575da2e3ebdSchin sh_offoption(SH_ERREXIT);
25767c2fbfb3SApril Chin shp->st.prevst = prevscope;
25777c2fbfb3SApril Chin shp->st.self = &savst;
25787c2fbfb3SApril Chin shp->topscope = (Shscope_t*)shp->st.self;
25797c2fbfb3SApril Chin shp->st.opterror = shp->st.optchar = 0;
25807c2fbfb3SApril Chin shp->st.optindex = 1;
25817c2fbfb3SApril Chin shp->st.loopcnt = 0;
2582da2e3ebdSchin if(!fun)
2583da2e3ebdSchin {
2584da2e3ebdSchin fp = (struct funenv*)arg;
25857c2fbfb3SApril Chin shp->st.real_fun = (fp->node)->nvalue.rp;
2586da2e3ebdSchin envlist = fp->env;
2587da2e3ebdSchin }
25887c2fbfb3SApril Chin prevscope->save_tree = shp->var_tree;
25897c2fbfb3SApril Chin sh_scope(shp,envlist,1);
25907c2fbfb3SApril Chin if(dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0))
2591da2e3ebdSchin {
2592da2e3ebdSchin /* eliminate parent scope */
2593da2e3ebdSchin nv_scan(prevscope->save_tree, local_exports,(void*)0, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
2594da2e3ebdSchin }
25957c2fbfb3SApril Chin shp->st.save_tree = shp->var_tree;
2596da2e3ebdSchin if(!fun)
2597da2e3ebdSchin {
2598da2e3ebdSchin Namval_t *np;
2599da2e3ebdSchin if(nv_isattr(fp->node,NV_TAGGED))
2600da2e3ebdSchin sh_onoption(SH_XTRACE);
2601da2e3ebdSchin else
2602da2e3ebdSchin sh_offoption(SH_XTRACE);
2603da2e3ebdSchin #if SHOPT_NAMESPACE
26047c2fbfb3SApril Chin if((np=(fp->node)->nvalue.rp->nspace) && np!=shp->namespace)
2605da2e3ebdSchin {
26067c2fbfb3SApril Chin Dt_t *dt = shp->var_tree;
2607da2e3ebdSchin dtview(dt,0);
2608da2e3ebdSchin dtview(dt,nv_dict(np));
26097c2fbfb3SApril Chin shp->var_tree = nv_dict(np);
26107c2fbfb3SApril Chin shp->namespace = np;
2611da2e3ebdSchin }
2612da2e3ebdSchin #endif /* SHOPT_NAMESPACE */
2613da2e3ebdSchin }
26147c2fbfb3SApril Chin shp->st.cmdname = argv[0];
2615da2e3ebdSchin /* save trap table */
26167c2fbfb3SApril Chin if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
2617da2e3ebdSchin {
2618da2e3ebdSchin nsig += sizeof(char*);
26197c2fbfb3SApril Chin memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
2620da2e3ebdSchin }
2621da2e3ebdSchin sh_sigreset(0);
26227c2fbfb3SApril Chin argsav = sh_argnew(shp,argv,&saveargfor);
2623da2e3ebdSchin sh_pushcontext(&buff,SH_JMPFUN);
2624da2e3ebdSchin errorpush(&buff.err,0);
2625da2e3ebdSchin error_info.id = argv[0];
26267c2fbfb3SApril Chin shp->st.var_local = shp->var_tree;
2627da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
2628da2e3ebdSchin if(!fun)
2629da2e3ebdSchin {
26307c2fbfb3SApril Chin shp->st.filename = fp->node->nvalue.rp->fname;
26317c2fbfb3SApril Chin shp->st.funname = nv_name(fp->node);
26327c2fbfb3SApril Chin nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
26337c2fbfb3SApril Chin nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
2634da2e3ebdSchin }
2635da2e3ebdSchin if(jmpval == 0)
2636da2e3ebdSchin {
26377c2fbfb3SApril Chin if(shp->fn_depth++ > MAXDEPTH)
263834f9b3eeSRoland Mainz {
263934f9b3eeSRoland Mainz shp->toomany = 1;
26407c2fbfb3SApril Chin siglongjmp(*shp->jmplist,SH_JMPERRFN);
264134f9b3eeSRoland Mainz }
2642da2e3ebdSchin else if(fun)
2643da2e3ebdSchin r= (*fun)(arg);
2644da2e3ebdSchin else
2645da2e3ebdSchin {
2646da2e3ebdSchin sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
26477c2fbfb3SApril Chin r = shp->exitval;
2648da2e3ebdSchin }
2649da2e3ebdSchin }
26507c2fbfb3SApril Chin if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN)
2651da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]);
2652da2e3ebdSchin sh_popcontext(&buff);
26537c2fbfb3SApril Chin if (shp->st.self != &savst)
26547c2fbfb3SApril Chin shp->var_tree = (Dt_t*)savst.save_tree;
26557c2fbfb3SApril Chin sh_unscope(shp);
26567c2fbfb3SApril Chin shp->namespace = nspace;
26577c2fbfb3SApril Chin shp->var_tree = (Dt_t*)prevscope->save_tree;
26587c2fbfb3SApril Chin if(shp->topscope != (Shscope_t*)shp->st.self)
26597c2fbfb3SApril Chin sh_setscope(shp->topscope);
26607c2fbfb3SApril Chin sh_argreset(shp,argsav,saveargfor);
26617c2fbfb3SApril Chin trap = shp->st.trapcom[0];
26627c2fbfb3SApril Chin shp->st.trapcom[0] = 0;
2663da2e3ebdSchin sh_sigreset(1);
26647c2fbfb3SApril Chin if (shp->st.self != &savst)
26657c2fbfb3SApril Chin *shp->st.self = shp->st;
26667c2fbfb3SApril Chin shp->st = *prevscope;
26677c2fbfb3SApril Chin shp->topscope = (Shscope_t*)prevscope;
26687c2fbfb3SApril Chin nv_getval(sh_scoped(shp,IFSNOD));
2669da2e3ebdSchin if(nsig)
26707c2fbfb3SApril Chin memcpy((char*)&shp->st.trapcom[0],savstak,nsig);
26717c2fbfb3SApril Chin shp->trapnote=0;
2672da2e3ebdSchin if(nsig)
2673da2e3ebdSchin stakset(savstak,0);
267434f9b3eeSRoland Mainz shp->options = options;
267534f9b3eeSRoland Mainz shp->last_root = last_root;
2676*3e14f97fSRoger A. Faulkner if(jmpval == SH_JMPSUB)
2677*3e14f97fSRoger A. Faulkner siglongjmp(*shp->jmplist,jmpval);
2678da2e3ebdSchin if(trap)
2679da2e3ebdSchin {
2680da2e3ebdSchin sh_trap(trap,0);
2681da2e3ebdSchin free(trap);
2682da2e3ebdSchin }
26837c2fbfb3SApril Chin if(shp->exitval > SH_EXITSIG)
26847c2fbfb3SApril Chin sh_fault(shp->exitval&SH_EXITMASK);
2685da2e3ebdSchin if(jmpval > SH_JMPFUN)
2686da2e3ebdSchin {
2687da2e3ebdSchin sh_chktrap();
26887c2fbfb3SApril Chin siglongjmp(*shp->jmplist,jmpval);
2689da2e3ebdSchin }
2690da2e3ebdSchin return(r);
2691da2e3ebdSchin }
2692da2e3ebdSchin
sh_funct(Shell_t * shp,Namval_t * np,int argn,char * argv[],struct argnod * envlist,int execflg)26937c2fbfb3SApril Chin static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
2694da2e3ebdSchin {
2695da2e3ebdSchin struct funenv fun;
2696da2e3ebdSchin char *fname = nv_getval(SH_FUNNAMENOD);
26977c2fbfb3SApril Chin struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun);
269834f9b3eeSRoland Mainz int level, pipepid=shp->pipepid;
269934f9b3eeSRoland Mainz shp->pipepid = 0;
27007c2fbfb3SApril Chin sh_stats(STAT_FUNCT);
27017c2fbfb3SApril Chin if(!lp->hdr.disc)
27027c2fbfb3SApril Chin lp = init_level(0);
27037c2fbfb3SApril Chin if((struct sh_scoped*)shp->topscope != shp->st.self)
27047c2fbfb3SApril Chin sh_setscope(shp->topscope);
27057c2fbfb3SApril Chin level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
27067c2fbfb3SApril Chin SH_LEVELNOD->nvalue.s = lp->maxlevel;
27077c2fbfb3SApril Chin shp->st.lineno = error_info.line;
2708da2e3ebdSchin if(nv_isattr(np,NV_FPOSIX))
2709da2e3ebdSchin {
2710da2e3ebdSchin char *save;
27117c2fbfb3SApril Chin int loopcnt = shp->st.loopcnt;
27127c2fbfb3SApril Chin shp->posix_fun = np;
2713da2e3ebdSchin save = argv[-1];
2714da2e3ebdSchin argv[-1] = 0;
27157c2fbfb3SApril Chin shp->st.funname = nv_name(np);
2716da2e3ebdSchin nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE);
27177c2fbfb3SApril Chin opt_info.index = opt_info.offset = 0;
27187c2fbfb3SApril Chin error_info.errors = 0;
27197c2fbfb3SApril Chin shp->st.loopcnt = 0;
27207c2fbfb3SApril Chin b_dot_cmd(argn+1,argv-1,&shp->bltindata);
27217c2fbfb3SApril Chin shp->st.loopcnt = loopcnt;
2722da2e3ebdSchin argv[-1] = save;
2723da2e3ebdSchin }
2724da2e3ebdSchin else
2725da2e3ebdSchin {
2726da2e3ebdSchin fun.env = envlist;
2727da2e3ebdSchin fun.node = np;
2728da2e3ebdSchin sh_funscope(argn,argv,0,&fun,execflg);
2729da2e3ebdSchin }
27307c2fbfb3SApril Chin if(level-- != nv_getnum(SH_LEVELNOD))
27317c2fbfb3SApril Chin {
27327c2fbfb3SApril Chin Shscope_t *sp = sh_getscope(0,SEEK_END);
27337c2fbfb3SApril Chin sh_setscope(sp);
27347c2fbfb3SApril Chin }
27357c2fbfb3SApril Chin lp->maxlevel = level;
27367c2fbfb3SApril Chin SH_LEVELNOD->nvalue.s = lp->maxlevel;
27377c2fbfb3SApril Chin #if 0
27387c2fbfb3SApril Chin nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
27397c2fbfb3SApril Chin #else
2740da2e3ebdSchin nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE);
27417c2fbfb3SApril Chin #endif
27427c2fbfb3SApril Chin nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
274334f9b3eeSRoland Mainz shp->pipepid = pipepid;
2744da2e3ebdSchin }
2745da2e3ebdSchin
2746da2e3ebdSchin /*
2747da2e3ebdSchin * external interface to execute a function without arguments
2748da2e3ebdSchin * <np> is the function node
2749da2e3ebdSchin * If <nq> is not-null, then sh.name and sh.subscript will be set
2750da2e3ebdSchin */
sh_fun(Namval_t * np,Namval_t * nq,char * argv[])2751da2e3ebdSchin int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
2752da2e3ebdSchin {
27537c2fbfb3SApril Chin Shell_t *shp = &sh;
2754da2e3ebdSchin register int offset;
2755da2e3ebdSchin register char *base;
2756da2e3ebdSchin Namval_t node;
27577c2fbfb3SApril Chin struct Namref nr;
27587c2fbfb3SApril Chin long mode;
27597c2fbfb3SApril Chin char *prefix = shp->prefix;
2760da2e3ebdSchin int n=0;
2761da2e3ebdSchin char *av[2];
2762da2e3ebdSchin Fcin_t save;
2763da2e3ebdSchin fcsave(&save);
2764da2e3ebdSchin if((offset=staktell())>0)
2765da2e3ebdSchin base=stakfreeze(0);
27667c2fbfb3SApril Chin shp->prefix = 0;
2767da2e3ebdSchin if(!argv)
2768da2e3ebdSchin {
2769da2e3ebdSchin argv = av;
2770da2e3ebdSchin argv[1]=0;
2771da2e3ebdSchin }
2772da2e3ebdSchin argv[0] = nv_name(np);
2773da2e3ebdSchin while(argv[n])
2774da2e3ebdSchin n++;
2775da2e3ebdSchin if(nq)
2776*3e14f97fSRoger A. Faulkner mode = set_instance(shp,nq,&node, &nr);
2777da2e3ebdSchin if(is_abuiltin(np))
2778da2e3ebdSchin {
2779da2e3ebdSchin int jmpval;
2780da2e3ebdSchin struct checkpt buff;
27817c2fbfb3SApril Chin Shbltin_t *bp = &sh.bltindata;
2782da2e3ebdSchin sh_pushcontext(&buff,SH_JMPCMD);
2783da2e3ebdSchin jmpval = sigsetjmp(buff.buff,1);
2784da2e3ebdSchin if(jmpval == 0)
2785da2e3ebdSchin {
27867c2fbfb3SApril Chin bp->bnode = np;
27877c2fbfb3SApril Chin bp->ptr = nv_context(np);
2788da2e3ebdSchin errorpush(&buff.err,0);
2789da2e3ebdSchin error_info.id = argv[0];
2790da2e3ebdSchin opt_info.index = opt_info.offset = 0;
2791da2e3ebdSchin opt_info.disc = 0;
2792da2e3ebdSchin sh.exitval = 0;
27937c2fbfb3SApril Chin sh.exitval = (*funptr(np))(n,argv,(void*)bp);
2794da2e3ebdSchin }
2795da2e3ebdSchin sh_popcontext(&buff);
2796da2e3ebdSchin if(jmpval>SH_JMPCMD)
2797da2e3ebdSchin siglongjmp(*sh.jmplist,jmpval);
2798da2e3ebdSchin }
2799da2e3ebdSchin else
28007c2fbfb3SApril Chin sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
2801da2e3ebdSchin if(nq)
28027c2fbfb3SApril Chin unset_instance(nq, &node, &nr, mode);
2803da2e3ebdSchin fcrestore(&save);
2804da2e3ebdSchin if(offset>0)
2805da2e3ebdSchin stakset(base,offset);
28067c2fbfb3SApril Chin shp->prefix = prefix;
2807da2e3ebdSchin return(sh.exitval);
2808da2e3ebdSchin }
2809da2e3ebdSchin
2810da2e3ebdSchin /*
2811da2e3ebdSchin * This dummy routine is called by built-ins that do recursion
2812da2e3ebdSchin * on the file system (chmod, chgrp, chown). It causes
2813da2e3ebdSchin * the shell to invoke the non-builtin version in this case
2814da2e3ebdSchin */
cmdrecurse(int argc,char * argv[],int ac,char * av[])2815da2e3ebdSchin int cmdrecurse(int argc, char* argv[], int ac, char* av[])
2816da2e3ebdSchin {
2817da2e3ebdSchin NOT_USED(argc);
2818da2e3ebdSchin NOT_USED(argv[0]);
2819da2e3ebdSchin NOT_USED(ac);
2820da2e3ebdSchin NOT_USED(av[0]);
2821da2e3ebdSchin return(SH_RUNPROG);
2822da2e3ebdSchin }
2823da2e3ebdSchin
2824da2e3ebdSchin /*
2825da2e3ebdSchin * set up pipe for cooperating process
2826da2e3ebdSchin */
coproc_init(Shell_t * shp,int pipes[])28277c2fbfb3SApril Chin static void coproc_init(Shell_t *shp, int pipes[])
2828da2e3ebdSchin {
2829da2e3ebdSchin int outfd;
28307c2fbfb3SApril Chin if(shp->coutpipe>=0 && shp->cpid)
2831da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_pexists);
28327c2fbfb3SApril Chin shp->cpid = 0;
28337c2fbfb3SApril Chin if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0)
2834da2e3ebdSchin {
2835da2e3ebdSchin /* first co-process */
28367c2fbfb3SApril Chin sh_pclose(shp->cpipe);
28377c2fbfb3SApril Chin sh_pipe(shp->cpipe);
28387c2fbfb3SApril Chin if((outfd=shp->cpipe[1]) < 10)
2839da2e3ebdSchin {
28407c2fbfb3SApril Chin int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
2841da2e3ebdSchin if(fd>=10)
2842da2e3ebdSchin {
28437c2fbfb3SApril Chin shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
2844da2e3ebdSchin close(outfd);
28457c2fbfb3SApril Chin shp->fdstatus[outfd] = IOCLOSE;
28467c2fbfb3SApril Chin shp->cpipe[1] = fd;
2847da2e3ebdSchin }
2848da2e3ebdSchin }
28497c2fbfb3SApril Chin if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0)
28507c2fbfb3SApril Chin shp->fdstatus[shp->cpipe[0]] |= IOCLEX;
28517c2fbfb3SApril Chin shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
2852da2e3ebdSchin
28537c2fbfb3SApril Chin if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0)
28547c2fbfb3SApril Chin shp->fdstatus[shp->cpipe[1]] |= IOCLEX;
2855da2e3ebdSchin }
28567c2fbfb3SApril Chin shp->outpipe = shp->cpipe;
28577c2fbfb3SApril Chin sh_pipe(shp->inpipe=pipes);
28587c2fbfb3SApril Chin shp->coutpipe = shp->inpipe[1];
28597c2fbfb3SApril Chin shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
28607c2fbfb3SApril Chin if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
28617c2fbfb3SApril Chin shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
2862da2e3ebdSchin }
2863da2e3ebdSchin
2864da2e3ebdSchin #if SHOPT_SPAWN
2865da2e3ebdSchin
2866da2e3ebdSchin
2867da2e3ebdSchin #if SHOPT_AMP || !defined(_lib_fork)
2868da2e3ebdSchin /*
2869da2e3ebdSchin * print out function definition
2870da2e3ebdSchin */
print_fun(register Namval_t * np,void * data)2871da2e3ebdSchin static void print_fun(register Namval_t* np, void *data)
2872da2e3ebdSchin {
2873da2e3ebdSchin register char *format;
2874da2e3ebdSchin NOT_USED(data);
2875da2e3ebdSchin if(!is_afunction(np) || !np->nvalue.ip)
2876da2e3ebdSchin return;
2877da2e3ebdSchin if(nv_isattr(np,NV_FPOSIX))
2878da2e3ebdSchin format="%s()\n{ ";
2879da2e3ebdSchin else
2880da2e3ebdSchin format="function %s\n{ ";
2881da2e3ebdSchin sfprintf(sfstdout,format,nv_name(np));
2882da2e3ebdSchin sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0);
2883da2e3ebdSchin sfwrite(sfstdout,"}\n",2);
2884da2e3ebdSchin }
2885da2e3ebdSchin
2886da2e3ebdSchin /*
2887da2e3ebdSchin * create a shell script consisting of t->fork.forktre and execute it
2888da2e3ebdSchin */
run_subshell(const Shnode_t * t,pid_t grp)2889da2e3ebdSchin static int run_subshell(const Shnode_t *t,pid_t grp)
2890da2e3ebdSchin {
28917c2fbfb3SApril Chin static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
2892da2e3ebdSchin register int i, fd, trace = sh_isoption(SH_XTRACE);
2893da2e3ebdSchin int pin,pout;
2894da2e3ebdSchin pid_t pid;
2895da2e3ebdSchin char *arglist[2], *envlist[2], devfd[12], *cp;
2896da2e3ebdSchin Sfio_t *sp = sftmp(0);
2897da2e3ebdSchin envlist[0] = "_=" SH_ID;
2898da2e3ebdSchin envlist[1] = 0;
2899da2e3ebdSchin arglist[0] = error_info.id?error_info.id:sh.shname;
2900da2e3ebdSchin if(*arglist[0]=='-')
2901da2e3ebdSchin arglist[0]++;
2902da2e3ebdSchin arglist[1] = devfd;
2903da2e3ebdSchin strncpy(devfd,e_devfdNN,sizeof(devfd));
2904da2e3ebdSchin arglist[2] = 0;
2905da2e3ebdSchin sfstack(sfstdout,sp);
2906da2e3ebdSchin if(trace)
2907da2e3ebdSchin sh_offoption(SH_XTRACE);
2908da2e3ebdSchin sfwrite(sfstdout,"typeset -A -- ",14);
2909da2e3ebdSchin sh_trap(prolog,0);
2910da2e3ebdSchin nv_scan(sh.fun_tree, print_fun, (void*)0,0, 0);
2911da2e3ebdSchin if(sh.st.dolc>0)
2912da2e3ebdSchin {
2913da2e3ebdSchin /* pass the positional parameters */
2914da2e3ebdSchin char **argv = sh.st.dolv+1;
2915da2e3ebdSchin sfwrite(sfstdout,"set --",6);
2916da2e3ebdSchin while(*argv)
2917da2e3ebdSchin sfprintf(sfstdout," %s",sh_fmtq(*argv++));
2918da2e3ebdSchin sfputc(sfstdout,'\n');
2919da2e3ebdSchin }
2920da2e3ebdSchin pin = (sh.inpipe?sh.inpipe[1]:0);
2921da2e3ebdSchin pout = (sh.outpipe?sh.outpipe[0]:0);
2922da2e3ebdSchin for(i=3; i < 10; i++)
2923da2e3ebdSchin {
2924da2e3ebdSchin if(sh.fdstatus[i]&IOCLEX && i!=pin && i!=pout)
2925da2e3ebdSchin {
2926da2e3ebdSchin sfprintf(sfstdout,"exec %d<&%d\n",i,i);
2927da2e3ebdSchin fcntl(i,F_SETFD,0);
2928da2e3ebdSchin }
2929da2e3ebdSchin }
2930da2e3ebdSchin sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline);
2931da2e3ebdSchin if(trace)
2932da2e3ebdSchin {
2933da2e3ebdSchin sfwrite(sfstdout,"set -x\n",7);
2934da2e3ebdSchin sh_onoption(SH_XTRACE);
2935da2e3ebdSchin }
2936da2e3ebdSchin sfstack(sfstdout,NIL(Sfio_t*));
2937da2e3ebdSchin sh_deparse(sp,t->fork.forktre,0);
2938da2e3ebdSchin sfseek(sp,(Sfoff_t)0,SEEK_SET);
2939da2e3ebdSchin fd = sh_dup(sffileno(sp));
2940da2e3ebdSchin cp = devfd+8;
2941da2e3ebdSchin if(fd>9)
2942da2e3ebdSchin *cp++ = '0' + (fd/10);
2943da2e3ebdSchin *cp++ = '0' + fd%10;
2944da2e3ebdSchin *cp = 0;
2945da2e3ebdSchin sfclose(sp);
2946da2e3ebdSchin sfsync(NIL(Sfio_t*));
2947da2e3ebdSchin if(!sh.shpath)
2948da2e3ebdSchin sh.shpath = pathshell();
2949da2e3ebdSchin pid = spawnveg(sh.shpath,arglist,envlist,grp);
2950da2e3ebdSchin close(fd);
2951da2e3ebdSchin for(i=3; i < 10; i++)
2952da2e3ebdSchin {
2953da2e3ebdSchin if(sh.fdstatus[i]&IOCLEX && i!=pin && i!=pout)
2954da2e3ebdSchin fcntl(i,F_SETFD,FD_CLOEXEC);
2955da2e3ebdSchin }
2956da2e3ebdSchin if(pid <=0)
2957da2e3ebdSchin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
2958da2e3ebdSchin return(pid);
2959da2e3ebdSchin }
2960da2e3ebdSchin #endif /* !_lib_fork */
2961da2e3ebdSchin
sigreset(int mode)2962da2e3ebdSchin static void sigreset(int mode)
2963da2e3ebdSchin {
2964da2e3ebdSchin register char *trap;
2965da2e3ebdSchin register int sig=sh.st.trapmax;
2966da2e3ebdSchin while(sig-- > 0)
2967da2e3ebdSchin {
2968da2e3ebdSchin if((trap=sh.st.trapcom[sig]) && *trap==0)
2969da2e3ebdSchin signal(sig,mode?sh_fault:SIG_IGN);
2970da2e3ebdSchin }
2971da2e3ebdSchin }
2972da2e3ebdSchin
2973da2e3ebdSchin /*
2974da2e3ebdSchin * A combined fork/exec for systems with slow or non-existent fork()
2975da2e3ebdSchin */
sh_ntfork(Shell_t * shp,const Shnode_t * t,char * argv[],int * jobid,int flag)29767c2fbfb3SApril Chin static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
2977da2e3ebdSchin {
2978da2e3ebdSchin static pid_t spawnpid;
2979da2e3ebdSchin static int savetype;
2980da2e3ebdSchin static int savejobid;
2981da2e3ebdSchin struct checkpt buff;
29827c2fbfb3SApril Chin int otype=0, jmpval;
29837c2fbfb3SApril Chin volatile int jobwasset=0, scope=0, sigwasset=0;
2984da2e3ebdSchin char **arge, *path;
29857c2fbfb3SApril Chin volatile pid_t grp = 0;
2986da2e3ebdSchin Pathcomp_t *pp;
2987da2e3ebdSchin if(flag)
2988da2e3ebdSchin {
2989da2e3ebdSchin otype = savetype;
2990da2e3ebdSchin savetype=0;
2991da2e3ebdSchin }
2992da2e3ebdSchin # if SHOPT_AMP || !defined(_lib_fork)
2993da2e3ebdSchin if(!argv)
2994da2e3ebdSchin {
2995da2e3ebdSchin register Shnode_t *tchild = t->fork.forktre;
2996da2e3ebdSchin int optimize=0;
2997da2e3ebdSchin otype = t->tre.tretyp;
2998da2e3ebdSchin savetype = otype;
2999da2e3ebdSchin spawnpid = 0;
3000da2e3ebdSchin # ifndef _lib_fork
3001da2e3ebdSchin if((tchild->tre.tretyp&COMMSK)==TCOM)
3002da2e3ebdSchin {
3003da2e3ebdSchin Namval_t *np = (Namval_t*)(tchild->com.comnamp);
3004da2e3ebdSchin if(np)
3005da2e3ebdSchin {
3006da2e3ebdSchin path = nv_name(np);
3007da2e3ebdSchin if(!nv_isattr(np,BLT_ENV))
3008da2e3ebdSchin np=0;
3009da2e3ebdSchin else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
3010da2e3ebdSchin np=0;
3011da2e3ebdSchin }
3012da2e3ebdSchin else if(!tchild->com.comarg)
3013da2e3ebdSchin optimize=1;
3014da2e3ebdSchin else if(tchild->com.comtyp&COMSCAN)
3015da2e3ebdSchin {
3016da2e3ebdSchin if(tchild->com.comarg->argflag&ARG_RAW)
3017da2e3ebdSchin path = tchild->com.comarg->argval;
3018da2e3ebdSchin else
3019da2e3ebdSchin path = 0;
3020da2e3ebdSchin }
3021da2e3ebdSchin else
3022da2e3ebdSchin path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
3023da2e3ebdSchin if(!np && path && !nv_search(path,shp->fun_tree,0))
3024da2e3ebdSchin optimize=1;
3025da2e3ebdSchin }
3026da2e3ebdSchin # endif
3027da2e3ebdSchin sh_pushcontext(&buff,SH_JMPIO);
3028da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
3029da2e3ebdSchin {
3030da2e3ebdSchin if((otype&FINT) && !sh_isstate(SH_MONITOR))
3031da2e3ebdSchin {
3032da2e3ebdSchin signal(SIGQUIT,SIG_IGN);
3033da2e3ebdSchin signal(SIGINT,SIG_IGN);
3034da2e3ebdSchin if(!shp->st.ioset)
3035da2e3ebdSchin {
30367c2fbfb3SApril Chin sh_iosave(shp,0,buff.topfd,(char*)0);
30377c2fbfb3SApril Chin sh_iorenumber(shp,sh_chkopen(e_devnull),0);
3038da2e3ebdSchin }
3039da2e3ebdSchin }
3040da2e3ebdSchin if(otype&FPIN)
3041da2e3ebdSchin {
3042da2e3ebdSchin int fd = shp->inpipe[1];
30437c2fbfb3SApril Chin sh_iosave(shp,0,buff.topfd,(char*)0);
30447c2fbfb3SApril Chin sh_iorenumber(shp,shp->inpipe[0],0);
3045da2e3ebdSchin if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
3046da2e3ebdSchin shp->fdstatus[fd] |= IOCLEX;
3047da2e3ebdSchin }
3048da2e3ebdSchin if(otype&FPOU)
3049da2e3ebdSchin {
30507c2fbfb3SApril Chin sh_iosave(shp,1,buff.topfd,(char*)0);
30517c2fbfb3SApril Chin sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1);
3052da2e3ebdSchin if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
3053da2e3ebdSchin shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
3054da2e3ebdSchin }
3055da2e3ebdSchin
3056da2e3ebdSchin if(t->fork.forkio)
30577c2fbfb3SApril Chin sh_redirect(shp,t->fork.forkio,0);
3058da2e3ebdSchin if(optimize==0)
3059da2e3ebdSchin {
3060da2e3ebdSchin #ifdef SIGTSTP
3061da2e3ebdSchin if(job.jobcontrol)
3062da2e3ebdSchin {
3063da2e3ebdSchin signal(SIGTTIN,SIG_DFL);
3064da2e3ebdSchin signal(SIGTTOU,SIG_DFL);
3065da2e3ebdSchin }
3066da2e3ebdSchin #endif /* SIGTSTP */
3067da2e3ebdSchin #ifdef JOBS
3068da2e3ebdSchin if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3069da2e3ebdSchin {
3070da2e3ebdSchin if((otype&FAMP) || job.curpgid==0)
3071da2e3ebdSchin grp = 1;
3072da2e3ebdSchin else
3073da2e3ebdSchin grp = job.curpgid;
3074da2e3ebdSchin }
3075da2e3ebdSchin #endif /* JOBS */
3076da2e3ebdSchin spawnpid = run_subshell(t,grp);
3077da2e3ebdSchin }
3078da2e3ebdSchin else
3079da2e3ebdSchin {
3080da2e3ebdSchin sh_exec(tchild,SH_NTFORK);
3081da2e3ebdSchin if(jobid)
3082da2e3ebdSchin *jobid = savejobid;
3083da2e3ebdSchin }
3084da2e3ebdSchin }
3085da2e3ebdSchin sh_popcontext(&buff);
3086da2e3ebdSchin if((otype&FINT) && !sh_isstate(SH_MONITOR))
3087da2e3ebdSchin {
3088da2e3ebdSchin signal(SIGQUIT,sh_fault);
3089da2e3ebdSchin signal(SIGINT,sh_fault);
3090da2e3ebdSchin }
3091da2e3ebdSchin if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
3092da2e3ebdSchin shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX;
3093da2e3ebdSchin if(t->fork.forkio || otype)
30947c2fbfb3SApril Chin sh_iorestore(shp,buff.topfd,jmpval);
3095da2e3ebdSchin if(optimize==0)
3096da2e3ebdSchin {
3097da2e3ebdSchin #ifdef SIGTSTP
3098da2e3ebdSchin if(job.jobcontrol)
3099da2e3ebdSchin {
3100da2e3ebdSchin signal(SIGTTIN,SIG_IGN);
3101da2e3ebdSchin signal(SIGTTOU,SIG_IGN);
3102da2e3ebdSchin }
3103da2e3ebdSchin #endif /* SIGTSTP */
3104da2e3ebdSchin if(spawnpid>0)
3105da2e3ebdSchin _sh_fork(spawnpid,otype,jobid);
3106da2e3ebdSchin if(grp>0 && !(otype&FAMP))
3107da2e3ebdSchin {
3108da2e3ebdSchin while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
3109da2e3ebdSchin job.curpgid = spawnpid;
3110da2e3ebdSchin }
3111da2e3ebdSchin }
3112da2e3ebdSchin savetype=0;
3113da2e3ebdSchin if(jmpval>SH_JMPIO)
3114da2e3ebdSchin siglongjmp(*shp->jmplist,jmpval);
3115da2e3ebdSchin if(spawnpid<0 && (otype&FCOOP))
3116da2e3ebdSchin {
3117da2e3ebdSchin sh_close(shp->coutpipe);
3118da2e3ebdSchin sh_close(shp->cpipe[1]);
3119da2e3ebdSchin shp->cpipe[1] = -1;
3120da2e3ebdSchin shp->coutpipe = -1;
3121da2e3ebdSchin }
3122da2e3ebdSchin shp->exitval = 0;
3123da2e3ebdSchin return(spawnpid);
3124da2e3ebdSchin }
3125da2e3ebdSchin # endif /* !_lib_fork */
3126da2e3ebdSchin sh_pushcontext(&buff,SH_JMPCMD);
3127da2e3ebdSchin errorpush(&buff.err,ERROR_SILENT);
3128da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
3129da2e3ebdSchin if(jmpval == 0)
3130da2e3ebdSchin {
3131da2e3ebdSchin if((otype&FINT) && !sh_isstate(SH_MONITOR))
3132da2e3ebdSchin {
3133da2e3ebdSchin signal(SIGQUIT,SIG_IGN);
3134da2e3ebdSchin signal(SIGINT,SIG_IGN);
3135da2e3ebdSchin }
3136da2e3ebdSchin spawnpid = -1;
3137da2e3ebdSchin if(t->com.comio)
31387c2fbfb3SApril Chin sh_redirect(shp,t->com.comio,0);
3139da2e3ebdSchin error_info.id = *argv;
3140da2e3ebdSchin if(t->com.comset)
3141da2e3ebdSchin {
3142da2e3ebdSchin scope++;
31437c2fbfb3SApril Chin sh_scope(shp,t->com.comset,0);
3144da2e3ebdSchin }
3145da2e3ebdSchin if(!strchr(path=argv[0],'/'))
3146da2e3ebdSchin {
3147da2e3ebdSchin Namval_t *np;
3148da2e3ebdSchin if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
3149da2e3ebdSchin path = nv_getval(np);
3150da2e3ebdSchin else if(path_absolute(path,NIL(Pathcomp_t*)))
3151da2e3ebdSchin {
31527c2fbfb3SApril Chin path = stkptr(shp->stk,PATH_OFFSET);
31537c2fbfb3SApril Chin stkfreeze(shp->stk,0);
3154da2e3ebdSchin }
3155da2e3ebdSchin else
3156da2e3ebdSchin {
3157da2e3ebdSchin pp=path_get(path);
3158da2e3ebdSchin while(pp)
3159da2e3ebdSchin {
3160da2e3ebdSchin if(pp->len==1 && *pp->name=='.')
3161da2e3ebdSchin break;
3162da2e3ebdSchin pp = pp->next;
3163da2e3ebdSchin }
3164da2e3ebdSchin if(!pp)
3165da2e3ebdSchin path = 0;
3166da2e3ebdSchin }
3167da2e3ebdSchin }
3168da2e3ebdSchin else if(sh_isoption(SH_RESTRICTED))
3169da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
3170da2e3ebdSchin if(!path)
3171da2e3ebdSchin {
3172da2e3ebdSchin spawnpid = -1;
3173da2e3ebdSchin goto fail;
3174da2e3ebdSchin }
3175da2e3ebdSchin arge = sh_envgen();
3176da2e3ebdSchin shp->exitval = 0;
3177da2e3ebdSchin #ifdef SIGTSTP
3178da2e3ebdSchin if(job.jobcontrol)
3179da2e3ebdSchin {
3180da2e3ebdSchin signal(SIGTTIN,SIG_DFL);
3181da2e3ebdSchin signal(SIGTTOU,SIG_DFL);
3182da2e3ebdSchin jobwasset++;
3183da2e3ebdSchin }
3184da2e3ebdSchin #endif /* SIGTSTP */
3185da2e3ebdSchin #ifdef JOBS
3186da2e3ebdSchin if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
3187da2e3ebdSchin {
3188da2e3ebdSchin if((otype&FAMP) || job.curpgid==0)
3189da2e3ebdSchin grp = 1;
3190da2e3ebdSchin else
3191da2e3ebdSchin grp = job.curpgid;
3192da2e3ebdSchin }
3193da2e3ebdSchin #endif /* JOBS */
3194da2e3ebdSchin
3195da2e3ebdSchin sfsync(NIL(Sfio_t*));
3196da2e3ebdSchin sigreset(0); /* set signals to ignore */
3197da2e3ebdSchin sigwasset++;
3198da2e3ebdSchin /* find first path that has a library component */
3199da2e3ebdSchin for(pp=path_get(argv[0]); pp && !pp->lib ; pp=pp->next);
3200da2e3ebdSchin spawnpid = path_spawn(path,argv,arge,pp,(grp<<1)|1);
3201da2e3ebdSchin if(spawnpid < 0 && errno==ENOEXEC)
3202da2e3ebdSchin {
3203da2e3ebdSchin char *devfd;
3204da2e3ebdSchin int fd = open(path,O_RDONLY);
3205da2e3ebdSchin argv[-1] = argv[0];
3206da2e3ebdSchin argv[0] = path;
3207da2e3ebdSchin if(fd>=0)
3208da2e3ebdSchin {
3209da2e3ebdSchin struct stat statb;
3210da2e3ebdSchin sfprintf(sh.strbuf,"/dev/fd/%d",fd);
3211da2e3ebdSchin if(stat(devfd=sfstruse(sh.strbuf),&statb)>=0)
3212da2e3ebdSchin argv[0] = devfd;
3213da2e3ebdSchin }
3214da2e3ebdSchin if(!shp->shpath)
3215da2e3ebdSchin shp->shpath = pathshell();
3216da2e3ebdSchin spawnpid = path_spawn(shp->shpath,&argv[-1],arge,pp,(grp<<1)|1);
3217da2e3ebdSchin if(fd>=0)
3218da2e3ebdSchin close(fd);
3219da2e3ebdSchin argv[0] = argv[-1];
3220da2e3ebdSchin }
3221da2e3ebdSchin fail:
3222da2e3ebdSchin if(spawnpid < 0) switch(errno=shp->path_err)
3223da2e3ebdSchin {
3224da2e3ebdSchin case ENOENT:
3225da2e3ebdSchin errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4);
3226da2e3ebdSchin default:
3227da2e3ebdSchin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
3228da2e3ebdSchin }
3229da2e3ebdSchin }
3230da2e3ebdSchin else
3231da2e3ebdSchin exitset();
3232da2e3ebdSchin sh_popcontext(&buff);
3233da2e3ebdSchin if(buff.olist)
3234da2e3ebdSchin free_list(buff.olist);
3235da2e3ebdSchin #ifdef SIGTSTP
3236da2e3ebdSchin if(jobwasset)
3237da2e3ebdSchin {
3238da2e3ebdSchin signal(SIGTTIN,SIG_IGN);
3239da2e3ebdSchin signal(SIGTTOU,SIG_IGN);
3240da2e3ebdSchin }
3241da2e3ebdSchin #endif /* SIGTSTP */
3242da2e3ebdSchin if(sigwasset)
3243da2e3ebdSchin sigreset(1); /* restore ignored signals */
3244da2e3ebdSchin if(scope)
3245da2e3ebdSchin {
32467c2fbfb3SApril Chin sh_unscope(shp);
3247da2e3ebdSchin if(jmpval==SH_JMPSCRIPT)
324834f9b3eeSRoland Mainz nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
3249da2e3ebdSchin }
3250da2e3ebdSchin if(t->com.comio)
32517c2fbfb3SApril Chin sh_iorestore(shp,buff.topfd,jmpval);
3252da2e3ebdSchin if(jmpval>SH_JMPCMD)
3253da2e3ebdSchin siglongjmp(*shp->jmplist,jmpval);
3254da2e3ebdSchin if(spawnpid>0)
3255da2e3ebdSchin {
3256da2e3ebdSchin _sh_fork(spawnpid,otype,jobid);
3257da2e3ebdSchin #ifdef JOBS
3258da2e3ebdSchin if(grp==1)
3259da2e3ebdSchin job.curpgid = spawnpid;
3260da2e3ebdSchin # ifdef SIGTSTP
3261da2e3ebdSchin if(grp>0 && !(otype&FAMP))
3262da2e3ebdSchin {
3263da2e3ebdSchin while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
3264da2e3ebdSchin job.curpgid = spawnpid;
3265da2e3ebdSchin }
3266da2e3ebdSchin # endif /* SIGTSTP */
3267da2e3ebdSchin #endif /* JOBS */
3268da2e3ebdSchin savejobid = *jobid;
3269da2e3ebdSchin if(otype)
3270da2e3ebdSchin return(0);
3271da2e3ebdSchin }
3272da2e3ebdSchin return(spawnpid);
3273da2e3ebdSchin }
3274da2e3ebdSchin
3275da2e3ebdSchin # ifdef _was_lib_fork
3276da2e3ebdSchin # define _lib_fork 1
3277da2e3ebdSchin # endif
3278da2e3ebdSchin # ifndef _lib_fork
fork(void)3279da2e3ebdSchin pid_t fork(void)
3280da2e3ebdSchin {
3281da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork");
3282da2e3ebdSchin return(-1);
3283da2e3ebdSchin }
3284da2e3ebdSchin # endif /* _lib_fork */
3285da2e3ebdSchin #endif /* SHOPT_SPAWN */
3286