summary refs log tree commit diff
path: root/bin/cash/libedit/tty.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-01-11 17:38:59 -0500
committerJune McEnroe <june@causal.agency>2019-01-11 17:38:59 -0500
commite795c2ea0dfc6b17ac1217785319088d6f50f39c (patch)
treecc58a084a78f5f0952eba60c52b7c5b564964099 /bin/cash/libedit/tty.c
parentAdd PSlit for prompt escapes (diff)
downloadsrc-e795c2ea0dfc6b17ac1217785319088d6f50f39c.tar.gz
src-e795c2ea0dfc6b17ac1217785319088d6f50f39c.zip
Import /usr/src/lib/libedit from NetBSD 8.0
Diffstat (limited to 'bin/cash/libedit/tty.c')
-rw-r--r--bin/cash/libedit/tty.c1342
1 files changed, 1342 insertions, 0 deletions
diff --git a/bin/cash/libedit/tty.c b/bin/cash/libedit/tty.c
new file mode 100644
index 00000000..f524da47
--- /dev/null
+++ b/bin/cash/libedit/tty.c
@@ -0,0 +1,1342 @@
+/*	$NetBSD: tty.c,v 1.65 2016/05/09 21:46:56 christos Exp $	*/
+
+/*-
+ * 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. 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.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)tty.c	8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: tty.c,v 1.65 2016/05/09 21:46:56 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * tty.c: tty interface stuff
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>	/* for abort */
+#include <string.h>
+#include <strings.h>	/* for ffs */
+#include <unistd.h>	/* for isatty */
+
+#include "el.h"
+#include "fcns.h"
+#include "parse.h"
+
+typedef struct ttymodes_t {
+	const char *m_name;
+	unsigned int m_value;
+	int m_type;
+}          ttymodes_t;
+
+typedef struct ttymap_t {
+	wint_t nch, och;	/* Internal and termio rep of chars */
+	el_action_t bind[3];	/* emacs, vi, and vi-cmd */
+} ttymap_t;
+
+
+static const ttyperm_t ttyperm = {
+	{
+		{"iflag:", ICRNL, (INLCR | IGNCR)},
+		{"oflag:", (OPOST | ONLCR), ONLRET},
+		{"cflag:", 0, 0},
+		{"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
+		(NOFLSH | ECHONL | EXTPROC | FLUSHO)},
+		{"chars:", 0, 0},
+	},
+	{
+		{"iflag:", (INLCR | ICRNL), IGNCR},
+		{"oflag:", (OPOST | ONLCR), ONLRET},
+		{"cflag:", 0, 0},
+		{"lflag:", ISIG,
+		(NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
+		{"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
+			    C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
+		    C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
+	},
+	{
+		{"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
+		{"oflag:", 0, 0},
+		{"cflag:", 0, 0},
+		{"lflag:", 0, ISIG | IEXTEN},
+		{"chars:", 0, 0},
+	}
+};
+
+static const ttychar_t ttychar = {
+	{
+		CINTR, CQUIT, CERASE, CKILL,
+		CEOF, CEOL, CEOL2, CSWTCH,
+		CDSWTCH, CERASE2, CSTART, CSTOP,
+		CWERASE, CSUSP, CDSUSP, CREPRINT,
+		CDISCARD, CLNEXT, CSTATUS, CPAGE,
+		CPGOFF, CKILL2, CBRK, CMIN,
+		CTIME
+	},
+	{
+		CINTR, CQUIT, CERASE, CKILL,
+		_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+		_POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
+		_POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
+		CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+		_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
+		0
+	},
+	{
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		0
+	}
+};
+
+static const ttymap_t tty_map[] = {
+#ifdef VERASE
+	{C_ERASE, VERASE,
+	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+#endif /* VERASE */
+#ifdef VERASE2
+	{C_ERASE2, VERASE2,
+	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+#endif /* VERASE2 */
+#ifdef VKILL
+	{C_KILL, VKILL,
+	{EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
+#endif /* VKILL */
+#ifdef VKILL2
+	{C_KILL2, VKILL2,
+	{EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
+#endif /* VKILL2 */
+#ifdef VEOF
+	{C_EOF, VEOF,
+	{EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
+#endif /* VEOF */
+#ifdef VWERASE
+	{C_WERASE, VWERASE,
+	{ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
+#endif /* VWERASE */
+#ifdef VREPRINT
+	{C_REPRINT, VREPRINT,
+	{ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
+#endif /* VREPRINT */
+#ifdef VLNEXT
+	{C_LNEXT, VLNEXT,
+	{ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
+#endif /* VLNEXT */
+	{(wint_t)-1, (wint_t)-1,
+	{ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
+};
+
+static const ttymodes_t ttymodes[] = {
+#ifdef	IGNBRK
+	{"ignbrk", IGNBRK, MD_INP},
+#endif /* IGNBRK */
+#ifdef	BRKINT
+	{"brkint", BRKINT, MD_INP},
+#endif /* BRKINT */
+#ifdef	IGNPAR
+	{"ignpar", IGNPAR, MD_INP},
+#endif /* IGNPAR */
+#ifdef	PARMRK
+	{"parmrk", PARMRK, MD_INP},
+#endif /* PARMRK */
+#ifdef	INPCK
+	{"inpck", INPCK, MD_INP},
+#endif /* INPCK */
+#ifdef	ISTRIP
+	{"istrip", ISTRIP, MD_INP},
+#endif /* ISTRIP */
+#ifdef	INLCR
+	{"inlcr", INLCR, MD_INP},
+#endif /* INLCR */
+#ifdef	IGNCR
+	{"igncr", IGNCR, MD_INP},
+#endif /* IGNCR */
+#ifdef	ICRNL
+	{"icrnl", ICRNL, MD_INP},
+#endif /* ICRNL */
+#ifdef	IUCLC
+	{"iuclc", IUCLC, MD_INP},
+#endif /* IUCLC */
+#ifdef	IXON
+	{"ixon", IXON, MD_INP},
+#endif /* IXON */
+#ifdef	IXANY
+	{"ixany", IXANY, MD_INP},
+#endif /* IXANY */
+#ifdef	IXOFF
+	{"ixoff", IXOFF, MD_INP},
+#endif /* IXOFF */
+#ifdef  IMAXBEL
+	{"imaxbel", IMAXBEL, MD_INP},
+#endif /* IMAXBEL */
+
+#ifdef	OPOST
+	{"opost", OPOST, MD_OUT},
+#endif /* OPOST */
+#ifdef	OLCUC
+	{"olcuc", OLCUC, MD_OUT},
+#endif /* OLCUC */
+#ifdef	ONLCR
+	{"onlcr", ONLCR, MD_OUT},
+#endif /* ONLCR */
+#ifdef	OCRNL
+	{"ocrnl", OCRNL, MD_OUT},
+#endif /* OCRNL */
+#ifdef	ONOCR
+	{"onocr", ONOCR, MD_OUT},
+#endif /* ONOCR */
+#ifdef ONOEOT
+	{"onoeot", ONOEOT, MD_OUT},
+#endif /* ONOEOT */
+#ifdef	ONLRET
+	{"onlret", ONLRET, MD_OUT},
+#endif /* ONLRET */
+#ifdef	OFILL
+	{"ofill", OFILL, MD_OUT},
+#endif /* OFILL */
+#ifdef	OFDEL
+	{"ofdel", OFDEL, MD_OUT},
+#endif /* OFDEL */
+#ifdef	NLDLY
+	{"nldly", NLDLY, MD_OUT},
+#endif /* NLDLY */
+#ifdef	CRDLY
+	{"crdly", CRDLY, MD_OUT},
+#endif /* CRDLY */
+#ifdef	TABDLY
+	{"tabdly", TABDLY, MD_OUT},
+#endif /* TABDLY */
+#ifdef	XTABS
+	{"xtabs", XTABS, MD_OUT},
+#endif /* XTABS */
+#ifdef	BSDLY
+	{"bsdly", BSDLY, MD_OUT},
+#endif /* BSDLY */
+#ifdef	VTDLY
+	{"vtdly", VTDLY, MD_OUT},
+#endif /* VTDLY */
+#ifdef	FFDLY
+	{"ffdly", FFDLY, MD_OUT},
+#endif /* FFDLY */
+#ifdef	PAGEOUT
+	{"pageout", PAGEOUT, MD_OUT},
+#endif /* PAGEOUT */
+#ifdef	WRAP
+	{"wrap", WRAP, MD_OUT},
+#endif /* WRAP */
+
+#ifdef	CIGNORE
+	{"cignore", CIGNORE, MD_CTL},
+#endif /* CBAUD */
+#ifdef	CBAUD
+	{"cbaud", CBAUD, MD_CTL},
+#endif /* CBAUD */
+#ifdef	CSTOPB
+	{"cstopb", CSTOPB, MD_CTL},
+#endif /* CSTOPB */
+#ifdef	CREAD
+	{"cread", CREAD, MD_CTL},
+#endif /* CREAD */
+#ifdef	PARENB
+	{"parenb", PARENB, MD_CTL},
+#endif /* PARENB */
+#ifdef	PARODD
+	{"parodd", PARODD, MD_CTL},
+#endif /* PARODD */
+#ifdef	HUPCL
+	{"hupcl", HUPCL, MD_CTL},
+#endif /* HUPCL */
+#ifdef	CLOCAL
+	{"clocal", CLOCAL, MD_CTL},
+#endif /* CLOCAL */
+#ifdef	LOBLK
+	{"loblk", LOBLK, MD_CTL},
+#endif /* LOBLK */
+#ifdef	CIBAUD
+	{"cibaud", CIBAUD, MD_CTL},
+#endif /* CIBAUD */
+#ifdef CRTSCTS
+#ifdef CCTS_OFLOW
+	{"ccts_oflow", CCTS_OFLOW, MD_CTL},
+#else
+	{"crtscts", CRTSCTS, MD_CTL},
+#endif /* CCTS_OFLOW */
+#endif /* CRTSCTS */
+#ifdef CRTS_IFLOW
+	{"crts_iflow", CRTS_IFLOW, MD_CTL},
+#endif /* CRTS_IFLOW */
+#ifdef CDTRCTS
+	{"cdtrcts", CDTRCTS, MD_CTL},
+#endif /* CDTRCTS */
+#ifdef MDMBUF
+	{"mdmbuf", MDMBUF, MD_CTL},
+#endif /* MDMBUF */
+#ifdef RCV1EN
+	{"rcv1en", RCV1EN, MD_CTL},
+#endif /* RCV1EN */
+#ifdef XMT1EN
+	{"xmt1en", XMT1EN, MD_CTL},
+#endif /* XMT1EN */
+
+#ifdef	ISIG
+	{"isig", ISIG, MD_LIN},
+#endif /* ISIG */
+#ifdef	ICANON
+	{"icanon", ICANON, MD_LIN},
+#endif /* ICANON */
+#ifdef	XCASE
+	{"xcase", XCASE, MD_LIN},
+#endif /* XCASE */
+#ifdef	ECHO
+	{"echo", ECHO, MD_LIN},
+#endif /* ECHO */
+#ifdef	ECHOE
+	{"echoe", ECHOE, MD_LIN},
+#endif /* ECHOE */
+#ifdef	ECHOK
+	{"echok", ECHOK, MD_LIN},
+#endif /* ECHOK */
+#ifdef	ECHONL
+	{"echonl", ECHONL, MD_LIN},
+#endif /* ECHONL */
+#ifdef	NOFLSH
+	{"noflsh", NOFLSH, MD_LIN},
+#endif /* NOFLSH */
+#ifdef	TOSTOP
+	{"tostop", TOSTOP, MD_LIN},
+#endif /* TOSTOP */
+#ifdef	ECHOCTL
+	{"echoctl", ECHOCTL, MD_LIN},
+#endif /* ECHOCTL */
+#ifdef	ECHOPRT
+	{"echoprt", ECHOPRT, MD_LIN},
+#endif /* ECHOPRT */
+#ifdef	ECHOKE
+	{"echoke", ECHOKE, MD_LIN},
+#endif /* ECHOKE */
+#ifdef	DEFECHO
+	{"defecho", DEFECHO, MD_LIN},
+#endif /* DEFECHO */
+#ifdef	FLUSHO
+	{"flusho", FLUSHO, MD_LIN},
+#endif /* FLUSHO */
+#ifdef	PENDIN
+	{"pendin", PENDIN, MD_LIN},
+#endif /* PENDIN */
+#ifdef	IEXTEN
+	{"iexten", IEXTEN, MD_LIN},
+#endif /* IEXTEN */
+#ifdef	NOKERNINFO
+	{"nokerninfo", NOKERNINFO, MD_LIN},
+#endif /* NOKERNINFO */
+#ifdef	ALTWERASE
+	{"altwerase", ALTWERASE, MD_LIN},
+#endif /* ALTWERASE */
+#ifdef	EXTPROC
+	{"extproc", EXTPROC, MD_LIN},
+#endif /* EXTPROC */
+
+#if defined(VINTR)
+	{"intr", C_SH(C_INTR), MD_CHAR},
+#endif /* VINTR */
+#if defined(VQUIT)
+	{"quit", C_SH(C_QUIT), MD_CHAR},
+#endif /* VQUIT */
+#if defined(VERASE)
+	{"erase", C_SH(C_ERASE), MD_CHAR},
+#endif /* VERASE */
+#if defined(VKILL)
+	{"kill", C_SH(C_KILL), MD_CHAR},
+#endif /* VKILL */
+#if defined(VEOF)
+	{"eof", C_SH(C_EOF), MD_CHAR},
+#endif /* VEOF */
+#if defined(VEOL)
+	{"eol", C_SH(C_EOL), MD_CHAR},
+#endif /* VEOL */
+#if defined(VEOL2)
+	{"eol2", C_SH(C_EOL2), MD_CHAR},
+#endif /* VEOL2 */
+#if defined(VSWTCH)
+	{"swtch", C_SH(C_SWTCH), MD_CHAR},
+#endif /* VSWTCH */
+#if defined(VDSWTCH)
+	{"dswtch", C_SH(C_DSWTCH), MD_CHAR},
+#endif /* VDSWTCH */
+#if defined(VERASE2)
+	{"erase2", C_SH(C_ERASE2), MD_CHAR},
+#endif /* VERASE2 */
+#if defined(VSTART)
+	{"start", C_SH(C_START), MD_CHAR},
+#endif /* VSTART */
+#if defined(VSTOP)
+	{"stop", C_SH(C_STOP), MD_CHAR},
+#endif /* VSTOP */
+#if defined(VWERASE)
+	{"werase", C_SH(C_WERASE), MD_CHAR},
+#endif /* VWERASE */
+#if defined(VSUSP)
+	{"susp", C_SH(C_SUSP), MD_CHAR},
+#endif /* VSUSP */
+#if defined(VDSUSP)
+	{"dsusp", C_SH(C_DSUSP), MD_CHAR},
+#endif /* VDSUSP */
+#if defined(VREPRINT)
+	{"reprint", C_SH(C_REPRINT), MD_CHAR},
+#endif /* VREPRINT */
+#if defined(VDISCARD)
+	{"discard", C_SH(C_DISCARD), MD_CHAR},
+#endif /* VDISCARD */
+#if defined(VLNEXT)
+	{"lnext", C_SH(C_LNEXT), MD_CHAR},
+#endif /* VLNEXT */
+#if defined(VSTATUS)
+	{"status", C_SH(C_STATUS), MD_CHAR},
+#endif /* VSTATUS */
+#if defined(VPAGE)
+	{"page", C_SH(C_PAGE), MD_CHAR},
+#endif /* VPAGE */
+#if defined(VPGOFF)
+	{"pgoff", C_SH(C_PGOFF), MD_CHAR},
+#endif /* VPGOFF */
+#if defined(VKILL2)
+	{"kill2", C_SH(C_KILL2), MD_CHAR},
+#endif /* VKILL2 */
+#if defined(VBRK)
+	{"brk", C_SH(C_BRK), MD_CHAR},
+#endif /* VBRK */
+#if defined(VMIN)
+	{"min", C_SH(C_MIN), MD_CHAR},
+#endif /* VMIN */
+#if defined(VTIME)
+	{"time", C_SH(C_TIME), MD_CHAR},
+#endif /* VTIME */
+	{NULL, 0, -1},
+};
+
+
+
+#define	tty__gettabs(td)	((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
+#define	tty__geteightbit(td)	(((td)->c_cflag & CSIZE) == CS8)
+#define	tty__cooked_mode(td)	((td)->c_lflag & ICANON)
+
+static int	tty_getty(EditLine *, struct termios *);
+static int	tty_setty(EditLine *, int, const struct termios *);
+static int	tty__getcharindex(int);
+static void	tty__getchar(struct termios *, unsigned char *);
+static void	tty__setchar(struct termios *, unsigned char *);
+static speed_t	tty__getspeed(struct termios *);
+static int	tty_setup(EditLine *);
+static void	tty_setup_flags(EditLine *, struct termios *, int);
+
+#define	t_qu	t_ts
+
+/* tty_getty():
+ *	Wrapper for tcgetattr to handle EINTR
+ */
+static int
+tty_getty(EditLine *el, struct termios *t)
+{
+	int rv;
+	while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
+		continue;
+	return rv;
+}
+
+/* tty_setty():
+ *	Wrapper for tcsetattr to handle EINTR
+ */
+static int
+tty_setty(EditLine *el, int action, const struct termios *t)
+{
+	int rv;
+	while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
+		continue;
+	return rv;
+}
+
+/* tty_setup():
+ *	Get the tty parameters and initialize the editing state
+ */
+static int
+tty_setup(EditLine *el)
+{
+	int rst = 1;
+
+	if (el->el_flags & EDIT_DISABLED)
+		return 0;
+
+	if (el->el_tty.t_initialized)
+		return -1;
+
+	if (!isatty(el->el_outfd)) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	if (tty_getty(el, &el->el_tty.t_or) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
+
+	el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
+	el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
+	el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
+
+	tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
+
+	/*
+         * Reset the tty chars to reasonable defaults
+         * If they are disabled, then enable them.
+         */
+	if (rst) {
+		if (tty__cooked_mode(&el->el_tty.t_ts)) {
+			tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+			/*
+	                 * Don't affect CMIN and CTIME for the editor mode
+	                 */
+			for (rst = 0; rst < C_NCC - 2; rst++)
+				if (el->el_tty.t_c[TS_IO][rst] !=
+				      el->el_tty.t_vdisable
+				    && el->el_tty.t_c[ED_IO][rst] !=
+				      el->el_tty.t_vdisable)
+					el->el_tty.t_c[ED_IO][rst] =
+					    el->el_tty.t_c[TS_IO][rst];
+			for (rst = 0; rst < C_NCC; rst++)
+				if (el->el_tty.t_c[TS_IO][rst] !=
+				    el->el_tty.t_vdisable)
+					el->el_tty.t_c[EX_IO][rst] =
+					    el->el_tty.t_c[TS_IO][rst];
+		}
+		tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+		if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+			(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
+			    __func__, strerror(errno));
+#endif /* DEBUG_TTY */
+			return -1;
+		}
+	}
+
+	tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
+
+	tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+	tty_bind_char(el, 1);
+	el->el_tty.t_initialized = 1;
+	return 0;
+}
+
+libedit_private int
+tty_init(EditLine *el)
+{
+
+	el->el_tty.t_mode = EX_IO;
+	el->el_tty.t_vdisable = _POSIX_VDISABLE;
+	el->el_tty.t_initialized = 0;
+	(void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
+	(void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
+	return tty_setup(el);
+}
+
+
+/* tty_end():
+ *	Restore the tty to its original settings
+ */
+libedit_private void
+/*ARGSUSED*/
+tty_end(EditLine *el)
+{
+	if (el->el_flags & EDIT_DISABLED)
+		return;
+
+	if (!el->el_tty.t_initialized)
+		return;
+
+	if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile,
+		    "%s: tty_setty: %s\n", __func__, strerror(errno));
+#endif /* DEBUG_TTY */
+	}
+}
+
+
+/* tty__getspeed():
+ *	Get the tty speed
+ */
+static speed_t
+tty__getspeed(struct termios *td)
+{
+	speed_t spd;
+
+	if ((spd = cfgetispeed(td)) == 0)
+		spd = cfgetospeed(td);
+	return spd;
+}
+
+/* tty__getspeed():
+ *	Return the index of the asked char in the c_cc array
+ */
+static 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
+ */
+static void
+tty__getchar(struct termios *td, unsigned char *s)
+{
+
+#ifdef VINTR
+	s[C_INTR] = td->c_cc[VINTR];
+#endif /* VINTR */
+#ifdef VQUIT
+	s[C_QUIT] = td->c_cc[VQUIT];
+#endif /* VQUIT */
+#ifdef VERASE
+	s[C_ERASE] = td->c_cc[VERASE];
+#endif /* VERASE */
+#ifdef VKILL
+	s[C_KILL] = td->c_cc[VKILL];
+#endif /* VKILL */
+#ifdef VEOF
+	s[C_EOF] = td->c_cc[VEOF];
+#endif /* VEOF */
+#ifdef VEOL
+	s[C_EOL] = td->c_cc[VEOL];
+#endif /* VEOL */
+#ifdef VEOL2
+	s[C_EOL2] = td->c_cc[VEOL2];
+#endif /* VEOL2 */
+#ifdef VSWTCH
+	s[C_SWTCH] = td->c_cc[VSWTCH];
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+	s[C_DSWTCH] = td->c_cc[VDSWTCH];
+#endif /* VDSWTCH */
+#ifdef VERASE2
+	s[C_ERASE2] = td->c_cc[VERASE2];
+#endif /* VERASE2 */
+#ifdef VSTART
+	s[C_START] = td->c_cc[VSTART];
+#endif /* VSTART */
+#ifdef VSTOP
+	s[C_STOP] = td->c_cc[VSTOP];
+#endif /* VSTOP */
+#ifdef VWERASE
+	s[C_WERASE] = td->c_cc[VWERASE];
+#endif /* VWERASE */
+#ifdef VSUSP
+	s[C_SUSP] = td->c_cc[VSUSP];
+#endif /* VSUSP */
+#ifdef VDSUSP
+	s[C_DSUSP] = td->c_cc[VDSUSP];
+#endif /* VDSUSP */
+#ifdef VREPRINT
+	s[C_REPRINT] = td->c_cc[VREPRINT];
+#endif /* VREPRINT */
+#ifdef VDISCARD
+	s[C_DISCARD] = td->c_cc[VDISCARD];
+#endif /* VDISCARD */
+#ifdef VLNEXT
+	s[C_LNEXT] = td->c_cc[VLNEXT];
+#endif /* VLNEXT */
+#ifdef VSTATUS
+	s[C_STATUS] = td->c_cc[VSTATUS];
+#endif /* VSTATUS */
+#ifdef VPAGE
+	s[C_PAGE] = td->c_cc[VPAGE];
+#endif /* VPAGE */
+#ifdef VPGOFF
+	s[C_PGOFF] = td->c_cc[VPGOFF];
+#endif /* VPGOFF */
+#ifdef VKILL2
+	s[C_KILL2] = td->c_cc[VKILL2];
+#endif /* KILL2 */
+#ifdef VMIN
+	s[C_MIN] = td->c_cc[VMIN];
+#endif /* VMIN */
+#ifdef VTIME
+	s[C_TIME] = td->c_cc[VTIME];
+#endif /* VTIME */
+}				/* tty__getchar */
+
+
+/* tty__setchar():
+ *	Set the tty characters
+ */
+static void
+tty__setchar(struct termios *td, unsigned char *s)
+{
+
+#ifdef VINTR
+	td->c_cc[VINTR] = s[C_INTR];
+#endif /* VINTR */
+#ifdef VQUIT
+	td->c_cc[VQUIT] = s[C_QUIT];
+#endif /* VQUIT */
+#ifdef VERASE
+	td->c_cc[VERASE] = s[C_ERASE];
+#endif /* VERASE */
+#ifdef VKILL
+	td->c_cc[VKILL] = s[C_KILL];
+#endif /* VKILL */
+#ifdef VEOF
+	td->c_cc[VEOF] = s[C_EOF];
+#endif /* VEOF */
+#ifdef VEOL
+	td->c_cc[VEOL] = s[C_EOL];
+#endif /* VEOL */
+#ifdef VEOL2
+	td->c_cc[VEOL2] = s[C_EOL2];
+#endif /* VEOL2 */
+#ifdef VSWTCH
+	td->c_cc[VSWTCH] = s[C_SWTCH];
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+	td->c_cc[VDSWTCH] = s[C_DSWTCH];
+#endif /* VDSWTCH */
+#ifdef VERASE2
+	td->c_cc[VERASE2] = s[C_ERASE2];
+#endif /* VERASE2 */
+#ifdef VSTART
+	td->c_cc[VSTART] = s[C_START];
+#endif /* VSTART */
+#ifdef VSTOP
+	td->c_cc[VSTOP] = s[C_STOP];
+#endif /* VSTOP */
+#ifdef VWERASE
+	td->c_cc[VWERASE] = s[C_WERASE];
+#endif /* VWERASE */
+#ifdef VSUSP
+	td->c_cc[VSUSP] = s[C_SUSP];
+#endif /* VSUSP */
+#ifdef VDSUSP
+	td->c_cc[VDSUSP] = s[C_DSUSP];
+#endif /* VDSUSP */
+#ifdef VREPRINT
+	td->c_cc[VREPRINT] = s[C_REPRINT];
+#endif /* VREPRINT */
+#ifdef VDISCARD
+	td->c_cc[VDISCARD] = s[C_DISCARD];
+#endif /* VDISCARD */
+#ifdef VLNEXT
+	td->c_cc[VLNEXT] = s[C_LNEXT];
+#endif /* VLNEXT */
+#ifdef VSTATUS
+	td->c_cc[VSTATUS] = s[C_STATUS];
+#endif /* VSTATUS */
+#ifdef VPAGE
+	td->c_cc[VPAGE] = s[C_PAGE];
+#endif /* VPAGE */
+#ifdef VPGOFF
+	td->c_cc[VPGOFF] = s[C_PGOFF];
+#endif /* VPGOFF */
+#ifdef VKILL2
+	td->c_cc[VKILL2] = s[C_KILL2];
+#endif /* VKILL2 */
+#ifdef VMIN
+	td->c_cc[VMIN] = s[C_MIN];
+#endif /* VMIN */
+#ifdef VTIME
+	td->c_cc[VTIME] = s[C_TIME];
+#endif /* VTIME */
+}				/* tty__setchar */
+
+
+/* tty_bind_char():
+ *	Rebind the editline functions
+ */
+libedit_private void
+tty_bind_char(EditLine *el, int force)
+{
+
+	unsigned char *t_n = el->el_tty.t_c[ED_IO];
+	unsigned char *t_o = el->el_tty.t_ed.c_cc;
+	wchar_t new[2], old[2];
+	const ttymap_t *tp;
+	el_action_t *map, *alt;
+	const el_action_t *dmap, *dalt;
+	new[1] = old[1] = '\0';
+
+	map = el->el_map.key;
+	alt = el->el_map.alt;
+	if (el->el_map.type == MAP_VI) {
+		dmap = el->el_map.vii;
+		dalt = el->el_map.vic;
+	} else {
+		dmap = el->el_map.emacs;
+		dalt = NULL;
+	}
+
+	for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
+		new[0] = (wchar_t)t_n[tp->nch];
+		old[0] = (wchar_t)t_o[tp->och];
+		if (new[0] == old[0] && !force)
+			continue;
+		/* Put the old default binding back, and set the new binding */
+		keymacro_clear(el, map, old);
+		map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]];
+		keymacro_clear(el, map, new);
+		/* MAP_VI == 1, MAP_EMACS == 0... */
+		map[(unsigned char)new[0]] = tp->bind[el->el_map.type];
+		if (dalt) {
+			keymacro_clear(el, alt, old);
+			alt[(unsigned char)old[0]] =
+			    dalt[(unsigned char)old[0]];
+			keymacro_clear(el, alt, new);
+			alt[(unsigned char)new[0]] =
+			    tp->bind[el->el_map.type + 1];
+		}
+	}
+}
+
+
+static tcflag_t *
+tty__get_flag(struct termios *t, int kind) {
+	switch (kind) {
+	case MD_INP:
+		return &t->c_iflag;
+	case MD_OUT:
+		return &t->c_oflag;
+	case MD_CTL:
+		return &t->c_cflag;
+	case MD_LIN:
+		return &t->c_lflag;
+	default:
+		abort();
+		/*NOTREACHED*/
+	}
+}
+
+
+static tcflag_t
+tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
+{
+	f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
+	f |= el->el_tty.t_t[mode][kind].t_setmask;
+	return f;
+}
+
+
+static void
+tty_update_flags(EditLine *el, int kind)
+{
+	tcflag_t *tt, *ed, *ex;
+	tt = tty__get_flag(&el->el_tty.t_ts, kind);
+	ed = tty__get_flag(&el->el_tty.t_ed, kind);
+	ex = tty__get_flag(&el->el_tty.t_ex, kind);
+
+	if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
+		*ed = tty_update_flag(el, *tt, ED_IO, kind);
+		*ex = tty_update_flag(el, *tt, EX_IO, kind);
+	}
+}
+
+
+static void
+tty_update_char(EditLine *el, int mode, int c) {
+	if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
+	    && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
+		el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
+	if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
+		el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
+}
+
+
+/* tty_rawmode():
+ *	Set terminal into 1 character at a time mode.
+ */
+libedit_private int
+tty_rawmode(EditLine *el)
+{
+
+	if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
+		return 0;
+
+	if (el->el_flags & EDIT_DISABLED)
+		return 0;
+
+	if (tty_getty(el, &el->el_tty.t_ts) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	/*
+         * We always keep up with the eight bit setting and the speed of the
+         * tty. But we only believe changes that are made to cooked mode!
+         */
+	el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
+	el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
+
+	if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
+	    tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
+		(void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+		(void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+		(void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+		(void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+	}
+	if (tty__cooked_mode(&el->el_tty.t_ts)) {
+		int i;
+
+		for (i = MD_INP; i <= MD_LIN; i++)
+			tty_update_flags(el, i);
+
+		if (tty__gettabs(&el->el_tty.t_ex) == 0)
+			el->el_tty.t_tabs = 0;
+		else
+			el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
+
+		tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+		/*
+		 * Check if the user made any changes.
+		 * If he did, then propagate the changes to the
+		 * edit and execute data structures.
+		 */
+		for (i = 0; i < C_NCC; i++)
+			if (el->el_tty.t_c[TS_IO][i] !=
+			    el->el_tty.t_c[EX_IO][i])
+				break;
+
+		if (i != C_NCC) {
+			/*
+			 * Propagate changes only to the unlibedit_private
+			 * chars that have been modified just now.
+			 */
+			for (i = 0; i < C_NCC; i++)
+				tty_update_char(el, ED_IO, i);
+
+			tty_bind_char(el, 0);
+			tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+
+			for (i = 0; i < C_NCC; i++)
+				tty_update_char(el, EX_IO, i);
+
+			tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+		}
+	}
+	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	el->el_tty.t_mode = ED_IO;
+	return 0;
+}
+
+
+/* tty_cookedmode():
+ *	Set the tty back to normal mode
+ */
+libedit_private int
+tty_cookedmode(EditLine *el)
+{				/* set tty in normal setup */
+
+	if (el->el_tty.t_mode == EX_IO)
+		return 0;
+
+	if (el->el_flags & EDIT_DISABLED)
+		return 0;
+
+	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	el->el_tty.t_mode = EX_IO;
+	return 0;
+}
+
+
+/* tty_quotemode():
+ *	Turn on quote mode
+ */
+libedit_private int
+tty_quotemode(EditLine *el)
+{
+	if (el->el_tty.t_mode == QU_IO)
+		return 0;
+
+	el->el_tty.t_qu = el->el_tty.t_ed;
+
+	tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
+
+	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	el->el_tty.t_mode = QU_IO;
+	return 0;
+}
+
+
+/* tty_noquotemode():
+ *	Turn off quote mode
+ */
+libedit_private int
+tty_noquotemode(EditLine *el)
+{
+
+	if (el->el_tty.t_mode != QU_IO)
+		return 0;
+	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+		(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+		    strerror(errno));
+#endif /* DEBUG_TTY */
+		return -1;
+	}
+	el->el_tty.t_mode = ED_IO;
+	return 0;
+}
+
+
+/* tty_stty():
+ *	Stty builtin
+ */
+libedit_private int
+/*ARGSUSED*/
+tty_stty(EditLine *el, int argc __attribute__((__unused__)),
+    const wchar_t **argv)
+{
+	const ttymodes_t *m;
+	char x;
+	int aflag = 0;
+	const wchar_t *s, *d;
+        char name[EL_BUFSIZ];
+	struct termios *tios = &el->el_tty.t_ex;
+	int z = EX_IO;
+
+	if (argv == NULL)
+		return -1;
+	strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
+        name[sizeof(name) - 1] = '\0';
+
+	while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
+		switch (argv[0][1]) {
+		case 'a':
+			aflag++;
+			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:
+			(void) fprintf(el->el_errfile,
+			    "%s: Unknown switch `%lc'.\n",
+			    name, (wint_t)argv[0][1]);
+			return -1;
+		}
+
+	if (!argv || !*argv) {
+		int i = -1;
+		size_t len = 0, st = 0, cu;
+		for (m = ttymodes; m->m_name; m++) {
+			if (m->m_type != i) {
+				(void) fprintf(el->el_outfile, "%s%s",
+				    i != -1 ? "\n" : "",
+				    el->el_tty.t_t[z][m->m_type].t_name);
+				i = m->m_type;
+				st = len =
+				    strlen(el->el_tty.t_t[z][m->m_type].t_name);
+			}
+			if (i != -1) {
+			    x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
+				?  '+' : '\0';
+
+			    if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
+				x = '-';
+			} else {
+			    x = '\0';
+			}
+
+			if (x != '\0' || aflag) {
+
+				cu = strlen(m->m_name) + (x != '\0') + 1;
+
+				if (len + cu >=
+				    (size_t)el->el_terminal.t_size.h) {
+					(void) fprintf(el->el_outfile, "\n%*s",
+					    (int)st, "");
+					len = st + cu;
+				} else
+					len += cu;
+
+				if (x != '\0')
+					(void) fprintf(el->el_outfile, "%c%s ",
+					    x, m->m_name);
+				else
+					(void) fprintf(el->el_outfile, "%s ",
+					    m->m_name);
+			}
+		}
+		(void) fprintf(el->el_outfile, "\n");
+		return 0;
+	}
+	while (argv && (s = *argv++)) {
+		const wchar_t *p;
+		switch (*s) {
+		case '+':
+		case '-':
+			x = (char)*s++;
+			break;
+		default:
+			x = '\0';
+			break;
+		}
+		d = s;
+		p = wcschr(s, L'=');
+		for (m = ttymodes; m->m_name; m++)
+			if ((p ? strncmp(m->m_name, ct_encode_string(d,
+			    &el->el_scratch), (size_t)(p - d)) :
+			    strcmp(m->m_name, ct_encode_string(d,
+			    &el->el_scratch))) == 0 &&
+			    (p == NULL || m->m_type == MD_CHAR))
+				break;
+
+		if (!m->m_name) {
+			(void) fprintf(el->el_errfile,
+			    "%s: Invalid argument `%ls'.\n", name, d);
+			return -1;
+		}
+		if (p) {
+			int c = ffs((int)m->m_value);
+			int v = *++p ? parse__escape(&p) :
+			    el->el_tty.t_vdisable;
+			assert(c != 0);
+			c--;
+			c = tty__getcharindex(c);
+			assert(c != -1);
+			tios->c_cc[c] = (cc_t)v;
+			continue;
+		}
+		switch (x) {
+		case '+':
+			el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
+			el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+			break;
+		case '-':
+			el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+			el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
+			break;
+		default:
+			el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+			el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+			break;
+		}
+	}
+
+	tty_setup_flags(el, tios, z);
+	if (el->el_tty.t_mode == z) {
+		if (tty_setty(el, TCSADRAIN, tios) == -1) {
+#ifdef DEBUG_TTY
+			(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
+			    __func__, strerror(errno));
+#endif /* DEBUG_TTY */
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+#ifdef notyet
+/* tty_printchar():
+ *	DEbugging routine to print the tty characters
+ */
+static void
+tty_printchar(EditLine *el, unsigned char *s)
+{
+	ttyperm_t *m;
+	int i;
+
+	for (i = 0; i < C_NCC; i++) {
+		for (m = el->el_tty.t_t; m->m_name; m++)
+			if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
+				break;
+		if (m->m_name)
+			(void) fprintf(el->el_errfile, "%s ^%c ",
+			    m->m_name, s[i] + 'A' - 1);
+		if (i % 5 == 0)
+			(void) fprintf(el->el_errfile, "\n");
+	}
+	(void) fprintf(el->el_errfile, "\n");
+}
+#endif /* notyet */
+
+
+static void
+tty_setup_flags(EditLine *el, struct termios *tios, int mode)
+{
+	int kind;
+	for (kind = MD_INP; kind <= MD_LIN; kind++) {
+		tcflag_t *f = tty__get_flag(tios, kind);
+		*f = tty_update_flag(el, *f, mode, kind);
+	}
+}