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 #define MAGIC_LENGTH (strlen(MAGIC))
29 #define SETUP_RUN(number) \
30 sprintf(argv0, "%s" MAGIC "%03d", argv[0], (number))
33 extern char **environ;
36 static int find_magic_run_number(char *argv0, int *number) {
37 size_t length = strlen(argv0);
38 if (length <= MAGIC_LENGTH + 3) {
41 /* Check if the string ends with "@RUN_YYY" where YYY should be a number
43 argv0 += length - MAGIC_LENGTH - 3;
44 if (strncmp(argv0, MAGIC, MAGIC_LENGTH)) {
47 *number = atoi(argv0 + MAGIC_LENGTH);
49 /* Strip off "@RUN_YYY". */
54 static void dump(char *argv[]) {
59 printf("argv[%zu] = |%s|\n", i++, *argv++);
64 /* Skip LD_PRELOAD which contains system dependent values. */
65 if (strncmp(*env, "LD_PRELOAD=", 11)) {
66 printf("environ[%zu] = |%s|\n", i, *env);
72 /* When not writing to stdout (e.g. redirection while testing), glibc is
73 * buffering heavily. Flush to display the output before the exec*(). */
78 int main(int argc, char **argv) {
79 char argv0[strlen(argv[0]) + MAGIC_LENGTH + 3 + 1];
81 char *old_ldpreload = getenv("LD_PRELOAD");
82 size_t ldpreload_length = strlen("LD_PRELOAD=") + 1;
84 ldpreload_length += strlen(old_ldpreload);
86 char ldpreload[ldpreload_length];
87 strcpy(ldpreload, "LD_PRELOAD=");
89 strcat(ldpreload, old_ldpreload);
95 if (!find_magic_run_number(argv[0], &run)) {
98 char *args[] = { argv0, NULL };
99 char *envp[] = { ldpreload, NULL };
101 execve(argv[0], args, envp);
105 /* Following calls, each testing an exec*() feature. */
113 /* Check that we update/insert the environment correctly. */
116 printf("\nCHECKING COLORING.\n\n");
121 char *args[] = { argv0, NULL };
122 char *envp[] = { ldpreload, NULL };
124 execve(argv[0], args, envp);
126 } else if (!skip--) {
129 execl(argv[0], argv0, NULL);
131 } else if (!skip--) {
134 execlp(argv[0], argv0, NULL);
136 } else if (!skip--) {
139 char *envp[] = { ldpreload, NULL };
141 execle(argv[0], argv0, NULL, envp);
143 } else if (!skip--) {
146 /* Test closing a few descriptors. */
150 char *args[] = { argv0, NULL };
152 execv(argv[0], args);
154 } else if (!skip--) {
157 /* And a few more. */
161 char *args[] = { argv0, NULL };
163 execvp(argv[0], args);
171 /* And make sure our hooks don't change the behaviour. */
175 printf("\nCHECKING TRANSPARENCY.\n\n");
178 char *args[] = { argv0, NULL };
179 char *envp[] = { ldpreload, NULL };
181 execve(argv[0], args, envp);
183 } else if (!skip--) {
184 char *args[] = { argv0, NULL };
185 char *envp[] = { "TEST=42", ldpreload, NULL };
187 execve(argv[0], args, envp);
189 } else if (!skip--) {
190 char *args[] = { argv0, "foo", "bar", NULL };
191 char *envp[] = { "TEST=43", "FOO=", ldpreload, NULL };
193 execve(argv[0], args, envp);
197 } else if (!skip--) {
198 setenv("TEST", "44", 1);
200 execl(argv[0], argv0, NULL);
202 } else if (!skip--) {
203 setenv("TEST", "45", 1);
205 execl(argv[0], argv0, "foo", "bar", NULL);
208 /* execp(3), but not testing the p(ath) part */
209 } else if (!skip--) {
210 setenv("TEST", "46", 1);
212 execlp(argv[0], argv0, NULL);
214 } else if (!skip--) {
215 setenv("TEST", "47", 1);
217 execlp(argv[0], argv0, "foo", "bar", NULL);
221 } else if (!skip--) {
222 char *envp[] = { ldpreload, NULL };
224 execle(argv[0], argv0, NULL, envp);
226 } else if (!skip--) {
227 char *envp[] = { "TEST=48", ldpreload, NULL };
229 execle(argv[0], argv0, NULL, envp);
231 } else if (!skip--) {
232 char *envp[] = { "TEST=49", "FOO=", ldpreload, NULL };
234 execle(argv[0], argv0, "foo", "bar", NULL, envp);
238 } else if (!skip--) {
239 setenv("TEST", "50", 1);
241 char *args[] = { argv0, NULL };
243 execv(argv[0], args);
245 } else if (!skip--) {
246 setenv("TEST", "51", 1);
248 char *args[] = { argv0, "foo", "bar", NULL };
250 execv(argv[0], args);
253 /* execvp(3), but not testing the p(ath) part */
254 } else if (!skip--) {
255 setenv("TEST", "52", 1);
257 char *args[] = { argv0, NULL };
259 execvp(argv[0], args);
261 } else if (!skip--) {
262 setenv("TEST", "53", 1);
264 char *args[] = { argv0, "foo", "bar", NULL };
266 execvp(argv[0], args);