One of the features of pdq and lpd is that they support printing over
the network to printers physically connected to a different machine.
With the careful combination of filter scripts and assorted utilities,
you can make either print transparently to printers on all sorts of
networks.
To allow remote machines to print to your printer using the LPD
protocol, you must list the machines in /etc/hosts.equiv or
/etc/hosts.lpd. (Note that hosts.equiv has a host of
other effects; be sure you know what you are doing if you list any
machine there). You can allow only certain users on the other
machines to print to your printer by usign the rs attribute; read
the lpd man
page for information on this.
With pdq
With PDQ, you define a printer with the interface type "bsd-lpd".
This interface takes arguments for the remote hostname and queue name;
the printer definition wizard will prompt you for these.
With lpd
To print to another machine, you make an /etc/printcap entry
like this:
Note that there is still a spool directory on the local machine
managed by lpd. If the remote machine is busy or offline, print
jobs from the local machine wait in the spool area until they can be
sent.
With rlpr
You can also use rlpr to send a print job directly to a queue
on a remote machine without going through the hassle of configuring
lpd to handle it. This is mostly useful in situations where you print
to a variety of printers only occasionally. From the announcement for
rlpr:
Rlpr uses TCP/IP to send print jobs to lpd servers anywhere on a
network.
Unlike lpr, it *does not* require that the remote printers be
explicitly known to the machine you wish to print from, (e.g. through
/etc/printcap) and thus is considerably more flexible and
requires less administration.
rlpr can be used anywhere a traditional lpr might be used, and is
backwards compatible with traditional BSD lpr.
The main power gained by rlpr is the power to print remotely *from
anywhere to anywhere* without regard for how the system you wish to
print from was configured. Rlpr can work as a filter just like
traditional lpr so that clients executing on a remote machine like
netscape, xemacs, etc, etc can print to your local machine with little
effort.
There is a Printing to Windows mini-HOWTO out there which has more
info than there is here.
From PDQ
There is not a prebuilt smb interface that I am aware of, but it would
be fairly easy to create using the model set by the Netatalk-based
appletalk interface. Someone please create one and submit it for
inclusion!
Read the Windows/LPD section below for more tips on how to do it.
From LPD
It is possible to direct a print queue through the smbclient
program (part of the samba suite) to a TCP/IP based SMB print service.
Samba includes a script to do this called smbprint. In short,
you put a configuration file for the specific printer in question in
the spool directory, and install the smbprint script as the
if.
The ncpfs suite includes a utility called nprint which provides
the same functionality as smbprint but for NetWare. You can get
ncpfs from
Metalab. From the
LSM entry for version 0.16:
With ncpfs you can mount volumes of your netware server under
Linux. You can also print to netware print queues and spool netware
print queues to the Linux printing system. You need kernel 1.2.x or
1.3.54 and above. ncpfs does NOT work with any 1.3.x kernel below
1.3.54.
From LPD
To make nprint work via lpd, you write a little shell script to
print stdin on the NetWare printer, and install that as the if
for an lpd print queue. You'll get something like:
The netatalk package includes something like nprint and
smbclient. Others have documented the procedure for
printing to and from an Apple network far better than I ever will; see
the
Linux Netatalk-HOWTO.
From PDQ
PDQ includes an interface declaration called "appletalk". This uses
the Netatalk package to print to a networked Apple printer. Just
select this interface in xpdq's "Add printer" wizard.
HPs and some other printers come with an ethernet interface which you
can print to directly using the lpd protocol. You should follow the
instructions that came with your printer or its network adaptor, but
in general, such printers are "running" lpd, and provide one or more
queues which you can print to. An HP, for example, might work with a
printcap like:
or, using the PDQ bsd-lpd interface arguments of
REMOTE_HOST=printer.name.com and QUEUE=raw.
HP Laserjet printers with Jet Direct interfaces generally support two
built in lpd queues - "raw" which accepts PCL (and possibly
Postscript) and "text" which accepts straight ascii (and copes
automatically with the staircase effect). If you've got a JetDirect
Plus3 three-port box, the queues are named "raw1", "text2", and so
forth.
Note that the ISS company has identified an assortment of denial of
service attacks which hang HP Jetdirect interfaces. Most of these
have been addressed beginning in Fall 98.
In a large scale environment, especially a large environment where
some printers do not support PostScript, it may be useful to establish
a dedicated print server to which all machines print and on which all
ghostscript jobs are run. This will allow the queue to be paused or
reordered using the topq and lprm commands.
This also allows your Linux box to act as a spool server for the
printer so that your network users can complete their print jobs
quickly and get on with things without waiting for the printer to
print any other job that someone else has sent. This is suggested too
if you have unfixable older HP Jetdirects; it reduces the likelihood
of the printers wedging.
To do this, set up a queue on your linux box that points at the
ethernet equipped HP LJ (as above). Now set up all the clients on your
LAN to point at the Linux queue (eg lj-5 in the example above).
Some HP network printers apparently don't heed the banner page setting
sent by clients; you can turn off their internally generated banner
page by telnetting to the printer, hitting return twice, typing
"banner: 0" followed by "quit". There are other settings you can
change this way, as well; type "?" to see a list.
The full range of settings can be controlled with HP's
WebJet software. This
package runs as a daemon, and accepts http requests on a designated
port. It serves up forms and Java applets which can control HP
printers on the network. In theory, it can also control Unix print
queues, but it does so using the rexec service, which is completely
unsecure. I don't advise using that feature.
To older HPs
Some printers (and printer networking "black boxes") support only a
cheesy little non-protocol involving plain TCP connections. Notable
in this category are early-model JetDirect (including some
JetDirectEx) cards. Basically, to print to the printer, you must open
a TCP connection to the printer on a specified port (typically 9100,
or 9100, 9101 and 9102 for three-port boxes) and stuff your print job
into it. LPRng has built-in support for stuffing print jobs
into random TCP ports, but with BSD lpd it's not so easy. The best
thing is probably to obtain and use the little utility called netcat.
A netcat-using PDQ interface would look something like this:
interface tcp-port-0.1 {
help "This is one of the first interfaces supported by standalone
network printers and print servers. The device simply
listens for a TCP connection on a certain port, and sends
data from any connection to the printer.\nThis interface
requires the netcat program (\"nc\")."
required_args "REMOTE_HOST"
argument {
var = "REMOTE_HOST"
desc = "Remote host"
help = "This is IP name or number of the print server."
}
argument {
var = "REMOTE_PORT"
def_value = "9100"
desc = "Remote port"
help = "This is the TCP port number on the print server that the
print job should be sent to. Most JetDirect cards, and
clones, accept jobs on port 9100 (or 9101 for port 2,
etc)."
}
requires "nc"
# nc ends after 45 seconds of no network activity; it doesn't
# actually stop on EOF the way we'd like.
send_exec { cat $OUTPUT | nc -w 45 $REMOTE_HOST $REMOTE_PORT }
}
Failing that, it can be implemented, among other ways, in Perl using
the program below. Or, or better performance, use the program netcat
("nc"), which does much the same thing in a general purpose way. Most
distributions should have netcat available in prepackaged form.
#!/usr/bin/perl
# Thanks to Dan McLaughlin for writing the original version of this
# script (And to Jim W. Jones for sitting next to Dan when writing me
# for help ;)
$fileName = @ARGV[0];
open(IN,"$fileName") || die "Can't open file $fileName";
$dpi300 = "\x1B*t300R";
$dosCr = "\x1B&k3G";
$ends = "\x0A";
$port = 9100 unless $port;
$them = "bach.sr.hp.com" unless $them;
$AF_INET = 2;
$SOCK_STREAM = 1;
$SIG{'INT'} = 'dokill';
$sockaddr = 'S n a4 x8';
chop($hostname = `hostname`);
($name,$aliases,$proto) = getprotobyname('tcp');
($name,$aliases,$port) = getservbyname($port,'tcp')
unless $port =~ /^\d+$/;;
($name,$aliases,$type,$len,$thisaddr) =
gethostbyname($hostname);
($name,$aliases,$type,$len,$thataddr) = gethostbyname($them);
$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
$that = pack($sockaddr, $AF_INET, $port, $thataddr);
if (socket(S, $AF_INET, $SOCK_STREAM, $proto)) {
# print "socket ok\n";
}
else {
die $!;
}
# Give the socket an address.
if (bind(S, $this)) {
# print "bind ok\n";
}
else {
die $!;
}
# Call up the server.
if (connect(S,$that)) {
# print "connect ok\n";
}
else {
die $!;
}
# Set socket to be command buffered.
select(S); $| = 1; select(STDOUT);
# print S "@PJL ECHO Hi $hostname! $ends";
# print S "@PJL OPMSG DISPLAY=\"Job $whoami\" $ends";
# print S $dpi300;
# Avoid deadlock by forking.
if($child = fork) {
print S $dosCr;
print S $TimesNewR;
while (<IN>) {
print S;
}
sleep 3;
do dokill();
} else {
while(<S>) {
print;
}
}
sub dokill {
kill 9,$child if $child;
}
One oddity of older version of lpd is that the if is not run for
remote printers. (Version after 0.43 or so have the change originated
on FreeBSD such that the if is always run). If you find that you need
to run an if for a remote printer, and it isn't working with your
lpr, you can do so by setting up a double queue and requeueing the
job. As an example, consider this printcap:
The -U option to lpr only works if lpr is run as daemon, and it
sets the submitter's name for the job in the resubmitted queue
correctly. You should probably use a more robust method of getting
the username, since in some cases it is not argument 5. See the man
page for printcap.
Printing from a Windows (or presumably, OS/2) client to a Linux
server is directly supported over SMB through the use of the SAMBA
package, which also supports file sharing of your Linux filesystem to
Windows clients.
Samba includes fairly complete documentation, and there is a good
Samba FAQ which covers it, too. You can either configure a magic
filter on the Linux box and print PostScript to it, or run around
installing printer-specific drivers on all the Windows machines and
having a queue for them with no filters at all. Relying on the
Windows drivers may in some cases produce better output, but is a bit
more of an administrative hassle if there are many Windows boxen. So
try Postscript first.
With PDQ, you should configure Samba to run the pdq command with
appropriate arguments instead of the lpr command that it defaults to
running. I believe that Samba will run pdq as the proper user, so it
should work well this way. There are several Samba options that you
should adjust to do this:
printcap
This should point to a "fake" printcap you whip up
listing available printers. All you need is a short and long name
for each printer, one per line:
lp1|Printer One
lp2|Printer Two
lp3|Printer Three
The short name will be used as the printer name for the print
command:
print command
This will need to be set to something like
pdq -P %p %s ; rm %s.
lprm command
There doesn't seem to be a good value for this
setting at the moment. PDQ's queued jobs will expire after a time,
so if the printer is totally gone there's no problem. If you just
change your mind, you can use xpdq to cancel jobs, but this is
inconvenient from Windows. Just put a do-nothing command like
true for now. If you use lpd or lprng as the back-end, then a
suitable lprm command should work. I'm not sure how Samba would
identify the lpr queue entry number for a pdq-submitted job.
lpq command
Again, PDQ doesn't offer a good value to put here.
Distributed systems don't offer a sensible way to see the queue, but
samba-centric centralized server systems to have a queue worth
examining. Just put a do-nothing command like true for now. If you
use lpd or lprng as the back-end, then a suitable lpq command should
work; you just won't see jobs until they're done being filtered by
PDQ.
The ncpfs package includes a daemon named pserver which can be used to
privide service to a NetWare print queue. From what I understand,
this system requires a Bindery-based NetWare, ie 2.x, 3.x, or 4.x with
bindery access enabled.
For more information on ncpfs and it's pserver program, see
the ncpfs FTP site.