Skip to content

Commit

Permalink
Don't persist redirs when failing to exec a program (re: 53937b9)
Browse files Browse the repository at this point in the history
As of the referenced commit, the interactive shell no longer forces
an exit upon 'exec program' when 'program' cannot be executed. This
is good. However, any redirections to 'program' then persist in the
current interactive shell environment, which is wrong and harmful.
Further discussion: https://austingroupbugs.net/view.php?id=1896

src/cmd/ksh93/sh/xec.c: sh_exec(): case TCOM:
- Upon processing redirections for 'exec', when the shell is
  interactive (which excludes subshells of interactive shells) and
  at least one non-redirection operand was passed to 'exec', pass a
  type/flag argument of 0 to sh_redirect (in io.c) instead of 1;
  this makes sh_redirect save the FD state for later restoraton in
  case exec fails.
- Mildly refactor this whole code block for legibility. Get rid of
  opaque arithmetic with boolean 0/1 results.
- For normal command redirections, simplify the exec optimisation
  for redirections: remove checks for virtual subshell and EXIT
  trap after checking for nonzero execflg. These became redundant
  since execflg is set to 0 if check_exec_optimization returns
  false on lines 1108 and 1109. (re: b0a6c1b, 88aa369)
  • Loading branch information
McDutchie committed Dec 19, 2024
1 parent 53937b9 commit c431140
Showing 1 changed file with 17 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/cmd/ksh93/sh/xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,19 +1216,31 @@ int sh_exec(const Shnode_t *t, int flags)
if(io)
{
struct openlist *item;
/* Below, 'type' is the type flag for sh_redirect; see there for info */
if(np == SYSEXEC) /* 'exec' */
type = 1 + !com[1];
else if(np == SYSREDIR) /* 'redirect' */
if(!com[1])
type = 2;
{
/* Interactive shells no longer force an exit on failure to exec,
* so if there is a program to 'exec', save the file descriptor
* state (type==0) on interactive shells in case path_exec fails */
if(com[1])
type = sh_isstate(SH_INTERACTIVE) ? 0 : 1;
else
type = 2; /* no operand: mark FD > 2 close-on-exec */
}
else if(np == SYSREDIR) /* 'redirect' */
{
if(com[1]) /* do not allow operands */
{
errormsg(SH_DICT, ERROR_exit(2), "%s: %s: %s",
SYSREDIR->nvname, e_badsyntax, com[1]);
UNREACHABLE();
}
type = 2;
}
else if(execflg)
type = 1; /* don't bother to save redirection state */
else
type = (execflg && !sh.subshell && !sh.st.trapcom[0]);
type = 0; /* normal non-persistent redirection */
sh.redir0 = 1;
sh_redirect(io,type);
for(item=buffp->olist;item;item=item->next)
Expand Down

0 comments on commit c431140

Please sign in to comment.