tags:

views:

242

answers:

2

Hello all,

I'm trying to extract the parameter with which an app was called by using the data inside cmdline.

If I start an application instance like this:

myapp 1 2

and then cat the cmdline of myapp I will see something like myapp12.

I needed to extract these values and I used this piece of code to do it


pid_t proc_id = getpid();

sprintf(buf,"/proc/%i/cmdline",proc_id);

FILE * pFile;
pFile = fopen (buf,"r");
if (pFile!=NULL)
{
    fread(buf,100,100,pFile);
    cout << "PID " << proc_id << endl;
    string str = buf;
    cout << buf << endl;
    size_t found=str.find_last_of("/\\");
    cout << " file: " << str.substr(found+1) << endl;

    fclose (pFile);
}


But what I am getting is only the app name and no parameters...

Any ideas?

Cheers

+2  A: 

All of the command line parameters (what would come through as the argv[] array) are actually null-separated strings in /proc/XXX/cmdline.

abatkin@penguin:~> hexdump -C /proc/28460/cmdline
00000000  70 65 72 6c 00 2d 65 00  31 20 77 68 69 6c 65 20  |perl.-e.1 while |
00000010  74 72 75 65 00                                    |true.|

This explains why when you cat'ed cmdline they were all "stuck" together (cat ignored the invalid NULL characters) and why your cout stopped after the first command line argument (the process name) since it thought that the process name was a null-terminated string and stopped looking for more characters at that point.

Processing Command Line Arguments

To process the command line arguments, you have a couple options. If you just want the entire command line as one giant string, loop from the 0 to (numRead - 2) (where numRead is the number of characters read) and replace any NULL bytes (curByte == 0) with spaces. Then just make sure to set the last character to be a NULL byte too (in case things got truncated due to the fixed-size buffer).

If you instead want an array with all of the arguments, you need to be more creative. One option would be to loop from 0 to (numRead - 1) and could all of the NULL bytes that you find. Then allocate an array of char*'s of that length. Then loop back through the command line, setting the beginning of every string (i.e. the first byte in the array, plus each byte following a NULL byte) to consecutive elements of the array of char*'s.

Just know that since you read to a fixed-size buffer, anything beyond that buffer would be truncated. So remember that whatever you do, you probably need to manually make sure that the end of the last string ends up being NULL terminated, otherwise most string handling functions won't know where the string ends and will keep on going forever.

Adam Batkin
I saw that already ;)The problem with read or fread is that they stop at the first NULL and don't get the rest of the parameters...how do I get around this?Cheers
Andre
`read` and `fread` don't stop, it is the `cout` (or possibly the `string` construction from the buffer, not sure) that stop. Check the return value from your `fread` and you will see what I mean.
Adam Batkin
Adam, this is my thanks to you for your help.I was getting the programmers syndrome and wanted to destroy the escape key ;).Your suggestion was spot on. Once again, thanks ;)
Andre
A: 

well, my question now seems to be how do I read the cmdline file without it stopping at the first NULL character...

fopen(cmdline, "rb") doesn't do anything else so...

arghhhh

This is so ***** simple...

I need help ;)

Andre