Summary: writing lpfilters

John Stoffel (jfs@fluent.com)
Tue, 20 May 1997 16:26:06 -0400 (EDT)

Well, I've solved my problem with printing using the LP filters to a
Canon CLBP360PS printer. What I was doing was calling the paper type
'postscript_tr' since I wanted to use the transparency (bypass) tray
on the printer. It turns out that the LPD daemon on the printer
itself doesn't like the name 'postscript_tr'. Once I changed the
output type to be 'PS', the conversion happened properly and the
printer accepted the print job.

>>>>> "John" == John Stoffel <jfs@fluent.com> writes:

John> I'm trying to write a filter program for the SYSV lp print system on
John> my Solaris 2.5.1 Ultra 140 Server. I've got the filter setup like
John> this:

John> Input types: postscript
John> Output types: manfeed_postscript
John> Printers: color,color_tr
John> Filter type: slow
John> Command: /usr/lib/lp/bin/canon_manfeed

John> And the program I'm running is a little C program that inserts some
John> postscript code after the '%%EndComments' line of a PS document. It
John> reads STDIN and writes to STDOUT. The filter writes to STDERR if
John> there's a problem, otherwise it returns 0. I've appended the program
John> at the end of this message.

John> This works correctly when it can't find the %%EndComments line in the
John> file and reports an error. But when I print a file with the proper
John> line, it comes back with:

John> encountered an error during filtering.
John> Filtering stopped with an exit code of 1.

John> But the _only_ filter that should be called is the above one since the
John> file I'm sending is postscript and is being converted properly.

John> Now when I change the filter speed to 'fast' I don't get any
John> errors, but it doesn't print the file properly since it doesn't take
John> input media from the proper tray. Nor does it correctly detect and
John> report errors from files that don't have the '%%EndComments' line.

John> Does anyone have any example filters written in C that they'd like to
John> share? Or in perl or sh? I'd also love to know how the 'lp' system
John> determines what input type a file is.

John> Here's the source code:

John> /*
John> * jks with help from everyone
John> */
John> #include <stdio.h>

John> #define BUFSIZE 1024
John> #define kEndCommentStrLen 12

John> main(argc,argv)
John> int argc;
John> char **argv;
John> {
John> char buf[BUFSIZE];
John> char endCommentStr[kEndCommentStrLen];
John> int c,n,matches,ok;

John> /*
John> * Setup
John> */
John> strcpy(endCommentStr, "%EndComments");

John> /*
John> * copy input to output looking for end of comment section
John> */
John> while( (c = getc(stdin)) != EOF && c == '%')
John> {

John> /* move input to output */
John> putc(c,stdout);

John> matches = 0;
John> ok = 0;
John> while( (c = getc(stdin)) != EOF)
John> {
John> putc(c,stdout);

John> if(c == endCommentStr[matches])
John> matches++;

John> if(matches == kEndCommentStrLen)
John> {
John> /* append the header */
John> fprintf(stdout,"\n\n");
John> fprintf(stdout,"userdict /FieryOverride known not \n");
John> fprintf(stdout,"{ (Resource/ProcSet/FieryOverride) run } \n");
John> fprintf(stdout,"if countdictstack [ { FieryOverride begin overridedict begin \n");

John> /* now the ppd code */
John> fprintf(stdout,"1 dict dup /ManualFeed true put setpagedevice \n");

John> /* append the footer */
John> fprintf(stdout,"end end} \nFieryOverride /featurecleanup get exec \n");

John> /* break */
John> matches = 0;
John> ok = 1;
John> }

John> if(c == 0xa || c == 0xd)
John> break;
John> }
John> }
John> if(c != EOF)
John> putc(c,stdout);

John> /* Munge the rest of the file to the output */
John> while( (n = fread(buf,1,BUFSIZE,stdin)) > 0)
John> fwrite(buf,1,n,stdout);

John> /* return our status */
John> if (!ok) {
John> fprintf(stderr,"Error: never found %%EndComments in the input file.\n");
John> return 1;
John> }
John> else {
John> return 0;
John> }
John> }

John> Well, I tried to write the above in Perl since it was quicker and
John> easier to do, this is what I've got:

John> #!/usr/local/solaris/bin/perl
John> #
John> # My stab at writing an lpfilter program. This one is stupid and will
John> # bomb if you're missing %%EndComments in the file. Oops!
John> #

John> # suck STDIN and process
John> while(<>) {
John> # print each line we get
John> print $_;

John> # if we match, print to STDOUT our postscript code.
John> if (/^%%EndComments/ && ($once < 1)) {
John> print "\n";
John> print "userdict /FieryOverride known not { \n";
John> print " (Resource/ProcSet/FieryOverride) run }\n";
John> print " if countdictstack [ { \n";
John> print " FieryOverride begin overridedict begin \n";
John> print " 1 dict dup /ManualFeed true put setpagedevice\n";
John> print " end\n";
John> print "end }\n";
John> print "FieryOverride /featurecleanup get exec\n\n";
John> print "\n/Times-Roman findfont 20 scalefont setfont 72 250 moveto 45 rotate (Did this make it?) show\n\n";
John> $once++;
John> }
John> }
John> exit(0);

John> This also has problems and doesn't work for simple test cases. I'm
John> really getting frustrated here.

John> Thanks,
John> John

John> John Stoffel - Unix Systems Administrator - Fluent, Inc.
John> jfs@fluent.com - http://www.fluent.com - 603-643-2600 x341
John> Kill your Television