Integrating under Solaristm; LP

Norman A. Jacobs
Sun Microsystems, Inc.

Background

On occasion, third party developers and customers find a need to integrate support for a new printer, or a need to perform some new data transformation under LP. When doing so, they read through the available documentation in the AnswerBook under the Solaristm; Administrator's Guide. From there, they can get a basic understanding of how an LP server operates, but some of the important specifics are missing. Also, limitations and interface commitment levels are not described. This page attempts to provide a more complete description of LP server facilities, operation and integration.

Introduction

At the core of the ability to print under Solaristm; is a service referred to at the LP service. The LP service has changed considerably between the releases of Solaristm; 2.5.1, and Solaristm; 2.6. The changes between these releases include a significant architectural shift, as well as a philosophical shift. With these shifts came the reimplementation, replacement or elimination of faulty services with newer, more flexible and more efficient components. These change are primarily centered around the client side functionality and networking support. As of this writing, the LP server (lpsched) remains pretty much in tact. It is this server that is being highlighted here. All of the other work done to Solaristm; LP is described in a separate paper "Solaristm; Printing - Near Term Directions".

System Overview

The primary purpose of the Solaristm; LP server is to provide print spooling to users for dedicated print devices. This is done through the cooperation of a number of facilities under a single process. These facilities include a specialized queue manager, a filtering (data transformation/matching) interface, a backed (printer/communication) interface, a faulting interface, a alerting/notification interface, a media management interface, and more.  A number of simple illustrations will provide a better understanding of how the various LP server components hang together

Let's start with job submission.  When a request to print is made, the requester contacts the LP server (lpsched), with a copy of the print request.  The first this the scheduler does is take this request and validate that the request can be handled.  This is done by validating that the requester has access to the destination and that the data contained in the request can can be transformed into a format that the destination can handle.  Once the request has been validated, the server accepts the request and informs the
requester that it has done so.  From there, the real work begins.  If the request is already in a format that is acceptable to the destination device, or if the transformation to an acceptable format only requires slow filtering, then the job is placed in the destination's queue for printing.  However, if the transformation requires a slow filter to perform the transformation, the print job is placed in a filtering queue, so they can be transformed before being queued to the destination.  Once the job reaches the top of the destinations
print queue, the scheduler (lpsched) starts a child process to manage the printing of the job.  This child process in turn opens and locks the print device and starts child process to pass this open device and run the interface script.  It is the interface script that actually runs any fast filters and completes processing of the job.  At any time during this processing, the interface script can detect and report error conditions and recovery from error conditions.  This information is reported back to the scheduler using lp.cat.  Upon receipt of an error condition from the interface script, the scheduler will use the configured alerting mechanism for the destination to alert the administrator and/or user.  Upon receipt of an "all clear" from the interface script, the scheduler will terminate it's alerting and continue processing normally.

Interfaces

Filtering

The Solaristm; LP server supports two different types of print filters. The first type of filter are referred to as "slow" filters. Slow filters are intended to be used when the data transformation is likely to take longer than it will take to print the data. This filtering is run "out-of-band", before the print request is actually scheduled to print, so the printer isn't stuck waiting for the data to be transformed.

The second type of filtering available under LP is "fast" filtering. This type of filtering is intended to be used when direct interaction with the printer is required, or when the transformation is not likely to be a bottleneck. Fast filters run in-line, on the way to the printer.

Filters are configured under LP using the lpfilter(1M) command. This command takes in a filter description file and configures a filter under lpsched. The filter description file and it's format are described reasonably well in the Answerbook and on-line man pages.

When adding filters to a Solaristm; LP server, there are a couple of important things to understand. First and foremost, a filter will only run if it is required to run for the job to print. Second, filters may be required to run either to convert data to a format acceptable to a printer, or to fold in special required, options called modes.

For further information on writing and integrating filters, see the LP filters web page, lpfilter(1M) man page and/or LP Filtering web page, the lpfilter(1M) man page, and/or the System Administrators Guide in the Answerbook.

Back-end

One very important interface in the Solaristm; LP server is it's back-end interface. It is this interface that ultimately runs and communicates the print job to the printer. The interface itself is simply a call out to an external program. This program can be written in any language, compiled, interpreted, whatever. The most common method of implementing this program is via a shell script, because of this, the interface is generally referred to as an interface script.

An interface script has a variety of inputs. The first set of input are the command line arguments. These arguments supply the printer name, request-id, user, title, number of copies, an options list, and the list of files to print. With the exception of the options list, each of these pieces of information is supplied in a separate command line argument. The options list is supplied as a single command line argument, but it can contain multiple options.

Another input the the interface script is the calling environment. The lp server takes great care when constructing a calling environment for an interface script to run in. This environment contains information about character set the printer is to use, any fast filter that should be run in-line to the printer, localization information, printer type, time zone information, and a token to be used when communicating status back to the scheduler. Each of these pieces of information are stored in environment variables that can be accessed via getenv(3C) in C or $VARIABLE in most shell languages.

A critical, input to the interface script is actually the set of open files descriptors. When lpsched starts the interface script, it opens up the actual print device for the script and passes the opened device to the script as standard output. Standard error is actually an output. It is a back channel to lpsched that can be used to communicate error information back to the scheduler.

The last input to the interface script is an asynchronous input. That is, the input can be supplied to the interface script at any time while it is running. This input is supplied via signals. Actually, the only signal that will be supplied from the scheduler is the SIGTERM (15) signal. This signal is supplied when the scheduler wants the interface script to stop what it's doing and terminate. It is usually supplied when the scheduler is being shutdown, or someone is attempting to perform maintenance on the printer.

Along with all of the above inputs to the interface script, it can communicate information back to the scheduler via a couple of outputs. The first output, which is described above, is the ability to send text messages back to the scheduler via standard error. These messages are used, verbatim, as the printer status message for lpstat. The second output is the exit code of the interface script. The exit status of the interface script communicates whether the script completed successfully, it failed and the job should reprint, or it failed and the job should be tossed out.

For further information on interface scripts, how they work, and how to write them, see the Interface Script web page and/or the System Administrators Guide in the Answerbook.

Faulting

As mentioned above, when an error is detected while passing a print job to an output device, the interface script reports this error back to the scheduler.  This is done through the faulting interface.  The faulting interface is largely made up of a single program external to the scheduler.  This program, lp.tell, sends messages back from the interface script to lpsched using the scheduler's communication FIFO.  The messages contain a
type (fault, clear fault), destination, key, and some amount of textual information.  It is these messages that trigger the alerting/notification process in the scheduler.  As stated, lp.cat is the program that passes these messages to the scheduler.  lp.tell is a relatively simple program.  It is placed in the process pipeline by an interface script while communicating with the output device.  It reads back the status messages from the communication program (described below), makes a determination as to whether the message is an error or not, and send a message to the scheduler.

Alerting/Notification

Upon detection of an error condition or when user interaction is required, the LP server will attempt to perform a notification.  This notification is a simple call-out to an external program.  It is configured under LP using the lpadmin(1M) command.  Since alerting is done via a call-out, this program can perform any task.  Depending on the configuration, the notification can occur a single time or at X minute intervals while the error condition or requirement for user interaction persists.  An interesting example using audio alerts is provided in the PRINTtoys package.

For further information on writing and integrating notification programs, see the LP Notification web page, the lpadmin(1M) man page, and/or the System Administrators Guide in the Answerbook.

Forms (Media)

The LP server comes with built-in support for arbitrary preprinted media.  This media support, refered to as form support, allows end users to select the media they require loaded in the printer at the time a print job is printed.  By default, all print jobs have no media selection when submitted.  For a use to request a type of media, the must supply a media/form name using the '-f' option to lp when submitting the job.  Also, the server for the printer must have a defintion of the requested media, the destination must be allowed to mount the media, and the user must be allowed to use the media.  If the media isn't present on the destination at the time the job is ready to print, the LP server will hold the job and request an operator to mount the media on the destination.  Once mounted, the operator must use lpadmin(1M) to notifiy the LP server that the media has been placed in the printer.

For further information on integrating media/forms support, see the LP Forms web page, the lpadmin(1M) man page, lpforms(1M) man page, and/or the System Administrators Guide in the Answerbook.

Communication

Although, communication with the printer is handled via the back-end interface script, the interface scripts supplied with Solaristm; run one of three different programs to do the actual communication.  These three communication programs send print data to the output device and gather status where possible.  The program chosen to communicate with the printer depends on the interfaces script run and the type of printer being communicated with.
 

postio

The first program that may used to communicate with a printer is "postio".  Postio is used to communicate with PostScripttm; (PS, PSR) printers attached to a serial port or parallel port (BPP, SPIF, ECPP).  It is configured under the standard interface script and reports back errors via this interface script to lpsched.  The errors it reports depend largely on the connectivity to the printer.  If the printer is connected to a serial port, postio will send a '^t' PostScripttm; status request to the printer and retrieve the printer's response before each block of data is sent to the printer.  This has the effect of providing any error that the printer can generate.  If the printer is connected to a parallel port, postio assumes the connection to the printer is unidirectional.  Since it is believed to be unidirectional, the results of a '^t' status request could not be retrieved.  Instead, postio checks the pin status from the parallel port itself.  This allows postio to discern and return the following error conditions: power off, off-line, paper out, and busy.
 

lp.cat

lp/cat is used to communicate with all other locally attached printers.  It is also configured to run under the standard interface script and report back errors via this script.  Again, the errors detected and reported back depend on the type of connection to the printer.  If the printer is connected to a parallel port, it can return the same types of errors that postio did when it communicated with a printer on a parallel port.  If the printer is hooked up to a serial port, the reporting is essentially limited to "can't communicate with printer".  This is because many serially connected printers don't support any form of status request.  With the exception of PostScripttm; printers, those that do support a status request do so in a vendor specific manner.

Now, having said all of this, there is one small lie here.  A serial port is not always a serial port.  In some cases people build elaborate mechanisms to make their pie, pty, socket, driver, etc. appear to software as a tty.  Some simply push the ldterm streams modules on the stack.  If the device responds "correctly" to isatty(3C), it is considered a serial port by postio and lp.cat.  Both postio and lp.cat check if the endpoint type using the following:

    is is a BPP parallel port,   -> use the BPP port pin status
    is it an ECPP parallel port  -> use the ECPP port status
    is it a SPIF parallel port   -> use the SPIF port status
    is is a tty                  -> use '^t' status under postio (act like a dumb connection under lp.cat)
    it must be dumb.             -> just send data in blocks, if we hang, report an error
 

netpr

One final program that is used to communicate with printers is netpr.  netpr is new to Solaristm; 2.6 and allows the LP system communicate with network attached printers.  It is capable of sending job data to printers that implement the BSD Print protocol (RFC-1179) or printers that can take a straight TCP stream of print data.  This program is configured to run under the "netstandard" interface script, which is also new to Solaristm; 2.6.  As is the case with lp.cat communicating via a serial port, this  programs ability to detect and report more than rudimentary error conditions is limited.  Again, status results returned from network attached printers are generally returns using vendor specific mechanisms and/or formats.  It is this that limits netpr's error reporting to transport related errors only.
 
 

Which interfaces are Public?

Well, under Solaristm;, the only public printing related interfaces are those described in the SVID or XPG4.  These interfaces are lp(1), lpstat(1), and cancel(1).  They include client side functionality only.  That being said, any of the interfaces described here can be used to integrate support under the LP system with the understanding the interfaces will change or be removed eventually.  Actually, this proclamation was made with the release of Solaristm; 2.3.

Solaristm; is a registered trademark of Sun Microsystems Incorprated
PostScript  is a registered trademark of Adobe Systems Incorporated
Any other trademarks, service marks, etc that I may have inadvertently used are property of their respective owners.