[PLUG] Terminals and stdin
Jonathan Sergent
sergent@ETLA.NET
Thu, 09 Sep 1999 23:50:38 -0700
/// jdaomteys@juno.com:
] I'm working on a C (not C++) program, and I need to read from the stdin
] buffer. The only problem is that when I do(tempchar = fgetc(stdin);), it
] pauses and waits for the terminal to send it something, but the terminal
] waits for the enter key to be pressed. Is there a way for me to disable
] the wait-for-enter thing, and to send the characters directly to the
] input buffer (I'm looking for a C function).
This has nothing to do with C or C++ in particular; it's a Unix thing.
Your terminal device (i.e. /dev/pts/1) is set to buffer lines when
you log into the system.
You need to change the tty modes so that the terminal device driver
passes characters to you one at a time.
>From a shell script or the command line, you would use the stty command,
like so:
stty raw
You return it to normal by doing:
stty sane
You probably won't notice anything if you do this while you're typing
since lots of shells reset the relevant mode bits before each prompt.
You can change tty modes from C on a POSIX compliant system (Linux,
Solaris, many more) with tcgetattr() and tcsetattr(). See the man page
for termios(3).
Something like this is probably what you want. I haven't tried this
code, but I think it's approximately correct.
/* (0 is the stdin fd) */
struct termios foo;
tcgetattr(0, &foo);
/* turn off canonical mode;
* disables buffering and processing of special characters */
foo.c_lflag &= ~(ICANON);
tcsetattr(0, TCSANOW, &foo);
Your fgetc's will return single characters now (as will system read()'s,
but fgetc is more efficient since it will do some buffering and reduce
the number of system calls made).
Make sure you turn the ICANON bit back on before you exit, or things will
be screwed when your program exits. Just do "foo.c_lflag |= ICANON;"
and then tcsetattr() again.
I hope this helps.
--jss.