aboutsummaryrefslogtreecommitdiff
path: root/en_US.ISO8859-1/books/handbook/printing/chapter.sgml
diff options
context:
space:
mode:
Diffstat (limited to 'en_US.ISO8859-1/books/handbook/printing/chapter.sgml')
-rw-r--r--en_US.ISO8859-1/books/handbook/printing/chapter.sgml4610
1 files changed, 0 insertions, 4610 deletions
diff --git a/en_US.ISO8859-1/books/handbook/printing/chapter.sgml b/en_US.ISO8859-1/books/handbook/printing/chapter.sgml
deleted file mode 100644
index d403e08700..0000000000
--- a/en_US.ISO8859-1/books/handbook/printing/chapter.sgml
+++ /dev/null
@@ -1,4610 +0,0 @@
-<!--
- The FreeBSD Documentation Project
-
- $FreeBSD: doc/en_US.ISO_8859-1/books/handbook/printing/chapter.sgml,v 1.29 2000/06/13 01:01:17 jim Exp $
--->
-
-<chapter id="printing">
- <title>Printing</title>
-
- <para><emphasis>Contributed by &a.kelly;, 30 September 1995.
- Restructured and updated by &a.jim;, March 2000.</emphasis></para>
-
- <sect1>
- <title>Synopsis</title>
-
- <para>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 chapter introduces the LPD spooling
- system, often simply called LPD, and will guide you through its
- configuration.</para>
-
- <para>If you are already familiar with LPD or another printer spooling
- system, you may wish to skip to section <link
- linkend="printing-intro-setup">Setting up the spooling
- system</link>.</para>
- </sect1>
-
- <sect1 id="printing-intro-spooler">
- <title>Introduction</title>
-
- <para>LPD controls everything about a host's printers. It is
- responsible for a number of things:</para>
-
- <itemizedlist>
- <listitem>
- <para>It controls access to attached printers and printers
- attached to other hosts on the network.</para>
- </listitem>
-
- <listitem>
- <para>It enables users to submit files to be printed; these
- submissions are known as <emphasis>jobs</emphasis>.</para>
- </listitem>
-
- <listitem>
- <para>It prevents multiple users from accessing a printer at the
- same time by maintaining a <emphasis>queue</emphasis> for each
- printer.</para>
- </listitem>
-
- <listitem>
- <para>It can print <emphasis>header pages</emphasis> (also known
- as <emphasis>banner</emphasis> or <emphasis>burst</emphasis>
- pages) so users can easily find jobs they have printed in a
- stack of printouts.</para>
- </listitem>
-
- <listitem>
- <para>It takes care of communications parameters for printers
- connected on serial ports.</para>
- </listitem>
-
- <listitem>
- <para>It can send jobs over the network to a LPD spooler on
- another host.</para>
- </listitem>
-
- <listitem>
- <para>It can run special filters to format jobs to be printed for
- various printer languages or printer capabilities.</para>
- </listitem>
-
- <listitem>
- <para>It can account for printer usage.</para>
- </listitem>
- </itemizedlist>
-
- <para>Through a configuration file
- (<filename>/etc/printcap</filename>), 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.</para>
-
- <sect2 id="printing-intro-why">
- <title>Why You Should Use the Spooler</title>
-
- <para>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:</para>
-
- <itemizedlist>
- <listitem>
- <para>LPD prints jobs in the background; you do not have to wait
- for data to be copied to the printer.</para>
- </listitem>
-
- <listitem>
- <para>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.</para>
- </listitem>
-
- <listitem>
- <para>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.</para>
- </listitem>
- </itemizedlist>
- </sect2>
- </sect1>
-
- <sect1 id="printing-intro-setup">
- <title>Basic Setup</title>
-
- <para>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:</para>
-
- <itemizedlist>
- <listitem>
- <para>See section <link linkend="printing-simple">Simple Printer
- Setup</link> to learn how to connect a printer, tell LPD how to
- communicate with it, and print plain text files to the
- printer.</para>
- </listitem>
-
- <listitem>
- <para>See section <link linkend="printing-advanced">Advanced
- Printer Setup</link> 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.</para>
- </listitem>
- </itemizedlist>
-
- <sect2 id="printing-simple">
- <title>Simple Printer Setup</title>
-
- <para>This section tells how to configure printer hardware and the
- LPD software to use the printer. It teaches the basics:</para>
-
- <itemizedlist>
- <listitem>
- <para>Section <link linkend="printing-hardware">Hardware
- Setup</link> gives some hints on connecting the printer to a
- port on your computer.</para>
- </listitem>
-
- <listitem>
- <para>Section <link linkend="printing-software">Software
- Setup</link> shows how to setup the LPD spooler configuration
- file (<filename>/etc/printcap</filename>).</para>
- </listitem>
- </itemizedlist>
-
- <para>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 <link linkend="printing-advanced-network-net-if">Printers With
- Networked Data Stream Interfaces</link>.</para>
-
- <para>Although this section is called <quote>Simple Printer
- Setup</quote>, 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.</para>
-
- <sect3 id="printing-hardware">
- <title>Hardware Setup</title>
-
- <para>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.</para>
-
- <para>If you have already connected your printer and have
- successfully printed with it under another operating system, you
- can probably skip to section <link
- linkend="printing-software">Software Setup</link>.</para>
-
- <sect4 id="printing-ports">
- <title>Ports and Cables</title>
-
- <para>Nearly all printers you can get for a PC today support one
- or both of the following interfaces:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>Serial</emphasis> 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.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Parallel</emphasis> 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.</para>
-
- <para>Parallel interfaces are sometimes known as
- <quote>Centronics</quote> interfaces, named after the
- connector type on the printer.</para>
- </listitem>
- </itemizedlist>
-
- <para>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 and printers
- can communicate in both directions under FreeBSD when a
- IEEE1284 compliant cable is used.</para>
-
- <para>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.</para>
- </sect4>
-
- <sect4 id="printing-parallel">
- <title>Parallel Ports</title>
-
- <para>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.</para>
-
- <para>Remember which parallel port you used on the computer.
- The first parallel port is <filename>/dev/lpt0</filename> to
- FreeBSD; the second is <filename>/dev/lpt1</filename>, and so
- on.</para>
- </sect4>
-
- <sect4 id="printing-serial">
- <title>Serial Ports</title>
-
- <para>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.</para>
-
- <para>If you are unsure what the <quote>proper serial
- cable</quote> is, you may wish to try one of the following
- alternatives:</para>
-
- <itemizedlist>
- <listitem>
- <para>A <emphasis>modem</emphasis> 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
- <quote>DTE-to-DCE</quote> cable.</para>
- </listitem>
-
- <listitem>
- <para>A <emphasis>null-modem</emphasis> 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
- <quote>DTE-to-DTE</quote> cable.</para>
- </listitem>
-
- <listitem>
- <para>A <emphasis>serial printer</emphasis> cable, required
- for some unusual printers, is like the null modem cable,
- but sends some signals to their counterparts instead of
- being internally shorted.</para>
- </listitem>
- </itemizedlist>
-
- <para>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
- <literal>bps</literal> (bits per second, sometimes
- <emphasis>baud rate</emphasis>) 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
- <quote>in-band</quote> or <quote>software</quote>) flow control.
- Remember these settings for the software configuration that
- follows.</para>
- </sect4>
- </sect3>
-
- <sect3 id="printing-software">
- <title>Software Setup</title>
-
- <para>This section describes the software setup necessary to print
- with the LPD spooling system in FreeBSD.</para>
-
- <para>Here is an outline of the steps involved:</para>
-
- <procedure>
- <step>
- <para>Configure your kernel, if necessary, for the port you
- are using for the printer; section <link
- linkend="printing-kernel">Kernel Configuration</link> tells
- you what you need to do.</para>
- </step>
-
- <step>
- <para>Set the communications mode for the parallel port, if
- you are using a parallel port; section <link
- linkend="printing-parallel-port-mode">Setting the
- Communication Mode for the Parallel Port</link> gives
- details.</para>
- </step>
-
- <step>
- <para>Test if the operating system can send data to the printer.
- Section <link linkend="printing-testing">Checking Printer
- Communications</link> gives some suggestions on how to do
- this.</para>
- </step>
-
- <step>
- <para>Set up LPD for the printer by modifying the file
- <filename>/etc/printcap</filename>. You will find out how
- to do this later in this chapter.</para>
- </step>
- </procedure>
-
- <sect4 id="printing-kernel">
- <title>Kernel Configuration</title>
-
- <para>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.</para>
-
- <para>To find out if the kernel you are currently using supports
- a serial interface, type:</para>
-
- <screen>&prompt.root; <userinput>dmesg | grep sio<replaceable>N</replaceable></userinput></screen>
-
- <para>Where <replaceable>N</replaceable> is the number of the
- serial port, starting from zero. If you see output similar to
- the following:</para>
-
- <screen>sio2 at 0x3e8-0x3ef irq 5 on isa
-sio2: type 16550A</screen>
-
- <para>then the kernel supports the port.</para>
-
- <para>To find out if the kernel supports a parallel interface,
- type:</para>
-
- <screen>&prompt.root; <userinput>dmesg | grep lpt<replaceable>N</replaceable></userinput></screen>
-
- <para>Where <replaceable>N</replaceable> is the number of the
- parallel port, starting from zero. If you see output similar
- to the following <screen>lpt0 at 0x378-0x37f on isa</screen>
- then the kernel supports the port.</para>
-
- <para>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.</para>
-
- <para>To add support for a serial port, see the section on
- kernel configuration. To add support for a parallel port, see
- that section <emphasis>and</emphasis> the section that
- follows.</para>
- </sect4>
- </sect3>
-
- <sect3 id="printing-dev-ports">
- <title>Adding <filename>/dev</filename> Entries for the
- Ports</title>
-
- <para>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
- <filename>/dev</filename> directory are for.</para>
-
- <para><emphasis>To add a <filename>/dev</filename> entry for a
- port:</emphasis></para>
-
- <procedure>
- <step>
- <para>Become root with the &man.su.1; command. Enter the
- root password when prompted.</para>
- </step>
-
- <step>
- <para>Change to the <filename>/dev</filename>
- directory:</para>
-
- <screen>&prompt.root; cd <filename>/dev</filename></screen>
- </step>
-
- <step>
- <para>Type:</para>
-
- <screen>&prompt.root; <userinput>./MAKEDEV <replaceable>port</replaceable></userinput></screen>
-
- <para>Where <replaceable>port</replaceable> is the device
- entry for the port you want to make. Use
- <literal>lpt0</literal> for the first parallel port,
- <literal>lpt1</literal> for the second, and so on; use
- <literal>ttyd0</literal> for the first serial port,
- <literal>ttyd1</literal> for the second, and so on.</para>
- </step>
-
- <step>
- <para>Type:</para>
-
- <screen>&prompt.root; <userinput>ls -l <replaceable>port</replaceable></userinput></screen>
-
- <para>to make sure the device entry got created.</para>
- </step>
- </procedure>
-
- <sect4 id="printing-parallel-port-mode">
- <title>Setting the Communication Mode for the Parallel
- Port</title>
-
- <para>When you are using the parallel interface, you can choose
- whether FreeBSD should use interrupt-driven or polled
- communication with the printer.</para>
-
- <itemizedlist>
- <listitem>
- <para>The <emphasis>interrupt-driven</emphasis> 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.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>polled</emphasis> 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.</para>
- </listitem>
- </itemizedlist>
-
- <para>The interrupt-driven method is somewhat faster but uses up
- a precious IRQ line. You should use whichever one
- works.</para>
-
- <para>You can set the communications mode in two ways: by
- configuring the kernel or by using the &man.lptcontrol.8;
- program.</para>
-
- <para><emphasis>To set the communications mode by configuring
- the kernel:</emphasis></para>
-
- <procedure>
- <step>
- <para>Edit your kernel configuration file. Look for or add
- an <literal>lpt0</literal> entry. If you are setting up
- the second parallel port, use <literal>lpt1</literal>
- instead. Use <literal>lpt2</literal> for the third port,
- and so on.</para>
-
- <itemizedlist>
- <listitem>
- <para>If you want interrupt-driven mode, add the
- <literal>irq</literal> specifier:</para>
-
- <programlisting>
-device lpt0 at isa? port? tty irq <replaceable>N</replaceable> vector lptintr</programlisting>
-
- <para>Where <replaceable>N</replaceable> is the IRQ
- number for your computer's parallel port.</para>
- </listitem>
-
- <listitem>
- <para>If you want polled mode, do not add the
- <literal>irq</literal> specifier:</para>
-
- <programlisting>
-device lpt0 at isa? port? tty vector lptintr</programlisting>
- </listitem>
- </itemizedlist>
- </step>
-
- <step>
- <para>Save the file. Then configure, build, and install the
- kernel, then reboot. See <link
- linkend="kernelconfig">kernel configuration</link> for
- more details.</para>
- </step>
- </procedure>
-
- <para><emphasis>To set the communications mode with</emphasis>
- &man.lptcontrol.8;:</para>
-
- <procedure>
- <step>
- <para>Type:</para>
-
- <screen>&prompt.root; <userinput>lptcontrol -i -u <replaceable>N</replaceable></userinput></screen>
-
- <para>to set interrupt-driven mode for
- <literal>lpt<replaceable>N</replaceable></literal>.</para>
- </step>
-
- <step>
- <para>Type:</para>
-
- <screen>&prompt.root; <userinput>lptcontrol -p -u <replaceable>N</replaceable></userinput></screen>
-
- <para>to set polled-mode for
- <literal>lpt<replaceable>N</replaceable></literal>.</para>
- </step>
- </procedure>
-
- <para>You could put these commands in your
- <filename>/etc/rc.local</filename> file to set the mode each
- time your system boots. See &man.lptcontrol.8; for more
- information.</para>
- </sect4>
-
- <sect4 id="printing-testing">
- <title>Checking Printer Communications</title>
-
- <para>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.</para>
-
- <para>To test the printer, we will send some text to it. For
- printers that can immediately print characters sent to them,
- the program &man.lptest.1; is perfect: it generates all 96
- printable ASCII characters in 96 lines.</para>
-
- <para>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:</para>
-
- <programlisting>
-%!PS
-100 100 moveto 300 300 lineto stroke
-310 310 moveto /Helvetica findfont 12 scalefont setfont
-(Is this thing working?) show
-showpage</programlisting>
-
- <note>
- <para>When this document refers to a printer language, it is
- 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.</para>
- </note>
-
- <sect5 id="printing-checking-parallel">
- <title>Checking a Parallel Printer</title>
-
- <para>This section tells you how to check if FreeBSD can
- communicate with a printer connected to a parallel
- port.</para>
-
- <para><emphasis>To test a printer on a parallel
- port:</emphasis></para>
-
- <procedure>
- <step>
- <para>Become root with &man.su.1;.</para>
- </step>
-
- <step>
- <para>Send data to the printer.</para>
-
- <itemizedlist>
- <listitem>
- <para>If the printer can print plain text, then use
- &man.lptest.1;. Type:</para>
-
- <screen>&prompt.root; <userinput>lptest &gt; /dev/lpt<replaceable>N</replaceable></userinput></screen>
-
- <para>Where <replaceable>N</replaceable> is the number
- of the parallel port, starting from zero.</para>
- </listitem>
-
- <listitem>
- <para>If the printer understands PostScript or other
- printer language, then send a small program to the
- printer. Type:</para>
-
- <screen>&prompt.root; <userinput>cat &gt; /dev/lpt<replaceable>N</replaceable></userinput></screen>
-
- <para>Then, line by line, type the program
- <emphasis>carefully</emphasis> as you cannot edit a
- line once you have pressed <literal>RETURN</literal>
- or <literal>ENTER</literal>. When you have finished
- entering the program, press
- <literal>CONTROL+D</literal>, or whatever your end
- of file key is.</para>
-
- <para>Alternatively, you can put the program in a file
- and type:</para>
-
- <screen>&prompt.root; <userinput>cat <replaceable>file</replaceable> &gt; /dev/lpt<replaceable>N</replaceable></userinput></screen>
-
- <para>Where <replaceable>file</replaceable> is the
- name of the file containing the program you want to
- send to the printer.</para>
- </listitem>
- </itemizedlist>
- </step>
- </procedure>
-
- <para>You should see something print. Do not worry if the
- text does not look right; we will fix such things
- later.</para>
- </sect5>
-
- <sect5 id="printing-checking-serial">
- <title>Checking a Serial Printer</title>
-
- <para>This section tells you how to check if FreeBSD can
- communicate with a printer on a serial port.</para>
-
- <para><emphasis>To test a printer on a serial
- port:</emphasis></para>
-
- <procedure>
- <step>
- <para>Become root with &man.su.1;.</para>
- </step>
-
- <step>
- <para>Edit the file <filename>/etc/remote</filename>. Add
- the following entry:</para>
-
- <programlisting>
-printer:dv=/dev/<replaceable>port</replaceable>:br#<replaceable>bps-rate</replaceable>:pa=<replaceable>parity</replaceable></programlisting>
-
- <para>Where <replaceable>port</replaceable> is the device
- entry for the serial port (<literal>ttyd0</literal>,
- <literal>ttyd1</literal>, etc.),
- <replaceable>bps-rate</replaceable> is the
- bits-per-second rate at which the printer communicates,
- and <replaceable>parity</replaceable> is the parity
- required by the printer (either <literal>even</literal>,
- <literal>odd</literal>, <literal>none</literal>, or
- <literal>zero</literal>).</para>
-
- <para>Here is a sample entry for a printer connected via
- a serial line to the third serial port at 19200 bps with
- no parity:</para>
-
- <programlisting>
-printer:dv=/dev/ttyd2:br#19200:pa=none</programlisting>
- </step>
-
- <step>
- <para>Connect to the printer with &man.tip.1;.
- Type:</para>
-
- <screen>&prompt.root; <userinput>tip printer</userinput></screen>
-
- <para>If this step does not work, edit the file
- <filename>/etc/remote</filename> again and try using
- <filename>/dev/cuaa<replaceable>N</replaceable></filename>
- instead of
- <filename>/dev/ttyd<replaceable>N</replaceable></filename>.</para>
- </step>
-
- <step>
- <para>Send data to the printer.</para>
-
- <itemizedlist>
- <listitem>
- <para>If the printer can print plain text, then use
- &man.lptest.1;. Type:</para>
-
- <screen><prompt>~</prompt><userinput>$lptest</userinput></screen>
- </listitem>
-
- <listitem>
- <para>If the printer understands PostScript or other
- printer language, then send a small program to the
- printer. Type the program, line by line,
- <emphasis>very carefully</emphasis> 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 <literal>CONTROL+D</literal>.</para>
-
- <para>Alternatively, you can put the program in a file
- and type:</para>
-
- <screen><prompt>~</prompt><userinput>&gt;<replaceable>file</replaceable></userinput></screen>
-
- <para>Where <replaceable>file</replaceable> is the
- name of the file containing the program. After
- &man.tip.1; sends the file, press any required
- end-of-file key.</para>
- </listitem>
- </itemizedlist>
- </step>
- </procedure>
-
- <para>You should see something print. Do not worry if the
- text does not look right; we will fix that later.</para>
- </sect5>
- </sect4>
- </sect3>
-
- <sect3 id="printing-printcap">
- <title>Enabling the Spooler: The <filename>/etc/printcap</filename>
- File</title>
-
- <para>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.</para>
-
- <para>You configure LPD by editing the file
- <filename>/etc/printcap</filename>. The LPD spooling system
- reads this file each time the spooler is used, so updates to the
- file take immediate effect.</para>
-
- <para>The format of the &man.printcap.5; file is straightforward.
- Use your favorite text editor to make changes to
- <filename>/etc/printcap</filename>. The format is identical to
- other capability files like
- <filename>/usr/share/misc/termcap</filename> and
- <filename>/etc/remote</filename>. For complete information
- about the format, see the &man.cgetent.3;.</para>
-
- <para>The simple spooler configuration consists of the following
- steps:</para>
-
- <procedure>
- <step>
- <para>Pick a name (and a few convenient aliases) for the
- printer, and put them in the
- <filename>/etc/printcap</filename> file; see the
- <link linkend="printing-naming">Naming the Printer</link>
- section for more information on naming.</para>
- </step>
-
- <step>
- <para>Turn off header pages (which are on by default) by
- inserting the <literal>sh</literal> capability; see the
- <link linkend="printing-no-header-pages">Suppressing Header
- Pages</link> section for more information.</para>
- </step>
-
- <step>
- <para>Make a spooling directory, and specify its location with
- the <literal>sd</literal> capability; see the <link
- linkend="printing-spooldir">Making the Spooling
- Directory</link> section for more information.</para>
- </step>
-
- <step>
- <para>Set the <filename>/dev</filename> entry to use for the
- printer, and note it in <filename>/etc/printcap</filename>
- with the <literal>lp</literal> capability; see the <link
- linkend="printing-device">Identifying the Printer
- Device</link> for more information. Also, if the printer is
- on a serial port, set up the communication parameters with
- the <literal>fs</literal>, <literal>fc</literal>,
- <literal>xs</literal>, and <literal>xc</literal>
- capabilities; which is discussed in the <link
- linkend="printing-commparam">Configuring Spooler
- Communications Parameters</link> section.</para>
- </step>
-
- <step>
- <para>Install a plain text input filter; see the <link
- linkend="printing-textfilter">Installing the Text
- Filter</link> section for details.</para>
- </step>
-
- <step>
- <para>Test the setup by printing something with the
- &man.lpr.1; command. More details are available in the
- <link linkend="printing-trying">Trying It Out</link> and
- <link
- linkend="printing-troubleshooting">Troubleshooting</link>
- sections.</para>
- </step>
- </procedure>
-
- <note>
- <para>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.</para>
- </note>
-
- <para>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 <emphasis>and</emphasis>
- 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. The section entitled <link
- linkend="printing-advanced-if-conversion">Accommodating Plain
- Text Jobs on PostScript Printers</link> tells how to do
- this.</para>
-
- <sect4 id="printing-naming">
- <title>Naming the Printer</title>
-
- <para>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 of aliases
- for the printer.</para>
-
- <para>At least one of the printers specified in the
- <filename>/etc/printcap</filename> should have the alias
- <literal>lp</literal>. This is the default printer's name.
- If users do not have the <envar>PRINTER</envar> environment
- variable nor specify a printer name on the command line of any
- of the LPD commands, then <literal>lp</literal> will be the
- default printer they get to use.</para>
-
- <para>Also, it is common practice to make the last alias for a
- printer be a full description of the printer, including make
- and model.</para>
-
- <para>Once you have picked a name and some common aliases, put
- them in the <filename>/etc/printcap</filename> 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.</para>
-
- <para>In the following example, we start with a skeletal
- <filename>/etc/printcap</filename> that defines two printers
- (a Diablo 630 line printer and a Panasonic KX-P4455 PostScript
- laser printer):</para>
-
- <programlisting>
-#
-# /etc/printcap for host rose
-#
-rattan|line|diablo|lp|Diablo 630 Line Printer:
-
-bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:</programlisting>
-
- <para>In this example, the first printer is named
- <literal>rattan</literal> and has as aliases
- <literal>line</literal>, <literal>diablo</literal>,
- <literal>lp</literal>, and <literal>Diablo 630 Line
- Printer</literal>. Since it has the alias
- <literal>lp</literal>, it is also the default printer. The
- second is named <literal>bamboo</literal>, and has as aliases
- <literal>ps</literal>, <literal>PS</literal>,
- <literal>S</literal>, <literal>panasonic</literal>, and
- <literal>Panasonic KX-P4455 PostScript v51.4</literal>.</para>
- </sect4>
-
- <sect4 id="printing-no-header-pages">
- <title>Suppressing Header Pages</title>
-
- <para>The LPD spooling system will by default print a
- <emphasis>header page</emphasis> 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.</para>
-
- <para>To suppress header pages, add the <literal>sh</literal>
- capability to the entry for the printer in
- <filename>/etc/printcap</filename>. Here is an example
- <filename>/etc/printcap</filename> with <literal>sh</literal>
- added:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>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.</para>
- </sect4>
-
- <sect4 id="printing-spooldir">
- <title>Making the Spooling Directory</title>
-
- <para>The next step in the simple spooler setup is to make a
- <emphasis>spooling directory</emphasis>, a directory where
- print jobs reside until they are printed, and where a number
- of other spooler support files live.</para>
-
- <para>Because of the variable nature of spooling directories, it
- is customary to put these directories under
- <filename>/var/spool</filename>. It is not necessary to
- backup the contents of spooling directories, either.
- Recreating them is as simple as running &man.mkdir.1;.</para>
-
- <para>It is also customary to make the directory with a name
- that is identical to the name of the printer, as shown
- below:</para>
-
- <screen>&prompt.root; <userinput>mkdir /var/spool/<replaceable>printer-name</replaceable></userinput></screen>
-
- <para>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
- <literal>rattan</literal> and
- <literal>bamboo</literal>:</para>
-
- <screen>&prompt.root; <userinput>mkdir /var/spool/lpd</userinput>
-&prompt.root; <userinput>mkdir /var/spool/lpd/rattan</userinput>
-&prompt.root; <userinput>mkdir /var/spool/lpd/bamboo</userinput></screen>
-
- <note>
- <para>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:</para>
-
- <screen>&prompt.root; <userinput>chown daemon.daemon /var/spool/lpd/rattan</userinput>
-&prompt.root; <userinput>chown daemon.daemon /var/spool/lpd/bamboo</userinput>
-&prompt.root; <userinput>chmod 770 /var/spool/lpd/rattan</userinput>
-&prompt.root; <userinput>chmod 770 /var/spool/lpd/bamboo</userinput></screen>
- </note>
-
- <para>Finally, you need to tell LPD about these directories
- using the <filename>/etc/printcap</filename> file. You
- specify the pathname of the spooling directory with the
- <literal>sd</literal> capability:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>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.</para>
-
- <para>If you do not specify a spooling directory with
- <literal>sd</literal>, the spooling system will use
- <filename>/var/spool/lpd</filename> as a default.</para>
- </sect4>
-
- <sect4 id="printing-device">
- <title>Identifying the Printer Device</title>
-
- <para>In the <link linkend="printing-dev-ports">Adding
- <filename>/dev</filename> Entries for the Ports</link>
- section, we identified which entry in the
- <filename>/dev</filename> 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).</para>
-
- <para>List the <filename>/dev</filename> entry pathname in the
- <filename>/etc/printcap</filename> file using the
- <literal>lp</literal> capability.</para>
-
- <para>In our running example, let us assume that
- <hostid>rattan</hostid> is on the first parallel port, and
- <hostid>bamboo</hostid> is on a sixth serial port; here are
- the additions to <filename>/etc/printcap</filename>:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>If you do not specify the <literal>lp</literal> capability
- for a printer in your <filename>/etc/printcap</filename> file,
- LPD uses <filename>/dev/lp</filename> as a default.
- <filename>/dev/lp</filename> currently does not exist in
- FreeBSD.</para>
-
- <para>If the printer you are installing is connected to a
- parallel port, skip to the section entitled, <link
- linkend="printing-textfilter">Installing the Text
- Filter</link>. Otherwise, be sure to follow the instructions
- in the next section.</para>
- </sect4>
-
- <sect4 id="printing-commparam">
- <title>Configuring Spooler Communication Parameters</title>
-
- <para>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:</para>
-
- <itemizedlist>
- <listitem>
- <para>It lets you try different communication parameters by
- simply editing the <filename>/etc/printcap</filename>
- file; you do not have to recompile the filter
- program.</para>
- </listitem>
-
- <listitem>
- <para>It enables the spooling system to use the same filter
- program for multiple printers which may have different
- serial communication settings.</para>
- </listitem>
- </itemizedlist>
-
- <para>The following <filename>/etc/printcap</filename>
- capabilities control serial communication parameters of the
- device listed in the <literal>lp</literal> capability:</para>
-
- <variablelist>
- <varlistentry>
- <term><literal>br#<replaceable>bps-rate</replaceable></literal></term>
-
- <listitem>
- <para>Sets the communications speed of the device to
- <replaceable>bps-rate</replaceable>, where
- <replaceable>bps-rate</replaceable> can be 50, 75, 110,
- 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600,
- 19200, or 38400 bits-per-second.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>fc#<replaceable>clear-bits</replaceable></literal></term>
-
- <listitem>
- <para>Clears the flag bits
- <replaceable>clear-bits</replaceable> in the
- <replaceable>sgttyb</replaceable> structure after
- opening the device.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>fs#<replaceable>set-bits</replaceable></literal></term>
-
- <listitem>
- <para>Sets the flag bits
- <replaceable>set-bits</replaceable> in the
- <replaceable>sgttyb</replaceable> structure.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>xc#<replaceable>clear-bits</replaceable></literal></term>
-
- <listitem>
- <para>Clears local mode bits
- <replaceable>clear-bits</replaceable> after opening the
- device.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>xs#<replaceable>set-bits</replaceable></literal></term>
-
- <listitem>
- <para>Sets local mode bits
- <replaceable>set-bits</replaceable>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>For more information on the bits for the
- <literal>fc</literal>, <literal>fs</literal>,
- <literal>xc</literal>, and <literal>xs</literal> capabilities,
- see the file
- <filename>/usr/include/sys/ioctl_compat.h</filename>.</para>
-
- <para>When LPD opens the device specified by the
- <literal>lp</literal> capability, it reads the flag bits in
- the <literal>sgttyb</literal> structure; it clears any bits in
- the <literal>fc</literal> capability, then sets bits in the
- <literal>fs</literal> capability, then applies the resultant
- setting. It does the same for the local mode bits as
- well.</para>
-
- <para>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 <literal>TANDEM</literal>,
- <literal>ANYP</literal>, <literal>LITOUT</literal>,
- <literal>FLUSHO</literal>, and <literal>PASS8</literal> flags.
- For the local mode bits, we will set the
- <literal>LITOUT</literal> and <literal>PASS8</literal>
- flags:</para>
-
- <programlisting>
-bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
- :sh:sd=/var/spool/lpd/bamboo:\
- :lp=/dev/ttyd5:fs#0x82000c1:xs#0x820:</programlisting>
- </sect4>
-
- <sect4 id="printing-textfilter">
- <title>Installing the Text Filter</title>
-
- <para>We are now ready to tell LPD what text filter to use to
- send jobs to the printer. A <emphasis>text filter</emphasis>,
- also known as an <emphasis>input filter</emphasis>, 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 <literal>lp</literal>
- 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
- the <link linkend="printing-advanced-filters">Filters</link>
- section.</para>
-
- <para>For our simple printer setup, the text filter can be a
- small shell script that just executes
- <command>/bin/cat</command> to send the job to the printer.
- FreeBSD comes with another filter called
- <filename>lpf</filename> 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 <command>lpf</command> is
- described in detail in section entitled <link
- linkend="printing-advanced-lpf">lpf: a Text
- Filter</link>.</para>
-
- <para>First, let us make the shell script
- <filename>/usr/local/libexec/if-simple</filename> be a simple
- text filter. Put the following text into that file with your
- favorite text editor:</para>
-
- <programlisting>
-#!/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 &amp;&amp; exit 0
-exit 2</programlisting>
-
- <para>Make the file executable:</para>
-
- <screen>&prompt.root; <userinput>chmod 555 /usr/local/libexec/if-simple</userinput></screen>
-
- <para>And then tell LPD to use it by specifying it with the
- <literal>if</literal> capability in
- <filename>/etc/printcap</filename>. We will add it to the two
- printers we have so far in the example
- <filename>/etc/printcap</filename>:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
- </sect4>
-
- <sect4>
- <title>Turn on LPD</title>
-
- <para>&man.lpd.8; is run from <filename>/etc/rc</filename>,
- controlled by the <literal>lpd_enable</literal> variable. This
- variable defaults to <literal>NO</literal>. If you have not done
- so already, add the line:</para>
-
- <programlisting>lpd_enable="YES"</programlisting>
-
- <para>to <filename>/etc/rc.conf</filename>, and then either restart
- your machine, or just run &man.lpd.8;.</para>
-
- <screen>&prompt.root; <userinput>lpd</userinput></screen>
- </sect4>
-
- <sect4 id="printing-trying">
- <title>Trying It Out</title>
-
- <para>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 &man.lpr.1;,
- which submits a job for printing.</para>
-
- <para>You can combine &man.lpr.1; with the &man.lptest.1;
- program, introduced in section <link
- linkend="printing-testing">Checking Printer
- Communications</link> to generate some test text.</para>
-
- <para><emphasis>To test the simple LPD setup:</emphasis></para>
-
- <para>Type:</para>
-
- <screen>&prompt.root; <userinput>lptest 20 5 | lpr -P<replaceable>printer-name</replaceable></userinput></screen>
-
- <para>Where <replaceable>printer-name</replaceable> is a the
- name of a printer (or an alias) specified in
- <filename>/etc/printcap</filename>. To test the default
- printer, type &man.lpr.1; without any <option>-P</option>
- argument. Again, if you are testing a printer that expects
- PostScript, send a PostScript program in that language instead
- of using &man.lptest.1;. You can do so by putting the program
- in a file and typing <command>lpr
- <replaceable>file</replaceable></command>.</para>
-
- <para>For a PostScript printer, you should get the results of
- the program. If you are using &man.lptest.1;, then your
- results should look like the following:</para>
-
- <programlisting>
-!"#$%&amp;'()*+,-./01234
-"#$%&amp;'()*+,-./012345
-#$%&amp;'()*+,-./0123456
-$%&amp;'()*+,-./01234567
-%&amp;'()*+,-./012345678</programlisting>
-
- <para>To further test the printer, try downloading larger
- programs (for language-based printers) or running
- &man.lptest.1; with different arguments. For example,
- <command>lptest 80 60</command> will produce 60 lines of 80
- characters each.</para>
-
- <para>If the printer did not work, see the <link
- linkend="printing-troubleshooting">Troubleshooting</link>
- section.</para>
- </sect4>
- </sect3>
- </sect2>
- </sect1>
-
- <sect1 id="printing-advanced">
- <title>Advanced Printer Setup</title>
-
- <para>This section describes filters for printing specially formatted
- files, header pages, printing across networks, and restricting and
- accounting for printer usage.</para>
-
- <sect2 id="printing-advanced-filter-intro">
- <title>Filters</title>
-
- <para>Although LPD handles network protocols, queuing, access control,
- and other aspects of printing, most of the <emphasis>real</emphasis>
- work happens in the <emphasis>filters</emphasis>. 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&mdash;an extremely simple one that
- should work with most printers (section <link
- linkend="printing-textfilter">Installing the Text
- Filter</link>).</para>
-
- <para>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
- <emphasis>you</emphasis> have to provide filters yourself. The good
- news is that many are generally available; when they are not, they are
- usually easy to write.</para>
-
- <para>Also, FreeBSD comes with one,
- <filename>/usr/libexec/lpr/lpf</filename>, 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.</para>
-
- <para>Here is what you will find in this section:</para>
-
- <itemizedlist>
- <listitem>
- <para>Section <link linkend="printing-advanced-filters">How Filters
- Work</link>, 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 <quote>under the hood</quote>
- 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.</para>
- </listitem>
-
- <listitem>
- <para>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 <link
- linkend="printing-advanced-if-conversion">Accommodating
- Plain Text Jobs on PostScript Printers</link> tells you what you
- should do to overcome this problem. I recommend reading this
- section if you have a PostScript printer.</para>
- </listitem>
-
- <listitem>
- <para>PostScript is a popular output format for many programs. Even
- some people (myself included) write PostScript code directly. But
- PostScript printers are expensive. Section <link
- linkend="printing-advanced-ps">Simulating PostScript on
- Non-PostScript Printers</link> tells how you can further modify
- a printer's text filter to accept and print PostScript data on a
- <emphasis>non-PostScript</emphasis> printer. I recommend reading
- this section if you do not have a PostScript printer.</para>
- </listitem>
-
- <listitem>
- <para>Section <link
- linkend="printing-advanced-convfilters">Conversion
- Filters</link> 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 <command>lpr -t</command> to print troff data, or
- <command>lpr -d</command> to print TeX DVI data, or <command>lpr
- -v</command> to print raster image data, and so forth. I
- recommend reading this section.</para>
- </listitem>
-
- <listitem>
- <para>Section <link linkend="printing-advanced-of">Output
- Filters</link> tells all about a not often used feature of LPD:
- output filters. Unless you are printing header pages (see <link
- linkend="printing-advanced-header-pages">Header Pages</link>),
- you can probably skip that section altogether.</para>
- </listitem>
-
- <listitem>
- <para>Section <link linkend="printing-advanced-lpf">lpf: a Text
- Filter</link> describes <command>lpf</command>, 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
- <command>lpf</command>.</para>
- </listitem>
- </itemizedlist>
-
- <sect3 id="printing-advanced-filters">
- <title>How Filters Work</title>
-
- <para>As mentioned before, a filter is an executable program started
- by LPD to handle the device-dependent part of communicating with the
- printer.</para>
-
- <para>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 <literal>lf</literal>
- capability in <filename>/etc/printcap</filename>, or
- <filename>/dev/console</filename> by default).</para>
-
- <para>Which filter LPD starts and the filter's arguments depend on
- what is listed in the <filename>/etc/printcap</filename> file and
- what arguments the user specified for the job on the
- &man.lpr.1; command line. For example, if the user typed
- <command>lpr -t</command>, LPD would start the troff filter, listed
- in the <literal>tf</literal> capability for the destination printer.
- If the user wanted to print plain text, it would start the
- <literal>if</literal> filter (this is mostly true: see <link
- linkend="printing-advanced-of">Output Filters</link> for
- details).</para>
-
- <para>There are three kinds of filters you can specify in
- <filename>/etc/printcap</filename>:</para>
-
- <itemizedlist>
- <listitem>
- <para>The <emphasis>text filter</emphasis>, confusingly called the
- <emphasis>input filter</emphasis> 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:
-
- <cmdsynopsis>
- <command>filter-name</command>
- <arg>-c</arg>
- <arg choice="plain">-w<replaceable>width</replaceable></arg>
- <arg choice="plain">-l<replaceable>length</replaceable></arg>
- <arg choice="plain">-i<replaceable>indent</replaceable></arg>
- <arg choice="plain">-n <replaceable>login</replaceable></arg>
- <arg choice="plain">-h <replaceable>host</replaceable></arg>
- <arg choice="plain"><replaceable>acct-file</replaceable></arg>
- </cmdsynopsis>
-
- where
-
- <variablelist>
- <varlistentry>
- <term><option>-c</option></term>
-
- <listitem>
- <para>appears if the job's submitted with <command>lpr
- -l</command></para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>width</replaceable></term>
-
- <listitem>
- <para>is the value from the <literal>pw</literal> (page
- width) capability specified in
- <filename>/etc/printcap</filename>, default 132</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>length</replaceable></term>
-
- <listitem>
- <para>is the value from the <literal>pl</literal> (page
- length) capability, default 66</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>indent</replaceable></term>
-
- <listitem>
- <para>is the amount of the indentation from <command>lpr
- -i</command>, default 0</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>login</replaceable></term>
-
- <listitem>
- <para>is the account name of the user printing the
- file</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>host</replaceable></term>
-
- <listitem>
- <para>is the host name from which the job was
- submitted</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>acct-file</replaceable></term>
-
- <listitem>
- <para>is the name of the accounting file from the
- <literal>af</literal> capability.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
- </listitem>
-
- <listitem>
- <para>A <emphasis>conversion filter</emphasis> 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 <link
- linkend="printing-advanced-convfilters">Conversion
- Filters</link> tells all about them. Conversion filters also
- need to do accounting, if you need printer accounting.
- Conversion filters are started with the following arguments:
-
- <cmdsynopsis>
- <command>filter-name</command>
- <arg
- choice="plain">-x<replaceable>pixel-width</replaceable></arg>
- <arg choice="plain">-y<replaceable>pixel-height</replaceable></arg>
- <arg choice="plain">-n <replaceable>login</replaceable></arg>
- <arg choice="plain">-h <replaceable>host</replaceable></arg>
- <arg choice="plain"><replaceable>acct-file</replaceable></arg>
- </cmdsynopsis>
-
- where <replaceable>pixel-width</replaceable> is the value
- from the <literal>px</literal> capability (default 0) and
- <replaceable>pixel-height</replaceable> is the value from the
- <literal>py</literal> capability (default 0).</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>output filter</emphasis> is used only if there
- is no text filter, or if header pages are enabled. In my
- experience, output filters are rarely used. Section <link
- linkend="printing-advanced-of">Output Filters</link> describe
- them. There are only two arguments to an output filter:
-
- <cmdsynopsis>
- <command>filter-name</command>
- <arg choice="plain">-w<replaceable>width</replaceable></arg>
- <arg choice="plain">-l<replaceable>length</replaceable></arg>
- </cmdsynopsis>
-
- which are identical to the text filters <option>-w</option> and
- <option>-l</option> arguments.</para>
- </listitem>
- </itemizedlist>
-
- <para>Filters should also <emphasis>exit</emphasis> with the
- following exit status:</para>
-
- <variablelist>
- <varlistentry>
- <term>exit 0</term>
-
- <listitem>
- <para>If the filter printed the file successfully.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>exit 1</term>
-
- <listitem>
- <para>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.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>exit 2</term>
-
- <listitem>
- <para>If the filter failed to print the file and does not want
- LPD to try again. LPD will throw out the file.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>The text filter that comes with the FreeBSD release,
- <filename>/usr/libexec/lpr/lpf</filename>, 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.</para>
-
- <para>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.</para>
- </sect3>
-
- <sect3 id="printing-advanced-if-conversion">
- <title>Accommodating Plain Text Jobs on PostScript Printers</title>
-
- <para>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.</para>
-
- <para>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
- <literal>%!</literal> (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.</para>
-
- <para>How do we do this?</para>
-
- <para>If you have got a serial printer, a great way to do it is to
- install <command>lprps</command>. <command>lprps</command> 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 <errorname>toner
- low</errorname> or <errorname>paper jam</errorname>). But more
- importantly, it includes a program called <command>psif</command>
- which detects whether the incoming job is plain text and calls
- <command>textps</command> (another program that comes with
- <command>lprps</command>) to convert it to PostScript. It then uses
- <command>lprps</command> to send the job to the printer.</para>
-
- <para><command>lprps</command> is part of the FreeBSD ports collection
- (see <link linkend="ports">The Ports Collection</link>). You can
- fetch, build and install it yourself, of course. After installing
- <command>lprps</command>, just specify the pathname to the
- <command>psif</command> program that is part of
- <command>lprps</command>. If you installed <command>lprps</command>
- from the ports collection, use the following in the serial
- PostScript printer's entry in
- <filename>/etc/printcap</filename>:</para>
-
- <programlisting>
-:if=/usr/local/libexec/psif:</programlisting>
-
- <para>You should also specify the <literal>rw</literal> capability;
- that tells LPD to open the printer in read-write mode.</para>
-
- <para>If you have a parallel PostScript printer (and therefore cannot
- use two-way communication with the printer, which
- <command>lprps</command> needs), you can use the following shell
- script as the text filter:</para>
-
- <programlisting>
-#!/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" &amp;&amp; cat &amp;&amp; printf "\004" &amp;&amp; exit 0
- exit 2
-else
- #
- # Plain text, convert it, then print it.
- #
- ( echo "$first_line"; cat ) | /usr/local/bin/textps &amp;&amp; printf "\004" &amp;&amp; exit 0
- exit 2
-fi</programlisting>
-
- <para>In the above script, <command>textps</command> 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 <link linkend="ports">The Ports Collection</link>)
- includes a full featured text-to-PostScript program called
- <literal>a2ps</literal> that you might want to investigate.</para>
- </sect3>
-
- <sect3 id="printing-advanced-ps">
- <title>Simulating PostScript on Non-PostScript Printers</title>
-
- <para>PostScript is the <emphasis>de facto</emphasis> standard for
- high quality typesetting and printing. PostScript is, however, an
- <emphasis>expensive</emphasis> standard. Thankfully, Alladin
- Enterprises has a free PostScript work-alike called
- <application>Ghostscript</application> 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.</para>
-
- <para>Ghostscript is 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.</para>
-
- <para>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.</para>
-
- <para>Here is an example: the following script is a text filter
- for Hewlett Packard DeskJet 500 printers. For other printers,
- substitute the <option>-sDEVICE</option> argument to the
- <command>gs</command> (Ghostscript) command. (Type <command>gs
- -h</command> to get a list of devices the current installation of
- Ghostscript supports.)</para>
-
- <programlisting>
-#!/bin/sh
-#
-# ifhp - Print Ghostscript-simulated PostScript on a DeskJet 500
-# Installed in /usr/local/libexec/hpif
-
-#
-# Treat LF as CR+LF:
-#
-printf "\033&amp;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.
- #
- # Note that PostScript files are actually interpreted programs,
- # and those programs are allowed to write to stdout, which will
- # mess up the printed output. So, we redirect stdout to stderr
- # and then make descriptor 3 go to stdout, and have Ghostscript
- # write its output there. Exercise for the clever reader:
- # capture the stderr output from Ghostscript and mail it back to
- # the user originating the print job.
- #
- exec 3&gt;&amp;1 1&gt;&amp;2
- /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
- -sOutputFile=/dev/fd/3 - &amp;&amp; exit 0
-
- #
- /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 -sOutputFile=- - \
- &amp;&amp; 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 &amp;&amp; cat &amp;&amp; printf "\033&amp;l0H" &amp;&amp;
-exit 0
-fi
-
-exit 2</programlisting>
-
- <para>Finally, you need to notify LPD of the filter via the
- <literal>if</literal> capability:</para>
-
- <programlisting>
-:if=/usr/local/libexec/hpif:</programlisting>
-
- <para>That is it. You can type <command>lpr plain.text</command> and
- <filename>lpr whatever.ps</filename> and both should print
- successfully.</para>
- </sect3>
-
- <sect3 id="printing-advanced-convfilters">
- <title>Conversion Filters</title>
-
- <para>After completing the simple setup described in <link
- linkend="printing-simple">Simple Printer Setup</link>, the first
- thing you will probably want to do is install conversion filters for
- your favorite file formats (besides plain ASCII text).</para>
-
- <sect4>
- <title>Why Install Conversion Filters?</title>
-
- <para>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:</para>
-
- <screen>&prompt.user; <userinput>dvips seaweed-analysis.dvi</userinput>
-&prompt.user; <userinput>lpr seaweed-analysis.ps</userinput></screen>
-
- <para>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:</para>
-
- <screen>&prompt.user; <userinput>lpr -d seaweed-analysis.dvi</userinput></screen>
-
- <para>We got LPD to do the DVI file conversion for us by specifying
- the <option>-d</option> option. Section <link
- linkend="printing-lpr-options-format">Formatting and Conversion
- Options</link> lists the conversion options.</para>
-
- <para>For each of the conversion options you want a printer to
- support, install a <emphasis>conversion filter</emphasis> and
- specify its pathname in <filename>/etc/printcap</filename>. A
- conversion filter is like the text filter for the simple printer
- setup (see section <link linkend="printing-textfilter">Installing
- the Text Filter</link>) except that instead of printing plain
- text, the filter converts the file into a format the printer can
- understand.</para>
- </sect4>
-
- <sect4>
- <title>Which Conversions Filters Should I Install?</title>
-
- <para>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.</para>
-
- <para>The following table summarizes the filters that LPD works
- with, their capability entries for the
- <filename>/etc/printcap</filename> file, and how to invoke them
- with the <command>lpr</command> command:</para>
-
- <informaltable frame="none">
- <tgroup cols="3">
- <thead>
- <row>
- <entry>File type</entry>
- <entry><filename>/etc/printcap</filename> capability</entry>
- <entry><command>lpr</command> option</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>cifplot</entry>
- <entry><literal>cf</literal></entry>
- <entry><option>-c</option></entry>
- </row>
-
- <row>
- <entry>DVI</entry>
- <entry><literal>df</literal></entry>
- <entry><option>-d</option></entry>
- </row>
-
- <row>
- <entry>plot</entry>
- <entry><literal>gf</literal></entry>
- <entry><option>-g</option></entry>
- </row>
-
- <row>
- <entry>ditroff</entry>
- <entry><literal>nf</literal></entry>
- <entry><option>-n</option></entry>
- </row>
-
- <row>
- <entry>FORTRAN text</entry>
- <entry><literal>rf</literal></entry>
- <entry><option>-f</option></entry>
- </row>
-
- <row>
- <entry>troff</entry>
- <entry><literal>rf</literal></entry>
- <entry><option>-f</option></entry>
- </row>
-
- <row>
- <entry>raster</entry>
- <entry><literal>vf</literal></entry>
- <entry><option>-v</option></entry>
- </row>
-
- <row>
- <entry>plain text</entry>
- <entry><literal>if</literal></entry>
- <entry>none, <option>-p</option>, or
- <option>-l</option></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>In our example, using <command>lpr -d</command> means the
- printer needs a <literal>df</literal> capability in its entry in
- <filename>/etc/printcap</filename>.</para>
-
- <para>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
- <literal>gf</literal> capability and then educate your users that
- <command>lpr -g</command> mean <quote>print Printerleaf
- files.</quote></para>
- </sect4>
-
- <sect4>
- <title>Installing Conversion Filters</title>
-
- <para>Since conversion filters are programs you install outside of
- the base FreeBSD installation, they should probably go under
- <filename>/usr/local</filename>. The directory
- <filename>/usr/local/libexec</filename> is a popular location,
- since they are specialized programs that only LPD will run;
- regular users should not ever need to run them.</para>
-
- <para>To enable a conversion filter, specify its pathname under the
- appropriate capability for the destination printer in
- <filename>/etc/printcap</filename>.</para>
-
- <para>In our example, we will add the DVI conversion filter to the
- entry for the printer named <literal>bamboo</literal>. Here is
- the example <filename>/etc/printcap</filename> file again, with
- the new <literal>df</literal> capability for the printer
- <literal>bamboo</literal>.</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>The DVI filter is a shell script named
- <filename>/usr/local/libexec/psdf</filename>. Here is that
- script:</para>
-
- <programlisting>
-#!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 "$@"</programlisting>
-
- <para>This script runs <command>dvips</command> in filter mode (the
- <option>-f</option> argument) on standard input, which is the job
- to print. It then starts the PostScript printer filter
- <command>lprps</command> (see section <link
- linkend="printing-advanced-if-conversion">Accommodating Plain
- Text Jobs on PostScript Printers</link>) with the arguments LPD
- passed to this script. <command>lprps</command> will use those
- arguments to account for the pages printed.</para>
- </sect4>
-
- <sect4>
- <title>More Conversion Filter Examples</title>
-
- <para>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.</para>
-
- <para>This example script is a raster (well, GIF file, actually)
- conversion filter for a Hewlett Packard LaserJet III-Si
- printer:</para>
-
- <programlisting>
-#!/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 \
- &amp;&amp; exit 0 \
- || exit 2</programlisting>
-
- <para>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.</para>
-
- <para>Here is the <filename>/etc/printcap</filename> file with an
- entry for a printer using the above filter:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>The following script is a conversion filter for troff data
- from the groff typesetting system for the PostScript printer named
- <literal>bamboo</literal>:</para>
-
- <programlisting>
-#!/bin/sh
-#
-# pstf - Convert groff's troff data into PS, then print.
-# Installed in /usr/local/libexec/pstf
-#
-exec grops | /usr/local/libexec/lprps "$@"</programlisting>
-
- <para>The above script makes use of <command>lprps</command> again
- to handle the communication with the printer. If the printer were
- on a parallel port, we would use this script instead:</para>
-
- <programlisting>
-#!/bin/sh
-#
-# pstf - Convert groff's troff data into PS, then print.
-# Installed in /usr/local/libexec/pstf
-#
-exec grops</programlisting>
-
- <para>That is it. Here is the entry we need to add to
- <filename>/etc/printcap</filename> to enable the filter:</para>
-
- <programlisting>
-:tf=/usr/local/libexec/pstf:</programlisting>
-
- <para>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
- <literal>teak</literal>:</para>
-
- <programlisting>
-#!/bin/sh
-#
-# hprf - FORTRAN text filter for LaserJet 3si:
-# Installed in /usr/local/libexec/hprf
-#
-
-printf "\033&amp;k2G" &amp;&amp; fpr &amp;&amp; printf "\033&amp;l0H" &amp;&amp;
- exit 0
-exit 2</programlisting>
-
- <para>And we will add this line to the
- <filename>/etc/printcap</filename> for the printer
- <literal>teak</literal> to enable this filter:</para>
-
- <programlisting>
-:rf=/usr/local/libexec/hprf:</programlisting>
-
- <para>Here is one final, somewhat complex example. We will add a
- DVI filter to the LaserJet printer <literal>teak</literal>
- introduced earlier. First, the easy part: updating
- <filename>/etc/printcap</filename> with the location of the DVI
- filter:</para>
-
- <programlisting>
-:df=/usr/local/libexec/hpdf:</programlisting>
-
- <para>Now, for the hard part: making the filter. For that, we need
- a DVI-to-LaserJet/PCL conversion program. The FreeBSD ports
- collection (see <link linkend="ports">The Ports Collection</link>)
- has one: <command>dvi2xx</command> is the name of the package.
- Installing this package gives us the program we need,
- <command>dvilj2p</command>, which converts DVI into LaserJet IIp,
- LaserJet III, and LaserJet 2000 compatible codes.</para>
-
- <para><command>dvilj2p</command> makes the filter
- <command>hpdf</command> quite complex since
- <command>dvilj2p</command> cannot read from standard input. It
- wants to work with a filename. What is worse, the filename has to
- end in <filename>.dvi</filename> so using
- <filename>/dev/fd/0</filename> for standard input is problematic.
- We can get around that problem by linking (symbolically) a
- temporary file name (one that ends in <filename>.dvi</filename>)
- to <filename>/dev/fd/0</filename>, thereby forcing
- <command>dvilj2p</command> to read from standard input.</para>
-
- <para>The only other fly in the ointment is the fact that we cannot
- use <filename>/tmp</filename> for the temporary link. Symbolic
- links are owned by user and group <username>bin</username>. The
- filter runs as user <username>daemon</username>. And the
- <filename>/tmp</filename> 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.</para>
-
- <para>Instead, the filter will make the symbolic link in the current
- working directory, which is the spooling directory (specified by
- the <literal>sd</literal> capability in
- <filename>/etc/printcap</filename>). 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
- <filename>/tmp</filename>.</para>
-
- <para>Here, finally, is the filter:</para>
-
- <programlisting>
-#!/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&gt;&amp;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&amp;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</programlisting>
- </sect4>
-
- <sect4 id="printing-advanced-autoconv">
- <title>Automated Conversion: An Alternative To Conversion
- Filters</title>
-
- <para>All these conversion filters accomplish a lot for your
- printing environment, but at the cost forcing the user to specify
- (on the &man.lpr.1; 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.</para>
-
- <para>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
- <command>file</command> can be of help here. Of course, it will
- be hard to determine the differences between
- <emphasis>some</emphasis> file types&mdash;and, of course, you can
- still provide conversion filters just for them.</para>
-
- <para>The FreeBSD ports collection has a text filter that performs
- automatic conversion called <command>apsfilter</command>. It can
- detect plain text, PostScript, and DVI files, run the proper
- conversions, and print.</para>
- </sect4>
- </sect3>
-
- <sect3 id="printing-advanced-of">
- <title>Output Filters</title>
-
- <para>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:</para>
-
- <itemizedlist>
- <listitem>
- <para>LPD starts an output filter once for the entire job instead
- of once for each file in the job.</para>
- </listitem>
-
- <listitem>
- <para>LPD does not make any provision to identify the start or the
- end of files within the job for the output filter.</para>
- </listitem>
-
- <listitem>
- <para>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:</para>
-
- <cmdsynopsis>
- <command>filter-name</command>
- <arg choice="plain">-w<replaceable>width</replaceable></arg>
- <arg choice="plain">-l<replaceable>length</replaceable></arg>
- </cmdsynopsis>
-
- <para>Where <replaceable>width</replaceable> is from the
- <literal>pw</literal> capability and
- <replaceable>length</replaceable> is from the
- <literal>pl</literal> capability for the printer in
- question.</para>
- </listitem>
- </itemizedlist>
-
- <para>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 <emphasis>will not work</emphasis>. Use a text filter (also
- known as an input filter); see section <link
- linkend="printing-textfilter">Installing the Text Filter</link>.
- Furthermore, an output filter is actually <emphasis>more
- complex</emphasis> 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.</para>
-
- <para>However, an output filter is <emphasis>necessary</emphasis> 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 <emphasis>futile</emphasis> 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.)</para>
-
- <para>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 <link
- linkend="printing-advanced-header-pages">Header Pages</link>)
- only. LPD then expects the output filter to <emphasis>stop
- itself</emphasis> 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.</para>
-
- <para>If there is an output filter but <emphasis>no</emphasis> 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
- <emphasis>not</emphasis> what you want. In almost all cases, you
- need a text filter.</para>
-
- <para>The program <command>lpf</command>, 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 <command>lpf</command>. You
- can also wrap <command>lpf</command> in a shell script to handle any
- initialization codes the printer might require.</para>
- </sect3>
-
- <sect3 id="printing-advanced-lpf">
- <title><command>lpf</command>: a Text Filter</title>
-
- <para>The program <filename>/usr/libexec/lpr/lpf</filename> that comes
- with FreeBSD binary distribution is a text filter (input filter)
- that can indent output (job submitted with <command>lpr
- -i</command>), allow literal characters to pass (job submitted
- with <command>lpr -l</command>), adjust the printing position for
- backspaces and tabs in the job, and account for pages printed. It
- can also act like an output filter.</para>
-
- <para><command>lpf</command> 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
- <command>lpf</command>.</para>
-
- <para>In order for <command>lpf</command> to do page accounting
- correctly, it needs correct values filled in for the
- <literal>pw</literal> and <literal>pl</literal> capabilities in the
- <filename>/etc/printcap</filename> 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 <link
- linkend="printing-advanced-acct">Accounting for Printer
- Usage</link>.</para>
- </sect3>
- </sect2>
-
- <sect2 id="printing-advanced-header-pages">
- <title>Header Pages</title>
-
- <para>If you have <emphasis>lots</emphasis> of users, all of them using
- various printers, then you probably want to consider <emphasis>header
- pages</emphasis> as a necessary evil.</para>
-
- <para>Header pages, also known as <emphasis>banner</emphasis> or
- <emphasis>burst pages</emphasis> 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.)</para>
-
- <para>The LPD system can provide header pages automatically for your
- printouts <emphasis>if</emphasis> 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 <link
- linkend="printing-advanced-header-pages-ps">Header Pages on
- PostScript Printers</link>.</para>
-
- <sect3 id="printing-advanced-header-pages-enabling">
- <title>Enabling Header Pages</title>
-
- <para>In the <link linkend="printing-simple">Simple Printer
- Setup</link>, we turned off header pages by specifying
- <literal>sh</literal> (meaning <quote>suppress header</quote>) in the
- <filename>/etc/printcap</filename> file. To enable header pages for
- a printer, just remove the <literal>sh</literal> capability.</para>
-
- <para>Sounds too easy, right?</para>
-
- <para>You are right. You <emphasis>might</emphasis> 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:</para>
-
- <programlisting>
-#!/bin/sh
-#
-# hpof - Output filter for Hewlett Packard PCL-compatible printers
-# Installed in /usr/local/libexec/hpof
-
-printf "\033&amp;k2G" || exit 2
-exec /usr/libexec/lpr/lpf</programlisting>
-
- <para>Specify the path to the output filter in the
- <literal>of</literal> capability. See <link
- linkend="printing-advanced-of">Output Filters</link> for more
- information.</para>
-
- <para>Here is an example <filename>/etc/printcap</filename> file for
- the printer <literal>teak</literal> that we introduced earlier; we
- enabled header pages and added the above output filter:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>Now, when users print jobs to <literal>teak</literal>, 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 <command>lpr -h</command>; see <link
- linkend="printing-lpr-options-misc">Header Page Options</link> for
- more &man.lpr.1; options.</para>
-
- <note>
- <para>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 <literal>ff</literal>
- capability in <filename>/etc/printcap</filename>.</para>
- </note>
- </sect3>
-
- <sect3 id="printing-advanced-header-pages-controlling">
- <title>Controlling Header Pages</title>
-
- <para>By enabling header pages, LPD will produce a <emphasis>long
- header</emphasis>, 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):</para>
-
- <programlisting>
- 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</programlisting>
-
- <para>LPD appends a form feed after this text so the job starts on a
- new page (unless you have <literal>sf</literal> (suppress form
- feeds) in the destination printer's entry in
- <filename>/etc/printcap</filename>).</para>
-
- <para>If you prefer, LPD can make a <emphasis>short header</emphasis>;
- specify <literal>sb</literal> (short banner) in the
- <filename>/etc/printcap</filename> file. The header page will look
- like this:</para>
-
- <programlisting>
-rose:kelly Job: outline Date: Sun Sep 17 11:07:51 1995</programlisting>
-
- <para>Also by default, LPD prints the header page first, then the job.
- To reverse that, specify <literal>hl</literal> (header last) in
- <filename>/etc/printcap</filename>.</para>
- </sect3>
-
- <sect3 id="printing-advanced-header-pages-accounting">
- <title>Accounting for Header Pages</title>
-
- <para>Using LPD's built-in header pages enforces a particular paradigm
- when it comes to printer accounting: header pages must be
- <emphasis>free of charge</emphasis>.</para>
-
- <para>Why?</para>
-
- <para>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 <emphasis>user or
- host</emphasis> information or an accounting file, so it has no
- idea whom to charge for printer use. It is also not enough to just
- <quote>add one page</quote> to the text filter or any of the
- conversion filters (which do have user and host information) since
- users can suppress header pages with <command>lpr -h</command>.
- They could still be charged for header pages they did not print.
- Basically, <command>lpr -h</command> will be the preferred option of
- environmentally-minded users, but you cannot offer any incentive to
- use it.</para>
-
- <para>It is <emphasis>still not enough</emphasis> 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 <command>lpr -h</command>, they will still get
- them and be charged for them since LPD does not pass any knowledge
- of the <option>-h</option> option to any of the filters.</para>
-
- <para>So, what are your options?</para>
-
- <para>You can:</para>
-
- <itemizedlist>
- <listitem>
- <para>Accept LPD's paradigm and make header pages free.</para>
- </listitem>
-
- <listitem>
- <para>Install an alternative to LPD, such as LPRng. Section
- <link linkend="printing-lpd-alternatives">Alternatives to the
- Standard Spooler</link> tells more about other spooling
- software you can substitute for LPD.</para>
- </listitem>
-
- <listitem>
- <para>Write a <emphasis>smart</emphasis> 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 <literal>af</literal> 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
- <literal>sh</literal> (short header) capability in
- <filename>/etc/printcap</filename>. Then again, all that might
- be too much trouble, and users will certainly appreciate the
- more generous system administrator who makes header pages
- free.</para>
- </listitem>
- </itemizedlist>
- </sect3>
-
- <sect3 id="printing-advanced-header-pages-ps">
- <title>Header Pages on PostScript Printers</title>
-
- <para>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&mdash;or mostly so.</para>
-
- <para>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 <command>lpr
- -h</command>.</para>
-
- <para>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:</para>
-
- <programlisting>
-#!/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` &lt;user&gt; &lt;host&gt; &lt;job&gt;" 1&gt;&amp;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 &lt;&lt;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</programlisting>
-
- <para>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:</para>
-
- <programlisting>
-#!/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&gt;&amp;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&gt;&amp;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</programlisting>
-
- <para>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 <link
- linkend="printing-advanced-filters">How Filters
- Work</link>).</para>
-
- <para>As we have mentioned before, the above scheme, though fairly
- simple, disables the <quote>suppress header page</quote> option (the
- <option>-h</option> option) to <command>lpr</command>. 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.</para>
-
- <para>To allow users to shut off header pages on a per-job basis, you
- will need to use the trick introduced in section <link
- linkend="printing-advanced-header-pages-accounting">Accounting for
- Header Pages</link>: write an output filter that parses the
- LPD-generated header page and produces a PostScript version. If the
- user submits the job with <command>lpr -h</command>, 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.</para>
-
- <para>If you have a PostScript printer on a serial line, you can make
- use of <command>lprps</command>, which comes with an output filter,
- <command>psof</command>, which does the above. Note that
- <command>psof</command> does not charge for header pages.</para>
- </sect3>
- </sect2>
-
- <sect2 id="printing-advanced-network-printers">
- <title>Networked Printing</title>
-
- <para>FreeBSD supports networked printing: sending jobs to remote
- printers. Networked printing generally refers to two different
- things:</para>
-
- <itemizedlist>
- <listitem>
- <para>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 <link
- linkend="printing-advanced-network-rm">Printers Installed on
- Remote Hosts</link> tells how to do this.</para>
- </listitem>
-
- <listitem>
- <para>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:</para>
-
- <itemizedlist>
- <listitem>
- <para>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 <link linkend="printing-advanced-network-rm">Printers
- Installed on Remote Hosts</link> to set up such a
- printer.</para>
- </listitem>
-
- <listitem>
- <para>It might support a data stream network connection. In this
- case, you <quote>attach</quote> the printer to one host on the
- network by making that host responsible for spooling jobs and
- sending them to the printer. Section <link
- linkend="printing-advanced-network-net-if">Printers with
- Networked Data Stream Interfaces</link> gives some
- suggestions on installing such printers.</para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
-
- <sect3 id="printing-advanced-network-rm">
- <title>Printers Installed on Remote Hosts</title>
-
- <para>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.</para>
-
- <para>To enable this kind of remote printing, first install a printer
- on one host, the <emphasis>printer host</emphasis>, using the simple
- printer setup described in <link linkend="printing-simple">Simple
- Printer Setup</link>. Do any advanced setup in <link
- linkend="printing-advanced">Advanced Printer Setup</link> that you
- need. Make sure to test the printer and see if it works with the
- features of LPD you have enabled. Also ensure that the
- <emphasis>local host</emphasis> has authorization to use the LPD
- service in the <emphasis>remote host</emphasis> (see <link
- linkend="printing-advanced-restricting-remote">Restricting Jobs
- from Remote Printers</link>).</para>
-
- <para>If you are using a printer with a network interface that is
- compatible with LPD, then the <emphasis>printer host</emphasis> in
- the discussion below is the printer itself, and the
- <emphasis>printer name</emphasis> is the name you configured for the
- printer. See the documentation that accompanied your printer and/or
- printer-network interface.</para>
-
- <tip>
- <para>If you are using a Hewlett Packard Laserjet then the printer
- name <literal>text</literal> will automatically perform the LF to
- CRLF conversion for you, so you will not require the
- <filename>hpif</filename> script.</para>
- </tip>
-
- <para>Then, on the other hosts you want to have access to the printer,
- make an entry in their <filename>/etc/printcap</filename> files with
- the following:</para>
-
- <orderedlist>
- <listitem>
- <para>Name the entry anything you want. For simplicity, though,
- you probably want to use the same name and aliases as on the
- printer host.</para>
- </listitem>
-
- <listitem>
- <para>Leave the <literal>lp</literal> capability blank, explicitly
- (<literal>:lp=:</literal>).</para>
- </listitem>
-
- <listitem>
- <para>Make a spooling directory and specify its location in the
- <literal>sd</literal> capability. LPD will store jobs here
- before they get sent to the printer host.</para>
- </listitem>
-
- <listitem>
- <para>Place the name of the printer host in the
- <literal>rm</literal> capability.</para>
- </listitem>
-
- <listitem>
- <para>Place the printer name on the <emphasis>printer
- host</emphasis> in the <literal>rp</literal>
- capability.</para>
- </listitem>
- </orderedlist>
-
- <para>That is it. You do not need to list conversion filters, page
- dimensions, or anything else in the
- <filename>/etc/printcap</filename> file.</para>
-
- <para>Here is an example. The host <hostid>rose</hostid> has two
- printers, <literal>bamboo</literal> and <literal>rattan</literal>.
- We will enable users on the host orchid to print to those printers.
- Here is the <filename>/etc/printcap</filename> file for
- <hostid>orchid</hostid> (back from section <link
- linkend="printing-advanced-header-pages-enabling">Enabling Header
- Pages</link>). It already had the entry for the printer
- <literal>teak</literal>; we have added entries for the two printers
- on the host rose:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>Then, we just need to make spooling directories on
- <hostid>orchid</hostid>:</para>
-
- <screen>&prompt.root; <userinput>mkdir -p /var/spool/lpd/rattan /var/spool/lpd/bamboo</userinput>
-&prompt.root; <userinput>chmod 770 /var/spool/lpd/rattan /var/spool/lpd/bamboo</userinput>
-&prompt.root; <userinput>chown daemon.daemon /var/spool/lpd/rattan /var/spool/lpd/bamboo</userinput></screen>
-
- <para>Now, users on <hostid>orchid</hostid> can print to
- <literal>rattan</literal> and <literal>bamboo</literal>. If, for
- example, a user on orchid typed
-
- <screen>&prompt.user; <userinput>lpr -P bamboo -d sushi-review.dvi</userinput></screen>
-
- the LPD system on orchid would copy the job to the spooling
- directory <filename>/var/spool/lpd/bamboo</filename> and note that
- it was a DVI job. As soon as the host rose has room in its
- <hostid>bamboo</hostid> 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.</para>
- </sect3>
-
- <sect3 id="printing-advanced-network-net-if">
- <title>Printers with Networked Data Stream Interfaces</title>
-
- <para>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 <link
- linkend="printing-advanced-network-rm">Printers Installed on
- Remote Hosts</link>.</para>
-
- <para>The format of the <filename>/etc/printcap</filename> 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.</para>
-
- <para>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
- <command>netprint</command> 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 <command>netprint</command>. 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.).</para>
-
- <programlisting>
-#!/usr/bin/perl
-#
-# netprint - Text filter for printer attached to network
-# Installed in /usr/local/libexec/netprint
-#
-$#ARGV eq 1 || die "Usage: $0 &lt;printer-hostname&gt; &lt;port-number&gt;";
-
-$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', &amp;AF_INET, $printer_port, $address);
-
-socket(PRINTER, &amp;PF_INET, &amp;SOCK_STREAM, $protocol)
- || die "Can't create TCP/IP stream socket: $!";
-connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!";
-while (&lt;STDIN&gt;) { print PRINTER; }
-exit 0;</programlisting>
-
- <para>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:</para>
-
- <programlisting>
-#!/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</programlisting>
- </sect3>
- </sect2>
-
- <sect2 id="printing-advanced-restricting">
- <title>Restricting Printer Usage</title>
-
- <para>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.</para>
-
- <sect3 id="printing-advanced-restricting-copies">
- <title>Restricting Multiple Copies</title>
-
- <para>The LPD system makes it easy for users to print multiple copies
- of a file. Users can print jobs with <command>lpr -#5</command>
- (for example) and get five copies of each file in the job. Whether
- this is a good thing is up to you.</para>
-
- <para>If you feel multiple copies cause unnecessary wear and tear on
- your printers, you can disable the <option>-#</option> option to
- &man.lpr.1; by adding the <literal>sc</literal> capability to the
- <filename>/etc/printcap</filename> file. When users submit jobs
- with the <option>-#</option> option, they will see:</para>
-
- <screen>lpr: multiple copies are not allowed</screen>
-
-
- <para>Note that if you have set up access to a printer remotely (see
- section <link linkend="printing-advanced-network-rm">Printers
- Installed on Remote Hosts</link>), you need the
- <literal>sc</literal> capability on the remote
- <filename>/etc/printcap</filename> files as well, or else users will
- still be able to submit multiple-copy jobs by using another
- host.</para>
-
- <para>Here is an example. This is the
- <filename>/etc/printcap</filename> file for the host
- <hostid>rose</hostid>. The printer <literal>rattan</literal> is
- quite hearty, so we will allow multiple copies, but the laser
- printer <literal>bamboo</literal>'s a bit more delicate, so we will
- disable multiple copies by adding the <literal>sc</literal>
- capability:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>Now, we also need to add the <literal>sc</literal> capability on
- the host <hostid>orchid</hostid>'s
- <filename>/etc/printcap</filename> (and while we are at it, let us
- disable multiple copies for the printer
- <literal>teak</literal>):</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>By using the <literal>sc</literal> capability, we prevent the
- use of <command>lpr -#</command>, but that still does not prevent
- users from running &man.lpr.1;
- multiple times, or from submitting the same file multiple times in
- one job like this:</para>
-
- <screen>&prompt.user; <userinput>lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign</userinput></screen>
-
- <para>There are many ways to prevent this abuse (including ignoring
- it) which you are free to explore.</para>
- </sect3>
-
- <sect3 id="printing-advanced-restricting-access">
- <title>Restricting Access To Printers</title>
-
- <para>You can control who can print to what printers by using the UNIX
- group mechanism and the <literal>rg</literal> capability in
- <filename>/etc/printcap</filename>. Just place the users you want
- to have access to a printer in a certain group, and then name that
- group in the <literal>rg</literal> capability.</para>
-
- <para>Users outside the group (including root) will be greeted with
-
- <errorname>lpr: Not a member of the restricted group</errorname>
-
- if they try to print to the controlled printer.</para>
-
- <para>As with the <literal>sc</literal> (suppress multiple copies)
- capability, you need to specify <literal>rg</literal> on remote
- hosts that also have access to your printers, if you feel it is
- appropriate (see section <link
- linkend="printing-advanced-network-rm">Printers Installed on
- Remote Hosts</link>).</para>
-
- <para>For example, we will let anyone access the printer
- <literal>rattan</literal>, but only those in group
- <literal>artists</literal> can use <literal>bamboo</literal>. Here
- is the familiar <filename>/etc/printcap</filename> for host
- <hostid>rose</hostid>:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
-
- <para>Let us leave the other example
- <filename>/etc/printcap</filename> file (for the host
- <hostid>orchid</hostid>) alone. Of course, anyone on
- <hostid>orchid</hostid> can print to <literal>bamboo</literal>. It
- might be the case that we only allow certain logins on
- <hostid>orchid</hostid> anyway, and want them to have access to the
- printer. Or not.</para>
-
- <note>
- <para>There can be only one restricted group per printer.</para>
- </note>
- </sect3>
-
- <sect3 id="printing-advanced-restricting-sizes">
- <title>Controlling Sizes of Jobs Submitted</title>
-
- <para>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.</para>
-
- <para>LPD enables you to limit the maximum byte size a file in a job
- can be with the <literal>mx</literal> 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; however, if no
- <literal>mx</literal> capability is specified, then a default limit
- of 1000 blocks will be used.</para>
-
- <note>
- <para>The limit applies to <emphasis>files</emphasis> in a job, and
- <emphasis>not</emphasis> the total job size.</para>
- </note>
-
- <para>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.</para>
-
- <para>Let us add limits to our example printers
- <literal>rattan</literal> and <literal>bamboo</literal>. 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:</para>
-
- <programlisting>
-#
-# /etc/printcap for host rose
-#
-
-#
-# No limit on job size:
-#
-rattan|line|diablo|lp|Diablo 630 Line Printer:\
- :sh:mx#0: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:</programlisting>
-
- <para>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 <literal>mx</literal>
- capability in the remote <filename>/etc/printcap</filename> files as
- well. See section <link
- linkend="printing-advanced-network-rm">Printers Installed on
- Remote Hosts</link> for more information on remote
- printing.</para>
-
- <para>There is another specialized way to limit job sizes from remote
- printers; see section <link
- linkend="printing-advanced-restricting-remote">Restricting Jobs
- from Remote Printers</link>.</para>
- </sect3>
-
- <sect3 id="printing-advanced-restricting-remote">
- <title>Restricting Jobs from Remote Printers</title>
-
- <para>The LPD spooling system provides several ways to restrict print
- jobs submitted from remote hosts:</para>
-
- <variablelist>
- <varlistentry>
- <term>Host restrictions</term>
-
- <listitem>
- <para>You can control from which remote hosts a local LPD
- accepts requests with the files
- <filename>/etc/hosts.equiv</filename> and
- <filename>/etc/hosts.lpd</filename>. 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.</para>
-
- <para>The format of these files is simple: one host name per
- line. Note that the file
- <filename>/etc/hosts.equiv</filename> is also used by the
- &man.ruserok.3; protocol, and affects programs like
- &man.rsh.1; and &man.rcp.1;, so be careful.</para>
-
- <para>For example, here is the
- <filename>/etc/hosts.lpd</filename> file on the host
- <hostid>rose</hostid>:</para>
-
- <programlisting>
-orchid
-violet
-madrigal.fishbaum.de</programlisting>
-
- <para>This means <hostid>rose</hostid> will accept requests from
- the hosts <hostid>orchid</hostid>, <hostid>violet</hostid>,
- and <hostid role="fqdn">madrigal.fishbaum.de</hostid>. If any
- other host tries to access <hostid>rose</hostid>'s
- LPD, the job will be refused.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Size restrictions</term>
-
- <listitem>
- <para>You can control how much free space there needs to remain
- on the filesystem where a spooling directory resides. Make a
- file called <filename>minfree</filename> 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.</para>
-
- <para>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
- <filename>minfree</filename> file.</para>
-
- <para>For example, let us add a <filename>minfree</filename>
- file for the printer <hostid>bamboo</hostid>. We examine
- <filename>/etc/printcap</filename> to find the spooling
- directory for this printer; here is <hostid>bamboo</hostid>'s
- entry:</para>
-
- <programlisting>
-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:</programlisting>
-
- <para>The spooling directory is the given in the
- <literal>sd</literal> 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:</para>
-
- <screen>&prompt.root; <userinput>echo 6144 &gt; /var/spool/lpd/bam
-boo/minfree</userinput></screen>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>User restrictions</term>
-
- <listitem>
- <para>You can control which remote users can print to local
- printers by specifying the <literal>rs</literal> capability in
- <filename>/etc/printcap</filename>. When
- <literal>rs</literal> appears in the entry for a
- locally-attached printer, LPD will accept jobs from remote
- hosts <emphasis>if</emphasis> the user submitting the job also
- has an account of the same login name on the local host.
- Otherwise, LPD refuses the job.</para>
-
- <para>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 <emphasis>only</emphasis> your
- printers and not your compute resources, you can give them
- <quote>token</quote> accounts, with no home directory and a
- useless shell like <filename>/usr/bin/false</filename>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect3>
- </sect2>
-
- <sect2 id="printing-advanced-acct">
- <title>Accounting for Printer Usage</title>
-
- <para>So, you need to charge for printouts. And why not? Paper and ink
- cost money. And then there are maintenance costs&mdash;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?</para>
-
- <para>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
- <emphasis>your</emphasis> requirements in charging for printer
- usage.</para>
-
- <para>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 <link
- linkend="printing-advanced-filter-intro">Filters</link>.</para>
-
- <para>Generally, there are two ways to do accounting:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>Periodic accounting</emphasis> 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.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Timely accounting</emphasis> 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
- <quote>print quotas.</quote> But this method requires some database
- code to track users and their quotas.</para>
- </listitem>
- </itemizedlist>
-
- <para>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.</para>
-
- <sect3>
- <title>Quick and Dirty Printer Accounting</title>
-
- <para>FreeBSD comes with two programs that can get you set up with
- simple periodic accounting right away. They are the text filter
- <command>lpf</command>, described in section <link
- linkend="printing-advanced-lpf">lpf: a Text Filter</link>, and
- &man.pac.8;, a program to gather and total
- entries from printer accounting files.</para>
-
- <para>As mentioned in the section on filters (<link
- linkend="printing-advanced-filters">Filters</link>), 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 <literal>af</literal> capability in
- <filename>/etc/printcap</filename>, and if not specified as an
- absolute path, is relative to the spooling directory.</para>
-
- <para>LPD starts <command>lpf</command> with page width and length
- arguments (from the <literal>pw</literal> and <literal>pl</literal>
- capabilities). <command>lpf</command> 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:</para>
-
- <programlisting>
-2.00 rose:andy
-3.00 rose:kelly
-3.00 orchid:mary
-5.00 orchid:mary
-2.00 orchid:zhang</programlisting>
-
- <para>You should use a separate accounting file for each printer, as
- <command>lpf</command> has no file locking logic built into it, and
- two <command>lpf</command>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
- <literal>af=acct</literal> in <filename>/etc/printcap</filename>.
- Then, each accounting file will be in the spooling directory for a
- printer, in a file named <filename>acct</filename>.</para>
-
- <para>When you are ready to charge users for printouts, run the
- &man.pac.8; program. Just change to the spooling directory for
- the printer you want to collect on and type <literal>pac</literal>.
- You will get a dollar-centric summary like the following:</para>
-
- <screen> 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</screen>
-
- <para>These are the arguments &man.pac.8; expects:</para>
-
- <variablelist>
- <varlistentry>
- <term><option>-P<replaceable>printer</replaceable></option></term>
-
- <listitem>
- <para>Which <replaceable>printer</replaceable> to summarize.
- This option works only if there is an absolute path in the
- <literal>af</literal> capability in
- <filename>/etc/printcap</filename>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-c</option></term>
-
- <listitem>
- <para>Sort the output by cost instead of alphabetically by user
- name.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-m</option></term>
-
- <listitem>
- <para>Ignore host name in the accounting files. With this
- option, user <username>smith</username> on host
- <hostid>alpha</hostid> is the same user
- <username>smith</username> on host <hostid>gamma</hostid>.
- Without, they are different users.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-p<replaceable>price</replaceable></option></term>
-
- <listitem>
- <para>Compute charges with <replaceable>price</replaceable>
- dollars per page or per foot instead of the price from the
- <literal>pc</literal> capability in
- <filename>/etc/printcap</filename>, or two cents (the
- default). You can specify <replaceable>price</replaceable> as
- a floating point number.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-r</option></term>
-
- <listitem>
- <para>Reverse the sort order.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-s</option></term>
-
- <listitem>
- <para>Make an accounting summary file and truncate the
- accounting file.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><replaceable>name</replaceable>
- <replaceable>&hellip;</replaceable></term>
-
- <listitem>
- <para>Print accounting information for the given user
- <replaceable>names</replaceable> only.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>In the default summary that &man.pac.8; 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 <command>pac -m</command>, to produce the following
- summary:</para>
-
- <screen> 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</screen>
-
-
- <para>To compute the dollar amount due,
- &man.pac.8; uses the <literal>pc</literal> capability in the
- <filename>/etc/printcap</filename> 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 &man.pac.8; with the
- <option>-p</option> option. The units for the <option>-p</option>
- option are in dollars, though, not hundredths of cents. For
- example,
-
- <screen>&prompt.root; <userinput>pac -p1.50</userinput></screen>
-
- makes each page cost one dollar and fifty cents. You can really
- rake in the profits by using this option.</para>
-
- <para>Finally, running <command>pac -s</command> will save the summary
- information in a summary accounting file, which is named the same as
- the printer's accounting file, but with <literal>_sum</literal>
- appended to the name. It then truncates the accounting file. When
- you run &man.pac.8; again, it rereads the
- summary file to get starting totals, then adds information from the
- regular accounting file.</para>
- </sect3>
-
- <sect3>
- <title>How Can You Count Pages Printed?</title>
-
- <para>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.</para>
-
- <para>For plain text jobs, the problem is 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.</para>
-
- <para>The text filter <command>lpf</command> (introduced in <link
- linkend="printing-advanced-lpf">lpf: a Text Filter</link>) 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 <command>lpf</command>'s source code.</para>
-
- <para>How do you handle other file formats, though?</para>
-
- <para>Well, for DVI-to-LaserJet or DVI-to-PostScript conversion, you
- can have your filter parse the diagnostic output of
- <command>dvilj</command> or <command>dvips</command> and look to see
- how many pages were converted. You might be able to do similar
- things with other file formats and conversion programs.</para>
-
- <para>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&mdash;and the user would still get
- charged.</para>
-
- <para>So, what can you do?</para>
-
- <para>There is only one <emphasis>sure</emphasis> way to do
- <emphasis>accurate</emphasis> 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
- <emphasis>only</emphasis>. There is no line counting nor
- error-prone file examination required.</para>
-
- <para>Of course, you can always be generous and make all printouts
- free.</para>
- </sect3>
- </sect2>
- </sect1>
-
- <sect1 id="printing-using">
- <title>Using Printers</title>
-
- <para>This section tells you how to use printers you have setup with
- FreeBSD. Here is an overview of the user-level commands:</para>
-
- <variablelist>
- <varlistentry>
- <term>&man.lpr.1;</term>
-
- <listitem>
- <para>Print jobs</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>&man.lpq.1;</term>
-
- <listitem>
- <para>Check printer queues</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>&man.lprm.1;</term>
-
- <listitem>
- <para>Remove jobs from a printer's queue</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>There is also an administrative command, &man.lpc.8;, described in
- the section <link linkend="printing-lpc">Administrating the LPD
- Spooler</link>, used to control printers and their queues.</para>
-
- <para>All three of the commands &man.lpr.1;, &man.lprm.1;, and &man.lpq.1;
- accept an option <option>-P
- <replaceable>printer-name</replaceable></option> to specify on which
- printer/queue to operate, as listed in the
- <filename>/etc/printcap</filename> file. This enables you to submit,
- remove, and check on jobs for various printers. If you do not use the
- <option>-P</option> option, then these commands use the printer
- specified in the <envar>PRINTER</envar> environment variable. Finally,
- if you do not have a <envar>PRINTER</envar> environment variable, these
- commands default to the printer named <literal>lp</literal>.</para>
-
- <para>Hereafter, the terminology <emphasis>default printer</emphasis>
- means the printer named in the <envar>PRINTER</envar> environment
- variable, or the printer named <literal>lp</literal> when there is no
- <envar>PRINTER</envar> environment variable.</para>
-
- <sect2 id="printing-lpr">
- <title>Printing Jobs</title>
-
- <para>To print files, type:</para>
-
- <screen>&prompt.user; <userinput>lpr <replaceable>filename</replaceable> <replaceable>...</replaceable></userinput></screen>
-
- <para>This prints each of the listed files to the default printer. If
- you list no files, &man.lpr.1; reads data to
- print from standard input. For example, this command prints some
- important system files:</para>
-
- <screen>&prompt.user; <userinput>lpr /etc/host.conf /etc/hosts.equiv</userinput></screen>
-
- <para>To select a specific printer, type:</para>
-
- <screen>&prompt.user; <userinput>lpr -P <replaceable>printer-name</replaceable> <replaceable>filename</replaceable> <replaceable>...</replaceable></userinput></screen>
-
- <para>This example prints a long listing of the current directory to the
- printer named <literal>rattan</literal>:</para>
-
- <screen>&prompt.user; <userinput>ls -l | lpr -P rattan</userinput></screen>
-
- <para>Because no files were listed for the
- &man.lpr.1; command, <command>lpr</command> read the data to print
- from standard input, which was the output of the <command>ls
- -l</command> command.</para>
-
- <para>The &man.lpr.1; 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 <link
- linkend="printing-lpr-options">Printing Options</link>.</para>
- </sect2>
-
- <sect2 id="printing-lpq">
- <title>Checking Jobs</title>
-
- <para>When you print with &man.lpr.1;, the data you wish to print is put
- together in a package called a <quote>print job</quote>, 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.</para>
-
- <para>To display the queue for the default printer, type &man.lpq.1;.
- For a specific printer, use the <option>-P</option> option. For
- example, the command
-
- <screen>&prompt.user; <userinput>lpq -P bamboo</userinput></screen>
-
- shows the queue for the printer named <hostid>bamboo</hostid>. Here
- is an example of the output of the <command>lpq</command>
- command:</para>
-
- <screen>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</screen>
-
- <para>This shows three jobs in the queue for <literal>bamboo</literal>.
- The first job, submitted by user kelly, got assigned <quote>job
- number</quote> 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 <link
- linkend="printing-lprm">Removing Jobs</link> for details.</para>
-
- <para>Job number nine consists of two files; multiple files given on the
- &man.lpr.1; command line are treated as part of a single job. It
- is the currently active job (note the word <literal>active</literal>
- under the <quote>Rank</quote> column), which means the printer should
- be currently printing that job. The second job consists of data
- passed as the standard input to the &man.lpr.1; command. The third
- job came from user <username>mary</username>; it is a much larger
- job. The pathname of the files she's trying to print is too long to
- fit, so the &man.lpq.1; command just shows three dots.</para>
-
- <para>The very first line of the output from &man.lpq.1; is also useful:
- it tells what the printer is currently doing (or at least what LPD
- thinks the printer is doing).</para>
-
- <para>The &man.lpq.1; command also support a <option>-l</option> option
- to generate a detailed long listing. Here is an example of
- <command>lpq -l</command>:</para>
-
- <screen>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</screen>
- </sect2>
-
- <sect2 id="printing-lprm">
- <title>Removing Jobs</title>
-
- <para>If you change your mind about printing a job, you can remove the
- job from the queue with the &man.lprm.1; command. Often, you can
- even use &man.lprm.1; to remove an active job, but some or all of the
- job might still get printed.</para>
-
- <para>To remove a job from the default printer, first use
- &man.lpq.1; to find the job number. Then type:</para>
-
- <screen>&prompt.user; <userinput>lprm <replaceable>job-number</replaceable></userinput></screen>
-
- <para>To remove the job from a specific printer, add the
- <option>-P</option> option. The following command removes job number
- 10 from the queue for the printer <hostid>bamboo</hostid>:</para>
-
- <screen>&prompt.user; <userinput>lprm -P bamboo 10</userinput></screen>
-
- <para>The &man.lprm.1; command has a few shortcuts:</para>
-
- <variablelist>
- <varlistentry>
- <term>lprm -</term>
-
- <listitem>
- <para>Removes all jobs (for the default printer) belonging to
- you.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>lprm <replaceable>user</replaceable></term>
-
- <listitem>
- <para>Removes all jobs (for the default printer) belonging to
- <replaceable>user</replaceable>. The superuser can remove other
- users' jobs; you can remove only your own jobs.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>lprm</term>
-
- <listitem>
- <para>With no job number, user name, or <option>-</option>
- appearing on the command line,
- &man.lprm.1; removes the currently active job on the
- default printer, if it belongs to you. The superuser can remove
- any active job.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>Just use the <option>-P</option> 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 <literal>rattan</literal>:</para>
-
- <screen>&prompt.user; <userinput>lprm -P rattan -</userinput></screen>
-
- <note>
- <para>If you are working in a networked environment, &man.lprm.1; 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:</para>
-
- <screen>&prompt.user; <userinput>lpr -P rattan myfile</userinput>
-&prompt.user; <userinput>rlogin orchid</userinput>
-&prompt.user; <userinput>lpq -P rattan</userinput>
-Rank Owner Job Files Total Size
-active seeyan 12 ... 49123 bytes
-2nd kelly 13 myfile 12 bytes
-&prompt.user; <userinput>lprm -P rattan 13</userinput>
-rose: Permission denied
-&prompt.user; <userinput>logout</userinput>
-&prompt.user; <userinput>lprm -P rattan 13</userinput>
-dfA013rose dequeued
-cfA013rose dequeued
- </screen>
- </note>
- </sect2>
-
- <sect2 id="printing-lpr-options">
- <title>Beyond Plain Text: Printing Options</title>
-
- <para>The &man.lpr.1; 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.</para>
-
- <sect3 id="printing-lpr-options-format">
- <title>Formatting and Conversion Options</title>
-
- <para>The following &man.lpr.1; 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
- &man.pr.1; utility.</para>
-
- <para>For example, the following command prints a DVI file (from the
- TeX typesetting system) named <filename>fish-report.dvi</filename>
- to the printer named <literal>bamboo</literal>:</para>
-
- <screen>&prompt.user; <userinput>lpr -P bamboo -d fish-report.dvi</userinput></screen>
-
- <para>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.</para>
-
- <note>
- <para>All of these options except <option>-p</option> and
- <option>-T</option> require conversion filters installed for the
- destination printer. For example, the <option>-d</option> option
- requires the DVI conversion filter. Section <link
- linkend="printing-advanced-convfilters">Conversion
- Filters</link> gives details.</para>
- </note>
-
- <variablelist>
- <varlistentry>
- <term><option>-c</option></term>
-
- <listitem>
- <para>Print cifplot files.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-d</option></term>
-
- <listitem>
- <para>Print DVI files.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-f</option></term>
-
- <listitem>
- <para>Print FORTRAN text files.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-g</option></term>
-
- <listitem>
- <para>Print plot data.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-i <replaceable>number</replaceable></option></term>
-
- <listitem>
- <para>Indent the output by <replaceable>number</replaceable>
- columns; if you omit <replaceable>number</replaceable>, indent
- by 8 columns. This option works only with certain conversion
- filters.</para>
-
- <note>
- <para>Do not put any space between the <option>-i</option> and
- the number.</para>
- </note>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-l</option></term>
-
- <listitem>
- <para>Print literal text data, including control
- characters.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-n</option></term>
-
- <listitem>
- <para>Print ditroff (device independent troff) data.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>-p</term>
-
- <listitem>
- <para>Format plain text with &man.pr.1; before printing. See
- &man.pr.1; for more information.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-T <replaceable>title</replaceable></option></term>
-
- <listitem>
- <para>Use <replaceable>title</replaceable> on the
- &man.pr.1; header instead of the file name. This option has
- effect only when used with the <option>-p</option>
- option.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-t</option></term>
-
- <listitem>
- <para>Print troff data.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-v</option></term>
-
- <listitem>
- <para>Print raster data.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>Here is an example: this command prints a nicely formatted
- version of the &man.ls.1; manual page on the default printer:</para>
-
- <screen>&prompt.user; <userinput>zcat /usr/share/man/man1/ls.1.gz | troff -t -man | lpr -t</userinput></screen>
-
- <para>The &man.zcat.1; command uncompresses the source of the
- &man.ls.1; manual page and passes it to the &man.troff.1;
- command, which formats that source and makes GNU troff
- output and passes it to &man.lpr.1;, which submits the job
- to the LPD spooler. Because we used the <option>-t</option>
- option to &man.lpr.1;, the spooler will convert the GNU
- troff output into a format the default printer can
- understand when it prints the job.</para>
- </sect3>
-
- <sect3 id="printing-lpr-options-job-handling">
- <title>Job Handling Options</title>
-
- <para>The following options to &man.lpr.1; tell LPD to handle the job
- specially:</para>
-
- <variablelist>
- <varlistentry>
- <term>-# <replaceable>copies</replaceable></term>
-
- <listitem>
- <para>Produce a number of <replaceable>copies</replaceable> 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
- <link
- linkend="printing-advanced-restricting-copies">Restricting
- Multiple Copies</link>.</para>
-
- <para>This example prints three copies of
- <filename>parser.c</filename> followed by three copies of
- <filename>parser.h</filename> to the default printer:</para>
-
- <screen>&prompt.user; <userinput>lpr -#3 parser.c parser.h</userinput></screen>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>-m</term>
-
- <listitem>
- <para>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.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>-s</term>
-
- <listitem>
- <para>Do not copy the files to the spooling directory, but make
- symbolic links to them instead.</para>
-
- <para>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.</para>
-
- <para>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.</para>
-
- <note>
- <para>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 <option>-s</option> option will save
- space only on the local spooling directory, not the remote.
- It is still useful, though.</para>
- </note>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>-r</term>
-
- <listitem>
- <para>Remove the files in the job after copying them to the
- spooling directory, or after printing them with the
- <option>-s</option> option. Be careful with this
- option!</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect3>
-
- <sect3 id="printing-lpr-options-misc">
- <title>Header Page Options</title>
-
- <para>These options to &man.lpr.1; 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
- <link linkend="printing-advanced-header-pages">Header Pages</link>
- for information about setting up header pages.</para>
-
- <variablelist>
- <varlistentry>
- <term>-C <replaceable>text</replaceable></term>
-
- <listitem>
- <para>Replace the hostname on the header page with
- <replaceable>text</replaceable>. The hostname is normally the
- name of the host from which the job was submitted.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>-J <replaceable>text</replaceable></term>
-
- <listitem>
- <para>Replace the job name on the header page with
- <replaceable>text</replaceable>. The job name is normally the
- name of the first file of the job, or
- <filename>stdin</filename> if you are printing standard
- input.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>-h</term>
-
- <listitem>
- <para>Do not print any header page.</para>
-
- <note>
- <para>At some sites, this option may have no effect due to the
- way header pages are generated. See <link
- linkend="printing-advanced-header-pages">Header
- Pages</link> for details.</para>
- </note>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect3>
- </sect2>
-
- <sect2 id="printing-lpc">
- <title>Administrating Printers</title>
-
- <para>As an administrator for your printers, you have had to install,
- set up, and test them. Using the &man.lpc.8; command, you
- can interact with your printers in yet more ways. With &man.lpc.8;,
- you can</para>
-
- <itemizedlist>
- <listitem>
- <para>Start and stop the printers</para>
- </listitem>
-
- <listitem>
- <para>Enable and disable their queues</para>
- </listitem>
-
- <listitem>
- <para>Rearrange the order of the jobs in each queue.</para>
- </listitem>
- </itemizedlist>
-
- <para>First, a note about terminology: if a printer is
- <emphasis>stopped</emphasis>, it will not print anything in its queue.
- Users can still submit jobs, which will wait in the queue until the
- printer is <emphasis>started</emphasis> or the queue is
- cleared.</para>
-
- <para>If a queue is <emphasis>disabled</emphasis>, no user (except root)
- can submit jobs for the printer. An <emphasis>enabled</emphasis>
- queue allows jobs to be submitted. A printer can be
- <emphasis>started</emphasis> for a disabled queue, in which case it
- will continue to print jobs in the queue until the queue is
- empty.</para>
-
- <para>In general, you have to have root privileges to use the
- &man.lpc.8; command. Ordinary users can use the &man.lpc.8; command
- to get printer status and to restart a hung printer only.</para>
-
- <para>Here is a summary of the &man.lpc.8; commands. Most of the
- commands takes a <replaceable>printer-name</replaceable> argument to
- tell on which printer to operate. You can use <literal>all</literal>
- for the <replaceable>printer-name</replaceable> to mean all printers
- listed in <filename>/etc/printcap</filename>.</para>
-
- <variablelist>
- <varlistentry>
- <term><command>abort
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>Cancel the current job and stop the printer. Users can
- still submit jobs if the queue's enabled.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>clean
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>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.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>disable
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>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.</para>
-
- <para>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
- <command>enable</command> command.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>down <replaceable>printer-name</replaceable>
- <replaceable>message</replaceable></command></term>
-
- <listitem>
- <para>Take a printer down. Equivalent to
- <command>disable</command> followed by <command>stop</command>.
- The <replaceable>message</replaceable> appears as the printer's
- status whenever a user checks the printer's queue with
- &man.lpq.1; or status with <command>lpc
- status</command>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>enable
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>Enable the queue for a printer. Users can submit jobs but
- the printer will not print anything until it is started.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>help
- <replaceable>command-name</replaceable></command></term>
-
- <listitem>
- <para>Print help on the command
- <replaceable>command-name</replaceable>. With no
- <replaceable>command-name</replaceable>, print a summary of the
- commands available.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>restart
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>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 <command>stop</command> or
- <command>down</command> commands. The
- <command>restart</command> command is equivalent to
- <command>abort</command> followed by
- <command>start</command>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>start
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>Start the printer. The printer will print jobs in its
- queue.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>stop
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>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.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>topq <replaceable>printer-name</replaceable>
- <replaceable>job-or-username</replaceable></command></term>
-
- <listitem>
- <para>Rearrange the queue for
- <replaceable>printer-name</replaceable> by placing the jobs with
- the listed <replaceable>job</replaceable> numbers or the jobs
- belonging to <replaceable>username</replaceable> at the top of
- the queue. For this command, you cannot use
- <literal>all</literal> as the
- <replaceable>printer-name</replaceable>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>up
- <replaceable>printer-name</replaceable></command></term>
-
- <listitem>
- <para>Bring a printer up; the opposite of the
- <command>down</command> command. Equivalent to
- <command>start</command> followed by
- <command>enable</command>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>&man.lpc.8; accepts the above commands on the command line. If
- you do not enter any commands, &man.lpc.8; enters an interactive mode,
- where you can enter commands until you type <command>exit</command>,
- <command>quit</command>, or end-of-file.</para>
- </sect2>
- </sect1>
-
- <sect1 id="printing-lpd-alternatives">
- <title>Alternatives to the Standard Spooler</title>
-
- <para>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:
- <quote>What other spooling systems are out there (and work with
- FreeBSD)?</quote></para>
-
- <variablelist>
- <varlistentry>
- <term>LPRng</term>
-
- <listitem>
- <para>LPRng, which purportedly means <quote>LPR: the Next
- Generation</quote> 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 <ulink
- url="http://www.astart.com/lprng/LPRng.html">http://www.astart.com/lprng/LPRng.html</ulink>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect1>
-
- <sect1 id="printing-troubleshooting">
- <title>Troubleshooting</title>
-
- <para>After performing the simple test with &man.lptest.1;, you might
- have gotten one of the following results instead of the correct
- printout:</para>
-
- <variablelist>
- <varlistentry>
- <term>It worked, after awhile; or, it did not eject a full
- sheet.</term>
-
- <listitem>
- <para>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.</para>
-
- <para>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.</para>
-
- <para>The following replacement for the shell script
- <filename>/usr/local/libexec/if-simple</filename> prints a
- form feed after it sends the job to the printer:</para>
-
- <programlisting>
-#!/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 &amp;&amp; printf "\f" &amp;&amp; exit 0
-exit 2</programlisting>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>It produced the <quote>staircase effect.</quote></term>
-
- <listitem>
- <para>You got the following on paper:</para>
-
- <programlisting>
-!"#$%&amp;'()*+,-./01234
- "#$%&amp;'()*+,-./012345
- #$%&amp;'()*+,-./0123456</programlisting>
-
- <para>You have become another victim of the <emphasis>staircase
- effect</emphasis>, 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 <emphasis>and</emphasis> ASCII code
- 13 (the carriage return or CR). Many printers use the MS-DOS
- convention for representing new-lines.</para>
-
- <para>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.</para>
-
- <para>Here is what FreeBSD wants your printer to do:</para>
-
- <informaltable frame="none">
- <tgroup cols="2">
- <tbody>
- <row>
- <entry>Printer received CR</entry>
- <entry>Printer prints CR</entry>
- </row>
-
- <row>
- <entry>Printer received LF</entry>
- <entry>Printer prints CR + LF</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Here are some ways to achieve this:</para>
-
- <itemizedlist>
- <listitem>
- <para>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.</para>
-
- <note>
- <para>If you boot your system into other operating systems
- besides FreeBSD, you may have to
- <emphasis>reconfigure</emphasis> 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.</para>
- </note>
- </listitem>
-
- <listitem>
- <para>Have FreeBSD's serial line driver automatically
- convert LF to CR+LF. Of course, this works with printers
- on serial ports <emphasis>only</emphasis>. To enable this
- feature, set the CRMOD bit in <literal>fs</literal>
- capability in the <filename>/etc/printcap</filename> file
- for the printer.</para>
- </listitem>
-
- <listitem>
- <para>Send an <emphasis>escape code</emphasis> 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.</para>
-
- <para>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.</para>
-
- <programlisting>
-#!/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. Ejects the page when done.
-
-printf "\033&amp;k2G" &amp;&amp; cat &amp;&amp; printf "\033&amp;l0H" &amp;&amp; exit 0
-exit 2</programlisting>
-
- <para>Here is an example <filename>/etc/printcap</filename>
- from a host called orchid. It has a single printer
- attached to its first parallel port, a Hewlett Packard
- LaserJet 3Si named <hostid>teak</hostid>. It is using the
- above script as its text filter:</para>
-
- <programlisting>
-#
-# /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:</programlisting>
- </listitem>
- </itemizedlist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>It overprinted each line.</term>
-
- <listitem>
- <para>The printer never advanced a line. All of the lines of
- text were printed on top of each other on one line.</para>
-
- <para>This problem is the <quote>opposite</quote> 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.</para>
-
- <para>Use the printer's configuration switches or control panel
- to enforce the following interpretation of LF and CR
- characters:</para>
-
- <informaltable frame="none">
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Printer receives</entry>
- <entry>Printer prints</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>CR</entry>
- <entry>CR</entry>
- </row>
-
- <row>
- <entry>LF</entry>
- <entry>CR + LF</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>The printer lost characters.</term>
-
- <listitem>
- <para>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.</para>
-
- <para>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:</para>
-
- <itemizedlist>
- <listitem>
- <para>If the printer supports XON/XOFF flow control, have
- FreeBSD use it by specifying the TANDEM bit in the
- <literal>fs</literal> capability.</para>
- </listitem>
-
- <listitem>
- <para>If the printer supports carrier flow control, specify
- the MDMBUF bit in the <literal>fs</literal> capability.
- Make sure the cable connecting the printer to the computer
- is correctly wired for carrier flow control.</para>
- </listitem>
-
- <listitem>
- <para>If the printer does not support any flow control, use
- some combination of the NLDELAY, TBDELAY, CRDELAY, VTDELAY,
- and BSDELAY bits in the <literal>fs</literal> capability
- to add appropriate delays to the stream of data sent to
- the printer.</para>
- </listitem>
- </itemizedlist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>It printed garbage.</term>
-
- <listitem>
- <para>The printer printed what appeared to be random garbage,
- but not the desired text.</para>
-
- <para>This is usually another symptom of incorrect
- communications parameters with a serial printer. Double-check
- the bps rate in the <literal>br</literal> capability, and the
- parity bits in the <literal>fs</literal> and
- <literal>fc</literal> capabilities; make sure the printer is
- using the same settings as specified in the
- <filename>/etc/printcap</filename> file.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Nothing happened.</term>
-
- <listitem>
- <para>If nothing happened, the problem is probably within
- FreeBSD and not the hardware. Add the log file
- (<literal>lf</literal>) capability to the entry for the
- printer you are debugging in the
- <filename>/etc/printcap</filename> file. For example, here is
- the entry for <literal>rattan</literal>, with the
- <literal>lf</literal> capability:</para>
-
- <programlisting>
-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</programlisting>
-
- <para>Then, try printing again. Check the log file (in our
- example, <filename>/var/log/rattan.log</filename>) to see any
- error messages that might appear. Based on the messages you
- see, try to correct the problem.</para>
-
- <para>If you do not specify a <literal>lf</literal> capability,
- LPD uses <filename>/dev/console</filename> as a
- default.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect1>
-</chapter>
-
-<!--
- Local Variables:
- mode: sgml
- sgml-declaration: "../chapter.decl"
- sgml-indent-data: t
- sgml-omittag: nil
- sgml-always-quote-attributes: t
- sgml-parent-document: ("../book.sgml" "part" "chapter")
- End:
--->
-
-