Mercurial > code
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