diff -up ksh-20100621/src/cmd/ksh93/include/io.h.macrob ksh-20100621/src/cmd/ksh93/include/io.h --- ksh-20100621/src/cmd/ksh93/include/io.h.macrob 2013-05-14 18:23:05.703939025 +0200 +++ ksh-20100621/src/cmd/ksh93/include/io.h 2013-05-14 18:23:05.718939148 +0200 @@ -68,6 +68,7 @@ extern void sh_ioinit(Shell_t*); extern int sh_iomovefd(int); extern int sh_iorenumber(Shell_t*,int,int); extern void sh_pclose(int[]); +extern int sh_rpipe(int[]); extern void sh_iorestore(Shell_t*,int,int); #if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell) __EXPORT__ @@ -78,6 +79,7 @@ extern void sh_iosave(Shell_t *, int,in extern int sh_iovalidfd(Shell_t*, int); extern int sh_inuse(int); extern void sh_iounsave(Shell_t*); +extern void iounpipe(Shell_t*); extern int sh_chkopen(const char*); extern int sh_ioaccess(int,int); extern int sh_devtofd(const char*); diff -up ksh-20100621/src/cmd/ksh93/sh/io.c.macrob ksh-20100621/src/cmd/ksh93/sh/io.c --- ksh-20100621/src/cmd/ksh93/sh/io.c.macrob 2013-05-14 18:23:05.704939033 +0200 +++ ksh-20100621/src/cmd/ksh93/sh/io.c 2013-05-14 18:23:05.719939157 +0200 @@ -858,18 +858,43 @@ int sh_iomovefd(register int fdold) */ int sh_pipe(register int pv[]) { + Shell_t *shp = sh_getinterp(); int fd[2]; if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0) errormsg(SH_DICT,ERROR_system(1),e_pipe); pv[0] = sh_iomovefd(pv[0]); pv[1] = sh_iomovefd(pv[1]); - sh.fdstatus[pv[0]] = IONOSEEK|IOREAD; - sh.fdstatus[pv[1]] = IONOSEEK|IOWRITE; + shp->fdstatus[pv[0]] = IONOSEEK|IOREAD; + shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE; sh_subsavefd(pv[0]); sh_subsavefd(pv[1]); return(0); } +#ifndef pipe + int sh_rpipe(register int pv[]) + { + return sh_pipe(pv); + } +#else +# undef pipe + /* create a real pipe when pipe() is socketpair */ + int sh_rpipe(register int pv[]) + { + Shell_t *shp = sh_getinterp(); + int fd[2]; + if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0) + errormsg(SH_DICT,ERROR_system(1),e_pipe); + pv[0] = sh_iomovefd(pv[0]); + pv[1] = sh_iomovefd(pv[1]); + shp->fdstatus[pv[0]] = IONOSEEK|IOREAD; + shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE; + sh_subsavefd(pv[0]); + sh_subsavefd(pv[1]); + return(0); + } +#endif + static int pat_seek(void *handle, const char *str, size_t sz) { char **bp = (char**)handle; diff -up ksh-20100621/src/cmd/ksh93/sh/subshell.c.macrob ksh-20100621/src/cmd/ksh93/sh/subshell.c --- ksh-20100621/src/cmd/ksh93/sh/subshell.c.macrob 2013-05-14 18:23:05.715939124 +0200 +++ ksh-20100621/src/cmd/ksh93/sh/subshell.c 2013-05-14 18:23:05.719939157 +0200 @@ -165,7 +165,7 @@ void sh_subfork(void) { register struct subshell *sp = subshell_data; Shell_t *shp = sp->shp; - int curenv = shp->curenv; + int curenv = shp->curenv, comsub=shp->comsub; pid_t pid; char *trap = shp->st.trapcom[0]; if(trap) @@ -174,6 +174,7 @@ void sh_subfork(void) if(sp->pipe) sh_subtmpfile(shp); shp->curenv = 0; + shp->savesig = -1; if(pid = sh_fork(FSHOWME,NIL(int*))) { shp->curenv = curenv; @@ -197,7 +198,8 @@ void sh_subfork(void) shp->comsub = 0; SH_SUBSHELLNOD->nvalue.s = 0; sp->subpid=0; - shp->st.trapcom[0] = trap; + shp->st.trapcom[0] = (comsub==2?NULL:trap); + shp->savesig = 0; } } @@ -696,7 +698,6 @@ Sfio_t *sh_subshell(Shnode_t *t, int fla shp->coutpipe = sp->coutpipe; } shp->subshare = sp->subshare; - shp->comsub = sp->comsub; shp->subdup = sp->subdup; if(shp->subshell) SH_SUBSHELLNOD->nvalue.s = --shp->subshell; @@ -717,10 +718,21 @@ Sfio_t *sh_subshell(Shnode_t *t, int fla } sh_sigcheck(); shp->trapnote = 0; + nsig = shp->savesig; + shp->savesig = 0; + if(nsig>0) + sh_fault(nsig); if(sp->subpid) + { job_wait(sp->subpid); + if(comsub>1) + iounpipe(shp); + } + shp->comsub = sp->comsub; if(comsub && iop && sp->pipefd<0) sfseek(iop,(off_t)0,SEEK_SET); + if(shp->trapnote) + sh_chktrap(); if(shp->exitval > SH_EXITSIG) { int sig = shp->exitval&SH_EXITMASK; diff -up ksh-20100621/src/cmd/ksh93/sh/xec.c.macrob ksh-20100621/src/cmd/ksh93/sh/xec.c --- ksh-20100621/src/cmd/ksh93/sh/xec.c.macrob 2013-05-14 18:23:05.716939132 +0200 +++ ksh-20100621/src/cmd/ksh93/sh/xec.c 2013-05-14 18:23:28.089123586 +0200 @@ -84,18 +84,32 @@ struct funenv * to use a pipe and to wait for the pipe to close before restoring to a * temp file. */ -static int subpipe[3] = {-1}; -static int subdup,tsetio; -static void iousepipe(Shell_t *shp) -{ - int i; - fcntl(subpipe[0],F_SETFD,FD_CLOEXEC); - subpipe[2] = sh_fcntl(1,F_DUPFD,10); - fcntl(subpipe[2],F_SETFD,FD_CLOEXEC); +static int subpipe[3],subdup,tsetio,usepipe; +void iounpipe(Shell_t*); + +int iousepipe(Shell_t *shp) +{ + int fd=sffileno(sfstdout),i,err=errno; + if(usepipe) + { + usepipe++; + iounpipe(shp); + } + if(sh_rpipe(subpipe) < 0) + return(0); + usepipe++; + if(shp->comsub!=1) + { + subpipe[2] = sh_fcntl(subpipe[1],F_DUPFD,10); + sh_close(subpipe[1]); + return(1); + } + subpipe[2] = sh_fcntl(fd,F_dupfd_cloexec,10); shp->fdstatus[subpipe[2]] = shp->fdstatus[1]; - close(1); - fcntl(subpipe[1],F_DUPFD,1); - shp->fdstatus[1] = shp->fdstatus[subpipe[1]]; + while(close(fd)<0 && errno==EINTR) + errno = err; + fcntl(subpipe[1],F_DUPFD,fd); + shp->fdstatus[1] = shp->fdstatus[subpipe[1]]&~IOCLEX; sh_close(subpipe[1]); if(subdup=shp->subdup) for(i=0; i < 10; i++) { @@ -106,14 +120,25 @@ static void iousepipe(Shell_t *shp) shp->fdstatus[i] = shp->fdstatus[1]; } } + return(1); } -static void iounpipe(Shell_t *shp) +void iounpipe(Shell_t *shp) { - int n; + int fd=sffileno(sfstdout),n,err=errno; char buff[SF_BUFSIZE]; - close(1); - fcntl(subpipe[2], F_DUPFD, 1); + if(!usepipe) + return; + --usepipe; + if(shp->comsub>1) + { + sh_close(subpipe[2]); + while(read(subpipe[0],buff,sizeof(buff))>0); + goto done; + } + while(close(fd)<0 && errno==EINTR) + errno = err; + fcntl(subpipe[2], F_DUPFD, fd); shp->fdstatus[1] = shp->fdstatus[subpipe[2]]; if(subdup) for(n=0; n < 10; n++) { @@ -126,16 +151,35 @@ static void iounpipe(Shell_t *shp) } shp->subdup = 0; sh_close(subpipe[2]); - while((n = read(subpipe[0],buff,sizeof(buff)))!=0) + if(usepipe==0) while(1) { + while(job.waitsafe && job.savesig==SIGCHLD) + { + if(!vmbusy()) + { + job.in_critical++; + job_reap(SIGCHLD); + job.in_critical--; + break; + } + sh_delay(1); + } + if((n = read(subpipe[0],buff,sizeof(buff)))==0) + break; if(n>0) sfwrite(sfstdout,buff,n); else if(errno!=EINTR) break; } +done: sh_close(subpipe[0]); subpipe[0] = -1; tsetio = 0; + if(usepipe) + { + usepipe = 0; + iousepipe(shp); + } } /* @@ -723,6 +767,7 @@ int sh_exec(register const Shnode_t *t, { register Shell_t *shp = &sh; Stk_t *stkp = shp->stk; + int unpipe=0; sh_sigcheck(); if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC)) { @@ -1256,18 +1301,20 @@ int sh_exec(register const Shnode_t *t, if(shp->subshell) { sh_subtmpfile(shp); - subpipe[0] = -1; - if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK) && sh_pipe(subpipe)>=0) - iousepipe(shp); if((type&(FAMP|TFORK))==(FAMP|TFORK)) - sh_subfork(); + { + if(shp->comsub && !(shp->fdstatus[1]&IONOSEEK)) + { + unpipe = iousepipe(shp); + sh_subfork(); + } + } } - no_fork = !ntflag && !(type&(FAMP|FPOU)) && + no_fork = !ntflag && !(type&(FAMP|FPOU)) && !shp->subshell && !(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && ((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL && - (execflg2 || (execflg && - !shp->subshell && shp->fn_depth==0 && + (execflg2 || (execflg && shp->fn_depth==0 && !(pipejob && sh_isoption(SH_PIPEFAIL)) )); if(sh_isstate(SH_PROFILE) || shp->dot_depth) @@ -1306,7 +1353,7 @@ int sh_exec(register const Shnode_t *t, parent = sh_fork(type,&jobid); if(parent<0) { - if(shp->comsub==1 && subpipe[0]>=0) + if(shp->comsub==1 && usepipe && unpipe) iounpipe(shp); break; } @@ -1323,7 +1370,7 @@ int sh_exec(register const Shnode_t *t, # endif /* _lib_fork */ if(parent<0) { - if(shp->comsub==1 && subpipe[0]>=0) + if(shp->comsub==1 && usepipe && unpipe) iounpipe(shp); break; } @@ -1360,7 +1407,7 @@ int sh_exec(register const Shnode_t *t, shp->pipepid = parent; else job_wait(parent); - if(tsetio && subdup) + if(usepipe && tsetio && subdup) iounpipe(shp); if(!sh_isoption(SH_MONITOR)) { @@ -1534,6 +1581,8 @@ int sh_exec(register const Shnode_t *t, if(type || !sh_isoption(SH_PIPEFAIL)) shp->exitval = type; } + if(shp->comsub==1 && usepipe) + iounpipe(shp); shp->pipepid = 0; shp->st.ioset = 0; if(simple && was_errexit) @@ -1598,7 +1647,11 @@ int sh_exec(register const Shnode_t *t, pid_t savepgid = job.curpgid; job.curpgid = 0; if(shp->subshell) + { sh_subtmpfile(shp); + if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK)) + iousepipe(shp); + } shp->inpipe = pvo; shp->outpipe = pvn; pvo[1] = -1; @@ -1609,15 +1662,11 @@ int sh_exec(register const Shnode_t *t, job_lock(); do { -#if SHOPT_FASTPIPE - type = pipe_exec(shp,pvn,t->lst.lstlef, errorflg); -#else /* create the pipe */ sh_pipe(pvn); /* execute out part of pipe no wait */ (t->lst.lstlef)->tre.tretyp |= showme; type = sh_exec(t->lst.lstlef, errorflg); -#endif /* SHOPT_FASTPIPE */ pipejob=1; /* save the pipe stream-ids */ pvo[0] = pvn[0]; @@ -2617,6 +2666,7 @@ pid_t _sh_fork(register pid_t parent,int if(sig>0) sh_fault(sig); sh_sigcheck(); + usepipe=0; return(0); } @@ -2643,10 +2693,13 @@ pid_t sh_fork(int flags, int *jobid) sh.savesig = -1; while(_sh_fork(parent=fork(),flags,jobid) < 0); sh_stats(STAT_FORKS); - sig = sh.savesig; - sh.savesig = 0; - if(sig>0) - sh_fault(sig); + if(!sh.subshell) + { + sig = sh.savesig; + sh.savesig = 0; + if(sig>0) + sh_fault(sig); + } job_fork(parent); return(parent); } diff -up ksh-20100621/src/lib/libast/features/fcntl.c.macrob ksh-20100621/src/lib/libast/features/fcntl.c --- ksh-20100621/src/lib/libast/features/fcntl.c.macrob 2006-10-26 19:19:10.000000000 +0200 +++ ksh-20100621/src/lib/libast/features/fcntl.c 2013-05-14 18:23:05.721939173 +0200 @@ -219,6 +219,11 @@ main() } printf("\n"); #endif +#ifdef F_DUPFD_CLOEXEC + printf("#define F_dupfd_cloexec F_DUPFD_CLOEXEC\n"); +#else + printf("#define F_dupfd_cloexec F_DUPFD\n"); +#endif #ifndef O_APPEND #define NEED_O 1 @@ -315,6 +320,11 @@ main() #ifndef O_BINARY printf("#define O_BINARY 0\n"); #endif +#ifdef O_CLOEXEC + printf("#define O_cloexec O_CLOEXEC\n"); +#else + printf("#define O_cloexec 0\n"); +#endif #ifndef O_TEMPORARY printf("#define O_TEMPORARY 0\n"); #endif