/
niceSOFT
/
kbd
Обзор
Документация
Войти
/
niceSOFT
/
kbd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/setfont.c
375 строк
10 KB
Alexey Gladkov
setfont: check whether console is suitable for font operations
13 мар 2026, 12:57
Не верифицирован
13 мар 2026, 12:57
f5695d3
Код
Авторство
О чём код?
/* * setfont.c - Eugene Crosser & Andries Brouwer */ #include "config.h" #include <stdio.h> #include <memory.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sysexits.h> #include <kfont.h> #include "libcommon.h" static void KBD_ATTR_NORETURN usage(int retcode, const struct kbd_help *options) { fprintf(stderr, _("Usage: %s [option...] [newfont...]\n"), program_invocation_short_name); fprintf(stderr, "\n"); fprintf(stderr, _("Loads the console font, and possibly the corresponding screen map(s).\n")); print_options(options); fprintf(stderr, "\n"); fprintf(stderr, _("The options -[o|O|om|ou] are processed before the new font is uploaded.\n" "\n" "If no <newfont> and no -[o|O|om|ou|m|u] option is given, a default\n" "font is loaded.\n" "\n" "There are two kinds of screen maps, one [-m] giving the correspondence\n" "between some arbitrary 8-bit character set currently in use and the\n" "font positions, and the second [-u] giving the correspondence between\n" "font positions and Unicode values.\n" "\n" "Explicitly (with -m or -u) or implicitly (in the fontfile) given\n" "mappings will be loaded and, in the case of consolemaps, activated.\n" "\n" "Files are loaded from the %s/*/.\n"), DATADIR); print_report_bugs(); exit(retcode); } enum kbd_getopt_arg { kbd_no_argument, kbd_required_argument }; struct kbd_option { const char *short_name; const char *long_name; enum kbd_getopt_arg has_arg; int val; }; static int kbd_getopt(int argc, char **argv, const struct kbd_option *opts) { const struct kbd_option *opt; char *p, *o, *option; const char *name; optarg = NULL; if (!optind) optind = 1; if (optind >= argc || !argv[optind]) return -1; if (argv[optind][0] != '-') return '?'; option = argv[optind]; if (option[1] && option[1] != '-') { // A short option that starts with "-" (not "--"). Unlike the // standard getopt for historical reasons we have two character // short options. option += 1; for (opt = opts; opt->val; opt++) { name = opt->short_name + 1; for (p = (char *) name, o = option; *p && *p == *o; p++, o++); switch (opt->short_name[0]) { // Case: full match option. case '=': if (*p == *o) { optind++; if (opt->has_arg) { if (optind == argc) goto required_argument; optarg = argv[optind++]; } return opt->val; } break; // Case: prefix option. case '+': if (*p == '\0' && *o != '\0') { optind++; if (opt->has_arg) optarg = o; return opt->val; } break; } } } else if (option[1] && option[1] == '-') { // The special argument "--" forces an end of option-scanning // regardless of the scanning mode. if (!option[2]) { optind++; return -1; } option += 2; for (opt = opts; opt->val; opt++) { name = opt->long_name; for (p = (char *) name, o = option; *p && *p == *o; p++, o++); // Case: --arg param if (*p == *o) { optind++; if (opt->has_arg) { if (optind == argc) goto required_argument; optarg = argv[optind++]; } return opt->val; } if (!opt->has_arg) continue; // Case: --arg=param if (*p == '\0' && *o == '=') { optind++; optarg = ++o; if (!optarg[0]) goto required_argument; return opt->val; } } } return '?'; required_argument: optind--; return '!'; } int main(int argc, char *argv[]) { const char *ifiles[MAXIFILES]; char *mfil, *ufil, *Ofil, *ofil, *omfil, *oufil, *console; int ifilct, fd, no_m, no_u, restore, check_console, ret, c; unsigned int iunit, hwunit; struct kfont_context *kfont; const struct kbd_help opthelp[] = { { "-<N>, --default8x <N>", _("load font \"default8x<N>\".") }, { "-h<N>, --font-height <N>", _("override font height (there shouldn't be a space in the short option).") }, { "-o, --output-font <FILE>", _("write current font to <FILE>.") }, { "-om, --output-consolemap <FILE>", _("write current consolemap to <FILE>.") }, { "-ou, --output-unicodemap <FILE>", _("write current unicodemap to <FILE>.") }, { "-O, --output-fullfont <FILE>", _("write current font and unicode map to <FILE>.") }, { "-m, --consolemap <FILE>", _("load console screen map ('none' means don't load it).") }, { "-u, --unicodemap <FILE>", _("load font unicode map ('none' means don't load it).") }, { "-C, --console <DEV>", _("the console device to be used.") }, { "-c, --check", _("check whether console is suitable for font operations.") }, { "-d, --double", _("double size of font horizontally and vertically.") }, { "-f, --force", _("force load unicode map.") }, { "-R, --reset", _("reset the screen font, size, and unicode map to the bootup defaults.") }, { "-v, --verbose", _("be more verbose.") }, { "-V, --version", _("print version number.") }, { "-h, --help", _("print this usage message.") }, { NULL, NULL } }; const struct kbd_option opts[] = { { "=c", "check", kbd_no_argument, 'c' }, { "=d", "double", kbd_no_argument, 'd' }, { "=f", "force", kbd_no_argument, 'f' }, { "=R", "reset", kbd_no_argument, 'R' }, { "=v", "verbose", kbd_no_argument, 'v' }, { "=V", "version", kbd_no_argument, 'V' }, { "=h", "help", kbd_no_argument, 'H' }, { "+h", "font-height", kbd_required_argument, 'h' }, { "=om", "output-consolemap", kbd_required_argument, 'M' }, { "=ou", "output-unicodemap", kbd_required_argument, 'U' }, { "=o", "output-font", kbd_required_argument, 'o' }, { "=O", "output-fullfont", kbd_required_argument, 'O' }, { "=m", "consolemap", kbd_required_argument, 'm' }, { "=u", "unicodemap", kbd_required_argument, 'u' }, { "=C", "console", kbd_required_argument, 'C' }, { "+", "default8x", kbd_required_argument, 'N' }, { NULL, NULL, 0, 0 }, }; setuplocale(); if ((ret = kfont_init(program_invocation_short_name, &kfont)) < 0) return -ret; ifiles[0] = mfil = ufil = Ofil = ofil = omfil = oufil = NULL; iunit = hwunit = 0; ifilct = no_m = no_u = 0; restore = check_console = 0; console = NULL; while ((c = kbd_getopt(argc, argv, opts)) != -1) { switch (c) { case 'h': { int num = atoi(optarg); if (num <= 0 || num > 32) { kbd_warning(0, "bad option '%s': not a number '%s'", argv[optind - 1], optarg); usage(EX_USAGE, opthelp); } hwunit = (unsigned int) num; } break; case 'N': { int num = atoi(optarg); if (num <= 0 || num > 32) { kbd_warning(0, "unrecognized option '%s'", argv[optind - 1]); usage(EX_USAGE, opthelp); } iunit = (unsigned int) num; } break; case 'o': ofil = optarg; break; case 'M': omfil = optarg; break; case 'U': oufil = optarg; break; case 'm': no_m = !strcmp(optarg, "none"); if (!no_m) mfil = optarg; break; case 'u': no_u = !strcmp(optarg, "none"); if (!no_u) ufil = optarg; break; case 'O': Ofil = optarg; break; case 'C': console = optarg; break; case 'R': restore = 1; break; case 'c': check_console = 1; break; case 'd': kfont_set_option(kfont, kfont_double_size); break; case 'f': kfont_set_option(kfont, kfont_force); break; case 'v': kfont_inc_verbosity(kfont); break; case 'V': print_version_and_exit(); break; case 'H': usage(EXIT_SUCCESS, opthelp); break; case '?': if (argv[optind][0] == '-') { kbd_warning(0, "invalid option '%s'", argv[optind]); usage(EX_USAGE, opthelp); } if (ifilct == MAXIFILES) kbd_error(EX_USAGE, 0, _("Too many input files.")); ifiles[ifilct++] = argv[optind++]; break; case '!': kbd_warning(0, "option '%s' requires an argument", argv[optind]); usage(EX_USAGE, opthelp); break; } } for (; optind < argc; optind++) { if (ifilct == MAXIFILES) kbd_error(EX_USAGE, 0, _("Too many input files.")); ifiles[ifilct++] = argv[optind]; } if (ifilct && restore) kbd_error(EX_USAGE, 0, _("Cannot both restore from character ROM" " and from file. Font unchanged.")); if ((fd = getfd(console)) < 0) kbd_error(EX_OSERR, 0, _("Couldn't get a file descriptor referring to the console.")); if (check_console) return kfont_is_font_console(kfont, fd) ? EX_OK : EXIT_FAILURE; int kd_mode = -1; if (!ioctl(fd, KDGETMODE, &kd_mode) && (kd_mode == KD_GRAPHICS)) { /* * PIO_FONT will fail on a console which is in foreground and in KD_GRAPHICS mode. * 2005-03-03, jw@suse.de. */ if (kfont_get_verbosity(kfont)) kbd_warning(0, "graphics console %s skipped", console ? console : ""); close(fd); return EX_OK; } if (!ifilct && !mfil && !ufil && !Ofil && !ofil && !omfil && !oufil && !restore) /* reset to some default */ ifiles[ifilct++] = ""; if (Ofil && (ret = kfont_save_font(kfont, fd, Ofil, 1)) < 0) return -ret; if (ofil && (ret = kfont_save_font(kfont, fd, ofil, 0)) < 0) return -ret; if (omfil && (ret = kfont_save_consolemap(kfont, fd, omfil)) < 0) return -ret; if (oufil && (ret = kfont_save_unicodemap(kfont, fd, oufil)) < 0) return -ret; if (mfil) { if ((ret = kfont_load_consolemap(kfont, fd, mfil)) < 0) return -ret; kfont_activatemap(fd); no_m = 1; } if (ufil) no_u = 1; if (restore) kfont_restore_font(kfont, fd); if (ifilct && (ret = kfont_load_fonts(kfont, fd, ifiles, ifilct, iunit, hwunit, no_m, no_u)) < 0) return -ret; if (ufil && (ret = kfont_load_unicodemap(kfont, fd, ufil)) < 0) return -ret; return EX_OK; }