#include <signal.h>

#include <sys/time.h> /* struct timeval, select() */

/* ICANON, ECHO, TCSANOW, struct termios */

#include <termios.h> /* tcgetattr(), tcsetattr() */

#include <stdlib.h> /* atexit(), exit() */

#include <unistd.h> /* read() */

#include <stdio.h> /* printf() */

 

static struct termios g_old_kbd_mode;

/*****************************************************************************

*****************************************************************************/

static void cooked(void)

{

        tcsetattr(0, TCSANOW, &g_old_kbd_mode);

}

/*****************************************************************************

*****************************************************************************/

static void raw(void)

{

        static char init;

/**/

        struct termios new_kbd_mode;

 

        if(init)

                return;

/* put keyboard (stdin, actually) in raw, unbuffered mode */

        tcgetattr(0, &g_old_kbd_mode);

        memcpy(&new_kbd_mode, &g_old_kbd_mode, sizeof(struct termios));

        new_kbd_mode.c_lflag &= ~(ICANON | ECHO);

        new_kbd_mode.c_cc[VTIME] = 0;

        new_kbd_mode.c_cc[VMIN] = 1;

        tcsetattr(0, TCSANOW, &new_kbd_mode);

/* when we exit, go back to normal, "cooked" mode */

        atexit(cooked);

 

        init = 1;

}

/*****************************************************************************

*****************************************************************************/

static int kbhit(void)

{

        struct timeval timeout;

        fd_set read_handles;

        int status;

 

        raw();

/* check stdin (fd 0) for activity */

        FD_ZERO(&read_handles);

        FD_SET(0, &read_handles);

        timeout.tv_sec = timeout.tv_usec = 0;

        status = select(0 + 1, &read_handles, NULL, NULL, &timeout);

        if(status < 0)

        {

                printf("select() failed in kbhit()\n");

                exit(1);

        }

        return status;

}

/*****************************************************************************

*****************************************************************************/

static int getch(void)

{

        unsigned char temp;

 

        raw();

/* stdin = fd 0 */

        if(read(0, &temp, 1) != 1)

                return 0;

        return temp;

}