?? sysdep.c
字號:
/*** Copyright (C) 1991, 1997 Free Software Foundation, Inc.** ** This file is part of TACK.** ** TACK 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, or (at your option)** any later version.** ** TACK is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.** ** You should have received a copy of the GNU General Public License** along with TACK; see the file COPYING. If not, write to** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,** Boston, MA 02111-1307, USA.*//* * Operating system dependent functions. We assume the POSIX API. * Note: on strict-POSIX systems (including BSD/OS) the select_delay_type * global has no effect. */#include <signal.h> /* include before curses.h to work around glibc bug */#include <tack.h>#include <term.h>#include <errno.h>#if defined(__BEOS__)#undef false#undef true#include <OS.h>#endif#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#endifMODULE_ID("$Id: sysdep.c,v 1.11 2002/04/21 19:40:43 tom Exp $")#if DECL_ERRNOextern int errno;#endif#ifdef TERMIOS#define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)#else#define PUT_TTY(fd, buf) stty(fd, buf)#endif/* globals */int tty_frame_size; /* asynch frame size times 2 */unsigned long tty_baud_rate; /* baud rate - bits per second */int not_a_tty; /* TRUE if output is not a tty (i.e. pipe) */int nodelay_read; /* TRUE if NDELAY is set */#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))#endifstatic TTY old_modes, new_modes;void catchsig(void);/* * These are a sneaky way of conditionalizing bit unsets so strict-POSIX * systems won't see them. */#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#endifvoidtty_raw(int minch GCC_UNUSED, int mask){ /* set tty to raw noecho */ 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){ /* set tty to special modes */ 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 /* the sequent System V emulation is broken */ new_modes = old_modes; new_modes.c_cc[VEOL] = 6; /* control F (ACK) */#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 /* NLDLY */ break; case 1:#ifdef NLDLY new_modes.c_oflag &= ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);#endif /* NLDLY */#ifdef NL1 new_modes.c_oflag |= NL1 | CR2;#endif /* NL1 */ 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){ /* reset the tty to the original modes */ fflush(stdout); if (not_a_tty) return; PUT_TTY(fileno(stdin), &old_modes);}void tty_init(void){ /* ATT terminal init */#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); } /* if TAB3 is set then setterm() wipes out tabs (ht) */ new_modes = old_modes;#ifdef TERMIOS#ifdef TABDLY new_modes.c_oflag &= ~TABDLY;#endif /* TABDLY */#endif if (PUT_TTY(fileno(stdin), &new_modes) == -1) { printf("tcsetattr error: %d\n", errno); exit(1); }#ifdef sequent /* the sequent ATT emulation is broken soooo. */ 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}/*** stty_query(question)**** Does the current driver settings have this property?*/intstty_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);}/*** initial_stty_query(question)**** Did the initial driver settings have this property?*/intinitial_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 intchar_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 FIONREADintchar_ready(void){ int i, j; /* the following loop has to be tuned for each computer */ for (j = 0; j < 1000; j++) { ioctl(fileno(stdin), FIONREAD, &i); if (i) return i; } return i;}#else#if defined(__BEOS__)intchar_ready(void){ int n = 0; int howmany = ioctl(0, 'ichr', &n); return (howmany >= 0 && n > 0);}#else#define char_ready() 1#endif#endif#endif/*** spin_flush()**** Wait for the input stream to stop.** Throw away all input characters.*/voidspin_flush(void){ unsigned char buf[64]; fflush(stdout); event_start(TIME_FLUSH); /* start the timer */ do { if (char_ready()) { (void) read(fileno(stdin), &buf, sizeof(buf)); } } while (event_time(TIME_FLUSH) < 400000);}/*** read_key(input-buffer, length-of-buffer)**** read one function key from the input stream.** A null character is converted to 0x80.*/void read_key(char *buf, int max){ int got, ask, i, l; char *s; *buf = '\0'; s = buf; fflush(stdout); /* ATT unix may return 0 or 1, Berkeley Unix should be 1 */ 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) { /* convert nulls to 0x80 */ *(unsigned char *)s = 128; } else { /* strip high order bits (if any) */ *s &= char_mask; } }}void ignoresig(void){ /* ignore signals */ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGALRM, SIG_IGN);} /* onintr( ) is the interrupt handling routine onintr turns off interrupts while doing clean-up onintr always exits fatally */static RETSIGTYPE onintr(int sig GCC_UNUSED){ ignoresig(); tty_reset(); exit(1);} /* catchsig( ) set up to field interrupts (via function onintr( )) so that if interrupted we can restore the correct terminal modes catchsig simply returns */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);}/*** alarm_event(sig)**** Come here for an alarm event*/static voidalarm_event( int sig GCC_UNUSED){ no_alarm_event = 0;}/*** set_alarm_clock(seconds)**** Set the alarm clock to fire in <seconds>*/voidset_alarm_clock( int seconds){ signal(SIGALRM, alarm_event); no_alarm_event = 1; (void) alarm(seconds);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -