File:  [gforth] / gforth / Attic / io.c
Revision 1.5: download - view: text, annotated - select for diffs
Tue Jul 12 11:30:58 1994 UTC (29 years, 9 months ago) by pazsan
Branches: MAIN
CVS tags: HEAD
Added job control

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

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