Skip to content

Repository files navigation

Custom Unix Shell

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.

🚀 Key Features

1. Process Lifecycle Management

  • Command Execution: Leverages fork(), execvp(), and waitpid() 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 custom SIGCHLD handling and a reap_jobs() mechanism to prevent zombie processes.

2. Multi-Stage Pipelines (IPC)

  • 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, redirecting stdout to the write end of the pipe, and stdin to the read end using dup2().
  • Resource Cleanup: Ensures rigorous closing of unused file descriptors in parent and child processes to prevent deadlocks and file table exhaustion.

3. I/O Redirection

  • 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.

4. Interactive CLI Features

  • GNU Readline Integration: Provides a robust, interactive user experience.
  • Tab Completion: Implements a custom rl_attempted_completion_function to auto-complete executable paths and internal shell commands.
  • Persistent History: Maintains a .shell_history file using read_history() and write_history(), supporting event recall (e.g., !n).

5. Advanced Tokenization

  • 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.

🛠️ Architecture

├── 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

💻 Building and Running

This project uses CMake for its build system.

Requirements:

  • CMake (3.10+)
  • A modern C++ compiler (GCC/Clang)
  • GNU Readline development headers (libreadline-dev on Ubuntu, readline on macOS/Homebrew)

Run via script:

chmod +x build_and_run.sh
./build_and_run.sh

Manual CMake Build:

mkdir build
cd build
cmake ..
make
./shell

📝 Example Usage

$ ./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

About

A POSIX-compliant Unix shell built in C++. Features dynamic multi-stage pipeline execution, file descriptor redirection, background job management with asynchronous zombie reaping, and GNU Readline integration.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages