Remote Printing Utilities

This chapter covers the following topics:

Introduction

QNX provides two separate print spooling facilities:

If you don't need TCP/IP connectivity (e.g. the printer in your QNX-only network is connected to a QNX node and will service other QNX nodes only), then you should you use the lpsrvr utility set, which is easier to configure and than lpd.

If you do require TCP/IP connectivity (e.g. your printer is connected to a non-QNX node or will service non-QNX nodes), then you should use the lpd utility set.

Although it's possible to use both utility sets, it's not recommended. Apart from the confusion of the utility naming scheme, as well as the added complexity of such a dual configuration, note that each server requires its own spool area per printer. So as print jobs get passed from one spool area to another, you'd loose the ability to query or remove these jobs.

The following table summarizes the equivalent configuration file, server, and client utilities of the native QNX set and the two TCP/IP sets. Notice that lpq, lpc, and lprm are present in both the QNX lpsrvr and UNIX lpd utility sets. To help avoid confusion, the QNX lpd set prefixes these utilities with ``lpr'' instead of just ``lp.''

Native QNX
(lpsrvr):
TCP/IP UNIX
(lpd):
TCP/IP QNX
(lpd):
/etc/config/lpsrvr /etc/printcap /etc/printcap
lpsrvr lpd lpd
lp lpr lpr
lpq lpq lprq
lpc lpc lprc
lprm lprm lprrm

Overview of the lpd system

The line printer system supports:

The line printer system consists mainly of the following files and commands:

The file /etc/printcap is a master database describing printers directly attached to a machine and printers accessible across a network. The /etc/printcap file provides the authoritative definition of the format of this database and specifies default values for important items (e.g. the spooling directory).

Summary of lpd utilities

lpd - line printer daemon

The lpd program, which is usually invoked at boot time from the /etc/config/sysinit file, acts as a master server for coordinating and controlling the spooling queues configured in the /etc/printcap file. When started, lpd makes a single pass through the /etc/printcap database, restarting any printers that have jobs. In normal operation, lpd listens for service requests on a socket within the Internet domain (under the ``printer'' service specification) for requests for printer access.

The daemon spawns a copy of itself to process the request; the master daemon continues to listen for new requests.

Clients communicate with lpd using a simple transaction-oriented protocol. Authentication of remote clients is done based on the ``privilege port'' scheme employed by rshd and rcmd.

The lpr command lets users enter a print job in a local queue and notify the local lpd that there are new jobs in the spooling area. The daemon either schedules the job to be printed locally, or if printing remotely, attempts to forward the job to the appropriate machine. If the printer can't be opened or the destination machine can't be reached, the job will remain queued until the work can be completed.

lprq - show line printer queue

The lprq program works recursively backwards displaying the queue of the machine with the printer and then the queue(s) of the machine(s) that lead to it. This utility has two forms of output:

lprrm - remove jobs from a queue

The lprrm command deletes jobs from a spooling queue. If necessary, lprrm will first kill off a running daemon that is servicing the queue and restart it after the required files are removed. When removing jobs destined for a remote printer, lprrm acts like lprq, except it first checks locally for jobs to remove and then tries to remove files in queues off-machine.

lprc - line printer control program

The lprc program is used to control the operation of the line printer system. For each line printer configured in /etc/printcap, lprc may be used to:

Access control

The printer system maintains protected spooling areas so that users can't circumvent printer accounting or remove files other than their own. The strategy used to maintain protected spooling areas is:

  1. The spooling area is writable only by a daemon user and daemon group.
  2. The lpr program runs setuid to root and setgid to group daemon. The root access permits reading any file required. Accessibility is verified with an access() call. The group ID is used in setting up proper ownership of files in the spooling area for lprrm.
  3. Control files in a spooling area are made with daemon ownership and group ownership daemon. Their mode is 0660. This ensures that users won't modify control files and that no user can remove files except through lprrm.
  4. The spooling programs - lpd, lprq, and lprrm - run setuid to root and setgid to group daemon to access spool files and printers.
  5. The printer server, lpd, uses the same verification procedures as rshd in authenticating remote clients. The host on which a client resides must be present in the file /etc/hosts.equiv or /etc/hosts.lpd and the request message must come from a reserved port number.

Setting up /etc/printcap

The real work in setting up is to create the /etc/printcap file and any printer filters you'll need for specific hardware.

Creating a /etc/printcap file

The /etc/printcap database contains one or more entries per printer. A printer should have a separate spooling directory. If it doesn't, jobs will be printed on different printers depending on which printer daemon starts first.

Printers on serial lines

When a printer is connected via a serial line it must have the proper baud rate and terminal modes set. The following example is for a DecWriter III printer connected locally via a 1200 baud serial line.

  lp|LA-180 DecWriter III:\
    :lp=/dev/lp:br#1200:fs#06320:\
    :tr=\f:of=/usr/lib/lpf:lf=/usr/adm/lpd-errs:

The lp entry specifies the file name to open for output. The br entry sets the baud rate for the tty line and the fs entry sets CRMOD, no parity, and XTABS. The tr entry indicates that a formfeed should be printed when the queue empties so the paper can be torn off without turning the printer offline and pressing formfeed. The of entry specifies the filter program lpf should be used for printing the files (more will be said about filters later).

The last entry causes errors to be written to the file /usr/adm/lpd-errs instead of the console. Most errors from lpd are logged using syslogd and won't be logged in the specified file. The filters should use syslogd to report errors; only those that write to standard error output will end up with errors in the lf file.


Note: Sometimes errors sent to standard error output don't appear in the log file. The use of syslogd is therefore highly recommended.

Remote printers

Printers that reside on remote hosts should have an empty lp entry. For example, the following /etc/printcap entry would send output to the printer named ``lp'' on the machine ``ucbvax'':

  lp|default line printer:\
    :lp=:rm=ucbvax:rp=lp:sd=/usr/spool/vaxlpd:

The rm entry is the name of the remote machine to connect to; this name must be a known hostname for a machine on the network. The rp capability indicates that the name of the remote printer is ``lp'' (here it could be left out since this is the default value). The sd entry specifies /usr/spool/vaxlpd as the spooling directory instead of the default value of /usr/spool/output/lpd.

Output filters

Filters are used to handle device dependencies and accounting functions. The output filtering of is used when accounting isn't being done or when all text data must be passed through a filter. This filer isn't intended to do accounting since it's started only once, all text files are filtered through it, and no provision is made for passing owners' login names, for identifying the beginning and end of jobs, etc.

The other filters (if specified) are started for each file printed and do accounting if there's an af entry. If entries for both of and other filters are specified, the output filter is used only to print the banner page; it's then stopped to allow other filters to access the printer.

An example of a printer that requires output filters is the Benson-Varian:

  va|varian|Benson-Varian:\
    :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\
    :tf=/usr/lib/rvcat:mx#2000:pl#58:px=2112:py=1700:tr=\f:

The tf entry specifies /usr/lib/rvcat as the filter to be used in printing troff output. This filter is needed to set the device into print mode for text and into plot mode for printing troff files and raster images. Note that the page length is set to 58 lines by the pl entry for 8.5 x 11-inch fan-fold paper. To enable accounting, the varian entry would be augmented with an af filter:

  va|varian|Benson-Varian:\
    :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\
    :if=/usr/lib/vpf:tf=/usr/lib/rvcat:af=/usr/adm/vaacct:\
    :mx#2000:pl#58:px=2112:py=1700:tr=\f:

Output filter specifications

Filters are spawned by lpd; their standard input is the data to be printed, standard output is the printer. The standard error is attached to the lf file for logging errors (or syslogd may be used). A filter must return a 0 exit code if there were no errors, 1 if the job should be reprinted, and 2 if the job should be thrown away.

When lprrm sends a kill signal to the lpd process controlling printing, it sends a SIGINT signal to all filters and descendants of filters. This signal can be trapped by filters that need to do cleanup operations such as deleting temporary files.

Arguments passed to a filter depend on its type. The of filter is called with the following arguments:

  filter -wwidth -llength

The width and length values come from the pw and pl entries in the /etc/printcap database. The if filter is passed the following parameters:

filter [-c] -wwidth -llength -iindent -n login -h host accounting_file

The optional -c flag is used only when control characters are to be passed uninterpreted to the printer (when using the -l option of lpr to print the file). The -w and -l parameters are the same as for the of filter. The -n and -h parameters specify the login name and hostname of the job owner. The last argument is the name of the accounting file from /etc/printcap. All other filters are called with these arguments:

  filter -xwidth -ylength -n login -h host accounting_file

The -x and -y options specify the horizontal and vertical page size in pixels (from the px and py entries in the /etc/printcap file). The rest of the arguments are the same as for the if filter.

Access control

Local access to queues is controlled with the rg printcap entry:

:rg=lprgroup:

Users must be in the group lprgroup to submit jobs to the specified printer. The default is to allow all users access. Note that once the files are in the local queue, they can be printed locally or forwarded to another host depending on the configuration.

Remote access is controlled by listing the hosts in either the file /etc/hosts.equiv or /etc/hosts.lpd, one host per line. Note that rsh and rlogin use /etc/hosts.equiv to determine which hosts are equivalent for allowing logins without passwords.

The file /etc/hosts.lpd is used only to control which hosts have line printer access. To further restrict remote access (i.e. allow only remote users with accounts on the local host to print jobs), use the rs printcap entry:

:rs:

Line printer administration

The lprc program provides local control over line printer activity. The program's major commands and their intended use are described here; the command format and remaining commands are described in lprc.

abort and start

The abort command terminates an active spooling daemon on the local host immediately and then disables printing (preventing new daemons from being started by lpr). This is normally used to forcibly restart a hung line printer daemon (i.e. lprq reports that a daemon is present but nothing is happening). The abort command doesn't remove any jobs from the queue (use lprrm instead). The start command enables printing and asks lpd to start printing jobs.

enable and disable

These commands allow spooling in the local queue to be turned on/off in order to allow/prevent lpr from putting new jobs in the spool queue. You may want to turn spooling off while testing new line printer filters, since the root user can still use lpr to put jobs in the queue (but no one else can). The other main use is to prevent users from putting jobs in the queue when the printer is expected to be unavailable for a long time.

restart

The restart command allows ordinary users to restart printer daemons when lprq reports that no daemon is present.

stop

The stop command halts a spooling daemon after the current job completes; this also disables printing. This is a clean way to shut a printer down for maintenance, etc. Note that users can still enter jobs in a spool queue while a printer is stopped.

topq

The topq command places jobs at the top of a printer queue. This can be used to reorder high-priority jobs, since lpr provides only first-come-first-served ordering of jobs.

Sample lpd configurations

You'll find four QNX lpd sample configurations in this section:

Example #1: a single printer

A local (node1) /etc/printcap (assuming the printer is /dev/par1):

lpt1:\
  :lp=/dev/par1:

This file is very short and basic. All it does is give the printer connected to /dev/par1 a name of lpt1. No other capabilities need to be described because the defaults will suffice for such a simple case.


Note: The spool directory (sd) must exist; it defaults to /usr/spool/output/lpd. Remember to use the -P option or set the PRINTER environment variable to lpt1 so the default /dev/lp won't cause a failure.

A remote (node2) /etc/printcap:

rlpt1:\
  :rm=node1:rp=lpt1:

This file specifies the remote host with the printer named lpt1 to be node1. The local name, rlpt1, is used by local clients and could be the same as the remote name lpt1.

Example #2: multiple printers

You should define multiple printers carefully, because the default capabilities won't be suitable for all printers. For example, the spool directory (sd) wisely restricts each printer to its own unique spool area.

The following example builds on the previous by adding another printer definition for host node1.

A local (node1) /etc/printcap:

lpt1:\
  :lp=/dev/par1:sd=/usr/spool/output/lpt1:

lpt2:\
  :lp=/dev/par2:sd=/usr/spool/output/lpt2:

This file specifies two printers:

A remote (node2) /etc/printcap:



lpt1:\
  :rm=node1:rp=lpt1:sd=/usr/spool/output/lpt1:

lpt2:\
  :rm=node1:rp=lpt2:sd=/usr/spool/output/lpt2:

Example #3: local and remote printers

From the previous example, lpt2 has been physically relocated to node2. Both /etc/printcaps on node1 and node2 will need to be changed. Likewise, the /etc/printcap on node3 will also need changing to reflect the different remote host (rm) for lpt2.

The /etc/printcap on node1:

lpt1:\
  :lp=/dev/par1:sd=/usr/spool/output/lpt1:

lpt2:\
  :rm=node2:rp=lpt2:sd=/usr/spool/output/lpt2:

The /etc/printcap on node2:

lpt1:\
  :rm=node1:rp=lpt1:sd=/usr/spool/output/lpt1:

lpt2:\
  :lp=/dev/par1:sd=/usr/spool/output/lpt2:

The /etc/printcap on node3:

lpt1:\
  :rm=node1:rp=lpt1:sd=/usr/spool/output/lpt1:

lpt2:\
  :rm=node2:rp=lpt2:sd=/usr/spool/output/lpt2:


Caution: The following example (#4) may be considered ``advanced'' - we recommend that you proceed with caution!

Example #4: inter-mixing lpsrvr/lpd

For proper cooperation, it's important that each physical device be controlled only by one print spooling server. This means that if lpd has direct access to /dev/par1 (like the node1 example above), then lpsrvr MUST NOT reference /dev/par1.

The following is a small /etc/config/lpsrvr.1 example that would forward print requests for the local queue to the lpd on node1 (from example 3):

[local]
  ta=null
  co=/usr/ucb/lpr -P lpt1 $(spfile)

[-null]
  dv=/dev/null

All other QNX nodes can now use lp instead of lpr to summit print jobs. This also means that only node1 requires a /etc/printcap configuration file. But with such a configuration, QNX nodes using lp won't be able to query or remove their spooled jobs once lpsrvr has passed them on to lpd.


Note: QNX nodes can still use lpd (lpr) like before, but those that do require their own specific copy of /etc/printcap.

To switch the ownership, or controlling server, to be lpsrvr, you'll need to modify both /etc/printcap and /etc/config/lpsrvr.1:

  1. Remove the co operation and change the dv device to /dev/par1 in the lpsrvr.1
  2. Change the lp capability in the lpt1 definition in /etc/printcap to reference a pseudo-device owned by lpsrvr. Note that lpsrvr creates a pseudo-device for each queue it manages under the /dev/spool directory. Writing to this device is equivalent to submitting a job using the lp utility.

Here are the modified files:

/etc/config/lpsrvr.1

[local]
  ta=real

[-real]
  dv=/dev/par1

Node1 /etc/printcap

lpt1:\
  :lp=/dev/spool/local:sd=/usr/spool/output/lpt1:

lpt2:\
  :rm=node2:rp=lpt2:sd=/usr/spool/output/lpt2:

With this configuration, all QNX nodes can submit jobs to lpsrvr and query/remove them. Clients who submit jobs to lpd loose the ability to query/remove them once lpd has passed the jobs on to lpsrvr.

Troubleshooting

lpr error messages

lpr: filename: copyfile is too large
The submitted file was larger than the printer's maximum file size, as defined by the mx capability in its printcap entry.
lpr: printer: unknown printer
The printer wasn't found in the /etc/printcap database; could be a typo or a missing or incorrect entry in the /etc/printcap file.
lpr: printer: jobs queued, but cannot start daemon
The connection to lpd on the local machine failed, probably because the printer server has died or is hung. A superuser can restart lpd: /usr/ucb/lpd. You can also check the state of the master printer daemon: sin -P lpd. Another possibility is that lpr isn't setuid to root and setgid to group daemon. You can check with: ls -lg /usr/ucb/lpr.
lpr: printer: printer queue is disabled
This means the queue was turned off with: lprc disable printer to prevent lpr from putting files in the queue. This is usually done when a printer is going to be down for a long time. A superuser can turn the printer back on with lprc.

lprq error messages

waiting for printer to become ready (offline ?)
The daemon couldn't open the printer device. This can happen for several reasons: the printer is offline, out of paper, the paper is jammed, etc. The actual reason depends on the meaning of error codes returned by the system device driver. Not all printers supply enough information to distinguish when a printer is offline or having trouble (e.g. a printer connected through a serial line). Another possible cause of this message is that some other process, such as an output filter, has an exclusive open on the device. Your only recourse here is to kill off the offending program(s) and restart the printer with lprc.
printer is ready and printing
The lprq program checks to see if a daemon process exists for printer and prints the file status located in the spooling directory. If the daemon is hung, a superuser can use lprc to abort the current daemon and start a new one.
waiting for host to come up
This implies there's a daemon trying to connect to the remote machine named host to send the files in the local queue. If the remote machine is up, lpd on the remote machine is probably dead or hung and should be restarted as mentioned for lpr.
sending to host
The files should be in the process of being transferred to the remote host. If not, the local daemon should be aborted and started with lprc.
Warning: printer is down
The printer has been marked as being unavailable with lprc.
Warning: no daemon present
The lpd process overseeing the spooling queue, as specified in the ``lock'' file in that directory, doesn't exist. This normally occurs only when the daemon has unexpectedly died. The error log file for the printer and the syslogd logs should be checked for a diagnostic from the deceased process. To restart an lpd, use: % lprc restart printer.
no space on remote; waiting for queue to drain
This implies that there isn't enough disk space on the remote. If the file's large enough, there will never be enough space on the remote (even after the queue on the remote is empty). The solution here is to move the spooling queue or make more free space on the remote.

lprrm error messages

lprrm: printer: cannot restart printer daemon
This case is the same as when lpr prints that the daemon can't be started.

lprc error messages

couldn't start printer
This case is the same as when lpr reports that the daemon can't be started.
cannot examine spool directory
Error messages beginning with ``cannot...'' are usually because of incorrect ownership or protection mode of the lock file, spooling directory, or the lprc program.

lpd error messages

The lpd program can log many different messages using syslogd. Most of these messages are about files that can't be opened and usually imply that the /etc/printcap file or the protection modes of the files are incorrect. Files may also be inaccessible if people manually manipulate the line printer system (i.e. they bypass the lpr program).

In addition to messages generated by lpd, any of the filters that lpd spawns may log messages to the syslog file or to the error log file (the file specified in the lf entry in /etc/printcap).