Calling stream popen () with shell shell command line

I am testing this example for pipe programming and it seems pretty simple.

But I was wondering what happens if the first argument to the first call to popen () (the line containing the shell command) contains a while while loop.

For example, if I execute this shell command for 3 seconds, I get this output:

tomas@ubuntu64:~$ while true; do ps -A; sleep 1; done | grep init
    1 ?        00:00:03 init
    1 ?        00:00:03 init
    1 ?        00:00:03 init

      

so grep works on every iteration.

However, if I do this using the C language example, changing the popen () in the example to:

FILE* ps_pipe = popen("while true; do ps -A; sleep 1; done", "r");

      

I am not getting any result when executing the compiled C program.

Can anyone shed some light on this?

+3


source to share


3 answers


Edit: As JF Sebastian pointed out, by default grep uses large buffers when output is not directed to the terminal. You need to use the option --line-buffered

for immediate output (after each line)

Well I tried it and it works great (thanks to JFSebastian fix). Here's the complete code in a FreeBSD 9 box:

#include <stdio.h>

int main() {

    char buffer[256];

    FILE *fd = popen("while true; do ps -A; sleep 1; done | grep --line-buffered init", "r");

        while(NULL != fgets(buffer, sizeof(buffer), fd)) {
            printf("GOT >%s<\n", buffer);
        }

    return 0;

}

      



And (since I didn't delete \n

at the end buffer

) the output is:

GOT >   1 ??  ILs    0:00:02 /sbin/init --
>
GOT >1334 v0  R+     0:00:00 grep --line-buffered init
>
GOT >   1 ??  ILs    0:00:02 /sbin/init --
>
GOT >1334 v0  R+     0:00:00 grep --line-buffered init
>

      

+2


source


This is a block buffering problem . When grep stdout is not a terminal (tty), such as when it is a pipe (created popen()

), as in your case; it uses block buffering instead of line buffering. You won't see anything until the grep stdout buffer overflows. Add a parameter --line-buffered

to grep

and you will see it immediately (every second).



+2


source


All you have to do is write

output to standard I / O, so change the options popen()

to the following:

          FILE* ps_pipe = popen("while true; do ps -A; sleep 1; done", "w");

      

-2


source







All Articles