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