I have a program where I need to communicate with another program on its standard input and output. I can use a pipe to send it input and redirect its output to a specified file to be read when it is done, and that works fine. I am not using pipe and dup2 because I would like my program to at least somewhat work on windows as well as linux.
My issue is that I want to use the pipes to stream data.
I tried the following snippet:
#include <stdio.h>
int main()
{
while (!feof(stdin)) {
int x;
scanf("%d", &x);
printf("%x ", x);
fflush(0);
}
return 0;
}
in conjunction with:
#include <unistd.h>
#include <stdio.h>
int main()
{
int x;
FILE *p = popen("./test > tmp.datafile", "w");
FILE *f = fopen("tmp.datafile", "r");
for (int i = 0; i < 100; ++i) {
fprintf(p, "%d", i);
sleep(1);
x = fgetc(f);
printf("%c ", x);
fflush(0);
}
fclose(f);
pclose(p);
return 0;
}
However no matter what I do, I just keep getting nulls out of the file. I suspect that perhaps there are concurrency issues, in that I try to read the file before the test executable finishes flushing it, however I am not sure how to fix this.
Is there a better way to communicate with a program via standard streams in c?
fgetc() won't read past EOF once EOF has been reached — which may happen on the very first read. Doing something like
if(feof(f)) {
clearerr(f);
sleep(1);
} else {
printf("%c ", x);
}
should sort-of solve the issue with a busy loop.
A better idea would be to wait for the file to change once EOF has been reached, but that would require system-specific calls.
Beware of another race condition: fopen may happen before the file has been created by the command started via popen.
while(!(f = fopen(..., "r"))
sleep(1);
It's another busy loop and overall not a good solution that should only be used if dup2() is not available.