Next Previous Contents

6. Filters

This section gives an overview of how LPRng uses filter programs, and gives a detailed discussion of how the printcap options and filters interact.

6.1 What are filters?

Print filters are one of the most powerful tools in BSD-style printer systems.

In general UNIX terms, a filter is a program that takes its input file(s), does something with it, and sends the result to its standard output. Most UNIX utilities are designed as filters. (But since you are a system manager, you should already know that :))

In the context of a BSD-style print spooler (and also LPRng), the term filter refers to a program that does processing on a file that is submitted to the printer. As such, it is a specific example of the general class of programs called `filters'.

Usually the filter is executed with STDIN reading from the file to be printed or program generating the output and STDOUT to the printer device. STDERR (file handle 2) is redirected to a log file, and file handle 3 to an accounting file.

A filter can be as simple as a LF to CR/LF translator (the example used before), or it can incorporate a complete accounting system, automatic file type translations, or even redirect the job to another printing system.

As part of the LPRng project, the following filters are supported. See the associated documentation for details.

The supported filters and other facilities are available from ftp://ftp.astart.com/pub/LPRng

6.2 What are print formats?

Options used:

LPRng has inherited a set of so-called `print formats' from its BSD ancestor. The format was originally used to specify the type of file that was being printed. The lpd daemon would use the print format to select the required filter for processing the file. The default format is f.

The user can specify the format (i.e., the file type) by giving the appropriate option to lpr:

Alternatively, one can also use -Fx, where x is the format specifier. (E.g., -Fc instead of -c.) This last form also allows you to use other (non-standard) format specifiers.

The filter for format X is the value for the Xf printcap option, with some minor exceptions. The following Xf options have a pre-defined meaning.

6.3 OF Filter

The of filter is used to process banners and job separators. The of filter is responsible for performing appropriate processing of this information and sending to the printer for action.

While the various file filters are invoked on a once per print file basis, the of filter is invoked on a once per print job basis.

This filter is the first one to be started, and should perform whatever specialized device initialization is needed. It should also do whatever accounting procedure is desired for start of job accounting.

The of filter will be given any banner printing or job separation information for a job. As part of its operation, it can detect a specific string, corresponding to a banner print request, and generate a banner. (See the Job Processing Steps and Printcap Options for details.)

During operation, the lpd server will send the special stop sequence of \031\001 to the of filter. The filter must then suspend itself using a kill -STOP operation. The lpd server will detect that the of filter has suspended itself and then will perform other printing operations.

After the other printing operations have been completed, the of will then be sent a kill -CONT signal.

This sequence will continue until all information has been printed, and then the of filter's STDIN will be closed. The filter will then perform whatever cleanup operations are needed, update accounting or other information, and exit.

6.4 The lpr -p format and pr option

Options used:

The -p format is implemented by sending the file through the program specified by the pr printcap utility (default is /bin/pr), and passing the result to the normal :if filter.

6.5 The lpr -l format and binary format

The binary (or literal) format is indicated by format type -l. The if filter is used to process the file, and is invoked with the -c (cancel processing?) flag.

6.6 Job Processing and Printcap Options

Much of the flexibility of the LPRng software is obtained from the ability to control the details of each step of job processing. The following section details each step in the processing of a job, and explains the printcap options used to control each operation.

Assume the pr printcap entry has the form:

pr
    :lp=/dev/lp  OR  :lp=rp@rm
    :sd=/var/spool/lpd/pr
    :lf=log
    :of=/usr/local/bin/lpf
    :if=/usr/local/bin/lpf

Assume that we have used the following command to print a set of files.

lpr -Ppr file1 file2

This will create a control file in the /var/spool/lpd/pr directory with the following contents (this is an example - in practice there may be minor differences between the example and an actual control file):

Hastart4.astart.com
J/tmp/file1 /tmp/file2
CA
Lpapowell
Ppapowell
fdfA002230astart4.astart.com
N/tmp/file1
UdfA002230astart4.astart.com
fdfB002230astart4.astart.com
N/tmp/file2
UdfB002230astart4.astart.com

Opening the Output Device

Options used:

Sequence of Operations:
  1. During the server operations, it will try to create temporary files in the print queue spool directory. If this is not desirable, it will create them in the server_tmp_dir directory.
  2. If the accounting file specified by af exists, it is opened (af_fd) and the af_fd is passed as file descriptor 3 to all filters. If the af value has the form af=|/program then the program is started and the program STDIN is used as af_fd. If the af value has the form af=host%port, then a TCP/IP connection to the corresponding port on the remote host is made and the port used as af_fd. In the latter two cases, the filter STDIN (file descriptor 0) is actualy opened read/write, and is used when information is needed from the accounting filter or remote server. See Accounting Printcap Options for more information on the LPRng accounting support.
  3. If the connect_grace value is non-zero and the server is opening a device or network_connect_grace is non-zero and a network connection is being made, the server will pause the specified time. This is to accommodate devices which need a recovery time between jobs.
  4. The lp option is checked to determine the type of IO device.

    Format
    Meaning
    /pathnameAbsolute pathname of IO device
    pr@hosttransfer to pr on remote host
    host%portopen a TCP/IP connection to port on host. host can be name or IP address
    |filterrun the filter program; it STDIN will be used as device
  5. The IO device specified by lp is opened write-only or read-write if the rw flag is true, and the resulting file descriptor is io_fd. If the nb flag is set, a non-blocking open will be done as well. If the lk (lock device) flag is true, the device will be locked against use by other LPD servers.
  6. If a host%port combination, a TCP/IP connection will be opened to the remote port and the connection will be used as io_fd.
  7. If a filter program is specified, the filter program will be run and the STDIN of the filter will be used as the device file descriptor.
  8. If a rp@rm combination, or none of the above combinations are true and the rm and rp values are non-zero, then the job will be transferred to a remote printer. The type of operation will be a job transfer, rather than printing operation.
  9. If the connect_timeout value is non-zero, a timeout is setup for the device or socket open. If the device or connection open does not succeed within the timeout, then the open operation fails.
  10. If a connection is to a network address (i.e. - connect() system call) and the connection attempt fails with an ECONNREFUSED error, if the retry_econnrefused flag is set then the connection attempt is retried, but this time using an alternative port number. See RFC1179 for details. This is repeated until all of the possible originating port numbers are exhausted.
  11. If the open or connect operation fails, and the retry_nolink flag is set, then the server will pause for a minimum of connect_grace plus a multiple of connect_interval seconds based on the number of attempts before retrying the open operation. Note that the interval may increase as the number of attempts increases.
  12. If printing a job and the of filter is specified, it is created with its STDOUT (fd 1) attached to the io_fd. Its stdin (of_fd) will be used in the steps listed below. If there is no of filter, then the of_fd value will be the io_fd descriptor.
  13. If transferring a job and the control_filter option is specified, then the program specified by the control_filter value will be run. It will have its STDIN set to the control file, and its STDOUT output will be used as the new value of the control file to transfer to the remote host. See Filter Command Line Flags for details of options passed to the control filter, and errorcodes for the exit codes of the filter.
  14. If la (local accounting) is true and we are printing a job or ar (remote accounting) is true and we are transferring a job, the as value is examined. If it is a filter (program) specification, then the program is started with its STDIN attached to /dev/null and STDOUT to the io_fd, STDERR to the error file, and file descriptor 3 to the accounting file descriptor af_fd. The lpd program will wait until it terminates, and examine the error code for action, as for the filters (see errorcodes below). If it is a string, then it is interpreted, the escape sequences replaced with the appropriate information, and written to the accounting file.
  15. If the achk (accounting check) flag is set, a line is read from the accounting filter af_fd file descriptor. This line should be accept, otherwise the job processing terminates with a JFAIL indication.
  16. If the operation is a job transfer, the operation proceeds as outlined in RFC1179, and then the Normal Termination operations are carried out.
  17. If the operation is a print operation and the ld (leader on open) value is provided, the string is translated (escapes removed) and written to the of_fd file descriptor.
  18. If the fo (form feed on open) flag is true, then the ff (form feed) string is translated (escapes removed) and written to the of_fd file descriptor.

Printing Banner At Beginning

Options used:

Sequence of Operations:
  1. If the sh (suppress header) flag is true, no banner is printed, and the actions in this section are skipped.
  2. If the hl flag is true, the banner is printed at the end of the job, and the actions in this section are skipped.
  3. If the user does not supply a banner name, (the L line in the control file) and ab (always print a banner) is false (the default), then no banner is printed. If no name is supplied and ab is true, then ANONYMOUS is used.
  4. There are two types of banners - short and long. If the sb flag is set, then we send the bl (banner line) contents directly to the of_fd; By default the bl value is: bl=$-'C:$-'n Job: $-'J Date: $-'t (See Filter Command Line Flags for details.) This will get translated to:
    papowell:A Job: file1 file2 Date: Thu Nov 27 23:02:04 PST 1997
  5. If the sb flag is clear, we will generate a long banner using a program instead. If bs (start banner) program is specified, then it is used to generate a banner, otherwise if the bp (banner) program is specified, then it is used to generate a banner. If no program is available, we skip the banner generation. The banner generator program is started with the normal command line flags (see Filter Command Line Flags), with its STDOUT attached to the of_fd descriptor. The short banner string described in the previous step is written to the STDIN. The banner printer is responsible for generating a banner appropriate to the printing device.
  6. The ff (form feed) string will be interpreted and sent to the of_fd.

Printing Job Files

Options used:

Sequence of Operations: for each job in listed in the control file, the following operations are done in turn.

  1. If there is an of filter present, the suspend string \031\001 is written to of_fd and the no further action is taken until the of filter is suspended.
  2. The control file line for the job is examined, and the first letter of the data file specification is used as the format.
  3. If the format is p, the job is first processed by the program specified by the pr program, and the program output used as the print file.
  4. If the format is f, l, or p then the if filter is used, otherwise the keyword Xf is used. Note that certain formats such as p, a, l, may not be used as formats.
  5. The direct_read flag determines how the print file is provided to the filter. Normally, the lpd writes the file to the filter process, and can monitor the printing activity in this way. However, some filters require a direct connection in order to do lseek or other operations on the file. If the direct_read flag is true, then the print file is opened and passed directly to the filter process, otherwise the lpd program will read the file and write its contents to the filter.
  6. The filter program is started with an appropriate set of command line options (see Filter Command Line Flags), and with its STDOUT attached to the printing device (io_fd), STDERR to the log file (lf), and file descriptor 3 to the accounting fd af_fd. If direct_read is false, the file is then written to the STDIN of the filter. This allows the server to monitor job progress.
  7. When doing a read/write operation to a device or remote system, a timeout can be specified. When doing a print or job transfer operation, the send_job_rw_timeout value is used. When doing a status or query operation, the send_query_rw_timeout value is used. If a write or write operation does not complete within the specified timeout seconds, then we have an error condition and job processing or the query operation is terminated with JFAIL status. If the timeout value is 0, then no timeout is done.
  8. lpd will then wait for the filter to exit. The exit status can be as follows:
    Key      Value   Meaning
    JSUCC    0       Successful
    JFAIL    1, 32   Failed - retry later
    JABORT   2, 33   Abort - terminate queue processing
    JREMOVE  3, 34   Failed - remove job
    JHOLD    6, 37   Failed - hold this job
    Other            Abort - terminate queue processing
    
  9. If the filter exit status was JSUCC (0), or no error indicated, then processing will continue otherwise the job termination takes (see Abnormal Termination).
  10. If the of filter is present, then it is reactivated with a kill -CONT signal.
  11. If the sf (suppress FF print file separators ) is false, then the ff (form feed) string will be interpreted and sent to the of_fd.

Printing Banner At End

Options used:

The actions taken in this step are identical to those for the Printing Banner At Beginning, with the exception that the be (end banner program) is used in the procedure rather than the bs (start banner program).

Normal Termination

Options used:

Sequence of Operations:

  1. If we are printing and the fq flag is set and the sf (suppress interfile FF) flag is set, then the ff (form feed) string will be interpreted and sent to the of_fd.
  2. If we are printing, the tr (trailer) string will be interpreted and sent to the of_fd.
  3. If printing and the la (local printer accounting) flag is set or transferring a job and the ar (remote accounting) flag is set, the ae is examined and accounting is done as described for the as field.
  4. If the of filter is present, its STDIN is closed, and the lpd server waits for it to exit. The exit status is used as described above.
  5. The device (io_fd) is closed.
  6. The job is marked as completed in the spool queue.
  7. If the save_when_done flag is not specified, the job is removed.

Abnormal Termination

Options used:

If the job processing terminates abnormally, the following sequence of events occurs:

  1. The job is marked as having an error during processing.
  2. The LPD server will attempt to kill all filters and other associated process by using a sequence of kill -INT, kill -QUIT, and finally kill -KILL operations.
  3. If there is a mail_operator_on_error value, the specified operator will be mailed an error indication. The sendmail option specifies the pathname of the sendmail program and the options needed to have it read mail addresses from its standard input. For example, sendmail=/usr/sbin/sendmail -oi -t is a commonly used set of options.
  4. The mail_from value specifies the user name used for mail origination. If not specified, the default is to use the print spool queue or printer name.
  5. If there is a send_failure_action specified, then it is decoded and the corresponding action taken. If the value is remove, hold, abort, or retry, then the job is removed, held, aborted, or retried. If the value is |/program, the program is executed and the number of attempts are written to the filter STDIN. The exit status of the filter will be used to determine the consequent actions. That is, JSUCC (0) will be success, and the standard success action will be taken; JFAIL will cause retry, JREMOVE will cause the job to be removed, JHOLD will cause the job to be held, JABORT or other status will abort processing.
  6. If the status is ABORT and the stop_on_abort flag is set, then further processing of jobs is terminated. The job is not removed from the queue.
  7. If the error status indicates removal, and the save_on_error flag is clear then the job is removed from the spool queue.
  8. If the error status indicates that no further operations should be performed on the queue, then the lpd server will stop processing jobs.
  9. If the error code indicated that the job should be retried, and the rt value is 0 or the number of attempts is less than the rt value, then the job is retried. Between each attempt to transfer a job to a remote site. This pause will double after each attempt, reaching a maximum of max_connect_interval seconds. If max_connect_interval is 0, there is no limit on the interval value.

LPD Spool Queue Processing

Options used:

When the lpd server starts, it will fork a set of subserver processes, each which will handle an individual queue.

If a system has a large number of queues, then this forking operation may result in the lpd server exhausting the process resources. To control this, the max_servers_active value restricts the number of active children to the specified value. If this value is 0, then 50% of the maximum system processes value will be used.

Due to the limits on the number of processes, there may be times when a job is placed in a queue, but the lpd server is unable to start handling the job. When all of the children of the main lpd server have exited, the server starts a timer. After lpd_poll_time seconds, it will scan the queues, looking for jobs to process, and starts a process to service them. If it does not find any jobs it remains idle.

The lpd_force_poll flag causes the server to periodically poll the queues. This is useful when there is a high possibility that jobs could fail to be printed due to high loads on the server.

6.7 Filter Command Line Flags

Options used:

A filter (or program) specification in the LPRng printcap database usually has the form:

:option=| [flags] /path [arguments]
:option=[flags] /path [arguments]

The first case is used where the option value can be a string or filter, and the second where a program is always expected. The following procedure is used to run a filter program.

The sequence of operations to run a filter is as follows:

  1. The program must be specified with an absolute path name.
  2. By default, the program is run as the user if invoked from a client program such as lpr, lpc, etc. If invoked from lpd, it is run as the server_user user (default daemon) configuration entry.
  3. The flags control how the program is to be run. The following flags are supported:
  4. If the -$ flag is not specified, the arguments determined by the value of the bkf (Berkeley LPD filter compatible flag) flag are added to the filter command line. If bkf is false the filter_options are added for OF filters and of_filter_options are added for non-OF filters; if it is true, then the bk_filter_options and bk_of_filter_options are added for OF and non-OF filters respectively.


    Option
    DefaultValue
    filter_options$C $F $H $J $L $P $Q $R $Z $a $c $d $e $f $h $i $j $k $l $n $p$r $s $w $x $y $-a
    of_filter_options(same as filter_options)
    bk_filter_options$P $w $l $x $y $F $c $L $i $J $C $0n $0h $-a
    bk_of_filter_options$w $l $x $y

  5. By default, for programs that are not being invoked as print job file filters, the filter_options arguments are added. For print job filters, if the bkf flag is set, then the bk_filter_options and bk_of_filter_options entries are used. The default bk filter options are the same as originally used with the BSD LPR filters. For the of filter, either the of_filter_options or bk_of_filter_options arguments will be added.
  6. The program arguments will then be scanned and interpreted. Arguments of the form $letter will be translated into values from the print job control file and/or printcap entry. The letters have the following meaning:

    Letter
    TranslatedValue
    a printcap af (accounting file name)
    b job size (in K bytes)
    c binary file (l format for print file)
    d printcap cd or sd entry
    e print job data file name (currently being processed)
    f print job original name when spooled for printing (N info from control file)
    h print job originating host (H info from control file)
    i indent request (I info from control file)
    j job number in spool queue
    k print job control file name
    l printcap pl (page length)
    m printcap co
    n user name (L info from control file)
    p remote printer (when processing for bounce queue)
    r remote host (when processing for bounce queue)
    s printcap sf (status file)
    t time in common UNIX format
    w printcap pw (page width)
    x printcap px (page x dimension)
    y printcap py (page y dimension)
    F print file format
    P printer name
    S printcap cm (comment field)
    Capital letterCorresponding line from control file
    {key}printcap value for key
  7. If there is no value for the specified argument, then the argument is removed from the list. If there is a value, the actual form of the substitution is controlled by additional flags as follows.

    Form
    TranslatedValue
    $x '-xvalue'
    $-x 'value'
    $0x -x 'value'
    $'x -x value

    Each entry in quotes is treated as a single value, as in /bin/sh. The $'x does not quote the value. Combinations of the various flags are allowed. For example, $-x would simply substitute the value for x, and then pass the whitespace separated components as individual arguments. This last form is useful for adding in additional flags on the command line.

  8. The command line is parsed, metacharacters are ruthlessly stripped from all arguments and pathnames and replaced by _ (underscores), and an argument list suitable for the execve system call is formed.
  9. A sanitized environment is set up for the program execution, with the following environment variables.


    USER
    User name (client only)
    LOGNAME L control file info
    HOME Home directory (client only)
    LOGDIR Home directory (client only)
    PATH filter_path configuration information
    LD_LIBRARY_PATH filter_ld_path configuration information
    SHELL /bin/sh
    IFS " \t"
    TZ Time zone
    SPOOL_DIR sd printcap info
    CONTROL_DIR cd printcap info
    PRINTCAP_ENTRY printcap info
    CONTROL control file

  10. If the filter is to be run by a client program such as lpr, then the environment variables specified by the pass_env configuration or printcap option will be extracted from the environment, have any metacharacters removed, and then placed in the environment variable list. Commonly, the PGPPASS and PGPPATH are specified.
  11. The program is started, with STDIN, STDOUT, and STDERR attached to the appropriate files or file descriptors. If none is specified, then they are attached to /dev/null.

6.8 Bounce queues and filters: caveats

There are a few situations in which a filter of a bounce queue will behave differently from an ordinary queue.

6.9 The lpr -p format and :pr filter

The -p format doesn't behave as expected. Instead of running pr | if, the daemon will try to call the :pf filter.

After filtering, the file might be of a different type than before. Since the result is transfered to another print service (which might do its own filtering), it is important that the right file type (by means of the print format) is passed on to the second queue.

Use the translate_format =oNoN... printcap option. Its value takes the form of old/new pairs of formats. For example:

translate_format=pf

The -p format file will now be renamed with the f format.

6.10 LPRng Supported Filters

There already exists a large library of ready-to-use filters. Some of them have LPRng-specific versions, which can be found at the LPRng ftp mirror sites.

Filter Distribution Conventions

By convention, most filters are either totally standalone (very rare), or require a set of support files. There are two types of support files: per print queue configuration information and global support information.

Since a print filter will execute with the current directory set to the spool queue directory, most filters expect that per print queue configuration information should be kept in the spool directory. Most vintage filters insist on having these files hidden with names such as .setup. This can make it difficult for administrators to determine where the configuration files are.

It is strongly recommended that filters and information be placed in commonly accessible directories such as /usr/local/lib/filters, and the executables in subdirectories. This allows the LPRng administrator to set the privileges on these directories such that only the lpd process can access them.

Most of the LPRng supported filters can either be used as a if or of filter. The filter will examine the format type passed by the -FX command line argument, and if it is o it will perform as an of filter.

Alternatively, the filter will check the filename in the pathname by which is was invoked. If the name has the substring of in the filename, then it assumes it is to act as an of filter. This allows symbolic links to be made to a common filter executable, each of which corresponds to the filter name by which it is to be invoked.

When a filter is invoked, it is passed a large number of options, many of which are totally ignored in filter operation. However, for many purposes it is necessary to provide options to the filters to tailor their operation to the particular spool queue needs.

By convention, all LPRng supported filters use the

-Tkey=value[,key=value]

convention for specifying filter configuration option values.

lpf

Source code: LPRng Distribution

This filter is distributed as part of the LPRng source code, and has a very limited functionality. By default, it only translates \n to \r\n sequences, and detects the OF Filter Stop sequence when invoked as an OF filter.

6.11 CTI-ifhp ifhp Filters

Source code: LPRng Distribution, CTI-ifhp-<em>version</em>.tgz

This filter supports a wide variety of Hewlett-Packard printers, or to be more specific, printers which support the Hewlett-Packard PCL and/or PJL languages. In addition, they try to detect PostScript jobs and send the correct commands to the printers to enable PostScript rather than PJL operation.

This filter was originally developed by Panos Dimakopoulos, Systems Programmer, of the CTI-Print project at the Division of Computing Facilities of the Computer Technology Institute (CTI), Patras, Greece. The code has been heavily modified by Patrick Powell <papowell@astart.com> to support newer versions of HP Printers. It is intended to replace the HPJetDirect drivers supplied by Hewlett-Packard.

Printer Capabilities

As explained in Setting Up Your Printer, you can have a parallel (unidirectional), serial (bidirectional), or network (bidirectional) connection. When using a bidirectional connection, you can sometime obtain or gratuitously receive error and/or status information from the printer.

Some printers will spontaneously generate error messages when printing a job on a bidirectional interface. Usually, though, it it necessary to force the printer to provide status in a reasonable format.

Some printers have the capability of printing either PCL or PostScript; some require special setup commands and some will autosense which type of job is being printed.

If you are printing text, and not using a Page Description Language like PostScript or PCL, then you may want to download a font to the printer. This is especially the case when you are trying to print text files in a non-English font.

Some printers will provide a hardware page counter value when requested; however, the means of requesting differ from model to model.

Sometimes you want to generate a special banner for a particular printer, and need to put in some dynamic information. While this can be done by the lpd server using the bp program specification, it turns out that non-LPRng systems which want to use the ifhp want to have the same facilities. Thus, you need to have some way to get the same effect as the bp option, but at the filter level.

Having done lpd banner generation and printing, why not have the filter run an accounting script as well?

At this point, I suspect that the reader is beginning to suspect that making a general purpose filter to support all of these possibilities is difficult. That is incorrect. It is extremely difficult.

hpif Options

These options are specified by the -Tkey=value [key=value]* on the command line.


Option
Purpose
accounting=accounting_script_pathnameInvoke the accounting script with a subset of theoptions passed to the filter. In addition, the-bpagecount option indicates the number of pagesprinted for the job.
autodetect=[on|off*]The printer has or does not have job type autode-tect capability. Do not download fonts or try todetermine job type if autodetect is on.
banner=[on|off*]If banner is on, then the ifhp filter will attemptto print a banner using information passed on thecommand line or on the standard input. The titleoption can be used to specify additional titleinformation on the banner. See BANNERS below fordetails.
cartridge=[*on|off](Alias for postscript)If cartridge is on, the printer has PostScript sup-port. The filter will try to determine if a job ispostscript and send Printer Job Language commandsto put the printer in PostScript mode.
debug=debuglevelSets the debugging level; 2 is the default; alarger number causes more verbose error messages.
defaultfont=fontnameSets the default font to be downloaded; default isNONE.
dev=/device or dev=host%portOpen the specified device or connection to remotehost; by default ifhp filter uses file descriptor 1(stdout). If the optional orig_port is specified,connections will be originated from this port.Some printers require that connections originatefrom a port in the range 1-1024.
infostatus=[*on|off]The PJL INFOSTATUS request is not supported on someHP printers. Use this to turn the status requestoff. Note that you cannot get real time reports ofthe printer status if you do this. This will alsosuppress getting pagecount information using thePJL facilities.
forcepagecount=[on|off*]If you have a printer that has PostScript pagecount information support, you can set infostatusto OFF and forcepagecount to ON. This will causethe PostScript facility to be used. If you setcartridge or postscript to OFF then this will notbe done.
logallSave all of the error and information messages fromthe printer in the log file. This is useful whenyou wish to examine returned status from theprinter.
model=(C5M|III|IIID|IIISi|IV*)The model of HP printer. C5M is Color 5M, III isHP LaserJet 3, IIID is HP LaserJet 3D, etc. Addi-tional printers may be added or defined at varioustimes - please consult the source for details.This selects various timing and format characteristic-tics. This is a desperation parameter for userswith antique or non-conforming PJL based equipment;read the source code for details on the particularpeculiarities.
pagecount=[on*|off]Get the hardware pagecounter value for accounting.Some printers such as the HP LJ4s do not have hard-ware support for pagecounters, and return bogusnumbers. Use this to suppress attempting to getvalid information. If your printer does supportPostScript, then you can get the page count valueusing PostScript by setting forcepagecount to ON.
plp=[on|off*]Return PLP status values on exit; by default LPRngstatus values are returned.
postscript=[on*|off]The printer has postscript support.
quiet=[on|off*]If set, do not report common status messages.
retries=countThe number of times to retry connecting to theprinter.
sleep=timeThe number of seconds to wait before trying to con-nect to the printer.
status=[*on|off]When on, the printer is treated as a write onlydevice and is not queried for pagecount and statusinformation. Set status=OFF for parallel printers.If status is OFF, then the ifhp filter simply addsjob control language headers, fonts, and trailersto the jobs.
stty=stty flagsif the output device is a serial line, set the linecharacters according to the stty flags. Theseflags are (most likely) identical to those avail-able with the stty(1) command on the host system.
summary=[filename|host%port]This option specifies that summary or informationalmessages should be placed in the specified file orsent, using the UDP protocol, to the indicated hostand port address. This allows remote monitoring ofthe printing and error activity. The undocumentedprogram included with the filter distribution is asimple program that can be used to perform the mon-itoring.
sync=[*on|off]Try to synchronize communications with printer.This will ensure that the printer has been reset,and no problems involving the previous job willresult.
tbcp=[on|*off]When invoked as an IF filter and transferring aPostScript job, the filter will use the AdobeTagged Binary Communications protocol. This allowsbinary data to be transferred and not interpretedas control information.
title=line[/line]*The title information is printed on the bannerpage; it consists of a list of / separated lineswhich are added to the banner information.
wrap=[on|off*]enables or disables line wrapping in PCLmode.

Parallel Port Printer

On a parallel port printer, you cannot get status, or do much besides set up the printer to either handle PostScript or do autosensee. The following is a typical printcap entry:

pr:.... options
  :of=/usr/local/lib/filters/ifhp -Tstatus=off
  :if=/usr/local/lib/filters/ifhp -Tstatus=off

You might want to also look at the autodetect or postscript options.

Printing Banners

By default, the ifhp filter when used as an OF filter will interpret the first line to it as a short banner line, and use the information on this line to produce a PCL based banner. The short banner line should have the format:

class:username Job: jobinfo Date: dateformat

Example:
  A:papowell Job: (stdin) Date: Sun Dec 14 07:13:34 PST 1997

This is produced by the default short banner line option value:

bl=$-'C:$-'n Job: $-'J Date: $-'t

If you want to suppress banner printing, then you need to suppress generation of this short banner line. If you want to have the lpd program to generate the default long special banner, then you need to suppress ifhp from interpreting the information sent to is as banner information. Finally, you may want to have lpd invoke the bp (banner program) and have its output used as the banner. Here are the various possible ways:

# no banner at all, use :sh: - suppress headers
lp:....
  :sh
  :of=/usr/local/lib/filters/ifhp
# have ifhp generate banner from short banner input
lp:....
  :sb
  :of=/usr/local/lib/filters/ifhp
# have LPD generate long banner, have of filter pass it
lp:...
  :sb@
  :of=/usr/local/lib/filters/ifhp -Tbanner=off
# have LPD invoke bp banner generation program, have of filter pass it
# bp programs require short banner on STDIN to work, so we need to
# generate short banner
lp:...
  :sb
  :bp=/usr/local/lib/filters/banner_program
  :of=/usr/local/lib/filters/ifhp -Tbanner=off

The ifhp banner is generated in PCL, and uses the minimum PCL facilities. Since when you send a banner to an autosensing printer you cause it to enter the requested mode, the if filter (ifhp) will need to reset the printer to autosense mode. The ifhp filter automatically does this.

If you want very fancy banners, the banner.sh (PCL) and psbanner.sh (PostScript) banner generating programs in the CTI-ifhp distribution make a good starting point.

Error Logging

Error logging and reporting is done by the ifhp filter as follows.

  1. Messages are produced by the actions of the ifhp software. This are logged to the STDERR output of the filter.
  2. Messages are produced by status returned from the printer, when the -Tstatus=on (default) option is enabled. These are classified according to the Hewlett-Packard Printer Job Language error status definitions, and logged to the STDERR output of the filter.
  3. In addition to error messages, ongoing status messages are also produced. If the printcap entry has a ps=statusfile entry and the statusfile exists and is writeable, then the error and status messages will be written to the log file.
  4. If the message concerns a serious matter or has been returned from the printer as an 'ALERT' in it, then the message can also be sent to a 'summaryfile'. This file can be either a file OR a UDP socket on a host. This is specified with the -Tsummary=summaryfile option. For example,
            ifhp -Tsummary=taco%3000
    
    would send messages to UDP port 3000 on host taco.
  5. If you do not want the filter to report status on its STDERR output, use the -Tquiet option to suppress this, or compile it with the -DQUIET option.

Accounting Information

Doing printer accounting is not simple. Read LPRng Accounting for more information.

In order to help aid in accounting, by default the ifhp filter will query the printer to get the current value of the hardware page counter value, if there is such a thing on the printer. Unfortunately, due to different types of printers and errors in their PJL, PCL, and PostScript implementations, several different methods need to be used.

  1. Only a printer with a bidirectional port will return status, so you need to have a bidirectional connection.
  2. If the printer is still printing a job, then getting the value of the hardware page counter will be useless; you need to wait until the printer is idle, i.e. - synchronize your operations with the printer.

    Unfortunately, some printers return an idle indication even when they are printing pages of the previous job. This means that the printer has to be polled, and only when it is idle and the pagecounter value has been stable for a reasonable time (5 seconds?) can you trust the page counter value. This slows down job printing very seriously.

    Some of the newer PJL printers have a PJL TEOJ, or return end of job indication when the last page of a job has been printed. If you have this capability, you can speed up printing.

  3. If your printer supports Hewlett-Packard Printer Job Language PJL INFO PAGECOUNT facility, then it will first be tried to get the page count.
  4. If your printer does not return pagecount information using the PJL facility and it has PostScript support (default), then a small PostScript job will be sent to the printer requesting the systemdict pagecounter value. Unfortunately, different implementations and versions of PostScript will need different programs. The PostScript Printer Definition file for the printer will have the correct script that is needed. The default script that is used is:
     /ps { print flush } def
     (\tPAGECOUNT ) ps
     statusdict begin pagecount end == flush
    
  5. To confuse matters totally, some printers which can do PostScript interpretation do not support PJL PAGECOUNT reporting. You can use the PostScript method to get the pagecount information, but you cannot get status.
  6. The pagecounter information is obtained at the start and end of processing a job, and is printed in the accounting file and also on File Descriptor 3 (if it is open). This information has the format:

      start -ppagecounter -Ff -kjob -uuser -hhost -R...
      end  -ppages -qpagecounter -Ff -kjob -uuser -hhost -R...
    

    When we use the OF filter and/or banners, we will see the individual jobs bracketed by the OF filter records:

        start -p100 -Fo -kcfA100taco -uuser -hhost -R...
        start -p101 -Ff -kcfA100taco -uuser -hhost -R...
        end  -p1 -q102 -Ff -kcfA100taco -uuser -hhost -R...
        start -p102 -Ff -kcfA100taco -uuser -hhost -R...
    

    We can use the various job numbers and other information to track page usage.

The following are a selected set of printcap entries that can be used to get page counting information:

# use defaults, try to get pagecount using all methods, wait for stable
# value of pagecount before proceeding
pr:...
  :of=/usr/local/lib/filter/ifhp
# printer support PJL True End of Job and PAGECOUNT
pr:...
  :of=/usr/local/lib/filter/ifhp -Ttrue_eoj=on
# no PJL INFO status available, but you can get page count using postscript
pr:...
  :of=/usr/local/lib/filter/ifhp -Tinfostatus=off,forcepagecount

You should try connecting to your printer directly and testing the accounting facilities. You can do this by using the ifhp -Tdev=... facility. For example:

ifhp '-Tdev=/dev/ttyb,stty=38400 -echo -crmod -raw -oddp \
-evenp ixon pass8 -ixany cbreak' -Tdebug=5 <ellipse.ps
ifhp -Tdev=astart14%9100 -Tdebug=5 -Ttrue_eoj <ellipse.ps

6.12 psfilter PostScript Printer Filter

Source code: LPRng Distribution, psfilter-<version>.tgz

The psfilter is similar to the CTI-ifhp filter in its operation and functionality. Its general operation and procedures are similar, but it has the following additions:

  1. It will translate text jobs to PostScript and print them using PostScript unless the jobs are literal or binary formats.
  2. It will use the PostScript serial line status query support to obtain status and other error information.
  3. When you are sending a PostScript file with binary information, you need to either suppress status gathering, or you need to use the Transparent Binary Communications Protocol. Note that older PostScript printers do not support this.

IF and OF Filter Support

During the installation process, psif and psof symbolic links are made to the psfilter executable. Thus, the following printcap entries can be used:

# common use:
lp:...
  :of=/usr/local/lib/filters/psof
  :if=/usr/local/lib/filters/psif
# same effect:
lp:...
  :of=/usr/local/lib/filters/psfilter
  :if=/usr/local/lib/filters/psfilter

Options

The -Tkey=value[,key=value] convention is used to pass options to the psfilter. The following options are supported. Many of these are identical in intent to CTI-ifhp options.


Option
Purpose
accounting=/pathname_to_executableWhen the -Taccounting is specified, the specifiedprogram is executed with the same options as thefilter.
debug=levelset debugging level. The default level is 2;higher values produce more verbose output.
dev=/devicedev=host%portOpen a connection to either the device or to theport on the host and send output to it. Bydefault, output is send to stdout.
endpause=delayWhen used as the OF filter, at the start and end ofthe job psfilter will query the printer for thevalue of the hardware pagecounter. The differencebetween the start and end values is reported as thenumber of pages used for the job. Unfortunately,some printers such as the HP LaserJet 4 and HPLaserJet 5 report the current value of the pagecounter at the time of request, and it is difficultto determine if the last page has been completelyprinted by examining returned PostScript status.Before querying the printer at the end of a job,the psfilter software will wait endpause seconds(default is 5). On a 12 page per minute printer,this appears to be sufficient to allow the lastpage to be completely printed. However, if theprinter jams on the last page, it will still not bereported and the page count will be off by one.
forcepagecount=[off*|on]To find the pagecount value, a PostScript programis sent to the printer. This overrides any otherflags and forces the program to be sent. Usuallyused in combination with -Tstatus=off -Tforceps,and -Tnosync flags. See the comments below forprinter specific problems.
forceps=[off*|on]Forces a dummy PostScript job to be sent at thestart of operations. This usually tricks autosense-ing printers into going into PostScript mode andresponding to the PostScript conventions. See thecomments below for printer specific problems.
maxresponse=seconds(default30seconds)Specifies how long to wait for a status responsebefore giving an error indication.
nosync=[off*|on]Suppresses trying to get status from the PostScriptprinter, as would normally be returned by sending a^T. See the comments below for printer specificproblems.
pagecount=[off|on*]Get the pagecounter value from the printer and usefor accounting information. Note that some HPprinters (LJ4s) do not appear to have pagecounters.(Default is on).
reverse=[off*|on]Reverse page order on output.
status=[off|on*]Query the print device for status and page countinformation. If status is off, then psfilter sim-ply formats input into postscript and does not doaccounting.
stty=stty_optionsIf the output device is a serial port, set the con-figuration according to the stty options. Theseoptions should be identical to those used bystty(1).
summary=destinationWrite a one line status summary to the destination.The destination can be a file (i.e. - /tmp/status)or a UDP port on a host (host%port). The host namecan be an hostname or an IP address (i.e.-info.sdsu.edu%2000 or 130.191.163.56%1000).
tbcp=[off*|on]Use the Adobe Tagged Binary Communications protocolto send the document when invoked as an IF filter.The OF filter cannot handle binary PostScript docu-ments as it will remove various control sequences.The -Ztbcp LPRng option will also enable TBCP oper-ations.
udp_status_port=host%portThe HP5m and possibly other printers use port 9101(UDP) to request and send status. When sent a UDPpacket on this port, the printer responds by sendingstatus back to the sender. This option forces theuse of this port for sending status. However, pagecounts and other information still use the standardconnection to the printer.

Accounting

The psfilter uses the same methods for doing accounting as the CTI-ifhp filter. See IFHP Accounting for details.

Consult your printer's PostScript Printer Description file to determine the PostScript script needed to do accounting. You may need to modify the default one supplied in the psfilter code.

Always test that the printer returns the right accounting information using a test similar to the following:

psfilter -Tdebug=8 '-Tdev=/dev/ttyb,stty=38400 -echo -crmod -raw -oddp \
-evenp ixon pass8 -ixany cbreak' <ellipse.ps
psfilter -Tdebug=8 -Tdev=astart14%9100 -Ttrue_eoj <ellipse.ps

6.13 lp_pipe Filters

Source code: LPRng Distribution, part of FILTERS_LPRng-<version>.tgz

The lp_pipe family of filters was developed to act as a network pipe to network devices. They are largely replaced by the lp=host%port, facility.

6.14 apsfilter Filter

Source code: LPRng Distribution, apsfilter-<version>.tgz

The apsfilter is basically a simple front end to the a2ps program (See: http://www-inf.enst.fr/~demaille/a2ps/ for details), and is an example of a MagicFilter that has powerful processing capability. The apsfilter program sets up options for the a2ps program and then invokes it.

The a2ps program can convert just about any type of file into PostScript, and then by using the GhostScript facility can convert this to the output compatible with a particular printer.

Combined with the LPRng qq and force_queuename options, we can set up virtual queues that do various types of reformatting. Here is a sample set of printcap entries:

# seen by users - note that the queue name is put into control file,
#  and we then send it to the frontend@host queue for processing
raw:qq:lp=frontend@host
twoup:qq:lp=frontend@host
landscape:qq:lp=frontend@host
frontend:lp=frontend@host:force_queuename=raw
# frontend does the job conversions and accounting
frontend:server
  :lp=/dev/lp:force_queuename=raw
  :if=/usr/local/lib/filter/apsfilter

6.15 Using your own filters

If you already have a working setup, with its own specific filter programs, you might want to keep them. Or, you might want to write a set of your own.

See the source code in the LPRng Distribution, FILTERS_LPRng-<version>.tgz files for examples.


Next Previous Contents