/
niceSOFT
/
kbd
Обзор
Документация
Войти
/
niceSOFT
/
kbd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/loadkeys.c
386 строк
10 KB
Alexey Gladkov
loadkeys: Allow tkeymap to dump numeric values
25 июн 2026, 18:42
Не верифицирован
25 июн 2026, 18:42
bdba2e6
Код
Авторство
О чём код?
/* loadkeys.c * * This file is part of kbd project. * Copyright (C) 1993 Risto Kankkunen. * Copyright (C) 1993 Eugene G. Crosser. * Copyright (C) 1994-2007 Andries E. Brouwer. * Copyright (C) 2007-2012 Alexey Gladkov <gladkov.alexey@gmail.com> * * This file is covered by the GNU General Public License, * which should be included with kbd as the file COPYING. */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <getopt.h> #include <unistd.h> #include <errno.h> #include <sysexits.h> #include <sys/ioctl.h> #include <keymap.h> #include "libcommon.h" #ifdef USE_XKB #include "xkbsupport.h" #endif static const char *const dirpath1[] = { DATADIR "/" KEYMAPDIR "/**", KERNDIR "/", NULL }; static const char *const suffixes[] = { "", ".kmap", ".map", NULL }; static void KBD_ATTR_NORETURN usage(int rc, const struct kbd_help *options) { fprintf(stderr, _("Usage: %s [option...] [mapfile...]\n"), program_invocation_short_name); print_options(options); fprintf(stderr, "\n"); fprintf(stderr, _("Default keymap: %s\n"), DEFMAP); fprintf(stderr, _("Available shapes:\n" " 2 - default output;\n" " 4 - one line for each keycode;\n" " 8 - one line for each (modifier,keycode) pair;\n" " 16 - one line for each keycode until 1st hole.\n" )); print_report_bugs(); exit(rc); } int main(int argc, char *argv[]) { int options = 0; lk_table_shape table_shape = LK_SHAPE_DEFAULT; const char *const *dirpath; const char *dirpath2[] = { NULL, NULL }; struct lk_ctx *ctx; lk_flags flags = 0; int c, i, rc = -1; int fd = -1; int kbd_mode; int kd_mode; char *console = NULL; char *ev; struct kbdfile_ctx *fctx; struct kbdfile *fp = NULL; #ifdef USE_XKB struct xkeymap_params xkeymap_params = { .model = "pc104", .layout = NULL, .variant = NULL, .options = NULL, .locale = NULL, }; int use_xkb = 0; #endif setuplocale(); const char *const short_opts = "abcC:dhmpst::uqvV"; const struct option long_opts[] = { { "console", required_argument, NULL, 'C' }, { "ascii", no_argument, NULL, 'a' }, { "bkeymap", no_argument, NULL, 'b' }, { "clearcompose", no_argument, NULL, 'c' }, { "default", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "mktable", no_argument, NULL, 'm' }, { "parse", no_argument, NULL, 'p' }, { "clearstrings", no_argument, NULL, 's' }, { "tkeymap", optional_argument, NULL, 't' }, { "unicode", no_argument, NULL, 'u' }, { "quiet", no_argument, NULL, 'q' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, #ifdef USE_XKB //{ "xkb-rules", required_argument, NULL, 1 }, { "xkb-model", required_argument, NULL, 2 }, { "xkb-layout", required_argument, NULL, 3 }, { "xkb-variant", required_argument, NULL, 4 }, { "xkb-options", required_argument, NULL, 5 }, { "xkb-locale", required_argument, NULL, 6 }, #endif { NULL, 0, NULL, 0 } }; const struct kbd_help opthelp[] = { #ifdef USE_XKB { "--xkb-model=STR", _("Specifies model used to choose component names.") }, { "--xkb-layout=STR", _("Specifies layout used to choose component names.") }, { "--xkb-variant=STR", _("Specifies layout variant used to choose component names.") }, { "--xkb-options=STR", _("Adds an option used to choose component names.") }, { "--xkb-locale=LOCALE", _("Use LOCALE to search an appropriate compose file.") }, #endif { "-C, --console=DEV", _("the console device to be used.") }, { "-a, --ascii", _("force conversion to ASCII.") }, { "-b, --bkeymap", _("output a binary keymap to stdout.") }, { "-c, --clearcompose", _("clear kernel compose table.") }, { "-d, --default", _("load default.") }, { "-m, --mktable", _("output a 'defkeymap.c' to stdout.") }, { "-p, --parse", _("search and parse keymap without action.") }, { "-s, --clearstrings", _("clear kernel string table.") }, { "-u, --unicode", _("force conversion to Unicode.") }, { "-q, --quiet", _("suppress all normal output.") }, { "-t, --tkeymap[=SHAPE]", _("output a text keymap to stdout.") }, { "-v, --verbose", _("be more verbose.") }, { "-V, --version", _("print version number.") }, { "-h, --help", _("print this usage message.") }, { NULL, NULL } }; enum options { OPT_A = (1 << 1), OPT_B = (1 << 2), OPT_D = (1 << 3), OPT_M = (1 << 4), OPT_U = (1 << 5), OPT_P = (1 << 6), OPT_T = (1 << 7) }; ctx = lk_init(); if (!ctx) { exit(EXIT_FAILURE); } if (!(fctx = kbdfile_context_new())) kbd_error(EXIT_FAILURE, errno, _("Unable to create kbdfile context")); while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (c) { #ifdef USE_XKB case 2: xkeymap_params.model = optarg; use_xkb = 1; break; case 3: xkeymap_params.layout = optarg; use_xkb = 1; break; case 4: xkeymap_params.variant = optarg; use_xkb = 1; break; case 5: xkeymap_params.options = optarg; use_xkb = 1; break; case 6: xkeymap_params.locale = optarg; use_xkb = 1; break; #endif case 'a': options |= OPT_A; break; case 'b': options |= OPT_B; break; case 'c': flags |= LK_FLAG_CLEAR_COMPOSE; break; case 'C': console = optarg; break; case 'd': options |= OPT_D; break; case 'm': options |= OPT_M; break; case 'p': options |= OPT_P; break; case 's': flags |= LK_FLAG_CLEAR_STRINGS; break; case 'u': options |= OPT_U; flags |= LK_FLAG_UNICODE_MODE; flags |= LK_FLAG_PREFER_UNICODE; break; case 'q': lk_set_log_priority(ctx, LOG_ERR); break; case 't': options |= OPT_T; if (optarg) { table_shape = atoi(optarg); } break; case 'v': lk_set_log_priority(ctx, LOG_INFO); break; case 'V': print_version_and_exit(); break; case 'h': usage(EXIT_SUCCESS, opthelp); break; case '?': usage(EX_USAGE, opthelp); break; } } if ((options & OPT_U) && (options & OPT_A)) kbd_error(EXIT_FAILURE, 0, _("Options %s and %s are mutually exclusive."), "--unicode", "--ascii"); if (!(options & OPT_M) && !(options & OPT_B) && !(options & OPT_T)) { /* get console */ if ((fd = getfd(console)) < 0) kbd_error(EXIT_FAILURE, 0, _("Couldn't get a file descriptor referring to the console.")); /* check whether the keyboard is in Unicode mode */ if (ioctl(fd, KDGKBMODE, &kbd_mode)) kbd_error(EXIT_FAILURE, errno, _("Unable to read keyboard mode")); if (ioctl(fd, KDGETMODE, &kd_mode)) kbd_error(EXIT_FAILURE, errno, _("Unable to read console mode")); if (kbd_mode == K_UNICODE) { if (options & OPT_A) { kbd_warning(0, _("Warning: loading non-Unicode keymap on Unicode console\n" " (perhaps you want to do `kbd_mode -a'?)")); } else { flags |= LK_FLAG_PREFER_UNICODE; } /* reset -u option if keyboard is in K_UNICODE anyway */ flags ^= LK_FLAG_UNICODE_MODE; } else if (options & OPT_U && kd_mode != KD_GRAPHICS) { kbd_warning(0, _("Warning: loading Unicode keymap on non-Unicode console\n" " (perhaps you want to do `kbd_mode -u'?)")); } } lk_set_parser_flags(ctx, flags); dirpath = dirpath1; if ((ev = getenv("LOADKEYS_KEYMAP_PATH")) != NULL) { dirpath2[0] = ev; dirpath = dirpath2; } if (options & OPT_D) { if (!(fp = kbdfile_new(fctx))) kbd_error(EXIT_FAILURE, 0, _("Unable to create kbdfile instance: %m")); /* first read default map - search starts in . */ if (kbdfile_find(DEFMAP, dirpath, suffixes, fp)) kbd_error(EXIT_FAILURE, 0, _("Unable to find file: %s"), DEFMAP); rc = lk_parse_keymap(ctx, fp); kbdfile_free(fp); if (rc == -1) goto fail; #ifdef USE_XKB } else if (use_xkb) { if (!xkeymap_params.locale || !*xkeymap_params.locale) xkeymap_params.locale = getenv("LC_ALL"); if (!xkeymap_params.locale || !*xkeymap_params.locale) xkeymap_params.locale = getenv("LC_CTYPE"); if (!xkeymap_params.locale || !*xkeymap_params.locale) xkeymap_params.locale = getenv("LANG"); if (!xkeymap_params.locale || !*xkeymap_params.locale) xkeymap_params.locale = "C"; rc = convert_xkb_keymap(ctx, &xkeymap_params); if (rc == -1) goto fail; #endif } else if (optind == argc) { if (!(fp = kbdfile_new(fctx))) kbd_error(EXIT_FAILURE, 0, _("Unable to create kbdfile instance: %m")); kbdfile_set_file(fp, stdin); kbdfile_set_pathname(fp, "<stdin>"); rc = lk_parse_keymap(ctx, fp); kbdfile_free(fp); if (rc == -1) goto fail; } for (i = optind; argv[i]; i++) { if (!(fp = kbdfile_new(fctx))) { kbd_error(EXIT_FAILURE, 0, _("Unable to create kbdfile instance: %m")); } if (!strcmp(argv[i], "-")) { kbdfile_set_file(fp, stdin); kbdfile_set_pathname(fp, "<stdin>"); } else if (kbdfile_find(argv[i], dirpath, suffixes, fp)) { kbd_warning(0, _("Unable to open file: %s: %m"), argv[i]); goto fail; } rc = lk_parse_keymap(ctx, fp); kbdfile_free(fp); if (rc == -1) goto fail; } if (!(options & OPT_P)) { if (options & OPT_B) { rc = lk_dump_bkeymap(ctx, stdout); } else if (options & OPT_M) { rc = lk_dump_ctable(ctx, stdout); } else if (options & OPT_T) { char numeric = getenv("LK_DUMP_NUMERIC") != NULL; rc = lk_dump_keymap2(ctx, stdout, table_shape, numeric); if (rc < 0) goto fail; #ifdef KDGKBDIACR lk_dump_diacs(ctx, stdout); #endif rc = 0; } else { rc = lk_load_keymap(ctx, fd, kbd_mode); } } else if (getenv("LK_DUMPKEYS")) { lk_dump_keymap(ctx, stdout, LK_SHAPE_SEPARATE_LINES, 0); lk_dump_diacs(ctx, stdout); } fail: lk_free(ctx); kbdfile_context_free(fctx); if (fd >= 0) close(fd); if (rc < 0) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); }