École 42
Pipex
Réimplémenter un pipe shell (cmd1 | cmd2) avec fork, pipe, dup2 et execve, jusqu'à enchaîner un nombre arbitraire de commandes et lire un heredoc.
Le contexte
Pipex reproduit ce que fait le shell quand il exécute < infile cmd1 | cmd2 > outfile : un processus fils est créé pour chaque commande, leurs entrées et sorties standard sont redirigées via un pipe, et chacune est finalement remplacée par execve. La partie bonus étend ce mécanisme à un nombre quelconque de commandes chaînées, ainsi qu'à un mode heredoc qui lit l'entrée standard jusqu'à un délimiteur donné.
À qui appartient un buffer
Le mode heredoc a été l'occasion de manipuler une règle simple en apparence mais facile à négliger en C : quand une fonction retourne un pointeur vers une zone qu'elle a elle-même allouée, la responsabilité de la libérer doit être transférée à l'appelant, jamais reprise localement après le retour. Un principe de propriété mémoire qui revient dans énormément de code C au-delà de ce projet, et qui structure directement la façon d'écrire une fonction qui retourne un pointeur.
Un compteur, un rôle
Enchaîner un nombre arbitraire de commandes a demandé de séparer clairement deux boucles qui, au premier abord, semblaient pouvoir partager un seul compteur : celle qui choisit le mode d'ouverture du fichier de sortie, et celle qui parcourt la liste des commandes à exécuter. Donner à chaque boucle son propre compteur, même quand cela semble redondant, est une habitude directement issue de ce projet : mélanger deux rôles dans une seule variable de boucle est une source d'erreurs discrète, qui ne se voit qu'à l'usage.
Valider contre la référence
Vérifier que pipex se comporte comme le pipe shell qu'il reproduit (cmd1 | cmd2) a demandé de comparer systématiquement sa sortie à celle du shell, sur des chaînes de deux, trois et quatre commandes. Tester contre un comportement de référence connu plutôt que contre une intuition du résultat attendu est devenu une façon de valider par défaut ce genre de projet de réimplémentation.
Code bientôt disponible sur GitHub.