/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Create and manage subshells avoiding forks when possible
*
* David Korn
* AT&T Labs
*
*/
#include "defs.h"
#include <ls.h>
#include "io.h"
#include "fault.h"
#include "shnodes.h"
#include "shlex.h"
#include "jobs.h"
#include "variables.h"
#include "path.h"
#ifndef PIPE_BUF
#endif
/*
* Note that the following structure must be the same
* size as the Dtlink_t structure
*/
struct Link
{
};
/*
* The following structure is used for command substitution and (...)
*/
static struct subshell
{
#if (ERROR_VERSION >= 20030214L)
#else
#endif
char jobcontrol;
char monitor;
unsigned char fdstatus;
int coutpipe;
int cpipe;
int nofork;
char subshare;
} *subshell_data;
static int subenv;
/*
* This routine will turn the sftmp() file into a real /tmp file or pipe
*/
{
{
register int fd;
/* save file descriptor 1 if open */
{
close(1);
}
{
}
{
{
if(fd==1)
else
{
}
goto skip;
}
}
}
{
int fd;
/* write the data to the pipe */
{
}
{
if(fd==1 || ((shp->fdstatus[fd]&(IONOSEEK|IOSEEK|IOWRITE))!=(IOSEEK|IOWRITE)) || fstat(fd,&statx)<0)
continue;
{
}
}
skip:
}
}
/*
* This routine creates a temp file if necessary and creates a subshell.
* The parent routine longjmps back to sh_subshell()
* The child continues possibly with its standard output replaced by temp file
*/
void sh_subfork(void)
{
if(trap)
/* see whether inside $(...) */
sh_subtmpfile(1);
{
/* this is the parent part of the fork */
if(trap)
}
else
{
/* this is the child part of the fork */
/* setting subpid to 1 causes subshell to exit when reached */
subshell_data = 0;
SH_SUBSHELLNOD->nvalue.s = 0;
}
}
{
{
{
return(1);
}
}
return(0);
}
/*
* This routine will make a copy of the given node in the
* layer created by the most recent subshell_fork if the
* node hasn't already been copied
*/
{
int save;
/* don't bother with this */
return(np);
/* don't bother to save if in newer scope */
{
return(np);
}
{
return(np);
}
{
return(np);
}
/* first two pointers use linkage from np */
{
{
break;
}
}
return(np);
}
/*
* restore the variables
*/
{
{
continue;
if(nv_isarray(mp))
if(nv_isarray(np))
{
goto skip;
}
{
}
else
{
}
skip:
{
}
}
}
/*
* return pointer to alias tree
* create new one if in a subshell and one doesn't exist and create is non-zero
*/
{
return(sh.alias_tree);
{
}
}
/*
* return pointer to function tree
* create new one if in a subshell and one doesn't exist and create is non-zero
*/
{
{
}
}
{
int flag;
{
flag=0;
{
}
else
}
}
{
register int old=0;
if(sp)
{
}
return(old);
}
{
while(sp)
{
{
return;
}
}
}
/*
* Run command tree <t> in a virtual sub-shell
* If comsub is not null, then output will be placed in temp file (or buffer)
* If comsub is not null, the return value will be a stream consisting of
* output of command <t>. Otherwise, NULL will be returned.
*/
{
char *savsig;
{
subenv = 0;
}
subshell_data = sp;
/* make sure initialization has occurred */
path_get(".");
path_pwd(0);
if(comsub)
{
/* save trap table */
{
nsig += sizeof(char*);
/* this nonsense needed for $(trap) */
}
sh_sigreset(0);
}
if(jmpval==0)
{
if(comsub)
{
/* disable job control */
job.jobcontrol=0;
/* save sfstdout and status */
/* use sftmp() file for standard output */
{
}
}
{
}
}
{
/* trap on EXIT not handled by child */
}
{
if(jmpval==SH_JMPSCRIPT)
}
if(comsub)
{
/* re-enable job control */
{
/* sftmp() file has been returned into pipe */
}
else
{
/* move tmp file to iop and restore sfstdout */
if(!iop)
{
/* maybe locked try again */
}
{
if(fd<0)
{
}
}
}
/* check if standard output was preserved */
{
close(1);
duped++;
}
}
{
if(comsub)
}
{
int n;
nv_restore(sp);
{
}
{
}
sh_sigreset(1);
if(n>0)
if(nsig)
{
}
{
/* restore PWDNOD */
{
}
}
{
}
else
{
}
}
{
else
{
sh_chktrap();
}
}
sh_sigcheck();
{
}
if(duped)
{
}
return(iop);
}