From: Chet Ramey Date: Thu, 11 Mar 2021 23:44:09 +0000 (-0500) Subject: commit readline-20210311 snapshot X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=109eadf6fe5c6a7e95ef0298820897ce6ee9172e;p=thirdparty%2Freadline.git commit readline-20210311 snapshot --- diff --git a/MANIFEST b/MANIFEST index ad49d66..5af8d0f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -32,6 +32,7 @@ posixdir.h f posixjmp.h f posixselect.h f posixstat.h f +posixtime.h f readline.h f rlconf.h f rldefs.h f @@ -121,6 +122,8 @@ examples/rlevent.c f examples/rlkeymaps.c f examples/rltest.c f examples/rl-callbacktest.c f +examples/rl-timeout.c f +examples/rl-test-timeout f examples/rl.c f examples/rlptytest.c f examples/rlversion.c f diff --git a/callback.c b/callback.c index a466cf9..cfff650 100644 --- a/callback.c +++ b/callback.c @@ -147,6 +147,14 @@ rl_callback_read_char (void) (*rl_redisplay_function) (); _rl_want_redisplay = 0; memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t)); + + /* If we longjmped because of a timeout, handle it here. */ + if (RL_ISSTATE (RL_STATE_TIMEOUT)) + { + RL_SETSTATE (RL_STATE_DONE); + rl_done = 1; + } + CALLBACK_READ_RETURN (); } @@ -278,7 +286,8 @@ rl_callback_read_char (void) rl_clear_signals (); #endif in_handler = 0; - (*rl_linefunc) (line); + if (rl_linefunc) /* just in case */ + (*rl_linefunc) (line); /* If the user did not clear out the line, do it for him. */ if (rl_line_buffer[0]) diff --git a/config.h.in b/config.h.in index 6de47b5..bc6753f 100644 --- a/config.h.in +++ b/config.h.in @@ -58,6 +58,9 @@ /* Define if you have the getpwuid function. */ #undef HAVE_GETPWUID +/* Define if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + /* Define if you have the isascii function. */ #undef HAVE_ISASCII @@ -106,6 +109,9 @@ /* Define if you have the setenv function. */ #undef HAVE_SETENV +/* Define if you have the setitimer function. */ +#undef HAVE_SETITIMER + /* Define if you have the setlocale function. */ #undef HAVE_SETLOCALE @@ -120,6 +126,9 @@ /* Define if you have the strpbrk function. */ #undef HAVE_STRPBRK +/* Define if you have the sysconf function. */ +#undef HAVE_SYSCONF + /* Define if you have the tcgetattr function. */ #undef HAVE_TCGETATTR @@ -218,6 +227,9 @@ /* Define if you have the header file. */ #undef HAVE_SYS_STREAM_H +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + /* Define if you have the header file. */ #undef HAVE_TERMCAP_H @@ -256,6 +268,8 @@ /* Define if you have and it defines AUDIT_USER_TTY */ #undef HAVE_DECL_AUDIT_USER_TTY +#undef TIME_WITH_SYS_TIME + /* Definitions pulled in from aclocal.m4. */ #undef VOID_SIGHANDLER @@ -279,6 +293,8 @@ #undef HAVE_STRUCT_DIRENT_D_NAMLEN +#undef HAVE_TIMEVAL + #undef HAVE_BSD_SIGNALS #undef HAVE_POSIX_SIGNALS diff --git a/configure b/configure old mode 100755 new mode 100644 index 5a0bf2f..21deb8c --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac for Readline 8.1, version 2.90. +# From configure.ac for Readline 8.1, version 2.91. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for readline 8.1. # @@ -4793,8 +4793,43 @@ fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + -for ac_func in fcntl kill lstat readlink +for ac_func in fcntl gettimeofday kill lstat pselect readlink select setitimer do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -4806,8 +4841,8 @@ _ACEOF fi done -for ac_func in fnmatch memmove pselect putenv select setenv setlocale \ - strcasecmp strpbrk tcgetattr vsnprintf +for ac_func in fnmatch memmove putenv setenv setlocale \ + strcasecmp strpbrk sysconf tcgetattr vsnprintf do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -4994,7 +5029,8 @@ fi done -for ac_header in sys/ioctl.h sys/pte.h sys/stream.h sys/select.h sys/file.h +for ac_header in sys/ioctl.h sys/pte.h sys/stream.h sys/select.h \ + sys/time.h sys/file.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -6086,6 +6122,43 @@ $as_echo "#define HAVE_STRUCT_DIRENT_D_FILENO 1" >>confdefs.h fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct timeval in sys/time.h and time.h" >&5 +$as_echo_n "checking for struct timeval in sys/time.h and time.h... " >&6; } +if ${bash_cv_struct_timeval+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if HAVE_SYS_TIME_H + #include + #endif + #include + +int +main () +{ +static struct timeval x; x.tv_sec = x.tv_usec; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + bash_cv_struct_timeval=yes +else + bash_cv_struct_timeval=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bash_cv_struct_timeval" >&5 +$as_echo "$bash_cv_struct_timeval" >&6; } +if test $bash_cv_struct_timeval = yes; then + $as_echo "#define HAVE_TIMEVAL 1" >>confdefs.h + +fi + for ac_header in libaudit.h do : diff --git a/configure.ac b/configure.ac index 147bae5..93d9a9a 100644 --- a/configure.ac +++ b/configure.ac @@ -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.1, version 2.90]) +AC_REVISION([for Readline 8.1, version 2.91]) AC_INIT(readline, 8.1, bug-readline@gnu.org) @@ -145,10 +145,11 @@ AC_HEADER_STDC AC_HEADER_STAT AC_HEADER_DIRENT +AC_HEADER_TIME -AC_CHECK_FUNCS(fcntl kill lstat readlink) -AC_CHECK_FUNCS(fnmatch memmove pselect putenv select setenv setlocale \ - strcasecmp strpbrk tcgetattr vsnprintf) +AC_CHECK_FUNCS(fcntl gettimeofday kill lstat pselect readlink select setitimer) +AC_CHECK_FUNCS(fnmatch memmove putenv setenv setlocale \ + strcasecmp strpbrk sysconf tcgetattr vsnprintf) AC_CHECK_FUNCS(isascii isxdigit) AC_CHECK_FUNCS(getpwent getpwnam getpwuid) @@ -158,7 +159,8 @@ AC_FUNC_STRCOLL AC_CHECK_HEADERS(fcntl.h unistd.h stdlib.h varargs.h stdarg.h stdbool.h \ string.h strings.h \ limits.h locale.h pwd.h memory.h termcap.h termios.h termio.h) -AC_CHECK_HEADERS(sys/ioctl.h sys/pte.h sys/stream.h sys/select.h sys/file.h) +AC_CHECK_HEADERS(sys/ioctl.h sys/pte.h sys/stream.h sys/select.h \ + sys/time.h sys/file.h) AC_CHECK_HEADERS(sys/ptem.h,,, [[ @@ -190,6 +192,7 @@ BASH_CHECK_SPEED_T BASH_STRUCT_WINSIZE BASH_STRUCT_DIRENT_D_INO BASH_STRUCT_DIRENT_D_FILENO +BASH_STRUCT_TIMEVAL AC_CHECK_HEADERS(libaudit.h) AC_CHECK_DECLS([AUDIT_USER_TTY],,, [[#include ]]) diff --git a/doc/hsuser.texi b/doc/hsuser.texi index b8fedf3..0a81c46 100644 --- a/doc/hsuser.texi +++ b/doc/hsuser.texi @@ -214,8 +214,9 @@ end of the history, and an index of @samp{-1} refers to the current @code{history -d} command. @item -d @var{start}-@var{end} -Delete the history entries between positions @var{start} and @var{end}, -inclusive. Positive and negative values for @var{start} and @var{end} +Delete the range of history entries between positions @var{start} and +@var{end}, inclusive. +Positive and negative values for @var{start} and @var{end} are interpreted as described above. @item -a @@ -250,6 +251,11 @@ used, if @var{filename} is given, then it is used as the history file. If not, then the value of the @env{HISTFILE} variable is used. +The return value is 0 unless an invalid option is encountered, an +error occurs while reading or writing the history file, an invalid +@var{offset} or range is supplied as an argument to @option{-d}, or the +history expansion supplied as an argument to @option{-p} fails. + @end table @end ifset diff --git a/doc/rltech.texi b/doc/rltech.texi index bbf57c2..a440225 100644 --- a/doc/rltech.texi +++ b/doc/rltech.texi @@ -455,6 +455,11 @@ If non-zero, this is the address of a function to call if a read system call is interrupted when Readline is reading terminal input. @end deftypevar +@deftypevar {rl_hook_func_t *} rl_timeout_event_hook +If non-zero, this is the address of a function to call if Readline times +out while reading input. +@end deftypevar + @deftypevar {rl_hook_func_t *} rl_input_available_hook If non-zero, Readline will use this function's return value when it needs to determine whether or not there is available input on the current input @@ -588,6 +593,10 @@ the current call to @code{readline()}. @item RL_STATE_DONE Readline has read a key sequence bound to @code{accept-line} and is about to return the line to the caller. +@item RL_STATE_TIMEOUT +Readline has timed out (it did not receive a line or specified number of +characters before the timeout duration specified by @code{rl_set_timeout} +elapsed) and is returning that status to the caller. @end table @end deftypevar @@ -1151,6 +1160,27 @@ The default waiting period is one-tenth of a second. Returns the old timeout value. @end deftypefun +@deftypefun int rl_set_timeout (unsigned int secs, unsigned int usecs) +Set a timeout for subsequent calls to @code{readline()}. If Readline does +not read a complete line, or the number of characters specified by +@code{rl_num_chars_to_read}, before the duration specfied by @var{secs} +(in seconds) and @var{usecs} (microseconds), it returns and sets +@code{RL_STATE_TIMEOUT} in @code{rl_readline_state}. +Passing 0 for @code{secs} and @code{usecs} cancels any previously set +timeout; the convenience macro @code{rl_clear_timeout()} is shorthand +for this. +Returns 0 if the timeout is set successfully. +@end deftypefun + +@deftypefun int rl_timeout_remaining (unsigned int *secs, unsigned int *usecs) +Return the number of seconds and microseconds remaining in the current +timeout duration in @code{*secs} and @code{*usecs}, respectively. +Returns -1 on error or when there is no timeout set, 0 when the timeout has +expired (leaving @code{*secs} and @code{*usecs} unchanged), and 1 if the +timeout has not expired. If @code{secs} and @code{usecs} are @code{NULL}, +the return value indicates whether the timeout has expired. +@end deftypefun + @node Terminal Management @subsection Terminal Management diff --git a/doc/texi2dvi b/doc/texi2dvi old mode 100755 new mode 100644 diff --git a/doc/texi2html b/doc/texi2html old mode 100755 new mode 100644 diff --git a/doc/version.texi b/doc/version.texi index abb9cb6..a935f83 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -1,10 +1,10 @@ @ignore -Copyright (C) 1988-2020 Free Software Foundation, Inc. +Copyright (C) 1988-2021 Free Software Foundation, Inc. @end ignore @set EDITION 8.1 @set VERSION 8.1 -@set UPDATED 29 October 2020 -@set UPDATED-MONTH October 2020 +@set UPDATED 10 March 2021 +@set UPDATED-MONTH March 2021 -@set LASTCHANGE Thu Oct 29 16:49:01 EDT 2020 +@set LASTCHANGE Wed Mar 10 15:43:49 EST 2021 diff --git a/examples/Makefile.in b/examples/Makefile.in index 4a7c39e..291c6b7 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -72,17 +72,17 @@ TERMCAP_LIB = @TERMCAP_LIB@ SOURCES = excallback.c fileman.c histexamp.c manexamp.c rl-fgets.c rl.c \ rlbasic.c rlcat.c rlevent.c rlptytest.c rltest.c rlversion.c \ rltest2.c rl-callbacktest.c hist_erasedups.c hist_purgecmd.c \ - rlkeymaps.c + rlkeymaps.c rl-timeout.c EXECUTABLES = fileman$(EXEEXT) rltest$(EXEEXT) rl$(EXEEXT) rlcat$(EXEEXT) \ rlevent$(EXEEXT) rlversion$(EXEEXT) histexamp$(EXEEXT) \ rl-callbacktest$(EXEEXT) rlbasic$(EXEEXT) \ hist_erasedups$(EXEEXT) hist_purgecmd$(EXEEXT) \ - rlkeymaps$(EXEEXT) + rlkeymaps$(EXEEXT) rl-timeout$(EXEEXT) OBJECTS = fileman.o rltest.o rl.o rlevent.o rlcat.o rlversion.o histexamp.o \ rltest2.o rl-callbacktest.o rlbasic.o hist_erasedups.o hist_purgecmd.o \ - rlkeymaps.o + rlkeymaps.o rl-timeout.o OTHEREXE = rlptytest$(EXEEXT) OTHEROBJ = rlptytest.o @@ -141,6 +141,9 @@ rl-callbacktest$(EXEEXT): rl-callbacktest.o $(READLINE_LIB) rlptytest$(EXEEXT): rlptytest.o $(READLINE_LIB) $(CC) $(LDFLAGS) -o $@ rlptytest.o $(READLINE_LIB) $(TERMCAP_LIB) $(LIBUTIL) +rl-timeout$(EXEEXT): rl-timeout.o $(READLINE_LIB) + $(CC) $(LDFLAGS) -o $@ rl-timeout.o $(READLINE_LIB) $(TERMCAP_LIB) + rlversion$(EXEEXT): rlversion.o $(READLINE_LIB) $(CC) $(LDFLAGS) -o $@ rlversion.o $(READLINE_LIB) $(TERMCAP_LIB) @@ -173,6 +176,7 @@ rlkeymaps.o: rlkeymaps.c rlcat.o: rlcat.c rlptytest.o: rlptytest.c rl-callbacktest.o: rl-callbacktest.c +rl-timeout.o: rl-timeout.c fileman.o: $(top_srcdir)/readline.h rltest.o: $(top_srcdir)/readline.h @@ -186,3 +190,4 @@ rlbasic.o: $(top_srcdir)/readline.h $(top_srcdir)/history.h rlcat.o: $(top_srcdir)/readline.h $(top_srcdir)/history.h rlptytest.o: $(top_srcdir)/readline.h $(top_srcdir)/history.h rl-callbacktest.o: $(top_srcdir)/readline.h $(top_srcdir)/history.h +rl-timeout.o: $(top_srcdir)/readline.h $(top_srcdir)/history.h diff --git a/examples/rl-test-timeout b/examples/rl-test-timeout new file mode 100644 index 0000000..2c9de1a --- /dev/null +++ b/examples/rl-test-timeout @@ -0,0 +1,6 @@ +./rl-timeout readline1 0.5 +./rl-timeout readline2 0.25 + +./rl-timeout callback1 0.5 +./rl-timeout callback2 0.5 + diff --git a/examples/rl-timeout.c b/examples/rl-timeout.c new file mode 100644 index 0000000..b8a24ba --- /dev/null +++ b/examples/rl-timeout.c @@ -0,0 +1,245 @@ +/* rl-timeout: test various readline builtin timeouts. */ + +/* Copyright (C) 2021 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. + + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with readline. If not, see . +*/ + +/* Standard include files. stdio.h is required. */ +#include +#include +#include +#include + +/* Used for select(2) */ +#include +#include + +#include +#include + +/* Standard readline include files. */ +#if defined (READLINE_LIBRARY) +# include "readline.h" +# include "history.h" +#else +# include +# include +#endif + +extern int errno; + +static void cb_linehandler (char *); + +int timeout_secs = 1, timeout_usecs = 0; +int running; +const char *prompt = "rl-timeout$ "; + +/* **************************************************************** */ +/* */ +/* Example 1: readline () with rl_readline_state */ +/* */ +/* **************************************************************** */ + +void +rltest_timeout_readline1 () +{ + const char *temp; + + rl_set_timeout (timeout_secs, timeout_usecs); + temp = readline (prompt); + if (RL_ISSTATE (RL_STATE_TIMEOUT)) + printf ("timeout\n"); + else if (temp == NULL) + printf ("no input line\n"); + else + printf ("input line: %s\n", temp); + free ((void *) temp); +} + +/* **************************************************************** */ +/* */ +/* Example 2: readline () with rl_timeout_event_hook */ +/* */ +/* **************************************************************** */ + +static int +timeout_handler () +{ + printf ("timeout\n"); + return READERR; +} + +void +rltest_timeout_readline2 () +{ + const char *temp; + + rl_set_timeout (timeout_secs, timeout_usecs); + rl_timeout_event_hook = timeout_handler; + temp = readline (prompt); + if (temp == NULL) + printf ("no input line\n"); + else + printf ("input line: %s\n", temp); + free ((void *)temp); +} + +/* **************************************************************** */ +/* */ +/* Example 3: rl_callback_* () with rl_timeout_remaining */ +/* */ +/* **************************************************************** */ + +/* Callback function called for each line when accept-line executed, EOF + seen, or EOF character read. This sets a flag and returns; it could + also call exit(3). */ +static void +cb_linehandler (char *line) +{ + /* Can use ^D (stty eof) or `exit' to exit. */ + if (line == NULL || strcmp (line, "exit") == 0) + { + if (line == 0) + printf ("\n"); + printf ("exit\n"); + /* This function needs to be called to reset the terminal settings, + and calling it from the line handler keeps one extra prompt from + being displayed. */ + rl_callback_handler_remove (); + + running = 0; + } + else + { + if (*line) + add_history (line); + printf ("input line: %s\n", line); + free (line); + } +} + +void +rltest_timeout_callback1 () +{ + fd_set fds; + int r; + unsigned sec, usec; + + rl_set_timeout (timeout_secs, timeout_usecs); + rl_callback_handler_install (prompt, cb_linehandler); + running = 1; + while (running) + { + FD_ZERO (&fds); + FD_SET (fileno (rl_instream), &fds); + r = rl_timeout_remaining (&sec, &usec); + if (r == 1) + { + struct timeval timeout = {sec, usec}; + r = select (FD_SETSIZE, &fds, NULL, NULL, &timeout); + } + if (r < 0 && errno != EINTR) + { + perror ("rl-timeout: select"); + rl_callback_handler_remove (); + break; + } + else if (r == 0) + { + printf ("rl-timeout: timeout\n"); + rl_callback_handler_remove (); + break; + } + + if (FD_ISSET (fileno (rl_instream), &fds)) + rl_callback_read_char (); + } + + printf ("rl-timeout: Event loop has exited\n"); +} + +/* **************************************************************** */ +/* */ +/* Example 4: rl_callback_* () with rl_timeout_event_hook */ +/* */ +/* **************************************************************** */ + +static int +cb_timeouthandler () +{ + printf ("timeout\n"); + rl_callback_handler_remove (); + running = 0; + return READERR; +} + +void +rltest_timeout_callback2 () +{ + int r; + + rl_set_timeout (timeout_secs, timeout_usecs); + rl_timeout_event_hook = cb_timeouthandler; + rl_callback_handler_install (prompt, cb_linehandler); + running = 1; + while (running) + rl_callback_read_char (); + + printf ("rl-timeout: Event loop has exited\n"); +} + +int +main (int argc, char **argv) +{ + if (argc >= 2) + { + if (argc >= 3) + { + double timeout = atof (argv[2]); + if (timeout <= 0.0) + { + fprintf (stderr, "rl-timeout: specify a positive number for timeout.\n"); + return 2; + } + else if (timeout > UINT_MAX) + { + fprintf (stderr, "rl-timeout: timeout too large.\n"); + return 2; + } + timeout_secs = (unsigned) timeout; + timeout_usecs = (unsigned) ((timeout - timeout_secs) * 1000000 + 0.5); + } + + if (strcmp (argv[1], "readline1") == 0) + rltest_timeout_readline1 (); + else if (strcmp (argv[1], "readline2") == 0) + rltest_timeout_readline2 (); + else if (strcmp (argv[1], "callback1") == 0) + rltest_timeout_callback1 (); + else if (strcmp (argv[1], "callback2") == 0) + rltest_timeout_callback2 (); + else + return 2; + } + else + { + fprintf (stderr, "usage: rl-timeout [readline1 | readline2 | callback1 | callback2] [timeout]\n"); + return 2; + } + return 0; +} diff --git a/examples/rlfe/configure b/examples/rlfe/configure old mode 100755 new mode 100644 diff --git a/histexpand.c b/histexpand.c index 34506da..8ab6809 100644 --- a/histexpand.c +++ b/histexpand.c @@ -1207,13 +1207,36 @@ history_expand (char *hstring, char **output) characters in history_no_expand_chars, then it is not a candidate for expansion of any kind. */ if (cc == 0 || member (cc, history_no_expand_chars) || - (dquote && cc == '"') || - (history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i))) + (dquote && cc == '"')) { ADD_CHAR (string[i]); break; } + /* If the application has defined a function to determine whether + or not a history expansion should be performed, call it here. */ + /* We check against what we've expanded so far, with the current + expansion appended, because that seems to be what csh does. We + decide to expand based on what we have to this point, not what + we started with. */ + if (history_inhibit_expansion_function) + { + int save_j, temp; + + save_j = j; + ADD_CHAR (string[i]); + ADD_CHAR (cc); + + temp = (*history_inhibit_expansion_function) (result, save_j); + if (temp) + { + result[--j] = '\0'; /* `unadd' cc, leaving ADD_CHAR(string[i]) */ + break; + } + else + result[j = save_j] = '\0'; + } + #if defined (NO_BANG_HASH_MODIFIERS) /* There is something that is listed as a `word specifier' in csh documentation which means `the expanded text to this point'. diff --git a/input.c b/input.c index f514d8c..930efa4 100644 --- a/input.c +++ b/input.c @@ -50,6 +50,7 @@ #include #include "posixselect.h" +#include "posixtime.h" #if defined (FIONREAD_IN_SYS_IOCTL) # include @@ -89,6 +90,9 @@ rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL; /* A function to call if a read(2) is interrupted by a signal. */ rl_hook_func_t *rl_signal_event_hook = (rl_hook_func_t *)NULL; +/* A function to call when readline times out after a time is specified. */ +rl_hook_func_t *rl_timeout_event_hook = (rl_hook_func_t *)NULL; + /* A function to replace _rl_input_available for applications using the callback interface. */ rl_hook_func_t *rl_input_available_hook = (rl_hook_func_t *)NULL; @@ -132,6 +136,36 @@ win32_isatty (int fd) #define isatty(x) win32_isatty(x) #endif +/* Readline timeouts */ + +/* I don't know how to set a timeout for _getch() in MinGW32, so we use + SIGALRM. */ +#if (defined (HAVE_PSELECT) || defined (HAVE_SELECT)) && !defined (__MINGW32__) +# define RL_TIMEOUT_USE_SELECT +#else +# define RL_TIMEOUT_USE_SIGALRM +#endif + +int rl_set_timeout (unsigned int, unsigned int); +int rl_timeout_remaining (unsigned int *, unsigned int *); + +int _rl_timeout_init (void); +int _rl_timeout_sigalrm_handler (void); +int _rl_timeout_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *, const sigset_t *); + +static void _rl_timeout_handle (void); +#if defined (RL_TIMEOUT_USE_SIGALRM) +static int set_alarm (unsigned int *, unsigned int *); +static void reset_alarm (void); +#endif + +/* We implement timeouts as a future time using a supplied interval + (timeout_duration) from when the timeout is set (timeout_point). + That allows us to easily determine whether the timeout has occurred + and compute the time remaining until it does. */ +static struct timeval timeout_point; +static struct timeval timeout_duration; + /* **************************************************************** */ /* */ /* Character Input Buffering */ @@ -223,13 +257,17 @@ rl_gather_tyi (void) input = 0; tty = fileno (rl_instream); -#if defined (HAVE_SELECT) +#if defined (HAVE_PSELECT) || defined (HAVE_SELECT) FD_ZERO (&readfds); FD_ZERO (&exceptfds); FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout); +#if defined (RL_TIMEOUT_USE_SELECT) + result = _rl_timeout_select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout, NULL); +#else result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout); +#endif if (result <= 0) return 0; /* Nothing to read. */ #endif @@ -330,11 +368,11 @@ rl_set_keyboard_input_timeout (int u) int _rl_input_available (void) { -#if defined(HAVE_SELECT) +#if defined (HAVE_PSELECT) || defined (HAVE_SELECT) fd_set readfds, exceptfds; struct timeval timeout; #endif -#if !defined (HAVE_SELECT) && defined(FIONREAD) +#if !defined (HAVE_SELECT) && defined (FIONREAD) int chars_avail; #endif int tty; @@ -344,13 +382,17 @@ _rl_input_available (void) tty = fileno (rl_instream); -#if defined (HAVE_SELECT) +#if defined (HAVE_PSELECT) || defined (HAVE_SELECT) FD_ZERO (&readfds); FD_ZERO (&exceptfds); FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout); +# if defined (RL_TIMEOUT_USE_SELECT) + return (_rl_timeout_select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout, NULL) > 0); +# else return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); +# endif #else #if defined (FIONREAD) @@ -463,6 +505,242 @@ rl_clear_pending_input (void) return 0; } +/* **************************************************************** */ +/* */ +/* Timeout utility */ +/* */ +/* **************************************************************** */ + +#if defined (RL_TIMEOUT_USE_SIGALRM) +# if defined (HAVE_SETITIMER) + +static int +set_alarm (unsigned int *secs, unsigned int *usecs) +{ + struct itimerval it; + + timerclear (&it.it_interval); + timerset (&it.it_value, *secs, *usecs); + return setitimer (ITIMER_REAL, &it, NULL); +} + +static void +reset_alarm () +{ + struct itimerval it; + + timerclear (&it.it_interval); + timerclear (&it.it_value); + setitimer (ITIMER_REAL, &it, NULL); +} +# else +static int +set_alarm (unsigned int *secs, unsigned int *usecs) +{ + if (*secs == 0 || *usecs >= USEC_PER_SEC / 2) + (*secs)++; + *usecs = 0; + + return alarm (*secs); +} +static void +reset_alarm () +{ + alarm (0); +} +# endif +#endif + +/* Set a timeout which will be used for the next call of `readline + ()'. When (0, 0) are specified the timeout is cleared. */ +int +rl_set_timeout (unsigned int secs, unsigned int usecs) +{ + timeout_duration.tv_sec = secs + usecs / USEC_PER_SEC; + timeout_duration.tv_usec = usecs % USEC_PER_SEC; + + return 0; +} + +/* Start measuring the time. Returns 0 on success. Returns -1 on + error. */ +int +_rl_timeout_init (void) +{ + unsigned int secs, usecs; + + /* Clear the timeout state of the previous edit */ + RL_UNSETSTATE(RL_STATE_TIMEOUT); + timerclear (&timeout_point); + + /* Return 0 when timeout is unset. */ + if (timerisunset (&timeout_duration)) + return 0; + + /* Return -1 on gettimeofday error. */ + if (gettimeofday(&timeout_point, 0) != 0) + { + timerclear (&timeout_point); + return -1; + } + + secs = timeout_duration.tv_sec; + usecs = timeout_duration.tv_usec; + +#if defined (RL_TIMEOUT_USE_SIGALRM) + /* If select(2)/pselect(2) is unavailable, use SIGALRM. */ + if (set_alarm (&secs, &usecs) < 0) + return -1; +#endif + + timeout_point.tv_sec += secs; + timeout_point.tv_usec += usecs; + if (timeout_point.tv_usec >= USEC_PER_SEC) + { + timeout_point.tv_sec++; + timeout_point.tv_usec -= USEC_PER_SEC; + } + + return 0; +} + +/* Get the remaining time until the scheduled timeout. Returns -1 on + error or no timeout set with secs and usecs unchanged. Returns 0 + on an expired timeout with secs and usecs unchanged. Returns 1 + when the timeout has not yet expired. The remaining time is stored + in secs and usecs. When NULL is specified to either of the + arguments, just the expiration is tested. */ +int +rl_timeout_remaining (unsigned int *secs, unsigned int *usecs) +{ + struct timeval current_time; + + /* Return -1 when timeout is unset. */ + if (timerisunset (&timeout_point)) + { + errno = 0; + return -1; + } + + /* Return -1 on error. errno is set by gettimeofday. */ + if (gettimeofday(¤t_time, 0) != 0) + return -1; + + /* Return 0 when timeout has already expired. */ + /* could use timercmp (&timeout_point, ¤t_time, <) here */ + if (current_time.tv_sec > timeout_point.tv_sec || + (current_time.tv_sec == timeout_point.tv_sec && + current_time.tv_usec >= timeout_point.tv_usec)) + return 0; + + if (secs && usecs) + { + *secs = timeout_point.tv_sec - current_time.tv_sec; + *usecs = timeout_point.tv_usec - current_time.tv_usec; + if (timeout_point.tv_usec < current_time.tv_usec) + { + (*secs)--; + *usecs += USEC_PER_SEC; + } + } + + return 1; +} + +/* This should only be called if RL_TIMEOUT_USE_SELECT is defined. */ + +#if defined (HAVE_PSELECT) || defined (HAVE_SELECT) +int +_rl_timeout_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout, const sigset_t *sigmask) +{ + int result; +#if defined (HAVE_PSELECT) + struct timespec ts; +#else + sigset_t origmask; + struct timeval tv; +#endif + int tmout_status; + struct timeval tmout; + unsigned int sec, usec; + + /* When the remaining time for rl_timeout is shorter than the + keyboard input timeout, replace `timeout' with the remaining time + for `rl_timeout' and set `tmout_status = 1'. */ + tmout_status = rl_timeout_remaining (&sec, &usec); + tmout.tv_sec = sec; + tmout.tv_usec = usec; + + if (tmout_status == 0) + _rl_timeout_handle (); + else if (tmout_status == 1) + { + if (timeout == NULL || timercmp (&tmout, timeout, <)) + timeout = &tmout; + else + tmout_status = -1; + } + +#if defined (HAVE_PSELECT) + if (timeout) + { + TIMEVAL_TO_TIMESPEC (timeout, &ts); + result = pselect (nfds, readfds, writefds, exceptfds, &ts, sigmask); + } + else + result = pselect (nfds, readfds, writefds, exceptfds, NULL, sigmask); +#else + if (sigmask) + sigprocmask (SIG_SETMASK, sigmask, &origmask); + + if (timeout) + { + tv.tv_sec = timeout->tv_sec; + tv.tv_usec = timeout->tv_usec; + result = select (nfds, readfds, writefds, exceptfds, &tv); + } + else + result = select (nfds, readfds, writefds, exceptfds, NULL); + + if (sigmask) + sigprocmask (SIG_SETMASK, &origmask, NULL); +#endif + + if (tmout_status == 1 && result == 0) + _rl_timeout_handle (); + + return result; +} +#endif + +static void +_rl_timeout_handle () +{ + if (rl_timeout_event_hook) + (*rl_timeout_event_hook) (); + + RL_SETSTATE(RL_STATE_TIMEOUT); + _rl_abort_internal (); +} + +int +_rl_timeout_handle_sigalrm () +{ +#if defined (RL_TIMEOUT_USE_SIGALRM) + if (timerisunset (&timeout_point)) + return -1; + + /* Reset `timeout_point' to the current time to ensure that later + calls of `rl_timeout_pending ()' return 0 (timeout expired). */ + if (gettimeofday(&timeout_point, 0) != 0) + timerclear (&timeout_point); + + reset_alarm (); + + _rl_timeout_handle (); +#endif + return -1; +} /* **************************************************************** */ /* */ /* Character Input */ @@ -497,6 +775,7 @@ rl_read_key (void) if ((r = rl_gather_tyi ()) < 0) /* XXX - EIO */ { rl_done = 1; + RL_SETSTATE (RL_STATE_DONE); return (errno == EIO ? (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF) : '\n'); } else if (r > 0) /* read something */ @@ -525,11 +804,13 @@ rl_getc (FILE *stream) { int result; unsigned char c; + int fd; #if defined (HAVE_PSELECT) sigset_t empty_set; fd_set readfds; #endif + fd = fileno (stream); while (1) { RL_CHECK_SIGNALS (); @@ -537,23 +818,27 @@ rl_getc (FILE *stream) /* We know at this point that _rl_caught_signal == 0 */ #if defined (__MINGW32__) - if (isatty (fileno (stream))) + if (isatty (fd) return (_getch ()); /* "There is no error return." */ #endif result = 0; -#if defined (HAVE_PSELECT) +#if defined (HAVE_PSELECT) || defined (HAVE_SELECT) + /* At this point, if we have pselect, we're using select/pselect for the + timeouts. We handled MinGW above. */ FD_ZERO (&readfds); - FD_SET (fileno (stream), &readfds); + FD_SET (fd, &readfds); # if defined (HANDLE_SIGNALS) - result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &_rl_orig_sigset); + result = _rl_timeout_select (fd + 1, &readfds, NULL, NULL, NULL, &_rl_orig_sigset); # else sigemptyset (&empty_set); sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &empty_set); - result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &empty_set); + result = _rl_timeout_select (fd + 1, &readfds, NULL, NULL, NULL, &empty_set); # endif /* HANDLE_SIGNALS */ + if (result == 0) + _rl_timeout_handle (); /* check the timeout */ #endif if (result >= 0) - result = read (fileno (stream), &c, sizeof (unsigned char)); + result = read (fd, &c, sizeof (unsigned char)); if (result == sizeof (unsigned char)) return (c); @@ -582,7 +867,7 @@ rl_getc (FILE *stream) if (errno == X_EWOULDBLOCK || errno == X_EAGAIN) { - if (sh_unset_nodelay_mode (fileno (stream)) < 0) + if (sh_unset_nodelay_mode (fd) < 0) return (EOF); continue; } diff --git a/isearch.c b/isearch.c index fdd18bb..33f67d3 100644 --- a/isearch.c +++ b/isearch.c @@ -318,7 +318,7 @@ _rl_search_getchar (_rl_search_cxt *cxt) #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] */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + if (c >= 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX); #endif diff --git a/parens.c b/parens.c index b8c5ac8..57ce704 100644 --- a/parens.c +++ b/parens.c @@ -135,7 +135,11 @@ rl_insert_close (int count, int invoking_key) orig_point = rl_point; rl_point = match_point; (*rl_redisplay_function) (); +# if defined (RL_TIMEOUT_USE_SELECT) + ready = _rl_timeout_select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer, NULL); +# else ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); +# endif rl_point = orig_point; #else /* !HAVE_SELECT */ _rl_insert_char (count, invoking_key); diff --git a/posixtime.h b/posixtime.h new file mode 100644 index 0000000..1d50ab6 --- /dev/null +++ b/posixtime.h @@ -0,0 +1,90 @@ +/* posixtime.h -- wrapper for time.h, sys/times.h mess. */ + +/* Copyright (C) 1999 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#ifndef _POSIXTIME_H_ +#define _POSIXTIME_H_ + +/* include this after config.h */ +/* Some systems require this, mostly for the definition of `struct timezone'. + For example, Dynix/ptx has that definition in rather than + sys/time.h */ +#if defined (TIME_WITH_SYS_TIME) +# include +# include +#else +# if defined (HAVE_SYS_TIME_H) +# include +# else +# include +# endif +#endif + +#if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK) +# if !defined (CLK_TCK) +# if defined (HZ) +# define CLK_TCK HZ +# else +# define CLK_TCK 60 /* 60HZ */ +# endif +# endif /* !CLK_TCK */ +#endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */ + +#if !HAVE_TIMEVAL +struct timeval +{ + time_t tv_sec; + long int tv_usec; +}; +#endif + +#if !HAVE_GETTIMEOFDAY +extern int gettimeofday PARAMS((struct timeval *, void *)); +#endif + +/* These exist on BSD systems, at least. */ +#if !defined (timerclear) +# define timerclear(tvp) do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0) +#endif +#if !defined (timerisset) +# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#endif +#if !defined (timercmp) +# define timercmp(a, b, CMP) \ + (((a)->tv_sec == (b)->tv_sec) ? ((a)->tv_usec CMP (b)->tv_usec) \ + : ((a)->tv_sec CMP (b)->tv_sec)) +#endif + +/* These are non-standard. */ +#if !defined (timerisunset) +# define timerisunset(tvp) ((tvp)->tv_sec == 0 && (tvp)->tv_usec == 0) +#endif +#if !defined (timerset) +# define timerset(tvp, s, u) do { tvp->tv_sec = s; tvp->tv_usec = u; } while (0) +#endif + +#ifndef TIMEVAL_TO_TIMESPEC +# define TIMEVAL_TO_TIMESPEC(tv, ts) \ + do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ + } while (0) +#endif + +#endif /* _POSIXTIME_H_ */ diff --git a/readline.c b/readline.c index de06af1..4002fe5 100644 --- a/readline.c +++ b/readline.c @@ -577,6 +577,15 @@ readline_internal_charloop (void) { (*rl_redisplay_function) (); _rl_want_redisplay = 0; + + /* If we longjmped because of a timeout, handle it here. */ + if (RL_ISSTATE (RL_STATE_TIMEOUT)) + { + RL_SETSTATE (RL_STATE_DONE); + rl_done = 1; + return 1; + } + /* If we get here, we're not being called from something dispatched from _rl_callback_read_char(), which sets up its own value of _rl_top_level (saving and restoring the old, of course), so @@ -1148,6 +1157,9 @@ _rl_subseq_result (int r, Keymap map, int key, int got_subseq) int rl_initialize (void) { + /* Initialize the timeout first to get the precise start time. */ + _rl_timeout_init (); + /* If we have never been called before, initialize the terminal and data structures. */ if (rl_initialized == 0) diff --git a/readline.h b/readline.h index 90b5389..ab33823 100644 --- a/readline.h +++ b/readline.h @@ -448,6 +448,13 @@ extern int rl_read_key (void); extern int rl_getc (FILE *); extern int rl_set_keyboard_input_timeout (int); +/* Functions to set and reset timeouts. */ +extern int rl_set_timeout (unsigned int, unsigned int); +extern int rl_timeout_remaining (unsigned int *, unsigned int *); + +#undef rl_clear_timeout +#define rl_clear_timeout() rl_set_timeout (0, 0) + /* `Public' utility functions . */ extern void rl_extend_line_buffer (int); extern int rl_ding (void); @@ -599,6 +606,8 @@ extern rl_hook_func_t *rl_event_hook; /* The address of a function to call if a read is interrupted by a signal. */ extern rl_hook_func_t *rl_signal_event_hook; +extern rl_hook_func_t *rl_timeout_event_hook; + /* The address of a function to call if Readline needs to know whether or not there is data available from the current input source. */ extern rl_hook_func_t *rl_input_available_hook; @@ -906,6 +915,7 @@ extern int rl_persistent_signal_handlers; #define RL_STATE_REDISPLAYING 0x1000000 /* updating terminal display */ #define RL_STATE_DONE 0x2000000 /* done; accepted line */ +#define RL_STATE_TIMEOUT 0x4000000 #define RL_SETSTATE(x) (rl_readline_state |= (x)) #define RL_UNSETSTATE(x) (rl_readline_state &= ~(x)) diff --git a/rlprivate.h b/rlprivate.h index 7d7c381..86a2912 100644 --- a/rlprivate.h +++ b/rlprivate.h @@ -4,7 +4,7 @@ /* Copyright (C) 1999-2021 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. + for reading lines of text with interactive input and history editing. Readline is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -78,7 +78,7 @@ typedef struct __rl_search_context int search_string_size; char **lines; - char *allocated_line; + char *allocated_line; int hlen; int hindex; @@ -169,7 +169,7 @@ typedef struct __rl_vimotion_context /* fill in more as needed */ /* `Generic' callback data and functions */ -typedef struct __rl_callback_generic_arg +typedef struct __rl_callback_generic_arg { int count; int i1, i2; @@ -259,7 +259,7 @@ extern void _rl_keyseq_cxt_dispose (_rl_keyseq_cxt *); extern void _rl_keyseq_chain_dispose (void); extern int _rl_dispatch_callback (_rl_keyseq_cxt *); - + /* callback.c */ extern _rl_callback_generic_arg *_rl_callback_data_alloc (int); extern void _rl_callback_data_dispose (_rl_callback_generic_arg *); @@ -301,6 +301,13 @@ extern void _rl_insert_typein (int); extern int _rl_unget_char (int); extern int _rl_pushed_input_available (void); +extern int _rl_timeout_init (void); +extern int _rl_timeout_handle_sigalrm (void); +#if defined (_POSIXSELECT_H_) +/* use as a sentinel for fd_set, struct timeval, and sigset_t definitions */ +extern int _rl_timeout_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *, const sigset_t *); +#endif + /* isearch.c */ extern _rl_search_cxt *_rl_scxt_alloc (int, int); extern void _rl_scxt_dispose (_rl_search_cxt *, int); @@ -371,7 +378,7 @@ extern void _rl_internal_char_cleanup (void); extern void _rl_init_executing_keyseq (void); extern void _rl_term_executing_keyseq (void); extern void _rl_end_executing_keyseq (void); -extern void _rl_add_executing_keyseq (int); +extern void _rl_add_executing_keyseq (int); /* rltty.c */ extern int _rl_disable_tty_signals (void); @@ -469,7 +476,7 @@ extern int _rl_vi_domove_motion_cleanup (int, _rl_vimotion_cxt *); /* Use HS_HISTORY_VERSION as the sentinel to see if we've included history.h and so can use HIST_ENTRY */ #if defined (HS_HISTORY_VERSION) -extern void _rl_free_history_entry (HIST_ENTRY *); +extern void _rl_free_history_entry (HIST_ENTRY *); #endif /************************************************************************* diff --git a/rltty.c b/rltty.c index e96fa8f..4a49200 100644 --- a/rltty.c +++ b/rltty.c @@ -692,7 +692,7 @@ rl_deprep_terminal (void) if (terminal_prepped & TPX_BRACKPASTE) { fprintf (rl_outstream, BRACK_PASTE_FINI); - if (_rl_eof_found) + if (_rl_eof_found && (RL_ISSTATE (RL_STATE_TIMEOUT) == 0)) fprintf (rl_outstream, "\n"); } diff --git a/signals.c b/signals.c index 0943c64..2bbec3e 100644 --- a/signals.c +++ b/signals.c @@ -222,6 +222,9 @@ _rl_handle_signal (int sig) switch (sig) { case SIGINT: + /* We will end up blocking SIGTTOU while we are resetting the tty, so + watch out for this if it causes problems. We could prevent this by + setting block_sig to 1 without modifying SET. */ _rl_reset_completion_state (); rl_free_line_state (); #if defined (READLINE_CALLBACKS) @@ -242,8 +245,11 @@ _rl_handle_signal (int sig) this even if we've been stopped on SIGTTOU, since we handle signals when we have returned from the signal handler and the signal is no longer blocked. */ - sigaddset (&set, SIGTTOU); - block_sig = 1; + if (block_sig == 0) + { + sigaddset (&set, SIGTTOU); + block_sig = 1; + } # endif #endif /* SIGTSTP */ /* Any signals that should be blocked during cleanup should go here. */ @@ -261,13 +267,17 @@ _rl_handle_signal (int sig) case SIGTERM: #if defined (SIGALRM) case SIGALRM: + if (sig == SIGALRM) + _rl_timeout_handle_sigalrm (); #endif #if defined (SIGQUIT) case SIGQUIT: #endif +#if defined (HAVE_POSIX_SIGNALS) if (block_sig) sigprocmask (SIG_BLOCK, &set, &oset); +#endif rl_echo_signal_char (sig); rl_cleanup_after_signal (); @@ -283,19 +293,6 @@ _rl_handle_signal (int sig) /* We don't have to bother unblocking the signal because we are not running in a signal handler context. */ -#if 0 -#if defined (HAVE_POSIX_SIGNALS) - /* Make sure this signal is not blocked when we resend it to the - calling application. */ - sigemptyset (&set); - sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); - sigdelset (&set, sig); -#else /* !HAVE_POSIX_SIGNALS */ -# if defined (HAVE_BSD_SIGNALS) - omask = sigblock (0); -# endif /* HAVE_BSD_SIGNALS */ -#endif /* !HAVE_POSIX_SIGNALS */ -#endif #if defined (__EMX__) signal (sig, SIG_ACK); @@ -309,16 +306,6 @@ _rl_handle_signal (int sig) /* We don't need to modify the signal mask now that this is not run in a signal handler context. */ -#if 0 - /* Let the signal that we just sent through if it is blocked. */ -#if defined (HAVE_POSIX_SIGNALS) - sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); -#else /* !HAVE_POSIX_SIGNALS */ -# if defined (HAVE_BSD_SIGNALS) - sigsetmask (omask & ~(sigmask (sig))); -# endif /* HAVE_BSD_SIGNALS */ -#endif /* !HAVE_POSIX_SIGNALS */ -#endif rl_reset_after_signal (); } diff --git a/support/config.guess b/support/config.guess old mode 100755 new mode 100644 diff --git a/support/config.rpath b/support/config.rpath old mode 100755 new mode 100644 diff --git a/support/config.sub b/support/config.sub old mode 100755 new mode 100644 diff --git a/support/install.sh b/support/install.sh old mode 100755 new mode 100644 diff --git a/support/mkdirs b/support/mkdirs old mode 100755 new mode 100644 diff --git a/support/mkdist b/support/mkdist old mode 100755 new mode 100644 index 282431d..133566f --- a/support/mkdist +++ b/support/mkdist @@ -96,6 +96,10 @@ do if [ -n "$mode" ]; then chmod $mode $newdir/$fname + elif [ "$type" = "f" ]; then + chmod $filmode $newdir/$fname + elif [ "$type" = "d" ]; then + chmod $dirmode $newdir/$fname fi done < $MANIFEST diff --git a/support/mkinstalldirs b/support/mkinstalldirs old mode 100755 new mode 100644 diff --git a/support/shlib-install b/support/shlib-install old mode 100755 new mode 100644 diff --git a/support/shobj-conf b/support/shobj-conf index 45e157c..729d847 100644 --- a/support/shobj-conf +++ b/support/shobj-conf @@ -151,13 +151,13 @@ darwin*) darwin[1-7].*) SHOBJ_STATUS=unsupported SHOBJ_LDFLAGS='-dynamic' - SHLIB_XLDFLAGS='-arch_only `/usr/bin/arch` -install_name $(libdir)/`echo $@ | sed "s:\\..*::"`.$(SHLIB_MAJOR).$(SHLIB_LIBSUFF) -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -v' + SHLIB_XLDFLAGS='-install_name $(libdir)/`echo $@ | sed "s:\\..*::"`.$(SHLIB_MAJOR).$(SHLIB_LIBSUFF) -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -v' ;; # Darwin 8 == Mac OS X 10.4; Mac OS X 10.N == Darwin N+4 *) case "${host_os}" in darwin[89]*|darwin1[012]*) - SHOBJ_ARCHFLAGS='-arch_only `/usr/bin/arch`' + SHOBJ_ARCHFLAGS= ;; *) # Mac OS X 10.9 (Mavericks) and later SHOBJ_ARCHFLAGS= diff --git a/text.c b/text.c index 828555d..e9de752 100644 --- a/text.c +++ b/text.c @@ -919,8 +919,11 @@ _rl_overwrite_char (int count, int c) int k; /* Read an entire multibyte character sequence to insert COUNT times. */ + k = 1; if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); + if (k < 0) + return 1; #endif rl_begin_undo_group (); diff --git a/util.c b/util.c index 1576b55..2cd7b3c 100644 --- a/util.c +++ b/util.c @@ -98,7 +98,8 @@ _rl_walphabetic (wchar_t wc) int _rl_abort_internal (void) { - rl_ding (); + if (RL_ISSTATE (RL_STATE_TIMEOUT) == 0) + rl_ding (); /* Don't ring the bell on a timeout */ rl_clear_message (); _rl_reset_argument (); rl_clear_pending_input (); diff --git a/vi_mode.c b/vi_mode.c index 80f82b9..da7350d 100644 --- a/vi_mode.c +++ b/vi_mode.c @@ -2036,6 +2036,9 @@ _rl_vi_callback_change_char (_rl_callback_generic_arg *data) char mb[MB_LEN_MAX+1]; c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + if (c < 0) + return -1; + #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX); @@ -2044,9 +2047,6 @@ _rl_vi_callback_change_char (_rl_callback_generic_arg *data) _rl_vi_last_replacement[0] = c; _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* XXX */ - if (c < 0) - return -1; - _rl_callback_func = 0; _rl_want_redisplay = 1; @@ -2077,6 +2077,8 @@ rl_vi_change_char (int count, int key) else { c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + if (c < 0) + return -1; #ifdef HANDLE_MULTIBYTE if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX); @@ -2113,7 +2115,8 @@ rl_vi_overstrike (int count, int key) if (count > 0) { - _rl_overwrite_char (count, key); + if (_rl_overwrite_char (count, key) != 0) + return (1); vi_replace_count += count; }