4.19. Job Options and the Z Control File Entry

Many printers have special capabilities such as printing in landscape mode, duplex printing, binding, or stapling. These capabilities are usually invoked or enabled by the print spooler sending special printer control commands to the printer based on values it finds in the control file. The LPRng print spooler uses the Z line in the control file to specify these options, while other print spoolers such as the Sun Microsystems Solaris lp system pass them on the S line.

Job formatting options are specified using the lpr -Z option. The lpr program concatenates the -Z options and puts them in the control file as a single Z line. For example:

h4: {289} % lpc stop
Printer: lp@h4
lp@h4.private: stopped
h4: {290} % lpr -Zthis -Zthat /tmp/hi
h4: {291} % cat /var/spool/lp/cf*
Hh4.private
Ppapowell
J/tmp/hi
CA
Lpapowell
Zthis,that
Apapowell@h4+115
D2000-05-05-10:05:41.351
Qlp
N/tmp/hi
fdfA115h4.private
UdfA115h4.private

As we see, the Z options have been put into the control file on the Z line. The Z option values are passed to filters on the command line as the -Z command line option. These values are used by the ifhp filter to determine what control commands to send to the printer and how to format the print job output. Because each printer is different and supports a different set of capabilities it is impossible to have a set of job options supported across all printers. The following are supported by the ifhp configuration where possible. Many of these options rely on the printer supporting PostScript or having the appropriate PCL commands to do the indicated operation.

4.19.1. Setting Job Options Using the Printcap

An alternative to this method of using lpr and the -Z option is to define a set of spool queues which will put the necessary options into the job control file. This can be done by the lpr program when the job is generated, or by the lpd spooler when the job is processed. The The options specified by the :prefix_z, :append_z, and :delete_z are prefixed, appended, or deleted from the current set of Z control file options by the lpr program when the job is submitted and they are specified in the printcap for the queue, or by the lpd spooler when the job is submitted to the queue. We can use this capapbility to configure print queues to a desired set of Z options into the control file. For example:

landscape:lp=%P@server
landscape:server:tc=.common
  :lp=raw@server:append_z=landscape:delete_z=portrait
raw:server:tc=.common:lp=....
  :filter=/usr/local/libexec/filters/ifhp
.common:sd=/var/spool/lpd/%P

When a job is sent to the landscape queue, the control file Z line will have the portrait option removed and the landscape option appended. The :delete_z values are glob patterns and options that match are removed from the option list. Options are assumed to be separated by commas or semicolons in the option list.

4.19.2. Converting SystemV Options to LPRng Options

On some SystemV lp print spoolers, the lp -o option, puts the option information into the control file S line, and on other systems on the puts the option information into the control file O line. To convert these options to LPRng Z options use the :prefix_option_to_option=from,from... to facility to prefix the from control file lines to the to control file line. For example:

# System V to LPRng - S and O to Z options
convert:server:tc=.common
  :lp=raw@server:prefix_option_to_option=S,O Z
# LPRng to System V O options
convert:server:tc=.common
    :lp=raw@server:prefix_option_to_option=Z O

4.19.3. Selecting a Single Option - Muliple Queues

Here is an example of how you can set up queues that will append the appropriate Z option to select landscape mode, do duplex printing, or select legal or ledger size paper:

landscape:lp=%P@server
landscape:server:tc=.common
    :lp=raw@server:append_z=landscape
duplex:lp=%P@server
duplex:server:tc=.common
    :lp=raw@server:append_z=duplex
ledger:lp=%P@server
ledger:server:tc=.common
    :lp=raw@server:append_z=ledger
legal:lp=%P@server
legal:server:tc=.common
    :lp=raw@server:append_z=legal
raw:server:tc=.common:lp=....
  :filter=/usr/local/libexec/filters/ifhp
.common:sd=/var/spool/lpd/%P

The problem with this method is that for each option we need to define a queue whose only purpose is to append the appropriate option and then forward this to the main print queue.

4.19.4. Selecting Multiple Options - Single Queue

In the previous section, we showed how to set up a queue that would append a single option to the control file Z line. If we want to have combinations of option options specified by the printer name then we will have to create a large number of queues each with a different set of options and each appending a different set of values. The problem becomes compounded when we have many printers, each of which requires these options.

The solution to this problem originated with the apsfilter program written by Andreas Klemm and Thomas Bueschgens. They made the observeration that if we know the name of the print queue then we can use this name to select options for the printer. The LPRng provides this functionality by using wildcard queues and editing or filtering the control file when the job is submitted to the spool queue.

The incoming_control_filter=/path filter processes the incoming job control or job ticket file. It can be used to values in the job ticket of incoming jobs. It reads the control file on its STDIN and writes the new or modified values on STDOUT. A 0 exit code value causes normal processing of the job, JHOLD will hold the job, and any other value will cause the job to be discarded. The incoming_control_filter filter can modify priority or other job options, including using the move= field to cause a job to be redirect to another spool queue or printer. Only changes to the jobs options need to be generated by the incoming_control_filter=/path filter.

The input and output have the format:

INPUT:
 X<option>       - option from control file
 X=<option>      - alternative option format
 key=<option>    - spooler option
 X==<option>     - option starting with = sign

OUTPUT:
 X                     - delete option or value
 X=                    - delete option or value
 X<option>       - set option value
 X=<option>      - set option value
 key=<option>    - set value of 'key' to option
 key=                  - delete option or value

In addition to modifying job options, the contents of the jobs data files can be modified or the data files removed. Any data files with a 0 length will be removed from the job. If all of the data files have a 0 length then the job will be discarded. Modification of job options may have unforseen effects on

The following shows how we can set up a single queue that will allow various combinations of options to be selected by the format of the queue name:

# for clients
pr|pr_*:lp=%Q@server
# for server
pr|pr_*:server
  :tc=.common:lp=....
  :incoming_control_filter=/usr/local/libexec/filters/update_z
  :filter=/usr/local/libexec/filters/ifhp
.common:sd=/var/spool/lpd/%P

The pr and pr_* aliases will match printer pr all print queue names starting with pr_. We can then use various suffixes to select job options. The following filter program uses the _landscape, _legal, and _ledger suffixes to set the corresponding option in the Z file. This program and other are available in the LPRng distribution in the UTILS directory. You should note that additional options can be specified as desired.

#
#!/usr/bin/perl
# update_z script:
# Determine the options according to the format of the queue name
#  Inspired by the psfilter code of Andreas Klemm
#  and Thomas Bueschgens 
# First, get command line arguments
#
use Getopt::Std;
my(%args,$Q,$Zopts,@file);
getopts(
"A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:" .
"a:b:cd:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v:w:x:y:z:",
\%args );
# read stdin
@file = <STDIN>;
$Zopts = "";
# first use command line Queue name
$Q = $args{"Q"};
if( not $Q and (($Q) = grep(/^Q/,@file)) ){
   # next use control file Queue name
    chomp $Q if $Q;
}
# now we split up the name and use as parameters for Z options
while( $Q =~ /_([^_]+)/g ){
    # you can add them or test and then add them
    if( $1 eq "landscape"
        or $1 eq "legal"
        or $1 eq "ledger" ){
        $Zopts .= ",$1"
    }
}
if( $Zopts ){
    # remove leading comma
    $Zopts = substr( $Zopts, 1 );
    #replace or prefix Z options
    if( not (grep { s/$/,$Zopts/ if /^Z/; } @file) ){
        print "Z" . $Zopts . "\n";
    }
}
print @file if( @file );
exit 0

Example Input:
...
Z=over
Q=lp_landscape_ledger
...

Example output:

Z=over,landscape,ledger
Q=lp_landscape_ledger

The Perl script first uses the getopts function to parse the command line options. If there is not a command line -Q option then the control file Q line is used after stripping the trailing newline. The queue name is then split up into parts separated by underscores (_) and those used as option names. As shown in the example, the literal values are placed in the control file. You can also use the following code segment to translate short forms of options into longer ones:

while( $Q =~ /_([^_]+)/g ){
    # you can add them or test and then add them
    Zopts .= ",landscape" if( $1 eq "ld" );
    Zopts .= ",ledger" if( $1 eq "11" );
    Zopts .= ",legal" if( $1 eq "15" );
    Zopts .= ",a4" if( $1 eq "a4" );
}