Removed the pthread_once() function because it doesn't actually do
[oota-llvm.git] / tools / llee / ExecveHandler.c
1 //===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===//
2 //
3 // This file implements a replacement execve() to spawn off LLVM programs to run
4 // transparently, without needing to be (JIT-)compiled manually by the user.
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "SysUtils.h"
9 #include "Config/errno.h"
10 #include "Config/stdlib.h"
11 #include "Config/unistd.h"
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 /*
17  * This is the expected header for all valid LLVM bytecode files.
18  * The first four characters must be exactly this.
19  */
20 static const char llvmHeader[] = "llvm";
21
22 /*
23  * This replacement execve() function first checks the file to be executed
24  * to see if it is a valid LLVM bytecode file, and then either invokes our
25  * execution environment or passes it on to the system execve() call.
26  */
27 int execve(const char *filename, char *const argv[], char *const envp[])
28 {
29   /* Open the file, test to see if first four characters are "llvm" */
30   size_t headerSize = strlen(llvmHeader);
31   char header[headerSize];
32   char* realFilename = 0;
33   /* 
34    * If the program is specified with a relative or absolute path, 
35    * then just use the path and filename as is, otherwise search for it.
36    */
37   if (filename[0] != '.' && filename[0] != '/')
38     realFilename = FindExecutable(filename);
39   else
40     realFilename = (char*) filename;
41   if (!realFilename) {
42     fprintf(stderr, "Cannot find path to `%s', exiting.\n", filename);
43     return -1;
44   }
45   errno = 0;
46   int file = open(realFilename, O_RDONLY);
47   /* Check validity of `file' */
48   if (errno) return EIO;
49   /* Read the header from the file */
50   ssize_t bytesRead = read(file, header, headerSize);
51   close(file);
52   if (bytesRead != (ssize_t)headerSize) return EIO;
53   if (!memcmp(llvmHeader, header, headerSize)) {
54     /* 
55      * This is a bytecode file, so execute the JIT with the program and
56      * parameters.
57      */
58     unsigned argvSize, idx;
59     for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
60       ++argvSize;
61     char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
62     char *LLIpath = FindExecutable("lli");
63     if (!LLIpath) {
64       fprintf(stderr, "Cannot find path to `lli', exiting.\n");
65       return -1;
66     }
67     LLIargs[0] = LLIpath;
68     LLIargs[1] = realFilename;
69     for (idx = 1; idx != argvSize; ++idx)
70       LLIargs[idx+1] = argv[idx];
71     LLIargs[argvSize + 1] = '\0';
72     return executeProgram(LLIpath, LLIargs, envp);
73   }
74   return executeProgram(filename, argv, envp); 
75 }