16

I have this requirement where I need to find the full path for the C++ program from within. For Windows, I have the following solution. The argv[0] may or may not contain the full path. But I need to be certain.

TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], base[_MAX_FNAME], ext[_MAX_EXT];
TCHAR fullPath[255+1];
_splitpath(argv[0],drive,dir,base,ext);
SearchPath(NULL,base,ext,255,fullPath,NULL);

What is the Linux (gcc) equivalent for the above code? Would love to see a portable code.

Sharath
  • 1,627
  • 2
  • 18
  • 34
  • are you *searching* for your file in your windows solution? what if there are multiple files with that name? – Karoly Horvath Aug 13 '11 at 16:46
  • @Tomalak: That is not a very useful comment. – Sharath Aug 13 '11 at 17:55
  • That windows solution doesn't always work, IMHO. If you call GetModuleFilename(nullptr), it should work to get the full path of the executable that is running. – Larry Osterman Aug 13 '11 at 17:56
  • 1
    @Sharath: Just because you didn't understand it doesn't mean that it is not useful. Programs are not supposed to know where the executable is: there is no meaning there. Programs only know the current working directory of the environment in which they're running. That is good and proper. That there are unfortunately ways to work around this on various OSes doesn't change that. I just thought you should know. – Lightness Races in Orbit Aug 13 '11 at 18:43
  • 1
    @Tomalak: You are talking about a philosophy or dogma. Such beliefs can vary according to ones programming background. I have forgotten more languages than I currently know, seen so many proper ways doing things flow under the bridge. Over years we all develop certain favorite ways of doing things. May be I need this feature because I don't have a working directory. Do you have to be so judgmental just because I asked a simple question? That's all I am saying. – Sharath Aug 17 '11 at 19:16
  • possible duplicate of [how to find the location of the executable in C](http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c) – ergosys Sep 10 '11 at 18:59
  • possible duplicate of [Finding current executable's path without /proc/self/exe](http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe) – mmmmmm Mar 24 '14 at 12:33

6 Answers6

18

On Linux (Posix?) you have a symbolic link /proc/self/exe which links to the full path of the executable.

On Windows, use GetModuleFileName.

Never rely on argv[0], which is not guaranteed to be anything useful.

Note that paths and file systems are not part of the language and thus necessarily a platform-dependent feature.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    I believe the proc filesystem is not part of the POSIX standard - it's just very common in Unix-like operating systems. – Joseph Mansfield Aug 13 '11 at 17:03
  • 1
    @sftrabbit: And since there is no standard governing it, `/proc/self/exe` may or may not actually work. If it's there, it's probably helpful. But if it isn't, then it's not helpful. I've actually only seen `/proc` on Linux based systems. – Omnifarious Aug 13 '11 at 17:59
8

The top answer to this question lists techniques for a whole bunch of OSes.

hoijui
  • 3,615
  • 2
  • 33
  • 41
olooney
  • 2,467
  • 1
  • 16
  • 25
  • Nice, you should also mention the [other question](http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c) linked in that one for even more platforms. – Kerrek SB Aug 13 '11 at 16:52
  • Yours, even though it's a link, is by far the better answer. :-) – Omnifarious Aug 13 '11 at 18:00
6
string get_path( )
{
        char arg1[20];
        char exepath[PATH_MAX + 1] = {0};

        sprintf( arg1, "/proc/%d/exe", getpid() );
        readlink( arg1, exepath, PATH_MAX );
        return string( exepath );
}
fret
  • 1,542
  • 21
  • 36
MetallicPriest
  • 29,191
  • 52
  • 200
  • 356
1

For Linux:
Function to execute system command

int syscommand(string aCommand, string & result) {
    FILE * f;
    if ( !(f = popen( aCommand.c_str(), "r" )) ) {
            cout << "Can not open file" << endl;
            return NEGATIVE_ANSWER;
        }
        const int BUFSIZE = 4096;
        char buf[ BUFSIZE ];
        if (fgets(buf,BUFSIZE,f)!=NULL) {
            result = buf;
        }
        pclose( f );
        return POSITIVE_ANSWER;
    }

Then we get app name

string getBundleName () {
    pid_t procpid = getpid();
    stringstream toCom;
    toCom << "cat /proc/" << procpid << "/comm";
    string fRes="";
    syscommand(toCom.str(),fRes);
    size_t last_pos = fRes.find_last_not_of(" \n\r\t") + 1;
    if (last_pos != string::npos) {
        fRes.erase(last_pos);
    }
    return fRes;
}

Then we extract application path

    string getBundlePath () {
    pid_t procpid = getpid();
    string appName = getBundleName();
    stringstream command;
    command <<  "readlink /proc/" << procpid << "/exe | sed \"s/\\(\\/" << appName << "\\)$//\"";
    string fRes;
    syscommand(command.str(),fRes);
    return fRes;
    }

Do not forget to trim the line after

ETech
  • 1,613
  • 16
  • 17
1

If you came here when Googling for GetModuleFileName Linux... you're probably looking for the ability to do this for dynamically-loaded libraries. This is how you do it:

struct link_map *lm;
dlinfo(module, RTLD_DI_LINKMAP, &lm);
lm->l_name  // use this
user541686
  • 205,094
  • 128
  • 528
  • 886
1
#include <string>
#include <unistd.h>
#include <limits.h>

std::string getApplicationDirectory() {
    char result[ PATH_MAX ];
    ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
    std::string appPath = std::string( result, (count > 0) ? count : 0 );

    std::size_t found = appPath.find_last_of("/\\");
    return appPath.substr(0,found);
}
suspic
  • 51
  • 8