localectl.c revision 63229aa1abdb98aa69fda9819ed2f40c8082762b
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/***
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt Copyright 2012 Lennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Copyright 2013 Kay Sievers
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt***/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <locale.h>
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt#include <stdlib.h>
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include <stdbool.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <unistd.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <getopt.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <string.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <ftw.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/mman.h>
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include <fcntl.h>
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-bus.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "bus-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-error.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-message.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "spawn-polkit-agent.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "build.h"
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include "strv.h"
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include "pager.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "set.h"
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering#include "path-util.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "utf8.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "def.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "virt.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "fileio.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "locale-util.h"
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williamsstatic bool arg_no_pager = false;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williamsstatic bool arg_ask_password = true;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic char *arg_host = NULL;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flyktstatic bool arg_convert = true;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic void pager_open_if_enabled(void) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (arg_no_pager)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt pager_open(false);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic void polkit_agent_open_if_enabled(void) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* Open the polkit agent as a child process if necessary */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!arg_ask_password)
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen return;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (arg_transport != BUS_TRANSPORT_LOCAL)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt polkit_agent_open();
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykttypedef struct StatusInfo {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt char **locale;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt const char *vconsole_keymap;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *vconsole_keymap_toggle;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *x11_layout;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *x11_model;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *x11_variant;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt const char *x11_options;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt} StatusInfo;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic void print_overriden_variables(void) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char *variables[_VARIABLE_LC_MAX] = {};
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt LocaleVariable j;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt bool print_warning = true;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (detect_container(NULL) > 0 || arg_host)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = parse_env_file("/proc/cmdline", WHITESPACE,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt "locale.LANG", &variables[VARIABLE_LANG],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_TIME", &variables[VARIABLE_LC_TIME],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_NAME", &variables[VARIABLE_LC_NAME],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt NULL);
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (r < 0 && r != -ENOENT) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt goto finish;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt }
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt for (j = 0; j < _VARIABLE_LC_MAX; j++)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (variables[j]) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (print_warning) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt printf("Warning: Settings on Kernel Command Line override system locale settings in /etc/locale.conf\n");
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt printf(" Command Line: %s=%s\n", locale_variable_to_string(j), variables[j]);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt print_warning = false;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt continue;
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt printf(" %s=%s\n", locale_variable_to_string(j), variables[j]);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt finish:
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt for (j = 0; j < _VARIABLE_LC_MAX; j++)
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt free(variables[j]);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic void print_status_info(StatusInfo *i) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert(i);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering if (strv_isempty(i->locale))
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering puts(" System Locale: n/a\n");
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering else {
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering char **j;
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt printf(" System Locale: %s\n", i->locale[0]);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams STRV_FOREACH(j, i->locale + 1)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams printf(" %s\n", *j);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams }
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt printf(" VC Keymap: %s\n", strna(i->vconsole_keymap));
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt if (!isempty(i->vconsole_keymap_toggle))
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams printf("VC Toggle Keymap: %s\n", i->vconsole_keymap_toggle);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams printf(" X11 Layout: %s\n", strna(i->x11_layout));
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (!isempty(i->x11_model))
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt printf(" X11 Model: %s\n", i->x11_model);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (!isempty(i->x11_variant))
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams printf(" X11 Variant: %s\n", i->x11_variant);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (!isempty(i->x11_options))
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams printf(" X11 Options: %s\n", i->x11_options);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams}
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williamsstatic int show_status(sd_bus *bus, char **args, unsigned n) {
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams StatusInfo info = {};
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams static const struct bus_properties_map map[] = {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt { "VConsoleKeymapToggle", "s", NULL, offsetof(StatusInfo, vconsole_keymap_toggle) },
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt { "X11Layout", "s", NULL, offsetof(StatusInfo, x11_layout) },
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering { "X11Model", "s", NULL, offsetof(StatusInfo, x11_model) },
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller { "X11Variant", "s", NULL, offsetof(StatusInfo, x11_variant) },
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller { "X11Options", "s", NULL, offsetof(StatusInfo, x11_options) },
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering { "Locale", "as", NULL, offsetof(StatusInfo, locale) },
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller {}
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller };
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller int r;
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering assert(bus);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering r = bus_map_all_properties(bus,
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams "org.freedesktop.locale1",
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams "/org/freedesktop/locale1",
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams map,
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams &info);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt if (r < 0) {
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt log_error("Could not get properties: %s", strerror(-r));
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen goto fail;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen }
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen print_overriden_variables();
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen print_status_info(&info);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersenfail:
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen strv_free(info.locale);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return r;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen}
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersenstatic int set_locale(sd_bus *bus, char **args, unsigned n) {
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen int r;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen assert(bus);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen assert(args);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen polkit_agent_open_if_enabled();
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen r = sd_bus_message_new_method_call(
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen bus,
ebe207d4acf38165adbc45298662982eecdb9e9fTom Gundersen &m,
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen "org.freedesktop.locale1",
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams "/org/freedesktop/locale1",
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams "org.freedesktop.locale1",
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams "SetLocale");
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams if (r < 0)
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poettering return bus_log_create_error(r);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt r = sd_bus_message_append_strv(m, args + 1);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return bus_log_create_error(r);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_bus_message_append(m, "b", arg_ask_password);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return bus_log_create_error(r);
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poettering
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_bus_call(bus, m, 0, &error, NULL);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic int list_locales(sd_bus *bus, char **args, unsigned n) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt _cleanup_strv_free_ char **l = NULL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(args);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = get_locales(&l);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_error("Failed to read list of locales: %s", strerror(-r));
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt }
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt pager_open_if_enabled();
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt strv_print(l);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return 0;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt const char *map, *toggle_map;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(bus);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(args);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (n > 3) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_error("Too many arguments.");
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -EINVAL;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt }
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt polkit_agent_open_if_enabled();
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt map = args[1];
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt toggle_map = n > 2 ? args[2] : "";
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
e6b18ffaea7d557eec3028a37c043da67a78550cDavid Herrmann r = sd_bus_call_method(
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt bus,
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt "org.freedesktop.locale1",
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt "/org/freedesktop/locale1",
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt "org.freedesktop.locale1",
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt "SetVConsoleKeyboard",
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt &error,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt NULL,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt "ssbb", map, toggle_map, arg_convert, arg_ask_password);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt return r;
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller}
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Hallerstatic Set *keymaps = NULL;
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Hallerstatic int nftw_cb(
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller const char *fpath,
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller const struct stat *sb,
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller int tflag,
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller struct FTW *ftwbuf) {
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char *p, *e;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek if (tflag != FTW_F)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (!endswith(fpath, ".map") &&
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt !endswith(fpath, ".map.gz"))
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return 0;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt p = strdup(basename(fpath));
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (!p)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return log_oom();
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt e = endswith(p, ".map");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (e)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt *e = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt e = endswith(p, ".map.gz");
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (e)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt *e = 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = set_consume(keymaps, p);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0 && r != -EEXIST) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt log_error("Can't add keymap: %s", strerror(-r));
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt return r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt}
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flyktstatic int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt _cleanup_strv_free_ char **l = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt const char *dir;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt keymaps = set_new(&string_hash_ops);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!keymaps)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return log_oom();
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt l = set_get_strv(keymaps);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!l) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt set_free_free(keymaps);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return log_oom();
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt set_free(keymaps);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (strv_isempty(l)) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Couldn't find any console keymaps.");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -ENOENT;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt strv_sort(l);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt pager_open_if_enabled();
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt strv_print(l);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flyktstatic int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen const char *layout, *model, *variant, *options;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt int r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(bus);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(args);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (n > 5) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt log_error("Too many arguments.");
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return -EINVAL;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt polkit_agent_open_if_enabled();
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt layout = args[1];
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt model = n > 2 ? args[2] : "";
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt variant = n > 3 ? args[3] : "";
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt options = n > 4 ? args[4] : "";
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = sd_bus_call_method(
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt bus,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt "org.freedesktop.locale1",
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt "/org/freedesktop/locale1",
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt "org.freedesktop.locale1",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt "SetX11Keyboard",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt &error,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt NULL,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt "ssssbb", layout, model, variant, options,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt arg_convert, arg_ask_password);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt}
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flyktstatic int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt _cleanup_fclose_ FILE *f = NULL;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt _cleanup_strv_free_ char **list = NULL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char line[LINE_MAX];
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt enum {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt NONE,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt MODELS,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt LAYOUTS,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt VARIANTS,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt OPTIONS
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt } state = NONE, look_for;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (n > 2) {
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller log_error("Too many arguments.");
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return -EINVAL;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt f = fopen("/usr/share/X11/xkb/rules/base.lst", "re");
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (!f) {
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt log_error("Failed to open keyboard mapping list. %m");
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt return -errno;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt }
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (streq(args[0], "list-x11-keymap-models"))
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt look_for = MODELS;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt else if (streq(args[0], "list-x11-keymap-layouts"))
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt look_for = LAYOUTS;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt else if (streq(args[0], "list-x11-keymap-variants"))
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt look_for = VARIANTS;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt else if (streq(args[0], "list-x11-keymap-options"))
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt look_for = OPTIONS;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt else
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert_not_reached("Wrong parameter");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt FOREACH_LINE(line, f, break) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char *l, *w;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt l = strstrip(line);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (isempty(l))
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt continue;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (l[0] == '!') {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (startswith(l, "! model"))
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt state = MODELS;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (startswith(l, "! layout"))
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt state = LAYOUTS;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (startswith(l, "! variant"))
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt state = VARIANTS;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (startswith(l, "! option"))
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt state = OPTIONS;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt state = NONE;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt continue;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (state != look_for)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt continue;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt w = l + strcspn(l, WHITESPACE);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (n > 1) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt char *e;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (*w == 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt continue;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt *w = 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt w++;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt w += strspn(w, WHITESPACE);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt e = strchr(w, ':');
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (!e)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt continue;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt *e = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!streq(w, args[1]))
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt continue;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt } else
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt *w = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = strv_extend(&list, l);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return log_oom();
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (strv_isempty(list)) {
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann log_error("Couldn't find any entries.");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -ENOENT;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt strv_sort(list);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt strv_uniq(list);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt pager_open_if_enabled();
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt strv_print(list);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic void help(void) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt printf("%s [OPTIONS...] COMMAND ...\n\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt "Query or change system locale and keyboard settings.\n\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " -h --help Show this help\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " --version Show package version\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " --no-pager Do not pipe output into a pager\n"
4b4923e65423e60d755841b5b264730e8f3deab3Tom Gundersen " --no-ask-password Do not prompt for password\n"
5e91345094a9e983e7abb2313334e7808bcd2cc2Tom Gundersen " -H --host=[USER@]HOST Operate on remote host\n"
513a6fa8679510ea1b55967bdb482dd5f8a39f21Ronny Chevalier " -M --machine=CONTAINER Operate on local container\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " --no-convert Don't convert keyboard mappings\n\n"
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt "Commands:\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " status Show current locale settings\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " set-locale LOCALE... Set system locale\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " list-locales Show known locales\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " set-keymap MAP [MAP] Set virtual console keyboard mapping\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " list-keymaps Show known virtual console keyboard mappings\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " set-x11-keymap LAYOUT [MODEL] [VARIANT] [OPTIONS]\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " Set X11 keyboard mapping\n"
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt " list-x11-keymap-models Show known X11 keyboard mapping models\n"
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt " list-x11-keymap-layouts Show known X11 keyboard mapping layouts\n"
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt " list-x11-keymap-variants [LAYOUT]\n"
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt " Show known X11 keyboard mapping variants\n"
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt " list-x11-keymap-options Show known X11 keyboard mapping options\n"
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt , program_invocation_short_name);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flyktstatic int parse_argv(int argc, char *argv[]) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt enum {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt ARG_VERSION = 0x100,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt ARG_NO_PAGER,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt ARG_NO_CONVERT,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt ARG_NO_ASK_PASSWORD
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt };
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt static const struct option options[] = {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "help", no_argument, NULL, 'h' },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt { "version", no_argument, NULL, ARG_VERSION },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt { "no-pager", no_argument, NULL, ARG_NO_PAGER },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt { "host", required_argument, NULL, 'H' },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt { "machine", required_argument, NULL, 'M' },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt { "no-convert", no_argument, NULL, ARG_NO_CONVERT },
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt {}
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt };
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt int c;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt assert(argc >= 0);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt assert(argv);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt switch (c) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case 'h':
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt help();
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case ARG_VERSION:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt puts(PACKAGE_STRING);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt puts(SYSTEMD_FEATURES);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case ARG_NO_CONVERT:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt arg_convert = false;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt break;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case ARG_NO_PAGER:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt arg_no_pager = true;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt break;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt case ARG_NO_ASK_PASSWORD:
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt arg_ask_password = false;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt break;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt case 'H':
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann arg_transport = BUS_TRANSPORT_REMOTE;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt arg_host = optarg;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt break;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen case 'M':
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt arg_transport = BUS_TRANSPORT_CONTAINER;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt arg_host = optarg;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt break;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt case '?':
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt return -EINVAL;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt default:
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert_not_reached("Unhandled option");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 1;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic int localectl_main(sd_bus *bus, int argc, char *argv[]) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt static const struct {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt const char* verb;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt const enum {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt MORE,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt LESS,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt EQUAL
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt } argc_cmp;
ed19c567e5fcdcec1a2b6dbac63787e001ad5d55Tom Gundersen const int argc;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt } verbs[] = {
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen { "status", LESS, 1, show_status },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "set-locale", MORE, 2, set_locale },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "list-locales", EQUAL, 1, list_locales },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "set-keymap", MORE, 2, set_vconsole_keymap },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "list-keymaps", EQUAL, 1, list_vconsole_keymaps },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "set-x11-keymap", MORE, 2, set_x11_keymap },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "list-x11-keymap-models", EQUAL, 1, list_x11_keymaps },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "list-x11-keymap-layouts", EQUAL, 1, list_x11_keymaps },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "list-x11-keymap-variants", LESS, 2, list_x11_keymaps },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt { "list-x11-keymap-options", EQUAL, 1, list_x11_keymaps },
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt };
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering int left;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen unsigned i;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen assert(argc >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(argv);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt left = argc - optind;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (left <= 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Special rule: no arguments means "status" */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt i = 0;
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen else {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (streq(argv[optind], "help")) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt help();
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt for (i = 0; i < ELEMENTSOF(verbs); i++)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (streq(argv[optind], verbs[i].verb))
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt break;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (i >= ELEMENTSOF(verbs)) {
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen log_error("Unknown operation %s", argv[optind]);
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering return -EINVAL;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen }
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt switch (verbs[i].argc_cmp) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt case EQUAL:
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (left != verbs[i].argc) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Invalid number of arguments.");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -EINVAL;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt break;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt case MORE:
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (left < verbs[i].argc) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Too few arguments.");
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EINVAL;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen break;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen case LESS:
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (left > verbs[i].argc) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Too many arguments.");
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EINVAL;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt default:
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek assert_not_reached("Unknown comparison operator.");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return verbs[i].dispatch(bus, argv + optind, left);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmekint main(int argc, char*argv[]) {
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek _cleanup_bus_close_unref_ sd_bus *bus = NULL;
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek int r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt setlocale(LC_ALL, "");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_parse_environment();
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_open();
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = parse_argv(argc, argv);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r <= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto finish;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = bus_open_transport(arg_transport, arg_host, false, &bus);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Failed to create bus connection: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto finish;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = localectl_main(bus, argc, argv);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktfinish:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt pager_close();
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt