Annotation of gforth/io.c, revision 1.2

1.1       anton       1: /*     direct key io driver
                      2: 
                      3:        The following is stolen from the readline library for bash
                      4: */
                      5: 
1.2     ! benschop    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: 
1.1       anton      14: #include <stdio.h>
                     15: #include <signal.h>
                     16: #include <sys/types.h>
1.2     ! benschop   17: #ifndef DOMAINOS
1.1       anton      18: #include <sys/ioctl.h>
1.2     ! benschop   19: #endif
1.1       anton      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
1.2     ! benschop   37: #ifndef DOMAINOS
1.1       anton      38: #define USE_XON_XOFF
1.2     ! benschop   39: #endif
1.1       anton      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: 
1.2     ! benschop  104: #if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(DOMAINOS)
1.1       anton     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, SIGEMT, SIGBUS, SIGSYS
                    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>