Un interpréteur de commandes simplifié inspiré de bash, réalisé dans le cadre du cursus 42.
Minishell est une implémentation d'un shell Unix minimaliste en C. Il permet d'exécuter des commandes, de gérer les redirections d'entrée/sortie, les pipes, les variables d'environnement et propose plusieurs commandes intégrées (builtins).
| Commande | Description |
|---|---|
echo |
Affiche les arguments (option -n pas de /n) |
cd |
Change le répertoire courant |
pwd |
Affiche le répertoire de travail actuel |
export |
Définit ou modifie des variables d'environnement |
unset |
Supprime des variables d'environnement |
env |
Affiche les variables d'environnement |
exit |
Quitte le shell avec un code de sortie optionnel |
| Opérateur | Description |
|---|---|
< |
Redirection de l'entrée standard |
> |
Redirection de la sortie standard (écrasement) |
>> |
Redirection de la sortie standard (ajout) |
<< |
Here-document (heredoc) |
- Support du pipe
|pour chaîner les commandes - Gestion de multiples pipes dans une même ligne de commande
$VAR: expansion des variables d'environnement$?: code de retour de la dernière commande- Gestion des guillemets simples et doubles
Ctrl+C: affiche un nouveau prompt (mode interactif)Ctrl+\: ignoré en mode interactifCtrl+D: quitte le shell
- GCC
- Make
- Bibliothèque readline (
libreadline-devsur Debian/Ubuntu)
# Cloner le dépôt
git clone <url-du-depot> minishell
cd minishell
# Compiler le projet
make
# Nettoyer les fichiers objets
make clean
# Nettoyer tout (objets + exécutable)
make fclean
# Recompiler entièrement
make re./minishellminishell> echo "Hello World"
Hello World
minishell> ls -la | grep minishell
minishell> cat < fichier.txt > sortie.txt
minishell> export MA_VAR="valeur"
minishell> echo $MA_VAR
valeur
minishell> << EOF cat
> Ceci est un heredoc
> EOF
Ceci est un heredoc
minishell> exitLe projet est divisé en trois modules principaux qui s'exécutent séquentiellement :
Entrée utilisateur → [PARSING] → [EXÉCUTION] → Sortie
Le parsing transforme la ligne de commande en structures exploitables par l'exécution.
1. Lecture (readline)
↓
2. Tokenisation
- Découpage en tokens (mots, opérateurs)
- Identification des types (ARG, PIPE, REDIR_IN, REDIR_OUT, etc.)
- Gestion des guillemets (simples et doubles)
↓
3. Expansion des variables
- Remplacement de $VAR par sa valeur
- Gestion de $? (code de retour)
- Respect des règles de guillemets
↓
4. Construction des commandes
- Création de la liste chaînée t_cmd
- Attribution des arguments, fichiers d'entrée/sortie
- Comptage des commandes et pipes
↓
5. Validation
- Vérification de la syntaxe
- Détection des erreurs (guillemets non fermés, redirections invalides)
Structures principales :
t_token: représente un token (valeur, type, flag d'expansion)t_cmd: représente une commande (arguments, redirections, heredoc)t_prompt: structure globale (liste de commandes, pipes, environnement)
L'exécution prend les structures du parsing et lance les commandes.
┌─────────────────┐
│ Commande unique │
│ ou pipeline ? │
└────────┬────────┘
│
┌──────────────────┴──────────────────┐
▼ ▼
┌─────────────┐ ┌───────────────┐
│ UNIQUE │ │ PIPELINE │
└──────┬──────┘ └───────┬───────┘
│ │
▼ ▼
┌─────────────┐ ┌───────────────┐
│ Builtin ? │ │ Création des │
└──────┬──────┘ │ pipes │
│ └───────┬───────┘
┌─────┴─────┐ │
▼ ▼ ▼
┌───────┐ ┌────────┐ ┌───────────────┐
│ Oui │ │ Non │ │ Pour chaque │
│ │ │ │ │ commande : │
│Exécute│ │ fork() │ │ fork() │
│ dans │ │ + │ └───────┬───────┘
│ le │ │execve()│ │
│parent │ │ │ ▼
└───────┘ └────────┘ ┌───────────────┐
│ Redirection │
│ des pipes │
│ + execve() │
└───────┬───────┘
│
▼
┌───────────────┐
│ waitpid() │
│ pour tous │
└───────────────┘
Gestion des pipes :
- Création d'un tableau de pipes (n-1 pipes pour n commandes)
- Chaque processus enfant :
- Lit depuis le pipe précédent (si ce n'est pas la première commande)
- Écrit vers le pipe suivant (si ce n'est pas la dernière commande)
- Le parent ferme tous les pipes et attend tous les enfants
Gestion des redirections :
- Sauvegarde des descripteurs originaux avec
dup() - Redirection avec
dup2() - Restauration après exécution des builtins
Les builtins sont exécutés directement dans le processus principal (sauf dans un pipeline).
| Builtin | Particularités |
|---|---|
cd |
Met à jour PWD et OLDPWD |
export |
Affichage trié alphabétiquement sans argument |
exit |
Vérifie si l'argument est numérique |
echo |
Gestion du flag -n en début d'arguments |
minishell/
├── Builtins/ # Implémentation des commandes intégrées
│ ├── builtin.c # Dispatcher des builtins
│ ├── builtin_echo.c
│ ├── builtin_cd.c
│ ├── builtin_pwd.c
│ ├── builtin_export.c
│ ├── builtin_unset.c
│ ├── builtin_env.c
│ └── builtin_exit.c
├── Exec/ # Moteur d'exécution
│ ├── exec.c # Point d'entrée de l'exécution
│ ├── exec_cmd.c # Exécution des commandes
│ ├── exec_pipe*.c # Gestion des pipes
│ ├── exec_heredoc.c # Gestion des heredocs
│ └── exec_path.c # Recherche dans le PATH
├── Parsing/ # Analyse syntaxique
│ ├── parsing_all.c # Orchestration du parsing
│ ├── parsing_tokenization_*.c # Tokenisation
│ ├── parsing_expender*.c # Expansion des variables
│ └── parsing_cmd_*.c # Construction des commandes
├── includes/ # Fichiers d'en-tête
│ └── minishell.h
├── libft/ # Bibliothèque utilitaire
├── main.c # Point d'entrée principal
├── handle_signal.c # Gestion des signaux
└── Makefile
| Code | Signification |
|---|---|
| 0 | Succès |
| 1 | Erreur générale |
| 2 | Erreur de syntaxe |
| 126 | Permission refusée |
| 127 | Commande introuvable |
| 130 | Interruption par Ctrl+C |
- edaubert
- jbensimo
Projet réalisé à l'école 42.