File:  [gforth] / gforth / Attic / io.c
Revision 1.3: download - view: text, annotated - select for diffs
Fri Jun 17 12:35:05 1994 UTC (25 years, 3 months ago) by anton
Branches: MAIN
CVS tags: HEAD
Integrated locals (in particular automatic scoping) into the system.

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

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