9

How to capture all the user input, reading one byte at a time?

I did this coding, but it's not working

if ((fd = open("/dev/char", O_RDONLY) != 1) {
    tty = open("/dev/tty", O_RDONLY);
    tcsetattr(0, TCSANOW, &orig_info);
    read (fd, &buf, sizeof(char));
}
close(fd);

I expected the terminal to wait for input, but it didn't.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Bunny Bunny
  • 745
  • 2
  • 6
  • 9

2 Answers2

14

The keyboard device itself is one of the entries in /dev/input. You can locate keyboards and other input devices by their connection type (e.g. PS/2, USB, …) in /dev/input/by-path. Obviously, you'll need to run as root to access the hardware directly, and you'll need to provide your own translation from raw bytes coming from the keyboard into things like key presses and key releases. This is probably not what you want.

If you're running a GUI application, the low-level method is to call XNextEvent and other functions in the same family. Decoding input events isn't completely trivial, as it's up to applications to apply modifiers. A GUI framework (Motif, Gtk, Qt, …) would help you.

If you're running a terminal application, read from standard input or from /dev/tty (/dev/tty is always the terminal that your program is running on, even if standard input has been redirected). You'll want to put the terminal in raw mode. You'll get decoded character keys, and function keys mostly as escape sequences. Here, too, a library helps; the de facto standard is ncurses.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
2

What exactly do you want to do?

If what you are looking for is unbuffered input in terminal, tcsetattr() is what you are looking for - you need to put the terminal into the non-canonical mode, i.e. set the terminal flags not to contain ICANON - see e.g. this code snippet. See man termios (or the function name, it usually links to the same man page on Linux).

If you want to have exclusive access to the keyboard, it is much more complicated.

peterph
  • 980
  • 6
  • 11
  • @BunnyBunny the thing is that in most cases you **don't** want to read from the keyboard as such - Gilles answer sums that pretty well (as always :)). And that's why it's better to describe the problem you are trying to solve - it might turn out that you are not headed in the best direction. – peterph Apr 08 '13 at 09:58
  • @peterph The problem is very simple. Open keyboard device and read one byte at a time. To gain control over keyboard we ahve to pen /dev/tty explicitly. – Bunny Bunny Apr 08 '13 at 12:52
  • 1
    @BunnyBunny `/dev/tty` **is not** the keyboard device, it is processed input (and doesn't even need to be a local keyboard in case of e.g. remote shells). That's why I wrote that stating your problem might help - *"I need to open keyboard device"* is not the problem you are solving - rather it is something like *"I need to read password from the user one character of input at a time and it must not be echoed on the screen"* or *"I need to capture **all** keyboard input"*. Giving more context will get you better answers. – peterph Apr 08 '13 at 13:01