Shellux (Shell + Linux) is a fully-featured custom Unix shell written in C. It provides an interactive command-line interface with support for built-in commands, process management, I/O redirection, pipes, background processes, signal handling, command history, aliases, and user-defined functions.
This shell was developed as a systems programming project to demonstrate understanding of:
- Process creation and management (
fork,exec,wait) - Signal handling (SIGINT, SIGTSTP, SIGCHLD)
- File descriptors and I/O redirection
- Inter-process communication via pipes
- Terminal control and raw mode
- Network programming for man page fetching
| Feature | Description |
|---|---|
| 🏠 Custom Prompt | Dynamic prompt showing <username@hostname:path> |
| 📂 hop | Built-in cd command with path shortcuts |
| 📋 reveal | Built-in ls command with color coding |
| 🔍 seek | Built-in file/directory search command |
| 📝 log | Command history with persistence |
| 🔬 proclore | Process information inspector |
| 📡 iMan | Fetch man pages from the internet |
| 👶 neonate | Monitor latest PIDs in real-time |
| ⏪ Background Processes | Run commands with & |
| 🔀 Pipes | Chain commands with ` |
| 📥 I/O Redirection | Support for <, >, >> |
| 🎯 Signal Handling | Ctrl+C, Ctrl+Z, Ctrl+D |
| 📌 fg/bg | Foreground/background process control |
| 🏷️ Aliases | Custom command shortcuts |
| 🔧 Functions | User-defined shell functions |
- Operating System: Linux (tested on Ubuntu 20.04+)
- Compiler: GCC with C11 support
- Build Tool: Make
-
Clone the repository
git clone https://github.com/iDheer/MiniProject-1.git cd MiniProject-1 -
Build the shell
make
-
Run the shell
./bin/shellux
# Debug build (with symbols)
make debug
# Release build (optimized)
make release
# Clean build artifacts
make clean
# Full rebuild
make rebuild
# Install system-wide (requires sudo)
make install
# Uninstall
make uninstallOnce you start the shell, you'll see a colorful prompt:
<username@hostname:~>
The prompt shows:
- Username: Current user
- Hostname: System name
- Path: Current directory (with
~representing the shell's home directory)
- Type
exitand press Enter - Press
Ctrl+D(EOF signal)
Navigate between directories with enhanced path handling.
Syntax:
hop [path] [path2] ...Examples:
hop # Go to shell's home directory
hop ~ # Go to shell's home directory
hop .. # Go to parent directory
hop . # Stay in current directory (prints path)
hop - # Go to previous directory
hop /absolute/path # Go to absolute path
hop ~/Documents # Go to Documents in user's home
hop dir1 dir2 dir3 # Navigate through multiple directoriesFeatures:
- Supports
~for home directory - Supports
-for previous directory (like cd -) - Supports
.and..for relative paths - Prints the new working directory after each hop
- Can handle multiple paths in sequence
List files and directories with color coding and detailed information.
Syntax:
reveal [flags] [path]Flags:
| Flag | Description |
|---|---|
-a |
Show all files including hidden ones (starting with .) |
-l |
Long format with permissions, size, dates, etc. |
Examples:
reveal # List current directory
reveal -a # Show all files including hidden
reveal -l # Long format listing
reveal -al # Combined: all files in long format
reveal -la # Same as above (order doesn't matter)
reveal ~/Documents # List specific directory
reveal -al ~ # All files in home, long formatColor Coding:
- 🔵 Blue: Directories
- 🟢 Green: Executable files
- ⚪ White: Regular files
Long Format Output:
drwxr-xr-x 2 user group 4096 Dec 18 14:30 Documents
-rwxr-xr-x 1 user group 12288 Dec 18 14:25 script.sh
-rw-r--r-- 1 user group 256 Dec 18 14:20 file.txt
Manage and execute commands from history. The log persists between sessions.
Syntax:
log # Display command history
log purge # Clear all history
log execute <index> # Execute command at indexExamples:
log # Show last 15 commands (numbered)
log purge # Clear the history
log execute 3 # Re-execute the 3rd most recent commandFeatures:
- Stores up to 15 commands
- Commands containing "log" are not stored (prevents recursive logging)
- Consecutive duplicate commands are not stored
- History is saved to
command_log.txtand persists across sessions
Recursively search for files and directories matching a pattern.
Syntax:
seek [flags] <target> [directory]Flags:
| Flag | Description |
|---|---|
-d |
Search for directories only |
-f |
Search for files only |
-e |
Execute: open file/cd into directory if exactly one match |
Examples:
seek file # Search for files/dirs starting with "file"
seek -f config # Search for files starting with "config"
seek -d src # Search for directories starting with "src"
seek -e main.c # Find and open main.c if single match
seek -de build # Find and cd into 'build' dir if single match
seek config ~/project # Search in specific directoryOutput Color Coding:
- 🔵 Blue: Directories
- 🟢 Green: Files
Special Behavior with -e:
- If exactly one file matches: displays its contents
- If exactly one directory matches: changes into that directory
- If multiple matches: only prints results
Display detailed information about a process.
Syntax:
proclore [pid]Examples:
proclore # Show info about the shell process
proclore 1234 # Show info about process with PID 1234Output:
PID: 12345
Process Group: 12345
State: S (sleeping)
VmSize: 4096 kB
Executable Path: /bin/bash
State Indicators:
R- RunningS- Sleeping (interruptible)T- StoppedZ- Zombie+suffix - Foreground process
Fetch manual pages from the internet using man.he.net.
Syntax:
iMan <command_name>Examples:
iMan ls # Fetch man page for 'ls'
iMan grep # Fetch man page for 'grep'
iMan fork # Fetch man page for 'fork' syscallRequirements:
- Internet connection
- Port 80 accessible
Continuously print the PID of the most recently created process.
Syntax:
neonate -n <time_interval>Examples:
neonate -n 1 # Print latest PID every 1 second
neonate -n 5 # Print latest PID every 5 secondsControls:
- Press
xto stop the monitor and return to shell
Send signals to processes by PID.
Syntax:
ping <pid> <signal_number>Examples:
ping 1234 9 # Send SIGKILL to process 1234
ping 1234 15 # Send SIGTERM to process 1234
ping 1234 19 # Send SIGSTOP to process 1234
ping 1234 18 # Send SIGCONT to process 1234Note: Signal numbers are taken modulo 32.
Bring a background process to the foreground.
Syntax:
fg <pid>Examples:
fg 1234 # Bring process 1234 to foregroundResume a stopped background process.
Syntax:
bg <pid>Examples:
bg 1234 # Resume process 1234 in backgroundDisplay all background processes spawned by the shell.
Syntax:
activitiesOutput:
[1234] : sleep 100 - Running
[5678] : vim file.txt - Stopped
States:
Running- Process is runningStopped- Process is stopped (Ctrl+Z)Terminated- Process has exited
Read input from a file instead of keyboard.
sort < unsorted.txt
wc -l < file.txtWrite output to a file (overwrites existing content).
ls > files.txt
echo "Hello" > greeting.txtAppend output to a file.
echo "New line" >> log.txt
date >> timestamps.txtConnect the output of one command to the input of another.
ls | wc -l # Count files
cat file.txt | grep pattern # Search in file
ps aux | grep firefox | head # Complex pipelinecat input.txt | sort | uniq > output.txt
grep error < log.txt | wc -l >> count.txtRun commands in the background by appending &.
sleep 100 & # Run sleep in background
gedit file.txt & # Open editor in background
./long_script.sh & # Run script in backgroundFeatures:
- Background processes print their PID when started
- Use
activitiesto list all background processes - Use
fg <pid>to bring to foreground - Use
bg <pid>to resume stopped process - Shell notifies when background processes exit
| Signal | Key | Behavior |
|---|---|---|
| SIGINT | Ctrl+C |
Terminates foreground process (not the shell) |
| SIGTSTP | Ctrl+Z |
Stops foreground process, moves to background |
| EOF | Ctrl+D |
Exits shell (after killing all background processes) |
- Foreground process running: Signal affects only the foreground process
- No foreground process: Signal is ignored with a message
- Shell protection: The shell itself ignores Ctrl+C and Ctrl+Z
The shell reads shellux.myshrc on startup to load aliases and functions.
alias shortname=commandExample shellux.myshrc:
alias dikhao=ls
alias cls=clear
alias ll=ls -laUsage:
dikhao # Executes 'ls'
cls # Executes 'clear'function_name()
{
command1 "$1"
command2
}Example Functions:
mk_hop()
{
mkdir "$1"
hop "$1"
}
hop_seek()
{
hop "$1"
seek "$1"
}Usage:
mk_hop new_project # Creates 'new_project' and cd's into it
hop_seek Documents # cd to Documents and search thereNote: $1 is replaced with the first argument passed to the function.
Execute multiple commands in sequence using ;.
hop ~ ; reveal ; proclore
mkdir test ; hop test ; revealCommands are executed left to right, regardless of previous command's exit status.
The prompt is dynamically generated with colors:
<username@hostname:path>
| Component | Color |
|---|---|
<, > |
Teal (bold) |
username@hostname |
Teal (bold) |
: |
Default |
path |
Coral (bold) |
Path Display:
~when in shell's home directory~/subdirwhen in subdirectory of home- Full path for directories outside home
MiniProject-1/
├── main.c # Entry point, signal handlers, main loop
├── commands.c # Built-in commands implementation
├── commands.h # Command function declarations
├── utils.c # Utility functions, command execution
├── utils.h # Utility function declarations
├── globals.c # Global variables, helper functions
├── globals.h # Global declarations, structs, macros
├── prompt.c # Prompt display logic
├── prompt.h # Prompt function declarations
├── alias.c # Alias and function handling
├── alias.h # Alias declarations
├── shellux.myshrc # Configuration file (aliases/functions)
├── Makefile # Build configuration
├── test_shell.sh # Testing script
├── README.md # This documentation
├── bin/ # Compiled binary
│ └── shellux
└── obj/ # Object files
└── *.o
- Dynamic allocation for background process tracking
- Proper cleanup on shell exit
- Memory is freed for command history and process lists
- Foreground processes are waited on with
waitpid - Background processes use non-blocking
waitpidwith WNOHANG - SIGCHLD handler cleans up terminated background processes
- Critical sections use signal blocking
- Foreground PID updates are protected
- Async-signal-safe functions used in handlers
- Proper dup2 usage for redirection
- File descriptors closed after duplication
- Multiple pipe support with dynamic fd allocation
Run the comprehensive test suite:
# Make test script executable
chmod +x test_shell.sh
# Run all tests
./test_shell.sh
# Run quick tests only
./test_shell.sh --quick
# Show help
./test_shell.sh --help# Start the shell
./bin/shellux
# Try these commands:
hop ~
reveal -al
echo "Hello World" > test.txt
cat test.txt
ls | grep test | wc -l
sleep 10 &
activities
proclore
log
exit- Platform: Linux only (uses
/procfilesystem) - Tab Completion: Not implemented
- Arrow Keys: History navigation via arrows not supported
- Job Control: Limited to basic fg/bg operations
- Quoted Strings: Limited support for complex quoting
- Environment Variables:
$VARexpansion not implemented - Wildcards: Glob patterns (
*,?) not expanded
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Inesh Dheer
- GitHub: @iDheer
- Operating Systems course concepts
- Linux man pages
- GNU Bash for inspiration
- man.he.net for online man pages
| Command | Description | Example |
|---|---|---|
hop |
Change directory | hop ~/Documents |
reveal |
List files | reveal -al |
seek |
Search files | seek -f config |
log |
Command history | log execute 3 |
proclore |
Process info | proclore 1234 |
iMan |
Online man | iMan grep |
neonate |
PID monitor | neonate -n 2 |
ping |
Send signal | ping 1234 9 |
fg |
Foreground | fg 1234 |
bg |
Background | bg 1234 |
activities |
List bg procs | activities |
exit |
Exit shell | exit |
Made with ❤️ by Inesh Dheer