diff --git a/CHANGES-4.4 b/CHANGES-4.4 index 23c6d87c..0089937b 100644 --- a/CHANGES-4.4 +++ b/CHANGES-4.4 @@ -635,7 +635,7 @@ jj. Asynchronous commands now always set $? to 0 and are not affected by whether or not the command's exit status is being inverted. kk. Fixed a problem that caused a line ending with an escaped newline and - containingh a prior `eval' to be incorrectly parsed. + containing a prior `eval' to be incorrectly parsed. ll. Fixed an issue with programmable completion and `!' in extglob patterns used as arguments to `compgen -X'. diff --git a/CHANGES-5.1 b/CHANGES-5.1 index 327ce383..2ca791c6 100644 --- a/CHANGES-5.1 +++ b/CHANGES-5.1 @@ -503,7 +503,8 @@ j. shell-transpose-words: a new bindable readline command that uses the same k. The shell now adds default bindings for shell-forward-word, shell-backward-word, shell-transpose-words, and shell-kill-word. -l. Bash now allows ARGV0 appearing in the initial shell environment to set $0. +l. Bash now allows BASH_ARGV0 appearing in the initial shell environment to + set $0. m. If `unset' is executed without option arguments, bash tries to unset a shell function if a name argument cannot be a shell variable name because it's not diff --git a/CHANGES-5.3 b/CHANGES-5.3 index 81e0a5a4..71097a70 100644 --- a/CHANGES-5.3 +++ b/CHANGES-5.3 @@ -534,7 +534,7 @@ dddd. Work around system-specific problems (macOS) where isblank(3) returns eeee. Fix for crash while parsing alias expansions that include compound assignments. -ffff. Fixe for non-interactive shells reading a script file that ends with +ffff. Fix for non-interactive shells reading a script file that ends with backslash preceding EOF. gggg. Fix to command printing when here-documents are attached to compound diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 3189d228..904e2ded 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13430,3 +13430,38 @@ error.c the `exec' builtin, since the `execfail' shopt is supposed to inhibit this. Report from Zev Weiss + + 10/5 + ---- +parse.y + - xparse_dolparen: turn off echo_input_at_read so we don't echo lines + a second time + - shell_getc: if echo_input_at_read is on, echo input lines even if + shell_eof_token is `)' or `}'; rely on the callers to make sure it's + off if not wanted (e.g., by xparse_dolparen) + From https://savannah.gnu.org/bugs/?68735 + + 10/13 + ----- +lib/readline/input.c + - rl_getc: handle receipt of SIGTERM while waiting for input like a + SIGINT (call RL_CHECK_SIGNALS()) instead of SIGHUP. Might need to + explicitly return error/EOF if the application's signal handler is + SIG_IGN for backwards compatibility. + From a report by Denys Vlasenko + + 10/14 + ----- +stringlib.c,externs.h + - strip_trailing: LEN argument is now size_t to avoid integer overflow + on command substitution strings longer than 2GB + Report from Lilian CRIMET + + 10/22 + ----- +trap.c + - run_pending_traps, _run_trap_internal: make sure to set breaking + and continuing to 0 before running the trap action, then restore + them after the action completes. Make sure to handle the case where + the trap action runs break or continue. + From a report by Dimitrios Christou diff --git a/doc/bashref.texi b/doc/bashref.texi index 2e9abd9f..198ba2f6 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -4394,7 +4394,7 @@ exec [-cl] [-a @var{name}] [@var{command} [@var{arguments}]] If @var{command} is supplied, it replaces the shell without creating a new process. @var{command} cannot be a shell builtin or function. -The @var{arguments} become the arguments to @var{command} +The @var{arguments} become the arguments to @var{command}. If the @option{-l} option is supplied, the shell places a dash at the beginning of the zeroth argument passed to @var{command}. This is what the @code{login} program does. @@ -9202,7 +9202,6 @@ Readline, and is ignored and removed otherwise, so it shouldn't be used in @env{PS0} or @env{PS4}, or when line editing is not enabled. - @item \] End a sequence of non-printing characters begun with @samp{\[} @end table diff --git a/externs.h b/externs.h index a21b4f9d..68c1aab1 100644 --- a/externs.h +++ b/externs.h @@ -174,7 +174,7 @@ extern char *substring (const char *, size_t, size_t); extern char *strsub (const char *, const char *, const char *, int); extern char *strcreplace (const char *, int, const char *, int); extern void strip_leading (char *); -extern void strip_trailing (char *, int, int); +extern void strip_trailing (char *, size_t, int); extern int str_firstdiff (const char *, const char *); extern int str_lastsame (const char *, const char *); diff --git a/lib/readline/input.c b/lib/readline/input.c index b2072122..d22c8538 100644 --- a/lib/readline/input.c +++ b/lib/readline/input.c @@ -958,18 +958,22 @@ rl_getc (FILE *stream) /* If the error that we received was EINTR, then try again, this is simply an interrupted system call to read (). We allow the read to be interrupted if we caught SIGHUP, SIGTERM, or any - of the other signals readline treats specially. If the - application sets an event hook, call it for other signals. + of the other signals readline treats specially. SIGHUP causes an + immediate error/EOF return; the other signals call back to the + application through RL_CHECK_SIGNALS. + If the application sets an event hook, call it for other signals. Otherwise (not EINTR), some error occurred, also signifying EOF. */ if (errno != EINTR) return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); /* fatal signals of interest */ #if defined (SIGHUP) - else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM) -#else - else if (_rl_caught_signal == SIGTERM) -#endif + else if (_rl_caught_signal == SIGHUP) return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); +#endif + else if (_rl_caught_signal == SIGTERM) + /* Allow the application to handle or exit instead of error/EOF */ + RL_CHECK_SIGNALS (); + /* keyboard-generated signals of interest */ #if defined (SIGQUIT) else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT) diff --git a/parse.y b/parse.y index e094bb6e..f9026221 100644 --- a/parse.y +++ b/parse.y @@ -453,7 +453,7 @@ inputunit: simple_list simple_list_terminator | funsub { /* This is special; look at the production and how - parse_comsub/parse_valsub sets token_to_read */ + parse_comsub sets token_to_read */ global_command = $1; YYACCEPT; } @@ -2713,15 +2713,18 @@ shell_getc (int remove_quoted_newline) if (shell_input_line) { /* Lines that signify the end of the shell's input should not be - echoed. We should not echo lines while parsing command - substitutions with recursive calls into the parsing engine; those - should only be echoed once when we read the word. That is the - reason for the test against shell_eof_token, which is set to a - right paren when parsing the contents of command substitutions. */ + echoed. We should echo lines while parsing command and process + substitutions only once: the first time parse_comsub() is called. + Further calls via xparse_dolparen or during parse_and_execute + should not result in echoing input; we rely on the callers to + set echo_input_at_read appropriately. That is the reason for the + test against shell_eof_token, which is probably more elaborate + than is really necessary. */ if (echo_input_at_read && (shell_input_line[0] || (shell_input_line_terminator != EOF && shell_input_line_terminator != READERR)) && - shell_eof_token == 0) +/*(*/ (shell_eof_token == 0 || + ((parser_state & PST_EOFTOKEN) && shell_eof_token == ')' || shell_eof_token == '}'))) fprintf (stderr, "%s\n", shell_input_line); } else @@ -4766,6 +4769,10 @@ xparse_dolparen (const char *base, char *string, size_t *indp, int flags) local_extglob = extended_glob; #endif + /* We also choose not to echo input at this stage; if verbose is on, the + first call to parse_comsub should echo the input lines. */ + echo_input_at_read = 0; + if (funsub && FUNSUB_CHAR (*string) && (*string == '|' || *string == ';')) string++; @@ -4787,6 +4794,7 @@ xparse_dolparen (const char *base, char *string, size_t *indp, int flags) #if defined (EXTENDED_GLOB) extended_glob = local_extglob; #endif + echo_input_at_read = verbose_flag; token_to_read = 0; simplecmd_lineno = save_lineno; diff --git a/stringlib.c b/stringlib.c index 190f36bf..2c9f4a92 100644 --- a/stringlib.c +++ b/stringlib.c @@ -259,7 +259,7 @@ strip_leading (char *string) newlines. If NEWLINES_ONLY is non-zero, only trailing newlines are removed. STRING should be terminated with a zero. */ void -strip_trailing (char *string, int len, int newlines_only) +strip_trailing (char *string, size_t len, int newlines_only) { while (len >= 0) { diff --git a/trap.c b/trap.c index a956b3aa..be1ab9fb 100644 --- a/trap.c +++ b/trap.c @@ -332,6 +332,7 @@ run_pending_traps (void) register int sig; int x; volatile int old_exit_value, old_running, old_context; + volatile int old_breaking, old_continuing; WORD_LIST *save_subst_varlist; HASH_TABLE *save_tempenv; sh_parser_state_t pstate; @@ -485,6 +486,10 @@ run_pending_traps (void) pending_traps[sig] = 0; evalnest++; + old_breaking = breaking; + old_continuing = continuing; + breaking = continuing = 0; + function_code = 0; save_return_catch_flag = return_catch_flag; if (return_catch_flag) @@ -507,6 +512,12 @@ run_pending_traps (void) x = return_catch_value; } + /* what if the trap command runs `break' or `continue'? */ + if (breaking == 0 || old_breaking != 0) + breaking = old_breaking; + if (continuing == 0 || old_continuing != 0) + continuing = old_continuing; + evalnest--; #if defined (JOB_CONTROL) restore_pipeline (1); @@ -1074,6 +1085,7 @@ run_exit_trap (void) pflags = interactive_shell ? SEVAL_NOTIFY : 0; pflags |= SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE; reset_parser (); + breaking = continuing = 0; parse_and_execute (trap_command, "exit trap", pflags); } else if (code == ERREXIT) @@ -1133,7 +1145,9 @@ _run_trap_internal (int sig, char *tag) char *old_trapsig; int trap_exit_value; volatile int save_return_catch_flag, function_code; - int old_modes, old_running, old_int, old_context; + volatile int old_running, old_int, old_context; + volatile int old_breaking, old_continuing; + int old_modes; int flags; procenv_t save_return_catch; WORD_LIST *save_subst_varlist; @@ -1204,6 +1218,10 @@ _run_trap_internal (int sig, char *tag) /* XXX - set pending_traps[sig] = 0 here? */ evalnest++; + old_breaking = breaking; + old_continuing = continuing; + breaking = continuing = 0; + /* If we're in a function, make sure return longjmps come here, too. */ function_code = 0; save_return_catch_flag = return_catch_flag; @@ -1225,6 +1243,13 @@ _run_trap_internal (int sig, char *tag) } else trap_exit_value = return_catch_value; + + /* what if the trap command runs `break' or `continue'? */ + if (breaking == 0 || old_breaking != 0) + breaking = old_breaking; + if (continuing == 0 || old_continuing != 0) + continuing = old_continuing; + evalnest--; #if defined (JOB_CONTROL)