$ ./minishell
yufonten@minishell:~ $ echo "hello, world" | cat -e | tr a-z A-Z > out.txt
yufonten@minishell:~ $ cat out.txt
HELLO, WORLD$
Minishell é uma reimplementação minimalista do shell bash, escrita inteiramente em C sem dependências externas além da libc e da GNU Readline. O projeto reproduz o ciclo completo de um interpretador de comandos POSIX: leitura da linha de comando, análise léxica, análise sintática, expansão de variáveis, execução de processos, gestão de descritores de arquivos e tratamento de sinais — tudo isso com gestão manual de memória e zero memory leaks.
Este é um dos projetos mais desafiadores do currículo da École 42, exigindo domínio profundo de chamadas de sistema POSIX, gerenciamento de processos e arquitetura de software em baixo nível.
| Categoria | Implementação |
|---|---|
| 🔧 Builtins | cd, echo (com flag -n), env, exit, export, pwd, unset |
| 🔀 Pipes | Encadeamento ilimitado de comandos via | com gestão de FDs e forks |
| 📤 Redirecionamentos | < (input), > (output), >> (append), << (heredoc) |
| 💲 Expansão de variáveis | $VAR, $? (exit status), preservação dentro de aspas duplas |
| 🗣️ Aspas | Aspas simples (literais) e duplas (com expansão) totalmente suportadas |
| ⚡ Sinais | SIGINT (Ctrl+C) e SIGQUIT (Ctrl+\) tratados em foreground e durante heredoc |
| 🌍 Variáveis de ambiente | Manipulação completa via export/unset, herança em subprocessos |
| 🎨 Prompt customizado | Estilo bash colorido com usuário, host e diretório atual |
| 📜 Histórico | Navegação por comandos anteriores via setas (via Readline) |
| 🧹 Zero leaks | Validado com valgrind --leak-check=full --show-leak-kinds=all |
O projeto segue uma separação rigorosa de responsabilidades em módulos independentes:
minishell/
├── inc/ # Headers públicos
│ └── minishell.h # Definições centrais e structs
├── src/
│ ├── main.c # Loop principal REPL
│ ├── prompt/ # 🎨 Renderização do prompt
│ ├── struct/ # 📦 Tokenização (linha → lista duplamente ligada)
│ ├── parser/ # 🧠 Análise léxica, sintática e expansão
│ │ ├── check_input.c # Validação de entrada
│ │ ├── check_syntax.c # Validação de sintaxe (pipes/redirects)
│ │ ├── analyzer.c # Classificação semântica de tokens
│ │ ├── expander.c # Expansão de variáveis ($VAR, $?)
│ │ └── remove_quotes.c # Remoção de aspas pós-expansão
│ ├── executor/ # ⚙️ Engine de execução (fork/execve/wait)
│ │ ├── ft_pipe.c # Pipeline recursivo de processos
│ │ └── path_commad.c # Resolução de PATH
│ ├── builtins/ # 🔧 Implementações dos comandos internos
│ ├── redirect/ # 📤 Redirecionamentos e heredocs
│ ├── signals/ # ⚡ Handlers de SIGINT/SIGQUIT
│ └── utils/ # 🛠️ Helpers e gestão de ambiente
├── libft/ # 📚 Biblioteca C customizada
└── ft_fprintf/ # 🖨️ Implementação própria de printf
┌─────────────┐ ┌───────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────────┐
│ readline │───▶│ tokenize │───▶│ analyzer │───▶│ expander │───▶│ check_syntax │
└─────────────┘ └───────────┘ └──────────────┘ └──────────┘ └──────────────┘
│
▼
┌─────────────┐ ┌───────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────────┐
│ cleanup │◀───│ waitpid │◀───│ execve │◀───│ fork │◀───│ redirections│
└─────────────┘ └───────────┘ └──────────────┘ └──────────┘ └──────────────┘
Este projeto consolida um conjunto sólido e profissional de competências em engenharia de sistemas:
- Gerenciamento manual de memória (
malloc/free) com zero leaks - Estruturas de dados customizadas (listas duplamente ligadas, enums de estado)
- Manipulação intensa de ponteiros, ponteiros duplos e strings
- Modularização com headers e separação clara entre interface e implementação
- Conformidade estrita com Norminette (padrão de código da École 42)
- Process management:
fork(),execve(),wait(),waitpid(),exit() - IPC:
pipe()para comunicação entre processos encadeados - File descriptors:
dup(),dup2(),close(),open(),unlink() - Signal handling:
signal(),SIGINT,SIGQUIT,WIFSIGNALED,WTERMSIG - Terminal control:
ioctl()comTIOCSTIpara manipulação de TTY - Environment: leitura, escrita e propagação do ambiente em subprocessos
- Tokenizer/Lexer com reconhecimento de operadores, palavras, aspas e variáveis
- Parser sintático com validação de gramática (pipes/redirects/comandos)
- AST-like token list: estrutura encadeada com metadados semânticos
- Expansion phase: substituição de variáveis com precedência correta de aspas
- Build system modular com
Makefile(compilação incremental, regrasre/fclean) - Bibliotecas estáticas: integração de
libft.aelibftprintf.a(escritas do zero) - Tratamento robusto de erros: códigos de saída fiéis ao bash
- Debugging avançado com
gdb(-ggdb3) evalgrind(com supressões customizadas) - Versionamento Git com histórico limpo e commits semânticos
- Pair programming: projeto desenvolvido em dupla, com divisão clara de responsabilidades
sudo apt install build-essential libreadline-dev # Debian/Ubuntu
brew install readline # macOSgit clone https://github.com/YuriFont/minishell.git
cd minishell
make./minishellmake clean # remove objetos
make fclean # remove objetos + binário
make re # rebuild completomake valgrind_supression# Pipes encadeados
$ ls -la | grep .c | wc -l
# Redirecionamento + heredoc
$ cat << EOF > greeting.txt
Hello from minishell!
EOF
# Expansão de variáveis e exit status
$ echo "User $USER finished with code $?"
# Variáveis de ambiente
$ export MY_VAR="42"
$ env | grep MY_VARYuri Fontenele — Estudante na 42 Rio
- 🐙 GitHub: @YuriFont
- 🏫 Intra 42: yufonten Erick Ramos — Estudante na École 42
- 🐙 GitHub: @erickramosxp
- 🏫 Intra 42: yufonten
Minishell is a minimal reimplementation of the bash shell, written entirely in C with no external dependencies beyond libc and GNU Readline. The project reproduces the full lifecycle of a POSIX command interpreter: command-line reading, lexical analysis, syntactic parsing, variable expansion, process execution, file descriptor handling and signal management — all with manual memory management and zero memory leaks.
This is one of the most challenging projects in the École 42 curriculum, requiring deep mastery of POSIX system calls, process management and low-level software architecture.
| Category | Implementation |
|---|---|
| 🔧 Builtins | cd, echo (with -n flag), env, exit, export, pwd, unset |
| 🔀 Pipes | Unlimited command chaining via | with FD and fork management |
| 📤 Redirections | < (input), > (output), >> (append), << (heredoc) |
| 💲 Variable expansion | $VAR, $? (exit status), preserved inside double quotes |
| 🗣️ Quotes | Single (literal) and double (with expansion) quotes fully supported |
| ⚡ Signals | SIGINT (Ctrl+C) and SIGQUIT (Ctrl+\) handled in foreground and heredoc |
| 🌍 Environment variables | Full manipulation via export/unset, inheritance to subprocesses |
| 🎨 Custom prompt | Bash-style colored prompt with user, host and current directory |
| 📜 History | Navigation of past commands via arrow keys (Readline integration) |
| 🧹 Zero leaks | Validated with valgrind --leak-check=full --show-leak-kinds=all |
The project enforces a strict separation of concerns across independent modules:
minishell/
├── inc/ # Public headers
│ └── minishell.h # Core definitions and structs
├── src/
│ ├── main.c # Main REPL loop
│ ├── prompt/ # 🎨 Prompt rendering
│ ├── struct/ # 📦 Tokenization (line → doubly-linked list)
│ ├── parser/ # 🧠 Lexing, syntax and expansion
│ │ ├── check_input.c # Input validation
│ │ ├── check_syntax.c # Syntax validation (pipes/redirects)
│ │ ├── analyzer.c # Semantic token classification
│ │ ├── expander.c # Variable expansion ($VAR, $?)
│ │ └── remove_quotes.c # Post-expansion quote removal
│ ├── executor/ # ⚙️ Execution engine (fork/execve/wait)
│ │ ├── ft_pipe.c # Recursive process pipeline
│ │ └── path_commad.c # PATH resolution
│ ├── builtins/ # 🔧 Built-in command implementations
│ ├── redirect/ # 📤 Redirections and heredocs
│ ├── signals/ # ⚡ SIGINT/SIGQUIT handlers
│ └── utils/ # 🛠️ Helpers and env management
├── libft/ # 📚 Custom C library
└── ft_fprintf/ # 🖨️ Custom printf implementation
┌─────────────┐ ┌───────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────────┐
│ readline │───▶│ tokenize │───▶│ analyzer │───▶│ expander │───▶│ check_syntax │
└─────────────┘ └───────────┘ └──────────────┘ └──────────┘ └──────────────┘
│
▼
┌─────────────┐ ┌───────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────────┐
│ cleanup │◀───│ waitpid │◀───│ execve │◀───│ fork │◀───│ redirections│
└─────────────┘ └───────────┘ └──────────────┘ └──────────┘ └──────────────┘
This project consolidates a solid, professional set of systems engineering skills:
- Manual memory management (
malloc/free) with zero leaks - Custom data structures (doubly-linked lists, state enums)
- Heavy pointer, double-pointer and string manipulation
- Modular code with headers and clear interface/implementation split
- Strict compliance with Norminette (École 42's coding standard)
- Process management:
fork(),execve(),wait(),waitpid(),exit() - IPC:
pipe()for inter-process communication in chained commands - File descriptors:
dup(),dup2(),close(),open(),unlink() - Signal handling:
signal(),SIGINT,SIGQUIT,WIFSIGNALED,WTERMSIG - Terminal control:
ioctl()withTIOCSTIfor TTY manipulation - Environment: reading, writing and propagating env across subprocesses
- Tokenizer/Lexer recognizing operators, words, quotes and variables
- Syntactic parser validating grammar (pipes/redirects/commands)
- AST-like token list: linked structure carrying semantic metadata
- Expansion phase: variable substitution honoring quote precedence
- Modular build system with
Makefile(incremental builds,re/fcleanrules) - Static libraries: integration of
libft.aandlibftprintf.a(written from scratch) - Robust error handling: exit codes faithful to bash
- Advanced debugging with
gdb(-ggdb3) andvalgrind(with custom suppressions) - Git versioning with clean history and semantic commits
- Pair programming: developed in a duo with clearly split responsibilities
sudo apt install build-essential libreadline-dev # Debian/Ubuntu
brew install readline # macOSgit clone https://github.com/YuriFont/minishell.git
cd minishell
make./minishellmake clean # remove object files
make fclean # remove objects + binary
make re # full rebuildmake valgrind_supression# Chained pipes
$ ls -la | grep .c | wc -l
# Redirection + heredoc
$ cat << EOF > greeting.txt
Hello from minishell!
EOF
# Variable expansion and exit status
$ echo "User $USER finished with code $?"
# Environment variables
$ export MY_VAR="42"
$ env | grep MY_VARYuri Fontenele — Estudante na 42 Rio
- 🐙 GitHub: @YuriFont
- 🏫 Intra 42: yufonten Erick Ramos — Estudante na École 42
- 🐙 GitHub: @erickramosxp
- 🏫 Intra 42: yufonten