blob: 830cf3749cbdbde49dc9aef544c5d9d8a8e901d6 [file] [log] [blame]
Laszlo Nagybc687582016-01-12 22:38:41 +00001/* -*- 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
24extern char **environ;
25#endif
26
27char **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 ::..
37static char const *cwd = NULL;
38static FILE *fd = NULL;
39static int need_comma = 0;
40
41void 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
52void expected_out_close() {
53 fprintf(fd, "]\n");
54 fclose(fd);
55 fd = NULL;
56
57 free((void *)cwd);
58 cwd = NULL;
59}
60
61void 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
74void 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
84typedef void (*exec_fun)();
85
86void 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
114void 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
127void 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
141void 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
154void 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
167void 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
181void 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
195void 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
207void 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
219void 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
232void 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
250void 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
267int 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}