Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <string.h>
4 : :
5 : : #include "env-util.h"
6 : : #include "fd-util.h"
7 : : #include "fileio.h"
8 : : #include "fs-util.h"
9 : : #include "serialize.h"
10 : : #include "string-util.h"
11 : : #include "strv.h"
12 : : #include "util.h"
13 : :
14 : 4 : static void test_strv_env_delete(void) {
15 : 4 : _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
16 : :
17 : 4 : a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
18 [ - + ]: 4 : assert_se(a);
19 : :
20 : 4 : b = strv_new("PIEP", "FOO");
21 [ - + ]: 4 : assert_se(b);
22 : :
23 : 4 : c = strv_new("SCHLUMPF");
24 [ - + ]: 4 : assert_se(c);
25 : :
26 : 4 : d = strv_env_delete(a, 2, b, c);
27 [ - + ]: 4 : assert_se(d);
28 : :
29 [ - + ]: 4 : assert_se(streq(d[0], "WALDO=WALDO"));
30 [ - + ]: 4 : assert_se(streq(d[1], "WALDO="));
31 [ - + ]: 4 : assert_se(strv_length(d) == 2);
32 : 4 : }
33 : :
34 : 4 : static void test_strv_env_get(void) {
35 : : char **l;
36 : :
37 : 4 : l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
38 : :
39 [ - + ]: 4 : assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2"));
40 [ - + ]: 4 : assert_se(streq(strv_env_get(l, "THREE"), "3"));
41 [ - + ]: 4 : assert_se(streq(strv_env_get(l, "FOUR"), "4"));
42 : 4 : }
43 : :
44 : 4 : static void test_strv_env_unset(void) {
45 : 4 : _cleanup_strv_free_ char **l = NULL;
46 : :
47 : 4 : l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
48 [ - + ]: 4 : assert_se(l);
49 : :
50 [ - + ]: 4 : assert_se(strv_env_unset(l, "SCHLUMPF") == l);
51 : :
52 [ - + ]: 4 : assert_se(streq(l[0], "PIEP"));
53 [ - + ]: 4 : assert_se(streq(l[1], "NANANANA=YES"));
54 [ - + ]: 4 : assert_se(strv_length(l) == 2);
55 : 4 : }
56 : :
57 : 4 : static void test_strv_env_set(void) {
58 : 4 : _cleanup_strv_free_ char **l = NULL, **r = NULL;
59 : :
60 : 4 : l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
61 [ - + ]: 4 : assert_se(l);
62 : :
63 : 4 : r = strv_env_set(l, "WALDO=WALDO");
64 [ - + ]: 4 : assert_se(r);
65 : :
66 [ - + ]: 4 : assert_se(streq(r[0], "PIEP"));
67 [ - + ]: 4 : assert_se(streq(r[1], "SCHLUMPF=SMURFF"));
68 [ - + ]: 4 : assert_se(streq(r[2], "NANANANA=YES"));
69 [ - + ]: 4 : assert_se(streq(r[3], "WALDO=WALDO"));
70 [ - + ]: 4 : assert_se(strv_length(r) == 4);
71 : 4 : }
72 : :
73 : 4 : static void test_strv_env_merge(void) {
74 : 4 : _cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL;
75 : :
76 : 4 : a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
77 [ - + ]: 4 : assert_se(a);
78 : :
79 : 4 : b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES");
80 [ - + ]: 4 : assert_se(b);
81 : :
82 : 4 : r = strv_env_merge(2, a, b);
83 [ - + ]: 4 : assert_se(r);
84 [ - + ]: 4 : assert_se(streq(r[0], "FOO="));
85 [ - + ]: 4 : assert_se(streq(r[1], "WALDO="));
86 [ - + ]: 4 : assert_se(streq(r[2], "PIEP"));
87 [ - + ]: 4 : assert_se(streq(r[3], "SCHLUMPF=SMURFF"));
88 [ - + ]: 4 : assert_se(streq(r[4], "PIEP="));
89 [ - + ]: 4 : assert_se(streq(r[5], "NANANANA=YES"));
90 [ - + ]: 4 : assert_se(strv_length(r) == 6);
91 : :
92 [ - + ]: 4 : assert_se(strv_env_clean(r) == r);
93 [ - + ]: 4 : assert_se(streq(r[0], "FOO="));
94 [ - + ]: 4 : assert_se(streq(r[1], "WALDO="));
95 [ - + ]: 4 : assert_se(streq(r[2], "SCHLUMPF=SMURFF"));
96 [ - + ]: 4 : assert_se(streq(r[3], "PIEP="));
97 [ - + ]: 4 : assert_se(streq(r[4], "NANANANA=YES"));
98 [ - + ]: 4 : assert_se(strv_length(r) == 5);
99 : 4 : }
100 : :
101 : 4 : static void test_env_strv_get_n(void) {
102 : 4 : const char *_env[] = {
103 : : "FOO=NO NO NO",
104 : : "FOO=BAR BAR",
105 : : "BAR=waldo",
106 : : "PATH=unset",
107 : : NULL
108 : : };
109 : 4 : char **env = (char**) _env;
110 : :
111 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR"));
112 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
113 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR"));
114 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
115 : :
116 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "PATH__", 4, 0), "unset"));
117 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "PATH", 4, 0), "unset"));
118 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
119 [ - + ]: 4 : assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
120 : :
121 : 4 : env[3] = NULL; /* kill our $PATH */
122 : :
123 [ - + ]: 4 : assert_se(!strv_env_get_n(env, "PATH__", 4, 0));
124 [ - + ]: 4 : assert_se(!strv_env_get_n(env, "PATH", 4, 0));
125 [ - + ]: 4 : assert_se(streq_ptr(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
126 : : getenv("PATH")));
127 [ - + ]: 4 : assert_se(streq_ptr(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
128 : : getenv("PATH")));
129 : 4 : }
130 : :
131 : 8 : static void test_replace_env(bool braceless) {
132 : 8 : const char *env[] = {
133 : : "FOO=BAR BAR",
134 : : "BAR=waldo",
135 : : NULL
136 : : };
137 : 8 : _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL;
138 : 8 : unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless;
139 : :
140 : 8 : t = replace_env("FOO=$FOO=${FOO}", (char**) env, flags);
141 [ + + - + ]: 8 : assert_se(streq(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR"));
142 : :
143 : 8 : s = replace_env("BAR=$BAR=${BAR}", (char**) env, flags);
144 [ + + - + ]: 8 : assert_se(streq(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo"));
145 : :
146 : 8 : q = replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags);
147 [ + + - + ]: 8 : assert_se(streq(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR="));
148 : :
149 : 8 : r = replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags);
150 [ + + - + ]: 8 : assert_se(streq(r, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo"));
151 : :
152 : 8 : p = replace_env("${BAR}$BAR$BAR", (char**) env, flags);
153 [ + + - + ]: 8 : assert_se(streq(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR"));
154 : 8 : }
155 : :
156 : 8 : static void test_replace_env2(bool extended) {
157 : 8 : const char *env[] = {
158 : : "FOO=foo",
159 : : "BAR=bar",
160 : : NULL
161 : : };
162 : 8 : _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL, *x = NULL;
163 : 8 : unsigned flags = REPLACE_ENV_ALLOW_EXTENDED*extended;
164 : :
165 : 8 : t = replace_env("FOO=${FOO:-${BAR}}", (char**) env, flags);
166 [ + + - + ]: 8 : assert_se(streq(t, extended ? "FOO=foo" : "FOO=${FOO:-bar}"));
167 : :
168 : 8 : s = replace_env("BAR=${XXX:-${BAR}}", (char**) env, flags);
169 [ + + - + ]: 8 : assert_se(streq(s, extended ? "BAR=bar" : "BAR=${XXX:-bar}"));
170 : :
171 : 8 : q = replace_env("XXX=${XXX:+${BAR}}", (char**) env, flags);
172 [ + + - + ]: 8 : assert_se(streq(q, extended ? "XXX=" : "XXX=${XXX:+bar}"));
173 : :
174 : 8 : r = replace_env("FOO=${FOO:+${BAR}}", (char**) env, flags);
175 [ + + - + ]: 8 : assert_se(streq(r, extended ? "FOO=bar" : "FOO=${FOO:+bar}"));
176 : :
177 : 8 : p = replace_env("FOO=${FOO:-${BAR}post}", (char**) env, flags);
178 [ + + - + ]: 8 : assert_se(streq(p, extended ? "FOO=foo" : "FOO=${FOO:-barpost}"));
179 : :
180 : 8 : x = replace_env("XXX=${XXX:+${BAR}post}", (char**) env, flags);
181 [ + + - + ]: 8 : assert_se(streq(x, extended ? "XXX=" : "XXX=${XXX:+barpost}"));
182 : 8 : }
183 : :
184 : 4 : static void test_replace_env_argv(void) {
185 : 4 : const char *env[] = {
186 : : "FOO=BAR BAR",
187 : : "BAR=waldo",
188 : : NULL
189 : : };
190 : 4 : const char *line[] = {
191 : : "FOO$FOO",
192 : : "FOO$FOOFOO",
193 : : "FOO${FOO}$FOO",
194 : : "FOO${FOO}",
195 : : "${FOO}",
196 : : "$FOO",
197 : : "$FOO$FOO",
198 : : "${FOO}${BAR}",
199 : : "${FOO",
200 : : "FOO$$${FOO}",
201 : : "$$FOO${FOO}",
202 : : "${FOO:-${BAR}}",
203 : : "${QUUX:-${FOO}}",
204 : : "${FOO:+${BAR}}",
205 : : "${QUUX:+${BAR}}",
206 : : "${FOO:+|${BAR}|}}",
207 : : "${FOO:+|${BAR}{|}",
208 : : NULL
209 : : };
210 : 4 : _cleanup_strv_free_ char **r = NULL;
211 : :
212 : 4 : r = replace_env_argv((char**) line, (char**) env);
213 [ - + ]: 4 : assert_se(r);
214 [ - + ]: 4 : assert_se(streq(r[0], "FOO$FOO"));
215 [ - + ]: 4 : assert_se(streq(r[1], "FOO$FOOFOO"));
216 [ - + ]: 4 : assert_se(streq(r[2], "FOOBAR BAR$FOO"));
217 [ - + ]: 4 : assert_se(streq(r[3], "FOOBAR BAR"));
218 [ - + ]: 4 : assert_se(streq(r[4], "BAR BAR"));
219 [ - + ]: 4 : assert_se(streq(r[5], "BAR"));
220 [ - + ]: 4 : assert_se(streq(r[6], "BAR"));
221 [ - + ]: 4 : assert_se(streq(r[7], "BAR BARwaldo"));
222 [ - + ]: 4 : assert_se(streq(r[8], "${FOO"));
223 [ - + ]: 4 : assert_se(streq(r[9], "FOO$BAR BAR"));
224 [ - + ]: 4 : assert_se(streq(r[10], "$FOOBAR BAR"));
225 [ - + ]: 4 : assert_se(streq(r[11], "${FOO:-waldo}"));
226 [ - + ]: 4 : assert_se(streq(r[12], "${QUUX:-BAR BAR}"));
227 [ - + ]: 4 : assert_se(streq(r[13], "${FOO:+waldo}"));
228 [ - + ]: 4 : assert_se(streq(r[14], "${QUUX:+waldo}"));
229 [ - + ]: 4 : assert_se(streq(r[15], "${FOO:+|waldo|}}"));
230 [ - + ]: 4 : assert_se(streq(r[16], "${FOO:+|waldo{|}"));
231 [ - + ]: 4 : assert_se(strv_length(r) == 17);
232 : 4 : }
233 : :
234 : 4 : static void test_env_clean(void) {
235 : 4 : _cleanup_strv_free_ char **e;
236 : :
237 : 4 : e = strv_new("FOOBAR=WALDO",
238 : : "FOOBAR=WALDO",
239 : : "FOOBAR",
240 : : "F",
241 : : "X=",
242 : : "F=F",
243 : : "=",
244 : : "=F",
245 : : "",
246 : : "0000=000",
247 : : "äöüß=abcd",
248 : : "abcd=äöüß",
249 : : "xyz\n=xyz",
250 : : "xyz=xyz\n",
251 : : "another=one",
252 : : "another=final one");
253 [ - + ]: 4 : assert_se(e);
254 [ - + ]: 4 : assert_se(!strv_env_is_valid(e));
255 [ - + ]: 4 : assert_se(strv_env_clean(e) == e);
256 [ - + ]: 4 : assert_se(strv_env_is_valid(e));
257 : :
258 [ - + ]: 4 : assert_se(streq(e[0], "FOOBAR=WALDO"));
259 [ - + ]: 4 : assert_se(streq(e[1], "X="));
260 [ - + ]: 4 : assert_se(streq(e[2], "F=F"));
261 [ - + ]: 4 : assert_se(streq(e[3], "abcd=äöüß"));
262 [ - + ]: 4 : assert_se(streq(e[4], "xyz=xyz\n"));
263 [ - + ]: 4 : assert_se(streq(e[5], "another=final one"));
264 [ - + ]: 4 : assert_se(e[6] == NULL);
265 : 4 : }
266 : :
267 : 4 : static void test_env_name_is_valid(void) {
268 [ - + ]: 4 : assert_se(env_name_is_valid("test"));
269 : :
270 [ - + ]: 4 : assert_se(!env_name_is_valid(NULL));
271 [ - + ]: 4 : assert_se(!env_name_is_valid(""));
272 [ - + ]: 4 : assert_se(!env_name_is_valid("xxx\a"));
273 [ - + ]: 4 : assert_se(!env_name_is_valid("xxx\007b"));
274 [ - + ]: 4 : assert_se(!env_name_is_valid("\007\009"));
275 [ - + ]: 4 : assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
276 [ - + ]: 4 : assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
277 : 4 : }
278 : :
279 : 4 : static void test_env_value_is_valid(void) {
280 [ - + ]: 4 : assert_se(env_value_is_valid(""));
281 [ - + ]: 4 : assert_se(env_value_is_valid("głąb kapuściany"));
282 [ - + ]: 4 : assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
283 [ - + ]: 4 : assert_se(env_value_is_valid("tab\tcharacter"));
284 [ - + ]: 4 : assert_se(env_value_is_valid("new\nline"));
285 : 4 : }
286 : :
287 : 4 : static void test_env_assignment_is_valid(void) {
288 [ - + ]: 4 : assert_se(env_assignment_is_valid("a="));
289 [ - + ]: 4 : assert_se(env_assignment_is_valid("b=głąb kapuściany"));
290 [ - + ]: 4 : assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
291 [ - + ]: 4 : assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
292 [ - + ]: 4 : assert_se(env_assignment_is_valid("f=tab\tcharacter"));
293 [ - + ]: 4 : assert_se(env_assignment_is_valid("g=new\nline"));
294 : :
295 [ - + ]: 4 : assert_se(!env_assignment_is_valid("="));
296 [ - + ]: 4 : assert_se(!env_assignment_is_valid("a b="));
297 [ - + ]: 4 : assert_se(!env_assignment_is_valid("a ="));
298 [ - + ]: 4 : assert_se(!env_assignment_is_valid(" b="));
299 : : /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
300 [ - + ]: 4 : assert_se(!env_assignment_is_valid("a.b="));
301 [ - + ]: 4 : assert_se(!env_assignment_is_valid("a-b="));
302 [ - + ]: 4 : assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
303 [ - + ]: 4 : assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
304 [ - + ]: 4 : assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
305 : 4 : }
306 : :
307 : 4 : int main(int argc, char *argv[]) {
308 : 4 : test_strv_env_delete();
309 : 4 : test_strv_env_get();
310 : 4 : test_strv_env_unset();
311 : 4 : test_strv_env_set();
312 : 4 : test_strv_env_merge();
313 : 4 : test_env_strv_get_n();
314 : 4 : test_replace_env(false);
315 : 4 : test_replace_env(true);
316 : 4 : test_replace_env2(false);
317 : 4 : test_replace_env2(true);
318 : 4 : test_replace_env_argv();
319 : 4 : test_env_clean();
320 : 4 : test_env_name_is_valid();
321 : 4 : test_env_value_is_valid();
322 : 4 : test_env_assignment_is_valid();
323 : :
324 : 4 : return 0;
325 : : }
|