localed.c revision 0732ef7acf37473847992888bcb6446726d9d877
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers This file is part of systemd.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers Copyright 2011 Lennart Poettering
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Copyright 2013 Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers 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
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers (at your option) any later version.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers systemd is distributed in the hope that it will be useful, but
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* We don't list LC_ALL here on purpose. People should be
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * using LANG instead. */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieverstypedef struct Context {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int free_and_copy(char **s, const char *v) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void free_and_replace(char **s, char *v) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void context_free(Context *c, sd_bus *bus) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bus_verify_polkit_async_registry_free(bus, c->polkit_registry);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->locale[p]) || streq_ptr(c->locale[LOCALE_LANG], c->locale[p])) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_TELEPHONE", &c->locale[LOCALE_LC_TELEPHONE],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_MEASUREMENT", &c->locale[LOCALE_LC_MEASUREMENT],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_IDENTIFICATION", &c->locale[LOCALE_LC_IDENTIFICATION],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Fill in what we got passed from systemd. */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = free_and_copy(&c->locale[p], getenv(names[p]));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = parse_env_file("/etc/vconsole.conf", NEWLINE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (l[0] == 0 || l[0] == '#')
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (!in_section && first_word(l, "Section")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_length(a) == 2 && streq(a[1], "InputClass"))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (in_section && first_word(l, "EndSection"))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, q, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r < 0 ? r : q < 0 ? q : p;
f73141d7657b3f60b8669bc8386413d8a8a372c6Lennart Poettering r = load_env_file("/etc/locale.conf", NULL, &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t, **u;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0) {
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer r = write_env_file_label("/etc/locale.conf", l);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int locale_update_system_manager(Context *c, sd_bus *bus) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0, c_set = 0, c_unset = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (asprintf(&s, "%s=%s", names[p], c->locale[p]) < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.systemd1.Manager",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "UnsetAndSetEnvironment", &m);
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering r = sd_bus_call(bus, m, 0, &error, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to update the manager environment: %s", strerror(-r));
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **l = NULL;
f73141d7657b3f60b8669bc8386413d8a8a372c6Lennart Poettering r = load_env_file("/etc/vconsole.conf", NULL, &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s, **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s, **u;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer r = write_env_file_label("/etc/vconsole.conf", l);
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *temp_path = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
9a9bb3ca1eddc8caa2d7aa3e6e27d270e296923fMichał Bartoszkiewicz mkdir_p_label("/etc/X11/xorg.conf.d", 0755);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "# manually too freely.\n"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "Section \"InputClass\"\n"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " Identifier \"system-keyboard\"\n"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " MatchIsKeyboard \"on\"\n", f);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unlink("/etc/X11/xorg.conf.d/00-keyboard.conf");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.systemd1.Manager",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "RestartUnit",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "ss", "systemd-vconsole-setup.service", "replace");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic char *strnulldash(const char *s) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return s == NULL || *s == 0 || (s[0] == '-' && s[1] == 0) ? NULL : (char*) s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_next_mapping(FILE *f, unsigned *n, char ***a) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *l, **b;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (l[0] == 0 || l[0] == '#')
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Invalid line "SYSTEMD_KBD_MODEL_MAP":%u, ignoring.", *n);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int vconsole_convert_to_x11(Context *c, sd_bus *bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned n = 0;
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **a = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_next_mapping(f, &n, &a);
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek if (!streq(c->vc_keymap, a[0]))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!streq_ptr(c->x11_layout, strnulldash(a[1])) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(c->x11_variant, strnulldash(a[3])) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(c->x11_options, strnulldash(a[4]))) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (free_and_copy(&c->x11_layout, strnulldash(a[1])) < 0 ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_copy(&c->x11_model, strnulldash(a[2])) < 0 ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_copy(&c->x11_variant, strnulldash(a[3])) < 0 ||
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek free_and_copy(&c->x11_options, strnulldash(a[4])) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmekstatic int find_converted_keymap(Context *c, char **new_keymap) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek n = strjoin(c->x11_layout, "-", c->x11_variant, NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *p = NULL, *pz = NULL;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek p = strjoin(dir, "xkb/", n, ".map", NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek pz = strjoin(dir, "xkb/", n, ".map.gz", NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (access(p, F_OK) == 0 || access(pz, F_OK) == 0) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmekstatic int find_legacy_keymap(Context *c, char **new_keymap) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **a = NULL;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek r = read_next_mapping(f, &n, &a);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* Determine how well matching this entry is */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (streq_ptr(c->x11_layout, a[1]))
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* If we got an exact match, this is best */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek x = strcspn(c->x11_layout, ",");
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* We have multiple X layouts, look for an
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek * entry that matches our key with everything
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek * but the first layout stripped off. */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek strneq(c->x11_layout, a[1], x))
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* If that didn't work, strip off the
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek * other layouts from the entry, too */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (x > 0 && x == w &&
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek memcmp(c->x11_layout, a[1], x) == 0)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek streq_ptr(c->x11_model, a[2])) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (streq_ptr(c->x11_variant, a[3])) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (streq_ptr(c->x11_options, a[4]))
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* The best matching entry so far, then let's save that */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (matching > best_matching) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int x11_convert_to_vconsole(Context *c, sd_bus *bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek r = find_converted_keymap(c, &new_keymap);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek else if (r == 0) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek r = find_legacy_keymap(c, &new_keymap);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set virtual console keymap: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int property_get_locale(sd_bus *bus, const char *path, const char *interface,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata) {
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **l = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0, q = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bool modified = false;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_read_basic(m, 'b', &interactive);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers /* Check whether a variable changed and if so valid */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bool valid = false;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (*i)[k] == '=' &&
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_reply_method_errorf(bus, m, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers /* Check whether a variable is unset */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = bus_verify_polkit_async(bus, &c->polkit_registry, m,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1.set-locale", interactive,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, &error);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (startswith(*i, names[p]) && (*i)[k] == '=') {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to set locale: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errnof(bus, m, r, "Failed to set locale: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_return(bus, m, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_read(m, "ssbb", &keymap, &keymap_toggle, &convert, &interactive);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(keymap_toggle, c->vc_keymap_toggle)) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if ((keymap && (!filename_is_safe(keymap) || !string_is_safe(keymap))) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle))))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errnof(bus, m, r, "Received invalid keymap data: %s", -EINVAL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = bus_verify_polkit_async(bus, &c->polkit_registry, m,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers interactive, &error, method_set_vc_keyboard, c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, &error);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_copy(&c->vc_keymap_toggle, keymap_toggle) < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to set virtual console keymap: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errnof(bus, m, r, "Failed to set virtual console keymap: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_info("Changed virtual console keymap to '%s'", strempty(c->vc_keymap));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to request keymap reload: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to convert keymap data: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_return(bus, m, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_read(m, "ssssbb", &layout, &model, &variant, &options, &convert, &interactive);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errnof(bus, m, r, "Received invalid keyboard data: %s", -EINVAL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = bus_verify_polkit_async(bus, &c->polkit_registry, m,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers interactive, &error, method_set_x11_keyboard, c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errno(bus, m, r, &error);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (free_and_copy(&c->x11_layout, layout) < 0 ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_errnof(bus, m, r, "Failed to set X11 keyboard layout: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_info("Changed X11 keyboard layout to '%s'", strempty(c->x11_layout));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "X11Layout" "X11Model" "X11Variant" "X11Options", NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to convert keymap data: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_reply_method_return(bus, m, NULL);
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("Locale", "as", property_get_locale, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Layout", "s", NULL, offsetof(Context, x11_layout), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Model", "s", NULL, offsetof(Context, x11_model), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Variant", "s", NULL, offsetof(Context, x11_variant), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Options", "s", NULL, offsetof(Context, x11_options), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("VConsoleKeymap", "s", NULL, offsetof(Context, vc_keymap), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", NULL, offsetof(Context, vc_keymap_toggle), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, 0),
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, 0),
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, 0),
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to get system bus connection: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_add_object_vtable(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to register object: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_request_name(bus, "org.freedesktop.locale1", SD_BUS_NAME_DO_NOT_QUEUE);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to register name: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to attach bus to event loop: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to allocate event loop: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to read locale data: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = bus_event_loop_with_idle(event, bus, "org.freedesktop.locale1", DEFAULT_EXIT_USEC);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to run event loop: %s", strerror(-r));