Как работающее приложение в Linux / *nix может определить свой собственный абсолютный путь?


Предположим, что вы запускаете приложение "app", набрав "app", а не его абсолютный путь. Из-за переменной $PATH на самом деле работает /foo/bar/app. Из внутреннего приложения я хотел бы определить /foo / bar / app. argv[0] - это просто "приложение", так что это не помогает.

Я знаю, что в Linux я могу получить взгляд на

/ proc / self / exe

Softlink, но это не работает на других * nix, в частности OS X. Есть ли более портативный способ определить dir, в котором живет приложение?

3 2

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();
  }