view modules/executable/executable.cpp @ 617:266f32919d0a

Misc: update copyright headers, closes #686
author David Demelier <markand@malikania.fr>
date Mon, 21 Aug 2017 11:49:11 +0200
parents 47f003c55e1e
children da9c2e128cae
line wrap: on
line source

/*
 * executable.cpp -- get executable path
 *
 * Copyright (c) 2016-2017 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;
}