0

I'm trying to display the details of each process, by redirecting the output of 'ps' command. I have redirected the ps output to a file. I'm reading from it and displaying the Pid and Command using fscanf. But I see that I get some lines duplicated, and in some cases a negative value for the Pids.

void TR69_DM_GetProcDetails(char *FileName, int32_t *ProcCount, struct ProcessInfo *ProcVar)
{
    char CharBuf[BUF_SIZE] ;
    int32_t i = 0;

    int Pid;
    char Cmd[100];

    FILE *FileDesc;
    FileDesc = fopen (FileName, "r");

    printf("\nFile pointer %ld\n", ftell(FileDesc));
    fscanf (FileDesc, "%[^\n]\n", CharBuf);
    puts(CharBuf);

    printf("\nFile pointer %ld\n", ftell(FileDesc));

    while ( EOF != fscanf (FileDesc, "%*s %lu %*d %*d %*s %*s %*s %s", &Pid, Cmd))
    {
        printf("\n PID is %d and cmd is %s", Pid, Cmd);
    //  i++;
    }

}

and I get the following output sample:

 PID is 2104 and cmd is /usr/lib/indicator-datetime/indicator-datetime-service
 PID is 2107 and cmd is /usr/lib/indicator-messages/indicator-messages-service
 PID is 2114 and cmd is /usr/lib/indicator-session/indicator-session-service
 PID is 2134 and cmd is /usr/lib/geoclue/geoclue-master
 PID is 2142 and cmd is gnome-screensaver
 PID is 2145 and cmd is /usr/lib/gnome-disk-utility/gdu-notification-daemon
 PID is 2342 and cmd is /usr/bin/python
 PID is 2342 and cmd is /usr/bin/python
 PID is 4316 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is -4 and cmd is /sbin/dhclient
 PID is 4444 and cmd is /usr/sbin/ntpd
 PID is 4444 and cmd is /usr/sbin/ntpd
 PID is 4444 and cmd is /usr/sbin/ntpd
 PID is 4444 and cmd is /usr/sbin/ntpd
 PID is 113 and cmd is /usr/sbin/ntpd
 PID is 113 and cmd is /usr/sbin/ntpd
 PID is 5411 and cmd is sshd:
 PID is 5411 and cmd is sshd:
 PID is 5411 and cmd is sshd:
 PID is 5584 and cmd is sshd:
 PID is 5584 and cmd is sshd:
 PID is 5585 and cmd is -bash
 PID is 6790 and cmd is /usr/lib/firefox-4.0.1/firefox-bin
 PID is 7007 and cmd is /usr/lib/firefox-4.0.1/plugin-container
 PID is 7007 and cmd is /usr/lib/firefox-4.0.1/plugin-container
 PID is 7007 and cmd is /usr/lib/firefox-4.0.1/plugin-container
 PID is 6790 and cmd is /usr/lib/firefox-4.0.1/plugin-container
 PID is 6790 and cmd is /usr/lib/firefox-4.0.1/plugin-container
 PID is 6790 and cmd is /usr/lib/firefox-4.0.1/plugin-container
 PID is 7023 and cmd is /usr/lib/nspluginwrapper/i386/linux/npviewer.bin
 PID is 7023 and cmd is /usr/lib/nspluginwrapper/i386/linux/npviewer.bin
 PID is 7023 and cmd is /usr/lib/nspluginwrapper/i386/linux/npviewer.bin
 PID is 7023 and cmd is /usr/lib/nspluginwrapper/i386/linux/npviewer.bin
 PID is 7023 and cmd is /usr/lib/nspluginwrapper/i386/linux/npviewer.bin
 PID is 8390 and cmd is man
 PID is 8390 and cmd is man
 PID is 8402 and cmd is pager
 PID is 8402 and cmd is pager
 PID is 8827 and cmd is ping
 PID is 8827 and cmd is ping
 PID is 8869 and cmd is bash
 PID is 8907 and cmd is bash
 PID is 12637 and cmd is cat
 PID is 12637 and cmd is cat
 PID is 15164 and cmd is tftp
 PID is 15185 and cmd is vim
 PID is 15185 and cmd is vim
 PID is 16827 and cmd is telnet
 PID is 16827 and cmd is telnet
 PID is 17117 and cmd is sshd:
 PID is 17117 and cmd is sshd:
 PID is 17117 and cmd is sshd:
 PID is 17226 and cmd is sshd:
 PID is 17226 and cmd is sshd:
 PID is 17227 and cmd is -sh
 PID is 18120 and cmd is su
 PID is 18127 and cmd is bash
 PID is 18896 and cmd is sshd:
 PID is 18896 and cmd is sshd:
 PID is 18896 and cmd is sshd:
 PID is 19069 and cmd is sshd:
 PID is 19069 and cmd is sshd:
 PID is 19070 and cmd is -sh
 PID is 20313 and cmd is gedit
 PID is 20313 and cmd is gedit
 PID is 20313 and cmd is gedit
 PID is 20334 and cmd is ssh
 PID is 20334 and cmd is ssh
 PID is 20337 and cmd is [kworker/1:1]
 PID is 20341 and cmd is su
 PID is 20349 and cmd is bash
 PID is 20371 and cmd is [kworker/0:1]
 PID is 20375 and cmd is [kworker/0:2]
 PID is 20377 and cmd is [kworker/1:0]
 PID is 21342 and cmd is [kjournald]
 PID is 23384 and cmd is /opt/Adobe/Reader9/Reader/intellinux/bin/acroread
 PID is 23384 and cmd is /opt/Adobe/Reader9/Reader/intellinux/bin/acroread
 PID is 23495 and cmd is gnome-terminal
 PID is 23498 and cmd is gnome-pty-helper
 PID is 23499 and cmd is bash
 PID is 26446 and cmd is ssh
 PID is 26446 and cmd is ssh
 PID is 26733 and cmd is sshd:
 PID is 26733 and cmd is sshd:
 PID is 26843 and cmd is -bash
 PID is 26943 and cmd is sshd:
 PID is 26943 and cmd is sshd:
 PID is 27036 and cmd is sshd:
 PID is 27036 and cmd is sshd:
 PID is 27036 and cmd is sshd:
 PID is 27052 and cmd is /usr/lib/openssh/sftp-server
 PID is 27149 and cmd is sshd:
 PID is 27149 and cmd is sshd:
 PID is 27150 and cmd is -bash
 PID is 27734 and cmd is ssh
 PID is 27734 and cmd is ssh
 PID is 28265 and cmd is bin/TR69_DM
 PID is 0 and cmd is bin/TR69_DM
 PID is 28266 and cmd is ps
 PID is 28266 and cmd is ps
 PID is 29510 and cmd is su
 PID is 29510 and cmd is su
 PID is 29517 and cmd is bash
 PID is 29951 and cmd is minicom
 PID is 30056 and cmd is bash
 PID is 30293 and cmd is bash
 PID is 30329 and cmd is ssh
 PID is 30329 and cmd is ssh
 PID is 30597 and cmd is bash
 PID is 30632 and cmd is ssh
 PID is 30632 and cmd is ssh
 PID is 31508 and cmd is bash

What might have went wrong?

Christy George
  • 309
  • 1
  • 5
  • 14

1 Answers1

3

fscanf() returns the number of assignments made. Checking against EOF is insufficient as some assignments may have been made and remaining ones not, meaning subsequent code would be processing stale or uninitialized values. The following loop will stop processing at the first line when the format is unexpected and avoid stale values:

while ( 2 == fscanf (FileDesc, "%*s %lu %*d %*d %*s %*s %*s %s", &Pid, Cmd))
{
}

An improved solution would use fgets() to read a line and then use sscanf() to parse the read line. This will allow you to detect EOF and allow multiple attempts to parse the line using different formats:

char line[1024];
while (fgets(line, sizeof(line), stdin))
{
    if (2 == sscanf (line, "%*s %lu %*d %*d %*s %*s %*s %s", &Pid, Cmd))
    {
    }
    else if (2 == sscanf (line, "some-other-format", &Pid, Cmd))
    {
    }
    else
    {
        fprintf(stderr, "Unable to parse '%s'\n", line);
    }
}

Additionally, prevent potential buffer overrun by specifying the maximum number of characters that sscanf() should write to Cmd. This should be one less than the size of Cmd, leaving room for the terminating null character. For example:

if (2 == sscanf(line, "%lu %255s", &Pid, Cmd))
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • Totally going to up vote this, but I think you meant to use `sscanf` and `line` in the second snippet. (if I followed your logic correctly, which is always a crapshoot with me). – WhozCraig Feb 21 '14 at 11:43
  • Using `scanf` safely and correctly is nontrivial. Nice answer. – ajay Feb 21 '14 at 12:02