diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2015-01-03 13:58:15 +0100 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2015-01-03 13:58:15 +0100 |
commit | 4aca87515a5083ae0e31ce3177189fd43b6d05ac (patch) | |
tree | 7b1d9a31393ca090757dc6f0d3859b4fcd93f271 /release/src/router/busybox/console-tools | |
parent | 008d0be72b2f160382c6e880765e96b64a050c65 (diff) | |
download | tomato-4aca87515a5083ae0e31ce3177189fd43b6d05ac.tar.gz tomato-4aca87515a5083ae0e31ce3177189fd43b6d05ac.tar.bz2 |
patch to Vanilla Tomato 1.28
Diffstat (limited to 'release/src/router/busybox/console-tools')
19 files changed, 1034 insertions, 899 deletions
diff --git a/release/src/router/busybox/console-tools/Config.in b/release/src/router/busybox/console-tools/Config.in index 83694a82..994140b7 100755..100644 --- a/release/src/router/busybox/console-tools/Config.in +++ b/release/src/router/busybox/console-tools/Config.in @@ -5,70 +5,134 @@ menu "Console Utilities" -config CONFIG_CHVT +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 CONFIG_CLEAR +config CLEAR bool "clear" default n help This program clears the terminal screen. -config CONFIG_DEALLOCVT +config DEALLOCVT bool "deallocvt" default n help This program deallocates unused virtual consoles. -config CONFIG_DUMPKMAP +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 CONFIG_LOADACM - bool "loadacm" +config KBD_MODE + bool "kbd_mode" default n help - This program loads an acm from standard input. + This program reports and sets keyboard mode. -config CONFIG_LOADFONT +config LOADFONT bool "loadfont" default n help This program loads a console font from standard input. -config CONFIG_LOADKMAP +config LOADKMAP bool "loadkmap" default n help This program loads a keyboard translation table from standard input. -config CONFIG_OPENVT +config OPENVT bool "openvt" default n help This program is used to start a command on an unused virtual terminal. -config CONFIG_RESET +config RESET bool "reset" default n help This program is used to reset the terminal screen, if it gets messed up. -config CONFIG_SETKEYCODES +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/release/src/router/busybox/console-tools/Kbuild b/release/src/router/busybox/console-tools/Kbuild new file mode 100644 index 00000000..df5ffdb9 --- /dev/null +++ b/release/src/router/busybox/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/release/src/router/busybox/console-tools/Makefile b/release/src/router/busybox/console-tools/Makefile deleted file mode 100644 index d54c778d..00000000 --- a/release/src/router/busybox/console-tools/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -TOPDIR:= ../ -CONSOLETOOLS_DIR:=./ -include $(TOPDIR).config -include $(TOPDIR)Rules.mak -include Makefile.in -all: $(libraries-y) --include $(TOPDIR).depend - -clean: - rm -f *.o *.a $(AR_TARGET) - diff --git a/release/src/router/busybox/console-tools/Makefile.in b/release/src/router/busybox/console-tools/Makefile.in deleted file mode 100755 index 1c4ac522..00000000 --- a/release/src/router/busybox/console-tools/Makefile.in +++ /dev/null @@ -1,41 +0,0 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -CONSOLETOOLS_AR:=console-tools.a -ifndef $(CONSOLETOOLS_DIR) -CONSOLETOOLS_DIR:=$(TOPDIR)console-tools/ -endif - -CONSOLETOOLS_DIR-y:= -CONSOLETOOLS_DIR-$(CONFIG_CHVT) += chvt.o -CONSOLETOOLS_DIR-$(CONFIG_CLEAR) += clear.o -CONSOLETOOLS_DIR-$(CONFIG_DEALLOCVT) += deallocvt.o -CONSOLETOOLS_DIR-$(CONFIG_DUMPKMAP) += dumpkmap.o -CONSOLETOOLS_DIR-$(CONFIG_LOADACM) += loadacm.o -CONSOLETOOLS_DIR-$(CONFIG_LOADFONT) += loadfont.o -CONSOLETOOLS_DIR-$(CONFIG_LOADKMAP) += loadkmap.o -CONSOLETOOLS_DIR-$(CONFIG_OPENVT) += openvt.o -CONSOLETOOLS_DIR-$(CONFIG_RESET) += reset.o -CONSOLETOOLS_DIR-$(CONFIG_SETKEYCODES) += setkeycodes.o - -libraries-y+=$(CONSOLETOOLS_DIR)$(CONSOLETOOLS_AR) - -$(CONSOLETOOLS_DIR)$(CONSOLETOOLS_AR): $(patsubst %,$(CONSOLETOOLS_DIR)%, $(CONSOLETOOLS_DIR-y)) - $(AR) -ro $@ $(patsubst %,$(CONSOLETOOLS_DIR)%, $(CONSOLETOOLS_DIR-y)) - diff --git a/release/src/router/busybox/console-tools/chvt.c b/release/src/router/busybox/console-tools/chvt.c index 11e1078b..302ffb4f 100644 --- a/release/src/router/busybox/console-tools/chvt.c +++ b/release/src/router/busybox/console-tools/chvt.c @@ -1,43 +1,24 @@ /* vi: set sw=4 ts=4: */ /* - * chvt.c - aeb - 940227 - Change virtual terminal + * Mini chvt implementation for busybox * - * busyboxed by Erik Andersen + * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -/* getopt not needed */ - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include "busybox.h" - -/* From <linux/vt.h> */ -static const int VT_ACTIVATE = 0x5606; /* make vt active */ -static const int VT_WAITACTIVE = 0x5607; /* wait for vt active */ +#include "libbb.h" +int chvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int chvt_main(int argc, char **argv) { - int fd, num; + int num; - if ((argc != 2) || (**(argv + 1) == '-')) + if (argc != 2) { bb_show_usage(); - fd = get_console_fd(); - num = atoi(argv[1]); - if (ioctl(fd, VT_ACTIVATE, num)) - bb_perror_msg_and_die("VT_ACTIVATE"); - if (ioctl(fd, VT_WAITACTIVE, num)) - bb_perror_msg_and_die("VT_WAITACTIVE"); + } + + num = xatou_range(argv[1], 1, 63); + console_make_active(get_console_fd_or_die(), num); return EXIT_SUCCESS; } - - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/release/src/router/busybox/console-tools/clear.c b/release/src/router/busybox/console-tools/clear.c index 5dbe214e..8b727b39 100644 --- a/release/src/router/busybox/console-tools/clear.c +++ b/release/src/router/busybox/console-tools/clear.c @@ -2,31 +2,18 @@ /* * Mini clear implementation for busybox * - * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * */ -#include <stdio.h> -#include <stdlib.h> -#include "busybox.h" +/* no options, no getopt */ +#include "libbb.h" -extern int clear_main(int argc, char **argv) +int clear_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { - printf("\033[H\033[J"); - return EXIT_SUCCESS; + return printf("\033[H\033[J") != 6; } diff --git a/release/src/router/busybox/console-tools/deallocvt.c b/release/src/router/busybox/console-tools/deallocvt.c index f641be8d..09748834 100644 --- a/release/src/router/busybox/console-tools/deallocvt.c +++ b/release/src/router/busybox/console-tools/deallocvt.c @@ -1,46 +1,33 @@ /* vi: set sw=4 ts=4: */ /* - * disalloc.c - aeb - 940501 - Disallocate virtual terminal(s) - * Renamed deallocvt. + * 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. */ -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include "busybox.h" -/* From <linux/vt.h> */ -static const int VT_DISALLOCATE = 0x5608; /* free memory associated to vt */ - -int deallocvt_main(int argc, char *argv[]) -{ - int fd, num=0; +/* no options, no getopt */ - if (argc > 2) - bb_show_usage(); +#include "libbb.h" - fd = get_console_fd(); - - /* num=0 deallocate all unused consoles */ - if (argc == 1) - goto disallocate_all; +/* From <linux/vt.h> */ +enum { VT_DISALLOCATE = 0x5608 }; /* free memory associated to vt */ - num=bb_xgetlarg(argv[1], 10, 0, INT_MAX); +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; - switch(num) - { - case 0: - bb_error_msg("0: illegal VT number"); - break; - case 1: - bb_error_msg("VT 1 cannot be deallocated"); - break; - default: -disallocate_all: - if (ioctl(fd, VT_DISALLOCATE, num)) - bb_perror_msg_and_die("VT_DISALLOCATE"); - return EXIT_SUCCESS; + if (argv[1]) { + if (argv[2]) + bb_show_usage(); + num = xatou_range(argv[1], 1, 63); } - return EXIT_FAILURE; + + /* 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/release/src/router/busybox/console-tools/dumpkmap.c b/release/src/router/busybox/console-tools/dumpkmap.c index 85926556..c382b5af 100644 --- a/release/src/router/busybox/console-tools/dumpkmap.c +++ b/release/src/router/busybox/console-tools/dumpkmap.c @@ -4,30 +4,12 @@ * * Copyright (C) Arne Bernin <arne@matrix.loopback.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * */ +/* no options, no getopt */ -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include "busybox.h" +#include "libbb.h" /* From <linux/kd.h> */ struct kbentry { @@ -35,61 +17,53 @@ struct kbentry { unsigned char kb_index; unsigned short kb_value; }; -static const int KDGKBENT = 0x4B46; /* gets one entry in translation table */ +#define KDGKBENT 0x4B46 /* gets one entry in translation table */ /* From <linux/keyboard.h> */ -static const int NR_KEYS = 128; -static const int MAX_NR_KEYMAPS = 256; +#define NR_KEYS 128 +#define MAX_NR_KEYMAPS 256 -int dumpkmap_main(int argc, char **argv) +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; - char flags[MAX_NR_KEYMAPS], magic[] = "bkeymap"; + RESERVE_CONFIG_BUFFER(flags,MAX_NR_KEYMAPS); - if (argc>=2 && *argv[1]=='-') { - bb_show_usage(); - } +/* bb_warn_ignoring_args(argc>=2);*/ - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) { - bb_perror_msg("Error opening " CURRENT_VC); - return EXIT_FAILURE; - } + fd = get_console_fd_or_die(); + + write(STDOUT_FILENO, "bkeymap", 7); - write(1, magic, 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; - for (i=0; i < MAX_NR_KEYMAPS; i++) flags[i]=0; - flags[0]=1; - flags[1]=1; - flags[2]=1; - flags[4]=1; - flags[5]=1; - flags[6]=1; - flags[8]=1; - flags[9]=1; - flags[10]=1; - flags[12]=1; - /* dump flags */ - for (i=0; i < MAX_NR_KEYMAPS; i++) write(1,&flags[i],1); + 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(fd, KDGKBENT, &ke) < 0) { - - bb_error_msg("ioctl returned: %m, %s, %s, %xqq", (char *)&ke.kb_index,(char *)&ke.kb_table,(int)&ke.kb_value); - } - else { - write(1,(void*)&ke.kb_value,2); - } - + 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); + } } } } - close(fd); + if (ENABLE_FEATURE_CLEAN_UP) { + close(fd); + RELEASE_CONFIG_BUFFER(flags); + } return EXIT_SUCCESS; } diff --git a/release/src/router/busybox/console-tools/kbd_mode.c b/release/src/router/busybox/console-tools/kbd_mode.c new file mode 100644 index 00000000..544bbb78 --- /dev/null +++ b/release/src/router/busybox/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/release/src/router/busybox/console-tools/loadacm.c b/release/src/router/busybox/console-tools/loadacm.c deleted file mode 100644 index 640aa440..00000000 --- a/release/src/router/busybox/console-tools/loadacm.c +++ /dev/null @@ -1,357 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Derived from - * mapscrn.c - version 0.92 - * - * Was taken from console-tools and adapted by - * Peter Novodvorsky <petya@logic.ru> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <memory.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <sys/kd.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include "busybox.h" - -typedef unsigned short unicode; - -static long int ctoi(unsigned char *s, int *is_unicode); -static int old_screen_map_read_ascii(FILE * fp, unsigned char buf[]); -static int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode); -static unicode utf8_to_ucs2(char *buf); -static int screen_map_load(int fd, FILE * fp); - -int loadacm_main(int argc, char **argv) -{ - int fd; - - if (argc>=2 && *argv[1]=='-') { - bb_show_usage(); - } - - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) { - bb_perror_msg_and_die("Error opening " CURRENT_VC); - } - - if (screen_map_load(fd, stdin)) { - bb_perror_msg_and_die("Error loading acm"); - } - - write(fd, "\033(K", 3); - - return EXIT_SUCCESS; -} - -static int screen_map_load(int fd, FILE * fp) -{ - struct stat stbuf; - unicode wbuf[E_TABSZ]; - unsigned char buf[E_TABSZ]; - int parse_failed = 0; - int is_unicode; - - if (fstat(fileno(fp), &stbuf)) - bb_perror_msg_and_die("Cannot stat map file"); - - /* first try a UTF screen-map: either ASCII (no restriction) or binary (regular file) */ - if (! - (parse_failed = - (-1 == uni_screen_map_read_ascii(fp, wbuf, &is_unicode))) -|| (S_ISREG(stbuf.st_mode) && (stbuf.st_size == (sizeof(unicode) * E_TABSZ)))) { /* test for binary UTF map by size */ - if (parse_failed) { - if (-1 == fseek(fp, 0, SEEK_SET)) { - if (errno == ESPIPE) - bb_error_msg_and_die("16bit screen-map MUST be a regular file."); - else - bb_perror_msg_and_die("fseek failed reading binary 16bit screen-map"); - } - - if (fread(wbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1) - bb_perror_msg_and_die("Cannot read [new] map from file"); -#if 0 - else - bb_error_msg("Input screen-map is binary."); -#endif - } - - /* if it was effectively a 16-bit ASCII, OK, else try to read as 8-bit map */ - /* same if it was binary, ie. if parse_failed */ - if (parse_failed || is_unicode) { - if (ioctl(fd, PIO_UNISCRNMAP, wbuf)) - bb_perror_msg_and_die("PIO_UNISCRNMAP ioctl"); - else - return 0; - } - } - - /* rewind... */ - if (-1 == fseek(fp, 0, SEEK_SET)) { - if (errno == ESPIPE) - bb_error_msg("Assuming 8bit screen-map - MUST be a regular file."), - exit(1); - else - bb_perror_msg_and_die("fseek failed assuming 8bit screen-map"); - } - - /* ... and try an old 8-bit screen-map */ - if (!(parse_failed = (-1 == old_screen_map_read_ascii(fp, buf))) || - (S_ISREG(stbuf.st_mode) && (stbuf.st_size == E_TABSZ))) { /* test for binary old 8-bit map by size */ - if (parse_failed) { - if (-1 == fseek(fp, 0, SEEK_SET)) { - if (errno == ESPIPE) - /* should not - it succedeed above */ - bb_error_msg_and_die("fseek() returned ESPIPE !"); - else - bb_perror_msg_and_die("fseek for binary 8bit screen-map"); - } - - if (fread(buf, E_TABSZ, 1, fp) != 1) - bb_perror_msg_and_die("Cannot read [old] map from file"); -#if 0 - else - bb_error_msg("Input screen-map is binary."); -#endif - } - - if (ioctl(fd, PIO_SCRNMAP, buf)) - bb_perror_msg_and_die("PIO_SCRNMAP ioctl"); - else - return 0; - } - bb_error_msg("Error parsing symbolic map"); - return(1); -} - - -/* - * - reads `fp' as a 16-bit ASCII SFM file. - * - returns -1 on error. - * - returns it in `unicode' in an E_TABSZ-elements array. - * - sets `*is_unicode' flagiff there were any non-8-bit - * (ie. real 16-bit) mapping. - * - * FIXME: ignores everything after second word - */ -static int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode) -{ - char buffer[256]; /* line buffer reading file */ - char *p, *q; /* 1st + 2nd words in line */ - int in, on; /* the same, as numbers */ - int tmp_is_unicode; /* tmp for is_unicode calculation */ - int i; /* loop index - result holder */ - int ret_code = 0; /* return code */ - sigset_t acmsigset, old_sigset; - - assert(is_unicode); - - *is_unicode = 0; - - /* first 128 codes defaults to ASCII */ - for (i = 0; i < 128; i++) - buf[i] = i; - /* remaining defaults to replacement char (usually E_TABSZ = 256) */ - for (; i < E_TABSZ; i++) - buf[i] = 0xfffd; - - /* block SIGCHLD */ - sigemptyset(&acmsigset); - sigaddset(&acmsigset, SIGCHLD); - sigprocmask(SIG_BLOCK, &acmsigset, &old_sigset); - - do { - if (NULL == fgets(buffer, sizeof(buffer), fp)) { - if (feof(fp)) - break; - else - bb_perror_msg_and_die("uni_screen_map_read_ascii() can't read line"); - } - - /* get "charset-relative charcode", stripping leading spaces */ - p = strtok(buffer, " \t\n"); - - /* skip empty lines and comments */ - if (!p || *p == '#') - continue; - - /* get unicode mapping */ - q = strtok(NULL, " \t\n"); - if (q) { - in = ctoi(p, NULL); - if (in < 0 || in > 255) { - ret_code = -1; - break; - } - - on = ctoi(q, &tmp_is_unicode); - if (in < 0 && on > 65535) { - ret_code = -1; - break; - } - - *is_unicode |= tmp_is_unicode; - buf[in] = on; - } else { - ret_code = -1; - break; - } - } - while (1); /* terminated by break on feof() */ - - /* restore sig mask */ - sigprocmask(SIG_SETMASK, &old_sigset, NULL); - - return ret_code; -} - - -static int old_screen_map_read_ascii(FILE * fp, unsigned char buf[]) -{ - char buffer[256]; - int in, on; - char *p, *q; - - for (in = 0; in < 256; in++) - buf[in] = in; - - while (fgets(buffer, sizeof(buffer) - 1, fp)) { - p = strtok(buffer, " \t\n"); - - if (!p || *p == '#') - continue; - - q = strtok(NULL, " \t\n#"); - if (q) { - in = ctoi(p, NULL); - if (in < 0 || in > 255) - return -1; - - on = ctoi(q, NULL); - if (in < 0 && on > 255) - return -1; - - buf[in] = on; - } else - return -1; - } - - return (0); -} - - -/* - * - converts a string into an int. - * - supports dec and hex bytes, hex UCS2, single-quoted byte and UTF8 chars. - * - returns the converted value - * - if `is_unicode != NULL', use it to tell whether it was unicode - * - * CAVEAT: will report valid UTF mappings using only 1 byte as 8-bit ones. - */ -static long int ctoi(unsigned char *s, int *is_unicode) -{ - int i; - size_t ls; - - ls = strlen(s); - if (is_unicode) - *is_unicode = 0; - - /* hex-specified UCS2 */ - if ((strncmp(s, "U+", 2) == 0) && - (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2)) { - sscanf(s + 2, "%x", &i); - if (is_unicode) - *is_unicode = 1; - } - - /* hex-specified byte */ - else if ((ls <= 4) && (strncmp(s, "0x", 2) == 0) && - (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2)) - sscanf(s + 2, "%x", &i); - - /* oct-specified number (byte) */ - else if ((*s == '0') && (strspn(s, "01234567") == ls)) - sscanf(s, "%o", &i); - - /* dec-specified number (byte) */ - else if (strspn(s, "0123456789") == ls) - sscanf(s, "%d", &i); - - /* single-byte quoted char */ - else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\'')) - i = s[1]; - - /* multi-byte UTF8 quoted char */ - else if ((s[0] == '\'') && (s[ls - 1] == '\'')) { - s[ls - 1] = 0; /* ensure we'll not "parse UTF too far" */ - i = utf8_to_ucs2(s + 1); - if (is_unicode) - *is_unicode = 1; - } else - return (-1); - - return (i); -} - - -static unicode utf8_to_ucs2(char *buf) -{ - int utf_count = 0; - long utf_char = 0; - unicode tc = 0; - unsigned char c; - - do { - c = *buf; - buf++; - - /* if byte should be part of multi-byte sequence */ - if (c & 0x80) { - /* if we have already started to parse a UTF8 sequence */ - if (utf_count > 0 && (c & 0xc0) == 0x80) { - utf_char = (utf_char << 6) | (c & 0x3f); - utf_count--; - if (utf_count == 0) - tc = utf_char; - else - continue; - } else { /* Possibly 1st char of a UTF8 sequence */ - - if ((c & 0xe0) == 0xc0) { - utf_count = 1; - utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - utf_count = 2; - utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - utf_count = 3; - utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - utf_count = 4; - utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - utf_count = 5; - utf_char = (c & 0x01); - } else - utf_count = 0; - continue; - } - } else { /* not part of multi-byte sequence - treat as ASCII - * this makes incomplete sequences to be ignored - */ - tc = c; - utf_count = 0; - } - } - while (utf_count); - - return tc; -} diff --git a/release/src/router/busybox/console-tools/loadfont.c b/release/src/router/busybox/console-tools/loadfont.c index 6108151a..33641806 100644 --- a/release/src/router/busybox/console-tools/loadfont.c +++ b/release/src/router/busybox/console-tools/loadfont.c @@ -6,68 +6,87 @@ * * Loads the console font, and possibly the corresponding screen map(s). * (Adapted for busybox by Matej Vela.) + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. */ -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <memory.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <dirent.h> -#include <errno.h> -#include <sys/ioctl.h> +#include "libbb.h" #include <sys/kd.h> -#include <endian.h> -#include "busybox.h" - -static const int PSF_MAGIC1 = 0x36; -static const int PSF_MAGIC2 = 0x04; - -static const int PSF_MODE512 = 0x01; -static const int PSF_MODEHASTAB = 0x02; -static const int PSF_MAXMODE = 0x03; -static const int PSF_SEPARATOR = 0xFFFF; -struct psf_header { - unsigned char magic1, magic2; /* Magic number */ - unsigned char mode; /* PSF font mode */ - unsigned char charsize; /* Character size */ +#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 PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) +#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 */ -static void loadnewfont(int fd); +#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 */ -extern int loadfont_main(int argc, char **argv) -{ - int fd; - if (argc != 1) - bb_show_usage(); +enum { + PSF_MAGIC1 = 0x36, + PSF_MAGIC2 = 0x04, - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) - bb_perror_msg_and_die("Error opening " CURRENT_VC); - loadnewfont(fd); + PSF_MODE512 = 0x01, + PSF_MODEHASTAB = 0x02, + PSF_MAXMODE = 0x03, + PSF_SEPARATOR = 0xffff +}; - return EXIT_SUCCESS; -} +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, char *inbuf, int unit, int fontsize) +static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize) { - char buf[16384]; + char *buf; int i; - memset(buf, 0, sizeof(buf)); - if (unit < 1 || unit > 32) - bb_error_msg_and_die("Bad character size %d", unit); + 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); -#if defined( PIO_FONTX ) && !defined( __sparc__ ) + { /* 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; @@ -75,31 +94,31 @@ static void do_loadfont(int fd, char *inbuf, int unit, int fontsize) cfd.charheight = unit; cfd.chardata = buf; - if (ioctl(fd, PIO_FONTX, &cfd) == 0) - return; /* success */ - bb_perror_msg("PIO_FONTX ioctl error (trying PIO_FONT)"); + if (!ioctl_or_perror(fd, PIO_FONTX, &cfd, "PIO_FONTX ioctl failed (will try PIO_FONT)")) + goto ret; /* success */ } #endif - if (ioctl(fd, PIO_FONT, buf)) - bb_perror_msg_and_die("PIO_FONT ioctl error"); + xioctl(fd, PIO_FONT, buf); + ret: +#endif /* 0 */ + free(buf); } -static void -do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) +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; - u_short unicode; + uint16_t unicode; - maxct = tailsz; /* more than enough */ - up = (struct unipair *) xmalloc(maxct * sizeof(struct unipair)); + maxct = tailsz; /* more than enough */ + up = xmalloc(maxct * sizeof(struct unipair)); for (glyph = 0; glyph < fontsize; glyph++) { while (tailsz >= 2) { - unicode = (((u_short) inbuf[1]) << 8) + inbuf[0]; + unicode = (((uint16_t) inbuf[1]) << 8) + inbuf[0]; tailsz -= 2; inbuf += 2; if (unicode == PSF_SEPARATOR) @@ -116,94 +135,239 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) advice.advised_hashsize = 0; advice.advised_hashstep = 0; advice.advised_hashlevel = 0; - if (ioctl(fd, PIO_UNIMAPCLR, &advice)) { -#ifdef ENOIOCTLCMD - if (errno == ENOIOCTLCMD) { - bb_error_msg("It seems this kernel is older than 1.1.92"); - bb_error_msg_and_die("No Unicode mapping table loaded."); - } else -#endif - bb_perror_msg_and_die("PIO_UNIMAPCLR"); - } + xioctl(fd, PIO_UNIMAPCLR, &advice); ud.entry_ct = ct; ud.entries = up; - if (ioctl(fd, PIO_UNIMAP, &ud)) { -#if 0 - if (errno == ENOMEM) { - /* change advice parameters */ - } + 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 - bb_perror_msg_and_die("PIO_UNIMAP"); + 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); } -static void loadnewfont(int fd) +#if ENABLE_LOADFONT +int loadfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int loadfont_main(int argc UNUSED_PARAM, char **argv) { - int unit; - char inbuf[32768]; /* primitive */ - unsigned int inputlth, offset; + 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. */ - inputlth = fread(inbuf, 1, sizeof(inbuf), stdin); - if (ferror(stdin)) - bb_perror_msg_and_die("Error reading input font"); - /* use malloc/realloc in case of giant files; - maybe these do not occur: 16kB for the font, - and 16kB for the map leaves 32 unicode values - for each font position */ - if (!feof(stdin)) - bb_perror_msg_and_die("Font too large"); + 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); - /* test for psf first */ - { - struct psf_header psfhdr; - int fontsize; - int hastable; - unsigned int head0, head; + return EXIT_SUCCESS; +} +#endif + +#if ENABLE_SETFONT - if (inputlth < sizeof(struct psf_header)) - goto no_psf; +/* +kbd-1.12: - psfhdr = *(struct psf_header *) &inbuf[0]; +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] - if (!PSF_MAGIC_OK(psfhdr)) - goto no_psf; +-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 (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"); +#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 - hastable = (psfhdr.mode & PSF_MODEHASTAB); - unit = psfhdr.charsize; - head0 = sizeof(struct psf_header); - head = head0 + fontsize * unit; - if (head > inputlth || (!hastable && head != inputlth)) - bb_error_msg_and_die("Input file: bad length"); - do_loadfont(fd, inbuf + head0, unit, fontsize); - if (hastable) - do_loadtable(fd, inbuf + head, inputlth - head, fontsize); - return; +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"); + } } - no_psf: + // 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); - /* file with three code pages? */ - if (inputlth == 9780) { - offset = 40; - unit = 16; - } else { - /* bare font */ - if (inputlth & 0377) - bb_error_msg_and_die("Bad input file size"); - offset = 0; - unit = inputlth / 256; + // 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); } - do_loadfont(fd, inbuf + offset, unit, 256); + + return EXIT_SUCCESS; } +#endif diff --git a/release/src/router/busybox/console-tools/loadkmap.c b/release/src/router/busybox/console-tools/loadkmap.c index f4208df6..ac2c0a6e 100644 --- a/release/src/router/busybox/console-tools/loadkmap.c +++ b/release/src/router/busybox/console-tools/loadkmap.c @@ -4,30 +4,9 @@ * * Copyright (C) 1998 Enrique Zanardi <ezanardi@ull.es> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include "busybox.h" +#include "libbb.h" #define BINARY_KEYMAP_MAGIC "bkeymap" @@ -37,43 +16,38 @@ struct kbentry { unsigned char kb_index; unsigned short kb_value; }; -static const int KDSKBENT = 0x4B47; /* sets one entry in translation table */ +/* sets one entry in translation table */ +#define KDSKBENT 0x4B47 /* From <linux/keyboard.h> */ -static const int NR_KEYS = 128; -static const int MAX_NR_KEYMAPS = 256; +#define NR_KEYS 128 +#define MAX_NR_KEYMAPS 256 -int loadkmap_main(int argc, char **argv) +int loadkmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int loadkmap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { struct kbentry ke; - u_short *ibuff; - int i, j, fd, readsz, pos, ibuffsz = NR_KEYS * sizeof(u_short); - char flags[MAX_NR_KEYMAPS], buff[7]; - - if (argc != 1) - bb_show_usage(); + int i, j, fd; + uint16_t ibuff[NR_KEYS]; +/* const char *tty_name = CURRENT_TTY; */ + RESERVE_CONFIG_BUFFER(flags,MAX_NR_KEYMAPS); - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) - bb_perror_msg_and_die("Error opening " CURRENT_VC); +/* 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); +*/ - read(0, buff, 7); - if (0 != strncmp(buff, BINARY_KEYMAP_MAGIC, 7)) - bb_error_msg_and_die("This is not a valid binary keymap."); + xread(STDIN_FILENO, flags, 7); + if (strncmp(flags, BINARY_KEYMAP_MAGIC, 7)) + bb_error_msg_and_die("not a valid binary keymap"); - if (MAX_NR_KEYMAPS != read(0, flags, MAX_NR_KEYMAPS)) - bb_perror_msg_and_die("Error reading keymap flags"); - - ibuff = (u_short *) xmalloc(ibuffsz); + xread(STDIN_FILENO, flags, MAX_NR_KEYMAPS); for (i = 0; i < MAX_NR_KEYMAPS; i++) { if (flags[i] == 1) { - pos = 0; - while (pos < ibuffsz) { - if ((readsz = read(0, (char *) ibuff + pos, ibuffsz - pos)) < 0) - bb_perror_msg_and_die("Error reading keymap"); - pos += readsz; - } + xread(STDIN_FILENO, ibuff, NR_KEYS * sizeof(uint16_t)); for (j = 0; j < NR_KEYS; j++) { ke.kb_index = j; ke.kb_table = i; @@ -82,8 +56,10 @@ int loadkmap_main(int argc, char **argv) } } } - /* Don't bother to close files. Exit does that - * automagically, so we can save a few bytes */ - /* close(fd); */ + + if (ENABLE_FEATURE_CLEAN_UP) { + close(fd); + RELEASE_CONFIG_BUFFER(flags); + } return EXIT_SUCCESS; } diff --git a/release/src/router/busybox/console-tools/openvt.c b/release/src/router/busybox/console-tools/openvt.c index 269dfc01..0906de46 100644 --- a/release/src/router/busybox/console-tools/openvt.c +++ b/release/src/router/busybox/console-tools/openvt.c @@ -5,93 +5,177 @@ * busyboxed by Quy Tonthat <quy@signal3.com> * hacked by Tito <farmatito@tiscali.it> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -/* getopt not needed */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <ctype.h> - -#include "busybox.h" +#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 +*/ -#define VTNAME "/dev/tty%d" +/* 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 */ +} -int openvt_main(int argc, char **argv) +/* Helper: get a fd suitable for VT_xxx */ +static int get_vt_fd(void) { - int pid; int fd; - int vtno; - char vtname[sizeof VTNAME + 2]; + /* 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"); +} - if (argc < 3) - bb_show_usage(); - - if (!isdigit(argv[1][0])) - bb_show_usage(); +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; +} - vtno = (int) atol(argv[1]); +/* 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]); + } +} - /* if (vtno <= 0 || vtno > 63) */ - if (vtno <= 0 || vtno > 12) - bb_error_msg_and_die("Illegal vt number (%d)", vtno); +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(); + } - sprintf(vtname, VTNAME, 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); + } - argv+=2; - argc-=2; + if (!argv[0]) { + argv--; + argv[0] = getenv("SHELL"); + if (!argv[0]) + argv[0] = (char *) DEFAULT_SHELL; + /*argv[1] = NULL; - already is */ + } - if((pid = fork()) == 0) { - /* leave current vt */ + xdup2(STDIN_FILENO, STDOUT_FILENO); + xdup2(STDIN_FILENO, STDERR_FILENO); -#ifdef ESIX_5_3_2_D - if (setpgrp() < 0) { -#else - if (setsid() < 0) { +#ifdef BLOAT + { + /* Handle -l (login shell) option */ + const char *prog = argv[0]; + if (flags & OPT_l) + argv[0] = xasprintf("-%s", argv[0]); + } #endif - bb_perror_msg_and_die("Unable to set new session"); + 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); } - close(0); /* so that new vt becomes stdin */ - - /* and grab new one */ - if ((fd = open(vtname, O_RDWR)) == -1) - bb_perror_msg_and_die("could not open %s", vtname); - - /* Reassign stdout and sterr */ - close(1); - close(2); - dup(fd); - dup(fd); - - execvp(argv[0], argv); - _exit(1); } return EXIT_SUCCESS; } - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/release/src/router/busybox/console-tools/reset.c b/release/src/router/busybox/console-tools/reset.c index 69b1e846..6917eda4 100644 --- a/release/src/router/busybox/console-tools/reset.c +++ b/release/src/router/busybox/console-tools/reset.c @@ -2,32 +2,46 @@ /* * Mini reset implementation for busybox * - * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> * Written by Erik Andersen and Kent Robotti <robotti@metconnect.com> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include <stdio.h> -#include <stdlib.h> -#include "busybox.h" +#include "libbb.h" + +/* BTW, which "standard" package has this utility? It doesn't seem + * to be ncurses, coreutils, console-tools... then what? */ -extern int reset_main(int argc, char **argv) +#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) { - printf("\033[?25h\033c\033[J"); - return EXIT_SUCCESS; -} + 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/release/src/router/busybox/console-tools/resize.c b/release/src/router/busybox/console-tools/resize.c new file mode 100644 index 00000000..4504cc85 --- /dev/null +++ b/release/src/router/busybox/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/release/src/router/busybox/console-tools/setconsole.c b/release/src/router/busybox/console-tools/setconsole.c new file mode 100644 index 00000000..8ad9948d --- /dev/null +++ b/release/src/router/busybox/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/release/src/router/busybox/console-tools/setkeycodes.c b/release/src/router/busybox/console-tools/setkeycodes.c index 0a5366be..597272a2 100644 --- a/release/src/router/busybox/console-tools/setkeycodes.c +++ b/release/src/router/busybox/console-tools/setkeycodes.c @@ -6,67 +6,44 @@ * * Adjusted for BusyBox by Erik Andersen <andersen@codepoet.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include "busybox.h" - +//#include <sys/ioctl.h> +#include "libbb.h" /* From <linux/kd.h> */ struct kbkeycode { - unsigned int scancode, keycode; + unsigned scancode, keycode; +}; +enum { + KDSETKEYCODE = 0x4B4D /* write kernel keycode table entry */ }; -static const int KDSETKEYCODE = 0x4B4D; /* write kernel keycode table entry */ -extern int -setkeycodes_main(int argc, char** argv) +int setkeycodes_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int setkeycodes_main(int argc, char **argv) { - char *ep; - int fd, sc; - struct kbkeycode a; + int fd, sc; + struct kbkeycode a; - if (argc % 2 != 1 || argc < 2) { - bb_show_usage(); + if (!(argc & 1) /* if even */ || argc < 2) { + bb_show_usage(); } - - fd = get_console_fd(); - while (argc > 2) { - a.keycode = atoi(argv[2]); - a.scancode = sc = strtol(argv[1], &ep, 16); - if (*ep) { - bb_error_msg_and_die("error reading SCANCODE: '%s'", argv[1]); - } - if (a.scancode > 127) { - a.scancode -= 0xe000; - a.scancode += 128; - } - if (a.scancode > 255 || a.keycode > 127) { - bb_error_msg_and_die("SCANCODE or KEYCODE outside bounds"); - } - if (ioctl(fd,KDSETKEYCODE,&a)) { - perror("KDSETKEYCODE"); - bb_error_msg_and_die("failed to set SCANCODE %x to KEYCODE %d", sc, a.keycode); + 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; } - argc -= 2; - argv += 2; - } return EXIT_SUCCESS; } diff --git a/release/src/router/busybox/console-tools/setlogcons.c b/release/src/router/busybox/console-tools/setlogcons.c new file mode 100644 index 00000000..dd44591a --- /dev/null +++ b/release/src/router/busybox/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/release/src/router/busybox/console-tools/showkey.c b/release/src/router/busybox/console-tools/showkey.c new file mode 100644 index 00000000..681114df --- /dev/null +++ b/release/src/router/busybox/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; +} |