Step 5: Redirect output to a file
How does echo hi > out.txt work? The shell opens the file, then in the child uses dup2 to make the file become standard output (file descriptor 1) before exec. The program does not know: it just prints to "stdout" as always. O_TRUNC empties the file first, which is why > replaces content (while >> would append with O_APPEND).
ExampleC
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
// Run argv with its standard output sent to a file (like "echo hi > out.txt").
int run_redirected(char *argv[], const char *file) {
fflush(stdout);
pid_t pid = fork();
if (pid == 0) {
int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) _exit(1);
dup2(fd, STDOUT_FILENO); // from now on, "stdout" IS the file
close(fd);
execvp(argv[0], argv);
_exit(127);
}
int status;
waitpid(pid, &status, 0);
return WIFEXITED(status) ? WEXITSTATUS(status) : 1;
}
int main(void) {
const char *file = "/tmp/tinyshell-out.txt";
char *cmd1[] = { "echo", "first line", NULL };
printf("status %d\n", run_redirected(cmd1, file));
char *cmd2[] = { "echo", "second line replaces it", NULL };
printf("status %d\n", run_redirected(cmd2, file)); // ">" truncates the file
FILE *f = fopen(file, "r");
char line[100];
while (fgets(line, sizeof(line), f)) printf("file contains: %s", line);
fclose(f);
remove(file);
return 0;
}Output
status 0 status 0 file contains: second line replaces it
The second command replaced the first one's text: the file holds only the second line. The idea that "everything is a file descriptor" is one of Unix's most powerful designs.
Quick check
What does dup2(fd, STDOUT_FILENO) do?
Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.
Tip: use the left and right arrow keys to move between lessons.