*BSD News Article 9788


Return to BSD News archive

Received: by minnie.vk1xwt.ampr.org with NNTP
	id AA6500 ; Sun, 10 Jan 93 10:14:41 EST
Path: sserve!manuel.anu.edu.au!munnari.oz.au!uunet!europa.asd.contel.com!howland.reston.ans.net!spool.mu.edu!agate!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
From: torek@horse.ee.lbl.gov (Chris Torek)
Newsgroups: comp.unix.bsd
Subject: Re: a unix terminal question
Date: 12 Jan 1993 21:05:35 GMT
Organization: Lawrence Berkeley Laboratory, Berkeley CA
Lines: 75
Message-ID: <28370@dog.ee.lbl.gov>
References: <1iql6kINNisk@ub.d.umn.edu> <1993Jan11.215312.2080@fcom.cc.utah.edu> <uonuhjc@zola.esd.sgi.com>
NNTP-Posting-Host: 128.3.112.15

(I note that this article would have gone to both comp.lang.c and
comp.unix.bsd.  It is rare for an article ever to belong in both
groups.  This particular stuff really should not be in comp.lang.c at
all, so I have redirected it.)

In article <uonuhjc@zola.esd.sgi.com> dps@delhi.esd.sgi.com (D.P. Suresh)
writes:
>select() or poll() in itself will not get you the desired result
>[because the O/S is doing line gathering and you must disable this too].

>	/* Create proper environment for select() */
>	FD_ZERO( &readfds );
>	FD_ZERO( &writefds );
>	FD_ZERO( &exceptfds );
>	FD_SET( fileno(stdin), &readfds );

Since no write or exception file descriptors will be used, none need be
provided.  Select() allows (fd_set *)NULL arguments, meaning `nothing
of interest here'.

>	/* We shall specify 0.5 sec as the waiting time */
>	timeout.tv_sec  = 0;	/*   0 seconds */
>	timeout.tv_usec = 500;	/* 500 microseconds */

tv_usec is indeed microseconds, so 500 us is 0.0005 seconds, not 0.5.
(Most current UNIX systems will round this up to their actual internal
timeout rate of 100 Hz, or .01 seconds.)

>	/* Put tty in raw mode */
>	ioctl(fileno(stdout), TCGETA, &otty);
	...
>	ioctl(fileno(stderr), TCSETAW, &ntty);

Here I have to wonder why the tty modes are obtained from stdout and
set on stderr when we are going to read stdin.  If the reading is to be
from fileno(stdin), the tty operations should be done there as well,
since their purpose is to affect this reading.

In more complex tty control programs (such as editors), the goal may be
both to affect input and output.  In this case it is a bit more
reasonable to try both stdin and stdout.  In any case it seems wrong to
touch stderr.  The wise and cautious programmer might consider:

	iocfd = STDIN_FILENO;		/* or simply 0 */
	if (ioctl(iocfd, TCGETA, &otty) < 0) {
		iocfd = STDOUT_FILENO;	/* 1---these should be in <unistd.h> */
		if (ioctl(iocfd, TCGETA, &otty) < 0) {
			/* disable tty operations, i/o is pipes or similar */
			ttycontrol = 0;
			return;
		}
	}
	...
	(void)ioctl(iocfd, TCSETAW, &ntty);

In this particular case (reading stdin only), the attempts using
STDOUT_FILENO are not advised.

On BSD systems, one should also use care lest code like this be stopped
(via, e.g., ^Z) between the `get' and `set' phases and the tty settings
be changed.  Careful use of signal handlers and, if necessary, setjmp
and longjmp can make tty alteration appear atomic.

>This feature should be used wisely. One could incur quite a lot of
>performance penalties as expressed by terry.

Indeed, particularly if the keyboard mode is changed twice on every call
to this checking function.

Incidentally, note that select() for reading returns true at EOF
(because reading EOF does not block).  Callers should be prepared for
this.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov