views:

3153

answers:

6

It seems to me that Linux has it easy with /proc/self/exe. But I'd like to know if there is a convenient way to find the current application's directory in C/C++ with cross-platform interfaces. I've seen some projects mucking around with argv[0], but it doesn't seem entirely reliable.

If you ever had to support, say, Mac OS X, which doesn't have /proc/, what would you have done? Use #ifdefs to isolate the platform-specific code (NSBundle, for example)? Or try to deduce the executable's path from argv[0], $PATH and whatnot, risking finding bugs in edge cases?

A: 

For Linux/Unix try

sprintf(cmd, "which %s", argv[0]);
file = popen(cmd, "r");
fgets(path, sizeof(path), file);
qrdl
This seems like a hilariously bad idea: which wont find the executable in a non-standard directory and seems equally non-portable except now it goes across Unixes.
Nikron
does it work on windows ?
Ahmed Said
When you start an application, you need to specify either full path, relative to current directory or no path - in this case $PATH will be checked. which supports all three options - it will give you the full path. And it works for both Linux and Mac OS X, as OP requested. So there is nothing bad with this approach and nothing hilarious.
qrdl
Nope, it doesn't work on Windows, because which is Linux/Unix command and popen() is POSIX function.
qrdl
A: 

AFAIK, no such way. And there is also an ambuiguity: what would you like to get as the answer if the same executable has multiple hard-links "pointing" to it? (Hard-links don't actually "point", they are the same file, just at another place in the FS hierarchy.) Once execve() successfully executes a new binary, all information about its arguments is lost.

zvrba
+3  A: 

You can use argv[0] and analyze the PATH environment variable. Look at : A sample of a program that can find itself

bill
This isn't actually reliable (though it will generally work with programs launched by the usual shells), because `execv` and kin take the path to the executable seperately of `argv`
dmckee
A: 

If you ever had to support, say, Mac OS X, which doesn't have /proc/, what would you have done? Use #ifdefs to isolate the platform-specific code (NSBundle, for example)?

Yes, writing platform specific code, and then isolating it with #ifdefs is the way to do. For example, check out how Poco C++ library does something similar for their Environment class.

StackedCrooked
A: 

Apparently very close from "Programatically retrieving the absolute path of an OS X command-line app".

bortzmeyer
Hmm... That one said that it couldn't be done. I've now added an answer to that question.
mark4o
+20  A: 

Some OS-specific interfaces:

The portable (but less reliable) method is to use argv[0]. Although it could be set to anything by the calling program, by convention it is set to either a path name of the executable or a name that was found using $PATH.

Some shells, including 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.

mark4o
And also readlink /proc/curproc/file on FreeBSD.
stepancheg
Thanks @stepancheg; added. However it looks like procfs is not mounted by default on FreeBSD so I have linked to another question mentioning sysctl.
mark4o
+1 Nice concise comprehensive answer!
Martin B