Chapter 6. Printing

Table of Contents
6.1. Enabling the printer daemon
6.2. Configuring /etc/printcap
6.3. Configuring Ghostscript
6.4. Printer management commands
6.5. Remote printing

This chapter describes a simple configuration for printing, using an HP Deskjet 690C connected to the first parallel port as an example. First, the system will be configured to print text documents, and next the configuration will be extended to print PostScript documents using the Ghostscript program.

6.1. Enabling the printer daemon

After installation it is not yet possible to print, because the lpd printer spooler daemon is not enabled. To enable lpd add the following line to /etc/rc.conf

lpd=YES    

The change will come into effect at the next boot, but the daemon can be started manually now:

# lpd -s    

To check if lpd is active, type the following command:

# ps ax | grep lpd
  179 ??  Is     0:00.01 lpd     

If you don't see an entry for lpd in the output of the previous command, the daemon is not active.

Before configuring /etc/printcap it is better to make a printer test, to check if the connection is working. For example:

# lptest 20 10 > /dev/lpt0    

To see what the output should look like, try the same command without redirecting the output to the printer:

# lptest 20 10    

A frequent problem is that the output on the printer is not correctly aligned in columns but has a "staircase" configuration. This usually means that the printer is configured to begin a new line at the left margin after receiving both a <CR> (carriage return, ASCII 13) character and a <LF> (line feed, ASCII 10) character. NetBSD only sends a <LF> character. You can fix this problem:

Note: in the previous example the lpd spooler is not involved because the program output is sent directly to the printer device (/dev/lpt0) and is not spooled.

6.2. Configuring /etc/printcap

This section explains how to configure the example printer to print text documents.

The printer must have an entry in the /etc/printcap file; the entry contains the printer id (the name of the printer) and the printer description. The lp id, is the default used by many programs.

Example 6-1. /etc/printcap

lp|local printer|HP DeskJet 690C:\
        :lp=/dev/lpa0:sd=/var/spool/lpd/lp:lf=/var/log/lpd-errs:\
        :sh:pl#66:pw#80:if=/usr/local/libexec/lpfilter:    

The file format and options are described in detail in printcap(5). Please note that an input filter has been specified (with the if option) which will take care of eliminating the staircase problem.

if=/usr/local/libexec/lpfilter    

Printer driver and HP printers: Example 6-1 uses the lpa# device (polled driver) for the printer, instead of the lpd# (interrupt driven driver). Using interrupts there is a communication problem with some printers, and the HP Deskjet 690C is one of them: printing is very slow and one PostScript page can take hours. The problem is solved using the lpa driver. It is also possible to compile a custom kernel where lpd is polled.

The printcap entry for the printer also specifies a spool directory, which must be created; this directory will be used by the lpd daemon to accumulate the data to be printed.

# cd /var/spool/lpd
# mkdir lp
# chown daemon:daemon lp
# chmod 770 lp
    

The only missing part is the lpfilter input filter, which must be written. The only task performed by this filter is to configure the printer for the elimination of the staircase problem before sending the text to be printed. The printer used in this example requires the following initialization string: "ESC &k2G".

Example 6-2. /usr/local/libexec/lpfilter

#!/bin/sh
# Treat LF as CR+LF
printf "\033&k2G" && cat && exit 0
exit 2    
# cd /usr/local/libexec
# chmod 755 lpfilter*
    

Note: there is another filter that can be used:

:if=/usr/libexec/lpr/lpf:    
This filter is much more complex than the one presented before. It is written to process the output of nroff and handles underline and overprinting, expands tab characters and converts LF to CR + LF. The source to this filter program can be found in /usr/src/usr.sbin/lpr/filters/lpf.c.

The lptest command can be run again now, this time using the lpd spooler.

# lptest 20 10 | lpr -h    

The lpr program prints text using the spooler to send data to the printer; the -h option turns off the printing of a banner page (not really necessary, because of the sh option in /etc/printcap).

You can solve the staircase problem using a variety of tools and methods, for example C programs. The solution presented has the benefit of being very simple.

6.3. Configuring Ghostscript

Now that basic printing works, the functionality for printing PostScript files can be added. The simple printer used in this example does not support native printing of PostScript files; a program must be used capable of converting a PostScript document in a sequence of commands that can be understood by the printer. The Ghostscript program, from the packages collection, can be used to this purpose (see Chapter 8). This section explains how to configure Ghostscript to print PostScript files on the HP Deskjet 690C.

A second id for the printer will be created in /etc/printcap: this new id will use a different input filter, which will call Ghostscript to perform the actual print of the PostScript document. Therefore, text documents will be printed on the lp printer and PostScript documents on the ps printer: both entries use the same physical printer but have different printing filters.

The same result can be achieved using different configurations. For example, a single entry with a filter could be used: the filter should be able to automatically determine the format of the document being printed and use the appropriate printing program. This approach is simpler but leads to a more complex filter; if you like it you should consider installing the magicfilter program from the packages collection: it does this and many other things automatically.

The new /etc/printcap file looks like this:

Example 6-3. /etc/printcap

lp|local printer|HP DeskJet 690C:\
        :lp=/dev/lpa0:sd=/var/spool/lpd/lp:lf=/var/log/lpd-errs:\
        :sh:pl#66:pw#80:if=/usr/local/libexec/lpfilter:

ps|Ghostscript driver:\
        :lp=/dev/lpa0:sd=/var/spool/lpd/ps:lf=/var/log/lpd-errs:\
        :mx#0:sh:if=/usr/local/libexec/lpfilter-ps:    

Option mx#0 is very important for printing PostScript files because it eliminates size restrictions on the input file; PostScript documents tend to be very big. The if option points to the new filter. There is also a new spool directory.

The last step is the creation of the new spool directory and of the filter program.

# cd /var/spool/lpd
# mkdir ps
# chown daemon:daemon ps
# chmod 770 ps
    

The filter program for PostScript output is more complex than the text base one: the file to be printed is fed to the interpreter which, in turn, sends to the printer a sequence of commands in the printer's control language. We have achieved to transform a cheap color printer in a device suitable for PostScript output, by virtue of the NetBSD operating system and some powerful freeware packages. The options used to configure Ghostscript are described in the Ghostscript documentation: cdj550 is the device used to drive the HP printer.

Example 6-4. /usr/local/libexec/lpfilter-ps

#!/bin/sh
# Treat LF as CR+LF
printf "\033&k2G" || exit 2
# Print the postscript file
/usr/pkg/bin/gs -dSAFER -dBATCH -dQUIET -dNOPAUSE -q -sDEVICE=cdj550 \
-sOutputFile=- -sPAPERSIZE=a4 - && exit 0
exit 2    

To summarize: two different printer names have been created on the system, which point to the same physical printer but use different options, different filters and different spool directories. Text files and PostScript files can be printed. To print PostScript files the Ghostscript package must be installed on the system.

6.4. Printer management commands

This section lists some useful BSD commands for printer and print jobs administration. Besides the already mentioned lpr and lpd commands, we have:

lpq

examine the printer job queue.

lprm

delete jobs from the printer's queue.

lpc

check the printing system, enable/disable printers and printer features.

6.5. Remote printing

It is possible to configure the printing system in order to print on a printer connected to a remote host. Let's say that, for example, you work on the wotan host and you want to print on the printer connected to the loge host. The /etc/printcap file of loge is the one of Example 6-3. From wotan it will be possible to print Postscript files using Ghostscript on loge.

The first step is to enable on the loge host the print jobs submitted from the wotan host. This is accomplished inserting a line with the wotan host name in the /etc/hosts.lpd file on loge. The format of this file is very simple: each line contains the name of a host to be enabled.

Next, the /etc/printcap file on wotan must be configured in order to send print jobs to loge. For example:

lp|line printer on loge:\
	:lp=:sd=/var/spool/lpd/lp:lf=/var/log/lp-errs:\
	:rm=loge:rp=lp

ps|Ghostscript driver on loge:\
	:lp=:sd=/var/spool/lpd/lp:lf=/var/log/lp-errs:\
	:mx#0:\
	:rm=loge:rp=ps    

There are four main differences between this configuration and the one of Example 6-3.

  1. The definition of "lp" is empty.

  2. The "rm" entry defines the name of the host to which the printer is connected.

  3. The "rp" entry defines the name of the printer connected to the remote host.

  4. It is not necessary to specify input filters because the definitions on the loge host will be used.

Now the print jobs for "lp" and "ps" on wotan will be sent automatically to printer connected to loge.