2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2012 Lennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers Copyright 2013 Kay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void polkit_agent_open_if_enabled(void) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Open the polkit agent as a child process if necessary */
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering if (arg_transport != BUS_TRANSPORT_LOCAL)
e7e55dbdc38f929805ab2407fbd50886043a9e7cDavid Herrmannstatic void status_info_clear(StatusInfo *info) {
ff9b60f38bf68eba4a47cabff14547d92e083214Torstein Husebøstatic void print_overridden_variables(void) {
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar r = parse_env_file("/proc/cmdline", WHITESPACE,
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_TIME", &variables[VARIABLE_LC_TIME],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_NAME", &variables[VARIABLE_LC_NAME],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (r < 0 && r != -ENOENT) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to read /proc/cmdline: %m");
63229aa1abdb98aa69fda9819ed2f40c8082762bLennart Poettering for (j = 0; j < _VARIABLE_LC_MAX; j++)
b344bcbbfda8fbe14dadc5aa4b5dfb3ced6d76e2Lennart Poettering log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
ff49bc3212cb07d850dcfd59940539773a0be26fMichal Schmidt " Command Line: %s=%s", locale_variable_to_string(j), variables[j]);
ff49bc3212cb07d850dcfd59940539773a0be26fMichal Schmidt log_warning(" %s=%s", locale_variable_to_string(j), variables[j]);
63229aa1abdb98aa69fda9819ed2f40c8082762bLennart Poettering for (j = 0; j < _VARIABLE_LC_MAX; j++)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void print_status_info(StatusInfo *i) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf(" System Locale: %s\n", i->locale[0]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf(" VC Keymap: %s\n", strna(i->vconsole_keymap));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf("VC Toggle Keymap: %s\n", i->vconsole_keymap_toggle);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf(" X11 Layout: %s\n", strna(i->x11_layout));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf(" X11 Model: %s\n", i->x11_model);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf(" X11 Variant: %s\n", i->x11_variant);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering printf(" X11 Options: %s\n", i->x11_options);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int show_status(sd_bus *bus, char **args, unsigned n) {
e7e55dbdc38f929805ab2407fbd50886043a9e7cDavid Herrmann _cleanup_(status_info_clear) StatusInfo info = {};
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers static const struct bus_properties_map map[] = {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "VConsoleKeymapToggle", "s", NULL, offsetof(StatusInfo, vconsole_keymap_toggle) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "X11Layout", "s", NULL, offsetof(StatusInfo, x11_layout) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "X11Model", "s", NULL, offsetof(StatusInfo, x11_model) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "X11Variant", "s", NULL, offsetof(StatusInfo, x11_variant) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "X11Options", "s", NULL, offsetof(StatusInfo, x11_options) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "Locale", "as", NULL, offsetof(StatusInfo, locale) },
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers "org.freedesktop.locale1",
e7e55dbdc38f929805ab2407fbd50886043a9e7cDavid Herrmann return log_error_errno(r, "Could not get properties: %m");
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int set_locale(sd_bus *bus, char **args, unsigned n) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "org.freedesktop.locale1",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "org.freedesktop.locale1",
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers r = sd_bus_message_append(m, "b", arg_ask_password);
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering r = sd_bus_call(bus, m, 0, &error, NULL);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (r < 0) {
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int list_locales(sd_bus *bus, char **args, unsigned n) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Failed to read list of locales: %m");
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "org.freedesktop.locale1",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "org.freedesktop.locale1",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "SetVConsoleKeyboard",
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers "ssbb", map, toggle_map, arg_convert, arg_ask_password);
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (r < 0 && r != -EEXIST)
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Can't add keymap: %m");
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Couldn't find any console keymaps.");
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *layout, *model, *variant, *options;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "org.freedesktop.locale1",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "org.freedesktop.locale1",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "SetX11Keyboard",
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
c62e11ce3966c55d23520b9f0785c7e839cf7f37Lennart Poettering f = fopen("/usr/share/X11/xkb/rules/base.lst", "re");
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to open keyboard mapping list. %m");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (streq(args[0], "list-x11-keymap-models"))
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else if (streq(args[0], "list-x11-keymap-layouts"))
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else if (streq(args[0], "list-x11-keymap-variants"))
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else if (streq(args[0], "list-x11-keymap-options"))
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (l[0] == '!') {
82c1d8f4eb74ddd9be2c9b9b56d9dc564c599effLennart Poettering "Query or change system locale and keyboard settings.\n\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " -h --help Show this help\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " --version Show package version\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " --no-pager Do not pipe output into a pager\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " --no-ask-password Do not prompt for password\n"
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers " -H --host=[USER@]HOST Operate on remote host\n"
a86a47ce1f63476631635fbcbc10af8877172114Lennart Poettering " -M --machine=CONTAINER Operate on local container\n"
a86a47ce1f63476631635fbcbc10af8877172114Lennart Poettering " --no-convert Don't convert keyboard mappings\n\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " status Show current locale settings\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " set-locale LOCALE... Set system locale\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " list-locales Show known locales\n"
2ebcf936702e8e511098711b4add885372360018Zbigniew Jędrzejewski-Szmek " set-keymap MAP [MAP] Set console and X11 keyboard mappings\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " list-keymaps Show known virtual console keyboard mappings\n"
31cf921abbeafc9dae2d5c777f3e2285e6f4c19dJan Synacek " set-x11-keymap LAYOUT [MODEL [VARIANT [OPTIONS]]]\n"
2ebcf936702e8e511098711b4add885372360018Zbigniew Jędrzejewski-Szmek " Set X11 and console keyboard mappings\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " list-x11-keymap-models Show known X11 keyboard mapping models\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " list-x11-keymap-layouts Show known X11 keyboard mapping layouts\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " list-x11-keymap-variants [LAYOUT]\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering " Show known X11 keyboard mapping variants\n"
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek " list-x11-keymap-options Show known X11 keyboard mapping options\n"
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek , program_invocation_short_name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers { "no-convert", no_argument, NULL, ARG_NO_CONVERT },
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sieversstatic int localectl_main(sd_bus *bus, int argc, char *argv[]) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering static const struct {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "list-locales", EQUAL, 1, list_locales },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "set-keymap", MORE, 2, set_vconsole_keymap },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "list-keymaps", EQUAL, 1, list_vconsole_keymaps },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "set-x11-keymap", MORE, 2, set_x11_keymap },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "list-x11-keymap-models", EQUAL, 1, list_x11_keymaps },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "list-x11-keymap-layouts", EQUAL, 1, list_x11_keymaps },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "list-x11-keymap-variants", LESS, 2, list_x11_keymaps },
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering { "list-x11-keymap-options", EQUAL, 1, list_x11_keymaps },
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Special rule: no arguments means "status" */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Unknown operation %s", argv[optind]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Invalid number of arguments.");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert_not_reached("Unknown comparison operator.");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return verbs[i].dispatch(bus, argv + optind, left);
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
266f3e269d173f104aa2a5e3ceac9b6979ea5039Lennart Poettering r = bus_connect_transport(arg_transport, arg_host, false, &bus);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to create bus connection: %m");