da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * UNIX shell parse tree executer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extern int nice(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _lib_nice */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* !_lib_spawnveg */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_SPAWN */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int trim_eq(const char*, const char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* ======== command execution ========*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * print time <t> in h:m:s format with precision <p>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void l_time(Sfio_t *outfile,register clock_t t,int p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c!='%')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = l = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='P')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='l')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='U')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='S')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c!='R')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * clear argument pointers that point into the stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* call builtin to cleanup state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(flag==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_OPTIMIZE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void out_pattern(Sfio_t *iop, register const char *cp, int n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(c= *cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(c = *++cp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(*cp++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * this is for a debugger but it hasn't been tested yet
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if a debug script sets .sh.level it should set up the scope
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * as if you were executing in that level
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* perhaps this should be an error */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic const Namdisc_t level_disc = { sizeof(struct Level), put_level };
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * write the current common on the stack and make it available as .sh.command
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* now setup .sh.level variable */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Given stream <iop> compile and execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Shnode_t *t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin io_save = iop; /* preserve correct value across longjmp */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define SH_TOPFUN 0x8000 /* this is a temporary tksh hack */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic int pipe_exec(Shell_t* shp,int pv[], Shnode_t *t, int errorflg)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin volatile int r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((tchild->tre.tretyp&COMMSK)!=TCOM || !(np=(Namval_t*)(tchild->com.comnamp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_FASTPIPE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * returns 1 when option -<c> is specified
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * set ${.sh.name} and ${.sh.subscript}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * set _ to reference for ${.sh.name}[$.sh.subscript]
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerstatic int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sh.var_tree!=sh.var_base && !nv_open(cp,nr->root,NV_VARNAME|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->com.comline-shp->st.firstline;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int n = b_command(0,com,&shp->bltindata);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = nv_bfsearch(stkptr(stkp,offset), root, &nq, &cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_NAMESPACE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(np==SYSTYPESET || (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if(!shp->typeinit && (checkopt(com,'L') || checkopt(com,'R') || checkopt(com,'Z')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_TYPEDEF */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* fake 'true' built-in */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set +x doesn't echo */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(n==2)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->com.comline-shp->st.firstline;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((np=nv_search(com0,shp->fun_tree,0)) && !np->nvalue.ip)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for builtins */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * disable editors for built-in
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * versions of commands on PATH
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* do close-on-exec */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ((Shnode_t*)t)->com.comstate = shp->bltindata.data;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(shp->hist_ptr && item->strm == shp->hist_ptr->histfp)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* failure on special built-ins fatal */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore directory changed */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't restore for subshell exec */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for functions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* increase refcnt for unset */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* disable foreground job monitor */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_DEVFD */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _lib_fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_SPAWN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* This is the parent branch of fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * It may or may not wait for the child
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* print job number */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * this is the FORKED branch (child) of execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* default std input for & */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pipe in or out */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _lib_nice */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->fork.forkline-shp->st.firstline;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't clear job table for out
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pipes so that jobs comand can
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin be used in a pipeline
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * don't create a new process, just
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * save and restore io-streams
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if read end of pipe is a simple command
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * treat as non-sharable to improve performance
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->fork.forkline-shp->st.firstline;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* wait for remainder of pipline */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz nsig += sizeof(char*);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This code sets up a pipe.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * All elements of the pipe are started by the parent.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The last element executes in current environment
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin type = pipe_exec(shp,pvn,t->lst.lstlef, errorflg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* create the pipe */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* execute out part of pipe no wait */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_FASTPIPE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save the pipe stream-ids */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* close out-part of pipe */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pipeline all in one process group */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* repeat until end of pipeline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * execute last element of pipeline
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * in the current process
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* execution failure, close pipe */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* a list of commands are executed here */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int jmpval = ((struct checkpt*)shp->jmplist)->mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_OPTIMIZE */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->for_.forline-shp->st.firstline;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reuse register */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->exitval=sh_readline(shp,&nullptr,0,1,1000*shp->st.tmout);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_OPTIMIZE */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin volatile int r=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_FILESCAN*/
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int jmpval = ((struct checkpt*)shp->jmplist)->mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_OPTIMIZE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_FILESCAN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_FILESCAN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* This is for the arithmetic for */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_FILESCAN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_OPTIMIZE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SHOPT_FILESCAN */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->ar.arline-shp->st.firstline;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->exitval = !arith_exec((Arith_t*)t->ar.arcomp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->exitval=0; /* force zero exit for if-then-fi */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->sw.swline-shp->st.firstline;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct argnod *rex=(struct argnod*)t->reg.regptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* time the command */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* timeofday */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* timeofday */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* timeofday */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin at += ((shp->lim.clk_tck*(((1000000L/2)/shp->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* timeofday */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *fname = ((struct functnod*)t)->functnam;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = nv_open(stkptr(stkp,offset),shp->var_base,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_NAMESPACE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* look for discipline functions */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->funct.functline-shp->st.firstline;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Function names cannot be special builtin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if((np=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_NAMESPACE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(tp=nv_open(shp->typeinit->nvname,shp->typedict,NV_IDENT|NV_NOFAIL))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* new test compound command */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.line = t->tst.tstline-shp->st.firstline;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set $_ */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* store last argument here if it fits */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct comnod *t = (struct comnod*)stakalloc(sizeof(struct comnod));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t->comnamp = (void*)nv_bfsearch(argv[0],sh.fun_tree,(Namval_t**)&t->comnamq,(char**)0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * test for equality with second argument trimmed
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * returns 1 if r == trim(s) otherwise 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int trim_eq(register const char *r,register const char *s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(c = *s++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c && c != *r++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*r==0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * print out the command line if set -x is on
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make this trace atomic */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't quote [ and [[ */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine creates a subshell by calling fork() or vfork()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If ((flags&COMASK)==TCOM), then vfork() is permitted
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If fork fails, the shell sleeps for exponentially longer periods
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and tries again until a limit is reached.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * SH_FORKLIM is the max period between forks - power of 2 usually.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Currently shell tries after 2,4,8,16, and 32 seconds and then quits
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Failures cause the routine to error exit.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Parent links to here-documents are removed by the child
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Traps are reset by the child
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The process-id of the child is returned to the parent, 0 to the child.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * called by parent and child after fork by sh_fork()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinpid_t _sh_fork(register pid_t parent,int flags,int *jobid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* first process defines process group */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * errno==EPERM means that an earlier processes
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * completed. Make parent the job group id.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* This is the child process */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_ACCT */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Reset remaining signals to parent */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* except for those `lost' by trap */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_FASTPIPE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * add exports from previous scope to the new scope
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void local_exports(register Namval_t *np, void *data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), sh.var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine is used to execute the given function <fun> in a new scope
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If <fun> is NULL, then arg points to a structure containing a pointer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * to a function that will be executed in the current environment.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin struct sh_scoped savst, *prevscope = shp->st.self;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin volatile int r = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* eliminate parent scope */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nv_scan(prevscope->save_tree, local_exports,(void*)0, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((np=(fp->node)->nvalue.rp->nspace) && np!=shp->namespace)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_NAMESPACE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save trap table */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nsig += sizeof(char*);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((struct sh_scoped*)shp->topscope != shp->st.self)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * external interface to execute a function without arguments
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <np> is the function node
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If <nq> is not-null, then sh.name and sh.subscript will be set
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This dummy routine is called by built-ins that do recursion
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * on the file system (chmod, chgrp, chown). It causes
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the shell to invoke the non-builtin version in this case
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint cmdrecurse(int argc, char* argv[], int ac, char* av[])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * set up pipe for cooperating process
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void coproc_init(Shell_t *shp, int pipes[])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* first co-process */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * print out function definition
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void print_fun(register Namval_t* np, void *data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create a shell script consisting of t->fork.forktre and execute it
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pass the positional parameters */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* !_lib_fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(sig-- > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * A combined fork/exec for systems with slow or non-existent fork()
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* !_lib_fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* find first path that has a library component */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pp=path_get(argv[0]); pp && !pp->lib ; pp=pp->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin spawnpid = path_spawn(shp->shpath,&argv[-1],arge,pp,(grp<<1)|1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _lib_fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_SPAWN */