From 6fb61ee126cf5ffdcbff9ae51345838dc21d935e Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 6 May 2024 11:25:35 -0400 Subject: [PATCH] allow some job notifications while running $PROMPT_COMMAND; allow notifications while running bind -x commands; change some translated messages to be more uniform --- CWRU/CWRU.chlog | 43 +++++++++++++++++++++++++++++++++++++++++++ Makefile.in | 2 +- bashline.c | 5 +++-- builtins/common.h | 1 + builtins/evalfile.c | 6 +++--- builtins/evalstring.c | 6 ++++++ eval.c | 7 +++++++ execute_cmd.c | 6 +++--- jobs.c | 6 +++++- jobs.h | 1 + nojobs.c | 3 +++ parse.y | 10 +++++----- shell.c | 2 +- trap.c | 18 ++++++++++++++---- unwind_prot.c | 4 ++-- 15 files changed, 98 insertions(+), 22 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index c4cb5621..29791610 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9327,3 +9327,46 @@ jobs.c jobs.h - LONGEST_SIGNAL_DESC: update to 27 (macos SIGPROF). This changes the test output + + 5/3 + --- +builtins/common.h + - SEVAL_NOTIFY: new flag for parse_and_execute; means we want job + notifications even though we're not interactive at this time and + would not satisfy the conditions + +builtins/evalstring.c + - parse_prologue: if SEVAL_NOTIFY is supplied, unwind-protect + want_job_notifications and set it to 1 + +jobs.c,jobs.h.nojobs.c + - want_job_notifications: new global variable, initialized to 0 + +jobs.c + - notify_and_cleanup: notify about dead jobs if want_job_notifications + is non-zero + +parse.y + - execute_variable_command: call parse_and_execute with the SEVAL_NOTIFY + flag + +eval.c + - reader_loop: call notify_and_cleanup before executing $PROMPT_COMMAND + if the shell is interactive and prompting + +trap.c + - run_pending_traps,_run_trap_internal,run_exit_trap: add SEVAL_NOTIFY + to the flags for parse_and_execute if the shell is interactive + +bashline.c + - bash_execute_unix_command: add SEVAL_NOTIFY to the flags for + parse_and_execute if the shell is interactive + Rest of fix for report by Koichi Murase + on 11/14/2022 + + 5/6 + --- + +execute_cmd.c,shell.c,builtins/evalfile.c,unwind_prot.c + - change some translated error messages to make the text more uniform + and reduce the number of gettext() calls diff --git a/Makefile.in b/Makefile.in index 8d9ffe19..51c55bf9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1103,7 +1103,7 @@ eval.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h $ eval.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h -eval.o: input.h execute_cmd.h +eval.o: input.h execute_cmd.h jobs.h eval.o: $(BASHINCDIR)/unlocked-io.h eval.o: bashhist.h assoc.h ${BASHINCDIR}/ocache.h ${BASHINCDIR}/chartypes.h execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h diff --git a/bashline.c b/bashline.c index 9df37a0e..b638e001 100644 --- a/bashline.c +++ b/bashline.c @@ -4545,7 +4545,7 @@ uw_unbind_readline_variables (void *ignore) int bash_execute_unix_command (int count, int key) { - int type; + int type, pflags; register int i, r; intmax_t mi; sh_parser_state_t ps; @@ -4627,7 +4627,8 @@ bash_execute_unix_command (int count, int key) add_unwind_protect (uw_unbind_readline_variables, 0); add_unwind_protect (uw_restore_parser_state, &ps); add_unwind_protect (uw_rl_set_signals, 0); - r = parse_and_execute (savestring (cmd), "bash_execute_unix_command", SEVAL_NOHIST); + pflags = interactive_shell ? (SEVAL_NOTIFY|SEVAL_NOHIST) : SEVAL_NOHIST; + r = parse_and_execute (savestring (cmd), "bash_execute_unix_command", pflags); rl_set_signals (); restore_parser_state (&ps); diff --git a/builtins/common.h b/builtins/common.h index 81ce259d..41437a33 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -52,6 +52,7 @@ do { \ #define SEVAL_ONECMD 0x100 /* only allow a single command */ #define SEVAL_NOHISTEXP 0x200 /* inhibit history expansion */ #define SEVAL_NOOPTIMIZE 0x400 /* don't try to set optimization flags */ +#define SEVAL_NOTIFY 0x800 /* want job notifications */ /* Flags for describe_command, shared between type.def and command.def */ #define CDESC_ALL 0x001 /* type -a */ diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 17a568a0..14a8488c 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -1,6 +1,6 @@ /* evalfile.c - read and evaluate commands from a file or file descriptor */ -/* Copyright (C) 1996-2017,2022-2023 Free Software Foundation, Inc. +/* Copyright (C) 1996-2017,2022-2024 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -185,7 +185,7 @@ file_error_and_exit: check_binary_file (string, (nr > 80) ? 80 : nr)) { free (string); - (*errfunc) (_("%s: cannot execute binary file"), filename); + (*errfunc) ("%s: %s", filename, _("cannot execute binary file")); return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1); } @@ -203,7 +203,7 @@ file_error_and_exit: if ((flags & FEVAL_BUILTIN) && ++nnull > 256) { free (string); - (*errfunc) (_("%s: cannot execute binary file"), filename); + (*errfunc) ("%s: %s", filename, _("cannot execute binary file")); return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1); } } diff --git a/builtins/evalstring.c b/builtins/evalstring.c index fedacdfc..eaa87d3d 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -247,6 +247,8 @@ parse_prologue (char *string, int flags, char *tag) unwind_protect_int (builtin_ignoring_errexit); if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) unwind_protect_int (interactive); + if (flags & SEVAL_NOTIFY) + unwind_protect_int (want_job_notifications); #if defined (HISTORY) if (parse_and_execute_level == 0) @@ -281,6 +283,9 @@ parse_prologue (char *string, int flags, char *tag) if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) interactive = (flags & SEVAL_NONINT) ? 0 : 1; + if (flags & SEVAL_NOTIFY) + want_job_notifications = 1; + #if defined (HISTORY) if (flags & SEVAL_NOHIST) bash_history_disable (); @@ -302,6 +307,7 @@ parse_prologue (char *string, int flags, char *tag) (flags & SEVAL_RESETLINE) -> reset line_number to 1 (flags & SEVAL_NOHISTEXP) -> history_expansion_inhibited -> 1 (flags & SEVAL_NOOPTIMIZE) -> don't try to turn on optimizing flags + (flags & SEVAL_NOTIFY) -> print job status notifications */ int diff --git a/eval.c b/eval.c index cbf408f0..c8f11163 100644 --- a/eval.c +++ b/eval.c @@ -48,6 +48,10 @@ # include "bashhist.h" #endif +#if defined (JOB_CONTROL) +# include "jobs.h" +#endif + static void send_pwd_to_eterm (void); static sighandler alrm_catcher (int); @@ -343,6 +347,9 @@ parse_command (void) actually printed. */ if (interactive && bash_input.type != st_string && parser_expanding_alias() == 0) { +#if defined (JOB_CONTROL) + notify_and_cleanup (); +#endif #if defined (READLINE) if (no_line_editing || (bash_input.type == st_stdin && parser_will_prompt ())) #endif diff --git a/execute_cmd.c b/execute_cmd.c index 5a9477a4..8a5e43c3 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -6081,7 +6081,7 @@ shell_execve (char *command, char **args, char **env) last_command_exit_value = (i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC; /* XXX Posix.2 says that exit status is 126 */ if (file_isdir (command)) #if defined (EISDIR) - internal_error (_("%s: %s"), command, strerror (EISDIR)); + internal_error ("%s: %s", command, strerror (EISDIR)); #else internal_error (_("%s: is a directory"), command); #endif @@ -6119,7 +6119,7 @@ shell_execve (char *command, char **args, char **env) interp[ilen] = 'M'; interp[ilen + 1] = '\0'; } - sys_error (_("%s: %s: bad interpreter"), command, interp); + sys_error ("%s: %s: %s", command, interp, _("bad interpreter")); FREE (interp); return (EX_NOEXEC); } @@ -6165,7 +6165,7 @@ shell_execve (char *command, char **args, char **env) #endif if (check_binary_file (sample, sample_len)) { - internal_error (_("%s: cannot execute binary file: %s"), command, strerror (i)); + internal_error ("%s: %s: %s", command, _("cannot execute binary file"), strerror (i)); errno = i; return (EX_BINARY_FILE); } diff --git a/jobs.c b/jobs.c index c0c9cb2b..63082cfe 100644 --- a/jobs.c +++ b/jobs.c @@ -231,6 +231,10 @@ int check_window_size = CHECKWINSIZE_DEFAULT; PROCESS *last_procsub_child = (PROCESS *)NULL; +/* Set to non-zero if you want to force job notifications even in contexts + where the shell would defer them. */ +int want_job_notifications = 0; + /* Functions local to this file. */ void debug_print_pgrps (void); @@ -3423,7 +3427,7 @@ notify_and_cleanup (void) if (jobs_list_frozen > 0) return; - if (interactive || interactive_shell == 0 || sourcelevel || (interactive_shell && running_trap)) + if (want_job_notifications || interactive || interactive_shell == 0 || sourcelevel) notify_of_job_status (); if (jobs_list_frozen < 0) diff --git a/jobs.h b/jobs.h index 31c4fd32..3711af20 100644 --- a/jobs.h +++ b/jobs.h @@ -222,6 +222,7 @@ extern struct jobstats js; extern pid_t original_pgrp, shell_pgrp, pipeline_pgrp; extern volatile pid_t last_made_pid, last_asynchronous_pid; extern int asynchronous_notification; +extern int want_job_notifications; extern int already_making_children; extern int running_in_background; diff --git a/nojobs.c b/nojobs.c index c429b6e3..3b32d12f 100644 --- a/nojobs.c +++ b/nojobs.c @@ -93,6 +93,9 @@ int check_window_size = CHECKWINSIZE_DEFAULT; /* We don't have job control. */ int job_control = 0; +/* and don't want job notifications */ +int want_job_notifications = 0; + int running_in_background = 0; /* can't tell without job control */ /* STATUS and FLAGS are only valid if pid != NO_PID diff --git a/parse.y b/parse.y index b347fbb5..d232481d 100644 --- a/parse.y +++ b/parse.y @@ -2461,10 +2461,10 @@ shell_getc (int remove_quoted_newline) if (interactive_shell == 0 || SHOULD_PROMPT()) { #if defined (JOB_CONTROL) - /* This can cause a problem when reading a command as the result - of a trap, when the trap is called from flush_child. This call - had better not cause jobs to disappear from the job table in - that case, or we will have big trouble. */ + /* This can cause a problem when reading a command as the result + of a trap, when the trap is called from flush_child. This call + had better not cause jobs to disappear from the job table in + that case, or we will have big trouble. */ notify_and_cleanup (); #else /* !JOB_CONTROL */ cleanup_dead_jobs (); @@ -2951,7 +2951,7 @@ execute_variable_command (const char *command, const char *vname) save_parser_state (&ps); last_lastarg = save_lastarg (); - parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE); + parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE|SEVAL_NOTIFY); restore_parser_state (&ps); bind_lastarg (last_lastarg); diff --git a/shell.c b/shell.c index 84ac5c4e..15e005d6 100644 --- a/shell.c +++ b/shell.c @@ -1685,7 +1685,7 @@ open_shell_script (char *script_name) } else if (sample_len > 0 && (check_binary_file (sample, sample_len))) { - internal_error (_("%s: cannot execute binary file"), filename); + internal_error ("%s: %s", filename, _("cannot execute binary file")); #if defined (JOB_CONTROL) end_job_control (); /* just in case we were run as bash -i script */ #endif diff --git a/trap.c b/trap.c index d2879136..9acd1973 100644 --- a/trap.c +++ b/trap.c @@ -483,8 +483,13 @@ run_pending_traps (void) } if (function_code == 0) - /* XXX is x always last_command_exit_value? */ - x = parse_and_execute (trap_command, "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE); + { + int pflags; + pflags = interactive_shell ? SEVAL_NOTIFY : 0; + pflags |= SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE; + /* XXX is x always last_command_exit_value? */ + x = parse_and_execute (trap_command, "trap", pflags); + } else { parse_and_execute_cleanup (sig + 1); /* XXX - could use -1 */ @@ -1049,8 +1054,11 @@ run_exit_trap (void) if (code == 0 && function_code == 0) { + int pflags; + pflags = interactive_shell ? SEVAL_NOTIFY : 0; + pflags |= SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE; reset_parser (); - parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE); + parse_and_execute (trap_command, "exit trap", pflags); } else if (code == ERREXIT) retval = last_command_exit_value; @@ -1172,7 +1180,9 @@ _run_trap_internal (int sig, char *tag) function_code = setjmp_nosigs (return_catch); } - flags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE; + /* XXX - reconsider this for DEBUG_TRAP, RETURN_TRAP, ERROR_TRAP? */ + flags = interactive_shell ? SEVAL_NOTIFY : 0; + flags |= SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE; if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP) flags |= SEVAL_RESETLINE; if (function_code == 0) diff --git a/unwind_prot.c b/unwind_prot.c index 4a5195a6..fbf5c85f 100644 --- a/unwind_prot.c +++ b/unwind_prot.c @@ -243,7 +243,7 @@ unwind_frame_discard_internal (char *tag) } if (found == 0) - internal_warning (_("unwind_frame_discard: %s: frame not found"), tag); + internal_warning ("unwind_frame_discard: %s: %s", tag, _("frame not found")); } /* Restore the value of a variable, based on the contents of SV. @@ -289,7 +289,7 @@ unwind_frame_run_internal (char *tag) uwpfree (elt); } if (tag && found == 0) - internal_warning (_("unwind_frame_run: %s: frame not found"), tag); + internal_warning ("unwind_frame_run: %s: %s", tag, _("frame not found")); } static void -- 2.47.2