Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Mar 2001 13:53:58 +1000 (EST)
From:      <andrew@ugh.net.au>
To:        <questions@freebsd.org>
Subject:   Printing loops
Message-ID:  <Pine.BSF.4.32.0103071230230.34937-100000@starbug.ugh.net.au>

next in thread | raw e-mail | index | archive | help
Hi,

I've just got printing going on an HP LaserJet 4050N and I thought I'd
send this to the archives to make it quicker for others trying the same
thing.

The LaserJet runs its own lpd server. It seems there are 2 virtual
printers controlled by the lpd server...RAW which accepts postscript jobs
and text which accepts text jobs.

I set up 2 printers in my printcap file...blah-ps and blah-text.

I set up a perl script as the if filter for blah-ps that checks the first
two chars of the print job and if they aren't %! runs lpr -Pblah-text and
writes the data to that process. If they are %! it just copies its input
to stdout.

I found what might be a bug in lpd at this point. If a filter produces no
output (because it sent all the data to lpr -Pblah-text) lpd tries to
reprint the job even if the filter exited with the exit value 0. I have
worked around that by guarenteeing output.

I attach below my printcap entries and the perl script.

Thanks,

Andrew

--

lp|blah|blah-ps|HP LaserJet 4050N (Blah):\
        :sh:\
        :if=/usr/local/libexec/hpfilter:\
        :sd=/var/spool/lpd/blah-ps:\
        :lp=:\
        :mx#0:\
        :rp=RAW:\
        :rm=blah.domain.au:

text|blah-text|HP LaserJet 4050N (Blah):\
        :sh:\
        :sd=/var/spool/lpd/blah-text:\
        :lp=:\
        :mx#0:\
        :rp=text:\
        :rm=blah.domain.au:



#!/usr/bin/perl -w
# $Id$

# Exit values:
#
# 0 - Printed fine
# 1 - Try to reprint
# 2 - Fatal error - give up

$block_size = 2048;			  # bytes to read/write at a time
$lpr = '/usr/bin/lpr';		  # path to lpr
$text_print = 'blah-text'; # name of text printer

# Catch SIGPIPE (in case lpr -P fails for text files)
$SIG{'SIGPIPE'} = \&sigpipe;

# Use syslog to report problems
use Sys::Syslog qw(:DEFAULT setlogsock);

# open log
setlogsock('unix');
openlog('hpfilter', 'pid', LOG_LPR);

syslog(LOG_DEBUG, 'starting up');

# Get the first 2 bytes
if (! defined(read(STDIN, $buff, 2))) {
	syslog(LOG_ERR, 'first read failed: %m');
	exit(1); # might work next time
}

if ($buff ne '%!') {
	syslog(LOG_DEBUG, 'non ps file, swapping modes');
	# Not a PS job so send to text printer. To keep lpd happy we have to
	# produce some output however so we'll send the following PS job.
	print('%!PS');

	$text_job = 1;	# remember we are printing text

	if (! open(STDOUT, "|$lpr -P$text_print")) {
		syslog(LOG_ERR, 'fork failed: %m');
		exit(1); # might work next time
	}
} else {
	# PS file
	$text_job = 0;
}

# print first 2 chars
print($buff);	# of course it wont fail...
# print everything else
while (defined($rv = read(STDIN, $buff, $block_size)) and ($rv > 0)) {
	print $buff or do {
		syslog(LOG_ERR, 'print failed: %m');
		exit(1); # might work next time
	};
}

if ($text_job) {
	# If we duped STDOUT we should close it and collect the return value
	if (! close(STDOUT)) {
		if ($! == 0) {
			# lpr exited with non 0 status
			syslog(LOG_ERR, 'lpr exited with code ' . ($? >> 8));
			exit(2); # probably the text printer doesn't exist
		} else {
			# close failed (something is very wrong)
			syslog(LOG_ERR, 'close failed: %m');
			exit(1); # might work next time
		}
	}
}

syslog(LOG_DEBUG, 'shutting down');

# we have finished logging now
closelog();

# everything worked
exit(0);


# signal handler for SIGPIPE (something went wrong writing to lpr for a text
# job)
sub sigpipe {

	syslog(LOG_ERR, 'received SIGPIPE'); # is this safe?
	exit(2); # or this for that matter
}


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.32.0103071230230.34937-100000>