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