summaryrefslogtreecommitdiff
path: root/beh.in
diff options
context:
space:
mode:
Diffstat (limited to 'beh.in')
-rwxr-xr-xbeh.in203
1 files changed, 203 insertions, 0 deletions
diff --git a/beh.in b/beh.in
new file mode 100755
index 0000000..1cc2b09
--- /dev/null
+++ b/beh.in
@@ -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;