blob: 00b556678da61ed61f0e3e845181ab6ab9b0b18c [file]
#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;
}