From 0390b4354a9e5df517ef2d4f9d78a099063b22b4 Mon Sep 17 00:00:00 2001 From: Chet Ramey 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