#include #include #include #include /* for main only */ #include #include #ifdef C_SOLARIS #define _STRUCTURED_PROC 1 #include #include #endif /* C_SOLARIS aka Solaris */ /** Get the ORIGIN aka path to this running program. E.g. if started via /opt/apps/bin/myapp it would return /opt/apps/bin. @param path where to store the calculated origin @param l maximum length of path @return the length of the actual ORIGIN. Might be greater than l. In this case, path contains only a part of the ORIGIN (truncated). */ int getOrigin(char *path, unsigned int l) { /* we store the path for the origin to avoid doing this again and again */ static char my_origin[MAXPATHLEN] = { '\0' }; #if defined(C_LINUX) || defined(C_SOLARIS) /* determine my origin if not already done */ if ( my_origin[0] == '\0' ) { int olen = 0; #ifdef C_SOLARIS /* get the name from initial argv[0] */ psinfo_t ps; int fd; char **argv; if ( (fd = open("/proc/self/psinfo", O_RDONLY)) > -1 ) { const char *execname; int res = read( fd, &ps, sizeof(psinfo_t) ); if (res > 0) { argv = (char **) ps.pr_argv; /* always try argv[0] first */ if (realpath(argv[0], my_origin) && (my_origin[0] == '/')) { olen = strlen(my_origin); } else if ((execname = getexecname())){ /* no absolute name - so probably invoked like "eval 'exec perl -S $0 ${1+"$@"}'" or "#!/bin/env perl" */ realpath(execname, my_origin); olen = strlen(my_origin); } else { my_origin[0] = '\0'; } } close(fd); } #else /* C_LINUX */ olen = readlink("/proc/self/exe", my_origin, sizeof(my_origin)); if ( olen < 1 || my_origin[0] == '[') { olen = 0; } #endif /* C_LINUX */ if (olen > 0) { /* remove everything after the last / incl. the / itself */ assert(my_origin[0] == '/'); while (olen > 1 && my_origin[olen - 1] != '/') --olen; my_origin[olen - 1] = '\0'; } else { my_origin[0] = '\0'; } } strncpy(path, my_origin, l); #endif /* C_LINUX || C_SOLARIS */ /* just make sure, that the result is null terminated (if strlen(orign) > l )*/ path[l-1] = '\0'; return strlen(my_origin); } /** Just print the path, where this binary is located. NOTE: Compile with -DC_SOLARIS=1 on Sun Solaris, with -DC_LINUX=1 on Linux systems. -DC_LINUX=1 may work on BSD and other *ix as well. @param argc ignored @param argv ignored @return 0 */ int main(int argc, char *argv[]) { char origin[MAXPATHLEN] = { '\0' }; int res; res = getOrigin(origin, MAXPATHLEN); if (res >= MAXPATHLEN || res < 1) { /* an executable should not be in / ;-) */ printf("Unusable ORIGIN - path too long."); } else { printf("My Origin is: %s\n", origin); } exit(0); }