popen() alternative

hari picture hari · Jul 19, 2011 · Viewed 14.5k times · Source

My question is extension of this one: popen creates an extra sh process

Motives:

1) My program need to create a child which does tail on a file. I need to process the output line by line. That is why I am using popen because it returns FILE *. I can easily fetch single line, do what I need to do and print it.

One problem with popen is that you do not get pid of child (tail command in my case).

2) My program should not exit before its child is done. So I need to do wait; but without pid, I cannot do it.

How can I achieve both the goals?

A possible (kludge) solution: do execvp("tail -f file > tmpfile") and the keep reading that tmpfile. I am not sure how good this solution is, though.

Answer

Patryk picture Patryk · Jul 19, 2011

Why aren't you using pipe/fork/exec method?

pid_t pid = 0;
int pipefd[2];
FILE* output;
char line[256];
int status;

pipe(pipefd); //create a pipe
pid = fork(); //span a child process
if (pid == 0)
{
// Child. Let's redirect its standard output to our pipe and replace process with tail
 close(pipefd[0]);
 dup2(pipefd[1], STDOUT_FILENO);
 dup2(pipefd[1], STDERR_FILENO);
 execl("/usr/bin/tail", "/usr/bin/tail", "-f", "path/to/your/file", (char*) NULL);
}

//Only parent gets here. Listen to what the tail says
close(pipefd[1]);
output = fdopen(pipefd[0], "r");

while(fgets(line, sizeof(line), output)) //listen to what tail writes to its standard output
{
//if you need to kill the tail application, just kill it:
  if(something_goes_wrong)
    kill(pid, SIGKILL);
}

//or wait for the child process to terminate
waitpid(pid, &status, 0);