elouann.dev
EN — English version

ProjetsSystèmes, réseau & algorithmes

Minishell

Une réplique de Bash POSIX

Période
mars 2025 – mai 2025
Cadre
cursus 42
Équipe
en groupe
Note
101/100
  • C
  • Bas-niveau
  • Programmation impérative
  • Shell
  • CLI
  • Unix

Voir le code

Une réplique de Bash, à deux, en C. De la ligne tapée au clavier jusqu’aux processus qui s’exécutent, il a fallu reproduire tout ce que fait un shell, y compris dans ses cas les plus tordus.

readlinela lignelexertokensparsercommandesexpansion$VAR, quotesexecfork / execve$ ls -l | grep .c > out.txtminishellparent, attendfork()fork()ls -lexecvepipegrep .cexecveout.txtstdout = pipe[1]stdin = pipe[0]dup2(fd, 1)fds dupliqués
SchémaEn haut, le trajet d’une ligne de commande. En bas, ce qui se passe réellement pour une ligne avec un pipe et une redirection.

Lire une ligne

La ligne est découpée en mots et en opérateurs (lexer), puis regroupée en commandes avec leurs redirections (parser). Il faut respecter les guillemets simples et doubles, développer les variables comme $HOME ou $?, et gérer les redirections <, >, >> et le heredoc <<.

Exécuter

Pour une suite de commandes reliées par des pipes, le shell crée les pipe(), fait un fork() par commande, branche les entrées et sorties avec dup2(), puis lance le programme avec execve() après l’avoir cherché dans le PATH. Les builtins (cd, echo, export, unset, env, pwd, exit) sont codés à la main, car certains doivent modifier le shell lui-même.

Les signaux changent de comportement selon le contexte : Ctrl+C vide la ligne au prompt, interrompt une commande en cours, et annule un heredoc. Toute la mémoire est libérée à chaque tour, et l’environnement est notre propre liste, qui fonctionne même lancé sans environnement.

En plus

Quatre thèmes de couleur pour le prompt, à choisir au lancement avec -t. C’était aussi mon premier vrai projet à deux : se répartir le parsing et l’exécution demandait de bien définir ce qui passait de l’un à l’autre.

Ce que j’en retiens

  • fork, pipe, dup2, execve et waitpid : le cœur de Unix tient en cinq appels.
  • Un descripteur de fichier oublié ouvert peut bloquer tout un pipeline.
  • Une interface claire entre deux parties du code facilite le travail à deux.