forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			308 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			308 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
| /* -*- 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;
 | |
| }
 |