<?xml version="1.0" encoding="iso-8859-1"?>
<!--
The FreeBSD Documentation Project
$FreeBSD$
-->
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
xml:id="printing">
<info>
<title>Printing</title>
<authorgroup>
<author>
<personname>
<firstname>Warren</firstname>
<surname>Block</surname>
</personname><contrib>Originally contributed by </contrib>
</author>
</authorgroup>
</info>
<para>Putting information on paper is a vital function, despite many
attempts to eliminate it. Printing has two basic components. The
data must be delivered to the printer, and must be in a form that
the printer can understand.</para>
<sect1 xml:id="printing-quick-start">
<title>Quick Start</title>
<para>Basic printing can be set up quickly. The printer must be
capable of printing plain <acronym>ASCII</acronym> text. For
printing to other types of files, see
<xref linkend="printing-lpd-filters"/>.</para>
<procedure>
<step>
<para>Create a directory to store files while they are being
printed:</para>
<screen>&prompt.root; <userinput>mkdir -p /var/spool/lpd/lp</userinput>
&prompt.root; <userinput>chown daemon:daemon /var/spool/lpd/lp</userinput>
&prompt.root; <userinput>chmod 770 /var/spool/lpd/lp</userinput></screen>
</step>
<step>
<para>As <systemitem class="username">root</systemitem>,
create <filename>/etc/printcap</filename> with these
contents:</para>
<programlisting>lp:\
<replaceable>:lp=/dev/unlpt0:\</replaceable> <co xml:id="printing-qs-co-printcap"/>
:sh:\
:mx#0:\
:sd=/var/spool/lpd/lp:\
:lf=/var/log/lpd-errs:</programlisting>
<calloutlist>
<callout arearefs="printing-qs-co-printcap">
<para>This line is for a printer connected to a
<acronym>USB</acronym> port.</para>
<para>For a printer connected to a parallel or
<quote>printer</quote> port, use:</para>
<programlisting>:lp=/dev/lpt0:\</programlisting>
<para>For a printer connected directly to a network,
use:</para>
<programlisting>:lp=:rm=<replaceable>network-printer-name</replaceable>:rp=raw:\</programlisting>
<para>Replace
<replaceable>network-printer-name</replaceable> with the
<acronym>DNS</acronym> host name of the network
printer.</para>
</callout>
</calloutlist>
</step>
<step>
<para>Enable <command>lpd</command> by editing
<filename>/etc/rc.conf</filename>, adding this line:</para>
<programlisting>lpd_enable="YES"</programlisting>
<para>Start the service:</para>
<screen>&prompt.root; <userinput>service lpd start</userinput>
Starting lpd.</screen>
</step>
<step>
<para>Print a test:</para>
<screen>&prompt.root; <userinput>printf "1. This printer can print.\n2. This is the second line.\n" | lpr</userinput></screen>
<tip>
<para>If both lines do not start at the left border, but
<quote>stairstep</quote> instead, see
<xref linkend="printing-lpd-filters-stairstep"/>.</para>
</tip>
<para>Text files can now be printed with
<command>lpr</command>. Give the filename on the command
line, or pipe output directly into
<command>lpr</command>.</para>
<screen>&prompt.user; <userinput>lpr textfile.txt</userinput>
&prompt.user; <userinput>ls -lh | lpr</userinput></screen>
</step>
</procedure>
</sect1>
<sect1 xml:id="printing-connections">
<title>Printer Connections</title>
<para>Printers are connected to computer systems in a variety of
ways. Small desktop printers are usually connected directly to
a computer's <acronym>USB</acronym> port. Older printers are
connected to a parallel or <quote>printer</quote> port. Some
printers are directly connected to a network, making it easy for
multiple computers to share them. A few printers use a rare
serial port connection.</para>
<para>&os; can communicate with all of these types of
printers.</para>
<variablelist>
<varlistentry xml:id="printing-connections-usb">
<term><acronym>USB</acronym></term>
<listitem>
<para><acronym>USB</acronym> printers can be connected to
any available <acronym>USB</acronym> port on the
computer.</para>
<para>When &os; detects a <acronym>USB</acronym> printer,
two device entries are created:
<filename>/dev/ulpt0</filename> and
<filename>/dev/unlpt0</filename>. Data sent to either
device will be relayed to the printer. After each print
job, <filename>ulpt0</filename> resets the
<acronym>USB</acronym> port. Resetting the port can cause
problems with some printers, so the
<filename>unlpt0</filename> device is usually used
instead. <filename>unlpt0</filename> does not reset the
USB port at all.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="printing-connections-parallel">
<term>Parallel (<acronym>IEEE</acronym>-1284)</term>
<listitem>
<para>The parallel port device is
<filename>/dev/lpt0</filename>. This device appears
whether a printer is attached or not, it is not
autodetected.</para>
<para>Vendors have largely moved away from these
<quote>legacy</quote> ports, and many computers no longer
have them. Adapters can be used to connect a parallel
printer to a <acronym>USB</acronym> port. With such an
adapter, the printer can be treated as if it were actually
a <acronym>USB</acronym> printer. Devices called
<emphasis>print servers</emphasis> can also be used to
connect parallel printers directly to a network.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="printing-connections-serial">
<term>Serial (RS-232)</term>
<listitem>
<para>Serial ports are another legacy port, rarely used for
printers except in certain niche applications. Cables,
connectors, and required wiring vary widely.</para>
<para>For serial ports built into a motherboard, the serial
device name is <filename>/dev/cuau0</filename> or
<filename>/dev/cuau1</filename>. Serial
<acronym>USB</acronym> adapters can also be used, and
these will appear as
<filename>/dev/cuaU<replaceable>0</replaceable></filename>.</para>
<para>Several communication parameters must be known to
communicate with a serial printer. The most important are
<emphasis>baud rate</emphasis> or <acronym>BPS</acronym>
(Bits Per Second) and <emphasis>parity</emphasis>. Values
vary, but typical serial printers use a baud rate of 9600
and no parity.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="printing-connections-network">
<term>Network</term>
<listitem>
<para>Network printers are connected directly to the local
computer network.</para>
<para>The <acronym>DNS</acronym> hostname of the printer
must be known. If the printer is assigned a dynamic
address by <acronym>DHCP</acronym>, <acronym>DNS</acronym>
should be dynamically updated so that the host name always
has the correct <acronym>IP</acronym> address. Network
printers are often given static <acronym>IP</acronym>
addresses to avoid this problem.</para>
<para>Most network printers understand print jobs sent with
the <acronym>LPD</acronym> protocol. A print queue name
can also be specified. Some printers process data
differently depending on which queue is used. For
example, a <literal>raw</literal> queue prints the data
unchanged, while the <literal>text</literal> queue adds
carriage returns to plain text.</para>
<para>Many network printers can also print data sent
directly to port 9100.</para>
</listitem>
</varlistentry>
</variablelist>
<sect2 xml:id="printing-connections-summary">
<title>Summary</title>
<para>Wired network connections are usually the easiest to
set up and give the fastest printing. For direct connection
to the computer, <acronym>USB</acronym> is preferred for speed
and simplicity. Parallel connections work but have
limitations on cable length and speed. Serial connections are
more difficult to configure. Cable wiring differs between
models, and communication parameters like baud rate and parity
bits must add to the complexity. Fortunately, serial printers
are rare.</para>
</sect2>
</sect1>
<sect1 xml:id="printing-pdls">
<title>Common Page Description Languages</title>
<para>Data sent to a printer must be in a language that the
printer can understand. These languages are called Page
Description Languages, or <acronym>PDL</acronym>s.</para>
<variablelist>
<varlistentry xml:id="print-pdls-ascii">
<term><acronym>ASCII</acronym></term>
<listitem>
<para>Plain <acronym>ASCII</acronym> text is the simplest
way to send data to a printer. Characters correspond one
to one with what will be printed: an <literal>A</literal>
in the data prints an <literal>A</literal> on the page.
Very little formatting is available. There is no way to
select a font or proportional spacing. The forced
simplicity of plain <acronym>ASCII</acronym> means that
text can be printed straight from the computer with little
or no encoding or translation. The printed output
corresponds directly with what was sent.</para>
<para>Some inexpensive printers cannot print plain
<acronym>ASCII</acronym> text. This makes them more
difficult to set up, but it is usually still
possible.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="print-pdls-postscript">
<term>&postscript;</term>
<listitem>
<para>&postscript; is almost the opposite of
<acronym>ASCII</acronym>. Rather than simple text, a
&postscript; program is a set of instructions that draw
the final document. Different fonts and graphics can be
used. However, this power comes at a price. The program
that draws the page must be written. Usually this program
is generated by application software, so the process is
invisible to the user.</para>
<para>Inexpensive printers sometimes leave out &postscript;
compatibility as a cost-saving measure.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="print-pdls-pcl">
<term><acronym>PCL</acronym> (Printer Command Language)</term>
<listitem>
<para><acronym>PCL</acronym> is an extension of
<acronym>ASCII</acronym>, adding escape sequences for
formatting, font selection, and printing graphics. Many
printers provide <acronym>PCL5</acronym> support. Some
support the newer <acronym>PCL6</acronym> or
<acronym>PCLXL</acronym>. These later versions are
supersets of <acronym>PCL5</acronym> and can provide
faster printing.</para>
</listitem>
</varlistentry>
<varlistentry xml:id="print-pdls-host-based">
<term>Host-Based</term>
<listitem>
<para>Manufacturers can reduce the cost of a printer by
giving it a simple processor and very little memory.
These printers are not capable of printing plain text.
Instead, bitmaps of text and graphics are drawn by a
driver on the host computer and then sent to the printer.
These are called <emphasis>host-based</emphasis>
printers.</para>
<para>Communication between the driver and a host-based
printer is often through proprietary or undocumented
protocols, making them functional only on the most common
operating systems.</para>
</listitem>
</varlistentry>
</variablelist>
<sect2 xml:id="print-pdls-table">
<title>Converting &postscript; to Other
<acronym>PDL</acronym>s</title>
<para>Many applications from the Ports Collection and &os;
utilities produce &postscript; output. This table shows
the utilities available to convert that into other common
<acronym>PDL</acronym>s:</para>
<table xml:id="print-pdls-ps-to-other-tbl" frame="none">
<title>Output <acronym>PDL</acronym>s</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry align="left">Output
<acronym>PDL</acronym></entry>
<entry align="left">Generated By</entry>
<entry align="left">Notes</entry>
</row>
</thead>
<tbody>
<row>
<entry><acronym>PCL</acronym> or
<acronym>PCL5</acronym></entry>
<entry><package
role="port">print/ghostscript9-base</package></entry>
<entry><literal>-sDEVICE=ljet4</literal> for monochrome,
<literal>-sDEVICE=cljet5</literal> for color</entry>
</row>
<row>
<entry><acronym>PCLXL</acronym> or
<acronym>PCL6</acronym></entry>
<entry><package
role="port">print/ghostscript9-base</package></entry>
<entry><literal>-sDEVICE=pxlmono</literal> for
monochrome, <literal>-sDEVICE=pxlcolor</literal> for
color</entry>
</row>
<row>
<entry><acronym>ESC/P2</acronym></entry>
<entry><package
role="port">print/ghostscript9-base</package></entry>
<entry><literal>-sDEVICE=uniprint</literal></entry>
</row>
<row>
<entry><acronym>XQX</acronym></entry>
<entry><package
role="port">print/foo2zjs</package></entry>
<entry/>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 xml:id="print-pdls-summary">
<title>Summary</title>
<para>For the easiest printing, choose a printer that supports
&postscript;. Printers that support <acronym>PCL</acronym>
are the next preferred. With
<package role="port">print/ghostscript9-base</package>, these
printers can be used as if they understood &postscript;
natively. Printers that support &postscript; or
<acronym>PCL</acronym> directly almost always support direct
printing of plain <acronym>ASCII</acronym> text files
also.</para>
<para>Line-based printers like typical inkjets usually do not
support &postscript; or <acronym>PCL</acronym>. They often
can print plain <acronym>ASCII</acronym> text files.
<package role="port">print/ghostscript9-base</package>
supports the <acronym>PDL</acronym>s used by some of these
printers. However, printing an entire graphic-based page on
these printers is often very slow due to the large amount of
data to be transferred and printed.</para>
<para>Host-based printers are often more difficult to set up.
Some cannot be used at all because of proprietary
<acronym>PDL</acronym>s. Avoid these printers when
possible.</para>
<para>Descriptions of many <acronym>PDL</acronym>s can be found
at <link
xlink:href="http://www.undocprint.org/formats/page_description_languages"></link>.
The particular <acronym>PDL</acronym> used by various models
of printers can be found at <link
xlink:href="http://www.openprinting.org/printers"></link>.</para>
</sect2>
</sect1>
<sect1 xml:id="printing-direct">
<title>Direct Printing</title>
<para>For occasional printing, files can be sent directly to a
printer device without any setup. For example, a file called
<filename>sample.txt</filename> can be sent to a
<acronym>USB</acronym> printer:</para>
<screen>&prompt.root; <userinput>cp sample.txt /dev/unlpt0</userinput></screen>
<para>Direct printing to network printers depends on the
abilities of the printer, but most accept print jobs on port
9100, and &man.nc.1; can be used with them. To print the
same file to a printer with the <acronym>DNS</acronym>
hostname of <replaceable>netlaser</replaceable>:</para>
<screen>&prompt.root; <userinput>nc <replaceable>netlaser</replaceable> 9100 < sample.txt</userinput></screen>
</sect1>
<sect1 xml:id="printing-lpd">
<title><acronym>LPD</acronym> (Line Printer Daemon)</title>
<para>Printing a file in the background is called
<emphasis>spooling</emphasis>. A spooler allows the user to
continue with other programs on the computer without waiting for
the printer to slowly complete the print job.</para>
<para>&os; includes a spooler called &man.lpd.8;. Print jobs are
submitted with &man.lpr.1;.</para>
<sect2 xml:id="printing-lpd-setup">
<title>Initial Setup</title>
<para>A directory for storing print jobs is created, ownership
is set, and the permissions are set to prevent other users
from viewing the contents of those files:</para>
<screen>&prompt.root; <userinput>mkdir -p /var/spool/lpd/lp</userinput>
&prompt.root; <userinput>chown daemon:daemon /var/spool/lpd/lp</userinput>
&prompt.root; <userinput>chmod 770 /var/spool/lpd/lp</userinput></screen>
<para>Printers are defined in
<filename>/etc/printcap</filename>. An entry for each printer
includes details like a name, the port where it is attached,
and various other settings. Create
<filename>/etc/printcap</filename> with these contents:</para>
<programlisting>lp:\ <co xml:id="printing-lpd-co-name"/>
:lp=/dev/unlpt0:\ <co xml:id="printing-lpd-co-device"/>
:sh:\ <co xml:id="printing-lpd-co-header"/>
:mx#0:\ <co xml:id="printing-lpd-co-mx"/>
:sd=/var/spool/lpd/lp:\ <co xml:id="printing-lpd-co-sd"/>
:lf=/var/log/lpd-errs: <co xml:id="printing-lpd-co-lf"/></programlisting>
<calloutlist>
<callout arearefs="printing-lpd-co-name">
<para>The name of this printer. &man.lpr.1; sends print
jobs to the <literal>lp</literal> printer unless another
printer is specified with <option>-P</option>, so the
default printer should be named
<literal>lp</literal>.</para>
</callout>
<callout arearefs="printing-lpd-co-device">
<para>The device where the printer is connected. Replace
this line with the appropriate one for the connection type
shown here.</para>
<informaltable xml:id="printing-lpd-co-device-tbl">
<tgroup cols="2">
<thead>
<row>
<entry>Connection Type</entry>
<entry>Device Entry in
<filename>/etc/printcap</filename></entry>
</row>
</thead>
<tbody>
<row>
<entry><acronym>USB</acronym></entry>
<entry><programlisting>:lp=/dev/unlpt0:\</programlisting>
<para>This is the
<emphasis>non-resetting</emphasis>
<acronym>USB</acronym> printer device. If
problems are experienced, use
<filename>ulpt0</filename> instead, which resets
the <acronym>USB</acronym> port on each
use.</para></entry>
</row>
<row>
<entry>Parallel</entry>
<entry><programlisting>:lp=/dev/lpt0:\</programlisting></entry>
</row>
<row>
<entry>Network</entry>
<entry><para>For a printer supporting the
<acronym>LPD</acronym> protocol:</para>
<programlisting>:lp=:rm=<replaceable>network-printer-name</replaceable>:rp=raw:\</programlisting>
<para>For printers supporting port 9100
printing:</para>
<programlisting>:lp=9100@<replaceable>network-printer-name</replaceable>:\</programlisting>
<para>For both types, replace
<replaceable>network-printer-name</replaceable>
with the <acronym>DNS</acronym> host name of the
network printer.</para></entry>
</row>
<row>
<entry>Serial</entry>
<entry><programlisting>:lp=/dev/cuau0:br=9600:pa=none:\</programlisting>
<para>These values are for a typical serial
printer connected to a motherboard serial port.
The baud rate is 9600, and no parity is
used.</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</callout>
<callout arearefs="printing-lpd-co-header">
<para>Suppress the printing of a header page at the start of
a print job.</para>
</callout>
<callout arearefs="printing-lpd-co-mx">
<para>Do not limit the maximum size of a print job.</para>
</callout>
<callout arearefs="printing-lpd-co-sd">
<para>The path to the spooling directory for this printer.
Each printer uses its own spooling directory.</para>
</callout>
<callout arearefs="printing-lpd-co-lf">
<para>The log file where errors on this printer will be
reported.</para>
</callout>
</calloutlist>
<para>After creating <filename>/etc/printcap</filename>, use
&man.chkprintcap.8; to test it for errors:</para>
<screen>&prompt.root; <userinput>chkprintcap</userinput></screen>
<para>Fix any reported problems before continuing.</para>
<para>Enable &man.lpd.8; in
<filename>/etc/rc.conf</filename>:</para>
<programlisting>lpd_enable="YES"</programlisting>
<para>Start the service:</para>
<screen>&prompt.root; <userinput>service lpd start</userinput></screen>
</sect2>
<sect2 xml:id="printing-lpd-lpr">
<title>Printing with &man.lpr.1;</title>
<para>Documents are sent to the printer with
<command>lpr</command>. A file to be printed can be named on
the command line or piped into <command>lpr</command>. These
two commands are equivalent, sending the contents of
<filename>doc.txt</filename> to the default printer:</para>
<screen>&prompt.user; <userinput>lpr doc.txt</userinput>
&prompt.user; <userinput>cat doc.txt | lpr</userinput></screen>
<para>Printers can be selected with <option>-P</option>. To
print to a printer called
<replaceable>laser</replaceable>:</para>
<screen>&prompt.user; <userinput>lpr -Plaser doc.txt</userinput></screen>
</sect2>
<sect2 xml:id="printing-lpd-filters">
<title>Filters</title>
<para>The examples shown so far have sent the contents of a text
file directly to the printer. As long as the printer
understands the content of those files, output will be printed
correctly.</para>
<para>Some printers are not capable of printing plain text, and
the input file might not even be plain text.</para>
<para><emphasis>Filters</emphasis> allow files to be
translated or processed. The typical use is to translate one
type of input, like plain text, into a form that the printer
can understand, like &postscript; or <acronym>PCL</acronym>.
Filters can also be used to provide additional features, like
adding page numbers or highlighting source code to make it
easier to read.</para>
<para>The filters discussed here are
<emphasis>input filters</emphasis> or
<emphasis>text filters</emphasis>. These filters convert the
incoming file into different forms. Use &man.su.1; to become
<systemitem class="username">root</systemitem> before
creating the files.</para>
<para>Filters are specified in
<filename>/etc/printcap</filename> with the
<literal>if=</literal> identifier. To use
<filename>/usr/local/libexec/lf2crlf</filename> as a filter,
modify <filename>/etc/printcap</filename> like this:</para>
<programlisting>lp:\
:lp=/dev/unlpt0:\
:sh:\
:mx#0:\
:sd=/var/spool/lpd/lp:\
:if=/usr/local/libexec/lf2crlf:\ <co xml:id="printing-lpd-filters-co-if"/>
:lf=/var/log/lpd-errs:</programlisting>
<calloutlist>
<callout arearefs="printing-lpd-filters-co-if">
<para><literal>if=</literal> identifies the
<emphasis>input filter</emphasis> that will be used on
incoming text.</para>
</callout>
</calloutlist>
<tip xml:id="printing-lpd-filters-oneline">
<para>The backslash <emphasis>line continuation</emphasis>
characters at the end of the lines in
<filename>printcap</filename> entries reveal that an entry
for a printer is really just one long line with entries
delimited by colon characters. An earlier example can be
rewritten as a single less-readable line:</para>
<programlisting>lp:lp=/dev/unlpt0:sh:mx#0:sd=/var/spool/lpd/lp:if=/usr/local/libexec/lf2crlf:lf=/var/log/lpd-errs:</programlisting>
</tip>
<sect3 xml:id="printing-lpd-filters-stairstep">
<title>Preventing Stairstepping on Plain Text Printers</title>
<para>Typical &os; text files contain only a single line feed
character at the end of each line. These lines will
<quote>stairstep</quote> on a standard printer:</para>
<programlisting>A printed file looks
like the steps of a staircase
scattered by the wind</programlisting>
<para>A filter can convert the newline characters into
carriage returns and newlines. The carriage returns make
the printer return to the left after each line. Create
<filename>/usr/local/libexec/lf2crlf</filename> with these
contents:</para>
<programlisting>#!/bin/sh
CR=$'\r'
/usr/bin/sed -e "s/$/${CR}/g"</programlisting>
<para>Set the permissions and make it executable:</para>
<screen>&prompt.root; <userinput>chmod 555 /usr/local/libexec/lf2crlf</userinput></screen>
<para>Modify <filename>/etc/printcap</filename> to use the
new filter:</para>
<programlisting>:if=/usr/local/libexec/lf2crlf:\</programlisting>
<para>Test the filter by printing the same plain text file.
The carriage returns will cause each line to start at the
left side of the page.</para>
</sect3>
<sect3 xml:id="printing-lpd-filters-enscript">
<title>Fancy Plain Text on &postscript; Printers with
<package>print/enscript</package></title>
<para><acronym>GNU</acronym>
<application>Enscript</application> converts plain text
files into nicely-formatted &postscript; for printing on
&postscript; printers. It adds page numbers, wraps long
lines, and provides numerous other features to make printed
text files easier to read. Depending on the local paper
size, install either
<package role="port">print/enscript-letter</package> or
<package role="port">print/enscript-a4</package> from the
Ports Collection.</para>
<para>Create <filename>/usr/local/libexec/enscript</filename>
with these contents:</para>
<programlisting>#!/bin/sh
/usr/local/bin/enscript -o -</programlisting>
<para>Set the permissions and make it executable:</para>
<screen>&prompt.root; <userinput>chmod 555 /usr/local/libexec/enscript</userinput></screen>
<para>Modify <filename>/etc/printcap</filename> to use the
new filter:</para>
<programlisting>:if=/usr/local/libexec/enscript:\</programlisting>
<para>Test the filter by printing a plain text file.</para>
</sect3>
<sect3 xml:id="printing-lpd-filters-ps2pcl">
<title>Printing &postscript; to
<acronym>PCL</acronym> Printers</title>
<para>Many programs produce &postscript; documents.
However, inexpensive printers often only understand plain
text or <acronym>PCL</acronym>. This filter converts
&postscript; files to <acronym>PCL</acronym> before sending
them to the printer.</para>
<para>Install the Ghostscript &postscript; interpreter,
<package role="port">print/ghostscript9-base</package>,
from the Ports Collection.</para>
<para>Create <filename>/usr/local/libexec/ps2pcl</filename>
with these contents:</para>
<programlisting>#!/bin/sh
/usr/local/bin/gs -dSAFER -dNOPAUSE -dBATCH -q -sDEVICE=ljet4 -sOutputFile=- -</programlisting>
<para>Set the permissions and make it executable:</para>
<screen>&prompt.root; <userinput>chmod 555 /usr/local/libexec/ps2pcl</userinput></screen>
<para>&postscript; input sent to this script will be rendered
and converted to <acronym>PCL</acronym> before being sent on
to the printer.</para>
<para>Modify <filename>/etc/printcap</filename> to use this
new input filter:</para>
<programlisting>:if=/usr/local/libexec/ps2pcl:\</programlisting>
<para>Test the filter by sending a small &postscript; program
to it:</para>
<screen>&prompt.user; <userinput>printf "%%\!PS \n /Helvetica findfont 18 scalefont setfont \
72 432 moveto (PostScript printing successful.) show showpage \004" | lpr</userinput></screen>
</sect3>
<sect3 xml:id="printing-lpd-filters-smart">
<title>Smart Filters</title>
<para>A filter that detects the type of input and
automatically converts it to the correct format for the
printer can be very convenient. The first two characters of
a &postscript; file are usually <literal>%!</literal>. A
filter can detect those two characters. &postscript; files
can be sent on to a &postscript; printer unchanged. Text
files can be converted to &postscript; with
<application>Enscript</application> as shown earlier.
Create <filename>/usr/local/libexec/psif</filename> with
these contents:</para>
<programlisting>#!/bin/sh
#
# psif - Print PostScript or plain text on a PostScript printer
#
IFS="" read -r first_line
first_two_chars=`expr "$first_line" : '\(..\)'`
case "$first_two_chars" in
%!)
# %! : PostScript job, print it.
echo "$first_line" && cat && exit 0
exit 2
;;
*)
# otherwise, format with enscript
( echo "$first_line"; cat ) | /usr/local/bin/enscript -o - && exit 0
exit 2
;;
esac</programlisting>
<para>Set the permissions and make it executable:</para>
<screen>&prompt.root; <userinput>chmod 555 /usr/local/libexec/psif</userinput></screen>
<para>Modify <filename>/etc/printcap</filename> to use this
new input filter:</para>
<programlisting>:if=/usr/local/libexec/psif:\</programlisting>
<para>Test the filter by printing &postscript; and plain text
files.</para>
</sect3>
<sect3 xml:id="printing-lpd-filters-othersmart">
<title>Other Smart Filters</title>
<para>Writing a filter that detects many different types of
input and formats them correctly is challenging.
<package role="port">print/apsfilter</package> from the
Ports Collection is a smart <quote>magic</quote> filter that
detects dozens of file types and automatically converts them
to the <acronym>PDL</acronym> understood by the printer.
See <link xlink:href="http://www.apsfilter.org"></link> for
more details.</para>
</sect3>
</sect2>
<sect2 xml:id="printing-lpd-queues">
<title>Multiple Queues</title>
<para>The entries in <filename>/etc/printcap</filename> are
really definitions of <emphasis>queues</emphasis>. There can
be more than one queue for a single printer. When combined
with filters, multiple queues provide users more control over
how their jobs are printed.</para>
<para>As an example, consider a networked &postscript; laser
printer in an office. Most users want to print plain text,
but a few advanced users want to be able to print &postscript;
files directly. Two entries can be created for the same
printer in <filename>/etc/printcap</filename>:</para>
<programlisting>textprinter:\
:lp=9100@officelaser:\
:sh:\
:mx#0:\
:sd=/var/spool/lpd/textprinter:\
:if=/usr/local/libexec/enscript:\
:lf=/var/log/lpd-errs:
psprinter:\
:lp=9100@officelaser:\
:sh:\
:mx#0:\
:sd=/var/spool/lpd/psprinter:\
:lf=/var/log/lpd-errs:</programlisting>
<para>Documents sent to <literal>textprinter</literal> will be
formatted by the
<filename>/usr/local/libexec/enscript</filename> filter shown
in an earlier example. Advanced users can print &postscript;
files on <literal>psprinter</literal>, where no filtering is
done.</para>
<para>This multiple queue technique can be used to provide
direct access to all kinds of printer features. A printer
with a duplexer could use two queues, one for ordinary
single-sided printing, and one with a filter that sends the
command sequence to enable double-sided printing and then
sends the incoming file.</para>
</sect2>
<sect2 xml:id="printing-lpd-monitor">
<title>Monitoring and Controlling Printing</title>
<para>Several utilities are available to monitor print jobs and
check and control printer operation.</para>
<sect3 xml:id="printing-lpd-monitor-lpq">
<title>&man.lpq.1;</title>
<para>&man.lpq.1; shows the status of a user's print
jobs. Print jobs from other users are not shown.</para>
<para>Show the current user's pending jobs on a single
printer:</para>
<screen>&prompt.user; <userinput>lpq -P<replaceable>lp</replaceable></userinput>
Rank Owner Job Files Total Size
1st jsmith 0 (standard input) 12792 bytes</screen>
<para>Show the current user's pending jobs on all
printers:</para>
<screen>&prompt.user; <userinput>lpq -a</userinput>
lp:
Rank Owner Job Files Total Size
1st jsmith 1 (standard input) 27320 bytes
laser:
Rank Owner Job Files Total Size
1st jsmith 287 (standard input) 22443 bytes</screen>
</sect3>
<sect3 xml:id="printing-lpd-monitor-lprm">
<title>&man.lprm.1;</title>
<para>&man.lprm.1; is used to remove print jobs. Normal users
are only allowed to remove their own jobs.
<systemitem class="username">root</systemitem> can remove
any or all jobs.</para>
<para>Remove all pending jobs from a printer:</para>
<screen>&prompt.root; <userinput>lprm -P<replaceable>lp</replaceable> -</userinput>
dfA002smithy dequeued
cfA002smithy dequeued
dfA003smithy dequeued
cfA003smithy dequeued
dfA004smithy dequeued
cfA004smithy dequeued</screen>
<para>Remove a single job from a
printer. &man.lpq.1; is used to find the job number.</para>
<screen>&prompt.user; <userinput>lpq</userinput>
Rank Owner Job Files Total Size
1st jsmith 5 (standard input) 12188 bytes
&prompt.user; <userinput>lprm -P<replaceable>lp</replaceable> <replaceable>5</replaceable></userinput>
dfA005smithy dequeued
cfA005smithy dequeued</screen>
</sect3>
<sect3 xml:id="printing-lpd-monitor-lpc">
<title>&man.lpc.8;</title>
<para>&man.lpc.8; is used to check and modify printer status.
<literal>lpc</literal> is followed by a command and an
optional printer name. <literal>all</literal> can be used
instead of a specific printer name, and the command will be
applied to all printers. Normal users can view status with
&man.lpc.8;. Only
<systemitem class="username">root</systemitem> can use
commands which modify printer status.</para>
<para>Show the status of all printers:</para>
<screen>&prompt.user; <userinput>lpc status all</userinput>
lp:
queuing is enabled
printing is enabled
1 entry in spool area
printer idle
laser:
queuing is enabled
printing is enabled
1 entry in spool area
waiting for laser to come up</screen>
<para>Prevent a printer from accepting new jobs, then begin
accepting new jobs again:</para>
<screen>&prompt.root; <userinput>lpc disable <replaceable>lp</replaceable></userinput>
lp:
queuing disabled
&prompt.root; <userinput>lpc enable <replaceable>lp</replaceable></userinput>
lp:
queuing enabled</screen>
<para>Stop printing, but continue to accept new jobs. Then
begin printing again:</para>
<screen>&prompt.root; <userinput>lpc stop <replaceable>lp</replaceable></userinput>
lp:
printing disabled
&prompt.root; <userinput>lpc start <replaceable>lp</replaceable></userinput>
lp:
printing enabled
daemon started</screen>
<para>Restart a printer after some error condition:</para>
<screen>&prompt.root; <userinput>lpc restart <replaceable>lp</replaceable></userinput>
lp:
no daemon to abort
printing enabled
daemon restarted</screen>
<para>Turn the print queue off and disable printing, with a
message to explain the problem to users:</para>
<screen>&prompt.root; <userinput>lpc down <replaceable>lp</replaceable> Repair parts will arrive on Monday</userinput>
lp:
printer and queuing disabled
status message is now: Repair parts will arrive on Monday</screen>
<para>Re-enable a printer that is down:</para>
<screen>&prompt.root; <userinput>lpc up <replaceable>lp</replaceable></userinput>
lp:
printing enabled
daemon started</screen>
<para>See &man.lpc.8; for more commands and options.</para>
</sect3>
</sect2>
<sect2 xml:id="printing-lpd-shared">
<title>Shared Printers</title>
<para>Printers are often shared by multiple users in businesses
and schools. Additional features are provided to make sharing
printers more convenient.</para>
<sect3 xml:id="printing-shared-aliases">
<title>Aliases</title>
<para>The printer name is set in the first line of the
entry in <filename>/etc/printcap</filename>. Additional
names, or <emphasis>aliases</emphasis>, can be added after
that name. Aliases are separated from the name and each
other by vertical bars:</para>
<programlisting>lp|<replaceable>repairsprinter</replaceable>|<replaceable>salesprinter</replaceable>:\</programlisting>
<para>Aliases can be used in place of the printer name. For
example, users in the Sales department print to their
printer with</para>
<screen>&prompt.user; <userinput>lpr -P<replaceable>salesprinter</replaceable> <replaceable>sales-report.txt</replaceable></userinput></screen>
<para>Users in the Repairs department print to
<emphasis>their</emphasis> printer with</para>
<screen>&prompt.user; <userinput>lpr -P<replaceable>repairsprinter</replaceable> <replaceable>repairs-report.txt</replaceable></userinput></screen>
<para>All of the documents print on that single printer. When
the Sales department grows enough to need their own printer,
the alias can be removed from the shared printer entry and
used as the name of a new printer. Users in both
departments continue to use the same commands, but the Sales
documents are sent to the new printer.</para>
</sect3>
<sect3 xml:id="printing-shared-headers">
<title>Header Pages</title>
<para>It can be difficult for users to locate their documents
in the stack of pages produced by a busy shared printer.
<emphasis>Header pages</emphasis> were created to solve this
problem. A header page with the user name and document name
is printed before each print job. These pages are also
sometimes called <emphasis>banner</emphasis> or
<emphasis>separator</emphasis> pages.</para>
<para>Enabling header pages differs depending on whether the
printer is connected directly to the computer with a
<acronym>USB</acronym>, parallel, or serial cable, or
is connected remotely over a network.</para>
<para>Header pages on directly-connected printers are enabled
by removing the <literal>:sh:\</literal> (Suppress Header)
line from the entry in <filename>/etc/printcap</filename>.
These header pages only use line feed characters for new
lines. Some printers will need the
<filename>/usr/share/examples/printing/hpif</filename>
filter to prevent stairstepped text. The filter configures
<acronym>PCL</acronym> printers to print both carriage
returns and line feeds when a line feed is received.</para>
<para>Header pages for network printers must be configured on
the printer itself. Header page entries in
<filename>/etc/printcap</filename> are ignored. Settings
are usually available from the printer front panel or a
configuration web page accessible with a web browser.</para>
</sect3>
<!-- conversion filters?,
restricting printer usage?, accounting? -->
</sect2>
<sect2 xml:id="printing-lpd-references">
<title>References</title>
<para>Example files: <filename
role="directory">/usr/share/examples/printing/</filename>.</para>
<para>The <emphasis>4.3BSD Line Printer Spooler
Manual</emphasis>,
<filename>/usr/share/doc/smm/07.lpd/paper.ascii.gz</filename>.</para>
<para>Manual pages: &man.printcap.5;, &man.lpd.8;, &man.lpr.1;,
&man.lpc.8;, &man.lprm.1;, &man.lpq.1;.</para>
</sect2>
</sect1>
<sect1 xml:id="printing-other">
<title>Other Printing Systems</title>
<para>Several other printing systems are available in
addition to the built-in &man.lpd.8;. These systems
offer support for other protocols or additional features.</para>
<sect2 xml:id="printing-other-cups">
<title><acronym>CUPS</acronym> (Common &unix; Printing
System)</title>
<para><acronym>CUPS</acronym> is a popular printing system
available on many operating systems. Using
<acronym>CUPS</acronym> on &os; is documented in a separate
article:<link xlink:href="&url.articles.cups;"></link></para>
</sect2>
<sect2 xml:id="printing-other-hplip">
<title>HPLIP</title>
<para>Hewlett Packard provides a printing system that supports
many of their inkjet and laser printers. The port is
<package role="port">print/hplip</package>. The main web page
is at <link
xlink:href="http://hplipopensource.com/hplip-web/index.html"></link>.
The port handles all the installation details on &os;.
Configuration information is shown at <link
xlink:href="http://hplipopensource.com/hplip-web/install/manual/hp_setup.html"></link>.</para>
</sect2>
<sect2 xml:id="printing-other-lprng">
<title>LPRng</title>
<para><application>LPRng</application> was developed as an
enhanced alternative to &man.lpd.8;. The port is
<package role="port">sysutils/LPRng</package>. For details
and documentation, see
<link xlink:href="http://www.lprng.com/"></link>.</para>
</sect2>
</sect1>
</chapter>