| #include "config.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <getopt.h> |
| #include <errno.h> |
| #include <ctype.h> |
| #include <unistd.h> |
| #include <sysexits.h> |
| #include <sys/ioctl.h> |
| #include <linux/kd.h> |
| |
| #include <kfont.h> |
| |
| #include "libcommon.h" |
| |
| #ifndef USE_LIBC |
| /* There is such function in libc5 but it doesn't work for me [libc 5.4.13] */ |
| #include "wctomb.c" |
| #define wctomb our_wctomb |
| #endif |
| |
| static int |
| ud_compar(const void *u1, const void *u2) |
| { |
| unsigned short fp1 = ((struct unipair *)u1)->fontpos; |
| unsigned short fp2 = ((struct unipair *)u2)->fontpos; |
| return (int)fp1 - (int)fp2; |
| } |
| |
| static void KBD_ATTR_NORETURN |
| usage(int rc, const struct kbd_help *options) |
| { |
| fprintf(stderr, _("Usage: %s [option...]\n"), program_invocation_short_name); |
| |
| print_options(options); |
| print_report_bugs(); |
| |
| exit(rc); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int sortflag = 0; |
| char mb[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
| int mb_length; |
| int fd, c, i; |
| char *console = NULL; |
| struct unimapdesc ud; |
| |
| setuplocale(); |
| |
| const char *const short_opts = "hVsC:"; |
| const struct option long_opts[] = { |
| { "sort", no_argument, NULL, 's' }, |
| { "console", required_argument, NULL, 'C' }, |
| { "help", no_argument, NULL, 'h' }, |
| { "version", no_argument, NULL, 'V' }, |
| { NULL, 0, NULL, 0 } |
| }; |
| const struct kbd_help opthelp[] = { |
| { "-s, --sort", _("sort and merge elements.") }, |
| { "-C, --console=DEV", _("the console device to be used.") }, |
| { "-V, --version", _("print version number.") }, |
| { "-h, --help", _("print this usage message.") }, |
| { NULL, NULL } |
| }; |
| |
| while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { |
| switch (c) { |
| case 's': |
| sortflag = 1; |
| break; |
| case 'C': |
| console = optarg; |
| break; |
| case 'V': |
| print_version_and_exit(); |
| break; |
| case 'h': |
| usage(EXIT_SUCCESS, opthelp); |
| break; |
| case '?': |
| usage(EX_USAGE, opthelp); |
| break; |
| } |
| } |
| |
| if (optind < argc) |
| usage(EX_USAGE, opthelp); |
| |
| if ((fd = getfd(console)) < 0) |
| kbd_error(EXIT_FAILURE, 0, _("Couldn't get a file descriptor referring to the console.")); |
| |
| int ret; |
| struct kfont_context *kfont; |
| |
| if ((ret = kfont_init(program_invocation_short_name, &kfont)) < 0) |
| return -ret; |
| |
| if (kfont_get_unicodemap(kfont, fd, &ud)) |
| goto kfont_fail; |
| |
| if (sortflag) { |
| printf("# sorted kernel unimap - count=%d\n", ud.entry_ct); |
| /* sort and merge entries */ |
| qsort(ud.entries, ud.entry_ct, sizeof(ud.entries[0]), |
| ud_compar); |
| for (i = 0; i < ud.entry_ct; i++) { |
| int fp = ud.entries[i].fontpos; |
| printf("0x%03x\tU+%04x", fp, ud.entries[i].unicode); |
| while (i + 1 < ud.entry_ct && |
| ud.entries[i + 1].fontpos == fp) |
| printf(" U+%04x", ud.entries[++i].unicode); |
| printf("\n"); |
| } |
| } else { |
| printf("# kernel unimap - count=%d\n", ud.entry_ct); |
| for (i = 0; i < ud.entry_ct; i++) { |
| mb_length = wctomb(mb, ud.entries[i].unicode); |
| mb[(mb_length > 6) ? 0 : mb_length] = 0; |
| if (mb_length == 1 && !isprint(mb[0])) { |
| mb[2] = 0; |
| mb[1] = mb[0] + 0100; |
| mb[0] = '^'; |
| } |
| printf("0x%03x\tU+%04x\t# %s \n", |
| ud.entries[i].fontpos, |
| ud.entries[i].unicode, mb); |
| } |
| } |
| |
| free(ud.entries); |
| kfont_free(kfont); |
| |
| return EXIT_SUCCESS; |
| |
| kfont_fail: |
| kfont_free(kfont); |
| return EXIT_FAILURE; |
| } |