I'm new to Linux. For a C console application I need unbuffered keyboard input
(non blocked). I have tried to use select() and poll() but they both buffer
until a '\n'. setvbuf() to set the stream unbuffered don't seem to work.
In some operating systems it's posible to set a signal/event on data available.
Is there a way to do a timed read() that isn't buffered. How to set the the
input stream to unbuffered.
Thanks in advancd for any help.
Michel.
select/poll/read/write works on descriptors, setvbuf on FILE*s, you
shouldn't mix them.
>
> In some operating systems it's posible to set a signal/event on data available.
>
> Is there a way to do a timed read() that isn't buffered. How to set the the
> input stream to unbuffered.
an input stream(well, not a FILE* stream) connected to a terminal/tty is
usually
line buffered, you can turn off that
http://www.iso-9899.info/wiki/Snippet_POSIX_STDIN_mode
http://www.daimi.au.dk/~kasperd/comp.os.linux.development.faq.html#termios
--
Kasper Dupont -- Rigtige mænd skriver deres egne backupprogrammer
#define _(_)"d.%.4s%."_"2s" /* This is my new email address */
char*_="@2kaspner"_()"%03"_("4s%.")"t\n";printf(_+11,_+6,_,6,_+2,_+7,_+6);
Michel van Bergen wrote:
> Hi,
>
> I'm new to Linux. For a C console application I need unbuffered keyboard input
> (non blocked). I have tried to use select() and poll() but they both buffer
> until a '\n'. setvbuf() to set the stream unbuffered don't seem to work.
That's because you are going down the wrong path, and haven't really
changed the buffering.
What you want to do is read the termios(3) manpage ("man 3 termios") and
tty_ioctl(4) manpage ("man 4 tty_ioctl"), and turn off ICANON parsing on
your terminal.
You have your choice of the termios(3) interface, or the ioctl(2)
interface; ioctl(2) is a low-level interface, while termios(3) is higher
level. I'd suggest sticking with the termios(3) interface.
Your code will look something like...
#include <termios.h>
set_to_raw(int tty_fd)
{
struct termios tty_attr;
tcgetattr(tty_fd,&tty_attr);
tty_attr.c_lflag &= ~ICANON;
tcsetattr(tty_fd,&tty_attr);
}
Of course, you will, at some point, need to set the fd back to ICANON
processing. Just OR back in the ICANON flag at that point.
- --
Lew Pitcher, IT Specialist, Corporate Technology Solutions,
Enterprise Technology Solutions, TD Bank Financial Group
(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFECE4OagVFX4UWr64RAkzmAJ9kan1Wdor7DYFYAL1ARliYZZ6swwCfcANn
++anLPI+8S1NgKtfrJiyPcw=
=FZZ8
-----END PGP SIGNATURE-----
You had many nice suggestions, I used this a lot:
#include <stdio.h>
int main(int argc, char **argv)
{
int c;
while(1)
{
/* read a user key */
system("stty raw");
c = getc(stdin);
if(c == 27) break; /* ESCAPE exits */
system("stty sane"); // you can do this later
printf(": c = %d\n", c);
}
exit(0);
}
Thanks all.
You put me on the right path
Michel.