da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
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* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Create and manage subshells avoiding forks when possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "defs.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "io.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "fault.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "shnodes.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "shlex.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "jobs.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "variables.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "path.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef PIPE_BUF
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define PIPE_BUF 512
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Note that the following structure must be the same
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * size as the Dtlink_t structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct Link
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct Link *next;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t *child;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Dt_t *dict;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Namval_t *node;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The following structure is used for command substitution and (...)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct subshell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Shell_t *shp; /* shell interpreter */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct subshell *prev; /* previous subshell data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct subshell *pipe; /* subshell where output goes to pipe on fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dt_t *var; /* variable table at time of subshell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct Link *svar; /* save shell variable table */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dt_t *sfun; /* function scope for subshell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dt_t *salias;/* alias scope for subshell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Pathcomp_t *pathlist; /* for PATH variable */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if (ERROR_VERSION >= 20030214L)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct Error_context_s *errcontext;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct errorcontext *errcontext;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Shopt_t options;/* save shell options */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid_t subpid; /* child process id */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* saveout;/*saved standard output */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *pwd; /* present working directory */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char *shpwd; /* saved pointer to sh.pwd */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin void *jobs; /* save job info */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode_t mask; /* saved umask */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short tmpfd; /* saved tmp file descriptor */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short pipefd; /* read fd if pipe is created */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char jobcontrol;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char monitor;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char fdstatus;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int fdsaved; /* bit make for saved files */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int sig; /* signal for $$ */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pid_t bckpid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pid_t cpid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int coutpipe;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int cpipe;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int nofork;
81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6aCasper H.S. Dik char subshare;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} *subshell_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int subenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine will turn the sftmp() file into a real /tmp file or pipe
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinvoid sh_subtmpfile(int pflag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Shell_t *shp = &sh;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int fds[2];
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Sfoff_t off;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register struct checkpt *pp = (struct checkpt*)shp->jmplist;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register struct subshell *sp = subshell_data->pipe;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sfset(sfstdout,0,0)&SF_STRING)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save file descriptor 1 if open */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(fd,F_SETFD,FD_CLOEXEC);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(1);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->fdstatus[1] = IOCLOSE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(errno!=EBADF)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->toomany = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_system(1),e_toomany);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(shp->subshare || !pflag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfdisc(sfstdout,SF_POPDISC);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((fd=sffileno(sfstdout))>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->fdstatus[fd] = IOREAD|IOWRITE;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfsync(sfstdout);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(fd==1)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fcntl(1,F_SETFD,0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfsetfd(sfstdout,1);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->fdstatus[1] = shp->fdstatus[fd];
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->fdstatus[fd] = IOCLOSE;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin goto skip;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sp && (shp->fdstatus[1]==IOCLOSE || (!shp->subshare && !(shp->fdstatus[1]&IONOSEEK))))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz struct stat statb,statx;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int fd;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_pipe(fds);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->pipefd = fds[0];
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* write the data to the pipe */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(off = sftell(sfstdout))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfpurge(sfstdout);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((sfset(sfstdout,0,0)&SF_STRING) || fstat(1,&statb)<0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz statb.st_ino = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfclose(sfstdout);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz errormsg(SH_DICT,ERROR_system(1),e_redirect);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(fds[1]);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(statb.st_ino) for(fd=0; fd < 10; fd++)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(fd==1 || ((shp->fdstatus[fd]&(IONOSEEK|IOSEEK|IOWRITE))!=(IOSEEK|IOWRITE)) || fstat(fd,&statx)<0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz continue;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(statb.st_ino==statx.st_ino && statb.st_dev==statx.st_dev)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_close(fd);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz fcntl(1,F_DUPFD, fd);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin skip:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_iostream(shp,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfset(sfstdout,SF_SHARE|SF_PUBLIC,1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfpool(sfstdout,shp->outpool,SF_WRITE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pp && pp->olist && pp->olist->strm == sfstdout)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp->olist->strm = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid sh_subfork(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = subshell_data;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Shell_t *shp = sp->shp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int curenv = shp->curenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid_t pid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char *trap = shp->st.trapcom[0];
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(trap)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz trap = strdup(trap);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether inside $(...) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->pipe)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_subtmpfile(1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->curenv = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(pid = sh_fork(FSHOWME,NIL(int*)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->curenv = curenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this is the parent part of the fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->subpid==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->subpid = pid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(trap)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz free((void*)trap);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin siglongjmp(*shp->jmplist,SH_JMPSUB);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this is the child part of the fork */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* setting subpid to 1 causes subshell to exit when reached */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_onstate(SH_FORKED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_onstate(SH_NOLOG);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner sh_offoption(SH_MONITOR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_offstate(SH_MONITOR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subshell_data = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->subshell = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SH_SUBSHELLNOD->nvalue.s = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->subpid=0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->st.trapcom[0] = trap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint nv_subsaved(register Namval_t *np)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct subshell *sp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct Link *lp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(sp = (struct subshell*)subshell_data; sp; sp=sp->prev)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(lp=sp->svar; lp; lp = lp->next)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(lp->node==np)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinNamval_t *sh_assignok(register Namval_t *np,int add)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register Namval_t *mp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct Link *lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = (struct subshell*)subshell_data;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin struct Ufunction *rp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Shell_t *shp = sp->shp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Dt_t *dp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t *mpnext;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namarr_t *ap;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int save;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't bother with this */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(!sp->shpwd || (nv_isnull(np) && !add) || np==SH_LEVELNOD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(np);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* don't bother to save if in newer scope */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(rp=shp->st.real_fun) || !(dp=rp->sdict))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dp = sp->var;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(np->nvenv && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && shp->last_root)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dp = shp->last_root;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((mp=nv_search((char*)np,dp,HASH_BUCKET))!=np)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(mp || !np->nvfun || np->nvfun->subshell>=sh.subshell)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(np);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((ap=nv_arrayptr(np)) && (mp=nv_opensub(np)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->last_root = ap->table;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_assignok(mp,add);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!add || array_assoc(ap))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(np);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(lp=subshell_data->svar; lp; lp = lp->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lp->node==np)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(np);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* first two pointers use linkage from np */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp = (struct Link*)malloc(sizeof(*np)+2*sizeof(void*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memset(lp,0, sizeof(*mp)+2*sizeof(void*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lp->node = np;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!add && nv_isvtree(np))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t fake;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Dt_t *walk, *root=shp->var_tree;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin char *name = nv_name(np);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int len = strlen(name);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fake.nvname = name;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mpnext = dtnext(root,&fake);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dp = root->walk?root->walk:root;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while(mp=mpnext)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin walk = root->walk?root->walk:root;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mpnext = dtnext(root,mp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(memcmp(name,mp->nvname,len) || mp->nvname[len]!='.')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin break;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_delete(mp,walk,NV_NOFREE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin *((Namval_t**)mp) = lp->child;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->child = mp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->dict = dp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mp = (Namval_t*)&lp->dict;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lp->next = subshell_data->svar;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subshell_data->svar = lp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin save = shp->subshell;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->subshell = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mp->nvname = np->nvname;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_clone(np,mp,(add?(nv_isnull(np)?0:NV_NOFREE)|NV_ARRAY:NV_MOVE));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->subshell = save;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(np);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * restore the variables
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void nv_restore(struct subshell *sp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct Link *lp, *lq;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Namval_t *mp, *np;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char *save = sp->shpwd;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t *mpnext;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->shpwd = 0; /* make sure sh_assignok doesn't save with nv_unset() */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(lp=sp->svar; lp; lp=lq)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = (Namval_t*)&lp->dict;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lq = lp->next;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mp = lp->node;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!mp->nvname)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nv_isarray(mp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nv_putsub(mp,NIL(char*),ARRAY_SCAN);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz _nv_unset(mp,NV_RDONLY|NV_CLONE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(nv_isarray(np))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_clone(np,mp,NV_MOVE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin goto skip;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nv_setsize(mp,nv_size(np));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mp->nvenv = np->nvenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mp->nvfun = np->nvfun;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mp->nvflag = np->nvflag;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(nv_cover(mp))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz nv_putval(mp, nv_getval(np),np->nvflag|NV_NOFREE);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(!nv_isattr(np,NV_NOFREE))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz nv_offattr(mp,NV_NOFREE);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mp->nvalue.cp = np->nvalue.cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin np->nvfun = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nv_isattr(mp,NV_EXPORT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *name = nv_name(mp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_envput(sh.env,mp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*name=='_' && strcmp(name,"_AST_FEATURES")==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin astconf(NiL, NiL, NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(nv_isattr(np,NV_EXPORT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env_delete(sh.env,nv_name(mp));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin skip:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(mp=lp->child; mp; mp=mpnext)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mpnext = *((Namval_t**)mp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dtinsert(lp->dict,mp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin free((void*)lp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->svar = lq;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->shpwd=save;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinDt_t *sh_subaliastree(int create)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = subshell_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sp || sh.curenv==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sh.alias_tree);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sp->salias && create)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->salias = dtopen(&_Nvdisc,Dtoset);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dtview(sp->salias,sh.alias_tree);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.alias_tree = sp->salias;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sp->salias);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinDt_t *sh_subfuntree(int create)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = subshell_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sp || sh.curenv==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sh.fun_tree);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sp->sfun && create)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->sfun = dtopen(&_Nvdisc,Dtoset);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dtview(sp->sfun,sh.fun_tree);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.fun_tree = sp->sfun;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(sh.fun_tree);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic void table_unset(register Dt_t *root,int fun)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Namval_t *np,*nq;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int flag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(np=(Namval_t*)dtfirst(root);np;np=nq)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nq = (Namval_t*)dtnext(root,np);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin flag=0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(fun && np->nvalue.rp && np->nvalue.rp->fname && *np->nvalue.rp->fname=='/')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np->nvalue.rp->fdict = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin flag = NV_NOFREE;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin _nv_unset(np,NV_RDONLY);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nv_delete(np,root,flag|NV_FUNCTION);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sh_subsavefd(register int fd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = subshell_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int old=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = !(sp->fdsaved&(1<<(fd-1)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->fdsaved |= (1<<(fd-1));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(old);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinvoid sh_subjobcheck(pid_t pid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct subshell *sp = subshell_data;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while(sp)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sp->cpid==pid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(sp->coutpipe);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(sp->cpipe);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->coutpipe = sp->cpipe = -1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp = sp->prev;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t *sh_subshell(Shnode_t *t, int flags, int comsub)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Shell_t *shp = &sh;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct subshell sub_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct subshell *sp = &sub_data;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int jmpval,nsig=0,duped=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int savecurenv = shp->curenv;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int savejobpgid = job.curpgid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int16_t subshell;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *savsig;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t *iop=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct checkpt buff;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct sh_scoped savst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct dolnod *argsav=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset((char*)sp, 0, sizeof(*sp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(shp->outpool);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin argsav = sh_arguse(shp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(shp->curenv==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subshell_data=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subenv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->curenv = ++subenv;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin job.curpgid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin savst = shp->st;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_pushcontext(&buff,SH_JMPSUB);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subshell = shp->subshell+1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SH_SUBSHELLNOD->nvalue.s = subshell;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->subshell = subshell;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->prev = subshell_data;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->shp = shp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->sig = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subshell_data = sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->errcontext = &buff.err;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->var = shp->var_tree;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->options = shp->options;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->jobs = job_subsave();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure initialization has occurred */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!shp->pathlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_get(".");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!shp->pwd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_pwd(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->bckpid = shp->bckpid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(comsub)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_stats(STAT_COMSUB);
81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6aCasper H.S. Dik sp->subshare = shp->subshare;
81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6aCasper H.S. Dik shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6aCasper H.S. Dik if(!comsub || !shp->subshare)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->shpwd = shp->pwd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->pwd = (shp->pwd?strdup(shp->pwd):0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->mask = shp->mask;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_stats(STAT_SUBSHELL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save trap table */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->st.otrapcom = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nsig += sizeof(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this nonsense needed for $(trap) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->st.otrapcom = (char**)savsig;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->cpid = shp->cpid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->coutpipe = shp->coutpipe;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->cpipe = shp->cpipe[1];
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->cpid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_sigreset(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jmpval = sigsetjmp(buff.buff,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jmpval==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(comsub)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* disable job control */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->spid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->jobcontrol = job.jobcontrol;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->monitor = (sh_isstate(SH_MONITOR)!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.jobcontrol=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_offstate(SH_MONITOR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->pipe = sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save sfstdout and status */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->saveout = sfswap(sfstdout,NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->fdstatus = shp->fdstatus[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->tmpfd = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->pipefd = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use sftmp() file for standard output */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(iop = sftmp(PIPE_BUF)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfswap(sp->saveout,sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfswap(iop,sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfset(sfstdout,SF_READ,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->fdstatus[1] = IOWRITE;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(sp->nofork = sh_state(SH_NOFORK)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_onstate(SH_NOFORK);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin flags |= sh_state(SH_NOFORK);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sp->prev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->pipe = sp->prev->pipe;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~sh_state(SH_NOFORK);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_exec(t,flags);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(comsub!=2 && jmpval!=SH_JMPSUB && shp->st.trapcom[0] && shp->subshell)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* trap on EXIT not handled by child */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *trap=shp->st.trapcom[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->st.trapcom[0] = 0; /* prevent recursion */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->oldexit = shp->exitval;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_trap(trap,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(trap);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_popcontext(&buff);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(shp->subshell==0) /* must be child process */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subshell_data = sp->prev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jmpval==SH_JMPSCRIPT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin siglongjmp(*shp->jmplist,jmpval);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->exitval &= SH_EXITMASK;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_done(shp,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(comsub)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* re-enable job control */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!sp->nofork)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_offstate(SH_NOFORK);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.jobcontrol = sp->jobcontrol;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->monitor)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_onstate(SH_MONITOR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->pipefd>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* sftmp() file has been returned into pipe */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin iop = sh_iostream(shp,sp->pipefd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move tmp file to iop and restore sfstdout */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin iop = sfswap(sfstdout,NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!iop)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* maybe locked try again */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclrlock(sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin iop = sfswap(sfstdout,NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(iop && sffileno(iop)==1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int fd=sfsetfd(iop,3);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fd<0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->toomany = 1;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_system(1),e_toomany);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->sftable[fd] = iop;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(fd,F_SETFD,FD_CLOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->fdstatus[fd] = (shp->fdstatus[1]|IOCLEX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->fdstatus[1] = IOCLOSE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfset(iop,SF_READ,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfswap(sp->saveout,sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check if standard output was preserved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->tmpfd>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(1);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (fcntl(sp->tmpfd,F_DUPFD,1) != 1)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz duped++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_close(sp->tmpfd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->fdstatus[1] = sp->fdstatus;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->subpid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(shp->exitval > SH_EXITSIG)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->sig = (shp->exitval&SH_EXITMASK);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->exitval = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(comsub)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->spid = sp->subpid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(comsub && iop && sp->pipefd<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfseek(iop,(off_t)0,SEEK_SET);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_delete((Pathcomp_t*)shp->pathlist);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->pathlist = (void*)sp->pathlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_subrestore(sp->jobs);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->jobenv = savecurenv;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin job.curpgid = savejobpgid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->bckpid = sp->bckpid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->shpwd) /* restore environment if saved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->options = sp->options;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nv_restore(sp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->salias)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->alias_tree = dtview(sp->salias,0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin table_unset(sp->salias,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dtclose(sp->salias);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->sfun)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->fun_tree = dtview(sp->sfun,0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin table_unset(sp->sfun,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dtclose(sp->sfun);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin n = shp->st.trapmax-savst.trapmax;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_sigreset(1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(n>0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memset(&shp->st.trapcom[savst.trapmax],0,n*sizeof(char*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->st = savst;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->curenv = savecurenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nsig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((char*)&shp->st.trapcom[0],savsig,nsig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((void*)savsig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->options = sp->options;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!shp->pwd || strcmp(sp->pwd,shp->pwd))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore PWDNOD */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Namval_t *pwdnod = sh_scoped(shp,PWDNOD);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(shp->pwd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin chdir(shp->pwd=sp->pwd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path_newdir(shp->pathlist);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nv_isattr(pwdnod,NV_NOFREE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pwdnod->nvalue.cp = (const char*)sp->pwd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sp->shpwd != shp->pwd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->pwd = sp->pwd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(PWDNOD->nvalue.cp==sp->shpwd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PWDNOD->nvalue.cp = sp->pwd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((void*)sp->pwd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->mask!=shp->mask)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin umask(shp->mask=sp->mask);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(shp->coutpipe!=sp->coutpipe)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(shp->coutpipe);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(shp->cpipe[1]);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->cpid = sp->cpid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->cpipe[1] = sp->cpipe;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin shp->coutpipe = sp->coutpipe;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6aCasper H.S. Dik shp->subshare = sp->subshare;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(shp->subshell)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SH_SUBSHELLNOD->nvalue.s = --shp->subshell;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz subshell = shp->subshell;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz subshell_data = sp->prev;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_argfree(shp,argsav,0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(shp->topfd != buff.topfd)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_iorestore(shp,buff.topfd|IOSUBSHELL,jmpval);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sp->sig)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sp->prev)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sp->prev->sig = sp->sig;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_fault(sp->sig);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_chktrap();
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_sigcheck();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shp->trapnote = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sp->subpid && !comsub)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_wait(sp->subpid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(shp->exitval > SH_EXITSIG)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int sig = shp->exitval&SH_EXITMASK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig==SIGINT || sig== SIGQUIT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_fault(sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(duped)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->toomany = 1;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz errormsg(SH_DICT,ERROR_system(1),e_redirect);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(jmpval && shp->toomany)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz siglongjmp(*shp->jmplist,jmpval);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(iop);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}