Skip to content

Commit 52d1b7e

Browse files
committed
Try filling CFProcessPath with argv[0] on OpenBSD.
There is no native mechanism to get the running process path on OpenBSD. Currently, the shell needs to cooperate and fill in the path. This works, but not all shells set the `_` environment variable. We however are able to get `argv[0]` via sysctl on this platform. Instead of just trying `_` and then giving up otherwise, first try getting `argv[0]`. If that appears to be an absolute path, then we can likely assume that this is what we need; otherwise, search PATH. On other BSD platforms, this sysctl may need to be modified or an alternative mechanism supplied to get `argv[0]`, so we still fallback on `getenv("_")`.
1 parent 5d90405 commit 52d1b7e

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

CoreFoundation/Base.subproj/CFPlatform.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ static inline void _CFSetProgramNameFromPath(const char *path) {
119119
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
120120
}
121121

122+
#if TARGET_OS_BSD && defined(__OpenBSD__)
123+
#include <sys/types.h>
124+
#include <sys/sysctl.h>
125+
#include <sys/exec.h>
126+
#endif
127+
122128
const char *_CFProcessPath(void) {
123129
if (__CFProcessPath) return __CFProcessPath;
124130

@@ -175,6 +181,50 @@ const char *_CFProcessPath(void) {
175181
}
176182
return __CFProcessPath;
177183
#else // TARGET_OS_BSD
184+
char *argv0 = NULL;
185+
186+
// Get argv[0].
187+
#if defined(__OpenBSD__)
188+
int mib[2] = {CTL_VM, VM_PSSTRINGS};
189+
struct _ps_strings _ps;
190+
size_t len = sizeof(_ps);
191+
192+
if (sysctl(mib, 2, &_ps, &len, NULL, 0) != -1) {
193+
struct ps_strings *ps = _ps.val;
194+
char *res = realpath(ps->ps_argvstr[0], NULL);
195+
argv0 = res? res: strdup(ps->ps_argvstr[0]);
196+
}
197+
#endif
198+
199+
if (!__CFProcessIsRestricted() && argv0 && argv0[0] == '/') {
200+
_CFSetProgramNameFromPath(argv0);
201+
free(argv0);
202+
return __CFProcessPath;
203+
}
204+
205+
// Search PATH.
206+
if (argv0) {
207+
char *paths = getenv("PATH");
208+
char *p = NULL;
209+
while ((p = strsep(&paths, ":")) != NULL) {
210+
char pp[PATH_MAX];
211+
snprintf(pp, PATH_MAX, "%s/%s", p, argv0);
212+
char *res = realpath(pp, NULL);
213+
if (!res) {
214+
continue;
215+
}
216+
if (!__CFProcessIsRestricted() && access(res, X_OK) == 0) {
217+
_CFSetProgramNameFromPath(res);
218+
free(argv0);
219+
free(res);
220+
return __CFProcessPath;
221+
}
222+
free(res);
223+
}
224+
free(argv0);
225+
}
226+
227+
// See if the shell will help.
178228
if (!__CFProcessIsRestricted()) {
179229
char *path = getenv("_");
180230
if (path != NULL) {

0 commit comments

Comments
 (0)