A custom interactive shell written in C++ that replicates core POSIX shell features. This project demonstrates fundamental concepts of operating systems including process management, inter-process communication, and system calls.
-
Command Parsing: Reads and parses user input with support for:
- Multiple commands separated by semicolons (
;) - Command pipelining with pipes (
|) - Complex command chaining
- Multiple commands separated by semicolons (
-
Process Management:
- Creates and manages child processes using
fork()andexecvp() - Supports foreground and background process execution (with
&) - Handles process groups with
setpgid() - Signal handling for
SIGINT(Ctrl+C) andSIGTSTP(Ctrl+Z)
- Creates and manages child processes using
-
Input/Output Redirection:
- Output redirection:
>(overwrite) and>>(append) - Input redirection:
< - Piping between commands:
|
- Output redirection:
-
Built-in Commands:
cd- Change directory (with support for~and..)ls- List directory contents (with-aand-lflags)echo- Display textpwd- Print working directoryhistory- View and recall previous commandspinfo- Display process informationsearch- Recursively search for files
-
Command History:
- Maintains a persistent command history (stored in
history.txt) - Uses GNU Readline library for command-line editing
- Supports history navigation and recall
- Maintains a persistent command history (stored in
-
Custom Prompt:
- Dynamic prompt showing
username@hostname:path> - Displays current working directory relative to home
- Dynamic prompt showing
-
Error Handling:
- Graceful handling of invalid commands
- Proper error messages for missing arguments
- System error reporting
posix_shell/
├── problem/
│ └── AOS_Assignment_2_M25_V1.pdf # Assignment problem statement
├── solution/
│ ├── README.md # Documentation
│ ├── Makefile # Build configuration
│ ├── all_header.h # Common header includes
│ ├── utility.h # Function declarations
│ ├── utility.cpp # Utility functions
│ ├── home.cpp # Main entry point and shell loop
│ ├── base_cmd_file.cpp # Core command execution and piping
│ ├── io_file.cpp # I/O redirection handling
│ ├── ls_file.cpp # ls command implementation
│ ├── next_cmd_file.cpp # Additional commands (history, pinfo, search)
│ └── history.txt # Command history storage
├── .gitignore
└── README.md
| File | Purpose |
|---|---|
| all_header.h | Common header file including all necessary system libraries (iostream, unistd.h, readline, etc.) |
| utility.h / utility.cpp | Utility functions used throughout the shell (clearScreen, print, string formatting, etc.) |
| home.cpp | Main entry point containing the shell loop, command parsing, and signal handlers |
| base_cmd_file.cpp | Core command execution logic including process management, piping, and forking |
| io_file.cpp | Handles input/output redirection for <, >, and >> operators |
| ls_file.cpp | Implements the ls command with support for -a and -l flags |
| next_cmd_file.cpp | Implements additional commands: search, history, and pinfo |
- C++ Compiler: g++ (with C++11 support or higher)
- GNU Readline Library: Required for command-line editing and history
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install g++ libreadline-devmacOS:
brew install readline- Clone the repository:
git clone https://github.com/viserion999/posix_shell.git
cd posix_shell/solution- Compile the shell:
makeThis will compile all source files and link them with the readline library to produce the home executable.
- (Optional) Rebuild from scratch:
make rebuild- Clean build artifacts:
make cleanAfter building, run the shell with:
./homeYou should see a welcome message and a custom prompt like:
----------------------------
WELCOME
----------------------------
username@hostname:~>
# Print working directory
username@hostname:~> pwd
# List files
username@hostname:~> ls
username@hostname:~> ls -a # Show hidden files
username@hostname:~> ls -l # Long listing format
username@hostname:~> ls -la # Combined flags
# Change directory
username@hostname:~> cd /usr/local
username@hostname:/usr/local> cd ..
username@hostname:/usr> cd ~ # Return to home# Multiple commands with semicolon
username@hostname:~> ls ; pwd ; echo "Done"
# Piping
username@hostname:~> ls -l | grep ".cpp"
username@hostname:~> cat file.txt | wc -l# Output redirection
username@hostname:~> ls > output.txt # Overwrite
username@hostname:~> ls >> output.txt # Append
# Input redirection
username@hostname:~> cat < input.txt
# Combined
username@hostname:~> cat < input.txt > output.txt# Run in background
username@hostname:~> gedit &
[PID displayed]# Show last 10 commands
username@hostname:~> history
# Show last N commands
username@hostname:~> history 5# Show current shell process info
username@hostname:~> pinfo
# Show specific process info
username@hostname:~> pinfo 12345# Search for file recursively
username@hostname:~> search filenameThe shell tokenizes input in three levels:
- Split by semicolon (
;) for multiple commands - Split by pipe (
|) for piped commands - Split by whitespace for individual arguments
- Fork-Exec Model: Each command creates a new child process using
fork(), then replaces it with the target program usingexecvp() - Process Groups: Each command runs in its own process group for proper job control
- Background Execution: Commands ending with
&run asynchronously
- Multi-command pipelines are supported by creating a chain of pipes
- File descriptors are properly redirected using
dup2() - Parent closes all pipe ends and waits for all children
- SIGINT (Ctrl+C): Terminates foreground processes only
- SIGTSTP (Ctrl+Z): Suspends foreground processes
This shell is designed for educational purposes to demonstrate:
- How UNIX shells work internally
- Process creation and management
- Inter-process communication via pipes
- File descriptor manipulation
- System call usage
- Signal handling in multi-process applications