File:  [gforth] / gforth / Attic / io.c
Revision 1.8: download - view: text, annotated - select for diffs
Mon Mar 13 09:17:29 1995 UTC (26 years, 6 months ago) by anton
Branches: MAIN
CVS tags: HEAD
Added stuff for documenting Forth source and integrating it into the texi file
changed checks for DOMAINOS to checks for apollo (which is defined on apollos)
changed "-evaluate" (which did not work anyway) to "--evaluate"
added debugging.fs and assert.fs to startup.fs

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

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