[net.lang.c] 1-char input in C

mort@ihuxn.UUCP (Dubman) (12/22/83)

I am writing a program in C that requires a menu with four choices,
I, D, L, and Q for Insert, Delete, List and Quit.

I want to have it so that the program can key an ASCII value for the key
from the VT100 terminal without having to have the user type RETURN.

I tried using getchar() but inputs an entire line up to the RETURN, returns
the first letter, and shoves the rest in a buffer that is emptied the next
time getchar() is called.

Any ideas?

		Thanks in Advance,


-- 

Jonathan Dubman - care of:

		Mort Dubman		AT&T Bell Laboratories
		ihnp4!ihuxn!mort	Naperville, IL.

john@genrad.UUCP (John Nelson) (12/23/83)

Your problem is a common one.  The problem is that UNIX is buffering up
the data, as opposed to the C library routines.  The most portable solution
(and easiest to understand) is to use the system() call to change the
tty mode as follows:

#include <stdio.h>
main() {
    system("stty raw");		/* dont buffer data */
    getchar();
    system("stty -raw");	/* restore normal buffering */
}

The other option is to use ioctl() (or gtty & stty on systems that have it)
to set the tty modes properly.  The problem with this is that BELL, BSD and
V7 systems are all different in the exact format of these ioctl()'s

bbanerje@sjuvax.UUCP (B. Banerjee) (12/25/83)

>>(and easiest to understand) is to use the system() call to change the
>>tty mode as follows:

>>#include <stdio.h>
>>main() {
>>    system("stty raw");		/* dont buffer data */
>>    getchar();
>>    system("stty -raw");	/* restore normal buffering */
>>}
>>
>>The other option is to use ioctl() (or gtty & stty on systems that have
>>it) to set the tty modes properly.  The problem with this is that BELL,
>>BSD and V7 systems are all different in the exact format of these
>>ioctl()'s

Nice solution.  I was about to suggest mucking around with ioctl().
However, if I remember correctly from K & R, getchar() and putchar()
buffer their input/output respectively.  It might be best to use
read() instead. 
-- 


				Binayak Banerjee
		{allegra | astrovax | bpa | burdvax}!sjuvax!bbanerje

franka@tekcad.UUCP (12/25/83)

#R:ihuxn:-46300:tekcad:2600002:000:1170
tekcad!franka    Dec 25 10:10:00 1983

>Your problem is a common one.  The problem is that UNIX is buffering up
>the data, as opposed to the C library routines.  The most portable solution
>(and easiest to understand) is to use the system() call to change the
>tty mode as follows:
>
>#include <stdio.h>
>main() {
>    system("stty raw");		/* dont buffer data */
>    getchar();
>    system("stty -raw");	/* restore normal buffering */
>}
>
>The other option is to use ioctl() (or gtty & stty on systems that have it)
>to set the tty modes properly.  The problem with this is that BELL, BSD and
>V7 systems are all different in the exact format of these ioctl()'s

	The other problem with this is that if somebody hits a ^C (or ^\)
during the getchar, the terminal gets put in "raw" mode. This is very, very
confusing to a novice user (I assume that is who you are writing for, with
such a limited command set) who suddenly cannot backspace, use the return
key on a command, etc.

               				From the truly menacing,
   /- -\       				but usually underestimated
    <->                                 and soon to be gone,
               				Frank Adrian
               				(tektronix!tekcad!franka)

grunwald@uiuccsb.UUCP (01/13/84)

#R:ihuxn:-46300:uiuccsb:9000009:000:915
uiuccsb!grunwald    Jan 12 12:21:00 1984

re: using read over getchar to not buffer input

While it is true that when using the STDIO package, getchar and putchar cause
input to be buffered, the action that is occuring is due to the terminal
device driver. If one used "read" without changing to cbreak or raw mode, you
would still need to press return for the read to finish.
   When not using STDIO, getchar is equivilent to:

getchar()
{
	int	ch;
	read(STDIN,ch,1);
	return(ch);
}

When using STDIO, getchar is in fact a #define macro. When it runs out of
valid data in the current buffer, it calls "read" to fill up the buffer.

   If you're not doing a lot of mucking around, with switching between CBREAK,
RAW and COOKED modes, using the "system" call is sufficient. Otherwise, you
might want to look at ioctl(2) and tty(4) in the UNIX manual.

Dirk Grunwald
University of Illinois
USENET	: ihnp4 ! uiucdcs ! grunwald
CSNET	: grunwald.uiuc@Rand-Relay