A 42 School project reimplementing how a shell pipe (cmd1 | cmd2) works, using the fork, pipe, dup2, and execve system calls. The goal is to get a deep, hands-on understanding of redirections and inter-process communication on Unix.
pipex reproduces the shell command:
< infile cmd1 | cmd2 > outfilewithout going through /bin/sh. Each command runs in its own child process, with children connected to each other via pipe() and wired to the right input/output through dup2(). The program resolves each command's executable path itself by searching the directories listed in the PATH environment variable.
make # builds the pipex executable (mandatory part)
make bonus # builds the pipex executable (bonus part)
make clean # removes object files
make fclean # removes object files + the executable
make re # fclean then allMandatory version:
./pipex infile cmd1 cmd2 outfile
# equivalent to: < infile cmd1 | cmd2 > outfileExample:
./pipex infile "grep foo" "wc -l" outfileThe bonus version supports:
-
An unlimited number of commands, chained into a single pipeline:
./pipex infile cmd1 cmd2 cmd3 ... cmdN outfile
-
here_doc, which replaces the input file with standard input delimited by a terminator (like<<in shell):./pipex here_doc LIMITER cmd1 cmd2 ... cmdN outfile
-
Writing to
outfilehappens inappendmode whenhere_docis used, mirroring>>.
.
├── includes/
│ ├── pipex.h # structs, prototypes, internal libft
│ └── pipex_bonus.h # bonus-specific prototypes
├── srcs/
│ ├── pipex.c # main (mandatory part)
│ ├── pipex_bonus.c # main (bonus part) + here_doc handling
│ ├── pipeline.c # fork/pipe orchestration for each command
│ ├── execute.c # dup2, command lookup and execution (execve)
│ ├── path.c # PATH resolution to locate the executable
│ ├── fd_utils.c # safe opening/closing of files and file descriptors
│ ├── ft_split.c # string splitting (libft)
│ ├── str_utils.c # string utilities (libft)
│ └── utils.c # fatal error handling
└── Makefile
- Command lookup: if the command contains a
/, it is used as-is; otherwise, each directory in$PATHis tested until a matching executable is found (path.c). - Exit codes: the program returns the exit status of the last command in the pipeline (
126if found but not executable,127if not found), matching standard shell behavior. - Generic pipeline: the number of commands is not fixed — pipeline.c dynamically creates one pipe and one fork per stage, closing every unused file descriptor in each process to avoid descriptor leaks or read blocking.
- Error handling: allocations,
fork,pipe, and file opens are all checked; any fatal error frees already-allocated resources before exiting cleanly.
Note: project completed as part of the 42 curriculum, solo, scored 125/100.
