<!DOCTYPE book
  SYSTEM "IFHP-Reference.dtd"
 -- PUBLIC "-//FreeBSD//DTD DocBook V3.1-Based Extension//EN" --
 -- PUBLIC "-//OASIS//DTD DocBook V3.1//EN" --
[
  <!ENTITY LPRng "<application/LPRng/">
  <!ENTITY IFHP "<application/ifhp/">
]>

<book>
<bookinfo>
<title> IFHP Reference Manual</title>
<subtitle> 5 Oct 2004 (For ifhp-3.5.20)</subtitle>

<author>
<firstname>Patrick</firstname>
<othername role=mi>A</othername>
<surname>Powell</surname>
<affiliation>
<address>
<email>papowell@astart.com</email>
AStArt Technologies addr
6741 Convoy Court,
San Diego, CA 92111
Phone <phone>858-874-6543</phone>
Fax <fax>858-751-2435</fax>
</address>
</affiliation>
</author>
<copyright>
<year>2002</year>
<holder role="mailto:papowell@astart.com">Patrick Powell</holder>
</copyright>

<releaseinfo>$Id: IFHP-Reference.sgml,v 1.14 2004/10/05 15:50:15 papowell Exp papowell $</releaseinfo>

	<legalnotice>
	 <important>
	<para>
		THIS DOCUMENTATION AND THE DESCRIBED SOFTWARE IS PROVIDED BY
      THE AUTHORS "AS IS" AND ANY
	  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
	  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
	  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
	  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
	  DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
	  DAMAGE.</para>
      </important>
    </legalnotice>

<abstract><para>The &IFHP; program is an enhanced, extended, highly configurable,
and portable implementation of a print filter for use with the &LPRng;
Print spooler package.
<literal>&IFHP;</literal> supports network, serial, and parallel printers,
does page accounting and job recovery,
and allows an extremely high level of configuration and tuning.
<literal>&IFHP;</literal> gets its flexibility by using a configuration file
to set its operational characteristics.  The configuration file can contain
multiple separate printer configurations and the configuration selection is done
by a very simple command line option.
The filter supports text,  PostScript,
PCL, and PJL printers, and can be configured to handle a wide range of
printer quirks and mis-implementations.</para></abstract>

</bookinfo>

<preface>
<title>Preface</title>

<sect1><title>Introduction</title>
<para>
The &IFHP; Print Filter is the primary print filter for the &LPRng;
Print Spooler.
This document is designed to be the single basic reference for the
&IFHP; software;
the &LPRng; software is distributed separately
and has additional documentation.
</para>
</sect1>

<sect1>
<title>Acknowledgements</title>
<para>I would like to thank all of the &LPRng; users
who so relentlessly tried the incredible number of permutations and
combinations of printers and software,
and whose requests for <emphasis>just one more feature</emphasis>
led to the development of the software.
</para>
</sect1>

    <sect1>
      <title>Shell Prompts</title>

      <para>The following table shows the default system prompt and superuser
	prompt. The examples will use this prompt to indicate which user you
	should be running the example as.</para>

      <informaltable frame="none">
	<tgroup cols="2">
	  <thead>
	    <row>
	      <entry>User</entry>
	      <entry>Prompt</entry>
	    </row>
	  </thead>

	  <tbody>
	    <row>
	      <entry>Normal user</entry>
	      <entry><prompt>%</prompt></entry>
	    </row>

	    <row>
	      <entry><literal>root</literal></entry>
	      <entry><prompt>#</prompt></entry>
	    </row>
	  </tbody>
	</tgroup>
      </informaltable>
    </sect1>

    <sect1>
      <title>Typographic Conventions</title>

      <para>The following table describes the typographic conventions used in
	this book.</para>

      <informaltable frame="none">
	<tgroup cols="2">
	  <thead>
	    <row>
	      <entry>Meaning</entry>
	      <entry>Examples</entry>
	    </row>
	  </thead>

	  <tbody>
	    <row>
	      <entry>The name of commands, files, and directories. On screen
		computer output.</entry>
	      <entry><para>Edit your <filename>.login</filename>
		  file.</para><para>Use <command>ls -a</command> to list all
		  files.</para><para><screen>You have mail.</screen>
		</para></entry>
	    </row>

	    <row>
	      <entry>What you type, when contrasted with on-screen computer
		output.</entry>

	      <entry><screen><prompt>%</prompt> <userinput>su</userinput>
Password:</screen></entry>
	    </row>

	    <row>
	      <entry>Manual page references.</entry>

	      <entry>Use <citerefentry>
		  <refentrytitle>su</refentrytitle>
		  <manvolnum>1</manvolnum>
		</citerefentry> to change user names.</entry>
	    </row>

	    <row>
	      <entry>User and group names</entry>

	      <entry>Only <literal>root</literal> can do this.</entry>
	    </row>

	    <row>
	      <entry>Emphasis</entry>

	      <entry>You <emphasis>must</emphasis>
do this.</entry>
	    </row>

	    <row>
	      <entry>Command line variables; replace with the real name or
		variable.</entry>

	      <entry>To delete a file, type <command>rm <filename><replaceable>filename</replaceable></filename></command></entry>
	    </row>

	    <row>
	      <entry>Environment variables</entry>

	      <entry><envar>$HOME</envar> is your home directory.</entry>
	    </row>
	  </tbody>
	</tgroup>
      </informaltable>
    </sect1>

    <sect1>
      <title>Notes, warnings, and examples</title>

      <para>Within the text appear notes, warnings, and examples.</para>

      <note>
	<para>Notes are represented like this, and contain information that
	  you should take note of, as it may affect what you do.</para>
      </note>

      <warning>
	<para>Warnings are represented like this, and contain information
	  warning you about possible damage if you do not follow the
	  instructions. This damage may be physical, to your hardware or to
	  you, or it may be non-physical, such as the inadvertant deletion of
	  important files.</para>
      </warning>

      <informalexample>

	<para>Examples are represented like this, and typically contain
	  examples you should walk through, or show you what the results of a
	  particular action should be.</para>
      </informalexample>
    </sect1>

  </preface>
<chapter>
<title>Introduction</title>

<para>The &IFHP; print filter is the latest in a long evolutionary path
of print filters for the &LPRng; print spooler system.
It unifies the low level printer communication facilities
and provide a common code base for future development.</para>

<para>This document is the complete set of references and
installation guide for the &IFHP; print filter.
It covers compilation, installation,
initial testing,
details of system configuration,
and configuration options that would be needed by the
system administrator.
Previous releases of &IFHP; had a large selection of
<acronym>README</acronym>
files
which are now incorporated into the IFHP Reference Manual.</para>

<para><anchor id="website">
Information
about &LPRng; and &IFHP; can be found on the &LPRng; web page
<ulink URL="http://www.lprng.com">http://www.lprng.com</ulink>.</para>

<para><anchor id="maillist">
There is mailing list for &IFHP; and &LPRng; at <email>lprng@lprng.com</email>.
In order to reduce the amount of unsolicited <emphasis>spam</emphasis> mail posted to the list
you must subscribe to the list before posting to it.
To subscribe,
send email message to
<emphasis remap=tt><ulink URL="mailto:lprng-request@lprng.com">lprng-request@lprng.com</ulink></emphasis>,
with the single word <emphasis>subscribe</emphasis> in the body.</para>

<para>Several presentations of &LPRng; and print spooling software have been made
at the Large Scale Installation Administrator (LISA) conferences and
are in the &IFHP; distribution and available on web sites.
The slides for the LISA 97 tutorial on
<ulink URL="ftp://ftp.lprng.com/pub/LPRng/LISA97.tgz">Printers and Network Print Spooling</ulink>
are the <filename>LISA97.ppt</filename> in the
&LPRng; distribution.</para>

<para>During development of &IFHP;, the following documents were invaluable
references.
For Printer Job Language (PJL) related issues
see the Printer Job Language Technical Reference Manual,
Hewlett Packard, 10th Edition, October 1997.
For PCL related issues see
the PCL 5 Printer Language Technical Reference Manual,
First Edition, 1992.
These manuals are available through the Hewlett Packard Developers Program.
See
<ulink URL="http://www.hp.com/go/devexchange">http://www.hp.com/go/devexchange</ulink>
for information on how to join.</para>


<sect1>
<title>Copyright and Disclaimer</title>

<para>Material included in this document from the &IFHP; distribution
Copyright Patrick Powell 1988-1999, where applicable.
The rights to distribute this document complete or in part are hereby
granted for non-commercial purposes. Partial reproductions must
acknowledge the source.
Permission to distribute this file together with &LPRng;, &IFHP; and `derived
works' is explicitly granted.</para>

<para><emphasis remap=bf>THE MATERIAL IN THIS DOCUMENT IS PROVIDED WITHOUT FEE AND AS-IS WITH NO
WARRANTY REGARDING FITNESS OF USE FOR ANY PURPOSE. THE AUTHOR AND ALL
CONTRIBUTORS ARE NOT LIABLE FOR ANY DAMAGES, DIRECT OR INDIRECT,
RESULTING FROM THE USE OF INFORMATION PROVIDED IN THIS DOCUMENT.</emphasis></para>

</sect1>

<sect1>
<title>Commercial Support</title>

<para><ulink URL="http://www.astart.com">AStArt Technologies (http://www.astart.com)</ulink>
provides commercial support and enhancements for
&LPRng;, &IFHP;, and other network software.
AStArt provides network and system consulting services for UNIX and NT
systems, as well as real time and network software.</para>

</sect1>

<sect1>
<title>Web Site</title>

<para>Web Page:
<ulink URL="http://www.lprng.com">http://www.lprng.com</ulink></para>

</sect1>


<sect1
id="secftp">
<title>FTP Sites
</title>

<para>Main FTP Site:
<simplelist type=vert columns=1>
<member>
<ulink URL="ftp://ftp.lprng.com/pub/LPRng">ftp://ftp.lprng.com/pub/LPRng</ulink> (US)
</member>
</simplelist>
</para>

<!-- MIRRORSTART -->
<para>Mirrors:<!-- <br> -->
<simplelist type=vert columns=1>
<member><ulink URL="ftp://ftp.u-aizu.ac.jp/pub/net/lpr/LPRng">ftp://ftp.u-aizu.ac.jp/pub/net/lpr/LPRng</ulink> (JA) </member>
<member><ulink URL="ftp://ftp.cs.columbia.edu/pub/archives/pkg/LPRng">ftp://ftp.cs.columbia.edu/pub/archives/pkg/LPRng</ulink> (US) </member>
<member><ulink URL="ftp://ftp.cise.ufl.edu/pub/mirrors/LPRng">ftp://ftp.cise.ufl.edu/pub/mirrors/LPRng</ulink> (US) </member>
<member><ulink URL="ftp://ftp.cs.umn.edu/pub/LPRng">ftp://ftp.cs.umn.edu/pub/LPRng</ulink> (US) </member>
<member><ulink URL="ftp://uiarchive.uiuc.edu/pub/ftp/ftp.lprng.com/pub/LPRng">ftp://uiarchive.uiuc.edu/pub/ftp/ftp.lprng.com/pub/LPRng</ulink> (US) </member>
<member><ulink URL="ftp://ftp.sage-au.org.au/pub/printing/spooler/lprng/">ftp://ftp.sage-au.org.au/pub/printing/spooler/lprng/</ulink> (AU) </member>
<member><ulink URL="ftp://mirror.aarnet.edu.au/pub/LPRng/">ftp://mirror.aarnet.edu.au/pub/LPRng/</ulink> (AU/NZ) </member>
<member><ulink URL="http://mirror.aarnet.edu.au/pub/LPRng/">http://mirror.aarnet.edu.au/pub/LPRng/</ulink> (AU/NZ) </member>
<member><ulink URL="ftp://sunsite.ualberta.ca/pub/Mirror/LPRng">ftp://sunsite.ualberta.ca/pub/Mirror/LPRng</ulink> (CA) </member>
<member><ulink URL="ftp://ftp.informatik.uni-hamburg.de/pub/os/unix/utils/LPRng">ftp://ftp.informatik.uni-hamburg.de/pub/os/unix/utils/LPRng</ulink> (DE) </member>
<member><ulink URL="ftp://ftp.uni-paderborn.de/pub/unix/printer/LPRng">ftp://ftp.uni-paderborn.de/pub/unix/printer/LPRng</ulink> (DE) </member>
<member><ulink URL="ftp://ftp.mono.org/pub/LPRng">ftp://ftp.mono.org/pub/LPRng</ulink> (UK) </member>
<member><ulink URL="ftp://ftp.iona.com/pub/plp/LPRng">ftp://ftp.iona.com/pub/plp/LPRng</ulink> (IE) </member>
<member><ulink URL="ftp://uabgate.uab.ericsson.se/pub/unix/LPRng">ftp://uabgate.uab.ericsson.se/pub/unix/LPRng</ulink> (SE) </member>
</simplelist>
</para>
<!-- MIRROREND -->

</sect1>

<sect1>
<title>Mailing List</title>

<para>To join the &LPRng; mailing list, please send mail to
<ulink URL="mailto: lprng-request@lprng.ie">lprng-request@lprng.ie</ulink> with the only the
word <emphasis>subscribe</emphasis> in the body of the message.
<anchor id="faqref"></para>

</sect1>

<sect1>
<title>PGP Public Key</title>

<para>The &LPRng; and &IFHP; distributions have MD5 checksum files
which are signed with a PGP public key.
Here is the key for validating the checksums:
<informalexample>
<screen>Type Bits/KeyID    Date       User ID
pub  1024/00D95C9D 1997/01/31 Patrick A. Powell &lt;papowell@astart.com&gt;
							  Patrick A. Powell &lt;papowell@sdsu.edu&gt;

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3i

mQCNAzLygTQAAAEEANBW5fPYjN3wSAnP9xWOUc3CvsMUxjip0cN2sY5qrdoJyIhn
qbAspBopR+tGQfyp5T7C21yfWRRnfXmoJ3FVtgToAsJUYmzoSFY08eDx+rmSqCLe
rdJjX8aG8jVXpGipEo9U4QsUK+OKzx3/y/OaK4cizoWqKvy1l4lEzDsA2VydAAUT
tCdQYXRyaWNrIEEuIFBvd2VsbCA8cGFwb3dlbGxAYXN0YXJ0LmNvbT6JAJUDBRA0
XonoiUTMOwDZXJ0BAQ2cBAC7zU9Fn3sC3x0USJ+3vjhg/qA+Gjb5Fi1dJd4solc4
vJvtf0UL/1/rGipbR+A0XHpHzJUMP9ZfJzKZjaK/d0ZBNlS3i+JnypypeQiAqo9t
FV0OyUCwDfWybgAORuAa2V6UJnAhvj/7TpxMmCApolaIb4yFyKunHa8aBxN+17Ro
rrQlUGF0cmljayBBLiBQb3dlbGwgPHBhcG93ZWxsQHNkc3UuZWR1PokAlQMFEDLy
gTSJRMw7ANlcnQEBYBYD/0zTeoiDNnI+NjaIei6+6z6oakqO70qFVx0FG3aP3kRH
WlDhdtFaAuaMRh+RItHfFfcHhw5K7jiJdgKiTgGfj5Vt3OdHYkeeh/sddqgf9YnS
tpj0u5NfrotPTUw39n6YTgS5/aW0PQfO9dx7jVUcGeod1TGXTe9mIhDMwDJI4J14
=3Zbp
-----END PGP PUBLIC KEY BLOCK-----</screen>
</informalexample>
</para>

</sect1>
</chapter>

<chapter>
<title>Software Installation and Configuration</title>

<para>Before you do an installation
please read the following instructions.
You will need to:
<orderedlist>

<listitem>
<para>Use GNU Make.  You can get it from
<ulink URL="http://www.gnu.org/software/software.html">http://www.gnu.org/software/software.html</ulink>.
Don't even think about trying to use another
make unless you are a Wizard.  And even the Wizards use GNU Make.</para>
</listitem>

<listitem>
<para>Use an ANSI C compiler.
&IFHP; is developed and tested with the GNU C compiler.
You can get it from
<ulink URL="http://www.gnu.org/software/software.html">http://www.gnu.org/software/software.html</ulink>.
Solaris users should consult the excellent
<ulink URL="http://sunfreeware.com">http://sunfreeware.com</ulink>
site for binary distributions.
AIX users can use
<ulink URL="http://www.bull.de/pub/">http://www.bull.de/pub/</ulink>
or <ulink URL="ftp://ftp.htwk-leipzig.de">ftp://ftp.htwk-leipzig.de</ulink></para>
</listitem>

</orderedlist>
</para>


<sect1>
<title>Additional Recommended Software</title>

<para>The following software is recommended for use with &IFHP;.
If your printer does not support PostScript, PCL, or text printing directly
you will need to install GhostScript to convert from PostScript to the printer
format and use a suitable text to PostScript converter.
<variablelist>
<varlistentry><term>Unix File Utility</term>
<listitem>
<para><anchor id="fileutil">
The &IFHP; filter will recognize that a file
is PostScript, PJL, or PCL by examining the first
couple of bytes of a file and applying a simple set of rules.
If you require more elaborate file type detection then you can
configure &IFHP; to also use the UNIX <emphasis remap=tt>file</emphasis> utility
if it is unable to determine the file type.
See
<ulink URL="ftp://ftp.astron.com/pub/file/">
ftp://ftp.astron.com/pub/file/</ulink>
or
<ulink URL="ftp://ftp.lprng.com/pub/LPRng/UNIXTOOLS/file/">
ftp://ftp.lprng.com/pub/LPRng/UNIXTOOLS/file/</ulink>
to obtain this software.</para>


</listitem>
</varlistentry>

<varlistentry><term>&LPRng; Print Spooler</term>

<listitem>
<para><ulink URL="http://www.lprng.com">http://www.lprng.com</ulink>
The &IFHP; filter works best with the later versions of this software,
and the two are developed as an integrated unit.</para>


</listitem>
</varlistentry>

<varlistentry><term>GhostScript</term>

<listitem>
<para><anchor id="ghostscript">
<ulink URL="http://www.cs.wisc.edu/~ghost/index.html">http://www.cs.wisc.edu/~ghost/index.html</ulink>
or
<ulink URL="http://www.ghostscript.com/">http://www.ghostscript.com</ulink>
If your printer does not handle PostScript and you need to print PostScript,
GhostScript is used to convert PostScript to a format usable by the printer.</para>
</listitem>
</varlistentry>
<varlistentry><term>a2ps - Ascii Text To PostScript Converter</term>

<listitem>
<para><anchor id="a2ps">
If your printer is a PostScript only printer or you wish to have enhanced
formatting capability for documents,  then you will need a text to PostScript converter.
<ulink URL="http://www-inf.enst.fr/~demaille/a2ps/">http://www-inf.enst.fr/~demaille/a2ps/</ulink>
This package does a very good job of text to PostScript conversion.
It also makes use of the
<link linkend="fileutil">file utility</link>
to determine the required conversions.</para>


</listitem>
</varlistentry>

<varlistentry><term>enscript - GNU Enscript</term>

<listitem>
<para><anchor id="enscript">
<ulink URL="http://www.gnu.org">http://www.gnu.org/</ulink>
This package is an alternative to <literal>a2ps</literal>,
but requires careful handling due to the exit codes it produces.
Please see
<link linkend="conversion">Wrappers For Programs</link> for details on how to use
<literal>enscript</literal> with &IFHP;.</para>

</listitem>
</varlistentry>

<varlistentry><term>textps</term>

<listitem>
<para><anchor id="textps">
This program is included with the &IFHP; distribution
and is an extremely primitive text to PostScript filter.
It generates PostScript compatible with even the most ancient
of PostScript printers and is useful where
<literal>a2ps</literal> and <emphasis remap=tt>enscript</emphasis> are just too modern.
See
<ulink URL="http://www.lprng.com">http://www.lprng.com</ulink>.</para>


</listitem>
</varlistentry>

<varlistentry><term>psutils</term>

<listitem>
<para><anchor id="psutils">
The <literal>psutils</literal> package
developed by Angus Duggan is available from
<ulink URL="ftp://ftp.dcs.ed.ac.uk/pub/ajcd/">ftp://ftp.dcs.ed.ac.uk/pub/ajcd/</ulink>.
These are a collection of programs for manipulation of
PostScript files,
and include facilities for doing page selection,
page reversal, n-up printing,  and watermarking.</para>


</listitem>
</varlistentry>

<varlistentry><term>netcat</term>

<listitem>
<para><anchor id="netcat">
The <literal>netcat</literal> utility is extremely useful when trying to
send files to a network printer and you need to monitor its
activity.
Developed by <email>hobbit@avian.org</email>, it is available from
<ulink URL="ftp://avian.org/src/hacks/nc110.tgz">ftp://avian.org/src/hacks/nc110.tgz</ulink>.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Installation</title>

<para>The installation procedure uses the <literal>configure</literal>
facility to generate Makefiles.
By convention,
these files have the following variables that install
the &IFHP; executables and configuration files
in the following locations:
</para>
<table> <title>Configure File Location Variables</title>
<tgroup cols=4 align=left>
<thead>
<row><entry>Configure Variable</entry><entry>Default Value</entry>
<entry>Expanded Default Value</entry>
<entry>Override</entry> </row>
</thead>
<tbody>
<row><entry><literal>${prefix}</literal></entry><entry><literal>/usr/local</literal></entry><entry><literal>--prefix=PATH</literal></entry></row>
<row><entry><literal>${exec_prefix}</literal></entry><entry><literal>${prefix}</literal></entry><entry><literal>/usr/local</literal></entry><entry><literal>--execprefix=PATH</literal></entry></row>
<row><entry><literal>${bindir}</literal></entry><entry><literal>${exec_prefix}/bin</literal></entry><entry><literal>/usr/local/bin</literal></entry><entry><literal>--bindir=PATH</literal></entry></row>
<row><entry><literal>${sbindir}</literal></entry><entry><literal>${exec_prefix}/sbin</literal></entry><entry><literal>/usr/local/sbin</literal></entry><entry><literal>--sbindir=PATH</literal></entry></row>
<row><entry><literal>${libexecdir}</literal></entry><entry><literal>${exec_prefix}/libexec</literal></entry><entry><literal>/usr/local/libexec</literal></entry><entry><literal>--libexecdir=PATH</literal></entry></row>
<row><entry><literal>${sysconfdir}</literal></entry><entry><literal>${prefix}/etc</literal></entry><entry><literal>/usr/local/etc</literal></entry><entry><literal>--sysconfdir=PATH</literal></entry></row>
<row><entry><literal>${mandir}</literal></entry><entry><literal>${prefix}/man</literal></entry><entry><literal>/usr/local/man</literal></entry><entry><literal>--mandir=PATH</literal></entry></row>
</tbody>
</tgroup>
</table>

<para>The following files are installed as shown below:
<table>
<title>Executable and Configuration File Locations</title>
<tgroup cols=2 align=left>
<thead>
<row><entry>Configure Variable</entry><entry>Files</entry></row>
</thead>
<tbody>
<row><entry><literal>${libexecdir}/filters</literal></entry><entry><literal>lpf, ifhp</literal></entry></row>
<row><entry><literal>${sysconfdir}</literal></entry><entry><literal>ifhp.conf</literal></entry></row>
<row><entry><literal>${mandir}/man[1-9]</literal></entry><entry><literal>man pages</literal></entry></row>
</tbody>
</tgroup>
</table>

</para>

<para>The configuration you choose should match that of the
&LPRng; print spooler.  For example:
<informalexample>
<screen>./configure --prefix=/usr --sysconfdir=/etc \
  --mandir=/usr/share/man

executables and files in
   /usr/libexec/filters         ifhp
   /etc                         ifhp.conf
   /usr/share/man/man[0-9]      ifhp.man1</screen>
</informalexample>
</para>

<para>First,  we untar,  configure,  compile, and install the software:
<informalexample>
<screen><prompt>h4: {1} % </prompt><userinput>gunzip -c ifhp-&lt;version&gt;.tgz | tar xvf -</userinput>
<prompt>h4: {2} % </prompt><userinput>cd ifhp-&lt;version&gt;</userinput>
<prompt>h4: {3} % </prompt><userinput>./configure  [ ... configuration options ]</userinput>
<prompt>h4: {4} % </prompt><userinput>make clean all</userinput>
<prompt>h4: {5} % </prompt><userinput>su   # you must do the following commands as root</userinput>
<prompt>h4: {6} # </prompt><userinput>make install</userinput></screen>
</informalexample>
</para>

<para>Modify your printcap file to use &IFHP;.
Your printcap usually has the following format;
older version of <application/lpd/ require <emphasis remap=tt>:\</emphasis> at the end of each
line of a printcap entry.
The <emphasis remap=tt>:if</emphasis> and <emphasis remap=tt>:of</emphasis> filter entries are usually the ones of interest.
<informalexample>
<screen>lp:
  :lp=xxxx:sd=xxxx:....
  :if=/usr/local/path_to_old_filters/old_if_filter
  :of=/usr/local/path_to_old_filters/old_of_filter</screen>
</informalexample>
</para>

<para>Your new printcap entry will look like the one below.
The <acronym>MODEL</acronym> information is described in the next section.
<informalexample>
<screen>lp:
  :lp=xxxx:sd=xxxx:....
  #  see text for details about the next line
  :ifhp=model=MODEL,status@
  :filter=/usr/local/libexec/filters/ifhp
  # only if you are using accounting or banners
  #:of=/usr/local/libexec/filters/ifhp</screen>
</informalexample>
</para>

<para>Select a suitable printer from the
entries in the
configuration file
(<filename>/usr/local/etc/lpd.conf</filename>
or
<filename>/etc/lpd.conf</filename>).
These are described in more detail in the next section.</para>

<para>Shut down and restart your print spooler and then send a job to the printer.
If this works and you do not need any further capabilities of &IFHP;
such as error reporting or printer monitoring,
then you are finished.</para>

<para>If you want to use additional capabilities,
then you should read the detailed instructions in the next couple of sections.</para>

</sect1>

<sect1
id="modelselection">
<title>Printer Models Supported
</title>

<para>There are over 500 different printer models,
types and configurations supported by &IFHP;.
If your printer is not currently supported
and you have documentation about the printer then send mail to the
<link linkend="maillist">&LPRng; Mailing List</link>
and support will be added.</para>
<para>The default printer is an HP LaserJet 4MP,
which supports PostScript Level 3, PCL5, PJL,
and has bidirectional communication and a functional pagecounter.
</para>

<para>The <filename>ifhp.conf</filename> configuration file contains
configuration entries for various models of printers.
Each entry has a name usually corresponding to the model of printer
or its basic capabilities.
For example,
the HP LaserJet 4 printer has the <literal>model=hp4</literal> configuration entry.
The <emphasis remap=bf>default</emphasis> printer configuration
covers a wide range of network printers manufactured by Hewlett-Packard,
Canon,  Epson, and others and
is for a printer that has a bidirectional communications
connection that allows it to report status information
and the following capabilities:
<orderedlist>

<listitem>
<para> PJL support (<literal>pjl</literal>) compatible with HP 4 family of printers</para>
</listitem>

<listitem>
<para> PostScript (PS) support (<literal>ps</literal>).</para>
</listitem>

<listitem>
<para> PCL support (<literal>pcl</literal>).</para>
</listitem>

<listitem>
<para> Text files printed as PCL (<literal>text</literal>, <literal>default_language=pcl</literal>).</para>
</listitem>

</orderedlist>
</para>

<para>There is also support for
<link linkend="psonly">PostScript only printers</link>
(<literal>model=ps</literal>),
<link linkend="phaser">Tektronics Phasers</link>
(<literal>model=phaser</literal>),
<link linkend="phaser">QMS</link>
(<literal>model=qmsXXX</literal>)
and others.
The best way to determine the printers currently supported is
to examine the <filename>ifhp.conf</filename> file.
The following is a sample of the various entries in the
configuration file.
<!-- SUPPORTED START -->
<table frame=all id=configentries>
<title><literal/ifhp.conf/ Configuration Entries </title>
<tgroup cols=2 colsep=1 rowsep=1 align=left >
<thead><row><entry/Configuration/<entry/Printer Supported/</row></thead>
<tbody>
<row><entry><literal>default</literal></entry><entry>Generic Printer based on HP 4M Plus, PostScript, PJL, HPGL2, PCL, status, pagecount support</entry></row>
<row><entry><literal>apple</literal></entry><entry>Generic PostScript printer, text to PS conversion, status, pagecount support</entry></row>
<row><entry><literal>postscript</literal></entry><entry>Generic PostScript printer, text to PS conversion, status, pagecount support</entry></row>
<row><entry><literal>ps</literal></entry><entry>Generic PostScript printer, text to PS conversion, status, pagecount support</entry></row>
<row><entry><literal>pcl</literal></entry><entry>Generic PCL only printer, no status</entry></row>
<row><entry><literal>pcl_gs</literal></entry><entry>HP LaserJet 4 PCL only printer, write only, no status</entry></row>
<row><entry><literal>hpiiisi</literal></entry><entry>HP LaserJet III (PCL and PostScript Interpreter)</entry></row>
<row><entry><literal>hp3si</literal></entry><entry>HP LaserJet III (PCL and PostScript Interpreter)</entry></row>
<row><entry><literal>ljet3</literal></entry><entry>HP LaserJet III (PCL and PostScript Interpreter)</entry></row>
<row><entry><literal>lj3</literal></entry><entry>HP LaserJet III (PCL and PostScript Interpreter)</entry></row>
<row><entry><literal>hpiiisi.gs</literal></entry><entry>HP LaserJet III (PCL, PostScript via GhostScript)</entry></row>
<row><entry><literal>hp3si.gs</literal></entry><entry>HP LaserJet III (PCL, PostScript via GhostScript)</entry></row>
<row><entry><literal>ljet3.gs</literal></entry><entry>HP LaserJet III (PCL, PostScript via GhostScript)</entry></row>
<row><entry><literal>lj3.gs</literal></entry><entry>HP LaserJet III (PCL, PostScript via GhostScript)</entry></row>
<row><entry><literal>hp4</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4 (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4m</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4m (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4si</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4si (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4simx</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4simx (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4plus</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4plus (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4mplus</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4mplus (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4v</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4v (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4mv</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4mv (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4p</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4p (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4mp</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4mp (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4pj</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4pj (PostScript Interpreter)</entry></row>
<row><entry><literal>hpljpro</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet ljpro (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4lc</literal></entry><entry>HP LaserJet 4 Family, HP LaserJet 4lc (PostScript Interpreter)</entry></row>
<row><entry><literal>hp4mplus</literal></entry><entry>HP LaserJet 4MPlus</entry></row>
<row><entry><literal>hp5l</literal></entry><entry>HP LaserJet 5 Family, Hp LaserJet 5l</entry></row>
<row><entry><literal>hp6l</literal></entry><entry>HP LaserJet 6 Family, Hp LaserJet 6l</entry></row>
<row><entry><literal>hp1100</literal></entry><entry>HP LaserJet 6 Family, Hp LaserJet 1100</entry></row>
<row><entry><literal>hp1100</literal></entry><entry>HP LaserJet 1000 Family, Hp LaserJet 1100</entry></row>
<row><entry><literal>hp4l</literal></entry><entry>Hp LaserJet 4L, PCL only</entry></row>
<row><entry><literal>hp4ml</literal></entry><entry>HP LaserJet 4ml</entry></row>
<row><entry><literal>hp5p</literal></entry><entry>HP LaserJet 5p</entry></row>
<row><entry><literal>hp5mp</literal></entry><entry>HP LaserJet 5mp</entry></row>
<row><entry><literal>hp6p</literal></entry><entry>HP LaserJet 6p</entry></row>
<row><entry><literal>hp6mp</literal></entry><entry>HP LaserJet 6mp</entry></row>
<row><entry><literal>hp5</literal></entry><entry>HP LaserJet 5</entry></row>
<row><entry><literal>hp5si</literal></entry><entry>HP LaserJet 5si</entry></row>
<row><entry><literal>hp5simx</literal></entry><entry>HP LaserJet 5simx</entry></row>
<row><entry><literal>hp5m</literal></entry><entry>HP LaserJet 5m</entry></row>
<row><entry><literal>hp4100</literal></entry><entry>HP LaserJet 4100</entry></row>
<row><entry><literal>hp4200</literal></entry><entry>HP LaserJet 4200</entry></row>
<row><entry><literal>hp4300</literal></entry><entry>HP LaserJet 4300</entry></row>
<row><entry><literal>hp5simopier</literal></entry><entry>HP LaserJet 5simopier</entry></row>
<row><entry><literal>hp4000</literal></entry><entry>HP LaserJet 4000</entry></row>
<row><entry><literal>hpcolorlj</literal></entry><entry>HP Color LaserJet </entry></row>
<row><entry><literal>hpcolorlj5</literal></entry><entry>HP Color LaserJet 5</entry></row>
<row><entry><literal>hpcolorlj5m</literal></entry><entry>HP Color LaserJet 5m</entry></row>
<row><entry><literal>hpdj1200</literal></entry><entry>HP DesignJet 1200 Family</entry></row>
<row><entry><literal>hppjxl300</literal></entry><entry>HP PaintJet XL 300 Family</entry></row>
<row><entry><literal>hpdj1600</literal></entry><entry>HP DesignJet 1600 Family</entry></row>
<row><entry><literal>hpdj200</literal></entry><entry>HP DeskJet 200</entry></row>
<row><entry><literal>hpdj220</literal></entry><entry>HP DeskJet 220</entry></row>
<row><entry><literal>hpdj600</literal></entry><entry>HP DeskJet 600</entry></row>
<row><entry><literal>hpdj650</literal></entry><entry>HP DeskJet 650</entry></row>
<row><entry><literal>hpdj230</literal></entry><entry>HP DeskJet 230</entry></row>
<row><entry><literal>hpdj250c</literal></entry><entry>HP DeskJet 250c</entry></row>
<row><entry><literal>hpdj330</literal></entry><entry>HP DeskJet 330</entry></row>
<row><entry><literal>hpdj350c</literal></entry><entry>HP DeskJet 350c</entry></row>
<row><entry><literal>hpdj430</literal></entry><entry>HP DeskJet 430</entry></row>
<row><entry><literal>hpdj450c</literal></entry><entry>HP DeskJet 450c</entry></row>
<row><entry><literal>hpdj455ca</literal></entry><entry>HP DeskJet 455ca</entry></row>
<row><entry><literal>hpdj700</literal></entry><entry>HP DeskJet 700</entry></row>
<row><entry><literal>hpdj750c</literal></entry><entry>HP DeskJet 750c</entry></row>
<row><entry><literal>hpdj750cplus</literal></entry><entry>HP DeskJet 750cplus</entry></row>
<row><entry><literal>hpdj755cm</literal></entry><entry>HP DeskJet 755cm</entry></row>
<row><entry><literal>hpdj2000cp</literal></entry><entry>HP DeskJet 2000cp</entry></row>
<row><entry><literal>hp2500</literal></entry><entry>HP DesignJet 2500 - No PCL, PostScript Only</entry></row>
<row><entry><literal>hp2500cm</literal></entry><entry>HP DesignJet 2500cm - No PCL, PostScript Only</entry></row>
<row><entry><literal>hp2500c</literal></entry><entry>HP DesignJet 2500c - No PCL, PostScript Only</entry></row>
<row><entry><literal>hp2500cm</literal></entry><entry>HP DesignJet 2500cm - PCL and PostScript</entry></row>
<row><entry><literal>hpdj2500cp</literal></entry><entry>HP DesignJet 2500CP, not HP2500, HP2500c, HP2500cm</entry></row>
<row><entry><literal>hp4500</literal></entry><entry>HP Color LaserJet Printer 4500</entry></row>
<row><entry><literal>hp8500</literal></entry><entry>HP Color LaserJet Printer 8500</entry></row>
<row><entry><literal>hp8550</literal></entry><entry>HP Color LaserJet Printer 8550</entry></row>
<row><entry><literal>hp4550n</literal></entry><entry>HP 4550N</entry></row>
<row><entry><literal>hp5000</literal></entry><entry>HP 5000 Model C4111A (LaserJet 5000)</entry></row>
<row><entry><literal>hp8000</literal></entry><entry>HP LaserJet 8000 Series, HP8000</entry></row>
<row><entry><literal>hp8100</literal></entry><entry>HP LaserJet 8000 Series, HP8100</entry></row>
<row><entry><literal>hp8150</literal></entry><entry>HP LaserJet 8000 Series, HP8150</entry></row>
<row><entry><literal>hp2100</literal></entry><entry>HP LaserJet 2100 Series</entry></row>
<row><entry><literal>hp2200</literal></entry><entry>HP LaserJet 2200 Series</entry></row>
<row><entry><literal>hp4050</literal></entry><entry>HP 4050 Series Printers</entry></row>
<row><entry><literal>qms1725</literal></entry><entry>QMS 1725, uses appsocket, no status, PostScript only</entry></row>
<row><entry><literal>qms2025</literal></entry><entry>QMS Laser Printer QMS 2025, appsocket, no status, PostScript and PCL</entry></row>
<row><entry><literal>qms860</literal></entry><entry>QMS Laser Printer QMS 860, appsocket, no status, PostScript and PCL</entry></row>
<row><entry><literal>qms2060</literal></entry><entry>QMS Laser Printer QMS 2060, appsocket, no status, PostScript and PCL</entry></row>
<row><entry><literal>phaser</literal></entry><entry>Tektronics Generic Phaser Color Printer, appsocket, snmp monitoring, PostScript only</entry></row>
<row><entry><literal>phaser360</literal></entry><entry>Tektronics Phaser 360 Color Printer, appsocket, snmp monitoring, PostScript only</entry></row>
<row><entry><literal>phaser740</literal></entry><entry>Tektronics Phaser 740 Color Printer, appsocket, snmp monitoring, PostScript only</entry></row>
<row><entry><literal>phaser750</literal></entry><entry>Tektronics Phaser 750 Color Printer, appsocket, snmp monitoring, PostScript only</entry></row>
<row><entry><literal>phaser850</literal></entry><entry>Tektronics Phaser 850 Color Printer, appsocket, snmp monitoring, PostScript only</entry></row>
<row><entry><literal>phaser740</literal></entry><entry>Tektronics Phaser 740 Color Printer, appsocket, snmp monitoring, PostScript and PCL</entry></row>
<row><entry><literal>phaser5400</literal></entry><entry>Tektronics Phaser 5400 Color Printer, appsocket, snmp monitoring, PostScript and PCL</entry></row>
<row><entry><literal>phaser7700</literal></entry><entry>Tektronics Phaser 7700 Color Printer, appsocket, snmp monitoring, PostScript and PCL</entry></row>
<row><entry><literal>lexmark4039</literal></entry><entry>Lexmark 4039, Postscript only</entry></row>
<row><entry><literal>lexmark_optra_e312</literal></entry><entry>Lexmark Optra e312, Postscript, PCL and PJL</entry></row>
<row><entry><literal>ln15s</literal></entry><entry>Digital Laser LN15, LN17ps, Compaq Laser LN 16</entry></row>
<row><entry><literal>ln16s</literal></entry><entry>Digital Laser LN15, LN17ps, Compaq Laser LN 16</entry></row>
<row><entry><literal>ln17pss</literal></entry><entry>Digital Laser LN15, LN17ps, Compaq Laser LN 16</entry></row>
<row><entry><literal>hpij2250s</literal></entry><entry>HP Business Inkjet 2250</entry></row>
<row><entry><literal>gs_bj10</literal></entry><entry>Canon BubbleJet BJ10e </entry></row>
<row><entry><literal>gs_bj10</literal></entry><entry>Canon BubbleJet BJ20 </entry></row>
<row><entry><literal>gs_bj200</literal></entry><entry>Canon BubbleJet BJ200 </entry></row>
<row><entry><literal>gs_bj200</literal></entry><entry>Canon BubbleJet BJC-210 B/W only </entry></row>
<row><entry><literal>gs_bj200</literal></entry><entry>Canon BubbleJet BJC-240 B/W only </entry></row>
<row><entry><literal>gs_bj200</literal></entry><entry>Canon BubbleJet BJC-250 B/W only </entry></row>
<row><entry><literal>gs_bj200</literal></entry><entry>Canon BubbleJet BJC-70 B/W only </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-600 </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-610</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-50</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-70 </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-80 </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-210 Color only</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-240 Color only</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-250 </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-1000</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-2000</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-4000 </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-4100 B/W only</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-4200</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-4300</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-4550 </entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon BubbleJet BJC-6000</entry></row>
<row><entry><literal>gs_bjc600</literal></entry><entry>Canon MultiPASS C2500 color printer/fax/copier </entry></row>
<row><entry><literal>gs_bjc800</literal></entry><entry>Canon BubbleJet BJC-800 </entry></row>
<row><entry><literal>gs_bjc800</literal></entry><entry>Canon BubbleJet BJC-7000 Color. </entry></row>
<row><entry><literal>gs_bjc800</literal></entry><entry>Canon BubbleJet BJC-4300 Color</entry></row>
<row><entry><literal>gs_bjc800</literal></entry><entry>Canon BubbleJet BJC-4650 </entry></row>
<row><entry><literal>gs_deskjet</literal></entry><entry>HP DeskJet </entry></row>
<row><entry><literal>gs_deskjet</literal></entry><entry>HP DeskJet Plus </entry></row>
<row><entry><literal>gs_djet500</literal></entry><entry>HP DeskJet 500 B/W</entry></row>
<row><entry><literal>gs_djet500</literal></entry><entry>HP DeskJet Portable B/W</entry></row>
<row><entry><literal>gs_djet500</literal></entry><entry>HP OfficeJet 590 B/W</entry></row>
<row><entry><literal>gs_cdj500</literal></entry><entry>HP DeskJet 400</entry></row>
<row><entry><literal>gs_cdj500</literal></entry><entry>HP DeskJet 500C </entry></row>
<row><entry><literal>gs_cdj500</literal></entry><entry>HP DeskJet 540C </entry></row>
<row><entry><literal>gs_cdj500</literal></entry><entry>HP DeskJet 690C</entry></row>
<row><entry><literal>gs_cdj500</literal></entry><entry>HP DeskJet 693C</entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 550C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 560C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 600</entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 660C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 660C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 682C</entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 683C</entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 693C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 694C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 690C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 692C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 693C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 694C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 695C </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 850 </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 870Cse </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 895Cxi</entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP DeskJet 970 </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>HP OfficeJet 590 </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>Olivetti jp450 </entry></row>
<row><entry><literal>gs_cdj550</literal></entry><entry>Xerox XJ6C, PCL and Postscript using GhostScript</entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 850 </entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 855 </entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 870Cse </entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 870Cxi </entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 890C </entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 670C </entry></row>
<row><entry><literal>gs_cdj850</literal></entry><entry>HP DeskJet 680 </entry></row>
<row><entry><literal>gs_cdeskjet</literal></entry><entry>HP DeskJet 500C</entry></row>
<row><entry><literal>gs_cdjmono</literal></entry><entry>HP DeskJet 500C </entry></row>
<row><entry><literal>gs_cdjmono</literal></entry><entry>HP DeskJet 510 </entry></row>
<row><entry><literal>gs_cdjmono</literal></entry><entry>HP DeskJet 520 </entry></row>
<row><entry><literal>gs_cdjmono</literal></entry><entry>HP DeskJet 540C </entry></row>
<row><entry><literal>gs_cdjmono</literal></entry><entry>HP DeskJet 693C </entry></row>
<row><entry><literal>gs_epsonc</literal></entry><entry>Fujitsu DL-1100 </entry></row>
<row><entry><literal>gs_epsonc</literal></entry><entry>Fujitsu DL-2400 </entry></row>
<row><entry><literal>gs_hl7x0</literal></entry><entry>Brother HL-720 </entry></row>
<row><entry><literal>gs_hl7x0</literal></entry><entry>Brother HL-730 </entry></row>
<row><entry><literal>gs_laserjet</literal></entry><entry>Bull Compuprint Pagemaster 415 </entry></row>
<row><entry><literal>gs_lips3</literal></entry><entry>Canon LBP4+</entry></row>
<row><entry><literal>gs_lj4dith</literal></entry><entry>HP DeskJet 600 </entry></row>
<row><entry><literal>gs_ljet2</literal></entry><entry>HP LaserJet II </entry></row>
<row><entry><literal>gs_ljet2</literal></entry><entry>Xerox 4030 - PCL,  PostScript support using GhostScript</entry></row>
<row><entry><literal>gs_ljet3</literal></entry><entry>Tandy LP800 With LaserJet III emulation. </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>Brother HL-660 </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>Brother HL-760 600dpi </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>Epson EPL5700 300dpi OK</entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>HP DeskJet 600 margins wrong </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>HP DeskJet 870Cse </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>HP LaserJet 5 300dpi or 600dpi </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>HP LaserJet 5L 300dpi or 600dpi</entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>HP LaserJet 6L 600dpi</entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>HP LaserJet 1100 600dpi OK. </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>IBM Network Printer 17 </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>IBM/Lexmark 4029 Margins wrong. </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>Lexmark Optra E+ </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>Lexmark Optra SC 1275 B/W only. </entry></row>
<row><entry><literal>gs_ljet4</literal></entry><entry>Oki OL410ex LED printer 300dpi or 600dpi </entry></row>
<row><entry><literal>gs_ljetplus</literal></entry><entry>HP LaserJet Plus </entry></row>
<row><entry><literal>gs_ljetplus</literal></entry><entry>Canon Laser LBP-600 </entry></row>
<row><entry><literal>gs_ljetplus</literal></entry><entry>NEC SuperScript 860 </entry></row>
<row><entry><literal>gs_pjxl300</literal></entry><entry>HP PaintJet XL300 </entry></row>
<row><entry><literal>gs_pjxl300</literal></entry><entry>HP DeskJet 600</entry></row>
<row><entry><literal>gs_pjxl300</literal></entry><entry>HP DeskJet 1200C </entry></row>
<row><entry><literal>gs_pjxl300</literal></entry><entry>HP DeskJet 1600C</entry></row>
<row><entry><literal>gs_r4081</literal></entry><entry>Ricoh 4081 laser printer </entry></row>
<row><entry><literal>gs_r4081</literal></entry><entry>Ricoh 6000 laser printer </entry></row>
<row><entry><literal>bjc610a0.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi plain paper, high speed</entry></row>
<row><entry><literal>bjc610a1.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi plain paper</entry></row>
<row><entry><literal>bjc610a2.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi coated paper</entry></row>
<row><entry><literal>bjc610a3.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi transparency film</entry></row>
<row><entry><literal>bjc610a4.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi back print film</entry></row>
<row><entry><literal>bjc610a5.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi fabric sheet</entry></row>
<row><entry><literal>bjc610a6.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi glossy paper</entry></row>
<row><entry><literal>bjc610a7.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi high gloss film</entry></row>
<row><entry><literal>bjc610a8.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 360x360dpi high resolution paper</entry></row>
<row><entry><literal>bjc610b1.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi plain paper</entry></row>
<row><entry><literal>bjc610b2.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi coated paper</entry></row>
<row><entry><literal>bjc610b3.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi transparency film</entry></row>
<row><entry><literal>bjc610b4.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi back print film</entry></row>
<row><entry><literal>bjc610b6.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi glossy paper</entry></row>
<row><entry><literal>bjc610b7.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi high-gloss paper</entry></row>
<row><entry><literal>bjc610b8.upp</literal></entry><entry>Canon BubbleJet BJC-610 (color, rendered) 720x720dpi high resolution paper</entry></row>
<row><entry><literal>cdj550.upp</literal></entry><entry>HP DeskJet 550C 300x300dpi 32-bit CMYK</entry></row>
<row><entry><literal>necp2x.upp</literal></entry><entry>NEC P2X 360x360dpi 8-bit (Floyd-Steinberg)</entry></row>
<row><entry><literal>stcany.upp</literal></entry><entry>Epson Stylus Color (Any) 360x360dpi 4-bit, PostScript halftoning</entry></row>
<row><entry><literal>stc.upp</literal></entry><entry>Epson Stylus (Original) and Stylus Pro Color 360x360dpi 32-bit CMYK, 15-pin </entry></row>
<row><entry><literal>stc_l.upp</literal></entry><entry>Epson Stylus (Original) and Stylus Pro Color 360x360dpi 4-bit, PostScript halftoning, weaved noWeave</entry></row>
<row><entry><literal>stc_h.upp</literal></entry><entry>Epson Stylus (Original) and Stylus Pro Color 720x720dpi 32-bit CMYK, 15-pin Weave</entry></row>
<row><entry><literal>stc2.upp</literal></entry><entry>Epson Stylus (Original) and Stylus Pro Color 360x360dpi 32-bit CMYK, 20-pin, Epson Stylus Color II(s)</entry></row>
<row><entry><literal>stc2_h.upp</literal></entry><entry>Epson Stylus (Original) and Stylus Pro Color 720x720dpi 32-bit CMYK, 20-pin, Epson Stylus Color II </entry></row>
<row><entry><literal>stc2s_h.upp</literal></entry><entry>Epson Stylus (Original) and Stylus Pro Color 720x720dpi 32-bit CMYK, 20-pin, Epson Stylus Color IIs</entry></row>
<row><entry><literal>stc500p.upp</literal></entry><entry>Epson Stylus Color 500 360x360dpi 32-bit CMYK, noWeave, plain paper</entry></row>
<row><entry><literal>stc500ph.upp</literal></entry><entry>Epson Stylus Color 500 720x720dpi 32-bit CMYK, noWeave, plain paper</entry></row>
<row><entry><literal>stc600pl.upp</literal></entry><entry>Epson Stylus Color 600, 360x360dpi, 32/90-inch weaving 32-bit CMYK, 32-pin, plain paper</entry></row>
<row><entry><literal>stc600p.upp</literal></entry><entry>Epson Stylus Color 600, 720x720dpi, 32/90-inch weaving 32-bit CMYK, 32-pin, plain paper</entry></row>
<row><entry><literal>stc600ih.upp</literal></entry><entry>Epson Stylus Color 600, 1440x720dpi, 32/90-inch weaving 32-bit CMYK, 30-pin, inkjet paper</entry></row>
<row><entry><literal>stc800pl.upp</literal></entry><entry>Epson Stylus Color 800, 64/180-inch weaving 360x360dpi 32-bit CMYK, 64-pin, plain paper</entry></row>
<row><entry><literal>stc800p.upp</literal></entry><entry>Epson Stylus Color 800, 64/180-inch weaving 720x720dpi 32-bit CMYK, 64-pin, plain paper </entry></row>
<row><entry><literal>stc800ih.upp</literal></entry><entry>Epson Stylus Color 800, 64/180-inch weaving 1440x720dpi 32-bit CMYK, 62-pin, inkjet paper</entry></row>
<row><entry><literal>stc1520h.upp</literal></entry><entry>Epson Stylus Color 800, 64/180-inch weaving 1440x720dpi 32-bit CMYK, 62-pin, inkjet paper</entry></row>
<row><entry><literal>imagerunner550</literal></entry><entry>Canon imageRUNNER 550/600 iR600-550-60 </entry></row>
<row><entry><literal>imagerunner600</literal></entry><entry>Canon imageRUNNER 550/600 iR600-550-60 </entry></row>
<row><entry><literal>hpdj800ps</literal></entry><entry>HP DesignJet 800ps</entry></row>
<row><entry><literal>panther</literal></entry><entry>Sharp Generic Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-160</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-161</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-162</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-162s</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-163</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-164</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-200</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-200s</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-201</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-205</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-206</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-207</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-f201</literal></entry><entry>Sharp %, Panther Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>cougar</literal></entry><entry>Sharp Generic Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-335</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-336</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-337</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-s337</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-405</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-407</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-505</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-s505</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-507</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-s507</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-250</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-280</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-281</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-285</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-286</literal></entry><entry>Sharp %, Cougar Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>leopard</literal></entry><entry>Sharp Generic Leopard Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-235</literal></entry><entry>Sharp %s, Leopard Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-275</literal></entry><entry>Sharp %s, Leopard Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-n275</literal></entry><entry>Sharp %s, Leopard Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m208</literal></entry><entry>Sharp %s, Leopard Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>tiger</literal></entry><entry>Sharp Generic Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-p350</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m350</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m350u</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m350n</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-p450</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m450</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m450u</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-m450n</literal></entry><entry>Sharp %, Tiger Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>toshiba650</literal></entry><entry>Sharp Generic Toshiba650 Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-650</literal></entry><entry>Sharp %, Toshiba650 Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-800</literal></entry><entry>Sharp %, Toshiba650 Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>fiery651</literal></entry><entry>Sharp Generic Fiery651 Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-651</literal></entry><entry>Sharp %, Fiery651 Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
<row><entry><literal>ar-810</literal></entry><entry>Sharp %, Fiery651 Family, PS and PCL, uses SNMP for status and pagecount</entry></row>
</tbody>
</tgroup>
</table>
<!-- SUPPORTED END -->
</para>

<para>
If your printer is not in this this list
then you can use the following guidelines.
If you have a PostScript only printer
you should use the <literal>ps</literal> model.
If you have a PCL only printer,
then <literal>pcl</literal> is recommended.
If you want to process PostScript files on your PCL only printer
then install GhostScript
and use <symbol>pcl_ps</symbol> entry
and select the GhostScript driver suitable for your printer.
</para>

<para>The other model entries are used when specific printer
functionality or features are needed.
For example,
if you want to do accounting or use <emphasis remap=it>landscape</emphasis> mode,
then you should check for your specific printer model in the
configuration file.</para>

</sect1>
</chapter>

<chapter>
<title>Recommended -Z options for Users</title>

<para>Due to the general nature of the &IFHP; filter,
there is no standard set of <option>-Z</option> user options because there
is no standard set of user facilities.
However,
the following are recommended for
use by implementors of new configurations or printer support.</para>


<sect1>
<title>Input Tray Selection</title>

<para>If a printer supports an input tray selection
mechanism,
then the following options are recommended for use.
Local conditions or printer type may require addition
options.
<variablelist>
<varlistentry><term><literal>inupper, inlower, intray1, intray2, ..., manual, envelope</literal></term>
<listitem>
<para>The input tray selection options should start with the <literal>in</literal> prefix
and correspond to the various trays, if possible.
The <literal>manual</literal> and <literal>envelope</literal>
options are included to select manual feed or envelope feed.
There is a possible source of conflict here as there
may be an envelope feeder as well as an envelope media.
This is a printer specific dependency.</para>

</listitem>
</varlistentry>

<varlistentry><term><literal>source=name</literal></term>

<listitem>
<para>The <literal>key=value</literal>
form allows users to use options such as <literal>-Zsource=inbin1</literal>,
which may be useful for systems that have an unusual or nonstandard
input selection mechanism.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Output Bin Selection</title>

<para>If a printer has an output bin selection mechanism
or some other finishing mechanism,
then the following are recommended for use.</para>

<para>
<variablelist>
<varlistentry><term><literal>outupper, outlower, outbin1, ...</literal></term>
<listitem>
<para>The output bin selection should start with the <literal>out</literal> prefix.</para>

</listitem>
</varlistentry>

<varlistentry><term><literal>outbin=name</literal></term>

<listitem>
<para>The <literal>outbin=name</literal>
form allow users to use options such as <literal>-Zoutbin=stapler</literal>,
which may be useful for systems that have an unusual or nonstandard
output selection mechanism.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Media Size (Paper) Selection</title>

<para>The paper size selection facilities usually are quite printer
dependent,
and the input tray selection and paper size selection mechanisms
may interact in strange and mysterious ways.</para>

<para>
<variablelist>
<varlistentry><term><literal>letter, legal, ledger, oversize, a0, a1, ...</literal></term>
<listitem>
<para>These are standard paper size names.</para>

</listitem>
</varlistentry>

<varlistentry><term><literal>11x17, tabloid</literal></term>

<listitem>
<para>These are usually aliases for ledger,
but depending on local conditions can select different types of paper.</para>

</listitem>
</varlistentry>

<varlistentry><term><literal>paper=name</literal></term>

<listitem>
<para>The <literal>paper=name</literal>
form allow users to use options such as <literal>-Zpaper=b3</literal>,
which may be useful for systems that have an unusual or nonstandard
input media selection mechanism.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Media Type Selection</title>

<para>Media Type is not the same as paper size,
and corresponds to the name assigned to a particular media.
Of course,
the issue is complicated by the fact that some media have
standard sizes as well.
Again,
the input tray selection,
media size,
and media type selection will interact in confusing and
mysterious ways,
depending on the whim of the printer firmware implementors.</para>

<para>You will also notice that there is no general
<literal>mediatype=name</literal>
selection mechanism.
This is due to the extremely different way that the media names
must be passed for PostScript,
PJL, and PCL.</para>

<para>
<variablelist>
<varlistentry><term><literal>plain, preprinted, letterhead, transparency, glossy, prepunched, labels</literal></term>
<listitem>
<para>These are commonly used media type names gleaned from various PostScript Printer
Description Files,
Microsoft printer drivers,
and arcane lore of the Printer Working Group.
Note that these are not accepted terms in the paper industry
for any of these type of media.
You are warned.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Duplex and Simplex</title>

<para>Duplex printing is when impressions are placed on both sides
of a sheet of media.
Due to a general lack of conventions,
the orientation of each of the impressions varies from vendor
to vendor,
and has changed over the years.</para>

<para>
<variablelist>
<varlistentry><term><literal>duplex, lduplex</literal></term>
<listitem>
<para>Print on both sides using the default orientation.
The <literal>lduplex</literal> is an alias for <literal>duplex</literal></para>

</listitem>
</varlistentry>

<varlistentry><term><literal>duplexshort, sduplex</literal></term>

<listitem>
<para>Print on both sides but reverse the orientation of one page.
The <literal>sduplex</literal> is an alias for <literal>duplexshort</literal>
Which page is reversed is at the whim of the firmware implementors and
conventions for the printer.</para>

</listitem>
</varlistentry>

<varlistentry><term><literal>simplex</literal></term>

<listitem>
<para>Print on a single side of a page</para>

</listitem>
</varlistentry>

<varlistentry><term><literal>tumble, shortedge</literal></term>

<listitem>
<para>This is use to print a single page on one side of the media,
but using the (nonstandard) orientation for the <literal>duplexshort</literal>.
This is usually done when a single impression must be generated
on the alternative side of the media,
rather than the default side.
Again,
this is dependent on the whims and whimsies of the printer
firmware implementors,
and may have some unexpected side effects.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Copies</title>

<para>This option has been provided to effectively allow the printer to
make multiple copies of a single page or job.
This option tends to be misimplemented on almost all known printers,
and it is strongly recommended that users do not use it.
However,
for completeness,
compatibility,
and implementor consideration,
this is included,
even against the better judgement of the implementors of the &IFHP;
software.
<variablelist>
<varlistentry><term><literal>copies=nnn</literal></term>
<listitem>
<para>Attempt to make <literal>nnn</literal> copies of each impression.
This usually fails with catastrophic problems unless you have
a system that supports all of the various options required,
has enough memory to handle rasterization,
you do not have a paper outage,
and the printer does not stop with operator intervention.
You have been warned.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>
</chapter>

<chapter>
<title>Printer Capabilities, Configurations, and Printcaps</title>

<para>One of the major difficulties with printer software
is dealing with the wide range of different printer hardware configurations
and printer connections.
This section outlines the printer communication methods,
the types of print job languages,
and the effects of these on printing software and the &IFHP;
filter.</para>


<sect1>
<title>Printer Configurations</title>

<para>A printer consists of a hardware print engine which marks the output page
and delivers it,
a set of control hardware that takes a <emphasis remap=it>print job</emphasis>
in a well defined format and operates the hardware to produce output
according to information in the <emphasis remap=it>print job</emphasis>,
and a communication channel from the computer to the control hardware.
The control hardware is sometimes called a <emphasis remap=it>print engine</emphasis>.
In most modern computers the control hardware may consist of multiple microprocessors,
each with their own firmware,
and each performing a specific printing task.
For example,
one may control the paper feed path,
one may do rasterization,
and one may handle communications with the outside world.</para>

<para>In order to set up printing correctly,
it is necessary to know the following information about your printer.
<orderedlist>

<listitem>
<para>The capabilities of the hardware.
This is dependent on the model of printer,
and may be such things as the page feed,
output and input tray selection,
numbers of columns and/or rows of output available on the output device.
This information is readily available from most manufacturers.</para>
</listitem>

<listitem>
<para>The <emphasis remap=it>print job language</emphasis>
recognized by the control hardware.
This is the special set of codes,
commands, and formats recognized by the control hardware.</para>
</listitem>

<listitem>
<para>The protocol used to send jobs to the printer and obtain status
about the printing activity.</para>
</listitem>

</orderedlist>
</para>

<para>Usually the capabilities of a modern printer are very well known
and documented,
and the &IFHP; filter and most print spooling software has
little difficulty working with them.</para>

<para>The following checklist will help you in setting up your printer.
The various options that you will need to know about are indicated
where appropriate.
<orderedlist>

<listitem>
<para>Printer Model (<literal>model=???</literal>)
What is the exact printer model?
Check the serial number or other identification to get this information.
You should check the <filename>ifhp.conf</filename>
configuration file to see if your printer is already supported.</para>
</listitem>

<listitem>
<para>Print Languages Supported By Your Printer
<orderedlist>

<listitem>
<para>PJL? (<literal>pjl</literal> or <literal>pjl@</literal>)
The Printer Job Language (PJL) is a high level language supported by many Hewlett-Packard
printers that allows some print system configuration to be performed.
Due to historical developments,
not all printers support all PJL language facilities,
and some support them in different ways than other printers.
The &IFHP; filter can use the PJL support for a printer if it is available.</para>
</listitem>

<listitem>
<para>PostScript (and what version)?  (<literal>ps</literal> or <literal>ps@</literal>)
PostScript is the most common print job language in use.
If your printer supports PostScript,
then you will have a relatively trouble free time with it.
One problem is that it requires a fairly substantial amount of
memory and computational support,
and is usually not found on the low end (less than $500) printers.</para>
</listitem>

<listitem>
<para>PCL? (<literal>pcl</literal> or <literal>pcl@</literal>)
PCL is another Print Language supported by
many vendors, including Hewlett-Packard,
Lexmark, and others.
It is essentially text with escape sequences to tell the print engine
to place markings on a page at specific places in a specific font.
It is the second most common format used with modern printers.</para>
</listitem>

<listitem>
<para>Text? (<literal>text</literal> or <literal>text@</literal>)
Text is really just PCL without any control sequences.
However, it is easy to have &IFHP; convert ordinary text into PCL
by prefixing the appropriate PCL control codes.
You may also need to use the <literal>crlf</literal> option to force
<acronym>CR</acronym> to <literal>CR-LF</literal> translation.
If you have a simple text printer then you may want to use the much
easier to configure <application>lpf</application> filter from the &LPRng; distribution
(<ulink URL="http://www.lprng.com">http://www.lprng.com</ulink>).</para>
</listitem>

<listitem>
<para>Vendor Specific
There is a growing trend to have very proprietary Print Languages
for very low end  (less than $300) printers.
These printers usually require all of their jobs to be preformated by
software running on the host and to have the job delivered to them
in a specific manner.
If you have one of these printers,
you will need to get a rasterizing program that produces the correct format.
Check to see if
<link linkend="ghostscript">GhostScript</link>,
supports your printer.
If it does then you can use <literal>GhostScript</literal> to translate
PostScript to your printer's required format.</para>
</listitem>

</orderedlist>
</para>
</listitem>

<listitem>
<para>Memory Size.
If you are going to be sending large print jobs or ones with a large
amount of graphics to the printer, you will need a substantial amount
of memory to deal with rasterization.
Most high resolution Laser Copier based printers require a minimum of
16 megabytes for adequate performance,
and if you are printing complex PostScript or PDF documents you
may want at least 32 megabytes.
Color printers require substantially more and 64 megabytes is not uncommon.</para>
</listitem>

<listitem>
<para>Communications.
The connection between your printer
and the host computer.
<orderedlist>

<listitem>
<para>Network Connection
This is the most reliable and high speed way to connect a printer
to a system.
This is especially true if a printer must be accessible to multiple
users and is located at a distance from the user.</para>
</listitem>

<listitem>
<para>Parallel Port (<literal>status@</literal>)
The parallel port is a <emphasis>unidirectional</emphasis> communications channel
and does not do full duplex bidirectional communications.
Some operating system support bidirectional communications,
but they do so by requiring write operations to alternate with read operations.
</para>
</listitem>

<listitem>
<para>Serial Ports
This is the very worst way to communicate at high speed with a printer.
Serial ports usually have a high error rate,
suffer from data overruns,
and have a severe impact on system performance.
You will need to configure your printer speed,
format (bits per character, parity, stop bit),
and flow control method,
and then do the same for the host.
This can be an endless source of frustration for the novice user.</para>
</listitem>

<listitem>
<para>Print Server Box
Many older printers do not directly support a network connection
and have an external <emphasis remap=it>print server box</emphasis> attached to either their
serial or parallel ports.
If you have the printer connected to a parallel port,
then you will still most likely only have unidirectional communication
and no status information will be available from the printer.</para>
</listitem>

</orderedlist>
</para>
</listitem>

</orderedlist>
</para>

</sect1>

<sect1
id="networkprotocols">
<title>Network Communication Protocols
</title>

<para>The most high speed and reliable connection to your printer is using a
network connection.
The following protocols are usually used to communicate with a network printer:
RFC1179 (TCP/IP printing),
Socket Protocol (TCP/IP),
AppSocket Protocol (TCP/IP),
Novell Print Protocol (IPX),
SMB Print Protocol (TCP/IP),
and AppleTalk Print Protocol (TCP/IP).</para>

<para>It is highly recommended that you use TCP/IP networking to communications to
talk to your printer,
and that you do not enable any other protocol on your printer.
If you have two different systems trying to connect to the same printer
using different protocols,
a wide range of vendor's hardware will lock up and may require a power up reset
to recover.
Documented evidence for this behavior includes a wide range of
printers, including those from Hewlett-Packard, LexMark, IBM and other vendors.</para>

<para>Only the TCP/IP based network job transfer protocols are discussed in
this document.
For details on using other protocols,
please consult the consult the
<ulink URL="http://www.lprng.com">&LPRng;</ulink>
documentation.</para>

</sect1>

<sect1
id="rfc1179pc">
<title>RFC1179 (BSD or TCP/IP) Job Transfer Printcap Entry
</title>

<para>RFC1179 is used to transfer print jobs between
a client (user) and a print spooler,
or between two print spoolers.
Jobs are transferred as a set of files,
and the only information exchanged during the transfer process is the
success or failure of the transfer.
In order to get status about the actual job printing,
a separate query status (<application>lpq</application>) is sent to the print spooler.</para>

<para>Many,
if not all,
printers with a network interface that supports the TCP/IP protocol support
the RFC1179 protocol for job transfer.
However,
their support for print job status is usually minimal to non-existent.
If you want to send a job to a printer using the RFC1179 protocol,
please be aware of the following problems.</para>

<para>Normally a print spooler (System 5 lp, BSD lpd, &LPRng;)
does not modify a print job when forwarding it to another print spooler.
This means that your print job will normally pass from the originating
<application>lp</application>
or <application remap=tt>lpr</application> program to the destination printer with no changes.
This can have disastrous results if the job
<emphasis remap=bf>requires</emphasis>
filter processing.</para>

<para>If you are using the &LPRng; print spooler,
job transfers using <literal>RFC1179</literal>
is specified by using <literal>:lp=spoolqueue@host</literal>
or <literal>:rp=spoolqueue:rm=host</literal> printcap entries.
For example:
<informalexample>
<screen>raw:
  :lp=raw@host
  :sh:sf:mx=0
  :sd=/var/spool/lp
cooked:
  :rp=cooked:rm=host
  :sh:sf:mx=0
  :sd=/var/spool/lp
  :filter=/usr/local/libexec/filters/ifhp</screen>
</informalexample>
</para>

<para>The
<literal/raw/
queue does not have a filter
and jobs sent to the
<literal/raw/
are transfered intact from the
<literal/raw/ queue to the destination
<literal/raw/
printer on the
<literal/host/
server.
</para>

<para>
Jobs sent to the
<literal/cooked/
queue will be processed by the program specified by the
<literal/filter/
option.
For each data file in the job,
the
<application/lpd/ print spooler will open a temporary file
to hold the filter output,
and then run the filter program with
its <acronym>STDIN</acronym> set to the job's data file file
and the <acronym>STDOUT</acronym> set to the temporary file.
The filter <acronym>STDERR</acronym> will be recorded in
an error log.
</para>

<para>When a job is created
a job format may specified (default is <literal>f</literal>),
and an filter can be specified to process job files with this format.
The <literal>:i</literal>&lt;<emphasis remap=it>format</emphasis>&gt;
option specifies the filter program for use.
For example,
you can specify a different filter for the <literal/n/ format as shown
below.
The
<literal/translate_format/ option specifies the resulting
format for the processed files,
and uses a format similar to the
UNIX <literal>try</literal>(1) program.
In the example,
it specifies that the output of the
filter for the
<literal/n/
format be renamed as
<literal/f/.
<informalexample>
<screen>
cooked:
  :rp=cooked:rm=host
  :sh:sf:mx=0
  :sd=/var/spool/lp
  # default filter
  :filter=/usr/local/libexec/filters/ifhp
  # n filter
  :nf=/usr/local/libexec/filters/nfilter
  :translate_format=nf</screen>
</informalexample>
</para>

<para>There is a final option that is used
when rather than having a set of job files forwarded to a printer,
a single job file is desireable.
This is usually the case when sending a job to a host or printer
that has a defective
RFC1179 spooler implementation,
and drops or misprints jobs with multiple files in them.
The
<literal/lpd_bounce/
option causes the output of all the filters to be
put into a single file, and the
output is then forwarded to the destination.
You can also use the
<literal/bq_format/ option to specify the format of the
job:
<informalexample>
<screen>
cooked:
  :rp=cooked:rm=host
  :sh:sf:mx=0
  :sd=/var/spool/lp
  # default filter
  :filter=/usr/local/libexec/filters/ifhp
  :lpd_bounce
  # output has l (literal) or binary output
  :bq_format=l</screen>
</informalexample>
</para>

<para>
The <command>lpr -l</command> or <command>lpr -b</command>
flag is used to specify the special <literal>literal</literal>
or <literal/l/ job format.
Job that have the <literal>l</literal> format
usually have only the most perfunctory processing
done by the filter.
</para>

</sect1>

<sect1
id="socketpc">
<title>Socket Protocol (TCP/IP) Operation Printcap Entry
</title>

<para>Many printers with a network interface provide
a TCP/IP port that is a direct connection to the
internal <emphasis remap=it>print engine</emphasis>.
If a TCP/IP connection is made to this port
and a file is sent over this connection,
then the print engine will process the file.
More importantly,
the connection is bidirectional,
and the printer will report errors and status conditions
over the connection.
PJL and PostScript status request commands can be sent to the printer
and the printer will respond with information.</para>

<para>The &IFHP; filter makes extensive use of this protocol,
and provides support for status and error reporting.
In cooperation with the &LPRng; print spooler,
it will provide a detailed description of the actual print job progress
and any error conditions that arise.</para>

<para>To use a Socket connection with &LPRng;,
you use the <literal>:lp=host%port</literal> printcap entry shown below.
The <application/lpd/ print spooler will open a connection to the
TCP/IP <literal>port</literal> on <emphasis remap=tt>host</emphasis>
and passes the (bidirectional) connection to the &IFHP; filter
on file descriptor 1 (<acronym>STDOUT</acronym>) and the file to be printed on
file descriptor 0 (<acronym>STDIN</acronym>).
Errors and status information are reported by the &IFHP; filter
on file descriptor 2 (<acronym>STDOUT</acronym>) and placed in the error status log by the
<application/lpd/ print spooler.</para>

<para>The connection made by the <application/lpd/ server
to the printer is <emphasis>persistent</emphasis> over the entire job;
all file transfers for the same job are made over the same
connection.
This is important as it prevents other printer users
from <emphasis>hijacking</emphasis> the printer in the middle of print a job
and getting your job outputs mixed together.</para>

<para>The following is a typical printcap entry using the socket protocol.
<informalexample>
<screen>raw:
  :lp=host%9100
  :sh:sf:mx=0
  :sd=/var/spool/lp
  :filter=/usr/local/libexec/filters/ifhp</screen>
</informalexample>
</para>

</sect1>

<sect1
id="appsocketpc">
<title>Appsocket Protocol (TCP/IP) Operation
</title>

<para>The Tektronics Phaser Series printers and QMS printers use the
<emphasis remap=it>Appsocket</emphasis> protocol when sending a job to the printer.
This protocol uses two ports: a TCP/IP <emphasis remap=it>listening</emphasis> port  which
accepts TCP/IP connections and a UDP <emphasis remap=it>SNMP query</emphasis> port that
is used to obtain status information.
</para>

<para>The Appsocket protocol is (briefly):
<orderedlist>

<listitem>
<para>The Simple Network Management Protocol (SNMP) is a UDP protocol.
A SNMP Query packet containing a request for information is sent to the
printers SNMP Agent port (port 161), and a reply containing the requested information
is returned.
</para>
</listitem>

<listitem>
<para> To send a job to the printer,  a TCP/IP connection is opened to the TCP/IP port
and job data is sent.
Only a single job can be sent at a time - a EOJ in the job, i.e.-
CTRL-D for PostScript or ESC E for PCL
will cause the printer to terminate reading from the TCP/IP port,
and after job processing has finished,
to close the TCP/IP connection.
All input after the EOJ may be ignored by the printer and not processed.</para>
</listitem>

<listitem>
<para>While processing the job,
if <emphasis remap=it>bidirectional</emphasis> support is available
and has been enabled
the printer will return job status or information until all of the print job
which is has received has been processed.
This support is usually not enabled by default and must be enabled
by using a specialized administration interface or configuration tool.</para>
</listitem>

<listitem>
<para>Unfortunately,
some printers will also close the connection when the EOJ has been received.
These printers are virtually useless when trying to get error or status information
about a job.</para>
</listitem>

<listitem>
<para>Even more annoying is the behavior of some printers
that insist on the network connection remaining open until the job
has been processed.
The device sending the job to the printer must do a <emphasis>shutdown</emphasis>
on the sending direction of the network connection,
and then read status information from the receiving direction until the printer
terminates the connection.
Unfortunately,
some printers <emphasis>do not</emphasis> terminate the connection,
and the the user must close the connection after a suitable timeout.
</para>
</listitem>

<listitem>
<para>There are also printers that insist on the network connection being closed
before they will start processing small jobs.
The device sending the job to the printer must do a <emphasis>close</emphasis>
rather than a shutdown.
</para>
</listitem>

<listitem>
<para>While processing the job,
the printer will ignore any connection requests,
and only until the job has been processed
will the printer accept connections.</para>
</listitem>

<listitem>
<para>During job processing,  status and error indications can be obtained by sending
a query to the UDP port.
However,  the error conditions and other information are not very precise as the
status may change dramatically during job processing.</para>
</listitem>

<listitem>
<para>
a query to the UDP port.
However,  the error conditions and other information are not very precise as the
status may change dramatically during job processing.
</para>
</listitem>

</orderedlist>
</para>

<para>The Appsocket protocol does not use a <emphasis>persistent</emphasis> connection.
If two people are sending jobs to the printer simultaneously it is very likely
that the jobs will get intermixed.</para>

<para>The <literal>appsocket</literal> option causes the &IFHP; filter
to open and close a TCP/IP connection to the printer.
In order to reopen the device, &IFHP; needs the device name.
It gets this from the
<literal/PRINTCAP_ENTRY/
environment variable
which has the device information,
or by using the TCP/IP address of the initial end of the connection.
</para>
<para>
The <literal>close_appsocket</literal> option causes the &IFHP; filter
to close the connection after sending a job or part of a job.
This is necessary with printers that will not start printing small jobs
until a sufficient number of pages has been received.
</para>
<para>
The following is a sample printcap entry for this printer:
<informalexample>
<screen># Phaser Setup
#  Appsocket
lp:server  
  :<literal>lp=10.0.0.1%9100</literal>  
  :sd=<emphasis remap=it>spooldir</emphasis>  
  :...  
  :ifhp=model=ps,appsocket
  #path to ifhp filter  
  :filter=/.../ifhp</screen>
</informalexample>
</para>

<para>For your convenience,
the <literal>model=phaser</literal>
entry is suitable for use with the appsocket protocol.</para>

</sect1>

<sect1 id="snmp">
<title>Using SNMP For Status Information</title>
<itemizedlist>
<listitem><para><literal/snmp_monitor/ FLAG <emphasis/use snmp for status/</para></listitem>
<listitem><para><literal/snmp_program=/ <emphasis>path to snmp_printer_status</emphasis></para></listitem>
<listitem><para><literal/snmp_program_cfg=/ <emphasis>snmp_printer_status configuration file</emphasis></para></listitem>
<listitem><para><literal/snmp_model=/<emphasis/snmp model information/</para></listitem>
<listitem><para><literal/snmp_sync_status=/<emphasis/sync indicators/</para></listitem>
<listitem><para><literal/snmp_end_status=/<emphasis/end of job indicators/</para></listitem>
<listitem><para><literal/snmp_end_status=/<emphasis/end of job indicators/</para></listitem>
</itemizedlist>

<para>
The &IFHP; filter can be configured to use the SNMP helper program
<literal/snmp_printer_status/
to obtain SNMP status.
This program is supplied as part of the &IFHP; distribution.
<para>

<para>
The <literal/snmp_monitor/ flag is used to enable the use of the <literal/snmp_printer_status/ program.
The <literal/snmp_program/ specifies the program path and command line to invoke it.
The <literal/snmp_program_conf/ specifies the path to the
configuration file,
<literal/snmp_printer_stastus.conf/.
The configuration file contains information about the operation of the program
as well as the SNMP Object Identifiers (OIDs) for the status information.
</para>

<para>
Since different printers may not support all of the standard Printer MIB Oids,
the <literal/snmp_printer_status.conf/ can identify the options on a per-printer model basis,
and the appropriate ones can be selected using the <literal/snmp_model/ option.
</para>

<para>
The <literal/snmp_printer_status/ program returns status information on it STDOUT and errors on its
STDERR.
The status information has the format:
<informalexample><screen>PRINTERNAME=HP LaserJet 2200
DEVICEID=HP LaserJet
STATUS=Ready
DEVICESTATUS=running
PRINTERSTATUS=idle
PAGECOUNT=30</screen></informalexample>
Consult the
<literal/snmp_printer_status/ program and
<literal/snmp_printer_status.conf/
files for details of how the status is obtained.
</para>

<para>
When using <literal/snmp/ to detect idle or end conditions,
the <literal/snmp_sync_status/ and
the <literal/snmp_end_status/ values are used.
If the retured status matches a field in the
<literal/snmp_sync_status/ list, then a idle printer condtion is assumed.
If the retured status matches a field in the
<literal/snmp_end_status/ list, then an end of job condtion is assumed.
For example:
<informalexample><screen>snmp_end_status=ready idle
snmp_sync_status=ready power_save_mode</screen></informalexample>
</para>

<para>
When using SNMP to obtain status, it may be of little benefit to use other methods to obtain
sync, pagecount, or end of job (waitend).
Also, if a connection is open to the printer then the printer may never indicate
<literal/idle/
or non-printing status.
This problem can be avoided by using the
<literal/appsocket/ protocol.
If you use this, then you should also set the
<literal/sync/,
<literal/waitend/,
and
<literal/pagecount/
values to <literal/snmp/ as well.
For example:
<informalexample><screen>[ printer ]
snmp_monitor
appsocket
sync=snmp
waitend=snmp
pagecount=snmp</screen></informalexample>
This will cause the &IFHP; to perform the operations but not to send any query strings to the
printer.
</para>

</sect1>

<sect1>
<title>Common Print Server Boxes Configuration Information</title>

<para>The following is a list of print server manufacturers,
models,
and with hints on how to access these boxes with various protocols.</para>

<para>
<table frame=all id=networkprintservers>
<title>Network Print Servers</title>
<tgroup cols=4 colsep=1 rowsep=1 align=left >
<thead>
<row><entry>Manufacturer</entry><entry>Model</entry><entry>RFC1179 Port Name (rp=XXX)</entry><entry>Send to TCP port</entry></row>
</thead>
<tbody>
<row><entry><ulink URL="http://www.digprod.com/">Digital Products Inc.</ulink></entry><entry>NETPrint Print Server</entry><entry><literal/PORT/<emphasis/n/, where <emphasis remap=it>n</emphasis> is port on server</entry><entry>- Unknown if supported -</entry></row>
<row><entry morerows=3><ulink URL="http://www.efi.com/">Electronics For Imaging Inc.</ulink></entry><entry>Fiery RIP i series</entry><entry><literal>normalq</literal> or <emphasis remap=tt>urgentq</emphasis></entry><entry>- Unknown if supported -</entry></row>
<row><entry>Fiery RIP XJ series</entry><entry><literal>xjprint</literal></entry><entry>- Unknown if supported -</entry></row>
<row><entry>Fiery RIP XJ+ and SI series</entry><entry><symbol>print_</symbol><emphasis remap=it>Model</emphasis>, e.g. <symbol>print_DocuColor</symbol></entry><entry>- Unknown if supported -</entry></row>
<row><entry>Fiery models ZX2100, ZX3300, X2, X2e</entry><entry><literal>print</literal></entry><entry>- Unknown if supported -</entry></row>
<row><entry><ulink URL="http://www.emulex.com/">Emulex Corp.</ulink></entry><entry>NETJet/NETQue print server</entry><entry><acronym>PASSTHRU</acronym></entry><entry>- Unknown if supported -</entry></row>
<row><entry><ulink URL="http://www.extendsys.com/">Extended Systems Inc.</ulink></entry><entry>ExtendNet Print Server</entry><entry><emphasis remap=tt>Printer<replaceable>n</replaceable></emphasis>, where <emphasis remap=it>n</emphasis> is port on server</entry><entry>- Unknown if supported -</entry></row>
<row><entry morerows=1><ulink URL="http://www.hp.com/">Hewlett-Packard</ulink></entry><entry>JetDirect interface card</entry><entry><literal>raw</literal></entry><entry>9100</entry></row>
<row><entry>JetDirect Print Server</entry>
<entry>Port1=<literal>raw1</literal>,
Port2=<literal>raw2</literal>, ...
</entry>
<entry>
Port1=9100,
Port2=9101, ...
</entry></row>
<row><entry><ulink URL="http://www.i-data.com/">I-Data</ulink></entry><entry>Easycom 10 Printserver</entry><entry><literal>par1</literal> (parallel port 1)</entry><entry>- Unknown if supported -</entry></row>
<row><entry></entry><entry>Easycom 100 Printserver</entry><entry><literal>LPDPRT1</literal></entry><entry>- Unknown if supported -</entry></row>
<row><entry><ulink URL="http://www.printers.ibm.com/">IBM</ulink></entry><entry>Network Printer 12, 17, 24, and 24PS</entry><entry><acronym>PASS</acronym></entry><entry>- Unknown if supported -</entry></row>
<row><entry><ulink URL="http://www.lantronix.com/">Lantronix</ulink></entry><entry>EPS1, EPS2</entry><entry><literal>EPS_XXXX_S1 (serial) port 1, EPS_XXXX_P1 (parallel) port 2</literal>, etc.</entry><entry>3001 (port 1), 3002 (port 2), etc.</entry></row>
<row><entry><ulink URL="http://www.qms.com/">QMS</ulink></entry><entry>Various Models</entry><entry><acronym>RAW</acronym></entry><entry>35 (Appsocket)</entry></row>
<row><entry><ulink URL="http://www.tek.com/color_printers/">Tektronix</ulink> (Now <ulink URL="http://www.tektronix.xerox.com">Xerox</ulink>)</entry><entry>Tektronix printer network cards</entry><entry><acronym>PS</acronym> (PostScript), <acronym>PCL</acronym> (PCL), or <acronym>AUTO</acronym>(Auto-selection between PS, PCL, or HPGL). Not reliable.</entry><entry>9100 (Appsocket on some models)</entry></row>
<row><entry><ulink URL="http://www.rosel.com">Rose Electronics</ulink></entry><entry>Microserve Print Servers</entry><entry>lp</entry><entry>9100</entry></row>
<row><entry morerows=5><ulink URL="http://www.xerox.com/">Xerox</ulink></entry><entry>Models 4505, 4510, 4517, 4520</entry><entry><acronym>PASSTHRU</acronym></entry><entry>2501 (Appsocket on some models)</entry></row>
<row><entry>Model 4512</entry><entry><literal>PORT1</literal></entry><entry>10001 (programmable)</entry></row>
<row><entry>Model N17</entry><entry><acronym>RAW</acronym></entry><entry>9100</entry></row>
<row><entry>Models N24 and N32</entry><entry><acronym>RAW</acronym></entry><entry>2000</entry></row>
<row><entry>Models 4900, 4915, 4925, C55</entry><entry><acronym>PS</acronym></entry><entry>2000</entry></row>
<row><entry>Document Centre DC220/230</entry><entry><literal>lp</literal></entry><entry>- Unknown if supported -</entry></row>
</tbody>
</tgroup>
</table>
</para>

<para>All company, brand, and product names are properties of their respective owners.</para>

</sect1>

<sect1>
<title>Timeout Problems Sending A Job</title>

<para>The &IFHP; filter may need to run a program
such as <literal>ghostscript</literal> to do format conversion.
For large files this can take quite a bit of time and
most network printers have a
<emphasis remap=it>connection timeout</emphasis>.
If no data is received for this time the printer will
close the connection.
By default this timeout is fairly short: 30 or 90 seconds on most printers.</para>

<para>If you are sending large jobs to the printer using the
<literal>socket</literal> protocol and are getting timeout
problems due to conversion timeouts,
then there are two solutions: a) use the Appsocket protocol,
which will open and close the connection for each file,
and only send data when the converted file is available,
or b)
do your conversions first and then spool the converted job to be sent
directly to the printer.
The second method requires an &LPRng; bounce queue.
<informalexample>
<screen># Method a) Appsocket
lp:server 
  :lp=10.0.0.1%9100
  :sd=<emphasis remap=it>spooldir</emphasis> 
  :... 
  :ifhp=model=printer,appsocket
  #path to ifhp filter 
  :filter=/.../ifhp 

# Method b) Bounce Queue
#  this queue does the conversion if required
lp:server
  :lpd_bounce 
  :lp=real@localhost
  :sd=<emphasis remap=it>spooldir</emphasis> 
  :... 
  :ifhp=model=printer
  #path to ifhp filter 
  :filter=/.../ifhp 
# this queue does transmission
real:server 
  :lp=10.0.0.1%9100
  :sd=<emphasis remap=it>spooldir</emphasis> 
  :ifhp=model=printer
  #path to ifhp filter 
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

<para>For method a),
the Appsocket protocol is used and the &IFHP; filter will be invoked before sending a job.
For method b),
you use two queues:  a <emphasis remap=it>bounce</emphasis> queue that does the format conversion
and then sends the job to the real queue,
and the real queue that actually talks to the printer.</para>

</sect1>

<sect1 id="rwtimeout">
<title>Printers With Lockup Problems </title>

<para>
Due to firmware problems in some PostScript and PCL printers,
they will occasionally lock up and refuse to accept new connections
or continue with job processing.
This is extremely difficult to diagnose,
as the printer appears to be functional but will simply not
accept any addition data or respond to a command.
</para>
<para>
Unfortunately,  this is also the condition when these printers are turned offline.
</para>

<para>
The <literal/send_job_rw_timeout/ option is used to set a maximum timeout for
network and/or communication operations.
This value can be set to the maximum expected completion time of the print job.
When this time is exceeded, the IFHP filter will exit with a
<literal/JTIMEOUT/ error.
</para>
</sect1>

<sect1>
<title>PS, PCL, PJL Printer with TPC/IP Network Interface</title>

<para>The most common TCP/IP protocols used for transferring
jobs to network printers are
<link linkend="rfc1179pc">RFC 1179</link>,
a direct TCP/IP
<link linkend="socketpc">socket</link>,
connection to the print engine,
and the very odd
<link linkend="appsocketpc">Appsocket</link> protocol described
in previous sections.
Here is a reprise of the various printcaps and methods
to use them.
<informalexample>
<screen># printer setup  
#  force clients (lpr, lpq, to use server)  
lp:lp=lp@serverhost  
# server information  
lp:server  
  :sd=<emphasis remap=it>spooldir</emphasis>  
  :...  

  # No filtering, transfer using RFC1179, use:
  :lp=queue@10.1.1.1
  #    or 
  :rp=queue:rm=10.1.1.1

  # Filtering and then transfer using RFC1179, use:
  :lpd_bounce:lp=queue@10.1.1.1
  #    or 
  :lpd_bounce:rp=queue:rm=10.1.1.1
  :ifhp=model=<emphasis remap=it>name</emphasis>
  :filter=/.../ifhp  

  # Filter, transfer using socket, use:
  :lp=10.1.1.1%9100 
  :ifhp=model=<emphasis remap=it>name</emphasis>
  :filter=/.../ifhp  

  # Filter, transfer using Appsocket, use:
  :lp=10.1.1.1%9100 
  :ifhp=model=<emphasis remap=it>name</emphasis>,appsocket
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

<para>If your printer is a parallel port printer
connected to an <emphasis>external</emphasis> Network Print Spooler such as an HP JetDirect box,
then while the network connection to the Network Print Spooler is
bidirectional
the connection from the Network Print Spooler to the printer
may be unidirectional
and no status information will be returned from the Network Print Spooler.
In this case you <emphasis>must</emphasis> add the <literal>status@</literal>
option to tell &IFHP; not to expect status:
<informalexample>
<screen># Filter, transfer using socket
  :lp=10.1.1.1%9100 
  :ifhp=model=<emphasis remap=it>name</emphasis>,status@
  :filter=/.../ifhp </screen>
</informalexample>
</para>

</sect1>

<sect1>
<title>PS, PCL, PJL Printer with Parallel Port Connection</title>

<para>If your printer is connected to a
<emphasis/bidirectional/
parallel port you may be able to read status from the printer.
First,
determine if your printer has bidirectional IO capability
and if your operating system  has support for it.
If it does not,
then do not  use the
<literal>:rw</literal> (open connection read-write) option
to open the printer device in read write mode.
<informalexample>
<screen># printer setup  
#  force clients (lpr, lpq, to use server)  
lp:lp=lp@serverhost  
# server information  
lp:server  
  # do now open read write
  :rw@
  :sd=<emphasis remap=it>spooldir</emphasis>  
  :...  
  # parallel port 
  :lp=/dev/lpt
  #path to ifhp filter  
  :filter=/.../ifhp  </screen>
</informalexample>
</para>
<para>
If,
on the other hand,
your operating system reports that the parallel port
is bidirectional and is able to read the printer model
information,
then you can try opening the parallel port read-write
and seeing if the &IFHP; filter can read status information:
<informalexample>
<screen># printer setup  
#  force clients (lpr, lpq, to use server)  
lp:lp=lp@serverhost  
# server information  
lp:server  
  # open read write
  :rw
  :sd=<emphasis remap=it>spooldir</emphasis>  
  :...  
  # parallel port 
  :lp=/dev/lpt
  #path to ifhp filter  
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

</sect1>

<sect1>
<title>PS, PCL, PJL Printer with Serial Port</title>

<para>It is strongly advised that serial ports not be used
for high speed data transfers.
The main problem is trying to configure them in such as way
that they do not lose characters due to data overruns or parity errors.
LPRng is strongly deprecating support for serial port printers.</para>

<para>The &LPRng; print spooler will open and set the serial
line characteristics,
and pass the open connection to the
&IFHP; filter.
The
<literal>tty</literal> connection must pass all 8 bits with no parity,
and should use hardware flow control if at all possible.
Unfortunately,
the various <literal>stty</literal>
options needed to do this vary from system to system.
Also, you may discover that your serial connection does not
support hardware flow control.
If this is the case,
then you will have to use software flow control
which is rather unreliable for high speed (over 9600) serial
lines due to the timing latencies involved.
<informalexample>
<screen># printer setup  
#  force clients (lpr, lpq, to use server)  
lp:lp=lp@serverhost  
# server information  
lp:server  
  :sd=<emphasis remap=it>spooldir</emphasis>  
  :...  
  # serial port 
  :lp=<filename>/dev/ttyxxx</filename> 
  :stty=38400 -echo -crmod -raw -oddp -evenp \ 
     ixon pass8 -ixany cbreak crtscts 
  #path to ifhp filter  
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

</sect1>

<sect1
id="psonly">
<title>PostScript Only Printer
</title>

<para>The <literal>model=ps</literal> entry supports PostScript only printers.
<informalexample>
<screen># printer setup  
#  force clients (lpr, lpq, to use server)
lp:lp=lp@serverhost 
# server information  
lp:server  
  :sd=<emphasis remap=it>spooldir</emphasis> 
  :...  
  :ifhp=model=ps 
  #path to ifhp filter  
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

<para>If you have a <emphasis/unidirectional/ or <emphasis/write only/ (no status information)
connection such as a parallel port you should use:
<informalexample>
<screen>:ifhp=model=ps,status@</screen>
</informalexample>
</para>

<para>
<anchor id="ps-eoj">
<anchor id="ps-eoj-at-start">
<anchor id="ps-eoj-at-end">
<anchor id="pcl-eoj-at-start">
Many PostScript printers recognize
the PostScript EOJ marker (Control-D or <literal>\004</literal>)
as an end of PostScript job indication
and will perform page eject and other suitable actions.
Unfortunately,
strictly according to PostScript documentation
this character is only allowed in the Serial Port Data Stream,
and there are some printers that treat it as an error.
In addition,
the Control-T character is recognized as a printer status solicitation,
and some printers do not return status or recognize it as an error.
</para>
<para>
If your printer does not handle PostScript EOJ (Control-D)
at all,
set <literal>ps_eoj@</literal>
to suppress generation of extra Control-D characters by &IFHP;.
If your printer requires a Control-D at the end of the job but
fails when they occur at the start of the job,
set
<literal>ps_eoj_at_start@</literal>.
If
the printer requires a Control-D at the start but not at the end,
set
<literal>ps_eoj_at_start@</literal>.
</para>
<para>
PCL based printers are not nearly as fussy.
However,
you may discover that some of them do not correctly handle
a PCL EOJ at the start of a job
in spite of all examples and documention.
Use the
<literal>pcl_eoj_at_start@</literal>
to suppress adding a
PCL EOJ (Esc E)
command string to the start of a PCL job file.
<informalexample>
<screen>:ifhp=model=ps,ps_eoj@</screen>
</informalexample>
</para>

<para>See the section on
<link linkend="fileconversion">File Conversion Support</link>
for ways to print text and other files on a PostScript printer.
</para>

</sect1>

<sect1>
<title>GhostScript</title>

<para>Generating a raster image from a PostScript or PCL file in
a timely manner requires a high speed processor and substantial amounts
of memory.
Many of the low cost printers require the user's system to do the raster
conversion
and the raster file is then transferred to the printer.
The file format is usually a subset of PCL.</para>

<para>The
<link linkend="ghostscript">GhostScript</link>
program can process PostScript files and produce raster output for a
wide range of devices.
The
<literal>ghostscript</literal>
<literal>pcl_gs</literal>
printer configurations is used
with these printers.
See
<link linkend="ghostscriptconfig">GhostScript Printer</link>
for details.</para>

</sect1>

<sect1
id="phaser">
<title>Tektronics Phaser, QMS, and Appsocket Protocol
</title>

<para>The Tektronics Phaser, QMS Network Printers,
and a few others use the
<link linkend="appsocketpc">Appsocket</link> protocol described
in a previous section.
The Tektronics (<literal>model=phaser</literal>) configuration entry
has the required options for these printers:
<informalexample>
<screen>[ phaser qms ]
appsocket
ps
pjl@
pcl</screen>
</informalexample>
</para>

<para>The following shows a typical printcap entry:
<informalexample>
<screen>#  force clients (lpr, lpq, to use server)
lp:lp=lp@serverhost 
# server information  
lp:server  
  :sd=<emphasis remap=it>spooldir</emphasis> 
  :lp=10.1.1.1%35 
  :...  
  :ifhp=model=phaser
  #path to ifhp filter  
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

</sect1>
</chapter>

<chapter
id="options">
<title>Options and Arguments
</title>
<itemizedlist>
<listitem><para><literal/model=/<emphasis/Model Information/</para></listitem>
<listitem><para><literal/model_from_option=/<emphasis/Option with model information/</para></listitem>
</itemizedlist>

<para>The &IFHP; filter is designed to work with the &LPRng; print spooler
and expects to be passed the standard set of filter options.
These have the form:
<informalexample>
<screen>/.../ifhp [-c] [-X option]* accountingfile
Example:
/.../ifhp -n root -H hostname -P printer -s statusfile acct
# - X is any letter except T</screen>
</informalexample>
</para>

<para>All of the option letters except <literal>T</literal> are reserved by the &LPRng;
program to pass information to the filter.
For details about the options,  please consult the &LPRng; documentation.</para>


<sect1>
<title>Command Line Options</title>

<para>The most important options that &LPRng; passes and that &IFHP; uses are:
<variablelist>
<varlistentry><term>-s statusfile</term>
<listitem>
<para>The file where &IFHP; status information is placed.</para>

</listitem>
</varlistentry>

<varlistentry><term>-Z useroptions</term>

<listitem>
<para>The <command>lpr -Z</command> options passed by the user, and are discussed in
the
<link linkend="options">options</link>
section.</para>

</listitem>
</varlistentry>

<varlistentry><term>-T options</term>

<listitem>
<para>These are usually options specified in the printcap entry
and are discussed in
the
<link linkend="options">options</link> section.</para>
</listitem>
</varlistentry>
<varlistentry><term>accountingfile</term>
<listitem>
<para>The file where accounting information is written.</para>
</listitem>
</varlistentry>
</variablelist>
</para>

<para>
<informalexample>
<screen>Examples:
ifhp "-Tmodel=ps,status@" "-Za4,landscape"</screen>
</informalexample>
</para>

<para>Since commas are used to separate options,
whitespace is used to separate multiple values
for a particular option.
You will need to quote this on a command line. For example:
<informalexample>
<screen>ifhp "-Tfont=elite greek1 dingbat"</screen>
</informalexample>
</para>

<para>The &IFHP; program first checks to see if the
<acronym>PRINTCAP</acronym> environment variable is defined.
By convention, &LPRng; will place the printer printcap entry in this
variable when it starts the &IFHP; filter.
The printcap <literal>:ifhp=options</literal> value is extracted and used
as the default <option>-T</option> options.
After getting the options from the printcap,
the <option>-Toptions</option> command line options are appended to the list of <option>-T</option>
options.
The single letter command line options are also made available to
the &IFHP; programs as shown below:
<informalexample>
<screen>PRINTCAP=lp:ifhp=model=this,status@:...

ifhp -n root -h localhost -Tmodel=that,debug=1

Concatenated -T options:  model=this,status@,n=root,h=localhost,model=that,debug=1
Resulting    -T options:  status@,n=root,h=localhost,model=that,debug=1</screen>
</informalexample>
</para>

<para>The <option>-T</option> option list is scanned from left to right,
and later option values override earlier ones.
The <option>-T</option> option values have priority over values that are obtained
from the configuration file and cannot be overridden.
There are several options that have important effects on the operation
of the &IFHP; filter.</para>

</sect1>

<sect1
id="config">
<title>General Configuration Options - config, trace, debug</title>
<itemizedlist>
<listitem><para><literal/config=/<emphasis/Configuration file location/</para></listitem>
<listitem><para><literal/debug=/<emphasis/Debug options/</para></listitem>
<listitem><para><literal/trace/ FLAG <emphasis/trace on <acronym/STDERR//</para></listitem>
</itemizedlist>

<para>These options are used to control the global operation
of the &IFHP; filter,
and are only available from the <option>-T</option> command line options.
<variablelist>
<varlistentry><term>config=pathname</term>
<listitem>
<para>The <literal>config</literal> option specifies the location of the <filename>ifhp.conf</filename> file.
This overrides the default location.
The pathname can be a file name, list of filenames separated by spaces,
or a filter.
For example:
<informalexample>
<screen>ifhp '-Tconfig=/usr/local/etc/ifhp.conf'
ifhp '-Tconfig=|/usr/local/bin/getconfig'</screen>
</informalexample>
</para>

<para>The second example uses the <literal>getconfig</literal> program
to obtain configuration information.
The configuration information is read from the program's STDOUT.
There program is invoked with no command line  options
and is passed the environment variables that were provided
to &IFHP;.
</para>


</listitem>
</varlistentry>

<varlistentry><term>model=MODEL</term>

<listitem>
<para>The <literal>model</literal> option selects the portion of the &IFHP; configuration
that will set values of configuration parameters.
This is discussed in detail in the next section.</para>


</listitem>
</varlistentry>

<varlistentry><term>trace</term>

<listitem>
<para>As &IFHP; processes the print job,  it produces tracing and error message
information.
By default this is written to the status file specified by the <option>-s</option>
command line option.
The <literal>trace</literal> option will cause this information to be written to
<acronym>STDERR</acronym> (file descriptor 2).
This is usually used in debugging.</para>


</listitem>
</varlistentry>

<varlistentry><term>debug=n</term>

<listitem>
<para>This option sets the debugging level to <literal>n</literal>, where <emphasis remap=tt>n</emphasis> is an integer number.
Level 0 turns debugging off, level 1 produces a small amount of verbosity
and increasing levels produce more verbose information.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1
id="statusfile">
<title>Status Messages
</title>

<itemizedlist>
<listitem><para><literal/statusfile=/<emphasis/statusfile/</para></listitem>
<listitem><para><literal/statusfile_max=/<emphasis/maximum status file size/</para></listitem>
<listitem><para><literal/statusfile_min=/<emphasis/minimum status file size/</para></listitem>
<listitem><para><literal/summaryfile=/<emphasis/one line summary file/</para></listitem>
</itemizedlist>

<para>
<variablelist>
<varlistentry><term>statusfile=pathname or -s pathname</term>
<listitem>
<para>The status file pathname is set by the command line
<option>-s pathname</option>,
or if it is not present then the
<literal>statusfile=pathname</literal>
configuration option.
The file must exist and will not be created.</para>


</listitem>
</varlistentry>

<varlistentry><term>statusfile_max=n</term>

<listitem>
<para>If the status file is larger than
<symbol>statusfile_max</symbol> K bytes (default 8K),
then it is truncated to
<literal>statusfile_min=min</literal>
K bytes.</para>


</listitem>
</varlistentry>

<varlistentry><term>statusfile_min=n</term>

<listitem>
<para>The minimum size in Kbytes of the status file after truncation
(default 1K).</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1
id="status">
<title>Printer Status Available - status
</title>
<itemizedlist>
<listitem><para><literal/status/ FLAG <emphasis/status available from device/</para></listitem>
</itemizedlist>

<para>The <literal>status</literal> option indicates that there is a bidirectional
connection to the printer,
and that status can be obtained from the connection.
During initialization
the &IFHP; filter will test the printer connection and determine if
it supports reading.
If it does not then &IFHP; will set <literal>status@</literal>.</para>

</sect1>

<sect1>
<title>Monitoring Options - sync, waitend, pagecount</title>

<para>The <literal>sync</literal>, <literal>waitend</literal>, and <literal>pagecount</literal>
options are ignored if no status is available from the printer.
The <literal>sync</literal> option specifies the method to use to
determine if the printer is ready and operational.
The <literal>waitend</literal> option specifies the method used to determine
when a print job is finished.
The <literal>pagecount</literal> option specifies the method used to obtain pagecount
or status information.
<variablelist>
<varlistentry><term>sync@, waitend@, pagecount@ </term>
<listitem>
<para>This form of the tag indicates that the particular facility is disabled.</para>


</listitem>
</varlistentry>

<varlistentry><term>sync=pjl</term>

<listitem>
<para>PJL is used to determine if the printer is ready.
This can be done by sending a PJL JOB or PJL ECHO
command to the printer and waiting for return status.</para>


</listitem>
</varlistentry>

<varlistentry><term>sync=ps</term>

<listitem>
<para>A small PostScript job which causes a status report to be returned
is sent to the printer.</para>


</listitem>
</varlistentry>

<varlistentry><term>waitend=pjl, waitend=ps</term>

<listitem>
<para>This is similar to the <literal>sync</literal> operation,
but is done at the end of a job in order to determine if the
printer is busy.</para>


</listitem>
</varlistentry>

<varlistentry><term>pagecount=pjl</term>

<listitem>
<para>Many PJL capable printers support reporting total page usage by
means of PJL.
This option causes a PJL command to be sent requesting the
total page usage by the printer.</para>


</listitem>
</varlistentry>

<varlistentry><term>pagecount=ps</term>

<listitem>
<para>A small PostScript job which causes a status report to be returned
is sent to the printer.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>User -Z Option Support</title>

<para>The &IFHP; filter provides a simple way for users to request
a particular printer facility or option.
The <literal>lpr -Zkey=value</literal> command causes the <application/lpd/
print spooler to pass the <option>-Z</option> options on the &IFHP; command line.</para>

<para>The &IFHP; filter implements these options by first determining if they
are allowed,
and then using them to select a set of strings that are sent to the printer.
Since some options are implement by sending PJL strings to the printer,
some by PostScript,
and some by PCL commands,
the method of specifying and generating them is a bit involved.</para>

<para>The following facility is used to control the names and types of user
options.
<variablelist>
<varlistentry><term>pjl_user_opts=[ ... ]</term>
<listitem>
<para>This tag specifies the list of user options that are implemented by
sending PJL strings to the printer.
This is available only if the printer is PJL capable.</para>

</listitem>
</varlistentry>

<varlistentry><term>pcl_user_opts=[ ... ]</term>

<listitem>
<para>This tag specifies the list of user options that are implemented by
sending PCL strings to the printer.
This is available only if the printer is PCL capable.</para>

</listitem>
</varlistentry>

<varlistentry><term>ps_user_opts=[ ... ]</term>

<listitem>
<para>This tag specifies the list of user options that are implemented by
sending PostScript strings to the printer.
This is available only if the printer is PostScript capable.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

<para>For each option,
the actual string or set of strings is specified as follows.
<variablelist>
<varlistentry><term>pjl_<emphasis remap=it>key</emphasis>= ...</term>
<listitem>
<para>The value of the PJL user option <literal>key</literal>.
This value can be one or more lines;
the lines are checked for correct PJL format and sent to the printer
before any language specific information.</para>

</listitem>
</varlistentry>

<varlistentry><term>ps_<emphasis remap=it>key</emphasis>= ... </term>

<listitem>
<para>The value of the PostScript user option <literal>key</literal>.
This value can be one or more lines;
leading and trailing whitespace is removed and the lines are
placed before the first lines of a PostScript job file.</para>

</listitem>
</varlistentry>

<varlistentry><term>pcl_<emphasis remap=it>key</emphasis>= ... </term>

<listitem>
<para>The value of the PCL user option <literal>key</literal>.
This value can be one or more lines;
whitespace and new lines are removed and the
characters are placed before the first characters of a PCL job file.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

<para>The following user options are predefined in the default
<filename>ifhp.conf</filename> file and are recommended for use.
<variablelist>
<varlistentry><term>a3, a4, a5 </term>
<listitem>
<para>Use a3, a4, or a5 paper</para>

</listitem>
</varlistentry>

<varlistentry><term>copies=N</term>

<listitem>
<para>Print N copies of a page or job</para>

</listitem>
</varlistentry>

<varlistentry><term>duplex</term>

<listitem>
<para>Use duplex printing,  tumble on.
Pages will come out so that the margins are at opposite ends
of a page.</para>

</listitem>
</varlistentry>

<varlistentry><term>duplexshort</term>

<listitem>
<para>Use duplex printing,  tumble off.
Pages will come out so that the margins are at the same
ends of a page.</para>

</listitem>
</varlistentry>

<varlistentry><term>envelope</term>

<listitem>
<para>Select envelope media</para>

</listitem>
</varlistentry>

<varlistentry><term>inlower</term>

<listitem>
<para>Select media from lower input bin.</para>

</listitem>
</varlistentry>

<varlistentry><term>inupper</term>

<listitem>
<para>Select media from upper input bin.</para>

</listitem>
</varlistentry>

<varlistentry><term>landscape</term>

<listitem>
<para>Use Landscape orientation</para>

</listitem>
</varlistentry>

<varlistentry><term>lduplex</term>

<listitem>
<para>Alias for duplex</para>

</listitem>
</varlistentry>

<varlistentry><term>ledger</term>

<listitem>
<para>Select ledger size (11x15 inches) media</para>

</listitem>
</varlistentry>

<varlistentry><term>legal</term>

<listitem>
<para>Select legal size (8.5x15 inches) media</para>

</listitem>
</varlistentry>

<varlistentry><term>letter</term>

<listitem>
<para>Select letter size (8.5x11 inches) media</para>

</listitem>
</varlistentry>

<varlistentry><term>manual</term>

<listitem>
<para>Select media from manual feed</para>

</listitem>
</varlistentry>

<varlistentry><term>mediaselect=N</term>

<listitem>
<para>Select media number N</para>

</listitem>
</varlistentry>

<varlistentry><term>outlower</term>

<listitem>
<para>Put output in lower tray or bin</para>

</listitem>
</varlistentry>

<varlistentry><term>outupper</term>

<listitem>
<para>Put output in upper tray or bin</para>

</listitem>
</varlistentry>

<varlistentry><term>oversize</term>

<listitem>
<para>Select oversize media</para>

</listitem>
</varlistentry>

<varlistentry><term>portrait</term>

<listitem>
<para>Use Portrait orientation</para>

</listitem>
</varlistentry>

<varlistentry><term>sduplex</term>

<listitem>
<para>Alias for duplexshort.  Print on a single side of the media. </para>

</listitem>
</varlistentry>

<varlistentry><term>simplex</term>

<listitem>
<para>Print on the single side of the media. </para>

</listitem>
</varlistentry>

<varlistentry><term>transparency</term>

<listitem>
<para>Select transparency media</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Adding User Options</title>

<para>The following shows how to add a PJL option to an <filename>ifhp.conf</filename>
file.
By convention,
the configuration is added to the end of the <filename>ifhp.conf</filename> file.
<informalexample>
<screen>[ newprinter ]
pjl_user_opts += [ screen ]
pjl_screen = PJL SCREEN = ON

ps_user_opts += [ fuzzy ]
ps_fuzzy = &lt;&lt;/Fuzzy (\%s{fuzzy})&gt;&gt; setpagedevice
</screen>
</informalexample>
</para>

<para>In the first example we define the <literal>screen</literal> option.
The <command>lpr -Zscreen</command> option will cause the PJL command
<literal>PJL SCREEN = ON</literal> to be put into the output to the printer.</para>

<para>Similarly,
<literal>lpr -Zfuzzy=5</literal> will cause the PostScript command
<literal> &lt;&lt;/Fuzzy (\%s{fuzzy})&gt;&gt; setpagedevice </literal>
to be processed and the resulting
<literal> &lt;&lt;/Fuzzy (5)&gt;&gt; setpagedevice </literal>
command to be sent to the printer.</para>

</sect1>

<sect1>
<title>Initialization and Setup Control</title>

<para>Several options are used during
the processing steps discussed in
<link linkend="details">Filter Operation Details</link>
to control what setup is done for the printer.
<variablelist>
<varlistentry><term>pjl_init = [ ... ]</term>
<listitem>
<para>If PJL is enabled on this printer,
options in this list are expanded and the resulting values
are sent to the printer.
After this,
the -Z options are expanded and any options which
are listed in the <symbol>pjl_user_opts</symbol> are processed.</para>


</listitem>
</varlistentry>

<varlistentry><term>ps_init = [ ... ]</term>

<listitem>
<para>If PostScript is enabled on this printer and a PostScript file
is being processed,
then the
options in this list are expanded and the resulting values
are sent to the printer.
After this,
the -Z options are expanded and any options which
are listed in the <symbol>ps_user_opts</symbol> are processed.</para>


</listitem>
</varlistentry>

<varlistentry><term>pcl_init = [ ... ]</term>

<listitem>
<para>If PCL is enabled on this printer and a PCL file
is being processed,
then the
options in this list are expanded and the resulting values
are sent to the printer.
After this,
the -Z options are expanded and any options which
are listed in the <symbol>pcl_user_opts</symbol> are processed.</para>

</listitem>
</varlistentry>
</variablelist>
</para>

<para>These initialization options are very useful in order to set up
information controlling the default format or options for a
print job.
For example:
<informalexample>
<screen>pcl_init = [ normalpage ]
pcl_normalpage=[ letter crlf linewrap
  portrait clearmargins fixed pitch=10 courier ]</screen>
</informalexample>
</para>

<para>When processing a PCL job, <literal>normalpage</literal> is expanded by searching first
for <literal>normalpage</literal> and then for <symbol>pcl_normalpage</symbol>;
this in turn results in the expansion of the list of values.
For example,
<symbol>pcl_crlf</symbol> is usually defined as <literal>pcl_crlf=\033&amp;k2G</literal>,
which is the PCL command to translate a New Line (<literal>\015</literal>) character
as a Carriage Return/New Line.
The other entries have similar definitions that produce the
desired effects.</para>

</sect1>
</chapter>

<chapter>
<title>Configuration File</title>

<para>This section will cover the <filename>ifhp.conf</filename> file and the various options
and configuration methods used to control the operation of the &IFHP;
filter.</para>


<sect1>
<title>Configuration File Entries</title>

<para>The &IFHP; filter uses a simple text based configuration file,
usually <filename>/usr/local/etc/ifhp.conf</filename> or <filename>/etc/ifhp.conf</filename>
to get a set of configuration values which control its operation.
The following sample configuration file segment shows how information
is specified.
<informalexample>
<screen># comment line - first non-blank character is a #
#---- DEFAULTS ----
# we first have the default section
#   - a flag option whose value is 1
on_flag
#   - a flag option whose value is 0
off_flag@
#   - a flag option whose value is a string (single line)
#     its value will be 'this is a string'
strval = this is a string
#   - a flag option whose value is multiple lines
#     each additional line starts with whitespace
#     value is 'this\nis1\na\nstring'
longstrval = this
 is\061
 a
 string
#   - and a list that gets expanded -
#     '[ this ] [ is a\nlist ]' -&gt; [ this is a list ]
longlist = [ this ] [ is a
 list ]
#    we can extend a string.
#    strval will  now be 'this is a string added'
strval += added
#    and we can expand a list
#     '[ this ] [ is a\nlist ] [ more ]' -&gt; [ this is a list more ]
longlist += [ more ]

# a printer specific section
# ---- PRINTER ----
[ hp hp4* ]
# this match model=hp, model=hp4, model=hp4x
# override the default
onflag@
include /usr/local/etc/ifhp.conf.local

[ entry1 ]
value
[ entry2 ]
tc=entry1</screen>
</informalexample>
</para>

</sect1>

<sect1>
<title>Comments</title>

<para>Comments are lines whose first non-whitespace character is <literal>#</literal>.
Use <literal>\#</literal> if the first non-whitespace character must be <emphasis remap=tt>#</emphasis>.</para>

</sect1>

<sect1>
<title>Option Setting</title>

<para>
<informalexample>
<screen>Syntax             Equivalent To
option                     option=1
option@                    option=0
option=val
option=[ v1 v2  ... ]      value contains all whitespace
option=[ v1                up to the next option entry
 v2                        blank lines and comments
 v3                        are not included
 ]
option=v1
 v2
 v3</screen>
</informalexample>
</para>

<para>If an option's default value is the empty string (<literal>''</literal>).
The &IFHP; program uses the Perl language convention that this
value is equivalent to 0 when used in a numerical context or
the empty string when used in a string context.</para>

<para>In general when a string is used in an integer context it is converted
to a the appropriate numerical type using the standard Perl/C
numerical representation and conversion methods.</para>

<para>The <literal>flag</literal> syntax sets the value of <emphasis remap=tt>flag</emphasis> to the string <literal>'1'</literal>,
that is, the string with a 1 value, and <literal>flag@</literal> sets it to <literal>'0'</literal>. </para>

<para>The <literal>option = value</literal> syntax sets the option value to a string.
The string can extend across multiple lines.
A line starting with a space has its value appended to the
previous option with a new line (<literal>\n</literal>) separator.</para>

<para>As shown in the example,
the <literal>+=</literal> operator is used to append to a string value.
The <literal>[ option option ...]</literal> syntax is used to specify that the
value is a list.
Lists are used to specify a list of options which can be flags or string
values.
Lists have the property of
<emphasis>recursive evaluation</emphasis>
which means that the individual list items will be further processed during
printing.
This is discussed later in detail.</para>

<para>The <literal>include</literal> facility is currently deprecated,
and may not be implemented in future releases.
It will cause the specified file to be read and processed at
that point in the configuration file.</para>

</sect1>

<sect1>
<title>Option Use</title>

<para>Options and their values are used to control printer operation.
There are two types of options:
those with a predefined or
<emphasis>builtin</emphasis>
meaning to the
&IFHP;
filter and those which
have their values sent to the printer when appropriate.
The builtin options are listed
and their use is explained
in later sections.</para>

</sect1>

<sect1>
<title>List Expansion</title>

<para>The
&IFHP;
filter configures a printer by sending the values of options to the printer
or performing built-in operations.
An option can have a flag, string, or list value.</para>

<para>A LIST value has the form <literal>[ v1 v2 ... ]</literal>.
When a list value is to be sent to the printer
each of <literal>v1</literal>, <emphasis remap=tt>v2</emphasis>, etc. is expanded in turn
and the corresponding string value or builtin action is carried out.
If the string value of a term is itself a list,
the list will be expanded in turn.
Recursive list evaluation will result in an error.
The following is an example of list expansion:
<informalexample>
<screen>t1=[ p1 p2 ]
p1=this is
p2=[ p3 p4 ]
p3=a
p4=test</screen>
</informalexample>
</para>

<para>The option <literal>t1</literal> is expanded by expanding <emphasis remap=tt>p1</emphasis> and then <emphasis remap=tt>p2</emphasis>;
The expansion of <literal>p1</literal> produces
<literal>"this is"</literal>,
and <literal>p2</literal> produces
<literal>[p3 p4]</literal>.
This list is then expanded to produce
<literal>"a"</literal>
and
<literal>"test"</literal>.</para>

<para>Some LIST options are used in
printer language specific contexts
and their values are processed appropriately.
For example,
pjl_init=[...] specifies a set of
initialization operations for PJL printers,
and pcl_init=[...] is used to specify the initialization
needed for PCL printing.
The expansion of the LIST entries is done in the language
specific context.
For PJL this requires that the output be well formed PJL commands,
and for PCL that all whitespace be removed.</para>

<para>The context dependent expansion is required because sometimes it
is necessary to do operations both using PJL and PCL or PJL and PS
combinations to ensure correct printer operation.
During expansion the language name and an underscore
is prefixed to the list entry name and this is used as the option name during expansion.
If the prefixed name is not found then the unprefixed name will be used.
For example,  suppose that we have:
<informalexample>
<screen>pjl_init=[ initstr test ]
pcl_init=[ initstr ]
pjl_initstr=@PJL ECHO YES
pcl_initstr=\033(*0V
test=DONE</screen>
</informalexample>
</para>

<para>When PJL initialization is being done and we want string values
for the <symbol>pjl_init</symbol> LIST, we expand  <literal>initstr</literal> and <literal>test</literal>
in the <symbol>pjl_</symbol> context.
First a defined <symbol>pjl_initstr</symbol> value will be looked for and then
a defined <literal>initstr</literal> value.
Since there is a value of <symbol>pjl_initstr</symbol> it will be used.</para>

<para>Similarly we will check for <symbol>pjl_test</symbol> and <literal>test</literal> values.
Since <symbol>pjl_test</symbol> does not have a defined value
the <literal>test</literal> value <acronym>DONE</acronym> will be used.</para>

<para>When PCL initialization is being done and we want string values
for the <symbol>pcl_init</symbol> LIST, then we expand  <literal>initstr</literal>
in a similar way, resulting in <literal>\033(*0V</literal>.</para>

<para>We can use the list entry
<literal>[ option=value ]</literal>
to temporarily specify the value of a variable
which is then used during language specific expansion.
For example,
suppose that we have the following set of definitions:
<informalexample>
<screen>pjl_init=[ initstr=testing ]
pjl_initstr=@PJL INIT=\%s%lcub;initstr%rcub;XQ</screen>
</informalexample>
</para>

<para>As discussed in the next section,
the <literal>\%s%lcub;initstr%rcub;</literal> will cause the value for the <emphasis remap=tt>initstr</emphasis> value to
be substituted into the <symbol>pjl_initstr</symbol> string.
How this is done is discussed in the section on
<link linkend="stringescape">String Escape Sequences</link>.</para>

</sect1>

<sect1
id="stringescape">
<title>String Escape Sequences
</title>

<para>String values have a syntax similar to PERL or C.
The <literal>\</literal> (escape) character indicates the start of an escape sequence string.
This has the syntax:
<variablelist>
<varlistentry><term>Standard Character Replacement</term>
<listitem>
<para><literal>\f</literal>,
<literal>\r</literal>,
<literal>\n</literal>,
and
<literal>\t</literal>
are replaced in turn by the ASCII characters FF, CR, NL,
and HT whose values are 014, 015, 012, and 011 respectively.</para>

</listitem>
</varlistentry>

<varlistentry><term>Octal Character Replacement</term>

<listitem>
<para><literal>\nnn</literal>,
where nnn is 3 octal digits, is replaced by the corresponding character
with the specified value.</para>

</listitem>
</varlistentry>

<varlistentry><term>Option Value Replacement</term>

<listitem>
<para><literal>\%format{option}  OR  \%format[option]</literal></para>

<para>The value of the option will be determined and replaced by a formatted string.
The option value is determined by the following algorithm.
<orderedlist>

<listitem>
<para>When expanding a list value, the
<literal>option=word</literal>
will push the
<literal>option=word</literal>
combination onto an evaluation stack,
and then the <literal>option</literal> value is expanded in the
current language context.</para>
</listitem>

<listitem>
<para>When starting a search for
<literal>{option}</literal>
in a language context <symbol>lang_</symbol>,
the stack of list values is searched in oldest to newest order for a match
for <symbol>lang_option</symbol> and then for <literal>option</literal>.
The first one found is used as the option value.</para>
</listitem>

<listitem>
<para>After searching the evaluation stack for
<literal>{option}</literal>
and finding no match, the <option>-Z</option> command line option values
are searched for a matching entry.</para>
</listitem>

<listitem>
<para>If none is found, then the <option>-T</option> command line option values
and next the printer configuration will then be searched for
<symbol>lang_option</symbol> and then for <literal>option</literal>.
If no match is found,  then the empty string will be the result
if a string is wanted, or the value 0 if a number is wanted.</para>
</listitem>

<listitem>
<para>If the result of this lookup is a list,
then the list will be expanded in turn,
and the concatenating values of the expansion will be used.</para>
</listitem>

<listitem>
<para>When starting a search for
<literal>[option]</literal>
the
<option>-T</option> command line options will be searched first
and next the printer configuration will be searched for
<symbol>lang_option</symbol> and then for <literal>option</literal>.
If no match is found,  then the empty string will be the result
if a string is wanted, or the value 0 if a number is wanted.</para>
</listitem>

<listitem>
<para>***help*** If the result of this lookup is a list
If no match was found,
then the search rules for
<literal>{option}</literal>
will be used,
and the list expansion will be done as described above.
If no match was found a null (empty string) value will be used.</para>
</listitem>

</orderedlist>
</para>

</listitem>
</varlistentry>

<varlistentry><term>Option Value Format</term>

<listitem>
<para>
<informalexample>
<screen>   %[-][0][length[.precision]][format]
   %d{1}   =&gt;  '1'       %s{1}   =&gt; '1'
   %3d{1}  =&gt;  '  1'     %3s{1}  =&gt; '  1'
   %03d{1} =&gt;  '0001'    %-3s{1} =&gt; '1  '
   %4.2f{1} =&gt; '1.00'
 Special Case Conversion:
   %s{ThisWord} =&gt; 'ThisWord'
   %U{ThisWord} =&gt; 'THISWORD'
   %M{ThisWord} =&gt; 'Thisword'
   %L{ThisWord} =&gt; 'thisword'
</screen>
</informalexample>

The format specifies how the value is to appear,
and is similar to the printf format usage.</para>

<para>Depending on the format type,
a value will be converted and used appropriately.
The empty string or null value (<literal>''</literal>) will be treated as a <emphasis remap=tt>'0'</emphasis>
value when used in an numeric context.</para>

<para>The default format is %d, ie, \%{val} would be \%d{val}.
The numerical formats supported are: %d, %o, %x, %X, %e, %f, and %g;
The %s format use the string value of the result.</para>

<para>The
<literal/U/,
<literal/M/,
and
<literal/L/ have the same behavior as the <literal/s/ format,
but the string value is then uppercased,
lowercased  and the first letter uppercased,
and lowercased respectively.
This allows various programs that have fussy requirement about the
case of their options to be handled correctly.
</para>

</listitem>
</varlistentry>
</variablelist>
</para>

</sect1>

<sect1>
<title>Language Context and Value Expansion</title>

<para>The &IFHP; filter sends initialization and configuration commands to the
printer.
Depending on the type of language of a print file (i.e. - PostScript or PCL),
different command formats would need to be used to implement different options.
For example,  to implement a <emphasis>landscape</emphasis> option for a PJL aware printer
you would need to send the PJL command <literal>@PJL SET ORIENTATION=LANDSCAPE</literal>.
For a PostScript printer you would need to send a very strange string
which would depend on the actual printer mode.</para>

<para>Our language context also includes various checks for
language specific dependencies.
This section refers to material that is discussed in depth in later
sections of this document,
and on first reading may be a little confusing.
However,
if you are not aware of some of these restrictions then much of the information
in the configuration files may be very confusing.</para>


<sect2>
<title>PJL Language</title>

<para>A PJL command has the form
<literal>@PJL OPCODE ...</literal>,
and PJL commands must be sent as a block before any other commands.
In order to assist with this,
the &IFHP; filter provides the following assistance.
When expanding a list value,
each list entry is expected to form a well formatted PJL command.
<orderedlist>

<listitem>
<para>Before sending any PJL command to the printer,
the PJL Universal Exit Command
(<literal>\033%-12345X</literal>)
string is sent to the printer.
This is automatically done if <literal>pjl</literal> is enabled for the printer.</para>
</listitem>

<listitem>
<para>The list item is expanded,
and all value substitutions are done.
Leading and trailing whitespace is removed,
all characters are converted to uppercase,
and a new line (<literal>\n</literal>) value is appended to the command.</para>
</listitem>

<listitem>
<para>Because not all printers support all PJL commands,
the &IFHP; filter performs uses the
<symbol>pjl_only</symbol>
and
<symbol>pjl_except</symbol>
configuration lists to ensure that the options are allowed by the printer.
The OPCODE must appear in the
<symbol>pjl_only</symbol>
list and not in the
<symbol>pjl_except</symbol>
list.
For example:
<informalexample>
<screen>pjl_only = [ JOB SET STATUS ]
pjl_except = [ STATUS ]</screen>
</informalexample>

</para>

<para>The <symbol>pjl_only</symbol> indicates that the printer supports the PJL JOB, SET, and STATUS
commands,  but the <symbol>pjl_except</symbol> list removes the STATUS from this list.
This means that only the
JOB and SET commands will be allowed.</para>
</listitem>

<listitem>
<para>If the command is a <acronym>SET</acronym> command,
then the PJL variable must appear in the <symbol>pjl_vars_set</symbol>  list
and not in the <symbol>pjl_vars_except</symbol> list.
<informalexample>
<screen>pjl_vars_set = [ PAPER SIZE ORIENTATION ]
pjl_vars_except = [ PAPER ]

@PJL SET SIZE=A4
@PJL SET PAPER=LETTER</screen>
</informalexample>

</para>

<para>In the above example, the <literal>SIZE=A4</literal> command would be allowed
and sent while the
<literal>PAPER=LETTER</literal> command would be rejected and not sent.</para>
</listitem>

</orderedlist>
</para>

</sect2>

<sect2>
<title>PCL Language</title>

<para>When sending PCL initialization strings to a printer,
it is essential to send nothing that could cause a printable character to
be sent before the actual file contents.
Such output could cause the location and positioning of text to be altered
in unexpected ways.
To avoid this,
the following steps are taken when expanding a list in a PCL language context.
<orderedlist>

<listitem>
<para>Before any PCL string is sent to the printer,
the PCL End of Job
(<literal>\033E</literal>) string is sent to the printer.</para>
</listitem>

<listitem>
<para>All whitespace (blanks, tabs, etc) are removed from the string value.</para>
</listitem>

<listitem>
<para>Next, all escaped values are substituted.
At this point you can
<emphasis>force</emphasis>
printable strings containing whitespace into the output by using the
<literal>\nnn</literal>
escape mechanism.</para>
</listitem>

<listitem>
<para>All list values are concatenated and then sent to the printer.</para>
</listitem>

</orderedlist>
</para>

</sect2>

<sect2>
<title>PostScript Language</title>

<para>The PostScript language processing is very minimal,
as there are few problems sending PostScript to a printer.
<orderedlist>

<listitem>
<para>Before sending any PostScript initialization strings,
the PostScript End of Job indicator
(<literal>\004</literal> or Control-D) is sent.</para>
</listitem>

<listitem>
<para>Strings are then expanded and the escape sequences are substituted.</para>
</listitem>

<listitem>
<para>Individual strings have a newline
(<literal>\n</literal>) appended to them before being sent to the printer.</para>
</listitem>

</orderedlist>
</para>

</sect2>
</sect1>

<sect1>
<title>Printer Entries</title>

<para>The <filename>ifhp.conf</filename> file is divided into printer entries by <literal>[ pattern pattern ...]</literal>
lines.
Each pattern is glob matched against the <literal>model</literal> option value,
and if the match is successful then the options on the following lines
until the next
printer entry header
are appended to the specific printer configuration entry.</para>

<para>By convention,
each configuration file is assumed to start with the header
<literal>[ default ]</literal>,
and the initial set of lines are used to
set default values for the various &IFHP; options.</para>

<para>The algorithm for scanning the configuration files first
sets the <literal>model</literal> value to <emphasis remap=tt>default</emphasis>,
and extracts the default information.
It then sets the <literal>model</literal> value to the user specified value,
and rescans the configuration file information.</para>

<para>If users need to add or modify the <filename>ifhp.conf</filename> file,
then they should add their entries to the end of the file,
and override any default options by specific values in their new entry.
To aid with system configuration and maintenance,
the distributed <filename>ifhp.conf</filename> file has the following text at the end of the file:
<informalexample>
<screen>##### This is the end of the standard ifhp.conf file.
##### Add your local files after this
##### If you want to override some entries, simply change the names to
##### something different, i.e. hp4 hp4.old
##### Here is a script to do this and then append your local file to the
##### end of the ifhp.conf file:
#####
##### #!/bin/sh
##### for i in $* ; do
#####   perl -spi.bak -e 's/ $i / $i.orig /g' ifhp.conf
##### done
#####
##### sed -n -e '1,/XXX END XXX/p' ifhp.conf &gt;ifhp.conf.new
##### sed '1,/XXX END XXX/d' ifhp.old &gt;&gt; ifhp.conf.new
#####
##### You can probably improve on this.
#####
#### XXX END XXX #####

# user adds new default values here for all printer entries
[ default ]
# set default value
pcl_option= \033test

[ mypcl_printer ]
# override default value
pcl_option=
</screen>
</informalexample>
</para>

</sect1>

<sect1>
<title>Include Facility</title>
<para>
The <literal>include filename</literal>
facility is similar to the standard compiler
file inclusion facility.
The specified file or list of files separated by commas or whitespace
will be substituted for the indicated line.
</para>
</sect1>

<sect1>
<title>tc Entry Inclusion Facility</title>
<para>
The <literal>tc=entry</literal> facilty is similar to the printcap <literal>tc</literal>
facility used in the &LPRng; software other places.
The specified entry or list of entries separated by commas or whitespace
will be substituted for the indicated line.
</para>
</sect1>
</chapter>

<chapter
id="details">
<title>Filter Operation Details

</title>

<para>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
<acronym>STDIN</acronym>
(file descriptor 0)
and results written to
<acronym>STDOUT</acronym> (file descriptor 1).
Status reports are written to
a status file or optionally to
<acronym>STDERR</acronym> (file descriptor 2),
together with any error messages or diagnostics.</para>

<para>In addition to normal operation
the filter can run in the
<acronym>OF</acronym> 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 two character sequence <literal>"\031\001"</literal> to the filter.
will cause the filter to suspend itself by sending itself a <acronym>SIGSUSP</acronym>
signal.
The print spooler will detect this and then
send job files to the same output device.
After the files have been transferred the
the filter will be restarted with a SIGCONT signal.</para>


<sect1>
<title>Filter Pseudo-Code</title>

<para>The details of the filter operations are
described in the following
<emphasis>pseudo-code</emphasis>.
The sections marked with <literal>###</literal> are discussed later in this document
in detail.</para>

<para><filename>///</filename> See:
<link linkend="setup">Options, Initialization and Setup</link>
<informalexample>
<screen>###+++ 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
	}
}
Add the -T command line options to the Toptions list
Add the -Z command line options to the Zoptions list
foreach option in -Toptions do
    if( option = "debug=level" ){
        set Debuglevel = level;
    }
    if( option = "trace" ){
        output error and trace on STDERR
    }
    if( option = "config=pathlist" ){
        set configuration pathlist = pathlist;
    }
    if( option = "model=name" and model not set ){
        set model = name;
    }
}
Read the configuration files from the config file list
Prepend each file with a [ default ] header

Scan the configuration files for [ default ] entries;
  later entry values will override earlier ones.

Repeat the scan, but this time search for [ model ] entries
  matching the specified model.

Put the command line options and -T options into configuration
  information, effectively overriding the information from the
  configuration files.

if( appsocket ) {
   Get the :lp=... entry from the PRINTCAP_ENTRY environment variable
   if( no information ) {
       use the getpeername() to get the TCP/IP address of the current
       connection.
   }
   if( no informtion AND no dev=... parameter ) {
       error!
   }
   close connection to printer and set -Tdev= device or IP Address
}

// open a connection to the printer if required
// usually only done when appsocket protocol is used
if( device specified using -Tdev=device ){
    close(1)
	// if device is host%port, we open TCP/IP connection
	fd = open(device);
	// Note - status  opens RW
	//        status@ opens WO
	dup fd to 1; close fd;
}

###---</screen>
</informalexample>

<filename>///</filename> See:
<link linkend="syncpage">Synchronization and Pagecount</link>
<informalexample>
<screen>###+++ Synchronization and Pagecount
if( status returned by printer and sync requested ){
	do{
		send command and wait for timeout;
    } while( no response );
	if( appsocket ){
		close and reopen TCP/IP connection;
	}
}


if( status and pagecount requested ){
    // 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;
	}
}
###---</screen>
</informalexample>

<filename>///</filename> See:
<link linkend="pjlinit">PJL Initialization</link>
<informalexample>
<screen>### 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</screen>
</informalexample>

<filename>///</filename> See:
<link linkend="conversion">File Conversion Support</link>
<informalexample>
<screen>// 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 ps_eoj_at_start is clear ){
		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 pcl_eoj_at_start is clear ){
		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
}</screen>
</informalexample>

<filename>///</filename> See:
<link linkend="languageinit">Language Specific Initialization</link>
<anchor id="pcl-user-opts">
<anchor id="ps-user-opts">
<informalexample>
<screen>// 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_opts=[ ... ] ){
            ###+++ expansion as above
            ###---
        }
    }
    remove whitespace and expand string results;
} else if( language = PS ){
    ###+++ language specific actions as above,
      using the ps_ prefix for lookup
      allow only user option in the ps_user_opts list
    expand string results but do not remove whitespace
}</screen>
</informalexample>

<filename>///</filename> See:
<link linkend="filetransfer">File Transfer and Error Status Monitoring</link>
<informalexample>
<screen>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( 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</screen>
</informalexample>
</para>

</sect1>

<sect1
id="setup">
<title>Options, Initialization and Setup
</title>

<para>During the setup step,
the &IFHP; system will extract command line options
and scan configuration files for printer entries.
These operations are covered in detail in other sections.</para>

</sect1>

<sect1
id="languages">
<title>Languages Supported- pjl, pcl, ps, and text
</title>
<itemizedlist>
<listitem><para><literal/pjl/ FLAG <emphasis/PJL Supported/</para></listitem>
<listitem><para><literal/pcl/ FLAG <emphasis/PCL Supported/</para></listitem>
<listitem><para><literal/ps/ FLAG <emphasis/PostScript Supported/</para></listitem>
<listitem><para><literal/text/ FLAG <emphasis/Text Supported/</para></listitem>
</itemizedlist>

<para>These flags set the languages that are recognized or processed by
the filter.</para>


<sect2
id="pjl-job">
<title>pjl_job FLAG
</title>
<itemizedlist>
<listitem><para><literal/pjl_job/ FLAG <emphasis/Send PJL Job and EOJ/</para></listitem>
</itemizedlist>

<para>If PJL is enabled and the <literal/pjl_job/ flag is SET
a PJL JOB and PJL EOJ command will be generated
and sent to the printer at the job start and end respectively.
The <literal/JOB/ command has the form:
<informalexample>
<screen>@PJL JOB NAME = "..." [ START = nnn ] [ END = mmm ]</screen>
</informalexample>

The START and END values can be specified by
<literal>-Zstartpage=nnn</literal>
and
<literal>-Zendpage=mmm</literal>
command line options.
The EOJ command has must match the JOB command.
<informalexample>
<screen>@PJL EOJ NAME = "..." [ START = nnn ] [ END = nnn ]</screen>
</informalexample>
</para>

</sect2>

<sect2
id="pjl-enter">
<title>pjl_enter FLAG
</title>
<itemizedlist>
<listitem><para><literal/pjl_enter/ FLAG <emphasis/Send PJL ENTER /</para></listitem>
</itemizedlist>

<para>If PJL is enabled and the <literal/pjl_enter/ flag is SET,
a PJL ENTER LANGUAGE = xx command will be generated
when PCL or PS files are sent to the printer.
<informalexample>
<screen>@PJL ENTER LANGUAGE = PCL
@PJL ENTER LANGUAGE = POSTSCRIPT</screen>
</informalexample>
</para>

</sect2>

<sect2
id="remove-pjl-at-start">
<title>remove_pjl_at_start FLAG
</title>
<itemizedlist>
<listitem><para><literal/remove_pjl_at_start/ FLAG <emphasis/Remove PJL code from begining of job/</para></listitem>
</itemizedlist>

<para>Some printer drivers will prepend PJL code to the begining of print jobs.  If the <literal/remove_pjl_at_start/ flag is SET,
&IFHP; will remove this PJL code.</para>

</sect2>

<sect2
id="nullpad">
<title>nullpad STRING
</title>
<itemizedlist>
<listitem><para><literal/nullpad=/ ephasis/null character count/</para></listitem>
</itemizedlist>

<para>Some older model HP printers require receiving a large number of
NULL (0) characters to force commands in the input buffer to be read.
This can be done using the
<literal>nullpad</literal> option.
In practice,
this has turned out to be largely irrelevant
as most newer printers and network interface printers
do not have this problem.
</para>

</sect2>

<sect2
id="pjl-console">
<title>pjl_console FLAG
</title>
<itemizedlist>
<listitem><para><literal/pjl_console/ FLAG <emphasis/printer console messages/</para></listitem>
</itemizedlist>

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

</sect2>

<sect2
id="remove-ctrl">
<title>remove_ctrl STRING
</title>
<itemizedlist>
<listitem><para><literal/remove_ctrl=/<emphasis/remove control characters /</para></listitem>
</itemizedlist>

<para>The
<symbol>remove_ctrl</symbol> 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:
<informalexample>
<screen>remove_ctrl=CT</screen>
</informalexample>

would cause Control-C and Control-T characters to be removed.</para>

</sect2>

<sect2
id="tbcp">
<title>tbcp FLAG
</title>
<itemizedlist>
<listitem><para><literal/tbcp/ FLAG <emphasis/Use TBCP protocol/</para></listitem>
</itemizedlist>

<para>The
<literal>tbcp</literal>
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.)</para>

<para>At the start of the PostScript job,
the sequence <literal>\001</literal> <emphasis remap=tt>M</emphasis> is sent.
Afterwards,  all control characters in the set
<literal>0x01, 0x03, 0x04, 0x05,
0x11, 0x13, 0x14, 0x1C,</literal>
are replaced by the two character sequence <literal>\001</literal>
<literal>X+'@'</literal> or
<literal>X+'\100'</literal> or
is sent.
For example:
<informalexample>
<screen>C\001\003   -&gt;  \001\115\103\001\101\001\103 or \001MC\001A\001C</screen>
</informalexample>
</para>

</sect2>
</sect1>

<sect1
id="syncpage">
<title>Synchronization and Pagecounts
</title>

<itemizedlist>
<listitem><para><literal/accounting=/ <emphasis/accounting program/</para></listitem>
<listitem><para><literal/accounting_info=/ <emphasis/accounting information/</para></listitem>
<listitem><para><literal/pagecount/ FLAG or Option <emphasis/pagecounter available /</para></listitem>
<listitem><para><literal/pagecount_interval=/ <emphasis/get pagecounter interval /</para></listitem>
<listitem><para><literal/pagecount_timeout=/ <emphasis/get pagecounter timeout /</para></listitem>
<listitem><para><literal/pagecount_start=/ <emphasis/get pagecounter at job start /</para></listitem>
<listitem><para><literal/pagecount_end=/ <emphasis/get pagecounter at job end /</para></listitem>
<listitem><para><literal/pagecount_ps_code=/ <emphasis/PostScript to get pagecounter /</para></listitem>
<listitem><para><literal/sync/ FLAG or Option <emphasis/sync required /</para></listitem>
<listitem><para><literal/sync_interval=/ <emphasis/do sync at interval /</para></listitem>
<listitem><para><literal/sync_timeout=/ <emphasis/sync timeout /</para></listitem>
<listitem><para><literal/wait_for_banner/ FLAG <emphasis/wait for banner page /</para></listitem>
</itemizedlist>

<para>Many printers are able to provide status information back to the
filter.
It is assumed that in these circumstances file descriptor 1
(FD1)
is
<emphasis>bidirectional</emphasis>
and status information can be read from it.
When the
<literal>status</literal>
option is TRUE,
FD1 is readable and is a device or communications socket,
then the filter assumes that it can read FD1.
</para>

<para>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.</para>

<para>The value of the
<literal>sync</literal> option determines if a PJL ECHO command or simple PostScript
program is used.
The PostScript program has the form:
<informalexample>
<screen>\004%!PS-Adobe-2.0
( %%[ echo: <acronym>TODSTR</acronym> ]%% ) print () = flush
\004</screen>
</informalexample>
where <acronym>TODSTR</acronym> is replaced with the current Time of Day.</para>

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

<para>
When the &IFHP; filter is operating in OF mode and the
<literal/wait_for_banner/ option is true,
the filter will wait until it determines that the banner page
has been completely printed before carrying out other filter functions.
</para>

<para>Pagecounts are used to do accounting and report the number of pages
used for a job.
Most printers 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
<informalexample>
<screen>@PJL INFO PAGECOUNT</screen>
</informalexample>
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
<literal>pagecount_ps_code=...</literal>
option specifies the PostScript program to use.
For example:
<informalexample>
<screen>pagecount_ps_code=
  /p {print} def ( %%[ pagecount: ) p
  statusdict begin pagecount end 20 string cvs p
  ( ]%% ) p () = flush</screen>
</informalexample>
</para>


<para>The <application/lpd/ print server and the &IFHP; filter must act
in coordination to do reliable pagecounting.
The following options are used by the &IFHP; filter to
assist with this:
<informaltable frame=all id=pagecountoptions>
<tgroup cols=2 colsep=1 rowsep=1 align=left >
<thead><row><entry>Option</entry><entry>Purpose</entry></row></thead>
<tbody>
<row><entry><literal/accounting=/.../</entry><entry> accounting program</entry></row>
<row><entry><literal/accounting_info=AnPR/</entry><entry> accounting information</entry></row>
<row><entry><literal/pagecount@/</entry><entry> do not get pagecounter value</entry></row>
<row><entry><literal/pagecount/</entry><entry> get pagecounter using either PJL or PostScript if available on the printer (default)</entry></row>
<row><entry><literal/pagecount=pjl/</entry><entry> get pagecounter using PJL</entry></row>
<row><entry><literal/pagecount=ps/</entry><entry> get pagecounter using PostScript</entry></row>
<row><entry><literal/pagecount_start/</entry><entry> get pagecounter at job start (default)</entry></row>
<row><entry><literal/pagecount_end/</entry><entry> get pagecounter at job end (default)</entry></row>
<row><entry><literal/pagecount_poll=N/</entry><entry> if nonzero, poll printer and conclude pagecounter value is nonzero when identical N times (default 1)</entry></row>
<row><entry><literal/pagecount_interval/</entry><entry> if polling more than once,  then leave this interval (in seconds) between polls.</entry></row>
<row><entry><literal/of_options=.../</entry><entry> Use these option values when running in OF Mode</entry></row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The following options are used in the &LPRng; printcap entry
to assist with getting the pagecounter values:
<informalexample>
<screen>lp:
  # run at job start
  :as=/.../accounting_at_start
  # run at job end
  :ae=/.../accounting_at_end
  # -a filter option value or last command line argument
  :af=/.../acct
  # default filter
  :filter=/.../ifhp
  # of filter - run before and after job, can be suspended
  # desperation flag for desperate situations
  #:suspend_of_filter@
  :of=/.../ifhp
  #options
  :ifhp=...,of_options=pagecount waitend</screen>
</informalexample>
</para>

<para>The <literal>:as</literal> program is run at the start of a print job,
and is used to determine if the user has sufficient resourses to print
a job.
The <literal>:ae</literal> program is run at the end of a print job and is used to
collect the accounting statistics.
The &IFHP; filter will write accounting information to the
accounting file specified by the command line <option>-a</option> option,
or the last command line argument.
When both the <literal>:of</literal> filter and normal filters are used
together,  the accounting information will be nested as shown.
<informalexample>
<screen>Normal Mode:
  start                     '-qProcessID' '-pPagecounter' \
     '-tStartTime' '-Pprinter' '-Hhost' '-nuser' '-Raccntinfo'
  end '-bPages' '-Telapsed' '-qProcessID' '-pPagecounter' 
     '-tEndTime' '-Pprinter' '-Hhost' '-nuser' '-Raccntinfo' \
     '-TElapsedTime'

OF Mode:
  filestart                     '-qProcessID' '-pPagecounter' \
     '-tStartTime' '-Pprinter' '-Hhost' '-nuser' '-Raccntinfo'
  fileend '-bPages' '-Telapsed' '-qProcessID' '-pPagecounter' \
     '-tEndTime' '-Pprinter' '-Hhost' '-nuser' '-Raccntinfo'
     

Sample Accounting File Entry:

  start '-q10699' '-p234' '-t2000-05-24-09:27:47.784' \
      -Plp -Hh4.private -npapowell
  filestart '-q10700' '-p234' '-t2000-05-24-09:27:47.784' \
      -Plp -Hh4.private -npapowell
  fileend '-b0' '-T1' '-q10700' '-p235' '-t2000-05-24-09:27:47.863' \
      -Plp -Hh4.private -npapowell
  end '-b1' '-T1' '-q10699' '-p235' '-t2000-05-24-09:27:47.863'
      -Plp -Hh4.private -npapowell</screen>
</informalexample>
</para>

<para>
The format of the information written to the accounting file is controlled
by the 
<literal>accounting_info=AHPn</literal> &IFHP; configuration value.
If they are present,
the specified &IFHP; command line flags are appended to the end of the standard
accounting information.
The <literal>accounting=...</literal>
option specfies a program to run at then end of the job.
This program has all of the accounting information passed as command line options.
The program should exit with a 0 exit code; otherwise the results are undefined.
</para>
<para>The printcap <symbol>:suspend_of_filter</symbol> controls how the <application/lpd/
spooler manages the <literal>of</literal> filter.
When a file is to be printed
normally, a special two character
suspend message (<literal>\031\001</literal>)
is written to the filter STDIN.
When the &IFHP; filter detects this string in the input
it is required to suspend itself by sending itself a <literal/SIGSUSP/
signal.
The <literal>:suspend_of_filter@</literal> flag causes the <application/lpd/ process to
close the <literal>:of</literal> filter rather than suspending it,
and to start a new <literal>:of</literal> filter process when it needs one.
This option is used when there can be at most one process communicating with the
printer,
or when the &IFHP; filter must totally reinitialize the printer at job end.
</para>

<para>The <literal>pagecount</literal>
option controls if and how the pagecounter value will be fetched.
Currently
<literal>pagecount=ps</literal> (PostScript)
and
<literal>pagecount=pjl</literal> (PJL)
are supported.
The <literal>pagecount</literal> form
will use PJL if it is available; otherwise PostScript if it is available.
The <literal>pagecount@</literal> suppresses pagecount operation.
The <symbol>pagecount_start</symbol> and <symbol>pagecount_end</symbol> flags control
if the pagecounter will be obtained at the start and end of the
print job.</para>

<para>One of the major problems with getting printcounter values is that the
print job must be totally finished or at least have all of its pages
run through the paper feed stream when the pagecounter value is reported.
Unfortunately,
most manufacturers do not provide accurate ways to coordinate the two
activities.
The <literal>waitend</literal> option is used to enable the &IFHP; filter to
send special command sequences to the printer which will detect
the true end of job,
but this may not be possible on many printers.</para>

<para>The <literal>printcounter_poll=N</literal> (default 1) option provides a method to deal with
these types of printers.
Commands to get the printcounter value are sent to the printer,
and repeated at <symbol>printcap_interval</symbol> second intervals
until the printcounter value has been stable for <literal>N</literal> readings.</para>

<para>The PJL TEOJ (True End Of Job) command has been used with only
limited success to force End of Job reporting only when the
job has finished.  This can be sent to the printer during PJL initialization
by specifying it as one of the PJL initialization strings:
<informalexample>
<screen>pjl_init=[ ... teoj ... ]
pjl_teoj=@PJL TEOJ=ON</screen>
</informalexample>
</para>


<para>The
<link linkend="ofoptions"/<symbol/of_options//
are used to modify the actions of the &IFHP;
filter when it is running in OF Mode.</para>
<para>The <symbol>pagecount_start</symbol> and <symbol>pagecount_end</symbol> (both default to TRUE or ON)
control if pagecounter values are obtained at the start or end
respectively of the job.</para>
<para>The pagecount request is sent to the printer every
<literal>pagecount_interval=nnn</literal>
second intervals; if nnn is 0, then it is sent only once.
If no pagecount value is obtained within
<literal>pagecount_timeout=nnn</literal>
seconds then the filter exits with an error.</para>
</sect1>

<sect1 id="pjlinit">
<title>PJL Initialization
</title>
<itemizedlist>
<listitem><para><literal/pjl_init=[ ... ]/<emphasis/ pjl initialization/</para></listitem>
<listitem><para><literal/startpage=/<emphasis/ start page to print/</para></listitem>
<listitem><para><literal/endpage=/<emphasis/ end page to print/</para></listitem>
<listitem><para><literal/pjl_only=[ ... ]/<emphasis/ pjl commands supported/</para></listitem>
<listitem><para><literal/pjl_except=[ ... ]/<emphasis/ pjl commands not to be used/</para></listitem>
<listitem><para><literal/pjl_vars_set=[ ... ]/<emphasis/ pjl variables supported/</para></listitem>
<listitem><para><literal/pjl_vars_except=[ ... ]/<emphasis/ pjl variables not to be used/</para></listitem>
<listitem><para><literal/pjl_user_opts=[ ... ]/<emphasis/ pjl options available to user/</para></listitem>
</itemizedlist>

<para>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:
<informalexample>
<screen>@PJL COMMAND OPTION OPTION ...</screen>
</informalexample>

A PJL variable is set using:
<informalexample>
<screen>@PJL SET <emphasis remap=it>var</emphasis> = <emphasis remap=it>value</emphasis> ...</screen>
</informalexample>

The
<literal>pjl_only=[ ... ]</literal>,
<literal>pjl_except=[ ... ]</literal>,
<literal>pjl_vars_set=[ ... ]</literal>,
and
<literal>pjl_vars_except=[ ... ]</literal>
options are used to control which PJL commands and which PJL variables
can be set.
The
<symbol>pjl_only</symbol>
variable lists the commands supported by the printer,
and the
<symbol>pjl_except</symbol>
lists commands <emphasis>not</emphasis>
supported by the printer.
Before sending a PJL command,
the
&IFHP;
filter checks to make sure that the command name is in
<symbol>pjl_only</symbol>
and not in
<symbol>pjl_except</symbol>.
If the tests fail, then tne command is not sent.</para>

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

<para>If PJL is enabled,
then the following actions are taken.
<orderedlist>

<listitem>
<para> PJL Universal Exit Language (UEL) <literal>\033%-12345X</literal> is sent to the printer.
</para>

<para>This is required to ensure that the following PJL commands are
accepted.</para>
</listitem>

<listitem>
<para> 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
<literal>-Zstartpage=nnn</literal>
or
<literal>-Zendpage=mmm</literal>
option is present, then the PJL JOB command has the form:
<informalexample>
<screen>@PJL JOB START=nnn END=mmm</screen>
</informalexample>
</para>
</listitem>

<listitem>
<para> The
<literal>pjl_init=[ ... ]</literal>
value option is expanded using the PJL
(<literal>"pjl_"</literal>) language context as described above.</para>
</listitem>

<listitem>
<para> The
<literal>-Toption=value</literal>s
and
<literal>-Zoption=value</literal>s
are scanned for matching option names in the
<literal>pjl_user_opts=[ ... ]</literal>
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:
<informalexample>
<screen>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</screen>
</informalexample>
</para>
</listitem>

</orderedlist>
</para>

</sect1>

<sect1
id="fileconversion">
<title>File Conversion Support
</title>
<itemizedlist>
<listitem><para><literal/forceconversion/ FLAG <emphasis/force use of file utility /</para></listitem>
<listitem><para><literal/default_language=/<emphasis/ default job language /</para></listitem>
</itemizedlist>




<para>The <command>lpr -l</command> or <command>lp -b</command> flags indicate that the spooled files
are not to be processed by an output filter.
The &LPRng; spooler recognizes this option and passes the <option>-c</option>
command line option to suppress any language specific processing for files.</para>

<para>However,
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,
and some printers require language specific setup in order to print
PCL, PostScript or text files correctly.</para>

<para>The &IFHP; filter has builtin tests for PJL,
PCL, and PostScript files.
These tests are almost identical to those used
by many printers which do
<emphasis>autodetection</emphasis>.
If you need to recognize a wider range of file types,
you can configure &IFHP; to use the
UNIX <literal>file</literal>(1) program.</para>

<para>Finally,
some printers have a very specialized job format that requires
conversion to by a
<literal>rasterizer</literal>
program.
This is handled as detailed in the following sections.</para>


<sect2
id="file-util-path">
<title>File Type Detection
</title>

<itemizedlist>
<listitem><para><literal/file_util_path=/<emphasis/ file utilty path /</para></listitem>
<listitem><para><literal/forceprocessing/ FLAG <emphasis/force file processing/</para></listitem>
</itemizedlist>
<para>The &IFHP; filter has a set of built-in tests
to determine if the input job file is
PJL, PostScript, and PCL, or (default) text,
and flags the file
with language types
<literal>pjl</literal>,
<literal>ps</literal>,
<literal>pcl</literal>,
and
<literal>text</literal> respectively.</para>

<para>You can also use the UNIX
<link linkend="fileutil"/file utility/
utility to determine type as well.
The <literal>file</literal> utility is invoked with it <acronym>STDIN</acronym> attached to the file
and &IFHP; uses the information it writes to <acronym>STDOUT</acronym>
as the raw file type.
The &IFHP; program will
convert the output to lowercase,
remove multiple whitespace characters,
and replace the remaining whitespace characters with underscores <symbol>_</symbol>.</para>

<para>By default,
&IFHP;
will not try to detect <emphasis>binary</emphasis> files,
i.e. - files printed with the binary or literal flag (<literal>-c</literal>
command line flag).
You can use the <literal>forceprocessing</literal> flag to cause
all files of all types to be processed.
&IFHP;
will first try to use its builtin tests and then will
use the <literal>file</literal> utility.
You can set the <symbol>forceconversion</symbol> flag to force &IFHP;
to only use the <literal>file</literal> utility.
The following shows the information in the <filename>ifhp.conf</filename>
file used to configure the file type detection.
<informalexample>
<screen>##forceprocessing - check all files for type - default 'no'
forceprocessing@
## default
default_language=text
## force only use of file program
## default is to let ifhp try first, then try file
forceconversion@
##  file utility path
file_util_path=/usr/bin/file -</screen>
</informalexample>
</para>

<para>The output of the file utility is converted to lower case and
used as the language type for further processing.</para>

</sect2>

<sect2
id="conversion">
<title>Conversion
</title>

<itemizedlist>
<listitem><para><literal/file_output_match=/ TABLE <emphasis/file utility output match list /</para></listitem>
<listitem><para><literal/language=/<emphasis/ language type override /</para></listitem>
</itemizedlist>

<para>Once the language type has been determined,
the &IFHP; filter then decides if a conversion program
needs to be run and will convert the input file to a required file type.
This activity is  controlled by the <symbol>file_output_match</symbol>
table.
<informalexample>
<screen>file_output_match = [
  *postscript*  ps  \%s{ps_converter}
  *pcl*         pcl  \%s{pcl_converter}
  *pjl*         pjl  \%s{pjl_converter}
  *printer*job*language* pjl
  *text*  pcl  \%s{pcl_converter}
  *gzip_compressed*  filter  \%s{gzip_decompresser}
  ]</screen>
</informalexample>

Each line of the
<symbol>file_output_match</symbol>
table contains
a (URL encoded) <emphasis remap=it>glob</emphasis> pattern,
the language type (<literal>ps</literal>, <emphasis remap=tt>pcl</emphasis>, etc.) produced by the conversion program,
and the (optional) conversion program.</para>

<para>The format:
<informalexample>
<screen>file_output_match = &lt;/pathname</screen>
</informalexample>
</para>

<para>will cause &IFHP; to open and read the specified file
for the <symbol>file_output_match</symbol> table.
The file's contents must have the same format as the
<symbol>file_output_match</symbol> table but without the <literal>[</literal> or <literal>]</literal> delimiters.</para>

<para>The <symbol>file_match_table</symbol> is scanned from first to last entry
for a <literal>glob</literal> pattern that
matches the file type determined by the &IFHP; program or the output of the
<symbol>file_util_path</symbol> program.
If no match is found,
then the language is set to the
<symbol>default_language</symbol> value.</para>

<para>The output language of the conversion program is set to the second entry.
The conversion program will be run with its STDIN set to the input file
and its STDOUT used as the converted output.
If there is no conversion program then the original file is used
and only the language type is modified.</para>

<para>The <literal>filter</literal> language type causes the specified conversion program to
be run and then the output of the program to be reprocessed.
As shown above,
this allows file decompression routines to be used to expand the
files.</para>

<para>The following are some short samples of what can be done with the
conversion facility.
<informalexample>
<screen>
# set up GhostScript
gs_device=epsonc
gs_options=-r1440
gs=/usr/bin/gs
gs_converter= [ \%s{gs} -dBATCH -q -sOutputFile=- \
  -sDEVICE=\%s{gs_device} \%s{gs_options} - ]
# use GhostScript for conversion
ps_converter = [ \%{gs_converter} ]
text_converter= [/usr/bin/a2ps -q -B -1 -M Letter \
  --borders=no -o- \%s{ps_converter} ]
gzip_decompresser = [ /usr/bin/gzip -c -d ]

[ ghostscript gs ]
file_output_match = [
  *postscript*  ps  \%s{ps_converter}
  *text*  pcl  \%s{pcl_converter}
  *gzip_compressed*  filter  \%s{gzip_decompresser}
  ]

Printcap entry:

pr:
  :ifhp=model=ghostscript,gs_device=laserjet,gs_options=-r300x300
</screen>
</informalexample>
</para>

<para>In this example,
we have shown a very interesting device - the GhostScript device.
We use the <literal>gs</literal> (GhostScript) program to do the conversion,
and specify the <symbol>gs_device</symbol> and <symbol>gs_options</symbol> values in the
printcap entry.
There are a few details that should be observed when using this facility.
<orderedlist>

<listitem>
<para>The output from the <literal>file</literal> program has spaces converted to underscores.
If you need to match spaces then use the underscore in the pattern.
For example, <literal>ascii text</literal> would be matched by <emphasis remap=tt>*ascii_text*</emphasis>.</para>
</listitem>

<listitem>
<para>If the conversion program contains a shell meta character such as
<literal>|</literal>,
<literal>;</literal>,
<literal>&gt;</literal>,
<literal>&lt;</literal>,
etc,
then it will be executed using
<literal>/bin/sh -c 'command'</literal>.
This allows a pipe of conversion commands to be constructed.
This is discussed in detail below.</para>
</listitem>

<listitem>
<para>The most commonly used conversion programs are
<link linkend="ghostscript"/GhostScript/,
used to convert PostScript to a format compatible with a non-PostScript
printer,
and the
<link linkend="a2ps">a2ps</link>,
<link linkend="enscript">enscript</link>, and
<link linkend="textps">textps</link>
Text to PostScript conversion programs which
convert text into PostScript for a non-text supporting printer.
The use of a <literal>wrapper</literal> program with these utilities is discussed below.</para>
</listitem>

<listitem>
<para>All of the command line options can be substituted on the command
line using <literal>\%{X}</literal>, where <emphasis remap=tt>X</emphasis> is the single letter command
line option flag.</para>
</listitem>

<listitem>
<para>The <literal>\%s{ARGV}</literal> value is replaced by the command line arguments.</para>
</listitem>

<listitem>
<para>The conversion program must exit with a 0 error code or an error is assumed
to have occurred.</para>
</listitem>

</orderedlist>
</para>

<para>The <literal>enscript</literal> program
will exit with a non-zero error codes even for successful conversions
and we need to use a
<literal>wrapper</literal> script that will run it and then return the correct
error code as shown below.
<informalexample>
<screen>#!/bin/sh
# /usr.../wrapper path [options]
# wrapper script for a2ps, enscript and others
#   path is the path to the program and options are the
#   options to pass.  The program is run and then the exit
#   code is corrected
"$@"
status=$?
case "$status" in
	1 ) exit $status ;;
esac
exit 0</screen>
</informalexample>
</para>

</sect2>

<sect2
id="crlf">
<title>LF to CR/LF Conversion
</title>
<itemizedlist>
<listitem><para><literal/crlf/ FLAG <emphasis/LF to CR-LF conversion/</para></listitem>
</itemizedlist>

<para>When processing <literal>text</literal> or <emphasis remap=tt>pcl</emphasis> files,
the <literal>crlf</literal> option will enable translation of
LF (<literal>\n</literal>) to CR/LF (<emphasis remap=tt>\r\n</emphasis>) sequences.
If you are using &IFHP; to simply do LF to CR/LF translation,
then you can use:
<informalexample>
<screen>ifhp -Tcrlf</screen>
</informalexample>
</para>

</sect2>

<sect2>
<title>Text Treated Like PCL</title>

<para>Text is simply PCL with no special formatting codes.
However, you will still need to send the PCL initialization
strings to the printer.
You can do this by using the following entry in the
<symbol>file_output_match</symbol> table:
<informalexample>
<screen>file_output_match = [
 *text*  pcl
 ]</screen>
</informalexample>
</para>

</sect2>

<sect2>
<title>Default to Passthrough</title>

<para>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 the following entry in the
<symbol>file_output_match</symbol> table:
<informalexample>
<screen>file_output_match = [
 *  raw
 ]</screen>
</informalexample>
</para>

</sect2>
</sect1>

<sect1
id="ghostscriptconfig">
<title>GhostScript Printer
</title>

<para>Generating a raster image from a PostScript or PCL file in
a timely manner requires a high speed processor and substantial amounts
of memory.
Many of the low cost printers require the user's system to do the raster
conversion,
and a raster file is then transferred to the printer.
These files are usually in a proprietary format.
The
<link linkend="ghostscript">GhostScript</link>
program can process PostScript files and produce raster output for a
wide range of devices.
See the GhostScript documentation for details.
Some printers have PCL support but do not support PostScript.
The
<literal>gs</literal> and <literal>pcl_gs</literal>
printer configuration support these printers.
<informalexample>
<screen>
# PRINTER ghostscript - Printer with GhostScript conversion to raster files
gs_converter= [ /usr/bin/gs -dSAFER -dBATCH -q 
   -sOutputFile=- -sDEVICE=\%s{gs_device} \%s{gs_options} -
 ]
text_converter= [ /usr/bin/a2ps -q -B -1 -M Letter --borders=no -o-
 ]

[ ghostscript gs ]
pcl@
pjl@
ps
text@
file_output_match = [
# PostScript to Raster
  *postscript*  raw  \%s{gs_converter}
# text to PostScript to Raster conversion
  *text*  filter  \%s{text_converter}
  ]

# PRINTER pcl_gs - PCL Printer with GhostScript conversion to raster files
[ pcl_gs ]
pcl
pjl@
ps
text@
file_output_match = [
# PostScript to Raster
  *postscript*  raw  \%s{gs_converter}
  *pcl*  pcl
# text to PostScript to Raster conversion
  *text*  filter  \%s{text_converter}
  ]</screen>
</informalexample>
</para>

<para>The <literal>\%s{gs_device}</literal> and <literal>\%s{gs_options}</literal> parameters can now be
specified in the printcap.
The following shows a typical printcap entry for use with this entry.
<informalexample>
<screen>#  force clients (lpr, lpq, to use server)
lp:lp=lp@serverhost 
# server information  
lp:server  
  :sd=<emphasis remap=it>spooldir</emphasis> 
  :lp=/dev/lpt0     
  :...  
  :ifhp=model=gs,gs_device=epson,gs_options=-r240x72 
  #path to ifhp filter  
  :filter=/.../ifhp  </screen>
</informalexample>
</para>

<para>The &IFHP; configuration entry uses GhostScript to do the
rasterization of the PostScript file,
and the <literal>a2ps</literal> program to do a text to PostScript conversion.</para>

</sect1>

<sect1
id="languageinit">
<title>Language Specific Initialization
</title>

<itemizedlist>
<listitem><para><literal/ps_init=/ <emphasis/PostScript initialization steps /</para></listitem>
<listitem><para><literal/pcl_init=/ <emphasis/PCL initialization steps /</para></listitem>
</itemizedlist>

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

<para>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.</para>

</sect1>

<sect1
id="filetransfer">
<title>File Transfer and Error Status Monitoring
</title>
<itemizedlist>
<listitem><para><literal/logall/ FLAG <emphasis/log all printer status/</para></listitem>
<listitem><para><literal/pjl_error_codes/ TABLE <emphasis/PJL error code translations/</para></listitem>
<listitem><para><literal/pjl_quiet_codes/ TABLE <emphasis/ignore these PJL error codes/</para></listitem>
<listitem><para><literal/pjl_alert_codes/ TABLE <emphasis/alert operation on these PJL error codes/</para></listitem>
<listitem><para><literal/pjl_alert_handler/ TABLE <emphasis/program to alert operator /</para></listitem>
</itemizedlist>

<para>If the printer can return status, i.e., the
<literal>status</literal> option is on,
the filter will read status information from the printer.</para>

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

<para>If the printer is returning PJL status information,
then this has a specific format:
<informalexample>
<screen>@PJL UINFO DEVICE
CODE=nnnn
DISPLAY="value"
...

@PJL UINFO JOB
START
...

@PJL UINFO JOB
END
...
</screen>
</informalexample>
</para>

<para>The
&IFHP; program will extract the
<acronym>CODE</acronym>
and job start and end flags,
and log these as appropriate.</para>

<para>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
<emphasis remap=bf>changed</emphasis>,
rather than when it has been reported.</para>

<para>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
<literal>logall</literal>
option is set.
The list of values is used as <emphasis remap=it>glob</emphasis> patterns.
For example:
<informalexample>
<screen>  pjl_quiet_codes=[ 10000 10001 10003 10023 10024 35078 41* ]</screen>
</informalexample>
</para>

<para>Also, there may be error codes which do not have a builtin error
message available.  New messages can be added using the
<symbol>pjl_error_codes</symbol>
option.
Its value is a list of lines, each line consisting of an error code
followed by the corresponding error message:
<informalexample>
<screen>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
  ]</screen>
</informalexample>
</para>

<para>Finally,
there are codes or classes of codes that require operator intervention.
These are specified using the <symbol>pjl_alert_codes</symbol>,
and the <symbol>pjl_alert_handler</symbol> program will be invoked to send them
to the appropriate destination.
The formated error message will be available on STDIN for the handler.
For example:
<informalexample>
<screen>pjl_alert_codes=[ 41* 42* 23* ]
pjl_alert_handler=/usr/local/libexec/filters/alert_handler</screen>
</informalexample>
</para>

</sect1>

<sect1
id="waitend">
<title>End of Job
</title>

<itemizedlist>
<listitem><para><literal/waitend/ OPTION <emphasis/wait for job completion status/</para></listitem>
<listitem><para><literal/waitend_interval=/<emphasis/ query for end at this interval/</para></listitem>
<listitem><para><literal/waitend_ctrl_t_interval=/<emphasis/ send CTRL-T at this interval/</para></listitem>
</itemizedlist>

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

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

<para>When the <literal>appsocket</literal> protocol is used,
suppressing <literal>waitend</literal> will cause no error messages from the printer to
be reported.</para>

<para>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
<literal>waitend=ps</literal>
and
The <literal>end_ctrl_t=word:word:...</literal>
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
<literal>printing</literal> or something other
than
<literal>idle</literal> or <emphasis remap=tt>busy</emphasis>
as long as paper is moving in the print engine.
When status is returned,
the words in the
<literal>end_ctrl_t=word:word:...</literal>
list value are examined for a match.
If the status word is present then the end of job condition is assumed.</para>

<para>The <symbol>waitend_interval</symbol>
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.</para>

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

</sect1>

<sect1
id="appsocket">
<title>Tektronix Phaser, QMS and AppSocket Support
</title>

<itemizedlist>
<listitem><para><literal/appsocket/ FLAG <emphasis/connect to printer and use AppSocket Protocol/</para></listitem>
</itemizedlist>
<para>The <literal>appsocket</literal> flag is used to specify that data transfer will
be done using the
<link linkend="appsocketpc">AppSocket</link>
protocol.
The &IFHP; filter will open a connection to the ip address and
port specified by the <literal>dev=host%port</literal> option
and carry out the various operations that it needs to do.</para>

<para>
Normally after sending information to the printer a <function/close()/
operation is done on the network connection.
This will usually be acceptible as the printer will print the job
that was sent to it.
However, some printers require that the network connection be left
open to report status.
</para>

<para>If page count information is needed,
the &IFHP; filter will then reopen the connection and get the page count information.</para>

</sect1>
</chapter>

<chapter>
<title>Banners and OF Mode Operation</title>

<para>One of the more difficult administrative issues is whether to print
banners (job separators) or to save the large amount of wasted
paper, time and effort.
The &LPRng; and
&IFHP;
combination provide a rather esoteric set of methods to generate banners,
at least one of which should be suitable for your application.</para>

<para>You should be aware that some printers have the obnoxious habit of
generating their own banner pages when jobs are transferred via
the RFC1179 protocol.
You should consult the manufacturers documentation and take the
necessary steps to turn printer banner page generation off.
It may turn out that this is impossible to do,
and in that case the only option is to use the Socket or Appsocket
connection methods.</para>

<para>In the original BSD print spooler,
the <literal>:of</literal> print filter was responsible for
banner generation.
The print server would send it a
<emphasis remap=it>magic string</emphasis> that the filter would recognize
as a <emphasis remap=it>print a banner</emphasis> request,
and it would then generate a banner.
After this,
another special <literal>magic cookie</literal> string,
the character sequence <literal>0x19,0x01</literal>,
was sent to cause the <literal>:of</literal> filter to suspend itself.
This allowed the print spooler to hold the connection to the printer
open while it started another filter to transfer a file.
Finally,
after all the jobs were sent, the <literal>:of</literal> filter was
sent a <acronym>SIGCONT</acronym> signal to wake up and perform whatever
closing operations were necessary.</para>

<para>This mixing of functionality causes horrible problems when
special setup strings must be sent to printers in order to
configure them for various operation.
In order to avoid these problems,
the banner printing and filter functions have been separated in
the &IFHP; filter.
If a banner is needed,
then &LPRng; will use a special banner generating program
to generate the banner.
The output of this program is then sent to the
<literal>:of</literal> filter, or directly to the printer if there is no
<literal>:of</literal> filter.</para>


<sect1>
<title>No Banner</title>

<para>Here is a typical printcap entry when banner printing
is not wanted:
<informalexample>
<screen>lp:
  :sh
  :filter=/.../ifhp</screen>
</informalexample>
</para>

<para>The <literal>:sh</literal> (suppress headers or banners) explicitly disables
banner printing,
and the <application/lpd/ server will not even attempt to print a banner.</para>

</sect1>

<sect1>
<title>Banner Printing and No OF Filter</title>

<para>This printcap entry specifies a banner generator program and
and banner generation.
There is no <literal>:of</literal> filter specified, so the banner is sent
directly to the printer.
In such a case the banner printing program should make sure that
it generates output with the appropriate set of initialization
strings.
The <literal>pclbanner</literal>,
<literal>psbanner</literal>,
and
<literal>lpbanner</literal>
programs produce PCL,
PostScript,
and text banners suitable for a wide range of printers.
The code for these banner generators is part of the &LPRng; distribution.
<informalexample>
<screen>lp:
  :bp=/.../pclbanner
  :of=/.../ifhp
  :filter=/.../ifhp
   # or
  :bp=/.../psbanner
  :of=/.../ifhp
  :filter=/.../ifhp
   # or
  :bp=/.../lpbanner
  :of=/.../ifhp
  :filter=/.../ifhp</screen>
</informalexample>
</para>

</sect1>

<sect1>
<title>Banner Printing With OF Filter</title>

<para>Finally,
we may want banner printing together with the <literal>:of</literal> filter.
This is usually the case when we need to perform special printer
setups or require the &IFHP; filter to do accounting.
In this case we need to make sure that the banner page is counted
as part of the job:
<informalexample>
<screen>lp:
  :bp=/.../pclbanner <emphasis/or/ :bp=/.../psbanner <emphasis/or/ :bp=/.../lpbanner
  :of=/.../ifhp
  :filter=/.../ifhp</screen>
</informalexample>
</para>

<para>When invoked as an <literal>:of</literal> filter, the <application/lpd/
server passes a <option>-Fo</option> option on the command line,
so that the &IFHP; filter knows what mode it is operating in.</para>

</sect1>

<sect1>
<title>&LPRng; Options Controlling Banner Printing</title>

<para>
The <command>lpr -h</command> (no header or banner) option
suppresses putting <emphasis/banner name/
(<literal/L/ line) into the control file.
The &LPRng; <symbol>:ab</symbol>
(always banner) overrides this,
and will print a banner using the user name information.
The <literal>:sh</literal> (suppress header) option will override everything
and prevent banners from being generated.
</para>
<para>
Banners are generated by the
<literal>:bp=/...</literal> (banner program)
program;
different banners at start and end can be generated by using the
<literal>:bs=/...</literal> (banner start)
and
<literal>:be=/...</literal> (banner end)
options,
which override the <literal>:bp=</literal> option.
</para>

</sect1>

<sect1 id="ofoptions">
<title>of_options option</title>

<para>This option,
usually used on the command line or in the
<literal>printcap</literal> file as part of the
<literal>:ifhp</literal> information,
specifies a set of options to use when the filter is running in
OF mode.
For example:
<informalexample>
<screen>lp:
  :ifhp=sync@,pagecount@,waitend@,of_options=sync pagecount waitend
  :filter=/usr/local/libexec/filtes/ifhp
  :of=/usr/local/libexec/filtes/ifhp

same as:

lp:
  :filter=/usr/local/libexec/filtes/ifhp -Tsync@,pagecount@,waitend@
  :of=/usr/local/libexec/filtes/ifhp -Tsync,pagecount,waitend</screen>
</informalexample>
</para>

<para>In this printcap entry,
the &IFHP; filter is invoked normally with the
<literal>sync@</literal>,
<literal>pagecount@</literal>
and
<literal>waitend@</literal> options.
This causes it to send jobs as fast as possible to the output device
and only monitor the device for error status.
The <literal>of=</literal> entry causes the <application/lpd/ print spooler to start &IFHP;
in OF mode,
and the <symbol>of_options</symbol> are used to override the other ones.</para>

</sect1>
</chapter>

<chapter>
<title>Font Download Support</title>

<para>For historical reasons,
there is support for downloading a font or other file to the
printer.
A large amount of the necessary operations are now in the
<filename>ifhp.conf</filename>
file.</para>

<para>The
<symbol>font_download</symbol>
built-in option supports downloading as described below.</para>


<sect1>
<title>PCL Font Downloading</title>

<para>The following shows the a typical
<filename>ifhp.conf</filename>
file which has PCL font downloading enabled.
<informalexample>
<screen>#
# Fonts and Font Downloading
#  fontid is used to set the current font
pcl_init=[ ... font ... ]

# combination command
pcl_font=[ delete_fonts font_id font_download font_primary ]

# font control
#
font_op=0
pcl_font_op=\033*c\%{font_op}F
pcl_delete_fonts=\033*c0F

font_id=1
pcl_font_id=\033*c\%{font_id}D

# set primary font
font_primary=1
pcl_font_primary=\033(\%{font_primary}X

# font directory
pcl_fontdir=/usr/local/lib/fonts

#default font file
font=c1201b.10
</screen>
</informalexample>
</para>

<para>To allow users to download a font and have it set up for PCL use,
the
<symbol>pcl_init</symbol>
option should include the
<literal>font</literal>
option in an appropriate position in the initialization sequence.
As shown above,
this will get expanded into the
<symbol>pcl_delete_fonts</symbol>,
<symbol>pcl_font_id</symbol>,
<symbol>pcl_font_download</symbol> (which is has built-in support),
and the
<symbol>pcl_font_primary</symbol>
options,
which are expanded in order.</para>

<para>The
<symbol>pcl_font_download</symbol> is supported by the builtin operation which will
find the
<symbol>pcl_fontdir</symbol>
directory value
and a value for the
<literal>font</literal>
variable,
using values from the
<option>-Z</option>
and
<option>-T</option>
and configuration information in that order.
If no
<literal>font</literal>
value is found,
no font will be downloaded.
For example:
<informalexample>
<screen>lpr -Tfont=font1,font2</screen>
</informalexample>
</para>

<para>When the
<symbol>pcl_font_download</symbol>
option is expanded,
it will generate the pathnames
<filename>/usr/local/lib/fonts/font1</filename>
and
<filename>/usr/local/lib/fonts/font2</filename>,
open these files,
and send their contents directly to the printer.</para>

</sect1>

<sect1>
<title>PS Font Downloading</title>

<para>PostScript font downloading is supported in a similar manner to
PCL font downloading.
<informalexample>
<screen>#
# Fonts and Font Downloading
#
ps_init=[ ... font ... ]

# combination command
ps_font=[ font_download ]

# font directory
ps_fontdir=/usr/local/lib/fonts

#default font file
font=font.ps.10</screen>
</informalexample>
</para>

<para>In a similar manner to the PCL font downloading,
when the
<symbol>ps_init</symbol>
list is expanded,
the
<symbol>ps_font</symbol>
entry will be expanded in turn.
If the <literal>-Zfont=ZapDingbat.ps</literal> is specified,
then the
<filename>/usr/local/lib/fonts/ZapDingbat.sp</filename>
file will be opened and downloaded to the printer.</para>

</sect1>

<sect1>
<title>PJL File Downloading</title>

<para>In a similar manner to the above font downloading,
you can specify a configuration or other setup file that should be
sent to the printer as part of the PJL setups.
The following configuration shows how to set this up.
<informalexample>
<screen>#
# PJL Initialization File Downloading
#  fontid is used to set the current font
pjl_init=[ ... setup  ... ]

setup=initval
font=\%s{setup}
# setup directory
pjl_fontdir=/usr/local/lib/fonts
pjl_setup=[ font_download ]</screen>
</informalexample>
</para>

<para>The above configuration will cause the value of the
<literal>setup</literal>
<option>-Z</option>,
<option>-T</option>
or configuration option to be used.</para>

</sect1>
</chapter>

<chapter>
<title>Debugging and Problem Solving</title>

<para>If you are reading this section,
then most likely you have had a problem using &IFHP; with &LPRng;.
Before going any further,
please read
<link linkend="rfc1179pc">RFC1179 (BSD or TCP/IP) Job Transfer Printcap Entry</link>,
and make sure that your printcap entry has the
<symbol>lpd_bounce</symbol> flag set.
This is the <emphasis remap=it>Most Frequently Asked Question</emphasis> and the
<emphasis remap=it>Most Frequently Provided Answer</emphasis> on the &LPRng; mailing list.</para>

<para>The following section outlines a method to debug problems with the
&IFHP; filter.
It will make use of some <literal>diagnostic</literal> options that are normally
not used in a printcap entry.
First,
let us start with a typical printcap entry and a problem.
<informalexample>
<screen>lw4:
  :lp=10.0.0.14%9100
  :sd=/var/spool/lpd/%P
  :ifhp=/usr/local/lib/filters/ifhp

Command:
  lpr -Plw4 -V /etc/motd

LPR output:

sending job 'papowell@h4+223' to lw4@localhost
connecting to 'localhost', attempt 1
connected to 'localhost'
requesting printer lw4@localhost
sending control file 'cfA223h4.private' to lw4@localhost
completed sending 'cfA223h4.private' to lw4@localhost
sending data file 'dfA223h4.private' to lw4@localhost
completed sending 'dfA223h4.private' to lw4@localhost
done job 'papowell@h4+223' transfer to lw4@localhost
Version LPRng-3.6.14</screen>
</informalexample>
</para>

<para>When trying to print to the print queue,
the user discovers that no output comes out of the printer.
The immediate suspicion is that the filter is not working.
You should make sure that the <literal>lpr</literal> command is actually sending
the job to the print queue.
You can then use <literal>lpq</literal> to discover what happened:
<informalexample>
<screen># lpq -llll
Printer: lw4@h4  'Hp : Laserwriter'
 Queue: no printable jobs in queue
 Status: subserver pid 27251 starting at 15:34:09.350
 Status: accounting at start at 15:34:09.357
 Status: opening device 'h14.private%9100' at 15:34:09.366
 Status: printing job 'root@h4+223' at 15:34:09.375
 Status: printing data file 'dfA223h4.private', size 3, IF filter 'ifhp' at 15:34:09.376
 Status: IF filter finished at 15:34:35.012
 Status: printing done 'root@h4+223' at 15:34:35.012
 Status: accounting at end at 15:34:35.014
 Status: finished 'root@h4+223', status 'JSUCC' at 15:34:35.014
 Status: subserver pid 27251 exit status 'JSUCC' at 15:34:35.018
 Status: lw4@h4.private: job 'root@h4+223' printed at 15:34:35.020
 Status: job 'root@h4+223' removed at 15:34:35.101
 Filter_status: accounting at start, pagecount 89696, pages 0 at 15:34:13.304
 Filter_status: sending job file at 15:34:13.306
 Filter_status: starting transfer at 15:34:13.306
 Filter_status: initial job type 'text' at 15:34:13.306
 Filter_status: job type 'pcl' at 15:34:13.306
 Filter_status: transferring 3 bytes at 15:34:13.308
 Filter_status: 100 percent done at 15:34:13.308
 Filter_status: finished writing file, cleaning up at 15:34:13.308
 Filter_status: sent job file at 15:34:13.308
 Filter_status: doing cleanup at 15:34:13.308
 Filter_status: getting end using 'pjl job/eoj' at 15:34:13.309
 Filter_status: end of job detected at 15:34:33.219
 Filter_status: getting pagecount using 'pjl info pagecount' at 15:34:33.219
 Filter_status: final pagecount 89697 at 15:34:35.009
 Filter_status: accounting at end, pagecount 89697, pages 1 at 15:34:35.010
 Filter_status: done at 15:34:35.010</screen>
</informalexample>
</para>

<para>As you can see from the <literal>lpq</literal> output,
the <literal>Status</literal> section shows the
<application/lpd/ activities
and the <symbol>Filter_status</symbol> section shows what &IFHP;
is doing.
This is the first line of defense - make sure that the information
and errors reported here are for the correct filter.</para>

<para>If this does not help,
then we will start with the basic filter tests and work our way
<emphasis remap=it>back</emphasis> to the print server.
First,  you will need a couple of test files.
If you have a PostScript printer,
find a simple PostScript file - the <filename>ellipse.ps</filename>
file is included in the &IFHP; distribution in the
<acronym>UTILS</acronym> directory.
You will also need a short text file - <filename>/etc/motd</filename>
is usually handy to use.</para>

<para>Create the <filename>/tmp/send</filename> file with the following contents:
<informalexample>
<screen>#!/bin/sh
cp /dev/null /tmp/t
/usr/local/libexec/filters/ifhp -Tdev=/tmp/t,trace,debug=1 &lt;/etc/motd 2&gt;/tmp/trace</screen>
</informalexample>
</para>

<para>This will create the <filename>/tmp/t</filename> file,
run the &IFHP; filter,
and put the trace and debugging information into the <filename>/tmp/trace</filename>
file.
Run this command using:
<informalexample>
<screen>#!/bin/sh
sh -x /tmp/send</screen>
</informalexample>
</para>

<para>Examine the output in <filename>/tmp/trace</filename>.
It will look like:
<informalexample>
<screen>ifhp 15:46:14.402 [27307] main: Debug '1'
ifhp 15:46:14.403 [27307] main: dump &lt;NULL&gt;
ifhp 15:46:14.403 [27307] main: Model_id '&lt;NULL&gt;'
ifhp 15:46:14.440 [27307] main: scanning Raw for default, then model '&lt;NULL&gt;'
ifhp 15:46:14.441 [27307] Select_model_info: id 'default', list-&gt;count 1940, model-&gt;count 0, init 0
ifhp 15:46:14.448 [27307] Dump_line_list: main: Model information - count 156, max 204, list 0x806e000
ifhp 15:46:14.448 [27307]   [ 0]='T=dev=/tmp/g,trace,debug=1'
ifhp 15:46:14.448 [27307]   [ 1]='banner@'
ifhp 15:46:14.448 [27307]   [ 2]='banner_file=/usr/local/libexec/filters/psbanner.ps'
ifhp 15:46:14.448 [27307]   [ 3]='converter='
ifhp 15:46:14.448 [27307]   [ 4]='debug=1'
ifhp 15:46:14.449 [27307]   [ 5]='default_language=text'
ifhp 15:46:14.449 [27307]   [ 6]='dev=/tmp/g'
ifhp 15:46:14.449 [27307]   [ 7]='duplex_select=1'</screen>
</informalexample>
</para>

<para>Most of the information with debug level 1 is simply showing the details of
options,
command execution, and error status.
This will,
however,
help with the majority of problems.</para>

<para>You can now modify the <filename>/tmp/send</filename> file to better reflect your
printer.
<informalexample>
<screen>#!/bin/sh
cp /dev/null /tmp/t
# substitute your ifhp options here
ifhp=model=hp4,status@
/usr/local/libexec/filters/ifhp -Tdev=/tmp/t,trace,debug=1,${ifhp} &lt;/etc/motd 2&gt;/tmp/trace</screen>
</informalexample>

Now run this again and examine the trace and output in <filename>/tmp/t</filename>.
If this looks correct,
we move on to the interactive tests.</para>

<para>If your printer is a network based printer and you are using RFC1179 transfers,
then you can use the following <literal>lpr</literal> command to
send the <filename>/tmp/t</filename> file
directly to the printer:
<informalexample>
<screen>  lpr -Ppr@host /tmp/t
Example:
  print queue 'raw'

  lpr -Praw@10.1.1.1 /tmp/t
</screen>
</informalexample>
</para>

<para> This form of the command causes <literal>lpr</literal> to send the job directly
to the printer.
If this works correctly then we know that there is no problem with &IFHP;
formatting the file,
and that the problem must be with the <application/lpd/ print spooler.</para>

<para>If your printer is network based and uses a socket connection,
then you can have &IFHP; connect to the printer by using the <literal>dev=host%port</literal>
connection option.
This is only used for testing or when you want to use the AppSocket protocol.
<informalexample>
<screen>#!/bin/sh
# substitute your ifhp options here
#  this should always work
#ifhp=model=hp4,status@
#  this does status checking, no pagecount
#ifhp=model=hp4,pagecount@
#  this does status checking and pagecount
#ifhp=model=hp4
/usr/local/libexec/filters/ifhp -Tdev=10.1.1.1%9100,trace,debug=1,${ifhp} &lt;/etc/motd 2&gt;/tmp/trace</screen>
</informalexample>
</para>

<para>If you have a windowing system, run this command from one window and
in another window use the <command>tail -f /tmp/trace</command> command to view status.
Most of the time you will discover that the system is failing to print
because either the
<literal>sync</literal>,
<literal>pagecount</literal>,
or
<literal>waitidle</literal>
step of the printing process is not completing correctly.
If there is insufficient detail for you to decide  the failure mechanism,
set <literal>debug=3</literal>, or even <literal>debug=4</literal> and explore what is happening.</para>

<para>If you have a parallel port connected printer on <filename>/dev/lptxx</filename>,
then you can simply use <command>cat /tmp/t &gt;/dev/lptxx</command> and see what happens.
If this works, then use:
<informalexample>
<screen>#!/bin/sh
# substitute your ifhp options here
ifhp=model=hp4,status@
/usr/local/libexec/filters/ifhp -Tdev=/dev/lptxxx,trace,debug=1,${ifhp} &lt;/etc/motd 2&gt;/tmp/trace</screen>
</informalexample>
</para>

<para>If you have a serial port printer,
then you can use a similar method for setting up a connection.
You will need to use the undocumented <literal>stty</literal> option to set the speed and
other parameters.
These are identical to those used by &LPRng;, so you should have no problems.
<informalexample>
<screen>#!/bin/sh
# substitute your ifhp options here
#  this should always work
#ifhp=model=hp4,status@
#  this does status checking, no pagecount
#ifhp=model=hp4,pagecount@
#  this does status checking and pagecount
#ifhp="model=hp4,stty= 9600 -parity crtscts raw"
stty="9600 -parity crtscts raw"
/usr/local/libexec/filters/ifhp -Tdev=/dev/tty00,trace,debug=1,${ifhp},stty=\"${stty}\" &lt;/etc/motd 2&gt;/tmp/trace</screen>
</informalexample>
</para>

<para>If all this does not help,
then subscribe to the &LPRng; mailing list and ask for help.</para>

</chapter>

<appendix id=ifhpoptions>
<title>Index to Options</title>

<para>

<table frame=all id=ifhpoptionstable>
<title><literal/ifhp.conf/ - &IFHP; Options</title>
<tgroup cols=2 colsep=1 rowsep=1 align=left >
<thead><row><entry>Option</entry><entry>Purpose</entry></row></thead>
<tbody>
<row><entry><link linkend="modelselection"/<literal/default//</entry> <entry>HP 4M Plus, PostScript, PJL, PCL, status, pagecount support </entry></row>
<row><entry><link linkend="appsocket"/<literal/appsocket FLAG//</entry> <entry>Use Tektronix AppSocket Protocol </entry></row>
<row><entry><link linkend="config"/<literal/config=PATHNAMES//</entry> <entry>Configuration file pathnames </entry></row>
<row><entry><link linkend="crlf"/<literal/crlf FLAG//</entry> <entry>Do LF to CRLF translation </entry></row>
<row><entry><link linkend="config"/<literal/debug FLAG//</entry> <entry>Debugging level </entry></row>
<row><entry><link linkend="conversion"/<literal/default_language=LANGUAGE//</entry> <entry>Default job file language (ps, pcl, raw, text, etc) </entry></row>
<row><entry><link linkend="pjlinit"/<literal/endpage=NNN//</entry> <entry>PJL JOB command END = NNN value </entry></row>
<row><entry><link linkend="fileconversion"/<literal/forceconversion FLAG//</entry> <entry>Force conversion using UNIX file(1) utility </entry></row>
<row><entry><link linkend="conversion"/<literal/file_output_match=LIST//</entry> <entry>File type and conversion matching </entry></row>
<row><entry><link linkend="file-util-path"/<literal/file_util_path=PATHNAME//</entry> <entry>Pathname of the UNIX file(1) utility </entry></row>
<row><entry><link linkend="conversion"/<literal/language=LANGUAGE//</entry> <entry>Specify job file language to be used (ps, pcl, raw, text, etc) </entry></row>
<row><entry><link linkend="filetransfer"/<literal/logall FLAG//</entry> <entry>Log all status reports from printer if set </entry></row>
<row><entry><link linkend="nullpad"/<literal/nullpad=COUNT//</entry> <entry>Send COUNT nulls to force full buffer condition </entry></row>
<row><entry><link linkend="options"/<literal/model=NAME//</entry> <entry>Specify model name for configuration selection </entry></row>
<row><entry><link linkend="options"/<literal/model_from_option=X//</entry> <entry>Specify model name using a command line option value </entry></row>
<row><entry><link linkend="syncpage"/<literal/pagecount=LANGUAGE//</entry> <entry>Get pagecount using pjl, ps or default </entry></row>
<row><entry><link linkend="syncpage"/<literal/pagecount_interval=SECONDS//</entry> <entry>Send pagecount command at SECONDS interval </entry></row>
<row><entry><link linkend="syncpage"/<literal/pagecount_ps_code=STRING//</entry> <entry>PostScript code to get pagecount information </entry></row>
<row><entry><link linkend="syncpage"/<literal/pagecount_timeout=SECONDS//</entry> <entry>Timeout getting pagecount after SECONDS </entry></row>
<row><entry><link linkend="languages"/<literal/pcl FLAG//</entry> <entry>Printer supports PCL if set </entry></row>
<row><entry><link linkend="pcl-eoj-at-start"/<literal/pcl_eoj_at_start FLAG//</entry> <entry>PCL EOJ (CTRL-D) at start of job </entry></row>
<row><entry><link linkend="languageinit"/<literal/pcl_init=LIST//</entry> <entry>PCL initializations to be done </entry></row>
<row><entry><link linkend="pcl-user-opts"/<literal/pcl_user_opts=LIST//</entry> <entry>User PCL options supported </entry></row>
<row><entry><link linkend="languages"/<literal/pjl FLAG//</entry> <entry>Printer supports PJL if set </entry></row>
<row><entry><link linkend="filetransfer"/<literal/pjl_alert_codes=LIST//</entry> <entry>alert operator on these PJL error codes </entry></row>
<row><entry><link linkend="filetransfer"/<literal/pjl_alert_handler=STRING//</entry> <entry>program to alert operator on PJL error </entry></row>
<row><entry><link linkend="pjl-console"/<literal/pjl_console FLAG//</entry> <entry>Printer supports messages on console </entry></row>
<row><entry><link linkend="filetransfer"/<literal/pjl_error_codes=LIST//</entry> <entry>PJL error messages for error codes </entry></row>
<row><entry><link linkend="pjlinit"/<literal/pjl_except=LIST//</entry> <entry>Do not allow these PJL commands </entry></row>
<row><entry><link linkend="pjlinit"/<literal/pjl_init=LIST//</entry> <entry>PJL initializations to be done </entry></row>
<row><entry><link linkend="pjl-job"/<literal/pjl_job FLAG//</entry> <entry>PJL JOB and EOJ supported </entry></row>
<row><entry><link linkend="pjlinit"/<literal/pjl_only=LIST//</entry> <entry>Allow only these PJL commands </entry></row>
<row><entry><link linkend="filetransfer"/<literal/pjl_quiet_codes=LIST//</entry> <entry>ignore these PJL error codes </entry></row>
<row><entry><link linkend="pjlinit"/<literal/pjl_user_opts=LIST//</entry> <entry>Allow only these user PJL commands or variables to be set </entry></row>
<row><entry><link linkend="pjlinit"/<literal/pjl_vars_except=LIST//</entry> <entry>Do not allow these PJL variables to be set </entry></row>
<row><entry><link linkend="pjlinit"/<literal/pjl_vars_set=LIST//</entry> <entry>Allow these PJL variables to be set </entry></row>
<row><entry><link linkend="languages"/<literal/ps FLAG//</entry> <entry>Printer supports PostScript (ps) </entry></row>
<row><entry><link linkend="ps-eoj-at-start"/<literal/ps_eoj_at_start FLAG//</entry> <entry>PostScript EOJ (CTRL-D) at start of job </entry></row>
<row><entry><link linkend="languageinit"/<literal/ps_init=LIST//</entry> <entry>PS initializations to be done </entry></row>
<row><entry><link linkend="ps-user-opts"/<literal/ps_user_opts=LIST//</entry> <entry>Support these PostScript user options </entry></row>
<row><entry><link linkend="remove-ctrl"/<literal/remove_ctrl=LIST//</entry> <entry>Remove these characters from PostScript jobs </entry></row>
<row><entry><link linkend="remove-pjl-at-start"/<literal/remove_pjl_at_start FLAG//</entry> <entry>Remove PJL commands from begining of job </entry></row>
<row><entry><link linkend="pjlinit"/<literal/startpage=NNN//</entry> <entry>PJL JOB command START = NNN value </entry></row>
<row><entry><link linkend="rwtimeout"/<literal/send_job_rw_timeout=NNN//</entry> <entry>Timeout for non-responding printer</entry></row>
<row><entry><link linkend="status"/<literal/status FLAG//</entry> <entry>Printer supplies status information </entry></row>
<row><entry><link linkend="statusfile"/<literal/statusfile=PATHNAME//</entry> <entry>Status file pathname </entry></row>
<row><entry><link linkend="statusfile"/<literal/statusfile_max=NNN//</entry> <entry>Status file has maximum size of NNN Kbytes </entry></row>
<row><entry><link linkend="statusfile"/<literal/statusfile_min=NNN//</entry> <entry>Status file has truncated size of NNN Kbytes </entry></row>
<row><entry><link linkend="statusfile"/<literal/summaryfile=PATHNAME//</entry> <entry>Summary file pathname </entry></row>
<row><entry><link linkend="syncpage"/<literal/sync FLAG//</entry> <entry>Synchronize printer if set </entry></row>
<row><entry><link linkend="syncpage"/<literal/sync_interval=SECONDS//</entry> <entry>Send synchronization request at SECONDS interval </entry></row>
<row><entry><link linkend="syncpage"/<literal/sync_timeout=SECONDS//</entry> <entry>Timeout synchronization request after SECONDS </entry></row>
<row><entry><link linkend="tbcp"/<literal/tbcp FLAG//</entry> <entry>Use Transparent Binary Communications Protocol for PostScript files </entry></row>
<row><entry><link linkend="languages"/<literal/text FLAG//</entry> <entry>Printer supports text mode </entry></row>
<row><entry><link linkend="config"/<literal/trace FLAG//</entry> <entry>Put error and trace messages on STDERR if set </entry></row>
<row><entry><link linkend="waitend"/<literal/waitend=METHOD//</entry> <entry>How to wait for printer to end printing </entry></row>
<row><entry><link linkend="waitend"/<literal/waitend_interval=SECONDS//</entry> <entry>How often to query printer for end of printing </entry></row>
<row><entry><link linkend="waitend"/<literal/waitend_ctrl_t_interval=SECONDS//</entry> <entry>How often to send CTRL-T for end of printing status </entry></row>

</tbody>
</tgroup>
</table>

</para>

</appendix>


<appendix>
<title>HP JetDirect Card Support</title>

<para>The  HPJetDirect  card or external
JetDirect box can  be configured through the printer front
panel  or through a set of network files.  Here is a summary
of  the  methods  used  from  UNIX  systems, or when you are
desperate, to configure the printer.</para>


<sect1>
<title>MicroSoft JetDirect Support</title>
<para>
There is limited support from HP for non-MicroSoft configuration tools.
However,
the tools that are provided are simple and easy to use,
especially for the initial configuration.
</para>
</sect1>

<sect1>
<title>TCP/IP Address</title>
<para>You can set the TCP/IP address from the front panel.
Reset  the printer and then use the MENU, +-, SELECT keys as follows:
<informalexample>
<screen> MENU  -&gt; MIO MENU (use MENU to display MIO MENU)
 ITEM  -&gt; CFG NETWORK=NO*
 +     -&gt; CFG NETWORK=YES
 ENTER -&gt; CFG NETWORK=YES*
 ITEM  -&gt; TCP/IP=OFF* (use ITEM to display TCP/IP)
 +     -&gt; TCP/IP=ON
 ENTER -&gt; TCP/IP=ON*
 ITEM  -&gt; CFG TCP/IP=NO* (use ITEM to display TCP/IP)
 +     -&gt; CFG TCP/IP=YES
 ENTER -&gt; CFG TCP/IP=YES*
 ITEM  -&gt; BOOTP=NO*
	 (Enable BOOTP if you want to - see below)
 ITEM  -&gt; IP BYTE 1=0*
	 This is IP address MSB byte.
	 Use +- keys to change value, and then ENTER to change
	 Use ITEM keys to get IP BYTE=2,3,4
 ITEM  -&gt; SM BYTE 1=255*
	  This is the subnet mask value
	 Use +- keys to change value, and then ENTER to change
	 Use ITEM keys to get IP BYTE=2,3,4
 ITEM  -&gt; LG BYTE 1=255*
	 This is the Syslog server (LoGger) IP address
	 Use +- keys to change value, and then ENTER to change
	 Use ITEM keys to get IP BYTE=2,3,4
 ITEM  -&gt; GW BYTE 1=255*
	 This is the subnet gateway (router) IP address
	 Use +- keys to change value, and then ENTER to change
	 Use ITEM keys to get IP BYTE=2,3,4
 ITEM  -&gt; TIMEOUT=90
	  This is the connection timeout value.  It puts a limit
	 on time between connections.  A value of 10 is reasonable.</screen>
</informalexample>
</para>

</sect1>
<sect1>
<title>Web Server Configuration</title>
<para>
Many of the newer releases of HP JetDirect firmware have a Web Server
configuration capability.
Unfortunately,
the web pages assume that you have JavaScript support for the browser,
and not all of the facilities used are supported by all browsers.
However the configuration information and pages presented are extremely simple
to use and understand.
</para>
<para>
The major problem with the Web Server configuration is that not all of the
options can be set through the Web Server pages.
</para>
</sect1>

<sect1>
<title>Telnet Configuration</title>
<para>
Once you have assigned an IP address to the JetDirect Box you can telnet to
the box and configure it through a simple command line interface.
When you first connect to the box,
hit <literal/RETURN/ a couple of times,
followed by <literal/?/ (Question Mark) <literal/RETURN/
and you should get a simple help menu.
This help information usually scrolls off a small (25 line) screen so a
buffer that allows you to see all of the information is advisable.
</para>
<para>
The major problem with the telnet configuration is that not all of the
options can be set through the command line facilties.
</para>
</sect1>

<sect1>
<title>BOOTP Information</title>

<para>If  you have a bootp server, you can put this information
in  the  bootptab  file.   To  use this, you must enable the
bootp  option  on  the printer.  The T144 option specifies a
file to be read from the bootp server.  This file is read by
using  the  TFTP  protocol, and you must have a TFTPD server
enabled.  Here is a sample bootptab entry.
<informalexample>
<screen># Example /etc/bootptab: database for bootp server (/etc/bootpd).
# Blank lines and lines beginning with '#' are ignored.
#
# Legend:
#
#       first field -- hostname
#                       (may be full domain name)
#
#       hd -- home directory
#       bf -- bootfile
#       cs -- cookie servers
#       ds -- domain name servers
#       gw -- gateways
#       ha -- hardware address
#       ht -- hardware type
#       im -- impress servers
#       ip -- host IP address
#       lg -- log servers
#       lp -- LPR servers
#       ns -- IEN-116 name servers
#       rl -- resource location protocol servers
#       sm -- subnet mask
#       tc -- template host (points to similar host entry)
#       to -- time offset (seconds)
#       ts -- time servers
#
# Be careful about including backslashes where they're needed.  Weird (bad)
# things can happen when a backslash is omitted where one is intended.
#
peripheral1:
:hn:ht=ether:vm=rfc1048:
:ha=08000903212F:
:ip=190.40.101.22:
:sm=255.255.255.0:
:gw=190.40.101.1:
:lg=190.40.101.3:
:T144="hpnp/peripheral1.cfg":</screen>
</informalexample>
</para>

<para>If  you  are  using the T144 option, you will need to create
the  configuration file.  The sample configuration file from
the HP Direct distribution is included below.
<informalexample>
<screen>#
# Example HP Network Peripheral Interface configuration file
#
# Comments begin with '#' and end at the end of the line.
# Blank lines are ignored.  Entries cannot span lines.

# Name is the peripheral (or node) name.  It is displayed on the peripheral's
# self-test page or configuration plot, and when sysName is obtained through
# SNMP.  This name can be provided in the BOOTP response or can be specified
# in the NPI configuration file to prevent the BOOTP response from overflowing
# the packet.  The domain portion of the name is not necessary because the
# peripheral does not perform Domain Name System (DNS) searches.  Name is
# limited to 64 characters.

name: picasso

# Location describes the physical location of the peripheral.  This is the
# value used by the interface for the MIB-II sysLocation object.  The default
# location is undefined.  Only printable ASCII characters are allowed.
# Maximum length is 64 characters.

location: 1st floor, south wall

# Contact is the name of the person who administers or services the peripheral
# and may include how to contact this person.  It is limited to 64 characters.
# This is the value used by the interface for the MIB-II sysContact object.
# The default contact is undefined.  Only printable ASCII characters are
# allowed.  Maximum length is 64 characters.

contact: Phil, ext 1234

# The host access list contains the list of hosts or networks of hosts
# that are allowed to connect to the peripheral.  The format is
# "allow: netnum [mask]", where netnum is a network number or a host IP
# address.  Mask is an address mask of bits to apply to the network number
# and connecting host's IP address to verify access to the peripheral.
# The mask usually matches the network or subnet mask, but this is not
# required.  If netnum is a host IP address, the mask 255.255.255.255 can
# be omitted.  Up to ten access list entries are permitted.

# to allow all of network 10 to access the peripheral:
allow: 10.0.0.0  255.0.0.0

# to allow a single host without specifying the mask:
allow: 15.1.2.3

# Idle timeout is the time (in seconds) after which an idle
# print data connection is closed.  A value of zero disables
# the timeout mechanism.  The default timeout is 90 seconds.

idle-timeout: 120

# A community name is a password that allows SNMP access to MIB values on
# the network peripheral.  Community names are not highly secure; they are
# not encrypted across the network.  The get community name determines which
# SNMP GetRequests are responded to.  By default, the network peripheral
# responds to all GetRequests.  The get community name is limited to 32
# characters.
#
# For hpnpstat and hpnpadmin, the community name can be stored in
# /usr/lib/hpnp/hpnpsnmp.

get-community-name: blue

# The set community name is similar to the get community name.  The set
# community name determines which SNMP SetRequests are responded to.  In
# addition, SetRequests are only honored if the sending host is on the
# host access list.  By default, the network peripheral does not respond
# to any SetRequests.  The set community name is limited to 32 characters.
#
# The set community name can come from /usr/lib/hpnp/hpnpsnmp
# if it is the same as the get community name.  We recommend that the
# set community name be different from the get community name though.

set-community-name: yellow

# SNMP traps are asynchronous notifications of some event that has occurred.
# SNMP traps are useful only with network management software.  Traps are
# sent to specific hosts and include a trap community name.  Up to four
# hosts can be sent SNMP traps.   The trap community name is limited to
# 32 characters.  The default name is public.

trap-community-name: red

# The SNMP trap destination list specifies systems to which SNMP
# traps are sent.  Up to four IP addresses are allowed.  If no
# trap destinations are listed, traps are not sent.

trap-dest: 15.1.2.3
trap-dest: 15.2.3.4

# The SNMP authentication trap parameter enables or disables the sending
# of SNMP authentication traps.  Authentication traps indicate that an SNMP
# request was received and the community name check failed.  By default,
# the parameter is off.

authentication-trap: on

# The syslog-facility parameter sets the source facility identifier that the
# card uses when issuing syslog messages.  Other facilities, for example,
# include the kernel (LOG_KERN), the mail system (LOG_MAIL), and the spooling
# system (LOG_LPR).  The card only allows its syslog facility to be configured
# to one of the local user values (LOG_LOCAL0 through LOG_LOCAL7).  The
# selectable option strings, local0 through local7 (configured to LOG_LOCAL0
# through LOG_LOCAL7, respectively) are case insensitive.  The default
# syslog-facility for the card is LOG_LPR.

syslog-facility: local2

# This parameter allows the card to treat hosts on other subnets as if the
# hosts were on the card's subnet.  This parameter determines the TCP
# Maximum Segment Size (MSS) advertised by the card to hosts on other subnets
# and affects the card's initial receive-window size.  The card will use a
# TCP MSS of 1460 bytes for local hosts, and 536 bytes for a non-local host.
# The default is off, that is, the card will use the maximum packet sizes
# only on the card's configured subnet.
#
# The configuration utility does not allow access to this parameter.  If you
# want to configure it, you must manually edit the NPI configuration file
# and add it to the bottom of the entry for the network peripheral.

subnets-local: on

# This parameter affects how the card handles TCP connection requests from
# the host.  By default, the JetDirect MPS card will accept a TCP connection
# even if the peripheral is off-line.  If this parameter is set to "on", then
# the card will only accept a TCP connection when the peripheral is on-line.

old-idle-mode: off
</screen>
</informalexample>
</para>

</sect1>

<sect1>
<title>Timeouts</title>

<para>You should be aware that the
<literal>idle-timeout</literal>
value in the configuration file will override the value
entered on the control panel of the printer.</para>

<para>Also,
the
<literal>@PJL SET TIMEOUT = NNN</literal>
command will override this value as well.</para>

</sect1>
</appendix>
</book>
