localed.c revision da927ba997d68401563b927f92e6e40e021a8e5c
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
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Copyright 2013 Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers (at your option) any later version.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers systemd is distributed in the hope that it will be useful, but
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers***/
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <errno.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <string.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include <unistd.h>
def9a7aa0182e5ecca3ac61b26f75136a5c4f103Lennart Poettering#include <sys/capability.h>
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers#include "sd-bus.h"
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "util.h"
49e942b2bc9fdedba79cd266a076ce9c9d91fc13Kay Sievers#include "mkdir.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "strv.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers#include "def.h"
4d1a69043862ed979642f5688097160355d4cc81Lennart Poettering#include "env-util.h"
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer#include "fileio.h"
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer#include "fileio-label.h"
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer#include "label.h"
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers#include "bus-util.h"
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers#include "bus-error.h"
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers#include "bus-message.h"
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers#include "event-util.h"
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering#include "locale-util.h"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann#ifdef HAVE_XKBCOMMON
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann#include <xkbcommon/xkbcommon.h>
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann#endif
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversenum {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* We don't list LC_ALL here on purpose. People should be
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers * using LANG instead. */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LANG,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LANGUAGE,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_CTYPE,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_NUMERIC,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_TIME,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_COLLATE,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_MONETARY,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_MESSAGES,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_PAPER,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_NAME,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_ADDRESS,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_TELEPHONE,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_MEASUREMENT,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers LOCALE_LC_IDENTIFICATION,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _LOCALE_MAX
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers};
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic const char * const names[_LOCALE_MAX] = {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LANG] = "LANG",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LANGUAGE] = "LANGUAGE",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_CTYPE] = "LC_CTYPE",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_NUMERIC] = "LC_NUMERIC",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_TIME] = "LC_TIME",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_COLLATE] = "LC_COLLATE",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_MONETARY] = "LC_MONETARY",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_MESSAGES] = "LC_MESSAGES",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_PAPER] = "LC_PAPER",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_NAME] = "LC_NAME",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_ADDRESS] = "LC_ADDRESS",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_TELEPHONE] = "LC_TELEPHONE",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_MEASUREMENT] = "LC_MEASUREMENT",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers [LOCALE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers};
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieverstypedef struct Context {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *locale[_LOCALE_MAX];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *x11_layout;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *x11_model;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *x11_variant;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *x11_options;
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *vc_keymap;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char *vc_keymap_toggle;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Hashmap *polkit_registry;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers} Context;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmekstatic const char* nonempty(const char *s) {
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek return isempty(s) ? NULL : s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void free_and_replace(char **s, char *v) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free(*s);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers *s = v;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmekstatic bool startswith_comma(const char *s, const char *prefix) {
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek const char *t;
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek return s && (t = startswith(s, prefix)) && (*t == ',');
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek}
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void context_free_x11(Context *c) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_layout, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_model, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_variant, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_options, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void context_free_vconsole(Context *c) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->vc_keymap, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->vc_keymap_toggle, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void context_free_locale(Context *c) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->locale[p], NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
36e34057a202d389263e98030fbd775b28b28af6Stef Walterstatic void context_free(Context *c) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_locale(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_x11(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_vconsole(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
36e34057a202d389263e98030fbd775b28b28af6Stef Walter bus_verify_polkit_async_registry_free(c->polkit_registry);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers};
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic void locale_simplify(Context *c) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = LOCALE_LANG+1; p < _LOCALE_MAX; p++)
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek if (isempty(c->locale[p]) || streq_ptr(c->locale[LOCALE_LANG], c->locale[p]))
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_replace(&c->locale[p], NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int locale_read_data(Context *c) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_locale(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = parse_env_file("/etc/locale.conf", NEWLINE,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LANG", &c->locale[LOCALE_LANG],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LANGUAGE", &c->locale[LOCALE_LANGUAGE],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_CTYPE", &c->locale[LOCALE_LC_CTYPE],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_NUMERIC", &c->locale[LOCALE_LC_NUMERIC],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_TIME", &c->locale[LOCALE_LC_TIME],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_COLLATE", &c->locale[LOCALE_LC_COLLATE],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_MONETARY", &c->locale[LOCALE_LC_MONETARY],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_MESSAGES", &c->locale[LOCALE_LC_MESSAGES],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_PAPER", &c->locale[LOCALE_LC_PAPER],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_NAME", &c->locale[LOCALE_LC_NAME],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_ADDRESS", &c->locale[LOCALE_LC_ADDRESS],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_TELEPHONE", &c->locale[LOCALE_LC_TELEPHONE],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_MEASUREMENT", &c->locale[LOCALE_LC_MEASUREMENT],
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "LC_IDENTIFICATION", &c->locale[LOCALE_LC_IDENTIFICATION],
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r == -ENOENT) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers /* Fill in what we got passed from systemd. */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek r = free_and_strdup(&c->locale[p],
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek nonempty(getenv(names[p])));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers locale_simplify(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int vconsole_read_data(Context *c) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_vconsole(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = parse_env_file("/etc/vconsole.conf", NEWLINE,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "KEYMAP", &c->vc_keymap,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "KEYMAP_TOGGLE", &c->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
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int x11_read_data(Context *c) {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char line[LINE_MAX];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool in_section = false;
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_x11(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
f687b2738229570453c9412add6b9c4f99c9c004Lennart Poettering if (!f)
f687b2738229570453c9412add6b9c4f99c9c004Lennart Poettering return errno == ENOENT ? 0 : -errno;
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")) {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **a = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
f88e6be5ee31ff0e45fabcdedaf26d3be0d4817aLennart Poettering r = strv_split_quoted(&a, l, false);
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek if (r < 0)
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_length(a) == 3) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (streq(a[1], "XkbLayout")) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_layout, a[2]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (streq(a[1], "XkbModel")) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_model, a[2]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (streq(a[1], "XkbVariant")) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_variant, a[2]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (streq(a[1], "XkbOptions")) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->x11_options, a[2]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers a[2] = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (!in_section && first_word(l, "Section")) {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **a = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
f88e6be5ee31ff0e45fabcdedaf26d3be0d4817aLennart Poettering r = strv_split_quoted(&a, l, false);
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_length(a) == 2 && streq(a[1], "InputClass"))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers in_section = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else if (in_section && first_word(l, "EndSection"))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers in_section = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int context_read_data(Context *c) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, q, p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = locale_read_data(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers q = vconsole_read_data(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers p = x11_read_data(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r < 0 ? r : q < 0 ? q : p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmekstatic int locale_write_data(Context *c, char ***settings) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r, p;
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **l = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek /* Set values will be returned as strv in *settings on success. */
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = load_env_file(NULL, "/etc/locale.conf", NULL, &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_free_ char *t = NULL;
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek char **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->locale[p])) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strv_env_unset(l, names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers u = strv_env_set(l, t);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!u)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_isempty(l)) {
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
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek r = write_env_file_label("/etc/locale.conf", l);
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek if (r < 0)
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek return r;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek *settings = l;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek l = NULL;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int locale_update_system_manager(Context *c, sd_bus *bus) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_free_ char **l_unset = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_strv_free_ char **l_set = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_error error = SD_BUS_ERROR_NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers unsigned c_set, c_unset, p;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers l_unset = new0(char*, _LOCALE_MAX);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!l_unset)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers l_set = new0(char*, _LOCALE_MAX);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!l_set)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return -ENOMEM;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0, c_set = 0, c_unset = 0; p < _LOCALE_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(names[p]);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->locale[p]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l_unset[c_set++] = (char*) names[p];
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (asprintf(&s, "%s=%s", names[p], c->locale[p]) < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l_set[c_unset++] = s;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers assert(c_set + c_unset == _LOCALE_MAX);
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering r = sd_bus_message_new_method_call(bus, &m,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.systemd1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "/org/freedesktop/systemd1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.systemd1.Manager",
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering "UnsetAndSetEnvironment");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_append_strv(m, l_unset);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_append_strv(m, l_set);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering r = sd_bus_call(bus, m, 0, &error, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to update the manager environment: %m");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int vconsole_write_data(Context *c) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **l = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = load_env_file(NULL, "/etc/vconsole.conf", NULL, &l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0 && r != -ENOENT)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->vc_keymap))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strv_env_unset(l, "KEYMAP");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_free_ char *s = NULL;
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek char **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers s = strappend("KEYMAP=", c->vc_keymap);
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek if (!s)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers u = strv_env_set(l, s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!u)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->vc_keymap_toggle))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = strv_env_unset(l, "KEYMAP_TOGGLE");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers else {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_free_ char *s = NULL;
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek char **u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek if (!s)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers u = strv_env_set(l, s);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!u)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek strv_free(l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers l = u;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (strv_isempty(l)) {
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
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek return write_env_file_label("/etc/vconsole.conf", l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
e78af5ffe53a0d24854d721d1166a60f8ed0dfb6Zbigniew Jędrzejewski-Szmekstatic int x11_write_data(Context *c) {
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *temp_path = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->x11_layout) &&
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers isempty(c->x11_model) &&
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers isempty(c->x11_variant) &&
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers isempty(c->x11_options)) {
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
9a9bb3ca1eddc8caa2d7aa3e6e27d270e296923fMichał Bartoszkiewicz mkdir_p_label("/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
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!isempty(c->x11_layout))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!isempty(c->x11_model))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!isempty(c->x11_variant))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!isempty(c->x11_options))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->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);
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek return r;
f687b2738229570453c9412add6b9c4f99c9c004Lennart Poettering } else
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int vconsole_reload(sd_bus *bus) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_call_method(bus,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.systemd1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/systemd1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.systemd1.Manager",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "RestartUnit",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers &error,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers NULL,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "ss", "systemd-vconsole-setup.service", "replace");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmekstatic const char* strnulldash(const char *s) {
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek return isempty(s) || streq(s, "-") ? NULL : 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;
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek int r;
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
f88e6be5ee31ff0e45fabcdedaf26d3be0d4817aLennart Poettering r = strv_split_quoted(&b, l, false);
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek if (r < 0)
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek return r;
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
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int vconsole_convert_to_x11(Context *c, sd_bus *bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers assert(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->vc_keymap)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified =
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !isempty(c->x11_layout) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !isempty(c->x11_model) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !isempty(c->x11_variant) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !isempty(c->x11_options);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_x11(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else {
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
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 (;;) {
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **a = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers r = read_next_mapping(f, &n, &a);
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r == 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
98fce79dea6f653dead88638fc17a27280b1f250Zbigniew Jędrzejewski-Szmek if (!streq(c->vc_keymap, a[0]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!streq_ptr(c->x11_layout, strnulldash(a[1])) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(c->x11_model, strnulldash(a[2])) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(c->x11_variant, strnulldash(a[3])) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(c->x11_options, strnulldash(a[4]))) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek if (free_and_strdup(&c->x11_layout, strnulldash(a[1])) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->x11_model, strnulldash(a[2])) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->x11_variant, strnulldash(a[3])) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->x11_options, strnulldash(a[4])) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (modified) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
e78af5ffe53a0d24854d721d1166a60f8ed0dfb6Zbigniew Jędrzejewski-Szmek r = x11_write_data(c);
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to set X11 keyboard layout: %m");
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek return r;
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_layout),
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_model),
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_variant),
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_options));
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_emit_properties_changed(bus,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek } else
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_debug("X11 keyboard layout was not modified.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmekstatic int find_converted_keymap(const char *x11_layout, const char *x11_variant, char **new_keymap) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek const char *dir;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *n;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek if (x11_variant)
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek n = strjoin(x11_layout, "-", x11_variant, NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek else
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek n = strdup(x11_layout);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (!n)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return -ENOMEM;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *p = NULL, *pz = NULL;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek bool uncompressed;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek p = strjoin(dir, "xkb/", n, ".map", NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek pz = strjoin(dir, "xkb/", n, ".map.gz", NULL);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (!p || !pz)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return -ENOMEM;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek uncompressed = access(p, F_OK) == 0;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek if (uncompressed || access(pz, F_OK) == 0) {
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_debug("Found converted keymap %s at %s",
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek n, uncompressed ? p : pz);
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek *new_keymap = n;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek n = NULL;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return 1;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return 0;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek}
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmekstatic int find_legacy_keymap(Context *c, char **new_keymap) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek unsigned n = 0;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek unsigned best_matching = 0;
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek int r;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (!f)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return -errno;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek for (;;) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **a = NULL;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek unsigned matching = 0;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek r = read_next_mapping(f, &n, &a);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (r < 0)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return r;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (r == 0)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek break;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* Determine how well matching this entry is */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (streq_ptr(c->x11_layout, a[1]))
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* If we got an exact match, this is best */
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek matching = 10;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek else {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* We have multiple X layouts, look for an
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek * entry that matches our key with everything
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek * but the first layout stripped off. */
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek if (startswith_comma(c->x11_layout, a[1]))
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek matching = 5;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek else {
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek char *x;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* If that didn't work, strip off the
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek * other layouts from the entry, too */
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek x = strndupa(a[1], strcspn(a[1], ","));
81fd105a5f9762fa2f2e42bc949876e32b3a126fZbigniew Jędrzejewski-Szmek if (startswith_comma(c->x11_layout, x))
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek matching = 1;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar if (matching > 0) {
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar if (isempty(c->x11_model) || streq_ptr(c->x11_model, a[2])) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek matching++;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar if (streq_ptr(c->x11_variant, a[3])) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek matching++;
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar if (streq_ptr(c->x11_options, a[4]))
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar matching++;
387066c2e5bda159201896b194711965b52f34a9Michal Sekletar }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek /* The best matching entry so far, then let's save that */
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek if (matching >= MAX(best_matching, 1u)) {
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_debug("Found legacy keymap %s with score %u",
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek a[0], matching);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek if (matching > best_matching) {
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek best_matching = matching;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek r = free_and_strdup(new_keymap, a[0]);
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek if (r < 0)
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek return r;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek }
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek if (best_matching < 10 && c->x11_layout) {
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek /* The best match is only the first part of the X11
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek * keymap. Check if we have a converted map which
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek * matches just the first layout.
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek */
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek char *l, *v = NULL, *converted;
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek l = strndupa(c->x11_layout, strcspn(c->x11_layout, ","));
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek if (c->x11_variant)
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek v = strndupa(c->x11_variant, strcspn(c->x11_variant, ","));
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek r = find_converted_keymap(l, v, &converted);
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek if (r < 0)
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek return r;
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek if (r > 0)
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek free_and_replace(new_keymap, converted);
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek }
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return 0;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek}
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int x11_convert_to_vconsole(Context *c, sd_bus *bus) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers bool modified = false;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers assert(bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->x11_layout)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified =
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !isempty(c->vc_keymap) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !isempty(c->vc_keymap_toggle);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers context_free_x11(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *new_keymap = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
78bd12a05a9252cf573da28394b23e2b891cbba8Zbigniew Jędrzejewski-Szmek r = find_converted_keymap(c->x11_layout, c->x11_variant, &new_keymap);
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek if (r < 0)
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek return r;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek else if (r == 0) {
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek r = find_legacy_keymap(c, &new_keymap);
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!streq_ptr(c->vc_keymap, new_keymap)) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->vc_keymap, new_keymap);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->vc_keymap_toggle, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers } else
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers free(new_keymap);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (modified) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = vconsole_write_data(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to set virtual console keymap: %m");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_info("Changed virtual console keymap to '%s' toggle '%s'",
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->vc_keymap), strempty(c->vc_keymap_toggle));
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_emit_properties_changed(bus,
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "/org/freedesktop/locale1",
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return vconsole_reload(bus);
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek } else
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_debug("Virtual console keymap was not modified.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int property_get_locale(
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering sd_bus *bus,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering const char *path,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering const char *interface,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering const char *property,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering sd_bus_message *reply,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering void *userdata,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering sd_bus_error *error) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Context *c = userdata;
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **l = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int p, q;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers l = new0(char*, _LOCALE_MAX+1);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (!l)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0, q = 0; p < _LOCALE_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers char *t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(c->locale[p]))
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers l[q++] = t;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return sd_bus_message_append_strv(reply, l);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Context *c = userdata;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_strv_free_ char **l = NULL;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers char **i;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int interactive;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bool modified = false;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bool passed[_LOCALE_MAX] = {};
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int p;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = bus_message_read_strv_extend(m, &l);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_read_basic(m, 'b', &interactive);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek /* Check whether a variable changed and if it is valid */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers STRV_FOREACH(i, l) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bool valid = false;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers size_t k;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers k = strlen(names[p]);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (startswith(*i, names[p]) &&
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (*i)[k] == '=' &&
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering locale_is_valid((*i) + k + 1)) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers valid = true;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers passed[p] = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!streq_ptr(*i + k + 1, c->locale[p]))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers modified = true;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers break;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!valid)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers /* Check whether a variable is unset */
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek if (!modified)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!isempty(c->locale[p]) && !passed[p]) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers modified = true;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers break;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (modified) {
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **settings = NULL;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
f38857914ab5c9cc55aac05795e1886963a5fd04Lennart Poettering r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-locale", interactive, &c->polkit_registry, error);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r == 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek STRV_FOREACH(i, l)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers size_t k;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers k = strlen(names[p]);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (startswith(*i, names[p]) && (*i)[k] == '=') {
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek r = free_and_strdup(&c->locale[p], *i + k + 1);
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek if (r < 0)
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers break;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers for (p = 0; p < _LOCALE_MAX; p++) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (passed[p])
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers continue;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers free_and_replace(&c->locale[p], NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers locale_simplify(c);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek r = locale_write_data(c, &settings);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to set locale: %m");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to set locale: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers locale_update_system_manager(c, bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek if (settings) {
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *line;
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek line = strv_join(settings, ", ");
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_info("Changed locale to %s.", strnull(line));
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek } else
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_info("Changed locale to unset.");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_emit_properties_changed(bus,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "/org/freedesktop/locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "Locale", NULL);
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek } else
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_debug("Locale settings were not modified.");
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering return sd_bus_reply_method_return(m, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Context *c = userdata;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers const char *keymap, *keymap_toggle;
102d8f8169427cb68cdebf5ee0f0e07788e9c2b2Kay Sievers int convert, interactive;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int r;
f2cc3753ce0e85960f0299855c3b98ba60efa580Václav Pavlín
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_read(m, "ssbb", &keymap, &keymap_toggle, &convert, &interactive);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(keymap))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers keymap = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(keymap_toggle))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers keymap_toggle = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!streq_ptr(keymap, c->vc_keymap) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(keymap_toggle, c->vc_keymap_toggle)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if ((keymap && (!filename_is_safe(keymap) || !string_is_safe(keymap))) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle))))
d14ab08b29d5b0b3ead6e63ac8be472f273011f9Lennart Poettering return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keymap data");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
f38857914ab5c9cc55aac05795e1886963a5fd04Lennart Poettering r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, &c->polkit_registry, error);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r == 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek if (free_and_strdup(&c->vc_keymap, keymap) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return -ENOMEM;
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = vconsole_write_data(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to set virtual console keymap: %m");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %s", strerror(-r));
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_info("Changed virtual console keymap to '%s' toggle '%s'",
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->vc_keymap), strempty(c->vc_keymap_toggle));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = vconsole_reload(bus);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to request keymap reload: %m");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_emit_properties_changed(bus,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "/org/freedesktop/locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (convert) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = vconsole_convert_to_x11(c, bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to convert keymap data: %m");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering return sd_bus_reply_method_return(m, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann#ifdef HAVE_XKBCOMMON
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmannstatic void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann /* suppress xkb messages for now */
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann}
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmannstatic int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann const struct xkb_rule_names rmlvo = {
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann .model = model,
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann .layout = layout,
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann .variant = variant,
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann .options = options,
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann };
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann struct xkb_context *ctx = NULL;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann struct xkb_keymap *km = NULL;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann int r;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann /* compile keymap from RMLVO information to check out its validity */
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann ctx = xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann if (!ctx) {
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann r = -ENOMEM;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann goto exit;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann }
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann xkb_context_set_log_fn(ctx, log_xkb);
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann km = xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS);
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann if (!km) {
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann r = -EINVAL;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann goto exit;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann }
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann r = 0;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmannexit:
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann xkb_keymap_unref(km);
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann xkb_context_unref(ctx);
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann return r;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann}
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann#else
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmannstatic int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann return 0;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann}
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann#endif
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers Context *c = userdata;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers const char *layout, *model, *variant, *options;
102d8f8169427cb68cdebf5ee0f0e07788e9c2b2Kay Sievers int convert, interactive;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_message_read(m, "ssssbb", &layout, &model, &variant, &options, &convert, &interactive);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(layout))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers layout = NULL;
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(model))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers model = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(variant))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers variant = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (isempty(options))
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers options = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (!streq_ptr(layout, c->x11_layout) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(model, c->x11_model) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(variant, c->x11_variant) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers !streq_ptr(options, c->x11_options)) {
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if ((layout && !string_is_safe(layout)) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (model && !string_is_safe(model)) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (variant && !string_is_safe(variant)) ||
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers (options && !string_is_safe(options)))
d14ab08b29d5b0b3ead6e63ac8be472f273011f9Lennart Poettering return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
f38857914ab5c9cc55aac05795e1886963a5fd04Lennart Poettering r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, &c->polkit_registry, error);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r == 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
8623d3a3b2e3463fa6e4ded734323483540c3ed4David Herrmann r = verify_xkb_rmlvo(model, layout, variant, options);
8623d3a3b2e3463fa6e4ded734323483540c3ed4David Herrmann if (r < 0)
8623d3a3b2e3463fa6e4ded734323483540c3ed4David Herrmann log_warning("Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %s",
8623d3a3b2e3463fa6e4ded734323483540c3ed4David Herrmann strempty(model), strempty(layout), strempty(variant), strempty(options), strerror(-r));
8623d3a3b2e3463fa6e4ded734323483540c3ed4David Herrmann
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek if (free_and_strdup(&c->x11_layout, layout) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->x11_model, model) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->x11_variant, variant) < 0 ||
af76d302c1e26f916494202f1b3663f15710bdcdZbigniew Jędrzejewski-Szmek free_and_strdup(&c->x11_options, options) < 0)
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return -ENOMEM;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
e78af5ffe53a0d24854d721d1166a60f8ed0dfb6Zbigniew Jędrzejewski-Szmek r = x11_write_data(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to set X11 keyboard layout: %m");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %s", strerror(-r));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_layout),
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_model),
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_variant),
502f961425f9dea1a85239766a3189695194da63Zbigniew Jędrzejewski-Szmek strempty(c->x11_options));
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers sd_bus_emit_properties_changed(bus,
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "/org/freedesktop/locale1",
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers "org.freedesktop.locale1",
c168eb6785bacc2042687bf879259dfc27d5a523David Herrmann "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (convert) {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = x11_convert_to_vconsole(c, bus);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to convert keymap data: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering return sd_bus_reply_method_return(m, NULL);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic const sd_bus_vtable locale_vtable[] = {
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers SD_BUS_VTABLE_START(0),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("Locale", "as", property_get_locale, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Layout", "s", NULL, offsetof(Context, x11_layout), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Model", "s", NULL, offsetof(Context, x11_model), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Variant", "s", NULL, offsetof(Context, x11_variant), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("X11Options", "s", NULL, offsetof(Context, x11_options), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("VConsoleKeymap", "s", NULL, offsetof(Context, vc_keymap), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6d1bd3b2bbae29dbd3862fdb9af2b472b01c480eLennart Poettering SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", NULL, offsetof(Context, vc_keymap_toggle), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, SD_BUS_VTABLE_UNPRIVILEGED),
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, SD_BUS_VTABLE_UNPRIVILEGED),
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, SD_BUS_VTABLE_UNPRIVILEGED),
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers SD_BUS_VTABLE_END
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers};
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sieversstatic int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers assert(c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers assert(event);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers assert(_bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
76b543756ef69ce69784d571aefe8de65eaeb331Lennart Poettering r = sd_bus_default_system(&bus);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to get system bus connection: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to register object: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
5bb658a1784a0fd4f0f32adb4b1fb636ff503f7dKay Sievers r = sd_bus_request_name(bus, "org.freedesktop.locale1", 0);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to register name: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = sd_bus_attach_event(bus, event, 0);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to attach bus to event loop: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return r;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers *_bus = bus;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers bus = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers return 0;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversint main(int argc, char *argv[]) {
28efac0d37ceb5093a804da6a00c620034c5484fZbigniew Jędrzejewski-Szmek _cleanup_(context_free) Context context = {};
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers _cleanup_event_unref_ sd_event *event = NULL;
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers int r;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_set_target(LOG_TARGET_AUTO);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_parse_environment();
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers log_open();
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers umask(0022);
cc56fafeebf814ef035e549115cf1850e6473fa5WaLyong Cho mac_selinux_init("/etc");
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
afc6adb5ec7e73bc13156c43f52fb015cd80cc68Lennart Poettering r = sd_event_default(&event);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to allocate event loop: %m");
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
cde93897cdefdd7c7f66c400a61e42ceee5f6a46Lennart Poettering sd_event_set_watchdog(event, true);
cde93897cdefdd7c7f66c400a61e42ceee5f6a46Lennart Poettering
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = connect_bus(&context, event, &bus);
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers if (r < 0)
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers r = context_read_data(&context);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to read locale data: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers goto finish;
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
37224a5ff522a366b353e8a01e2c2eee1e5416e5Lennart Poettering r = bus_event_loop_with_idle(event, bus, "org.freedesktop.locale1", DEFAULT_EXIT_USEC, NULL, NULL);
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to run event loop: %m");
8d451309667578d3a03cdfc91d6e339fb9fe64a7Kay Sievers goto finish;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers }
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sieversfinish:
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1822350db15b089f094a6dbd2469842ab42c1d87Kay Sievers}