| 295 | } |
| 296 | |
| 297 | string Env::GetExecutablePath() { |
| 298 | char exe_path[PATH_MAX] = {0}; |
| 299 | #ifdef __APPLE__ |
| 300 | uint32_t buffer_size(0U); |
| 301 | _NSGetExecutablePath(nullptr, &buffer_size); |
| 302 | char unresolved_path[buffer_size]; |
| 303 | _NSGetExecutablePath(unresolved_path, &buffer_size); |
| 304 | CHECK(realpath(unresolved_path, exe_path)); |
| 305 | #elif defined(__FreeBSD__) |
| 306 | int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; |
| 307 | size_t exe_path_size = PATH_MAX; |
| 308 | |
| 309 | if (sysctl(mib, 4, exe_path, &exe_path_size, NULL, 0) != 0) { |
| 310 | // Resolution of path failed |
| 311 | return ""; |
| 312 | } |
| 313 | #elif defined(PLATFORM_WINDOWS) |
| 314 | HMODULE hModule = GetModuleHandleW(NULL); |
| 315 | WCHAR wc_file_path[MAX_PATH] = {0}; |
| 316 | GetModuleFileNameW(hModule, wc_file_path, MAX_PATH); |
| 317 | string file_path = WideCharToUtf8(wc_file_path); |
| 318 | std::copy(file_path.begin(), file_path.end(), exe_path); |
| 319 | #else |
| 320 | char buf[PATH_MAX] = {0}; |
| 321 | int path_length = readlink("/proc/self/exe", buf, sizeof(buf) - 1); |
| 322 | CHECK_NE(-1, path_length); |
| 323 | |
| 324 | if (strstr(buf, "python") != nullptr) { |
| 325 | // Discard the path of the python binary, and any flags. |
| 326 | int fd = open("/proc/self/cmdline", O_RDONLY); |
| 327 | int cmd_length = read(fd, buf, PATH_MAX - 1); |
| 328 | CHECK_NE(-1, cmd_length); |
| 329 | int token_pos = 0; |
| 330 | for (bool token_is_first_or_flag = true; token_is_first_or_flag;) { |
| 331 | // Get token length, including null |
| 332 | int token_len = strlen(&buf[token_pos]) + 1; |
| 333 | token_is_first_or_flag = false; |
| 334 | // Check if we can skip without overshooting |
| 335 | if (token_pos + token_len < cmd_length) { |
| 336 | token_pos += token_len; |
| 337 | token_is_first_or_flag = (buf[token_pos] == '-'); // token is a flag |
| 338 | } |
| 339 | } |
| 340 | snprintf(exe_path, sizeof(exe_path), "%s", &buf[token_pos]); |
| 341 | } else { |
| 342 | snprintf(exe_path, sizeof(exe_path), "%s", buf); |
| 343 | } |
| 344 | |
| 345 | #endif |
| 346 | // Make sure it's null-terminated: |
| 347 | exe_path[sizeof(exe_path) - 1] = 0; |
| 348 | |
| 349 | return exe_path; |
| 350 | } |
| 351 | |
| 352 | bool Env::LocalTempFilename(string* filename) { |
| 353 | std::vector<string> dirs; |