--- execute_cmd.c
+++ execute_cmd.c	2010-09-28 14:44:54.948426641 +0000
@@ -119,7 +119,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 *));
@@ -400,12 +400,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
@@ -618,7 +619,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);
@@ -2667,7 +2668,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)
     {
@@ -2709,10 +2710,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);
@@ -3516,7 +3517,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 */
@@ -3575,8 +3576,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);
--- redir.c
+++ redir.c	2005-01-28 14:22:22.000000000 +0000
@@ -169,12 +169,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)
@@ -190,14 +191,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
@@ -765,6 +773,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;
 
 	  if ((fd != redirector) && (dup2 (fd, redirector) < 0))
 	    return (errno);
@@ -844,6 +854,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;
@@ -886,6 +899,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);
