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