From 0390b4354a9e5df517ef2d4f9d78a099063b22b4 Mon Sep 17 00:00:00 2001
From: Chet Ramey <chet.ramey@case.edu>
Date: Tue, 28 Jan 2025 10:15:16 -0500
Subject: [PATCH] posix change for undoing redirections after failed exec;
 change readline to set lines and columns after SIGTSTP/SIGCONT

Conflict:only the modified content of builtins/exec.def and execute_cmd.c is rounded.

---
 builtins/exec.def | 11 +++++-----
 execute_cmd.c     | 56 +++++++++++++++++++++++++++++++----------------
 2 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/builtins/exec.def b/builtins/exec.def
index cbcb641..ee4921f 100644
--- a/builtins/exec.def
+++ b/builtins/exec.def
@@ -129,12 +129,13 @@ exec_builtin (list)
     }
   list = loptend;
 
-  /* First, let the redirections remain. */
-  dispose_redirects (redirection_undo_list);
-  redirection_undo_list = (REDIRECT *)NULL;
-
+  /* First, let the redirections remain if exec is called without operands */
   if (list == 0)
-    return (EXECUTION_SUCCESS);
+    {
+      dispose_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+      return (EXECUTION_SUCCESS);
+    }
 
 #if defined (RESTRICTED_SHELL)
   if (restricted)
diff --git a/execute_cmd.c b/execute_cmd.c
index 9adb9cb..82ad27d 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -5292,7 +5292,7 @@ execute_builtin_or_function (words, builtin, var, redirects,
      struct fd_bitmap *fds_to_close;
      int flags;
 {
-  int result;
+  int result, has_exec_redirects;
   REDIRECT *saved_undo_list;
 #if defined (PROCESS_SUBSTITUTION)
   int ofifo, nfifo, osize;
@@ -5319,17 +5319,25 @@ execute_builtin_or_function (words, builtin, var, redirects,
       return (EX_REDIRFAIL);	/* was EXECUTION_FAILURE */
     }
 
+  /* Is this the exec builtin with redirections? We want to undo them and
+     throw away the exec_redirection_undo_list if exec has a program name
+     argument, fails to execute it, and does not exit the shell */
+  has_exec_redirects = (builtin == exec_builtin) && redirection_undo_list;
+
   saved_undo_list = redirection_undo_list;
 
   /* Calling the "exec" builtin changes redirections forever. */
   if (builtin == exec_builtin)
     {
-      dispose_redirects (saved_undo_list);
+      /* let exec_builtin handle disposing redirection_undo_list */
       saved_undo_list = exec_redirection_undo_list;
       exec_redirection_undo_list = (REDIRECT *)NULL;
     }
   else
-    dispose_exec_redirects ();
+    {
+      dispose_exec_redirects ();
+      redirection_undo_list = (REDIRECT *)NULL;
+    }
 
   if (saved_undo_list)
     {
@@ -5337,8 +5345,6 @@ execute_builtin_or_function (words, builtin, var, redirects,
       add_unwind_protect (cleanup_redirects, (char *)saved_undo_list);
     }
 
-  redirection_undo_list = (REDIRECT *)NULL;
-
   if (builtin)
     result = execute_builtin (builtin, words, flags, 0);
   else
@@ -5350,26 +5356,38 @@ execute_builtin_or_function (words, builtin, var, redirects,
   if (ferror (stdout))
     clearerr (stdout);  
 
-  /* If we are executing the `command' builtin, but this_shell_builtin is
-     set to `exec_builtin', we know that we have something like
-     `command exec [redirection]', since otherwise `exec' would have
-     overwritten the shell and we wouldn't get here.  In this case, we
-     want to behave as if the `command' builtin had not been specified
-     and preserve the redirections. */
-  if (builtin == command_builtin && this_shell_builtin == exec_builtin)
+  if (has_exec_redirects && redirection_undo_list)
     {
-      int discard;
-
-      discard = 0;
+      /* We have returned from the exec builtin. If redirection_undo_list is
+	 still non-null, we had an operand and failed to exit the shell for
+	 some reason. We want to dispose of saved_undo_list, discard the frame,
+	 and let the redirections be undone as usual. If redirection_undo_list
+	 is NULL, then exec_builtin had no program name operand and disposed
+	 of it. In that case, we should perform the redirections in
+	 exec_redirection_undo_list (saved_undo_list) like usual. */
+      if (saved_undo_list)
+        {
+	  dispose_redirects (saved_undo_list);	/* exec_redirection_undo_list */
+	  discard_unwind_frame ("saved-redirects");
+        }
+      saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;      
+    }
+  /* This code is no longer executed and remains only for explanatory reasons. */
+  else if (builtin == command_builtin && this_shell_builtin == exec_builtin)
+    {
+      /* If we are executing the `command' builtin, but this_shell_builtin is
+	 set to `exec_builtin', we know that we have something like
+	 `command exec [redirection]', since otherwise `exec' would have
+	 overwritten the shell and we wouldn't get here. In this case, we
+	 want to behave as if the `command' builtin had not been specified
+	 and preserve the redirections. */
       if (saved_undo_list)
 	{
-	  dispose_redirects (saved_undo_list);
-	  discard = 1;
+	  dispose_redirects (saved_undo_list);	/* redirection_undo_list */
+	  discard_unwind_frame ("saved-redirects");
 	}
       redirection_undo_list = exec_redirection_undo_list;
       saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;      
-      if (discard)
-	discard_unwind_frame ("saved-redirects");
     }
 
   if (saved_undo_list)
-- 
2.33.0

