gnu: Add localed, extracted from systemd.

* gnu/packages/freedesktop.scm (localed): New variable.
* gnu/packages/patches/localed-xorg-keyboard.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
This commit is contained in:
Ludovic Courtès 2019-04-02 22:33:22 +02:00
parent b68f65007f
commit f63861b5a6
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
3 changed files with 469 additions and 0 deletions

View File

@ -937,6 +937,7 @@ dist_patch_DATA = \
%D%/packages/patches/kdbusaddons-kinit-file-name.patch \ %D%/packages/patches/kdbusaddons-kinit-file-name.patch \
%D%/packages/patches/khmer-use-libraries.patch \ %D%/packages/patches/khmer-use-libraries.patch \
%D%/packages/patches/libziparchive-add-includes.patch \ %D%/packages/patches/libziparchive-add-includes.patch \
%D%/packages/patches/localed-xorg-keyboard.patch \
%D%/packages/patches/kiki-level-selection-crash.patch \ %D%/packages/patches/kiki-level-selection-crash.patch \
%D%/packages/patches/kiki-makefile.patch \ %D%/packages/patches/kiki-makefile.patch \
%D%/packages/patches/kiki-missing-includes.patch \ %D%/packages/patches/kiki-missing-includes.patch \

View File

@ -307,6 +307,152 @@ the org.freedesktop.login1 interface over the system bus, allowing other parts
of a the system to know what users are logged in, and where.") of a the system to know what users are logged in, and where.")
(license license:lgpl2.1+))) (license license:lgpl2.1+)))
(define-public localed
;; XXX: This package is extracted from systemd but we retain so little of it
;; that it would make more sense to maintain a fork of the bits we need.
(package
(name "localed")
(version "241")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/systemd/systemd")
(commit (string-append "v" version))))
(sha256
(base32
"0sy91flzbhpq58k7v0294pa2gxpr0bk27rcnxlbhk2fi6nc51d28"))
(file-name (git-file-name name version))
(modules '((guix build utils)))
(snippet
'(begin
;; Connect to the right location for our D-Bus daemon.
(substitute* '("src/basic/def.h"
"src/libsystemd/sd-bus/sd-bus.c"
"src/stdio-bridge/stdio-bridge.c")
(("/run/dbus/system_bus_socket")
"/var/run/dbus/system_bus_socket"))
;; Don't insist on having systemd as PID 1 (otherwise
;; 'localectl' would exit without doing anything.)
(substitute* "src/shared/bus-util.c"
(("sd_booted\\(\\)")
"(1)"))
#t))
(patches (search-patches "localed-xorg-keyboard.patch"))))
(build-system meson-build-system)
(arguments
;; Try to build as little as possible (list of components taken from the
;; top-level 'meson.build' file.)
(let ((components '("utmp"
"hibernate"
"environment-d"
"binfmt"
"coredump"
"resolve"
"logind"
"hostnamed"
"localed"
"machined"
"portabled"
"networkd"
"timedated"
"timesyncd"
"firstboot"
"randomseed"
"backlight"
"vconsole"
"quotacheck"
"sysusers"
"tmpfiles"
"hwdb"
"rfkill"
"ldconfig"
"efi"
"tpm"
"ima"
"smack"
"gshadow"
"idn"
"nss-myhostname"
"nss-systemd")))
`(#:configure-flags ',(map (lambda (component)
(string-append "-D" component "=false"))
(delete "localed" components))
;; It doesn't make sense to test all of systemd.
#:tests? #f
#:phases (modify-phases %standard-phases
(add-after 'unpack 'set-xkeyboard-config-file-name
(lambda* (#:key inputs #:allow-other-keys)
;; Set the file name to xkeyboard-config and kbd.
;; This is used by 'localectl list-x11-keymap-layouts'
;; and similar functions.
(let ((xkb (assoc-ref inputs "xkeyboard-config"))
(kbd (assoc-ref inputs "kbd")))
(substitute* "src/locale/localectl.c"
(("/usr/share/X11/xkb/rules")
(string-append xkb "/share/X11/xkb/rules")))
(substitute* "src/basic/def.h"
(("/usr/share/keymaps")
(string-append kbd "/share/keymaps")))
#t)))
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
;; Install 'localed', the D-Bus and polkit files, and
;; 'localectl'.
(let* ((out (assoc-ref outputs "out"))
(libexec (string-append out "/libexec/localed"))
(bin (string-append out "/bin"))
(lib (string-append out "/lib"))
(dbus (string-append out
"/share/dbus-1/system-services"))
(conf (string-append out
"/etc/dbus-1/system.d/"))
(polkit (string-append out
"/share/polkit-1/actions"))
(data (string-append out "/share/systemd")))
(define (source-file regexp)
(car (find-files ".." regexp)))
(mkdir-p libexec)
(copy-file "systemd-localed"
(string-append libexec "/localed"))
(install-file "localectl" bin)
(let ((service-file (source-file
"\\.locale1\\.service$")))
(substitute* service-file
(("^Exec=.*$")
(string-append "Exec=" libexec "/localed\n")))
(install-file service-file dbus))
(install-file (source-file "\\.locale1\\.policy$")
polkit)
(install-file (source-file "\\.locale1\\.conf$")
conf)
(for-each (lambda (file)
(install-file file lib))
(find-files "src/shared"
"libsystemd-shared.*\\.so"))
(for-each (lambda (map)
(install-file map data))
(find-files ".." "^(kbd-model-map|language-fallback-map)$"))
#t)))))))
(native-inputs (package-native-inputs elogind))
(inputs `(("libmount" ,util-linux)
("xkeyboard-config" ,xkeyboard-config)
("kbd" ,kbd)
,@(package-inputs elogind)))
(home-page "https://www.freedesktop.org/wiki/Software/systemd/localed/")
(synopsis "Control the system locale and keyboard layout")
(description
"Localed is a tiny daemon that can be used to control the system locale
and keyboard mapping from user programs. It is used among other things by the
GNOME Shell. The @command{localectl} command-line tool allows you to interact
with localed. This package is extracted from the broader systemd package.")
(license license:lgpl2.1+)))
(define-public packagekit (define-public packagekit
(package (package
(name "packagekit") (name "packagekit")

View File

@ -0,0 +1,322 @@
Normally localed would do an approximate parsing of the Xorg config file
to determine the XKB keyboard layout. This doesn't make sense on Guix
where there's no such file in /etc, and where the keyboard layout is
known statically at configuration time.
This patch removes the XOrg configuration parsing and expects to read the
configuration from environment variables instead. It also removes the
stateful bits that would write configuration to /etc/vconsole.conf
and /etc/X11, which are unused in Guix anyway.
Patch by Ludovic Courtès <ludo@gnu.org>.
diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
index 6b6b32a591..46aab472b0 100644
--- a/src/locale/keymap-util.c
+++ b/src/locale/keymap-util.c
@@ -174,32 +174,16 @@ int vconsole_read_data(Context *c, sd_bus_message *m) {
c->vc_cache = sd_bus_message_ref(m);
}
- if (stat("/etc/vconsole.conf", &st) < 0) {
- if (errno != ENOENT)
- return -errno;
-
- c->vc_mtime = USEC_INFINITY;
- context_free_vconsole(c);
- return 0;
- }
-
- /* If mtime is not changed, then we do not need to re-read */
- t = timespec_load(&st.st_mtim);
- if (c->vc_mtime != USEC_INFINITY && t == c->vc_mtime)
- return 0;
-
- c->vc_mtime = t;
+ c->vc_mtime = USEC_INFINITY;
context_free_vconsole(c);
-
- r = parse_env_file(NULL, "/etc/vconsole.conf",
- "KEYMAP", &c->vc_keymap,
- "KEYMAP_TOGGLE", &c->vc_keymap_toggle);
- if (r < 0)
- return r;
-
return 0;
}
+static char *getenv_strdup(const char *variable) {
+ const char *value = getenv(variable);
+ return value == NULL ? NULL : strdup(value);
+}
+
int x11_read_data(Context *c, sd_bus_message *m) {
_cleanup_fclose_ FILE *f = NULL;
bool in_section = false;
@@ -216,258 +200,27 @@ int x11_read_data(Context *c, sd_bus_message *m) {
c->x11_cache = sd_bus_message_ref(m);
}
- if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) {
- if (errno != ENOENT)
- return -errno;
-
- c->x11_mtime = USEC_INFINITY;
- context_free_x11(c);
- return 0;
- }
-
- /* If mtime is not changed, then we do not need to re-read */
- t = timespec_load(&st.st_mtim);
- if (c->x11_mtime != USEC_INFINITY && t == c->x11_mtime)
- return 0;
-
- c->x11_mtime = t;
+ c->x11_mtime = 0;
context_free_x11(c);
- f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
- if (!f)
- return -errno;
-
- for (;;) {
- _cleanup_free_ char *line = NULL;
- char *l;
-
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- l = strstrip(line);
- if (IN_SET(l[0], 0, '#'))
- continue;
-
- if (in_section && first_word(l, "Option")) {
- _cleanup_strv_free_ char **a = NULL;
-
- r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES);
- if (r < 0)
- return r;
-
- if (strv_length(a) == 3) {
- char **p = NULL;
-
- if (streq(a[1], "XkbLayout"))
- p = &c->x11_layout;
- else if (streq(a[1], "XkbModel"))
- p = &c->x11_model;
- else if (streq(a[1], "XkbVariant"))
- p = &c->x11_variant;
- else if (streq(a[1], "XkbOptions"))
- p = &c->x11_options;
-
- if (p) {
- free_and_replace(*p, a[2]);
- }
- }
-
- } else if (!in_section && first_word(l, "Section")) {
- _cleanup_strv_free_ char **a = NULL;
-
- r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES);
- if (r < 0)
- return -ENOMEM;
-
- if (strv_length(a) == 2 && streq(a[1], "InputClass"))
- in_section = true;
-
- } else if (in_section && first_word(l, "EndSection"))
- in_section = false;
- }
+ c->x11_layout = getenv_strdup("GUIX_XKB_LAYOUT");
+ c->x11_model = getenv_strdup("GUIX_XKB_MODEL");
+ c->x11_variant = getenv_strdup("GUIX_XKB_VARIANT");
+ c->x11_options = getenv_strdup("GUIX_XKB_OPTIONS");
return 0;
}
int locale_write_data(Context *c, char ***settings) {
- _cleanup_strv_free_ char **l = NULL;
- struct stat st;
- int r, p;
-
- /* Set values will be returned as strv in *settings on success. */
-
- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
- _cleanup_free_ char *t = NULL;
- char **u;
- const char *name;
-
- name = locale_variable_to_string(p);
- assert(name);
-
- if (isempty(c->locale[p]))
- continue;
-
- if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0)
- return -ENOMEM;
-
- u = strv_env_set(l, t);
- if (!u)
- return -ENOMEM;
-
- strv_free_and_replace(l, u);
- }
-
- if (strv_isempty(l)) {
- if (unlink("/etc/locale.conf") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- c->locale_mtime = USEC_INFINITY;
- return 0;
- }
-
- r = write_env_file_label("/etc/locale.conf", l);
- if (r < 0)
- return r;
-
- *settings = TAKE_PTR(l);
-
- if (stat("/etc/locale.conf", &st) >= 0)
- c->locale_mtime = timespec_load(&st.st_mtim);
-
- return 0;
+ return -ENOSYS;
}
int vconsole_write_data(Context *c) {
- _cleanup_strv_free_ char **l = NULL;
- struct stat st;
- int r;
-
- r = load_env_file(NULL, "/etc/vconsole.conf", &l);
- if (r < 0 && r != -ENOENT)
- return r;
-
- if (isempty(c->vc_keymap))
- l = strv_env_unset(l, "KEYMAP");
- else {
- _cleanup_free_ char *s = NULL;
- char **u;
-
- s = strappend("KEYMAP=", c->vc_keymap);
- if (!s)
- return -ENOMEM;
-
- u = strv_env_set(l, s);
- if (!u)
- return -ENOMEM;
-
- strv_free_and_replace(l, u);
- }
-
- if (isempty(c->vc_keymap_toggle))
- l = strv_env_unset(l, "KEYMAP_TOGGLE");
- else {
- _cleanup_free_ char *s = NULL;
- char **u;
-
- s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
- if (!s)
- return -ENOMEM;
-
- u = strv_env_set(l, s);
- if (!u)
- return -ENOMEM;
-
- strv_free_and_replace(l, u);
- }
-
- if (strv_isempty(l)) {
- if (unlink("/etc/vconsole.conf") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- c->vc_mtime = USEC_INFINITY;
- return 0;
- }
-
- r = write_env_file_label("/etc/vconsole.conf", l);
- if (r < 0)
- return r;
-
- if (stat("/etc/vconsole.conf", &st) >= 0)
- c->vc_mtime = timespec_load(&st.st_mtim);
-
- return 0;
+ return -ENOSYS;
}
int x11_write_data(Context *c) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *temp_path = NULL;
- struct stat st;
- int r;
-
- if (isempty(c->x11_layout) &&
- isempty(c->x11_model) &&
- isempty(c->x11_variant) &&
- isempty(c->x11_options)) {
-
- if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- c->vc_mtime = USEC_INFINITY;
- return 0;
- }
-
- mkdir_p_label("/etc/X11/xorg.conf.d", 0755);
-
- r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
- if (r < 0)
- return r;
-
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
- (void) fchmod(fileno(f), 0644);
-
- fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n"
- "# probably wise not to edit this file manually. Use localectl(1) to\n"
- "# instruct systemd-localed to update it.\n"
- "Section \"InputClass\"\n"
- " Identifier \"system-keyboard\"\n"
- " MatchIsKeyboard \"on\"\n", f);
-
- if (!isempty(c->x11_layout))
- fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout);
-
- if (!isempty(c->x11_model))
- fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model);
-
- if (!isempty(c->x11_variant))
- fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant);
-
- if (!isempty(c->x11_options))
- fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options);
-
- fputs("EndSection\n", f);
-
- r = fflush_sync_and_check(f);
- if (r < 0)
- goto fail;
-
- if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
- r = -errno;
- goto fail;
- }
-
- if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) >= 0)
- c->x11_mtime = timespec_load(&st.st_mtim);
-
- return 0;
-
-fail:
- if (temp_path)
- (void) unlink(temp_path);
-
- return r;
+ return -ENOSYS;
}
static int read_next_mapping(const char* filename,