dup2(2)

System call

Makes one file descriptor a copy of another. It is the call that redirects standard output to a file or a pipe before an exec.

Synopsis
#include <unistd.h>
int dup2(int oldfd, int newfd);

Description

dup2(oldfd, newfd) makes the descriptor newfd refer to the same open file as oldfd. If newfd was already open, it is closed first, without reporting any error. After the call, both numbers refer to the same file and share its offset and its file status flags; only the close-on-exec flag stays separate for each one.

The most common use is redirection. Descriptors 0, 1 and 2 are standard input, standard output and standard error (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO). dup2(fd, STDOUT_FILENO) sends everything the process writes to its standard output into fd, which can be a file or the write end of a pipe. Since descriptors survive execvp, a program started afterwards also writes to the new place, without knowing it.

Return value

The new descriptor, so newfd. -1 on error, with errno: EBADF if oldfd is not open (in that case newfd is not closed), EINTR if a signal interrupted the call. If oldfd and newfd are equal, dup2 does nothing and returns newfd.

Pitfalls

  • After dup2(fd, STDOUT_FILENO), close fd: you no longer need it, and a pipe descriptor left open keeps the reader from ever seeing the end of the stream.

  • The argument order is the one cp uses: source first, destination second. dup2(STDOUT_FILENO, fd) does the opposite of what you meant.

  • Redirection does not touch the printf buffer. Text written before dup2 and not flushed yet will go to the new place. Call fflush(stdout) before you redirect.

Example

redirect.c
#include <fcntl.h>#include <stdio.h>#include <unistd.h>
int main(void){    printf("on the screen\n");    fflush(stdout);
    int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);    if (fd == -1) {        perror("open");        return 1;    }    dup2(fd, STDOUT_FILENO);    close(fd);    printf("in the file\n");    return 0;}
Terminal
$ gcc -Wall -Wextra redirect.c -o redirect$ ./redirecton the screen$ cat output.txtin the file

The second printf is no different from the first: descriptor 1 now leads to the file.

C

process_stream_open

Write process_stream_open, which runs a command in a child and redirects its standard output or input to a pipe whose other end you return.

Open the exercise

Now write it yourself.