A lightweight, POSIX-compliant Unix shell implementation in C that supports pipelines, redirections, background processes, and signal handling.
- Command Execution: Execute any program in your PATH
- Multi-stage Pipelines: Chain multiple commands together (
ls | grep txt | wc -l) - I/O Redirection:
- Output redirection (
>) - Input redirection (
<) - Append mode (
>>)
- Output redirection (
- Background Processes: Run commands asynchronously with
& - Signal Handling: Proper Ctrl+C handling without terminating the shell
- Built-in Commands:
cdfor directory navigation
- Dynamic memory allocation (no arbitrary argument limits)
- Asynchronous zombie process reaping via SIGCHLD
- Signal-safe foreground process tracking
- Proper pipe and file descriptor management
- Clean error handling and resource cleanup
- GCC or any C compiler supporting C99
- POSIX-compliant Unix-like operating system (Linux, macOS, BSD)
gcc -Wall -Wextra -o minishell main.cFor debugging:
gcc -Wall -Wextra -g -o minishell main.c./minishellYou'll see a prompt:
>
> ls
> pwd
> echo "Hello, World!"> ls -la | grep .c
> cat file.txt | sort | uniq
> ps aux | grep bash | wc -l> ls > output.txt
> cat < input.txt
> echo "append this" >> log.txt
> cat < input.txt > output.txt> sleep 10 &
[BG Process: 12345]
> > cat file.txt | grep pattern > results.txt
> sort < unsorted.txt | uniq > sorted.txt &> cd /path/to/directory
> cd ~
> cdPress Ctrl+D or close the terminal.
Node Structure: Represents a command in the pipeline
struct node {
int type; // EXEC, REDIR, PIPE, or BG
char *cmd_line; // The command string
char *file; // Redirection target file
int redir_type; // 1: >, 2: <, 3: >>
struct node *next; // Next command in pipeline
};- Parser (
parse_line,parse_segment): Tokenizes input and builds command tree - Executor (
execute_pipeline): Manages process creation, pipes, and file descriptors - Signal Handlers: Manages SIGINT (Ctrl+C) and SIGCHLD (zombie reaping)
- Built-ins: Implements shell built-in commands
Input → Parse → Build Node Chain → Execute Pipeline → Wait/Continue
↓
Fork → Setup FDs → Exec
- Each command in a pipeline runs in its own forked process
- Parent process tracks foreground process for signal delivery
- SIGCHLD handler asynchronously reaps terminated background processes
- Pre-allocates all pipes before forking
- Each child inherits all pipe FDs and closes unused ones
- Proper setup of stdin/stdout redirection for each stage
- Dynamic allocation using
malloc,realloc, andcalloc - Proper cleanup with
free_node()after command execution - Uses
getline()for arbitrary-length input
- No quote handling (arguments with spaces require external quoting)
- No environment variable expansion (
$VAR) - No job control (
jobs,fg,bgcommands) - No command history or line editing
- No wildcards/globbing (
*,?) cddoesn't work in pipelines (only as standalone command)
- Command history with readline integration
- Environment variable expansion
- Quote and escape sequence handling
- Job control (track background jobs, implement
jobs,fg,bg) - Wildcard expansion
- More built-ins (
export,unset,exit,history) - Tab completion
- Configuration file support (.minishellrc)
# Test simple execution
> ls
# Test pipeline
> echo "test" | cat
# Test redirection
> echo "hello" > test.txt
> cat < test.txt
# Test background
> sleep 5 &
# Test complex pipeline
> cat /etc/passwd | grep root | cut -d: -f1# Empty input
>
# Multiple spaces
> ls -la
# Mixed features
> cat < input.txt | sort | uniq > output.txt &Contributions are welcome! Areas for improvement:
- Better error messages
- Additional built-in commands
- Quote and escape handling
- Environment variable support
- Test suite
This project is open source and available under the MIT License.
Built following POSIX standards and inspired by:
- The original Unix shell by Ken Thompson
- xv6 shell implementation
- Modern shells (bash, zsh, fish)
Created as a systems programming project to demonstrate Unix process management and shell implementation.
Note: This is an educational project demonstrating Unix systems programming concepts. It is not intended as a replacement for production shells like bash or zsh.