https://github.com/chgomez04/minishell
Unix shell implementation in C developed at 42 Barcelona, with parsing, pipes, redirections, builtins, signals and environment expansion.
https://github.com/chgomez04/minishell
42-barcelona 42-school bash c execve file-descriptors fork lexer linux makefile minishell parser pipes readline redirections shell signals unix
Last synced: about 4 hours ago
JSON representation
Unix shell implementation in C developed at 42 Barcelona, with parsing, pipes, redirections, builtins, signals and environment expansion.
- Host: GitHub
- URL: https://github.com/chgomez04/minishell
- Owner: chgomez04
- Created: 2026-06-21T10:58:12.000Z (16 days ago)
- Default Branch: main
- Last Pushed: 2026-06-21T11:50:25.000Z (15 days ago)
- Last Synced: 2026-06-21T14:17:51.725Z (15 days ago)
- Topics: 42-barcelona, 42-school, bash, c, execve, file-descriptors, fork, lexer, linux, makefile, minishell, parser, pipes, readline, redirections, shell, signals, unix
- Language: C
- Homepage: https://github.com/chgomez04
- Size: 1.29 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
*This project was created as part of the 42 curriculum by tmege and chgomez.*
# minishell
## Overview
`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`.
## Description
`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:
```text
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.
## Features
- Interactive prompt using GNU Readline.
- Command history support.
- External command execution.
- `PATH` resolution.
- 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.
## Supported Built-ins
| 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 |
## Supported Operators
| Operator | Description |
| --- | --- |
| `|` | Connects commands through a pipeline |
| `<` | 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 |
## Signal Behavior
| 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.
## Technologies
- 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`
## Project Structure
```text
.
├── 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
```
## Requirements
Install GNU Readline development files before compiling.
On Debian or Ubuntu:
```bash
sudo apt-get install libreadline-dev
```
You also need:
- `cc`
- `make`
- A Unix-like environment
## How to Compile
Compile the project:
```bash
make
```
This generates the executable:
```text
minishell
```
Remove object files:
```bash
make clean
```
Remove object files and the executable:
```bash
make fclean
```
Rebuild the project:
```bash
make re
```
## How to Run
Start the shell:
```bash
./minishell
```
Exit the shell:
```bash
exit
```
or press:
```text
Ctrl-D
```
## Usage Examples
Run a simple command:
```bash
echo "Hello, minishell"
```
Use an environment variable:
```bash
echo $USER
```
Check the previous exit status:
```bash
echo $?
```
Run a pipeline:
```bash
ls -la | grep ".c" | wc -l
```
Use input and output redirection:
```bash
cat < input.txt > output.txt
```
Append output to a file:
```bash
echo "new line" >> output.txt
```
Use a heredoc:
```bash
cat << EOF
hello
world
EOF
```
Use a quoted heredoc delimiter to avoid expansion:
```bash
cat << 'EOF'
$HOME is kept literal here
EOF
```
## Behavior at a Glance
| 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 |
## Testing
Rebuild the project:
```bash
make re
```
Run Norminette if available:
```bash
norminette inc src Libft get_next_line
```
Run the shell:
```bash
./minishell
```
Suggested manual tests:
```bash
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:
```bash
|
echo >
cat <
echo hello |
```
Suggested signal tests:
```bash
sleep 10
```
Then press `Ctrl-C`.
## Implementation Highlights
- 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`, `unset` and `cd`.
- Cleanup logic releases allocated memory and closes file descriptors across success and error paths.
## What I Learned
- 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.
## Resources
- 42 minishell subject
- Bash Reference Manual
- POSIX Shell and Utilities documentation
- GNU Readline documentation
- Linux manual pages:
- `man fork`
- `man execve`
- `man pipe`
- `man dup2`
- `man waitpid`
- `man signal`
- `man readline`
## Notes
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.
## Authors
`tmege`
42 Barcelona student
Christian Gómez (`chgomez`)
Junior Software Developer in training at 42 Barcelona
GitHub: [github.com/chgomez04](https://github.com/chgomez04)