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