pipex
pipex est un projet systèmes en C où je recrée le comportement d’un pipe UNIX entre deux commandes. L’idée est de comprendre “ce qui se passe vraiment” derrière une ligne de shell, en manipulant directement les appels système : processus, redirections, pipes et exécution de commandes.
L’objectif est double :
- Comprendre comment le shell connecte l’output d’une commande à l’input d’une autre via
pipe(). - Maîtriser la gestion de processus avec
fork()+execve()et les redirections avecdup2().
Principe
Le programme est lancé ainsi :
./pipex file1 cmd1 cmd2 file2
Il doit se comporter comme la commande shell suivante :
< file1 cmd1 | cmd2 > file2
Concrètement :
- Ouvrir
file1en lecture etfile2en écriture. - Créer un pipe (
pipe(fd)) pour relier deux processus. - fork #1 :
- rediriger
stdinversfile1 - rediriger
stdoutvers l’entrée du pipe -
exécuter
cmd1
4. fork #2 : -
rediriger
stdinvers la sortie du pipe - rediriger
stdoutversfile2 - exécuter
cmd2
5. Fermer les bons descripteurs etwait()les enfants.
Points importants
- Parsing des commandes : gérer
cmd+ arguments (ex."ls -l") et construireargvpourexecve(). - Résolution du binaire : retrouver le chemin de la commande via
PATH(ou gérer un chemin absolu/relatif). - Redirections propres : fermer systématiquement les fd inutiles pour éviter les deadlocks et fuites de descripteurs.
- Gestion d’erreurs : messages clairs (permissions, fichier absent, commande introuvable, etc.) et exit codes cohérents.
Contraintes respectées
- Appels système typiques :
open/close,dup/dup2,pipe,fork,execve,wait/waitpid,access, etc. - Gestion mémoire :
malloc/free(zéro leak) - Makefile standard (pas de relink)
- Libft autorisée (si intégrée)
Ce que ça m’a apporté
pipex m’a fait passer un cap sur la programmation UNIX : compréhension des flux (stdin/stdout), maîtrise des processus et du cycle fork → exec, et rigueur sur la gestion des ressources (fd/mémoire). C’est une base très concrète pour la suite (minishell, webserv, etc.).
Bonus
- Chaînage de plusieurs commandes :
bash
./pipex file1 cmd1 cmd2 cmd3 ... cmdn file2
équivalent à :
bash
< file1 cmd1 | cmd2 | cmd3 ... | cmdn > file2
- Support
here_doc:
bash
./pipex here_doc LIMITER cmd cmd1 file
équivalent à :
bash
cmd << LIMITER | cmd1 >> file
Syntaxe
./pipex file1 cmd1 cmd2 file2
Équivalent shell
< file1 cmd1 | cmd2 > file2
Ce que doit faire le programme
- Lire depuis
file1et écrire le résultat final dansfile2. - Exécuter
cmd1puis envoyer sa sortie dans un pipe. - Exécuter
cmd2en lisant depuis ce pipe. -
Gérer correctement les erreurs :
-
fichiers (absent, permissions)
- commandes (introuvable)
- appels système (
pipe,fork,dup2,execve)
Notes importantes
- Le parsing doit produire un
argvexploitable parexecve(). - La recherche des binaires doit utiliser
PATH(sauf si un chemin est fourni). - Les fd inutiles doivent être fermés dans chaque processus.
Schéma mental
- Parent : crée le pipe + fork les deux enfants + wait
-
Enfant 1 (cmd1) :
-
stdin <- file1 stdout -> pipe_write-
Enfant 2 (cmd2) :
-
stdin <- pipe_read stdout -> file2
Pseudo-flux (simplifié)
pipe(p)→p[0]read,p[1]writepid1 = fork()
dup2(infile, STDIN_FILENO)dup2(p[1], STDOUT_FILENO)- fermer :
p[0],p[1],infile,outfile -
execve(cmd1_path, cmd1_argv, envp)
3.pid2 = fork() -
dup2(p[0], STDIN_FILENO) dup2(outfile, STDOUT_FILENO)- fermer :
p[0],p[1],infile,outfile -
execve(cmd2_path, cmd2_argv, envp)
4. Parent : -
fermer :
p[0],p[1],infile,outfile waitpid(pid1, ...),waitpid(pid2, ...)
Points d’attention
- Fermer les bons fd évite les blocages : si le parent garde
p[1]ouvert,cmd2peut attendre un EOF qui n’arrive jamais. - Codes de sortie et messages d’erreur : rester cohérent (ex. “command not found”, permissions…).
PATH: split + join +access(X_OK)pour résoudre le binaire.
Multi-pipe
./pipex file1 cmd1 cmd2 cmd3 ... cmdn file2
Équivalent :
< file1 cmd1 | cmd2 | cmd3 ... | cmdn > file2
here_doc
./pipex here_doc LIMITER cmd1 cmd2 file
Équivalent :
cmd1 << LIMITER | cmd2 >> file
Implémentation typique : lire depuis stdin jusqu’à LIMITER, écrire dans un pipe, puis chaîner comme d’habitude.