[ale] FAQ: I need to fake DOS' kbhit(), getch()

Dunlap, Randy randy.dunlap at intel.com
Thu Jul 27 17:00:04 EDT 2000


>From lkml on 2000-june-29:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[PS: this is off-topic for both linux-kernel and linux-net. Try
linux-admin at vger, or linux-c-programming at lists.chorus.net.]

shannon loi wrote:

> I'm writing an application using C language, in which
> I have a while loop that run infinitely, only stop if
> user hit 'q'on the keyboard. 
> Does Linux C library has a function to detect keyboard
> hit (like function _kbhit in Windows)?

No. Unix boxes historically haven't tended to have directly-attached
keyboards like PCs. Instead, they relied upon serial terminals for
user interaction. Consequently, "PC" Unices such as Linux tend to use
the keyboard and display to emulate one or more serial terminals.

The default setting for the virtual terminals is "canonical" mode. In
canonical mode, input is line-buffered; nothing is actually sent to
the application which is reading from the terminal until the user
presses Return. This allows the user to edit the line (with Backspace,
^U and ^W) without any help from the application.

Also, if you use the ANSI stdio functions, these will perform
additional buffering. By default, stdin and stdout are line buffered
if they are associated with a terminal device and fully buffered
(block buffered) otherwise. You have to make stdin unbuffered if you
want getchar() etc to read directly from the underlying descriptor.

If you want to be able to read each character as it is typed, you have
to:

1. disable line buffering in the terminal, and
2. disable line buffering in the stdio library,

with something like:

int set_raw_mode(void)
{
	int fd = STDIN_FILENO;
	struct termios t;

	if (tcgetattr(fd, &t) < 0)
	{
		perror("tcgetattr");
		return -1;
	}

	t.c_lflag &= ~ICANON;

	if (tcsetattr(fd, TCSANOW, &t) < 0)
	{
		perror("tcsetattr");
		return -1;
	}

	setbuf(stdin, NULL);

	return 0;
}

As for checking whether any input is available, you can use select()
or ioctl(FIONREAD).

If you are planning on doing much programming on Linux, it would be
worthwhile getting a decent book on Unix programming. It's quite
different to DOS.

-- 
Glynn Clements <glynn at sensei.co.uk>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo at vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~Randy
___________________________________________________
|Randy Dunlap     Intel Corp., DAL    Sr. SW Engr.|
|randy.dunlap.at.intel.com            503-696-2055|
|NOTE:  Any views presented here are mine alone   |
|and may not represent the views of my employer.  |
|_________________________________________________|

> I've inherited a MSWin console application which tests for operator
> keystroke input while repeatedly calling a service routine, 
> then exits on
> a keystroke. Could someone please remind me how to fake those 
> DOS-style
> tests in UNIX/Linux, or suggest a library with exports these
> Borland/MS-style functions? I have seen this, but draw a 
> blank at present.
> 
> I could use Stevens' APUE/Ch.11 examples, but a handy-dandy 
> interface lib would be great!

--
To unsubscribe: mail majordomo at ale.org with "unsubscribe ale" in message body.





More information about the Ale mailing list