SUMMARY: Print filters

From: Fred Muehlmann (fred@upl.com)
Date: Tue May 04 1993 - 09:43:41 CDT


My original questions was:

Does anyone have information on writing print filters to be included in
/etc/printcap via the if= and of= options? How does lpd invoke these filters,
how is the data passed to them (via stdin?), and what are the filters supposed
to write the data to? Does lpd expect filters to have any startup parameters
that will be passed on the command-line? References or any info would be
appreciated.

Thanks to the following who responded, indicating that there is a discussion on
filters in Chapter 12.5 of System & Network Administration and who gave other
references:

eckhard@ts.go.dlr.de (Eckhard Rueggeberg)
Peter Samuel <peters@mega.com.au>
John Valdes <valdes@geosun.uchicago.edu>
Don Lewis <gdonl@ssi1.com> also suggested looking in:
        ftp.uu.net:systems/unix/bsd-sources/share/doc/smm/06.lpd/*

Very hearty thanks to the following who sent very useful examples and code on
writing filters. I'm sure others besides myself will benefit. Their lengthy
replies follow:

mirnaz@appli.mimuw.edu.pl (Mirek Nazaruk) sent source for the lpf filter
(the default filter), which I was very interested in seeing.

baum@kirk.es.go.dlr.de (Peter Baumann) sent the source to an Hp Laserjet III
filter which he uses. Danke Peter.

don@mars.dgrc.doc.ca (Donald McLachlan) discusses use of filters and sent an
example of a script.

"Chris Phillips" <chris@cs.yorku.ca> sent source code for several filters
(both "C" and script). Source code is always appreciated.

poffen@sj.ate.slb.com (Russ Poffenberger) offers to send a filter for a
plotter that counts the feet of paper used from a roll. Interesting!

root@micom.com (Todd L. Kindig @ Micom Comm. Corp.) sends comments and a
script file he kept from a similar question in comp.unix.wizards.

strombrg@hydra.acs.uci.edu sends part of the MSD 2.6 man page for printcap.

Trevor Morrison <trevor@ssci.liverpool.ac.uk> sends source code for a modified
text2ps filter. This was also very useful ... Thanks.

shevett@sparc.bighouse.unipress.com (Dave Shevett) sends an example of a
filter that strips off the annoying DOS ^D at the start of print jobs (at
least the Postscript ones coming from MS Windows). Thanks Dave.

poul@nilu.no (Poul Sorensen) sends a very useful filter ... to prevent those
postscript jobs from printing on a standard line printer.

Lengthy responses follow:
*****************************************************************************
mirnaz@appli.mimuw.edu.pl (Mirek Nazaruk) writes:

There are three types of filters. Arguments passed to a filter depend on
its type. The of filter has syntax:
  ofilter -wwidth -llength (where width and length are taken from
pw and pl entries in printcap)
The if filter:
  ifilter [-c] -wwidth -llength -iindent -n login -h host account_file
-c means that control characters should be passed through filter uninterpreted.

Others filters are called with arguments:
 filter -xwidth -ylength -n login -h host account_file,
where x i y are page sizes in pixels (px, py fields in printcap).

The above information are taken from SunOS manual
(System and Network Admin/Procedures).

The input data is taken from stdin and output is passed to stdout.
As a example I am sending you source of the lpf filter:

Mirek Nazaruk
---------------------------- lpf.c --------------------------------------

/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved. The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#ifndef lint
static char sccsid[] = "@(#)lpf.c 5.1 (Berkeley) 5/15/85";
#endif not lint

/*
 * filter which reads the output of nroff and converts lines
 * with ^H's to overwritten lines. Thus this works like 'ul'
 * but is much better: it can handle more than 2 overwrites
 * and it is written with some style.
 * modified by kls to use register references instead of arrays
 * to try to gain a little speed.
 */

#include <stdio.h>
#include <signal.h>

#define MAXWIDTH 132
#define MAXREP 10

char buf[MAXREP][MAXWIDTH];
int maxcol[MAXREP] = {-1};
int lineno;
int width = 132; /* default line length */
int length = 66; /* page length */
int indent; /* indentation length */
int npages = 1;
int literal; /* print control characters */
char *name; /* user's login name */
char *host; /* user's machine name */
char *acctfile; /* accounting information file */

main(argc, argv)
        int argc;
        char *argv[];
{
        register FILE *p = stdin, *o = stdout;
        register int i, col;
        register char *cp;
        int done, linedone, maxrep;
        char ch, *limit;

        while (--argc) {
                if (*(cp = *++argv) == '-') {
                        switch (cp[1]) {
                        case 'n':
                                argc--;
                                name = *++argv;
                                break;

                        case 'h':
                                argc--;
                                host = *++argv;
                                break;

                        case 'w':
                                if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
                                        width = i;
                                break;

                        case 'l':
                                length = atoi(&cp[2]);
                                break;

                        case 'i':
                                indent = atoi(&cp[2]);
                                break;

                        case 'c': /* Print control chars */
                                literal++;
                                break;
                        }
                } else
                        acctfile = cp;
        }

        for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
        done = 0;
        
        while (!done) {
                col = indent;
                maxrep = -1;
                linedone = 0;
                while (!linedone) {
                        switch (ch = getc(p)) {
                        case EOF:
                                linedone = done = 1;
                                ch = '\n';
                                break;

                        case '\f':
                                lineno = length;
                        case '\n':
                                if (maxrep < 0)
                                        maxrep = 0;
                                linedone = 1;
                                break;

                        case '\b':
                                if (--col < indent)
                                        col = indent;
                                break;

                        case '\r':
                                col = indent;
                                break;

                        case '\t':
                                col = ((col - indent) | 07) + indent + 1;
                                break;

                        case '\031':
                                /*
                                 * lpd needs to use a different filter to
                                 * print data so stop what we are doing and
                                 * wait for lpd to restart us.
                                 */
                                if ((ch = getchar()) == '\1') {
                                        fflush(stdout);
                                        kill(getpid(), SIGSTOP);
                                        break;
                                } else {
                                        ungetc(ch, stdin);
                                        ch = '\031';
                                }

                        default:
                                if (col >= width || !literal && ch < ' ') {
                                        col++;
                                        break;
                                }
                                cp = &buf[0][col];
                                for (i = 0; i < MAXREP; i++) {
                                        if (i > maxrep)
                                                maxrep = i;
                                        if (*cp == ' ') {
                                                *cp = ch;
                                                if (col > maxcol[i])
                                                        maxcol[i] = col;
                                                break;
                                        }
                                        cp += MAXWIDTH;
                                }
                                col++;
                                break;
                        }
                }

                /* print out lines */
                for (i = 0; i <= maxrep; i++) {
                        for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
                                putc(*cp, o);
                                *cp++ = ' ';
                        }
                        if (i < maxrep)
                                putc('\r', o);
                        else
                                putc(ch, o);
                        if (++lineno >= length) {
                                fflush(o);
                                npages++;
                                lineno = 0;
                        }
                        maxcol[i] = -1;
                }
        }
        if (lineno) { /* be sure to end on a page boundary */
                putchar('\f');
                npages++;
        }
        if (name && acctfile && access(acctfile, 02) >= 0 &&
            freopen(acctfile, "a", stdout) != NULL) {
                printf("%7.2f\t%s:%s\n", (float)npages, host, name);
        }
        exit(0);
}

*****************************************************************************
baum@kirk.es.go.dlr.de (Peter Baumann) writes:

Here are two files together with our printcap entry. The printer is a HPLJ III
connected to the parallel port of a SS 10/41 with 4.1.3.

If you have more questions feel free to contact me. My information is from
the standard SUN docs.

printcap:

hplj|lp|ps|postscript|PostScript:\
        :lp=/dev/hplj:sd=/usr/spool/hplj:\
        :lf=/usr/spool/hplj/hplj-log:af=/usr/adm/hplj.acct:\
        :mx#0:sh:\
        :if=/usr/local/bin/hplj_if.sh:

-----------------------------------------
hplj_if.c:

/**************************************************************************
* input filter for printer queue *
* test if the incoming file is Postscript or not. If it is Postscript *
* send it directly to the printer, if not send it to enscript. *
* the file to be printed comes from stdin the printer is connected to *
* stdout. stderr is connected to the log file defined in /etc/printcap *
* return values: 0: no errors; 1: reprint the job; 2: throw job away *
**************************************************************************/

/* P. Baumann Feb. 93 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>

int main(argc, argv)
        int argc;
        char **argv;
{
  char c1, c2; /* first two characters in file */
  FILE* fptr; /* file pointer for enscript file */
  time_t TheTime=0; /* current time (for generating file name) */
  char *filename[200];
  char *en_command[250]; /* enscript command */
  int i;

/* read first two characters from stdin */

  c1 = getchar();

  /* Von Windows erzeugte PS-Files beginnen mit ^D (ASCII 4). Da kein
   * anstaendiger Text so beginnt, wird ^D einfach ueberlesen
   */
  if (c1 == 4) {
    c1 = getchar();
  }

  c2 = getchar();

/* check for Postscript file */

  if ( (c1=='%') && (c2=='!')) {

/* Postscript file: pipe directly to stdout (printer) */

    putchar(c1);
    putchar(c2);
    while ( (c1=getchar()) != EOF)
      putchar(c1);
  }
  else {

/* non postscript file: write to file and let enscript do the printing */

    sprintf(filename, "/tmp/hplj%d", time(&TheTime));
    fptr = fopen(filename, "w");
    if (!fptr) {
      fprintf(stderr, "could not open temporary file for enscript: %s\n",
              filename);
      return(1); /* reprint job */
    }
    fputc(c1, fptr);
    fputc(c2, fptr);
    while ( (c1=getchar()) != EOF)
      fputc(c1, fptr);
    fclose (fptr);
    sprintf(en_command,
            "/usr/tran/sparc/lib/enscript -Plp -2Gr -fCourier8 -L57 %s",
            filename);
    system (en_command);
    sprintf(en_command, "/bin/rm %s", filename);
    system (en_command);
  }
  return(0);
}

-----------------------------------------
hplj_if.sh:

#!/bin/sh
export PATH
PATH=/usr/ucb:$PATH
/usr/local/bin/hplj_if

****************************************************************************
don@mars.dgrc.doc.ca (Donald McLachlan) writes:

This is non-authoratative, bust the way I see it.

of= filters are opened once for each printer when lpd starts up. So if you do
    some filtering of ALL data to a printer it can best be done here. Weird
    'for instance', if you had a printer that ONLY knew EBCDIC you could
    have an of which does ASCII to EBCDIC conversions.

if= filters are opened once for each print job. This is NOT that same as once
    for each file. (ie. lpr /etc/hosts /etc/printcap, is one job of 2 files)

You are correct, the data is passed to the filter via stdin.
In fact, lpd essentinally looks at /etc/printcap, and sets up the pipeline...

        cat $files | $if | $of | $lp

where

$files are the files specified on the lpr command line.
$if, $of, $lp are the values from the printcap entry.

Although filters normally read and add/delete/modify the data from stdin
and write to stdout, there is nothing preventing them from sending the
data somewhere other than stdout. My favorite "other" place to send data is
back to lpr. This allows me to set up a pseudo local-printer and then
respool the data to remote-printer. This must be done, because lpd will only
do filtering for local (non-remote) printcap entries.

Here is a sample of one such filter ...

#!/bin/sh
#
# This file is an lpr input filter which pipes the data to be printed
# though the qms-input-filter to lpr which will then queue it up to
# the np213 printer queue.
#
# 1) the data to be printed is piped to the input filter, this program.
# 2) since this program is a shell script the loader attaches the output of
# the pipe to the input of the shell.
# 3) any program started by the shell (including this program and the one
# about to be started) inherit the stdin of the shell.
# 4) therefore the next command; passes the data to print through the
# qms-input-filter, and pipes it on to the lpr command which will
# requeue it to a different print queue.
#
/usr/local/qms/qms-parallel-filter | /usr/ucb/lpr -Pnp213_qprn

*****************************************************************************
"Chris Phillips" <chris@cs.yorku.ca> writes:

Three sample filters follow,

Here is a c example filter:
============================= ifilter.c ====================================
/* lp if filter $Header$ */
/*
 * $Log$
 */
/*
 *filter [-c] -w/width/ -l/length/ -i/indent/ -n /login/ -h /host/ /accounting_file/
 * return 0 - for success
 * return 1 - for try again
 * return 2 - to cancel
 ** Comments below stolen from berkeley printjob.c lpd rtn.
 * 2 if the filter detected some errors (but printed the job anyway),
 * 1 if we should try to reprint this job and
 * 0 if all is well.
 * Note: all filters take stdin as the file, stdout as the printer,
 * stderr as the log file, and must not ignore SIGINT.
 **
 *
 * "if" is passed all params,
 * "of" for banner page and direct print, is passed only < -w -l >
 * "of" spools the banner and then suspends.
 * Others are passed : -x -y -n -h /a-f/
 * "cf" - cifplot
 * "df" - dvi
 * "gf" - plot(3x)
 * "rf" - "fortran carriage ctl"
 * "tf" - troff (C/A/T)
 * "nf" - ditroff
 * "vf" - raster output
 *
 */
#ifndef lint
static char rcsid[] = "$Id$";
#endif

#include <stdio.h>
#include <syslog.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
int getopt();

extern unsigned char *optarg;
extern int optind, opterr;

int ErrFlag = 0;
int CtlFlag = 0;
int Width = 0;
int Length = 0;
int Indent = 0;

unsigned char *LogName;
unsigned char *HostName;
unsigned char *AcctFile;

int
main(argc,argv)
int argc;
unsigned char **argv;
{
        register int count,input,linefeeds,c;
        FILE *acctf;
        char date[64];
        char *show_date();
#if defined(DEBUG)
        register int k;

        fprintf ( stderr , "ifilter invoked: argc = %d " , argc);
        for(k=0;k<argc;k++) {
                fprintf ( stderr , " [%d] <%s>" , k , argv[k] );
        }
        fprintf ( stderr , "\n" );
#endif
        ErrFlag = 0;
        while ((c = getopt(argc, argv, "cw:l:i:n:h:")) != EOF) {
                switch (c) {
                case 'c':
                        CtlFlag++;
                        break;
                case 'w':
                        Width = atoi(optarg);
                        break;
                case 'l':
                        Length = atoi(optarg);
                        break;
                case 'i':
                        Indent = atoi(optarg);
                        break;
                case 'n':
                        LogName = optarg;
                        break;
                case 'h':
                        HostName = optarg;
                        break;
                default:
                case '?':
                        ErrFlag++;
                        break;
                }
        }

        AcctFile = argv[optind];
        if (ErrFlag) {
                if (openlog("LPR-IF", LOG_PID) != -1) {
                        fprintf(stderr ,"LPR-IF Error in input args.\n");
                        syslog(LOG_WARNING,"LPR-IF %s.","Error in input args.");
                        closelog();
                }
#if defined(DEBUG)
                fprintf ( stderr , "Error exit: bad input.\n" );
#endif
                return(2);
        }
        input = count = linefeeds = 0;
        while ( (input = getchar()) != EOF ) {
                putchar((unsigned char) input);
                count++;
                if(input == '\f') linefeeds++;
        }
        if (acctf = fopen(AcctFile,"a")) {
                fprintf(acctf,"LP-IF:%s:%s:%d:%d:%s",HostName,LogName,count,linefeeds,show_date(date));
                fclose(acctf);
        } else {
                c = errno;
                fprintf ( stderr , "LP-IF:%s:%s:%d:%d:%s",HostName,LogName,count,linefeeds,show_date(date));
                fprintf ( stderr , "LP-IF:Accounting file %s failed to open<%d>.\n", AcctFile , c);
        }
#if defined(DEBUG)
        fprintf ( stderr , "Normal exit: LP-IF:%s:%s:%d:%d:%s",HostName,LogName,count,linefeeds,show_date(date) );
#endif
        return(0);

}
char *
show_date(sp)
char *sp;
{
        struct timeval t1;
        struct timezone tz1;

        if ( gettimeofday(&t1 , &tz1) == 0 ) {
                sprintf( sp , "%s",asctime(localtime(&(t1.tv_sec))));
        }
        return ( sp );
}
==================================================================================

And here is a shell script example:

============================RESPOOL=================================
#! /bin/sh
exec 5<&0
exec 6>&1
exec 7>&2
exec 0</dev/null
exec 1>&2
wd="`pwd`"
PRINTER="`/usr/bin/basename $wd`"
#
#echo "PRINTER=$PRINTER STATUS=$wd/status" >> /tmp/printer.debug
JobT="Respool"
Dstmp="`/usr/bin/date +%y%m%d.%H%M%S`"
Cfile="`/usr/ucb/tail -1 lock`"
Lpdpid="`/usr/ucb/head -1 lock`"
echo "${Dstmp}:${Lpdpid}:${Cfile}"
SHost=`/usr/bin/grep '^H' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^H\(.*\)/\1/'`
SPuser=`/usr/bin/grep '^P' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^P\(.*\)/\1/'`
SJob=`/usr/bin/grep '^J' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^J\(.*\)/\1/'`
SCsys=`/usr/bin/grep '^C' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^C\(.*\)/\1/'`
SLogin=`/usr/bin/grep '^L' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^L\(.*\)/\1/'`
Sfile=`/usr/bin/grep '^f' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^f\(.*\)/\1/'`
Sufile=`/usr/bin/grep '^u' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^u\(.*\)/\1/'`
Sname=`/usr/bin/grep '^N' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^N\(.*\)/\1/'`
Jobno=`echo ${Sfile} | /usr/bin/sed -e 's/^df.\([0-9]*\).*$/\1/'`
DHost=`echo ${Sfile} | /usr/bin/sed -e 's/^df.[0-9]*\(.*\)$/\1/'`
DFcnt=`/usr/ucb/wc -c ${Sfile} | /usr/bin/sed -e 's/^[ ]*\([0-9]*\)[^0-9].*$/\1/'`
echo "${Dstmp},${DHost},${Jobno},${SHost},${SPuser},${SJob},${SCsys},${SLogin},${Sfile}<${DFcnt}>,${Sufile},\"${Sname}\",${JobT}" >> lprlog
exec 0<&5
exec 1>&6
exec 2>&7
/usr/lib/daemon lprus N733 $SPuser
exit 0
===========================================================================

and another:
==============================psif-text===============================
#! /bin/sh
exec 5<&0
exec 6>&1
exec 7>&2
exec 0</dev/null
exec 1>&2
wd="`pwd`"
PRINTER="`/usr/bin/basename $wd`"
#
#echo "PRINTER=$PRINTER STATUS=$wd/status" >> /tmp/printer.debug
JobT="Text"
Dstmp="`/usr/bin/date +%y%m%d.%H%M%S`"
Cfile="`/usr/ucb/tail -1 lock`"
Lpdpid="`/usr/ucb/head -1 lock`"
echo "${Dstmp}:${Lpdpid}:${Cfile}"
SHost=`/usr/bin/grep '^H' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^H\(.*\)/\1/'`
SPuser=`/usr/bin/grep '^P' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^P\(.*\)/\1/'`
SJob=`/usr/bin/grep '^J' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^J\(.*\)/\1/'`
SCsys=`/usr/bin/grep '^C' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^C\(.*\)/\1/'`
SLogin=`/usr/bin/grep '^L' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^L\(.*\)/\1/'`
Sfile=`/usr/bin/grep '^f' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^f\(.*\)/\1/'`
Sufile=`/usr/bin/grep '^u' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^u\(.*\)/\1/'`
Sname=`/usr/bin/grep '^N' $Cfile | /usr/ucb/head -1 | /usr/bin/sed 's/^N\(.*\)/\1/'`
Jobno=`echo ${Sfile} | /usr/bin/sed -e 's/^df.\([0-9]*\).*$/\1/'`
DHost=`echo ${Sfile} | /usr/bin/sed -e 's/^df.[0-9]*\(.*\)$/\1/'`
DFcnt=`/usr/ucb/wc -c ${Sfile} | /usr/bin/sed -e 's/^[ ]*\([0-9]*\)[^0-9].*$/\1/'`
echo "${Dstmp},${DHost},${Jobno},${SHost},${SPuser},${SJob},${SCsys},${SLogin},${Sfile}<${DFcnt}>,${Sufile},\"${Sname}\",${JobT}" >> lprlog
exec 0<&5
exec 1>&6
exec 2>&7
/usr/local/bin/lpscript | /usr/lib/psrev | /usr/lib/lprps -D 3 -S $wd/status -P $PRINTER "$@"
============================================================================

One small note : the "of=" filter is different
in that it runs for the duration of the job as
opposed to the duration of the file.

*****************************************************************************
poffen@sj.ate.slb.com (Russ Poffenberger) writes:

These filters merely take input from stdin, and send output to stdout.

I wrote a simple one that sends all data verbatim from in to out, but counts
feet of paper on a continuous roll HP electrostatic plotter (it reads the HPGL
language) for accounting purposes.

I can send it if interested.

mdl@cypress.com (J. Matt Landrum) writes:

Here's one I had to do to get WP to print on a SPARCprinter

al-mdl[13] more sp1wp
#!/bin/csh -f
/usr/newsprint/lpd/if $argv
exit $status

I invoke it using the -c option to use the CIF filter. This was discovered
through experimentation. I don't know what else to tell you. Looks pretty much
like stdin.

The printcap looks like this.

################################################################
# entry for a SPARCprinter printer NeWSprint printer on a video port
lp|sp1|lw|sp1, a SPARCprinter printer:\
        :lp=/dev/lpvi0:\
        :sd=/usr/spoolit/sp1:\
        :lf=/usr/spoolit/sp1/log:\
        :af=/usr/spoolit/sp1/acct:\
        :if=/usr/newsprint/lpd/if:\
        :gf=/usr/newsprint/lpd/gf:\
        :nf=/usr/newsprint/lpd/nf:\
        :tf=/usr/newsprint/lpd/tf:\
        :rf=/usr/newsprint/lpd/rf:\
        :vf=/usr/newsprint/lpd/vf:\
        :cf=/usr/spool/sp1/sp1wp:\
        :df=/usr/newsprint/lpd/df:\
        :of=/usr/newsprint/lpd/of:\
        :mx#0:\
        :sf:\
        :sb:

*******************************************************************************
root@micom.com (Todd L. Kindig @ Micom Comm. Corp.) writes:

Here's some mail I kept and have used to do what I believe you want...

>From micom!gordius!noiro.oac.uci.edu!usc!cs.utexas.edu!swrinde!network.ucsd.edu!news.acns.nwu.edu!uicvm.uic.edu!u36842 Wed Apr 22 11:41:08 PDT 1992
Article: 23986 of comp.unix.wizards
Path: micom!gordius!noiro.oac.uci.edu!usc!cs.utexas.edu!swrinde!network.ucsd.edu!news.acns.nwu.edu!uicvm.uic.edu!u36842
From: U36842@uicvm.uic.edu (Ashish Desai)
Newsgroups: info.sun-managers,comp.unix.wizards
Subject: SUMMARY: Creating lpr input filter
Message-ID: <92109.153412U36842@uicvm.uic.edu>
Date: 18 Apr 92 20:34:12 GMT
Organization: University of Illinois at Chicago
Lines: 95

Sorry for posting the summary this late, here it is anyway:-

>Problem: Right now we have a shell script that created a header that is
>prefixed to a file before it is printed. That is, stick a header
>to the file and then do an lpr fname.
>I would like put the filter as a "printcap entry" input filter, which
>gets invoked when the file is printed using "lpr".
>I know that you can specify an input
>filter for a printer in the "printcap".
>The problem is I can't find documentation on how to write a filter
>such that "lpr" invokes it.
>
>System: SUN SPARCSTATION 1 and 1+.
>OS: 4.1.1

>Can anybody send me some suggestions.

----------------------------------------------------------
>From beldar@rimulac.microunity.com

A trivial example of what you want to do:

#!/bin/csh -f
cat /full/path/to/prefixfile
cat

----------------------------------------------------------
>From tom@uni-paderborn.de

There is some info in the Anserbook Rel 1 Issue 3

  System and Network Administration ( Book )
    12. Maintaining Printers and Print Servers ( Chapter )
      12.5 Output Filters ( Section )
        Output Filter Specifications ( Subsection )

-------------------------------------------------------
>From mills@ccu.UManitoba.CA

This was described in the Sys & Net Admin manual for 4.1, but was
omitted for 4.1.1. Here is a shell script we used for an if= filter.
It illustrates the calling conventions.

#!/bin/sh
#
# if filter for lpr
# filter [-c] -wwidth -llength -iindent -n login -h host acc_file
# files: 0 --> input data 1 --> printer 2 --> lf file
# return: 0: okay 1: reprint 2: discard
#

PATH=/usr/5bin:/usr/bin:/usr/ucb:/usr/local/bin
Z=`basename $0`
#
# parse options
#
for i in $*
do
        arg=`expr $1 : '..\(.*\)'`
        case $1 in
        -c) shift ;;
        -w*) form=$arg; shift;;
        -l*) length=$arg; shift;;
        -i*) indent=$arg; shift;;
        -n) shift; login=$1; shift;;
        -h) shift; host=$1; shift;;
        *) acc=$1;;
        esac
done

echo '\033%-12345X@PJL ENTER LANGUAGE=PostScript'
cat
echo '\033%-12345X\c'

exit 0

#!/end
-------------------------------------------------------------------------

Thanks to:

kalli!kevin@fourx.Aus.Sun.COM
mills@ccu.UManitoba.CA
eckhard@ikarus.ts.go.dlr.de
mario@wdc.sps.mot.com
kcurrans@CORDLEY.ORST.EDU
etnibsd!vsh@uunet.UU.NET
wls@cray.csd.uwm.edu
tom@uni-paderborn.de
beldar@rimulac.microunity.com

****************************************************************************
strombrg@hydra.acs.uci.edu writes:

This is from an MSD 2.6 "man printcap", which uses a BSD print system,
much like SunOS x, x<=4. This information was not in the Sun man page
I checked, though it might be in some suplementary documentation, esp
on paper.

FILTERS
     The lpd(8) daemon creates a pipeline of filters to process
     files for various printer types. The filters selected
     depend on the flags passed to lpr(1). The pipeline set up
     is:

          -p pr | if regular text + pr(1)
          none if regular text
          -c cf cifplot
          -d df DVI (tex)
          -g gf plot(3)
          -n nf ditroff
          -f rf Fortran
          -t tf troff
          -v vf raster image

     The if filter is invoked with arguments:

          if [ -c ] -wwidth -llength -iindent -n login -h host
     acct-file

     The -c flag is passed only if the -l flag (pass control
     specify the page width and length (from pw and pl respec-

     tively) in characters. The -n and -h parameters specify the
     login name and host name of the owner of the job respec-
     tively. Acct-file is passed from the af printcap entry.

     If no if is specified, of is used instead, with the distinc-
     tion that of is opened only once, while if is opened for
     every individual job. Thus, if is better suited to
     performing accounting. The of is only given the width and
     length flags.

     All other filters are called as:

          filter -xwidth -ylength -n login -h host acct-file
     where width and length are represented in pixels, specified
     by the px and py entries respectively.

     All filters take stdin as the file, stdout as the printer,
     may log either to stderr or using syslog(3), and must not
     ignore SIGINT.

****************************************************************************
Trevor Morrison <trevor@ssci.liverpool.ac.uk> writes:

The SunOs manual might be a good place to look but of course
it's sparse on information. Version 4.0 versions were better
but I found it in chapter 12 of the System and network admin
manual. It of course doesn't tell you about the signals necessary
for the filter to listen to. You can also pull the lpd source from
ftp.uu.net where they are kept in /systems/unix/bsd-sources/lpd
and have a look at the documentation which comes with it.
Finally, I have included a copy of a filter program I use here
which acts to carry out conversion for a PostScript filter attached
to ttya of one of our workstations. Here is its printcap entry:

ea1alp|lab1|lp0|lp:\
        :lp=/dev/ttya:\
        :br#9600:\
        :ms=-parity,onlcr,ixon,decctlq:\
        :sd=/var/spool/lpd/lp0:\
        :pl#66:pw#80:\
        :if=/usr/lib/t2ps:sh:\
        :af=/var/adm/lpd-acct:\
        :lf=/var/adm/lpd-errs:

Note that the filter is on if so that a banner can be generated
per job. (Manual tells you the way lpd gives the filter arguments
such as names and hosts which this "if" filter uses) Finally, here
is the C code for t2ps which is a (MUCH MODIFIED BY ME) version of
text2ps by Stephen Frede. Notice that it also logs usage to /var/adm/lpd-acct.

/*
        t2ps
        As the original described below with modifications to act as
        an input filter under unix lp systems. Creates a simple
        banner page with login name and host of the job.
        Uses -H for horizontal spacing instead of -h as
        text2ps did to distinguish from the -h <hostname>
        option supplied by the lp daemon. Writes accounting
        information to an accounts file whose name is supplied
        as the last argument when the filter is started.
        Filtering is switched off if first record starts
        with the customary %! hence will treat PostScript
        text properly. If you want to print PostScript files
        as text then you must prepend a blank line or something!
        T.P.Morrison. University of Liverpool May 1991.
        
*/

/*
 * text2ps
 *
 * Convert plain text to postscript
 * - Stephen Frede, UNSW, Australia
 */

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#define TRUE 1
#define FALSE 0
#define INCH 72.0 /* no. postscript units / inch */
#define CM 28.35 /* postscript units / cm */
#define NEW_PAGE 014 /* ^L forces a new page */

#define OPAGEOFFSET (1.0*CM) /* default hor offset if option used */
#define DTOPMARGIN (0.0*CM) /* default top margin */
#define OTOPMARGIN (1.5*CM) /* default top margin if option used */
#define DFONTSIZE 10.0 /* default font size (in points) */
#define OFONTSIZE 12.0 /* default font size if option used */
#define CHARSPERLINE 10000 /* no. of chars/line */
#define LINESPERPAGE 10000 /* no. of lines/page */
#define ROTATION 0.0 /* default orientation */
#define FONT "Courier"
#define TABSIZE 8

/* typedef char int; */

FILE *ostr,*astr; /*Output and accounts*/

char usage[] = "Valid t2ps options:\n\t-r[angle]\n\t-f[font]\n\t-s[size]\n\t-H[space]\n\t-p[pitch]\n\t-o[offset]\n\t-oe[offset]\n\t-m[topmargin]\n\t-w[width]\n\t-l[length]\n\t-v\n\t-?\n";
char aferr[] = "Filter t2ps: Can't open this accounting file: %s\n";

char name[8]="nobody"; /*Login name*/
char host[40]=""; /*Host name*/
char acctfile[40]=""; /*Accounts file*/
char starttime[40]; /*Job start time produced in logstart*/

int tabsize,charsperline, /* tab spacing in # chars, # chars per line */
        linesperpage; /* # lines per page */
int numbytes;

main(argc, argv)
int argc;
char **argv;
{
        int status = 0; /* exit status (no. errors occured) */
        float opageoffset,
                epageoffset,
                topmargin,
                fontsize,
                linepitch,
                spacing,
                rotation;
        char *fontname;
        FILE *istr;
        double atof();

        astr=NULL;
        numbytes=0;
        fontsize = DFONTSIZE;
        linepitch = 0.0;
        opageoffset = 0.0;
        epageoffset = 0.0;
        topmargin = DTOPMARGIN;
        spacing = 0.0;
        tabsize = TABSIZE;
        charsperline = CHARSPERLINE;
        linesperpage = LINESPERPAGE;
        rotation = ROTATION;
        fontname = FONT;
        ostr = stdout;
        argv++; /* skip program name */
        while(*argv && **argv == '-')
        {
                char c;

                (*argv)++; /* skip the '-' */
                c = **argv; /* option letter */
                (*argv)++; /* skip option letter */
                switch(c)
                {
                        case 'i': /*Indent -Treat as offset for now. TPM*/
                        case 'o': /* offset */
                                if (**argv != 'e') {
                                        if(**argv == '\0')
                                                opageoffset = OPAGEOFFSET;
                                        else
                                                opageoffset = atof(*argv) * CM;
                                        epageoffset = opageoffset;
                                        }
                                else {
                                        (*argv)++;
                                        if (**argv == '\0')
                                                epageoffset = OPAGEOFFSET;
                                        else
                                                epageoffset = atof(*argv) * CM;
                                        }
                                break;

                        case 'm': /* top margin */
                                if(**argv == '\0')
                                        topmargin = OTOPMARGIN;
                                else
                                        topmargin = atof(*argv) * CM;
                                break;

                        case 'r': /* rotation */
                                if(**argv == '\0')
                                        rotation = 90.0;
                                else
                                        rotation = atof(*argv);
                                break;

                        case 'p': /* pitch (line spacing) */
                                linepitch = atof(*argv);
                                break;

                        case 's': /* font size */
                                if(**argv == '\0')
                                        fontsize = OFONTSIZE;
                                else
                                        fontsize = atof(*argv);
                                break;

                        case 't': /* tab size */
                                if(**argv == '\0')
                                        tabsize = 4;
                                else
                                        tabsize = (int) atof(*argv);
                                break;

                        case 'f': /* font */
                                if(**argv == '\0')
                                        fontname = "Times-Roman";
                                else
                                        fontname = *argv;
                                break;

                        case 'h': /*Host name*/
                                argv++;
                                strncpy(host,*argv,40);
                                break;
                                
                        case 'H': /* horizontal spacing */
                                if(**argv == '\0')
                                        spacing = 0.25;
                                else
                                        spacing = atof(*argv);
                                break;

                        case 'w': /* linewidth (chars per line) */
                                if(**argv == '\0')
                                        charsperline = 72;
                                else
                                        charsperline = (int) atof(*argv);
                                break;

                        case 'l': /* lines per page) */
                                if(**argv == '\0')
                                        linesperpage = 60;
                                else
                                        linesperpage = (int) atof(*argv);
                                break;

                        case 'n': /*Login name*/
                                argv++;
                                strncpy(name,*argv,8);
                                break;
                        
                        case 'v': /* version # */
                                fprintf(stderr,"Version 1.04\n");
                                exit(status);
                                break;

                        case '?': /* usage - options */
                                fprintf(stderr, usage);
                                exit(status);
                                break;

                        default:
                                (*argv)--; (*argv)--;
                                fprintf(stderr, "Illegal option: [%s]\n",
                                        *argv);
                                (*argv)++; (*argv)++;
                                status++;
                                break;
                }
                argv++;
        }

        if(status)
        {
                fprintf(stderr, usage);
                exit(status);
                /* NOTREACHED */
        }
        if(linepitch == 0)
                linepitch = fontsize + 1;
        spacing *= fontsize;

        if(*argv) { /* There was a final argument
                 - Assume to be an accounting file */
                astr=fopen(*argv,"a"); /*Append accounting information to this file*/
                if (astr==NULL) {
                        fprintf(stderr,aferr,*argv);
                }
        }

/*THIS IS WHERE ALL THE WORK HAPPENS*/
        logstart();
        init(fontsize, opageoffset, epageoffset, topmargin, linepitch, rotation, fontname, spacing,name,host);
        process(stdin);
        fclose(istr);
        putc('\004', ostr);
        fclose(ostr);
        logfinish(status);
        fclose(astr);
        
        exit(status);
}
/*-------------------------------------------------------------------------*/
process(istr)
FILE *istr;
{
        register char ch;
        register int x, /* used for tab calculations and folding */
                        linenum;
        char firstpair[2];
        int firstline;
        
        *firstpair='\0';
         
        linenum = 1;
        x = 0;
        
        while((ch=getc(istr)) != EOF)
        {
                /*PostScript FILES ONLY*/
                if (numbytes<=1) { /*PostScript trip if first 2 bytes are %!*/
                
                        firstpair[numbytes]=ch;
                        if (numbytes==1) {
                                if (strncmp(firstpair,"%!",2)==0) { /*IS PostScript*/
                                        fprintf(ostr,"null) pop\n"); /* Must close
                                                                assumed string
                                                                and pop from
                                                                stack.*/
                                        fprintf(ostr,"%%!");
                                        while ((ch=getc(istr)) != EOF){
                                                putc(ch,ostr);
                                                numbytes++;
                                        }
                                        return(0);
                                }
                        }
                }
                
                /*TEXT FILES ONLY*/
                if (!numbytes) putc('(',ostr); /*Assume a string start needed*/
                numbytes++;
                
                if(ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != NEW_PAGE)
                {
                        ch = '?';
                }
                if(ch == '\t')
                {
                        int n = x + tabsize - (x % tabsize);

                        while(x < n) {
                                        pch(' ');
                                        x++;
                                }
                }
                else if(ch == '\n')
                {
                        fprintf(ostr, ") n\n");
                        linenum = linenum + 1;
                        if (linenum > linesperpage) {
                                fprintf(ostr,"p\n");
                                linenum = 1;
                        }
                        x = 0;
                        putc('(', ostr);
                }
                else if(ch == '\r')
                {
                        fprintf(ostr, ") r\n");
                        x = 0;
                        putc('(', ostr);
                }
                else if(ch == NEW_PAGE)
                {
                        fprintf(ostr, ") n p\n");
                        linenum = 1;
                        x = 0;
                        putc('(', ostr);
                }
                else
                {
                        if (x >= charsperline) {
                                fprintf(ostr, ") n\n");
                                linenum = linenum + 1;
                                if (linenum > linesperpage) {
                                        fprintf(ostr,"p\n");
                                        linenum = 1;
                                }
                                x = 0;
                                putc('(', ostr);
                        }
                        pch(ch);
                        x++;
                }
        }
        fprintf(ostr, ") n p\n\f");
}

/*----------------------------------------------------------------*/

char *inittab[] = {
        /* print a page and start a new one */
        "/p",
        "{ 0.0 coffset sub 0 translate",
        " /temp coffset def",
        " /coffset noffset def",
        " /noffset temp def",
        " coffset 0 translate",
        " copypage erasepage newpath 0 pgtop moveto",
        "} def",
        "/n",
        /* show the string given as an arg */
        "{ spacing 0 3 -1 roll ashow",
        /* now move down a line; linepitch is -'ve */
        " 0 linepitch rmoveto",
        /* save the new y posn */
        " /y currentpoint exch pop def",
        /* test if the next line would be below the bottom margin */
        " y 0 lt",
        /* if so, print the page, and move to the top of a new page */
        " { p }",
        /* else go to where the next line is due to start */
        " { 0 y moveto } ifelse",
        "} def",
        "/r",
        /* show the string given as an arg */
        "{ spacing 0 3 -1 roll ashow",
        /* save y */
        " /y currentpoint exch pop def",
        /* and then move to the beginning of the current line */
        " 0 y moveto",
        "} def",
        (char *)0 };

/*----------------------------------------------------------------*/
init(fontsize, opageoffset, epageoffset, topmargin, linepitch, rotation, fontname, spacing, uname, hostname)
float fontsize,
        opageoffset,
        epageoffset,
        topmargin,
        linepitch,
        spacing,
        rotation;
char *fontname;
char *uname,*hostname;
{
        register char **p;

        fprintf(ostr, "\004\n");
        
        fprintf(ostr, "%%!t2ps\n"); /* <--- This added by T.P.Morrison.
                                        May 1991. University of Liverpool*/

/*=======================================================================*/
  fprintf(ostr,"%% ******Simple error handler by T.P.Morrison 1991:\n");
  fprintf(ostr,"/newline\n");
  fprintf(ostr,"{currentpoint 20 sub 20 exch moveto pop currentpoint 100 lt exch pop\n");
  fprintf(ostr,"{20 790 moveto} if } bind def\n");

  fprintf(ostr,"errordict /handleerror %% Independent error handling\n");
  fprintf(ostr,"{\n");
  fprintf(ostr,"$error begin\n");

  fprintf(ostr,"newerror\n");
  fprintf(ostr,"{\n");
  fprintf(ostr,"/#copies 1 def\n");
  fprintf(ostr,"initmatrix\n");
  fprintf(ostr,"/str 512 string def\n");
  fprintf(ostr,"/Courier findfont 12 scalefont setfont\n");
  fprintf(ostr," 20 770 moveto (Error: ) show\n");
  fprintf(ostr," /Courier-Bold findfont 12 scalefont setfont\n");
  fprintf(ostr," errorname str cvs show\n");
  fprintf(ostr,"/Courier findfont 12 scalefont setfont\n");
  fprintf( ostr," ( Command: ) show\n");
  fprintf(ostr," /Courier-Bold findfont 12 scalefont setfont\n");
  fprintf(ostr,"/command load str cvs show newline\n");
  fprintf(ostr," newline\n");

  fprintf(ostr,"/Courier findfont 12 scalefont setfont\n");
  fprintf(ostr,"(Oper. stack dump: ) show newline\n");
  fprintf(ostr," /Courier-Bold findfont 12 scalefont setfont\n");
  fprintf(ostr," ostack {str cvs show newline} forall newline\n");

  fprintf(ostr,"/Courier findfont 12 scalefont setfont \n");
  fprintf(ostr,"(Exec. stack dump: ) show newline\n");
  fprintf(ostr,"/Courier-Bold findfont 12 scalefont setfont \n");
  fprintf(ostr,"estack {str show newline} forall\n");
  fprintf(ostr,"/newerror false def\n");
  fprintf(ostr,"showpage\n");
  fprintf(ostr,"stop\n");
  fprintf(ostr,"} if\n");

  fprintf(ostr,"} bind put\n");
/*=======================End of error handler============================*/

        p = inittab;
        while(*p)
                fprintf(ostr, "%s\n", *p++);

        /*Print header page T.P.M.*/
        fprintf(ostr,"/Courier findfont 48 scalefont setfont\n");
        fprintf(ostr,"20 500 moveto (User: ) show\n");
        fprintf(ostr,"/Times-Bold findfont 48 scalefont setfont\n");
        fprintf(ostr,"(%s) show\n",uname);
        fprintf(ostr,"/Courier findfont 24 scalefont setfont\n");
        fprintf(ostr,"20 450 moveto (Host: %s) show\n",hostname);
        fprintf(ostr,"20 425 moveto\n");
        fprintf(ostr,"(Started: %s) show\n",starttime);
        fprintf(ostr,"/Times-Italic findfont 18 scalefont setfont\n");
        fprintf(ostr,"20 380 moveto\n");
        fprintf(ostr,"((c) IRC in Surface Science, University of Liverpool May 1991) show showpage\n");
        
        
        fprintf(ostr, "/%s findfont %.1f scalefont setfont\n",
                fontname, fontsize);
        fprintf(ostr, "/linepitch %.1f def\n", -linepitch);
        fprintf(ostr, "/spacing %.1f def\n", spacing);
        fprintf(ostr, "/coffset %.1f def\n", opageoffset + 4);
        fprintf(ostr, "/noffset %.1f def\n", epageoffset + 4);
        /* apply rotation transformation, if any */
        if(rotation != 0.0)
                fprintf(ostr, "%.1f rotate\n", rotation);
        /* get current imageable area */
        fprintf(ostr, "clippath pathbbox\n");
        /* save the upper right y coordinate */
        fprintf(ostr, "/pgtop exch def\n");
        /* save lower left y; translate origin to lower left */
        fprintf(ostr, "pop /y exch def y translate\n");
        /* subtract old lower left from upper right to get top of page */
        /* then subtract top margin to set top of page */
        fprintf(ostr, "/pgtop pgtop y sub %.1f sub linepitch add def\n", topmargin);
        /* apply horizontal offset, if any */
        /* unfortunately, a slight fudge factor is required here */
        fprintf(ostr, "coffset 0 translate\n");
        /* move to top of page, ready to start printing */
        fprintf(ostr, "newpath 0 pgtop moveto\n");
}
/*----------------------------------------------------------------*/
pch(ch)
int ch;
{
        if(ch < ' ' || ch > '~')
                fprintf(ostr, "\\%3.3o", ch);
        else
        {
                if(ch == '(' || ch == ')' || ch == '\\')
                        putc('\\', ostr);
                putc(ch, ostr);
        }
}
/*----------------------------------------------------------------*/
double atof(s) /* convert string to double */
char s[];
{
     double val, power;
     int i;

     for (i=0; s[i]==' ' || s[i]=='\t'; i++) ; /* skip white space or tabs */
     if (s[i] == '+' || s[i] == '-') /* sign -if '-', ignore it */
         i++;
     for (val = 0; s[i] >= '0' && s[i] <= '9'; i++)
          val = 10 * val + s[i] - '0';
     if (s[i] == '.') {
         i++;
         for (power = 1; s[i] >= '0' && s[i] <= '9'; i++) {
              power = power /10;
              val = power * (s[i] - '0') + val;
         }
     }
     return (val);
}

/*----------------------------------------------------------------*/
logstart()
{
        struct tm *newtime;
        time_t aclock;
        int l;
        
        time(&aclock); /*Get system time*/
        newtime=localtime(&aclock);
        strcpy(starttime,asctime(newtime));
        /*Remove \n or other control chars*/
        l=strlen(starttime)-1;
        for (; l>=0; l--) if (iscntrl((int)starttime[l])) starttime[l]=' ';
        
        if (astr!=NULL) {
                fprintf(astr,"%s %s %s ",starttime,name,host);
                                                                /*(\n from
                                                                logfinish)*/
        }
        return(0);
}
/*----------------------------------------------------------------*/
logfinish(status)
{
        if (astr!=NULL) {
                fprintf(astr,"%d bytes. Completion code=%d\n",numbytes,status);
        }
        return(0);
}
/*----------------------------------------------------------------*/

***********************************************************************
shevett@sparc.bighouse.unipress.com (Dave Shevett) writes:

Hi Fred... Pretty easy actually - i wrote a filter for our printers here to
strip off the first ^D in a print job (something the DOS Windows driver does..)

Here's what it looked like:

[/etc/printcap]
iprdos|IMAGEN dos:\
        :lp=/dev/null:if=/usr/local/lib/iprdos.filt:

(this entry creates a new printer called 'iprdos' - the script 'iprdos.filt'
is run reading standard input as the print job. The script is simply:

[/usr/local/lib/ipsdos.filt]
sed '1s///'|/usr/ucb/lpr -Pipr

Hope this helps some - I'm not sure where standard output goes from the
script. I just re-submit it as another print job :)

***********************************************************************
poul@nilu.no (Poul Sorensen) writes:

Here is an input (assigned using the if= in /etc/printcap).
It is use to avoid printing PostScript documents on a stupid
line printer (Canon).
it is invoked as
inputfilter [-c] -w<width> -l<length> -i<indent> -n <login> -h <host> [<accountingfile>]
-c iff lpr -l (i.e.: don't interpret control characters)
<width> and <length> are from the pw= and pl= fields of /etc/printcap

output fileters are invoked:
outputfilter -w<width> -l<length>

other filters:
filter -x<width> -y<length> -n <login> -h <host> [<accountingfile>]
where <width> and <length> are from th epx= and py= ffields of /etc/printcap

Filters has stdin to data to be printed, stdout to printer and stderr to lf= (from /etc/printcap)
Filters should return:
0 iff no errors
1 iff job should be reprinted
2 if job should be thrown away

lprm(1) sends a SIGINT when job is aborted (catch to cleanup)

see also System & Network Administration: Adding Hardware to your System (11.5 ??)

                                 hilsen/regards

                                     Poul.

---
#define E_MAIL  Poul.Sorensen@nilu.no
#define CC      +-1     /* the computer constant - very usefull when writing loops. */
#include <std/disclaim.h>

#!/bin/sh VER="@(#)canon_if 1.7 10/16/92" LINO=12 if [ "$1" = "-c" ]; then # Print Control characters as is # I would have done that anyway, # therefore I interpret -c as # accept PostScript without complaining # (and hope that that's what the user want's :-) shift LINO=0 fi WIDTH="$1" LENGTH="$2" INDENT="$3" # $4=-n USERNAME="$5" # $6=-h HOSTNAME="$7" shift; shift; shift; shift; shift; shift; shift; if [ $# -eq 1 ]; then ACCOUNTING="$1"; shift # Very simple accounting: echo " 1.00 ${HOSTNAME}:${USERNAME}" >> $ACCOUNTING fi ISPS="" while [ $LINO -gt 0 ] do LINO=`expr $LINO - 1` L="`line`" echo "$L" PS="`echo $L | egrep '^%(!PS| FrameMaker PostScript)'" if [ ! -z "$PS" ]; then ISPS="$PS" fi done if [ ! -z "$ISPS" ]; then # It's a PostScript file (and we don't want that) echo "____________________________________________" echo "" echo "" echo "Dear ${USERNAME}" echo "" echo "" echo "I (canon) can not print PostScript very nice" echo "" echo "" echo "Please use a PostScript printer..." echo "" echo "____________________________________________" date 1>&2 echo " $0:" 1>&2 echo " [$VER]" 1>&2 echo " $USERNAME@$HOSTNAME" 1>&2 echo " Ignoring PostScript input" 1>&2 echo ' "'"$ISPS"'"' 1>&2 echo "" 1>&2 else # It's NOT a PostScript file (or maybe the user wanted that # and indicated that with the -i option to lpr(1)) cat - fi echo " " exit 0

*************************************************************************



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:07:48 CDT