Pipex 42
zakaria guellouch
June 16, 2025
Welcome! We’re going to build our own pipex program in C. Before we write any code, we’ll see:
1-What is pipex
2-Play in the shell to experiment with <
, |
, >
, >>
, <<
.
3-Learn the key system calls (access
, open
, pipe
, fork
, dup2
, execve
, wait
)
4-Combine everything
1. What Is Pipex?
pipex
is a small C program that mimics how your shell connects commands with pipes and redirects their input/output—when you run
./pipex infile "cmd1 args" "cmd2 args" outfile
it does exactly what
< infile cmd1 args | cmd2 args > outfile
does in Bash.
2-Bash Redirections & Pipes
Try these mini-experiments in your terminal!
2.1 Input Redirection <
- Syntax:
< infile command
- Behavior: The command reads its stdin from
infile
, not from your keyboard.
echo "Hello Pipex" > hello.txt # create a file hello.txt, and the text inside is "Life is good"
cat < hello.txt # 'cat' reads from hello.txt and prints "Life is good"
2.2 Pipe |
- Syntax:
cmd1 | cmd2
- Behavior: Feeds output of
cmd1
into input ofcmd2
.
echo "Life is good" | wc -w # → 3 words
2.3 Output Redirection >
- Syntax:
command > outfile
- Behavior: Writes output to
outfile
, replacing old content.
ls > list.txt # creates a file list.txt if it doesn't exit and save file list in it
cat list.txt # view it
echo "life is good" > list.txt # you're gonna notice that list of files is removed and it's replaced by "life is good", that what i meant in "replacing old content"
# to save the old content it's in the next section
2.4 Append Redirection >>
(Bonus)
- Syntax:
command >> outfile
- Behavior: Appends output to the end of
outfile
.
echo "Line 1" > notes.txt # creates a file notes.txt if it doesn't exit and save "Line 1" in it
echo "Line 2" >> notes.txt # adds to end of the file "Line 2" without losing the "Line 1"
cat notes.txt
2.5 Here-Document <<
(Bonus)
- Syntax:
cmd << LIMITER
- Behavior: Reads from keyboard (stdin) until you type exactly
LIMITER
on its own line.
cat << STOP | grep good
>Line 1
>Line 2
>life is bad
>life is good
>STOP
life is good
Types until STOP, then
grep
filters “life is good”
2.6 Everything is a file
if you run “which ls” in bash, you’re gonna notice a path whether “/bin/ls” or “/usr/bin/ls” it doesn’t matter, try to run that absolute path
$> which ls /usr/bin/ls $> /usr/bin/ls infile libft main.c Makefile minipipex minipipex.h outfile utils.c $> ls infile libft main.c Makefile minipipex minipipex.h outfile utils.c
you’ll notice that every command is just an executable file, try for other commands like echo, cat, it’s gonna be the same, why am i showing you this? you’ll see it in the next chapter
3-The C System Calls You’ll Use
1. access(pathname, mode)
What it does
Checks whether the file at pathname
exists and/or whether your process has the requested permissions on it.
-
-
Returns:
-
0
→ you do have those permissions -
-1
→ you don’t (or the file doesn’t exist)
-
-
Common mode
flags
-
-
F_OK
→ does the file exist? -
R_OK
→ can I read it? -
W_OK
→ can I write to it? -
X_OK
→ can I execute it?
-
Examples
2. open(pathname, flags, [mode])
What it does
Opens (or creates) a file and returns a file descriptor.
-
-
flags
tell the kernel how you want to open it:-
O_RDONLY
→ read only -
O_WRONLY
→ write only -
O_RDWR
→ read & write -
O_CREAT
→ create if it doesn’t exist -
O_TRUNC
→ if it exists, truncate to zero length
-
-
mode
(0644
, etc.) only matters when you useO_CREAT
, and sets the new file’s permissions. -
Returns:
-
>= 0
→ a valid file descriptor -
-1
→ open failed to open the file
-
-
Example
3. pipe(int pipefd[2])
What it does
Creates a unidirectional data channel (a pipe) with two file descriptors:
-
-
pipefd[0]
→ read end -
pipefd[1]
→ write end
-
Data written to pipefd[1]
can be read from pipefd[0]
.
-
-
Returns:
-
0
→ success -
-1
→ error
-
-
Example
4. fork()
What it does
Creates a child process. The child is a near-identical copy of the parent.
-
-
Returns:
-
> 0
→ in the parent, the return value is the child’s PID -
0
→ in the child -
-1
→ error (no child created)
-
-
Example
5. dup2(oldfd, newfd)
What it does
Redirects one file descriptor (newfd
) to the same open file/table entry as another (oldfd
).
-
-
Closes
newfd
if it’s already open. -
Makes
newfd
refer to the same file/pipe asoldfd
.
-
After dup2
: both descriptors share the same offset and flags.
-
-
Returns:
-
newfd
on success -
-1
on error
-
-
Why you do this in pipex
-
-
dup2(in_fd, STDIN_FILENO)
makes stdin read from your input file. -
dup2(pipefd[1], STDOUT_FILENO)
makes stdout write into the pipe.
-
Important: Always close(oldfd)
afterward to avoid leaking that descriptor.
6. execve(path, args, env)
What it does
Replaces the current process image with a new program.
-
-
path
→ path to the executable -
args
→ argument vector (args[0]
is the command name) -
env
→ environment variables -
Returns:
-
Never returns on success (the new program runs instead).
-
-1
on error (old program continues).
-
-
Example
we’re gonna start building pipex
4. Combine everything
PART1: MANDATORY