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