diff modules/executable/executable.cpp @ 616:47f003c55e1e

Executable: dedicate new module directory, closes #684
author David Demelier <markand@malikania.fr>
date Mon, 21 Aug 2017 11:40:55 +0200
parents misc/executable.cpp@beef249c796c
children 266f32919d0a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/executable/executable.cpp	Mon Aug 21 11:40:55 2017 +0200
@@ -0,0 +1,126 @@
+/*
+ * executable.cpp -- get executable path
+ *
+ * Copyright (c) 2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string>
+#include <stdexcept>
+
+#if defined(__linux__)
+#   include <unistd.h>
+
+#   include <cerrno>
+#   include <climits>
+#   include <cstring>
+#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#   if defined(__NetBSD__)
+#       include <sys/param.h>
+#       include <unistd.h>
+#   else
+#       include <sys/types.h>
+#   endif
+
+#   if defined(__OpenBSD__)
+#       include <unistd.h>
+#   endif
+
+#   include <sys/sysctl.h>
+
+#   include <cerrno>
+#   include <climits>
+#   include <cstddef>
+#   include <cstdlib>
+#   include <cstring>
+#elif defined(__APPLE__)
+#   include <cerrno>
+#   include <cstring>
+#   include <libproc.h>
+#   include <unistd.h>
+#elif defined(_WIN32)
+#   include <Windows.h>
+#endif
+
+std::string executable_path()
+{
+    std::string result;
+
+#if defined(__linux__)
+    char path[PATH_MAX + 1] = {0};
+
+    if (readlink("/proc/self/exe", path, sizeof (path) - 1) < 0)
+        throw std::runtime_error(std::strerror(errno));
+
+    result = path;
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+    int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+    char path[PATH_MAX + 1] = {0};
+    size_t size = PATH_MAX;
+
+    if (sysctl(mib, 4, path, &size, nullptr, 0) < 0)
+        throw std::runtime_error(std::strerror(errno));
+
+    result = path;
+#elif defined(__APPLE__)
+    char path[PROC_PIDPATHINFO_MAXSIZE + 1] = {0};
+
+    if ((proc_pidpath(getpid(), path, sizeof (path) - 1) == 0)
+        throw std::runtime_error(std::strerror(errno));
+
+    result = path;
+#elif defined(_WIN32)
+    char path[PATH_MAX + 1] = {0};
+
+    if (GetModuleFileNameA(nullptr, path, sizeof (path) - 1) == 0)
+        throw std::runtime_error("GetModuleFileName error");
+
+    result = path;
+#elif defined(__NetBSD__)
+    char path[4096 + 1] = {0};
+
+#   if defined(KERN_PROC_PATHNAME)
+    int mib[] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
+    int size = sizeof (path) - 1;
+
+    if (sysctl(mib, 4, path, &size, nullptr, 0) < 0)
+        throw std::runtime_error(std::strerror(errno));
+#   else
+    if (readlink("/proc/curproc/exe", path, sizeof (path) - 1) < 0)
+        throw std::runtime_error(std::strerror(errno));
+#   endif
+
+    result = path;
+#elif defined(__OpenBSD__)
+    char **paths, path[PATH_MAX + 1] = {0};
+    int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
+    size_t length = 0;
+
+    if (sysctl(mib, 4, 0, &length, 0, 0) < 0)
+        throw std::runtime_error(std::strerror(errno));
+    if (!(paths = static_cast<char**>(std::malloc(length))))
+        throw std::runtime_error(std::strerror(errno));
+    if (sysctl(mib, 4, paths, &length, 0, 0) < 0) {
+        std::free(paths);
+        throw std::runtime_error(std::strerror(errno));
+    }
+
+    realpath(paths[0], path);
+    result = path;
+
+    std::free(paths);
+#endif
+
+    return result;
+}