Mercurial > code
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; +}