11.4.3.3.2 Command Identifiers for LPD defined in RFC

11.5 Filters

Filters in UNIX are generally programs that read from standard in (stdin), and write to standard out (stdout), and somewhere in the middle modify the data in some way. Filters can be run directly from the command line, from a shell script, or from within a virtual printer. This section will cover how to use a filter from a virtual printer, and some of the details on filters available with AIX.

In AIX Version 4 Info Explorer there is a sample C filter for adding carriage returns to line feeds.

11.5.1 AIX Filters

The filters that are part of AIX are shown in Table 19.


Table 19: AIX Filters

Filters are generally setup in a virtual printer to run before the data goes to the formatting pipeline. You can implement a filter even when the virtual printer is set in pass through mode and when it does not use either the ci (initialization) or cr (reset) sequences.

Filters are the first programs in the input data stream processing pipeline set up by piobe that have an opportunity to selectively manipulate the data stream. A particular filter can be selected from the command line on a per-job basis, or permanently selected by modifying the virtual printer definition.

The qprt command uses the -f flag to select a particular filter on a per-job basis. The argument to the -f flag is the second letter of the two letters that name the filter attribute in the virtual printer definition. For instance, to select the pr filter for a job on an ASCII queue named asc on an IBM 4029 LaserPrinter, you could issue the command:

qprt -Pasc -fp /etc/motd

The filter attribute that selects the pr filter is named fp, so the argument to the -f flag is just p, the second letter.

To permanently select the pr filter, use lsvirprt to edit the virtual printer definition and set the value of the _f attribute to p. The _f attribute selects a filter that will be used to pre-process any job submitted to the queue associated with this virtual printer definition.

Since the lp, lpr, and qprt commands are all just front ends to the enq command, the true entry point to the spooler, you would assume that enq must support the -f flag. If you issue the enq command with the -f flag, however, you will receive an error message as follows:

# enq -f
enq: Not a recognized flag: f

This is a situation where the previously described technique of mounting /bin/echo over /bin/enq proves useful.

The root user can issue the following commands from a shell prompt:

  1. mount /bin/echo /bin/enq

  2. # qprt -Pasc -fp /etc/motd
    -P asc -o -f -o p /etc/motd
    

  3. umount /bin/enq

After the second command is issued the element defined by your TERM environment variable is displayed, as shown in step 2, above.

These are the arguments qprt tried to pass to enq. You get to see them because qprt found echo instead of enq. The following command is equivalent to the command shown in step 2 previously:

enq -P asc -o -f -o p /etc/motd

The -o option specifies that flags specific to the backend should be passed to the backend. The -o option can be thought of as a free pass through the syntax checking that occurs before the enq command builds a job description file and notifies the qdaemon of the existence of a new job.

11.5.1.1 Using Filters

In this section you will look at an example of a filter that maps linefeeds to carriage returns and linefeeds.

Many users have written or purchased applications that prepare data streams to fill in the blanks on pre-printed checks, invoices, bills-of-lading, or other forms. Printing these data streams requires precise control of the physical printer. It is often the case that the job processing pipeline created by piobe inserts or deletes enough data from the original data stream that the output data no longer falls at the proper position on the pre-printed form.

The root user can frequently use lsvirprt to set the value of the _d attribute in the virtual printer definition top. On an ASCII queue on an IBM 4029 Laser Printer, this would cause piobe to select the IP pipeline to process the job. The IP pipeline is for passthrough printing, which means that the formatter filters use the passthru() routine to simply pass the input data stream through to the printer without modification.

This frequently removes all the printer control problems that existed, but adds one new one. When the formatter filter operates in passthrough mode, the mapping of linefeeds to carriage returns and linefeeds is disabled. The forms still do not print correctly.

Supposing that the application does not allow the insertion of carriage returns into the data stream, you can fix this problem with a simple filter, as follows:

#include <stdio.h>
main(int argc, char **argv)
{
int ch;
while (EOF != (ch = fgetc(stdin)))
 {
  switch (ch)
   {
    case 10: fputc(ch,stdout);
             fputc(0x0D,stdout);
             break;
    default: fputc(ch,stdout);
             break;
   }
 }
}

Compile this and name it cr_mapper and install it somewhere accessible, such as /usr/lib/lpd. Assign it ownership of root.printq and permissions 555.

Assuming you have an ASCII queue named asc on an IBM 4029 Laser Printer, in AIX 4 you can use lsvirprt to select the asc queue and then format the f1 filter attribute. You should see something like the following:

User defined filter 1
f1 =

As the f1 attribute has a null default value, the definition is sparse.

Edit the f1 attribute so its definition appears as follows:

User defined filter 1
f1 =
 '/usr/lib/lpd/cr_mapper'

When you save the new definition of f1, you can again format it with lsvirprt. you should see something like the following:

User defined filter 1
f1 = /usr/lib/lpd/cr_mapper
 '/usr/lib/lpd/cr_mapper'

The f1 filter can now be used from the command line by using commands such as:

qprt -Pasc -f1 filename
enq -Pasc -o -f -o 1 filename

If the _d attribute was not set to p, the -dp flag and argument would have to be added to the commands as follows:

qprt -Pasc -dp -f1 filename
enq -Pasc -o -d -o p -o -f -o 1 filename

The cr_mapper program reads characters from stdin and writes them to stdout. Whenever it reads and writes a line feed (a hex A, or decimal 10), it writes out a carriage return (a hex D).

11.6 Clearing and Preventing Queue Hangs in AIX