#if defined(__BEOS__)
#include <OS.h>
#endif
#include <signal.h>
#include <tack.h>
#include <term.h>
#include <errno.h>
#if HAVE_SELECT
#if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT
#include <sys/time.h>
#endif
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif
MODULE_ID("$Id: sysdep.c,v 1.1.1.1 2001/11/29 20:40:59 jevans Exp $")
#if DECL_ERRNO
extern int errno;
#endif
#ifdef TERMIOS
#define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)
#else
#define PUT_TTY(fd, buf) stty(fd, buf)
#endif
int tty_frame_size;
unsigned long tty_baud_rate;
int not_a_tty;
int nodelay_read;
#ifdef TERMIOS
#define TTY_IS_NOECHO !(new_modes.c_lflag & ECHO)
#define TTY_IS_OUT_TRANS (new_modes.c_oflag & OPOST)
#define TTY_IS_CHAR_MODE !(new_modes.c_lflag & ICANON)
#define TTY_WAS_CS8 ((old_modes.c_cflag & CSIZE) == CS8)
#define TTY_WAS_XON_XOFF (old_modes.c_iflag & (IXON|IXOFF))
#else
#define TTY_IS_NOECHO !(new_modes.sg_flags & (ECHO))
#define TTY_IS_OUT_TRANS (new_modes.sg_flags & (CRMOD))
#define TTY_IS_CHAR_MODE (new_modes.sg_flags & (RAW|CBREAK))
#define TTY_WAS_CS8 (old_modes.sg_flags & (PASS8))
#define TTY_WAS_XON_XOFF (old_modes.sg_flags & (TANDEM|MDMBUF|DECCTQ))
#endif
static TTY old_modes, new_modes;
void catchsig(void);
#ifndef XCASE
#define XCASE 0
#endif
#ifndef OLCUC
#define OLCUC 0
#endif
#ifndef IUCLC
#define IUCLC 0
#endif
#ifndef TABDLY
#define TABDLY 0
#endif
#ifndef IXANY
#define IXANY 0
#endif
void
tty_raw(int minch GCC_UNUSED, int mask)
{
new_modes = old_modes;
#ifdef TERMIOS
#if HAVE_SELECT
new_modes.c_cc[VMIN] = 1;
#else
new_modes.c_cc[VMIN] = minch;
#endif
new_modes.c_cc[VTIME] = 2;
new_modes.c_lflag &=
~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL);
#ifdef LOBLK
new_modes.c_lflag &= ~LOBLK;
#endif
new_modes.c_oflag &= ~(OPOST | OLCUC | TABDLY);
if (mask == ALLOW_PARITY) {
new_modes.c_cflag &= ~(CSIZE | PARENB | HUPCL);
new_modes.c_cflag |= CS8;
}
new_modes.c_iflag &=
~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL |
IUCLC | IXON | IXANY | IXOFF);
#else
new_modes.sg_flags |= RAW;
#endif
if (not_a_tty)
return;
PUT_TTY(fileno(stdin), &new_modes);
}
void
tty_set(void)
{
new_modes = old_modes;
#ifdef TERMIOS
new_modes.c_cc[VMIN] = 1;
new_modes.c_cc[VTIME] = 1;
new_modes.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
#if defined(ONLCR) && defined(OCRNL) && defined(ONLRET) && defined(OFILL)
new_modes.c_oflag &= ~(ONLCR | OCRNL | ONLRET | OFILL);
#else
new_modes.c_oflag &= ~(OPOST);
#endif
if (char_mask == ALLOW_PARITY)
new_modes.c_iflag &= ~ISTRIP;
switch (select_xon_xoff) {
case 0:
new_modes.c_iflag &= ~(IXON | IXOFF);
break;
case 1:
#if defined(sequent) && sequent
new_modes = old_modes;
new_modes.c_cc[VEOL] = 6;
#endif
new_modes.c_iflag |= IXON | IXOFF;
break;
}
switch (select_delay_type) {
case 0:
#ifdef NLDLY
new_modes.c_oflag &=
~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
#endif
break;
case 1:
#ifdef NLDLY
new_modes.c_oflag &=
~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
#endif
#ifdef NL1
new_modes.c_oflag |= NL1 | CR2;
#endif
break;
}
if (!(new_modes.c_oflag & ~OPOST))
new_modes.c_oflag &= ~OPOST;
#else
new_modes.sg_flags |= RAW;
if (not_a_tty)
return;
#endif
PUT_TTY(fileno(stdin), &new_modes);
}
void
tty_reset(void)
{
fflush(stdout);
if (not_a_tty)
return;
PUT_TTY(fileno(stdin), &old_modes);
}
void
tty_init(void)
{
#if defined(F_GETFL) && defined(O_NDELAY)
int flags;
flags = fcntl(fileno(stdin), F_GETFL, 0);
nodelay_read = flags & O_NDELAY;
#else
nodelay_read = FALSE;
#endif
not_a_tty = FALSE;
if (GET_TTY(fileno(stdin), &old_modes) == -1) {
if (errno == ENOTTY) {
tty_frame_size = 20;
not_a_tty = TRUE;
return;
}
printf("tcgetattr error: %d\n", errno);
exit(1);
}
new_modes = old_modes;
#ifdef TERMIOS
#ifdef TABDLY
new_modes.c_oflag &= ~TABDLY;
#endif
#endif
if (PUT_TTY(fileno(stdin), &new_modes) == -1) {
printf("tcsetattr error: %d\n", errno);
exit(1);
}
#ifdef sequent
old_modes.c_cflag &= ~(CSIZE | CSTOPB);
old_modes.c_cflag |= CS7 | PARENB;
#endif
catchsig();
#ifdef TERMIOS
switch (old_modes.c_cflag & CSIZE) {
#if defined(CS5) && (CS5 != 0)
case CS5:
tty_frame_size = 10;
break;
#endif
#if defined(CS6) && (CS6 != 0)
case CS6:
tty_frame_size = 12;
break;
#endif
#if defined(CS7) && (CS7 != 0)
case CS7:
tty_frame_size = 14;
break;
#endif
#if defined(CS8) && (CS8 != 0)
case CS8:
tty_frame_size = 16;
break;
#endif
}
tty_frame_size += 2 +
((old_modes.c_cflag & PARENB) ? 2 : 0) +
((old_modes.c_cflag & CSTOPB) ? 4 : 2);
#else
tty_frame_size = 6 +
(old_modes.sg_flags & PASS8) ? 16 : 14;
#endif
}
int
stty_query(int q)
{
switch (q) {
case TTY_NOECHO:
return TTY_IS_NOECHO;
case TTY_OUT_TRANS:
return TTY_IS_OUT_TRANS;
case TTY_CHAR_MODE:
return TTY_IS_CHAR_MODE;
}
return (-1);
}
int
initial_stty_query(int q)
{
switch (q) {
case TTY_8_BIT:
return TTY_WAS_CS8;
case TTY_XON_XOFF:
return TTY_WAS_XON_XOFF;
}
return (-1);
}
#if HAVE_SELECT && defined(FD_ZERO)
static int
char_ready(void)
{
int n;
fd_set ifds;
struct timeval tv;
FD_ZERO(&ifds);
FD_SET(fileno(stdin), &ifds);
tv.tv_sec = 0;
tv.tv_usec = 200000;
n = select(fileno(stdin)+1, &ifds, NULL, NULL, &tv);
return (n != 0);
}
#else
#ifdef FIONREAD
int
char_ready(void)
{
int i, j;
for (j = 0; j < 1000; j++) {
ioctl(fileno(stdin), FIONREAD, &i);
if (i)
return i;
}
return i;
}
#else
#if defined(__BEOS__)
int
char_ready(void)
{
int n = 0;
int howmany = ioctl(0, 'ichr', &n);
return (howmany >= 0 && n > 0);
}
#else
#define char_ready() 1
#endif
#endif
#endif
void
spin_flush(void)
{
unsigned char buf[64];
fflush(stdout);
event_start(TIME_FLUSH);
do {
if (char_ready()) {
(void) read(fileno(stdin), &buf, sizeof(buf));
}
} while (event_time(TIME_FLUSH) < 400000);
}
void
read_key(char *buf, int max)
{
int got, ask, i, l;
char *s;
*buf = '\0';
s = buf;
fflush(stdout);
while (read(fileno(stdin), s, 1) == 0);
++s;
--max;
while (max > 0 && (ask = char_ready())) {
if (ask > max) {
ask = max;
}
if ((got = read(fileno(stdin), s, ask))) {
s += got;
} else {
break;
}
max -= got;
}
*s = '\0';
l = s - buf;
for (s = buf, i = 0; i < l; i++) {
if ((*s & 0x7f) == 0) {
*(unsigned char *)s = 128;
} else {
*s &= char_mask;
}
}
}
void
ignoresig(void)
{
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGALRM, SIG_IGN);
}
static RETSIGTYPE
onintr(int sig GCC_UNUSED)
{
ignoresig();
tty_reset();
exit(1);
}
void
catchsig(void)
{
if ((signal(SIGINT, SIG_IGN)) == SIG_DFL)
signal(SIGINT, onintr);
if ((signal(SIGHUP, SIG_IGN)) == SIG_DFL)
signal(SIGHUP, onintr);
if ((signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
signal(SIGQUIT, onintr);
if ((signal(SIGTERM, SIG_IGN)) == SIG_DFL)
signal(SIGTERM, onintr);
}
static void
alarm_event(
int sig GCC_UNUSED)
{
no_alarm_event = 0;
}
void
set_alarm_clock(
int seconds)
{
signal(SIGALRM, alarm_event);
no_alarm_event = 1;
(void) alarm(seconds);
}