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