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/>.
27 #include "../src/compiler.h"
31 #define MAGIC_LENGTH (strlen(MAGIC))
33 #define SETUP_RUN(number) \
34 sprintf(argv0, "%s" MAGIC "%03d", argv[0], (number))
37 extern char **environ;
40 static int find_magic_run_number(char *argv0, int *number) {
41 size_t length = strlen(argv0);
42 if (length <= MAGIC_LENGTH + 3) {
45 /* Check if the string ends with "@RUN_YYY" where YYY should be a number
47 argv0 += length - MAGIC_LENGTH - 3;
48 if (strncmp(argv0, MAGIC, MAGIC_LENGTH)) {
51 *number = atoi(argv0 + MAGIC_LENGTH);
53 /* Strip off "@RUN_YYY". */
58 static void dump(char *argv[]) {
63 printf("argv[%zu] = |%s|\n", i++, *argv++);
68 /* Skip LD_PRELOAD which contains system dependent values. */
69 if (strncmp(*env, "LD_PRELOAD=", 11)) {
70 printf("environ[%zu] = |%s|\n", i, *env);
76 /* When not writing to stdout (e.g. redirection while testing), glibc is
77 * buffering heavily. Flush to display the output before the exec*(). */
82 int main(int argc unused, char **argv) {
83 char argv0[strlen(argv[0]) + MAGIC_LENGTH + 3 + 1];
85 char *old_ldpreload = getenv("LD_PRELOAD");
86 size_t ldpreload_length = strlen("LD_PRELOAD=") + 1;
88 ldpreload_length += strlen(old_ldpreload);
90 char ldpreload[ldpreload_length];
91 strcpy(ldpreload, "LD_PRELOAD=");
93 strcat(ldpreload, old_ldpreload);
99 if (!find_magic_run_number(argv[0], &run)) {
102 char *args[] = { argv0, NULL };
103 char *envp[] = { ldpreload, NULL };
105 execve(argv[0], args, envp);
109 /* Following calls, each testing an exec*() feature. */
117 /* Check that we update/insert the environment correctly. */
120 printf("\nCHECKING COLORING.\n\n");
125 char *args[] = { argv0, NULL };
126 char *envp[] = { ldpreload, NULL };
128 execve(argv[0], args, envp);
130 } else if (!skip--) {
133 execl(argv[0], argv0, NULL);
135 } else if (!skip--) {
138 execlp(argv[0], argv0, NULL);
140 } else if (!skip--) {
143 char *envp[] = { ldpreload, NULL };
145 execle(argv[0], argv0, NULL, envp);
147 } else if (!skip--) {
150 /* Test closing a few descriptors. */
154 char *args[] = { argv0, NULL };
156 execv(argv[0], args);
158 } else if (!skip--) {
161 /* And a few more. */
165 char *args[] = { argv0, NULL };
167 execvp(argv[0], args);
175 /* And make sure our hooks don't change the behaviour. */
179 printf("\nCHECKING TRANSPARENCY.\n\n");
182 char *args[] = { argv0, NULL };
183 char *envp[] = { ldpreload, NULL };
185 execve(argv[0], args, envp);
187 } else if (!skip--) {
188 char *args[] = { argv0, NULL };
189 char *envp[] = { "TEST=42", ldpreload, NULL };
191 execve(argv[0], args, envp);
193 } else if (!skip--) {
194 char *args[] = { argv0, "foo", "bar", NULL };
195 char *envp[] = { "TEST=43", "FOO=", ldpreload, NULL };
197 execve(argv[0], args, envp);
201 } else if (!skip--) {
202 setenv("TEST", "44", 1);
204 execl(argv[0], argv0, NULL);
206 } else if (!skip--) {
207 setenv("TEST", "45", 1);
209 execl(argv[0], argv0, "foo", "bar", NULL);
212 /* execp(3), but not testing the p(ath) part */
213 } else if (!skip--) {
214 setenv("TEST", "46", 1);
216 execlp(argv[0], argv0, NULL);
218 } else if (!skip--) {
219 setenv("TEST", "47", 1);
221 execlp(argv[0], argv0, "foo", "bar", NULL);
225 } else if (!skip--) {
226 char *envp[] = { ldpreload, NULL };
228 execle(argv[0], argv0, NULL, envp);
230 } else if (!skip--) {
231 char *envp[] = { "TEST=48", ldpreload, NULL };
233 execle(argv[0], argv0, NULL, envp);
235 } else if (!skip--) {
236 char *envp[] = { "TEST=49", "FOO=", ldpreload, NULL };
238 execle(argv[0], argv0, "foo", "bar", NULL, envp);
242 } else if (!skip--) {
243 setenv("TEST", "50", 1);
245 char *args[] = { argv0, NULL };
247 execv(argv[0], args);
249 } else if (!skip--) {
250 setenv("TEST", "51", 1);
252 char *args[] = { argv0, "foo", "bar", NULL };
254 execv(argv[0], args);
257 /* execvp(3), but not testing the p(ath) part */
258 } else if (!skip--) {
259 setenv("TEST", "52", 1);
261 char *args[] = { argv0, NULL };
263 execvp(argv[0], args);
265 } else if (!skip--) {
266 setenv("TEST", "53", 1);
268 char *args[] = { argv0, "foo", "bar", NULL };
270 execvp(argv[0], args);