return SYSTEMD_LANGUAGE_FALLBACK_MAP;
}
-static void x11_context_clear(X11Context *xc) {
+void x11_context_clear(X11Context *xc) {
assert(xc);
xc->layout = mfree(xc->layout);
xc->variant = mfree(xc->variant);
}
-static bool x11_context_isempty(const X11Context *xc) {
+void x11_context_replace(X11Context *dest, X11Context *src) {
+ assert(dest);
+ assert(src);
+
+ x11_context_clear(dest);
+ *dest = *src;
+ *src = (X11Context) {};
+}
+
+bool x11_context_isempty(const X11Context *xc) {
assert(xc);
return
x11_context_clear(&c->x11_from_vc);
}
-static void vc_context_clear(VCContext *vc) {
+void vc_context_clear(VCContext *vc) {
assert(vc);
vc->keymap = mfree(vc->keymap);
vc->toggle = mfree(vc->toggle);
}
-static bool vc_context_isempty(const VCContext *vc) {
+void vc_context_replace(VCContext *dest, VCContext *src) {
+ assert(dest);
+ assert(src);
+
+ vc_context_clear(dest);
+ *dest = *src;
+ *src = (VCContext) {};
+}
+
+bool vc_context_isempty(const VCContext *vc) {
assert(vc);
return
return 0;
}
-int vconsole_convert_to_x11(Context *c) {
- int r, modified = -1;
- X11Context *xc;
-
- assert(c);
+int vconsole_convert_to_x11(const VCContext *vc, X11Context *ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ const char *map;
+ int r;
- /* If Context.x11_from_vc is empty, then here we update Context.x11_from_xorg, as the caller may
- * already have been called context_get_x11_context() or _safe(), and otherwise the caller's
- * X11Context may be outdated. The updated context will be copied to Context.x11_from_vc in
- * vconsole_write_data() if necessary. */
- xc = context_get_x11_context_safe(c);
+ assert(vc);
+ assert(ret);
- if (isempty(c->vc.keymap)) {
- modified = !x11_context_isempty(xc);
- context_clear_x11(c);
- } else {
- _cleanup_fclose_ FILE *f = NULL;
- const char *map;
+ if (isempty(vc->keymap)) {
+ *ret = (X11Context) {};
+ return 0;
+ }
- map = systemd_kbd_model_map();
- f = fopen(map, "re");
- if (!f)
- return -errno;
+ map = systemd_kbd_model_map();
+ f = fopen(map, "re");
+ if (!f)
+ return -errno;
- for (unsigned n = 0;;) {
- _cleanup_strv_free_ char **a = NULL;
+ for (unsigned n = 0;;) {
+ _cleanup_strv_free_ char **a = NULL;
- r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a);
- if (r < 0)
- return r;
- if (r == 0)
- break;
+ r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ log_notice("No conversion found for virtual console keymap \"%s\".", vc->keymap);
+ *ret = (X11Context) {};
+ return 0;
+ }
- if (!streq(c->vc.keymap, a[0]))
- continue;
+ if (!streq(vc->keymap, a[0]))
+ continue;
- r = x11_context_copy(xc,
- &(X11Context) {
- .layout = empty_or_dash_to_null(a[1]),
- .model = empty_or_dash_to_null(a[2]),
- .variant = empty_or_dash_to_null(a[3]),
- .options = empty_or_dash_to_null(a[4]),
- });
- if (r < 0)
- return r;
- modified = r > 0;
+ r = x11_context_copy(ret,
+ &(X11Context) {
+ .layout = empty_or_dash_to_null(a[1]),
+ .model = empty_or_dash_to_null(a[2]),
+ .variant = empty_or_dash_to_null(a[3]),
+ .options = empty_or_dash_to_null(a[4]),
+ });
+ if (r < 0)
+ return r;
- break;
- }
+ log_info("The virtual console keymap '%s' is converted to X11 keyboard layout '%s' model '%s' variant '%s' options '%s'",
+ vc->keymap, strempty(ret->layout), strempty(ret->model), strempty(ret->variant), strempty(ret->options));
+ return 0;
}
-
- if (modified > 0)
- log_info("Changing X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
- strempty(xc->layout),
- strempty(xc->model),
- strempty(xc->variant),
- strempty(xc->options));
- else if (modified < 0)
- log_notice("X11 keyboard layout was not modified: no conversion found for \"%s\".",
- c->vc.keymap);
- else
- log_debug("X11 keyboard layout did not need to be modified.");
-
- return modified > 0;
}
int find_converted_keymap(const X11Context *xc, char **ret) {
}
}
-int x11_convert_to_vconsole(Context *c) {
- bool modified = false;
- const X11Context *xc;
-
- assert(c);
+int x11_convert_to_vconsole(const X11Context *xc, VCContext *ret) {
+ _cleanup_free_ char *keymap = NULL;
+ int r;
- xc = context_get_x11_context_safe(c);
+ assert(xc);
+ assert(ret);
if (isempty(xc->layout)) {
- modified = !vc_context_isempty(&c->vc);
- vc_context_clear(&c->vc);
- } else {
- _cleanup_free_ char *new_keymap = NULL;
- int r;
-
- r = find_converted_keymap(xc, &new_keymap);
- if (r == 0)
- r = find_legacy_keymap(xc, &new_keymap);
- if (r < 0)
- return r;
- if (r == 0)
- /* We search for layout-variant match first, but then we also look
- * for anything which matches just the layout. So it's accurate to say
- * that we couldn't find anything which matches the layout. */
- log_notice("No conversion to virtual console map found for \"%s\".", xc->layout);
-
- if (!streq_ptr(c->vc.keymap, new_keymap)) {
- vc_context_clear(&c->vc);
- c->vc.keymap = TAKE_PTR(new_keymap);
- modified = true;
- }
+ *ret = (VCContext) {};
+ return 0;
}
- if (modified)
- log_info("Changing virtual console keymap to '%s' toggle '%s'",
- strempty(c->vc.keymap), strempty(c->vc.toggle));
+ r = find_converted_keymap(xc, &keymap);
+ if (r == 0)
+ r = find_legacy_keymap(xc, &keymap);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ /* We search for layout-variant match first, but then we also look
+ * for anything which matches just the layout. So it's accurate to say
+ * that we couldn't find anything which matches the layout. */
+ log_notice("No conversion to virtual console map found for \"%s\".", xc->layout);
else
- log_debug("Virtual console keymap was not modified.");
+ log_info("The X11 keyboard layout '%s' is converted to virtual console keymap '%s'",
+ xc->layout, strempty(keymap));
- return modified;
+ *ret = (VCContext) {
+ .keymap = TAKE_PTR(keymap),
+ };
+ return 0;
}
bool locale_gen_check_available(void) {
}
TEST(vconsole_convert_to_x11) {
- _cleanup_(context_clear) Context c = {};
- X11Context *xc = &c.x11_from_vc;
+ _cleanup_(x11_context_clear) X11Context xc = {};
+ _cleanup_(vc_context_clear) VCContext vc = {};
- log_info("/* test emptying first (:) */");
- assert_se(free_and_strdup(&xc->layout, "foo") >= 0);
- assert_se(free_and_strdup(&xc->variant, "bar") >= 0);
- assert_se(vconsole_convert_to_x11(&c) == 1);
- assert_se(xc->layout == NULL);
- assert_se(xc->variant == NULL);
-
- log_info("/* test emptying second (:) */");
-
- assert_se(vconsole_convert_to_x11(&c) == 0);
- assert_se(xc->layout == NULL);
- assert_se(xc->variant == NULL);
+ log_info("/* test empty keymap */");
+ assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
+ assert_se(x11_context_isempty(&xc));
log_info("/* test without variant, new mapping (es:) */");
- assert_se(free_and_strdup(&c.vc.keymap, "es") >= 0);
-
- assert_se(vconsole_convert_to_x11(&c) == 1);
- assert_se(streq(xc->layout, "es"));
- assert_se(xc->variant == NULL);
+ assert_se(free_and_strdup(&vc.keymap, "es") >= 0);
+ assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
+ assert_se(streq(xc.layout, "es"));
+ assert_se(xc.variant == NULL);
+ x11_context_clear(&xc);
log_info("/* test with known variant, new mapping (es:dvorak) */");
- assert_se(free_and_strdup(&c.vc.keymap, "es-dvorak") >= 0);
-
- assert_se(vconsole_convert_to_x11(&c) == 1);
- assert_se(streq(xc->layout, "es"));
- assert_se(streq(xc->variant, "dvorak"));
+ assert_se(free_and_strdup(&vc.keymap, "es-dvorak") >= 0);
+ assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
+ assert_se(streq(xc.layout, "es"));
+ assert_se(streq(xc.variant, "dvorak"));
+ x11_context_clear(&xc);
log_info("/* test with old mapping (fr:latin9) */");
- assert_se(free_and_strdup(&c.vc.keymap, "fr-latin9") >= 0);
-
- assert_se(vconsole_convert_to_x11(&c) == 1);
- assert_se(streq(xc->layout, "fr"));
- assert_se(streq(xc->variant, "latin9"));
+ assert_se(free_and_strdup(&vc.keymap, "fr-latin9") >= 0);
+ assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
+ assert_se(streq(xc.layout, "fr"));
+ assert_se(streq(xc.variant, "latin9"));
+ x11_context_clear(&xc);
log_info("/* test with a compound mapping (ru,us) */");
- assert_se(free_and_strdup(&c.vc.keymap, "ru") >= 0);
-
- assert_se(vconsole_convert_to_x11(&c) == 1);
- assert_se(streq(xc->layout, "ru,us"));
- assert_se(xc->variant == NULL);
+ assert_se(free_and_strdup(&vc.keymap, "ru") >= 0);
+ assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
+ assert_se(streq(xc.layout, "ru,us"));
+ assert_se(xc.variant == NULL);
+ x11_context_clear(&xc);
log_info("/* test with a simple mapping (us) */");
- assert_se(free_and_strdup(&c.vc.keymap, "us") >= 0);
-
- assert_se(vconsole_convert_to_x11(&c) == 1);
- assert_se(streq(xc->layout, "us"));
- assert_se(xc->variant == NULL);
+ assert_se(free_and_strdup(&vc.keymap, "us") >= 0);
+ assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
+ assert_se(streq(xc.layout, "us"));
+ assert_se(xc.variant == NULL);
}
TEST(x11_convert_to_vconsole) {
- _cleanup_(context_clear) Context c = {};
- X11Context *xc = &c.x11_from_xorg;
- int r;
-
- log_info("/* test emptying first (:) */");
- assert_se(free_and_strdup(&c.vc.keymap, "foobar") >= 0);
- assert_se(x11_convert_to_vconsole(&c) == 1);
- assert_se(c.vc.keymap == NULL);
-
- log_info("/* test emptying second (:) */");
+ _cleanup_(x11_context_clear) X11Context xc = {};
+ _cleanup_(vc_context_clear) VCContext vc = {};
- assert_se(x11_convert_to_vconsole(&c) == 0);
- assert_se(c.vc.keymap == NULL);
+ log_info("/* test empty layout (:) */");
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(vc_context_isempty(&vc));
log_info("/* test without variant, new mapping (es:) */");
- assert_se(free_and_strdup(&xc->layout, "es") >= 0);
-
- assert_se(x11_convert_to_vconsole(&c) == 1);
- assert_se(streq(c.vc.keymap, "es"));
+ assert_se(free_and_strdup(&xc.layout, "es") >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(streq(vc.keymap, "es"));
+ vc_context_clear(&vc);
log_info("/* test with unknown variant, new mapping (es:foobar) */");
- assert_se(free_and_strdup(&xc->variant, "foobar") >= 0);
-
- assert_se(x11_convert_to_vconsole(&c) == 0);
- assert_se(streq(c.vc.keymap, "es"));
+ assert_se(free_and_strdup(&xc.variant, "foobar") >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(streq(vc.keymap, "es"));
+ vc_context_clear(&vc);
log_info("/* test with known variant, new mapping (es:dvorak) */");
- assert_se(free_and_strdup(&xc->variant, "dvorak") >= 0);
-
- r = x11_convert_to_vconsole(&c);
- if (r == 0) {
+ assert_se(free_and_strdup(&xc.variant, "dvorak") >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ if (vc_context_isempty(&vc)) {
log_info("Skipping rest of %s: keymaps are not installed", __func__);
return;
}
-
- assert_se(r == 1);
- assert_se(streq(c.vc.keymap, "es-dvorak"));
+ assert_se(streq(vc.keymap, "es-dvorak"));
+ vc_context_clear(&vc);
log_info("/* test with old mapping (fr:latin9) */");
- assert_se(free_and_strdup(&xc->layout, "fr") >= 0);
- assert_se(free_and_strdup(&xc->variant, "latin9") >= 0);
-
- assert_se(x11_convert_to_vconsole(&c) == 1);
- assert_se(streq(c.vc.keymap, "fr-latin9"));
+ assert_se(free_and_strdup(&xc.layout, "fr") >= 0);
+ assert_se(free_and_strdup(&xc.variant, "latin9") >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(streq(vc.keymap, "fr-latin9"));
+ vc_context_clear(&vc);
log_info("/* test with a compound mapping (us,ru:) */");
- assert_se(free_and_strdup(&xc->layout, "us,ru") >= 0);
- assert_se(free_and_strdup(&xc->variant, NULL) >= 0);
-
- assert_se(x11_convert_to_vconsole(&c) == 1);
- assert_se(streq(c.vc.keymap, "us"));
+ assert_se(free_and_strdup(&xc.layout, "us,ru") >= 0);
+ assert_se(free_and_strdup(&xc.variant, NULL) >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(streq(vc.keymap, "us"));
+ vc_context_clear(&vc);
log_info("/* test with a compound mapping (ru,us:) */");
- assert_se(free_and_strdup(&xc->layout, "ru,us") >= 0);
- assert_se(free_and_strdup(&xc->variant, NULL) >= 0);
-
- assert_se(x11_convert_to_vconsole(&c) == 1);
- assert_se(streq(c.vc.keymap, "ru"));
+ assert_se(free_and_strdup(&xc.layout, "ru,us") >= 0);
+ assert_se(free_and_strdup(&xc.variant, NULL) >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(streq(vc.keymap, "ru"));
+ vc_context_clear(&vc);
/* https://bugzilla.redhat.com/show_bug.cgi?id=1333998 */
log_info("/* test with a simple new mapping (ru:) */");
- assert_se(free_and_strdup(&xc->layout, "ru") >= 0);
- assert_se(free_and_strdup(&xc->variant, NULL) >= 0);
-
- assert_se(x11_convert_to_vconsole(&c) == 0);
- assert_se(streq(c.vc.keymap, "ru"));
+ assert_se(free_and_strdup(&xc.layout, "ru") >= 0);
+ assert_se(free_and_strdup(&xc.variant, NULL) >= 0);
+ assert_se(x11_convert_to_vconsole(&xc, &vc) >= 0);
+ assert_se(streq(vc.keymap, "ru"));
}
static int intro(void) {