From: Chet Ramey Date: Tue, 7 Oct 2025 18:08:09 +0000 (-0400) Subject: fixes for readline getting signals at unlikely times; don't allow keyboard macros... X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fdevel;p=thirdparty%2Freadline.git fixes for readline getting signals at unlikely times; don't allow keyboard macros while reading from a macro bound to a key sequence; fix for reading an incomplete bracketed paste prefix --- diff --git a/README b/README index 75eaa2f..d3bb12b 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Introduction ============ -This is the Gnu Readline library, version 8.3. +This is the GNU Readline library, version 8.3. The Readline library provides a set of functions for use by applications that allow users to edit command lines as they are typed in. Both diff --git a/aclocal.m4 b/aclocal.m4 index 8d72b67..561465f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -943,19 +943,24 @@ if test "X$_bash_needmsg" = "Xyes"; then AC_MSG_CHECKING(which library has the termcap functions) fi AC_MSG_RESULT(using $bash_cv_termcap_lib) -if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then +# we assume that anyone specifying --with-curses=library is savvy enough to +# put it in a place that the linker can find it without a special -L option +if test "$opt_curses" != "no" && test "$opt_curses" != "yes" ; then +TERMCAP_LIB="$opt_curses" +TERMCAP_DEP= +elif test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" TERMCAP_DEP="./lib/termcap/libtermcap.a" elif test $bash_cv_termcap_lib = libtermcap && test -z "$prefer_curses"; then TERMCAP_LIB=-ltermcap TERMCAP_DEP= -elif test $bash_cv_termcap_lib = libtinfo; then -TERMCAP_LIB=-ltinfo -TERMCAP_DEP= elif test $bash_cv_termcap_lib = libtinfow; then TERMCAP_LIB=-ltinfow TERMCAP_DEP= +elif test $bash_cv_termcap_lib = libtinfo; then +TERMCAP_LIB=-ltinfo +TERMCAP_DEP= elif test $bash_cv_termcap_lib = libncursesw; then TERMCAP_LIB=-lncursesw TERMCAP_DEP= diff --git a/config.h.in b/config.h.in index 71b051e..6a0ba84 100644 --- a/config.h.in +++ b/config.h.in @@ -62,6 +62,9 @@ /* Define if you have the chown function. */ #undef HAVE_CHOWN +/* Define if you have the clock_gettime function. */ +#undef HAVE_CLOCK_GETTIME + /* Define if you have the fcntl function. */ #undef HAVE_FCNTL diff --git a/configure b/configure index e74c229..8993c00 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac for Readline 8.3, version 2.103. +# From configure.ac for Readline 8.3, version 2.104. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for readline 8.3. # @@ -5191,6 +5191,12 @@ fi fi +ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes +then : + printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h + +fi ac_fn_c_check_func "$LINENO" "fcntl" "ac_cv_func_fcntl" if test "x$ac_cv_func_fcntl" = xyes then : @@ -7233,6 +7239,53 @@ printf "%s\n" "$ac_cv_lib_tinfo_tgetent" >&6; } if test "x$ac_cv_lib_tinfo_tgetent" = xyes then : bash_cv_termcap_lib=libtinfo +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltinfow" >&5 +printf %s "checking for tgetent in -ltinfow... " >&6; } +if test ${ac_cv_lib_tinfow_tgetent+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_check_lib_save_LIBS=$LIBS +LIBS="-ltinfow $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. + The 'extern "C"' is for builds by C++ compilers; + although this is not generally supported in C code supporting it here + has little cost and some practical benefit (sr 110532). */ +#ifdef __cplusplus +extern "C" +#endif +char tgetent (void); +int +main (void) +{ +return tgetent (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_tinfow_tgetent=yes +else case e in #( + e) ac_cv_lib_tinfow_tgetent=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfow_tgetent" >&5 +printf "%s\n" "$ac_cv_lib_tinfow_tgetent" >&6; } +if test "x$ac_cv_lib_tinfow_tgetent" = xyes +then : + bash_cv_termcap_lib=libtinfow else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5 printf %s "checking for tgetent in -lcurses... " >&6; } @@ -7395,6 +7448,9 @@ esac fi ;; esac +fi + ;; +esac fi if test "X$_bash_needmsg" = "Xyes"; then @@ -7403,13 +7459,21 @@ printf %s "checking which library has the termcap functions... " >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using $bash_cv_termcap_lib" >&5 printf "%s\n" "using $bash_cv_termcap_lib" >&6; } -if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then +# we assume that anyone specifying --with-curses=library is savvy enough to +# put it in a place that the linker can find it without a special -L option +if test "$opt_curses" != "no" && test "$opt_curses" != "yes" ; then +TERMCAP_LIB="$opt_curses" +TERMCAP_DEP= +elif test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" TERMCAP_DEP="./lib/termcap/libtermcap.a" elif test $bash_cv_termcap_lib = libtermcap && test -z "$prefer_curses"; then TERMCAP_LIB=-ltermcap TERMCAP_DEP= +elif test $bash_cv_termcap_lib = libtinfow; then +TERMCAP_LIB=-ltinfow +TERMCAP_DEP= elif test $bash_cv_termcap_lib = libtinfo; then TERMCAP_LIB=-ltinfo TERMCAP_DEP= diff --git a/configure.ac b/configure.ac index 5599d12..04bf72a 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu dnl dnl Process this file with autoconf to produce a configure script. -# Copyright (C) 1987-2024 Free Software Foundation, Inc. +# Copyright (C) 1987-2025 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ dnl Process this file with autoconf to produce a configure script. # You should have received a copy of the GNU General Public License # along with this program. If not, see . -AC_REVISION([for Readline 8.3, version 2.103]) +AC_REVISION([for Readline 8.3, version 2.104]) AC_INIT(readline, 8.3, bug-readline@gnu.org) @@ -154,7 +154,8 @@ AC_TYPE_MODE_T AC_HEADER_STAT AC_HEADER_DIRENT -AC_CHECK_FUNCS(fcntl gettimeofday kill lstat pselect readlink select setitimer) +AC_CHECK_FUNCS(clock_gettime fcntl gettimeofday \ + kill lstat pselect readlink select setitimer) AC_CHECK_FUNCS(fnmatch memmove putenv setenv setlocale strcasecmp \ strpbrk sysconf tcgetattr tcgetwinsize tcsetwinsize \ vsnprintf) diff --git a/display.c b/display.c index 5c5f58d..18e6006 100644 --- a/display.c +++ b/display.c @@ -826,10 +826,10 @@ rl_redisplay (void) if (_rl_echoing_p == 0) return; + RL_SETSTATE (RL_STATE_REDISPLAYING); /* Block keyboard interrupts because this function manipulates global data structures. */ _rl_block_sigint (); - RL_SETSTATE (RL_STATE_REDISPLAYING); cur_face = FACE_NORMAL; /* Can turn this into an array for multiple highlighted objects in addition @@ -1708,8 +1708,8 @@ rl_redisplay (void) _rl_quick_redisplay = 0; } - RL_UNSETSTATE (RL_STATE_REDISPLAYING); _rl_release_sigint (); + RL_UNSETSTATE (RL_STATE_REDISPLAYING); } static void diff --git a/doc/history.3 b/doc/history.3 index 53be120..9acf75d 100644 --- a/doc/history.3 +++ b/doc/history.3 @@ -6,15 +6,18 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Tue Dec 31 13:35:52 EST 2024 +.\" Last Change: Mon Oct 6 09:57:49 EDT 2025 .\" -.TH HISTORY 3 "2024 December 31" "GNU History 8.3" +.TH HISTORY 3 "2025 October 6" "GNU History 8.3" +.\" Ensure this string is initialized to avoid groff warnings. +.ds zX \" empty .\" .ie \n(.g \{\ .ds ' \(aq .ds " \(dq .ds ^ \(ha .ds ~ \(ti +.ds : \:\" hyphenless break point (e.g., for long file names and URLs) .\} .el \{\ .ds ' ' @@ -22,6 +25,7 @@ .ds " ""\" two adjacent quotes and no space before this comment .ds ^ ^ .ds ~ ~ +.ds : \" empty .\} . .\" Fix broken EX/EE macros on DWB troff. @@ -76,6 +80,43 @@ \fI\\$1\fP \fB\\$2\fP .br .. +.if \n(.g .ig zX +.\" The following macro definitions are from groff's "an-ext.tmac". +. +.\" Prepare link text for mail/web hyperlinks. `MT` and `UR` call this. +.de mV +. ds mU \\$1\" +.. +.\" Emit hyperlink. The optional argument supplies trailing punctuation +.\" after link text. `ME` and `UE` call this. +.de mQ +. mY +. nh +<\\*(mU>\\$1 +. hy \\n(mH +. rm mU +.. +.\" Start URL. +.\" .UR url +.de UR +. mV \\$1 +.. +.\" End URL. +.\" .UE [punctuation] +.de UE +. mQ \\$1 +.. +.\" Start email address. +.\" .MT address +.de MT +. mV \\$1 +.. +.\" End email address. +.\" .ME [punctuation] +.de ME +. mQ \\$1 +.. +.zX .SH NAME history \- GNU History Library .SH COPYRIGHT @@ -759,41 +800,48 @@ Default filename for reading and writing saved history .SH "SEE ALSO" .PD 0 .TP -\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey +\fIThe GNU Readline Library\fP, Brian Fox and Chet Ramey .TP -\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey +\fIThe GNU History Library\fP, Brian Fox and Chet Ramey .TP \fIbash\fP(1) .TP \fIreadline\fP(3) .PD .SH AUTHORS +.MT bfox@\*:gnu\*:.org Brian Fox, Free Software Foundation -.br -bfox@gnu.org +.ME .PP +.MT chet\*:.ramey@\*:case\*:.edu Chet Ramey, Case Western Reserve University -.br -chet.ramey@case.edu -.SH BUG REPORTS +.ME +.SH "BUG REPORTS" If you find a bug in the .B history -library, you should report it. But first, you should +library, you should report it. +But first, you should make sure that it really is a bug, and that it appears in the latest version of the .B history library that you have. .PP Once you have determined that a bug actually exists, mail a -bug report to \fIbug\-readline\fP@\fIgnu.org\fP. -If you have a fix, you are welcome to mail that -as well! Suggestions and +bug report to +.MT bug\-readline@\*:gnu\*:.org +.ME . +If you have a fix, you are welcome to mail that as well! +Please send suggestions and .Q philosophical -bug reports may be mailed -to \fIbug\-readline\fP@\fIgnu.org\fP or posted to the Usenet +bug reports to +.MT bug\-readline@\*:gnu\*:.org +.ME +or post them to the +Usenet newsgroup -.BR gnu.bash.bug . +.BR gnu\*:.bash\*:.bug . .PP -Comments and bug reports concerning -this manual page should be directed to -.IR chet.ramey@case.edu . +Please send comments and bug reports concerning +this manual page to +.MT bug\-readline@\*:gnu\*:.org +.ME . diff --git a/doc/readline.3 b/doc/readline.3 index dac6618..e748f46 100644 --- a/doc/readline.3 +++ b/doc/readline.3 @@ -6,15 +6,18 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Tue Jul 15 10:19:29 EDT 2025 +.\" Last Change: Mon Oct 6 09:58:21 EDT 2025 .\" -.TH READLINE 3 "2024 July 15" "GNU Readline 8.3" +.TH READLINE 3 "2025 October 6" "GNU Readline 8.3" +.\" Ensure this string is initialized to avoid groff warnings. +.ds zX \" empty .\" .ie \n(.g \{\ .ds ' \(aq .ds " \(dq .ds ^ \(ha .ds ~ \(ti +.ds : \:\" hyphenless break point (e.g., for long file names and URLs) .\} .el \{\ .ds ' ' @@ -22,6 +25,7 @@ .ds " ""\" two adjacent quotes and no space before this comment .ds ^ ^ .ds ~ ~ +.ds : \" empty .\} . .\" File Name macro. This used to be `.PN', for Path Name, @@ -42,6 +46,43 @@ . if n "\\$1"\\$2 .\} .. +.if \n(.g .ig zX +.\" The following macro definitions are from groff's "an-ext.tmac". +. +.\" Prepare link text for mail/web hyperlinks. `MT` and `UR` call this. +.de mV +. ds mU \\$1\" +.. +.\" Emit hyperlink. The optional argument supplies trailing punctuation +.\" after link text. `ME` and `UE` call this. +.de mQ +. mY +. nh +<\\*(mU>\\$1 +. hy \\n(mH +. rm mU +.. +.\" Start URL. +.\" .UR url +.de UR +. mV \\$1 +.. +.\" End URL. +.\" .UE [punctuation] +.de UE +. mQ \\$1 +.. +.\" Start email address. +.\" .MT address +.de MT +. mV \\$1 +.. +.\" End email address. +.\" .ME [punctuation] +.de ME +. mQ \\$1 +.. +.zX .SH NAME readline \- get a line from a user with editing .SH SYNOPSIS @@ -1845,9 +1886,9 @@ VI Command Mode functions .SH "SEE ALSO" .PD 0 .TP -\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey +\fIThe GNU Readline Library\fP, Brian Fox and Chet Ramey .TP -\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey +\fIThe GNU History Library\fP, Brian Fox and Chet Ramey .TP \fIbash\fP(1) .PD @@ -1858,34 +1899,40 @@ VI Command Mode functions Individual \fBreadline\fP initialization file .PD .SH AUTHORS +.MT bfox@\*:gnu\*:.org Brian Fox, Free Software Foundation -.br -bfox@gnu.org +.ME .PP +.MT chet\*:.ramey@\*:case\*:.edu Chet Ramey, Case Western Reserve University -.br -chet.ramey@case.edu -.SH BUG REPORTS +.ME +.SH "BUG REPORTS" If you find a bug in .BR readline , -you should report it. But first, you should +you should report it. +But first, you should make sure that it really is a bug, and that it appears in the latest version of the .B readline library that you have. .PP Once you have determined that a bug actually exists, mail a -bug report to \fIbug\-readline\fP@\fIgnu.org\fP. -If you have a fix, you are welcome to mail that -as well! Suggestions and +bug report to +.MT bug\-readline@\*:gnu\*:.org +.ME . +If you have a fix, you are welcome to mail that as well! +Please send suggestions and .Q philosophical -bug reports may be mailed -to \fPbug-readline\fP@\fIgnu.org\fP or posted to the Usenet +bug reports +to +.MT bug\-readline@\*:gnu\*:.org +.ME +or post them to the +Usenet newsgroup -.BR gnu.bash.bug . +.BR gnu\*:.bash\*:.bug . .PP -Comments and bug reports concerning -this manual page should be directed to -.IR chet.ramey@case.edu . -.SH BUGS -It's too big and too slow. +Please send comments and bug reports concerning +this manual page to +.MT bug\-readline@\*:gnu\*:.org +.ME . diff --git a/doc/rltech.texi b/doc/rltech.texi index ccf7427..a4bc764 100644 --- a/doc/rltech.texi +++ b/doc/rltech.texi @@ -696,7 +696,7 @@ This determines the current keymap and key bindings. * Terminal Management:: Functions to manage terminal settings. * Utility Functions:: Generally useful functions and hooks. * Miscellaneous Functions:: Functions that don't fall into any category. -* Alternate Interface:: Using Readline in a `callback' fashion. +* Alternate Interface:: Using Readline in a ``callback'' fashion. * A Readline Example:: An example Readline function. * Alternate Interface Example:: An example program using the alternate interface. @end menu @@ -1545,7 +1545,7 @@ Some applications need to interleave keyboard I/O with file, device, or window system I/O, typically by using a main loop to @code{select()} on various file descriptors. To accommodate this use case, Readline can -also be invoked as a `callback' function from an event loop. +also be invoked as a ``callback'' function from an event loop. There are functions available to make this easy. @deftypefun void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *line_handler) diff --git a/doc/rluser.texi b/doc/rluser.texi index 6affd6d..45b9a8f 100644 --- a/doc/rluser.texi +++ b/doc/rluser.texi @@ -85,11 +85,11 @@ Line editing can be enabled at any time using the @option{-o emacs} or The following paragraphs use Emacs style to describe the notation used to represent keystrokes. -The text @kbd{C-k} is read as `Control-K' and describes the character +The text @kbd{C-k} is read as ``Control-K'' and describes the character produced when the @key{k} key is pressed while the Control key is depressed. -The text @kbd{M-k} is read as `Meta-K' and describes the character +The text @kbd{M-k} is read as ``Meta-K'' and describes the character produced when the Meta key (if you have one) is depressed, and the @key{k} key is pressed (a @dfn{meta character}), then both are released. The Meta key is labeled @key{ALT} or @key{Option} on many keyboards. @@ -120,7 +120,7 @@ you can make @kbd{M-key} key bindings you specify (see @code{Key Bindings} in @ref{Readline Init File Syntax}) do the same thing by setting the @code{force-meta-prefix} variable. -The text @kbd{M-C-k} is read as `Meta-Control-k' and describes the +The text @kbd{M-C-k} is read as ``Meta-Control-k'' and describes the character produced by metafying @kbd{C-k}. In addition, several keys have their own names. @@ -178,10 +178,10 @@ and then correct your mistake. Afterwards, you can move the cursor to the right with @kbd{C-f}. When you add text in the middle of a line, you will notice that characters -to the right of the cursor are `pushed over' to make room for the text +to the right of the cursor are ``pushed over'' to make room for the text that you have inserted. Likewise, when you delete text behind the cursor, -characters to the right of the cursor are `pulled back' to fill in the +characters to the right of the cursor are ``pulled back'' to fill in the blank space created by the removal of the text. These are the bare essentials for editing the text of an input line: @@ -244,9 +244,9 @@ operate on characters while meta keystrokes operate on words. @dfn{Killing} text means to delete the text from the line, but to save it away for later use, usually by @dfn{yanking} (re-inserting) it back into the line. -(`Cut' and `paste' are more recent jargon for `kill' and `yank'.) +(``Cut'' and ``paste'' are more recent jargon for ``kill'' and ``yank''.) -If the description for a command says that it `kills' text, then you can +If the description for a command says that it ``kills'' text, then you can be sure that you can get the text back in a different (or the same) place later. @@ -307,9 +307,10 @@ act in a backward direction. For example, to kill text back to the start of the line, you might type @samp{M-- C-k}. -The general way to pass numeric arguments to a command is to type meta -digits before the command. -If the first `digit' typed is a minus +The general way to pass numeric arguments to a command is to type +the Meta key and then digits (``meta digits'') +before the command. +If the first ``digit'' typed is a minus sign (@samp{-}), then the sign of the argument will be negative. Once you have typed one meta digit to get the argument started, you can type the remainder of the digits, and then the command. @@ -1420,11 +1421,11 @@ If this line is a modified history line, then restore the history line to its original state. @item previous-history (C-p) -Move `back' through the history list, fetching the previous command. +Move ``back'' through the history list, fetching the previous command. This may also be bound to the up arrow key on some keyboards. @item next-history (C-n) -Move `forward' through the history list, fetching the next command. +Move ``forward'' through the history list, fetching the next command. This may also be bound to the down arrow key on some keyboards. @item beginning-of-history (M-<) @@ -1435,25 +1436,26 @@ Move to the end of the input history, i.e., the line currently being entered. @item reverse-search-history (C-r) -Search backward starting at the current line and moving `up' through +Search backward starting at the current line and moving ``up'' through the history as necessary. This is an incremental search. This command sets the region to the matched text and activates the region. @item forward-search-history (C-s) -Search forward starting at the current line and moving `down' through +Search forward starting at the current line and moving ``down'' through the history as necessary. This is an incremental search. This command sets the region to the matched text and activates the region. @item non-incremental-reverse-search-history (M-p) -Search backward starting at the current line and moving `up' +Search backward starting at the current line and moving ``up'' + through the history as necessary using a non-incremental search for a string supplied by the user. The search string may match anywhere in a history line. @item non-incremental-forward-search-history (M-n) -Search forward starting at the current line and moving `down' +Search forward starting at the current line and moving ``down'' through the history as necessary using a non-incremental search for a string supplied by the user. The search string may match anywhere in a history line. @@ -2135,8 +2137,8 @@ when in @code{vi} mode and to vi-editing-mode in @code{emacs} mode). The Readline default is @code{emacs} mode. When you enter a line in @code{vi} mode, you are already placed in -`insertion' mode, as if you had typed an @samp{i}. Pressing @key{ESC} -switches you into `command' mode, where you can edit the text of the +``insertion'' mode, as if you had typed an @samp{i}. Pressing @key{ESC} +switches you into ``command'' mode, where you can edit the text of the line with the standard @code{vi} movement keys, move to previous history lines with @samp{k} and subsequent lines with @samp{j}, and so forth. @@ -2259,6 +2261,25 @@ the standard output. Backslash will escape a newline, if necessary. These are added to the set of possible completions. +External commands that are invoked to generate completions +("external completers") +receive the word preceding the completion word as an argument, +as described above. +This provides context that is sometimes useful, but may include +information that is considered sensitive or part of a word expansion +that will not appear in the command line after expansion. +That word may be visible in process listings or in audit logs. +This may be a concern to users and completion specification authors +if there is sensitive information on the command line before +expansion, since completion takes place before words are expanded. +If this is an issue, completion authors should use functions as +wrappers around external commands and pass context information to the +external command in a different way. +External completers can infer context from the @var{COMP_LINE} +and @var{COMP_POINT} environment variables, but they need to ensure +they break words in the same way Readline does, using the +@var{COMP_WORDBREAKS} variable. + After generating all of the possible completions, Bash applies any filter specified with the @option{-X} option to the completions in the list. diff --git a/doc/version.texi b/doc/version.texi index 52bde74..0b68b50 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -5,7 +5,7 @@ Copyright (C) 1988-2025 Free Software Foundation, Inc. @set EDITION 8.3 @set VERSION 8.3 -@set UPDATED 15 July 2025 -@set UPDATED-MONTH July 2025 +@set UPDATED 25 August 2025 +@set UPDATED-MONTH August 2025 -@set LASTCHANGE Tue Jul 15 10:18:40 EDT 2025 +@set LASTCHANGE Mon Aug 25 11:33:46 EDT 2025 diff --git a/input.c b/input.c index 3383edb..b207212 100644 --- a/input.c +++ b/input.c @@ -825,8 +825,14 @@ rl_read_key (void) { if (rl_get_char (&c) == 0) c = (*rl_getc_function) (rl_instream); -/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d\r\n", _rl_caught_signal); */ - RL_CHECK_SIGNALS (); + /* This can happen if rl_getc_function != rl_getc */ + if (_rl_caught_signal) + { + if (c > 0) + rl_stuff_char (c); + c = -1; + RL_CHECK_SIGNALS (); + } } } @@ -837,13 +843,14 @@ int rl_getc (FILE *stream) { int result, ostate, osig; - unsigned char c; + unsigned char c, savec; int fd; #if defined (HAVE_PSELECT) || defined (HAVE_SELECT) sigset_t empty_set; fd_set readfds; #endif + savec = 0; fd = fileno (stream); while (1) { @@ -852,19 +859,24 @@ rl_getc (FILE *stream) RL_CHECK_SIGNALS (); -#if defined (READLINE_CALLBACKS) - /* Do signal handling post-processing here, but just in callback mode - for right now because the signal cleanup can change some of the + /* Do signal handling post-processing here, not just in callback mode + now, because the signal cleanup can change some of the readline and callback state, and we need to either let the application have a chance to react or abort some current operation that gets cleaned - up by rl_callback_sigcleanup(). If not, we'll just run through the - loop again. */ - if (osig != 0 && (ostate & RL_STATE_CALLBACK)) + up by rl_callback_sigcleanup() or another signal cleanup function. + If not, we'll just run through the loop again. */ + if (osig != 0) goto postproc_signal; -#endif /* We know at this point that _rl_caught_signal == 0 */ + if (savec > 0) + { + c = savec; + savec = 0; + return c; + } + #if defined (__MINGW32__) if (isatty (fd)) return (_getch ()); /* "There is no error return." */ @@ -888,6 +900,20 @@ rl_getc (FILE *stream) if (result >= 0) result = read (fd, &c, sizeof (unsigned char)); +/* fprintf(stderr, "rl_getc: read result = %d errno = %d _rl_caught_signal = %d\n", result, errno, _rl_caught_signal); */ + /* It is possible, though extremely unlikely, for read to both succeed + (result == 1) and receive a signal (_rl_caught_signal != 0). We + know we have a signal we're interested in, since readline's handler + was called, so we want to handle it below and defer returning the + character we read until the next time through the loop. */ + if (result > 0 && _rl_caught_signal != 0) + { + if (c > 0) /* if result == 1 we assume that c is valid */ + savec = c; /* one level of pushback */ + result = -1; + errno = EINTR; + } + if (result == sizeof (unsigned char)) return (c); @@ -923,7 +949,7 @@ rl_getc (FILE *stream) #undef X_EWOULDBLOCK #undef X_EAGAIN -/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */ +/* fprintf(stderr, "rl_getc: read result = %d errno = %d _rl_caught_signal = %d\n", result, errno, _rl_caught_signal); */ /* Handle errors here. */ osig = _rl_caught_signal; @@ -975,11 +1001,11 @@ postproc_signal: call the application's signal event hook. */ if (rl_signal_event_hook) (*rl_signal_event_hook) (); -#if defined (READLINE_CALLBACKS) - else if (osig == SIGINT && (ostate & RL_STATE_CALLBACK) && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG))) + /* If the application's SIGINT handler returns, make sure we abort out of + searches and numeric arguments because we've freed necessary state. */ + if (osig == SIGINT && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG|RL_STATE_MOREINPUT))) /* just these cases for now */ _rl_abort_internal (); -#endif } } diff --git a/isearch.c b/isearch.c index 7b845c2..e2125e4 100644 --- a/isearch.c +++ b/isearch.c @@ -153,10 +153,11 @@ rl_display_search (char *search_string, int flags, int where) { char *message; size_t msglen, searchlen; + unsigned char c; searchlen = (search_string && *search_string) ? strlen (search_string) : 0; - message = (char *)xmalloc (searchlen + 64); + message = (char *)xmalloc (searchlen * 2 + 64); msglen = 0; #if defined (NOTDEF) @@ -186,8 +187,15 @@ rl_display_search (char *search_string, int flags, int where) if (search_string && *search_string) { - strcpy (message + msglen, search_string); - msglen += searchlen; + for ( ; c = *search_string; search_string++) + { + if (CTRL_CHAR (c) || c == RUBOUT) + { + message[msglen++] = '^'; + c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; + } + message[msglen++] = c; + } } else _rl_optimize_redisplay (); @@ -319,7 +327,7 @@ _rl_search_getchar (_rl_search_cxt *cxt) /* Read a key and decide how to proceed. */ RL_SETSTATE(RL_STATE_MOREINPUT); - c = cxt->lastc = rl_read_key (); + c = cxt->lastc = rl_read_key (); /* XXX */ RL_UNSETSTATE(RL_STATE_MOREINPUT); #if defined (HANDLE_MULTIBYTE) @@ -889,12 +897,14 @@ opcode_dispatch: int _rl_isearch_cleanup (_rl_search_cxt *cxt, int r) { + RL_UNSETSTATE(RL_STATE_ISEARCH); + if (cxt == 0) + return (r != 0); + + _rl_iscxt = 0; if (r >= 0) _rl_isearch_fini (cxt); _rl_scxt_dispose (cxt, 0); - _rl_iscxt = 0; - - RL_UNSETSTATE(RL_STATE_ISEARCH); return (r != 0); } diff --git a/kill.c b/kill.c index ca92ea1..9d3bdb4 100644 --- a/kill.c +++ b/kill.c @@ -1,6 +1,6 @@ /* kill.c -- kill ring management. */ -/* Copyright (C) 1994-2024 Free Software Foundation, Inc. +/* Copyright (C) 1994-2025 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. @@ -718,7 +718,7 @@ _rl_bracketed_text (size_t *lenp) RL_SETSTATE (RL_STATE_MOREINPUT); while ((c = rl_read_key ()) >= 0) { - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0) _rl_add_macro_char (c); if (c == '\r') /* XXX */ @@ -736,7 +736,11 @@ _rl_bracketed_text (size_t *lenp) } } RL_UNSETSTATE (RL_STATE_MOREINPUT); - + if (c < 0) /* read error */ + { + free (buf); + _rl_abort_internal (); + } if (len == cap) buf = xrealloc (buf, cap + 1); buf[len] = '\0'; @@ -790,7 +794,7 @@ _rl_read_bracketed_paste_prefix (int c) break; } - if (ind < BRACK_PASTE_SLEN-1) /* read incomplete sequence */ + if (ind < BRACK_PASTE_SLEN-1 || key != BRACK_PASTE_LAST) /* read incomplete sequence */ { while (ind >= 0) _rl_unget_char (pbuf[ind--]); diff --git a/macro.c b/macro.c index 9ac258d..9f26f4b 100644 --- a/macro.c +++ b/macro.c @@ -241,11 +241,13 @@ _rl_kill_kbd_macro (void) End the definition with rl_end_kbd_macro (). If a numeric argument was explicitly typed, then append this definition to the end of the existing macro, and start by - re-executing the existing macro. */ + re-executing the existing macro. + We don't allow recursive keyboard macro definitions or keyboard macro + definitions while reading input from a bound macro. */ int rl_start_kbd_macro (int ignore1, int ignore2) { - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF|RL_STATE_MACROINPUT)) { _rl_abort_internal (); return 1; diff --git a/readline.c b/readline.c index 33b6c13..e976f8f 100644 --- a/readline.c +++ b/readline.c @@ -890,7 +890,7 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq) { if (map[ESC].type == ISKMAP) { - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0) _rl_add_macro_char (ESC); RESIZE_KEYSEQ_BUFFER (); rl_executing_keyseq[rl_key_sequence_length++] = ESC; @@ -903,7 +903,7 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq) return 0; } - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0) _rl_add_macro_char (key); r = 0; diff --git a/rlprivate.h b/rlprivate.h index eb0495f..c8cb673 100644 --- a/rlprivate.h +++ b/rlprivate.h @@ -446,8 +446,10 @@ extern void _rl_signal_handler (int); extern void _rl_block_sigint (void); extern void _rl_release_sigint (void); +extern int _rl_sigint_blocked_p (void); extern void _rl_block_sigwinch (void); extern void _rl_release_sigwinch (void); +extern int _rl_sigwinch_blocked_p (void); extern void _rl_state_sigcleanup (void); diff --git a/signals.c b/signals.c index 5a070d7..6cd73f5 100644 --- a/signals.c +++ b/signals.c @@ -672,12 +672,25 @@ _rl_block_sigint (void) void _rl_release_sigint (void) { + int osig, ostate; + if (sigint_blocked == 0) return; sigint_blocked = 0; + osig = _rl_caught_signal; + ostate = rl_readline_state; if (RL_ISSTATE (RL_STATE_SIGHANDLER) == 0) RL_CHECK_SIGNALS (); + /* These are basically all the places that call rl_message() */ + if (osig == SIGINT && (ostate & (RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_NUMERICARG|RL_STATE_MOREINPUT|RL_STATE_READSTR))) + _rl_abort_internal (); +} + +int +_rl_sigint_blocked_p (void) +{ + return sigint_blocked; } /* Cause SIGWINCH to not be delivered until the corresponding call to @@ -736,6 +749,12 @@ _rl_release_sigwinch (void) sigwinch_blocked = 0; } +int +_rl_sigwinch_blocked_p (void) +{ + return sigwinch_blocked; +} + /* **************************************************************** */ /* */ /* Echoing special control characters */ diff --git a/text.c b/text.c index d842589..9b00a6f 100644 --- a/text.c +++ b/text.c @@ -39,6 +39,7 @@ # include #endif +#include #include /* System-specific feature definitions and include files. */ @@ -1047,7 +1048,7 @@ _rl_insert_next (int count) if (c < 0) return 1; - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0) _rl_add_macro_char (c); #if defined (HANDLE_SIGNALS) @@ -1793,7 +1794,7 @@ _rl_char_search (int count, int fdir, int bdir) if (mb_len <= 0) return 1; - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0) for (i = 0; i < mb_len; i++) _rl_add_macro_char (mbchar[i]); @@ -1813,7 +1814,7 @@ _rl_char_search (int count, int fdir, int bdir) if (c < 0) return 1; - if (RL_ISSTATE (RL_STATE_MACRODEF)) + if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0) _rl_add_macro_char (c); if (count < 0) @@ -2026,14 +2027,14 @@ _rl_readstr_init (int pchar, int flags) rl_end = rl_point = 0; p = _rl_make_prompt_for_search (pchar ? pchar : '@'); - cxt->flags |= READSTR_FREEPMT; - rl_message ("%s", p); - xfree (p); RL_SETSTATE (RL_STATE_READSTR); - + cxt->flags |= READSTR_FREEPMT; _rl_rscxt = cxt; + rl_message ("%s", p); + xfree (p); + return cxt; } @@ -2081,7 +2082,7 @@ _rl_readstr_getchar (_rl_readstr_cxt *cxt) RL_SETSTATE(RL_STATE_MOREINPUT); c = cxt->lastc = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); - + #if defined (HANDLE_MULTIBYTE) /* This ends up with C (and LASTC) being set to the last byte of the multibyte character. In most cases c == lastc == mb[0] */ @@ -2089,6 +2090,9 @@ _rl_readstr_getchar (_rl_readstr_cxt *cxt) c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX); #endif + if (_rl_caught_signal == SIGINT) /* XXX maybe more signals here */ + c = -1; + RL_CHECK_SIGNALS (); return c; } @@ -2331,6 +2335,8 @@ _rl_read_command_name () if (c < 0) { + if (_rl_rscxt == 0) /* signal */ + _rl_abort_internal (); _rl_readstr_restore (cxt); _rl_readstr_cleanup (cxt, r); return NULL;