Bug in TCSETA ioctl?

Ian Dall ian at sibyl.eleceng.ua.OZ
Wed Apr 6 17:12:18 AEST 1988


There appears to be a bug in the code to impliment the TCSETA[F,W]
code Sys5.2 rel 2. I would be interested to know if this bug is a)
already known or b) fixed in later releases.

According to the "termio" man pages

              "TCSETA    Set the parameters associated with the
                         terminal from the structure referenced by
                         arg.  The change is immediate.

               TCSETAW   Wait for the output to drain before setting
                         the new parameters.  This form should be used
                         when changing parameters that will affect
                         output."

The implication is that the converse of the last sentence holds. And that
providing your change does not affect output post processing TCSETA should
be fine. In practice this turns out not to be the case. I only have a binary
licence which does include the hardware tt driver source but not the
generic tt driver stuff.

The hardware tt driver calls ttiocom and if it returns non zero goes and
stuffs things in the DUART registers to set up baud rates no of stop bits
etc. Not too surprisingly this tends to corrupt anything the DUART is in
the process of outputing.

Using adb on the kernal to find out what ttiocom does (remember I don't
have the source) reveals that the code must be some thing like:

ttiocom(.........)

{
  .
  .
  .
    switch ( command )

	case TCSETAW:
	case TCSETAF:
		ttywait(...);
		if (command == TCSETAF)
			ttyflush(....);
	case TCSETA:
                .
		.
		.
		/* code to get parameters from users area */

		return(1);

	case TCGETA:
                .
	        .
		.
		/* code to put parameters into users area */

                break;

	case TCSBRK:
                .
	        .
		.
		break;

	case TCXONC:
                .
	        .
		.
		break;

	case TCFLSH:
                .
	        .
		.
		break;
	return(0);
}


I contend that this code should only return 1 if the HARDWARE setup has
changed. Many (most?) TCSETAs will NOT change the hardware setup.

Something like replacing the "return (1);" with

           if ( old_c_cflag == c_cflag ) break;
	   else return (1);

should do the trick. Do later SysVs do this? Perhaps other hardware is
less fussy and don't get upset by setting the hardware registers to the
same as they already are.

Here is a test program so you can see if your system exhibits this bug.

If the output is garbled you have the bug.

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by ian on Wed Apr  6 16:07:04 CST 1988
# Contents:  checktermio.c
 
echo x - checktermio.c
sed 's/^@//' > "checktermio.c" <<'@//E*O*F checktermio.c//'
#include <termio.h>
#include <stdio.h>
#define TSET TCSETA
int kbd_count;
char *kbd_ptr, kbd_buffer[256];
char longstring[] = "The quick brown fox jumped over the lazy dogs back and\
 made him howl horribly.\n";

main()
{
  register i;
  for (i=1; i < 20; i++)
    {
      printf(longstring);
      read_avail_input();
    }
}

read_avail_input ()
{
  struct termio tnow, told;

  if (ioctl (fileno (stdin), TCGETA, &tnow) < 0)
    return;

  told = tnow;
  tnow.c_lflag &= ~ICANON;
  tnow.c_cc[VMIN] = 0;
  tnow.c_cc[VTIME] = 0;
  ioctl (fileno (stdin), TCSETA, &tnow);
  kbd_ptr = kbd_buffer;
  kbd_count = read (fileno (stdin), kbd_buffer, sizeof kbd_buffer);
  ioctl (fileno (stdin), TCSETA, &told);
}
@//E*O*F checktermio.c//
chmod u=rw,g=r,o=r checktermio.c
 
exit 0



More information about the Comp.bugs.sys5 mailing list