localed.c revision d200735e13c52dcfe36c0e066f9f6c2fbfb85a9c
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers/***
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers This file is part of systemd.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers Copyright 2011 Lennart Poettering
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers systemd is free software; you can redistribute it and/or modify it
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers under the terms of the GNU General Public License as published by
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers the Free Software Foundation; either version 2 of the License, or
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers (at your option) any later version.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers General Public License for more details.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers You should have received a copy of the GNU General Public License
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers***/
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <dbus/dbus.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <errno.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <string.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <unistd.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "util.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "strv.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "dbus-common.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "polkit.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "def.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#define INTERFACE \
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
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#define INTROSPECTION \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "<node>\n" \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers INTERFACE \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers BUS_PROPERTIES_INTERFACE \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers BUS_INTROSPECTABLE_INTERFACE \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers BUS_PEER_INTERFACE \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "</node>\n"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#define INTERFACES_LIST \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers BUS_GENERIC_INTERFACES_LIST \
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversconst char locale_interface[] _introspect_("locale1") = INTERFACE;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversenum {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* We don't list LC_ALL here on purpose. People should be
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * using LANG instead. */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LANG,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LANGUAGE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_CTYPE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_NUMERIC,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_TIME,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_COLLATE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_MONETARY,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_MESSAGES,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_PAPER,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_NAME,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_ADDRESS,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_TELEPHONE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_MEASUREMENT,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers PROP_LC_IDENTIFICATION,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers _PROP_MAX
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers};
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic const char * const names[_PROP_MAX] = {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LANG] = "LANG",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LANGUAGE] = "LANGUAGE",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_CTYPE] = "LC_CTYPE",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_NUMERIC] = "LC_NUMERIC",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_TIME] = "LC_TIME",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_COLLATE] = "LC_COLLATE",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_MONETARY] = "LC_MONETARY",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_MESSAGES] = "LC_MESSAGES",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_PAPER] = "LC_PAPER",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_NAME] = "LC_NAME",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_ADDRESS] = "LC_ADDRESS",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_TELEPHONE] = "LC_TELEPHONE",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_MEASUREMENT] = "LC_MEASUREMENT",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers [PROP_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers};
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic char *data[_PROP_MAX] = {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers};
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidttypedef struct State {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt char *x11_layout, *x11_model, *x11_variant, *x11_options;
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt char *vc_keymap, *vc_keymap_toggle;
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt} State;
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidtstatic State state;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic usec_t remain_until = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int free_and_set(char **s, const char *v) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = strdup_or_null(isempty(v) ? NULL : v, &t);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(*s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers *s = t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data_locale(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(data[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers data[p] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data_x11(void) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_layout);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_model);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_variant);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_options);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.x11_layout = state.x11_model = state.x11_variant = state.x11_options = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data_vconsole(void) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.vc_keymap);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.vc_keymap_toggle);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.vc_keymap = state.vc_keymap_toggle = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void simplify(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 1; p < _PROP_MAX; p++)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(data[p]) || streq_ptr(data[PROP_LANG], data[p])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(data[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers data[p] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data_locale(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_locale();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = parse_env_file("/etc/locale.conf", NEWLINE,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LANG", &data[PROP_LANG],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LANGUAGE", &data[PROP_LANGUAGE],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_CTYPE", &data[PROP_LC_CTYPE],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_NUMERIC", &data[PROP_LC_NUMERIC],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_TIME", &data[PROP_LC_TIME],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_COLLATE", &data[PROP_LC_COLLATE],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_MONETARY", &data[PROP_LC_MONETARY],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_MESSAGES", &data[PROP_LC_MESSAGES],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_PAPER", &data[PROP_LC_PAPER],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_NAME", &data[PROP_LC_NAME],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_ADDRESS", &data[PROP_LC_ADDRESS],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_TELEPHONE", &data[PROP_LC_TELEPHONE],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_MEASUREMENT", &data[PROP_LC_MEASUREMENT],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "LC_IDENTIFICATION", &data[PROP_LC_IDENTIFICATION],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r == -ENOENT) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Fill in what we got passed from systemd. */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *e, *d;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers e = getenv(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (e) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers d = strdup(e);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!d)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers d = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(data[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers data[p] = d;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers simplify();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void free_data(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_locale();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_vconsole();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_x11();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data_vconsole(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_vconsole();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = parse_env_file("/etc/vconsole.conf", NEWLINE,
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt "KEYMAP", &state.vc_keymap,
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt "KEYMAP_TOGGLE", &state.vc_keymap_toggle,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data_x11(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers FILE *f;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char line[LINE_MAX];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool in_section = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_x11();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!f) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (errno == ENOENT) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#ifdef TARGET_FEDORA
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers f = fopen("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf", "re");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!f) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (errno == ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#else
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#endif
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers while (fgets(line, sizeof(line), f)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *l;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char_array_0(line);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strstrip(line);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (l[0] == 0 || l[0] == '#')
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (in_section && first_word(l, "Option")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **a;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a = strv_split_quoted(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!a) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_length(a) == 3) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (streq(a[1], "XkbLayout")) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_layout);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.x11_layout = a[2];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (streq(a[1], "XkbModel")) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_model);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.x11_model = a[2];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (streq(a[1], "XkbVariant")) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_variant);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.x11_variant = a[2];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (streq(a[1], "XkbOptions")) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.x11_options);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.x11_options = a[2];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (!in_section && first_word(l, "Section")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **a;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a = strv_split_quoted(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!a) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_length(a) == 2 && streq(a[1], "InputClass"))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers in_section = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (in_section && first_word(l, "EndSection"))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers in_section = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_data(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, q, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_data_locale();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers q = read_data_vconsole();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers p = read_data_x11();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r < 0 ? r : q < 0 ? q : p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int write_data_locale(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **l = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = load_env_file("/etc/locale.conf", &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t, **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(data[p])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strv_env_unset(l, names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (asprintf(&t, "%s=%s", names[p], data[p]) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers u = strv_env_set(l, t);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(t);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!u)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_isempty(l)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (unlink("/etc/locale.conf") < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return errno == ENOENT ? 0 : -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_env_file("/etc/locale.conf", l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic void push_data(DBusConnection *bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **l_set = NULL, **l_unset = NULL, **t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int c_set = 0, c_unset = 0, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusError error;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessage *m = NULL, *reply = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessageIter iter, sub;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_init(&error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l_set = new0(char*, _PROP_MAX);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l_unset = new0(char*, _PROP_MAX);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!l_set || !l_unset) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Out of memory");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(data[p]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l_unset[c_set++] = (char*) names[p];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (asprintf(&s, "%s=%s", names[p], data[p]) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Out of memory");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l_set[c_unset++] = s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(c_set + c_unset == _PROP_MAX);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!m) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Could not allocate message.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_iter_init_append(m, &iter);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Out of memory.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers STRV_FOREACH(t, l_unset)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Out of memory.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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 log_error("Out of memory.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers STRV_FOREACH(t, l_set)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Out of memory.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_close_container(&iter, &sub)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Out of memory.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!reply) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set locale information: %s", bus_error_message(&error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversfinish:
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (m)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(m);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (reply)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(reply);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_free(&error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l_set);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(l_unset);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int write_data_vconsole(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **l = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = load_env_file("/etc/vconsole.conf", &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (isempty(state.vc_keymap))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strv_env_unset(l, "KEYMAP");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s, **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt s = strappend("KEYMAP=", state.vc_keymap);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!s) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers u = strv_env_set(l, s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!u)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (isempty(state.vc_keymap_toggle))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strv_env_unset(l, "KEYMAP_TOGGLE");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s, **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt s = strappend("KEYMAP_TOGGLE=", state.vc_keymap_toggle);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!s) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers u = strv_env_set(l, s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!u)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_isempty(l)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (unlink("/etc/vconsole.conf") < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return errno == ENOENT ? 0 : -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_env_file("/etc/vconsole.conf", l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int write_data_x11(void) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers FILE *f;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *temp_path;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (isempty(state.x11_layout) &&
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt isempty(state.x11_model) &&
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt isempty(state.x11_variant) &&
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt isempty(state.x11_options)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#ifdef TARGET_FEDORA
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unlink("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Symlink this to /dev/null, so that s-s-k (if it is
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * still running) doesn't recreate this. */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers symlink("/dev/null", "/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#endif
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return errno == ENOENT ? 0 : -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers mkdir_parents("/etc/X11/xorg.conf.d", 0755);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fchmod(fileno(f), 0644);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!isempty(state.x11_layout))
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbLayout\" \"%s\"\n", state.x11_layout);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!isempty(state.x11_model))
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbModel\" \"%s\"\n", state.x11_model);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!isempty(state.x11_variant))
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbVariant\" \"%s\"\n", state.x11_variant);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!isempty(state.x11_options))
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt fprintf(f, " Option \"XkbOptions\" \"%s\"\n", state.x11_options);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fputs("EndSection\n", f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fflush(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unlink("/etc/X11/xorg.conf.d/00-keyboard.conf");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unlink(temp_path);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#ifdef TARGET_FEDORA
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unlink("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Symlink this to /dev/null, so that s-s-k (if it is
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * still running) doesn't recreate this. */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers symlink("/dev/null", "/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#endif
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(temp_path);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int load_vconsole_keymap(DBusConnection *bus, DBusError *error) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessage *m = NULL, *reply = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers const char *name = "systemd-vconsole-setup.service", *mode = "replace";
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusError _error;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!error) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_init(&_error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers error = &_error;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers m = dbus_message_new_method_call(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.systemd1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/systemd1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.systemd1.Manager",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "RestartUnit");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!m) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Could not allocate message.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_append_args(m,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &name,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &mode,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_INVALID)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Could not append arguments to message.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!reply) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to issue method call: %s", bus_error_message(error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -EIO;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversfinish:
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (m)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(m);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (reply)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(reply);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (error == &_error)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_free(error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic char *strnulldash(const char *s) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return s == NULL || *s == 0 || (s[0] == '-' && s[1] == 0) ? NULL : (char*) s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int read_next_mapping(FILE *f, unsigned *n, char ***a) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(n);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (;;) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char line[LINE_MAX];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *l, **b;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers errno = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!fgets(line, sizeof(line), f)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (ferror(f))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return errno ? -errno : -EIO;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers (*n) ++;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strstrip(line);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (l[0] == 0 || l[0] == '#')
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers b = strv_split_quoted(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!b)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_length(b) < 5) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Invalid line "SYSTEMD_KBD_MODEL_MAP":%u, ignoring.", *n);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(b);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers *a = b;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 1;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int convert_vconsole_to_x11(DBusConnection *connection) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(connection);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (isempty(state.vc_keymap)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified =
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !isempty(state.x11_layout) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !isempty(state.x11_model) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !isempty(state.x11_variant) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !isempty(state.x11_options);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_x11();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers FILE *f;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned n = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!f)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (;;) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **a;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_next_mapping(f, &n, &a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r == 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!streq(state.vc_keymap, a[0])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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]))) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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 strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (modified) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_bool_t b;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessage *changed;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_data_x11();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers changed = bus_properties_changed_new(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Layout\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Model\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Variant\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Options\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!changed)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers b = dbus_connection_send(connection, changed, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(changed);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!b)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int convert_x11_to_vconsole(DBusConnection *connection) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(connection);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (isempty(state.x11_layout)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified =
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !isempty(state.vc_keymap) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !isempty(state.vc_keymap_toggle);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data_x11();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers FILE *f;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned n = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned best_matching = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *new_keymap = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!f)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -errno;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (;;) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **a;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers unsigned matching = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_next_mapping(f, &n, &a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r == 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Determine how well matching this entry is */
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (streq_ptr(state.x11_layout, a[1]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* If we got an exact match, this is best */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers matching = 10;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers size_t x;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt x = strcspn(state.x11_layout, ",");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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 strlen(a[1]) == x &&
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt strncmp(state.x11_layout, a[1], x) == 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers matching = 5;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers size_t w;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* If that didn't work, strip
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * off the other layouts from
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * the entry, too */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers w = strcspn(a[1], ",");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (x > 0 && x == w &&
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt memcmp(state.x11_layout, a[1], x) == 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers matching = 1;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (matching > 0 &&
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt streq_ptr(state.x11_model, a[2])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers matching++;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (streq_ptr(state.x11_variant, a[3])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers matching++;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (streq_ptr(state.x11_options, a[4]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers matching++;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* The best matching entry so far, then let's
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * save that */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (matching > best_matching) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers best_matching = matching;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(new_keymap);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers new_keymap = strdup(a[0]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!new_keymap) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(a);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fclose(f);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!streq_ptr(state.vc_keymap, new_keymap)) {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.vc_keymap);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.vc_keymap = new_keymap;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free(state.vc_keymap_toggle);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt state.vc_keymap_toggle = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(new_keymap);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (modified) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_bool_t b;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessage *changed;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_data_vconsole();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to set virtual console keymap: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers changed = bus_properties_changed_new(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymap\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymapToggle\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!changed)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers b = dbus_connection_send(connection, changed, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(changed);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!b)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return load_vconsole_keymap(connection, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int append_locale(DBusMessageIter *i, const char *property, void *userdata) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, c = 0, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **l;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = new0(char*, _PROP_MAX+1);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!l)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(data[p]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (asprintf(&t, "%s=%s", names[p], data[p]) < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l[c++] = t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = bus_property_append_strv(i, property, (void*) l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidtstatic const BusProperty bus_locale_properties[] = {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "Locale", append_locale, "as", 0 },
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 { NULL, }
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt};
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidtstatic const BusBoundProperties bps[] = {
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { "org.freedesktop.locale1", bus_locale_properties, &state },
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt { NULL, }
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt};
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic DBusHandlerResult locale_message_handler(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusConnection *connection,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessage *message,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers void *userdata) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessage *reply = NULL, *changed = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusError error;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(connection);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(message);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_init(&error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetLocale")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char **l = NULL, **i;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_bool_t interactive;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusMessageIter iter;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool passed[_PROP_MAX];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_init(message, &iter))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = bus_parse_strv_iter(&iter, &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r == -ENOMEM)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_iter_next(&iter) ||
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_iter_get_basic(&iter, &interactive);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers zero(passed);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Check whether a variable changed and if so valid */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers STRV_FOREACH(i, l) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool valid = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers size_t k;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers k = strlen(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (startswith(*i, names[p]) && (*i)[k] == '=') {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers valid = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers passed[p] = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!streq_ptr(*i + k + 1, data[p]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!valid) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, NULL, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Check whether a variable is unset */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!modified) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!isempty(data[p]) && !passed[p]) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (modified) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = verify_polkit(connection, message, "org.freedesktop.locale1.set-locale", interactive, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers STRV_FOREACH(i, l) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers size_t k;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers k = strlen(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (startswith(*i, names[p]) && (*i)[k] == '=') {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers t = strdup(*i + k + 1);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!t) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(data[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers data[p] = t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (p = 0; p < _PROP_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (passed[p])
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(data[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers data[p] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers simplify();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_data_locale();
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 }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers push_data(connection);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_info("Changed locale information.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers changed = bus_properties_changed_new(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "Locale\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!changed)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetVConsoleKeyboard")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers const char *keymap, *keymap_toggle;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_bool_t convert, interactive;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_get_args(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers message,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers &error,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &keymap,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &keymap_toggle,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_BOOLEAN, &convert,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_BOOLEAN, &interactive,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_INVALID))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(keymap))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers keymap = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(keymap_toggle))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers keymap_toggle = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!streq_ptr(keymap, state.vc_keymap) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(keymap_toggle, state.vc_keymap_toggle)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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 goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_data_vconsole();
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);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt log_info("Changed virtual console keymap to '%s'", strempty(state.vc_keymap));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = load_vconsole_keymap(connection, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to request keymap reload: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers changed = bus_properties_changed_new(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymap\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "VConsoleKeymapToggle\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!changed)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (convert) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = convert_vconsole_to_x11(connection);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to convert keymap data: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetX11Keyboard")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers const char *layout, *model, *variant, *options;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_bool_t convert, interactive;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_message_get_args(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers message,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers &error,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &layout,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &model,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &variant,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_STRING, &options,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_BOOLEAN, &convert,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_BOOLEAN, &interactive,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBUS_TYPE_INVALID))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, -EINVAL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(layout))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers layout = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(model))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers model = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(variant))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers variant = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (isempty(options))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers options = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (!streq_ptr(layout, state.x11_layout) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(model, state.x11_model) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(variant, state.x11_variant) ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt !streq_ptr(options, state.x11_options)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return bus_send_error_reply(connection, message, &error, r);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt if (free_and_set(&state.x11_layout, layout) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_model, model) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_variant, variant) < 0 ||
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt free_and_set(&state.x11_options, options) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = write_data_x11();
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);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt log_info("Changed X11 keyboard layout to '%s'", strempty(state.x11_layout));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers changed = bus_properties_changed_new(
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Layout\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Model\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Variant\0"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "X11Options\0");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!changed)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (convert) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = convert_x11_to_vconsole(connection);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to convert keymap data: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!(reply = dbus_message_new_method_return(message)))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_send(connection, reply, NULL))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(reply);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers reply = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (changed) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_send(connection, changed, NULL))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto oom;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(changed);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return DBUS_HANDLER_RESULT_HANDLED;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversoom:
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (reply)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(reply);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (changed)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_message_unref(changed);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_free(&error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return DBUS_HANDLER_RESULT_NEED_MEMORY;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversstatic int connect_bus(DBusConnection **_bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers static const DBusObjectPathVTable locale_vtable = {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers .message_function = locale_message_handler
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers };
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusError error;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusConnection *bus = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(_bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_init(&error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -ECONNREFUSED;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto fail;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_set_exit_on_disconnect(bus, FALSE);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
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 log_error("Not enough memory");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto fail;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = dbus_bus_request_name(bus, "org.freedesktop.locale1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (dbus_error_is_set(&error)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to register name on bus: %s", bus_error_message(&error));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -EEXIST;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto fail;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to acquire name.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -EEXIST;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto fail;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (_bus)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers *_bus = bus;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversfail:
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_close(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_unref(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_error_free(&error);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversint main(int argc, char *argv[]) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers DBusConnection *bus = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool exiting = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_set_target(LOG_TARGET_AUTO);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_parse_environment();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_open();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers umask(0022);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (argc == 2 && streq(argv[1], "--introspect")) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "<node>\n", stdout);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fputs(locale_interface, stdout);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers fputs("</node>\n", stdout);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (argc != 1) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("This program takes no arguments.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = -EINVAL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_data();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_error("Failed to read locale data: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = connect_bus(&bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers for (;;) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers exiting = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bus_async_unregister_and_exit(bus, "org.freedesktop.locale1");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversfinish:
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free_data();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_flush(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_close(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers dbus_connection_unref(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}