blob: 1c3aa85e5c60218d36c6353ed5bf330de66578d6 [file] [log] [blame]
Misha Brukman0abaaf42003-08-11 22:29:36 +00001//===- SystemUtils.h - Utilities to do low-level system stuff --*- C++ -*--===//
2//
3// This file contains functions used to do a variety of low-level, often
4// system-specific, tasks.
5//
6//===----------------------------------------------------------------------===//
7
8#include "SysUtils.h"
9#include "Config/sys/types.h"
10#include "Config/sys/stat.h"
11#include "Config/fcntl.h"
12#include "Config/sys/wait.h"
13#include "Config/unistd.h"
14#include "Config/errno.h"
15#include <stdlib.h>
16#include <string.h>
17
18/// isExecutableFile - This function returns true if the filename specified
19/// exists and is executable.
20///
21bool isExecutableFile(const char *ExeFileName) {
22 struct stat Buf;
23 if (stat(ExeFileName, &Buf))
24 return false; // Must not be executable!
25
26 if (!(Buf.st_mode & S_IFREG))
27 return false; // Not a regular file?
28
29 if (Buf.st_uid == getuid()) // Owner of file?
30 return Buf.st_mode & S_IXUSR;
31 else if (Buf.st_gid == getgid()) // In group of file?
32 return Buf.st_mode & S_IXGRP;
33 else // Unrelated to file?
34 return Buf.st_mode & S_IXOTH;
35}
36
37/// FindExecutable - Find a named executable in the directories listed in $PATH.
38/// If the executable cannot be found, returns NULL.
39///
40char *FindExecutable(const char *ExeName) {
41 /* Try to find the executable in the path */
42 const char *PathStr = getenv("PATH");
43 if (PathStr == 0) return "";
44
45 // Now we have a colon separated list of directories to search... try them...
46 unsigned PathLen = strlen(PathStr);
47 while (PathLen) {
48 /* Find the next colon */
49 const char *Colon = strchr(PathStr, ':');
50
51 /* Check to see if this first directory contains the executable... */
52 unsigned DirLen = Colon ? (Colon-PathStr) : strlen(PathStr);
53 char *FilePath = alloca(sizeof(char) * (DirLen+1+strlen(ExeName)+1));
54 unsigned i, e;
55 for (i = 0; i != DirLen; ++i)
56 FilePath[i] = PathStr[i];
57 FilePath[i] = '/';
58 for (i = 0, e = strlen(ExeName); i != e; ++i)
59 FilePath[DirLen + 1 + i] = ExeName[i];
60 FilePath[DirLen + 1 + i] = '\0';
61 if (isExecutableFile(FilePath))
62 return strdup(FilePath); /* Found the executable! */
63
64 /* If Colon is NULL, there are no more colon separators and no more dirs */
65 if (!Colon) break;
66
67 /* Nope, it wasn't in this directory, check the next range! */
68 PathLen -= DirLen;
69 PathStr = Colon;
70 while (*PathStr == ':') { /* Advance past colons */
71 PathStr++;
72 PathLen--;
73 }
74
75 /* Advance past the colon */
76 ++Colon;
77 }
78
79 // If we fell out, we ran out of directories in PATH to search, return failure
80 return NULL;
81}