2 * Test execve() and exec*() functions.
4 * Copyright (C) 2013 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/>.
30 #include "../src/compiler.h"
34 #define MAGIC_LENGTH (strlen(MAGIC))
36 #define SETUP_RUN(number) \
37 sprintf(argv0, "%s" MAGIC "%03d", argv[0], (number))
40 extern char **environ;
43 static int find_magic_run_number(char *argv0, int *number) {
44 size_t length = strlen(argv0);
45 if (length <= MAGIC_LENGTH + 3) {
48 /* Check if the string ends with "@RUN_YYY" where YYY should be a number
50 argv0 += length - MAGIC_LENGTH - 3;
51 if (strncmp(argv0, MAGIC, MAGIC_LENGTH)) {
54 *number = atoi(argv0 + MAGIC_LENGTH);
56 /* Strip off "@RUN_YYY". */
61 static void dump(char *argv[]) {
66 printf("argv[%zu] = |%s|\n", i++, *argv++);
71 /* Skip LD_PRELOAD which contains system dependent values. */
72 if (strncmp(*env, "LD_PRELOAD=", 11)) {
73 printf("environ[%zu] = |%s|\n", i, *env);
79 /* When not writing to stdout (e.g. redirection while testing), glibc is
80 * buffering heavily. Flush to display the output before the exec*(). */
85 int main(int argc unused, char **argv) {
86 char argv0[strlen(argv[0]) + MAGIC_LENGTH + 3 + 1];
88 char *old_ldpreload = getenv("LD_PRELOAD");
89 size_t ldpreload_length = strlen("LD_PRELOAD=") + 1;
91 ldpreload_length += strlen(old_ldpreload);
93 char ldpreload[ldpreload_length];
94 strcpy(ldpreload, "LD_PRELOAD=");
96 strcat(ldpreload, old_ldpreload);
102 if (!find_magic_run_number(argv[0], &run)) {
105 char *args[] = { argv0, NULL };
106 char *envp[] = { ldpreload, NULL };
108 execve(argv[0], args, envp);
112 /* Following calls, each testing an exec*() feature. */
120 /* Check that we update/insert the environment correctly. */
123 printf("\nCHECKING COLORING.\n\n");
128 char *args[] = { argv0, NULL };
129 char *envp[] = { ldpreload, NULL };
131 execve(argv[0], args, envp);
133 } else if (!skip--) {
136 execl(argv[0], argv0, NULL);
138 } else if (!skip--) {
141 execlp(argv[0], argv0, NULL);
143 } else if (!skip--) {
146 char *envp[] = { ldpreload, NULL };
148 execle(argv[0], argv0, NULL, envp);
150 } else if (!skip--) {
153 /* Test closing a few descriptors. */
157 char *args[] = { argv0, NULL };
159 execv(argv[0], args);
161 } else if (!skip--) {
164 /* And a few more. */
168 char *args[] = { argv0, NULL };
170 execvp(argv[0], args);
173 /* Test handling of COLORED_STDERR_FDS. */
175 } else if (!skip--) {
182 char *args[] = { argv0, NULL };
183 char *envp[] = { ldpreload, "COLORED_STDERR_FDS=5,", NULL };
185 execve(argv[0], args, envp);
187 } else if (!skip--) {
188 char *args[] = { argv0, NULL };
189 char *envp[] = { ldpreload, NULL };
194 execve(argv[0], args, envp);
196 } else if (!skip--) {
199 char *args[] = { argv0, NULL };
200 setenv("COLORED_STDERR_FDS", "2,", 1);
202 execv(argv[0], args);
207 /* And make sure our hooks don't change the behaviour. */
211 printf("\nCHECKING TRANSPARENCY.\n\n");
214 char *args[] = { argv0, NULL };
215 char *envp[] = { ldpreload, NULL };
217 execve(argv[0], args, envp);
219 } else if (!skip--) {
220 char *args[] = { argv0, NULL };
221 char *envp[] = { "TEST=42", ldpreload, NULL };
223 execve(argv[0], args, envp);
225 } else if (!skip--) {
226 char *args[] = { argv0, "foo", "bar", NULL };
227 char *envp[] = { "TEST=43", "FOO=", ldpreload, NULL };
229 execve(argv[0], args, envp);
233 } else if (!skip--) {
234 setenv("TEST", "44", 1);
236 execl(argv[0], argv0, NULL);
238 } else if (!skip--) {
239 setenv("TEST", "45", 1);
241 execl(argv[0], argv0, "foo", "bar", NULL);
244 /* execp(3), but not testing the p(ath) part */
245 } else if (!skip--) {
246 setenv("TEST", "46", 1);
248 execlp(argv[0], argv0, NULL);
250 } else if (!skip--) {
251 setenv("TEST", "47", 1);
253 execlp(argv[0], argv0, "foo", "bar", NULL);
257 } else if (!skip--) {
258 char *envp[] = { ldpreload, NULL };
260 execle(argv[0], argv0, NULL, envp);
262 } else if (!skip--) {
263 char *envp[] = { "TEST=48", ldpreload, NULL };
265 execle(argv[0], argv0, NULL, envp);
267 } else if (!skip--) {
268 char *envp[] = { "TEST=49", "FOO=", ldpreload, NULL };
270 execle(argv[0], argv0, "foo", "bar", NULL, envp);
274 } else if (!skip--) {
275 setenv("TEST", "50", 1);
277 char *args[] = { argv0, NULL };
279 execv(argv[0], args);
281 } else if (!skip--) {
282 setenv("TEST", "51", 1);
284 char *args[] = { argv0, "foo", "bar", NULL };
286 execv(argv[0], args);
289 /* execvp(3), but not testing the p(ath) part */
290 } else if (!skip--) {
291 setenv("TEST", "52", 1);
293 char *args[] = { argv0, NULL };
295 execvp(argv[0], args);
297 } else if (!skip--) {
298 setenv("TEST", "53", 1);
300 char *args[] = { argv0, "foo", "bar", NULL };
302 execvp(argv[0], args);
306 /* execvpe(3), but not testing the p(ath) part */
307 } else if (!skip--) {
308 char *args[] = { argv0, NULL };
309 char *envp[] = { "TEST=54", ldpreload, NULL };
311 execvpe(argv[0], args, envp);
313 } else if (!skip--) {
314 char *args[] = { argv0, "foo", "bar", NULL };
315 char *envp[] = { "TEST=55", ldpreload, NULL };
317 execvpe(argv[0], args, envp);
320 /* Fake output to let the test pass. */
321 } else if (!skip--) {
322 puts("argv[0] = |./example_exec|");
323 puts("environ[0] = |TEST=54|");
324 puts("environ[2] = |COLORED_STDERR_PRIVATE_FDS=2,|");
326 puts("argv[0] = |./example_exec|");
327 puts("argv[1] = |foo|");
328 puts("argv[2] = |bar|");
329 puts("environ[0] = |TEST=55|");
330 puts("environ[2] = |COLORED_STDERR_PRIVATE_FDS=2,|");