localed.c revision 0b507b17a760b21e33fc52ff377db6aa5086c680
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
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 " <interface name=\"org.freedesktop.locale1\">\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"Locale\" type=\"as\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"VConsoleKeymap\" type=\"s\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"VConsoleKeymapToggle\" type=\"s\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"X11Layout\" type=\"s\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"X11Model\" type=\"s\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"X11Variant\" type=\"s\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <property name=\"X11Options\" type=\"s\" access=\"read\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <method name=\"SetLocale\">\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"locale\" type=\"as\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " </method>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <method name=\"SetVConsoleKeyboard\">\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"keymap\" type=\"s\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"keymap_toggle\" type=\"s\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"convert\" type=\"b\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " </method>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <method name=\"SetX11Keyboard\">\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"layout\" type=\"s\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"model\" type=\"s\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"variant\" type=\"s\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"options\" type=\"s\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"convert\" type=\"b\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " </method>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers " </interface>\n"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "<node>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversconst char locale_interface[] _introspect_("locale1") = INTERFACE;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* We don't list LC_ALL here on purpose. People should be
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * using LANG instead. */
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidttypedef struct State {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt char *x11_layout, *x11_model, *x11_variant, *x11_options;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int free_and_set(char **s, const char *v) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data_locale(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data_x11(void) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.x11_layout = state.x11_model = state.x11_variant = state.x11_options = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data_vconsole(void) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.vc_keymap = state.vc_keymap_toggle = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void simplify(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(data[p]) || streq_ptr(data[PROP_LANG], data[p])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data_locale(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_IDENTIFICATION", &data[PROP_LC_IDENTIFICATION],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Fill in what we got passed from systemd. */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *e, *d;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data_vconsole(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = parse_env_file("/etc/vconsole.conf", NEWLINE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data_x11(void) {
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 Sieversstatic int read_data(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, q, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r < 0 ? r : q < 0 ? q : p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int write_data_locale(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t, **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (asprintf(&t, "%s=%s", names[p], data[p]) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (asprintf(&s, "%s=%s", names[p], data[p]) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_close_container(&iter, &sub) ||
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_close_container(&iter, &sub)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set locale information: %s", bus_error_message(&error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int write_data_vconsole(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s, **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s, **u;
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt s = strappend("KEYMAP_TOGGLE=", state.vc_keymap_toggle);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int write_data_x11(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
d2e54fae5ca7a0f71b5ac8b356a589ff0a09ea0aKay Sievers mkdir_parents_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);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbLayout\" \"%s\"\n", state.x11_layout);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbModel\" \"%s\"\n", state.x11_model);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbVariant\" \"%s\"\n", state.x11_variant);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbOptions\" \"%s\"\n", state.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");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int load_vconsole_keymap(DBusConnection *bus, DBusError *error) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers const char *name = "systemd-vconsole-setup.service", *mode = "replace";
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.systemd1.Manager",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "RestartUnit");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Could not append arguments to message.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to issue method call: %s", bus_error_message(error));
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);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int convert_vconsole_to_x11(DBusConnection *connection) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned n = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_next_mapping(f, &n, &a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!streq_ptr(state.x11_layout, strnulldash(a[1])) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(state.x11_model, strnulldash(a[2])) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(state.x11_variant, strnulldash(a[3])) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(state.x11_options, strnulldash(a[4]))) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (free_and_set(&state.x11_layout, strnulldash(a[1])) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_model, strnulldash(a[2])) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_variant, strnulldash(a[3])) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_options, strnulldash(a[4])) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Layout\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Model\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Variant\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Options\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers b = dbus_connection_send(connection, changed, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int convert_x11_to_vconsole(DBusConnection *connection) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned n = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned matching = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_next_mapping(f, &n, &a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Determine how well matching this entry is */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* If we got an exact match, this is best */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* We have multiple X layouts, look
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * for an entry that matches our key
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * with the everything but the first
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * layout stripped off. */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (x > 0 &&
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* If that didn't work, strip
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * off the other layouts from
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * the entry, too */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (x > 0 && x == w &&
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* The best matching entry so far, then let's
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * save that */
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!streq_ptr(state.vc_keymap, new_keymap)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set virtual console keymap: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymap\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymapToggle\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers b = dbus_connection_send(connection, changed, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int append_locale(DBusMessageIter *i, const char *property, void *userdata) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, c = 0, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (asprintf(&t, "%s=%s", names[p], data[p]) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = bus_property_append_strv(i, property, (void*) l);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidtstatic const BusProperty bus_locale_properties[] = {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "X11Layout", bus_property_append_string, "s", offsetof(State, x11_layout), true },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "X11Model", bus_property_append_string, "s", offsetof(State, x11_model), true },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "X11Variant", bus_property_append_string, "s", offsetof(State, x11_variant), true },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "X11Options", bus_property_append_string, "s", offsetof(State, x11_options), true },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "VConsoleKeymap", bus_property_append_string, "s", offsetof(State, vc_keymap), true },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "VConsoleKeymapToggle", bus_property_append_string, "s", offsetof(State, vc_keymap_toggle), true },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "org.freedesktop.locale1", bus_locale_properties, &state },
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetLocale")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **l = NULL, **i;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_iter_get_basic(&iter, &interactive);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Check whether a variable changed and if so valid */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool valid = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering (*i)[k] == '=' &&
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Check whether a variable is unset */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++)
89f134406af6a4b4c7493f624a89dcd654b48e81Lennart Poettering r = verify_polkit(connection, message, "org.freedesktop.locale1.set-locale", interactive, NULL, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (startswith(*i, names[p]) && (*i)[k] == '=') {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set locale: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "Locale\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetVConsoleKeyboard")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, -EINVAL);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(keymap_toggle, state.vc_keymap_toggle)) {
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering if ((keymap && (!filename_is_safe(keymap) || !string_is_safe(keymap))) ||
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle))))
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering return bus_send_error_reply(connection, message, NULL, -EINVAL);
89f134406af6a4b4c7493f624a89dcd654b48e81Lennart Poettering r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, NULL, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, r);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (free_and_set(&state.vc_keymap, keymap) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.vc_keymap_toggle, keymap_toggle) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set virtual console keymap: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, r);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt log_info("Changed virtual console keymap to '%s'", strempty(state.vc_keymap));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to request keymap reload: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymap\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymapToggle\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to convert keymap data: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetX11Keyboard")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, -EINVAL);
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering if ((layout && !string_is_safe(layout)) ||
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering return bus_send_error_reply(connection, message, NULL, -EINVAL);
89f134406af6a4b4c7493f624a89dcd654b48e81Lennart Poettering r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, NULL, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, r);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (free_and_set(&state.x11_layout, layout) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_variant, variant) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_options, options) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, r);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt log_info("Changed X11 keyboard layout to '%s'", strempty(state.x11_layout));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Layout\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Model\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Variant\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Options\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to convert keymap data: %s", strerror(-r));
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!(reply = dbus_message_new_method_return(message)))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_send(connection, reply, NULL))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_send(connection, changed, NULL))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers static const DBusObjectPathVTable locale_vtable = {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_set_exit_on_disconnect(bus, FALSE);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL) ||
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = dbus_bus_request_name(bus, "org.freedesktop.locale1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to register name on bus: %s", bus_error_message(&error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool exiting = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (argc == 2 && streq(argv[1], "--introspect")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to read locale data: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bus_async_unregister_and_exit(bus, "org.freedesktop.locale1");