When setting any of those using set-x11-keymap, check that their values are available on the system. --- src/locale/localectl.c | 179 ++++++++++++++++++++++++++++++------------------- 1 file changed, 110 insertions(+), 69 deletions(-)
diff --git a/src/locale/localectl.c b/src/locale/localectl.c index 3690f9f..79bc2d0 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,114 @@ 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; + const char *layout, *model, *variant, *options; + 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(); + + layout = args[1]; + model = n > 2 ? args[2] : ""; + variant = n > 3 ? args[3] : ""; + options = n > 4 ? args[4] : ""; + + look_for = LAYOUTS; + look_for |= !streq(model, "") * MODELS | + !streq(variant, "") * VARIANTS | + !streq(options, "") * OPTIONS; + + r = get_x11_keymaps_internal(&list, look_for, NULL); + if (!strv_find(list, layout)) { + fprintf(stderr, "Requested layout '%s' not available.\n", layout); + return -EINVAL; + } + if ((look_for & MODELS) && !strv_find(list, model)) { + fprintf(stderr, "Requested model '%s' not available.\n", model); + return -EINVAL; + } + if ((look_for & VARIANTS) && !strv_find(list, variant)) { + fprintf(stderr, "Requested variant '%s' not available.\n", variant); + return -EINVAL; + } + if ((look_for & OPTIONS) && !strv_find(list, options)) { + fprintf(stderr, "Requested options '%s' not available.\n", options); + return -EINVAL; + } + + 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) { + _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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel