Binfmt

De Lea Linux
Révision datée du 16 décembre 2006 à 20:47 par Notafish (discussion | contributions) (mise en forme)
Aller à la navigation Aller à la recherche

Associer un type de fichier avec un exécutable

Associer un type de fichier avec un exécutable
Pour faire aussi bien que Windows, mais en utilisant une méthode qui nous laisse le contrôle de tout le processus d'exécution, et en utilisant le principe des droits d'exécution cher aux systèmes Un*x.

Un problème : associer un type de fichiers avec une application

Le problème est le suivant : sur un système Un*x, l'exécution d'un programme repose sur les permissions (j'aime mieux dire droits) d'exécution. Mais les environnements actuels autorisent à gérer comme des exécutables du système, des fichiers de données, via une association. Le problème est que tous ces environnements n'utilisent pas, loin s'en faut, le même système d'association. Pour l'administrateur c'est un casse-tête chinois : il faut créer les associations pour KDE, les recréer pour Gnome, et ainsi de suite.

La solution : binfmt

La solution parait, somme toute, évidente : faire en sorte que tel fichier soit considéré par le système comme un exécutable standard. Pour cela il faut faire en sorte que le noyau de Linux soit capable de reconnaître de nouveaux exécutables.

Pour cela il faut recompiler le noyau avec l'option : [Kernel support MISC binaries] activée (dans le noyau lui même c'est plus simple, mais pas obligatoire : vous pouvez aussi utiliser un module). Cette étape pénible mais nécessaire accomplie, on relance le noyau (autrement dit on reboote... sauf si vous avez compilé cette option en tant que module auquel cas il vous suffit de charger le dit module à grand coup de modprobe binfmt_misc).

On peut vérifier que tout va bien en faisant :

[user@becane ~]$ cat /proc/sys/fs/binfmt_misc/status
enabled

Si vous obtenez un message d'erreur c'est que vous n'avez pas chargé le module, ou que vous n'avez pas booté sur le bon noyau. Réparez votre erreur et tout devrait rentrer dans l'ordre.

Maintenant, supposons que vous souhaitiez à l'invocation d'un fichier .txt lancer automatiquement la commande less <le-dit-fichier>.txt. Eh bien, ce n'est pas très compliqué : il suffit maintenant de le dire au noyau par la commande (sur une seule ligne) :

[user@becane ~]$ echo ":format-txt:E::txt::/usr/bin/less:" > /proc/sys/fs/binfmt_misc/register

Attention : tous les <:> sont significatifs. On peut vérifier que tout à fonctionné comme prévu :

[user@becane ~]$ cat /proc/sys/fs/binfmt_misc/format-txt
enabled
interpreter /usr/bin/less
extension .txt

Tout message d'erreur est anormal (vérifier que vous tapez bien tout comme c'est indiqué). Il ne reste plus qu'à marquer comme exécutable un fichier .txt par une commande du type :

[user@becane ~]$ chmod a+x readme.txt

Pour «l'exécuter» il suffit maintenant, soit de cliquer dessus, soit de taper :

[user@becane ~]$ ./readme.txt

de la même façon que si c'était un exécutable. Pour rendre exécutable n'importe quel fichier .txt il suffit maintenant le marquer comme exécutable pour le système et tous vos gestionnaires de programmes quels qu'ils soient pourront les exécuter en cliquant simplement dessus.

En utilisant la même même méthode vous pouvez rendre exécutable vos images, vos fichiers de paquetages (.rpm) etc.

évidemment, il y a un petit problème : quand vous redémarrerez Linux (ce qui n'arrive que très rarement ;) toutes ces belles associations seront perdues, et il faudra les retaper à la main...

Une automatisation possible

Une solution pourrait être de mettre dans un script appelé au démarrage de Linux toutes les commandes qu'il faut pour activer ces associations. Cette solution n'est pas très souple, et nécessite de modifier un script pour chaque ajout que nous ne manquerons pas de vouloir faire. Nous retiendrons plutôt la solution d'un fichier de configuration dans /etc et d'un script un peu plus général.

Le script

Sauvez ce script sous /usr/sbin/binfmt

#!/bin/sh
if [ ! -e /etc/binfmt.conf ] ; then
        echo -n "Pas de fichier /etc/binfmt.conf,"
        echo "je n\'ai rien à faire."
        exit 0
else
        echo /etc/binfmt.conf trouvé
fi

if [ -x /sbin/modprobe ] 
   && [ ! -d /proc/sys/fs/binfmt_misc ] ; then
        echo chargement du module binfmt_misc
        /sbin/modprobe binfmt_misc ;
fi

if [ -d /proc/sys/fs/binfmt_misc ] ; then
        echo module binfmt_misc chargé

        echo -n "Effacement des associations précédentes : "
        for i in `ls /proc/sys/fs/binfmt_misc/* \
                  | grep -v -e "/status"        \
                  | grep -v -e "/register"` ; do
                echo -n "$i, "
                echo -1 > $i
        done
        echo

        for i in `cat /etc/binfmt.conf          \
                  | grep -v -e "^[\t ]*#.*"` ; do
                echo $i |    \
                  awk -F':'  \
                      '{print ("Les extensions [",$5,"] \
                      sont associées à : [",$7,"].") ; }'
                echo $i > /proc/sys/fs/binfmt_misc/register
        done

else
        echo -n "Impossible de charger le modules binfmt_misc. "
        echo -n "êtes-vous root ? "
        echo "Avez-vous compilé le noyau avec binfmt_misc activé ?"
        exit 1
fi

Explications :

Le script lit une par une les lignes du fichier /etc/binfmt.conf en rejetant les lignes commençant par un <#>, et envoie celles-ci directement dans /proc/sys/fs/binfmt_misc/register. Il nous faut donc un fichier de configuration.

Le fichier de configuration

Ce qui suit est un exemple de fichier de configuration à sauver dans /etc/binfmt.conf. Adaptez-le à vos programmes préférés.

#!/etc/binfmt.conf
# pour en savoir plus sur le format des lignes de configuration
# que l'on peut envoyer a /proc/sys/fs/binfmt_misc/register
# lire /usr/src/linux/Documentation/binfmt_misc.txt

# on associe les .pdf à acrobat reader
:pdf-acrobat:E::pdf::/opt/acrobat/bin/acroread:

# on associe les .png et .gif à ElectricEyes
:png-gimp:E::png::/opt/gnome/bin/ee:
:gif-gimp:E::gif::/opt/gnome/bin/ee:

# on associe les .rpm à kpackage
:rpm-kpackage:E::rpm::/usr/bin/kpackage:

# on associe les .txt et .doc à gless
:txt-gless:E::txt::/opt/gnome/bin/gless:
:doc-gless:E::doc::/opt/gnome/bin/gless:

Il ne reste plus qu'à ajouter la ligne : /usr/sbin/binfmt au fichier /etc/rc.d/rc.sysinit (sur une Mandrake/Red Had, ou dans le rc.local par exemple) pour que nos associations soient chargées à chaque démarrage de Linux.

Conclusion

Pour parfaire la configuration de votre boîte Linux, vous n'avez plus qu'à mettre dans /etc/binfmt.conf toutes les associations que vous souhaitez. Elles seront reconnues par tous les gestionnaires de fichiers du monde Linux sans aucun travail supplémentaire. On pourrait créer un utilitaire plus fenêtré que celui que j'ai fourni, qui serait capable de d'ajouter au vol des associations. Mais cela pas dans une optique d'administration d'un système, plus dans celui d'une machine utilisée par quelques personnes qui ne voudraient pas avoir tous les même associations.

Et n'oubliez pas de marquer comme exécutable la plupart des fichiers que vous aurez associés. C'est le cas par défaut des fichiers qui sont sur des partitions vfat et souvent iso9660.

Note de Jean-Christophe :
Vous pouvez aussi utiliser la commande umask : cette commande permet de choisir le mode par défaut associé à chaque nouveau fichier d'un utilisateur. En ajoutant dans votre $HOME/.bashrc la ligne umask mode (où mode est une combinaison de chiffres octaux ou de 'r', 'w' et 'x' comme pour chmod (voir rubrique [shell.php3 Shell] et [permissions.php3 Permissions])), tous vos nouveaux fichiers auront ce mode par défaut.

Cette page est issue de la documentation 'pré-wiki' de Léa a été convertie avec HTML::WikiConverter. Elle fut créée par Frédéric Bonnaud le 15/04/2000.

Copyright

Copyright © 15/04/2000, Frédéric Bonnaud

Creative Commons License
Creative Commons Attribution iconCreative Commons Share Alike iconCreative Commons Noncommercial
Ce document est publié sous licence Creative Commons
Attribution, Partage à l'identique, Contexte non commercial 2.0 :
http://creativecommons.org/licenses/by-nc-sa/2.0/fr/