File:  [gforth] / gforth / Attic / io.c
Revision 1.11: download - view: text, annotated - select for diffs
Tue Nov 7 18:06:46 1995 UTC (23 years, 11 months ago) by anton
Branches: MAIN
CVS tags: gforth-0_1beta, HEAD
added copyright headers
changes to loadfilename & co. to make savesystem transparent to
 assertions and ~~

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

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