Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C how do you redirect stdin/stdout/stderr to files when making an execvp() or similar call?

I have the following code:

pid_t pid = fork();
if (pid == -1)
{
    // ...
}
else if (pid == 0)
{
    stdin = someopenfile;
    stdout = someotherfile;
    stderr = somethirdopenfile;
    execvp(args[0], args);
    // handle error ...
}
else
{
    // ...
}

The problem is, the input/output of the execvp() call is still the console, rather than the files. Clearly I am doing something wrong, what is the right way to do this?

like image 683
Matt Avatar asked Jan 27 '13 01:01

Matt


2 Answers

The right way to do it is to replace the file descriptors STDIN_FILENO, STDOUT_FILENO and STDERR_FILENO with the opened files using dup2(). You should also then close the original files in the child process:

else if (pid == 0) {     dup2(fileno(someopenfile), STDIN_FILENO);     dup2(fileno(someotherfile), STDOUT_FILENO);     dup2(fileno(somethirdopenfile), STDERR_FILENO);     fclose(someopenfile);     fclose(someotheropenfile);     fclose(somethirdopenfile);     execvp(args[0], args);     // handle error ... } 
like image 152
caf Avatar answered Sep 19 '22 00:09

caf


Take a look at freopen function.

I had to do something similar with stdout and wrote two functions that do the work for me:

static int fd;
static fpos_t pos;

void switchStdout(const char *newStream)
{
  fflush(stdout);
  fgetpos(stdout, &pos);
  fd = dup(fileno(stdout));
  freopen(newStream, "w", stdout);
}

void revertStdout()
{
  fflush(stdout);
  dup2(fd, fileno(stdout));
  close(fd);
  clearerr(stdout);
  fsetpos(stdout, &pos);
}
like image 34
Jack Avatar answered Sep 21 '22 00:09

Jack