@@ -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+
139143const 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