----
configure.ac
- bump library version to 7.0 because of addition of rl_callback_sigcleanup
+
+ 8/26
+ ----
+configure.ac,Makefile.in,examples/Makefile.in
+ - remove references to purify
r. Paren matching now works in vi insert mode.
+s. Colored completion prefixes are now displayed using a different color, less
+ likely to collide with files.
+
+t. Fixed a bug that caused vi-mode character search to misbehave when
+ running in callback mode.
+
+u. Fixed a bug that caused output to be delayed when input is coming from a
+ macro in vi-mode.
+
+v. Fixed a bug that caused the vi-mode `.' command to misbehave when redoing
+ a multi-key key sequence via a macro.
+
+w. Fixed a bug that caused problems with applications that supply their own
+ input function when performing completion.
+
+x. When read returns -1/EIO when attempting to read a key, return an error
+ instead of line termination back to the caller.
+
+y. Updated tty auditing feature based on patch from Red Hat.
+
+z. Fixed a bug that could cause the history library to crash on overflows
+ introduced by malicious editing of timestamps in the history file.
+
2. New Features in Readline
a. The history truncation code now uses the same error recovery mechansim as
CP = cp
MV = mv
-PURIFY = @PURIFY@
-
@SET_MAKE@
SHELL = @MAKE_SHELL@
$(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
$(srcdir)/shell.c $(srcdir)/savestring.c $(srcdir)/tilde.c \
$(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
- $(srcdir)/mbutil.c $(srcdir)/xfree.c
+ $(srcdir)/mbutil.c
# The header files for this library.
HSOURCES = $(srcdir)/readline.h $(srcdir)/rldefs.h $(srcdir)/chardefs.h \
CALLBACK_READ_RETURN ();
}
#if defined (VI_MODE)
+ /* States that can occur while in state VIMOTION have to be checked
+ before RL_STATE_VIMOTION */
+ else if (RL_ISSTATE (RL_STATE_CHARSEARCH))
+ {
+ int k;
+
+ k = _rl_callback_data->i2;
+
+ eof = (*_rl_callback_func) (_rl_callback_data);
+ /* If the function `deregisters' itself, make sure the data is
+ cleaned up. */
+ if (_rl_callback_func == 0) /* XXX - just sanity check */
+ {
+ if (_rl_callback_data)
+ {
+ _rl_callback_data_dispose (_rl_callback_data);
+ _rl_callback_data = 0;
+ }
+ }
+
+ /* Messy case where vi motion command can be char search */
+ if (RL_ISSTATE (RL_STATE_VIMOTION))
+ {
+ _rl_vi_domove_motion_cleanup (k, _rl_vimvcxt);
+ _rl_internal_char_cleanup ();
+ CALLBACK_READ_RETURN ();
+ }
+
+ _rl_internal_char_cleanup ();
+ }
else if (RL_ISSTATE (RL_STATE_VIMOTION))
{
eof = _rl_vi_domove_callback (_rl_vimvcxt);
}
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
RL_UNSETSTATE (RL_STATE_MULTIKEY);
+ if (RL_ISSTATE (RL_STATE_CHARSEARCH))
+ RL_UNSETSTATE (RL_STATE_CHARSEARCH);
_rl_callback_func = 0;
}
/* Returns whether any color sequence was printed. */
bool
-_rl_print_color_indicator (char *f)
+_rl_print_color_indicator (const char *f)
{
enum indicator_no colored_filetype;
COLOR_EXT_TYPE *ext; /* Color extension */
arg_directory
};
-/* Prefix color, currently same as directory */
-#define C_PREFIX C_DIR
+/* Prefix color, currently same as socket */
+#define C_PREFIX C_SOCK
extern void _rl_put_indicator (const struct bin_str *ind);
extern void _rl_set_normal_color (void);
extern bool _rl_print_prefix_color (void);
-extern bool _rl_print_color_indicator (char *f);
+extern bool _rl_print_color_indicator (const char *f);
extern void _rl_prep_non_filename_text (void);
#endif /* !_COLORS_H_ */
#endif
#if defined (COLOR_SUPPORT)
-static int colored_stat_start PARAMS((char *));
+static int colored_stat_start PARAMS((const char *));
static void colored_stat_end PARAMS((void));
static int colored_prefix_start PARAMS((void));
static void colored_prefix_end PARAMS((void));
static int _rl_internal_pager PARAMS((int));
static char *printable_part PARAMS((char *));
static int fnwidth PARAMS((const char *));
-static int fnprint PARAMS((const char *, int));
+static int fnprint PARAMS((const char *, int, const char *));
static int print_filename PARAMS((char *, char *, int));
static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
completions. The colors used are taken from $LS_COLORS, if set. */
int _rl_colored_stats = 0;
+/* Non-zero means to use a color (currently magenta) to indicate the common
+ prefix of a set of possible word completions. */
int _rl_colored_completion_prefix = 1;
#endif
#if defined (COLOR_SUPPORT)
static int
colored_stat_start (filename)
- char *filename;
+ const char *filename;
{
_rl_set_normal_color ();
return (_rl_print_color_indicator (filename));
if (temp == 0 || *temp == '\0')
return (pathname);
+ else if (temp[1] == 0 && temp == pathname)
+ return (pathname);
/* If the basename is NULL, we might have a pathname like '/usr/src/'.
Look for a previous slash and, if one is found, return the portion
following that slash. If there's no previous slash, just return the
#define ELLIPSIS_LEN 3
static int
-fnprint (to_print, prefix_bytes)
+fnprint (to_print, prefix_bytes, real_pathname)
const char *to_print;
int prefix_bytes;
+ const char *real_pathname;
{
int printed_len, w;
const char *s;
printed_len = common_prefix_len = 0;
/* Don't print only the ellipsis if the common prefix is one of the
- possible completions */
- if (to_print[prefix_bytes] == '\0')
+ possible completions. Only cut off prefix_bytes if we're going to be
+ printing the ellipsis, which takes precedence over coloring the
+ completion prefix (see print_filename() below). */
+ if (_rl_completion_prefix_display_length > 0 && to_print[prefix_bytes] == '\0')
prefix_bytes = 0;
+#if defined (COLOR_SUPPORT)
+ if (_rl_colored_stats && (prefix_bytes == 0 || _rl_colored_completion_prefix <= 0))
+ colored_stat_start (real_pathname);
+#endif
+
if (prefix_bytes && _rl_completion_prefix_display_length > 0)
{
char ellipsis;
}
if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len)
{
+#if defined (COLOR_SUPPORT)
/* printed bytes = s - to_print */
/* printed bytes should never be > but check for paranoia's sake */
colored_prefix_end ();
+ if (_rl_colored_stats)
+ colored_stat_start (real_pathname); /* XXX - experiment */
+#endif
common_prefix_len = 0;
}
}
+#if defined (COLOR_SUPPORT)
+ /* XXX - unconditional for now */
+ if (_rl_colored_stats)
+ colored_stat_end ();
+#endif
+
return printed_len;
}
/* Defer printing if we want to prefix with a color indicator */
if (_rl_colored_stats == 0 || rl_filename_completion_desired == 0)
#endif
- printed_len = fnprint (to_print, prefix_bytes);
+ printed_len = fnprint (to_print, prefix_bytes, to_print);
if (rl_filename_completion_desired && (
#if defined (VISIBLE_STATS)
extension_char = '/';
}
+ /* Move colored-stats code inside fnprint() */
#if defined (COLOR_SUPPORT)
if (_rl_colored_stats)
- {
- colored_stat_start (new_full_pathname);
- printed_len = fnprint (to_print, prefix_bytes);
- colored_stat_end ();
- }
+ printed_len = fnprint (to_print, prefix_bytes, new_full_pathname);
#endif
xfree (new_full_pathname);
if (_rl_complete_mark_directories && path_isdir (s))
extension_char = '/';
+ /* Move colored-stats code inside fnprint() */
#if defined (COLOR_SUPPORT)
if (_rl_colored_stats)
- {
- colored_stat_start (s);
- printed_len = fnprint (to_print, prefix_bytes);
- colored_stat_end ();
- }
+ printed_len = fnprint (to_print, prefix_bytes, s);
#endif
-
}
xfree (s);
/* Define if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
+/* Define if you have the <libaudit.h> header file. */
+#undef HAVE_LIBAUDIT_H
+
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
LOCAL_LDFLAGS
LOCAL_CFLAGS
BUILD_DIR
-PURIFY
SHARED_INSTALL_TARGET
STATIC_INSTALL_TARGET
SHARED_TARGET
ac_user_opts='
enable_option_checking
with_curses
-with_purify
enable_multibyte
enable_shared
enable_static
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-curses use the curses library instead of the termcap
library
- --with-purify configure to postprocess with purify
Some influential environment variables:
CC C compiler command
opt_curses=no
-opt_purify=no
# Check whether --with-curses was given.
fi
-# Check whether --with-purify was given.
-if test "${with_purify+set}" = set; then :
- withval=$with_purify; opt_purify=$withval
-fi
-
-
if test "$opt_curses" = "yes"; then
prefer_curses=yes
fi
-if test "$opt_purify" = yes; then
- PURIFY="purify"
-else
- PURIFY=
-fi
-
opt_multibyte=yes
opt_static_libs=yes
opt_shared_libs=yes
fi
+for ac_header in libaudit.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "libaudit.h" "ac_cv_header_libaudit_h" "$ac_includes_default"
+if test "x$ac_cv_header_libaudit_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBAUDIT_H 1
+_ACEOF
+
+fi
+
+done
+
ac_fn_c_check_decl "$LINENO" "AUDIT_USER_TTY" "ac_cv_have_decl_AUDIT_USER_TTY" "#include <linux/audit.h>
"
if test "x$ac_cv_have_decl_AUDIT_USER_TTY" = xyes; then :
-
ac_config_files="$ac_config_files Makefile doc/Makefile examples/Makefile shlib/Makefile readline.pc"
ac_config_commands="$ac_config_commands default"
dnl configure defaults
opt_curses=no
-opt_purify=no
dnl arguments to configure
AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval)
-AC_ARG_WITH(purify, AC_HELP_STRING([--with-purify], [configure to postprocess with purify]), opt_purify=$withval)
if test "$opt_curses" = "yes"; then
prefer_curses=yes
fi
-if test "$opt_purify" = yes; then
- PURIFY="purify"
-else
- PURIFY=
-fi
-
dnl option parsing for optional features
opt_multibyte=yes
opt_static_libs=yes
BASH_STRUCT_DIRENT_D_INO
BASH_STRUCT_DIRENT_D_FILENO
+AC_CHECK_HEADERS(libaudit.h)
AC_CHECK_DECLS([AUDIT_USER_TTY],,, [[#include <linux/audit.h>]])
dnl yuck
*) ;;
esac
-AC_SUBST(PURIFY)
AC_SUBST(BUILD_DIR)
AC_SUBST(CFLAGS)
int *lbreaks;
int lbsize;
#if defined (HANDLE_MULTIBYTE)
- int *wrapped_line;
int wbsize;
+ int *wrapped_line;
#endif
};
<HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!-- Created on July, 1 2015 by texi2html 1.64 -->
+<!-- Created on September, 29 2015 by texi2html 1.64 -->
<!--
Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
Karl Berry <karl@freefriends.org>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="history.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<H1>About this document</H1>
-This document was generated by <I>Chet Ramey</I> on <I>July, 1 2015</I>
+This document was generated by <I>Chet Ramey</I> on <I>September, 29 2015</I>
using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
"><I>texi2html</I></A>
<P></P>
<BR>
<FONT SIZE="-1">
This document was generated
-by <I>Chet Ramey</I> on <I>July, 1 2015</I>
+by <I>Chet Ramey</I> on <I>September, 29 2015</I>
using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
"><I>texi2html</I></A>
-This is history.info, produced by makeinfo version 5.2 from
+This is history.info, produced by makeinfo version 6.0 from
history.texi.
This document describes the GNU History library (version 6.4, 28 May
%!PS-Adobe-2.0
-%%Creator: dvips(k) 5.994 Copyright 2014 Radical Eye Software
+%%Creator: dvips(k) 5.995 Copyright 2015 Radical Eye Software
%%Title: history.dvi
-%%CreationDate: Wed Jul 1 10:32:46 2015
+%%CreationDate: Tue Sep 29 09:50:39 2015
%%Pages: 24
%%PageOrder: Ascend
%%BoundingBox: 0 0 612 792
%DVIPSWebPage: (www.radicaleye.com)
%DVIPSCommandLine: dvips -D 600 -t letter -o history.ps history.dvi
%DVIPSParameters: dpi=600
-%DVIPSSource: TeX output 2015.07.01:1032
+%DVIPSSource: TeX output 2015.09.29:0950
%%BeginProcSet: tex.pro 0 0
%!
/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S
arguments to a previous command into the current input line, or
fix errors in previous commands quickly.
+@ifset BashFeatures
+History expansion is performed immediately after a complete line
+is read, before the shell breaks it into words.
+@end ifset
+
History expansion takes place in two parts. The first is to determine
which line from the history list should be used during substitution.
The second is to select portions of that line for inclusion into the
history expansion character, which is @samp{!} by default.
@ifset BashFeatures
Only @samp{\} and @samp{'} may be used to escape the history expansion
-character.
+character, but the history expansion character is
+also treated as quoted if it immediately precedes the closing double quote
+in a double-quoted string.
@end ifset
@ifset BashFeatures
CCFLAGS = $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LDFLAGS = -g -L.. @LDFLAGS@
-PURIFY = @PURIFY@
-
READLINE_LIB = ../libreadline.a
HISTORY_LIB = ../libhistory.a
-rmdir $(DESTDIR)$(installdir)
rl$(EXEEXT): rl.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rl.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rl.o $(READLINE_LIB) $(TERMCAP_LIB)
rlbasic$(EXEEXT): rlbasic.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rlbasic.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rlbasic.o $(READLINE_LIB) $(TERMCAP_LIB)
rlcat$(EXEEXT): rlcat.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rlcat.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rlcat.o $(READLINE_LIB) $(TERMCAP_LIB)
rlevent$(EXEEXT): rlevent.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rlevent.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rlevent.o $(READLINE_LIB) $(TERMCAP_LIB)
fileman$(EXEEXT): fileman.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ fileman.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ fileman.o $(READLINE_LIB) $(TERMCAP_LIB)
rltest$(EXEEXT): rltest.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rltest.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rltest.o $(READLINE_LIB) $(TERMCAP_LIB)
rl-callbacktest$(EXEEXT): rl-callbacktest.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rl-callbacktest.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rl-callbacktest.o $(READLINE_LIB) $(TERMCAP_LIB)
rlptytest$(EXEEXT): rlptytest.o $(READLINE_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ rlptytest.o $(READLINE_LIB) $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ rlptytest.o $(READLINE_LIB) $(TERMCAP_LIB)
rlversion$(EXEEXT): rlversion.o $(READLINE_LIB)
$(CC) $(LDFLAGS) -o $@ rlversion.o $(READLINE_LIB) $(TERMCAP_LIB)
histexamp$(EXEEXT): histexamp.o $(HISTORY_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ histexamp.o -lhistory $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ histexamp.o -lhistory $(TERMCAP_LIB)
hist_erasedups$(EXEEXT): hist_erasedups.o $(HISTORY_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ hist_erasedups.o -lhistory $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ hist_erasedups.o -lhistory $(TERMCAP_LIB)
hist_purgecmd$(EXEEXT): hist_purgecmd.o $(HISTORY_LIB)
- $(PURIFY) $(CC) $(LDFLAGS) -o $@ hist_purgecmd.o -lhistory $(TERMCAP_LIB)
+ $(CC) $(LDFLAGS) -o $@ hist_purgecmd.o -lhistory $(TERMCAP_LIB)
clean mostlyclean:
$(RM) $(OBJECTS) $(OTHEROBJ)
extern char *xmalloc PARAMS((size_t));
+void initialize_readline PARAMS((void));
+void too_dangerous PARAMS((char *));
+
+int execute_line PARAMS((char *));
+int valid_argument PARAMS((char *, char *));
+
/* The names of functions that actually do the manipulation. */
int com_list PARAMS((char *));
int com_view PARAMS((char *));
return (r);
}
+int
main (argc, argv)
int argc;
char **argv;
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
+void
initialize_readline ()
{
/* Allow conditional parsing of the ~/.inputrc file. */
static char syscom[1024];
/* List the file(s) named in arg. */
+int
com_list (arg)
char *arg;
{
return (system (syscom));
}
+int
com_view (arg)
char *arg;
{
return (system (syscom));
}
+int
com_rename (arg)
char *arg;
{
return (1);
}
+int
com_stat (arg)
char *arg;
{
return (0);
}
+int
com_delete (arg)
char *arg;
{
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
+int
com_help (arg)
char *arg;
{
}
/* Change to the directory ARG. */
+int
com_cd (arg)
char *arg;
{
}
/* Print out the current working directory. */
+int
com_pwd (ignore)
char *ignore;
{
}
/* The user wishes to quit using this program. Just set DONE non-zero. */
+int
com_quit (arg)
char *arg;
{
}
/* Function which tells you that you can't do this. */
+void
too_dangerous (caller)
char *caller;
{
# include <config.h>
#endif
+#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <string.h>
#if defined (READLINE_LIBRARY)
# include "readline.h"
# include <readline/readline.h>
#endif
+int
main()
{
printf ("%s\n", rl_library_version ? rl_library_version : "unknown");
# include <unistd.h>
#endif
+#include <errno.h>
+
#include "history.h"
#include "histlib.h"
#include "xmalloc.h"
+#if !defined (errno)
+extern int errno;
+#endif
+
/* How big to make the_history when we first allocate it. */
#define DEFAULT_HISTORY_INITIAL_SIZE 502
ts = hist->timestamp;
if (ts[0] != history_comment_char)
return 0;
+ errno = 0;
t = (time_t) strtol (ts + 1, (char **)NULL, 10); /* XXX - should use strtol() here */
+ if (errno == ERANGE)
+ return (time_t)0;
return t;
}
}
}
- temp = alloc_history_entry (string, hist_inittime ());
+ temp = alloc_history_entry ((char *)string, hist_inittime ());
the_history[history_length] = (HIST_ENTRY *)NULL;
the_history[history_length - 1] = temp;
WHICH >= 0 means to replace that particular history entry's data, as
long as it matches OLD. */
void
-replace_history_data (which, old, new)
+_hs_replace_history_data (which, old, new)
int which;
histdata_t *old, *new;
{
elements are numbered from 0. */
extern HIST_ENTRY *remove_history PARAMS((int));
+/* Allocate a history entry consisting of STRING and TIMESTAMP and return
+ a pointer to it. */
+extern HIST_ENTRY *alloc_history_entry PARAMS((char *, char *));
+
+/* Copy the history entry H, but not the (opaque) data pointer */
+extern HIST_ENTRY *copy_history_entry PARAMS((HIST_ENTRY *));
+
/* Free the history entry H and return any application-specific data
associated with it. */
extern histdata_t free_history_entry PARAMS((HIST_ENTRY *));
extern int history_base;
extern int history_length;
extern int history_max_entries;
+extern int history_offset;
extern int history_lines_read_from_file;
extern int history_lines_written_to_file;
/* input.c -- character input functions for readline. */
-/* Copyright (C) 1994-2013 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2015 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.
#endif
result = -1;
-#if defined (FIONREAD)
errno = 0;
+#if defined (FIONREAD)
result = ioctl (tty, FIONREAD, &chars_avail);
if (result == -1 && errno == EIO)
return -1;
fcntl (tty, F_SETFL, tem);
if (chars_avail == -1 && errno == EAGAIN)
return 0;
+ if (chars_avail == -1 && errno == EIO)
+ return -1;
if (chars_avail == 0) /* EOF */
{
rl_stuff_char (EOF);
if ((r = rl_gather_tyi ()) < 0) /* XXX - EIO */
{
rl_done = 1;
- return ('\n');
+ return (errno == EIO ? (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF) : '\n');
}
else if (r > 0) /* read something */
continue;
int slot;
/* First, find the slot to work with. */
- if (_rl_last_command_was_kill == 0)
+ if (_rl_last_command_was_kill == 0 || rl_kill_ring == 0)
{
/* Get a new slot. */
if (rl_kill_ring == 0)
/* If we see a key bound to `universal-argument' after seeing digits,
it ends the argument but is otherwise ignored. */
- if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
+ if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
{
if ((cxt & NUM_SAWDIGITS) == 0)
{
int c, r;
c = _rl_arg_getchar ();
+ if (c < 0)
+ return (1); /* EOF */
if (_rl_argcxt & NUM_READONE)
{
#endif
/* Flags word encapsulating the current readline state. */
-int rl_readline_state = RL_STATE_NONE;
+unsigned long rl_readline_state = RL_STATE_NONE;
/* The current offset in the current input line. */
int rl_point;
RL_SETSTATE (RL_STATE_CALLBACK);
#endif
-#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
+#if HAVE_DECL_AUDIT_USER_TTY && defined (HAVE_LIBAUDIT_H) && defined (ENABLE_TTY_AUDIT_SUPPORT)
if (value)
_rl_audit_tty (value);
#endif
/* Special case rl_do_lowercase_version (). */
if (func == rl_do_lowercase_version)
/* Should we do anything special if key == ANYOTHERKEY? */
- return (_rl_dispatch (_rl_to_lower (key), map));
+ return (_rl_dispatch (_rl_to_lower ((unsigned char)key), map));
rl_executing_keymap = map;
rl_executing_key = key;
default) or a timeout determined by the value of `keyseq-timeout' */
/* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
takes microseconds, so multiply by 1000 */
- if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
- && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
+ if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap &&
+ (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
+ _rl_pushed_input_available () == 0 &&
+ _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
#endif
/* Allocate new context here. Use linked contexts (linked through
cxt->ocxt) to simulate recursion */
#if defined (READLINE_CALLBACKS)
+# if defined (VI_MODE)
+ /* If we're redoing a vi mode command and we know there is a shadowed
+ function corresponding to this key, just call it -- all the redoable
+ vi mode commands already have all the input they need, and rl_vi_redo
+ assumes that one call to rl_dispatch is sufficient to complete the
+ command. */
+ if (_rl_vi_redoing && RL_ISSTATE (RL_STATE_CALLBACK) &&
+ map[ANYOTHERKEY].function != 0)
+ return (_rl_subseq_result (-2, map, key, got_subseq));
+# endif
if (RL_ISSTATE (RL_STATE_CALLBACK))
{
/* Return 0 only the first time, to indicate success to
/* Tentative inter-character timeout for potential multi-key
sequences? If no input within timeout, abort sequence and
act as if we got non-matching input. */
- /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued[B
takes microseconds, so multiply by 1000 */
if (_rl_keyseq_timeout > 0 &&
(RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
}
break;
}
+
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
key != ANYOTHERKEY &&
type = m[ANYOTHERKEY].type;
func = m[ANYOTHERKEY].function;
if (type == ISFUNC && func == rl_do_lowercase_version)
- r = _rl_dispatch (_rl_to_lower (key), map);
+ r = _rl_dispatch (_rl_to_lower ((unsigned char)key), map);
else if (type == ISFUNC)
{
/* If we shadowed a function, whatever it is, we somehow need a
m[key].type = type;
m[key].function = func;
- r = _rl_dispatch (key, m);
+ /* Don't change _rl_dispatching_keymap, set it here */
+ _rl_dispatching_keymap = map; /* previous map */
+ r = _rl_dispatch_subseq (key, m, 0);
m[key].type = nt;
m[key].function = nf;
}
extern int rl_gnu_readline_p;
/* Flags word encapsulating the current readline state. */
-extern int rl_readline_state;
+extern unsigned long rl_readline_state;
/* Says which editing mode readline is currently using. 1 means emacs mode;
0 means vi mode. */
#define RL_STATE_VIMOTION 0x0100000 /* reading vi motion arg */
#define RL_STATE_MULTIKEY 0x0200000 /* reading multiple-key command */
#define RL_STATE_VICMDONCE 0x0400000 /* entered vi command mode at least once */
-#define RL_STATE_REDISPLAYING 0x0800000 /* updating terminal display */
+#define RL_STATE_CHARSEARCH 0x0800000 /* vi mode char search */
+#define RL_STATE_REDISPLAYING 0x1000000 /* updating terminal display */
-#define RL_STATE_DONE 0x1000000 /* done; accepted line */
+#define RL_STATE_DONE 0x2000000 /* done; accepted line */
#define RL_SETSTATE(x) (rl_readline_state |= (x))
#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
int point;
int end;
int mark;
- char *buffer;
int buflen;
+ char *buffer;
UNDO_LIST *ul;
char *prompt;
int edmode;
char *kseq;
int kseqlen;
+
+ int pendingin;
FILE *inf;
FILE *outf;
- int pendingin;
char *macro;
/* signal state */
/* Define this if you want to enable code that talks to the Linux kernel
tty auditing system. */
-#define ENABLE_TTY_AUDIT_SUPPORT
+/* #define ENABLE_TTY_AUDIT_SUPPORT */
/* Defaults for the various editing mode indicators, inserted at the beginning
of the last (maybe only) line of the prompt if show-mode-in-prompt is on */
int flags;
int subseq_arg;
int subseq_retval; /* XXX */
- Keymap dmap;
+ int okey;
+ Keymap dmap;
Keymap oldmap;
- int okey;
+
struct __rl_keyseq_context *ocxt;
int childval;
} _rl_keyseq_cxt;
extern int _rl_vi_motion_command PARAMS((int));
extern void _rl_vi_done_inserting PARAMS((void));
extern int _rl_vi_domove_callback PARAMS((_rl_vimotion_cxt *));
+extern int _rl_vi_domove_motion_cleanup PARAMS((int, _rl_vimotion_cxt *));
/*************************************************************************
* Undocumented private variables *
/* vi_mode.c */
extern int _rl_vi_last_command;
+extern int _rl_vi_redoing;
extern _rl_vimotion_cxt *_rl_vimvcxt;
#endif /* _RL_PRIVATE_H_ */
extern HIST_ENTRY *_rl_saved_line_for_history;
/* Functions imported from the rest of the library. */
-extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
+extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
static char *noninc_search_string = (char *) NULL;
static int noninc_history_pos;
$(topdir)/shell.c $(topdir)/savestring.c $(topdir)/tilde.c \
$(topdir)/text.c $(topdir)/misc.c $(topdir)/compat.c \
$(topdir)/colors.c $(topdir)/parse-colors.c \
- $(topdir)/mbutil.c $(topdir)/xfree.c
+ $(topdir)/mbutil.c
# The header files for this library.
HSOURCES = $(topdir)/readline.h $(topdir)/rldefs.h $(topdir)/chardefs.h \
while (ch >= 0x20 && ch < 0x40);
RL_UNSETSTATE (RL_STATE_MOREINPUT);
- return 0;
+ return (ch < 0);
}
int
RL_SETSTATE(RL_STATE_MOREINPUT);
ch = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ if (ch < 0)
+ return (1);
switch (_rl_to_upper (ch))
{
}
if (n != (unsigned short)-2) /* -2 = sentinel value for having inserted N */
- r = rl_execute_next (n);
+ {
+ /* setting rl_pending_input inhibits setting rl_last_func so we do it
+ ourselves here */
+ rl_last_func = rl_insert;
+ r = rl_execute_next (n);
+ }
return r;
}
#include "rlprivate.h"
#include "xmalloc.h"
-extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
+extern void _hs_replace_history_data PARAMS((int, histdata_t *, histdata_t *));
/* Non-zero tells rl_delete_text and rl_insert_text to not add to
the undo list. */
orig_list = rl_undo_list;
_rl_free_undo_list (rl_undo_list);
rl_undo_list = (UNDO_LIST *)NULL;
- replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
+ _hs_replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
}
UNDO_LIST *
xfree (temp);
}
- replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
+ _hs_replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
xfree (release);
}
#endif /* DEBUG */
-#if HAVE_DECL_AUDIT_USER_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
+#if HAVE_DECL_AUDIT_USER_TTY && defined (HAVE_LIBAUDIT_H) && defined (ENABLE_TTY_AUDIT_SUPPORT)
#include <sys/socket.h>
+#include <libaudit.h>
#include <linux/audit.h>
#include <linux/netlink.h>
_rl_audit_tty (string)
char *string;
{
+ struct audit_message req;
struct sockaddr_nl addr;
- struct msghdr msg;
- struct nlmsghdr nlm;
- struct iovec iov[2];
size_t size;
int fd;
- fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
+ fd = socket (PF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
if (fd < 0)
return;
size = strlen (string) + 1;
- nlm.nlmsg_len = NLMSG_LENGTH (size);
- nlm.nlmsg_type = AUDIT_USER_TTY;
- nlm.nlmsg_flags = NLM_F_REQUEST;
- nlm.nlmsg_seq = 0;
- nlm.nlmsg_pid = 0;
+ if (NLMSG_SPACE (size) > MAX_AUDIT_MESSAGE_LENGTH)
+ return;
- iov[0].iov_base = &nlm;
- iov[0].iov_len = sizeof (nlm);
- iov[1].iov_base = string;
- iov[1].iov_len = size;
+ memset (&req, 0, sizeof(req));
+ req.nlh.nlmsg_len = NLMSG_SPACE (size);
+ req.nlh.nlmsg_type = AUDIT_USER_TTY;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST;
+ req.nlh.nlmsg_seq = 0;
+ if (size && string)
+ memcpy (NLMSG_DATA(&req.nlh), string, size);
+ memset (&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = 0;
addr.nl_groups = 0;
- msg.msg_name = &addr;
- msg.msg_namelen = sizeof (addr);
- msg.msg_iov = iov;
- msg.msg_iovlen = 2;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- (void)sendmsg (fd, &msg, 0);
+ sendto (fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr));
close (fd);
}
#endif
_rl_vimotion_cxt *_rl_vimvcxt = 0;
+/* Non-zero indicates we are redoing a vi-mode command with `.' */
+int _rl_vi_redoing;
+
/* Non-zero means enter insertion mode. */
static int _rl_vi_doing_insert;
static int _rl_vi_last_key_before_insert;
-static int vi_redoing;
-
/* Text modification commands. These are the `redoable' commands. */
static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
}
r = 0;
- vi_redoing = 1;
+ _rl_vi_redoing = 1;
/* If we're redoing an insert with `i', stuff in the inserted text
and do not go into insertion mode. */
if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
}
else
r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
- vi_redoing = 0;
+
+ _rl_vi_redoing = 0;
return (r);
}
rl_domove_motion_callback (m)
_rl_vimotion_cxt *m;
{
- int c, save, r;
- int old_end;
+ int c;
_rl_vi_last_motion = c = m->motion;
/* Append a blank character temporarily so that the motion routines
- work right at the end of the line. */
- old_end = rl_end;
+ work right at the end of the line. Original value of rl_end is saved
+ as m->end. */
rl_line_buffer[rl_end++] = ' ';
rl_line_buffer[rl_end] = '\0';
_rl_dispatch (c, _rl_keymap);
- /* Remove the blank that we added. */
- rl_end = old_end;
+#if defined (READLINE_CALLBACKS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ /* Messy case where char search can be vi motion command; see rest of
+ details in callback.c. vi_char_search and callback_char_search just
+ set and unset the CHARSEARCH state. This is where any vi motion
+ command that needs to set its own state should be handled, with any
+ corresponding code to manage that state in callback.c */
+ if (RL_ISSTATE (RL_STATE_CHARSEARCH))
+ return 0;
+ else
+ return (_rl_vi_domove_motion_cleanup (c, m));
+ }
+#endif
+
+ return (_rl_vi_domove_motion_cleanup (c, m));
+}
+
+int
+_rl_vi_domove_motion_cleanup (c, m)
+ int c;
+ _rl_vimotion_cxt *m;
+{
+ int r;
+
+ /* Remove the blank that we added in rl_domove_motion_callback. */
+ rl_end = m->end;
rl_line_buffer[rl_end] = '\0';
if (rl_point > rl_end)
rl_point = rl_end;
/* No change in position means the command failed. */
if (rl_mark == rl_point)
- return (-1);
+ {
+ RL_UNSETSTATE (RL_STATE_VIMOTION);
+ return (-1);
+ }
/* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
word. If we are not at the end of the line, and we are on a
int c, r;
m->motion = c = rl_vi_domove_getchar (m);
- /* XXX - what to do if this returns -1? Should we return 1 for eof to
- callback code? */
+ if (c < 0)
+ return 1; /* EOF */
r = rl_domove_read_callback (m);
return ((r == 0) ? r : 1); /* normalize return values */
_rl_vimvcxt->motion = '$';
r = rl_domove_motion_callback (_rl_vimvcxt);
}
- else if (vi_redoing && _rl_vi_last_motion != 'd') /* `dd' is special */
+ else if (_rl_vi_redoing && _rl_vi_last_motion != 'd') /* `dd' is special */
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
r = rl_domove_motion_callback (_rl_vimvcxt);
}
- else if (vi_redoing) /* handle redoing `dd' here */
+ else if (_rl_vi_redoing) /* handle redoing `dd' here */
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
rl_mark = rl_end;
if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
rl_point = m->start;
- if (vi_redoing)
+ if (_rl_vi_redoing)
{
if (vi_insert_buffer && *vi_insert_buffer)
rl_begin_undo_group ();
_rl_vimvcxt->motion = '$';
r = rl_domove_motion_callback (_rl_vimvcxt);
}
- else if (vi_redoing && _rl_vi_last_motion != 'c') /* `cc' is special */
+ else if (_rl_vi_redoing && _rl_vi_last_motion != 'c') /* `cc' is special */
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
r = rl_domove_motion_callback (_rl_vimvcxt);
}
- else if (vi_redoing) /* handle redoing `cc' here */
+ else if (_rl_vi_redoing) /* handle redoing `cc' here */
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
rl_mark = rl_end;
_rl_vimvcxt->motion = '$';
r = rl_domove_motion_callback (_rl_vimvcxt);
}
- else if (vi_redoing && _rl_vi_last_motion != 'y') /* `yy' is special */
+ else if (_rl_vi_redoing && _rl_vi_last_motion != 'y') /* `yy' is special */
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
r = rl_domove_motion_callback (_rl_vimvcxt);
}
- else if (vi_redoing) /* handle redoing `yy' here */
+ else if (_rl_vi_redoing) /* handle redoing `yy' here */
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
rl_mark = rl_end;
#endif
if (c <= 0)
- return -1;
+ {
+ RL_UNSETSTATE (RL_STATE_CHARSEARCH);
+ return -1;
+ }
#if !defined (HANDLE_MULTIBYTE)
_rl_vi_last_search_char = c;
_rl_callback_func = 0;
_rl_want_redisplay = 1;
+ RL_UNSETSTATE (RL_STATE_CHARSEARCH);
#if defined (HANDLE_MULTIBYTE)
return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
break;
}
- if (vi_redoing)
+ if (_rl_vi_redoing)
{
/* set target and tlen below */
}
{
_rl_callback_data = _rl_callback_data_alloc (count);
_rl_callback_data->i1 = _rl_cs_dir;
+ _rl_callback_data->i2 = key;
_rl_callback_func = _rl_vi_callback_char_search;
+ RL_SETSTATE (RL_STATE_CHARSEARCH);
return (0);
}
#endif
int c;
char mb[MB_LEN_MAX];
- if (vi_redoing)
+ if (_rl_vi_redoing)
{
c = _rl_vi_last_replacement;
mb[0] = c;
int count, key;
{
/* If we are redoing, rl_vi_change_to will stuff the last motion char */
- if (vi_redoing == 0)
+ if (_rl_vi_redoing == 0)
rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
return (rl_vi_change_to (count, 'c'));