xref: /freebsd/sys/kern/tty_compat.c (revision 29363fb446372cb3f10bc98664e9767c53fbb457)
1df8bae1dSRodney W. Grimes /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
4df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1991, 1993
5df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
6df8bae1dSRodney W. Grimes  *
7df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
8df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
9df8bae1dSRodney W. Grimes  * are met:
10df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
11df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
12df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
13df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
14df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
1569a28758SEd Maste  * 3. Neither the name of the University nor the names of its contributors
16df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
17df8bae1dSRodney W. Grimes  *    without specific prior written permission.
18df8bae1dSRodney W. Grimes  *
19df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
30df8bae1dSRodney W. Grimes  */
31df8bae1dSRodney W. Grimes 
32677b542eSDavid E. O'Brien #include <sys/cdefs.h>
33df8bae1dSRodney W. Grimes /*
34df8bae1dSRodney W. Grimes  * mapping routines for old line discipline (yuck)
35df8bae1dSRodney W. Grimes  */
36df8bae1dSRodney W. Grimes 
37df8bae1dSRodney W. Grimes #include <sys/param.h>
38df8bae1dSRodney W. Grimes #include <sys/systm.h>
39afd2f6c2SBruce Evans #include <sys/ioctl_compat.h>
40df8bae1dSRodney W. Grimes #include <sys/tty.h>
41df8bae1dSRodney W. Grimes #include <sys/kernel.h>
4287b6de2bSPoul-Henning Kamp #include <sys/sysctl.h>
43df8bae1dSRodney W. Grimes 
44bc093719SEd Schouten struct speedtab {
45bc093719SEd Schouten 	int sp_speed;			/* Speed. */
46bc093719SEd Schouten 	int sp_code;			/* Code. */
47bc093719SEd Schouten };
48bc093719SEd Schouten 
494d77a549SAlfred Perlstein static int ttcompatgetflags(struct tty *tp);
504d77a549SAlfred Perlstein static void ttcompatsetflags(struct tty *tp, struct termios *t);
514d77a549SAlfred Perlstein static void ttcompatsetlflags(struct tty *tp, struct termios *t);
524d77a549SAlfred Perlstein static int ttcompatspeedtab(int speed, struct speedtab *table);
5326f9a767SRodney W. Grimes 
5487b6de2bSPoul-Henning Kamp static int ttydebug = 0;
5587b6de2bSPoul-Henning Kamp SYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, "");
56df8bae1dSRodney W. Grimes 
57df8bae1dSRodney W. Grimes static struct speedtab compatspeeds[] = {
585b96a5b9SBruce Evans #define MAX_SPEED	17
595b96a5b9SBruce Evans 	{ 115200, 17 },
605b96a5b9SBruce Evans 	{ 57600, 16 },
61df8bae1dSRodney W. Grimes 	{ 38400, 15 },
62df8bae1dSRodney W. Grimes 	{ 19200, 14 },
63df8bae1dSRodney W. Grimes 	{ 9600,	13 },
64df8bae1dSRodney W. Grimes 	{ 4800,	12 },
65df8bae1dSRodney W. Grimes 	{ 2400,	11 },
66df8bae1dSRodney W. Grimes 	{ 1800,	10 },
67df8bae1dSRodney W. Grimes 	{ 1200,	9 },
68df8bae1dSRodney W. Grimes 	{ 600,	8 },
69df8bae1dSRodney W. Grimes 	{ 300,	7 },
70df8bae1dSRodney W. Grimes 	{ 200,	6 },
71df8bae1dSRodney W. Grimes 	{ 150,	5 },
72df8bae1dSRodney W. Grimes 	{ 134,	4 },
73df8bae1dSRodney W. Grimes 	{ 110,	3 },
74df8bae1dSRodney W. Grimes 	{ 75,	2 },
75df8bae1dSRodney W. Grimes 	{ 50,	1 },
76df8bae1dSRodney W. Grimes 	{ 0,	0 },
77df8bae1dSRodney W. Grimes 	{ -1,	-1 },
78df8bae1dSRodney W. Grimes };
79af2a00bbSAndrey A. Chernov static int compatspcodes[] = {
80af2a00bbSAndrey A. Chernov 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
813b9a76f0SBruce Evans 	1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
82af2a00bbSAndrey A. Chernov };
83df8bae1dSRodney W. Grimes 
843b9a76f0SBruce Evans static int
ttcompatspeedtab(int speed,struct speedtab * table)8555dbc267SPoul-Henning Kamp ttcompatspeedtab(int speed, struct speedtab *table)
864e5f7358SAndrey A. Chernov {
874e5f7358SAndrey A. Chernov 	if (speed == 0)
884e5f7358SAndrey A. Chernov 		return (0); /* hangup */
894e5f7358SAndrey A. Chernov 	for ( ; table->sp_speed > 0; table++)
904e5f7358SAndrey A. Chernov 		if (table->sp_speed <= speed) /* nearest one, rounded down */
914e5f7358SAndrey A. Chernov 			return (table->sp_code);
924e5f7358SAndrey A. Chernov 	return (1); /* 50, min and not hangup */
934e5f7358SAndrey A. Chernov }
944e5f7358SAndrey A. Chernov 
9551514bc4SPoul-Henning Kamp static int
ttsetcompat(struct tty * tp,u_long * com,caddr_t data,struct termios * term)9655dbc267SPoul-Henning Kamp ttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term)
970a247e7dSAndrey A. Chernov {
980a247e7dSAndrey A. Chernov 	switch (*com) {
990a247e7dSAndrey A. Chernov 	case TIOCSETP:
1000a247e7dSAndrey A. Chernov 	case TIOCSETN: {
10155dbc267SPoul-Henning Kamp 		struct sgttyb *sg = (struct sgttyb *)data;
1020a247e7dSAndrey A. Chernov 		int speed;
1030a247e7dSAndrey A. Chernov 
1040a247e7dSAndrey A. Chernov 		if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
1050a247e7dSAndrey A. Chernov 			return(EINVAL);
106bc093719SEd Schouten 		else if (speed != ttcompatspeedtab(tp->t_termios.c_ispeed,
107bc093719SEd Schouten 		    compatspeeds))
108af2a00bbSAndrey A. Chernov 			term->c_ispeed = compatspcodes[speed];
109e581051dSAndrey A. Chernov 		else
110bc093719SEd Schouten 			term->c_ispeed = tp->t_termios.c_ispeed;
1110a247e7dSAndrey A. Chernov 		if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
1120a247e7dSAndrey A. Chernov 			return(EINVAL);
113bc093719SEd Schouten 		else if (speed != ttcompatspeedtab(tp->t_termios.c_ospeed,
114bc093719SEd Schouten 		    compatspeeds))
115af2a00bbSAndrey A. Chernov 			term->c_ospeed = compatspcodes[speed];
116e581051dSAndrey A. Chernov 		else
117bc093719SEd Schouten 			term->c_ospeed = tp->t_termios.c_ospeed;
1180a247e7dSAndrey A. Chernov 		term->c_cc[VERASE] = sg->sg_erase;
1190a247e7dSAndrey A. Chernov 		term->c_cc[VKILL] = sg->sg_kill;
1202bda9238SEd Schouten 		tp->t_compatflags = (tp->t_compatflags&0xffff0000) |
1212bda9238SEd Schouten 		    (sg->sg_flags&0xffff);
1220a247e7dSAndrey A. Chernov 		ttcompatsetflags(tp, term);
1230a247e7dSAndrey A. Chernov 		*com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA;
1240a247e7dSAndrey A. Chernov 		break;
1250a247e7dSAndrey A. Chernov 	}
1260a247e7dSAndrey A. Chernov 	case TIOCSETC: {
1270a247e7dSAndrey A. Chernov 		struct tchars *tc = (struct tchars *)data;
12855dbc267SPoul-Henning Kamp 		cc_t *cc;
1290a247e7dSAndrey A. Chernov 
1300a247e7dSAndrey A. Chernov 		cc = term->c_cc;
1310a247e7dSAndrey A. Chernov 		cc[VINTR] = tc->t_intrc;
1320a247e7dSAndrey A. Chernov 		cc[VQUIT] = tc->t_quitc;
1330a247e7dSAndrey A. Chernov 		cc[VSTART] = tc->t_startc;
1340a247e7dSAndrey A. Chernov 		cc[VSTOP] = tc->t_stopc;
1350a247e7dSAndrey A. Chernov 		cc[VEOF] = tc->t_eofc;
1360a247e7dSAndrey A. Chernov 		cc[VEOL] = tc->t_brkc;
137a77c37b6SOlivier Houchard 		if (tc->t_brkc == (char)_POSIX_VDISABLE)
1380a247e7dSAndrey A. Chernov 			cc[VEOL2] = _POSIX_VDISABLE;
1390a247e7dSAndrey A. Chernov 		*com = TIOCSETA;
1400a247e7dSAndrey A. Chernov 		break;
1410a247e7dSAndrey A. Chernov 	}
1420a247e7dSAndrey A. Chernov 	case TIOCSLTC: {
1430a247e7dSAndrey A. Chernov 		struct ltchars *ltc = (struct ltchars *)data;
14455dbc267SPoul-Henning Kamp 		cc_t *cc;
1450a247e7dSAndrey A. Chernov 
1460a247e7dSAndrey A. Chernov 		cc = term->c_cc;
1470a247e7dSAndrey A. Chernov 		cc[VSUSP] = ltc->t_suspc;
1480a247e7dSAndrey A. Chernov 		cc[VDSUSP] = ltc->t_dsuspc;
1490a247e7dSAndrey A. Chernov 		cc[VREPRINT] = ltc->t_rprntc;
1500a247e7dSAndrey A. Chernov 		cc[VDISCARD] = ltc->t_flushc;
1510a247e7dSAndrey A. Chernov 		cc[VWERASE] = ltc->t_werasc;
1520a247e7dSAndrey A. Chernov 		cc[VLNEXT] = ltc->t_lnextc;
1530a247e7dSAndrey A. Chernov 		*com = TIOCSETA;
1540a247e7dSAndrey A. Chernov 		break;
1550a247e7dSAndrey A. Chernov 	}
1560a247e7dSAndrey A. Chernov 	case TIOCLBIS:
1570a247e7dSAndrey A. Chernov 	case TIOCLBIC:
1580a247e7dSAndrey A. Chernov 	case TIOCLSET:
1590a247e7dSAndrey A. Chernov 		if (*com == TIOCLSET)
1602bda9238SEd Schouten 			tp->t_compatflags = (tp->t_compatflags&0xffff) |
1612bda9238SEd Schouten 			    *(int *)data<<16;
1620a247e7dSAndrey A. Chernov 		else {
1632bda9238SEd Schouten 			tp->t_compatflags = (ttcompatgetflags(tp)&0xffff0000) |
1642bda9238SEd Schouten 			    (tp->t_compatflags&0xffff);
1650a247e7dSAndrey A. Chernov 			if (*com == TIOCLBIS)
1662bda9238SEd Schouten 				tp->t_compatflags |= *(int *)data<<16;
1670a247e7dSAndrey A. Chernov 			else
1682bda9238SEd Schouten 				tp->t_compatflags &= ~(*(int *)data<<16);
1690a247e7dSAndrey A. Chernov 		}
1700a247e7dSAndrey A. Chernov 		ttcompatsetlflags(tp, term);
1710a247e7dSAndrey A. Chernov 		*com = TIOCSETA;
1720a247e7dSAndrey A. Chernov 		break;
1730a247e7dSAndrey A. Chernov 	}
1740a247e7dSAndrey A. Chernov 	return 0;
1750a247e7dSAndrey A. Chernov }
1760a247e7dSAndrey A. Chernov 
177df8bae1dSRodney W. Grimes /*ARGSUSED*/
17826f9a767SRodney W. Grimes int
tty_ioctl_compat(struct tty * tp,u_long com,caddr_t data,int fflag,struct thread * td)179328d9d2cSEd Schouten tty_ioctl_compat(struct tty *tp, u_long com, caddr_t data, int fflag,
180328d9d2cSEd Schouten     struct thread *td)
181df8bae1dSRodney W. Grimes {
182df8bae1dSRodney W. Grimes 	switch (com) {
1830a247e7dSAndrey A. Chernov 	case TIOCSETP:
1840a247e7dSAndrey A. Chernov 	case TIOCSETN:
1850a247e7dSAndrey A. Chernov 	case TIOCSETC:
1860a247e7dSAndrey A. Chernov 	case TIOCSLTC:
1870a247e7dSAndrey A. Chernov 	case TIOCLBIS:
1880a247e7dSAndrey A. Chernov 	case TIOCLBIC:
1890a247e7dSAndrey A. Chernov 	case TIOCLSET: {
1900a247e7dSAndrey A. Chernov 		struct termios term;
1910a247e7dSAndrey A. Chernov 		int error;
1920a247e7dSAndrey A. Chernov 
1930a247e7dSAndrey A. Chernov 		term = tp->t_termios;
1940a247e7dSAndrey A. Chernov 		if ((error = ttsetcompat(tp, &com, data, &term)) != 0)
1950a247e7dSAndrey A. Chernov 			return error;
196328d9d2cSEd Schouten 		return tty_ioctl(tp, com, &term, fflag, td);
1970a247e7dSAndrey A. Chernov 	}
198df8bae1dSRodney W. Grimes 	case TIOCGETP: {
19955dbc267SPoul-Henning Kamp 		struct sgttyb *sg = (struct sgttyb *)data;
200bc093719SEd Schouten 		cc_t *cc = tp->t_termios.c_cc;
201df8bae1dSRodney W. Grimes 
202bc093719SEd Schouten 		sg->sg_ospeed = ttcompatspeedtab(tp->t_termios.c_ospeed,
203bc093719SEd Schouten 		    compatspeeds);
204bc093719SEd Schouten 		if (tp->t_termios.c_ispeed == 0)
205df8bae1dSRodney W. Grimes 			sg->sg_ispeed = sg->sg_ospeed;
2064e5f7358SAndrey A. Chernov 		else
207bc093719SEd Schouten 			sg->sg_ispeed = ttcompatspeedtab(tp->t_termios.c_ispeed,
208bc093719SEd Schouten 			    compatspeeds);
209df8bae1dSRodney W. Grimes 		sg->sg_erase = cc[VERASE];
210df8bae1dSRodney W. Grimes 		sg->sg_kill = cc[VKILL];
2112bda9238SEd Schouten 		sg->sg_flags = tp->t_compatflags = ttcompatgetflags(tp);
212df8bae1dSRodney W. Grimes 		break;
213df8bae1dSRodney W. Grimes 	}
214df8bae1dSRodney W. Grimes 	case TIOCGETC: {
215df8bae1dSRodney W. Grimes 		struct tchars *tc = (struct tchars *)data;
216bc093719SEd Schouten 		cc_t *cc = tp->t_termios.c_cc;
217df8bae1dSRodney W. Grimes 
218df8bae1dSRodney W. Grimes 		tc->t_intrc = cc[VINTR];
219df8bae1dSRodney W. Grimes 		tc->t_quitc = cc[VQUIT];
220df8bae1dSRodney W. Grimes 		tc->t_startc = cc[VSTART];
221df8bae1dSRodney W. Grimes 		tc->t_stopc = cc[VSTOP];
222df8bae1dSRodney W. Grimes 		tc->t_eofc = cc[VEOF];
223df8bae1dSRodney W. Grimes 		tc->t_brkc = cc[VEOL];
224df8bae1dSRodney W. Grimes 		break;
225df8bae1dSRodney W. Grimes 	}
226df8bae1dSRodney W. Grimes 	case TIOCGLTC: {
227df8bae1dSRodney W. Grimes 		struct ltchars *ltc = (struct ltchars *)data;
228bc093719SEd Schouten 		cc_t *cc = tp->t_termios.c_cc;
229df8bae1dSRodney W. Grimes 
230df8bae1dSRodney W. Grimes 		ltc->t_suspc = cc[VSUSP];
231df8bae1dSRodney W. Grimes 		ltc->t_dsuspc = cc[VDSUSP];
232df8bae1dSRodney W. Grimes 		ltc->t_rprntc = cc[VREPRINT];
233df8bae1dSRodney W. Grimes 		ltc->t_flushc = cc[VDISCARD];
234df8bae1dSRodney W. Grimes 		ltc->t_werasc = cc[VWERASE];
235df8bae1dSRodney W. Grimes 		ltc->t_lnextc = cc[VLNEXT];
236df8bae1dSRodney W. Grimes 		break;
237df8bae1dSRodney W. Grimes 	}
238df8bae1dSRodney W. Grimes 	case TIOCLGET:
2392bda9238SEd Schouten 		tp->t_compatflags =
240dec3cc97SAndrey A. Chernov 		 (ttcompatgetflags(tp) & 0xffff0000UL)
2412bda9238SEd Schouten 		   | (tp->t_compatflags & 0xffff);
2422bda9238SEd Schouten 		*(int *)data = tp->t_compatflags>>16;
243df8bae1dSRodney W. Grimes 		if (ttydebug)
244df8bae1dSRodney W. Grimes 			printf("CLGET: returning %x\n", *(int *)data);
245df8bae1dSRodney W. Grimes 		break;
246df8bae1dSRodney W. Grimes 
247df8bae1dSRodney W. Grimes 	case OTIOCGETD:
248bc093719SEd Schouten 		*(int *)data = 2;
249df8bae1dSRodney W. Grimes 		break;
250df8bae1dSRodney W. Grimes 
251df8bae1dSRodney W. Grimes 	case OTIOCSETD: {
252df8bae1dSRodney W. Grimes 		int ldisczero = 0;
253df8bae1dSRodney W. Grimes 
254bc093719SEd Schouten 		return (tty_ioctl(tp, TIOCSETD,
255328d9d2cSEd Schouten 			*(int *)data == 2 ? (caddr_t)&ldisczero : data,
256328d9d2cSEd Schouten 			fflag, td));
257df8bae1dSRodney W. Grimes 	    }
258df8bae1dSRodney W. Grimes 
259*467e6276SBrooks Davis 	case OTIOCCONS: {
260*467e6276SBrooks Davis 		int one = 1;
261*467e6276SBrooks Davis 
262*467e6276SBrooks Davis 		return (tty_ioctl(tp, TIOCCONS, (caddr_t)&one, fflag, td));
263*467e6276SBrooks Davis 	}
264df8bae1dSRodney W. Grimes 
265df8bae1dSRodney W. Grimes 	default:
266239b7b69SBruce Evans 		return (ENOIOCTL);
267df8bae1dSRodney W. Grimes 	}
268df8bae1dSRodney W. Grimes 	return (0);
269df8bae1dSRodney W. Grimes }
270df8bae1dSRodney W. Grimes 
271efb76ea6SAndrey A. Chernov static int
ttcompatgetflags(struct tty * tp)27255dbc267SPoul-Henning Kamp ttcompatgetflags(struct tty *tp)
273df8bae1dSRodney W. Grimes {
274bc093719SEd Schouten 	tcflag_t iflag	= tp->t_termios.c_iflag;
275bc093719SEd Schouten 	tcflag_t lflag	= tp->t_termios.c_lflag;
276bc093719SEd Schouten 	tcflag_t oflag	= tp->t_termios.c_oflag;
277bc093719SEd Schouten 	tcflag_t cflag	= tp->t_termios.c_cflag;
27855dbc267SPoul-Henning Kamp 	int flags = 0;
279df8bae1dSRodney W. Grimes 
280df8bae1dSRodney W. Grimes 	if (iflag&IXOFF)
281df8bae1dSRodney W. Grimes 		flags |= TANDEM;
282df8bae1dSRodney W. Grimes 	if (iflag&ICRNL || oflag&ONLCR)
283df8bae1dSRodney W. Grimes 		flags |= CRMOD;
284dec3cc97SAndrey A. Chernov 	if ((cflag&CSIZE) == CS8) {
285dec3cc97SAndrey A. Chernov 		flags |= PASS8;
286dec3cc97SAndrey A. Chernov 		if (iflag&ISTRIP)
287dec3cc97SAndrey A. Chernov 			flags |= ANYP;
288dec3cc97SAndrey A. Chernov 	}
289dec3cc97SAndrey A. Chernov 	else if (cflag&PARENB) {
290df8bae1dSRodney W. Grimes 		if (iflag&INPCK) {
291df8bae1dSRodney W. Grimes 			if (cflag&PARODD)
292df8bae1dSRodney W. Grimes 				flags |= ODDP;
293df8bae1dSRodney W. Grimes 			else
294df8bae1dSRodney W. Grimes 				flags |= EVENP;
295df8bae1dSRodney W. Grimes 		} else
296df8bae1dSRodney W. Grimes 			flags |= EVENP | ODDP;
297df8bae1dSRodney W. Grimes 	}
298df8bae1dSRodney W. Grimes 
299df8bae1dSRodney W. Grimes 	if ((lflag&ICANON) == 0) {
300df8bae1dSRodney W. Grimes 		/* fudge */
301dec3cc97SAndrey A. Chernov 		if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
302694ad0a9SSteve Price 		    || (cflag&(CSIZE|PARENB)) != CS8)
303df8bae1dSRodney W. Grimes 			flags |= CBREAK;
304df8bae1dSRodney W. Grimes 		else
305df8bae1dSRodney W. Grimes 			flags |= RAW;
306df8bae1dSRodney W. Grimes 	}
307694ad0a9SSteve Price 	if (!(flags&RAW) && !(oflag&OPOST) && (cflag&(CSIZE|PARENB)) == CS8)
308dec3cc97SAndrey A. Chernov 		flags |= LITOUT;
309df8bae1dSRodney W. Grimes 	if (cflag&MDMBUF)
310df8bae1dSRodney W. Grimes 		flags |= MDMBUF;
311df8bae1dSRodney W. Grimes 	if ((cflag&HUPCL) == 0)
312df8bae1dSRodney W. Grimes 		flags |= NOHANG;
313bc093719SEd Schouten 	if (oflag&TAB3)
314df8bae1dSRodney W. Grimes 		flags |= XTABS;
315df8bae1dSRodney W. Grimes 	if (lflag&ECHOE)
316df8bae1dSRodney W. Grimes 		flags |= CRTERA|CRTBS;
317df8bae1dSRodney W. Grimes 	if (lflag&ECHOKE)
318df8bae1dSRodney W. Grimes 		flags |= CRTKIL|CRTBS;
319df8bae1dSRodney W. Grimes 	if (lflag&ECHOPRT)
320df8bae1dSRodney W. Grimes 		flags |= PRTERA;
321df8bae1dSRodney W. Grimes 	if (lflag&ECHOCTL)
322df8bae1dSRodney W. Grimes 		flags |= CTLECH;
323df8bae1dSRodney W. Grimes 	if ((iflag&IXANY) == 0)
324df8bae1dSRodney W. Grimes 		flags |= DECCTQ;
325df8bae1dSRodney W. Grimes 	flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH);
326df8bae1dSRodney W. Grimes 	if (ttydebug)
327df8bae1dSRodney W. Grimes 		printf("getflags: %x\n", flags);
328df8bae1dSRodney W. Grimes 	return (flags);
329df8bae1dSRodney W. Grimes }
330df8bae1dSRodney W. Grimes 
331efb76ea6SAndrey A. Chernov static void
ttcompatsetflags(struct tty * tp,struct termios * t)33255dbc267SPoul-Henning Kamp ttcompatsetflags(struct tty *tp, struct termios *t)
333df8bae1dSRodney W. Grimes {
3342bda9238SEd Schouten 	int flags = tp->t_compatflags;
33555dbc267SPoul-Henning Kamp 	tcflag_t iflag	= t->c_iflag;
33655dbc267SPoul-Henning Kamp 	tcflag_t oflag	= t->c_oflag;
33755dbc267SPoul-Henning Kamp 	tcflag_t lflag	= t->c_lflag;
33855dbc267SPoul-Henning Kamp 	tcflag_t cflag	= t->c_cflag;
339df8bae1dSRodney W. Grimes 
340df8bae1dSRodney W. Grimes 	if (flags & RAW) {
341f1e302d4SAndrey A. Chernov 		iflag = IGNBRK;
342df8bae1dSRodney W. Grimes 		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
343df8bae1dSRodney W. Grimes 	} else {
344f1e302d4SAndrey A. Chernov 		iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
345df8bae1dSRodney W. Grimes 		iflag |= BRKINT|IXON|IMAXBEL;
346df8bae1dSRodney W. Grimes 		lflag |= ISIG|IEXTEN|ECHOCTL;	/* XXX was echoctl on ? */
347df8bae1dSRodney W. Grimes 		if (flags & XTABS)
348bc093719SEd Schouten 			oflag |= TAB3;
349df8bae1dSRodney W. Grimes 		else
350bc093719SEd Schouten 			oflag &= ~TAB3;
351df8bae1dSRodney W. Grimes 		if (flags & CBREAK)
352df8bae1dSRodney W. Grimes 			lflag &= ~ICANON;
353df8bae1dSRodney W. Grimes 		else
354df8bae1dSRodney W. Grimes 			lflag |= ICANON;
355df8bae1dSRodney W. Grimes 		if (flags&CRMOD) {
356df8bae1dSRodney W. Grimes 			iflag |= ICRNL;
357df8bae1dSRodney W. Grimes 			oflag |= ONLCR;
358df8bae1dSRodney W. Grimes 		} else {
359df8bae1dSRodney W. Grimes 			iflag &= ~ICRNL;
360df8bae1dSRodney W. Grimes 			oflag &= ~ONLCR;
361df8bae1dSRodney W. Grimes 		}
362df8bae1dSRodney W. Grimes 	}
363df8bae1dSRodney W. Grimes 	if (flags&ECHO)
364df8bae1dSRodney W. Grimes 		lflag |= ECHO;
365df8bae1dSRodney W. Grimes 	else
366df8bae1dSRodney W. Grimes 		lflag &= ~ECHO;
367df8bae1dSRodney W. Grimes 
368df8bae1dSRodney W. Grimes 	cflag &= ~(CSIZE|PARENB);
369dec3cc97SAndrey A. Chernov 	if (flags&(RAW|LITOUT|PASS8)) {
370df8bae1dSRodney W. Grimes 		cflag |= CS8;
371dec3cc97SAndrey A. Chernov 		if (!(flags&(RAW|PASS8))
372dec3cc97SAndrey A. Chernov 		    || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
373df8bae1dSRodney W. Grimes 			iflag |= ISTRIP;
374df8bae1dSRodney W. Grimes 		else
375df8bae1dSRodney W. Grimes 			iflag &= ~ISTRIP;
376dec3cc97SAndrey A. Chernov 		if (flags&(RAW|LITOUT))
377dec3cc97SAndrey A. Chernov 			oflag &= ~OPOST;
378dec3cc97SAndrey A. Chernov 		else
379dec3cc97SAndrey A. Chernov 			oflag |= OPOST;
380df8bae1dSRodney W. Grimes 	} else {
381df8bae1dSRodney W. Grimes 		cflag |= CS7|PARENB;
382df8bae1dSRodney W. Grimes 		iflag |= ISTRIP;
383dec3cc97SAndrey A. Chernov 		oflag |= OPOST;
384df8bae1dSRodney W. Grimes 	}
3853b9a76f0SBruce Evans 	/* XXX don't set INPCK if RAW or PASS8? */
386df8bae1dSRodney W. Grimes 	if ((flags&(EVENP|ODDP)) == EVENP) {
387df8bae1dSRodney W. Grimes 		iflag |= INPCK;
388df8bae1dSRodney W. Grimes 		cflag &= ~PARODD;
389df8bae1dSRodney W. Grimes 	} else if ((flags&(EVENP|ODDP)) == ODDP) {
390df8bae1dSRodney W. Grimes 		iflag |= INPCK;
391df8bae1dSRodney W. Grimes 		cflag |= PARODD;
392df8bae1dSRodney W. Grimes 	} else
393df8bae1dSRodney W. Grimes 		iflag &= ~INPCK;
394df8bae1dSRodney W. Grimes 	if (flags&TANDEM)
395df8bae1dSRodney W. Grimes 		iflag |= IXOFF;
396df8bae1dSRodney W. Grimes 	else
397df8bae1dSRodney W. Grimes 		iflag &= ~IXOFF;
39822055302SAndrey A. Chernov 	if ((flags&DECCTQ) == 0)
39922055302SAndrey A. Chernov 		iflag |= IXANY;
40022055302SAndrey A. Chernov 	else
40122055302SAndrey A. Chernov 		iflag &= ~IXANY;
402df8bae1dSRodney W. Grimes 	t->c_iflag = iflag;
403df8bae1dSRodney W. Grimes 	t->c_oflag = oflag;
404df8bae1dSRodney W. Grimes 	t->c_lflag = lflag;
405df8bae1dSRodney W. Grimes 	t->c_cflag = cflag;
406df8bae1dSRodney W. Grimes }
407df8bae1dSRodney W. Grimes 
408efb76ea6SAndrey A. Chernov static void
ttcompatsetlflags(struct tty * tp,struct termios * t)40955dbc267SPoul-Henning Kamp ttcompatsetlflags(struct tty *tp, struct termios *t)
410df8bae1dSRodney W. Grimes {
4112bda9238SEd Schouten 	int flags = tp->t_compatflags;
41255dbc267SPoul-Henning Kamp 	tcflag_t iflag	= t->c_iflag;
41355dbc267SPoul-Henning Kamp 	tcflag_t oflag	= t->c_oflag;
41455dbc267SPoul-Henning Kamp 	tcflag_t lflag	= t->c_lflag;
41555dbc267SPoul-Henning Kamp 	tcflag_t cflag	= t->c_cflag;
416df8bae1dSRodney W. Grimes 
417f1e302d4SAndrey A. Chernov 	iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
418df8bae1dSRodney W. Grimes 	if (flags&CRTERA)
419df8bae1dSRodney W. Grimes 		lflag |= ECHOE;
420df8bae1dSRodney W. Grimes 	else
421df8bae1dSRodney W. Grimes 		lflag &= ~ECHOE;
422df8bae1dSRodney W. Grimes 	if (flags&CRTKIL)
423df8bae1dSRodney W. Grimes 		lflag |= ECHOKE;
424df8bae1dSRodney W. Grimes 	else
425df8bae1dSRodney W. Grimes 		lflag &= ~ECHOKE;
426df8bae1dSRodney W. Grimes 	if (flags&PRTERA)
427df8bae1dSRodney W. Grimes 		lflag |= ECHOPRT;
428df8bae1dSRodney W. Grimes 	else
429df8bae1dSRodney W. Grimes 		lflag &= ~ECHOPRT;
430df8bae1dSRodney W. Grimes 	if (flags&CTLECH)
431df8bae1dSRodney W. Grimes 		lflag |= ECHOCTL;
432df8bae1dSRodney W. Grimes 	else
433df8bae1dSRodney W. Grimes 		lflag &= ~ECHOCTL;
43422055302SAndrey A. Chernov 	if (flags&TANDEM)
43522055302SAndrey A. Chernov 		iflag |= IXOFF;
43622055302SAndrey A. Chernov 	else
43722055302SAndrey A. Chernov 		iflag &= ~IXOFF;
438df8bae1dSRodney W. Grimes 	if ((flags&DECCTQ) == 0)
439df8bae1dSRodney W. Grimes 		iflag |= IXANY;
440df8bae1dSRodney W. Grimes 	else
441df8bae1dSRodney W. Grimes 		iflag &= ~IXANY;
442df8bae1dSRodney W. Grimes 	if (flags & MDMBUF)
443df8bae1dSRodney W. Grimes 		cflag |= MDMBUF;
444df8bae1dSRodney W. Grimes 	else
445df8bae1dSRodney W. Grimes 		cflag &= ~MDMBUF;
446df8bae1dSRodney W. Grimes 	if (flags&NOHANG)
447df8bae1dSRodney W. Grimes 		cflag &= ~HUPCL;
448df8bae1dSRodney W. Grimes 	else
449df8bae1dSRodney W. Grimes 		cflag |= HUPCL;
450df8bae1dSRodney W. Grimes 	lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
451df8bae1dSRodney W. Grimes 	lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
452dec3cc97SAndrey A. Chernov 
453dec3cc97SAndrey A. Chernov 	/*
454dec3cc97SAndrey A. Chernov 	 * The next if-else statement is copied from above so don't bother
455dec3cc97SAndrey A. Chernov 	 * checking it separately.  We could avoid fiddlling with the
456dec3cc97SAndrey A. Chernov 	 * character size if the mode is already RAW or if neither the
457dec3cc97SAndrey A. Chernov 	 * LITOUT bit or the PASS8 bit is being changed, but the delta of
458dec3cc97SAndrey A. Chernov 	 * the change is not available here and skipping the RAW case would
459dec3cc97SAndrey A. Chernov 	 * make the code different from above.
460dec3cc97SAndrey A. Chernov 	 */
461df8bae1dSRodney W. Grimes 	cflag &= ~(CSIZE|PARENB);
462dec3cc97SAndrey A. Chernov 	if (flags&(RAW|LITOUT|PASS8)) {
463df8bae1dSRodney W. Grimes 		cflag |= CS8;
464dec3cc97SAndrey A. Chernov 		if (!(flags&(RAW|PASS8))
465dec3cc97SAndrey A. Chernov 		    || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
466df8bae1dSRodney W. Grimes 			iflag |= ISTRIP;
467dec3cc97SAndrey A. Chernov 		else
468dec3cc97SAndrey A. Chernov 			iflag &= ~ISTRIP;
469dec3cc97SAndrey A. Chernov 		if (flags&(RAW|LITOUT))
470dec3cc97SAndrey A. Chernov 			oflag &= ~OPOST;
471dec3cc97SAndrey A. Chernov 		else
472dec3cc97SAndrey A. Chernov 			oflag |= OPOST;
473dec3cc97SAndrey A. Chernov 	} else {
474df8bae1dSRodney W. Grimes 		cflag |= CS7|PARENB;
475dec3cc97SAndrey A. Chernov 		iflag |= ISTRIP;
476df8bae1dSRodney W. Grimes 		oflag |= OPOST;
477df8bae1dSRodney W. Grimes 	}
478df8bae1dSRodney W. Grimes 	t->c_iflag = iflag;
479df8bae1dSRodney W. Grimes 	t->c_oflag = oflag;
480df8bae1dSRodney W. Grimes 	t->c_lflag = lflag;
481df8bae1dSRodney W. Grimes 	t->c_cflag = cflag;
482df8bae1dSRodney W. Grimes }
483