3 LPR

Contenu de cette section

Ce chapitre fut au départ la Foire Aux Questions lpd, puis a fait partie de la Foire Aux Questions Linux. Il est maintenant inclus dans ce document. Qui sait ce qu'il deviendra après...

3.1 Configurer les services d'impression

Cette partie a été originellement écrite par Karl Auer <Karl.Auer@anu.oedu.au> (11/1/93) et est maintenant incluse ici, car ce manuel, écrit dans le style d'un manuel de référence, ne remplissait pas complètement son objectif, puisqu'il ne décrivait pas franchement la façon de configurer les services d'impression sur votre machine Linux.

C'est maintenant chose faite. Quelques modifications ont été apportées au document d'origine. A noter que certaines informations peuvent donc être redondantes par rapport au reste du document. Elles devraient néanmoins être utiles aux nouveaux venus dans le monde des techniques de l'impression BSD.

Impression locale et impression distante

L'impression locale permet aux utilisateurs d'envoyer des travaux d'impression à l'imprimante directement rattachée à leur machine.

L'impression distante, par contre, permet de soumettre des travaux d'impression depuis une machine, à une autre machine sur le réseau, sur laquelle est connectée une imprimante.

De quoi avez vous besoin

Nous supposons que vous savez éditer un fichier texte sous Linux et que vous avez une bonne compréhension des notions de droits d'accès et de propriété (chmod, chown).

Nous supposons également que votre système Linux fonctionne correctement. En particulier, si vous souhaitez faire de l'impression distante, que votre réseau fonctionne déjà.

Consultez à ce propos les nombreuses documentations disponibles sur le sujet.

Comment fonctionne l'impression sous Linux

La façon la plus simple d'imprimer sous Unix (et donc Linux) est d'envoyer les données directement à l'imprimante.

ls >/dev/lp0

en est un exemple simple. Cette méthode, si elle a l'avantage d'être simple, ne tire pas avantage des caractéristiques multi-tâches de Linux, puisqu'elle attendra que l'imprimante ait absorbé toutes les données avant de se terminer. Plus l'imprimante est lente, et a un petit buffer, plus ce sera long.

Une meilleure méthode consiste à utiliser un spool d'impression, dont le rôle est de collecter les données temporairement dans des fichiers afin de les envoyer, en tâche de fond, à l'imprimante.

C'est la façon de travailler de Linux. Pour chaque imprimante est définie une zone de spool. Les données à envoyer à l'imprimante sont collectées dans le spool, un fichier par travail soumis. Le processus démon (donc en tâche de fond) est averti des nouveaux travaux soumis, et se charge d'envoyer les données à l'imprimante (locale), ou à la machine (distante) qui se chargera de l'impression. Lorsque plusieurs fichiers sont soumis, ils seront imprimés dans l'ordre de soumission. (premier entré, premier sorti). La zone de spool est donc bien une file. On dit que les travaux sont dans la file d'impression.

Lors de la soumission de travaux pour une imprimante distante, les fichiers sont d'abord mis en file localement avant d'être envoyés au démon distant qui se chargera alors de les mettre dans le spool de l'imprimante.

Toutes les informations nécessaires au démon (numéro du périphérique à utiliser, zone de spool, nom de la machine distante ou de l'imprimante, ...) sont décrites dans le fichier /etc/printcap. Les détails et la syntaxe de ce fichier son explicités plus loin.

Dans la description qui suit, le terme "imprimante" correspondra toujours à une imprimante déclarée dans /etc/printcap. Le terme "imprimante physique", correspondra toujours à l'objet qui imprime~! Il est possible d'avoir plusieurs entrées dans /etc/printcap, chacune définissant une imprimante physique différente, ou alors toutes décrivant la même imprimante, mais avec des options différentes. Vous comprendrez mieux les détails plus loin.

Les programmes importants

Le système d'impression Unix comprend (au moins) 5 programmes. Ils doivent se trouver à l'endroit décrit (c'est le mieux) ou dans un répertoire accessible (avec la variable PATH), appartenir à root (groupe lp), et avoir les permissions suivantes~:

        -r-sr-sr-x      root    lp      /usr/bin/lpr
        -r-sr-sr-x      root    lp      /usr/bin/lpq
        -r-sr-sr-x      root    lp      /usr/bin/lprm
        -r-xr-sr-x      root    lp      /usr/sbin/lpc
        -rwxr--r--      root    lp      /usr/sbin/lpd

Les quatre premiers sont utilisés pour soumettre, visualiser, annuler, contrôler les travaux d'impression. Le dernier est le démon.

Il existe bien entendu des pages de manuel en ligne pour ces commandes que vous pourrez consulter pour plus d'information. Le point important à noter est que les commandes lpr, lpq, lpc et lprm opèrent sur une imprimante par défaut nommée lp. La variable d'environnement PRINTER peut contenir le nom de l'imprimante que vous avez définie. La spécification du nom d'une imprimante sur la ligne de commande surchargera ces définitions (les imprimantes de l'exemple sont hors-ligne)~:

# echo $PRINTER
                           (vide)
#
# lpq
waiting for lpr0 to become ready (offline ?)
...
# export PRINTER=mon_imprimante
# lpq
waiting for mon_imprimante to become ready (offline ?)
...

# lpq -Plpr0
waiting for lpr0 to become ready (offline ?)
...

La commande lpr

La commande lpr soumet un travail d'impression. Elle se charge de mettre les données à imprimer dans un fichier dans le spool d'impression. Ces données peuvent provenir soit d'un fichier (les données sont dupliquées et toute modification ultérieure du fichier d'origine n'affectera pas l'impression), soit de l'entrée standard (stdin). Le démon est averti de l'existence d'un nouveau fichier et envoie, dès que possible, les données vers l'imprimante physique (ou la machine distante).

La commande lpq

La commande lpq affiche le contenu du spool, pour une imprimante donnée. Une des informations importantes fournies est le numéro du travail (job). C'est lui qui pourra servir à annuler un des travaux soumis, y compris celui en cours d'impression. Parmi tous les travaux soumis, l'indication "active" indique le travail en cours d'impression (ou que lpd essaie d'envoyer à l'impression).

La commande lprm

La commande lprm enlève un travail de la file (et donc le fichier du spool). Vous pouvez soit spécifier un numéro de job, soit un tiret permettant de supprimer tous les travaux vous appartenant. Si vous êtes root, tous les travaux sont supprimés. Pour supprimer les travaux d'un utilisateur, spécifiez son nom.

# lprm 1
dfA001Aa00484 dequeued
cfA001Aa00484 dequeued
#

Le premier fichier contient les données à imprimer. Il a été créé par lpr. Le deuxième contient des informations que le démon utilisera pour savoir que faire des donnés (impression locale, distante, ...) Consultez le manuel en ligne~: lpd(8)

Le commande lpc

La commande lpc permet de contrôler les travaux en cours ainsi que l'imprimante, et certains aspects de son utilisation. En particulier, vous pouvez démarrer ou stopper la sortie des travaux du spool pour l'impression, valider ou invalider une imprimante, et même modifier l'ordre d'impression des fichiers. Les commandes suivantes permettent d'invalider l'impression sur mon_imprimante, de valider le spool sur ton_imprimante, et de faire passer le job 37 en début de file~:

lpc down mon_imprimante
lpc enable ton_imprimante
lpc topq 37

lpc peut fonctionner en interactif si aucun paramètre ne lui est passé. Vous pouvez lire les pages du manuel en ligne pour obtenir des instructions complètes. A noter que certaines actions de lpc sont réservées à root.

Les répertoires importants

Le répertoire le plus important est le répertoire de spool, dans lequel les données vont être stockées avant d'être imprimées. Typiquement, un système sera configuré pour avoir un répertoire de spool par imprimante. Cela rend la gestion plus facile. Sur mon système, par exemple, le répertoire /usr/spool/lp est le répertoire principal. Sous ce répertoire, on y trouve le sous-répertoire lpr0, correspondant à la déclaration que j'ai faite dans /etc/printcap pour le répertoire de spool de mon imprimante.

NDT: Ce qui va suivre décrit une façon de faire pour donner les bons droits d'accès aux répertoires de spool. Différentes méthodes sont possibles, sachant que, comme sous Un*x, beaucoup de choses sont possibles dans ce domaine, il convient de faire attention de ne pas offrir de failles à la sécurité de l'ensemble.

Le répertoire de spool doit appartenir à root, et au groupe lp, avec les droits de lecture/d'écriture pour utilisateur et groupe, et lecture seule pour le reste du monde.

        chmod ug=rwx,o=rx lpr0
        chgrp lp lpr0

drwxrwxr-x   2 root     lp           1024 Feb 11 10:51 lpr0/

Un autre répertoire doit également être présent~: /usr/spool/lpd avec les mêmes droits. Vous aurez plus d'informations plus avant dans ce document.

Les fichiers importants

En dehors des programmes que nous avons déjà évoqués précédemment, quatre fichiers doivent se trouver dans chaque répertoire de spool Avec les versions récentes des gestionnaires d'impression, vous n'avez pas à vous soucier de ces fichiers. Ils sont créés automatiquement s'ils n'existent pas. ~: .seq, errs, lock et status. Ces fichiers doivent avoirs les droits -rw-rw-r--. Le fichier .seq contient un compteur pour l'affectation des numéros de jobs. Le fichier status contient le message devant être émis par la commande lpc~stat. Le fichier lock est utilisé par le démon pour qu'il n'imprime qu'un fichier à la fois. Le fichier errs contient les erreurs survenues sur l'imprimante.

Le fichier errs n'est pas obligatoire. De plus, il peut s'appeler comme vous le souhaitez, pourvu que son nom soit déclaré dans le fichier /etc/printcap que nous décrirons dans la suite.

A propos de /etc/printcap

Le fichier /etc/printcap, qui peut être modifié avec votre éditeur préféré, doit appartenir à root et avoir les droits suivants:

-rw-r--r--   1 root     system        164 Oct 25 21:23 /etc/printcap

Le contenu du fichier semble assez imcompréhensible à première vue. Il respecte effectivement une syntaxe particulière et malgré les apparences, assez simple lorsque l'on connaît~! Il n'y a pas toujours de manuels concernant ce fichier, et cela complique un peu les choses. Un petit conseil en passant~: essayez, dans la mesure du possible de rendre votre fichier le plus lisible possible, avec des commentaires. Vous pouvez consulter les pages du manuel en ligne concernant printcap(5) (ou empressez-vous de les récupérer si vous ne les avez pas). Plus loin sont décrits les paramètres importants.

Une entrée de printcap décrit une imprimante, c'est-à-dire une correspondance nom logique - imprimante physique, puis décrit la façon de transmettre les données. Par exemple, une entrée va décrire le périphérique physique à utiliser, le répertoire de spool, les traitements à effectuer sur les données avant impression, ou encore le répertoire dans lequel seront notifiées les erreurs. Vous pouvez aussi limiter la quantité de données pour un job, ou même limiter l'accès d'une imprimante à une classe d'utilisateurs. Vous trouverez dans la partie suivante la description des champs.

Il est tout à fait possible d'avoir plusieurs entrées décrivant différentes façons d'envoyer des données à une même imprimante physique. Par exemple, une imprimante physique peut supporter les formats HP LaserJet et PostScript, en fonction de la séquence de caractères envoyée au début d'un travail. Vous définirez donc deux entrées, l'une permettant de traiter le format HP, l'autre le format PostScript. Les programmes générant des données "HP" les enverront à l'imprimante HP, ceux générant des données PostScript les enverront à l'imprimante PostScript.

Les programmes qui modifient les données avant de les envoyer à l'imprimante physique sont des filtres.

Exemple d'entrée d'un fichier /etc/printcap~:

# exemple d'entree de printcap avec deux alias
lpr0|laserwriter\
# lp est le peripherique d'impression - ici une imprimante parallele
:lp=/dev/lp0:\
# sd signifie spool directory - ou les donnees sont collectees
:sd=/usr/spool/lp/lpr0:

Les champs de /etc/printcap

Il y a tellement de champs que nous ne pourrons tous les décrire ici. Nous verrons seulement les principaux. Tous les champs exceptés les noms d'imprimantes sont entourés de deux-points et repérés par un symbole de deux lettres suivi du signe égal. Ensuite est indiquée la valeur qui peut être numérique, booléenne ou chaîne de caractères~:

champ           type            signification

lp              string          designe le peripherique d'impression
sd              string          designe le repertoire de spool
lf              string          designe le fichier de rapport d'erreurs
if              string          specifie le nom du filtre d'entree
rm              string          designe le nom d'un site d'impression distant
rp              string          designe le nom d'une imprimante distante
sh              booleen         indique s'il faut supprimer les en-tetes
sf              booleen         indique s'il faut supprimer les sauts de pages de fin de travaux
mx              numerique       indique la taille maximum d'un job (en blocs = 1Ko sous linux)

Détails sur le champ lp

Si vous spécifiez /dev/null comme périphérique, tous les traitements se feront, mais tout partira à la poubelle. Ca semble ridicule, mais cela vous permet par exemple de tester une configuration. Lisez le chapitre Imprimantes qui ne sont pas de simples périphériques. Si vous désignez une imprimante distante avec rp et rm, lp doit contenir ":lp=:".

Ne laissez pas ce champ vide en cas d'impression locale, le démon signalerait une erreur.

Détails sur le champ lf

Tout fichier spécifié ici doit exister, sinon le rapport d'erreurs ne se ferait pas.

Détails sur le champ if

Les filtres d'entrée sont des utilitaires transformant les données qu'il reçoivent sur leur entrée standard en un format particulier qu'il sortent sur leur sortie standard. Typiquement, la conversion texte - PostScript déjà mentionnée. Voir Ecrire des filtres.

Si vous spécifiez un filtre d'entrée, le démon n'envoie pas directement les données au périphérique. Il exécute le filtre en dirigeant les donnés sur son entrée standard et en désignant le périphérique de sortie comme sortie standard. Voir Une entrée Printcap de test pour d'autres utilisations des filtres.

Détails sur les champs rm et rp

Envoyer des données à une imprimante rattachée à une machine distante est très simple~: il suffit de spécifier le nom de la machine avec rm et le nom de l'imprimante avec rp. S'assurer que l'entrée lp est vide. A noter que les données seront d'abord mises dans le spool local avant d'être transférées. Même si votre imprimante est distante, il faudra également un spool local. Tout filtre d'entrée sera bien entendu exécuté avant.

Détails sur les champs sh et sf

Les bannières concernent éventuellement les utilisations à plusieurs personnes. Elles identifient les jobs.

La suppression de ces bannières vous permet d'économiser du papier. Par contre la gestion des sauts de page sera plus intéressante, surtout si vous utilisez des traitements de textes qui formatent toujours des pages pleines. Dans ce cas, pas besoin de saut de page supplémentaire. Vous auriez sinon une page blanche en fin de chaque travail. Si vous utilisez des listings ou autres documents, ajouter un saut de page garantit que chaque travail commancera bien en début de page.

Détail sur le champ mx

Ce champ permet de limiter la taille des données pour chaque job. Le nombre à spécifier est en blocs de BUFSIZE (pardon, de 1 Ko sous Linux). La valeur 0 rend la taille illimitée, permettant la soumission de travaux limitée à la taille du disque. Notez que la limite concerne la taille des données mises en spool, et non pas les données envoyées à l'imprimante physique. Si la limite est dépassée, le fichier est tronqué avec l'émission d'un message disant: lpr: <fichier>: copy file is too large.

Cela peut être intéressant pour des imprimantes physiques en mode texte, notamment si des utilisateurs ou des programmes créent accidentellement des données trop volumineuses.

Si vous manquez de mémoire de masse, pourquoi n'inventeriez-vous pas un filtre qui décompresse ce qu'il a à envoyer à l'imprimante. Vous soumettriez alors des données compressées.

Une Entrée Printcap de test

Le shell-script suivant est un exemple de filtre très simple. Il ajoute ce qu'il reçoit à un fichier temporaire /tmp/testlp.out après avoir inséré une bannière. Dans le fichier printcap, nous spécifions ce filtre dans le champ if, puis utilisons le périphérique /dev/null. Il ne sera pas réellement utilisé, mais il faut spécifier quelque chose, sinon le démon émettrait une erreur.

# Ce fichier pourra etre place dans le repertoire de spool
# et nomme filtre_entree. Il devra appartenir a root
# et au groupe daemon, et etre executable par tout le monde.

echo ------------------------------------- >> /tmp/testlp.out
date                                       >> /tmp/testlp.out
echo ------------------------------------- >> /tmp/testlp.out
cat                                        >> /tmp/testlp.out

Voici l'entrée du fichier printcap. Notez la lisibilité (toute relative) et l'utilisation de caractères de continuation~:

lpr0|lpr0: \
        :lp=/dev/null: \
        :sd=/usr/spool/lp/lpr0: \
        :lf=/usr/spool/lp/lpr0/errs: \
        :if=/usr/spool/lp/lpr0/filtre_entree: \
        :mx#0: \
        :sh: \
        :sf:

Mettons tout ensemble

Mettre tout ce qui est ci-dessus ensemble~! Voici un guide de configuration étape par étape pour une imprimante nommée /dev/lp0. Vous pouvez l'étendre à votre guise. Pour faire ce qui suit, vous devez être root. (NDT~: L'auteur a tout installé dans /usr/spool/lpd. J'ai préféré modifier légèrement cette configuration en définissant /usr/spool/lp/lpr0 et /usr/spool/lpd, comme dans la plupart des distributions)

  1. Vérifiez les droits d'accès et l'emplacement de lpr, lprm, lpq, lpc et lpd. Voir à ce propos~: Les programmes importants.
  2. Créez le répertoire de spool pour votre imprimante, appelée dans notre exemple lpr0~:
    mkdir /usr/spool/lp /usr/spool/lp/lpr0
    chowm root.lp /usr/spool/lp /usr/spool/lp/lpr0
    chmod ug=rwx,o=rx /usr/spool/lp /usr/spool/lp/lpr0
    
  3. Créez un répertoire permettant au démon d'y mettre son propre fichier de verrouillage lpd.lock~:
    mkdir /usr/spool/lpd
    chowm root.lp /usr/spool/lpd
    chmod ug=rwx,o=rx /usr/spool/lpd
    
  4. Dans les répertoires /usr/spool/lp/lpr0 et /usr/spool/lpd, créez les fichier nécessaires, avec les bons droits (Cette manipulation n'est pas nécessaire avec les versions récentes du gestionnaire d'impression)~:
    cd /usr/spool/lp/lpr0
    touch .seq errs status lock
    chown root.lp .seq errs status lock
    chmod ug=rw,o=r errs status
    chmod u=rw,go=r lock
    chmod u=rw,g=r,o=x .seq
    
    cd /usr/spool/lpd
    touch .seq errs status lock
    chown root.lp .seq errs status lock
    chmod ug=rw,o=r errs status
    chmod u=rw,go=r lock
    chmod u=rw,g=r,o=x .seq
    
  5. Créez le shell-script "filtre_entree" dans le répertoire /usr/spool/lp/lpr0. Utilisez le filtre décrit précédemment. Donnez-lui les bons droits.
    cd /usr/spool/lp/lpr0
    chmod ug=rwx,o=rx filtre_entree
    
  6. Créez le fichier /etc/printcap, s'il n'existe pas. Enlevez les entrées qu'il contient et ajoutez une entrée de test décrite précédemment. Donnez-lui les droits -rw-r--r--.
  7. Editez le fichier rc.local ou rc.multi. Ajoutez la ligne /usr/sbin/lpd à la fin. Cela lancera le démon au boot. Vous pouvez aussi le lancer à la main~: #~/usr/sbin/lpd.
  8. Effectuez un test d'impression
    ls -l | lpr -Plpr0
    
  9. Regardez dans /tmp et vérifiez la présence du fichier testlp.out. Il devrait contenir le listing du répertoire dans lequel vous étiez.
  10. Editez /etc/printcap. Dupliquez l'entrée lpr0. Vous avez alors 2 entrées identiques.
    • Dans la première entrée, changez, sur la première ligne uniquement, les occurrences de lpr0 par testlp.
    • Dans la seconde entrée, changez /dev/null par le périphérique réel, par exemple /dev/lp0
    • Dans la seconde entrée, enlevez le champ if complètement.
  11. Rebootez le système ou tuez le démon d'impression et relancez-le, afin qu'il reprenne en compte le fichier /etc/printcap modifié.
  12. Refaites un test d'impression - Allumez votre imprimante. Cela devrait imprimer~!
    ls -l | lpr -Plpr0
    

L'impression à distance

Pour que des machines distantes puissent utiliser l'imprimante attachée à votre machine, le nom de ces machines doit être référencé soit dans le fichier /etc/hosts.lpd, soit dans le fichier /etc/hosts.equiv. Ce sont des fichiers textes normaux, dans lesquels on indique un nom de machine par ligne.

Il est préférable de déclarer les machines dans /etc/hosts.lpd spécialement réservé à l'impression, le fichier /etc/hosts.equiv donnant des droits plus étendus.

Vous pouvez restreindre les droits d'accès distants par groupe ou par utilisateur. Les groupes autorisés sont indiqués grâce au paramètre :rg=: du fichier printcap~; :rg=admin: restreint l'utilisation aux utilisateurs du groupe admin. Le paramètre booléen :rs=: du même fichier restreint l'accès aux utilisateurs ayant un compte sur votre machine.

Compléments et réglages

Si tout ce que vous avez fait ci-dessus fonctionne, vous devez avoir deux imprimantes déclarées, l'une, testlp, ajoutant les données reçues au fichier /tmp/testlp.out, l'autre lpr0, imprimant sans modification sur le périphérique physique attaché à /dev/lp0. Les deux partagent le même spool. A titre d'exercice, amusez-vous à définir un spool différent pour testlp.

Si votre imprimante est PostScript, elle peut ne pas être capable de traiter du texte pur. Si tel est le cas, vous devrez mettre en place un filtre pour transformer le texte en PostScript. Un excellent freeware Logiciel libre de tout droit de distribution et d'utilisation appelé nenscript réalise très bien cela. Si vous ne mettez pas en place un tel filtre, vous devez vous assurez par d'autres moyens que l'imprimante ne reçoit bien que du PostScript.

Vous pouvez également définir dans vos fichiers de login (.profile, par exemple) ou celui par défaut, une variable d'environnement PRINTER définissant l'imprimante à utiliser. Exemple~:

export PRINTER=lpr0

Ceci évite d'avoir à spécifier -Plpr0 à chaque fois.

Il est possible de "réutiliser" une entrée printcap. Si vous déclarez votre propre machine comme machine hôte distante, et une autre imprimante comme imprimante distante, vous pouvez rediriger les données à imprimer de l'une vers l'autre. Souvenez-vous que si vous utilisez cette technique, les données passeront par chaque filtre de la chaîne et seront mises successivement dans chaque spool.

Bien que vous puissiez spécifier pour une imprimante autant d'alias que vous le souhaitez, il semble que pour la meilleure utilisation, les deux premiers doivent être identiques et doivent correspondre au nom réel. Certains programmes n'utiliseront que ces deux entrées. La commande lpc indiquera seulement le premier alias, alors que les commandes lpr, lprm et lpq comprennent tous les alias.

Plutôt que de spécifier une taille maximum de fichier pour l'impression, vous préfereriez sans doute que les fichiers du spool ne puissent remplir votre disque, même temporairement. Pour ce faire, créez un fichier appelé minfree dans chaque répertoire de spool, contenant, sous forme d'un nombre de blocs (1 Ko pour Linux), la quantité minimum d'espace disque devant rester pour que les données puissent être acceptées dans le spool. Vous créerez un fichier réel dans le répertoire principal de spool et, dans chaque sous-répertoire, un lien symbolique vers ce fichier.

Problèmes

Problème

Vous avez un message indiquant: lpd: connect: No such file or directory

Réponse

Le démon lpd ne tourne pas. Vous avez peut-être oublié de l'inclure dans rc.local ou rc.multi. Ou n'avez vous tout simplement pas rebooté. Eventuellement lancez le à la main en étant root.

Problème

Vous obtenez un message~: Job queued, but cannot start daemon

Réponse

Ceci apparaît en général après le message précédent~!

Problème

Vous avez un message indiquant~: lpd: cannot create <spooldir>/.seq.

Réponse

Vous n'avez pas créé (ou pas correctement) le répertoire de spool défini dans /etc/printcap. Peut-être n'avez vous plus d'espace disque disponible~?

Problème

Vous avez un message indiquant~: lpr: Printer queue is disabled

Réponse

Sous root utilisez lpc enable <NOM_IMPRIMANTE> pour valider l'imprimante. Notez que en tant que root, vous pouvez soumettre des travaux, l'imprimante étant invalidée.

Problème

Vous soumettez un travail, aucun message d'erreur n'est enregistré, mais rien ne sort.

Réponse

Plusieurs raisons. L'imprimante est éteinte, mal connectée ou mal sélectionnée~! Utilisez lpq pour vérifier que l'entrée est dans la file. Si c'est le cas, le périphérique peut être occupé, l'imprimante pas prête ou en erreur. Regardez dans le fichier d'erreurs référencé dans /etc/printcap pour avoir des indices. Utilisez lpc status pour voir si l'imprimante est prête, et lancez lpc up <NOM_IMPRIMANTE> si ce n'est pas le cas.

Si après tout cela, rien ne sort, vérifiez que les filtres existent bien, dans les bons répertoires, avec les bons droits. Si vous utilisez syslogd, vous pouvez regarder les messages enregistrés concernant lpd. Si une entrée indique cannot execv <name of input filter>, c'est certainement ce problème.

Une autre possibilité est que votre imprimante est PostScript et que vous lui envoyez autre chose que du PostScript. Certaines imprimantes ignorent les données qui ne sont pas PostScript. Installez un filtre approprié.

Enfin, (et si c'est cela, je sens un certain état fébrile~!) vérifiez que votre filtre sort bien quelque chose sur la sortie standard, et qu'il n'est pas relié à /dev/null.

Problème

Lorsque vous imprimez à distance, vos travaux vont bien dans la file distante, mais ils ne sortent pas.

Réponse

Si vous pouvez, regardez l'entrée de l'imprimante distante dans /etc/printcap de la machine distante. Il se peut que vous n'ayez pas l'autorisation. Regardez le champ :rg=:, qui restreint aux membres d'un groupe et :rs=: qui limite l'accès aux utilisateurs connus de la machine distante. Eventuellement l'imprimante a été invalidée par l'administrateur de la machine distante. Voir aussi: Utiliser lpr en réseau.

3.2 A props de lpr et lpd

La plupart des systèmes Unix possèdent le démon d'impression lpd (et la variante System V: lp) accompagné des commandes déjà décrites et utilisant éventuellement des filtres. Il est à noter que la méthode de spool et de traitement par filtre est une chose bien adaptée aux imprimantes modernes, les imprimantes "ligne" tendant à disparaitre. (Note subliminale~:-) trouvez et lisez les pages de manuel concernant lpr, lpc, lpq, lpd et lprm).

3.3 Obtenir un gestionnaire d'impression

Le gestionnaire d'impression est disponible à différents endroits. En général un ensemble est livré avec chaque distribution~: slackware livre lpr.tgz dans le disque a3. TAMU également, soit binaires, soit sources (lpd-5.12.tar.gz). On peut trouver des sources sur tsx-11 dans sources/usr.bin.

NDT: L'auteur semble dire que les distributions contiennent des versions assez "légères", et qu'il serait bien de les mettres à jour. Laissons-lui ses mots qui datent peut être un peu. Je pense personnellement que les versions livrées, soit avec la slackware, soit avec des distributions comme yggdrasil sont très correctes.

Les fans de System V pourrons opter pour l'ensemble plp dont ce document ne parlera pas).

Si vous possédez une version assez ancienne du noyau et éventuellement des outils réseau, pensez à mettre à jour votre système pour éviter des instabilités.

Pensez également à mettre à jour le fichier /etc/printcap pour configurer lpd et utiliser votre imprimante. Configurer lpd pour une impression PostScript n'est pas très difficile~; écrivez un filtre comme indiqué au paragraphe Ecrire des filtres.

Configurer lpd correctement en vaut vraiment l'effort que cela nécessite, sauf si vous n'imprimez quasiment rien~!

Ghostscript 2.6.x est livré avec un shell-script assez compliqué permettant de générer les entrées du fichier /etc/printcap adapté à la gestion de plusieurs files pour une imprimante. Je n'ai pas pu le tester, mais je pense que cela fonctionne. Si vous travaillez dans un environnement assez vaste avec de multiple machines, je pense que cela vaut le coup d'y prêter attention.

3.4 Les fichiers, leur emplacement et les droits d'accès

Les différences qui existent entrent les nombreuses distributions font que l'on ne peut ici être exhaustif. Je pense que beaucoup de gens utilisent maintenant les distributions type slackware et on peut raisonnablement s'appuyer sur cet exemple.

Pensez à inclure lpd dans le fichier rc.local après le démarrage éventuel de syslogd. Voici les fichiers tels que l'on peut les trouver:

-r-sr-xr-x   1 root     lp           9308 Aug 23 21:45 /usr/bin/lpq*
-r-sr-xr-x   1 root     lp          10056 Aug 23 21:45 /usr/bin/lpr*
-r-sr-xr-x   1 root     lp           8900 Aug 23 21:45 /usr/bin/lprm*
-r-x------   1 root     lp           1596 Aug 23 21:45 /usr/bin/lptest*

-r-xr-sr-x   1 root     lp          17160 Aug 23 21:45 /usr/sbin/lpc*
-rwxr--r--   1 root     lp          34072 Aug 23 21:45 /usr/sbin/lpd*

et pour chaque répertoire de spool~:


/usr/spool/lp/lpr0/
total 5
drwxr-xr-x   2 root     lp           1024 Feb 12 15:15 ./
drwxr-xr-x   3 root     lp           1024 Sep  2  1993 ../
-rw-r----x   1 root     lp              4 Feb 12 15:15 .seq
-rw-r--r--   1 root     lp              3 Feb 13 20:46 lock
-rw-rw-r--   1 root     root           27 Feb 12 15:15 status

Ces trois fichiers sont créés par lpr et lpd. Ils peuvent être absents si vous ne les avez encore jamais lancés. Avec d'anciennes versions il fallait exécuter touch sur ces fichiers ou bien modifier leurs droits. Les bugs concernant ces fichiers ont maintenant été corrigés dans les versions récentes.

Il est à noter également que le groupe d'appartenance était daemon avec d'anciennes versions, et est maintenant lp.

Ne soyez pas surpris de trouver des choses légèrement différentes sur votre système. D'un autre côté, si quelque chose ne fonctionne pas, pensez à soupçonner ces droits avant d'affoler nos boîtes aux lettres (Si vous saviez le nombre de courriers électroniques reçus et basés sur ces problèmes~!).

On peut trouver le programme lpr avec ou sans le bit setuid(root). En fait ce n'est pas si évident que cela. Tout dépend des droits et permissions des répertoires de spool. Autant que je sache, il y a une totale sécurité avec lpr, même si il est setuid(root). Donc, à la limite, positionnez le bit pour ne pas vous soucier des droits d'accès au répertoire de spool.

Vous êtes libre de mettre les binaires dans les répertoires que vous voulez, bien qu'ils se trouvent couramment dans /usr/bin ou /usr/sbin. (lpc et lpd peuvent se trouver par exemple dans /etc). Certaines commandes étant intéressantes pour tout utilisateur, il est bon de les laisser aux endroits habituels.

Attention toutefois, car les gens qui conçoivent les distributions, sont également libres de choisir. Pensez à supprimer les anciennes versions, si vous changez de distribution.

L'emplacement du fichier de verrouillage principal du démon lpd (lpd.lock), est fixé en dur dans le code. Il se trouve dans /var/spool/lpd/lpd.lock. Donc, vous devrez prévoir un répertoire /var/spool/lpd même si votre répertoire de spool est différent. Les binaires anciens mettaient ce fichier dans /var/spool/lpd.lock

Typiquement, chez moi, on trouve

/var/spool/lpd/
drwxr-xr-x   4 root     lp           1024 Aug 18  1994 ./
drwxr-xr-x  18 root     root         1024 Aug 17  1994 ../
-rw-r--r--   1 root     root            3 Feb 14 20:12 lpd.lock

/var/spool/lp/lpr0
drwxr-xr-x   2 root     lp           1024 Feb 12 15:15 ./
drwxr-xr-x   3 root     lp           1024 Sep  2  1993 ../
-rw-r----x   1 root     lp              4 Feb 12 15:15 .seq*
-rw-r--r--   1 root     root            3 Feb 14 20:12 lock
-rw-rw-r--   1 root     root           27 Feb 12 15:15 status

Etant donné que l'on jongle en permanence entre /usr et /var, il est clair qu'un lien doit exister entre les deux. Soit vous définissez vos répertoires dans /usr/spool/... et définissez le lien /var vers /usr, soit vous mettez tout sous /var/spool/lpd... et définissez le lien /usr/spool vers /var/spool.

Si vous avez, comme moi une partition root (/) et une partition /usr, les deux cas ne sont pas identiques. Dans le premier, vos fichiers seront stockés dans la partition de root, /var etant créé sous /, dans l'autre, ce sera dans la partition /usr, puisque /usr est monté. Vous pouvez aussi avoir un système de fichiers /var réservé.

Le fichier de configuration principal est /etc/printcap. Il existe aussi, pour l'impression distante, les fichiers /etc/hosts.allow et /etc/hosts.lpd.

Désormais, le répertoire /etc est le répertoire où sont situés les fichiers de configuration. Vous pouvez choisir de les mettre ailleurs, mais définissez toujours un lien symbolique de /etc vers vos fichiers. Si votre système comporte des binaires qui vont toujours chercher leur configuration dans /usr/etc ou /etc/inet, ils sont sûrement très anciens et vous gagneriez à mettre votre système à jour.

3.5 Le démon ne fonctionne pas

Si votre commande ps favorite~: ps -a, ne vous révèle pas de démon, soit vous ne l'avez pas lancé, soit il est mort. Il se peut qu'il n'ait pas pu créer le fichier de verrouillage. Il se peut également qu'il n'ait pas eu accès au fichier /etc/services, qui décrit les ports réservés (ce qui peut arriver si tous vos systèmes de fichiers ne sont pas montés).

Si la commande lpr ne fonctionne que pour root, il y a sûrement un problème de droits.

Si la seule chose que vous pouvez faire pour imprimer est d'utiliser la redirection vers le périphérique (/dev/...), c'est que celui déclaré dans votre fichier /etc/printcap n'est pas le bon. Voir~: Noms de périphériques d'imprimantes. Vous pouvez effectuer des paramétrages avec tunelp. Voir~: Matériels et pilotes.

Si l'un des messages "Job queued, but cannot start daemon" ou "lpc: connect: No such file or directory" apparaît alors que le démon tourne, c'est peut-être qu'il y a un problème de connexion socket. ("start", dans ce contexte, signifie réveiller.) Vérifiez que vous avez compilé un noyau avec les sockets.

NDT: L'auteur semble dire qu'il y a ici des interactions entre des problèmes réseaux et les sockets (non réseaux) du monde Unix. Non seulement je doute de ce genre d'interaction (mais là le débat est ouvert~...) mais en plus certains gestionnaires d'impression (tels que PLP de l'Université du Minnesota) n'utilisent quasiment plus que les sockets INET).

De toute façon, même sur une configuration isolée, vous devrez inclure les commandes suivantes à votre configuration~:

ifconfig lo localhost
route add localhost

3.6 Où puis-je trouver un fichier /etc/printcap pour mon imprimante ?

Cette question est malheureusement sans objet. Veuillez ne pas encombrer les boîtes aux lettres et Usenet avec ces questions. Jetez un oeil à la syntaxe du fichier. Il est très facile d'en écrire un. Voir le paragraphe suivant.

3.7 La sémantique du fichier /etc/printcap

Bien qu'apparemment similaires, les fichiers /etc/termcap et /etc/printcap sont très différents. Alors que /etc/termcap contient les caractéristiques de terminaux (séquences d'échappement), printcap contient, lui, des informations liées à l'environnement de votre imprimante pour qu'elle fonctionne (répertoire de spool, taille réservée, nom du périphérique, fichier d'erreurs, ...). En aucun cas il ne contiendra les séquences d'échappement nécessaires à son fonctionnement. Ce rôle est affecté aux filtres. On indiquera seulement, dans le fichier printcap, l'endroit où se trouvent ces filtres.

3.8 La syntaxe du fichier /etc/printcap

Vous pouvez lire la documentation sur termcap(5) si vous la possédez.

Comme vous auriez pu le deviner, les lignes commençant par \# sont des commentaires.

Chaque imprimante utilisable avec la commande lpr doit correspondre à une entrée (ligne logique) dans /etc/printcap. Pour des raisons de lisibilité, une ligne logique peut être découpée en plusieurs lignes physiques pourvu qu'elles se terminent par le caractère `\' (anti-slash).

Chaque ligne logique à la syntaxe suivante~:

NOM1|NOM2|NOM3:CAPACITE_CHAINE=VALEUR_CHAINE:\
        :CAPACITE_NUMERIQUE#VALEUR_NUMERIQUE:CAPACITE_BOOLEENNE:

Les espaces en début de deuxième ligne ne sont utilisées que pour la lisibilité.

Une imprimante peut avoir autant de noms (alias) que vous le souhaitez et traditionnellement le dernier nom correspond à une description plus étendue mais rarement utilisée. Vous pouvez très bien ensuite entrer la commande suivante~:

lpr -P"imprimante laser situee en salle 213"
Un des noms de votre imprimante par défaut doit être lp.

Le terme capacité provient de l'héritage de termcap~: il est plus juste de parler ici de paramètre ou attribut.

Note de Ross Biro~:

Les capacités de 3 caractères ne fonctionnent pas correctement, ce qui explique pourquoi le port série n'était pas bien géré avec les anciens binaires.

Les paramètres de type chaîne sont délimités par le signe = entre leur nom et la chaîne. Les paramètres numériques sont délimités par le symbole \# (le symbole = est accepté). Les paramètres booléens sont vrais s'ils apparaissent et faux sinon.

Les caractères spéciaux dans une chaîne peuvent être exprimés à l'aide de séquences d'échappement précédées d'un anti-slash comme en langage C~; De plus \E correspond à Escape (ESC). `ˆ' sert aussi pour les caractères d'échappement. `ˆ' suivi d'un caractère (CHAR) permet de coder Control-CHAR. Donc `ˆa' définit control-a, de la même manière que \001. `\' et `ˆ' eux-même doivent être définis respectivement par `\\' et `\ˆ'. `\:' définit `:' mais il semble préférable d'utiliser `\072'. Le code source met en garde sur l'utilisation de ce codage.

Exemple:

        lp|bam|Epson FX-80:lp=/dev/lp1:sd=/usr/spool/lp1:sh=mx#0: \
                :df=/usr/local/lib/magic-filter/lp.df: \
                :if=/usr/local/lib/magic-filter/lp.if:

Le nom de l'imprimante par défaut est lp. Elle est aussi conue sous les noms bam et Epson FX-80.

L'imprimante est sur /dev/lp1 (AT-bus LPT1:). Pas de rupture de page, pas de taille limite de fichier. Les fichiers imprimés par la commande lpr -d sont passés par le filtre /usr/local/lib/magic-filter/lp.df et ceux imprimés par la commande lpr passent par le filtre /usr/local/lib/magic-filter/lp.if.

Voir aussi le chapitre suivant.

3.9 Erreurs cachées dans /etc/printcap

Deux fichiers /etc/printcap peuvent sembler identiques et pourtant l'un va fonctionner et pas l'autre. La commande lpc stat permet d'avoir des informations sur vos imprimantes. Si lpc stat indique qu'une imprimante s'appelle `:', vous avez peut-être oublié une anti-slash en fin de ligne. Des blancs après l'anti-slash annule son effet et la ligne suivante ne sera pas prise en compte en tant que suite de la même ligne logique.

3.10 Le fichier /etc/printcap minimum

Cette question ne devrait pas se poser, et pourtant~! On peut répondre ceci: "lp:sh", ce qui fait 6 caractères avec la fin de ligne. Vous devez créer un lien de /dev/lp vers votre périphérique et créer un répertoire de spool /usr/spool/lpd. Vous pensez peut-être, si vous ne voulez pas de bannière, pouvoir enlever ":sh". Malheureusement la syntaxe nécessite au moins une capacité par entrée.

3.11 Comment éviter l'effet d'escalier

Le système Unix, contrairement à DOS termine chaque ligne d'un fichier avec un caractère avance de ligne (linefeed linefeed est parfois employé tel quel en français ), sans retour chariot traduction de carriage-return qui, lui, est peu utilisé en français . Imprimé tel quel sur un périphérique ASCII, chaque nouvelle ligne commencera en dessous et à la suite de l'autre~: c'est l'effet d'escalier. Certaines imprimantes sont capables de traiter correctement ce caractère `linefeed' en extrapolant `line-feed' + `retour-chariot'. Si la vôtre ne le fait pas vous pouvez créer un shell-script comme ci-après~:

#!/bin/sh
if [ "$1" = -c ]; then
  cat
else
  sed -e s/$/^M/
fi
# echo -ne suppose que /bin/sh correspond a bash
echo -ne \\f

Notez que `ˆM' symbolise le caractère retour-chariot et non pas un `ˆ' suivi d'un M. Dans emacs, pour saisir ce caractère, entrez la séquence C-q~C-m, alors que sous vi, entrez C-v~C-m. Le test de $1 permet d'invalider l'insertion du retour-chariot par la commande lpr~-l A savoir que lpr génère des paramètres qui sont passés au filtre. Par défaut il passe -w0. Si l'option -l est donnée, il passe -c . Ce script est traditionnellement nommé /usr/lib/lpf. Si vous avez plusieurs scripts de la sorte, une bonne idée consiste à les mettre tous dans un sous-répertoire, par exemple /usr/lib/lpd.

Déclarez ce filtre dans /etc/printcap, avec le paramètre if~: :if=/usr/lib/lpf:.

Il se peut aussi que votre imprimante puisse passer dans un mode permettant l'ajout de retour-chariots grâce à une séquence d'échappement. Voici un exemple de filtre utilisant la commande echo -ne pour envoyer cette séquence~:

#!/bin/sh
# Filtre pour imprimantes HP, permettant de traiter LF comme CRLF
# La commande echo -ne suppose que /bin/sh correspond a bash
echo -ne \\033&k2G
cat
echo -ne \\f

3.12 Réinitialiser l'imprimante entre deux impressions de fichier

Vous pouvez confier cette tâche soit à votre filtre, soit au paramètre tr du fichier printcap. Pour avoir les détails sur le format de ce paramètre, consultez le chapitre sur La syntaxe du fichier /etc/printcap. Vous pouvez rencontrer des problèmes si l'impression se plante en plein milieu d'un séquence d'échappement. Essayer de mettre plusiers caractères `ˆ@' au début de la chaîne (ceci risque fort de ne pas suffire lors d'impression de graphiques).

3.13 Eviter les sauts de page après chaque impression de fichier

Si le paramètre `if' n'est pas présent dans le fichier printcap, lpd ajoutera systématiquement un saut de page à la fin de chaque fichier. Si vous utilisez un filtre, c'est à lui de mettre ou non un saut de page. Pour complètement supprimer les sauts de page si vous n'avez pas de paramètre if, mettez le paramètre :ff=: dans /etc/printcap. Mais notez que ceci supprimera également les sauts qui seront faits lorsque un filtre meurt (arrêt d'impression). Si vous désirez des sauts de pages après impression sauf celles soumises avec la commande lpr -l, vous pouvez créer le filtre suivant~:

#!/bin/sh
# La commande echo -ne suppose que /bin/sh correspond a bash
cat
if [ "$1" != -c ]; then
  echo -ne \\f
fi

Si vous souhaitez un saut de page optionnel après lpr~-l, vous pouvez par exemple redéfinir l'utilisation du paramètre -i de la commande lpr~:

#!/bin/sh
cat
# La commande lpr -i -l imprime tel quel et supprime les sauts de lignes
if [ "$1" != -c -o "$4" = -i0 ]; then
# echo -ne suppose que /bin/sh correspond a bash
echo -ne \\f
fi

3.14 Imprimer via un port série

En premier lieu, si votre version de lpd signale "ioctl(TIOCEXCL)", prenez un version plus récente n'émettant pas ce message (lpd-590p2).

Deux ensembles de paramètres sont à positionner dans le fichier printcap, ainsi que la vitesse du port en bauds. Pour la vitesse du port, la syntaxe est évidente. Exemple: br\#9600.

Les autres paramètres à positionner correspondent à un ensemble de bits, que l'on pourra soit positionner (1), soit mettre à 0. Pour effacer des bits, on utilisera les paramètres fc\# et xc\#, pour les positionner, fs\# et xs\#.

Faites bien attention aux bits que vous sélectionnez. Mais au fait que sont-ils~? Souvenez-vous..., la commande stty. Elle indique de nombreux paramètres caractérisant un tty. La commande stty~-a affiche en clair les paramètres du tty, certains d'entre-eux étant précédés d'un tiret s'ils sont invalidés et sans tiret s'ils sont validés. Ce sont ces paramètres (des drapeaux, des flags, donc des bits) que l'on va manipuler.

# stty -a < /dev/ttyS2
     speed 9600 baud; rows 0; columns 0; line = 0;
     intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
     eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
     lnext = ^V; min = 1; time = 0;
     -parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
     -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr
     -igncr -icrnl ixon -ixoff -iuclc -ixany -imaxbel
     -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
     bs0 vt0 ff0
     -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop
     -echoprt -echoctl -echoke

Vous pouvez utiliser cette commande pour configurer le port de façon à obtenir une impression correcte. Par exemple, les différences que l'on peut noter entre le stty ci-dessus et l'initialisation du port au démarrage de ma machine réside dans les informations -clocal, -crtscts et ixon. (La configuration de votre port pourra très bien être différente selon la manière dont votre imprimante gère le contrôle de flux).

Lorsque vous avez configuré votre port correctement à l'aide de cette commande, faites~: cat fichier > /dev/ttyS? (? est le numéro de votre port) pour imprimer un fichier.

Imprimez par exemple le fichier /usr/src/linux/include/linux/termios.h. Vous y découvrirez un tas de définitions de constantes et de structures. Nous allons voir quelles valeurs définies dans ce fichier vont nous servir pour configurer le port, non plus avec stty, mais avec les paramètres fc, xc, fs et xs du fichier printcap. Regardez la section commençant par~:

/* c_cflag bit meaning */
#define CBAUD   0010017

Elle décrit justement les bits manipulables à l'aide de fc\# et fs\# dont on parlait. On y voit les constantes des vitesses de modulation en baud, puis des lignes qui nous intéressent particulièrement~: ce sont les mêmes paramètres que dans la commande stty. Je sens que vous voyez où on veut en venir. Modifier un paramètres de stty, cela va consister à positionner ou effacer un bit dont la position est indiquée dans la constante.

Vous savez maintenant que les paramètres de stty sont des bits, et qui ont la valeur 0 lorsqu'il y a un tiret devant. Notez alors les bits à effacer (ce sera fait avec la paramètre fc\#) et ceux à positionner (paramètre fs\#). Exemple: `fc\#0177777' (Attention le paramètre fc semble surcharger le paramètre br\#, donc prenez garde à les positionner correctement).

Ensuite occupez-vous des bits à positionner. Par exemple s'il faut positionner les bits cs8, hupcl et cread, regardez les constantes CS8 (0000060), HUPCL (0002000) et CREAD (0000200). Pensez à la vitesse de modulation qu'il faut aussi définir, dans mon cas, ce sera B9600 (0000015). Tous ces bits ensemble font `0002275'. Indiquez cette valeur au paramètre fs\#.

Effectuez les même réglages avec la section suivante intitulée

/* c_lflag bits */

Dans mon cas je n'ai rien à positionner, j'ai donc simplement à fournir la valeur xc\#0157777, puis xs\#0. Une fois votre fichier correctement défini, essayez d'imprimer. Si quelque chose ne va pas, continuez à lire les paragraphes suivants.

Souvenez-vous de toujours commencer par les bits que vous souhaitez voir à 0 (fc\# et xc\#), puis de définir seulement après des bits à positionner (fs\# et xs\#).

3.15 La commande cat fonctionne pour le port série, mais pas lpd (1)

La mise en place de lpd n'est pas traitée ici, mais sachez que si vous avez des problèmes avec la configuration du port série, vous pouvez empêcher lpd de le configurer en considérant votre imprimante comme ne présentant pas une interface normale. Lisez également à ce propos le chapitre suivant.

  1. Donnez à votre imprimante le périphérique /dev/null1 (mknod~/dev/null1~c~1~3). N'utilisez pas /dev/null, pour ne pas qu'il soit ouvert de manière exclusive. Enlevez les paramètres de vitesse et de positionnement des bits du fichier printcap.
  2. Créez un shell-script comme ci-dessous~:
    #!/bin/sh
    echo if: $* >> /var/spool/lpd/results
    # /dev/lp est un lien vers /dev/ttyS2 auquel est reliee l'imprimante
    exec votre_vieux_filtre $* > /dev/lp
    
    ...ou si vous n'avez pas de paramètre `if' configuré...
    #!/bin/sh
    echo if: $* >> /var/spool/lpd/results
    cat > /dev/lp
    # la commande ``echo -ne'' suppose que /bin/sh correspond a bash
    echo -en \\f > /dev/lp
    
    Donnez-lui les droits de lecture/écriture pour tout le monde. Essayez-le~: /usr/lib/lpd/if~<FICHIER.
  3. Définissez un filtre d'entrée dans votre fichier printcap pour appeler ce script. `:if=/usr/lib/lpd/if:'.
  4. Utilisez la commande stty pour configurer le port correctement. Essayez d'imprimer. Vous devriez pouvoir déterminer si le(s) fichier(s) sont bien mis dans le répertoire de spool. Cela devrait imprimer, si votre essai manuel du script précédent a fonctionné. Bien entendu, le mieux serait de pouvoir se passer du script d'entrée et donc du paramètre if.

Supposons donc que la méthode précédente a fonctionné, et que vous pensez avoir correctement configuré votre fichier printcap. Exécutez la commande stty~-a~</dev/ttyS?. Si certains paramètres ne sont pas corrects, vérifiez les constantes du fichier termios.h. Si la configuration est incorrecte, malgré tous vos efforts de vérification, n'hésitez pas à installer un démon récent.

Le patch qui suit (et vous verrez rapidement pourquoi il est nécessaire) est réservé aux anciennes versions de lpd. La version lpd-590p2 et ultérieures l'intègrent déjà.

Lorsque j'ai inséré le mien, j'ai effectué les essais suivants:

lprm TOUT          # assurez-vous que la file est vide, que le demon tourne
stty PARAMETRE < /dev/ttyS2
lpr JUSTE_UN_PETIT_TRUC
stty -a < /dev/ttyS2

réglage des bits

lprm TOUT # la file doit être à nouveau vide.

Voici le patch (il est inversé et il faut l'appliquer avec `-R' ou plutôt à la main~!)

   -------------------------------Cut Here-------------------------------------
   *** lpd-590/lpd/printjob.c  Thu Jul  8 20:56:59 1993
   --- lpd-590/lpd/printjob.c~ Sat Feb 27 09:07:01 1993
   ***************
   *** 1271,1277 ****
           }
     #ifdef LINUX
           ttybuf.c_cflag &= ~FC;          /* not quite right! */
   !       ttybuf.c_cflag |= FS;           /* not quite right! */
     #else
           ttybuf.sg_flags &= ~FC;
           ttybuf.sg_flags |= FS;
   --- 1271,1277 ----
           }
     #ifdef LINUX
           ttybuf.c_cflag &= ~FC;          /* not quite right! */
   !       ttybuf.c_cflag |= ~FS;          /* not quite right! */
     #else
           ttybuf.sg_flags &= ~FC;
           ttybuf.sg_flags |= FS;
   -------------------------------Cut Here-------------------------------------

Cut Here~: Coupez ici.\\ not quite right!~: Pas tout à fait ça~!

3.16 Les imprimantes qui ne sont pas de simples périphériques

Qu'est-ce qu'une telle imprimante~? Imaginez une imprimante distante à laquelle vous ne pouvez accéder que par courrier électronique~!

Pour utiliser ce genre d'imprimante avec lpr, le paramètre `lp' du fichier printcap doit définir un périphérique de type /dev/null (disons /dev/null1: mknod /dev/null1 c 1 3), mais pas /dev/null puisque lpd ouvre le périphérique en accès exclusif. Un filtre devra donc encoder les données (uuencode) et envoyer un courrier (mail) dont le contenu correspond à ce qu'il émet sur la sortie standard.

Plus difficile est le cas ou vous avez déjà défini un filtre avec le paramètre `if' ou `of' pour une imprimante spéciale. Dans ce cas ce filtre existant doit diriger sa sortie vers le nouveau filtre. Le filtre `if' doit être appelé avec le paramètre -c pour minimiser les modifications de données.

Quelqu'un m'a dit avoir déjà essayé une telle manipulation avec un réseau Novell NetWare et l'outil d'envoi de mails "Charon".

3.17 Génération de ruptures de pages ou de bannières

Pour une imprimante classique (texte, non PostScript), et pour une bannière simple, enlevez simplement le paramètre `sh' du fichier printcap.

Si vous optez pour une bannière, positionnez aussi le paramètre `tr' pour figer la fonte utilisée pour la bannière et éviter des bannières fantaisistes dépendantes de la dernière fonte utilisée.

Si vous souhaitez définir votre banière (avec une imprimante PostScript par exemple), laissez le paramètre `sh' et faites imprimer la bannière à votre filtre. Consultez la documentation sur printcap (man printcap). Si vous utilisez les filtres magiques de <B.A.McCauley@bham.ac.uk> (magic-filters-0.4), appelez le code permettant d'imprimer les bannières.

3.18 Envoyer du texte à une imprimante PostScript

Vous aurez besoin d'un filtre basé sur un programme qui convertit l'Ascii en PostScript. Le plus connu d'entre-eux est enscript, mais il est aussi le plus dur à trouver (et pas gratuit). D'autres tels que a2ps, nenscript, mpage pourront faire l'affaire. Voir Imprimer du texte via PostScript.

3.19 Pourquoi les fichiers graphiques sont parfois tronqués

C'est sûrement parce que vous avez limité la taille des fichiers imprimables à une valeur trop petite. Mettez `mx\#0' dans votre fichier printcap.

3.20 Pourquoi lpr -i ne fonctionne pas

Pour que lpr -i fonctionne, vous devez avoir un filtre `if' qui implémente son fonctionnement. Le paramètre `-i' est simplement passé au filtre par lpd. Le filtre appelé lpf livré avec lpd supporte cette caractéristique, mais ne peut être utilisé qu'avec du texte. Si vous souhaitez utiliser cet outil et effectuer en plus certaines initialisations, écrivez un script comme le suivant~:

#!/bin/sh
# Ici, mes diverses initialisations
exec /usr/lib/lpf $*

Mieux, votre filtre peut envoyer à l'imprimante la séquence de définition de marge gauche~:

#!/usr/bin/perl
# Cet exemple est ecrit en perl pour changer, car convertir
# les nombres en chaine est plus dur en langage 'shell'

for ($i=0; !($_ = $ARGV[$i]) || !/^-i([0-9])+/; $i++) {}

print pack("cAc",27,"l",$1);

while (<STDIN>) { print; }

3.21 Pourquoi lpr -p ne fonctionne pas

Essentiellement parce que vous avez une version trop ancienne du gestionnaire d'impression pr croit que la largeur de page est à 0 . Il y a eu un patch à ce propos qui est maintenant appliqué à partir de la version lpd-590p1.

Il est également possible que le programme pr ne soit pas à l'endroit ou lpd va le chercher (et ce n'est pas paramétrable). Déplacez-le ou définissez un lien (normalement~: /usr/bin/pr).

3.22 lpc et lpq signalent que le démon est absent

Le démon lpd tourne tout le temps. Il crée un fils pour chaque imprimante à gérer, selon la configuration décrite dans printcap. La santé du démon n'est pas explicitement rapportée par lpc néanmoins, l'absence d'erreur indique un fonctionnement correct. Voir le chapitre~: Le démon ne fonctionne pas. La commande lpc~stat signalera "no daemon present" (pas de démon) pour chaque file d'impression pour laquelle il n'y a pas d'impression en cours~: c'est normal. Si la file a été invalidée ou si elle est vide, il n'y a pas d'erreur. lpq, quant à lui est un peu plus alarmiste, puisqu'il indique "Warning: no daemon present". Si la file n'est pas vide, n'a pas été stoppée et que le démon est absent, il y a probablement une erreur dans un filtre. Corrigez-le et relancez le démon à l'aide de la commande~: lpd~up~NOM_DE_FILE.

Il se peut également que lpc essaie de tuer un démon absent lorsque vous voulez arrêter une imprimante. Ceci conduit à des messages d'erreurs gênant mais sans gravité. Ils sont rares à partir de la version lpd-590p2.

3.23 Utiliser lpr en réseau

Pour imprimer sur l'imprimante nommée lpdist sur la machine dist.net.fr à partir de la machine moi.net.fr, mettez une entrée dans /etc/printcap ressemblant à la suivante~:

     lpdist:lp=:rm=dist.net.fr:rp=lpdist:sd=/usr/lpd/spool/dist:

et, bien sûr, créez le répertoire /usr/spool/lpd/dist

Aucun filtre n'est spécifié puisque ce seront ceux de la machine distante qui seront utilisés.

Sur la machine distante dist.net.fr, vous devrez notifier la machine locale moi.net.fr soit dans /etc/hosts.equiv, soit dans /etc/hosts.lpd, plus spécifiquement réservé à l'impression.

Les machines décrites dans /etc/hosts.* doivent avoir des noms ou des numéros sous forme canonique, puisque lpd va chercher les noms à partir des adresses IP (DNS inverse). Si vous n'êtes pas sûr des noms, listez les noms déjà connus pour une machine. L'utilitaire dig réalise très bien cela. dig~-x~A.B.C.D donne les noms canoniques de la machine dont l'adresse IP est A.B.C.D.

Si le serveur d'impression n'est pas de type BSD, il sera possible de le faire fonctionner mais les fichiers d'autorisation pourront avoir un format différent. Chris Nystrom <chrisn@medianet.com> a trouvé qu'il fallait qu'il crée le fichier /usr/spool/lp/admins/lp/Systems sur la machine distante, indiquant son nom de machine linux. Nous ne savons pas si cela est spécifique à System V ou à dynix/ptx 2.0.3 qu'il utilise.

Si vous ne pouvez pas imprimer à distance, utilisez les commandes d'exécution à distance~:

rsh dist.net.fr "lp -dlp" < FICHIER

Cet exemple correspond à un système d'impression à distance System V sur la machine dist.net.fr.

3.24 Ecrire des filtres

Dans la terminologie Unix standard un filtre est un simple programme (donc avec les droits d'exécution) qui lit les données sur son entrée standard et sort le résultat sur sa sortie standard.

Les filtres lpd correspondent tout à fait à cette définition puisqu'ils lisent sur stdin et écrivent sur stdout. Leurs particularités résident dans le fait qu'ils supposent que leur entrée standard est un fichier à accès aléatoire, et donc qu'il peuvent faire des positionnements à l'aide d'opérations lseek().

Tous les filtres lpd ont une syntaxe d'appel commune (et souvent ne nécessitent pas de paramètres). La documentation de printcap détaille un peu comment passer des paramètres.

Si vous souhaitez écrire un filtre sous forme de shell-script, celui-ci doit commencer par \#!/bin/sh. Un filtre très classique pour l'interprétation PostScript est le suivant~:

#!/bin/sh
/PATH/.../gs -q -dSAFER -dNOPAUSE -r??? -sDEVICE=????? -sOutputFile=- -

Le paramètre -dSAFER tente d'éviter des problèmes d'interprétation PostScript. Les paramètres -q et -dNOPAUSE permet de supprimer la pause qui est normalement insérée entre chaque page (notamment lors d'une visualisation à l'écran). Indiquez dans printcap le chemin d'accès complet à votre filtre pour l'un des paramètres de type filtre (sauf pour of~!). Je vous conseille d'ailleurs de placer vos filtres dans /usr/lib/lpd. Vous pouvez également les placer dans le répertoire de spool, mais ceci va un peu à l'encontre de la règle qui veut que l'on sépare données et programmes.

Voici par exemple mon filtre pour une Epson Stylus 800~:

#!/bin/sh
/usr/bin/gs -q -dSAFER -dNOPAUSE -sPAPERSIZE=a4 -sDEVICE=escp2 -sOutputFile=- -

D'autres outils sont décrits à divers endroits de ce document.

3.25 Déboguer des filtres

Il est beaucoup plus facile de tester et corriger un filtre si vous l'exécutez à la main, plutôt que de l'insérer tout de suite dans printcap. Vous devez alors rediriger les entrées et sorties standard~: mon_filtre~<FICHIER~>/dev/lp1.

Une astuce que beaucoup de gens utilisent lors des tests, lorsque leur filtre nécessite des arguments, consiste à ajouter au début du filtre un ligne comme celle-ci~:

echo $* >> /tmp/filter-log

Si le filtre fonctionne pendant les tests et qu'il ne fonctionne plus une fois appelé par lpd, c'est peut-être qu'il manque #!/bin/sh au début. Il se peut aussi que le démon ne sache pas accéder à un répertoire, auquel cas vous devrez inclure ce chemin dans le script. Enfin sachez que le filtre est lancé par root ou daemon, et que tout programme qu'il appelle doit être exécutable par tout le monde.

3.26 Filtre de sortie (of)

A ne jamais utiliser. Je veux dire par là que je souhaite que vous ne soyez pas dans une situation ou vous en aurez besoin. Au début de 1994, il y a eu un grand débat sur comp.os.linux.help à propos de ces filtres. Le paramètre `of' est utilisé par exemple lorsque la soumission d'un nouveau travail est pris en compte immédiatement pour l'impression, ce qui se traduit par la sortie du fichier avec un simple saut de page pour interrompre la sortie en cours. Ceci peut conduire à un résultat mauvais puisqu'il n'y a pas eu de réinitialisation de l'imprimante.

3.27 Où trouver un filtre pour mon imprimante ?

Une fois que vous avez choisi le programme qui vous convient pour la conversion de format, il faut très peu de temps pour écrire un filtre. De plus des filtres existent déjà dans certaines distributions. Il y a donc peu de demandes et pas de site ftp pour cela.

Si vous disposez déjà d'un programme pour imprimer ce que vous souhaitez, ce n'est vraiment pas un problème pour en faire un filtre. En général, un petit script suffit. Voir~: Ecrire des filtres. Si malheureusement votre programme ne sait lire que des fichiers passés en paramètres (donc pas sur l'entrée standard), lisez le chapitre suivant.

Les filtres en mode texte sont également très simples, sauf si vous souhaitez pouvoir sélectionner des fontes, ce qui complique un peu. Vous pourrez par exemple insérer une commande echo~-ne au début et à la fin du filtre pour choisir une fonte.

3.28 Filtres utilisant des programmes ne sachant pas lire stdin

Il est tout à fait possible d'écrire des filtres avec de tels programmes. Par exemple dvilj2p demande un nom de fichier (de plus avec l'extension .dvi). L'exemple ci-après vous montre comment vous en sortir~:

#!/bin/sh
ln -s /proc/self/fd/0 /tmp/$$.dvi
dvilj2p /tmp/$$
rm /tmp/$$.dvi

Note: Un lien symbolique est nécessaire ici parce que dvilj2p ajoute lui même l'extension .dvi. Sinon vous pouvez donner au programme directement /proc/self/fd/0. Il peut être astucieux de créer un lien permanent~: ln~-s~/proc/self/fd/0~/dev/stdin. Si vous êtes très attentifs aux problèmes de sécurité, et ne permettez pas l'accès à /proc, utilisez plutôt la méthode du fichier temporaire.

3.29 Avoir plusieurs filtres

Les gestionnaires d'impression ne reconnaissent basiquement qu'un nombre limité de types de fichiers. En fait, toutes les raisons sont bonnes pour utiliser un filtre. Ils peuvent être activables lorsque certains paramètres de lpr sont donnés. Par exemple lpr -v peut permettre d'imprimer un fichier GIF. L'option supplémentaire -d pouvant sélectionner une résolution inférieure. Sachez que les temps de traitement dûs aux filtres peuvent être assez long (attente entre deux jobs).

Si vous êtes en réseau, des filtres s'exécuteront aussi sur le serveur d'impression. Une façon d'activer ou non certains filtres, consiste à créer plusieurs entrées dans printcap ciblant toutes la même imprimante physique, mais définissant des paramètres `if' différents. Ceci a l'avantage d'un paramétrage facile grâce à la variable d'environnement PRINTER pour choisir l'imprimante (je veux dire l'entrée du fichier printcap), évitant de donner le paramètre à chaque fois.

Une autre possibilité (et cela se fait de plus en plus) est d'utiliser des filtres magiques.

3.30 Les filtres magiques

Les filtres magiques déduisent le type de données qu'ils ont en entrée d'un nombre magique caractérisant ce type. Ceci existe déjà pour certains fichiers Unix.

Les filtres magiques sont généralement des scripts écrits en perl, en shell ou en langage C qui identifient le fichier et appellent le bon programme (qui, lui, n'est pas magique). Brian (un des auteurs) possède un filtre magique assez générique écrit en bash, permettant de sélectionner le filtre selon le résultat de la commande file. Avec un filtre magique et 3 filtres normaux, vous pouvez lancer une impression comme celle-ci~:

lpr -d fichier1.dvi fichier2.div.Z fichier3.ps fichier4.texinfo.gz

(Pas besoin de configurer lpr pour des fichier texinfo)

De tels filtres magiques sont disponibles sur~:

tsx-11.mit.edu:/pub/linux/sources/usr.bin/magic-filter-0.4.tar.gz

apsfilter est un exemple de shell-script assez simple ne nécessitant aucun filtre supplémentaire et utile pour les imprimantes laser compatibles HP.

Les filtres magiques ne doivent pas être utilisés en sortie (paramètre `of') puisqu'ils ne sont appelés qu'une fois lorsque plusieurs fichiers sont envoyés à la suite (en une fois).

Remarque~: Mon opinion (Brian) est que les filtres d'entrée sont assez inélégants. Essayez par exemple d'imprimer un source PostScript ou nroff~! Mais je reconnais que les opinions sont partagées.

3.31 Exemples de filtres magiques

L'exemple suivant est un shell-script magique capable de traiter les données au format PostScript ou texte~:

#!/bin/sh
# Base sur un script envoye par Scott Doty et ecrit par Keith Walker
# Utilise le fait que lpd passe des parametres a `if'.
#
# <if> -w<width> -l<length> -i<ident> -n<user> -h<host> <fichier>
#
# pour imprimer un fichier a n'importe quelle taille. Ces options sont
# interessantes si vous vous faites votre propre banniere.
#
# `gs' reinitialisera l'imprimante. L'initialisation doit inclure la
# conversion des retour-chariot si besoin
printf "<initialisation imprimante pour impression texte (code echappement,
etc)>"

read premiere_ligne
deux_prem_caract=`expr $premiere_ligne : '\(..\)'`

if [ "$deux_prem_caract" = "%!" ]; then     # c'est du PostScript

      /usr/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=??????? -sOutputFile=- -

else      # c'est du texte

      echo -n $premiere_ligne
      cat
      printf "\014"

fi

A noter (pour les paranos de l'effraction logicielle) que certains scripts lancés par d'autres peuvent poser des problèmes de sécurité, mais ici ce n'est pas le cas avec les filtres pour lpd, car l'environnement de travail n'est pas sous le contrôle d'un pirate potentiel.

Chapitre Suivant , Chapitre Précédent

Table des matières de ce chapitre, Table des matières générale

Début du document, Début de ce chapitre