File:  [gforth] / gforth / Attic / io.c
Revision 1.10: download - view: text, annotated - select for diffs
Mon Oct 16 18:33:10 1995 UTC (23 years, 10 months ago) by anton
Branches: MAIN
CVS tags: HEAD
added answords.fs and strsignal.c
added checking of documenetation of ANS Forth words
Fixed many documentation errors and added some documentation
signal handling now uses strsignal and can handle signals not present on all machines

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

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