From 45c6c942f9dd38db66734efb05e8306a21fc0188 Mon Sep 17 00:00:00 2001 From: John Fieber Date: Sun, 1 Oct 1995 04:43:15 +0000 Subject: [PATCH] Added a very complete new chapter on printing. This brings the printed handbook to ~275 pages. Submitted by: Sean Kelly --- handbook/Makefile | 5 +- handbook/authors.sgml | 6 +- handbook/handbook.sgml | 8 +- handbook/printing.sgml | 3878 ++++++++++++++++++++++++++++++++++++++++ handbook/sections.sgml | 3 +- 5 files changed, 3893 insertions(+), 7 deletions(-) create mode 100644 handbook/printing.sgml diff --git a/handbook/Makefile b/handbook/Makefile index fa00946625..c8fa84f6af 100644 --- a/handbook/Makefile +++ b/handbook/Makefile @@ -1,11 +1,12 @@ -# $Id: Makefile,v 1.3 1995-09-25 18:23:02 wollman Exp $ +# $Id: Makefile,v 1.4 1995-10-01 04:43:11 jfieber Exp $ SRCS= authors.sgml basics.sgml bibliography.sgml boothelp.sgml SRCS+= booting.sgml contrib.sgml crypt.sgml ctm.sgml current.sgml dialup.sgml SRCS+= diskless.sgml dma.sgml eresources.sgml esdi.sgml glossary.sgml SRCS+= handbook.sgml history.sgml hw.sgml install.sgml kerberos.sgml SRCS+= kerneldebug.sgml memoryuse.sgml mirrors.sgml nfs.sgml nutshell.sgml -SRCS+= porting.sgml ports.sgml ppp.sgml relnotes.sgml scsi.sgml sections.sgml +SRCS+= porting.sgml ports.sgml ppp.sgml printing.sgml relnotes.sgml +SRCS+= scsi.sgml sections.sgml SRCS+= skey.sgml slipc.sgml slips.sgml submitters.sgml sup.sgml SRCS+= troubleshooting.sgml userppp.sgml diff --git a/handbook/authors.sgml b/handbook/authors.sgml index 93fa26190a..b6f5a6b758 100644 --- a/handbook/authors.sgml +++ b/handbook/authors.sgml @@ -1,4 +1,4 @@ - + + The FreeBSD Documentation Project - September 24, 1995 + September 30, 1995 Welcome to FreeBSD! This handbook covers the installation and day to day use of FreeBSD Release @@ -80,11 +80,13 @@ Web server">. &kerberos; * Firewalls + &printing; + The X-Window System

Pending the completion of this section, please refer to documentation supplied by the + +

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