*BSD News Article 15945


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!spool.mu.edu!howland.reston.ans.net!torn!nott!bnrgate!bnr.co.uk!uknet!pipex!sunic!news.funet.fi!fuug!kiae!bitcom!kiae!relcom!newsserv
From: "Andrew A. Chernov, Black Mage" <ache@astral.msk.su>
Newsgroups: comp.os.386bsd.bugs
Subject: Revised patch to tty_compat.c: fix bug with cs8 and many other
Date: Mon, 10 May 93 19:06:02 +0400
Distribution: world
Organization: Ha-olahm Yetzirah
Message-ID: <rMQzcxhuB0@astral.msk.su>
Sender: news-service@newcom.kiae.su
Reply-To: ache@astral.msk.su
Lines: 227

Hi.
Main problem are, that in switching to RAW or CBREAK modes and
back tty driver lost some flags and some flags are incorrect.
The most significant bug is lost CS8 character size.

+This patch version have fixed false INPCK set,
+fix come from Guido van Rooij <guido@gvr.win.tue.nl>,
+thanx to him.

Advantages:
1) Can preserve CS8 mode
2) Can preserve ISTRIP mode in CS8 mode
3) Can preserve parity modes and INPCK in CS7 mode
4) LITOUT mode doesn't stuck.
5) Can preserve IXANY mode

Disadvantages:
1) Using POSIX tty ioctls mixed with old-style ioctl
cause wrong results (present in original driver).
2) Can't handle output parity without corresponding input
parity, if even or odd parity set (impossible in old-style ioctls).
3) Using TIOCLGET after stty and may produce wrong results.
IMHO, it doesn't matter, because all programs I seen first get all
modes, then set.
In original driver using TIOCLGET before gtty may produce wrong results.

*** tty_compat.c.orig	Thu Nov 26 22:38:06 1992
--- tty_compat.c	Mon May 10 18:46:42 1993
*************** ttcompat(tp, com, data, flag)
*** 98,104 ****
  		}
  		sg->sg_erase = cc[VERASE];
  		sg->sg_kill = cc[VKILL];
! 		sg->sg_flags = ttcompatgetflags(tp);
  		break;
  	}
  
--- 98,104 ----
  		}
  		sg->sg_erase = cc[VERASE];
  		sg->sg_kill = cc[VKILL];
! 		sg->sg_flags = tp->t_flags = ttcompatgetflags(tp);
  		break;
  	}
  
*************** ttcompat(tp, com, data, flag)
*** 194,200 ****
  		return (ttioctl(tp, TIOCSETA, &term, flag));
  	}
  	case TIOCLGET:
! 		*(int *)data = ttcompatgetflags(tp)>>16;
  		if (ttydebug)
  			printf("CLGET: returning %x\n", *(int *)data);
  		break;
--- 194,202 ----
  		return (ttioctl(tp, TIOCSETA, &term, flag));
  	}
  	case TIOCLGET:
! 		tp->t_flags =
! 		 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
! 		*(int *)data = tp->t_flags>>16;
  		if (ttydebug)
  			printf("CLGET: returning %x\n", *(int *)data);
  		break;
*************** ttcompatgetflags(tp)
*** 233,239 ****
  		flags |= TANDEM;
  	if (iflag&ICRNL || oflag&ONLCR)
  		flags |= CRMOD;
! 	if (cflag&PARENB) {
  		if (iflag&INPCK) {
  			if (cflag&PARODD)
  				flags |= ODDP;
--- 235,246 ----
  		flags |= TANDEM;
  	if (iflag&ICRNL || oflag&ONLCR)
  		flags |= CRMOD;
! 	if ((cflag&CSIZE) == CS8) {
! 		flags |= PASS8;
! 		if (iflag&ISTRIP)
! 			flags |= ANYP;
! 	}
! 	else if (cflag&PARENB) {
  		if (iflag&INPCK) {
  			if (cflag&PARODD)
  				flags |= ODDP;
*************** ttcompatgetflags(tp)
*** 242,259 ****
  		} else
  			flags |= EVENP | ODDP;
  	}
! 	if (!(oflag&OPOST) && (!(cflag&PARENB) || (cflag&CSIZE) == CS8))
! 		flags |= LITOUT;
! 	if ((cflag&CSIZE) == CS8 && !(iflag&ISTRIP))
! 		flags |= PASS8;
! 	
  	if ((lflag&ICANON) == 0) {	
  		/* fudge */
! 		if (oflag&OPOST || iflag&ISTRIP || iflag&IXON || lflag&ISIG || lflag&IEXTEN || (cflag&PARENB) && (cflag&CSIZE) != CS8)
  			flags |= CBREAK;
  		else
  			flags |= RAW;
  	}
  	if (oflag&OXTABS)
  		flags |= XTABS;
  	if (lflag&ECHOE)
--- 249,264 ----
  		} else
  			flags |= EVENP | ODDP;
  	}
! 
  	if ((lflag&ICANON) == 0) {	
  		/* fudge */
! 		if (oflag&OPOST || iflag&ISTRIP || iflag&IXON || lflag&ISIG || lflag&IEXTEN || cflag&PARENB || iflag&INPCK || (cflag&CSIZE) != CS8)
  			flags |= CBREAK;
  		else
  			flags |= RAW;
  	}
+ 	if (!(flags&RAW) && !(oflag&OPOST) && (!(cflag&PARENB) || (cflag&CSIZE) == CS8))
+ 		flags |= LITOUT;
  	if (oflag&OXTABS)
  		flags |= XTABS;
  	if (lflag&ECHOE)
*************** ttcompatsetflags(tp, t)
*** 283,289 ****
  	register long cflag = t->c_cflag;
  
  	if (flags & RAW) {
! 		iflag &= IXOFF;
  		oflag &= ~OPOST;
  		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
  	} else {
--- 288,294 ----
  	register long cflag = t->c_cflag;
  
  	if (flags & RAW) {
! 		iflag &= (IXOFF|IXANY);
  		oflag &= ~OPOST;
  		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
  	} else {
*************** ttcompatsetflags(tp, t)
*** 311,327 ****
  	else
  		lflag &= ~ECHO;
  		
  	if (flags&(RAW|LITOUT|PASS8)) {
- 		cflag &= ~(CSIZE|PARENB);
  		cflag |= CS8;
! 		if ((flags&(RAW|PASS8)) == 0)
  			iflag |= ISTRIP;
  		else
  			iflag &= ~ISTRIP;
  	} else {
- 		cflag &= ~CSIZE;
  		cflag |= CS7;
! 		if (flags&(ODDP|EVENP))
  			cflag |= PARENB;
  		iflag |= ISTRIP;
  	}
--- 316,331 ----
  	else
  		lflag &= ~ECHO;
  		
+ 	cflag &= ~(CSIZE|PARENB);
  	if (flags&(RAW|LITOUT|PASS8)) {
  		cflag |= CS8;
! 		if (!(flags&(RAW|PASS8)) || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
  			iflag |= ISTRIP;
  		else
  			iflag &= ~ISTRIP;
  	} else {
  		cflag |= CS7;
! 		if ((flags&(EVENP|ODDP)) && (flags&ANYP) != ANYP)
  			cflag |= PARENB;
  		iflag |= ISTRIP;
  	}
*************** ttcompatsetlflags(tp, t)
*** 377,396 ****
  		lflag &= ~IXANY;
  	lflag &= ~(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
  	lflag |= flags&(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
  	if (flags&(LITOUT|PASS8)) {
- 		iflag &= ~ISTRIP;
- 		cflag &= ~(CSIZE|PARENB);
  		cflag |= CS8;
! 		if (flags&LITOUT)
  			oflag &= ~OPOST;
! 		if ((flags&(PASS8|RAW)) == 0)
! 			iflag |= ISTRIP;
  	} else if ((flags&RAW) == 0) {
- 		cflag &= ~CSIZE;
  		cflag |= CS7;
! 		if (flags&(ODDP|EVENP))
  			cflag |= PARENB;
! 		oflag |= OPOST;
  	}
  	t->c_iflag = iflag;
  	t->c_oflag = oflag;
--- 381,402 ----
  		lflag &= ~IXANY;
  	lflag &= ~(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
  	lflag |= flags&(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
+ 	cflag &= ~(CSIZE|PARENB);
  	if (flags&(LITOUT|PASS8)) {
  		cflag |= CS8;
! 		if (flags&(LITOUT|RAW))
  			oflag &= ~OPOST;
! 		else
! 			oflag |= OPOST;
! 		if (!(flags&(RAW|PASS8)) || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
!   			iflag |= ISTRIP;
! 		else
! 			iflag &= ~ISTRIP;
  	} else if ((flags&RAW) == 0) {
  		cflag |= CS7;
! 		if ((flags&(EVENP|ODDP)) && (flags&ANYP) != ANYP)
  			cflag |= PARENB;
! 		oflag |= ISTRIP|OPOST;
  	}
  	t->c_iflag = iflag;
  	t->c_oflag = oflag;
-- 
In-This-Life:    Andrew A. Chernov      | "Hay mas dicha, mas contento
Internet:        ache@astral.msk.su     | "Que adorar una hermosura
FIDOnet:         2:5020/23.34           | "Brujuleada entre los lejos
RELCOM Development Team, Moscow, Russia | "De lo imposible?!" (Calderon)