All virtual printer definitions contain an attribute named mo. The mo attribute specifies the command string to invoke the device driver interface program. The device driver interface program is the last process in the input data stream processing pipeline and, in the case of local spooler queues with piobe as the backend, is usually pioout. It is named the device driver interface program because, as the last process in the pipeline, it generally opens the device driver for writing and then writes the processed input data stream to the device driver. See Datastream Flow for Common Print Jobs for additional information.
One of the useful features of the base operating system spooler is that its design allows the root user to replace pieces of the input data stream processing pipeline with user-written code. In this article an example of redefining the mo attribute, whose default value is the full path of pioout, to the full path of a user-written delivery program will be discussed. See Overview of Backend Processing for more information.
Suppose that you have an IP-addressable terminal server attached to your Ethernet network. The terminal server has some number of asynchronous ports to which you can attach ASCII terminals, modems, printers, or other asynchronous devices. Further suppose that the terminal server vendor supplied you with a program, named ts_print, that has the following properties:
(Clearly this is not a particularly hypothetical scenario.)
To turn this into a specific example, suppose that you have an IBM 4029 LaserPrinter that you want to attach to port 11 on the terminal server and that the terminal server's IP address is 220.127.116.11. Your goal is have a queue on a print server to which users can submit ASCII jobs and have them printed on the 4029 on the terminal server. Though you can use ts_print from the command line, you would prefer to make use of the formatter filter's ability to perform extensive manipulation of both the printer's mode and the input data stream. Providing true serial access to the printer is also a goal.
There is more than one way to accomplish this goal. The easiest way involves making a local ASCII queue on a normal file, instead of on a character-special file in the /dev directory. After you create the queue and the associated virtual printer, you can modify the virtual printer to use ts_print.
To begin the queue creation process, type the SMIT fast path smit mkquedev. A menu similar to the following displays:
Add a Print Queue
Move cursor to desired item and press Enter. Use arrow keys to scroll.
# ATTACHMENT TYPE DESCRIPTION local Printer Attached to Local Host remote Printer Attached to Remote Host ascii Printer Attached to ASCII Terminal hpJetDirect Network Printer (HP JetDirect) file File (in /dev directory) other User Defined Backend
Choose the file option, then choose a printer type. After you choose the IBM 4029 LaserPrinter (or whatever is correct for your situation), provide the name of an existing file in the /dev directory. This is the file to which processed jobs submitted to the queue you are creating are written. The name of the file can be anything that adheres to the base operating system naming conventions. A reasonable action is to create a file just for the purpose of being the target of file queues. For instance, the root user can issue the command touch /dev/lxx to create a file named lxx in the /dev directory.
After you provide the name of a file in the /dev directory, choose a queue name for each input data stream supported by the printer type you selected earlier. In this example, suppose the name asc was chosen for an ASCII queue. An entry like the following would appear in /etc/qconfig:
asc: device = lxx lxx: file = /dev/lxx header = never trailer = never access = both backend = /usr/lib/lpd/piobe
Any print job submitted to the spooler queue asc is processed by the pipeline set up by piobe. The processed data stream is written to /dev/lxx. This is not what you want to happen. Since the goal is to have ts_print write the output to port 11 on the terminal server, there should in fact not even be a file associated with this queue. To this end, edit the new stanza pair in /etc/qconfig and change the value of the file parameter to FALSE, like this:
asc: device = lxx lxx: file = FALSE header = never trailer = never access = both backend = /usr/lib/lpd/piobe
If you use this queue in this state, you do not see anything written to a file or printed anywhere, except maybe for error messages. When the qdaemon sets the backend, piobe, into execution, it passes piobe an open file descriptor based on the value of the file parameter in /etc/qconfig. When that value is set to FALSE, the file descriptor is not passed. The eventual recipient and user of the file descriptor is whatever program is pointed to by the mo attribute. The default program pointed to by the mo attribute is pioout and, when jobs are put on the queue when it is in this state, pioout will not have a valid value for stdout, and the processed job will simply vanish.
At this point, you can use lsvirprt to select the asc virtual printer definition for modification (Viewing, Formatting, or Modifying Virtual Printer Definitions). A prompt similiar to the following displays:
To LIST attributes, enter AttributeName1 ... (* for all attributes) To CHANGE an attribute value, enter AttributeName=NewValue To FORMAT and EDIT an attribute value, enter AttributeName~v To EDIT the attribute file, enter ~v To terminate, press Enter:
Assuming the ts_print program was installed in /usr/bin, enter the following at the prompt:
mo=/usr/bin/ts_print -A 18.104.22.168 -P 11
Jobs submitted to the asc queue will now be processed as if they were local jobs but, when the end of the pipeline is reached, the ts_print program will deliver the output data stream to port 11 on the terminal server instead of pioout delivering it to a device driver.
In general, the mo attribute in the virtual printer definition for a queue with piobe as the backend can be redefined to deliver a processed data stream to any file or device the user chooses, provided the you can write the code to do it.