








           PPLLPP -- TThhee PPuubblliicc LLiinnee PPrriinntteerr SSppoooolleerr
            AA PPoorrttaabbllee UUNN**XX LLiinnee PPrriinntteerr SSppoooolleerr
                  RReelleeaassee 33..44,, AAuugguusstt 11999944


         Prof. Patrick Powell of the Electrical and
Computer Engineering Dept., San Diego State University (papowell@sdsu.edu).







          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 (C) 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 complex legal reasons, PLP is NOT  public
     domain software, but may be copied and/or modified
     as long as the original copyright notification  is
     retained.



December 6, 1994





























           PPLLPP -- TThhee PPuubblliicc LLiinnee PPrriinntteerr SSppoooolleerr
            AA PPoorrttaabbllee UUNN**XX LLiinnee PPrriinntteerr SSppoooolleerr
                  RReelleeaassee 33..44,, AAuugguusstt 11999944


         Prof. Patrick Powell of the Electrical and
Computer Engineering Dept., San Diego State University (papowell@sdsu.edu).




_1_.  _O_v_e_r_v_i_e_w

     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
resort to any of the Berkeley LPD  source,  other  than  for
tables that are used to print big letter banners[1].  Due to
experience with the Berkeley software, some LPD routines and
functionality may be duplicated, but in general  the  imple-
mentation  and  structure  of  the PLP software is radically
different.

     The Public Line Printer Spooler supports:

1).More than one printer per spooling queue.

2).Multiple prioritized spooling queues.

3).Both local and remote printers.

4).Printers attached via serial lines, which can  have  line
   characteristics  such  as baud rate, parity, etc., speci-
   fied.

5).Devices such as an Imagen laser printer which may require
   a special communications protocol for printing.

6).Operation  in  a  shared file system environment (such as
   NFS).

7).Restriction of use by a printer  permissions  data  base.
   In addition to a per-host database, each individual spool
   queue may have a supplementary database.

_________________________
  [1] The  author has seen these appear in several pub-
lic domain games programs,  and  has  recollections  of
running  card decks which produced suspiciously similar
output.




                      December 6, 1994





page 2                                            PLP Manual


     The major components of line  printer  system  are  the
following files and commands in Table 1.1.

+---------------------------+---------+------------------------------------------------+
|Name                       | Type    | Purpose                                        |
+---------------------------+---------+------------------------------------------------+
|/etc/plp.conf              | file    | PLP configuration file                         |
|/etc/printcap              | file    | printer configuration and capability data base |
|/etc/printer_perms         | file    | printer permissions data base                  |
|/var/spool/lpd/log.<host>  | file    | daemon log file                                |
|/var/spool/lpd/lock.<host> | file    | daemon lock                                    |
|/usr/local/bin/lpd         | daemon  | line printer daemon                            |
|/usr/local/bin/lpr         | command | enter a job in a printer queue                 |
|/usr/local/bin/lpq         | command | examine queues                                 |
|/usr/local/bin/lprm        | command | delete jobs from a queue                       |
|/usr/local/bin/lpc         | command | administer printers and spooling queues        |
|printer,tcp                | port    | inet service port on which lpd listens         |
+---------------------------+---------+------------------------------------------------+
               Table 1.1 Major PLP Components


     The  locations  of  most  of  these  components  can be
changed using the _p_l_p_._c_o_n_f configuration file, which usually
lives  in /etc, but whose location is determined at compile-
time. See the manual page _p_l_p_._c_o_n_f_(_5_) for more details.


     The printcap file is  a  master  data  base  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 the _t_e_r_m_c_a_p(5) format.


     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, and sup-
ports shell-like wildcard matching on all its  fields.   The
printer  permissions  file  is  similar  in  purpose  to the
_h_o_s_t_s_._l_p_d file that is used by the BSD lpd, but has signifi-
cantly extended functionality.


     PLP    also   includes   support   for   printcap   and
printer_perms lookups  using  the  NIS  and  Hesiod  network
database  protocols.  See the supplementary document, _C_r_o_s_s_-
_D_o_m_a_i_n _p_r_i_n_t_i_n_g _u_s_i_n_g _H_e_s_i_o_d _w_i_t_h _P_L_P, for more details.


     The    logand    lock    files    have    the     form:
/var/spool/lpd/<file>.<host>,  where  <host>  is  the fully-
qualified form of the host name.  This allows a single spool
directory  to  be  made available via NFS to all the systems
using PLP.  All files in the  spool  directory  are  created
using  the  daemon user and group ID, avoiding problems with



                      December 6, 1994





PLP Manual                                            page 3


NFS systems and root userids.


     The lpd program is a _d_a_e_m_o_n or server program that car-
ries  out  actions  as requested by other programs.  The lpr
program creates print jobs in the appropriate  spool  queue,
and  then  requests  the  lpd  daemon  to perform unspooling
actions.  The lpq program is used to  print  the  status  of
local  and remote spool queues.  The lprm program is used to
remove jobs from spool queues, and the lpc program  is  used
to control spooling and unspooling activities.


     Communication  between  the  lpd daemon and the utility
programs is done using the  Internet  TCP/IP  communications
support provided by most UNIX systems.  Each host has an lpd
daemon which listens on a well known port of the  host,  and
carries out requested activities.


     The  remainder of this document provides details of the
structure and implementation of  the  above  facilities  and
programs.   Section 2 describes the functionality of the lpd
daemon and  the lpr, lpq, lprm, and lpc programs.  Section 3
describes  the  structure  of the spool directory associated
with each spool queue, and the security precautions taken to
ensure  the  integrity  of the the spool directory and print
jobs.  Section 4 is a description of the _p_r_i_n_t_c_a_p data base,
and  how  the  information in the database is used by PLP to
perform spooling operations.  Section 5 is a description  of
the  inter-host file transfer protocol used by PLP.  Section
6 is a description of the unspooling operations carried  out
by  the  _l_p_d  program,  and  how  they are controlled by the
printcap information.  Section 7 details how filter programs
are  invoked  by the spool server processes and how they are
specified in the printcap.  Section 8 describes how PLP  can
be  used  in a networked file system environment.  Section 9
outlines how the _l_p_c program is  used  to  control  spooling
operations.   Section  10  is a discussion of the diagnostic
information supplied by the PLP programs.  Section 11  docu-
ments  ways of testing PLP before a full installation.  Sec-
tion 12 documents some of the features  recently  introduced
to  PLP (since version 3.4.0) that don't really fit anywhere
else in the documentation.

_2_.  _T_h_e _P_L_P _P_r_o_g_r_a_m_s

     The following section outlines  the  operation  of  the
_l_p_d(8) line printer _d_a_e_m_o_n, and the _l_p_r(1), _l_p_q(1), _l_p_r_m(1),
and _l_p_c(1) utility programs.

_2_._1_.  _l_p_d _- _L_i_n_e _P_r_i_n_t_e_r _D_a_m_e_o_n _P_r_o_g_r_a_m

     The _l_p_d(8) program is usually invoked at boot time from



                      December 6, 1994





page 4                                            PLP Manual


the  /etc/rc  or  /etc/rc.local  startup file, and acts as a
server or _d_a_e_m_o_n for coordinating and controlling the spool-
ing queues configured in the printcap file or files.  Figure
2.1 is a section of sh(1) script typically used to start the
_l_p_d daemon.
          # Start up 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  _l_p_d  is  started, it checks to see if there is an
active _l_p_d daemon already running  by  trying  to  lock  the
/var/spool/lpd/lpd.lock.hostname file.  If no daemon is pre-
sent, _l_p_d forks a server process for  each  non-empty  spool
queue  in  the  _p_r_i_n_t_c_a_p(5)  data base, and then listens for
service requests on  specific  Internet  domain  port.   The
Internet  port  number  is  found using the _g_e_t_s_e_r_v_b_y_n_a_m_e(3)
facility.  The _A_d_v_a_n_c_e_d _T_u_t_u_r_i_a_l _o_n _I_n_t_e_r_p_r_o_c_e_s_s  _C_o_m_m_u_n_i_c_a_-
_t_i_o_n_s  distributed with Berkeley UNIX 4.3 BSD (and reprinted
by SUN  Microsystems)  provides  an  excellent  tutorial  on
interprocess  communications.   See   the  manual  pages for
_s_o_c_k_e_t(2) and _s_e_r_v_i_c_e_s(5) for more  information  on  sockets
and service specifications.


     _l_p_d can also be started from _i_n_e_t_d(8) using the -i com-
mand-line option. If it is used in this fashion, it will not
start a sub-server for each non-empty queue at startup.


     When a connection is made to the _l_p_d port by a request-
ing process (usually called a client), _l_p_d  forks  a  server
process to carry out the request and continues to listen for
new requests.  The Table 2.1 shows the  requests  understood
by  _l_p_d.   The  first  byte  of a request is a binary number
specifying the request type, and the following characters up
to  a  terminating  a  new  line  ('\n')  character  are the
request.

+------------------------------------------+-------------------------------------------+
|Request                                   | Interpretation                            |
+------------------------------------------+-------------------------------------------+
|^Aprinter\n                               | start a server for the queue              |
|^Bprinter\n                               | receive and queue a job from another host |
|^Cprinter [users ...] [jobs ...]\n        | return short form of printer queue status |
|^Dprinter [users ...] [jobs ...]\n        | return long form of printer queue status  |
|^Eprinter person [users ...] [jobs ...]\n | remove jobs from a queue                  |
|^Fperson command [printers]\n             | perform lpc control function              |
+------------------------------------------+-------------------------------------------+
            Table 2.1 LPD Request Message Format




                      December 6, 1994





PLP Manual                                            page 5


     After reading the request, the server process reads the
printer  permissions  file  to  determine if the originating
host has permissions to access the specified printer.  Next,
the  _p_r_i_n_t_c_a_p  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 per-
form the requested action.



     In response to a ``start server'' message,  the  server
process  checks  to  see if a server is present, and if not,
starts unspooling activities itself.


     The two forms of status requests cause  the  server  to
check  the spool queue and report on the current activities.


     The file transfer request causes the server and  client
process  to  start  transferring control and data files that
make up a print job.  This activity is described  in  detail
in Section 5.


     The  remove job request causes the server to check that
the user has suitable permissions for the particular  queue,
and will then remove the specified jobs.


     The  control  request  will cause the server to perform
control functions.  This function allows control over spool-
ing  operations to be done using the _l_p_c program on a remote
host.



_2_._1_._1_.  _S_e_c_u_r_i_t_y _I_s_s_u_e_s _I_n _a _N_e_t_w_o_r_k_e_d _E_n_v_i_r_o_n_m_e_n_t

     The permissions and restriction checks performed by _l_p_d
are  based on the assumption that the client host machine is
well known by the network-layer software, and that the  pro-
cess originating a request authenticates the user requesting
the service.  The port from which the client request  origi-
nates  is  restricted to a range which is reserved for users
with root permissions (in a UNIX environment, at least).


     In an environment where users can implement  their  own
support for TCP/IP facilities, these security checks may not
be sufficient.  In fact, given access to the network  commu-
nications  hardware,  it  is possible to forge messages that
appear to be originating from any valid site. The problem of
authentication of requests is currently open.



                      December 6, 1994





page 6                                            PLP Manual


_2_._1_._2_.  _S_p_o_o_l _Q_u_e_u_e _A_c_c_e_s_s _a_n_d _P_e_r_m_i_s_s_i_o_n_s

     As  discussed  in the previous section, there are prob-
lems in controlling access  to  PLP  by  clients  on  remote
hosts.  As a preliminary step towards a more general authen-
tication procedure, PLP uses a _p_r_i_n_t_e_r___p_e_r_m_s or printer per-
missions  file  containing  a list of machines, users, spool
queues and associated privileges.  Authentication of  remote
hosts  is  based  on the network connection information pro-
vided by the _g_e_t_p_e_e_r_n_a_m_e(3N) networking function.

+------------------------------------------------------------------------------------------------------------+
|# -- Line printer permissions                                                                               |
|# host               name    group     queue    Ops   Pr   Max    Done   #Comment                           |
|~*.umn.edu           *       *         *        C     A    0      0      # no non-local sites               |
|central.*.umn.edu    root    *         *        C     A    0      0      # root@central can do anything     |
|*.umn.edu            root    *         lp       C     A    0      100    # root@* can access lp, priority A |
|server.adm.umn.edu   admin   *         lp       R     C    1000   200    # admin@server, lp priority C      |
|!*                   CS*     *         laser*   R     Z    *      *      # CS accounts, no laserprinters    |
|!*                   *       firstyr   laser*   R     Z    *      *      # firstyr group, no laserprinters  |
|*.umn.edu            *       *         lp       R     Z    *      *      # default is priority Z            |
+------------------------------------------------------------------------------------------------------------+
         Table 2.2 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  pri-
ority  (A-Z),  and a maximum and current page counts associ-
ated with use of a spool queue.  Blank lines and lines  that
start  with  #  (comment) are ignored.  Fields are separated
with one or more spaces or tabs.  There is a simple wildcard
match  facility  similar  to  the  UNIX  shell metacharacter
match.  The * character will match 0 or more  characters  in
the  string,  and  the  ?  will match exactly one character.
Lines that start with a  !  indicate  that  permissions  are
denied for queries that would otherwise match.

     Given  a  host, user, and spool queue, the printer per-
missions 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 group field is matched based upon the  login  group.  If
the  user  is  listed  in  the groups(5) entry for the named
group, it is also a match.  If an tilde _(_~_) is first charac-
ter on the line, the fields are checked for a match.  If the
match fails, then permissions are  refused.   If  the  match
succeeds,  then further searching will be done.  This facil-
ity allows only sites with suitable  path  names,  etc.,  to
have  access  to  a spool queue.  If an exclamation mark _(_!_)
is first character on the line, all permissions are refused;
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 (starting with !) precede



                      December 6, 1994





PLP Manual                                            page 7


any matching entries.



     For example, the printer permissions file in Table  2.1
allows  root  on host central (i.e.- root@central) to access
all queues, root on any machine to access the lp queue,  and
admin  on  server  to access the lp queue.  Userids starting
with CS are denied permission  to  use  spool  queues  whose
names  start  with  laser.  Note that the host name used for
checking is the full name returned by the  _g_e_t_h_o_s_t_b_y_n_a_m_e(3N)
function.

     Spool  queue operations, spooling priorities, and other
information are set by the matching  line.   The  _O_p_s  field
controls  the  allowed operations; a C value stands for Con-
trol, and means that the user has permissions to use the LPC
and LPRM programs to manage a queue as well as spool jobs to
the queue.  An M value stands for Move, and means  that  the
user has permissions to use the LPC _m_o_v_e command to move one
of his/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 his  own  jobs.   Control
functions  can  be  exercised  from  remote  hosts using the
_r_e_m_o_t_e command of the _l_p_c 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 and other purposes.  They are checked when a  job
is  queued by _l_p_r and when the job is unqueued for printing.
If the current maximum page count is exceeded by  the  user,
the job will be refused.


     The  server process checks the printer permissions file
to determine if a requesting host is  allowed  access  to  a
particular  queue;  if  so,  it  will  perform the requested
actions as detailed in the following sections.

_2_._1_._3_.  _U_n_s_p_o_o_l_e_r _P_r_o_c_e_s_s_e_s_, _o_r _Q_u_e_u_e _S_e_r_v_e_r_s

     During initialization and in response to _s_t_a_r_t  _p_r_i_n_t_e_r
requests, _l_p_d forks an unspooler or server process that pro-
cesses jobs in the spool queue.   Jobs  are  placed  in  the
spool queue by _l_p_r or are transferred from a remote site and
removed by the server process.  Each spool queue has a  _l_o_c_k
file which is used to control spooling and unspooling activ-
ities.  The lock file _o_w_n_e_r, _g_r_o_u_p and  _e_x_e_c_u_t_e  permissions
are  used to control spooling and unspooling actions; if the



                      December 6, 1994





page 8                                            PLP Manual


owner execute permission is set then unspooling is  disabled
and  if the group execute permission is set then spooling is
disabled.  The _l_p_c utility is designed as  a  front-end  for
manipulating  these  attributes.   If unspooling is enabled,
the server tries to lock the _l_o_c_k file;  if  it  cannot   be
locked,  then  another server is active and the process will
exit.

     Once the server has gained control  of  the  queue,  it
finds the entries in the queue, sort them in order of prior-
ity and time, and then unspools them according to specifica-
tions  in  the  _p_r_i_n_t_c_a_p  file.   When  a job unspooled, the
server will lock the job's control file in order to  prevent
other  processes  from  manipulating  the job.  If it cannot
lock the control file,  then  the  job  is  currently  being
manipulated  by another PLP program and the server will pro-
cess another job in the queue.

_2_._1_._4_.  _L_o_c_a_l _P_r_i_n_t_e_r _Q_u_e_u_e_s

     If the spool queue is for  a  local  printer  then  the
server  process  will  print the job according to specifica-
tions in the _p_r_i_n_t_c_a_p file.  The printcap file  specify  the
physcial  printer device, any characteristics of the connec-
tion between the lpd and the printer device which need to be
set  (such  as  serial line attributes), and any _f_i_l_t_e_r pro-
grams  used to print the job.


_2_._1_._5_.  _R_e_m_o_t_e _P_r_i_n_t_e_r _Q_u_e_u_e_s

     If the spool queue is for a printer attached to another
host,  the server attempts to connect to the remote host and
transfer the jobs in the spool queue to the remote host.  If
the  file  system  used to store the job is flagged as being
shared by the local host and the remote host, then it is not
neccessary  to  transfer files but only to inform the remote
host that there are jobs in the spool queue.

_2_._1_._6_.  _M_u_l_t_i_p_l_e _P_r_i_n_t_e_r_s _F_o_r _a _S_p_o_o_l _Q_u_e_u_e

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

_2_._2_.  _l_p_r _- _J_o_b _S_u_b_m_i_s_s_i_o_n _P_r_o_g_r_a_m

     The _l_p_r(1) program is used to place a print  job  in  a



                      December 6, 1994





PLP Manual                                            page 9


spool  queue and to then send a _s_t_a_r_t _p_r_i_n_t_e_r message to the
_l_p_d process.  The _l_p_d process is then responsible for print-
ing the job or forwarding it to the correct destination.

     The _l_p_r program uses the printcap database to determine
the actions  required  for  spooling  a  job.   Spooling  is
enabled  by  the  state of the spool queue lock file permis-
sions; if the owner permission is set, then spooling is dis-
abled.

     Permission  to use a spool queue is determined by using
the printer permissions file.  _L_p_r determines the user  name
and  searches the printer permission file to see if the user
can submit jobs to the spool queue (has R or C  privileges).
If  the user can use the spool queue, _l_p_r will then copy the
users files to the spool queue.  _l_p_r can also make  symbolic
links to the original files rather than copying them.  After
copying a file, _l_p_r can be requested to remove the file.

     Before a job is placed in the spool queue,  it  may  be
desirable to do some local processing or _p_r_e_f_i_l_t_e_r_i_n_g of the
files.  For example, running a formatter such as _p_r,  trans-
lating  a typesetter format file into a different form, etc,
can be done by lpr.  These actions are  controlled  by  pre-
filter  information  specified in the printcap entry for the
spool queue.

     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.
The  prefilter facility is usually used when files must have
some further form of processing carried out, but the  remote
site  where  they  are to be printed cannot perform the pro-
cessing.

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

_2_._3_.  _l_p_q _- _S_p_o_o_l _Q_u_e_u_e _S_t_a_t_u_s _D_i_s_p_l_a_y

     The  _l_p_q(1) program displays the status and contents of
selected spool queues.  _L_p_q 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 for-
mat of _l_p_q is extraordinarily verbose, and attempts to  give
a  full  picture  of the total state of the line printer and
its associated queues, servers, and other information.   The
following  is  an example of the output produced by _l_p_q when
displaying the status of a remote spool queue.





                      December 6, 1994





page 10                                           PLP Manual



        Printer 'diablo' (julius.cs.umn.edu):
          processing, active job started Wed May 11 15:20:54 1988, attempt 1
          Rank Owner       Pr Job Host        Files                Size
        active root        A  15  julius      /tmp/test5           132
           2nd root        X  14  julius      /tmp/test2           15
        Remote printer 'lp2' (umn-cs.cs.umn.edu):
        Warning: no server present
          work done at Wed May 11 15:16:43 1988
          Rank Owner       Pr Job Host        Files                Size
           1st root        X  13  julius      /tmp/test3           30
           2nd root        X  14  julius      /tmp/test4           9


     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,
which  is transferring a file to the remote site.  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.

        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_.  _l_p_r_m _- _r_e_m_o_v_e _j_o_b_s _f_r_o_m _a _q_u_e_u_e

     The _l_p_r_m(1) command deletes jobs from a spooling queue.
If  necessary,  _l_p_r_m will kill(2) off a server process which
is working on the job.  After removing any  files,  it  will
then  restart the queue by sending a request to the lpd dae-
mon.  _L_p_r_m 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,  he  can  remove
jobs  that  he has submitted.  The root, or superuser, for a
host can remove any job submitted from that particular host.
Finally,  the  printer  permission  file will allow any user
with control permissions for a spool queue to remove any job
from the spool queue.





                      December 6, 1994





PLP Manual                                           page 11


_2_._5_.  _l_p_c _- _l_i_n_e _p_r_i_n_t_e_r _c_o_n_t_r_o_l _p_r_o_g_r_a_m

     The  _l_p_c(1)  program is used to monitor and control the
operation of the Line Printer Software 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
printer permissions file has the appropriate  entries.   The
commands accepted by the _l_p_c program are detailed in section
9.2.  Unless specified as unpriviledged, they  can  only  be
used  by  a  user with control permissions for the specified
spool queue, and on the current or local host machine.   _A_l_l
or individual queues can be operated on.

_3_.  _S_p_o_o_l _D_i_r_e_c_t_o_r_i_e_s_, _P_r_o_g_r_a_m_s_, _a_n_d _P_e_r_m_i_s_s_i_o_n_s

     Each  spool  queue  has a spool directory that contains
the control and data files associated with a job.  The  per-
missions  and  ownerships of spool directories and PLP soft-
ware are intended to allow only PLP programs to read, write,
or  remove jobs from the spool directory.  The strategy used
to protect spooling information is as follows:

1). Each spool queue directory is owned by user  _d_a_e_m_o_n  and
    group _d_a_e_m_o_n.  The spool queue directory permissions are
    0755, i.e.- user (daemon) rwx, group  (daemon)  rx,  and
    other  rx. These could be restricted to 0600, user (dae-
    mon) rw only, as PLP programs run SUID _r_o_o_t.

2). All PLP programs which modify or read the entries in the
    spool queue directories run SUID _r_o_o_t.  The SUID _r_o_o_t is
    needed on most UNIX implementations in order  to  change
    the file ownership and group information.

3). Control  and data files in the spooling directories have
    owner _d_a_e_m_o_n and group _d_a_e_m_o_n, and are mode 0600.   This
    ensures control and data files are not readable or modi-
    fiable by an ordinary user and that no ordinary user can
    remove files except through _l_p_r_m.

4). Each spool queue has a _l_o_c_k file which controls queueing
    and printing.  If the _l_o_c_k has _o_w_n_e_r _e_x_e_c_u_t_e  permission
    set then unspooling is disabled; if it has _g_r_o_u_p _e_x_e_c_u_t_e
    permissions set then spooling is  disabled;  if  it  has
    _o_t_h_e_r  _e_x_e_c_u_t_e  permissions  set  then  the  spool queue
    should  be  reordered  for  unspooling  purposes.  These
    attributes are controlled using the _l_p_c command.

5). Prevention of multiple instances of a spool queue server
    is done by using the  _f_c_n_t_l(2),  _l_o_c_k_f(3),  or  _f_l_o_c_k(2)
    facility.   When  a  server starts, it will try and lock
    the _l_o_c_k file using one of the above locking mechanisms;



                      December 6, 1994





page 12                                           PLP Manual


    if the lock fails then another server is active.

6). The active server process records its _p_r_o_c_e_s_s _i_d and the
    name of the control file being  processed  in  the  _l_o_c_k
    file.   This  information  is  used by _l_p_q to report the
    queue activity.

7). Before processing a job, the server  process  will  lock
    the job's control file.  This prevents multiple PLP pro-
    grams such as _l_p_r_m and _l_p_d from operating  on  the  same
    job simultaneously.

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

9). Each spool queue has a _s_t_a_t_u_s  file  which  is  used  to
    record  the current status of the server process and any
    LP-pipe processes.  This information is displayed by _l_p_q
    and _l_p_c.

10).A server process is setuid _r_o_o_t and its process group is
    its process id.  Any subprocesses that it forks will  be
    in  the  same  process  group.   The  _l_p_r_m  program uses
    _k_i_l_l_p_g(2) or _k_i_l_l(2) to signal an active server process.
    This  will effect all subprocesses as well as the origi-
    nal server process.

_4_.  _P_r_i_n_t_c_a_p _a_n_d _P_L_P _O_p_e_r_a_t_i_o_n_s

     The entries in the printcap file or files are  used  to
define  and  control  the actions of PLP.  Each host machine
must have at least one printcap file that is used to specify
the  spool queues that are available on the host, and it (or
they) must be readable by all users to be used by PLP.  Per-
missions  to  use a particular spool queue are determined by
the printer permissions file.  The  following  section  dis-
cusses  the  structure of the printcap file, and the purpose
of entries therein.

_4_._1_.  _P_r_i_n_t_c_a_p _F_o_r_m_a_t

     The printcap file format is analogous to  that  of  the
_t_e_r_m_c_a_p(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 4.1 is an example
of a typical printcap entry.

1).Blank lines and lines which start with a # are treated as
   comments and can be used to separate entries.

2).Each  entry  starts  in column 1, and is continued across
   multiple lines  by  escaping  the  end  of  line  with  a



                      December 6, 1994





PLP Manual                                           page 13


          #   Default line printer is first in printcap entry
          #   Clunker Printer in Lind 23
          clunker_lind23|clunker:\
              :lp=/dev/lp:\
              :st=\t\r\015:\
              :mx#20:\
              :wt:fl@:
             Figure 4.1  Sample Printcap Entry
   backslash  (\\).   Fields  of  the  entry are separated by
   colons (::).

3).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 (||).

4).Parameter fields start with a two letter parameter  name,
   followed by a flag indicating the parameter type.  Param-
   eters can be strings, integers, or flags.  String parame-
   ters  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.

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

6).See the _p_r_i_n_t_c_a_p(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  han-
dled.

PLP  can also include files, in the same way as a preproces-
sor such as the C preprocessor; use the _i_n_c_l_u_d_e directive to
do this, as follows:
             include /share/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.conffile; _p_l_p_._c_o_n_f(5) manual page for more details.

     PLP the printcap  format  supports  the  _t_c  directive,
which has the same effect as it does in the termcap database
format. This allows you to inherit the fields  from  another
printcap entry.

     PLP  searches  the  printcap files for a printcap entry
with a matching printer name or alias. A useful  enhancement
is  that  PLP  will  first  search  for  the  printer  name,



                      December 6, 1994





page 14                                           PLP Manual


qualified by the non-fully-qualified version  of  the  host-
name,   (ie.    _p_r_i_n_t_e_r_n_a_m_e_/_h_o_s_t_n_a_m_e;   for  example,  _h_p_4_m_-
_p_s_/_c_l_a_s_s).  This allows you to use a  single  printcap  file
for  an  entire  network of machines, with one special entry
for the printer server, and  a  general  _r_m  entry  for  the
client machines. See figure 4.2.

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

          hp4m-ps/class:cm=HP LaserJet 4Mplus, postscript:\
              :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:
Figure 4.2  Client and Server Remote Printer Printcap Entries

By  convention, if a user does not specify a printer, either
by using a command line option or  by  setting  the  _P_R_I_N_T_E_R
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.

_4_._2_.  _S_p_o_o_l _Q_u_e_u_e _D_i_r_e_c_t_o_r_y

     The  _s_d (spool directory) field specifies the path name
of the directory which will  hold  spool  queue  entries  or
jobs.   The  _s_d  parameter  _m_u_s_t 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 _s_s (multiple server) queues.

     Figure  4.3  is  a  typical printcap entry for a remote
printer spool queue, whose spool directory is  specified  as
/var/spool/lpd/lind33_decwriter.
          # Decwriter III in Lind 33
          # Modified 11 Feb. 1988 Patrick Powell - added fx=n for ditroff
          # queue printer permissions file
          # maximum job size 2000K bytes, no copies
          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 4.3  Remote Printer Printcap Entry

_4_._3_.  _J_o_b _S_u_b_m_i_s_s_i_o_n _C_o_n_t_r_o_l_s

     The  following  fields  are used to control job submis-
sion.





                      December 6, 1994





PLP Manual                                           page 15


_4_._3_._1_.  _J_o_b _F_o_r_m_a_t_s

     Each job in a spool queue  has  an  associated  format,
which  is  represented by a lower case letter[2].  There are
several _l_p_r options such as _-_n_, _-_d_, etc. which can  be  used
to  specify  a limited set of formats, or the _-_F_x option can
be used to specify any format.  For example, the _-_F_n options
specifies printing using the _n format, as below.
     ditroff -Tdumb -ms myfile | lpr -Fn -Premote

     The format supported by a spool queue can be restricted
by the _f_x printcap field, which specifies the  formats  sup-
ported by the spool queue.  In Figure 4.3, the _f_x_=_i_l_p_n field
restricts formats to i, l, p, and n.  Some  formats  require
that  files  be  printable  (i.e.- contain characters in the
ASCII characters set, or other restrictions).   By  default,
only  the  f  and p formats are checked by _l_p_r for printable
files.  The _x_t field is used to specify  additional  formats
to be checked for printable files.

_4_._3_._2_.  _P_e_r_m_i_s_s_i_o_n_s _F_i_l_e_s

     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 addi-
tion, the _x_u (check user) printcap field is used to  specify
an  additional  printer permission file which is checked for
jobs in the spool queue.  For example,  the  _x_u_=_p_e_r_m_s  field
causes  the  perms file in the spool directory to be checked
by _l_p_r when  the job is submitted.  Similarly, the  unspool-
ing server process will also check this file when the job is
finally printed.

_4_._3_._3_.  _P_r_e_f_i_l_t_e_r_s

     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  XXe=filtername  or
XXe=filtername,y  where  X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 _l_p_r _-_p
option specifies filtering with the _p_r program; _l_p_r  invokes
the  program  specified  by  the  pprr==filtername  (default is
/bin/pr).

_4_._3_._4_.  _J_o_b _S_i_z_e _a_n_d _N_u_m_b_e_r _o_f _C_o_p_i_e_s

     The _m_x (maximum size) field is used to specify a  maxi-
mum  file  size  (in  1 Kbyte blocks) that can be spooled by
_________________________
  [2] Actually, each file in the job can have a differ-
ent format, but the current version  of  _l_p_r  does  not
support this.




                      December 6, 1994





page 16                                           PLP Manual


_l_p_r_.  Jobs whose total size (including  duplicates)  exceeds
this  limit are not spooled.  For example, the _m_x_#_2_0_0_0 entry
restricts jobs to a maximum of 2000 Kbytes.  Also, if the _m_i
field  has a value greater than zero, it specifies the mini-
mum 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 refused.

     The _m_c (maximum copies)  value  specifies  the  maximum
number  of  copies allowed and the _s_c (suppress copies) flag
which suppresses multiple copies.

     Using the _l_i(file size limit) field, it is possible  to
set  up  multiple queues 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. See
section 12 for more details.


_4_._4_.  _R_e_m_o_t_e _P_r_i_n_t_e_r _S_p_o_o_l _Q_u_e_u_e_s

     Remote  spool  queues specify the remote host using the
_r_m field and the remote printer using  the  _r_p  field.   The
remote  host  addressing  information  is obtained using the
_g_e_t_h_o_s_t_b_y_n_a_m_e(3N) facility.  The remote printer must  appear
in  the  remote  host's  printcap data base. Unlike most lpd
implementations, PLP supports the use of  an  _i_f  filter  on
files  being sent to a remote printer; a filter is run inde-
pendently on each file being transmitted, in the same way as
an  _i_f  filter  for a local printer.  See section 7 for more
details on the use of filters.  Also, multiple remote print-
ers  are  supported,  where  one  remote printer can feed to
another remote printer, _a_d _i_n_f_i_n_i_t_u_m.

     Figure 4.3 is an example of an entry for a remote spool
queue  that  will  be  sent  to  host umn-cs.cs.umn.edu, and
printed on the lind33_decwriter printer.


Remote Jobs Failing on non-PLP Hosts
   If PLP is sending jobs to a remote host that is not  run-
   ning  PLP,  jobs  may fail. This often happens with Sun's
   default lpd. In this case,  turn  on  the  _b_k  parameter,
   which  will  re-order  the  control file's fields into an
   order which these lpd implementations will accept.

_4_._5_.  _L_o_c_a_l _P_r_i_n_t_e_r _Q_u_e_u_e_s

     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 _q_u_e_u_e _h_a_n_d_l_e_r process.  The
latter method is discussed later in this section.



                      December 6, 1994





PLP Manual                                           page 17


     Associated with each local queue is an  output  device.
These  can  be  categorized  as  serial  line, a specialized
device with a non-serial interface, or a pipe.  If a  device
is  attached  to  a serial line, the printcap can be used to
specify how the serial line is to be conditioned in order to
communicate with the printer.  Figure 4.3 is a sample print-
cap entry for a DecWriter III printer connected over a  1200
baud serial line.
          # Local Printer Entry
          # Decwriter III in Lind 33
          # Modified 11 Feb. 1988 Patrick Powell - added fx=n for ditroff, max 2 retries
          lind33_decwriter|clunker|Decwriter Model 3:\
              :fx=ilpn:\
              :sd=/var/spool/lpd/lind33_decwriter:\
              :xu=/usr/adm/perms/lind33_decwriter:\
              :rt=2:\
              :ne=/usr/local/lib/ddumb:\
              :lp=/dev/ttyh8:rw:\
              :br#1200:fs#06320:ty=-nl odd even -tabs tandem new:\
              :lf=error:
      Figure 4.3 Printcap Entry for Serial Line Device

_4_._5_._1_.  _O_u_t_p_u_t _D_e_v_i_c_e _P_a_t_h_n_a_m_e

     The  _l_p  (line printer) parameter specifies a path name
of the device, or an LP-pipe command, that is to  be  opened
and  output  sent  to.   See  section  4.5.4.  The device is
opened for writing only (default), or reading and writing if
the  _r_w  flag  is   present.   Note that there is no default
value for the _l_p field.  If there is no physical device cor-
responding  to the printer, then lp=/dev/null should be used
to specify a null device.

_4_._5_._2_.  _R_e_t_r_y _L_i_m_i_t_s

     The server will attempt to unspool and print a job  for
a limited number of times.  The number of attempts is set by
the _r_t (retry) parameter; the default value is 3, and  a  -1
value specifies unlimited retries.

_4_._5_._3_.  _S_e_r_i_a_l _L_i_n_e _C_h_a_r_a_c_t_e_r_i_s_t_i_c_s

     Printers connected via a serial communication line must
have the proper baud rate and line characteristics set.

Setting Bit (Baud) Rates
   The _b_r parameter sets the bit (baud)  rate  for  the  tty
   line.   For  example,  300 means 300 BPI, 9600 means 9600
   BPI.

Setting Line Characteristics
   The _f_s (set bits) and _f_c (clear bits) parameter  is  used
   to  set the serial line characteristics with the TIOCSETP
   _i_o_c_t_l(2) operation.  The _f_s and _f_c set and clear bits  in



                      December 6, 1994





page 18                                           PLP Manual


   the  line  control  status  word returned by the TIOGSETP
   ioctl operation, which is then restored  with  the  ioctl
   TIOCSETP.   In  the above example, _f_s sets CRMOD, no par-
   ity, and XTABS (see _t_t_y(4) for details).  The _x_s  and  _x_c
   are  be  used to set and clear local control  information
   using the TIOCCLGET and TIOCCLSET ioctl calls.

Alternate Method
   In case you find the _f_s, _f_c, etc., method of setting line
   characteristics  embarassingly  user-hostile, you can use
   the _t_y (stty) parameter, which  uses  (almost)  the  same
   keywords  and  options as the _s_t_t_y(1) command.  For exam-
   ple, ty=nl -odd -even -tabs can be used  instead  of  the
   above _f_s values.  If you need tandem line control you may
   have to open the output device for  reading  and  writing
   using  the  _r_w  field;  this appears to be implementation
   dependent.  Use of the _t_y parameter is endorsed, as it is
   both  more  portable  and  more  comprehensible  than the
   rather opaque _f_s, _f_c, _x_s, and  _x_c  parameters.   See  the
   _p_r_i_n_t_c_a_p(5) manual page for details of which _s_t_t_y options
   _l_p_d recognises. The _s_t_t_y(1) manual page will  provide  an
   explanation of the different options.


_4_._5_._4_.  _L_P _P_i_p_e_s

     To  connect  to  a  printer using anything other than a
serial line, the _l_p parameter must contain an entry  of  the
following  style: _| _l_p_-_p_i_p_e_-_c_m_d _[ _a_r_g_s _] If this is found in
the printcap, the lpd will attempt to run the  command,  and
use it as the output device.

     The _r_w entry is not used with LP-pipes.

_4_._6_.  _J_o_b_, _L_o_g_, _L_o_c_k_, _a_n_d _S_t_a_t_u_s _F_i_l_e_s

     The  pathnames  for  all  files associated with a spool
queue are relative to the spool queue directory or are abso-
lute  paths.   The  following  sections  discuss the various
files that are used for logging and status reporting.

_4_._6_._1_.  _J_o_b _F_i_l_e_s

     A job consists of a control file  and  a  set  of  data
files.   Lines in the control file provide information about
the user, the originating hosts, and the names of  the  data
files,  and the data file unspooling formats.  A job control
file name has the form:
     _c_f [Priority - A-Z] [Job Number - 000-999] [Host Name]
     Example:   cfA002attila.cs.umn.edu

     The first two letters identify the file  as  a  control
file,  the next letter is the job's priority level, the next
3 digits are the job number, and the trailing characters are



                      December 6, 1994





PLP Manual                                           page 19


the host name.

     The  priority  level  is  set by the LPR process at the
time that the job is submitted; the _l_p_c program can be  used
to  upgrade  a  job's  priority.   The  sequence  number  is
obtained from a sequence file, which is locked when  in  use
by  _l_p_r  in  order  to  avoid duplicate sequence file names.
Each host has a unique sequence file, and the combination of
host  and sequence number should be unique.  This is true as
long as there are less  than  1000  jobs  outstanding  in  a
queue.

     The  data  files associated with a job have files names
with a similar form, as follows:
     _d_f _[_S_e_q_u_e_n_c_e_] _[_J_o_bNumber] _[_H_o_s_t_]
     Example:  dfA002attila, dfB002attila

     The PLP software checks to ensure that control file and
data file names have the same corresponding form.

_4_._6_._2_.  _C_o_n_t_r_o_l _F_i_l_e

     A  control  file contains the information neccessary to
print a job.  Figure 4.4 is a typical  control  file  for  a
job.
          Hattila.cs.umn.edu
          LPatrick Powell,L136
          Ppapowell
          N(stdin)
          J(stdin)
          CZ
          fdfA001attila
          UdfA001attila
            Figure 4.4. Job Control File Example

     The  first  character  on each line is a flag character
used to decode the remainder of the line.  Upper case  flags
provide   information  or  pass  options  for  the  printing
actions.  Lower  case characters are format  indicators  for
specified data files.  Note that there is a maximum limit on
the size of each line of a control file.   Table  4.1  lists
the various control flags that are used in the control file.















                      December 6, 1994





page 20                                           PLP Manual



  +-----+---------------+---------------------------------+
  |Flag | Parameter     | Meaning                         |
  +-----+---------------+---------------------------------+
  |C    | class name    | banner page                     |
  |H    | host name     | originating host                |
  |I    | indent        | amount to indent output         |
  |J    | job name      | banner page                     |
  |L    | user name     | name to print on banner         |
  |M    | mail          | mail to user when done printing |
  |N    | name          | name of file in job             |
  |P    | Person        | user's login name               |
  |S    | flag          | no header request               |
  |R    | account       | accounting information          |
  |U    | file name     | remove file after we print it   |
  |W    | width         | page width for PR               |
  |X    | header        | header title for PR             |
  |Z    | extra options | options for filters from lpr    |
  |f    | file name     | ordinary file                   |
  |l    | file name     | text file with control chars    |
  |p    | file name     | text file to print with pr(1)   |
  |t    | file name     | troff(1) file                   |
  |n    | file name     | ditroff(1) file                 |
  |d    | file name     | dvi file                        |
  |g    | file name     | plot(1G) file                   |
  |v    | file name     | plain raster file               |
  |c    | file name     | cifplot file                    |
  +-----+---------------+---------------------------------+
               Table 4.1. Control File Flags

_4_._6_._3_.  _L_o_g _F_i_l_e

     The spool queue server process writes error and  infor-
mational messages to the server log file, which is specified
by the _l_f field; the default log file is the file _l_o_g in the
spool  directory.   If  the log file does not exist, then no
logging is done.  Serious error messages (those with a  pri-
ority  higher  than notice) are written both to the log file
and logged using the _s_y_s_l_o_g(3) facility if it is  available,
or to /dev/console if it is not.

     If  the  error  in question results in the failure of a
job to print, mail will be sent to the user (and to the dae-
mon user), detailing the error that caused this failure.  It
is possible to change the address that error mail is sent to
(and  ostensibly  from), using the plp.conf directive, _m_a_i_l_-
_f_r_o_m_-_a_d_d_r_e_s_s.

_4_._6_._4_.  _L_o_c_k _F_i_l_e

     The spool queue lock file is used to  control  spooling
and unspooling  operations.  The lock file name is specified
using the _l_o (lock file) field, and the  default  lock  file
name is _l_o_c_k.



                      December 6, 1994





PLP Manual                                           page 21


_4_._6_._5_.  _S_t_a_t_u_s _F_i_l_e_s

     The  server  status  file (default file is _s_t_a_t_u_s) con-
tains status information reflecting the  operations  of  the
unspooling  server  processes.  The _s_t (status) field can be
used to specify an explicity name for the status  file.   An
additional  printer status file can be specified with the _p_s
field.  This file can be used by filter programs that gener-
ate  additional  status information that should be available
for display.

_4_._7_.  _M_u_l_t_i_p_l_e _S_e_r_v_e_r_s

     If a spool queue has multiple printers or servers,  the
server  names  are  specified by the _s_v (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 _s_s (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 _s_d  field  of
the  spool queue that it serves.  Note that this name corre-
sponds to the name of the queue,  not  the  spool  directory
pathname.
          # Multiple servers
          fast:\
              :sd=/var/spool/lpd/fast:\
              :sv=fast.a,fast.b:
          fast.a:\
              :ss=fast:\
              :lo=lp1:lf=fast.a:st=status.a:lp=/dev/ttya:
          fast.b:\
              :ss=fast:\
              :lo=lp2:lf=fast.b:st=status.b:lp=/dev/ttyb:
         Figure 4.5  Multiple Server Printcap Entry

     In  the example in Figure 4.5, the lp1 and lp2 printers
are used to serve the fast spool queue.  Note that  each  of
them  explicitly  specify  the  name  of  their lock and log
files; as they will use the same queue directory  the  names
of  the  lock,  log,  and status files must be different. We
suggest you use ``.a'', ``.b'', and so on  as  a  suffix  to
distinguish  the  printers  and their control files; this is
supported by the _l_i_m_i_t_s functionality as a way  of  imposing
different  limits on different printers. See the file ``PLP-
with-limits'' in the doc subdirectory  of  the  distribution
for more details.


_4_._8_.  _M_u_l_t_i_p_l_e _Q_u_e_u_e_s _f_o_r _a _S_i_n_g_l_e _O_u_t_p_u_t _D_e_v_i_c_e

     You  will  probably  want  to use multiple queues for a
single output device, such  as  one  postscript  queue,  one
plain-text  queue,  and one plain-text with formatting. What
you should do here is set up  all  these  queues,  with  the



                      December 6, 1994





page 22                                           PLP Manual


lowest common denominator being the local-printer queue, and
all the other queues feeding into this one as remote-printer
queues.  The  queue  that  they feed into is called a _f_u_n_n_e_l
_q_u_e_u_e.

     For example, let's say you have an HP Laserjet  4M+  in
PostScript mode, set up as the queue _h_p_4_m_-_p_s, and you want a
plain-text queue ( _h_p_4_m_-_m_p) and a  plain-text-2-up  queue  (
_h_p_4_m_-_m_p_-_2_u_p) that print to the same device.  The _h_p_4_m_-_m_p and
_h_p_4_m_-_m_p_-_2_u_p queues should forward their jobs directly to the
_h_p_4_m_-_p_s  funnel  queue  after  filtering them.  The printcap
entries in figure 4.6 illustrate how to do this.
          # Multiple queues for one device
          #
          hp4m-ps:\
              :cm=HP LaserJet 4Mplus, postscript:\
              :sd=/var/spool/lpd/hp4m-ps:\
              :lf=/share/logs/lpd/hp4m/ps:\
              :lp=9100@exception.iona.ie:rs:mx#0:

          hp4m-mp|hp4m-mp-1up:\
              :cm=HP LaserJet 4Mplus, with "mp" filter:\
              :sd=/var/spool/lpd/hp4m-mp:lf=/share/logs/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:lf=/share/logs/lpd/hp4m/mp-2up:\
              :if=/usr/local/etc/printer/run-mp-2up:\
              :rm=localhost:rp=hp4m-ps:
         Figure 4.6  Multiple Queue Printcap Entry


     Using a funnel queue will avoid the following difficul-
ties:

_4_._8_._1_.  _D_e_v_i_c_e _L_o_c_k_i_n_g _D_i_f_f_i_c_u_l_t_i_e_s

     Occasionally,  you  may  run  into problems with device
locking, where by some bug in your operating  system's  ker-
nel,  two queues could output jobs (or parts of jobs) to the
same device at once. This should not  happen,  but  Murphy's
Law dictates that it may; using a funnel queue would prevent
this.

_4_._8_._2_.  _Q_u_e_u_e_s _H_o_g_g_i_n_g _t_h_e _O_u_t_p_u_t _D_e_v_i_c_e

     If two queues, _q_a and _q_b share the same output  device,
the  following  could happen.  User _A_n_n sends a large job to
_q_a, and user _B_i_l_l sends a job to _q_b shortly after  _q_a,  com-
mences  printing  Ann's  job.  Bill's  job should be printed
next, but if Ann submits another job to _q_a before the  first
job  is  finished,  _q_a will move straight on to Ann's second



                      December 6, 1994





PLP Manual                                           page 23


job, without allowing _q_b to print Bill's  job,  even  though
Bill's  job  was  lpr'ed  first.  This  entirely defeats the
queueing functionality.

_4_._8_._3_.  _F_o_r_w_a_r_d_i_n_g _J_o_b_s _t_o _S_i_n_g_l_e_-_T_h_r_e_a_d_e_d _L_P_D_s

     Recently, some LPD implementations have appeared,  such
as  the  HP  JetDirect embedded LPD, that 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, the connection is refused, and PLP
must sleep and retry.  Unfortunately, If two queues are try-
ing to send jobs to the same printer at once while a job  is
printing,  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 printing job finishes. Again, this entirely defeats  the
queueing functionality.







































                      December 6, 1994





page 24                                           PLP Manual


_5_.  _R_e_m_o_t_e _S_p_o_o_l _Q_u_e_u_e_s _(_t_h_e _L_P_D _P_r_o_t_o_c_o_l_)

     Entries  in  a remote spool queue are transfered to the
remote host by a server process forked by  the  _l_p_d  daemon.
The  server  process  checks the spool queue for entries and
then initiates communication with the remote  host  and  the
line  printer  daemon on the remote end.  The following sec-
tion discusses the protocol used to transfer  files  to  the
remote hosts.

_5_._1_.  _E_s_t_a_b_l_i_s_h_i_n_g _C_o_m_m_u_n_i_c_a_t_i_o_n

     Interhost  job  transfer  is done by using the Internet
(Inet) interprocess communication facilities.  For an excel-
lent  tutorial on this, see the _4_._3_B_S_DAdvanced The client or
process that wishes to send files to a  remote  host  estab-
lishes communication using the following procedure.

1).The client opens an AF_INET socket, using the SOCK_STREAM
   protocol.  The socket will use a reliable message  deliv-
   ery  method  for  communication.  Note that the socket is
   written to send a message, read to receive a message.

2).The client socket is bound to  a  reserved  port  on  the
   local  host, that is, a port on the local host whose port
   number is less than 1024.  These can only be bound to  by
   root  processes  or  a  process  which is SUID root.  The
   server on the remote machine will check  to  ensure  that
   the client originated his request from a reserved port.

3).The client determines the remote host addressing informa-
   tion using the _g_e_t_h_o_s_t_b_y_n_a_m_e(3) facility.   This  returns
   the fully-qualified domain name of the remote host.

4).The client determines the port number that the remote _l_p_d
   server  is  listening  on  by   using   the   _p_l_p_._c_o_n_f(5)
   ``printer-port''  parameter, and the _g_e_t_s_e_r_v_e_n_t(3) facil-
   ity, if necessary.

5).Using the above information, the client process will  use
   _c_o_n_n_e_c_t(2)  to establish a connection to the remote host.
   If the connect call fails, then  the  client  will  retry
   several  times  until  successful,  or  terminate with an
   error condition.

_5_._2_.  _S_e_n_d_i_n_g _R_e_q_u_e_s_t_s

     After establishing connection with the remote host, the
_l_p_d  daemon  will  fork  a  server  process to deal with the
request.  The format of the requests is specified  in  Table
1.1,  and is an extended version of the LPD Protocol, as set
out in RFC 1179.  Requests consist of a simple message  con-
sisting  of  a flag (unsigned character value) followed by a
string terminated with a new line character.   For  example,



                      December 6, 1994





PLP Manual                                           page 25


the request to transfer files to the remote host consists of
a line of the form:
     ^Bprinter

     The remote server process uses information supplied  by
_g_e_t_p_e_e_r_n_a_m_e(3N)  to  determine  the  name of the client host
machine, and the port that originated the message.  It  will
check the local printer permissions file to determine if the
host is allowed to access the specified printer spool queue.
After  checking  this basic permission, the remote host will
then perform any requested actions.

_5_._3_.  _F_i_l_e _T_r_a_n_s_f_e_r_s

     A job is transferred between the local and remote hosts
by  using  one  of two methods.  The first method is to send
the data files of a job first, followed by the control  file
(Berkeley  Protocol);  the second method is to send the con-
trol file, followed by the data files (PLP  Protocol).   The
_f_j  flag is used to select the PLP (control file first) pro-
tocol to be used in sending jobs.  The default  protocol  is
the Berkeley (data files first) protocol.

     The  file  transfer protocol consists of sending a line
identifying the type of protocol being used, the size of the
file  (in bytes), and the name of the file.  The remote host
will return a single 0 (zero) confirmation byte if it agrees
to accept the file; any other value is a fatal error.  After
confirmation, the file is transferred to the other end, fol-
lowed by a single 0 (zero) byte.  If the remote end receives
the file and the terminating 0 byte, it will return  a  con-
firming  0  (zero)  byte.   The next file may then be trans-
ferred.  After all files have been transferred, a  single  0
(zero) byte will terminate the file transfer.

     The  file transferred to the remote site will be placed
in the remote site spool queue directory, with the same path
name  it  had  at the local site.  Both the local and remote
sites will lock any files being transfered in order to  pre-
vent  other PLP processes from manipulating them.  Table 5.1
specifies the values of the flags used in the protocol.

             +---------+--------+--------------+
             |Protocol | Flag   | Meaning      |
             +---------+--------+--------------+
             |Berkeley | 2 (^B) | control file |
             |Both     | 3 (^C) | data file    |
             |PLP      | 4 (^D) | control file |
             |PLP      | 5 (^E) | last file    |
             +---------+--------+--------------+
          Table 5.1. File Transfer Protocol Flags

     To use the Berkeley Protocol, the data files  would  be
transferred  first  using  the  3 (^B) flag, followed by the



                      December 6, 1994





page 26                                           PLP Manual


control file using the 2 (^C) flag.  To use the  PLP  Proto-
col, the control file would be transferred first using the 4
(^D) flag, followed by the data files.  When all of the data
files  had  been  transferred, a confirming message would be
sent using the 5 (^E) flag, indicating that the job had been
transferred.

     For  example,  assume that we have a job with a control
file    cfA123attila.cs.umn.edu,    and    a    data    file
dfA123attila.cs.umn.edu.   Using  the Berkeley Protocol, the
client would first send the message
     ^C1293 dfA123attila.cs.umn.edu,
requesting transfer of a 1293 byte data file, whose name  is
dfA123attila.  After confirmation, the data file followed by
a single 0 byte would be sent, and a confirmation should  be
received.   Next, the message ^B343 cfA123attila.cs.umn.edu,
would be sent, and then the control file followed by a  sin-
gle 0 byte would be sent.  Having received the control file,
the remote end would acknowledge the reception of  the  job,
allowing  the client to delete the job and send another one.
When the control file is transferred, the remote  host  will
check  the  job  to  make sure that all data files have been
transferred, and enable it for printing or further  process-
ing.  If anything happens to disturb this communication, the
connection is terminated and any partially transferred  jobs
are removed.

     To  prevent interaction between an unspooler server and
a file transfer server, the job control file  is  locked  by
the file transfer server until it has been completely trans-
ferred.

_5_._4_.  _E_r_r_o_r _R_e_c_o_v_e_r_y _a_n_d _R_e_t_r_y

     When either end of the file transfer  protocol  detects
an error, they will shut down the link.  It is the responsi-
bility of the client process to retry sending jobs.

_5_._5_.  _S_e_c_u_r_i_t_y _C_h_e_c_k_s _a_n_d _A_u_t_h_o_r_i_z_a_t_i_o_n_s

     The PLP file transfer protocol restricts the  names  of
control  and data files to a fixed format.  In addition, the
_U (unlink) flag  has  no  effect  on  a  remote  host.   The
enforcement  of  the  fixed  format of data and control file
names makes it simple to remove all files associated with  a
job on completion.

     Before  placing a job in the spool queue, the user name
and hostname are checked to see if permissions  are  accept-
able.  The security of this check is based on the assumption
that the client host is a trusted originator  of  PLP  jobs.
In  a  networked environment with many different users, this
may not be the case, as it is possible to forge  information
in  a  control file.  The _f_d (no forward) flag in a printcap



                      December 6, 1994





PLP Manual                                           page 27


entry prevents the acceptance of jobs from  other  than  the
current  client.   This  is intended to prevent clients from
attempting to transfer control files that  would  appear  to
have  originated from another host.  While this will provide
verification at the host level, assuming that network  level
software  will  uniquely  identify a host, it still does not
provide a secure user identification.

_6_.  _L_o_c_a_l _S_p_o_o_l _Q_u_e_u_e_s _a_n_d _S_e_r_v_e_r_s

     The _l_p_d process  handles  the  unspooling  process  for
local  and remote spool queues in much the same manner.  _L_p_d
forks a server process to unspool entries from a queue.  The
server  (or  unspooler)  process checks the spool queue lock
file to see if unspooling is enabled, sorts  jobs  according
to priority, and then takes printing actions as specified by
the printcap entry for the spool queue.  In order to provide
fine  control over the printing process, the unspooler forks
a set of filter processes based on information in the print-
cap entry to handle specialized printer requirements.  These
filter processes are used to:

1).Provide control  over  device  dependencies,  above  that
   allowed by the simple serial line control functions.

2).Print banners or job separator information.

3).Provide  specific processing for a particular job format.

4).Provide accounting information.

     Different classes of output devices  require  different
amounts  or kinds of filter support.  The following sections
outline the different options and the  filter  support  pro-
vided for them.

_6_._1_.  _J_o_b _F_o_r_m_a_t _a_n_d _F_i_l_t_e_r _S_e_l_e_c_t_i_o_n

     Associated with each data file of a job is a unspooling
format.  When unspooling a job, the server uses this  format
to  select a filter to be used to process the data file.  By
convention, the format used for printing a job is  specified
by  a  lower case letter (a-z), and the corresponding filter
for the format is specified by the printcap field x_f_,  where
x represents the format.  This is not uniformly true, as the
_a_f (accounting file name), _l_f (log file name), and _f_f  (form
feed string) entries are used for other purposes.  In Figure
6.1, _a_f specifies the accounting file, _l_f is the  log  file,
and _o_f, _i_f, _d_f, and _t_f are filter programs.


_6_._2_.  _C_l_o_s_i_n_g _T_h_e _O_u_t_p_u_t _D_e_v_i_c_e _B_e_t_w_e_e_n _J_o_b_s

     PLP  allows  this  using  the _c_l printcap parameter. If



                      December 6, 1994





page 28                                           PLP Manual


          # Versatec Printer, Lind 33
          #   Uses the new filters
          versatec_lind33|versatec:\
              :fx=flpdt:mx#2000:\
              :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\
              :af=vaacct:\
              :lf=logfile:\
              :of=/usr/lib/vpf:\
              :if=/usr/lib/vpf:\
              :df=/usr/lib/vpf:\
              :tf=/usr/lib/rvcat:
         Figure 6.1.  Local Printer Printcap Entry
this is set, the output device will be closed and  re-opened
between  jobs.  This is useful, for example, with PostScript
printers, as it stops them keeping state between jobs.

_6_._3_.  _N_o _F_i_l_t_e_r _S_u_p_p_o_r_t _S_p_e_c_i_f_i_e_d

     If no output filters are specified,  the  server  opens
the  output  device, sets the serial line characteristics if
it is a serial line,  and  prints  directly  to  the  output
device.

_6_._4_.  _B_a_n_n_e_r_s _a_n_d _S_e_p_a_r_a_t_o_r_s

     By default, jobs are separated by a banner page or sep-
arator page that is generated by the  server  process.   The
default  banner is a single page, with the user name and job
information printed in large letters.  The _s_b (short banner)
option specifies a single line banner of the following form:
     [user]:[host] Job: [jobname] Date: [date]
     papowell:attila.cs.umn.edu Job: (stdin) Date: Fri May 20 11:29:05 1988

     The _s_h (suppress header) flag suppress banner printing.
The  _l_p_r no header option (-h) allows the user to request no
header or banner for the job; the _a_b (always  print  banner)
printcap  flag  causes  the  server  to ignore the no banner
request.

     Consecutive printer jobs are normally  separated  by  a
form  feed; the default ( _\_f) can be changed by specifying a
value for the _f_f (form feed string) field.  The _s_f (suppress
form  feeds)  can  be  used to suppress any printing of form
feeds between jobs.  When the printer is started, it may  be
necessary  to  initialize  the printer by sending some addi-
tional information.  The _f_o (form feed on open) flag  speci-
fies that the _f_f string is printed before the first job, and
the _f_q (form feed on quitting) flag specifies  that  a  form
feed is printed after the last job.  In addition, _l_d (leader
on open)  specifies  a  string  to  be  printed  before  the
(optional) intial form feed and the _t_r (trailer) specifies a
string to be printed after the  the  (optional)  final  form
feed.   The  _l_d  and _t_r strings are useful for specifying an
escape sequence that sets up form length, etc.



                      December 6, 1994





PLP Manual                                           page 29


     In addition to the built  in  banner  printer,  the  _b_p
(banner  printer) and _e_p (end printer) fields can be used to
specify banner and trailer printing  programs.   These  pro-
grams  are  invoked  to  print  banners or other information
instead of the built in banner or separator.  Custom  banner
printing may be done by suppressing built in banners with _s_h
and _s_f and using the _b_p and _e_p entries.

_6_._5_.  _S_i_m_p_l_e _O_F _a_n_d _I_F _F_i_l_t_e_r _S_u_p_p_o_r_t

     The _O_F (output filter) specified by  the  _o_f  field  is
used  by  the  server  to print banners and provide a simple
filter action for devices that need a minmum amount of  con-
trol.   The  OF filter is not intended to perform accounting
since it is started only once and no provision is  made  for
passing  owners'  login  name,  identifying the begining and
ending of jobs, etc.

     The OF filter is started when the server discovers that
it  has  a  job  to  print.  The server will open the output
device, do any line control operations, and then  start  the
OF filter.  Banner and job separator strings will be sent to
the OF filter, which filters them and sends them to the out-
put  device.  In order to use other filters, the server will
request the OF filter to suspend itself by  sending  it  the
two-character  sequence  \031\001  or ESC ^A.  The OF filter
should  then  suspend  itself  by   calling   the   function
kill(0,SIGSTOP).   The  server will wait for this event, and
then start up other filters.  After they have completed, the
server  will  signal  the  OF  filter  to  continue by using
kill(OF_pid,SIGCONT).

     The IF filter specified by the _i_f field is used to for-
mat  jobs  with  the _f format, which is for ordinary textual
output.  The _l_p_r program will use _f format by default if  no
format  is  specified,  and also for printing literal output
(lpr -l option) or _p_r output (lpr -p option).  The IF filter
is  expected to do formatting and update an accounting file.
If there is no IF filter and an _f format job is printed,  it
is  filtered  through the OF filter.  If there is no OF fil-
ter, then the printer will copy the  file  directly  to  the
output device.

_6_._6_.  _N_o_n_-_s_t_a_n_d_a_r_d _F_o_r_m_a_t_s _a_n_d _F_i_l_t_e_r_s

     The  _l_p_r  program allows the user to specify a job for-
mat; the _f format is the default format for text files.  The
_f_x  printcap  field  specifies  the  formats  allowed on the
printer; the default permitted formats are f, l, and p.  The
_l_p_r program checks to see if the requested format is allowed
when it spools a job.  Each format must have a corresponding
filter, which is used to process data files of the specified
format.  Note that these filters may  be  invoked  once  per
data  file,  or the entire set of data files may be combined



                      December 6, 1994





page 30                                           PLP Manual


into a single file and passed through a single invocation of
the filter.  Usually the effects of doing this are indistin-
guishable, but some  filters  will  cause  an  alignment  of
printer  media  to  be done for each invocation.  This is an
implementation dependent phenomenon.

     The commonly available set of formats is  specified  in
the  _l_p_r man page.  The _f (default), _l (literal), and _p (use
the ``pr'' program to format  output)  formats  are  printed
using  the  _i_f  output filter.  The _l_p_r -f option is used to
specify printing with a filter that handles FORTRAN formats;
this flag is translated by _l_p_r into printing with the _r for-
mat.  The _a_, _i_, _l_, and _o formats are unavailable,  as  their
filter  names  (af,  if,  lf and of) are used for other pur-
poses.

_6_._7_.  _P_r_e_f_i_l_t_e_r_s

     The _l_p_r program can pre-filter  files  before  spooling
them.   The  _X_e field is used to specify that format _X files
are to processed by the specified prefilter.  The  prefilter
specification  consists of the pathname and arguments of the
prefilter program, followed by the format that is to be used
for spooling the output.
          # Versatec Printer, Lind 33
          #   Uses a prefilter for f format
          versatec_lind33|versatec:\
              :fx=flpdt:mx#2000:\
              :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\
              :af=/usr/adm/vaacct:\
              :of=/usr/lib/vpf:\
              :if=/usr/lib/vpf:\
              :df=/usr/lib/vpf:\
              :tf=/usr/lib/rvcat:\
              :fe=/usr/local/lib/vprintup -X w4,f:
            Figure 6.2 Prefilter Printcap Entry

     For example, the printcap entry in Figure 6.2 specifies
that _f format files are prefiltered through _v_p_r_i_n_t_u_p and the
output is in the _f format.

_6_._8_.  _S_p_e_c_i_a_l _Q_u_e_u_e _H_a_n_d_l_e_r_s

     If  the  user does not like the way that the PLP server
handles files, the printcap can be used to specify  a  queue
handler  program  to  handle  processing of the job and data
files.  This is useful when  you  are  sending  files  to  a
remote  machine  using a special protocol or a remote proce-
dure call.  The printcap queue handler field _q_h specifies  a
program which will be responsible for handling the job.

     The  queue handler is invoked once per queue entry, and
exits with a 0 (successful),  1  (unsuccessful,  retry),  or
other  (give  up  and  delete entry) status.  Error messages



                      December 6, 1994





PLP Manual                                           page 31


          # Special queue entry, used for bizzare purposes
          # The queue_handler program will take care of everything
          special:\
              :lp=/dev/null:\
              :qh=/usr/local/lib/queue_handler:
          Figure 6.3 Queue Handler Printcap Entry
printed on _s_t_d_e_r_r (file descriptor 2) will be placed in  the
spool queue log file.

_6_._9_.  _M_u_l_t_i_p_l_e _S_e_r_v_e_r_s _F_o_r _a _S_p_o_o_l _Q_u_e_u_e

     If  a spool queue has multiple servers, they are speci-
fied using the _s_v  (servers)  parameter,  which  contains  a
comma separated list of server entries in the printcap file.
The printcap entry for  a  server  contains  a  _s_s  (serves)
parameter which contains the name of the spool queue that it
serves.

     Printcap entries for the server are determined  in  the
following manner.  When the spool queue server starts up, it
reads the spool queue printcap entry,  and  determines  that
there  are  multiple servers for the queue.  It then forks a
printer server process for each name in the _s_v list.

     The individual printer server process reads the  print-
cap  entry for the individual printer, overwriting or adding
any existing values read from printcap for the spool  queue.
Since  server  entries  use  the  the spool directory of the
spool queue, their individual log  and  other  files  should
have  distinct  names.  Common information can be put in the
spool queue printcap entry, and entries that differ for each
printer, such as the output device, need to appear the indi-
vidual printer printcap entry.
























                      December 6, 1994





page 32                                           PLP Manual


_7_.  _F_i_l_t_e_r _S_u_p_p_o_r_t

     The filter programs are started by a  queue  server  in
order  to  support specialized unspooling operations.  While
the server process runs SUID root, the filter  process  will
run  as  the  daemon  user  (as specified in the plp.conf(5)
file's ``user'' parameter).  The ownerships of files,  etc.,
which  have to be manipulated by filter programs should have
the appropriate permissions to be manipulated by the  daemon
userid.


     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 shell or perl script as a filter, and  have  the
shell script invoke a specialized program with the appropri-
ate parameters.  This technique has a slight penalty in per-
formance, but is very quick to implement.


_7_._1_.  _F_i_l_t_e_r _P_r_o_g_r_a_m _I_n_v_o_c_a_t_i_o_n _a_n_d _A_c_t_i_o_n_s

     Output  filters are invoked by the queue server daemon,
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  _l_f  (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 std-
out.

     A filter process runs setuid _d_a_e_m_o_n and is in the  same
process  group  as its creating server process.  This allows
_k_i_l_l_p_g(2) or _k_i_l_l(2) to kill both the queue  server  process
and  any  filters  it has created.  For example, _l_p_r_m termi-
nates 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.

_7_._2_.  _F_i_l_t_e_r _P_a_r_a_m_e_t_e_r_s _a_n_d _I_n_v_o_c_a_t_i_o_n

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

     A filter is invoked with the parameters in Figure  7.2,
which  may  be  present  or  missing, and in any order.  The



                      December 6, 1994





PLP Manual                                           page 33


          # Versatec Printer, Lind 33
          # Patrick Powell, 3 Nov 87
          #   Uses the new filters
          versatec|versatec_lind33:\
              :fx=flpdt:mx#2000:\
              :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\
              :af=/usr/adm/vaacct:\
              :of=/usr/lib/vpf -v3 -m '-K prefix \013\015':
          Figure 7.1. Filter Specification Example
accounting file (if present) will always be the last parame-
ter,  and is the only one without a _- prefix. Note that this
may cause problems with _p_e_r_l scripts which  use  <>  as  the
input filehandle - they should use <STDIN> instead.


          filtername arguments \
              -Pprinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
              [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost \
              -Fformat [affile]
                Figure 7.2  Filter Arguments

     The _f_i_l_t_e_r_n_a_m_e and _a_r_g_u_m_e_n_t_s values are provided in the
printcap filter information.  Arguments can  be  quoted  and
will  be  passed as a single argument to the filter program,
similar to the method used by the Bourne shell.   Note  that
the escape sequences in Figure 7.1 will be translated into a
single character value, and the resulting string will be  an
arguement for the filter.

     The  _-_P  (printer)  option is used to pass the printcap
entry printer name.  The _-_w and _-_l options specify the hori-
zontal  and  vertical  page  size  in  characters  and lines
(obtained from the _p_w and _p_l printcap entries).   Note  that
the  lpr -wNNN value will be passed if it has been specified
by a user as the _-_w option value.  The  _-_x  and  _-_y  options
specify  the  horizontal  and  vertical  page size in pixels
(from the _p_x and _p_y  printcap  entries).   The  _-_F  (format)
option  specifies  the format that this filter is being used
for.

     The above parameters  are  provided  for  all  filters,
including  the  OF filter and BP and EP banner printing fil-
ters.  A well-behaved OF filter must  detect  the  character
sequence  ESC ^A (\031, \001), flush its output, and suspend
itself using _k_i_l_l(_g_e_t_p_i_d(), SIGSTOP).  The server will  then
start  up  other filters, and use them to print jobs.  After
the job has been printed, the server will signal the OF fil-
ter to continue using SIGCONT.

     All  filters are invoked with the above parameters, and
the additional ones may be provided depending on functional-
ity.   The  _-_c  (literal) flag is optional, and is specified
for literal or _-_l output being printed using the _I_F  filter.
The  _-_i  (indent)  value  is  optional,  and  is  the  value



                      December 6, 1994





page 34                                           PLP Manual


specified by the _-_i option of _l_p_r.  The  _-_Z  (extra  parame-
ters)  are  parameters  passed  to  the filter by the _l_p_r _-_Z
option.  The _-_C (class or priority) and _-_J  (job  name)  are
optional  and  generated  by  _l_p_r.  The _-_n and _-_h parameters
specify the login name and host  name  respectively  of  the
originator  of  the  job.  The lpd will surround each string
parameter with single ticks ('), in order  to  protect  them
from misinterpretation by the shell, and in order to provide
security against hacking attempts.


     The last (optional) entry is the name of the accounting
file,  taken  from  the  _a_f  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.

_7_._3_.  _B_a_n_n_e_r _P_r_i_n_t_i_n_g _F_i_l_t_e_r_s

     The _b_p (banner printer BP)  and  _e_p  (end  printer  EP)
entries  specify  a  banner and end printing program that is
invoked at the start and end of a job.  The BP and  EP  fil-
ters  are invoked with the same parameters as the IF filter,
and with the _-_F_f format option.  Special flags  and  parame-
ters  for  these  filters  may  be specified in the printcap
entry.

     The banner printing programs will have  their  standard
input  (file descriptor 0) set to /dev/null, standard output
(file descriptor 1) to the output device, and standard error
(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 the and an error
will be reported.

_7_._4_.  _A_c_c_o_u_n_t_i_n_g _I_n_f_o_r_m_a_t_i_o_n

     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  _p_a_c  program  has
been  supplied  to  make  accounting information easily man-
agable, but most accounting procedures can  be  carried  out
with  a  simple shell script, and a hearty use of _s_o_r_t, _s_e_d,
and _a_w_k.  In order to keep track of accounting  information,
it  must  be  maintained in a consistent manner.  Entries in
the raw accounting file should have the form illustrated  in
Figure 7.3.
          host              user printer       format pages date
          attila.cs.umn.edu root imagen_lind22 n      5     Fri May 20 21:29:22 CDT 1988
              Figure 7.3 Accounting File Entry

     The  host, user, printer, and format information can be



                      December 6, 1994





PLP Manual                                           page 35


obtained from the parameters passed to the filter.  The page
entry is the number of billable pages.  When the _p_a_c program
produces a summary, the summary file has the  format  as  in
Figure 7.4.
          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 7.4 Summary File Entry

     PLP  provides  a default mode for accounting; if the _a_f
field is set, and either the _l_a or _a_r  fields  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 _l_a or  _a_r  printcap
parameters,  and  performing your own accounting in a filter
program (usually in the _i_f filter).

_7_._5_.  _P_r_e_f_i_l_t_e_r_s

     The _l_p_r program can use _p_r_e_f_i_l_t_e_r_s to process the  text
before  spooling.   The  prefilters are invoked with the the
following arguments, which are the same as specified for the
output filter.

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


     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 _l_p_r stderr output.

_7_._6_.  _A_d_a_p_t_i_n_g _E_x_i_s_t_i_n_g _F_i_l_t_e_r_s _a_n_d _W_r_i_t_i_n_g _F_i_l_t_e_r_s

     If you have an existing set of filters for the Berkeley
LPD daemon, you can use the  compat  program  supplied  with
this  package  to  adapt them to use with PLP.  This program
invokes an OF, IF, or other filter  with  the  old  Berkeley
style  of  parameters.   For  example,  the  following entry
printcap _i_f entry will invoke the  imfilter  program  to  be
used as the IF filter.
     if=/usr/local/lib/compat /usr/local/lib/imfilter




                      December 6, 1994





page 36                                           PLP Manual


     If  a new filter is needed, you can start with the pro-
grams supplied with this distribution, found in the  _f_i_l_t_e_r_s
directory.   A sample filter would consist of an application
independent main routine which parses the command line input
flags  and calls a user supplied filter() function, and sup-
port functions.  These are available  in  the  filter/main.c
file.   The  _s_u_s_p_e_n_d_(_)  support  routine suspends the filter
when the appropriate string is detected in the input.  Error
message and termination routines are provided.
















































                      December 6, 1994





PLP Manual                                           page 37


_8_.  _U_s_i_n_g _a_n _N_F_S _S_p_o_o_l _D_i_r_e_c_t_o_r_y

     In  an NFS environment, a common or shared spool direc-
tory can be used to  avoid  needless  copying  or  duplicate
rules.   The  _l_p_r program places jobs in the shared spooling
directory and then requests the _l_p_d daemon on the  appropri-
ate  remote  machine  to  start  unspooling actions.  The _n_w
(networked file system) flag and  _r_m  (remote  machine)  are
used to indicate this type of file system organization.

     In  this environment, only machines which have printers
attached or  are  acting  as  forwarding  systems  to  other
machines need to have an _l_p_d daemon running.


     The    convention   of   keeping   the   printcap   and
printer_perms files in the /etc directory is easy to use  in
a single host or loosely coupled multiple processor environ-
ment, it can be difficult to manage and apply in  a  network
based around a distributed file system such as NFS.  The PLP
software allows the printcapand printer_perms  files  to  be
kept in the /var/spool/lpd directory, qualified by hostname;
with an  NFS-mounted  /var/spool/lpd  directory,  this  will
greatly  simply  administration.   This  can be accomplished
using the _p_l_p_._c_o_n_f file's printcap-path  and  printer_perms-
path directives, as follows.

        printcap-path       /etc/printcap:/var/spool/lpd/printcap.%h:/var/spool/lpd/printcap
        printer_perms-path  /etc/pperms:/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 you can put only
the  local entries in /var/plp/printcap.hostname, and a gen-
eral-case rm=hostname,rp=port  entry  in  /var/plp/printcap.
If  you  wish  to simplify things even more, use a qualified
printer-name in the local printcap entry, so it is specified
as  _h_p_4_m_-_p_s_/_h_o_s_t_n_a_m_e and then specify the general-case entry
in the normal way. This allows you to use one printcap  file
for the entire network.


     See the manual page _p_l_p_._c_o_n_f_(_5_) and the sample configu-
ration file ``plp.conf.nfs'' in  the  examples  subdirectory
for more details.


     One  of the problems with the current implementation of
the NFS distributed file system is file locking across  file
systems.   The  current implemenation of PLP uses either the
_f_c_n_t_l_, _l_o_c_k_f or  _f_l_o_c_k  facility,  selected  at  compilation
time.   Only  _f_c_n_t_l  and  _l_o_c_k_f  will perform correctly when
locking a file on an NFS file system.  Most  implementations
of  NFS do not support atomic exclusive file-creation, which
is very important for PLP; PLP, however, does support  this,



                      December 6, 1994





page 38                                           PLP Manual


using a really grotesque hack.

     A warning message will be logged if an NFS spool direc-
tory is used in conjunction with _f_l_o_c_k file locking.

_9_.  _L_i_n_e _P_r_i_n_t_e_r _S_p_o_o_l_e_r _A_d_m_i_n_i_s_t_r_a_t_i_o_n

     Most of the administration of PLP commands consists  of
printcap  entries, permissions entries, and spool queue man-
agement.  In addition, killing and restarting the _l_p_d daemon
is occasionally needed.

_9_._1_.  _P_r_i_n_t_c_a_p _F_i_l_e _M_a_n_a_g_e_m_e_n_t

     Each  spool  queue  or  printer must have an entry in a
printcap file.  In a single, non-networked environment, this
is  usually  a  simple  and  easily managed system, but in a
highly networked environment it may be  a  difficult  proce-
dure.   In order to simply the generation of printcap files,
the PLP distribution has a set of programs that allow a sim-
ple  printcap  data base to be set up, and a set of programs
to generate printcaps for different hosts.

_9_._1_._1_.  _P_r_i_n_t_e_r _N_a_m_e_s

     Printer names and aliases are a major problem faced  by
administrators.   The convention adopted by many sites is to
make the primary (first) name of the printer  correspond  to
the  physical  printer  type  and its location.  For exmple,
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  checked  against  the  information  in  the
printer  permissions  file, and also checked in the printcap
database.  For this reason, the name  used  in  the  printer
permissions file and the name of the printer should be iden-
tical.  When sending files to a  remote  site,  the  printer
name  found in the printcap entry and not the alias provided
by a user is used to determine permissions.

_9_._1_._2_.  _P_r_i_n_t_c_a_p _F_i_l_e _G_e_n_e_r_a_t_i_o_n

     Each  printer  usually  has  three  forms  of  printcap
entries:  remote,  forward,  and  output device.  The remote
entry is used by a system that will treat the spool queue as
a  remote  site  and forward all jobs to a remote site.  The
forwarding entry is usually used for sites that accept  jobs
from  other  sites,  and then forward them to a remote site.
The forwarding is usually done by a specialized file  trans-
fer  program.   Finally,  a  local or output device entry is
used for the host which has  the  actual  printer  attached.
Files  with  the appropriate form printcap entry can be pre-
pared.  As part of the PLP distribution, a set  of  programs



                      December 6, 1994





PLP Manual                                           page 39


to generate printcap files tailored to a particular host has
been developed, and is available in the printcap  directory.

_9_._1_._3_.  _P_r_i_n_t_e_r _P_e_r_m_i_s_s_i_o_n_s _F_i_l_e

     The main printer permissions file is intended to act as
a filter for general user permissions.  As  described  else-
where,  each line is checked for a matching set of user per-
missions, and the first matching line determines the  avail-
able  permissions.  It is strongly suggested that the set of
entries in the printer_perms file  be  used  to  filter  out
unauthorized users, and the remaining set of entries used to
determine the appropriate permissions.

     If restrictions on the number of pages are desired, the
printer  permissions  file  can be used on a global or local
basis.  The current page count field is compared against the
maximum  field  at the time a job is spooled or printed.  In
order to keep this file concurrent, some form of simple per-
missions  file  updating  must be done.  This can be done by
using the _p_a_c (printer accounting) program  and  a  suitable
shell  script.   Due  to  the  wide  divergence of different
sites, an accounting package to do  this  automatically  has
not been provided.

_9_._2_.  _U_s_i_n_g _L_P_C

     The  _l_p_c  program  provides  control  over line printer
activity.  The major commands and  their  intended  use  are
described  in  this section.  See the manual page _l_p_c(8) for
details, and other commands not mentioned here.

_s_t_a_t_u_s_, _l_p_q

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

_s_t_a_r_t_, _a_b_o_r_t_, _k_i_l_l

     _S_t_a_r_t enables printing and requests _l_p_d to start print-
     ing jobs.

     _A_b_o_r_t disables  unspooling  and  terminates  an  active
     server  and its filters.  This is normally used to kill
     a  catatonic  filter  or  spooler  process  (i.e.,  _l_p_q
     reports  that  there is a daemon present but nothing is
     happening).  It does  not  remove  any  jobs  from  the
     queue.

     _K_i_l_l  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



                      December 6, 1994





page 40                                           PLP Manual


     an upper limit on the numbers of times  a  server  will
     attempt to print a job.

_r_e_q_u_e_u_e

     This command is useful if the printer hardware malfunc-
     tions during the printing of a job; _R_e_q_u_e_u_e  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  _s_t_a_r_t
     command, and the job will the reprinted.

_e_n_a_b_l_e_, _d_i_s_a_b_l_e

     _E_n_a_b_l_e  and _d_i_s_a_b_l_e control spooling to a queue or list
     of queues.  This is used to prevent  _l_p_r  from  putting
     new  jobs  in the spool queue.  The main use is to pre-
     vent users from putting jobs  in  the  queue  when  the
     printer  is expected to be unavailable for a long time.


_l_p_d

     _L_p_d reports the state of the lpd on that system and its
     pid.


_r_e_s_t_a_r_t

     _R_e_s_t_a_r_t  allows  mere  mortal  users to restart printer
     daemons when _l_p_q reports that there is no  daemon  pre-
     sent.

_s_t_o_p

     _S_t_o_p disables any further unspooling, but does not kill
     off the server.  This is a  clean  way  to  shutdown  a
     printer  in  order  to  perform maintenence, etc.  Note
     that users can still enter jobs in a spool queue  while
     a printer is _s_t_o_p_p_e_d_.

_t_o_p_q

     _T_o_p_q  places  jobs at the top of a printer queue.  This
     can be used to reorder high priority jobs.

_r_e_m_o_t_e _(_c_o_m_m_a_n_d_)

     _r_e_m_o_t_e is used to send a command to the remote site for
     processing.   This  is  useful  to  control remote line
     printer queues.

_c_l_e_a_n



                      December 6, 1994





PLP Manual                                           page 41


     _c_l_e_a_n totally purges a queue.   This  functionality  is
     needed   very   infrequently,  and  perhaps  should  be
     removed.

_9_._3_.  _S_t_a_r_t_i_n_g _t_h_e _L_P_D _D_a_e_m_o_n

     Under various circumstances it may be necessary to kill
and/or restart the _l_p_d daemon.  The currently executing dae-
mon writes its process ID and the time it was started in the
/var/spool/lpd/lock.lpd  file.   The  program in Figure 9.1,
lpd.restart, can be used to kill and restart the LPD daemon.
          #!/bin/sh

          pid=`head -1 /var/spool/lpd/lpd.lock`
          host=`hostname`

          if [ "x$pid" = x ] ; then
              echo "$h: no lpd daemon"
          else
              echo "$h: killing $pid and restarting lpd"
              kill $pid; sleep 1
              /usr/local/bin/lpd
          fi
               Figure 9.1 lpd.restart Program

_1_0_.  _D_i_a_g_n_o_s_t_i_c_s _a_n_d _T_r_o_u_b_l_e_s_h_o_o_t_i_n_g

     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  explana-
tion does help, and if you 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 _f_a_c_i_l_i_t_i_e_s, or parts of the PLP functionality.
At the moment, there are the following facilities:


_p_c_a_p _- _l_o_o_k_u_p_s _o_n _t_h_e _p_r_i_n_t_c_a_p _f_i_l_e _o_r _f_i_l_e_s

_p_e_r_m_s _- _l_o_o_k_u_p_s _o_n _t_h_e _p_e_r_m_i_s_s_i_o_n_s _f_i_l_e _o_r _f_i_l_e_s

_r_e_m_o_t_e _- _t_h_e _r_e_m_o_t_e_-_p_r_i_n_t_e_r _t_r_a_n_s_f_e_r _m_e_c_h_a_n_i_s_m

_l_o_c_a_l _- _t_h_e _l_o_c_a_l_-_p_r_i_n_t_e_r _c_o_d_e_; _s_t_t_y_, _d_e_v_i_c_e _l_o_c_k_i_n_g_, _e_t_c_.

_c_o_n_f _- _t_h_e _p_l_p_._c_o_n_f _r_e_a_d_i_n_g _a_n_d _f_i_l_e_n_a_m_e _e_x_p_a_n_s_i_o_n_s

     You  can  also  set a general debug setting, which will
set debug modes for all the facilities you don't  explicitly



                      December 6, 1994





page 42                                           PLP Manual


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 _f_a_c_i_l_-
_i_t_y_=_l_e_v_e_l_.  To set the general debug level,  use  _-_D  _l_e_v_e_l_.
You  can  also combine these by separating them with commas,
for example _-_D _p_c_a_p_=_6_,_4 would set a general level of 4 and a
level of 6 for the printcap code.

     The  debug levels are 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.

_1_0_._1_.  _L_P_D

     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 _s_y_s_l_o_g(8) facility.  You can
also specify a log file using the _-_L _f_i_l_e_n_a_m_e option to lpd;
_-_L _- will cause it to log error messages to standard output.

     Each spool queue has an associated log file as well, as
does  each  server for a spool queue.  Most of the PLP soft-
ware will also use _s_y_s_l_o_g(8) for important messages, or  log
them to /dev/console if syslog is not available.

_1_0_._2_.  _L_P_R

_l_p_r_: _p_r_i_n_t_e_r_: _u_n_k_n_o_w_n _p_r_i_n_t_e_r

     The  _p_r_i_n_t_e_r  was  not  found in the _p_r_i_n_t_c_a_p database.
     Usually this is a typing mistake; however, it may indi-
     cate a missing or incorrect entry in the printcap file.

_l_p_r_: _p_r_i_n_t_e_r_: _j_o_b_s _q_u_e_u_e_d_, _b_u_t _c_a_n_n_o_t _s_t_a_r_t _s_e_r_v_e_r_.

     The connection to _l_p_d  on  the  local  machine  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  _l_p_d process is running.  If it appears to be
     absent, start a new lpd  process  using  the  following
     command.

             % /usr/local/bin/lpd


_1_0_._3_.  _L_P_Q

_w_a_i_t_i_n_g _f_o_r _p_r_i_n_t_e_r _t_o _b_e_c_o_m_e _r_e_a_d_y _(_t_r_y_i_n_g _s_i_n_c_e _?_?_?_?_)

     The  printer  device could not be opened by the server.
     This can happen for a number of reasons, the most  com-
     mon  being  that  the printer is turned off-line.  This



                      December 6, 1994





PLP Manual                                           page 43


     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 suffi-
     cient information to distinguish when a printer is off-
     line  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 _l_p_c.

_c_o_n_n_e_c_t_i_n_g _t_o _<_h_o_s_t_> _(_t_r_y_i_n_g _s_i_n_c_e _?_?_?_?_)

     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, _l_p_d on the remote
     machine  is  probably  dead  or  hung  and  should   be
     restarted.

_w_a_r_n_i_n_g_: _n_o _s_e_r_v_e_r _p_r_e_s_e_n_t

     There  are  entries  in  the spool queue, but no server
     exists.  This normally occurs when the server  has  not
     started  yet; if this message persists and the jobs are
     not unspooled, the server may actually  have  unexpect-
     edly  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.


























                      December 6, 1994





page 44                                           PLP Manual


_1_1_.  _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d _T_e_s_t_i_n_g

     The following is a summary of the test  procedures  for
the  PLP  software.   See the file "INSTALL" in the PLP base
directory for installation instructions.

_1_1_._1_.  _T_e_s_t _V_e_r_s_i_o_n

     A test version of the spooling software can  be  gener-
ated  by  compiling with the CONFIG_FILE definition set to a
non-standard  location,  such  as  /tmp/plp.test.cf.    This
allows  you  to use /tmp/printcap.%h, /tmp/printer_perms.%h,
and a non-priviledged INET port, rather than  /etc/printcap,
/etc/printer_perms,   and  the  priviledged  TCP/IP  printer
server port.  If you compile PLP with the SUID_CFLAGS  defi-
nition uncommented in the Makefile, you can test PLP without
using any form of specially-privileged user, be it  root  or
daemon;  ie.  using  your own userid.  The following diagram
depicts a sample test _p_l_p_._c_o_n_f file, and is  also  available
in  the file test/plp.conf.  See the manual page _p_l_p_._c_o_n_f(5)
for more details.

        user        yourname

        logfile     /tmp/lpd.log.%H
        lockfile    /tmp/lpd.lock.%H
        printcap-path   /tmp/printcap.%H
        printer_perms-path  /tmp/printer_perms.%H

        lpd-port    45321
        allow-non-priv-portsallow quiet


     The PLP distribution _t_e_s_t directory contains  prototype
or  debugging versions of printcap, printer_perms, plp.conf,
and other files; _t_e_s_t_/_M_a_k_e_f_i_l_e will generate and install the
necessary  directories  and  filters.  The test devices have
their spool directories in /tmp, and should  be  trivial  to
install.  You  need  to edit the Makefile so a few of things
are set properly for  your  local  site  (eg,  hostname  and
paths).  Run the tests listed below to ensure that the vari-
ous programs are working.

     In summary, to make the test verions, do the following.

1).  Run  the  configure  script, edit the Makefile, and run
     make, as detailed in INSTALL.

2).  Set up your shell $path or $PATH to use  the  directory
     where   you  compiled  the  PLP  executables  ahead  of
     /usr/ucb and  /usr/bin,  otherwise  you  will  use  the
     existing LPD programs.

3).  Go  to  the  test directory, read the test/README file,



                      December 6, 1994





PLP Manual                                           page 45


     edit the test/Makefile according to the directions, and
     do  make  bin.   This  generates  some  executables and
     places  them  in  the  /tmp  directory,  as   well   as
     installing  a  test  version of the printer permissions
     and plp.conf files.

4).  Now you should take a nap, play  nethack,  or  whatever
     you do to relax.  The next part is not fun.

_1_1_._1_._1_.  _T_e_s_t _1_- _L_P_C_, _L_P_R_, _L_P_Q

     To  run  the  first tests, change to the test directory
and do make test1.  This installs the printcap file of  Fig-
ure 11.2 in /tmp/printcap:
          #
          # TEST VERSION OF PRINTCAP FILE:
          # Test 1: simple lpr functions
          #
          test:\
              :fx=flpdnt:ex:\
              :pw#75:pl#66:rw:\
              :br#9600:fs#040:fc#011:\
              :ty=new 19200 even -tabs tandem:\
              :lp=output:\
              :if=/tmp/filter -delay30:\
              :of=/tmp/lpf -D5:\
              :sd=/tmp/test:
             Figure 11.2  Test 1 Printcap File

     You  should look at the code for the filter and the lpf
programs which were created by the  make  bin.   The  filter
program  is  a handy dandy debugging filter.  The lpf filter
simply copies stdin to stdout, and suspends itself  when  it
detects  the  stop  string.   The  lpf  filter source is the
skeleton for any new filters that are needed.

     You can test the functionality of the lpq, and lpr pro-
grams  by using the illustrated commands.  Sample output has
been provided.
%>lpq -D5   #should display queue (empty)
lpq: pid=4233, LOG_DEBUG, First_printer: simple at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, Get_Printer: First_printer 'simple' at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, Get_printer: using Printer simple at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, Readlockfile: lockfile 'lock' at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, Readlockfile: lock, perms 0100644 at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, Readlockfile: 'lock' pid 0 len 0 at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, Checklockfile: lock server 0 at Fri May 20 17:02:08 1988
lpq: simple- pid=4233, LOG_DEBUG, printstatus: ST status at Fri May 20 17:02:08 1988
Printer 'simple' (attila.cs.umn.edu):
  work done at Wed May 18 09:38:59 1988

%>lpr xx    #place job in queue
lpr: Warning- File 'xx' not printed: cannot access it
lpr: Fatal error- nothing to print



                      December 6, 1994





page 46                                           PLP Manual


%>echo hi | lpr #place job in queue
lpr: simple- Startserver: host 'attila.cs.umn.edu' server for 'simple'
            not started - Connection refused at Fri May 20 17:08:51 1988

%>lpq       #should display queue one entry
Printer 'simple' (attila.cs.umn.edu):
Warning: no server present
  Rank Owner       Pr Job Host        Files                Size
   1st papowell    Z  13  attila      (stdin)              3

%>lpc       #play with lpc
>status
Queue          Jobs    Queueing     Printing
simple            1    enabled      enabled (no server)

>disable simple
simple: queueing disabled
>status
Queue          Jobs    Queueing     Printing
simple            1    disabled     enabled (no server)
>quit


_1_1_._1_._2_.  _T_e_s_t _2_- _L_P_D _F_u_n_c_t_i_o_n_a_l_i_t_y

     Use the commands:
     echo >/tmp/error
     lpd  -D5 -L /tmp/error; tail -f /tmp/error
to create the error log file and to start  up  lpd.   It  is
best  to  do  this  at  one terminal/window, and then do the
remaining tests at another  terminal/window.   You  will  be
amused to watch the lpd spring into action, trying to create
servers,  etc.   The  simple  server  will  log   into   the
/tmp/simple/log file.

     You  can  remove /tmp/test/log, and see the interaction
of the lpd daemon and the printer server little clearer.  To
kill the lpd daemon, do the following:

        lpc lpd     ##- prints the lpd daemon id
        kill <pid>  # kill off the daemon
        rm /tmp/test/log    # remove the log file
        echo >/tmp/error
        lpd -D5 -L /tmp/error
        tail -f /tmp/error


     If you are curious, try starting multiple lpd programs;
when lpd is started, it checks for a running daemon, print a
message, and then exits.

     You can examine the conditions of the servers and other
activites by using _l_p_q.  Note that  the  lpq  status  report
includes   a   chatty  informational  piece  about  the  job



                      December 6, 1994





PLP Manual                                           page 47


progress.

     The OF filter has been carefully created to  print  out
various  pieces of information.  You can see what this is if
you look at /tmp/test/output, where  the  output  is  going.
You  will  notice  that the IF filter is a shell script, and
will sleep for a while.  You can now test  out  the  various
lpq, lpr, and lpc functions.


_1_1_._1_._3_.  _T_e_s_t _3 _- _L_P_D _F_u_n_c_t_i_o_n_a_l_i_t_y _f_r_o_m _i_n_e_t_d _(_o_p_t_i_o_n_a_l_)

     If  you  want  to run lpd from inetd, now's the time to
test it out; add the following  line  to  the  /etc/services
file  (this  assumes that you're using the ``plp.conf'' file
from figure 11.1):

        nprinter    44444/tcp


     and the following to the /etc/inetd.conf file, changing
$(PLP_BIN) as appropriate:

        nprinter  stream  tcp  nowait  root  $(PLP_BIN)/lpd  lpd -i


     Now, kill off the current lpd process; type lpc lpd and
kill -3 _<_l_p_d_p_i_d_>, where lpdpid is the process ID  output  by
lpc.   Restart  the  inetd  process[3].  This will cause the
inetd process to reread the /etc/inetd.conf file, and  start
listening  for requests on the nprinter port. When one comes
in, it will fork an LPD process to handle it.

     Test this out using the lpq, lpr and other commands, as
in  step  2.  Make sure the ``plp.conf'' file is set up with
an lpd-port entry, so the client commands don't end up talk-
ing to the system lpd instead of PLP.

_1_1_._1_._4_.  _T_e_s_t _4 _- _R_e_m_o_t_e _S_e_r_v_e_r_s

     These  tests  check out the functionality of inter-host
spooling functions.  They have been  written  so  that  they
will  use  the local host intitially, but can be extended to
the remote host.

     In the test direcotory, do make test2  to  install  the
second form of the printcap file.  You will not have to kill
the lpd to do this.  Now try
     lpq -Premote
_________________________
  [3] Send the inetd process a SIGHUP signal by finding
out its pid using ps -ef or ps aux and typing  kill  -1
_<_p_i_d_>.




                      December 6, 1994





page 48                                           PLP Manual


and examine the output.  The lpq program will print out  the
local  queue,  and  then  send  a message to the remote host
(which is the local host).  This will check  out  the  func-
tionality  of  the network communication.  You can play with
lpr, lpc, etc. and check this out.  Try the _r_e_m_o_t_e functions
of the _l_p_c program.

     If  you have two hosts available, install the PLP soft-
ware on both of them.  Edit the printcap files so  that  one
of  them  has  the local test, and the other the remote test
entry.  Don't forget to install and modify the printer_perms
file  so  that  the  remote  host  can access the test spool
queue.  Try the communications out.

_1_1_._1_._5_.  _T_e_s_t _5 _- _M_u_l_t_i_p_l_e _S_e_r_v_e_r_s

     This will demonstrate how to have multiple servers  for
a  single  spool  queue.  Install the printcap file by doing
make test3.  Use lpq to check the status of the spool queue.
Now  use  lpr  to send a slog (10 or more) jobs to the multi
queue.  You can use
     lpq +10 -a
to monitor what happens.

_1_1_._1_._6_.  _T_e_s_t _6 _- _S_e_r_i_a_l _L_i_n_e _C_o_n_t_r_o_l

     If you have a printer, attach it to a  suitable  serial
line,  and  modify the test printcap entry so that it is set
up for the printer.  I have found that the following  proce-
dure works pretty good.

     Set  the _s_h (suppress headers or banners) in the print-
cap entry, and remove the _o_f entry.  Set up a new entry  for
if, _i_f_=_/_t_m_p_/_s_e_r_i_a_l _-_d_3_0 and edit the filter program to print
out the stty settings.  You can now run lpr to try and  send
things  out  to  the  printer.  You will either have lots of
problems or no problems in communicating with the printer.

     Watch out for parity; you may have to fool around  with
the printer parity settings.  I strongly suggest a NO parity
setting.  Tandem flow control is another tricky  area.   You
may have to open the printer read/write using _r_w to get tan-
dem flow control.  This has  been  a  problem  with  several
installations.


_1_1_._2_.  _C_h_e_c_k_i_n_g _O_u_t _E_x_i_s_t_i_n_g _P_r_i_n_t_c_a_p_s _a_n_d _F_i_l_t_e_r_s

     If you have an existing printcap file, you can check it
out by using a test form of PLP before  you  commit  to  the
actual form.

1).First,  edit  the  Makefile  and  change  CONFIG_PATH  to
   /tmp/plp.test.cf, the ``plp.conf'' file from figure 11.1,



                      December 6, 1994





PLP Manual                                           page 49


   then compile up PLP.

2).Copy     the     original     /etc/printcap    file    to
   /tmp/printcap.<host>.

3).Modify  the  /tmp/printcap.<host>  file   so   that   the
   /var/spool  directories  in  it  are  modified to be /tmp
   directories.

4).Set your $pathor PATH environment  variable  to  use  the
   test  version,  and  run  checkpc  -f to create the spool
   directories needed by the /tmp/printcap.<host> version.

5).You can now run a parallel version of the  PLP  software,
   and check out the behaviour of devices and filters.


_1_1_._3_.  _I_n_s_t_a_l_l_i_n_g _a _W_o_r_k_i_n_g _V_e_r_s_i_o_n

     Before  you install a the PLP software, you should make
a copy of the existing print spooler software.  There  is  a
set of programs in the backup directory of the PLP distribu-
tion that have proven to be very useful.  Here's how to make
an installable version.

1).  Edit  the Makefile and change the CONFIG_PATH directive
     to point to a non-test version, such as  /etc/plp.conf,
     and  comment  out  the SUID_CFLAGS definition so setuid
     mode is re-enabled.

2).  Do a make clean; make all  to  regenerate  the  working
     version.

3).  Create  a  printer permissions file.  You can base this
     on the version in the test directory.  The  version  in
     Figure  11.3  is  useful for initial installations, and
     can be found in test/printer_perms.all.
     # Printer permissions data base
     # host user printerqueue maxpriority maxpages currentpages
     # * is a wildcard
     #host   user      printer     perms  pr maxpages pages
     *       root      *           *      *  0        0  #root on any system
     *       *         *           R      G  0        0 #anybody can do remote
          Figure 11.3  Sample Printer Permissions File


4).  Do a make install and check that permissions have  been
     set correctly.

5).  Using  the same tests as outlined above, make sure that
     lpr, lpc, and lpq are functional.

6).  Start lpd and check that files are unspooled and trans-
     ferred correctly.



                      December 6, 1994





page 50                                           PLP Manual


_1_1_._4_.  _I_m_p_r_o_v_i_n_g _P_L_P_'_s _P_e_r_f_o_r_m_a_n_c_e

     PLP's  in-built defaults state that it should not cache
printcap and printer_perms information, but  instead  should
read  the  file  every  time an entry is requested.  This is
noticeably detrimental to the speed of the lpd, but is  very
useful for testing.

     Once  you  are  satisfied  that  your PLP configuration
files will be reasonably static for a while, turn on caching
by putting the following lines in the plp.conf file:

        use-printcap-cache  yes
        use-perms-cache yes


     These  will  enable caching, and should speed things up
significantly. You can cause the lpd to reread all its  con-
figuration  files  at  any time by sending it a SIGHUP (kill
-1).





































                      December 6, 1994





PLP Manual                                           page 51


_1_2_.  _R_e_c_e_n_t_l_y_-_a_d_d_e_d _F_u_n_c_t_i_o_n_a_l_i_t_y

     The following is some of the useful features that  have
been added to PLP in recent versions, but which don't really
fit into the current organisation of this manual.

_1_2_._1_.  _O_r_g_a_n_i_z_a_t_i_o_n _o_f _P_r_i_n_t_c_a_p _I_n_f_o_r_m_a_t_i_o_n

     If you are working in an environment with a large  num-
ber  of different hosts and different printers, PLP provides
several mechanisms to aid printcap-file administration.


_1_2_._1_._1_.  _M_e_t_h_o_d _1 _- _u_s_i_n_g _H_e_s_i_o_d _o_r _N_I_S

     PLP supports the use of Hesiod or NIS databases to hold
the  printcap  information.  See the supplementary document,
_E_U_C_S_-_e_x_t_e_n_s_i_o_n_s_._p_s, in the PLP doc subdirectory for details.

_1_2_._1_._2_.   _M_e_t_h_o_d  _2  _-  _u_s_i_n_g  _h_o_s_t_n_a_m_e_-_q_u_a_l_i_f_i_c_a_t_i_o_n _o_n _t_h_e
_s_e_r_v_e_r_'_s _p_r_i_n_t_c_a_p _e_n_t_r_y

     When performing printcap lookups, PLP will check for  a
printer  called  _p_r_i_n_t_e_r_n_a_m_e_/_h_o_s_t_n_a_m_e  before  checking  for
_p_r_i_n_t_e_r_n_a_m_e.  With this setup, it is possible that only  one
printcap  file  is needed for your entire network. Here's an
example:

        #
        # HP4Mplus printer, PLP client
        #
        hp|laser|ps|postscript|hp4m-ps:cm=HP LaserJet 4Mplus, postscript:\
                    :sd=/var/spool/print/hp-ps:lf=/share/logs/lpd/hp4m/ps:\
                    :rp=hp4m-ps:rm=class.iona.ie:
        #
        # HP4Mplus printer, PLP server
        #
        hp/class|laser/class|ps/class|postscript/class|hp4m-ps/class:\
                    :cm=HP LaserJet 4Mplus, postscript:\
                    :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:



_1_2_._1_._3_.  _M_e_t_h_o_d _3 _-  _u_s_i_n_g  _t_h_e  _p_l_p_._c_o_n_f  _`_`_p_r_i_n_t_c_a_p_-_p_a_t_h_'_'
_d_i_r_e_c_t_i_v_e

     The  plp.conf  file supports a path-based lookup mecha-
nism, where you can qualify elements  of  the  path  by  the
machine's  hostname.   Each  file will be checked, in order,
and the first entry with the correct printer  name  will  be
used.

        printcap-path   /etc/printcap:/var/spool/lpd/printcap.%h:/var/spool/lpd/printcap



                      December 6, 1994





page 52                                           PLP Manual


     The  %h  in  this line will be expanded into the host's
name, allowing the administrator to use the following print-
caps:

        #
        # /var/spool/lpd/printcap
        #
        hp|laser|ps|postscript|hp4m-ps:cm=HP LaserJet 4Mplus, postscript:\
            :sd=/var/spool/print/hp-ps:lf=/share/logs/lpd/hp4m/ps:\
            :rp=hp4m-ps:rm=class.iona.ie:


     and

        #
        # /var/spool/lpd/printcap.class
        #
        hp|laser|ps|postscript|hp4m-ps:cm=HP LaserJet 4Mplus, postscript:\
            :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:



_1_2_._1_._4_.  _M_e_t_h_o_d _4 _- _u_s_i_n_g _t_h_e _i_n_c_l_u_d_e _d_i_r_e_c_t_i_v_e_s

     The printcap, printer_perms and plp.conf files all sup-
port inclusion of other files into them, in the same  manner
as preprocessors such as _c_p_p_(_1_), the C compiler's preproces-
sor. Say, for example, you place a line  consisting  of  the
following into your printcap file:

        include /var/spool/lpd/pcaps/hp4m.remote


     This  will cause your printcap file to include the file
/var/spool/lpd/pcaps/hp4m.remote.  You can also use relative
paths,  in  which  case  the _p_l_p_._c_o_n_f_'_s config-include-path,
printcap-include-path and printer_perms-include-path  direc-
tives  are  used  to  specify  a  list  of directories to be
searched for these files.  See the _p_l_p_._c_o_n_f_(_5_)  manual  page
for more details.

_1_2_._1_._5_.  _M_e_t_h_o_d _5 _- _u_s_i_n_g _t_h_e _s_c_r_i_p_t_s _i_n _t_h_e _p_r_i_n_t_c_a_p _d_i_r_e_c_-
_t_o_r_y

     If you fancy a solution that'll work with old BSD  lpds
as well as PLP ones, you may find the programs in the print-
cap directory handy to manage printcap files.  The organiza-
tion and management is based on the following structure.

     Each  printer has a physical location name and a set of
aliases.  For our sample printer, printer_loc,  There  is  a
printer_loc.local file which contains a printcap entry suit-
able  for  the  host  which  has  the  device  attached,   a



                      December 6, 1994





PLP Manual                                           page 53


printer_loc.remote  file  which  contains  a  printcap entry
suitable for a host which can communicate  directly  to  the
remote host, and a printer_loc.forward file which contains a
printcap entry suitable for a host which  forwards  jobs  to
either  a local or remote host.  For example, here are typi-
cal entries for the 3 files.  These files are stored in  the
directory printcap/devices.  Figure 11.4 is a sample of sev-
eral of them.

+---------------------------------------+-------------------------------------+
|dg1_lind23.local                       | dg1_lind23.remote                   |
+---------------------------------------+-------------------------------------+
|dg1_lind23.local|dg1:\                 | dg1_lind23.local|dg1:\              |
|    :sd=/var/spool/lpd/dg1_lind23:\    |     :sd=/var/spool/lpd/dg1_lind23:\ |
|    :lp=/dev/tty09:ty=9600 -even -odd: |     :rm=attila:rp=dg1_lind23:       |
+---------------------------------------+-------------------------------------+

           +------------------------------------+
           |dg1_lind23.forward                  |
           +------------------------------------+
           |dg1_lind23.local|dg1:\              |
           |    :sd=/var/spool/lpd/dg1_lind23:\ |
           |    :rm=attila:rp=dg1_lind23:       |
           +------------------------------------+
             Figure 11.4  Sample Printcap Files

     Each host will have a file containing the names of  the
entries in the printcap file.  The genpc program will gener-
ate a printcap file from the named printer file by  concate-
nating   the  printcap  information  and  placing  it  in  a
host.printcap file.  This file can then  be  copied  to  the
desired destination.

_1_2_._2_.  _L_P _P_i_p_e_s

     If  you  intend to use PLP to print to devices that are
not connected to a serial line, such as HP LaserJet printers
with  the  JetDirect  ethernet  interface board, or printers
connected to Annex terminal servers, you will probably  want
to use an _l_p_-_p_i_p_e process to communicate with the printer.

     LP-pipes  are  run as root, and are passed the standard
set of filter arguments  on  the  command-line,  except  the
accounting  filename  is replaced by the status filename (if
used; see section 3.9 for details).  In addition,  they  are
passed  the  arguments  specified in the printcap entry, and
this is where you should include any device-specific parame-
ters.   If you intend to use an LP-pipe, the _c_l(close output
device between jobs) printcap parameter  may  prove  useful.
See section 6.2 for more details on this.

     The  LP-pipe  is passed the status filename on the com-
mand-line so it can insert its own  progress  messages  into
it, which will then be displayed to the user via _l_p_q.



                      December 6, 1994





page 54                                           PLP Manual


     You  may want to use the errors-file functionality with
LP-pipes, in order  to  communicate  device-specific  errors
back  to  the  user. This functionality allows you to put an
error message into a file in the spool directory,  typically
called   _e_r_r_o_r_s(although  this  can  be  changed  using  the
_p_l_p_._c_o_n_f directive errors-file), and when an error  mail  is
sent, the contents of this file will be appended.

     Several  sample  LP-pipe programs are included with the
PLP distribution, in the src/lp-pipes subdirectory. See  the
file doc/README.lp-pipes for details.

_1_2_._3_.  _U_s_i_n_g _t_h_e _M_i_n_f_r_e_e _a_n_d _L_i_m_i_t_s _P_r_i_n_t_c_a_p _P_a_r_a_m_e_t_e_r_s

     Minfree  is  a  method  of stopping the spool directory
from filling up the entire filesystem; if an  incoming  file
would  push the free space on the spool directory's filesys-
tem below this value, it is refused.

     Limits is similar to the _m_x printcap parameter;  it  is
used  to specify a maximum job size for that queue. However,
instead of rejecting the print job straight  away,  it  will
accept  the  job, but will not print it.  This is useful for
multiple-device queues; one device queue could  have  a  low
limit  value,  and would print the smaller jobs, and another
device queue would share the same spool directory and have a
higher limit value, and print the larger jobs that the first
queue skips.

     Both of these fields have  dual  values;  if  they  are
numeric,  they  specify  the actual value in 1 Kbyte blocks.
However, if their first character is non-numeric,  they  are
treated  as  a filename to be opened, from which the desired
value is to be read from.























                      December 6, 1994


