diff --git a/Sources/CoreFoundation/CFPlatform.c b/Sources/CoreFoundation/CFPlatform.c index 186a6e8970..776dc4c8eb 100644 --- a/Sources/CoreFoundation/CFPlatform.c +++ b/Sources/CoreFoundation/CFPlatform.c @@ -136,6 +136,10 @@ static inline void _CFSetProgramNameFromPath(const char *path) { #include #endif +#if TARGET_OS_BSD && defined(__FreeBSD__) +#include +#endif + const char *_CFProcessPath(void) { if (__CFProcessPath) return __CFProcessPath; @@ -230,6 +234,29 @@ const char *_CFProcessPath(void) { char *res = realpath(ps->ps_argvstr[0], NULL); argv0 = res? res: strdup(ps->ps_argvstr[0]); } +#elif defined(__FreeBSD__) + // see sysctl(3), pid == -1 means current process + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + int sysctl_ret = 0; + size_t len = PATH_MAX + 1; + argv0 = calloc(len, 1); + + sysctl_ret = sysctl(mib, 4, argv0, &len, NULL, 0); + + // in case for whatever reason the path is > PATH_MAX + if (sysctl_ret == -1 && errno == ENOMEM) { + // get size needed + sysctl_ret = sysctl(mib, 4, NULL, &len, NULL, 0); + if (sysctl_ret != -1) { + argv0 = realloc(argv0, len); + sysctl_ret = sysctl(mib, 4, argv0, &len, NULL, 0); + } + } + + if (sysctl_ret == -1) { + free(argv0); + argv0 = NULL; + } #endif if (!__CFProcessIsRestricted() && argv0 && argv0[0] == '/') { @@ -908,6 +935,9 @@ static void __CFTSDFinalize(void *arg) { if (!arg || arg == CF_TSD_BAD_PTR) { // We've already been destroyed. The call above set the bad pointer again. Now we just return. +#if defined(__FreeBSD__) + __CFTSDSetSpecific(NULL); +#endif return; }