2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
4 ** This file is part of TACK.
6 ** TACK is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2, or (at your option)
11 ** TACK is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
16 ** You should have received a copy of the GNU General Public License
17 ** along with TACK; see the file COPYING. If not, write to
18 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 ** Boston, MA 02110-1301, USA
22 * Operating system dependent functions. We assume the POSIX API.
23 * Note: on strict-POSIX systems (including BSD/OS) the select_delay_type
24 * global has no effect.
28 #include <ncurses_cfg.h>
30 #include <signal.h> /* include before curses.h to work around glibc bug */
44 #if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT
48 #include <sys/select.h>
52 MODULE_ID("$Id: sysdep.c,v 1.15 2005/09/17 19:49:16 tom Exp $")
59 #define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)
61 #define PUT_TTY(fd, buf) stty(fd, buf)
65 int tty_frame_size; /* asynch frame size times 2 */
66 unsigned tty_baud_rate; /* baud rate - bits per second */
67 int not_a_tty; /* TRUE if output is not a tty (i.e. pipe) */
68 int nodelay_read; /* TRUE if NDELAY is set */
71 #define TTY_IS_NOECHO !(new_modes.c_lflag & ECHO)
72 #define TTY_IS_OUT_TRANS (new_modes.c_oflag & OPOST)
73 #define TTY_IS_CHAR_MODE !(new_modes.c_lflag & ICANON)
74 #define TTY_WAS_CS8 ((old_modes.c_cflag & CSIZE) == CS8)
75 #define TTY_WAS_XON_XOFF (old_modes.c_iflag & (IXON|IXOFF))
77 #define TTY_IS_NOECHO !(new_modes.sg_flags & (ECHO))
78 #define TTY_IS_OUT_TRANS (new_modes.sg_flags & (CRMOD))
79 #define TTY_IS_CHAR_MODE (new_modes.sg_flags & (RAW|CBREAK))
80 #define TTY_WAS_CS8 (old_modes.sg_flags & (PASS8))
81 #define TTY_WAS_XON_XOFF (old_modes.sg_flags & (TANDEM|MDMBUF|DECCTQ))
84 static TTY old_modes, new_modes;
89 * These are a sneaky way of conditionalizing bit unsets so strict-POSIX
90 * systems won't see them.
109 tty_raw(int minch GCC_UNUSED, int mask)
110 { /* set tty to raw noecho */
111 new_modes = old_modes;
114 new_modes.c_cc[VMIN] = 1;
116 new_modes.c_cc[VMIN] = minch;
118 new_modes.c_cc[VTIME] = 2;
120 ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL);
122 new_modes.c_lflag &= ~LOBLK;
124 new_modes.c_oflag &= ~(OPOST | OLCUC | TABDLY);
125 if (mask == ALLOW_PARITY) {
126 new_modes.c_cflag &= ~(CSIZE | PARENB | HUPCL);
127 new_modes.c_cflag |= CS8;
130 ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL |
131 IUCLC | IXON | IXANY | IXOFF);
133 new_modes.sg_flags |= RAW;
137 PUT_TTY(fileno(stdin), &new_modes);
142 { /* set tty to special modes */
143 new_modes = old_modes;
145 new_modes.c_cc[VMIN] = 1;
146 new_modes.c_cc[VTIME] = 1;
147 new_modes.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
148 #if defined(ONLCR) && defined(OCRNL) && defined(ONLRET) && defined(OFILL)
149 new_modes.c_oflag &= ~(ONLCR | OCRNL | ONLRET | OFILL);
151 new_modes.c_oflag &= ~(OPOST);
153 if (char_mask == ALLOW_PARITY)
154 new_modes.c_iflag &= ~ISTRIP;
155 switch (select_xon_xoff) {
157 new_modes.c_iflag &= ~(IXON | IXOFF);
160 #if defined(sequent) && sequent
161 /* the sequent System V emulation is broken */
162 new_modes = old_modes;
163 new_modes.c_cc[VEOL] = 6; /* control F (ACK) */
165 new_modes.c_iflag |= IXON | IXOFF;
168 switch (select_delay_type) {
172 ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
178 ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
181 new_modes.c_oflag |= NL1 | CR2;
185 if (!(new_modes.c_oflag & (unsigned long) ~OPOST))
186 new_modes.c_oflag &= (unsigned long) ~OPOST;
188 new_modes.sg_flags |= RAW;
192 PUT_TTY(fileno(stdin), &new_modes);
198 { /* reset the tty to the original modes */
202 PUT_TTY(fileno(stdin), &old_modes);
208 { /* ATT terminal init */
209 #if defined(F_GETFL) && defined(O_NDELAY)
212 flags = fcntl(fileno(stdin), F_GETFL, 0);
213 nodelay_read = flags & O_NDELAY;
215 nodelay_read = FALSE;
218 if (GET_TTY(fileno(stdin), &old_modes) == -1) {
219 if (errno == ENOTTY) {
224 printf("tcgetattr error: %d\n", errno);
227 /* if TAB3 is set then setterm() wipes out tabs (ht) */
228 new_modes = old_modes;
231 new_modes.c_oflag &= ~TABDLY;
234 if (PUT_TTY(fileno(stdin), &new_modes) == -1) {
235 printf("tcsetattr error: %d\n", errno);
239 /* the sequent ATT emulation is broken soooo. */
240 old_modes.c_cflag &= ~(CSIZE | CSTOPB);
241 old_modes.c_cflag |= CS7 | PARENB;
245 switch (old_modes.c_cflag & CSIZE) {
246 #if defined(CS5) && (CS5 != 0)
251 #if defined(CS6) && (CS6 != 0)
256 #if defined(CS7) && (CS7 != 0)
261 #if defined(CS8) && (CS8 != 0)
267 tty_frame_size += 2 +
268 ((old_modes.c_cflag & PARENB) ? 2 : 0) +
269 ((old_modes.c_cflag & CSTOPB) ? 4 : 2);
272 (old_modes.sg_flags & PASS8) ? 16 : 14;
277 ** stty_query(question)
279 ** Does the current driver settings have this property?
286 return TTY_IS_NOECHO;
288 return TTY_IS_OUT_TRANS;
290 return TTY_IS_CHAR_MODE;
296 ** initial_stty_query(question)
298 ** Did the initial driver settings have this property?
301 initial_stty_query(int q)
307 return TTY_WAS_XON_XOFF;
312 #if HAVE_SELECT && defined(FD_ZERO)
321 FD_SET(fileno(stdin), &ifds);
324 n = select(fileno(stdin)+1, &ifds, NULL, NULL, &tv);
335 /* the following loop has to be tuned for each computer */
336 for (j = 0; j < 1000; j++) {
337 ioctl(fileno(stdin), FIONREAD, &i);
345 #if defined(__BEOS__)
350 int howmany = ioctl(0, 'ichr', &n);
351 return (howmany >= 0 && n > 0);
354 #define char_ready() 1
362 ** Wait for the input stream to stop.
363 ** Throw away all input characters.
368 unsigned char buf[64];
371 event_start(TIME_FLUSH); /* start the timer */
374 (void) read(fileno(stdin), &buf, sizeof(buf));
376 } while (event_time(TIME_FLUSH) < 400000);
380 ** read_key(input-buffer, length-of-buffer)
382 ** read one function key from the input stream.
383 ** A null character is converted to 0x80.
386 read_key(char *buf, int max)
394 /* ATT unix may return 0 or 1, Berkeley Unix should be 1 */
395 while (read(fileno(stdin), s, 1) == 0);
398 while (max > 0 && (ask = char_ready())) {
402 if ((got = read(fileno(stdin), s, (unsigned) ask))) {
411 for (s = buf, i = 0; i < l; i++) {
412 if ((*s & 0x7f) == 0) {
413 /* convert nulls to 0x80 */
414 *(unsigned char *)s = 128;
416 /* strip high order bits (if any) */
427 signal(SIGINT, SIG_IGN);
428 signal(SIGHUP, SIG_IGN);
429 signal(SIGQUIT, SIG_IGN);
430 signal(SIGTERM, SIG_IGN);
431 signal(SIGALRM, SIG_IGN);
437 is the interrupt handling routine onintr turns off interrupts while doing
440 onintr always exits fatally
445 onintr(int sig GCC_UNUSED)
456 set up to field interrupts (via function onintr( )) so that if interrupted
457 we can restore the correct terminal modes
459 catchsig simply returns
466 if ((signal(SIGINT, SIG_IGN)) == SIG_DFL)
467 signal(SIGINT, onintr);
469 if ((signal(SIGHUP, SIG_IGN)) == SIG_DFL)
470 signal(SIGHUP, onintr);
472 if ((signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
473 signal(SIGQUIT, onintr);
475 if ((signal(SIGTERM, SIG_IGN)) == SIG_DFL)
476 signal(SIGTERM, onintr);
483 ** Come here for an alarm event
493 ** set_alarm_clock(seconds)
495 ** Set the alarm clock to fire in <seconds>
501 signal(SIGALRM, alarm_event);
503 (void) alarm((unsigned) seconds);