How can a running application in Linux/*nix determine its own absolute path?
Suppose you run the application 'app' by typing 'app', rather than its absolute path. Due to your $PATH variable, what actually runs is /foo/bar/app. From inside app I'd like to determine /foo/bar/app. argv[0] is just 'app', so that doesn't help.
I know in Linux I can get look at the
/proc/self/exe
softlink, but that doesn't work o开发者_运维技巧n other *nix, specifically OS X. Is there a more portable way to determine the dir in which the app lives?
Don't use path, use /proc. Here is some code i've written
const char* eif_ft__binary_file()
{
#ifdef OS_WINDOWS
wchar_t* p = (wchar_t*)malloc(282 * sizeof(wchar_t));
GetModuleFileNameW(NULL, p, 280);
char* res = transform__utf16_to_utf8(p,-1,NULL);
free(p);
return res;
#elif OS_LINUX
char* path = (char*)malloc(512);
int res = readlink("/proc/self/exe", path, 510);
if (res == -1) { free(path); return ""; }
path[res]=0;
TEMP_STRING_1 = path;
free(path);
return TEMP_STRING_1.text();
#elif OS_SOLARIS
char* path = (char*)malloc(512);
int res = readlink("/proc/self/path/a.out", path, 510);
if (res == -1) { free(path); return ""; }
path[res]=0;
TEMP_STRING_1 = path;
free(path);
return TEMP_STRING_1.text();
#elif OS_FREEBSD
char* path = (char*)malloc(512);
int res = readlink("/proc/curproc/file", path, 510);
if (res == -1) { free(path); return ""; }
path[res]=0;
TEMP_STRING_1 = path;
free(path);
return TEMP_STRING_1.text();
#else
TEMP_STRING_1 = "";
return TEMP_STRING_1.text();
#endif
}
TEMP_STRING ist just a generic macro for a String class.
I'm not sure that there is any good portable way to do this.
On OS X, you can use _NSGetExecutablePath()
(then apply realpath()
to the result if you like).
I ended up mimicking the 'which' program and looking at each dir in $PATH to see if $dir/app is executable:
if (strchr(progname, '/') == NULL) {
std::string pathStr = getenv("PATH");
std::string testDir;
pathStr += ":"; // add a trailing ':' to make search easier
size_t pos = 0;
bool found = false;
while (!found && ((pos = pathStr.find(":")) != std::string::npos)) {
testDir = pathStr.substr(0, pos);
testPath = testDir + "/" + progname;
pathStr = pathStr.substr(pos + 1, pathStr.size() - pos + 1);
if (access(testPath.c_str(), X_OK) == 0)
found = true;
}
if (found)
dir = testDir.c_str();
}
精彩评论