tags:

views:

3814

answers:

8

Hi All, I want to get the full path of the running process (executable) without having root permission using C++ code. Can someone suggest a way to achieve this.

on Linux platforms i can do it by using following way.

char exepath[1024] = {0};
char procid[1024] = {0};
char exelink[1024] = {0};

sprintf(procid, "%u", getpid());

strcpy(exelink, "/proc/");
strcat(exelink, procid);
strcat(exelink, "/exe");

readlink(exelink, exepath, sizeof(exepath));

Here exepath gives us the full path of the executable.

Similarly for windows we do it using

GetModuleFileName(NULL, exepath, sizeof(exepath));  /* get fullpath of the service */

Please help me how to do it on HP-UX since there is no /proc directory in HP-UX.

A: 

Hi All, Problem that i have is executable can be run from any location and that location can be in the PATH variable, so in that scenario printing argv[0] will not work. Thats the reason i found proper solution for other platforms. if you guys can suggest some way to achieve similar result in HP-UX, it will be great.

+1  A: 

I have done this before in a general case. The general idea is to grab argv[0], and do some processing on it:

int main( int argc, char** argv )
{
  string full_prog_path = argv[0];
  if ( full_prog_path[0] == "/" )
  {   // It was specified absolutely; no processing necessary.
  }
  else
  {
    string check_cwd = getcwd();
    check_cwd += argv[0];
    if ( FileExists( check_cwd ) )
    { // It was specified relatively.
      full_prog_path = check_cwd;
    }
    else
    { // Check through the path to find it
      string path = getenv( "PATH" );
      list<string> paths = path.split( ":" );
      foreach( test_path, paths )
      {
        if ( FileExists( test_path + argv[0] ) )
        { // We found the first path entry with the program
          full_prog_path = test_path + argv[0];
          break;
        }
      }
    }
  }

  cout << "Program path: " << full_prog_path << endl;

  return 0;
}

Obviously, this has some assumptions that might break at some point, but it should work for most cases.

Caleb Huitt - cjhuitt
In the simple cases, this is fine. However, it is not reliable. I could write: execl("/path/to/your/program", "../../penguins/rule/the/world", "arg1", (char *)0); and the value of argv[0] bears no resemblance to the name of the executable.
Jonathan Leffler
@Jonathan: Like I said, it has some assumptions but works for most cases. I don't know of any way of handling the scenario you mention in code.
Caleb Huitt - cjhuitt
A: 

Thanks for the reply. Do you see any way we can get the full path using the process ID (of running executable), since this requirement in general for us.

+1  A: 

The earlier answer referring to the Unix Programming FAQ was right. The problem, even with the Linux /proc answer, is that the path to the executable may have changed since the exec(). In fact, the executable may have been deleted. Further complications arise from considering links (both symbolic and hard) -- there may be multiple paths to the same executable. There is no general answer that covers all cases, since there may not be a path remaining, and if there is one it may not be unique.

That said, using argv[0] with some logic, as advocated by cjhuitt earlier, will probably do what you want 99.9% of the time. I'd add a check for a path containing "/" before doing the relative path check (and note, you must do that before any cwd() calls). Note that if your calling program is feeling mischievous, there's a host of things that can be done between fork() and exec() to mess this up. Don't rely on this for anything that could affect application security (like location of configuration files).

mpez0
A: 

Hi All, ACtually i don have option to append argv[0] to getcwd() output, because my code has to detect the excecutable path (which is running). my code to find the full executable path is in some shared library loaded by executable, so i dont really have argv[0] option to use. Only thing that i have is the process id, under which my shared library is loaded. so if someone can suggest a way to use process id and then from that find the executalbe full path, it would be great. As you can see in my initial description i have used way to find full path of executable using process id or directly with some system function (which also uses current process to return result). I see there is one function pstat_getpathname() available on hpux but is restricted to root or equivalent user, but my requirement is any user should be able to get the path (obviously user who is running the process).

Any help would be greatly appreciated.

+1  A: 

For what purpose do you need the executable path? Bear in mind, as I put in my earlier post, that there is no guarantee that a path to the executable will exist, or that it will be unique.

mpez0
+7  A: 

First, I'd like to comment on your Linux solution: it is about 5 times as long as it needs to be, and performs a lot of completely unnecessary operations, as well as using 1024 magic number which is just plain wrong:

$ grep PATH_MAX /usr/include/linux/limits.h 
#define PATH_MAX        4096    /* # chars in a path name */

Here is a correct minimal replacement:

#include <limits.h>
...
  char exepath[PATH_MAX] = {0};
  readlink("/proc/self/exe", exepath, sizeof(exepath));

Second, on HP-UX you can use shl_get_r() to obtain information about all loaded modules. At index 0, you will find information about the main executable. The desc.filename will point to the name of the executable at execve(2) time.

Unfortunately, that name is relative, so you may have to search $PATH, and may fail if the application did putenv("PATH=some:new:path") or if the original exename was e.g. ./a.out and the application has performed chdir(2) since.

Man seems to indicate that "readlink() does not append a null byte to buf. It will truncate the contents (to a length of bufsiz characters), in case the buffer is too small to hold all of the contents."
rpg
+2  A: 
Randy Proctor
This example from HP, combines the standard approaches first,then falling back to pstat:http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=88086d6e1de021106d6e1de02110275d6e10RCRD
pixelbeat