blob: 90d6bb129011f7c3006c57fb6402b8efe4846a13 [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
Misha Brukman593ece02003-08-15 23:31:16 +000018/*
19 * isExecutableFile - This function returns true if the filename specified
20 * exists and is executable.
21 */
22unsigned isExecutableFile(const char *ExeFileName) {
Misha Brukman0abaaf42003-08-11 22:29:36 +000023 struct stat Buf;
24 if (stat(ExeFileName, &Buf))
Misha Brukman593ece02003-08-15 23:31:16 +000025 return 0; // Must not be executable!
Misha Brukman0abaaf42003-08-11 22:29:36 +000026
27 if (!(Buf.st_mode & S_IFREG))
Misha Brukman593ece02003-08-15 23:31:16 +000028 return 0; // Not a regular file?
Misha Brukman0abaaf42003-08-11 22:29:36 +000029
30 if (Buf.st_uid == getuid()) // Owner of file?
31 return Buf.st_mode & S_IXUSR;
32 else if (Buf.st_gid == getgid()) // In group of file?
33 return Buf.st_mode & S_IXGRP;
34 else // Unrelated to file?
35 return Buf.st_mode & S_IXOTH;
36}
37
Misha Brukman593ece02003-08-15 23:31:16 +000038/*
39 * FindExecutable - Find a named executable in the directories listed in $PATH.
40 * If the executable cannot be found, returns NULL.
41 */
Misha Brukman0abaaf42003-08-11 22:29:36 +000042char *FindExecutable(const char *ExeName) {
43 /* Try to find the executable in the path */
44 const char *PathStr = getenv("PATH");
45 if (PathStr == 0) return "";
46
Misha Brukman593ece02003-08-15 23:31:16 +000047 /* Now we have a colon separated list of directories to search, try them. */
Misha Brukman0abaaf42003-08-11 22:29:36 +000048 unsigned PathLen = strlen(PathStr);
49 while (PathLen) {
50 /* Find the next colon */
51 const char *Colon = strchr(PathStr, ':');
52
53 /* Check to see if this first directory contains the executable... */
54 unsigned DirLen = Colon ? (Colon-PathStr) : strlen(PathStr);
55 char *FilePath = alloca(sizeof(char) * (DirLen+1+strlen(ExeName)+1));
56 unsigned i, e;
57 for (i = 0; i != DirLen; ++i)
58 FilePath[i] = PathStr[i];
59 FilePath[i] = '/';
60 for (i = 0, e = strlen(ExeName); i != e; ++i)
61 FilePath[DirLen + 1 + i] = ExeName[i];
62 FilePath[DirLen + 1 + i] = '\0';
63 if (isExecutableFile(FilePath))
64 return strdup(FilePath); /* Found the executable! */
65
66 /* If Colon is NULL, there are no more colon separators and no more dirs */
67 if (!Colon) break;
68
69 /* Nope, it wasn't in this directory, check the next range! */
70 PathLen -= DirLen;
71 PathStr = Colon;
72 while (*PathStr == ':') { /* Advance past colons */
73 PathStr++;
74 PathLen--;
75 }
76
77 /* Advance past the colon */
78 ++Colon;
79 }
80
Misha Brukman593ece02003-08-15 23:31:16 +000081 /* If we fell out, we ran out of directories to search, return failure. */
Misha Brukman0abaaf42003-08-11 22:29:36 +000082 return NULL;
83}