aboutsummaryrefslogtreecommitdiff
path: root/en/handbook/printing/chapter.sgml
diff options
context:
space:
mode:
Diffstat (limited to 'en/handbook/printing/chapter.sgml')
-rw-r--r--en/handbook/printing/chapter.sgml4919
1 files changed, 0 insertions, 4919 deletions
diff --git a/en/handbook/printing/chapter.sgml b/en/handbook/printing/chapter.sgml
deleted file mode 100644
index 0b045fd4e9..0000000000
--- a/en/handbook/printing/chapter.sgml
+++ /dev/null
@@ -1,4919 +0,0 @@
- <chapter id="printing">
- <title>Printing</title>
-
- <para><emphasis>Contributed by &a.kelly;<!-- <br> -->30 September
- 1995</emphasis></para>
-
- <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 section introduces the LPD spooling system, often
- simply called LPD.</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 id="printing-intro-spooler">
- <title>What the Spooler Does</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 another 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, 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>
-
- </sect1>
-
- <sect1 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>
-
-
- </sect1>
-
- <sect1 id="printing-intro-setup">
- <title>Setting Up the Spooling System</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>
-
-
- </sect1>
-
- <sect1 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 Interaces</link>.</para>
-
- <para>Although this section is called &ldquo;Simple Printer Setup,&rdquo; 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>
-
-
- <sect2 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>
-
-
- <sect3 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
- &ldquo;Centronics&rdquo; 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 can also receive data from
- the printer, but only few printers need to send data back to the
- computer. And FreeBSD does not support two-way parallel
- communication yet.</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>
-
- <para>So, which interface should you use?</para>
-
-
- <itemizedlist>
-
- <listitem>
- <para>If you need two-way communication, use a serial port.
- FreeBSD does not yet support two-way communication over a
- parallel port.</para>
- </listitem>
-
- <listitem>
- <para>If you do not need two-way communication and can pick
- parallel or serial, prefer the parallel interface. It
- keeps a serial port free for other peripherals&mdash;such as a
- terminal or a modem&mdash;and is faster most of the time. It
- is also easier to configure.</para>
- </listitem>
-
- <listitem>
- <para>Finally, use whatever works.</para>
- </listitem>
-
- </itemizedlist>
-
-
- </sect3>
-
- <sect3 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>
-
- </sect3>
-
- <sect3 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 &ldquo;proper serial cable&rdquo; 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 &ldquo;DTE-to-DCE&rdquo;
- 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
- &ldquo;DTE-to-DTE&rdquo; 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 bps (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
- &ldquo;in-band&rdquo; or &ldquo;software&rdquo;)
- flow control. Remember these settings for the software
- configuration that follows.</para>
-
- </sect3>
- </sect2>
-
- <sect2 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>. Section <link
- linkend="printing-printcap">The /etc/printcap
- File</link> shows you how.</para>
- </step>
-
- </procedure>
-
- <sect3 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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>dmesg | grep sio<replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <para>Where <replaceable>N</replaceable> is the
- number of the serial port, starting from zero. If you see
- output similar to the following:</para>
-
- <informalexample>
- <screen>sio2 at 0x3e8-0x3ef irq 5 on isa
-sio2: type 16550A</screen>
- </informalexample>
-
- <para>then the kernel supports the port.</para>
-
- <para>To find out if the kernel supports a parallel interface,
- type:</para>
-
- <informalexample>
- <screen>&prompt.root; <userinput>dmesg | grep lpt<replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <para>Where <replaceable>N</replaceable> is the
- number of the parallel port, starting from zero. If you see
- output similar to the following
-
- <informalexample>
- <screen>lpt0 at 0x378-0x37f on isa</screen>
- </informalexample> 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 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 <citerefentry>
- <refentrytitle>su</refentrytitle></citerefentry>
- command. Enter the root password when prompted.</para>
- </step>
-
- <step>
- <para>Change to the <filename>/dev</filename> directory:</para>
-
- <informalexample>
- <screen>&prompt.root; cd /dev</screen>
- </informalexample>
- </step>
-
- <step>
- <para>Type:</para>
-
- <informalexample>
- <screen>&prompt.root; <userinput>./MAKEDEV <replaceable>port</replaceable></userinput></screen>
- </informalexample>
-
- <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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>ls -l <replaceable>port</replaceable></userinput></screen>
- </informalexample>
-
- <para>to make sure the device entry got
- created.</para>
- </step>
-
- </procedure>
-
- </sect4>
-
- <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 <citerefentry>
- <refentrytitle>lptcontrol</refentrytitle></citerefentry> 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> <citerefentry>
- <refentrytitle>lptcontrol</refentrytitle></citerefentry>:</para>
-
- <procedure>
-
- <step>
- <para>Type:</para>
-
- <informalexample>
- <screen>&prompt.root; <userinput>lptcontrol -i -u <replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <para>to set interrupt-driven mode for
- <literal>lpt<replaceable>N</replaceable></literal>.</para>
- </step>
-
- <step>
- <para>Type:</para>
-
- <informalexample>
- <screen>&prompt.root; <userinput>lptcontrol -p -u <replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <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 <citerefentry><refentrytitle>lptcontrol</refentrytitle><manvolnum>8</manvolnum></citerefentry> 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 <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry> 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, I am
- assuming a language like PostScript, and not Hewlett
- Packard's PCL. Although PCL has great functionality, you can
- intermingle plain text with its escape sequences.
- PostScript cannot directly print plain text, and that is the
- kind of printer language for which we must make special
- accommodations.</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 <citerefentry>
- <refentrytitle>su</refentrytitle></citerefentry>.</para>
- </step>
-
- <step>
- <para>Send data to the printer.</para>
- <itemizedlist>
-
- <listitem>
- <para>If the printer can print plain text, then
- use <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry>. Type:</para>
-
- <informalexample>
- <screen>&prompt.root; <userinput>lptest &gt; /dev/lpt<replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>cat &gt; /dev/lpt<replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <para>Then, line by line, type the
- program <emphasis>carefully</emphasis> as you
- cannot edit a line once you have pressed RETURN
- or ENTER. When you have finished entering the
- program, press CONTROL+D, or whatever your end
- of file key is.</para>
-
- <para>Alternatively, you can put the program in a
- file and type:</para>
-
- <informalexample>
- <screen>&prompt.root; <userinput>cat <replaceable>file</replaceable> &gt; /dev/lpt<replaceable>N</replaceable></userinput></screen>
- </informalexample>
-
- <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 <citerefentry>
- <refentrytitle>su</refentrytitle></citerefentry>.</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 <citerefentry>
- <refentrytitle>tip</refentrytitle></citerefentry>. Type:</para>
- <informalexample>
- <screen>&prompt.root; <userinput>tip printer</userinput></screen>
- </informalexample>
-
- <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 <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry>. Type:</para>
-
- <informalexample>
- <screen><prompt>~</prompt><userinput>$lptest</userinput></screen>
- </informalexample>
- </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 CONTROL+D.</para>
-
- <para>Alternatively, you can put the program in a
- file and type:</para>
-
- <informalexample>
- <screen><prompt>~</prompt><userinput>&gt;<replaceable>file</replaceable></userinput></screen>
- </informalexample>
-
- <para>Where <replaceable>file</replaceable> is the name of the
- file containing the program. After
- <citerefentry>
- <refentrytitle>tip</refentrytitle></citerefentry> 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 <citerefentry>
- <refentrytitle>printcap</refentrytitle></citerefentry> 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 <citerefentry><refentrytitle>cgetent</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</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 <link
- linkend="printing-naming">Naming the Printer</link>.</para>
- </step>
-
- <step>
- <para>Turn off header pages (which are on by default) by
- inserting the <literal>sh</literal> capability;
- see <link linkend="printing-no-header-pages">Suppressing Header Pages</link>.</para>
- </step>
-
- <step>
- <para>Make a spooling directory, and specify its location
- with the <literal>sd</literal> capability; see
- <link linkend="printing-spooldir">Making the Spooling Directory</link>.</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
- <link
- linkend="printing-device">Identifying the Printer
- Device</link>. 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; see <link
- linkend="printing-commparam">Configuring Spooler
- Communications Parameters</link>.</para>
- </step>
-
- <step>
- <para>Install a plain text input filter; see <link
- linkend="printing-textfilter">Installing the Text
- Filter</link></para>
- </step>
-
- <step>
- <para>Test the setup by printing something with the
- <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- command; see <link linkend="printing-trying">Trying
- It Out</link> and <link linkend="printing-troubleshooting">Troubleshooting</link>.</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. Section <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 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 the
- 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 <citerefentry>
- <refentrytitle>mkdir</refentrytitle></citerefentry>.</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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>mkdir /var/spool/<replaceable>printer-name</replaceable></userinput></screen>
- </informalexample>
-
- <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>
-
- <informalexample>
- <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>
- </informalexample>
-
- <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>
-
-
- <informalexample>
- <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>
- </informalexample>
- </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 section <link linkend="printing-dev-ports">Adding /dev Entries for the Ports</link>, 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 <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 TANDEM, ANYP, LITOUT, FLUSHO, and PASS8 flags.
- For the local mode bits, we will set the LITOUT and PASS8
- 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 section <link
- linkend="printing-advanced-filters">Filters</link>.</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
- <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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>chmod 555 /usr/local/libexec/if-simple</userinput></screen>
- </informalexample>
-
- <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 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>,
- which submits a job for printing.</para>
-
- <para>You can combine <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- with the <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry> 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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>lptest 20 5 | lpr -P<replaceable>printer-name</replaceable></userinput></screen>
- </informalexample>
-
- <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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry>. 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 <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry>, 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 <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry> 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 next section, <link
- linkend="printing-troubleshooting">Troubleshooting</link>.</para>
-
- </sect4>
-
- <sect4 id="printing-troubleshooting">
- <title>Troubleshooting</title>
-
- <para>After performing the simple test with <citerefentry>
- <refentrytitle>lptest</refentrytitle></citerefentry>, 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 &ldquo;staircase
- effect.&rdquo;</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. Writes a form feed character
-# after printing job.
-
-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 &ldquo;opposite&rdquo; 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>
-
- </sect4>
- </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><citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry></term>
- <listitem>
- <para>Print jobs</para>
- </listitem>
- </varlistentry>
-
- <varlistentry><term><citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry></term>
-
- <listitem>
- <para>Check printer queues</para>
- </listitem>
- </varlistentry>
-
- <varlistentry><term><citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry></term>
-
- <listitem>
- <para>Remove jobs from a printer's queue</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>There is also an administrative command, <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry>,
- 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>, <citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry>, and
- <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry>
- 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>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr <replaceable>filename</replaceable> <replaceable>...</replaceable></userinput></screen>
- </informalexample>
-
- <para>This prints each of the listed files to the
- default printer. If you list no files, <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry> reads
- data to print from standard input. For example, this command
- prints some important system files:</para>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr /etc/host.conf /etc/hosts.equiv</userinput></screen>
- </informalexample>
-
- <para>To select a specific printer, type:</para>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr -P <replaceable>printer-name</replaceable> <replaceable>filename</replaceable> <replaceable>...</replaceable></userinput></screen>
- </informalexample>
-
- <para>This example prints a long listing of the
- current directory to the printer named <literal>rattan</literal>:</para>
-
- <informalexample>
- <screen>&prompt.user; <userinput>ls -l | lpr -P rattan</userinput></screen>
- </informalexample>
-
- <para>Because no files were listed for the
- <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry> 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>, the
- data you wish to print is put together in a package called a
- &ldquo;print job&rdquo;, 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
- <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry>. For a
- specific printer, use the <option>-P</option> option. For
- example, the command
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpq -P bamboo</userinput></screen>
- </informalexample> shows the queue for the printer named <hostid>bamboo</hostid>. Here is an example of the output of
- the <command>lpq</command> command:</para>
-
- <informalexample>
- <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>
- </informalexample>
-
- <para>This shows three jobs in the queue for
- <literal>bamboo</literal>. The first job, submitted by
- user kelly, got assigned &ldquo;job number&rdquo; 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry> command
- line are treated as part of a single job. It is the currently
- active job (note the word <literal>active</literal>
- under the &ldquo;Rank&rdquo; column), which means the printer should be
- currently printing that job. The second job consists of data
- passed as the standard input to the</para>
-
- <para><citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- command. The third job came from user mary; it is a much larger
- job. The pathname of the files she's trying to print is too long
- to fit, so the <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry> command
- just shows three dots.</para>
-
- <para>The very first line of the output from <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry> is also
- useful: it tells what the printer is currently doing (or at least
- what LPD thinks the printer is doing).</para>
-
- <para>The <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry> command
- also support a <option>-l</option> option to generate a detailed
- long listing. Here is an example of <command>lpq -l</command>:</para>
-
- <informalexample>
- <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>
- </informalexample>
-
- </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 <citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry>
- command. Often, you can even use <citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry> 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
- <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry> to find
- the job number. Then type:</para>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lprm <replaceable>job-number</replaceable></userinput></screen>
- </informalexample>
-
- <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>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lprm -P bamboo 10</userinput></screen>
- </informalexample>
-
- <para>The <citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry>
- 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,
- <citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry> 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>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lprm -P rattan -</userinput></screen>
- </informalexample>
-
- <note>
- <para>If you are working in a networked
- environment, <citerefentry>
- <refentrytitle>lprm</refentrytitle></citerefentry>
- 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>
-
- <informalexample>
- <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>
- </informalexample>
- </note>
- </sect2>
-
- <sect2 id="printing-lpr-options">
- <title>Beyond Plain Text: Printing Options</title>
-
- <para>The <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry> 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>pr</refentrytitle></citerefentry>
- 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>
- <informalexample>
- <screen>&prompt.user; <userinput>lpr -P bamboo -d fish-report.dvi</userinput></screen>
- </informalexample>
-
- <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 <citerefentry>
- <refentrytitle>pr</refentrytitle></citerefentry>
- before printing. See <citerefentry><refentrytitle>pr</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more information.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry><term><option>-T
- <replaceable>title</replaceable></option></term>
-
- <listitem>
- <para>Use <replaceable>title</replaceable> on the
- <citerefentry>
- <refentrytitle>pr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>ls</refentrytitle></citerefentry> manual
- page on the default printer:</para>
-
- <informalexample>
- <screen>&prompt.user; <userinput>zcat /usr/share/man/man1/ls.1.gz | troff -t -man | lpr -t</userinput></screen>
- </informalexample>
-
- <para>The <citerefentry>
- <refentrytitle>zcat</refentrytitle></citerefentry>
- command uncompresses the source of the</para>
-
- <para><citerefentry>
- <refentrytitle>ls</refentrytitle></citerefentry> manual
- page and passes it to the <citerefentry>
- <refentrytitle>troff</refentrytitle></citerefentry>
- command, which formats that source and makes GNU troff output
- and passes it to <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>,
- which submits the job to the LPD spooler. Because we used the
- <option>-t</option> option to</para>
-
- <para><citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>, 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry> 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>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr -#3 parser.c parser.h</userinput></screen>
- </informalexample>
- </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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry>
- command, you can interact with your printers in yet more ways.
- With <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry>, 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 <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry>
- command. Ordinary users can use the <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry> command
- to get printer status and to restart a hung printer only.</para>
-
- <para>Here is a summary of the <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry>
- 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
- <citerefentry>
- <refentrytitle>lpq</refentrytitle></citerefentry>
- 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><citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry> accepts
- the above commands on the command line. If you do not enter any
- commands, <citerefentry>
- <refentrytitle>lpc</refentrytitle></citerefentry> 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-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 &ldquo;under
- the hood&rdquo; 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</para>
-
- <para><citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>a2ps</refentrytitle></citerefentry> 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 should be in the FreeBSD ports collection, if
- you would like to install it from there. You can fetch, build,
- and install it quite easily yourself, as well.</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</para>
-
- <para><citerefentry>
- <refentrytitle>gs</refentrytitle></citerefentry> (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
- #
- /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 "\f" &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>
-
- <informalexample>
- <screen>&prompt.user; <userinput>dvips seaweed-analysis.dvi</userinput>
-&prompt.user; <userinput>lpr seaweed-analysis.ps</userinput></screen>
- </informalexample>
-
- <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>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr -d seaweed-analysis.dvi</userinput></screen>
- </informalexample>
-
- <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 &ldquo;print
- Printerleaf files.&rdquo;</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 <citerefentry>
- <refentrytitle>dvips</refentrytitle></citerefentry> 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 "\f" &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: <citerefentry>
- <refentrytitle>dvi2xx</refentrytitle></citerefentry> is the
- name of the package. Installing this package gives us the
- program we need, <citerefentry>
- <refentrytitle>dvilj2p</refentrytitle></citerefentry>, which converts DVI into LaserJet IIp, LaserJet III, and LaserJet 2000 compatible codes.</para>
-
- <para><citerefentry>
- <refentrytitle>dvilj2p</refentrytitle></citerefentry> makes
- the filter <command>hpdf</command> quite complex since
- <citerefentry>
- <refentrytitle>dvilj2p</refentrytitle></citerefentry> 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 <citerefentry>
- <refentrytitle>dvilj2p</refentrytitle></citerefentry> 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>apsfilter</refentrytitle></citerefentry>. 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 &ldquo;suppress
- header&rdquo;) 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- 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 &ldquo;add one page&rdquo; 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 LPDng or PLP.
- 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 &ldquo;suppress header page&rdquo; 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 &ldquo;attach&rdquo; 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>
-
- <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>
-
- <informalexample>
- <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>
- </informalexample>
-
- <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
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr -P bamboo -d sushi-review.dvi</userinput></screen>
- </informalexample> 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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry> 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>
-
- <informalexample>
- <screen>lpr: multiple copies are not allowed</screen>
- </informalexample>
-
- <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 <citerefentry>
- <refentrytitle>lpr</refentrytitle></citerefentry>
- multiple times, or from submitting the same file multiple times
- in one job like this:</para>
-
- <informalexample>
- <screen>&prompt.user; <userinput>lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign</userinput></screen>
- </informalexample>
-
- <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.</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: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
- <citerefentry><refentrytitle>ruserok</refentrytitle><manvolnum>3</manvolnum></citerefentry> protocol, and affects programs like <citerefentry>
- <refentrytitle>rsh</refentrytitle></citerefentry> and
- <citerefentry>
- <refentrytitle>rcp</refentrytitle></citerefentry>, 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, LPD will
- refuse them.</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>
-
- <informalexample>
- <screen>&prompt.root; <userinput>echo 6144 &gt; /var/spool/lpd/bamboo/minfree</userinput></screen>
- </informalexample>
-
- </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 &ldquo;token&rdquo; 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 &ldquo;print quotas.&rdquo; 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 <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry>, 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 <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry>
- program. Just change to the spooling directory for the printer
- you want to collect on and type <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry>. You
- will get a dollar-centric summary like the following:</para>
-
- <informalexample>
- <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>
- </informalexample>
-
- <para>These are the arguments <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry>
- 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 <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry>
- 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>
-
- <informalexample>
- <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>
- </informalexample>
-
- <para>To compute the dollar amount due,
- <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry> 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
- <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry> with
- the <option>-p</option> option. The units for the
- <option>-p</option> option are in dollars, though, not
- hundredths of cents. For example,
-
- <informalexample>
- <screen>&prompt.root; <userinput>pac -p1.50</userinput></screen>
- </informalexample>
-
- 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 <citerefentry>
- <refentrytitle>pac</refentrytitle></citerefentry>
- 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's not that hard to solve:
- you count how many lines are in a job and compare it to how many
- lines per page your printer supports. Do not forget to take
- into account backspaces in the file which overprint lines, or
- long logical lines that wrap onto one or more additional
- physical lines.</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 <citerefentry>
- <refentrytitle>dvilj</refentrytitle></citerefentry> or
- <citerefentry>
- <refentrytitle>dvips</refentrytitle></citerefentry> 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-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: &ldquo;What other spooling systems are out there (and work with
- FreeBSD)?&rdquo;</para>
-
- <para>Unfortunately, I have located only <emphasis>two</emphasis>
- alternatives&mdash;and they are almost identical to each other! They
- are:</para>
-
- <variablelist>
- <varlistentry><term>PLP, the Portable Line Printer Spooler
- System</term>
- <listitem>
- <para>PLP was based on software developed by Patrick Powell
- and then maintained by an Internet-wide group of developers.
- The main site for the software is at <ulink
- URL="ftp://ftp.iona.ie/pub/plp">ftp://ftp.iona.ie/pub/plp</ulink>. There is also a <ulink URL="http://www.iona.ie:8000/www/hyplan/jmason/plp.html">web page</ulink>.</para>
-
- <para>It is quite similar to the BSD LPD spooler, but boasts a
- host of features, including:</para>
- <itemizedlist>
-
- <listitem>
- <para>Better network support, including built-in support
- for networked printers, NIS-maintained printcaps, and
- NFS-mounted spooling directories</para>
- </listitem>
-
- <listitem>
- <para>Sophisticated queue management, allowing multiple
- printers on a queue, transfer of jobs between queues,
- and queue redirection</para>
- </listitem>
-
- <listitem>
- <para>Remote printer control functions</para>
- </listitem>
-
- <listitem>
- <para>Prioritization of jobs</para>
- </listitem>
-
- <listitem>
- <para>Expansive security and access options</para>
- </listitem>
-
- </itemizedlist>
-
- </listitem>
- </varlistentry>
-
- <varlistentry><term>LPRng</term>
-
- <listitem>
- <para>LPRng, which purportedly means &ldquo;LPR: the Next
- Generation&rdquo; 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="ftp://dickory.sdsu.edu/pub/LPRng">ftp://dickory.sdsu.edu/pub/LPRng</ulink>.</para>
-
- </listitem>
- </varlistentry>
- </variablelist>
-
- </sect1>
-
- <sect1>
- <title>Acknowledgments</title>
-
- <para>I would like to thank the following people who have assisted in
- the development of this document:</para>
-
-
- <variablelist>
- <varlistentry><term>Daniel Eischen
- <email>deischen@iworks.interworks.org</email></term>
- <listitem>
- <para>For providing a plethora of HP filter programs for
- perusal.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry><term>&a.jehamby;</term>
-
- <listitem>
- <para>For the Ghostscript-to-HP filter.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry><term>My wife, Mary Kelly
- <email>urquhart@argyre.colorado.edu</email></term>
-
- <listitem>
- <para>For allowing me to spend more time with FreeBSD than
- with her.</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: ("../handbook.sgml" "part" "chapter")
- End:
--->
-