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 */
l_time(Sfio_t * outfile,register clock_t t,int p)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
p_time(Shell_t * shp,Sfio_t * out,const char * format,clock_t * tm)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*);
p_comarg(register struct comnod * com)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
sh_tclear(register Shnode_t * t)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
p_arg(register struct argnod * arg,int flag)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
p_switch(register struct regnod * reg)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
out_pattern(Sfio_t * iop,register const char * cp,int n)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
out_string(Sfio_t * iop,register const char * cp,int c,int quoted)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 */
put_level(Namval_t * np,const char * val,int flags,Namfun_t * fp)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
init_level(int level)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 */
sh_debug(Shell_t * shp,const char * trap,const char * name,const char * subscript,char * const argv[],int flags)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 */
sh_eval(register Sfio_t * iop,int mode)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
pipe_exec(Shell_t * shp,int pv[],Shnode_t * t,int errorflg)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 */
checkopt(char * argv[],int c)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
free_list(struct openlist * olist)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 */
set_instance(Shell_t * shp,Namval_t * nq,Namval_t * node,struct Namref * nr)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
unset_instance(Namval_t * nq,Namval_t * node,struct Namref * nr,long mode)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
sh_exec(register const Shnode_t * t,int flags)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
sh_run(int argn,char * argv[])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
trim_eq(register const char * r,register const char * s)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
sh_trace(register char * argv[],register int nl)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
timed_out(void * handle)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 */
_sh_fork(register pid_t parent,int flags,int * jobid)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
sh_fork(int flags,int * jobid)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 */
local_exports(register Namval_t * np,void * data)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 */
sh_funscope(int argn,char * argv[],int (* fun)(void *),void * arg,int execflg)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
sh_funct(Shell_t * shp,Namval_t * np,int argn,char * argv[],struct argnod * envlist,int execflg)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 */
sh_fun(Namval_t * np,Namval_t * nq,char * argv[])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 */
cmdrecurse(int argc,char * argv[],int ac,char * av[])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 */
coproc_init(Shell_t * shp,int pipes[])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 */
print_fun(register Namval_t * np,void * data)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 */
run_subshell(const Shnode_t * t,pid_t grp)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
sigreset(int mode)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 */
sh_ntfork(Shell_t * shp,const Shnode_t * t,char * argv[],int * jobid,int flag)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
fork(void)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