1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1982-2012 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * Create and manage subshells avoiding forks when possible
23da2e3ebdSchin *
24da2e3ebdSchin * David Korn
25da2e3ebdSchin * AT&T Labs
26da2e3ebdSchin *
27da2e3ebdSchin */
28da2e3ebdSchin
29da2e3ebdSchin #include "defs.h"
30da2e3ebdSchin #include <ls.h>
31da2e3ebdSchin #include "io.h"
32da2e3ebdSchin #include "fault.h"
33da2e3ebdSchin #include "shnodes.h"
34da2e3ebdSchin #include "shlex.h"
35da2e3ebdSchin #include "jobs.h"
36da2e3ebdSchin #include "variables.h"
37da2e3ebdSchin #include "path.h"
38da2e3ebdSchin
39da2e3ebdSchin #ifndef PIPE_BUF
40da2e3ebdSchin # define PIPE_BUF 512
41da2e3ebdSchin #endif
42da2e3ebdSchin
43*b30d1939SAndy Fiddaman #ifndef O_SEARCH
44*b30d1939SAndy Fiddaman # ifdef O_PATH
45*b30d1939SAndy Fiddaman # define O_SEARCH O_PATH
46*b30d1939SAndy Fiddaman # else
47*b30d1939SAndy Fiddaman # define O_SEARCH 0
48*b30d1939SAndy Fiddaman # endif
49*b30d1939SAndy Fiddaman #endif
50*b30d1939SAndy Fiddaman
51da2e3ebdSchin /*
52da2e3ebdSchin * Note that the following structure must be the same
53da2e3ebdSchin * size as the Dtlink_t structure
54da2e3ebdSchin */
55da2e3ebdSchin struct Link
56da2e3ebdSchin {
57da2e3ebdSchin struct Link *next;
587c2fbfb3SApril Chin Namval_t *child;
597c2fbfb3SApril Chin Dt_t *dict;
60da2e3ebdSchin Namval_t *node;
61da2e3ebdSchin };
62da2e3ebdSchin
63da2e3ebdSchin /*
64da2e3ebdSchin * The following structure is used for command substitution and (...)
65da2e3ebdSchin */
66da2e3ebdSchin static struct subshell
67da2e3ebdSchin {
687c2fbfb3SApril Chin Shell_t *shp; /* shell interpreter */
69da2e3ebdSchin struct subshell *prev; /* previous subshell data */
70da2e3ebdSchin struct subshell *pipe; /* subshell where output goes to pipe on fork */
71da2e3ebdSchin Dt_t *var; /* variable table at time of subshell */
72da2e3ebdSchin struct Link *svar; /* save shell variable table */
73da2e3ebdSchin Dt_t *sfun; /* function scope for subshell */
74da2e3ebdSchin Dt_t *salias;/* alias scope for subshell */
75da2e3ebdSchin Pathcomp_t *pathlist; /* for PATH variable */
76da2e3ebdSchin #if (ERROR_VERSION >= 20030214L)
77da2e3ebdSchin struct Error_context_s *errcontext;
78da2e3ebdSchin #else
79da2e3ebdSchin struct errorcontext *errcontext;
80da2e3ebdSchin #endif
81da2e3ebdSchin Shopt_t options;/* save shell options */
82da2e3ebdSchin pid_t subpid; /* child process id */
83da2e3ebdSchin Sfio_t* saveout;/*saved standard output */
84da2e3ebdSchin char *pwd; /* present working directory */
85da2e3ebdSchin const char *shpwd; /* saved pointer to sh.pwd */
86da2e3ebdSchin void *jobs; /* save job info */
87*b30d1939SAndy Fiddaman int pwdfd; /* file descritor for pwd */
88da2e3ebdSchin mode_t mask; /* saved umask */
89da2e3ebdSchin short tmpfd; /* saved tmp file descriptor */
90da2e3ebdSchin short pipefd; /* read fd if pipe is created */
91da2e3ebdSchin char jobcontrol;
92da2e3ebdSchin char monitor;
93da2e3ebdSchin unsigned char fdstatus;
94da2e3ebdSchin int fdsaved; /* bit make for saved files */
957c2fbfb3SApril Chin int sig; /* signal for $$ */
967c2fbfb3SApril Chin pid_t bckpid;
977c2fbfb3SApril Chin pid_t cpid;
987c2fbfb3SApril Chin int coutpipe;
997c2fbfb3SApril Chin int cpipe;
1007c2fbfb3SApril Chin int nofork;
101*b30d1939SAndy Fiddaman int subdup;
10281af778eSCasper H.S. Dik char subshare;
103*b30d1939SAndy Fiddaman char comsub;
104*b30d1939SAndy Fiddaman char pwdclose;
105*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
106*b30d1939SAndy Fiddaman void *coshell;
107*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
108da2e3ebdSchin } *subshell_data;
109da2e3ebdSchin
110da2e3ebdSchin static int subenv;
111da2e3ebdSchin
112*b30d1939SAndy Fiddaman
113da2e3ebdSchin /*
114da2e3ebdSchin * This routine will turn the sftmp() file into a real /tmp file or pipe
115*b30d1939SAndy Fiddaman * if the /tmp file create fails
116da2e3ebdSchin */
sh_subtmpfile(Shell_t * shp)117*b30d1939SAndy Fiddaman void sh_subtmpfile(Shell_t *shp)
118da2e3ebdSchin {
119da2e3ebdSchin if(sfset(sfstdout,0,0)&SF_STRING)
120da2e3ebdSchin {
121da2e3ebdSchin register int fd;
122*b30d1939SAndy Fiddaman register struct checkpt *pp = (struct checkpt*)shp->jmplist;
123*b30d1939SAndy Fiddaman register struct subshell *sp = subshell_data->pipe;
124da2e3ebdSchin /* save file descriptor 1 if open */
125da2e3ebdSchin if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
126da2e3ebdSchin {
127da2e3ebdSchin fcntl(fd,F_SETFD,FD_CLOEXEC);
128*b30d1939SAndy Fiddaman VALIDATE_FD(shp, fd);
1297c2fbfb3SApril Chin shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
130da2e3ebdSchin close(1);
131da2e3ebdSchin }
132da2e3ebdSchin else if(errno!=EBADF)
133da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),e_toomany);
134*b30d1939SAndy Fiddaman /* popping a discipline forces a /tmp file create */
135*b30d1939SAndy Fiddaman sfdisc(sfstdout,SF_POPDISC);
136*b30d1939SAndy Fiddaman if((fd=sffileno(sfstdout))<0)
137da2e3ebdSchin {
138*b30d1939SAndy Fiddaman /* unable to create the /tmp file so use a pipe */
139*b30d1939SAndy Fiddaman int fds[3];
140*b30d1939SAndy Fiddaman Sfoff_t off;
141*b30d1939SAndy Fiddaman fds[2] = 0;
142*b30d1939SAndy Fiddaman sh_pipe(fds);
143*b30d1939SAndy Fiddaman sp->pipefd = fds[0];
144*b30d1939SAndy Fiddaman sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
145*b30d1939SAndy Fiddaman /* write the data to the pipe */
146*b30d1939SAndy Fiddaman if(off = sftell(sfstdout))
147*b30d1939SAndy Fiddaman write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
148*b30d1939SAndy Fiddaman sfclose(sfstdout);
149*b30d1939SAndy Fiddaman if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1)
150*b30d1939SAndy Fiddaman errormsg(SH_DICT,ERROR_system(1),e_file+4);
151*b30d1939SAndy Fiddaman sh_close(fds[1]);
1527c2fbfb3SApril Chin }
153*b30d1939SAndy Fiddaman else
15434f9b3eeSRoland Mainz {
155*b30d1939SAndy Fiddaman VALIDATE_FD(shp, fd);
156*b30d1939SAndy Fiddaman shp->fdstatus[fd] = IOREAD|IOWRITE;
157*b30d1939SAndy Fiddaman sfsync(sfstdout);
158*b30d1939SAndy Fiddaman if(fd==1)
159*b30d1939SAndy Fiddaman fcntl(1,F_SETFD,0);
160*b30d1939SAndy Fiddaman else
16134f9b3eeSRoland Mainz {
162*b30d1939SAndy Fiddaman sfsetfd(sfstdout,1);
163*b30d1939SAndy Fiddaman shp->fdstatus[1] = shp->fdstatus[fd];
164*b30d1939SAndy Fiddaman shp->fdstatus[fd] = IOCLOSE;
16534f9b3eeSRoland Mainz }
16634f9b3eeSRoland Mainz }
1677c2fbfb3SApril Chin sh_iostream(shp,1);
168da2e3ebdSchin sfset(sfstdout,SF_SHARE|SF_PUBLIC,1);
1697c2fbfb3SApril Chin sfpool(sfstdout,shp->outpool,SF_WRITE);
170da2e3ebdSchin if(pp && pp->olist && pp->olist->strm == sfstdout)
171da2e3ebdSchin pp->olist->strm = 0;
172da2e3ebdSchin }
173da2e3ebdSchin }
174da2e3ebdSchin
17534f9b3eeSRoland Mainz
176da2e3ebdSchin /*
177da2e3ebdSchin * This routine creates a temp file if necessary and creates a subshell.
178da2e3ebdSchin * The parent routine longjmps back to sh_subshell()
179da2e3ebdSchin * The child continues possibly with its standard output replaced by temp file
180da2e3ebdSchin */
sh_subfork(void)181da2e3ebdSchin void sh_subfork(void)
182da2e3ebdSchin {
183da2e3ebdSchin register struct subshell *sp = subshell_data;
1847c2fbfb3SApril Chin Shell_t *shp = sp->shp;
1857c2fbfb3SApril Chin int curenv = shp->curenv;
186da2e3ebdSchin pid_t pid;
18734f9b3eeSRoland Mainz char *trap = shp->st.trapcom[0];
18834f9b3eeSRoland Mainz if(trap)
18934f9b3eeSRoland Mainz trap = strdup(trap);
190da2e3ebdSchin /* see whether inside $(...) */
191da2e3ebdSchin if(sp->pipe)
192*b30d1939SAndy Fiddaman sh_subtmpfile(shp);
1937c2fbfb3SApril Chin shp->curenv = 0;
194*b30d1939SAndy Fiddaman shp->savesig = -1;
195*b30d1939SAndy Fiddaman if(pid = sh_fork(shp,FSHOWME,NIL(int*)))
196da2e3ebdSchin {
1977c2fbfb3SApril Chin shp->curenv = curenv;
198da2e3ebdSchin /* this is the parent part of the fork */
199da2e3ebdSchin if(sp->subpid==0)
200da2e3ebdSchin sp->subpid = pid;
20134f9b3eeSRoland Mainz if(trap)
20234f9b3eeSRoland Mainz free((void*)trap);
2037c2fbfb3SApril Chin siglongjmp(*shp->jmplist,SH_JMPSUB);
204da2e3ebdSchin }
205da2e3ebdSchin else
206da2e3ebdSchin {
207da2e3ebdSchin /* this is the child part of the fork */
208da2e3ebdSchin /* setting subpid to 1 causes subshell to exit when reached */
209da2e3ebdSchin sh_onstate(SH_FORKED);
210da2e3ebdSchin sh_onstate(SH_NOLOG);
2113e14f97fSRoger A. Faulkner sh_offoption(SH_MONITOR);
212da2e3ebdSchin sh_offstate(SH_MONITOR);
213da2e3ebdSchin subshell_data = 0;
2147c2fbfb3SApril Chin shp->subshell = 0;
215*b30d1939SAndy Fiddaman shp->comsub = 0;
2167c2fbfb3SApril Chin SH_SUBSHELLNOD->nvalue.s = 0;
217da2e3ebdSchin sp->subpid=0;
21834f9b3eeSRoland Mainz shp->st.trapcom[0] = trap;
219*b30d1939SAndy Fiddaman shp->savesig = 0;
220da2e3ebdSchin }
221da2e3ebdSchin }
222da2e3ebdSchin
nv_subsaved(register Namval_t * np)2237c2fbfb3SApril Chin int nv_subsaved(register Namval_t *np)
2247c2fbfb3SApril Chin {
2257c2fbfb3SApril Chin register struct subshell *sp;
2267c2fbfb3SApril Chin register struct Link *lp;
2277c2fbfb3SApril Chin for(sp = (struct subshell*)subshell_data; sp; sp=sp->prev)
2287c2fbfb3SApril Chin {
2297c2fbfb3SApril Chin for(lp=sp->svar; lp; lp = lp->next)
2307c2fbfb3SApril Chin {
2317c2fbfb3SApril Chin if(lp->node==np)
2327c2fbfb3SApril Chin return(1);
2337c2fbfb3SApril Chin }
2347c2fbfb3SApril Chin }
2357c2fbfb3SApril Chin return(0);
2367c2fbfb3SApril Chin }
2377c2fbfb3SApril Chin
238da2e3ebdSchin /*
239da2e3ebdSchin * This routine will make a copy of the given node in the
240da2e3ebdSchin * layer created by the most recent subshell_fork if the
241da2e3ebdSchin * node hasn't already been copied
242da2e3ebdSchin */
sh_assignok(register Namval_t * np,int add)243da2e3ebdSchin Namval_t *sh_assignok(register Namval_t *np,int add)
244da2e3ebdSchin {
2457c2fbfb3SApril Chin register Namval_t *mp;
2467c2fbfb3SApril Chin register struct Link *lp;
247*b30d1939SAndy Fiddaman register struct subshell *sp;
248*b30d1939SAndy Fiddaman Shell_t *shp;
2497c2fbfb3SApril Chin Dt_t *dp;
2507c2fbfb3SApril Chin Namval_t *mpnext;
2517c2fbfb3SApril Chin Namarr_t *ap;
2527c2fbfb3SApril Chin int save;
253*b30d1939SAndy Fiddaman
254*b30d1939SAndy Fiddaman sp = (struct subshell*)subshell_data;
255*b30d1939SAndy Fiddaman
256da2e3ebdSchin /* don't bother with this */
257*b30d1939SAndy Fiddaman if(!sp || !sp->shpwd || np==SH_LEVELNOD || np==L_ARGNOD || np==SH_SUBSCRNOD || np==SH_NAMENOD)
258da2e3ebdSchin return(np);
259*b30d1939SAndy Fiddaman
260*b30d1939SAndy Fiddaman shp = sp->shp;
261*b30d1939SAndy Fiddaman dp = shp->var_tree;
262*b30d1939SAndy Fiddaman
2637c2fbfb3SApril Chin if((ap=nv_arrayptr(np)) && (mp=nv_opensub(np)))
2647c2fbfb3SApril Chin {
2657c2fbfb3SApril Chin shp->last_root = ap->table;
2667c2fbfb3SApril Chin sh_assignok(mp,add);
2677c2fbfb3SApril Chin if(!add || array_assoc(ap))
2687c2fbfb3SApril Chin return(np);
2697c2fbfb3SApril Chin }
270*b30d1939SAndy Fiddaman for(lp=sp->svar; lp;lp = lp->next)
271da2e3ebdSchin {
272da2e3ebdSchin if(lp->node==np)
273da2e3ebdSchin return(np);
274da2e3ebdSchin }
2757c2fbfb3SApril Chin /* first two pointers use linkage from np */
2767c2fbfb3SApril Chin lp = (struct Link*)malloc(sizeof(*np)+2*sizeof(void*));
2777c2fbfb3SApril Chin memset(lp,0, sizeof(*mp)+2*sizeof(void*));
278da2e3ebdSchin lp->node = np;
2797c2fbfb3SApril Chin if(!add && nv_isvtree(np))
2807c2fbfb3SApril Chin {
2817c2fbfb3SApril Chin Namval_t fake;
2827c2fbfb3SApril Chin Dt_t *walk, *root=shp->var_tree;
2837c2fbfb3SApril Chin char *name = nv_name(np);
284*b30d1939SAndy Fiddaman size_t len = strlen(name);
2857c2fbfb3SApril Chin fake.nvname = name;
2867c2fbfb3SApril Chin mpnext = dtnext(root,&fake);
2877c2fbfb3SApril Chin dp = root->walk?root->walk:root;
2887c2fbfb3SApril Chin while(mp=mpnext)
2897c2fbfb3SApril Chin {
2907c2fbfb3SApril Chin walk = root->walk?root->walk:root;
2917c2fbfb3SApril Chin mpnext = dtnext(root,mp);
2927c2fbfb3SApril Chin if(memcmp(name,mp->nvname,len) || mp->nvname[len]!='.')
2937c2fbfb3SApril Chin break;
2947c2fbfb3SApril Chin nv_delete(mp,walk,NV_NOFREE);
2957c2fbfb3SApril Chin *((Namval_t**)mp) = lp->child;
2967c2fbfb3SApril Chin lp->child = mp;
2977c2fbfb3SApril Chin
2987c2fbfb3SApril Chin }
2997c2fbfb3SApril Chin }
3007c2fbfb3SApril Chin lp->dict = dp;
3017c2fbfb3SApril Chin mp = (Namval_t*)&lp->dict;
302da2e3ebdSchin lp->next = subshell_data->svar;
303da2e3ebdSchin subshell_data->svar = lp;
3047c2fbfb3SApril Chin save = shp->subshell;
3057c2fbfb3SApril Chin shp->subshell = 0;
3067c2fbfb3SApril Chin mp->nvname = np->nvname;
307*b30d1939SAndy Fiddaman if(nv_isattr(np,NV_NOFREE))
308*b30d1939SAndy Fiddaman nv_onattr(mp,NV_IDENT);
3097c2fbfb3SApril Chin nv_clone(np,mp,(add?(nv_isnull(np)?0:NV_NOFREE)|NV_ARRAY:NV_MOVE));
3107c2fbfb3SApril Chin shp->subshell = save;
311da2e3ebdSchin return(np);
312da2e3ebdSchin }
313da2e3ebdSchin
314da2e3ebdSchin /*
315da2e3ebdSchin * restore the variables
316da2e3ebdSchin */
nv_restore(struct subshell * sp)317da2e3ebdSchin static void nv_restore(struct subshell *sp)
318da2e3ebdSchin {
319da2e3ebdSchin register struct Link *lp, *lq;
320da2e3ebdSchin register Namval_t *mp, *np;
321da2e3ebdSchin const char *save = sp->shpwd;
3227c2fbfb3SApril Chin Namval_t *mpnext;
323*b30d1939SAndy Fiddaman int flags,nofree;
324da2e3ebdSchin sp->shpwd = 0; /* make sure sh_assignok doesn't save with nv_unset() */
325da2e3ebdSchin for(lp=sp->svar; lp; lp=lq)
326da2e3ebdSchin {
3277c2fbfb3SApril Chin np = (Namval_t*)&lp->dict;
328da2e3ebdSchin lq = lp->next;
3297c2fbfb3SApril Chin mp = lp->node;
3307c2fbfb3SApril Chin if(!mp->nvname)
3317c2fbfb3SApril Chin continue;
332*b30d1939SAndy Fiddaman flags = 0;
333*b30d1939SAndy Fiddaman if(nv_isattr(mp,NV_MINIMAL) && !nv_isattr(np,NV_EXPORT))
334*b30d1939SAndy Fiddaman flags |= NV_MINIMAL;
335da2e3ebdSchin if(nv_isarray(mp))
336da2e3ebdSchin nv_putsub(mp,NIL(char*),ARRAY_SCAN);
337*b30d1939SAndy Fiddaman nofree = mp->nvfun?mp->nvfun->nofree:0;
33834f9b3eeSRoland Mainz _nv_unset(mp,NV_RDONLY|NV_CLONE);
3397c2fbfb3SApril Chin if(nv_isarray(np))
3407c2fbfb3SApril Chin {
3417c2fbfb3SApril Chin nv_clone(np,mp,NV_MOVE);
3427c2fbfb3SApril Chin goto skip;
3437c2fbfb3SApril Chin }
344da2e3ebdSchin nv_setsize(mp,nv_size(np));
345*b30d1939SAndy Fiddaman if(!(flags&NV_MINIMAL))
346da2e3ebdSchin mp->nvenv = np->nvenv;
347*b30d1939SAndy Fiddaman if(!nofree)
348*b30d1939SAndy Fiddaman mp->nvfun = np->nvfun;
349*b30d1939SAndy Fiddaman if(nv_isattr(np,NV_IDENT))
35034f9b3eeSRoland Mainz {
351*b30d1939SAndy Fiddaman nv_offattr(np,NV_IDENT);
352*b30d1939SAndy Fiddaman flags |= NV_NOFREE;
35334f9b3eeSRoland Mainz }
354*b30d1939SAndy Fiddaman mp->nvflag = np->nvflag|(flags&NV_MINIMAL);
355*b30d1939SAndy Fiddaman if(nv_cover(mp))
356*b30d1939SAndy Fiddaman nv_putval(mp, nv_getval(np),np->nvflag|NV_NOFREE|NV_RDONLY);
357da2e3ebdSchin else
358da2e3ebdSchin mp->nvalue.cp = np->nvalue.cp;
359*b30d1939SAndy Fiddaman if(nofree && np->nvfun && !np->nvfun->nofree)
360*b30d1939SAndy Fiddaman free((char*)np->nvfun);
361da2e3ebdSchin np->nvfun = 0;
362da2e3ebdSchin if(nv_isattr(mp,NV_EXPORT))
363da2e3ebdSchin {
364da2e3ebdSchin char *name = nv_name(mp);
365*b30d1939SAndy Fiddaman sh_envput(sp->shp->env,mp);
366da2e3ebdSchin if(*name=='_' && strcmp(name,"_AST_FEATURES")==0)
367da2e3ebdSchin astconf(NiL, NiL, NiL);
368da2e3ebdSchin }
369da2e3ebdSchin else if(nv_isattr(np,NV_EXPORT))
370*b30d1939SAndy Fiddaman env_delete(sp->shp->env,nv_name(mp));
371*b30d1939SAndy Fiddaman nv_onattr(mp,flags);
3727c2fbfb3SApril Chin skip:
3737c2fbfb3SApril Chin for(mp=lp->child; mp; mp=mpnext)
3747c2fbfb3SApril Chin {
3757c2fbfb3SApril Chin mpnext = *((Namval_t**)mp);
3767c2fbfb3SApril Chin dtinsert(lp->dict,mp);
3777c2fbfb3SApril Chin }
3787c2fbfb3SApril Chin free((void*)lp);
3797c2fbfb3SApril Chin sp->svar = lq;
380da2e3ebdSchin }
381da2e3ebdSchin sp->shpwd=save;
382da2e3ebdSchin }
383da2e3ebdSchin
384da2e3ebdSchin /*
385da2e3ebdSchin * return pointer to alias tree
386da2e3ebdSchin * create new one if in a subshell and one doesn't exist and create is non-zero
387da2e3ebdSchin */
sh_subaliastree(int create)388da2e3ebdSchin Dt_t *sh_subaliastree(int create)
389da2e3ebdSchin {
390da2e3ebdSchin register struct subshell *sp = subshell_data;
391*b30d1939SAndy Fiddaman if(!sp || sp->shp->curenv==0)
392da2e3ebdSchin return(sh.alias_tree);
393da2e3ebdSchin if(!sp->salias && create)
394da2e3ebdSchin {
395da2e3ebdSchin sp->salias = dtopen(&_Nvdisc,Dtoset);
396*b30d1939SAndy Fiddaman dtview(sp->salias,sp->shp->alias_tree);
397*b30d1939SAndy Fiddaman sp->shp->alias_tree = sp->salias;
398da2e3ebdSchin }
399da2e3ebdSchin return(sp->salias);
400da2e3ebdSchin }
401da2e3ebdSchin
402da2e3ebdSchin /*
403da2e3ebdSchin * return pointer to function tree
404da2e3ebdSchin * create new one if in a subshell and one doesn't exist and create is non-zero
405da2e3ebdSchin */
sh_subfuntree(int create)406da2e3ebdSchin Dt_t *sh_subfuntree(int create)
407da2e3ebdSchin {
408da2e3ebdSchin register struct subshell *sp = subshell_data;
409*b30d1939SAndy Fiddaman if(!sp || sp->shp->curenv==0)
410da2e3ebdSchin return(sh.fun_tree);
411da2e3ebdSchin if(!sp->sfun && create)
412da2e3ebdSchin {
413da2e3ebdSchin sp->sfun = dtopen(&_Nvdisc,Dtoset);
414*b30d1939SAndy Fiddaman dtview(sp->sfun,sp->shp->fun_tree);
415*b30d1939SAndy Fiddaman sp->shp->fun_tree = sp->sfun;
416da2e3ebdSchin }
417*b30d1939SAndy Fiddaman return(sp->shp->fun_tree);
418da2e3ebdSchin }
419da2e3ebdSchin
table_unset(register Dt_t * root,int fun)4207c2fbfb3SApril Chin static void table_unset(register Dt_t *root,int fun)
421da2e3ebdSchin {
422da2e3ebdSchin register Namval_t *np,*nq;
4237c2fbfb3SApril Chin int flag;
424da2e3ebdSchin for(np=(Namval_t*)dtfirst(root);np;np=nq)
425da2e3ebdSchin {
426da2e3ebdSchin nq = (Namval_t*)dtnext(root,np);
4277c2fbfb3SApril Chin flag=0;
42834f9b3eeSRoland Mainz if(fun && np->nvalue.rp && np->nvalue.rp->fname && *np->nvalue.rp->fname=='/')
4297c2fbfb3SApril Chin {
4307c2fbfb3SApril Chin np->nvalue.rp->fdict = 0;
4317c2fbfb3SApril Chin flag = NV_NOFREE;
4327c2fbfb3SApril Chin }
4337c2fbfb3SApril Chin else
4347c2fbfb3SApril Chin _nv_unset(np,NV_RDONLY);
4357c2fbfb3SApril Chin nv_delete(np,root,flag|NV_FUNCTION);
436da2e3ebdSchin }
437da2e3ebdSchin }
438da2e3ebdSchin
sh_subsavefd(register int fd)439da2e3ebdSchin int sh_subsavefd(register int fd)
440da2e3ebdSchin {
441da2e3ebdSchin register struct subshell *sp = subshell_data;
442da2e3ebdSchin register int old=0;
443da2e3ebdSchin if(sp)
444da2e3ebdSchin {
445da2e3ebdSchin old = !(sp->fdsaved&(1<<(fd-1)));
446da2e3ebdSchin sp->fdsaved |= (1<<(fd-1));
447da2e3ebdSchin }
448da2e3ebdSchin return(old);
449da2e3ebdSchin }
450da2e3ebdSchin
sh_subjobcheck(pid_t pid)4517c2fbfb3SApril Chin void sh_subjobcheck(pid_t pid)
4527c2fbfb3SApril Chin {
4537c2fbfb3SApril Chin register struct subshell *sp = subshell_data;
4547c2fbfb3SApril Chin while(sp)
4557c2fbfb3SApril Chin {
4567c2fbfb3SApril Chin if(sp->cpid==pid)
4577c2fbfb3SApril Chin {
4587c2fbfb3SApril Chin sh_close(sp->coutpipe);
4597c2fbfb3SApril Chin sh_close(sp->cpipe);
4607c2fbfb3SApril Chin sp->coutpipe = sp->cpipe = -1;
4617c2fbfb3SApril Chin return;
4627c2fbfb3SApril Chin }
4637c2fbfb3SApril Chin sp = sp->prev;
4647c2fbfb3SApril Chin }
4657c2fbfb3SApril Chin }
4667c2fbfb3SApril Chin
467da2e3ebdSchin /*
468da2e3ebdSchin * Run command tree <t> in a virtual sub-shell
469da2e3ebdSchin * If comsub is not null, then output will be placed in temp file (or buffer)
470da2e3ebdSchin * If comsub is not null, the return value will be a stream consisting of
471da2e3ebdSchin * output of command <t>. Otherwise, NULL will be returned.
472da2e3ebdSchin */
473da2e3ebdSchin
sh_subshell(Shell_t * shp,Shnode_t * t,volatile int flags,int comsub)474*b30d1939SAndy Fiddaman Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
475da2e3ebdSchin {
476da2e3ebdSchin struct subshell sub_data;
477da2e3ebdSchin register struct subshell *sp = &sub_data;
47834f9b3eeSRoland Mainz int jmpval,nsig=0,duped=0;
479da2e3ebdSchin int savecurenv = shp->curenv;
4807c2fbfb3SApril Chin int savejobpgid = job.curpgid;
481*b30d1939SAndy Fiddaman int *saveexitval = job.exitval;
482da2e3ebdSchin int16_t subshell;
483da2e3ebdSchin char *savsig;
484da2e3ebdSchin Sfio_t *iop=0;
485da2e3ebdSchin struct checkpt buff;
486da2e3ebdSchin struct sh_scoped savst;
487da2e3ebdSchin struct dolnod *argsav=0;
488*b30d1939SAndy Fiddaman int argcnt;
489da2e3ebdSchin memset((char*)sp, 0, sizeof(*sp));
490da2e3ebdSchin sfsync(shp->outpool);
491*b30d1939SAndy Fiddaman sh_sigcheck(shp);
492*b30d1939SAndy Fiddaman shp->savesig = -1;
493*b30d1939SAndy Fiddaman if(argsav = sh_arguse(shp))
494*b30d1939SAndy Fiddaman argcnt = argsav->dolrefcnt;
495da2e3ebdSchin if(shp->curenv==0)
496da2e3ebdSchin {
497da2e3ebdSchin subshell_data=0;
498da2e3ebdSchin subenv = 0;
499da2e3ebdSchin }
500da2e3ebdSchin shp->curenv = ++subenv;
501da2e3ebdSchin savst = shp->st;
502*b30d1939SAndy Fiddaman sh_pushcontext(shp,&buff,SH_JMPSUB);
503da2e3ebdSchin subshell = shp->subshell+1;
5047c2fbfb3SApril Chin SH_SUBSHELLNOD->nvalue.s = subshell;
505da2e3ebdSchin shp->subshell = subshell;
506da2e3ebdSchin sp->prev = subshell_data;
5077c2fbfb3SApril Chin sp->shp = shp;
5087c2fbfb3SApril Chin sp->sig = 0;
509da2e3ebdSchin subshell_data = sp;
510da2e3ebdSchin sp->errcontext = &buff.err;
511da2e3ebdSchin sp->var = shp->var_tree;
512da2e3ebdSchin sp->options = shp->options;
513da2e3ebdSchin sp->jobs = job_subsave();
514*b30d1939SAndy Fiddaman sp->subdup = shp->subdup;
515*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
516*b30d1939SAndy Fiddaman sp->coshell = shp->coshell;
517*b30d1939SAndy Fiddaman shp->coshell = 0;
518*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
519da2e3ebdSchin /* make sure initialization has occurred */
520da2e3ebdSchin if(!shp->pathlist)
521*b30d1939SAndy Fiddaman {
522*b30d1939SAndy Fiddaman shp->pathinit = 1;
523*b30d1939SAndy Fiddaman path_get(shp,".");
524*b30d1939SAndy Fiddaman shp->pathinit = 0;
525*b30d1939SAndy Fiddaman }
526da2e3ebdSchin sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
527*b30d1939SAndy Fiddaman sp->pwdfd = -1;
528da2e3ebdSchin if(!shp->pwd)
529*b30d1939SAndy Fiddaman path_pwd(shp,0);
530da2e3ebdSchin sp->bckpid = shp->bckpid;
5317c2fbfb3SApril Chin if(comsub)
5327c2fbfb3SApril Chin sh_stats(STAT_COMSUB);
533*b30d1939SAndy Fiddaman else
534*b30d1939SAndy Fiddaman job.curpgid = 0;
53581af778eSCasper H.S. Dik sp->subshare = shp->subshare;
536*b30d1939SAndy Fiddaman sp->comsub = shp->comsub;
53781af778eSCasper H.S. Dik shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
538*b30d1939SAndy Fiddaman if(comsub)
539*b30d1939SAndy Fiddaman shp->comsub = comsub;
54081af778eSCasper H.S. Dik if(!comsub || !shp->subshare)
541da2e3ebdSchin {
542*b30d1939SAndy Fiddaman struct subshell *xp;
543da2e3ebdSchin sp->shpwd = shp->pwd;
544*b30d1939SAndy Fiddaman #ifdef _lib_fchdir
545*b30d1939SAndy Fiddaman for(xp=sp->prev; xp; xp=xp->prev)
546*b30d1939SAndy Fiddaman {
547*b30d1939SAndy Fiddaman if(xp->pwdfd>0 && strcmp(xp->pwd,shp->pwd)==0)
548*b30d1939SAndy Fiddaman {
549*b30d1939SAndy Fiddaman sp->pwdfd = xp->pwdfd;
550*b30d1939SAndy Fiddaman break;
551*b30d1939SAndy Fiddaman }
552*b30d1939SAndy Fiddaman }
553*b30d1939SAndy Fiddaman if(sp->pwdfd<0)
554*b30d1939SAndy Fiddaman {
555*b30d1939SAndy Fiddaman int n = open(".",O_RDONLY);
556*b30d1939SAndy Fiddaman if(O_SEARCH && errno==EACCES)
557*b30d1939SAndy Fiddaman n = open(".",O_RDONLY);
558*b30d1939SAndy Fiddaman if(n>=0)
559*b30d1939SAndy Fiddaman {
560*b30d1939SAndy Fiddaman sp->pwdfd = n;
561*b30d1939SAndy Fiddaman if(n<10)
562*b30d1939SAndy Fiddaman {
563*b30d1939SAndy Fiddaman sp->pwdfd = fcntl(n,F_DUPFD,10);
564*b30d1939SAndy Fiddaman close(n);
565*b30d1939SAndy Fiddaman }
566*b30d1939SAndy Fiddaman if(sp->pwdfd>0)
567*b30d1939SAndy Fiddaman {
568*b30d1939SAndy Fiddaman fcntl(sp->pwdfd,F_SETFD,FD_CLOEXEC);
569*b30d1939SAndy Fiddaman sp->pwdclose = 1;
570*b30d1939SAndy Fiddaman }
571*b30d1939SAndy Fiddaman }
572*b30d1939SAndy Fiddaman }
573*b30d1939SAndy Fiddaman #endif
574da2e3ebdSchin sp->pwd = (shp->pwd?strdup(shp->pwd):0);
575da2e3ebdSchin sp->mask = shp->mask;
5767c2fbfb3SApril Chin sh_stats(STAT_SUBSHELL);
577da2e3ebdSchin /* save trap table */
578da2e3ebdSchin shp->st.otrapcom = 0;
579*b30d1939SAndy Fiddaman shp->st.otrap = savst.trap;
580da2e3ebdSchin if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
581da2e3ebdSchin {
582da2e3ebdSchin nsig += sizeof(char*);
583da2e3ebdSchin memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
584da2e3ebdSchin /* this nonsense needed for $(trap) */
585da2e3ebdSchin shp->st.otrapcom = (char**)savsig;
586da2e3ebdSchin }
5877c2fbfb3SApril Chin sp->cpid = shp->cpid;
5887c2fbfb3SApril Chin sp->coutpipe = shp->coutpipe;
5897c2fbfb3SApril Chin sp->cpipe = shp->cpipe[1];
5907c2fbfb3SApril Chin shp->cpid = 0;
591da2e3ebdSchin sh_sigreset(0);
592da2e3ebdSchin }
593da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
594da2e3ebdSchin if(jmpval==0)
595da2e3ebdSchin {
596da2e3ebdSchin if(comsub)
597da2e3ebdSchin {
598da2e3ebdSchin /* disable job control */
5997c2fbfb3SApril Chin shp->spid = 0;
600da2e3ebdSchin sp->jobcontrol = job.jobcontrol;
601da2e3ebdSchin sp->monitor = (sh_isstate(SH_MONITOR)!=0);
602da2e3ebdSchin job.jobcontrol=0;
603da2e3ebdSchin sh_offstate(SH_MONITOR);
604da2e3ebdSchin sp->pipe = sp;
605da2e3ebdSchin /* save sfstdout and status */
606da2e3ebdSchin sp->saveout = sfswap(sfstdout,NIL(Sfio_t*));
607da2e3ebdSchin sp->fdstatus = shp->fdstatus[1];
608da2e3ebdSchin sp->tmpfd = -1;
609da2e3ebdSchin sp->pipefd = -1;
610da2e3ebdSchin /* use sftmp() file for standard output */
611da2e3ebdSchin if(!(iop = sftmp(PIPE_BUF)))
612da2e3ebdSchin {
613da2e3ebdSchin sfswap(sp->saveout,sfstdout);
614da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
615da2e3ebdSchin }
616da2e3ebdSchin sfswap(iop,sfstdout);
617da2e3ebdSchin sfset(sfstdout,SF_READ,0);
618da2e3ebdSchin shp->fdstatus[1] = IOWRITE;
6197c2fbfb3SApril Chin if(!(sp->nofork = sh_state(SH_NOFORK)))
6207c2fbfb3SApril Chin sh_onstate(SH_NOFORK);
6217c2fbfb3SApril Chin flags |= sh_state(SH_NOFORK);
622da2e3ebdSchin }
623da2e3ebdSchin else if(sp->prev)
624da2e3ebdSchin {
625da2e3ebdSchin sp->pipe = sp->prev->pipe;
626da2e3ebdSchin flags &= ~sh_state(SH_NOFORK);
627da2e3ebdSchin }
628*b30d1939SAndy Fiddaman if(shp->savesig < 0)
629*b30d1939SAndy Fiddaman {
630*b30d1939SAndy Fiddaman shp->savesig = 0;
631*b30d1939SAndy Fiddaman sh_exec(t,flags);
632*b30d1939SAndy Fiddaman }
633da2e3ebdSchin }
6347c2fbfb3SApril Chin if(comsub!=2 && jmpval!=SH_JMPSUB && shp->st.trapcom[0] && shp->subshell)
635da2e3ebdSchin {
636da2e3ebdSchin /* trap on EXIT not handled by child */
637da2e3ebdSchin char *trap=shp->st.trapcom[0];
638da2e3ebdSchin shp->st.trapcom[0] = 0; /* prevent recursion */
639da2e3ebdSchin shp->oldexit = shp->exitval;
640da2e3ebdSchin sh_trap(trap,0);
641da2e3ebdSchin free(trap);
642da2e3ebdSchin }
643*b30d1939SAndy Fiddaman sh_popcontext(shp,&buff);
644da2e3ebdSchin if(shp->subshell==0) /* must be child process */
645da2e3ebdSchin {
646da2e3ebdSchin subshell_data = sp->prev;
647da2e3ebdSchin if(jmpval==SH_JMPSCRIPT)
648da2e3ebdSchin siglongjmp(*shp->jmplist,jmpval);
64934f9b3eeSRoland Mainz shp->exitval &= SH_EXITMASK;
6507c2fbfb3SApril Chin sh_done(shp,0);
651da2e3ebdSchin }
652*b30d1939SAndy Fiddaman if(!shp->savesig)
653*b30d1939SAndy Fiddaman shp->savesig = -1;
654*b30d1939SAndy Fiddaman nv_restore(sp);
655da2e3ebdSchin if(comsub)
656da2e3ebdSchin {
657da2e3ebdSchin /* re-enable job control */
6587c2fbfb3SApril Chin if(!sp->nofork)
6597c2fbfb3SApril Chin sh_offstate(SH_NOFORK);
660da2e3ebdSchin job.jobcontrol = sp->jobcontrol;
661da2e3ebdSchin if(sp->monitor)
662da2e3ebdSchin sh_onstate(SH_MONITOR);
663da2e3ebdSchin if(sp->pipefd>=0)
664da2e3ebdSchin {
665da2e3ebdSchin /* sftmp() file has been returned into pipe */
6667c2fbfb3SApril Chin iop = sh_iostream(shp,sp->pipefd);
667da2e3ebdSchin sfclose(sfstdout);
668da2e3ebdSchin }
669da2e3ebdSchin else
670da2e3ebdSchin {
671da2e3ebdSchin /* move tmp file to iop and restore sfstdout */
672da2e3ebdSchin iop = sfswap(sfstdout,NIL(Sfio_t*));
673da2e3ebdSchin if(!iop)
674da2e3ebdSchin {
675da2e3ebdSchin /* maybe locked try again */
676da2e3ebdSchin sfclrlock(sfstdout);
677da2e3ebdSchin iop = sfswap(sfstdout,NIL(Sfio_t*));
678da2e3ebdSchin }
679da2e3ebdSchin if(iop && sffileno(iop)==1)
680da2e3ebdSchin {
681*b30d1939SAndy Fiddaman int fd=sfsetfd(iop,sh_get_unused_fd(shp, 3));
682da2e3ebdSchin if(fd<0)
68334f9b3eeSRoland Mainz {
68434f9b3eeSRoland Mainz shp->toomany = 1;
68534f9b3eeSRoland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
686da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),e_toomany);
68734f9b3eeSRoland Mainz }
688*b30d1939SAndy Fiddaman VALIDATE_FD(shp, fd);
689da2e3ebdSchin shp->sftable[fd] = iop;
690da2e3ebdSchin fcntl(fd,F_SETFD,FD_CLOEXEC);
691da2e3ebdSchin shp->fdstatus[fd] = (shp->fdstatus[1]|IOCLEX);
692da2e3ebdSchin shp->fdstatus[1] = IOCLOSE;
693da2e3ebdSchin }
694da2e3ebdSchin sfset(iop,SF_READ,1);
695da2e3ebdSchin }
696da2e3ebdSchin sfswap(sp->saveout,sfstdout);
697da2e3ebdSchin /* check if standard output was preserved */
698da2e3ebdSchin if(sp->tmpfd>=0)
699da2e3ebdSchin {
700da2e3ebdSchin close(1);
70134f9b3eeSRoland Mainz if (fcntl(sp->tmpfd,F_DUPFD,1) != 1)
70234f9b3eeSRoland Mainz duped++;
703da2e3ebdSchin sh_close(sp->tmpfd);
704da2e3ebdSchin }
705da2e3ebdSchin shp->fdstatus[1] = sp->fdstatus;
706da2e3ebdSchin }
707da2e3ebdSchin path_delete((Pathcomp_t*)shp->pathlist);
708da2e3ebdSchin shp->pathlist = (void*)sp->pathlist;
709da2e3ebdSchin job_subrestore(sp->jobs);
710da2e3ebdSchin shp->jobenv = savecurenv;
7117c2fbfb3SApril Chin job.curpgid = savejobpgid;
712*b30d1939SAndy Fiddaman job.exitval = saveexitval;
713da2e3ebdSchin shp->bckpid = sp->bckpid;
714da2e3ebdSchin if(sp->shpwd) /* restore environment if saved */
715da2e3ebdSchin {
7167c2fbfb3SApril Chin int n;
717da2e3ebdSchin shp->options = sp->options;
718da2e3ebdSchin if(sp->salias)
719da2e3ebdSchin {
720da2e3ebdSchin shp->alias_tree = dtview(sp->salias,0);
7217c2fbfb3SApril Chin table_unset(sp->salias,0);
722da2e3ebdSchin dtclose(sp->salias);
723da2e3ebdSchin }
724da2e3ebdSchin if(sp->sfun)
725da2e3ebdSchin {
726da2e3ebdSchin shp->fun_tree = dtview(sp->sfun,0);
7277c2fbfb3SApril Chin table_unset(sp->sfun,1);
728da2e3ebdSchin dtclose(sp->sfun);
729da2e3ebdSchin }
7307c2fbfb3SApril Chin n = shp->st.trapmax-savst.trapmax;
731da2e3ebdSchin sh_sigreset(1);
7327c2fbfb3SApril Chin if(n>0)
7337c2fbfb3SApril Chin memset(&shp->st.trapcom[savst.trapmax],0,n*sizeof(char*));
734da2e3ebdSchin shp->st = savst;
735da2e3ebdSchin shp->curenv = savecurenv;
736*b30d1939SAndy Fiddaman shp->st.otrap = 0;
737da2e3ebdSchin if(nsig)
738da2e3ebdSchin {
739da2e3ebdSchin memcpy((char*)&shp->st.trapcom[0],savsig,nsig);
740da2e3ebdSchin free((void*)savsig);
741da2e3ebdSchin }
742da2e3ebdSchin shp->options = sp->options;
743da2e3ebdSchin if(!shp->pwd || strcmp(sp->pwd,shp->pwd))
744da2e3ebdSchin {
745da2e3ebdSchin /* restore PWDNOD */
7467c2fbfb3SApril Chin Namval_t *pwdnod = sh_scoped(shp,PWDNOD);
747da2e3ebdSchin if(shp->pwd)
748da2e3ebdSchin {
749*b30d1939SAndy Fiddaman if(sp->pwdfd >=0)
750*b30d1939SAndy Fiddaman {
751*b30d1939SAndy Fiddaman if(fchdir(sp->pwdfd)<0)
752*b30d1939SAndy Fiddaman chdir(sp->pwd);
753*b30d1939SAndy Fiddaman }
754*b30d1939SAndy Fiddaman else
755*b30d1939SAndy Fiddaman chdir(sp->pwd);
756*b30d1939SAndy Fiddaman shp->pwd=sp->pwd;
757*b30d1939SAndy Fiddaman path_newdir(shp,shp->pathlist);
758da2e3ebdSchin }
759da2e3ebdSchin if(nv_isattr(pwdnod,NV_NOFREE))
760da2e3ebdSchin pwdnod->nvalue.cp = (const char*)sp->pwd;
761da2e3ebdSchin }
762da2e3ebdSchin else if(sp->shpwd != shp->pwd)
763da2e3ebdSchin {
764da2e3ebdSchin shp->pwd = sp->pwd;
765da2e3ebdSchin if(PWDNOD->nvalue.cp==sp->shpwd)
766da2e3ebdSchin PWDNOD->nvalue.cp = sp->pwd;
767da2e3ebdSchin }
768da2e3ebdSchin else
769da2e3ebdSchin free((void*)sp->pwd);
770*b30d1939SAndy Fiddaman if(sp->pwdclose)
771*b30d1939SAndy Fiddaman close(sp->pwdfd);
772da2e3ebdSchin if(sp->mask!=shp->mask)
7737c2fbfb3SApril Chin umask(shp->mask=sp->mask);
77434f9b3eeSRoland Mainz if(shp->coutpipe!=sp->coutpipe)
7757c2fbfb3SApril Chin {
7767c2fbfb3SApril Chin sh_close(shp->coutpipe);
7777c2fbfb3SApril Chin sh_close(shp->cpipe[1]);
7787c2fbfb3SApril Chin }
7797c2fbfb3SApril Chin shp->cpid = sp->cpid;
7807c2fbfb3SApril Chin shp->cpipe[1] = sp->cpipe;
7817c2fbfb3SApril Chin shp->coutpipe = sp->coutpipe;
782da2e3ebdSchin }
78381af778eSCasper H.S. Dik shp->subshare = sp->subshare;
784*b30d1939SAndy Fiddaman shp->comsub = sp->comsub;
785*b30d1939SAndy Fiddaman shp->subdup = sp->subdup;
786*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
787*b30d1939SAndy Fiddaman shp->coshell = sp->coshell;
788*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
7897c2fbfb3SApril Chin if(shp->subshell)
7907c2fbfb3SApril Chin SH_SUBSHELLNOD->nvalue.s = --shp->subshell;
79134f9b3eeSRoland Mainz subshell = shp->subshell;
79234f9b3eeSRoland Mainz subshell_data = sp->prev;
793*b30d1939SAndy Fiddaman if(!argsav || argsav->dolrefcnt==argcnt)
794*b30d1939SAndy Fiddaman sh_argfree(shp,argsav,0);
79534f9b3eeSRoland Mainz if(shp->topfd != buff.topfd)
79634f9b3eeSRoland Mainz sh_iorestore(shp,buff.topfd|IOSUBSHELL,jmpval);
7977c2fbfb3SApril Chin if(sp->sig)
7987c2fbfb3SApril Chin {
7997c2fbfb3SApril Chin if(sp->prev)
8007c2fbfb3SApril Chin sp->prev->sig = sp->sig;
8017c2fbfb3SApril Chin else
8027c2fbfb3SApril Chin {
803*b30d1939SAndy Fiddaman kill(getpid(),sp->sig);
804*b30d1939SAndy Fiddaman sh_chktrap(shp);
8057c2fbfb3SApril Chin }
8067c2fbfb3SApril Chin }
807*b30d1939SAndy Fiddaman sh_sigcheck(shp);
808da2e3ebdSchin shp->trapnote = 0;
809*b30d1939SAndy Fiddaman nsig = shp->savesig;
810*b30d1939SAndy Fiddaman shp->savesig = 0;
811*b30d1939SAndy Fiddaman if(nsig>0)
812*b30d1939SAndy Fiddaman kill(getpid(),nsig);
813*b30d1939SAndy Fiddaman if(sp->subpid)
81434f9b3eeSRoland Mainz job_wait(sp->subpid);
815*b30d1939SAndy Fiddaman if(comsub && iop && sp->pipefd<0)
816*b30d1939SAndy Fiddaman sfseek(iop,(off_t)0,SEEK_SET);
817*b30d1939SAndy Fiddaman if(shp->trapnote)
818*b30d1939SAndy Fiddaman sh_chktrap(shp);
819da2e3ebdSchin if(shp->exitval > SH_EXITSIG)
820da2e3ebdSchin {
821da2e3ebdSchin int sig = shp->exitval&SH_EXITMASK;
822da2e3ebdSchin if(sig==SIGINT || sig== SIGQUIT)
823*b30d1939SAndy Fiddaman kill(getpid(),sig);
824da2e3ebdSchin }
82534f9b3eeSRoland Mainz if(duped)
82634f9b3eeSRoland Mainz {
82734f9b3eeSRoland Mainz ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
82834f9b3eeSRoland Mainz shp->toomany = 1;
82934f9b3eeSRoland Mainz errormsg(SH_DICT,ERROR_system(1),e_redirect);
83034f9b3eeSRoland Mainz }
831*b30d1939SAndy Fiddaman if(shp->ignsig)
832*b30d1939SAndy Fiddaman kill(getpid(),shp->ignsig);
833*b30d1939SAndy Fiddaman if(jmpval==SH_JMPSUB && shp->lastsig)
834*b30d1939SAndy Fiddaman kill(getpid(),shp->lastsig);
83534f9b3eeSRoland Mainz if(jmpval && shp->toomany)
83634f9b3eeSRoland Mainz siglongjmp(*shp->jmplist,jmpval);
837da2e3ebdSchin return(iop);
838da2e3ebdSchin }
839