Skip to content

Commit c23cc23

Browse files
authored
Merge pull request #5189 from michael-yuji/freebsd-execpath
[FreeBSD] lookup process path via sysctl
2 parents af2ecd8 + 4ff6839 commit c23cc23

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

Sources/CoreFoundation/CFPlatform.c

+30
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ static inline void _CFSetProgramNameFromPath(const char *path) {
136136
#include <sys/exec.h>
137137
#endif
138138

139+
#if TARGET_OS_BSD && defined(__FreeBSD__)
140+
#include <sys/sysctl.h>
141+
#endif
142+
139143
const char *_CFProcessPath(void) {
140144
if (__CFProcessPath) return __CFProcessPath;
141145

@@ -230,6 +234,29 @@ const char *_CFProcessPath(void) {
230234
char *res = realpath(ps->ps_argvstr[0], NULL);
231235
argv0 = res? res: strdup(ps->ps_argvstr[0]);
232236
}
237+
#elif defined(__FreeBSD__)
238+
// see sysctl(3), pid == -1 means current process
239+
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
240+
int sysctl_ret = 0;
241+
size_t len = PATH_MAX + 1;
242+
argv0 = calloc(len, 1);
243+
244+
sysctl_ret = sysctl(mib, 4, argv0, &len, NULL, 0);
245+
246+
// in case for whatever reason the path is > PATH_MAX
247+
if (sysctl_ret == -1 && errno == ENOMEM) {
248+
// get size needed
249+
sysctl_ret = sysctl(mib, 4, NULL, &len, NULL, 0);
250+
if (sysctl_ret != -1) {
251+
argv0 = realloc(argv0, len);
252+
sysctl_ret = sysctl(mib, 4, argv0, &len, NULL, 0);
253+
}
254+
}
255+
256+
if (sysctl_ret == -1) {
257+
free(argv0);
258+
argv0 = NULL;
259+
}
233260
#endif
234261

235262
if (!__CFProcessIsRestricted() && argv0 && argv0[0] == '/') {
@@ -908,6 +935,9 @@ static void __CFTSDFinalize(void *arg) {
908935

909936
if (!arg || arg == CF_TSD_BAD_PTR) {
910937
// We've already been destroyed. The call above set the bad pointer again. Now we just return.
938+
#if defined(__FreeBSD__)
939+
__CFTSDSetSpecific(NULL);
940+
#endif
911941
return;
912942
}
913943

0 commit comments

Comments
 (0)