[net.unix] Non-blocking tty read

54394gt@hocda.UUCP (G.TOMASEVICH) (02/06/84)

Recently I posted an article to 'net.unix-wizards' on nonblocking terminal
reads.  We have USG 4.2 UNIX, which has 'struct termio'; if you have
an oldter system with 'struct sgtty' you cannot do it.  One changes to
raw mode by saving the contents of the struct for line 0, then changes
some constants.  Assume you have the following code:

#include <termio.h>
struct termio svt;		/* for saving initial parameters */
struct termio stt;		/* for changing line parameters */

	...
	ioctl(0,TCGETA,&svt);	/* save old */
	stt.c_iflag = stt.c_oflag = stt.c_lflag = 0;
	stt.c_cflag = (svt.c_cflag&CBAUD)|CS8|CREAD|CLOCAL; /* direct line */
	stt.c_cc[VMIN] = 0;	/* no chars needed for read() to return */
	stt.c_cc[VTIME] = 0;	/* timeout limit = 0 */
	ioctl(0,TCSETA,&stt);

To try to get a char, do the following:

	char key;
	if(read(0,&key,1) == 1)
		there is a char;
	else
		there is no char;

If there is a character available, then the read() returns 1,
so you can test the return value.  I use it in conjuction with a DR11-W
read/write program, which must poll the DR11-W status while waiting
for characters to be typed.  Of course, you hog the computer while running
such a loop.  If you want a blocking read, then set stt.c_cc[VMIN] = 1;
I change back and forth, depending on whether anything besides keyboard
input is happening at any particular instant.

To avoid lousing up your line, catch all signals so you can do

	ioctl(0,TCSETA,&svt);
	and then an abort() if you want a core dump;

before the process exits;

guy@rlgvax.UUCP (Guy Harris) (02/07/84)

> We have USG 4.2 UNIX, which has 'struct termio'; if you have
> an oldter system with 'struct sgtty' you cannot do it.

For the record, "System III" is USG 3.0.1 and "System V Release N" is
USG 5.0 or later; USG 3.0 and later releases have it, although there
is a bug in USG 3.0 and USG 3.0.1 (System III) that causes no-delay
read not to work (it's trivial to fix).

> One changes to raw mode by saving the contents of the struct for line 0,
> then changes some constants.  Assume you have the following code:
  .
  .
  .
> 	stt.c_iflag = stt.c_oflag = stt.c_lflag = 0;
> 	stt.c_cflag = (svt.c_cflag&CBAUD)|CS8|CREAD|CLOCAL; /* direct line */
> 	stt.c_cc[VMIN] = 0;	/* no chars needed for read() to return */
> 	stt.c_cc[VTIME] = 0;	/* timeout limit = 0 */
> 	ioctl(0,TCSETA,&stt);

Two points:

	1) Going into raw mode (meaning 8-bit data path with no special
	   processing of input or output) may be overkill; one should only
	   go into raw mode if one really wants to get 8-bit characters
	   (i.e., the eighth bit is not a parity bit) and one wants to
	   disable all "canonicalization" (erase, kill, eof), signals
	   (interrupt, quit), XON/XOFF processing (think twice if you
	   have a VT100), etc., etc..  If one is just reading single
	   characters and responding to them directly (such as in a screen
	   editor), merely turning the ICANON bit off in "c_lflag" will suffice.
	   In the V7 terminal driver (and the enhanced V7 driver that
	   comes with various Berkeley releases), turning on the CBREAK
	   bit and possibly disabling characters like the interrupt and
	   quit characters will suffice.

	2) The trick of setting c_cc[VMIN] to 0 may not work on systems
	   prior to USG 4.2 (I tried it on a System III system and it
	   didn't work).

I will note that the documentation of the UNIX terminal driver given in
the System III and System V documentation is rather incomplete.  There
are several features in both drivers which are not documented, and it
is not clear that all the documented features are completely or clearly
documented, so be prepared for surprises if you try some things that
"look" like they should work; the fact that setting c_cc[VMIN] has the
effect of putting you in no-delay mode is not 100% obvious from the
S3/S5 manual page.  (Also, I would like to shoot the idiot at Bell
who decided that the terminal driver manual pages belonged in the
Administrator's Manual rather than the User's Manual.  There is little
correlation between administrator status and need to know the pecularities
of a device interface; there is *no* correlation between administrator
status and the desire or right to write a screen-oriented program, but
in order to put the terminal into character-at-a-time mode you need the
stuff that appears in TERMIO(7) in the *Administrator's* Manual.)

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy