2 * Test execve() and exec*() functions.
4 * Copyright (C) 2013-2014 Simon Ruderich
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include "../src/compiler.h"
35 #define MAGIC_LENGTH (strlen(MAGIC))
37 #define SETUP_RUN(number) \
38 sprintf(argv0, "%s" MAGIC "%03d", argv[0], (number))
41 extern char **environ;
44 static int find_magic_run_number(char *argv0, int *number) {
45 size_t length = strlen(argv0);
46 if (length <= MAGIC_LENGTH + 3) {
49 /* Check if the string ends with "@RUN_YYY" where YYY should be a number
51 argv0 += length - MAGIC_LENGTH - 3;
52 if (strncmp(argv0, MAGIC, MAGIC_LENGTH)) {
55 *number = atoi(argv0 + MAGIC_LENGTH);
57 /* Strip off "@RUN_YYY". */
62 static int cmp(void const *a, void const *b) {
63 return strcmp(*(char * const *)a, *(char * const *)b);
65 static void dump(char *argv[]) {
70 printf("argv[%zu] = |%s|\n", i++, *argv++);
73 /* Order of environment variables is not defined, sort them for consistent
80 qsort(environ, i, sizeof(*env), cmp);
85 /* Skip LD_PRELOAD which contains system dependent values. */
86 if (strncmp(*env, "LD_PRELOAD=", 11)) {
87 printf("environ[%zu] = |%s|\n", i++, *env);
92 /* When not writing to stdout (e.g. redirection while testing), glibc is
93 * buffering heavily. Flush to display the output before the exec*(). */
98 int main(int argc unused, char **argv) {
99 char argv0[strlen(argv[0]) + MAGIC_LENGTH + 3 + 1];
101 char *old_ldpreload = getenv("LD_PRELOAD");
102 size_t ldpreload_length = strlen("LD_PRELOAD=") + 1;
104 ldpreload_length += strlen(old_ldpreload);
106 char ldpreload[ldpreload_length];
107 strcpy(ldpreload, "LD_PRELOAD=");
109 strcat(ldpreload, old_ldpreload);
115 if (!find_magic_run_number(argv[0], &run)) {
118 char *args[] = { argv0, NULL };
119 char *envp[] = { ldpreload, NULL };
121 execve(argv[0], args, envp);
125 /* Following calls, each testing an exec*() feature. */
133 /* Check that we update/insert the environment correctly. */
136 printf("\nCHECKING COLORING.\n\n");
141 char *args[] = { argv0, NULL };
142 char *envp[] = { ldpreload, NULL };
144 execve(argv[0], args, envp);
146 } else if (!skip--) {
149 execl(argv[0], argv0, NULL);
151 } else if (!skip--) {
154 execlp(argv[0], argv0, NULL);
156 } else if (!skip--) {
159 char *envp[] = { ldpreload, NULL };
161 execle(argv[0], argv0, NULL, envp);
163 } else if (!skip--) {
166 /* Test closing a few descriptors. */
170 char *args[] = { argv0, NULL };
172 execv(argv[0], args);
174 } else if (!skip--) {
177 /* And a few more. */
181 char *args[] = { argv0, NULL };
183 execvp(argv[0], args);
186 /* Test handling of COLORED_STDERR_FDS. */
188 } else if (!skip--) {
195 char *args[] = { argv0, NULL };
196 char *envp[] = { ldpreload, "COLORED_STDERR_FDS=5,", NULL };
198 execve(argv[0], args, envp);
200 } else if (!skip--) {
201 char *args[] = { argv0, NULL };
202 char *envp[] = { ldpreload, NULL };
207 execve(argv[0], args, envp);
209 } else if (!skip--) {
212 char *args[] = { argv0, NULL };
213 setenv("COLORED_STDERR_FDS", "2,", 1);
215 execv(argv[0], args);
220 /* And make sure our hooks don't change the behaviour. */
224 printf("\nCHECKING TRANSPARENCY.\n\n");
227 char *args[] = { argv0, NULL };
228 char *envp[] = { ldpreload, NULL };
230 execve(argv[0], args, envp);
232 } else if (!skip--) {
233 char *args[] = { argv0, NULL };
234 char *envp[] = { "TEST=42", ldpreload, NULL };
236 execve(argv[0], args, envp);
238 } else if (!skip--) {
239 char *args[] = { argv0, "foo", "bar", NULL };
240 char *envp[] = { "TEST=43", "FOO=", ldpreload, NULL };
242 execve(argv[0], args, envp);
246 } else if (!skip--) {
247 setenv("TEST", "44", 1);
249 execl(argv[0], argv0, NULL);
251 } else if (!skip--) {
252 setenv("TEST", "45", 1);
254 execl(argv[0], argv0, "foo", "bar", NULL);
257 /* execp(3), but not testing the p(ath) part */
258 } else if (!skip--) {
259 setenv("TEST", "46", 1);
261 execlp(argv[0], argv0, NULL);
263 } else if (!skip--) {
264 setenv("TEST", "47", 1);
266 execlp(argv[0], argv0, "foo", "bar", NULL);
270 } else if (!skip--) {
271 char *envp[] = { ldpreload, NULL };
273 execle(argv[0], argv0, NULL, envp);
275 } else if (!skip--) {
276 char *envp[] = { "TEST=48", ldpreload, NULL };
278 execle(argv[0], argv0, NULL, envp);
280 } else if (!skip--) {
281 char *envp[] = { "TEST=49", "FOO=", ldpreload, NULL };
283 execle(argv[0], argv0, "foo", "bar", NULL, envp);
287 } else if (!skip--) {
288 setenv("TEST", "50", 1);
290 char *args[] = { argv0, NULL };
292 execv(argv[0], args);
294 } else if (!skip--) {
295 setenv("TEST", "51", 1);
297 char *args[] = { argv0, "foo", "bar", NULL };
299 execv(argv[0], args);
302 /* execvp(3), but not testing the p(ath) part */
303 } else if (!skip--) {
304 setenv("TEST", "52", 1);
306 char *args[] = { argv0, NULL };
308 execvp(argv[0], args);
310 } else if (!skip--) {
311 setenv("TEST", "53", 1);
313 char *args[] = { argv0, "foo", "bar", NULL };
315 execvp(argv[0], args);
319 /* execvpe(3), but not testing the p(ath) part */
320 } else if (!skip--) {
321 char *args[] = { argv0, NULL };
322 char *envp[] = { "TEST=54", ldpreload, NULL };
324 execvpe(argv[0], args, envp);
326 } else if (!skip--) {
327 char *args[] = { argv0, "foo", "bar", NULL };
328 char *envp[] = { "TEST=55", ldpreload, NULL };
330 execvpe(argv[0], args, envp);
333 /* Fake output to let the test pass. */
334 } else if (!skip--) {
335 puts("argv[0] = |./example_exec|");
336 puts("environ[0] = |COLORED_STDERR_PRIVATE_FDS=2,|");
337 puts("environ[1] = |TEST=54|");
339 puts("argv[0] = |./example_exec|");
340 puts("argv[1] = |foo|");
341 puts("argv[2] = |bar|");
342 puts("environ[0] = |COLORED_STDERR_PRIVATE_FDS=2,|");
343 puts("environ[1] = |TEST=55|");