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