subshell.c revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Copyright (c) 1982-2007 AT&T Knowledge Ventures *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* by AT&T Knowledge Ventures *
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 (...)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct subshell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct subshell *pipe; /* subshell where output goes to pipe on fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char fdstatus;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine will turn the sftmp() file into a real /tmp file or pipe
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if the /tmp file create fails
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct checkpt *pp = (struct checkpt*)sh.jmplist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save file descriptor 1 if open */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* popping a discipline forces a /tmp file create */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* unable to create the /tmp file so use a pipe */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* write the data to the pipe */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
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 */
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't bother to save if in newer scope */
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))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((mp==nv_scoped(PATHNOD)) || (mp==nv_scoped(IFSNOD)))
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
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int old=0;
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 */
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check if standard output was preserved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore PWDNOD */