Para compartilhar uma impressora de uma máquina Windows, você deve fazer o seguinte:
cm - comentário
lp - dispositivo a abrir para saída
sd - o diretório de spool da impressora (na máquina local).
af - o arquivo de registro (contabilidade)
mx - o tamanho máximo de arquivo (zero é ilimitado)
if - o nome do filtro de entrada.
# /etc/printcap
#
# //zimmerman/oreilly via smbprint
#
lp:\
:cm=HP 5MP Postscript OReilly on zimmerman:\
:lp=/dev/lp1:\
:sd=/var/spool/lpd/lp:\
:af=/var/spool/lpd/lp/acct:\
:mx#0:\
:if=/usr/bin/smbprint:
Tenha certeza que os diretórios de spool e registro (contabilidade) existem e são graváveis. Assegure-se que a linha que tem o 'if' contenha o caminho correto para o script smbprint (dado abaixo) e tenha certeza que o dispositivo apropriado tenha sido indicado (o arquivo especial /dev).
Depois vem o próprio script smbprint. Ele normalmente é colocado em /usr/bin e é atribuído a Andrew Tridgell, a pessoa que criou o Samba, até onde eu sei. Ele vem junto da distribuição dos fontes do Samba, mas não vem em algumas distribuições binárias, assim sendo eu o reproduzi aqui.
Você pode quer dar uma olhada cuidadosa nele. Há algumas pequenas alterações que se mostraram muito úteis.
#!/bin/sh -x
# This script is an input filter for printcap printing on a unix machine. It
# uses the smbclient program to print the file to the specified smb-based
# server and service.
# For example you could have a printcap entry like this
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# which would create a unix printer called "smb" that will print via this
# script. You will need to create the spool directory /usr/spool/smb with
# appropriate permissions and ownerships for your system.
# Set these to the server and service you wish to print to
# In this example I have a WfWg PC called "lapland" that has a printer
# exported called "printer" with no password.
#
# Script further altered by hamiltom@ecnz.co.nz (Michael Hamilton)
# so that the server, service, and password can be read from
# a /usr/var/spool/lpd/PRINTNAME/.config file.
#
# In order for this to work the /etc/printcap entry must include an
# accounting file (af=...):
#
# cdcolour:\
# :cm=CD IBM Colorjet on 6th:\
# :sd=/var/spool/lpd/cdcolour:\
# :af=/var/spool/lpd/cdcolour/acct:\
# :if=/usr/local/etc/smbprint:\
# :mx=0:\
# :lp=/dev/null:
#
# The /usr/var/spool/lpd/PRINTNAME/.config file should contain:
# server=PC_SERVER
# service=PR_SHARENAME
# password="password"
#
# E.g.
# server=PAULS_PC
# service=CJET_371
# password=""
#
# Debugging log file, change to /dev/null if you like.
#
logfile=/tmp/smb-print.log
# logfile=/dev/null
#
# The last parameter to the filter is the accounting file name.
#
spool_dir=/var/spool/lpd/lp
config_file=$spool_dir/.config
# Should read the following variables set in the config file:
# server
# service
# password
# user
eval `cat $config_file`
#
# Some debugging help, change the >> to > if you want to same space.
#
echo "server $server, service $service" >> $logfile
(
# NOTE You may wish to add the line `echo translate' if you want automatic
# CR/LF translation when printing.
echo translate
echo "print -"
cat
) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $logfile
A maioria das distribuições Linux vem com o nenscript para converter documentos ASCII em Postscript. O script perl abaixo facilita a nossa vida fornecendo uma interface simples ao Linux para impressão via smbprint.
Uso: print [-a|c|p] <nomedoarquivo>
-a imprime <nomedoarquivo> como ASCII
-c imprime <nomedoarquivo> como arquivo fonte formatado
-p imprime <nomedoarquivo> como Postscript
Se nenhuma opção for dada, print tenta descobrir o
tipo de arquivo e imprimi-lo apropriadamente.
#!/usr/bin/perl
# Script: print
# Autores: Brad Marshall, David Wood
# Plugged In Communications
# Data: 960808
#
# Script para imprimir numa impressora Postscript printer via Samba.
# Finalidade: Pega arquivos de vários tipos e arqumentos e os processa
# apropriadamente para um canal(pipe) do script de impressão do Samba.
#
# Currently supported file types:
#
# ASCII - assegura-se que as linhas maiores que $line_length caracteres
# sejam quebradas nos espaçoes em branco.
# Postscript - Não faz nada.
# Code - Formata em Postscript (usando nenscript) para aparecer
# adequadamente(landscape, font, etc).
#
# Determina o maior comprimento de linha permitido em textos ASCII
$line_length = 76;
# Determina o nome e o caminho do script de impressão do samba
$print_prog = "/usr/bin/smbprint";
# Determina o nome e o caminho para o nescript (o conversor ASCII-->Postscript)
$nenscript = "/usr/bin/nenscript";
unless ( -f $print_prog ) {
die "Não pude encontrar $print_prog!";
}
unless ( -f $nenscript ) {
die "Não pude encontrar $nenscript!";
}
&ParseCmdLine(@ARGV);
# DBG
print "Arquivo do tipo $filetype\n";
if ($filetype eq "ASCII") {
&wrap($line_length);
} elsif ($filetype eq "code") {
&codeformat;
} elsif ($filetype eq "ps") {
&createarray;
} else {
print "Desculpe... tipo de arquivo desconhecido.\n";
exit 0;
}
# Canalisa a matriz para o smbprint
open(PRINTER, "|$print_prog") || die "Não pude abrir $print_prog: $!\n";
foreach $line (@newlines) {
print PRINTER $line;
}
# Envia um linefeed extra no caso do arquivo ter uma última linha incompleta.
print PRINTER "\n";
close(PRINTER);
print "Completed\n";
exit 0;
# --------------------------------------------------- #
# Tudo daqui para baixo são sub-rotinas #
# --------------------------------------------------- #
sub ParseCmdLine {
# Parses the command line, finding out what file type the file is
# Gets $arg and $file to be the arguments (if the exists)
# and the filename
if ($#_ < 0) {
&usage;
}
# DBG
# foreach $element (@_) {
# print "*$element* \n";
# }
$arg = shift(@_);
if ($arg =~ /\-./) {
$cmd = $arg;
# DBG
# print "\$cmd found.\n";
$file = shift(@_);
} else {
$file = $arg;
}
# Defining the file type
unless ($cmd) {
# We have no arguments
if ($file =~ /\.ps$/) {
$filetype = "ps";
} elsif ($file =~ /\.java$|\.c$|\.h$|\.pl$|\.sh$|\.csh$|\.m4$|\.inc$|\.html$|\.htm$/) {
$filetype = "code";
} else {
$filetype = "ASCII";
}
# Process $file for what type is it and return $filetype
} else {
# We have what type it is in $arg
if ($cmd =~ /^-p$/) {
$filetype = "ps";
} elsif ($cmd =~ /^-c$/) {
$filetype = "code";
} elsif ($cmd =~ /^-a$/) {
$filetype = "ASCII"
}
}
}
sub usage {
print "
Usage: print [-a|c|p] <filename>
-a prints <filename> as ASCII
-c prints <filename> formatted as source code
-p prints <filename> as Postscript
If no switch is given, print attempts to
guess the file type and print appropriately.\n
";
exit(0);
}
sub wrap {
# Create an array of file lines, where each line is < the
# number of characters specified, and wrapped only on whitespace
# Get the number of characters to limit the line to.
$limit = pop(@_);
# DBG
#print "Entering subroutine wrap\n";
#print "The line length limit is $limit\n";
# Read in the file, parse and put into an array.
open(FILE, "<$file") || die "Can't open $file: $!\n";
while(<FILE>) {
$line = $_;
# DBG
#print "The line is:\n$line\n";
# Wrap the line if it is over the limit.
while ( length($line) > $limit ) {
# DBG
#print "Wrapping...";
# Get the first $limit +1 characters.
$part = substr($line,0,$limit +1);
# DBG
#print "The partial line is:\n$part\n";
# Check to see if the last character is a space.
$last_char = substr($part,-1, 1);
if ( " " eq $last_char ) {
# If it is, print the rest.
# DBG
#print "The last character was a space\n";
substr($line,0,$limit + 1) = "";
substr($part,-1,1) = "";
push(@newlines,"$part\n");
} else {
# If it is not, find the last space in the
# sub-line and print up to there.
# DBG
#print "The last character was not a space\n";
# Remove the character past $limit
substr($part,-1,1) = "";
# Reverse the line to make it easy to find
# the last space.
$revpart = reverse($part);
$index = index($revpart," ");
if ( $index > 0 ) {
substr($line,0,$limit-$index) = "";
push(@newlines,substr($part,0,$limit-$index)
. "\n");
} else {
# There was no space in the line, so
# print it up to $limit.
substr($line,0,$limit) = "";
push(@newlines,substr($part,0,$limit)
. "\n");
}
}
}
push(@newlines,$line);
}
close(FILE);
}
sub codeformat {
# Call subroutine wrap then filter through nenscript
&wrap($line_length);
# Pipe the results through nenscript to create a Postscript
# file that adheres to some decent format for printing
# source code (landscape, Courier font, line numbers).
# Print this to a temporary file first.
$tmpfile = "/tmp/nenscript$$";
open(FILE, "|$nenscript -2G -i$file -N -p$tmpfile -r") ||
die "Can't open nenscript: $!\n";
foreach $line (@newlines) {
print FILE $line;
}
close(FILE);
# Read the temporary file back into an array so it can be
# passed to the Samba print script.
@newlines = ("");
open(FILE, "<$tmpfile") || die "Can't open $file: $!\n";
while(<FILE>) {
push(@newlines,$_);
}
close(FILE);
system("rm $tmpfile");
}
sub createarray {
# Create the array for postscript
open(FILE, "<$file") || die "Can't open $file: $!\n";
while(<FILE>) {
push(@newlines,$_);
}
close(FILE);
}
Agora, via MagicFilter. Obrigado a Alberto Menegazzi (
flash.egon@iol.it) por esta informação.
Alberto disse:
--------------------------%<----------------------------------
1) Instale o MagicFilter com o filtro de impressoras que você precisa em /usr/bin/local mas não preencha o /etc/printcap com a sugestão dada na documentação do MagicFilter.
2) Escreva o /etc/printcap desta forma (está feito para minha LaserJet 4L):
lp|ljet4l:\
:cm=HP LaserJet 4L:\
:lp=/dev/null:\ # or /dev/lp1
:sd=/var/spool/lpd/ljet4l:\
:af=/var/spool/lpd/ljet4l/acct:\
:sh:mx#0:\
:if=/usr/local/bin/main-filter:
Você pode perceber que o lp=/dev/... está aberto para fazer o locking de tais dispositivos "virtuais", deve ser usado um para cada impressora remota.
Exemplo criando com: touch /dev/ljet4l
Escreva o filtro /usr/local/bin/main-filter, o mesmo que você sugeriu usando o filtro ljet4l-filter ao invés do cat.
Aqui está o meu:
#! /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. : aqui vai uma citação do Print2Win mini-Howto sobre locking e porque criar impressoras virtuais
Starts here-->
---Começa aqui
Dica de Rick Bressler :
Boa dica. Eu uso algo muito parecido. Uma dica útil é que isso não é uma boa idéia:
:lp=/dev/null:\
lpr abre em modo exclusivo o arquivo que você especifica em lp=. Ele o faz para evitar que vários processos tentem imprimir na mesma impressora ao mesmo tempo.
O efeito colateral disto no seu caso, eng e colour não podem imprimir ao mesmo tempo, (normalmente mais ou menos transparente, já que provavelmente elas imprimem rapidamente e já que elas enfileram, você provavelmente não percebe) mas qualquer outro processo que tenta escrever em /dev/null será quebrado!
Em um sistema monousuário, provavelmente não é um grande problema. Eu tenho um sistema com mais de 50 impressoras. Haveria um problema aqui.
A solução é criar uma impressora burra para cada. Exemplo: touch /dev/eng.
Eu modifiquei as entradas lp no arquivo printcap acima para levar em conta as sugestões do Rick. Eu fiz o seguinte:
#touch /dev/eng
#touch /dev/colour
Ends here-->
---Termina aqui
--------------------------%<----------------------------------