tags:

views:

1858

answers:

10

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).

Thanks.

+7  A: 

If under any POSIX system, then 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
/proc is not POSIX, and it's not very standardized. Many modern Unices have it, some don't.
Dietrich Epp
Always good to learn new things. Thanks. Is there more "programmatic" way to do this?
eran
@Dietrich: you're right, it's not posix. According to Wikipedia unix-like systems having it are: Linux, AIX, BSD, Solaris, QNX. It however it's not stated whether all those systems have /proc/*/cmd simlink.
Solaris does have /proc, but doesn't have /proc/*/cmd.
sth
@unknown(google): check out man 2:3 readlink or here: http://linux.die.net/man/3/readlink
In Linux /proc filesystem is a kernel level option- so it can't be guaranteed to be available or enabled on any given Linux system. Also, it could be enabled in the kernel but not available if /etc/fstab does not have a mount point for it. Also, you may run into security issues.
Klathzazt
+8  A: 

Use GetModuleFileName() function if you are using Windows.

Shino C G
Thanks, but I'm using linux and unix.
eran
+3  A: 
readlink("/proc/self/exe", buffer, buffer_size);
finnw
A: 

I don't think there is a portable way to do this.

Does argv[0] have the full path if you invoke the program with a full static path? If so, you could force the user to execute the binary as such, like sshd does.

vext01
+9  A: 

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:

  1. If argv[0] is an absolute path, assume this is the full path to the executable.
  2. If argv[0] is a relative path, ie, it contains a /, determine the current working directory with getcwd() and then append argv[0] to it.
  3. If argv[0] is a plain word, search $PATH looking for argv[0], and append argv[0] to whatever directory you find it in.

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.

Dale Hagglund
+42  A: 
lispmachine
+1 nice sharp answer
Anything that depends on argv[0] being the program name is not reliable. It will work most of the time, but not *every* time. This problem is hard on unixes without /proc
dmckee
Not all unixes with proc have /proc/self/exe. The layout of /proc is entirely OS-specific and they all do it a bit differently. For example, FreeBSD provides /proc/curproc/file which works the same as Linux's /proc/self/exe. But others may not do this at all.
MarkR
+1  A: 

Remember that in 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.

Thomas
+2  A: 

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.

Michael
A: 

I would

1) Use the basename() function: http://linux.die.net/man/3/basename
2) chdir() to that directory
3) Use getpwd() to get the current directory

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.

JCCyC
+2  A: 

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:

Grumbel
+1 for the BinReloc library.
Danilo Piazzalunga