forked from p4lang/p4c
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexename.cpp
69 lines (58 loc) · 2.44 KB
/
exename.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
Copyright 2020-present Barefoot Networks, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "exename.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "exceptions.h"
template <size_t N>
static void convertToAbsPath(const char *const relPath, char (&output)[N]) {
output[0] = '\0'; // Default to the empty string, indicating failure.
char cwd[PATH_MAX];
if (!getcwd(cwd, sizeof(cwd))) return;
const size_t cwdLen = strlen(cwd);
if (cwdLen == 0) return;
const char *separator = cwd[cwdLen - 1] == '/' ? "" : "/";
// Construct an absolute path. We're assuming that @relPath is relative to
// the current working directory.
int n = snprintf(output, N, "%s%s%s", cwd, separator, relPath);
BUG_CHECK(n >= 0, "Pathname too long");
}
const char *exename(const char *argv0) {
// Leave 1 extra char for the \0
static char buffer[PATH_MAX + 1];
if (buffer[0]) return buffer; // done already
int len;
/* find the path of the executable. We use a number of techniques that may fail
* or work on different systems, and take the first working one we find. Fall
* back to not overriding the compiled-in installation path */
if ((len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1)) > 0 ||
(len = readlink("/proc/curproc/exe", buffer, sizeof(buffer) - 1)) > 0 ||
(len = readlink("/proc/curproc/file", buffer, sizeof(buffer) - 1)) > 0 ||
(len = readlink("/proc/self/path/a.out", buffer, sizeof(buffer) - 1)) > 0) {
buffer[len] = 0;
} else if (argv0 && argv0[0] == '/') {
snprintf(buffer, sizeof(buffer), "%s", argv0);
} else if (argv0 && strchr(argv0, '/')) {
convertToAbsPath(argv0, buffer);
} else if (getenv("_")) {
strncpy(buffer, getenv("_"), sizeof(buffer));
buffer[sizeof(buffer) - 1] = 0;
} else {
buffer[0] = 0;
}
return buffer;
}