From 73c56ffacc739a6a9230d9da0a665681224eaf2e Mon Sep 17 00:00:00 2001 From: Gregory Pakosz Date: Thu, 11 Feb 2016 13:30:39 +0000 Subject: [PATCH] added support for FreeBSD. Closes #4. --- README.md | 1 + _gnu-make/Makefile | 13 +++++- src/whereami.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c82d394..cb0379a 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Supported platforms: - iOS - Android - QNX Neutrino +- FreeBSD Just drop `whereami.h` and `whereami.c` into your build and get started. (see also [customizing compilation]) diff --git a/_gnu-make/Makefile b/_gnu-make/Makefile index afde4aa..665cdc2 100644 --- a/_gnu-make/Makefile +++ b/_gnu-make/Makefile @@ -24,6 +24,10 @@ ifeq ($(platform),) override CC := gcc endif endif + ifeq ($(__uname_s),freebsd) + override platform := freebsd + override architecture := $(__uname_m) + endif endif ifeq ($(architecture),) override architecture := unknown-architecture @@ -41,13 +45,17 @@ CFLAGS := -O2 -g -Wall -pedantic -Werror -std=c99 CXXFLAGS := -O2 -g -Wall -pedantic -Werror ifeq ($(platform),linux) -override LDFLAGS := $(LDFLAGS) -ldl +LDFLAGS += -ldl CFLAGS += -D_XOPEN_SOURCE=500 -fpic CXXFLAGS += -fpic endif ifeq ($(platform),mac) CFLAGS += -D_DARWIN_C_SOURCE endif +ifeq ($(platform),freebsd) +CFLAGS += -fpic +CXXFLAGS += -fpic +endif ifeq ($(platform),mac) libsuffix := .dylib @@ -58,6 +66,9 @@ endif ifeq ($(platform),windows) libsuffix := .dll endif +ifeq ($(platform),freebsd) +libsuffix := .so +endif .PHONY: build-executable build: build-executable diff --git a/src/whereami.c b/src/whereami.c index d030611..19d3781 100644 --- a/src/whereami.c +++ b/src/whereami.c @@ -545,6 +545,114 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) return length; } +#elif defined(__FreeBSD__) + +#include +#include +#include +#include +#include +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + + for (;;) + { + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t size = sizeof(buffer1); + + if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0) + break; + + resolved = realpath(path, buffer2); + 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; + } + } + } + } + + break; + } + + if (path != buffer1) + WAI_FREE(path); + + return length; +} + +WAI_NOINLINE +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + 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; + } + } + } + } + } + + break; + } + + return length; +} + +#else + +#error unsupported platform + #endif #ifdef __cplusplus