11 * This function returns the absolute path to the executable it is running in.
13 * The implementation follows http://stackoverflow.com/a/933996/712014
15 * Returned value must be freed by the caller.
17 char *get_exe_path(const char *argv0) {
18 size_t destpath_size = 1024;
19 size_t tmp_size = 1024;
20 char *destpath = smalloc(destpath_size);
21 char *tmp = smalloc(tmp_size);
24 #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
25 /* Linux and Debian/kFreeBSD provide /proc/self/exe */
26 #if defined(__linux__) || defined(__FreeBSD_kernel__)
27 const char *exepath = "/proc/self/exe";
28 #elif defined(__FreeBSD__)
29 const char *exepath = "/proc/curproc/file";
33 while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
34 destpath_size = destpath_size * 2;
35 destpath = srealloc(destpath, destpath_size);
38 /* readlink() does not NULL-terminate strings, so we have to. */
39 destpath[linksize] = '\0';
45 /* argv[0] is most likely a full path if it starts with a slash. */
46 if (argv0[0] == '/') {
49 return sstrdup(argv0);
52 /* if argv[0] contains a /, prepend the working directory */
53 if (strchr(argv0, '/') != NULL) {
55 while ((retgcwd = getcwd(tmp, tmp_size)) == NULL && errno == ERANGE) {
56 tmp_size = tmp_size * 2;
57 tmp = srealloc(tmp, tmp_size);
59 if (retgcwd != NULL) {
61 sasprintf(&destpath, "%s/%s", tmp, argv0);
67 /* Fall back to searching $PATH (or _CS_PATH in absence of $PATH). */
68 char *path = getenv("PATH");
70 /* _CS_PATH is typically something like "/bin:/usr/bin" */
71 while (confstr(_CS_PATH, tmp, tmp_size) > tmp_size) {
72 tmp_size = tmp_size * 2;
73 tmp = srealloc(tmp, tmp_size);
75 sasprintf(&path, ":%s", tmp);
79 const char *component;
82 if ((component = strtok(str, ":")) == NULL)
86 sasprintf(&destpath, "%s/%s", component, argv0);
87 /* Of course this is not 100% equivalent to actually exec()ing the
89 if (access(destpath, X_OK) == 0) {
99 /* Last resort: maybe it’s in /usr/bin? */
100 return sstrdup("/usr/bin/i3-nagbar");