diff options
Diffstat (limited to 'en/handbook/printing/chapter.sgml')
-rw-r--r-- | en/handbook/printing/chapter.sgml | 4919 |
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 “Simple Printer Setup,” it is - actually fairly complex. Getting the printer to work with your - computer and the LPD spooler is the hardest part. The advanced - options like header pages and accounting are fairly easy once you - get the printer working.</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 - “Centronics” 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—such as a - terminal or a modem—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 “proper serial cable” 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 “DTE-to-DCE” - 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 - “DTE-to-DTE” 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 - “in-band” or “software”) - 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 > /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 > /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> > /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>><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 && 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> -!"#$%&'()*+,-./01234 -"#$%&'()*+,-./012345 -#$%&'()*+,-./0123456 -$%&'()*+,-./01234567 -%&'()*+,-./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 && printf "\f" && exit 0 -exit 2</programlisting> - </listitem> - </varlistentry> - - <varlistentry><term>It produced the “staircase - effect.”</term> - - <listitem> - <para>You got the following on paper:</para> - - <programlisting> -!"#$%&'()*+,-./01234 - "#$%&'()*+,-./012345 - #$%&'()*+,-./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&k2G" && cat && printf "\033&l0H" && 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 “opposite” of the staircase - effect, described above, and is much rarer. Somewhere, - the LF characters that FreeBSD uses to end a line are - being treated as CR characters to return the print - location to the left edge of the paper, but not also - down a line.</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 - “print job”, which is sent to the LPD spooling - system. Each printer has a queue of jobs, and your job waits in - that queue along with other jobs from yourself and from other - users. The printer prints those jobs in a first-come, first-served - order.</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 “job number” 9. Every - job for a printer gets a unique job number. Most of the time you - can ignore the job number, but you will need it if you want to - cancel the job; see section - <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 “Rank” column), which means the printer should be - currently printing that job. The second job consists of data - passed as the standard input to the</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—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 “under - the hood” when LPD uses filters. This knowledge could help - you anticipate and debug problems you might encounter as you - install more and more filters on each of your printers.</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" && cat && printf "\004" && exit 0 - exit 2 -else - # - # Plain text, convert it, then print it. - # - ( echo "$first_line"; cat ) | /usr/local/bin/textps && printf "\004" && exit 0 - exit 2 -fi</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&k2G" || exit 2 - -# -# Read first two characters of the file -# -read first_line -first_two_chars=`expr "$first_line" : '\(..\)'` - -if [ "$first_two_chars" = "%!" ]; then - # - # It is PostScript; use Ghostscript to scan-convert and print it - # - /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 -sOutputFile=- - \ - && exit 0 -else - # - # Plain text or HP/PCL, so just print it directly; print a form - # at the end to eject the last page. - # - echo "$first_line" && cat && printf "\f" && exit 0 -fi - -exit 2</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 “print - Printerleaf files.”</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 \ - && 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&k2G" && fpr && printf "\f" && 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>&2 - cleanup - exit 2 -} - -# -# If user removes the job, LPD will send SIGINT, so trap SIGINT -# (and a few other signals) to clean up after ourselves. -# -trap cleanup 1 2 15 - -# -# Make sure we are not colliding with any existing files. -# -cleanup - -# -# Link the DVI input file to standard input (the file to print). -# -ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0" - -# -# Make LF = CR+LF -# -printf "\033&k2G" || fatal "Cannot initialize printer" - -# -# Convert and print. Return value from dvilj2p does not seem to be -# reliable, so we ignore it. -# -dvilj2p -M1 -q -e- dfhp$$.dvi - -# -# Clean up and exit -# -cleanup -exit 0</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—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 “suppress - header”) 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&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 “add one page” to the text filter or any of the - conversion filters (which do have user and host information) - since users can suppress header pages with <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—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` <user> <host> <job>" 1>&2 - exit 1 -fi - -# -# Save these, mostly for readability in the PostScript, below. -# -user=$1 -host=$2 -job=$3 -date=`date` - -# -# Send the PostScript code to stdout. -# -exec cat <<EOF -%!PS - -% -% Make sure we do not interfere with user's job that will follow -% -save - -% -% Make a thick, unpleasant border around the edge of the paper. -% -$border $border moveto -$page_width $border 2 mul sub 0 rlineto -0 $page_height $border 2 mul sub rlineto -currentscreen 3 -1 roll pop 100 3 1 roll setscreen -$border 2 mul $page_width sub 0 rlineto closepath -0.8 setgray 10 setlinewidth stroke 0 setgray - -% -% Display user's login name, nice and large and prominent -% -/Helvetica-Bold findfont 64 scalefont setfont -$page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto -($user) show - -% -% Now show the boring particulars -% -/Helvetica findfont 14 scalefont setfont -/y 200 def -[ (Job:) (Host:) (Date:) ] { -200 y moveto show /y y 18 sub def } -forall - -/Helvetica-Bold findfont 14 scalefont setfont -/y 200 def -[ ($job) ($host) ($date) ] { - 270 y moveto show /y y 18 sub def -} forall - -% -% That is it -% -restore -showpage -EOF</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>&2 - exit 2 -} - -while getopts "x:y:n:h:" option; do - case $option in - x|y) ;; # Ignore - n) login=$OPTARG ;; - h) host=$OPTARG ;; - *) echo "LPD started `basename $0` wrong." 1>&2 - exit 2 - ;; - esac -done - -[ "$login" ] || fail "No login name" -[ "$host" ] || fail "No host name" - -( /usr/local/libexec/make-ps-header $login $host "DVI File" - /usr/local/bin/dvips -f ) | eval /usr/local/libexec/lprps $orig_args</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 “suppress header page” 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 “attach” 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 <printer-hostname> <port-number>"; - -$printer_host = $ARGV[0]; -$printer_port = $ARGV[1]; - -require 'sys/socket.ph'; - -($ignore, $ignore, $protocol) = getprotobyname('tcp'); -($ignore, $ignore, $ignore, $ignore, $address) - = gethostbyname($printer_host); - -$sockaddr = pack('S n a4 x8', &AF_INET, $printer_port, $address); - -socket(PRINTER, &PF_INET, &SOCK_STREAM, $protocol) - || die "Can't create TCP/IP stream socket: $!"; -connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!"; -while (<STDIN>) { print PRINTER; } -exit 0;</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 > /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 “token” 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—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 “print quotas.” 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>…</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—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: “What other spooling systems are out there (and work with - FreeBSD)?”</para> - - <para>Unfortunately, I have located only <emphasis>two</emphasis> - alternatives—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 “LPR: the Next - Generation” is a complete rewrite of PLP. Patrick Powell - and Justin Mason (the principal maintainer of PLP) - collaborated to make LPRng. The main site for LPRng is - <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: ---> - |