Pour partager une imprimante sur une machine Windows, vous devez suivre les points suivants :
/etc/printcap
et elles doivent correspondre à la structure locale des
répertoires (pour le répertoire de spool, etc...).
/usr/bin/smbprint
. Il est fournit avec les
sources de Samba, mais pas avec toutes les distributions binaires. Une version
légèrement modifiée de ce script est présentée plus loin.
nenscript
, ou équivalent. nenscript
est un convertisseur
Postscript et se trouve généralement dans /usr/bin
.
L'entrée dans /etc/printcap
est pour une imprimante HP 5 MP sur une
machine utilisant Windows NT. Les entrées sont comme suit :
cm - commentaire lp - nom du périphérique à ouvrir en écriture sd - le répertoire de spool de l'imprimante (sur la machine locale) af - le fichier d'accounting mx - la taille maximum de fichier (zéro pour aucune limite) if - le nom du filtre en entrée (un script)
Pour plus ample information, lisez le Printing HOWTO ou la page de manuel de printcap.
# /etc/printcap
#
# //zimmerman/oreilly avec smbprint
#
lp:\
~:cm=HP 5MP Postscript OReilly sur zimmerman:\
~:lp=/dev/lp1:\
~:sd=/var/spool/lpd/lp:\
~:af=/var/spool/lpd/lp/acct:\
~:mx#0:\
~:if=/usr/bin/smbprint:
Assurez que le répertoire de spool et celui d'accounting existent et son
accessibles en écriture, que le chemin correct vers le script smbprint (donné
ci-dessous) est indiqué par la ligne « if » et que vous avez sélectionné le
bon fichier de périphérique (le fichier spécial dans /dev
).
Vient ensuite le script smbprint. Il est généralement mis dans le répertoire
/usr/bin
et a été créé par Andre Tridgell, le créateur de Samba pour
autant que je sache. Il est fourni avec la distribution sous forme de code
source de Samba, mais est absent de certaines distribution binaires. Je l'ai
donc recopié ici.
Examinez le avec attention. Certains changement fait à ce script se sont avérées être utiles.
#!/bin/sh -x
# Ce script est un filtre d'entrée sur l'impression avec printcap sur une
# machine Linux. Il utilise le programme smbclient pour imprimer le fichier au
# serveur et service spécifié.
# Par exemple, vous pouvez avoir une entrée printcap comme celle-ci~:
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# qui créerai une imprimante Unix appelée "smb" qui imprimerait par
# l'intermédiaire de ce script. Vous devrez créer le répertoire de spool,
# /usr/spool/smb avec les permissions qui conviennent et le bon propriétaire,
# pour votre système.
# Mettez les valeurs pour le serveur et le service sur lequel vous voulez
# imprimer. Dans cet exemple, j'utilise un PC sous Windows pour Workgroups
# nommé "laplan" ayant une imprimante appelée "printer" sans mot de passe.
#
# Script modifié par hamiltom@ecnz.co.nz (Michael Hamilton) afin que le
# serveur, le service et le mot de passe puissent être lus depuis un fichier
# /usr/var/spool/lpd/PRINTNAME/.config
#
# Pour que ceci puisse fonctionner, l'entrée du /etc/printcap doit inclure un
# fichier d'accounting (af=...)~:
#
# cdcolour:\
# :cm=CD IBM Colorjet au 6eme etage:\
# :sd=/var/spool/lpd/cdcolour:\
# :af=/var/spool/lpd/cdcolour/acct:\
# :if=/usr/local/etc/smbprint:\
# :mx=0:\
# :lp=/dev/null:
#
# Le fichier /usr/var/spool/lpd/PRINTNAME/.config devrait contenir~:
# server=SERVEUR_PC
# service=NOM_IMPRIMANTE
# password="mot_de_passe"
#
# Pas exemple~:
# server=MON_BO_PC
# service=CJET_371
# password=""
#
# Fichier de log pour debuggage, changez le à /dev/null si vous le voulez
#
logfile=/tmp/smb-print.log
# logfile=/dev/null
#
# Le dernier paramètre du filtre est le nom du fichier d'accounting
#
spool_dir=/var/spool/lpd/lp
config_file=$spool_dir/.config
# Les variables suivantes devraient être lues depuis le fichier de
# configuration~:
# server
# service
# password
# user
eval `cat $config_file`
#
# Des informations de débogage, changez le >> en > si vous voulez économiser
# de la place.
#
echo "server $server, service $service" >> $logfile
(
# NOTE Vous voudrez peut être ajouter la ligne "echo translate" si vous voulez
# une conversion automatiques des CR/LF lors de l'impression
echo translate
echo "print -"
cat
) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $logfile
La plupart des distributions Linux sont fournies avec nenscript pour convertir des documents ASCII en Postscript. Le script perl qui suit simplifie la vie en fournissant une interface simple à smbprint pour l'impression sous Linux.
Usage: print [-a|c|p] <fichier> -a imprime <fichier> comme un fichier ASCII -c imprime <fichier> formatté en code source -p imprime <fichier> en tant que fichier Postscript Si aucun paramètre n'est donné, print tente de deviner le type de fichier et imprime en conséquence.
smbprint a tendance à tronquer les longues lignes lors de l'impression de fichiers ASCII. Ce script coupe les longues lignes sur les espaces (plutôt qu'au milieu d'un mot), si possible.
Le formatage en code source est réalisé par nenscript.Il prend en entrée un fichier ASCII et le formatte sur deux colonnes avec une entête (date, nom du fichier, etc...). Il numérote également les lignes. En prenant ce script comme exemple, on peut faire d'autres types de formatage.
Les documents sont déjà correctement formatés, donc ils passent directement à travers le filtre.
#!/usr/bin/perl
# Script: print
# Auteurs: Brad Marshall, David Wood
# Plugged In Communications
# Date: 960808
#
# Script pour imprimer sur une imprimante postscript via samba.
# But: Prendre différentes sortes de fichier en argument et les
# traiter pour les injecter dans le script d'impression de Samba.
#
# Types de fichier supportés pour l'instant~:
#
# ASCII - vérifie que les lignes plus longues que $line_length
# caractères sont coupés sur un espace.
# Postscript - Aucune action.
# Code - Formatte en Postscript (à l'aide de nenscript) pour un
# affichage correct (orientation, fonte, etc...).
#
# Fixe la longueur maximale d'une ligne de texte ASCII
$line_length = 76;
# Le chemin d'accès vers le script d'impression de Samba
$print_prog = "/usr/bin/smbprint";
# Le chemin vers le programme nenscript (le convertisseur
# ASCII->Postscript)
$nenscript = "/usr/bin/nenscript";
unless ( -f $print_prog ) {
die "Je ne peux pas trouver $print_prog!";
}
unless ( -f $nenscript ) {
die "Je ne peux pas trouver $nenscript!";
}
&ParseCmdLine(@ARGV);
# Débug
print "filetype is $filetype\n";
if ($filetype eq "ASCII") {
&wrap($line_length);
} elsif ($filetype eq "code") {
&codeformat;
} elsif ($filetype eq "ps") {
&createarray;
} else {
print "Désolé, ce n'est pas un type de fichier que je connais";
exit 0;
}
# Envoie le tableau à smbprint
open(PRINTER, "|$print_prog")
|| die "Je ne peux pas ouvrir $print_prog: $!\n";
foreach $line (@newlines) {
print PRINTER $line;
}
# Envoie un retour à la ligne supplémentaire si jamais le fichier a sa
# dernière ligne incomplète
print PRINTER "\n";
close(PRINTER);
print "Achevé\n";
exit 0;
# --------------------------------------------------- #
# Tout ce qui suit est un sous programme #
# --------------------------------------------------- #
sub ParseCmdLine {
# Traite la ligne de commande, détermine le type de fichier
# $arg et $file sont respectivement les arguments (s'ils
# existent) et le nom de fichier
if ($#_ < 0) {
&usage;
}
# Débug
# foreach $element (@_) {
# print "*$element* \n";
# }
$arg = shift(@_);
if ($arg =~ /\-./) {
$cmd = $arg;
# Débug
# print "\$cmd trouvé.\n";
$file = shift(@_);
} else {
$file = $arg;
}
# Définition du type de fichier
unless ($cmd) {
# Aucun argument
if ($file =~ /\.ps$/) {
$filetype = "ps";
} elsif ($file =~ /\.java$|\.c$|\.h$|\.pl$|\.sh$|\.csh$|\.m4$|\.inc$|\.html$|\.htm$/) {
$filetype = "code";
} else {
$filetype = "ASCII";
}
# Traite $file selon le type de fichier et retourne
# le type de fichier ($filetype)
} else {
# Nous utilisons ltype de fichier décrit dans $arg
if ($cmd =~ /^-p$/) {
$filetype = "ps";
} elsif ($cmd =~ /^-c$/) {
$filetype = "code";
} elsif ($cmd =~ /^-a$/) {
$filetype = "ASCII"
}
}
}
sub usage {
print "
Usage: print [-a|c|p] <fichier>
-a imprime <fichier> comme un fichier ASCII
-c imprime <fichier> formaté en code source
-p imprime <fichier> en tant que fichier Postscript
Si aucun paramètre n'est donné, print tente de
deviner le type de fichier et imprime en conséquence.\n
";
exit(0);
}
sub wrap {
# Crée un table contenant les lignes du fichier, avec chaque
# ligne ayant une longueur < au nombre de caractères
# spécifiés, et coupée uniquement sur un espace.
# Récupère la longueur maximum d'une ligne
$limit = pop(@_);
# Débug
#print "Entrée dans la procédure wrap\n";
#print "La longueur maximum d'une ligne est $limit\n";
# Lit le fichier, le traite et le stocke dans le tableau
open(FILE, "<$file") || die "Impossible d'ouvrir $file: $!\n";
while(<FILE>) {
$line = $_;
# Débug
#print "La ligne est~:\n$line\n";
# Coupe la ligne si celle-ci dépasse la limite
while ( length($line) > $limit ) {
# Débug
#print "Je coupe...";
# Prend les premiers $limit +1 caractères.
$part = substr($line,0,$limit +1);
# Débug
#print "La ligne partielle est~:\n$part\n";
# Vérifie si le dernier caractère est un
# espace
$last_char = substr($part,-1, 1);
if ( " " eq $last_char ) {
# Oui, on imprime le reste
# Débug
#print "Le dernier caractère était un espace\n";
substr($line,0,$limit + 1) = "";
substr($part,-1,1) = "";
push(@newlines,"$part\n");
} else {
# Non, on cherche le dernier espace de la
# ligne et on imprime jusqu'à lui
# Débug
#print "Le dernier caractère n'était pas un espace\n";
# Supprime le caractère après $limit
substr($part,-1,1) = "";
# Inverse la ligne pour trouver plus
# facilement l'espace
$revpart = reverse($part);
$index = index($revpart," ");
if ( $index > 0 ) {
substr($line,0,$limit-$index) = "";
push(@newlines,substr($part,0,$limit-$index)
. "\n");
} else {
# Aucun espace dans la ligne
# Imprime jusqu'à $limit
substr($line,0,$limit) = "";
push(@newlines,substr($part,0,$limit)
. "\n");
}
}
}
push(@newlines,$line);
}
close(FILE);
}
sub codeformat {
# Appelle la procédure wrap et filtre par nenscript
&wrap($line_length);
# Envoie le résultat à nenscript pour créer un fichier
# Postscript qui respecte un format décent d'impression pour
# du code source (orientation paysage, font Courier,
# numérotation des lignes).
# Imprime d'abord dans un fichier temporaire.
$tmpfile = "/tmp/nenscript$$";
open(FILE, "|$nenscript -2G -i$file -N -p$tmpfile -r") ||
die "Je ne peux pas ouvrir nenscript~: $!\n";
foreach $line (@newlines) {
print FILE $line;
}
close(FILE);
# Relis le fichier temporaire dans un tableau pour pouvoir
# être passé au script smbprint de Samba.
@newlines = ("");
open(FILE, "<$tmpfile") || die "Je ne peux pas ouvrir $file~: $!\n";
while(<FILE>) {
push(@newlines,$_);
}
close(FILE);
system("rm $tmpfile");
}
sub createarray {
# Crée le tableau pour un fichier postscript
open(FILE, "<$file") || die "Can't open $file: $!\n";
while(<FILE>) {
push(@newlines,$_);
}
close(FILE);
}
Maintenant, avec MagicFilter. Merci a Alberto Menegazzi ( flash.egon@iol.it) pour ces informations.
Alberto nous dit :
--------------------------%<----------------------------------
1) Installez MagicFilter avec le filtre pour l'imprimante que vous comptez
utiliser dans /usr/local/bin
mais ne mettez pas dans votre
/etc/printcap
ce qui est conseillé par la documentation de MagicFiler.
2) Ecrivez un /etc/printcap
comme celui la (c'est pour ma LaserJet
4L) :
lp|ljet4l:\
:cm=HP LaserJet 4L:\
:lp=/dev/null:\ # ou /dev/lp1
:sd=/var/spool/lpd/ljet4l:\
:af=/var/spool/lpd/ljet4l/acct:\
:sh:mx#0:\
:if=/usr/local/bin/main-filter:
Le lp=/dev/..
n'est la que pour servir de vérrou, par conséquent, un
périphérique ``virtuel'' est necessaire pour chaque imprimante distante.
Par exemple, créez le avec un touch /dev/ljet4l
.
3) Ecrivez un filtre /usr/local/bin/main-filter
de cette maniere la, en
utilisant ljet4l-filter
a la place de cat
:
Voici le mien :
#! /bin/sh
logfile=/var/log/smb-print.log
spool_dir=/var/spool/lpd/ljet4l
(
echo "print -"
/usr/local/bin/ljet4l-filter
) | /usr/bin/smbclient "\\\\SHIR\\HPLJ4" -N -P >> $logfile
P.S. : Voici l'extrait du mini howto Print2Win a propos des vérous et des imprimantes virtuelles.
---Ca commence ici
deux petits trucs de Rick Bressler :
Voici un bon truc. J'utilise quelque chose d'assez similaire. Un truc qui aide pas mal, voici la chose a ne pas faire :
:lp=/dev/null:\
lpr ouvre de maniere exclusive le fichier que vous spécifiez comme
lp=
. Il fait cela de maniere a empecher plusieurs process d'imprimer
sur la même imprimante en même temps.
L'effet de bord dans ce cas est que deux imprimantes ayant le meme lp=
ne pourront pas imprimer en même temps, (c'est habituellement assez
transparent car elles sont peut etre rapides et comme elles utilisent une file
d'attente, vous ne vous en rendez peut etre pas compte) mais tout autre
processus qui tentera d'écrire sur /dev/null ne marchera plus !
Sur un systeme monoutilisateur, ce n'est probablement pas un probleme. J'ai un systeme avec plus de 50 imprimantes, et la, c'est un probleme
La solution est de créer une imprimante virtuelle pour chacun. Ex : touch /dev/couleur
J'ai modifié les entrées lp dans le fichier printcap
pour prendre en
compte les suggestions de Rick. J'ai fait les choses suivantes :
#touch /dev/laser
#touch /dev/couleur
---Fin
--------------------------%<----------------------------------