Basically, I want to store entire program output in buffers for longer runtimes. Issue is, popen(3)
forks a process and since data to be read by poll(2)
is delivered in buffered blocks, any intermittent lines between each subsequent call of poll(2)
may result in output being skipped in the child process. I was hoping blocking with poll(2) would temporarily halt the forked process, but this is not the case. Is there some way to gain control of this forked process that would allow it to pause, read input, pause, read input, ...? I don't see any way of dropping popen(3)
, but it looks like poll(2)
should be replaced.
/tmp/script.sh
#!/bin/bash
for i in {1..5}
do
echo $i
sleep 1
done
main.c
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#define OUT_LEN 256
#define CMD_LEN 128
void die(char *msg)
{
printf("Error: %s\n", msg);
exit(EXIT_FAILURE);
}
int main()
{
FILE *fp;
char cmd[CMD_LEN+1] = "/tmp/script.sh";
char output[OUT_LEN+1];
struct pollfd *ps;
int n = 1, c, x;
if((fp = popen(cmd, "r")) == NULL)
die("failed in popen()");
output[OUT_LEN] = '\0';
ps = calloc(n, sizeof(struct pollfd));
ps[0].fd = fp->_fileno;
ps[0].events = POLLIN;
for(x = 0; (c = fgetc(fp)) != EOF && x < OUT_LEN; ++x)
{
if(poll(ps, n, 0) == -1) { die("poll()"); }
if(ps[0].revents & POLLIN)
output[x] = c;
}
if(x >= OUT_LEN)
die("LEN too short for stdout of cmd");
printf("see output below:\n%s", output);
return 0;
}
Desired output:
see output below:
1
2
3
4
5
Actual output:
see output below: