changeset 563:668975a91fb2

Misc: add executable.cpp, get the executable path
author David Demelier <markand@malikania.fr>
date Tue, 21 Jun 2016 15:55:57 +0200
parents b6c6d98054d9
children 21fa534ce42f
files misc/executable.cpp
diffstat 1 files changed, 177 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/executable.cpp	Tue Jun 21 15:55:57 2016 +0200
@@ -0,0 +1,177 @@
+#include <string>
+#include <stdexcept>
+
+#if defined(__linux__)
+#  include <unistd.h>
+
+#  include <cerrno>
+#  include <cstring>
+#  include <stdexcept>
+#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#  if defined(__NetBSD__)
+#    include <sys/param.h>
+#  else
+#    include <sys/types.h>
+#  endif
+
+#  if defined(__OpenBSD__)
+#    include <unistd.h>
+#  endif
+
+#  include <sys/sysctl.h>
+
+#  include <array>
+#  include <cerrno>
+#  include <climits>
+#  include <cstddef>
+#  include <cstdlib>
+#  include <cstring>
+#  include <stdexcept>
+#elif defined(__APPLE__)
+#  include <cerrno>
+#  include <cstring>
+#  include <libproc.h>
+#  include <unistd.h>
+#elif defined(_WIN32)
+#  include <Windows.h>
+#endif
+
+#if defined(__linux__)
+
+std::string executable()
+{
+    std::string result;
+
+    result.resize(2048, '\0');
+
+    auto size = readlink("/proc/self/exe", &result[0], 2048);
+
+    if (size < 0)
+        throw std::runtime_error(std::strerror(errno));
+
+    result.resize(size, '\0');
+
+    return result;
+}
+
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+
+std::string executable()
+{
+    std::array<int, 4> mib{ CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+    std::string result;
+    std::size_t size = PATH_MAX + 1;
+
+    result.resize(size, '\0');
+
+    if (sysctl(mib.data(), 4, &result[0], &size, nullptr, 0) < 0)
+        throw std::runtime_error(std::strerror(errno));
+
+    result.resize(size, '\0');
+
+    return result;
+}
+
+#elif defined(__APPLE__)
+
+std::string executable()
+{
+    std::string result;
+    std::size_t size = PROC_PIDPATHINFO_MAXSIZE;
+
+    result.resize(size, '\0');
+
+    if ((size = proc_pidpath(getpid(), &result[0], size)) == 0)
+        throw std::runtime_error(std::strerror(errno));
+
+    result.resize(size, '\0');
+
+    return result;
+}
+
+#elif defined(_WIN32)
+
+std::string executable()
+{
+    std::string result;
+    std::size_t size = PATH_MAX;
+
+    result.resize(size, '\0');
+
+    if (!(size = GetModuleFileNameA(nullptr, &result[0], size)))
+        throw std::runtime_error("GetModuleFileName error");
+
+    result.resize(size, '\0');
+
+    return result;
+}
+
+#elif defined(__NetBSD__)
+
+std::string executable()
+{
+        std::string result;
+
+#if defined(KERN_PROC_PATHNAME)
+        std::array<int, 4> mib{ CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
+        std::size_t size = MAXPATHLEN;
+
+        result.resize(size, '\0');
+
+        if (sysctl(mib.data(), 4, &result[0], &size, nullptr, 0) < 0)
+            throw std::runtime_error(std::strerror(errno));
+
+        result.resize(size, '\0');
+#else
+        result.resize(2048, '\0');
+
+        auto size = readlink("/proc/curproc/exe", &result[0], 2048);
+
+        if (size < 0)
+            throw std::runtime_error(std::strerror(errno));
+
+        result.resize(size, '\0');
+#endif
+
+        return result;
+}
+
+#elif defined(__OpenBSD__)
+
+std::string executable()
+{
+    char **paths, *path;
+    std::string result;
+    std::size_t len;
+    std::array<int, 4> mib{ CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
+
+    if (sysctl(mib.data(), 4, nullptr, &len, nullptr, 0) == -1)
+        throw std::runtime_error(std::strerror(errno));
+    if ((paths = static_cast<char **>(malloc(len))) == nullptr)
+        throw std::runtime_error(std::strerror(errno));
+
+    sysctl(mib.data(), 4, paths, &len, nullptr, 0);
+
+    if ((path = static_cast<char *>(std::malloc(PATH_MAX + 1))) == nullptr) {
+        std::free(paths);
+        throw std::runtime_error(std::strerror(errno));
+    }
+
+    realpath(paths[0], path);
+    result = path;
+
+    std::free(paths);
+    std::free(path);
+
+    return result;
+}
+
+#else
+
+std::string executable()
+{
+    // Not supported.
+    return "";
+}
+
+#endif