Search code examples
cnetwork-programmingconky

Network Programming in C for name of running process for established connection


I am new to C network programming. I am trying to code a patch for my conky to display something like "netstat -pan --inet". Conky's inbuilt tcp_mon to not include process name.

Initially I did this using netstat and awk but my script got a performance hit using this approach. So I am trying to code it in C directly. The output from netstat looks something like this

Proto Recv-Q Send-Q Local Address           Foreign Address         State           PID/Program name    
tcp        0      0 0.0.0.0:17500           0.0.0.0:*               LISTEN         1042/dropbox        
tcp        0      0 192.168.0.1:3333        24.244.4.104:2222     ESTABLISHED    1225/chrome 

I am interested in displaying the last column "PID/Program" I look at the sockets library but I did not come across anything regarding the process name or its pid. I am on Archlinux by the way

So my questions are 1) Am I looking at the right place ? If not, where ? 2) Is there a better way of doing this ?


Solution

  • At least when using a recent Linux kernel it is possible to read out a process' name (as defined by a comment to the OP) using prctl():

    #include <sys/prctl.h>
    #include <stdio.h> /* for perror() */
    ...
    
    char [17] = proc_name = {0}; /* the buffer provided shall at least be 16+1 bytes long */
    
    if (-1 == prctl(PR_GET_NAME, proc_name, ...))
      perror("prctl(PR_GET_NAME, ...)"); 
    

    One should be aware that a maximum of 16 bytes is returned, and that in this case no trailing 0-termination will be added. So initialising the character array to passed to prctl()to all 0 is a good idea.

    It is also possible to set this "name" by doing:

    char [17] = proc_name = "new name"; /* The name will be truncated to 16 bytes */
    
    if (-1 == prctl(PR_SET_NAME, proc_name, ...))
      perror("prctl(PR_SET_NAME, ...)"); 
    

    The relevant excerpts from prctl()'s man pages are:

    PR_SET_NAME (since Linux 2.6.9)

    Set the process name for the calling process, using the value in the location pointed to by (char *) arg2. The name can be up to 16 bytes long, and should be null-terminated if it contains fewer bytes.

    PR_GET_NAME (since Linux 2.6.11)

    Return the process name for the calling process, in the buffer pointed to by (char *) arg2. The buffer should allow space for up to 16 bytes; the returned string will be null-terminated if it is shorter than that.


    Please note that the "process name"-value as described above is different form the command line for a process. The latter can be found in /proc/<pid>/cmdline.

    It is stored in there as 0-terminated character array.


    A convenient way to read out /proc is to use the tool kit provided by PROCPS.


    Update:

    After taking a look at netstat's sources it seem it takes the process's name from /proc/<pid>/cmdline. The relevant pids come from scanning /proc/<pid>/fd looking for matches to socket:*.