Skip to content

Commit

Permalink
Fix process substitution combined with redirection
Browse files Browse the repository at this point in the history
The code for handling process substitution with redirection was
never being run because IORAW is usually set when IOPROCSUB is
set. This commit fixes the problem by moving the required code
out of the !IORAW if statement. The following command now prints
'good' instead of writing 'ok' to a bizzare file:

$ ksh -c 'echo ok > >(sed s/ok/good/); wait'
good

This commit also fixes a bug that caused the process ID of the
asynchronous process to print when the shell was in interactive
mode. The following command no longer prints a process ID,
behaving like in Bash and zsh:

$ echo >(/bin/true)
/dev/fd/5

src/cmd/ksh93/sh/args.c:
 - Temporarily turn off the interactive state while in a process
   substitution to prevent the shell from printing the PID of
   the asynchronous process.

src/cmd/ksh93/sh/io.c:
 - Move the code for process substitution with redirection into
   a separate if statement.

src/cmd/ksh93/tests/basic.sh:
 - Add two tests for both process substitution bugs fixed by this
   commit.

Fixes ksh93#2
  • Loading branch information
JohnoKing committed Jun 23, 2020
1 parent 1463236 commit 829cd42
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 15 deletions.
8 changes: 8 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ For full details, see the git log at: https://github.com/ksh93/ksh

Any uppercase BUG_* names are modernish shell bug IDs.

2020-06-23:

- Fixed a bug that caused combining process substitution with redirection
to create a bizarre file in the user's current working directory.

- Using process substitution while the shell is interactive no longer
causes the process ID of the asynchronous process to be printed.

2020-06-22:

- The 'stop' and 'suspend' default aliases have been converted into regular
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#define SH_RELEASE "93u+m 2020-06-22"
#define SH_RELEASE "93u+m 2020-06-23"
12 changes: 11 additions & 1 deletion src/cmd/ksh93/sh/args.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
{
/* argument of the form <(cmd) or >(cmd) */
register struct argnod *ap;
int monitor, fd, pv[3];
int monitor, interactive, fd, pv[3];
int subshell = shp->subshell;
ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
ap->argflag |= ARG_MAKE;
Expand All @@ -805,8 +805,14 @@ struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
ap = (struct argnod*)stkfreeze(shp->stk,0);
shp->inpipe = shp->outpipe = 0;

/* turn off job control */
if(interactive = (sh_isstate(SH_INTERACTIVE)!=0))
sh_offstate(SH_INTERACTIVE);
if(monitor = (sh_isstate(SH_MONITOR)!=0))
sh_offstate(SH_MONITOR);

/* do the process substitution */
shp->subshell = 0;
if(fd)
{
Expand All @@ -818,9 +824,13 @@ struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
shp->outpipe = pv;
sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
}

/* restore the previous state */
shp->subshell = subshell;
if(monitor)
sh_onstate(SH_MONITOR);
if(interactive)
sh_onstate(SH_INTERACTIVE);
#if SHOPT_DEVFD
close(pv[1-fd]);
sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
Expand Down
26 changes: 13 additions & 13 deletions src/cmd/ksh93/sh/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1182,21 +1182,21 @@ int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
strcpy(ap->argval,iop->ioname);
fname=sh_macpat(shp,ap,(iof&IOARITH)?ARG_ARITH:ARG_EXP);
}
else if(iof&IOPROCSUB)
{
struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
memset(ap, 0, ARGVAL);
if(iof&IOPUT)
ap->argflag = ARG_RAW;
else if(shp->subshell)
sh_subtmpfile(shp);
ap->argchn.ap = (struct argnod*)fname;
ap = sh_argprocsub(shp,ap);
fname = ap->argval;
}
else
else if(!(iof&IOPROCSUB))
fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
}
if((iof&IOPROCSUB) && !(iof&IOLSEEK))
{
struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
memset(ap, 0, ARGVAL);
if(iof&IOPUT)
ap->argflag = ARG_RAW;
else if(shp->subshell)
sh_subtmpfile(shp);
ap->argchn.ap = (struct argnod*)fname;
ap = sh_argprocsub(shp,ap);
fname = ap->argval;
}
errno=0;
np = 0;
#if SHOPT_COSHELL
Expand Down
16 changes: 16 additions & 0 deletions src/cmd/ksh93/tests/basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,20 @@ $SHELL -xc '$(LD_LIBRARY_PATH=$LD_LIBRARY_PATH exec $SHELL -c :)' > /dev/null 2>
$SHELL 2> /dev/null -c $'for i;\ndo :;done' || err_exit 'for i ; <newline> not vaid'
# ======
# Process substitution should work when combined with redirection. The
# `cd $tmp` is because in many versions of ksh the test creates a bizarre
# file that isn't easy to delete individually.
cd $tmp
result="$($SHELL -c 'echo ok > >(sed s/ok/good/); wait')"
[[ $result == good ]] || err_exit 'process substitution does not work with redirections'
cd - >> /dev/null
# ======
# Process substitution in an interactive shell shouldn't print the
# process ID of the asynchronous process.
result="$($SHELL -ic 'echo >(/bin/true) >> /dev/null' 2>&1)"
[[ $result == $(echo) ]] || err_exit 'interactive shells print a PID during process substitution'
# ======
exit $((Errors<125?Errors:125))

0 comments on commit 829cd42

Please sign in to comment.