aboutsummaryrefslogtreecommitdiff
path: root/console-tools
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2015-05-15 10:20:47 +0200
committerBjørn Mork <bjorn@mork.no>2015-05-15 10:20:47 +0200
commit73b16af8feec390afbabd9356d6e5e83c0390838 (patch)
tree3730020ba2f9caeb9d7815a975af51830b51ce11 /console-tools
busybox: imported from http://www.busybox.net/downloads/busybox-1.13.3.tar.bz2busybox-1.13.3
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Diffstat (limited to 'console-tools')
-rw-r--r--console-tools/Config.in138
-rw-r--r--console-tools/Kbuild22
-rw-r--r--console-tools/chvt.c24
-rw-r--r--console-tools/clear.c19
-rw-r--r--console-tools/deallocvt.c33
-rw-r--r--console-tools/dumpkmap.c69
-rw-r--r--console-tools/kbd_mode.c55
-rw-r--r--console-tools/loadfont.c371
-rw-r--r--console-tools/loadkmap.c65
-rw-r--r--console-tools/openvt.c181
-rw-r--r--console-tools/reset.c47
-rw-r--r--console-tools/resize.c71
-rw-r--r--console-tools/setconsole.c39
-rw-r--r--console-tools/setkeycodes.c49
-rw-r--r--console-tools/setlogcons.c30
-rw-r--r--console-tools/showkey.c138
16 files changed, 1351 insertions, 0 deletions
diff --git a/console-tools/Config.in b/console-tools/Config.in
new file mode 100644
index 0000000..994140b
--- /dev/null
+++ b/console-tools/Config.in
@@ -0,0 +1,138 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Console Utilities"
+
+config CHVT
+ bool "chvt"
+ default n
+ help
+ This program is used to change to another terminal.
+ Example: chvt 4 (change to terminal /dev/tty4)
+
+config CLEAR
+ bool "clear"
+ default n
+ help
+ This program clears the terminal screen.
+
+config DEALLOCVT
+ bool "deallocvt"
+ default n
+ help
+ This program deallocates unused virtual consoles.
+
+config DUMPKMAP
+ bool "dumpkmap"
+ default n
+ help
+ This program dumps the kernel's keyboard translation table to
+ stdout, in binary format. You can then use loadkmap to load it.
+
+config KBD_MODE
+ bool "kbd_mode"
+ default n
+ help
+ This program reports and sets keyboard mode.
+
+config LOADFONT
+ bool "loadfont"
+ default n
+ help
+ This program loads a console font from standard input.
+
+config LOADKMAP
+ bool "loadkmap"
+ default n
+ help
+ This program loads a keyboard translation table from
+ standard input.
+
+config OPENVT
+ bool "openvt"
+ default n
+ help
+ This program is used to start a command on an unused
+ virtual terminal.
+
+config RESET
+ bool "reset"
+ default n
+ help
+ This program is used to reset the terminal screen, if it
+ gets messed up.
+
+config RESIZE
+ bool "resize"
+ default n
+ help
+ This program is used to (re)set the width and height of your current
+ terminal.
+
+config FEATURE_RESIZE_PRINT
+ bool "Print environment variables"
+ default n
+ depends on RESIZE
+ help
+ Prints the newly set size (number of columns and rows) of
+ the terminal.
+ E.g.:
+ COLUMNS=80;LINES=44;export COLUMNS LINES;
+
+config SETCONSOLE
+ bool "setconsole"
+ default n
+ help
+ This program redirects the system console to another device,
+ like the current tty while logged in via telnet.
+
+config FEATURE_SETCONSOLE_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on SETCONSOLE && GETOPT_LONG
+ help
+ Support long options for the setconsole applet.
+
+config SETFONT
+ bool "setfont"
+ default n
+ help
+ Allows to load console screen map. Useful for i18n.
+
+config FEATURE_SETFONT_TEXTUAL_MAP
+ bool "Support reading textual screen maps"
+ default n
+ depends on SETFONT
+ help
+ Support reading textual screen maps.
+
+config DEFAULT_SETFONT_DIR
+ string "Default directory for console-tools files"
+ default ""
+ depends on SETFONT
+ help
+ Directory to use if setfont's params are simple filenames
+ (not /path/to/file or ./file). Default is "" (no default directory).
+
+config SETKEYCODES
+ bool "setkeycodes"
+ default n
+ help
+ This program loads entries into the kernel's scancode-to-keycode
+ map, allowing unusual keyboards to generate usable keycodes.
+
+config SETLOGCONS
+ bool "setlogcons"
+ default n
+ help
+ This program redirects the output console of kernel messages.
+
+config SHOWKEY
+ bool "showkey"
+ default n
+ help
+ Shows keys pressed.
+
+endmenu
diff --git a/console-tools/Kbuild b/console-tools/Kbuild
new file mode 100644
index 0000000..df5ffdb
--- /dev/null
+++ b/console-tools/Kbuild
@@ -0,0 +1,22 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+lib-y:=
+lib-$(CONFIG_CHVT) += chvt.o
+lib-$(CONFIG_CLEAR) += clear.o
+lib-$(CONFIG_DEALLOCVT) += deallocvt.o
+lib-$(CONFIG_DUMPKMAP) += dumpkmap.o
+lib-$(CONFIG_SETCONSOLE) += setconsole.o
+lib-$(CONFIG_KBD_MODE) += kbd_mode.o
+lib-$(CONFIG_LOADFONT) += loadfont.o
+lib-$(CONFIG_LOADKMAP) += loadkmap.o
+lib-$(CONFIG_OPENVT) += openvt.o
+lib-$(CONFIG_RESET) += reset.o
+lib-$(CONFIG_RESIZE) += resize.o
+lib-$(CONFIG_SETFONT) += loadfont.o
+lib-$(CONFIG_SETKEYCODES) += setkeycodes.o
+lib-$(CONFIG_SETLOGCONS) += setlogcons.o
+lib-$(CONFIG_SHOWKEY) += showkey.o
diff --git a/console-tools/chvt.c b/console-tools/chvt.c
new file mode 100644
index 0000000..302ffb4
--- /dev/null
+++ b/console-tools/chvt.c
@@ -0,0 +1,24 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chvt implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+int chvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int chvt_main(int argc, char **argv)
+{
+ int num;
+
+ if (argc != 2) {
+ bb_show_usage();
+ }
+
+ num = xatou_range(argv[1], 1, 63);
+ console_make_active(get_console_fd_or_die(), num);
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/clear.c b/console-tools/clear.c
new file mode 100644
index 0000000..8b727b3
--- /dev/null
+++ b/console-tools/clear.c
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini clear implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+
+/* no options, no getopt */
+
+#include "libbb.h"
+
+int clear_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ return printf("\033[H\033[J") != 6;
+}
diff --git a/console-tools/deallocvt.c b/console-tools/deallocvt.c
new file mode 100644
index 0000000..0974883
--- /dev/null
+++ b/console-tools/deallocvt.c
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Disallocate virtual terminal(s)
+ *
+ * Copyright (C) 2003 by Tito Ragusa <farmatito@tiscali.it>
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* no options, no getopt */
+
+#include "libbb.h"
+
+/* From <linux/vt.h> */
+enum { VT_DISALLOCATE = 0x5608 }; /* free memory associated to vt */
+
+int deallocvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int deallocvt_main(int argc UNUSED_PARAM, char **argv)
+{
+ /* num = 0 deallocate all unused consoles */
+ int num = 0;
+
+ if (argv[1]) {
+ if (argv[2])
+ bb_show_usage();
+ num = xatou_range(argv[1], 1, 63);
+ }
+
+ /* double cast suppresses "cast to ptr from int of different size" */
+ xioctl(get_console_fd_or_die(), VT_DISALLOCATE, (void *)(ptrdiff_t)num);
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/dumpkmap.c b/console-tools/dumpkmap.c
new file mode 100644
index 0000000..c382b5a
--- /dev/null
+++ b/console-tools/dumpkmap.c
@@ -0,0 +1,69 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini dumpkmap implementation for busybox
+ *
+ * Copyright (C) Arne Bernin <arne@matrix.loopback.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+/* no options, no getopt */
+
+#include "libbb.h"
+
+/* From <linux/kd.h> */
+struct kbentry {
+ unsigned char kb_table;
+ unsigned char kb_index;
+ unsigned short kb_value;
+};
+#define KDGKBENT 0x4B46 /* gets one entry in translation table */
+
+/* From <linux/keyboard.h> */
+#define NR_KEYS 128
+#define MAX_NR_KEYMAPS 256
+
+int dumpkmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int dumpkmap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ struct kbentry ke;
+ int i, j, fd;
+ RESERVE_CONFIG_BUFFER(flags,MAX_NR_KEYMAPS);
+
+/* bb_warn_ignoring_args(argc>=2);*/
+
+ fd = get_console_fd_or_die();
+
+ write(STDOUT_FILENO, "bkeymap", 7);
+
+ /* Here we want to set everything to 0 except for indexes:
+ * [0-2] [4-6] [8-10] [12] */
+ memset(flags, 0x00, MAX_NR_KEYMAPS);
+ memset(flags, 0x01, 13);
+ flags[3] = flags[7] = flags[11] = 0;
+
+ /* dump flags */
+ write(STDOUT_FILENO, flags, MAX_NR_KEYMAPS);
+
+ for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+ if (flags[i] == 1) {
+ for (j = 0; j < NR_KEYS; j++) {
+ ke.kb_index = j;
+ ke.kb_table = i;
+ if (!ioctl_or_perror(fd, KDGKBENT, &ke,
+ "ioctl failed with %s, %s, %p",
+ (char *)&ke.kb_index,
+ (char *)&ke.kb_table,
+ &ke.kb_value)
+ ) {
+ write(STDOUT_FILENO, (void*)&ke.kb_value, 2);
+ }
+ }
+ }
+ }
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ close(fd);
+ RELEASE_CONFIG_BUFFER(flags);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/kbd_mode.c b/console-tools/kbd_mode.c
new file mode 100644
index 0000000..544bbb7
--- /dev/null
+++ b/console-tools/kbd_mode.c
@@ -0,0 +1,55 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini kbd_mode implementation for busybox
+ *
+ * Copyright (C) 2007 Loic Grenie <loic.grenie@gmail.com>
+ * written using Andries Brouwer <aeb@cwi.nl>'s kbd_mode from
+ * console-utils v0.2.3, licensed under GNU GPLv2
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include <linux/kd.h>
+
+int kbd_mode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int kbd_mode_main(int argc UNUSED_PARAM, char **argv)
+{
+ enum {
+ SCANCODE = (1 << 0),
+ ASCII = (1 << 1),
+ MEDIUMRAW = (1 << 2),
+ UNICODE = (1 << 3),
+ };
+ int fd;
+ unsigned opt;
+ const char *tty_name = CURRENT_TTY;
+
+ opt = getopt32(argv, "sakuC:", &tty_name);
+ fd = xopen(tty_name, O_NONBLOCK);
+ opt &= 0xf; /* clear -C bit, see (*) */
+
+ if (!opt) { /* print current setting */
+ const char *mode = "unknown";
+ int m;
+
+ xioctl(fd, KDGKBMODE, &m);
+ if (m == K_RAW)
+ mode = "raw (scancode)";
+ else if (m == K_XLATE)
+ mode = "default (ASCII)";
+ else if (m == K_MEDIUMRAW)
+ mode = "mediumraw (keycode)";
+ else if (m == K_UNICODE)
+ mode = "Unicode (UTF-8)";
+ printf("The keyboard is in %s mode\n", mode);
+ } else {
+ /* here we depend on specific bits assigned to options (*) */
+ opt = opt & UNICODE ? 3 : opt >> 1;
+ /* double cast prevents warnings about widening conversion */
+ xioctl(fd, KDSKBMODE, (void*)(ptrdiff_t)opt);
+ }
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close(fd);
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c
new file mode 100644
index 0000000..863c6ef
--- /dev/null
+++ b/console-tools/loadfont.c
@@ -0,0 +1,371 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * loadfont.c - Eugene Crosser & Andries Brouwer
+ *
+ * Version 0.96bb
+ *
+ * Loads the console font, and possibly the corresponding screen map(s).
+ * (Adapted for busybox by Matej Vela.)
+ */
+#include "libbb.h"
+#include <sys/kd.h>
+
+#ifndef KDFONTOP
+#define KDFONTOP 0x4B72
+struct console_font_op {
+ unsigned op; /* KD_FONT_OP_* */
+ unsigned flags; /* KD_FONT_FLAG_* */
+ unsigned width, height;
+ unsigned charcount;
+ unsigned char *data; /* font data with height fixed to 32 */
+};
+
+#define KD_FONT_OP_SET 0 /* Set font */
+#define KD_FONT_OP_GET 1 /* Get font */
+#define KD_FONT_OP_SET_DEFAULT 2 /* Set font to default,
+ data points to name / NULL */
+#define KD_FONT_OP_COPY 3 /* Copy from another console */
+
+#define KD_FONT_FLAG_OLD 0x80000000 /* Invoked via old interface */
+#define KD_FONT_FLAG_DONT_RECALC 1 /* Don't call adjust_height() */
+ /* (Used internally for PIO_FONT support) */
+#endif /* KDFONTOP */
+
+
+enum {
+ PSF_MAGIC1 = 0x36,
+ PSF_MAGIC2 = 0x04,
+
+ PSF_MODE512 = 0x01,
+ PSF_MODEHASTAB = 0x02,
+ PSF_MAXMODE = 0x03,
+ PSF_SEPARATOR = 0xffff
+};
+
+struct psf_header {
+ unsigned char magic1, magic2; /* Magic number */
+ unsigned char mode; /* PSF font mode */
+ unsigned char charsize; /* Character size */
+};
+
+#define PSF_MAGIC_OK(x) ((x)->magic1 == PSF_MAGIC1 && (x)->magic2 == PSF_MAGIC2)
+
+static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
+{
+ char *buf;
+ int i;
+
+ if (unit < 1 || unit > 32)
+ bb_error_msg_and_die("bad character size %d", unit);
+
+ buf = xzalloc(16 * 1024);
+ for (i = 0; i < fontsize; i++)
+ memcpy(buf + (32 * i), inbuf + (unit * i), unit);
+
+ { /* KDFONTOP */
+ struct console_font_op cfo;
+
+ cfo.op = KD_FONT_OP_SET;
+ cfo.flags = 0;
+ cfo.width = 8;
+ cfo.height = unit;
+ cfo.charcount = fontsize;
+ cfo.data = (void*)buf;
+#if 0
+ if (!ioctl_or_perror(fd, KDFONTOP, &cfo, "KDFONTOP ioctl failed (will try PIO_FONTX)"))
+ goto ret; /* success */
+#else
+ xioctl(fd, KDFONTOP, &cfo);
+#endif
+ }
+
+#if 0
+/* These ones do not honour -C tty (they set font on current tty regardless)
+ * On x86, this distinction is visible on framebuffer consoles
+ * (regular character consoles may have only one shared font anyway)
+ */
+#if defined(PIO_FONTX) && !defined(__sparc__)
+ {
+ struct consolefontdesc cfd;
+
+ cfd.charcount = fontsize;
+ cfd.charheight = unit;
+ cfd.chardata = buf;
+
+ if (!ioctl_or_perror(fd, PIO_FONTX, &cfd, "PIO_FONTX ioctl failed (will try PIO_FONT)"))
+ goto ret; /* success */
+ }
+#endif
+ xioctl(fd, PIO_FONT, buf);
+ ret:
+#endif /* 0 */
+ free(buf);
+}
+
+static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
+{
+ struct unimapinit advice;
+ struct unimapdesc ud;
+ struct unipair *up;
+ int ct = 0, maxct;
+ int glyph;
+ uint16_t unicode;
+
+ maxct = tailsz; /* more than enough */
+ up = xmalloc(maxct * sizeof(struct unipair));
+
+ for (glyph = 0; glyph < fontsize; glyph++) {
+ while (tailsz >= 2) {
+ unicode = (((uint16_t) inbuf[1]) << 8) + inbuf[0];
+ tailsz -= 2;
+ inbuf += 2;
+ if (unicode == PSF_SEPARATOR)
+ break;
+ up[ct].unicode = unicode;
+ up[ct].fontpos = glyph;
+ ct++;
+ }
+ }
+
+ /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
+ this printf did not work on many kernels */
+
+ advice.advised_hashsize = 0;
+ advice.advised_hashstep = 0;
+ advice.advised_hashlevel = 0;
+ xioctl(fd, PIO_UNIMAPCLR, &advice);
+ ud.entry_ct = ct;
+ ud.entries = up;
+ xioctl(fd, PIO_UNIMAP, &ud);
+}
+
+static void do_load(int fd, struct psf_header *psfhdr, size_t len)
+{
+ int unit;
+ int fontsize;
+ int hastable;
+ unsigned head0, head = head;
+
+ /* test for psf first */
+ if (len >= sizeof(struct psf_header) && PSF_MAGIC_OK(psfhdr)) {
+ if (psfhdr->mode > PSF_MAXMODE)
+ bb_error_msg_and_die("unsupported psf file mode");
+ fontsize = ((psfhdr->mode & PSF_MODE512) ? 512 : 256);
+#if !defined(PIO_FONTX) || defined(__sparc__)
+ if (fontsize != 256)
+ bb_error_msg_and_die("only fontsize 256 supported");
+#endif
+ hastable = (psfhdr->mode & PSF_MODEHASTAB);
+ unit = psfhdr->charsize;
+ head0 = sizeof(struct psf_header);
+
+ head = head0 + fontsize * unit;
+ if (head > len || (!hastable && head != len))
+ bb_error_msg_and_die("input file: bad length");
+ } else {
+ /* file with three code pages? */
+ if (len == 9780) {
+ head0 = 40;
+ unit = 16;
+ } else {
+ /* bare font */
+ if (len & 0377)
+ bb_error_msg_and_die("input file: bad length");
+ head0 = 0;
+ unit = len / 256;
+ }
+ fontsize = 256;
+ hastable = 0;
+ }
+
+ do_loadfont(fd, (unsigned char *)psfhdr + head0, unit, fontsize);
+ if (hastable)
+ do_loadtable(fd, (unsigned char *)psfhdr + head, len - head, fontsize);
+}
+
+#if ENABLE_LOADFONT
+int loadfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int loadfont_main(int argc UNUSED_PARAM, char **argv)
+{
+ size_t len;
+ struct psf_header *psfhdr;
+
+ // no arguments allowed!
+ opt_complementary = "=0";
+ getopt32(argv, "");
+
+ /*
+ * We used to look at the length of the input file
+ * with stat(); now that we accept compressed files,
+ * just read the entire file.
+ */
+ len = 32*1024; // can't be larger
+ psfhdr = xmalloc_read(STDIN_FILENO, &len);
+ // xmalloc_open_zipped_read_close(filename, &len);
+ if (!psfhdr)
+ bb_perror_msg_and_die("error reading input font");
+ do_load(get_console_fd_or_die(), psfhdr, len);
+
+ return EXIT_SUCCESS;
+}
+#endif
+
+#if ENABLE_SETFONT
+
+/*
+kbd-1.12:
+
+setfont [-O font+umap.orig] [-o font.orig] [-om cmap.orig]
+[-ou umap.orig] [-N] [font.new ...] [-m cmap] [-u umap] [-C console]
+[-hNN] [-v] [-V]
+
+-h NN Override font height
+-o file
+ Save previous font in file
+-O file
+ Save previous font and Unicode map in file
+-om file
+ Store console map in file
+-ou file
+ Save previous Unicode map in file
+-m file
+ Load console map or Unicode console map from file
+-u file
+ Load Unicode table describing the font from file
+ Example:
+ # cp866
+ 0x00-0x7f idem
+ #
+ 0x80 U+0410 # CYRILLIC CAPITAL LETTER A
+ 0x81 U+0411 # CYRILLIC CAPITAL LETTER BE
+ 0x82 U+0412 # CYRILLIC CAPITAL LETTER VE
+-C console
+ Set the font for the indicated console
+-v Verbose
+-V Version
+*/
+
+#if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
+static int ctoi(char *s)
+{
+ if (s[0] == '\'' && s[1] != '\0' && s[2] == '\'' && s[3] == '\0')
+ return s[1];
+ // U+ means 0x
+ if (s[0] == 'U' && s[1] == '+') {
+ s[0] = '0';
+ s[1] = 'x';
+ }
+ if (!isdigit(s[0]))
+ return -1;
+ return xstrtoul(s, 0);
+}
+#endif
+
+int setfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int setfont_main(int argc UNUSED_PARAM, char **argv)
+{
+ size_t len;
+ unsigned opts;
+ int fd;
+ struct psf_header *psfhdr;
+ char *mapfilename;
+ const char *tty_name = CURRENT_TTY;
+
+ opt_complementary = "=1";
+ opts = getopt32(argv, "m:C:", &mapfilename, &tty_name);
+ argv += optind;
+
+ fd = xopen(tty_name, O_NONBLOCK);
+
+ if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
+ if (*argv[0] != '/') {
+ // goto default fonts location. don't die if doesn't exist
+ chdir(CONFIG_DEFAULT_SETFONT_DIR "/consolefonts");
+ }
+ }
+ // load font
+ len = 32*1024; // can't be larger
+ psfhdr = xmalloc_open_zipped_read_close(*argv, &len);
+ if (!psfhdr)
+ bb_simple_perror_msg_and_die(*argv);
+ do_load(fd, psfhdr, len);
+
+ // load the screen map, if any
+ if (opts & 1) { // -m
+ unsigned mode = PIO_SCRNMAP;
+ void *map;
+
+ if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
+ if (mapfilename[0] != '/') {
+ // goto default keymaps location
+ chdir(CONFIG_DEFAULT_SETFONT_DIR "/consoletrans");
+ }
+ }
+ // fetch keymap
+ map = xmalloc_open_zipped_read_close(mapfilename, &len);
+ if (!map)
+ bb_simple_perror_msg_and_die(mapfilename);
+ // file size is 256 or 512 bytes? -> assume binary map
+ if (len == E_TABSZ || len == 2*E_TABSZ) {
+ if (len == 2*E_TABSZ)
+ mode = PIO_UNISCRNMAP;
+ }
+#if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
+ // assume textual Unicode console maps:
+ // 0x00 U+0000 # NULL (NUL)
+ // 0x01 U+0001 # START OF HEADING (SOH)
+ // 0x02 U+0002 # START OF TEXT (STX)
+ // 0x03 U+0003 # END OF TEXT (ETX)
+ else {
+ int i;
+ char *token[2];
+ parser_t *parser;
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(map);
+ map = xmalloc(E_TABSZ * sizeof(unsigned short));
+
+#define unicodes ((unsigned short *)map)
+ // fill vanilla map
+ for (i = 0; i < E_TABSZ; i++)
+ unicodes[i] = 0xf000 + i;
+
+ parser = config_open(mapfilename);
+ while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
+ // parse code/value pair
+ int a = ctoi(token[0]);
+ int b = ctoi(token[1]);
+ if (a < 0 || a >= E_TABSZ
+ || b < 0 || b > 65535
+ ) {
+ bb_error_msg_and_die("map format");
+ }
+ // patch map
+ unicodes[a] = b;
+ // unicode character is met?
+ if (b > 255)
+ mode = PIO_UNISCRNMAP;
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ config_close(parser);
+
+ if (mode != PIO_UNISCRNMAP) {
+#define asciis ((unsigned char *)map)
+ for (i = 0; i < E_TABSZ; i++)
+ asciis[i] = unicodes[i];
+#undef asciis
+ }
+#undef unicodes
+ }
+#endif // ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
+
+ // do set screen map
+ xioctl(fd, mode, map);
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(map);
+ }
+
+ return EXIT_SUCCESS;
+}
+#endif
diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c
new file mode 100644
index 0000000..ac2c0a6
--- /dev/null
+++ b/console-tools/loadkmap.c
@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini loadkmap implementation for busybox
+ *
+ * Copyright (C) 1998 Enrique Zanardi <ezanardi@ull.es>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+
+#define BINARY_KEYMAP_MAGIC "bkeymap"
+
+/* From <linux/kd.h> */
+struct kbentry {
+ unsigned char kb_table;
+ unsigned char kb_index;
+ unsigned short kb_value;
+};
+/* sets one entry in translation table */
+#define KDSKBENT 0x4B47
+
+/* From <linux/keyboard.h> */
+#define NR_KEYS 128
+#define MAX_NR_KEYMAPS 256
+
+int loadkmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int loadkmap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ struct kbentry ke;
+ int i, j, fd;
+ uint16_t ibuff[NR_KEYS];
+/* const char *tty_name = CURRENT_TTY; */
+ RESERVE_CONFIG_BUFFER(flags,MAX_NR_KEYMAPS);
+
+/* bb_warn_ignoring_args(argc >= 2); */
+ fd = get_console_fd_or_die();
+/* or maybe:
+ opt = getopt32(argv, "C:", &tty_name);
+ fd = xopen(tty_name, O_NONBLOCK);
+*/
+
+ xread(STDIN_FILENO, flags, 7);
+ if (strncmp(flags, BINARY_KEYMAP_MAGIC, 7))
+ bb_error_msg_and_die("not a valid binary keymap");
+
+ xread(STDIN_FILENO, flags, MAX_NR_KEYMAPS);
+
+ for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+ if (flags[i] == 1) {
+ xread(STDIN_FILENO, ibuff, NR_KEYS * sizeof(uint16_t));
+ for (j = 0; j < NR_KEYS; j++) {
+ ke.kb_index = j;
+ ke.kb_table = i;
+ ke.kb_value = ibuff[j];
+ ioctl(fd, KDSKBENT, &ke);
+ }
+ }
+ }
+
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ close(fd);
+ RELEASE_CONFIG_BUFFER(flags);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/openvt.c b/console-tools/openvt.c
new file mode 100644
index 0000000..0906de4
--- /dev/null
+++ b/console-tools/openvt.c
@@ -0,0 +1,181 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * openvt.c - open a vt to run a command.
+ *
+ * busyboxed by Quy Tonthat <quy@signal3.com>
+ * hacked by Tito <farmatito@tiscali.it>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <linux/vt.h>
+#include "libbb.h"
+
+/* "Standard" openvt's man page (we do not support all of this):
+
+openvt [-c NUM] [-fsulv] [--] [command [args]]
+
+Find the first available VT, and run command on it. Stdio is directed
+to that VT. If no command is specified then $SHELL is used.
+
+-c NUM
+ Use the given VT number, not the first free one.
+-f
+ Force opening a VT: don't try to check if VT is already in use.
+-s
+ Switch to the new VT when starting the command.
+ The VT of the new command will be made the new current VT.
+-u
+ Figure out the owner of the current VT, and run login as that user.
+ Suitable to be called by init. Shouldn't be used with -c or -l.
+-l
+ Make the command a login shell: a "-" is prepended to the argv[0]
+ when command is executed.
+-v
+ Verbose.
+-w
+ Wait for command to complete. If -w and -s are used together,
+ switch back to the controlling terminal when the command completes.
+
+bbox:
+-u: not implemented
+-f: always in effect
+-l: not implemented, ignored
+-v: ignored
+-ws: does NOT switch back
+*/
+
+/* Helper: does this fd understand VT_xxx? */
+static int not_vt_fd(int fd)
+{
+ struct vt_stat vtstat;
+ return ioctl(fd, VT_GETSTATE, &vtstat); /* !0: error, it's not VT fd */
+}
+
+/* Helper: get a fd suitable for VT_xxx */
+static int get_vt_fd(void)
+{
+ int fd;
+
+ /* Do we, by chance, already have it? */
+ for (fd = 0; fd < 3; fd++)
+ if (!not_vt_fd(fd))
+ return fd;
+ /* _only_ O_NONBLOCK: ask for neither read nor write perms */
+ /*FIXME: use? device_open(DEV_CONSOLE,0); */
+ fd = open(DEV_CONSOLE, O_NONBLOCK);
+ if (fd >= 0 && !not_vt_fd(fd))
+ return fd;
+ bb_error_msg_and_die("can't find open VT");
+}
+
+static int find_free_vtno(void)
+{
+ int vtno;
+ int fd = get_vt_fd();
+
+ errno = 0;
+ /*xfunc_error_retval = 3; - do we need compat? */
+ if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0)
+ bb_perror_msg_and_die("can't find open VT");
+// Not really needed, grep for DAEMON_ONLY_SANITIZE
+// if (fd > 2)
+// close(fd);
+ return vtno;
+}
+
+/* vfork scares gcc, it generates bigger code.
+ * Keep it away from main program.
+ * TODO: move to libbb; or adapt existing libbb's spawn().
+ */
+static NOINLINE void vfork_child(char **argv)
+{
+ if (vfork() == 0) {
+ /* CHILD */
+ /* Try to make this VT our controlling tty */
+ setsid(); /* lose old ctty */
+ ioctl(STDIN_FILENO, TIOCSCTTY, 0 /* 0: don't forcibly steal */);
+ //bb_error_msg("our sid %d", getsid(0));
+ //bb_error_msg("our pgrp %d", getpgrp());
+ //bb_error_msg("VT's sid %d", tcgetsid(0));
+ //bb_error_msg("VT's pgrp %d", tcgetpgrp(0));
+ BB_EXECVP(argv[0], argv);
+ bb_perror_msg_and_die("exec %s", argv[0]);
+ }
+}
+
+int openvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int openvt_main(int argc UNUSED_PARAM, char **argv)
+{
+ char vtname[sizeof(VC_FORMAT) + sizeof(int)*3];
+ struct vt_stat vtstat;
+ char *str_c;
+ int vtno;
+ int flags;
+ enum {
+ OPT_c = (1 << 0),
+ OPT_w = (1 << 1),
+ OPT_s = (1 << 2),
+ OPT_l = (1 << 3),
+ OPT_f = (1 << 4),
+ OPT_v = (1 << 5),
+ };
+
+ /* "+" - stop on first non-option */
+ flags = getopt32(argv, "+c:wslfv", &str_c);
+ argv += optind;
+
+ if (flags & OPT_c) {
+ /* Check for illegal vt number: < 1 or > 63 */
+ vtno = xatou_range(str_c, 1, 63);
+ } else {
+ vtno = find_free_vtno();
+ }
+
+ /* Grab new VT */
+ sprintf(vtname, VC_FORMAT, vtno);
+ /* (Try to) clean up stray open fds above fd 2 */
+ bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS | DAEMON_ONLY_SANITIZE, NULL);
+ close(STDIN_FILENO);
+ /*setsid(); - BAD IDEA: after we exit, child is SIGHUPed... */
+ xopen(vtname, O_RDWR);
+ xioctl(STDIN_FILENO, VT_GETSTATE, &vtstat);
+
+ if (flags & OPT_s) {
+ console_make_active(STDIN_FILENO, vtno);
+ }
+
+ if (!argv[0]) {
+ argv--;
+ argv[0] = getenv("SHELL");
+ if (!argv[0])
+ argv[0] = (char *) DEFAULT_SHELL;
+ /*argv[1] = NULL; - already is */
+ }
+
+ xdup2(STDIN_FILENO, STDOUT_FILENO);
+ xdup2(STDIN_FILENO, STDERR_FILENO);
+
+#ifdef BLOAT
+ {
+ /* Handle -l (login shell) option */
+ const char *prog = argv[0];
+ if (flags & OPT_l)
+ argv[0] = xasprintf("-%s", argv[0]);
+ }
+#endif
+
+ vfork_child(argv);
+ if (flags & OPT_w) {
+ /* We have only one child, wait for it */
+ safe_waitpid(-1, NULL, 0); /* loops on EINTR */
+ if (flags & OPT_s) {
+ console_make_active(STDIN_FILENO, vtstat.v_active);
+ // Compat: even with -c N (try to) disallocate:
+ // # /usr/app/kbd-1.12/bin/openvt -f -c 9 -ws sleep 5
+ // openvt: could not deallocate console 9
+ xioctl(STDIN_FILENO, VT_DISALLOCATE, (void*)(ptrdiff_t)vtno);
+ }
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/reset.c b/console-tools/reset.c
new file mode 100644
index 0000000..6917eda
--- /dev/null
+++ b/console-tools/reset.c
@@ -0,0 +1,47 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini reset implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ * Written by Erik Andersen and Kent Robotti <robotti@metconnect.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+/* BTW, which "standard" package has this utility? It doesn't seem
+ * to be ncurses, coreutils, console-tools... then what? */
+
+#if ENABLE_STTY
+int stty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+#endif
+
+int reset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ static const char *const args[] = {
+ "stty", "sane", NULL
+ };
+
+ /* no options, no getopt */
+
+ if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
+ /* See 'man 4 console_codes' for details:
+ * "ESC c" -- Reset
+ * "ESC ( K" -- Select user mapping
+ * "ESC [ J" -- Erase display
+ * "ESC [ 0 m" -- Reset all display attributes
+ * "ESC [ ? 25 h" -- Make cursor visible.
+ */
+ printf("\033c\033(K\033[J\033[0m\033[?25h");
+ /* http://bugs.busybox.net/view.php?id=1414:
+ * people want it to reset echo etc: */
+#if ENABLE_STTY
+ return stty_main(2, (char**)args);
+#else
+ execvp("stty", (char**)args);
+#endif
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/resize.c b/console-tools/resize.c
new file mode 100644
index 0000000..4504cc8
--- /dev/null
+++ b/console-tools/resize.c
@@ -0,0 +1,71 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * resize - set terminal width and height.
+ *
+ * Copyright 2006 Bernhard Reutner-Fischer
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+/* no options, no getopt */
+#include "libbb.h"
+
+#define ESC "\033"
+
+#define old_termios (*(struct termios*)&bb_common_bufsiz1)
+
+static void
+onintr(int sig UNUSED_PARAM)
+{
+ tcsetattr(STDERR_FILENO, TCSANOW, &old_termios);
+ exit(EXIT_FAILURE);
+}
+
+int resize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int resize_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ struct termios new;
+ struct winsize w = { 0, 0, 0, 0 };
+ int ret;
+
+ /* We use _stderr_ in order to make resize usable
+ * in shell backticks (those redirect stdout away from tty).
+ * NB: other versions of resize open "/dev/tty"
+ * and operate on it - should we do the same?
+ */
+
+ tcgetattr(STDERR_FILENO, &old_termios); /* fiddle echo */
+ new = old_termios;
+ new.c_cflag |= (CLOCAL | CREAD);
+ new.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ bb_signals(0
+ + (1 << SIGINT)
+ + (1 << SIGQUIT)
+ + (1 << SIGTERM)
+ + (1 << SIGALRM)
+ , onintr);
+ tcsetattr(STDERR_FILENO, TCSANOW, &new);
+
+ /* save_cursor_pos 7
+ * scroll_whole_screen [r
+ * put_cursor_waaaay_off [$x;$yH
+ * get_cursor_pos [6n
+ * restore_cursor_pos 8
+ */
+ fprintf(stderr, ESC"7" ESC"[r" ESC"[999;999H" ESC"[6n");
+ alarm(3); /* Just in case terminal won't answer */
+ scanf(ESC"[%hu;%huR", &w.ws_row, &w.ws_col);
+ fprintf(stderr, ESC"8");
+
+ /* BTW, other versions of resize recalculate w.ws_xpixel, ws.ws_ypixel
+ * by calculating character cell HxW from old values
+ * (gotten via TIOCGWINSZ) and recomputing *pixel values */
+ ret = ioctl(STDERR_FILENO, TIOCSWINSZ, &w);
+
+ tcsetattr(STDERR_FILENO, TCSANOW, &old_termios);
+
+ if (ENABLE_FEATURE_RESIZE_PRINT)
+ printf("COLUMNS=%d;LINES=%d;export COLUMNS LINES;\n",
+ w.ws_col, w.ws_row);
+
+ return ret;
+}
diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c
new file mode 100644
index 0000000..8ad9948
--- /dev/null
+++ b/console-tools/setconsole.c
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * setconsole.c - redirect system console output
+ *
+ * Copyright (C) 2004,2005 Enrik Berkhan <Enrik.Berkhan@inka.de>
+ * Copyright (C) 2008 Bernhard Reutner-Fischer
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+int setconsole_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int setconsole_main(int argc UNUSED_PARAM, char **argv)
+{
+ const char *device = CURRENT_TTY;
+ bool reset;
+
+#if ENABLE_FEATURE_SETCONSOLE_LONG_OPTIONS
+ static const char setconsole_longopts[] ALIGN1 =
+ "reset\0" No_argument "r"
+ ;
+ applet_long_options = setconsole_longopts;
+#endif
+ /* at most one non-option argument */
+ opt_complementary = "?1";
+ reset = getopt32(argv, "r");
+
+ argv += 1 + reset;
+ if (*argv) {
+ device = *argv;
+ } else {
+ if (reset)
+ device = DEV_CONSOLE;
+ }
+
+ xioctl(xopen(device, O_RDONLY), TIOCCONS, NULL);
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/setkeycodes.c b/console-tools/setkeycodes.c
new file mode 100644
index 0000000..597272a
--- /dev/null
+++ b/console-tools/setkeycodes.c
@@ -0,0 +1,49 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * setkeycodes
+ *
+ * Copyright (C) 1994-1998 Andries E. Brouwer <aeb@cwi.nl>
+ *
+ * Adjusted for BusyBox by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+//#include <sys/ioctl.h>
+#include "libbb.h"
+
+/* From <linux/kd.h> */
+struct kbkeycode {
+ unsigned scancode, keycode;
+};
+enum {
+ KDSETKEYCODE = 0x4B4D /* write kernel keycode table entry */
+};
+
+int setkeycodes_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int setkeycodes_main(int argc, char **argv)
+{
+ int fd, sc;
+ struct kbkeycode a;
+
+ if (!(argc & 1) /* if even */ || argc < 2) {
+ bb_show_usage();
+ }
+
+ fd = get_console_fd_or_die();
+
+ while (argc > 2) {
+ a.keycode = xatou_range(argv[2], 0, 127);
+ a.scancode = sc = xstrtoul_range(argv[1], 16, 0, 255);
+ if (a.scancode > 127) {
+ a.scancode -= 0xe000;
+ a.scancode += 128;
+ }
+ ioctl_or_perror_and_die(fd, KDSETKEYCODE, &a,
+ "can't set SCANCODE %x to KEYCODE %d",
+ sc, a.keycode);
+ argc -= 2;
+ argv += 2;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/setlogcons.c b/console-tools/setlogcons.c
new file mode 100644
index 0000000..dd44591
--- /dev/null
+++ b/console-tools/setlogcons.c
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * setlogcons: Send kernel messages to the current console or to console N
+ *
+ * Copyright (C) 2006 by Jan Kiszka <jan.kiszka@web.de>
+ *
+ * Based on setlogcons (kbd-1.12) by Andries E. Brouwer
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+int setlogcons_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int setlogcons_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct {
+ char fn;
+ char subarg;
+ } arg = { 11, /* redirect kernel messages */
+ 0 /* to specified console (current as default) */
+ };
+
+ if (argv[1])
+ arg.subarg = xatou_range(argv[1], 0, 63);
+
+ xioctl(xopen(VC_1, O_RDONLY), TIOCLINUX, &arg);
+
+ return EXIT_SUCCESS;
+}
diff --git a/console-tools/showkey.c b/console-tools/showkey.c
new file mode 100644
index 0000000..681114d
--- /dev/null
+++ b/console-tools/showkey.c
@@ -0,0 +1,138 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * shows keys pressed. inspired by kbd package
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include <linux/kd.h>
+
+// set raw tty mode
+// also used by microcom
+// libbb candidates?
+static void xget1(int fd, struct termios *t, struct termios *oldt)
+{
+ tcgetattr(fd, oldt);
+ *t = *oldt;
+ cfmakeraw(t);
+}
+
+static int xset1(int fd, struct termios *tio, const char *device)
+{
+ int ret = tcsetattr(fd, TCSAFLUSH, tio);
+
+ if (ret) {
+ bb_perror_msg("can't tcsetattr for %s", device);
+ }
+ return ret;
+}
+
+/*
+ * 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(STDIN_FILENO, &tio0, "stdin");
+ 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
+ };
+
+ // 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(STDIN_FILENO, &tio, &tio0);
+ // put stdin in raw mode
+ xset1(STDIN_FILENO, &tio, "stdin");
+
+ if (option_mask32 & OPT_a) {
+ char c;
+ // just read stdin char by char
+ while (1 == safe_read(STDIN_FILENO, &c, 1)) {
+ printf("%3d 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);
+ // set raw keyboard mode
+ xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW));
+
+ // read and show scancodes
+ while (1) {
+ 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) {
+ printf("0x%02x ", buf[i++]);
+ // show interpreted scancodes (default) ? ->
+ } else {
+ int kc;
+ if (i+2 < n && (c & 0x7f) == 0
+ && (buf[i+1] & 0x80) != 0
+ && (buf[i+2] & 0x80) != 0) {
+ kc = ((buf[i+1] & 0x7f) << 7) | (buf[i+2] & 0x7f);
+ i += 3;
+ } else {
+ kc = (c & 0x7f);
+ i++;
+ }
+ printf("keycode %3d %s", kc, (c & 0x80) ? "release" : "press");
+ }
+ }
+ puts("\r");
+ }
+ }
+
+ // cleanup
+ signal_handler(SIGALRM);
+
+ // should never be here!
+ return EXIT_SUCCESS;
+}