]>
Commit | Line | Data |
---|---|---|
c24eb49e LP |
1 | /*** |
2 | This file is part of systemd. | |
3 | ||
4 | Copyright 2010 Lennart Poettering | |
b8c83cfc | 5 | Copyright 2016 Zbigniew Jędrzejewski-Szmek |
c24eb49e LP |
6 | |
7 | systemd is free software; you can redistribute it and/or modify it | |
5430f7f2 LP |
8 | under the terms of the GNU Lesser General Public License as published by |
9 | the Free Software Foundation; either version 2.1 of the License, or | |
c24eb49e LP |
10 | (at your option) any later version. |
11 | ||
12 | systemd is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
5430f7f2 | 15 | Lesser General Public License for more details. |
c24eb49e | 16 | |
5430f7f2 | 17 | You should have received a copy of the GNU Lesser General Public License |
c24eb49e LP |
18 | along with systemd; If not, see <http://www.gnu.org/licenses/>. |
19 | ***/ | |
20 | ||
c24eb49e LP |
21 | #include <string.h> |
22 | ||
4d1a6904 | 23 | #include "env-util.h" |
07630cea LP |
24 | #include "string-util.h" |
25 | #include "strv.h" | |
26 | #include "util.h" | |
c24eb49e | 27 | |
940bd473 TA |
28 | static void test_strv_env_delete(void) { |
29 | _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; | |
30 | ||
31 | a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL); | |
9b5d6bd9 LP |
32 | assert_se(a); |
33 | ||
940bd473 | 34 | b = strv_new("PIEP", "FOO", NULL); |
9b5d6bd9 LP |
35 | assert_se(b); |
36 | ||
940bd473 | 37 | c = strv_new("SCHLUMPF", NULL); |
9b5d6bd9 | 38 | assert_se(c); |
940bd473 TA |
39 | |
40 | d = strv_env_delete(a, 2, b, c); | |
9b5d6bd9 | 41 | assert_se(d); |
940bd473 | 42 | |
9b5d6bd9 LP |
43 | assert_se(streq(d[0], "WALDO=WALDO")); |
44 | assert_se(streq(d[1], "WALDO=")); | |
45 | assert_se(strv_length(d) == 2); | |
940bd473 TA |
46 | } |
47 | ||
6162512c RS |
48 | static void test_strv_env_get(void) { |
49 | char **l; | |
50 | ||
51 | l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4"); | |
52 | ||
53 | assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2")); | |
54 | assert_se(streq(strv_env_get(l, "THREE"), "3")); | |
55 | assert_se(streq(strv_env_get(l, "FOUR"), "4")); | |
56 | } | |
57 | ||
940bd473 TA |
58 | static void test_strv_env_unset(void) { |
59 | _cleanup_strv_free_ char **l = NULL; | |
60 | ||
61 | l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL); | |
9b5d6bd9 | 62 | assert_se(l); |
940bd473 | 63 | |
9b5d6bd9 | 64 | assert_se(strv_env_unset(l, "SCHLUMPF") == l); |
940bd473 | 65 | |
9b5d6bd9 LP |
66 | assert_se(streq(l[0], "PIEP")); |
67 | assert_se(streq(l[1], "NANANANA=YES")); | |
68 | assert_se(strv_length(l) == 2); | |
940bd473 TA |
69 | } |
70 | ||
71 | static void test_strv_env_set(void) { | |
72 | _cleanup_strv_free_ char **l = NULL, **r = NULL; | |
73 | ||
74 | l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL); | |
9b5d6bd9 | 75 | assert_se(l); |
940bd473 TA |
76 | |
77 | r = strv_env_set(l, "WALDO=WALDO"); | |
9b5d6bd9 | 78 | assert_se(r); |
940bd473 | 79 | |
9b5d6bd9 LP |
80 | assert_se(streq(r[0], "PIEP")); |
81 | assert_se(streq(r[1], "SCHLUMPF=SMURFF")); | |
82 | assert_se(streq(r[2], "NANANANA=YES")); | |
83 | assert_se(streq(r[3], "WALDO=WALDO")); | |
84 | assert_se(strv_length(r) == 4); | |
940bd473 TA |
85 | } |
86 | ||
1f28b2de TA |
87 | static void test_strv_env_merge(void) { |
88 | _cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL; | |
89 | ||
90 | a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL); | |
9b5d6bd9 LP |
91 | assert_se(a); |
92 | ||
1f28b2de | 93 | b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL); |
9b5d6bd9 | 94 | assert_se(b); |
c24eb49e | 95 | |
1f28b2de | 96 | r = strv_env_merge(2, a, b); |
9b5d6bd9 LP |
97 | assert_se(r); |
98 | assert_se(streq(r[0], "FOO=")); | |
99 | assert_se(streq(r[1], "WALDO=")); | |
100 | assert_se(streq(r[2], "PIEP")); | |
101 | assert_se(streq(r[3], "SCHLUMPF=SMURFF")); | |
102 | assert_se(streq(r[4], "PIEP=")); | |
103 | assert_se(streq(r[5], "NANANANA=YES")); | |
104 | assert_se(strv_length(r) == 6); | |
105 | ||
106 | assert_se(strv_env_clean(r) == r); | |
107 | assert_se(streq(r[0], "FOO=")); | |
108 | assert_se(streq(r[1], "WALDO=")); | |
109 | assert_se(streq(r[2], "SCHLUMPF=SMURFF")); | |
110 | assert_se(streq(r[3], "PIEP=")); | |
111 | assert_se(streq(r[4], "NANANANA=YES")); | |
112 | assert_se(strv_length(r) == 5); | |
1f28b2de TA |
113 | } |
114 | ||
37f3ffca RS |
115 | static void test_env_strv_get_n(void) { |
116 | const char *_env[] = { | |
117 | "FOO=NO NO NO", | |
118 | "FOO=BAR BAR", | |
119 | "BAR=waldo", | |
120 | "PATH=unset", | |
121 | NULL | |
122 | }; | |
123 | char **env = (char**) _env; | |
124 | ||
125 | assert_se(streq(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR")); | |
126 | assert_se(streq(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR")); | |
127 | assert_se(streq(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR")); | |
128 | assert_se(streq(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR")); | |
129 | ||
130 | assert_se(streq(strv_env_get_n(env, "PATH__", 4, 0), "unset")); | |
131 | assert_se(streq(strv_env_get_n(env, "PATH", 4, 0), "unset")); | |
132 | assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset")); | |
133 | assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset")); | |
134 | ||
135 | env[3] = NULL; /* kill our $PATH */ | |
136 | ||
137 | assert_se(!strv_env_get_n(env, "PATH__", 4, 0)); | |
138 | assert_se(!strv_env_get_n(env, "PATH", 4, 0)); | |
139 | assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), | |
140 | getenv("PATH"))); | |
141 | assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), | |
142 | getenv("PATH"))); | |
143 | } | |
144 | ||
ccad1fd0 ZJS |
145 | static void test_replace_env(bool braceless) { |
146 | const char *env[] = { | |
147 | "FOO=BAR BAR", | |
148 | "BAR=waldo", | |
149 | NULL | |
150 | }; | |
151 | _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL; | |
152 | unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless; | |
153 | ||
154 | t = replace_env("FOO=$FOO=${FOO}", (char**) env, flags); | |
155 | assert_se(streq(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR")); | |
156 | ||
157 | s = replace_env("BAR=$BAR=${BAR}", (char**) env, flags); | |
158 | assert_se(streq(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo")); | |
159 | ||
160 | q = replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags); | |
161 | assert_se(streq(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR=")); | |
162 | ||
163 | q = replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags); | |
164 | assert_se(streq(q, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo")); | |
165 | ||
166 | p = replace_env("${BAR}$BAR$BAR", (char**) env, flags); | |
167 | assert_se(streq(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR")); | |
168 | } | |
169 | ||
170 | static void test_replace_env_argv(void) { | |
c24eb49e LP |
171 | const char *env[] = { |
172 | "FOO=BAR BAR", | |
173 | "BAR=waldo", | |
174 | NULL | |
175 | }; | |
c24eb49e LP |
176 | const char *line[] = { |
177 | "FOO$FOO", | |
178 | "FOO$FOOFOO", | |
179 | "FOO${FOO}$FOO", | |
180 | "FOO${FOO}", | |
181 | "${FOO}", | |
182 | "$FOO", | |
183 | "$FOO$FOO", | |
184 | "${FOO}${BAR}", | |
185 | "${FOO", | |
df553b58 MS |
186 | "FOO$$${FOO}", |
187 | "$$FOO${FOO}", | |
b82f58bf RS |
188 | "${FOO:-${BAR}}", |
189 | "${QUUX:-${FOO}}", | |
190 | "${FOO:+${BAR}}", | |
191 | "${QUUX:+${BAR}}", | |
192 | "${FOO:+|${BAR}|}}", | |
193 | "${FOO:+|${BAR}{|}", | |
c24eb49e LP |
194 | NULL |
195 | }; | |
1f28b2de | 196 | _cleanup_strv_free_ char **r = NULL; |
c24eb49e LP |
197 | |
198 | r = replace_env_argv((char**) line, (char**) env); | |
9b5d6bd9 LP |
199 | assert_se(r); |
200 | assert_se(streq(r[0], "FOO$FOO")); | |
201 | assert_se(streq(r[1], "FOO$FOOFOO")); | |
202 | assert_se(streq(r[2], "FOOBAR BAR$FOO")); | |
203 | assert_se(streq(r[3], "FOOBAR BAR")); | |
204 | assert_se(streq(r[4], "BAR BAR")); | |
205 | assert_se(streq(r[5], "BAR")); | |
206 | assert_se(streq(r[6], "BAR")); | |
207 | assert_se(streq(r[7], "BAR BARwaldo")); | |
208 | assert_se(streq(r[8], "${FOO")); | |
df553b58 MS |
209 | assert_se(streq(r[9], "FOO$BAR BAR")); |
210 | assert_se(streq(r[10], "$FOOBAR BAR")); | |
b82f58bf RS |
211 | assert_se(streq(r[11], "${FOO:-waldo}")); |
212 | assert_se(streq(r[12], "${QUUX:-BAR BAR}")); | |
213 | assert_se(streq(r[13], "${FOO:+waldo}")); | |
214 | assert_se(streq(r[14], "${QUUX:+waldo}")); | |
215 | assert_se(streq(r[15], "${FOO:+|waldo|}}")); | |
216 | assert_se(streq(r[16], "${FOO:+|waldo{|}")); | |
217 | assert_se(strv_length(r) == 17); | |
1f28b2de | 218 | } |
a6ff950e | 219 | |
4d1a6904 | 220 | static void test_env_clean(void) { |
4d1a6904 LP |
221 | _cleanup_strv_free_ char **e; |
222 | ||
223 | e = strv_new("FOOBAR=WALDO", | |
224 | "FOOBAR=WALDO", | |
225 | "FOOBAR", | |
226 | "F", | |
227 | "X=", | |
228 | "F=F", | |
229 | "=", | |
230 | "=F", | |
231 | "", | |
232 | "0000=000", | |
233 | "äöüß=abcd", | |
234 | "abcd=äöüß", | |
235 | "xyz\n=xyz", | |
236 | "xyz=xyz\n", | |
237 | "another=one", | |
238 | "another=final one", | |
239 | NULL); | |
9b5d6bd9 LP |
240 | assert_se(e); |
241 | assert_se(!strv_env_is_valid(e)); | |
242 | assert_se(strv_env_clean(e) == e); | |
243 | assert_se(strv_env_is_valid(e)); | |
4d1a6904 LP |
244 | |
245 | assert_se(streq(e[0], "FOOBAR=WALDO")); | |
246 | assert_se(streq(e[1], "X=")); | |
247 | assert_se(streq(e[2], "F=F")); | |
248 | assert_se(streq(e[3], "abcd=äöüß")); | |
249 | assert_se(streq(e[4], "another=final one")); | |
250 | assert_se(e[5] == NULL); | |
251 | } | |
252 | ||
8354c34e TA |
253 | static void test_env_name_is_valid(void) { |
254 | assert_se(env_name_is_valid("test")); | |
255 | ||
256 | assert_se(!env_name_is_valid(NULL)); | |
257 | assert_se(!env_name_is_valid("")); | |
b8c83cfc ZJS |
258 | assert_se(!env_name_is_valid("xxx\a")); |
259 | assert_se(!env_name_is_valid("xxx\007b")); | |
260 | assert_se(!env_name_is_valid("\007\009")); | |
8354c34e TA |
261 | assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong")); |
262 | assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed")); | |
263 | } | |
264 | ||
b8c83cfc ZJS |
265 | static void test_env_value_is_valid(void) { |
266 | assert_se(env_value_is_valid("")); | |
267 | assert_se(env_value_is_valid("głąb kapuściany")); | |
268 | assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\"")); | |
269 | } | |
270 | ||
271 | static void test_env_assignment_is_valid(void) { | |
272 | assert_se(env_assignment_is_valid("a=")); | |
273 | assert_se(env_assignment_is_valid("b=głąb kapuściany")); | |
274 | assert_se(env_assignment_is_valid("c=\\007\\009\\011")); | |
275 | assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\"")); | |
276 | ||
277 | assert_se(!env_assignment_is_valid("=")); | |
278 | assert_se(!env_assignment_is_valid("a b=")); | |
279 | assert_se(!env_assignment_is_valid("a =")); | |
280 | assert_se(!env_assignment_is_valid(" b=")); | |
281 | /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */ | |
282 | assert_se(!env_assignment_is_valid("a.b=")); | |
283 | assert_se(!env_assignment_is_valid("a-b=")); | |
284 | assert_se(!env_assignment_is_valid("\007=głąb kapuściany")); | |
285 | assert_se(!env_assignment_is_valid("c\009=\007\009\011")); | |
286 | assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\"")); | |
287 | } | |
288 | ||
1f28b2de | 289 | int main(int argc, char *argv[]) { |
940bd473 | 290 | test_strv_env_delete(); |
6162512c | 291 | test_strv_env_get(); |
940bd473 TA |
292 | test_strv_env_unset(); |
293 | test_strv_env_set(); | |
1f28b2de | 294 | test_strv_env_merge(); |
37f3ffca | 295 | test_env_strv_get_n(); |
ccad1fd0 ZJS |
296 | test_replace_env(false); |
297 | test_replace_env(true); | |
298 | test_replace_env_argv(); | |
4d1a6904 | 299 | test_env_clean(); |
8354c34e | 300 | test_env_name_is_valid(); |
b8c83cfc ZJS |
301 | test_env_value_is_valid(); |
302 | test_env_assignment_is_valid(); | |
a6ff950e | 303 | |
5f7c426e | 304 | return 0; |
c24eb49e | 305 | } |