Nuke INTR_NETSAFE
[dragonfly/netmp.git] / contrib / ncurses-5.4 / tack / sysdep.c
blobd8b4802377151c7b8d5441c37c777e2c539f9314
1 /*
2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
3 **
4 ** This file is part of TACK.
5 **
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)
9 ** any later version.
10 **
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.
15 **
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 */
29 #include <tack.h>
31 #include <term.h>
32 #include <errno.h>
34 #if defined(__BEOS__)
35 #undef false
36 #undef true
37 #include <OS.h>
38 #endif
40 #if HAVE_SELECT
41 #if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT
42 #include <sys/time.h>
43 #endif
44 #if HAVE_SYS_SELECT_H
45 #include <sys/select.h>
46 #endif
47 #endif
49 MODULE_ID("$Id: sysdep.c,v 1.11 2002/04/21 19:40:43 tom Exp $")
51 #if DECL_ERRNO
52 extern int errno;
53 #endif
55 #ifdef TERMIOS
56 #define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)
57 #else
58 #define PUT_TTY(fd, buf) stty(fd, buf)
59 #endif
61 /* globals */
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 */
67 #ifdef TERMIOS
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))
73 #else
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))
79 #endif
81 static TTY old_modes, new_modes;
83 void catchsig(void);
86 * These are a sneaky way of conditionalizing bit unsets so strict-POSIX
87 * systems won't see them.
89 #ifndef XCASE
90 #define XCASE 0
91 #endif
92 #ifndef OLCUC
93 #define OLCUC 0
94 #endif
95 #ifndef IUCLC
96 #define IUCLC 0
97 #endif
98 #ifndef TABDLY
99 #define TABDLY 0
100 #endif
101 #ifndef IXANY
102 #define IXANY 0
103 #endif
105 void
106 tty_raw(int minch GCC_UNUSED, int mask)
107 { /* set tty to raw noecho */
108 new_modes = old_modes;
109 #ifdef TERMIOS
110 #if HAVE_SELECT
111 new_modes.c_cc[VMIN] = 1;
112 #else
113 new_modes.c_cc[VMIN] = minch;
114 #endif
115 new_modes.c_cc[VTIME] = 2;
116 new_modes.c_lflag &=
117 ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL);
118 #ifdef LOBLK
119 new_modes.c_lflag &= ~LOBLK;
120 #endif
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;
126 new_modes.c_iflag &=
127 ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL |
128 IUCLC | IXON | IXANY | IXOFF);
129 #else
130 new_modes.sg_flags |= RAW;
131 #endif
132 if (not_a_tty)
133 return;
134 PUT_TTY(fileno(stdin), &new_modes);
137 void
138 tty_set(void)
139 { /* set tty to special modes */
140 new_modes = old_modes;
141 #ifdef TERMIOS
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);
147 #else
148 new_modes.c_oflag &= ~(OPOST);
149 #endif
150 if (char_mask == ALLOW_PARITY)
151 new_modes.c_iflag &= ~ISTRIP;
152 switch (select_xon_xoff) {
153 case 0:
154 new_modes.c_iflag &= ~(IXON | IXOFF);
155 break;
156 case 1:
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) */
161 #endif
162 new_modes.c_iflag |= IXON | IXOFF;
163 break;
165 switch (select_delay_type) {
166 case 0:
167 #ifdef NLDLY
168 new_modes.c_oflag &=
169 ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
170 #endif /* NLDLY */
171 break;
172 case 1:
173 #ifdef NLDLY
174 new_modes.c_oflag &=
175 ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
176 #endif /* NLDLY */
177 #ifdef NL1
178 new_modes.c_oflag |= NL1 | CR2;
179 #endif /* NL1 */
180 break;
182 if (!(new_modes.c_oflag & ~OPOST))
183 new_modes.c_oflag &= ~OPOST;
184 #else
185 new_modes.sg_flags |= RAW;
186 if (not_a_tty)
187 return;
188 #endif
189 PUT_TTY(fileno(stdin), &new_modes);
193 void
194 tty_reset(void)
195 { /* reset the tty to the original modes */
196 fflush(stdout);
197 if (not_a_tty)
198 return;
199 PUT_TTY(fileno(stdin), &old_modes);
203 void
204 tty_init(void)
205 { /* ATT terminal init */
206 #if defined(F_GETFL) && defined(O_NDELAY)
207 int flags;
209 flags = fcntl(fileno(stdin), F_GETFL, 0);
210 nodelay_read = flags & O_NDELAY;
211 #else
212 nodelay_read = FALSE;
213 #endif
214 not_a_tty = FALSE;
215 if (GET_TTY(fileno(stdin), &old_modes) == -1) {
216 if (errno == ENOTTY) {
217 tty_frame_size = 20;
218 not_a_tty = TRUE;
219 return;
221 printf("tcgetattr error: %d\n", errno);
222 exit(1);
224 /* if TAB3 is set then setterm() wipes out tabs (ht) */
225 new_modes = old_modes;
226 #ifdef TERMIOS
227 #ifdef TABDLY
228 new_modes.c_oflag &= ~TABDLY;
229 #endif /* TABDLY */
230 #endif
231 if (PUT_TTY(fileno(stdin), &new_modes) == -1) {
232 printf("tcsetattr error: %d\n", errno);
233 exit(1);
235 #ifdef sequent
236 /* the sequent ATT emulation is broken soooo. */
237 old_modes.c_cflag &= ~(CSIZE | CSTOPB);
238 old_modes.c_cflag |= CS7 | PARENB;
239 #endif
240 catchsig();
241 #ifdef TERMIOS
242 switch (old_modes.c_cflag & CSIZE) {
243 #if defined(CS5) && (CS5 != 0)
244 case CS5:
245 tty_frame_size = 10;
246 break;
247 #endif
248 #if defined(CS6) && (CS6 != 0)
249 case CS6:
250 tty_frame_size = 12;
251 break;
252 #endif
253 #if defined(CS7) && (CS7 != 0)
254 case CS7:
255 tty_frame_size = 14;
256 break;
257 #endif
258 #if defined(CS8) && (CS8 != 0)
259 case CS8:
260 tty_frame_size = 16;
261 break;
262 #endif
264 tty_frame_size += 2 +
265 ((old_modes.c_cflag & PARENB) ? 2 : 0) +
266 ((old_modes.c_cflag & CSTOPB) ? 4 : 2);
267 #else
268 tty_frame_size = 6 +
269 (old_modes.sg_flags & PASS8) ? 16 : 14;
270 #endif
274 ** stty_query(question)
276 ** Does the current driver settings have this property?
279 stty_query(int q)
281 switch (q) {
282 case TTY_NOECHO:
283 return TTY_IS_NOECHO;
284 case TTY_OUT_TRANS:
285 return TTY_IS_OUT_TRANS;
286 case TTY_CHAR_MODE:
287 return TTY_IS_CHAR_MODE;
289 return (-1);
293 ** initial_stty_query(question)
295 ** Did the initial driver settings have this property?
298 initial_stty_query(int q)
300 switch (q) {
301 case TTY_8_BIT:
302 return TTY_WAS_CS8;
303 case TTY_XON_XOFF:
304 return TTY_WAS_XON_XOFF;
306 return (-1);
309 #if HAVE_SELECT && defined(FD_ZERO)
310 static int
311 char_ready(void)
313 int n;
314 fd_set ifds;
315 struct timeval tv;
317 FD_ZERO(&ifds);
318 FD_SET(fileno(stdin), &ifds);
319 tv.tv_sec = 0;
320 tv.tv_usec = 200000;
321 n = select(fileno(stdin)+1, &ifds, NULL, NULL, &tv);
322 return (n != 0);
325 #else
326 #ifdef FIONREAD
328 char_ready(void)
330 int i, j;
332 /* the following loop has to be tuned for each computer */
333 for (j = 0; j < 1000; j++) {
334 ioctl(fileno(stdin), FIONREAD, &i);
335 if (i)
336 return i;
338 return i;
341 #else
342 #if defined(__BEOS__)
344 char_ready(void)
346 int n = 0;
347 int howmany = ioctl(0, 'ichr', &n);
348 return (howmany >= 0 && n > 0);
350 #else
351 #define char_ready() 1
352 #endif
353 #endif
354 #endif
357 ** spin_flush()
359 ** Wait for the input stream to stop.
360 ** Throw away all input characters.
362 void
363 spin_flush(void)
365 unsigned char buf[64];
367 fflush(stdout);
368 event_start(TIME_FLUSH); /* start the timer */
369 do {
370 if (char_ready()) {
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.
382 void
383 read_key(char *buf, int max)
385 int got, ask, i, l;
386 char *s;
388 *buf = '\0';
389 s = buf;
390 fflush(stdout);
391 /* ATT unix may return 0 or 1, Berkeley Unix should be 1 */
392 while (read(fileno(stdin), s, 1) == 0);
393 ++s;
394 --max;
395 while (max > 0 && (ask = char_ready())) {
396 if (ask > max) {
397 ask = max;
399 if ((got = read(fileno(stdin), s, ask))) {
400 s += got;
401 } else {
402 break;
404 max -= got;
406 *s = '\0';
407 l = s - buf;
408 for (s = buf, i = 0; i < l; i++) {
409 if ((*s & 0x7f) == 0) {
410 /* convert nulls to 0x80 */
411 *(unsigned char *)s = 128;
412 } else {
413 /* strip high order bits (if any) */
414 *s &= char_mask;
420 void
421 ignoresig(void)
423 /* ignore signals */
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);
432 onintr( )
434 is the interrupt handling routine onintr turns off interrupts while doing
435 clean-up
437 onintr always exits fatally
441 static RETSIGTYPE
442 onintr(int sig GCC_UNUSED)
444 ignoresig();
445 tty_reset();
446 exit(1);
451 catchsig( )
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
460 void
461 catchsig(void)
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);
478 ** alarm_event(sig)
480 ** Come here for an alarm event
482 static void
483 alarm_event(
484 int sig GCC_UNUSED)
486 no_alarm_event = 0;
490 ** set_alarm_clock(seconds)
492 ** Set the alarm clock to fire in <seconds>
494 void
495 set_alarm_clock(
496 int seconds)
498 signal(SIGALRM, alarm_event);
499 no_alarm_event = 1;
500 (void) alarm(seconds);