From 6fecd62c1ea649a0bcfd4f7b510e76afbeb46485 Mon Sep 17 00:00:00 2001
From: stefanf <stefanf@FreeBSD.org>
Date: Sun, 7 Aug 2005 20:55:59 +0000
Subject: [PATCH] Sync libedit with recent NetBSD developments.  Including
 improvements to the vi-mode, removal of clause 3, cleanups and the export of
 the tokenization functions.

Not included: config.h, filecomplete.{c,h}
---
 include/histedit.h      |  50 ++-
 lib/libedit/Makefile    |   8 +-
 lib/libedit/TEST/test.c |  82 ++--
 lib/libedit/chared.c    | 343 ++++++++++-------
 lib/libedit/chared.h    |  54 +--
 lib/libedit/common.c    | 217 +++++------
 lib/libedit/editline.3  | 190 ++++++++-
 lib/libedit/editrc.5    |  36 +-
 lib/libedit/el.c        | 127 ++++--
 lib/libedit/el.h        |  35 +-
 lib/libedit/emacs.c     | 104 +++--
 lib/libedit/hist.c      |  59 +--
 lib/libedit/hist.h      |  12 +-
 lib/libedit/history.c   | 258 +++++++++----
 lib/libedit/key.c       |  50 +--
 lib/libedit/key.h       |  23 +-
 lib/libedit/makelist    |  10 +-
 lib/libedit/map.c       | 310 ++++++++-------
 lib/libedit/map.h       |  10 +-
 lib/libedit/parse.c     |  36 +-
 lib/libedit/parse.h     |  10 +-
 lib/libedit/prompt.c    |  14 +-
 lib/libedit/prompt.h    |   8 +-
 lib/libedit/read.c      | 215 ++++++++---
 lib/libedit/read.h      |  58 +++
 lib/libedit/refresh.c   |  54 ++-
 lib/libedit/refresh.h   |   8 +-
 lib/libedit/search.c    | 202 +++++-----
 lib/libedit/search.h    |  14 +-
 lib/libedit/sig.c       |  14 +-
 lib/libedit/sig.h       |  11 +-
 lib/libedit/sys.h       |  19 +-
 lib/libedit/term.c      |  68 ++--
 lib/libedit/term.h      |  29 +-
 lib/libedit/tokenizer.c | 126 ++++--
 lib/libedit/tokenizer.h |  54 ---
 lib/libedit/tty.c       | 155 +++++++-
 lib/libedit/tty.h       |  16 +-
 lib/libedit/vi.c        | 827 ++++++++++++++++++++++++----------------
 39 files changed, 2417 insertions(+), 1499 deletions(-)
 create mode 100644 lib/libedit/read.h
 delete mode 100644 lib/libedit/tokenizer.h

diff --git a/include/histedit.h b/include/histedit.h
index e2d71903ae44..a4db871fc964 100644
--- a/include/histedit.h
+++ b/include/histedit.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)histedit.h	8.2 (Berkeley) 1/3/94
- *	$NetBSD: histedit.h,v 1.15 2000/02/28 17:41:05 chopps Exp $
+ *	$NetBSD: histedit.h,v 1.28 2005/07/14 15:00:58 christos Exp $
  * $FreeBSD$
  */
 
@@ -52,6 +48,7 @@ __BEGIN_DECLS
 /*
  * ==== Editing ====
  */
+
 typedef struct editline EditLine;
 
 /*
@@ -63,7 +60,6 @@ typedef struct lineinfo {
 	const char	*lastchar;
 } LineInfo;
 
-
 /*
  * EditLine editor function return codes.
  * For user-defined function interface
@@ -83,16 +79,15 @@ typedef struct lineinfo {
  * Initialization, cleanup, and resetting
  */
 EditLine	*el_init(const char *, FILE *, FILE *, FILE *);
-void		 el_reset(EditLine *);
 void		 el_end(EditLine *);
-
+void		 el_reset(EditLine *);
 
 /*
  * Get a line, a character or push a string back in the input queue
  */
 const char	*el_gets(EditLine *, int *);
 int		 el_getc(EditLine *, char *);
-void		 el_push(EditLine *, const char *);
+void		 el_push(EditLine *, char *);
 
 /*
  * Beep!
@@ -103,13 +98,16 @@ void		 el_beep(EditLine *);
  * High level function internals control
  * Parses argc, argv array and executes builtin editline commands
  */
-int		 el_parse(EditLine *, int, char **);
+int		 el_parse(EditLine *, int, const char **);
 
 /*
  * Low level editline access functions
  */
 int		 el_set(EditLine *, int, ...);
 int		 el_get(EditLine *, int, void *);
+#if 0
+unsigned char	_el_fn_complete(EditLine *, int);
+#endif
 
 /*
  * el_set/el_get parameters
@@ -128,6 +126,12 @@ int		 el_get(EditLine *, int, void *);
 #define	EL_HIST		10	/* , hist_fun_t, const char *);	*/
 #define	EL_EDITMODE	11	/* , int);			*/
 #define	EL_RPROMPT	12	/* , el_pfunc_t);		*/
+#define	EL_GETCFN	13	/* , el_rfunc_t);		*/
+#define	EL_CLIENTDATA	14	/* , void *);			*/
+#define	EL_UNBUFFERED	15	/* , int);			*/
+#define	EL_PREP_TERM    16      /* , int);                      */
+
+#define EL_BUILTIN_GETCFN	(NULL)
 
 /*
  * Source named file or $PWD/.editrc or $HOME/.editrc
@@ -155,6 +159,7 @@ const LineInfo	*el_line(EditLine *);
 int		 el_insertstr(EditLine *, const char *);
 void		 el_deletestr(EditLine *, int);
 
+
 /*
  * ==== History ====
  */
@@ -183,7 +188,7 @@ int		history(History *, HistEvent *, int, ...);
 #define	H_PREV		 5	/* , void);		*/
 #define	H_NEXT		 6	/* , void);		*/
 #define	H_CURR		 8	/* , const int);	*/
-#define	H_SET		 7	/* , void);		*/
+#define	H_SET		 7	/* , int);		*/
 #define	H_ADD		 9	/* , const char *);	*/
 #define	H_ENTER		10	/* , const char *);	*/
 #define	H_APPEND	11	/* , const char *);	*/
@@ -195,6 +200,27 @@ int		history(History *, HistEvent *, int, ...);
 #define	H_LOAD		17	/* , const char *);	*/
 #define	H_SAVE		18	/* , const char *);	*/
 #define	H_CLEAR		19	/* , void);		*/
+#define	H_SETUNIQUE	20	/* , int);		*/
+#define	H_GETUNIQUE	21	/* , void);		*/
+#define	H_DEL		22	/* , int);		*/
+
+
+/*
+ * ==== Tokenization ====
+ */
+
+typedef struct tokenizer Tokenizer;
+
+/*
+ * String tokenization functions, using simplified sh(1) quoting rules
+ */
+Tokenizer	*tok_init(const char *);
+void		 tok_end(Tokenizer *);
+void		 tok_reset(Tokenizer *);
+int		 tok_line(Tokenizer *, const LineInfo *,
+		    int *, const char ***, int *, int *);
+int		 tok_str(Tokenizer *, const char *,
+		    int *, const char ***);
 
 __END_DECLS
 
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile
index dcd79eae2f5a..5ec70efc7a85 100644
--- a/lib/libedit/Makefile
+++ b/lib/libedit/Makefile
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.19 2000/08/15 12:01:40 mrg Exp $
+#	$NetBSD: Makefile,v 1.34 2005/05/28 12:02:53 lukem Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/4/93
 # $FreeBSD$
 
@@ -20,7 +20,9 @@ MLINKS=	editline.3 el_deletestr.3 editline.3 el_end.3 editline.3 el_init.3 \
 	editline.3 history_init.3 editline.3 el_insertstr.3 \
 	editline.3 el_line.3 editline.3 el_parse.3 editline.3 el_push.3 \
 	editline.3 el_reset.3 editline.3 el_resize.3 editline.3 el_set.3 \
-	editline.3 el_source.3
+	editline.3 el_source.3 \
+	editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \
+	editline.3 tok_line.3 editline.3 tok_str.3
 
 # For speed and debugging
 #SRCS=   ${OSRCS} tokenizer.c history.c
@@ -31,7 +33,7 @@ CLEANFILES+= common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h
 
 CFLAGS+= -I. -I${.CURDIR}
 CFLAGS+= #-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
-CFLAGS+= #-DDEBUG_PASTE
+CFLAGS+= #-DDEBUG_PASTE -DDEBUG_EDIT
 
 AHDR=	vi.h emacs.h common.h
 ASRC=	${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
diff --git a/lib/libedit/TEST/test.c b/lib/libedit/TEST/test.c
index d7b4df52336f..facbdaa7e3df 100644
--- a/lib/libedit/TEST/test.c
+++ b/lib/libedit/TEST/test.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -43,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
 #if !defined(lint) && !defined(SCCSID)
 static char sccsid[] = "@(#)test.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
-__RCSID("$NetBSD: test.c,v 1.8 1999/09/21 00:07:03 lukem Exp $");
+__RCSID("$NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem Exp $");
 __FBSDID("$FreeBSD$");
 
 /*
@@ -60,12 +56,11 @@ __FBSDID("$FreeBSD$");
 #include <dirent.h>
 
 #include "histedit.h"
-#include "tokenizer.h"
 
 static int continuation = 0;
-static EditLine *el = NULL;
+volatile sig_atomic_t gotsig = 0;
 
-static	u_char	complete(EditLine *, int);
+static	unsigned char	complete(EditLine *, int);
 	int	main(int, char **);
 static	char   *prompt(EditLine *);
 static	void	sig(int);
@@ -73,8 +68,8 @@ static	void	sig(int);
 static char *
 prompt(EditLine *el)
 {
-	static char a[] = "Edit$";
-	static char b[] = "Edit>";
+	static char a[] = "Edit$ ";
+	static char b[] = "Edit> ";
 
 	return (continuation ? b : a);
 }
@@ -82,9 +77,7 @@ prompt(EditLine *el)
 static void
 sig(int i)
 {
-
-	(void) fprintf(stderr, "Got signal %d.\n", i);
-	el_reset(el);
+	gotsig = i;
 }
 
 static unsigned char
@@ -99,7 +92,8 @@ complete(EditLine *el, int ch)
 	/*
 	 * Find the last word
 	 */
-	for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--)
+	for (ptr = lf->cursor - 1;
+	    !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)
 		continue;
 	len = lf->cursor - ++ptr;
 
@@ -122,10 +116,14 @@ complete(EditLine *el, int ch)
 int
 main(int argc, char *argv[])
 {
+	EditLine *el = NULL;
 	int num;
 	const char *buf;
 	Tokenizer *tok;
-	int lastevent = 0, ncontinuation;
+#if 0
+	int lastevent = 0;
+#endif
+	int ncontinuation;
 	History *hist;
 	HistEvent ev;
 
@@ -169,17 +167,41 @@ main(int argc, char *argv[])
 	el_source(el, NULL);
 
 	while ((buf = el_gets(el, &num)) != NULL && num != 0)  {
-		int ac;
-		char **av;
+		int ac, cc, co;
 #ifdef DEBUG
-		(void) fprintf(stderr, "got %d %s", num, buf);
+		int i;
 #endif
+		const char **av;
+		const LineInfo *li;
+		li = el_line(el);
+#ifdef DEBUG
+		(void) fprintf(stderr, "==> got %d %s", num, buf);
+		(void) fprintf(stderr, "  > li `%.*s_%.*s'\n",
+		    (li->cursor - li->buffer), li->buffer,
+		    (li->lastchar - 1 - li->cursor),
+		    (li->cursor >= li->lastchar) ? "" : li->cursor);
+
+#endif
+		if (gotsig) {
+			(void) fprintf(stderr, "Got signal %d.\n", gotsig);
+			gotsig = 0;
+			el_reset(el);
+		}
+
 		if (!continuation && num == 1)
 			continue;
 
-		if (tok_line(tok, buf, &ac, &av) > 0)
-			ncontinuation = 1;
-
+		ac = cc = co = 0;
+		ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co);
+		if (ncontinuation < 0) {
+			(void) fprintf(stderr, "Internal error\n");
+			continuation = 0;
+			continue;
+		}
+#ifdef DEBUG
+		(void) fprintf(stderr, "  > nc %d ac %d cc %d co %d\n",
+		    ncontinuation, ac, cc, co);
+#endif
 #if 0
 		if (continuation) {
 			/*
@@ -187,7 +209,7 @@ main(int argc, char *argv[])
 			 * moved around in history.
 			 */
 			if (history(hist, &ev, H_SET, lastevent) == -1)
-				err(1, "%d: %s\n", lastevent, ev.str);
+				err(1, "%d: %s", lastevent, ev.str);
 			history(hist, &ev, H_ADD , buf);
 		} else {
 			history(hist, &ev, H_ENTER, buf);
@@ -200,6 +222,18 @@ main(int argc, char *argv[])
 
 		continuation = ncontinuation;
 		ncontinuation = 0;
+		if (continuation)
+			continue;
+#ifdef DEBUG
+		for (i = 0; i < ac; i++) {
+			(void) fprintf(stderr, "  > arg# %2d ", i);
+			if (i != cc)
+				(void) fprintf(stderr, "`%s'\n", av[i]);
+			else
+				(void) fprintf(stderr, "`%.*s_%s'\n",
+				    co, av[i], av[i] + co);
+		}
+#endif
 
 		if (strcmp(av[0], "history") == 0) {
 			int rv;
@@ -235,7 +269,7 @@ main(int argc, char *argv[])
 		} else if (el_parse(el, ac, av) == -1) {
 			switch (fork()) {
 			case 0:
-				execvp(av[0], av);
+				execvp(av[0], __DECONST(char *const *, av));
 				perror(av[0]);
 				_exit(1);
 				/*NOTREACHED*/
diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c
index 8efb35d3be47..6bbfcf877460 100644
--- a/lib/libedit/chared.c
+++ b/lib/libedit/chared.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: chared.c,v 1.13 2001/04/13 01:04:19 lukem Exp $
+ *	$NetBSD: chared.c,v 1.24 2005/08/01 23:00:15 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -50,6 +46,8 @@ __FBSDID("$FreeBSD$");
 #include <stdlib.h>
 #include "el.h"
 
+private void ch__clearmacro(EditLine *);
+
 /* value to leave unused in line buffer */
 #define	EL_LEAVE	2
 
@@ -57,17 +55,36 @@ __FBSDID("$FreeBSD$");
  *	Handle state for the vi undo command
  */
 protected void
-cv_undo(EditLine *el,int action, size_t size, char *ptr)
+cv_undo(EditLine *el)
 {
 	c_undo_t *vu = &el->el_chared.c_undo;
-	vu->action = action;
-	vu->ptr    = ptr;
-	vu->isize  = size;
-	(void) memcpy(vu->buf, vu->ptr, size);
-#ifdef DEBUG_UNDO
-	(void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
-	       vu->ptr, vu->isize, vu->dsize);
-#endif
+	c_redo_t *r = &el->el_chared.c_redo;
+	unsigned int size;
+
+	/* Save entire line for undo */
+	size = el->el_line.lastchar - el->el_line.buffer;
+	vu->len = size;
+	vu->cursor = el->el_line.cursor - el->el_line.buffer;
+	memcpy(vu->buf, el->el_line.buffer, size);
+
+	/* save command info for redo */
+	r->count = el->el_state.doingarg ? el->el_state.argument : 0;
+	r->action = el->el_chared.c_vcmd.action;
+	r->pos = r->buf;
+	r->cmd = el->el_state.thiscmd;
+	r->ch = el->el_state.thisch;
+}
+
+/* cv_yank():
+ *	Save yank/delete data for paste
+ */
+protected void
+cv_yank(EditLine *el, const char *ptr, int size)
+{
+	c_kill_t *k = &el->el_chared.c_kill;
+
+	memcpy(k->buf, ptr, size +0u);
+	k->last = k->buf + size;
 }
 
 
@@ -79,8 +96,10 @@ c_insert(EditLine *el, int num)
 {
 	char *cp;
 
-	if (el->el_line.lastchar + num >= el->el_line.limit)
-		return;			/* can't go past end of buffer */
+	if (el->el_line.lastchar + num >= el->el_line.limit) {
+		if (!ch_enlargebufs(el, num +0u))
+			return;		/* can't go past end of buffer */
+	}
 
 	if (el->el_line.cursor < el->el_line.lastchar) {
 		/* if I must move chars */
@@ -101,12 +120,14 @@ c_delafter(EditLine *el, int num)
 	if (el->el_line.cursor + num > el->el_line.lastchar)
 		num = el->el_line.lastchar - el->el_line.cursor;
 
+	if (el->el_map.current != el->el_map.emacs) {
+		cv_undo(el);
+		cv_yank(el, el->el_line.cursor, num);
+	}
+
 	if (num > 0) {
 		char *cp;
 
-		if (el->el_map.current != el->el_map.emacs)
-			cv_undo(el, INSERT, (size_t)num, el->el_line.cursor);
-
 		for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
 			*cp = cp[num];
 
@@ -115,6 +136,21 @@ c_delafter(EditLine *el, int num)
 }
 
 
+/* c_delafter1():
+ *	Delete the character after the cursor, do not yank
+ */
+protected void
+c_delafter1(EditLine *el)
+{
+	char *cp;
+
+	for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+		*cp = cp[1];
+
+	el->el_line.lastchar--;
+}
+
+
 /* c_delbefore():
  *	Delete num characters before the cursor
  */
@@ -125,13 +161,14 @@ c_delbefore(EditLine *el, int num)
 	if (el->el_line.cursor - num < el->el_line.buffer)
 		num = el->el_line.cursor - el->el_line.buffer;
 
+	if (el->el_map.current != el->el_map.emacs) {
+		cv_undo(el);
+		cv_yank(el, el->el_line.cursor - num, num);
+	}
+
 	if (num > 0) {
 		char *cp;
 
-		if (el->el_map.current != el->el_map.emacs)
-			cv_undo(el, INSERT, (size_t)num,
-			    el->el_line.cursor - num);
-
 		for (cp = el->el_line.cursor - num;
 		    cp <= el->el_line.lastchar;
 		    cp++)
@@ -142,38 +179,52 @@ c_delbefore(EditLine *el, int num)
 }
 
 
+/* c_delbefore1():
+ *	Delete the character before the cursor, do not yank
+ */
+protected void
+c_delbefore1(EditLine *el)
+{
+	char *cp;
+
+	for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
+		*cp = cp[1];
+
+	el->el_line.lastchar--;
+}
+
+
 /* ce__isword():
  *	Return if p is part of a word according to emacs
  */
 protected int
 ce__isword(int p)
 {
-	return (isalpha((unsigned char)p) || isdigit((unsigned char)p) || strchr("*?_-.[]~=", p) != NULL);
+	return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);
 }
 
 
 /* cv__isword():
- *	Return type of word for p according to vi
+ *	Return if p is part of a word according to vi
  */
 protected int
 cv__isword(int p)
 {
-    if (isspace((unsigned char) p))
-        return 0;
-    if ((unsigned char) p == '_' || isalnum((unsigned char) p))
-        return 1;
-    return 2;
+	if (isalnum(p) || p == '_')
+		return 1;
+	if (isgraph(p))
+		return 2;
+	return 0;
 }
 
 
-/* c___isword():
- *	Return if p is part of a space-delimited word (!isspace)
+/* cv__isWord():
+ *	Return if p is part of a big word according to vi
  */
 protected int
-c___isword(p)
-    int p;
+cv__isWord(int p)
 {
-    return !isspace((unsigned char) p);
+	return (!isspace(p));
 }
 
 
@@ -235,7 +286,7 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
 		 * vi historically deletes with cw only the word preserving the
 		 * trailing whitespace! This is not what 'w' does..
 		 */
-		if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+		if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
 			while ((p < high) && isspace((unsigned char) *p))
 				p++;
 	}
@@ -252,26 +303,19 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
  *	Find the previous word vi style
  */
 protected char *
-cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int))
+cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
 {
 	int test;
 
+	p--;
 	while (n--) {
-		p--;
-		/*
-		 * vi historically deletes with cb only the word preserving the
-		 * leading whitespace! This is not what 'b' does..
-		 */
-		if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
-			while ((p > low) && isspace((unsigned char) *p))
-				p--;
+		while ((p > low) && isspace((unsigned char) *p))
+			p--;
 		test = (*wtest)((unsigned char) *p);
 		while ((p >= low) && (*wtest)((unsigned char) *p) == test)
 			p--;
-		p++;
-		while (isspace((unsigned char) *p))
-			p++;
 	}
+	p++;
 
 	/* p now points where we want it */
 	if (p < low)
@@ -322,47 +366,34 @@ protected void
 cv_delfini(EditLine *el)
 {
 	int size;
-	int oaction;
+	int action = el->el_chared.c_vcmd.action;
 
-	if (el->el_chared.c_vcmd.action & INSERT)
+	if (action & INSERT)
 		el->el_map.current = el->el_map.key;
 
-	oaction = el->el_chared.c_vcmd.action;
-	el->el_chared.c_vcmd.action = NOP;
-
 	if (el->el_chared.c_vcmd.pos == 0)
+		/* sanity */
 		return;
 
-
-	if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
-		size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
-		c_delbefore(el, size);
-		el->el_line.cursor = el->el_chared.c_vcmd.pos;
-		re_refresh_cursor(el);
-	} else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
-		size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
-		c_delafter(el, size);
-	} else {
+	size = el->el_line.cursor - el->el_chared.c_vcmd.pos;
+	if (size == 0)
 		size = 1;
-		c_delafter(el, size);
+	el->el_line.cursor = el->el_chared.c_vcmd.pos;
+	if (action & YANK) {
+		if (size > 0)
+			cv_yank(el, el->el_line.cursor, size);
+		else
+			cv_yank(el, el->el_line.cursor + size, -size);
+	} else {
+		if (size > 0) {
+			c_delafter(el, size);
+			re_refresh_cursor(el);
+		} else  {
+			c_delbefore(el, -size);
+			el->el_line.cursor += size;
+		}
 	}
-	switch (oaction) {
-	case DELETE|INSERT:
-		el->el_chared.c_undo.action = DELETE|INSERT;
-		break;
-	case DELETE:
-		el->el_chared.c_undo.action = INSERT;
-		break;
-	case NOP:
-	case INSERT:
-	default:
-		EL_ABORT((el->el_errfile, "Bad oaction %d\n", oaction));
-		break;
-	}
-
-
-	el->el_chared.c_undo.ptr = el->el_line.cursor;
-	el->el_chared.c_undo.dsize = size;
+	el->el_chared.c_vcmd.action = NOP;
 }
 
 
@@ -392,21 +423,19 @@ ce__endword(char *p, char *high, int n)
  *	Go to the end of this word according to vi
  */
 protected char *
-cv__endword(char *p, char *high, int n)
+cv__endword(char *p, char *high, int n, int (*wtest)(int))
 {
+	int test;
+
 	p++;
 
 	while (n--) {
 		while ((p < high) && isspace((unsigned char) *p))
 			p++;
 
-		if (isalnum((unsigned char) *p))
-			while ((p < high) && isalnum((unsigned char) *p))
-				p++;
-		else
-			while ((p < high) && !(isspace((unsigned char) *p) ||
-			    isalnum((unsigned char) *p)))
-				p++;
+		test = (*wtest)((unsigned char) *p);
+		while ((p < high) && (*wtest)((unsigned char) *p) == test)
+			p++;
 	}
 	p--;
 	return (p);
@@ -418,6 +447,8 @@ cv__endword(char *p, char *high, int n)
 protected int
 ch_init(EditLine *el)
 {
+	c_macro_t *ma = &el->el_chared.c_macro;
+
 	el->el_line.buffer		= (char *) el_malloc(EL_BUFSIZ);
 	if (el->el_line.buffer == NULL)
 		return (-1);
@@ -425,20 +456,23 @@ ch_init(EditLine *el)
 	(void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
 	el->el_line.cursor		= el->el_line.buffer;
 	el->el_line.lastchar		= el->el_line.buffer;
-	el->el_line.limit		= &el->el_line.buffer[EL_BUFSIZ - 2];
+	el->el_line.limit		= &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
 
 	el->el_chared.c_undo.buf	= (char *) el_malloc(EL_BUFSIZ);
 	if (el->el_chared.c_undo.buf == NULL)
 		return (-1);
 	(void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
-	el->el_chared.c_undo.action	= NOP;
-	el->el_chared.c_undo.isize	= 0;
-	el->el_chared.c_undo.dsize	= 0;
-	el->el_chared.c_undo.ptr	= el->el_line.buffer;
+	el->el_chared.c_undo.len	= -1;
+	el->el_chared.c_undo.cursor	= 0;
+	el->el_chared.c_redo.buf	= (char *) el_malloc(EL_BUFSIZ);
+	if (el->el_chared.c_redo.buf == NULL)
+		return (-1);
+	el->el_chared.c_redo.pos	= el->el_chared.c_redo.buf;
+	el->el_chared.c_redo.lim	= el->el_chared.c_redo.buf + EL_BUFSIZ;
+	el->el_chared.c_redo.cmd	= ED_UNASSIGNED;
 
 	el->el_chared.c_vcmd.action	= NOP;
 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
-	el->el_chared.c_vcmd.ins	= el->el_line.buffer;
 
 	el->el_chared.c_kill.buf	= (char *) el_malloc(EL_BUFSIZ);
 	if (el->el_chared.c_kill.buf == NULL)
@@ -455,11 +489,10 @@ ch_init(EditLine *el)
 	el->el_state.argument		= 1;
 	el->el_state.lastcmd		= ED_UNASSIGNED;
 
-	el->el_chared.c_macro.nline	= NULL;
-	el->el_chared.c_macro.level	= -1;
-	el->el_chared.c_macro.macro	= (char **) el_malloc(EL_MAXMACRO *
-	    sizeof(char *));
-	if (el->el_chared.c_macro.macro == NULL)
+	ma->level	= -1;
+	ma->offset	= 0;
+	ma->macro	= (char **) el_malloc(EL_MAXMACRO * sizeof(char *));
+	if (ma->macro == NULL)
 		return (-1);
 	return (0);
 }
@@ -468,19 +501,16 @@ ch_init(EditLine *el)
  *	Reset the character editor
  */
 protected void
-ch_reset(EditLine *el)
+ch_reset(EditLine *el, int mclear)
 {
 	el->el_line.cursor		= el->el_line.buffer;
 	el->el_line.lastchar		= el->el_line.buffer;
 
-	el->el_chared.c_undo.action	= NOP;
-	el->el_chared.c_undo.isize	= 0;
-	el->el_chared.c_undo.dsize	= 0;
-	el->el_chared.c_undo.ptr	= el->el_line.buffer;
+	el->el_chared.c_undo.len	= -1;
+	el->el_chared.c_undo.cursor	= 0;
 
 	el->el_chared.c_vcmd.action	= NOP;
 	el->el_chared.c_vcmd.pos	= el->el_line.buffer;
-	el->el_chared.c_vcmd.ins	= el->el_line.buffer;
 
 	el->el_chared.c_kill.mark	= el->el_line.buffer;
 
@@ -492,9 +522,17 @@ ch_reset(EditLine *el)
 	el->el_state.argument		= 1;
 	el->el_state.lastcmd		= ED_UNASSIGNED;
 
-	el->el_chared.c_macro.level	= -1;
+	if (mclear)
+		ch__clearmacro(el);
+}
 
-	el->el_history.eventno		= 0;
+private void
+ch__clearmacro(el)
+	EditLine *el;
+{
+	c_macro_t *ma = &el->el_chared.c_macro;
+	while (ma->level >= 0)
+		el_free((ptr_t)ma->macro[ma->level--]);
 }
 
 /* ch_enlargebufs():
@@ -535,7 +573,8 @@ ch_enlargebufs(el, addlen)
 	el->el_line.buffer = newbuffer;
 	el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
 	el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
-	el->el_line.limit  = &newbuffer[newsz - EL_LEAVE];
+	/* don't set new size until all buffers are enlarged */
+	el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
 
 	/*
 	 * Reallocate kill buffer.
@@ -564,14 +603,22 @@ ch_enlargebufs(el, addlen)
 
 	/* zero the newly added memory, leave old data in */
 	(void) memset(&newbuffer[sz], 0, newsz - sz);
-
-	el->el_chared.c_undo.ptr = el->el_line.buffer +
-				    (el->el_chared.c_undo.ptr - oldbuf);
 	el->el_chared.c_undo.buf = newbuffer;
+
+	newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz);
+	if (!newbuffer)
+		return 0;
+	el->el_chared.c_redo.pos = newbuffer +
+			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
+	el->el_chared.c_redo.lim = newbuffer +
+			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
+	el->el_chared.c_redo.buf = newbuffer;
 	
 	if (!hist_enlargebuf(el, sz, newsz))
 		return 0;
 
+	/* Safe to set enlarged buffer size */
+	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
 	return 1;
 }
 
@@ -586,11 +633,16 @@ ch_end(EditLine *el)
 	el->el_line.limit = NULL;
 	el_free((ptr_t) el->el_chared.c_undo.buf);
 	el->el_chared.c_undo.buf = NULL;
+	el_free((ptr_t) el->el_chared.c_redo.buf);
+	el->el_chared.c_redo.buf = NULL;
+	el->el_chared.c_redo.pos = NULL;
+	el->el_chared.c_redo.lim = NULL;
+	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
 	el_free((ptr_t) el->el_chared.c_kill.buf);
 	el->el_chared.c_kill.buf = NULL;
+	ch_reset(el, 1);
 	el_free((ptr_t) el->el_chared.c_macro.macro);
 	el->el_chared.c_macro.macro = NULL;
-	ch_reset(el);
 }
 
 
@@ -638,51 +690,64 @@ el_deletestr(EditLine *el, int n)
  *	Get a string
  */
 protected int
-c_gets(EditLine *el, char *buf)
+c_gets(EditLine *el, char *buf, const char *prompt)
 {
 	char ch;
-	int len = 0;
+	int len;
+	char *cp = el->el_line.buffer;
+
+	if (prompt) {
+		len = strlen(prompt);
+		memcpy(cp, prompt, len + 0u);
+		cp += len;
+	}
+	len = 0;
+
+	for (;;) {
+		el->el_line.cursor = cp;
+		*cp = ' ';
+		el->el_line.lastchar = cp + 1;
+		re_refresh(el);
+
+		if (el_getc(el, &ch) != 1) {
+			ed_end_of_file(el, 0);
+			len = -1;
+			break;
+		}
 
-	for (ch = 0; ch == 0;) {
-		if (el_getc(el, &ch) != 1)
-			return (ed_end_of_file(el, 0));
 		switch (ch) {
+
 		case '\010':	/* Delete and backspace */
 		case '\177':
-			if (len > 1) {
-				*el->el_line.cursor-- = '\0';
-				el->el_line.lastchar = el->el_line.cursor;
-				buf[len--] = '\0';
-			} else {
-				el->el_line.buffer[0] = '\0';
-				el->el_line.lastchar = el->el_line.buffer;
-				el->el_line.cursor = el->el_line.buffer;
-				return (CC_REFRESH);
+			if (len <= 0) {
+				len = -1;
+				break;
 			}
-			re_refresh(el);
-			ch = 0;
-			break;
+			cp--;
+			continue;
 
 		case '\033':	/* ESC */
 		case '\r':	/* Newline */
 		case '\n':
+			buf[len] = ch;
 			break;
 
 		default:
-			if (len >= EL_BUFSIZ)
+			if (len >= EL_BUFSIZ - 16)
 				term_beep(el);
 			else {
 				buf[len++] = ch;
-				*el->el_line.cursor++ = ch;
-				el->el_line.lastchar = el->el_line.cursor;
+				*cp++ = ch;
 			}
-			re_refresh(el);
-			ch = 0;
-			break;
+			continue;
 		}
+		break;
 	}
-	buf[len] = ch;
-	return (len);
+
+	el->el_line.buffer[0] = '\0';
+	el->el_line.lastchar = el->el_line.buffer;
+	el->el_line.cursor = el->el_line.buffer;
+	return len;
 }
 
 
diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h
index 80606bb83192..9ea1416ee0da 100644
--- a/lib/libedit/chared.h
+++ b/lib/libedit/chared.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)chared.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: chared.h,v 1.5 2000/09/04 22:06:29 lukem Exp $
+ *	$NetBSD: chared.h,v 1.15 2005/08/01 23:00:15 christos Exp $
  * $FreeBSD$
  */
 
@@ -66,28 +62,36 @@
 
 typedef struct c_macro_t {
 	int	  level;
+	int	  offset;
 	char	**macro;
-	char	 *nline;
 } c_macro_t;
 
 /*
- * Undo information for both vi and emacs
+ * Undo information for vi - no undo in emacs (yet)
  */
 typedef struct c_undo_t {
-	int	 action;
-	size_t	 isize;
-	size_t	 dsize;
-	char	*ptr;
-	char	*buf;
+	int	 len;			/* length of saved line */
+	int	 cursor;		/* position of saved cursor */
+	char	*buf;			/* full saved text */
 } c_undo_t;
 
+/* redo for vi */
+typedef struct c_redo_t {
+	char	*buf;			/* redo insert key sequence */
+	char	*pos;
+	char	*lim;
+	el_action_t	cmd;		/* command to redo */
+	char	ch;			/* char that invoked it */
+	int	count;
+	int	action;			/* from cv_action() */
+} c_redo_t;
+
 /*
  * Current action information for vi
  */
 typedef struct c_vcmd_t {
 	int	 action;
 	char	*pos;
-	char	*ins;
 } c_vcmd_t;
 
 /*
@@ -106,6 +110,7 @@ typedef struct c_kill_t {
 typedef struct el_chared_t {
 	c_undo_t	c_undo;
 	c_kill_t	c_kill;
+	c_redo_t	c_redo;
 	c_vcmd_t	c_vcmd;
 	c_macro_t	c_macro;
 } el_chared_t;
@@ -120,10 +125,10 @@ typedef struct el_chared_t {
 #define	NOP		0x00
 #define	DELETE		0x01
 #define	INSERT		0x02
-#define	CHANGE		0x04
+#define	YANK		0x04
 
-#define	CHAR_FWD	0
-#define	CHAR_BACK	1
+#define	CHAR_FWD	(+1)
+#define	CHAR_BACK	(-1)
 
 #define	MODE_INSERT	0
 #define	MODE_REPLACE	1
@@ -137,23 +142,26 @@ typedef struct el_chared_t {
 
 
 protected int	 cv__isword(int);
+protected int	 cv__isWord(int);
 protected void	 cv_delfini(EditLine *);
-protected char	*cv__endword(char *, char *, int);
+protected char	*cv__endword(char *, char *, int, int (*)(int));
 protected int	 ce__isword(int);
-protected int	 c___isword(int);
-protected void	 cv_undo(EditLine *, int, size_t, char *);
+protected void	 cv_undo(EditLine *);
+protected void	 cv_yank(EditLine *, const char *, int);
 protected char	*cv_next_word(EditLine*, char *, char *, int, int (*)(int));
-protected char	*cv_prev_word(EditLine*, char *, char *, int, int (*)(int));
+protected char	*cv_prev_word(char *, char *, int, int (*)(int));
 protected char	*c__next_word(char *, char *, int, int (*)(int));
 protected char	*c__prev_word(char *, char *, int, int (*)(int));
 protected void	 c_insert(EditLine *, int);
 protected void	 c_delbefore(EditLine *, int);
+protected void	 c_delbefore1(EditLine *);
 protected void	 c_delafter(EditLine *, int);
-protected int	 c_gets(EditLine *, char *);
+protected void	 c_delafter1(EditLine *);
+protected int	 c_gets(EditLine *, char *, const char *);
 protected int	 c_hpos(EditLine *);
 
 protected int	 ch_init(EditLine *);
-protected void	 ch_reset(EditLine *);
+protected void	 ch_reset(EditLine *, int);
 protected int	 ch_enlargebufs(EditLine *, size_t);
 protected void	 ch_end(EditLine *);
 
diff --git a/lib/libedit/common.c b/lib/libedit/common.c
index 145f4b7d6de4..99d4660340e9 100644
--- a/lib/libedit/common.c
+++ b/lib/libedit/common.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: common.c,v 1.9 2000/09/04 22:06:29 lukem Exp $
+ *	$NetBSD: common.c,v 1.17 2005/08/01 23:00:15 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -54,7 +50,7 @@ __FBSDID("$FreeBSD$");
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_end_of_file(EditLine *el, int c)
+ed_end_of_file(EditLine *el, int c __unused)
 {
 
 	re_goto_bottom(el);
@@ -70,7 +66,7 @@ ed_end_of_file(EditLine *el, int c)
 protected el_action_t
 ed_insert(EditLine *el, int c)
 {
-	int i;
+	int count = el->el_state.argument;
 
 	if (c == '\0')
 		return (CC_ERROR);
@@ -78,46 +74,28 @@ ed_insert(EditLine *el, int c)
 	if (el->el_line.lastchar + el->el_state.argument >=
 	    el->el_line.limit) {
 		/* end of buffer space, try to allocate more */
-		if (!ch_enlargebufs(el, (size_t) el->el_state.argument))
+		if (!ch_enlargebufs(el, (size_t) count))
 			return CC_ERROR;	/* error allocating more */
 	}
 
-	if (el->el_state.argument == 1) {
-		if (el->el_state.inputmode != MODE_INSERT) {
-			el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
-			    *el->el_line.cursor;
-			el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
-			    '\0';
-			c_delafter(el, 1);
-		}
-		c_insert(el, 1);
+	if (count == 1) {
+		if (el->el_state.inputmode == MODE_INSERT
+		    || el->el_line.cursor >= el->el_line.lastchar)
+			c_insert(el, 1);
 
 		*el->el_line.cursor++ = c;
-		el->el_state.doingarg = 0;	/* just in case */
 		re_fastaddc(el);		/* fast refresh for one char. */
 	} else {
-		if (el->el_state.inputmode != MODE_INSERT) {
-			for (i = 0; i < el->el_state.argument; i++)
-				el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
-				    el->el_line.cursor[i];
+		if (el->el_state.inputmode != MODE_REPLACE_1)
+			c_insert(el, el->el_state.argument);
 
-			el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
-			    '\0';
-			c_delafter(el, el->el_state.argument);
-		}
-		c_insert(el, el->el_state.argument);
-
-		while (el->el_state.argument--)
+		while (count-- && el->el_line.cursor < el->el_line.lastchar)
 			*el->el_line.cursor++ = c;
 		re_refresh(el);
 	}
 
-	if (el->el_state.inputmode == MODE_REPLACE_1
-	    || el->el_state.inputmode == MODE_REPLACE)
-		el->el_chared.c_undo.action=CHANGE;
- 
 	if (el->el_state.inputmode == MODE_REPLACE_1)
-		return (vi_command_mode(el, 0));
+		return vi_command_mode(el, 0);
 
 	return (CC_NORM);
 }
@@ -129,7 +107,7 @@ ed_insert(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_delete_prev_word(EditLine *el, int c)
+ed_delete_prev_word(EditLine *el, int c __unused)
 {
 	char *cp, *p, *kp;
 
@@ -157,7 +135,7 @@ ed_delete_prev_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_delete_next_char(EditLine *el, int c)
+ed_delete_next_char(EditLine *el, int c __unused)
 {
 #ifdef notdef			/* XXX */
 #define	EL	el->el_line
@@ -208,7 +186,7 @@ ed_delete_next_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_kill_line(EditLine *el, int c)
+ed_kill_line(EditLine *el, int c __unused)
 {
 	char *kp, *cp;
 
@@ -229,7 +207,7 @@ ed_kill_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_move_to_end(EditLine *el, int c)
+ed_move_to_end(EditLine *el, int c __unused)
 {
 
 	el->el_line.cursor = el->el_line.lastchar;
@@ -237,7 +215,7 @@ ed_move_to_end(EditLine *el, int c)
 #ifdef VI_MOVE
 		el->el_line.cursor--;
 #endif
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -252,7 +230,7 @@ ed_move_to_end(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_move_to_beg(EditLine *el, int c)
+ed_move_to_beg(EditLine *el, int c __unused)
 {
 
 	el->el_line.cursor = el->el_line.buffer;
@@ -261,7 +239,7 @@ ed_move_to_beg(EditLine *el, int c)
 			/* We want FIRST non space character */
 		while (isspace((unsigned char) *el->el_line.cursor))
 			el->el_line.cursor++;
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -301,18 +279,22 @@ ed_transpose_chars(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_next_char(EditLine *el, int c)
+ed_next_char(EditLine *el, int c __unused)
 {
+	char *lim = el->el_line.lastchar;
 
-	if (el->el_line.cursor >= el->el_line.lastchar)
+	if (el->el_line.cursor >= lim ||
+	    (el->el_line.cursor == lim - 1 &&
+	    el->el_map.type == MAP_VI &&
+	    el->el_chared.c_vcmd.action == NOP))
 		return (CC_ERROR);
 
 	el->el_line.cursor += el->el_state.argument;
-	if (el->el_line.cursor > el->el_line.lastchar)
-		el->el_line.cursor = el->el_line.lastchar;
+	if (el->el_line.cursor > lim)
+		el->el_line.cursor = lim;
 
 	if (el->el_map.type == MAP_VI)
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -326,7 +308,7 @@ ed_next_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_word(EditLine *el, int c)
+ed_prev_word(EditLine *el, int c __unused)
 {
 
 	if (el->el_line.cursor == el->el_line.buffer)
@@ -338,7 +320,7 @@ ed_prev_word(EditLine *el, int c)
 	    ce__isword);
 
 	if (el->el_map.type == MAP_VI)
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -352,7 +334,7 @@ ed_prev_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_char(EditLine *el, int c)
+ed_prev_char(EditLine *el, int c __unused)
 {
 
 	if (el->el_line.cursor > el->el_line.buffer) {
@@ -361,7 +343,7 @@ ed_prev_char(EditLine *el, int c)
 			el->el_line.cursor = el->el_line.buffer;
 
 		if (el->el_map.type == MAP_VI)
-			if (el->el_chared.c_vcmd.action & DELETE) {
+			if (el->el_chared.c_vcmd.action != NOP) {
 				cv_delfini(el);
 				return (CC_REFRESH);
 			}
@@ -413,25 +395,9 @@ ed_digit(EditLine *el, int c)
 			    (el->el_state.argument * 10) + (c - '0');
 		}
 		return (CC_ARGHACK);
-	} else {
-		if (el->el_line.lastchar + 1 >= el->el_line.limit) {
-			if (!ch_enlargebufs(el, 1))
-				return (CC_ERROR);
-		}
-
-		if (el->el_state.inputmode != MODE_INSERT) {
-			el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
-			    *el->el_line.cursor;
-			el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
-			    '\0';
-			c_delafter(el, 1);
-		}
-		c_insert(el, 1);
-		*el->el_line.cursor++ = c;
-		el->el_state.doingarg = 0;
-		re_fastaddc(el);
 	}
-	return (CC_NORM);
+
+	return ed_insert(el, c);
 }
 
 
@@ -465,12 +431,10 @@ ed_argument_digit(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_unassigned(EditLine *el, int c)
+ed_unassigned(EditLine *el, int c __unused)
 {
 
-	term_beep(el);
-	term__flush();
-	return (CC_NORM);
+	return (CC_ERROR);
 }
 
 
@@ -484,7 +448,8 @@ ed_unassigned(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_sigint(EditLine *el, int c)
+ed_tty_sigint(EditLine *el __unused, 
+	      int c __unused)
 {
 
 	return (CC_NORM);
@@ -497,7 +462,8 @@ ed_tty_sigint(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_dsusp(EditLine *el, int c)
+ed_tty_dsusp(EditLine *el __unused, 
+	     int c __unused)
 {
 
 	return (CC_NORM);
@@ -510,7 +476,8 @@ ed_tty_dsusp(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_flush_output(EditLine *el, int c)
+ed_tty_flush_output(EditLine *el __unused, 
+		    int c __unused)
 {
 
 	return (CC_NORM);
@@ -523,7 +490,8 @@ ed_tty_flush_output(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_sigquit(EditLine *el, int c)
+ed_tty_sigquit(EditLine *el __unused, 
+	       int c __unused)
 {
 
 	return (CC_NORM);
@@ -536,7 +504,8 @@ ed_tty_sigquit(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_sigtstp(EditLine *el, int c)
+ed_tty_sigtstp(EditLine *el __unused, 
+	       int c __unused)
 {
 
 	return (CC_NORM);
@@ -549,7 +518,8 @@ ed_tty_sigtstp(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_stop_output(EditLine *el, int c)
+ed_tty_stop_output(EditLine *el __unused, 
+		   int c __unused)
 {
 
 	return (CC_NORM);
@@ -562,7 +532,8 @@ ed_tty_stop_output(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_start_output(EditLine *el, int c)
+ed_tty_start_output(EditLine *el __unused, 
+		    int c __unused)
 {
 
 	return (CC_NORM);
@@ -575,14 +546,12 @@ ed_tty_start_output(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_newline(EditLine *el, int c)
+ed_newline(EditLine *el, int c __unused)
 {
 
 	re_goto_bottom(el);
 	*el->el_line.lastchar++ = '\n';
 	*el->el_line.lastchar = '\0';
-	if (el->el_map.type == MAP_VI)
-		el->el_chared.c_vcmd.ins = el->el_line.buffer;
 	return (CC_NEWLINE);
 }
 
@@ -593,7 +562,7 @@ ed_newline(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_delete_prev_char(EditLine *el, int c)
+ed_delete_prev_char(EditLine *el, int c __unused)
 {
 
 	if (el->el_line.cursor <= el->el_line.buffer)
@@ -613,7 +582,7 @@ ed_delete_prev_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_clear_screen(EditLine *el, int c)
+ed_clear_screen(EditLine *el, int c __unused)
 {
 
 	term_clear_screen(el);	/* clear the whole real screen */
@@ -628,7 +597,8 @@ ed_clear_screen(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_redisplay(EditLine *el, int c)
+ed_redisplay(EditLine *el __unused, 
+	     int c __unused)
 {
 
 	return (CC_REDISPLAY);
@@ -641,10 +611,10 @@ ed_redisplay(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_start_over(EditLine *el, int c)
+ed_start_over(EditLine *el, int c __unused)
 {
 
-	ch_reset(el);
+	ch_reset(el, 0);
 	return (CC_REFRESH);
 }
 
@@ -655,7 +625,8 @@ ed_start_over(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_sequence_lead_in(EditLine *el, int c)
+ed_sequence_lead_in(EditLine *el __unused, 
+		    int c __unused)
 {
 
 	return (CC_NORM);
@@ -668,11 +639,12 @@ ed_sequence_lead_in(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_history(EditLine *el, int c)
+ed_prev_history(EditLine *el, int c __unused)
 {
 	char beep = 0;
+	int sv_event = el->el_history.eventno;
 
-	el->el_chared.c_undo.action = NOP;
+	el->el_chared.c_undo.len = -1;
 	*el->el_line.lastchar = '\0';		/* just in case */
 
 	if (el->el_history.eventno == 0) {	/* save the current buffer
@@ -685,15 +657,17 @@ ed_prev_history(EditLine *el, int c)
 	el->el_history.eventno += el->el_state.argument;
 
 	if (hist_get(el) == CC_ERROR) {
+		if (el->el_map.type == MAP_VI) {
+			el->el_history.eventno = sv_event;
+			return CC_ERROR;
+		}
 		beep = 1;
 		/* el->el_history.eventno was fixed by first call */
 		(void) hist_get(el);
 	}
-	re_refresh(el);
 	if (beep)
-		return (CC_ERROR);
-	else
-		return (CC_NORM);	/* was CC_UP_HIST */
+		return CC_REFRESH_BEEP;
+	return CC_REFRESH;
 }
 
 
@@ -703,19 +677,24 @@ ed_prev_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_next_history(EditLine *el, int c)
+ed_next_history(EditLine *el, int c __unused)
 {
+	el_action_t beep = CC_REFRESH, rval;
 
-	el->el_chared.c_undo.action = NOP;
+	el->el_chared.c_undo.len = -1;
 	*el->el_line.lastchar = '\0';	/* just in case */
 
 	el->el_history.eventno -= el->el_state.argument;
 
 	if (el->el_history.eventno < 0) {
 		el->el_history.eventno = 0;
-		return (CC_ERROR);/* make it beep */
+		beep = CC_REFRESH_BEEP;
 	}
-	return (hist_get(el));
+	rval = hist_get(el);
+	if (rval == CC_REFRESH)
+		return beep;
+	return rval;
+
 }
 
 
@@ -725,14 +704,14 @@ ed_next_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_search_prev_history(EditLine *el, int c)
+ed_search_prev_history(EditLine *el, int c __unused)
 {
 	const char *hp;
 	int h;
 	bool_t found = 0;
 
 	el->el_chared.c_vcmd.action = NOP;
-	el->el_chared.c_undo.action = NOP;
+	el->el_chared.c_undo.len = -1;
 	*el->el_line.lastchar = '\0';	/* just in case */
 	if (el->el_history.eventno < 0) {
 #ifdef DEBUG_EDIT
@@ -793,14 +772,14 @@ ed_search_prev_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_search_next_history(EditLine *el, int c)
+ed_search_next_history(EditLine *el, int c __unused)
 {
 	const char *hp;
 	int h;
 	bool_t found = 0;
 
 	el->el_chared.c_vcmd.action = NOP;
-	el->el_chared.c_undo.action = NOP;
+	el->el_chared.c_undo.len = -1;
 	*el->el_line.lastchar = '\0';	/* just in case */
 
 	if (el->el_history.eventno == 0)
@@ -847,7 +826,7 @@ ed_search_next_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_line(EditLine *el, int c)
+ed_prev_line(EditLine *el, int c __unused)
 {
 	char *ptr;
 	int nchars = c_hpos(el);
@@ -890,7 +869,7 @@ ed_prev_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_next_line(EditLine *el, int c)
+ed_next_line(EditLine *el, int c __unused)
 {
 	char *ptr;
 	int nchars = c_hpos(el);
@@ -924,30 +903,18 @@ ed_next_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_command(EditLine *el, int c)
+ed_command(EditLine *el, int c __unused)
 {
 	char tmpbuf[EL_BUFSIZ];
 	int tmplen;
 
-	el->el_line.buffer[0] = '\0';
-	el->el_line.lastchar = el->el_line.buffer;
-	el->el_line.cursor = el->el_line.buffer;
+	tmplen = c_gets(el, tmpbuf, "\n: ");
+	term__putc('\n');
 
-	c_insert(el, 3);	/* prompt + ": " */
-	*el->el_line.cursor++ = '\n';
-	*el->el_line.cursor++ = ':';
-	*el->el_line.cursor++ = ' ';
-	re_refresh(el);
+	if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
+		term_beep(el);
 
-	tmplen = c_gets(el, tmpbuf);
-	tmpbuf[tmplen] = '\0';
-
-	el->el_line.buffer[0] = '\0';
-	el->el_line.lastchar = el->el_line.buffer;
-	el->el_line.cursor = el->el_line.buffer;
-
-	if (parse_line(el, tmpbuf) == -1)
-		return (CC_ERROR);
-	else
-		return (CC_REFRESH);
+	el->el_map.current = el->el_map.key;
+	re_clear_display(el);
+	return CC_REFRESH;
 }
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
index 56c81f49a1cf..b733c797fb6b 100644
--- a/lib/libedit/editline.3
+++ b/lib/libedit/editline.3
@@ -1,6 +1,6 @@
-.\"	$NetBSD: editline.3,v 1.20 2000/02/28 17:41:05 chopps Exp $
+.\"	$NetBSD: editline.3,v 1.48 2005/07/14 15:02:37 wiz Exp $
 .\"
-.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
 .\" All rights reserved.
 .\"
 .\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
@@ -35,7 +35,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 12, 1999
+.Dd July 14, 2005
 .Os
 .Dt EDITLINE 3
 .Sh NAME
@@ -55,8 +55,13 @@
 .Nm el_deletestr ,
 .Nm history_init ,
 .Nm history_end ,
-.Nm history
-.Nd line editor and history functions
+.Nm history ,
+.Nm tok_init ,
+.Nm tok_end ,
+.Nm tok_reset ,
+.Nm tok_line ,
+.Nm tok_str
+.Nd line editor, history and tokenization functions
 .Sh LIBRARY
 .Lb libedit
 .Sh SYNOPSIS
@@ -74,7 +79,7 @@
 .Ft void
 .Fn el_push "EditLine *e" "const char *str"
 .Ft int
-.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
+.Fn el_parse "EditLine *e" "int argc" "const char *argv[]"
 .Ft int
 .Fn el_set "EditLine *e" "int op" "..."
 .Ft int
@@ -95,10 +100,20 @@
 .Fn history_end "History *h"
 .Ft int
 .Fn history "History *h" "HistEvent *ev" "int op" "..."
+.Ft Tokenizer *
+.Fn tok_init "const char *IFS"
+.Ft void
+.Fn tok_end "Tokenizer *t"
+.Ft void
+.Fn tok_reset "Tokenizer *t"
+.Ft int
+.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro"
+.Ft int
+.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]"
 .Sh DESCRIPTION
 The
 .Nm
-library provides generic line editing and history functions,
+library provides generic line editing, history and tokenization functions,
 similar to those found in
 .Xr sh 1 .
 .Pp
@@ -154,7 +169,7 @@ if no characters were read or if an error occurred.
 Read a character from the tty.
 .Fa ch
 is modified to contain the character read.
-Returns the number of characters read if successful, -1 otherwise.
+Returns the number of characters read if successful, \-1 otherwise.
 .It Fn el_push
 Pushes
 .Fa str
@@ -176,7 +191,7 @@ to execute builtin
 .Nm
 commands.
 If the command is prefixed with
-.Dq prog:
+.Dq prog :
 then
 .Fn el_parse
 will only execute the command if
@@ -186,7 +201,7 @@ matches the
 argument supplied to
 .Fn el_init .
 The return value is
--1 if the command is unknown,
+\-1 if the command is unknown,
 0 if there was no error or
 .Dq prog
 did not match, or
@@ -305,7 +320,7 @@ for more information.
 .It Dv EL_ADDFN , Xo
 .Fa "const char *name" ,
 .Fa "const char *help" ,
-.Fa "unsigned char (*func)(EditLine *e, int ch)
+.Fa "unsigned char (*func)(EditLine *e, int ch)"
 .Xc
 Add a user defined function,
 .Fn func ,
@@ -370,6 +385,24 @@ check this
 (using
 .Fn el_get )
 to determine if editing should be enabled or not.
+.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)"
+Define the character reading function as
+.Fa f ,
+which is to return the number of characters read and store them in
+.Fa c .
+This function is called internally by
+.Fn el_gets
+and
+.Fn el_getc .
+The builtin function can be set or restored with the special function
+name ``EL_BUILTIN_GETCFN''.
+.It Dv EL_CLIENTDATA , Fa "void *data"
+Register
+.Fa data
+to be associated with this EditLine structure.
+It can be retrieved with the corresponding
+.Fn el_get
+call.
 .El
 .It Fn el_get
 Get
@@ -378,6 +411,7 @@ parameters.
 .Fa op
 determines which parameter to retrieve into
 .Fa result .
+Returns 0 if successful, \-1 otherwise.
 .Pp
 The following values for
 .Fa op
@@ -401,6 +435,22 @@ has installed private signal handlers (see
 above).
 .It Dv EL_EDITMODE, Fa "int *"
 Return non-zero if editing is enabled.
+.It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)"
+Return a pointer to the function that read characters, which is equal to
+``EL_BUILTIN_GETCFN'' in the case of the default builtin function.
+.It Dv EL_CLIENTDATA , Fa "void **data"
+Retrieve
+.Fa data
+previously registered with the corresponding
+.Fn el_set
+call.
+.It Dv EL_UNBUFFERED, Fa "int"
+Sets or clears unbuffered mode.
+In this mode,
+.Fn el_gets
+will return immediately after processing a single character.
+.It Dv EL_PREP_TERM, Fa "int"
+Sets or clears terminal editing mode.
 .El
 .It Fn el_source
 Initialise
@@ -443,11 +493,21 @@ typedef struct lineinfo {
     const char *lastchar;  /* address of last character */
 } LineInfo;
 .Ed
+.Pp
+.Fa buffer
+is not NUL terminated.
+This function may be called after
+.Fn el_gets
+to obtain the
+.Fa LineInfo
+structure pertaining to line returned by that function,
+and from within user defined functions added with
+.Dv EL_ADDFN .
 .It Fn el_insertstr
 Insert
 .Fa str
 into the line at the cursor.
-Returns -1 if
+Returns \-1 if
 .Fa str
 is empty or will not fit, and 0 otherwise.
 .It Fn el_deletestr
@@ -527,7 +587,11 @@ Set the cursor to point to the requested element.
 .It Dv H_ADD , Fa "const char *str"
 Append
 .Fa str
-to the current element of the history, or create an element with
+to the current element of the history, or perform the
+.Dv H_ENTER
+operation with argument
+.Fa str
+if there is no current element.
 .It Dv H_APPEND , Fa "const char *str"
 Append
 .Fa str
@@ -537,6 +601,17 @@ Add
 .Fa str
 as a new element to the history, and, if necessary,
 removing the oldest entry to keep the list to the created size.
+If
+.Dv H_SETUNIQUE
+was has been called with a non-zero arguments, the element
+will not be entered into the history if its contents match
+the ones of the current history element.
+If the element is entered
+.Fn history
+returns 1, if it is ignored as a duplicate returns 0.
+Finally
+.Fn history
+returns \-1 if an error occurred.
 .It Dv H_PREV_STR , Fa "const char *str"
 Return the closest previous event that starts with
 .Fa str .
@@ -555,6 +630,20 @@ Load the history list stored in
 .It Dv H_SAVE , Fa "const char *file"
 Save the history list to
 .Fa file .
+.It Dv H_SETUNIQUE , Fa "int unique"
+Set if the adjacent identical event strings should not be entered into
+the history.
+.It Dv H_GETUNIQUE
+Retrieve the current setting if if adjacent elements should be entered into
+the history.
+.It Dv H_DEL , Fa "int num"
+Delete the event numbered
+.Fa e .
+This function is only provided for
+.Xr readline 3
+compatibility.
+The caller is responsible for free'ing the string in the returned
+.Fa HistEvent .
 .El
 .Pp
 The
@@ -566,6 +655,78 @@ Otherwise, \-1 is returned and
 .Fa ev
 is updated to contain more details about the error.
 .El
+.Sh TOKENIZATION FUNCTIONS
+The tokenization functions use a common data structure,
+.Fa Tokenizer ,
+which is created by
+.Fn tok_init
+and freed by
+.Fn tok_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn tok_init
+Initialise the tokenizer, and return a data structure
+to be used by all other tokenizer functions.
+.Fa IFS
+contains the Input Field Separators, which defaults to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline
+if
+.Dv NULL .
+.It Fn tok_end
+Clean up and finish with
+.Fa t ,
+assumed to have been created with
+.Fn tok_init .
+.It Fn tok_reset
+Reset the tokenizer state.
+Use after a line has been successfully tokenized
+by
+.Fn tok_line
+or
+.Fn tok_str
+and before a new line is to be tokenized.
+.It Fn tok_line
+Tokenize
+.Fa li ,
+If successful, modify:
+.Fa argv
+to contain the words,
+.Fa argc
+to contain the number of words,
+.Fa cursorc
+(if not
+.Dv NULL )
+to contain the index of the word containing the cursor,
+and
+.Fa cursoro
+(if not
+.Dv NULL )
+to contain the offset within
+.Fa argv[cursorc]
+of the cursor.
+.Pp
+Returns
+0 if successful,
+\-1 for an internal error,
+1 for an unmatched single quote,
+2 for an unmatched double quote,
+and
+3 for a backslash quoted
+.Aq newline .
+A positive exit code indicates that another line should be read
+and tokenization attempted again.
+.
+.It Fn tok_str
+A simpler form of
+.Fn tok_line ;
+.Fa str
+is a NUL terminated string to tokenize.
+.El
+.
 .\"XXX.Sh EXAMPLES
 .\"XXX: provide some examples
 .Sh SEE ALSO
@@ -603,9 +764,6 @@ wrote this manual and implemented
 and
 .Dv EL_RPROMPT .
 .Sh BUGS
-The tokenization functions are not publically defined in
-.In histedit.h .
-.Pp
 At this time, it is the responsibility of the caller to
 check the result of the
 .Dv EL_EDITMODE
diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5
index e1fba8bb1eba..35d30cc671a4 100644
--- a/lib/libedit/editrc.5
+++ b/lib/libedit/editrc.5
@@ -1,4 +1,4 @@
-.\"	$NetBSD: editrc.5,v 1.10 2000/11/08 00:09:38 lukem Exp $
+.\"	$NetBSD: editrc.5,v 1.19 2003/11/01 23:35:33 christos Exp $
 .\"
 .\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -35,7 +35,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 8, 2000
+.Dd October 18, 2003
 .Os
 .Dt EDITRC 5
 .Sh NAME
@@ -64,7 +64,7 @@ for more information.
 .Ar prog
 is the program name string that a program defines when it calls
 .Xr el_init 3
-to setup
+to set up
 .Xr editline 3 ,
 which is usually
 .Va argv[0] .
@@ -230,8 +230,24 @@ causes messages to be verbose.
 Enable or disable the
 .Nm editline
 functionality in a program.
-.It Ic history
-List the history.
+.It Ic history Ar list | Ar size Dv n | Ar unique Dv n
+The 
+.Ar list
+command lists all entries in the history.
+The
+.Ar size
+command sets the history size to
+.Dv n
+entries.
+The
+.Ar unique
+command controls if history should keep duplicate entries.
+If
+.Dv n
+is non zero, only keep unique history entries.
+If
+.Dv n
+is zero, then keep all entries (the default).
 .It Ic telltc
 List the values of all the terminal capabilities (see
 .Xr termcap 5 ) .
@@ -251,6 +267,7 @@ No sanity checking is done.
 .Op Ar +mode
 .Op Ar -mode
 .Op Ar mode
+.Op Ar char=c
 .Xc
 Control which tty modes that
 .Nm
@@ -287,6 +304,15 @@ fixes
 on or off or removes control of
 .Ar mode
 in the chosen set.
+.Pp
+.Ic Setty
+can also be used to set tty characters to particular values using
+.Ar char=value .
+If
+.Ar value
+is empty
+then the character is set to
+.Dv _POSIX_VDISABLE .
 .El
 .Sh EDITOR COMMANDS
 The following editor commands are available for use in key bindings:
diff --git a/lib/libedit/el.c b/lib/libedit/el.c
index 4491b30e45a8..e06628e58476 100644
--- a/lib/libedit/el.c
+++ b/lib/libedit/el.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: el.c,v 1.20 2000/11/11 22:18:57 christos Exp $
+ *	$NetBSD: el.c,v 1.40 2005/08/01 23:00:15 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -54,6 +50,8 @@ __FBSDID("$FreeBSD$");
 #include <stdarg.h>
 #include "el.h"
 
+#define	HAVE_ISSETUGID
+
 /* el_init():
  *	Initialize editline and set default parameters.
  */
@@ -62,9 +60,6 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
 {
 
 	EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
-#ifdef DEBUG
-	char *tty;
-#endif
 
 	if (el == NULL)
 		return (NULL);
@@ -74,14 +69,21 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
 	el->el_infd = fileno(fin);
 	el->el_outfile = fout;
 	el->el_errfile = ferr;
-	el->el_prog = strdup(prog);
+	if ((el->el_prog = el_strdup(prog)) == NULL) {
+		el_free(el);
+		return NULL;
+	}
 
 	/*
          * Initialize all the modules. Order is important!!!
          */
 	el->el_flags = 0;
 
-	(void) term_init(el);
+	if (term_init(el) == -1) {
+		el_free(el->el_prog);
+		el_free(el);
+		return NULL;
+	}
 	(void) key_init(el);
 	(void) map_init(el);
 	if (tty_init(el) == -1)
@@ -91,7 +93,7 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
 	(void) hist_init(el);
 	(void) prompt_init(el);
 	(void) sig_init(el);
-	el->data = NULL;
+	(void) read_init(el);
 
 	return (el);
 }
@@ -132,7 +134,7 @@ el_reset(EditLine *el)
 {
 
 	tty_cookedmode(el);
-	ch_reset(el);		/* XXX: Do we want that? */
+	ch_reset(el, 0);		/* XXX: Do we want that? */
 }
 
 
@@ -143,11 +145,12 @@ public int
 el_set(EditLine *el, int op, ...)
 {
 	va_list va;
-	int rv;
-	va_start(va, op);
+	int rv = 0;
 
 	if (el == NULL)
 		return (-1);
+	va_start(va, op);
+
 	switch (op) {
 	case EL_PROMPT:
 	case EL_RPROMPT:
@@ -167,7 +170,6 @@ el_set(EditLine *el, int op, ...)
 			el->el_flags |= HANDLE_SIGNALS;
 		else
 			el->el_flags &= ~HANDLE_SIGNALS;
-		rv = 0;
 		break;
 
 	case EL_BIND:
@@ -176,7 +178,7 @@ el_set(EditLine *el, int op, ...)
 	case EL_ECHOTC:
 	case EL_SETTY:
 	{
-		char *argv[20];
+		const char *argv[20];
 		int i;
 
 		for (i = 1; i < 20; i++)
@@ -244,8 +246,41 @@ el_set(EditLine *el, int op, ...)
 		rv = 0;
 		break;
 
+	case EL_GETCFN:
+	{
+		el_rfunc_t rc = va_arg(va, el_rfunc_t);
+		rv = el_read_setfn(el, rc);
+		break;
+	}
+
+	case EL_CLIENTDATA:
+		el->el_data = va_arg(va, void *);
+		break;
+
+	case EL_UNBUFFERED:
+		rv = va_arg(va, int);
+		if (rv && !(el->el_flags & UNBUFFERED)) {
+			el->el_flags |= UNBUFFERED;
+			read_prepare(el);
+		} else if (!rv && (el->el_flags & UNBUFFERED)) {
+			el->el_flags &= ~UNBUFFERED;
+			read_finish(el);
+		}
+		rv = 0;
+		break;
+
+	case EL_PREP_TERM:
+		rv = va_arg(va, int);
+		if (rv)
+			(void) tty_rawmode(el);
+		else
+			(void) tty_cookedmode(el);
+		rv = 0;
+		break;
+
 	default:
 		rv = -1;
+		break;
 	}
 
 	va_end(va);
@@ -266,11 +301,11 @@ el_get(EditLine *el, int op, void *ret)
 	switch (op) {
 	case EL_PROMPT:
 	case EL_RPROMPT:
-		rv = prompt_get(el, (el_pfunc_t *) & ret, op);
+		rv = prompt_get(el, (void *) &ret, op);
 		break;
 
 	case EL_EDITOR:
-		rv = map_get_editor(el, (const char **) &ret);
+		rv = map_get_editor(el, (void *) &ret);
 		break;
 
 	case EL_SIGNAL:
@@ -283,21 +318,22 @@ el_get(EditLine *el, int op, void *ret)
 		rv = 0;
 		break;
 
-#if 0				/* XXX */
 	case EL_TERMINAL:
-		rv = term_get(el, (const char *) &ret);
+		term_get(el, (const char **)ret);
+		rv = 0;
 		break;
 
+#if 0				/* XXX */
 	case EL_BIND:
 	case EL_TELLTC:
 	case EL_SETTC:
 	case EL_ECHOTC:
 	case EL_SETTY:
 	{
-		char *argv[20];
+		const char *argv[20];
 		int i;
 
-		for (i = 1; i < 20; i++)
+ 		for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++)
 			if ((argv[i] = va_arg(va, char *)) == NULL)
 				break;
 
@@ -354,6 +390,21 @@ el_get(EditLine *el, int op, void *ret)
 		break;
 #endif /* XXX */
 
+	case EL_GETCFN:
+		*((el_rfunc_t *)ret) = el_read_getfn(el);
+		rv = 0;
+		break;
+
+	case EL_CLIENTDATA:
+		*((void **)ret) = el->el_data;
+		rv = 0;
+		break;
+
+	case EL_UNBUFFERED:
+		*((int *) ret) = (!(el->el_flags & UNBUFFERED));
+		rv = 0;
+		break;
+
 	default:
 		rv = -1;
 	}
@@ -369,7 +420,7 @@ el_data_set (el, data)
     EditLine *el;
     void *data;
 {
-    el->data = data;
+    el->el_data = data;
 
     return;
 }
@@ -381,8 +432,8 @@ public void *
 el_data_get (el)
     EditLine *el;
 {
-    if (el->data)
-	return (el->data);
+    if (el->el_data)
+	return (el->el_data);
     return (NULL);
 }
 
@@ -396,7 +447,6 @@ el_line(EditLine *el)
 	return (const LineInfo *) (void *) &el->el_line;
 }
 
-static const char elpath[] = "/.editrc";
 
 /* el_source():
  *	Source a file
@@ -406,10 +456,14 @@ el_source(EditLine *el, const char *fname)
 {
 	FILE *fp;
 	size_t len;
-	char *ptr, path[MAXPATHLEN];
+	char *ptr;
 
 	fp = NULL;
 	if (fname == NULL) {
+#ifdef HAVE_ISSETUGID
+		static const char elpath[] = "/.editrc";
+		char path[MAXPATHLEN];
+
 		if (issetugid())
 			return (-1);
 		if ((ptr = getenv("HOME")) == NULL)
@@ -419,6 +473,14 @@ el_source(EditLine *el, const char *fname)
 		if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
 			return (-1);
 		fname = path;
+#else
+		/*
+		 * If issetugid() is missing, always return an error, in order
+		 * to keep from inadvertently opening up the user to a security
+		 * hole.
+		 */
+		return (-1);
+#endif
 	}
 	if (fp == NULL)
 		fp = fopen(fname, "r");
@@ -477,7 +539,7 @@ el_beep(EditLine *el)
  */
 protected int
 /*ARGSUSED*/
-el_editmode(EditLine *el, int argc, char **argv)
+el_editmode(EditLine *el, int argc, const char **argv)
 {
 	const char *how;
 
@@ -485,10 +547,13 @@ el_editmode(EditLine *el, int argc, char **argv)
 		return (-1);
 
 	how = argv[1];
-	if (strcmp(how, "on") == 0)
+	if (strcmp(how, "on") == 0) {
 		el->el_flags &= ~EDIT_DISABLED;
-	else if (strcmp(how, "off") == 0)
+		tty_rawmode(el);
+	} else if (strcmp(how, "off") == 0) {
+		tty_cookedmode(el);
 		el->el_flags |= EDIT_DISABLED;
+	}
 	else {
 		(void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
 		return (-1);
diff --git a/lib/libedit/el.h b/lib/libedit/el.h
index 655b3912b763..fb07e26ed0df 100644
--- a/lib/libedit/el.h
+++ b/lib/libedit/el.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)el.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: el.h,v 1.7 2000/11/11 22:18:57 christos Exp $
+ *	$NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $
  * $FreeBSD$
  */
 
@@ -55,9 +51,10 @@
 
 #define	EL_BUFSIZ	1024		/* Maximum line size		*/
 
-#define	HANDLE_SIGNALS	1<<0
-#define	NO_TTY		1<<1
-#define	EDIT_DISABLED	1<<2
+#define	HANDLE_SIGNALS	0x01
+#define	NO_TTY		0x02
+#define	EDIT_DISABLED	0x04
+#define	UNBUFFERED	0x08
 
 typedef int bool_t;			/* True or not			*/
 
@@ -72,7 +69,7 @@ typedef struct el_line_t {
 	char	*buffer;		/* Input line			*/
 	char	*cursor;		/* Cursor position		*/
 	char	*lastchar;		/* Last character		*/
-	const char	*limit;			/* Max position			*/
+	const char	*limit;		/* Max position			*/
 } el_line_t;
 
 /*
@@ -84,11 +81,14 @@ typedef struct el_state_t {
 	int		argument;	/* Numeric argument		*/
 	int		metanext;	/* Is the next char a meta char */
 	el_action_t	lastcmd;	/* Previous command		*/
+	el_action_t	thiscmd;	/* this command 		*/
+	char		thisch;		/* char that generated it	*/
 } el_state_t;
 
 /*
  * Until we come up with something better...
  */
+#define	el_strdup(a)	strdup(a)
 #define	el_malloc(a)	malloc(a)
 #define	el_realloc(a,b)	realloc(a, b)
 #define	el_free(a)	free(a)
@@ -106,6 +106,7 @@ typedef struct el_state_t {
 #include "parse.h"
 #include "sig.h"
 #include "help.h"
+#include "read.h"
 
 struct editline {
 	char		 *el_prog;	/* the program name		*/
@@ -116,6 +117,7 @@ struct editline {
 	coord_t		  el_cursor;	/* Cursor location		*/
 	char		**el_display;	/* Real screen image = what is there */
 	char		**el_vdisplay;	/* Virtual screen image = what we see */
+	void		 *el_data;	/* Client data			*/
 	el_line_t	  el_line;	/* The current line information	*/
 	el_state_t	  el_state;	/* Current editor state		*/
 	el_term_t	  el_term;	/* Terminal dependent stuff	*/
@@ -129,15 +131,18 @@ struct editline {
 	el_history_t	  el_history;	/* History stuff		*/
 	el_search_t	  el_search;	/* Search stuff			*/
 	el_signal_t	  el_signal;	/* Signal handling stuff	*/
-
-	void		 *data;		/* user data */
+	el_read_t	  el_read;	/* Character reading stuff	*/
 };
 
-protected int	el_editmode(EditLine *, int, char **);
+protected int	el_editmode(EditLine *, int, const char **);
 
 #ifdef DEBUG
-#define EL_ABORT(a)	(void) (fprintf(el->el_errfile, "%s, %d: ", \
-				__FILE__, __LINE__), fprintf a, abort())
+#define	EL_ABORT(a)	do { \
+				fprintf(el->el_errfile, "%s, %d: ", \
+					 __FILE__, __LINE__); \
+				fprintf a; \
+				abort(); \
+			} while( /*CONSTCOND*/0);
 #else
 #define EL_ABORT(a)	abort()
 #endif
diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c
index eff478dfdbbc..e66961bf4f73 100644
--- a/lib/libedit/emacs.c
+++ b/lib/libedit/emacs.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: emacs.c,v 1.8 2000/09/04 22:06:29 lukem Exp $
+ *	$NetBSD: emacs.c,v 1.19 2004/10/28 21:14:52 dsl Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -54,7 +50,7 @@ __FBSDID("$FreeBSD$");
  */
 protected el_action_t
 /*ARGSUSED*/
-em_delete_or_list(EditLine *el, int c)
+em_delete_or_list(EditLine *el, int c __unused)
 {
 
 	if (el->el_line.cursor == el->el_line.lastchar) {
@@ -73,7 +69,10 @@ em_delete_or_list(EditLine *el, int c)
 			return (CC_ERROR);
 		}
 	} else {
-		c_delafter(el, el->el_state.argument);	/* delete after dot */
+		if (el->el_state.doingarg)
+			c_delafter(el, el->el_state.argument);
+		else
+			c_delafter1(el);
 		if (el->el_line.cursor > el->el_line.lastchar)
 			el->el_line.cursor = el->el_line.lastchar;
 				/* bounds check */
@@ -88,7 +87,7 @@ em_delete_or_list(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_delete_next_word(EditLine *el, int c)
+em_delete_next_word(EditLine *el, int c __unused)
 {
 	char *cp, *p, *kp;
 
@@ -117,14 +116,12 @@ em_delete_next_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_yank(EditLine *el, int c)
+em_yank(EditLine *el, int c __unused)
 {
 	char *kp, *cp;
 
-	if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) {
-		if (!ch_enlargebufs(el, 1))
-			return (CC_ERROR);
-	}
+	if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
+		return (CC_NORM);
 
 	if (el->el_line.lastchar +
 	    (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
@@ -154,7 +151,7 @@ em_yank(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_kill_line(EditLine *el, int c)
+em_kill_line(EditLine *el, int c __unused)
 {
 	char *kp, *cp;
 
@@ -176,7 +173,7 @@ em_kill_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_kill_region(EditLine *el, int c)
+em_kill_region(EditLine *el, int c __unused)
 {
 	char *kp, *cp;
 
@@ -209,11 +206,11 @@ em_kill_region(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_copy_region(EditLine *el, int c)
+em_copy_region(EditLine *el, int c __unused)
 {
 	char *kp, *cp;
 
-	if (el->el_chared.c_kill.mark)
+	if (!el->el_chared.c_kill.mark)
 		return (CC_ERROR);
 
 	if (el->el_chared.c_kill.mark > el->el_line.cursor) {
@@ -233,12 +230,12 @@ em_copy_region(EditLine *el, int c)
 }
 
 
-/* em_gosmacs_traspose():
+/* em_gosmacs_transpose():
  *	Exchange the two characters before the cursor
  *	Gosling emacs transpose chars [^T]
  */
 protected el_action_t
-em_gosmacs_traspose(EditLine *el, int c)
+em_gosmacs_transpose(EditLine *el, int c)
 {
 
 	if (el->el_line.cursor > &el->el_line.buffer[1]) {
@@ -258,7 +255,7 @@ em_gosmacs_traspose(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_next_word(EditLine *el, int c)
+em_next_word(EditLine *el, int c __unused)
 {
 	if (el->el_line.cursor == el->el_line.lastchar)
 		return (CC_ERROR);
@@ -269,7 +266,7 @@ em_next_word(EditLine *el, int c)
 	    ce__isword);
 
 	if (el->el_map.type == MAP_VI)
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -283,7 +280,7 @@ em_next_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_upper_case(EditLine *el, int c)
+em_upper_case(EditLine *el, int c __unused)
 {
 	char *cp, *ep;
 
@@ -291,8 +288,8 @@ em_upper_case(EditLine *el, int c)
 	    el->el_state.argument, ce__isword);
 
 	for (cp = el->el_line.cursor; cp < ep; cp++)
-		if (islower((unsigned char) *cp))
-			*cp = toupper((unsigned char) *cp);
+		if (islower((unsigned char)*cp))
+			*cp = toupper((unsigned char)*cp);
 
 	el->el_line.cursor = ep;
 	if (el->el_line.cursor > el->el_line.lastchar)
@@ -307,7 +304,7 @@ em_upper_case(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_capitol_case(EditLine *el, int c)
+em_capitol_case(EditLine *el, int c __unused)
 {
 	char *cp, *ep;
 
@@ -315,16 +312,16 @@ em_capitol_case(EditLine *el, int c)
 	    el->el_state.argument, ce__isword);
 
 	for (cp = el->el_line.cursor; cp < ep; cp++) {
-		if (isalpha((unsigned char) *cp)) {
-			if (islower((unsigned char) *cp))
-				*cp = toupper((unsigned char) *cp);
+		if (isalpha((unsigned char)*cp)) {
+			if (islower((unsigned char)*cp))
+				*cp = toupper((unsigned char)*cp);
 			cp++;
 			break;
 		}
 	}
 	for (; cp < ep; cp++)
-		if (isupper((unsigned char) *cp))
-			*cp = tolower((unsigned char) *cp);
+		if (isupper((unsigned char)*cp))
+			*cp = tolower((unsigned char)*cp);
 
 	el->el_line.cursor = ep;
 	if (el->el_line.cursor > el->el_line.lastchar)
@@ -339,7 +336,7 @@ em_capitol_case(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_lower_case(EditLine *el, int c)
+em_lower_case(EditLine *el, int c __unused)
 {
 	char *cp, *ep;
 
@@ -347,8 +344,8 @@ em_lower_case(EditLine *el, int c)
 	    el->el_state.argument, ce__isword);
 
 	for (cp = el->el_line.cursor; cp < ep; cp++)
-		if (isupper((unsigned char) *cp))
-			*cp = tolower((unsigned char) *cp);
+		if (isupper((unsigned char)*cp))
+			*cp = tolower((unsigned char)*cp);
 
 	el->el_line.cursor = ep;
 	if (el->el_line.cursor > el->el_line.lastchar)
@@ -363,7 +360,7 @@ em_lower_case(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_set_mark(EditLine *el, int c)
+em_set_mark(EditLine *el, int c __unused)
 {
 
 	el->el_chared.c_kill.mark = el->el_line.cursor;
@@ -377,7 +374,7 @@ em_set_mark(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_exchange_mark(EditLine *el, int c)
+em_exchange_mark(EditLine *el, int c __unused)
 {
 	char *cp;
 
@@ -394,7 +391,7 @@ em_exchange_mark(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_universal_argument(EditLine *el, int c)
+em_universal_argument(EditLine *el, int c __unused)
 {				/* multiply current argument by 4 */
 
 	if (el->el_state.argument > 1000000)
@@ -411,7 +408,7 @@ em_universal_argument(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_meta_next(EditLine *el, int c)
+em_meta_next(EditLine *el, int c __unused)
 {
 
 	el->el_state.metanext = 1;
@@ -424,7 +421,7 @@ em_meta_next(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_toggle_overwrite(EditLine *el, int c)
+em_toggle_overwrite(EditLine *el, int c __unused)
 {
 
 	el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
@@ -438,7 +435,7 @@ em_toggle_overwrite(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_copy_prev_word(EditLine *el, int c)
+em_copy_prev_word(EditLine *el, int c __unused)
 {
 	char *cp, *oldc, *dp;
 
@@ -465,7 +462,7 @@ em_copy_prev_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_inc_search_next(EditLine *el, int c)
+em_inc_search_next(EditLine *el, int c __unused)
 {
 
 	el->el_search.patlen = 0;
@@ -478,9 +475,32 @@ em_inc_search_next(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_inc_search_prev(EditLine *el, int c)
+em_inc_search_prev(EditLine *el, int c __unused)
 {
 
 	el->el_search.patlen = 0;
 	return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
 }
+
+
+/* em_delete_prev_char():
+ *	Delete the character to the left of the cursor
+ *	[^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_prev_char(EditLine *el, int c __unused)
+{
+
+	if (el->el_line.cursor <= el->el_line.buffer)
+		return (CC_ERROR);
+
+	if (el->el_state.doingarg)
+		c_delbefore(el, el->el_state.argument);
+	else
+		c_delbefore1(el);
+	el->el_line.cursor -= el->el_state.argument;
+	if (el->el_line.cursor < el->el_line.buffer)
+		el->el_line.cursor = el->el_line.buffer;
+	return (CC_REFRESH);
+}
diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c
index f4bbf5dee2e3..601e10272dce 100644
--- a/lib/libedit/hist.c
+++ b/lib/libedit/hist.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: hist.c,v 1.8 2001/01/10 07:45:41 jdolecek Exp $
+ *	$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -130,18 +126,16 @@ hist_get(EditLine *el)
 			el->el_history.eventno = h;
 			return (CC_ERROR);
 		}
-	(void) strncpy(el->el_line.buffer, hp,
+	(void) strlcpy(el->el_line.buffer, hp,
 			(size_t)(el->el_line.limit - el->el_line.buffer));
 	el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
 
-	if (el->el_line.lastchar > el->el_line.buffer) {
-		if (el->el_line.lastchar[-1] == '\n')
-			el->el_line.lastchar--;
-		if (el->el_line.lastchar[-1] == ' ')
-			el->el_line.lastchar--;
-		if (el->el_line.lastchar < el->el_line.buffer)
-			el->el_line.lastchar = el->el_line.buffer;
-	}
+	if (el->el_line.lastchar > el->el_line.buffer
+	    && el->el_line.lastchar[-1] == '\n')
+		el->el_line.lastchar--;
+	if (el->el_line.lastchar > el->el_line.buffer
+	    && el->el_line.lastchar[-1] == ' ')
+		el->el_line.lastchar--;
 #ifdef KSHVI
 	if (el->el_map.type == MAP_VI)
 		el->el_line.cursor = el->el_line.buffer;
@@ -153,21 +147,40 @@ hist_get(EditLine *el)
 }
 
 
-/* hist_list()
- *	List history entries
+/* hist_command()
+ *	process a history command
  */
 protected int
-/*ARGSUSED*/
-hist_list(EditLine *el, int argc, char **argv)
+hist_command(EditLine *el, int argc, const char **argv)
 {
 	const char *str;
+	int num;
+	HistEvent ev;
 
 	if (el->el_history.ref == NULL)
 		return (-1);
-	for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
-		(void) fprintf(el->el_outfile, "%d %s",
-		    el->el_history.ev.num, str);
-	return (0);
+
+	if (argc == 1 || strcmp(argv[1], "list") == 0) {
+		 /* List history entries */
+
+		for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
+			(void) fprintf(el->el_outfile, "%d %s",
+			    el->el_history.ev.num, str);
+		return (0);
+	}
+
+	if (argc != 3)
+		return (-1);
+
+	num = (int)strtol(argv[2], NULL, 0);
+
+	if (strcmp(argv[1], "size") == 0)
+		return history(el->el_history.ref, &ev, H_SETSIZE, num);
+
+	if (strcmp(argv[1], "unique") == 0)
+		return history(el->el_history.ref, &ev, H_SETUNIQUE, num);
+
+	return -1;
 }
 
 /* hist_enlargebuf()
diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h
index 7fbaaa4a5c78..4f2824aff200 100644
--- a/lib/libedit/hist.h
+++ b/lib/libedit/hist.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)hist.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: hist.h,v 1.5 2000/09/04 22:06:30 lukem Exp $
+ *	$NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $
  * $FreeBSD$
  */
 
@@ -66,7 +62,7 @@ typedef struct el_history_t {
 #define	HIST_FIRST(el)		HIST_FUN(el, H_FIRST, NULL)
 #define	HIST_LAST(el)		HIST_FUN(el, H_LAST, NULL)
 #define	HIST_PREV(el)		HIST_FUN(el, H_PREV, NULL)
-#define	HIST_EVENT(el, num)	HIST_FUN(el, H_EVENT, num)
+#define	HIST_SET(el, num)	HIST_FUN(el, H_SET, num)
 #define	HIST_LOAD(el, fname)	HIST_FUN(el, H_LOAD fname)
 #define	HIST_SAVE(el, fname)	HIST_FUN(el, H_SAVE fname)
 
@@ -74,7 +70,7 @@ protected int		hist_init(EditLine *);
 protected void		hist_end(EditLine *);
 protected el_action_t	hist_get(EditLine *);
 protected int		hist_set(EditLine *, hist_fun_t, ptr_t);
-protected int		hist_list(EditLine *, int, char **);
+protected int		hist_command(EditLine *, int, const char **);
 protected int		hist_enlargebuf(EditLine *, size_t, size_t);
 
 #endif /* _h_el_hist */
diff --git a/lib/libedit/history.c b/lib/libedit/history.c
index f2e6aee6fdce..af4892a92a21 100644
--- a/lib/libedit/history.c
+++ b/lib/libedit/history.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: history.c,v 1.16 2000/09/04 22:06:30 lukem Exp $
+ *	$NetBSD: history.c,v 1.31 2005/08/01 14:34:06 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -71,10 +67,12 @@ struct history {
 	history_gfun_t h_prev;	/* Get the previous element	 */
 	history_gfun_t h_curr;	/* Get the current element	 */
 	history_sfun_t h_set;	/* Set the current element	 */
+	history_sfun_t h_del;	/* Set the given element	 */
 	history_vfun_t h_clear;	/* Clear the history list	 */
 	history_efun_t h_enter;	/* Add an element		 */
 	history_efun_t h_add;	/* Append to an element		 */
 };
+
 #define	HNEXT(h, ev)		(*(h)->h_next)((h)->h_ref, ev)
 #define	HFIRST(h, ev)		(*(h)->h_first)((h)->h_ref, ev)
 #define	HPREV(h, ev)		(*(h)->h_prev)((h)->h_ref, ev)
@@ -84,14 +82,24 @@ struct history {
 #define	HCLEAR(h, ev)		(*(h)->h_clear)((h)->h_ref, ev)
 #define	HENTER(h, ev, str)	(*(h)->h_enter)((h)->h_ref, ev, str)
 #define	HADD(h, ev, str)	(*(h)->h_add)((h)->h_ref, ev, str)
+#define	HDEL(h, ev, n)		(*(h)->h_del)((h)->h_ref, ev, n)
 
+#define	h_strdup(a)	strdup(a)
 #define	h_malloc(a)	malloc(a)
 #define	h_realloc(a, b)	realloc((a), (b))
 #define	h_free(a)	free(a)
 
+typedef struct {
+    int		num;
+    char	*str;
+} HistEventPrivate;
+
+
 
 private int history_setsize(History *, HistEvent *, int);
 private int history_getsize(History *, HistEvent *);
+private int history_setunique(History *, HistEvent *, int);
+private int history_getunique(History *, HistEvent *);
 private int history_set_fun(History *, History *);
 private int history_load(History *, const char *);
 private int history_save(History *, const char *);
@@ -110,31 +118,41 @@ typedef struct hentry_t {
 	HistEvent ev;		/* What we return		 */
 	struct hentry_t *next;	/* Next entry			 */
 	struct hentry_t *prev;	/* Previous entry		 */
-}        hentry_t;
+} hentry_t;
 
 typedef struct history_t {
-	hentry_t list;		/* Fake list header element	 */
-	hentry_t *cursor;	/* Current element in the list	 */
-	int max;		/* Maximum number of events	 */
-	int cur;		/* Current number of events	 */
+	hentry_t list;		/* Fake list header element	*/
+	hentry_t *cursor;	/* Current element in the list	*/
+	int max;		/* Maximum number of events	*/
+	int cur;		/* Current number of events	*/
 	int eventid;		/* For generation of unique event id	 */
-}         history_t;
+	int flags;		/* History flags		*/
+#define H_UNIQUE	1	/* Store only unique elements	*/
+} history_t;
 
-private int history_def_first(ptr_t, HistEvent *);
-private int history_def_last(ptr_t, HistEvent *);
 private int history_def_next(ptr_t, HistEvent *);
+private int history_def_first(ptr_t, HistEvent *);
 private int history_def_prev(ptr_t, HistEvent *);
+private int history_def_last(ptr_t, HistEvent *);
 private int history_def_curr(ptr_t, HistEvent *);
-private int history_def_set(ptr_t, HistEvent *, const int n);
+private int history_def_set(ptr_t, HistEvent *, const int);
+private void history_def_clear(ptr_t, HistEvent *);
 private int history_def_enter(ptr_t, HistEvent *, const char *);
 private int history_def_add(ptr_t, HistEvent *, const char *);
-private void history_def_init(ptr_t *, HistEvent *, int);
-private void history_def_clear(ptr_t, HistEvent *);
+private int history_def_del(ptr_t, HistEvent *, const int);
+
+private int history_def_init(ptr_t *, HistEvent *, int);
 private int history_def_insert(history_t *, HistEvent *, const char *);
 private void history_def_delete(history_t *, HistEvent *, hentry_t *);
 
-#define	history_def_setsize(p, num)(void) (((history_t *) p)->max = (num))
-#define	history_def_getsize(p)  (((history_t *) p)->cur)
+#define	history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
+#define	history_def_getsize(p)  (((history_t *)p)->cur)
+#define	history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
+#define	history_def_setunique(p, uni) \
+    if (uni) \
+	(((history_t *)p)->flags) |= H_UNIQUE; \
+    else \
+	(((history_t *)p)->flags) &= ~H_UNIQUE
 
 #define	he_strerror(code)	he_errlist[code]
 #define	he_seterrev(evp, code)	{\
@@ -227,20 +245,19 @@ history_def_next(ptr_t p, HistEvent *ev)
 {
 	history_t *h = (history_t *) p;
 
-	if (h->cursor != &h->list)
-		h->cursor = h->cursor->next;
-	else {
+	if (h->cursor == &h->list) {
 		he_seterrev(ev, _HE_EMPTY_LIST);
 		return (-1);
 	}
 
-	if (h->cursor != &h->list)
-		*ev = h->cursor->ev;
-	else {
+	if (h->cursor->next == &h->list) {
 		he_seterrev(ev, _HE_END_REACHED);
 		return (-1);
 	}
 
+        h->cursor = h->cursor->next;
+        *ev = h->cursor->ev;
+
 	return (0);
 }
 
@@ -253,21 +270,20 @@ history_def_prev(ptr_t p, HistEvent *ev)
 {
 	history_t *h = (history_t *) p;
 
-	if (h->cursor != &h->list)
-		h->cursor = h->cursor->prev;
-	else {
+	if (h->cursor == &h->list) {
 		he_seterrev(ev,
 		    (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
 		return (-1);
 	}
 
-	if (h->cursor != &h->list)
-		*ev = h->cursor->ev;
-	else {
+	if (h->cursor->prev == &h->list) {
 		he_seterrev(ev, _HE_START_REACHED);
 		return (-1);
 	}
 
+        h->cursor = h->cursor->prev;
+        *ev = h->cursor->ev;
+
 	return (0);
 }
 
@@ -328,39 +344,59 @@ history_def_add(ptr_t p, HistEvent *ev, const char *str)
 	history_t *h = (history_t *) p;
 	size_t len;
 	char *s;
+	HistEventPrivate *evp = (void *)&h->cursor->ev;
 
 	if (h->cursor == &h->list)
 		return (history_def_enter(p, ev, str));
-	len = strlen(h->cursor->ev.str) + strlen(str) + 1;
+	len = strlen(evp->str) + strlen(str) + 1;
 	s = (char *) h_malloc(len);
-	if (!s) {
+	if (s == NULL) {
 		he_seterrev(ev, _HE_MALLOC_FAILED);
 		return (-1);
 	}
 	(void) strlcpy(s, h->cursor->ev.str, len);
 	(void) strlcat(s, str, len);
-	/* LINTED const cast */
-	h_free((ptr_t) h->cursor->ev.str);
-	h->cursor->ev.str = s;
+	h_free((ptr_t)evp->str);
+	evp->str = s;
 	*ev = h->cursor->ev;
 	return (0);
 }
 
 
+/* history_def_del():
+ *	Delete element hp of the h list
+ */
+/* ARGSUSED */
+private int
+history_def_del(ptr_t p, HistEvent *ev __unused,
+    const int num)
+{
+	history_t *h = (history_t *) p;
+	if (history_def_set(h, ev, num) != 0)
+		return (-1);
+	ev->str = strdup(h->cursor->ev.str);
+	ev->num = h->cursor->ev.num;
+	history_def_delete(h, ev, h->cursor);
+	return (0);
+}
+
+
 /* history_def_delete():
  *	Delete element hp of the h list
  */
 /* ARGSUSED */
 private void
-history_def_delete(history_t *h, HistEvent *ev, hentry_t *hp)
+history_def_delete(history_t *h, 
+		   HistEvent *ev __unused, hentry_t *hp)
 {
-
+	HistEventPrivate *evp = (void *)&hp->ev;
 	if (hp == &h->list)
 		abort();
+	if (h->cursor == hp)
+		h->cursor = hp->prev;
 	hp->prev->next = hp->next;
 	hp->next->prev = hp->prev;
-	/* LINTED const cast */
-	h_free((ptr_t) hp->ev.str);
+	h_free((ptr_t) evp->str);
 	h_free(hp);
 	h->cur--;
 }
@@ -374,11 +410,11 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str)
 {
 
 	h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
-	if (h->cursor)
-		h->cursor->ev.str = strdup(str);
-	if (!h->cursor || !h->cursor->ev.str) {
-		he_seterrev(ev, _HE_MALLOC_FAILED);
-		return (-1);
+	if (h->cursor == NULL)
+		goto oomem;
+	if ((h->cursor->ev.str = h_strdup(str)) == NULL) {
+		h_free((ptr_t)h->cursor);
+		goto oomem;
 	}
 	h->cursor->ev.num = ++h->eventid;
 	h->cursor->next = h->list.next;
@@ -389,6 +425,9 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str)
 
 	*ev = h->cursor->ev;
 	return (0);
+oomem:
+	he_seterrev(ev, _HE_MALLOC_FAILED);
+	return (-1);
 }
 
 
@@ -400,6 +439,10 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)
 {
 	history_t *h = (history_t *) p;
 
+	if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
+	    strcmp(h->list.next->ev.str, str) == 0)
+	    return (0); 
+
 	if (history_def_insert(h, ev, str) == -1)
 		return (-1);	/* error, keep error message */
 
@@ -407,10 +450,10 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)
          * Always keep at least one entry.
          * This way we don't have to check for the empty list.
          */
-	while (h->cur - 1 > h->max)
+	while (h->cur > h->max && h->cur > 0)
 		history_def_delete(h, ev, h->list.prev);
 
-	return (0);
+	return (1);
 }
 
 
@@ -418,10 +461,12 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)
  *	Default history initialization function
  */
 /* ARGSUSED */
-private void
-history_def_init(ptr_t *p, HistEvent *ev, int n)
+private int
+history_def_init(ptr_t *p, HistEvent *ev __unused, int n)
 {
 	history_t *h = (history_t *) h_malloc(sizeof(history_t));
+	if (h == NULL)
+		return -1;
 
 	if (n <= 0)
 		n = 0;
@@ -432,7 +477,9 @@ history_def_init(ptr_t *p, HistEvent *ev, int n)
 	h->list.ev.str = NULL;
 	h->list.ev.num = 0;
 	h->cursor = &h->list;
+	h->flags = 0;
 	*p = (ptr_t) h;
+	return 0;
 }
 
 
@@ -461,10 +508,15 @@ history_def_clear(ptr_t p, HistEvent *ev)
 public History *
 history_init(void)
 {
-	History *h = (History *) h_malloc(sizeof(History));
 	HistEvent ev;
+	History *h = (History *) h_malloc(sizeof(History));
+	if (h == NULL)
+		return NULL;
 
-	history_def_init(&h->h_ref, &ev, 0);
+	if (history_def_init(&h->h_ref, &ev, 0) == -1) {
+		h_free((ptr_t)h);
+		return NULL;
+	}
 	h->h_ent = -1;
 	h->h_next = history_def_next;
 	h->h_first = history_def_first;
@@ -475,6 +527,7 @@ history_init(void)
 	h->h_clear = history_def_clear;
 	h->h_enter = history_def_enter;
 	h->h_add = history_def_add;
+	h->h_del = history_def_del;
 
 	return (h);
 }
@@ -490,6 +543,7 @@ history_end(History *h)
 
 	if (h->h_next == history_def_next)
 		history_def_clear(h->h_ref, &ev);
+	h_free(h);
 }
 
 
@@ -520,18 +574,46 @@ history_setsize(History *h, HistEvent *ev, int num)
 private int
 history_getsize(History *h, HistEvent *ev)
 {
-	int retval = 0;
+	if (h->h_next != history_def_next) {
+		he_seterrev(ev, _HE_NOT_ALLOWED);
+		return (-1);
+	}
+	ev->num = history_def_getsize(h->h_ref);
+	if (ev->num < -1) {
+		he_seterrev(ev, _HE_SIZE_NEGATIVE);
+		return (-1);
+	}
+	return (0);
+}
+
+
+/* history_setunique():
+ *	Set if adjacent equal events should not be entered in history.
+ */
+private int
+history_setunique(History *h, HistEvent *ev, int uni)
+{
 
 	if (h->h_next != history_def_next) {
 		he_seterrev(ev, _HE_NOT_ALLOWED);
 		return (-1);
 	}
-	retval = history_def_getsize(h->h_ref);
-	if (retval < -1) {
-		he_seterrev(ev, _HE_SIZE_NEGATIVE);
+	history_def_setunique(h->h_ref, uni);
+	return (0);
+}
+
+
+/* history_getunique():
+ *	Get if adjacent equal events should not be entered in history.
+ */
+private int
+history_getunique(History *h, HistEvent *ev)
+{
+	if (h->h_next != history_def_next) {
+		he_seterrev(ev, _HE_NOT_ALLOWED);
 		return (-1);
 	}
-	ev->num = retval;
+	ev->num = history_def_getunique(h->h_ref);
 	return (0);
 }
 
@@ -547,7 +629,7 @@ history_set_fun(History *h, History *nh)
 	if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
 	    nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
 	    nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
-	    nh->h_ref == NULL) {
+	    nh->h_del == NULL || nh->h_ref == NULL) {
 		if (h->h_next != history_def_next) {
 			history_def_init(&h->h_ref, &ev, 0);
 			h->h_first = history_def_first;
@@ -559,6 +641,7 @@ history_set_fun(History *h, History *nh)
 			h->h_clear = history_def_clear;
 			h->h_enter = history_def_enter;
 			h->h_add = history_def_add;
+			h->h_del = history_def_del;
 		}
 		return (-1);
 	}
@@ -575,6 +658,7 @@ history_set_fun(History *h, History *nh)
 	h->h_clear = nh->h_clear;
 	h->h_enter = nh->h_enter;
 	h->h_add = nh->h_add;
+	h->h_del = nh->h_del;
 
 	return (0);
 }
@@ -603,6 +687,8 @@ history_load(History *h, const char *fname)
 		goto done;
 
 	ptr = h_malloc(max_size = 1024);
+	if (ptr == NULL)
+		goto done;
 	for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
 		char c = line[sz];
 
@@ -612,15 +698,24 @@ history_load(History *h, const char *fname)
 			line[sz] = '\0';
 
 		if (max_size < sz) {
-			max_size = (sz + 1023) & ~1023;
-			ptr = h_realloc(ptr, max_size);
+			char *nptr;
+			max_size = (sz + 1024) & ~1023;
+			nptr = h_realloc(ptr, max_size);
+			if (nptr == NULL) {
+				i = -1;
+				goto oomem;
+			}
+			ptr = nptr;
 		}
 		(void) strunvis(ptr, line);
 		line[sz] = c;
-		HENTER(h, &ev, ptr);
+		if (HENTER(h, &ev, ptr) == -1) {
+			h_free((ptr_t)ptr);
+			return -1;
+		}
 	}
-	h_free(ptr);
-
+oomem:
+	h_free((ptr_t)ptr);
 done:
 	(void) fclose(fp);
 	return (i);
@@ -635,28 +730,40 @@ history_save(History *h, const char *fname)
 {
 	FILE *fp;
 	HistEvent ev;
-	int i = 0, retval;
+	int i = -1, retval;
 	size_t len, max_size;
 	char *ptr;
 
 	if ((fp = fopen(fname, "w")) == NULL)
 		return (-1);
 
-	(void) fchmod(fileno(fp), S_IRUSR|S_IWUSR);
-	(void) fputs(hist_cookie, fp);
+	if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
+		goto done;
+	if (fputs(hist_cookie, fp) == EOF)
+		goto done;
 	ptr = h_malloc(max_size = 1024);
-	for (retval = HLAST(h, &ev);
+	if (ptr == NULL)
+		goto done;
+	for (i = 0, retval = HLAST(h, &ev);
 	    retval != -1;
 	    retval = HPREV(h, &ev), i++) {
 		len = strlen(ev.str) * 4;
 		if (len >= max_size) {
-			max_size = (len + 1023) & 1023;
-			ptr = h_realloc(ptr, max_size);
+			char *nptr;
+			max_size = (len + 1024) & ~1023;
+			nptr = h_realloc(ptr, max_size);
+			if (nptr == NULL) {
+				i = -1;
+				goto oomem;
+			}
+			ptr = nptr;
 		}
 		(void) strvis(ptr, ev.str, VIS_WHITE);
 		(void) fprintf(fp, "%s\n", ptr);
 	}
-	h_free(ptr);
+oomem:
+	h_free((ptr_t)ptr);
+done:
 	(void) fclose(fp);
 	return (i);
 }
@@ -755,11 +862,23 @@ history(History *h, HistEvent *ev, int fun, ...)
 		retval = history_setsize(h, ev, va_arg(va, int));
 		break;
 
+	case H_GETUNIQUE:
+		retval = history_getunique(h, ev);
+		break;
+
+	case H_SETUNIQUE:
+		retval = history_setunique(h, ev, va_arg(va, int));
+		break;
+
 	case H_ADD:
 		str = va_arg(va, const char *);
 		retval = HADD(h, ev, str);
 		break;
 
+	case H_DEL:
+		retval = HDEL(h, ev, va_arg(va, const int));
+		break;
+
 	case H_ENTER:
 		str = va_arg(va, const char *);
 		if ((retval = HENTER(h, ev, str)) != -1)
@@ -844,6 +963,7 @@ history(History *h, HistEvent *ev, int fun, ...)
 		hf.h_clear = va_arg(va, history_vfun_t);
 		hf.h_enter = va_arg(va, history_efun_t);
 		hf.h_add = va_arg(va, history_efun_t);
+		hf.h_del = va_arg(va, history_sfun_t);
 
 		if ((retval = history_set_fun(h, &hf)) == -1)
 			he_seterrev(ev, _HE_PARAM_MISSING);
diff --git a/lib/libedit/key.c b/lib/libedit/key.c
index 7643f3d75d5d..ada5648e8e61 100644
--- a/lib/libedit/key.c
+++ b/lib/libedit/key.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: key.c,v 1.11 2001/01/23 15:55:30 jdolecek Exp $
+ *	$NetBSD: key.c,v 1.16 2005/07/06 21:13:02 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -63,7 +59,6 @@ __FBSDID("$FreeBSD$");
  *      1) It is not possible to have one key that is a
  *	   substr of another.
  */
-#include "sys.h"
 #include <string.h>
 #include <stdlib.h>
 
@@ -87,9 +82,11 @@ private int		 node_trav(EditLine *, key_node_t *, char *,
 private int		 node__try(EditLine *, key_node_t *, const char *,
     key_value_t *, int);
 private key_node_t	*node__get(int);
+private void		 node__free(key_node_t *);
 private void		 node__put(EditLine *, key_node_t *);
-private int		 node__delete(EditLine *, key_node_t **, char *);
-private int		 node_lookup(EditLine *, char *, key_node_t *, int);
+private int		 node__delete(EditLine *, key_node_t **, const char *);
+private int		 node_lookup(EditLine *, const char *, key_node_t *,
+    int);
 private int		 node_enum(EditLine *, key_node_t *, int);
 private int		 key__decode_char(char *, int, int);
 
@@ -111,7 +108,6 @@ key_init(EditLine *el)
 	return (0);
 }
 
-
 /* key_end():
  *	Free the key maps
  */
@@ -121,8 +117,7 @@ key_end(EditLine *el)
 
 	el_free((ptr_t) el->el_key.buf);
 	el->el_key.buf = NULL;
-	/* XXX: provide a function to clear the keys */
-	el->el_key.map = NULL;
+	node__free(el->el_key.map);
 }
 
 
@@ -216,7 +211,7 @@ key_add(EditLine *el, const char *key, key_value_t *val, int ntype)
  *
  */
 protected void
-key_clear(EditLine *el, el_action_t *map, char *in)
+key_clear(EditLine *el, el_action_t *map, const char *in)
 {
 
 	if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) &&
@@ -233,7 +228,7 @@ key_clear(EditLine *el, el_action_t *map, char *in)
  *      they exists.
  */
 protected int
-key_delete(EditLine *el, char *key)
+key_delete(EditLine *el, const char *key)
 {
 
 	if (key[0] == '\0') {
@@ -254,7 +249,7 @@ key_delete(EditLine *el, char *key)
  *	Print entire el->el_key.map if null
  */
 protected void
-key_print(EditLine *el, char *key)
+key_print(EditLine *el, const char *key)
 {
 
 	/* do nothing if el->el_key.map is empty and null key specified */
@@ -353,7 +348,8 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int
 			break;
 		case XK_STR:
 		case XK_EXE:
-			ptr->val.str = strdup(val->str);
+			if ((ptr->val.str = el_strdup(val->str)) == NULL)
+				return -1;
 			break;
 		default:
 			EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
@@ -373,7 +369,7 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int
  *	Delete node that matches str
  */
 private int
-node__delete(EditLine *el, key_node_t **inptr, char *str)
+node__delete(EditLine *el, key_node_t **inptr, const char *str)
 {
 	key_node_t *ptr;
 	key_node_t *prev_ptr = NULL;
@@ -468,14 +464,22 @@ node__get(int ch)
 	return (ptr);
 }
 
-
+private void
+node__free(key_node_t *k)
+{
+	if (k == NULL)
+		return;
+	node__free(k->sibling);
+	node__free(k->next);
+	el_free((ptr_t) k);
+}
 
 /* node_lookup():
  *	look for the str starting at node ptr.
  *	Print if last node
  */
 private int
-node_lookup(EditLine *el, char *str, key_node_t *ptr, int cnt)
+node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)
 {
 	int ncnt;
 
@@ -565,7 +569,7 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt)
  *	function specified by val
  */
 protected void
-key_kprint(EditLine *el, char *key, key_value_t *val, int ntype)
+key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)
 {
 	el_bindings_t *fp;
 	char unparsbuf[EL_BUFSIZ];
@@ -638,13 +642,15 @@ key__decode_char(char *buf, int cnt, int ch)
 	return (cnt);
 }
 
+
 /* key__decode_str():
  *	Make a printable version of the ey
  */
 protected char *
-key__decode_str(char *str, char *buf, char *sep)
+key__decode_str(const char *str, char *buf, const char *sep)
 {
-	char *b, *p;
+	char *b;
+	const char *p;
 
 	b = buf;
 	if (sep[0] != '\0')
diff --git a/lib/libedit/key.h b/lib/libedit/key.h
index c6d71881e840..c318788587c4 100644
--- a/lib/libedit/key.h
+++ b/lib/libedit/key.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)key.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: key.h,v 1.4 2000/09/04 22:06:30 lukem Exp $
+ *	$NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $
  * $FreeBSD$
  */
 
@@ -62,6 +58,10 @@ typedef struct el_key_t {
 #define	XK_NOD	2
 #define	XK_EXE	3
 
+#undef key_end
+#undef key_clear
+#undef key_print
+
 protected int		 key_init(EditLine *);
 protected void		 key_end(EditLine *);
 protected key_value_t	*key_map_cmd(EditLine *, int);
@@ -69,10 +69,11 @@ protected key_value_t	*key_map_str(EditLine *, char *);
 protected void		 key_reset(EditLine *);
 protected int		 key_get(EditLine *, char *, key_value_t *);
 protected void		 key_add(EditLine *, const char *, key_value_t *, int);
-protected void		 key_clear(EditLine *, el_action_t *, char *);
-protected int		 key_delete(EditLine *, char *);
-protected void		 key_print(EditLine *, char *);
-protected void	         key_kprint(EditLine *, char *, key_value_t *, int);
-protected char		*key__decode_str(char *, char *, char *);
+protected void		 key_clear(EditLine *, el_action_t *, const char *);
+protected int		 key_delete(EditLine *, const char *);
+protected void		 key_print(EditLine *, const char *);
+protected void	         key_kprint(EditLine *, const char *, key_value_t *,
+    int);
+protected char		*key__decode_str(const char *, char *, const char *);
 
 #endif /* _h_el_key */
diff --git a/lib/libedit/makelist b/lib/libedit/makelist
index 3201a1436c20..75faa417e83c 100644
--- a/lib/libedit/makelist
+++ b/lib/libedit/makelist
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$NetBSD: makelist,v 1.6 2000/09/04 23:45:18 lukem Exp $
+#	$NetBSD: makelist,v 1.9 2005/05/16 13:14:43 lukem Exp $
 # $FreeBSD$
 #
 # Copyright (c) 1992, 1993
@@ -16,11 +16,7 @@
 # 2. Redistributions in binary form must reproduce the above copyright
 #    notice, this list of conditions and the following disclaimer in the
 #    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 4. Neither the name of the University nor the names of its contributors
+# 3. Neither the name of the University nor the names of its contributors
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
 #
@@ -40,7 +36,7 @@
 
 # makelist.sh: Automatically generate header files...
 
-AWK=/usr/bin/awk
+AWK=awk
 USAGE="usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
 
 if [ "x$1" = "x" ]
diff --git a/lib/libedit/map.c b/lib/libedit/map.c
index eae4da2a9298..4f225e84545f 100644
--- a/lib/libedit/map.c
+++ b/lib/libedit/map.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: map.c,v 1.13 2001/01/04 15:56:32 christos Exp $
+ *	$NetBSD: map.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -51,7 +47,7 @@ __FBSDID("$FreeBSD$");
 
 #define	N_KEYS 256
 
-private void	map_print_key(EditLine *, el_action_t *, char *);
+private void	map_print_key(EditLine *, el_action_t *, const char *);
 private void	map_print_some_keys(EditLine *, el_action_t *, int, int);
 private void	map_print_all_keys(EditLine *);
 private void	map_init_nls(EditLine *);
@@ -69,7 +65,7 @@ private const el_action_t  el_map_emacs[] = {
 	/*   5 */	ED_MOVE_TO_END,		/* ^E */
 	/*   6 */	ED_NEXT_CHAR,		/* ^F */
 	/*   7 */	ED_UNASSIGNED,		/* ^G */
-	/*   8 */	ED_DELETE_PREV_CHAR,	/* ^H */
+	/*   8 */	EM_DELETE_PREV_CHAR,	/* ^H */
 	/*   9 */	ED_UNASSIGNED,		/* ^I */
 	/*  10 */	ED_NEWLINE,		/* ^J */
 	/*  11 */	ED_KILL_LINE,		/* ^K */
@@ -188,7 +184,7 @@ private const el_action_t  el_map_emacs[] = {
 	/* 124 */	ED_INSERT,		/* | */
 	/* 125 */	ED_INSERT,		/* } */
 	/* 126 */	ED_INSERT,		/* ~ */
-	/* 127 */	ED_DELETE_PREV_CHAR,	/* ^? */
+	/* 127 */	EM_DELETE_PREV_CHAR,	/* ^? */
 	/* 128 */	ED_UNASSIGNED,		/* M-^@ */
 	/* 129 */	ED_UNASSIGNED,		/* M-^A */
 	/* 130 */	ED_UNASSIGNED,		/* M-^B */
@@ -377,7 +373,7 @@ private const el_action_t  el_map_vi_insert[] = {
 	/*   5 */	ED_MOVE_TO_END,		/* ^E */
 	/*   6 */	ED_NEXT_CHAR,		/* ^F */
 	/*   7 */	ED_UNASSIGNED,		/* ^G */
-	/*   8 */	ED_DELETE_PREV_CHAR,	/* ^H */   /* BackSpace key */
+	/*   8 */	VI_DELETE_PREV_CHAR,	/* ^H */   /* BackSpace key */
 	/*   9 */	ED_UNASSIGNED,		/* ^I */   /* Tab Key */
 	/*  10 */	ED_NEWLINE,		/* ^J */
 	/*  11 */	ED_KILL_LINE,		/* ^K */
@@ -497,135 +493,135 @@ private const el_action_t  el_map_vi_insert[] = {
 	/* 124 */	ED_INSERT,		/* | */
 	/* 125 */	ED_INSERT,		/* } */
 	/* 126 */	ED_INSERT,		/* ~ */
-	/* 127 */	ED_DELETE_PREV_CHAR,	/* ^? */
-	/* 128 */	ED_UNASSIGNED,		/* M-^@ */
-	/* 129 */	ED_UNASSIGNED,		/* M-^A */
-	/* 130 */	ED_UNASSIGNED,		/* M-^B */
-	/* 131 */	ED_UNASSIGNED,		/* M-^C */
-	/* 132 */	ED_UNASSIGNED,		/* M-^D */
-	/* 133 */	ED_UNASSIGNED,		/* M-^E */
-	/* 134 */	ED_UNASSIGNED,		/* M-^F */
-	/* 135 */	ED_UNASSIGNED,		/* M-^G */
-	/* 136 */	ED_UNASSIGNED,		/* M-^H */
-	/* 137 */	ED_UNASSIGNED,		/* M-^I */
-	/* 138 */	ED_UNASSIGNED,		/* M-^J */
-	/* 139 */	ED_UNASSIGNED,		/* M-^K */
-	/* 140 */	ED_UNASSIGNED,		/* M-^L */
-	/* 141 */	ED_UNASSIGNED,		/* M-^M */
-	/* 142 */	ED_UNASSIGNED,		/* M-^N */
-	/* 143 */	ED_UNASSIGNED,		/* M-^O */
-	/* 144 */	ED_UNASSIGNED,		/* M-^P */
-	/* 145 */	ED_UNASSIGNED,		/* M-^Q */
-	/* 146 */	ED_UNASSIGNED,		/* M-^R */
-	/* 147 */	ED_UNASSIGNED,		/* M-^S */
-	/* 148 */	ED_UNASSIGNED,		/* M-^T */
-	/* 149 */	ED_UNASSIGNED,		/* M-^U */
-	/* 150 */	ED_UNASSIGNED,		/* M-^V */
-	/* 151 */	ED_UNASSIGNED,		/* M-^W */
-	/* 152 */	ED_UNASSIGNED,		/* M-^X */
-	/* 153 */	ED_UNASSIGNED,		/* M-^Y */
-	/* 154 */	ED_UNASSIGNED,		/* M-^Z */
-	/* 155 */	ED_UNASSIGNED,		/* M-^[ */
-	/* 156 */	ED_UNASSIGNED,		/* M-^\ */
-	/* 157 */	ED_UNASSIGNED,		/* M-^] */
-	/* 158 */	ED_UNASSIGNED,		/* M-^^ */
-	/* 159 */	ED_UNASSIGNED,		/* M-^_ */
-	/* 160 */	ED_UNASSIGNED,		/* M-SPACE */
-	/* 161 */	ED_UNASSIGNED,		/* M-! */
-	/* 162 */	ED_UNASSIGNED,		/* M-" */
-	/* 163 */	ED_UNASSIGNED,		/* M-# */
-	/* 164 */	ED_UNASSIGNED,		/* M-$ */
-	/* 165 */	ED_UNASSIGNED,		/* M-% */
-	/* 166 */	ED_UNASSIGNED,		/* M-& */
-	/* 167 */	ED_UNASSIGNED,		/* M-' */
-	/* 168 */	ED_UNASSIGNED,		/* M-( */
-	/* 169 */	ED_UNASSIGNED,		/* M-) */
-	/* 170 */	ED_UNASSIGNED,		/* M-* */
-	/* 171 */	ED_UNASSIGNED,		/* M-+ */
-	/* 172 */	ED_UNASSIGNED,		/* M-, */
-	/* 173 */	ED_UNASSIGNED,		/* M-- */
-	/* 174 */	ED_UNASSIGNED,		/* M-. */
-	/* 175 */	ED_UNASSIGNED,		/* M-/ */
-	/* 176 */	ED_UNASSIGNED,		/* M-0 */
-	/* 177 */	ED_UNASSIGNED,		/* M-1 */
-	/* 178 */	ED_UNASSIGNED,		/* M-2 */
-	/* 179 */	ED_UNASSIGNED,		/* M-3 */
-	/* 180 */	ED_UNASSIGNED,		/* M-4 */
-	/* 181 */	ED_UNASSIGNED,		/* M-5 */
-	/* 182 */	ED_UNASSIGNED,		/* M-6 */
-	/* 183 */	ED_UNASSIGNED,		/* M-7 */
-	/* 184 */	ED_UNASSIGNED,		/* M-8 */
-	/* 185 */	ED_UNASSIGNED,		/* M-9 */
-	/* 186 */	ED_UNASSIGNED,		/* M-: */
-	/* 187 */	ED_UNASSIGNED,		/* M-; */
-	/* 188 */	ED_UNASSIGNED,		/* M-< */
-	/* 189 */	ED_UNASSIGNED,		/* M-= */
-	/* 190 */	ED_UNASSIGNED,		/* M-> */
-	/* 191 */	ED_UNASSIGNED,		/* M-? */
-	/* 192 */	ED_UNASSIGNED,		/* M-@ */
-	/* 193 */	ED_UNASSIGNED,		/* M-A */
-	/* 194 */	ED_UNASSIGNED,		/* M-B */
-	/* 195 */	ED_UNASSIGNED,		/* M-C */
-	/* 196 */	ED_UNASSIGNED,		/* M-D */
-	/* 197 */	ED_UNASSIGNED,		/* M-E */
-	/* 198 */	ED_UNASSIGNED,		/* M-F */
-	/* 199 */	ED_UNASSIGNED,		/* M-G */
-	/* 200 */	ED_UNASSIGNED,		/* M-H */
-	/* 201 */	ED_UNASSIGNED,		/* M-I */
-	/* 202 */	ED_UNASSIGNED,		/* M-J */
-	/* 203 */	ED_UNASSIGNED,		/* M-K */
-	/* 204 */	ED_UNASSIGNED,		/* M-L */
-	/* 205 */	ED_UNASSIGNED,		/* M-M */
-	/* 206 */	ED_UNASSIGNED,		/* M-N */
-	/* 207 */	ED_UNASSIGNED,		/* M-O */
-	/* 208 */	ED_UNASSIGNED,		/* M-P */
-	/* 209 */	ED_UNASSIGNED,		/* M-Q */
-	/* 210 */	ED_UNASSIGNED,		/* M-R */
-	/* 211 */	ED_UNASSIGNED,		/* M-S */
-	/* 212 */	ED_UNASSIGNED,		/* M-T */
-	/* 213 */	ED_UNASSIGNED,		/* M-U */
-	/* 214 */	ED_UNASSIGNED,		/* M-V */
-	/* 215 */	ED_UNASSIGNED,		/* M-W */
-	/* 216 */	ED_UNASSIGNED,		/* M-X */
-	/* 217 */	ED_UNASSIGNED,		/* M-Y */
-	/* 218 */	ED_UNASSIGNED,		/* M-Z */
-	/* 219 */	ED_UNASSIGNED,		/* M-[ */
-	/* 220 */	ED_UNASSIGNED,		/* M-\ */
-	/* 221 */	ED_UNASSIGNED,		/* M-] */
-	/* 222 */	ED_UNASSIGNED,		/* M-^ */
-	/* 223 */	ED_UNASSIGNED,		/* M-_ */
-	/* 224 */	ED_UNASSIGNED,		/* M-` */
-	/* 225 */	ED_UNASSIGNED,		/* M-a */
-	/* 226 */	ED_UNASSIGNED,		/* M-b */
-	/* 227 */	ED_UNASSIGNED,		/* M-c */
-	/* 228 */	ED_UNASSIGNED,		/* M-d */
-	/* 229 */	ED_UNASSIGNED,		/* M-e */
-	/* 230 */	ED_UNASSIGNED,		/* M-f */
-	/* 231 */	ED_UNASSIGNED,		/* M-g */
-	/* 232 */	ED_UNASSIGNED,		/* M-h */
-	/* 233 */	ED_UNASSIGNED,		/* M-i */
-	/* 234 */	ED_UNASSIGNED,		/* M-j */
-	/* 235 */	ED_UNASSIGNED,		/* M-k */
-	/* 236 */	ED_UNASSIGNED,		/* M-l */
-	/* 237 */	ED_UNASSIGNED,		/* M-m */
-	/* 238 */	ED_UNASSIGNED,		/* M-n */
-	/* 239 */	ED_UNASSIGNED,		/* M-o */
-	/* 240 */	ED_UNASSIGNED,		/* M-p */
-	/* 241 */	ED_UNASSIGNED,		/* M-q */
-	/* 242 */	ED_UNASSIGNED,		/* M-r */
-	/* 243 */	ED_UNASSIGNED,		/* M-s */
-	/* 244 */	ED_UNASSIGNED,		/* M-t */
-	/* 245 */	ED_UNASSIGNED,		/* M-u */
-	/* 246 */	ED_UNASSIGNED,		/* M-v */
-	/* 247 */	ED_UNASSIGNED,		/* M-w */
-	/* 248 */	ED_UNASSIGNED,		/* M-x */
-	/* 249 */	ED_UNASSIGNED,		/* M-y */
-	/* 250 */	ED_UNASSIGNED,		/* M-z */
-	/* 251 */	ED_UNASSIGNED,		/* M-{ */
-	/* 252 */	ED_UNASSIGNED,		/* M-| */
-	/* 253 */	ED_UNASSIGNED,		/* M-} */
-	/* 254 */	ED_UNASSIGNED,		/* M-~ */
-	/* 255 */	ED_UNASSIGNED		/* M-^? */
+	/* 127 */	VI_DELETE_PREV_CHAR,	/* ^? */
+	/* 128 */	ED_INSERT,		/* M-^@ */
+	/* 129 */	ED_INSERT,		/* M-^A */
+	/* 130 */	ED_INSERT,		/* M-^B */
+	/* 131 */	ED_INSERT,		/* M-^C */
+	/* 132 */	ED_INSERT,		/* M-^D */
+	/* 133 */	ED_INSERT,		/* M-^E */
+	/* 134 */	ED_INSERT,		/* M-^F */
+	/* 135 */	ED_INSERT,		/* M-^G */
+	/* 136 */	ED_INSERT,		/* M-^H */
+	/* 137 */	ED_INSERT,		/* M-^I */
+	/* 138 */	ED_INSERT,		/* M-^J */
+	/* 139 */	ED_INSERT,		/* M-^K */
+	/* 140 */	ED_INSERT,		/* M-^L */
+	/* 141 */	ED_INSERT,		/* M-^M */
+	/* 142 */	ED_INSERT,		/* M-^N */
+	/* 143 */	ED_INSERT,		/* M-^O */
+	/* 144 */	ED_INSERT,		/* M-^P */
+	/* 145 */	ED_INSERT,		/* M-^Q */
+	/* 146 */	ED_INSERT,		/* M-^R */
+	/* 147 */	ED_INSERT,		/* M-^S */
+	/* 148 */	ED_INSERT,		/* M-^T */
+	/* 149 */	ED_INSERT,		/* M-^U */
+	/* 150 */	ED_INSERT,		/* M-^V */
+	/* 151 */	ED_INSERT,		/* M-^W */
+	/* 152 */	ED_INSERT,		/* M-^X */
+	/* 153 */	ED_INSERT,		/* M-^Y */
+	/* 154 */	ED_INSERT,		/* M-^Z */
+	/* 155 */	ED_INSERT,		/* M-^[ */
+	/* 156 */	ED_INSERT,		/* M-^\ */
+	/* 157 */	ED_INSERT,		/* M-^] */
+	/* 158 */	ED_INSERT,		/* M-^^ */
+	/* 159 */	ED_INSERT,		/* M-^_ */
+	/* 160 */	ED_INSERT,		/* M-SPACE */
+	/* 161 */	ED_INSERT,		/* M-! */
+	/* 162 */	ED_INSERT,		/* M-" */
+	/* 163 */	ED_INSERT,		/* M-# */
+	/* 164 */	ED_INSERT,		/* M-$ */
+	/* 165 */	ED_INSERT,		/* M-% */
+	/* 166 */	ED_INSERT,		/* M-& */
+	/* 167 */	ED_INSERT,		/* M-' */
+	/* 168 */	ED_INSERT,		/* M-( */
+	/* 169 */	ED_INSERT,		/* M-) */
+	/* 170 */	ED_INSERT,		/* M-* */
+	/* 171 */	ED_INSERT,		/* M-+ */
+	/* 172 */	ED_INSERT,		/* M-, */
+	/* 173 */	ED_INSERT,		/* M-- */
+	/* 174 */	ED_INSERT,		/* M-. */
+	/* 175 */	ED_INSERT,		/* M-/ */
+	/* 176 */	ED_INSERT,		/* M-0 */
+	/* 177 */	ED_INSERT,		/* M-1 */
+	/* 178 */	ED_INSERT,		/* M-2 */
+	/* 179 */	ED_INSERT,		/* M-3 */
+	/* 180 */	ED_INSERT,		/* M-4 */
+	/* 181 */	ED_INSERT,		/* M-5 */
+	/* 182 */	ED_INSERT,		/* M-6 */
+	/* 183 */	ED_INSERT,		/* M-7 */
+	/* 184 */	ED_INSERT,		/* M-8 */
+	/* 185 */	ED_INSERT,		/* M-9 */
+	/* 186 */	ED_INSERT,		/* M-: */
+	/* 187 */	ED_INSERT,		/* M-; */
+	/* 188 */	ED_INSERT,		/* M-< */
+	/* 189 */	ED_INSERT,		/* M-= */
+	/* 190 */	ED_INSERT,		/* M-> */
+	/* 191 */	ED_INSERT,		/* M-? */
+	/* 192 */	ED_INSERT,		/* M-@ */
+	/* 193 */	ED_INSERT,		/* M-A */
+	/* 194 */	ED_INSERT,		/* M-B */
+	/* 195 */	ED_INSERT,		/* M-C */
+	/* 196 */	ED_INSERT,		/* M-D */
+	/* 197 */	ED_INSERT,		/* M-E */
+	/* 198 */	ED_INSERT,		/* M-F */
+	/* 199 */	ED_INSERT,		/* M-G */
+	/* 200 */	ED_INSERT,		/* M-H */
+	/* 201 */	ED_INSERT,		/* M-I */
+	/* 202 */	ED_INSERT,		/* M-J */
+	/* 203 */	ED_INSERT,		/* M-K */
+	/* 204 */	ED_INSERT,		/* M-L */
+	/* 205 */	ED_INSERT,		/* M-M */
+	/* 206 */	ED_INSERT,		/* M-N */
+	/* 207 */	ED_INSERT,		/* M-O */
+	/* 208 */	ED_INSERT,		/* M-P */
+	/* 209 */	ED_INSERT,		/* M-Q */
+	/* 210 */	ED_INSERT,		/* M-R */
+	/* 211 */	ED_INSERT,		/* M-S */
+	/* 212 */	ED_INSERT,		/* M-T */
+	/* 213 */	ED_INSERT,		/* M-U */
+	/* 214 */	ED_INSERT,		/* M-V */
+	/* 215 */	ED_INSERT,		/* M-W */
+	/* 216 */	ED_INSERT,		/* M-X */
+	/* 217 */	ED_INSERT,		/* M-Y */
+	/* 218 */	ED_INSERT,		/* M-Z */
+	/* 219 */	ED_INSERT,		/* M-[ */
+	/* 220 */	ED_INSERT,		/* M-\ */
+	/* 221 */	ED_INSERT,		/* M-] */
+	/* 222 */	ED_INSERT,		/* M-^ */
+	/* 223 */	ED_INSERT,		/* M-_ */
+	/* 224 */	ED_INSERT,		/* M-` */
+	/* 225 */	ED_INSERT,		/* M-a */
+	/* 226 */	ED_INSERT,		/* M-b */
+	/* 227 */	ED_INSERT,		/* M-c */
+	/* 228 */	ED_INSERT,		/* M-d */
+	/* 229 */	ED_INSERT,		/* M-e */
+	/* 230 */	ED_INSERT,		/* M-f */
+	/* 231 */	ED_INSERT,		/* M-g */
+	/* 232 */	ED_INSERT,		/* M-h */
+	/* 233 */	ED_INSERT,		/* M-i */
+	/* 234 */	ED_INSERT,		/* M-j */
+	/* 235 */	ED_INSERT,		/* M-k */
+	/* 236 */	ED_INSERT,		/* M-l */
+	/* 237 */	ED_INSERT,		/* M-m */
+	/* 238 */	ED_INSERT,		/* M-n */
+	/* 239 */	ED_INSERT,		/* M-o */
+	/* 240 */	ED_INSERT,		/* M-p */
+	/* 241 */	ED_INSERT,		/* M-q */
+	/* 242 */	ED_INSERT,		/* M-r */
+	/* 243 */	ED_INSERT,		/* M-s */
+	/* 244 */	ED_INSERT,		/* M-t */
+	/* 245 */	ED_INSERT,		/* M-u */
+	/* 246 */	ED_INSERT,		/* M-v */
+	/* 247 */	ED_INSERT,		/* M-w */
+	/* 248 */	ED_INSERT,		/* M-x */
+	/* 249 */	ED_INSERT,		/* M-y */
+	/* 250 */	ED_INSERT,		/* M-z */
+	/* 251 */	ED_INSERT,		/* M-{ */
+	/* 252 */	ED_INSERT,		/* M-| */
+	/* 253 */	ED_INSERT,		/* M-} */
+	/* 254 */	ED_INSERT,		/* M-~ */
+	/* 255 */	ED_INSERT		/* M-^? */
 };
 
 private const el_action_t el_map_vi_command[] = {
@@ -637,7 +633,7 @@ private const el_action_t el_map_vi_command[] = {
 	/*   5 */	ED_MOVE_TO_END,		/* ^E */
 	/*   6 */	ED_UNASSIGNED,		/* ^F */
 	/*   7 */	ED_UNASSIGNED,		/* ^G */
-	/*   8 */	ED_PREV_CHAR,		/* ^H */
+	/*   8 */	ED_DELETE_PREV_CHAR,	/* ^H */
 	/*   9 */	ED_UNASSIGNED,		/* ^I */
 	/*  10 */	ED_NEWLINE,		/* ^J */
 	/*  11 */	ED_KILL_LINE,		/* ^K */
@@ -664,9 +660,9 @@ private const el_action_t el_map_vi_command[] = {
 	/*  32 */	ED_NEXT_CHAR,		/* SPACE */
 	/*  33 */	ED_UNASSIGNED,		/* ! */
 	/*  34 */	ED_UNASSIGNED,		/* " */
-	/*  35 */	ED_UNASSIGNED,		/* # */
+	/*  35 */	VI_COMMENT_OUT,		/* # */
 	/*  36 */	ED_MOVE_TO_END,		/* $ */
-	/*  37 */	ED_UNASSIGNED,		/* % */
+	/*  37 */	VI_MATCH,		/* % */
 	/*  38 */	ED_UNASSIGNED,		/* & */
 	/*  39 */	ED_UNASSIGNED,		/* ' */
 	/*  40 */	ED_UNASSIGNED,		/* ( */
@@ -675,7 +671,7 @@ private const el_action_t el_map_vi_command[] = {
 	/*  43 */	ED_NEXT_HISTORY,	/* + */
 	/*  44 */	VI_REPEAT_PREV_CHAR,	/* , */
 	/*  45 */	ED_PREV_HISTORY,	/* - */
-	/*  46 */	ED_UNASSIGNED,		/* . */
+	/*  46 */	VI_REDO,		/* . */
 	/*  47 */	VI_SEARCH_PREV,		/* / */
 	/*  48 */	VI_ZERO,		/* 0 */
 	/*  49 */	ED_ARGUMENT_DIGIT,	/* 1 */
@@ -693,14 +689,14 @@ private const el_action_t el_map_vi_command[] = {
 	/*  61 */	ED_UNASSIGNED,		/* = */
 	/*  62 */	ED_UNASSIGNED,		/* > */
 	/*  63 */	VI_SEARCH_NEXT,		/* ? */
-	/*  64 */	ED_UNASSIGNED,		/* @ */
+	/*  64 */	VI_ALIAS,		/* @ */
 	/*  65 */	VI_ADD_AT_EOL,		/* A */
-	/*  66 */	VI_PREV_SPACE_WORD,	/* B */
+	/*  66 */	VI_PREV_BIG_WORD,	/* B */
 	/*  67 */	VI_CHANGE_TO_EOL,	/* C */
 	/*  68 */	ED_KILL_LINE,		/* D */
-	/*  69 */	VI_TO_END_WORD,		/* E */
+	/*  69 */	VI_END_BIG_WORD,	/* E */
 	/*  70 */	VI_PREV_CHAR,		/* F */
-	/*  71 */	ED_UNASSIGNED,		/* G */
+	/*  71 */	VI_TO_HISTORY_LINE,	/* G */
 	/*  72 */	ED_UNASSIGNED,		/* H */
 	/*  73 */	VI_INSERT_AT_BOL,	/* I */
 	/*  74 */	ED_SEARCH_NEXT_HISTORY,	/* J */
@@ -716,15 +712,15 @@ private const el_action_t el_map_vi_command[] = {
 	/*  84 */	VI_TO_PREV_CHAR,	/* T */
 	/*  85 */	VI_UNDO_LINE,		/* U */
 	/*  86 */	ED_UNASSIGNED,		/* V */
-	/*  87 */	VI_NEXT_SPACE_WORD,	/* W */
+	/*  87 */	VI_NEXT_BIG_WORD,	/* W */
 	/*  88 */	ED_DELETE_PREV_CHAR,	/* X */
-	/*  89 */	ED_UNASSIGNED,		/* Y */
+	/*  89 */	VI_YANK_END,		/* Y */
 	/*  90 */	ED_UNASSIGNED,		/* Z */
 	/*  91 */	ED_SEQUENCE_LEAD_IN,	/* [ */
 	/*  92 */	ED_UNASSIGNED,		/* \ */
 	/*  93 */	ED_UNASSIGNED,		/* ] */
 	/*  94 */	ED_MOVE_TO_BEG,		/* ^ */
-	/*  95 */	ED_UNASSIGNED,		/* _ */
+	/*  95 */	VI_HISTORY_WORD,	/* _ */
 	/*  96 */	ED_UNASSIGNED,		/* ` */
 	/*  97 */	VI_ADD,			/* a */
 	/*  98 */	VI_PREV_WORD,		/* b */
@@ -747,13 +743,13 @@ private const el_action_t el_map_vi_command[] = {
 	/* 115 */	VI_SUBSTITUTE_CHAR,	/* s */
 	/* 116 */	VI_TO_NEXT_CHAR,	/* t */
 	/* 117 */	VI_UNDO,		/* u */
-	/* 118 */	ED_UNASSIGNED,		/* v */
+	/* 118 */	VI_HISTEDIT,		/* v */
 	/* 119 */	VI_NEXT_WORD,		/* w */
 	/* 120 */	ED_DELETE_NEXT_CHAR,	/* x */
-	/* 121 */	ED_UNASSIGNED,		/* y */
+	/* 121 */	VI_YANK,		/* y */
 	/* 122 */	ED_UNASSIGNED,		/* z */
 	/* 123 */	ED_UNASSIGNED,		/* { */
-	/* 124 */	ED_UNASSIGNED,		/* | */
+	/* 124 */	VI_TO_COLUMN,		/* | */
 	/* 125 */	ED_UNASSIGNED,		/* } */
 	/* 126 */	VI_CHANGE_CASE,		/* ~ */
 	/* 127 */	ED_DELETE_PREV_CHAR,	/* ^? */
@@ -1124,7 +1120,7 @@ map_get_editor(EditLine *el, const char **editor)
  *	Print the function description for 1 key
  */
 private void
-map_print_key(EditLine *el, el_action_t *map, char *in)
+map_print_key(EditLine *el, el_action_t *map, const char *in)
 {
 	char outbuf[EL_BUFSIZ];
 	el_bindings_t *bp;
@@ -1237,14 +1233,14 @@ map_print_all_keys(EditLine *el)
  *	Add/remove/change bindings
  */
 protected int
-map_bind(EditLine *el, int argc, char **argv)
+map_bind(EditLine *el, int argc, const char **argv)
 {
 	el_action_t *map;
 	int ntype, rem;
-	char *p;
+	const char *p;
 	char inbuf[EL_BUFSIZ];
 	char outbuf[EL_BUFSIZ];
-	char *in = NULL;
+	const char *in = NULL;
 	char *out = NULL;
 	el_bindings_t *bp;
 	int cmd;
diff --git a/lib/libedit/map.h b/lib/libedit/map.h
index 5ca7f52b29af..a76d8727b92a 100644
--- a/lib/libedit/map.h
+++ b/lib/libedit/map.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)map.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: map.h,v 1.5 2000/09/04 22:06:31 lukem Exp $
+ *	$NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $
  * $FreeBSD$
  */
 
@@ -67,7 +63,7 @@ typedef struct el_map_t {
 #define	MAP_EMACS	0
 #define	MAP_VI		1
 
-protected int	map_bind(EditLine *, int, char **);
+protected int	map_bind(EditLine *, int, const char **);
 protected int	map_init(EditLine *);
 protected void	map_end(EditLine *);
 protected void	map_init_vi(EditLine *);
diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c
index f83dc94c6e38..0ffe51d8ec45 100644
--- a/lib/libedit/parse.c
+++ b/lib/libedit/parse.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: parse.c,v 1.13 2000/09/04 22:06:31 lukem Exp $
+ *	$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -57,17 +53,16 @@ __FBSDID("$FreeBSD$");
  */
 #include "sys.h"
 #include "el.h"
-#include "tokenizer.h"
 #include <stdlib.h>
 
 private const struct {
-	char *name;
-	int (*func)(EditLine *, int, char **);
+	const char *name;
+	int (*func)(EditLine *, int, const char **);
 } cmds[] = {
 	{ "bind",	map_bind	},
 	{ "echotc",	term_echotc	},
 	{ "edit",	el_editmode	},
-	{ "history",	hist_list	},
+	{ "history",	hist_command	},
 	{ "telltc",	term_telltc	},
 	{ "settc",	term_settc	},
 	{ "setty",	tty_stty	},
@@ -81,12 +76,12 @@ private const struct {
 protected int
 parse_line(EditLine *el, const char *line)
 {
-	char **argv;
+	const char **argv;
 	int argc;
 	Tokenizer *tok;
 
 	tok = tok_init(NULL);
-	tok_line(tok, line, &argc, &argv);
+	tok_str(tok, line, &argc, &argv);
 	argc = el_parse(el, argc, argv);
 	tok_end(tok);
 	return (argc);
@@ -97,9 +92,9 @@ parse_line(EditLine *el, const char *line)
  *	Command dispatcher
  */
 public int
-el_parse(EditLine *el, int argc, char *argv[])
+el_parse(EditLine *el, int argc, const char *argv[])
 {
-	char *ptr;
+	const char *ptr;
 	int i;
 
 	if (argc < 1)
@@ -139,7 +134,7 @@ el_parse(EditLine *el, int argc, char *argv[])
  *	the appropriate character or -1 if the escape is not valid
  */
 protected int
-parse__escape(const char **const ptr)
+parse__escape(const char **ptr)
 {
 	const char *p;
 	int c;
@@ -204,7 +199,7 @@ parse__escape(const char **const ptr)
 			c = *p;
 			break;
 		}
-	} else if (*p == '^' && isascii(p[1]) && (p[1] == '?' || isalpha(p[1])))  {
+	} else if (*p == '^') {
 		p++;
 		c = (*p == '?') ? '\177' : (*p & 0237);
 	} else
@@ -212,6 +207,7 @@ parse__escape(const char **const ptr)
 	*ptr = ++p;
 	return ((unsigned char)c);
 }
+
 /* parse__string():
  *	Parse the escapes from in and put the raw string out
  */
@@ -234,6 +230,14 @@ parse__string(char *out, const char *in)
 			*out++ = n;
 			break;
 
+		case 'M':
+			if (in[1] == '-' && in[2] != '\0') {
+				*out++ = '\033';
+				in += 2;
+				break;
+			}
+			/*FALLTHROUGH*/
+
 		default:
 			*out++ = *in++;
 			break;
diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h
index 356750d7ad60..cca4abf1999c 100644
--- a/lib/libedit/parse.h
+++ b/lib/libedit/parse.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)parse.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: parse.h,v 1.3 1999/07/02 15:21:26 simonb Exp $
+ *	$NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $
  * $FreeBSD$
  */
 
@@ -45,7 +41,7 @@
 #define	_h_el_parse
 
 protected int	 parse_line(EditLine *, const char *);
-protected int	 parse__escape(const char ** const);
+protected int	 parse__escape(const char **);
 protected char	*parse__string(char *, const char *);
 protected int	 parse_cmd(EditLine *, const char *);
 
diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c
index 10ba70b2baca..3d72da73e947 100644
--- a/lib/libedit/prompt.c
+++ b/lib/libedit/prompt.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: prompt.c,v 1.7 2000/09/04 22:06:31 lukem Exp $
+ *	$NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -57,7 +53,7 @@ private char	*prompt_default_r(EditLine *);
  */
 private char *
 /*ARGSUSED*/
-prompt_default(EditLine *el)
+prompt_default(EditLine *el __unused)
 {
 	static char a[3] = {'?', ' ', '\0'};
 
@@ -70,7 +66,7 @@ prompt_default(EditLine *el)
  */
 private char *
 /*ARGSUSED*/
-prompt_default_r(EditLine *el)
+prompt_default_r(EditLine *el __unused)
 {
 	static char a[1] = {'\0'};
 
@@ -125,7 +121,7 @@ prompt_init(EditLine *el)
  */
 protected void
 /*ARGSUSED*/
-prompt_end(EditLine *el)
+prompt_end(EditLine *el __unused)
 {
 }
 
diff --git a/lib/libedit/prompt.h b/lib/libedit/prompt.h
index 509c9207cf29..6523add855cd 100644
--- a/lib/libedit/prompt.h
+++ b/lib/libedit/prompt.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)prompt.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: prompt.h,v 1.4 1999/11/12 01:05:07 lukem Exp $
+ *	$NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $
  * $FreeBSD$
  */
 
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
index 6b9d71688aa7..4d0b39460cfe 100644
--- a/lib/libedit/read.c
+++ b/lib/libedit/read.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: read.c,v 1.18 2000/11/11 22:18:58 christos Exp $
+ *	$NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -57,8 +53,48 @@ __FBSDID("$FreeBSD$");
 
 private int	read__fixio(int, int);
 private int	read_preread(EditLine *);
-private int	read_getcmd(EditLine *, el_action_t *, char *);
 private int	read_char(EditLine *, char *);
+private int	read_getcmd(EditLine *, el_action_t *, char *);
+
+/* read_init():
+ *	Initialize the read stuff
+ */
+protected int
+read_init(EditLine *el)
+{
+	/* builtin read_char */
+	el->el_read.read_char = read_char;
+	return 0;
+}
+
+
+/* el_read_setfn():
+ *	Set the read char function to the one provided.
+ *	If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
+ */
+protected int
+el_read_setfn(EditLine *el, el_rfunc_t rc)
+{
+	el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
+	return 0;
+}
+
+
+/* el_read_getfn():
+ *	return the current read char function, or EL_BUILTIN_GETCFN
+ *	if it is the default one
+ */
+protected el_rfunc_t
+el_read_getfn(EditLine *el)
+{
+       return (el->el_read.read_char == read_char) ?
+	    EL_BUILTIN_GETCFN : el->el_read.read_char;
+}
+
+
+#ifndef MIN
+#define MIN(A,B) ((A) < (B) ? (A) : (B))
+#endif
 
 #ifdef DEBUG_EDIT
 private void
@@ -84,7 +120,7 @@ read_debug(EditLine *el)
  */
 /* ARGSUSED */
 private int
-read__fixio(int fd, int e)
+read__fixio(int fd __unused, int e)
 {
 
 	switch (e) {
@@ -149,10 +185,6 @@ read_preread(EditLine *el)
 {
 	int chrs = 0;
 
-	if (el->el_chared.c_macro.nline) {
-		el_free((ptr_t) el->el_chared.c_macro.nline);
-		el->el_chared.c_macro.nline = NULL;
-	}
 	if (el->el_tty.t_mode == ED_IO)
 		return (0);
 
@@ -165,8 +197,7 @@ read_preread(EditLine *el)
 		    (size_t) MIN(chrs, EL_BUFSIZ - 1));
 		if (chrs > 0) {
 			buf[chrs] = '\0';
-			el->el_chared.c_macro.nline = strdup(buf);
-			el_push(el, el->el_chared.c_macro.nline);
+			el_push(el, buf);
 		}
 	}
 #endif /* FIONREAD */
@@ -179,18 +210,18 @@ read_preread(EditLine *el)
  *	Push a macro
  */
 public void
-el_push(EditLine *el, const char *str)
+el_push(EditLine *el, char *str)
 {
 	c_macro_t *ma = &el->el_chared.c_macro;
 
 	if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
 		ma->level++;
-		/* LINTED const cast */
-		ma->macro[ma->level] = (char *) str;
-	} else {
-		term_beep(el);
-		term__flush();
+		if ((ma->macro[ma->level] = el_strdup(str)) != NULL)
+			return;
+		ma->level--;
 	}
+	term_beep(el);
+	term__flush();
 }
 
 
@@ -200,10 +231,10 @@ el_push(EditLine *el, const char *str)
 private int
 read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
 {
-	el_action_t cmd = ED_UNASSIGNED;
+	el_action_t cmd;
 	int num;
 
-	while (cmd == ED_UNASSIGNED || cmd == ED_SEQUENCE_LEAD_IN) {
+	do {
 		if ((num = el_getc(el, ch)) != 1)	/* if EOF or error */
 			return (num);
 
@@ -242,7 +273,7 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
 		}
 		if (el->el_map.alt == NULL)
 			el->el_map.current = el->el_map.key;
-	}
+	} while (cmd == ED_SEQUENCE_LEAD_IN);
 	*cmdnum = cmd;
 	return (OKCMD);
 }
@@ -287,14 +318,16 @@ el_getc(EditLine *el, char *cp)
 		if (ma->level < 0)
 			break;
 
-		if (*ma->macro[ma->level] == 0) {
-			ma->level--;
+		if (ma->macro[ma->level][ma->offset] == '\0') {
+			el_free(ma->macro[ma->level--]);
+			ma->offset = 0;
 			continue;
 		}
-		*cp = *ma->macro[ma->level]++ & 0377;
-		if (*ma->macro[ma->level] == 0) {	/* Needed for QuoteMode
-							 * On */
-			ma->level--;
+		*cp = ma->macro[ma->level][ma->offset++] & 0377;
+		if (ma->macro[ma->level][ma->offset] == '\0') {
+			/* Needed for QuoteMode On */
+			el_free(ma->macro[ma->level--]);
+			ma->offset = 0;
 		}
 		return (1);
 	}
@@ -308,13 +341,42 @@ el_getc(EditLine *el, char *cp)
 #ifdef DEBUG_READ
 	(void) fprintf(el->el_errfile, "Reading a character\n");
 #endif /* DEBUG_READ */
-	num_read = read_char(el, cp);
+	num_read = (*el->el_read.read_char)(el, cp);
 #ifdef DEBUG_READ
 	(void) fprintf(el->el_errfile, "Got it %c\n", *cp);
 #endif /* DEBUG_READ */
 	return (num_read);
 }
 
+protected void
+read_prepare(EditLine *el)
+{
+	if (el->el_flags & HANDLE_SIGNALS)
+		sig_set(el);
+	if (el->el_flags & NO_TTY)
+		return;
+	if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
+		tty_rawmode(el);
+
+	/* This is relatively cheap, and things go terribly wrong if
+	   we have the wrong size. */
+	el_resize(el);
+	re_clear_display(el);	/* reset the display stuff */
+	ch_reset(el, 0);
+	re_refresh(el);		/* print the prompt */
+
+	if (el->el_flags & UNBUFFERED)
+		term__flush();
+}
+
+protected void
+read_finish(EditLine *el)
+{
+	if ((el->el_flags & UNBUFFERED) == 0)
+		(void) tty_cookedmode(el);
+	if (el->el_flags & HANDLE_SIGNALS)
+		sig_clr(el);
+}
 
 public const char *
 el_gets(EditLine *el, int *nread)
@@ -323,18 +385,16 @@ el_gets(EditLine *el, int *nread)
 	el_action_t cmdnum = 0;
 	int num;		/* how many chars we have read at NL */
 	char ch;
+	int crlf = 0;
 #ifdef FIONREAD
 	c_macro_t *ma = &el->el_chared.c_macro;
 #endif /* FIONREAD */
 
-	if (el->el_flags & HANDLE_SIGNALS)
-		sig_set(el);
-
 	if (el->el_flags & NO_TTY) {
 		char *cp = el->el_line.buffer;
 		size_t idx;
 
-		while (read_char(el, cp) == 1) {
+		while ((*el->el_read.read_char)(el, cp) == 1) {
 			/* make sure there is space for next character */
 			if (cp + 1 >= el->el_line.limit) {
 				idx = (cp - el->el_line.buffer);
@@ -343,6 +403,8 @@ el_gets(EditLine *el, int *nread)
 				cp = &el->el_line.buffer[idx];
 			}
 			cp++;
+			if (el->el_flags & UNBUFFERED)
+				break;
 			if (cp[-1] == '\r' || cp[-1] == '\n')
 				break;
 		}
@@ -353,8 +415,7 @@ el_gets(EditLine *el, int *nread)
 			*nread = el->el_line.cursor - el->el_line.buffer;
 		return (el->el_line.buffer);
 	}
-	re_clear_display(el);	/* reset the display stuff */
-	ch_reset(el);
+
 
 #ifdef FIONREAD
 	if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
@@ -371,15 +432,20 @@ el_gets(EditLine *el, int *nread)
 	}
 #endif /* FIONREAD */
 
-	re_refresh(el);		/* print the prompt */
+	if ((el->el_flags & UNBUFFERED) == 0)
+		read_prepare(el);
 
 	if (el->el_flags & EDIT_DISABLED) {
-		char *cp = el->el_line.buffer;
+		char *cp;
 		size_t idx;
+		if ((el->el_flags & UNBUFFERED) == 0)
+			cp = el->el_line.buffer;
+		else
+			cp = el->el_line.lastchar;
 
 		term__flush();
 
-		while (read_char(el, cp) == 1) {
+		while ((*el->el_read.read_char)(el, cp) == 1) {
 			/* make sure there is space next character */
 			if (cp + 1 >= el->el_line.limit) {
 				idx = (cp - el->el_line.buffer);
@@ -387,8 +453,13 @@ el_gets(EditLine *el, int *nread)
 					break;
 				cp = &el->el_line.buffer[idx];
 			}
+			if (*cp == 4)	/* ought to be stty eof */
+				break;
 			cp++;
-			if (cp[-1] == '\r' || cp[-1] == '\n')
+			crlf = cp[-1] == '\r' || cp[-1] == '\n';
+			if (el->el_flags & UNBUFFERED)
+				break;
+			if (crlf)
 				break;
 		}
 
@@ -398,6 +469,7 @@ el_gets(EditLine *el, int *nread)
 			*nread = el->el_line.cursor - el->el_line.buffer;
 		return (el->el_line.buffer);
 	}
+
 	for (num = OKCMD; num == OKCMD;) {	/* while still editing this
 						 * line */
 #ifdef DEBUG_EDIT
@@ -411,7 +483,7 @@ el_gets(EditLine *el, int *nread)
 #endif /* DEBUG_READ */
 			break;
 		}
-		if ((int) cmdnum >= el->el_map.nfunc) {	/* BUG CHECK command */
+		if ((unsigned int)cmdnum >= el->el_map.nfunc) {	/* BUG CHECK command */
 #ifdef DEBUG_EDIT
 			(void) fprintf(el->el_errfile,
 			    "ERROR: illegal command from key 0%o\r\n", ch);
@@ -433,7 +505,24 @@ el_gets(EditLine *el, int *nread)
 				    "Error command = %d\n", cmdnum);
 		}
 #endif /* DEBUG_READ */
+		/* vi redo needs these way down the levels... */
+		el->el_state.thiscmd = cmdnum;
+		el->el_state.thisch = ch;
+		if (el->el_map.type == MAP_VI &&
+		    el->el_map.current == el->el_map.key &&
+		    el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
+			if (cmdnum == VI_DELETE_PREV_CHAR &&
+			    el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
+			    && isprint((unsigned char)el->el_chared.c_redo.pos[-1]))
+				el->el_chared.c_redo.pos--;
+			else
+				*el->el_chared.c_redo.pos++ = ch;
+		}
 		retval = (*el->el_map.func[cmdnum]) (el, ch);
+#ifdef DEBUG_READ
+		(void) fprintf(el->el_errfile,
+			"Returned state %d\n", retval );
+#endif /* DEBUG_READ */
 
 		/* save the last command here */
 		el->el_state.lastcmd = cmdnum;
@@ -441,8 +530,6 @@ el_gets(EditLine *el, int *nread)
 		/* use any return value */
 		switch (retval) {
 		case CC_CURSOR:
-			el->el_state.argument = 1;
-			el->el_state.doingarg = 0;
 			re_refresh_cursor(el);
 			break;
 
@@ -452,29 +539,29 @@ el_gets(EditLine *el, int *nread)
 			/* FALLTHROUGH */
 
 		case CC_REFRESH:
-			el->el_state.argument = 1;
-			el->el_state.doingarg = 0;
 			re_refresh(el);
 			break;
 
 		case CC_REFRESH_BEEP:
-			el->el_state.argument = 1;
-			el->el_state.doingarg = 0;
 			re_refresh(el);
 			term_beep(el);
 			break;
 
 		case CC_NORM:	/* normal char */
-			el->el_state.argument = 1;
-			el->el_state.doingarg = 0;
 			break;
 
 		case CC_ARGHACK:	/* Suggested by Rich Salz */
 			/* <rsalz@pineapple.bbn.com> */
-			break;	/* keep going... */
+			continue;	/* keep going... */
 
 		case CC_EOF:	/* end of file typed */
-			num = 0;
+			if ((el->el_flags & UNBUFFERED) == 0)
+				num = 0;
+			else if (num == -1) {
+				*el->el_line.lastchar++ = CONTROL('d');
+				el->el_line.cursor = el->el_line.lastchar;
+				num = 1;
+			}
 			break;
 
 		case CC_NEWLINE:	/* normal end of line */
@@ -488,10 +575,8 @@ el_gets(EditLine *el, int *nread)
 #endif /* DEBUG_READ */
 			/* put (real) cursor in a known place */
 			re_clear_display(el);	/* reset the display stuff */
-			ch_reset(el);	/* reset the input pointers */
+			ch_reset(el, 1);	/* reset the input pointers */
 			re_refresh(el);	/* print the prompt again */
-			el->el_state.argument = 1;
-			el->el_state.doingarg = 0;
 			break;
 
 		case CC_ERROR:
@@ -500,20 +585,26 @@ el_gets(EditLine *el, int *nread)
 			(void) fprintf(el->el_errfile,
 			    "*** editor ERROR ***\r\n\n");
 #endif /* DEBUG_READ */
-			el->el_state.argument = 1;
-			el->el_state.doingarg = 0;
 			term_beep(el);
 			term__flush();
 			break;
 		}
+		el->el_state.argument = 1;
+		el->el_state.doingarg = 0;
+		el->el_chared.c_vcmd.action = NOP;
+		if (el->el_flags & UNBUFFERED)
+			break;
 	}
 
 	term__flush();		/* flush any buffered output */
-				/* make sure the tty is set up correctly */
-	(void) tty_cookedmode(el);
-	if (el->el_flags & HANDLE_SIGNALS)
-		sig_clr(el);
-	if (nread)
-		*nread = num;
+	/* make sure the tty is set up correctly */
+	if ((el->el_flags & UNBUFFERED) == 0) {
+		read_finish(el);
+		if (nread)
+			*nread = num;
+	} else {
+		if (nread)
+			*nread = el->el_line.lastchar - el->el_line.buffer;
+	}
 	return (num ? el->el_line.buffer : NULL);
 }
diff --git a/lib/libedit/read.h b/lib/libedit/read.h
new file mode 100644
index 000000000000..e4a87991f7d9
--- /dev/null
+++ b/lib/libedit/read.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Anthony Mallet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	$NetBSD: read.h,v 1.4 2004/02/27 14:52:18 christos Exp $
+ * $FreeBSD$
+ */
+
+/*
+ * el.read.h: Character reading functions
+ */
+#ifndef	_h_el_read
+#define	_h_el_read
+
+typedef int (*el_rfunc_t)(EditLine *, char *);
+
+typedef struct el_read_t {
+	el_rfunc_t	read_char;	/* Function to read a character */
+} el_read_t;
+ 
+protected int		read_init(EditLine *);
+protected void		read_prepare(EditLine *);
+protected void		read_finish(EditLine *);
+protected int		el_read_setfn(EditLine *, el_rfunc_t);
+protected el_rfunc_t	el_read_getfn(EditLine *);
+
+#endif /* _h_el_read */
diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c
index 08f1336e203a..72556545507e 100644
--- a/lib/libedit/refresh.c
+++ b/lib/libedit/refresh.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: refresh.c,v 1.16 2001/01/10 07:45:42 jdolecek Exp $
+ *	$NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -47,6 +43,7 @@ __FBSDID("$FreeBSD$");
  */
 #include "sys.h"
 #include <stdio.h>
+#include <ctype.h>
 #include <unistd.h>
 #include <string.h>
 
@@ -58,24 +55,24 @@ private void	re_insert (EditLine *, char *, int, int, char *, int);
 private void	re_delete(EditLine *, char *, int, int, int);
 private void	re_fastputc(EditLine *, int);
 private void	re__strncopy(char *, char *, size_t);
-private void	re__copy_and_pad(char *, char *, size_t);
+private void	re__copy_and_pad(char *, const char *, size_t);
 
 #ifdef DEBUG_REFRESH
-private void	re_printstr(EditLine *, char *, char *, char *);
+private void	re_printstr(EditLine *, const char *, char *, char *);
 #define	__F el->el_errfile
 #define	ELRE_ASSERT(a, b, c)	do 				\
-				    if (a) {			\
+				    if (/*CONSTCOND*/ a) {	\
 					(void) fprintf b;	\
 					c;			\
 				    }				\
-				while (0)
+				while (/*CONSTCOND*/0)
 #define	ELRE_DEBUG(a, b)	ELRE_ASSERT(a,b,;)
 
 /* re_printstr():
  *	Print a string on the debugging pty
  */
 private void
-re_printstr(EditLine *el, char *str, char *f, char *t)
+re_printstr(EditLine *el, const char *str, char *f, char *t)
 {
 
 	ELRE_DEBUG(1, (__F, "%s:\"", str));
@@ -96,8 +93,6 @@ private void
 re_addc(EditLine *el, int c)
 {
 
-	c = (unsigned char)c;
-
 	if (isprint(c)) {
 		re_putc(el, c, 1);
 		return;
@@ -208,6 +203,14 @@ re_refresh(EditLine *el)
 	el->el_refresh.r_cursor.h = 0;
 	el->el_refresh.r_cursor.v = 0;
 
+	if (el->el_line.cursor >= el->el_line.lastchar) {
+		if (el->el_map.current == el->el_map.alt
+		    && el->el_line.lastchar != el->el_line.buffer)
+			el->el_line.cursor = el->el_line.lastchar - 1;
+		else
+			el->el_line.cursor = el->el_line.lastchar;
+	}
+
 	cur.h = -1;		/* set flag in case I'm not set */
 	cur.v = 0;
 
@@ -317,7 +320,6 @@ re_goto_bottom(EditLine *el)
 {
 
 	term_move_to_line(el, el->el_refresh.r_oldcv);
-	term__putc('\r');
 	term__putc('\n');
 	re_clear_display(el);
 	term__flush();
@@ -330,7 +332,8 @@ re_goto_bottom(EditLine *el)
  */
 private void
 /*ARGSUSED*/
-re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num)
+re_insert(EditLine *el __unused,
+    char *d, int dat, int dlen, char *s, int num)
 {
 	char *a, *b;
 
@@ -373,7 +376,8 @@ re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num)
  */
 private void
 /*ARGSUSED*/
-re_delete(EditLine *el, char *d, int dat, int dlen, int num)
+re_delete(EditLine *el __unused,
+    char *d, int dat, int dlen, int num)
 {
 	char *a, *b;
 
@@ -906,9 +910,9 @@ re_update_line(EditLine *el, char *old, char *new, int i)
  *	Copy string and pad with spaces
  */
 private void
-re__copy_and_pad(char *dst, char *src, size_t width)
+re__copy_and_pad(char *dst, const char *src, size_t width)
 {
-	int i;
+	size_t i;
 
 	for (i = 0; i < width; i++) {
 		if (*src == '\0')
@@ -932,6 +936,14 @@ re_refresh_cursor(EditLine *el)
 	char *cp, c;
 	int h, v, th;
 
+	if (el->el_line.cursor >= el->el_line.lastchar) {
+		if (el->el_map.current == el->el_map.alt
+		    && el->el_line.lastchar != el->el_line.buffer)
+			el->el_line.cursor = el->el_line.lastchar - 1;
+		else
+			el->el_line.cursor = el->el_line.lastchar;
+	}
+
 	/* first we must find where the cursor is... */
 	h = el->el_prompt.p_pos.h;
 	v = el->el_prompt.p_pos.v;
@@ -939,7 +951,7 @@ re_refresh_cursor(EditLine *el)
 
 	/* do input buffer to el->el_line.cursor */
 	for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
-		c = (unsigned char)*cp;
+		c = *cp;
 		h++;		/* all chars at least this long */
 
 		if (c == '\n') {/* handle newline in data part too */
@@ -1054,8 +1066,8 @@ re_fastaddc(EditLine *el)
 		re_fastputc(el, c);
 	} else {
 		re_fastputc(el, '\\');
-		re_fastputc(el, (int) ((((unsigned int) c >> 6) & 7) + '0'));
-		re_fastputc(el, (int) ((((unsigned int) c >> 3) & 7) + '0'));
+		re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0'));
+		re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0'));
 		re_fastputc(el, (c & 7) + '0');
 	}
 	term__flush();
diff --git a/lib/libedit/refresh.h b/lib/libedit/refresh.h
index 516f3ad2825c..e44ef9c5f274 100644
--- a/lib/libedit/refresh.h
+++ b/lib/libedit/refresh.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)refresh.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: refresh.h,v 1.3 2000/09/04 22:06:32 lukem Exp $
+ *	$NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $
  * $FreeBSD$
  */
 
diff --git a/lib/libedit/search.c b/lib/libedit/search.c
index 96a0206bd285..991bad246141 100644
--- a/lib/libedit/search.c
+++ b/lib/libedit/search.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: search.c,v 1.10 2001/01/04 15:56:32 christos Exp $
+ *	$NetBSD: search.c,v 1.20 2004/11/04 01:16:03 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -74,7 +70,8 @@ search_init(EditLine *el)
 	el->el_search.patlen = 0;
 	el->el_search.patdir = -1;
 	el->el_search.chacha = '\0';
-	el->el_search.chadir = -1;
+	el->el_search.chadir = CHAR_FWD;
+	el->el_search.chatflg = 0;
 	return (0);
 }
 
@@ -223,8 +220,11 @@ ce_inc_search(EditLine *el, int dir)
 		if (el->el_search.patlen == 0) {	/* first round */
 			pchar = ':';
 #ifdef ANCHOR
+#define	LEN	2
 			el->el_search.patbuf[el->el_search.patlen++] = '.';
 			el->el_search.patbuf[el->el_search.patlen++] = '*';
+#else
+#define	LEN	0
 #endif
 		}
 		done = redo = 0;
@@ -233,7 +233,7 @@ ce_inc_search(EditLine *el, int dir)
 		    *cp; *el->el_line.lastchar++ = *cp++)
 			continue;
 		*el->el_line.lastchar++ = pchar;
-		for (cp = &el->el_search.patbuf[1];
+		for (cp = &el->el_search.patbuf[LEN];
 		    cp < &el->el_search.patbuf[el->el_search.patlen];
 		    *el->el_line.lastchar++ = *cp++)
 			continue;
@@ -246,7 +246,7 @@ ce_inc_search(EditLine *el, int dir)
 		switch (el->el_map.current[(unsigned char) ch]) {
 		case ED_INSERT:
 		case ED_DIGIT:
-			if (el->el_search.patlen > EL_BUFSIZ - 3)
+			if (el->el_search.patlen >= EL_BUFSIZ - LEN)
 				term_beep(el);
 			else {
 				el->el_search.patbuf[el->el_search.patlen++] =
@@ -267,8 +267,9 @@ ce_inc_search(EditLine *el, int dir)
 			redo++;
 			break;
 
+		case EM_DELETE_PREV_CHAR:
 		case ED_DELETE_PREV_CHAR:
-			if (el->el_search.patlen > 1)
+			if (el->el_search.patlen > LEN)
 				done++;
 			else
 				term_beep(el);
@@ -283,17 +284,18 @@ ce_inc_search(EditLine *el, int dir)
 
 			case 0027:	/* ^W: Append word */
 			/* No can do if globbing characters in pattern */
-				for (cp = &el->el_search.patbuf[1];; cp++)
-				    if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
+				for (cp = &el->el_search.patbuf[LEN];; cp++)
+				    if (cp >= &el->el_search.patbuf[
+					el->el_search.patlen]) {
 					el->el_line.cursor +=
-					    el->el_search.patlen - 1;
+					    el->el_search.patlen - LEN - 1;
 					cp = c__next_word(el->el_line.cursor,
 					    el->el_line.lastchar, 1,
 					    ce__isword);
 					while (el->el_line.cursor < cp &&
 					    *el->el_line.cursor != '\n') {
-						if (el->el_search.patlen >
-						    EL_BUFSIZ - 3) {
+						if (el->el_search.patlen >=
+						    EL_BUFSIZ - LEN) {
 							term_beep(el);
 							break;
 						}
@@ -335,13 +337,13 @@ ce_inc_search(EditLine *el, int dir)
 			/* Can't search if unmatched '[' */
 			for (cp = &el->el_search.patbuf[el->el_search.patlen-1],
 			    ch = ']';
-			    cp > el->el_search.patbuf;
+			    cp >= &el->el_search.patbuf[LEN];
 			    cp--)
 				if (*cp == '[' || *cp == ']') {
 					ch = *cp;
 					break;
 				}
-			if (el->el_search.patlen > 1 && ch != '[') {
+			if (el->el_search.patlen > LEN && ch != '[') {
 				if (redo && newdir == dir) {
 					if (pchar == '?') { /* wrap around */
 						el->el_history.eventno =
@@ -371,9 +373,8 @@ ce_inc_search(EditLine *el, int dir)
 				    '\0';
 				if (el->el_line.cursor < el->el_line.buffer ||
 				    el->el_line.cursor > el->el_line.lastchar ||
-				    (ret = ce_search_line(el,
-				    &el->el_search.patbuf[1],
-				    newdir)) == CC_ERROR) {
+				    (ret = ce_search_line(el, newdir))
+				    == CC_ERROR) {
 					/* avoid c_setpat */
 					el->el_state.lastcmd =
 					    (el_action_t) newdir;
@@ -386,11 +387,11 @@ ce_inc_search(EditLine *el, int dir)
 						    el->el_line.lastchar :
 						    el->el_line.buffer;
 						(void) ce_search_line(el,
-						    &el->el_search.patbuf[1],
 						    newdir);
 					}
 				}
-				el->el_search.patbuf[--el->el_search.patlen] =
+				el->el_search.patlen -= LEN;
+				el->el_search.patbuf[el->el_search.patlen] =
 				    '\0';
 				if (ret == CC_ERROR) {
 					term_beep(el);
@@ -446,29 +447,20 @@ cv_search(EditLine *el, int dir)
 	char tmpbuf[EL_BUFSIZ];
 	int tmplen;
 
-	tmplen = 0;
 #ifdef ANCHOR
-	tmpbuf[tmplen++] = '.';
-	tmpbuf[tmplen++] = '*';
+	tmpbuf[0] = '.';
+	tmpbuf[1] = '*';
 #endif
+	tmplen = LEN;
 
-	el->el_line.buffer[0] = '\0';
-	el->el_line.lastchar = el->el_line.buffer;
-	el->el_line.cursor = el->el_line.buffer;
 	el->el_search.patdir = dir;
 
-	c_insert(el, 2);	/* prompt + '\n' */
-	*el->el_line.cursor++ = '\n';
-	*el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
-	re_refresh(el);
+	tmplen = c_gets(el, &tmpbuf[LEN],
+		dir == ED_SEARCH_PREV_HISTORY ? "\n/" : "\n?" );
+	if (tmplen == -1)
+		return CC_REFRESH;
 
-#ifdef ANCHOR
-#define	LEN	2
-#else
-#define	LEN	0
-#endif
-
-	tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
+	tmplen += LEN;
 	ch = tmpbuf[tmplen];
 	tmpbuf[tmplen] = '\0';
 
@@ -477,9 +469,6 @@ cv_search(EditLine *el, int dir)
 		 * Use the old pattern, but wild-card it.
 		 */
 		if (el->el_search.patlen == 0) {
-			el->el_line.buffer[0] = '\0';
-			el->el_line.lastchar = el->el_line.buffer;
-			el->el_line.cursor = el->el_line.buffer;
 			re_refresh(el);
 			return (CC_ERROR);
 		}
@@ -510,19 +499,15 @@ cv_search(EditLine *el, int dir)
 	el->el_state.lastcmd = (el_action_t) dir;	/* avoid c_setpat */
 	el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
 	if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
-		ed_search_next_history(el, 0)) == CC_ERROR) {
+	    ed_search_next_history(el, 0)) == CC_ERROR) {
 		re_refresh(el);
 		return (CC_ERROR);
-	} else {
-		if (ch == 0033) {
-			re_refresh(el);
-			*el->el_line.lastchar++ = '\n';
-			*el->el_line.lastchar = '\0';
-			re_goto_bottom(el);
-			return (CC_NEWLINE);
-		} else
-			return (CC_REFRESH);
 	}
+	if (ch == 0033) {
+		re_refresh(el);
+		return ed_newline(el, 0);
+	}
+	return (CC_REFRESH);
 }
 
 
@@ -530,24 +515,39 @@ cv_search(EditLine *el, int dir)
  *	Look for a pattern inside a line
  */
 protected el_action_t
-ce_search_line(EditLine *el, char *pattern, int dir)
+ce_search_line(EditLine *el, int dir)
 {
-	char *cp;
+	char *cp = el->el_line.cursor;
+	char *pattern = el->el_search.patbuf;
+	char oc, *ocp;
+#ifdef ANCHOR
+	ocp = &pattern[1];
+	oc = *ocp;
+	*ocp = '^';
+#else
+	ocp = pattern;
+	oc = *ocp;
+#endif
 
 	if (dir == ED_SEARCH_PREV_HISTORY) {
-		for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--)
-			if (el_match(cp, pattern)) {
+		for (; cp >= el->el_line.buffer; cp--) {
+			if (el_match(cp, ocp)) {
+				*ocp = oc;
 				el->el_line.cursor = cp;
 				return (CC_NORM);
 			}
+		}
+		*ocp = oc;
 		return (CC_ERROR);
 	} else {
-		for (cp = el->el_line.cursor; *cp != '\0' &&
-		    cp < el->el_line.limit; cp++)
-			if (el_match(cp, pattern)) {
+		for (; *cp != '\0' && cp < el->el_line.limit; cp++) {
+			if (el_match(cp, ocp)) {
+				*ocp = oc;
 				el->el_line.cursor = cp;
 				return (CC_NORM);
 			}
+		}
+		*ocp = oc;
 		return (CC_ERROR);
 	}
 }
@@ -579,69 +579,53 @@ cv_repeat_srch(EditLine *el, int c)
 }
 
 
-/* cv_csearch_back():
- *	Vi character search reverse
+/* cv_csearch():
+ *	Vi character search
  */
 protected el_action_t
-cv_csearch_back(EditLine *el, int ch, int count, int tflag)
+cv_csearch(EditLine *el, int direction, int ch, int count, int tflag)
 {
 	char *cp;
 
+	if (ch == 0)
+		return CC_ERROR;
+
+	if (ch == -1) {
+		char c;
+		if (el_getc(el, &c) != 1)
+			return ed_end_of_file(el, 0);
+		ch = c;
+	}
+
+	/* Save for ';' and ',' commands */
+	el->el_search.chacha = ch;
+	el->el_search.chadir = direction;
+	el->el_search.chatflg = tflag;
+
 	cp = el->el_line.cursor;
 	while (count--) {
 		if (*cp == ch)
-			cp--;
-		while (cp > el->el_line.buffer && *cp != ch)
-			cp--;
+			cp += direction;
+		for (;;cp += direction) {
+			if (cp >= el->el_line.lastchar)
+				return CC_ERROR;
+			if (cp < el->el_line.buffer)
+				return CC_ERROR;
+			if (*cp == ch)
+				break;
+		}
 	}
 
-	if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
-		return (CC_ERROR);
-
-	if (*cp == ch && tflag)
-		cp++;
+	if (tflag)
+		cp -= direction;
 
 	el->el_line.cursor = cp;
 
-	if (el->el_chared.c_vcmd.action & DELETE) {
-		el->el_line.cursor++;
+	if (el->el_chared.c_vcmd.action != NOP) {
+		if (direction > 0)
+			el->el_line.cursor++;
 		cv_delfini(el);
-		return (CC_REFRESH);
+		return CC_REFRESH;
 	}
-	re_refresh_cursor(el);
-	return (CC_NORM);
-}
-
-
-/* cv_csearch_fwd():
- *	Vi character search forward
- */
-protected el_action_t
-cv_csearch_fwd(EditLine *el, int ch, int count, int tflag)
-{
-	char *cp;
-
-	cp = el->el_line.cursor;
-	while (count--) {
-		if (*cp == ch)
-			cp++;
-		while (cp < el->el_line.lastchar && *cp != ch)
-			cp++;
-	}
-
-	if (cp >= el->el_line.lastchar)
-		return (CC_ERROR);
-
-	if (*cp == ch && tflag)
-		cp--;
-
-	el->el_line.cursor = cp;
-
-	if (el->el_chared.c_vcmd.action & DELETE) {
-		el->el_line.cursor++;
-		cv_delfini(el);
-		return (CC_REFRESH);
-	}
-	re_refresh_cursor(el);
-	return (CC_NORM);
+	return CC_CURSOR;
 }
diff --git a/lib/libedit/search.h b/lib/libedit/search.h
index 8f9594a0d0be..725af7cadacd 100644
--- a/lib/libedit/search.h
+++ b/lib/libedit/search.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)search.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: search.h,v 1.4 1999/07/02 15:21:27 simonb Exp $
+ *	$NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $
  * $FreeBSD$
  */
 
@@ -52,6 +48,7 @@ typedef struct el_search_t {
 	int	 patdir;		/* Direction of the last search	*/
 	int	 chadir;		/* Character search direction	*/
 	char	 chacha;		/* Character we are looking for	*/
+	char	 chatflg;		/* 0 if f, 1 if t */
 } el_search_t;
 
 
@@ -62,9 +59,8 @@ protected int		c_hmatch(EditLine *, const char *);
 protected void		c_setpat(EditLine *);
 protected el_action_t	ce_inc_search(EditLine *, int);
 protected el_action_t	cv_search(EditLine *, int);
-protected el_action_t	ce_search_line(EditLine *, char *, int);
+protected el_action_t	ce_search_line(EditLine *, int);
 protected el_action_t	cv_repeat_srch(EditLine *, int);
-protected el_action_t	cv_csearch_back(EditLine *, int, int, int);
-protected el_action_t	cv_csearch_fwd(EditLine *, int, int, int);
+protected el_action_t	cv_csearch(EditLine *, int, int, int, int);
 
 #endif /* _h_el_search */
diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c
index 55bebb03b59c..a895aeabb158 100644
--- a/lib/libedit/sig.c
+++ b/lib/libedit/sig.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: sig.c,v 1.7 2001/01/04 15:55:03 christos Exp $
+ *	$NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -119,9 +115,9 @@ sig_init(EditLine *el)
 #undef	_DO
 	    (void) sigprocmask(SIG_BLOCK, &nset, &oset);
 
-#define	SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
+#define	SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(el_signalhandler_t))
 
-	el->el_signal = (sig_t *) el_malloc(SIGSIZE);
+	el->el_signal = (el_signalhandler_t *) el_malloc(SIGSIZE);
 	if (el->el_signal == NULL)
 		return (-1);
 	for (i = 0; sighdl[i] != -1; i++)
@@ -161,7 +157,7 @@ sig_set(EditLine *el)
 	    (void) sigprocmask(SIG_BLOCK, &nset, &oset);
 
 	for (i = 0; sighdl[i] != -1; i++) {
-		sig_t s;
+		el_signalhandler_t s;
 		/* This could happen if we get interrupted */
 		if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
 			el->el_signal[i] = s;
diff --git a/lib/libedit/sig.h b/lib/libedit/sig.h
index 80910658c856..b1ce14b09096 100644
--- a/lib/libedit/sig.h
+++ b/lib/libedit/sig.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)sig.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: sig.h,v 1.2 1997/01/11 06:48:11 lukem Exp $
+ *	$NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $
  * $FreeBSD$
  */
 
@@ -62,7 +58,8 @@
 	_DO(SIGCONT)	\
 	_DO(SIGWINCH)
 
-typedef sig_t	*el_signal_t;
+typedef void (*el_signalhandler_t)(int);
+typedef el_signalhandler_t *el_signal_t;
 
 protected void	sig_end(EditLine*);
 protected int	sig_init(EditLine*);
diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h
index 894f59e8ec66..323aebe4dafa 100644
--- a/lib/libedit/sys.h
+++ b/lib/libedit/sys.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)sys.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: sys.h,v 1.3 1997/01/11 06:48:12 lukem Exp $
+ *	$NetBSD: sys.h,v 1.9 2004/01/17 17:57:40 christos Exp $
  * $FreeBSD$
  */
 
@@ -74,20 +70,24 @@ typedef void	*ioctl_t;
 #define	REGEX		/* Use POSIX.2 regular expression functions */
 #undef	REGEXP		/* Use UNIX V8 regular expression functions */
 
-#ifdef SUNOS
+#ifdef notdef
 # undef REGEX
 # undef REGEXP
 # include <malloc.h>
-typedef void (*sig_t)(int);
 # ifdef __GNUC__
 /*
  * Broken hdrs.
  */
+extern int	tgetent(const char *bp, char *name);
+extern int	tgetflag(const char *id);
+extern int	tgetnum(const char *id);
+extern char    *tgetstr(const char *id, char **area);
+extern char    *tgoto(const char *cap, int col, int row);
+extern int	tputs(const char *str, int affcnt, int (*putc)(int));
 extern char    *getenv(const char *);
 extern int	fprintf(FILE *, const char *, ...);
 extern int	sigsetmask(int);
 extern int	sigblock(int);
-extern int	ioctl(int, int, void *);
 extern int	fputc(int, FILE *);
 extern int	fgetc(FILE *);
 extern int	fflush(FILE *);
@@ -96,7 +96,6 @@ extern int	toupper(int);
 extern int	errno, sys_nerr;
 extern char	*sys_errlist[];
 extern void	perror(const char *);
-extern int	read(int, const char*, int);
 #  include <string.h>
 #  define strerror(e)	sys_errlist[e]
 # endif
diff --git a/lib/libedit/term.c b/lib/libedit/term.c
index 03cd4c444536..b9263034c97b 100644
--- a/lib/libedit/term.c
+++ b/lib/libedit/term.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: term.c,v 1.31 2001/01/10 22:42:56 jdolecek Exp $
+ *	$NetBSD: term.c,v 1.40 2004/05/22 23:21:28 christos Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -47,13 +43,15 @@ __FBSDID("$FreeBSD$");
  *	   We have to declare a static variable here, since the
  *	   termcap putchar routine does not take an argument!
  */
-#include "sys.h"
 #include <stdio.h>
 #include <signal.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <termcap.h>
+#include <curses.h>
+#include <ncurses.h>
+#include <term.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 
@@ -258,7 +256,7 @@ private void	term_setflags(EditLine *);
 private int	term_rebuffer_display(EditLine *);
 private void	term_free_display(EditLine *);
 private int	term_alloc_display(EditLine *);
-private void	term_alloc(EditLine *, const struct termcapstr *, char *);
+private void	term_alloc(EditLine *, const struct termcapstr *, const char *);
 private void	term_init_arrow(EditLine *);
 private void	term_reset_arrow(EditLine *);
 
@@ -339,10 +337,10 @@ term_init(EditLine *el)
 	(void) memset(el->el_term.t_val, 0, T_val * sizeof(int));
 	term_outfile = el->el_outfile;
 	term_init_arrow(el);
-	if (term_set(el, NULL) == -1)
-		return (-1);
+	(void) term_set(el, NULL);
 	return (0);
 }
+
 /* term_end():
  *	Clean up the terminal stuff
  */
@@ -359,6 +357,8 @@ term_end(EditLine *el)
 	el->el_term.t_str = NULL;
 	el_free((ptr_t) el->el_term.t_val);
 	el->el_term.t_val = NULL;
+	el_free((ptr_t) el->el_term.t_fkey);
+	el->el_term.t_fkey = NULL;
 	term_free_display(el);
 }
 
@@ -367,7 +367,7 @@ term_end(EditLine *el)
  *	Maintain a string pool for termcap strings
  */
 private void
-term_alloc(EditLine *el, const struct termcapstr *t, char *cap)
+term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
 {
 	char termbuf[TC_BUFSIZE];
 	int tlen, clen;
@@ -635,7 +635,8 @@ mc_again:
 				 * from col 0
 				 */
 				if (EL_CAN_TAB ?
-				    (-del > (((unsigned int) where >> 3) +
+				    ((unsigned int)-del >
+				    (((unsigned int) where >> 3) +
 				     (where & 07)))
 				    : (-del > where)) {
 					term__putc('\r');	/* do a CR */
@@ -655,7 +656,7 @@ mc_again:
  *	Overstrike num characters
  */
 protected void
-term_overwrite(EditLine *el, char *cp, int n)
+term_overwrite(EditLine *el, const char *cp, int n)
 {
 	if (n <= 0)
 		return;		/* catch bugs */
@@ -863,12 +864,18 @@ term_clear_to_bottom(EditLine *el)
 }
 #endif
 
+protected void
+term_get(EditLine *el, const char **term)
+{
+	*term = el->el_term.t_name;
+}
+
 
 /* term_set():
  *	Read in the terminal capabilities from the requested terminal
  */
 protected int
-term_set(EditLine *el, char *term)
+term_set(EditLine *el, const char *term)
 {
 	int i;
 	char buf[TC_BUFSIZE];
@@ -924,8 +931,11 @@ term_set(EditLine *el, char *term)
 		/* Get the size */
 		Val(T_co) = tgetnum("co");
 		Val(T_li) = tgetnum("li");
-		for (t = tstr; t->name != NULL; t++)
-			term_alloc(el, t, tgetstr(t->name, &area));
+		for (t = tstr; t->name != NULL; t++) {
+			/* XXX: some systems tgetstr needs non const */
+			term_alloc(el, t, tgetstr(strchr(t->name, *t->name),
+			    &area));
+		}
 	}
 
 	if (Val(T_co) < 2)
@@ -944,6 +954,7 @@ term_set(EditLine *el, char *term)
 		return (-1);
 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
 	term_bind_arrow(el);
+	el->el_term.t_name = term;
 	return (i <= 0 ? -1 : 0);
 }
 
@@ -1105,7 +1116,7 @@ term_reset_arrow(EditLine *el)
  *	Set an arrow key binding
  */
 protected int
-term_set_arrow(EditLine *el, char *name, key_value_t *fun, int type)
+term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type)
 {
 	fkey_t *arrow = el->el_term.t_fkey;
 	int i;
@@ -1124,7 +1135,7 @@ term_set_arrow(EditLine *el, char *name, key_value_t *fun, int type)
  *	Clear an arrow key binding
  */
 protected int
-term_clear_arrow(EditLine *el, char *name)
+term_clear_arrow(EditLine *el, const char *name)
 {
 	fkey_t *arrow = el->el_term.t_fkey;
 	int i;
@@ -1142,7 +1153,7 @@ term_clear_arrow(EditLine *el, char *name)
  *	Print the arrow key bindings
  */
 protected void
-term_print_arrow(EditLine *el, char *name)
+term_print_arrow(EditLine *el, const char *name)
 {
 	int i;
 	fkey_t *arrow = el->el_term.t_fkey;
@@ -1239,7 +1250,8 @@ term__flush(void)
  */
 protected int
 /*ARGSUSED*/
-term_telltc(EditLine *el, int argc, char **argv)
+term_telltc(EditLine *el, int argc __unused, 
+    const char **argv __unused)
 {
 	const struct termcapstr *t;
 	char **ts;
@@ -1274,11 +1286,12 @@ term_telltc(EditLine *el, int argc, char **argv)
  */
 protected int
 /*ARGSUSED*/
-term_settc(EditLine *el, int argc, char **argv)
+term_settc(EditLine *el, int argc __unused,
+    const char **argv)
 {
 	const struct termcapstr *ts;
 	const struct termcapval *tv;
-	char *what, *how;
+	const char *what, *how;
 
 	if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
 		return (-1);
@@ -1350,7 +1363,8 @@ term_settc(EditLine *el, int argc, char **argv)
  */
 protected int
 /*ARGSUSED*/
-term_echotc(EditLine *el, int argc, char **argv)
+term_echotc(EditLine *el, int argc __unused,
+    const char **argv)
 {
 	char *cap, *scap, *ep;
 	int arg_need, arg_cols, arg_rows;
@@ -1409,7 +1423,7 @@ term_echotc(EditLine *el, int argc, char **argv)
 			}
 		(void) fprintf(el->el_outfile, fmtd, 0);
 #else
-		(void) fprintf(el->el_outfile, fmtd, el->el_tty.t_speed);
+		(void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed);
 #endif
 		return (0);
 	} else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
@@ -1428,8 +1442,10 @@ term_echotc(EditLine *el, int argc, char **argv)
 			scap = el->el_term.t_str[t - tstr];
 			break;
 		}
-	if (t->name == NULL)
-		scap = tgetstr(*argv, &area);
+	if (t->name == NULL) {
+		/* XXX: some systems tgetstr needs non const */
+		scap = tgetstr(strchr(*argv, **argv), &area);
+	}
 	if (!scap || scap[0] == '\0') {
 		if (!silent)
 			(void) fprintf(el->el_errfile,
diff --git a/lib/libedit/term.h b/lib/libedit/term.h
index 9dff45727344..d97b46d35789 100644
--- a/lib/libedit/term.h
+++ b/lib/libedit/term.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)term.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: term.h,v 1.11 2000/11/11 22:18:58 christos Exp $
+ *	$NetBSD: term.h,v 1.16 2005/03/15 00:10:40 christos Exp $
  * $FreeBSD$
  */
 
@@ -47,13 +43,14 @@
 #include "histedit.h"
 
 typedef struct {		/* Symbolic function key bindings	*/
-	char		*name;	/* name of the key			*/
+	const char	*name;	/* name of the key			*/
 	int		 key;	/* Index in termcap table		*/
 	key_value_t	 fun;	/* Function bound to it			*/
 	int		 type;	/* Type of function			*/
 } fkey_t;
 
 typedef struct {
+	const char *t_name;		/* the terminal name	*/
 	coord_t	  t_size;		/* # lines and cols	*/
 	int	  t_flags;
 #define	TERM_CAN_INSERT		0x001	/* Has insert cap	*/
@@ -87,7 +84,7 @@ typedef struct {
 protected void	term_move_to_line(EditLine *, int);
 protected void	term_move_to_char(EditLine *, int);
 protected void	term_clear_EOL(EditLine *, int);
-protected void	term_overwrite(EditLine *, char *, int);
+protected void	term_overwrite(EditLine *, const char *, int);
 protected void	term_insertwrite(EditLine *, char *, int);
 protected void	term_deletechars(EditLine *, int);
 protected void	term_clear_screen(EditLine *);
@@ -96,14 +93,15 @@ protected int	term_change_size(EditLine *, int, int);
 protected int	term_get_size(EditLine *, int *, int *);
 protected int	term_init(EditLine *);
 protected void	term_bind_arrow(EditLine *);
-protected void	term_print_arrow(EditLine *, char *);
-protected int	term_clear_arrow(EditLine *, char *);
-protected int	term_set_arrow(EditLine *, char *, key_value_t *, int);
+protected void	term_print_arrow(EditLine *, const char *);
+protected int	term_clear_arrow(EditLine *, const char *);
+protected int	term_set_arrow(EditLine *, const char *, key_value_t *, int);
 protected void	term_end(EditLine *);
-protected int	term_set(EditLine *, char *);
-protected int	term_settc(EditLine *, int, char **);
-protected int	term_telltc(EditLine *, int, char **);
-protected int	term_echotc(EditLine *, int, char **);
+protected void	term_get(EditLine *, const char **);
+protected int	term_set(EditLine *, const char *);
+protected int	term_settc(EditLine *, int, const char **);
+protected int	term_telltc(EditLine *, int, const char **);
+protected int	term_echotc(EditLine *, int, const char **);
 protected int	term__putc(int);
 protected void	term__flush(void);
 
@@ -117,6 +115,7 @@ protected void	term__flush(void);
 #define	EL_CAN_CEOL		(EL_FLAGS & TERM_CAN_CEOL)
 #define	EL_CAN_TAB		(EL_FLAGS & TERM_CAN_TAB)
 #define	EL_CAN_ME		(EL_FLAGS & TERM_CAN_ME)
+#define EL_CAN_UP		(EL_FLAGS & TERM_CAN_UP)
 #define	EL_HAS_META		(EL_FLAGS & TERM_HAS_META)
 #define	EL_HAS_AUTO_MARGINS	(EL_FLAGS & TERM_HAS_AUTO_MARGINS)
 #define	EL_HAS_MAGIC_MARGINS	(EL_FLAGS & TERM_HAS_MAGIC_MARGINS)
diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c
index 463a980bcad6..8e3100de586b 100644
--- a/lib/libedit/tokenizer.c
+++ b/lib/libedit/tokenizer.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: tokenizer.c,v 1.6 2000/09/04 22:06:33 lukem Exp $
+ *	$NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -48,7 +44,7 @@ __FBSDID("$FreeBSD$");
 #include "sys.h"
 #include <string.h>
 #include <stdlib.h>
-#include "tokenizer.h"
+#include "histedit.h"
 
 typedef enum {
 	Q_none, Q_single, Q_double, Q_one, Q_doubleone
@@ -62,6 +58,7 @@ typedef enum {
 #define	WINCR		20
 #define	AINCR		10
 
+#define	tok_strdup(a)		strdup(a)
 #define	tok_malloc(a)		malloc(a)
 #define	tok_free(a)		free(a)
 #define	tok_realloc(a, b)	realloc(a, b)
@@ -107,16 +104,29 @@ tok_init(const char *ifs)
 {
 	Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer));
 
-	tok->ifs = strdup(ifs ? ifs : IFS);
+	if (tok == NULL)
+		return NULL;
+	tok->ifs = tok_strdup(ifs ? ifs : IFS);
+	if (tok->ifs == NULL) {
+		tok_free((ptr_t)tok);
+		return NULL;
+	}
 	tok->argc = 0;
 	tok->amax = AINCR;
 	tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
-	if (tok->argv == NULL)
-		return (NULL);
+	if (tok->argv == NULL) {
+		tok_free((ptr_t)tok->ifs);
+		tok_free((ptr_t)tok);
+		return NULL;
+	}
 	tok->argv[0] = NULL;
 	tok->wspace = (char *) tok_malloc(WINCR);
-	if (tok->wspace == NULL)
-		return (NULL);
+	if (tok->wspace == NULL) {
+		tok_free((ptr_t)tok->argv);
+		tok_free((ptr_t)tok->ifs);
+		tok_free((ptr_t)tok);
+		return NULL;
+	}
 	tok->wmax = tok->wspace + WINCR;
 	tok->wstart = tok->wspace;
 	tok->wptr = tok->wspace;
@@ -158,21 +168,39 @@ tok_end(Tokenizer *tok)
 
 
 /* tok_line():
- *	Bourne shell like tokenizing
- *	Return:
- *		-1: Internal error
- *		 3: Quoted return
- *		 2: Unmatched double quote
- *		 1: Unmatched single quote
- *		 0: Ok
+ *	Bourne shell (sh(1)) like tokenizing
+ *	Arguments:
+ *		tok	current tokenizer state (setup with tok_init())
+ *		line	line to parse
+ *	Returns:
+ *		-1	Internal error
+ *		 3	Quoted return
+ *		 2	Unmatched double quote
+ *		 1	Unmatched single quote
+ *		 0	Ok
+ *	Modifies (if return value is 0):
+ *		argc	number of arguments
+ *		argv	argument array
+ *		cursorc	if !NULL, argv element containing cursor
+ *		cursorv	if !NULL, offset in argv[cursorc] of cursor
  */
 public int
-tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)
+tok_line(Tokenizer *tok, const LineInfo *line,
+    int *argc, const char ***argv, int *cursorc, int *cursoro)
 {
 	const char *ptr;
+	int cc, co;
 
-	for (;;) {
-		switch (*(ptr = line++)) {
+	cc = co = -1;
+	ptr = line->buffer;
+	for (ptr = line->buffer; ;ptr++) {
+		if (ptr >= line->lastchar)
+			ptr = "";
+		if (ptr == line->cursor) {
+			cc = tok->argc;
+			co = tok->wptr - tok->wstart;
+		}
+		switch (*ptr) {
 		case '\'':
 			tok->flags |= TOK_KEEP;
 			tok->flags &= ~TOK_EAT;
@@ -271,10 +299,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)
 			tok->flags &= ~TOK_EAT;
 			switch (tok->quote) {
 			case Q_none:
-				tok_finish(tok);
-				*argv = tok->argv;
-				*argc = tok->argc;
-				return (0);
+				goto tok_line_outok;
 
 			case Q_single:
 			case Q_double:
@@ -304,10 +329,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)
 					tok->flags &= ~TOK_EAT;
 					return (3);
 				}
-				tok_finish(tok);
-				*argv = tok->argv;
-				*argc = tok->argc;
-				return (0);
+				goto tok_line_outok;
 
 			case Q_single:
 				return (1);
@@ -367,20 +389,20 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)
 		if (tok->wptr >= tok->wmax - 4) {
 			size_t size = tok->wmax - tok->wspace + WINCR;
 			char *s = (char *) tok_realloc(tok->wspace, size);
-			/* SUPPRESS 22 */
-			int offs = s - tok->wspace;
 			if (s == NULL)
 				return (-1);
 
-			if (offs != 0) {
+			if (s != tok->wspace) {
 				int i;
-				for (i = 0; i < tok->argc; i++)
-					tok->argv[i] = tok->argv[i] + offs;
-				tok->wptr = tok->wptr + offs;
-				tok->wstart = tok->wstart + offs;
-				tok->wmax = s + size;
+				for (i = 0; i < tok->argc; i++) {
+				    tok->argv[i] =
+					(tok->argv[i] - tok->wspace) + s;
+				}
+				tok->wptr = (tok->wptr - tok->wspace) + s;
+				tok->wstart = (tok->wstart - tok->wspace) + s;
 				tok->wspace = s;
 			}
+			tok->wmax = s + size;
 		}
 		if (tok->argc >= tok->amax - 4) {
 			char **p;
@@ -392,4 +414,32 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)
 			tok->argv = p;
 		}
 	}
+ tok_line_outok:
+	if (cc == -1 && co == -1) {
+		cc = tok->argc;
+		co = tok->wptr - tok->wstart;
+	}
+	if (cursorc != NULL)
+		*cursorc = cc;
+	if (cursoro != NULL)
+		*cursoro = co;
+	tok_finish(tok);
+	*argv = (const char **)tok->argv;
+	*argc = tok->argc;
+	return (0);
+}
+
+/* tok_str():
+ *	Simpler version of tok_line, taking a NUL terminated line
+ *	and splitting into words, ignoring cursor state.
+ */
+public int
+tok_str(Tokenizer *tok, const char *line, int *argc, const char ***argv)
+{
+	LineInfo li;
+
+	memset(&li, 0, sizeof(li));
+	li.buffer = line;
+	li.cursor = li.lastchar = strchr(line, '\0');
+	return (tok_line(tok, &li, argc, argv, NULL, NULL));
 }
diff --git a/lib/libedit/tokenizer.h b/lib/libedit/tokenizer.h
deleted file mode 100644
index b49c9dbc0f8c..000000000000
--- a/lib/libedit/tokenizer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)tokenizer.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: tokenizer.h,v 1.3 1999/07/02 15:21:27 simonb Exp $
- * $FreeBSD$
- */
-
-/*
- * tokenizer.h: Header file for tokenizer routines
- */
-#ifndef _h_tokenizer
-#define	_h_tokenizer
-
-typedef struct tokenizer Tokenizer;
-
-Tokenizer	*tok_init(const char *);
-void		 tok_reset(Tokenizer *);
-void		 tok_end(Tokenizer *);
-int		 tok_line(Tokenizer *, const char *, int *, char ***);
-
-#endif /* _h_tokenizer */
diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c
index b4c9f4f4e10e..e2b99327ea96 100644
--- a/lib/libedit/tty.c
+++ b/lib/libedit/tty.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: tty.c,v 1.14 2001/01/09 17:31:04 jdolecek Exp $
+ *	$NetBSD: tty.c,v 1.23 2005/06/01 11:37:52 lukem Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -45,20 +41,21 @@ __FBSDID("$FreeBSD$");
 /*
  * tty.c: tty interface stuff
  */
+#include <assert.h>
 #include "sys.h"
 #include "tty.h"
 #include "el.h"
 
 typedef struct ttymodes_t {
 	const char *m_name;
-	u_int m_value;
+	unsigned int m_value;
 	int m_type;
 }          ttymodes_t;
 
 typedef struct ttymap_t {
 	int nch, och;		/* Internal and termio rep of chars */
 	el_action_t bind[3];	/* emacs, vi, and vi-cmd */
-}        ttymap_t;
+} ttymap_t;
 
 
 private const ttyperm_t ttyperm = {
@@ -122,11 +119,11 @@ private const ttychar_t ttychar = {
 private const ttymap_t tty_map[] = {
 #ifdef VERASE
 	{C_ERASE, VERASE,
-	{ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
 #endif /* VERASE */
 #ifdef VERASE2
 	{C_ERASE2, VERASE2,
-	{ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
 #endif /* VERASE2 */
 #ifdef VKILL
 	{C_KILL, VKILL,
@@ -453,6 +450,7 @@ private const ttymodes_t ttymodes[] = {
 #define	tty__geteightbit(td)	(((td)->c_cflag & CSIZE) == CS8)
 #define	tty__cooked_mode(td)	((td)->c_lflag & ICANON)
 
+private int	tty__getcharindex(int);
 private void	tty__getchar(struct termios *, unsigned char *);
 private void	tty__setchar(struct termios *, unsigned char *);
 private speed_t	tty__getspeed(struct termios *);
@@ -544,7 +542,7 @@ tty_init(EditLine *el)
  */
 protected void
 /*ARGSUSED*/
-tty_end(EditLine *el)
+tty_end(EditLine *el __unused)
 {
 
 	/* XXX: Maybe reset to an initial state? */
@@ -564,6 +562,113 @@ tty__getspeed(struct termios *td)
 	return (spd);
 }
 
+/* tty__getspeed():
+ *	Return the index of the asked char in the c_cc array
+ */
+private int
+tty__getcharindex(int i)
+{
+	switch (i) {
+#ifdef VINTR
+	case C_INTR:
+		return VINTR;
+#endif /* VINTR */
+#ifdef VQUIT
+	case C_QUIT:
+		return VQUIT;
+#endif /* VQUIT */
+#ifdef VERASE
+	case C_ERASE:
+		return VERASE;
+#endif /* VERASE */
+#ifdef VKILL
+	case C_KILL:
+		return VKILL;
+#endif /* VKILL */
+#ifdef VEOF
+	case C_EOF:
+		return VEOF;
+#endif /* VEOF */
+#ifdef VEOL
+	case C_EOL:
+		return VEOL;
+#endif /* VEOL */
+#ifdef VEOL2
+	case C_EOL2:
+		return VEOL2;
+#endif /* VEOL2 */
+#ifdef VSWTCH
+	case C_SWTCH:
+		return VSWTCH;
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+	case C_DSWTCH:
+		return VDSWTCH;
+#endif /* VDSWTCH */
+#ifdef VERASE2
+	case C_ERASE2:
+		return VERASE2;
+#endif /* VERASE2 */
+#ifdef VSTART
+	case C_START:
+		return VSTART;
+#endif /* VSTART */
+#ifdef VSTOP
+	case C_STOP:
+		return VSTOP;
+#endif /* VSTOP */
+#ifdef VWERASE
+	case C_WERASE:
+		return VWERASE;
+#endif /* VWERASE */
+#ifdef VSUSP
+	case C_SUSP:
+		return VSUSP;
+#endif /* VSUSP */
+#ifdef VDSUSP
+	case C_DSUSP:
+		return VDSUSP;
+#endif /* VDSUSP */
+#ifdef VREPRINT
+	case C_REPRINT:
+		return VREPRINT;
+#endif /* VREPRINT */
+#ifdef VDISCARD
+	case C_DISCARD:
+		return VDISCARD;
+#endif /* VDISCARD */
+#ifdef VLNEXT
+	case C_LNEXT:
+		return VLNEXT;
+#endif /* VLNEXT */
+#ifdef VSTATUS
+	case C_STATUS:
+		return VSTATUS;
+#endif /* VSTATUS */
+#ifdef VPAGE
+	case C_PAGE:
+		return VPAGE;
+#endif /* VPAGE */
+#ifdef VPGOFF
+	case C_PGOFF:
+		return VPGOFF;
+#endif /* VPGOFF */
+#ifdef VKILL2
+	case C_KILL2:
+		return VKILL2;
+#endif /* KILL2 */
+#ifdef VMIN
+	case C_MIN:
+		return VMIN;
+#endif /* VMIN */
+#ifdef VTIME
+	case C_TIME:
+		return VTIME;
+#endif /* VTIME */
+	default:
+		return -1;
+	}
+}
 
 /* tty__getchar():
  *	Get the tty characters
@@ -990,13 +1095,14 @@ tty_noquotemode(EditLine *el)
  */
 protected int
 /*ARGSUSED*/
-tty_stty(EditLine *el, int argc, char **argv)
+tty_stty(EditLine *el, int argc __unused, const char **argv)
 {
 	const ttymodes_t *m;
-	char x, *d;
+	char x;
 	int aflag = 0;
-	char *s;
-	char *name;
+	const char *s, *d;
+	const char *name;
+	struct termios *tios = &el->el_tty.t_ex;
 	int z = EX_IO;
 
 	if (argv == NULL)
@@ -1011,14 +1117,17 @@ tty_stty(EditLine *el, int argc, char **argv)
 			break;
 		case 'd':
 			argv++;
+			tios = &el->el_tty.t_ed;
 			z = ED_IO;
 			break;
 		case 'x':
 			argv++;
+			tios = &el->el_tty.t_ex;
 			z = EX_IO;
 			break;
 		case 'q':
 			argv++;
+			tios = &el->el_tty.t_ts;
 			z = QU_IO;
 			break;
 		default:
@@ -1068,6 +1177,7 @@ tty_stty(EditLine *el, int argc, char **argv)
 		return (0);
 	}
 	while (argv && (s = *argv++)) {
+		const char *p;
 		switch (*s) {
 		case '+':
 		case '-':
@@ -1078,8 +1188,11 @@ tty_stty(EditLine *el, int argc, char **argv)
 			break;
 		}
 		d = s;
+		p = strchr(s, '=');
 		for (m = ttymodes; m->m_name; m++)
-			if (strcmp(m->m_name, d) == 0)
+			if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) :
+			    strcmp(m->m_name, d)) == 0 &&
+			    (p == NULL || m->m_type == MD_CHAR))
 				break;
 
 		if (!m->m_name) {
@@ -1087,6 +1200,16 @@ tty_stty(EditLine *el, int argc, char **argv)
 			    "%s: Invalid argument `%s'.\n", name, d);
 			return (-1);
 		}
+		if (p) {
+			int c = ffs((int)m->m_value);
+			int v = *++p ? parse__escape((const char **) &p) :
+			    el->el_tty.t_vdisable;
+			assert(c-- != 0);
+			c = tty__getcharindex(c);
+			assert(c != -1);
+			tios->c_cc[c] = v;
+			continue;
+		}
 		switch (x) {
 		case '+':
 			el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h
index 7e9cd8b038ae..3a4e94accf33 100644
--- a/lib/libedit/tty.h
+++ b/lib/libedit/tty.h
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -34,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)tty.h	8.1 (Berkeley) 6/4/93
- *	$NetBSD: tty.h,v 1.7 1999/09/26 14:37:47 lukem Exp $
+ *	$NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $
  * $FreeBSD$
  */
 
@@ -453,16 +449,16 @@
 #define	MD_NN	5
 
 typedef struct {
-	char	*t_name;
-	u_int	 t_setmask;
-	u_int	 t_clrmask;
+	const char	*t_name;
+	unsigned int	 t_setmask;
+	unsigned int	 t_clrmask;
 } ttyperm_t[NN_IO][MD_NN];
 
 typedef unsigned char ttychar_t[NN_IO][C_NCC];
 
 protected int	tty_init(EditLine *);
 protected void	tty_end(EditLine *);
-protected int	tty_stty(EditLine *, int, char**);
+protected int	tty_stty(EditLine *, int, const char **);
 protected int	tty_rawmode(EditLine *);
 protected int	tty_cookedmode(EditLine *);
 protected int	tty_quotemode(EditLine *);
diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c
index 72de5c9b0ce7..ae65bbcb29ba 100644
--- a/lib/libedit/vi.c
+++ b/lib/libedit/vi.c
@@ -13,11 +13,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -33,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$NetBSD: vi.c,v 1.7 1999/07/02 15:21:28 simonb Exp $
+ *	$NetBSD: vi.c,v 1.21 2005/04/25 01:06:03 matt Exp $
  */
 
 #if !defined(lint) && !defined(SCCSID)
@@ -45,6 +41,7 @@ __FBSDID("$FreeBSD$");
 /*
  * vi.c: Vi mode commands.
  */
+#include <sys/wait.h>
 #include "sys.h"
 #include "el.h"
 
@@ -57,22 +54,18 @@ private el_action_t	cv_paste(EditLine *, int);
 private el_action_t
 cv_action(EditLine *el, int c)
 {
-	char *cp, *kp;
 
-	if (el->el_chared.c_vcmd.action & DELETE) {
+	if (el->el_chared.c_vcmd.action != NOP) {
+		/* 'cc', 'dd' and (possibly) friends */
+		if (c != el->el_chared.c_vcmd.action)
+			return CC_ERROR;
+
+		if (!(c & YANK))
+			cv_undo(el);
+		cv_yank(el, el->el_line.buffer,
+			    el->el_line.lastchar - el->el_line.buffer);
 		el->el_chared.c_vcmd.action = NOP;
 		el->el_chared.c_vcmd.pos = 0;
-
-		el->el_chared.c_undo.isize = 0;
-		el->el_chared.c_undo.dsize = 0;
-		kp = el->el_chared.c_undo.buf;
-		for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
-			*kp++ = *cp;
-			el->el_chared.c_undo.dsize++;
-		}
-
-		el->el_chared.c_undo.action = INSERT;
-		el->el_chared.c_undo.ptr = el->el_line.buffer;
 		el->el_line.lastchar = el->el_line.buffer;
 		el->el_line.cursor = el->el_line.buffer;
 		if (c & INSERT)
@@ -83,25 +76,8 @@ cv_action(EditLine *el, int c)
 	el->el_chared.c_vcmd.pos = el->el_line.cursor;
 	el->el_chared.c_vcmd.action = c;
 	return (CC_ARGHACK);
-
-#ifdef notdef
-	/*
-         * I don't think that this is needed. But we keep it for now
-         */
-	else
-	if (el_chared.c_vcmd.action == NOP) {
-		el->el_chared.c_vcmd.pos = el->el_line.cursor;
-		el->el_chared.c_vcmd.action = c;
-		return (CC_ARGHACK);
-	} else {
-		el->el_chared.c_vcmd.action = 0;
-		el->el_chared.c_vcmd.pos = 0;
-		return (CC_ERROR);
-	}
-#endif
 }
 
-
 /* cv_paste():
  *	Paste previous deletion before or after the cursor
  */
@@ -109,23 +85,25 @@ private el_action_t
 cv_paste(EditLine *el, int c)
 {
 	char *ptr;
-	c_undo_t *un = &el->el_chared.c_undo;
+	c_kill_t *k = &el->el_chared.c_kill;
+	int len = k->last - k->buf;
 
-#ifdef DEBUG_PASTE
-	(void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
-	    un->action, un->buf, un->isize, un->dsize);
-#endif
-	if (un->isize == 0)
+	if (k->buf == NULL || len == 0)
 		return (CC_ERROR);
+#ifdef DEBUG_PASTE
+	(void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf);
+#endif
+
+	cv_undo(el);
 
 	if (!c && el->el_line.cursor < el->el_line.lastchar)
 		el->el_line.cursor++;
 	ptr = el->el_line.cursor;
 
-	c_insert(el, (int) un->isize);
-	if (el->el_line.cursor + un->isize > el->el_line.lastchar)
+	c_insert(el, len);
+	if (el->el_line.cursor + len > el->el_line.lastchar)
 		return (CC_ERROR);
-	(void) memcpy(ptr, un->buf, un->isize);
+	(void) memcpy(ptr, k->buf, len +0u);
 	return (CC_REFRESH);
 }
 
@@ -136,7 +114,7 @@ cv_paste(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_paste_next(EditLine *el, int c)
+vi_paste_next(EditLine *el, int c __unused)
 {
 
 	return (cv_paste(el, 0));
@@ -149,31 +127,31 @@ vi_paste_next(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_paste_prev(EditLine *el, int c)
+vi_paste_prev(EditLine *el, int c __unused)
 {
 
 	return (cv_paste(el, 1));
 }
 
 
-/* vi_prev_space_word():
+/* vi_prev_big_word():
  *	Vi move to the previous space delimited word
  *	[B]
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_prev_space_word(EditLine *el, int c)
+vi_prev_big_word(EditLine *el, int c)
 {
 
 	if (el->el_line.cursor == el->el_line.buffer)
 		return (CC_ERROR);
 
-	el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
 	    el->el_line.buffer,
 	    el->el_state.argument,
-	    c___isword);
+	    cv__isWord);
 
-	if (el->el_chared.c_vcmd.action & DELETE) {
+	if (el->el_chared.c_vcmd.action != NOP) {
 		cv_delfini(el);
 		return (CC_REFRESH);
 	}
@@ -187,18 +165,18 @@ vi_prev_space_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_prev_word(EditLine *el, int c)
+vi_prev_word(EditLine *el, int c __unused)
 {
 
 	if (el->el_line.cursor == el->el_line.buffer)
 		return (CC_ERROR);
 
-	el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
 	    el->el_line.buffer,
 	    el->el_state.argument,
 	    cv__isword);
 
-	if (el->el_chared.c_vcmd.action & DELETE) {
+	if (el->el_chared.c_vcmd.action != NOP) {
 		cv_delfini(el);
 		return (CC_REFRESH);
 	}
@@ -206,25 +184,23 @@ vi_prev_word(EditLine *el, int c)
 }
 
 
-/* vi_next_space_word():
+/* vi_next_big_word():
  *	Vi move to the next space delimited word
  *	[W]
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_next_space_word(EditLine *el, int c)
+vi_next_big_word(EditLine *el, int c)
 {
 
-	if (el->el_line.cursor == el->el_line.lastchar)
+	if (el->el_line.cursor >= el->el_line.lastchar - 1)
 		return (CC_ERROR);
 
 	el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
-	    el->el_line.lastchar,
-	    el->el_state.argument,
-	    c___isword);
+	    el->el_line.lastchar, el->el_state.argument, cv__isWord);
 
 	if (el->el_map.type == MAP_VI)
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -238,19 +214,17 @@ vi_next_space_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_next_word(EditLine *el, int c)
+vi_next_word(EditLine *el, int c __unused)
 {
 
-	if (el->el_line.cursor == el->el_line.lastchar)
+	if (el->el_line.cursor >= el->el_line.lastchar - 1)
 		return (CC_ERROR);
 
 	el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
-	    el->el_line.lastchar,
-	    el->el_state.argument,
-	    cv__isword);
+	    el->el_line.lastchar, el->el_state.argument, cv__isword);
 
 	if (el->el_map.type == MAP_VI)
-		if (el->el_chared.c_vcmd.action & DELETE) {
+		if (el->el_chared.c_vcmd.action != NOP) {
 			cv_delfini(el);
 			return (CC_REFRESH);
 		}
@@ -265,19 +239,27 @@ vi_next_word(EditLine *el, int c)
 protected el_action_t
 vi_change_case(EditLine *el, int c)
 {
+	int i;
 
-	if (el->el_line.cursor < el->el_line.lastchar) {
-		c = (unsigned char)*el->el_line.cursor;
+	if (el->el_line.cursor >= el->el_line.lastchar)
+		return (CC_ERROR);
+	cv_undo(el);
+	for (i = 0; i < el->el_state.argument; i++) {
+
+		c = *(unsigned char *)el->el_line.cursor;
 		if (isupper(c))
-			*el->el_line.cursor++ = tolower(c);
+			*el->el_line.cursor = tolower(c);
 		else if (islower(c))
-			*el->el_line.cursor++ = toupper(c);
-		else
-			el->el_line.cursor++;
+			*el->el_line.cursor = toupper(c);
+
+		if (++el->el_line.cursor >= el->el_line.lastchar) {
+			el->el_line.cursor--;
+			re_fastaddc(el);
+			break;
+		}
 		re_fastaddc(el);
-		return (CC_NORM);
 	}
-	return (CC_ERROR);
+	return CC_NORM;
 }
 
 
@@ -287,7 +269,7 @@ vi_change_case(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_change_meta(EditLine *el, int c)
+vi_change_meta(EditLine *el, int c __unused)
 {
 
 	/*
@@ -304,15 +286,11 @@ vi_change_meta(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_insert_at_bol(EditLine *el, int c)
+vi_insert_at_bol(EditLine *el, int c __unused)
 {
 
 	el->el_line.cursor = el->el_line.buffer;
-	el->el_chared.c_vcmd.ins = el->el_line.cursor;
-
-	el->el_chared.c_undo.ptr = el->el_line.cursor;
-	el->el_chared.c_undo.action = DELETE;
-
+	cv_undo(el);
 	el->el_map.current = el->el_map.key;
 	return (CC_CURSOR);
 }
@@ -324,15 +302,15 @@ vi_insert_at_bol(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_replace_char(EditLine *el, int c)
+vi_replace_char(EditLine *el, int c __unused)
 {
 
+	if (el->el_line.cursor >= el->el_line.lastchar)
+		return CC_ERROR;
+
 	el->el_map.current = el->el_map.key;
 	el->el_state.inputmode = MODE_REPLACE_1;
-	el->el_chared.c_undo.action = CHANGE;
-	el->el_chared.c_undo.ptr = el->el_line.cursor;
-	el->el_chared.c_undo.isize = 0;
-	el->el_chared.c_undo.dsize = 0;
+	cv_undo(el);
 	return (CC_ARGHACK);
 }
 
@@ -343,16 +321,13 @@ vi_replace_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_replace_mode(EditLine *el, int c)
+vi_replace_mode(EditLine *el, int c __unused)
 {
 
 	el->el_map.current = el->el_map.key;
 	el->el_state.inputmode = MODE_REPLACE;
-	el->el_chared.c_undo.action = CHANGE;
-	el->el_chared.c_undo.ptr = el->el_line.cursor;
-	el->el_chared.c_undo.isize = 0;
-	el->el_chared.c_undo.dsize = 0;
-	return (CC_ARGHACK);
+	cv_undo(el);
+	return (CC_NORM);
 }
 
 
@@ -362,7 +337,7 @@ vi_replace_mode(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_substitute_char(EditLine *el, int c)
+vi_substitute_char(EditLine *el, int c __unused)
 {
 
 	c_delafter(el, el->el_state.argument);
@@ -377,9 +352,12 @@ vi_substitute_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_substitute_line(EditLine *el, int c)
+vi_substitute_line(EditLine *el, int c __unused)
 {
 
+	cv_undo(el);
+	cv_yank(el, el->el_line.buffer,
+		    el->el_line.lastchar - el->el_line.buffer);
 	(void) em_kill_line(el, 0);
 	el->el_map.current = el->el_map.key;
 	return (CC_REFRESH);
@@ -392,9 +370,12 @@ vi_substitute_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_change_to_eol(EditLine *el, int c)
+vi_change_to_eol(EditLine *el, int c __unused)
 {
 
+	cv_undo(el);
+	cv_yank(el, el->el_line.cursor,
+		    el->el_line.lastchar - el->el_line.cursor);
 	(void) ed_kill_line(el, 0);
 	el->el_map.current = el->el_map.key;
 	return (CC_REFRESH);
@@ -407,15 +388,11 @@ vi_change_to_eol(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_insert(EditLine *el, int c)
+vi_insert(EditLine *el, int c __unused)
 {
 
 	el->el_map.current = el->el_map.key;
-
-	el->el_chared.c_vcmd.ins = el->el_line.cursor;
-	el->el_chared.c_undo.ptr = el->el_line.cursor;
-	el->el_chared.c_undo.action = DELETE;
-
+	cv_undo(el);
 	return (CC_NORM);
 }
 
@@ -426,9 +403,9 @@ vi_insert(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_add(EditLine *el, int c)
+vi_add(EditLine *el, int c __unused)
 {
-	el_action_t ret;
+	int ret;
 
 	el->el_map.current = el->el_map.key;
 	if (el->el_line.cursor < el->el_line.lastchar) {
@@ -439,9 +416,7 @@ vi_add(EditLine *el, int c)
 	} else
 		ret = CC_NORM;
 
-	el->el_chared.c_vcmd.ins = el->el_line.cursor;
-	el->el_chared.c_undo.ptr = el->el_line.cursor;
-	el->el_chared.c_undo.action = DELETE;
+	cv_undo(el);
 
 	return (ret);
 }
@@ -453,16 +428,12 @@ vi_add(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_add_at_eol(EditLine *el, int c)
+vi_add_at_eol(EditLine *el, int c __unused)
 {
 
 	el->el_map.current = el->el_map.key;
 	el->el_line.cursor = el->el_line.lastchar;
-
-	/* Mark where insertion begins */
-	el->el_chared.c_vcmd.ins = el->el_line.lastchar;
-	el->el_chared.c_undo.ptr = el->el_line.lastchar;
-	el->el_chared.c_undo.action = DELETE;
+	cv_undo(el);
 	return (CC_CURSOR);
 }
 
@@ -473,29 +444,29 @@ vi_add_at_eol(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_delete_meta(EditLine *el, int c)
+vi_delete_meta(EditLine *el, int c __unused)
 {
 
 	return (cv_action(el, DELETE));
 }
 
 
-/* vi_end_word():
+/* vi_end_big_word():
  *	Vi move to the end of the current space delimited word
  *	[E]
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_end_word(EditLine *el, int c)
+vi_end_big_word(EditLine *el, int c)
 {
 
 	if (el->el_line.cursor == el->el_line.lastchar)
 		return (CC_ERROR);
 
 	el->el_line.cursor = cv__endword(el->el_line.cursor,
-	    el->el_line.lastchar, el->el_state.argument);
+	    el->el_line.lastchar, el->el_state.argument, cv__isWord);
 
-	if (el->el_chared.c_vcmd.action & DELETE) {
+	if (el->el_chared.c_vcmd.action != NOP) {
 		el->el_line.cursor++;
 		cv_delfini(el);
 		return (CC_REFRESH);
@@ -504,22 +475,22 @@ vi_end_word(EditLine *el, int c)
 }
 
 
-/* vi_to_end_word():
+/* vi_end_word():
  *	Vi move to the end of the current word
  *	[e]
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_to_end_word(EditLine *el, int c)
+vi_end_word(EditLine *el, int c __unused)
 {
 
 	if (el->el_line.cursor == el->el_line.lastchar)
 		return (CC_ERROR);
 
 	el->el_line.cursor = cv__endword(el->el_line.cursor,
-	    el->el_line.lastchar, el->el_state.argument);
+	    el->el_line.lastchar, el->el_state.argument, cv__isword);
 
-	if (el->el_chared.c_vcmd.action & DELETE) {
+	if (el->el_chared.c_vcmd.action != NOP) {
 		el->el_line.cursor++;
 		cv_delfini(el);
 		return (CC_REFRESH);
@@ -534,144 +505,40 @@ vi_to_end_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_undo(EditLine *el, int c)
+vi_undo(EditLine *el, int c __unused)
 {
-	char *cp, *kp;
-	char temp;
-	int i, size;
-	c_undo_t *un = &el->el_chared.c_undo;
+	c_undo_t un = el->el_chared.c_undo;
 
-#ifdef DEBUG_UNDO
-	(void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
-	    un->action, un->buf, un->isize, un->dsize);
-#endif
-	switch (un->action) {
-	case DELETE:
-		if (un->dsize == 0)
-			return (CC_NORM);
+	if (un.len == -1)
+		return CC_ERROR;
 
-		(void) memcpy(un->buf, un->ptr, un->dsize);
-		for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
-			*cp = cp[un->dsize];
-
-		el->el_line.lastchar -= un->dsize;
-		el->el_line.cursor = un->ptr;
-
-		un->action = INSERT;
-		un->isize = un->dsize;
-		un->dsize = 0;
-		break;
-
-	case DELETE | INSERT:
-		size = un->isize - un->dsize;
-		if (size > 0)
-			i = un->dsize;
-		else
-			i = un->isize;
-		cp = un->ptr;
-		kp = un->buf;
-		while (i-- > 0) {
-			temp = *kp;
-			*kp++ = *cp;
-			*cp++ = temp;
-		}
-		if (size > 0) {
-			el->el_line.cursor = cp;
-			c_insert(el, size);
-			while (size-- > 0 && cp < el->el_line.lastchar) {
-				temp = *kp;
-				*kp++ = *cp;
-				*cp++ = temp;
-			}
-		} else if (size < 0) {
-			size = -size;
-			for (; cp <= el->el_line.lastchar; cp++) {
-				*kp++ = *cp;
-				*cp = cp[size];
-			}
-			el->el_line.lastchar -= size;
-		}
-		el->el_line.cursor = un->ptr;
-		i = un->dsize;
-		un->dsize = un->isize;
-		un->isize = i;
-		break;
-
-	case INSERT:
-		if (un->isize == 0)
-			return (CC_NORM);
-
-		el->el_line.cursor = un->ptr;
-		c_insert(el, (int) un->isize);
-		(void) memcpy(un->ptr, un->buf, un->isize);
-		un->action = DELETE;
-		un->dsize = un->isize;
-		un->isize = 0;
-		break;
-
-	case CHANGE:
-		if (un->isize == 0)
-			return (CC_NORM);
-
-		el->el_line.cursor = un->ptr;
-		size = (int) (el->el_line.cursor - el->el_line.lastchar);
-		if (size < un->isize)
-			size = un->isize;
-		cp = un->ptr;
-		kp = un->buf;
-		for (i = 0; i < size; i++) {
-			temp = *kp;
-			*kp++ = *cp;
-			*cp++ = temp;
-		}
-		un->dsize = 0;
-		break;
-
-	default:
-		return (CC_ERROR);
-	}
+	/* switch line buffer and undo buffer */
+	el->el_chared.c_undo.buf = el->el_line.buffer;
+	el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
+	el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer;
+	el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
+	el->el_line.buffer = un.buf;
+	el->el_line.cursor = un.buf + un.cursor;
+	el->el_line.lastchar = un.buf + un.len;
 
 	return (CC_REFRESH);
 }
 
 
-/* vi_undo_line():
- *	Vi undo all changes
- *	[U]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_undo_line(EditLine *el, int c)
-{
-
-	return hist_get(el);
-}
-
-
 /* vi_command_mode():
  *	Vi enter command mode (use alternative key bindings)
  *	[<ESC>]
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_command_mode(EditLine *el, int c)
+vi_command_mode(EditLine *el, int c __unused)
 {
-	int size;
 
 	/* [Esc] cancels pending action */
-	el->el_chared.c_vcmd.ins = 0;
 	el->el_chared.c_vcmd.action = NOP;
 	el->el_chared.c_vcmd.pos = 0;
 
 	el->el_state.doingarg = 0;
-	size = el->el_chared.c_undo.ptr - el->el_line.cursor;
-	if (size < 0)
-		size = -size;
-	if (el->el_chared.c_undo.action == (INSERT | DELETE) ||
-	    el->el_chared.c_undo.action == DELETE)
-		el->el_chared.c_undo.dsize = size;
-	else
-		el->el_chared.c_undo.isize = size;
 
 	el->el_state.inputmode = MODE_INSERT;
 	el->el_map.current = el->el_map.alt;
@@ -691,42 +558,32 @@ protected el_action_t
 vi_zero(EditLine *el, int c)
 {
 
-	if (el->el_state.doingarg) {
-		if (el->el_state.argument > 1000000)
-			return (CC_ERROR);
-		el->el_state.argument =
-		    (el->el_state.argument * 10) + (c - '0');
-		return (CC_ARGHACK);
-	} else {
-		el->el_line.cursor = el->el_line.buffer;
-		if (el->el_chared.c_vcmd.action & DELETE) {
-			cv_delfini(el);
-			return (CC_REFRESH);
-		}
-		return (CC_CURSOR);
+	if (el->el_state.doingarg)
+		return ed_argument_digit(el, c);
+
+	el->el_line.cursor = el->el_line.buffer;
+	if (el->el_chared.c_vcmd.action != NOP) {
+		cv_delfini(el);
+		return (CC_REFRESH);
 	}
+	return (CC_CURSOR);
 }
 
 
 /* vi_delete_prev_char():
  * 	Vi move to previous character (backspace)
- *	[^H]
+ *	[^H] in insert mode only
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_delete_prev_char(EditLine *el, int c)
+vi_delete_prev_char(EditLine *el, int c __unused)
 {
 
-	if (el->el_chared.c_vcmd.ins == 0)
+	if (el->el_line.cursor <= el->el_line.buffer)
 		return (CC_ERROR);
 
-	if (el->el_chared.c_vcmd.ins >
-	    el->el_line.cursor - el->el_state.argument)
-		return (CC_ERROR);
-
-	c_delbefore(el, el->el_state.argument);
-	el->el_line.cursor -= el->el_state.argument;
-
+	c_delbefore1(el);
+	el->el_line.cursor--;
 	return (CC_REFRESH);
 }
 
@@ -737,23 +594,35 @@ vi_delete_prev_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_list_or_eof(EditLine *el, int c)
+vi_list_or_eof(EditLine *el, int c __unused)
 {
 
-#ifdef notyet
-	if (el->el_line.cursor == el->el_line.lastchar &&
-	    el->el_line.cursor == el->el_line.buffer) {
-#endif
-		term_overwrite(el, STReof, 4);	/* then do an EOF */
-		term__flush();
-		return (CC_EOF);
-#ifdef notyet
+	if (el->el_line.cursor == el->el_line.lastchar) {
+		if (el->el_line.cursor == el->el_line.buffer) {
+			term_overwrite(el, STReof, 4);	/* then do a EOF */
+			term__flush();
+			return (CC_EOF);
+		} else {
+			/*
+			 * Here we could list completions, but it is an
+			 * error right now
+			 */
+			term_beep(el);
+			return (CC_ERROR);
+		}
 	} else {
+#ifdef notyet
 		re_goto_bottom(el);
 		*el->el_line.lastchar = '\0';	/* just in case */
 		return (CC_LIST_CHOICES);
-	}
+#else
+		/*
+		 * Just complain for now.
+		 */
+		term_beep(el);
+		return (CC_ERROR);
 #endif
+	}
 }
 
 
@@ -763,7 +632,7 @@ vi_list_or_eof(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_kill_line_prev(EditLine *el, int c)
+vi_kill_line_prev(EditLine *el, int c __unused)
 {
 	char *kp, *cp;
 
@@ -784,7 +653,7 @@ vi_kill_line_prev(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_search_prev(EditLine *el, int c)
+vi_search_prev(EditLine *el, int c __unused)
 {
 
 	return (cv_search(el, ED_SEARCH_PREV_HISTORY));
@@ -797,7 +666,7 @@ vi_search_prev(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_search_next(EditLine *el, int c)
+vi_search_next(EditLine *el, int c __unused)
 {
 
 	return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
@@ -810,7 +679,7 @@ vi_search_next(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_repeat_search_next(EditLine *el, int c)
+vi_repeat_search_next(EditLine *el, int c __unused)
 {
 
 	if (el->el_search.patlen == 0)
@@ -826,7 +695,7 @@ vi_repeat_search_next(EditLine *el, int c)
  */
 /*ARGSUSED*/
 protected el_action_t
-vi_repeat_search_prev(EditLine *el, int c)
+vi_repeat_search_prev(EditLine *el, int c __unused)
 {
 
 	if (el->el_search.patlen == 0)
@@ -844,18 +713,9 @@ vi_repeat_search_prev(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_next_char(EditLine *el, int c)
+vi_next_char(EditLine *el, int c __unused)
 {
-	char ch;
-
-	if (el_getc(el, &ch) != 1)
-		return (ed_end_of_file(el, 0));
-
-	el->el_search.chadir = CHAR_FWD;
-	el->el_search.chacha = ch;
-
-	return (cv_csearch_fwd(el, ch, el->el_state.argument, 0));
-
+	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
 }
 
 
@@ -865,17 +725,9 @@ vi_next_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_prev_char(EditLine *el, int c)
+vi_prev_char(EditLine *el, int c __unused)
 {
-	char ch;
-
-	if (el_getc(el, &ch) != 1)
-		return (ed_end_of_file(el, 0));
-
-	el->el_search.chadir = CHAR_BACK;
-	el->el_search.chacha = ch;
-
-	return (cv_csearch_back(el, ch, el->el_state.argument, 0));
+	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
 }
 
 
@@ -885,15 +737,9 @@ vi_prev_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_to_next_char(EditLine *el, int c)
+vi_to_next_char(EditLine *el, int c __unused)
 {
-	char ch;
-
-	if (el_getc(el, &ch) != 1)
-		return (ed_end_of_file(el, 0));
-
-	return (cv_csearch_fwd(el, ch, el->el_state.argument, 1));
-
+	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
 }
 
 
@@ -903,14 +749,9 @@ vi_to_next_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_to_prev_char(EditLine *el, int c)
+vi_to_prev_char(EditLine *el, int c __unused)
 {
-	char ch;
-
-	if (el_getc(el, &ch) != 1)
-		return (ed_end_of_file(el, 0));
-
-	return (cv_csearch_back(el, ch, el->el_state.argument, 1));
+	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
 }
 
 
@@ -920,17 +761,11 @@ vi_to_prev_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_repeat_next_char(EditLine *el, int c)
+vi_repeat_next_char(EditLine *el, int c __unused)
 {
 
-	if (el->el_search.chacha == 0)
-		return (CC_ERROR);
-
-	return (el->el_search.chadir == CHAR_FWD
-	    ? cv_csearch_fwd(el, el->el_search.chacha,
-		el->el_state.argument, 0)
-	    : cv_csearch_back(el, el->el_search.chacha,
-		el->el_state.argument, 0));
+	return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
+		el->el_state.argument, el->el_search.chatflg);
 }
 
 
@@ -940,13 +775,345 @@ vi_repeat_next_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-vi_repeat_prev_char(EditLine *el, int c)
+vi_repeat_prev_char(EditLine *el, int c __unused)
+{
+	el_action_t r;
+	int dir = el->el_search.chadir;
+
+	r = cv_csearch(el, -dir, el->el_search.chacha,
+		el->el_state.argument, el->el_search.chatflg);
+	el->el_search.chadir = dir;
+	return r;
+}
+
+
+/* vi_match():
+ *	Vi go to matching () {} or []
+ *	[%]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_match(EditLine *el, int c)
+{
+	const char match_chars[] = "()[]{}";
+	char *cp;
+	int delta, i, count;
+	char o_ch, c_ch;
+
+	*el->el_line.lastchar = '\0';		/* just in case */
+
+	i = strcspn(el->el_line.cursor, match_chars);
+	o_ch = el->el_line.cursor[i];
+	if (o_ch == 0)
+		return CC_ERROR;
+	delta = strchr(match_chars, o_ch) - match_chars;
+	c_ch = match_chars[delta ^ 1];
+	count = 1;
+	delta = 1 - (delta & 1) * 2;
+
+	for (cp = &el->el_line.cursor[i]; count; ) {
+		cp += delta;
+		if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
+			return CC_ERROR;
+		if (*cp == o_ch)
+			count++;
+		else if (*cp == c_ch)
+			count--;
+	}
+
+	el->el_line.cursor = cp;
+
+	if (el->el_chared.c_vcmd.action != NOP) {
+		/* NB posix says char under cursor should NOT be deleted
+		   for -ve delta - this is different to netbsd vi. */
+		if (delta > 0)
+			el->el_line.cursor++;
+		cv_delfini(el);
+		return (CC_REFRESH);
+	}
+	return (CC_CURSOR);
+}
+
+/* vi_undo_line():
+ *	Vi undo all changes to line
+ *	[U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_undo_line(EditLine *el, int c)
 {
 
-	if (el->el_search.chacha == 0)
-		return (CC_ERROR);
-
-	return el->el_search.chadir == CHAR_BACK ?
-	    cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
-	    cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
+	cv_undo(el);
+	return hist_get(el);
+}
+
+/* vi_to_column():
+ *	Vi go to specified column
+ *	[|]
+ * NB netbsd vi goes to screen column 'n', posix says nth character
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_column(EditLine *el, int c)
+{
+
+	el->el_line.cursor = el->el_line.buffer;
+	el->el_state.argument--;
+	return ed_next_char(el, 0);
+}
+
+/* vi_yank_end():
+ *	Vi yank to end of line
+ *	[Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_yank_end(EditLine *el, int c)
+{
+
+	cv_yank(el, el->el_line.cursor,
+		el->el_line.lastchar - el->el_line.cursor);
+	return CC_REFRESH;
+}
+
+/* vi_yank():
+ *	Vi yank
+ *	[y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_yank(EditLine *el, int c)
+{
+
+	return cv_action(el, YANK);
+}
+
+/* vi_comment_out():
+ *	Vi comment out current command
+ *	[c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_comment_out(EditLine *el, int c)
+{
+
+	el->el_line.cursor = el->el_line.buffer;
+	c_insert(el, 1);
+	*el->el_line.cursor = '#';
+	re_refresh(el);
+	return ed_newline(el, 0);
+}
+
+/* vi_alias():
+ *	Vi include shell alias
+ *	[@]
+ * NB: posix impiles that we should enter insert mode, however
+ * this is against historical precedent...
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_alias(EditLine *el, int c)
+{
+#ifdef __weak_extern
+	char alias_name[3];
+	char *alias_text;
+	extern char *get_alias_text(const char *);
+	__weak_extern(get_alias_text);
+
+	if (get_alias_text == 0) {
+		return CC_ERROR;
+	}
+
+	alias_name[0] = '_';
+	alias_name[2] = 0;
+	if (el_getc(el, &alias_name[1]) != 1)
+		return CC_ERROR;
+
+	alias_text = get_alias_text(alias_name);
+	if (alias_text != NULL)
+		el_push(el, alias_text);
+	return CC_NORM;
+#else
+	return CC_ERROR;
+#endif
+}
+
+/* vi_to_history_line():
+ *	Vi go to specified history file line.
+ *	[G]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_history_line(EditLine *el, int c)
+{
+	int sv_event_no = el->el_history.eventno;
+	el_action_t rval;
+
+
+	if (el->el_history.eventno == 0) {
+		 (void) strncpy(el->el_history.buf, el->el_line.buffer,
+		     EL_BUFSIZ);
+		 el->el_history.last = el->el_history.buf +
+			 (el->el_line.lastchar - el->el_line.buffer);
+	}
+
+	/* Lack of a 'count' means oldest, not 1 */
+	if (!el->el_state.doingarg) {
+		el->el_history.eventno = 0x7fffffff;
+		hist_get(el);
+	} else {
+		/* This is brain dead, all the rest of this code counts
+		 * upwards going into the past.  Here we need count in the
+		 * other direction (to match the output of fc -l).
+		 * I could change the world, but this seems to suffice.
+		 */
+		el->el_history.eventno = 1;
+		if (hist_get(el) == CC_ERROR)
+			return CC_ERROR;
+		el->el_history.eventno = 1 + el->el_history.ev.num 
+					- el->el_state.argument;
+		if (el->el_history.eventno < 0) {
+			el->el_history.eventno = sv_event_no;
+			return CC_ERROR;
+		}
+	}
+	rval = hist_get(el);
+	if (rval == CC_ERROR)
+		el->el_history.eventno = sv_event_no;
+	return rval;
+}
+
+/* vi_histedit():
+ *	Vi edit history line with vi
+ *	[v]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_histedit(EditLine *el, int c)
+{
+	int fd;
+	pid_t pid;
+	int st;
+	char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
+	char *cp;
+
+	if (el->el_state.doingarg) {
+		if (vi_to_history_line(el, 0) == CC_ERROR)
+			return CC_ERROR;
+	}
+
+	fd = mkstemp(tempfile);
+	if (fd < 0)
+		return CC_ERROR;
+	cp = el->el_line.buffer;
+	write(fd, cp, el->el_line.lastchar - cp +0u);
+	write(fd, "\n", 1);
+	pid = fork();
+	switch (pid) {
+	case -1:
+		close(fd);
+		unlink(tempfile);
+		return CC_ERROR;
+	case 0:
+		close(fd);
+		execlp("vi", "vi", tempfile, NULL);
+		exit(0);
+		/*NOTREACHED*/
+	default:
+		while (waitpid(pid, &st, 0) != pid)
+			continue;
+		lseek(fd, 0ll, SEEK_SET);
+		st = read(fd, cp, el->el_line.limit - cp +0u);
+		if (st > 0 && cp[st - 1] == '\n')
+			st--;
+		el->el_line.cursor = cp;
+		el->el_line.lastchar = cp + st;
+		break;
+	}
+
+	close(fd);
+	unlink(tempfile);
+	/* return CC_REFRESH; */
+	return ed_newline(el, 0);
+}
+
+/* vi_history_word():
+ *	Vi append word from previous input line
+ *	[_]
+ * Who knows where this one came from!
+ * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_history_word(EditLine *el, int c)
+{
+	const char *wp = HIST_FIRST(el);
+	const char *wep, *wsp;
+	int len;
+	char *cp;
+	const char *lim;
+
+	if (wp == NULL)
+		return CC_ERROR;
+
+	wep = wsp = 0;
+	do {
+		while (isspace((unsigned char)*wp))
+			wp++;
+		if (*wp == 0)
+			break;
+		wsp = wp;
+		while (*wp && !isspace((unsigned char)*wp))
+			wp++;
+		wep = wp;
+	} while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0);
+
+	if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
+		return CC_ERROR;
+
+	cv_undo(el);
+	len = wep - wsp;
+	if (el->el_line.cursor < el->el_line.lastchar)
+		el->el_line.cursor++;
+	c_insert(el, len + 1);
+	cp = el->el_line.cursor;
+	lim = el->el_line.limit;
+	if (cp < lim)
+		*cp++ = ' ';
+	while (wsp < wep && cp < lim)
+		*cp++ = *wsp++;
+	el->el_line.cursor = cp;
+
+	el->el_map.current = el->el_map.key;
+	return CC_REFRESH;
+}
+
+/* vi_redo():
+ *	Vi redo last non-motion command
+ *	[.]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_redo(EditLine *el, int c)
+{
+	c_redo_t *r = &el->el_chared.c_redo;
+
+	if (!el->el_state.doingarg && r->count) {
+		el->el_state.doingarg = 1;
+		el->el_state.argument = r->count;
+	}
+
+	el->el_chared.c_vcmd.pos = el->el_line.cursor;
+	el->el_chared.c_vcmd.action = r->action;
+	if (r->pos != r->buf) {
+		if (r->pos + 1 > r->lim)
+			/* sanity */
+			r->pos = r->lim - 1;
+		r->pos[0] = 0;
+		el_push(el, r->buf);
+	}
+
+	el->el_state.thiscmd = r->cmd;
+	el->el_state.thisch = r->ch;
+	return  (*el->el_map.func[r->cmd])(el, r->ch);
 }