[gforth] / gforth / engine / io.c  

gforth: gforth/engine/io.c


1 : anton 1.10 /* direct key io driver
2 : anton 1.1
3 : anton 1.25 Copyright (C) 1995,1996,1997,1998,1999,2002,2003,2006 Free Software Foundation, Inc.
4 : anton 1.1
5 :     This file is part of Gforth.
6 :    
7 :     Gforth is free software; you can redistribute it and/or
8 :     modify it under the terms of the GNU General Public License
9 :     as published by the Free Software Foundation; either version 2
10 :     of the License, or (at your option) any later version.
11 :    
12 :     This program is distributed in the hope that it will be useful,
13 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
14 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 :     GNU General Public License for more details.
16 :    
17 :     You should have received a copy of the GNU General Public License
18 :     along with this program; if not, write to the Free Software
19 : anton 1.13 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20 : anton 1.1
21 :     The following is stolen from the readline library for bash
22 :     */
23 :    
24 :     /*
25 :     Use -D_POSIX_VERSION for POSIX systems.
26 :     */
27 :    
28 :     #include "config.h"
29 : anton 1.15 #include "forth.h"
30 : pazsan 1.7 #include <sys/time.h>
31 :     #include <sys/types.h>
32 : anton 1.1 #include <unistd.h>
33 :    
34 :     #if defined(apollo) || defined(_WIN32)
35 :     #define _POSIX_VERSION
36 :     #endif
37 :    
38 : pazsan 1.6 #if !defined(Solaris) && defined(sun) && defined(__svr4__)
39 :     #define Solaris
40 :     typedef unsigned int uint32_t;
41 :     #endif
42 :    
43 : anton 1.1 #include <stdio.h>
44 :     #include <signal.h>
45 :     #include <string.h>
46 :     #if !defined(apollo) && !defined(MSDOS)
47 :     #include <sys/ioctl.h>
48 :     #endif
49 :     #include <fcntl.h>
50 :     #include <sys/file.h>
51 :     #if defined(Solaris) && !defined(FIONREAD)
52 :     #include <sys/filio.h>
53 :     #endif
54 :     #include <setjmp.h>
55 :     #include "io.h"
56 :    
57 :     #ifndef MSDOS
58 :     #if defined (__GNUC__)
59 :     # define alloca __builtin_alloca
60 :     #else
61 :     # if defined (sparc) || defined (HAVE_ALLOCA_H)
62 :     # include <alloca.h>
63 :     # endif
64 :     #endif
65 :    
66 :     #define NEW_TTY_DRIVER
67 :     #define HAVE_BSD_SIGNALS
68 :     /*
69 :     #ifndef apollo
70 :     #define USE_XON_XOFF
71 :     #endif
72 :     */
73 :    
74 :     #define HANDLE_SIGNALS
75 :    
76 :     /* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
77 :     #if defined (USG) && !defined (hpux)
78 :     #undef HAVE_BSD_SIGNALS
79 :     #endif
80 :    
81 :     /* System V machines use termio. */
82 :     #if !defined (_POSIX_VERSION)
83 :     # if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) || defined (Solaris) || defined(_WIN32)
84 :     # undef NEW_TTY_DRIVER
85 :     # define TERMIO_TTY_DRIVER
86 :     # include <termio.h>
87 :     # if !defined (TCOON)
88 :     # define TCOON 1
89 :     # endif
90 :     # endif /* USG || hpux || Xenix || sgi || DUGX || ultrix*/
91 :     #endif /* !_POSIX_VERSION */
92 :    
93 :     /* Posix systems use termios and the Posix signal functions. */
94 : pazsan 1.5 #if defined (_POSIX_VERSION) || defined (NeXT)
95 : anton 1.1 # if !defined (TERMIOS_MISSING)
96 :     # undef NEW_TTY_DRIVER
97 :     # define TERMIOS_TTY_DRIVER
98 :     # include <termios.h>
99 :     # endif /* !TERMIOS_MISSING */
100 : pazsan 1.5 #endif /* _POSIX_VERSION || NeXT */
101 :    
102 :     #if defined (_POSIX_VERSION)
103 : anton 1.1 # define HAVE_POSIX_SIGNALS
104 :     # if !defined (O_NDELAY)
105 :     # define O_NDELAY O_NONBLOCK /* Posix-style non-blocking i/o */
106 :     # endif /* O_NDELAY */
107 :     #endif /* _POSIX_VERSION */
108 :    
109 :     /* Other (BSD) machines use sgtty. */
110 :     #if defined (NEW_TTY_DRIVER)
111 :     #include <sgtty.h>
112 :     #endif
113 :    
114 :     /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
115 :     it is not already defined. It is used both to determine if a
116 :     special character is disabled and to disable certain special
117 :     characters. Posix systems should set to 0, USG systems to -1. */
118 :     #if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
119 : pazsan 1.5 # if defined (_POSIX_VERSION) || defined (NeXT)
120 : anton 1.1 # define _POSIX_VDISABLE 0
121 :     # else /* !_POSIX_VERSION */
122 :     # define _POSIX_VDISABLE -1
123 :     # endif /* !_POSIX_VERSION */
124 :     #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
125 :    
126 :     #include <errno.h>
127 :     /* extern int errno; */
128 :    
129 :     #if defined (SHELL)
130 :     # include <posixstat.h>
131 :     #else
132 :     # include <sys/stat.h>
133 :     #endif /* !SHELL */
134 :     /* #define HACK_TERMCAP_MOTION */
135 :    
136 :     #if defined (USG) && defined (hpux)
137 :     # if !defined (USGr3)
138 :     # define USGr3
139 :     # endif /* USGr3 */
140 :     #endif /* USG && hpux */
141 :    
142 :     #if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(apollo)
143 :     # include <dirent.h>
144 :     # define direct dirent
145 :     # if defined (_POSIX_VERSION)
146 :     # define D_NAMLEN(d) (strlen ((d)->d_name))
147 :     # else /* !_POSIX_VERSION */
148 :     # define D_NAMLEN(d) ((d)->d_reclen)
149 :     # endif /* !_POSIX_VERSION */
150 :     #else /* !_POSIX_VERSION && !USGr3 */
151 :     # define D_NAMLEN(d) ((d)->d_namlen)
152 :     # if !defined (USG)
153 :     # include <sys/dir.h>
154 :     # else /* USG */
155 :     # if defined (Xenix)
156 :     # include <sys/ndir.h>
157 :     # else /* !Xenix */
158 :     # include <ndir.h>
159 :     # endif /* !Xenix */
160 :     # endif /* USG */
161 :     #endif /* !POSIX_VERSION && !USGr3 */
162 :    
163 :     #if defined (USG) && defined (TIOCGWINSZ)
164 :     # include <sys/stream.h>
165 :     # if defined (USGr4) || defined (USGr3)
166 :     # if defined (Symmetry) || defined (_SEQUENT_)
167 :     # include <sys/pte.h>
168 :     # else
169 :     # include <sys/ptem.h>
170 :     # endif /* !Symmetry || _SEQUENT_ */
171 :     # endif /* USGr4 */
172 :     #endif /* USG && TIOCGWINSZ */
173 :    
174 :     #if defined (TERMIOS_TTY_DRIVER)
175 :     static struct termios otio;
176 :     #else
177 :     static struct termio otio;
178 :     #endif /* !TERMIOS_TTY_DRIVER */
179 :    
180 :     /* Non-zero means echo characters as they are read. */
181 :     int readline_echoing_p = 1;
182 :    
183 :     /* The character that can generate an EOF. Really read from
184 :     the terminal driver... just defaulted here. */
185 :    
186 :     #ifndef CTRL
187 :     #define CTRL(key) ((key)-'@')
188 :     #endif
189 :    
190 :     static int eof_char = CTRL ('D');
191 :    
192 :     /* **************************************************************** */
193 :     /* */
194 :     /* Saving and Restoring the TTY */
195 :     /* */
196 :     /* **************************************************************** */
197 :    
198 :     /* Non-zero means that the terminal is in a prepped state. */
199 :     int terminal_prepped = 0;
200 :    
201 :     #if defined (NEW_TTY_DRIVER)
202 :    
203 :     /* Standard flags, including ECHO. */
204 :     static int original_tty_flags = 0;
205 :    
206 :     /* Local mode flags, like LPASS8. */
207 :     static int local_mode_flags = 0;
208 :    
209 :     /* Terminal characters. This has C-s and C-q in it. */
210 :     static struct tchars original_tchars;
211 :    
212 :     /* Local special characters. This has the interrupt characters in it. */
213 :     #if defined (TIOCGLTC)
214 :     static struct ltchars original_ltchars;
215 :     #endif
216 :    
217 :     /* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */
218 :    
219 :     #if defined (TIOCGETC)
220 :     #if defined (USE_XON_XOFF)
221 :    
222 :     int
223 :     bind_key (key, function)
224 :     int key;
225 :     Function *function;
226 :     {
227 :     if (key < 0)
228 :     return (key);
229 :    
230 :     if (key > 127 && key < 256)
231 :     {
232 :     if (keymap[ESC].type == ISKMAP)
233 :     {
234 :     Keymap escmap = (Keymap)keymap[ESC].function;
235 :    
236 :     key -= 128;
237 :     escmap[key].type = ISFUNC;
238 :     escmap[key].function = function;
239 :     return (0);
240 :     }
241 :     return (key);
242 :     }
243 :    
244 :     keymap[key].type = ISFUNC;
245 :     keymap[key].function = function;
246 :     return (0);
247 :     }
248 :     #endif
249 :     #endif
250 :    
251 :     /* We use this to get and set the tty_flags. */
252 :     static struct sgttyb the_ttybuff;
253 :    
254 :     #if defined (USE_XON_XOFF)
255 :     /* If the terminal was in xoff state when we got to it, then xon_char
256 :     contains the character that is supposed to start it again. */
257 :     static int xon_char, xoff_state;
258 :     #endif /* USE_XON_XOFF */
259 :    
260 :     /* **************************************************************** */
261 :     /* */
262 :     /* Bogus Flow Control */
263 :     /* */
264 :     /* **************************************************************** */
265 :    
266 :     restart_output (count, key)
267 :     int count, key;
268 :     {
269 :     int fildes = fileno (stdin);
270 :     #if defined (TIOCSTART)
271 :     #if defined (apollo)
272 :     ioctl (&fildes, TIOCSTART, 0);
273 :     #else
274 :     ioctl (fildes, TIOCSTART, 0);
275 :     #endif /* apollo */
276 :    
277 :     #else
278 :     # if defined (TERMIOS_TTY_DRIVER)
279 :     tcflow (fildes, TCOON);
280 :     # else
281 :     # if defined (TCXONC)
282 :     ioctl (fildes, TCXONC, TCOON);
283 :     # endif /* TCXONC */
284 :     # endif /* !TERMIOS_TTY_DRIVER */
285 :     #endif /* TIOCSTART */
286 :     }
287 :    
288 :     /* Put the terminal in CBREAK mode so that we can detect key presses. */
289 :     void prep_terminal ()
290 :     {
291 :     int tty = fileno (stdin);
292 :     #if defined (HAVE_BSD_SIGNALS)
293 :     int oldmask;
294 :     #endif /* HAVE_BSD_SIGNALS */
295 :    
296 :     if (terminal_prepped)
297 :     return;
298 :    
299 :     if (!isatty(tty)) { /* added by MdG */
300 :     terminal_prepped = 1; /* added by MdG */
301 :     return; /* added by MdG */
302 :     } /* added by MdG */
303 :    
304 :     oldmask = sigblock (sigmask (SIGINT));
305 :    
306 :     /* We always get the latest tty values. Maybe stty changed them. */
307 :     ioctl (tty, TIOCGETP, &the_ttybuff);
308 :     original_tty_flags = the_ttybuff.sg_flags;
309 :    
310 :     readline_echoing_p = (original_tty_flags & ECHO);
311 :    
312 :     #if defined (TIOCLGET)
313 :     ioctl (tty, TIOCLGET, &local_mode_flags);
314 :     #endif
315 :    
316 :     #if !defined (ANYP)
317 :     # define ANYP (EVENP | ODDP)
318 :     #endif
319 :    
320 :     /* If this terminal doesn't care how the 8th bit is used,
321 :     then we can use it for the meta-key. We check by seeing
322 :     if BOTH odd and even parity are allowed. */
323 :     if (the_ttybuff.sg_flags & ANYP)
324 :     {
325 :     #if defined (PASS8)
326 :     the_ttybuff.sg_flags |= PASS8;
327 :     #endif
328 :    
329 :     /* Hack on local mode flags if we can. */
330 :     #if defined (TIOCLGET) && defined (LPASS8)
331 :     {
332 :     int flags;
333 :     flags = local_mode_flags | LPASS8;
334 :     ioctl (tty, TIOCLSET, &flags);
335 :     }
336 :     #endif /* TIOCLGET && LPASS8 */
337 :     }
338 :    
339 :     #if defined (TIOCGETC)
340 :     {
341 :     struct tchars temp;
342 :    
343 :     ioctl (tty, TIOCGETC, &original_tchars);
344 :     temp = original_tchars;
345 :    
346 :     #if defined (USE_XON_XOFF)
347 :     /* Get rid of C-s and C-q.
348 :     We remember the value of startc (C-q) so that if the terminal is in
349 :     xoff state, the user can xon it by pressing that character. */
350 :     xon_char = temp.t_startc;
351 :     temp.t_stopc = -1;
352 :     temp.t_startc = -1;
353 :    
354 :     /* If there is an XON character, bind it to restart the output. */
355 :     if (xon_char != -1)
356 :     bind_key (xon_char, restart_output);
357 :     #endif /* USE_XON_XOFF */
358 :    
359 :     /* If there is an EOF char, bind eof_char to it. */
360 :     if (temp.t_eofc != -1)
361 :     eof_char = temp.t_eofc;
362 :    
363 :     #if defined (NO_KILL_INTR)
364 :     /* Get rid of C-\ and C-c. */
365 :     temp.t_intrc = temp.t_quitc = -1;
366 :     #endif /* NO_KILL_INTR */
367 :    
368 :     ioctl (tty, TIOCSETC, &temp);
369 :     }
370 :     #endif /* TIOCGETC */
371 :    
372 :     #if defined (TIOCGLTC)
373 :     {
374 :     struct ltchars temp;
375 :    
376 :     ioctl (tty, TIOCGLTC, &original_ltchars);
377 :     temp = original_ltchars;
378 :    
379 :     /* Make the interrupt keys go away. Just enough to make people
380 :     happy. */
381 :     temp.t_dsuspc = -1; /* C-y */
382 :     temp.t_lnextc = -1; /* C-v */
383 :    
384 :     ioctl (tty, TIOCSLTC, &temp);
385 :     }
386 :     #endif /* TIOCGLTC */
387 :    
388 :     the_ttybuff.sg_flags &= ~(ECHO | CRMOD);
389 :     the_ttybuff.sg_flags |= CBREAK;
390 :     ioctl (tty, TIOCSETN, &the_ttybuff);
391 :    
392 :     terminal_prepped = 1;
393 :    
394 :     #if defined (HAVE_BSD_SIGNALS)
395 :     sigsetmask (oldmask);
396 :     #endif
397 :     }
398 :    
399 :     /* Restore the terminal to its original state. */
400 :     void deprep_terminal ()
401 :     {
402 :     int tty = fileno (stdin);
403 :     #if defined (HAVE_BSD_SIGNALS)
404 :     int oldmask;
405 :     #endif
406 :    
407 :     if (!terminal_prepped)
408 :     return;
409 :    
410 :     /* Added by MdG */
411 :     if (!isatty(tty)) {
412 :     terminal_prepped = 0;
413 :     return;
414 :     }
415 :    
416 :     oldmask = sigblock (sigmask (SIGINT));
417 :    
418 :     the_ttybuff.sg_flags = original_tty_flags;
419 :     ioctl (tty, TIOCSETN, &the_ttybuff);
420 :     readline_echoing_p = 1;
421 :    
422 :     #if defined (TIOCLGET)
423 :     ioctl (tty, TIOCLSET, &local_mode_flags);
424 :     #endif
425 :    
426 :     #if defined (TIOCSLTC)
427 :     ioctl (tty, TIOCSLTC, &original_ltchars);
428 :     #endif
429 :    
430 :     #if defined (TIOCSETC)
431 :     ioctl (tty, TIOCSETC, &original_tchars);
432 :     #endif
433 :     terminal_prepped = 0;
434 :    
435 :     #if defined (HAVE_BSD_SIGNALS)
436 :     sigsetmask (oldmask);
437 :     #endif
438 :     }
439 :    
440 :     #else /* !defined (NEW_TTY_DRIVER) */
441 :    
442 :     #if !defined (VMIN)
443 :     #define VMIN VEOF
444 :     #endif
445 :    
446 :     #if !defined (VTIME)
447 :     #define VTIME VEOL
448 :     #endif
449 :    
450 : pazsan 1.18 #include <locale.h>
451 :    
452 : anton 1.1 void prep_terminal ()
453 :     {
454 :     int tty = fileno (stdin);
455 :     #if defined (TERMIOS_TTY_DRIVER)
456 :     struct termios tio;
457 :     #else
458 :     struct termio tio;
459 :     #endif /* !TERMIOS_TTY_DRIVER */
460 :    
461 :     #if defined (HAVE_POSIX_SIGNALS)
462 :     sigset_t set, oset;
463 :     #else
464 :     # if defined (HAVE_BSD_SIGNALS)
465 :     int oldmask;
466 :     # endif /* HAVE_BSD_SIGNALS */
467 :     #endif /* !HAVE_POSIX_SIGNALS */
468 :    
469 :     if (terminal_prepped)
470 :     return;
471 :    
472 :     if (!isatty(tty)) { /* added by MdG */
473 :     terminal_prepped = 1; /* added by MdG */
474 :     return; /* added by MdG */
475 :     } /* added by MdG */
476 :    
477 : pazsan 1.18 setlocale(LC_ALL, "");
478 : pazsan 1.24 setlocale(LC_NUMERIC, "C");
479 : pazsan 1.18
480 : anton 1.1 /* Try to keep this function from being INTerrupted. We can do it
481 :     on POSIX and systems with BSD-like signal handling. */
482 :     #if defined (HAVE_POSIX_SIGNALS)
483 :     sigemptyset (&set);
484 :     sigemptyset (&oset);
485 :     sigaddset (&set, SIGINT);
486 :     sigprocmask (SIG_BLOCK, &set, &oset);
487 :     #else /* !HAVE_POSIX_SIGNALS */
488 :     # if defined (HAVE_BSD_SIGNALS)
489 :     oldmask = sigblock (sigmask (SIGINT));
490 :     # endif /* HAVE_BSD_SIGNALS */
491 :     #endif /* !HAVE_POSIX_SIGNALS */
492 :    
493 :     #if defined (TERMIOS_TTY_DRIVER)
494 :     tcgetattr (tty, &tio);
495 :     #else
496 :     ioctl (tty, TCGETA, &tio);
497 :     #endif /* !TERMIOS_TTY_DRIVER */
498 :    
499 :     otio = tio;
500 :    
501 :     readline_echoing_p = (tio.c_lflag & ECHO);
502 :    
503 :     tio.c_lflag &= ~(ICANON | ECHO);
504 :    
505 :     if (otio.c_cc[VEOF] != _POSIX_VDISABLE)
506 :     eof_char = otio.c_cc[VEOF];
507 :    
508 :     #if defined (USE_XON_XOFF)
509 :     #if defined (IXANY)
510 :     tio.c_iflag &= ~(IXON | IXOFF | IXANY);
511 :     #else
512 :     /* `strict' Posix systems do not define IXANY. */
513 :     tio.c_iflag &= ~(IXON | IXOFF);
514 :     #endif /* IXANY */
515 :     #endif /* USE_XON_XOFF */
516 :    
517 :     /* Only turn this off if we are using all 8 bits. */
518 :     if ((tio.c_cflag & CSIZE) == CS8)
519 :     tio.c_iflag &= ~(ISTRIP | INPCK);
520 :    
521 :     /* Make sure we differentiate between CR and NL on input. */
522 :     tio.c_iflag &= ~(ICRNL | INLCR);
523 :    
524 :     #if !defined (HANDLE_SIGNALS)
525 :     tio.c_lflag &= ~ISIG;
526 :     #else
527 :     tio.c_lflag |= ISIG;
528 :     #endif
529 :    
530 :     tio.c_cc[VMIN] = 1;
531 :     tio.c_cc[VTIME] = 0;
532 :    
533 :     /* Turn off characters that we need on Posix systems with job control,
534 :     just to be sure. This includes ^Y and ^V. This should not really
535 :     be necessary. */
536 :     #if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_JOB_CONTROL)
537 :    
538 :     #if defined (VLNEXT)
539 :     tio.c_cc[VLNEXT] = _POSIX_VDISABLE;
540 :     #endif
541 :    
542 :     #if defined (VDSUSP)
543 :     tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
544 :     #endif
545 :    
546 :     #endif /* POSIX && JOB_CONTROL */
547 :    
548 :     #if defined (TERMIOS_TTY_DRIVER)
549 :     tcsetattr (tty, TCSADRAIN, &tio);
550 :     tcflow (tty, TCOON); /* Simulate a ^Q. */
551 :     #else
552 :     ioctl (tty, TCSETAW, &tio);
553 :     ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
554 :     #endif /* !TERMIOS_TTY_DRIVER */
555 :    
556 :     terminal_prepped = 1;
557 :    
558 :     #if defined (HAVE_POSIX_SIGNALS)
559 :     sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
560 :     #else
561 :     # if defined (HAVE_BSD_SIGNALS)
562 :     sigsetmask (oldmask);
563 :     # endif /* HAVE_BSD_SIGNALS */
564 :     #endif /* !HAVE_POSIX_SIGNALS */
565 :     }
566 :    
567 :     void deprep_terminal ()
568 :     {
569 :     int tty = fileno (stdin);
570 :    
571 :     /* Try to keep this function from being INTerrupted. We can do it
572 :     on POSIX and systems with BSD-like signal handling. */
573 :     #if defined (HAVE_POSIX_SIGNALS)
574 :     sigset_t set, oset;
575 :     #else /* !HAVE_POSIX_SIGNALS */
576 :     # if defined (HAVE_BSD_SIGNALS)
577 :     int oldmask;
578 :     # endif /* HAVE_BSD_SIGNALS */
579 :     #endif /* !HAVE_POSIX_SIGNALS */
580 :    
581 :     if (!terminal_prepped)
582 :     return;
583 :    
584 :     /* Added by MdG */
585 :     if (!isatty(tty)) {
586 :     terminal_prepped = 0;
587 :     return;
588 :     }
589 :    
590 :     #if defined (HAVE_POSIX_SIGNALS)
591 :     sigemptyset (&set);
592 :     sigemptyset (&oset);
593 :     sigaddset (&set, SIGINT);
594 :     sigprocmask (SIG_BLOCK, &set, &oset);
595 :     #else /* !HAVE_POSIX_SIGNALS */
596 :     # if defined (HAVE_BSD_SIGNALS)
597 :     oldmask = sigblock (sigmask (SIGINT));
598 :     # endif /* HAVE_BSD_SIGNALS */
599 :     #endif /* !HAVE_POSIX_SIGNALS */
600 :    
601 :     #if defined (TERMIOS_TTY_DRIVER)
602 :     tcsetattr (tty, TCSADRAIN, &otio);
603 :     tcflow (tty, TCOON); /* Simulate a ^Q. */
604 :     #else /* TERMIOS_TTY_DRIVER */
605 :     ioctl (tty, TCSETAW, &otio);
606 :     ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
607 :     #endif /* !TERMIOS_TTY_DRIVER */
608 :    
609 :     terminal_prepped = 0;
610 :    
611 :     #if defined (HAVE_POSIX_SIGNALS)
612 :     sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
613 :     #else /* !HAVE_POSIX_SIGNALS */
614 :     # if defined (HAVE_BSD_SIGNALS)
615 :     sigsetmask (oldmask);
616 :     # endif /* HAVE_BSD_SIGNALS */
617 :     #endif /* !HAVE_POSIX_SIGNALS */
618 :     }
619 :     #endif /* NEW_TTY_DRIVER */
620 :    
621 : pazsan 1.7 long key_avail (FILE * stream)
622 : anton 1.1 {
623 :     int tty = fileno (stream);
624 : anton 1.21 fd_set selin;
625 : pazsan 1.28 static struct timespec now = { 0 , 0 };
626 : anton 1.21 int res;
627 : anton 1.1
628 : anton 1.22 setvbuf(stream, NULL, _IONBF, 0);
629 : anton 1.20 if(!terminal_prepped && stream == stdin)
630 :     prep_terminal();
631 : anton 1.1
632 : anton 1.21 FD_ZERO(&selin);
633 :     FD_SET(tty, &selin);
634 : pazsan 1.28 return select(1, &selin, NULL, NULL, &now);
635 : anton 1.1 }
636 :    
637 :     /* Get a key from the buffer of characters to be read.
638 :     Return the key in KEY.
639 :     Result is KEY if there was a key, or 0 if there wasn't. */
640 :    
641 :     /* When compiling and running in the `Posix' environment, Ultrix does
642 :     not restart system calls, so this needs to do it. */
643 :    
644 : anton 1.11 Cell getkey(FILE * stream)
645 : anton 1.1 {
646 : anton 1.11 Cell result;
647 : anton 1.1 unsigned char c;
648 :    
649 : anton 1.23 setvbuf(stream, NULL, _IONBF, 0);
650 : anton 1.22 if(!terminal_prepped && stream == stdin)
651 : anton 1.11 prep_terminal();
652 : anton 1.1
653 : anton 1.22 result = fread(&c, sizeof(c), 1, stream);
654 : pazsan 1.30 return result==0 ? (errno == EINTR ? 12 : 4) : c;
655 : anton 1.1 }
656 :    
657 : pazsan 1.26 #ifdef STANDALONE
658 :     void emit_char(char x)
659 :     {
660 :     putc(x, stdout);
661 :     }
662 :    
663 :     void type_chars(char *addr, unsigned int l)
664 :     {
665 :     fwrite(addr, l, 1, stdout);
666 :     }
667 :     #endif
668 :    
669 : anton 1.1 #ifdef TEST
670 :    
671 :     #include <time.h>
672 :    
673 :     int timewait=100000;
674 :    
675 :     int main()
676 :     {
677 :     unsigned char c;
678 :    
679 :     prep_terminal();
680 :    
681 :     do
682 :     {
683 :     int i=0;
684 :    
685 :     while(!key_avail(stdin))
686 :     {
687 :     printf("%04d",i);
688 :     fflush(stdout);
689 :     {
690 :     struct timeval timeout;
691 :     timeout.tv_sec=timewait/1000000;
692 :     timeout.tv_usec=timewait%1000000;
693 :     (void)select(0,0,0,0,&timeout);
694 :     }
695 :     i++;
696 :     printf("\b\b\b\b");
697 :     fflush(stdout);
698 :     }
699 :     c = getkey(stdin);
700 :     printf("%02x,",(int)c);
701 :     fflush(stdout);
702 :     } while(c != 0x1B);
703 :    
704 :     deprep_terminal();
705 :     puts("");
706 :     }
707 :     #endif
708 :     #endif /* MSDOS */
709 :    

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help