From: Chet Ramey Date: Mon, 26 Jun 2023 21:09:08 +0000 (-0400) Subject: fix for exit builtin when ignoreeof set; better resource deallocation when completion... X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=829aad36dbbeee462fa142fe2c571fd7ab735ba8;p=thirdparty%2Fbash.git fix for exit builtin when ignoreeof set; better resource deallocation when completion is interrupted; fix small memleak in globbing; compile out obsolete readline typedefs by default; readline callback mode doesn't print signal chars by default; xtrace mode prefers to use $'...' quoting if required --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index cb9fb3327..2dfd28d1f 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -6875,4 +6875,46 @@ examples/loadables/{kv,stat}.c lib/readline/complete.c - rl_menu_complete: use _rl_free_match_list instead of just freeing MATCHES if we have too many possible completions to display. + From a report by Grisha Levit + + 6/25 + ---- +eval.c + - reader_loop: make sure to allow exit builtin (code == EXITBLTIN) to + exit the shell when ignoreeof is set + From a report by Grisha Levit + + 6/26 + ---- +lib/readline/complete.c + - complete_sigcleanarg_t: new struct to hold match list and saved line + buffer for cleanup on receipt of SIGINT + - _rl_complete_sigcleanup: use new sigcleanarg_t struct and free both + members + - rl_complete_internal: whenever we display the match list, set up to + clean the matches and saved line buffer in the event of a SIGINT + From a report by Grisha Levit + +lib/readline/signals.c + - _rl_handle_signal: if readline is compiled to include callbacks, only + call rl_echo_signal_char if we're not in callback mode or the + application has set rl_persistent_signal_handlers, leaving any + application signal handler to call it (or not) otherwise. + From a discussion with Andrew Burgess + +lib/glob/glob.c + - glob_filename: if ARRAY == TEMP_RESULTS, make sure to free TEMP_RESULTS + after copying the filenames out of ARRAY, since we either assigned it + directly or glob_dir_to_array returned it because the dirname was + the empty string. + From a report by Grisha Levit + +lib/readline/rltypedefs.h + - Function: only compile in these obsolete typedefs if + WANT_OBSOLETE_TYPEDEFS is defined + +print_cmd.c + - xtrace_print_assignment,xtrace_print_word_list: prioritize checking + for characters that need $'...' printing over shell metacharacters + so that strings containing both get the $'...' treatment From a report by Grisha Levit diff --git a/eval.c b/eval.c index 8337a275f..2f5d1fbec 100644 --- a/eval.c +++ b/eval.c @@ -183,7 +183,7 @@ reader_loop (void) current_command = (COMMAND *)NULL; } } - if (EOF_Reached && interactive && ignoreeof && parse_and_execute_level == 0) + if (EOF_Reached && interactive && ignoreeof && parse_and_execute_level == 0 && code != EXITBLTIN) { if (handle_ignoreeof (1)) EOF_Reached = 0; diff --git a/examples/loadables/getconf.c b/examples/loadables/getconf.c index 27a04dcfd..af5544f0b 100644 --- a/examples/loadables/getconf.c +++ b/examples/loadables/getconf.c @@ -274,9 +274,13 @@ static const struct conf vars[] = #ifdef _SC_AVPHYS_PAGES { "_AVPHYS_PAGES", _SC_AVPHYS_PAGES, SYSCONF }, #endif +#ifdef _NPROCESSORS_CONF { "_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF, SYSCONF }, { "_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN, SYSCONF }, +#endif +#ifdef _PHYS_PAGES { "_PHYS_PAGES", _SC_PHYS_PAGES, SYSCONF }, +#endif #ifdef _SC_ARG_MAX { "_POSIX_ARG_MAX", _SC_ARG_MAX, SYSCONF }, #else @@ -859,7 +863,9 @@ static const struct conf vars[] = { "SEM_VALUE_MAX", _SC_SEM_VALUE_MAX, SYSCONF }, #endif { "SIGQUEUE_MAX", _SC_SIGQUEUE_MAX, SYSCONF }, +#ifdef _PC_FILESIZEBITS { "FILESIZEBITS", _PC_FILESIZEBITS, PATHCONF }, +#endif #ifdef _PC_ALLOC_SIZE_MIN { "POSIX_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN, PATHCONF }, #endif @@ -875,7 +881,9 @@ static const struct conf vars[] = #ifdef _PC_REC_XFER_ALIGN { "POSIX_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN, PATHCONF }, #endif +#ifdef _PC_SYMLINK_MAX { "SYMLINK_MAX", _PC_SYMLINK_MAX, PATHCONF }, +#endif #ifdef _PC_2_SYMLINKS { "POSIX2_SYMLINKS", _PC_2_SYMLINKS, PATHCONF }, #endif diff --git a/lib/glob/glob.c b/lib/glob/glob.c index c8027aadc..2227cd980 100644 --- a/lib/glob/glob.c +++ b/lib/glob/glob.c @@ -1402,6 +1402,12 @@ glob_filename (char *pathname, int flags) free ((char *) array); else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0') free (temp_results); /* expanding ** case above */ + else if (array == temp_results) + /* If array == temp_results, either we assigned it above or + glob_dir_to_array returned temp_results because the dirname + was the empty string. In any case, we assume temp_results + has not been freed, and free it here. */ + free (temp_results); if (shouldbreak) break; @@ -1517,6 +1523,7 @@ only_filename: if (free_dirname) free (directory_name); + return (result); } diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 05779f974..349c87a1f 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -489,6 +489,32 @@ rl_completion_mode (rl_command_func_t *cfunc) return TAB; } +/********************************************/ +/* */ +/* Completion signal handling and cleanup */ +/* */ +/********************************************/ + +/* State to clean up and free if completion is interrupted by a signal. */ +typedef struct { + char **matches; + char *saved_line; +} complete_sigcleanarg_t; + +static void +_rl_complete_sigcleanup (int sig, void *ptr) +{ + complete_sigcleanarg_t *arg; + + if (sig == SIGINT) /* XXX - for now */ + { + arg = ptr; + _rl_free_match_list (arg->matches); + FREE (arg->saved_line); + _rl_complete_display_matches_interrupt = 1; + } +} + /************************************/ /* */ /* Completion utility functions */ @@ -503,16 +529,6 @@ _rl_reset_completion_state (void) rl_completion_quote_character = 0; } -static void -_rl_complete_sigcleanup (int sig, void *ptr) -{ - if (sig == SIGINT) /* XXX - for now */ - { - _rl_free_match_list ((char **)ptr); - _rl_complete_display_matches_interrupt = 1; - } -} - /* Set default values for readline word completion. These are the variables that application completion functions can change or inspect. */ static void @@ -2010,10 +2026,11 @@ rl_complete_internal (int what_to_do) { char **matches; rl_compentry_func_t *our_func; - int start, end, delimiter, found_quote, i, nontrivial_lcd; + int start, end, delimiter, found_quote, i, nontrivial_lcd, do_display; char *text, *saved_line_buffer; char quote_char; int tlen, mlen, saved_last_completion_failed; + complete_sigcleanarg_t cleanarg; /* state to clean up on signal */ RL_SETSTATE(RL_STATE_COMPLETING); @@ -2092,6 +2109,8 @@ rl_complete_internal (int what_to_do) if (matches && matches[0] && *matches[0]) last_completion_failed = 0; + do_display = 0; + switch (what_to_do) { case TAB: @@ -2125,13 +2144,13 @@ rl_complete_internal (int what_to_do) { if (what_to_do == '!') { - display_matches (matches); + do_display = 1; break; } else if (what_to_do == '@') { if (nontrivial_lcd == 0) - display_matches (matches); + do_display = 1; break; } else if (rl_editing_mode != vi_mode) @@ -2156,22 +2175,7 @@ rl_complete_internal (int what_to_do) break; } - if (rl_completion_display_matches_hook == 0) - { - _rl_sigcleanup = _rl_complete_sigcleanup; - _rl_sigcleanarg = matches; - _rl_complete_display_matches_interrupt = 0; - } - display_matches (matches); - if (_rl_complete_display_matches_interrupt) - { - matches = 0; /* already freed by rl_complete_sigcleanup */ - _rl_complete_display_matches_interrupt = 0; - if (rl_signal_event_hook) - (*rl_signal_event_hook) (); /* XXX */ - } - _rl_sigcleanup = 0; - _rl_sigcleanarg = 0; + do_display = 1; break; default: @@ -2184,6 +2188,34 @@ rl_complete_internal (int what_to_do) return 1; } + /* If we need to display the match list, set up to clean it up on receipt of + a signal and do it here. If the application has registered a function to + display the matches, let it do the work. */ + if (do_display) + { + if (rl_completion_display_matches_hook == 0) + { + _rl_sigcleanup = _rl_complete_sigcleanup; + cleanarg.matches = matches; + cleanarg.saved_line = saved_line_buffer; + _rl_sigcleanarg = &cleanarg; + _rl_complete_display_matches_interrupt = 0; + } + + display_matches (matches); + + if (_rl_complete_display_matches_interrupt) + { + matches = 0; /* Both already freed by _rl_complete_sigcleanup */ + saved_line_buffer = 0; + _rl_complete_display_matches_interrupt = 0; + if (rl_signal_event_hook) + (*rl_signal_event_hook) (); + } + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; + } + _rl_free_match_list (matches); /* Check to see if the line has changed through all of this manipulation. */ diff --git a/lib/readline/rltypedefs.h b/lib/readline/rltypedefs.h index b1ffeb05c..d179e858f 100644 --- a/lib/readline/rltypedefs.h +++ b/lib/readline/rltypedefs.h @@ -1,6 +1,6 @@ /* rltypedefs.h -- Type declarations for readline functions. */ -/* Copyright (C) 2000-2021 Free Software Foundation, Inc. +/* Copyright (C) 2000-2023 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -28,7 +28,7 @@ extern "C" { /* Old-style, attempt to mark as deprecated in some way people will notice. */ -#if !defined (_FUNCTION_DEF) +#if !defined (_FUNCTION_DEF) && defined (WANT_OBSOLETE_TYPEDEFS) # define _FUNCTION_DEF typedef int Function () __attribute__((deprecated)); @@ -36,7 +36,7 @@ typedef void VFunction () __attribute__((deprecated)); typedef char *CPFunction () __attribute__((deprecated)); typedef char **CPPFunction () __attribute__((deprecated)); -#endif /* _FUNCTION_DEF */ +#endif /* _FUNCTION_DEF && WANT_OBSOLETE_TYPEDEFS */ /* New style. */ diff --git a/lib/readline/signals.c b/lib/readline/signals.c index ec835e5aa..51d746809 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -267,6 +267,9 @@ _rl_handle_signal (int sig) sigprocmask (SIG_BLOCK, &set, &oset); #endif +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK) == 0 || rl_persistent_signal_handlers) +#endif rl_echo_signal_char (sig); rl_cleanup_after_signal (); diff --git a/print_cmd.c b/print_cmd.c index f8524e04a..d7c5bbf9c 100644 --- a/print_cmd.c +++ b/print_cmd.c @@ -514,10 +514,10 @@ xtrace_print_assignment (char *name, char *value, int assign_list, int xflags) /* VALUE should not be NULL when this is called. */ if (*value == '\0' || assign_list) nval = value; - else if (sh_contains_shell_metas (value)) - nval = sh_single_quote (value); else if (ansic_shouldquote (value)) nval = ansic_quote (value, 0, (int *)0); + else if (sh_contains_shell_metas (value)) + nval = sh_single_quote (value); else nval = value; @@ -554,15 +554,15 @@ xtrace_print_word_list (WORD_LIST *list, int xtflags) fprintf (xtrace_fp, "''%s", w->next ? " " : ""); else if (xtflags & 2) fprintf (xtrace_fp, "%s%s", t, w->next ? " " : ""); - else if (sh_contains_shell_metas (t)) + else if (ansic_shouldquote (t)) { - x = sh_single_quote (t); + x = ansic_quote (t, 0, (int *)0); fprintf (xtrace_fp, "%s%s", x, w->next ? " " : ""); free (x); } - else if (ansic_shouldquote (t)) + else if (sh_contains_shell_metas (t)) { - x = ansic_quote (t, 0, (int *)0); + x = sh_single_quote (t); fprintf (xtrace_fp, "%s%s", x, w->next ? " " : ""); free (x); }