File:  [gforth] / gforth / Attic / io.c
Revision 1.1: download - view: text, annotated - select for diffs
Fri Feb 11 16:30:46 1994 UTC (25 years, 5 months ago) by anton
Branches: MAIN
CVS tags: HEAD
Initial revision

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

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