Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

327 lines (310 sloc) 6.855 kb
/* $Id: ttymodes.c,v 1.21 2011/12/06 10:29:59 tom Exp $ */
#include <vttest.h>
#include <ttymodes.h>
#include <esc.h> /* inflush() */
#undef tabs
#ifdef TAB3
# define tabs TAB3
#else
# ifdef XTABS
# define tabs XTABS
# else
# ifdef OXTABS
# define tabs OXTABS
# else
# define tabs 0
# endif
# endif
#endif
static TTY old_modes, new_modes;
/* *INDENT-OFF* */
static struct {
int name;
int code;
} speeds[] = {
{B0, 0},
{B50, 50},
{B75, 75},
{B110, 110},
{B134, 134},
{B150, 150},
{B200, 200},
{B300, 300},
{B600, 600},
{B1200, 1200},
{B1800, 1800},
{B2400, 2400},
{B4800, 4800},
{B9600, 9600},
#ifdef B19200
{B19200, 19200},
#else
#ifdef EXTA
{EXTA, 19200},
#endif
#endif
#ifdef B38400
{B38400, 38400},
#else
#ifdef EXTB
{EXTB, 38400},
#endif
#endif
#ifdef B57600
{B57600, 57600},
#endif
#ifdef B115200
{B115200, 115200},
#endif
};
/* *INDENT-ON* */
#if !USE_POSIX_TERMIOS && !USE_TERMIO && USE_SGTTY
static struct tchars old_tchars;
static struct ltchars old_ltchars;
#endif
#if USE_POSIX_TERMIOS || USE_TERMIO
static void
disable_control_chars(TTY * modes)
{
# if USE_POSIX_TERMIOS
int n;
int temp;
# ifdef HAVE_POSIX_VDISABLE
temp = _POSIX_VDISABLE;
# else
errno = 0;
temp = fpathconf(0, _PC_VDISABLE);
if (temp == -1) {
if (errno != 0) {
restore_ttymodes();
fprintf(stderr, "Cannot disable special characters!\n");
exit(EXIT_FAILURE);
}
temp = 0377;
}
# endif
for (n = 0; n < NCCS; n++)
modes->c_cc[n] = (unsigned char) temp;
# else /* USE_TERMIO */
# ifdef VSWTCH
modes->c_cc[VSWTCH] = VDISABLE;
# endif
modes->c_cc[VSUSP] = VDISABLE;
# if defined (VDSUSP) && defined(NCCS) && VDSUSP < NCCS
modes->c_cc[VDSUSP] = VDISABLE;
# endif
modes->c_cc[VSTART] = VDISABLE;
modes->c_cc[VSTOP] = VDISABLE;
# endif
modes->c_cc[VMIN] = 1;
modes->c_cc[VTIME] = 0;
}
#endif
static void
set_ttymodes(TTY * modes)
{
# if USE_POSIX_TERMIOS
fflush(stdout);
tcsetattr(0, TCSAFLUSH, modes);
# else
# if USE_TERMIO
tcsetattr(0, TCSETAF, modes);
# else /* USE_SGTTY */
stty(0, modes);
# endif
# endif
}
#ifndef log_ttymodes
void
log_ttymodes(char *file, int line)
{
if (LOG_ENABLED)
fprintf(log_fp, "%s @%d\n", file, line);
}
#endif
#ifndef dump_ttymodes
void
dump_ttymodes(char *tag, int flag)
{
#ifdef UNIX
TTY tmp_modes;
if (LOG_ENABLED) {
fprintf(log_fp, "%s (%d):\n", tag, flag);
# if USE_POSIX_TERMIOS || USE_TERMIO
tcgetattr(0, &tmp_modes);
fprintf(log_fp, " iflag %08o\n", tmp_modes.c_iflag);
fprintf(log_fp, " oflag %08o\n", tmp_modes.c_oflag);
fprintf(log_fp, " lflag %08o\n", tmp_modes.c_lflag);
if (!tmp_modes.c_lflag & ICANON) {
fprintf(log_fp, " %d:min =%d\n", VMIN, tmp_modes.c_cc[VMIN]);
fprintf(log_fp, " %d:time =%d\n", VTIME, tmp_modes.c_cc[VTIME]);
}
# else
gtty(0, &tmp_modes);
fprintf(log_fp, " flags %08o\n", tmp_modes.sg_flags);
# endif
}
#endif
}
#endif
void
close_tty(void)
{
restore_ttymodes();
}
void
init_ttymodes(int pn)
{
int speed_code, n;
dump_ttymodes("init_ttymodes", pn);
#ifdef UNIX
if (pn == 0) {
fflush(stdout);
# if USE_POSIX_TERMIOS || USE_TERMIO
tcgetattr(0, &old_modes);
speed_code = (int) cfgetospeed(&old_modes);
# else
# if USE_SGTTY
gtty(0, &old_modes);
ioctl(0, TIOCGETC, &old_tchars);
ioctl(0, TIOCGLTC, &old_ltchars);
speed_code = old_modes.sg_ospeed;
# endif
# endif
new_modes = old_modes;
for (n = 0; n < TABLESIZE(speeds); n++) {
if (speeds[n].name == speed_code) {
tty_speed = speeds[n].code;
break;
}
}
} else {
putchar(BEL);
fflush(stdout);
inflush();
new_modes = old_modes;
sleep(2);
}
# if USE_POSIX_TERMIOS || USE_TERMIO
new_modes.c_iflag = BRKINT | old_modes.c_iflag;
new_modes.c_oflag &= (unsigned) ~tabs;
# else /* USE_SGTTY */
new_modes.sg_flags = old_modes.sg_flags | CBREAK;
# endif
set_ttymodes(&new_modes);
# ifdef HAVE_FCNTL_H
# ifndef O_NDELAY
# define O_NDELAY O_NONBLOCK /* O_NONBLOCK is POSIX */
# endif
close(2);
open("/dev/tty", O_RDWR | O_NDELAY);
# endif
#endif /* UNIX */
dump_ttymodes("...init_ttymodes", pn);
}
void
restore_ttymodes(void)
{
dump_ttymodes("restore_ttymodes", -1);
#ifdef UNIX
set_ttymodes(&old_modes);
#endif
dump_ttymodes("...restore_ttymodes", -1);
}
void
set_tty_crmod(int enabled)
{
dump_ttymodes("set_tty_crmod", enabled);
#ifdef UNIX
# if USE_POSIX_TERMIOS || USE_TERMIO
# if USE_POSIX_TERMIOS
# define MASK_CRMOD ((unsigned) (ICRNL | IXON))
# else
# define MASK_CRMOD ((unsigned) (ICRNL))
# endif
if (enabled) {
new_modes.c_iflag |= MASK_CRMOD;
new_modes.c_lflag |= ICANON;
memcpy(new_modes.c_cc, old_modes.c_cc, sizeof(new_modes.c_cc));
} else {
new_modes.c_iflag &= ~MASK_CRMOD;
new_modes.c_lflag &= (unsigned) ~ICANON;
disable_control_chars(&new_modes);
}
# else
if (enabled)
new_modes.sg_flags |= CRMOD;
else
new_modes.sg_flags &= ~CRMOD;
# endif
set_ttymodes(&new_modes);
#endif
dump_ttymodes("...set_tty_crmod", enabled);
}
void
set_tty_echo(int enabled)
{
dump_ttymodes("set_tty_echo", enabled);
#ifdef UNIX
# if USE_POSIX_TERMIOS || USE_TERMIO
if (enabled)
new_modes.c_lflag |= ECHO;
else
new_modes.c_lflag &= (unsigned) ~ECHO;
# else /* USE_SGTTY */
if (enabled)
new_modes.sg_flags |= ECHO;
else
new_modes.sg_flags &= (unsigned) ~ECHO;
# endif
set_ttymodes(&new_modes);
#endif
dump_ttymodes("...set_tty_echo", enabled);
}
void
set_tty_raw(int enabled)
{
dump_ttymodes("set_tty_raw", enabled);
if (enabled) {
#ifdef UNIX
# if USE_POSIX_TERMIOS || USE_TERMIO
/* *INDENT-EQLS* */
new_modes.c_iflag = 0;
new_modes.c_lflag = 0;
new_modes.c_cc[VMIN] = 1;
new_modes.c_cc[VTIME] = 0;
set_ttymodes(&new_modes);
set_tty_crmod(FALSE);
# else /* USE_SGTTY */
# ifdef HAVE_FCNTL_H
new_modes.sg_flags &= ~CBREAK;
# endif
new_modes.sg_flags |= RAW;
set_ttymodes(&new_modes);
{
struct tchars tmp_tchars;
struct ltchars tmp_ltchars;
memset(&tmp_tchars, -1, sizeof(tmp_tchars));
memset(&tmp_ltchars, -1, sizeof(tmp_ltchars));
ioctl(0, TIOCSETC, &tmp_tchars);
ioctl(0, TIOCSLTC, &tmp_ltchars);
}
# endif
#endif
} else {
#ifdef UNIX
# if USE_POSIX_TERMIOS || USE_TERMIO
new_modes = old_modes; /* FIXME */
# else /* USE_SGTTY */
new_modes.sg_flags &= ~RAW;
# ifdef HAVE_FCNTL_H
new_modes.sg_flags |= CBREAK;
# endif
ioctl(0, TIOCSETC, &old_tchars);
ioctl(0, TIOCSLTC, &old_ltchars);
# endif
set_ttymodes(&new_modes);
#endif
}
dump_ttymodes("...set_tty_raw", enabled);
}
Jump to Line
Something went wrong with that request. Please try again.