From: "Andrew A. Chernov, Black Mage" <ache@astral.msk.su>
Resent-From: "Andrew A. Chernov, Black Mage" <ache@astral.msk.su>
Newsgroups: comp.unix.bsd
Subject: [386bsd] United (1-3) patch for tty COMPAT_43 modes (great win!)
Date: Wed, 09 Dec 92 23:18:00 +0300
Distribution: world
Organization: Ha-oh-lahm Yetzirah
Reply-To: ache@astral.msk.su

In comp.unix.bsd article <RHbBb9hSE0@astral.msk.su> I write:

>Hi, folks.
>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.
>
>I produce two patches to fix it, but problem are deeper.
>In 3rd patch I decide return back to original driver concept,
>use tp->t_flag field and completely rewrite old patches.
>Now, if program call gtty, modes stored into tp->t_flag,
>for later stty call.
>
>Advantages:
>1) Can preserve CS8 mode
>2) Can preserve ISTRIP mode in CS8 mode
>3) Can preserve parity modes 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.

WARNING: Because my patches goes so far, this is united (1-3) patch.
Apply it to ORIGINAL unmodified tty_compat.c ONLY.
3rd level patch sent in separate message to whom, who applied
previous two my patches.

*** tty_compat.c.was	Wed Dec 25 00:24:09 1991
--- tty_compat.c	Wed Dec  9 05:45:34 1992
***************
*** 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;
  	}
  
***************
*** 195,201 ****
  		return (ttioctl(tp, TIOCSETA, &term, flag));
  	}
  	case TIOCLGET:
! 		*(int *)data = ttcompatgetflags(tp)>>16;
  		if (ttydebug)
  			printf("CLGET: returning %x\n", *(int *)data);
  		break;
--- 195,203 ----
  		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;
***************
*** 234,261 ****
  		flags |= TANDEM;
  	if (iflag&ICRNL || oflag&ONLCR)
  		flags |= CRMOD;
! 	if (cflag&PARENB) {
! 		if (iflag&INPCK) {
  			if (cflag&PARODD)
  				flags |= ODDP;
  			else
  				flags |= EVENP;
- 		} else
- 			flags |= EVENP | ODDP;
- 	} else {
- 		if ((tp->t_flags&LITOUT) && !(oflag&OPOST))
- 			flags |= LITOUT;
- 		if (tp->t_flags&PASS8)
- 			flags |= PASS8;
  	}
  	
  	if ((lflag&ICANON) == 0) {	
  		/* fudge */
! 		if (iflag&IXON || lflag&ISIG || lflag&IEXTEN || cflag&PARENB)
  			flags |= CBREAK;
  		else
  			flags |= RAW;
  	}
  	if (oflag&OXTABS)
  		flags |= XTABS;
  	if (lflag&ECHOE)
--- 236,262 ----
  		flags |= TANDEM;
  	if (iflag&ICRNL || oflag&ONLCR)
  		flags |= CRMOD;
! 	if ((cflag&CSIZE) == CS8) {
! 		flags |= PASS8;
! 		if (iflag&ISTRIP)
! 			flags |= ANYP;
! 	}
! 	else if (iflag&INPCK || cflag&PARENB) {
  		if (cflag&PARODD)
  			flags |= ODDP;
  		else
  			flags |= EVENP;
  	}
  	
  	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)
***************
*** 285,291 ****
  	register long cflag = t->c_cflag;
  
  	if (flags & RAW) {
! 		iflag &= IXOFF;
  		oflag &= ~OPOST;
  		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
  	} else {
--- 286,292 ----
  	register long cflag = t->c_cflag;
  
  	if (flags & RAW) {
! 		iflag &= (IXOFF|IXANY);
  		oflag &= ~OPOST;
  		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
  	} else {
***************
*** 313,328 ****
  	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|PARENB;
  		iflag |= ISTRIP;
  	}
  	if ((flags&(EVENP|ODDP)) == EVENP) {
--- 314,330 ----
  	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;
  	}
  	if ((flags&(EVENP|ODDP)) == EVENP) {
***************
*** 377,394 ****
  		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|PARENB;
! 		oflag |= OPOST;
  	}
  	t->c_iflag = iflag;
  	t->c_oflag = oflag;
--- 379,400 ----
  		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
Organization:  The RELCOM Corp.,    |  "Brujuleada entre los lejos
               Moscow, Russia       |  "De lo imposible?!"  (Calderon)


Newsgroups: comp.unix.bsd