tags:

views:

74

answers:

4

I want the output of the shell command (echo free | grep Mem| awk '{print $2}') collected in a variable so that I can use it in a C program. So I have the code here.

 system("TOTAL=$(echo `free | grep Mem| awk '{print $2}'`)");
 popen("grep -v procs $1 | grep -v free | awk '{USED=TOTAL-$4-$5-$6;print USED}'", "r");

Can I use the variable TOTAL in the same program inside a popen() call as shown above ?

A: 

I do not think that is possible as system forks a shell to run the command and returns after the command completes, essentially killing the shell that it forked as well. Thus any environment variable that was set will be lost as well.

Alan Haggai Alavi
Then how does one achieve this ? I want a value returned by a shell command , and use it at a later stage !
Sharat Chandra
By using `popen` to run the command instead of `system`.
Alan Haggai Alavi
A: 

You need to handle the setting of TOTAL within the same subshell as where you use it; environment variables are not transferred between subprocesses (the only thing that works is a subprocess inheriting its parent process's env-vars). You might do that like this (I removed a bit of useless obfuscation):

FILE *f = popen("TOTAL=$(free | grep Mem | awk '{print $2}');"
        "grep -v procs $1 | grep -v free | "
        "awk '{USED=TOTAL-$4-$5-$6;print USED}'",
        "r");

Note the multi-line string constant. However, I suspect that even that won't work as it seems a confused jumble of different languages. (For example, the $1 looks very suspicious as it is not inside a context that usually works with these things.) You might find it easier to put all that complex script into a proper shell script that you can run, since then you'll be working with fewer languages at once and can debug things in stages rather than all at once…

Donal Fellows
A: 

You could use a FIFO or at least use a simple temp-file.

Tim
+2  A: 

You will need to create a string which contains the complete script that you want run, or you will need to create a script which can be run simply, and then arrange to read the output of that script with popen(). Either is possible; which is easier depends on the level of your scripting skills vs your C programming skills.

char command[4096];

strcpy(command, "TOTAL=$(free | grep Mem| awk '{print $2}')\n");
strcat(command, "grep -v procs $1 | grep -v free |\n");
strcat(command, "awk '{USED=TOTAL-$4-$5-$6;print USED}' TOTAL=$TOTAL\n");

FILE *in = popen(command, "r");

...read the results, etc...

The string operations simplify the first shell script, and then pass the value of TOTAL calculated to awk.

The other way to do it would be to read the output from free | grep Mem | awk '{print $2}' - the value that is TOTAL - from one use of popen(), then build that value into the second command:

char command[4096];

strcpy(command, "free | grep Mem| awk '{print $2}'");
char total[20];
FILE *in1 = popen(command, "r");
...read TOTAL into total...

strcpy(command, "grep -v procs $1 | grep -v free |\n");
strcat(command, "awk '{USED=TOTAL-$4-$5-$6;print USED}' TOTAL=");
strcat(command, total);

FILE *in2 = popen(command, "r");
Jonathan Leffler