Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <stdlib.h>
5 : : #include <string.h>
6 : :
7 : : #include "env-file.h"
8 : : #include "env-util.h"
9 : : #include "locale-setup.h"
10 : : #include "locale-util.h"
11 : : #include "proc-cmdline.h"
12 : : #include "string-util.h"
13 : : #include "strv.h"
14 : : #include "util.h"
15 : : #include "virt.h"
16 : :
17 : 0 : int locale_setup(char ***environment) {
18 : 0 : _cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
19 : 0 : _cleanup_strv_free_ char **add = NULL;
20 : : LocaleVariable i;
21 : : int r;
22 : :
23 : 0 : r = proc_cmdline_get_key_many(PROC_CMDLINE_STRIP_RD_PREFIX,
24 : : "locale.LANG", &variables[VARIABLE_LANG],
25 : : "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
26 : : "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
27 : : "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
28 : : "locale.LC_TIME", &variables[VARIABLE_LC_TIME],
29 : : "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
30 : : "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
31 : : "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
32 : : "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
33 : : "locale.LC_NAME", &variables[VARIABLE_LC_NAME],
34 : : "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
35 : : "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
36 : : "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
37 : : "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]);
38 [ # # # # ]: 0 : if (r < 0 && r != -ENOENT)
39 [ # # ]: 0 : log_warning_errno(r, "Failed to read /proc/cmdline: %m");
40 : :
41 : : /* Hmm, nothing set on the kernel cmd line? Then let's try /etc/locale.conf */
42 [ # # ]: 0 : if (r <= 0) {
43 : 0 : r = parse_env_file(NULL, "/etc/locale.conf",
44 : : "LANG", &variables[VARIABLE_LANG],
45 : : "LANGUAGE", &variables[VARIABLE_LANGUAGE],
46 : : "LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
47 : : "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
48 : : "LC_TIME", &variables[VARIABLE_LC_TIME],
49 : : "LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
50 : : "LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
51 : : "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
52 : : "LC_PAPER", &variables[VARIABLE_LC_PAPER],
53 : : "LC_NAME", &variables[VARIABLE_LC_NAME],
54 : : "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
55 : : "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
56 : : "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
57 : : "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]);
58 [ # # # # ]: 0 : if (r < 0 && r != -ENOENT)
59 [ # # ]: 0 : log_warning_errno(r, "Failed to read /etc/locale.conf: %m");
60 : : }
61 : :
62 [ # # ]: 0 : for (i = 0; i < _VARIABLE_LC_MAX; i++) {
63 : : char *s;
64 : :
65 [ # # ]: 0 : if (!variables[i])
66 : 0 : continue;
67 : :
68 : 0 : s = strjoin(locale_variable_to_string(i), "=", variables[i]);
69 [ # # ]: 0 : if (!s)
70 : 0 : return -ENOMEM;
71 : :
72 [ # # ]: 0 : if (strv_consume(&add, s) < 0)
73 : 0 : return -ENOMEM;
74 : : }
75 : :
76 [ # # ]: 0 : if (strv_isempty(add)) {
77 : : /* If no locale is configured then default to compile-time default. */
78 : :
79 : 0 : add = strv_new("LANG=" SYSTEMD_DEFAULT_LOCALE);
80 [ # # ]: 0 : if (!add)
81 : 0 : return -ENOMEM;
82 : : }
83 : :
84 [ # # ]: 0 : if (strv_isempty(*environment))
85 : 0 : strv_free_and_replace(*environment, add);
86 : : else {
87 : : char **merged;
88 : :
89 : 0 : merged = strv_env_merge(2, *environment, add);
90 [ # # ]: 0 : if (!merged)
91 : 0 : return -ENOMEM;
92 : :
93 : 0 : strv_free_and_replace(*environment, merged);
94 : : }
95 : :
96 : 0 : return 0;
97 : : }
|