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