1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                  David Korn <dgk@research.att.com>                   *
18*4887Schin *                                                                      *
19*4887Schin ***********************************************************************/
20*4887Schin #pragma prototyped
21*4887Schin /*
22*4887Schin  *   Create and manage subshells avoiding forks when possible
23*4887Schin  *
24*4887Schin  *   David Korn
25*4887Schin  *   AT&T Labs
26*4887Schin  *
27*4887Schin  */
28*4887Schin 
29*4887Schin #include	"defs.h"
30*4887Schin #include	<ls.h>
31*4887Schin #include	"io.h"
32*4887Schin #include	"fault.h"
33*4887Schin #include	"shnodes.h"
34*4887Schin #include	"shlex.h"
35*4887Schin #include	"jobs.h"
36*4887Schin #include	"variables.h"
37*4887Schin #include	"path.h"
38*4887Schin 
39*4887Schin #ifndef PIPE_BUF
40*4887Schin #   define PIPE_BUF	512
41*4887Schin #endif
42*4887Schin 
43*4887Schin /*
44*4887Schin  * Note that the following structure must be the same
45*4887Schin  * size as the Dtlink_t structure
46*4887Schin  */
47*4887Schin struct Link
48*4887Schin {
49*4887Schin 	struct Link	*next;
50*4887Schin 	Namval_t	*node;
51*4887Schin };
52*4887Schin 
53*4887Schin /*
54*4887Schin  * The following structure is used for command substitution and (...)
55*4887Schin  */
56*4887Schin static struct subshell
57*4887Schin {
58*4887Schin 	struct subshell	*prev;	/* previous subshell data */
59*4887Schin 	struct subshell	*pipe;	/* subshell where output goes to pipe on fork */
60*4887Schin 	Dt_t		*var;	/* variable table at time of subshell */
61*4887Schin 	struct Link	*svar;	/* save shell variable table */
62*4887Schin 	Dt_t		*sfun;	/* function scope for subshell */
63*4887Schin 	Dt_t		*salias;/* alias scope for subshell */
64*4887Schin #ifdef PATH_BFPATH
65*4887Schin 	Pathcomp_t	*pathlist; /* for PATH variable */
66*4887Schin #endif
67*4887Schin #if (ERROR_VERSION >= 20030214L)
68*4887Schin 	struct Error_context_s *errcontext;
69*4887Schin #else
70*4887Schin 	struct errorcontext *errcontext;
71*4887Schin #endif
72*4887Schin 	Shopt_t		options;/* save shell options */
73*4887Schin 	pid_t		subpid;	/* child process id */
74*4887Schin 	Sfio_t*	saveout;/*saved standard output */
75*4887Schin 	char		*pwd;	/* present working directory */
76*4887Schin 	const char	*shpwd;	/* saved pointer to sh.pwd */
77*4887Schin 	void		*jobs;	/* save job info */
78*4887Schin 	mode_t		mask;	/* saved umask */
79*4887Schin 	short		tmpfd;	/* saved tmp file descriptor */
80*4887Schin 	short		pipefd;	/* read fd if pipe is created */
81*4887Schin 	char		jobcontrol;
82*4887Schin 	char		monitor;
83*4887Schin 	unsigned char	fdstatus;
84*4887Schin 	int		fdsaved; /* bit make for saved files */
85*4887Schin 	int		bckpid;
86*4887Schin } *subshell_data;
87*4887Schin 
88*4887Schin static int subenv;
89*4887Schin 
90*4887Schin /*
91*4887Schin  * This routine will turn the sftmp() file into a real /tmp file or pipe
92*4887Schin  * if the /tmp file create fails
93*4887Schin  */
94*4887Schin void	sh_subtmpfile(void)
95*4887Schin {
96*4887Schin 	if(sfset(sfstdout,0,0)&SF_STRING)
97*4887Schin 	{
98*4887Schin 		register int fd;
99*4887Schin 		register struct checkpt	*pp = (struct checkpt*)sh.jmplist;
100*4887Schin 		register struct subshell *sp = subshell_data->pipe;
101*4887Schin 		/* save file descriptor 1 if open */
102*4887Schin 		if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
103*4887Schin 		{
104*4887Schin 			fcntl(fd,F_SETFD,FD_CLOEXEC);
105*4887Schin 			sh.fdstatus[fd] = sh.fdstatus[1]|IOCLEX;
106*4887Schin 			close(1);
107*4887Schin 		}
108*4887Schin 		else if(errno!=EBADF)
109*4887Schin 			errormsg(SH_DICT,ERROR_system(1),e_toomany);
110*4887Schin 		/* popping a discipline forces a /tmp file create */
111*4887Schin 		sfdisc(sfstdout,SF_POPDISC);
112*4887Schin 		if((fd=sffileno(sfstdout))<0)
113*4887Schin 		{
114*4887Schin 			/* unable to create the /tmp file so use a pipe */
115*4887Schin 			int fds[2];
116*4887Schin 			Sfoff_t off;
117*4887Schin 			sh_pipe(fds);
118*4887Schin 			sp->pipefd = fds[0];
119*4887Schin 			sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
120*4887Schin 			/* write the data to the pipe */
121*4887Schin 			if(off = sftell(sfstdout))
122*4887Schin 				write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
123*4887Schin 			sfclose(sfstdout);
124*4887Schin 			if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1)
125*4887Schin 				errormsg(SH_DICT,ERROR_system(1),e_file+4);
126*4887Schin 			sh_close(fds[1]);
127*4887Schin 		}
128*4887Schin 		else
129*4887Schin 		{
130*4887Schin 			sh.fdstatus[fd] = IOREAD|IOWRITE;
131*4887Schin 			sfsync(sfstdout);
132*4887Schin 			if(fd==1)
133*4887Schin 				fcntl(1,F_SETFD,0);
134*4887Schin 			else
135*4887Schin 			{
136*4887Schin 				sfsetfd(sfstdout,1);
137*4887Schin 				sh.fdstatus[1] = sh.fdstatus[fd];
138*4887Schin 				sh.fdstatus[fd] = IOCLOSE;
139*4887Schin 			}
140*4887Schin 		}
141*4887Schin 		sh_iostream(1);
142*4887Schin 		sfset(sfstdout,SF_SHARE|SF_PUBLIC,1);
143*4887Schin 		sfpool(sfstdout,sh.outpool,SF_WRITE);
144*4887Schin 		if(pp && pp->olist  && pp->olist->strm == sfstdout)
145*4887Schin 			pp->olist->strm = 0;
146*4887Schin 	}
147*4887Schin }
148*4887Schin 
149*4887Schin /*
150*4887Schin  * This routine creates a temp file if necessary and creates a subshell.
151*4887Schin  * The parent routine longjmps back to sh_subshell()
152*4887Schin  * The child continues possibly with its standard output replaced by temp file
153*4887Schin  */
154*4887Schin void sh_subfork(void)
155*4887Schin {
156*4887Schin 	register struct subshell *sp = subshell_data;
157*4887Schin 	pid_t pid;
158*4887Schin 	/* see whether inside $(...) */
159*4887Schin 	if(sp->pipe)
160*4887Schin 		sh_subtmpfile();
161*4887Schin 	if(pid = sh_fork(0,NIL(int*)))
162*4887Schin 	{
163*4887Schin 		/* this is the parent part of the fork */
164*4887Schin 		if(sp->subpid==0)
165*4887Schin 			sp->subpid = pid;
166*4887Schin 		siglongjmp(*sh.jmplist,SH_JMPSUB);
167*4887Schin 	}
168*4887Schin 	else
169*4887Schin 	{
170*4887Schin 		int16_t subshell;
171*4887Schin 		/* this is the child part of the fork */
172*4887Schin 		/* setting subpid to 1 causes subshell to exit when reached */
173*4887Schin 		sh_onstate(SH_FORKED);
174*4887Schin 		sh_onstate(SH_NOLOG);
175*4887Schin 		sh_offstate(SH_MONITOR);
176*4887Schin 		subshell_data = 0;
177*4887Schin 		subshell = sh.subshell = 0;
178*4887Schin 		nv_putval(SH_SUBSHELLNOD, (char*)&subshell, NV_INT16);
179*4887Schin 		sp->subpid=0;
180*4887Schin 	}
181*4887Schin }
182*4887Schin 
183*4887Schin /*
184*4887Schin  * This routine will make a copy of the given node in the
185*4887Schin  * layer created by the most recent subshell_fork if the
186*4887Schin  * node hasn't already been copied
187*4887Schin  */
188*4887Schin Namval_t *sh_assignok(register Namval_t *np,int add)
189*4887Schin {
190*4887Schin 	register Namval_t *mp;
191*4887Schin 	register struct Link *lp;
192*4887Schin 	register struct subshell *sp = (struct subshell*)subshell_data;
193*4887Schin 	int save;
194*4887Schin 	/* don't bother with this */
195*4887Schin 	if(!sp->shpwd || (nv_isnull(np) && !add))
196*4887Schin 		return(np);
197*4887Schin 	/* don't bother to save if in newer scope */
198*4887Schin 	if(nv_search((char*)np,sp->var,HASH_BUCKET)!=np)
199*4887Schin 		return(np);
200*4887Schin 	for(lp=subshell_data->svar; lp; lp = lp->next)
201*4887Schin 	{
202*4887Schin 		if(lp->node==np)
203*4887Schin 			return(np);
204*4887Schin 	}
205*4887Schin 	mp =  newof(0,Namval_t,1,0);
206*4887Schin 	lp = (struct Link*)mp;
207*4887Schin 	lp->node = np;
208*4887Schin 	lp->next = subshell_data->svar;
209*4887Schin 	subshell_data->svar = lp;
210*4887Schin 	save = sh.subshell;
211*4887Schin 	sh.subshell = 0;;
212*4887Schin 	nv_clone(np,mp,NV_NOFREE);
213*4887Schin 	sh.subshell = save;
214*4887Schin 	return(np);
215*4887Schin }
216*4887Schin 
217*4887Schin /*
218*4887Schin  * restore the variables
219*4887Schin  */
220*4887Schin static void nv_restore(struct subshell *sp)
221*4887Schin {
222*4887Schin 	register struct Link *lp, *lq;
223*4887Schin 	register Namval_t *mp, *np;
224*4887Schin 	const char *save = sp->shpwd;
225*4887Schin 	sp->shpwd = 0;	/* make sure sh_assignok doesn't save with nv_unset() */
226*4887Schin 	for(lp=sp->svar; lp; lp=lq)
227*4887Schin 	{
228*4887Schin 		np = (Namval_t*)lp;
229*4887Schin 		mp = lp->node;
230*4887Schin 		lq = lp->next;
231*4887Schin 		if(nv_isarray(mp))
232*4887Schin 			 nv_putsub(mp,NIL(char*),ARRAY_SCAN);
233*4887Schin 		_nv_unset(mp,NV_RDONLY);
234*4887Schin 		nv_setsize(mp,nv_size(np));
235*4887Schin 		if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
236*4887Schin 			mp->nvenv = np->nvenv;
237*4887Schin 		mp->nvfun = np->nvfun;
238*4887Schin 		mp->nvflag = np->nvflag;
239*4887Schin 		if((mp==nv_scoped(PATHNOD)) || (mp==nv_scoped(IFSNOD)))
240*4887Schin 			nv_putval(mp, np->nvalue.cp,0);
241*4887Schin 		else
242*4887Schin 			mp->nvalue.cp = np->nvalue.cp;
243*4887Schin 		np->nvfun = 0;
244*4887Schin 		if(nv_isattr(mp,NV_EXPORT))
245*4887Schin 		{
246*4887Schin 			char *name = nv_name(mp);
247*4887Schin 			sh_envput(sh.env,mp);
248*4887Schin 			if(*name=='_' && strcmp(name,"_AST_FEATURES")==0)
249*4887Schin 				astconf(NiL, NiL, NiL);
250*4887Schin 		}
251*4887Schin 		else if(nv_isattr(np,NV_EXPORT))
252*4887Schin 			env_delete(sh.env,nv_name(mp));
253*4887Schin 		free((void*)np);
254*4887Schin 	}
255*4887Schin 	sp->shpwd=save;
256*4887Schin }
257*4887Schin 
258*4887Schin /*
259*4887Schin  * return pointer to alias tree
260*4887Schin  * create new one if in a subshell and one doesn't exist and create is non-zero
261*4887Schin  */
262*4887Schin Dt_t *sh_subaliastree(int create)
263*4887Schin {
264*4887Schin 	register struct subshell *sp = subshell_data;
265*4887Schin 	if(!sp || sh.curenv==0)
266*4887Schin 		return(sh.alias_tree);
267*4887Schin 	if(!sp->salias && create)
268*4887Schin 	{
269*4887Schin 		sp->salias = dtopen(&_Nvdisc,Dtoset);
270*4887Schin 		dtview(sp->salias,sh.alias_tree);
271*4887Schin 		sh.alias_tree = sp->salias;
272*4887Schin 	}
273*4887Schin 	return(sp->salias);
274*4887Schin }
275*4887Schin 
276*4887Schin /*
277*4887Schin  * return pointer to function tree
278*4887Schin  * create new one if in a subshell and one doesn't exist and create is non-zero
279*4887Schin  */
280*4887Schin Dt_t *sh_subfuntree(int create)
281*4887Schin {
282*4887Schin 	register struct subshell *sp = subshell_data;
283*4887Schin 	if(!sp || sh.curenv==0)
284*4887Schin 		return(sh.fun_tree);
285*4887Schin 	if(!sp->sfun && create)
286*4887Schin 	{
287*4887Schin 		sp->sfun = dtopen(&_Nvdisc,Dtoset);
288*4887Schin 		dtview(sp->sfun,sh.fun_tree);
289*4887Schin 		sh.fun_tree = sp->sfun;
290*4887Schin 	}
291*4887Schin 	return(sp->sfun);
292*4887Schin }
293*4887Schin 
294*4887Schin static void table_unset(register Dt_t *root)
295*4887Schin {
296*4887Schin 	register Namval_t *np,*nq;
297*4887Schin 	for(np=(Namval_t*)dtfirst(root);np;np=nq)
298*4887Schin 	{
299*4887Schin 		_nv_unset(np,NV_RDONLY);
300*4887Schin 		nq = (Namval_t*)dtnext(root,np);
301*4887Schin 		dtdelete(root,np);
302*4887Schin 		free((void*)np);
303*4887Schin 	}
304*4887Schin }
305*4887Schin 
306*4887Schin int sh_subsavefd(register int fd)
307*4887Schin {
308*4887Schin 	register struct subshell *sp = subshell_data;
309*4887Schin 	register int old=0;
310*4887Schin 	if(sp)
311*4887Schin 	{
312*4887Schin 		old = !(sp->fdsaved&(1<<(fd-1)));
313*4887Schin 		sp->fdsaved |= (1<<(fd-1));
314*4887Schin 	}
315*4887Schin 	return(old);
316*4887Schin }
317*4887Schin 
318*4887Schin /*
319*4887Schin  * Run command tree <t> in a virtual sub-shell
320*4887Schin  * If comsub is not null, then output will be placed in temp file (or buffer)
321*4887Schin  * If comsub is not null, the return value will be a stream consisting of
322*4887Schin  * output of command <t>.  Otherwise, NULL will be returned.
323*4887Schin  */
324*4887Schin 
325*4887Schin Sfio_t *sh_subshell(Shnode_t *t, int flags, int comsub)
326*4887Schin {
327*4887Schin 	Shell_t *shp = &sh;
328*4887Schin 	struct subshell sub_data;
329*4887Schin 	register struct subshell *sp = &sub_data;
330*4887Schin 	int jmpval,nsig;
331*4887Schin 	int savecurenv = shp->curenv;
332*4887Schin 	int16_t subshell;
333*4887Schin 	char *savsig;
334*4887Schin 	Sfio_t *iop=0;
335*4887Schin 	struct checkpt buff;
336*4887Schin 	struct sh_scoped savst;
337*4887Schin 	struct dolnod   *argsav=0;
338*4887Schin 	memset((char*)sp, 0, sizeof(*sp));
339*4887Schin 	sfsync(shp->outpool);
340*4887Schin 	argsav = sh_arguse();
341*4887Schin 	if(shp->curenv==0)
342*4887Schin 	{
343*4887Schin 		subshell_data=0;
344*4887Schin 		subenv = 0;
345*4887Schin 	}
346*4887Schin 	shp->curenv = ++subenv;
347*4887Schin 	savst = shp->st;
348*4887Schin 	sh_pushcontext(&buff,SH_JMPSUB);
349*4887Schin 	subshell = shp->subshell+1;
350*4887Schin 	nv_putval(SH_SUBSHELLNOD, (char*)&subshell, NV_INT16);
351*4887Schin 	shp->subshell = subshell;
352*4887Schin 	sp->prev = subshell_data;
353*4887Schin 	subshell_data = sp;
354*4887Schin 	sp->errcontext = &buff.err;
355*4887Schin 	sp->var = shp->var_tree;
356*4887Schin 	sp->options = shp->options;
357*4887Schin 	sp->jobs = job_subsave();
358*4887Schin #ifdef PATH_BFPATH
359*4887Schin 	/* make sure initialization has occurred */
360*4887Schin 	if(!shp->pathlist)
361*4887Schin 		path_get(".");
362*4887Schin 	sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
363*4887Schin #endif
364*4887Schin 	if(!shp->pwd)
365*4887Schin 		path_pwd(0);
366*4887Schin 	sp->bckpid = shp->bckpid;
367*4887Schin 	if(!comsub || !sh_isoption(SH_SUBSHARE))
368*4887Schin 	{
369*4887Schin 		sp->shpwd = shp->pwd;
370*4887Schin 		sp->pwd = (shp->pwd?strdup(shp->pwd):0);
371*4887Schin 		sp->mask = shp->mask;
372*4887Schin 		/* save trap table */
373*4887Schin 		shp->st.otrapcom = 0;
374*4887Schin 		if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
375*4887Schin 		{
376*4887Schin 			nsig += sizeof(char*);
377*4887Schin 			memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
378*4887Schin 			/* this nonsense needed for $(trap) */
379*4887Schin 			shp->st.otrapcom = (char**)savsig;
380*4887Schin 		}
381*4887Schin 		sh_sigreset(0);
382*4887Schin 	}
383*4887Schin 	jmpval = sigsetjmp(buff.buff,0);
384*4887Schin 	if(jmpval==0)
385*4887Schin 	{
386*4887Schin 		if(comsub)
387*4887Schin 		{
388*4887Schin 			/* disable job control */
389*4887Schin 			sp->jobcontrol = job.jobcontrol;
390*4887Schin 			sp->monitor = (sh_isstate(SH_MONITOR)!=0);
391*4887Schin 			job.jobcontrol=0;
392*4887Schin 			sh_offstate(SH_MONITOR);
393*4887Schin 			sp->pipe = sp;
394*4887Schin 			/* save sfstdout and status */
395*4887Schin 			sp->saveout = sfswap(sfstdout,NIL(Sfio_t*));
396*4887Schin 			sp->fdstatus = shp->fdstatus[1];
397*4887Schin 			sp->tmpfd = -1;
398*4887Schin 			sp->pipefd = -1;
399*4887Schin 			/* use sftmp() file for standard output */
400*4887Schin 			if(!(iop = sftmp(PIPE_BUF)))
401*4887Schin 			{
402*4887Schin 				sfswap(sp->saveout,sfstdout);
403*4887Schin 				errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
404*4887Schin 			}
405*4887Schin 			sfswap(iop,sfstdout);
406*4887Schin 			sfset(sfstdout,SF_READ,0);
407*4887Schin 			shp->fdstatus[1] = IOWRITE;
408*4887Schin 		}
409*4887Schin 		else if(sp->prev)
410*4887Schin 		{
411*4887Schin 			sp->pipe = sp->prev->pipe;
412*4887Schin 			flags &= ~sh_state(SH_NOFORK);
413*4887Schin 		}
414*4887Schin 		sh_exec(t,flags);
415*4887Schin 	}
416*4887Schin 	if(jmpval!=SH_JMPSUB && shp->st.trapcom[0] && shp->subshell)
417*4887Schin 	{
418*4887Schin 		/* trap on EXIT not handled by child */
419*4887Schin 		char *trap=shp->st.trapcom[0];
420*4887Schin 		shp->st.trapcom[0] = 0;	/* prevent recursion */
421*4887Schin 		shp->oldexit = shp->exitval;
422*4887Schin 		sh_trap(trap,0);
423*4887Schin 		free(trap);
424*4887Schin 	}
425*4887Schin 	sh_popcontext(&buff);
426*4887Schin 	if(shp->subshell==0)	/* must be child process */
427*4887Schin 	{
428*4887Schin 		subshell_data = sp->prev;
429*4887Schin 		if(jmpval==SH_JMPSCRIPT)
430*4887Schin 			siglongjmp(*shp->jmplist,jmpval);
431*4887Schin 		sh_done(0);
432*4887Schin 	}
433*4887Schin 	if(comsub)
434*4887Schin 	{
435*4887Schin 		/* re-enable job control */
436*4887Schin 		job.jobcontrol = sp->jobcontrol;
437*4887Schin 		if(sp->monitor)
438*4887Schin 			sh_onstate(SH_MONITOR);
439*4887Schin 		if(sp->pipefd>=0)
440*4887Schin 		{
441*4887Schin 			/* sftmp() file has been returned into pipe */
442*4887Schin 			iop = sh_iostream(sp->pipefd);
443*4887Schin 			sfdisc(iop,SF_POPDISC);
444*4887Schin 			sfclose(sfstdout);
445*4887Schin 		}
446*4887Schin 		else
447*4887Schin 		{
448*4887Schin 			/* move tmp file to iop and restore sfstdout */
449*4887Schin 			iop = sfswap(sfstdout,NIL(Sfio_t*));
450*4887Schin 			if(!iop)
451*4887Schin 			{
452*4887Schin 				/* maybe locked try again */
453*4887Schin 				sfclrlock(sfstdout);
454*4887Schin 				iop = sfswap(sfstdout,NIL(Sfio_t*));
455*4887Schin 			}
456*4887Schin 			if(iop && sffileno(iop)==1)
457*4887Schin 			{
458*4887Schin 				int fd=sfsetfd(iop,3);
459*4887Schin 				if(fd<0)
460*4887Schin 					errormsg(SH_DICT,ERROR_system(1),e_toomany);
461*4887Schin 				shp->sftable[fd] = iop;
462*4887Schin 				fcntl(fd,F_SETFD,FD_CLOEXEC);
463*4887Schin 				shp->fdstatus[fd] = (shp->fdstatus[1]|IOCLEX);
464*4887Schin 				shp->fdstatus[1] = IOCLOSE;
465*4887Schin 			}
466*4887Schin 			sfset(iop,SF_READ,1);
467*4887Schin 		}
468*4887Schin 		sfswap(sp->saveout,sfstdout);
469*4887Schin 		/*  check if standard output was preserved */
470*4887Schin 		if(sp->tmpfd>=0)
471*4887Schin 		{
472*4887Schin 			close(1);
473*4887Schin 			fcntl(sp->tmpfd,F_DUPFD,1);
474*4887Schin 			sh_close(sp->tmpfd);
475*4887Schin 		}
476*4887Schin 		shp->fdstatus[1] = sp->fdstatus;
477*4887Schin 	}
478*4887Schin 	if(sp->subpid)
479*4887Schin 		job_wait(sp->subpid);
480*4887Schin 	if(comsub && iop)
481*4887Schin 		sfseek(iop,(off_t)0,SEEK_SET);
482*4887Schin 	if(shp->subshell)
483*4887Schin 		shp->subshell--;
484*4887Schin 	subshell = shp->subshell;
485*4887Schin 	nv_putval(SH_SUBSHELLNOD, (char*)&subshell, NV_INT16);
486*4887Schin #ifdef PATH_BFPATH
487*4887Schin 	path_delete((Pathcomp_t*)shp->pathlist);
488*4887Schin 	shp->pathlist = (void*)sp->pathlist;
489*4887Schin #endif
490*4887Schin 	job_subrestore(sp->jobs);
491*4887Schin 	shp->jobenv = savecurenv;
492*4887Schin 	shp->bckpid = sp->bckpid;
493*4887Schin 	if(sp->shpwd)	/* restore environment if saved */
494*4887Schin 	{
495*4887Schin 		shp->options = sp->options;
496*4887Schin 		nv_restore(sp);
497*4887Schin 		if(sp->salias)
498*4887Schin 		{
499*4887Schin 			shp->alias_tree = dtview(sp->salias,0);
500*4887Schin 			table_unset(sp->salias);
501*4887Schin 			dtclose(sp->salias);
502*4887Schin 		}
503*4887Schin 		if(sp->sfun)
504*4887Schin 		{
505*4887Schin 			shp->fun_tree = dtview(sp->sfun,0);
506*4887Schin 			table_unset(sp->sfun);
507*4887Schin 			dtclose(sp->sfun);
508*4887Schin 		}
509*4887Schin 		sh_sigreset(1);
510*4887Schin 		shp->st = savst;
511*4887Schin 		shp->curenv = savecurenv;
512*4887Schin 		if(nsig)
513*4887Schin 		{
514*4887Schin 			memcpy((char*)&shp->st.trapcom[0],savsig,nsig);
515*4887Schin 			free((void*)savsig);
516*4887Schin 		}
517*4887Schin 		shp->options = sp->options;
518*4887Schin 		if(!shp->pwd || strcmp(sp->pwd,shp->pwd))
519*4887Schin 		{
520*4887Schin 			/* restore PWDNOD */
521*4887Schin 			Namval_t *pwdnod = nv_scoped(PWDNOD);
522*4887Schin 			if(shp->pwd)
523*4887Schin 			{
524*4887Schin 				chdir(shp->pwd=sp->pwd);
525*4887Schin #ifdef PATH_BFPATH
526*4887Schin 				path_newdir(shp->pathlist);
527*4887Schin #endif
528*4887Schin 			}
529*4887Schin 			if(nv_isattr(pwdnod,NV_NOFREE))
530*4887Schin 				pwdnod->nvalue.cp = (const char*)sp->pwd;
531*4887Schin 		}
532*4887Schin 		else if(sp->shpwd != shp->pwd)
533*4887Schin 		{
534*4887Schin 			shp->pwd = sp->pwd;
535*4887Schin 			if(PWDNOD->nvalue.cp==sp->shpwd)
536*4887Schin 				PWDNOD->nvalue.cp = sp->pwd;
537*4887Schin 		}
538*4887Schin 		else
539*4887Schin 			free((void*)sp->pwd);
540*4887Schin 		if(sp->mask!=shp->mask)
541*4887Schin 			umask(shp->mask);
542*4887Schin 	}
543*4887Schin 	subshell_data = sp->prev;
544*4887Schin 	sh_argfree(argsav,0);
545*4887Schin 	shp->trapnote = 0;
546*4887Schin 	if(shp->topfd != buff.topfd)
547*4887Schin 		sh_iorestore(buff.topfd|IOSUBSHELL,jmpval);
548*4887Schin 	if(shp->exitval > SH_EXITSIG)
549*4887Schin 	{
550*4887Schin 		int sig = shp->exitval&SH_EXITMASK;
551*4887Schin 		if(sig==SIGINT || sig== SIGQUIT)
552*4887Schin 			sh_fault(sig);
553*4887Schin 	}
554*4887Schin 	return(iop);
555*4887Schin }
556