/* REDIRECTING STANDARD INPUT & OUTPUT In the previous example we explicitly read and wrote a pipe using the read() and write() system calls. This example shows how to redirect the standard input (stdin) and the standard output (stdout) of a process, so that scanf() reads from the pipe and printf() writes into the pipe. */ #include #include #include main() { int fd[2]; int n=0, i; pipe(fd); /* Recall from the previous example that the pipe(fd) system call creates two file descriptors -- one for reading and one for writing the pipe, and copies these file descriptor numbers in fd[0] and fd[1]. Also recall that each process has a file descriptor table (FDT) containing all the file descriptors. The first three file descriptors in a FDT are special ones. The first one (FD = 0) is for the standard input (stdin) which is the terminal input (from keyboard) by default. The second one (FD = 1) is for the standard output (stdout) which is the terminal output (screen) by default. The third (FD = 2) is for the standard error (stderr), for which the terminal output (screen) is the default. The close(fd) system call closes the file with file descriptor fd and leaves that entry in the file descriptor table empty. The dup(fd) system call copies the file descriptor fd into the FIRST EMPTY ENTRY in the file descriptor table. Thus, the sequence of calls: close(0); dup(fd); closes the standard input and then copies the file descriptor fd into its place in FDT. After this fd becomes the standard input. Similarly, the sequence of calls: close(1); dup(fd); redirects the standard output to the file for fd. */ if (fork() == 0) { /* Child process */ close(1) ; dup(fd[1]) ; /* Redirect the stdout of this process to the pipe. */ close(fd[0]); /* This process will not read from the pipe in this example. Hence we close fd[0]. */ for (i=0; i < 10; i++) { printf("%d\n",n); /* Now that stdout has been redirected, printf automatically writes into the pipe. */ n++; } } else { /* Parent process */ close(0) ; dup(fd[0]) ; /* Redirect the stdin of this process to the pipe */ close(fd[1]); /* In this example, this process will not write into the pipe. Hence we close fd[1]. */ for (i=0; i < 10; i++) { scanf("%d",&n); /* Now that stdin has been redirected, scanf automatically reads from the pipe. */ printf("n = %d\n",n); /* The stdout of this process has not been changed. So this will be shown in the terminal. */ sleep(1); } } } /* NOTES: The system call dup() can be used very effectively with calls like execlp() and execvp() to run pre-compiled programs. For example, suppose a process A forks a process B. We create a pipe between A and B, and then redirect the stdin of B to the pipe. After this, B performs an execlp() to execute some application. The process A can now communicate with the application through the pipe, since whatever A writes into the pipe comes as standard input to the application run by B. */