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] 3rd patch for tty COMPAT_43 modes (great win!)
Date: Wed, 09 Dec 92 23:11:17 +0300
Distribution: world
Organization: Ha-oh-lahm Yetzirah
Reply-To: ache@astral.msk.su

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: apply this patch ONLY if two previous my patches installed.
Because my patches goes so far I just produce united (1-3) patch
in separate message.

*** tty_compat.c.was2	Wed Dec  2 23:05:17 1992
--- 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;
  	}
  
***************
*** 119,125 ****
  			term.c_ospeed = compatspcodes[speed];
  		term.c_cc[VERASE] = sg->sg_erase;
  		term.c_cc[VKILL] = sg->sg_kill;
! 		tp->t_flags = ttcompatgetflags(tp)&0xffff0000 | sg->sg_flags&0xffff;
  		ttcompatsetflags(tp, &term);
  		return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA, 
  			&term, flag));
--- 119,125 ----
  			term.c_ospeed = compatspcodes[speed];
  		term.c_cc[VERASE] = sg->sg_erase;
  		term.c_cc[VKILL] = sg->sg_kill;
! 		tp->t_flags = tp->t_flags&0xffff0000 | sg->sg_flags&0xffff;
  		ttcompatsetflags(tp, &term);
  		return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA, 
  			&term, flag));
***************
*** 182,190 ****
  
  		term = tp->t_termios;
  		if (com == TIOCLSET)
! 			tp->t_flags = (ttcompatgetflags(tp)&0xffff) | *(int *)data<<16;
  		else {
! 			tp->t_flags = ttcompatgetflags(tp);
  			if (com == TIOCLBIS)
  				tp->t_flags |= *(int *)data<<16;
  			else
--- 182,191 ----
  
  		term = tp->t_termios;
  		if (com == TIOCLSET)
! 			tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
  		else {
! 			tp->t_flags = 
! 			 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
  			if (com == TIOCLBIS)
  				tp->t_flags |= *(int *)data<<16;
  			else
***************
*** 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;
--- 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;
***************
*** 233,253 ****
  		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;
  	}
- 	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;
--- 236,256 ----
  		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;
***************
*** 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;
  	}
--- 314,329 ----
  	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;
  	}
***************
*** 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;
--- 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.solaris,comp.windows.x,comp.unix.programmer