Skip to content

Commit 59410fe

Browse files
committed
[CF] Unify implementations of _CFProcessPath.
Firstly, _CFProcessPath has no implementation for TARGET_OS_BSD. Indeed, there is no portable implementation of this action across multiple platforms. As an initial implementation for TARGET_OS_BSD, use the environment to help us. Some shells set the environment variable "_" to the path used to invoke the binary. This mirrors the implementation for TARGET_OS_OSX, so add the same conditionals on __CFProcessIsRestricted. Relying on the shell has drawbacks, including that the shell doesn't set the full path to the current executable if it isn't part of the PATH (or, of course, specified explicitly). Perhaps on some other platforms there is some miscellaneous kernel trickery that could be done, but let's defer that to the future and keep getenv("_") as a last resort. Second, given that, we should bring the implementations together (like we've done elsewhere), not to mention that _CFProcessPath is fundamental to other parts of CF. This highlights the repetition in each implementation, so here we also factor off some of it and share it across the implementations to facilitate code reuse.
1 parent 9d31226 commit 59410fe

File tree

1 file changed

+44
-40
lines changed

1 file changed

+44
-40
lines changed

CoreFoundation/Base.subproj/CFPlatform.c

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -113,44 +113,36 @@ const char **_CFGetProcessPath(void) {
113113
return &__CFProcessPath;
114114
}
115115

116-
#if TARGET_OS_WIN32
116+
static inline void _CFSetProgramNameFromPath(const char *path) {
117+
__CFProcessPath = strdup(path);
118+
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
119+
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
120+
}
121+
117122
const char *_CFProcessPath(void) {
118123
if (__CFProcessPath) return __CFProcessPath;
124+
125+
#if TARGET_OS_WIN32
119126
wchar_t buf[CFMaxPathSize] = {0};
120127
DWORD rlen = GetModuleFileNameW(NULL, buf, sizeof(buf) / sizeof(buf[0]));
121128
if (0 < rlen) {
122129
char asciiBuf[CFMaxPathSize] = {0};
123130
int res = WideCharToMultiByte(CP_UTF8, 0, buf, rlen, asciiBuf, sizeof(asciiBuf) / sizeof(asciiBuf[0]), NULL, NULL);
124131
if (0 < res) {
125-
__CFProcessPath = strdup(asciiBuf);
126-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
127-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
132+
_CFSetProgramNameFromPath(asciiBuf);
128133
}
129134
}
130135
if (!__CFProcessPath) {
131136
__CFProcessPath = "";
132137
__CFprogname = __CFProcessPath;
133138
}
134139
return __CFProcessPath;
135-
}
136-
#endif
137-
138-
#if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_BSD
139-
CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void) {
140-
return pthread_main_np() == 1;
141-
}
142-
#endif
143-
144-
#if TARGET_OS_MAC
145-
const char *_CFProcessPath(void) {
146-
if (__CFProcessPath) return __CFProcessPath;
140+
#elif TARGET_OS_MAC
147141
#if TARGET_OS_OSX
148142
if (!__CFProcessIsRestricted()) {
149143
const char *path = (char *)__CFgetenv("CFProcessPath");
150144
if (path) {
151-
__CFProcessPath = strdup(path);
152-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
153-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
145+
_CFSetProgramNameFromPath(path);
154146
return __CFProcessPath;
155147
}
156148
}
@@ -160,9 +152,7 @@ const char *_CFProcessPath(void) {
160152
uint32_t size = CFMaxPathSize;
161153
char buffer[size];
162154
if (0 == _NSGetExecutablePath(buffer, &size)) {
163-
__CFProcessPath = strdup(buffer);
164-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
165-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
155+
_CFSetProgramNameFromPath(buffer);
166156
}
167157
}
168158

@@ -171,6 +161,38 @@ const char *_CFProcessPath(void) {
171161
__CFprogname = __CFProcessPath;
172162
}
173163
return __CFProcessPath;
164+
#elif TARGET_OS_LINUX
165+
char buf[CFMaxPathSize + 1];
166+
167+
ssize_t res = readlink("/proc/self/exe", buf, CFMaxPathSize);
168+
if (res > 0) {
169+
// null terminate, readlink does not
170+
buf[res] = 0;
171+
_CFSetProgramNameFromPath(buf);
172+
} else {
173+
__CFProcessPath = "";
174+
__CFprogname = __CFProcessPath;
175+
}
176+
return __CFProcessPath;
177+
#else // TARGET_OS_BSD
178+
if (!__CFProcessIsRestricted()) {
179+
char *path = getenv("_");
180+
if (path != NULL) {
181+
_CFSetProgramNameFromPath(path);
182+
return __CFProcessPath;
183+
}
184+
}
185+
186+
// We don't yet have anything left to try.
187+
__CFProcessPath = "";
188+
__CFprogname = __CFProcessPath;
189+
return __CFProcessPath;
190+
#endif
191+
}
192+
193+
#if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_BSD
194+
CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void) {
195+
return pthread_main_np() == 1;
174196
}
175197
#endif
176198

@@ -185,24 +207,6 @@ const char *_CFProcessPath(void) {
185207
Boolean _CFIsMainThread(void) {
186208
return syscall(SYS_gettid) == getpid();
187209
}
188-
189-
const char *_CFProcessPath(void) {
190-
if (__CFProcessPath) return __CFProcessPath;
191-
char buf[CFMaxPathSize + 1];
192-
193-
ssize_t res = readlink("/proc/self/exe", buf, CFMaxPathSize);
194-
if (res > 0) {
195-
// null terminate, readlink does not
196-
buf[res] = 0;
197-
__CFProcessPath = strdup(buf);
198-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
199-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
200-
} else {
201-
__CFProcessPath = "";
202-
__CFprogname = __CFProcessPath;
203-
}
204-
return __CFProcessPath;
205-
}
206210
#endif
207211

208212
CF_PRIVATE CFStringRef _CFProcessNameString(void) {

0 commit comments

Comments
 (0)