2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Thomas H.P. Andersen
7 systemd is free software; you can redistribute it and/or modify it
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
10 (at your option) any later version.
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
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
31 #include "exec-util.h"
38 #include "string-util.h"
41 static int here
= 0, here2
= 0, here3
= 0;
42 void *ignore_stdout_args
[] = {&here
, &here2
, &here3
};
44 /* noop handlers, just check that arguments are passed correctly */
45 static int ignore_stdout_func(int fd
, void *arg
) {
52 static int ignore_stdout_func2(int fd
, void *arg
) {
54 assert(arg
== &here2
);
59 static int ignore_stdout_func3(int fd
, void *arg
) {
61 assert(arg
== &here3
);
67 static const gather_stdout_callback_t ignore_stdout
[] = {
73 static void test_execute_directory(bool gather_stdout
) {
74 char template_lo
[] = "/tmp/test-exec-util.lo.XXXXXXX";
75 char template_hi
[] = "/tmp/test-exec-util.hi.XXXXXXX";
76 const char * dirs
[] = {template_hi
, template_lo
, NULL
};
77 const char *name
, *name2
, *name3
,
78 *overridden
, *override
,
80 *masked2
, *mask2
, /* the mask is non-executable */
81 *masked2e
, *mask2e
; /* the mask is executable */
83 log_info("/* %s (%s) */", __func__
, gather_stdout
? "gathering stdout" : "asynchronous");
85 assert_se(mkdtemp(template_lo
));
86 assert_se(mkdtemp(template_hi
));
88 name
= strjoina(template_lo
, "/script");
89 name2
= strjoina(template_hi
, "/script2");
90 name3
= strjoina(template_lo
, "/useless");
91 overridden
= strjoina(template_lo
, "/overridden");
92 override
= strjoina(template_hi
, "/overridden");
93 masked
= strjoina(template_lo
, "/masked");
94 mask
= strjoina(template_hi
, "/masked");
95 masked2
= strjoina(template_lo
, "/masked2");
96 mask2
= strjoina(template_hi
, "/masked2");
97 masked2e
= strjoina(template_lo
, "/masked2e");
98 mask2e
= strjoina(template_hi
, "/masked2e");
100 assert_se(write_string_file(name
,
101 "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works",
102 WRITE_STRING_FILE_CREATE
) == 0);
103 assert_se(write_string_file(name2
,
104 "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2",
105 WRITE_STRING_FILE_CREATE
) == 0);
106 assert_se(write_string_file(overridden
,
107 "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
108 WRITE_STRING_FILE_CREATE
) == 0);
109 assert_se(write_string_file(override
,
110 "#!/bin/sh\necho 'Executing '$0",
111 WRITE_STRING_FILE_CREATE
) == 0);
112 assert_se(write_string_file(masked
,
113 "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
114 WRITE_STRING_FILE_CREATE
) == 0);
115 assert_se(write_string_file(masked2
,
116 "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
117 WRITE_STRING_FILE_CREATE
) == 0);
118 assert_se(write_string_file(masked2e
,
119 "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
120 WRITE_STRING_FILE_CREATE
) == 0);
121 assert_se(symlink("/dev/null", mask
) == 0);
122 assert_se(touch(mask2
) == 0);
123 assert_se(touch(mask2e
) == 0);
124 assert_se(touch(name3
) >= 0);
126 assert_se(chmod(name
, 0755) == 0);
127 assert_se(chmod(name2
, 0755) == 0);
128 assert_se(chmod(overridden
, 0755) == 0);
129 assert_se(chmod(override
, 0755) == 0);
130 assert_se(chmod(masked
, 0755) == 0);
131 assert_se(chmod(masked2
, 0755) == 0);
132 assert_se(chmod(masked2e
, 0755) == 0);
133 assert_se(chmod(mask2e
, 0755) == 0);
136 execute_directories(dirs
, DEFAULT_TIMEOUT_USEC
, ignore_stdout
, ignore_stdout_args
, NULL
);
138 execute_directories(dirs
, DEFAULT_TIMEOUT_USEC
, NULL
, NULL
, NULL
);
140 assert_se(chdir(template_lo
) == 0);
141 assert_se(access("it_works", F_OK
) >= 0);
142 assert_se(access("failed", F_OK
) < 0);
144 assert_se(chdir(template_hi
) == 0);
145 assert_se(access("it_works2", F_OK
) >= 0);
146 assert_se(access("failed", F_OK
) < 0);
148 (void) rm_rf(template_lo
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
149 (void) rm_rf(template_hi
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
152 static void test_execution_order(void) {
153 char template_lo
[] = "/tmp/test-exec-util-lo.XXXXXXX";
154 char template_hi
[] = "/tmp/test-exec-util-hi.XXXXXXX";
155 const char *dirs
[] = {template_hi
, template_lo
, NULL
};
156 const char *name
, *name2
, *name3
, *overridden
, *override
, *masked
, *mask
;
157 const char *output
, *t
;
158 _cleanup_free_
char *contents
= NULL
;
160 assert_se(mkdtemp(template_lo
));
161 assert_se(mkdtemp(template_hi
));
163 output
= strjoina(template_hi
, "/output");
165 log_info("/* %s >>%s */", __func__
, output
);
167 /* write files in "random" order */
168 name2
= strjoina(template_lo
, "/90-bar");
169 name
= strjoina(template_hi
, "/80-foo");
170 name3
= strjoina(template_lo
, "/last");
171 overridden
= strjoina(template_lo
, "/30-override");
172 override
= strjoina(template_hi
, "/30-override");
173 masked
= strjoina(template_lo
, "/10-masked");
174 mask
= strjoina(template_hi
, "/10-masked");
176 t
= strjoina("#!/bin/sh\necho $(basename $0) >>", output
);
177 assert_se(write_string_file(name
, t
, WRITE_STRING_FILE_CREATE
) == 0);
179 t
= strjoina("#!/bin/sh\necho $(basename $0) >>", output
);
180 assert_se(write_string_file(name2
, t
, WRITE_STRING_FILE_CREATE
) == 0);
182 t
= strjoina("#!/bin/sh\necho $(basename $0) >>", output
);
183 assert_se(write_string_file(name3
, t
, WRITE_STRING_FILE_CREATE
) == 0);
185 t
= strjoina("#!/bin/sh\necho OVERRIDDEN >>", output
);
186 assert_se(write_string_file(overridden
, t
, WRITE_STRING_FILE_CREATE
) == 0);
188 t
= strjoina("#!/bin/sh\necho $(basename $0) >>", output
);
189 assert_se(write_string_file(override
, t
, WRITE_STRING_FILE_CREATE
) == 0);
191 t
= strjoina("#!/bin/sh\necho MASKED >>", output
);
192 assert_se(write_string_file(masked
, t
, WRITE_STRING_FILE_CREATE
) == 0);
194 assert_se(symlink("/dev/null", mask
) == 0);
196 assert_se(chmod(name
, 0755) == 0);
197 assert_se(chmod(name2
, 0755) == 0);
198 assert_se(chmod(name3
, 0755) == 0);
199 assert_se(chmod(overridden
, 0755) == 0);
200 assert_se(chmod(override
, 0755) == 0);
201 assert_se(chmod(masked
, 0755) == 0);
203 execute_directories(dirs
, DEFAULT_TIMEOUT_USEC
, ignore_stdout
, ignore_stdout_args
, NULL
);
205 assert_se(read_full_file(output
, &contents
, NULL
) >= 0);
206 assert_se(streq(contents
, "30-override\n80-foo\n90-bar\nlast\n"));
208 (void) rm_rf(template_lo
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
209 (void) rm_rf(template_hi
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
212 static int gather_stdout_one(int fd
, void *arg
) {
217 assert_se(read(fd
, buf
, sizeof buf
) >= 0);
220 assert_se(t
= strndup(buf
, sizeof buf
));
221 assert_se(strv_push(s
, t
) >= 0);
225 static int gather_stdout_two(int fd
, void *arg
) {
226 char ***s
= arg
, **t
;
229 assert_se(write(fd
, *t
, strlen(*t
)) == (ssize_t
) strlen(*t
));
234 static int gather_stdout_three(int fd
, void *arg
) {
238 assert_se(read(fd
, buf
, sizeof buf
- 1) > 0);
240 assert_se(*s
= strndup(buf
, sizeof buf
));
245 const gather_stdout_callback_t gather_stdout
[] = {
252 static void test_stdout_gathering(void) {
253 char template[] = "/tmp/test-exec-util.XXXXXXX";
254 const char *dirs
[] = {template, NULL
};
255 const char *name
, *name2
, *name3
;
258 char **tmp
= NULL
; /* this is only used in the forked process, no cleanup here */
259 _cleanup_free_
char *output
= NULL
;
261 void* args
[] = {&tmp
, &tmp
, &output
};
263 assert_se(mkdtemp(template));
265 log_info("/* %s */", __func__
);
268 name
= strjoina(template, "/10-foo");
269 name2
= strjoina(template, "/20-bar");
270 name3
= strjoina(template, "/30-last");
272 assert_se(write_string_file(name
,
273 "#!/bin/sh\necho a\necho b\necho c\n",
274 WRITE_STRING_FILE_CREATE
) == 0);
275 assert_se(write_string_file(name2
,
276 "#!/bin/sh\necho d\n",
277 WRITE_STRING_FILE_CREATE
) == 0);
278 assert_se(write_string_file(name3
,
279 "#!/bin/sh\nsleep 1",
280 WRITE_STRING_FILE_CREATE
) == 0);
282 assert_se(chmod(name
, 0755) == 0);
283 assert_se(chmod(name2
, 0755) == 0);
284 assert_se(chmod(name3
, 0755) == 0);
286 r
= execute_directories(dirs
, DEFAULT_TIMEOUT_USEC
, gather_stdout
, args
, NULL
);
289 log_info("got: %s", output
);
291 assert_se(streq(output
, "a\nb\nc\nd\n"));
294 static void test_environment_gathering(void) {
295 char template[] = "/tmp/test-exec-util.XXXXXXX", **p
;
296 const char *dirs
[] = {template, NULL
};
297 const char *name
, *name2
, *name3
;
300 char **tmp
= NULL
; /* this is only used in the forked process, no cleanup here */
301 _cleanup_strv_free_
char **env
= NULL
;
303 void* const args
[] = { &tmp
, &tmp
, &env
};
305 assert_se(mkdtemp(template));
307 log_info("/* %s */", __func__
);
310 name
= strjoina(template, "/10-foo");
311 name2
= strjoina(template, "/20-bar");
312 name3
= strjoina(template, "/30-last");
314 assert_se(write_string_file(name
,
317 WRITE_STRING_FILE_CREATE
) == 0);
318 assert_se(write_string_file(name2
,
320 "echo A=22:$A\n\n\n", /* substitution from previous generator */
321 WRITE_STRING_FILE_CREATE
) == 0);
322 assert_se(write_string_file(name3
,
327 "echo C=001\n" /* variable overwriting */
328 /* various invalid entries */
335 /* test variable assignment without newline */
336 "echo PATH=$PATH:/no/such/file", /* no newline */
337 WRITE_STRING_FILE_CREATE
) == 0);
339 assert_se(chmod(name
, 0755) == 0);
340 assert_se(chmod(name2
, 0755) == 0);
341 assert_se(chmod(name3
, 0755) == 0);
343 r
= execute_directories(dirs
, DEFAULT_TIMEOUT_USEC
, gather_environment
, args
, NULL
);
347 log_info("got env: \"%s\"", *p
);
349 assert_se(streq(strv_env_get(env
, "A"), "22:23:24"));
350 assert_se(streq(strv_env_get(env
, "B"), "12"));
351 assert_se(streq(strv_env_get(env
, "C"), "001"));
352 assert_se(endswith(strv_env_get(env
, "PATH"), ":/no/such/file"));
355 int main(int argc
, char *argv
[]) {
356 log_set_max_level(LOG_DEBUG
);
357 log_parse_environment();
360 test_execute_directory(true);
361 test_execute_directory(false);
362 test_execution_order();
363 test_stdout_gathering();
364 test_environment_gathering();