Как работающее приложение в Linux / *nix может определить свой собственный абсолютный путь?
Предположим, что вы запускаете приложение "app", набрав "app", а не его абсолютный путь. Из-за переменной $PATH на самом деле работает /foo/bar/app. Из внутреннего приложения я хотел бы определить /foo / bar / app. argv[0] - это просто "приложение", так что это не помогает.
Я знаю, что в Linux я могу получить взгляд на
/ proc / self / exe
Softlink, но это не работает на других * nix, в частности OS X. Есть ли более портативный способ определить dir, в котором живет приложение?
3 ответа:
Не используйте path, используйте /proc. Вот какой код я написал
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 - это всего лишь универсальный макрос для класса String.
Я не уверен, что есть какой-либо хороший портативный способ сделать это.
В OS X можно использовать
_NSGetExecutablePath()
(затем применитеrealpath()
к результату, если хотите).
В итоге я имитировал программу which и смотрел на каждый dir в $PATH, чтобы увидеть, является ли $dir/app исполняемым:
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(); }