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

96,100

Solution 1

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 ...
}

Solution 2

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);
}

Solution 3

You can use this when stdin , stdout , stderr are terminal-

//change stdin,stdout,stderr
    freopen("new_stdin","r",stdin);
    freopen("new_stdout","r",stdout);
    freopen("new_stderr","r",stderr);

    //----do something;

//reset stdin,stdout,stderr
     freopen("/dev/tty","r",stdin);
     freopen("/dev/tty","r",stdout);
     freopen("/dev/tty","r",stderr);
Share:
96,100
Matt
Author by

Matt

If I'm giving you a hard time, it's because I'm trying to learn as much as I can from you.

Updated on July 09, 2022

Comments

  • Matt
    Matt almost 2 years

    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?