Next Previous Contents

4. Filter Operation Details

The ifhp filter operates by first reading a configuration file to determine the type of printer it is working with, and then proceeds to carry out operations requested by the values of option variables passed on the command line or found in the configuration files. In normal operation, input is read from STDIN (file descriptor 0), massaged in the appropriate manner, and then written out to STDOUT (file descriptor 1). Status reports are written to a status file, or optionally to STDERR (file descriptor 2), together with any error messages or diagnostics.

In addition to normal operation the filter can run in the OF mode and act as a printer initializer and job terminator. This is discussed in detail in the LPRng documentation. When in the OF mode, The first nonblank input line will be treated as a request to generate a banner. The string "\031\001" will cause the filter to suspend operations using a SIGSUSP signal. At this point, job files will be sent to the output device by the spooler, and the filter will then be restarted with a SIGCONT signal.

These steps are best explained algorithmically. The following is a pseudo-code description of the steps performed during the printing activity. The sections marked with ### are discussed later in this document in detail.

/// See: Options, Initialization and Setup

###+++ Initialization and Setup
// get ifhp information from PRINTCAP_ENTRY environment variable
if( PRINTCAP_ENTRY environment variable has a value ){
        split printcap information into printcap fields
        if( :ifhp=options,options is present in printcap ){
                split the options list and place in the Toptions list
        }
}
foreach option in -Toptions, -Zoptions do
    if( option = "debug=level"  and Debuglevel not set ){
        set Debuglevel = level;
    }
    if( option = "trace" ){
        output error and trace on STDERR
    }
    if( option = "config=pathlist" and from -Toption ){
        set configuration pathlist = pathlist;
    }
    if( option = "model=name" and model not set ){
        set model = name;
    }
}
/// See: Operation Configuration Options
// extract configuration information
foreach path in configuration pathlist {
    open path;
    for each line in file information {
                if( line is selected to be in configuration ){
                        process input line, adding it to configuration
                        if( line is 'debug=','model='
                           and the corresponding value not set ){
                           set the value;
                        }
                }
    }
}

// get values of options with predefined meanings
// these include status, forcestatus, etc
foreach option in predefined list {
        if( option=value is in selected configuration information ){
                set option=value;
        }
}

// open a direct connection if specified
if( device specified using -Tdev=device ){
        // if device is host%port, we open TCP/IP connection
        fd = open(device);
        // Note - option read_write will open the device or file read write
        dup fd to 1; close fd;
}
if( appsocket protocol specified and TCP/IP device ){
        udp_socket = open( udp socket to device UDP port )
}


###---
/// See: Synchronization and Pagecount
###+++ Synchronization and Pagecount
if( status returned by printer and sync requested ){
    // APPSOCKET protocol
    // sync has the form sync@ (none), sync=ps, sync=pjl, ...
        if( appsocket ){
                command = "\n\r"
        } else {
                // decode status=language and determine sync
        if( sync = pjl and PJL ECHO available ){
            send PJL ECHO command to printer
                } else if( sync = ps ){
            send PS program to printer
                } else {
                        terminate with error;
                }
        do{
                send command and wait for timeout;
    } while( no response );

        if( appsocket ){
                close and reopen TCP/IP connection;
        }

    // pagecount has the form pagecount@ (none),
    //   pagecount=ps, pagecount=pjl, ...
    if( pagecount=language has value ) do {
                if( pagecount TRUE ){
                        set pagecount= pjl or ps depending on availability
                }
        if( pagecount = pjl and PJL INFO available ){
           send PJL INFO PAGECOUNT command to printer
                } else if( pagecount = ps ){
           send PS program to printer
                } else {
                        terminate with error;
                }
    } while( no pagecount response );

        if( appsocket ){
                close and reopen TCP/IP connection;
        }
}
###---
/// See: PJL Initialization
### PJL Initialization
if( PJL enabled ){
    language = "pjl_"
    foreach option in pjl_init=[...] {
       expand the option using the language value
       #+++ PJL OPTION ACTIONS +++
       if( option in pjl_vars_set=[ ... ]
         and option not in pjl_vars_except
         expand "@PJL SET OPTION=\%{option}"
         output = expanded string value
       } else {
         if( option value is a string ){
           output = expanded string value;
         }
       }
       // output has the form @PJL COMMAND ....
       if( COMMAND is in pjl_only=[ ... ]
           and not in pjl_except=[ ... ] ){
           send output to printer
       }
       #--- end PJL OPTION ACTIONS
    }
    if( !OF_mode ){
         foreach option in -Toption=value {
            if( option in pjl_user_opts ){
                #+++ USER PJL OPTIONS
                // join 'pjl_' and the option name
                expand 'pjl_' . option
                // perform PJL actions as above
                    #+++ PJL OPTION ACTIONS +++
                    ....
                    #-- PJL OPTION ACTIONS +++
                #--- USER PJL OPTIONS
            }
         }
         foreach option in -Zoption=value {
            if( option in pjl_user_opts ){
                // perform USER PJL actions as above
                #+++ USER PJL OPTIONS
                #--- USER PJL OPTIONS
            }
         }
    }
}

###--- PJL INITIALIZATION
/// See: Text File Conversion
// language is set to the type of job language
// - PS, PCL, TEXT, RAW, UNKNOWN
//  the first part of the job file is read and the filter takes
//  a (wimpy) guess at the job file based only on the first couple
//  of characters;  language is  be PJL, PS, or TEXT, or RAW
//  This is the same algorithm as the UNIX FILE utility

language = default_language (from configuration);
if( command line -c (binary) option present ){
    language = RAW;
} else if( -Zlanguage=xxx option present ){
    language=xxx
} else if( forceconversion set ){
    use UNIX file utility to get file type
} else if( file is PS file ){
    language=PS
        if( file starts with PS EOJ (CTRL-D)
                and no_ps_eoj is set ){
                remove the PS EOJ
        } else {
                send a PS EOJ first
        }
} else if( file is PCL file ){
    language=PCL
        if( file starts with PCL EOJ (ESC E)
                and no_pcl_eoj is set ){
                remove the PCL EOJ
        }
}
if( file conversion table specified then ){
        look up file type in conversion table;
        if( conversion program specified ){
        run input through conversion program
        }
        set file type to output type
}


if( language = TEXT and PCL allowed ){
    language = PCL;
}

if( language not recognized by printer ){
    exit with error;
}

if( PJL ENTER supported ){
        use PJL ENTER command to select language;
        send nullpad NULLS to force full buffer condition
}
/// See: Language Specific Initialization
// LANGUAGE SPECIFIC INITIALIZATIONS
if( language = PCL ){
    foreach option in pcl_init {
        ###+++ expansion 
        do expansion similar to PJL OPTION actions
            using "pcl_" prefix for option lookup;
        ###---
    }
    if( not in OF_MODE ){
        foreach option in -Toption do {
            if( option in pcl_user_vars=[ ... ] ){
            ###+++ expansion as above
            ###---
        }
        foreach option in -Zoption do {
            if( option in pcl_user_vars=[ ... ] ){
            ###+++ expansion as above
            ###---
        }
    }
    remove whitespace and expand string results;
} else if( language = PS ){
    ###+++ language specific actions as above,
      using the ps_ prefix for lookup 
    expand string results but do not remove whitespace
}
/// See: File Transfer and Error Status Monitoring
Transfer job to printer, reading error and other information
  back from the printer if enabled

if( language = PCL ){
    send PCL End of Job
} else if( language = PS ){
    send PS End of Job
}


// job termination

###+++ Synchronization and Pagecount as above
finished = 0
while( waitend and not finished ){
        // timeouts and retries are done here
        if( time taken is too long ){
                give up and report an error
        }
        if( appsocket ){
                send \r\n to get status reply
        } else if( waitend with PJL ){
                wait for end of job using UINFO;
        } else if( waitend with PS ){
                send PostScript echo program to printer
                if end_ctrl_t then add ^T
        }
        wait for response
        if( response has end of job indication ) {
                finished = 1;
        }
}
if( pagecount ){
        if( appsocket ){
                close and reopen connection;
        }
        get pagecount using previously described algorithm
}

###---

exit

4.1 Options, Initialization and Setup

The ifhp filter is designed to work with the LPRng print spooler, but will also work with other spooling systems. The LPRng system will set the PRINTCAP_ENTRY environment variable to the current printcap value. By convention, the filter command line -Toptions are reserved for the print spooler to pass configuration information and the -Zoptions are passed by the user. For example, examine the following lpr command and printcap example:

Printcap:
pr:...
  :ifhp=opt1=value1,opt2=value2
  :if=/usr/ifhp -Topt1=value4,opt3=value3

Command:
lpr -Zopt4=value4

PRINTCAP_ENTRY environment variable: 
  pr:...\n
    :ifhp=opt1=value1,opt2=value2\n
    :if=/usr/ifhp -Topt1=value4,opt3=value3\n

Resulting option list:

-Toptions:
  opt1=value4
  opt2=value2
  opt3=value3

-Zoptions:
  opt4=value4

When started, the ifhp filter process the environment and command line options as follows.

  1. If the PRINTCAP_ENTRY environment variable has a value, then this value is used to initialize the -Toption list.
  2. If there is a -Toption command line option, then these values are added to the option list, overriding values from the PRINTCAP_ENTRY set.
  3. The command line -Zoption list is generated by splitting the -Zoption command line option.

The option lists are scanned for values for the debug, trace, config, and model options. These options have the property that once they are set, then they cannot be modified (i.e. - sticky values).

There is another, and rather bizarre way to specify the printer model, and that is the model_from_option option in the configuration file. This option causes the command line options to be scanned, and if there is a value for the command line option then it is used as the model. For example:

model_from_option=Q

The above setting will cause the model to be taken from the Q option. This can be used to select a configuration for the printer based on values specified by the user.

Debug and Trace

The value of the debug option sets the debugging level. It can be increased, but not decreased. The trace flag causes debugging information to be sent to STDERR (file descriptor 2) as well as to the status file.

Configuration File Paths

The main source of configuration information are the configuration files. The

config=pathname,pathname
option can be used to specify the list of configuration files to be read. This can only be done using the PRINTCAP_ENTRY :ifhp entry or the -Tconfig=pathname,pathname command line option.

4.2 Model Selection

The model=name option is used to establishes the model name for extracting configuration information. For details on this, see Configuration Files.

During initialization, the -Toptions list is scanned for a -Tmodel=name entry. Once the model name is set, it cannot be changed. After this, the configuration files are read, and the first model=name option encountered will set the model option to name.

The recommended method of model selection is to specify it in the LPRng printcap entry for the printer, using the :ifhp=... printcap field. For example:

lp:ifhp=model=HP4,status@
  :if=/usr/local/ifhp

Resulting -Toption List:
 model=HP4
 status@

This will cause the -Toption list to be initialized as indicated, and the model option value will be set to HP4.

The next method is use a -Toption command line option.

lp:...
  :if=/usr/local/ifhp -Tmodel=HP4

Resulting -Toption List:
 model=HP4

This will cause the -Toption list to be initialized as indicated, and the model option value will be set to HP4.

Another method is to put the model information in a ./ifhp.conf file in the spool directory of the print queue. The config=/pathname,/pathname,... option specifies the list of configuration files to read, and the default value is:

config=./ifhp.conf,/etc/ifhp.conf,./ifhp.conf

If the model information is put in the ./ifhp.conf configuration file, the first reading will set the model name, and the name is used to select the model information from the /etc/ifhp.conf file. When the ./ifhp.conf is reread, the values in it can be used to override values from the /etc/ifhp.conf file. For example:

./ifhp.conf:
  model=HP4
  lines=66

/etc/ifhp.conf:
[ hp* ]
 lines=60
[ apple* ]
 lines=20

When the ./ifhp.conf is first read, it will establish model=hp (sticky) and lines=66. When the /etc/ifhp.conf file is read, the model name matches the hp* selector (case insensitive GLOB matching is used), and the lines=60 is selected and overrides the lines=66 value. Finally, when the ./ifhp.conf file is reread, lines=66 will establish the final value.

4.3 Statusfile, Statusfile_max, Statusfile_min

The status file pathname is set by the command line -s /pathname or the statusfile=/pathname configuration file entry. If the /pathname file does not exist then it will not be created. If the statusfile is larger than the statusfile_max=max K bytes option value (default 8K), then it will be truncated to statusfile_min=min K bytes.

Summmaryfile

For historical and vintage software compatibility, the summaryfile=/pathname or summaryfile=host%port option will cause either a file to be open or a UDP network connection established to the host and port combination. Debugging or trace information will be written to this file or network connection as well, but the file will be truncated each time, holding only the last line of trace information.

4.4 Operation Configuration Options

The -Toption=value and model configuration information is scanned to set values of options which control filter activity. There are some options whose related actions do not fall into the simple model of string expansion. These usually require generating commands dynamically, or sending files containing font or setup information to the printer. The following is a list of these options.

status and forcestatus FLAGS

These options have the side effect of enabling the reception of status and error information from the printer.

pjl, pcl, ps and text FLAGS

These flags set the languages that are recognized or processed by the filter.

crlf FLAG

The crlf causes LF (\n) to be translated to CR-LF (\r\n) sequences. The following options will turn the ifhp filter into a simple CRLF translation filter. Note that CRLF translation should have no effect on PostScript, Text, or PCL files.

[ myprinter ]
status@
pjl@
ps@
pcl@
text
text_converter_output@
text_converter@
crlf

pjl_job FLAG

If PJL is enabled and this flag is SET, a PJL JOB and PJL EOJ command will be generated and sent to the printer. The JOB command has the form:

@PJL JOB NAME = "..." [ START = nnn ] [ END = mmm ]
The START and END values can be specified by -Zstart=nnn and -Zend=mmm command line options. The EOJ command has must match the JOB command.
@PJL EOJ NAME = "..." [ START = nnn ] [ END = nnn ]

pjl_enter FLAG

If PJL is enabled and this flag is SET, a PJL ENTER LANGUAGE = xx command will be generated when PCL or PS files are sent to the printer.

@PJL ENTER LANGUAGE = PCL
@PJL ENTER LANGUAGE = POSTSCRIPT

nullpad STRING

Some older model HP printers required sending a large number of NULL (0) characters to force commands in the input buffer to be read. This can be done using the nullpad option.

In practice, this has turned out to be largely historical, as most printers do not have this problem.

pjl_console FLAG

When this flag is set, PJL is available, and the PJL RDYMSG command is supported, then a short message will be put on the console.

remove_ctrl STRING

The remove_ctrl string option species a list of (control) characters that will be removed from PostScript jobs. This solves the problem of jobs with embedded Control-T or Control-C characters causing abnormal printer operation. For example:

remove_ctrl=CT
would cause Control-C and Control-T characters to be removed.

tbcp FLAG

The tbcp flag can be specified as a user option as well as a configuration file option. If the file type is PostScript and this flag is set, then the file is transferred using the Transparent Binary Communication Protocol. (See the Adobe PostScript Language Reference Manual for details on the protocol.)

At the start of the PostScript job, the sequence \001 M is sent. Afterwards, all control characters in the set 0x01, 0x03, 0x04, 0x05, 0x11, 0x13, 0x14, 0x1C, are replaced by the two character sequence \001 X+'@' or X+'\100' or is sent. For example:

C\001\003   ->  \001\115\103\001\101\001\103 or \001MC\001A\001C

4.5 Synchronization and Pagecounts

Many printers are able to provide status information back to the filter. It is assumed that in these circumstances file descriptor 1 (FD1) is bidirectional and status information can be read from it. When the status or forcestatus option is TRUE, then the filter assumes that it can read FD1. In order to simplify configuration, the ifhp filter will test FD1, and if it is not a serial port or a network socket, will set status@ or OFF.

However, there are some devices such as bidirectional printer ports that will report status. By setting forcestatus ON, the filter can be forced to check for status. This can have fatal or unexpected effects if status is not returned correctly.

Synchronization is usually done in order to ensure that a previously spooled job or printer action has completed correctly, and the printer is ready to accept a new job. It is usually carried out by sending a request to the printer to echo a string back to the filter. Clearly, if the printer cannot provide status or echo values back, then synchronization is impossible.

The value of the sync option determines if a PJL ECHO command or simple PostScript program is used. The PostScript program has the form:

\004%!PS-Adobe-2.0
( %%[ echo: TODSTR ]%% ) print () = flush
\004

where TODSTR is replaced with the current Time of Day.

To control obtaining synchronization, the and sync_timeout=nnn options are used. The PJL or PS command is repeated at sync_interval=nnn second intervals; if nnn is 0, then it is sent only once. If synchronization is not obtained within sync_timeout=nnn seconds, then the filter exits with an error status. A 0 value or sync_timeout@ disables timeouts.

Pagecounts are used to do accounting and report the number of pages used for a job. Most printer have a hardware based pagecounter mechanism whose value can be read by the appropriate PJL command or PostScript program. For example, if the PJL INFO command

@PJL INFO PAGECOUNT
is supported by a printer, the printer will return a status message containing the current pagecounter value. Printers that support PostScript may also be able to access the pagecounter value using a PostScript program. The exact details of the PostScript program vary from vendor to vendor and the pagecount_ps_code=... option specifies the PostScript program to use. For example:
pagecount_ps_code=
  /p {print} def ( %%[ pagecount: ) p
  statusdict begin pagecount end 20 string cvs p
  ( ]%% ) p () = flush

Pagecounting is supported by the pagecount=language, pagecount_interval=nnn, and pagecount_timeout=nnn options. The pagecount=language option enables pagecounting, and sets the language to be used. Currently ps (PostScript) and pjl (PJL) are supported. The pagecount request is repeated every pagecount_interval=nnn second intervals; if nnn is 0, then it is sent only once. If no pagecount value is obtained within pagecount_timeout=nnn seconds, then the filter exits with an error. A 0 value or sync_timeout@ disables timeouts.

Some printers do not correctly report end of job and must be polled until the pagecount information stabilizes. The PJL TEOJ (True End Of Job) PJL has been tried with limited success on various printers to force End of Job reporting only when the job has finished.

pjl_init=[ ... teoj ... ]
pjl_teoj=@PJL TEOJ=ON

4.6 PJL Initialization

If a printer supports PJL, the many printer operations can be initiated and controlled using PJL commands. Unfortunately, not all printers support the same set of commands. In addition, not all printers support the same set of operations or options. A PJL command has the form:

@PJL COMMAND OPTION OPTION ...
A PJL variable is set using:
@PJL SET var = value ...
The pjl_only=[ ... ], pjl_except=[ ... ], pjl_vars_set=[ ... ], and pjl_vars_except=[ ... ] options are used to control which PJL commands and which PJL variables can be set. The pjl_only variable lists the commands supported by the printer, and the pjl_except lists commands not supported by the printer. Before sending a PJL command, the ifhp filter checks to make sure that the command name is in pjl_only and not in pjl_except. If the tests fail, then tne command is not sent.

Similarly, when sending a command to set a PJL variable, the pjl_vars_set and pjl_vars_except lists are checked to determine if the variable name is in pjl_vars_set and not in pjl_except list. If the tests fail, then tne command is not sent.

If PJL is enabled, then the following actions are taken.

  1. PJL Universal Exit Language (UEL) \033%-12345X is sent to the printer.

    This is required to ensure that the following PJL commands are accepted.

  2. PJL JOB command is sent at the start of job. The JOB command can be used to select pages or impressions to be printed. If the -Zstartpage=nnn or -Zendpage=mmm option is present, then the PJL JOB command has the form:
    @PJL JOB START=nnn END=mmm
  3. The pjl_init=[ ... ] value option is expanded using the PJL ("pjl_") language context as described above.
  4. The -Toption=values and -Zoption=values are scanned for matching option names in the pjl_user_opts=[ ... ] list. If they are found, then the options are recursively evaluated in the PJL language context. The expansion algorithm will cause the option value to be used to set PJL variables. For example:
    Configuration:
      pjl_vars_set=[ OUTBIN AUTOSELECT JAM=YES ]
    
    Command
      ifhp -Zoutbin=upper,autoselect,jam
    
    PJL command generated:
      @PJL SET OUTBIN=UPPER
      @PJL SET AUTOSELECT=ON
      @PJL SET JAM=YES
    

4.7 File Conversion Support

Many PostScript printers cannot handle text files, and produce many hundreds of pages of garbage output if they are sent to the printer without being translated into PostScript. Also, while most PCL printers will accept text files and do a reasonable job of printing them some form of initialization strings or setup may need to be done. These problems usually require some sort of file type determination and conversion facility.

File Type Determination and Conversion

You can use the more flexible and powerful UNIX file(1) program to determine the file type, and then determine a converter program to use.

When spooling a file, a user can specify that its format is l (literal). The LPRng spooler will pass a special -c command line option which suppresses any file type checks by ifhp.

If the file is not a literal file, then the forceconversion option will cause ifhp to use the UNIX file utility to determine the file type and any conversion programs to invoke. The following section from the default ifhp.conf file shows how this is done:

Configuration:
default_language=unknown
force_conversion
##  file utility path
file_util_path=/usr/bin/file -
##  patterns and outputs
file_output_match = [
 *postscript*  ps
 *pcl*         pcl
 *pjl*         raw
 *%20gif%20*   ps  /usr/local/bin/gif2ps
 *text*  ps /usr/local/bin/a2ps -q -B -1 -M Letter --borders=no -o-
 ]

The file_util_path option specifies the path to the UNIX file program. This version should be capable determining the file type on its STDIN (file descriptor 0), and should produce file type information on STDOUT. The file_output_match entry consists of a list of lines containing a (URL encoded) glob pattern, a language type (ps, pcl, or raw), and an optional conversion program specification.

Alternatively, it can have the form:

file_output_match = </pathname

This will cause the indicated file to be opened and read to obtain the output match values.

The file utility is run and its output is matched against the specified glob patterns. If a space or tab needs to be in the glob pattern, the glob pattern can be URL encoded.

The converted or detected file language type is set to the second entry, and the optional conversion program is run with STDIN set to the original input file and the conversion program output is sent to the printer. If no conversion program is specified, then the original file is used.

If the conversion program specification contains one or more of the shell metacharacters |, <, or <, then it will be invoked using the /bin/sh -c filterprogram. This allows users to specify some rather bizzare conversion programs and to chain together conversion programs. For example, if you have an Epson printer, then you can convert PostScript to suitable Epson format and text to Epson format using the following entries. Note that line breaks have been inserted for clarity; all conversion program specifications must be on a single line:

 # invoked via execve
 *postscript*  raw \
   gs -sDEVICE=epson \
        -sOutputFile=- -sPAPERSIZE=letter -q -
 # invoked via /bin/sh -c
 *text*  raw \
    a2ps -q -o- -M letter | \
    gs -sDEVICE=epson \
       -sOutputFile=- -sPAPERSIZE=letter -q -

If no match for the file type is found, then the file language is set to the default_language value.

If force_conversion is not set, then the ifhp filter will attempt to determine if the input file language is PJL, PCL, or simple text using the algorithm similar to the UNIX file program. It will then use the file_output_match entries to specify a conversion program.

If the detected file type is text, no conversion program found, and the text_converter option is defined, then this value is used as the conversion program, and the output will be specified by the text_conversion_format value. The text_tempfile value is used as a template for temporary file locations, and usually defaults to /var/tmp.

If the detected file type is unknown or not supported by the printer then the file is not printed.

In order to support a flexible conversion strategy, the following substitutions are made in the conversion program options.

  1. Configuration variable name value will be substituted for \%{name}.
  2. The -Z and -T options will be substituted for the word ZOPTS and TOPTS respectively.
  3. The argument list to the filter will be substituted for the work ARGV. This allows access to the entire argument list passed to the ifhp filter.

No Textfile Conversion Needed

If your printer can handle text files without conversion, but require PCL initialization, then the following combination will simply set the language to pcl:

file_output_match = [
 *text*  pcl
 ]

Default Passthrough of Unknown File Types

Your printer may be capable of handling a wide variety of job formats. If you want to simply pass through files of unknown type or language then use:

file_output_match = [
 *  raw
 ]

4.8 Language Specific Initialization

After determining the output file language type, language specific operations are then carried out by expanding the language__init=[ ... ] options in the language context, and then the options in the -Toption=value and -Zoption=value command line options. The -T options are expanded before the -Z, allowing the -Z actions to override any set by the -T actions.

As mentioned elsewhere, the reason for the language specific processing is to allow different actions for the same command line option, depending on the file type that is being processed. For example, when processing a PCL file it might be necessary to send PCL command strings and when processing a PostScript file, you would need to send PostScript commands.

4.9 File Transfer and Error Status Monitoring

If the printer can return status, i.e., the status or forcestatus flag is set, then the ifhp filter will read status information back from the printer.

If the logall flag is SET, then all error messages will be written to the status or log file.

If the printer is returning PJL status information, then this has a specific format:

@PJL UINFO DEVICE
CODE=nnnn
DISPLAY="value"
...

@PJL UINFO JOB
START
...

@PJL UINFO JOB
END
...

The ifhp program will extract the CODE and job start and end flags, and log these as appropriate.

Unfortunately, some PJL based printers are extremely verbose in their generation of status messages. In order to reduce the amount of logging of redundant information, ifhp will only record when a device status has changed, rather than when it has been reported.

The pjl_quiet_codes=[ code code code ] value is used to suppress reporting of selected error codes. If the error code is in the pjl_quiet_codes list, then the error status will not be reported to the user unless the logall option is set. For example:

  pjl_quiet_codes=[ 10000 10001 10003 10023 10024 35078 ]

Also, there may be error codes which does not have a builtin error message available. New messages can be added using the pjl_error_codes option. Its value is a list of lines, each line consisting of an error code followed by the corresponding error message:

pjl_error_codes=[
   code=msg
   code=msg
   ...
]

Example:
  pjl_error_codes=[
     10000=powersave mode
     10001=Ready Online
     10002=Ready Offline
     10003=Warming Up
     10004=Self Test
     10005=Reset
  ]

4.10 End of Job

The waitend option controls the job termination sequence. By default, this will do the same work as the sync operation, and the option takes the same set of values.

If waitend is suppressed using waitend@, then as soon as a job has been transferred, the next step, pagecount, will be attempted. If the print job has not finished at this point, then erroneous page counts will be reported.

When using the appsocket protocol, then suppressing waitend will cause no error messages from the printer to be reported.

Some printers do not have a True End Of Job reporting capability using PJL. This means that the job will be reported as done, but paper is still moving through the print engine. If you try to get pagecounts at this point you will get the wrong value. An alternative method is to set waitend=ps and The end_ctrl_t=word:word:... This will cause a CONTROL-T to be sent to the printer, a PostScript convention that will cause the PostScript interpreter to return the actual printing status. In most printers this will be printing or something other than idle or busy as long as paper is moving in the print engine. When status is returned, the words in the end_ctrl_t=word:word:... list value are examined for a match. If the status word is present then the end of job condition is assumed.

The waitend_interval value controls how often the waitend operation is repeated. This is usually set to a fairly large value, as it is normally used only to recover from printer failures such as users turning the printer on and off.

The waitend_ctrl_t_interval controls how often the printer is queried for status using CTRL-T and is usually set to a short (2 or 3 second) value.

4.11 Tektronix Phaser, QMS and AppSocket Support

The Tektronix Phaser PostScript and QMS printers uses the AppSocket protocol for sending a job to the printer over a network connection. The appsocket flag enables this operation. The protocol is (briefly):

  1. The Tektronix printer listens for TCP/IP connections on port 9100 and for UDP packets on port 9101 (the UDP port is the TCP/IP port + 1). The QMS printers listen on UDP port 35 and TCP/IP port 35 (the UDP and TCP ports have the same number). These port numbers can be modified using the printer control panel configuration and setup menus, or via the network configuration utilities.
  2. When a UDP packet is received on the UDP port a reply packet containing status information is returned to the originator's address. This packet contains an status indication, in a undefined format.
  3. To send a job to the printer, a TCP/IP connection is opened to the TCP port and a PostScript job is sent. Only a single job can be sent at a time - a EOJ (CTRL-D) will terminate input and flush all following jobs.
  4. Return status will be sent in the reverse direction until the job has completed, at which point the connection will be closed.

To use this protocol, the printer TCP/IP address and port must be specified using the -Tdev=host%port option (port is usually 9100 for TEK and 35 for QMS) and the -Tappsocket option specified. If a QMS printer is being used, then -Tappsocket,qms is specified.

Also, the printer device in the printcap entry should be lp=/dev/null.

When using the Appsocket protocol, the ifhp filter will open a UDP port and use it to send query packets to the printer UDP port 9101. In addition, it will try to open a connection to port 9100. When a connection has been established, and pagecount has been determined, the connection will be close and reopened.

After job transfer, the connection will be half-closed. That is, the shutdown() facility will be used to cause the TCP/IP connection to be set to closed for transmission but open for reception. The printer will send status information until the job is completed, and then close the connection.

If page count information is needed, the ifhp filter will then reopen the connection and get the page count information.


Next Previous Contents