Skip to content

Commit 0502fb4

Browse files
3405691582dana
authored andcommitted
[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 2389ca0 commit 0502fb4

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
@@ -109,60 +109,82 @@ const char **_CFGetProcessPath(void) {
109109
return &__CFProcessPath;
110110
}
111111

112-
#if TARGET_OS_WIN32
112+
static inline void _CFSetProgramNameFromPath(const char *path) {
113+
__CFProcessPath = strdup(path);
114+
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
115+
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
116+
}
117+
113118
const char *_CFProcessPath(void) {
114119
if (__CFProcessPath) return __CFProcessPath;
120+
121+
#if TARGET_OS_WIN32
115122
wchar_t buf[CFMaxPathSize] = {0};
116123
DWORD rlen = GetModuleFileNameW(NULL, buf, sizeof(buf) / sizeof(buf[0]));
117124
if (0 < rlen) {
118125
char asciiBuf[CFMaxPathSize] = {0};
119126
int res = WideCharToMultiByte(CP_UTF8, 0, buf, rlen, asciiBuf, sizeof(asciiBuf) / sizeof(asciiBuf[0]), NULL, NULL);
120127
if (0 < res) {
121-
__CFProcessPath = strdup(asciiBuf);
122-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
123-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
128+
_CFSetProgramNameFromPath(asciiBuf);
124129
}
125130
}
126131
if (!__CFProcessPath) {
127132
__CFProcessPath = "";
128133
__CFprogname = __CFProcessPath;
129134
}
130135
return __CFProcessPath;
131-
}
132-
#endif
133-
134-
#if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_BSD
135-
CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void) {
136-
return pthread_main_np() == 1;
137-
}
138-
#endif
139-
140-
#if TARGET_OS_MAC
141-
const char *_CFProcessPath(void) {
142-
if (__CFProcessPath) return __CFProcessPath;
136+
#elif TARGET_OS_MAC
143137
#if TARGET_OS_OSX
144138
if (!__CFProcessIsRestricted()) {
145139
const char *path = (char *)__CFgetenv("CFProcessPath");
146140
if (path) {
147-
__CFProcessPath = strdup(path);
148-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
149-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
141+
_CFSetProgramNameFromPath(path);
150142
return __CFProcessPath;
151143
}
152144
}
153145
#endif
154146
uint32_t size = CFMaxPathSize;
155147
char buffer[size];
156148
if (0 == _NSGetExecutablePath(buffer, &size)) {
157-
__CFProcessPath = strdup(buffer);
158-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
159-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
149+
_CFSetProgramNameFromPath(buffer);
160150
}
161151
if (!__CFProcessPath) {
162152
__CFProcessPath = "";
163153
__CFprogname = __CFProcessPath;
164154
}
165155
return __CFProcessPath;
156+
#elif TARGET_OS_LINUX
157+
char buf[CFMaxPathSize + 1];
158+
159+
ssize_t res = readlink("/proc/self/exe", buf, CFMaxPathSize);
160+
if (res > 0) {
161+
// null terminate, readlink does not
162+
buf[res] = 0;
163+
_CFSetProgramNameFromPath(buf);
164+
} else {
165+
__CFProcessPath = "";
166+
__CFprogname = __CFProcessPath;
167+
}
168+
return __CFProcessPath;
169+
#else // TARGET_OS_BSD
170+
if (!__CFProcessIsRestricted()) {
171+
char *path = getenv("_");
172+
if (path != NULL) {
173+
_CFSetProgramNameFromPath(path);
174+
return __CFProcessPath;
175+
}
176+
}
177+
178+
// We don't yet have anything left to try.
179+
__CFProcessPath = "";
180+
__CFprogname = __CFProcessPath;
181+
return __CFProcessPath;
182+
#endif
183+
}
184+
185+
#if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_BSD
186+
CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void) {
187+
return pthread_main_np() == 1;
166188
}
167189
#endif
168190

@@ -177,24 +199,6 @@ const char *_CFProcessPath(void) {
177199
Boolean _CFIsMainThread(void) {
178200
return syscall(SYS_gettid) == getpid();
179201
}
180-
181-
const char *_CFProcessPath(void) {
182-
if (__CFProcessPath) return __CFProcessPath;
183-
char buf[CFMaxPathSize + 1];
184-
185-
ssize_t res = readlink("/proc/self/exe", buf, CFMaxPathSize);
186-
if (res > 0) {
187-
// null terminate, readlink does not
188-
buf[res] = 0;
189-
__CFProcessPath = strdup(buf);
190-
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
191-
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
192-
} else {
193-
__CFProcessPath = "";
194-
__CFprogname = __CFProcessPath;
195-
}
196-
return __CFProcessPath;
197-
}
198202
#endif
199203

200204
CF_PRIVATE CFStringRef _CFProcessNameString(void) {

0 commit comments

Comments
 (0)