Is there a way in C/C++ to find the location (full path) of the current executed program?
(The problem with argv[0]
is that it does not give the full path.)
Is there a way in C/C++ to find the location (full path) of the current executed program?
(The problem with argv[0]
is that it does not give the full path.)
To summarize:
On Unixes with /proc
really straight and realiable way is to:
readlink("/proc/self/exe", buf, bufsize)
(Linux)
readlink("/proc/curproc/file", buf, bufsize)
(FreeBSD)
readlink("/proc/self/path/a.out", buf, bufsize)
(Solaris)
On Unixes without /proc
(i.e. if above fails):
If argv[0] starts with "/" (absolute path) this is the path.
Otherwise if argv[0] contains "/" (relative path) append it to cwd (assuming it hasn't been changed yet).
Otherwise search directories in $PATH
for executable argv[0]
.
Afterwards it may be reasonable to check whether the executable isn't actually a symlink. If it is resolve it relative to the symlink directory.
This step is not necessary in /proc method (at least for Linux). There the proc symlink points directly to executable.
Note that it is up to the calling process to set argv[0]
correctly.
It is right most of the times however there are occasions when the calling process cannot be trusted (ex. setuid executable).
On Windows: use GetModuleFileName(NULL, buf, bufsize)
execl("/home/hacker/.hidden/malicious", "/bin/ls", "-s", (char *)0);
leaves argv[0]
with an absolute pathname that has nothing whatsoever to do with the name of the file executed. The other information is useful, though; thanks. –
Psittacine /proc/self/exe
, I don't see how the library can work out reliably which program is executing it. It is causing a major headache right now. I'm interested in the AIX and HP-UX solutions to the 'identify the executable' problem, too. (Linux, MacOS X, Solaris, Windows don't seem to be a major problem.) –
Psittacine GetModuleFileName
. Instead, just #include <windows.h>
and use the path string provided automatically by Windows in _pgmptr
. It's easier than using the GetModuleFileName
function because that has the possibility of failing. –
Daughterly argv[0]
, but I do not now recall what the function calls were (other than 'non-portable'). I don't have direct access to the code any more, so I can't look up what we did. Time to hit the o/s manuals — section 2 and/or section 3. –
Psittacine AT_EXECFN
is also a possibility. –
Lookin Use GetModuleFileName() function if you are using Windows.
Please note that the following comments are unix-only.
The pedantic answer to this question is that there is no general way to answer this question correctly in all cases. As you've discovered, argv[0] can be set to anything at all by the parent process, and so need have no relation whatsoever to the actual name of the program or its location in the file system.
However, the following heuristic often works:
/
, determine the current working directory with getcwd() and then append argv[0] to it.Note that all of these can be circumvented by the process which invoked the program in question. Finally, you can use linux-specific techniques, such as mentioned by emg-2. There are probably equivalent techniques on other operating systems.
Even supposing that the steps above give you a valid path name, you still might not have the path name you actually want (since I suspect that what you actually want to do is find a configuration file somewhere). The presence of hard links means that you can have the following situation:
-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo # create a hard link to foo
$ /some/where/else/foo
Now, the approach above (including, I suspect, /proc/$pid/exe) will give /some/where/else/foo
as the real path to the program. And, in fact, it is a real path to the program, just not the one you wanted. Note that this problem doesn't occur with symbolic links which are much more common in practice than hard links.
In spite of the fact that this approach is in principle unreliable, it works well enough in practice for most purposes.
Not an answer actually, but just a note to keep in mind.
As we could see, the problem of finding the location of running executable is quite tricky and platform-specific in Linux and Unix. One should think twice before doing that.
If you need your executable location for discovering some configuration or resource files, maybe you should follow the Unix way of placing files in the system: put configs to /etc
or /usr/local/etc
or in current user home directory, and /usr/share
is a good place to put your resource files.
Remember that on Unix systems the binary may have been removed since it was started. It's perfectly legal and safe on Unix. Last I checked Windows will not allow you to remove a running binary.
/proc/self/exe will still be readable, but it will not be a working symlink really. It will be... odd.
In many POSIX systems you could check a simlink located under /proc/PID/exe. Few examples:
# file /proc/*/exe
/proc/1001/exe: symbolic link to /usr/bin/distccd
/proc/1023/exe: symbolic link to /usr/sbin/sendmail.sendmail
/proc/1043/exe: symbolic link to /usr/sbin/crond
On Mac OS X, use _NSGetExecutablePath
.
See man 3 dyld
and this answer to a similar question.
For Linux you can find the /proc/self/exe
way of doing things bundled up in a nice library called binreloc, you can find the library at:
I would
That way you'll get the directory in a neat, full form, instead of ./ or ../bin/.
Maybe you'll want to save and restore the current directory, if that is important for your program.
open(".")
and return to it later using fchdir()
. –
Fen realpath()
can turn a relative pathname to absolute and resolve symbolic links. –
Fen getpwd
? –
Hessney © 2022 - 2024 — McMap. All rights reserved.
argv[0]
is that it is not available if you are trying to do this in a library. – Shortage