[prog] C problem I am unable to solve

John Clarke johnc+linuxchix at kirriwa.net
Fri May 13 12:50:12 EST 2005


On Thu, May 12, 2005 at 08:58:36 +0100, Conor Daly wrote:

> I'm wondering if there's an ordinary way in C to just grab a single
> char from stdin without waiting for an <ENTER> keystroke? 

I don't know if simply turning off buffering will do it, or whether you
need to put the terminal into raw mode.  Turning off buffering is
simple: just call "setbuf(stdin, NULL)".

Putting the terminal into raw mode is a little harder, but something
like this will do it (untested but mostly stolen from a working
program):

    /* saved state of stdin so it can be restored on exit */
    struct termios SavedStdInState;

    void RestoreTerminalState(void)
    {
        tcsetattr(fileno(stdin), TCSAFLUSH, &SavedStdInState);
    }

    int SaveTerminalState(void)
    {
        return tcgetattr(fileno(stdin), &SavedStdInState);
    }

    int SetUnbufferedRawMode(void)
    {
        struct termios T;
        int Error, Flags;

        /* save state and make sure it's restored on exit */
        if ((Error = SaveTerminalState()) != 0)
            return Error;
        if ((Error = atexit(RestoreTerminalState)) ! = 0)
            return Error;

        /* set stdin to be unbuffered and non-blocking */
        setbuf(stdin, NULL);
        if ((Flags = fcntl(fileno(stdin), F_GETFL, 0)) == -1)
            return Flags;
        if ((Error = fcntl(fileno(stdin), F_SETFL, Flags | O_NONBLOCK)) != 0)
            return Error;

        /* get current terminal attributes */
        if ((Error = tcgetattr(fileno(stdin), &T)) != 0)
            return Error;

        /* turn off echo and line editing */
        T.c_lflag &= ~(ECHO | ICANON | IEXTEN);
        T.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        T.c_cflag &= ~(CSIZE | PARENB);
        T.c_cflag |= CS8;
        T.c_cc[VMIN] = 1;
        T.c_cc[VTIME] = 0;

        return tcsetattr(fileno(stdin), TCSAFLUSH, &T);
    }


Note that in addition to setting raw mode, it also turns off character
echo.  Adding the required system header files is left as an exercise
for the reader :-)


Cheers,

John
-- 
> Why do polar bears never eat penguins?
Well, that's trivial. Penguins are pure evil. They _ate_ all the polar
bears at the antartic. And now they're moving north.
            -- Abigail


More information about the Programming mailing list