mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
locale: split out xkbcommon related functions to xkbcommon-util.c
Then, use dlopen_many_sym_or_warn() with DLSYM_ARG() macro.
This commit is contained in:
parent
384f22e39f
commit
d45cbc0711
16
meson.build
16
meson.build
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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',
|
||||
),
|
||||
},
|
||||
]
|
||||
|
80
src/locale/xkbcommon-util.c
Normal file
80
src/locale/xkbcommon-util.c
Normal file
@ -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
|
30
src/locale/xkbcommon-util.h
Normal file
30
src/locale/xkbcommon-util.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user