Listing 2. Terminal I/O Examples

#include <termios.h>
#include <signal.h>
#include <stdlib.h>

/* This will be used for new terminal settings */
static struct termios current;

/* This will hold the initial state so that we
 * can restore it later. */
static struct termios initial;

/* Restore the terminal settings to those saved
 * when term_init was called. */
void term_restore(void)
{
  tcsetattr(0, TCSANOW, &initial);
}

/* Clean up terminal; called on exit */
void term_exit()
{
  term_restore();
}

/* Will be called when control-Z is pressed;
 * this correctly handles the terminal. */
void term_ctrlz()
{
  signal(SIGTSTP, term_ctrlz);
  term_restore();
  signal(getpid(), SIGSTOP);
}

/* Will be called when the application is
 * continued after having been stopped. */
void term_cont()
{
  signal(SIGCONT, term_cont);
  tcsetattr(0, TCSANOW, &current);
}

/* Needs to be called to initialize the terminal */
void term_init(void)
{
  /* If stdin isn't a terminal this fails. But
   * then so does tcsetattr so it doesn't matter. */
  tcgetattr(0, &initial);
  /* Save a copy to work with later */
  current = initial;
  /* We _must_ clean up when we exit */
  signal(SIGINT, term_exit);
  signal(SIGQUIT, term_exit);
  /* Control-Z must also be handled */
  signal(SIGTSTP, term_ctrlz);
  signal(SIGCONT, term_cont);
  atexit(term_exit);
}

/* Set character-by-character input mode */
void term_character(void)
{
  /* One or more characters are sufficient
   * to cause a read to return. */
  current.c_cc[VMIN] = 1;
  /* No timeout; read waits forever
   * until ready. */
  current.c_cc[VTIME] = 0;
  /* Line-by-line mode off */
  current.c_lflag &= ~ICANON;
  tcsetattr(0, TCSANOW, &current);
}

/* Return to line-by-line input mode */
void term_line(void)
{
  current.c_lflag |= ICANON;
  tcsetattr(0, TCSANOW, &current);
}

Features


Porting DOS Applications to Linux