Thread: Issue with reading /proc/<PID>/status

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Issue with reading /proc/<PID>/status

    More specifically getting the file size is my issue, this is what I got:
    Code:
    	sprintf( path, "/proc/%s/status", ent->d_name );
    	file = fopen(path,"r");
    	if ( !file ) {
    		if ( err ) *err = errno;
    		proc_glance_shut( glance );
    		return NULL;
    	}
    	fseek( file, 0, SEEK_END );
    	if ( notice->name_size < (need = ftell(file)) ) {
    ...
    	if ( need ) {
    		fseek( file, 0, SEEK_SET );
    		fscanf( file, "%s", notice->name );
    		fscanf( file, "%s", notice->name );
    	}
    I have code that reads the name after that but it always comes out as '(null)' when I pass it to printf, any ideas what I'm doing wrong?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You might want to consider parsing /proc/<PID>/stat instead as it is supposed to be more machine-readable (with say, scanf or sscanf) whereas /proc/<PID>/status is supposed to be more human-readable.

    If you do want to parse /proc/<PID>/status, I don't see why you need the file size: just read line by line and parse with say, sscanf into a mapping of field name/value pairs, then extract the value corresponding to the field name that you want.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by laserlight View Post
    You might want to consider parsing /proc/<PID>/stat instead as it is supposed to be more machine-readable (with say, scanf or sscanf) whereas /proc/<PID>/status is supposed to be more human-readable.

    If you do want to parse /proc/<PID>/status, I don't see why you need the file size: just read line by line and parse with say, sscanf into a mapping of field name/value pairs, then extract the value corresponding to the field name that you want.
    I needed the size as a work around for lack of ability to limit number of characters read into the variable without doing complicated code for fread instead, I didn't know about stat, I simply looked for a means to get the executable name via google, status is what I found in the results, I'll look into it another day, tonight I need some sleep

  4. #4
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338

    Cool Never read it...

    Quote Originally Posted by laserlight View Post
    You might want to consider parsing /proc/<PID>/stat instead as it is supposed to be more machine-readable (with say, scanf or sscanf) whereas /proc/<PID>/status is supposed to be more human-readable.

    If you do want to parse /proc/<PID>/status, I don't see why you need the file size: just read line by line and parse with say, sscanf into a mapping of field name/value pairs, then extract the value corresponding to the field name that you want.
    I would listen...
    "without goto we would be wtf'd"

  5. #5
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by awsdert View Post
    I needed the size as a work around for lack of ability to limit number of characters read into the variable without doing complicated code for fread instead, I didn't know about stat, I simply looked for a means to get the executable name via google, status is what I found in the results, I'll look into it another day, tonight I need some sleep
    Quote Originally Posted by Structure View Post
    I would listen...
    What part of my message says I'm not listening? I needed sleep so I went to sleep, that is NOT ignoring, it is putting it off until I'm not about to drop into an unconscience state, like now

  6. #6
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    What part of my message says I'm not listening?
    none of it.
    "without goto we would be wtf'd"

  7. #7
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Structure View Post
    none of it.
    Then what was the point of the post?

    Anyways I've tried both now but the my problem keeps coming back to getting the file size, I've tried this:
    Code:
    size_t file_get_size( int *err, char const *path ) {
    	int fd;
    	off_t size;
    	errno = EXIT_SUCCESS;
    	if ( (fd = open(path,O_RDONLY)) < 0 ) {
    		if ( err ) *err = errno;
    		return 0;
    	}
    	if ( (size =  lseek( fd, 0, SEEK_END )) <= 0 ) {
    		if ( err ) *err = errno;
    	}
    	close( fd );
    	return (size > 0) ? size : 0;
    }
    But somehow lseek is saying I'm giving and invalid argument or at least that is where I detect the error value changing anyways

    Edit: I've tried looking at the man page also but nothing I've read indicates an issue
    Last edited by awsdert; 01-22-2020 at 06:03 AM. Reason: didn't realise the forum would still remember the multiquote state after leaving it

  8. #8
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    I really didn't understand what you really want.
    Take a look at procfs manpage to see what /proc/[pid]/stat offer. Maybe you want something like /proc/[pid]/statm (notice the 'm' at the end).
    BTW: procfs manpage will give you all entries on procfs you can use.

  9. #9
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by flp1969 View Post
    I really didn't understand what you really want.
    Take a look at procfs manpage to see what /proc/[pid]/stat offer. Maybe you want something like /proc/[pid]/statm (notice the 'm' at the end).
    BTW: procfs manpage will give you all entries on procfs you can use.
    no I do not want statm, at least not yet anyways, stat or status are the only suitable ones, atm I need to get the executable name but I also need to get the parent pid later (will be using for filtering), unfortunatly both have poor design, neither declares the length of the executable name so I have to get the file size just to prevent buffer overrun when I read the name, if I can't do that then I won't be able to safely access the info further on from there either

  10. #10
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by awsdert View Post
    no I do not want statm, at least not yet anyways, stat or status are the only suitable ones, atm I need to get the executable name but I also need to get the parent pid later (will be using for filtering), unfortunatly both have poor design, neither declares the length of the executable name so I have to get the file size just to prevent buffer overrun when I read the name, if I can't do that then I won't be able to safely access the info further on from there either
    Since you want to allocate the right amount of memory to read the "executable" name, you do know scanf() can allocate the buffer dynamically, don't ya?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main( void )
    {
      char *buffer;
    
      scanf( "%ms", &buffer );
    
      printf( "%s (len=%zu bytes)\n", buffer, strlen( buffer ) + 1 );
    
      free( buffer );
    }
    Compiling and linking:
    Code:
    $ cc -O2 -o test test.c
    $ ./test <<< 'ffmpeg'
    ffmpeg (len=7 bytes)
    Last edited by flp1969; 01-22-2020 at 07:41 AM.

  11. #11
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    There's also /proc/<PID>/exename if you only want the executable name:

    Code:
    $ cat /proc/self/exename
    /usr/bin/bash
    I think you'll have a problem finding the length of any file under /proc because their contents are generated on the fly by the kernel.

    I would follow laserlight's advice of reading the file line by line and parsing it as you go (though with exename the contents is only the name of the executable, so there's no parsing involved). If you still want to parse /proc/<PID>/status, it's pretty easy to limit how many characters are read with scanf:

    Code:
    char buf[1000];
    fgets(buf, sizeof buf, file);
    sscanf(buf, "%100[^:]:%*[\t]%100[^\n]", key, value);
    (Not tested.)

    That will read a whole line and then limit the key (e.g., "Name") and value (e.g., "cat") to 100 characters each. It also properly handles spaces inside the executable name too, if the name happens to include spaces. (It assumes the key doesn't contain spaces, which is true for /proc/<PID>/status.)

    (Of course, you'll need to check to see if fgets() read a complete line (if the file contains line longer than the buffer, then fgets() won't read the whole line). If the string doesn't end in a newline character, then the line in the file was too long. You'll have to decide how best to handle that situation.)

  12. #12
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by flp1969 View Post
    Since you want to allocate the right amount of memory to read the "executable" name, you do know scanf() can allocate the buffer dynamically, don't ya?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main( void )
    {
      char *buffer;
    
      scanf( "%ms", &buffer );
    
      printf( "%s (len=%zu bytes)\n", buffer, strlen( buffer ) + 1 );
    
      free( buffer );
    }
    Compiling and linking:
    Code:
    $ cc -O2 -o test test.c
    $ ./test <<< 'ffmpeg'
    ffmpeg (len=7 bytes)
    true but inefficient, the app I'm working on has to go through every process looking for specific ones, having to keep allocating memory and freeing it for each process name will just slow it down hence I need to get the file size so I can just increase a shared memory as and when I need to, if I could get the length of the name before hand I would've been fine with that but alas there is no such option so file size it is

  13. #13
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by christop View Post
    There's also /proc/<PID>/exename if you only want the executable name:

    Code:
    $ cat /proc/self/exename
    /usr/bin/bash
    I think you'll have a problem finding the length of any file under /proc because their contents are generated on the fly by the kernel.

    I would follow laserlight's advice of reading the file line by line and parsing it as you go (though with exename the contents is only the name of the executable, so there's no parsing involved). If you still want to parse /proc/<PID>/status, it's pretty easy to limit how many characters are read with scanf:

    Code:
    char buf[1000];
    fgets(buf, sizeof buf, file);
    sscanf(buf, "%100[^:]:%*[\t]%100[^\n]", key, value);
    (Not tested.)

    That will read a whole line and then limit the key (e.g., "Name") and value (e.g., "cat") to 100 characters each. It also properly handles spaces inside the executable name too, if the name happens to include spaces. (It assumes the key doesn't contain spaces, which is true for /proc/<PID>/status.)

    (Of course, you'll need to check to see if fgets() read a complete line (if the file contains line longer than the buffer, then fgets() won't read the whole line). If the string doesn't end in a newline character, then the line in the file was too long. You'll have to decide how best to handle that situation.)
    man page never mentioned exename so I never even tried, does it provide a length at all?
    as for the fgets idea I'll give it a try, probably have to put it in a loop to get the whole line but still better than a buffer overflow

  14. #14
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by awsdert View Post
    man page never mentioned exename so I never even tried, does it provide a length at all?
    as for the fgets idea I'll give it a try, probably have to put it in a loop to get the whole line but still better than a buffer overflow
    There is no 'exename', but there is a 'comm':

    Issue with reading /proc/&lt;PID&gt;/status-untitled-jpg

    Just the executable name...

  15. #15
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by flp1969 View Post
    There is no 'exename', but there is a 'comm':

    Issue with reading /proc/&lt;PID&gt;/status-untitled-jpg

    Just the executable name...
    Hehe, that's what I get for testing stuff with Cygwin instead of a real Linux system. Yep, it's "exename" in Cygwin but "comm" in Linux.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading /proc/stat and passing file to func
    By bedtime in forum Linux Programming
    Replies: 1
    Last Post: 03-10-2019, 10:45 PM
  2. /proc/pid/mem Reading
    By redcrusher in forum C Programming
    Replies: 1
    Last Post: 01-14-2012, 11:38 AM
  3. Reading a proc file in user space
    By Fillis52 in forum C Programming
    Replies: 3
    Last Post: 12-06-2010, 11:03 AM
  4. My Status Bar Issue. Need Help.
    By userpingz in forum Windows Programming
    Replies: 8
    Last Post: 10-21-2009, 08:42 AM
  5. Reading /proc
    By crisis in forum Linux Programming
    Replies: 3
    Last Post: 11-07-2007, 04:46 AM

Tags for this Thread