home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Running Linux, 4th Ed.Running Linux, 4th Ed.Search this book

8.4. Managing Print Services

Linux has a fairly complicated printing system, compared to the printing services most PCs use. It allows many users to print documents at the same time, and each user can send documents from one or more applications without waiting for the previous document to finish printing. The printing system processes the files to be printed correctly on different kinds of printers connected to the computer in different ways. If you print on a network, files can be created on one host and printed out on a printer controlled by another host.

Before we go into the inner workings of the Linux printing system, we would like to point you to www.linuxprinting.org, a very comprehensive site with information about printing on Linux. If you have problems or questions concerning printing that this chapter cannot answer, this site should be your next stop.

The whole process happens without much fuss, when you press the Print button in an application or issue a command, such as lpr, to print a document. That document does not go directly to the printer, though, because it might already be busy. Instead, the document is stored in a temporary file in a directory called the printer spool directory. As the word "spool" suggests, the documents get taken out of the directory one by one as the printer becomes free. Each printer has its own spool directory.

When Linux starts, it sets up a printer daemon (an independently running process) called lpd. This process waits around, checking each spool directory for files that should be printed. When the process finds a file, it makes a copy of itself. The new lpd takes control of the print spool where the file was placed and queues it for printing. It won't send the next file to that printer until the last file has finished printing. The master lpd starts an lpd for each spooling directory on the system when a file is sent to it, so there may be as many lpd daemons running as the number of active spooling directories, plus the master lpd. Each subordinate lpd stays around until its spool directory is empty.

Your Linux installation process associates the printer port on your system to a device named in the /dev directory. You must then link that device name to the convenient printer names you use in your commands; that's the role of the printer capability file called /etc/printcap.

Another key task in printer management is to make sure you have filters in place for lpd to use when formatting documents for printing. These filters are also specified in the /etc/printcap file, and we'll talk a lot about them in this section.

There are several printer-support packages for Linux. Most distributions use the BSD-derived package that contains the lpd printer daemon. These packages include a set of utilities and manpage documents to support traditional Unix-style printing on Linux. The BSD printing system doesn't have as many administrative tools or user controls as, for example, the System V Unix printer-management system (which uses the lpsched or lprng daemon), but each user controls the files that she sends to the printer. This section describes installation and configuration of the BSD printer-support package. (The various printing utilities are described in Section 9.6 in Chapter 9.)

There is a new system called Common Unix Printer System (CUPS) that is bound to take over the Linux (if not Unix) printing world. At this point, very few distributions come with CUPS preinstalled — the BSD printing system is still ubiquitous — which is why we concentrate on the older system here. We'll look at CUPS in brief later in this chapter, though.

Some Linux distributions provide a printer-management tool that simplifies printer installation and management through a GUI. These tools are documented by the vendor that supplies them. They manage printing by controlling the same tools and files we are about to describe, but with less fine control. They can save you a lot of trouble getting started, but they don't always get things right. If you want to correct an installation set up through these tools or want to improve on their performance, you still should work through the procedures in this section.

8.4.1. Checking Printer Hardware

Before you set up printer services, be sure the printing devices are online. If you also use another operating system, such as Microsoft Windows, you can exercise the hardware to ensure that it is connected properly and working before loading Linux. Successfully printing a document from another operating system immediately eliminates one major source of woe and head scratching. Similarly, if you are going to use printer services on a network, your system should be on the network and all protocols functioning before proceeding.

A word about the so-called GDI printers (or Windows printers) is in order here. GDI printers are really brain-damaged printers in the true sense of the meaning: their "brain," the internal processing unit that builds up a page from the data sent to it, has been removed; this task is performed in the printer driver on the computer itself. The printer itself only consists of the actual printing hardware and a very small amount of software that controls the hardware. Of course, drivers for these printers are typically available only for Microsoft Windows systems (where the graphics subsystem is called GDI, which is where the name comes from), so there is hardly any hope of getting such a printer to work with Linux.

Install printer services as the root user, with superuser privileges. The superuser is the only user besides the lpd print daemon able to write directly to a printer by directing output to the corresponding output device. Other users cannot send output directly to the printer and must instead use the printer utilities to handle printing tasks.

Before you get started, you can abuse your root privileges to verify that your system's assigned device files actually have a valid link to the physical device. Just send a brief ASCII test file directly to the printer by redirection. For instance, if you have a printer on your first parallel port, its device name is probably either /dev/lp0 or /dev/lp1, depending on your installation. The following command outputs some text suited for testing a printer setup, which you can redirect to your printer. (If you have an early PostScript printer, you may need instead to send it a small PostScript test file to prevent it from getting confused. Newer PostScript printers can often perform this conversion themselves.)

lptest > /dev/lp1

The lptest utility (which may not be available on all distributions) is designed to conveniently exercise an ASCII printer or terminal to make sure it is working correctly. It sends a prepend file composed of the 96 ASCII characters in a sequence that creates a "ripple" or "barber-pole" output effect. The default output of lptest on Linux is 16,000 characters arrayed in 79-character lines, long enough to require more than one page to print. If you run lptest with no arguments, it prints the standard output to your screen, and you can see what should be sent to the printer. The lptest command allows you to trim the width of the output column and to limit the number of output lines. For example, to display an output 35 characters wide, limited to six lines, you would enter:

lptest 35 6

The output should look much like this:

!"#$%&'( )*+,-./0123456789:;<=>?@ABC
"#$%&'( )*+,-./0123456789:;<=>?@ABCD
#$%&'( )*+,-./0123456789:;<=>?@ABCDE
$%&'( )*+,-./0123456789:;<=>?@ABCDEF
%&'( )*+,-./0123456789:;<=>?@ABCDEFG
&'( )*+,-./0123456789:;<=>?@ABCDEFGH

This output is short enough that you can see the result of redirecting it to your printer without wasting a lot of paper, and it is long enough to identify many obvious problems with printing.

Of course, you can also use the cat command to direct a file to the printer. To send a PostScript test file to a PostScript printer, for example, type:

cat testfile.ps > /dev/lp1

If you have a serial printer, try directing output to the serial port to which it is connected. For the first serial port (COM1 in MS-DOS) try something like:

lptest > /dev/ttys0

or:

lptest > /dev/ttyS0

Make sure you send to the correct serial port; don't try to output the file to a serial mouse, for example. If your serial printer is on, say, the second serial port, it is addressed as /dev/ttyS1 or /dev/ttys1.

If you have a page printer that buffers a partial page, after it stops printing you may need to take the printer offline and press the Form Feed button to get it to print the last partial page. Don't forget to put the printer back online afterward. (A permanent solution is to get Linux to send the formfeed character to the printer, either by forcing it through the /etc/printcap entry for the printer or by having the printer filter-append it to the end of the file. We'll discuss these options later.)

If your little test resulted in "laddered" text (text that looks something like the following example) and then continued off the page, the printer did not insert a carriage return at the end of each line:

!"#$%&'( )*+,-./0123456789:;<=>?@ABC
                                   "#$%&'( )*+,-./0123456789:;<=>?@ABCD
                                                                      #$

You might be able to figure out what went wrong here. Text files in Unix use just a newline (also known as a linefeed, ASCII code 10) to terminate each line. MS-DOS uses both a newline and a carriage return. Your printer was therefore set up to use MS-DOS-style line endings with both newline and carriage-return characters at the end of each line. In order to print a text file from Unix, you can install a printer filter to accommodate the Unix newline, or you can reconfigure your printer to properly return to the start of the line on receipt of a newline character. Often this is simply a matter of setting a dip switch. Check your printer manual. (Be careful about changing your printer characteristics if you use multiple operating systems.)

Laddering won't be an issue if you have a printer using a page-description language, such as PostScript (the universally used page-layout language from Adobe), and you always filter plain text into that output form before printing. Filtering is described later in this chapter.

8.4.2. Gathering Resources

OK, you have your printer hardware set up and connected. You should collect a hardcopy of your resource documents (at least the manpages for the print utilities and files described here, and the Printing HOWTO file). Also, it is useful to have the technical specifications for your printer. Often these are no longer provided when you buy your printer, but you can usually download the information you need from an FTP site or a web site operated by the printer manufacturer. While you are retrieving such information, look around and see if there is documentation (such as a description of printer error messages and their meanings) that can help you troubleshoot and manage your printer. Most printer manufacturers also offer a technical manual for the printer that you can buy. This may or may not be the same volume as the service manual.

For example, on the Hewlett-Packard web site, http://www.hp.com/cposupport/software.html, you can retrieve printer technical data sheets; product specs; port-configuration information; PostScript, PCL, and HP-GL files for testing your printers (and filters); descriptions of printer control sequences you can pass to the printer to control its behavior; and documents telling how you can integrate lpd-based printing services with HP's JetAdmin package (and thereby with Netware-networked printers as well).

Now, before starting, take a deep breath; be patient with yourself. Printer services configuration is a skill that takes time to develop. If you have sufficiently standard equipment and successfully use one of the new-fangled printer management utilities to quickly and efficiently install and configure printer services, celebrate! Then note that you can probably fine-tune the installation for better performance by applying the procedures we describe next, and perhaps by using filters and utilities written specifically to support all the features of your printer model. If you decide to revise a successful printer installation, make sure you take notes on the changes you make so that you can find your way back if your changes don't do what you expected.

8.4.3. Choosing Printer Software

In order to print from Linux, you need to install the BSD print system (or an alternative system). This provides basic tools, but it does not support modern printers. Indeed, it was designed to support line printers (hence the name "line printing daemon") and devices common to the computer rooms of the 1960s and 1970s. In order to support modern printers, powerful supplemental packages provide the features most users think of as essential. (The ftp://ftp.ibiblio.org FTP site and its mirrors archive the packages we mention here.)

In this section, we discuss some important packages to support modern print services. We assume your system will have at least the groff formatter, the Ghostscript page-formatting package, and the GNU Enscript filter packages, which are described in Chapter 9. Most Linux distributions already include these as well as other formatting and printing utilities. If yours does not, you can retrieve them from the usual Linux FTP sites or take them from the CD-ROM of another distribution.

It matters where you get formatting and filtering packages. If you receive Ghostscript from a European distribution, for example, it probably defaults to an A4 paper format rather than the 8.5x11-inch paper format kept in U.S. binary archives. In either case, you can easily override the default through an lpr option passed to the filter. Alternatively, you can build the tools from source.

The trend in printer technology is away from character-oriented output and toward adoption of a page-description language (PDL) that provides sophisticated graphics and font control. By far the most popular of the PDLs is PostScript, which has been widely adopted in the Unix and Internet communities. A major reason for its acceptance is Ghostscript, a PostScript implementation copyrighted by Aladdin Enterprises. A version is also distributed under the GNU Public License through the Free Software Foundation, along with a large font library that can be used with either version and with other PostScript interpreters. Ghostscript is indispensable if you do any kind of printing besides character-based output, and it is easily extensible.

Ghostscript implements almost all the instructions of the PostScript language and supports viewer utilities, such as Ghostview, that allow PostScript documents to be displayed in an X window. Similarly, excellent filters are readily available that convert PostScript output into other printing languages, such as Hewlett-Packard's PCL, and into forms printable as raster output on inkjet, dot matrix, and laser printers. The Ghostscript package supports Adobe Type 1 and 3 PostScript fonts and provides a number of utilities for graphics format conversion and filtering. It can even generate PDF files — i.e., files that conform to the Adobe Portable Document Format specification.

Ghostscript may be insufficient to use by itself, however, because it doesn't provide printer control to switch between PostScript and text modes. Although Ghostscript does provide a filter that provides this capability (and more), the nenscript filter meets the tests of simplicity, flexibility, and reliability for most systems, so we document it here.

A typical Linux formatting and printing system might primarily use groff to format documents, creating PostScript output that is then processed by Ghostscript for printing and display.

8.4.4. Checking Print Utilities

You probably also want to install the TEX formatting package. Even if you do not install the full TEX distribution, you should at least install the xdvi utility, in order to view TEX output and (processed) Texinfo files in an X window (unless you have installed the KDE Desktop Environment, which contains a more user-friendly replacement called kdvi). Other filters can process device independent (DVI) output into forms such as PostScript (dvips) or PCL (dvilj) if you have an aversion to the Ghostscript package or need to use native printer fonts for efficient data transfer and rapid printing.

The Lout package is also worthy of consideration as an efficient and compact package to format text documents for PostScript output. It supports Level 2 PostScript and the Adobe Structuring Conventions, takes comparatively little memory, and comes with good enough documentation to learn quickly. Lout doesn't create an intermediate output form; it goes directly from markup input to PostScript output.

To support graphics work and X Window System utilities, you probably want to install other tools, some of which probably come with your distribution. A collection of current versions of the most popular print support packages for Linux can be found at the ftp://ftp.ibiblio.org Linux archive, in /pub/Linux/system/printing. The netpbm and pbmplus packages support a large variety of graphics file format conversions. (Such formats have to be converted to PostScript before you try to print them.) The Ghostview package provides display tools to view PostScript files in an X Window System environment, and also provides PostScript and PDF support for other packages, such as your web browser.

The ImageMagick package, described in Chapter 9, deserves special mention. It lets you display a large number of graphics formats in an X window and convert many file formats to other file formats. (It uses Ghostview and Ghostscript when it needs to display a PostScript image.) Most of the graphics files you can print you can also display using ImageMagick.

A "magic" filter package may also save you much grief in configuring and supporting different document output formats. We will touch on the APSfilter magic filter package, but you may prefer the Magic-Filter package instead. Both are available at the ftp://ftp.ibiblio.org FTP archive. For more on magic filters, see Section 8.4.9 later in this chapter.

If you want to support fax devices, you can use the tiffg3 utility with Ghostscript to output Group III fax format files. To control a Class 1 or Class 2 fax modem on your Linux host, you can use the efax package, which is provided in many distributions, or you can install and configure the more capable, but more complex, FlexFax or HylaFax packages.

There are additional tools to support double-sided printing on laser printers, and packages that convert PostScript to less common printer-control languages to support Canon and IBM Proprinter devices, for example. There is a package to support printing in Chinese on laser printers and bitmap devices. Most of these packages don't directly affect management of print services, so we don't describe them in detail here, but this is a good time to install them if you wish to use them.

For the benefit of your users, make sure that all the manual pages for the packages you install are prepared properly when you complete your installations. Then run /sbin/mkwhatis (/usr/bin/mandb on Debian) to build the manual page index file that facilitates locating information online. Some packages, such as Ghostscript, also provide additional documention that you can print or make available on the system for reference. (Linux distributions tend to omit these documents, but you can FTP them from the sites where the software packages are developed and maintained. The GNU archives of the Free Software Foundation, for example, are accessed by anonymous FTP at ftp://GNU.ai.mit.edu.)

8.4.5. Setting Up the Printcap File

The essence of printer configuration is creating correct entries in the printer capabilities file, /etc/printcap. A simple printcap entry for an HP LaserJet 4MP laser printer attached to the first (bidirectional) parallel port on an ISA bus PC might look something like this:[31]

[31]In this chapter, we use ljet4 in several examples. Be aware that the HP LaserJet 4 model is available in several versions. Some LaserJet 4 models are PCL5 printers only, and others use PostScript. Unless you are aware that different types exist, you can find it very frustrating trying to debug a printer filter that is expecting, for example, PostScript, when Ghostscript is passing it PCL5 input.

ljet|lp|ps|PostScript|600dpi 20MB memory|local|LPT1:\
     :lp=/dev/lp0:rw:\
     :sd=/var/spool/lpd/ljet4:mx#0:mc#0:pl#72:pw#85:\
     :lf=/var/log/lpd-errs:if=/usr/local/cap/ljet4:

Don't be scared. After reading the following sections, you will find yourself browsing printcap files with ease.

The /etc/printcap file should accommodate every printer and printer port or address — serial, parallel, SCSI, USB, or networked — your system will use. Make sure it reflects any change in hardware. And as always, be aware that some hardware changes should be performed only when power to your system is shut off.

8.4.5.1. Printcap file format rules

The printcap file format rules, briefly, are:

  • A comment line begins with a pound sign (#).

  • Each "line" of the printcap file defines a printer. A line that ends with a backslash character (\) is continued on the next line. Be very careful that no space or tab character follows the backslash character on the line. Traditionally, a continuation line is indented for readability. Multiple printer definitions can use the same actual printer, applying the same or different filters.

  • Fields in the line are separated by colon characters (:); fields can be empty. However, a printcap line entry cannot be an empty field.

  • Traditionally, the first field in the entry has no preceding colon.

  • The first field of the entry line contains names for the printer, each separated by a vertical bar character (|). In the earlier example entry, this portion is the name field:

    ljet|lp|ps|PostScript|600dpi 20MB memory|local|LPT1

    Printer naming is discussed in detail in the next section. You should create a subdirectory of /var/spool/lpd with the same name as the first printer ID listed in each printcap entry. However, the actual print spool that is used is assigned by the sd variable for the printcap entry; if the sd variable doesn't point to the actual print spool directory, any file sent to that printer definition will vanish.

  • There must be at least a default printer entry in printcap. If a printer is named lp, that printer is used as the default system printer. Do not confuse the lp default printer name with the lp local printer variable, which is described next. We recommend you use lp as an alias (one of the names after the | characters) rather than the primary printer name (the first in the list), so you can switch the default printer without difficulty.

  • Each local printer must have an lp variable set. In the previous example, the variable was set by this segment of the printcap entry:

    lp=/dev/lp0
  • For compulsive and sometimes practical reasons, some administrators recommend that the entries of the printcap file be kept in alphabetical order.

8.4.5.2. Printer names

Most printer entries traditionally begin with a short printer name entry in the first field, at least one fuller printer name, and one longer explanatory entry. Thus, both ljet and PostScript are names for the printer whose nameline is:

ljet|lp|ps|PostScript|600dpi 20MB memory|local|LPT1:

Documents can be output to any printer named in a nameline in /etc/printcap.

You might name your printers after the model (HP, Epson), or the type of printer (PS, PCL), or its specific modes. The DeskJet 540, for example, is a printer that should have two definitions in the printcap file, one for black print and another for color. The filters you use to support it are likely to be those for the DeskJet 500 or 550C. For simple administration, you can assign printer names that are the names of a filter or filter parameter used for a specific device. Thus, if you have one LaserJet 4 and will use the ljet4 filter only for it, ljet4 is one logical name for the printer. Similarly, a dot-matrix printer might be named 72dpi when accessed via its low-resolution printer definition line, and have the name 144dpi when accessed in a higher resolution.

If you use a printer administration utility that comes with your Linux distribution, you may have to follow certain arbitrary rules in preparing your printcap entries in order to get the tools working. For example, if you use Red Hat's printer manager utility provided on the administrator's desktop, you may need to make sure that hp is the first name of the first active printer entry in the printcap file. This means that when you need to switch default printers, you need to move the new default printer to the top entry of the list and then remove the hp name from the old default printer and prepare it as the first name of the new default printer. In order to prevent confusion in use of the spool queues, you should just leave the /var/spool/lpd/lp directory set up and create a new directory with the actual name of the spool directory that corresponds to the name by which you actually will address the printer. Thus, if you want to send your files to print on a printer named moa, you will need to create a directory named /var/spool/lpd/moa, with appropriate permissions, and specify that directory as the printer spool for that printer. Setting up printer directories is described in the next section.

8.4.5.3. The rest of the printcap variables

The printcap file provides a number of variables that you can define. Most variables are provided to specify page parameters, files and directories, filters, communications channel settings, and remote access control. Anytime you prepare a printcap file on a new system, read the printcap manual page to make sure you use the correct variable names. Variables set in a printcap entry that are not recognized are passed through to the filter for processing.

The printcap variables described here are listed in roughly their order of importance. Some variables are boolean, and are considered set if they are present. Others are set with the assignment operator (=) or numeric value operator (#) and a value; the variable precedes the operator and the string or number follows the operator. Examples of the variables described in the following list are included in the contrived sample /etc/printcap file that follows. The printcap manual page has a more complete listing of variables recognized by lpd.

sd
Specifies the spool directory used by the printer. Spool directories should all be in the same directory tree (on a fast hard disk), which is usually /var/spool. Spool files are defined even for remote printers. Each spool file should have one of the names assigned to the printer it serves.

lp
Assigns a local printer device, typically connected through a parallel port, serial port, or SCSI interface. The lp variable must be assigned to a device file in the /dev directory, which may be a link to a physical device. The lp variable must be assigned if there is a local printer. This variable should not be assigned if the rp variable is assigned (that is, the print spool manager is on another host).[32] If lp assigns a serial device, the baud rate must be specified with the br variable.

[32]A special case arises where the printer to be addressed is a true networked printer (that is, it has its own IP address). In that instance, the lp variable assigns the name of a dummy file that is used for setting a temporary lock on the file when the networked printer is in use. The documentation for the networked printer should describe the procedure for setting up and managing print services to access it.

lf
Specifies the log file for storing error messages. All printers should have this variable set and normally use the same error log file. Error entries include the name of the printer and can reveal problems with the user's printer environment, the host configuration, the communications channel that is used, and sometimes the printer hardware itself.

rw
This variable should be specified if the printer is able to send data back to the host through the specified device file. The rw variable tells lpd that the device should be opened for both reading and writing. This can be useful for serial or SCSI PostScript printers, for example, because they may return fairly useful error messages to lpd, which stores them in the error log.

mx
Specifies the maximum size of a print job in the spool. A value of zero sets no limit (the default, mx#0), and any other value sets the maximum file size in blocks. Most of the time you don't want to set a limit, but you could, for example, set a value slightly smaller than the expected minimum space available on a disk.

if
Specifies an input filter to use. If you do not specify an input (if) or output (of) filter, the system uses the default /usr/sbin/lpf filter. For some MS-DOS-style character printers, this is sufficient. Other useful filters are provided in the formatting utilities, and there are some flexible "magic filter" packages that will determine (usually correctly) the filtering to apply from the content of the data file passed to it. See Section 8.4.7 that follows.

of
Specifies an output filter to use. When you assign the of variable and don't assign the if variable, the system uses the filter once when the device is opened. All queued jobs are then sent until the queue is exhausted (and lpd removes the lock file from the spool directory). This is not normally useful, but it could serve such purposes as sending faxes to a fax modem for dialed connection over a telephone line.

When you assign both the if and of variables, the if-specified filter normally processes the file, but the of-specified filter prints a banner page before the input filter is applied. Using both input and output filters effectively on the same print queue is notoriously difficult.

br
Specifies the data-transfer rate (baud rate) for a serial port. You must supply this value if the printer is accessed via serial port. A pound sign precedes a numeric value that expresses the data-transfer rate in bits per second (not truly the baud rate, which is an effective rate of flow as opposed to the maximum rate of flow). The specified rate should not exceed any hardware limits. For example, if your serial port is capable of a 57.6 Kbps rate and the printer can process 28.8 Kbps, the assigned rate should not exceed that lower limit (perhaps br#19200). Supported bps values are the usual multiples for serial communications: 300, 600, 1200, 2400, 4800, 9600, and so on. A number of additional data conditioning values may be set if you do assign a br value, but most of them aren't useful for typical Linux installations. The default behavior is probably acceptable for your printing purposes, but if you intend to print via serial port, study the br, fc, fs, xc, and xs variables in the printcap manual page.

pl
Specifies the page length as the number of lines using the default font characters for character devices (and printers that can use a character mode). An example is pl#66 for an 11-inch page at six lines per inch. This value allows space for cropping and accommodates the limits of some other devices, such as inkjet printers that cannot print to the bottom of the sheet or the edge of the paper. Normally used in conjunction with the pw variable.

pw
Specifies the width of the page supported, in characters, using the default font characters for character devices. pw is set like the pl variable; for example, pw#85 for 10 characters per inch with an 8.5-inch printable page width.

px
Specifies the number of pixels to use on the X axis for a bitmap image file sent to a raster device.

py
Specifies the number of pixels to use on the Y axis for a bitmap image file sent to a raster device.

sh
Suppresses printing of a header or banner page. In most cases, you should set this.

rp
Specifies the name of a remote printer to use. This variable cannot be set if the lp variable is set for the same printer. The printer handling is performed by the remote host assigned in the rm variable, which is required when rp is set. Usually, the only variables set along with these are spooling and error recording. See the example that follows.

rm
Specifies a remote host that controls the remote printer to which you print. The specified host ID assigned by rm should be one that is known to the network services as installed (set up in /etc/hosts or known through NIS, for example).

rs
Restricts access to local printers to those users with an account on the system.

rg
Specifies a restricted group that can use the printer. For example, to reserve a defined printer for superuser, enter rg=root.

sf
Suppresses the formfeed sent to the printer by default at the end of a print file.

ff
Assigns the formfeed character or string the device should use. The default is Ctrl-L (equivalent to ff='\f'), which is usual for most devices.

fo
Sends a formfeed character to the device before sending the file.

mc
Specifies the maximum number of copies you can print. Values are the same as for the mx variable; usually you want to allow unlimited copies (mc#0), which is the default.

sc
Suppresses multiple copies (equivalent to mc#1).

Example 8-1 contains a sample printcap file that shows off many of the variables discussed in the previous list. It contains an entry for a remote printer; printing to the printer named hp (also the default, as it is the first entry) sends the documents to the host spigot.berk.ora.com, where they are printed on the printer queue lp.

Example 8-1. Sample /etc/printcap file

# Fare well, sweet prints.
hp|bat|west|spigot|berkeley|TI MicroLaser Turbo:\
     :mx#0:rp=lp:\
     :lp=:sd=/var/spool/lpd:rm=spigot.berk.ora.com:\
     :lf=/var/log/lpd-errs:
# To the print room
kiwi|810|rint|Big Apple|Apple 810 via EtherTalk:\
     :lp=/var/spool/lpd/kiwi:sh:\
     :sd=/var/spool/lpd/kiwi:pl#72:pw#85:mx#0:\
     :lf=/var/log/lpd-errs:if=/usr/local/cap/kiwi:


# big bird--agapornis via shielded serial access
samoa|S|PostScript|secure|QMS 1725 by serial adapter:\
     :lp=dev/tty01:br#38400:rw:xc#0:xs#0400040:sh:\
     :sd=/var/spool/lpd/samoa:pl#72:pw#85:mx#0:mc#0:\
     :lf=/var/log/lpd-errs:if=/usr/local/cap/samoa:
# agapornis via printer room subnet (standard access)
moa|ps|QMS 1725 via Ethernet:\
     :lp=/var/spool/lpd/moa/moa:rm=agapornis:rp=samoa:\
     :sd=/var/spool/lpd/moa:mx#0:sh:\
     :lf=/var/log/lpd-errs:if=/usr/local/cap/samoa:

8.4.6. Configuring Ghostscript

Ghostscript is included in standard Linux packages; it is an essential utility in an X Window System environment and is useful even if you don't run X. Ghostscript can provide graphics output to a standard VGA display even where no window manager is running and can also process and create PostScript-formatted files without a graphics display. You can examine what devices Ghostscript is configured to recognize and format for on your system by entering Ghostscript in interactive mode. If you enter:

$ gs

Ghostscript should load in interactive mode and await your instructions:

GS>

You can then query the devices that Ghostscript is configured to recognize, and Ghostscript will display them:

GS> devicenames ==
[/lips3 /ljet3d /djet500 /cdj970 /st800 /iwlo /x11alpha /la75plus
/bjc800 /ljet2p /djet820c /cdj880 /lp8000 /appledmp /la70 /bj200 /stp
/DJ9xxVIP /cdj670 /eps9high /vgalib /dl2100 /lp2563 /pjxl300 /DJ8xx
/cdj500 /epson /x11mono /lex2050 /lj5gray /pjetxl /DJ6xx /cdjcolor
/tek4696 /x11gray2 /lex5700 /ljetplus /paintjet /hpijs /uniprint
/t4693d4 /x11cmyk4 /lxm5700m /ljet4 /djet500c /cdj1600 /stcolor
/iwlq /x11cmyk /ln03 /lbp8 /ljet3 /deskjet /cdj890 /lq850 /iwhi /x11
/la75 /bjc600 /laserjet /AP21xx /cdj850 /epsonc /sxlcrt /la50 /bj10e
/hpdj /DJ9xx /cdj550 /eps9mid /lvga256 /declj250 /cljet5 /pjxl /DJ6xxP
/cdjmono /ap3250 /x11gray4 /lex3200 /lj5mono /pj /DJ630 /cdeskjet
/t4693d8 /x11cmyk8 /lex7000 /lj4dith /dnj650c /chp2200 /hl7x0 /t4693d2
/x11cmyk2 /lj250 /jpeggray /png256 /mgrgray4 /tiffg4 /ppmraw /okiibm
/cif /pnggray /mgrmono /tiffg3 /pnmraw /oki182 /nullpage /cgm8
/pcxcmyk /bitrgb /faxg4 /pgnmraw /necp6 /pxlmono /bmp16m /pcx256
/psrgb /faxg3 /pgmraw /jetp3852 /pswrite /bmp16 /pcxgray /psmono
/dfaxhigh /pbmraw /ibmpro /pdfwrite /bmpmono /mgr8 /tifflzw /plan9bm
/xes /ccr /miff24 /png16m /mgrgray8 /tiff12nc /pkm /r4081 /jpeg /png16
/mgrgray2 /tiffg32d /ppm /oki4w /cgm24 /pngmono /bitcmyk /tiffcrle
/pnm /oce9050 /pxlcolor /cgmmono /pcx24b /bit /faxg32d /pgnm /m8510
/epswrite /bmp256 /pcx16 /psgray /dfaxlow /pgm /imagen /bbox /bmpamono
/pcxmono /tiffpack /inferno /pbm /cp50 /omni /sgirgb /mgr4 /tiff24nc
/pkmraw /sj48] 
GS> quit
$

If you are not using X, and Ghostscript fails to initialize when you try to invoke it, complaining that it cannot open an X display, the first device Ghostscript loaded in its build file was the X Window System device; Ghostscript uses the first device as its default device. You can work around this problem by specifying some other device that Ghostscript will have installed — for example, gs -sDEVICE=epson. You can guard against the problem in the future by setting a global GS_DEVICE environment variable to some other device on your system that can be opened by Ghostscript.

If you have such an unusual output device that the default Ghostscript installation does not support it, you need to rebuild Ghostscript to support the device, or else process your output files through a filter that converts it to a form usable by your output device. Ghostscript comes with makefiles and is easy to build if you follow the Ghostscript documentation that comes with the distribution.

The more graphics utilities, X window managers, games, and applications you use, the more likely you will need to reinstall Ghostscript to suit your requirements. Read the Ghostscript documentation before running the makefile that comes with the package. (This requires that you have gcc installed on your system.)

You can define the GSDIR environment variable to locate the path of the ghostscript command and set GS_LIB variables, if you need to build Ghostscript utilities and add them to your installation. For example:

export GSDIR=/usr/bin
export GS_LIB=/usr/lib/ghostscript:/usr/local/lib/fonts:/usr/X11R6/fonts

Set the GS_LIB_DEFAULTS variable before you make a new build of Ghostscript; see the gs manual page.

The Ghostscript package also contains some PostScript programs that provide useful print-support functions, including some sophisticated printing capabilities we do not document here. The gs_init.ps file, in particular, affects the general behavior of Ghostscript. Additional scripts (filters, shell scripts, and so on) can be found in /usr/lib/ghostscript or /usr/local/lib/ghostscript. You may find it useful to examine the ps2epsi.ps utility, which converts PostScript into encapsulated PostScript, and the ps2ascii.ps utility, which converts PostScript files into plain text.

8.4.7. Print Filters

Every document passes through a filter before going to the printer, thanks to the if variable in the printcap file. A print filter can be found in a Linux distribution, acquired from the printer's vendor, found on the Net, or even made yourself from scratch or by cobbling together existing filters and shell utilities.

An input filter can also be used to restrict use of a printer to a specific user or group, or to users with accounts on a particular host. Typical if-assigned filters are executable shell scripts that process the text file, but they can be any program that can take the input data stream and process it for output to a printer.

It is increasingly common for commercial Linux distributions to build a filter interactively. While you can usually improve on such a filter, it can help to use one as a starting point. The Red Hat distribution, for example, created the following shell-script filter (named /var/spool/lpd/ljet4/filter)[33] on one of our systems from information provided to it in the printer manager window and from default assumptions. The /etc/printcap file was modified to specify the use of this filter, which proved to be perfectly functional on our system:

[33]Putting a filter in a printer's spool directory is a convenient technique for a printer-management program to use when setting up your printer system. You may prefer to keep all your print filters and graphics conversion filters in the same directory (following the Unix tradition), such as /usr/sbin or /var/spool/lpd/filters. Of course, in that case, each filter you create must be uniquely named.

#!/bin/sh
        
DEVICE=ljet4
RESOLUTION=600x600
PAPERSIZE=letter
SENDEOF=
        
nenscript -TUS -ZB -p- |
if [ "$DEVICE" = "PostScript" ]; then
        cat -
else
        gs -q -sDEVICE=$DEVICE \
                -r$RESOLUTION \
                -sPAPERSIZE=$PAPERSIZE \
                -dNOPAUSE \
                -dSAFER \
                -sOutputFile=- -
fi
        
if [ "$SENDEOF" != "" ]; then
        printf ""
fi
        
exit 0

There's nothing exotic about this filter. First it sets some variables that appear later as arguments in the Ghostscript command. The script passes output through nenscript and passes PostScript files to the gs Ghostscript utility. (In this particular case, the automatically generated filter will never invoke gs because DEVICE never equals "PostScript" in the if test.) If your printer doesn't eject the final pages of output, you can force it to by setting the SENDEOF variable near the top of the file. For example:

SENDEOF='\f'

will cause a formfeed to be sent to the printer when it reaches the end of a file.

You might modify such a script and substitute a filter specifically designed for a LaserJet 4 printer, such as the actual ljet4 filter package, for example, and accommodate printing of TEX DVI files by filtering them through dvips and feeding them to Ghostscript. There is an elementary discussion of how to create a filter in the Linux Printing HOWTO.

If you use a character printer that expects a carriage return at the end of each line, it will be unhappy with Linux, which follows Unix fashion in terminating a line with a linefeed, but no carriage return. To force correct treatment of newlines on these printers, the filter has to insert the carriage return. You can do this by writing the processing into the filter, or, alternatively, by using a filter that already has the capability to insert the character.

Some printer vendors provide filters and utilities for their printers, especially where the usual solutions are likely to be inadequate to take advantage of the printer's capabilities. For example, Hewlett-Packard provides a JetAdmin package with filters to use with its TCP/IP network-addressed LaserJet printers.

The default filter that comes with the BSD print-management package is /usr/sbin/lpf. This filter is undocumented and probably best ignored, unless you wish to retrieve the C source and trace through the program to learn its capabilities. (You can find the full BSD source in the lpr-secure package in the printing directory from ftp://ftp.ibiblio.org.)

Most of the print-filtering needs you have were long ago resolved, and there are filters out there to meet your needs. By running:

apropos filter

you can probably identify several print filters installed on your host.

Changing filters is simple. You need only change the /etc/printcap input filter specification (if) to specify the filter you want, and then kill and restart lpd, which you can do using the lpc utility. Enter (as root):

lpc restart all

The lpc utility reports any lpd processes it kills, then restarts lpd. If files are in a print spool waiting to print, lpd also reports that an lpd daemon for that printer has been started. The lpc printer control utility is described later in this chapter, in Section 8.4.12.

Before adopting a strange print filter, study the manual page for that filter and pass some test files through it. We have found that filters don't always perform "as advertised" in their manual page; often the document is obsolete or the filter was compiled by someone using different configuration parameters than the document assumes. There is no substitute for testing all the things you expect the filter to do before adopting it. Two good filtering packages, nenscript, a newer version of the traditional Unix filter enscript, and APSfilter, are discussed in the next sections.

8.4.8. The nenscript Filter

The nenscript filter is a typical modern filter for Linux. You should find it in /usr/bin/nenscript if it was provided in your Linux distribution. Otherwise, it may be installed in /usr/local/bin. nenscript controls headers, footers, rotation of text, and so on, and produces PostScript output conforming to the Adobe Structuring Conventions from plain ASCII input (by calling Ghostscript). It sends output to the printer specified by either the user's NENSCRIPT environment variable, if set, or by the user's PRINTER environment variable. If neither variable is set, nenscript uses the default printer that lpr wants to use.

If nenscript is called using the -Z option, it is supposed to pass PostScript files through without altering them. nenscript examines the input file, and if the first two characters in the input file are %!, nenscript suppresses formatting. Because this output "type-checking" is primitive, it is easily fooled. Obviously if the first two characters happen to be something other than %!, perhaps because a formfeed is the first character, for example, the file will not be recognized as PostScript even if it is. This can easily happen if some filter processing takes place before the file passes through to nenscript. Of course, a file can also have %! as the first characters and not be PostScript (or could be nonconforming PostScript) and therefore may not be handled properly if passed to a PostScript printer. There are smarter filters for this type of checking, including Magic-Filter or APSfilter, but nenscript may easily meet your needs, especially if you print only to a PostScript printer.

If you use the nenscript filter for a PostScript printer on your system, therefore, you could specify the -Z option in the NENSCRIPT environment variable for all user shells by default, in order to pass through the PostScript received by the filter.

A shell script provided in the nenscript package invokes nenscript configured to behave as though it were another (similar) traditional Unix filter, pstext.

To use nenscript to filter your print files, make sure nenscript is installed in an appropriate path, and then set the printers for which you want nenscript to filter to point to a filter that invokes the nenscript filter. You may find that the printcap entry can point directly to the nenscript filter if you set a systemwide default NENSCRIPT variable to control its options, or you can create a simple processing filter that calls nenscript, much like the sample configuration file shown earlier.

8.4.9. Magic Filters: APSfilter and Alternatives

The most versatile filters are the so-called "magic" filters. A magic filter examines the contents of a file passed to it, and filters the output for printing based on what it learns from the format of the information. If it sees the file is DVI routed to a PostScript printer, for instance, it will apply another filter (perhaps dvips) to convert the data into PostScript for printing. This is very convenient, but on occasion, the filter can make a mistake. If that happens, the user can resubmit the file with command-line options that specify which filtering to perform, or the user can preprocess the file by piping it through the needed filtering before passing it to lpr for routine print processing. There are some good magic filter packages, including APSfilter (which we have chosen to describe here), Magic-Filter, and the gslp.ps filter provided with complete Ghostscript packages.

Some Linux distributions, regrettably, omit Ghostscript's supplemental utilities or documents, but you can always retrieve a complete Ghostscript distribution via FTP from the GNU archive site (ftp://ftp.gnu.org/gnu/ ) or one of its mirrors. You can get the APSfilter and Magic-Filter packages from the ftp://ftp.ibiblio.org FTP site in the /pub/Linux/system/printing directory. The Ghostscript filter, gslp.ps, is written in the PostScript language and can be used only with Ghostscript or another interpreter compatible with Adobe PostScript.

The APSfilter package for Linux is a port of a package developed for FreeBSD. For that reason, you should take a few precautions in order to ensure that things configure properly when you install the APSfilter package. On a Linux host, it is probably best to install the APSfilter package in /usr/lib/apsfilter. The package comes from ftp://ftp.ibiblio.org as a gzipped, tarred file. To unpack the package, put it in the /usr/lib directory and enter:

tar xvfz apsfilter*.tar.gz

Now the APSfilter package unpacks within subdirectories of the apsfilter directory.

Change to the apsfilter directory. Before you run the SETUP command, make sure you have all the filters you might want to use with APSfilter installed and configured. The /usr/lib/apsfilter/FAQ file tells you some of the more important and useful packages.

Before you run the installation, read the INSTALL document to make sure there aren't any surprises. Then run ./SETUP. It tests for the presence and location of graphics utilities and other filters APSfilter uses to convert files into a form printable on your printer.

The SETUP script lets you know if the filter installed correctly. You can run it again if you wish to install more than one printer or more than one mode for a single printer. For example, if you install a DeskJet 540 printer, you probably will want to use the dj500 definition for the black cartridge and the dj550c definition for the CMYK color cartridge. APSfilter uses very long directory names for its spool directories. If you don't like that, you can rename the spool directories and change the corresponding directory fields in the corresponding /etc/printcap entry. Be sure not to shorten the name of the filter used; that path is critical. We don't recommend you make things pretty until you are satisfied that things are working.

Before you try your new setup, you need to restart the print daemon:

/usr/sbin/lpc restart all

APSfilter sets systemwide variables for printer definitions in the /etc/apsfilterrc file; reading this file can be informative. Common print problems are typically caused by file ownership or permission problems; we show you the proper settings in the upcoming section Section 8.4.10.2. Then, read the FAQ and TROUBLESHOOTING files in the /usr/lib/apsfilter directory.

If your APSfilter installation didn't work, you can always return to the configuration you had before you installed it by copying back to /etc/printcap the /etc/printcap.orig file that APSfilter saved for you.

APSfilter names its printers sequentially, from lp1 up. Don't be confused; that has nothing to do with the actual physical device assigned to the printer. Again, you can change those names.

APSfilter allows you to loosen restrictions so that individual users can set up their own .apsfilterr file in their home directories. The default is to not allow it, which is a bit more secure.

The latest version of Magic-Filter (at the time of this writing, Version 1.2) is remarkably easy to install and makes a clean alternative to APSfilter. However, the installation doesn't do any hand-holding. Though there is a useful manual page, there isn't much information to help you set up the alternate processing that the Magic-Filter utility can do for most printing devices. In particular, if you have a versatile printer that outputs in multiple modes (PostScript, PCL5, text, and so on), you may find it worth your while to install and use this package.

8.4.10. BSD Print System Elements: Files, Directories, and Utilities

The print-management system requires you to create directories that match the printcap printer names in order to spool files for printing. It also requires you to create other files for controlling the print process itself. You must set up directories and files with the correct ownership and privileges, and the printer utilities themselves also need correct permissions.

8.4.10.1. Setting up printer directories

Your Linux installation created a standard spool directory. Ideally, this is on a fast-access disk drive. The basic spool directory (/var/spool ) is normally used for managing mail, news, and UUCP communications as well as for holding printer files. We recommend you follow this practice, which is a Linux standard. Some utilities or filters you get may expect to find /usr/spool/lpd as the printer spool path. You will have to make corrections if you find this condition. You can, of course, create /usr/spool and link it to /var/spool, but that is a good idea only if /usr and /var are on the same disk drive.

You must create your own printer spool directories. The /var/spool/lpd directory is the standard path containing each printer subdirectory. Each printer subdirectory name must be used as a printer name in the first field in a corresponding /etc/printcap entry. For example, /var/spool/lpd/moa is appropriate for a printer with moa in a name field of the printcap entry. In turn, the /etc/printcap entry for this printer should have an sd variable set to point to the spooling directory (sd=/var/spool/lpd/moa, for example).

You shouldn't use lp as the actual spool directory name unless you never expect to have more than one printer on your system or network because lp is the default printer. (If your default printer is somewhere else on the network, your files will still get spooled to /var/spool/lpd/lp first, before your lpd forwards them to the print daemon on the remote host to print.) You may have a printer-management utility that automatically creates an lp spool directory, but you can always edit the printcap file to point to any directory you wish.

The spool directory name should be the first name listed in the associated /etc/printcap entry for the printer to make identification easy. The printcap entry will then be associated with the names under which the lpq and lpc utilities report print queue status.

8.4.10.2. File, directory, and utility privileges

The most common problem in establishing print services is with file and directory permissions. Table 8-1 lists the important files, directories, and utilities that comprise BSD print management on Linux. Installed locations may vary according to your Linux distribution. The ownerships and permissions given in the following table are recommended for the files and directories of the printing system. (Additional filters and nonstandard spool paths may be specified in /etc/printcap.) Different permissions may still work, but if you have permissions problems, this is where you can straighten them out. An asterisk in the first column of the table indicates that many files can exist with the names of different printers. Note that different distributions may have slightly different settings here; some distributions even have different "security modes," which you can select depending on your security requirements and which have an effect on the permissions used.

Table 8-1. BSD's files, directories, and utilities for printing

Directory or file

Permissions

Owner/group

Description

/dev/ttys1

crwsr-----

root/lp

Typical serial port printing device

/dev/lp1

crws------

root/lp

Typical parallel port device (not bidirectional)

/usr/bin/lpc

-rwsrwsr-x

root/lp

Controls print-spooling services

/usr/bin/lpr

-rwsrwsr-x

root/lp

Receives print file, assigns processing data, and spools both

/usr/bin/lpq

-rwsrwsr-x

root/lp

Reports on spooled files with user and print queue data

/usr/bin/lprm

-rwsrwsr--

root/lp

Removes print jobs from spool

/usr/bin/tunelp

-rwsr-sr--

root/lp

Tests print services to improve them

/usr/bin/lptest

-rwxr-xr-x

root/root

Outputs an ASCII file for printer and display testing

/usr/sbin/lpd

-rwsr-s---

root/lp

Daemon that manages printing using printcap data and data passed by lpr

/usr/sbin/lpf

-rwxr-xr-x

root/lp

Primitive BSD text print filter

/usr/sbin/pac

-rwxr--r--

root/root

BSD utility that reports on printer activity and usage by user ID

/var/spool/

drwxr-sr-x

root/daemon

Basic system location for temporary files

/var/spool/lpd

-rws--s--x

root/lp

Standard path for the print-spooling system

/var/spool/lpd/*

drwxr-sr-x

root/lp

Spooling subdirectories for each defined printer

/var/spool/lpd/*/filter

-rwxr-xr-x

root/lp

Filters created by Red Hat printer-management utility for each print spool

/var/spool/lpd/lpd.lock

-rw-rw----

root/lp

lpd queue control lock

/var/spool/lpd/*/.seq

-rw-rw----

lp/lp

Sequence file that lpd uses to order spooled files

/var/spool/lpd/*/lock

-rw-------

root/lp

lpd writes this lock file to prevent sending next file until printer is ready

/var/spool/lpd/*/status

-rw-------

lp/lp

lpd stores latest printer status report here

/var/log/lp-acct

-rw-------

root/root

Accounting record file, from which pac extracts and formats print data[34]

/var/log/lpd-errs

-rw-rw-r--

root/lp

Standard BSD log file for lpd errors

[34]This file remains empty if system accounting is not installed, unless you configure Ghostscript to perform its limited reporting there and make the file writable by all.

The usual Linux printer-management utilities set the print files with root ownership and lp group privilege. Traditionally, BSD distributions have used root ownership and daemon group privilege. You can use either group privilege, but if you use both daemon and lp privileges with different utilities and files, you will have problems. Be particularly careful about this if you add utilities from other packages to your services.

Let's say you (as root) need to create the printer-spooling directory, /var/spool/lpd. You execute the command:

mkdir /var/spool/lpd

Assuming your /var/spool was created with the usual permissions, the new lpd directory has permissions of drwxrwxr-x, which is too permissive. If you enter the command:

chmod 755 /var/spool/lpd

the permissions are changed to drwxr-xr-x. This is close, but not what you want. You need to set the setuid bit, so lp can setuid root:

chmod +s /var/spool/lpd

This results in drwsr-sr-x, which is what you want. However, the group should be lp, not root, so you need to fix that:

chgrp lp /var/spool/lpd

Create the spool directories needed for each printer as subdirectories of the /var/spool/lpd directory in the same way, and then use touch to create a .seq file in each print directory:

touch .seq

8.4.11. Exercising the Printer Daemon

The lpd daemon consults /etc/printcap and then sends files to printers by directing them to a device file in the /dev directory. Most printers on Linux boxes are serial (usually addressed through devices named /dev/ttys0, /dev/ttys1, and so on, or /dev/ttyS0, /dev/ttyS1, and so on) or parallel (/dev/lp0, /dev/lp1, or /dev/lp2, depending on the physical addresses the ports use). The port assignments are described in Section 8.4.14, later in this chapter. A common mistake when configuring print services is to use the wrong port.

You can link a virtual device — /dev/fax, for example — to an actual device you can use by creating a symbolic link. For example:

ln -s /dev/ttys1 /dev/fax

This allows users to set up scripts and filters that address /dev/fax, which is much easier to remember than /dev/ttys1. Also, you can move the physical device (a fax modem, for example) without breaking user setup simply by removing /dev/fax and then creating it again with a link to the new device.

The BSD printer daemon is notorious for dying or just becoming inert. To be fair, this seems to be less common than it was some years ago, but it still happens. When it does, just kill the old daemon and start a new one. If lpd isn't fairly reliable, though, there is a cause somewhere. Something could be wrong with a user's environment, with the specified command-line options used with lpr, or with a faulty filter that sends setup data to the printer in a form the printer doesn't like. However, you have every reason to expect to have a "pretty good" printing package installation. If you are having problems, check out Section 8.4.14, later in this chapter.

OK, let's see if you have a working print system. After making all these changes, you can be sure that lpd doesn't know what is going on. So run the ps command and find the ID of the lpd process. Then enter:

kill -9 processid

to kill the process you specified.[35] You should now have no print daemon running. Just enter /usr/sbin/lpd to start the print daemon.

[35]You may prefer to use lpc to perform this task. Also, if your root desktop has a printer-manager tool, you can probably click the lpd button to kill and restart the print daemon.

Now, while watching the activity LEDs on your printer front panel (if there are any), send a file to the printer (still acting with superuser privilege):

lptest | lpr

The lptest ASCII barber pole should begin printing to your default printer, as configured in your /etc/printcap file. If it doesn't, you have a configuration problem that has nothing to do with privileges.

Did the printer show any activity? Does your default printer have a spool directory? Does the directory have a .seq file? Check /var/log/lpd-errs and see if anything was stored in it. Use the lpc command and get a report on the status of the print daemon and the print spool.

If everything else looks good, make sure the printer is using the port you expected by sending a file directly to the port. For example:

# lptest > /dev/lp1

Or, to test for a serial printer:

# lptest > /dev/ttys1

and so on. If none of these worked, reexamine your /etc/printcap file. Is your entry properly formed? Are there no blank spaces or tabs following the continuation character (\) on your entry line? Is the printer queue correctly specified? Does the name lp appear as one of the printer names of the name field? Is the first name in the name field the same name as the spool directory it uses?

Let's assume you got through this first little test unscathed, and you now have several pages of lovely barber-pole printout in your printer tray. Next comes the real challenge. Can you print as a regular user? Log in (or run su) to become a normal system user. Now, try the same experiment. If it works, congratulations, you've got a printer! If it doesn't, you have a problem, but it is probably a file or directory ownership or permissions problem. You know what you have to do about that. Become root again, look at the manual pages for chgrp, chmod, and chown, and go down the list of files and directories to find your problem and fix it. Repeat until Joe User can print.

8.4.12. Controlling Printer Services with lpc

The lpc utility is provided to manage printer queues and requires root privilege to perform most of its functions. lpc reports on all print queues and their attending lpd daemons. You can also specify reports on a specific printer or printing system user. To get a status report on all printers and users, type:

$ lpc status
ibis:
        queuing is enabled
        printing is enabled
        no entries
        no daemon present
crow:
        queuing is enabled
        printing is enabled
        1 entry in spool area
        crow is ready and printing

ada:
        queuing is disabled
        printing is disabled
        no entries
        no daemon present

You can enable queuing within lpc through its enable command and disable queing using its disable command. The disable command works by setting a group execute permission on the lock file in the print spool directory.

You can enable printing in lpc using its start command and disable it using its stop command. Jobs held in a print queue when a printer is stopped will remain there until printing is restarted. The stop command functions by setting a lock file in the printer spool directory and killing the print daemon for that queue, but it allows the currently printing job to complete. The abort command works like stop, but also halts any printing job immediately. (Because the job did not complete, lpr retains it and starts over again when the queue is restarted.)

The down command functions as though both a disable and a stop command were issued, and the up command does the reverse, issuing enable and start commands.

You could also limit the display to one printer:

$ lpc status crow
crow:
        queuing is enabled
        printing is enabled
        1 entry in spool area
        crow is ready and printing

The status-reporting feature is useful for anyone, and lpc allows all users to use it.

The real work for lpc usually involves solving a printing crisis. Sometimes a print daemon dies, and printing jobs back up. Sometimes a printer runs out of ink or paper, or even fails. Jobs in the print spools have to be suspended or moved to another spool where they can be printed. Someone may simply have an urgent printing task that needs to be moved to the top of the queue.

The lpc command is a classic Unix command: tight-lipped and forbidding. When you simply enter the lpc command, all you get back is a prompt:

lpc>

The command is interactive and waiting for your instructions. You can get help by entering help or a question mark at the lpc prompt. lpc responds and gives you a new prompt. For example, entering a question mark displays:

#  lpc
lpc> ?
Commands may be abbreviated.  Commands are:
abort   enable  disable help    restart status  topq    ?
clean   exit    down    quit    start   stop    up
lpc>

You can get additional help by asking for help about a specific command. For example, to learn more about restarting a stalled print queue, type:

lpc> help restart
restart         kill (if possible) and restart a spooling daemon
lpc>

The lpc help message does not offer online help about the secondary arguments you can specify in some places. The manual page will offer you some guidance. Most of the commands accept all or a print spool name as a secondary argument.

The lpc topq command recognizes a print spool name as the first argument and printer job numbers or user IDs as the following arguments. The arguments are used to reorder the print queue. For example, to move job 237 to the top of the ada print queue, followed by all jobs owned by bckeller in the queue, enter:

lpc> topq ada 237 bckeller

The lpd daemon will start job 237 as soon as the current job is finished and will put any files in the queue owned by bckeller before the rest of the print spool. If you were very impatient, you could use the abort and clean commands to kill and purge the currently printing job, then use topq to put the job you want at the top of the queue, before using restart to create a new lpd and restart the queue.

When you use the stop command to stop a print spool (or all print spools) you can broadcast a message to all system users at the same time. For example:

lpc> stop ada "Printer Ada taken down to replace toner cartridge."

If you do major surgery on the print spools — stopping queues and moving files around — it is wise to use lpc's clean command. This minimizes the risk that some loose end will cause an lpd daemon to stall:

lpc> clean

Then get a new status report and restart or start all stopped print spools before exiting. There is a difference between aborting a process, stopping a process, and bringing a print queue down. If you bring a print queue down (lpc down ada, for example) you will find you cannot get lpd to serve the print spool again until you restore services with an lpc up ada command. Similarly, if you stop a queue, you have to start or restart it.

Follow up after you clear print spool problems using lpc. Further status reports will let you know promptly whether the problems were actually solved.

You should not wait for disaster to become familiar with lpc commands because printing jobs can pass through a Linux spool very fast, especially when a printer has lots of memory to buffer jobs sent to it. Study the manual page and work with lpc enough to be comfortable with the control it gives you over print spools and lpd daemons.

You can abbreviate subcommands unless it makes them ambiguous. For instance, in the following command, h stands for help :

lpc> h topq

To exit from lpc, enter the command:

lpc> quit

or:

lpc> exit

8.4.13. Printer Optimization

For performance improvement, you can first try to maximize the physical tuning of the system. You should try to determine the maximum data flow rates you can sustain to the printers you install. Don't specify a faster rate of communication than can be supported unless your printer is going to return flow control signals to the print daemon. That is, you must have bidirectional communications (and the printer must return the necessary signals) or else you must limit your transmission speeds so that data doesn't get lost en route to the printer. You may have to experiment with this to wring the best possible performance from printers limited by restricted bandwidth.

Old PC serial and parallel cards just don't have the throughput available with later cards. Newer serial cards have faster I/O processors. Newer parallel ports are typically faster and meet the Enhanced Parallel Port (EPP) standard to support bidirectional communications, which may allow lpd to control data flow to the printer better. A significant performance improvement may be only a few dollars away.

If your printer is just plain slow and cannot buffer print jobs, there isn't much to be gained from optimizing the data-transfer rate, of course, but it may still be useful for you to use interrupt-driven flow control made possible by bidirectional communications instead of port polling, if your hardware permits, as that will decrease the system load.

You can try out various printer optimizations using the tunelp utility. Read the manual page carefully before attempting this. If a tuning procedure fails, you may need to turn the printer off and back on to reset it. Also, don't forget to use lpc to restart the lpd daemon after each change to the configuration. Back up your working setup before monkeying around with tunelp.

An excellent first use for tunelp is to cause a print job to abort on receiving a printer error and to notify you. (The default is not to abort.) Setting this up can shorten the test cycle. To cause abort on printer error, enter as root:

tunelp -aon

If you use a parallel port printer and your parallel port supports interrupt-driven printing, you can use tunelp to accelerate printer access:

tunelp /dev/lp1 -i7

This example switches the port controlled by interrupt 7 to use interrupt-driven printing. If an attempt to print after you made this change fails, you should reset the port and switch back to noninterrupt-driven polling:

tunelp /dev/lp1 -r -i0

If you don't know the interrupt this device uses, you can query with tunelp -q on, and the IRQ setting will be displayed.

You can probably speed up printing a bit by reducing the pause the driver takes when it cannot send a character to the printer after a certain number of tries. For example, a fast laser printer might happily accommodate very brief pauses and not require many attempts to transmit. To try sending a character 10 times before pausing (the default is 250 attempts) and set the pause to .01, type:

tunelp /dev/lp1 -c10 -t1

The -t takes a numeric value that represents a multiple of .01 second. The default pause is .1 second.

Note that the optimal transfer rate for plain-text files is likely to be less efficient for graphics files, which are generally processed more slowly.

When you finish tuning your printing system, you may want to reset the printer abort flag to prevent the process from aborting on receipt of printer error:

tunelp -aoff

The tunelp utility will continue to be developed in subsequent releases of Linux. Check the manual page to see the capabilities of your release.

8.4.14. Printer System Troubleshooting

When you have a printer problem, first resort to lpc to generate a status report. The print daemons should be alive and well, and no error should be returned. Restart the daemons if they have stopped. You can also check the contents of the /var/spool/lpd/printername/status file and see if an error message from the printer is stored there. Check the /var/log/lpd-errs file for any errors reported by lpd. If you are using Ghostscript and its reporting features are active, use /sbin/pac on Ghostscript's log file to get a report that may reveal errors Ghostscript generated. (As long as Linux system accounting isn't available, you might as well use /var/log/lp-acct to store these reports. You'll have to make the file writable by all to do this.)

Look at that lpc status report again. Do files get to the print spool? Do they leave the spool? Are the necessary supporting files for lpd present (.seq, lock, and so on)? If lpc status reported a printer named " : " there is a malformed /etc/printcap line; the last character on a continuation line must be the backslash, not a space or tab.

Sometimes the /etc/printcap file is set up incorrectly, and it makes lpd misroute a file. To test for that condition, prepare a file for print but save it to a file instead of spooling it to the printer. Examine the file. Is it in the form you expect? Try a couple of sanity checks:

  • If as root you send the file directly to the device (for example, cat filename.ps > /dev/lp1), does it print? If so, it means the problem lies in your software configuration, not in the hardware.

  • Can you view your PostScript file using Ghostview? If so, you know that the format of the file is correct but the printer or filter is not interpreting it properly.

If you are testing a text file, try preparing it and routing it to a display, passing it through a utility such as less, and examine the result. A custom filter can also misroute a file.

Sometimes it is difficult to figure out where a printing problem originates. Printer configuration problems can be masked (or introduced) by having defaults overridden, for example. You may have to start by looking at an individual user's printing habits and then work forward. Individual users can set environment variables in their shell startup files to specify the printer they want to use as a default, and the behavior of formatters and print filters. Default system values are often overridden by environment variables, and they in turn are overridden by option arguments passed to lpr on the command line or by another utility.

When a print job terminates abnormally, it may be necessary to clear the lock file for the spool before lpd will send another file to print from that spool (/var/spool/lpd/printername/lock). The lpd daemon creates the lock file and changes it on completion. You can use lpc to stop the print daemon and then clean up the spool before starting it again.

Some problems derive from the data-transfer process. A printer may drop characters or be unable to keep up with the data flow you are attempting to provide, especially if the printer is old and slow or if the cable is unusually long. One possible symptom of data-transfer problems is when the printer can handle plain text readily, but pauses and thrashes when trying to print graphics files. If you suspect some problem of this nature, try increasing the pause the system takes before attempting to resend data and slowing the wait loop. The tunelp utility lets you control this conveniently:

tunelp -t200 -w5

This command tells lpd to pause 2 seconds between attempts. The -w option sets the number of loops for the busy loop counter to read between strobe signals. Normally -w is set to 0. For more information on tunelp, see Section 8.4.13 earlier in this chapter.

If lpd never seems to run on your system, perhaps it isn't started up when the system boots. If this is the case, append a /etc/lpd line to the end of your /etc/rc.d/rc.local file. Most Linux distributions start lpd these days as part of the default installation.

Some problems may never occur unless you use another package that presents conflicts by attempting to address the same devices. For example, UUCP utilities address a serial port using a /dev/ttyS* device driver. However, UUCP is a daemon with greater privileges than lp, and (although it shouldn't) it can leave the device set with a privilege level to which lpd cannot write.

The Linux distribution of the BSD print package is usually installed with lp group permissions. On traditional BSD print-management installations, lpd is owned by daemon and has daemon group privileges. (There's no special lp group to support printing.) If you think there are subtle problems relating to device access collisions by processes owned by different daemons, you can change all print utilities, group privileges to daemon and, of course, change directory and file-access privileges as well. That would restore the traditional BSD configuration. A better solution would be to find the problem devices and change their ownership to lp, because UUCP will still be able to use devices lp owns. Be aware that a serial port address can be reached by a number of virtual devices linked to the actual device; you have to correctly set the ownership of the real device.

Occasionally, a user believes his print job is going to the "wrong" printer. This is usually an environment variable problem. Double-check your /etc/printcap, but also check the user's environment variables. For example, a user may have a GS_DEVICE variable set so that Ghostscript uses that printer as the default printer. If Ghostscript processing precedes nenscript processing, for example, the Ghostscript printer assignment could be passed to nenscript, overriding a NENSCRIPT or PRINTER device specification. This can also cause strange results if one parameter is overridden while others stay as before so that, for example, a filter performs some special page layout for one printer, but the file goes to another.

Older PostScript printers may simply ignore ASCII files sent to them. If a user complains about disappearing output, maybe the file isn't getting passed through nenscript for PostScript encapsulation, or (very rarely) maybe nenscript was fooled into thinking it is already PostScript.

A multimode printer that knows when to switch modes (between PCL and plain text, for example) may still fail to eject the page and start the next file on the new page when one file of the same type is queued immediately following another of the same type. If this occurs, you can force the filter to add a formfeed at the end of each document (see the sample filter in Section 8.4.7) at the cost of sometimes printing unnecessary blank pages.

Parallel port printer addressing can be confusing. On an XT bus system, the first parallel port is addressed as /dev/lp0 at 0x3bc, referring to an address in your computer's I/O memory. On the usual ISA bus system, the first parallel port device is /dev/lp1 at 0x378, which is the second parallel port on an XT system (still the /dev/lp1 device). The usual second parallel port on an ISA bus system is /dev/lp2, as you would expect, at 0x278. However, there are some unusual configurations out there, such as systems with three parallel ports (if installed correctly these will be addressed as /dev/lp0, /dev/lp1, and /dev/lp2). IRQ assignments may also be unusual and present a problem if you are trying to set up interrupt-driven printing.

If all else fails, review the initial installation procedure. Make sure the hardware is actually connected and functional by booting another operating system if possible, testing devices as root user, and so on.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.