On Linux specifically:
you might use proc(5) and the /proc/self/exe
symlink, so use readlink(2) on that. Once you did that, you could use basename(3) or realpath(3) on the obtained symlink.
However, be aware that a program might not always have a file path. It could have several file paths (for example /bin/rbash
is a symlink to /bin/bash
, and the shell process behave differently when invoked as rbash
or as bash
). Sometimes a given file (actually an inode, see inode(7)) has several hardlinks to it. In weird cases there is none.
And it could happen that a program is execve(2)-ed and then removed with unlink(2) (perhaps from another process scheduled to run before yours) etc..
(BTW, your question is OS specific; readdir(3) is POSIX and there are some operating systems not even having directories, and readdir
is not mentioned by the C11 standard; check by reading n1570)
I experimented with the following (pathological) ./selfremove
program (in my /home/basile/tmp/
directory) which removes its own binary:
// file selfremove.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main (int argc, char **argv)
{
char selfpath[128];
memset (selfpath, 0, sizeof (selfpath));
if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
{
perror ("first readlink");
exit (EXIT_FAILURE);
};
printf ("initial /proc/self/exe -> %s\n", selfpath);
if (unlink (argv[0]))
{
fprintf (stderr, "unlink %s: %m\n", argv[0]);
exit (EXIT_FAILURE);
};
printf ("%s unlinked\n", argv[0]);
if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
{
perror ("second readlink");
exit (EXIT_FAILURE);
};
printf ("final /proc/self/exe -> %s\n", selfpath);
return 0;
}
It works, and the kernel is constructing a * (deleted)
symlink (since a perverse coder might rename an executable as selfremove (deleted)
, so that kernel added suffix is only an indication ....):
% ./selfremove
initial /proc/self/exe -> /home/basile/tmp/selfremove
./selfremove unlinked
final /proc/self/exe -> /home/basile/tmp/selfremove (deleted)
So even with /proc/self/exe
you cannot always trust the result.
If you assume that your program has been execve(2)-ed by some shell (or similar program doing execvp(3)) -and that is not always the case- then the PATH
variable might have been used (and searched from your main
's argv[0]
if it has no /
). You might use getenv(3) as getenv("PATH")
to get it from your environment (see environ(7) for more). That $PATH
is generally set and used, but they are pathological cases too.
So in general there is no way to reliably print its own executable (as my pathological selfremove.c
demonstrates). In most cases you could find it (e.g. by readlink
of /proc/self/exe
, or by searching in $PATH
using argv[0]
).