#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> main() { char *line = new char[100]; int f = open("test", O_WRONLY | O_CREAT, 0700); dup2(f, 1); // or ... close(1); dup(f); puts(gets(line)); }The open system call creates a file and assigns it the next available descriptor in the process' file descriptor table -- that is, file descriptor 3, because 0, 1, 2 are already allocated by default. The system call dup2 then makes file descriptor 1 point to the same file as file descriptor 3. As a result, the output of puts goes to the file instead of stdout which was originally pointed to by file descriptor 1. Here is what happens in picture:
The following one is slightly more elaborate; it implements a pipe between two programs, cat and wc. source (compile with gcc)
#include <stdio.h> main() { int fd[2]; pipe(fd); if (fork() == 0) { // first child dup2(fd[1], 1); // or ... close(1); dup(fd[1]); close(fd[0]); close(fd[1]); execlp("cat", "cat", NULL); } if (fork() == 0) { // second child dup2(fd[0], 0); // or ... close(0), dup(fd[0]); close(fd[0]); close(fd[1]); execlp("wc", "wc", "-c", NULL); } close(fd[0]); close(fd[1]); while (wait(NULL) != -1) ; }The pipe system call grabs the next two available file descriptors, i.e., 3 and 4, and store them in fd[0] and fd[1]. fd[0] is connected to the input end of the pipe, and fd[1] the output end.
When a child is forked, its parent's file descriptors table is copied to the child so that all the opened files (including any pipes) are automatically pointed to by both processes.
A pipe is a FIFO type of file implemented as a memory object by the kernel.
Using dup2 and close, we can achieve the desired effect, as shown below.