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 option specifies a filter that processes the incoming job control file. It should be used to update and/or modify information on the option lines of the control files of incoming jobs. It reads the control file on its STDIN, writes the new or modified control file lines on its STDOUT, and then exits. 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.

In addition, the control file filter can specify new values for the hold file entries, as well as new values control file values. This latter capability can be used to modify priority or other facilities, such as using the hold file move= field to reroute a job. The hold file output has the format:

    X<option>       - change value of control file X option
    X<no option>    - set value of X option to empty or none
    ...
    <blank line>    - separator keyword=value options
    key=<option>    - set value of 'key' to option
    key=<no option>    - set value of 'key' to empty or none


The key=value form can be used to set option values that are outside of the range of the control file options. For example, the move= option specifies a destination for the job, overriding the default destintation. By adding a move= entry, simple job routing can be done. This is an alternative to the more powerful routing filter capabilities.

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 Control file:
    
    ...
    Zover
    Qlp_landscape_ledger
    ...
    
    Modified output:
    
    ...
    Zover,landscape,ledger
    Qlp_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" );
    }