4056 lines
		
	
	
	
		
			149 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			4056 lines
		
	
	
	
		
			149 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| <!-- This is an SGML document in the linuxdoc DTD describing
 | |
|      Printing with FreeBSD.  By Sean Kelly, 1995.
 | |
| 
 | |
|      $Id: printing.sgml,v 1.21 1997-10-11 11:20:20 jraynard Exp $
 | |
| 
 | |
|      The FreeBSD Documentation Project
 | |
| 
 | |
| <!DOCTYPE linuxdoc PUBLIC "-//FreeBSD//DTD linuxdoc//EN">
 | |
| 
 | |
|   <article>
 | |
|       <title> Printing with FreeBSD
 | |
|       <author> Sean Kelly <tt/kelly@fsl.noaa.gov/
 | |
|       <date> 30 September 1995, (c) 1995
 | |
| 
 | |
|       <abstract> This document describes printing with FreeBSD.  It
 | |
| 	tells how to set up printer hardware, how to configure FreeBSD
 | |
| 	to use printers, and how to control the print queue and print
 | |
| 	a variety of file formats. </abstract>
 | |
| 
 | |
|     <toc>
 | |
| -->
 | |
| 
 | |
|   <chapt><heading>Printing<label id="printing"></heading>
 | |
| 
 | |
|     <p><em>Contributed by &a.kelly;<newline>30 September 1995</em>
 | |
| 
 | |
|         In order to use printers with FreeBSD, you will need to set
 | |
| 	them up to work with the Berkeley line printer spooling
 | |
| 	system, also known as the LPD spooling system.  It is the
 | |
| 	standard printer control system in FreeBSD.  This section
 | |
| 	introduces the LPD spooling system, often simply called LPD.
 | |
| 
 | |
| 	If you are already familiar with LPD or another printer
 | |
| 	spooling system, you may wish to skip to section <ref
 | |
| 	id="printing:intro:setup" name="Setting up the spooling
 | |
| 	system">.
 | |
| 
 | |
|       <sect><heading>What the Spooler Does<label
 | |
| 	    id="printing:intro:spooler"></heading>
 | |
| 
 | |
| 	<p> LPD controls everything about a host's printers.  It is
 | |
| 	  responsible for a number of things:
 | |
| 
 | |
| 	  <itemize>
 | |
| 	    <item>It controls access to attached printers and
 | |
| 	      printers attached to other hosts on the network.
 | |
| 
 | |
| 	    <item>It enables users to submit files to be printed;
 | |
| 	      these submissions are known as <em/jobs/.
 | |
| 
 | |
| 	    <item>It prevents multiple users from accessing a printer
 | |
| 	      at the same time by maintaining a <em/queue/ for each
 | |
| 	      printer.
 | |
| 
 | |
| 	    <item>It can print <em/header pages/ (also known as
 | |
| 	      <em/banner/ or <em/burst/ pages) so users can easily
 | |
| 	      find jobs they have printed in a stack of printouts.
 | |
| 
 | |
| 	    <item>It takes care of communications parameters for
 | |
| 	      printers connected on serial ports.
 | |
| 
 | |
| 	    <item>It can send jobs over the network to another LPD
 | |
| 	      spooler on another host.
 | |
| 
 | |
| 	    <item>It can run special filters to format jobs to be
 | |
| 	      printed for various printer languages or printer
 | |
| 	      capabilities.
 | |
| 
 | |
| 	    <item>It can account for printer usage.
 | |
| 	  </itemize>
 | |
| 
 | |
| 	  Through a configuration file, and by providing the special
 | |
| 	  filter programs, you can enable the LPD system to do all or
 | |
| 	  some subset of the above for a great variety of printer
 | |
| 	  hardware.
 | |
| 
 | |
|       <sect><heading>Why You Should Use the Spooler<label
 | |
| 	    id="printing:intro:why"></heading> 
 | |
| 
 | |
| 	<p> If you are the sole user of your system, you may be
 | |
| 	  wondering why you should bother with the spooler when you
 | |
| 	  do not need access control, header pages, or printer
 | |
| 	  accounting.  While it is possible to enable direct access to
 | |
| 	  a printer, you should use the spooler anyway since
 | |
| 
 | |
| 	  <itemize>
 | |
| 	    <item>LPD prints jobs in the background; you do not have
 | |
| 	      to wait for data to be copied to the printer.
 | |
| 
 | |
| 	    <item>LPD can conveniently run a job to be printed
 | |
| 	      through filters to add date/time headers or convert a
 | |
| 	      special file format (such as a TeX DVI file) into a
 | |
| 	      format the printer will understand.   You will not have to do
 | |
| 	      these steps manually.
 | |
| 
 | |
| 	    <item>Many free and commercial programs that provide a
 | |
| 	      print feature usually expect to talk to the spooler on
 | |
| 	      your system.  By setting up the spooling system, you will
 | |
| 	      more easily support other software you may later add or
 | |
| 	      already have.
 | |
| 	  </itemize>
 | |
| 
 | |
|       <sect><heading>Setting Up the Spooling System<label
 | |
| 	    id="printing:intro:setup"></heading>
 | |
| 
 | |
| 	<p> To use printers with the LPD spooling system, you will need
 | |
| 	  to set up both your printer hardware and the LPD software.
 | |
| 	  This document describes two levels of setup:
 | |
| 
 | |
| 	  <itemize>
 | |
| 	    <item>See section <ref name="Simple Printer Setup"
 | |
| 		id="printing:simple"> to learn how to connect a
 | |
| 		printer, tell LPD how to communicate with it, and
 | |
| 		print plain text files to the printer.
 | |
| 
 | |
| 	    <item>See section <ref name="Advanced Printer Setup"
 | |
| 		id="printing:advanced"> to find out how to print a
 | |
| 		variety of special file formats, to print header
 | |
| 		pages, to print across a network, to control access to
 | |
| 		printers, and to do printer accounting.
 | |
| 	  </itemize>
 | |
| 
 | |
| 
 | |
|     <sect><heading>Simple Printer Setup<label
 | |
| 	  id="printing:simple"></heading>
 | |
| 
 | |
|       <p> This section tells how to configure printer hardware and the
 | |
| 	LPD software to use the printer.  It teaches the basics:
 | |
| 
 | |
| 	<itemize>
 | |
| 	  <item>Section <ref id="printing:hardware" name="Hardware
 | |
| 	    Setup"> gives some hints on connecting the printer to a
 | |
| 	    port on your computer.
 | |
| 
 | |
| 	  <item>Section <ref id="printing:software" name="Software
 | |
| 	    Setup"> shows how to setup the LPD spooler configuration
 | |
| 	    file <tt>/etc/printcap</tt>.
 | |
| 	</itemize>
 | |
| 
 | |
|         If you are setting up a printer that uses a network protocol
 | |
| 	to accept data to print instead of a serial or parallel interface,
 | |
| 	see <ref id="printing:advanced:network:net-if" name="Printers
 | |
| 	  With Networked Data Stream Interaces">.
 | |
| 
 | |
| 	Although this section is called ``Simple Printer Setup,'' it is
 | |
| 	actually fairly complex.  Getting the printer to work with
 | |
| 	your computer and the LPD spooler is the hardest part.  The
 | |
| 	advanced options like header pages and accounting are fairly
 | |
| 	easy once you get the printer working.
 | |
| 
 | |
|       <sect1><heading>Hardware Setup<label id="printing:hardware"></heading>
 | |
| 
 | |
| 	<p> This section tells about the various ways you can connect a
 | |
| 	  printer to your PC.  It talks about the kinds of ports and
 | |
| 	  cables, and also the kernel configuration you may need to
 | |
| 	  enable FreeBSD to speak to the printer.
 | |
| 
 | |
| 	  If you have already connected your printer and have
 | |
| 	  successfully printed with it under another operating system,
 | |
| 	  you can probably skip to section <ref id="printing:software"
 | |
| 	  name="Software Setup">.
 | |
| 
 | |
| 	<sect2><heading>Ports and Cables<label
 | |
| 	      id="printing:ports"></heading> 
 | |
| 
 | |
| 	  <p> Nearly all printers you can get for a PC today support
 | |
| 	    one or both of the following interfaces:
 | |
| 
 | |
| 	    <itemize>
 | |
| 	      <item><em/Serial/ interfaces use a serial port on your
 | |
| 		computer to send data to the printer.  Serial
 | |
| 		interfaces are common in the computer industry and
 | |
| 		cables are readily available and also easy to
 | |
| 		construct.  Serial interfaces sometimes need special
 | |
| 		cables and might require you to configure somewhat
 | |
| 		complex communications options.
 | |
| 
 | |
| 	      <item><em/Parallel/ interfaces use a parallel port on
 | |
| 		your computer to send data to the printer.  Parallel
 | |
| 		interfaces are common in the PC market.  Cables are
 | |
| 		readily available but more difficult to construct by
 | |
| 		hand.  There are usually no communications options
 | |
| 		with parallel interfaces, making their configuration
 | |
| 		exceedingly simple.
 | |
| 
 | |
| 		<p> Parallel interfaces are sometimes known as
 | |
| 		  ``Centronics'' interfaces, named after the connector
 | |
| 		  type on the printer.
 | |
| 	    </itemize>
 | |
| 
 | |
| 	    In general, serial interfaces are slower than parallel
 | |
| 	    interfaces.  Parallel interfaces usually offer just
 | |
| 	    one-way communication (computer to printer) while serial
 | |
| 	    gives you two-way.  Many newer parallel ports can also
 | |
| 	    receive data from the printer, but only few printers need
 | |
| 	    to send data back to the computer.  And FreeBSD does not
 | |
| 	    support two-way parallel communication yet.
 | |
| 
 | |
| 	    Usually, the only time you need two-way communication with
 | |
| 	    the printer is if the printer speaks PostScript.
 | |
| 	    PostScript printers can be very verbose.  In fact,
 | |
| 	    PostScript jobs are actually programs sent to the printer;
 | |
| 	    they need not produce paper at all and may return results
 | |
| 	    directly to the computer.  PostScript also uses
 | |
| 	    two-way communication to tell the computer about problems,
 | |
| 	    such as errors in the PostScript program or paper jams.
 | |
| 	    Your users may be appreciative of such information.
 | |
| 	    Furthermore, the best way to do effective accounting with
 | |
| 	    a PostScript printer requires two-way communication: you
 | |
| 	    ask the printer for its page count (how many pages it has
 | |
| 	    printed in its lifetime), then send the user's job, then
 | |
| 	    ask again for its page count. Subtract the two values and
 | |
| 	    you know how much paper to charge the user.
 | |
| 
 | |
| 	    So, which interface should you use?
 | |
| 
 | |
| 	    <itemize>
 | |
| 	      <item>If you need two-way communication, use a serial
 | |
| 		port.  FreeBSD does not yet support two-way
 | |
| 		communication over a parallel port.
 | |
| 
 | |
| 	      <item>If you do not need two-way communication and can
 | |
| 		pick parallel or serial, prefer the parallel
 | |
| 		interface.  It keeps a serial port free for other
 | |
| 		peripherals---such as a terminal or a modem---and is
 | |
| 		faster most of the time.  It is also easier to
 | |
| 		configure.
 | |
| 
 | |
| 	      <item>Finally, use whatever works.	
 | |
| 	    </itemize>
 | |
| 
 | |
| 
 | |
| 	<sect2><heading>Parallel Ports<label id="printing:parallel"></heading>
 | |
| 
 | |
| 	  <p> To hook up a printer using a parallel interface, connect
 | |
| 	    the Centronics cable between the printer and the
 | |
| 	    computer. The instructions that came with the printer, the
 | |
| 	    computer, or both should give you complete guidance.
 | |
| 
 | |
| 	    Remember which parallel port you used on the computer. The
 | |
| 	    first parallel port is /dev/lpt0 to FreeBSD; the second is
 | |
| 	    /dev/lpt1, and so on.
 | |
| 
 | |
| 	<sect2><heading>Serial Ports<label id="printing:serial"></heading>
 | |
| 
 | |
| 	  <p> To hook up a printer using a serial interface, connect
 | |
| 	    the proper serial cable between the printer and the
 | |
| 	    computer.  The instructions that came with the printer,
 | |
| 	    the computer, or both should give you complete guidance.
 | |
| 
 | |
| 	    If you are unsure what the ``proper serial cable'' is, you
 | |
| 	    may wish to try one of the following alternatives:
 | |
| 	    <itemize>
 | |
| 	      <item>A <em/modem/ cable connects each pin of the
 | |
| 		connector on one end of the cable straight through to
 | |
| 		its corresponding pin of the connector on the other
 | |
| 		end.  This type of cable is also known as a DTE-to-DCE
 | |
| 		cable.
 | |
| 
 | |
| 	      <item>A <em/null-modem/ cable connects some pins
 | |
| 		straight through, swaps others (send data to receive
 | |
| 		data, for example), and shorts some internally in each
 | |
| 		connector hood.  This type of cable is also known as a
 | |
| 		DTE-to-DTE cable.
 | |
| 
 | |
| 	      <item>A <em/serial printer/ cable, required for some
 | |
| 		unusual printers, is like the null modem cable, but
 | |
| 		sends some signals to their counterparts instead of
 | |
| 		being internally shorted.
 | |
| 	    </itemize>
 | |
| 
 | |
| 	    You should also set up the communications parameters for
 | |
| 	    the printer, usually through front-panel controls or DIP
 | |
| 	    switches on the printer.  Choose the highest bps (bits per
 | |
| 	    second, sometimes <em/baud rate/) rate that both your
 | |
| 	    computer and the printer can support.  Choose 7 or 8 data
 | |
| 	    bits; none, even, or odd parity; and 1 or 2 stop bits.
 | |
| 	    Also choose a flow control protocol: either none, or
 | |
| 	    XON/XOFF (also known as <em/in-band/ or <em/software/)
 | |
| 	    flow control.  Remember these settings for the software
 | |
| 	    configuration that follows.
 | |
| 
 | |
|       <sect1><heading>Software Setup<label id="printing:software"></heading>
 | |
| 
 | |
| 	<p> This section describes the software setup necessary to
 | |
| 	  print with the LPD spooling system in FreeBSD.
 | |
| 
 | |
| 	  Here is an outline of the steps involved:
 | |
| 	  <enum>
 | |
| 	    <item>Configure your kernel, if necessary, for the port
 | |
| 	      you are using for the printer; section <ref
 | |
| 	      id="printing:kernel" name="Kernel Configuration"> tells
 | |
| 	      you what you need to do.
 | |
| 
 | |
| 	    <item>Set the communications mode for the parallel port,
 | |
| 	      if you are using a parallel port; section <ref
 | |
| 	      id="printing:parallel-port-mode" name = "Setting the
 | |
| 	      Communication Mode for the Parallel Port"> gives
 | |
| 	      details.
 | |
| 
 | |
| 	    <item>Test if the operating system can send data to the
 | |
| 	      printer.  Section <ref id="printing:testing"
 | |
| 	      name="Checking Printer Communications"> gives some
 | |
| 	      suggestions on how to do this.
 | |
| 
 | |
| 	    <item>Set up LPD for the printer by modifying the file
 | |
| 	      <tt>/etc/printcap</tt>.  Section <ref
 | |
| 	      id="printing:printcap" name="The /etc/printcap File">
 | |
| 	      shows you how.
 | |
| 	  </enum>
 | |
| 
 | |
| 	<sect2><heading>Kernel Configuration<label
 | |
| 	      id="printing:kernel"></heading>
 | |
| 
 | |
| 	  <p> The operating system kernel is compiled to work with a
 | |
| 	    specific set of devices.  The serial or parallel interface
 | |
| 	    for your printer is a part of that set.  Therefore, it
 | |
| 	    might be necessary to add support for an additional serial
 | |
| 	    or parallel port if your kernel is not already configured
 | |
| 	    for one.
 | |
| 
 | |
| 	    To find out if the kernel you are currently using supports a serial
 | |
| 	    interface, type
 | |
| <tscreen>
 | |
| <tt>dmesg | grep sio</tt><it/N/
 | |
| </tscreen>
 | |
| 	    where <it/N/ is the number of the serial port, starting
 | |
| 	    from zero.  If you see output similar to the following
 | |
| <tscreen><verb> 
 | |
| sio2 at 0x3e8-0x3ef irq 5 on isa
 | |
| sio2: type 16550A
 | |
| </verb></tscreen>
 | |
| 	    then the kernel supports the port.
 | |
| 
 | |
| 	    To find out if the kernel supports a parallel interface,
 | |
| 	    type
 | |
| <tscreen>
 | |
| <tt>dmesg | grep lpt</tt><it/N/
 | |
| </tscreen>
 | |
| 	    where <it/N/ is the number of the parallel port, starting
 | |
| 	    from zero.  If you see output similar to the following
 | |
| <tscreen><verb>
 | |
| lpt0 at 0x378-0x37f on isa
 | |
| </verb></tscreen>
 | |
| 	    then the kernel supports the port.
 | |
| 
 | |
| 	    You might have to reconfigure your kernel in order for the
 | |
| 	    operating system to recognize and use the parallel or
 | |
| 	    serial port you are using for the printer.
 | |
| 
 | |
| 	    To add support for a serial port, see the section on
 | |
|             kernel configuration.  To add support for a parallel port,
 | |
|             see that section <em/and/ the section that follows.
 | |
| 
 | |
| 	  <sect3><heading>Adding <tt>/dev</tt> Entries for the Ports
 | |
| 	      <label id="printing:dev-ports"></heading>
 | |
| 
 | |
| 	    <p> Even though the kernel may support communication along
 | |
| 	      a serial or parallel port, you will still need a software
 | |
| 	      interface through which programs running on the system
 | |
| 	      can send and receive data.  That is what entries in the
 | |
| 	      <tt>/dev</tt> directory are for.
 | |
| 
 | |
| 	      <bf>To add a <tt>/dev</tt> entry for a port:</bf>
 | |
| 	      <enum>
 | |
| 		<item>Become root with the 
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?su" 
 | |
| 		name="su"> command.  Enter
 | |
| 		  the root password when prompted.
 | |
| 
 | |
| 		<item>Change to the <tt>/dev</tt> directory:
 | |
| <tscreen><verb>
 | |
| cd /dev
 | |
| </verb></tscreen>
 | |
| 
 | |
| 		<item>Type
 | |
| <tscreen>
 | |
| <tt> ./MAKEDEV</tt> <it/port/
 | |
| </tscreen>
 | |
| 		  where <it/port/ is the device entry for the port you
 | |
| 		  want to make.  Use <tt/lpt0/ for the first parallel
 | |
| 		  port, <tt/lpt1/ for the second, and so on; use
 | |
| 		  <tt/ttyd0/ for the first serial port, <tt/ttyd1/ for
 | |
| 		  the second, and so on.
 | |
| 
 | |
| 		<item>Type
 | |
| <tscreen>
 | |
| <tt>ls -l</tt> <it/port/
 | |
| </tscreen>
 | |
| 		  to make sure the device entry got created.
 | |
| 	      </enum>
 | |
| 
 | |
| 	  <sect3><heading>Setting the Communication Mode for the Parallel Port
 | |
| 	      <label id="printing:parallel-port-mode"></heading>
 | |
| 
 | |
| 	    <p> When you are using the parallel interface, you can
 | |
| 	      choose whether FreeBSD should use interrupt-driven or
 | |
| 	      polled communication with the printer.
 | |
| 
 | |
| 	      <itemize>
 | |
| 		<item>The <em/interrupt-driven/ method is the default
 | |
| 		  with the GENERIC kernel.  With this method, the
 | |
| 		  operating system uses an IRQ line to determine when
 | |
| 		  the printer is ready for data.
 | |
| 
 | |
| 		<item>The <em/polled/ method directs the operating
 | |
| 		  system to repeatedly ask the printer if it is ready
 | |
| 		  for more data.  When it responds ready, the kernel
 | |
| 		  sends more data.
 | |
| 	      </itemize>
 | |
| 
 | |
| 	      The interrupt-driven method is somewhat faster but uses
 | |
| 	      up a precious IRQ line.  You should use whichever one
 | |
| 	      works.
 | |
| 
 | |
| 	      You can set the communications mode in two ways: by
 | |
| 	      configuring the kernel or by using the 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptcontrol"
 | |
| 	      name="lptcontrol">
 | |
| 
 | |
| 	      program.
 | |
| 
 | |
| 	      <bf>To set the communications mode by configuring the
 | |
| 		kernel:</bf>
 | |
| 	      <enum>
 | |
| 		<item>Edit your kernel configuration file.  Look for
 | |
| 		  or add an <tt/lpt0/ entry.  If you are setting up the
 | |
| 		  second parallel port, use <tt/lpt1/ instead.  Use
 | |
| 		  <tt/lpt2/ for the third port, and so on.
 | |
| 		  <itemize>
 | |
| 		    <item>If you want interrupt-driven mode, add the <tt/irq/
 | |
| 		      specifier:
 | |
| <tscreen>
 | |
| <tt>device lpt0 at isa? port? tty irq <it/N/ vector lptintr</tt>
 | |
| </tscreen>
 | |
| 		      where <it/N/ is the IRQ number for your
 | |
| 		      computer's parallel port.
 | |
| 
 | |
| 		    <item>If you want polled mode, do not add the
 | |
| 		      <tt/irq/ specifier:
 | |
| <tscreen>
 | |
| <tt>device lpt0 at isa? port? tty vector lptintr</tt>		
 | |
| </tscreen>
 | |
| 		  </itemize>
 | |
| 		<item>Save the file.  Then configure, build, and
 | |
| 		  install the kernel, then reboot.  See <ref id="kernelconfig"
 | |
| 		  name="kernel configuration"> for more details.
 | |
| 	      </enum>
 | |
| 
 | |
| 	      <bf>To set the communications mode with</bf>
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptcontrol"
 | |
| 		 name="lptcontrol">:
 | |
| 	      <itemize>
 | |
| 		<item>
 | |
| 		  Type
 | |
| <tscreen>
 | |
| <tt>lptcontrol -i -u <it/N/</tt>
 | |
| </tscreen>
 | |
| 		  to set interrupt-driven mode for <tt/lpt<it/N//.
 | |
| 
 | |
| 		<item>
 | |
| 		  Type
 | |
| <tscreen>
 | |
| <tt>lptcontrol -p -u <it/N/</tt>
 | |
| </tscreen>
 | |
| 		  to set polled-mode for <tt/lpt<it/N//.
 | |
| 	      </itemize>
 | |
| 	      You could put these commands in your
 | |
| 	      <tt>/etc/rc.local</tt> file to set the mode each time
 | |
| 	      your system boots.  See 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptcontrol(8)"
 | |
| 	      name="lptcontrol(8)"> for more information.
 | |
| 
 | |
| 	  <sect3><heading>Checking Printer Communications<label
 | |
| 		id="printing:testing"></heading>
 | |
| 
 | |
| 	    <p> Before proceeding to configure the spooling system,
 | |
| 	      you should make sure the operating system can
 | |
| 	      successfully send data to your printer.  It is a lot
 | |
| 	      easier to debug printer communication and the spooling
 | |
| 	      system separately.
 | |
| 
 | |
| 	      To test the printer, we will send some text to it.  For
 | |
| 	      printers that can immediately print characters sent to
 | |
| 	      them, the program 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 	      name="lptest"> is perfect: it generates
 | |
| 	      all 96 printable ASCII characters in 96 lines.
 | |
| 
 | |
| 	      For a PostScript (or other language-based) printer,
 | |
| 	      we will need a more sophisticated test.  A small
 | |
| 	      PostScript program, such as the following, will suffice:
 | |
| <code>
 | |
| %!PS
 | |
| 100 100 moveto 300 300 lineto stroke
 | |
| 310 310 moveto
 | |
| /Helvetica findfont 12 scalefont setfont
 | |
| (Is this thing working?) show
 | |
| showpage
 | |
| </code>
 | |
| 	      <em/Note:/ When this document refers to a printer
 | |
| 	      language, I am assuming a language like PostScript, and
 | |
| 	      not Hewlett Packard's PCL.  Although PCL has great
 | |
| 	      functionality, you can intermingle plain text with its
 | |
| 	      escape sequences.  PostScript cannot directly print
 | |
| 	      plain text, and that is the kind of printer language for
 | |
| 	      which we must make special accommodations.
 | |
| 
 | |
| 	    <sect4><heading>Checking a Parallel Printer<label
 | |
| 		  id="printing:checking:parallel"></heading>
 | |
| 
 | |
| 	      <p> This section tells you how to check if FreeBSD can
 | |
| 		communicate with a printer connected to a parallel port.
 | |
| 
 | |
| 		<bf>To test a printer on a parallel port:</bf>
 | |
| 		<enum>
 | |
| 		  <item>Become root with 
 | |
| 		  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?su"
 | |
| 		  name="su">.
 | |
| 		  <item>Send data to the printer.
 | |
| 		    <itemize>
 | |
| 		      <item>If the printer can print plain text, then
 | |
| 			use <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest" 
 | |
| 			name="lptest">. Type:
 | |
| <tscreen>
 | |
| <tt>lptest > /dev/lpt<it/N/</tt>
 | |
| </tscreen>
 | |
| 			where <it/N/ is the number of the parallel
 | |
| 			port, starting from zero.
 | |
| 
 | |
| 		      <item>If the printer understands PostScript or
 | |
| 			other printer language, then send a small
 | |
| 			program to the printer.  Type
 | |
| <tscreen>
 | |
| <tt>cat > /dev/lpt<it/N/</tt>
 | |
| </tscreen>
 | |
| 			Then, line by line, type the program
 | |
| 			<em/carefully/ as you cannot edit a line once
 | |
| 			you have pressed RETURN or ENTER. When you have
 | |
| 			finished entering the program, press
 | |
| 			CONTROL+D, or whatever your end of file key
 | |
| 			is.
 | |
| 
 | |
| 			<p> Alternatively, you can put the program in
 | |
| 			  a file and type
 | |
| <tscreen>
 | |
| <tt>cat <it/file/ > /dev/lpt<it/N/</tt>
 | |
| </tscreen>
 | |
| 			  where <it/file/ is the name of the file
 | |
| 			  containing the program you want to send to
 | |
| 			  the printer.
 | |
| 		    </itemize>
 | |
| 		</enum>
 | |
| 
 | |
| 		You should see something print.  Do not worry if the
 | |
| 		text does not look right; we will fix such things later.
 | |
| 
 | |
| 	    <sect4><heading>Checking a Serial Printer<label
 | |
| 		  id="printing:checking:serial"></heading>
 | |
| 
 | |
| 	      <p> This section tells you how to check if FreeBSD can
 | |
| 		communicate with a printer on a serial port.
 | |
| 
 | |
| 		<bf>To test a printer on a serial port:</bf>
 | |
| 		<enum>
 | |
| 		  <item>Become root with 
 | |
| 		  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?su"
 | |
| 		  name="su">.
 | |
| 
 | |
| 		  <item>Edit the file <tt>/etc/remote</tt>.  Add the
 | |
| 		    following entry:
 | |
| <tscreen>
 | |
| <tt>printer:dv=/dev/<it/port/:br#<it/bps-rate/:pa=<it/parity/</tt>
 | |
| </tscreen>
 | |
| 		    where <it/port/ is the device entry for the serial
 | |
| 		    port (<tt/ttyd0/, <tt/ttyd1/, etc.), <it/bps-rate/
 | |
| 		    is the bits-per-second rate at which the printer
 | |
| 		    communicates, and <it/parity/ is the parity
 | |
| 		    required by the printer (either <tt/even/,
 | |
| 		    <tt/odd/, <tt/none/, or <tt/zero/).
 | |
| 		    <p>
 | |
| 		      Here is a sample entry for a printer connected
 | |
| 		      via a serial line to the third serial port at
 | |
| 		      19200 bps with no parity:
 | |
| <code>
 | |
| printer:dv=/dev/ttyd2:br#19200:pa=none
 | |
| </code>
 | |
| 
 | |
| 		  <item>Connect to the printer with 
 | |
| 		  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?tip"
 | |
| 		  name="tip">.  Type:
 | |
| <tscreen><verb>
 | |
| tip printer
 | |
| </verb></tscreen>
 | |
| 		    If this step does not work, edit the file
 | |
| 		    <tt>/etc/remote</tt> again and try using
 | |
| 		    <tt>/dev/cuaa<it/N/</tt> instead of
 | |
| 		    <tt>/dev/ttyd<it/N/</tt>.
 | |
| 
 | |
| 		  <item>Send data to the printer.
 | |
| 		    <itemize>
 | |
| 		      <item>If the printer can print plain text, then
 | |
| 			use 
 | |
| 			<htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 			name="lptest">. Type:
 | |
| <tscreen><verb>
 | |
| ~$lptest
 | |
| </verb></tscreen>
 | |
| 
 | |
| 		      <item>If the printer understands PostScript or
 | |
| 			other printer language, then send a small
 | |
| 			program to the printer.  Type the program,
 | |
| 			line by line, <em/very carefully/ as
 | |
| 			backspacing or other editing keys may be
 | |
| 			significant to the printer. You may also need
 | |
| 			to type a special end-of-file key for the
 | |
| 			printer so it knows it received the whole
 | |
| 			program.  For PostScript printers, press
 | |
| 			CONTROL+D.
 | |
| 
 | |
| 			<p> Alternatively, you can put the program in
 | |
| 			  a file and type
 | |
| <tscreen>
 | |
| <tt>˜><it/file/</tt>
 | |
| </tscreen>
 | |
| 			  where <it/file/ is the name of the file
 | |
| 			  containing the program.  After 
 | |
| 			  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?tip"
 | |
| 			  name="tip"> sends the file, press any required
 | |
| 			  end-of-file key.
 | |
| 		    </itemize>
 | |
| 		</enum>
 | |
| 
 | |
| 		You should see something print.  Do not worry if the
 | |
| 		text does not look right; we will fix that later.
 | |
| 
 | |
| 	<sect2><heading>Enabling the Spooler: The <tt>/etc/printcap</tt> File
 | |
| 	    <label id="printing:printcap"></heading>
 | |
| 
 | |
| 	  <p> At this point, your printer should be hooked up, your
 | |
| 	    kernel configured to communicate with it (if necessary),
 | |
| 	    and you have been able to send some simple data to the
 | |
| 	    printer.  Now, we are ready to configure LPD to control
 | |
| 	    access to your printer.
 | |
| 
 | |
| 	    You configure LPD by editing the file
 | |
| 	    <tt>/etc/printcap</tt>.  The LPD spooling system reads
 | |
| 	    this file each time the spooler is used, so updates to the
 | |
| 	    file take immediate effect.
 | |
| 
 | |
| 	    The format of the 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?printcap"
 | |
| 	    name="printcap"> file is straightforward.
 | |
| 	    Use your favorite text editor to make changes to
 | |
| 	    <tt>/etc/printcap</tt>.  The format is identical to other
 | |
| 	    capability files like <tt>/usr/share/misc/termcap</tt> and
 | |
| 	    <tt>/etc/remote</tt>.  For complete information about the
 | |
| 	    format, see the 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?cgetent(3)"
 | |
| 	    name="cgetent(3)">.
 | |
| 
 | |
| 	    The simple spooler configuration consists of the following steps:
 | |
| 	    <enum>
 | |
| 	      <item>Pick a name (and a few convenient aliases) for
 | |
| 		the printer, and put them in the
 | |
| 		<tt>/etc/printcap</tt> file; see <ref
 | |
| 		id="printing:naming" name="Naming the Printer">.
 | |
| 
 | |
| 	      <item>Turn off header pages (which are on by default)
 | |
| 		by inserting the <tt/sh/ capability; see <ref
 | |
| 		id="printing:no-header-pages" name="Suppressing Header
 | |
| 		Pages">.
 | |
| 
 | |
| 	      <item>Make a spooling directory, and specify its
 | |
| 		location with the <tt/sd/ capability; see <ref
 | |
| 		id="printing:spooldir" name="Making the Spooling
 | |
| 		Directory">.
 | |
| 
 | |
| 	      <item>Set the <tt>/dev</tt> entry to use for the
 | |
| 		printer, and note it in <tt>/etc/printcap</tt> with
 | |
| 		the <tt/lp/ capability; see <ref id="printing:device"
 | |
| 		name="Identifying the Printer Device">.  Also, if the
 | |
| 		printer is on a serial port, set up the communication
 | |
| 		parameters with the <tt/fs/, <tt/fc/, <tt/xs/, and
 | |
| 		<tt/xc/ capabilities; see <ref id="printing:commparam"
 | |
| 		name="Configuring Spooler Communications Parameters">.
 | |
| 
 | |
| 	      <item>Install a plain text input filter; see <ref
 | |
| 		  id="printing:textfilter" name="Installing the Text
 | |
| 		  Filter">
 | |
| 
 | |
| 	      <item>Test the setup by printing something with the
 | |
| 		
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 		name="lpr"> command; see <ref id="printing:trying"
 | |
| 		name="Trying It Out"> and <ref
 | |
| 		id="printing:troubleshooting" name="Troubleshooting">.
 | |
| 	    </enum>
 | |
| 
 | |
| 	    <em/Note:/ Language-based printers, such as PostScript
 | |
| 	    printers, cannot directly print plain text.  The simple
 | |
| 	    setup outlined above and described in the following
 | |
| 	    sections assumes that if you are installing such a printer
 | |
| 	    you will print only files that the printer can understand.
 | |
| 
 | |
| 	    Users often expect that they can print plain text to any
 | |
| 	    of the printers installed on your system.  Programs that
 | |
| 	    interface to LPD to do their printing usually make the
 | |
| 	    same assumption.  If you are installing such a printer and
 | |
| 	    want to be able to print jobs in the printer language
 | |
| 	    <em/and/ print plain text jobs, you are strongly urged to
 | |
| 	    add an additional step to the simple setup outlined above:
 | |
| 	    install an automatic plain-text--to--PostScript (or other
 | |
| 	    printer language) conversion program.  Section <ref
 | |
| 	    id="printing:advanced:if-conversion" name="Accommodating
 | |
| 	    Plain Text Jobs on PostScript Printers"> tells how to do
 | |
| 	    this.
 | |
| 
 | |
| 	  <sect3><heading>Naming the Printer<label
 | |
| 		id="printing:naming"></heading>
 | |
| 
 | |
| 	    <p> The first (easy) step is to pick a name for your
 | |
| 	      printer.  It really does not matter whether you choose
 | |
| 	      functional or whimsical names since you can also provide
 | |
| 	      a number aliases for the printer.
 | |
| 
 | |
| 	      At least one of the printers specified in the
 | |
| 	      <tt>/etc/printcap</tt> should have the alias
 | |
| 	      <tt/lp/. This is the default printer's name.  If users
 | |
| 	      do not have the PRINTER environment variable nor
 | |
| 	      specify a printer name on the command line of any of the
 | |
| 	      LPD commands, then <tt/lp/ will be the default printer
 | |
| 	      they get to use.
 | |
| 
 | |
| 	      Also, it is common practice to make the last alias for a
 | |
| 	      printer be a full description of the printer, including
 | |
| 	      make and model.
 | |
| 
 | |
| 	      Once you have picked a name and some common aliases, put
 | |
| 	      them in the <tt>/etc/printcap</tt> file.  The name of
 | |
| 	      the printer should start in the leftmost column.
 | |
| 	      Separate each alias with a vertical bar and put a colon
 | |
| 	      after the last alias.
 | |
| 
 | |
| 	      In the following example, we start with a skeletal
 | |
| 	      <tt>/etc/printcap</tt> that defines two printers (a
 | |
| 	      Diablo 630 line printer and a Panasonic KX-P4455
 | |
| 	      PostScript laser printer):
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:
 | |
| </code>
 | |
| 	      In this example, the first printer is named <tt/rattan/
 | |
| 	      and has as aliases <tt/line/, <tt/diablo/, <tt/lp/, and
 | |
| 	      <tt/Diablo 630 Line Printer/.  Since it has the alias
 | |
| 	      <tt/lp/, it is also the default printer.  The second is
 | |
| 	      named <tt/bamboo/, and has as aliases <tt/ps/, <tt/PS/,
 | |
| 	      <tt/S/, <tt/panasonic/, and <tt/Panasonic KX-P4455
 | |
| 	      PostScript v51.4/.
 | |
| 
 | |
| 	  <sect3><heading>Suppressing Header Pages<label
 | |
| 		id="printing:no-header-pages"></heading>
 | |
| 
 | |
| 	    <p> The LPD spooling system will by default print a
 | |
| 	      <em/header page/ for each job.  The header page contains
 | |
| 	      the user name who requested the job, the host from which
 | |
| 	      the job came, and the name of the job, in nice large
 | |
| 	      letters.  Unfortunately, all this extra text gets in the
 | |
| 	      way of debugging the simple printer setup, so we will
 | |
| 	      suppress header pages.
 | |
| 
 | |
| 	      To suppress header pages, add the <tt/sh/ capability to
 | |
| 	      the entry for the printer in
 | |
| 	      <tt>/etc/printcap</tt>. Here is the example
 | |
| 	      <tt>/etc/printcap</tt> with <tt/sh/ added:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - no header pages anywhere
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:
 | |
| </code>
 | |
| 	      Note how we used the correct format: the first line
 | |
| 	      starts in the leftmost column, and subsequent lines are
 | |
| 	      indented with a single TAB.  Every line in an entry
 | |
| 	      except the last ends in a backslash character.
 | |
| 
 | |
| 	  <sect3><heading>Making the Spooling Directory<label
 | |
| 		id="printing:spooldir"></heading>
 | |
| 
 | |
| 	    <p> The next step in the simple spooler setup is to make a
 | |
| 	      <em/spooling directory/, a directory where print jobs
 | |
| 	      reside until they are printed, and where a number of
 | |
| 	      other spooler support files live.
 | |
| 
 | |
| 	      Because of the variable nature of spooling directories,
 | |
| 	      it is customary to put these directories under
 | |
| 	      <tt>/var/spool</tt>.  It is not necessary to backup the
 | |
| 	      contents of spooling directories, either.  Recreating
 | |
| 	      them is as simple as running 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?mkdir"
 | |
| 	      name="mkdir">.
 | |
| 
 | |
| 	      It is also customary to make the directory with a name
 | |
| 	      that is identical to the name of the printer, as shown
 | |
| 	      below:
 | |
| <tscreen>
 | |
| <tt>mkdir /var/spool/<it>printer-name</it></tt>
 | |
| </tscreen>
 | |
| 	      However, if you have a lot of printers on your network,
 | |
| 	      you might want to put the spooling directories under a
 | |
| 	      single directory that you reserve just for printing with
 | |
| 	      LPD.  We will do this for our two example printers
 | |
| 	      <tt/rattan/ and <tt/bamboo/:
 | |
| <tscreen><verb>
 | |
| mkdir /var/spool/lpd
 | |
| mkdir /var/spool/lpd/rattan
 | |
| mkdir /var/spool/lpd/bamboo
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      <em/Note:/ If you are concerned about the privacy of jobs
 | |
| 	      that users print, you might want to protect the spooling
 | |
| 	      directory so it is not publicly accessible.  Spooling
 | |
| 	      directories should be owned and be readable, writable,
 | |
| 	      and searchable by user daemon and group daemon, and no
 | |
| 	      one else.  We will do this for our example printers:
 | |
| 
 | |
| <tscreen><verb>
 | |
| chown daemon.daemon /var/spool/lpd/rattan
 | |
| chown daemon.daemon /var/spool/lpd/bamboo
 | |
| chmod 770 /var/spool/lpd/rattan
 | |
| chmod 770 /var/spool/lpd/bamboo
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      Finally, you need to tell LPD about these directories
 | |
| 	      using the <tt>/etc/printcap</tt> file.  You specify the
 | |
| 	      pathname of the spooling directory with the <tt/sd/
 | |
| 	      capability:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - added spooling directories
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:
 | |
| </code>
 | |
| 	      Note that the name of the printer starts in the first
 | |
| 	      column but all other entries describing the printer
 | |
| 	      should be indented with a tab and each line escaped with
 | |
| 	      a backslash.
 | |
| 
 | |
| 	      If you do not specify a spooling directory with <tt/sd/,
 | |
| 	      the spooling system will use <tt>/var/spool/lpd</tt> as
 | |
| 	      a default.
 | |
| 
 | |
| 	  <sect3><heading>Identifying the Printer Device<label
 | |
| 		id="printing:device"></heading>
 | |
| 
 | |
| 	    <p> In section <ref id="printing:dev-ports" name="Adding
 | |
| 		/dev Entries for the Ports">, we identified which
 | |
| 	      entry in the <tt>/dev</tt> directory FreeBSD will use
 | |
| 	      to communicate with the printer.  Now, we tell LPD
 | |
| 	      that information.  When the spooling system has a job
 | |
| 	      to print, it will open the specified device on behalf
 | |
| 	      of the filter program (which is responsible for
 | |
| 	      passing data to the printer).
 | |
| 
 | |
| 	      List the <tt>/dev</tt> entry pathname in the
 | |
| 	      <tt>/etc/printcap</tt> file using the <tt/lp/
 | |
| 	      capability.
 | |
| 
 | |
| 	      In our running example, let us assume that <tt/rattan/ is
 | |
| 	      on the first parallel port, and <tt/bamboo/ is on a
 | |
| 	      sixth serial port; here are the additions to
 | |
| 	      <tt>/etc/printcap</tt>:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - identified what devices to use
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:\
 | |
| 	:lp=/dev/ttyd5:
 | |
| </code>
 | |
| 
 | |
| 	      If you do not specify the <tt/lp/ capability for a
 | |
| 	      printer in your <tt>/etc/printcap</tt> file, LPD uses
 | |
| 	      <tt>/dev/lp</tt> as a default.  <tt>/dev/lp</tt>
 | |
| 	      currently does not exist in FreeBSD.
 | |
| 
 | |
| 	      If the printer you are installing is connected to a
 | |
| 	      parallel port, skip to the section <ref name="Installing
 | |
| 	      the Text Filter" id="printing:textfilter">.  Otherwise,
 | |
| 	      be sure to follow the instructions in the next section.
 | |
| 
 | |
| 	  <sect3><heading>Configuring Spooler Communication
 | |
| 	      Parameters<label id="printing:commparam"></heading>
 | |
| 
 | |
| 	    <p> For printers on serial ports, LPD can set up the bps
 | |
| 	      rate, parity, and other serial communication parameters
 | |
| 	      on behalf of the filter program that sends data to the
 | |
| 	      printer.  This is advantageous since
 | |
| 	      <itemize>
 | |
| 		<item>It lets you try different communication
 | |
| 		  parameters by simply editing the
 | |
| 		  <tt>/etc/printcap</tt> file; you do not have to
 | |
| 		  recompile the filter program.
 | |
| 
 | |
| 		<item>It enables the spooling system to use the same
 | |
| 		  filter program for multiple printers which may have
 | |
| 		  different serial communication settings.
 | |
| 	      </itemize>
 | |
| 
 | |
| 	      The following <tt>/etc/printcap</tt> capabilities
 | |
| 	      control serial communication parameters of the device
 | |
| 	      listed in the <tt/lp/ capability:
 | |
| 	      <descrip>
 | |
| 		<tag/<tt>br#<it/bps-rate/</tt>/
 | |
| 
 | |
| 		  Sets the communications speed of the device to
 | |
| 		  <it/bps-rate/, where <it/bps-rate/ can be 50, 75,
 | |
| 		  110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
 | |
| 		  4800, 9600, 19200, or 38400 bits-per-second.
 | |
| 
 | |
| 		<tag/<tt>fc#<it/clear-bits/</tt>/
 | |
| 
 | |
| 		  Clears the flag bits <it/clear-bits/ in the
 | |
| 		  <tt/sgttyb/ structure after opening the device.
 | |
| 
 | |
| 		<tag/<tt>fs#<it/set-bits/</tt>/
 | |
| 
 | |
| 		  Sets the flag bits <it/set-bits/ in the <tt/sgttyb/
 | |
| 		  structure.
 | |
| 
 | |
| 		<tag/<tt>xc#<it/clear-bits/</tt>/
 | |
| 
 | |
| 		  Clears local mode bits <it/clear-bits/ after opening
 | |
| 		  the device.
 | |
| 
 | |
| 		<tag/<tt>xs#<it/set-bits/</tt>/
 | |
| 
 | |
| 		  Sets local mode bits <it/set-bits/.
 | |
| 	      </descrip>
 | |
| 	      For more information on the bits for the <tt/fc/,
 | |
| 	      <tt/fs/, <tt/xc/, and <tt/xs/ capabilities, see the file
 | |
| 	      <tt>/usr/include/sys/ioctl_compat.h</tt>.
 | |
| 
 | |
| 	      When LPD opens the device specified by the <tt/lp/
 | |
| 	      capability, it reads the flag bits in the <tt/sgttyb/
 | |
| 	      structure; it clears any bits in the <tt/fc/ capability,
 | |
| 	      then sets bits in the <tt/fs/ capability, then applies
 | |
| 	      the resultant setting.  It does the same for the local
 | |
| 	      mode bits as well.
 | |
| 
 | |
| 	      Let us add to our example printer on the sixth serial
 | |
| 	      port.  We will set the bps rate to 38400. For the flag
 | |
| 	      bits, we will set the TANDEM, ANYP, LITOUT, FLUSHO, and
 | |
| 	      PASS8 flags.  For the local mode bits, we will set the
 | |
| 	      LITOUT and PASS8 flags:
 | |
| <tscreen><verb>
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000c1:xs#0x820:
 | |
| </verb></tscreen>
 | |
| 
 | |
| 
 | |
| 	  <sect3><heading>Installing the Text Filter<label
 | |
| 		id="printing:textfilter"></heading>
 | |
| 
 | |
| 	    <p> We are now ready to tell LPD what text filter to use to
 | |
| 	      send jobs to the printer.  A <em/text filter/, also
 | |
| 	      known as an <em/input filter/, is a program that LPD
 | |
| 	      runs when it has a job to print.  When LPD runs the text
 | |
| 	      filter for a printer, it sets the filter's standard
 | |
| 	      input to the job to print, and its standard output to
 | |
| 	      the printer device specified with the <tt/lp/
 | |
| 	      capability.  The filter is expected to read the job from
 | |
| 	      standard input, perform any necessary translation for the
 | |
| 	      printer, and write the results to standard output, which
 | |
| 	      will get printed.  For more information on the text
 | |
| 	      filter, see section <ref id="printing:advanced:filters"
 | |
| 	      name="Filters">.
 | |
| 
 | |
| 	      For our simple printer setup, the text filter can be a
 | |
| 	      small shell script that just executes <tt>/bin/cat</tt>
 | |
| 	      to send the job to the printer.  FreeBSD comes with
 | |
| 	      another filter called <tt/lpf/ that handles backspacing
 | |
| 	      and underlining for printers that might not deal with
 | |
| 	      such character streams well.  And, of course, you can
 | |
| 	      use any other filter program you want.  The filter
 | |
| 	      <tt/lpf/ is described in detail in section <ref
 | |
| 	      id="printing:advanced:lpf" name="lpf: a Text Filter">.
 | |
| 
 | |
| 	      First, let us make the shell script
 | |
| 	      <tt>/usr/local/libexec/if-simple</tt> be a simple text
 | |
| 	      filter. Put the following text into that file with your
 | |
| 	      favorite text editor:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| # if-simple - Simple text input filter for lpd
 | |
| # Installed in /usr/local/libexec/if-simple
 | |
| #
 | |
| # Simply copies stdin to stdout.  Ignores all filter arguments.
 | |
| 
 | |
| /bin/cat && exit 0
 | |
| exit 2
 | |
| </code>
 | |
| 	      Make the file executable:
 | |
| <tscreen><verb>
 | |
| chmod 555 /usr/local/libexec/if-simple
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      And then tell LPD to use it by specifying it with the
 | |
| 	      <tt/if/ capability in <tt>/etc/printcap</tt>.  We will add
 | |
| 	      it to the two printers we have so far in the example
 | |
| 	      <tt>/etc/printcap</tt>:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - added text filter
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:\
 | |
| 	:if=/usr/local/libexec/if-simple:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:\
 | |
| 	:if=/usr/local/libexec/if-simple:
 | |
| </code>
 | |
| 
 | |
| 	  <sect3><heading>Trying It Out<label id="printing:trying"></heading>
 | |
| 
 | |
| 	    <p> You have reached the end of the simple LPD setup.
 | |
| 	      Unfortunately, congratulations are not quite yet in
 | |
| 	      order, since we still have to test the setup and
 | |
| 	      correct any problems.  To test the setup, try printing
 | |
| 	      something.  To print with the LPD system, you use the
 | |
| 	      command 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	      name="lpr">, which submits a job for printing.
 | |
| 
 | |
| 	      You can combine 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	      name="lpr"> with the 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 	      name="lptest"> program,
 | |
| 	      introduced in section <ref id="printing:testing"
 | |
| 	      name="Checking Printer Communications"> to generate some
 | |
| 	      test text.
 | |
| 
 | |
| 	      <bf>To test the simple LPD setup:</bf>
 | |
| 
 | |
| 	    <p> Type:
 | |
| <tscreen>
 | |
| <tt>lptest 20 5 | lpr -P<it/printer-name/</tt>
 | |
| </tscreen>
 | |
| 	      where <it/printer-name/ is a the name of a printer (or
 | |
| 	      an alias) specified in <tt>/etc/printcap</tt>.  To test
 | |
| 	      the default printer, type 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	      name="lpr"> without any <tt/-P/
 | |
| 	      argument.  Again, if you are testing a printer that
 | |
| 	      expects PostScript, send a PostScript program in that
 | |
| 	      language instead of using 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 	      name="lptest">.  You can do so by
 | |
| 	      putting the program in a file and typing <tt/lpr
 | |
| 	      <it/file//.
 | |
| 
 | |
| 	      For a PostScript printer, you should get the results
 | |
| 	      of the program.  If you are using 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 	      name="lptest">, then your
 | |
| 	      results should look like the following:
 | |
| 
 | |
| <tscreen><verb>
 | |
| !"#$%&'()*+,-./01234
 | |
| "#$%&'()*+,-./012345
 | |
| #$%&'()*+,-./0123456
 | |
| $%&'()*+,-./01234567
 | |
| %&'()*+,-./012345678
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      To further test the printer, try downloading larger
 | |
| 	      programs (for language-based printers) or running
 | |
| 	      
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 	      name="lptest"> with different arguments.  For example,
 | |
| 	      <tt/lptest 80 60/ will produce 60 lines of 80 characters
 | |
| 	      each.
 | |
| 
 | |
| 	      If the printer did not work, see the next section, <ref
 | |
| 		id="printing:troubleshooting" name="Troubleshooting">.
 | |
| 
 | |
| 	  <sect3><heading>Troubleshooting<label
 | |
| 		id="printing:troubleshooting"></heading>
 | |
| 
 | |
| 	    <p> After performing the simple test with 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lptest"
 | |
| 	    name="lptest">, you
 | |
| 	      might have gotten one of the following results instead of
 | |
| 	      the correct printout:
 | |
| 	      <descrip>
 | |
| 		<tag/It worked, after awhile; or, it did not eject a full sheet./
 | |
| 
 | |
| 		  The printer printed the above, but it sat for awhile
 | |
| 		  and did nothing.  In fact, you might have needed to
 | |
| 		  press a PRINT REMAINING or FORM FEED button on the
 | |
| 		  printer to get any results to appear.
 | |
| 
 | |
| 		  If this is the case, the printer was probably
 | |
| 		  waiting to see if there was any more data for your
 | |
| 		  job before it printed anything.  To fix this
 | |
| 		  problem, you can have the text filter send a FORM
 | |
| 		  FEED character (or whatever is necessary) to the
 | |
| 		  printer.  This is usually sufficient to have the
 | |
| 		  printer immediately print any text remaining in its
 | |
| 		  internal buffer.  It is also useful to make sure each
 | |
| 		  print job ends on a full sheet, so the next job
 | |
| 		  does not start somewhere on the middle of the last
 | |
| 		  page of the previous job.
 | |
| 
 | |
| 		  The following replacement for the shell script
 | |
| 		  <tt>/usr/local/libexec/if-simple</tt> prints a form
 | |
| 		  feed after it sends the job to the printer:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| # if-simple - Simple text input filter for lpd
 | |
| # Installed in /usr/local/libexec/if-simple
 | |
| #
 | |
| # Simply copies stdin to stdout.  Ignores all filter arguments.
 | |
| # Writes a form feed character (\f) after printing job.
 | |
| 
 | |
| /bin/cat && printf "\f" && exit 0
 | |
| exit 2
 | |
| </code>
 | |
| 
 | |
| 		<tag/It produced the ``staircase effect.''/
 | |
| 
 | |
| 		  You got the following on paper:
 | |
| <tscreen><verb>
 | |
| !"#$%&'()*+,-./01234
 | |
|                         "#$%&'()*+,-./012345
 | |
|                                                 #$%&'()*+,-./0123456
 | |
| </verb></tscreen>
 | |
| 		  You have become another victim of the <em/staircase
 | |
| 		  effect/, caused by conflicting interpretations of
 | |
| 		  what characters should indicate a new-line.
 | |
| 		  UNIX-style operating systems use a single character:
 | |
| 		  ASCII code 10, the line feed (LF).  MS-DOS, OS/2,
 | |
| 		  and others uses a pair of characters, ASCII code 10
 | |
| 		  <em/and/ ASCII code 13 (the carriage return or CR).
 | |
| 		  Many printers use the MS-DOS convention for
 | |
| 		  representing new-lines.
 | |
| 
 | |
| 		  When you print with FreeBSD, your text used just the
 | |
| 		  line feed character.  The printer, upon seeing a
 | |
| 		  line feed character, advanced the paper one line,
 | |
| 		  but maintained the same horizontal position on the
 | |
| 		  page for the next character to print.  That is what
 | |
| 		  the carriage return is for: to move the location of
 | |
| 		  the next character to print to the left edge of the
 | |
| 		  paper.
 | |
| 
 | |
| 		  Here is what FreeBSD wants your printer to do:
 | |
| <tscreen><verb>
 | |
| Printer received CR		Printer prints CR
 | |
| Printer received LF		Printer prints CR + LF
 | |
| </verb></tscreen>
 | |
| 		  
 | |
| 		  Here are some ways to achieve this:
 | |
| 		  <itemize>
 | |
| 		    <item>Use the printer's configuration switches or
 | |
| 		      control panel to alter its interpretation of
 | |
| 		      these characters.  Check your printer's manual
 | |
| 		      to find out how to do this.
 | |
| 
 | |
| 		      <p> <em/Note:/ If you boot your system into
 | |
| 			other operating systems besides FreeBSD, you
 | |
| 			may have to <em/reconfigure/ the printer to
 | |
| 			use a an interpretation for CR and LF
 | |
| 			characters that those other operating systems
 | |
| 			use.  You might prefer one of the other
 | |
| 			solutions, below.
 | |
| 
 | |
| 		    <item>Have FreeBSD's serial line driver
 | |
| 		      automatically convert LF to CR+LF. Of course,
 | |
| 		      this works with printers on serial ports
 | |
| 		      <em/only/.  To enable this feature, set the
 | |
| 		      CRMOD bit in <tt/fs/ capability in the
 | |
| 		      <tt>/etc/printcap</tt> file for the printer.
 | |
| 
 | |
| 		    <item>Send an <em/escape code/ to the printer to
 | |
| 		      have it temporarily treat LF characters
 | |
| 		      differently.  Consult your printer's manual for
 | |
| 		      escape codes that your printer might support.
 | |
| 		      When you find the proper escape code, modify the
 | |
| 		      text filter to send the code first, then send
 | |
| 		      the print job.
 | |
| 
 | |
| 		      <p> Here is an example text filter for printers
 | |
| 			that understand the Hewlett-Packard PCL escape
 | |
| 			codes.  This filter makes the printer treat LF
 | |
| 			characters as a LF and CR; then it sends the
 | |
| 			job; then it sends a form feed to eject the
 | |
| 			last page of the job.  It should work with
 | |
| 			nearly all Hewlett Packard printers.
 | |
| 
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| # hpif - Simple text input filter for lpd for HP-PCL based printers
 | |
| # Installed in /usr/local/libexec/hpif
 | |
| #
 | |
| # Simply copies stdin to stdout.  Ignores all filter arguments.
 | |
| # Tells printer to treat LF as CR+LF. Writes a form feed character
 | |
| # after printing job.
 | |
| 
 | |
| printf "\033&k2G" && cat && printf "\f" && exit 0
 | |
| exit 2
 | |
| </code>
 | |
| 
 | |
| 			Here is an example <tt>/etc/printcap</tt> from
 | |
| 			a host called orchid.  It has a single printer
 | |
| 			attached to its first parallel port, a Hewlett
 | |
| 			Packard LaserJet 3Si named <tt/teak/.  It is
 | |
| 			using the above script as its text filter:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host orchid
 | |
| #
 | |
| teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
 | |
| 	:lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\
 | |
| 	:if=/usr/local/libexec/hpif:
 | |
| </code>
 | |
| 		  </itemize>
 | |
| 
 | |
| 		<tag/It overprinted each line./
 | |
| 
 | |
| 		  The printer never advanced a line.  All of the lines
 | |
| 		  of text were printed on top of each other on one
 | |
| 		  line.
 | |
| 
 | |
| 		  This problem is the ``opposite'' of the staircase
 | |
| 		  effect, described above, and is much rarer.
 | |
| 		  Somewhere, the LF characters that FreeBSD uses to
 | |
| 		  end a line are being treated as CR characters to
 | |
| 		  return the print location to the left edge of the
 | |
| 		  paper, but not also down a line.
 | |
| 
 | |
| 		  Use the printer's configuration switches or control
 | |
| 		  panel to enforce the following interpretation of LF
 | |
| 		  and CR characters:
 | |
| <tscreen><verb>
 | |
| Printer received CR		Printer prints CR
 | |
| Printer received LF		Printer prints CR + LF
 | |
| </verb></tscreen>
 | |
| 
 | |
| 		<tag/The printer lost characters./
 | |
| 
 | |
| 		  While printing, the printer did not print a few
 | |
| 		  characters in each line.  The problem might have
 | |
| 		  gotten worse as the printer ran, losing more and
 | |
| 		  more characters.
 | |
| 
 | |
| 		  The problem is that the printer cannot keep up with
 | |
| 		  the speed at which the computer sends data over a
 | |
| 		  serial line.  (This problem should not occur with
 | |
| 		  printers on parallel ports.)  There are two ways to
 | |
| 		  overcome the problem:
 | |
| 		  <itemize>
 | |
| 		    <item>If the printer supports XON/XOFF flow
 | |
| 		      control, have FreeBSD use it by specifying the
 | |
| 		      TANDEM bit in the <tt/fs/ capability.
 | |
| 
 | |
| 		    <item>If the printer supports carrier flow
 | |
| 		      control, specify the MDMBUF bit in the <tt/fs/
 | |
| 		      capability.  Make sure the cable connecting the
 | |
| 		      printer to the computer is correctly wired for
 | |
| 		      carrier flow control.
 | |
| 
 | |
| 		    <item>If the printer does not support any flow
 | |
| 		      control, use some combination of the NLDELAY,
 | |
| 		      TBDELAY, CRDELAY, VTDELAY, and BSDELAY bits in
 | |
| 		      the <tt/fs/ capability to add appropriate delays
 | |
| 		      to the stream of data sent to the printer.
 | |
| 		  </itemize>
 | |
| 
 | |
| 		<tag/It printed garbage./
 | |
| 
 | |
| 		  The printer printed what appeared to be random
 | |
| 		  garbage, but not the desired text.
 | |
| 
 | |
| 		  This is usually another symptom of incorrect
 | |
| 		  communications parameters with a serial printer.
 | |
| 		  Double-check the bps rate in the <tt/br/ capability,
 | |
| 		  and the parity bits in the <tt/fs/ and <tt/fc/
 | |
| 		  capabilities; make sure the printer is using the
 | |
| 		  same settings as specified in the
 | |
| 		  <tt>/etc/printcap</tt> file.
 | |
| 
 | |
| 		<tag/Nothing happened./
 | |
| 
 | |
| 		  If nothing happened, the problem is probably within
 | |
| 		  FreeBSD and not the hardware.  Add the log file
 | |
| 		  (<tt/lf/) capability to the entry for the printer
 | |
| 		  you are debugging in the <tt>/etc/printcap</tt> file.
 | |
| 		  For example, here is the entry for <tt/rattan/, with
 | |
| 		  the <tt/lf/ capability:
 | |
| <tscreen><verb>
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:\
 | |
| 	:if=/usr/local/libexec/if-simple:\
 | |
| 	:lf=/var/log/rattan.log
 | |
| </verb></tscreen>
 | |
| 		  Then, try printing again.  Check the log file (in
 | |
| 		  our example, <tt>/var/log/rattan.log</tt>) to see
 | |
| 		  any error messages that might appear.  Based on the
 | |
| 		  messages you see, try to correct the problem.
 | |
| 
 | |
| 		  If you do not specify a <tt/lf/ capability, LPD uses
 | |
| 		  <tt>/dev/console</tt> as a default.
 | |
| 	      </descrip>
 | |
| 
 | |
|     <sect><heading>Using Printers<label id="printing:using"></heading>
 | |
| 
 | |
|       <p> This section tells you how to use printers you have setup with
 | |
| 	FreeBSD.  Here is an overview of the user-level commands:
 | |
| 	<descrip>
 | |
| 	  <tag><htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	  name="lpr"></tag> Print jobs
 | |
| 
 | |
| 	  <tag><htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq"></tag> Check printer queues
 | |
| 
 | |
| 	  <tag><htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	   name="lprm"></tag> Remove jobs from a printer's queue
 | |
| 
 | |
| 	</descrip>
 | |
| 
 | |
| 	There is also an administrative command, 
 | |
| 	<htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	name="lpc">, described in
 | |
| 	the section <ref id="printing:lpc" name="Administrating the
 | |
| 	LPD Spooler">, used to control printers and their queues.
 | |
| 
 | |
| 	All three of the commands 
 | |
| 	<htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	 name="lpr">, 
 | |
| 	 <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	  name="lprm">, and 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq">
 | |
| 	accept an option ``<tt/-P/ <it/printer-name/'' to specify on
 | |
| 	which printer/queue to operate, as listed in the
 | |
| 	<tt>/etc/printcap</tt> file.  This enables you to submit,
 | |
| 	remove, and check on jobs for various printers.  If you do not
 | |
| 	use the <tt/-P/ option, then these commands use the printer
 | |
| 	specified in the PRINTER environment variable.  Finally, if
 | |
| 	you do not have a PRINTER environment variable, these commands
 | |
| 	default to the printer named <tt/lp/.
 | |
| 
 | |
| 	Hereafter, the terminology <em/default printer/ means the
 | |
| 	printer named in the PRINTER environment variable, or the
 | |
| 	printer named <tt/lp/ when there is no PRINTER environment
 | |
| 	variable.
 | |
| 
 | |
|       <sect1><heading>Printing Jobs<label id="printing:lpr"></heading>
 | |
| 	<p>
 | |
| 
 | |
| 	  To print files, type
 | |
| <tscreen>
 | |
| <tt>lpr <it/filename.../</tt>
 | |
| </tscreen>
 | |
| 	  This prints each of the listed files to the default printer.
 | |
| 	  If you list no files, 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	  name="lpr"> reads data to print from
 | |
| 	  standard input.  For example, this command prints some
 | |
| 	  important system files:
 | |
| <tscreen><verb>
 | |
| lpr /etc/host.conf /etc/hosts.equiv
 | |
| </verb></tscreen>
 | |
| 	  To select a specific printer, type
 | |
| <tscreen>
 | |
| <tt>lpr -P <it/printer-name/ <it/filename.../</tt>
 | |
| </tscreen>
 | |
| 	  This example prints a long listing of the current directory
 | |
| 	  to the printer named <tt/rattan/:
 | |
| <tscreen><verb>
 | |
| ls -l | lpr -P rattan
 | |
| </verb></tscreen>
 | |
| 	  Because no files were listed for the 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> command,
 | |
| 	  <tt/lpr/ read the data to print from standard input, which
 | |
| 	  was the output of the <tt/ls -l/ command.
 | |
| 
 | |
| 	  The <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> command can also accept a wide variety of
 | |
| 	  options to control formatting, apply file conversions,
 | |
| 	  generate multiple copies, and so forth.  For more
 | |
| 	  information, see the section <ref id="printing:lpr:options"
 | |
| 	  name="Printing Options">.
 | |
| 
 | |
|       <sect1><heading>Checking Jobs<label id="printing:lpq"></heading>
 | |
| 
 | |
| 	<p> When you print with 
 | |
| 	<htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	 name="lpr">, the data you wish to print
 | |
| 	  is put together in a package called a <em/print job/, which
 | |
| 	  is sent to the LPD spooling system.  Each printer has a
 | |
| 	  queue of jobs, and your job waits in that queue along with
 | |
| 	  other jobs from yourself and from other users. The printer
 | |
| 	  prints those jobs in a first-come, first-served order.
 | |
| 
 | |
| 	  To display the queue for the default printer, type 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq">.
 | |
| 	  For a specific printer, use the <tt/-P/ option.  For
 | |
| 	  example, the command
 | |
| <tscreen><verb>
 | |
| lpq -P bamboo
 | |
| </verb></tscreen>
 | |
| 	  shows the queue for the printer named <tt/bamboo/.  Here is
 | |
| 	  an example of the output of the <tt/lpq/ command:
 | |
| <tscreen><verb>
 | |
| bamboo is ready and printing
 | |
| Rank  Owner	Job  Files				Total Size
 | |
| active kelly    9    /etc/host.conf, /etc/hosts.equiv   88 bytes
 | |
| 2nd    kelly    10   (standard input)                   1635 bytes
 | |
| 3rd    mary     11   ...                                78519 bytes
 | |
| </verb></tscreen>
 | |
| 	  This shows three jobs in the queue for <tt/bamboo/.  The
 | |
| 	  first job, submitted by user kelly, got assigned <em/job
 | |
| 	  number/ 9.  Every job for a printer gets a unique job
 | |
| 	  number.  Most of the time you can ignore the job number, but
 | |
| 	  you will need it if you want to cancel the job; see section
 | |
| 	  <ref id="printing:lprm" name="Removing Jobs"> for details.
 | |
| 
 | |
| 	  Job number nine consists of two files; multiple files given
 | |
| 	  on the 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> command line are treated as part of a single
 | |
| 	  job.  It is the currently active job (note the word
 | |
| 	  <tt/active/ under the ``Rank'' column), which means the
 | |
| 	  printer should be currently printing that job.  The second
 | |
| 	  job consists of data passed as the standard input to the
 | |
| 	  
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> command. The third job came from user mary; it is a
 | |
| 	  much larger job.  The pathname of the files she's trying to
 | |
| 	  print is too long to fit, so the 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq"> command just shows
 | |
| 	  three dots.
 | |
| 
 | |
| 	  The very first line of the output from 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq"> is also
 | |
| 	  useful: it tells what the printer is currently doing (or at
 | |
| 	  least what LPD thinks the printer is doing).
 | |
| 
 | |
| 	  The 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq"> command also support a <tt/-l/ option to
 | |
| 	  generate a detailed long listing. Here is an example of
 | |
| 	  <tt/lpq -l/:
 | |
| <tscreen><verb>
 | |
| waiting for bamboo to become ready (offline ?)
 | |
| 
 | |
| kelly: 1st				 [job 009rose]
 | |
|        /etc/host.conf			 73 bytes
 | |
|        /etc/hosts.equiv		         15 bytes
 | |
| 
 | |
| kelly: 2nd				 [job 010rose]
 | |
|        (standard input)		         1635 bytes
 | |
| 
 | |
| mary: 3rd				 [job 011rose]
 | |
|       /home/orchid/mary/research/venus/alpha-regio/mapping 78519 bytes
 | |
| </verb></tscreen>
 | |
| 
 | |
|       <sect1><heading>Removing Jobs<label
 | |
| 	    id="printing:lprm"></heading>
 | |
| 
 | |
| 	<p> If you change your mind about printing a job, you can
 | |
| 	  remove the job from the queue with the 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	   name="lprm"> command.
 | |
| 	  Often, you can even use 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	   name="lprm"> to remove an active job,
 | |
| 	  but some or all of the job might still get printed.
 | |
| 
 | |
| 	  To remove a job from the default printer, first use 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	   name="lpq"> to find the job number.  Then type
 | |
| <tscreen>
 | |
| <tt/lprm <it/job-number//
 | |
| </tscreen>
 | |
| 	  To remove the job from a specific printer, add the <tt/-P/
 | |
| 	  option.  The following command removes job number 10 from
 | |
| 	  the queue for the printer <tt/bamboo/:
 | |
| <tscreen><verb>
 | |
| lprm -P bamboo 10
 | |
| </verb></tscreen>
 | |
| 	  The 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	   name="lprm"> command has a few shortcuts:
 | |
| 	  <descrip>
 | |
| 	    <tag/lprm -/
 | |
| 
 | |
| 	      Removes all jobs (for the default printer) belonging to
 | |
| 	      you.
 | |
| 
 | |
| 	    <tag/lprm <it/user//
 | |
| 
 | |
| 	      Removes all jobs (for the default printer) belonging to
 | |
| 	      <it/user/.  The superuser can remove other users' jobs;
 | |
| 	      you can remove only your own jobs.
 | |
| 
 | |
| 	    <tag/lprm/
 | |
| 
 | |
| 	      With no job number, user name, or ``<tt/-/'' appearing
 | |
| 	      on the command line, 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	       name="lprm"> removes the currently
 | |
| 	      active job on the default printer, if it belongs to
 | |
| 	      you. The superuser can remove any active job.
 | |
| 	  </descrip>
 | |
| 
 | |
| 	  Just use the <tt/-P/ option with the above shortcuts to
 | |
| 	  operate on a specific printer instead of the default.  For
 | |
| 	  example, the following command removes all jobs for the
 | |
| 	  current user in the queue for the printer named <tt/rattan/:
 | |
| 
 | |
| <tscreen><verb>
 | |
| lprm -P rattan -
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	  <em/Note:/ If you are working in a networked environment,
 | |
| 	  
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lprm"
 | |
| 	   name="lprm"> will let you remove jobs only from the host from
 | |
| 	  which the jobs were submitted, even if the same printer is
 | |
| 	  available from other hosts.  The following command sequence
 | |
| 	  demonstrates this:
 | |
| <code>
 | |
| rose% lpr -P rattan myfile
 | |
| rose% rlogin orchid
 | |
| orchid% lpq -P rattan
 | |
| Rank   Owner	  Job  Files				     Total Size
 | |
| active seeyan	  12	...				     49123 bytes
 | |
| 2nd    kelly	  13   myfile				     12 bytes
 | |
| orchid% lprm -P rattan 13
 | |
| rose: Permission denied
 | |
| orchid% logout
 | |
| rose% lprm -P rattan 13
 | |
| dfA013rose dequeued
 | |
| cfA013rose dequeued
 | |
| rose% 
 | |
| </code>
 | |
| 
 | |
|       <sect1><heading>Beyond Plain Text: Printing Options<label
 | |
| 	    id="printing:lpr:options"></heading>
 | |
| 
 | |
|       <p> The 
 | |
|       <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
|        name="lpr"> command supports a number of options that
 | |
| 	  control formatting text, converting graphic and other file
 | |
| 	  formats, producing multiple copies, handling of the job, and
 | |
| 	  more.  This section describes the options.
 | |
| 
 | |
| 	<sect2><heading>Formatting and Conversion Options<label
 | |
| 	      id="printing:lpr:options:format"></heading>
 | |
| 
 | |
| 	  <p> The following 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> options control formatting of the
 | |
| 	    files in the job.  Use these options if the job does not
 | |
| 	    contain plain text or if you want plain text formatted
 | |
| 	    through the 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pr"
 | |
| 	     name="pr"> utility.
 | |
| 
 | |
| 	    For example, the following command prints a DVI file (from
 | |
| 	    the TeX typesetting system) named <tt/fish-report.dvi/
 | |
| 	    to the printer named <tt/bamboo/: 
 | |
| <tscreen><verb>
 | |
| lpr -P bamboo -d fish-report.dvi
 | |
| </verb></tscreen>
 | |
| 	    These options apply to every file in the job, so you cannot
 | |
| 	    mix (say) DVI and ditroff files together in a job.
 | |
| 	    Instead, submit the files as separate jobs, using a
 | |
| 	    different conversion option for each job.
 | |
| 
 | |
| 	    <em/Note:/ All of these options except <tt/-p/ and <tt/-T/
 | |
| 	    require conversion filters installed for the destination
 | |
| 	    printer.  For example, the <tt/-d/ option requires the DVI
 | |
| 	    conversion filter.  Section <ref
 | |
| 	    id="printing:advanced:convfilters" name="Conversion
 | |
| 	    Filters"> gives details.
 | |
| 	    
 | |
| 	    <descrip>
 | |
| 	      <tag/<tt/-c// Print cifplot files.
 | |
| 
 | |
| 	      <tag/<tt/-d// Print DVI files.
 | |
| 
 | |
| 	      <tag/<tt/-f// Print FORTRAN text files.
 | |
| 
 | |
| 	      <tag/<tt/-g// Print plot data.
 | |
| 
 | |
| 	      <tag/<tt/-i <it/number///
 | |
| 
 | |
| 		Indent the output by <it/number/ columns; if you omit
 | |
| 		<it/number/, indent by 8 columns.  This option works
 | |
| 		only with certain conversion filters.
 | |
| 
 | |
| 		<em/Note:/ Do not put any space between the <tt/-i/ and
 | |
| 		the number.
 | |
| 
 | |
| 	      <tag/<tt/-l//
 | |
| 
 | |
| 		Print literal text data, including control characters.
 | |
| 
 | |
| 	      <tag/<tt/-n// Print ditroff (device independent troff) data.
 | |
| 
 | |
| 	      <tag/-p/
 | |
| 
 | |
| 		Format plain text with 
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?pr"
 | |
| 		 name="pr"> before printing.  See
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?pr(1)"
 | |
| 		name="pr(1)"> for more information.
 | |
| 
 | |
| 	      <tag/<tt/-T <it/title///
 | |
| 
 | |
| 		Use <it/title/ on the 
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?pr"
 | |
|  name="pr">
 | |
|  header instead of the
 | |
| 		file name.  This option has effect only when used with
 | |
| 		the <tt/-p/ option.
 | |
| 
 | |
| 	      <tag/<tt/-t// Print troff data.
 | |
| 
 | |
| 	      <tag/<tt/-v// Print raster data.
 | |
| 
 | |
| 	    </descrip>
 | |
| 		
 | |
| 	    Here is an example: this command prints a nicely
 | |
| 	    formatted version of the 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?ls"
 | |
| 	    name="ls"> manual page on the
 | |
| 	    default printer:
 | |
| <tscreen><verb>
 | |
| zcat /usr/share/man/man1/ls.1.gz | troff -t -man | lpr -t
 | |
| </verb></tscreen>
 | |
| 	    The 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?zcat"
 | |
| 	     name="zcat"> command uncompresses the source of the
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?ls"
 | |
| 	     name="ls"> manual page and passes it to the 
 | |
| 	     <htmlurl url="http://www.freebsd.org/cgi/man.cgi?troff"
 | |
| 	      name="troff">
 | |
| 	    command, which formats that source and makes GNU troff
 | |
| 	    output and passes it to 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	     name="lpr">, which submits the job to
 | |
| 	    the LPD spooler.  Because we used the <tt/-t/ option to
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	     name="lpr">, the spooler will convert the GNU troff output
 | |
| 	    into a format the default printer can understand when it
 | |
| 	    prints the job.
 | |
| 
 | |
| 	<sect2><heading>Job Handling Options<label
 | |
| 	      id="printing:lpr:options:job-handling"></heading>
 | |
| 
 | |
| 	  <p> The following options to 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> tell LPD to handle the
 | |
| 	    job specially:
 | |
| 
 | |
| 	    <descrip>
 | |
| 	      <tag/-# <it/copies//
 | |
| 
 | |
| 		Produce a number of <it/copies/ of each file in the
 | |
| 		job instead of just one copy.  An administrator may
 | |
| 		disable this option to reduce printer wear-and-tear
 | |
| 		and encourage photocopier usage.  See section <ref
 | |
| 		id="printing:advanced:restricting:copies"
 | |
| 		name="Restricting Multiple Copies">.
 | |
| 
 | |
| 		<p> This example prints three copies of <tt/parser.c/
 | |
| 		followed by three copies of <tt/parser.h/ to the
 | |
| 		default printer:
 | |
| <tscreen><verb>
 | |
| lpr -#3 parser.c parser.h
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      <tag/-m/
 | |
| 	      
 | |
| 		Send mail after completing the print job.  With this
 | |
| 		option, the LPD system will send mail to your account
 | |
| 		when it finishes handling your job.  In its message,
 | |
| 		it will tell you if the job completed successfully or
 | |
| 		if there was an error, and (often) what the error was.
 | |
| 
 | |
| 	      <tag/-s/ Do not copy the files to the spooling directory,
 | |
| 		but make symbolic links to them instead.
 | |
| 
 | |
| 		If you are printing a large job, you probably want to
 | |
| 		use this option.  It saves space in the spooling
 | |
| 		directory (your job might overflow the free space on
 | |
| 		the filesystem where the spooling directory resides).
 | |
| 		It saves time as well since LPD will not have to copy
 | |
| 		each and every byte of your job to the spooling
 | |
| 		directory.
 | |
| 
 | |
| 		There is a drawback, though: since LPD will refer to
 | |
| 		the original files directly, you cannot modify or
 | |
| 		remove them until they have been printed.
 | |
| 
 | |
| 		<em/Note:/ If you are printing to a remote printer, LPD
 | |
| 		will eventually have to copy files from the local host
 | |
| 		to the remote host, so the <tt/-s/ option will save
 | |
| 		space only on the local spooling directory, not the
 | |
| 		remote.  It is still useful, though.
 | |
| 
 | |
| 	      <tag/-r/
 | |
| 
 | |
| 		Remove the files in the job after copying them to the
 | |
| 		spooling directory, or after printing them with the
 | |
| 		<tt/-s/ option.  Be careful with this option!
 | |
| 
 | |
| 	    </descrip>
 | |
| 
 | |
| 	<sect2><heading>Header Page Options<label
 | |
| 	      id="printing:lpr:options:misc"></heading>
 | |
| 
 | |
| 	  <p> These options to 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	   name="lpr"> adjust the text that normally
 | |
| 	    appears on a job's header page.  If header pages are
 | |
| 	    suppressed for the destination printer, these options have
 | |
| 	    no effect.  See section <ref name="Header Pages"
 | |
| 	    id="printing:advanced:header-pages"> for information about
 | |
| 	    setting up header pages.
 | |
| 
 | |
| 	    <descrip>
 | |
| 	      <tag/-C <it/text//
 | |
| 
 | |
| 		Replace the hostname on the header page with
 | |
| 		<it/text/.  The hostname is normally the name of the
 | |
| 		host from which the job was submitted.
 | |
| 
 | |
| 	      <tag/-J <it/text//
 | |
| 
 | |
| 		Replace the job name on the header page with
 | |
| 		<it/text/.  The job name is normally the name of the
 | |
| 		first file of the job, or ``stdin'' if you are printing
 | |
| 		standard input.
 | |
| 
 | |
| 	      <tag/-h/
 | |
| 	      
 | |
| 		Do not print any header page.  <em/Note:/ At some
 | |
| 		sites, this option may have no effect due to the way
 | |
| 		header pages are generated.  See <ref name="Header
 | |
| 		Pages" id="printing:advanced:header-pages"> for
 | |
| 		details.
 | |
| 
 | |
| 	    </descrip>
 | |
| 
 | |
|       <sect1><heading>Administrating Printers<label
 | |
| 	    id="printing:lpc"></heading>
 | |
| 
 | |
| 	<p> As an administrator for your printers, you have had to
 | |
| 	  install, set up, and test them.  Using the 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	   name="lpc"> command,
 | |
| 	  you can interact with your printers in yet more ways.  With
 | |
| 	  
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	   name="lpc">, you can
 | |
| 
 | |
| 	  <itemize>
 | |
| 	    <item>Start and stop the printers
 | |
| 
 | |
| 	    <item>Enable and disable their queues
 | |
| 
 | |
| 	    <item>Rearrange the order of the jobs in each queue.
 | |
| 	  </itemize>
 | |
| 
 | |
| 	  First, a note about terminology: if a printer is
 | |
| 	  <em/stopped/, it will not print anything in its queue.  Users
 | |
| 	  can still submit jobs, which will wait in the queue until
 | |
| 	  the printer is <em/started/ or the queue is cleared.
 | |
| 
 | |
| 	  If a queue is <em/disabled/, no user (except root) can
 | |
| 	  submit jobs for the printer.  An <em/enabled/ queue allows
 | |
| 	  jobs to be submitted.  A printer can be <em/started/ for a
 | |
| 	  disabled queue, in which case it will continue to print jobs
 | |
| 	  in the queue until the queue is empty.
 | |
| 
 | |
| 	  In general, you have to have root privileges to use the
 | |
| 	  
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	   name="lpc"> command.  Ordinary users can use the 
 | |
| 	   <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	    name="lpc">
 | |
| 	    command to get printer status and to restart a hung printer
 | |
| 	  only.
 | |
| 
 | |
| 	  Here is a summary of the 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	   name="lpc"> commands.  Most of the
 | |
| 	  commands takes a <it/printer-name/ argument to tell on which
 | |
| 	  printer to operate.  You can use <tt/all/ for the
 | |
| 	  <it/printer-name/ to mean all printers listed in
 | |
| 	  <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 	  <descrip>
 | |
| 	    <tag/<tt/abort <it/printer-name///
 | |
| 
 | |
| 	      Cancel the current job and stop the printer.  Users can
 | |
| 	      still submit jobs if the queue's enabled.
 | |
| 
 | |
| 	    <tag/<tt/clean <it/printer-name///
 | |
| 
 | |
| 	      Remove old files from the printer's spooling directory.
 | |
| 	      Occasionally, the files that make up a job are not
 | |
| 	      properly removed by LPD, particularly if there have been
 | |
| 	      errors during printing or a lot of administrative
 | |
| 	      activity.  This command finds files that do not belong in
 | |
| 	      the spooling directory and removes them.
 | |
| 
 | |
| 	    <tag/<tt/disable <it/printer-name///
 | |
| 
 | |
| 	      Disable queuing of new jobs.  If the printer's started,
 | |
| 	      it will continue to print any jobs remaining in the
 | |
| 	      queue.  The superuser (root) can always submit jobs,
 | |
| 	      even to a disabled queue.
 | |
| 
 | |
| 	      This command is useful while you are testing a new
 | |
| 	      printer or filter installation: disable the queue and
 | |
| 	      submit jobs as root.  Other users will not be able to
 | |
| 	      submit jobs until you complete your testing and re-enable
 | |
| 	      the queue with the <tt/enable/ command.
 | |
| 
 | |
| 	    <tag/<tt/down <it/printer-name/ <it/message...///
 | |
| 
 | |
| 	      Take a printer down.  Equivalent to <tt/disable/
 | |
| 	      followed by <tt/stop/.  The <it/message/ appears as the
 | |
| 	      printer's status whenever a user checks the printer's
 | |
| 	      queue with 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpq"
 | |
| 	       name="lpq"> or status with <tt/lpc status/.
 | |
| 
 | |
| 	    <tag/<tt/enable <it/printer-name///
 | |
| 
 | |
| 	      Enable the queue for a printer.  Users can submit jobs
 | |
| 	      but the printer will not print anything until it is started.
 | |
| 
 | |
| 	    <tag/<tt/help <it/command-name///
 | |
| 
 | |
| 	      Print help on the command <it/command-name/.  With no
 | |
| 	      <it/command-name/, print a summary of the commands
 | |
| 	      available.
 | |
| 
 | |
| 	    <tag/<tt/restart <it/printer-name///
 | |
| 
 | |
| 	      Start the printer.  Ordinary users can use this command
 | |
| 	      if some extraordinary circumstance hangs LPD, but they
 | |
| 	      cannot start a printer stopped with either the <tt/stop/
 | |
| 	      or <tt/down/ commands.  The <tt/restart/ command is
 | |
| 	      equivalent to <tt/abort/ followed by <tt/start/.
 | |
| 
 | |
| 	    <tag/<tt/start <it/printer-name///
 | |
| 
 | |
| 	      Start the printer.  The printer will print jobs in its
 | |
| 	      queue.
 | |
| 
 | |
| 	    <tag/<tt/stop <it/printer-name///
 | |
| 
 | |
| 	      Stop the printer.  The printer will finish the current
 | |
| 	      job and will not print anything else in its queue.  Even
 | |
| 	      though the printer is stopped, users can still submit
 | |
| 	      jobs to an enabled queue.
 | |
| 
 | |
| 	    <tag/<tt/topq <it/printer-name/ <it/job-or-username...///
 | |
| 
 | |
| 	      Rearrange the queue for <it/printer-name/ by placing the
 | |
| 	      jobs with the listed <it/job/ numbers or the jobs
 | |
| 	      belonging to <it/username/ at the top of the queue.  For
 | |
| 	      this command, you cannot use <tt/all/ as the
 | |
| 	      <it/printer-name/.
 | |
| 
 | |
| 	    <tag/<tt/up <it/printer-name///
 | |
| 
 | |
| 	      Bring a printer up; the opposite of the <tt/down/
 | |
| 	      command.  Equivalent to <tt/start/ followed by
 | |
| 	      <tt/enable/.
 | |
| 
 | |
| 	  </descrip>
 | |
| 
 | |
| 	  
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	   name="lpc"> accepts the above commands on the command line.  If
 | |
| 	  you do not enter any commands, 
 | |
| 	  <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpc"
 | |
| 	   name="lpc"> enters an interactive
 | |
| 	  mode, where you can enter commands until you type <tt/exit/,
 | |
| 	  <tt/quit/, or end-of-file.
 | |
| 
 | |
|     <sect><heading>Advanced Printer Setup<label
 | |
| 	  id="printing:advanced"></heading>
 | |
| 
 | |
|       <p> This section describes filters for printing specially
 | |
| 	formatted files, header pages, printing across networks, and
 | |
| 	restricting and accounting for printer usage.
 | |
| 
 | |
| 	<sect1><heading>Filters<label
 | |
| 	    id="printing:advanced:filter-intro"></heading>
 | |
| 
 | |
| 	<p> Although LPD handles network protocols, queuing, access
 | |
| 	  control, and other aspects of printing, most of the
 | |
| 	  <em/real/ work happens in the <em/filters/.  Filters are
 | |
| 	  programs that communicate with the printer and handle its
 | |
| 	  device dependencies and special requirements.  In the simple
 | |
| 	  printer setup, we installed a plain text filter---an
 | |
| 	  extremely simple one that should work with most printers
 | |
| 	  (section <ref id="printing:textfilter" name="Installing the
 | |
| 	  Text Filter">).
 | |
| 
 | |
| 	  However, in order to take advantage of format conversion,
 | |
| 	  printer accounting, specific printer quirks, and so on, you
 | |
| 	  should understand how filters work.  It will ultimately be
 | |
| 	  the filter's responsibility to handle these aspects.  And the
 | |
| 	  bad news is that most of the time <em/you/ have to provide
 | |
| 	  filters yourself.  The good news is that many are generally
 | |
| 	  available; when they are not, they are usually easy to write.
 | |
| 
 | |
| 	  Also, FreeBSD comes with one, <tt>/usr/libexec/lpr/lpf</tt>,
 | |
| 	  that works with many printers that can print plain text.
 | |
| 	  (It handles backspacing and tabs in the file, and does
 | |
| 	  accounting, but that is about all it does.)  There are also
 | |
| 	  several filters and filter components in the FreeBSD ports
 | |
| 	  collection.
 | |
| 
 | |
| 	  Here is what you will find in this section:
 | |
| 
 | |
| 	  <itemize>
 | |
| 	    <item>Section <ref id="printing:advanced:filters"
 | |
| 	      name="How Filters Work">, tries to give an overview of a
 | |
| 	      filter's role in the printing process.  You should read
 | |
| 	      this section to get an understanding of what is happening
 | |
| 	      ``under the hood'' when LPD uses filters.  This
 | |
| 	      knowledge could help you anticipate and debug problems
 | |
| 	      you might encounter as you install more and more filters
 | |
| 	      on each of your printers.
 | |
| 	      
 | |
| 	    <item>LPD expects every printer to be able to print plain
 | |
| 	      text by default.  This presents a problem for PostScript
 | |
| 	      (or other language-based printers) which cannot directly
 | |
| 	      print plain text.  Section <ref
 | |
| 	      id="printing:advanced:if-conversion" name="Accommodating
 | |
| 	      Plain Text Jobs on PostScript Printers"> tells you what
 | |
| 	      you should do to overcome this problem.  I recommend
 | |
| 	      reading this section if you have a PostScript printer.
 | |
| 
 | |
| 	    <item>PostScript is a popular output format for many
 | |
| 	      programs.  Even some people (myself included) write
 | |
| 	      PostScript code directly.  But PostScript printers are
 | |
| 	      expensive.  Section <ref id="printing:advanced:ps"
 | |
| 	      name="Simulating PostScript on Non-PostScript Printers">
 | |
| 	      tells how you can further modify a printer's text filter
 | |
| 	      to accept and print PostScript data on a
 | |
| 	      <em/non-PostScript/ printer.  I recommend reading this
 | |
| 	      section if you do not have a PostScript printer.
 | |
| 	      
 | |
| 	    <item>Section <ref id="printing:advanced:convfilters"
 | |
| 		name="Conversion Filters"> tells about a way you can
 | |
| 		automate the conversion of specific file formats, such
 | |
| 		as graphic or typesetting data, into formats your
 | |
| 		printer can understand.  After reading this section,
 | |
| 		you should be able to set up your printers such that
 | |
| 		users can type <tt/lpr -t/ to print troff data, or
 | |
| 		<tt/lpr -d/ to print TeX DVI data, or <tt/lpr -v/ to
 | |
| 		print raster image data, and so forth.  I recommend
 | |
| 		reading this section.
 | |
| 
 | |
| 	    <item>Section <ref id="printing:advanced:of" name="Output
 | |
| 		Filters"> tells all about a not often used feature of
 | |
| 		LPD: output filters.  Unless you are printing header
 | |
| 		pages (see <ref id="printing:advanced:header-pages"
 | |
| 		name="Header Pages">), you can probably skip that
 | |
| 		section altogether.
 | |
| 
 | |
| 	    <item>Section <ref id="printing:advanced:lpf" name="lpf:
 | |
| 		a Text Filter"> describes <tt/lpf/, a fairly complete
 | |
| 		if simple text filter for line printers (and laser
 | |
| 		printers that act like line printers) that comes with
 | |
| 		FreeBSD.  If you need a quick way to get printer
 | |
| 		accounting working for plain text, or if you have a
 | |
| 		printer which emits smoke when it sees backspace
 | |
| 		characters, you should definitely consider <tt/lpf/.
 | |
| 	  </itemize>
 | |
| 
 | |
| 	<sect2><heading>How Filters Work<label
 | |
| 	      id="printing:advanced:filters"></heading>
 | |
| 
 | |
| 	  <p> As mentioned before, a filter is an executable program
 | |
| 	    started by LPD to handle the device-dependent part of
 | |
| 	    communicating with the printer.
 | |
| 
 | |
| 	    When LPD wants to print a file in a job, it starts a
 | |
| 	    filter program.  It sets the filter's standard input to
 | |
| 	    the file to print, its standard output to the printer, and
 | |
| 	    its standard error to the error logging file (specified in
 | |
| 	    the <tt/lf/ capability in <tt>/etc/printcap</tt>, or
 | |
| 	    <tt>/dev/console</tt> by default).
 | |
| 
 | |
| 	    Which filter LPD starts and the filter's arguments depend
 | |
| 	    on what is listed in the <tt>/etc/printcap</tt> file and
 | |
| 	    what arguments the user specified for the job on the
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	     name="lpr"> command line.  For example, if the user typed
 | |
| 	    <tt/lpr -t/, LPD would start the troff filter, listed in
 | |
| 	    the <tt/tf/ capability for the destination printer.  If
 | |
| 	    the user wanted to print plain text, it would start the
 | |
| 	    <tt/if/ filter (this is mostly true: see <ref
 | |
| 	    id="printing:advanced:of" name="Output Filters"> for
 | |
| 	    details).
 | |
| 
 | |
| 	    There are three kinds of filters you can specify in
 | |
| 	    <tt>/etc/printcap</tt>:
 | |
| 	    <itemize>
 | |
| 	      <item>The <em/text filter/, confusingly called the
 | |
| 		<em/input filter/ in LPD documentation, handles
 | |
| 		regular text printing.  Think of it as the default
 | |
|                 filter.  LPD expects every printer to be able to print
 | |
| 		plain text by default, and it is the text filter's job
 | |
| 		to make sure backspaces, tabs, or other special
 | |
| 		characters do not confuse the printer.
 | |
| 
 | |
| 		If you are in an environment where you have to account
 | |
| 		for printer usage, the text filter must also account
 | |
| 		for pages printed, usually by counting the number of
 | |
| 		lines printed and comparing that to the number of
 | |
| 		lines per page the printer supports.
 | |
| 
 | |
| 		The text filter is started with the following argument
 | |
| 		list:
 | |
| <tscreen>
 | |
| <tt>[-c] -w<it/width/ -l<it/length/ -i<it/indent/ -n <it/login/ -h <it/host/ <it/acct-file/</tt>
 | |
| </tscreen>
 | |
| 		where
 | |
| 		<descrip>
 | |
| 		  <tag/<tt/-c//
 | |
| 
 | |
| 		    appears if the job's submitted with <tt/lpr -l/
 | |
| 
 | |
| 		  <tag/<tt/<it/width///
 | |
| 
 | |
| 		    is the value from the <tt/pw/ (page width)
 | |
| 		    capability specified in <tt>/etc/printcap</tt>,
 | |
| 		    default 132
 | |
| 
 | |
| 		  <tag/<tt/<it/length///
 | |
| 
 | |
| 		    is the value from the <tt/pl/ (page length)
 | |
| 		    capability, default 66
 | |
| 
 | |
| 		  <tag/<tt/<it/indent///
 | |
| 
 | |
| 		    is the amount of the indentation from <tt/lpr -i/,
 | |
| 		    default 0
 | |
| 
 | |
| 		  <tag/<tt/<it/login///
 | |
| 
 | |
| 		    is the account name of the user printing the file
 | |
| 
 | |
| 		  <tag/<tt/<it/host///
 | |
| 
 | |
| 		    is the host name from which the job was submitted
 | |
| 
 | |
| 		  <tag/<tt/<it/acct-file///
 | |
| 
 | |
| 		    is the name of the accounting file from the <tt/af/
 | |
| 		    capability.
 | |
| 
 | |
| 		</descrip>
 | |
| 
 | |
| 	      <item>A <em/conversion filter/ converts a specific file
 | |
| 		format into one the printer can render onto paper.
 | |
| 		For example, ditroff typesetting data cannot be
 | |
| 		directly printed, but you can install a conversion
 | |
| 		filter for ditroff files to convert the ditroff data
 | |
| 		into a form the printer can digest and print.  Section
 | |
| 		<ref id="printing:advanced:convfilters"
 | |
| 		name="Conversion Filters"> tells all about them.
 | |
| 		Conversion filters also need to do accounting, if you
 | |
| 		need printer accounting.
 | |
| 
 | |
| 		Conversion filters are started with the following
 | |
| 		arguments:
 | |
| <tscreen>
 | |
| <tt>-x<it/pixel-width/ -y<it/pixel-height/ -n <it/login/ -h <it/host/ <it/acct-file/</tt>
 | |
| </tscreen>
 | |
| 		where <it/pixel-width/ is the value from the <tt/px/
 | |
| 		capability (default 0) and <it/pixel-height/ is the
 | |
| 		value from the <tt/py/ capability (default 0).
 | |
| 
 | |
| 	      <item>The <em/output filter/ is used only if there is no
 | |
| 		text filter, or if header pages are enabled.  In my
 | |
| 		experience, output filters are rarely used.  Section
 | |
| 		<ref id="printing:advanced:of" name="Output Filters">
 | |
| 		describe them.  There are only two arguments to an
 | |
| 		output filter:
 | |
| <tscreen>
 | |
| <tt>-w<it/width/ -l<it/length/</tt>
 | |
| </tscreen>
 | |
|                 which are identical to the text filters <tt/-w/ and
 | |
| 		<tt/-l/ arguments.
 | |
| 	    </itemize>
 | |
| 
 | |
| 	    Filters should also <em/exit/ with the following exit
 | |
| 	    status:
 | |
| 	    <descrip>
 | |
| 	      <tag/exit 0/
 | |
| 
 | |
| 		If the filter printed the file successfully.
 | |
| 
 | |
| 	      <tag/exit 1/
 | |
| 
 | |
| 	        If the filter failed to print the file but wants LPD
 | |
| 		to try to print the file again.  LPD will restart a
 | |
| 		filter if it exits with this status.
 | |
| 
 | |
| 	      <tag/exit 2/
 | |
| 
 | |
| 	        If the filter failed to print the file and does not
 | |
| 		want LPD to try again.  LPD will throw out the file.
 | |
| 	    </descrip>
 | |
| 
 | |
| 	    The text filter that comes with the FreeBSD release,
 | |
| 	    <tt>/usr/libexec/lpr/lpf</tt>, takes advantage of the page
 | |
| 	    width and length arguments to determine when to send a
 | |
| 	    form feed and how to account for printer usage.  It uses
 | |
| 	    the login, host, and accounting file arguments to make the
 | |
| 	    accounting entries.
 | |
| 
 | |
| 	    If you are shopping for filters, see if they are
 | |
| 	    LPD-compatible.  If they are, they must support the
 | |
| 	    argument lists described above.  If you plan on writing
 | |
| 	    filters for general use, then have them support the same
 | |
| 	    argument lists and exit codes.
 | |
| 
 | |
| 	<sect2><heading>Accommodating Plain Text Jobs on PostScript Printers
 | |
| 	    <label id="printing:advanced:if-conversion"></heading>
 | |
| 
 | |
| 	  <p> If you are the only user of your computer and PostScript
 | |
| 	    (or other language-based) printer, and you promise to
 | |
| 	    never send plain text to your printer and to never use
 | |
| 	    features of various programs that will want to send plain
 | |
| 	    text to your printer, then you do not need to worry about
 | |
| 	    this section at all.
 | |
| 
 | |
| 	    But, if you would like to send both PostScript and plain
 | |
| 	    text jobs to the printer, then you are urged to augment
 | |
| 	    your printer setup.  To do so, we have the text filter
 | |
| 	    detect if the arriving job is plain text or PostScript.
 | |
| 	    All PostScript jobs must start with <tt/%!/ (for
 | |
| 	    other printer languages, see your printer documentation).
 | |
| 	    If those are the first two characters in the job, we have
 | |
| 	    PostScript, and can pass the rest of the job directly.  If
 | |
| 	    those are not the first two characters in the file, then
 | |
| 	    the filter will convert the text into PostScript and print
 | |
| 	    the result.
 | |
| 
 | |
| 	    How do we do this?
 | |
| 
 | |
| 	    If you have got a serial printer, a great way to do it is to
 | |
| 	    install <tt/lprps/.  <tt/lprps/ is a PostScript printer
 | |
| 	    filter which performs two-way communication with the
 | |
| 	    printer.  It updates the printer's status file with
 | |
| 	    verbose information from the printer, so users and
 | |
| 	    administrators can see exactly what the state of the
 | |
| 	    printer is (such as ``toner low'' or ``paper jam'').  But
 | |
| 	    more importantly, it includes a program called <tt/psif/
 | |
| 	    which detects whether the incoming job is plain text and
 | |
| 	    calls <tt/textps/ (another program that comes with
 | |
| 	    <tt/lprps/) to convert it to PostScript.  It then uses
 | |
| 	    <tt/lprps/ to send the job to the printer.
 | |
| 
 | |
| 	    <tt/lprps/ is part of the FreeBSD ports collection
 | |
| 	    (see <ref id="ports" name="The Ports Collection">).
 | |
| 	    You can fetch, build and install it
 | |
| 	    yourself, of course.  After installing <tt/lprps/, just
 | |
| 	    specify the pathname to the <tt/psif/ program that is part
 | |
| 	    of <tt/lprps/.  If you installed <tt/lprps/ from the ports
 | |
| 	    collection, use the following in the serial PostScript
 | |
| 	    printer's entry in <tt>/etc/printcap</tt>:
 | |
| <tscreen><verb>
 | |
| 	    :if=/usr/local/libexec/psif:
 | |
| </verb></tscreen>
 | |
| 	    You should also specify the <tt/rw/ capability; that tells
 | |
| 	    LPD to open the printer in read-write mode.
 | |
| 
 | |
| 	    If you have a parallel PostScript printer (and therefore
 | |
| 	    cannot use two-way communication with the printer, which
 | |
| 	    <tt/lprps/ needs), you can use the following shell script
 | |
| 	    as the text filter:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  psif - Print PostScript or plain text on a PostScript printer
 | |
| #  Script version; NOT the version that comes with lprps
 | |
| #  Installed in /usr/local/libexec/psif
 | |
| #
 | |
| 
 | |
| read first_line
 | |
| first_two_chars=`expr "$first_line" : '\(..\)'`
 | |
| 
 | |
| if [ "$first_two_chars" = "%!" ]; then
 | |
|    #
 | |
|    #  PostScript job, print it.
 | |
|    #
 | |
|    echo $first_line && cat && printf "\004" && exit 0
 | |
|    exit 2
 | |
| else
 | |
|    #
 | |
|    #  Plain text, convert it, then print it.
 | |
|    #
 | |
|    ( echo $first_line; cat ) | /usr/local/bin/textps && printf "\004" && exit 0
 | |
|    exit 2
 | |
| fi
 | |
| </code>
 | |
| 	    In the above script, <tt/textps/ is a program we installed
 | |
| 	    separately to convert plain text to PostScript.  You can
 | |
| 	    use any text-to-PostScript program you wish.  The FreeBSD
 | |
| 	    ports collection (see <ref id="ports" name="The Ports
 | |
| 	    Collection">) includes a full featured text-to-PostScript
 | |
| 	    program called 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=a2ps"
 | |
| 	     name="a2ps"> that you might want to
 | |
| 	    investigate.
 | |
| 
 | |
| 	<sect2><heading>Simulating PostScript on Non-PostScript Printers
 | |
| 	    <label id="printing:advanced:ps"></heading>
 | |
| 
 | |
| 	  <p> PostScript is the <it/de facto/ standard for high
 | |
| 	    quality typesetting and printing.  PostScript is, however,
 | |
| 	    an <em/expensive/ standard.  Thankfully, Alladin
 | |
| 	    Enterprises has a free PostScript work-alike called
 | |
| 	    <it/Ghostscript/ that runs with FreeBSD.  Ghostscript can
 | |
| 	    read most PostScript files and can render their pages onto
 | |
| 	    a variety of devices, including many brands of
 | |
| 	    non-PostScript printers.  By installing Ghostscript and
 | |
| 	    using a special text filter for your printer, you can make
 | |
| 	    your non-PostScript printer act like a real PostScript
 | |
| 	    printer.
 | |
| 
 | |
| 	    Ghostscript should be in the FreeBSD ports collection, if
 | |
| 	    you would like to install it from there.  You can fetch,
 | |
| 	    build, and install it quite easily yourself, as well.
 | |
| 
 | |
| 	    To simulate PostScript, we have the text filter detect if
 | |
| 	    it is printing a PostScript file.  If it is not, then the
 | |
| 	    filter will pass the file directly to the printer;
 | |
| 	    otherwise, it will use Ghostscript to first convert the
 | |
| 	    file into a format the printer will understand.
 | |
| 
 | |
| 	    Here is an example: the following script is a text filter
 | |
| 	    for Hewlett Packard DeskJet 500 printers.  For other
 | |
| 	    printers, substitute the <tt/-sDEVICE/ argument to the
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=gs"
 | |
| 	     name="gs"> (Ghostscript) command.  (Type <tt/gs -h/ to get a
 | |
| 	    list of devices the current installation of Ghostscript
 | |
| 	    supports.)
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  ifhp - Print Ghostscript-simulated PostScript on a DeskJet 500
 | |
| #  Installed in /usr/local/libexec/hpif
 | |
| 
 | |
| #
 | |
| #  Treat LF as CR+LF:
 | |
| #
 | |
| printf "\033&k2G" || exit 2
 | |
| 
 | |
| #
 | |
| #  Read first two characters of the file
 | |
| #
 | |
| read first_line
 | |
| first_two_chars=`expr "$first_line" : '\(..\)'`
 | |
| 
 | |
| if [ "$first_two_chars" = "%!" ]; then
 | |
|     #
 | |
|     #  It is PostScript; use Ghostscript to scan-convert and print it
 | |
|     #
 | |
|     /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 -sOutputFile=- - \
 | |
|         && exit 0
 | |
| 
 | |
| else
 | |
|     #
 | |
|     #  Plain text or HP/PCL, so just print it directly; print a form
 | |
|     #  at the end to eject the last page.
 | |
|     #
 | |
|     echo $first_line && cat && printf "\f" && exit 0
 | |
| fi
 | |
| 
 | |
| exit 2
 | |
| </code>
 | |
| 	    Finally, you need to notify LPD of the filter via the
 | |
| 	    <tt/if/ capability:
 | |
| <tscreen><verb>
 | |
| 	:if=/usr/local/libexec/hpif:
 | |
| </verb></tscreen>
 | |
| 	    That is it.  You can type <tt/lpr plain.text/ and <tt/lpr
 | |
| 	    whatever.ps/ and both should print successfully.
 | |
| 
 | |
| 
 | |
| 	<sect2><heading>Conversion Filters<label
 | |
| 	      id="printing:advanced:convfilters"></heading>
 | |
| 
 | |
| 	  <p> After completing the simple setup described in <ref
 | |
| 	      name="Simple Printer Setup" id="printing:simple">, the
 | |
| 	      first thing you will probably want to do is install
 | |
| 	      conversion filters for your favorite file formats
 | |
| 	      (besides plain ASCII text).
 | |
| 
 | |
| 	    <sect3><heading>Why Install Conversion Filters?</heading>
 | |
| 
 | |
| 	    <p> Conversion filters make printing various kinds of
 | |
| 	      files easy.  As an example, suppose we do a lot of work
 | |
| 	      with the TeX typesetting system, and we have a
 | |
| 	      PostScript printer.  Every time we generate a DVI file
 | |
| 	      from TeX, we cannot print it directly until we convert
 | |
| 	      the DVI file into PostScript.  The command sequence
 | |
| 	      goes like this:
 | |
| <tscreen><verb>
 | |
| dvips seaweed-analysis.dvi
 | |
| lpr seaweed-analysis.ps
 | |
| </verb></tscreen>
 | |
| 	      By installing a conversion filter for DVI files, we can
 | |
| 	      skip the hand conversion step each time by having LPD do
 | |
| 	      it for us.  Now, each time we get a DVI file, we are just
 | |
| 	      one step away from printing it:
 | |
| <tscreen><verb>
 | |
| lpr -d seaweed-analysis.dvi
 | |
| </verb></tscreen>
 | |
| 	      We got LPD to do the DVI file conversion for us by
 | |
| 	      specifying the <tt/-d/ option.  Section <ref
 | |
| 		id="printing:lpr:options:format" name="Formatting and
 | |
| 		Conversion Options"> lists the conversion options.
 | |
| 
 | |
| 	      For each of the conversion options you want a printer to
 | |
| 	      support, install a <em/conversion filter/ and specify
 | |
| 	      its pathname in <tt>/etc/printcap</tt>.  A conversion
 | |
| 	      filter is like the text filter for the simple printer
 | |
| 	      setup (see section <ref id="printing:textfilter"
 | |
| 	      name="Installing the Text Filter">) except that instead
 | |
| 	      of printing plain text, the filter converts the file
 | |
| 	      into a format the printer can understand.
 | |
| 
 | |
| 	  <sect3><heading>Which Conversions Filters Should I Install?
 | |
| 	    </heading>
 | |
| 
 | |
| 	    <p> You should install the conversion filters you expect
 | |
| 	      to use.  If you print a lot of DVI data, then a DVI
 | |
| 	      conversion filter is in order.  If you have got plenty of
 | |
| 	      troff to print out, then you probably want a troff
 | |
| 	      filter.
 | |
| 
 | |
| 	      The following table summarizes the filters that LPD
 | |
| 	      works with, their capability entries for the
 | |
| 	      <tt>/etc/printcap</tt> file, and how to invoke them with
 | |
| 	      the <tt/lpr/ command:
 | |
| <code>
 | |
|               /etc/printcap
 | |
| File type       Capability  lpr option
 | |
| ------------  ------------- ----------
 | |
| cifplot            cf          -c
 | |
| DVI                df          -d
 | |
| plot               gf          -g
 | |
| ditroff            nf          -n
 | |
| FORTRAN text       rf          -f
 | |
| troff              tf          -t
 | |
| raster             vf          -v
 | |
| plain text         if     none, -p, or -l
 | |
| </code>
 | |
| 
 | |
| 	      In our example, using <tt/lpr -d/ means the printer
 | |
| 	      needs a <tt/df/ capability in its entry in
 | |
| 	      <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 	      Despite what others might contend, formats like FORTRAN
 | |
| 	      text and plot are probably obsolete.  At your site, you
 | |
| 	      can give new meanings to these or any of the formatting
 | |
| 	      options just by installing custom filters.  For example,
 | |
| 	      suppose you would like to directly print Printerleaf files
 | |
| 	      (files from the Interleaf desktop publishing program),
 | |
| 	      but will never print plot files.  You could install a
 | |
| 	      Printerleaf conversion filter under the <tt/gf/
 | |
| 	      capability and then educate your users that <tt/lpr -g/
 | |
| 	      mean ``print Printerleaf files.''
 | |
| 
 | |
| 	  <sect3><heading>Installing Conversion Filters</heading>
 | |
| 
 | |
| 	    <p> Since conversion filters are programs you install
 | |
| 	      outside of the base FreeBSD installation, they should
 | |
| 	      probably go under <tt>/usr/local</tt>.  The directory
 | |
| 	      <tt>/usr/local/libexec</tt> is a popular location, since
 | |
| 	      they are specialized programs that only LPD will
 | |
| 	      run; regular users should not ever need to run them.
 | |
| 
 | |
| 	      To enable a conversion filter, specify its pathname
 | |
| 	      under the appropriate capability for the destination
 | |
| 	      printer in <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 	      In our example, we will add the DVI conversion filter to
 | |
| 	      the entry for the printer named <tt/bamboo/.  Here is the
 | |
| 	      example <tt>/etc/printcap</tt> file again, with the new
 | |
| 	      <tt/df/ capability for the printer <tt/bamboo/
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - added df filter for bamboo
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:\
 | |
| 	:if=/usr/local/libexec/if-simple:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\
 | |
| 	:if=/usr/local/libexec/psif:\
 | |
| 	:df=/usr/local/libexec/psdf:
 | |
| </code>
 | |
| 	      The DVI filter is a shell script named
 | |
| 	      <tt>/usr/local/libexec/psdf</tt>.  Here is that script:
 | |
| <code>
 | |
| #!bin/sh
 | |
| #
 | |
| #  psdf - DVI to PostScript printer filter
 | |
| #  Installed in /usr/local/libexec/psdf
 | |
| #
 | |
| #  Invoked by lpd when user runs lpr -d
 | |
| #
 | |
| exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps "$@"
 | |
| </code>
 | |
| 	      This script runs 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvips"
 | |
| 	       name="dvips"> in filter mode (the <tt/-f/
 | |
| 	      argument) on standard input, which is the job to print.
 | |
| 	      It then starts the PostScript printer filter <tt/lprps/
 | |
| 	      (see section <ref id="printing:advanced:if-conversion"
 | |
| 	      name="Accommodating Plain Text Jobs on PostScript
 | |
| 	      Printers">) with the arguments LPD passed to this script.
 | |
| 	      <tt/lprps/ will use those arguments to account for the
 | |
| 	      pages printed.
 | |
| 
 | |
| 	  <sect3><heading>More Conversion Filter Examples</heading>
 | |
| 
 | |
| 	    <p> Since there is no fixed set of steps to install
 | |
| 	      conversion filters, let me instead provide more
 | |
| 	      examples.  Use these as guidance to making your own
 | |
| 	      filters.  Use them directly, if appropriate.
 | |
| 
 | |
| 	      This example script is a raster (well, GIF file,
 | |
| 	      actually) conversion filter for a Hewlett Packard
 | |
| 	      LaserJet III-Si printer:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  hpvf - Convert GIF files into HP/PCL, then print
 | |
| #  Installed in /usr/local/libexec/hpvf
 | |
| 
 | |
| PATH=/usr/X11R6/bin:$PATH; export PATH
 | |
| 
 | |
| giftopnm | ppmtopgm | pgmtopbm | pbmtolj -resolution 300 \
 | |
|     && exit 0 \
 | |
|     || exit 2
 | |
| </code>
 | |
| 	      It works by converting the GIF file into a portable
 | |
| 	      anymap, converting that into a portable graymap,
 | |
| 	      converting that into a portable bitmap, and converting
 | |
| 	      that into LaserJet/PCL-compatible data.
 | |
| 
 | |
| 	      Here is the <tt>/etc/printcap</tt> file with an entry for
 | |
| 	      a printer using the above filter:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host orchid
 | |
| #
 | |
| teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
 | |
| 	:lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\
 | |
| 	:if=/usr/local/libexec/hpif:\
 | |
| 	:vf=/usr/local/libexec/hpvf:
 | |
| </code>
 | |
| 
 | |
| 	      The following script is a conversion filter for troff
 | |
| 	      data from the groff typesetting system for the
 | |
| 	      PostScript printer named <tt/bamboo/:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  pstf - Convert groff's troff data into PS, then print.
 | |
| #  Installed in /usr/local/libexec/pstf
 | |
| #
 | |
| exec grops | /usr/local/libexec/lprps "$@"
 | |
| </code>
 | |
| 	      The above script makes use of <tt/lprps/ again to handle
 | |
| 	      the communication with the printer.  If the printer were
 | |
| 	      on a parallel port, we would use this script instead:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  pstf - Convert groff's troff data into PS, then print.
 | |
| #  Installed in /usr/local/libexec/pstf
 | |
| #
 | |
| exec grops
 | |
| </code>
 | |
| 	      That is it.  Here is the entry we need to add to
 | |
| 	      <tt>/etc/printcap</tt> to enable the filter:
 | |
| <tscreen><verb>
 | |
| 	:tf=/usr/local/libexec/pstf:
 | |
| </verb></tscreen>
 | |
| 
 | |
|               Here is an example that might make old hands at FORTRAN
 | |
|               blush.  It is a FORTRAN-text filter for any printer that
 | |
| 	      can directly print plain text.  We will install it for the
 | |
| 	      printer <tt/teak/:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| # hprf - FORTRAN text filter for LaserJet 3si:
 | |
| # Installed in /usr/local/libexec/hprf
 | |
| #
 | |
| 
 | |
| printf "\033&k2G" && fpr && printf "\f" && exit 0
 | |
| exit 2
 | |
| </code>
 | |
| 	      And we will add this line to the <tt>/etc/printcap</tt>
 | |
| 	      for the printer <tt/teak/ to enable this filter:
 | |
| <tscreen><verb>
 | |
| 	:rf=/usr/local/libexec/hprf:
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      Here is one final, somewhat complex example.  We will add a
 | |
| 	      DVI filter to the LaserJet printer <tt/teak/ introduced
 | |
| 	      earlier.  First, the easy part: updating
 | |
| 	      <tt>/etc/printcap</tt> with the location of the DVI
 | |
| 	      filter:
 | |
| <tscreen><verb>
 | |
| 	:df=/usr/local/libexec/hpdf:
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	      Now, for the hard part: making the filter.  For that, we
 | |
| 	      need a DVI-to-LaserJet/PCL conversion program.  The
 | |
| 	      FreeBSD ports collection (see <ref id="ports" name="The
 | |
| 	      Ports Collection">) has one: 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvi2xx"
 | |
| 	       name="dvi2xx"> is the name of
 | |
| 	      the package.  Installing this package gives us the
 | |
| 	      program we need, 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvilj2p"
 | |
| 	       name="dvilj2p">, which converts DVI into
 | |
| 	      LaserJet IIp, LaserJet III, and LaserJet 2000 compatible
 | |
| 	      codes.
 | |
| 
 | |
| 	      
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvilj2p"
 | |
| 	       name="dvilj2p"> makes the filter <tt/hpdf/ quite complex
 | |
| 	      since 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvilj2p"
 | |
| 	       name="dvilj2p"> cannot read from standard input.  It
 | |
| 	      wants to work with a filename.  What is worse, the
 | |
| 	      filename has to end in <tt/.dvi/ so using
 | |
| 	      <tt>/dev/fd/0</tt> for standard input is problematic.
 | |
| 	      We can get around that problem by linking (symbolically)
 | |
| 	      a temporary file name (one that ends in <tt/.dvi/) to
 | |
| 	      <tt>/dev/fd/0</tt>, thereby forcing 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvilj2p"
 | |
| 	       name="dvilj2p"> to read
 | |
| 	      from standard input.
 | |
| 
 | |
| 	      The only other fly in the ointment is the fact that we
 | |
| 	      cannot use /tmp for the temporary link.  Symbolic links
 | |
| 	      are owned by user and group <tt/bin/.  The filter runs
 | |
| 	      as user <tt/daemon/.  And the <tt>/tmp</tt> directory
 | |
| 	      has the sticky bit set.  The filter can create the link,
 | |
| 	      but it will not be able clean up when done and remove it
 | |
| 	      since the link will belong to a different user.
 | |
| 
 | |
| 	      Instead, the filter will make the symbolic link in the
 | |
| 	      current working directory, which is the spooling
 | |
| 	      directory (specified by the <tt/sd/ capability in
 | |
| 	      <tt>/etc/printcap</tt>).  This is a perfect place for
 | |
| 	      filters to do their work, especially since there is
 | |
| 	      (sometimes) more free disk space in the spooling directory
 | |
| 	      than under <tt>/tmp</tt>.
 | |
| 
 | |
| 	      Here, finally, is the filter:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  hpdf - Print DVI data on HP/PCL printer
 | |
| #  Installed in /usr/local/libexec/hpdf
 | |
| 
 | |
| PATH=/usr/local/bin:$PATH; export PATH
 | |
| 
 | |
| #
 | |
| #  Define a function to clean up our temporary files.  These exist
 | |
| #  in the current directory, which will be the spooling directory
 | |
| #  for the printer.
 | |
| #
 | |
| cleanup() {
 | |
|    rm -f hpdf$$.dvi
 | |
| }
 | |
| 
 | |
| #
 | |
| #  Define a function to handle fatal errors: print the given message
 | |
| #  and exit 2.  Exiting with 2 tells LPD to do not try to reprint the
 | |
| #  job.
 | |
| #
 | |
| fatal() {
 | |
|     echo "$@" 1>&2
 | |
|     cleanup
 | |
|     exit 2
 | |
| }
 | |
| 
 | |
| #
 | |
| #  If user removes the job, LPD will send SIGINT, so trap SIGINT
 | |
| #  (and a few other signals) to clean up after ourselves.
 | |
| #
 | |
| trap cleanup 1 2 15 
 | |
| 
 | |
| #
 | |
| #  Make sure we are not colliding with any existing files.
 | |
| #
 | |
| cleanup
 | |
| 
 | |
| #
 | |
| #  Link the DVI input file to standard input (the file to print).
 | |
| #
 | |
| ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0"
 | |
| 
 | |
| #
 | |
| #  Make LF = CR+LF
 | |
| #
 | |
| printf "\033&k2G" || fatal "Cannot initialize printer"
 | |
| 
 | |
| # 
 | |
| #  Convert and print.  Return value from dvilj2p does not seem to be
 | |
| #  reliable, so we ignore it.
 | |
| #
 | |
| dvilj2p -M1 -q -e- dfhp$$.dvi
 | |
| 
 | |
| #
 | |
| #  Clean up and exit
 | |
| #
 | |
| cleanup
 | |
| exit 0
 | |
| </code>
 | |
| 
 | |
| 	  <sect3><heading>Automated Conversion: An Alternative To Conversion Filters
 | |
| 	      <label id="printing:advanced:autoconv"></heading>
 | |
| 
 | |
| 	    <p> All these conversion filters accomplish a lot for your
 | |
| 	      printing environment, but at the cost forcing the user
 | |
| 	      to specify (on the 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	       name="lpr"> command line) which one to
 | |
| 	      use.  If your users are not particularly computer
 | |
| 	      literate, having to specify a filter option will become
 | |
| 	      annoying.  What is worse, though, is that an incorrectly
 | |
| 	      specified filter option may run a filter on the wrong
 | |
| 	      type of file and cause your printer to spew out hundreds
 | |
| 	      of sheets of paper.
 | |
| 
 | |
| 	      Rather than install conversion filters at all, you might
 | |
| 	      want to try having the text filter (since it is the
 | |
| 	      default filter) detect the type of file it has been asked to
 | |
| 	      print and then automatically run the right conversion
 | |
| 	      filter.  Tools such as <tt/file/ can be of help here.
 | |
| 	      Of course, it will be hard to determine the differences
 | |
| 	      between <em/some/ file types---and, of course, you can
 | |
| 	      still provide conversion filters just for them.
 | |
| 
 | |
| 	      The FreeBSD ports collection has a text filter that
 | |
| 	      performs automatic conversion called 
 | |
| 	      <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=apsfilter"
 | |
| 	       name="apsfilter">. It
 | |
| 	      can detect plain text, PostScript, and DVI files, run
 | |
| 	      the proper conversions, and print.
 | |
| 
 | |
| 	<sect2><heading>Output Filters<label
 | |
| 	      id="printing:advanced:of"></heading>
 | |
| 	  
 | |
| 	  <p> The LPD spooling system supports one other type of
 | |
| 	    filter that we have not yet explored: an output filter.  An
 | |
| 	    output filter is intended for printing plain text only,
 | |
| 	    like the text filter, but with many simplifications.  If
 | |
| 	    you are using an output filter but no text filter, then
 | |
| 	    <itemize>
 | |
| 	      <item>LPD starts an output filter once for the entire
 | |
| 		job instead of once for each file in the job.
 | |
| 
 | |
| 	      <item>LPD does not make any provision to identify the
 | |
| 		start or the end of files within the job for the
 | |
| 		output filter.
 | |
| 
 | |
| 	      <item>LPD does not pass the user's login or host to
 | |
| 		the filter, so it is not intended to do accounting.  In
 | |
| 		fact, it gets only two arguments:
 | |
| <tscreen>
 | |
| <tt>-w<it/width/ -l<it/length/</tt>
 | |
| </tscreen>
 | |
| 		where <it/width/ is from the <tt/pw/ capability and
 | |
| 		<it/length/ is from the <tt/pl/ capability for the
 | |
| 		printer in question.
 | |
| 	    </itemize>
 | |
| 
 | |
| 	    Do not be seduced by an output filter's simplicity.  If
 | |
| 	    you would like each file in a job to start on a different page
 | |
| 	    an output filter <em/will not work/.  Use a text filter (also
 | |
| 	    known as an input filter); see section <ref
 | |
| 	    id="printing:textfilter" name="Installing the Text
 | |
| 	    Filter">.  Furthermore, an output filter is actually
 | |
| 	    <em/more complex/ in that it has to examine the byte
 | |
| 	    stream being sent to it for special flag characters and
 | |
| 	    must send signals to itself on behalf of LPD.
 | |
| 
 | |
| 	    However, an output filter is <em/necessary/ if you want
 | |
| 	    header pages and need to send escape sequences or other
 | |
| 	    initialization strings to be able to print the header
 | |
| 	    page.  (But it is also <em/futile/ if you want to charge
 | |
| 	    header pages to the requesting user's account, since LPD
 | |
| 	    does not give any user or host information to the output
 | |
| 	    filter.)
 | |
| 
 | |
| 	    On a single printer, LPD allows both an output filter and
 | |
| 	    text or other filters.  In such cases, LPD will start the
 | |
| 	    output filter to print the header page (see section <ref
 | |
| 	    id="printing:advanced:header-pages" name="Header Pages">)
 | |
| 	    only.  LPD then expects the output filter to <em/stop
 | |
| 	    itself/ by sending two bytes to the filter: ASCII 031
 | |
| 	    followed by ASCII 001.  When an output filter sees these
 | |
| 	    two bytes (031, 001), it should stop by sending SIGSTOP to
 | |
| 	    itself.  When LPD's done running other filters, it will
 | |
| 	    restart the output filter by sending SIGCONT to it.
 | |
| 
 | |
| 	    If there is an output filter but <em/no/ text filter and
 | |
| 	    LPD is working on a plain text job, LPD uses the output
 | |
| 	    filter to do the job.  As stated before, the output filter
 | |
| 	    will print each file of the job in sequence with no
 | |
| 	    intervening form feeds or other paper advancement, and
 | |
| 	    this is probably <em/not/ what you want.  In almost all
 | |
| 	    cases, you need a text filter.
 | |
| 
 | |
| 	    The program <tt/lpf/, which we introduced earlier as a text
 | |
| 	    filter, can also run as an output filter.  If you need a
 | |
| 	    quick-and-dirty output filter but do not want to write the
 | |
| 	    byte detection and signal sending code, try <tt/lpf/.  You
 | |
| 	    can also wrap <tt/lpf/ in a shell script to handle any
 | |
| 	    initialization codes the printer might require.
 | |
| 
 | |
| 	<sect2><heading><tt/lpf/: a Text Filter<label
 | |
| 	      id="printing:advanced:lpf"></heading>
 | |
| 
 | |
| 	  <p> The program <tt>/usr/libexec/lpr/lpf</tt> that comes
 | |
| 	    with FreeBSD binary distribution is a text filter (input
 | |
| 	    filter) that can indent output (job submitted with <tt/lpr
 | |
| 	    -i/), allow literal characters to pass (job submitted with
 | |
| 	    <tt/lpr -l/), adjust the printing position for backspaces
 | |
| 	    and tabs in the job, and account for pages printed.  It
 | |
| 	    can also act like an output filter.
 | |
| 
 | |
| 	    <tt/lpf/ is suitable for many printing environments.  And
 | |
| 	    although it has no capability to send initialization
 | |
| 	    sequences to a printer, it is easy to write a shell script
 | |
| 	    to do the needed initialization and then execute <tt/lpf/.
 | |
| 
 | |
| 	    In order for <tt/lpf/ to do page accounting correctly, it
 | |
| 	    needs correct values filled in for the <tt/pw/ and <tt/pl/
 | |
| 	    capabilities in the <tt>/etc/printcap</tt> file.  It uses
 | |
| 	    these values to determine how much text can fit on a page
 | |
| 	    and how many pages were in a user's job.  For more
 | |
| 	    information on printer accounting, see <ref
 | |
| 	    id="printing:advanced:acct" name="Accounting for Printer
 | |
| 	    Usage">.
 | |
| 
 | |
|       <sect1><heading>Header Pages<label
 | |
| 	    id="printing:advanced:header-pages"></heading>
 | |
| 
 | |
| 	<p> If you have <em/lots/ of users, all of them using
 | |
| 	  various printers, then you probably want to consider
 | |
| 	  <em/header pages/ as a necessary evil.
 | |
| 
 | |
| 	  Header pages, also known as <em/banner/ or <em/burst pages/
 | |
| 	  identify to whom jobs belong after they are printed.  They are
 | |
| 	  usually printed in large, bold letters, perhaps with
 | |
| 	  decorative borders, so that in a stack of printouts they
 | |
| 	  stand out from the real documents that comprise users' jobs.
 | |
| 	  They enable users to locate their jobs quickly.  The obvious
 | |
| 	  drawback to a header page is that it is yet one more sheet
 | |
| 	  that has to be printed for every job, their ephemeral
 | |
| 	  usefulness lasting not more than a few minutes, ultimately
 | |
| 	  finding themselves in a recycling bin or rubbish heap.
 | |
| 	  (Note that header pages go with each job, not each file in a
 | |
| 	  job, so the paper waste might not be that bad.)
 | |
| 
 | |
| 	  The LPD system can provide header pages automatically for
 | |
| 	  your printouts <em/if/ your printer can directly print plain
 | |
| 	  text.  If you have a PostScript printer, you will need an
 | |
| 	  external program to generate the header page; see <ref
 | |
| 	  id="printing:advanced:header-pages:ps" name="Header Pages on
 | |
| 	  PostScript Printers">.
 | |
| 
 | |
| 	<sect2><heading>Enabling Header Pages<label
 | |
| 	      id="printing:advanced:header-pages:enabling"></heading>
 | |
| 
 | |
| 	  <p> In the <ref id="printing:simple" name="Simple Printer
 | |
| 	      Setup">, we turned off header pages by specifying
 | |
| 	    <tt/sh/ (meaning ``suppress header'') in the
 | |
| 	    <tt>/etc/printcap</tt> file.  To enable header pages for
 | |
| 	    a printer, just remove the <tt/sh/ capability.
 | |
| 
 | |
| 	    Sounds too easy, right?
 | |
| 
 | |
| 	    You are right.  You <em/might/ have to provide an output
 | |
| 	    filter to send initialization strings to the printer.
 | |
| 	    Here is an example output filter for Hewlett Packard
 | |
| 	    PCL-compatible printers:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  hpof - Output filter for Hewlett Packard PCL-compatible printers
 | |
| #  Installed in /usr/local/libexec/hpof
 | |
| 
 | |
| 
 | |
| printf "\033&k2G" || exit 2
 | |
| exec /usr/libexec/lpr/lpf
 | |
| </code>
 | |
| 	    Specify the path to the output filter in the <tt/of/
 | |
| 	    capability.  See <ref id="printing:advanced:of"
 | |
| 	    name="Output Filters"> for more information.
 | |
| 
 | |
| 	    Here is an example <tt>/etc/printcap</tt> file for the printer
 | |
| 	    <tt/teak/ that we introduced earlier; we enabled header
 | |
| 	    pages and added the above output filter:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host orchid
 | |
| #
 | |
| teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
 | |
| 	:lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\
 | |
| 	:if=/usr/local/libexec/hpif:\
 | |
| 	:vf=/usr/local/libexec/hpvf:\
 | |
| 	:of=/usr/local/libexec/hpof:
 | |
| </code>
 | |
| 	    Now, when users print jobs to <tt/teak/, they get a header
 | |
| 	    page with each job.  If users want to spend time searching
 | |
| 	    for their printouts, they can suppress header pages by
 | |
| 	    submitting the job with <tt/lpr -h/; see <ref
 | |
| 	    id="printing:lpr:options:misc" name="Header Page Options">
 | |
| 	    for more 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	     name="lpr"> options.
 | |
| 
 | |
| 	    <tt/Note:/ LPD prints a form feed character after the
 | |
| 	    header page.  If your printer uses a different character
 | |
| 	    or sequence of characters to eject a page, specify them
 | |
| 	    with the <tt/ff/ capability in <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 	<sect2><heading>Controlling Header Pages<label
 | |
| 	      id="printing:advanced:header-pages:controlling"></heading>
 | |
| 
 | |
| 	  <p> By enabling header pages, LPD will produce a <em/long
 | |
| 	      header/, a full page of large letters identifying the
 | |
| 	    user, host, and job.  Here is an example (kelly printed
 | |
| 	    the job named outline from host rose):
 | |
| <tscreen><verb>
 | |
| k                   ll       ll
 | |
| k                    l        l
 | |
| k                    l        l
 | |
| k   k     eeee       l        l     y    y
 | |
| k  k     e    e      l        l     y    y
 | |
| k k      eeeeee      l        l     y    y
 | |
| kk k     e           l        l     y    y
 | |
| k   k    e    e      l        l     y   yy
 | |
| k    k    eeee      lll      lll     yyy y
 | |
|                                          y
 | |
|                                     y    y
 | |
|                                      yyyy
 | |
| 
 | |
| 
 | |
|                              ll
 | |
|                     t         l        i
 | |
|                     t         l
 | |
|  oooo    u    u   ttttt       l       ii     n nnn     eeee
 | |
| o    o   u    u     t         l        i     nn   n   e    e
 | |
| o    o   u    u     t         l        i     n    n   eeeeee
 | |
| o    o   u    u     t         l        i     n    n   e
 | |
| o    o   u   uu     t  t      l        i     n    n   e    e
 | |
|  oooo     uuu u      tt      lll      iii    n    n    eeee
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| r rrr     oooo     ssss     eeee
 | |
| rr   r   o    o   s    s   e    e
 | |
| r        o    o    ss      eeeeee
 | |
| r        o    o      ss    e
 | |
| r        o    o   s    s   e    e
 | |
| r         oooo     ssss     eeee
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 					Job:  outline
 | |
| 					Date: Sun Sep 17 11:04:58 1995
 | |
| </verb></tscreen>
 | |
| 	    LPD appends a form feed after this text so the job starts
 | |
| 	    on a new page (unless you have <tt/sf/ (suppress form
 | |
| 	    feeds) in the destination printer's entry in
 | |
| 	    <tt>/etc/printcap</tt>).
 | |
| 
 | |
| 	    If you prefer, LPD can make a <em/short header/; specify
 | |
| 	    <tt/sb/ (short banner) in the <tt>/etc/printcap</tt> file.
 | |
| 	    The header page will look like this:
 | |
| <tscreen><verb>
 | |
| rose:kelly  Job: outline  Date: Sun Sep 17 11:07:51 1995
 | |
| </verb></tscreen>
 | |
| 	    Also by default, LPD prints the header page first, then
 | |
| 	    the job.  To reverse that, specify <tt/hl/ (header last)
 | |
| 	    in <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 	<sect2><heading>Accounting for Header Pages<label
 | |
| 	      id="printing:advanced:header-pages:accounting"></heading>
 | |
| 
 | |
| 	  <p> Using LPD's built-in header pages enforces a particular
 | |
| 	    paradigm when it comes to printer accounting: header pages
 | |
| 	    must be <em/free of charge/.
 | |
| 
 | |
| 	    Why?
 | |
| 
 | |
| 	    Because the output filter is the only external program
 | |
| 	    that will have control when the header page is printed
 | |
| 	    that could do accounting, and it is not provided with any
 | |
| 	    <em/user or host/ information or an accounting file, so it
 | |
| 	    has no idea whom to charge for printer use.  It is also not
 | |
| 	    enough to just ``add one page'' to the text filter or any
 | |
| 	    of the conversion filters (which do have user and host
 | |
| 	    information) since users can suppress header pages with
 | |
| 	    <tt/lpr -h/.  They could still be charged for header pages
 | |
| 	    they did not print.  Basically, <tt/lpr -h/ will be the
 | |
| 	    preferred option of environmentally-minded users, but you
 | |
| 	    cannot offer any incentive to use it.
 | |
| 
 | |
| 	    It is <em/still not enough/ to have each of the filters
 | |
| 	    generate their own header pages (thereby being able to
 | |
| 	    charge for them).  If users wanted the option of
 | |
| 	    suppressing the header pages with <tt/lpr -h/, they will
 | |
| 	    still get them and be charged for them since LPD does not
 | |
| 	    pass any knowledge of the <tt/-h/ option to any of the
 | |
| 	    filters.
 | |
| 
 | |
| 	    So, what are your options?
 | |
| 
 | |
| 	    You can
 | |
| 	    <itemize>
 | |
| 	      <item>Accept LPD's paradigm and make header pages free.
 | |
| 
 | |
| 	      <item>Install an alternative to LPD, such as LPDng or
 | |
| 		PLP.  Section <ref name="Alternatives to the Standard
 | |
| 		Spooler" id="printing:lpd-alternatives"> tells more
 | |
| 		about other spooling software you can substitute for
 | |
| 		LPD.
 | |
| 
 | |
| 	      <item>Write a <em/smart/ output filter.  Normally, an
 | |
| 		output filter is not meant to do anything more than
 | |
| 		initialize a printer or do some simple character
 | |
| 		conversion.  It is suited for header pages and plain
 | |
| 		text jobs (when there is no text (input) filter).
 | |
| 
 | |
| 		But, if there is a text filter for the plain text
 | |
| 		jobs, then LPD will start the output filter only for
 | |
| 		the header pages.  And the output filter can parse the
 | |
| 		header page text that LPD generates to determine what
 | |
| 		user and host to charge for the header page.  The only
 | |
| 		other problem with this method is that the output
 | |
| 		filter still does not know what accounting file to use
 | |
| 		(it is not passed the name of the file from the <tt/af/
 | |
| 		capability), but if you have a well-known accounting
 | |
| 		file, you can hard-code that into the output filter.
 | |
| 
 | |
| 		To facilitate the parsing step, use the <tt/sh/ (short
 | |
| 		header) capability in <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 		Then again, all that might be too much trouble, and
 | |
| 		users will certainly appreciate the more generous
 | |
| 		system administrator who makes header pages free.
 | |
| 	    </itemize>
 | |
| 
 | |
| 	<sect2><heading>Header Pages on PostScript Printers<label
 | |
| 	      id="printing:advanced:header-pages:ps"></heading>
 | |
| 
 | |
| 	  <p> As described above, LPD can generate a plain text header
 | |
| 	    page suitable for many printers.  Of course, PostScript
 | |
| 	    cannot directly print plain text, so the header page
 | |
| 	    feature of LPD is useless---or mostly so.
 | |
| 
 | |
| 	    One obvious way to get header pages is to have every
 | |
| 	    conversion filter and the text filter generate the header
 | |
| 	    page.  The filters should should use the user and host
 | |
| 	    arguments to generate a suitable header page.  The
 | |
| 	    drawback of this method is that users will always get a
 | |
| 	    header page, even if they submit jobs with <tt/lpr -h/.
 | |
| 
 | |
| 	    Let us explore this method.  The following script takes
 | |
| 	    three arguments (user login name, host name, and job name)
 | |
| 	    and makes a simple PostScript header page:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  make-ps-header - make a PostScript header page on stdout
 | |
| #  Installed in /usr/local/libexec/make-ps-header
 | |
| #
 | |
| 
 | |
| #
 | |
| #  These are PostScript units (72 to the inch).  Modify for A4 or
 | |
| #  whatever size paper you are using:
 | |
| #
 | |
| page_width=612
 | |
| page_height=792
 | |
| border=72
 | |
| 
 | |
| #
 | |
| #  Check arguments
 | |
| #
 | |
| if [ $# -ne 3 ]; then
 | |
|     echo "Usage: `basename $0` <user> <host> <job>" 1>&2
 | |
|     exit 1
 | |
| fi
 | |
| 
 | |
| #
 | |
| #  Save these, mostly for readability in the PostScript, below.
 | |
| #
 | |
| user=$1
 | |
| host=$2
 | |
| job=$3
 | |
| date=`date`
 | |
| 
 | |
| #
 | |
| #  Send the PostScript code to stdout.
 | |
| #
 | |
| exec cat <<EOF
 | |
| %!PS
 | |
| 
 | |
| %
 | |
| %  Make sure we do not interfere with user's job that will follow
 | |
| %
 | |
| save
 | |
| 
 | |
| %
 | |
| %  Make a thick, unpleasant border around the edge of the paper.
 | |
| %
 | |
| $border $border moveto
 | |
| $page_width $border 2 mul sub 0 rlineto
 | |
| 0 $page_height $border 2 mul sub rlineto
 | |
| currentscreen 3 -1 roll pop 100 3 1 roll setscreen
 | |
| $border 2 mul $page_width sub 0 rlineto closepath
 | |
| 0.8 setgray 10 setlinewidth stroke 0 setgray
 | |
| 
 | |
| %
 | |
| %  Display user's login name, nice and large and prominent
 | |
| %
 | |
| /Helvetica-Bold findfont 64 scalefont setfont
 | |
| $page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto
 | |
| ($user) show
 | |
| 
 | |
| %
 | |
| %  Now show the boring particulars
 | |
| %
 | |
| /Helvetica findfont 14 scalefont setfont
 | |
| /y 200 def
 | |
| [ (Job:) (Host:) (Date:) ] {
 | |
| 	200 y moveto show /y y 18 sub def
 | |
| } forall
 | |
| 
 | |
| /Helvetica-Bold findfont 14 scalefont setfont
 | |
| /y 200 def
 | |
| [ ($job) ($host) ($date) ] {
 | |
| 	270 y moveto show /y y 18 sub def
 | |
| } forall
 | |
| 
 | |
| %
 | |
| %  That is it
 | |
| %
 | |
| restore
 | |
| showpage
 | |
| EOF
 | |
| </code>
 | |
| 	    Now, each of the conversion filters and the text filter
 | |
| 	    can call this script to first generate the header page,
 | |
| 	    and then print the user's job.  Here is the DVI conversion
 | |
| 	    filter from earlier in this document, modified to make a
 | |
| 	    header page:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  psdf - DVI to PostScript printer filter
 | |
| #  Installed in /usr/local/libexec/psdf
 | |
| #
 | |
| #  Invoked by lpd when user runs lpr -d
 | |
| #
 | |
| 
 | |
| orig_args="$@"
 | |
| 
 | |
| fail() {
 | |
|     echo "$@" 1>&2
 | |
|     exit 2
 | |
| }
 | |
| 
 | |
| while getopts "x:y:n:h:" option; do
 | |
|     case $option in
 | |
|         x|y)  ;; # Ignore
 | |
| 	n)    login=$OPTARG ;;
 | |
| 	h)    host=$OPTARG ;; 
 | |
| 	*)    echo "LPD started `basename $0` wrong." 1>&2
 | |
|               exit 2
 | |
|               ;;
 | |
|     esac
 | |
| done
 | |
| 
 | |
| [ "$login" ] || fail "No login name"
 | |
| [ "$host" ] || fail "No host name"
 | |
| 
 | |
| ( /usr/local/libexec/make-ps-header $login $host "DVI File"
 | |
|   /usr/local/bin/dvips -f ) | eval /usr/local/libexec/lprps $orig_args
 | |
| </code>
 | |
| 	    Notice how the filter has to parse the argument list in
 | |
| 	    order to determine the user and host name.  The parsing
 | |
| 	    for the other conversion filters is identical.  The text
 | |
| 	    filter takes a slightly different set of arguments, though
 | |
| 	    (see section <ref id="printing:advanced:filters" name="How
 | |
| 	    Filters Work">).
 | |
| 
 | |
| 	    As we have mentioned before, the above scheme, though fairly
 | |
| 	    simple, disables the ``suppress header page'' option (the
 | |
| 	    <tt/-h/ option) to <tt/lpr/.  If users wanted to save a
 | |
| 	    tree (or a few pennies, if you charge for header pages),
 | |
| 	    they would not be able to do so, since every filter's going
 | |
| 	    to print a header page with every job.
 | |
| 
 | |
| 	    To allow users to shut off header pages on a per-job
 | |
| 	    basis, you will need to use the trick introduced in section
 | |
| 	    <ref id="printing:advanced:header-pages:accounting"
 | |
| 	    name="Accounting for Header Pages">: write an output
 | |
| 	    filter that parses the LPD-generated header page and
 | |
| 	    produces a PostScript version.  If the user submits the
 | |
| 	    job with <tt/lpr -h/, then LPD will not generate a header
 | |
| 	    page, and neither will your output filter.  Otherwise,
 | |
| 	    your output filter will read the text from LPD and send
 | |
| 	    the appropriate header page PostScript code to the
 | |
| 	    printer.
 | |
| 
 | |
| 	    If you have a PostScript printer on a serial line, you
 | |
| 	    can make use of <tt/lprps/, which comes with an output
 | |
| 	    filter, <tt/psof/, which does the above.  Note that
 | |
| 	    <tt/psof/ does not charge for header pages.
 | |
| 
 | |
|       <sect1><heading>Networked Printing<label
 | |
| 	    id="printing:advanced:network-printers"></heading>
 | |
| 
 | |
| 	<p> FreeBSD supports networked printing: sending jobs to
 | |
| 	  remote printers.  Networked printing generally refers to two
 | |
| 	  different things:
 | |
| 	  <itemize>
 | |
| 	    <item>Accessing a printer attached to a remote host.  You
 | |
| 	      install a printer that has a conventional serial or
 | |
| 	      parallel interface on one host.  Then, you set up LPD to
 | |
| 	      enable access to the printer from other hosts on the
 | |
| 	      network.  Section <ref id="printing:advanced:network:rm"
 | |
| 	      name="Printers Installed on Remote Hosts"> tells how to
 | |
| 	      do this.
 | |
| 
 | |
| 	      <item>Accessing a printer attached directly to a network.
 | |
| 		The printer has a network interface in addition (or in
 | |
| 		place of) a more conventional serial or parallel
 | |
| 		interface.  Such a printer might work as follows:
 | |
| 
 | |
| 	      <itemize>
 | |
| 		<item>It might understand the LPD protocol and can
 | |
| 		  even queue jobs from remote hosts.  In this case, it
 | |
| 		  acts just like a regular host running LPD.  Follow
 | |
| 		  the same procedure in section <ref
 | |
| 		  id="printing:advanced:network:rm" name="Printers
 | |
| 		  Installed on Remote Hosts"> to set up such a
 | |
| 		  printer.
 | |
| 
 | |
| 		<item>It might support a data stream network
 | |
| 		  connection.  In this case, you ``attach'' the
 | |
| 		  printer to one host on the network by making that
 | |
| 		  host responsible for spooling jobs and sending them
 | |
| 		  to the printer.  Section <ref
 | |
| 		  id="printing:advanced:network:net-if" name="Printers
 | |
| 		  with Networked Data Stream Interfaces"> gives some
 | |
| 		  suggestions on installing such printers.
 | |
| 	      </itemize>
 | |
| 	  </itemize>
 | |
| 
 | |
| 	<sect2><heading>Printers Installed on Remote Hosts<label
 | |
| 	      id="printing:advanced:network:rm"></heading>
 | |
| 
 | |
| 	  <p> The LPD spooling system has built-in support for sending
 | |
| 	    jobs to other hosts also running LPD (or are compatible
 | |
| 	    with LPD).  This feature enables you to install a printer
 | |
| 	    on one host and make it accessible from other hosts.  It
 | |
| 	    also works with printers that have network interfaces that
 | |
| 	    understand the LPD protocol.  
 | |
| 
 | |
| 	    To enable this kind of remote printing, first install a
 | |
| 	    printer on one host, the <em/printer host/, using the
 | |
| 	    simple printer setup described in <ref
 | |
| 	    id="printing:simple" name="Simple Printer Setup">.  Do any
 | |
| 	    advanced setup in <ref id="printing:advanced"
 | |
| 	    name="Advanced Printer Setup"> that you need.  Make sure
 | |
| 	    to test the printer and see if it works with the features
 | |
| 	    of LPD you have enabled.
 | |
| 
 | |
| 	    If you are using a printer with a network interface that is
 | |
| 	    compatible with LPD, then the <em/printer host/ in the
 | |
| 	    discussion below is the printer itself, and the
 | |
| 	    <em/printer name/ is the name you configured for the
 | |
| 	    printer.  See the documentation that accompanied your
 | |
| 	    printer and/or printer-network interface.
 | |
| 
 | |
| 	    Then, on the other hosts you want to have access to the
 | |
| 	    printer, make an entry in their <tt>/etc/printcap</tt>
 | |
| 	    files with the following:
 | |
| 	    <enum>
 | |
| 	      <item>Name the entry anything you want.  For
 | |
| 		simplicity, though, you probably want to use the same
 | |
| 		name and aliases as on the printer host.
 | |
| 
 | |
| 	      <item>Leave the <tt/lp/ capability blank, explicitly
 | |
| 		(<tt/:lp=:/).
 | |
| 
 | |
| 	      <item>Make a spooling directory and specify its
 | |
| 		location in the <tt/sd/ capability.  LPD will store
 | |
| 		jobs here before they get sent to the printer host.
 | |
| 
 | |
| 	      <item>Place the name of the printer host in the <tt/rm/
 | |
| 		capability.
 | |
| 
 | |
| 	      <item>Place the printer name on the <em/printer host/ in
 | |
| 		the <tt/rp/ capability.
 | |
| 	    </enum>
 | |
| 	    That is it.  You do not need to list conversion filters,
 | |
| 	    page dimensions, or anything else in the
 | |
| 	    <tt>/etc/printcap</tt> file.
 | |
| 
 | |
| 	    Here is an example.  The host rose has two printers,
 | |
| 	    <tt/bamboo/ and <tt/rattan/.  We will enable users on the
 | |
| 	    host orchid to print to those printers.  Here is the
 | |
| 	    <tt>/etc/printcap</tt> file for orchid (back from section
 | |
| 	    <ref id="printing:advanced:header-pages:enabling"
 | |
| 	    name="Enabling Header Pages">).  It already had the entry
 | |
| 	    for the printer <tt/teak/; we have added entries for the two
 | |
| 	    printers on the host rose:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host orchid - added (remote) printers on rose
 | |
| #
 | |
| 
 | |
| #
 | |
| #  teak is local; it is connected directly to orchid:
 | |
| #
 | |
| teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
 | |
| 	:lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\
 | |
| 	:if=/usr/local/libexec/ifhp:\
 | |
| 	:vf=/usr/local/libexec/vfhp:\
 | |
| 	:of=/usr/local/libexec/ofhp:
 | |
| 
 | |
| #
 | |
| #  rattan is connected to rose; send jobs for rattan to rose:
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan:
 | |
| 
 | |
| #
 | |
| #  bamboo is connected to rose as well:
 | |
| #
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:
 | |
| </code>
 | |
| 	    Then, we just need to make spooling directories on orchid:
 | |
| <tscreen><verb>
 | |
| mkdir -p /var/spool/lpd/rattan /var/spool/lpd/bamboo
 | |
| chmod 770 /var/spool/lpd/rattan /var/spool/lpd/bamboo
 | |
| chown daemon.daemon /var/spool/lpd/rattan /var/spool/lpd/bamboo
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	    Now, users on orchid can print to <tt/rattan/ and
 | |
| 	    <tt/bamboo/.  If, for example, a user on orchid typed
 | |
| <tscreen><verb>
 | |
| lpr -P bamboo -d sushi-review.dvi
 | |
| </verb></tscreen>
 | |
| 	    the LPD system on orchid would copy the job to the
 | |
| 	    spooling directory <tt>/var/spool/lpd/bamboo</tt> and note
 | |
| 	    that it was a DVI job.  As soon as the host rose has room
 | |
| 	    in its <tt/bamboo/ spooling directory, the two
 | |
| 	    LPDs would transfer the file to rose.  The file would wait
 | |
| 	    in rose's queue until it was finally printed.  It would be
 | |
| 	    converted from DVI to PostScript (since bamboo is a
 | |
| 	    PostScript printer) on rose.
 | |
| 
 | |
| 	<sect2><heading>Printers with Networked Data Stream Interfaces<label
 | |
| 	      id="printing:advanced:network:net-if"></heading>
 | |
| 
 | |
| 	  <p> Often, when you buy a network interface card for a
 | |
| 	    printer, you can get two versions: one which emulates a
 | |
| 	    spooler (the more expensive version), or one which just
 | |
| 	    lets you send data to it as if you were using a serial or
 | |
| 	    parallel port (the cheaper version).  This section tells
 | |
| 	    how to use the cheaper version.  For the more expensive
 | |
| 	    one, see the previous section <ref name="Printers
 | |
| 	    Installed on Remote Hosts" id="printing:advanced:network:rm">.
 | |
| 
 | |
| 	    The format of the <tt>/etc/printcap</tt> file lets you
 | |
| 	    specify what serial or parallel interface to use, and (if
 | |
| 	    you are using a serial interface), what baud rate, whether
 | |
| 	    to use flow control, delays for tabs, conversion of
 | |
| 	    newlines, and more.  But there is no way to specify a
 | |
| 	    connection to a printer that is listening on a TCP/IP or
 | |
| 	    other network port.
 | |
| 
 | |
| 	    To send data to a networked printer, you need to develop a
 | |
| 	    communications program that can be called by the text and
 | |
| 	    conversion filters.  Here is one such example: the script
 | |
| 	    <tt/netprint/ takes all data on standard input and sends
 | |
| 	    it to a network-attached printer.  We specify the hostname
 | |
| 	    of the printer as the first argument and the port number
 | |
| 	    to which to connect as the second argument to
 | |
| 	    <tt/netprint/.  Note that this supports one-way
 | |
| 	    communication only (FreeBSD to printer); many network
 | |
| 	    printers support two-way communication, and you might want
 | |
| 	    to take advantage of that (to get printer status, perform
 | |
| 	    accounting, etc.).
 | |
| <code>
 | |
| #!/usr/bin/perl
 | |
| #
 | |
| #  netprint - Text filter for printer attached to network
 | |
| #  Installed in /usr/local/libexec/netprint
 | |
| #
 | |
| 
 | |
| $#ARGV eq 1 || die "Usage: $0 <printer-hostname> <port-number>";
 | |
| 
 | |
| $printer_host = $ARGV[0];
 | |
| $printer_port = $ARGV[1];
 | |
| 
 | |
| require 'sys/socket.ph';
 | |
| 
 | |
| ($ignore, $ignore, $protocol) = getprotobyname('tcp');
 | |
| ($ignore, $ignore, $ignore, $ignore, $address)
 | |
|     = gethostbyname($printer_host);
 | |
| 
 | |
| $sockaddr = pack('S n a4 x8', &AF_INET, $printer_port, $address);
 | |
| 
 | |
| socket(PRINTER, &PF_INET, &SOCK_STREAM, $protocol)
 | |
|     || die "Can't create TCP/IP stream socket: $!";
 | |
| connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!";
 | |
| while (<STDIN>) { print PRINTER; }
 | |
| exit 0;
 | |
| </code>
 | |
| 	    We can then use this script in various filters.  Suppose
 | |
| 	    we had a Diablo 750-N line printer connected to the
 | |
| 	    network.  The printer accepts data to print on port number
 | |
| 	    5100.  The host name of the printer is scrivener.  Here is
 | |
| 	    the text filter for the printer:
 | |
| <code>
 | |
| #!/bin/sh
 | |
| #
 | |
| #  diablo-if-net - Text filter for Diablo printer `scrivener' listening
 | |
| #  on port 5100.  Installed in /usr/local/libexec/diablo-if-net
 | |
| #
 | |
| 
 | |
| exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100
 | |
| </code>
 | |
| 
 | |
| 
 | |
|       <sect1><heading>Restricting Printer Usage<label
 | |
| 	    id="printing:advanced:restricting"></heading>
 | |
| 	
 | |
| 	<p> This section gives information on restricting printer
 | |
| 	  usage.  The LPD system lets you control who can access a
 | |
| 	  printer, both locally or remotely, whether they can print
 | |
| 	  multiple copies, how large their jobs can be, and how large
 | |
| 	  the printer queues can get.
 | |
| 
 | |
| 	<sect2><heading>Restricting Multiple Copies<label
 | |
| 	      id="printing:advanced:restricting:copies"></heading>
 | |
| 
 | |
| 	  <p> The LPD system makes it easy for users to print multiple
 | |
| 	    copies of a file.  Users can print jobs with <tt/lpr -#5/
 | |
| 	    (for example) and get five copies of each file in the job.
 | |
| 	    Whether this is a good thing is up to you.
 | |
| 
 | |
| 	    If you feel multiple copies cause unnecessary wear and
 | |
| 	    tear on your printers, you can disable the <tt/-#/ option
 | |
| 	    to 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	     name="lpr"> by adding the <tt/sc/ capability to the
 | |
| 	    <tt>/etc/printcap</tt> file.  When users submit jobs
 | |
| 	    with the <tt/-#/ option, they will see
 | |
| <tscreen><verb>
 | |
| lpr: multiple copies are not allowed
 | |
| </verb></tscreen>
 | |
| 
 | |
| 	    Note that if you have set up access to a printer remotely
 | |
| 	    (see section <ref name="Printers Installed on Remote
 | |
| 	    Hosts" id="printing:advanced:network:rm">), you need the
 | |
| 	    <tt/sc/ capability on the remote <tt>/etc/printcap</tt>
 | |
| 	    files as well, or else users will still be able to submit
 | |
| 	    multiple-copy jobs by using another host.
 | |
| 
 | |
| 	    Here is an example.  This is the <tt>/etc/printcap</tt>
 | |
| 	    file for the host rose.  The printer <tt/rattan/ is quite
 | |
| 	    hearty, so we will allow multiple copies, but the laser
 | |
| 	    printer <tt/bamboo/'s a bit more delicate, so we will
 | |
| 	    disable multiple copies by adding the <tt/sc/ capability:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - restrict multiple copies on bamboo
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:\
 | |
| 	:if=/usr/local/libexec/if-simple:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:sc:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\
 | |
| 	:if=/usr/local/libexec/psif:\
 | |
| 	:df=/usr/local/libexec/psdf:
 | |
| </code>
 | |
| 	    Now, we also need to add the <tt/sc/ capability on the
 | |
| 	    host orchid's <tt>/etc/printcap</tt> (and while we are at
 | |
| 	    it, let us disable multiple copies for the printer
 | |
| 	    <tt/teak/):
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host orchid - no multiple copies for local
 | |
| #  printer teak or remote printer bamboo
 | |
| 
 | |
| teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
 | |
| 	:lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:sc:\
 | |
| 	:if=/usr/local/libexec/ifhp:\
 | |
| 	:vf=/usr/local/libexec/vfhp:\
 | |
| 	:of=/usr/local/libexec/ofhp:
 | |
| 
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:sc:
 | |
| </code>
 | |
| 	    By using the <tt/sc/ capability, we prevent the use of
 | |
| 	    <tt/lpr -#/, but that still does not prevent users from
 | |
| 	    running 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?lpr"
 | |
| 	     name="lpr"> multiple times, or from submitting the
 | |
| 	    same file multiple times in one job like this:
 | |
| <tscreen><verb>
 | |
| lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign 
 | |
| </verb></tscreen>
 | |
| 	    There are many ways to prevent this abuse (including
 | |
| 	    ignoring it) which you are free to explore.
 | |
| 
 | |
| 	<sect2><heading>Restricting Access To Printers<label
 | |
| 	      id="printing:advanced:restricting:access"></heading>
 | |
| 
 | |
| 	  <p> You can control who can print to what printers by using
 | |
| 	    the UNIX group mechanism and the <tt/rg/ capability in
 | |
| 	    <tt>/etc/printcap</tt>.  Just place the users you want to
 | |
| 	    have access to a printer in a certain group, and then name
 | |
| 	    that group in the <tt/rg/ capability.
 | |
| 
 | |
| 	    Users outside the group (including root) will be greeted
 | |
| 	    with
 | |
| <tscreen><verb>
 | |
| lpr: Not a member of the restricted group
 | |
| </verb></tscreen>
 | |
| 	    if they try to print to the controlled printer.
 | |
| 
 | |
| 	    As with the <tt/sc/ (suppress multiple copies) capability,
 | |
| 	    you need to specify <tt/rg/ on remote hosts that also have
 | |
| 	    access to your printers, if you feel it is appropriate (see
 | |
| 	    section <ref name="Printers Installed on Remote Hosts"
 | |
| 	    id="printing:advanced:network:rm">).
 | |
| 
 | |
| 	    For example, we will let anyone access the printer
 | |
| 	    <tt/rattan/, but only those in group <tt/artists/ can use
 | |
| 	    <tt/bamboo/.  Here is the familiar <tt>/etc/printcap</tt>
 | |
| 	    for host rose:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose - restricted group for bamboo
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:\
 | |
| 	:if=/usr/local/libexec/if-simple:
 | |
| 
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\
 | |
| 	:if=/usr/local/libexec/psif:\
 | |
| 	:df=/usr/local/libexec/psdf:
 | |
| </code>
 | |
| 	    Let us leave the other example <tt>/etc/printcap</tt> file
 | |
| 	    (for the host orchid) alone.  Of course, anyone on orchid
 | |
| 	    can print to <tt/bamboo/.  It might be the case that we
 | |
| 	    only allow certain logins on orchid anyway, and want them
 | |
| 	    to have access to the printer.  Or not.
 | |
| 
 | |
| 	    <em/Note:/ there can be only one restricted group per
 | |
| 	    printer.
 | |
| 
 | |
| 	<sect2><heading>Controlling Sizes of Jobs Submitted<label
 | |
| 	      id="printing:advanced:restricting:sizes"></heading>
 | |
| 
 | |
| 	  <p> If you have many users accessing the printers, you
 | |
| 	    probably need to put an upper limit on the sizes of the
 | |
| 	    files users can submit to print.  After all, there is only
 | |
| 	    so much free space on the filesystem that houses the
 | |
| 	    spooling directories, and you also need to make sure
 | |
| 	    there is room for the jobs of other users.
 | |
| 
 | |
| 	    LPD enables you to limit the maximum byte size a file in a
 | |
| 	    job can be with the <tt/mx/ capability.  The units are in
 | |
| 	    BUFSIZ blocks, which are 1024 bytes.  If you put a zero
 | |
| 	    for this capability, there will be no limit on file size.
 | |
| 	    Note that the limit applies to <em/files/ in a job, and
 | |
| 	    <em/not/ the total job size.
 | |
| 
 | |
| 	    LPD will not refuse a file that is larger than the limit you
 | |
| 	    place on a printer.  Instead, it will queue as much of the
 | |
| 	    file up to the limit, which will then get printed.  The
 | |
| 	    rest will be discarded.  Whether this is correct behavior
 | |
| 	    is up for debate.
 | |
| 
 | |
| 	    Let us add limits to our example printers <tt/rattan/ and
 | |
| 	    <tt/bamboo/.  Since those artists' PostScript files tend
 | |
| 	    to be large, we will limit them to five megabytes.  We will
 | |
| 	    put no limit on the plain text line printer:
 | |
| <code>
 | |
| #
 | |
| #  /etc/printcap for host rose
 | |
| #
 | |
| 
 | |
| #
 | |
| #  No limit on job size:
 | |
| #
 | |
| rattan|line|diablo|lp|Diablo 630 Line Printer:\
 | |
| 	:sh:sd=/var/spool/lpd/rattan:\
 | |
| 	:lp=/dev/lpt0:\
 | |
| 	:if=/usr/local/libexec/if-simple:
 | |
| 
 | |
| #
 | |
| #  Limit of five megabytes:
 | |
| #
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\
 | |
| 	:if=/usr/local/libexec/psif:\
 | |
| 	:df=/usr/local/libexec/psdf:
 | |
| </code>
 | |
| 	    Again, the limits apply to the local users only.  If
 | |
| 	    you have set up access to your printers remotely, remote
 | |
| 	    users will not get those limits.  You will need to specify the
 | |
| 	    <tt/mx/ capability in the remote <tt>/etc/printcap</tt>
 | |
| 	    files as well.  See section <ref name="Printers Installed
 | |
| 	    on Remote Hosts" id="printing:advanced:network:rm"> for
 | |
| 	    more information on remote printing.
 | |
| 
 | |
| 	    There is another specialized way to limit job sizes from
 | |
| 	    remote printers; see section <ref
 | |
| 	    id="printing:advanced:restricting:remote"
 | |
| 	    name="Restricting Jobs from Remote Printers">.
 | |
| 
 | |
| 	<sect2><heading>Restricting Jobs from Remote Printers<label
 | |
| 	      id="printing:advanced:restricting:remote"></heading>
 | |
| 
 | |
| 	  <p> The LPD spooling system provides several ways to restrict
 | |
| 	    print jobs submitted from remote hosts:
 | |
| 
 | |
| 	    <descrip>
 | |
| 	      <tag/Host restrictions/
 | |
| 
 | |
| 		You can control from which remote hosts a local LPD
 | |
| 		accepts requests with the files
 | |
| 		<tt>/etc/hosts.equiv</tt> and <tt>/etc/hosts.lpd</tt>.
 | |
| 		LPD checks to see if an incoming request is from a
 | |
| 		host listed in either one of these files.  If not, LPD
 | |
| 		refuses the request.
 | |
| 
 | |
| 		The format of these files is simple: one host name per
 | |
| 		line.  Note that the file <tt>/etc/hosts.equiv</tt> is
 | |
| 		also used by the 
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?ruserok(3)"
 | |
| 		name="ruserok(3)"> protocol, and affects
 | |
| 		programs like 
 | |
| 		<htmlurl url="http://www.freebsd.org/cgi/man.cgi?rsh"
 | |
| 		 name="rsh"> and 
 | |
| 		 <htmlurl url="http://www.freebsd.org/cgi/man.cgi?rcp"
 | |
| 		  name="rcp">, so be careful.
 | |
| 
 | |
| 		For example, here is the <tt>/etc/hosts.lpd</tt> file
 | |
| 		on the host rose:
 | |
| <code>
 | |
| orchid
 | |
| violet
 | |
| madrigal.fishbaum.de
 | |
| </code>
 | |
| 		This means rose will accept requests from the hosts
 | |
| 		orchid, violet, and madrigal.fishbaum.de.  If any
 | |
| 		other host tries to access rose's LPD, LPD will
 | |
| 		refuse them.
 | |
| 
 | |
| 	      <tag/Size restrictions/
 | |
| 
 | |
| 		You can control how much free space there needs to
 | |
| 		remain on the filesystem where a spooling directory
 | |
| 		resides.  Make a file called <tt/minfree/ in the
 | |
| 		spooling directory for the local printer.  Insert in
 | |
| 		that file a number representing how many disk blocks
 | |
| 		(512 bytes) of free space there has to be for a remote
 | |
| 		job to be accepted.
 | |
| 
 | |
| 	        This lets you insure that remote users will not fill your
 | |
| 		filesystem.  You can also use it to give a certain
 | |
| 		priority to local users: they will be able to queue jobs
 | |
| 		long after the free disk space has fallen below the
 | |
| 		amount specified in the <tt/minfree/ file.
 | |
| 
 | |
| 	        For example, let us add a <tt/minfree/ file for the
 | |
| 		printer <tt/bamboo/.  We examine
 | |
| 		<tt>/etc/printcap</tt> to find the spooling directory
 | |
| 		for this printer; here is <tt/bamboo/'s entry:
 | |
| <tscreen><verb>
 | |
| bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
 | |
| 	:sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\
 | |
| 	:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:mx#5000:\
 | |
| 	:if=/usr/local/libexec/psif:\
 | |
| 	:df=/usr/local/libexec/psdf:
 | |
| </verb></tscreen>
 | |
| 		The spooling directory is the given in the <tt/sd/
 | |
| 		capability.  We will make three megabytes (which is 6144
 | |
| 		disk blocks) the amount of free disk space that must
 | |
| 		exist on the filesystem for LPD to accept remote jobs:
 | |
| <tscreen><verb>
 | |
| echo 6144 > /var/spool/lpd/bamboo/minfree
 | |
| </verb></tscreen>
 | |
| 	      <tag/User restrictions/
 | |
| 
 | |
| 		You can control which remote users can print to local
 | |
| 		printers by specifying the <tt/rs/ capability in
 | |
| 		<tt>/etc/printcap</tt>.  When <tt/rs/ appears in the
 | |
| 		entry for a locally-attached printer, LPD will accept
 | |
| 		jobs from remote hosts <em/if/ the user submitting the
 | |
| 		job also has an account of the same login name on the
 | |
| 		local host.  Otherwise, LPD refuses the job.
 | |
| 
 | |
| 	        This capability is particularly useful in an
 | |
| 		environment where there are (for example) different
 | |
| 		departments sharing a network, and some users
 | |
| 		transcend departmental boundaries.  By giving them
 | |
| 		accounts on your systems, they can use your printers
 | |
| 		from their own departmental systems.  If you would rather
 | |
| 		allow them to use <em/only/ your printers and not your
 | |
| 		compute resources, you can give them ``token''
 | |
| 		accounts, with no home directory and a useless shell
 | |
| 		like <tt>/usr/bin/false</tt>.
 | |
| 	    </descrip>
 | |
| 
 | |
|       <sect1><heading>Accounting for Printer Usage<label
 | |
| 	    id="printing:advanced:acct"></heading>
 | |
| 
 | |
| 	<p> So, you need to charge for printouts.  And why not?  Paper
 | |
| 	  and ink cost money.  And then there are maintenance
 | |
| 	  costs---printers are loaded with moving parts and tend to
 | |
| 	  break down.  You have examined your printers, usage patterns,
 | |
| 	  and maintenance fees and have come up with a per-page (or
 | |
| 	  per-foot, per-meter, or per-whatever) cost.  Now, how do you
 | |
| 	  actually start accounting for printouts?
 | |
| 
 | |
| 	  Well, the bad news is the LPD spooling system does not
 | |
| 	  provide much help in this department.  Accounting is highly
 | |
| 	  dependent on the kind of printer in use, the formats being
 | |
| 	  printed, and <em/your/ requirements in charging for printer
 | |
| 	  usage.
 | |
| 
 | |
| 	  To implement accounting, you have to modify a printer's text
 | |
| 	  filter (to charge for plain text jobs) and the conversion
 | |
| 	  filters (to charge for other file formats), to count pages
 | |
| 	  or query the printer for pages printed.  You cannot get away
 | |
| 	  with using the simple output filter, since it cannot do
 | |
| 	  accounting.  See section <ref name="Filters"
 | |
| 	  id="printing:advanced:filter-intro">.
 | |
| 
 | |
| 	  Generally, there are two ways to do accounting:
 | |
| 	  <itemize>
 | |
| 	    <item><em/Periodic accounting/ is the more common way,
 | |
| 	      possibly because it is easier.  Whenever someone prints a
 | |
| 	      job, the filter logs the user, host, and number of pages
 | |
| 	      to an accounting file.  Every month, semester, year, or
 | |
| 	      whatever time period you prefer, you collect the
 | |
| 	      accounting files for the various printers, tally up the
 | |
| 	      pages printed by users, and charge for usage.  Then you
 | |
| 	      truncate all the logging files, starting with a clean
 | |
| 	      slate for the next period.
 | |
| 
 | |
| 	    <item><em/Timely accounting/ is less common, probably
 | |
| 	      because it is more difficult.  This method has the
 | |
| 	      filters charge users for printouts as soon as they use
 | |
| 	      the printers.  Like disk quotas, the accounting is
 | |
| 	      immediate.  You can prevent users from printing when
 | |
| 	      their account goes in the red, and might provide a way
 | |
| 	      for users to check and adjust their ``print quotas.''
 | |
| 	      But this method requires some database code to track
 | |
| 	      users and their quotas.
 | |
| 	  </itemize>
 | |
| 
 | |
| 	  The LPD spooling system supports both methods easily: since
 | |
| 	  you have to provide the filters (well, most of the time),
 | |
| 	  you also have to provide the accounting code.  But there is
 | |
| 	  a bright side: you have enormous flexibility in your
 | |
| 	  accounting methods.  For example, you choose whether to use
 | |
| 	  periodic or timely accounting.  You choose what information
 | |
| 	  to log: user names, host names, job types, pages printed,
 | |
| 	  square footage of paper used, how long the job took to
 | |
| 	  print, and so forth.  And you do so by modifying the filters
 | |
| 	  to save this information.
 | |
| 
 | |
| 	<sect2><heading>Quick and Dirty Printer Accounting</heading>
 | |
| 
 | |
| 	  <p> FreeBSD comes with two programs that can get you set up
 | |
| 	    with simple periodic accounting right away.  They are the
 | |
| 	    text filter <tt/lpf/, described in section <ref
 | |
| 	    id="printing:advanced:lpf" name="lpf: a Text Filter">, and
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac">, a program to gather and total entries from
 | |
| 	    printer accounting files.
 | |
| 
 | |
| 	    As mentioned in the section on filters (<ref
 | |
| 	      id="printing:advanced:filters" name="Filters">), LPD
 | |
| 	      starts the text and the conversion filters with the name
 | |
| 	      of the accounting file to use on the filter command
 | |
| 	      line.  The filters can use this argument to know where
 | |
| 	      to write an accounting file entry.  The name of this
 | |
| 	      file comes from the <tt/af/ capability in
 | |
| 	      <tt>/etc/printcap</tt>, and if not specified as an
 | |
| 	      absolute path, is relative to the spooling directory.
 | |
| 
 | |
| 	    LPD starts <tt/lpf/ with page width and length arguments
 | |
| 	    (from the <tt/pw/ and <tt/pl/ capabilities).  <tt/lpf/
 | |
| 	    uses these arguments to determine how much paper will be
 | |
| 	    used.  After sending the file to the printer, it then
 | |
| 	    writes an accounting entry in the accounting file.  The
 | |
| 	    entries look like this:
 | |
| <tscreen><verb>
 | |
|    2.00 rose:andy
 | |
|    3.00 rose:kelly
 | |
|    3.00 orchid:mary
 | |
|    5.00 orchid:mary
 | |
|    2.00 orchid:zhang
 | |
| </verb></tscreen>
 | |
| 	    You should use a separate accounting file for each
 | |
| 	    printer, as <tt/lpf/ has no file locking logic built into
 | |
| 	    it, and two <tt/lpf/s might corrupt each other's entries
 | |
| 	    if they were to write to the same file at the same time.
 | |
| 	    A easy way to insure a separate accounting file for each
 | |
| 	    printer is to use <tt/af=acct/ in <tt>/etc/printcap</tt>.
 | |
| 	    Then, each accounting file will be in the spooling directory
 | |
| 	    for a printer, in a file named <tt/acct/.
 | |
| 
 | |
| 	    When you are ready to charge users for printouts, run the
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac"> program.  Just change to the spooling directory
 | |
| 	    for the printer you want to collect on and type 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac">.
 | |
| 	    You will get a dollar-centric summary like the following:
 | |
| <code>
 | |
|   Login               pages/feet   runs    price
 | |
| orchid:kelly                5.00    1   $  0.10
 | |
| orchid:mary                31.00    3   $  0.62
 | |
| orchid:zhang                9.00    1   $  0.18
 | |
| rose:andy                   2.00    1   $  0.04
 | |
| rose:kelly                177.00  104   $  3.54
 | |
| rose:mary                  87.00   32   $  1.74
 | |
| rose:root                  26.00   12   $  0.52
 | |
| 
 | |
| total                     337.00  154   $  6.74
 | |
| </code>
 | |
| 	    These are the arguments 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac"> expects:
 | |
| 	    <descrip>
 | |
| 	      <tag/<tt/-P<it/printer///
 | |
| 
 | |
| 	        Which <it/printer/ to summarize.  This option works
 | |
| 		only if there is an absolute path in the <tt/af/
 | |
| 		capability in <tt>/etc/printcap</tt>.
 | |
| 
 | |
| 	      <tag/<tt/-c//
 | |
| 
 | |
| 		Sort the output by cost instead of alphabetically by
 | |
| 		user name.
 | |
| 
 | |
| 	      <tag/<tt/-m//
 | |
| 
 | |
| 		Ignore host name in the accounting files.  With this
 | |
| 		option, user smith on host alpha is the same user
 | |
| 		smith on host gamma.  Without, they are different users.
 | |
| 
 | |
| 	      <tag/<tt/-p<it/price///
 | |
| 
 | |
| 		Compute charges with <it/price/ dollars per page or
 | |
| 		per foot instead of the price from the <tt/pc/
 | |
| 		capability in <tt>/etc/printcap</tt>, or two cents (the
 | |
| 		default).  You can specify <it/price/ as a floating
 | |
| 		point number.
 | |
| 
 | |
| 	      <tag/<tt/-r//
 | |
| 
 | |
| 		Reverse the sort order.
 | |
| 
 | |
| 	      <tag/<tt/-s//
 | |
| 	      
 | |
| 		Make an accounting summary file and truncate the
 | |
| 		accounting file.
 | |
| 
 | |
| 	      <tag/<tt/<it/names...///
 | |
| 
 | |
| 		Print accounting information for the given user
 | |
| 		<it/names/ only.
 | |
| 	    </descrip>
 | |
| 
 | |
| 	    In the default summary that 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac"> produces, you see the
 | |
| 	    number of pages printed by each user from various hosts.
 | |
| 	    If, at your site, host does not matter (because users can
 | |
| 	    use any host), run <tt/pac -m/, to produce the following
 | |
| 	    summary:
 | |
| <code>
 | |
|   Login               pages/feet   runs    price
 | |
| andy                        2.00    1   $  0.04
 | |
| kelly                     182.00  105   $  3.64
 | |
| mary                      118.00   35   $  2.36
 | |
| root                       26.00   12   $  0.52
 | |
| zhang                       9.00    1   $  0.18
 | |
| 
 | |
| total                     337.00  154   $  6.74
 | |
| </code>
 | |
| 	    To compute the dollar amount due, 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac"> uses the
 | |
| 	    <tt/pc/ capability in the <tt>/etc/printcap</tt> file
 | |
| 	    (default of 200, or 2 cents per page).  Specify, in
 | |
| 	    hundredths of cents, the price per page or per foot you
 | |
| 	    want to charge for printouts in this capability.  You can
 | |
| 	    override this value when you run 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac"> with the <tt/-p/
 | |
| 	    option.  The units for the <tt/-p/ option are in dollars,
 | |
| 	    though, not hundredths of cents.  For example,
 | |
| <tscreen><verb>
 | |
| pac -p1.50
 | |
| </verb></tscreen>
 | |
| 	    makes each page cost one dollar and fifty cents.  You can
 | |
| 	    really rake in the profits by using this option.
 | |
| 
 | |
| 	    Finally, running <tt/pac -s/ will save the summary
 | |
| 	    information in a summary accounting file, which is named
 | |
| 	    the same as the printer's accounting file, but with
 | |
| 	    <tt/_sum/ appended to the name.  It then truncates the
 | |
| 	    accounting file.  When you run 
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?pac"
 | |
| 	     name="pac"> again, it rereads
 | |
| 	    the summary file to get starting totals, then adds
 | |
| 	    information from the regular accounting file.
 | |
| 
 | |
| 
 | |
| 	<sect2><heading>How Can You Count Pages Printed?</heading>
 | |
| 
 | |
| 	  <p> In order to perform even remotely accurate accounting,
 | |
| 	    you need to be able to determine how much paper a job
 | |
| 	    uses.  This is the essential problem of printer
 | |
| 	    accounting.
 | |
| 
 | |
| 	    For plain text jobs, the problem's not that hard to solve:
 | |
| 	    you count how many lines are in a job and compare it to
 | |
| 	    how many lines per page your printer supports.  Do not
 | |
| 	    forget to take into account backspaces in the file which
 | |
| 	    overprint lines, or long logical lines that wrap onto one
 | |
| 	    or more additional physical lines.
 | |
| 
 | |
| 	    The text filter <tt/lpf/ (introduced in <ref
 | |
| 	    id="printing:advanced:lpf" name="lpf: a Text Filter">)
 | |
| 	    takes into account these things when it does accounting.
 | |
| 	    If you are writing a text filter which needs to do
 | |
| 	    accounting, you might want to examine <tt/lpf/'s source
 | |
| 	    code.
 | |
| 
 | |
| 	    How do you handle other file formats, though?
 | |
| 
 | |
| 	    Well, for DVI-to-LaserJet or DVI-to-PostScript conversion,
 | |
| 	    you can have your filter parse the diagnostic output of
 | |
| 	    
 | |
| 	    <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvilj"
 | |
| 	     name="dvilj"> or 
 | |
| 	     <htmlurl url="http://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+Ports&query=dvips"
 | |
| 	      name="dvips"> and look to see how many pages
 | |
| 	    were converted.  You might be able to do similar things
 | |
| 	    with other file formats and conversion programs.
 | |
| 
 | |
| 	    But these methods suffer from the fact that the printer
 | |
| 	    may not actually print all those pages.  For example, it
 | |
| 	    could jam, run out of toner, or explode---and the user
 | |
| 	    would still get charged.
 | |
| 
 | |
| 	    So, what can you do?
 | |
| 
 | |
| 	    There is only one <em/sure/ way to do <em/accurate/
 | |
| 	    accounting.  Get a printer that can tell you how much
 | |
| 	    paper it uses, and attach it via a serial line or a
 | |
| 	    network connection.  Nearly all PostScript printers
 | |
| 	    support this notion.  Other makes and models do as well
 | |
| 	    (networked Imagen laser printers, for example).  Modify
 | |
| 	    the filters for these printers to get the page usage after
 | |
| 	    they print each job and have them log accounting
 | |
| 	    information based on that value <em/only/.  There is no
 | |
| 	    line counting nor error-prone file examination required.
 | |
| 
 | |
| 	    Of course, you can always be generous and make all
 | |
| 	    printouts free.
 | |
| 
 | |
|     <sect><heading>Alternatives to the Standard Spooler<label
 | |
| 	  id="printing:lpd-alternatives"></heading> 
 | |
| 
 | |
|       <p> If you have been reading straight through this manual, by now
 | |
| 	you have learned just about everything there is to know about
 | |
| 	the LPD spooling system that comes with FreeBSD.  You can
 | |
| 	probably appreciate many of its shortcomings, which naturally
 | |
| 	leads to the question: ``What other spooling systems are out
 | |
| 	there (and work with FreeBSD)?''
 | |
| 
 | |
| 	Unfortunately, I have located only <em/two/ alternatives---and
 | |
| 	they are almost identical to each other!  They are:
 | |
| 	<descrip>
 | |
| 	  <tag/PLP, the Portable Line Printer Spooler System/
 | |
| 
 | |
| 	    PLP was based on software developed by Patrick Powell and
 | |
| 	    then maintained by an Internet-wide group of developers.
 | |
| 	    The main site for the software is at 
 | |
| 	    	    <htmlurl
 | |
| 	    url="ftp://ftp.iona.ie/pub/plp"
 | |
| 	    name="ftp://ftp.iona.ie/pub/plp">.  There is also a <htmlurl
 | |
| 	      url="http://www.iona.ie:8000/www/hyplan/jmason/plp.html"
 | |
| 	      name="web page">.
 | |
| 
 | |
| 	    It is quite similar to the BSD LPD spooler, but boasts a
 | |
| 	    host of features, including:
 | |
| 	    <itemize>
 | |
| 	      <item>Better network support, including built-in support
 | |
| 		for networked printers, NIS-maintained printcaps, and
 | |
| 		NFS-mounted spooling directories
 | |
| 
 | |
| 	      <item>Sophisticated queue management, allowing multiple
 | |
| 		printers on a queue, transfer of jobs between queues,
 | |
| 		and queue redirection
 | |
| 
 | |
| 	      <item>Remote printer control functions
 | |
| 
 | |
| 	      <item>Prioritization of jobs
 | |
| 
 | |
| 	      <item>Expansive security and access options
 | |
| 	    </itemize>
 | |
| 
 | |
| 	  <tag/LPRng/
 | |
| 
 | |
| 	    LPRng, which purportedly means ``LPR: the Next
 | |
| 	    Generation'' is a complete rewrite of PLP.  Patrick Powell
 | |
| 	    and Justin Mason (the principal maintainer of PLP)
 | |
| 	    collaborated to make LPRng.  The main site for LPRng is
 | |
| 	    <htmlurl url="ftp://dickory.sdsu.edu/pub/LPRng"
 | |
| 	    name="ftp://dickory.sdsu.edu/pub/LPRng">.
 | |
| 	</descrip>
 | |
| 
 | |
| 
 | |
|     <sect><heading>Acknowledgments</heading>
 | |
| 
 | |
|       <p> I would like to thank the following people who have assisted in
 | |
| 	the development of this document:
 | |
| 
 | |
| 	<descrip>
 | |
| 	  <tag/Daniel Eischen <tt/<deischen@iworks.interworks.org>//
 | |
| 
 | |
| 	    For providing a plethora of HP filter programs for perusal.
 | |
| 
 | |
| 	  <tag/&a.jehamby;/
 | |
| 
 | |
| 	    For the Ghostscript-to-HP filter.
 | |
| 
 | |
| 	  <tag/My wife, Mary Kelly <tt/<urquhart@argyre.colorado.edu>//
 | |
| 
 | |
| 	    For allowing me to spend more time with FreeBSD than with her.
 | |
| 
 | |
| 	</descrip>
 |