forked from pool/cups-backends
206 lines
7.1 KiB
Plaintext
206 lines
7.1 KiB
Plaintext
|
#!/usr/bin/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.openprinting.org/cups-doc.html and the additional
|
||
|
# instructions below.
|
||
|
|
||
|
# beh - Backend Error Handler
|
||
|
#
|
||
|
# Copyright 2005 Till Kamppeter <till.kamppeter@gmail.com>
|
||
|
#
|
||
|
# 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 || "/usr/lib/cups/backend");
|
||
|
|
||
|
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
|
||
|
my $tmpDir = $ENV{TMPDIR};
|
||
|
$tmpDir ||= "/tmp";
|
||
|
$tempFile = "$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;
|