TIM@ENH.Prime.COM (06/07/90)
I'm trying to write a function in C on Un*x that will allow me to read one character unbuffered from stdin. I'm using the Berkeley shell, but I want to write it to be able to use in the Bourne shell as well. If you're familiar with Turbo C on the PC, I'm trying to write a getche() function. If there's already one there, or you know how to make one function read one character unbuffered (not the whole program - just that function), please give me a clue. Send replies to address below, or post here. Thanks in advance! /* Tim Cantin, Prime Computer, Inc., MS 10-13 500 Old Conn Path, Framingham, MA 01701 (508)879-2960 x3101 (TIM@ENH.Prime.COM) || (csnet-relay!ENH.Prime.COM!TIM) */ #include "stddisclaimer.h"
hannum@chopin.psu.edu (Charles Hannum) (06/09/90)
What you need to do is set 'cbreak' mode on your tty. This tells the tty driver not to do line editing. Here's what to do: When you want to start character-by-character input: #include <sys/ioctl.h> #include <sgtty.h> struct sgttyb otty, ntty; /* emacs-insert-whatever-code-here */ ioctl(stdin, TIOCGETP, &otty); ntty=otty; ntty.sg_flags |= CBREAK; /* Use the following line if you *don't* want it to echo: */ /* ntty.sg_flags &= ~ECHO; */ ioctl(stdin, TIOCSETP, &ntty); /* emacs-insert-more-code-here */ Then, to set the terminal back to its previous mode: ioctl(stdin, TIOCSETP, &otty); MAKE SURE YOU DO THIS! If you don't set the tty back to the correct mode, you will have no line editing (and if you turned off echo, no echo either), which makes life very miserable. (tcsh sets the mode back automatically, BTW, but csh does not.) NOTE: This only works on ttys, not sockets or other types of files. -- Virtually, Charles Martin Hannum "Those who say a thing cannot be done should Please send mail to: under no circumstances stand in the way of hannum@schubert.psu.edu he who is doing it." - a misquote
scs@adam.mit.edu (Steve Summit) (06/12/90)
This topic is discussed in the frequently-asked questions list (question 43 in the June posting). In article <612@nic.stolaf.edu> hannum@chopin.psu.edu (Charles Hannum) writes: >What you need to do is set 'cbreak' mode on your tty. This is true only under some versions of Unix. It is not true under other versions of Unix (i.e. under System V and POSIX and related systems, including, I am told, 4.4bsd, you play with "min" and "time" parameters to set up various forms of "non- canonical mode input processing") nor is it generally true under non-Unix systems. > ioctl(stdin, TIOCGETP, &otty); stdin is usually a FILE *, not the int which ioctl expects. You could use fileno(stdin). Note that you should really make sure the ioctl succeeds -- it will not, for instance, in the common case when your program has its input redirected from a file. (Chris did note later in his posting that "this only works on ttys.") Steve Summit scs@adam.mit.edu > (tcsh sets the mode back automatically... A questionable feature, since (at least on the version of tcsh here, which may be out of date) the stty command cannot then be used to adjust terminal driver parameters you do want to change permanently. I'm sure there have been flame wars about this topic before; I probably shouldn't mention it.