posixjmp.h f
posixselect.h f
posixstat.h f
+posixtime.h f
readline.h f
rlconf.h f
rldefs.h 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
(*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 ();
}
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])
/* 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
/* 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
/* 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
/* Define if you have the <sys/stream.h> header file. */
#undef HAVE_SYS_STREAM_H
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
/* Define if you have the <termcap.h> header file. */
#undef HAVE_TERMCAP_H
/* Define if you have <linux/audit.h> 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
#undef HAVE_STRUCT_DIRENT_D_NAMLEN
+#undef HAVE_TIMEVAL
+
#undef HAVE_BSD_SIGNALS
#undef HAVE_POSIX_SIGNALS
#! /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.
#
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 <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+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"
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"
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"
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 <sys/time.h>
+ #endif
+ #include <time.h>
+
+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 :
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-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)
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)
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,,,
[[
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 <linux/audit.h>]])
@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
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
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
@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
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
@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
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
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)
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
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
--- /dev/null
+./rl-timeout readline1 0.5
+./rl-timeout readline2 0.25
+
+./rl-timeout callback1 0.5
+./rl-timeout callback2 0.5
+
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>.
+*/
+
+/* Standard include files. stdio.h is required. */
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+
+/* Used for select(2) */
+#include <sys/types.h>
+#include <sys/select.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+/* Standard readline include files. */
+#if defined (READLINE_LIBRARY)
+# include "readline.h"
+# include "history.h"
+#else
+# include <readline/readline.h>
+# include <readline/history.h>
+#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;
+}
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'.
#include <signal.h>
#include "posixselect.h"
+#include "posixtime.h"
#if defined (FIONREAD_IN_SYS_IOCTL)
# include <sys/ioctl.h>
/* 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;
#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 */
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
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;
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)
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 */
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 */
{
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 ();
/* 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);
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;
}
#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
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);
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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 <time.h> rather than
+ sys/time.h */
+#if defined (TIME_WITH_SYS_TIME)
+# include <sys/time.h>
+# include <time.h>
+#else
+# if defined (HAVE_SYS_TIME_H)
+# include <sys/time.h>
+# else
+# include <time.h>
+# 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_ */
{
(*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
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)
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);
/* 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;
#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))
/* 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
int search_string_size;
char **lines;
- char *allocated_line;
+ char *allocated_line;
int hlen;
int hindex;
/* 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;
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 *);
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);
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);
/* 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
/*************************************************************************
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");
}
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)
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. */
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 ();
/* 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);
/* 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 ();
}
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
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=
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 ();
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 ();
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);
_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;
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);
if (count > 0)
{
- _rl_overwrite_char (count, key);
+ if (_rl_overwrite_char (count, key) != 0)
+ return (1);
vi_replace_count += count;
}