Friday, December 2, 2011

How to get process full name programmatically (Solaris)

In the previous post I described how to get the command line and the full name of process executable file on Linux. However, the described solution does not work on Solaris.

Solaris has the /proc pseudo-filesystem directory as well, but it’s structure is different.

On Solaris 10 there is a link /proc/PID/path/a.out which points to the executable file. So it’s enough to call readlink function.
Prior to Solaris 10, things are more complex. I haven’t found a reliable way to get a full name of the executable file. But the following notes may be useful.

There is a binary /proc/<PID>/psinfo file, which stores data as in struct psinfo (#include <procfs.h>). This struct has pr_fname and pr_psargs fields. But it seems that pr_fname usually holds the file name of executable only, without the absolute path. The second problem is that both pr_fname and pr_psargs can be truncated.

There is a function called getexecname(), which returns file name of the executable. But it has the same problem: it may hold the file name part only, without the absolute path. Manual recommends getcwd function which returns the current working directory. However, current working directory may differ from the starting directory so this solution is not reliable.

So the following program illustrates all of these approaches:

#include <stdio.h>
#include <unistd.h>
#include <procfs.h>
#include <stdlib.h>

int main() {
ssize_t linknamelen;
FILE *f;
char linkname[256], filename[256];
pid_t pid = getpid();

/* try to readlink the file /proc/PID/path/a.out */
sprintf(linkname, "/proc/%d/path/a.out", pid);
linknamelen = readlink(linkname, filename, sizeof(filename) / sizeof(*filename) - 1);
if (linknamelen > 0) {
 filename[linknamelen] = 0;
 printf("Full name is %s\n", filename);
} else {
 getcwd(filename, sizeof(filename) / sizeof(*filename) - 1);
 printf("Current directory is %s. Name is %s\n", filename, getexecname());
}

/* read the command line from /proc/PID/psinfo */
sprintf(filename, "/proc/%d/psinfo", pid);

f = fopen(filename, "r");
if (f) {
psinfo_t info;
if (fread(&info, sizeof(info), 1, f) > 0) {
    printf("fname=%s, args=%s\n", info.pr_fname, info.pr_psargs);
}
fclose(f);
}

return 0;
}

No comments:

Post a Comment