11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes *
291541Srgrimes *	@(#)tty_compat.c	8.1 (Berkeley) 6/10/93
301541Srgrimes */
311541Srgrimes
32116182Sobrien#include <sys/cdefs.h>
33116182Sobrien__FBSDID("$FreeBSD$");
34116182Sobrien
3531778Seivind#include "opt_compat.h"
3631778Seivind
378876Srgrimes/*
381541Srgrimes * mapping routines for old line discipline (yuck)
391541Srgrimes */
401541Srgrimes
411541Srgrimes#include <sys/param.h>
421541Srgrimes#include <sys/systm.h>
4324207Sbde#include <sys/ioctl_compat.h>
441541Srgrimes#include <sys/tty.h>
451541Srgrimes#include <sys/kernel.h>
4612819Sphk#include <sys/sysctl.h>
471541Srgrimes
48181905Sedstruct speedtab {
49181905Sed	int sp_speed;			/* Speed. */
50181905Sed	int sp_code;			/* Code. */
51181905Sed};
52181905Sed
5393076Sbdestatic int ttcompatgetflags(struct tty *tp);
5493076Sbdestatic void ttcompatsetflags(struct tty *tp, struct termios *t);
5593076Sbdestatic void ttcompatsetlflags(struct tty *tp, struct termios *t);
5693076Sbdestatic int ttcompatspeedtab(int speed, struct speedtab *table);
571549Srgrimes
5812819Sphkstatic int ttydebug = 0;
5912819SphkSYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, "");
601541Srgrimes
611541Srgrimesstatic struct speedtab compatspeeds[] = {
622271Sbde#define MAX_SPEED	17
632271Sbde	{ 115200, 17 },
642271Sbde	{ 57600, 16 },
651541Srgrimes	{ 38400, 15 },
661541Srgrimes	{ 19200, 14 },
671541Srgrimes	{ 9600,	13 },
681541Srgrimes	{ 4800,	12 },
691541Srgrimes	{ 2400,	11 },
701541Srgrimes	{ 1800,	10 },
711541Srgrimes	{ 1200,	9 },
721541Srgrimes	{ 600,	8 },
731541Srgrimes	{ 300,	7 },
741541Srgrimes	{ 200,	6 },
751541Srgrimes	{ 150,	5 },
761541Srgrimes	{ 134,	4 },
771541Srgrimes	{ 110,	3 },
781541Srgrimes	{ 75,	2 },
791541Srgrimes	{ 50,	1 },
801541Srgrimes	{ 0,	0 },
811541Srgrimes	{ -1,	-1 },
821541Srgrimes};
839851Sachestatic int compatspcodes[] = {
849851Sache	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
8512370Sbde	1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
869851Sache};
871541Srgrimes
8812370Sbdestatic int
89130840Sphkttcompatspeedtab(int speed, struct speedtab *table)
909859Sache{
919859Sache	if (speed == 0)
929859Sache		return (0); /* hangup */
939859Sache	for ( ; table->sp_speed > 0; table++)
949859Sache		if (table->sp_speed <= speed) /* nearest one, rounded down */
959859Sache			return (table->sp_code);
969859Sache	return (1); /* 50, min and not hangup */
979859Sache}
989859Sache
99151386Sphkstatic int
100130840Sphkttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term)
1011541Srgrimes{
1027758Sache	switch (*com) {
1031541Srgrimes	case TIOCSETP:
1041541Srgrimes	case TIOCSETN: {
105130840Sphk		struct sgttyb *sg = (struct sgttyb *)data;
1061541Srgrimes		int speed;
1071541Srgrimes
1082271Sbde		if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
1097581Sache			return(EINVAL);
110181905Sed		else if (speed != ttcompatspeedtab(tp->t_termios.c_ispeed,
111181905Sed		    compatspeeds))
1129861Sache			term->c_ispeed = compatspcodes[speed];
1131541Srgrimes		else
114181905Sed			term->c_ispeed = tp->t_termios.c_ispeed;
1152271Sbde		if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
1167581Sache			return(EINVAL);
117181905Sed		else if (speed != ttcompatspeedtab(tp->t_termios.c_ospeed,
118181905Sed		    compatspeeds))
1199861Sache			term->c_ospeed = compatspcodes[speed];
1201541Srgrimes		else
121181905Sed			term->c_ospeed = tp->t_termios.c_ospeed;
1227758Sache		term->c_cc[VERASE] = sg->sg_erase;
1237758Sache		term->c_cc[VKILL] = sg->sg_kill;
124182763Sed		tp->t_compatflags = (tp->t_compatflags&0xffff0000) |
125182763Sed		    (sg->sg_flags&0xffff);
1267758Sache		ttcompatsetflags(tp, term);
1277758Sache		*com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA;
1281541Srgrimes		break;
1291541Srgrimes	}
1301541Srgrimes	case TIOCSETC: {
1311541Srgrimes		struct tchars *tc = (struct tchars *)data;
132130840Sphk		cc_t *cc;
1331541Srgrimes
1347758Sache		cc = term->c_cc;
1351541Srgrimes		cc[VINTR] = tc->t_intrc;
1361541Srgrimes		cc[VQUIT] = tc->t_quitc;
1371541Srgrimes		cc[VSTART] = tc->t_startc;
1381541Srgrimes		cc[VSTOP] = tc->t_stopc;
1391541Srgrimes		cc[VEOF] = tc->t_eofc;
1401541Srgrimes		cc[VEOL] = tc->t_brkc;
141129035Scognet		if (tc->t_brkc == (char)_POSIX_VDISABLE)
1421541Srgrimes			cc[VEOL2] = _POSIX_VDISABLE;
1437758Sache		*com = TIOCSETA;
1447758Sache		break;
1451541Srgrimes	}
1461541Srgrimes	case TIOCSLTC: {
1471541Srgrimes		struct ltchars *ltc = (struct ltchars *)data;
148130840Sphk		cc_t *cc;
1491541Srgrimes
1507758Sache		cc = term->c_cc;
1511541Srgrimes		cc[VSUSP] = ltc->t_suspc;
1521541Srgrimes		cc[VDSUSP] = ltc->t_dsuspc;
1531541Srgrimes		cc[VREPRINT] = ltc->t_rprntc;
1541541Srgrimes		cc[VDISCARD] = ltc->t_flushc;
1551541Srgrimes		cc[VWERASE] = ltc->t_werasc;
1561541Srgrimes		cc[VLNEXT] = ltc->t_lnextc;
1577758Sache		*com = TIOCSETA;
1581541Srgrimes		break;
1591541Srgrimes	}
1601541Srgrimes	case TIOCLBIS:
1611541Srgrimes	case TIOCLBIC:
1627582Sache	case TIOCLSET:
1637758Sache		if (*com == TIOCLSET)
164182763Sed			tp->t_compatflags = (tp->t_compatflags&0xffff) |
165182763Sed			    *(int *)data<<16;
1661541Srgrimes		else {
167182763Sed			tp->t_compatflags = (ttcompatgetflags(tp)&0xffff0000) |
168182763Sed			    (tp->t_compatflags&0xffff);
1697758Sache			if (*com == TIOCLBIS)
170182763Sed				tp->t_compatflags |= *(int *)data<<16;
1711541Srgrimes			else
172182763Sed				tp->t_compatflags &= ~(*(int *)data<<16);
1731541Srgrimes		}
1747758Sache		ttcompatsetlflags(tp, term);
1757758Sache		*com = TIOCSETA;
1767758Sache		break;
1777758Sache	}
1787758Sache	return 0;
1797758Sache}
1807582Sache
1817758Sache/*ARGSUSED*/
1827758Sacheint
183201532Sedtty_ioctl_compat(struct tty *tp, u_long com, caddr_t data, int fflag,
184201532Sed    struct thread *td)
1857758Sache{
1867758Sache	switch (com) {
1877758Sache	case TIOCSETP:
1887758Sache	case TIOCSETN:
1897758Sache	case TIOCSETC:
1907758Sache	case TIOCSLTC:
1917758Sache	case TIOCLBIS:
1927758Sache	case TIOCLBIC:
1937758Sache	case TIOCLSET: {
1947758Sache		struct termios term;
1957758Sache		int error;
1967758Sache
1977758Sache		term = tp->t_termios;
1987758Sache		if ((error = ttsetcompat(tp, &com, data, &term)) != 0)
1997758Sache			return error;
200201532Sed		return tty_ioctl(tp, com, &term, fflag, td);
2017758Sache	}
2027758Sache	case TIOCGETP: {
203130840Sphk		struct sgttyb *sg = (struct sgttyb *)data;
204181905Sed		cc_t *cc = tp->t_termios.c_cc;
2057758Sache
206181905Sed		sg->sg_ospeed = ttcompatspeedtab(tp->t_termios.c_ospeed,
207181905Sed		    compatspeeds);
208181905Sed		if (tp->t_termios.c_ispeed == 0)
2097758Sache			sg->sg_ispeed = sg->sg_ospeed;
2109859Sache		else
211181905Sed			sg->sg_ispeed = ttcompatspeedtab(tp->t_termios.c_ispeed,
212181905Sed			    compatspeeds);
2137758Sache		sg->sg_erase = cc[VERASE];
2147758Sache		sg->sg_kill = cc[VKILL];
215182763Sed		sg->sg_flags = tp->t_compatflags = ttcompatgetflags(tp);
2167758Sache		break;
2177758Sache	}
2187758Sache	case TIOCGETC: {
2197758Sache		struct tchars *tc = (struct tchars *)data;
220181905Sed		cc_t *cc = tp->t_termios.c_cc;
2217758Sache
2227758Sache		tc->t_intrc = cc[VINTR];
2237758Sache		tc->t_quitc = cc[VQUIT];
2247758Sache		tc->t_startc = cc[VSTART];
2257758Sache		tc->t_stopc = cc[VSTOP];
2267758Sache		tc->t_eofc = cc[VEOF];
2277758Sache		tc->t_brkc = cc[VEOL];
2287758Sache		break;
2297758Sache	}
2307758Sache	case TIOCGLTC: {
2317758Sache		struct ltchars *ltc = (struct ltchars *)data;
232181905Sed		cc_t *cc = tp->t_termios.c_cc;
2337758Sache
2347758Sache		ltc->t_suspc = cc[VSUSP];
2357758Sache		ltc->t_dsuspc = cc[VDSUSP];
2367758Sache		ltc->t_rprntc = cc[VREPRINT];
2377758Sache		ltc->t_flushc = cc[VDISCARD];
2387758Sache		ltc->t_werasc = cc[VWERASE];
2397758Sache		ltc->t_lnextc = cc[VLNEXT];
2407758Sache		break;
2417758Sache	}
2421541Srgrimes	case TIOCLGET:
243182763Sed		tp->t_compatflags =
2448876Srgrimes		 (ttcompatgetflags(tp) & 0xffff0000UL)
245182763Sed		   | (tp->t_compatflags & 0xffff);
246182763Sed		*(int *)data = tp->t_compatflags>>16;
2471541Srgrimes		if (ttydebug)
2481541Srgrimes			printf("CLGET: returning %x\n", *(int *)data);
2491541Srgrimes		break;
2501541Srgrimes
2511541Srgrimes	case OTIOCGETD:
252181905Sed		*(int *)data = 2;
2531541Srgrimes		break;
2541541Srgrimes
2551541Srgrimes	case OTIOCSETD: {
2561541Srgrimes		int ldisczero = 0;
2571541Srgrimes
258181905Sed		return (tty_ioctl(tp, TIOCSETD,
259201532Sed			*(int *)data == 2 ? (caddr_t)&ldisczero : data,
260201532Sed			fflag, td));
2611541Srgrimes	    }
2621541Srgrimes
2631541Srgrimes	case OTIOCCONS:
2641541Srgrimes		*(int *)data = 1;
265201532Sed		return (tty_ioctl(tp, TIOCCONS, data, fflag, td));
2661541Srgrimes
2671541Srgrimes	default:
26831577Sbde		return (ENOIOCTL);
2691541Srgrimes	}
2701541Srgrimes	return (0);
2711541Srgrimes}
2721541Srgrimes
2737594Sachestatic int
274130840Sphkttcompatgetflags(struct tty *tp)
2751541Srgrimes{
276181905Sed	tcflag_t iflag	= tp->t_termios.c_iflag;
277181905Sed	tcflag_t lflag	= tp->t_termios.c_lflag;
278181905Sed	tcflag_t oflag	= tp->t_termios.c_oflag;
279181905Sed	tcflag_t cflag	= tp->t_termios.c_cflag;
280130840Sphk	int flags = 0;
2811541Srgrimes
2821541Srgrimes	if (iflag&IXOFF)
2831541Srgrimes		flags |= TANDEM;
2841541Srgrimes	if (iflag&ICRNL || oflag&ONLCR)
2851541Srgrimes		flags |= CRMOD;
2863509Sache	if ((cflag&CSIZE) == CS8) {
2873509Sache		flags |= PASS8;
2883509Sache		if (iflag&ISTRIP)
2893509Sache			flags |= ANYP;
2903509Sache	}
2913509Sache	else if (cflag&PARENB) {
2921541Srgrimes		if (iflag&INPCK) {
2931541Srgrimes			if (cflag&PARODD)
2941541Srgrimes				flags |= ODDP;
2951541Srgrimes			else
2961541Srgrimes				flags |= EVENP;
2971541Srgrimes		} else
2981541Srgrimes			flags |= EVENP | ODDP;
2991541Srgrimes	}
3008876Srgrimes
3018876Srgrimes	if ((lflag&ICANON) == 0) {
3021541Srgrimes		/* fudge */
3033509Sache		if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
30432773Ssteve		    || (cflag&(CSIZE|PARENB)) != CS8)
3051541Srgrimes			flags |= CBREAK;
3061541Srgrimes		else
3071541Srgrimes			flags |= RAW;
3081541Srgrimes	}
30932773Ssteve	if (!(flags&RAW) && !(oflag&OPOST) && (cflag&(CSIZE|PARENB)) == CS8)
3103509Sache		flags |= LITOUT;
3111541Srgrimes	if (cflag&MDMBUF)
3121541Srgrimes		flags |= MDMBUF;
3131541Srgrimes	if ((cflag&HUPCL) == 0)
3141541Srgrimes		flags |= NOHANG;
315181905Sed	if (oflag&TAB3)
3161541Srgrimes		flags |= XTABS;
3171541Srgrimes	if (lflag&ECHOE)
3181541Srgrimes		flags |= CRTERA|CRTBS;
3191541Srgrimes	if (lflag&ECHOKE)
3201541Srgrimes		flags |= CRTKIL|CRTBS;
3211541Srgrimes	if (lflag&ECHOPRT)
3221541Srgrimes		flags |= PRTERA;
3231541Srgrimes	if (lflag&ECHOCTL)
3241541Srgrimes		flags |= CTLECH;
3251541Srgrimes	if ((iflag&IXANY) == 0)
3261541Srgrimes		flags |= DECCTQ;
3271541Srgrimes	flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH);
3283510Sache	if (ttydebug)
3293510Sache		printf("getflags: %x\n", flags);
3301541Srgrimes	return (flags);
3311541Srgrimes}
3321541Srgrimes
3337594Sachestatic void
334130840Sphkttcompatsetflags(struct tty *tp, struct termios *t)
3351541Srgrimes{
336182763Sed	int flags = tp->t_compatflags;
337130840Sphk	tcflag_t iflag	= t->c_iflag;
338130840Sphk	tcflag_t oflag	= t->c_oflag;
339130840Sphk	tcflag_t lflag	= t->c_lflag;
340130840Sphk	tcflag_t cflag	= t->c_cflag;
3411541Srgrimes
3421541Srgrimes	if (flags & RAW) {
3437472Sache		iflag = IGNBRK;
3441541Srgrimes		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
3451541Srgrimes	} else {
3467472Sache		iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
3471541Srgrimes		iflag |= BRKINT|IXON|IMAXBEL;
3481541Srgrimes		lflag |= ISIG|IEXTEN|ECHOCTL;	/* XXX was echoctl on ? */
3491541Srgrimes		if (flags & XTABS)
350181905Sed			oflag |= TAB3;
3511541Srgrimes		else
352181905Sed			oflag &= ~TAB3;
3531541Srgrimes		if (flags & CBREAK)
3541541Srgrimes			lflag &= ~ICANON;
3551541Srgrimes		else
3561541Srgrimes			lflag |= ICANON;
3571541Srgrimes		if (flags&CRMOD) {
3581541Srgrimes			iflag |= ICRNL;
3591541Srgrimes			oflag |= ONLCR;
3601541Srgrimes		} else {
3611541Srgrimes			iflag &= ~ICRNL;
3621541Srgrimes			oflag &= ~ONLCR;
3631541Srgrimes		}
3641541Srgrimes	}
3651541Srgrimes	if (flags&ECHO)
3661541Srgrimes		lflag |= ECHO;
3671541Srgrimes	else
3681541Srgrimes		lflag &= ~ECHO;
3698876Srgrimes
3703510Sache	cflag &= ~(CSIZE|PARENB);
3711541Srgrimes	if (flags&(RAW|LITOUT|PASS8)) {
3721541Srgrimes		cflag |= CS8;
3733509Sache		if (!(flags&(RAW|PASS8))
3743509Sache		    || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
3751541Srgrimes			iflag |= ISTRIP;
3761541Srgrimes		else
3771541Srgrimes			iflag &= ~ISTRIP;
3783509Sache		if (flags&(RAW|LITOUT))
3793509Sache			oflag &= ~OPOST;
3803509Sache		else
3813509Sache			oflag |= OPOST;
3821541Srgrimes	} else {
3831541Srgrimes		cflag |= CS7|PARENB;
3841541Srgrimes		iflag |= ISTRIP;
3853509Sache		oflag |= OPOST;
3861541Srgrimes	}
38712370Sbde	/* XXX don't set INPCK if RAW or PASS8? */
3881541Srgrimes	if ((flags&(EVENP|ODDP)) == EVENP) {
3891541Srgrimes		iflag |= INPCK;
3901541Srgrimes		cflag &= ~PARODD;
3911541Srgrimes	} else if ((flags&(EVENP|ODDP)) == ODDP) {
3921541Srgrimes		iflag |= INPCK;
3931541Srgrimes		cflag |= PARODD;
3948876Srgrimes	} else
3951541Srgrimes		iflag &= ~INPCK;
3961541Srgrimes	if (flags&TANDEM)
3971541Srgrimes		iflag |= IXOFF;
3981541Srgrimes	else
3991541Srgrimes		iflag &= ~IXOFF;
4003510Sache	if ((flags&DECCTQ) == 0)
4013510Sache		iflag |= IXANY;
4023510Sache	else
4033510Sache		iflag &= ~IXANY;
4041541Srgrimes	t->c_iflag = iflag;
4051541Srgrimes	t->c_oflag = oflag;
4061541Srgrimes	t->c_lflag = lflag;
4071541Srgrimes	t->c_cflag = cflag;
4081541Srgrimes}
4091541Srgrimes
4107594Sachestatic void
411130840Sphkttcompatsetlflags(struct tty *tp, struct termios *t)
4121541Srgrimes{
413182763Sed	int flags = tp->t_compatflags;
414130840Sphk	tcflag_t iflag	= t->c_iflag;
415130840Sphk	tcflag_t oflag	= t->c_oflag;
416130840Sphk	tcflag_t lflag	= t->c_lflag;
417130840Sphk	tcflag_t cflag	= t->c_cflag;
4181541Srgrimes
4197472Sache	iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
4201541Srgrimes	if (flags&CRTERA)
4211541Srgrimes		lflag |= ECHOE;
4221541Srgrimes	else
4231541Srgrimes		lflag &= ~ECHOE;
4241541Srgrimes	if (flags&CRTKIL)
4251541Srgrimes		lflag |= ECHOKE;
4261541Srgrimes	else
4271541Srgrimes		lflag &= ~ECHOKE;
4281541Srgrimes	if (flags&PRTERA)
4291541Srgrimes		lflag |= ECHOPRT;
4301541Srgrimes	else
4311541Srgrimes		lflag &= ~ECHOPRT;
4321541Srgrimes	if (flags&CTLECH)
4331541Srgrimes		lflag |= ECHOCTL;
4341541Srgrimes	else
4351541Srgrimes		lflag &= ~ECHOCTL;
4363510Sache	if (flags&TANDEM)
4373510Sache		iflag |= IXOFF;
4383510Sache	else
4393510Sache		iflag &= ~IXOFF;
4401541Srgrimes	if ((flags&DECCTQ) == 0)
4411541Srgrimes		iflag |= IXANY;
4421541Srgrimes	else
4431541Srgrimes		iflag &= ~IXANY;
4441541Srgrimes	if (flags & MDMBUF)
4451541Srgrimes		cflag |= MDMBUF;
4461541Srgrimes	else
4471541Srgrimes		cflag &= ~MDMBUF;
4481541Srgrimes	if (flags&NOHANG)
4491541Srgrimes		cflag &= ~HUPCL;
4501541Srgrimes	else
4511541Srgrimes		cflag |= HUPCL;
4521541Srgrimes	lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
4531541Srgrimes	lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
4543509Sache
4553509Sache	/*
4563509Sache	 * The next if-else statement is copied from above so don't bother
4573509Sache	 * checking it separately.  We could avoid fiddlling with the
4583509Sache	 * character size if the mode is already RAW or if neither the
4593509Sache	 * LITOUT bit or the PASS8 bit is being changed, but the delta of
4603509Sache	 * the change is not available here and skipping the RAW case would
4613509Sache	 * make the code different from above.
4623509Sache	 */
4633510Sache	cflag &= ~(CSIZE|PARENB);
4643509Sache	if (flags&(RAW|LITOUT|PASS8)) {
4651541Srgrimes		cflag |= CS8;
4663509Sache		if (!(flags&(RAW|PASS8))
4673509Sache		    || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
4683509Sache			iflag |= ISTRIP;
4693509Sache		else
4703509Sache			iflag &= ~ISTRIP;
4713509Sache		if (flags&(RAW|LITOUT))
4721541Srgrimes			oflag &= ~OPOST;
4733509Sache		else
4743509Sache			oflag |= OPOST;
4753509Sache	} else {
4761541Srgrimes		cflag |= CS7|PARENB;
4773509Sache		iflag |= ISTRIP;
4781541Srgrimes		oflag |= OPOST;
4791541Srgrimes	}
4801541Srgrimes	t->c_iflag = iflag;
4811541Srgrimes	t->c_oflag = oflag;
4821541Srgrimes	t->c_lflag = lflag;
4831541Srgrimes	t->c_cflag = cflag;
4841541Srgrimes}
485