Unix Redirection In C
Published: Jul 28, 2020
Last updated: Jul 28, 2020
This short post is a recount of an exploration into redirection in the C language.
As always, let's go to our friend Wikipedia
In computing, redirection is a form of interprocess communication, and is a function common to most command-line interpreters, including the various Unix shells that can redirect standard streams to user-specified locations.
In Unix-like operating systems, programs do redirection with the dup2(2) system call, or its less-flexible but higher-level stdio analogues, freopen(3) and popen(3).
Basic redirection can use <
to redirect input and >
to redirect output.
For example, we can use the redirect output operator to redirect the output from echo "Hello!"
into a file example.txt
.
> echo "Hello!" > example.txt > cat example.txt Hello!
As mentioned by our pal Wikipedia, we can use the dup2
system call in C to manage a similar thing!
A simple example
In our first example, we are going to write a simple example of two variables that open a foobar.txt
that iterates character by character.
touch foobar.txt one.c
Inside of foobar.txt
, add th following:
foobar test
As for the contents of one.c
:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> int main() { int fd1, fd2; char c; fd1 = open("foobar.txt", O_RDONLY); fd2 = open("foobar.txt", O_RDONLY); // c becomes f read(fd2, &c, 1); // c becomes o read(fd2, &c, 1); // c becomes o read(fd2, &c, 1); // c becomes b read(fd2, &c, 1); printf("c = %c\n", c); // c = b // now reading in fd1, so c becomes f again read(fd1, &c, 1); printf("c = %c\n", c); // c = f // redirect and now fd2 is now back at f dup2(fd1, fd2); // reading back fd2 which has been redirected, // so c actually becomes o! read(fd2, &c, 1); printf("c = %c\n", c); // c = 0 exit(0); }
The comments in the code explain what is happening in order, but we're just going to print out the result by running gcc one.c && ./a.out
. The output binary a.out
is the name given since we do not provide output to GCC.
> gcc one.c && ./a.out c = b c = f c = o
To explain further what is going on:
- We assign
fd1
andfd2
to openfoobar.txt
. - We use
read
to read in a character and assign it to variablec
. - Each time we read
fd2
, we move one character further along in the text file. - Eventually, we read
fd1
once and then we redirectfd1
tofd2
. - We read
fd2
one last time, but after redirection the value now reads "o".
A more readable example
The above can seem hard to comprehend - it is better playing around with this stuff in C. This example, I decided to use scanf
to read in from stdin in the second example, because I feel like the example was a little clearer for me.
Note: Given I knew the length of the words in the file, I just set a max STR_LEN of 6 as opposed to some dynamic calculation.
Create a file two.c
.
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #define STR_LEN 6 int main() { int fd1; char *c1 = (char*)malloc(STR_LEN); char *c2 = (char*)malloc(STR_LEN); // notice no values printf("c1 = %s\nc2 = %s\n", c1, c2); fd1 = open("foobar.txt", O_RDONLY); // redirect fd1 to stdin if (dup2(fd1, STDIN_FILENO) < 0) { printf("Unable to duplicate file descriptor."); exit(EXIT_FAILURE); } // scan c1 and c2 in from stdin scanf("%s %s", c1, c2); // values now becomes "foobar" and "test" respectively printf("c1 = %s\nc2 = %s\n", c1, c2); // SAVE THE WHALES, FREE THE MALLOCS free(c1); free(c2); exit(0); }
Now if we run gcc two.c && ./a.out
, we get the following:
> gcc two.c && ./a.out c1 = c2 = c1 = foobar c2 = test
In this case, we do the following:
- Allocate memory for
c1
andc2
. - Confirm no values in first print.
- Read in the
foobar.txt
file to file descriptorfd1
. - Redirect
fd1
tostdin
. - Use
scanf
to assign the values toc1
andc2
fromstdin
. - Confirm with the last print that
c1
andc2
have been assigned the words "foobar" and "test" respectively!
Hooray! Redirection to stdin is a success (and no segmentation faults).
I will likely redo this exercise in Rust and Golang this week to show the how-to.
Resources
- Computer Systems A Programmer's Perspective - Page 944
- dup2 System Call
- Stack Overflow - difference between read and fread
- Unix System Calls - read
- Top 20 C Pointer Mistakes
- Stack Overflow - Reading file and getting string length
- CS 702 Operating Systems - redirect and pipes
- TutorialsPoint - Redirection
- Redirection - Wikipedia
Image credit: Michael Kubler
Dennis O'Keeffe
Melbourne, Australia
1,200+ PEOPLE ALREADY JOINED ❤️️
Get fresh posts + news direct to your inbox.
No spam. We only send you relevant content.
Unix Redirection In C
Introduction