nc: use symbolic SHUT_WR instead of literal 1
[oweals/busybox.git] / console-tools / showkey.c
index 149ea64659f2f13b50fe34ac9768ab22954f77cc..69b785ec6200d3f788a814962d86a268fa95c950 100644 (file)
@@ -7,9 +7,31 @@
  * Licensed under GPLv2, see file LICENSE in this source tree.
  */
 
+//usage:#define showkey_trivial_usage
+//usage:       "[-a | -k | -s]"
+//usage:#define showkey_full_usage "\n\n"
+//usage:       "Show keys pressed\n"
+//usage:     "\n       -a      Display decimal/octal/hex values of the keys"
+//usage:     "\n       -k      Display interpreted keycodes (default)"
+//usage:     "\n       -s      Display raw scan-codes"
+
 #include "libbb.h"
 #include <linux/kd.h>
 
+
+struct globals {
+       int kbmode;
+       struct termios tio, tio0;
+};
+#define G (*ptr_to_globals)
+#define kbmode (G.kbmode)
+#define tio    (G.tio)
+#define tio0   (G.tio0)
+#define INIT_G() do { \
+       SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+} while (0)
+
+
 // set raw tty mode
 // also used by microcom
 // libbb candidates?
@@ -20,97 +42,85 @@ static void xget1(struct termios *t, struct termios *oldt)
        cfmakeraw(t);
 }
 
-static void xset1(struct termios *tio)
+static void xset1(struct termios *t)
 {
-       int ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, tio);
+       int ret = tcsetattr(STDIN_FILENO, TCSAFLUSH, t);
        if (ret) {
                bb_perror_msg("can't tcsetattr for stdin");
        }
 }
 
-/*
- * GLOBALS
- */
-struct globals {
-       int kbmode;
-       struct termios tio, tio0;
-};
-#define G (*ptr_to_globals)
-#define kbmode (G.kbmode)
-#define tio    (G.tio)
-#define tio0   (G.tio0)
-#define INIT_G() do { \
-       SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
-} while (0)
-
-
-static void signal_handler(int signo)
-{
-       // restore keyboard and console settings
-       xset1(&tio0);
-       xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode);
-       // alarmed? -> exit 0
-       exit(SIGALRM == signo);
-}
-
 int showkey_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int showkey_main(int argc UNUSED_PARAM, char **argv)
 {
        enum {
-               OPT_a = (1<<0), // display the decimal/octal/hex values of the keys
-               OPT_k = (1<<1), // display only the interpreted keycodes (default)
-               OPT_s = (1<<2), // display only the raw scan-codes
+               OPT_a = (1<<0), // display the decimal/octal/hex values of the keys
+               OPT_k = (1<<1), // display only the interpreted keycodes (default)
+               OPT_s = (1<<2), // display only the raw scan-codes
        };
 
+       INIT_G();
+
        // FIXME: aks are all mutually exclusive
        getopt32(argv, "aks");
 
-       INIT_G();
-
-       // get keyboard settings
-       xioctl(STDIN_FILENO, KDGKBMODE, &kbmode);
-       printf("kb mode was %s\n\nPress any keys. Program terminates %s\n\n",
-               kbmode == K_RAW ? "RAW" :
-                       (kbmode == K_XLATE ? "XLATE" :
-                               (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" :
-                                       (kbmode == K_UNICODE ? "UNICODE" : "?UNKNOWN?")))
-               , (option_mask32 & OPT_a) ? "when CTRL+D pressed" : "10s after last keypress"
-       );
        // prepare for raw mode
        xget1(&tio, &tio0);
        // put stdin in raw mode
        xset1(&tio);
 
+#define press_keys "Press any keys, program terminates %s:\r\n\n"
+
        if (option_mask32 & OPT_a) {
-               unsigned char c;
                // just read stdin char by char
-               while (1 == safe_read(STDIN_FILENO, &c, 1)) {
+               unsigned char c;
+
+               printf(press_keys, "on EOF (ctrl-D)");
+
+               // read and show byte values
+               while (1 == read(STDIN_FILENO, &c, 1)) {
                        printf("%3u 0%03o 0x%02x\r\n", c, c, c);
                        if (04 /*CTRL-D*/ == c)
                                break;
                }
+
        } else {
-               // we should exit on any signal
-               bb_signals(BB_FATAL_SIGS, signal_handler);
+               // we assume a PC keyboard
+               xioctl(STDIN_FILENO, KDGKBMODE, &kbmode);
+               printf("Keyboard mode was %s.\r\n\n",
+                       kbmode == K_RAW ? "RAW" :
+                               (kbmode == K_XLATE ? "XLATE" :
+                                       (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" :
+                                               (kbmode == K_UNICODE ? "UNICODE" : "UNKNOWN")))
+               );
+
                // set raw keyboard mode
                xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW));
 
+               // we should exit on any signal; signals should interrupt read
+               bb_signals_recursive_norestart(BB_FATAL_SIGS, record_signo);
+
+               // inform user that program ends after time of inactivity
+               printf(press_keys, "10s after last keypress");
+
                // read and show scancodes
-               while (1) {
+               while (!bb_got_signal) {
                        char buf[18];
                        int i, n;
+
                        // setup 10s watchdog
                        alarm(10);
+
                        // read scancodes
                        n = read(STDIN_FILENO, buf, sizeof(buf));
                        i = 0;
                        while (i < n) {
-                               char c = buf[i];
-                               // show raw scancodes ordered? ->
                                if (option_mask32 & OPT_s) {
+                                       // show raw scancodes
                                        printf("0x%02x ", buf[i++]);
-                               // show interpreted scancodes (default) ? ->
                                } else {
+                                       // show interpreted scancodes (default)
+                                       char c = buf[i];
                                        int kc;
                                        if (i+2 < n
                                         && (c & 0x7f) == 0
@@ -128,11 +138,13 @@ int showkey_main(int argc UNUSED_PARAM, char **argv)
                        }
                        puts("\r");
                }
+
+               // restore keyboard mode
+               xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode);
        }
 
-       // cleanup
-       signal_handler(SIGALRM);
+       // restore console settings
+       xset1(&tio0);
 
-       // should never be here!
        return EXIT_SUCCESS;
 }