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/>.
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 void dump(char *argv[]) {
67 printf("argv[%zu] = |%s|\n", i++, *argv++);
72 /* Skip LD_PRELOAD which contains system dependent values. */
73 if (strncmp(*env, "LD_PRELOAD=", 11)) {
74 printf("environ[%zu] = |%s|\n", i, *env);
80 /* When not writing to stdout (e.g. redirection while testing), glibc is
81 * buffering heavily. Flush to display the output before the exec*(). */
86 int main(int argc unused, char **argv) {
87 char argv0[strlen(argv[0]) + MAGIC_LENGTH + 3 + 1];
89 char *old_ldpreload = getenv("LD_PRELOAD");
90 size_t ldpreload_length = strlen("LD_PRELOAD=") + 1;
92 ldpreload_length += strlen(old_ldpreload);
94 char ldpreload[ldpreload_length];
95 strcpy(ldpreload, "LD_PRELOAD=");
97 strcat(ldpreload, old_ldpreload);
103 if (!find_magic_run_number(argv[0], &run)) {
106 char *args[] = { argv0, NULL };
107 char *envp[] = { ldpreload, NULL };
109 execve(argv[0], args, envp);
113 /* Following calls, each testing an exec*() feature. */
121 /* Check that we update/insert the environment correctly. */
124 printf("\nCHECKING COLORING.\n\n");
129 char *args[] = { argv0, NULL };
130 char *envp[] = { ldpreload, NULL };
132 execve(argv[0], args, envp);
134 } else if (!skip--) {
137 execl(argv[0], argv0, NULL);
139 } else if (!skip--) {
142 execlp(argv[0], argv0, NULL);
144 } else if (!skip--) {
147 char *envp[] = { ldpreload, NULL };
149 execle(argv[0], argv0, NULL, envp);
151 } else if (!skip--) {
154 /* Test closing a few descriptors. */
158 char *args[] = { argv0, NULL };
160 execv(argv[0], args);
162 } else if (!skip--) {
165 /* And a few more. */
169 char *args[] = { argv0, NULL };
171 execvp(argv[0], args);
174 /* Test handling of COLORED_STDERR_FDS. */
176 } else if (!skip--) {
183 char *args[] = { argv0, NULL };
184 char *envp[] = { ldpreload, "COLORED_STDERR_FDS=5,", NULL };
186 execve(argv[0], args, envp);
188 } else if (!skip--) {
189 char *args[] = { argv0, NULL };
190 char *envp[] = { ldpreload, NULL };
195 execve(argv[0], args, envp);
197 } else if (!skip--) {
200 char *args[] = { argv0, NULL };
201 setenv("COLORED_STDERR_FDS", "2,", 1);
203 execv(argv[0], args);
208 /* And make sure our hooks don't change the behaviour. */
212 printf("\nCHECKING TRANSPARENCY.\n\n");
215 char *args[] = { argv0, NULL };
216 char *envp[] = { ldpreload, NULL };
218 execve(argv[0], args, envp);
220 } else if (!skip--) {
221 char *args[] = { argv0, NULL };
222 char *envp[] = { "TEST=42", ldpreload, NULL };
224 execve(argv[0], args, envp);
226 } else if (!skip--) {
227 char *args[] = { argv0, "foo", "bar", NULL };
228 char *envp[] = { "TEST=43", "FOO=", ldpreload, NULL };
230 execve(argv[0], args, envp);
234 } else if (!skip--) {
235 setenv("TEST", "44", 1);
237 execl(argv[0], argv0, NULL);
239 } else if (!skip--) {
240 setenv("TEST", "45", 1);
242 execl(argv[0], argv0, "foo", "bar", NULL);
245 /* execp(3), but not testing the p(ath) part */
246 } else if (!skip--) {
247 setenv("TEST", "46", 1);
249 execlp(argv[0], argv0, NULL);
251 } else if (!skip--) {
252 setenv("TEST", "47", 1);
254 execlp(argv[0], argv0, "foo", "bar", NULL);
258 } else if (!skip--) {
259 char *envp[] = { ldpreload, NULL };
261 execle(argv[0], argv0, NULL, envp);
263 } else if (!skip--) {
264 char *envp[] = { "TEST=48", ldpreload, NULL };
266 execle(argv[0], argv0, NULL, envp);
268 } else if (!skip--) {
269 char *envp[] = { "TEST=49", "FOO=", ldpreload, NULL };
271 execle(argv[0], argv0, "foo", "bar", NULL, envp);
275 } else if (!skip--) {
276 setenv("TEST", "50", 1);
278 char *args[] = { argv0, NULL };
280 execv(argv[0], args);
282 } else if (!skip--) {
283 setenv("TEST", "51", 1);
285 char *args[] = { argv0, "foo", "bar", NULL };
287 execv(argv[0], args);
290 /* execvp(3), but not testing the p(ath) part */
291 } else if (!skip--) {
292 setenv("TEST", "52", 1);
294 char *args[] = { argv0, NULL };
296 execvp(argv[0], args);
298 } else if (!skip--) {
299 setenv("TEST", "53", 1);
301 char *args[] = { argv0, "foo", "bar", NULL };
303 execvp(argv[0], args);
307 /* execvpe(3), but not testing the p(ath) part */
308 } else if (!skip--) {
309 char *args[] = { argv0, NULL };
310 char *envp[] = { "TEST=54", ldpreload, NULL };
312 execvpe(argv[0], args, envp);
314 } else if (!skip--) {
315 char *args[] = { argv0, "foo", "bar", NULL };
316 char *envp[] = { "TEST=55", ldpreload, NULL };
318 execvpe(argv[0], args, envp);
321 /* Fake output to let the test pass. */
322 } else if (!skip--) {
323 puts("argv[0] = |./example_exec|");
324 puts("environ[0] = |TEST=54|");
325 puts("environ[2] = |COLORED_STDERR_PRIVATE_FDS=2,|");
327 puts("argv[0] = |./example_exec|");
328 puts("argv[1] = |foo|");
329 puts("argv[2] = |bar|");
330 puts("environ[0] = |TEST=55|");
331 puts("environ[2] = |COLORED_STDERR_PRIVATE_FDS=2,|");