How can I read keyboard without stopping

der Mouse mouse at mcgill-vision.UUCP
Mon Aug 15 18:09:47 AEST 1988


In article <813 at ms3.UUCP>, isns02 at ms3.UUCP (Harris Reavin) writes:
> I would like to know if it is possible to get input data from the
> keyboard while my program is constantly looping and displaying output
> to the screen.  The input comes from a call to "popen()".

Now wait a minute!  If you used popen(), your input is coming from
another program, and only indirectly (if at all) from the keyboard.

> I am using C, curses, and BSD4.2 on a VAX-780.  I have only been able
> to enter input if the display stops for "getch()".  This is not
> acceptable because I want the display to be continuous unless I am
> going to change one of the parameters.

It sounds as though you really want to read from the keyboard, so I'll
ignore the bit about popen().

I know of at least four ways to do this (read without jamming the whole
process), of varying degrees of portability and functionality.

1) Signals.  Set up an alarm signal (eg, with alarm()) before doing the
   read and disable it afterwards.  Have the signal handler either
   longjmp out or, depending on how signals interact with read on the
   system in question, simply do nothing.

   Good:	- works nearly everywhere.

   Bad:		- program blocks for a while.
		- if alarm() is used (as it must for portability), the
		  granularity of this timeout is one second.

2) Non-blocking I/O.  BSD systems, and I believe recent SV systems,
   support the notion of "non-blocking" reads.  What this amounts to is
   you make a call to turn this mode on, and then any read for which no
   characters are available will return an error indication instead of
   blocking.

   Good:	- no temporary blockage.
		- reasonably widely available (I think).

   Bad:		- may not interact well with curses.  Many programs
		  (and library packages) are not prepared to handle
		  "would block" errors.
		- specifics vary from system to system.
		- generally, non-blocking mode *must* be turned off or
		  the shell will die - so you must trap SIGBUS,
		  SIGSEGV, SIGINT, etc.
		- requires constant polling.

3) FIONREAD.  BSD systems have an ioctl you can apply to a terminal
   line to get the number of characters queued available for a read().
   SV may have something similar; I don't know.

   Good:	- no temporary blockage.
		- indicates not only *whether* input is available but
		  also *how much* input is available.

   Bad:		- BSD only (as far as I know).
		- requires constant polling.

4) select().  BSD systems, and some "SV with BSD extensions" systems (I
   know of at least one) have the select() syscall.  This allows you to
   block until something is available from any one of several sources
   you specify, or a timeout expires.  (It is possible to wait for
   other conditions as well, but I'm not trying to write a manpage for
   the thing.)  This is the most flexible method of the four.

   Good:	- full control over blockage, from a zero timeout
		  (polling) to infinite (blocking).

   Bad:		- BSD-specific, though your system may have it even if
		  it's primarily SV.

Pick the one you think best suits your needs.  Since you're on a BSD
system, all four are available.  If you aren't interested in porting to
non-BSD systems, I recommend select().  (Actually, I recommend that you
use select(), with preprocessor #if lines to select some other method
if you have to compile somewhere select() is unavailable.)

					der Mouse

			old: mcgill-vision!mouse
			new: mouse at larry.mcrcim.mcgill.edu



More information about the Comp.unix.wizards mailing list