# Using dup2() to redirect output

Sometimes, you want to redirect the output of your program to a file–maybe to record it for another program, or because you want to search through it with grep. If you have to do this at the C level, there are a few ways you can accomplish this.

### Using a variable

Perhaps the simplest way to do this is to use the fprintf family of functions along with a variable that controls what file we want to output to. For example, we can do the following:

  const char* filename = get_filename_or_null(); // NULL means "use stdout"
FILE* outStream;

if(filename){
FILE* out = fopen(filename, "w");
if(out){
outStream = out;
} else {
outStream = stdout;
}
} else {
outStream = stdout;
}

// Filler code here
fprintf(outStream, "my fancy output");


Note that this is a little annoying because we have to specify outStream whenever we want to print. What if we wanted to avoid this variable shenaniganery?

### Modifying stdout

It turns out that on many (though not all!) systems, printf is defined to be something like this:

int printf(const char* format, other_args...){
fprintf(stdout, format, other_args...);
}


Don’t worry too much about the other_args stuff for now. Notice that printf is just fprintf with a FILE* variable called stdout. This suggests that if we overrode the stdout variable, we could get all usages of printf to print to a file.

Let’s try it out:

  const char* filename = get_filename_or_null();
if(filename){
FILE* outputFile = open(filename, "w");
if(outputFile){
stdout = outputFile;
}
}
// Filler code here
printf("my fancy output");


Does this work on your system? It works on mine…but this is wildly unsafe to rely on!. All it takes is a different implementation of printf, and output redirection will stop working.

These two methods also have the disadvantage that, if you fork-and-exec, they stop working. Let’s take a look at a method that gets rid of all these issues.

### Using dup2()

We can use dup2() to duplicate a file descriptor, which will allow us to redirect output with the following code snippet:

  const char* filename = get_filename_or_null();
if(filename){
int fd = open(filename, O_WRONLY, 0666);
dup2(fd, STDOUT_FILENO); // Check man stdin for more info
dup2(fd, STDERR_FILENO);
// Check the return values of dup2 here
}

// Filler code here
printf("My fancy output");


Notice that this code essentially does the same thing as previously: it redirects output to a file. However, there’s a very important difference here. If the process forks-and-execs, the child process will still have its output redirected to file, even after the exec!. This is something that was not true of our earlier solutions, and is a very useful property of the dup2() solution.

Written August 30, 2020 • Last modified January 16, 2021