diff --git a/pkg/urbit/daemon/whereami.c b/pkg/urbit/daemon/whereami.c index 290005766..5e31a2490 100644 --- a/pkg/urbit/daemon/whereami.c +++ b/pkg/urbit/daemon/whereami.c @@ -1,4 +1,6 @@ -// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz) +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) // https://github.com/gpakosz/whereami // in case you want to #include "whereami.c" in a larger compilation unit @@ -10,6 +12,15 @@ extern "C" { #endif +#if defined(__linux__) || defined(__CYGWIN__) +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#elif defined(__APPLE__) +#undef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE +#define _DARWIN_BETTER_REALPATH +#endif + #if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) #include #endif @@ -46,7 +57,9 @@ extern "C" { #if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #if defined(_MSC_VER) #pragma warning(push, 3) #endif @@ -55,6 +68,7 @@ extern "C" { #if defined(_MSC_VER) #pragma warning(pop) #endif +#include static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) { @@ -62,8 +76,9 @@ static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, i wchar_t buffer2[MAX_PATH]; wchar_t* path = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { DWORD size; int length_, length__; @@ -119,14 +134,12 @@ static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, i } length = length__; - - break; } if (path != buffer1) WAI_FREE(path); - return length; + return ok ? length : -1; } WAI_NOINLINE WAI_FUNCSPEC @@ -156,7 +169,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) return length; } -#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE) #include #include @@ -170,6 +183,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #define __STDC_FORMAT_MACROS #endif #include +#include #if !defined(WAI_PROC_SELF_EXE) #if defined(__sun) @@ -185,8 +199,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char buffer[PATH_MAX]; char* resolved = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { resolved = realpath(WAI_PROC_SELF_EXE, buffer); if (!resolved) @@ -211,11 +226,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } - return length; + return ok ? length : -1; } #if !defined(WAI_PROC_SELF_MAPS_RETRY) @@ -235,6 +248,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) #include #include #endif +#include WAI_NOINLINE WAI_FUNCSPEC int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) @@ -281,15 +295,24 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) &&buffer[length - 4] == '.') { int fd = open(path, O_RDONLY); - char* begin; - char* p; + if (fd == -1) + { + length = -1; // retry + break; + } - begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); - p = begin + offset; + char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); + if (begin == MAP_FAILED) + { + close(fd); + length = -1; // retry + break; + } + char* p = begin + offset - 30; // minimum size of local file header while (p >= begin) // scan backwards { - if (*((uint32_t*)p) == 0x04034b50UL) // local file header found + if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found { uint16_t length_ = *((uint16_t*)(p + 26)); @@ -303,7 +326,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) break; } - p -= 4; + --p; } munmap(begin, offset); @@ -341,20 +364,17 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) break; } - if (maps) - fclose(maps); - return length; } #elif defined(__APPLE__) -#define _DARWIN_BETTER_REALPATH #include #include #include #include #include +#include WAI_FUNCSPEC int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) @@ -364,8 +384,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char* path = buffer1; char* resolved = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { uint32_t size = (uint32_t)sizeof(buffer1); if (_NSGetExecutablePath(path, &size) == -1) @@ -398,14 +419,12 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } if (path != buffer1) WAI_FREE(path); - return length; + return ok ? length : -1; } WAI_NOINLINE WAI_FUNCSPEC @@ -459,6 +478,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #include #include #include +#include #if !defined(WAI_PROC_SELF_EXE) #define WAI_PROC_SELF_EXE "/proc/self/exefile" @@ -472,8 +492,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char* resolved = NULL; FILE* self_exe = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { self_exe = fopen(WAI_PROC_SELF_EXE, "r"); if (!self_exe) @@ -505,13 +526,11 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } fclose(self_exe); - return length; + return ok ? length : -1; } WAI_FUNCSPEC @@ -559,7 +578,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) } #elif defined(__DragonFly__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__) + defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include @@ -567,6 +586,116 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #include #include #include +#include + +#if defined(__OpenBSD__) + +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[4096]; + char buffer2[PATH_MAX]; + char buffer3[PATH_MAX]; + char** argv = (char**)buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t size; + + if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0) + break; + + if (size > sizeof(buffer1)) + { + argv = (char**)WAI_MALLOC(size); + if (!argv) + break; + } + + if (sysctl(mib, 4, argv, &size, NULL, 0) != 0) + break; + + if (strchr(argv[0], '/')) + { + resolved = realpath(argv[0], buffer2); + if (!resolved) + break; + } + else + { + const char* PATH = getenv("PATH"); + if (!PATH) + break; + + size_t argv0_length = strlen(argv[0]); + + const char* begin = PATH; + while (1) + { + const char* separator = strchr(begin, ':'); + const char* end = separator ? separator : begin + strlen(begin); + + if (end - begin > 0) + { + if (*(end -1) == '/') + --end; + + if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2)) + { + memcpy(buffer2, begin, end - begin); + buffer2[end - begin] = '/'; + memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1); + + resolved = realpath(buffer2, buffer3); + if (resolved) + break; + } + } + + if (!separator) + break; + + begin = ++separator; + } + + if (!resolved) + break; + } + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (argv != (char**)buffer1) + WAI_FREE(argv); + + return ok ? length : -1; +} + +#else WAI_FUNCSPEC int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) @@ -576,13 +705,18 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char* path = buffer1; char* resolved = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { +#if defined(__NetBSD__) + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; +#else int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; +#endif size_t size = sizeof(buffer1); - if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0) + if (sysctl(mib, 4, path, &size, NULL, 0) != 0) break; resolved = realpath(path, buffer2); @@ -608,16 +742,13 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } - if (path != buffer1) - WAI_FREE(path); - - return length; + return ok ? length : -1; } +#endif + WAI_NOINLINE WAI_FUNCSPEC int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) { @@ -670,4 +801,4 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/pkg/urbit/daemon/whereami.h b/pkg/urbit/daemon/whereami.h index 6c81af818..d5edffb8c 100644 --- a/pkg/urbit/daemon/whereami.h +++ b/pkg/urbit/daemon/whereami.h @@ -1,4 +1,6 @@ -// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz) +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) // https://github.com/gpakosz/whereami #ifndef WHEREAMI_H @@ -62,4 +64,4 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); } #endif -#endif // #ifndef WHEREAMI_H +#endif // #ifndef WHEREAMI_H \ No newline at end of file