| /* -*- coding: utf-8 -*- |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| */ |
| |
| #include "config.h" |
| |
| #include <sys/wait.h> |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <paths.h> |
| |
| #if defined HAVE_POSIX_SPAWN || defined HAVE_POSIX_SPAWNP |
| #include <spawn.h> |
| #endif |
| |
| // ..:: environment access fixer - begin ::.. |
| #ifdef HAVE_NSGETENVIRON |
| #include <crt_externs.h> |
| #else |
| extern char **environ; |
| #endif |
| |
| char **get_environ() { |
| #ifdef HAVE_NSGETENVIRON |
| return *_NSGetEnviron(); |
| #else |
| return environ; |
| #endif |
| } |
| // ..:: environment access fixer - end ::.. |
| |
| // ..:: test fixtures - begin ::.. |
| static char const *cwd = NULL; |
| static FILE *fd = NULL; |
| static int need_comma = 0; |
| |
| void expected_out_open(const char *expected) { |
| cwd = getcwd(NULL, 0); |
| fd = fopen(expected, "w"); |
| if (!fd) { |
| perror("fopen"); |
| exit(EXIT_FAILURE); |
| } |
| fprintf(fd, "[\n"); |
| need_comma = 0; |
| } |
| |
| void expected_out_close() { |
| fprintf(fd, "]\n"); |
| fclose(fd); |
| fd = NULL; |
| |
| free((void *)cwd); |
| cwd = NULL; |
| } |
| |
| void expected_out(const char *file) { |
| if (need_comma) |
| fprintf(fd, ",\n"); |
| else |
| need_comma = 1; |
| |
| fprintf(fd, "{\n"); |
| fprintf(fd, " \"directory\": \"%s\",\n", cwd); |
| fprintf(fd, " \"command\": \"cc -c %s\",\n", file); |
| fprintf(fd, " \"file\": \"%s/%s\"\n", cwd, file); |
| fprintf(fd, "}\n"); |
| } |
| |
| void create_source(char *file) { |
| FILE *fd = fopen(file, "w"); |
| if (!fd) { |
| perror("fopen"); |
| exit(EXIT_FAILURE); |
| } |
| fprintf(fd, "typedef int score;\n"); |
| fclose(fd); |
| } |
| |
| typedef void (*exec_fun)(); |
| |
| void wait_for(pid_t child) { |
| int status; |
| if (-1 == waitpid(child, &status, 0)) { |
| perror("wait"); |
| exit(EXIT_FAILURE); |
| } |
| if (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE) { |
| fprintf(stderr, "children process has non zero exit code\n"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| #define FORK(FUNC) \ |
| { \ |
| pid_t child = fork(); \ |
| if (-1 == child) { \ |
| perror("fork"); \ |
| exit(EXIT_FAILURE); \ |
| } else if (0 == child) { \ |
| FUNC fprintf(stderr, "children process failed to exec\n"); \ |
| exit(EXIT_FAILURE); \ |
| } else { \ |
| wait_for(child); \ |
| } \ |
| } |
| // ..:: test fixtures - end ::.. |
| |
| #ifdef HAVE_EXECV |
| void call_execv() { |
| char *const file = "execv.c"; |
| char *const compiler = "/usr/bin/cc"; |
| char *const argv[] = {"cc", "-c", file, 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execv(compiler, argv);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECVE |
| void call_execve() { |
| char *const file = "execve.c"; |
| char *const compiler = "/usr/bin/cc"; |
| char *const argv[] = {compiler, "-c", file, 0}; |
| char *const envp[] = {"THIS=THAT", 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execve(compiler, argv, envp);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECVP |
| void call_execvp() { |
| char *const file = "execvp.c"; |
| char *const compiler = "cc"; |
| char *const argv[] = {compiler, "-c", file, 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execvp(compiler, argv);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECVP2 |
| void call_execvP() { |
| char *const file = "execv_p.c"; |
| char *const compiler = "cc"; |
| char *const argv[] = {compiler, "-c", file, 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execvP(compiler, _PATH_DEFPATH, argv);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECVPE |
| void call_execvpe() { |
| char *const file = "execvpe.c"; |
| char *const compiler = "cc"; |
| char *const argv[] = {"/usr/bin/cc", "-c", file, 0}; |
| char *const envp[] = {"THIS=THAT", 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execvpe(compiler, argv, envp);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECT |
| void call_exect() { |
| char *const file = "exect.c"; |
| char *const compiler = "/usr/bin/cc"; |
| char *const argv[] = {compiler, "-c", file, 0}; |
| char *const envp[] = {"THIS=THAT", 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(exect(compiler, argv, envp);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECL |
| void call_execl() { |
| char *const file = "execl.c"; |
| char *const compiler = "/usr/bin/cc"; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execl(compiler, "cc", "-c", file, (char *)0);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECLP |
| void call_execlp() { |
| char *const file = "execlp.c"; |
| char *const compiler = "cc"; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execlp(compiler, compiler, "-c", file, (char *)0);) |
| } |
| #endif |
| |
| #ifdef HAVE_EXECLE |
| void call_execle() { |
| char *const file = "execle.c"; |
| char *const compiler = "/usr/bin/cc"; |
| char *const envp[] = {"THIS=THAT", 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| FORK(execle(compiler, compiler, "-c", file, (char *)0, envp);) |
| } |
| #endif |
| |
| #ifdef HAVE_POSIX_SPAWN |
| void call_posix_spawn() { |
| char *const file = "posix_spawn.c"; |
| char *const compiler = "cc"; |
| char *const argv[] = {compiler, "-c", file, 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| pid_t child; |
| if (0 != posix_spawn(&child, "/usr/bin/cc", 0, 0, argv, get_environ())) { |
| perror("posix_spawn"); |
| exit(EXIT_FAILURE); |
| } |
| wait_for(child); |
| } |
| #endif |
| |
| #ifdef HAVE_POSIX_SPAWNP |
| void call_posix_spawnp() { |
| char *const file = "posix_spawnp.c"; |
| char *const compiler = "cc"; |
| char *const argv[] = {compiler, "-c", file, 0}; |
| |
| expected_out(file); |
| create_source(file); |
| |
| pid_t child; |
| if (0 != posix_spawnp(&child, "cc", 0, 0, argv, get_environ())) { |
| perror("posix_spawnp"); |
| exit(EXIT_FAILURE); |
| } |
| wait_for(child); |
| } |
| #endif |
| |
| int main(int argc, char *const argv[]) { |
| if (argc != 2) |
| exit(EXIT_FAILURE); |
| |
| expected_out_open(argv[1]); |
| #ifdef HAVE_EXECV |
| call_execv(); |
| #endif |
| #ifdef HAVE_EXECVE |
| call_execve(); |
| #endif |
| #ifdef HAVE_EXECVP |
| call_execvp(); |
| #endif |
| #ifdef HAVE_EXECVP2 |
| call_execvP(); |
| #endif |
| #ifdef HAVE_EXECVPE |
| call_execvpe(); |
| #endif |
| #ifdef HAVE_EXECT |
| call_exect(); |
| #endif |
| #ifdef HAVE_EXECL |
| call_execl(); |
| #endif |
| #ifdef HAVE_EXECLP |
| call_execlp(); |
| #endif |
| #ifdef HAVE_EXECLE |
| call_execle(); |
| #endif |
| #ifdef HAVE_POSIX_SPAWN |
| call_posix_spawn(); |
| #endif |
| #ifdef HAVE_POSIX_SPAWNP |
| call_posix_spawnp(); |
| #endif |
| expected_out_close(); |
| return 0; |
| } |