summaryrefslogtreecommitdiff
path: root/src/locale/localed.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-11-24 15:12:42 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2014-11-24 15:16:33 +0100
commitd4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62 (patch)
tree54e891570c54a505a6babdefc95169d1efb1aaa2 /src/locale/localed.c
parent8a52210c9392887a31fdb2845f65b4c5869e8e66 (diff)
localed: validate xkb keymaps
Introduce a new optional dependency on libxkbcommon for systemd-localed. Whenever the x11 keymap settings are changed, use libxkbcommon to compile the keymap. If the compilation fails, print a warning so users will get notified. On compilation failure, we still update the keymap settings for now. This patch just introduces the xkbcommon infrastructure to have keymap validation in place. We can later decide if/how we want to enforce this.
Diffstat (limited to 'src/locale/localed.c')
-rw-r--r--src/locale/localed.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 9377ce5015..4e56382f4f 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -41,6 +41,10 @@
#include "event-util.h"
#include "locale-util.h"
+#ifdef HAVE_XKBCOMMON
+#include <xkbcommon/xkbcommon.h>
+#endif
+
enum {
/* We don't list LC_ALL here on purpose. People should be
* using LANG instead. */
@@ -1005,6 +1009,51 @@ static int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata
return sd_bus_reply_method_return(m, NULL);
}
+#ifdef HAVE_XKBCOMMON
+static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
+ /* suppress xkb messages for now */
+}
+
+static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
+ const struct xkb_rule_names rmlvo = {
+ .model = model,
+ .layout = layout,
+ .variant = variant,
+ .options = options,
+ };
+ struct xkb_context *ctx = NULL;
+ struct xkb_keymap *km = NULL;
+ int r;
+
+ /* compile keymap from RMLVO information to check out its validity */
+
+ ctx = xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
+ if (!ctx) {
+ r = -ENOMEM;
+ goto exit;
+ }
+
+ xkb_context_set_log_fn(ctx, log_xkb);
+
+ km = xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!km) {
+ r = -EINVAL;
+ goto exit;
+ }
+
+ r = 0;
+
+exit:
+ xkb_keymap_unref(km);
+ xkb_context_unref(ctx);
+ return r;
+}
+#else
+static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
+ return 0;
+}
+#endif
+
static int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
const char *layout, *model, *variant, *options;
@@ -1038,6 +1087,11 @@ static int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdat
(options && !string_is_safe(options)))
return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data");
+ r = verify_xkb_rmlvo(model, layout, variant, options);
+ if (r < 0)
+ log_warning("Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %s",
+ strempty(model), strempty(layout), strempty(variant), strempty(options), strerror(-r));
+
r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, &c->polkit_registry, error);
if (r < 0)
return r;