execrom(8) : l’exécuteur de ROMs
Sous les systèmes d’exploitation de type Unix, il est possible de lancer des programmes textes interprétés comme s’ils étaient des exécutables natifs. Il suffit pour ce faire de placer en tête du fichier une ligne començant par « #! » et se terminant par le chemin absolu vers le programme capable de l’interpréter. Un argument peut aussi être donné. Par exemple, un fichier possédant les permissions appropriées et contenant le programme suivant est exécuté par le programme /bin/sh et affiche « Salut! ».
Cette fonctionalité est très utile et polyvalente. Elle n’est malheureusement pas compatible avec tous les fichiers qu’on voudrait pouvoir exécuter de cette manière: l’interpréteur doit traiter cette première ligne comme un commentaire, l’ignorer, et certains types de fichier contenant des programmes en format texte ou en format binaire ne le permettent pas.
Mon objectif en concevant execrom(8) était de rendre possible l’exécution de ROMs compatibles avec le CPU fictif Uxn sans avoir à en spécifier explicitement l’interpréteur ni avoir à donner le chemin vers la ROM à interpréter. Bref, je voulais pouvoir les lancer à la manière des autres programmes du système. La solution que je propose ici est plus générable. Elle est capable de préparer l’interprétation de n’importe quel fichier avec presque n’importe quel interpréteur, pourvu que l’interpréteur approprié se trouve dans le chemin (PATH) et qu’il soit programmé pour interpréter le programme donné comme premier argument.
Principe
Le fonctionnement d’execrom(8) repose sur le fait qu’il est possible d’invoquer un même programme par différents noms, et que le nom d’invocation est accessible au programme invoqué. Selon une convention presque unanime, le premier élement de la liste d’arguments donnés à un programme correspond au nom d’invocation. Dans l’interpréteur de commandes, il est contenu dans la variable $0.
Dans l’exemple qui suit, le fichier illustration.sh contient un programme interprété qui affiche son nom d’invocation.
N’oublions pas d’autoriser l’exécution du programme.
Si le programme est invoqué par « ./illustration.sh », $0 contient « ./illustration.sh »; s’il est invoqué par « ././illustration.sh », $0 contient « ././illustration.sh », etc.
On peut invoquer le programme avec un nom complètement différent grâce aux liens symboliques. En créant un tel lien nommé « autre_nom.sh » vers « illustration.sh », on peut exécuter le même programme sous cet autre nom.
Cette donnée permet à un programme de prendre des décisions informées par son nom d’invocation.
L’idée est donc la suivante. Les fichiers à interpréter sont placés dans un ou plusieurs dossiers répertoriés par la variable EXECROM_CHEM et dont la structure est analogue à celle de PATH. Le nom de ces fichiers a la forme « nom.interpréteur », où le préfixe « nom » correspond au nom du programme à interpréter et où le suffixe « interpréteur » est le nom de l’exécutable destiné à interpréter le programme. À son lancement, execrom(8) prend connaissance de son nom d’invocation et parcourt les dossiers répertoriés dans EXECROM_CHEM à la recherche d’un fichier dont le préfixe soit conforme au nom d’invocation. S’il le trouve, il exécute l’interpréteur désigné par le suffixe, en lui donnant sa liste d’arguments en argument.
L’idée est probablement plus facile à saisir avec un exemple.
Exemple
J’illustrerai l’utilisation d’execrom(8) avec drifblim et left, deux programmes écrits pour la machine virtuelle Varvara. Je supposerai que leurs ROMs se trouvent dans le dossier ~/uxn.
drifblim est un assembleur uxntal interprétable par la machine virtuelle en mode texte uxncli(1). La commande ci-dessous assemble prog.tal dans prog.rom.
left est un éditeur de texte en mode graphique. Il doit donc être interprété par uxnemu(1). La commande suivante ouvre le fichier doc.txt avec l’éditeur.
Je trouve que ces longues commandes rendent l’utilisation des ROMs pour Uxn peu conviviale. Mais grâce à execrom(8), il est possible d’exécuter les ROMs directement.
Pour ce faire, il faut régler la variable d’environnement EXECROM_CHEM pour qu’elle contienne le chemin vers le dossier où se trouvent les ROMs, ici, ~/uxn.
Il faut aussi modifier le nom de chaque ROM pour que son préfixe et son suffixe correspondent à son nom d’invocation et au nom du programme destiné à l’interpréter, respectivement. Le résultat devrait être le suivant.
Enfin, un lien symbolique accessible par PATH et pointant vers l’exécutable d’execrom(8) doit être créé pour chaque ROM. Ici, je prends pour acquis qu’execrom(8) est installé dans /usr/local/libexec/execrom.
Voilà!
Conclusion
Je suis pour l’instant très content de mon outil. Il est très discret une fois installé et rend l’utilisation des ROMs Uxn bien plus conviviales. Malheureusement, il n’est pas dépourvu d’inconvénients; j’en ai identifié deux.
D’abord, cette méthode est moins simple à mettre en place qu’on ne pourrait l’espérer. Pour rendre exécutables des programmes sh, Perl, Python, Lua… compatibles avec la syntaxe, il suffit d’une ligne commençant par « #! » et d’un « chmod +x ». La méthode execrom(8) impose d’installer un outil supplémentaire, de régler la variable d’environnement EXECROM_CHEM pour qu’elle contienne le ou les dossiers appropriés, de donner un nom spécial aux ROMs dans une convention inusitée et de créer un lien symbolique vers l’exécutable de l’utilitaire. Ces manipulations rendent cette méthode un peu plus fragile. Je n’ai pourtant pas trouvé mieux.
Aussi, ce mécanisme n’est pas compatible avec les interpréteurs qui s’attendent à recevoir en argument plus qu’un le chemin vers un programme. Par exemple, pour être interprété, un programme awk(1) doit être donné en argument à l’option -f. Or execrom(8) n’a accès qu’au nom de l’interpréteur approprié, et non aussi aux options requises.
Il n’y a pas de solution universelle.