diff --git a/cups-backends-silenct-hal.patch b/cups-backends-silenct-hal.patch new file mode 100644 index 0000000..579aed3 --- /dev/null +++ b/cups-backends-silenct-hal.patch @@ -0,0 +1,30 @@ +diff -ur /usr/src/packages/BUILD/cups-backends-1.0/hal.c ./hal.c +--- /usr/src/packages/BUILD/cups-backends-1.0/hal.c 2005-07-26 05:50:29.000000000 -0400 ++++ ./hal.c 2007-07-12 15:39:37.000000000 -0400 +@@ -75,11 +75,14 @@ + static void + list_devices (void) + { +- LibHalContext *hal_ctx; +- char **printers; +- int i, n; ++ //LibHalContext *hal_ctx; ++ //char **printers; ++ //int i, n; + +- if (!(hal_ctx = get_hal_ctx ())) ++ printf("direct hal \"Unknown\" \"Hal printing backend\"\n"); ++ ++#if 0 ++ if (!(hal_ctx = get_hal_ctx ())) + return; + + printers = libhal_find_device_by_capability (hal_ctx, "printer", &n, NULL); +@@ -126,6 +129,7 @@ + + libhal_ctx_shutdown (hal_ctx, NULL); + libhal_ctx_free (hal_ctx); ++#endif + } + + /* diff --git a/cups-backends.changes b/cups-backends.changes index be79a3f..9b71392 100644 --- a/cups-backends.changes +++ b/cups-backends.changes @@ -1,15 +1,3 @@ -------------------------------------------------------------------- -Thu Apr 8 17:51:24 CEST 2010 - jsmeix@suse.de - -- Work with upstream compliant CUPS 1.4 on all platforms - which means to have a fixed "/usr/lib/cups/" directory - on all platforms (see Novell/Suse Bugzilla bnc#575544). -- Removed the hal backend because HAL is deprecated - (see Novell/Suse Bugzilla bnc#593946). -- Removed the hpnpf sources because those were "never" built - (at least not in any of our currently maintained - products SLES10, 11.0, 11.1, SLES11, and 11.2). - ------------------------------------------------------------------- Thu Aug 27 13:28:39 CEST 2009 - meissner@suse.de diff --git a/cups-backends.spec b/cups-backends.spec index 7079fac..7966f44 100644 --- a/cups-backends.spec +++ b/cups-backends.spec @@ -19,13 +19,19 @@ Name: cups-backends -Summary: Additional Backends for CUPS -License: GPL v2 +BuildRequires: cups-devel hal-devel +Summary: Various Free Backends for the cups Package +License: GPL v2 or later Group: Hardware/Printing Version: 1.0 Release: 255 -Source0: cups-pipe.sh -Requires: cups +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.sh +Source4: hal.c +Patch0: hpnpf.patch +Patch1: cups-backends-silenct-hal.patch +Requires: cups-libs, dbus-1, hal BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -35,23 +41,34 @@ This package contains free additional backends for CUPS. Authors: -------- + Jiri Srain + Jeffrey Stedfast + Klaus Singvogel Johannes Meixner %prep -# There is nothing to do here because Source0 is installed directly from RPM_SOURCE_DIR. +%setup -c -T +mkdir hpnpf +cd hpnpf +tar xzvvf %{SOURCE0} +cd .. +cp -a %{SOURCE4} . +%patch1 -p0 %build -# There is nothing to build because Source0 is a bash script. +gcc $RPM_OPT_FLAGS -fPIC -fPIE -pie -DDBUS_API_SUBJECT_TO_CHANGE \ + -I%{_includedir}/dbus-1.0/ -I%{_libdir}/dbus-1.0/include/ \ + hal.c -o hal -ldbus-1 -lhal %install -mkdir -p $RPM_BUILD_ROOT/usr/lib/cups/backend -install -m 755 -D ${RPM_SOURCE_DIR}/cups-pipe.sh $RPM_BUILD_ROOT/usr/lib/cups/backend/pipe +mkdir -p $RPM_BUILD_ROOT/%{_libdir}/cups/backend +install -m 755 -D ${RPM_SOURCE_DIR}/cups-pipe.sh $RPM_BUILD_ROOT%{_libdir}/cups/backend/pipe +install -m 755 -D hal $RPM_BUILD_ROOT%{_libdir}/cups/backend/hal %files %defattr(-, root,root) -%dir /usr/lib/cups -%dir /usr/lib/cups/backend -/usr/lib/cups/backend/pipe +%dir %{_libdir}/cups +%dir %{_libdir}/cups/backend +%{_libdir}/cups/backend/* %changelog - 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).