Unix Shell
A command interpreter written in C.
Design goal
Build a working Unix shell from scratch: parsing, process control, pipes and redirection.
What it handles
Fork and execve, pipes and dup2, input and output redirection including heredocs, signal handling, and built-in commands.


The rewrite
The first version worked and was unmaintainable — 1,800 lines spread across thirty files with names like shell1.c, shell12.c and shell0_33.c. The second version is 1,265 lines organised by responsibility: parser, execution, builtins, redirection, signals, environment, pipes. Same functionality, half the cognitive load. Splitting it that way meant every file could be reasoned about on its own, and it made the parts I had got wrong visible, because a function in the wrong module is obvious in a way that a function in shell17.c is not.
Main learnings
Process creation and management, file descriptors, signal handling, modular architecture. Rewriting it taught me more than building it did.
Academic project · C, Unix system calls, Make · 2024