307 lines · c
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-exception5*/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_SPAWNP16#include <spawn.h>17#endif18 19// ..:: environment access fixer - begin ::..20#ifdef HAVE_NSGETENVIRON21#include <crt_externs.h>22#else23extern char **environ;24#endif25 26char **get_environ() {27#ifdef HAVE_NSGETENVIRON28 return *_NSGetEnviron();29#else30 return environ;31#endif32}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 else64 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_EXECV113void 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#endif124 125#ifdef HAVE_EXECVE126void 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#endif138 139#ifdef HAVE_EXECVP140void 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#endif151 152#ifdef HAVE_EXECVP2153void 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#endif164 165#ifdef HAVE_EXECVPE166void 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#endif178 179#ifdef HAVE_EXECT180void 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#endif192 193#ifdef HAVE_EXECL194void 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#endif204 205#ifdef HAVE_EXECLP206void 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#endif216 217#ifdef HAVE_EXECLE218void 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#endif229 230#ifdef HAVE_POSIX_SPAWN231void 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#endif247 248#ifdef HAVE_POSIX_SPAWNP249void 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#endif265 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_EXECV272 call_execv();273#endif274#ifdef HAVE_EXECVE275 call_execve();276#endif277#ifdef HAVE_EXECVP278 call_execvp();279#endif280#ifdef HAVE_EXECVP2281 call_execvP();282#endif283#ifdef HAVE_EXECVPE284 call_execvpe();285#endif286#ifdef HAVE_EXECT287 call_exect();288#endif289#ifdef HAVE_EXECL290 call_execl();291#endif292#ifdef HAVE_EXECLP293 call_execlp();294#endif295#ifdef HAVE_EXECLE296 call_execle();297#endif298#ifdef HAVE_POSIX_SPAWN299 call_posix_spawn();300#endif301#ifdef HAVE_POSIX_SPAWNP302 call_posix_spawnp();303#endif304 expected_out_close();305 return 0;306}307