diff --git a/src/cmd/ksh93/include/io.h b/src/cmd/ksh93/include/io.h index 5e4058e4e..eca543aba 100644 --- a/src/cmd/ksh93/include/io.h +++ b/src/cmd/ksh93/include/io.h @@ -79,6 +79,7 @@ extern Sfio_t *sh_iostream(Shell_t*,int); extern int sh_redirect(Shell_t*,struct ionod*,int); extern void sh_iosave(Shell_t *, int,int,char*); extern int sh_iovalidfd(Shell_t*, int); +extern int sh_iosafefd(Shell_t*, int); extern int sh_inuse(Shell_t*, int); extern void sh_iounsave(Shell_t*); extern void sh_iounpipe(Shell_t*); diff --git a/src/cmd/ksh93/sh/io.c b/src/cmd/ksh93/sh/io.c index 63e2af26d..6636e027f 100644 --- a/src/cmd/ksh93/sh/io.c +++ b/src/cmd/ksh93/sh/io.c @@ -436,6 +436,24 @@ int sh_iovalidfd(Shell_t *shp, int fd) return(1); } +int sh_iosafefd(Shell_t* shp, int sfd) +{ + register int fd; + while(1) + { + for(fd=0; fd < shp->topfd; fd++) + { + if (filemap[fd].save_fd==sfd || filemap[fd].orig_fd==sfd || (fcntl(sfd, F_GETFD) != -1 || errno != EBADF)) + { + sfd++; + continue; + } + } + break; + } + return(sfd); +} + int sh_inuse(Shell_t *shp, int fd) { return(fd < shp->gd->lim.open_max && shp->fdptrs[fd]); diff --git a/src/cmd/ksh93/sh/subshell.c b/src/cmd/ksh93/sh/subshell.c index 64d1100f8..4ba0a5e48 100644 --- a/src/cmd/ksh93/sh/subshell.c +++ b/src/cmd/ksh93/sh/subshell.c @@ -679,7 +679,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub) } if(iop && sffileno(iop)==1) { - int fd=sfsetfd(iop,3); + int fd = sfsetfd(iop,sh_iosafefd(shp,3)); if(fd<0) { shp->toomany = 1; diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index c62295f45..539ee9020 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -830,5 +830,22 @@ sleep_pid=$! ((!(e = $?))) || err_exit "backtick comsub with pipe hangs (got status $e$( ((e>128)) && print -n / && kill -l "$e"))" kill "$sleep_pid" 2>/dev/null +# ====== +# https://bugzilla.redhat.com/1116072 + +expect='return-value' +function get_value +{ + /dev/null/foo 2>/dev/null # trigger part 1: external command (even nonexistent) + exec 3>&- # trigger part 2: close file descriptor 3 + print return-value # with the bug, the comsub won't output this +} +actual=$(get_value) +[[ $actual == "$expect" ]] || err_exit "\$(Comsub) failed to return output (expected '$expect', got '$actual')" +actual=${ get_value; } +[[ $actual == "$expect" ]] || err_exit "\${ Comsub; } failed to return output (expected '$expect', got '$actual')" +actual=`get_value` +[[ $actual == "$expect" ]] || err_exit "\`Comsub\` failed to return output (expected '$expect', got '$actual')" + # ====== exit $((Errors<125?Errors:125))