Wednesday, November 30, 2011

How to get process full name programmatically (Linux)

In the previous post I described Windows API that can be used to get command line and full path of the EXE file of the process.
This post describes how to get the same information on Linux.

There is a  pseudo-filesystem directory called “/proc/[PROCESS-ID]”,  which contains a set of useful files that describe the process with PROCESS-ID. In our case we may use files “/proc/[PROCESS-ID]/cmdline” and “/proc/[PROCESS-ID]/exe”.

/proc/[PROCESS-ID]/cmdline” is a text file which contains the command line. Note that arguments are separated by 0 character, so if you just fgets / puts you see program name only.
/proc/[PROCESS-ID]/exe” is a symbolic link to executed command. To read the value of symbolic link you may use readlink (note that readlink may not append 0 character to the string!).

So the code may look like:

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

void get_command_line() {
 FILE *f;
 char file[256], cmdline[256] = {0};
 sprintf(file, "/proc/%d/cmdline", getpid());

 f = fopen(file, "r");
 if (f) {
    char *p = cmdline;
    fgets(cmdline, sizeof(cmdline) / sizeof(*cmdline), f);
    fclose(f);

    while (*p) {
     p += strlen(p);
     if (*(p + 1)) {
       *p = ' ';
     }
     p++;
    }
    puts(cmdline);
 } else {
    printf("unable to open file %s\n", file);
 }
}

void get_full_process_name() {
 size_t linknamelen;
 char file[256], cmdline[256] = {0};

 sprintf(file, "/proc/%d/exe", getpid());
 linknamelen = readlink(file, cmdline, sizeof(cmdline) / sizeof(*cmdline) - 1);
 cmdline[linknamelen + 1] = 0;

 printf("Full name is %s\n", cmdline);
}

To get more information:

man proc
man 2 getpid
man 2 readlink

And now a few notes about links. Suppose that you compile the source to “a.out” file and created a soft link called “aaa” to it:
ln -s ./a.out aaa

Now if you run
./aaa
the result is:
Command line: aaa
Full name: /home/ivbel/my_tests/a.out

And if you create a hard link like
link ./a.out hard_a

The result of running hard_a is
Command line: hard_a
Full name: /home/ivbel/my_tests/hard_a 

1 comment: