Index: redir.c =================================================================== --- redir.c.orig +++ redir.c @@ -176,12 +176,13 @@ redirection_error (temp, error) how to undo the redirections later, if non-zero. If flags & RX_CLEXEC is non-zero, file descriptors opened in do_redirection () have their close-on-exec flag set. */ +static int close_before_dup2_err; int do_redirections (list, flags) REDIRECT *list; int flags; { - int error; + int error, ret = 0; REDIRECT *temp; if (flags & RX_UNDOABLE) @@ -197,14 +198,21 @@ do_redirections (list, flags) for (temp = list; temp; temp = temp->next) { + close_before_dup2_err = 0; error = do_redirection_internal (temp, flags); if (error) { redirection_error (temp, error); return (error); } + if (close_before_dup2_err) + { + redirection_error (temp, close_before_dup2_err); + ret = close_before_dup2_err; + } } - return (0); + + return (ret); } /* Return non-zero if the redirection pointed to by REDIRECT has a @@ -786,6 +794,8 @@ do_redirection_internal (redirect, flags #if defined (BUFFERED_INPUT) check_bash_input (redirector); #endif + if ((fd != redirector) && (close(redirector) < 0) && (errno != EBADF)) + close_before_dup2_err = errno; /* Make sure there is no pending output before we change the state of the underlying file descriptor, since the builtins use stdio @@ -879,6 +889,9 @@ do_redirection_internal (redirect, flags #if defined (BUFFERED_INPUT) check_bash_input (redirector); #endif + if ((fd != redirector) && (close(redirector) < 0) && (errno != EBADF)) + close_before_dup2_err = errno; + if (fd != redirector && dup2 (fd, redirector) < 0) { r = errno; @@ -920,6 +933,9 @@ do_redirection_internal (redirect, flags #if defined (BUFFERED_INPUT) check_bash_input (redirector); #endif + if ((close(redirector) < 0) && (errno != EBADF)) + close_before_dup2_err = errno; + /* This is correct. 2>&1 means dup2 (1, 2); */ if (dup2 (redir_fd, redirector) < 0) return (errno); Index: execute_cmd.c =================================================================== --- execute_cmd.c.orig +++ execute_cmd.c @@ -121,7 +121,7 @@ static void close_pipes __P((int, int)); static void do_piping __P((int, int)); static void bind_lastarg __P((char *)); static int shell_control_structure __P((enum command_type)); -static void cleanup_redirects __P((REDIRECT *)); +static int cleanup_redirects __P((REDIRECT *)); #if defined (JOB_CONTROL) static int restore_signal_mask __P((sigset_t *)); @@ -417,12 +417,13 @@ shell_control_structure (type) /* A function to use to unwind_protect the redirection undo list for loops. */ -static void +static int cleanup_redirects (list) REDIRECT *list; { - do_redirections (list, RX_ACTIVE); + int ret = do_redirections (list, RX_ACTIVE); dispose_redirects (list); + return (ret ? 1 : 0); } #if 0 @@ -664,7 +665,7 @@ execute_command_internal (command, async redirection.) */ if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0) { - cleanup_redirects (redirection_undo_list); + (void)cleanup_redirects (redirection_undo_list); redirection_undo_list = (REDIRECT *)NULL; dispose_exec_redirects (); return (last_command_exit_value = EXECUTION_FAILURE); @@ -3314,7 +3315,7 @@ execute_null_command (redirects, pipe_in REDIRECT *redirects; int pipe_in, pipe_out, async; { - int r; + int r, s; if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async) { @@ -3361,10 +3362,10 @@ execute_null_command (redirects, pipe_in substitution. Otherwise, return EXECUTION_SUCCESS. */ r = do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE); - cleanup_redirects (redirection_undo_list); + s = cleanup_redirects (redirection_undo_list); redirection_undo_list = (REDIRECT *)NULL; - if (r != 0) + if (r != 0 || s != 0) return (EXECUTION_FAILURE); else if (last_command_subst_pid != NO_PID) return (last_command_exit_value); @@ -4238,7 +4239,7 @@ execute_builtin_or_function (words, buil if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0) { - cleanup_redirects (redirection_undo_list); + (void)cleanup_redirects (redirection_undo_list); redirection_undo_list = (REDIRECT *)NULL; dispose_exec_redirects (); return (EX_REDIRFAIL); /* was EXECUTION_FAILURE */ @@ -4299,8 +4300,10 @@ execute_builtin_or_function (words, buil if (redirection_undo_list) { - cleanup_redirects (redirection_undo_list); + int ret = cleanup_redirects (redirection_undo_list); redirection_undo_list = (REDIRECT *)NULL; + if (result == 0) + result = ret; } return (result);