On Linux specifically:
you can use proc (5) and the symbolic link /proc/self/exe , so use readlink (2) . Once you have done this, you can use basename (3) or realpath (3) on the resulting symbolic link.
However, remember that a program may not always have a file path. It can have several file paths (for example, /bin/rpath is a symbolic link to /bin/bash , and the shell process behaves differently when rbash called or as bash ). Sometimes a given file (actually an inode ) has several hard links to it. In strange cases, they are not. And it may happen that the program execve (2) -ed, and then removed using unlink (2) (possibly 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 that don't even have directories and readdir not mentioned by the C11 standard, checking by reading n1570 )
I experimented with the following (pathological) program ./selfremove (in my directory /home/basile/tmp/ ), which deletes 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 creates a symbolic link * (deleted) (since a distorted encoder can rename the executable file as selfremove (deleted) , so the kernel added with the 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 was execve (2) -ed by some kind of shell (or a similar program executing execvp (3) ) - and this is not always the case, then the PATH variable may have been used (and searched from your main argv[0] if she does not have / ). You can use getenv (3) as getenv("PATH") to get it from your environment (see environment (7) for more). This $PATH is usually installed and used, but they are also pathological cases.
Thus, in the general case, it is not possible to reliably print your own executable file (as my pathological selfremove.c ). In most cases, you can find it (for example, readlink from /proc/self/exe or by searching in $PATH using argv[0] ).