|
|
|
@ -39,50 +39,32 @@
|
|
|
|
|
#include "terminal-util.h"
|
|
|
|
|
#include "virt.h"
|
|
|
|
|
|
|
|
|
|
typedef enum VCMeta {
|
|
|
|
|
VC_KEYMAP,
|
|
|
|
|
VC_KEYMAP_TOGGLE,
|
|
|
|
|
VC_FONT,
|
|
|
|
|
VC_FONT_MAP,
|
|
|
|
|
VC_FONT_UNIMAP,
|
|
|
|
|
_VC_META_MAX,
|
|
|
|
|
_VC_META_INVALID = -EINVAL,
|
|
|
|
|
} VCMeta;
|
|
|
|
|
|
|
|
|
|
typedef struct Context {
|
|
|
|
|
char *config[_VC_META_MAX];
|
|
|
|
|
char *keymap;
|
|
|
|
|
char *keymap_toggle;
|
|
|
|
|
char *font;
|
|
|
|
|
char *font_map;
|
|
|
|
|
char *font_unimap;
|
|
|
|
|
} Context;
|
|
|
|
|
|
|
|
|
|
static const char * const vc_meta_names[_VC_META_MAX] = {
|
|
|
|
|
[VC_KEYMAP] = "vconsole.keymap",
|
|
|
|
|
[VC_KEYMAP_TOGGLE] = "vconsole.keymap_toggle",
|
|
|
|
|
[VC_FONT] = "vconsole.font",
|
|
|
|
|
[VC_FONT_MAP] = "vconsole.font_map",
|
|
|
|
|
[VC_FONT_UNIMAP] = "vconsole.font_unimap",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* compatibility with obsolete multiple-dot scheme */
|
|
|
|
|
static const char * const vc_meta_compat_names[_VC_META_MAX] = {
|
|
|
|
|
[VC_KEYMAP_TOGGLE] = "vconsole.keymap.toggle",
|
|
|
|
|
[VC_FONT_MAP] = "vconsole.font.map",
|
|
|
|
|
[VC_FONT_UNIMAP] = "vconsole.font.unimap",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char * const vc_env_names[_VC_META_MAX] = {
|
|
|
|
|
[VC_KEYMAP] = "KEYMAP",
|
|
|
|
|
[VC_KEYMAP_TOGGLE] = "KEYMAP_TOGGLE",
|
|
|
|
|
[VC_FONT] = "FONT",
|
|
|
|
|
[VC_FONT_MAP] = "FONT_MAP",
|
|
|
|
|
[VC_FONT_UNIMAP] = "FONT_UNIMAP",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void context_done(Context *c) {
|
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
|
|
FOREACH_ARRAY(cc, c->config, _VC_META_MAX)
|
|
|
|
|
free(*cc);
|
|
|
|
|
free(c->keymap);
|
|
|
|
|
free(c->keymap_toggle);
|
|
|
|
|
free(c->font);
|
|
|
|
|
free(c->font_map);
|
|
|
|
|
free(c->font_unimap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define context_merge(dst, src, src_compat, name) \
|
|
|
|
|
({ \
|
|
|
|
|
if (src->name) \
|
|
|
|
|
free_and_replace(dst->name, src->name); \
|
|
|
|
|
else if (src_compat && src_compat->name) \
|
|
|
|
|
free_and_replace(dst->name, src_compat->name); \
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
static void context_merge_config(
|
|
|
|
|
Context *dst,
|
|
|
|
|
Context *src,
|
|
|
|
@ -91,21 +73,11 @@ static void context_merge_config(
|
|
|
|
|
assert(dst);
|
|
|
|
|
assert(src);
|
|
|
|
|
|
|
|
|
|
for (VCMeta i = 0; i < _VC_META_MAX; i++)
|
|
|
|
|
if (src->config[i])
|
|
|
|
|
free_and_replace(dst->config[i], src->config[i]);
|
|
|
|
|
else if (src_compat && src_compat->config[i])
|
|
|
|
|
free_and_replace(dst->config[i], src_compat->config[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char* context_get_config(Context *c, VCMeta meta) {
|
|
|
|
|
assert(c);
|
|
|
|
|
assert(meta >= 0 && meta < _VC_META_MAX);
|
|
|
|
|
|
|
|
|
|
if (meta == VC_KEYMAP)
|
|
|
|
|
return isempty(c->config[VC_KEYMAP]) ? SYSTEMD_DEFAULT_KEYMAP : c->config[VC_KEYMAP];
|
|
|
|
|
|
|
|
|
|
return empty_to_null(c->config[meta]);
|
|
|
|
|
context_merge(dst, src, src_compat, keymap);
|
|
|
|
|
context_merge(dst, src, src_compat, keymap_toggle);
|
|
|
|
|
context_merge(dst, src, src_compat, font);
|
|
|
|
|
context_merge(dst, src, src_compat, font_map);
|
|
|
|
|
context_merge(dst, src, src_compat, font_unimap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int context_read_creds(Context *c) {
|
|
|
|
@ -115,11 +87,11 @@ static int context_read_creds(Context *c) {
|
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
|
|
r = read_credential_strings_many(
|
|
|
|
|
vc_meta_names[VC_KEYMAP], &v.config[VC_KEYMAP],
|
|
|
|
|
vc_meta_names[VC_KEYMAP_TOGGLE], &v.config[VC_KEYMAP_TOGGLE],
|
|
|
|
|
vc_meta_names[VC_FONT], &v.config[VC_FONT],
|
|
|
|
|
vc_meta_names[VC_FONT_MAP], &v.config[VC_FONT_MAP],
|
|
|
|
|
vc_meta_names[VC_FONT_UNIMAP], &v.config[VC_FONT_UNIMAP]);
|
|
|
|
|
"vconsole.keymap", &v.keymap,
|
|
|
|
|
"vconsole.keymap_toggle", &v.keymap_toggle,
|
|
|
|
|
"vconsole.font", &v.font,
|
|
|
|
|
"vconsole.font_map", &v.font_map,
|
|
|
|
|
"vconsole.font_unimap", &v.font_unimap);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
log_warning_errno(r, "Failed to import credentials, ignoring: %m");
|
|
|
|
|
|
|
|
|
@ -135,11 +107,11 @@ static int context_read_env(Context *c) {
|
|
|
|
|
|
|
|
|
|
r = parse_env_file(
|
|
|
|
|
NULL, "/etc/vconsole.conf",
|
|
|
|
|
vc_env_names[VC_KEYMAP], &v.config[VC_KEYMAP],
|
|
|
|
|
vc_env_names[VC_KEYMAP_TOGGLE], &v.config[VC_KEYMAP_TOGGLE],
|
|
|
|
|
vc_env_names[VC_FONT], &v.config[VC_FONT],
|
|
|
|
|
vc_env_names[VC_FONT_MAP], &v.config[VC_FONT_MAP],
|
|
|
|
|
vc_env_names[VC_FONT_UNIMAP], &v.config[VC_FONT_UNIMAP]);
|
|
|
|
|
"KEYMAP", &v.keymap,
|
|
|
|
|
"KEYMAP_TOGGLE", &v.keymap_toggle,
|
|
|
|
|
"FONT", &v.font,
|
|
|
|
|
"FONT_MAP", &v.font_map,
|
|
|
|
|
"FONT_UNIMAP", &v.font_unimap);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
if (r != -ENOENT)
|
|
|
|
|
log_warning_errno(r, "Failed to read /etc/vconsole.conf, ignoring: %m");
|
|
|
|
@ -158,14 +130,15 @@ static int context_read_proc_cmdline(Context *c) {
|
|
|
|
|
|
|
|
|
|
r = proc_cmdline_get_key_many(
|
|
|
|
|
PROC_CMDLINE_STRIP_RD_PREFIX,
|
|
|
|
|
vc_meta_names[VC_KEYMAP], &v.config[VC_KEYMAP],
|
|
|
|
|
vc_meta_names[VC_KEYMAP_TOGGLE], &v.config[VC_KEYMAP_TOGGLE],
|
|
|
|
|
vc_meta_names[VC_FONT], &v.config[VC_FONT],
|
|
|
|
|
vc_meta_names[VC_FONT_MAP], &v.config[VC_FONT_MAP],
|
|
|
|
|
vc_meta_names[VC_FONT_UNIMAP], &v.config[VC_FONT_UNIMAP],
|
|
|
|
|
vc_meta_compat_names[VC_KEYMAP_TOGGLE], &w.config[VC_KEYMAP_TOGGLE],
|
|
|
|
|
vc_meta_compat_names[VC_FONT_MAP], &w.config[VC_FONT_MAP],
|
|
|
|
|
vc_meta_compat_names[VC_FONT_UNIMAP], &w.config[VC_FONT_UNIMAP]);
|
|
|
|
|
"vconsole.keymap", &v.keymap,
|
|
|
|
|
"vconsole.keymap_toggle", &v.keymap_toggle,
|
|
|
|
|
"vconsole.font", &v.font,
|
|
|
|
|
"vconsole.font_map", &v.font_map,
|
|
|
|
|
"vconsole.font_unimap", &v.font_unimap,
|
|
|
|
|
/* compatibility with obsolete multiple-dot scheme */
|
|
|
|
|
"vconsole.keymap.toggle", &w.keymap_toggle,
|
|
|
|
|
"vconsole.font.map", &w.font_map,
|
|
|
|
|
"vconsole.font.unimap", &w.font_unimap);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
if (r != -ENOENT)
|
|
|
|
|
log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
|
|
|
|
@ -285,8 +258,11 @@ static int toggle_utf8_sysfs(bool utf8) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* SYSTEMD_DEFAULT_KEYMAP must not be empty */
|
|
|
|
|
assert_cc(STRLEN(SYSTEMD_DEFAULT_KEYMAP) > 0);
|
|
|
|
|
|
|
|
|
|
static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
|
|
|
|
const char *map, *map_toggle, *args[8];
|
|
|
|
|
const char* args[8];
|
|
|
|
|
unsigned i = 0;
|
|
|
|
|
pid_t pid;
|
|
|
|
|
int r;
|
|
|
|
@ -294,11 +270,11 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
|
|
|
|
assert(vc);
|
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
|
|
map = context_get_config(c, VC_KEYMAP);
|
|
|
|
|
map_toggle = context_get_config(c, VC_KEYMAP_TOGGLE);
|
|
|
|
|
const char
|
|
|
|
|
*keymap = empty_to_null(c->keymap) ?: SYSTEMD_DEFAULT_KEYMAP,
|
|
|
|
|
*keymap_toggle = empty_to_null(c->keymap_toggle);
|
|
|
|
|
|
|
|
|
|
/* An empty map means kernel map */
|
|
|
|
|
if (isempty(map) || streq(map, "@kernel"))
|
|
|
|
|
if (streq(keymap, "@kernel"))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
args[i++] = KBD_LOADKEYS;
|
|
|
|
@ -307,9 +283,9 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
|
|
|
|
args[i++] = vc;
|
|
|
|
|
if (utf8)
|
|
|
|
|
args[i++] = "-u";
|
|
|
|
|
args[i++] = map;
|
|
|
|
|
if (map_toggle)
|
|
|
|
|
args[i++] = map_toggle;
|
|
|
|
|
args[i++] = keymap;
|
|
|
|
|
if (keymap_toggle)
|
|
|
|
|
args[i++] = keymap_toggle;
|
|
|
|
|
args[i++] = NULL;
|
|
|
|
|
|
|
|
|
|
if (DEBUG_LOGGING) {
|
|
|
|
@ -331,7 +307,7 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int font_load_and_wait(const char *vc, Context *c) {
|
|
|
|
|
const char *font, *map, *unimap, *args[9];
|
|
|
|
|
const char* args[9];
|
|
|
|
|
unsigned i = 0;
|
|
|
|
|
pid_t pid;
|
|
|
|
|
int r;
|
|
|
|
@ -339,24 +315,25 @@ static int font_load_and_wait(const char *vc, Context *c) {
|
|
|
|
|
assert(vc);
|
|
|
|
|
assert(c);
|
|
|
|
|
|
|
|
|
|
font = context_get_config(c, VC_FONT);
|
|
|
|
|
map = context_get_config(c, VC_FONT_MAP);
|
|
|
|
|
unimap = context_get_config(c, VC_FONT_UNIMAP);
|
|
|
|
|
const char
|
|
|
|
|
*font = empty_to_null(c->font),
|
|
|
|
|
*font_map = empty_to_null(c->font_map),
|
|
|
|
|
*font_unimap = empty_to_null(c->font_unimap);
|
|
|
|
|
|
|
|
|
|
/* Any part can be set independently */
|
|
|
|
|
if (!font && !map && !unimap)
|
|
|
|
|
if (!font && !font_map && !font_unimap)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
args[i++] = KBD_SETFONT;
|
|
|
|
|
args[i++] = "-C";
|
|
|
|
|
args[i++] = vc;
|
|
|
|
|
if (map) {
|
|
|
|
|
if (font_map) {
|
|
|
|
|
args[i++] = "-m";
|
|
|
|
|
args[i++] = map;
|
|
|
|
|
args[i++] = font_map;
|
|
|
|
|
}
|
|
|
|
|
if (unimap) {
|
|
|
|
|
if (font_unimap) {
|
|
|
|
|
args[i++] = "-u";
|
|
|
|
|
args[i++] = unimap;
|
|
|
|
|
args[i++] = font_unimap;
|
|
|
|
|
}
|
|
|
|
|
if (font)
|
|
|
|
|
args[i++] = font;
|
|
|
|
@ -377,7 +354,7 @@ static int font_load_and_wait(const char *vc, Context *c) {
|
|
|
|
|
_exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. This might mean various
|
|
|
|
|
/* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. This might mean various
|
|
|
|
|
* things, but in particular lack of a graphical console. Let's be generous and not treat this as an
|
|
|
|
|
* error. */
|
|
|
|
|
r = wait_for_terminate_and_check(KBD_SETFONT, pid, WAIT_LOG_ABNORMAL);
|
|
|
|
|