A POSIX-compliant Unix shell built entirely in C++.
This project explores core systems programming concepts, including the complete process lifecycle, Inter-Process Communication (IPC), file descriptor manipulation, and standard interactive CLI features. It was built to demonstrate proficiency with low-level Linux/Unix system calls and C++ systems architecture.
- Command Execution: Leverages
fork(),execvp(), andwaitpid()to safely spawn and manage child processes for external commands (e.g.,ls,grep,cat). - Background Jobs: Supports asynchronous job execution via the
&operator, implementing customSIGCHLDhandling and areap_jobs()mechanism to prevent zombie processes.
- Dynamic Piping: Supports unlimited chained pipelines (e.g.,
ls | grep .txt | wc -l). - File Descriptor Orchestration: Creates and manages IPC
pipe()connections between dynamically forked child processes, redirectingstdoutto thewriteend of the pipe, andstdinto thereadend usingdup2(). - Resource Cleanup: Ensures rigorous closing of unused file descriptors in parent and child processes to prevent deadlocks and file table exhaustion.
- Standard Redirections: Supports output redirection (
>), append redirection (>>), and standard error redirection (2>,2>>). - Save & Restore: Implements a clean state-restoration pattern using
dup()to save standard file descriptors before redirection and restore them after execution, preventing the shell itself from losing its terminal connection.
- GNU Readline Integration: Provides a robust, interactive user experience.
- Tab Completion: Implements a custom
rl_attempted_completion_functionto auto-complete executable paths and internal shell commands. - Persistent History: Maintains a
.shell_historyfile usingread_history()andwrite_history(), supporting event recall (e.g.,!n).
- State-Machine Parser: A custom lexer that correctly handles three quoting modes: unquoted, single-quoted (
'), and double-quoted ("). - Escape Sequences: Properly processes backslash (
\) escape characters for special characters and literal spaces within arguments.
├── src/
│ ├── main.cpp # Shell initialization and REPL loop
│ ├── executor.cpp # fork/exec/wait logic & built-ins
│ ├── pipeline.cpp # IPC pipe and process chaining logic
│ ├── tokenizer.cpp # State-machine lexer for parsing
│ └── io_redirect.cpp # File descriptor dup/dup2 management
├── CMakeLists.txt # Build configuration
└── build_and_run.sh # One-step compilation and execution wrapper
This project uses CMake for its build system.
Requirements:
- CMake (3.10+)
- A modern C++ compiler (GCC/Clang)
- GNU Readline development headers (
libreadline-devon Ubuntu,readlineon macOS/Homebrew)
Run via script:
chmod +x build_and_run.sh
./build_and_run.shManual CMake Build:
mkdir build
cd build
cmake ..
make
./shell$ ./shell
shell> echo "Hello World" > output.txt
shell> cat output.txt | wc -w
2
shell> sleep 10 &
[1] 48291
shell> ls /nonexistent 2> error.log
shell> cat error.log
ls: /nonexistent: No such file or directory
shell> exit 0