unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
* [bug#35118] [PATCH 0/4] Add localed, fixing keyboard layout in GDM
@ 2019-04-03  9:41 Ludovic Courtès
  2019-04-03  9:44 ` [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service' Ludovic Courtès
  2019-04-05 13:47 ` bug#35118: [PATCH 0/4] Add localed, fixing keyboard layout in GDM Ludovic Courtès
  0 siblings, 2 replies; 6+ messages in thread
From: Ludovic Courtès @ 2019-04-03  9:41 UTC (permalink / raw)
  To: 35118

Hello Guix!

This patch adds localed, a D-Bus service for keyboard layout
and “locales” (not quite actually):

  https://www.freedesktop.org/wiki/Software/systemd/localed/

The only motivation was to fix keyboard layout in GDM: until
now, GDM would always install a US English layout, regardless
of how we configured Xorg.  It did that because it tried to
ask localed about the current keyboard layout, but since that
daemon was unavailable, it would assume that the current layout
is US English and tell XKB to install it.

You would think that it would simply ask X to know what the
current layout is—after all, X knows that first-hand.  But no!
Instead, there’s this localed daemon that normally goes ahead
and greps /etc/X11/xorg.d/00-keyboard.conf in search of
“XkbLayout” and similar options.

This patch modifies localed so that it gets this information
directly from environment variables set by our ‘localed’ service;
their values is inherited from the ‘xorg-configuration’ field of
<gdm-configuration>.

This is all pretty ugly.  Regarding localed itself, I think we
should maintain our own fork since we really just need a couple
of files from systemd.  That would require disentangling the code
from systemd’s own support functions (like its D-Bus API wrapper).
That should be easy for someone who’s ever played with D-Bus in
C, but that’s not me.  :-)

Another option, of course, is to write a D-Bus implementation in
Guile and do the whole thing in Guile.  Shave a yak!

Anyway, in the meantime, this thing does the job.

Thoughts?

Ludo’.

Ludovic Courtès (4):
  services: dbus: Add 'wrapped-dbus-service'.
  gnu: Add localed, extracted from systemd.
  services: dbus: 'wrapped-dbus-service' accepts a list of variables.
  services: Add 'localed' service type and have GDM extend it.

 gnu/local.mk                                  |   1 +
 gnu/packages/freedesktop.scm                  | 148 +++++++-
 .../patches/localed-xorg-keyboard.patch       | 322 ++++++++++++++++++
 gnu/services/dbus.scm                         |  48 +++
 gnu/services/desktop.scm                      |  52 +--
 gnu/services/xorg.scm                         |  89 ++++-
 6 files changed, 612 insertions(+), 48 deletions(-)
 create mode 100644 gnu/packages/patches/localed-xorg-keyboard.patch

-- 
2.21.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service'.
  2019-04-03  9:41 [bug#35118] [PATCH 0/4] Add localed, fixing keyboard layout in GDM Ludovic Courtès
@ 2019-04-03  9:44 ` Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 2/4] gnu: Add localed, extracted from systemd Ludovic Courtès
                     ` (2 more replies)
  2019-04-05 13:47 ` bug#35118: [PATCH 0/4] Add localed, fixing keyboard layout in GDM Ludovic Courtès
  1 sibling, 3 replies; 6+ messages in thread
From: Ludovic Courtès @ 2019-04-03  9:44 UTC (permalink / raw)
  To: 35118

* gnu/services/desktop.scm (wrapped-dbus-service): Move to...
* gnu/services/dbus.scm (wrapped-dbus-service): ... here.  New
procedure.
---
 gnu/services/dbus.scm    | 42 ++++++++++++++++++++++++++++++++++++++++
 gnu/services/desktop.scm | 40 --------------------------------------
 2 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/gnu/services/dbus.scm b/gnu/services/dbus.scm
index 606ee0c2f5..3d2dbb903c 100644
--- a/gnu/services/dbus.scm
+++ b/gnu/services/dbus.scm
@@ -26,6 +26,7 @@
   #:use-module (gnu packages polkit)
   #:use-module (gnu packages admin)
   #:use-module (guix gexp)
+  #:use-module ((guix packages) #:select (package-name))
   #:use-module (guix records)
   #:use-module (srfi srfi-1)
   #:use-module (ice-9 match)
@@ -33,6 +34,7 @@
             dbus-configuration?
             dbus-root-service-type
             dbus-service
+            wrapped-dbus-service
 
             polkit-service-type
             polkit-service))
@@ -229,6 +231,46 @@ and policy files.  For example, to allow avahi-daemon to use the system bus,
            (dbus-configuration (dbus dbus)
                                (services services))))
 
+(define (wrapped-dbus-service service program variable value)
+  "Return a wrapper for @var{service}, a package containing a D-Bus service,
+where @var{program} is wrapped such that environment variable @var{variable}
+is set to @var{value} when the bus daemon launches it."
+  (define wrapper
+    (program-file (string-append (package-name service) "-program-wrapper")
+                  #~(begin
+                      (setenv #$variable #$value)
+                      (apply execl (string-append #$service "/" #$program)
+                             (string-append #$service "/" #$program)
+                             (cdr (command-line))))))
+
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils))
+
+          (define service-directory
+            "/share/dbus-1/system-services")
+
+          (mkdir-p (dirname (string-append #$output
+                                           service-directory)))
+          (copy-recursively (string-append #$service
+                                           service-directory)
+                            (string-append #$output
+                                           service-directory))
+          (symlink (string-append #$service "/etc") ;for etc/dbus-1
+                   (string-append #$output "/etc"))
+
+          (for-each (lambda (file)
+                      (substitute* file
+                        (("Exec[[:blank:]]*=[[:blank:]]*([[:graph:]]+)(.*)$"
+                          _ original-program arguments)
+                         (string-append "Exec=" #$wrapper arguments
+                                        "\n"))))
+                    (find-files #$output "\\.service$")))))
+
+  (computed-file (string-append (package-name service) "-wrapper")
+                 build))
+
 \f
 ;;;
 ;;; Polkit privilege management service.
diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index dcab950822..230aeb324c 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -150,46 +150,6 @@
       ((package . _) package))))
 
 
-(define (wrapped-dbus-service service program variable value)
-  "Return a wrapper for @var{service}, a package containing a D-Bus service,
-where @var{program} is wrapped such that environment variable @var{variable}
-is set to @var{value} when the bus daemon launches it."
-  (define wrapper
-    (program-file (string-append (package-name service) "-program-wrapper")
-                  #~(begin
-                      (setenv #$variable #$value)
-                      (apply execl (string-append #$service "/" #$program)
-                             (string-append #$service "/" #$program)
-                             (cdr (command-line))))))
-
-  (define build
-    (with-imported-modules '((guix build utils))
-      #~(begin
-          (use-modules (guix build utils))
-
-          (define service-directory
-            "/share/dbus-1/system-services")
-
-          (mkdir-p (dirname (string-append #$output
-                                           service-directory)))
-          (copy-recursively (string-append #$service
-                                           service-directory)
-                            (string-append #$output
-                                           service-directory))
-          (symlink (string-append #$service "/etc") ;for etc/dbus-1
-                   (string-append #$output "/etc"))
-
-          (for-each (lambda (file)
-                      (substitute* file
-                        (("Exec[[:blank:]]*=[[:blank:]]*([[:graph:]]+)(.*)$"
-                          _ original-program arguments)
-                         (string-append "Exec=" #$wrapper arguments
-                                        "\n"))))
-                    (find-files #$output "\\.service$")))))
-
-  (computed-file (string-append (package-name service) "-wrapper")
-                 build))
-
 \f
 ;;;
 ;;; Upower D-Bus service.
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [bug#35118] [PATCH 2/4] gnu: Add localed, extracted from systemd.
  2019-04-03  9:44 ` [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service' Ludovic Courtès
@ 2019-04-03  9:44   ` Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 3/4] services: dbus: 'wrapped-dbus-service' accepts a list of variables Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 4/4] services: Add 'localed' service type and have GDM extend it Ludovic Courtès
  2 siblings, 0 replies; 6+ messages in thread
From: Ludovic Courtès @ 2019-04-03  9:44 UTC (permalink / raw)
  To: 35118

* gnu/packages/freedesktop.scm (localed): New variable.
* gnu/packages/patches/localed-xorg-keyboard.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
---
 gnu/local.mk                                  |   1 +
 gnu/packages/freedesktop.scm                  | 148 +++++++-
 .../patches/localed-xorg-keyboard.patch       | 322 ++++++++++++++++++
 3 files changed, 470 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/localed-xorg-keyboard.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 45598d4e14..5c86ee0809 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -929,6 +929,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/kdbusaddons-kinit-file-name.patch	\
   %D%/packages/patches/khmer-use-libraries.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-makefile.patch			\
   %D%/packages/patches/kiki-missing-includes.patch		\
diff --git a/gnu/packages/freedesktop.scm b/gnu/packages/freedesktop.scm
index 56aeca0478..ec8688d2d4 100644
--- a/gnu/packages/freedesktop.scm
+++ b/gnu/packages/freedesktop.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2015, 2017 Andy Wingo <wingo@pobox.com>
-;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2017, 2019 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015, 2017, 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 David Hashe <david.hashe@dhashe.com>
 ;;; Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
@@ -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.")
     (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 of 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
   (package
     (name "packagekit")
diff --git a/gnu/packages/patches/localed-xorg-keyboard.patch b/gnu/packages/patches/localed-xorg-keyboard.patch
new file mode 100644
index 0000000000..9a9071ba0a
--- /dev/null
+++ b/gnu/packages/patches/localed-xorg-keyboard.patch
@@ -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,
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [bug#35118] [PATCH 3/4] services: dbus: 'wrapped-dbus-service' accepts a list of variables.
  2019-04-03  9:44 ` [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service' Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 2/4] gnu: Add localed, extracted from systemd Ludovic Courtès
@ 2019-04-03  9:44   ` Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 4/4] services: Add 'localed' service type and have GDM extend it Ludovic Courtès
  2 siblings, 0 replies; 6+ messages in thread
From: Ludovic Courtès @ 2019-04-03  9:44 UTC (permalink / raw)
  To: 35118

* gnu/services/dbus.scm (wrapped-dbus-service): Replace 'variable' and
'value' by 'variables', and adjust code accordingly.
* gnu/services/desktop.scm (upower-dbus-service):
(geoclue-dbus-service, elogind-dbus-service): Adjust accordingly.
---
 gnu/services/dbus.scm    | 14 ++++++++++----
 gnu/services/desktop.scm | 12 ++++++------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/gnu/services/dbus.scm b/gnu/services/dbus.scm
index 3d2dbb903c..35d7ff3c9c 100644
--- a/gnu/services/dbus.scm
+++ b/gnu/services/dbus.scm
@@ -231,14 +231,20 @@ and policy files.  For example, to allow avahi-daemon to use the system bus,
            (dbus-configuration (dbus dbus)
                                (services services))))
 
-(define (wrapped-dbus-service service program variable value)
+(define (wrapped-dbus-service service program variables)
   "Return a wrapper for @var{service}, a package containing a D-Bus service,
-where @var{program} is wrapped such that environment variable @var{variable}
-is set to @var{value} when the bus daemon launches it."
+where @var{program} is wrapped such that @var{variables}, a list of name/value
+tuples, are all set as environment variables when the bus daemon launches it."
   (define wrapper
     (program-file (string-append (package-name service) "-program-wrapper")
                   #~(begin
-                      (setenv #$variable #$value)
+                      (use-modules (ice-9 match))
+
+                      (for-each (match-lambda
+                                  ((variable value)
+                                   (setenv variable value)))
+                                '#$variables)
+
                       (apply execl (string-append #$service "/" #$program)
                              (string-append #$service "/" #$program)
                              (cdr (command-line))))))
diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index 230aeb324c..578095b146 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -217,8 +217,8 @@
 (define (upower-dbus-service config)
   (list (wrapped-dbus-service (upower-configuration-upower config)
                               "libexec/upowerd"
-                              "UPOWER_CONF_FILE_NAME"
-                              (upower-configuration-file config))))
+                              `(("UPOWER_CONF_FILE_NAME"
+                                 ,(upower-configuration-file config))))))
 
 (define (upower-shepherd-service config)
   "Return a shepherd service for UPower with CONFIG."
@@ -349,8 +349,8 @@ users are allowed."
 (define (geoclue-dbus-service config)
   (list (wrapped-dbus-service (geoclue-configuration-geoclue config)
                               "libexec/geoclue"
-                              "GEOCLUE_CONFIG_FILE"
-                              (geoclue-configuration-file config))))
+                              `(("GEOCLUE_CONFIG_FILE"
+                                 ,(geoclue-configuration-file config))))))
 
 (define %geoclue-accounts
   (list (user-group (name "geoclue") (system? #t))
@@ -702,8 +702,8 @@ include the @command{udisksctl} command, part of UDisks, and GNOME Disks."
 (define (elogind-dbus-service config)
   (list (wrapped-dbus-service (elogind-package config)
                               "libexec/elogind/elogind"
-                              "ELOGIND_CONF_FILE"
-                              (elogind-configuration-file config))))
+                              `(("ELOGIND_CONF_FILE"
+                                 ,(elogind-configuration-file config))))))
 
 (define (pam-extension-procedure config)
   "Return an extension for PAM-ROOT-SERVICE-TYPE that ensures that all the PAM
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [bug#35118] [PATCH 4/4] services: Add 'localed' service type and have GDM extend it.
  2019-04-03  9:44 ` [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service' Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 2/4] gnu: Add localed, extracted from systemd Ludovic Courtès
  2019-04-03  9:44   ` [bug#35118] [PATCH 3/4] services: dbus: 'wrapped-dbus-service' accepts a list of variables Ludovic Courtès
@ 2019-04-03  9:44   ` Ludovic Courtès
  2 siblings, 0 replies; 6+ messages in thread
From: Ludovic Courtès @ 2019-04-03  9:44 UTC (permalink / raw)
  To: 35118

This fixes a bug whereby GDM would always switch to US English keyboard
layout regardless to the configured Xorg keyboard layout.

* gnu/services/xorg.scm (<localed-configuration>): New record type.
(localed-dbus-service): New procedure.
(localed-service-type): New variable.
(gdm-service-type): Extend LOCALED-SERVICE-TYPE.
---
 gnu/services/xorg.scm | 89 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/gnu/services/xorg.scm b/gnu/services/xorg.scm
index 29c7f30013..7745f9a3cc 100644
--- a/gnu/services/xorg.scm
+++ b/gnu/services/xorg.scm
@@ -27,6 +27,7 @@
   #:use-module (gnu services shepherd)
   #:use-module (gnu system pam)
   #:use-module (gnu system keyboard)
+  #:use-module (gnu services base)
   #:use-module (gnu services dbus)
   #:use-module ((gnu packages base) #:select (canonical-package))
   #:use-module (gnu packages guile)
@@ -35,6 +36,7 @@
   #:use-module (gnu packages gl)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages display-managers)
+  #:use-module (gnu packages freedesktop)
   #:use-module (gnu packages gnustep)
   #:use-module (gnu packages gnome)
   #:use-module (gnu packages admin)
@@ -91,6 +93,10 @@
             screen-locker-service-type
             screen-locker-service
 
+            localed-configuration
+            localed-configuration?
+            localed-service-type
+
             gdm-configuration
             gdm-service-type
             gdm-service))
@@ -653,6 +659,82 @@ makes the good ol' XlockMore usable."
                           (file-append package "/bin/" program)
                           allow-empty-passwords?)))
 
+\f
+;;;
+;;; Locale service.
+;;;
+
+(define-record-type* <localed-configuration>
+  localed-configuration make-localed-configuration
+  localed-configuration?
+  (localed         localed-configuration-localed
+                   (default localed))
+  (keyboard-layout localed-configuration-keyboard-layout
+                   (default #f)))
+
+(define (localed-dbus-service config)
+  "Return the 'localed' D-Bus service for @var{config}, a
+@code{<localed-configuration>} record."
+  (define keyboard-layout
+    (localed-configuration-keyboard-layout config))
+
+  ;; The primary purpose of 'localed' is to tell GDM what the "current" Xorg
+  ;; keyboard layout is.  If 'localed' is missing, or if it's unable to
+  ;; determine the current XKB layout, then GDM forcefully installs its
+  ;; default XKB config (US English).  Here we communicate the configured
+  ;; layout through environment variables.
+
+  (if keyboard-layout
+      (let* ((layout  (keyboard-layout-name keyboard-layout))
+             (variant (keyboard-layout-variant keyboard-layout))
+             (model   (keyboard-layout-model keyboard-layout))
+             (options (keyboard-layout-options keyboard-layout)))
+        (list (wrapped-dbus-service
+               (localed-configuration-localed config)
+               "libexec/localed/localed"
+               `(("GUIX_XKB_LAYOUT" ,layout)
+                 ,@(if variant
+                       `(("GUIX_XKB_VARIANT" ,variant))
+                       '())
+                 ,@(if model
+                       `(("GUIX_XKB_MODEL" ,model))
+                       '())
+                 ,@(if (null? options)
+                       '()
+                       `(("GUIX_XKB_OPTIONS"
+                          ,(string-join options ","))))))))
+      (localed-configuration-localed config)))
+
+(define localed-service-type
+  (let ((package (compose list localed-configuration-localed)))
+    (service-type (name 'localed)
+                  (extensions
+                   (list (service-extension dbus-root-service-type
+                                            localed-dbus-service)
+                         (service-extension udev-service-type package)
+                         (service-extension polkit-service-type package)
+
+                         ;; Add 'localectl' to the profile.
+                         (service-extension profile-service-type package)))
+
+                  ;; This service can be extended, typically by the X login
+                  ;; manager, to communicate the chosen Xorg keyboard layout.
+                  (compose first)
+                  (extend (lambda (config keyboard-layout)
+                            (localed-configuration
+                             (inherit config)
+                             (keyboard-layout keyboard-layout))))
+                  (description
+                   "Run the locale daemon, @command{localed}, which can be used
+to control the system locale and keyboard mapping from user programs such as
+the GNOME desktop environment.")
+                  (default-value (localed-configuration)))))
+
+\f
+;;;
+;;; GNOME Desktop Manager.
+;;;
+
 (define %gdm-accounts
   (list (user-group (name "gdm") (system? #t))
         (user-account
@@ -787,7 +869,12 @@ makes the good ol' XlockMore usable."
                                           gdm-configuration-gnome-shell-assets)
                        (service-extension dbus-root-service-type
                                           (compose list
-                                                   gdm-configuration-gdm))))
+                                                   gdm-configuration-gdm))
+                       (service-extension localed-service-type
+                                          (compose
+                                           xorg-configuration-keyboard-layout
+                                           gdm-configuration-xorg))))
+
                 (default-value (gdm-configuration))
                 (description
                  "Run the GNOME Desktop Manager (GDM), a program that allows
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* bug#35118: [PATCH 0/4] Add localed, fixing keyboard layout in GDM
  2019-04-03  9:41 [bug#35118] [PATCH 0/4] Add localed, fixing keyboard layout in GDM Ludovic Courtès
  2019-04-03  9:44 ` [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service' Ludovic Courtès
@ 2019-04-05 13:47 ` Ludovic Courtès
  1 sibling, 0 replies; 6+ messages in thread
From: Ludovic Courtès @ 2019-04-05 13:47 UTC (permalink / raw)
  To: 35118-done

Hello,

Pushed!

Ludovic Courtès <ludo@gnu.org> skribis:

> This is all pretty ugly.  Regarding localed itself, I think we
> should maintain our own fork since we really just need a couple
> of files from systemd.  That would require disentangling the code
> from systemd’s own support functions (like its D-Bus API wrapper).
> That should be easy for someone who’s ever played with D-Bus in
> C, but that’s not me.  :-)

As discussed on IRC with Julien and others, I tried to actually fork
systemd and strip everything but src/locale.  Unfortunately that turned
out to be pretty tricky because of all the systemd-internal utilities
being used (allocation, string manipulation, etc.)

If someone is willing to give it a try, I can share what I have so far!

Ludo’.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-04-05 13:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-03  9:41 [bug#35118] [PATCH 0/4] Add localed, fixing keyboard layout in GDM Ludovic Courtès
2019-04-03  9:44 ` [bug#35118] [PATCH 1/4] services: dbus: Add 'wrapped-dbus-service' Ludovic Courtès
2019-04-03  9:44   ` [bug#35118] [PATCH 2/4] gnu: Add localed, extracted from systemd Ludovic Courtès
2019-04-03  9:44   ` [bug#35118] [PATCH 3/4] services: dbus: 'wrapped-dbus-service' accepts a list of variables Ludovic Courtès
2019-04-03  9:44   ` [bug#35118] [PATCH 4/4] services: Add 'localed' service type and have GDM extend it Ludovic Courtès
2019-04-05 13:47 ` bug#35118: [PATCH 0/4] Add localed, fixing keyboard layout in GDM Ludovic Courtès

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).