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