summaryrefslogtreecommitdiff
path: root/src/locale
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-06-14 09:07:00 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-06-14 20:56:23 +0900
commit3d36b5d7e7b191fca7c5c65dbab94d99cf5f0230 (patch)
tree6f68c94200e0e9f58abe486fdd0dcf2e8dd58d32 /src/locale
parentd2e96a4f87f814f3d5c8be986a4d4f616bfd67f4 (diff)
downloadsystemd-3d36b5d7e7b191fca7c5c65dbab94d99cf5f0230.tar.gz
locale-setup: merge locale handling in PID1 and localed
Diffstat (limited to 'src/locale')
-rw-r--r--src/locale/keymap-util.c102
-rw-r--r--src/locale/keymap-util.h7
-rw-r--r--src/locale/localectl.c47
-rw-r--r--src/locale/localed.c87
4 files changed, 35 insertions, 208 deletions
diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
index 9759f46163..0717697e5b 100644
--- a/src/locale/keymap-util.c
+++ b/src/locale/keymap-util.c
@@ -65,13 +65,8 @@ static void context_free_vconsole(Context *c) {
c->vc_keymap_toggle = mfree(c->vc_keymap_toggle);
}
-static void context_free_locale(Context *c) {
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
- c->locale[p] = mfree(c->locale[p]);
-}
-
void context_clear(Context *c) {
- context_free_locale(c);
+ locale_context_clear(&c->locale_context);
context_free_x11(c);
context_free_vconsole(c);
@@ -82,15 +77,8 @@ void context_clear(Context *c) {
bus_verify_polkit_async_registry_free(c->polkit_registry);
};
-void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
- for (LocaleVariable p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
- if (isempty(locale[p]) || streq_ptr(locale[VARIABLE_LANG], locale[p]))
- locale[p] = mfree(locale[p]);
-}
-
int locale_read_data(Context *c, sd_bus_message *m) {
- struct stat st;
- int r;
+ assert(c);
/* Do not try to re-read the file within single bus operation. */
if (m) {
@@ -101,57 +89,7 @@ int locale_read_data(Context *c, sd_bus_message *m) {
c->locale_cache = sd_bus_message_ref(m);
}
- r = stat("/etc/locale.conf", &st);
- if (r < 0 && errno != ENOENT)
- return -errno;
-
- if (r >= 0) {
- usec_t t;
-
- /* If mtime is not changed, then we do not need to re-read the file. */
- t = timespec_load(&st.st_mtim);
- if (c->locale_mtime != USEC_INFINITY && t == c->locale_mtime)
- return 0;
-
- c->locale_mtime = t;
- context_free_locale(c);
-
- r = parse_env_file(NULL, "/etc/locale.conf",
- "LANG", &c->locale[VARIABLE_LANG],
- "LANGUAGE", &c->locale[VARIABLE_LANGUAGE],
- "LC_CTYPE", &c->locale[VARIABLE_LC_CTYPE],
- "LC_NUMERIC", &c->locale[VARIABLE_LC_NUMERIC],
- "LC_TIME", &c->locale[VARIABLE_LC_TIME],
- "LC_COLLATE", &c->locale[VARIABLE_LC_COLLATE],
- "LC_MONETARY", &c->locale[VARIABLE_LC_MONETARY],
- "LC_MESSAGES", &c->locale[VARIABLE_LC_MESSAGES],
- "LC_PAPER", &c->locale[VARIABLE_LC_PAPER],
- "LC_NAME", &c->locale[VARIABLE_LC_NAME],
- "LC_ADDRESS", &c->locale[VARIABLE_LC_ADDRESS],
- "LC_TELEPHONE", &c->locale[VARIABLE_LC_TELEPHONE],
- "LC_MEASUREMENT", &c->locale[VARIABLE_LC_MEASUREMENT],
- "LC_IDENTIFICATION", &c->locale[VARIABLE_LC_IDENTIFICATION]);
- if (r < 0)
- return r;
- } else {
- c->locale_mtime = USEC_INFINITY;
- context_free_locale(c);
-
- /* Fill in what we got passed from systemd. */
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
- const char *name;
-
- name = locale_variable_to_string(p);
- assert(name);
-
- r = free_and_strdup(&c->locale[p], empty_to_null(getenv(name)));
- if (r < 0)
- return r;
- }
- }
-
- locale_simplify(c->locale);
- return 0;
+ return locale_context_load(&c->locale_context, LOCALE_LOAD_LOCALE_CONF | LOCALE_LOAD_ENVIRONMENT | LOCALE_LOAD_SIMPLIFY);
}
int vconsole_read_data(Context *c, sd_bus_message *m) {
@@ -280,40 +218,6 @@ int x11_read_data(Context *c, sd_bus_message *m) {
return 0;
}
-int locale_write_data(Context *c, char ***settings) {
- _cleanup_strv_free_ char **l = NULL;
- struct stat st;
- int r;
-
- /* Set values will be returned as strv in *settings on success. */
-
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
- if (!isempty(c->locale[p])) {
- r = strv_env_assign(&l, locale_variable_to_string(p), c->locale[p]);
- if (r < 0)
- return r;
- }
-
- 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;
-}
-
int vconsole_write_data(Context *c) {
_cleanup_strv_free_ char **l = NULL;
struct stat st;
diff --git a/src/locale/keymap-util.h b/src/locale/keymap-util.h
index c087dbcbbe..5470d1bb9b 100644
--- a/src/locale/keymap-util.h
+++ b/src/locale/keymap-util.h
@@ -4,13 +4,12 @@
#include "sd-bus.h"
#include "hashmap.h"
-#include "locale-util.h"
+#include "locale-setup.h"
#include "time-util.h"
typedef struct Context {
sd_bus_message *locale_cache;
- usec_t locale_mtime;
- char *locale[_VARIABLE_LC_MAX];
+ LocaleContext locale_context;
sd_bus_message *x11_cache;
usec_t x11_mtime;
@@ -40,8 +39,6 @@ int vconsole_convert_to_x11(Context *c);
int vconsole_write_data(Context *c);
int x11_convert_to_vconsole(Context *c);
int x11_write_data(Context *c);
-void locale_simplify(char *locale[_VARIABLE_LC_MAX]);
-int locale_write_data(Context *c, char ***settings);
bool locale_gen_check_available(void);
int locale_gen_enable_locale(const char *locale);
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 661d54c27d..6bfb564f97 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -12,7 +12,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "kbd-util.h"
-#include "locale-util.h"
+#include "locale-setup.h"
#include "main-func.h"
#include "memory-util.h"
#include "pager.h"
@@ -52,44 +52,25 @@ static void status_info_clear(StatusInfo *info) {
}
static void print_overridden_variables(void) {
- _cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
- bool print_warning = true;
+ _cleanup_(locale_context_clear) LocaleContext c = { .mtime = USEC_INFINITY };
+ _cleanup_strv_free_ char **env = NULL;
int r;
if (arg_transport != BUS_TRANSPORT_LOCAL)
return;
- r = proc_cmdline_get_key_many(
- PROC_CMDLINE_STRIP_RD_PREFIX,
- "locale.LANG", &variables[VARIABLE_LANG],
- "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
- "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
- "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
- "locale.LC_TIME", &variables[VARIABLE_LC_TIME],
- "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
- "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
- "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
- "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
- "locale.LC_NAME", &variables[VARIABLE_LC_NAME],
- "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
- "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
- "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
- "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]);
- if (r < 0 && r != -ENOENT) {
- log_warning_errno(r, "Failed to read /proc/cmdline: %m");
- return;
- }
-
- for (LocaleVariable j = 0; j < _VARIABLE_LC_MAX; j++)
- if (variables[j]) {
- if (print_warning) {
- log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
- " Command Line: %s=%s", locale_variable_to_string(j), variables[j]);
+ (void) locale_context_load(&c, LOCALE_LOAD_PROC_CMDLINE);
- print_warning = false;
- } else
- log_warning(" %s=%s", locale_variable_to_string(j), variables[j]);
- }
+ r = locale_context_build_env(&c, &env, NULL);
+ if (r < 0)
+ return (void) log_warning_errno(r, "Failed to build locale settings from kernel command line, ignoring: %m");
+
+ STRV_FOREACH(p, env)
+ if (p == env)
+ log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
+ " Command Line: %s", *p);
+ else
+ log_warning(" %s", *p);
}
static void print_status_info(StatusInfo *i) {
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 89bf9c6fba..9718c5b95f 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -21,7 +21,6 @@
#include "dlfcn-util.h"
#include "kbd-util.h"
#include "keymap-util.h"
-#include "locale-util.h"
#include "macro.h"
#include "main-func.h"
#include "missing_capability.h"
@@ -33,44 +32,13 @@
#include "strv.h"
#include "user-util.h"
-static int locale_update_system_manager(Context *c, sd_bus *bus) {
- _cleanup_free_ char **l_unset = NULL;
- _cleanup_strv_free_ char **l_set = NULL;
+static int locale_update_system_manager(sd_bus *bus, char **l_set, char **l_unset) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- size_t c_set = 0, c_unset = 0;
int r;
assert(bus);
- l_unset = new0(char*, _VARIABLE_LC_MAX);
- if (!l_unset)
- return log_oom();
-
- l_set = new0(char*, _VARIABLE_LC_MAX);
- if (!l_set)
- return log_oom();
-
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
- const char *name;
-
- name = locale_variable_to_string(p);
- assert(name);
-
- if (isempty(c->locale[p]))
- l_unset[c_set++] = (char*) name;
- else {
- char *s;
-
- s = strjoin(name, "=", c->locale[p]);
- if (!s)
- return log_oom();
-
- l_set[c_unset++] = s;
- }
- }
-
- assert(c_set + c_unset == _VARIABLE_LC_MAX);
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -188,21 +156,9 @@ static int property_get_locale(
if (!l)
return -ENOMEM;
- for (LocaleVariable p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
- char *t;
- 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;
-
- l[q++] = t;
- }
+ r = locale_context_build_env(&c->locale_context, &l, NULL);
+ if (r < 0)
+ return r;
return sd_bus_message_append_strv(reply, l);
}
@@ -342,9 +298,8 @@ static int locale_gen_process_locale(char *new_locale[static _VARIABLE_LC_MAX],
static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) {
_cleanup_(locale_variables_freep) char *new_locale[_VARIABLE_LC_MAX] = {};
- _cleanup_strv_free_ char **settings = NULL, **l = NULL;
+ _cleanup_strv_free_ char **l = NULL, **l_set = NULL, **l_unset = NULL;
Context *c = userdata;
- bool modified = false;
int interactive, r;
bool use_localegen;
@@ -402,22 +357,13 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
}
/* Merge with the current settings */
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
- if (!isempty(c->locale[p]) && isempty(new_locale[p])) {
- new_locale[p] = strdup(c->locale[p]);
- if (!new_locale[p])
- return -ENOMEM;
- }
-
- locale_simplify(new_locale);
+ r = locale_context_merge(&c->locale_context, new_locale);
+ if (r < 0)
+ return r;
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
- if (!streq_ptr(c->locale[p], new_locale[p])) {
- modified = true;
- break;
- }
+ locale_variables_simplify(new_locale);
- if (!modified) {
+ if (locale_context_equal(&c->locale_context, new_locale)) {
log_debug("Locale settings were not modified.");
return sd_bus_reply_method_return(m, NULL);
}
@@ -443,22 +389,21 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
return r;
}
- for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
- free_and_replace(c->locale[p], new_locale[p]);
+ locale_context_take(&c->locale_context, new_locale);
/* Write locale configuration */
- r = locale_write_data(c, &settings);
+ r = locale_context_save(&c->locale_context, &l_set, &l_unset);
if (r < 0) {
log_error_errno(r, "Failed to set locale: %m");
return sd_bus_error_set_errnof(error, r, "Failed to set locale: %m");
}
- (void) locale_update_system_manager(c, sd_bus_message_get_bus(m));
+ (void) locale_update_system_manager(sd_bus_message_get_bus(m), l_set, l_unset);
- if (settings) {
+ if (!strv_isempty(l_set)) {
_cleanup_free_ char *line = NULL;
- line = strv_join(settings, ", ");
+ line = strv_join(l_set, ", ");
log_info("Changed locale to %s.", strnull(line));
} else
log_info("Changed locale to unset.");
@@ -827,7 +772,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
static int run(int argc, char *argv[]) {
_cleanup_(context_clear) Context context = {
- .locale_mtime = USEC_INFINITY,
+ .locale_context.mtime = USEC_INFINITY,
.vc_mtime = USEC_INFINITY,
.x11_mtime = USEC_INFINITY,
};