views:

77

answers:

3

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 on other *nix, specifically OS X. Is there a more portable way to determine the dir in which the app lives?

+3  A: 

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.

Lothar
Doesn't work on OS X, for example. I was hoping for a more generic answer, but if none exists, I'll do something like the above, thanks.
Dave Wade-Stein
Thanks for /proc/self...I didn't realize that I didn't have to use getpid() to determine the current proc and could use 'self' instead.
Dave Wade-Stein
+1  A: 

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).

Matthew Slattery
Thanks. That's really helpful, as I hadn't tackled OS X yet.
Dave Wade-Stein
This does AFAIK only work if there is an Application bundle.I have not yet found a way to get the path for a command line executable. But i haven't tried it hard enough i guess.
Lothar
Ah, I wondered about that. This is a command-line app, not an Application bundle.
Dave Wade-Stein
Works for me with a command line app run from a shell on OS X 10.4 (sorry, I don't have anything more recent to hand right now)...
Matthew Slattery
A: 

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