tags:

views:

204

answers:

2

I want to run the following command from a C program to read the system's CPU and memory use:

ps aux|awk 'NR > 0 { cpu +=$3; ram+=$4 }; END {print cpu,ram}'

I am trying to pass it to the execl command and after that read its output:

execl("/bin/ps", "/bin/ps", "aux|awk", "'NR > 0 { cpu +=$3; ram+=$4 }; END {print cpu,ram}'",(char *) 0);

But in the terminal I am getting the following error:

ERROR: Unsupported option (BSD syntax)

I would like to know how to properly pass awk as argument to execl?

+1  A: 

You can't do this here this way.

The problem is that you want to execute several commands. execl is for executing a single command. The statement you have is using shell syntax (notably the | )

You will have better luck combining it all up in a single string and using the system(3) call.

Will Hartung
Well, I agree with the problem diagnosis; the solution, though, is not clearly correct. I would expect to use popen() so that the launching program can read the output.
Jonathan Leffler
A: 

Instead of running awk and parsing awk's output, you can do the filtering and summation in C, which often can quickly become much more convenient. (It's about the same for the exact command you have here.)

#include <errno.h>
#include <stdio.h>

void ps_cpumem(FILE* f, double* cpu_total, double* mem_total) {
  for (;;) {
    char buf[2000];
    if (!fgets(buf, sizeof buf, f)) {
      return;
    }
    double cpu, mem;
    if (sscanf(buf, "%*s %*s %lf %lf", &cpu, &mem) == 2) {
      *cpu_total += cpu;
      *mem_total += mem;
    }
  }
}

int main() {
  errno = 0;
  FILE* ps = popen("ps aux", "r");
  if (!ps) {
    if (errno == 0) puts("popen: memory allocation failed");
    else perror("popen");
    return 1;
  }
  double cpu = 0, mem = 0;
  ps_cpumem(ps, &cpu, &mem);
  int rc = pclose(ps);
  if (rc == -1) return 1;
  printf("%%cpu: %5.1f\n" "%%mem: %5.1f\n", cpu, mem);
  return 0;
}

However, you can run the full command through popen, as it executes a shell:

FILE* output = popen("ps aux | awk 'NR > 0 { cpu +=$3; ram+=$4 }; END {print cpu,ram}'", "r");
// read from output to do with as you like
Roger Pate