Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an executable discover its own path? (Linux) [duplicate]

Tags:

Possible Duplicate:
how to find the location of the executable in C

I would like an executable to be able to discover its own path; I have a feeling that the answer is "you can't do this", but I would like this to be confirmed!

I don't think I can use getcwd(), because I might not be executing it from the same directory. I don't think I can use argv[0], because that is based on the string that's used to execute it. Are there any other options?

Rationale

The real problem is that I'd like to place an executable somewhere on a filesystem, and place a default config file alongside it. I want the executable to be able to read its config file at runtime, but I don't want to hardcode this location into the executable, nor do I want the user to have to set environment variables. If there's a better solution to this situation, I'm all ears...

like image 200
Oliver Charlesworth Avatar asked Oct 26 '10 15:10

Oliver Charlesworth


4 Answers

The file /proc/self/exe is a simlink to the currently running executable.

like image 59
Cercerilla Avatar answered Sep 21 '22 07:09

Cercerilla


Edit: It was pointed out that using /proc/self/exe is more straightforward. That is entirely true, but I didn't see any benefit in editing the code. Since I still get comments about it, I've edited it.

#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>

int main()
{
  char dest[PATH_MAX];
  memset(dest,0,sizeof(dest)); // readlink does not null terminate!
  if (readlink("/proc/self/exe", dest, PATH_MAX) == -1) {
    perror("readlink");
  } else {
    printf("%s\n", dest);
  }
  return 0;
}

Initial answer: You can use getpid() to find the pid of the current process, then read /proc/<pid>/cmdline (for a human reader) or /proc/<pid>/exe which is a symlink to the actual program. Then, using readlink(), you can find the full path of the program.

Here is an implementation in C:

#include <sys/types.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>

int main()
{
  char path[PATH_MAX];
  char dest[PATH_MAX];
  memset(dest,0,sizeof(dest)); // readlink does not null terminate!
  pid_t pid = getpid();
  sprintf(path, "/proc/%d/exe", pid);
  if (readlink(path, dest, PATH_MAX) == -1) {
    perror("readlink");
  } else {
    printf("%s\n", dest);
  }
  return 0;
}

If you want to try, you can then compile this, make a symlink from the executable to an other path, and call the link:

$ gcc -o mybin source.c
$ ln -s ./mybin /tmp/otherplace
$ /tmp/otherplace
/home/fser/mybin
like image 22
Aif Avatar answered Sep 23 '22 07:09

Aif


Use the proc filesystem

Your flow would be:

  • Get pid of executable
  • look at /proc/PID/exe for a symlink
like image 6
NG. Avatar answered Sep 22 '22 07:09

NG.


Well, you have to use getcwd() in conjuction with argv[0]. The first one gives you the working directory, the second one gives you the relative location of the binary from the working directory (or an absolute path).

like image 1
Šimon Tóth Avatar answered Sep 22 '22 07:09

Šimon Tóth