Be a bit more efficient when processing the active and inactive
[oota-llvm.git] / tools / llee / SysUtils.c
1 /*===- SystemUtils.h - Utilities to do low-level system stuff -------------===*\
2  *                                                                            
3  *                     The LLVM Compiler Infrastructure                       
4  *
5  * This file was developed by the LLVM research group and is distributed under
6  * the University of Illinois Open Source License. See LICENSE.TXT for details.
7  * 
8  *===----------------------------------------------------------------------===
9  *
10  * This file contains functions used to do a variety of low-level, often
11  * system-specific, tasks.
12  *
13 \*===----------------------------------------------------------------------===*/
14
15 #include "SysUtils.h"
16 #include "Config/dlfcn.h"
17 #include "Config/fcntl.h"
18 #include "Config/unistd.h"
19 #include "Config/sys/stat.h"
20 #include "Config/sys/types.h"
21 #include "Config/sys/wait.h"
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 /*
28  * isExecutable - This function returns true if given struct stat describes the
29  * file as being executable.
30  */ 
31 unsigned isExecutable(const struct stat *buf) {
32   if (!(buf->st_mode & S_IFREG))
33     return 0;                         // Not a regular file?
34
35   if (buf->st_uid == getuid())        // Owner of file?
36     return buf->st_mode & S_IXUSR;
37   else if (buf->st_gid == getgid())   // In group of file?
38     return buf->st_mode & S_IXGRP;
39   else                                // Unrelated to file?
40     return buf->st_mode & S_IXOTH;
41 }
42
43 /*
44  * isExecutableFile - This function returns true if the filename specified
45  * exists and is executable.
46  */
47 unsigned isExecutableFile(const char *ExeFileName) {
48   struct stat buf;
49   if (stat(ExeFileName, &buf))
50     return 0;                        // Must not be executable!
51
52   return isExecutable(&buf);
53 }
54
55
56 /*
57  * FindExecutable - Find a named executable in the directories listed in $PATH.
58  * If the executable cannot be found, returns NULL.
59  */ 
60 char *FindExecutable(const char *ExeName) {
61   /* Try to find the executable in the path */
62   const char *PathStr = getenv("PATH");
63   if (PathStr == 0) return 0;
64
65   /* Now we have a colon separated list of directories to search, try them. */
66   unsigned PathLen = strlen(PathStr);
67   while (PathLen) {
68     /* Find the next colon */
69     const char *Colon = strchr(PathStr, ':');
70     
71     /* Check to see if this first directory contains the executable... */
72     unsigned DirLen = Colon ? (unsigned)(Colon-PathStr) : strlen(PathStr);
73     char *FilePath = alloca(sizeof(char) * (DirLen+1+strlen(ExeName)+1));
74     unsigned i, e;
75     for (i = 0; i != DirLen; ++i)
76       FilePath[i] = PathStr[i];
77     FilePath[i] = '/';
78     for (i = 0, e = strlen(ExeName); i != e; ++i)
79       FilePath[DirLen + 1 + i] = ExeName[i];
80     FilePath[DirLen + 1 + i] = '\0';
81     if (isExecutableFile(FilePath))
82       return strdup(FilePath); /* Found the executable! */
83
84     /* If Colon is NULL, there are no more colon separators and no more dirs */
85     if (!Colon) break;
86
87     /* Nope, it wasn't in this directory, check the next range! */
88     PathLen -= DirLen;
89     PathStr = Colon;
90     while (*PathStr == ':') {   /* Advance past colons */
91       PathStr++;
92       PathLen--;
93     }
94
95     /* Advance past the colon */
96     ++Colon;
97   }
98
99   /* If we fell out, we ran out of directories to search, return failure. */
100   return NULL;
101 }
102
103 /*
104  * The type of the execve() function is long and boring, but required.
105  */
106 typedef int(*execveTy)(const char*, char *const[], char *const[]);
107
108 /*
109  * This method finds the real `execve' call in the C library and executes the
110  * given program.
111  */
112 int executeProgram(const char *filename, char *const argv[], char *const envp[])
113 {
114   /*
115    * Find a pointer to the *real* execve() function starting the search in the
116    * next library and forward, to avoid finding the one defined in this file.
117    */
118   char *error;
119   execveTy execvePtr = (execveTy) dlsym(RTLD_NEXT, "execve");
120   if ((error = dlerror()) != NULL) {
121     fprintf(stderr, "%s\n", error);
122     return -1;
123   }
124
125   /* Really execute the program */
126   return execvePtr(filename, argv, envp);
127 }