Annotation of gforth/io.c, revision 1.1

1.1     ! anton       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>