1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini loadkmap implementation for busybox
4  *
5  * Copyright (C) 1998 Enrique Zanardi <ezanardi@ull.es>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8  */
9 //config:config LOADKMAP
10 //config:	bool "loadkmap (1.8 kb)"
11 //config:	default y
12 //config:	help
13 //config:	This program loads a keyboard translation table from
14 //config:	standard input.
15 
16 //applet:IF_LOADKMAP(APPLET_NOEXEC(loadkmap, loadkmap, BB_DIR_SBIN, BB_SUID_DROP, loadkmap))
17 
18 //kbuild:lib-$(CONFIG_LOADKMAP) += loadkmap.o
19 
20 //usage:#define loadkmap_trivial_usage
21 //usage:       "< keymap"
22 //usage:#define loadkmap_full_usage "\n\n"
23 //usage:       "Load a binary keyboard translation table from stdin"
24 ////usage:       "\n"
25 ////usage:       "\n	-C TTY	Affect TTY instead of /dev/tty"
26 //usage:
27 //usage:#define loadkmap_example_usage
28 //usage:       "$ loadkmap < /etc/i18n/lang-keymap\n"
29 
30 #include "libbb.h"
31 
32 #define BINARY_KEYMAP_MAGIC "bkeymap"
33 
34 /* From <linux/kd.h> */
35 struct kbentry {
36 	unsigned char kb_table;
37 	unsigned char kb_index;
38 	unsigned short kb_value;
39 };
40 /* sets one entry in translation table */
41 #define KDSKBENT        0x4B47
42 
43 /* From <linux/keyboard.h> */
44 #define NR_KEYS         128
45 #define MAX_NR_KEYMAPS  256
46 
47 int loadkmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
loadkmap_main(int argc UNUSED_PARAM,char ** argv)48 int loadkmap_main(int argc UNUSED_PARAM, char **argv)
49 {
50 	struct kbentry ke;
51 	int i, j, fd;
52 	uint16_t ibuff[NR_KEYS];
53 /*	const char *tty_name = CURRENT_TTY; */
54 	RESERVE_CONFIG_BUFFER(flags, MAX_NR_KEYMAPS);
55 
56 	/* When user accidentally runs "loadkmap FILE"
57 	 * instead of "loadkmap <FILE", we end up waiting for input from tty.
58 	 * Let's prevent it: */
59 	if (argv[1])
60 		bb_show_usage();
61 /* bb_warn_ignoring_args(argv[1]); */
62 
63 	fd = get_console_fd_or_die();
64 /* or maybe:
65 	opt = getopt32(argv, "C:", &tty_name);
66 	fd = xopen_nonblocking(tty_name);
67 */
68 
69 	xread(STDIN_FILENO, flags, 7);
70 	if (!is_prefixed_with(flags, BINARY_KEYMAP_MAGIC))
71 		bb_simple_error_msg_and_die("not a valid binary keymap");
72 
73 	xread(STDIN_FILENO, flags, MAX_NR_KEYMAPS);
74 
75 	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
76 		if (flags[i] != 1)
77 			continue;
78 		xread(STDIN_FILENO, ibuff, NR_KEYS * sizeof(uint16_t));
79 		for (j = 0; j < NR_KEYS; j++) {
80 			ke.kb_index = j;
81 			ke.kb_table = i;
82 			ke.kb_value = ibuff[j];
83 			/*
84 			 * Note: table[idx:0] can contain special value
85 			 * K_ALLOCATED (marks allocated tables in kernel).
86 			 * dumpkmap saves the value as-is; but attempts
87 			 * to load it here fail, since it isn't a valid
88 			 * key value: it is K(KT_SPEC,126) == 2<<8 + 126,
89 			 * whereas last valid KT_SPEC is
90 			 * K_BARENUMLOCK == K(KT_SPEC,19).
91 			 * So far we just ignore these errors:
92 			 */
93 			ioctl(fd, KDSKBENT, &ke);
94 		}
95 	}
96 
97 	if (ENABLE_FEATURE_CLEAN_UP) {
98 		close(fd);
99 		RELEASE_CONFIG_BUFFER(flags);
100 	}
101 	return EXIT_SUCCESS;
102 }
103