Go to file
2025-10-02 10:15:37 +02:00
includes evaluation done 2022-04-26 11:27:00 +02:00
libft fix norm 2022-04-19 12:41:00 +02:00
srcs evaluation done 2022-04-26 11:27:00 +02:00
ignoreliberror first 2022-03-06 16:07:02 +01:00
launch_minishell fix leak parent and add cmd to launch with good settings 2022-04-16 16:18:20 +02:00
Makefile evaluation done 2022-04-26 11:27:00 +02:00
README.md docs: enhance README with detailed Unix shell implementation guide 2025-10-02 10:15:37 +02:00

Minishell - École 42

Description

Minishell est un projet de l'École 42 qui consiste à créer un shell Unix minimaliste mais fonctionnel, similaire à bash. Ce projet permet de comprendre en profondeur le fonctionnement des shells, la gestion des processus, et l'exécution de commandes sous Unix.

Objectifs pédagogiques

  • Maîtriser la programmation système Unix/Linux
  • Comprendre l'exécution de processus (fork, exec, wait)
  • Gérer les pipes et redirections d'I/O
  • Implémenter un parser pour analyser les commandes
  • Traiter les signaux système (SIGINT, SIGQUIT)
  • Gérer les variables d'environnement

Fonctionnalités implémentées

Built-ins

  • echo avec option -n
  • cd avec chemins relatifs et absolus
  • pwd - affichage du répertoire courant
  • export - définition de variables d'environnement
  • unset - suppression de variables
  • env - affichage de l'environnement
  • exit - fermeture du shell avec code de retour

Fonctionnalités shell

  • Exécution de programmes via PATH ou chemin absolu
  • Pipes (|) pour chaîner les commandes
  • Redirections :
    • < redirection d'entrée
    • > redirection de sortie
    • >> redirection de sortie en mode append
    • << here document avec délimiteur
  • Variables d'environnement ($VAR, $?, $$)
  • Gestion des quotes simples et doubles
  • Historique des commandes
  • Autocomplétion basique

Gestion des signaux

  • Ctrl+C (SIGINT) - interruption
  • Ctrl+D (EOF) - fermeture propre
  • Ctrl+\ (SIGQUIT) - ignoré en mode interactif

Technologies utilisées

  • Langage : C (norme 42)
  • Bibliothèques : readline, termcap
  • Appels système : fork, execve, wait, pipe, dup2
  • Gestion mémoire : malloc, free (pas de leaks)

Architecture du projet

Structure des fichiers

Minishell/
├── Makefile              # Compilation
├── includes/             # Headers (.h)
│   ├── minishell.h      # Header principal
│   └── libft.h          # Bibliothèque libft
├── srcs/                # Code source
│   ├── main.c           # Point d'entrée
│   ├── parsing/         # Analyseur lexical/syntaxique
│   │   ├── lexer.c
│   │   ├── parser.c
│   │   └── expander.c
│   ├── execution/       # Exécution des commandes
│   │   ├── executor.c
│   │   ├── pipes.c
│   │   └── redirections.c
│   ├── builtins/        # Commandes intégrées
│   │   ├── echo.c
│   │   ├── cd.c
│   │   ├── pwd.c
│   │   ├── export.c
│   │   ├── unset.c
│   │   ├── env.c
│   │   └── exit.c
│   ├── signals/         # Gestion des signaux
│   │   └── signals.c
│   └── utils/           # Fonctions utilitaires
│       ├── env_utils.c
│       ├── error.c
│       └── cleanup.c
└── libft/               # Bibliothèque personnelle

Flux d'exécution

  1. Lecture de la ligne de commande (readline)
  2. Tokenisation et analyse lexicale
  3. Parsing et construction de l'AST
  4. Expansion des variables et wildcards
  5. Exécution avec gestion des processus
  6. Nettoyage mémoire et gestion d'erreurs

Installation et compilation

Prérequis

  • GCC compiler
  • Make
  • Bibliothèque readline (sudo apt-get install libreadline-dev)

Compilation

git clone <repository-url>
cd Minishell
make

Nettoyage

make clean     # Supprime les fichiers .o
make fclean    # Supprime tout + l'exécutable
make re        # Recompile entièrement

Utilisation

Lancement

./minishell

Exemples de commandes

# Commandes simples
$ ls -la
$ pwd
$ echo "Hello World"

# Pipes
$ cat file.txt | grep "pattern" | wc -l
$ ls | head -5

# Redirections
$ echo "test" > output.txt
$ cat < input.txt
$ ls >> log.txt

# Here document
$ cat << EOF
> line 1
> line 2
> EOF

# Variables d'environnement
$ export MY_VAR="value"
$ echo $MY_VAR
$ echo $?    # Code de retour dernière commande
$ echo $$    # PID du shell

# Built-ins
$ cd /home/user
$ pwd
$ env | grep PATH
$ unset MY_VAR
$ exit 0

Gestion des quotes

$ echo "Hello $USER"        # Expansion dans les doubles quotes
$ echo 'Hello $USER'        # Pas d'expansion dans les simples quotes
$ echo "He said 'hello'"    # Imbrication de quotes

Gestion d'erreurs

Types d'erreurs gérées

  • Commandes introuvables (command not found)
  • Permissions insuffisantes (permission denied)
  • Fichiers inexistants (no such file or directory)
  • Erreurs de syntaxe (syntax error)
  • Erreurs de pipe (broken pipe)
  • Allocation mémoire (malloc failure)

Codes de retour

  • 0 - Succès
  • 1 - Erreur générale
  • 2 - Erreur de syntaxe
  • 126 - Permission refusée
  • 127 - Commande introuvable
  • 130 - Interruption par signal

Parsing et analyse

Étapes du parsing

  1. Tokenisation : Division en tokens (mots, opérateurs)
  2. Classification : Identification du type de chaque token
  3. Validation syntaxique : Vérification de la grammaire
  4. Construction AST : Arbre syntaxique abstrait
  5. Expansion : Variables, quotes, wildcards

Grammaire simplifiée

command_line : pipeline
pipeline     : command ('|' command)*
command      : simple_command redirection*
simple_command : word word*
redirection  : '<' word | '>' word | '>>' word | '<<' word

Gestion mémoire

Stratégies appliquées

  • Allocation tracking : Suivi de toutes les allocations
  • Cleanup systématique : Libération en cas d'erreur
  • Valgrind clean : Aucun leak détecté
  • Error handling : Gestion robuste des échecs malloc

Tests et validation

Tests automatisés

# Tests de base
make test

# Tests avec valgrind
make test_memory

# Tests de régression
make test_all

Cas de test couverts

  • Commandes simples et complexes
  • Pipes multiples
  • Redirections combinées
  • Gestion d'erreurs
  • Variables d'environnement
  • Signaux et interruptions

Optimisations

Performance

  • Parser optimisé pour les cas courants
  • Gestion mémoire efficace
  • Exécution directe des built-ins
  • Cache PATH pour les exécutables

Compatibilité

  • POSIX compliance pour les fonctionnalités de base
  • Bash-like behavior pour l'expérience utilisateur
  • Cross-platform (Linux, macOS)

Compétences développées

  • Programmation système avancée Unix/Linux
  • Gestion des processus et communication inter-processus
  • Parsing et analyse syntaxique
  • Architecture logicielle modulaire
  • Debugging multi-processus
  • Gestion mémoire rigoureuse sans leaks
  • Tests et validation de systèmes complexes

Contraintes et normes 42

  • Norme de codage 42 strictement respectée
  • Pas de variables globales (sauf une pour les signaux)
  • Gestion d'erreurs exhaustive
  • Pas de memory leaks (validé Valgrind)
  • Fonctions autorisées uniquement celles de la liste 42

Challenges techniques

Difficultés rencontrées

  • Parsing complexe avec gestion des quotes et échappements
  • Gestion des signaux dans un contexte multi-processus
  • Race conditions entre processus père et fils
  • Memory management dans un contexte d'erreurs multiples
  • Compatibilité bash pour les edge cases

Solutions apportées

  • Architecture modulaire facilitant la maintenance
  • Error handling centralisé et robuste
  • Tests exhaustifs couvrant les cas limites
  • Documentation du code pour la compréhension

Auteur

Alexandre Pommier (apommier) - École 42

Licence

Projet académique - École 42