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.
-Zlandscape -Zportrait - select landscape or portrait orientation.
-Zduplex -Zsimplex - select duplex (both sides of a page) or simplex (single side of a page) printing.
-Zletter -Zlegal -Zledger -Za4 -Za5 -Zenvelope -Ztransparency - select a paper size
-Zinupper -Zinmiddle -Zinlower - select input media from the appropriate input tray
-Zmanual - select input from the manual feed
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.
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
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.
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" ); }