This project was created as part of the 42 curriculum by tmege and chgomez.
minishell is a Unix shell implementation written in C.
The project recreates a focused subset of Bash behavior, including interactive input, lexical analysis, syntax validation, environment expansion, command parsing, process execution, pipes, redirections, built-ins and signal handling.
The goal of the project is to understand how a shell works internally and how Unix processes, file descriptors, signals and environment variables interact.
Built collaboratively by tmege and chgomez.
minishell reads a command line from the user, analyzes it, expands variables, builds an internal command representation and executes the result.
The command-processing flow is divided into clear stages:
input -> lexer -> syntax checker -> expander -> parser -> executor
The project focuses on:
- Interactive command-line input.
- Tokenization and quote-aware parsing.
- Syntax validation for pipes and redirections.
- Environment variable expansion.
- Built-in command implementation.
- Execution of external commands through
PATH. - Process creation with
fork(). - Program execution with
execve(). - File descriptor redirection with
dup2(). - Pipeline execution with
pipe(). - Signal handling in interactive and child-process contexts.
- Memory management and cleanup.
- Interactive prompt using GNU Readline.
- Command history support.
- External command execution.
PATHresolution.- Multi-command pipelines.
- Input redirection with
<. - Output redirection with
>. - Append redirection with
>>. - Heredoc support with
<<. - Single quote handling.
- Double quote handling.
- Environment variable expansion with
$VARIABLE. - Previous exit status expansion with
$?. - Built-in command execution.
- Exit status propagation.
- Interactive signal handling.
- Clean resource management.
| Built-in | Description |
|---|---|
echo |
Prints arguments to standard output |
cd |
Changes the current working directory |
pwd |
Prints the current working directory |
export |
Adds or updates environment variables |
unset |
Removes environment variables |
env |
Prints the current environment |
exit |
Exits the shell |
| Operator | Description |
|---|---|
| ` | ` |
< |
Redirects input from a file |
> |
Redirects output to a file, truncating it |
>> |
Redirects output to a file, appending to it |
<< |
Starts a heredoc input block |
| Input | Behavior |
|---|---|
Ctrl-C |
Interrupts the current prompt or running child process |
Ctrl-\ |
Managed differently depending on interactive or execution context |
Ctrl-D |
Exits the shell when entered on an empty prompt |
Signal behavior is handled differently depending on whether the shell is waiting for input or executing a child process.
- C language
- Unix system calls
- GNU Readline
- File descriptors
- Pipes
- Processes
- Signals
- Environment variables
- Dynamic memory management
- Makefile
- Compilation with
cc - Flags:
-Wall -Wextra -Werror
.
├── Makefile
├── README.md
├── es.subject.pdf
├── Libft/
├── get_next_line/
├── inc/
│ └── minishell.h
└── src/
├── builtins/
├── executor*.c
├── expander*.c
├── heredoc*.c
├── lexer*.c
├── parser*.c
├── redirections.c
├── signals.c
├── syntax_check.c
└── main source files
Install GNU Readline development files before compiling.
On Debian or Ubuntu:
sudo apt-get install libreadline-devYou also need:
ccmake- A Unix-like environment
Compile the project:
makeThis generates the executable:
minishell
Remove object files:
make cleanRemove object files and the executable:
make fcleanRebuild the project:
make reStart the shell:
./minishellExit the shell:
exitor press:
Ctrl-D
Run a simple command:
echo "Hello, minishell"Use an environment variable:
echo $USERCheck the previous exit status:
echo $?Run a pipeline:
ls -la | grep ".c" | wc -lUse input and output redirection:
cat < input.txt > output.txtAppend output to a file:
echo "new line" >> output.txtUse a heredoc:
cat << EOF
hello
world
EOFUse a quoted heredoc delimiter to avoid expansion:
cat << 'EOF'
$HOME is kept literal here
EOF| Area | Supported behavior |
|---|---|
| Commands | External commands with arguments |
| Pipelines | Multi-stage pipelines |
| Redirections | <, >, >>, << |
| Quoting | Single quotes, double quotes and mixed quoting |
| Expansion | Environment variables and $? |
| Built-ins | echo, cd, pwd, export, unset, env, exit |
| Signals | Interactive and execution-time signal behavior |
Rebuild the project:
make reRun Norminette if available:
norminette inc src Libft get_next_lineRun the shell:
./minishellSuggested manual tests:
echo hello
echo "$USER"
echo '$USER'
pwd
cd ..
pwd
export TEST=minishell
echo $TEST
unset TEST
env
ls -la | grep ".c" | wc -l
cat < input.txt | grep minishell > output.txt
echo $?Suggested syntax-error tests:
|
echo >
cat <
echo hello |Suggested signal tests:
sleep 10Then press Ctrl-C.
- The lexer converts user input into tokens while respecting quotes.
- The syntax checker validates pipe and redirection placement before execution.
- The expander resolves environment variables and
$?. - The parser transforms tokens into executable command structures.
- The executor handles built-ins, external commands, pipes and process creation.
- Redirection logic manages input, output, append and heredoc file descriptors.
- Signal handling is adapted for interactive mode and child-process execution.
- Environment data is stored and updated internally for built-ins such as
export,unsetandcd. - Cleanup logic releases allocated memory and closes file descriptors across success and error paths.
- How Unix shells parse and execute commands.
- How to build a lexer and parser for command-line input.
- How quoting rules affect tokenization and expansion.
- How environment variable expansion works.
- How to implement built-in shell commands.
- How to create processes with
fork(). - How to execute programs with
execve(). - How to connect commands with
pipe(). - How to redirect input and output with
dup2(). - How to manage signals in interactive programs.
- How to organize a larger C project with multiple modules.
- How to work collaboratively on a complex C codebase.
- 42 minishell subject
- Bash Reference Manual
- POSIX Shell and Utilities documentation
- GNU Readline documentation
- Linux manual pages:
man forkman execveman pipeman dup2man waitpidman signalman readline
This project follows the constraints and style expected in the 42 curriculum.
The implementation is intentionally written in C and focuses on shell internals, parsing, process management, file descriptors, signals and environment handling.
This is not intended to be a full Bash replacement. It implements the subset of behavior required by the project subject.
tmege
42 Barcelona student
Christian Gómez (chgomez)
Junior Software Developer in training at 42 Barcelona
GitHub: github.com/chgomez04