As beautiful as a shell.
A fully functional Unix shell written from scratch in C.
Handles pipes, redirections, environment variables, signals, and built-in commands โ
replicating core bash behavior with strict memory discipline.
- About
- Features
- Built-in Commands
- Redirections & Pipes
- Getting Started
- Usage Examples
- Architecture
- Signal Handling
- Testing
- Project Structure
- Author
Minishell is the most complex project in the 42 common core before the final exams. It requires building a bash-like shell that handles:
- Tokenization and parsing of user input
- Abstract Syntax Tree (AST) construction for command pipelines
- Process creation with
fork()andexecve() - File descriptor management for redirections and pipes
- Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
- Environment variable expansion and management
This is a team project โ building it deepens your understanding of how Unix actually works under the hood.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MINISHELL FEATURES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โ
Interactive prompt with command history โ
โ โ
Command execution via PATH resolution โ
โ โ
Single and double quote handling โ
โ โ
Environment variable expansion ($VAR, $?) โ
โ โ
Input redirection ( < file ) โ
โ โ
Output redirection ( > file ) โ
โ โ
Append redirection ( >> file ) โ
โ โ
Here-document ( << DELIMITER ) โ
โ โ
Pipes ( cmd1 | cmd2 | cmd3 ) โ
โ โ
Exit status tracking ( $? ) โ
โ โ
Signal handling ( Ctrl+C, Ctrl+D, Ctrl+\ ) โ
โ โ
7 built-in commands โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Command | Syntax | Description |
|---|---|---|
echo |
echo [-n] [text] |
Print text; -n suppresses trailing newline |
cd |
cd [path] |
Change working directory |
pwd |
pwd |
Print current working directory |
export |
export [KEY=value] |
Set environment variable |
unset |
unset [KEY] |
Remove environment variable |
env |
env |
Display all environment variables |
exit |
exit [status] |
Exit the shell with optional status code |
minishell$ echo "Hello, 42!"
Hello, 42!
minishell$ echo -n "no newline"
no newlineminishell$
minishell$ cd /tmp && pwd
/tmp
minishell$ export MY_VAR="hello world"
minishell$ echo $MY_VAR
hello world
minishell$ unset MY_VAR
minishell$ echo $MY_VAR
minishell$ env | grep PATH
PATH=/usr/local/bin:/usr/bin:/bin
minishell$ exit 42# Input redirection โ read from file
< infile cat
# Output redirection โ write to file (overwrite)
echo "hello" > outfile
# Append redirection โ write to file (append)
echo "world" >> outfile
# Here-document โ read until delimiter
cat << EOF
This is a heredoc
Multiple lines supported
EOF# Simple pipe
ls -la | grep ".c"
# Multi-pipe
cat file.txt | grep "pattern" | wc -l
# Pipes with redirections
< infile grep "search" | sort | uniq > outfile# Pipe + redirection + built-in
env | grep USER > user_info.txt
# Here-doc + pipe
cat << STOP | wc -l
line one
line two
line three
STOP
# Multiple redirections
< input.txt sort > sorted.txt- GCC compiler
- GNU Make
readlinelibrary (libreadline-devon Debian/Ubuntu)
# Install readline (if needed)
sudo apt-get install libreadline-dev # Debian/Ubuntu
brew install readline # macOS
# Compile
make
# Run
./minishellmake # Build minishell
make clean # Remove object files
make fclean # Remove everything
make re # Full rebuild# Start the shell
./minishell
# Execute commands like bash
minishell$ ls -la
minishell$ cat /etc/hostname
minishell$ echo "Current dir: $PWD"
# Pipes
minishell$ ls | wc -l
minishell$ cat Makefile | grep "FLAGS" | head -1
# Redirections
minishell$ echo "test" > output.txt
minishell$ cat < output.txt
minishell$ ls -la >> log.txt
# Environment variables
minishell$ export NAME="Adil"
minishell$ echo "Hello $NAME, exit status was $?"
# Exit
minishell$ exit# Single quotes โ no expansion
minishell$ echo '$USER is not expanded'
$USER is not expanded
# Double quotes โ expansion happens
minishell$ echo "$USER is expanded"
adil is expanded
# Mixed quotes
minishell$ echo "Hello '$USER'"
Hello 'adil'โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MINISHELL PIPELINE โ
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โ INPUT โ โ โ LEXER โ โ โ PARSER โ โ
โ โ readline โ โ tokenize โ โ build AST โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโฌโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โ OUTPUT โ โ โ EXECUTOR โ โ โ EXPANDER โ โ
โ โ stdout โ โ fork+execโ โ $VAR โ valโ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Lexer โ Breaks input into tokens (words, operators, quotes)
- Parser โ Builds command structure with redirections
- Expander โ Resolves
$VAR,$?, and quote removal - Executor โ Forks processes, sets up pipes/redirections, calls
execve()
| Signal | Interactive Mode | During Execution |
|---|---|---|
Ctrl+C (SIGINT) |
New prompt on new line | Interrupts child process |
Ctrl+D (EOF) |
Exits the shell | Closes stdin for child |
Ctrl+\ (SIGQUIT) |
Ignored | Sends SIGQUIT to child |
# Basic commands
ls -la
echo hello world
cat /etc/hostname
# Pipes
ls | grep Makefile | wc -l
# Redirections
echo test > /tmp/test_minishell
cat < /tmp/test_minishell
# Exit status
ls nonexistent_file
echo $? # Should print non-zero
# Edge cases
"" # Empty quotes
'' # Empty single quotes
| # Error: syntax errorvalgrind --leak-check=full --show-leak-kinds=all \
--suppressions=readline.supp ./minishellThe
readline.suppfile suppresses known readline library leaks that are not our responsibility.
minishell/
โโโ include/ # Header files
โ โโโ minishell.h
โโโ parsing/ # Lexer, parser, token handling
โ โโโ tokenizer.c
โ โโโ parser.c
โ โโโ expander.c
โ โโโ quotes.c
โโโ execution/ # Command execution engine
โ โโโ executor.c
โ โโโ pipes.c
โ โโโ redirections.c
โ โโโ builtins.c
โโโ functions_utils1/ # Utility functions
โโโ minishell.c # Main loop
โโโ readline.supp # Valgrind suppressions
โโโ Makefile
โโโ README.md
Adil Bourji โ @adi7-x
42 School ยท Common Core ยท Unix ยท Processes