|  | /* | 
|  | .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; | 
|  | } |