| /* |
| .Some useful path tools. |
| .ASCII only for now. |
| .Written by Ray Donnelly in 2014. |
| .Licensed under CC0 (and anything. |
| .else you need to license it under). |
| .No warranties whatsoever. |
| .email: <mingw.android@gmail.com>. |
| */ |
| |
| #include <stdlib.h> |
| #include <limits.h> |
| #include <stdio.h> |
| #include <string.h> |
| #if defined(__linux__) || defined(__CYGWIN__) || defined(__MSYS__) |
| #include <alloca.h> |
| #endif |
| #include <unistd.h> |
| |
| /* If you don't define this, then get_executable_path() |
| can only use argv[0] which will often not work well */ |
| #define IMPLEMENT_SYS_GET_EXECUTABLE_PATH |
| |
| #if defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) |
| #if defined(__linux__) || defined(__CYGWIN__) || defined(__MSYS__) |
| /* Nothing needed, unistd.h is enough. */ |
| #elif defined(__APPLE__) |
| #include <mach-o/dyld.h> |
| #elif defined(_WIN32) |
| // widl can't include the normal Windows headers due to providing its own winnt.h (and others). |
| #ifdef __x86_64__ |
| __attribute__((dllimport)) long GetModuleFileNameA (long hModule, void* lpFilename, long nSize); |
| #else |
| __attribute__((dllimport)) long __attribute__((__stdcall__)) GetModuleFileNameA (long hModule, void* lpFilename, long nSize); |
| #endif |
| #endif |
| #else |
| #define PATH_MAX 260 |
| #endif /* defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) */ |
| |
| #include "pathtools.h" |
| |
| int |
| get_executable_path(char const * argv0, char * result, ssize_t max_size) |
| { |
| char * system_result = (char *) alloca (max_size); |
| ssize_t system_result_size = -1; |
| ssize_t result_size = -1; |
| |
| if (system_result != NULL) |
| { |
| #if defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) |
| #if defined(__linux__) || defined(__CYGWIN__) || defined(__MSYS__) |
| system_result_size = readlink("/proc/self/exe", system_result, max_size); |
| #elif defined(__APPLE__) |
| uint32_t bufsize = (uint32_t)max_size; |
| if (_NSGetExecutablePath(system_result, &bufsize) == 0) |
| { |
| system_result_size = strlen (system_result); |
| } |
| #elif defined(_WIN32) |
| unsigned long bufsize = (unsigned long)max_size; |
| system_result_size = GetModuleFileNameA(0, system_result, bufsize); |
| if (system_result_size == 0 || system_result_size == (ssize_t)bufsize) |
| { |
| /* Error, possibly not enough space. */ |
| system_result_size = -1; |
| } |
| else |
| { |
| /* Early conversion to unix slashes instead of more changes |
| everywhere else .. */ |
| char * winslash; |
| system_result[system_result_size] = '\0'; |
| while ((winslash = strchr (system_result, '\\')) != NULL) |
| { |
| *winslash = '/'; |
| } |
| } |
| #else |
| #warning "Don't know how to get executable path on this system" |
| #endif |
| #endif /* defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) */ |
| } |
| /* Use argv0 as a default in-case of failure */ |
| if (system_result_size != -1) |
| { |
| strncpy (result, system_result, system_result_size); |
| result[system_result_size] = '\0'; |
| } |
| else |
| { |
| if (argv0 != NULL) |
| { |
| strncpy (result, argv0, max_size); |
| char *slash; |
| while ((slash = strchr(result, '\\')) != NULL) { |
| *slash++ = '/'; |
| } |
| result[max_size-1] = '\0'; |
| } |
| else |
| { |
| result[0] = '\0'; |
| } |
| } |
| result_size = strlen (result); |
| return result_size; |
| } |