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 * Create and manage subshells avoiding forks when possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Note that the following structure must be the same
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * size as the Dtlink_t structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The following structure is used for command substitution and (...)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct subshell *pipe; /* subshell where output goes to pipe on fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine will turn the sftmp() file into a real /tmp file or pipe
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register struct checkpt *pp = (struct checkpt*)shp->jmplist;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register struct subshell *sp = subshell_data->pipe;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save file descriptor 1 if open */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sp && (shp->fdstatus[1]==IOCLOSE || (!shp->subshare && !(shp->fdstatus[1]&IONOSEEK))))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* write the data to the pipe */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((sfset(sfstdout,0,0)&SF_STRING) || fstat(1,&statb)<0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(fd==1 || ((shp->fdstatus[fd]&(IONOSEEK|IOSEEK|IOWRITE))!=(IOSEEK|IOWRITE)) || fstat(fd,&statx)<0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(statb.st_ino==statx.st_ino && statb.st_dev==statx.st_dev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine creates a temp file if necessary and creates a subshell.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The parent routine longjmps back to sh_subshell()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The child continues possibly with its standard output replaced by temp file
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether inside $(...) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this is the parent part of the fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this is the child part of the fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* setting subpid to 1 causes subshell to exit when reached */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(sp = (struct subshell*)subshell_data; sp; sp=sp->prev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine will make a copy of the given node in the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * layer created by the most recent subshell_fork if the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * node hasn't already been copied
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = (struct subshell*)subshell_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't bother with this */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(!sp->shpwd || (nv_isnull(np) && !add) || np==SH_LEVELNOD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't bother to save if in newer scope */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(np->nvenv && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && shp->last_root)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(mp || !np->nvfun || np->nvfun->subshell>=sh.subshell)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* first two pointers use linkage from np */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp = (struct Link*)malloc(sizeof(*np)+2*sizeof(void*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(memcmp(name,mp->nvname,len) || mp->nvname[len]!='.')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_clone(np,mp,(add?(nv_isnull(np)?0:NV_NOFREE)|NV_ARRAY:NV_MOVE));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * restore the variables
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->shpwd = 0; /* make sure sh_assignok doesn't save with nv_unset() */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz nv_putval(mp, nv_getval(np),np->nvflag|NV_NOFREE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return pointer to alias tree
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create new one if in a subshell and one doesn't exist and create is non-zero
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return pointer to function tree
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create new one if in a subshell and one doesn't exist and create is non-zero
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void table_unset(register Dt_t *root,int fun)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(fun && np->nvalue.rp && np->nvalue.rp->fname && *np->nvalue.rp->fname=='/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Run command tree <t> in a virtual sub-shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If comsub is not null, then output will be placed in temp file (or buffer)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If comsub is not null, the return value will be a stream consisting of
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * output of command <t>. Otherwise, NULL will be returned.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure initialization has occurred */
81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6aCasper H.S. Dik shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save trap table */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nsig += sizeof(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this nonsense needed for $(trap) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* disable job control */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save sfstdout and status */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use sftmp() file for standard output */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(comsub!=2 && jmpval!=SH_JMPSUB && shp->st.trapcom[0] && shp->subshell)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* trap on EXIT not handled by child */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* re-enable job control */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* sftmp() file has been returned into pipe */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move tmp file to iop and restore sfstdout */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* maybe locked try again */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check if standard output was preserved */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memset(&shp->st.trapcom[savst.trapmax],0,n*sizeof(char*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore PWDNOD */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_iorestore(shp,buff.topfd|IOSUBSHELL,jmpval);