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