Parsing proc / pid / cmdline to get function parameters
I am trying to extract the parameter with which the application was called using the data inside the cmdline.
If I start my application instance like this:
myapp 1 2
and then cat cmdline 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 I only get the application name and no parameters ...
Update copied from answer:
Well, now my question is, how do I read the cmdline file without stopping at the first NULL character ...
fopen(cmdline, "rb")
does nothing, so ...
source to share
All command line options (what came out as an array argv[]
) are actually zero-delimited 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 all "got stuck" together ( cat
ignoring invalid NULLs) and why yours cout
stopped after the first command line argument (process name), since it thought the process name was a null string and stopped looking for more characters at that point.
Handling command line arguments
You have a couple of options for handling command line arguments. If you just want the whole command line to be one giant line, loop from 0 to (numRead - 2)
(where numRead
is the number of characters read) and replace any NULL bytes with (curByte == 0)
spaces. Then just make sure the last character is also a NULL byte (in case things got truncated due to a fixed size buffer).
If you want an array with all the arguments, you need to be more creative. One option is to loop from 0 to (numRead - 1)
and all NULL bytes you find. Then allocate an array of char*
that length. Then step back through the command line, setting the start of each line (i.e., the first byte in the array plus each byte following a NULL byte) for consecutive array elements char*
.
Just be aware that since you are reading a fixed-size buffer, anything outside of that buffer will be truncated. So remember that whatever you do, you probably need to manually ensure that the end of the last line ends with a NULL termination, otherwise most of the string processing functions won't know where the line ends and will go on forever.
source to share