[systemd-devel] [PATCH 2/2] localectl: verify layout, model, variant and options
Jan Synacek
jsynacek at redhat.com
Mon Oct 20 03:43:40 PDT 2014
When setting any of those using set-x11-keymap, check that their values
are available on the system.
---
src/locale/localectl.c | 208 +++++++++++++++++++++++++++++++++----------------
1 file changed, 139 insertions(+), 69 deletions(-)
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 3690f9f..0caf467 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -53,6 +53,14 @@ static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static char *arg_host = NULL;
static bool arg_convert = true;
+enum keymap_state {
+ NONE,
+ MODELS = 1 << 0,
+ LAYOUTS = 1 << 1,
+ VARIANTS = 1 << 2,
+ OPTIONS = 1 << 3
+};
+
static void pager_open_if_enabled(void) {
if (arg_no_pager)
@@ -350,59 +358,12 @@ static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *layout, *model, *variant, *options;
- int r;
-
- assert(bus);
- assert(args);
-
- if (n > 5) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- polkit_agent_open_if_enabled();
-
- layout = args[1];
- model = n > 2 ? args[2] : "";
- variant = n > 3 ? args[3] : "";
- options = n > 4 ? args[4] : "";
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.locale1",
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "SetX11Keyboard",
- &error,
- NULL,
- "ssssbb", layout, model, variant, options,
- arg_convert, arg_ask_password);
- if (r < 0)
- log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
-
- return r;
-}
-
-static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
+static int get_x11_keymaps_internal(char ***list, enum keymap_state look_for, const char *layout)
+{
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_strv_free_ char **list = NULL;
char line[LINE_MAX];
- enum {
- NONE,
- MODELS,
- LAYOUTS,
- VARIANTS,
- OPTIONS
- } state = NONE, look_for;
- int r;
-
- if (n > 2) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
+ enum keymap_state state = NONE;
+ int r = 0;
f = fopen("/usr/share/X11/xkb/rules/base.lst", "re");
if (!f) {
@@ -410,17 +371,6 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
return -errno;
}
- if (streq(args[0], "list-x11-keymap-models"))
- look_for = MODELS;
- else if (streq(args[0], "list-x11-keymap-layouts"))
- look_for = LAYOUTS;
- else if (streq(args[0], "list-x11-keymap-variants"))
- look_for = VARIANTS;
- else if (streq(args[0], "list-x11-keymap-options"))
- look_for = OPTIONS;
- else
- assert_not_reached("Wrong parameter");
-
FOREACH_LINE(line, f, break) {
char *l, *w;
@@ -444,12 +394,12 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
continue;
}
- if (state != look_for)
+ if (!(state & look_for))
continue;
w = l + strcspn(l, WHITESPACE);
- if (n > 1) {
+ if (layout) {
char *e;
if (*w == 0)
@@ -465,23 +415,143 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
*e = 0;
- if (!streq(w, args[1]))
+ if (!streq(w, layout))
continue;
} else
*w = 0;
- r = strv_extend(&list, l);
+ r = strv_extend(list, l);
if (r < 0)
return log_oom();
}
- if (strv_isempty(list)) {
+ if (strv_isempty(*list)) {
log_error("Couldn't find any entries.");
return -ENOENT;
}
- strv_sort(list);
- strv_uniq(list);
+ strv_sort(*list);
+ strv_uniq(*list);
+
+ return r;
+}
+
+static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_strv_free_ char **list = NULL, **layouts = NULL, **variants = NULL, **options = NULL;
+ char **it;
+ const char *layouts_arg, *variants_arg, *options_arg;
+ const char *model;
+ enum keymap_state look_for;
+ int r;
+
+ assert(bus);
+ assert(args);
+
+ if (n > 5) {
+ log_error("Too many arguments.");
+ return -EINVAL;
+ }
+
+ polkit_agent_open_if_enabled();
+
+ layouts_arg = args[1];
+ model = n > 2 ? args[2] : "";
+ variants_arg = n > 3 ? args[3] : "";
+ options_arg = n > 4 ? args[4] : "";
+
+ look_for = LAYOUTS;
+ layouts = strv_split(layouts_arg, ",");
+ if (!layouts)
+ return log_oom();
+
+ if (!streq(variants_arg, "")) {
+ look_for |= VARIANTS;
+ variants = strv_split(variants_arg, ",");
+ if (!variants)
+ return log_oom();
+ }
+
+ if (!streq(options_arg, "")) {
+ look_for |= OPTIONS;
+ options = strv_split(options_arg, ",");
+ if (!options)
+ return log_oom();
+ }
+
+ look_for |= !streq(model, "") * MODELS;
+
+ r = get_x11_keymaps_internal(&list, look_for, NULL);
+
+ STRV_FOREACH(it, layouts)
+ if (!strv_find(list, *it)) {
+ fprintf(stderr, "Requested layout '%s' not available.\n", *it);
+ return -EINVAL;
+ }
+
+
+ if (variants)
+ STRV_FOREACH(it, variants)
+ if ((look_for & VARIANTS) && !strv_find(list, *it)) {
+ fprintf(stderr, "Requested variant '%s' not available.\n", *it);
+ return -EINVAL;
+ }
+
+ if (options)
+ STRV_FOREACH(it, options)
+ if ((look_for & OPTIONS) && !strv_find(list, *it)) {
+ fprintf(stderr, "Requested options '%s' not available.\n", *it);
+ return -EINVAL;
+ }
+
+ if ((look_for & MODELS) && !strv_find(list, model)) {
+ fprintf(stderr, "Requested model '%s' not available.\n", model);
+ return -EINVAL;
+ }
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.locale1",
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "SetX11Keyboard",
+ &error,
+ NULL,
+ "ssssbb", layouts_arg, model, variants_arg, options_arg,
+ arg_convert, arg_ask_password);
+ if (r < 0)
+ log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
+
+ return r;
+}
+
+
+static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
+ _cleanup_strv_free_ char **list = NULL;
+ const char *layout;
+ enum keymap_state look_for;
+ int r;
+
+ if (n > 2) {
+ log_error("Too many arguments.");
+ return -EINVAL;
+ }
+
+ if (streq(args[0], "list-x11-keymap-models"))
+ look_for = MODELS;
+ else if (streq(args[0], "list-x11-keymap-layouts"))
+ look_for = LAYOUTS;
+ else if (streq(args[0], "list-x11-keymap-variants"))
+ look_for = VARIANTS;
+ else if (streq(args[0], "list-x11-keymap-options"))
+ look_for = OPTIONS;
+ else
+ assert_not_reached("Wrong parameter");
+
+ layout = (n == 2) ? args[1] : NULL;
+ r = get_x11_keymaps_internal(&list, look_for, layout);
+ if (r < 0)
+ return r;
pager_open_if_enabled();
--
1.9.3
More information about the systemd-devel
mailing list