diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-06-14 09:07:00 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-06-14 20:56:23 +0900 |
commit | 3d36b5d7e7b191fca7c5c65dbab94d99cf5f0230 (patch) | |
tree | 6f68c94200e0e9f58abe486fdd0dcf2e8dd58d32 /src/locale | |
parent | d2e96a4f87f814f3d5c8be986a4d4f616bfd67f4 (diff) | |
download | systemd-3d36b5d7e7b191fca7c5c65dbab94d99cf5f0230.tar.gz |
locale-setup: merge locale handling in PID1 and localed
Diffstat (limited to 'src/locale')
-rw-r--r-- | src/locale/keymap-util.c | 102 | ||||
-rw-r--r-- | src/locale/keymap-util.h | 7 | ||||
-rw-r--r-- | src/locale/localectl.c | 47 | ||||
-rw-r--r-- | src/locale/localed.c | 87 |
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, }; |