#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. */
if (in_section && first_word(l, "Option")) {
_cleanup_strv_free_ char **a = NULL;
- r = strv_split_quoted(&a, l);
+ r = strv_split_quoted(&a, l, false);
if (r < 0)
return r;
} else if (!in_section && first_word(l, "Section")) {
_cleanup_strv_free_ char **a = NULL;
- r = strv_split_quoted(&a, l);
+ r = strv_split_quoted(&a, l, false);
if (r < 0)
return -ENOMEM;
return write_env_file_label("/etc/vconsole.conf", l);
}
-static int write_data_x11(Context *c) {
+static int x11_write_data(Context *c) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *temp_path = NULL;
int r;
if (l[0] == 0 || l[0] == '#')
continue;
- r = strv_split_quoted(&b, l);
+ r = strv_split_quoted(&b, l, false);
if (r < 0)
return r;
if (modified) {
int r;
- r = write_data_x11(c);
+ r = x11_write_data(c);
if (r < 0) {
log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
return r;
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;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ 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));
+
if (free_and_strdup(&c->x11_layout, layout) < 0 ||
free_and_strdup(&c->x11_model, model) < 0 ||
free_and_strdup(&c->x11_variant, variant) < 0 ||
free_and_strdup(&c->x11_options, options) < 0)
return -ENOMEM;
- r = write_data_x11(c);
+ r = x11_write_data(c);
if (r < 0) {
log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %s", strerror(-r));
log_open();
umask(0022);
- label_init("/etc");
+ mac_selinux_init("/etc");
if (argc != 1) {
log_error("This program takes no arguments.");