Lp is a collection of programs used to provide an easy-to-use interface for printing a variety of document types on a variety of printers. Lp is the glue that connects various document language translators and printer communication programs together so that the users may have a consistent view of printers. Most of the glue is shell script, which can be easily modified. The user need not specify options to get sensible output in most cases. Lp is described here so that others may make additions and changes.
Lp is used to format and print data on a variety of output devices. The need for lp was rooted in the inability of other printer spoolers to do simple tasks without a great deal of user specification of options. At the time lp was written, there were several printer languages, such as ImPress and PostScript, and an internally developed printer that would accept troff output. Now, all our printers take PostScript, but printers that use HPCL and HPGL abound and support for those printers may be added easily. A great deal of what underlies lp is taken from BSD's lpr and System V's lp. The important features of this system are that most of the programs are easily modified shell scripts and the user need not learn to use the large amount of underlying software developed by others. Lp runs under Plan 9 and several flavors of UNIX. This document deals with lp as it relates to Plan 9. Lp was developed using both Datakit and Ethernet to transport data between machines. Now only the Ethernet transport mechanism remains.
Text, graphics, and formatted text files are appropriately processed and placed into a spool directory from which they are taken to be printed by a daemon process. Additional functions include checking the status of a printer queue and removing jobs from the printer queue.
All the shell scripts (see rc(1)) associated with lp reside in the spool directory /sys/lib/lp except for the lp command itself, which resides in /rc/bin. Commands related to lp that are not shell scripts can most often be found in /$cputype/bin/aux. The directory where all the lp scripts reside is defined within lp by the shell variable LPLIB. In the remainder of this document, file names will be specified with this shell variable as their root.
Lp requires an output device to be specified before it will process input. This can be done in any of three ways described here.
If
printer
is
?,
a list of printers and other information in the
devices
file is printed, as shown in Figure 1.
Quote the question mark to prevent it from being
interpreted by the shell language as a metacharacter.
% lp -d'?' device location host class fn 2C-501 helix post/2+600dpi+duplex pcclone - - post+nohead peacock 2C-501 cetus post/2+300dpi+nohead+color ps83 st8_fl3 rice post+300dpi+reverse psu 2C-501 cetus post/2+1200dpi . . . %
Normally, lp uses the file command to figure out what type of input it is receiving. This is done within the generic process which is discussed later in this paper in the Process directory section. To select a specific input processor the -pprocess option is used where process is one of the shell scripts in the process directory.
% troff -ms lp.ms | lp -dfn
% troff -ms lp.ms | lp -dstdout > lp.ps
% latex lp.tex . . % lp lp.dvi . . %
% lp -dpsu -q daemon status: : 67.17% sent printer status: %%[ status: busy; source: lpd ]%% queue on cetus: job user try size rice29436.1 pg 0 17454 slocum17565.1 ches 1 49995 %
$ lp -dpsu -k rice29436.1 rice29436.1 removed from psu queue on cetus
There are options available to modify the way in which a job is handled.
It is the job of the
lp
programs to convert the option settings so they may be used by each of the
different translation and interface programs.
Not all options are applicable to all printer environments.
Table 1 lists the standard
lp
options, the shell variable settings, and description of the options.
Table 1. Lp Option List
The devices file is found in the spool directory. Each line in the file is composed of 12 fields, separated by tabs or spaces, that describe the attributes of the printer and how it should be serviced. Within the lp command, a shell variable is set for each attribute; the following list describes them:
The following sections describe the basic functions of the programs that are found in the subdirectories of $LPLIB. The programs in a specific directory vary with the type of output device or networks that have to be used.
The generic preprocessor is the default preprocessor for most printers. It uses the file(1) command to determine the format of the input file. The appropriate preprocessor is then selected to transform the file to a format suitable for the printer.
Here is a list of some of the preprocessors and
a description of their function.
A complete list of preprocessors and their descriptions can be found in the manual page
lp(8).
The generic spooler is responsible for executing the preprocessor and directing its output to a file in the printer's queue. An additional file is created containing information such as the system name, user id, job number, and number of times this job was attempted.
Certain printer handling programs do not require separate preprocessing and spooling. For such circumstances a nospool spooler is available that just executes the preprocessing program. The processing and spooling functions are assumed by this program and the output is sent to OUT_DEV or standard output if OUT_DEV is '-'.
The pcclone spooler is used to send print jobs directly to a printer connected to a 386 compatible printer port (See lpt(3)).
The function of the shell scripts in the stat directory is to present status information about the printer and its queue. When necessary, the stat scripts may be designed to return information about the local queue as well as the remote queue. This is not done on Plan 9 because many systems share the same queue directory. The scheduler is used to print the queue in the order in which the jobs will be executed.
The kill scripts receive command line arguments passed to them by lp and remove the job and id files which match the arguments for the particular queue. When a job is killed, the generic kill procedure:
The daemon shell scripts are the last to be invoked by lp if the -Q option has not been given. The daemon process is executed asynchronously with its standard output and standard error appended to the printer log file. The log file is described in a subsequent section. Because the daemon runs asynchronously, it must catch signals that could cause it to terminate abnormally. The daemon first checks to see that it is the only one running by using the LOCK program found in the /$cputype/bin/aux directory. The LOCK command creates a LOCK file in the printer's queue directory. The daemon then executes the scheduler to obtain the name of the next job on the queue.
The processing of jobs may entail transfer to another host or transmission to a printer. The details of this are specific to the individual daemons. If a job is processed without error, it is removed from the queue. If a job does not succeed, the associated files may be moved to a printer specific directory in $LPLIB/prob. In either case, the daemon can make an entry in the printer's log file. Before exiting, the daemon should clean up lock files by calling UNLOCK.
Several non-standard daemon programs have been designed to suit various requirements and whims. One such program announces job completion and empty paper trays by causing icons to appear in peoples' seemail window. Another, using a voice synthesizer, makes verbal announcements. Other daemons may be designed to taste.
The scheduler must decide which job files should be executed and in what order. The most commonly used scheduler program is FIFO, which looks like this:
ls -tr $* | sed -n -e 's/.* *//' \ -e '/^[0-9][0-9]*.[1-9][0-9]*$/p'
There are four directories where lp writes files. On the Plan 9 release these directories may be found in a directory on a scratch filesystem that is not backed-up. This directory is /n/emelieother/lp. It is built on top of a file system other that is mounted on the file server emelie. The four directories in this scratch directory are log, prob, queue, and tmp. Lp binds (see bind(1)) the first three into the directory /sys/lib/lp for its processes and their children. The tmp directory is bound to the /tmp directory so that the lp daemons, which run as user `none', may write into this directory.
On any new installation, it is important that these directories be set up and that the /rc/bin/lp command be editted to reflect the change. If you do not have a scratch filesystem for these directories, create the four directories log, prob, queue, and tmp in $LPLIB (/sys/lib/lp) so that they are writable by anyone.
The log files for a particular printer appear in a subdirectory of the spool directory log/printer. There are currently two types of log files. One is for the daemon to log errors and successful completions of jobs. These are named printer.day where day is the three letter abbreviation for the day of the week. These are overwritten once a week to avoid the need for regular cleanup. The other type of log file contains the status of the printer and is written by the program that communicates with the printer itself. These are named printer.st. These are overwritten with each new job and are saved in the $LPLIB/prob directory along with the job under circumstances described below. When a printer does not appear to be functioning these files are the place to look first.
When a job fails to produce output, the log files should be checked for any obvious problems. If none can be found, a directory with full read and write permissions should be created with the name of the printer in the $LPLIB/prob directory. Subsequent failure of a job will cause the daemon to leave a copy of the job and the printer communication log in $LPLIB/prob/printer directory. It is common for a printer to enter states from which it cannot be rescued except by manually cycling the power on the printer. After this is done the print daemon should recover by itself (give it a minute). If it does not recover, remove the LOCK file from the printer's spool directory to kill the daemon. The daemon will have to be restarted by sending another job to the printer. For PostScript printers just use:
echo '%!PS' | lp
There are conditions that occur which are not handled by the daemons. One such problem can only be described as the printer entering a comatose state. The printer does not respond to any messages sent to it. The daemon should recover from the reset and an error message will appear in the log files. If all else fails, one can kill the first job in the queue or remove the LOCK file from the queue directory. This will kill the daemon, which will have to be restarted.
A Plan 9 CPU server can be set up as a printer's spooling host. That is, the machine where jobs are spooled and from which those jobs are sent directly to the printer. To do this, the CPU must listen on TCP port 515 which is the well known port for the BSD line printer daemon. The file /rc/bin/service/tcp515 is executed when a call comes in on that port. The Plan 9 lpdaemon will accept jobs sent from BSD LPR/LPD systems. The /$cputype/bin/aux/lpdaemon command is executed from the service call and it accepts print jobs, requests for status, and requests to kill jobs. The command /$cputype/bin/aux/lpsend is used to send jobs to other Plan 9 machines and is usually called from within a spooler or daemon script. The command /$cputype/bin/aux/lpdsend is used to send jobs to machines and printers that use the BSD LPR/LPD protocol and is also usually called from within a spooler or daemon script.
Special thanks to Rich Drechsler for supplying and maintaining most of the PostScript translation and interface programs, without which lp would be an empty shell. Tomas Rokicki provided the TeX to PostScript translation program.