14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * UNIX shell parse tree executer 234887Schin * 244887Schin * David Korn 254887Schin * AT&T Labs 264887Schin * 274887Schin */ 284887Schin 294887Schin #include "defs.h" 304887Schin #include <fcin.h> 314887Schin #include "variables.h" 324887Schin #include "path.h" 334887Schin #include "name.h" 344887Schin #include "io.h" 354887Schin #include "shnodes.h" 364887Schin #include "jobs.h" 374887Schin #include "test.h" 384887Schin #include "builtins.h" 394887Schin #include "FEATURE/time" 404887Schin #include "FEATURE/externs" 414887Schin #include "FEATURE/locale" 424887Schin #include "streval.h" 434887Schin 444887Schin #if !_std_malloc 454887Schin # include <vmalloc.h> 464887Schin #endif 474887Schin 488462SApril.Chin@Sun.COM #if _lib_vfork 498462SApril.Chin@Sun.COM # include <ast_vfork.h> 508462SApril.Chin@Sun.COM #else 518462SApril.Chin@Sun.COM # define vfork() fork() 528462SApril.Chin@Sun.COM #endif 538462SApril.Chin@Sun.COM 544887Schin #define SH_NTFORK SH_TIMING 554887Schin 564887Schin #if _lib_nice 574887Schin extern int nice(int); 584887Schin #endif /* _lib_nice */ 594887Schin #if !_lib_spawnveg 604887Schin # define spawnveg(a,b,c,d) spawnve(a,b,c) 614887Schin #endif /* !_lib_spawnveg */ 624887Schin #if SHOPT_SPAWN 638462SApril.Chin@Sun.COM static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int); 644887Schin #endif /* SHOPT_SPAWN */ 654887Schin 668462SApril.Chin@Sun.COM static void sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int); 674887Schin static int trim_eq(const char*, const char*); 688462SApril.Chin@Sun.COM static void coproc_init(Shell_t*, int pipes[]); 694887Schin 704887Schin static void *timeout; 714887Schin static char pipejob; 724887Schin 734887Schin struct funenv 744887Schin { 754887Schin Namval_t *node; 764887Schin struct argnod *env; 774887Schin }; 784887Schin 794887Schin /* ======== command execution ========*/ 804887Schin 814887Schin /* 824887Schin * print time <t> in h:m:s format with precision <p> 834887Schin */ 844887Schin static void l_time(Sfio_t *outfile,register clock_t t,int p) 854887Schin { 864887Schin register int min, sec, frac; 874887Schin register int hr; 884887Schin if(p) 894887Schin { 904887Schin frac = t%sh.lim.clk_tck; 914887Schin frac = (frac*100)/sh.lim.clk_tck; 924887Schin } 934887Schin t /= sh.lim.clk_tck; 944887Schin sec = t%60; 954887Schin t /= 60; 964887Schin min = t%60; 974887Schin if(hr=t/60) 984887Schin sfprintf(outfile,"%dh",hr); 994887Schin if(p) 1004887Schin sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac); 1014887Schin else 1024887Schin sfprintf(outfile,"%dm%ds",min,sec); 1034887Schin } 1044887Schin 1058462SApril.Chin@Sun.COM static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm) 1064887Schin { 1078462SApril.Chin@Sun.COM int c,p,l,n,offset = staktell(); 1088462SApril.Chin@Sun.COM const char *first; 1098462SApril.Chin@Sun.COM double d; 1108462SApril.Chin@Sun.COM Stk_t *stkp = shp->stk; 1114887Schin for(first=format ; c= *format; format++) 1124887Schin { 1134887Schin if(c!='%') 1144887Schin continue; 1158462SApril.Chin@Sun.COM sfwrite(stkp, first, format-first); 1164887Schin n = l = 0; 1174887Schin p = 3; 1184887Schin if((c= *++format) == '%') 1194887Schin { 1204887Schin first = format; 1214887Schin continue; 1224887Schin } 1234887Schin if(c>='0' && c <='9') 1244887Schin { 1254887Schin p = (c>'3')?3:(c-'0'); 1264887Schin c = *++format; 1274887Schin } 1284887Schin else if(c=='P') 1294887Schin { 1304887Schin if(d=tm[0]) 1314887Schin d = 100.*(((double)(tm[1]+tm[2]))/d); 1324887Schin p = 2; 1334887Schin goto skip; 1344887Schin } 1354887Schin if(c=='l') 1364887Schin { 1374887Schin l = 1; 1384887Schin c = *++format; 1394887Schin } 1404887Schin if(c=='U') 1414887Schin n = 1; 1424887Schin else if(c=='S') 1434887Schin n = 2; 1444887Schin else if(c!='R') 1454887Schin { 1468462SApril.Chin@Sun.COM stkseek(stkp,offset); 1474887Schin errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c); 1484887Schin return(0); 1494887Schin } 1504887Schin d = (double)tm[n]/sh.lim.clk_tck; 1514887Schin skip: 1524887Schin if(l) 1538462SApril.Chin@Sun.COM l_time(stkp, tm[n], p); 1544887Schin else 1558462SApril.Chin@Sun.COM sfprintf(stkp,"%.*f",p, d); 1564887Schin first = format+1; 1574887Schin } 1584887Schin if(format>first) 1598462SApril.Chin@Sun.COM sfwrite(stkp,first, format-first); 1608462SApril.Chin@Sun.COM sfputc(stkp,'\n'); 1618462SApril.Chin@Sun.COM n = stktell(stkp)-offset; 1628462SApril.Chin@Sun.COM sfwrite(out,stkptr(stkp,offset),n); 1638462SApril.Chin@Sun.COM stkseek(stkp,offset); 1644887Schin return(n); 1654887Schin } 1664887Schin 1674887Schin #if SHOPT_OPTIMIZE 1684887Schin /* 1694887Schin * clear argument pointers that point into the stack 1704887Schin */ 1714887Schin static int p_arg(struct argnod*,int); 1724887Schin static int p_switch(struct regnod*); 1734887Schin static int p_comarg(register struct comnod *com) 1744887Schin { 1754887Schin Namval_t *np=com->comnamp; 1764887Schin int n = p_arg(com->comset,ARG_ASSIGN); 1774887Schin if(com->comarg && (com->comtyp&COMSCAN)) 1784887Schin n+= p_arg(com->comarg,0); 1794887Schin if(com->comstate && np) 1804887Schin { 1814887Schin /* call builtin to cleanup state */ 1828462SApril.Chin@Sun.COM Shbltin_t *bp = &sh.bltindata; 1838462SApril.Chin@Sun.COM void *save_ptr = bp->ptr; 1848462SApril.Chin@Sun.COM void *save_data = bp->data; 1858462SApril.Chin@Sun.COM bp->bnode = np; 1868462SApril.Chin@Sun.COM bp->vnode = com->comnamq; 1878462SApril.Chin@Sun.COM bp->ptr = nv_context(np); 1888462SApril.Chin@Sun.COM bp->data = com->comstate; 1898462SApril.Chin@Sun.COM bp->flags = SH_END_OPTIM; 1908462SApril.Chin@Sun.COM (*funptr(np))(0,(char**)0, bp); 1918462SApril.Chin@Sun.COM bp->ptr = save_ptr; 1928462SApril.Chin@Sun.COM bp->data = save_data; 1934887Schin } 1944887Schin com->comstate = 0; 1954887Schin if(com->comarg && !np) 1964887Schin n++; 1974887Schin return(n); 1984887Schin } 1994887Schin 2004887Schin extern void sh_optclear(Shell_t*, void*); 2014887Schin 2024887Schin static int sh_tclear(register Shnode_t *t) 2034887Schin { 2044887Schin int n=0; 2054887Schin if(!t) 2064887Schin return(0); 2074887Schin switch(t->tre.tretyp&COMMSK) 2084887Schin { 2094887Schin case TTIME: 2104887Schin case TPAR: 2114887Schin return(sh_tclear(t->par.partre)); 2124887Schin case TCOM: 2134887Schin return(p_comarg((struct comnod*)t)); 2144887Schin case TSETIO: 2154887Schin case TFORK: 2164887Schin return(sh_tclear(t->fork.forktre)); 2174887Schin case TIF: 2184887Schin n=sh_tclear(t->if_.iftre); 2194887Schin n+=sh_tclear(t->if_.thtre); 2204887Schin n+=sh_tclear(t->if_.eltre); 2214887Schin return(n); 2224887Schin case TWH: 2234887Schin if(t->wh.whinc) 2244887Schin n=sh_tclear((Shnode_t*)(t->wh.whinc)); 2254887Schin n+=sh_tclear(t->wh.whtre); 2264887Schin n+=sh_tclear(t->wh.dotre); 2274887Schin return(n); 2284887Schin case TLST: 2294887Schin case TAND: 2304887Schin case TORF: 2314887Schin case TFIL: 2324887Schin n=sh_tclear(t->lst.lstlef); 2334887Schin return(n+sh_tclear(t->lst.lstrit)); 2344887Schin case TARITH: 2354887Schin return(p_arg(t->ar.arexpr,ARG_ARITH)); 2364887Schin case TFOR: 2374887Schin n=sh_tclear(t->for_.fortre); 2384887Schin return(n+sh_tclear((Shnode_t*)t->for_.forlst)); 2394887Schin case TSW: 2404887Schin n=p_arg(t->sw.swarg,0); 2414887Schin return(n+p_switch(t->sw.swlst)); 2424887Schin case TFUN: 2434887Schin n=sh_tclear(t->funct.functtre); 2444887Schin return(n+sh_tclear((Shnode_t*)t->funct.functargs)); 2454887Schin case TTST: 2464887Schin if((t->tre.tretyp&TPAREN)==TPAREN) 2474887Schin return(sh_tclear(t->lst.lstlef)); 2484887Schin else 2494887Schin { 2504887Schin n=p_arg(&(t->lst.lstlef->arg),0); 2514887Schin if(t->tre.tretyp&TBINARY) 2524887Schin n+=p_arg(&(t->lst.lstrit->arg),0); 2534887Schin } 2544887Schin } 2554887Schin return(n); 2564887Schin } 2574887Schin 2584887Schin static int p_arg(register struct argnod *arg,int flag) 2594887Schin { 2604887Schin while(arg) 2614887Schin { 2624887Schin if(strlen(arg->argval) || (arg->argflag==ARG_RAW)) 2634887Schin arg->argchn.ap = 0; 2644887Schin else if(flag==0) 2654887Schin sh_tclear((Shnode_t*)arg->argchn.ap); 2664887Schin else 2674887Schin sh_tclear(((struct fornod*)arg->argchn.ap)->fortre); 2684887Schin arg = arg->argnxt.ap; 2694887Schin } 2704887Schin return(0); 2714887Schin } 2724887Schin 2734887Schin static int p_switch(register struct regnod *reg) 2744887Schin { 2754887Schin int n=0; 2764887Schin while(reg) 2774887Schin { 2784887Schin n+=p_arg(reg->regptr,0); 2794887Schin n+=sh_tclear(reg->regcom); 2804887Schin reg = reg->regnxt; 2814887Schin } 2824887Schin return(n); 2834887Schin } 2844887Schin # define OPTIMIZE_FLAG (ARG_OPTIMIZE) 2854887Schin # define OPTIMIZE (flags&OPTIMIZE_FLAG) 2864887Schin #else 2874887Schin # define OPTIMIZE_FLAG (0) 2884887Schin # define OPTIMIZE (0) 2894887Schin # define sh_tclear(x) 2904887Schin #endif /* SHOPT_OPTIMIZE */ 2914887Schin 2924887Schin static void out_pattern(Sfio_t *iop, register const char *cp, int n) 2934887Schin { 2944887Schin register int c; 2954887Schin do 2964887Schin { 2974887Schin switch(c= *cp) 2984887Schin { 2994887Schin case 0: 3004887Schin if(n<0) 3014887Schin return; 3024887Schin c = n; 3034887Schin break; 3044887Schin case '\n': 3054887Schin sfputr(iop,"$'\\n",'\''); 3064887Schin continue; 3074887Schin case '\\': 3084887Schin if (!(c = *++cp)) 3094887Schin c = '\\'; 3104887Schin /*FALLTHROUGH*/ 3114887Schin case ' ': 3124887Schin case '<': case '>': case ';': 3134887Schin case '$': case '`': case '\t': 3144887Schin sfputc(iop,'\\'); 3154887Schin break; 3164887Schin } 3174887Schin sfputc(iop,c); 3184887Schin } 3194887Schin while(*cp++); 3204887Schin } 3214887Schin 3224887Schin static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted) 3234887Schin { 3244887Schin if(quoted) 3254887Schin { 3268462SApril.Chin@Sun.COM int n = stktell(stkstd); 3274887Schin cp = sh_fmtq(cp); 3284887Schin if(iop==stkstd && cp==stkptr(stkstd,n)) 3294887Schin { 3304887Schin *stkptr(stkstd,stktell(stkstd)-1) = c; 3314887Schin return; 3324887Schin } 3334887Schin } 3344887Schin sfputr(iop,cp,c); 3354887Schin } 3364887Schin 3374887Schin struct Level 3384887Schin { 3394887Schin Namfun_t hdr; 3404887Schin short maxlevel; 3414887Schin }; 3424887Schin 3434887Schin /* 3444887Schin * this is for a debugger but it hasn't been tested yet 3454887Schin * if a debug script sets .sh.level it should set up the scope 3464887Schin * as if you were executing in that level 3474887Schin */ 3484887Schin static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp) 3494887Schin { 3504887Schin Shscope_t *sp; 3514887Schin struct Level *lp = (struct Level*)fp; 3524887Schin int16_t level, oldlevel = (int16_t)nv_getnum(np); 3534887Schin nv_putv(np,val,flags,fp); 3548462SApril.Chin@Sun.COM if(!val) 35510898Sroland.mainz@nrubsig.org { 35610898Sroland.mainz@nrubsig.org fp = nv_stack(np, NIL(Namfun_t*)); 35710898Sroland.mainz@nrubsig.org if(fp && !fp->nofree) 35810898Sroland.mainz@nrubsig.org free((void*)fp); 3598462SApril.Chin@Sun.COM return; 36010898Sroland.mainz@nrubsig.org } 3614887Schin level = nv_getnum(np); 3624887Schin if(level<0 || level > lp->maxlevel) 3634887Schin { 3648462SApril.Chin@Sun.COM nv_putv(np, (char*)&oldlevel, NV_INT16, fp); 3654887Schin /* perhaps this should be an error */ 3664887Schin return; 3674887Schin } 3684887Schin if(level==oldlevel) 3694887Schin return; 3704887Schin if(sp = sh_getscope(level,SEEK_SET)) 3714887Schin { 3728462SApril.Chin@Sun.COM sh_setscope(sp); 3738462SApril.Chin@Sun.COM error_info.id = sp->cmdname; 3748462SApril.Chin@Sun.COM 3754887Schin } 3764887Schin } 3774887Schin 3788462SApril.Chin@Sun.COM static const Namdisc_t level_disc = { sizeof(struct Level), put_level }; 3798462SApril.Chin@Sun.COM 3808462SApril.Chin@Sun.COM static struct Level *init_level(int level) 3818462SApril.Chin@Sun.COM { 3828462SApril.Chin@Sun.COM struct Level *lp = newof(NiL,struct Level,1,0); 3838462SApril.Chin@Sun.COM lp->maxlevel = level; 3848462SApril.Chin@Sun.COM _nv_unset(SH_LEVELNOD,0); 3858462SApril.Chin@Sun.COM nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE); 3868462SApril.Chin@Sun.COM nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16); 3878462SApril.Chin@Sun.COM lp->hdr.disc = &level_disc; 3888462SApril.Chin@Sun.COM nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST); 3898462SApril.Chin@Sun.COM return(lp); 3908462SApril.Chin@Sun.COM } 3914887Schin 3924887Schin /* 3934887Schin * write the current common on the stack and make it available as .sh.command 3944887Schin */ 3958462SApril.Chin@Sun.COM int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags) 3964887Schin { 3978462SApril.Chin@Sun.COM Stk_t *stkp=shp->stk; 3984887Schin struct sh_scoped savst; 3994887Schin Namval_t *np = SH_COMMANDNOD; 4008462SApril.Chin@Sun.COM char *sav = stkptr(stkp,0); 4018462SApril.Chin@Sun.COM int n=4, offset=stktell(stkp); 4024887Schin const char *cp = "+=( "; 4034887Schin Sfio_t *iop = stkstd; 4048462SApril.Chin@Sun.COM short level; 4058462SApril.Chin@Sun.COM if(shp->indebug) 4068462SApril.Chin@Sun.COM return(0); 4078462SApril.Chin@Sun.COM shp->indebug = 1; 4084887Schin if(name) 4094887Schin { 4104887Schin sfputr(iop,name,-1); 4114887Schin if(subscript) 4124887Schin { 4134887Schin sfputc(iop,'['); 4144887Schin out_string(iop,subscript,']',1); 4154887Schin } 4164887Schin if(!(flags&ARG_APPEND)) 4174887Schin cp+=1, n-=1; 4184887Schin if(!(flags&ARG_ASSIGN)) 4194887Schin n -= 2; 4204887Schin sfwrite(iop,cp,n); 4214887Schin } 42210898Sroland.mainz@nrubsig.org if(*argv && !(flags&ARG_RAW)) 4234887Schin out_string(iop, *argv++,' ', 0); 4244887Schin n = (flags&ARG_ARITH); 4254887Schin while(cp = *argv++) 4264887Schin { 4274887Schin if((flags&ARG_EXP) && argv[1]==0) 4284887Schin out_pattern(iop, cp,' '); 4294887Schin else 4304887Schin out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv); 4314887Schin } 4324887Schin if(flags&ARG_ASSIGN) 4334887Schin sfputc(iop,')'); 4344887Schin else if(iop==stkstd) 4358462SApril.Chin@Sun.COM *stkptr(stkp,stktell(stkp)-1) = 0; 4368462SApril.Chin@Sun.COM np->nvalue.cp = stkfreeze(stkp,1); 4374887Schin /* now setup .sh.level variable */ 4388462SApril.Chin@Sun.COM shp->st.lineno = error_info.line; 4398462SApril.Chin@Sun.COM level = shp->fn_depth+shp->dot_depth; 4408462SApril.Chin@Sun.COM if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE)) 4418462SApril.Chin@Sun.COM init_level(level); 4428462SApril.Chin@Sun.COM else 4438462SApril.Chin@Sun.COM nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16); 4448462SApril.Chin@Sun.COM savst = shp->st; 4458462SApril.Chin@Sun.COM shp->st.trap[SH_DEBUGTRAP] = 0; 4464887Schin n = sh_trap(trap,0); 4474887Schin np->nvalue.cp = 0; 4488462SApril.Chin@Sun.COM shp->indebug = 0; 4498462SApril.Chin@Sun.COM if(shp->st.cmdname) 4508462SApril.Chin@Sun.COM error_info.id = shp->st.cmdname; 4518462SApril.Chin@Sun.COM nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE); 4528462SApril.Chin@Sun.COM nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE); 4538462SApril.Chin@Sun.COM shp->st = savst; 4548462SApril.Chin@Sun.COM if(sav != stkptr(stkp,0)) 4558462SApril.Chin@Sun.COM stkset(stkp,sav,0); 4564887Schin else 4578462SApril.Chin@Sun.COM stkseek(stkp,offset); 4584887Schin return(n); 4594887Schin } 4604887Schin 4614887Schin /* 4624887Schin * Given stream <iop> compile and execute 4634887Schin */ 4644887Schin int sh_eval(register Sfio_t *iop, int mode) 4654887Schin { 4664887Schin register Shnode_t *t; 4674887Schin Shell_t *shp = sh_getinterp(); 4684887Schin struct slnod *saveslp = shp->st.staklist; 4694887Schin int jmpval; 4704887Schin struct checkpt *pp = (struct checkpt*)shp->jmplist; 4714887Schin struct checkpt buff; 4724887Schin static Sfio_t *io_save; 4738462SApril.Chin@Sun.COM volatile int traceon=0, lineno=0; 47410898Sroland.mainz@nrubsig.org int binscript=shp->binscript; 4754887Schin io_save = iop; /* preserve correct value across longjmp */ 47610898Sroland.mainz@nrubsig.org shp->binscript = 0; 4778462SApril.Chin@Sun.COM #define SH_TOPFUN 0x8000 /* this is a temporary tksh hack */ 4788462SApril.Chin@Sun.COM if (mode & SH_TOPFUN) 4798462SApril.Chin@Sun.COM { 4808462SApril.Chin@Sun.COM mode ^= SH_TOPFUN; 4818462SApril.Chin@Sun.COM shp->fn_reset = 1; 4828462SApril.Chin@Sun.COM } 4834887Schin sh_pushcontext(&buff,SH_JMPEVAL); 4844887Schin buff.olist = pp->olist; 4854887Schin jmpval = sigsetjmp(buff.buff,0); 48610898Sroland.mainz@nrubsig.org while(jmpval==0) 4874887Schin { 4888462SApril.Chin@Sun.COM if(mode&SH_READEVAL) 4898462SApril.Chin@Sun.COM { 4908462SApril.Chin@Sun.COM lineno = shp->inlineno; 4918462SApril.Chin@Sun.COM if(traceon=sh_isoption(SH_XTRACE)) 4928462SApril.Chin@Sun.COM sh_offoption(SH_XTRACE); 4938462SApril.Chin@Sun.COM } 49410898Sroland.mainz@nrubsig.org t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL); 49510898Sroland.mainz@nrubsig.org if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0)) 49610898Sroland.mainz@nrubsig.org { 49710898Sroland.mainz@nrubsig.org if(!(mode&SH_READEVAL)) 49810898Sroland.mainz@nrubsig.org sfclose(iop); 49910898Sroland.mainz@nrubsig.org io_save = 0; 50010898Sroland.mainz@nrubsig.org mode &= ~SH_FUNEVAL; 50110898Sroland.mainz@nrubsig.org } 50210898Sroland.mainz@nrubsig.org mode &= ~SH_READEVAL; 5034887Schin if(!sh_isoption(SH_VERBOSE)) 5044887Schin sh_offstate(SH_VERBOSE); 50510898Sroland.mainz@nrubsig.org if((mode&~SH_FUNEVAL) && shp->hist_ptr) 5064887Schin { 5074887Schin hist_flush(shp->hist_ptr); 5084887Schin mode = sh_state(SH_INTERACTIVE); 5094887Schin } 51010898Sroland.mainz@nrubsig.org sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL)); 51110898Sroland.mainz@nrubsig.org if(!(mode&SH_FUNEVAL)) 51210898Sroland.mainz@nrubsig.org break; 5134887Schin } 5144887Schin sh_popcontext(&buff); 51510898Sroland.mainz@nrubsig.org shp->binscript = binscript; 5168462SApril.Chin@Sun.COM if(traceon) 5178462SApril.Chin@Sun.COM sh_onoption(SH_XTRACE); 5188462SApril.Chin@Sun.COM if(lineno) 5198462SApril.Chin@Sun.COM shp->inlineno = lineno; 5204887Schin if(io_save) 5214887Schin sfclose(io_save); 5228462SApril.Chin@Sun.COM sh_freeup(shp); 5234887Schin shp->st.staklist = saveslp; 5248462SApril.Chin@Sun.COM shp->fn_reset = 0; 5254887Schin if(jmpval>SH_JMPEVAL) 5264887Schin siglongjmp(*shp->jmplist,jmpval); 5278462SApril.Chin@Sun.COM return(shp->exitval); 5284887Schin } 5294887Schin 5304887Schin #if SHOPT_FASTPIPE 5318462SApril.Chin@Sun.COM static int pipe_exec(Shell_t* shp,int pv[], Shnode_t *t, int errorflg) 5324887Schin { 5334887Schin struct checkpt buff; 5344887Schin register Shnode_t *tchild = t->fork.forktre; 5354887Schin Namval_t *np; 5368462SApril.Chin@Sun.COM int jmpval; 5378462SApril.Chin@Sun.COM volatile Sfio_t *iop; 5388462SApril.Chin@Sun.COM volatile int r; 5394887Schin if((tchild->tre.tretyp&COMMSK)!=TCOM || !(np=(Namval_t*)(tchild->com.comnamp))) 5404887Schin { 5414887Schin sh_pipe(pv); 5424887Schin return(sh_exec(t,errorflg)); 5434887Schin } 5448462SApril.Chin@Sun.COM pv[0] = shp->lim.open_max; 5458462SApril.Chin@Sun.COM shp->fdstatus[pv[0]] = IOREAD|IODUP|IOSEEK; 5468462SApril.Chin@Sun.COM pv[1] = shp->lim.open_max+1; 5478462SApril.Chin@Sun.COM shp->fdstatus[pv[1]] = IOWRITE|IOSEEK; 5484887Schin iop = sftmp(IOBSIZE+1); 5498462SApril.Chin@Sun.COM shp->sftable[shp->lim.open_max+1] = iop; 5504887Schin sh_pushcontext(&buff,SH_JMPIO); 5514887Schin if(t->tre.tretyp&FPIN) 5528462SApril.Chin@Sun.COM sh_iosave(shp,0,shp->topfd,(char*)0); 5538462SApril.Chin@Sun.COM sh_iosave(shp,1,shp->topfd,(char*)0); 5544887Schin jmpval = sigsetjmp(buff.buff,0); 5554887Schin if(jmpval==0) 5564887Schin { 5574887Schin if(t->tre.tretyp&FPIN) 5588462SApril.Chin@Sun.COM sh_iorenumber(shp,shp->inpipe[0],0); 5598462SApril.Chin@Sun.COM sh_iorenumber(shp,shp->lim.open_max+1,1); 5604887Schin r = sh_exec(tchild,errorflg); 5614887Schin if(sffileno(sfstdout)>=0) 5624887Schin pv[0] = sfsetfd(sfstdout,10); 5634887Schin iop = sfswap(sfstdout,0); 5644887Schin } 5654887Schin sh_popcontext(&buff); 5668462SApril.Chin@Sun.COM shp->sftable[pv[0]] = iop; 5678462SApril.Chin@Sun.COM shp->fdstatus[pv[0]] = IOREAD|IODUP|IOSEEK; 5684887Schin sfset(iop,SF_WRITE,0); 5694887Schin sfseek(iop,0L,SEEK_SET); 5708462SApril.Chin@Sun.COM sh_iorestore(shp,buff.topfd,jmpval); 5714887Schin if(jmpval>SH_JMPIO) 5728462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 5734887Schin return(r); 5744887Schin } 5754887Schin #endif /* SHOPT_FASTPIPE */ 5764887Schin 5774887Schin /* 5784887Schin * returns 1 when option -<c> is specified 5794887Schin */ 5804887Schin static int checkopt(char *argv[], int c) 5814887Schin { 5824887Schin char *cp; 5834887Schin while(cp = *++argv) 5844887Schin { 5854887Schin if(*cp=='+') 5864887Schin continue; 5874887Schin if(*cp!='-' || cp[1]=='-') 5884887Schin break; 5898462SApril.Chin@Sun.COM if(strchr(++cp,c)) 5904887Schin return(1); 5918462SApril.Chin@Sun.COM if(*cp=='h' && cp[1]==0 && *++argv==0) 5928462SApril.Chin@Sun.COM break; 5934887Schin } 5944887Schin return(0); 5954887Schin } 5964887Schin 5974887Schin static void free_list(struct openlist *olist) 5984887Schin { 5994887Schin struct openlist *item,*next; 6004887Schin for(item=olist;item;item=next) 6014887Schin { 6024887Schin next = item->next; 6034887Schin free((void*)item); 6044887Schin } 6054887Schin } 6064887Schin 6078462SApril.Chin@Sun.COM /* 6088462SApril.Chin@Sun.COM * set ${.sh.name} and ${.sh.subscript} 6098462SApril.Chin@Sun.COM * set _ to reference for ${.sh.name}[$.sh.subscript] 6108462SApril.Chin@Sun.COM */ 611*12068SRoger.Faulkner@Oracle.COM static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr) 6128462SApril.Chin@Sun.COM { 61310898Sroland.mainz@nrubsig.org char *sp=0,*cp = nv_name(nq); 6148462SApril.Chin@Sun.COM Namarr_t *ap; 6158462SApril.Chin@Sun.COM memset(nr,0,sizeof(*nr)); 6168462SApril.Chin@Sun.COM nr->np = nq; 6178462SApril.Chin@Sun.COM nr->root = sh.var_tree; 6188462SApril.Chin@Sun.COM nr->table = sh.last_table; 619*12068SRoger.Faulkner@Oracle.COM shp->instance = 1; 62010898Sroland.mainz@nrubsig.org if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq))) 62110898Sroland.mainz@nrubsig.org sp = strdup(sp); 622*12068SRoger.Faulkner@Oracle.COM shp->instance = 0; 6238462SApril.Chin@Sun.COM if(sh.var_tree!=sh.var_base && !nv_open(cp,nr->root,NV_VARNAME|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)) 6248462SApril.Chin@Sun.COM nr->root = sh.var_base; 6258462SApril.Chin@Sun.COM nv_putval(SH_NAMENOD, cp, NV_NOFREE); 6268462SApril.Chin@Sun.COM memcpy(node,L_ARGNOD,sizeof(*node)); 6278462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = nr; 6288462SApril.Chin@Sun.COM L_ARGNOD->nvflag = NV_REF|NV_NOFREE; 6298462SApril.Chin@Sun.COM L_ARGNOD->nvfun = 0; 6308462SApril.Chin@Sun.COM L_ARGNOD->nvenv = 0; 63110898Sroland.mainz@nrubsig.org if(sp) 6328462SApril.Chin@Sun.COM { 63310898Sroland.mainz@nrubsig.org nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE); 6348462SApril.Chin@Sun.COM return(ap->nelem&ARRAY_SCAN); 6358462SApril.Chin@Sun.COM } 6368462SApril.Chin@Sun.COM return(0); 6378462SApril.Chin@Sun.COM } 6388462SApril.Chin@Sun.COM 6398462SApril.Chin@Sun.COM static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode) 6408462SApril.Chin@Sun.COM { 6418462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = node->nvalue.nrp; 6428462SApril.Chin@Sun.COM L_ARGNOD->nvflag = node->nvflag; 6438462SApril.Chin@Sun.COM L_ARGNOD->nvfun = node->nvfun; 6448462SApril.Chin@Sun.COM if(nr->sub) 6458462SApril.Chin@Sun.COM { 6468462SApril.Chin@Sun.COM nv_putsub(nq, nr->sub, mode); 6478462SApril.Chin@Sun.COM free((void*)nr->sub); 6488462SApril.Chin@Sun.COM } 6498462SApril.Chin@Sun.COM nv_unset(SH_NAMENOD); 6508462SApril.Chin@Sun.COM nv_unset(SH_SUBSCRNOD); 6518462SApril.Chin@Sun.COM } 6524887Schin 6534887Schin int sh_exec(register const Shnode_t *t, int flags) 6544887Schin { 6558462SApril.Chin@Sun.COM register Shell_t *shp = &sh; 6568462SApril.Chin@Sun.COM Stk_t *stkp = shp->stk; 6574887Schin sh_sigcheck(); 6588462SApril.Chin@Sun.COM if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC)) 6594887Schin { 6604887Schin register int type = flags; 6614887Schin register char *com0 = 0; 6624887Schin int errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE; 6634887Schin int execflg = (type&sh_state(SH_NOFORK)); 66410898Sroland.mainz@nrubsig.org int execflg2 = (type&sh_state(SH_FORKED)); 6654887Schin int mainloop = (type&sh_state(SH_INTERACTIVE)); 6668462SApril.Chin@Sun.COM #if SHOPT_AMP || SHOPT_SPAWN 6674887Schin int ntflag = (type&sh_state(SH_NTFORK)); 66810898Sroland.mainz@nrubsig.org #else 66910898Sroland.mainz@nrubsig.org int ntflag = 0; 6704887Schin #endif 6718462SApril.Chin@Sun.COM int topfd = shp->topfd; 6728462SApril.Chin@Sun.COM char *sav=stkptr(stkp,0); 6738462SApril.Chin@Sun.COM char *cp=0, **com=0, *comn; 6744887Schin int argn; 6754887Schin int skipexitset = 0; 6764887Schin int was_interactive = 0; 6774887Schin int was_errexit = sh_isstate(SH_ERREXIT); 6784887Schin int was_monitor = sh_isstate(SH_MONITOR); 6794887Schin int echeck = 0; 6804887Schin if(flags&sh_state(SH_INTERACTIVE)) 6814887Schin { 68210898Sroland.mainz@nrubsig.org if(pipejob==2) 68310898Sroland.mainz@nrubsig.org job_unlock(); 6844887Schin pipejob = 0; 6854887Schin job.curpgid = 0; 6864887Schin flags &= ~sh_state(SH_INTERACTIVE); 6874887Schin } 6884887Schin sh_offstate(SH_ERREXIT); 6894887Schin sh_offstate(SH_DEFPATH); 6904887Schin if(was_errexit&flags) 6914887Schin sh_onstate(SH_ERREXIT); 6924887Schin if(was_monitor&flags) 6934887Schin sh_onstate(SH_MONITOR); 6944887Schin type = t->tre.tretyp; 6958462SApril.Chin@Sun.COM if(!shp->intrap) 6968462SApril.Chin@Sun.COM shp->oldexit=shp->exitval; 6978462SApril.Chin@Sun.COM shp->exitval=0; 6988462SApril.Chin@Sun.COM shp->lastsig = 0; 6998462SApril.Chin@Sun.COM shp->lastpath = 0; 7004887Schin switch(type&COMMSK) 7014887Schin { 7024887Schin case TCOM: 7034887Schin { 7044887Schin register struct argnod *argp; 7054887Schin char *trap; 7064887Schin Namval_t *np, *nq, *last_table; 7074887Schin struct ionod *io; 7088462SApril.Chin@Sun.COM int command=0, flgs=NV_ASSIGN; 7098462SApril.Chin@Sun.COM shp->bltindata.invariant = type>>(COMBITS+2); 7108462SApril.Chin@Sun.COM type &= (COMMSK|COMSCAN); 7118462SApril.Chin@Sun.COM sh_stats(STAT_SCMDS); 7128462SApril.Chin@Sun.COM error_info.line = t->com.comline-shp->st.firstline; 7138462SApril.Chin@Sun.COM com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE); 7144887Schin echeck = 1; 7154887Schin if(t->tre.tretyp&COMSCAN) 7164887Schin { 7174887Schin argp = t->com.comarg; 7184887Schin if(argp && *com && !(argp->argflag&ARG_RAW)) 7194887Schin sh_sigcheck(); 7204887Schin } 7214887Schin np = (Namval_t*)(t->com.comnamp); 7224887Schin nq = (Namval_t*)(t->com.comnamq); 7234887Schin com0 = com[0]; 7248462SApril.Chin@Sun.COM shp->xargexit = 0; 7254887Schin while(np==SYSCOMMAND) 7264887Schin { 7278462SApril.Chin@Sun.COM register int n = b_command(0,com,&shp->bltindata); 7284887Schin if(n==0) 7294887Schin break; 7304887Schin command += n; 7314887Schin np = 0; 7324887Schin if(!(com0= *(com+=n))) 7334887Schin break; 7348462SApril.Chin@Sun.COM np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp); 7354887Schin } 7368462SApril.Chin@Sun.COM if(shp->xargexit) 7374887Schin { 7388462SApril.Chin@Sun.COM shp->xargmin -= command; 7398462SApril.Chin@Sun.COM shp->xargmax -= command; 7404887Schin } 7414887Schin else 7428462SApril.Chin@Sun.COM shp->xargmin = 0; 7434887Schin argn -= command; 7444887Schin if(!command && np && is_abuiltin(np)) 7458462SApril.Chin@Sun.COM np = dtsearch(shp->fun_tree,np); 7468462SApril.Chin@Sun.COM if(com0) 7474887Schin { 7488462SApril.Chin@Sun.COM if(!np && !strchr(com0,'/')) 7494887Schin { 7508462SApril.Chin@Sun.COM Dt_t *root = command?shp->bltin_tree:shp->fun_tree; 7518462SApril.Chin@Sun.COM np = nv_bfsearch(com0, root, &nq, &cp); 7528462SApril.Chin@Sun.COM #if SHOPT_NAMESPACE 7538462SApril.Chin@Sun.COM if(shp->namespace && !nq && !cp) 7548462SApril.Chin@Sun.COM { 7558462SApril.Chin@Sun.COM int offset = stktell(stkp); 7568462SApril.Chin@Sun.COM sfputr(stkp,nv_name(shp->namespace),-1); 7578462SApril.Chin@Sun.COM sfputc(stkp,'.'); 7588462SApril.Chin@Sun.COM sfputr(stkp,com0,0); 7598462SApril.Chin@Sun.COM stkseek(stkp,offset); 7608462SApril.Chin@Sun.COM np = nv_bfsearch(stkptr(stkp,offset), root, &nq, &cp); 7618462SApril.Chin@Sun.COM } 7628462SApril.Chin@Sun.COM #endif /* SHOPT_NAMESPACE */ 7634887Schin } 7648462SApril.Chin@Sun.COM comn = com[argn-1]; 7654887Schin } 7664887Schin io = t->tre.treio; 7678462SApril.Chin@Sun.COM if(shp->envlist = argp = t->com.comset) 7684887Schin { 7698462SApril.Chin@Sun.COM if(argn==0 || (np && nv_isattr(np,BLT_SPC))) 7704887Schin { 77110898Sroland.mainz@nrubsig.org Namval_t *tp=0; 7728462SApril.Chin@Sun.COM if(argn) 7738462SApril.Chin@Sun.COM { 7748462SApril.Chin@Sun.COM if(checkopt(com,'A')) 7758462SApril.Chin@Sun.COM flgs |= NV_ARRAY; 7768462SApril.Chin@Sun.COM else if(checkopt(com,'a')) 7778462SApril.Chin@Sun.COM flgs |= NV_IARRAY; 7788462SApril.Chin@Sun.COM } 7794887Schin #if SHOPT_BASH 7804887Schin if(np==SYSLOCAL) 7814887Schin { 7824887Schin if(!nv_getval(SH_FUNNAMENOD)) 7834887Schin errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0); 7848462SApril.Chin@Sun.COM if(!shp->st.var_local) 7854887Schin { 7868462SApril.Chin@Sun.COM sh_scope(shp,(struct argnod*)0,0); 7878462SApril.Chin@Sun.COM shp->st.var_local = shp->var_tree; 7884887Schin } 7894887Schin 7904887Schin } 7914887Schin if(np==SYSTYPESET || np==SYSLOCAL) 7924887Schin #else 7938462SApril.Chin@Sun.COM if(np==SYSTYPESET || (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp)) 7944887Schin #endif 7954887Schin { 7968462SApril.Chin@Sun.COM if(np!=SYSTYPESET) 79710898Sroland.mainz@nrubsig.org { 7988462SApril.Chin@Sun.COM shp->typeinit = np; 79910898Sroland.mainz@nrubsig.org tp = nv_type(np); 80010898Sroland.mainz@nrubsig.org } 8018462SApril.Chin@Sun.COM if(checkopt(com,'C')) 8028462SApril.Chin@Sun.COM flgs |= NV_COMVAR; 8038462SApril.Chin@Sun.COM if(checkopt(com,'S')) 8048462SApril.Chin@Sun.COM flgs |= NV_STATIC; 8054887Schin if(checkopt(com,'n')) 8064887Schin flgs |= NV_NOREF; 80710898Sroland.mainz@nrubsig.org else if(!shp->typeinit && (checkopt(com,'L') || checkopt(com,'R') || checkopt(com,'Z'))) 80810898Sroland.mainz@nrubsig.org flgs |= NV_UNJUST; 8094887Schin #if SHOPT_TYPEDEF 8108462SApril.Chin@Sun.COM else if(argn>=3 && checkopt(com,'T')) 8114887Schin { 8128462SApril.Chin@Sun.COM shp->prefix = NV_CLASS; 8134887Schin flgs |= NV_TYPE; 8144887Schin 8154887Schin } 8164887Schin #endif /* SHOPT_TYPEDEF */ 8178462SApril.Chin@Sun.COM if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL) 8184887Schin flgs |= NV_NOSCOPE; 8194887Schin } 8204887Schin else if(np==SYSEXPORT) 8214887Schin flgs |= NV_EXPORT; 8228462SApril.Chin@Sun.COM if(flgs&(NV_EXPORT|NV_NOREF)) 8238462SApril.Chin@Sun.COM flgs |= NV_IDENT; 8248462SApril.Chin@Sun.COM else 8258462SApril.Chin@Sun.COM flgs |= NV_VARNAME; 8264887Schin #if 0 8274887Schin if(OPTIMIZE) 8284887Schin flgs |= NV_TAGGED; 8294887Schin #endif 83010898Sroland.mainz@nrubsig.org nv_setlist(argp,flgs,tp); 8318462SApril.Chin@Sun.COM if(np==shp->typeinit) 8328462SApril.Chin@Sun.COM shp->typeinit = 0; 8338462SApril.Chin@Sun.COM shp->envlist = argp; 8344887Schin argp = NULL; 8354887Schin } 8364887Schin } 8378462SApril.Chin@Sun.COM last_table = shp->last_table; 8388462SApril.Chin@Sun.COM shp->last_table = 0; 8394887Schin if((io||argn)) 8404887Schin { 8418462SApril.Chin@Sun.COM Shbltin_t *bp=0; 8424887Schin static char *argv[1]; 8438462SApril.Chin@Sun.COM int tflags = 1; 8448462SApril.Chin@Sun.COM if(np && nv_isattr(np,BLT_DCL)) 8458462SApril.Chin@Sun.COM tflags |= 2; 8464887Schin if(argn==0) 8474887Schin { 8484887Schin /* fake 'true' built-in */ 8494887Schin np = SYSTRUE; 8504887Schin *argv = nv_name(np); 8514887Schin com = argv; 8524887Schin } 8534887Schin /* set +x doesn't echo */ 8544887Schin else if((np!=SYSSET) && sh_isoption(SH_XTRACE)) 8558462SApril.Chin@Sun.COM sh_trace(com-command,tflags); 8564887Schin else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME)) 8574887Schin { 8584887Schin int ison = sh_isoption(SH_XTRACE); 8594887Schin if(!ison) 8604887Schin sh_onoption(SH_XTRACE); 8618462SApril.Chin@Sun.COM sh_trace(com-command,tflags); 8624887Schin if(io) 8638462SApril.Chin@Sun.COM sh_redirect(shp,io,SH_SHOWME); 8644887Schin if(!ison) 8654887Schin sh_offoption(SH_XTRACE); 8664887Schin break; 8674887Schin } 8688462SApril.Chin@Sun.COM if(trap=shp->st.trap[SH_DEBUGTRAP]) 8698462SApril.Chin@Sun.COM { 8708462SApril.Chin@Sun.COM int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW); 8718462SApril.Chin@Sun.COM if(n==255 && shp->fn_depth+shp->dot_depth) 8728462SApril.Chin@Sun.COM { 8738462SApril.Chin@Sun.COM np = SYSRETURN; 8748462SApril.Chin@Sun.COM argn = 1; 8758462SApril.Chin@Sun.COM com[0] = np->nvname; 8768462SApril.Chin@Sun.COM com[1] = 0; 8778462SApril.Chin@Sun.COM io = 0; 8788462SApril.Chin@Sun.COM argp = 0; 8798462SApril.Chin@Sun.COM } 8808462SApril.Chin@Sun.COM else if(n==2) 8818462SApril.Chin@Sun.COM break; 8828462SApril.Chin@Sun.COM } 8834887Schin if(io) 8848462SApril.Chin@Sun.COM sfsync(shp->outpool); 8858462SApril.Chin@Sun.COM shp->lastpath = 0; 8864887Schin if(!np && !strchr(com0,'/')) 8874887Schin { 8888462SApril.Chin@Sun.COM if(path_search(com0,NIL(Pathcomp_t**),1)) 8898462SApril.Chin@Sun.COM { 8908462SApril.Chin@Sun.COM error_info.line = t->com.comline-shp->st.firstline; 8918462SApril.Chin@Sun.COM if((np=nv_search(com0,shp->fun_tree,0)) && !np->nvalue.ip) 8928462SApril.Chin@Sun.COM { 8938462SApril.Chin@Sun.COM Namval_t *mp=nv_search(com0,shp->bltin_tree,0); 8948462SApril.Chin@Sun.COM if(mp) 8958462SApril.Chin@Sun.COM np = mp; 8968462SApril.Chin@Sun.COM } 8978462SApril.Chin@Sun.COM } 8984887Schin else 8994887Schin { 9008462SApril.Chin@Sun.COM if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp) 9018462SApril.Chin@Sun.COM np=nv_search(nv_getval(np),shp->bltin_tree,0); 9024887Schin else 9034887Schin np = 0; 9044887Schin } 9054887Schin } 90610898Sroland.mainz@nrubsig.org if(np && pipejob==2) 90710898Sroland.mainz@nrubsig.org { 90810898Sroland.mainz@nrubsig.org job_unlock(); 90910898Sroland.mainz@nrubsig.org pipejob = 1; 91010898Sroland.mainz@nrubsig.org } 9114887Schin /* check for builtins */ 9124887Schin if(np && is_abuiltin(np)) 9134887Schin { 9148462SApril.Chin@Sun.COM volatile int scope=0, share=0; 9158462SApril.Chin@Sun.COM volatile void *save_ptr; 9168462SApril.Chin@Sun.COM volatile void *save_data; 9178462SApril.Chin@Sun.COM int jmpval, save_prompt; 91810898Sroland.mainz@nrubsig.org int was_nofork = execflg?sh_isstate(SH_NOFORK):0; 9194887Schin struct checkpt buff; 9204887Schin unsigned long was_vi=0, was_emacs=0, was_gmacs=0; 9214887Schin struct stat statb; 9228462SApril.Chin@Sun.COM bp = &shp->bltindata; 9238462SApril.Chin@Sun.COM save_ptr = bp->ptr; 9248462SApril.Chin@Sun.COM save_data = bp->data; 9258462SApril.Chin@Sun.COM memset(&statb, 0, sizeof(struct stat)); 9264887Schin if(strchr(nv_name(np),'/')) 9274887Schin { 9284887Schin /* 9294887Schin * disable editors for built-in 9304887Schin * versions of commands on PATH 9314887Schin */ 9324887Schin was_vi = sh_isoption(SH_VI); 9334887Schin was_emacs = sh_isoption(SH_EMACS); 9344887Schin was_gmacs = sh_isoption(SH_GMACS); 9354887Schin sh_offoption(SH_VI); 9364887Schin sh_offoption(SH_EMACS); 9374887Schin sh_offoption(SH_GMACS); 9384887Schin } 93910898Sroland.mainz@nrubsig.org if(execflg) 94010898Sroland.mainz@nrubsig.org sh_onstate(SH_NOFORK); 9414887Schin sh_pushcontext(&buff,SH_JMPCMD); 9424887Schin jmpval = sigsetjmp(buff.buff,1); 9434887Schin if(jmpval == 0) 9444887Schin { 9454887Schin if(!(nv_isattr(np,BLT_ENV))) 9464887Schin error_info.flags |= ERROR_SILENT; 9474887Schin errorpush(&buff.err,0); 9484887Schin if(io) 9494887Schin { 9504887Schin struct openlist *item; 9514887Schin if(np==SYSLOGIN) 9524887Schin type=1; 9534887Schin else if(np==SYSEXEC) 9544887Schin type=1+!com[1]; 9554887Schin else 9568462SApril.Chin@Sun.COM type = (execflg && !shp->subshell && !shp->st.trapcom[0]); 9578462SApril.Chin@Sun.COM sh_redirect(shp,io,type); 9584887Schin for(item=buff.olist;item;item=item->next) 9594887Schin item->strm=0; 9604887Schin } 9614887Schin if(!(nv_isattr(np,BLT_ENV))) 9624887Schin { 9638462SApril.Chin@Sun.COM if(bp->nosfio) 9648462SApril.Chin@Sun.COM { 9658462SApril.Chin@Sun.COM if(!shp->pwd) 9668462SApril.Chin@Sun.COM path_pwd(0); 9678462SApril.Chin@Sun.COM if(shp->pwd) 9688462SApril.Chin@Sun.COM stat(".",&statb); 9698462SApril.Chin@Sun.COM } 9708462SApril.Chin@Sun.COM sfsync(NULL); 9714887Schin share = sfset(sfstdin,SF_SHARE,0); 9724887Schin sh_onstate(SH_STOPOK); 9734887Schin sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE); 9744887Schin sfset(sfstderr,SF_LINE,1); 9758462SApril.Chin@Sun.COM save_prompt = shp->nextprompt; 9768462SApril.Chin@Sun.COM shp->nextprompt = 0; 9774887Schin } 9784887Schin if(argp) 9794887Schin { 9804887Schin scope++; 9818462SApril.Chin@Sun.COM sh_scope(shp,argp,0); 9824887Schin } 9834887Schin opt_info.index = opt_info.offset = 0; 9844887Schin opt_info.disc = 0; 9854887Schin error_info.id = *com; 9868462SApril.Chin@Sun.COM if(argn) 9878462SApril.Chin@Sun.COM shp->exitval = 0; 9888462SApril.Chin@Sun.COM shp->bltinfun = funptr(np); 9898462SApril.Chin@Sun.COM bp->bnode = np; 9908462SApril.Chin@Sun.COM bp->vnode = nq; 9918462SApril.Chin@Sun.COM bp->ptr = nv_context(np); 9928462SApril.Chin@Sun.COM bp->data = t->com.comstate; 9938462SApril.Chin@Sun.COM bp->sigset = 0; 9948462SApril.Chin@Sun.COM bp->notify = 0; 9958462SApril.Chin@Sun.COM bp->flags = (OPTIMIZE!=0); 9968462SApril.Chin@Sun.COM if(shp->subshell && nv_isattr(np,BLT_NOSFIO)) 9978462SApril.Chin@Sun.COM sh_subtmpfile(0); 9988462SApril.Chin@Sun.COM if(execflg && !shp->subshell && 9998462SApril.Chin@Sun.COM !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV)) 10004887Schin { 10014887Schin /* do close-on-exec */ 10024887Schin int fd; 10038462SApril.Chin@Sun.COM for(fd=0; fd < shp->lim.open_max; fd++) 10048462SApril.Chin@Sun.COM if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd) 10054887Schin sh_close(fd); 10064887Schin } 10078462SApril.Chin@Sun.COM if(argn) 10088462SApril.Chin@Sun.COM shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp); 10094887Schin if(error_info.flags&ERROR_INTERACTIVE) 10104887Schin tty_check(ERRIO); 10118462SApril.Chin@Sun.COM ((Shnode_t*)t)->com.comstate = shp->bltindata.data; 10128462SApril.Chin@Sun.COM bp->data = (void*)save_data; 10138462SApril.Chin@Sun.COM if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG) 10148462SApril.Chin@Sun.COM shp->exitval &= SH_EXITMASK; 10154887Schin } 10164887Schin else 10174887Schin { 10184887Schin struct openlist *item; 10194887Schin for(item=buff.olist;item;item=item->next) 10204887Schin { 10214887Schin if(item->strm) 10224887Schin { 10234887Schin sfclrlock(item->strm); 10248462SApril.Chin@Sun.COM if(shp->hist_ptr && item->strm == shp->hist_ptr->histfp) 10258462SApril.Chin@Sun.COM hist_close(shp->hist_ptr); 10264887Schin else 10274887Schin sfclose(item->strm); 10284887Schin } 10294887Schin } 10308462SApril.Chin@Sun.COM if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY)) 10318462SApril.Chin@Sun.COM (*shp->bltinfun)(-2,com,(void*)bp); 10324887Schin /* failure on special built-ins fatal */ 10334887Schin if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command)) 10344887Schin jmpval=0; 10354887Schin } 10368462SApril.Chin@Sun.COM if(bp && bp->ptr!= nv_context(np)) 10378462SApril.Chin@Sun.COM np->nvfun = (Namfun_t*)bp->ptr; 103810898Sroland.mainz@nrubsig.org if(execflg && !was_nofork) 103910898Sroland.mainz@nrubsig.org sh_offstate(SH_NOFORK); 10404887Schin if(!(nv_isattr(np,BLT_ENV))) 10414887Schin { 10428462SApril.Chin@Sun.COM if(bp->nosfio && shp->pwd) 10434887Schin { 10444887Schin struct stat stata; 10454887Schin stat(".",&stata); 10464887Schin /* restore directory changed */ 10474887Schin if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev) 10488462SApril.Chin@Sun.COM chdir(shp->pwd); 10494887Schin } 10504887Schin sh_offstate(SH_STOPOK); 10514887Schin if(share&SF_SHARE) 10524887Schin sfset(sfstdin,SF_PUBLIC|SF_SHARE,1); 10534887Schin sfset(sfstderr,SF_LINE,0); 10548462SApril.Chin@Sun.COM sfpool(sfstderr,shp->outpool,SF_WRITE); 10554887Schin sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE); 10568462SApril.Chin@Sun.COM shp->nextprompt = save_prompt; 10574887Schin } 10584887Schin sh_popcontext(&buff); 10594887Schin errorpop(&buff.err); 106010898Sroland.mainz@nrubsig.org error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY); 10618462SApril.Chin@Sun.COM shp->bltinfun = 0; 10624887Schin if(buff.olist) 10634887Schin free_list(buff.olist); 10644887Schin if(was_vi) 10654887Schin sh_onoption(SH_VI); 10664887Schin else if(was_emacs) 10674887Schin sh_onoption(SH_EMACS); 10684887Schin else if(was_gmacs) 10694887Schin sh_onoption(SH_GMACS); 10704887Schin if(scope) 10718462SApril.Chin@Sun.COM sh_unscope(shp); 10728462SApril.Chin@Sun.COM bp->ptr = (void*)save_ptr; 10738462SApril.Chin@Sun.COM bp->data = (void*)save_data; 10744887Schin /* don't restore for subshell exec */ 10758462SApril.Chin@Sun.COM if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC)) 10768462SApril.Chin@Sun.COM sh_iorestore(shp,topfd,jmpval); 10774887Schin if(jmpval) 10788462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 10798462SApril.Chin@Sun.COM #if 0 10808462SApril.Chin@Sun.COM if(flgs&NV_STATIC) 10818462SApril.Chin@Sun.COM ((Shnode_t*)t)->com.comset = 0; 10828462SApril.Chin@Sun.COM #endif 10838462SApril.Chin@Sun.COM if(shp->exitval >=0) 10844887Schin goto setexit; 10854887Schin np = 0; 10864887Schin type=0; 10874887Schin } 10884887Schin /* check for functions */ 10894887Schin if(!command && np && nv_isattr(np,NV_FUNCTION)) 10904887Schin { 10918462SApril.Chin@Sun.COM volatile int indx; 10928462SApril.Chin@Sun.COM int jmpval=0; 10934887Schin struct checkpt buff; 10944887Schin Namval_t node; 10958462SApril.Chin@Sun.COM struct Namref nr; 10968462SApril.Chin@Sun.COM long mode; 10974887Schin register struct slnod *slp; 10984887Schin if(!np->nvalue.ip) 10994887Schin { 11008462SApril.Chin@Sun.COM indx = path_search(com0,NIL(Pathcomp_t**),0); 11014887Schin if(indx==1) 11028462SApril.Chin@Sun.COM np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE); 11038462SApril.Chin@Sun.COM 11044887Schin if(!np->nvalue.ip) 11054887Schin { 11064887Schin if(indx==1) 11074887Schin { 11084887Schin errormsg(SH_DICT,ERROR_exit(0),e_defined,com0); 11098462SApril.Chin@Sun.COM shp->exitval = ERROR_NOEXEC; 11104887Schin } 11114887Schin else 11124887Schin { 11134887Schin errormsg(SH_DICT,ERROR_exit(0),e_found,"function"); 11148462SApril.Chin@Sun.COM shp->exitval = ERROR_NOENT; 11154887Schin } 11164887Schin goto setexit; 11174887Schin } 11184887Schin } 11194887Schin /* increase refcnt for unset */ 11204887Schin slp = (struct slnod*)np->nvenv; 11214887Schin sh_funstaks(slp->slchild,1); 11224887Schin staklink(slp->slptr); 11234887Schin if(nq) 11244887Schin { 11258462SApril.Chin@Sun.COM shp->last_table = last_table; 1126*12068SRoger.Faulkner@Oracle.COM mode = set_instance(shp,nq,&node,&nr); 11274887Schin } 11284887Schin if(io) 11294887Schin { 11308462SApril.Chin@Sun.COM indx = shp->topfd; 11314887Schin sh_pushcontext(&buff,SH_JMPCMD); 11324887Schin jmpval = sigsetjmp(buff.buff,0); 11334887Schin } 11344887Schin if(jmpval == 0) 11354887Schin { 11364887Schin if(io) 11378462SApril.Chin@Sun.COM indx = sh_redirect(shp,io,execflg); 11388462SApril.Chin@Sun.COM sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG)); 11394887Schin } 11404887Schin if(io) 11414887Schin { 11424887Schin if(buff.olist) 11434887Schin free_list(buff.olist); 11444887Schin sh_popcontext(&buff); 11458462SApril.Chin@Sun.COM sh_iorestore(shp,indx,jmpval); 11464887Schin } 11474887Schin if(nq) 11488462SApril.Chin@Sun.COM unset_instance(nq,&node,&nr,mode); 11494887Schin sh_funstaks(slp->slchild,-1); 11504887Schin stakdelete(slp->slptr); 11514887Schin if(jmpval > SH_JMPFUN) 11528462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 11534887Schin goto setexit; 11544887Schin } 11554887Schin } 11564887Schin else if(!io) 11574887Schin { 11584887Schin setexit: 11594887Schin exitset(); 11604887Schin break; 11614887Schin } 11624887Schin } 11634887Schin case TFORK: 11644887Schin { 11654887Schin register pid_t parent; 11664887Schin int no_fork,jobid; 11674887Schin int pipes[2]; 11688462SApril.Chin@Sun.COM if(shp->subshell) 116910898Sroland.mainz@nrubsig.org { 117010898Sroland.mainz@nrubsig.org if(shp->subshare) 117110898Sroland.mainz@nrubsig.org sh_subtmpfile(1); 117210898Sroland.mainz@nrubsig.org else 117310898Sroland.mainz@nrubsig.org sh_subfork(); 117410898Sroland.mainz@nrubsig.org } 117510898Sroland.mainz@nrubsig.org no_fork = !ntflag && !(type&(FAMP|FPOU)) && 117610898Sroland.mainz@nrubsig.org !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && 1177*12068SRoger.Faulkner@Oracle.COM ((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL && 117810898Sroland.mainz@nrubsig.org (execflg2 || (execflg && 117910898Sroland.mainz@nrubsig.org !shp->subshell && shp->fn_depth==0 && 118010898Sroland.mainz@nrubsig.org !(pipejob && sh_isoption(SH_PIPEFAIL)) 118110898Sroland.mainz@nrubsig.org )); 11828462SApril.Chin@Sun.COM if(sh_isstate(SH_PROFILE) || shp->dot_depth) 11834887Schin { 11844887Schin /* disable foreground job monitor */ 11854887Schin if(!(type&FAMP)) 11864887Schin sh_offstate(SH_MONITOR); 11874887Schin #if SHOPT_DEVFD 11884887Schin else if(!(type&FINT)) 11894887Schin sh_offstate(SH_MONITOR); 11904887Schin #endif /* SHOPT_DEVFD */ 11914887Schin } 11924887Schin if(no_fork) 11934887Schin job.parent=parent=0; 11944887Schin else 11954887Schin { 119610898Sroland.mainz@nrubsig.org #ifdef SHOPT_BGX 119710898Sroland.mainz@nrubsig.org int maxjob; 119810898Sroland.mainz@nrubsig.org if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0) 119910898Sroland.mainz@nrubsig.org { 120010898Sroland.mainz@nrubsig.org while(job.numbjob >= maxjob) 120110898Sroland.mainz@nrubsig.org { 120210898Sroland.mainz@nrubsig.org job_lock(); 120310898Sroland.mainz@nrubsig.org job_reap(0); 120410898Sroland.mainz@nrubsig.org job_unlock(); 120510898Sroland.mainz@nrubsig.org } 120610898Sroland.mainz@nrubsig.org } 120710898Sroland.mainz@nrubsig.org #endif /* SHOPT_BGX */ 12084887Schin if(type&FCOOP) 12098462SApril.Chin@Sun.COM coproc_init(shp,pipes); 12104887Schin nv_getval(RANDNOD); 12114887Schin #if SHOPT_AMP 12124887Schin if((type&(FAMP|FINT)) == (FAMP|FINT)) 12138462SApril.Chin@Sun.COM parent = sh_ntfork(shp,t,com,&jobid,ntflag); 12144887Schin else 12154887Schin parent = sh_fork(type,&jobid); 12164887Schin if(parent<0) 12174887Schin break; 12184887Schin #else 12194887Schin #if SHOPT_SPAWN 12204887Schin # ifdef _lib_fork 12214887Schin if(com) 12228462SApril.Chin@Sun.COM parent = sh_ntfork(shp,t,com,&jobid,ntflag); 12234887Schin else 12244887Schin parent = sh_fork(type,&jobid); 12254887Schin # else 12268462SApril.Chin@Sun.COM if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0) 12274887Schin break; 12284887Schin # endif /* _lib_fork */ 12294887Schin if(parent<0) 12304887Schin break; 12314887Schin #else 12324887Schin parent = sh_fork(type,&jobid); 12334887Schin #endif /* SHOPT_SPAWN */ 12344887Schin #endif 12354887Schin } 12364887Schin if(job.parent=parent) 12374887Schin /* This is the parent branch of fork 12384887Schin * It may or may not wait for the child 12394887Schin */ 12404887Schin { 124110898Sroland.mainz@nrubsig.org if(pipejob==2) 124210898Sroland.mainz@nrubsig.org { 124310898Sroland.mainz@nrubsig.org pipejob = 1; 124410898Sroland.mainz@nrubsig.org job_unlock(); 124510898Sroland.mainz@nrubsig.org } 12464887Schin if(type&FPCL) 12478462SApril.Chin@Sun.COM sh_close(shp->inpipe[0]); 12484887Schin if(type&(FCOOP|FAMP)) 12498462SApril.Chin@Sun.COM shp->bckpid = parent; 12508462SApril.Chin@Sun.COM else if(!(type&(FAMP|FPOU))) 12514887Schin { 12528462SApril.Chin@Sun.COM if(shp->topfd > topfd) 12538462SApril.Chin@Sun.COM sh_iorestore(shp,topfd,0); 12548462SApril.Chin@Sun.COM if(!sh_isoption(SH_MONITOR)) 12558462SApril.Chin@Sun.COM { 12568462SApril.Chin@Sun.COM if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF))) 12578462SApril.Chin@Sun.COM sh_sigtrap(SIGINT); 12588462SApril.Chin@Sun.COM shp->trapnote |= SH_SIGIGNORE; 12598462SApril.Chin@Sun.COM } 126010898Sroland.mainz@nrubsig.org if(execflg && shp->subshell && !shp->subshare) 12618462SApril.Chin@Sun.COM { 12628462SApril.Chin@Sun.COM shp->spid = parent; 12638462SApril.Chin@Sun.COM job.pwlist->p_env--; 12648462SApril.Chin@Sun.COM } 126510898Sroland.mainz@nrubsig.org else if(shp->pipepid) 126610898Sroland.mainz@nrubsig.org shp->pipepid = parent; 12678462SApril.Chin@Sun.COM else 12688462SApril.Chin@Sun.COM job_wait(parent); 12698462SApril.Chin@Sun.COM if(!sh_isoption(SH_MONITOR)) 12708462SApril.Chin@Sun.COM { 12718462SApril.Chin@Sun.COM shp->trapnote &= ~SH_SIGIGNORE; 12728462SApril.Chin@Sun.COM if(shp->exitval == (SH_EXITSIG|SIGINT)) 12738462SApril.Chin@Sun.COM sh_fault(SIGINT); 12748462SApril.Chin@Sun.COM } 12754887Schin } 12764887Schin if(type&FAMP) 12774887Schin { 12784887Schin if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE)) 12794887Schin { 12804887Schin /* print job number */ 12814887Schin #ifdef JOBS 12824887Schin sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent); 12834887Schin #else 12844887Schin sfprintf(sfstderr,"%d\n",parent); 12854887Schin #endif /* JOBS */ 12864887Schin } 12874887Schin } 12884887Schin break; 12894887Schin } 12904887Schin else 12914887Schin /* 12924887Schin * this is the FORKED branch (child) of execute 12934887Schin */ 12944887Schin { 12958462SApril.Chin@Sun.COM volatile int jmpval; 12964887Schin struct checkpt buff; 12974887Schin if(no_fork) 12984887Schin sh_sigreset(2); 12994887Schin sh_pushcontext(&buff,SH_JMPEXIT); 13004887Schin jmpval = sigsetjmp(buff.buff,0); 13014887Schin if(jmpval) 13024887Schin goto done; 13034887Schin if((type&FINT) && !sh_isstate(SH_MONITOR)) 13044887Schin { 13054887Schin /* default std input for & */ 13064887Schin signal(SIGINT,SIG_IGN); 13074887Schin signal(SIGQUIT,SIG_IGN); 13088462SApril.Chin@Sun.COM if(!shp->st.ioset) 13094887Schin { 13104887Schin if(sh_close(0)>=0) 13114887Schin sh_chkopen(e_devnull); 13124887Schin } 13134887Schin } 13144887Schin sh_offstate(SH_MONITOR); 13154887Schin /* pipe in or out */ 13164887Schin #ifdef _lib_nice 13174887Schin if((type&FAMP) && sh_isoption(SH_BGNICE)) 13184887Schin nice(4); 13194887Schin #endif /* _lib_nice */ 13204887Schin if(type&FPIN) 13214887Schin { 13228462SApril.Chin@Sun.COM sh_iorenumber(shp,shp->inpipe[0],0); 13234887Schin if(!(type&FPOU) || (type&FCOOP)) 13248462SApril.Chin@Sun.COM sh_close(shp->inpipe[1]); 13254887Schin } 13264887Schin if(type&FPOU) 13274887Schin { 13288462SApril.Chin@Sun.COM sh_iorenumber(shp,shp->outpipe[1],1); 13298462SApril.Chin@Sun.COM sh_pclose(shp->outpipe); 13304887Schin } 13314887Schin if((type&COMMSK)!=TCOM) 13328462SApril.Chin@Sun.COM error_info.line = t->fork.forkline-shp->st.firstline; 13338462SApril.Chin@Sun.COM if(shp->topfd) 13348462SApril.Chin@Sun.COM sh_iounsave(shp); 13358462SApril.Chin@Sun.COM topfd = shp->topfd; 13368462SApril.Chin@Sun.COM sh_redirect(shp,t->tre.treio,1); 13378462SApril.Chin@Sun.COM if(shp->topfd > topfd) 13388462SApril.Chin@Sun.COM { 1339*12068SRoger.Faulkner@Oracle.COM job_lock(); 13408462SApril.Chin@Sun.COM while((parent = vfork()) < 0) 13418462SApril.Chin@Sun.COM _sh_fork(parent, 0, (int*)0); 1342*12068SRoger.Faulkner@Oracle.COM job_fork(parent); 13438462SApril.Chin@Sun.COM if(parent) 13448462SApril.Chin@Sun.COM { 13458462SApril.Chin@Sun.COM job_clear(); 13468462SApril.Chin@Sun.COM job_post(parent,0); 13478462SApril.Chin@Sun.COM job_wait(parent); 13488462SApril.Chin@Sun.COM sh_iorestore(shp,topfd,SH_JMPCMD); 13498462SApril.Chin@Sun.COM sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0); 13508462SApril.Chin@Sun.COM 13518462SApril.Chin@Sun.COM } 13528462SApril.Chin@Sun.COM } 13534887Schin if((type&COMMSK)!=TCOM) 13544887Schin { 13554887Schin /* don't clear job table for out 13564887Schin pipes so that jobs comand can 13574887Schin be used in a pipeline 13584887Schin */ 13594887Schin if(!no_fork && !(type&FPOU)) 13604887Schin job_clear(); 136110898Sroland.mainz@nrubsig.org sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED)); 13624887Schin } 13634887Schin else if(com0) 13644887Schin { 13654887Schin sh_offoption(SH_ERREXIT); 13668462SApril.Chin@Sun.COM sh_freeup(shp); 13674887Schin path_exec(com0,com,t->com.comset); 13684887Schin } 13694887Schin done: 13704887Schin sh_popcontext(&buff); 13714887Schin if(jmpval>SH_JMPEXIT) 13728462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 13738462SApril.Chin@Sun.COM sh_done(shp,0); 13744887Schin } 13754887Schin } 13764887Schin 13774887Schin case TSETIO: 13784887Schin { 13794887Schin /* 13804887Schin * don't create a new process, just 13814887Schin * save and restore io-streams 13824887Schin */ 13834887Schin pid_t pid; 138410898Sroland.mainz@nrubsig.org int jmpval, waitall; 138510898Sroland.mainz@nrubsig.org int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM; 13864887Schin struct checkpt buff; 13878462SApril.Chin@Sun.COM if(shp->subshell) 13884887Schin execflg = 0; 13894887Schin sh_pushcontext(&buff,SH_JMPIO); 13904887Schin if(type&FPIN) 13914887Schin { 13924887Schin was_interactive = sh_isstate(SH_INTERACTIVE); 13934887Schin sh_offstate(SH_INTERACTIVE); 139410898Sroland.mainz@nrubsig.org sh_iosave(shp,0,shp->topfd,(char*)0); 139510898Sroland.mainz@nrubsig.org shp->pipepid = simple; 13968462SApril.Chin@Sun.COM sh_iorenumber(shp,shp->inpipe[0],0); 13974887Schin /* 13984887Schin * if read end of pipe is a simple command 13994887Schin * treat as non-sharable to improve performance 14004887Schin */ 140110898Sroland.mainz@nrubsig.org if(simple) 14024887Schin sfset(sfstdin,SF_PUBLIC|SF_SHARE,0); 14034887Schin waitall = job.waitall; 14044887Schin job.waitall = 0; 14054887Schin pid = job.parent; 14064887Schin } 14074887Schin else 14088462SApril.Chin@Sun.COM error_info.line = t->fork.forkline-shp->st.firstline; 14094887Schin jmpval = sigsetjmp(buff.buff,0); 14104887Schin if(jmpval==0) 14114887Schin { 14128462SApril.Chin@Sun.COM sh_redirect(shp,t->fork.forkio,execflg); 14134887Schin (t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME; 141410898Sroland.mainz@nrubsig.org sh_exec(t->fork.forktre,flags&~simple); 14154887Schin } 14168462SApril.Chin@Sun.COM else 14178462SApril.Chin@Sun.COM sfsync(shp->outpool); 14184887Schin sh_popcontext(&buff); 14198462SApril.Chin@Sun.COM sh_iorestore(shp,buff.topfd,jmpval); 14204887Schin if(buff.olist) 14214887Schin free_list(buff.olist); 14224887Schin if(type&FPIN) 14234887Schin { 14244887Schin job.waitall = waitall; 14258462SApril.Chin@Sun.COM type = shp->exitval; 14264887Schin if(!(type&SH_EXITSIG)) 14274887Schin { 14284887Schin /* wait for remainder of pipline */ 142910898Sroland.mainz@nrubsig.org if(shp->pipepid>1) 143010898Sroland.mainz@nrubsig.org { 143110898Sroland.mainz@nrubsig.org job_wait(shp->pipepid); 143210898Sroland.mainz@nrubsig.org type = shp->exitval; 143310898Sroland.mainz@nrubsig.org } 143410898Sroland.mainz@nrubsig.org else 143510898Sroland.mainz@nrubsig.org job_wait(waitall?pid:0); 14364887Schin if(type || !sh_isoption(SH_PIPEFAIL)) 14378462SApril.Chin@Sun.COM shp->exitval = type; 14384887Schin } 143910898Sroland.mainz@nrubsig.org shp->pipepid = 0; 14408462SApril.Chin@Sun.COM shp->st.ioset = 0; 144110898Sroland.mainz@nrubsig.org if(simple && was_errexit) 144210898Sroland.mainz@nrubsig.org { 144310898Sroland.mainz@nrubsig.org echeck = 1; 144410898Sroland.mainz@nrubsig.org sh_onstate(SH_ERREXIT); 144510898Sroland.mainz@nrubsig.org } 14464887Schin } 14474887Schin if(jmpval>SH_JMPIO) 14488462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 14494887Schin break; 14504887Schin } 14514887Schin 14524887Schin case TPAR: 14534887Schin echeck = 1; 14544887Schin flags &= ~OPTIMIZE_FLAG; 14558462SApril.Chin@Sun.COM if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK))) 14564887Schin { 145710898Sroland.mainz@nrubsig.org char *savsig; 145810898Sroland.mainz@nrubsig.org int nsig,jmpval; 14594887Schin struct checkpt buff; 146010898Sroland.mainz@nrubsig.org shp->st.otrapcom = 0; 146110898Sroland.mainz@nrubsig.org if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0]) 146210898Sroland.mainz@nrubsig.org { 146310898Sroland.mainz@nrubsig.org nsig += sizeof(char*); 146410898Sroland.mainz@nrubsig.org memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig); 146510898Sroland.mainz@nrubsig.org shp->st.otrapcom = (char**)savsig; 146610898Sroland.mainz@nrubsig.org } 146710898Sroland.mainz@nrubsig.org sh_sigreset(0); 14684887Schin sh_pushcontext(&buff,SH_JMPEXIT); 14694887Schin jmpval = sigsetjmp(buff.buff,0); 14704887Schin if(jmpval==0) 14714887Schin sh_exec(t->par.partre,flags); 14724887Schin sh_popcontext(&buff); 14734887Schin if(jmpval > SH_JMPEXIT) 14748462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 14758462SApril.Chin@Sun.COM sh_done(shp,0); 14764887Schin } 14774887Schin else 14784887Schin sh_subshell(t->par.partre,flags,0); 14794887Schin break; 14804887Schin 14814887Schin case TFIL: 14824887Schin { 14834887Schin /* 14844887Schin * This code sets up a pipe. 14854887Schin * All elements of the pipe are started by the parent. 14864887Schin * The last element executes in current environment 14874887Schin */ 14884887Schin int pvo[2]; /* old pipe for multi-stage */ 14894887Schin int pvn[2]; /* current set up pipe */ 14904887Schin int savepipe = pipejob; 14914887Schin int showme = t->tre.tretyp&FSHOWME; 14924887Schin pid_t savepgid = job.curpgid; 14938462SApril.Chin@Sun.COM job.curpgid = 0; 14948462SApril.Chin@Sun.COM if(shp->subshell) 14958810SCasper.Dik@Sun.COM { 14968810SCasper.Dik@Sun.COM if(shp->subshare) 14978810SCasper.Dik@Sun.COM sh_subtmpfile(0); 14988810SCasper.Dik@Sun.COM else 14998810SCasper.Dik@Sun.COM sh_subfork(); 15008810SCasper.Dik@Sun.COM } 15018462SApril.Chin@Sun.COM shp->inpipe = pvo; 15028462SApril.Chin@Sun.COM shp->outpipe = pvn; 15034887Schin pvo[1] = -1; 15044887Schin if(sh_isoption(SH_PIPEFAIL)) 15054887Schin job.waitall = 1; 15064887Schin else 15074887Schin job.waitall |= !pipejob && sh_isstate(SH_MONITOR); 150810898Sroland.mainz@nrubsig.org job_lock(); 15094887Schin do 15104887Schin { 15114887Schin #if SHOPT_FASTPIPE 15128462SApril.Chin@Sun.COM type = pipe_exec(shp,pvn,t->lst.lstlef, errorflg); 15134887Schin #else 15144887Schin /* create the pipe */ 15154887Schin sh_pipe(pvn); 15164887Schin /* execute out part of pipe no wait */ 15174887Schin (t->lst.lstlef)->tre.tretyp |= showme; 15184887Schin type = sh_exec(t->lst.lstlef, errorflg); 15194887Schin #endif /* SHOPT_FASTPIPE */ 15204887Schin pipejob=1; 15214887Schin /* save the pipe stream-ids */ 15224887Schin pvo[0] = pvn[0]; 15234887Schin /* close out-part of pipe */ 15244887Schin sh_close(pvn[1]); 15254887Schin /* pipeline all in one process group */ 15264887Schin t = t->lst.lstrit; 15274887Schin } 15284887Schin /* repeat until end of pipeline */ 15294887Schin while(!type && t->tre.tretyp==TFIL); 15308462SApril.Chin@Sun.COM shp->inpipe = pvn; 15318462SApril.Chin@Sun.COM shp->outpipe = 0; 153210898Sroland.mainz@nrubsig.org pipejob = 2; 15334887Schin if(type == 0) 15344887Schin { 15354887Schin /* 15364887Schin * execute last element of pipeline 15374887Schin * in the current process 15384887Schin */ 15394887Schin ((Shnode_t*)t)->tre.tretyp |= showme; 15404887Schin sh_exec(t,flags); 15414887Schin } 15424887Schin else 15434887Schin /* execution failure, close pipe */ 15444887Schin sh_pclose(pvn); 154510898Sroland.mainz@nrubsig.org if(pipejob==2) 154610898Sroland.mainz@nrubsig.org job_unlock(); 15474887Schin pipejob = savepipe; 15484887Schin #ifdef SIGTSTP 15494887Schin if(!pipejob && sh_isstate(SH_MONITOR)) 15508462SApril.Chin@Sun.COM tcsetpgrp(JOBTTY,shp->pid); 15514887Schin #endif /*SIGTSTP */ 15524887Schin job.curpgid = savepgid; 15534887Schin break; 15544887Schin } 15554887Schin 15564887Schin case TLST: 15574887Schin { 15584887Schin /* a list of commands are executed here */ 15594887Schin do 15604887Schin { 15614887Schin sh_exec(t->lst.lstlef,errorflg|OPTIMIZE); 15624887Schin t = t->lst.lstrit; 15634887Schin } 15644887Schin while(t->tre.tretyp == TLST); 15654887Schin sh_exec(t,flags); 15664887Schin break; 15674887Schin } 15684887Schin 15694887Schin case TAND: 15704887Schin if(type&TTEST) 15714887Schin skipexitset++; 15724887Schin if(sh_exec(t->lst.lstlef,OPTIMIZE)==0) 15734887Schin sh_exec(t->lst.lstrit,flags); 15744887Schin break; 15754887Schin 15764887Schin case TORF: 15774887Schin if(type&TTEST) 15784887Schin skipexitset++; 15794887Schin if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0) 15804887Schin sh_exec(t->lst.lstrit,flags); 15814887Schin break; 15824887Schin 15834887Schin case TFOR: /* for and select */ 15844887Schin { 15854887Schin register char **args; 15864887Schin register int nargs; 15874887Schin register Namval_t *np; 15884887Schin int flag = errorflg|OPTIMIZE_FLAG; 15894887Schin struct dolnod *argsav=0; 15904887Schin struct comnod *tp; 15914887Schin char *cp, *trap, *nullptr = 0; 15924887Schin int nameref, refresh=1; 15938462SApril.Chin@Sun.COM char *av[5]; 15944887Schin #if SHOPT_OPTIMIZE 15958462SApril.Chin@Sun.COM int jmpval = ((struct checkpt*)shp->jmplist)->mode; 15964887Schin struct checkpt buff; 15978462SApril.Chin@Sun.COM void *optlist = shp->optlist; 15988462SApril.Chin@Sun.COM shp->optlist = 0; 15994887Schin sh_tclear(t->for_.fortre); 16004887Schin sh_pushcontext(&buff,jmpval); 16014887Schin jmpval = sigsetjmp(buff.buff,0); 16024887Schin if(jmpval) 16034887Schin goto endfor; 16044887Schin #endif /* SHOPT_OPTIMIZE */ 16058462SApril.Chin@Sun.COM error_info.line = t->for_.forline-shp->st.firstline; 16064887Schin if(!(tp=t->for_.forlst)) 16074887Schin { 16088462SApril.Chin@Sun.COM args=shp->st.dolv+1; 16098462SApril.Chin@Sun.COM nargs = shp->st.dolc; 16108462SApril.Chin@Sun.COM argsav=sh_arguse(shp); 16114887Schin } 16124887Schin else 16134887Schin { 16148462SApril.Chin@Sun.COM args=sh_argbuild(shp,&argn,tp,0); 16154887Schin nargs = argn; 16164887Schin } 16178462SApril.Chin@Sun.COM np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF); 16184887Schin nameref = nv_isref(np)!=0; 16198462SApril.Chin@Sun.COM shp->st.loopcnt++; 16204887Schin cp = *args; 16218462SApril.Chin@Sun.COM while(cp && shp->st.execbrk==0) 16224887Schin { 16234887Schin if(t->tre.tretyp&COMSCAN) 16244887Schin { 16254887Schin char *val; 16264887Schin int save_prompt; 16274887Schin /* reuse register */ 16284887Schin if(refresh) 16294887Schin { 16304887Schin sh_menu(sfstderr,nargs,args); 16314887Schin refresh = 0; 16324887Schin } 16338462SApril.Chin@Sun.COM save_prompt = shp->nextprompt; 16348462SApril.Chin@Sun.COM shp->nextprompt = 3; 16358462SApril.Chin@Sun.COM shp->timeout = 0; 16368462SApril.Chin@Sun.COM shp->exitval=sh_readline(shp,&nullptr,0,1,1000*shp->st.tmout); 16378462SApril.Chin@Sun.COM shp->nextprompt = save_prompt; 16388462SApril.Chin@Sun.COM if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin)) 16394887Schin { 16408462SApril.Chin@Sun.COM shp->exitval = 1; 16414887Schin break; 16424887Schin } 16438462SApril.Chin@Sun.COM if(!(val=nv_getval(sh_scoped(shp,REPLYNOD)))) 16444887Schin continue; 16454887Schin else 16464887Schin { 16474887Schin if(*(cp=val) == 0) 16484887Schin { 16494887Schin refresh++; 16504887Schin goto check; 16514887Schin } 16524887Schin while(type = *cp++) 16534887Schin if(type < '0' && type > '9') 16544887Schin break; 16554887Schin if(type!=0) 16564887Schin type = nargs; 16574887Schin else 16584887Schin type = (int)strtol(val, (char**)0, 10)-1; 16594887Schin if(type<0 || type >= nargs) 16604887Schin cp = ""; 16614887Schin else 16624887Schin cp = args[type]; 16634887Schin } 16644887Schin } 16654887Schin if(nameref) 16664887Schin nv_offattr(np,NV_REF); 16674887Schin else if(nv_isattr(np, NV_ARRAY)) 16684887Schin nv_putsub(np,NIL(char*),0L); 16694887Schin nv_putval(np,cp,0); 16704887Schin if(nameref) 16714887Schin nv_setref(np,(Dt_t*)0,NV_VARNAME); 16728462SApril.Chin@Sun.COM if(trap=shp->st.trap[SH_DEBUGTRAP]) 16734887Schin { 16744887Schin av[0] = (t->tre.tretyp&COMSCAN)?"select":"for"; 16754887Schin av[1] = t->for_.fornam; 16768462SApril.Chin@Sun.COM av[2] = "in"; 16774887Schin av[3] = cp; 16788462SApril.Chin@Sun.COM av[4] = 0; 16798462SApril.Chin@Sun.COM sh_debug(shp,trap,(char*)0,(char*)0,av,0); 16804887Schin } 16814887Schin sh_exec(t->for_.fortre,flag); 16824887Schin flag &= ~OPTIMIZE_FLAG; 16834887Schin if(t->tre.tretyp&COMSCAN) 16844887Schin { 16858462SApril.Chin@Sun.COM if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0) 16864887Schin refresh++; 16874887Schin } 16884887Schin else 16894887Schin cp = *++args; 16904887Schin check: 16918462SApril.Chin@Sun.COM if(shp->st.breakcnt<0) 16928462SApril.Chin@Sun.COM shp->st.execbrk = (++shp->st.breakcnt !=0); 16934887Schin } 16944887Schin #if SHOPT_OPTIMIZE 16954887Schin endfor: 16964887Schin sh_popcontext(&buff); 16974887Schin sh_tclear(t->for_.fortre); 16988462SApril.Chin@Sun.COM sh_optclear(shp,optlist); 16994887Schin if(jmpval) 17008462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 17014887Schin #endif /*SHOPT_OPTIMIZE */ 17028462SApril.Chin@Sun.COM if(shp->st.breakcnt>0) 17038462SApril.Chin@Sun.COM shp->st.execbrk = (--shp->st.breakcnt !=0); 17048462SApril.Chin@Sun.COM shp->st.loopcnt--; 17058462SApril.Chin@Sun.COM sh_argfree(shp,argsav,0); 17064887Schin nv_close(np); 17074887Schin break; 17084887Schin } 17094887Schin 17104887Schin case TWH: /* while and until */ 17114887Schin { 17128462SApril.Chin@Sun.COM volatile int r=0; 17134887Schin int first = OPTIMIZE_FLAG; 17144887Schin Shnode_t *tt = t->wh.whtre; 17154887Schin #if SHOPT_FILESCAN 17164887Schin Sfio_t *iop=0; 17174887Schin int savein,fd; 17184887Schin #endif /*SHOPT_FILESCAN*/ 17194887Schin #if SHOPT_OPTIMIZE 17208462SApril.Chin@Sun.COM int jmpval = ((struct checkpt*)shp->jmplist)->mode; 17214887Schin struct checkpt buff; 17228462SApril.Chin@Sun.COM void *optlist = shp->optlist; 17238462SApril.Chin@Sun.COM shp->optlist = 0; 17244887Schin sh_tclear(t->wh.whtre); 17254887Schin sh_tclear(t->wh.dotre); 17264887Schin sh_pushcontext(&buff,jmpval); 17274887Schin jmpval = sigsetjmp(buff.buff,0); 17284887Schin if(jmpval) 17294887Schin goto endwhile; 17304887Schin #endif /* SHOPT_OPTIMIZE */ 17314887Schin #if SHOPT_FILESCAN 17324887Schin if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio) 17334887Schin { 17348462SApril.Chin@Sun.COM fd = sh_redirect(shp,tt->com.comio,3); 17354887Schin savein = dup(0); 17364887Schin if(fd==0) 17374887Schin fd = savein; 17384887Schin iop = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ); 17394887Schin close(0); 17404887Schin open("/dev/null",O_RDONLY); 17418462SApril.Chin@Sun.COM shp->offsets[0] = -1; 17428462SApril.Chin@Sun.COM shp->offsets[1] = 0; 17434887Schin if(tt->com.comset) 174410898Sroland.mainz@nrubsig.org nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0); 17454887Schin } 17464887Schin #endif /*SHOPT_FILESCAN */ 17478462SApril.Chin@Sun.COM shp->st.loopcnt++; 17488462SApril.Chin@Sun.COM while(shp->st.execbrk==0) 17494887Schin { 17504887Schin #if SHOPT_FILESCAN 17514887Schin if(iop) 17524887Schin { 17538462SApril.Chin@Sun.COM if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING))) 17544887Schin break; 17554887Schin } 17564887Schin else 17574887Schin #endif /*SHOPT_FILESCAN */ 17584887Schin if((sh_exec(tt,first)==0)!=(type==TWH)) 17594887Schin break; 17604887Schin r = sh_exec(t->wh.dotre,first|errorflg); 17618462SApril.Chin@Sun.COM if(shp->st.breakcnt<0) 17628462SApril.Chin@Sun.COM shp->st.execbrk = (++shp->st.breakcnt !=0); 17634887Schin /* This is for the arithmetic for */ 17648462SApril.Chin@Sun.COM if(shp->st.execbrk==0 && t->wh.whinc) 17654887Schin sh_exec((Shnode_t*)t->wh.whinc,first); 17664887Schin first = 0; 17674887Schin errorflg &= ~OPTIMIZE_FLAG; 17684887Schin #if SHOPT_FILESCAN 17698462SApril.Chin@Sun.COM shp->offsets[0] = -1; 17708462SApril.Chin@Sun.COM shp->offsets[1] = 0; 17714887Schin #endif /*SHOPT_FILESCAN */ 17724887Schin } 17734887Schin #if SHOPT_OPTIMIZE 17744887Schin endwhile: 17754887Schin sh_popcontext(&buff); 17764887Schin sh_tclear(t->wh.whtre); 17774887Schin sh_tclear(t->wh.dotre); 17788462SApril.Chin@Sun.COM sh_optclear(shp,optlist); 17794887Schin if(jmpval) 17808462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 17814887Schin #endif /*SHOPT_OPTIMIZE */ 17828462SApril.Chin@Sun.COM if(shp->st.breakcnt>0) 17838462SApril.Chin@Sun.COM shp->st.execbrk = (--shp->st.breakcnt !=0); 17848462SApril.Chin@Sun.COM shp->st.loopcnt--; 17858462SApril.Chin@Sun.COM shp->exitval= r; 17864887Schin #if SHOPT_FILESCAN 17874887Schin if(iop) 17884887Schin { 17894887Schin sfclose(iop); 17904887Schin close(0); 17914887Schin dup(savein); 17928462SApril.Chin@Sun.COM shp->cur_line = 0; 17934887Schin } 17944887Schin #endif /*SHOPT_FILESCAN */ 17954887Schin break; 17964887Schin } 17974887Schin case TARITH: /* (( expression )) */ 17984887Schin { 17994887Schin register char *trap; 18008462SApril.Chin@Sun.COM char *arg[4]; 18018462SApril.Chin@Sun.COM error_info.line = t->ar.arline-shp->st.firstline; 18028462SApril.Chin@Sun.COM arg[0] = "(("; 18034887Schin if(!(t->ar.arexpr->argflag&ARG_RAW)) 18048462SApril.Chin@Sun.COM arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH); 18054887Schin else 18064887Schin arg[1] = t->ar.arexpr->argval; 18078462SApril.Chin@Sun.COM arg[2] = "))"; 18088462SApril.Chin@Sun.COM arg[3] = 0; 18098462SApril.Chin@Sun.COM if(trap=shp->st.trap[SH_DEBUGTRAP]) 18108462SApril.Chin@Sun.COM sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH); 18114887Schin if(sh_isoption(SH_XTRACE)) 18124887Schin { 18134887Schin sh_trace(NIL(char**),0); 18144887Schin sfprintf(sfstderr,"((%s))\n",arg[1]); 18154887Schin } 18164887Schin if(t->ar.arcomp) 18178462SApril.Chin@Sun.COM shp->exitval = !arith_exec((Arith_t*)t->ar.arcomp); 18184887Schin else 18198462SApril.Chin@Sun.COM shp->exitval = !sh_arith(arg[1]); 18204887Schin break; 18214887Schin } 18224887Schin 18234887Schin case TIF: 18244887Schin if(sh_exec(t->if_.iftre,OPTIMIZE)==0) 18254887Schin sh_exec(t->if_.thtre,flags); 18264887Schin else if(t->if_.eltre) 18274887Schin sh_exec(t->if_.eltre, flags); 18284887Schin else 18298462SApril.Chin@Sun.COM shp->exitval=0; /* force zero exit for if-then-fi */ 18304887Schin break; 18314887Schin 18324887Schin case TSW: 18334887Schin { 18344887Schin Shnode_t *tt = (Shnode_t*)t; 18358462SApril.Chin@Sun.COM char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE); 18368462SApril.Chin@Sun.COM error_info.line = t->sw.swline-shp->st.firstline; 18374887Schin t= (Shnode_t*)(tt->sw.swlst); 18388462SApril.Chin@Sun.COM if(trap=shp->st.trap[SH_DEBUGTRAP]) 18394887Schin { 18408462SApril.Chin@Sun.COM char *av[4]; 18418462SApril.Chin@Sun.COM av[0] = "case"; 18424887Schin av[1] = r; 18438462SApril.Chin@Sun.COM av[2] = "in"; 18448462SApril.Chin@Sun.COM av[3] = 0; 18458462SApril.Chin@Sun.COM sh_debug(shp,trap, (char*)0, (char*)0, av, 0); 18464887Schin } 18474887Schin while(t) 18484887Schin { 18494887Schin register struct argnod *rex=(struct argnod*)t->reg.regptr; 18504887Schin while(rex) 18514887Schin { 18524887Schin register char *s; 18534887Schin if(rex->argflag&ARG_MAC) 18544887Schin { 18558462SApril.Chin@Sun.COM s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP); 18564887Schin while(*s=='\\' && s[1]==0) 18574887Schin s+=2; 18584887Schin } 18594887Schin else 18604887Schin s = rex->argval; 18614887Schin type = (rex->argflag&ARG_RAW); 18624887Schin if((type && strcmp(r,s)==0) || 18634887Schin (!type && (strmatch(r,s) 18644887Schin || trim_eq(r,s)))) 18654887Schin { 18664887Schin do sh_exec(t->reg.regcom,(t->reg.regflag?0:flags)); 18674887Schin while(t->reg.regflag && 18684887Schin (t=(Shnode_t*)t->reg.regnxt)); 18694887Schin t=0; 18704887Schin break; 18714887Schin } 18724887Schin else 18734887Schin rex=rex->argnxt.ap; 18744887Schin } 18754887Schin if(t) 18764887Schin t=(Shnode_t*)t->reg.regnxt; 18774887Schin } 18784887Schin break; 18794887Schin } 18804887Schin 18814887Schin case TTIME: 18824887Schin { 18834887Schin /* time the command */ 18844887Schin struct tms before,after; 18854887Schin const char *format = e_timeformat; 18864887Schin clock_t at, tm[3]; 18874887Schin #ifdef timeofday 18884887Schin struct timeval tb,ta; 18894887Schin #else 18904887Schin clock_t bt; 18914887Schin #endif /* timeofday */ 18924887Schin if(type!=TTIME) 18934887Schin { 18944887Schin sh_exec(t->par.partre,OPTIMIZE); 18958462SApril.Chin@Sun.COM shp->exitval = !shp->exitval; 18964887Schin break; 18974887Schin } 18984887Schin if(t->par.partre) 18994887Schin { 19004887Schin long timer_on; 19014887Schin timer_on = sh_isstate(SH_TIMING); 19024887Schin #ifdef timeofday 19034887Schin timeofday(&tb); 19044887Schin times(&before); 19054887Schin #else 19064887Schin bt = times(&before); 19074887Schin #endif /* timeofday */ 19084887Schin job.waitall = 1; 19094887Schin sh_onstate(SH_TIMING); 19104887Schin sh_exec(t->par.partre,OPTIMIZE); 19114887Schin if(!timer_on) 19124887Schin sh_offstate(SH_TIMING); 19134887Schin job.waitall = 0; 19144887Schin } 19154887Schin else 19164887Schin { 19174887Schin #ifndef timeofday 19184887Schin bt = 0; 19194887Schin #endif /* timeofday */ 19204887Schin before.tms_utime = before.tms_cutime = 0; 19214887Schin before.tms_stime = before.tms_cstime = 0; 19224887Schin } 19234887Schin #ifdef timeofday 19244887Schin times(&after); 19254887Schin timeofday(&ta); 19268462SApril.Chin@Sun.COM at = shp->lim.clk_tck*(ta.tv_sec-tb.tv_sec); 19278462SApril.Chin@Sun.COM at += ((shp->lim.clk_tck*(((1000000L/2)/shp->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L); 19284887Schin #else 19294887Schin at = times(&after) - bt; 19304887Schin #endif /* timeofday */ 19314887Schin tm[0] = at; 19324887Schin if(t->par.partre) 19334887Schin { 19348462SApril.Chin@Sun.COM Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD); 19354887Schin if(np) 19364887Schin { 19374887Schin format = nv_getval(np); 19384887Schin nv_close(np); 19394887Schin } 19404887Schin if(!format) 19414887Schin format = e_timeformat; 19424887Schin } 19434887Schin else 19444887Schin format = strchr(format+1,'\n')+1; 19454887Schin tm[1] = after.tms_utime - before.tms_utime; 19464887Schin tm[1] += after.tms_cutime - before.tms_cutime; 19474887Schin tm[2] = after.tms_stime - before.tms_stime; 19484887Schin tm[2] += after.tms_cstime - before.tms_cstime; 19494887Schin if(format && *format) 19508462SApril.Chin@Sun.COM p_time(shp,sfstderr,sh_translate(format),tm); 19514887Schin break; 19524887Schin } 19534887Schin case TFUN: 19544887Schin { 19554887Schin register Namval_t *np; 19564887Schin register struct slnod *slp; 19574887Schin register char *fname = ((struct functnod*)t)->functnam; 19584887Schin register char *cp = strrchr(fname,'.'); 19594887Schin register Namval_t *npv=0; 19604887Schin #if SHOPT_NAMESPACE 19614887Schin if(t->tre.tretyp==TNSPACE) 19624887Schin { 19634887Schin Dt_t *root,*oldroot, *top=0; 19648462SApril.Chin@Sun.COM Namval_t *oldnspace = shp->namespace; 19658462SApril.Chin@Sun.COM int offset = stktell(stkp); 19668462SApril.Chin@Sun.COM long optindex = shp->st.optindex; 19674887Schin if(cp) 19684887Schin errormsg(SH_DICT,ERROR_exit(1),e_ident,fname); 19698462SApril.Chin@Sun.COM sfputc(stkp,'.'); 19708462SApril.Chin@Sun.COM sfputr(stkp,fname,0); 19718462SApril.Chin@Sun.COM np = nv_open(stkptr(stkp,offset),shp->var_base,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME); 19728462SApril.Chin@Sun.COM offset = stktell(stkp); 19738462SApril.Chin@Sun.COM shp->namespace = np; 19744887Schin if(!(root=nv_dict(np))) 19754887Schin { 19764887Schin root = dtopen(&_Nvdisc,Dtoset); 19774887Schin nv_putval(np,(char*)root,NV_TABLE|NV_NOFREE); 19788462SApril.Chin@Sun.COM shp->st.optindex = 1; 19794887Schin } 19808462SApril.Chin@Sun.COM if(oldnspace && dtvnext(dtvnext(shp->var_tree))) 19818462SApril.Chin@Sun.COM top = dtview(shp->var_tree,0); 19828462SApril.Chin@Sun.COM else if(dtvnext(shp->var_tree)) 19838462SApril.Chin@Sun.COM top = dtview(shp->var_tree,0); 19848462SApril.Chin@Sun.COM oldroot = shp->var_tree; 19858462SApril.Chin@Sun.COM dtview(root,shp->var_base); 19868462SApril.Chin@Sun.COM shp->var_tree = root; 19874887Schin if(top) 19888462SApril.Chin@Sun.COM dtview(shp->var_tree,top); 19894887Schin sh_exec(t->for_.fortre,flags); 19908462SApril.Chin@Sun.COM if(dtvnext(shp->var_tree)) 19918462SApril.Chin@Sun.COM top = dtview(shp->var_tree,0); 19928462SApril.Chin@Sun.COM shp->var_tree = oldroot; 19934887Schin if(top) 19948462SApril.Chin@Sun.COM dtview(top,shp->var_tree); 19958462SApril.Chin@Sun.COM shp->namespace = oldnspace; 19968462SApril.Chin@Sun.COM shp->st.optindex = optindex; 19974887Schin break; 19984887Schin } 19994887Schin #endif /* SHOPT_NAMESPACE */ 20004887Schin /* look for discipline functions */ 20018462SApril.Chin@Sun.COM error_info.line = t->funct.functline-shp->st.firstline; 20024887Schin /* Function names cannot be special builtin */ 20038462SApril.Chin@Sun.COM if(cp || shp->prefix) 20044887Schin { 20058462SApril.Chin@Sun.COM int offset = stktell(stkp); 20068462SApril.Chin@Sun.COM if(shp->prefix) 20074887Schin { 20088462SApril.Chin@Sun.COM cp = shp->prefix; 20098462SApril.Chin@Sun.COM shp->prefix = 0; 20108462SApril.Chin@Sun.COM npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME); 20118462SApril.Chin@Sun.COM shp->prefix = cp; 20124887Schin cp = fname; 20134887Schin } 20144887Schin else 20154887Schin { 20168462SApril.Chin@Sun.COM sfwrite(stkp,fname,cp++-fname); 20178462SApril.Chin@Sun.COM sfputc(stkp,0); 20188462SApril.Chin@Sun.COM npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME); 20194887Schin } 20208462SApril.Chin@Sun.COM offset = stktell(stkp); 20218462SApril.Chin@Sun.COM sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0); 20228462SApril.Chin@Sun.COM fname = stkptr(stkp,offset); 20234887Schin } 20248462SApril.Chin@Sun.COM else if((np=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC)) 20254887Schin errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname); 20264887Schin #if SHOPT_NAMESPACE 20278462SApril.Chin@Sun.COM else if(shp->namespace) 20284887Schin { 20298462SApril.Chin@Sun.COM int offset = stktell(stkp); 20308462SApril.Chin@Sun.COM sfputr(stkp,nv_name(shp->namespace),-1); 20318462SApril.Chin@Sun.COM sfputc(stkp,'.'); 20328462SApril.Chin@Sun.COM sfputr(stkp,fname,0); 20338462SApril.Chin@Sun.COM fname = stkptr(stkp,offset); 20344887Schin } 20354887Schin #endif /* SHOPT_NAMESPACE */ 20364887Schin np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE); 20374887Schin if(npv) 20384887Schin { 20398462SApril.Chin@Sun.COM Namval_t *tp = npv; 20408462SApril.Chin@Sun.COM if(!shp->mktype) 20418462SApril.Chin@Sun.COM { 20428462SApril.Chin@Sun.COM if(shp->typeinit) 20438462SApril.Chin@Sun.COM { 20448462SApril.Chin@Sun.COM if(tp=nv_open(shp->typeinit->nvname,shp->typedict,NV_IDENT|NV_NOFAIL)) 20458462SApril.Chin@Sun.COM nv_close(npv); 20468462SApril.Chin@Sun.COM else 20478462SApril.Chin@Sun.COM tp = npv; 20488462SApril.Chin@Sun.COM } 20498462SApril.Chin@Sun.COM cp = nv_setdisc(tp,cp,np,(Namfun_t*)tp); 20508462SApril.Chin@Sun.COM } 20518462SApril.Chin@Sun.COM nv_close(tp); 20524887Schin if(!cp) 20534887Schin errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname); 20544887Schin } 20554887Schin if(np->nvalue.rp) 20564887Schin { 20574887Schin slp = (struct slnod*)np->nvenv; 20584887Schin sh_funstaks(slp->slchild,-1); 20594887Schin stakdelete(slp->slptr); 20608462SApril.Chin@Sun.COM if(shp->funload) 20618462SApril.Chin@Sun.COM { 20628462SApril.Chin@Sun.COM free((void*)np->nvalue.rp); 20638462SApril.Chin@Sun.COM np->nvalue.rp = 0; 20648462SApril.Chin@Sun.COM } 20658462SApril.Chin@Sun.COM 20664887Schin } 20678462SApril.Chin@Sun.COM if(!np->nvalue.rp) 20688462SApril.Chin@Sun.COM { 20698462SApril.Chin@Sun.COM np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0); 20708462SApril.Chin@Sun.COM memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction)); 20718462SApril.Chin@Sun.COM } 20724887Schin if(t->funct.functstak) 20734887Schin { 20748462SApril.Chin@Sun.COM static Dtdisc_t _Rpdisc = 20758462SApril.Chin@Sun.COM { 20768462SApril.Chin@Sun.COM offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction) 20778462SApril.Chin@Sun.COM }; 20784887Schin struct functnod *fp; 20794887Schin slp = t->funct.functstak; 20804887Schin sh_funstaks(slp->slchild,1); 20814887Schin staklink(slp->slptr); 20824887Schin np->nvenv = (char*)slp; 20834887Schin nv_funtree(np) = (int*)(t->funct.functtre); 20844887Schin np->nvalue.rp->hoffset = t->funct.functloc; 20854887Schin np->nvalue.rp->lineno = t->funct.functline; 20868462SApril.Chin@Sun.COM np->nvalue.rp->nspace = shp->namespace; 20874887Schin np->nvalue.rp->fname = 0; 20888462SApril.Chin@Sun.COM np->nvalue.rp->fdict = shp->fun_tree; 20894887Schin fp = (struct functnod*)(slp+1); 20904887Schin if(fp->functtyp==(TFUN|FAMP)) 20914887Schin np->nvalue.rp->fname = fp->functnam; 20924887Schin nv_setsize(np,fp->functline); 20934887Schin nv_offattr(np,NV_FPOSIX); 20948462SApril.Chin@Sun.COM if(shp->funload) 20958462SApril.Chin@Sun.COM { 20968462SApril.Chin@Sun.COM struct Ufunction *rp = np->nvalue.rp; 20978462SApril.Chin@Sun.COM rp->np = np; 20988462SApril.Chin@Sun.COM if(!shp->fpathdict) 20998462SApril.Chin@Sun.COM shp->fpathdict = dtopen(&_Rpdisc,Dtbag); 21008462SApril.Chin@Sun.COM if(shp->fpathdict) 21018462SApril.Chin@Sun.COM dtinsert(shp->fpathdict,rp); 21028462SApril.Chin@Sun.COM } 21034887Schin } 21044887Schin else 21054887Schin nv_unset(np); 21064887Schin if(type&FPOSIX) 21074887Schin nv_onattr(np,NV_FUNCTION|NV_FPOSIX); 21084887Schin else 21094887Schin nv_onattr(np,NV_FUNCTION); 21104887Schin if(type&FPIN) 21114887Schin nv_onattr(np,NV_FTMP); 21128462SApril.Chin@Sun.COM if(type&FOPTGET) 21138462SApril.Chin@Sun.COM nv_onattr(np,NV_OPTGET); 21144887Schin break; 21154887Schin } 21164887Schin 21174887Schin /* new test compound command */ 21184887Schin case TTST: 21194887Schin { 21204887Schin register int n; 21214887Schin register char *left; 21224887Schin int negate = (type&TNEGATE)!=0; 21234887Schin if(type&TTEST) 21244887Schin skipexitset++; 21258462SApril.Chin@Sun.COM error_info.line = t->tst.tstline-shp->st.firstline; 21264887Schin echeck = 1; 21274887Schin if((type&TPAREN)==TPAREN) 21284887Schin { 21294887Schin sh_exec(t->lst.lstlef,OPTIMIZE); 21308462SApril.Chin@Sun.COM n = !shp->exitval; 21314887Schin } 21324887Schin else 21334887Schin { 21344887Schin register int traceon=0; 21354887Schin register char *right; 21364887Schin register char *trap; 21374887Schin char *argv[6]; 21384887Schin n = type>>TSHIFT; 21398462SApril.Chin@Sun.COM left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE); 21404887Schin if(type&TBINARY) 21418462SApril.Chin@Sun.COM right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE); 21428462SApril.Chin@Sun.COM if(trap=shp->st.trap[SH_DEBUGTRAP]) 21434887Schin argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[["; 21444887Schin if(sh_isoption(SH_XTRACE)) 21454887Schin { 21464887Schin traceon = sh_trace(NIL(char**),0); 21474887Schin sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3)); 21484887Schin } 21494887Schin if(type&TUNARY) 21504887Schin { 21514887Schin if(traceon) 21524887Schin sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left)); 21534887Schin if(trap) 21544887Schin { 21554887Schin char unop[3]; 21564887Schin unop[0] = '-'; 21574887Schin unop[1] = n; 21584887Schin unop[2] = 0; 21594887Schin argv[1] = unop; 21604887Schin argv[2] = left; 21614887Schin argv[3] = "]]"; 21624887Schin argv[4] = 0; 21638462SApril.Chin@Sun.COM sh_debug(shp,trap,(char*)0,(char*)0,argv, 0); 21644887Schin } 21654887Schin n = test_unop(n,left); 21664887Schin } 21674887Schin else if(type&TBINARY) 21684887Schin { 21694887Schin char *op; 21704887Schin int pattern = 0; 21714887Schin if(trap || traceon) 21724887Schin op = (char*)(shtab_testops+(n&037)-1)->sh_name; 21734887Schin type >>= TSHIFT; 21744887Schin if(type==TEST_PEQ || type==TEST_PNE) 21754887Schin pattern=ARG_EXP; 21764887Schin if(trap) 21774887Schin { 21784887Schin argv[1] = left; 21794887Schin argv[2] = op; 21804887Schin argv[3] = right; 21814887Schin argv[4] = "]]"; 21824887Schin argv[5] = 0; 21838462SApril.Chin@Sun.COM sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern); 21844887Schin } 21854887Schin n = test_binop(n,left,right); 21864887Schin if(traceon) 21874887Schin { 21884887Schin sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op); 21894887Schin if(pattern) 21904887Schin out_pattern(sfstderr,right,-1); 21914887Schin else 21924887Schin sfputr(sfstderr,sh_fmtq(right),-1); 21934887Schin } 21944887Schin } 21954887Schin if(traceon) 21964887Schin sfwrite(sfstderr,e_tstend,4); 21974887Schin } 21988462SApril.Chin@Sun.COM shp->exitval = ((!n)^negate); 21994887Schin if(!skipexitset) 22004887Schin exitset(); 22014887Schin break; 22024887Schin } 22034887Schin } 22048462SApril.Chin@Sun.COM if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) && 22054887Schin t && echeck) 22064887Schin sh_chktrap(); 22074887Schin /* set $_ */ 22084887Schin if(mainloop && com0) 22094887Schin { 22104887Schin /* store last argument here if it fits */ 22114887Schin static char lastarg[32]; 22124887Schin if(sh_isstate(SH_FORKED)) 22138462SApril.Chin@Sun.COM sh_done(shp,0); 22148462SApril.Chin@Sun.COM if(shp->lastarg!= lastarg && shp->lastarg) 22158462SApril.Chin@Sun.COM free(shp->lastarg); 22168462SApril.Chin@Sun.COM if(strlen(comn) < sizeof(lastarg)) 22174887Schin { 22184887Schin nv_onattr(L_ARGNOD,NV_NOFREE); 22198462SApril.Chin@Sun.COM shp->lastarg = strcpy(lastarg,comn); 22204887Schin } 22214887Schin else 22224887Schin { 22234887Schin nv_offattr(L_ARGNOD,NV_NOFREE); 22248462SApril.Chin@Sun.COM shp->lastarg = strdup(comn); 22254887Schin } 22264887Schin } 22274887Schin if(!skipexitset) 22284887Schin exitset(); 22294887Schin if(!(OPTIMIZE)) 22304887Schin { 22318462SApril.Chin@Sun.COM if(sav != stkptr(stkp,0)) 22328462SApril.Chin@Sun.COM stkset(stkp,sav,0); 22338462SApril.Chin@Sun.COM else if(stktell(stkp)) 22348462SApril.Chin@Sun.COM stkseek(stkp,0); 22354887Schin } 22368462SApril.Chin@Sun.COM if(shp->trapnote&SH_SIGSET) 22378462SApril.Chin@Sun.COM sh_exit(SH_EXITSIG|shp->lastsig); 22384887Schin if(was_interactive) 22394887Schin sh_onstate(SH_INTERACTIVE); 22404887Schin if(was_monitor && sh_isoption(SH_MONITOR)) 22414887Schin sh_onstate(SH_MONITOR); 22424887Schin if(was_errexit) 22434887Schin sh_onstate(SH_ERREXIT); 22444887Schin } 22458462SApril.Chin@Sun.COM return(shp->exitval); 22468462SApril.Chin@Sun.COM } 22478462SApril.Chin@Sun.COM 22488462SApril.Chin@Sun.COM int sh_run(int argn, char *argv[]) 22498462SApril.Chin@Sun.COM { 22508462SApril.Chin@Sun.COM register struct dolnod *dp; 22518462SApril.Chin@Sun.COM register struct comnod *t = (struct comnod*)stakalloc(sizeof(struct comnod)); 22528462SApril.Chin@Sun.COM int savtop = staktell(); 22538462SApril.Chin@Sun.COM char *savptr = stakfreeze(0); 22548462SApril.Chin@Sun.COM Opt_t *op, *np = optctx(0, 0); 22558462SApril.Chin@Sun.COM Shbltin_t bltindata; 22568462SApril.Chin@Sun.COM bltindata = sh.bltindata; 22578462SApril.Chin@Sun.COM op = optctx(np, 0); 22588462SApril.Chin@Sun.COM memset(t, 0, sizeof(struct comnod)); 22598462SApril.Chin@Sun.COM dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*)); 22608462SApril.Chin@Sun.COM dp->dolnum = argn; 22618462SApril.Chin@Sun.COM dp->dolbot = ARG_SPARE; 22628462SApril.Chin@Sun.COM memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*)); 22638462SApril.Chin@Sun.COM t->comarg = (struct argnod*)dp; 22648462SApril.Chin@Sun.COM if(!strchr(argv[0],'/')) 22658462SApril.Chin@Sun.COM t->comnamp = (void*)nv_bfsearch(argv[0],sh.fun_tree,(Namval_t**)&t->comnamq,(char**)0); 22668462SApril.Chin@Sun.COM argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT)); 22678462SApril.Chin@Sun.COM optctx(op,np); 22688462SApril.Chin@Sun.COM sh.bltindata = bltindata; 22698462SApril.Chin@Sun.COM if(savptr!=stakptr(0)) 22708462SApril.Chin@Sun.COM stakset(savptr,savtop); 22718462SApril.Chin@Sun.COM else 22728462SApril.Chin@Sun.COM stakseek(savtop); 22738462SApril.Chin@Sun.COM return(argn); 22744887Schin } 22754887Schin 22764887Schin /* 22774887Schin * test for equality with second argument trimmed 22784887Schin * returns 1 if r == trim(s) otherwise 0 22794887Schin */ 22804887Schin 22814887Schin static int trim_eq(register const char *r,register const char *s) 22824887Schin { 22834887Schin register char c; 22844887Schin while(c = *s++) 22854887Schin { 22864887Schin if(c=='\\') 22874887Schin c = *s++; 22884887Schin if(c && c != *r++) 22894887Schin return(0); 22904887Schin } 22914887Schin return(*r==0); 22924887Schin } 22934887Schin 22944887Schin /* 22954887Schin * print out the command line if set -x is on 22964887Schin */ 22974887Schin 22984887Schin int sh_trace(register char *argv[], register int nl) 22994887Schin { 23008462SApril.Chin@Sun.COM Shell_t *shp = &sh; 23014887Schin register char *cp; 23024887Schin register int bracket = 0; 23038462SApril.Chin@Sun.COM int decl = (nl&2); 23048462SApril.Chin@Sun.COM nl &= ~2; 23054887Schin if(sh_isoption(SH_XTRACE)) 23064887Schin { 23074887Schin /* make this trace atomic */ 23084887Schin sfset(sfstderr,SF_SHARE|SF_PUBLIC,0); 23098462SApril.Chin@Sun.COM if(!(cp=nv_getval(sh_scoped(shp,PS4NOD)))) 23104887Schin cp = "+ "; 23114887Schin else 23124887Schin { 23134887Schin sh_offoption(SH_XTRACE); 23148462SApril.Chin@Sun.COM cp = sh_mactry(shp,cp); 23154887Schin sh_onoption(SH_XTRACE); 23164887Schin } 23174887Schin if(*cp) 23184887Schin sfputr(sfstderr,cp,-1); 23194887Schin if(argv) 23204887Schin { 23214887Schin char *argv0 = *argv; 23224887Schin nl = (nl?'\n':-1); 23234887Schin /* don't quote [ and [[ */ 23244887Schin if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='[')) 23254887Schin { 23264887Schin sfputr(sfstderr,cp,*++argv?' ':nl); 23274887Schin bracket = 1; 23284887Schin } 23294887Schin while(cp = *argv++) 23304887Schin { 23314887Schin if(bracket==0 || *argv || *cp!=']') 23324887Schin cp = sh_fmtq(cp); 23338462SApril.Chin@Sun.COM if(decl && shp->prefix && cp!=argv0 && *cp!='-') 23344887Schin { 23354887Schin if(*cp=='.' && cp[1]==0) 23368462SApril.Chin@Sun.COM cp = shp->prefix; 23374887Schin else 23388462SApril.Chin@Sun.COM sfputr(sfstderr,shp->prefix,'.'); 23394887Schin } 23404887Schin sfputr(sfstderr,cp,*argv?' ':nl); 23414887Schin } 23424887Schin sfset(sfstderr,SF_SHARE|SF_PUBLIC,1); 23434887Schin } 23444887Schin return(1); 23454887Schin } 23464887Schin return(0); 23474887Schin } 23484887Schin 23494887Schin /* 23504887Schin * This routine creates a subshell by calling fork() or vfork() 23514887Schin * If ((flags&COMASK)==TCOM), then vfork() is permitted 23524887Schin * If fork fails, the shell sleeps for exponentially longer periods 23534887Schin * and tries again until a limit is reached. 23544887Schin * SH_FORKLIM is the max period between forks - power of 2 usually. 23554887Schin * Currently shell tries after 2,4,8,16, and 32 seconds and then quits 23564887Schin * Failures cause the routine to error exit. 23574887Schin * Parent links to here-documents are removed by the child 23584887Schin * Traps are reset by the child 23594887Schin * The process-id of the child is returned to the parent, 0 to the child. 23604887Schin */ 23614887Schin 23624887Schin static void timed_out(void *handle) 23634887Schin { 23644887Schin NOT_USED(handle); 23654887Schin timeout = 0; 23664887Schin } 23674887Schin 23684887Schin 23694887Schin /* 23704887Schin * called by parent and child after fork by sh_fork() 23714887Schin */ 23724887Schin pid_t _sh_fork(register pid_t parent,int flags,int *jobid) 23734887Schin { 23744887Schin static long forkcnt = 1000L; 23758462SApril.Chin@Sun.COM Shell_t *shp = &sh; 23764887Schin pid_t curpgid = job.curpgid; 23774887Schin pid_t postid = (flags&FAMP)?0:curpgid; 23788462SApril.Chin@Sun.COM int sig,nochild; 23794887Schin if(parent<0) 23804887Schin { 23818462SApril.Chin@Sun.COM sh_sigcheck(); 23824887Schin if((forkcnt *= 2) > 1000L*SH_FORKLIM) 23834887Schin { 23844887Schin forkcnt=1000L; 23854887Schin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork); 23864887Schin } 23874887Schin timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*)); 23888462SApril.Chin@Sun.COM nochild = job_wait((pid_t)1); 23894887Schin if(timeout) 23904887Schin { 23918462SApril.Chin@Sun.COM if(nochild) 23928462SApril.Chin@Sun.COM pause(); 23938462SApril.Chin@Sun.COM else if(forkcnt>1000L) 23948462SApril.Chin@Sun.COM forkcnt /= 2; 23954887Schin timerdel(timeout); 23968462SApril.Chin@Sun.COM timeout = 0; 23974887Schin } 23984887Schin return(-1); 23994887Schin } 24008462SApril.Chin@Sun.COM forkcnt = 1000L; 24014887Schin if(parent) 24024887Schin { 24038462SApril.Chin@Sun.COM int myjob,waitall=job.waitall; 24048462SApril.Chin@Sun.COM shp->nforks++; 24054887Schin if(job.toclear) 24064887Schin job_clear(); 24078462SApril.Chin@Sun.COM job.waitall = waitall; 24084887Schin #ifdef JOBS 24094887Schin /* first process defines process group */ 24104887Schin if(sh_isstate(SH_MONITOR)) 24114887Schin { 24124887Schin /* 24134887Schin * errno==EPERM means that an earlier processes 24144887Schin * completed. Make parent the job group id. 24154887Schin */ 24164887Schin if(postid==0) 24174887Schin job.curpgid = parent; 24184887Schin if(job.jobcontrol || (flags&FAMP)) 24194887Schin { 24204887Schin if(setpgid(parent,job.curpgid)<0 && errno==EPERM) 24214887Schin setpgid(parent,parent); 24224887Schin } 24234887Schin } 24244887Schin #endif /* JOBS */ 24254887Schin if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0) 24264887Schin job.curpgid = parent; 24274887Schin if(flags&FCOOP) 24288462SApril.Chin@Sun.COM shp->cpid = parent; 242910898Sroland.mainz@nrubsig.org #ifdef SHOPT_BGX 243010898Sroland.mainz@nrubsig.org if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT)) 243110898Sroland.mainz@nrubsig.org postid = 1; 24324887Schin myjob = job_post(parent,postid); 243310898Sroland.mainz@nrubsig.org if(postid==1) 243410898Sroland.mainz@nrubsig.org postid = 0; 243510898Sroland.mainz@nrubsig.org #else 243610898Sroland.mainz@nrubsig.org myjob = job_post(parent,postid); 243710898Sroland.mainz@nrubsig.org #endif /* SHOPT_BGX */ 24384887Schin if(flags&FAMP) 24394887Schin job.curpgid = curpgid; 24404887Schin if(jobid) 24414887Schin *jobid = myjob; 24424887Schin return(parent); 24434887Schin } 24444887Schin #if !_std_malloc 24454887Schin vmtrace(-1); 24464887Schin #endif 24474887Schin /* This is the child process */ 24488462SApril.Chin@Sun.COM if(shp->trapnote&SH_SIGTERM) 24494887Schin sh_exit(SH_EXITSIG|SIGTERM); 24508462SApril.Chin@Sun.COM shp->nforks=0; 24514887Schin timerdel(NIL(void*)); 24524887Schin #ifdef JOBS 24534887Schin if(!job.jobcontrol && !(flags&FAMP)) 24544887Schin sh_offstate(SH_MONITOR); 24554887Schin if(sh_isstate(SH_MONITOR)) 24564887Schin { 24574887Schin parent = getpid(); 24584887Schin if(postid==0) 24594887Schin job.curpgid = parent; 24604887Schin while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent) 24614887Schin job.curpgid = parent; 24624887Schin # ifdef SIGTSTP 24634887Schin if(job.curpgid==parent && !(flags&FAMP)) 24644887Schin tcsetpgrp(job.fd,job.curpgid); 24654887Schin # endif /* SIGTSTP */ 24664887Schin } 24674887Schin # ifdef SIGTSTP 24684887Schin if(job.jobcontrol) 24694887Schin { 24704887Schin signal(SIGTTIN,SIG_DFL); 24714887Schin signal(SIGTTOU,SIG_DFL); 24724887Schin signal(SIGTSTP,SIG_DFL); 24734887Schin } 24744887Schin # endif /* SIGTSTP */ 24754887Schin job.jobcontrol = 0; 24764887Schin #endif /* JOBS */ 24774887Schin job.toclear = 1; 24788462SApril.Chin@Sun.COM shp->login_sh = 0; 24794887Schin sh_offoption(SH_LOGIN_SHELL); 24804887Schin sh_onstate(SH_FORKED); 24814887Schin sh_onstate(SH_NOLOG); 24828462SApril.Chin@Sun.COM if (shp->fn_reset) 24838462SApril.Chin@Sun.COM shp->fn_depth = shp->fn_reset = 0; 24844887Schin #if SHOPT_ACCT 24854887Schin sh_accsusp(); 24864887Schin #endif /* SHOPT_ACCT */ 24874887Schin /* Reset remaining signals to parent */ 24884887Schin /* except for those `lost' by trap */ 248910898Sroland.mainz@nrubsig.org if(!(flags&FSHOWME)) 249010898Sroland.mainz@nrubsig.org sh_sigreset(2); 24918462SApril.Chin@Sun.COM shp->subshell = 0; 24928462SApril.Chin@Sun.COM if((flags&FAMP) && shp->coutpipe>1) 24938462SApril.Chin@Sun.COM sh_close(shp->coutpipe); 24948462SApril.Chin@Sun.COM sig = shp->savesig; 24958462SApril.Chin@Sun.COM shp->savesig = 0; 24964887Schin if(sig>0) 24974887Schin sh_fault(sig); 24984887Schin sh_sigcheck(); 24994887Schin return(0); 25004887Schin } 25014887Schin 25024887Schin pid_t sh_fork(int flags, int *jobid) 25034887Schin { 25044887Schin register pid_t parent; 25054887Schin register int sig; 25064887Schin #if SHOPT_FASTPIPE 25074887Schin if(sffileno(sfstdin)<0) 25084887Schin { 25094887Schin off_t current = sfseek(sfstdin,(off_t)0,SEEK_CUR); 25104887Schin sfseek(sfstdin,(off_t)0,SEEK_END); 25114887Schin sfdisc(sfstdin,SF_POPDISC); 25124887Schin fcntl(sffileno(sfstdin),F_SETFD,0); 25134887Schin sh_iostream(0); 25144887Schin sfseek(sfstdin,current,SEEK_SET); 25154887Schin } 25164887Schin #endif /* SHOPT_FASTPIPE */ 25174887Schin if(!sh.pathlist) 25184887Schin path_get(""); 25194887Schin sfsync(NIL(Sfio_t*)); 25204887Schin sh.trapnote &= ~SH_SIGTERM; 25214887Schin job_fork(-1); 25224887Schin sh.savesig = -1; 25234887Schin while(_sh_fork(parent=fork(),flags,jobid) < 0); 25248462SApril.Chin@Sun.COM sh_stats(STAT_FORKS); 25254887Schin sig = sh.savesig; 25264887Schin sh.savesig = 0; 25274887Schin if(sig>0) 25284887Schin sh_fault(sig); 25294887Schin job_fork(parent); 25304887Schin return(parent); 25314887Schin } 25324887Schin 25334887Schin /* 25344887Schin * add exports from previous scope to the new scope 25354887Schin */ 25364887Schin static void local_exports(register Namval_t *np, void *data) 25374887Schin { 25384887Schin register Namval_t *mp; 25394887Schin register char *cp; 25404887Schin if(nv_isarray(np)) 25414887Schin nv_putsub(np,NIL(char*),0); 25424887Schin if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), sh.var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp)) 25434887Schin nv_putval(mp, cp, 0); 25444887Schin } 25454887Schin 25464887Schin /* 25474887Schin * This routine is used to execute the given function <fun> in a new scope 25484887Schin * If <fun> is NULL, then arg points to a structure containing a pointer 25494887Schin * to a function that will be executed in the current environment. 25504887Schin */ 25514887Schin int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg) 25524887Schin { 25538462SApril.Chin@Sun.COM register char *trap; 25548462SApril.Chin@Sun.COM register int nsig; 25558462SApril.Chin@Sun.COM register Shell_t *shp = &sh; 25568462SApril.Chin@Sun.COM struct dolnod *argsav=0,*saveargfor; 25578462SApril.Chin@Sun.COM struct sh_scoped savst, *prevscope = shp->st.self; 25588462SApril.Chin@Sun.COM struct argnod *envlist=0; 25598462SApril.Chin@Sun.COM int jmpval; 25608462SApril.Chin@Sun.COM volatile int r = 0; 25618462SApril.Chin@Sun.COM char *savstak; 25628462SApril.Chin@Sun.COM struct funenv *fp; 25638462SApril.Chin@Sun.COM struct checkpt buff; 25648462SApril.Chin@Sun.COM Namval_t *nspace = shp->namespace; 256510898Sroland.mainz@nrubsig.org Dt_t *last_root = shp->last_root; 256610898Sroland.mainz@nrubsig.org Shopt_t options = shp->options; 25678462SApril.Chin@Sun.COM if(shp->fn_depth==0) 25688462SApril.Chin@Sun.COM shp->glob_options = shp->options; 25698462SApril.Chin@Sun.COM else 25708462SApril.Chin@Sun.COM shp->options = shp->glob_options; 25718462SApril.Chin@Sun.COM #if 0 25728462SApril.Chin@Sun.COM shp->st.lineno = error_info.line; 25738462SApril.Chin@Sun.COM #endif 25748462SApril.Chin@Sun.COM *prevscope = shp->st; 25754887Schin sh_offoption(SH_ERREXIT); 25768462SApril.Chin@Sun.COM shp->st.prevst = prevscope; 25778462SApril.Chin@Sun.COM shp->st.self = &savst; 25788462SApril.Chin@Sun.COM shp->topscope = (Shscope_t*)shp->st.self; 25798462SApril.Chin@Sun.COM shp->st.opterror = shp->st.optchar = 0; 25808462SApril.Chin@Sun.COM shp->st.optindex = 1; 25818462SApril.Chin@Sun.COM shp->st.loopcnt = 0; 25824887Schin if(!fun) 25834887Schin { 25844887Schin fp = (struct funenv*)arg; 25858462SApril.Chin@Sun.COM shp->st.real_fun = (fp->node)->nvalue.rp; 25864887Schin envlist = fp->env; 25874887Schin } 25888462SApril.Chin@Sun.COM prevscope->save_tree = shp->var_tree; 25898462SApril.Chin@Sun.COM sh_scope(shp,envlist,1); 25908462SApril.Chin@Sun.COM if(dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0)) 25914887Schin { 25924887Schin /* eliminate parent scope */ 25934887Schin nv_scan(prevscope->save_tree, local_exports,(void*)0, NV_EXPORT, NV_EXPORT|NV_NOSCOPE); 25944887Schin } 25958462SApril.Chin@Sun.COM shp->st.save_tree = shp->var_tree; 25964887Schin if(!fun) 25974887Schin { 25984887Schin Namval_t *np; 25994887Schin if(nv_isattr(fp->node,NV_TAGGED)) 26004887Schin sh_onoption(SH_XTRACE); 26014887Schin else 26024887Schin sh_offoption(SH_XTRACE); 26034887Schin #if SHOPT_NAMESPACE 26048462SApril.Chin@Sun.COM if((np=(fp->node)->nvalue.rp->nspace) && np!=shp->namespace) 26054887Schin { 26068462SApril.Chin@Sun.COM Dt_t *dt = shp->var_tree; 26074887Schin dtview(dt,0); 26084887Schin dtview(dt,nv_dict(np)); 26098462SApril.Chin@Sun.COM shp->var_tree = nv_dict(np); 26108462SApril.Chin@Sun.COM shp->namespace = np; 26114887Schin } 26124887Schin #endif /* SHOPT_NAMESPACE */ 26134887Schin } 26148462SApril.Chin@Sun.COM shp->st.cmdname = argv[0]; 26154887Schin /* save trap table */ 26168462SApril.Chin@Sun.COM if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0]) 26174887Schin { 26184887Schin nsig += sizeof(char*); 26198462SApril.Chin@Sun.COM memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig); 26204887Schin } 26214887Schin sh_sigreset(0); 26228462SApril.Chin@Sun.COM argsav = sh_argnew(shp,argv,&saveargfor); 26234887Schin sh_pushcontext(&buff,SH_JMPFUN); 26244887Schin errorpush(&buff.err,0); 26254887Schin error_info.id = argv[0]; 26268462SApril.Chin@Sun.COM shp->st.var_local = shp->var_tree; 26274887Schin jmpval = sigsetjmp(buff.buff,0); 26284887Schin if(!fun) 26294887Schin { 26308462SApril.Chin@Sun.COM shp->st.filename = fp->node->nvalue.rp->fname; 26318462SApril.Chin@Sun.COM shp->st.funname = nv_name(fp->node); 26328462SApril.Chin@Sun.COM nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE); 26338462SApril.Chin@Sun.COM nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE); 26344887Schin } 26354887Schin if(jmpval == 0) 26364887Schin { 26378462SApril.Chin@Sun.COM if(shp->fn_depth++ > MAXDEPTH) 263810898Sroland.mainz@nrubsig.org { 263910898Sroland.mainz@nrubsig.org shp->toomany = 1; 26408462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,SH_JMPERRFN); 264110898Sroland.mainz@nrubsig.org } 26424887Schin else if(fun) 26434887Schin r= (*fun)(arg); 26444887Schin else 26454887Schin { 26464887Schin sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT); 26478462SApril.Chin@Sun.COM r = shp->exitval; 26484887Schin } 26494887Schin } 26508462SApril.Chin@Sun.COM if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN) 26514887Schin errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]); 26524887Schin sh_popcontext(&buff); 26538462SApril.Chin@Sun.COM if (shp->st.self != &savst) 26548462SApril.Chin@Sun.COM shp->var_tree = (Dt_t*)savst.save_tree; 26558462SApril.Chin@Sun.COM sh_unscope(shp); 26568462SApril.Chin@Sun.COM shp->namespace = nspace; 26578462SApril.Chin@Sun.COM shp->var_tree = (Dt_t*)prevscope->save_tree; 26588462SApril.Chin@Sun.COM if(shp->topscope != (Shscope_t*)shp->st.self) 26598462SApril.Chin@Sun.COM sh_setscope(shp->topscope); 26608462SApril.Chin@Sun.COM sh_argreset(shp,argsav,saveargfor); 26618462SApril.Chin@Sun.COM trap = shp->st.trapcom[0]; 26628462SApril.Chin@Sun.COM shp->st.trapcom[0] = 0; 26634887Schin sh_sigreset(1); 26648462SApril.Chin@Sun.COM if (shp->st.self != &savst) 26658462SApril.Chin@Sun.COM *shp->st.self = shp->st; 26668462SApril.Chin@Sun.COM shp->st = *prevscope; 26678462SApril.Chin@Sun.COM shp->topscope = (Shscope_t*)prevscope; 26688462SApril.Chin@Sun.COM nv_getval(sh_scoped(shp,IFSNOD)); 26694887Schin if(nsig) 26708462SApril.Chin@Sun.COM memcpy((char*)&shp->st.trapcom[0],savstak,nsig); 26718462SApril.Chin@Sun.COM shp->trapnote=0; 26724887Schin if(nsig) 26734887Schin stakset(savstak,0); 267410898Sroland.mainz@nrubsig.org shp->options = options; 267510898Sroland.mainz@nrubsig.org shp->last_root = last_root; 2676*12068SRoger.Faulkner@Oracle.COM if(jmpval == SH_JMPSUB) 2677*12068SRoger.Faulkner@Oracle.COM siglongjmp(*shp->jmplist,jmpval); 26784887Schin if(trap) 26794887Schin { 26804887Schin sh_trap(trap,0); 26814887Schin free(trap); 26824887Schin } 26838462SApril.Chin@Sun.COM if(shp->exitval > SH_EXITSIG) 26848462SApril.Chin@Sun.COM sh_fault(shp->exitval&SH_EXITMASK); 26854887Schin if(jmpval > SH_JMPFUN) 26864887Schin { 26874887Schin sh_chktrap(); 26888462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 26894887Schin } 26904887Schin return(r); 26914887Schin } 26924887Schin 26938462SApril.Chin@Sun.COM static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg) 26944887Schin { 26954887Schin struct funenv fun; 26964887Schin char *fname = nv_getval(SH_FUNNAMENOD); 26978462SApril.Chin@Sun.COM struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun); 269810898Sroland.mainz@nrubsig.org int level, pipepid=shp->pipepid; 269910898Sroland.mainz@nrubsig.org shp->pipepid = 0; 27008462SApril.Chin@Sun.COM sh_stats(STAT_FUNCT); 27018462SApril.Chin@Sun.COM if(!lp->hdr.disc) 27028462SApril.Chin@Sun.COM lp = init_level(0); 27038462SApril.Chin@Sun.COM if((struct sh_scoped*)shp->topscope != shp->st.self) 27048462SApril.Chin@Sun.COM sh_setscope(shp->topscope); 27058462SApril.Chin@Sun.COM level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1; 27068462SApril.Chin@Sun.COM SH_LEVELNOD->nvalue.s = lp->maxlevel; 27078462SApril.Chin@Sun.COM shp->st.lineno = error_info.line; 27084887Schin if(nv_isattr(np,NV_FPOSIX)) 27094887Schin { 27104887Schin char *save; 27118462SApril.Chin@Sun.COM int loopcnt = shp->st.loopcnt; 27128462SApril.Chin@Sun.COM shp->posix_fun = np; 27138462SApril.Chin@Sun.COM save = argv[-1]; 27148462SApril.Chin@Sun.COM argv[-1] = 0; 27158462SApril.Chin@Sun.COM shp->st.funname = nv_name(np); 27168462SApril.Chin@Sun.COM nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE); 27174887Schin opt_info.index = opt_info.offset = 0; 27184887Schin error_info.errors = 0; 27198462SApril.Chin@Sun.COM shp->st.loopcnt = 0; 27208462SApril.Chin@Sun.COM b_dot_cmd(argn+1,argv-1,&shp->bltindata); 27218462SApril.Chin@Sun.COM shp->st.loopcnt = loopcnt; 27224887Schin argv[-1] = save; 27234887Schin } 27244887Schin else 27254887Schin { 27264887Schin fun.env = envlist; 27274887Schin fun.node = np; 27284887Schin sh_funscope(argn,argv,0,&fun,execflg); 27294887Schin } 27308462SApril.Chin@Sun.COM if(level-- != nv_getnum(SH_LEVELNOD)) 27318462SApril.Chin@Sun.COM { 27328462SApril.Chin@Sun.COM Shscope_t *sp = sh_getscope(0,SEEK_END); 27338462SApril.Chin@Sun.COM sh_setscope(sp); 27348462SApril.Chin@Sun.COM } 27358462SApril.Chin@Sun.COM lp->maxlevel = level; 27368462SApril.Chin@Sun.COM SH_LEVELNOD->nvalue.s = lp->maxlevel; 27378462SApril.Chin@Sun.COM #if 0 27388462SApril.Chin@Sun.COM nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE); 27398462SApril.Chin@Sun.COM #else 27404887Schin nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE); 27418462SApril.Chin@Sun.COM #endif 27428462SApril.Chin@Sun.COM nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE); 274310898Sroland.mainz@nrubsig.org shp->pipepid = pipepid; 27444887Schin } 27454887Schin 27464887Schin /* 27474887Schin * external interface to execute a function without arguments 27484887Schin * <np> is the function node 27494887Schin * If <nq> is not-null, then sh.name and sh.subscript will be set 27504887Schin */ 27514887Schin int sh_fun(Namval_t *np, Namval_t *nq, char *argv[]) 27524887Schin { 27538462SApril.Chin@Sun.COM Shell_t *shp = &sh; 27544887Schin register int offset; 27554887Schin register char *base; 27564887Schin Namval_t node; 27578462SApril.Chin@Sun.COM struct Namref nr; 27588462SApril.Chin@Sun.COM long mode; 27598462SApril.Chin@Sun.COM char *prefix = shp->prefix; 27604887Schin int n=0; 27614887Schin char *av[2]; 27624887Schin Fcin_t save; 27634887Schin fcsave(&save); 27644887Schin if((offset=staktell())>0) 27654887Schin base=stakfreeze(0); 27668462SApril.Chin@Sun.COM shp->prefix = 0; 27674887Schin if(!argv) 27684887Schin { 27694887Schin argv = av; 27704887Schin argv[1]=0; 27714887Schin } 27724887Schin argv[0] = nv_name(np); 27734887Schin while(argv[n]) 27744887Schin n++; 27754887Schin if(nq) 2776*12068SRoger.Faulkner@Oracle.COM mode = set_instance(shp,nq,&node, &nr); 27774887Schin if(is_abuiltin(np)) 27784887Schin { 27794887Schin int jmpval; 27804887Schin struct checkpt buff; 27818462SApril.Chin@Sun.COM Shbltin_t *bp = &sh.bltindata; 27824887Schin sh_pushcontext(&buff,SH_JMPCMD); 27834887Schin jmpval = sigsetjmp(buff.buff,1); 27844887Schin if(jmpval == 0) 27854887Schin { 27868462SApril.Chin@Sun.COM bp->bnode = np; 27878462SApril.Chin@Sun.COM bp->ptr = nv_context(np); 27884887Schin errorpush(&buff.err,0); 27894887Schin error_info.id = argv[0]; 27904887Schin opt_info.index = opt_info.offset = 0; 27914887Schin opt_info.disc = 0; 27924887Schin sh.exitval = 0; 27938462SApril.Chin@Sun.COM sh.exitval = (*funptr(np))(n,argv,(void*)bp); 27944887Schin } 27954887Schin sh_popcontext(&buff); 27964887Schin if(jmpval>SH_JMPCMD) 27974887Schin siglongjmp(*sh.jmplist,jmpval); 27984887Schin } 27994887Schin else 28008462SApril.Chin@Sun.COM sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT)); 28014887Schin if(nq) 28028462SApril.Chin@Sun.COM unset_instance(nq, &node, &nr, mode); 28034887Schin fcrestore(&save); 28044887Schin if(offset>0) 28054887Schin stakset(base,offset); 28068462SApril.Chin@Sun.COM shp->prefix = prefix; 28074887Schin return(sh.exitval); 28084887Schin } 28094887Schin 28104887Schin /* 28114887Schin * This dummy routine is called by built-ins that do recursion 28124887Schin * on the file system (chmod, chgrp, chown). It causes 28134887Schin * the shell to invoke the non-builtin version in this case 28144887Schin */ 28154887Schin int cmdrecurse(int argc, char* argv[], int ac, char* av[]) 28164887Schin { 28174887Schin NOT_USED(argc); 28184887Schin NOT_USED(argv[0]); 28194887Schin NOT_USED(ac); 28204887Schin NOT_USED(av[0]); 28214887Schin return(SH_RUNPROG); 28224887Schin } 28234887Schin 28244887Schin /* 28254887Schin * set up pipe for cooperating process 28264887Schin */ 28278462SApril.Chin@Sun.COM static void coproc_init(Shell_t *shp, int pipes[]) 28284887Schin { 28294887Schin int outfd; 28308462SApril.Chin@Sun.COM if(shp->coutpipe>=0 && shp->cpid) 28314887Schin errormsg(SH_DICT,ERROR_exit(1),e_pexists); 28328462SApril.Chin@Sun.COM shp->cpid = 0; 28338462SApril.Chin@Sun.COM if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0) 28344887Schin { 28354887Schin /* first co-process */ 28368462SApril.Chin@Sun.COM sh_pclose(shp->cpipe); 28378462SApril.Chin@Sun.COM sh_pipe(shp->cpipe); 28388462SApril.Chin@Sun.COM if((outfd=shp->cpipe[1]) < 10) 28394887Schin { 28408462SApril.Chin@Sun.COM int fd=fcntl(shp->cpipe[1],F_DUPFD,10); 28414887Schin if(fd>=10) 28424887Schin { 28438462SApril.Chin@Sun.COM shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX); 28444887Schin close(outfd); 28458462SApril.Chin@Sun.COM shp->fdstatus[outfd] = IOCLOSE; 28468462SApril.Chin@Sun.COM shp->cpipe[1] = fd; 28474887Schin } 28484887Schin } 28498462SApril.Chin@Sun.COM if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0) 28508462SApril.Chin@Sun.COM shp->fdstatus[shp->cpipe[0]] |= IOCLEX; 28518462SApril.Chin@Sun.COM shp->fdptrs[shp->cpipe[0]] = shp->cpipe; 28524887Schin 28538462SApril.Chin@Sun.COM if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0) 28548462SApril.Chin@Sun.COM shp->fdstatus[shp->cpipe[1]] |= IOCLEX; 28554887Schin } 28568462SApril.Chin@Sun.COM shp->outpipe = shp->cpipe; 28578462SApril.Chin@Sun.COM sh_pipe(shp->inpipe=pipes); 28588462SApril.Chin@Sun.COM shp->coutpipe = shp->inpipe[1]; 28598462SApril.Chin@Sun.COM shp->fdptrs[shp->coutpipe] = &shp->coutpipe; 28608462SApril.Chin@Sun.COM if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0) 28618462SApril.Chin@Sun.COM shp->fdstatus[shp->outpipe[0]] |= IOCLEX; 28624887Schin } 28634887Schin 28644887Schin #if SHOPT_SPAWN 28654887Schin 28664887Schin 28674887Schin #if SHOPT_AMP || !defined(_lib_fork) 28684887Schin /* 28694887Schin * print out function definition 28704887Schin */ 28714887Schin static void print_fun(register Namval_t* np, void *data) 28724887Schin { 28734887Schin register char *format; 28744887Schin NOT_USED(data); 28754887Schin if(!is_afunction(np) || !np->nvalue.ip) 28764887Schin return; 28774887Schin if(nv_isattr(np,NV_FPOSIX)) 28784887Schin format="%s()\n{ "; 28794887Schin else 28804887Schin format="function %s\n{ "; 28814887Schin sfprintf(sfstdout,format,nv_name(np)); 28824887Schin sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0); 28834887Schin sfwrite(sfstdout,"}\n",2); 28844887Schin } 28854887Schin 28864887Schin /* 28874887Schin * create a shell script consisting of t->fork.forktre and execute it 28884887Schin */ 28894887Schin static int run_subshell(const Shnode_t *t,pid_t grp) 28904887Schin { 28918462SApril.Chin@Sun.COM static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)"; 28924887Schin register int i, fd, trace = sh_isoption(SH_XTRACE); 28934887Schin int pin,pout; 28944887Schin pid_t pid; 28954887Schin char *arglist[2], *envlist[2], devfd[12], *cp; 28964887Schin Sfio_t *sp = sftmp(0); 28974887Schin envlist[0] = "_=" SH_ID; 28984887Schin envlist[1] = 0; 28994887Schin arglist[0] = error_info.id?error_info.id:sh.shname; 29004887Schin if(*arglist[0]=='-') 29014887Schin arglist[0]++; 29024887Schin arglist[1] = devfd; 29034887Schin strncpy(devfd,e_devfdNN,sizeof(devfd)); 29044887Schin arglist[2] = 0; 29054887Schin sfstack(sfstdout,sp); 29064887Schin if(trace) 29074887Schin sh_offoption(SH_XTRACE); 29084887Schin sfwrite(sfstdout,"typeset -A -- ",14); 29094887Schin sh_trap(prolog,0); 29104887Schin nv_scan(sh.fun_tree, print_fun, (void*)0,0, 0); 29114887Schin if(sh.st.dolc>0) 29124887Schin { 29134887Schin /* pass the positional parameters */ 29144887Schin char **argv = sh.st.dolv+1; 29154887Schin sfwrite(sfstdout,"set --",6); 29164887Schin while(*argv) 29174887Schin sfprintf(sfstdout," %s",sh_fmtq(*argv++)); 29184887Schin sfputc(sfstdout,'\n'); 29194887Schin } 29204887Schin pin = (sh.inpipe?sh.inpipe[1]:0); 29214887Schin pout = (sh.outpipe?sh.outpipe[0]:0); 29224887Schin for(i=3; i < 10; i++) 29234887Schin { 29244887Schin if(sh.fdstatus[i]&IOCLEX && i!=pin && i!=pout) 29254887Schin { 29264887Schin sfprintf(sfstdout,"exec %d<&%d\n",i,i); 29274887Schin fcntl(i,F_SETFD,0); 29284887Schin } 29294887Schin } 29304887Schin sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline); 29314887Schin if(trace) 29324887Schin { 29334887Schin sfwrite(sfstdout,"set -x\n",7); 29344887Schin sh_onoption(SH_XTRACE); 29354887Schin } 29364887Schin sfstack(sfstdout,NIL(Sfio_t*)); 29374887Schin sh_deparse(sp,t->fork.forktre,0); 29384887Schin sfseek(sp,(Sfoff_t)0,SEEK_SET); 29394887Schin fd = sh_dup(sffileno(sp)); 29404887Schin cp = devfd+8; 29414887Schin if(fd>9) 29424887Schin *cp++ = '0' + (fd/10); 29434887Schin *cp++ = '0' + fd%10; 29444887Schin *cp = 0; 29454887Schin sfclose(sp); 29464887Schin sfsync(NIL(Sfio_t*)); 29474887Schin if(!sh.shpath) 29484887Schin sh.shpath = pathshell(); 29494887Schin pid = spawnveg(sh.shpath,arglist,envlist,grp); 29504887Schin close(fd); 29514887Schin for(i=3; i < 10; i++) 29524887Schin { 29534887Schin if(sh.fdstatus[i]&IOCLEX && i!=pin && i!=pout) 29544887Schin fcntl(i,F_SETFD,FD_CLOEXEC); 29554887Schin } 29564887Schin if(pid <=0) 29574887Schin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]); 29584887Schin return(pid); 29594887Schin } 29604887Schin #endif /* !_lib_fork */ 29614887Schin 29624887Schin static void sigreset(int mode) 29634887Schin { 29644887Schin register char *trap; 29654887Schin register int sig=sh.st.trapmax; 29664887Schin while(sig-- > 0) 29674887Schin { 29684887Schin if((trap=sh.st.trapcom[sig]) && *trap==0) 29694887Schin signal(sig,mode?sh_fault:SIG_IGN); 29704887Schin } 29714887Schin } 29724887Schin 29734887Schin /* 29744887Schin * A combined fork/exec for systems with slow or non-existent fork() 29754887Schin */ 29768462SApril.Chin@Sun.COM static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag) 29774887Schin { 29784887Schin static pid_t spawnpid; 29794887Schin static int savetype; 29804887Schin static int savejobid; 29818462SApril.Chin@Sun.COM struct checkpt buff; 29828462SApril.Chin@Sun.COM int otype=0, jmpval; 29838462SApril.Chin@Sun.COM volatile int jobwasset=0, scope=0, sigwasset=0; 29848462SApril.Chin@Sun.COM char **arge, *path; 29858462SApril.Chin@Sun.COM volatile pid_t grp = 0; 29868462SApril.Chin@Sun.COM Pathcomp_t *pp; 29874887Schin if(flag) 29884887Schin { 29894887Schin otype = savetype; 29904887Schin savetype=0; 29914887Schin } 29924887Schin # if SHOPT_AMP || !defined(_lib_fork) 29934887Schin if(!argv) 29944887Schin { 29954887Schin register Shnode_t *tchild = t->fork.forktre; 29964887Schin int optimize=0; 29974887Schin otype = t->tre.tretyp; 29984887Schin savetype = otype; 29994887Schin spawnpid = 0; 30004887Schin # ifndef _lib_fork 30014887Schin if((tchild->tre.tretyp&COMMSK)==TCOM) 30024887Schin { 30034887Schin Namval_t *np = (Namval_t*)(tchild->com.comnamp); 30044887Schin if(np) 30054887Schin { 30064887Schin path = nv_name(np); 30074887Schin if(!nv_isattr(np,BLT_ENV)) 30084887Schin np=0; 30094887Schin else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0) 30104887Schin np=0; 30114887Schin } 30124887Schin else if(!tchild->com.comarg) 30134887Schin optimize=1; 30144887Schin else if(tchild->com.comtyp&COMSCAN) 30154887Schin { 30164887Schin if(tchild->com.comarg->argflag&ARG_RAW) 30174887Schin path = tchild->com.comarg->argval; 30184887Schin else 30194887Schin path = 0; 30204887Schin } 30214887Schin else 30224887Schin path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE]; 30234887Schin if(!np && path && !nv_search(path,shp->fun_tree,0)) 30244887Schin optimize=1; 30254887Schin } 30264887Schin # endif 30274887Schin sh_pushcontext(&buff,SH_JMPIO); 30284887Schin jmpval = sigsetjmp(buff.buff,0); 30294887Schin { 30304887Schin if((otype&FINT) && !sh_isstate(SH_MONITOR)) 30314887Schin { 30324887Schin signal(SIGQUIT,SIG_IGN); 30334887Schin signal(SIGINT,SIG_IGN); 30344887Schin if(!shp->st.ioset) 30354887Schin { 30368462SApril.Chin@Sun.COM sh_iosave(shp,0,buff.topfd,(char*)0); 30378462SApril.Chin@Sun.COM sh_iorenumber(shp,sh_chkopen(e_devnull),0); 30384887Schin } 30394887Schin } 30404887Schin if(otype&FPIN) 30414887Schin { 30424887Schin int fd = shp->inpipe[1]; 30438462SApril.Chin@Sun.COM sh_iosave(shp,0,buff.topfd,(char*)0); 30448462SApril.Chin@Sun.COM sh_iorenumber(shp,shp->inpipe[0],0); 30454887Schin if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0) 30464887Schin shp->fdstatus[fd] |= IOCLEX; 30474887Schin } 30484887Schin if(otype&FPOU) 30494887Schin { 30508462SApril.Chin@Sun.COM sh_iosave(shp,1,buff.topfd,(char*)0); 30518462SApril.Chin@Sun.COM sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1); 30524887Schin if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0) 30534887Schin shp->fdstatus[shp->outpipe[0]] |= IOCLEX; 30544887Schin } 30554887Schin 30564887Schin if(t->fork.forkio) 30578462SApril.Chin@Sun.COM sh_redirect(shp,t->fork.forkio,0); 30584887Schin if(optimize==0) 30594887Schin { 30604887Schin #ifdef SIGTSTP 30614887Schin if(job.jobcontrol) 30624887Schin { 30634887Schin signal(SIGTTIN,SIG_DFL); 30644887Schin signal(SIGTTOU,SIG_DFL); 30654887Schin } 30664887Schin #endif /* SIGTSTP */ 30674887Schin #ifdef JOBS 30684887Schin if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP))) 30694887Schin { 30704887Schin if((otype&FAMP) || job.curpgid==0) 30714887Schin grp = 1; 30724887Schin else 30734887Schin grp = job.curpgid; 30744887Schin } 30754887Schin #endif /* JOBS */ 30764887Schin spawnpid = run_subshell(t,grp); 30774887Schin } 30784887Schin else 30794887Schin { 30804887Schin sh_exec(tchild,SH_NTFORK); 30814887Schin if(jobid) 30824887Schin *jobid = savejobid; 30834887Schin } 30844887Schin } 30854887Schin sh_popcontext(&buff); 30864887Schin if((otype&FINT) && !sh_isstate(SH_MONITOR)) 30874887Schin { 30884887Schin signal(SIGQUIT,sh_fault); 30894887Schin signal(SIGINT,sh_fault); 30904887Schin } 30914887Schin if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0) 30924887Schin shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX; 30934887Schin if(t->fork.forkio || otype) 30948462SApril.Chin@Sun.COM sh_iorestore(shp,buff.topfd,jmpval); 30954887Schin if(optimize==0) 30964887Schin { 30974887Schin #ifdef SIGTSTP 30984887Schin if(job.jobcontrol) 30994887Schin { 31004887Schin signal(SIGTTIN,SIG_IGN); 31014887Schin signal(SIGTTOU,SIG_IGN); 31024887Schin } 31034887Schin #endif /* SIGTSTP */ 31044887Schin if(spawnpid>0) 31054887Schin _sh_fork(spawnpid,otype,jobid); 31064887Schin if(grp>0 && !(otype&FAMP)) 31074887Schin { 31084887Schin while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid) 31094887Schin job.curpgid = spawnpid; 31104887Schin } 31114887Schin } 31124887Schin savetype=0; 31134887Schin if(jmpval>SH_JMPIO) 31144887Schin siglongjmp(*shp->jmplist,jmpval); 31154887Schin if(spawnpid<0 && (otype&FCOOP)) 31164887Schin { 31174887Schin sh_close(shp->coutpipe); 31184887Schin sh_close(shp->cpipe[1]); 31194887Schin shp->cpipe[1] = -1; 31204887Schin shp->coutpipe = -1; 31214887Schin } 31224887Schin shp->exitval = 0; 31234887Schin return(spawnpid); 31244887Schin } 31254887Schin # endif /* !_lib_fork */ 31264887Schin sh_pushcontext(&buff,SH_JMPCMD); 31274887Schin errorpush(&buff.err,ERROR_SILENT); 31284887Schin jmpval = sigsetjmp(buff.buff,0); 31294887Schin if(jmpval == 0) 31304887Schin { 31314887Schin if((otype&FINT) && !sh_isstate(SH_MONITOR)) 31324887Schin { 31334887Schin signal(SIGQUIT,SIG_IGN); 31344887Schin signal(SIGINT,SIG_IGN); 31354887Schin } 31364887Schin spawnpid = -1; 31374887Schin if(t->com.comio) 31388462SApril.Chin@Sun.COM sh_redirect(shp,t->com.comio,0); 31394887Schin error_info.id = *argv; 31404887Schin if(t->com.comset) 31414887Schin { 31424887Schin scope++; 31438462SApril.Chin@Sun.COM sh_scope(shp,t->com.comset,0); 31444887Schin } 31454887Schin if(!strchr(path=argv[0],'/')) 31464887Schin { 31474887Schin Namval_t *np; 31484887Schin if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp) 31494887Schin path = nv_getval(np); 31504887Schin else if(path_absolute(path,NIL(Pathcomp_t*))) 31514887Schin { 31528462SApril.Chin@Sun.COM path = stkptr(shp->stk,PATH_OFFSET); 31538462SApril.Chin@Sun.COM stkfreeze(shp->stk,0); 31548462SApril.Chin@Sun.COM } 31558462SApril.Chin@Sun.COM else 31568462SApril.Chin@Sun.COM { 31578462SApril.Chin@Sun.COM pp=path_get(path); 31588462SApril.Chin@Sun.COM while(pp) 31594887Schin { 31608462SApril.Chin@Sun.COM if(pp->len==1 && *pp->name=='.') 31618462SApril.Chin@Sun.COM break; 31628462SApril.Chin@Sun.COM pp = pp->next; 31634887Schin } 31648462SApril.Chin@Sun.COM if(!pp) 31658462SApril.Chin@Sun.COM path = 0; 31664887Schin } 31678462SApril.Chin@Sun.COM } 31688462SApril.Chin@Sun.COM else if(sh_isoption(SH_RESTRICTED)) 31698462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_restricted,path); 31708462SApril.Chin@Sun.COM if(!path) 31718462SApril.Chin@Sun.COM { 31728462SApril.Chin@Sun.COM spawnpid = -1; 31738462SApril.Chin@Sun.COM goto fail; 31748462SApril.Chin@Sun.COM } 31758462SApril.Chin@Sun.COM arge = sh_envgen(); 31768462SApril.Chin@Sun.COM shp->exitval = 0; 31774887Schin #ifdef SIGTSTP 31784887Schin if(job.jobcontrol) 31794887Schin { 31804887Schin signal(SIGTTIN,SIG_DFL); 31814887Schin signal(SIGTTOU,SIG_DFL); 31824887Schin jobwasset++; 31834887Schin } 31844887Schin #endif /* SIGTSTP */ 31854887Schin #ifdef JOBS 31864887Schin if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP))) 31874887Schin { 31884887Schin if((otype&FAMP) || job.curpgid==0) 31894887Schin grp = 1; 31904887Schin else 31914887Schin grp = job.curpgid; 31924887Schin } 31934887Schin #endif /* JOBS */ 31944887Schin 31954887Schin sfsync(NIL(Sfio_t*)); 31964887Schin sigreset(0); /* set signals to ignore */ 31974887Schin sigwasset++; 31984887Schin /* find first path that has a library component */ 31994887Schin for(pp=path_get(argv[0]); pp && !pp->lib ; pp=pp->next); 32004887Schin spawnpid = path_spawn(path,argv,arge,pp,(grp<<1)|1); 32014887Schin if(spawnpid < 0 && errno==ENOEXEC) 32024887Schin { 32034887Schin char *devfd; 32044887Schin int fd = open(path,O_RDONLY); 32054887Schin argv[-1] = argv[0]; 32064887Schin argv[0] = path; 32074887Schin if(fd>=0) 32084887Schin { 32094887Schin struct stat statb; 32104887Schin sfprintf(sh.strbuf,"/dev/fd/%d",fd); 32114887Schin if(stat(devfd=sfstruse(sh.strbuf),&statb)>=0) 32124887Schin argv[0] = devfd; 32134887Schin } 32144887Schin if(!shp->shpath) 32154887Schin shp->shpath = pathshell(); 32164887Schin spawnpid = path_spawn(shp->shpath,&argv[-1],arge,pp,(grp<<1)|1); 32174887Schin if(fd>=0) 32184887Schin close(fd); 32194887Schin argv[0] = argv[-1]; 32204887Schin } 32214887Schin fail: 32224887Schin if(spawnpid < 0) switch(errno=shp->path_err) 32234887Schin { 32244887Schin case ENOENT: 32254887Schin errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4); 32264887Schin default: 32274887Schin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4); 32284887Schin } 32294887Schin } 32304887Schin else 32314887Schin exitset(); 32324887Schin sh_popcontext(&buff); 32334887Schin if(buff.olist) 32344887Schin free_list(buff.olist); 32354887Schin #ifdef SIGTSTP 32364887Schin if(jobwasset) 32374887Schin { 32384887Schin signal(SIGTTIN,SIG_IGN); 32394887Schin signal(SIGTTOU,SIG_IGN); 32404887Schin } 32414887Schin #endif /* SIGTSTP */ 32424887Schin if(sigwasset) 32434887Schin sigreset(1); /* restore ignored signals */ 32444887Schin if(scope) 32454887Schin { 32468462SApril.Chin@Sun.COM sh_unscope(shp); 32474887Schin if(jmpval==SH_JMPSCRIPT) 324810898Sroland.mainz@nrubsig.org nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0); 32494887Schin } 32504887Schin if(t->com.comio) 32518462SApril.Chin@Sun.COM sh_iorestore(shp,buff.topfd,jmpval); 32524887Schin if(jmpval>SH_JMPCMD) 32534887Schin siglongjmp(*shp->jmplist,jmpval); 32544887Schin if(spawnpid>0) 32554887Schin { 32564887Schin _sh_fork(spawnpid,otype,jobid); 32574887Schin #ifdef JOBS 32584887Schin if(grp==1) 32594887Schin job.curpgid = spawnpid; 32604887Schin # ifdef SIGTSTP 32614887Schin if(grp>0 && !(otype&FAMP)) 32624887Schin { 32634887Schin while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid) 32644887Schin job.curpgid = spawnpid; 32654887Schin } 32664887Schin # endif /* SIGTSTP */ 32674887Schin #endif /* JOBS */ 32684887Schin savejobid = *jobid; 32694887Schin if(otype) 32704887Schin return(0); 32714887Schin } 32724887Schin return(spawnpid); 32734887Schin } 32744887Schin 32754887Schin # ifdef _was_lib_fork 32764887Schin # define _lib_fork 1 32774887Schin # endif 32784887Schin # ifndef _lib_fork 32794887Schin pid_t fork(void) 32804887Schin { 32814887Schin errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork"); 32824887Schin return(-1); 32834887Schin } 32844887Schin # endif /* _lib_fork */ 32854887Schin #endif /* SHOPT_SPAWN */ 3286