]> ruderich.org/simon Gitweb - coloredstderr/coloredstderr.git/blob - tests/example_exec.c
tests: Fix warnings about unused parameters.
[coloredstderr/coloredstderr.git] / tests / example_exec.c
1 /*
2  * Test execve() and exec*() functions.
3  *
4  * Copyright (C) 2013  Simon Ruderich
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "../src/compiler.h"
28
29
30 #define MAGIC "@RUN_"
31 #define MAGIC_LENGTH (strlen(MAGIC))
32
33 #define SETUP_RUN(number) \
34         sprintf(argv0, "%s" MAGIC "%03d", argv[0], (number))
35
36
37 extern char **environ;
38
39
40 static int find_magic_run_number(char *argv0, int *number) {
41     size_t length = strlen(argv0);
42     if (length <= MAGIC_LENGTH + 3) {
43         return 0;
44     }
45     /* Check if the string ends with "@RUN_YYY" where YYY should be a number
46      * (not checked). */
47     argv0 += length - MAGIC_LENGTH - 3;
48     if (strncmp(argv0, MAGIC, MAGIC_LENGTH)) {
49         return 0;
50     }
51     *number = atoi(argv0 + MAGIC_LENGTH);
52
53     /* Strip off "@RUN_YYY". */
54     argv0[0] = 0;
55     return 1;
56 }
57
58 static void dump(char *argv[]) {
59     size_t i;
60
61     i = 0;
62     while (*argv) {
63         printf("argv[%zu] = |%s|\n", i++, *argv++);
64     }
65     i = 0;
66     char **env = environ;
67     while (*env) {
68         /* Skip LD_PRELOAD which contains system dependent values. */
69         if (strncmp(*env, "LD_PRELOAD=", 11)) {
70             printf("environ[%zu] = |%s|\n", i, *env);
71         }
72         i++;
73         env++;
74     }
75     printf("\n");
76     /* When not writing to stdout (e.g. redirection while testing), glibc is
77      * buffering heavily. Flush to display the output before the exec*(). */
78     fflush(stdout);
79 }
80
81
82 int main(int argc unused, char **argv) {
83     char argv0[strlen(argv[0]) + MAGIC_LENGTH + 3 + 1];
84
85     char *old_ldpreload = getenv("LD_PRELOAD");
86     size_t ldpreload_length = strlen("LD_PRELOAD=") + 1;
87     if (old_ldpreload) {
88         ldpreload_length += strlen(old_ldpreload);
89     }
90     char ldpreload[ldpreload_length];
91     strcpy(ldpreload, "LD_PRELOAD=");
92     if (old_ldpreload) {
93         strcat(ldpreload, old_ldpreload);
94     }
95
96     int run;
97
98     /* First call. */
99     if (!find_magic_run_number(argv[0], &run)) {
100         SETUP_RUN(1);
101
102         char *args[] = { argv0, NULL };
103         char *envp[] = { ldpreload, NULL };
104
105         execve(argv[0], args, envp);
106         return EXIT_FAILURE;
107     }
108
109     /* Following calls, each testing an exec*() feature. */
110
111     dump(argv);
112     SETUP_RUN(run + 1);
113
114     int skip = run - 1;
115
116
117     /* Check that we update/insert the environment correctly. */
118
119     if (!skip--) {
120         printf("\nCHECKING COLORING.\n\n");
121         fflush(stdout);
122
123         dup2(2, 3);
124
125         char *args[] = { argv0, NULL };
126         char *envp[] = { ldpreload, NULL };
127
128         execve(argv[0], args, envp);
129         return EXIT_FAILURE;
130     } else if (!skip--) {
131         dup2(2, 4);
132
133         execl(argv[0], argv0, NULL);
134         return EXIT_FAILURE;
135     } else if (!skip--) {
136         dup2(2, 5);
137
138         execlp(argv[0], argv0, NULL);
139         return EXIT_FAILURE;
140     } else if (!skip--) {
141         dup2(2, 6);
142
143         char *envp[] = { ldpreload, NULL };
144
145         execle(argv[0], argv0, NULL, envp);
146         return EXIT_FAILURE;
147     } else if (!skip--) {
148         dup2(2, 7);
149
150         /* Test closing a few descriptors. */
151         close(5);
152         close(6);
153
154         char *args[] = { argv0, NULL };
155
156         execv(argv[0], args);
157         return EXIT_FAILURE;
158     } else if (!skip--) {
159         dup2(2, 8);
160
161         /* And a few more. */
162         close(7);
163         close(4);
164
165         char *args[] = { argv0, NULL };
166
167         execvp(argv[0], args);
168         return EXIT_FAILURE;
169     } else {
170         close(3);
171         close(8);
172     }
173
174
175     /* And make sure our hooks don't change the behaviour. */
176
177     /* execve(2) */
178     if (!skip--) {
179         printf("\nCHECKING TRANSPARENCY.\n\n");
180         fflush(stdout);
181
182         char *args[] = { argv0, NULL };
183         char *envp[] = { ldpreload, NULL };
184
185         execve(argv[0], args, envp);
186         return EXIT_FAILURE;
187     } else if (!skip--) {
188         char *args[] = { argv0, NULL };
189         char *envp[] = { "TEST=42", ldpreload, NULL };
190
191         execve(argv[0], args, envp);
192         return EXIT_FAILURE;
193     } else if (!skip--) {
194         char *args[] = { argv0, "foo", "bar", NULL };
195         char *envp[] = { "TEST=43", "FOO=", ldpreload, NULL };
196
197         execve(argv[0], args, envp);
198         return EXIT_FAILURE;
199
200     /* execl(3) */
201     } else if (!skip--) {
202         setenv("TEST", "44", 1);
203
204         execl(argv[0], argv0, NULL);
205         return EXIT_FAILURE;
206     } else if (!skip--) {
207         setenv("TEST", "45", 1);
208
209         execl(argv[0], argv0, "foo", "bar", NULL);
210         return EXIT_FAILURE;
211
212     /* execp(3), but not testing the p(ath) part */
213     } else if (!skip--) {
214         setenv("TEST", "46", 1);
215
216         execlp(argv[0], argv0, NULL);
217         return EXIT_FAILURE;
218     } else if (!skip--) {
219         setenv("TEST", "47", 1);
220
221         execlp(argv[0], argv0, "foo", "bar", NULL);
222         return EXIT_FAILURE;
223
224     /* execle(3) */
225     } else if (!skip--) {
226         char *envp[] = { ldpreload, NULL };
227
228         execle(argv[0], argv0, NULL, envp);
229         return EXIT_FAILURE;
230     } else if (!skip--) {
231         char *envp[] = { "TEST=48", ldpreload, NULL };
232
233         execle(argv[0], argv0, NULL, envp);
234         return EXIT_FAILURE;
235     } else if (!skip--) {
236         char *envp[] = { "TEST=49", "FOO=", ldpreload, NULL };
237
238         execle(argv[0], argv0, "foo", "bar", NULL, envp);
239         return EXIT_FAILURE;
240
241     /* execv(3) */
242     } else if (!skip--) {
243         setenv("TEST", "50", 1);
244
245         char *args[] = { argv0, NULL };
246
247         execv(argv[0], args);
248         return EXIT_FAILURE;
249     } else if (!skip--) {
250         setenv("TEST", "51", 1);
251
252         char *args[] = { argv0, "foo", "bar", NULL };
253
254         execv(argv[0], args);
255         return EXIT_FAILURE;
256
257     /* execvp(3), but not testing the p(ath) part */
258     } else if (!skip--) {
259         setenv("TEST", "52", 1);
260
261         char *args[] = { argv0, NULL };
262
263         execvp(argv[0], args);
264         return EXIT_FAILURE;
265     } else if (!skip--) {
266         setenv("TEST", "53", 1);
267
268         char *args[] = { argv0, "foo", "bar", NULL };
269
270         execvp(argv[0], args);
271         return EXIT_FAILURE;
272     }
273
274     printf("Done.\n");
275     return EXIT_SUCCESS;
276 }