11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
3184260Sobrien *
32268782Spfg *	$NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 christos Exp $
331573Srgrimes */
341573Srgrimes
351573Srgrimes#if !defined(lint) && !defined(SCCSID)
361573Srgrimesstatic char sccsid[] = "@(#)tty.c	8.1 (Berkeley) 6/4/93";
371573Srgrimes#endif /* not lint && not SCCSID */
3884260Sobrien#include <sys/cdefs.h>
3984260Sobrien__FBSDID("$FreeBSD$");
401573Srgrimes
418870Srgrimes/*
421573Srgrimes * tty.c: tty interface stuff
431573Srgrimes */
44148834Sstefanf#include <assert.h>
451573Srgrimes#include "sys.h"
461573Srgrimes#include "tty.h"
471573Srgrimes#include "el.h"
481573Srgrimes
491573Srgrimestypedef struct ttymodes_t {
5084260Sobrien	const char *m_name;
51148834Sstefanf	unsigned int m_value;
5284260Sobrien	int m_type;
5384260Sobrien}          ttymodes_t;
541573Srgrimes
551573Srgrimestypedef struct ttymap_t {
5684260Sobrien	int nch, och;		/* Internal and termio rep of chars */
5784260Sobrien	el_action_t bind[3];	/* emacs, vi, and vi-cmd */
58148834Sstefanf} ttymap_t;
591573Srgrimes
601573Srgrimes
6184260Sobrienprivate const ttyperm_t ttyperm = {
6284260Sobrien	{
6384260Sobrien		{"iflag:", ICRNL, (INLCR | IGNCR)},
6484260Sobrien		{"oflag:", (OPOST | ONLCR), ONLRET},
6584260Sobrien		{"cflag:", 0, 0},
6684260Sobrien		{"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
6784260Sobrien		(NOFLSH | ECHONL | EXTPROC | FLUSHO)},
6884260Sobrien		{"chars:", 0, 0},
6984260Sobrien	},
7084260Sobrien	{
7184260Sobrien		{"iflag:", (INLCR | ICRNL), IGNCR},
7284260Sobrien		{"oflag:", (OPOST | ONLCR), ONLRET},
7384260Sobrien		{"cflag:", 0, 0},
7484260Sobrien		{"lflag:", ISIG,
7584260Sobrien		(NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
7684260Sobrien		{"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
7784260Sobrien			    C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
7884260Sobrien		    C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
7984260Sobrien	},
8084260Sobrien	{
8184260Sobrien		{"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
8284260Sobrien		{"oflag:", 0, 0},
8384260Sobrien		{"cflag:", 0, 0},
8484260Sobrien		{"lflag:", 0, ISIG | IEXTEN},
8584260Sobrien		{"chars:", 0, 0},
8684260Sobrien	}
871573Srgrimes};
881573Srgrimes
8984260Sobrienprivate const ttychar_t ttychar = {
9084260Sobrien	{
9184260Sobrien		CINTR, CQUIT, CERASE, CKILL,
9284260Sobrien		CEOF, CEOL, CEOL2, CSWTCH,
9384260Sobrien		CDSWTCH, CERASE2, CSTART, CSTOP,
9484260Sobrien		CWERASE, CSUSP, CDSUSP, CREPRINT,
9584260Sobrien		CDISCARD, CLNEXT, CSTATUS, CPAGE,
9684260Sobrien		CPGOFF, CKILL2, CBRK, CMIN,
9784260Sobrien		CTIME
9884260Sobrien	},
9984260Sobrien	{
10084260Sobrien		CINTR, CQUIT, CERASE, CKILL,
10184260Sobrien		_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
10284260Sobrien		_POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
10384260Sobrien		_POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
10484260Sobrien		CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
10584260Sobrien		_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
10684260Sobrien		0
10784260Sobrien	},
10884260Sobrien	{
10984260Sobrien		0, 0, 0, 0,
11084260Sobrien		0, 0, 0, 0,
11184260Sobrien		0, 0, 0, 0,
11284260Sobrien		0, 0, 0, 0,
11384260Sobrien		0, 0, 0, 0,
11484260Sobrien		0, 0, 0, 0,
11584260Sobrien		0
11684260Sobrien	}
1171573Srgrimes};
1181573Srgrimes
11984260Sobrienprivate const ttymap_t tty_map[] = {
1201573Srgrimes#ifdef VERASE
12184260Sobrien	{C_ERASE, VERASE,
122148834Sstefanf	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
1231573Srgrimes#endif /* VERASE */
1241573Srgrimes#ifdef VERASE2
12584260Sobrien	{C_ERASE2, VERASE2,
126148834Sstefanf	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
1271573Srgrimes#endif /* VERASE2 */
1281573Srgrimes#ifdef VKILL
12984260Sobrien	{C_KILL, VKILL,
13084260Sobrien	{EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
1311573Srgrimes#endif /* VKILL */
1321573Srgrimes#ifdef VKILL2
13384260Sobrien	{C_KILL2, VKILL2,
13484260Sobrien	{EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
1351573Srgrimes#endif /* VKILL2 */
1361573Srgrimes#ifdef VEOF
13784260Sobrien	{C_EOF, VEOF,
13884260Sobrien	{EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
1391573Srgrimes#endif /* VEOF */
1401573Srgrimes#ifdef VWERASE
14184260Sobrien	{C_WERASE, VWERASE,
14284260Sobrien	{ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
1431573Srgrimes#endif /* VWERASE */
1441573Srgrimes#ifdef VREPRINT
14584260Sobrien	{C_REPRINT, VREPRINT,
14684260Sobrien	{ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
1471573Srgrimes#endif /* VREPRINT */
1481573Srgrimes#ifdef VLNEXT
14984260Sobrien	{C_LNEXT, VLNEXT,
15084260Sobrien	{ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
1511573Srgrimes#endif /* VLNEXT */
15284260Sobrien	{-1, -1,
15384260Sobrien	{ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
15484260Sobrien};
1551573Srgrimes
15684260Sobrienprivate const ttymodes_t ttymodes[] = {
15784260Sobrien#ifdef	IGNBRK
15884260Sobrien	{"ignbrk", IGNBRK, MD_INP},
15984260Sobrien#endif /* IGNBRK */
16084260Sobrien#ifdef	BRKINT
16184260Sobrien	{"brkint", BRKINT, MD_INP},
16284260Sobrien#endif /* BRKINT */
16384260Sobrien#ifdef	IGNPAR
16484260Sobrien	{"ignpar", IGNPAR, MD_INP},
16584260Sobrien#endif /* IGNPAR */
16684260Sobrien#ifdef	PARMRK
16784260Sobrien	{"parmrk", PARMRK, MD_INP},
16884260Sobrien#endif /* PARMRK */
16984260Sobrien#ifdef	INPCK
17084260Sobrien	{"inpck", INPCK, MD_INP},
17184260Sobrien#endif /* INPCK */
17284260Sobrien#ifdef	ISTRIP
17384260Sobrien	{"istrip", ISTRIP, MD_INP},
17484260Sobrien#endif /* ISTRIP */
17584260Sobrien#ifdef	INLCR
17684260Sobrien	{"inlcr", INLCR, MD_INP},
17784260Sobrien#endif /* INLCR */
17884260Sobrien#ifdef	IGNCR
17984260Sobrien	{"igncr", IGNCR, MD_INP},
18084260Sobrien#endif /* IGNCR */
18184260Sobrien#ifdef	ICRNL
18284260Sobrien	{"icrnl", ICRNL, MD_INP},
18384260Sobrien#endif /* ICRNL */
18484260Sobrien#ifdef	IUCLC
18584260Sobrien	{"iuclc", IUCLC, MD_INP},
18684260Sobrien#endif /* IUCLC */
18784260Sobrien#ifdef	IXON
18884260Sobrien	{"ixon", IXON, MD_INP},
18984260Sobrien#endif /* IXON */
19084260Sobrien#ifdef	IXANY
19184260Sobrien	{"ixany", IXANY, MD_INP},
19284260Sobrien#endif /* IXANY */
19384260Sobrien#ifdef	IXOFF
19484260Sobrien	{"ixoff", IXOFF, MD_INP},
19584260Sobrien#endif /* IXOFF */
19684260Sobrien#ifdef  IMAXBEL
19784260Sobrien	{"imaxbel", IMAXBEL, MD_INP},
19884260Sobrien#endif /* IMAXBEL */
1991573Srgrimes
20084260Sobrien#ifdef	OPOST
20184260Sobrien	{"opost", OPOST, MD_OUT},
20284260Sobrien#endif /* OPOST */
20384260Sobrien#ifdef	OLCUC
20484260Sobrien	{"olcuc", OLCUC, MD_OUT},
20584260Sobrien#endif /* OLCUC */
20684260Sobrien#ifdef	ONLCR
20784260Sobrien	{"onlcr", ONLCR, MD_OUT},
20884260Sobrien#endif /* ONLCR */
20984260Sobrien#ifdef	OCRNL
21084260Sobrien	{"ocrnl", OCRNL, MD_OUT},
21184260Sobrien#endif /* OCRNL */
21284260Sobrien#ifdef	ONOCR
21384260Sobrien	{"onocr", ONOCR, MD_OUT},
21484260Sobrien#endif /* ONOCR */
21584260Sobrien#ifdef ONOEOT
21684260Sobrien	{"onoeot", ONOEOT, MD_OUT},
21784260Sobrien#endif /* ONOEOT */
21884260Sobrien#ifdef	ONLRET
21984260Sobrien	{"onlret", ONLRET, MD_OUT},
22084260Sobrien#endif /* ONLRET */
22184260Sobrien#ifdef	OFILL
22284260Sobrien	{"ofill", OFILL, MD_OUT},
22384260Sobrien#endif /* OFILL */
22484260Sobrien#ifdef	OFDEL
22584260Sobrien	{"ofdel", OFDEL, MD_OUT},
22684260Sobrien#endif /* OFDEL */
22784260Sobrien#ifdef	NLDLY
22884260Sobrien	{"nldly", NLDLY, MD_OUT},
22984260Sobrien#endif /* NLDLY */
23084260Sobrien#ifdef	CRDLY
23184260Sobrien	{"crdly", CRDLY, MD_OUT},
23284260Sobrien#endif /* CRDLY */
23384260Sobrien#ifdef	TABDLY
23484260Sobrien	{"tabdly", TABDLY, MD_OUT},
23584260Sobrien#endif /* TABDLY */
23684260Sobrien#ifdef	XTABS
23784260Sobrien	{"xtabs", XTABS, MD_OUT},
23884260Sobrien#endif /* XTABS */
23984260Sobrien#ifdef	BSDLY
24084260Sobrien	{"bsdly", BSDLY, MD_OUT},
24184260Sobrien#endif /* BSDLY */
24284260Sobrien#ifdef	VTDLY
24384260Sobrien	{"vtdly", VTDLY, MD_OUT},
24484260Sobrien#endif /* VTDLY */
24584260Sobrien#ifdef	FFDLY
24684260Sobrien	{"ffdly", FFDLY, MD_OUT},
24784260Sobrien#endif /* FFDLY */
24884260Sobrien#ifdef	PAGEOUT
24984260Sobrien	{"pageout", PAGEOUT, MD_OUT},
25084260Sobrien#endif /* PAGEOUT */
25184260Sobrien#ifdef	WRAP
25284260Sobrien	{"wrap", WRAP, MD_OUT},
25384260Sobrien#endif /* WRAP */
2541573Srgrimes
25584260Sobrien#ifdef	CIGNORE
25684260Sobrien	{"cignore", CIGNORE, MD_CTL},
25784260Sobrien#endif /* CBAUD */
25884260Sobrien#ifdef	CBAUD
25984260Sobrien	{"cbaud", CBAUD, MD_CTL},
26084260Sobrien#endif /* CBAUD */
26184260Sobrien#ifdef	CSTOPB
26284260Sobrien	{"cstopb", CSTOPB, MD_CTL},
26384260Sobrien#endif /* CSTOPB */
26484260Sobrien#ifdef	CREAD
26584260Sobrien	{"cread", CREAD, MD_CTL},
26684260Sobrien#endif /* CREAD */
26784260Sobrien#ifdef	PARENB
26884260Sobrien	{"parenb", PARENB, MD_CTL},
26984260Sobrien#endif /* PARENB */
27084260Sobrien#ifdef	PARODD
27184260Sobrien	{"parodd", PARODD, MD_CTL},
27284260Sobrien#endif /* PARODD */
27384260Sobrien#ifdef	HUPCL
27484260Sobrien	{"hupcl", HUPCL, MD_CTL},
27584260Sobrien#endif /* HUPCL */
27684260Sobrien#ifdef	CLOCAL
27784260Sobrien	{"clocal", CLOCAL, MD_CTL},
27884260Sobrien#endif /* CLOCAL */
27984260Sobrien#ifdef	LOBLK
28084260Sobrien	{"loblk", LOBLK, MD_CTL},
28184260Sobrien#endif /* LOBLK */
28284260Sobrien#ifdef	CIBAUD
28384260Sobrien	{"cibaud", CIBAUD, MD_CTL},
28484260Sobrien#endif /* CIBAUD */
28584260Sobrien#ifdef CRTSCTS
28684260Sobrien#ifdef CCTS_OFLOW
28784260Sobrien	{"ccts_oflow", CCTS_OFLOW, MD_CTL},
28884260Sobrien#else
28984260Sobrien	{"crtscts", CRTSCTS, MD_CTL},
29084260Sobrien#endif /* CCTS_OFLOW */
29184260Sobrien#endif /* CRTSCTS */
29284260Sobrien#ifdef CRTS_IFLOW
29384260Sobrien	{"crts_iflow", CRTS_IFLOW, MD_CTL},
29484260Sobrien#endif /* CRTS_IFLOW */
29584260Sobrien#ifdef CDTRCTS
29684260Sobrien	{"cdtrcts", CDTRCTS, MD_CTL},
29784260Sobrien#endif /* CDTRCTS */
29884260Sobrien#ifdef MDMBUF
29984260Sobrien	{"mdmbuf", MDMBUF, MD_CTL},
30084260Sobrien#endif /* MDMBUF */
30184260Sobrien#ifdef RCV1EN
30284260Sobrien	{"rcv1en", RCV1EN, MD_CTL},
30384260Sobrien#endif /* RCV1EN */
30484260Sobrien#ifdef XMT1EN
30584260Sobrien	{"xmt1en", XMT1EN, MD_CTL},
30684260Sobrien#endif /* XMT1EN */
3071573Srgrimes
30884260Sobrien#ifdef	ISIG
30984260Sobrien	{"isig", ISIG, MD_LIN},
31084260Sobrien#endif /* ISIG */
31184260Sobrien#ifdef	ICANON
31284260Sobrien	{"icanon", ICANON, MD_LIN},
31384260Sobrien#endif /* ICANON */
31484260Sobrien#ifdef	XCASE
31584260Sobrien	{"xcase", XCASE, MD_LIN},
31684260Sobrien#endif /* XCASE */
31784260Sobrien#ifdef	ECHO
31884260Sobrien	{"echo", ECHO, MD_LIN},
31984260Sobrien#endif /* ECHO */
32084260Sobrien#ifdef	ECHOE
32184260Sobrien	{"echoe", ECHOE, MD_LIN},
32284260Sobrien#endif /* ECHOE */
32384260Sobrien#ifdef	ECHOK
32484260Sobrien	{"echok", ECHOK, MD_LIN},
32584260Sobrien#endif /* ECHOK */
32684260Sobrien#ifdef	ECHONL
32784260Sobrien	{"echonl", ECHONL, MD_LIN},
32884260Sobrien#endif /* ECHONL */
32984260Sobrien#ifdef	NOFLSH
33084260Sobrien	{"noflsh", NOFLSH, MD_LIN},
33184260Sobrien#endif /* NOFLSH */
33284260Sobrien#ifdef	TOSTOP
33384260Sobrien	{"tostop", TOSTOP, MD_LIN},
33484260Sobrien#endif /* TOSTOP */
33584260Sobrien#ifdef	ECHOCTL
33684260Sobrien	{"echoctl", ECHOCTL, MD_LIN},
33784260Sobrien#endif /* ECHOCTL */
33884260Sobrien#ifdef	ECHOPRT
33984260Sobrien	{"echoprt", ECHOPRT, MD_LIN},
34084260Sobrien#endif /* ECHOPRT */
34184260Sobrien#ifdef	ECHOKE
34284260Sobrien	{"echoke", ECHOKE, MD_LIN},
34384260Sobrien#endif /* ECHOKE */
34484260Sobrien#ifdef	DEFECHO
34584260Sobrien	{"defecho", DEFECHO, MD_LIN},
34684260Sobrien#endif /* DEFECHO */
34784260Sobrien#ifdef	FLUSHO
34884260Sobrien	{"flusho", FLUSHO, MD_LIN},
34984260Sobrien#endif /* FLUSHO */
35084260Sobrien#ifdef	PENDIN
35184260Sobrien	{"pendin", PENDIN, MD_LIN},
35284260Sobrien#endif /* PENDIN */
35384260Sobrien#ifdef	IEXTEN
35484260Sobrien	{"iexten", IEXTEN, MD_LIN},
35584260Sobrien#endif /* IEXTEN */
35684260Sobrien#ifdef	NOKERNINFO
35784260Sobrien	{"nokerninfo", NOKERNINFO, MD_LIN},
35884260Sobrien#endif /* NOKERNINFO */
35984260Sobrien#ifdef	ALTWERASE
36084260Sobrien	{"altwerase", ALTWERASE, MD_LIN},
36184260Sobrien#endif /* ALTWERASE */
36284260Sobrien#ifdef	EXTPROC
36384260Sobrien	{"extproc", EXTPROC, MD_LIN},
36484260Sobrien#endif /* EXTPROC */
3651573Srgrimes
36684260Sobrien#if defined(VINTR)
36784260Sobrien	{"intr", C_SH(C_INTR), MD_CHAR},
36884260Sobrien#endif /* VINTR */
36984260Sobrien#if defined(VQUIT)
37084260Sobrien	{"quit", C_SH(C_QUIT), MD_CHAR},
37184260Sobrien#endif /* VQUIT */
37284260Sobrien#if defined(VERASE)
37384260Sobrien	{"erase", C_SH(C_ERASE), MD_CHAR},
37484260Sobrien#endif /* VERASE */
37584260Sobrien#if defined(VKILL)
37684260Sobrien	{"kill", C_SH(C_KILL), MD_CHAR},
37784260Sobrien#endif /* VKILL */
37884260Sobrien#if defined(VEOF)
37984260Sobrien	{"eof", C_SH(C_EOF), MD_CHAR},
38084260Sobrien#endif /* VEOF */
38184260Sobrien#if defined(VEOL)
38284260Sobrien	{"eol", C_SH(C_EOL), MD_CHAR},
38384260Sobrien#endif /* VEOL */
38484260Sobrien#if defined(VEOL2)
38584260Sobrien	{"eol2", C_SH(C_EOL2), MD_CHAR},
38684260Sobrien#endif /* VEOL2 */
38784260Sobrien#if defined(VSWTCH)
38884260Sobrien	{"swtch", C_SH(C_SWTCH), MD_CHAR},
38984260Sobrien#endif /* VSWTCH */
39084260Sobrien#if defined(VDSWTCH)
39184260Sobrien	{"dswtch", C_SH(C_DSWTCH), MD_CHAR},
39284260Sobrien#endif /* VDSWTCH */
39384260Sobrien#if defined(VERASE2)
39484260Sobrien	{"erase2", C_SH(C_ERASE2), MD_CHAR},
39584260Sobrien#endif /* VERASE2 */
39684260Sobrien#if defined(VSTART)
39784260Sobrien	{"start", C_SH(C_START), MD_CHAR},
39884260Sobrien#endif /* VSTART */
39984260Sobrien#if defined(VSTOP)
40084260Sobrien	{"stop", C_SH(C_STOP), MD_CHAR},
40184260Sobrien#endif /* VSTOP */
40284260Sobrien#if defined(VWERASE)
40384260Sobrien	{"werase", C_SH(C_WERASE), MD_CHAR},
40484260Sobrien#endif /* VWERASE */
40584260Sobrien#if defined(VSUSP)
40684260Sobrien	{"susp", C_SH(C_SUSP), MD_CHAR},
40784260Sobrien#endif /* VSUSP */
40884260Sobrien#if defined(VDSUSP)
40984260Sobrien	{"dsusp", C_SH(C_DSUSP), MD_CHAR},
41084260Sobrien#endif /* VDSUSP */
41184260Sobrien#if defined(VREPRINT)
41284260Sobrien	{"reprint", C_SH(C_REPRINT), MD_CHAR},
41384260Sobrien#endif /* VREPRINT */
41484260Sobrien#if defined(VDISCARD)
41584260Sobrien	{"discard", C_SH(C_DISCARD), MD_CHAR},
41684260Sobrien#endif /* VDISCARD */
41784260Sobrien#if defined(VLNEXT)
41884260Sobrien	{"lnext", C_SH(C_LNEXT), MD_CHAR},
41984260Sobrien#endif /* VLNEXT */
42084260Sobrien#if defined(VSTATUS)
42184260Sobrien	{"status", C_SH(C_STATUS), MD_CHAR},
42284260Sobrien#endif /* VSTATUS */
42384260Sobrien#if defined(VPAGE)
42484260Sobrien	{"page", C_SH(C_PAGE), MD_CHAR},
42584260Sobrien#endif /* VPAGE */
42684260Sobrien#if defined(VPGOFF)
42784260Sobrien	{"pgoff", C_SH(C_PGOFF), MD_CHAR},
42884260Sobrien#endif /* VPGOFF */
42984260Sobrien#if defined(VKILL2)
43084260Sobrien	{"kill2", C_SH(C_KILL2), MD_CHAR},
43184260Sobrien#endif /* VKILL2 */
43284260Sobrien#if defined(VBRK)
43384260Sobrien	{"brk", C_SH(C_BRK), MD_CHAR},
43484260Sobrien#endif /* VBRK */
43584260Sobrien#if defined(VMIN)
43684260Sobrien	{"min", C_SH(C_MIN), MD_CHAR},
43784260Sobrien#endif /* VMIN */
43884260Sobrien#if defined(VTIME)
43984260Sobrien	{"time", C_SH(C_TIME), MD_CHAR},
44084260Sobrien#endif /* VTIME */
44184260Sobrien	{NULL, 0, -1},
4421573Srgrimes};
4431573Srgrimes
4441573Srgrimes
4451573Srgrimes
44684260Sobrien#define	tty__gettabs(td)	((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
44784260Sobrien#define	tty__geteightbit(td)	(((td)->c_cflag & CSIZE) == CS8)
44884260Sobrien#define	tty__cooked_mode(td)	((td)->c_lflag & ICANON)
4491573Srgrimes
450268782Spfgprivate int	tty_getty(EditLine *, struct termios *);
451268782Spfgprivate int	tty_setty(EditLine *, int, const struct termios *);
452148834Sstefanfprivate int	tty__getcharindex(int);
45384260Sobrienprivate void	tty__getchar(struct termios *, unsigned char *);
45484260Sobrienprivate void	tty__setchar(struct termios *, unsigned char *);
45584260Sobrienprivate speed_t	tty__getspeed(struct termios *);
45684260Sobrienprivate int	tty_setup(EditLine *);
4571573Srgrimes
45884260Sobrien#define	t_qu	t_ts
4591573Srgrimes
460268782Spfg/* tty_getty():
461268782Spfg *	Wrapper for tcgetattr to handle EINTR
462268782Spfg */
463268782Spfgprivate int
464268782Spfgtty_getty(EditLine *el, struct termios *t)
465268782Spfg{
466268782Spfg	int rv;
467268782Spfg	while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
468268782Spfg		continue;
469268782Spfg	return rv;
470268782Spfg}
4711573Srgrimes
472268782Spfg/* tty_setty():
473268782Spfg *	Wrapper for tcsetattr to handle EINTR
474268782Spfg */
475268782Spfgprivate int
476268782Spfgtty_setty(EditLine *el, int action, const struct termios *t)
477268782Spfg{
478268782Spfg	int rv;
479268782Spfg	while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
480268782Spfg		continue;
481268782Spfg	return rv;
482268782Spfg}
483268782Spfg
4841573Srgrimes/* tty_setup():
4851573Srgrimes *	Get the tty parameters and initialize the editing state
4861573Srgrimes */
4878870Srgrimesprivate int
48884260Sobrientty_setup(EditLine *el)
4891573Srgrimes{
49084260Sobrien	int rst = 1;
49184260Sobrien
49284260Sobrien	if (el->el_flags & EDIT_DISABLED)
49384260Sobrien		return (0);
49484260Sobrien
49584260Sobrien	if (tty_getty(el, &el->el_tty.t_ed) == -1) {
4961573Srgrimes#ifdef DEBUG_TTY
49784260Sobrien		(void) fprintf(el->el_errfile,
49884260Sobrien		    "tty_setup: tty_getty: %s\n", strerror(errno));
4991573Srgrimes#endif /* DEBUG_TTY */
50084260Sobrien		return (-1);
50184260Sobrien	}
50284260Sobrien	el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
5031573Srgrimes
50484260Sobrien	el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
50584260Sobrien	el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
50684260Sobrien	el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
5071573Srgrimes
50884260Sobrien	/*
50984260Sobrien         * Reset the tty chars to reasonable defaults
51084260Sobrien         * If they are disabled, then enable them.
51184260Sobrien         */
51284260Sobrien	if (rst) {
51384260Sobrien		if (tty__cooked_mode(&el->el_tty.t_ts)) {
51484260Sobrien			tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
51584260Sobrien			/*
51684260Sobrien	                 * Don't affect CMIN and CTIME for the editor mode
51784260Sobrien	                 */
51884260Sobrien			for (rst = 0; rst < C_NCC - 2; rst++)
51984260Sobrien				if (el->el_tty.t_c[TS_IO][rst] !=
52084260Sobrien				      el->el_tty.t_vdisable
52184260Sobrien				    && el->el_tty.t_c[ED_IO][rst] !=
52284260Sobrien				      el->el_tty.t_vdisable)
52384260Sobrien					el->el_tty.t_c[ED_IO][rst] =
52484260Sobrien					    el->el_tty.t_c[TS_IO][rst];
52584260Sobrien			for (rst = 0; rst < C_NCC; rst++)
52684260Sobrien				if (el->el_tty.t_c[TS_IO][rst] !=
52784260Sobrien				    el->el_tty.t_vdisable)
52884260Sobrien					el->el_tty.t_c[EX_IO][rst] =
52984260Sobrien					    el->el_tty.t_c[TS_IO][rst];
53084260Sobrien		}
53184260Sobrien	}
5321573Srgrimes
53384260Sobrien	el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
53484260Sobrien	el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
5351573Srgrimes
53684260Sobrien	el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
53784260Sobrien	el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
5381573Srgrimes
53984260Sobrien	el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
54084260Sobrien	el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
5411573Srgrimes
54284260Sobrien	el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
54384260Sobrien	el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
5441573Srgrimes
54584260Sobrien	tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
54684260Sobrien	tty_bind_char(el, 1);
54784260Sobrien	return (0);
5481573Srgrimes}
5491573Srgrimes
5501573Srgrimesprotected int
55184260Sobrientty_init(EditLine *el)
5521573Srgrimes{
5531573Srgrimes
55484260Sobrien	el->el_tty.t_mode = EX_IO;
55584260Sobrien	el->el_tty.t_vdisable = _POSIX_VDISABLE;
55684260Sobrien	(void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
55784260Sobrien	(void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
55884260Sobrien	return (tty_setup(el));
55984260Sobrien}
5601573Srgrimes
56184260Sobrien
5621573Srgrimes/* tty_end():
5631573Srgrimes *	Restore the tty to its original settings
5641573Srgrimes */
5651573Srgrimesprotected void
5661573Srgrimes/*ARGSUSED*/
567148834Sstefanftty_end(EditLine *el __unused)
5681573Srgrimes{
56984260Sobrien
57084260Sobrien	/* XXX: Maybe reset to an initial state? */
5711573Srgrimes}
5721573Srgrimes
5731573Srgrimes
5741573Srgrimes/* tty__getspeed():
5751573Srgrimes *	Get the tty speed
5761573Srgrimes */
5771573Srgrimesprivate speed_t
57884260Sobrientty__getspeed(struct termios *td)
5791573Srgrimes{
58084260Sobrien	speed_t spd;
5811573Srgrimes
58284260Sobrien	if ((spd = cfgetispeed(td)) == 0)
58384260Sobrien		spd = cfgetospeed(td);
58484260Sobrien	return (spd);
58584260Sobrien}
5861573Srgrimes
587148834Sstefanf/* tty__getspeed():
588148834Sstefanf *	Return the index of the asked char in the c_cc array
589148834Sstefanf */
590148834Sstefanfprivate int
591148834Sstefanftty__getcharindex(int i)
592148834Sstefanf{
593148834Sstefanf	switch (i) {
594148834Sstefanf#ifdef VINTR
595148834Sstefanf	case C_INTR:
596148834Sstefanf		return VINTR;
597148834Sstefanf#endif /* VINTR */
598148834Sstefanf#ifdef VQUIT
599148834Sstefanf	case C_QUIT:
600148834Sstefanf		return VQUIT;
601148834Sstefanf#endif /* VQUIT */
602148834Sstefanf#ifdef VERASE
603148834Sstefanf	case C_ERASE:
604148834Sstefanf		return VERASE;
605148834Sstefanf#endif /* VERASE */
606148834Sstefanf#ifdef VKILL
607148834Sstefanf	case C_KILL:
608148834Sstefanf		return VKILL;
609148834Sstefanf#endif /* VKILL */
610148834Sstefanf#ifdef VEOF
611148834Sstefanf	case C_EOF:
612148834Sstefanf		return VEOF;
613148834Sstefanf#endif /* VEOF */
614148834Sstefanf#ifdef VEOL
615148834Sstefanf	case C_EOL:
616148834Sstefanf		return VEOL;
617148834Sstefanf#endif /* VEOL */
618148834Sstefanf#ifdef VEOL2
619148834Sstefanf	case C_EOL2:
620148834Sstefanf		return VEOL2;
621148834Sstefanf#endif /* VEOL2 */
622148834Sstefanf#ifdef VSWTCH
623148834Sstefanf	case C_SWTCH:
624148834Sstefanf		return VSWTCH;
625148834Sstefanf#endif /* VSWTCH */
626148834Sstefanf#ifdef VDSWTCH
627148834Sstefanf	case C_DSWTCH:
628148834Sstefanf		return VDSWTCH;
629148834Sstefanf#endif /* VDSWTCH */
630148834Sstefanf#ifdef VERASE2
631148834Sstefanf	case C_ERASE2:
632148834Sstefanf		return VERASE2;
633148834Sstefanf#endif /* VERASE2 */
634148834Sstefanf#ifdef VSTART
635148834Sstefanf	case C_START:
636148834Sstefanf		return VSTART;
637148834Sstefanf#endif /* VSTART */
638148834Sstefanf#ifdef VSTOP
639148834Sstefanf	case C_STOP:
640148834Sstefanf		return VSTOP;
641148834Sstefanf#endif /* VSTOP */
642148834Sstefanf#ifdef VWERASE
643148834Sstefanf	case C_WERASE:
644148834Sstefanf		return VWERASE;
645148834Sstefanf#endif /* VWERASE */
646148834Sstefanf#ifdef VSUSP
647148834Sstefanf	case C_SUSP:
648148834Sstefanf		return VSUSP;
649148834Sstefanf#endif /* VSUSP */
650148834Sstefanf#ifdef VDSUSP
651148834Sstefanf	case C_DSUSP:
652148834Sstefanf		return VDSUSP;
653148834Sstefanf#endif /* VDSUSP */
654148834Sstefanf#ifdef VREPRINT
655148834Sstefanf	case C_REPRINT:
656148834Sstefanf		return VREPRINT;
657148834Sstefanf#endif /* VREPRINT */
658148834Sstefanf#ifdef VDISCARD
659148834Sstefanf	case C_DISCARD:
660148834Sstefanf		return VDISCARD;
661148834Sstefanf#endif /* VDISCARD */
662148834Sstefanf#ifdef VLNEXT
663148834Sstefanf	case C_LNEXT:
664148834Sstefanf		return VLNEXT;
665148834Sstefanf#endif /* VLNEXT */
666148834Sstefanf#ifdef VSTATUS
667148834Sstefanf	case C_STATUS:
668148834Sstefanf		return VSTATUS;
669148834Sstefanf#endif /* VSTATUS */
670148834Sstefanf#ifdef VPAGE
671148834Sstefanf	case C_PAGE:
672148834Sstefanf		return VPAGE;
673148834Sstefanf#endif /* VPAGE */
674148834Sstefanf#ifdef VPGOFF
675148834Sstefanf	case C_PGOFF:
676148834Sstefanf		return VPGOFF;
677148834Sstefanf#endif /* VPGOFF */
678148834Sstefanf#ifdef VKILL2
679148834Sstefanf	case C_KILL2:
680148834Sstefanf		return VKILL2;
681148834Sstefanf#endif /* KILL2 */
682148834Sstefanf#ifdef VMIN
683148834Sstefanf	case C_MIN:
684148834Sstefanf		return VMIN;
685148834Sstefanf#endif /* VMIN */
686148834Sstefanf#ifdef VTIME
687148834Sstefanf	case C_TIME:
688148834Sstefanf		return VTIME;
689148834Sstefanf#endif /* VTIME */
690148834Sstefanf	default:
691148834Sstefanf		return -1;
692148834Sstefanf	}
693148834Sstefanf}
6941573Srgrimes
6951573Srgrimes/* tty__getchar():
6961573Srgrimes *	Get the tty characters
6971573Srgrimes */
6981573Srgrimesprivate void
69984260Sobrientty__getchar(struct termios *td, unsigned char *s)
7008870Srgrimes{
7011573Srgrimes
70284260Sobrien#ifdef VINTR
70384260Sobrien	s[C_INTR] = td->c_cc[VINTR];
70484260Sobrien#endif /* VINTR */
70584260Sobrien#ifdef VQUIT
70684260Sobrien	s[C_QUIT] = td->c_cc[VQUIT];
70784260Sobrien#endif /* VQUIT */
70884260Sobrien#ifdef VERASE
70984260Sobrien	s[C_ERASE] = td->c_cc[VERASE];
71084260Sobrien#endif /* VERASE */
71184260Sobrien#ifdef VKILL
71284260Sobrien	s[C_KILL] = td->c_cc[VKILL];
71384260Sobrien#endif /* VKILL */
71484260Sobrien#ifdef VEOF
71584260Sobrien	s[C_EOF] = td->c_cc[VEOF];
71684260Sobrien#endif /* VEOF */
71784260Sobrien#ifdef VEOL
71884260Sobrien	s[C_EOL] = td->c_cc[VEOL];
71984260Sobrien#endif /* VEOL */
72084260Sobrien#ifdef VEOL2
72184260Sobrien	s[C_EOL2] = td->c_cc[VEOL2];
72284260Sobrien#endif /* VEOL2 */
72384260Sobrien#ifdef VSWTCH
72484260Sobrien	s[C_SWTCH] = td->c_cc[VSWTCH];
72584260Sobrien#endif /* VSWTCH */
72684260Sobrien#ifdef VDSWTCH
72784260Sobrien	s[C_DSWTCH] = td->c_cc[VDSWTCH];
72884260Sobrien#endif /* VDSWTCH */
72984260Sobrien#ifdef VERASE2
73084260Sobrien	s[C_ERASE2] = td->c_cc[VERASE2];
73184260Sobrien#endif /* VERASE2 */
73284260Sobrien#ifdef VSTART
73384260Sobrien	s[C_START] = td->c_cc[VSTART];
73484260Sobrien#endif /* VSTART */
73584260Sobrien#ifdef VSTOP
73684260Sobrien	s[C_STOP] = td->c_cc[VSTOP];
73784260Sobrien#endif /* VSTOP */
73884260Sobrien#ifdef VWERASE
73984260Sobrien	s[C_WERASE] = td->c_cc[VWERASE];
74084260Sobrien#endif /* VWERASE */
74184260Sobrien#ifdef VSUSP
74284260Sobrien	s[C_SUSP] = td->c_cc[VSUSP];
74384260Sobrien#endif /* VSUSP */
74484260Sobrien#ifdef VDSUSP
74584260Sobrien	s[C_DSUSP] = td->c_cc[VDSUSP];
74684260Sobrien#endif /* VDSUSP */
74784260Sobrien#ifdef VREPRINT
74884260Sobrien	s[C_REPRINT] = td->c_cc[VREPRINT];
74984260Sobrien#endif /* VREPRINT */
75084260Sobrien#ifdef VDISCARD
75184260Sobrien	s[C_DISCARD] = td->c_cc[VDISCARD];
75284260Sobrien#endif /* VDISCARD */
75384260Sobrien#ifdef VLNEXT
75484260Sobrien	s[C_LNEXT] = td->c_cc[VLNEXT];
75584260Sobrien#endif /* VLNEXT */
75684260Sobrien#ifdef VSTATUS
75784260Sobrien	s[C_STATUS] = td->c_cc[VSTATUS];
75884260Sobrien#endif /* VSTATUS */
75984260Sobrien#ifdef VPAGE
76084260Sobrien	s[C_PAGE] = td->c_cc[VPAGE];
76184260Sobrien#endif /* VPAGE */
76284260Sobrien#ifdef VPGOFF
76384260Sobrien	s[C_PGOFF] = td->c_cc[VPGOFF];
76484260Sobrien#endif /* VPGOFF */
76584260Sobrien#ifdef VKILL2
76684260Sobrien	s[C_KILL2] = td->c_cc[VKILL2];
76784260Sobrien#endif /* KILL2 */
76884260Sobrien#ifdef VMIN
76984260Sobrien	s[C_MIN] = td->c_cc[VMIN];
77084260Sobrien#endif /* VMIN */
77184260Sobrien#ifdef VTIME
77284260Sobrien	s[C_TIME] = td->c_cc[VTIME];
77384260Sobrien#endif /* VTIME */
77484260Sobrien}				/* tty__getchar */
7751573Srgrimes
77684260Sobrien
7771573Srgrimes/* tty__setchar():
7781573Srgrimes *	Set the tty characters
7791573Srgrimes */
7801573Srgrimesprivate void
78184260Sobrientty__setchar(struct termios *td, unsigned char *s)
7828870Srgrimes{
7831573Srgrimes
78484260Sobrien#ifdef VINTR
78584260Sobrien	td->c_cc[VINTR] = s[C_INTR];
78684260Sobrien#endif /* VINTR */
78784260Sobrien#ifdef VQUIT
78884260Sobrien	td->c_cc[VQUIT] = s[C_QUIT];
78984260Sobrien#endif /* VQUIT */
79084260Sobrien#ifdef VERASE
79184260Sobrien	td->c_cc[VERASE] = s[C_ERASE];
79284260Sobrien#endif /* VERASE */
79384260Sobrien#ifdef VKILL
79484260Sobrien	td->c_cc[VKILL] = s[C_KILL];
79584260Sobrien#endif /* VKILL */
79684260Sobrien#ifdef VEOF
79784260Sobrien	td->c_cc[VEOF] = s[C_EOF];
79884260Sobrien#endif /* VEOF */
79984260Sobrien#ifdef VEOL
80084260Sobrien	td->c_cc[VEOL] = s[C_EOL];
80184260Sobrien#endif /* VEOL */
80284260Sobrien#ifdef VEOL2
80384260Sobrien	td->c_cc[VEOL2] = s[C_EOL2];
80484260Sobrien#endif /* VEOL2 */
80584260Sobrien#ifdef VSWTCH
80684260Sobrien	td->c_cc[VSWTCH] = s[C_SWTCH];
80784260Sobrien#endif /* VSWTCH */
80884260Sobrien#ifdef VDSWTCH
80984260Sobrien	td->c_cc[VDSWTCH] = s[C_DSWTCH];
81084260Sobrien#endif /* VDSWTCH */
81184260Sobrien#ifdef VERASE2
81284260Sobrien	td->c_cc[VERASE2] = s[C_ERASE2];
81384260Sobrien#endif /* VERASE2 */
81484260Sobrien#ifdef VSTART
81584260Sobrien	td->c_cc[VSTART] = s[C_START];
81684260Sobrien#endif /* VSTART */
81784260Sobrien#ifdef VSTOP
81884260Sobrien	td->c_cc[VSTOP] = s[C_STOP];
81984260Sobrien#endif /* VSTOP */
82084260Sobrien#ifdef VWERASE
82184260Sobrien	td->c_cc[VWERASE] = s[C_WERASE];
82284260Sobrien#endif /* VWERASE */
82384260Sobrien#ifdef VSUSP
82484260Sobrien	td->c_cc[VSUSP] = s[C_SUSP];
82584260Sobrien#endif /* VSUSP */
82684260Sobrien#ifdef VDSUSP
82784260Sobrien	td->c_cc[VDSUSP] = s[C_DSUSP];
82884260Sobrien#endif /* VDSUSP */
82984260Sobrien#ifdef VREPRINT
83084260Sobrien	td->c_cc[VREPRINT] = s[C_REPRINT];
83184260Sobrien#endif /* VREPRINT */
83284260Sobrien#ifdef VDISCARD
83384260Sobrien	td->c_cc[VDISCARD] = s[C_DISCARD];
83484260Sobrien#endif /* VDISCARD */
83584260Sobrien#ifdef VLNEXT
83684260Sobrien	td->c_cc[VLNEXT] = s[C_LNEXT];
83784260Sobrien#endif /* VLNEXT */
83884260Sobrien#ifdef VSTATUS
83984260Sobrien	td->c_cc[VSTATUS] = s[C_STATUS];
84084260Sobrien#endif /* VSTATUS */
84184260Sobrien#ifdef VPAGE
84284260Sobrien	td->c_cc[VPAGE] = s[C_PAGE];
84384260Sobrien#endif /* VPAGE */
84484260Sobrien#ifdef VPGOFF
84584260Sobrien	td->c_cc[VPGOFF] = s[C_PGOFF];
84684260Sobrien#endif /* VPGOFF */
84784260Sobrien#ifdef VKILL2
84884260Sobrien	td->c_cc[VKILL2] = s[C_KILL2];
84984260Sobrien#endif /* VKILL2 */
85084260Sobrien#ifdef VMIN
85184260Sobrien	td->c_cc[VMIN] = s[C_MIN];
85284260Sobrien#endif /* VMIN */
85384260Sobrien#ifdef VTIME
85484260Sobrien	td->c_cc[VTIME] = s[C_TIME];
85584260Sobrien#endif /* VTIME */
85684260Sobrien}				/* tty__setchar */
8571573Srgrimes
85884260Sobrien
8591573Srgrimes/* tty_bind_char():
8601573Srgrimes *	Rebind the editline functions
8611573Srgrimes */
8621573Srgrimesprotected void
86384260Sobrientty_bind_char(EditLine *el, int force)
8641573Srgrimes{
8651573Srgrimes
86684260Sobrien	unsigned char *t_n = el->el_tty.t_c[ED_IO];
86784260Sobrien	unsigned char *t_o = el->el_tty.t_ed.c_cc;
86884260Sobrien	unsigned char new[2], old[2];
86984260Sobrien	const ttymap_t *tp;
87084260Sobrien	el_action_t *map, *alt;
87184260Sobrien	const el_action_t *dmap, *dalt;
87284260Sobrien	new[1] = old[1] = '\0';
8731573Srgrimes
87484260Sobrien	map = el->el_map.key;
87584260Sobrien	alt = el->el_map.alt;
87684260Sobrien	if (el->el_map.type == MAP_VI) {
87784260Sobrien		dmap = el->el_map.vii;
87884260Sobrien		dalt = el->el_map.vic;
87984260Sobrien	} else {
88084260Sobrien		dmap = el->el_map.emacs;
88184260Sobrien		dalt = NULL;
88284260Sobrien	}
8831573Srgrimes
88484260Sobrien	for (tp = tty_map; tp->nch != -1; tp++) {
88584260Sobrien		new[0] = t_n[tp->nch];
88684260Sobrien		old[0] = t_o[tp->och];
88784260Sobrien		if (new[0] == old[0] && !force)
88884260Sobrien			continue;
88984260Sobrien		/* Put the old default binding back, and set the new binding */
89084260Sobrien		key_clear(el, map, (char *)old);
89184260Sobrien		map[old[0]] = dmap[old[0]];
89284260Sobrien		key_clear(el, map, (char *)new);
89384260Sobrien		/* MAP_VI == 1, MAP_EMACS == 0... */
89484260Sobrien		map[new[0]] = tp->bind[el->el_map.type];
89584260Sobrien		if (dalt) {
89684260Sobrien			key_clear(el, alt, (char *)old);
89784260Sobrien			alt[old[0]] = dalt[old[0]];
89884260Sobrien			key_clear(el, alt, (char *)new);
89984260Sobrien			alt[new[0]] = tp->bind[el->el_map.type + 1];
90084260Sobrien		}
9011573Srgrimes	}
9021573Srgrimes}
9031573Srgrimes
90484260Sobrien
9051573Srgrimes/* tty_rawmode():
9061573Srgrimes * 	Set terminal into 1 character at a time mode.
9071573Srgrimes */
9081573Srgrimesprotected int
90984260Sobrientty_rawmode(EditLine *el)
9101573Srgrimes{
9111573Srgrimes
91284260Sobrien	if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
91384260Sobrien		return (0);
91484260Sobrien
91584260Sobrien	if (el->el_flags & EDIT_DISABLED)
91684260Sobrien		return (0);
91784260Sobrien
91884260Sobrien	if (tty_getty(el, &el->el_tty.t_ts) == -1) {
9191573Srgrimes#ifdef DEBUG_TTY
92084260Sobrien		(void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
92184260Sobrien		    strerror(errno));
9221573Srgrimes#endif /* DEBUG_TTY */
92384260Sobrien		return (-1);
9241573Srgrimes	}
92584260Sobrien	/*
92684260Sobrien         * We always keep up with the eight bit setting and the speed of the
92784260Sobrien         * tty. But only we only believe changes that are made to cooked mode!
92884260Sobrien         */
92984260Sobrien	el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
93084260Sobrien	el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
9311573Srgrimes
93284260Sobrien	if (tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
93384260Sobrien		(void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
93484260Sobrien		(void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
9351573Srgrimes	}
93684260Sobrien	if (tty__cooked_mode(&el->el_tty.t_ts)) {
93784260Sobrien		if ((el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) &&
93884260Sobrien		    (el->el_tty.t_ts.c_cflag != el->el_tty.t_ed.c_cflag)) {
93984260Sobrien			el->el_tty.t_ed.c_cflag =
94084260Sobrien			    el->el_tty.t_ts.c_cflag;
94184260Sobrien			el->el_tty.t_ed.c_cflag &=
94284260Sobrien			    ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
94384260Sobrien			el->el_tty.t_ed.c_cflag |=
94484260Sobrien			    el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
94584260Sobrien		}
94684260Sobrien		if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
94784260Sobrien		    (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
94884260Sobrien			el->el_tty.t_ed.c_lflag =
94984260Sobrien			    el->el_tty.t_ts.c_lflag;
95084260Sobrien			el->el_tty.t_ed.c_lflag &=
95184260Sobrien			    ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
95284260Sobrien			el->el_tty.t_ed.c_lflag |=
95384260Sobrien			    el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
95484260Sobrien		}
95584260Sobrien		if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
95684260Sobrien		    (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
95784260Sobrien			el->el_tty.t_ed.c_iflag =
95884260Sobrien			    el->el_tty.t_ts.c_iflag;
95984260Sobrien			el->el_tty.t_ed.c_iflag &=
96084260Sobrien			    ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
96184260Sobrien			el->el_tty.t_ed.c_iflag |=
96284260Sobrien			    el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
96384260Sobrien		}
96484260Sobrien		if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
96584260Sobrien		    (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
96684260Sobrien			el->el_tty.t_ed.c_oflag =
96784260Sobrien			    el->el_tty.t_ts.c_oflag;
96884260Sobrien			el->el_tty.t_ed.c_oflag &=
96984260Sobrien			    ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
97084260Sobrien			el->el_tty.t_ed.c_oflag |=
97184260Sobrien			    el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
97284260Sobrien		}
97384260Sobrien		if (tty__gettabs(&el->el_tty.t_ex) == 0)
97484260Sobrien			el->el_tty.t_tabs = 0;
97584260Sobrien		else
97684260Sobrien			el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
9771573Srgrimes
97884260Sobrien		{
97984260Sobrien			int i;
9801573Srgrimes
98184260Sobrien			tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
98284260Sobrien			/*
98384260Sobrien		         * Check if the user made any changes.
98484260Sobrien		         * If he did, then propagate the changes to the
98584260Sobrien		         * edit and execute data structures.
98684260Sobrien		         */
98784260Sobrien			for (i = 0; i < C_NCC; i++)
98884260Sobrien				if (el->el_tty.t_c[TS_IO][i] !=
98984260Sobrien				    el->el_tty.t_c[EX_IO][i])
99084260Sobrien					break;
9911573Srgrimes
99284260Sobrien			if (i != C_NCC) {
99384260Sobrien				/*
99484260Sobrien				 * Propagate changes only to the unprotected
99584260Sobrien				 * chars that have been modified just now.
99684260Sobrien				 */
99784260Sobrien				for (i = 0; i < C_NCC; i++) {
99884260Sobrien					if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
99984260Sobrien					    && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
100084260Sobrien						el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
100184260Sobrien					if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
100284260Sobrien						el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
100384260Sobrien				}
100484260Sobrien				tty_bind_char(el, 0);
100584260Sobrien				tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
10061573Srgrimes
100784260Sobrien				for (i = 0; i < C_NCC; i++) {
100884260Sobrien					if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
100984260Sobrien					    && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
101084260Sobrien						el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
101184260Sobrien					if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
101284260Sobrien						el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
101384260Sobrien				}
101484260Sobrien			}
10151573Srgrimes		}
10161573Srgrimes	}
10171573Srgrimes
101884260Sobrien	if (el->el_tty.t_mode == EX_IO)
101984260Sobrien		el->el_tty.t_ex = el->el_tty.t_ts;
102063947Sache
1021268782Spfg	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
10221573Srgrimes#ifdef DEBUG_TTY
102384260Sobrien		(void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
102484260Sobrien		    strerror(errno));
10251573Srgrimes#endif /* DEBUG_TTY */
102684260Sobrien		return (-1);
102784260Sobrien	}
102884260Sobrien	el->el_tty.t_mode = ED_IO;
102984260Sobrien	return (0);
103084260Sobrien}
10311573Srgrimes
10321573Srgrimes
10331573Srgrimes/* tty_cookedmode():
10341573Srgrimes *	Set the tty back to normal mode
10351573Srgrimes */
10361573Srgrimesprotected int
103784260Sobrientty_cookedmode(EditLine *el)
10381573Srgrimes{				/* set tty in normal setup */
10391573Srgrimes
104084260Sobrien	if (el->el_tty.t_mode == EX_IO)
104184260Sobrien		return (0);
104284260Sobrien
104384260Sobrien	if (el->el_flags & EDIT_DISABLED)
104484260Sobrien		return (0);
104584260Sobrien
1046268782Spfg	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
10471573Srgrimes#ifdef DEBUG_TTY
104884260Sobrien		(void) fprintf(el->el_errfile,
104984260Sobrien		    "tty_cookedmode: tty_setty: %s\n",
105084260Sobrien		    strerror(errno));
10511573Srgrimes#endif /* DEBUG_TTY */
105284260Sobrien		return (-1);
105384260Sobrien	}
105484260Sobrien	el->el_tty.t_mode = EX_IO;
105584260Sobrien	return (0);
105684260Sobrien}
10571573Srgrimes
10581573Srgrimes
10591573Srgrimes/* tty_quotemode():
10601573Srgrimes *	Turn on quote mode
10611573Srgrimes */
10621573Srgrimesprotected int
106384260Sobrientty_quotemode(EditLine *el)
10641573Srgrimes{
106584260Sobrien	if (el->el_tty.t_mode == QU_IO)
106684260Sobrien		return (0);
10671573Srgrimes
106884260Sobrien	el->el_tty.t_qu = el->el_tty.t_ed;
10691573Srgrimes
107084260Sobrien	el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
107184260Sobrien	el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
10721573Srgrimes
107384260Sobrien	el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
107484260Sobrien	el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
10751573Srgrimes
107684260Sobrien	el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
107784260Sobrien	el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
10781573Srgrimes
107984260Sobrien	el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
108084260Sobrien	el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
10811573Srgrimes
1082268782Spfg	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
10831573Srgrimes#ifdef DEBUG_TTY
108484260Sobrien		(void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
108584260Sobrien		    strerror(errno));
10861573Srgrimes#endif /* DEBUG_TTY */
108784260Sobrien		return (-1);
108884260Sobrien	}
108984260Sobrien	el->el_tty.t_mode = QU_IO;
109084260Sobrien	return (0);
109184260Sobrien}
10921573Srgrimes
10931573Srgrimes
10941573Srgrimes/* tty_noquotemode():
10951573Srgrimes *	Turn off quote mode
10961573Srgrimes */
10971573Srgrimesprotected int
109884260Sobrientty_noquotemode(EditLine *el)
10991573Srgrimes{
110084260Sobrien
110184260Sobrien	if (el->el_tty.t_mode != QU_IO)
110284260Sobrien		return (0);
1103268782Spfg	if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
11041573Srgrimes#ifdef DEBUG_TTY
110584260Sobrien		(void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
110684260Sobrien		    strerror(errno));
11071573Srgrimes#endif /* DEBUG_TTY */
110884260Sobrien		return (-1);
110984260Sobrien	}
111084260Sobrien	el->el_tty.t_mode = ED_IO;
111184260Sobrien	return (0);
11121573Srgrimes}
11131573Srgrimes
111484260Sobrien
11151573Srgrimes/* tty_stty():
11161573Srgrimes *	Stty builtin
11171573Srgrimes */
11181573Srgrimesprotected int
11191573Srgrimes/*ARGSUSED*/
1120148834Sstefanftty_stty(EditLine *el, int argc __unused, const char **argv)
11211573Srgrimes{
112284260Sobrien	const ttymodes_t *m;
1123148834Sstefanf	char x;
112484260Sobrien	int aflag = 0;
1125148834Sstefanf	const char *s, *d;
1126148834Sstefanf	const char *name;
1127148834Sstefanf	struct termios *tios = &el->el_tty.t_ex;
112884260Sobrien	int z = EX_IO;
11291573Srgrimes
113084260Sobrien	if (argv == NULL)
113184260Sobrien		return (-1);
113284260Sobrien	name = *argv++;
11331573Srgrimes
113484260Sobrien	while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
113584260Sobrien		switch (argv[0][1]) {
113684260Sobrien		case 'a':
113784260Sobrien			aflag++;
113884260Sobrien			argv++;
113984260Sobrien			break;
114084260Sobrien		case 'd':
114184260Sobrien			argv++;
1142148834Sstefanf			tios = &el->el_tty.t_ed;
114384260Sobrien			z = ED_IO;
114484260Sobrien			break;
114584260Sobrien		case 'x':
114684260Sobrien			argv++;
1147148834Sstefanf			tios = &el->el_tty.t_ex;
114884260Sobrien			z = EX_IO;
114984260Sobrien			break;
115084260Sobrien		case 'q':
115184260Sobrien			argv++;
1152148834Sstefanf			tios = &el->el_tty.t_ts;
115384260Sobrien			z = QU_IO;
115484260Sobrien			break;
115584260Sobrien		default:
115684260Sobrien			(void) fprintf(el->el_errfile,
115784260Sobrien			    "%s: Unknown switch `%c'.\n",
115884260Sobrien			    name, argv[0][1]);
115984260Sobrien			return (-1);
116084260Sobrien		}
11611573Srgrimes
116284260Sobrien	if (!argv || !*argv) {
116384260Sobrien		int i = -1;
1164268782Spfg		size_t len = 0, st = 0, cu;
116584260Sobrien		for (m = ttymodes; m->m_name; m++) {
116684260Sobrien			if (m->m_type != i) {
116784260Sobrien				(void) fprintf(el->el_outfile, "%s%s",
116884260Sobrien				    i != -1 ? "\n" : "",
116984260Sobrien				    el->el_tty.t_t[z][m->m_type].t_name);
117084260Sobrien				i = m->m_type;
117184260Sobrien				st = len =
117284260Sobrien				    strlen(el->el_tty.t_t[z][m->m_type].t_name);
117384260Sobrien			}
1174167464Sstefanf			if (i != -1) {
1175167464Sstefanf			    x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1176167464Sstefanf				?  '+' : '\0';
1177167464Sstefanf			    x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1178167464Sstefanf				? '-' : x;
1179167464Sstefanf			} else {
1180167464Sstefanf			    x = '\0';
1181167464Sstefanf			}
11821573Srgrimes
118384260Sobrien			if (x != '\0' || aflag) {
11841573Srgrimes
118584260Sobrien				cu = strlen(m->m_name) + (x != '\0') + 1;
11861573Srgrimes
1187268782Spfg				if (len + cu >= (size_t)el->el_term.t_size.h) {
118884260Sobrien					(void) fprintf(el->el_outfile, "\n%*s",
1189268782Spfg					    (int)st, "");
119084260Sobrien					len = st + cu;
119184260Sobrien				} else
119284260Sobrien					len += cu;
11931573Srgrimes
119484260Sobrien				if (x != '\0')
119584260Sobrien					(void) fprintf(el->el_outfile, "%c%s ",
119684260Sobrien					    x, m->m_name);
119784260Sobrien				else
119884260Sobrien					(void) fprintf(el->el_outfile, "%s ",
119984260Sobrien					    m->m_name);
120084260Sobrien			}
12011573Srgrimes		}
120284260Sobrien		(void) fprintf(el->el_outfile, "\n");
120384260Sobrien		return (0);
12041573Srgrimes	}
120584260Sobrien	while (argv && (s = *argv++)) {
1206148834Sstefanf		const char *p;
120784260Sobrien		switch (*s) {
120884260Sobrien		case '+':
120984260Sobrien		case '-':
121084260Sobrien			x = *s++;
121184260Sobrien			break;
121284260Sobrien		default:
121384260Sobrien			x = '\0';
121484260Sobrien			break;
121584260Sobrien		}
121684260Sobrien		d = s;
1217148834Sstefanf		p = strchr(s, '=');
121884260Sobrien		for (m = ttymodes; m->m_name; m++)
1219148834Sstefanf			if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) :
1220148834Sstefanf			    strcmp(m->m_name, d)) == 0 &&
1221148834Sstefanf			    (p == NULL || m->m_type == MD_CHAR))
122284260Sobrien				break;
12231573Srgrimes
122484260Sobrien		if (!m->m_name) {
122584260Sobrien			(void) fprintf(el->el_errfile,
122684260Sobrien			    "%s: Invalid argument `%s'.\n", name, d);
122784260Sobrien			return (-1);
122884260Sobrien		}
1229148834Sstefanf		if (p) {
1230148834Sstefanf			int c = ffs((int)m->m_value);
1231148834Sstefanf			int v = *++p ? parse__escape((const char **) &p) :
1232148834Sstefanf			    el->el_tty.t_vdisable;
1233268782Spfg			assert(c != 0);
1234268782Spfg			c--;
1235148834Sstefanf			c = tty__getcharindex(c);
1236148834Sstefanf			assert(c != -1);
1237148834Sstefanf			tios->c_cc[c] = v;
1238148834Sstefanf			continue;
1239148834Sstefanf		}
124084260Sobrien		switch (x) {
124184260Sobrien		case '+':
124284260Sobrien			el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
124384260Sobrien			el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
124484260Sobrien			break;
124584260Sobrien		case '-':
124684260Sobrien			el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
124784260Sobrien			el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
124884260Sobrien			break;
124984260Sobrien		default:
125084260Sobrien			el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
125184260Sobrien			el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
125284260Sobrien			break;
125384260Sobrien		}
12541573Srgrimes	}
1255268782Spfg
1256268782Spfg	if (el->el_tty.t_mode == z) {
1257268782Spfg		if (tty_setty(el, TCSADRAIN, tios) == -1) {
1258268782Spfg#ifdef DEBUG_TTY
1259268782Spfg			(void) fprintf(el->el_errfile,
1260268782Spfg			    "tty_stty: tty_setty: %s\n", strerror(errno));
1261268782Spfg#endif /* DEBUG_TTY */
1262268782Spfg			return (-1);
1263268782Spfg		}
1264268782Spfg	}
1265268782Spfg
126684260Sobrien	return (0);
126784260Sobrien}
12681573Srgrimes
12691573Srgrimes
12701573Srgrimes#ifdef notyet
12711573Srgrimes/* tty_printchar():
12721573Srgrimes *	DEbugging routine to print the tty characters
12731573Srgrimes */
12741573Srgrimesprivate void
127584260Sobrientty_printchar(EditLine *el, unsigned char *s)
12761573Srgrimes{
127784260Sobrien	ttyperm_t *m;
127884260Sobrien	int i;
12791573Srgrimes
128084260Sobrien	for (i = 0; i < C_NCC; i++) {
128184260Sobrien		for (m = el->el_tty.t_t; m->m_name; m++)
128284260Sobrien			if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
128384260Sobrien				break;
128484260Sobrien		if (m->m_name)
128584260Sobrien			(void) fprintf(el->el_errfile, "%s ^%c ",
128684260Sobrien			    m->m_name, s[i] + 'A' - 1);
128784260Sobrien		if (i % 5 == 0)
128884260Sobrien			(void) fprintf(el->el_errfile, "\n");
128984260Sobrien	}
129084260Sobrien	(void) fprintf(el->el_errfile, "\n");
12911573Srgrimes}
12921573Srgrimes#endif /* notyet */
1293