]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
locale: split out xkbcommon related functions to xkbcommon-util.c
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 1 Feb 2023 17:47:47 +0000 (02:47 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 25 Mar 2023 06:27:23 +0000 (15:27 +0900)
Then, use dlopen_many_sym_or_warn() with DLSYM_ARG() macro.

meson.build
src/locale/localed.c
src/locale/meson.build
src/locale/xkbcommon-util.c [new file with mode: 0644]
src/locale/xkbcommon-util.h [new file with mode: 0644]

index 6770deed4ff11a41d4e8cc68386d802a50b982eb..b624c6d8f02c91d62a6217c2b1cfa6ded657d24c 100644 (file)
@@ -3181,24 +3181,14 @@ if conf.get('ENABLE_HOSTNAMED') == 1
 endif
 
 if conf.get('ENABLE_LOCALED') == 1
-        if conf.get('HAVE_XKBCOMMON') == 1
-                # logind will load libxkbcommon.so dynamically on its own, but we still
-                # need to specify where the headers are
-                deps = [libdl,
-                        libxkbcommon.partial_dependency(compile_args: true),
-                        userspace,
-                        versiondep]
-        else
-                deps = [userspace,
-                        versiondep]
-        endif
-
         dbus_programs += executable(
                 'systemd-localed',
                 systemd_localed_sources,
                 include_directories : includes,
                 link_with : [libshared],
-                dependencies : deps,
+                dependencies : libxkbcommon_deps +
+                               [userspace,
+                                versiondep],
                 install_rpath : rootpkglibdir,
                 install : true,
                 install_dir : rootlibexecdir)
index e6e239d9bd3ea2f24f13a51ae68caab7c33436c6..587e072c6bcffccb40af72e20dc61ee1487b5a2f 100644 (file)
@@ -5,11 +5,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#if HAVE_XKBCOMMON
-#include <xkbcommon/xkbcommon.h>
-#include <dlfcn.h>
-#endif
-
 #include "sd-bus.h"
 
 #include "alloc-util.h"
@@ -19,7 +14,6 @@
 #include "bus-message.h"
 #include "bus-polkit.h"
 #include "constants.h"
-#include "dlfcn-util.h"
 #include "kbd-util.h"
 #include "localed-util.h"
 #include "macro.h"
@@ -32,6 +26,7 @@
 #include "string-util.h"
 #include "strv.h"
 #include "user-util.h"
+#include "xkbcommon-util.h"
 
 static int reload_system_manager(sd_bus *bus) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@@ -482,107 +477,6 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro
         return sd_bus_reply_method_return(m, NULL);
 }
 
-#if HAVE_XKBCOMMON
-
-_printf_(3, 0)
-static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
-        const char *fmt;
-
-        fmt = strjoina("libxkbcommon: ", format);
-        DISABLE_WARNING_FORMAT_NONLITERAL;
-        log_internalv(LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, fmt, args);
-        REENABLE_WARNING;
-}
-
-#define LOAD_SYMBOL(symbol, dl, name)                                   \
-        ({                                                              \
-                (symbol) = (typeof(symbol)) dlvsym((dl), (name), "V_0.5.0"); \
-                (symbol) ? 0 : -EOPNOTSUPP;                             \
-        })
-
-static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
-
-        /* We dlopen() the library in order to make the dependency soft. The library (and what it pulls in) is huge
-         * after all, hence let's support XKB maps when the library is around, and refuse otherwise. The function
-         * pointers to the shared library are below: */
-
-        struct xkb_context* (*symbol_xkb_context_new)(enum xkb_context_flags flags) = NULL;
-        void (*symbol_xkb_context_unref)(struct xkb_context *context) = NULL;
-        void (*symbol_xkb_context_set_log_fn)(struct xkb_context *context, void (*log_fn)(struct xkb_context *context, enum xkb_log_level level, const char *format, va_list args)) = NULL;
-        struct xkb_keymap* (*symbol_xkb_keymap_new_from_names)(struct xkb_context *context, const struct xkb_rule_names *names, enum xkb_keymap_compile_flags flags) = NULL;
-        void (*symbol_xkb_keymap_unref)(struct xkb_keymap *keymap) = NULL;
-
-        const struct xkb_rule_names rmlvo = {
-                .model          = model,
-                .layout         = layout,
-                .variant        = variant,
-                .options        = options,
-        };
-        struct xkb_context *ctx = NULL;
-        struct xkb_keymap *km = NULL;
-        _cleanup_(dlclosep) void *dl = NULL;
-        int r;
-
-        /* Compile keymap from RMLVO information to check out its validity */
-
-        dl = dlopen("libxkbcommon.so.0", RTLD_LAZY);
-        if (!dl)
-                return -EOPNOTSUPP;
-
-        r = LOAD_SYMBOL(symbol_xkb_context_new, dl, "xkb_context_new");
-        if (r < 0)
-                goto finish;
-
-        r = LOAD_SYMBOL(symbol_xkb_context_unref, dl, "xkb_context_unref");
-        if (r < 0)
-                goto finish;
-
-        r = LOAD_SYMBOL(symbol_xkb_context_set_log_fn, dl, "xkb_context_set_log_fn");
-        if (r < 0)
-                goto finish;
-
-        r = LOAD_SYMBOL(symbol_xkb_keymap_new_from_names, dl, "xkb_keymap_new_from_names");
-        if (r < 0)
-                goto finish;
-
-        r = LOAD_SYMBOL(symbol_xkb_keymap_unref, dl, "xkb_keymap_unref");
-        if (r < 0)
-                goto finish;
-
-        ctx = symbol_xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
-        if (!ctx) {
-                r = -ENOMEM;
-                goto finish;
-        }
-
-        symbol_xkb_context_set_log_fn(ctx, log_xkb);
-
-        km = symbol_xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS);
-        if (!km) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        r = 0;
-
-finish:
-        if (symbol_xkb_keymap_unref && km)
-                symbol_xkb_keymap_unref(km);
-
-        if (symbol_xkb_context_unref && ctx)
-                symbol_xkb_context_unref(ctx);
-
-        return r;
-}
-
-#else
-
-static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
-        return 0;
-}
-
-#endif
-
 static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) {
         _cleanup_(vc_context_clear) VCContext converted = {};
         Context *c = ASSERT_PTR(userdata);
index 60d2666ffd6921efb42012d27c9865dbe53d7848..98a0b44d6314caa442264154ff0c949c0d497a4f 100644 (file)
@@ -3,6 +3,7 @@
 systemd_localed_sources = files(
         'localed-util.c',
         'localed.c',
+        'xkbcommon-util.c',
 )
 
 localectl_sources = files('localectl.c')
@@ -28,11 +29,21 @@ if conf.get('ENABLE_LOCALED') == 1
                      install_dir : pkgdatadir)
 endif
 
+# logind will load libxkbcommon.so dynamically on its own, but we still need to
+# specify where the headers are.
+if conf.get('HAVE_XKBCOMMON') == 1
+        libxkbcommon_deps = [libdl,
+                             libxkbcommon.partial_dependency(compile_args: true)]
+else
+        libxkbcommon_deps = []
+endif
+
 tests += [
         {
                 'sources' : files(
                         'test-localed-util.c',
                         'localed-util.c',
+                        'xkbcommon-util.c',
                 ),
         },
 ]
diff --git a/src/locale/xkbcommon-util.c b/src/locale/xkbcommon-util.c
new file mode 100644 (file)
index 0000000..295ac8a
--- /dev/null
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "dlfcn-util.h"
+#include "log.h"
+#include "macro.h"
+#include "string-util.h"
+#include "xkbcommon-util.h"
+
+#if HAVE_XKBCOMMON
+static void *xkbcommon_dl = NULL;
+
+struct xkb_context* (*sym_xkb_context_new)(enum xkb_context_flags flags);
+void (*sym_xkb_context_unref)(struct xkb_context *context);
+void (*sym_xkb_context_set_log_fn)(
+                struct xkb_context *context,
+                void (*log_fn)(
+                        struct xkb_context *context,
+                        enum xkb_log_level level,
+                        const char *format,
+                        va_list args));
+struct xkb_keymap* (*sym_xkb_keymap_new_from_names)(
+                struct xkb_context *context,
+                const struct xkb_rule_names *names,
+                enum xkb_keymap_compile_flags flags);
+void (*sym_xkb_keymap_unref)(struct xkb_keymap *keymap);
+
+static int dlopen_xkbcommon(void) {
+        return dlopen_many_sym_or_warn(
+                        &xkbcommon_dl, "libxkbcommon.so.0", LOG_DEBUG,
+                        DLSYM_ARG(xkb_context_new),
+                        DLSYM_ARG(xkb_context_unref),
+                        DLSYM_ARG(xkb_context_set_log_fn),
+                        DLSYM_ARG(xkb_keymap_new_from_names),
+                        DLSYM_ARG(xkb_keymap_unref));
+}
+
+_printf_(3, 0)
+static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
+        const char *fmt;
+
+        fmt = strjoina("libxkbcommon: ", format);
+        DISABLE_WARNING_FORMAT_NONLITERAL;
+        log_internalv(LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, fmt, args);
+        REENABLE_WARNING;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct xkb_context *, sym_xkb_context_unref, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct xkb_keymap *, sym_xkb_keymap_unref, NULL);
+
+int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
+        _cleanup_(sym_xkb_context_unrefp) struct xkb_context *ctx = NULL;
+        _cleanup_(sym_xkb_keymap_unrefp) struct xkb_keymap *km = NULL;
+        const struct xkb_rule_names rmlvo = {
+                .model          = model,
+                .layout         = layout,
+                .variant        = variant,
+                .options        = options,
+        };
+        int r;
+
+        /* Compile keymap from RMLVO information to check out its validity */
+
+        r = dlopen_xkbcommon();
+        if (r < 0)
+                return r;
+
+        ctx = sym_xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
+        if (!ctx)
+                return -ENOMEM;
+
+        sym_xkb_context_set_log_fn(ctx, log_xkb);
+
+        km = sym_xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS);
+        if (!km)
+                return -EINVAL;
+
+        return 0;
+}
+
+#endif
diff --git a/src/locale/xkbcommon-util.h b/src/locale/xkbcommon-util.h
new file mode 100644 (file)
index 0000000..e99c2d7
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#if HAVE_XKBCOMMON
+#include <xkbcommon/xkbcommon.h>
+
+extern struct xkb_context* (*sym_xkb_context_new)(enum xkb_context_flags flags);
+extern void (*sym_xkb_context_unref)(struct xkb_context *context);
+extern void (*sym_xkb_context_set_log_fn)(
+                struct xkb_context *context,
+                void (*log_fn)(
+                        struct xkb_context *context,
+                        enum xkb_log_level level,
+                        const char *format,
+                        va_list args));
+extern struct xkb_keymap* (*sym_xkb_keymap_new_from_names)(
+                struct xkb_context *context,
+                const struct xkb_rule_names *names,
+                enum xkb_keymap_compile_flags flags);
+extern void (*sym_xkb_keymap_unref)(struct xkb_keymap *keymap);
+
+int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options);
+
+#else
+
+static inline int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
+        return 0;
+}
+
+#endif