Annotation of gforth/engine/io.c, revision 1.1

1.1     ! anton       1: /* direct key io driver; signal handler
        !             2: 
        !             3:   Copyright (C) 1995 Free Software Foundation, Inc.
        !             4: 
        !             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:   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            20: 
        !            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: #include <unistd.h>
        !            30: 
        !            31: #if defined(apollo) || defined(_WIN32)
        !            32: #define _POSIX_VERSION
        !            33: #endif
        !            34: 
        !            35: #include <stdio.h>
        !            36: #include <signal.h>
        !            37: #include <string.h>
        !            38: #include <sys/types.h>
        !            39: #if !defined(apollo) && !defined(MSDOS)
        !            40: #include <sys/ioctl.h>
        !            41: #endif
        !            42: #include <fcntl.h>
        !            43: #include <sys/file.h>
        !            44: #if defined(Solaris) && !defined(FIONREAD)
        !            45: #include <sys/filio.h>
        !            46: #endif
        !            47: #include <setjmp.h>
        !            48: #include "forth.h"
        !            49: #include "io.h"
        !            50: 
        !            51: #ifndef MSDOS
        !            52: #if defined (__GNUC__)
        !            53: #  define alloca __builtin_alloca
        !            54: #else
        !            55: #  if defined (sparc) || defined (HAVE_ALLOCA_H)
        !            56: #    include <alloca.h>
        !            57: #  endif
        !            58: #endif
        !            59: 
        !            60: #define NEW_TTY_DRIVER
        !            61: #define HAVE_BSD_SIGNALS
        !            62: /*
        !            63: #ifndef apollo
        !            64: #define USE_XON_XOFF
        !            65: #endif
        !            66: */
        !            67: 
        !            68: #define HANDLE_SIGNALS
        !            69: 
        !            70: /* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
        !            71: #if defined (USG) && !defined (hpux)
        !            72: #undef HAVE_BSD_SIGNALS
        !            73: #endif
        !            74: 
        !            75: /* System V machines use termio. */
        !            76: #if !defined (_POSIX_VERSION)
        !            77: #  if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) || defined (Solaris) || defined(_WIN32)
        !            78: #    undef NEW_TTY_DRIVER
        !            79: #    define TERMIO_TTY_DRIVER
        !            80: #    include <termio.h>
        !            81: #    if !defined (TCOON)
        !            82: #      define TCOON 1
        !            83: #    endif
        !            84: #  endif /* USG || hpux || Xenix || sgi || DUGX || ultrix*/
        !            85: #endif /* !_POSIX_VERSION */
        !            86: 
        !            87: /* Posix systems use termios and the Posix signal functions. */
        !            88: #if defined (_POSIX_VERSION)
        !            89: #  if !defined (TERMIOS_MISSING)
        !            90: #    undef NEW_TTY_DRIVER
        !            91: #    define TERMIOS_TTY_DRIVER
        !            92: #    include <termios.h>
        !            93: #  endif /* !TERMIOS_MISSING */
        !            94: #  define HAVE_POSIX_SIGNALS
        !            95: #  if !defined (O_NDELAY)
        !            96: #    define O_NDELAY O_NONBLOCK        /* Posix-style non-blocking i/o */
        !            97: #  endif /* O_NDELAY */
        !            98: #endif /* _POSIX_VERSION */
        !            99: 
        !           100: /* Other (BSD) machines use sgtty. */
        !           101: #if defined (NEW_TTY_DRIVER)
        !           102: #include <sgtty.h>
        !           103: #endif
        !           104: 
        !           105: /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
        !           106:    it is not already defined.  It is used both to determine if a
        !           107:    special character is disabled and to disable certain special
        !           108:    characters.  Posix systems should set to 0, USG systems to -1. */
        !           109: #if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
        !           110: #  if defined (_POSIX_VERSION)
        !           111: #    define _POSIX_VDISABLE 0
        !           112: #  else /* !_POSIX_VERSION */
        !           113: #    define _POSIX_VDISABLE -1
        !           114: #  endif /* !_POSIX_VERSION */
        !           115: #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
        !           116: 
        !           117: #include <errno.h>
        !           118: /* extern int errno; */
        !           119: 
        !           120: #if defined (SHELL)
        !           121: #  include <posixstat.h>
        !           122: #else
        !           123: #  include <sys/stat.h>
        !           124: #endif /* !SHELL */
        !           125: /* #define HACK_TERMCAP_MOTION */
        !           126: 
        !           127: #if defined (USG) && defined (hpux)
        !           128: #  if !defined (USGr3)
        !           129: #    define USGr3
        !           130: #  endif /* USGr3 */
        !           131: #endif /* USG && hpux */
        !           132: 
        !           133: #if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(apollo)
        !           134: #  include <dirent.h>
        !           135: #  define direct dirent
        !           136: #  if defined (_POSIX_VERSION)
        !           137: #    define D_NAMLEN(d) (strlen ((d)->d_name))
        !           138: #  else /* !_POSIX_VERSION */
        !           139: #    define D_NAMLEN(d) ((d)->d_reclen)
        !           140: #  endif /* !_POSIX_VERSION */
        !           141: #else /* !_POSIX_VERSION && !USGr3 */
        !           142: #  define D_NAMLEN(d) ((d)->d_namlen)
        !           143: #  if !defined (USG)
        !           144: #    include <sys/dir.h>
        !           145: #  else /* USG */
        !           146: #    if defined (Xenix)
        !           147: #      include <sys/ndir.h>
        !           148: #    else /* !Xenix */
        !           149: #      include <ndir.h>
        !           150: #    endif /* !Xenix */
        !           151: #  endif /* USG */
        !           152: #endif /* !POSIX_VERSION && !USGr3 */
        !           153: 
        !           154: #if defined (USG) && defined (TIOCGWINSZ)
        !           155: #  include <sys/stream.h>
        !           156: #  if defined (USGr4) || defined (USGr3)
        !           157: #    if defined (Symmetry) || defined (_SEQUENT_)
        !           158: #      include <sys/pte.h>
        !           159: #    else
        !           160: #      include <sys/ptem.h>
        !           161: #    endif /* !Symmetry || _SEQUENT_ */
        !           162: #  endif /* USGr4 */
        !           163: #endif /* USG && TIOCGWINSZ */
        !           164: 
        !           165: #if defined (TERMIOS_TTY_DRIVER)
        !           166: static struct termios otio;
        !           167: #else
        !           168: static struct termio otio;
        !           169: #endif /* !TERMIOS_TTY_DRIVER */
        !           170: 
        !           171: /* Non-zero means echo characters as they are read. */
        !           172: int readline_echoing_p = 1;
        !           173: 
        !           174: /* The character that can generate an EOF.  Really read from
        !           175:    the terminal driver... just defaulted here. */
        !           176: 
        !           177: #ifndef CTRL
        !           178: #define CTRL(key)      ((key)-'@')
        !           179: #endif
        !           180: 
        !           181: static int eof_char = CTRL ('D');
        !           182: 
        !           183: /* **************************************************************** */
        !           184: /*                                                                 */
        !           185: /*                   Saving and Restoring the TTY                  */
        !           186: /*                                                                 */
        !           187: /* **************************************************************** */
        !           188: 
        !           189: /* Non-zero means that the terminal is in a prepped state. */
        !           190: int terminal_prepped = 0;
        !           191: 
        !           192: #if defined (NEW_TTY_DRIVER)
        !           193: 
        !           194: /* Standard flags, including ECHO. */
        !           195: static int original_tty_flags = 0;
        !           196: 
        !           197: /* Local mode flags, like LPASS8. */
        !           198: static int local_mode_flags = 0;
        !           199: 
        !           200: /* Terminal characters.  This has C-s and C-q in it. */
        !           201: static struct tchars original_tchars;
        !           202: 
        !           203: /* Local special characters.  This has the interrupt characters in it. */
        !           204: #if defined (TIOCGLTC)
        !           205: static struct ltchars original_ltchars;
        !           206: #endif
        !           207: 
        !           208: /* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
        !           209: 
        !           210: #if defined (TIOCGETC)
        !           211: #if defined (USE_XON_XOFF)
        !           212: 
        !           213: int
        !           214: bind_key (key, function)
        !           215:      int key;
        !           216:      Function *function;
        !           217: {
        !           218:   if (key < 0)
        !           219:     return (key);
        !           220: 
        !           221:   if (key > 127 && key < 256)
        !           222:     {
        !           223:       if (keymap[ESC].type == ISKMAP)
        !           224:        {
        !           225:          Keymap escmap = (Keymap)keymap[ESC].function;
        !           226: 
        !           227:          key -= 128;
        !           228:          escmap[key].type = ISFUNC;
        !           229:          escmap[key].function = function;
        !           230:          return (0);
        !           231:        }
        !           232:       return (key);
        !           233:     }
        !           234: 
        !           235:   keymap[key].type = ISFUNC;
        !           236:   keymap[key].function = function;
        !           237:  return (0);
        !           238: }
        !           239: #endif
        !           240: #endif
        !           241: 
        !           242: /* We use this to get and set the tty_flags. */
        !           243: static struct sgttyb the_ttybuff;
        !           244: 
        !           245: #if defined (USE_XON_XOFF)
        !           246: /* If the terminal was in xoff state when we got to it, then xon_char
        !           247:    contains the character that is supposed to start it again. */
        !           248: static int xon_char, xoff_state;
        !           249: #endif /* USE_XON_XOFF */
        !           250: 
        !           251: /* **************************************************************** */
        !           252: /*                                                                 */
        !           253: /*                     Bogus Flow Control                          */
        !           254: /*                                                                 */
        !           255: /* **************************************************************** */
        !           256: 
        !           257: restart_output (count, key)
        !           258:      int count, key;
        !           259: {
        !           260:   int fildes = fileno (stdin);
        !           261: #if defined (TIOCSTART)
        !           262: #if defined (apollo)
        !           263:   ioctl (&fildes, TIOCSTART, 0);
        !           264: #else
        !           265:   ioctl (fildes, TIOCSTART, 0);
        !           266: #endif /* apollo */
        !           267: 
        !           268: #else
        !           269: #  if defined (TERMIOS_TTY_DRIVER)
        !           270:         tcflow (fildes, TCOON);
        !           271: #  else
        !           272: #    if defined (TCXONC)
        !           273:         ioctl (fildes, TCXONC, TCOON);
        !           274: #    endif /* TCXONC */
        !           275: #  endif /* !TERMIOS_TTY_DRIVER */
        !           276: #endif /* TIOCSTART */
        !           277: }
        !           278: 
        !           279: /* Put the terminal in CBREAK mode so that we can detect key presses. */
        !           280: void prep_terminal ()
        !           281: {
        !           282:   int tty = fileno (stdin);
        !           283: #if defined (HAVE_BSD_SIGNALS)
        !           284:   int oldmask;
        !           285: #endif /* HAVE_BSD_SIGNALS */
        !           286: 
        !           287:   if (terminal_prepped)
        !           288:     return;
        !           289: 
        !           290:   if (!isatty(tty)) {      /* added by MdG */
        !           291:     terminal_prepped = 1;      /* added by MdG */
        !           292:     return;      /* added by MdG */
        !           293:   }      /* added by MdG */
        !           294:    
        !           295:   oldmask = sigblock (sigmask (SIGINT));
        !           296: 
        !           297:   /* We always get the latest tty values.  Maybe stty changed them. */
        !           298:   ioctl (tty, TIOCGETP, &the_ttybuff);
        !           299:   original_tty_flags = the_ttybuff.sg_flags;
        !           300: 
        !           301:   readline_echoing_p = (original_tty_flags & ECHO);
        !           302: 
        !           303: #if defined (TIOCLGET)
        !           304:   ioctl (tty, TIOCLGET, &local_mode_flags);
        !           305: #endif
        !           306: 
        !           307: #if !defined (ANYP)
        !           308: #  define ANYP (EVENP | ODDP)
        !           309: #endif
        !           310: 
        !           311:   /* If this terminal doesn't care how the 8th bit is used,
        !           312:      then we can use it for the meta-key.  We check by seeing
        !           313:      if BOTH odd and even parity are allowed. */
        !           314:   if (the_ttybuff.sg_flags & ANYP)
        !           315:     {
        !           316: #if defined (PASS8)
        !           317:       the_ttybuff.sg_flags |= PASS8;
        !           318: #endif
        !           319: 
        !           320:       /* Hack on local mode flags if we can. */
        !           321: #if defined (TIOCLGET) && defined (LPASS8)
        !           322:       {
        !           323:        int flags;
        !           324:        flags = local_mode_flags | LPASS8;
        !           325:        ioctl (tty, TIOCLSET, &flags);
        !           326:       }
        !           327: #endif /* TIOCLGET && LPASS8 */
        !           328:     }
        !           329: 
        !           330: #if defined (TIOCGETC)
        !           331:   {
        !           332:     struct tchars temp;
        !           333: 
        !           334:     ioctl (tty, TIOCGETC, &original_tchars);
        !           335:     temp = original_tchars;
        !           336: 
        !           337: #if defined (USE_XON_XOFF)
        !           338:     /* Get rid of C-s and C-q.
        !           339:        We remember the value of startc (C-q) so that if the terminal is in
        !           340:        xoff state, the user can xon it by pressing that character. */
        !           341:     xon_char = temp.t_startc;
        !           342:     temp.t_stopc = -1;
        !           343:     temp.t_startc = -1;
        !           344: 
        !           345:     /* If there is an XON character, bind it to restart the output. */
        !           346:     if (xon_char != -1)
        !           347:       bind_key (xon_char, restart_output);
        !           348: #endif /* USE_XON_XOFF */
        !           349: 
        !           350:     /* If there is an EOF char, bind eof_char to it. */
        !           351:     if (temp.t_eofc != -1)
        !           352:       eof_char = temp.t_eofc;
        !           353: 
        !           354: #if defined (NO_KILL_INTR)
        !           355:     /* Get rid of C-\ and C-c. */
        !           356:     temp.t_intrc = temp.t_quitc = -1;
        !           357: #endif /* NO_KILL_INTR */
        !           358: 
        !           359:     ioctl (tty, TIOCSETC, &temp);
        !           360:   }
        !           361: #endif /* TIOCGETC */
        !           362: 
        !           363: #if defined (TIOCGLTC)
        !           364:   {
        !           365:     struct ltchars temp;
        !           366: 
        !           367:     ioctl (tty, TIOCGLTC, &original_ltchars);
        !           368:     temp = original_ltchars;
        !           369: 
        !           370:     /* Make the interrupt keys go away.  Just enough to make people
        !           371:        happy. */
        !           372:     temp.t_dsuspc = -1;        /* C-y */
        !           373:     temp.t_lnextc = -1;        /* C-v */
        !           374: 
        !           375:     ioctl (tty, TIOCSLTC, &temp);
        !           376:   }
        !           377: #endif /* TIOCGLTC */
        !           378: 
        !           379:   the_ttybuff.sg_flags &= ~(ECHO | CRMOD);
        !           380:   the_ttybuff.sg_flags |= CBREAK;
        !           381:   ioctl (tty, TIOCSETN, &the_ttybuff);
        !           382: 
        !           383:   terminal_prepped = 1;
        !           384: 
        !           385: #if defined (HAVE_BSD_SIGNALS)
        !           386:   sigsetmask (oldmask);
        !           387: #endif
        !           388: }
        !           389: 
        !           390: /* Restore the terminal to its original state. */
        !           391: void deprep_terminal ()
        !           392: {
        !           393:   int tty = fileno (stdin);
        !           394: #if defined (HAVE_BSD_SIGNALS)
        !           395:   int oldmask;
        !           396: #endif
        !           397: 
        !           398:   if (!terminal_prepped)
        !           399:     return;
        !           400: 
        !           401: /* Added by MdG */
        !           402:   if (!isatty(tty)) {
        !           403:     terminal_prepped = 0;
        !           404:     return;
        !           405:   }
        !           406:    
        !           407:   oldmask = sigblock (sigmask (SIGINT));
        !           408: 
        !           409:   the_ttybuff.sg_flags = original_tty_flags;
        !           410:   ioctl (tty, TIOCSETN, &the_ttybuff);
        !           411:   readline_echoing_p = 1;
        !           412: 
        !           413: #if defined (TIOCLGET)
        !           414:   ioctl (tty, TIOCLSET, &local_mode_flags);
        !           415: #endif
        !           416: 
        !           417: #if defined (TIOCSLTC)
        !           418:   ioctl (tty, TIOCSLTC, &original_ltchars);
        !           419: #endif
        !           420: 
        !           421: #if defined (TIOCSETC)
        !           422:   ioctl (tty, TIOCSETC, &original_tchars);
        !           423: #endif
        !           424:   terminal_prepped = 0;
        !           425: 
        !           426: #if defined (HAVE_BSD_SIGNALS)
        !           427:   sigsetmask (oldmask);
        !           428: #endif
        !           429: }
        !           430: 
        !           431: #else  /* !defined (NEW_TTY_DRIVER) */
        !           432: 
        !           433: #if !defined (VMIN)
        !           434: #define VMIN VEOF
        !           435: #endif
        !           436: 
        !           437: #if !defined (VTIME)
        !           438: #define VTIME VEOL
        !           439: #endif
        !           440: 
        !           441: void prep_terminal ()
        !           442: {
        !           443:   int tty = fileno (stdin);
        !           444: #if defined (TERMIOS_TTY_DRIVER)
        !           445:   struct termios tio;
        !           446: #else
        !           447:   struct termio tio;
        !           448: #endif /* !TERMIOS_TTY_DRIVER */
        !           449: 
        !           450: #if defined (HAVE_POSIX_SIGNALS)
        !           451:   sigset_t set, oset;
        !           452: #else
        !           453: #  if defined (HAVE_BSD_SIGNALS)
        !           454:   int oldmask;
        !           455: #  endif /* HAVE_BSD_SIGNALS */
        !           456: #endif /* !HAVE_POSIX_SIGNALS */
        !           457: 
        !           458:   if (terminal_prepped)
        !           459:     return;
        !           460: 
        !           461:   if (!isatty(tty))  {     /* added by MdG */
        !           462:     terminal_prepped = 1;      /* added by MdG */
        !           463:     return;      /* added by MdG */
        !           464:   }      /* added by MdG */
        !           465:    
        !           466:   /* Try to keep this function from being INTerrupted.  We can do it
        !           467:      on POSIX and systems with BSD-like signal handling. */
        !           468: #if defined (HAVE_POSIX_SIGNALS)
        !           469:   sigemptyset (&set);
        !           470:   sigemptyset (&oset);
        !           471:   sigaddset (&set, SIGINT);
        !           472:   sigprocmask (SIG_BLOCK, &set, &oset);
        !           473: #else /* !HAVE_POSIX_SIGNALS */
        !           474: #  if defined (HAVE_BSD_SIGNALS)
        !           475:   oldmask = sigblock (sigmask (SIGINT));
        !           476: #  endif /* HAVE_BSD_SIGNALS */
        !           477: #endif /* !HAVE_POSIX_SIGNALS */
        !           478: 
        !           479: #if defined (TERMIOS_TTY_DRIVER)
        !           480:   tcgetattr (tty, &tio);
        !           481: #else
        !           482:   ioctl (tty, TCGETA, &tio);
        !           483: #endif /* !TERMIOS_TTY_DRIVER */
        !           484: 
        !           485:   otio = tio;
        !           486: 
        !           487:   readline_echoing_p = (tio.c_lflag & ECHO);
        !           488: 
        !           489:   tio.c_lflag &= ~(ICANON | ECHO);
        !           490: 
        !           491:   if (otio.c_cc[VEOF] != _POSIX_VDISABLE)
        !           492:     eof_char = otio.c_cc[VEOF];
        !           493: 
        !           494: #if defined (USE_XON_XOFF)
        !           495: #if defined (IXANY)
        !           496:   tio.c_iflag &= ~(IXON | IXOFF | IXANY);
        !           497: #else
        !           498:   /* `strict' Posix systems do not define IXANY. */
        !           499:   tio.c_iflag &= ~(IXON | IXOFF);
        !           500: #endif /* IXANY */
        !           501: #endif /* USE_XON_XOFF */
        !           502: 
        !           503:   /* Only turn this off if we are using all 8 bits. */
        !           504:   if ((tio.c_cflag & CSIZE) == CS8)
        !           505:     tio.c_iflag &= ~(ISTRIP | INPCK);
        !           506: 
        !           507:   /* Make sure we differentiate between CR and NL on input. */
        !           508:   tio.c_iflag &= ~(ICRNL | INLCR);
        !           509: 
        !           510: #if !defined (HANDLE_SIGNALS)
        !           511:   tio.c_lflag &= ~ISIG;
        !           512: #else
        !           513:   tio.c_lflag |= ISIG;
        !           514: #endif
        !           515: 
        !           516:   tio.c_cc[VMIN] = 1;
        !           517:   tio.c_cc[VTIME] = 0;
        !           518: 
        !           519:   /* Turn off characters that we need on Posix systems with job control,
        !           520:      just to be sure.  This includes ^Y and ^V.  This should not really
        !           521:      be necessary.  */
        !           522: #if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_JOB_CONTROL)
        !           523: 
        !           524: #if defined (VLNEXT)
        !           525:   tio.c_cc[VLNEXT] = _POSIX_VDISABLE;
        !           526: #endif
        !           527: 
        !           528: #if defined (VDSUSP)
        !           529:   tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
        !           530: #endif
        !           531: 
        !           532: #endif /* POSIX && JOB_CONTROL */
        !           533: 
        !           534: #if defined (TERMIOS_TTY_DRIVER)
        !           535:   tcsetattr (tty, TCSADRAIN, &tio);
        !           536:   tcflow (tty, TCOON);         /* Simulate a ^Q. */
        !           537: #else
        !           538:   ioctl (tty, TCSETAW, &tio);
        !           539:   ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
        !           540: #endif /* !TERMIOS_TTY_DRIVER */
        !           541: 
        !           542:   terminal_prepped = 1;
        !           543: 
        !           544: #if defined (HAVE_POSIX_SIGNALS)
        !           545:   sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
        !           546: #else
        !           547: #  if defined (HAVE_BSD_SIGNALS)
        !           548:   sigsetmask (oldmask);
        !           549: #  endif /* HAVE_BSD_SIGNALS */
        !           550: #endif /* !HAVE_POSIX_SIGNALS */
        !           551: }
        !           552: 
        !           553: void deprep_terminal ()
        !           554: {
        !           555:   int tty = fileno (stdin);
        !           556: 
        !           557:   /* Try to keep this function from being INTerrupted.  We can do it
        !           558:      on POSIX and systems with BSD-like signal handling. */
        !           559: #if defined (HAVE_POSIX_SIGNALS)
        !           560:   sigset_t set, oset;
        !           561: #else /* !HAVE_POSIX_SIGNALS */
        !           562: #  if defined (HAVE_BSD_SIGNALS)
        !           563:   int oldmask;
        !           564: #  endif /* HAVE_BSD_SIGNALS */
        !           565: #endif /* !HAVE_POSIX_SIGNALS */
        !           566: 
        !           567:   if (!terminal_prepped)
        !           568:     return;
        !           569: 
        !           570: /* Added by MdG */
        !           571:   if (!isatty(tty)) {
        !           572:     terminal_prepped = 0;
        !           573:     return;
        !           574:   }
        !           575: 
        !           576: #if defined (HAVE_POSIX_SIGNALS)
        !           577:   sigemptyset (&set);
        !           578:   sigemptyset (&oset);
        !           579:   sigaddset (&set, SIGINT);
        !           580:   sigprocmask (SIG_BLOCK, &set, &oset);
        !           581: #else /* !HAVE_POSIX_SIGNALS */
        !           582: #  if defined (HAVE_BSD_SIGNALS)
        !           583:   oldmask = sigblock (sigmask (SIGINT));
        !           584: #  endif /* HAVE_BSD_SIGNALS */
        !           585: #endif /* !HAVE_POSIX_SIGNALS */
        !           586: 
        !           587: #if defined (TERMIOS_TTY_DRIVER)
        !           588:   tcsetattr (tty, TCSADRAIN, &otio);
        !           589:   tcflow (tty, TCOON);         /* Simulate a ^Q. */
        !           590: #else /* TERMIOS_TTY_DRIVER */
        !           591:   ioctl (tty, TCSETAW, &otio);
        !           592:   ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
        !           593: #endif /* !TERMIOS_TTY_DRIVER */
        !           594: 
        !           595:   terminal_prepped = 0;
        !           596: 
        !           597: #if defined (HAVE_POSIX_SIGNALS)
        !           598:   sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
        !           599: #else /* !HAVE_POSIX_SIGNALS */
        !           600: #  if defined (HAVE_BSD_SIGNALS)
        !           601:   sigsetmask (oldmask);
        !           602: #  endif /* HAVE_BSD_SIGNALS */
        !           603: #endif /* !HAVE_POSIX_SIGNALS */
        !           604: }
        !           605: #endif  /* NEW_TTY_DRIVER */
        !           606: 
        !           607: /* If a character is available to be read, then read it
        !           608:    and stuff it into IBUFFER.  Otherwise, just return. */
        !           609: 
        !           610: long pending = -1L;
        !           611: 
        !           612: long key_avail (stream)
        !           613:        FILE *stream;
        !           614: {
        !           615:   int tty = fileno (stream);
        !           616:   long chars_avail = pending;
        !           617:   int result;
        !           618: 
        !           619:   if(!terminal_prepped)  prep_terminal();
        !           620: 
        !           621: #ifndef _WIN32
        !           622:   result = ioctl (tty, FIONREAD, &chars_avail);
        !           623: #else
        !           624:   {
        !           625:      fd_set selin;
        !           626:      static int now[2] = { 0 , 0 };
        !           627:      int res;
        !           628: 
        !           629:      FD_ZERO(&selin);
        !           630:      FD_SET(tty, &selin);
        !           631:      chars_avail=select(1, &selin, NULL, NULL, now);
        !           632:   }
        !           633: #endif
        !           634: 
        !           635:   if(chars_avail == -1L)
        !           636:     {  unsigned char inchar;
        !           637: 
        !           638:        fcntl(tty, F_SETFL, O_NDELAY);
        !           639:        result = read(tty, &inchar, sizeof(char));
        !           640:        if(result == sizeof(char))
        !           641:        {
        !           642:          chars_avail = 1;
        !           643:          pending = (long)inchar;
        !           644:        }
        !           645:        else
        !           646:          chars_avail = 0;
        !           647:        fcntl(tty, F_SETFL, 0);
        !           648:     }
        !           649: 
        !           650:   return chars_avail;
        !           651: }
        !           652: 
        !           653: /* Get a key from the buffer of characters to be read.
        !           654:    Return the key in KEY.
        !           655:    Result is KEY if there was a key, or 0 if there wasn't. */
        !           656: 
        !           657: /* When compiling and running in the `Posix' environment, Ultrix does
        !           658:    not restart system calls, so this needs to do it. */
        !           659: 
        !           660: unsigned char getkey(stream)
        !           661:      FILE *stream;
        !           662: {
        !           663:   int result;
        !           664:   unsigned char c;
        !           665: 
        !           666:   if(!terminal_prepped)  prep_terminal();
        !           667: 
        !           668:   while (pending < 0)
        !           669:     {
        !           670:       result = read (fileno (stream), &c, sizeof (char));
        !           671: 
        !           672:       if (result == sizeof (char))
        !           673:         return /* (c == 0x7F ? 0x08 :*/ c /*)*/;
        !           674: 
        !           675:       /* If zero characters are returned, then the file that we are
        !           676:         reading from is empty!  Return EOF in that case. */
        !           677:       if (result == 0)
        !           678:        return CTRL('D');
        !           679: 
        !           680:       /* If the error that we received was SIGINT, then try again,
        !           681:         this is simply an interrupted system call to read ().
        !           682:         Otherwise, some error ocurred, also signifying EOF. */
        !           683:       if (errno != EINTR)
        !           684:        return (EOF);
        !           685:     }
        !           686: 
        !           687:   result = (int) pending;
        !           688:   pending = -1L;
        !           689: 
        !           690:   return result;
        !           691: }
        !           692: 
        !           693: #ifdef TEST
        !           694: 
        !           695: #include <time.h>
        !           696: 
        !           697: int timewait=100000;
        !           698: 
        !           699: int main()
        !           700: {
        !           701:        unsigned char c;
        !           702: 
        !           703:        prep_terminal();
        !           704: 
        !           705:        do
        !           706:        {
        !           707:                int i=0;
        !           708: 
        !           709:                while(!key_avail(stdin))
        !           710:                {
        !           711:                        printf("%04d",i);
        !           712:                        fflush(stdout);
        !           713:                        {
        !           714:                                struct timeval timeout;
        !           715:                                timeout.tv_sec=timewait/1000000;
        !           716:                                timeout.tv_usec=timewait%1000000;
        !           717:                                (void)select(0,0,0,0,&timeout);
        !           718:                        }
        !           719:                        i++;
        !           720:                        printf("\b\b\b\b");
        !           721:                        fflush(stdout);
        !           722:                }
        !           723:                c = getkey(stdin);
        !           724:                printf("%02x,",(int)c);
        !           725:                fflush(stdout);
        !           726:        }       while(c != 0x1B);
        !           727: 
        !           728:        deprep_terminal();
        !           729:        puts("");
        !           730: }
        !           731: #endif
        !           732: #endif /* MSDOS */
        !           733: 
        !           734: /* signal handling adapted from pfe by Dirk Zoller (Copylefted) - anton */
        !           735: 
        !           736: static void
        !           737: graceful_exit (int sig)
        !           738: {
        !           739:   deprep_terminal();
        !           740:   fprintf (stderr, "\n\n%s.\n", strsignal (sig));
        !           741:   exit (0x80|sig);
        !           742: }
        !           743: 
        !           744: jmp_buf throw_jmp_buf;
        !           745: 
        !           746: static void 
        !           747: signal_throw(int sig)
        !           748: {
        !           749:   int code;
        !           750:   struct {
        !           751:     int signal;
        !           752:     int throwcode;
        !           753:   } *p, throwtable[] = {
        !           754:     { SIGINT, -28 },
        !           755:     { SIGFPE, -55 },
        !           756: #ifdef SIGBUS
        !           757:     { SIGBUS, -23 },
        !           758: #endif
        !           759:     { SIGSEGV, -9 },
        !           760:   };
        !           761:   signal(sig,signal_throw);
        !           762:   for (code=-256-sig, p=throwtable; p<throwtable+(sizeof(throwtable)/sizeof(*p)); p++)
        !           763:     if (sig == p->signal) {
        !           764:       code = p->throwcode;
        !           765:       break;
        !           766:     }
        !           767:   longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */
        !           768: }
        !           769: 
        !           770: UCell cols=80;
        !           771: #if defined(MSDOS) || defined (_WIN32)
        !           772: UCell rows=25;
        !           773: #else
        !           774: UCell rows=24;
        !           775: #endif
        !           776: 
        !           777: #ifdef SIGCONT
        !           778: static void termprep (int sig)
        !           779: {
        !           780:   signal(sig,termprep);
        !           781:   terminal_prepped=0;
        !           782: }
        !           783: #endif
        !           784: 
        !           785: #ifdef SIGWINCH
        !           786: void get_winsize()
        !           787: {
        !           788: #ifdef TIOCGWINSZ
        !           789:   struct winsize size;
        !           790:   
        !           791:   if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
        !           792:     rows = size.ws_row;
        !           793:     cols = size.ws_col;
        !           794:   }
        !           795: #else
        !           796:   char *s, *ends;
        !           797:   unsigned long ul;
        !           798:   if (s=getenv("LINES")) {
        !           799:     rows=atoi(s);
        !           800:     if (rows==0)
        !           801:       rows=24;
        !           802:   }
        !           803:   if (s=getenv("COLUMNS")) {
        !           804:     rows=atoi(s);
        !           805:     if (rows==0)
        !           806:       cols=80;
        !           807:   }
        !           808: #endif
        !           809: }
        !           810: 
        !           811: static void change_winsize(int sig)
        !           812: {
        !           813:   signal(sig,change_winsize);
        !           814: #ifdef TIOCGWINSZ
        !           815:   get_winsize();
        !           816: #endif
        !           817: }
        !           818: #endif
        !           819: 
        !           820: void install_signal_handlers (void)
        !           821: {
        !           822: 
        !           823: #if 0
        !           824: /* these signals are handled right by default, no need to handle them;
        !           825:    they are listed here just for fun */
        !           826:   static short sigs_to_default [] = {
        !           827: #ifdef SIGCHLD
        !           828:     SIGCHLD,
        !           829: #endif
        !           830: #ifdef SIGINFO
        !           831:     SIGINFO,
        !           832: #endif
        !           833: #ifdef SIGIO
        !           834:     SIGIO,
        !           835: #endif
        !           836: #ifdef SIGLOST
        !           837:     SIGLOST,
        !           838: #endif
        !           839: #ifdef SIGKILL
        !           840:     SIGKILL,
        !           841: #endif
        !           842: #ifdef SIGSTOP
        !           843:     SIGSTOP,
        !           844: #endif
        !           845: #ifdef SIGPWR
        !           846:     SIGPWR,
        !           847: #endif
        !           848: #ifdef SIGMSG
        !           849:     SIGMSG,
        !           850: #endif
        !           851: #ifdef SIGDANGER
        !           852:     SIGDANGER,
        !           853: #endif
        !           854: #ifdef SIGMIGRATE
        !           855:     SIGMIGRATE,
        !           856: #endif
        !           857: #ifdef SIGPRE
        !           858:     SIGPRE,
        !           859: #endif
        !           860: #ifdef SIGVIRT
        !           861:     SIGVIRT,
        !           862: #endif
        !           863: #ifdef SIGGRANT
        !           864:     SIGGRANT,
        !           865: #endif
        !           866: #ifdef SIGRETRACT
        !           867:     SIGRETRACT,
        !           868: #endif
        !           869: #ifdef SIGSOUND
        !           870:     SIGSOUND,
        !           871: #endif
        !           872: #ifdef SIGSAK
        !           873:     SIGSAK,
        !           874: #endif
        !           875: #ifdef SIGTSTP
        !           876:     SIGTSTP,
        !           877: #endif
        !           878: #ifdef SIGTTIN
        !           879:     SIGTTIN,
        !           880: #endif
        !           881: #ifdef SIGTTOU
        !           882:     SIGTTOU,
        !           883: #endif
        !           884: #ifdef SIGSTKFLT
        !           885:     SIGSTKFLT,
        !           886: #endif
        !           887: #ifdef SIGUNUSED
        !           888:     SIGUNUSED,
        !           889: #endif
        !           890:   };
        !           891: #endif
        !           892: 
        !           893:   static short sigs_to_throw [] = {
        !           894: #ifdef SIGBREAK
        !           895:     SIGBREAK,
        !           896: #endif
        !           897: #ifdef SIGINT
        !           898:     SIGINT,
        !           899: #endif
        !           900: #ifdef SIGILL
        !           901:     SIGILL,
        !           902: #endif
        !           903: #ifdef SIGEMT
        !           904:     SIGEMT,
        !           905: #endif
        !           906: #ifdef SIGFPE
        !           907:     SIGFPE,
        !           908: #endif
        !           909: #ifdef SIGIOT
        !           910:     SIGIOT,
        !           911: #endif
        !           912: #ifdef SIGSEGV
        !           913:     SIGSEGV,
        !           914: #endif
        !           915: #ifdef SIGALRM
        !           916:     SIGALRM,
        !           917: #endif
        !           918: #ifdef SIGPIPE
        !           919:     SIGPIPE,
        !           920: #endif
        !           921: #ifdef SIGPOLL
        !           922:     SIGPOLL,
        !           923: #endif
        !           924: #ifdef SIGPROF
        !           925:     SIGPROF,
        !           926: #endif
        !           927: #ifdef SIGBUS
        !           928:     SIGBUS,
        !           929: #endif
        !           930: #ifdef SIGSYS
        !           931:     SIGSYS,
        !           932: #endif
        !           933: #ifdef SIGTRAP
        !           934:     SIGTRAP,
        !           935: #endif
        !           936: #ifdef SIGURG
        !           937:     SIGURG,
        !           938: #endif
        !           939: #ifdef SIGUSR1
        !           940:     SIGUSR1,
        !           941: #endif
        !           942: #ifdef SIGUSR2
        !           943:     SIGUSR2,
        !           944: #endif
        !           945: #ifdef SIGVTALRM
        !           946:     SIGVTALRM,
        !           947: #endif
        !           948: #ifdef SIGXFSZ
        !           949:     SIGXFSZ,
        !           950: #endif
        !           951:   };
        !           952:   static short sigs_to_quit [] = {
        !           953: #ifdef SIGHUP
        !           954:     SIGHUP,
        !           955: #endif
        !           956: #ifdef SIGQUIT
        !           957:     SIGQUIT,
        !           958: #endif
        !           959: #ifdef SIGABRT
        !           960:     SIGABRT,
        !           961: #endif
        !           962: #ifdef SIGTERM
        !           963:     SIGTERM,
        !           964: #endif
        !           965: #ifdef SIGXCPU
        !           966:     SIGXCPU,
        !           967: #endif
        !           968:   };
        !           969:   int i;
        !           970: 
        !           971: #define DIM(X)         (sizeof (X) / sizeof *(X))
        !           972: /*
        !           973:   for (i = 0; i < DIM (sigs_to_ignore); i++)
        !           974:     signal (sigs_to_ignore [i], SIG_IGN);
        !           975: */
        !           976:   for (i = 0; i < DIM (sigs_to_throw); i++)
        !           977:     signal (sigs_to_throw [i], signal_throw);
        !           978:   for (i = 0; i < DIM (sigs_to_quit); i++)
        !           979:     signal (sigs_to_quit [i], graceful_exit);
        !           980: #ifdef SIGCONT
        !           981:     signal (SIGCONT, termprep);
        !           982: #endif
        !           983: #ifdef SIGWINCH
        !           984:     signal (SIGWINCH, change_winsize);
        !           985: #endif
        !           986: }
        !           987: /* end signal handling */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>