[Solved-5 Solutions] Finding current executable's path without proc/self/exe - linux tutorial



Problem:

How to find current executable path without proc/self/exe ?

Solution 1:

Some OS-specific interfaces:

  • Mac OS X: _NSGetExecutablePath() (man 3 dyld)
  • Linux: readlink /proc/self/exe
  • Solaris: getexecname()
  • FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1
  • FreeBSD if it has procfs: readlink /proc/curproc/file (FreeBSD doesn't have procfs by default)
  • NetBSD: readlink /proc/curproc/exe
  • DragonFly BSD: readlink /proc/curproc/file

Some shells, consist of bash and ksh, set the environment variable "_" to the full path of the executable before it is executed. In that case you can use getenv("_") to get it. However this is unreliable because not all shells do this, and it could be set to anything or be left over from a parent process which did not change it before executing your program.

Solution 2:

  • Check out the whereami library from Gregory Pakosz (which has just a single C file).
  • To get the full path to the current executable on a variety of platforms.
  • It's available as a repo on github.

Solution 3:

To using either /proc/self/exe or argv[0] is using the information passed by the ELF interpreter, made available by glibc as such:

#include <stdio.h>
#include <sys/auxv.h>

int main(int argc, char **argv)
{
    printf("%s\n", (char *)getauxval(AT_EXECFN));
    return(0);
}

Solution 4:

Isolating platform specific code with #ifdefs.

The other type would be to have clean #ifdef-less header wich contains function declarations and put the implementations in platform specific source files. For example, check out how Poco C++ library does something similar for their Environment class.

Solution 5:

  • This code finds the executable's path in Windows, Linux, MacOS, Solaris or FreeBSD.
  • To simplify the code but it's easy enough to remove.
  • To use defines like _MSC_VER and __linux as the OS and compiler require.
#include <string>
#include <boost/predef/os.h>

#if (BOOST_OS_WINDOWS)
#  include <stdlib.h>
#elif (BOOST_OS_SOLARIS)
#  include <stdlib.h>
#  include <limits.h>
#elif (BOOST_OS_LINUX)
#  include <unistd.h>
#  include <limits.h>
#elif (BOOST_OS_MACOS)
#  include <mach-o/dyld.h>
#elif (BOOST_OS_BSD_FREE)
#  include <sys/types.h>
#  include <sys/sysctl.h>
#endif

/*
 * Returns the full path to the currently running executable,
 * or an empty string in case of failure.
 */
std::string getExecutablePath() {
#if (BOOST_OS_WINDOWS)
    char *exePath;
    if (_get_pgmptr(&exePath) != 0)
        exePath = "";
#elif (BOOST_OS_SOLARIS)
    char exePath[PATH_MAX];
    if (realpath(getexecname(), exePath) == NULL)
        exePath[0] = '\0';
#elif (BOOST_OS_LINUX)
    char exePath[PATH_MAX];
    ssize_t len = ::readlink("/proc/self/exe", exePath, sizeof(exePath));
    if (len == -1 || len == sizeof(exePath))
        len = 0;
    exePath[len] = '\0';
#elif (BOOST_OS_MACOS)
    char exePath[PATH_MAX];
    uint32_t len = sizeof(exePath);
    if (_NSGetExecutablePath(exePath, &len) != 0) 
    {
        exePath[0] = '\0'; // buffer too small (!)
    } else
    {
        // resolve symlinks, ., .. if possible
        char *canonicalPath = realpath(exePath, NULL);
        if (canonicalPath != NULL) 
        {
            strncpy(exePath,canonicalPath,len);
            free(canonicalPath);
        }
    }
#elif (BOOST_OS_BSD_FREE)
    char exePath[2048];
    int mib[4];  mib[0] = CTL_KERN;  mib[1] = KERN_PROC;  mib[2] = KERN_PROC_PATHNAME;  mib[3] = -1;
    size_t len = sizeof(exePath);
    if (sysctl(mib, 4, exePath, &len, NULL, 0) != 0)
        exePath[0] = '\0';
#endif
    return std::string(exePath);
}

The above version returns full paths including the executable name. If instead we want the path without the executable name, <#include boost/filesystem.hpp> and change the return statement :

return strlen(exePath)>0 ? boost::filesystem::path(exePath).remove_filename().make_preferred().string() : std::string();


Related Searches to - linux - linux tutorial - Finding current executable's path without proc/self/exe