From: joel@abigale.UUCP (Joel Rosi-Schwartz)
Newsgroups: comp.lang.perl
Subject: Re: How to read keyboard without blocking ?
Date: 9 Oct 92 09:55:57 GMT
Organization: Techne Research, Finchampstead, Berkshire (UK)

In article <1992Oct8.163021.12661@Warren.MENTORG.COM> tal@Warren.MENTORG.COM (Tom Limoncelli) writes:
>In article <1992Oct7.233512.23465@unixg.ubc.ca> admerlev@cipy.e-technik.uni-erlangen.de writes:
>>can anybody help me on how I can read the keyboard (/dev/tty)
>>in a nonblocking fashion ?
>>I tried read, sysread, getc... but they all wait for 
>>input. I want the program to continue when no key was pressed.
>
>It can't be done.
>
>Ok, that's a lie.  It *can* be done, but you have to read the FAQ posting
>first.
>

I see this coming up rather regularly in the group so I am going to
put minutes of my hard work into the PD ;-) Now I realise that this
is _NOT_ an efficient way to handly the problem if a lot of input is
being requested in the script, but if it is for the occaisional "get a
one key y/n from the user it works just fine.  Notice also that it
does not break if the script is run in the background, as long as a
reasonable default has been specified prior to the call for the key.
Use this with my blessings in anyway your wish, as long as it is in
the pursuit of peace and not war.

MANPAGE:

	Usage: getkey [-q]

	Gets one key from the terminal and returns that key to stdout.
	If the -q optin is given it reads the terminal and throw the
	keypress away, this is useful for such things as:

		print "[Press any key to continue]";
		`getkey -q`;

---- cut here ---  getkey.c  ------------------------------------------------

#include <sys/termio.h>

main(int argc, char **argv)
{
  struct termio	tty, save;
  char	c;
  int	quiet = 0;

	/*  Checking if we are connected to a terminal or
	 *	not permits a script to call us safely even if
	 *	it may be ran in the background, as long as
	 *	the script does not need a valid response.
	 ***************************************************/

	if (! isatty(0)) {
		return(0);
	}

	/*  Get a key but do not echo it.
	*********************************/

	if (argc > 1 && strncmp(argv[1], "-q", 2) == 0)
		quiet = 1;

	ioctl(0, TCGETA ,&tty);
	ioctl(0, TCGETA, &save);

	/*  Set up the terminal into raw mode.
	**  At least 1 char must be read before
	**  the read returns.
	****************************************/

	tty.c_lflag &= ~(ECHO|ICANON);
	tty.c_cc[VMIN] = 1;
	tty.c_cc[VTIME] = 0;

	ioctl(0, TCSETA, &tty);
	read(0, &c, 1);

	if (quiet == 0)
		write(1, &c, 1);

	ioctl(0, TCSETA, &save);
	return (0);
}
-----------------------------------------------------------------------------
-- 
     ==================================================================
     ||               T E C H N E   R E S E A R C H                  ||
     ||  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  ||
     ||                     Joel Rosi-Schwartz                       ||
     ||   Hildorien House            +   Email: joel@abigale.UUCP    ||
     ||   12 Waverley Way            +    (pyrltd!abigale.UUCP!joel) ||
     ||   Finchampstead, Wokingham   +   Phone: +44 (734) 730.260    ||
     ||   Berkshire RG11 4YD (UK)    +   Fax:   +44 (734) 730.272    ||
     ==================================================================
Newsgroups: comp.lang.perl