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