/*
 * getkey.c - Single-key TTY input
 *
 * Written 2010 by Werner Almesberger
 * Copyright 2010 Werner Almesberger
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */


#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>

#include "getkey.h"


#define	TTY_NAME	"/dev/tty"


static int tty = -1;
static struct termios old;


static void reset_tty(void)
{
	if (tty >= 0)
		if (tcsetattr(tty, TCSADRAIN, &old) < 0)
			perror("tcsetattr");
}


static void tty_open(void)
{
	struct termios new;

	tty = open(TTY_NAME, O_RDONLY | O_NOCTTY);
	if (tty < 0) {
		perror(TTY_NAME);
		exit(1);
	}

	if (tcgetattr(tty, &old) < 0) {
		perror("tcgetattr");
		exit(1);
	}
	atexit(reset_tty);

	new = old;
	cfmakeraw(&new);
	if (tcsetattr(tty, TCSANOW, &new) < 0) {
		perror("tcsetattr");
		exit(1);
	}
}


char getkey(void)
{
	char buf;
	ssize_t got;

	if (tty == -1)
		tty_open();
	got = read(tty, &buf, 1);
	if (got < 0) {
		perror("read");
		reset_tty();
		exit(1);
	}
	return got ? buf : 0;
}