I develop my app in linux for both unix and win32(cross compile at each build) plataforms, so a ready to use function would be nice :). I'm using glib that has the 'gchar* g_get_current_dir(void)' function and it returns the current directory, but what I really need is the executable's dir. I'm inexperienced in C programming so any sugestions are welcome.
views:
86answers:
3GetModuleFileName in Windows. argv[0] in linux
NOTE: If you do cross-platform programming you should use also some cross platform libraries that hide this layer (Qt, wxWidgets, ACE, Boost[Don't know but I think it has something] ... )
I cannot speak to windows. However in UNIX, a fair percentage of the time it is possible, but it is not guaranteed. The reasons for this involve calls to exec from other programs like shell which in some circumstances can cloud where the executable lives, for example, a relative path like "../../../mybin/exe/myprogram". The PATH variable also makes it fun to track down an executable.
Let me ask: what are you trying to do, or, more correctly, why do you need to know? IMO you don't need to know. you can check getcwd() and if you are not running in a directory that works, exit. It should not matter where your executable image lives.
Here is one code hunk that works most of the time, not always!
requires a call from main, using argv[0], I am using popen() calls to shell to make the code fit in a small are, popen() is not always a great choice, this can fail if there are other executables earlier in the PATH with the same name:
char *
mypath(const char *src)
{
FILE *cmd=NULL;
static char path_2_me[PATH_MAX]={0x0};
char tmp[PATH_MAX]={0x0};
const char *basename=strrchr(src, '/');
if(basename==NULL)
basename=src;
else
basename++;
if(memcmp(src, "./", 2)==0)
sprintf(path_2_me,"%s/%s", getcwd(tmp, PATH_MAX), basename);
else
{
sprintf(tmp, "/usr/bin/which %s", basename);
cmd=popen(tmp, "r");
fgets(path_2_me, sizeof(path_2_me), cmd); /* one read only */
pclose(cmd);
/* check for what your version of which says on failure */
if(memcmp(path_2_me, "no ", 3)==0)
*path_2_me=0x0;
}
return (*path_2_me) ?path_2_me: NULL;
}
Under Unix like operating systems that have the /proc
directory you can readlink
/proc/self/exe
to get the actual executable files full path even when argv[0]
does not have this.
This may not work, however, if the executable was started with fexecv
(not available on many systems) and if that is implemented as a system call on your system. fexecv
is just like execve
except that it is passed an open file descriptor rather than a filename to run. Under Linux it is implemented by calling execve
on the string generated by `"/proc/self/%i", fd", so the file would have to live in the file system at the time the program was started.
I think that GNU/Hurd supports fexecve
natively.
It is possible for an executable file to be renamed or unlinked from the filesystem after it has been executed which makes it become an unnamed file which will go away as soon as it ceases to be open (in this context running a file usually requires it to be open by the kernel).