localed.c revision 502f961425f9dea1a85239766a3189695194da63
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering This file is part of systemd.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Copyright 2011 Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Copyright 2013 Kay Sievers
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering (at your option) any later version.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is distributed in the hope that it will be useful, but
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Lesser General Public License for more details.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering You should have received a copy of the GNU Lesser General Public License
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
cec736d21ff86c4ac81b4d306ddba2120333818cLennart Poettering /* We don't list LC_ALL here on purpose. People should be
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering * using LANG instead. */
e6520a0fcebb4d5e07f4c81a51382501b0beb22fLennart Poetteringstatic const char * const names[_LOCALE_MAX] = {
de97b26ac5e29063632312ec1a20eb6318ca924cLennart Poettering [LOCALE_LC_MEASUREMENT] = "LC_MEASUREMENT",
9cfb57c989b62d11c073c77179df4bb7fa19f35dLennart Poettering [LOCALE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart Poetteringtypedef struct Context {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poetteringstatic const char* nonempty(const char *s) {
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poetteringstatic void free_and_replace(char **s, char *v) {
9cfb57c989b62d11c073c77179df4bb7fa19f35dLennart Poetteringstatic void context_free_x11(Context *c) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poetteringstatic void context_free_vconsole(Context *c) {
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering free_and_replace(&c->vc_keymap_toggle, NULL);
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poetteringstatic void context_free_locale(Context *c) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering for (p = 0; p < _LOCALE_MAX; p++)
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering bus_verify_polkit_async_registry_free(c->polkit_registry);
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering for (p = LOCALE_LANG+1; p < _LOCALE_MAX; p++)
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering if (isempty(c->locale[p]) || streq_ptr(c->locale[LOCALE_LANG], c->locale[p]))
c042179388f329fb1e45b00e1a533a0dc27fb9aeLennart Poettering r = parse_env_file("/etc/locale.conf", NEWLINE,
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering "LC_NUMERIC", &c->locale[LOCALE_LC_NUMERIC],
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering "LC_COLLATE", &c->locale[LOCALE_LC_COLLATE],
a3a52c0fd0c2597bf8233730c3ed3408affe0c9fLennart Poettering "LC_MONETARY", &c->locale[LOCALE_LC_MONETARY],
a3a52c0fd0c2597bf8233730c3ed3408affe0c9fLennart Poettering "LC_MESSAGES", &c->locale[LOCALE_LC_MESSAGES],
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering "LC_ADDRESS", &c->locale[LOCALE_LC_ADDRESS],
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering "LC_TELEPHONE", &c->locale[LOCALE_LC_TELEPHONE],
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering "LC_MEASUREMENT", &c->locale[LOCALE_LC_MEASUREMENT],
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering "LC_IDENTIFICATION", &c->locale[LOCALE_LC_IDENTIFICATION],
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering /* Fill in what we got passed from systemd. */
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering for (p = 0; p < _LOCALE_MAX; p++) {
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poetteringstatic int vconsole_read_data(Context *c) {
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering r = parse_env_file("/etc/vconsole.conf", NEWLINE,
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering if (r < 0 && r != -ENOENT)
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (l[0] == 0 || l[0] == '#')
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (in_section && first_word(l, "Option")) {
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering } else if (!in_section && first_word(l, "Section")) {
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (strv_length(a) == 2 && streq(a[1], "InputClass"))
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering } else if (in_section && first_word(l, "EndSection"))
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poetteringstatic int context_read_data(Context *c) {
3fbf9cbb02690e40cd65802e777519f3f3c8d88aLennart Poettering return r < 0 ? r : q < 0 ? q : p;
3fbf9cbb02690e40cd65802e777519f3f3c8d88aLennart Poetteringstatic int locale_write_data(Context *c, char ***settings) {
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering /* Set values will be returned as strv in *settings on success. */
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering r = load_env_file(NULL, "/etc/locale.conf", NULL, &l);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (r < 0 && r != -ENOENT)
cab8ac60837b489b27a247990f741315c71cb389Lennart Poettering for (p = 0; p < _LOCALE_MAX; p++) {
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0)
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering r = write_env_file_label("/etc/locale.conf", l);
5e62067d08d989ab98b12497a9b27a877de8515bLennart Poetteringstatic int locale_update_system_manager(Context *c, sd_bus *bus) {
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering for (p = 0, c_set = 0, c_unset = 0; p < _LOCALE_MAX; p++) {
5e62067d08d989ab98b12497a9b27a877de8515bLennart Poettering if (asprintf(&s, "%s=%s", names[p], c->locale[p]) < 0)
b1a0ab714863ae77e4683820757b3f49c03a0049Lennart Poettering r = sd_bus_message_new_method_call(bus, &m,
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering "org.freedesktop.systemd1.Manager",
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering "UnsetAndSetEnvironment");
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering r = sd_bus_message_append_strv(m, l_unset);
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering r = sd_bus_message_append_strv(m, l_set);
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering r = sd_bus_call(bus, m, 0, &error, NULL);
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering log_error("Failed to update the manager environment: %s", strerror(-r));
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poetteringstatic int vconsole_write_data(Context *c) {
99add6fd0b8f4307ed79256e25f38da318e795c4Lennart Poettering r = load_env_file(NULL, "/etc/vconsole.conf", NULL, &l);
0d0f0c50d3a1d90f03972a6abb82e6413daaa583Shawn Landden if (r < 0 && r != -ENOENT)
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
783d2675eff73d1937bf8f78b368b1004c2d28c5Lennart Poettering return write_env_file_label("/etc/vconsole.conf", l);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering mkdir_p_label("/etc/X11/xorg.conf.d", 0755);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
c2a623d842af3a4d67e1f4e365f6d6a47f1c6cb4Lennart Poettering fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n"
c2a623d842af3a4d67e1f4e365f6d6a47f1c6cb4Lennart Poettering "# manually too freely.\n"
c2a623d842af3a4d67e1f4e365f6d6a47f1c6cb4Lennart Poettering "Section \"InputClass\"\n"
c2a623d842af3a4d67e1f4e365f6d6a47f1c6cb4Lennart Poettering " Identifier \"system-keyboard\"\n"
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering " MatchIsKeyboard \"on\"\n", f);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options);
71fa6f006f92831c0c02e844b4c35e4b7197c6d6Lennart Poettering if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering unlink("/etc/X11/xorg.conf.d/00-keyboard.conf");
71fa6f006f92831c0c02e844b4c35e4b7197c6d6Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
32fca2d5b746b86bbbbd4f1b57064076cfc2ae4bLennart Poettering "org.freedesktop.systemd1.Manager",
32fca2d5b746b86bbbbd4f1b57064076cfc2ae4bLennart Poettering "RestartUnit",
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering "ss", "systemd-vconsole-setup.service", "replace");
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poetteringstatic const char* strnulldash(const char *s) {
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering return isempty(s) || streq(s, "-") ? NULL : s;
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poetteringstatic int read_next_mapping(FILE *f, unsigned *n, char ***a) {
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering if (l[0] == 0 || l[0] == '#')
de190aef08bb267b645205a747762df573b36834Lennart Poettering log_error("Invalid line "SYSTEMD_KBD_MODEL_MAP":%u, ignoring.", *n);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic int vconsole_convert_to_x11(Context *c, sd_bus *bus) {
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering unsigned n = 0;
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering if (!streq_ptr(c->x11_layout, strnulldash(a[1])) ||
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering !streq_ptr(c->x11_model, strnulldash(a[2])) ||
69e5d42db09dfb638bc74055c33bb2645f81563dLennart Poettering !streq_ptr(c->x11_variant, strnulldash(a[3])) ||
69e5d42db09dfb638bc74055c33bb2645f81563dLennart Poettering !streq_ptr(c->x11_options, strnulldash(a[4]))) {
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering if (free_and_strdup(&c->x11_layout, strnulldash(a[1])) < 0 ||
ba1261bc02693ac8a7712ade14aab8e22989ba88Lennart Poettering free_and_strdup(&c->x11_model, strnulldash(a[2])) < 0 ||
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering free_and_strdup(&c->x11_variant, strnulldash(a[3])) < 0 ||
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering free_and_strdup(&c->x11_options, strnulldash(a[4])) < 0)
62bca2c657bf95fd1f69935eef09915afa5c69d9Eelco Dolstra log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering "org.freedesktop.locale1",
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
8a0f04e6a283cc6734ee09a20305c13e09ba0418Lennart Poettering log_debug("X11 keyboard layout was not modified.");
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poetteringstatic int find_converted_keymap(Context *c, char **new_keymap) {
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering n = strjoin(c->x11_layout, "-", c->x11_variant, NULL);
de190aef08bb267b645205a747762df573b36834Lennart Poettering _cleanup_free_ char *p = NULL, *pz = NULL;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering p = strjoin(dir, "xkb/", n, ".map", NULL);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering pz = strjoin(dir, "xkb/", n, ".map.gz", NULL);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if (uncompressed || access(pz, F_OK) == 0) {
de190aef08bb267b645205a747762df573b36834Lennart Poettering log_debug("Found converted keymap %s at %s",
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic int find_legacy_keymap(Context *c, char **new_keymap) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering unsigned n = 0;
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering /* Determine how well matching this entry is */
94fb446e55babb713fb24850455627acf30d999bLennart Poettering /* If we got an exact match, this is best */
33eb8abfa51d5bffbf8819215fafdd1123a4a8c0Lennart Poettering /* We have multiple X layouts, look for an
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering * entry that matches our key with everything
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering * but the first layout stripped off. */
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering /* If that didn't work, strip off the
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering * other layouts from the entry, too */
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering if (x > 0 && x == w &&
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering if (isempty(c->x11_model) || streq_ptr(c->x11_model, a[2])) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* The best matching entry so far, then let's save that */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (matching >= MAX(best_matching, 1u)) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_debug("Found legacy keymap %s with score %u",
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poetteringstatic int x11_convert_to_vconsole(Context *c, sd_bus *bus) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering r = find_converted_keymap(c, &new_keymap);
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering else if (r == 0) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering if (!streq_ptr(c->vc_keymap, new_keymap)) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering free_and_replace(&c->vc_keymap, new_keymap);
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering free_and_replace(&c->vc_keymap_toggle, NULL);
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering log_error("Failed to set virtual console keymap: %s", strerror(-r));
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering log_info("Changed virtual console keymap to '%s' toggle '%s'",
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering strempty(c->vc_keymap), strempty(c->vc_keymap_toggle));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering "org.freedesktop.locale1",
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_debug("Virtual console keymap was not modified.");
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering for (p = 0, q = 0; p < _LOCALE_MAX; p++) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0)
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering return sd_bus_message_append_strv(reply, l);
adf7d506b50af9ba398a9925c8cd47ba328e720cLennart Poetteringstatic int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = sd_bus_message_read_basic(m, 'b', &interactive);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering /* Check whether a variable changed and if it is valid */
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering for (p = 0; p < _LOCALE_MAX; p++) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering (*i)[k] == '=' &&
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering if (!streq_ptr(*i + k + 1, c->locale[p]))
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering /* Check whether a variable is unset */
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering for (p = 0; p < _LOCALE_MAX; p++)
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering if (!isempty(c->locale[p]) && !passed[p]) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering _cleanup_strv_free_ char **settings = NULL;
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-locale", interactive, &c->polkit_registry, error);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart Poettering for (p = 0; p < _LOCALE_MAX; p++) {
54a7b863dd3937893abae47b20b6f655b8e9252aLennart Poettering if (startswith(*i, names[p]) && (*i)[k] == '=') {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = free_and_strdup(&c->locale[p], *i + k + 1);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering for (p = 0; p < _LOCALE_MAX; p++) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Failed to set locale: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to set locale: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_info("Changed locale to %s.", strnull(line));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering "org.freedesktop.locale1",
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_debug("Locale settings were not modified.");
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering return sd_bus_reply_method_return(m, NULL);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poetteringstatic int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = sd_bus_message_read(m, "ssbb", &keymap, &keymap_toggle, &convert, &interactive);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering !streq_ptr(keymap_toggle, c->vc_keymap_toggle)) {
ba6b3039531a70466dd955c6faa9bf521b3dfbacLennart Poettering if ((keymap && (!filename_is_safe(keymap) || !string_is_safe(keymap))) ||
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle))))
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keymap data");
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, &c->polkit_registry, error);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (free_and_strdup(&c->vc_keymap, keymap) < 0 ||
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering log_error("Failed to set virtual console keymap: %s", strerror(-r));
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %s", strerror(-r));
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering log_info("Changed virtual console keymap to '%s' toggle '%s'",
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering strempty(c->vc_keymap), strempty(c->vc_keymap_toggle));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Failed to request keymap reload: %s", strerror(-r));
ba6b3039531a70466dd955c6faa9bf521b3dfbacLennart Poettering "org.freedesktop.locale1",
ba6b3039531a70466dd955c6faa9bf521b3dfbacLennart Poettering "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Failed to convert keymap data: %s", strerror(-r));
51abe64c859c01ffad4f80840396ad9f6d5c9e62Lennart Poettering return sd_bus_reply_method_return(m, NULL);
6c1e6b98bde8288d65d7cddf87ff9bedf94a3e1cLennart Poetteringstatic int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
6c1e6b98bde8288d65d7cddf87ff9bedf94a3e1cLennart Poettering const char *layout, *model, *variant, *options;
6c1e6b98bde8288d65d7cddf87ff9bedf94a3e1cLennart Poettering r = sd_bus_message_read(m, "ssssbb", &layout, &model, &variant, &options, &convert, &interactive);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if ((layout && !string_is_safe(layout)) ||
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data");
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, &c->polkit_registry, error);
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if (free_and_strdup(&c->x11_layout, layout) < 0 ||
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering free_and_strdup(&c->x11_model, model) < 0 ||
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering free_and_strdup(&c->x11_variant, variant) < 0 ||
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering free_and_strdup(&c->x11_options, options) < 0)
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %s", strerror(-r));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "org.freedesktop.locale1",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_error("Failed to convert keymap data: %s", strerror(-r));
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering return sd_bus_reply_method_return(m, NULL);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic const sd_bus_vtable locale_vtable[] = {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("Locale", "as", property_get_locale, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("X11Layout", "s", NULL, offsetof(Context, x11_layout), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("X11Model", "s", NULL, offsetof(Context, x11_model), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("X11Variant", "s", NULL, offsetof(Context, x11_variant), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("X11Options", "s", NULL, offsetof(Context, x11_options), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("VConsoleKeymap", "s", NULL, offsetof(Context, vc_keymap), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", NULL, offsetof(Context, vc_keymap_toggle), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, SD_BUS_VTABLE_UNPRIVILEGED),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, SD_BUS_VTABLE_UNPRIVILEGED),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, SD_BUS_VTABLE_UNPRIVILEGED),
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering _cleanup_bus_close_unref_ sd_bus *bus = NULL;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering log_error("Failed to get system bus connection: %s", strerror(-r));
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering log_error("Failed to register object: %s", strerror(-r));
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering r = sd_bus_request_name(bus, "org.freedesktop.locale1", 0);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering log_error("Failed to register name: %s", strerror(-r));
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering log_error("Failed to attach bus to event loop: %s", strerror(-r));
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering _cleanup_(context_free) Context context = {};
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering _cleanup_event_unref_ sd_event *event = NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering _cleanup_bus_close_unref_ sd_bus *bus = NULL;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("This program takes no arguments.");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("Failed to allocate event loop: %s", strerror(-r));
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("Failed to read locale data: %s", strerror(-r));
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = bus_event_loop_with_idle(event, bus, "org.freedesktop.locale1", DEFAULT_EXIT_USEC, NULL, NULL);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("Failed to run event loop: %s", strerror(-r));