File:  [gforth] / gforth / Attic / io.c
Revision 1.4: download - view: text, annotated - select for diffs
Fri Jul 8 15:00:45 1994 UTC (29 years, 8 months ago) by anton
Branches: MAIN
CVS tags: HEAD
signals are now translated into THROWs
A number of bug fixes (make a diff of BUGS for details)
added assert.fs and debugging.fs
made .s nicer
keep names of included files (in loadfilename) and print them upon error

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

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