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