views:

2643

answers:

5

In Windows environment there is an API to obtain the path which is running a process. Is there something similar in Unix / Linux?

Or is there some other way to do that in these environments?

+4  A: 

If you want the path of the current executable, look at /proc/$PID/exe, which is a symlink to it

jpalecek
Linux-only, though.
kch
+3  A: 

In Linux every process has its own folder in /proc. So you could use getpid() to get the pid of the running process and then join it with the path '/proc' to get the folder you hopefully need.

Here's a short example in Python:

import os
print os.path.join('/proc', str(os.getpid()))

Here's the example in ANSI C as well:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>


int
main(int argc, char **argv)
{
    pid_t pid = getpid();

    fprintf(stdout, "Path to current process: '/proc/%d/'\n", (int)pid);

    return EXIT_SUCCESS;
}

Compile it with:

gcc -Wall -Werror -g -ansi -pedantic process_path.c -oprocess_path
hyperboreean
good, but i need C ANSI usage. Tanks
lsalamon
+1  A: 

In unix/linux, you can use the ps command to get the path of each process:

ps aux

I think this might be what you are looking for.

jonstjohn
I think the question was looking for an API rather than a command.
Stephen Doyle
but I believe this only occurs if the process was initiated with the full path, but worth. Thanks
lsalamon
+2  A: 

There's no "guaranteed to work anywhere" method.

Step 1 is to check argv[0], if the program was started by its full path, this would (usually) have the full path. If it was started by a relative path, the same holds (though this requires getting teh current working directory, using getcwd().

Step 2, if none of the above holds, is to get the name of the program, then get the name of the program from argv[0], then get the user's PATH from the environment and go through that to see if there's a suitable executable binary with the same name.

Note that argv[0] is set by the process that execs the program, so it is not 100% reliable.

Vatine
+5  A: 

A little bit late, but all the answers were specific to linux.

If you need also unix, then you need this:

char * getExecPath (char * path,size_t dest_len, char * argv0)
{
    char * baseName = NULL;
    char * systemPath = NULL;
    char * candidateDir = NULL;

    /* the easiest case: we are in linux */
    if (readlink ("/proc/self/exe", path, dest_len) != -1)
    {
        dirname (path);
        strcat  (path, "/");
        return path;
    }

    /* Ups... not in linux, no  guarantee */

    /* check if we have something like execve("foobar", NULL, NULL) */
    if (argv0 == NULL)
    {
        /* we surrender and give current path instead */
        if (getcwd (path, dest_len) == NULL) return NULL;
        strcat  (path, "/");
        return path;
    }


    /* argv[0] */
    /* if dest_len < PATH_MAX may cause buffer overflow */
    if ((realpath (argv0, path)) && (!access (path, F_OK)))
    {
        dirname (path);
        strcat  (path, "/");
        return path;
    }

    /* Current path */
    baseName = basename (argv0);
    if (getcwd (path, dest_len - strlen (baseName) - 1) == NULL)
        return NULL;

    strcat (path, "/");
    strcat (path, baseName);
    if (access (path, F_OK) == 0)
    {
        dirname (path);
        strcat  (path, "/");
        return path;
    }

    /* Try the PATH. */
    systemPath = getenv ("PATH");
    if (systemPath != NULL)
    {
        dest_len--;
        systemPath = strdup (systemPath);
        for (candidateDir = strtok (systemPath, ":"); candidateDir != NULL; candidateDir = strtok (NULL, ":"))
        {
            strncpy (path, candidateDir, dest_len);
            strncat (path, "/", dest_len);
            strncat (path, baseName, dest_len);

            if (access(path, F_OK) == 0)
            {
                free (systemPath);
                dirname (path);
                strcat  (path, "/");
                return path;
            }
        }
        free(systemPath);
        dest_len++;
    }

    /* again someone has use execve: we dont knowe the executable name; we surrender and give instead current path */
    if (getcwd (path, dest_len - 1) == NULL) return NULL;
    strcat  (path, "/");
    return path;
}
Hiperion