Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read /proc program

Tags:

c

I am trying to write a script that has a function to get process details.

So far I have

#include <stdio.h>
#include <string.h>
#include <ctype.h>

char* getField(FILE* file, char* prop, int len){
 char line[100], *p;

 while(fgets(line, 100, file)) {
     if(strncmp(line, prop, len) != 0)
           continue;

     p = line + len + 1;
     while(isspace(*p)) ++p;

     break;
 }

 return p;
}

int main(int argc, char *argv[]) {

  char tgid[40], status[40], *s, *n;
  FILE* statusf;

  printf("Please Enter PID\n");

  if (fgets(tgid, sizeof tgid, stdin)) {
    //Remove new line 
    strtok(tgid, "\n");
    snprintf(status, 40, "/proc/%s/status", tgid);

    statusf = fopen(status, "r");
    if(!statusf){
      perror("Error");
      return 0;
    }

    s = getField(statusf, "State:", 6);
    n = getField(statusf, "Name:", 5);

    printf("State: %s\n", s);
    printf("Name: %s\n", n);

  }else{
    printf("Error on input");
  }

  fclose(statusf);
  return 1;
}

I am still finding the pointers and memory a bit fuzzy. When I run this script without

n = getField(statusf, "Name:", 5);

I get the correct output ( eg. S - Sleeping );

But when I call the function to get the process name I seem to get the same out put for both eg.

State: ntary_ctx Name: ntary_ctx

And that isn't even the right name. I think the issue must be the functions variables are keeping there value. But I thought that when a function return its memory is then pop off the stack.

like image 368
David Kirwan Avatar asked Sep 16 '26 00:09

David Kirwan


1 Answers

Code is retuning a pointer to a local variable.
That is not valid - it is undefined behavior (UB). @stark
That explains the "I seem to get the same out put for both", as one possible UB is that the same buffer is re-used. Another possibility is that code crashes, amongst other candidates.

// Bad code
char* getField(FILE* file, char* prop, int len){
 char line[100], *p;
 ...
 p = line + len + 1;
 ...
 return p;  // `p` points to `line[]`
}

Code needs to make a copy. Could do this by allocation or passing in a destination as shown below.

char* getField(FILE* file, char *dest, const char* prop, int len){
  if (problem) return NULL;
  ...
  return strcpy(dest, p);
}

// Example call
char prop_state[100];
if (getField(statusf, prop_state, "State:", 6)) Success();
else Handle_Problem();
...
char prop_name[100];
if (getField(statusf, prop_name, "Name:", 6)) Success();
...

Better code would pass in the size of dest so getField() could handle that

char* getField(FILE* file, char *dest, size_t size, const char* prop, int len){
  ... 
  if (strlen(p) >= size) return NULL;  // Not enough room
  return strcpy(dest, p);
}

// usage
if (getField(statusf, prop_state, sizeof prop_state, "State:", 6)) Success();
...
like image 198
chux - Reinstate Monica Avatar answered Sep 17 '26 15:09

chux - Reinstate Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!