1 /* -*- coding: utf-8 -*-
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 */
7
8 #include "config.h"
9
10 #include <sys/wait.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <paths.h>
15
16 #if defined HAVE_POSIX_SPAWN || defined HAVE_POSIX_SPAWNP
17 #include <spawn.h>
18 #endif
19
20 // ..:: environment access fixer - begin ::..
21 #ifdef HAVE_NSGETENVIRON
22 #include <crt_externs.h>
23 #else
24 extern char **environ;
25 #endif
26
get_environ()27 char **get_environ() {
28 #ifdef HAVE_NSGETENVIRON
29 return *_NSGetEnviron();
30 #else
31 return environ;
32 #endif
33 }
34 // ..:: environment access fixer - end ::..
35
36 // ..:: test fixtures - begin ::..
37 static char const *cwd = NULL;
38 static FILE *fd = NULL;
39 static int need_comma = 0;
40
expected_out_open(const char * expected)41 void expected_out_open(const char *expected) {
42 cwd = getcwd(NULL, 0);
43 fd = fopen(expected, "w");
44 if (!fd) {
45 perror("fopen");
46 exit(EXIT_FAILURE);
47 }
48 fprintf(fd, "[\n");
49 need_comma = 0;
50 }
51
expected_out_close()52 void expected_out_close() {
53 fprintf(fd, "]\n");
54 fclose(fd);
55 fd = NULL;
56
57 free((void *)cwd);
58 cwd = NULL;
59 }
60
expected_out(const char * file)61 void expected_out(const char *file) {
62 if (need_comma)
63 fprintf(fd, ",\n");
64 else
65 need_comma = 1;
66
67 fprintf(fd, "{\n");
68 fprintf(fd, " \"directory\": \"%s\",\n", cwd);
69 fprintf(fd, " \"command\": \"cc -c %s\",\n", file);
70 fprintf(fd, " \"file\": \"%s/%s\"\n", cwd, file);
71 fprintf(fd, "}\n");
72 }
73
create_source(char * file)74 void create_source(char *file) {
75 FILE *fd = fopen(file, "w");
76 if (!fd) {
77 perror("fopen");
78 exit(EXIT_FAILURE);
79 }
80 fprintf(fd, "typedef int score;\n");
81 fclose(fd);
82 }
83
84 typedef void (*exec_fun)();
85
wait_for(pid_t child)86 void wait_for(pid_t child) {
87 int status;
88 if (-1 == waitpid(child, &status, 0)) {
89 perror("wait");
90 exit(EXIT_FAILURE);
91 }
92 if (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE) {
93 fprintf(stderr, "children process has non zero exit code\n");
94 exit(EXIT_FAILURE);
95 }
96 }
97
98 #define FORK(FUNC) \
99 { \
100 pid_t child = fork(); \
101 if (-1 == child) { \
102 perror("fork"); \
103 exit(EXIT_FAILURE); \
104 } else if (0 == child) { \
105 FUNC fprintf(stderr, "children process failed to exec\n"); \
106 exit(EXIT_FAILURE); \
107 } else { \
108 wait_for(child); \
109 } \
110 }
111 // ..:: test fixtures - end ::..
112
113 #ifdef HAVE_EXECV
call_execv()114 void call_execv() {
115 char *const file = "execv.c";
116 char *const compiler = "/usr/bin/cc";
117 char *const argv[] = {"cc", "-c", file, 0};
118
119 expected_out(file);
120 create_source(file);
121
122 FORK(execv(compiler, argv);)
123 }
124 #endif
125
126 #ifdef HAVE_EXECVE
call_execve()127 void call_execve() {
128 char *const file = "execve.c";
129 char *const compiler = "/usr/bin/cc";
130 char *const argv[] = {compiler, "-c", file, 0};
131 char *const envp[] = {"THIS=THAT", 0};
132
133 expected_out(file);
134 create_source(file);
135
136 FORK(execve(compiler, argv, envp);)
137 }
138 #endif
139
140 #ifdef HAVE_EXECVP
call_execvp()141 void call_execvp() {
142 char *const file = "execvp.c";
143 char *const compiler = "cc";
144 char *const argv[] = {compiler, "-c", file, 0};
145
146 expected_out(file);
147 create_source(file);
148
149 FORK(execvp(compiler, argv);)
150 }
151 #endif
152
153 #ifdef HAVE_EXECVP2
call_execvP()154 void call_execvP() {
155 char *const file = "execv_p.c";
156 char *const compiler = "cc";
157 char *const argv[] = {compiler, "-c", file, 0};
158
159 expected_out(file);
160 create_source(file);
161
162 FORK(execvP(compiler, _PATH_DEFPATH, argv);)
163 }
164 #endif
165
166 #ifdef HAVE_EXECVPE
call_execvpe()167 void call_execvpe() {
168 char *const file = "execvpe.c";
169 char *const compiler = "cc";
170 char *const argv[] = {"/usr/bin/cc", "-c", file, 0};
171 char *const envp[] = {"THIS=THAT", 0};
172
173 expected_out(file);
174 create_source(file);
175
176 FORK(execvpe(compiler, argv, envp);)
177 }
178 #endif
179
180 #ifdef HAVE_EXECT
call_exect()181 void call_exect() {
182 char *const file = "exect.c";
183 char *const compiler = "/usr/bin/cc";
184 char *const argv[] = {compiler, "-c", file, 0};
185 char *const envp[] = {"THIS=THAT", 0};
186
187 expected_out(file);
188 create_source(file);
189
190 FORK(exect(compiler, argv, envp);)
191 }
192 #endif
193
194 #ifdef HAVE_EXECL
call_execl()195 void call_execl() {
196 char *const file = "execl.c";
197 char *const compiler = "/usr/bin/cc";
198
199 expected_out(file);
200 create_source(file);
201
202 FORK(execl(compiler, "cc", "-c", file, (char *)0);)
203 }
204 #endif
205
206 #ifdef HAVE_EXECLP
call_execlp()207 void call_execlp() {
208 char *const file = "execlp.c";
209 char *const compiler = "cc";
210
211 expected_out(file);
212 create_source(file);
213
214 FORK(execlp(compiler, compiler, "-c", file, (char *)0);)
215 }
216 #endif
217
218 #ifdef HAVE_EXECLE
call_execle()219 void call_execle() {
220 char *const file = "execle.c";
221 char *const compiler = "/usr/bin/cc";
222 char *const envp[] = {"THIS=THAT", 0};
223
224 expected_out(file);
225 create_source(file);
226
227 FORK(execle(compiler, compiler, "-c", file, (char *)0, envp);)
228 }
229 #endif
230
231 #ifdef HAVE_POSIX_SPAWN
call_posix_spawn()232 void call_posix_spawn() {
233 char *const file = "posix_spawn.c";
234 char *const compiler = "cc";
235 char *const argv[] = {compiler, "-c", file, 0};
236
237 expected_out(file);
238 create_source(file);
239
240 pid_t child;
241 if (0 != posix_spawn(&child, "/usr/bin/cc", 0, 0, argv, get_environ())) {
242 perror("posix_spawn");
243 exit(EXIT_FAILURE);
244 }
245 wait_for(child);
246 }
247 #endif
248
249 #ifdef HAVE_POSIX_SPAWNP
call_posix_spawnp()250 void call_posix_spawnp() {
251 char *const file = "posix_spawnp.c";
252 char *const compiler = "cc";
253 char *const argv[] = {compiler, "-c", file, 0};
254
255 expected_out(file);
256 create_source(file);
257
258 pid_t child;
259 if (0 != posix_spawnp(&child, "cc", 0, 0, argv, get_environ())) {
260 perror("posix_spawnp");
261 exit(EXIT_FAILURE);
262 }
263 wait_for(child);
264 }
265 #endif
266
main(int argc,char * const argv[])267 int main(int argc, char *const argv[]) {
268 if (argc != 2)
269 exit(EXIT_FAILURE);
270
271 expected_out_open(argv[1]);
272 #ifdef HAVE_EXECV
273 call_execv();
274 #endif
275 #ifdef HAVE_EXECVE
276 call_execve();
277 #endif
278 #ifdef HAVE_EXECVP
279 call_execvp();
280 #endif
281 #ifdef HAVE_EXECVP2
282 call_execvP();
283 #endif
284 #ifdef HAVE_EXECVPE
285 call_execvpe();
286 #endif
287 #ifdef HAVE_EXECT
288 call_exect();
289 #endif
290 #ifdef HAVE_EXECL
291 call_execl();
292 #endif
293 #ifdef HAVE_EXECLP
294 call_execlp();
295 #endif
296 #ifdef HAVE_EXECLE
297 call_execle();
298 #endif
299 #ifdef HAVE_POSIX_SPAWN
300 call_posix_spawn();
301 #endif
302 #ifdef HAVE_POSIX_SPAWNP
303 call_posix_spawnp();
304 #endif
305 expected_out_close();
306 return 0;
307 }
308