From cc93d2f219166ff3047c187526658c36dc9d9b5ab8d7fa6f3a7cc2721ce46d1c Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Mon, 15 Jan 2007 23:08:17 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/cups-backends?expand=0&rev=1 --- .gitattributes | 23 +++ .gitignore | 1 + README-beh.html | 156 ++++++++++++++++++ beh | 203 ++++++++++++++++++++++++ cups-backends.changes | 33 ++++ cups-backends.spec | 83 ++++++++++ cups-pipe.pl | 68 ++++++++ hal.c | 358 ++++++++++++++++++++++++++++++++++++++++++ hpnpf.patch | 95 +++++++++++ hpnpf.tgz | 3 + hpnpf.txt | 92 +++++++++++ ready | 0 12 files changed, 1115 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 README-beh.html create mode 100644 beh create mode 100644 cups-backends.changes create mode 100644 cups-backends.spec create mode 100644 cups-pipe.pl create mode 100644 hal.c create mode 100644 hpnpf.patch create mode 100644 hpnpf.tgz create mode 100644 hpnpf.txt create mode 100644 ready diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/README-beh.html b/README-beh.html new file mode 100644 index 0000000..c820970 --- /dev/null +++ b/README-beh.html @@ -0,0 +1,156 @@ + + +beh - The Backend Error Handler + + + + + + + + + + + +
+ + + + + +
+ beh - + The Backend Error Handler
+
+ + Very annoying with CUPS is that when an error on the communication +between the CUPS backend and the printer occurs, CUPS disables the +print queue and to be able to continue printing an administrator (root +access required) has to re-enable the queue. It is not enough to +simply fix the printer's communication problem (like turning it on, +fixing the network connection, ...).

+ +This is especially a very bad design for desktop/home users. They +often only turn on their printers when they really want to print (to +save energy). Then it happens easily that they send a job and forget +to turn on the printer. CUPS disables the queue and the annoying +re-enabling procedure has to be done. And many users even do not know +about the problem. So the printer does not print and the queue gets +nuked and re-created. Or the people cry on the help forums or at the +installation support of their distributions.

+ +This problem can be easily worked around by installing beh, the +Backend Error Handler. 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 attempts 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. + +

+ +Simply download the +script, copy it into the CUPS backend directory (normally +/usr/lib/cups/backend/), and make it executable with +"chmod 755 beh. Then restart CUPS that it registers the new +backend, usually with "killall -HUP cupsd" or +"/etc/init.d/cups restart". If you did all correctly, there must be a +line containing "beh" in the output of "lpinfo +-v".

+ +beh is a wrapper which is called by CUPS in place of the usual backend, which is called by beh now. This way beh +can, depending on its configuration, repeat the call of the backend or +simply hide the error status of the backend from being seen by the CUPS +daemon.

+ +To make a print queue usinf beh, get root and call a command as follows:

+ +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 (use "lpstat + -v" to get your queue's URI shown).

+ +

+ + 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 + from HPLIP. If beh is + used with the hp backend, the HP Toolbox will not find the + printers any more.

+ + 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.

+ +

+ +Report bugs in linuxprinting.foomatic.devel. +

+ diff --git a/beh b/beh new file mode 100644 index 0000000..0b4d12d --- /dev/null +++ b/beh @@ -0,0 +1,203 @@ +#!/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.linuxprinting.org/cups-doc.html and the additional +# instructions below. + +# beh - Backend Error Handler +# +# Copyright 2005 Till Kamppeter +# +# 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 -E -v beh:/
/// +# +# with +# : The name of your print queue +#
: 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 retries) on to CUPS, so the queue +# usually gets disabled. +# : Attempts, number of attempts to recall the backend +# in case of an error. "0" means infinite retries. In +# this case
gets meaningless. +# : Delay between two attempts to call the beckend, to +# be given in seconds and as an integer number. +# Meaningless if is one. +# : The original URI, which your queue had before. +# +# All parameters, especially,
, , and 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 + $tempFile = "$ENV{TMPDIR}/$jid-$uid-cupsjob$$"; + + open (OUT, ">$tempFile") or die "ERROR: Cannot write $tempFile: $!\n"; + + while(){ + 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:/
///\"!\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; diff --git a/cups-backends.changes b/cups-backends.changes new file mode 100644 index 0000000..4dce3ae --- /dev/null +++ b/cups-backends.changes @@ -0,0 +1,33 @@ +------------------------------------------------------------------- +Wed Mar 22 19:20:19 CET 2006 - lmuelle@suse.de + +- Update beh backend to the current version. +- Add beh documentation derivated from http://www.linuxprinting.org/beh.html. +- Move ncp backend to the ncpfs package. + +------------------------------------------------------------------- +Wed Jan 25 21:35:17 CET 2006 - mls@suse.de + +- converted neededforbuild to BuildRequires + +------------------------------------------------------------------- +Thu Jan 12 15:54:28 CET 2006 - kssingvo@suse.de + +- added backend error handler (beh) (bugzilla#132002) + +------------------------------------------------------------------- +Tue Oct 4 10:23:29 CEST 2005 - jsrain@suse.cz + +- fixed the error handling in the pipe backend (#93480) + +------------------------------------------------------------------- +Mon Sep 19 23:12:59 CEST 2005 - lmuelle@suse.de + +- Don't redirect stdout to stderr in the pipe backend. +- Install the right files, [#117887]. + +------------------------------------------------------------------- +Tue Jul 26 12:47:55 CEST 2005 - kssingvo@suse.de + +- initial version + diff --git a/cups-backends.spec b/cups-backends.spec new file mode 100644 index 0000000..c73d257 --- /dev/null +++ b/cups-backends.spec @@ -0,0 +1,83 @@ +# +# spec file for package cups-backends (Version 1.0) +# +# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany. +# This file and all modifications and additions to the pristine +# package are under the same license as the package itself. +# +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + +# norootforbuild + +Name: cups-backends +BuildRequires: cups-devel hal-devel +Summary: Various Free Backends for the cups Package +License: GPL +Group: Hardware/Printing +Version: 1.0 +Release: 11 +Source0: http://www.srz.de/Members/bla/cups/backend/hpnpf/hpnpf.tgz +Source1: http://www.srz.de/Members/bla/cups/backend/hpnpf/hpnpf.txt +Source2: cups-pipe.pl +Source4: hal.c +Source5: http://www.linuxprinting.org/download/printing/beh +Source6: README-beh.html +Patch0: hpnpf.patch +Requires: cups-libs, dbus-1, hal +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description +This package contains free additional backends for CUPS. + + + +Authors: +-------- + Jiri Srain + Jeffrey Stedfast + +%prep +%setup -c -T +mkdir hpnpf +cd hpnpf +tar xzvvf %{SOURCE0} +cd .. +cp -a %{SOURCE4} . +cp -a %{SOURCE5} beh +cp -a %{SOURCE6} . + +%build +gcc $RPM_OPT_FLAGS -fPIC -fPIE -pie -DDBUS_API_SUBJECT_TO_CHANGE \ + -I%{_includedir}/dbus-1.0/ -I%{_libdir}/dbus-1.0/include/ \ + -ldbus-1 -lhal hal.c -o hal + +%install +mkdir -p $RPM_BUILD_ROOT/%{_libdir}/cups/backend +install -m 755 -D ${RPM_SOURCE_DIR}/cups-pipe.pl $RPM_BUILD_ROOT%{_libdir}/cups/backend/pipe +install -m 755 -D hal $RPM_BUILD_ROOT%{_libdir}/cups/backend/hal +install -m 755 -D beh $RPM_BUILD_ROOT%{_libdir}/cups/backend/beh + +%files +%defattr(-, root,root) +%dir %{_libdir}/cups +%dir %{_libdir}/cups/backend +%{_libdir}/cups/backend/* +%doc README-beh.html + +%changelog -n cups-backends +* Wed Mar 22 2006 - lmuelle@suse.de +- Update beh backend to the current version. +- Add beh documentation derivated from http://www.linuxprinting.org/beh.html. +- Move ncp backend to the ncpfs package. +* Wed Jan 25 2006 - mls@suse.de +- converted neededforbuild to BuildRequires +* Thu Jan 12 2006 - kssingvo@suse.de +- added backend error handler (beh) (bugzilla#132002) +* Tue Oct 04 2005 - jsrain@suse.cz +- fixed the error handling in the pipe backend (#93480) +* Mon Sep 19 2005 - lmuelle@suse.de +- Don't redirect stdout to stderr in the pipe backend. +- Install the right files, [#117887]. +* Tue Jul 26 2005 - kssingvo@suse.de +- initial version diff --git a/cups-pipe.pl b/cups-pipe.pl new file mode 100644 index 0000000..71e4999 --- /dev/null +++ b/cups-pipe.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w + +# +# CUPS backend for printing to any program via pipe +# +# Copyright (c) 2003 SuSE Linux AG, Nuernberg, Germany. +# +# Author: Jiri Srain , 2003 +# + +$scheme = "pipe"; + +if (@ARGV == 0) +{ + + print "file $scheme \"Unknown\" \"Printing to any command via pipe\"\n"; + exit 0; +} + + +# in case of wrong number of arguments: print usage hint +if (@ARGV != 5 && @ARGV != 6) +{ + print STDERR " +Usage: pipe job-id user title copies options [file] + example for device-URI: 'pipe:/path/to/targetcommand' + +Install a printqueue with 'lpadmin -p +-v pipe:/ -E + +"; + exit 1; +} + +if (defined ($ARGV[5])) +{ + $file = $ARGV[5]; +} +else +{ + $file = "-"; +} + +# get file to which the job is "printed" from device URI, so +# so that you can use this backend multiple times, for various +# "pipe" printers... + +$uri = $ENV{"DEVICE_URI"}; + +$arg = $uri; +$arg =~ s/$scheme:(.*)/$1/; + +$cmdln = "/bin/cat $file | $arg"; + +if ($> == 0) +{ + $cmdln = "su -c \"$cmdln \" lp"; +} + +my $exit = system ($cmdln); +if ($exit != 0) +{ + print STDERR "ERROR: Error occurred while executing $cmdln"; +} +exit $exit >> 8; + + + diff --git a/hal.c b/hal.c new file mode 100644 index 0000000..af10c5f --- /dev/null +++ b/hal.c @@ -0,0 +1,358 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast + * Authors: Klaus Singvogel + * + * Copyright 2005 Novell, Inc. (www.novell.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 Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +static LibHalContext * +get_hal_ctx (void) +{ + DBusConnection *connection; + LibHalContext *hal_ctx; + DBusError error; + + if (!(hal_ctx = libhal_ctx_new ())) { + fprintf (stderr, "ERROR: Unable to create HAL context\n"); + return NULL; + } + + dbus_error_init (&error); + if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error))) { + fprintf (stderr, "ERROR: Unable to connect to DBUS: %s\n", error.message); + libhal_ctx_free (hal_ctx); + dbus_error_free (&error); + return NULL; + } + + libhal_ctx_set_dbus_connection (hal_ctx, connection); + + if (!libhal_ctx_init (hal_ctx, &error)) { + fprintf (stderr, "ERROR: Unable to init HAL context: %s\n", error.message); + libhal_ctx_free (hal_ctx); + dbus_error_free (&error); + return NULL; + } + + return hal_ctx; +} + + +/* + * 'list_devices()' - List all HAL printer devices. + */ + +static void +list_devices (void) +{ + LibHalContext *hal_ctx; + char **printers; + int i, n; + + if (!(hal_ctx = get_hal_ctx ())) + return; + + printers = libhal_find_device_by_capability (hal_ctx, "printer", &n, NULL); + + if (n == 0) + printf("direct hal \"Unknown\" \"Hal printing backend\"\n"); + + for (i = 0; i < n; i++) { + char *vendor, *product, *description; + char make_model[1024]; + + /* We only want printers that have device nodes */ + if (!libhal_device_property_exists (hal_ctx, printers[i], "printer.device", NULL)) + continue; + + vendor = libhal_device_get_property_string (hal_ctx, printers[i], "printer.vendor", NULL); + product = libhal_device_get_property_string (hal_ctx, printers[i], "printer.product", NULL); + description = libhal_device_get_property_string (hal_ctx, printers[i], "printer.description", NULL); + + /* Try our hardest to get a good name */ + if (product != NULL) { + if (vendor != NULL) { + snprintf (make_model, sizeof (make_model), "%s %s", vendor, product); + } else { + strncpy (make_model, product, sizeof (make_model) - 1); + make_model[sizeof (make_model) - 1] = '\0'; + } + } else if (description != NULL) { + strncpy (make_model, description, sizeof (make_model) - 1); + make_model[sizeof (make_model) - 1] = '\0'; + } else if (vendor != NULL) { + snprintf (make_model, sizeof (make_model), "%s printer", vendor); + } else { + strcpy (make_model, "Unknown"); + } + + printf ("direct hal://%s \"%s\" \"%s\"\n", printers[i], make_model, + description != NULL ? description : make_model); + + libhal_free_string (vendor); + libhal_free_string (product); + libhal_free_string (description); + } + + libhal_ctx_shutdown (hal_ctx, NULL); + libhal_ctx_free (hal_ctx); +} + +/* + * 'get_device_file()' - Get a device file from a HAL device UDI + */ +static char * +get_device_file (const char *uri) +{ + LibHalContext *hal_ctx; + const char *udi; + char *device; + + if (strncmp (uri, "hal://", 6) != 0) + return NULL; + + if (!(hal_ctx = get_hal_ctx ())) + return NULL; + + udi = uri + 6; + + device = libhal_device_get_property_string (hal_ctx, udi, "printer.device", NULL); + + libhal_ctx_shutdown (hal_ctx, NULL); + libhal_ctx_free (hal_ctx); + + return device; +} + +/* + * 'main()' - Send a file to the specified HAL printer device. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int +main (int argc, char *argv[]) +{ + int fp; /* Print file */ + int copies; /* Number of copies to print */ + char *device; /* Device file to open */ + int fd; /* Device file descriptor */ + ssize_t nwritten; /* Number of bytes written */ + size_t nbytes; /* Number of bytes read */ + size_t tbytes; /* Total number of bytes written */ + char buffer[8192]; /* Output buffer */ + char *bufptr; /* Pointer into buffer */ + struct termios opts; /* Parallel port options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +#if defined(__linux) && defined(LP_POUTPA) + unsigned char status; /* Port status (off-line, out-of-paper, etc.) */ +#endif /* __linux */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf (stderr, NULL); + + /* + * Ignore SIGPIPE signals... + */ + +#ifdef HAVE_SIGSET + sigset (SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset (&action, 0, sizeof (action)); + action.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &action, NULL); +#else + signal (SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGSET */ + + /* + * Check command-line... + */ + + if (argc == 1) { + list_devices (); + return 0; + } else if (argc < 6 || argc > 7) { + fputs ("Usage: URI job-id user title copies options [file]\n", stderr); + return 1; + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) { + fp = 0; + copies = 1; + } else { + if ((fp = open (argv[6], O_RDONLY)) == -1) { + perror ("ERROR: unable to open print file"); + return 1; + } + + copies = atoi (argv[4]); + } + + if (!(device = get_device_file (argv[0]))) { + fprintf (stderr, "ERROR: Unable to open HAL device \"%s\"\n", argv[0]); + return 1; + } + + do { + if ((fd = open (device, O_RDWR | O_EXCL)) == -1) { + if (errno == EBUSY) { + fputs ("INFO: Device busy; will retry in 30 seconds...\n", stderr); + sleep (30); + } else if (errno == ENXIO || errno == EIO || errno == ENOENT) { + fputs ("INFO: Printer not connected; will retry in 30 seconds...\n", stderr); + sleep (30); + } else { + fprintf (stderr, "ERROR: Unable to open device \"%s\": %s\n", + argv[0], strerror (errno)); + return 1; + } + } + } while (fd == -1); + + libhal_free_string (device); + + /* + * Set any options provided... + */ + + tcgetattr (fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + /**** No options supported yet ****/ + + tcsetattr (fd, TCSANOW, &opts); + + /* + * Now that we are "connected" to the port, ignore SIGTERM so that we + * can finish out any page data the driver sends (e.g. to eject the + * current page... Only ignore SIGTERM if we are printing data from + * stdin (otherwise you can't cancel raw jobs...) + */ + + if (argc < 7) { +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset (SIGTERM, SIG_IGN); +#elif defined(HAVE_SIGACTION) + memset (&action, 0, sizeof (action)); + + sigemptyset (&action.sa_mask); + action.sa_handler = SIG_IGN; + sigaction (SIGTERM, &action, NULL); +#else + signal (SIGTERM, SIG_IGN); +#endif /* HAVE_SIGSET */ + } + +#if defined(__linux) && defined(LP_POUTPA) + if (ioctl (fd, LPGETSTATUS, &status) == 0) { + fprintf (stderr, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status); + + if (!(status & LP_POUTPA)) + fputs ("WARNING: Media tray empty!\n", stderr); + else if (!(status & LP_PERRORP)) + fputs ("WARNING: Printer fault!\n", stderr); + else if (!(status & LP_PSELECD)) + fputs ("WARNING: Printer off-line.\n", stderr); + } +#endif /* __linux && LP_POUTPA */ + + /* + * Finally, send the print file... + */ + + while (copies > 0) { + copies--; + + if (fp != 0) { + fputs ("PAGE: 1 1\n", stderr); + lseek (fp, 0, SEEK_SET); + } + + tbytes = 0; + while ((nbytes = read (fp, buffer, sizeof (buffer))) > 0) { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) { + if ((nwritten = write (fd, bufptr, nbytes)) == -1) + if (errno == ENOTTY) + nwritten = write (fd, bufptr, nbytes); + + if (nwritten == -1) { + perror ("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= nwritten; + bufptr += nwritten; + } + + if (nwritten == -1) + break; + + if (argc > 6) + fprintf (stderr, "INFO: Sending print file, %lu bytes...\n", (unsigned long) tbytes); + } + } + + /* + * Close the socket connection and input file and return... + */ + + close (fd); + if (fp != 0) + close (fp); + + fputs ("INFO: Ready to print.\n", stderr); + + return 0; +} diff --git a/hpnpf.patch b/hpnpf.patch new file mode 100644 index 0000000..e9a3876 --- /dev/null +++ b/hpnpf.patch @@ -0,0 +1,95 @@ +--- hpnpf/fifo.c.orig 2000-07-18 05:40:24.000000000 +0200 ++++ hpnpf/fifo.c 2005-07-26 12:15:35.000000000 +0200 +@@ -29,6 +29,7 @@ + #endif + + #include ++#include + #include "fifo.h" + + extern char leftstr[]; /* hpnpf: prepend or leftover string */ +--- hpnpf/hpnptyd.c.orig 1992-02-14 23:05:57.000000000 +0100 ++++ hpnpf/hpnptyd.c 2005-07-26 12:17:53.000000000 +0200 +@@ -81,8 +81,12 @@ + /* + * Declare external variables. + */ ++#ifndef errno + extern int errno; /* system error number */ ++#endif ++#ifndef LINUX + extern char *sys_errlist[]; /* array of system error messages */ ++#endif + extern char *optarg; /* pointer to option argument */ + extern int optind; /* index of current option */ + extern int opterr; /* flag to enable error logging by getopt() */ +--- hpnpf/linux_std.mak.orig 2004-02-14 21:46:29.000000000 +0100 ++++ hpnpf/linux_std.mak 2005-07-26 12:15:09.000000000 +0200 +@@ -1,8 +1,10 @@ +-CC=cc -DSVR4 -DLINUX -DSTDARG -lnsl ++CC=cc -DSVR4 -DLINUX -DSTDARG ++LIBS=-lnsl ++ + all: hpnpf hpnptyd + + hpnptyd: fifo.h hpnptyd.o network.o fifo.o log.o +- cc -o hpnptyd hpnptyd.o network.o fifo.o log.o ++ ${CC} -o hpnptyd hpnptyd.o network.o fifo.o log.o ${LIBS} + + hpnpf: fifo.h hpnpf.o network.o fifo.o log.o status.o + ${CC} -o hpnpf hpnpf.o network.o fifo.o log.o status.o +--- hpnpf/log.c.orig 2004-02-14 21:44:10.000000000 +0100 ++++ hpnpf/log.c 2005-07-26 12:16:23.000000000 +0200 +@@ -27,6 +27,8 @@ + #include + #include + #include ++#include ++#include + #ifdef STDARG + #include + #else +--- hpnpf/network.c.orig 2000-07-24 00:38:34.000000000 +0200 ++++ hpnpf/network.c 2005-07-26 12:12:55.000000000 +0200 +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifdef LINUX ++#include ++#endif + + /* adapt to UNIX System 5.4 1995-01-29/Bl */ + #ifdef SVR4 +--- hpnpf/hpnptyd.c.orig 2005-07-26 12:18:48.000000000 +0200 ++++ hpnpf/hpnptyd.c 2005-07-26 12:20:39.000000000 +0200 +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #if defined(BSD) + #include + #include +--- hpnpf/linux_std.mak.orig 2005-07-26 12:18:48.000000000 +0200 ++++ hpnpf/linux_std.mak 2005-07-26 12:23:22.000000000 +0200 +@@ -1,7 +1,8 @@ + CC=cc -DSVR4 -DLINUX -DSTDARG + LIBS=-lnsl + +-all: hpnpf hpnptyd ++all: hpnpf ++# doesn't link: hpnptyd + + hpnptyd: fifo.h hpnptyd.o network.o fifo.o log.o + ${CC} -o hpnptyd hpnptyd.o network.o fifo.o log.o ${LIBS} +--- hpnpf/network.c.orig 2005-07-26 12:23:54.000000000 +0200 ++++ hpnpf/network.c 2005-07-26 12:27:47.000000000 +0200 +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #ifdef LINUX + #include + #endif diff --git a/hpnpf.tgz b/hpnpf.tgz new file mode 100644 index 0000000..760d058 --- /dev/null +++ b/hpnpf.tgz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f1f135034f6be05ebb7066d8bed3630b895746f368206f3970d6bbe981b9d24 +size 27507 diff --git a/hpnpf.txt b/hpnpf.txt new file mode 100644 index 0000000..7f97649 --- /dev/null +++ b/hpnpf.txt @@ -0,0 +1,92 @@ +hpnpf A replacement backend for the CUPS socket backend +========================================================= + +DESCRIPTION + +This backend is based on HP's hpnpf utility (the sources of which have been freely +availabel until 1992) and has been extended to safely report the backchannel messages +from a JetDierect driven HP printer and - for PostScript printers only - to use +the TBCP (Tagged Binary Communications Protocol) as defined by Adobe. + +The program can be run either as a CUPS backend or as a standalone utility, depending +on the name it is called by: + +- if the name it is called with contains one of the strings '://' or 'backend/hpnpf' + (the latter for use with the CUPS backend test utility), it runs as a CUPS + backend, following the CUPS backend calling and input/output conventions. +- otherwise, it runs as a standalone utility and accepts additional switches. + + +INSTALLATION + +Unzip and untar the file hpnpf.tgz into a suitable directory. +Within that directory, on SYSV UNIXes, run "make hpnpf", on Linux systems, +run "make -f linux.mak hpnpf". (Don't try to make hpnptyd, this won't succeed.) +On systems which do not/no longer support the good old varargs stuff but +require the use of the new stdarg approach for variable argument lists, +use + make -f linux_std.mak +or + make -f sysv_std.mak +for SYSV systems. + +For CUPS use, copy the compiled binary hpnpf to the CUPS backend directory, +usually /usr/lib/cups/backend. +For standalone use, copy the binary to e.g. /usr/local/bin. + + +CUPS USAGE + +When configuring a CUPS printer for using this backend, the URI syntyx is much the same +as for the standard socket backend: + hpnpf://printername:port +where port usually is 9100. +To enable TBCP, append the string "/TBCP" to the URI, as: + hpnpf://printername:port/TBCP + +The backend writes information to a printer specific log file, + /var/log/cups/status_log.printername +For each job printed, an identification line like + INFO: [Mon Sep 11 11:08:08 2000] HPDIACOS.0001.SRZ0.11486.PS (1999) +containing the current date, the job ID (much like the standard backend) and the job number. +An info message like + INFO: Printing: HPDIACOS.0001.SRZ0.11486.PS +is written to stderr and thus captured by cupsd and available as status message. +Any PostScript error messages are logged like: + INFO: %%[ Error: rangecheck; OffendingCommand: getinterval ]%% +These errors are passed as info messages to cupsd as: + INFO: HPDIACOS.0001.SRZ0.11486.PS | %%[ Error: rangecheck; OffendingCommand: getinterval ]%% +and thus available as the printer's status message. +If no error occurred, a completion message is passed to cupsd like: + INFO: Printed: HPDIACOS.0001.SRZ0.11486.PS + +For debugging, you may append "-D" to the device-URI. In this case, any PJL commands and replies +are logged to the printer specific status log file as specified above, and +debugging messages from hpnpf are written to /var/log/cups/printername.log. + + +STANDALONE USAGE + +Called without any parameters the following usage message is printed to stderr: + +usage: hpnpf -x periph [-c port] [-nNPrRSTvwW] [-p port] [-s statusfile] [-l logfile] file ... + -n (PLC only) map LF->CRLF, FF->CRFF + -N map LF->CRLF physically + -P (PostScript only) print banner page + -r run in relay mode + -R do no retries if connection fails + -S delete all CRs + -T (PostScript only) use TBCP (Tagged Binary Communcations Protocol) + -v verbose mode + -w wait for the job to be completed + -W as -w, additionally display all PJL commands and replies + -c port control port number (for relay mode only) + -x periph name or IP addr of printer + -p port port number to connect with + -s statusfile file to which status messages are written; default: stdout + -l logfile file to which logging messages are written (- : stderr) + file ... files to be printed; read from stdin if no files are given + +The -w switch enables the logging of the PostScript messages, the -W switch additionally +logs the PJL commands and replies, -T enables the TBCP protocol. All other switches have the +same meaning as of the original hpnpf (but haven't been fully tested with this version). diff --git a/ready b/ready new file mode 100644 index 0000000..473a0f4