                                                                  







                PLP - The Public Line Printer Spooler
                                  
                                  
                                  
                                  
                                  
                                  
           A Portable UN*X Network Printer Spooler System
                                  
                                  
                                  
                      Release 4.0, January 1995
                                  
                                  
                                  
            - Prof. Patrick Powell of the Electrical and
                     Computer Engineering Dept.,
           San Diego State University (papowell@sdsu.edu).
                                  
                   Justin Mason, Iona Technologies
                          (jmason@iona.ie).




This document describes the Public Line Printer Spooler (PLP). The
functional resemblance between this software and the Berkeley Line
Printer Spooler (LPD) is intentional.


The author of the PLP software is Prof. Patrick Powell of the
Electrical and Computer Engineering Dept., San Diego State
University (papowell@sdsu.edu). PLP is copyright - 1988 Patrick
Powell. However, the maintenance and improvement of the PLP software
has been taken up by Justin Mason (jmason@iona.ie). This distribu
tion is released under the terms of the original copyright.


For legal reasons, PLP is not public domain software, but may be
copied and/or modified as long as the original copyright notice is
retained.



(Note: this document currently describes some features of PLP 4.1,
namely that the LPD is the only process to read or write the spool
directories and files directly;  PLP 4.0 allows the client programs
to alter and read these files. In addition, unless the NFS
functionality is used, PLP 4.0 requires a daemon on all PLP hosts.
These requirements will be unnecessary in the new version. PLP 4.1
is currently on alpha release).
                              Contents
1. OVERVIEW                                                            4
2. THE PLP PROGRAMS                                                    6
2.1. LPD -THE LINE PRINTER DAEMON PROGRAM                              6
 2.1.1. LPD -UNSPOOLER OR QUEUE SERVERS                                6
2.2 LPR -THE JOB SUBMISSION PROGRAM                                    7
2.3. LPQ - SPOOL QUEUE STATUS DISPLAY PROGRAM                          8
2.4. LPRM - JOB REMOVAL PROGRAM                                        8
2.5. LPC - PRINTER CONTROL PROGRAM                                     8
3.  SOME COMMON REQUIREMENTS                                           10
3.1.USING PLP IN A NETWORKED ENVIRONMENT                               10
 3.1.1. PRINTER NAMES                                                  10
3.2. PASSING FORMATTING OPTIONS FROM LPR                               10
 3.2.1. USING Z-OPTIONS FROM THE LPR COMMAND-LINE                      11
 3.2.2. USING THE PRINTER NAME TO PASS OPTIONS                         11
3.3. THE RELATIONSHIP BETWEEN PRINTERS AND QUEUES                      11
 3.3.1. FUNNEL QUEUES                                                  11
4. THE STRUCTURE OF THE SPOOL DIRECTORY                                13
5. THE PRINTCAP DATABASE                                               14
5.1. THE PRINTCAP FORMAT                                               14
5.2. THE SD PARAMETER                                                  15
6. THE PRINTCAP PARAMETERS                                             16
6.1. COMMON PRINTCAP PARAMETERS                                        16
 6.1.1. THE LOG FILE                                                   16
 6.1.2. THE LOCK AND STATUS FILES                                      16
 6.1.3. SUPPLEMENTAL PERMISSIONS FILES                                 16
 6.1.4. JOB SIZE AND NUMBER OF COPIES                                  16
 6.1.5. RETRY LIMITS                                                   17
6.2. LOCAL PRINTER PRINTCAP PARAMETERS                                 17
 6.2.1. OUTPUT DEVICE PATHNAME                                         17
 6.2.2. SERIAL LINE CHARACTERISTICS                                    17
 6.2.3. LP PIPES                                                       18
 6.2.4. BANNERS, LEADERS AND TRAILERS                                  18
 6.2.5. LOCAL PRINTER FILTER SUPPORT                                   19
 6.2.6. FORMAT-RELATED FIELDS                                          19
 6.2.7. PREFILTERS                                                     20
6.3. REMOTE PRINTER PRINTCAP PARAMETERS                                20
6.4. PARAMETERS FOR MULTIPLE-PRINTER QUEUES                            20
7. THE PRINTER PERMISSIONS FILE                                        22
8. FILTER SUPPORT                                                      24
8.1. FILTER PROGRAM INVOCATION AND ACTIONS                             24
8.2. PARAMETERS PASSED TO FILTERS                                      24
8.3. BANNER PRINTING FILTERS                                           26
8.4. ACCOUNTING INFORMATION                                            26
8.5. PREFILTERS                                                        26
8.6. ADAPTING EXISTING FILTERS AND WRITING FILTERS                     26
9. PLP DAY-TO-DAY ADMINISTRATION                                       28
9.1. USING LPC                                                         28
10. DIAGNOSTICS AND TROUBLESHOOTING                                    29
10.1. LPD                                                              29
10.2. LPR                                                              29
10.3. LPQ                                                              29


The Public Line Printer Spooler (PLP) software is a reverse
engineered version of the Berkeley Line Printer Spooler (LPD).
During the implementation, there was no recourse to any of the
Berkeley LPD source, other than for tables that are used to print
large letter banners1. Due to experience with the Berkeley software,
some LPD routines and functionality may be duplicated, but in
general the implementation and structure of the PLP software is
radically different.

The Public Line Printer Spooler supports:

1.  More than one printer per spooling queue.
2.  Prioritised jobs.
3.  Both local and remote printers, including support for chains of
     remote printers.
4.  Printers attached via serial lines, which can have line
     characteristics such as baud rate, parity, etc., specified.
5.  Devices such as an Imagen or HP laser printer which may require
     (or allow) use of a special communications protocol for
     printing.
6.  Operation in a networked environment.
7.  Precise restriction of use by a printer permissions data base.
8.  Holding  jobs.
9.  Forms, so that a job is automatically held until an operator
     changes the paper.
10. A method to pass "out of band" options to filters, so duplex
     mode or 2-up printing can be supported.

The major components of PLP are the following files and commands;
seeFigure 1.1.




Name          Default LocationType       Purpose
                                      
plp.conf      /etc           config     PLP configuration file
                           file
printcap      /etc           config     Printer description database
                           file
printer_perm  /etc           config     Printer permissions database
s                           file
log           /var/spool/lpd file       lpd log file
lock.host     /var/spool/lpd file       lpd lock file
lpd           /usr/local/bin command    PLP daemon
lpr           /usr/local/bin command    Enter job(s) in a printer
                                      queue
lpq           /usr/local/bin command    Examine a printer queue
lprm          /usr/local/bin command    Remove job(s) from a printer
                                      queue
lpc           /usr/local/bin command    Administer printers and
                                      queues
printer/tcp   /usr/local/bin TCP/IP     TCP/IP port on which lpd
                           port       listens
                                        
Figure 1.1: The major                
components of PLP.


The  locations of most of these components can be changed using  the
plp.conf  configuration file, which usually lives in /etc.  See  the
manual page plp.conf(5) for more details.

The  printcap file is a database describing characteristics of  line
printers either directly attached to the host or accessible across a
network. The format of the printcap database is based on that of the
termcap(5) database.

The  printer_perms, or printer permissions file, is used by  PLP  to
allow  or deny access to operations, queues, and services, based  on
user,  group, and remote machine. It supports wildcard  matching  on
all  its  fields. The printer permissions file is similar in purpose
to  the  hosts.lpd file that is used by the BSD lpd, but has signifi
cantly extended functionality.

PLP  also  includes optional support for printcap and  printer_perms
lookups using the NIS and Hesiod network database protocols. See the
supplementary document, Cross-Domain printing using Hesiod with PLP,
for more details.

The user and group IDs used by PLP can be altered; the default is to
use  user daemon, group daemon, but this can be overridden using the
plp.conf(5) file's user parameter.

The lpr program creates print jobs from the user's data, then passes
this  to  the  lpd  daemon and returns to the user,  so  the  actual
printing happens offline.

The lpq program can be used by the user to query the status of their
jobs and the queue.

The lprm program allows removal of jobs from spool queues.

An  extension  to  the  normal BSD suite of tools  is  the  printers
program, which outputs details of the available printer queues.

The   lpc  program  is  used  to  control  spooling  and  unspooling
activities by the printer operator, including starting and  stopping
queues,  disabling printing, changing priorities  of  jobs,  holding
jobs,  and notifying PLP of which forms or media are loaded  on  the
printer.

The   lpd  program  acts  as  a  daemon  and  carries  out  actions,
transparent to the user. These include queueing  jobs for  printing,
filtering  into other formats, adding banner or other user  and  job
identification  information, and the actual communication  with  the
printer hardware.

Communication  between the lpd daemon and the  utility  programs  is
done using the TCP/IP IPC support provided by most UNIX systems, and
is based on RFC-1179 (The LPD Protocol). Each host has an lpd daemon
which  listens  on a well known port of the host,  and  carries  out
requested activities.

The    lpd    daemon    lock   file   has   the   following    form:
/var/spool/lpd/lock.host, where host  is the non-qualified  form  of
the  host name. It is used to avoid running two LPD daemons  at  the
same time on the same host.

PLP  is deliberately file-format neutral, in that it does not impose
limitations on the format of spooled jobs. However, the lpr  program
can optionally restrict the characters used in input files, unless a
command-line option is used to indicate binary data.

The remainder of this document provides details of the structure and
implementation of the above facilities and programs, and how to  use
them.
2. The PLP Programs

The  following  section outlines the operation of  the  lpd(8)  line
printer  daemon, and the lpr(1), lpq(1), lprm(1), and lpc(1) utility
programs.

2.1. LPD -The Line Printer Daemon Program

The lpd(8) program is usually invoked at boot time from the /etc/rc
or /etc/rc.local startup file, and acts as a server or daemon for
coordinating and controlling the spooling queues configured in the
printcap file or files. Figure 2.1 is a section of sh(1) script
typically used to start the lpd daemon.

     # Start the lpd daemon
     #
     if [ -x /usr/local/bin/lpd ]; then
          /usr/local/bin/lpd && echo -n ' printer-
     >>/dev/console
     fi
     
     Figure 2.1 Startup File Command for LPD

When lpd is started, it checks to see if there is an active lpd
daemon already running by trying to lock the LPD lock file. If no
daemon is present, lpd forks a server process for each non-empty
spool queue in the printcap(5) data base (these queue servers  are
described in the next section). It then listens for service requests
on a specific Internet domain port, printer/tcp by default.

lpd can also be started from inetd(8) using the -i command-line
option. If it is used in this fashion, it will not start a queue
server for each non-empty queue at startup, as this would incur too
much of a performance hit to be worthwhile.

When a connection is made to the lpd port by a requesting client,
lpd uses fork(2) to create a sub-server process to carry out the
request; the original daemon process continues to listen for new
requests.

2.1.1. LPD -Unspooler or Queue Servers

After reading the request, the server process reads the permissions
file to determine if the originating host has permissions to access
the specified printer. Next, the printcap data base is read to
determine the set of options and restrictions that apply to the
spool queue or printer. Finally, the server uses this information to
perform the requested action.

During initialization and in response to start printer requests from
the network, lpd starts an unspooler or server process that pro
cesses jobs in the spool queue. Jobs are placed in the spool queue
and removed by the server process. If there is insufficient space to
store the job, it is refused.

Each spool queue has a lock file which is used to control spooling
and printing (correctly referred to as unspooling) activities on
that queue.  The lpc utility is designed as a front-end for
disabling and enabling spooling and printing.

If unspooling is enabled, the server tries to lock the lock file; if
it cannot be locked, then another server is active and the process
will change the permission of the lock file and exit. This causes
the existing server to re-check the queue for the newly-spooled
jobs.

Assuming no server was already running, this new server has gained
control of the queue. It finds the entries in the queue, sort them
in order of priority and time2, and then unspools3 them according to
specifications in the printcap file. When a job is unspooled, the
server will lock the job's control file in order to prevent other
processes from manipulating the job while PLP is working on it. If
it cannot lock the control file, then the job is currently being
manipulated, probably by another PLP program, and the server will
skip that job.

If the spool queue is for a printer attached to the local host (a
local printer), the server process will use the entries in the
printcap database to determine:

-     The path to the printer device, or an LP-pipe program to be
     used to communicate with the printer hardware;

-     Any characteristics of the connection between the lpd and the
     printer device which need to be set, such as serial line
     attributes;

-     Unusual methods of manipulating the printer hardware, eg.
     causing a form feed or forcing duplex printing;

-     Filter programs to be used to print banners, process the job,
     and/or handle accounting.

If the spool queue is for a printer attached to another host (a
remote printer), the server will attempt to connect to the remote
host and transfer the jobs in the spool queue to the remote host.
Filtering can be performed on the data files before the transfer.
multiple remote printers are supported, where one remote printer can
feed to another remote printer, ad infinitum.

If there are multiple unspooling devices or printers for a local
queue, the server process checks to see if unspooling is enabled for
the queue, and then forks individual unspooler processes for each
printer. The printer processes will read the printcap entries for
each printer, and then check the status of separate lock files which
control the action of each printer. Thus, individual printers can be
enabled or disabled as well as the entire spool queue.

A useful feature of multiple-printer queues is that size limitations
can be placed on each printer, so one printer can be set up to print
small jobs, with another printer to print the larger jobs.

2.2. LPR - The Job Submission Program

The lpr program is used to send a print job to a spool queue-s LPD
process for printing. The lpr program itself does not need to read
the printcap database, thus obviating the need for a printcap file
on hosts where no printer server is to be run. Instead, it contacts
the spool queue-s LPD process, and receives the relevant details
from the printcap and printer_perms database on that host.

Spooling is enabled by the state of the spool queue lock file permis
sions. Permission to use a spool queue is determined by using the
printer permissions file. If the user can submit jobs to the spool
queue (has R or C privileges),lpr will then transfer her file(s) to
the LPD process along with user details, options for printing,
information for banners and so on. In addition, lpr can be requested
to remove the original file after it has been spooled. For some
formats, lpr can be configured to check input files for printable
characters.

Before a job is placed in the spool queue, it may be desirable to do
some local processing or prefiltering of the files, especially when
this local processing may require input from the user. For example,
running a formatter such as pr, translating a typesetter format file
into a different form, etc., can be done by lpr. These actions are
controlled by prefilter information specified in the printcap entry
on the LPD host.

It is possible to suppress banner printing, using the lpr -h option,
although this can be overridden by the lpd.

Associated with each job is a format that specifies how the job is
to be processed. For example, the f format is the default format,
and is used when files contain printable information. Each format
can have a prefilter that is to be applied to the job before it is
placed in the spool queue.  This is primarily a historical feature,
and is provided for compatibility with the BSD LPR system.

Once the job has been placed in a queue, lpr will request the lpd
daemon to start a queue server.

2.3. LPQ - Spool Queue Status Display Program

The lpq program displays the status and contents of selected spool
queues. Lpq has two forms of output: the (default) long format which
displays a complete summary of the current spool queue activities,
and a short format which simply lists the jobs that are outstanding,
The output format of lpq is extraordinarily verbose, and attempts to
give a full picture of the total state of the printer device and its
associated queues, servers, and other information. The following is
an example of the output produced by lpq when displaying the status
of a remote spool queue.

Local Printer -lp- (destructor.cs.umn.edu):
  Printing since Mar 27 14:02:06.
  Rank Owner       Pr Opt  Job Host         Files               Size
Date
   1st jmason      X  -    154 destructor   /etc/motd           55
14:02
   2nd jmason      X  -    153 destructor   /etc/motd           55
14:02
Remote Printer -diablo- (julius.cs.umn.edu):
  Warning: no server present
  Rank Owner       Pr Opt  Job Host         Files               Size
Date
   1st jmason      X  -    152 destructor   /etc/motd           55
14:02

The first line identifies the name of the local printer, and the
host. It is followed by an informative message generated by the
currently active server process. Next is a list of the files in the
local queue, ranked according to their processing order. The next
line identifies the remote printer and site. The warning message
indicates that no server process is present, even though there are
jobs in the spool queue. This is a transitory condition, because the
server process will be started as soon as the file transfers are
completed. After that follows a list of the files in the remote
queue.

     imagen_lind27: 0 jobs
     imagen_ld27: 3 jobs
     1 cfZ022julius: root
     2 cfZ023julius: root
     3 cfZ024julius: root

The short form of status display illustrated above merely gives a
summary of the numbers of jobs and their order in the queue.

2.4. LPRM - Job Removal Program

The lprm command deletes jobs from a spooling queue. If necessary,
lprm will kill a server process which is working on the job. After
removing any files, it will then restart the queue by sending a
start printer request to the lpd daemon. Lprm will lock a job
control file before removing the job, preventing a server from
trying to unspool the job while it is being removed.

If a user can submit jobs to a queue, she can remove jobs that she
has submitted. The permissions file is used to determine which other
users can remove a job.

2.5. LPC - Printer Control Program

The lpc program is used to monitor and control the operation of PLP
by manipulating the status of spool queue lock files, and killing
active servers. It can send messages to PLP daemons requesting that
they carry out similar actions, controlling both local and remote
lpd daemons. It is not necessary to log onto a remote machine to
perform control actions, as long as the permissions file permits.
The commands accepted by the lpc program are detailed in section 9.
Unless specified as unprivileged, they can only be used by a user
with control permissions for the specified spool queue, and on the
local host. All or individual queues can be operated on.
3.  Some Common Requirements

This section describes some common requirements which are addressed
by PLP.

3.1. Using PLP In a Networked Environment


The BSD convention of keeping the printcap and permissions files in
the /etc directory is easy to use in a single host or loosely
coupled multiple processor environment. However, it can be difficult
to manage and apply in a networked environment.

As mentioned previously, PLP supports access to these databases
using the Hesiod and NIS network database protocols. This
functionality is discussed further in the supplementary document,
Cross-Domain printing using Hesiod with PLP.

If a file-based solution is preferred, the PLP software allows the
use of multiple printcap and printer_perms files, and allows the
names of these files to be qualified by the hostname of the machine
PLP is running on. This can be accomplished using the plp.conf
file's printcap-path and printer_perms-path directives, as follows.

     printcap-path
     /var/spool/lpd/printcap.%h:/var/spool/lpd/printcap
     printer_perms-path
     /var/spool/lpd/pperms.%h:/var/spool/lpd/pperms

Each file will be checked for a matching printcap, and the first
matching entry found will be used, so the local-printer entries can
be kept in /var/spool/lpd/printcap.hostname, and a general-case
rm=hostname, rp=port entry in /var/spool/lpd/printcap.

If you wish to simplify things even more, it is possible to qualify
the local printcap entry using the oh parameter. The general-case
entry can then be specified in the normal way. It is then possible
to use a single printcap file for the entire network!

See the manual page plp.conf(5) and the sample configuration file
plp.conf.nfs in the examples subdirectory for more details.

3.1.1. Printer Names

Printer names and aliases are a major problem faced by
administrators. The convention adopted by many sites is to make the
first, or canonical, name of the printer correspond to the physical
printer type and its location. For example, lw_lind23 is the name of
the Apple LaserWriter in Lind Hall 23. Additional aliases or names
can then be added.

In performing permissions checking, the name supplied by the user is
not used. Instead, the printer-s primary name is used. For this
reason, the primary name should be used in the printer permissions
file.

3.2. Passing Formatting Options from LPR

PLP supports several methods of passing options from lpr out-of-band
(ie, not as part of the file data). Common uses for this include:

-     layup, ie. 1-up, 2-up (2 virtual pages per physical page).

-     duplex printing.

-     print quality - draft, normal or letter quality.

It is up to filters to interpret the options appropriately, as PLP
is format-neutral.

3.2.1. Using Z-Options From the LPR Command-line

Lpr supports the -Z command-line option, which allows you to pass a
string of options into the PLP system. If the Z-options file exists
on the LPD host, it allows you to specify a set of options that can
be set, using the following syntax:

     option=value[,option=value,...]

If no option field is supplied then a default is assumed, also
specified in this file. If the Z-option file does not exist, any
string can be passed in the options string, and no warning will be
printed if an unsupported option is used.

The functionality offered by the Z-options file will probably be
integrated into the printcap database in a future version.

The option string can be passed to the filter using the %Z filter %-
escape. It is up to the filter to interpret it appropriately.

3.2.2. Using the Printer Name to Pass Options

If a set of the client machines cannot use LPR, it is possible to
use the printer name as supplied to the daemon to determine a set of
options that should be applied. The printcap entry for this queue
should contain a set of aliases for each of the options to be
supported; the %p filter %-escape will then contain the name used by
the client program.


3.3. The Relationship Between Printers and Queues

Normally, there is one queue for each output device. However, it is
sometimes worthwhile to change this; some situations where this is
necessary are listed below.

-     Load-balancing between printers, using PLP-s multiple-printer
     support.

-     Supporting several formats for one printer device, without
     using a file-format-detecting filter, or using the out-of-band
     option-passing mechanisms supported by PLP. This is detailed in
     the Funnel Queue section, below.

-     Allowing several queues to output to the same device, without
     one queue hogging the device. If two queues, qa and qb share
     the same output device, the following could happen: user Ann
     sends a large job to qa, and user Bill sends a job to qb
     shortly after qa,commences printing Ann's job. Bill's job
     should be printed next, but if Ann submits another job to qa
     before the first job is finished, qa will move straight on to
     Ann's second job, without allowing qb to print Bill's job, even
     though Bill's job was spooled first.

-     Some LPD implementations, such as the HP JetDirect embedded
     LPD, can only cope with one job at a time and do not perform
     any spooling. If another LPD implementation, such as PLP, tries
     to open a connection to these LPDs while a file is printing,
     the connection is refused, and PLP must sleep and retry. If two
     queues try to send jobs simultaneously, they must sleep and
     retry; even if one queue has been waiting longer, it can still
     be beaten to the printer by the other queue, depending on who
     wakes up soonest after the current job finishes.

3.3.1. Funnel Queues

Sometimes it may be necessary for several queues to feed into one
output device.  In this situation, you should set up a local-printer
queue for the lowest common denominator.  All the other queues feed
into this one as remote-printer queues. The queue that they feed
into is called a funnel queue.

For example, let's say you have an HP Laserjet 4M in PostScript
mode, set up as the queue hp4m ps, and you want a plain-text queue
(hp4m mp) and a plain-text-2-up queue (hp4m mp 2up) that print to
the same device. The hp4m mp and hp4m mp 2up queues should forward
their jobs directly to the hp4m ps funnel queue after filtering
them. The printcap entries in Figure 3.1 illustrate how to do this.
     
     # Multiple queues for one device
     #
     hp4m-ps:\
          :cm=HP LaserJet 4Mplus, postscript:\
          :sd=/var/spool/lpd/hp4m-ps:\
          :lp=|tcp-lp hp4m-host:rs:mx#0:
     
     hp4m-mp|hp4m-mp-1up:\
          :cm=HP LaserJet 4Mplus, with "mp" filter:\
          :sd=/var/spool/lpd/hp4m-mp:\
          :if=/usr/local/etc/printer/run-mp:\
          :rm=localhost:rp=hp4m-ps:
     
     hp4m-mp-2up:\
          :cm=HP LaserJet 4Mplus, with 2-up "mp" filter:\
          :sd=/var/spool/print/hp-mp-2up:\
          :if=/usr/local/etc/printer/run-mp-2up:\
              :rm=localhost:rp=hp4m-ps:
     
     Figure 3.1. Funnel Queue Printcap Entry
4. The Structure of the Spool Directory

Each queue has a spool directory that contains the control and data
files associated with a job. The strategy used to protect spooling
information is as follows:

-                     Each spool directory is owned by user daemon
     and group daemon. The spool directory permissions are 0700,
     i.e. user (daemon) rwx only.

-                     The LPD is the only program which directly
     modifies or reads the spool directory and the files therein.
     (Note: this is not the case in the current version of PLP --
     yet!)

-                     Control and data files in the spooling
     directories have owner daemon and group daemon, and are mode
     0600. This ensures control and data files are not readable or
     modifiable by an ordinary user and that no ordinary user can
     remove files except through lprm.

-                     Each spool queue has a lock file which
     controls queueing and printing. If the lock has owner execute
     permission set then unspooling is disabled; if it has group
     execute permissions set then spooling is disabled; if it has
     other execute permissions set then the spool queue should be re-
     ordered. These attributes are controlled using the lpc command,
     except for the latter which is set automatically by lpd (see
     below).

-    Prevention of multiple instances of a spool queue server is
     done by using the fcntl(2), lockf(3), or flock(2) facility.
     When a server starts, it will try and lock the lock file using
     one of the above locking mechanisms. If the lock fails then
     another server is active, and the permissions on the lock file
     are modified so the existing server knows that the queue should
     be reordered.

-    The active server process records its process ID and the name
     of the control file being processed in the lock file. This
     information is used by lpq to report the queue activity.

-                        Before processing a job, the server process
     will lock the job's control file. This prevents multiple PLP
     programs such as lprm and lpd from operating on the same job
     simultaneously.

-    If there are multiple servers for a single queue, the spool
     queue lock file is used to control spool activities, and
     individual printer server lock files are used to control the
     printers.

-    Each spool queue has a status file which is used to record the
     current status of the server process, and an optional secondary
     status file to record the status of any filters and LP-pipe
     processes. This information is displayed by lpq and lpc.
5. The Printcap Database

The entries in the printcap file or files are used to define and
control the actions of PLP. Each host running a PLP daemon must have
at least one printcap file that is used to specify the spool queues
that are available on the host, although the client machines do not
need one. It (or they) must be readable by all users to be used by
PLP. Permissions to use a particular spool queue are determined by
the printer permissions file. The following section discusses the
structure of the printcap file, and the purpose of entries therein.

5.1. The Printcap Format

The printcap file format is analogous to that of the termcap(5) data
base. Each spool queue has a corresponding printcap entry. Each
entry for a spool queue with multiple servers also has a printcap
entry. Figure 5.1 is an example of a typical entry.

     #    Clunker Printer in Lind 23
     #
     clunker_lind23|clunker:\
          :sd=/var/spool/lpd/clunker:\
          :lp=/dev/lp:st=\t\r\015:\
          :mx#20:wt:fl@:

     Figure 5.1 Sample Printcap Entry

-     Blank lines, leading whitespace, and lines which start with a #
     are ignored.

-     Each entry may be continued across multiple lines by escaping
     the end of line with a backslash (\). Fields of the entry are
     separated by colons (:).
                                  
-     The first field of an entry is the entry name followed by a an
     optional list of aliases. The entry name and aliases are
     separated by a bars (|). The following characters cannot be
     used in a printcap entry's name: |, :, /, @, and ;, as they are
     reserved for special purposes.

-     Parameter fields start with a two letter parameter name,
     followed by a flag indicating the parameter type. Parameters
     can be strings, integers, or flags. String parameters have the
     form xx=ssss (ssss is the string assigned to the parameter),
     integer parameters have the form xx#nnnn, and flag or boolean
     parameters use xx to set and xx@ to clear the flag.

-     Non-printing characters can be represented in a string by using
     the character escape sequences of the C programming language,
     e.g. \n, \015.

-     PLP  supports the tc directive, which has the same effect as it
     does with termcap, namely that it allows you to inherit the
     fields from another printcap entry. For example:

     laser1:sd=/var/spool/lpd/laser1:lp=/dev/ttya:br#19200:ty=-tabs:

     laser2:sd=/var/spool/lpd/laser2:lp=/dev/ttya:tc=laser1:

-     laser2 inherits the fields ty and br from laser1, but it
retains the fields it had, namely
     lp and sd.

-    If a printcap entry contains the nu parameter , it will not be
    used as a queue. This allows you to specify the equivalent of
    object-oriented -abstract base classes-, which act only as
    parents for printcap entries which inherit their fields using
    tc.

-     PLP can also -include- files into the printcap file. Use the
     include directive to do this, as follows:

     include /var/spool/plp/pcap/deskjet.remote

     You may also use relative paths, in which case the files will
     be searched for along a path. This path can be set in the
     plp.conf file, using the printcap-include-path directive; see
     the plp.conf(5) manual page for more details.

-     The plp.conf directive default-printcap-params allows a set of
     default values to be set for all printers, which may prove
     helpful. For example, the mx parameter is used to set a limit
     on the size of documents to be printed; you could disable this
     feature for all printers by adding the following line to your
     plp.conf file.

             default-printcap-params    :mx#0:

See the printcap(5) man page for a complete list of printcap
variables and their default values.

Each entry in the printcap file specifies either a remote spool
queue, a local spool queue with a single printer, a local spool
queue with multiple printers, or a printer for a spool queue with
multiple printers. The information in the printcap entry determines
the type of entry and how the entries in the spool queue are to be
handled.

It is possible to specify that a printcap entry is only to be used
on one machine, using the oh parameter. This allows you to use a
single printcap file for an entire network of machines, with one
local-printer entry for the printer server, and a general remote-
printer entry for the client machines. However, it is important that
the printcap entry with the oh parameter appears first in the
printcap file, otherwise the server machine will use the client
printcap entry as well! See figure 5.2 for an example.
     
     hp4m-ps:cm=HP LaserJet 4Mplus, postscript:oh=class:\
          :sd=/var/spool/print/hp-ps:lf=/share/logs/lpd/hp4m/ps:\
          :lp=|tcp-lp exception 9100:rs:pl#66:pw#80:sh:rw:mx#0:

     hp4m-ps:cm=HP LaserJet 4Mplus, postscript:\
          :sd=/var/spool/print/hp-ps:lf=/share/logs/lpd/hp4m/ps:\
          :rp=hp4m-ps:rm=class:

    Figure 5.2 Client and Server Remote Printer Printcap Entries

By convention, if a user does not specify a printer, either by using
the -P command line option or by setting the PRINTER environment
variable, the printer named lp is used as the default printer. If
there is no printer named lp, the first printer in the printcap file
is used instead.

The contents of the printcap file may be cached by the LPD; this is
enabled using the use-printcap-cache plp.conf directive. The lpd can
be made to reread all its configuration files at any time by sending
it a SIGHUP signal.

5.2. The sd Parameter

The sd (spool directory) printcap parameter specifies the path name
of the directory which will hold jobs. The sd parameter must be
present for all printcap entries which are used for spooling, even
if they only spool files before transferring them to a remote host.
Also, only one printer can use each spool directory, except in the
case of ss (multiple server) queues.
6. The Printcap Parameters

Each printcap entry is made up of a subset of the following
parameters.

6.1. Common Printcap Parameters

The pathnames for all files associated with a spool queue are
relative to the spool queue directory or are absolute paths. The
following section discusses the various files that are used during
the spooling and unspooling process. The following are printcap
parameters which are common to all printcap entries, in addition to
the sd parameter mentioned in the previous section.

6.1.1. The Log File

The spool queue server process, and its subprocesses such as
filters, LP-pipes, banner programs, etc. write error and infor
mational messages to the server log file, which is specified by the
lf (log file) parameter; the default log file is the file log in the
spool directory. If the log file does not exist, then the lpd log
file is used instead.

Serious error messages (those with a priority higher than
LOG_NOTICE) are written both to the log file and logged using the
syslog(3) facility if it is available, or to /dev/console if it is
not.

6.1.2. The Lock and Status Files

The spool queue lock file is used to control spooling and unspooling
operations. The lock file name is specified using the lo (lock file)
parameter, and the default lock file name is lock.  It is usually
only necessary to change this when a multiple-printer queue is used;
in this situation, each printer entry must have its own lock file.

The server status file (the default is status) contains status
information reflecting the operations of the unspooling server
processes for display by lpq. The st (status) parameter can be used
to specify an explicit name for the status file.

An additional status file can be specified with the ps parameter.
This file can be used by filter programs that generate additional
status information that should be available for display by lpq.

6.1.3. Supplemental Permissions Files

Each host has a printer permissions file which is checked by the PLP
software to determine if actions
requested by users or other hosts are permitted. In addition, the xu
(extra permsfile) printcap field may be used to specify an
additional printer permission file to be checked during spooling and
unspooling.

6.1.4.Job Size and Number of Copies

lpr allows multiple copies of a file to be printed, using the -
#number option. The mc (maximum copies) value specifies the maximum
number of copies allowed and the sc (suppress copies) flag
suppresses multiple copies entirely for that queue.

The mx (maximum size) field is used to specify a maximum file size
(in 1 Kbyte blocks) that can be spooled by lpr. Jobs whose total
size (including duplicates) exceeds this limit are not spooled. For
example, the mx#2000 entry restricts jobs to a maximum of 2000
Kbytes. Also, if the mi (minfree) field has a value greater than
zero, it specifies the minimum free space (in 1 Kbyte blocks) to be
left free in the spool directory's filesystem. If a job is received
that would push free space below this value, it is temporarily
refused.

The mi field has a dual value. If it is numeric, it specifies the
actual value in 1 Kbyte blocks. However, if its first character is
non-numeric, it is treated as a filename to be opened, from which
the desired value is to be read.

6.1.5. Retry Limits

The server will attempt to unspool and print a job a number of
times, in case of temporary failure. The number of attempts is set
by the rt (retry) parameter; the default value is 3. A value of -1
or 0 specifies unlimited retries.

If the retries run out, mail will be sent to the user, detailing the
error that caused this failure, and the job will be deleted from the
queue. If a file called errors exists in the spool directory, its
contents are appended to this error mail. This is useful for sending
error output from filters to the user.

It is possible to change the address that error mail is ostensibly
sent from, using the plp.conf directive, mail-from-address. A copy
of the error mail will be Cc-d to this address.

6.2. Local Printer Printcap Parameters

Unspooling from a local printer queue can be done in two manners:
using the unspooling capabilities of the PLP server created for the
queue by the lpd, or by having the server process invoke a special
queue handler process. The latter method is discussed later in this
section.

Associated with each local queue is an output device. These can be
categorized as a file, a serial line, a specialized device with a
non-serial interface, or a pipe. If a device is attached to a serial
line, the printcap should be used to specify how the serial line is
to be conditioned in order to communicate with the printer. Figure
6.3 is a sample printcap entry for a DecWriter III printer connected
over a 1200 baud serial line.

     # Decwriter III in Lind 33
     #
     lind33_decwriter|clunker|Decwriter Model 3:\
          :sd=/var/spool/lpd/lind33_decwriter:\
          :lp=/dev/ttya:rw:\
          :br#9600:ty=evenp -nl -tabs tandem new:
     
     Figure 6.3: Printcap Entry for Serial Line Device
     
6.2.1. Output Device Pathname

The lp (line printer) parameter specifies a path name of the file or
device, or an LP-pipe command (see section 4.5.4), that is to be
opened and output sent to. The device is opened for writing only
(default), or for both reading and writing if the rw flag is
present. Note that there is no default value for the lp field. If
there is no physical device corresponding to the printer, then
lp=/dev/null should be used to specify the null device.

6.2.2. Serial Line Characteristics

Printers connected via a serial communication line must have the
proper baud rate and line characteristics set. The br parameter sets
the bit (baud) rate for the tty line. There are two methods for
setting the line characteristics, as follows:

The fs (set bits) and fc (clear bits) parameter is used to set the
serial line characteristics. The fs and fc set and clear bits in the
line control status word returned by the TIOCGETP ioctl operation,
which is then restored with the ioctl TIOCSETP. In the above
example, fs sets CRMOD, no parity, and XTABS (see tty(4) for
details). The xs and xc are be used to set and clear local control
information using the TIOCCLGET and TIOCCLSET ioctl calls.

The fs/fc/xs/xc method of setting line characteristics is
embarassingly user-hostile, and its use is not recommended; it is
also unportable between BSD and System V based UNIX implementations.
It is only provided for backwards compatibility.
                                  
The ty (stty) parameter uses the same keywords and options as the
stty(1) command. For example, the following parameter can be used
instead of the above fs values:

   ty=nl -odd -even -tabs

Use of the ty parameter is endorsed, as it is both more portable and
more comprehensible than the rather opaque fs/fc/xs/xc parameters.
The ms parameter is an alias for the ty parameter, for compatibility
with SunOS printcap files.

If you need tandem line control you may have to open the output
device for reading and writing using the rw field; this appears to
be implementation dependent.

See the printcap(5) manual page for details of which stty options
lpd recognises. The stty(1) manual page provides an explanation of
the different options.

If it proves necessary to close the output device between jobs, this
is supported using the cl parameter. This may be necessary to clear
the printing engine of internal state.

6.2.3. LP Pipes

To connect to a printer using anything other than a serial line, the
lp parameter must contain an entry of the following form:

   lp=|lp pipe command

This causes the lpd to pipe all output to this command. In addition
to any arguments supplied in the printcap, the standard PLP filter
arguments are supplied (see the section on filters).

Use of the rw  option with LP-pipes is supported on most platforms,
but is not supported on some older UNIX System V derivatives.

6.2.4. Banners, Leaders and Trailers

By default, data files are separated by a banner page generated by
the server process. This is a single page with the user name and job
information printed in large letters. The sb (short banner) option
specifies a single line banner of the following form:

          [user]:[host] Job: [jobname] Date: [date]
Example:  papowell:attila Job: (stdin) Date: Fri May 20 11:29:05
1988

The sh (suppress header) flag suppress banner printing entirely.

The lpr no header option (-h) allows the user to request no header
or banner for the job; the ab (always print banner) printcap flag
causes the server to ignore this no banner request.

Consecutive data files are normally separated by a form feed; the
default (\f) can be changed by specifying a value for the ff (form
feed string) field. The sf (suppress form feeds) can be used to
suppress any printing of form feeds between files.

When the printer is started, it may be necessary to initialize the
printer by sending some additional information. The fo (form feed on
open) flag specifies that the ff string is printed before the first
job, and the fq (form feed on quit) flag specifies that a form feed
is printed after the last job.

In addition, ld (leader) specifies a string to be printed before the
file, and the tr (trailer) specifies a string to be printed after
the file. The ld and tr strings are useful for specifying an escape
sequence that sets up form length, etc.

In addition to the built in banner printer, the bp (banner printer)
and ep (end printer) fields can be used to specify banner and
trailer printing programs. These programs are invoked to print
banners or other information instead of the built in banner or
separator.

6.2.5. Local Printer Filter Support

Local printers support two types of filters - ifilters and ofilters.

Ifilters are invoked individually on each file, and can be used to

-     Add banner information to each page of a file;

-     Convert between formats;

-     Perform accounting;

or a combination of these. The default ifilter is specified by the
if parameter, and is used on jobs printed with the f , l (literal),
or p (pr) formats.

Ofilters are invoked once, when the queue server starts, and persist
until the queue is emptied of active jobs. They are useful to
perform simple conversions on jobs, such as converting the end-of-
line from LF to CR/LF.  No provision is made to identify the
submitter of the files printed, or the beginning or end of files.

Another purpose for which ofilters are used is to convert banners
and job separator strings to a different format. Although PLP
supports the bp, ep, and ff parameters, which provide this
functionality in a more efficient manner, this is provided for
compatibility with BSD ofilters.

Another feature of BSD ofilter semantics which is supported by PLP
is the ofilter stop string. If both an if and an of are specified,
and the fb (filter like BSD) flag is set, then the ofilter will be
instructed to stop between files and the ifilter has direct access
to the printer device or LP-pipe.

The ofilter is instructed to stop with the two-character sequence
\031\001, or ^Y^A. It should then suspend itself using kill(0,
SIGSTOP).  The server will wait for this event; once it happens, it
will start up the ifilter, and when that finishes, it will signal
the ofilter to restart using the SIGCONT signal.

By default, the fb flag is off.

6.2.6. Format-Related Fields

Each job in a spool queue has an associated format, which is
represented by a lower case letter4. There are several lpr options
such as n, d, etc. which can be used to specify a limited set of
formats, or the -Fx option can be used to specify any format. For
example, the -Fn option, used below, specifies printing using the n
format.

     ditroff -Tdumb -ms myfile | lpr -Fn -Premote

The format supported by a spool queue can be restricted by the fx
(formats supported) printcap field, which specifies the formats sup
ported by the spool queue. In Figure 4.3, the fx=ilpn field
restricts formats to i, l, p, and n. Some formats require that files
be printable (contain only the printable characters in the ISO-8859-
1 character set), or other restrictions. By default, only the f and
p formats are checked by lpr for printable files. The xt field is
used to specify additional formats to be checked for printability.

This is primarily a historical feature, and is included for
compatibility with the BSD LPR system. Nowadays, it is a better idea
to use a filter which can automatically detect file formats and
convert based on this information, such as fconvert. The advantage
of this method is that it requires no user knowledge of the -F
command line option and its corresponding formats.

6.2.7. Prefilters

It may be desirable to process or filter a job at the time that it
is spooled. The program used to filter a job is specified by a field
of the form xe=filtername or xe=filtername,y where x  is the
original format, filtername is the pathname of a program, and y is
the result format. The default result format is f. In addition, the
lpr p option specifies filtering with the pr program; lpr invokes
the program specified by the pr=filtername (default is /bin/pr).

6.3. Remote Printer Printcap Parameters

Remote spool queues specify the remote host using the .rm (remote
host) field and the remote printer using the rp (remote printer)
field. The remote host addressing information is obtained using the
gethostbyname(3N) facility. The remote printer must appear in the
remote host's printcap data base. Unlike most lpd implementations,
PLP supports the use of a filter on files being sent to a remote
printer; a filter is run independently on each file being
transmitted, in the same way as an if for a local printer, so it
uses the if printcap parameter. See section 7 for more details on
the use of filters. i.rm (remote machine) parameter;

Figure 6.4 is an example of an entry for a remote spool queue that
sends its jobs to host umn-cs.cs.umn.edu to be printed on the
lind33_decwriter printer.

     # Decwriter III in Lind 33
     #
     remote|lind33_decwriter:\
          :fx=ilpn:\
          :sd=/var/spool/lpd/lind33_decwriter:\
          :rm=umn-cs.cs.umn.edu:rp=lind33_decrwriter:\
          :xu=perms:ex=n:ne=/usr/local/lib/ddumb:\
          :mx#2000:sc:
     
     Figure 6.4. Remote Printer Printcap Entry

If PLP sends jobs to a remote host that is not running PLP, jobs may
fail due to the fragile nature of older implementations of the LPD
protocol (this often happens with SunOS- default lpd). In this case,
turn on the bk  (backwards compatibility) parameter, which will re-
order the control file's fields into an order which these lpd
implementations will accept, drop unsupported fields, and will force
strict compliance to the protocol.

6.4. Parameters for Multiple-Printer Queues

If a spool queue has been set up with multiple servers, the server
names are specified by the sv (servers) parameter, which contains a
comma separated list of server names. Each server name has a
printcap entry, and each server entry has a corresponding ss
(serves) field which contains the name of the spool queue served by
the printer. Each printer will use the spool queue directory
specified by the sd field of the spool queue that it serves.

     # Multiple servers example
     #
     fast:sd=/var/spool/lpd/fast:sv=fast.a,fast.b:\
          :br#9600:ty=nl -odd -even -tabs:
     
     fast.a:ss=fast:\
          :lo=lock.a:st=status.a:lp=/dev/ttya:
     
     fast.b:ss=fast:\
          :lo=lock.b:st=status.b:lp=/dev/ttyb:
     
     Figure  6.5. Multiple Server Printcap Entry

In the example in Figure 6.5, the fast.a and fast.b printers are
used to serve the fast spool queue. Note that each of them
explicitly specify the name of their lock and status files; as they
will use the same queue directory these filenames must be different.
It should also be noted that, in the example, the fast.a and fast.b
printers inherit the br and ty fields from the fast printcap entry.

Using the li (file size limit) field, it is possible to set up a
multiple-printer queue with different file size limits for each
printer, so a fast printer can be used to print long files, while a
slower printer is used to print shorter files. Again, this value is
specified in 1 Kbyte blocks. The value used specifies a maximum job
size for that queue. However, instead of rejecting the job straight
away (as the mx parameter does), it causes the server to accept the
job, but it will not be printed. This is useful for multiple-device
queues; one device queue has a low limit value, and would print the
smaller jobs. Another device queue has a higher limit value, and
prints the larger jobs that the first queue skips.

The mi field has a dual value. If it is numeric, it specifies the
actual value in 1 Kbyte blocks. However, if its first character is
non-numeric, it is treated as a filename to be opened, from which
the desired value is to be read.
7. The Printer Permissions File

The printer_perms, or printer permissions database, is used by PLP
to allow or deny access to operations, queues, and services, based
on user, group, and remote machine. It supports shell-like wildcard
matching on all its fields. The printer permissions file is similar
in purpose to the hosts.lpd file that is used by the BSD lpd, but
has significantly extended functionality.

The contents of the printer_perms file may be cached by the LPD;
this is enabled using the use-perms-cache plp.conf directive. The
lpd can be made to reread all its configuration files at any time by
sending it a SIGHUP signal.

# -- Line printer permissions
# host      nam  grou  queu  O  P  Max  Don  # Comment
            e    p     e     p  r       e
~*.umn.edu  *    *     *     C  A  0    0    # no non-local sites!
centra.umn  roo  *     *     C  A  0    0    # root@centra: anything
.edu        t
*.umn.edu   roo  *     lp    C  A  0    100  # root@*: ctrl lp, pri A
            t
server.umn  adm  *     lp    R  C  100  200  # admin@server: pri C on lp
.edu        in                     0
!*          cs*  *     lase  R  Z  *    *    # CS accounts, no lasers
                       r*
!*          *    year  lase  R  Z  *    *    # year1 group, no lasers
                 1     r*
*.umn.edu   *    *     lp    R  Z  *    *    # default is priority Z

Table  7.1. Example Printer Permissions File

Each entry in the printer permissions file specifies a host machine,
a username, a group name, a printer or spool queue name, a set of
operations (R, M or C), a maximum priority (A-Z), and a maximum and
current page counts associated with use of a spool queue. Blank
lines and lines that start with # (comments) are ignored. Fields are
separated with one or more spaces or tabs, and leading white space
is ignored.

There is a simple wildcard match facility similar to UNIX shell
globbing. The * character will match 0 or more characters in the
string, and the ? will match exactly one character.  This facility
is available on all fields.

Given a host, user, and spool queue, the printer permissions file is
searched for a matching entry in first line to last line, left to
right order. The host, user, group, and spool queue fields are
checked for a match; the first line found which matches these will
terminate the search.

The host field can refer to hosts (or groups of hosts) by either
their name or their IP address, and wildcard matching is available
for both, as long as it falls on domain or octet boundaries. It is
possible to use fully-qualified domain names (and match patterns
with domains) in the permissions file, regardless of what your
gethostbyname(3n) function returns; if a domain name is used, PLP
will check to see if the current hostname is valid in that domain,
and will return a match based on this. If PLP has been compiled with
the NIS option enabled, netgroups can be used here.

A note on group matching: if a user is in the named group, or has
that group as her login group, then the match succeeds.

If a tilde (~) is the first character on the line, the fields are
checked for a match. If the match fails, then permissions are
refused, regardless of what later matches would return. If the match
succeeds, then further searching will be done.

If an exclamation mark (!) is the first character on the line, all
permissions are refused if the match succeeds; this allows filtering
out requests that are to be rejected in a simple manner. If this
facility is used, entries should be ordered so that refusals (lines
starting with !) precede any matching entries.

For example, the printer permissions file in Table 2.1 allows root
on host centra to control all queues and submit prioritised jobs up
to priority A; root on any machine to control and use priority A on
the lp queue; and admin on server to submit prioritised jobs to the
lp queue. Users whose usernames start with -cs- are denied
permission to use spool queues whose names start with -laser-.

Spool queue operations, spooling priorities, and other information
are set by the matching line. The Ops field controls the allowed
operations; a C value stands for Control, and means that the user
has permissions to use the lpc and lprm programs to manage a queue
as well as spool jobs to it using lpr. An M stands for Move, and
means that the user has permissions to use the lpc move command to
move one of her own jobs to this queue, as well as spool jobs to it.
An R value stands for lpr and means that the user can only spool to
the queue and remove her own jobs. Control functions can be
exercised from remote hosts using the remote command of the lpc
program.

The Priority field determines the maximum priority available to a
user. Users can prioritize jobs, where A is highest priority and Z
is the lowest. The default priority is X.

The maximum and current page count fields are used for accounting .
They are checked when a job is queued by lpr and when the job is
unqueued for printing. If the maximum page count is exceeded by the
user, the job will be refused. They will be replaced by a user-based
page-credit tracking mechanism in the future (when one is
implemented).
8. Filter Support

The filter programs are started by a queue server in order to
support specialized unspooling operations, or to convert between
data formats.

There are a set of template filters supplied with the PLP software
that can be easily modified to meet most common requirements. A
common method of incorporating new filters is to use a sh(1),
perl(1) or tcl(1) script as a filter, and have the shell script
invoke a specialized program with the appropriate parameters. This
technique has a slight penalty in performance, but is very quick to
implement.

8.1. Filter Program Invocation and Actions

Filters are invoked by the queue server, and take their input from
stdin (file descriptor 0), have stdout (file descriptor 1) connected
to the output device, and stderr (file descriptor 2) connected
either to lf (log file) or to a data sink (/dev/null).

Normal completion of the filter results when it reads EOF on stdin,
and should exit with user status 0 if there were no errors. It
should ignore any SIGPIPE signals. A user status 1 indicates that
the job did not complete normally and should be reprinted, and any
other status will cause the job to be discarded. The filter should
also check for successful writes to stdout.

A filter process runs with real and effective user IDs set to daemon
and is in the same process group as its creating server process.
This allows killpg(2) or kill(2) to kill both the queue server
process and any filters it has created. For example, lprm terminates
a running queue handler by sending a SIGINT signal to the queue
server's process group. This signal can be trapped by filters which
need to perform cleanup operations such as deleting temporary files.

8.2. Parameters Passed to Filters

Filters are invoked with a set of parameters determined by the
entries in the printcap, their intended purpose, and other actions.
Figure 8.1 is an example of a filter specification.

     # Versatec Printer, Lind 33
     # Patrick Powell, 3 Nov 87
     #
     versatec|versatec_lind33:\
          :fx=flpdt:mx#2000:\
          :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\
          :af=/usr/adm/vaacct:\
          :if=/usr/lib/vif -h %h -n %n:\
          :of=/usr/lib/vpf -v3 -m '-K prefix \013\015':
     
     Figure  8.1. Filter Specification Example

There are two methods of specifying the special arguments provided
by PLP: using %-escapes, or allowing PLP to provide the default
arguments.

%-Escapes allow the writer of the printcap to specify which
arguments to provide to the filter and in which order. Each %-escape
consists of a % character followed by a character identifying which
parameter to insert, in the fashion of printf(3). The set of valid %-
escapes and their corresponding options are shown in Figure 8.2.

     %p    what the user invoked this printer as (lpr -P option)
     %P    the canonical name for this printer (for accounting)
     %a    accounting file (af printcap entry)
     %s    printer status file (ps printcap entry)
     %w    page width in columns (pw printcap entry, superceded
           by the lpr -w option)
     %l    page length in lines (pl printcap entry)
     %x    page width in pixels (px printcap entry)
     %y    page height in pixels (py printcap entry)
     %m    cost per 1000 pages (co printcap entry)
     %i    indent (lpr -i option)
     %n    username
     %h    hostname
     %N    filename
     %R    accounting name (from lpr)
     %J     job name
     %C    class name (priority)
     %F    job format (old BSD style: -l-, -n- for troff, etc.)
     %Z    Z-options
     %S    printer comment (cm printcap entry)
     %Y    line of perms file where match took place
     %c    "-c" if job format is literal (-l-) format

     Figure 8.2. Valid %-options

Arguments will always be passed as a single argument to the filter
program. Escape sequences, such as those in the of parameter in
Figure 8.1 will be translated into a single character value, and the
resulting string will be an argument for the filter.

The %P (canonical printer) and %p (printer) options are used to pass
the printcap entry printer name. The %w and %l options specify the
horizontal and vertical page size in characters and lines (obtained
from the pw and pl printcap parameters); the lpr -w value will be
passed as the %w option value, if it has been specified by the user.
The %x and %y options specify the horizontal and vertical page size
in pixels (from the px and py printcap entries). The %F (format)
option specifies the format that the user specified in lpr.

The above parameters are provided for all filters, including the
ofilter and bp and ep banner printing filters.

If the fb parameter is set in the printcap entry, an ofilter must
detect the character sequence ^Y^A (\031\001), flush its output, and
suspend itself using kill(0, SIGSTOP). The server may then start up
other filters, and use them to print jobs. After the job has been
printed, the server will signal the ofilter to continue using the
SIGCONT signal.

All filters are invoked with the above parameters, and the
additional ones may be provided depending on functionality. The %c
(literal) flag is optional, and is specified for literal (format l)
output being printed using the ifilter. The %i (indent) value is
optional, and is the value specified by the -i option of lpr. The %Z
(extra parameters) are parameters passed to the filter by the lpr -Z
option. The %C (class or priority) and %J (job name) are optional
and generated by lpr. The %n and %h parameters specify the login
name and host name respectively of the originator of the job.

The last (optional) entry is the name of the accounting file, taken
from the af printcap entry. This may be a default value, or
specified by the user. If the accounting file does not exist or is
unable to be opened in append mode, then accounting action is
suppressed.

If no %-escapes are used in the filter specification in the
printcap, a full set of arguments are provided. These are depicted
in Figure 8.3, which may be present or missing, and in any order.
The accounting file (if present) will always be the last parameter,
and is the only one without a dash prefix.  These are supplied for
compatibility with old versions of PLP.

     filtername arguments \
          -Pprinter -wwidth -llength -xwidth -ylength [-c] [-
iindent] \
          [-Zoptions] [-Cclass] [-Jjob] [-Raccountname] -nlogin -
hHost \
          -Fformat [affile]

     Figure 8.3. Filter Arguments

8.3. Banner Printing Filters

The bp (banner printer) and ep (end printer) entries specify a
banner and end printing program that is invoked at the start and end
of a job. The bp and ep filters are invoked with the same parameters
as the ifilter. Special flags and parameters for these filters may
be specified in the printcap entry.

The banner printing programs will have their stdin (file descriptor
0) set to /dev/null, stdout (file descriptor 1) to the output
device, and stderr (file descriptor 2) to the error logging file.
They must exit with 0 user status for successful completion; any
other value indicates unsuccessful completion and an error will be
reported.

8.4. Accounting Information

Accounting information is appended to the accounting file by the
appropriate filter, or by the lpd itself. Rather than have a complex
binary accounting database, this version assumes that accounting
information will be simple and easy to maintain and understand. The
pac program has been supplied to make accounting information easily
managable, but most accounting procedures can be carried out with a
simple shell script, and a hearty use of sort(1), sed(1), and
awk(1).

If you choose to use pac,  the accounting information produced by
your filters must be maintained in a consistent manner. Entries in
the raw accounting file should have the form illustrated in Figure
8.4.

     host              user printer       format pages date
     attila.cs.umn.edu    root imagen_lind22 n 5 Fri May 20 21:29:22
CDT 1988

     Figure 8.4. Accounting File Entry

The host, user, printer, and format information can be obtained from
the parameters passed to the filter. The page entry is the number of
billable pages, and should be determined, if possible, by the
filter. The pac program produces a summary in the format as in
Figure 8.5.

     host            user printer           format pages jobs
     attila.cs.umn.edu root imagen_lind22     n          5    1
     attila.cs.umn.edu root imagen_lind22     l        220    7

     Figure 8.5. Summary File Entry

PLP provides a default mode for accounting; if the af parameter is
set, and either the la (local accounting) flag or ar  (account
remote transfers) flag are set (as they are by default), then
accounting will be performed by PLP. However, experience has
indicated that most sites use differing approaches to accounting,
with little commonality between different sites- requirements. Thus,
accounting procedures and information may be modified as required,
by switching off PLP's accounting using the la or ar printcap
parameters, and performing your own accounting in a filter program
(usually in the ifilter).

8.5. Prefilters
                                  
The lpr program can use prefilters to process the text before
spooling.

The options are specified in exactly the same manner as for the
filter for the specified format. The prefilter must read its input
from stdin and send its output to stdout, performing whatever filter
functions are neccessary. If successful, the prefilter should exit
with a 0 user status; anything else will indicate failure and the
user job will be discarded. Errors written to stderr will be
directed to the lpr stderr output. Interaction with the user is
possible, using /dev/tty.

8.6. Adapting Existing Filters and Writing Filters

If you have an existing set of filters for the Berkeley LPD daemon,
you should use %-escapes to simulate the BSD arguments. For example,
the following printcap if entry will invoke the imfilter program to
be used as the ifilter.
                                  
      if=/usr/local/lib/imfilter -n %n -h %h [etc.]

It is important to be security-conscious when writing filters; a
compromised daemon account is one of the more popular ways for a
hacker to compromise a root account. PLP itself checks the filter
commands for shell metacharacters and so on, but some of the
metacharacters must be permitted in the arguments in order to avoid
restricting functionality.

If you use the information in  the filter arguments, especially the
ones that come from the control file (such as the job name, user
name etc.), try to check them for illegal characters, and be careful
to quote them if you use them in filenames or exec-d commands, or in
a shell script.

If you are writing a filter in perl, it is a very good idea to test
it out using taintperl; this will inform you when you are using
-tainted- data. You can -de-taint- data by copying it out with a
regular-expression match, which should be used to check for legal
metacharacters, as in this snippet of script:

      # $ARG is the -n element of the ARGV array -- it-s tainted.
      ($ARG =~ /^-n([-_+a-zA-Z0-9.]+)$/) || die -alert! [$ARG]\n-;
      $username = $1;         # $username is now de-tainted
9. PLP Day-to-Day Administration

Most of the administration of PLP consists of maintaining printcap
entries and permissions entries. However, it may be necessary to
manage queues using the lpc program.

9.1. Using LPC

The lpc program provides control over line printer activity. The
major commands and their intended use are described in this section.
See the manual page lpc(8) for further commands not mentioned here,
and extra details.

status, lpq
     Status is used to display the current status of various line
     printers. The lpq function invokes the lpq command with various
     parameters. This is useful to monitor various printer
     activities.

start, abort, kill
     Start enables unspooling and requests lpd to start printing
     jobs.

     Abort disables unspooling and terminates an active server and
     its filters. This is normally used to kill a catatonic filter
     or spooler process (i.e., lpq reports that there is a daemon
     present but nothing is happening). It does not remove any jobs
     from the queue.

     Kill does an abort followed by a start. This is handy for
     restarting a queue whose server process is hung due to problems
     with a job or hardware. Note that there is an upper limit on
     the number of times a server will attempt to print a job; this
     is specified by the rt printcap parameter.

requeue    is useful if the printer hardware malfunctions during the
     printing of a job; Requeue will stop the printer, kill the
     current job, and respool the job to the queue at top priority.
     Once the operator has completed whatever printer maintenance
     needs to be done, the printer should be restarted using the
     start command, and the job will the reprinted.

enable, disable     control spooling to a queue or list of queues.
     This is used to prevent lpr from putting new jobs in the spool
     queue. The main use is to prevent users from putting jobs in
     the queue when the printer is expected to be unavailable for a
     long time.

lpd  reports the state of the daemon on that system and its process
     id.

restart   allows mere mortal users to restart printer daemons when
     lpq reports that there is no daemon present.

stop disables any further unspooling, but does not kill off the
     server. This is a clean way to shutdown a printer in order to
     perform maintenance, etc. Note that users can still enter jobs
     in a spool queue while a printer is stopped, but they will not
     be unspooled until the start command is issued.

topq places jobs at the top of a printer queue. This can be used to
     re-order high priority jobs.

remote command
     used to send a command to the remote site for processing. This
     is useful to control line printer queues across a network.

clean         totally purges a queue. This functionality should be
     needed very infrequently.
10. Diagnostics and Troubleshooting

The diagnostic messages issued by the PLP software are verbose to
the point of being obnoxious. Usually there is enough information
available to determine the exact cause of problems. However, there
are times when a bit of explanation does help, and if you are unsure
of the cause of a problem, you should try enabling the debugging
messages to see if the cause becomes any clearer.

In order to get detailed diagnostic information from any of the PLP
software, you can enable diagnostic messages using the -D option.
PLP supports multiple debug settings for different facilities, or
parts of the PLP functionality. At the moment, there are the
following facilities:
     
pcap           lookups on the printcap file or
               files
perms          lookups on the permissions file
               or files
remote         the remote printer transfer
               mechanism
local          the local printer code; stty,
               device locking, etc.
conf           the plp.conf reading and
               filename expansions
     
You can also set a general debug setting, which will set debug modes
for all the facilities you don't explicitly specify, as well as the
miscellaneous functionality that doesn't fall into one of the above
categories.

The argument to the -D option is used as follows: to set a debug
level for a particular facility, use -D facility=level. To set the
general debug level, use -Dlevel. You can also combine these by
separating them with commas, for example -Dpcap=6,4  would set a
general level of 4 and a level of 6 for the printcap code.

The debug levels work as follows: level 0 is the normal setting (no
diagnostic output), level 3 is chatty, level 5 is pretty verbose,
and level 9 is absolutely everything.

10.1. LPD

When lpd is started, it will try and open a log file. If it cannot,
it will log to /dev/null. However, important errors are logged using
the syslog(3) facility. You can also specify a log file using the -
Lfilename option to lpd; -L- will cause it to log its debug and
error messages to standard output.

Each spool queue may have an associated log file as well, specified
with the lf printcap parameter; if this file does not exist, the lpd
log file is used. The PLP software will also use syslog(8) for
important messages, or log them to /dev/console if syslog is not
available.

10.2. LPR

lpr: printer: unknown printer
     The printer was not found in the printcap database. Usually
     this is a typing mistake on behalf of the user; however, it may
     indicate a missing or incorrect entry in the printcap file.

lpr: printer: jobs queued, but cannot start server.
     The connection to lpd on the server failed. This usually means
     the lpd process started at boot time has died or is hung. Use
     the lpc lpd command to check that the lpd process is running.
     If it appears to be absent, start a new lpd process.

10.3. LPQ

These messages are usually transitory, but may persist if a problem
exists.

waiting for printer to become ready (trying since time)
     The printer device could not be opened by the server. This can
     happen for a number of reasons, the most common being that the
     printer is turned off-line. This message can also be generated
     if the printer is out of paper, the paper is jammed, etc. The
     actual reason is dependent on the meaning of error codes
     returned by the system device driver. Not all printers supply
     sufficient information to distinguish when a printer is offline
     or having trouble (e.g. a printer connected through a serial
     line). Another possible cause of this message is that some
     other process, such as an output filter, has an exclusive open
     on the device. Your only recourse here is to kill off the
     offending program(s) and restart the printer with lpc.

connecting to host (trying since time)
     The server is trying to connect to the remote site and nothing
     has happened. The first indication is that the network is dead,
     or the host you are trying to reach is down. If the remote host
     is up, lpd on the remote machine is probably dead or hung and
     should be restarted.

warning: no server present
     There are entries in the spool queue, but no server exists. The
     server may actually have unexpectedly died. The error log file
     for the spool queue should be checked for a diagnostic from the
     deceased process. Use the lpc restart command to start a
     server.

%
%-escape, %p                                                      10
%-escape, %Z                                                      10
%-escapes                                                         23
/
/etc/rc                                                            5
/etc/rc.local                                                      5
A
ab (always print banner) parameter                                17
af (acct file) parameter                                  23, 24, 25
ar  (account remote transfers) parameter                          25
B
bk (backwards compatibility) parameter                            19
bp (banner printer) parameter                                 18, 25
bp, invocation parameters                                         24
br (baud rate) parameter                                          16
C
cl (close device) parameter                                       17
co (cost) parameter                                               24
D
daemon user                                                   12, 23
data format, related printcap parameters                          18
default-printcap-params plp.conf directive                        14
E
ep (end printer) parameter                                    18, 25
ep, invocation parameters                                         24
errors file                                                       16
F
fb (filter like BSD) parameter                                18, 24
fc (clear bits) parameter                                         16
ff (form feed string) parameter                                   17
filters                                                            6
fo (form feed on open) parameter                                  17
fq (form feed on quit) parameter                                  17
fs (set bits) parameter                                           16
fx (formats supported) printcap field                             18
H
Hesiod                                                             4
hosts.lpd                                                      4, 21
I
if (ifilter) parameter                                        18, 19
ifilter                                                           19
include printcap directive                                        13
inetd(8)                                                           5
L
la (local accounting) parameter                                   25
ld (leader) parameter                                             17
lf (log file) parameter                                   15, 23, 28
li (file size limit) field                                        20
lo (lock file) parameter                                          15
local printer                                                      6
lock file, lpd                                                  4, 5
lock file, spool queue                                  5, 6, 12, 15
log file, lpd                                                      3
lp (line printer) parameter                                       16
lpc                                                         3, 8, 27
lpd                                                            3, 12
lpd protocol                                                      19
lpd, invocation                                                    5
lp-pipes                                                       6, 17
lpq                                                             3, 7
lpr                                                             3, 6
lpr no header option (-h)                                         17
lprm                                                        3, 7, 12
M
mail-from-address plp.conf directive                              16
mc (maximum copies)                                               15
mi (minfree) field                                                15
ms  (stty) parameter                                              17
multiple-printer queues                                       10, 19
mx (maximum size) field                                           15
N
NIS                                                                4
NIS, netgroups in permissions file                                21
Non-printing characters, in printcap entry                        13
nu (not usable) parameter                                         13
O
ofilter, invocation parameters                                    24
ofilters                                                          18
oh (only host) parameter                                          14
oh (only on host) parameter                                        9
P
permissions file                                  3, 4, 5, 9, 15, 21
permissions file, group matching                                  21
permissions file, host matching                                   21
pl (page length) parameter                                        24
plp.conf                                                   4, 16, 21
plp.conf file                                                      3
prefilters                                                     6, 19
prefilters, invocation                                            25
printcap                                                        4, 9
printcap file                                                  3, 13
printcap-include-path plp.conf directive                          14
printcap-path                                                      9
printer aliases                                                   13
printer permissions file                                          21
printer_perms-path                                                 9
priority                                                          22
ps (printer status) parameter                                 15, 23
pw (page width) parameter                                         24
px (pixels X) parameter                                           24
py (pixels Y) parameter                                           24
Q
queue handler                                                     16
R
remote printer                                                     6
rm (remote machine) parameter                                      9
rp (remote printer) parameter                                  9, 19
rt (retries) parameter                                              27
rt (retry) parameter                                                16
rw (read/write) parameter                                           16
rw parameter, with lp-pipes                                         17
S
sb (short banner) parameter                                       17
sc (suppress copies) flag                                         15
sd (spool directory) parameter                                14, 15
sf (suppress form feeds) parameter                                17
sh (suppress header) parameter                                    17
single line banner                                                17
size limitations                                               6, 15
ss (serves) parameter                                               19
st (status) parameter                                               15
start printer requests                                             5
sv (servers) parameter                                              19
T
taintperl                                                         26
tc printcap directive                                             13
tr (trailer) parameter                                              17
ty (stty)  parameter                                                17
U
use-perms-cache plp.conf directive                                21
use-printcap-cache plp.conf directive                             14
X
xc (clear extended bits)                                          16
xs (set extended bits)                                              16
xu (extra permsfile) printcap field                                 15
Z
Z-options, in filter parameters                                   24

_______________________________
1  The   author has seen these appear in several public domain games
programs,  and  has  recollections  of  running   card  decks  which
produced suspiciously similar output.
2  PLP  allows millisecond accuracy in its queue ordering; this  may
not seem that useful for printing, but it may be essential for other
applications, such as video frame-grabbing.
3By  the  way,  I  use  the term -unspool-, as  a  job  may  not  be
-printed-,  per  se  -  ft may simply be appended  to  a  file,  for
example.
4  Actually,  each file in the job can have a different format,  but
the current version of PLP does not support this.
