• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/LPRng/DOCS/LPRng-Reference-Multipart/
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
3<html>
4  <head>
5    <meta name="generator" content="HTML Tidy, see www.w3.org">
6    <title>Job File Format Conversion with Filters</title>
7    <meta name="GENERATOR" content=
8    "Modular DocBook HTML Stylesheet Version 1.7">
9    <link rel="HOME" title=" LPRng Reference Manual" href=
10    "index.htm">
11    <link rel="UP" title="Print Spooling Tutorial " href=
12    "tutorial.htm">
13    <link rel="PREVIOUS" title="Print Job Filters" href=
14    "printjobfilters.htm">
15    <link rel="NEXT" title="Printcap Basics" href="x3103.htm">
16  </head>
17
18  <body class="SECT1" bgcolor="#FFFFFF" text="#000000" link=
19  "#0000FF" vlink="#840084" alink="#0000FF">
20    <div class="NAVHEADER">
21      <table summary="Header navigation table" width="100%" border=
22      "0" cellpadding="0" cellspacing="0">
23        <tr>
24          <th colspan="3" align="center">LPRng Reference Manual: 5
25          Sep 2003 (For LPRng-3.8.22)</th>
26        </tr>
27
28        <tr>
29          <td width="10%" align="left" valign="bottom"><a href=
30          "printjobfilters.htm" accesskey="P">Prev</a></td>
31
32          <td width="80%" align="center" valign="bottom">Chapter 4.
33          Print Spooling Tutorial</td>
34
35          <td width="10%" align="right" valign="bottom"><a href=
36          "x3103.htm" accesskey="N">Next</a></td>
37        </tr>
38      </table>
39      <hr align="LEFT" width="100%">
40    </div>
41
42    <div class="SECT1">
43      <h1 class="SECT1"><a name="JOBFILEFORMATCONVERSION">4.10. Job
44      File Format Conversion with Filters</a></h1>
45
46      <p>One of the major problems that face new users to UNIX
47      printing is when they have a printer that has a proprietary
48      print job format such as the HP DeskJet series of printers.
49      The solution to this problem is quite simple: generate your
50      output in PostScript, and then use the <a href=
51      "installation.htm#GHOSTSCRIPT">GhostScript</a> program to
52      convert the GhostScript output to a format compatible with
53      your printer.</p>
54
55      <div class="INFORMALEXAMPLE">
56        <a name="AEN2761"></a>
57<pre class="SCREEN">
58    lp:filter=/usr/local/lib/filters/myfilter:...
59    
60    /tmp/myfilter:
61    
62    #!/bin/sh
63    /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
64        -sOutputFile=- - &amp;&amp; exit 0
65    exit 2
66</pre>
67      </div>
68      <br>
69      <br>
70
71      <p>This simple <span class="emphasis"><i class=
72      "EMPHASIS">tutorial</i></span> example suffers from some
73      serious problems. If you accidentally send a non-PostScript
74      file to the printer GhostScript will detect this and exit
75      with an error message but only after trying to interpret the
76      input file as PostScript. If the input file was a text file,
77      this can result in literally thousands of error messages and
78      hundreds of pages of useless output.</p>
79
80      <p>In order to make a more robust filter we need to meet the
81      following minimum requirements:</p>
82
83      <ol type="1">
84        <li>
85          <p>The file type should be determined, and only files
86          that are PostScript should be passed to GhostScript.</p>
87        </li>
88
89        <li>
90          <p>We may have some conversion routines that can convert
91          files into PostScript files and then we can send them to
92          GhostScript for raster conversion.</p>
93        </li>
94
95        <li>
96          <p>If we cannot convert a file, then we should simply
97          terminate the printing and cause the spooler to remove
98          the job.</p>
99        </li>
100      </ol>
101      <br>
102      <br>
103
104      <p>The <b class="APPLICATION">ifhp</b> Print Filter program
105      is a companion to the <b class="APPLICATION">LPRng</b>
106      software and does this type of operation. If you are using
107      Linux, then you may find the <span class="emphasis"><i class=
108      "EMPHASIS">RedHat Print Filters</i></span> (<a href=
109      "http://www.debian.org" target=
110      "_top">http://www.debian.org</a>) installed and in use on
111      your system. The <span class="emphasis"><i class=
112      "EMPHASIS">magicfilter</i></span> developed by H. Peter Anvin
113      <a href="http://www.debian.org" target=
114      "_top">http://www.debian.org</a> is distributed with Debian
115      Linux. The <b class="APPLICATION">apsfilter</b> by Andreas
116      Klemm <a href="http://www.freebsd.org/~andreas/index.html"
117      target="_top">http://www.freebsd.org/~andreas/index.html</a>
118      is also widely used, although now most of its functionality
119      is directly available in <b class="APPLICATION">LPRng</b>.
120      Finally, the <b class="APPLICATION">a2ps</b> (Ascii to
121      PostScript) converter by <a href="demaille@inf.enst.fr"
122      target="_top">Akim Demaille</a> and <a href="santana@st.com"
123      target="_top">Miguel Santana</a> is available from <a href=
124      "www-inf.enst.fr/~demaille/a2ps" target=
125      "_top">www-inf.enst.fr/~demaille/a2ps</a>. This package
126      provides a very nice set of facilities for massaging,
127      mangling, bending, twisting, and being downright nasty with
128      text or other files.</p>
129
130      <div class="SECT2">
131        <h2 class="SECT2"><a name="AEN2787">4.10.1. Simple Filter
132        with File Format Detection</a></h2>
133
134        <p>Since this is a tutorial, we will demonstrate a simple
135        way to make your own <span class="emphasis"><i class=
136        "EMPHASIS">multi-format</i></span> print filter, and
137        provide insight into how more complex filters work.</p>
138
139        <p>The <a href="installation.htm#FILEPROG">file</a> utility
140        developed by Ian F. Darwin uses a database of file
141        signatures to determine what the contents of a file are.
142        For example:</p>
143
144        <div class="INFORMALEXAMPLE">
145          <a name="AEN2793"></a>
146<pre class="SCREEN">
147    <samp class="PROMPT">h4: {191} %</samp> <kbd class=
148"USERINPUT">cd /tmp</kbd>
149    <samp class="PROMPT">h4: {192} %</samp> <kbd class=
150"USERINPUT">echo hi &gt;hi</kbd>
151    <samp class="PROMPT">h4: {193} %</samp> <kbd class=
152"USERINPUT">gzip -c hi &gt;hi.gz</kbd>
153    <samp class="PROMPT">h4: {194} %</samp> <kbd class=
154"USERINPUT">echo "%!PS-Adobe-3.0" &gt;test.ps</kbd>
155    <samp class="PROMPT">h4: {195} %</samp> <kbd class=
156"USERINPUT">gzip -c test.ps &gt;test.ps.gz</kbd>
157    <samp class="PROMPT">h4: {196} %</samp> <kbd class=
158"USERINPUT">file hi hi.gz test.ps test.ps.gz</kbd>
159    hi:        ASCII text
160    hi.gz:     gzip compressed data, deflated
161    test.ps:   PostScript document text conforming at level 3.0
162    test.ps.gz: gzip compressed data, deflated
163    <samp class="PROMPT">h4: {197} %</samp> <kbd class=
164"USERINPUT">file - &lt;test.ps</kbd>
165    standard input: PostScript document text conforming at level 3.0
166</pre>
167        </div>
168        <br>
169        <br>
170
171        <p>If we are given a file, we can now use <b class=
172        "APPLICATION">file</b> to recognize the file type and if
173        the file type is suitable for our printer we can send it to
174        the printer, otherwise we can reject it. The following is a
175        simple yet very powerful shell script that does this.</p>
176
177        <div class="INFORMALEXAMPLE">
178          <a name="AEN2811"></a>
179<pre class="SCREEN">
180    #!/bin/sh
181    # set up converters
182    gs="/usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
183        -sOutputFile=/dev/fd/3 - 3&gt;&amp;1 1&gt;&amp;2"
184    a2ps="/usr/local/bin/a2ps -q -B -1 -M Letter --borders=no -o-"
185    decompress=""
186    # get the file type
187    type=`file - | tr A-Z a-z | sed -e 's/  */_/g'`;
188    echo TYPE $type &gt;&amp;2
189    case "$type" in
190      *gzip_compressed* ) decompress="gunzip -c |" compressed="compressed" ;;
191    esac
192    
193    # we need to rewind the file
194    perl -e "seek STDIN, 0, 0;"
195    
196    if test "X$decompress" != "X" ; then
197        type=`$decompress head | file - | tr A-Z a-z | sed -e 's/  */_/g'`;
198        echo COMPRESSED TYPE $type &gt;&amp;2
199        # we need to rewind the file
200        perl -e "seek STDIN, 0, 0;"
201    fi
202    case "$type" in
203      *postscript* ) process="$gs" ;;
204      *text* )       process="$a2ps | $gs" ;;
205      * )
206        echo "Cannot print type $compressed '$type'" &gt;&amp;2
207        # exit with JREMOVE status
208        exit 3
209        ;;
210    esac
211    # in real life, replace 'echo' with 'exec'
212    echo "$decompress $process"
213    # exit with JABORT if this fails
214    exit 2
215</pre>
216        </div>
217        <br>
218        <br>
219
220        <p>Copy this to the <tt class="FILENAME">/tmp/majik</tt>
221        file, and give it <var class="LITERAL">0755</var>
222        (executable) permissions. Here is an example of the output
223        of the script:</p>
224
225        <div class="INFORMALEXAMPLE">
226          <a name="AEN2816"></a>
227<pre class="SCREEN">
228    <samp class="PROMPT">h4: {198} %</samp> <kbd class=
229"USERINPUT">/tmp/majik &lt;test.ps.gz</kbd>
230    TYPE standard_input:_gzip_compressed_data,_deflated...
231    COMPRESSED TYPE standard_input:_postscript_document_level_3.0
232    gunzip -c | /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
233       -sOutputFile=/dev/fd/3 - 3&gt;&amp;1 1&gt;&amp;2
234    <samp class="PROMPT">h4: {199} %</samp> <kbd class=
235"USERINPUT">/tmp/majik &lt;/tmp/hi</kbd>
236    TYPE standard_input:_ascii_text
237     /usr/local/bin/a2ps -q -B -1 -M Letter --borders=no -o- \
238      | /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
239       -sOutputFile=/dev/fd/3 - 3&gt;&amp;1 1&gt;&amp;2
240</pre>
241        </div>
242        <br>
243        <br>
244
245        <p>The first part of the script sets up a standard set of
246        commands that we will use in the various conversions. A
247        full blown package for conversion would use a database or
248        setup file to get these values. We then use the <b class=
249        "APPLICATION">file</b> utility to determine the input file
250        type. The output of the <b class="APPLICATION">file</b>
251        utility is translated to lower case and multiple blanks and
252        tabs are removed.</p>
253
254        <p>We use a simple shell <var class="LITERAL">case</var>
255        statement to determine if we have a compressed file and get
256        a decompression program to use. We reapply the <b class=
257        "APPLICATION">file</b> utility to the decompressed file (if
258        it was compressed) and get the file type.</p>
259
260        <p>Finally we use another <var class="LITERAL">case</var>
261        statement to get the output converter and then we run the
262        command. For tutorial purposes, we use an <tt class=
263        "COMMAND">echo</tt> rather than an <tt class=
264        "COMMAND">exec</tt> so we can see the actual command,
265        rather than the output.</p>
266
267        <p>Just for completeness, here is <b class=
268        "APPLICATION">majikperl</b>:</p>
269
270        <div class="INFORMALEXAMPLE">
271          <a name="AEN2834"></a>
272<pre class="SCREEN">
273    #!/usr/bin/perl
274    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
275        if $running_under_some_shell;
276                # this emulates #! processing on NIH machines.
277                # (remove #! line above if indigestible)
278    my($gs) = "/usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
279        -sOutputFile=/dev/fd/3 - 3&gt;&amp;1 1&gt;&amp;2";
280    my($a2ps)="/usr/local/bin/a2ps -q -B -1 -M Letter --borders=no -o-";
281    
282    my($decompress,$compressed,$process,$type);
283    $decompress=$compressed=$process=$type="";
284    
285    # get the file type
286    $type = ` file - `;
287    $type =~ tr /A-Z/a-z/;
288    $type =~ s/\s+/_/g;
289    print STDERR "TYPE $type\n";
290    ($decompress,$compressed) = ("gunzip -c |", "gzipped")
291      if( $type =~ /gzip_compressed/ );
292    print STDERR "decompress $decompress\n";
293    unless( seek STDIN, 0, 0 ){
294        print "seek STDIN failed - $!\n"; exit 2; }
295    if( $decompress ne "" ){
296        $type = ` $decompress file - `;
297        $type =~ tr /A-Z/a-z/;
298        $type =~ s/\s+/_/g;
299        print STDERR "COMPRESSED TYPE $type\n";
300        unless( seek STDIN, 0, 0 ){
301            print "seek STDIN failed - $!\n"; exit 2; }
302    }
303    $_ = $type;
304    if( /postscript/ ){
305        $process="$gs";
306    } elsif( /_text_/ ){
307        $process="$a2ps | $gs" ;;
308    } else {
309        print STDERR "Cannot print $compressed '$type'" &gt;&amp;2;
310        # JREMOVE
311        exit 3;
312    }
313    exec "$decompress $process";
314    print "exec failed - $!\n";
315    exit 2;
316</pre>
317        </div>
318        <br>
319        <br>
320      </div>
321
322      <div class="SECT2">
323        <h2 class="SECT2"><a name="AEN2836">4.10.2. The <b class=
324        "APPLICATION">ifhp</b> Filter</a></h2>
325
326        <p>The <a href="secftp.htm">ifhp</a> Print Filter is the
327        companion print filter supplied with <b class=
328        "APPLICATION">LPRng</b> and is normally installed together
329        with the <b class="APPLICATION">LPRng</b> software. <b
330        class="APPLICATION">Ifhp</b> supports a wide range of
331        PostScript, PCL, text, and raster printers, and can be
332        configured to support almost any type of printer with a
333        stream based interface. It provides diagnostic and error
334        information as well as accounting information. It
335        recognizes a wide range of file types by using the <b
336        class="APPLICATION">file</b> utility and the pattern
337        matching technique demonstrated in the previous section,
338        and can do selective conversions from one format to
339        others.</p>
340
341        <p>The <a href="x291.htm#POSTSCRIPT">PostScript</a> and <a
342        href="x291.htm#PCL">PCL</a> printer job languages are
343        supported by most printer manufacturers. However, in order
344        to have a job printed correctly the following steps must be
345        taken.</p>
346
347        <ol type="1">
348          <li>
349            <p>The printer must be put into a known <span class=
350            "emphasis"><i class="EMPHASIS">initial</i></span> state
351            by sending it the appropriate reset strings or
352            performing a correct set of IO operations.</p>
353          </li>
354
355          <li>
356            <p>If accounting is being done, then the printer
357            accounting information must be obtained and recorded.
358            See <a href="accountingref.htm">Accounting</a> for more
359            information about <b class="APPLICATION">LPRng</b>
360            support for accounting.</p>
361          </li>
362
363          <li>
364            <p>The file to be printed must be checked to see if it
365            is compatible with the printer, and if not, a format
366            conversion program invoked to convert it to the
367            required format.</p>
368          </li>
369
370          <li>
371            <p>If the user selects a set of printer specific
372            options such as landscape mode, duplex printing,
373            multiple copies, or special paper, the appropriate
374            commands must be sent to the printer to select these
375            options.</p>
376          </li>
377
378          <li>
379            <p>The file must be transferred to the printer and the
380            printer is monitored for any error conditions.</p>
381          </li>
382
383          <li>
384            <p>Any required end of job commands are sent to the
385            printer, and the printer monitored for error conditions
386            while the job finishes printing.</p>
387          </li>
388
389          <li>
390            <p>If accounting is being done, the printer accounting
391            information such as page count and time used must be
392            obtained and recorded. See <a href=
393            "accountingref.htm">Accounting</a> for more information
394            about <b class="APPLICATION">LPRng</b> support for
395            accounting.</p>
396          </li>
397        </ol>
398        <br>
399        <br>
400
401        <p>The <b class="APPLICATION">ifhp</b> filter uses the <tt
402        class="FILENAME">ifhp.conf</tt> configuration file to
403        determine the actions and commands appropriate for various
404        models of printers. See the <b class="APPLICATION">ifhp</b>
405        documentation for details about the format and contents of
406        this file. This file contains entries for a large number of
407        PostScript, PJL, and other printers. The default printer
408        used by <b class="APPLICATION">ifhp</b> is the HP LaserJet
409        4M Plus which supports PostScript, PCL, and PJL. The
410        commands and formats used by this printer is compatible
411        with a large number of other HP printers.</p>
412
413        <p>We will demonstrate how to add the <b class=
414        "APPLICATION">ifhp</b> filter to your printcap entry. Find
415        the path to the <b class="APPLICATION">ifhp</b> filter
416        using the <b class="APPLICATION">find</b> command as we did
417        in the previous exercise. Modify the printcap as shown
418        below and use <tt class="COMMAND">lpc lpd</tt> to restart
419        <b class="APPLICATION">lpd</b>.</p>
420
421        <div class="INFORMALEXAMPLE">
422          <a name="AEN2879"></a>
423<pre class="SCREEN">
424    lp:sd=/var/spool/lpd/%P
425      :force_localhost
426      :lp=/tmp/lp
427      :ifhp=model=default
428      # modify the path to ifhp appropriately
429      :filter=/usr/local/libexec/filters/ifhp
430</pre>
431        </div>
432        <br>
433        <br>
434
435        <p>Now print the <tt class="FILENAME">/tmp/hi</tt> and then
436        display <tt class="FILENAME">/tmp/lp</tt> using a text
437        editor such as <b class="APPLICATION">vi</b> or <b class=
438        "APPLICATION">emacs</b> that shows control characters:</p>
439
440        <div class="INFORMALEXAMPLE">
441          <a name="AEN2886"></a>
442<pre class="SCREEN">
443    <samp class="PROMPT">h4: {200} %</samp> <kbd class=
444"USERINPUT">cp /dev/null /tmp/lp</kbd>
445    <samp class="PROMPT">h4: {201} %</samp> <kbd class=
446"USERINPUT">lpr /tmp/hi</kbd>
447    <samp class="PROMPT">h4: {202} %</samp> <kbd class=
448"USERINPUT">vi /tmp/lp</kbd>
449    ^[%-12345X@PJL
450    @PJL JOB NAME = "PID 405" DISPLAY = "papowell"
451    @PJL RDYMSG DISPLAY = "papowell"
452    @PJL USTATUSOFF
453    @PJL USTATUS JOB = ON
454    @PJL USTATUS DEVICE = ON
455    @PJL USTATUS PAGE = ON
456    @PJL USTATUS TIMED = 10
457    @PJL ENTER LANGUAGE = PCL
458    ^]E^]&amp;^]&amp;k2G^]&amp;s0C^]&amp;l0O^]9^](s0P^](s10.00H^](s4099Thi
459    ^]E^]%-12345X@PJL
460    @PJL RDYMSG DISPLAY = "papowell"
461    @PJL EOJ NAME = "PID 405"
462    @PJL USTATUSOFF
463    @PJL USTATUS JOB = ON
464    @PJL USTATUS DEVICE = ON
465    @PJL USTATUS PAGE = ON
466    @PJL USTATUS TIMED = 10
467    @PJL RDYMSG DISPLAY = ""
468    ^[%-12345X
469</pre>
470        </div>
471        <br>
472        <br>
473
474        <p>The output now contains all of the control sequences and
475        setup codes needed to print a text file on the default
476        printer. The <var class="LITERAL">:ifhp=model=default</var>
477        printcap entry is used by <b class="APPLICATION">ifhp</b>
478        to get the information it needs to perform its operation.
479        The following options are commonly provided in the <var
480        class="LITERAL">:ifhp=</var> option to configure the <b
481        class="APPLICATION">ifhp</b> filter.</p>
482
483        <div class="TABLE">
484          <a name="IFHPOPTS"></a>
485
486          <p><b>Table 4-3. :ifhp= Options</b></p>
487
488          <table border="1" frame="border" rules="all" class=
489          "CALSTABLE">
490            <col>
491            <col>
492
493            <thead>
494              <tr>
495                <th>Option</th>
496
497                <th>Purpose</th>
498              </tr>
499            </thead>
500
501            <tbody>
502              <tr>
503                <td><var class="LITERAL">model=</var><span class=
504                "emphasis"><i class="EMPHASIS">name</i></span></td>
505
506                <td>Use <span class="emphasis"><i class=
507                "EMPHASIS">name</i></span> entry in <var class=
508                "LITERAL">ifhp.conf</var></td>
509              </tr>
510
511              <tr>
512                <td><var class="LITERAL">status</var> or <var
513                class="LITERAL">status@</var></td>
514
515                <td>Printer does or does not provide status
516                information</td>
517              </tr>
518
519              <tr>
520                <td><var class="LITERAL">sync</var>, <var class=
521                "LITERAL">sync@</var>, <var class=
522                "LITERAL">sync=</var><span class="emphasis"><i
523                class="EMPHASIS">(ps|pjl)</i></span> </td>
524
525                <td>Printer does or does not indicate ready to
526                operate at start of job, or use PostScript or PJL
527                code sequence to determine if printer is
528                ready.</td>
529              </tr>
530
531              <tr>
532                <td><var class="LITERAL">pagecount</var>, <var
533                class="LITERAL">pagecount@</var>, <var class=
534                "LITERAL">pagecount=</var><span class="emphasis"><i
535                class="EMPHASIS">(ps|pjl)</i></span> </td>
536
537                <td>Printer does or does not have pagecount
538                support, or use PostScript or PJL code sequence to
539                determine pagecount.</td>
540              </tr>
541
542              <tr>
543                <td><var class="LITERAL">waitend</var>, <var class=
544                "LITERAL">waitend@</var>, <var class=
545                "LITERAL">waitend=</var><span class="emphasis"><i
546                class="EMPHASIS">(ps|pjl)</i></span> </td>
547
548                <td>Wait or do not wait for end of job, or send
549                PostScript or PJL code sequence to have printer
550                report end of job.</td>
551              </tr>
552            </tbody>
553          </table>
554        </div>
555
556        <p>The <var class="LITERAL">model=</var><span class=
557        "emphasis"><i class="EMPHASIS">name</i></span> entry is
558        used to specify the configuration entry in the <var class=
559        "LITERAL">ifhp.conf</var> file to be used by <b class=
560        "APPLICATION">ifhp</b>. This entry usually has all of the
561        specific information needed by the <b class=
562        "APPLICATION">ifhp</b> filter.</p>
563
564        <p>The <var class="LITERAL">status</var> option is the most
565        common option usually provided in a printcap entry. This
566        option is needed when the communication with the printer is
567        <span class="emphasis"><i class=
568        "EMPHASIS">write-only</i></span> and no status information
569        will be returned. If a printer normally supports returning
570        status information then the <var class=
571        "LITERAL">ifhp.conf</var> configuration entry will indicate
572        this and the <b class="APPLICATION">ifhp</b> filter will
573        try to get status. When no status is returned it will
574        either terminate operation after a timeout or sit in an
575        endless loop waiting for status. By specifying <var class=
576        "LITERAL">status@</var> you will suppress getting status.
577        This also has the effect of doing <var class=
578        "LITERAL">sync@</var>, <var class=
579        "LITERAL">pagecount@</var>, and <var class=
580        "LITERAL">waitend@</var></p>
581
582        <p>The <var class="LITERAL">sync</var> option is used to
583        cause <b class="APPLICATION">ifhp</b> to wait for an <span
584        class="emphasis"><i class="EMPHASIS">end of job</i></span>
585        indication from the printer before starting the next job.
586        This is usually done in order to make sure that all jobs
587        have been flushed from a printer before starting another
588        job. If you specify <var class="LITERAL">sync@</var> then
589        you may get slightly faster startup but at the expense of
590        losing the ends of previous print jobs.</p>
591
592        <p>The <var class="LITERAL">pagecount</var> option is used
593        to cause <b class="APPLICATION">ifhp</b> to get the value
594        of a hardware pagecounter from the printer. If your printer
595        supports such an item then the <var class=
596        "LITERAL">ifhp.conf</var> configuration option usually
597        indicates this. However, it takes a small amount of time to
598        get the pagecounter information from the printer and you
599        may not need it. Use <var class="LITERAL">sync@</var> if
600        you do not want page counts.</p>
601
602        <p>Finally, <var class="LITERAL">waitend</var> option is
603        used to cause <b class="APPLICATION">ifhp</b> to wait for
604        an <span class="emphasis"><i class="EMPHASIS">end of
605        job</i></span> indication from the printer before exiting.
606        If you specify <var class="LITERAL">waitend@</var> then the
607        filter will exit immediately after sending the job, but you
608        will possibly lose any error information or status reports
609        from the printer.</p>
610
611        <p>For a complete list of all of the <b class=
612        "APPLICATION">ifhp</b> options please see the IFHP
613        documentation.</p>
614      </div>
615
616      <div class="SECT2">
617        <h2 class="SECT2"><a name="JAGGIES">4.10.3. The Jaggies -
618        LF to CR-LF Conversion With lpf</a></h2>
619
620        <p>When printing to vintage hard copy devices or to
621        printers that support a <span class="emphasis"><i class=
622        "EMPHASIS">text</i></span> mode, many UNIX users discover
623        that their output suffers from a case of the jaggies.</p>
624
625        <div class="INFORMALEXAMPLE">
626          <a name="AEN2977"></a>
627<pre class="SCREEN">
628    Input file:
629    
630      This is
631      a nice day
632    
633    Output:
634    
635      This is
636             a nice day
637</pre>
638        </div>
639        <br>
640        <br>
641
642        <p>UNIX systems terminate lines with a single <acronym
643        class="ACRONYM">NL</acronym> (new line) character. This
644        causes the printer to move down one line on the printing
645        page but does not change its horizontal position and print
646        the next character at the left margin. This is done by
647        using the <acronym class="ACRONYM">CR</acronym> (carriage
648        return) character. You need to convert the single <acronym
649        class="ACRONYM">NL</acronym> to a <var class=
650        "LITERAL">CR-LF</var> combination and the <b class=
651        "APPLICATION">lpf</b> filter supplied with <b class=
652        "APPLICATION">LPRng</b> does this.</p>
653
654        <p>First, locate the <b class="APPLICATION">lpf</b> filter.
655        You can find it by using the command:</p>
656
657        <div class="INFORMALEXAMPLE">
658          <a name="AEN2988"></a>
659<pre class="SCREEN">
660    <samp class="PROMPT">h9: {160} %</samp> <kbd class=
661"USERINPUT">find /usr/ -type f -name lpf -print</kbd>
662    /usr/libexec/lpr/lpf
663</pre>
664        </div>
665        <br>
666        <br>
667
668        <p>We will first see what the output is like without <b
669        class="APPLICATION">lpf</b>, and then see what it does.
670        Modify the <b class="APPLICATION">lp</b> printcap entry as
671        shown below and then use <tt class="COMMAND">lpc
672        restart</tt> to restart the <b class="APPLICATION">lpd</b>
673        server.</p>
674
675        <div class="INFORMALEXAMPLE">
676          <a name="AEN2997"></a>
677<pre class="SCREEN">
678    lp:sd=/var/spool/lpd/%P
679      :force_localhost
680      :lp=/tmp/lp
681</pre>
682        </div>
683        <br>
684        <br>
685
686        <p>Print a file and view the output using the following
687        commands. If you do not have the <b class=
688        "APPLICATION">od</b> (octal dump) program, try using <b
689        class="APPLICATION">hexdump</b> or some other appropriate
690        program that displays the numerical contents of the
691        file.</p>
692
693        <div class="INFORMALEXAMPLE">
694          <a name="AEN3002"></a>
695<pre class="SCREEN">
696    <samp class="PROMPT">h4: {203} %</samp> <kbd class=
697"USERINPUT">cp /dev/null /tmp/lp</kbd>
698    <samp class="PROMPT">h4: {204} %</samp> <kbd class=
699"USERINPUT">lpr /tmp/hi</kbd>
700    <samp class="PROMPT">h4: {205} %</samp> <kbd class=
701"USERINPUT">od -bc /tmp/lp</kbd>
702    0000000  150 151 012
703               h   i  \n
704    0000003
705</pre>
706        </div>
707        <br>
708        <br>
709
710        <p>Now we will use the <b class="APPLICATION">lpf</b>
711        filter. Modify the printcap as shown below and use <tt
712        class="COMMAND">lpc reread</tt> to cause <b class=
713        "APPLICATION">lpd</b> to reread the configuration
714        information.</p>
715
716        <div class="INFORMALEXAMPLE">
717          <a name="AEN3014"></a>
718<pre class="SCREEN">
719    lp:sd=/var/spool/lpd/%P
720      :force_localhost
721      :lp=/tmp/lp
722      # modify the path to lpf appropriately
723      :filter=/usr/local/libexec/filters/lpf
724</pre>
725        </div>
726        <br>
727        <br>
728
729        <p>Now reprint the file:</p>
730
731        <div class="INFORMALEXAMPLE">
732          <a name="AEN3017"></a>
733<pre class="SCREEN">
734    <samp class="PROMPT">h4: {206} %</samp> <kbd class=
735"USERINPUT">cp /dev/null /tmp/lp</kbd>
736    <samp class="PROMPT">h4: {207} %</samp> <kbd class=
737"USERINPUT">lpr /tmp/hi</kbd>
738    <samp class="PROMPT">h4: {208} %</samp> <kbd class=
739"USERINPUT">od -bc /tmp/lp</kbd>
740    od -bc /tmp/lp
741    0000000  150 151 015 012
742               h   i  \r  \n
743    0000004
744</pre>
745        </div>
746        <br>
747        <br>
748
749        <p>As you see, <b class="APPLICATION">lpf</b> changes the
750        <var class="LITERAL">LF</var> to a <var class=
751        "LITERAL">CR-LF</var> sequence.</p>
752      </div>
753
754      <div class="SECT2">
755        <h2 class="SECT2"><a name="AEN3029">4.10.4. Store and
756        Forward Spool Queues</a></h2>
757
758        <p>Up to now we have assumed that associated with each
759        spool queue is a hardware printing device. When a job is
760        sent to the spool queue the <b class="APPLICATION">lpd</b>
761        server will take actions to filter it and then send it to
762        the printing device.</p>
763
764        <p>However, we can also have <span class="emphasis"><i
765        class="EMPHASIS">store and forward</i></span> spool queues.
766        These queue act to simply buffer jobs and then forward them
767        to another spooler. The following printcap entry shows how
768        you can specify a store and forward queue.</p>
769
770        <div class="INFORMALEXAMPLE">
771          <a name="AEN3035"></a>
772<pre class="SCREEN">
773    # store and forward using classical BSD :rm:rp
774    lp:rp=pr:rm=host
775      :sd=/var/spool/lpd/%P
776      :server
777    # store and forward using <b class=
778"APPLICATION">LPRng</b> lp=pr@host
779    lp:lp=pr@host
780      :sd=/var/spool/lpd/%P
781      :server
782</pre>
783        </div>
784        <br>
785        <br>
786
787        <p>The legacy <var class="LITERAL">:rp</var> (remote
788        printer) and <var class="LITERAL">:rm</var> (remote host)
789        format can be used to specify the print queue and
790        destination host for jobs sent to this queue. The <b class=
791        "APPLICATION">LPRng</b> <var class=
792        "LITERAL">:lp=pr@host</var> format serves the same
793        function, and has precedence over the <var class=
794        "LITERAL">:rm:rp</var> form.</p>
795
796        <p>Edit the printcap file so it has contents indicated
797        below, use <tt class="COMMAND">checkpc -f</tt> to check the
798        printcap, and then use <tt class="COMMAND">lpc reread</tt>
799        to restart the <b class="APPLICATION">lpd</b> server.</p>
800
801        <div class="INFORMALEXAMPLE">
802          <a name="AEN3048"></a>
803<pre class="SCREEN">
804    lp:force_localhost
805    lp:server
806      :sd=/var/spool/lpd/%P
807      :lp=lp2@localhost
808    lp2:force_localhost
809    lp2:server
810      :sd=/var/spool/lpd/%P
811      :lp=/tmp/lp2
812</pre>
813        </div>
814        Execute the following commands to print the <tt class=
815        "FILENAME">/tmp/hi</tt> file and observe the results: 
816
817        <div class="INFORMALEXAMPLE">
818          <a name="AEN3051"></a>
819<pre class="SCREEN">
820    <samp class="PROMPT">h4: {209} %</samp> <kbd class=
821"USERINPUT">lpr /tmp/hi</kbd>
822    <samp class="PROMPT">h4: {210} %</samp> <kbd class=
823"USERINPUT">lpq -lll</kbd>
824    Printer: lp@h4 (dest lp2@localhost)
825     Queue: no printable jobs in queue
826     Status: sending control file 'cfA029h4.private' \
827        to lp2@localhost at 09:39:57.719
828     Status: completed sending 'cfA029h4.private' \
829        to lp2@localhost at 09:39:57.724
830     Status: sending data file 'dfA029h4.private' \
831        to lp2@localhost at 09:39:57.727
832     Status: completed sending 'dfA029h4.private' \
833        to lp2@localhost at 09:39:57.925
834     Status: done job 'papowell@h4+29' transfer \
835        to lp2@localhost at 09:39:57.926
836     Status: subserver pid 29031 exit status 'JSUCC' at 09:39:57.953
837     Status: lp@h4.private: job 'papowell@h4+29' printed at 09:39:57.961
838     Status: job 'papowell@h4+29' removed at 09:39:57.993
839    Printer: lp2@h4
840     Queue: no printable jobs in queue
841     Status: no banner at 09:39:58.054
842     Status: printing data file 'dfA029h4.private', size 3 at 09:39:58.054
843     Status: printing done 'papowell@h4+29' at 09:39:58.054
844     Status: accounting at end at 09:39:58.054
845     Status: finished 'papowell@h4+29', status 'JSUCC' at 09:39:58.054
846     Status: subserver pid 29033 exit status 'JSUCC' at 09:39:58.056
847     Status: lp2@h4.private: job 'papowell@h4+29' printed at 09:39:58.056
848     Status: job 'papowell@h4+29' removed at 09:39:58.069
849</pre>
850        </div>
851        <br>
852        <br>
853
854        <p>As we see from the status, our job was sent to the <var
855        class="LITERAL">lp</var> spool queue first. It was store
856        there and then the <b class="APPLICATION">lpd</b> server
857        transferred it to the <var class="LITERAL">lp2</var> spool
858        queue, where it was printed to the file <tt class=
859        "FILENAME">/tmp/lp2</tt>.</p>
860      </div>
861
862      <div class="SECT2">
863        <h2 class="SECT2"><a name="AEN3062">4.10.5. Filtering Job
864        Files In Transit</a></h2>
865
866        <p>One of the major problems with store and forward
867        operation is that the destination spool queue may not
868        actually be a spool queue - it can be a printer. Many
869        network printers provide an RFC1179 compatible network
870        interface and act, for job forwarding purposes, like a host
871        running a limited capability BSD print spooler.</p>
872
873        <p>By adding a filter to the printcap information we can
874        modify the format of a job file so that it is compatible
875        with the destination printer.</p>
876
877        <p>Edit the printcap and <tt class=
878        "FILENAME">/tmp/testf</tt> files so they have the contents
879        indicated below, give <tt class="FILENAME">/tmp/testf</tt>
880        executable permissions, use <tt class="COMMAND">checkpc
881        -f</tt> to check the printcap, and then use <tt class=
882        "COMMAND">lpc reread</tt> to restart the <b class=
883        "APPLICATION">lpd</b> server.</p>
884
885        <div class="INFORMALEXAMPLE">
886          <a name="AEN3072"></a>
887<pre class="SCREEN">
888    # set /tmp/testf to contain the following
889    #   and chmod 755 /tmp/testf
890    #!/bin/sh
891    echo TESTF $0 $@
892    /bin/cat
893    exit 0
894    
895    # printcap
896    lp:force_localhost
897    lp:server
898      :sd=/var/spool/lpd/%P
899      :lp=lp2@localhost
900      :filter=/tmp/testf
901      :bq_format=ffl
902    lp2:force_localhost
903    lp2:server
904      :sd=/var/spool/lpd/%P
905      :lp=/tmp/lp2
906</pre>
907        </div>
908        Execute the following commands to print the <tt class=
909        "FILENAME">/tmp/hi</tt> file and observe the results: 
910
911        <div class="INFORMALEXAMPLE">
912          <a name="AEN3075"></a>
913<pre class="SCREEN">
914    <samp class="PROMPT">h4: {211} %</samp> <kbd class=
915"USERINPUT">lpr /tmp/hi</kbd>
916    <samp class="PROMPT">h4: {212} %</samp> <kbd class=
917"USERINPUT">lpq -llll</kbd>
918    <samp class="PROMPT">h4: {213} %</samp> <kbd class=
919"USERINPUT">lpq -llll</kbd>
920    Printer: lp@h4 (dest lp2@localhost)
921     Queue: no printable jobs in queue
922     Status: no banner at 09:55:53.681
923     Status: printing data file 'dfA086h4.private', size 3, \
924        IF filter 'testf' at 09:55:53.683
925     Status: IF filter finished at 09:55:53.713
926     Status: printing done 'papowell@h4+86' at 09:55:53.714
927     Status: sending job 'papowell@h4+86' to lp2@localhost at 09:55:53.734
928     Status: connecting to 'localhost', attempt 1 at 09:55:53.735
929     Status: connected to 'localhost' at 09:55:53.739
930     Status: requesting printer lp2@localhost at 09:55:53.740
931     Status: sending control file 'cfA086h4.private' 
932          to lp2@localhost at 09:55:53.752
933     Status: completed sending 'cfA086h4.private' 
934          to lp2@localhost at 09:55:53.757
935     Status: sending data file 'dfA086h4.private' 
936          to lp2@localhost at 09:55:53.758
937     Status: completed sending 'dfA086h4.private' 
938          to lp2@localhost at 09:55:53.939
939     Status: done job 'papowell@h4+86' transfer 
940          to lp2@localhost at 09:55:53.940
941     Status: subserver pid 29088 exit status 'JSUCC' at 09:55:53.980
942     Status: lp@h4.private: job 'papowell@h4+86' printed at 09:55:53.983
943     Status: job 'papowell@h4+86' removed at 09:55:53.998
944    Printer: lp2@h4
945     Queue: no printable jobs in queue
946     Status: subserver pid 29092 starting at 09:55:54.005
947     Status: accounting at start at 09:55:54.005
948     Status: opening device '/tmp/lp2' at 09:55:54.005
949     Status: printing job 'papowell@h4+86' at 09:55:54.005
950     Status: no banner at 09:55:54.006
951     Status: printing data file 'dfA086h4.private', size 298 at 09:55:54.006
952     Status: printing done 'papowell@h4+86' at 09:55:54.006
953     Status: accounting at end at 09:55:54.006
954     Status: finished 'papowell@h4+86', status 'JSUCC' at 09:55:54.006
955     Status: subserver pid 29092 exit status 'JSUCC' at 09:55:54.008
956     Status: lp2@h4.private: job 'papowell@h4+86' printed at 09:55:54.008
957     Status: job 'papowell@h4+86' removed at 09:55:54.020
958</pre>
959        </div>
960        <br>
961        <br>
962
963        <p>We have displayed a bit more status information so that
964        we can see what the actions the <var class=
965        "LITERAL">lp</var> queue carries out. It first <span class=
966        "emphasis"><i class="EMPHASIS">processes</i></span> the job
967        data file using the <b class="APPLICATION">testf</b> filter
968        and puts the results in a temporary file. Then it sends the
969        contents of the temporary file to the <var class=
970        "LITERAL">lp2</var> queue. The <var class=
971        "LITERAL">lp2</var> queue receives the converted job file
972        and then prints it to the <tt class=
973        "FILENAME">/tmp/lp2</tt> file in turn.</p>
974
975        <p>By default, each file in a job is processed by a print
976        file and the processed output is then sent to the
977        destintion as individual job files, each with the format
978        specified by the value of the <var class=
979        "LITERAL">bq_format</var> (default <var class=
980        "LITERAL">f</var>) option. The <var class=
981        "LITERAL">bq_format</var> option has the format <var class=
982        "LITERAL">iOiO...d</var>; each <var class="LITERAL">i</var>
983        is the original format and the corresponding <var class=
984        "LITERAL">O</var> is the output format. If there is an odd
985        number of characters then the last unmatched character is
986        used as the default format, otherwise no translation is
987        done. For example, <var class="LITERAL">flrfl</var> will
988        cause the <var class="LITERAL">f</var> format to be mapped
989        to <var class="LITERAL">l</var>, <var class=
990        "LITERAL">r</var> to <var class="LITERAL">f</var>, and any
991        others to <var class="LITERAL">l</var>.</p>
992      </div>
993    </div>
994
995    <div class="NAVFOOTER">
996      <hr align="LEFT" width="100%">
997
998      <table summary="Footer navigation table" width="100%" border=
999      "0" cellpadding="0" cellspacing="0">
1000        <tr>
1001          <td width="33%" align="left" valign="top"><a href=
1002          "printjobfilters.htm" accesskey="P">Prev</a></td>
1003
1004          <td width="34%" align="center" valign="top"><a href=
1005          "index.htm" accesskey="H">Home</a></td>
1006
1007          <td width="33%" align="right" valign="top"><a href=
1008          "x3103.htm" accesskey="N">Next</a></td>
1009        </tr>
1010
1011        <tr>
1012          <td width="33%" align="left" valign="top">Print Job
1013          Filters</td>
1014
1015          <td width="34%" align="center" valign="top"><a href=
1016          "tutorial.htm" accesskey="U">Up</a></td>
1017
1018          <td width="33%" align="right" valign="top">Printcap
1019          Basics</td>
1020        </tr>
1021      </table>
1022    </div>
1023  </body>
1024</html>
1025
1026