Skip to content

edaubert42/minishell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

130 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minishell

Un interpréteur de commandes simplifié inspiré de bash, réalisé dans le cadre du cursus 42.

Description

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).

Fonctionnalités

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

Redirections

Opérateur Description
< Redirection de l'entrée standard
> Redirection de la sortie standard (écrasement)
>> Redirection de la sortie standard (ajout)
<< Here-document (heredoc)

Pipes

  • Support du pipe | pour chaîner les commandes
  • Gestion de multiples pipes dans une même ligne de commande

Expansion de variables

  • $VAR : expansion des variables d'environnement
  • $? : code de retour de la dernière commande
  • Gestion des guillemets simples et doubles

Gestion des signaux

  • Ctrl+C : affiche un nouveau prompt (mode interactif)
  • Ctrl+\ : ignoré en mode interactif
  • Ctrl+D : quitte le shell

Compilation

Prérequis

  • GCC
  • Make
  • Bibliothèque readline (libreadline-dev sur Debian/Ubuntu)

Installation

# 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

Utilisation

./minishell

Exemples

minishell> 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> exit

Architecture

Vue d'ensemble

Le projet est divisé en trois modules principaux qui s'exécutent séquentiellement :

Entrée utilisateur → [PARSING] → [EXÉCUTION] → Sortie

Module de Parsing

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)

Module d'Exécution

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 :

  1. Création d'un tableau de pipes (n-1 pipes pour n commandes)
  2. 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)
  3. 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

Module 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

Structure du projet

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

Codes de retour

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

Auteurs

  • edaubert
  • jbensimo

Projet réalisé à l'école 42.

About

Let's replicate a 🐚

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors