2 * vim:ts=4:sw=4:expandtab
4 * i3 - an improved dynamic tiling window manager
5 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
18 * This function returns the absolute path to the executable it is running in.
20 * The implementation follows http://stackoverflow.com/a/933996/712014
22 * Returned value must be freed by the caller.
24 char *get_exe_path(const char *argv0) {
25 size_t destpath_size = 1024;
26 size_t tmp_size = 1024;
27 char *destpath = smalloc(destpath_size);
28 char *tmp = smalloc(tmp_size);
30 #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
31 /* Linux and Debian/kFreeBSD provide /proc/self/exe */
32 #if defined(__linux__) || defined(__FreeBSD_kernel__)
33 const char *exepath = "/proc/self/exe";
34 #elif defined(__FreeBSD__)
35 const char *exepath = "/proc/curproc/file";
39 while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
40 destpath_size = destpath_size * 2;
41 destpath = srealloc(destpath, destpath_size);
44 /* readlink() does not NULL-terminate strings, so we have to. */
45 destpath[linksize] = '\0';
51 /* argv[0] is most likely a full path if it starts with a slash. */
52 if (argv0[0] == '/') {
55 return sstrdup(argv0);
58 /* if argv[0] contains a /, prepend the working directory */
59 if (strchr(argv0, '/') != NULL) {
61 while ((retgcwd = getcwd(tmp, tmp_size)) == NULL && errno == ERANGE) {
62 tmp_size = tmp_size * 2;
63 tmp = srealloc(tmp, tmp_size);
65 if (retgcwd != NULL) {
67 sasprintf(&destpath, "%s/%s", tmp, argv0);
73 /* Fall back to searching $PATH (or _CS_PATH in absence of $PATH). */
74 char *path = getenv("PATH");
76 /* _CS_PATH is typically something like "/bin:/usr/bin" */
77 while (confstr(_CS_PATH, tmp, tmp_size) > tmp_size) {
78 tmp_size = tmp_size * 2;
79 tmp = srealloc(tmp, tmp_size);
81 sasprintf(&path, ":%s", tmp);
85 const char *component;
88 if ((component = strtok(str, ":")) == NULL)
92 sasprintf(&destpath, "%s/%s", component, argv0);
93 /* Of course this is not 100% equivalent to actually exec()ing the
95 if (access(destpath, X_OK) == 0) {
105 /* Last resort: maybe it’s in /usr/bin? */
106 return sstrdup("/usr/bin/i3-nagbar");