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., 59 Temple Place - Suite 330,
19 ** Boston, MA 02111-1307, 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.
27 #include <signal.h> /* include before curses.h to work around glibc bug */
41 #if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT
45 #include <sys/select.h>
49 MODULE_ID("$Id: sysdep.c,v 1.11 2002/04/21 19:40:43 tom Exp $")
56 #define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)
58 #define PUT_TTY(fd, buf) stty(fd, buf)
62 int tty_frame_size
; /* asynch frame size times 2 */
63 unsigned long tty_baud_rate
; /* baud rate - bits per second */
64 int not_a_tty
; /* TRUE if output is not a tty (i.e. pipe) */
65 int nodelay_read
; /* TRUE if NDELAY is set */
68 #define TTY_IS_NOECHO !(new_modes.c_lflag & ECHO)
69 #define TTY_IS_OUT_TRANS (new_modes.c_oflag & OPOST)
70 #define TTY_IS_CHAR_MODE !(new_modes.c_lflag & ICANON)
71 #define TTY_WAS_CS8 ((old_modes.c_cflag & CSIZE) == CS8)
72 #define TTY_WAS_XON_XOFF (old_modes.c_iflag & (IXON|IXOFF))
74 #define TTY_IS_NOECHO !(new_modes.sg_flags & (ECHO))
75 #define TTY_IS_OUT_TRANS (new_modes.sg_flags & (CRMOD))
76 #define TTY_IS_CHAR_MODE (new_modes.sg_flags & (RAW|CBREAK))
77 #define TTY_WAS_CS8 (old_modes.sg_flags & (PASS8))
78 #define TTY_WAS_XON_XOFF (old_modes.sg_flags & (TANDEM|MDMBUF|DECCTQ))
81 static TTY old_modes
, new_modes
;
86 * These are a sneaky way of conditionalizing bit unsets so strict-POSIX
87 * systems won't see them.
106 tty_raw(int minch GCC_UNUSED
, int mask
)
107 { /* set tty to raw noecho */
108 new_modes
= old_modes
;
111 new_modes
.c_cc
[VMIN
] = 1;
113 new_modes
.c_cc
[VMIN
] = minch
;
115 new_modes
.c_cc
[VTIME
] = 2;
117 ~(ISIG
| ICANON
| XCASE
| ECHO
| ECHOE
| ECHOK
| ECHONL
);
119 new_modes
.c_lflag
&= ~LOBLK
;
121 new_modes
.c_oflag
&= ~(OPOST
| OLCUC
| TABDLY
);
122 if (mask
== ALLOW_PARITY
) {
123 new_modes
.c_cflag
&= ~(CSIZE
| PARENB
| HUPCL
);
124 new_modes
.c_cflag
|= CS8
;
127 ~(IGNBRK
| BRKINT
| IGNPAR
| PARMRK
| INPCK
| ISTRIP
| INLCR
| IGNCR
| ICRNL
|
128 IUCLC
| IXON
| IXANY
| IXOFF
);
130 new_modes
.sg_flags
|= RAW
;
134 PUT_TTY(fileno(stdin
), &new_modes
);
139 { /* set tty to special modes */
140 new_modes
= old_modes
;
142 new_modes
.c_cc
[VMIN
] = 1;
143 new_modes
.c_cc
[VTIME
] = 1;
144 new_modes
.c_lflag
&= ~(ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
| ECHONL
);
145 #if defined(ONLCR) && defined(OCRNL) && defined(ONLRET) && defined(OFILL)
146 new_modes
.c_oflag
&= ~(ONLCR
| OCRNL
| ONLRET
| OFILL
);
148 new_modes
.c_oflag
&= ~(OPOST
);
150 if (char_mask
== ALLOW_PARITY
)
151 new_modes
.c_iflag
&= ~ISTRIP
;
152 switch (select_xon_xoff
) {
154 new_modes
.c_iflag
&= ~(IXON
| IXOFF
);
157 #if defined(sequent) && sequent
158 /* the sequent System V emulation is broken */
159 new_modes
= old_modes
;
160 new_modes
.c_cc
[VEOL
] = 6; /* control F (ACK) */
162 new_modes
.c_iflag
|= IXON
| IXOFF
;
165 switch (select_delay_type
) {
169 ~(NLDLY
| CRDLY
| TABDLY
| BSDLY
| VTDLY
| FFDLY
);
175 ~(NLDLY
| CRDLY
| TABDLY
| BSDLY
| VTDLY
| FFDLY
);
178 new_modes
.c_oflag
|= NL1
| CR2
;
182 if (!(new_modes
.c_oflag
& ~OPOST
))
183 new_modes
.c_oflag
&= ~OPOST
;
185 new_modes
.sg_flags
|= RAW
;
189 PUT_TTY(fileno(stdin
), &new_modes
);
195 { /* reset the tty to the original modes */
199 PUT_TTY(fileno(stdin
), &old_modes
);
205 { /* ATT terminal init */
206 #if defined(F_GETFL) && defined(O_NDELAY)
209 flags
= fcntl(fileno(stdin
), F_GETFL
, 0);
210 nodelay_read
= flags
& O_NDELAY
;
212 nodelay_read
= FALSE
;
215 if (GET_TTY(fileno(stdin
), &old_modes
) == -1) {
216 if (errno
== ENOTTY
) {
221 printf("tcgetattr error: %d\n", errno
);
224 /* if TAB3 is set then setterm() wipes out tabs (ht) */
225 new_modes
= old_modes
;
228 new_modes
.c_oflag
&= ~TABDLY
;
231 if (PUT_TTY(fileno(stdin
), &new_modes
) == -1) {
232 printf("tcsetattr error: %d\n", errno
);
236 /* the sequent ATT emulation is broken soooo. */
237 old_modes
.c_cflag
&= ~(CSIZE
| CSTOPB
);
238 old_modes
.c_cflag
|= CS7
| PARENB
;
242 switch (old_modes
.c_cflag
& CSIZE
) {
243 #if defined(CS5) && (CS5 != 0)
248 #if defined(CS6) && (CS6 != 0)
253 #if defined(CS7) && (CS7 != 0)
258 #if defined(CS8) && (CS8 != 0)
264 tty_frame_size
+= 2 +
265 ((old_modes
.c_cflag
& PARENB
) ? 2 : 0) +
266 ((old_modes
.c_cflag
& CSTOPB
) ? 4 : 2);
269 (old_modes
.sg_flags
& PASS8
) ? 16 : 14;
274 ** stty_query(question)
276 ** Does the current driver settings have this property?
283 return TTY_IS_NOECHO
;
285 return TTY_IS_OUT_TRANS
;
287 return TTY_IS_CHAR_MODE
;
293 ** initial_stty_query(question)
295 ** Did the initial driver settings have this property?
298 initial_stty_query(int q
)
304 return TTY_WAS_XON_XOFF
;
309 #if HAVE_SELECT && defined(FD_ZERO)
318 FD_SET(fileno(stdin
), &ifds
);
321 n
= select(fileno(stdin
)+1, &ifds
, NULL
, NULL
, &tv
);
332 /* the following loop has to be tuned for each computer */
333 for (j
= 0; j
< 1000; j
++) {
334 ioctl(fileno(stdin
), FIONREAD
, &i
);
342 #if defined(__BEOS__)
347 int howmany
= ioctl(0, 'ichr', &n
);
348 return (howmany
>= 0 && n
> 0);
351 #define char_ready() 1
359 ** Wait for the input stream to stop.
360 ** Throw away all input characters.
365 unsigned char buf
[64];
368 event_start(TIME_FLUSH
); /* start the timer */
371 (void) read(fileno(stdin
), &buf
, sizeof(buf
));
373 } while (event_time(TIME_FLUSH
) < 400000);
377 ** read_key(input-buffer, length-of-buffer)
379 ** read one function key from the input stream.
380 ** A null character is converted to 0x80.
383 read_key(char *buf
, int max
)
391 /* ATT unix may return 0 or 1, Berkeley Unix should be 1 */
392 while (read(fileno(stdin
), s
, 1) == 0);
395 while (max
> 0 && (ask
= char_ready())) {
399 if ((got
= read(fileno(stdin
), s
, ask
))) {
408 for (s
= buf
, i
= 0; i
< l
; i
++) {
409 if ((*s
& 0x7f) == 0) {
410 /* convert nulls to 0x80 */
411 *(unsigned char *)s
= 128;
413 /* strip high order bits (if any) */
424 signal(SIGINT
, SIG_IGN
);
425 signal(SIGHUP
, SIG_IGN
);
426 signal(SIGQUIT
, SIG_IGN
);
427 signal(SIGTERM
, SIG_IGN
);
428 signal(SIGALRM
, SIG_IGN
);
434 is the interrupt handling routine onintr turns off interrupts while doing
437 onintr always exits fatally
442 onintr(int sig GCC_UNUSED
)
453 set up to field interrupts (via function onintr( )) so that if interrupted
454 we can restore the correct terminal modes
456 catchsig simply returns
463 if ((signal(SIGINT
, SIG_IGN
)) == SIG_DFL
)
464 signal(SIGINT
, onintr
);
466 if ((signal(SIGHUP
, SIG_IGN
)) == SIG_DFL
)
467 signal(SIGHUP
, onintr
);
469 if ((signal(SIGQUIT
, SIG_IGN
)) == SIG_DFL
)
470 signal(SIGQUIT
, onintr
);
472 if ((signal(SIGTERM
, SIG_IGN
)) == SIG_DFL
)
473 signal(SIGTERM
, onintr
);
480 ** Come here for an alarm event
490 ** set_alarm_clock(seconds)
492 ** Set the alarm clock to fire in <seconds>
498 signal(SIGALRM
, alarm_event
);
500 (void) alarm(seconds
);