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