The LPRng package is an enhanced version of the BSD LPD print spooling system. It was initially developed in the early 1990s by PatrickPowell, first as a rewrite of the LPD spooler that was free of the licensing problems of the original code. Very quickly, however, it began to develop beyond the original LPD capabilities, and it is now a feature-rich version of the original. LPRng is available for virtually any Unix system. The home page for the project is http://www.lprng.com.
Using LPRng does require knowledge of the standard BSD printing subsystem, so you'll need to become familiar with it if your previous experience is mostly with the System V and/or AIX version.
LPRng provides the usual BSD-style user commands: lpr, lpq, and lprm. In addition, it provides versions of lp, lpstat, and cancel for compatibility. It uses the conventional top-level spool directory, /var/spool/lpd.
The LPRng version of lpr is quite a bit smarter than the standard version. It is capable of submitting print jobs directly to a remote system, so there is no longer any need to run the lpd daemon on hosts that are not also print servers themselves (eliminating its modest system load).
Here is an lpr example, which spools a print job directly to the matisse queue on system painters:
$ lpr -Pmatisse@painters files
Another nice feature of LPRng is that lpd may optionally be run as the daemon user rather than root.
Installing LPRng is straightforward and well documented in both the LPRng-HOWTO document and in the Network Printing book mentioned earlier, so I'll simply outline the steps here:
The LPRng package provides scripts for some operating systems, which can accomplish some of these tasks. They have names of the form preremove.*.sh (to shut down the printing subsystem before removing it), preinstall.*.sh (remove old printing system components), postremove.*.sh (performs actions needed after the old printing system is removed), and postinstall.*.sh (runs after the LPRng software is built and installed; sets up initial configuration files, spooling directories and the like). The middle component of each script name is the operating system name: e.g., solaris, linux, etc. Check the LPRng package directory and the documentation for the scripts applicable to your systems.
13.6.1 Enhancements to the lpc Command
The LPRng version of lpc provides many new subcommands. The most important are summarized in Table 13-6.
In most cases, you can substitute the keyword all for a queue name in these lpc subcommands to apply the command to all print queues.
188.8.131.52 Print classes and job priorities
LPRng implements a very simple print job priority scheme. It is combined with its support for print job classes: print jobs have a shared set of characteristics that require specific special handling and/or printer capabilities. The most common use for classes is for jobs requiring special paper.
A user can place a job into a specific class when submitting it using the -C option:
$ lpr -Ccheck -Plaser2 January
This job is placed into the class check on printer laser2.
The uppercased first letter of the class name is also used as the in-queue priority for the job. Priorities levels run from A (high) to Z. Thus, the preceding job would be assigned a priority level of C. The default value for jobs not specifying a specific class is class and priority level A.
By default, a print queue allows jobs of any class to print, printing them in accord with the priority scheme. To limit printing to a specific class, use an lpc command like this one:
# lpc class laser check
This will allow only jobs in class check to print; all others will be held. To allow any job to print, use this command:
# lpc class laser off
Using classes can be a bit tricky. For example, if you alternate between printing checks and regular output on a printer, you probably don't want to turn off class check after all the checks are printed. Rather, you want check jobs to be held until the proper paper is again in place in the printer. In this case, the following command will be more effective:
# lpc class laser A
This sets the allowed class to class A (the default), so jobs spooled in class check will be held as desired.
13.6.2 Configuring LPRng
LPRng uses three configuration files (stored in /etc): printcap, lpd.conf , and lpd.perms , which hold queue configuration, global spooler configuration and printer access rules, respectively. The first of these is a modified version of the standard LPD printcap file. It uses a relaxed syntax: all fields use an equal sign to assign values rather than having datatype-specific assignment characters (although the form name@ is still used to turn off Boolean flags), multiple line entries do not require final backslash characters, and no terminal colon is needed to designate field boundaries.
Here are two simple entries from printcap:
hp: Example local printer. :lp=/dev/lp0 :cm=HP Laser Jet printer Description for lpq command. :lf=/var/log/lpd.log :af=/var/adm/pacct :filter=/usr/local/lib/filters/ifhp :tc=.common Include the .common section. laser: Example remote printer. :lp=painters@matisse :tc=.common Include the .common section. .common: Named group of items. :sd=/var/spool/lpd/%P :mx=0
The first entry is for a local printer named hp on the first parallel port. This printcap entry specifies a description for the printer, the name of its log and accounting files, and a filter with which to process jobs. The final field, tc, provides an "include" feature within printcap entries. It takes a list of names as its argument. In this case, the field says to include the settings in the printcap entry called .common within the current entry. Thus, it has the effect of removing any length limits on print jobs to printer hp and of specifying its spool directory as /var/spool/lpd/hp.
The second printcap entry creates a queue for a remote printer, matisse on host painters, which also has no job length limits and uses the spool directory /var/spool/lpd/laser. The last two items are again set using the tc include field.
The LPRng printcap file allows for variable expansion within printcap entries. We saw an example of this in the sd field in the preceding example. The following variables are supported:
We will now go on to consider additional LPRng features and the printcap settings that support them.
184.108.40.206 Separate client and server entries
By default, printcap entries apply both to spooling system clients user programs like lpr and servers the lpd daemon. However, you can specify that an entry apply only to one of these contexts, as in these example entries:
laser:server Entry applies to the lpd daemon. :lp=/dev/lp0 laser: Entry applies to client programs. :lp=matisse@painters
The first entry defines the printer laser as the device on the first parallel port. The server field indicates that the entry is active only when lpd is using the printcap file (and not when it is accessed by programs like lpr). The second entry defines the printer laser for client programs as a remote printer (matisse on painters). Clients will be able to send jobs directly to this remote printer.
In this next example, clients are required to use the local print daemon in order to print to the printer laser2:
laser2:force_localhost Force clients to use the local server. laser2:server :lp=/dev/lp0 :sd=/var/spool/lpd/%P
The force_localhost setting (a Boolean, which is off by default) tells clients accessing this printcap entry to funnel jobs through the local lpd server process.
220.127.116.11 Using a common printcap file for many hosts
One of LPRng's most powerful capabilities is the built-in features for constructing a single central printcap file which can be copied to or shared among many hosts. This flexibility comes from the on setting (for "on host"). Here is an example:
laser: :oh=*.ahania.com,!astarte.ahania.com :lp=/dev/lp0
This entry defines a printer named laser on every host in the domain ahania.com except astarte. The printer will always be located on the first parallel port.
The following entry will define a printer named color on every host in the 10.0.0 subnet. For most hosts, the printer points to the color queue on 10.0.0.4, while for 10.0.0.4 itself, it points to the device on the first parallel port.
color: :oh=10.0.0.0/24,!10.0.0.4 Host specification by IP address. :lp=%P@10.0.0.4 :tc=.common color: :oh=10.0.0.4 :lp=/dev/lp0 ...
The %P construct in the first entry's lp setting is not really necessary here, but it would be useful if this setting occurred in a named group of settings, as in this example:
color:tc=.common laser:tc=.common draft:tc=.common .common: :oh=*.ahania.com,!astarte.ahania.com :lp=%P@astarte.ahania.com
These entries define the printers color, laser, and draft on every host in ahania.com except astarte as the corresponding queue on astarte (which are defined elsewhere in the printcap file).
18.104.22.168 Special-purpose queues
In this section, we examine how to set up queues for several more complex printing scenarios.
22.214.171.124.1 Bounce queues
Here is a printcap entry for a simple store-and-forward queue (as we've seen before):
laser:server :lp=matisse@painters :sd=/var/spool/lpd/%P
The queue laser collects jobs and sends them on to the queue matisse on host painters as is. However, it is sometimes useful to process the jobs locally before sending them on to be printed. This is accomplished via a bounce queue, as in this example:
blots:server :sd=/var/spool/lpd/%P :filter=path and arguments :bq_format=l Binary jobs will be sent on. :bq=picasso@painters
This queue named blots accepts jobs, runs them through program specified in the filter setting, and then sends them to queue picasso on host painters for printing.
126.96.36.199.2 Printer pools
LPRng allows you create aprinter pool: a queue that feeds several printing devices, as in this example:
scribes:server :sd=/var/spool/lpd/%P :sv=lp1,lp2,lp3
Here, the queue scribes sends jobs to queues lp1, lp2, and lp3 (which must be defined elsewhere in the printcap file), as each queue becomes free (which, of course, occurs when the associated device is free). This mechanism provides a very simple form of load balancing.
Here is part of the printcap entry for lp1:
lp1: :sd=/var/spool/lpd/%P :ss=scribes
The ss setting specifies the controlling queue for this printer. Note that it does not prevent jobs from being sent directly to queue lp1; the only effect of this setting seems to be to make queue status listings more readable.
Print job destinations can also be determined on a dynamic basis. Here is an example:
smart: :sd=/var/spool/lpd/%P :destinations=matisse@printers,degas@france,laser :router=/usr/local/sbin/pick_printer
The program specified in the router setting is responsible for determining the destination for each submitted print job. The router program is a standard print filter program. Its exit status determines what happens to the job (0 means print, 37 means hold, and any other value says to delete the job), and it must write the queue destination and other information to standard output (where lpd obtains it). See the LPRng-HOWTO document for full details on dynamic print job routing.
As we've noted before, print jobs are processed byfilter programs before they are sent to the printer device. Filters are responsible for initializing the device to a known initial state, transforming the output into a form that it understood by the printer, and ensuring that all output has been sent to the printer at the end of the job. The first and third tasks are typically accomplished by adding internal printer commands to the beginning and end of the print job. Filter programs are also responsible for creating printer accounting records.
As the examples we've looked at have shown, LPRng provides the filter printcap setting for specifying a default filter for all jobs in a particular queue. In addition, it supports many of the various output type-specific filter variables used in traditional printcap entries (i.e., the *f settings).
The LPRng package often uses the ifhp filter program also written by Patrick Powell. It is suitable for use with a wide variety of current printers. The characteristics of the various supported printers are stored in its configuration file, ifhp.conf (usually stored in /etc). The following printcap entry illustrates settings related to its use:
lp: :sd=/var/spool/lpd/%P :filter=/usr/local/libexec/filters/ifhp :ifhp=model=default
The filter setting specifies the path to ifhp, and the ifhp setting specifies the appropriate printer definition with its configuration file. In this case, we are using the default settings, which work well with a wide variety of printers.
The LPRng facility includes an excellent Perl script that demonstrates the method for getting page count information from modern printers. It is called accounting.pl and is included with the source distribution.
188.8.131.52 Other printcap entry options
It is also possible to store printcap entries in forms other than a flat text file. For example, they could be stored in an LDAP directory. LPRng allows for such possibilities by allowing printcap entries to be fetched or created dynamically as needed. This is accomplished by setting the printcap_path in the lpd.conf configuration file as a pipe to a program rather than a path to a printcap file:
Such an entry causes LPRng to execute the specified program whenever it needs a printcap entry (the desired entry is passed to the program as its standard input). For example, such a program could retrieve printcap information from an LDAP directory. See Chapter 11 of Network Printing for details and extended examples.
13.6.3 Global Print Spooler Settings
The lpd.conf configuration file holds a variety of settings relating to the print spooler service. Among the most important are ones related to printer connection and timeouts and to print job logging. Some of the most commonly used are listed in the example configuration file below:
# communication-related settings connect_grace=3 Wait period between jobs (default=0). network_connect_grace=3 connect_timeout=600 Cancel job after this interval (default=0). send_try=2 Maximum number of retries (default is no limit). max_servers_active=10 Max. # lpd child processes (default is half the system process limit). # logging settings max_log_file_size=256 Maximum file sizes in KB (default is no limit). max_status_size=256 min_log_file_size=128 Keep this much data when the files are too big min_status_size=64 (default is 25%). max_status_line=80 Truncate entries to this length (default=no limit). # central logging server logger_destination=scribe Destination for log file entries. logger_pathname=/tmp/lprng.tmp Local temporary file to use. logger_max_size=1024 Max. size of the temporary file (default=no limit). logger_timeout=600 Wait time between connections to the remote server (default is whenever data is generated).
13.6.4 Printer Access Control
The third LPRng configuration file, lpd.perms, is used to control access to the print service and its printers. Each entry in the file provides a set of characteristics against which potential print jobs are matched and also indicates whether such jobs should be accepted. The first entry that applies to a specific print job will be used to determine its access. Accordingly, the order of entries within the file is important.
The syntax of the lpd.perms file is explained best by examining some examples. For example, these entries allow users to remove their own print jobs and root to remove any print job:
ACCEPT SERVICE=M SAMEUSER ACCEPT SERVICE=M SERVER REMOTEUSER=root REJECT SERVICE=M
The first keyword in an entry is always ACCEPT or REJECT, indicating whether matching requests are to be performed. These entries all apply to the M service, which corresponds to removing jobs with lprm. The various entries allow the command to succeed if the user executing and the user owning the print jobs are the same (SAMEUSER), or if the user executing it is root (REMOTEUSER=root) on the local system (SERVER). All other lprm requests are rejected.
Available SERVICE codes include C (control jobs with lpc), R (spool jobs with lpr), M (remove jobs with lprm), Q (get status info with lpq), X (make connection to lpd), and P (general printing). More than one code letter can be specified to SERVICE.
There are several keywords that are compared against the characteristics of the print job and the command execution context:
The preceding keywords all take a string or list of strings as their arguments. These items are interpreted as patterns to be compared to the print job or command characteristics.
We'll now examine some additional lpd.perms entries. The following entry rejects all connections to the lpd server that originate outside the ahania.com domain or from the hosts dalton and hamlet:
REJECT SERVICE=X NOT REMOTEHOST=*.ahania.com REJECT SERVICE=X REMOTEHOST=dalton,hamlet
Note that these entries could not be formulated as ACCEPTs. Hosts may be specified by hostname or by IP address.
The following entries allow only members of the group padmin to use the lpc command on the local host:
ACCEPT SERVICE=C SERVER REMOTEGROUP=padmin REJECT SERVICE=C
The LPC keyword can be used to limit the lpc subcommands that can be executed. For example, the following entry allows members of group printop to hold and release individual print jobs and move them around within a queue:
ACCEPT SERVICE=C SERVER REMOTEGROUP=printop LPC=topq,hold,release
The following entries prevent anyone from printing to the printer test except user chavez:
ACCEPT SERVICE=R,M,C REMOTEUSER=chavez PRINTER=test REJECT SERVICE=* PRINTER=test
User chavez can also remove jobs from the queue and use lpc to control it.
The following command prevents print job forwarding on the local server:
REJECT SERVICE=R,C,M FORWARD
The DEFAULT keyword is used to specify a default action for all requests not matching any other configuration file entry:
# All everything that is not explicitly forbidden. DEFAULT ACCEPT
The default access permissions in the absence of an lpd.perms file is to accept all requests.
184.108.40.206 Other LPRng capabilities
LPRng has quite a few additional capabilities which space constraints prevent us from considering, including the ability for more sophisticated user authentication using a variety of mechanisms, including PGP and Kerberos. Consult the LPRng documentation for full details.