diff options
Diffstat (limited to 'beh.in')
-rwxr-xr-x | beh.in | 203 |
1 files changed, 203 insertions, 0 deletions
@@ -0,0 +1,203 @@ +#!@PERL@ +# The above Perl path may vary on your system; fix it!!! -*- perl -*- + +# beh - Backend Error Handler + +# A wrapper for CUPS backends to make error handling configurable + +# Usually, if a CUPS backend exits with an error status other than zero +# (for example if a printer is not turned on or not reachable on the +# network), CUPS disables the print queue and one can only print again +# if a system administrator re-enables the queue manually. Even restarting +# CUPS (or rebooting) does not re-enable disabled queues. +# +# For system administrators this can get annoying, for newbie users +# who are not aware of this problem it looks like that CUPS is severely +# broken. They remove and re-install print queues, getting on the nerves +# of distro install support, people, or even switch back to a proprietary +# operating system. +# +# This script makes the handling of such backend errors configurable, so +# that the problem can easily be worked around. The new possibilities are: +# +# - Let queues simply not being disabled. Simple approach, but job gets +# lost. +# +# - Repeat a given number of times. +# +# - Repeat infinitely often, until the job gets finally through. This +# is the standard of LPRng, and it eliminates loss of the job. +# +# - The interval between two attemts to run the backend can also be +# configured. +# +# - Configuration is done independently for each print queue. So local +# printers and network printers can be treated differently. + +# Save this file in your CUPS backend directory, usually +# /usr/lib/cups/backend/ or /usr/local/lib/cups/backend/ +# +# Mark this filter world-readable and world-executable. Restart CUPS to +# make the new backend known to the spooler. +# +# See http://www.linuxprinting.org/cups-doc.html and the additional +# instructions below. + +# beh - Backend Error Handler +# +# Copyright 2005 Till Kamppeter <till.kamppeter@gmx.net> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. + +# Usage: +# +# cp beh /usr/lib/cups/backend/ +# chmod 755 /usr/lib/cups/backend/beh +# killall -HUP cupsd (or "/etc/init.d/cups restart") +# lpadmin -p <queue name> -E -v beh:/<dd>/<att>/<delay>/<originaluri> +# +# with +# <queue name>: The name of your print queue +# <dd>: Don't Disable, if "1", beh always exits with zero +# status, so the queue gets never disabled when the +# original backend exits with an error. "0" carries +# the error status of the last call of the backend +# (after <att> retries) on to CUPS, so the queue +# usually gets disabled. +# <att>: Attempts, number of attempts to recall the backend +# in case of an error. "0" means infinite retries. In +# this case <dd> gets meaningless. +# <delay>: Delay between two attempts to call the beckend, to +# be given in seconds and as an integer number. +# Meaningless if <att> is one. +# <originaluri>: The original URI, which your queue had before. +# +# All parameters, especially, <dd>, <att>, and <delay> have always to +# be specified, even if one of them is meaningless due to the setting of +# the others. +# +# beh works with every backend except the "hp" backend of HPLIP. +# +# Example URIs: +# +# beh:/1/3/5/socket://printer:9100 +# +# On the network printer with host name "printer" it is tried to access +# 3 times with 5 second delays between the attempts. If the job still +# fails, the queue is not disabled (and the job discarded). +# +# beh:/0/10/60/socket://printer:9100 +# +# Retry 10 times in one minute intervals, disable the queue when still +# not succeeding. +# +# beh:/1/0/60/usb://Brother/HL-5040%20series +# +# On a Brother HL-5040 on the USB try infinitely often until the printer +# comes back, in intervals of one minute. This way the job does not get +# lost when the printer is turned off and one can intendedly delay +# printing by simply switching off the printer. The ideal configuration +# for desktop printers and/or home users. + +# Acknowledgement +# +# Thanks to Jeff Hardy (hardyjm at potsdam dot edu) for writing the +# "accsnmp" wrapper backend (http://fritz.potsdam.edu/projects/cupsapps/). +# This backend showed me the trick how to write a universal wrapper +# backend in a scripting language. + +use strict; + +$0 =~ m!^(.*)/([^/]+)\s*$!; +my $progname = ($2 || $0); +my $progpath = ($1 || "@CUPS_BACKENDS@"); + +if (!$ARGV[0]){ + print "network $progname \"Unknown\" \"Backend Error Handler\"\n"; + exit 0; +} + +if (scalar(@ARGV) < 5 || scalar(@ARGV) > 6){ + print STDERR "ERROR: Usage: $progname job-id user title copies options [file]\n"; + exit 1; +} + +my ($jobID, $userName, $jobTitle, $copies, $printOptions, $printFile) = + @ARGV; + +my $tempFile; +if (!$printFile) { + + my $jid = $jobID; + my $uid = $userName; + $jid =~ s/\W//g; #sanity check + $uid =~ s/\W//g; #sanity check + $tempFile = "$ENV{TMPDIR}/$jid-$uid-cupsjob$$"; + + open (OUT, ">$tempFile") or die "ERROR: Cannot write $tempFile: $!\n"; + + while(<STDIN>){ + print OUT "$_"; + } + + close OUT; + + $printFile = $tempFile; + + # Backends should only produce multiple copies if a file name is + # supplied (see CUPS Software Programmers Manual) + $copies = 1; + +} + +my $uri = $ENV{DEVICE_URI}; +$uri =~ m!^$progname:/(\d+)/(\d+)/(\d+)/(\S+)$! or + die "URI must be \"beh:/<dd>/<att>/<delay>/<original uri>\"!\n"; +my $dontdisable = $1; +my $attempts = $2; +my $delay = $3; +$uri = $4; +$uri =~ m!^([^:\s]+):!; +my $backend = $1; +$ENV{DEVICE_URI} = $uri; + +# Control by "lpr" command line options, commented out for security +# reasons (user could intendedly make queues being disabled) + +#$printOptions =~ m/\bBackendErrorDisableQueue=(\S*)\b/ && +# ($dontdisable = ($1 =~ /no/i ? 1 : 0)); +#$printOptions =~ m/\bBackendErrorRetries=(\S*)\b/ && ($attempts = $1); +#$printOptions =~ m/\bBackendErrorRetryDelay=(\S*)\b/ && ($delay = $1); +#$printOptions =~ m/\bBackendErrorRetryForever=(\S*)\b/ && +# ($delay = ($1 =~ /yes/i ? 0 : $delay)); + +my $exitvalue; +while($exitvalue = (($uri !~ m!^file:(.*)$!) && ($uri !~ m!^(/.*)$!) ? + system {"$progpath/$backend"} + ($uri, $jobID, $userName, $jobTitle, $copies, + $printOptions, $printFile) : + system ("cat $printFile > $1")) >> 8) { + if ($attempts > 0) { + $attempts --; + last if $attempts == 0; + } + sleep $delay if $delay > 0; +} + +unlink $tempFile if $tempFile; + +$exitvalue = 0 if $dontdisable; +exit $exitvalue; |