summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2012-10-25 20:57:13 +0200
committerDidier Raboud <odyx@debian.org>2012-10-25 20:57:13 +0200
commit49a2853988b074d087e82c51aec4f9fc052a057d (patch)
treec38ece96005bc33bd4e133fd0037f3428fdc039d /backend
parenta312f7e1ac68fb22275719f6208b670d9edd45b5 (diff)
downloadcups-49a2853988b074d087e82c51aec4f9fc052a057d.tar.gz
Imported Upstream version 1.5.0upstream/1.5.0
Diffstat (limited to 'backend')
-rw-r--r--backend/Dependencies169
-rw-r--r--backend/Makefile75
-rw-r--r--backend/backend-private.h37
-rw-r--r--backend/dnssd.c123
-rw-r--r--backend/easysw-firewire-design.txt71
-rw-r--r--backend/easysw-firewire-linux.txt35
-rw-r--r--backend/ieee1284.c59
-rw-r--r--backend/ipp.c2439
-rw-r--r--backend/lpd.c472
-rw-r--r--backend/network.c14
-rw-r--r--backend/pap.c1696
-rw-r--r--backend/parallel.c46
-rwxr-xr-xbackend/pseudo30
-rw-r--r--backend/runloop.c145
-rw-r--r--backend/scsi-irix.c241
-rw-r--r--backend/scsi-linux.c260
-rw-r--r--backend/scsi.c231
-rw-r--r--backend/serial.c79
-rw-r--r--backend/snmp-supplies.c22
-rw-r--r--backend/snmp.c126
-rw-r--r--backend/socket.c200
-rw-r--r--backend/test1284.c13
-rw-r--r--backend/testbackend.c13
-rw-r--r--backend/testsupplies.c8
-rw-r--r--backend/usb-darwin.c289
-rw-r--r--backend/usb-libusb.c118
-rw-r--r--backend/usb-unix.c56
-rw-r--r--backend/usb.c19
28 files changed, 2961 insertions, 4125 deletions
diff --git a/backend/Dependencies b/backend/Dependencies
index 9051be05..4f99c17e 100644
--- a/backend/Dependencies
+++ b/backend/Dependencies
@@ -1,76 +1,101 @@
# DO NOT DELETE THIS LINE -- make depend depends on it.
-ipp.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/versioning.h
-ipp.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h backend-private.h
-ipp.o: ../cups/backend.h ../cups/sidechannel.h ../cups/ppd-private.h
-ipp.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-ipp.o: ../cups/language.h ../cups/debug.h ../cups/i18n.h ../cups/transcode.h
-ipp.o: ../cups/snmp-private.h ../cups/string.h
-lpd.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/versioning.h
-lpd.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h backend-private.h
-lpd.o: ../cups/backend.h ../cups/sidechannel.h ../cups/ppd-private.h
-lpd.o: ../cups/cups.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-lpd.o: ../cups/language.h ../cups/debug.h ../cups/i18n.h ../cups/transcode.h
-lpd.o: ../cups/snmp-private.h ../cups/string.h
-dnssd.o: backend-private.h ../cups/backend.h ../cups/versioning.h
-dnssd.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-dnssd.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
-dnssd.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h
-dnssd.o: ../cups/transcode.h ../cups/snmp-private.h ../cups/string.h
-dnssd.o: ../config.h ../cups/array.h
-pap.o: ../config.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-pap.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-pap.o: ../cups/language.h ../cups/backend.h ../cups/sidechannel.h
-pap.o: ../cups/i18n.h ../cups/transcode.h
-parallel.o: backend-private.h ../cups/backend.h ../cups/versioning.h
-parallel.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-parallel.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
-parallel.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h
-parallel.o: ../cups/transcode.h ../cups/snmp-private.h ../cups/string.h
-parallel.o: ../config.h
-scsi.o: ../cups/backend.h ../cups/versioning.h ../cups/cups.h ../cups/ipp.h
-scsi.o: ../cups/http.h ../cups/ppd.h ../cups/array.h ../cups/file.h
-scsi.o: ../cups/language.h ../cups/i18n.h ../cups/transcode.h
-scsi.o: ../cups/string.h ../config.h
-serial.o: backend-private.h ../cups/backend.h ../cups/versioning.h
-serial.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-serial.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
-serial.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h
-serial.o: ../cups/transcode.h ../cups/snmp-private.h ../cups/string.h
-serial.o: ../config.h
-snmp.o: backend-private.h ../cups/backend.h ../cups/versioning.h
-snmp.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-snmp.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
-snmp.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h
-snmp.o: ../cups/transcode.h ../cups/snmp-private.h ../cups/string.h
-snmp.o: ../config.h ../cups/array.h ../cups/file.h ../cups/http-private.h
-snmp.o: ../cups/md5.h ../cups/ipp-private.h
+ipp.o: backend-private.h ../cups/cups-private.h ../cups/cups.h ../cups/file.h
+ipp.o: ../cups/versioning.h ../cups/ipp.h ../cups/http.h ../cups/array.h
+ipp.o: ../cups/language.h ../cups/string-private.h ../config.h
+ipp.o: ../cups/debug-private.h ../cups/ppd-private.h ../cups/ppd.h
+ipp.o: ../cups/cups.h ../cups/pwg-private.h ../cups/http-private.h
+ipp.o: ../cups/http.h ../cups/md5-private.h ../cups/ipp-private.h
+ipp.o: ../cups/ipp.h ../cups/language-private.h ../cups/transcode.h
+ipp.o: ../cups/thread-private.h ../cups/snmp-private.h ../cups/backend.h
+ipp.o: ../cups/sidechannel.h ../cups/array-private.h
+lpd.o: ../cups/http-private.h ../config.h ../cups/http.h
+lpd.o: ../cups/md5-private.h ../cups/ipp-private.h ../cups/ipp.h
+lpd.o: backend-private.h ../cups/cups-private.h ../cups/cups.h ../cups/file.h
+lpd.o: ../cups/versioning.h ../cups/ipp.h ../cups/http.h ../cups/array.h
+lpd.o: ../cups/language.h ../cups/string-private.h ../cups/debug-private.h
+lpd.o: ../cups/ppd-private.h ../cups/ppd.h ../cups/cups.h
+lpd.o: ../cups/pwg-private.h ../cups/http-private.h
+lpd.o: ../cups/language-private.h ../cups/transcode.h
+lpd.o: ../cups/thread-private.h ../cups/snmp-private.h ../cups/backend.h
+lpd.o: ../cups/sidechannel.h
+dnssd.o: backend-private.h ../cups/cups-private.h ../cups/cups.h
+dnssd.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h ../cups/http.h
+dnssd.o: ../cups/array.h ../cups/language.h ../cups/string-private.h
+dnssd.o: ../config.h ../cups/debug-private.h ../cups/ppd-private.h
+dnssd.o: ../cups/ppd.h ../cups/cups.h ../cups/pwg-private.h
+dnssd.o: ../cups/http-private.h ../cups/http.h ../cups/md5-private.h
+dnssd.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/language-private.h
+dnssd.o: ../cups/transcode.h ../cups/thread-private.h ../cups/snmp-private.h
+dnssd.o: ../cups/backend.h ../cups/sidechannel.h ../cups/array.h
+parallel.o: backend-private.h ../cups/cups-private.h ../cups/cups.h
+parallel.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h ../cups/http.h
+parallel.o: ../cups/array.h ../cups/language.h ../cups/string-private.h
+parallel.o: ../config.h ../cups/debug-private.h ../cups/ppd-private.h
+parallel.o: ../cups/ppd.h ../cups/cups.h ../cups/pwg-private.h
+parallel.o: ../cups/http-private.h ../cups/http.h ../cups/md5-private.h
+parallel.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/language-private.h
+parallel.o: ../cups/transcode.h ../cups/thread-private.h
+parallel.o: ../cups/snmp-private.h ../cups/backend.h ../cups/sidechannel.h
+serial.o: backend-private.h ../cups/cups-private.h ../cups/cups.h
+serial.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h ../cups/http.h
+serial.o: ../cups/array.h ../cups/language.h ../cups/string-private.h
+serial.o: ../config.h ../cups/debug-private.h ../cups/ppd-private.h
+serial.o: ../cups/ppd.h ../cups/cups.h ../cups/pwg-private.h
+serial.o: ../cups/http-private.h ../cups/http.h ../cups/md5-private.h
+serial.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/language-private.h
+serial.o: ../cups/transcode.h ../cups/thread-private.h ../cups/snmp-private.h
+serial.o: ../cups/backend.h ../cups/sidechannel.h
+snmp.o: backend-private.h ../cups/cups-private.h ../cups/cups.h
+snmp.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h ../cups/http.h
+snmp.o: ../cups/array.h ../cups/language.h ../cups/string-private.h
+snmp.o: ../config.h ../cups/debug-private.h ../cups/ppd-private.h
+snmp.o: ../cups/ppd.h ../cups/cups.h ../cups/pwg-private.h
+snmp.o: ../cups/http-private.h ../cups/http.h ../cups/md5-private.h
+snmp.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/language-private.h
+snmp.o: ../cups/transcode.h ../cups/thread-private.h ../cups/snmp-private.h
+snmp.o: ../cups/backend.h ../cups/sidechannel.h ../cups/array.h
+snmp.o: ../cups/file.h ../cups/http-private.h
socket.o: ../cups/http-private.h ../config.h ../cups/http.h
-socket.o: ../cups/versioning.h ../cups/md5.h ../cups/ipp-private.h
-socket.o: ../cups/ipp.h backend-private.h ../cups/backend.h
-socket.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-socket.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
-socket.o: ../cups/debug.h ../cups/i18n.h ../cups/transcode.h
-socket.o: ../cups/snmp-private.h ../cups/string.h
-test1284.o: ../cups/string.h ../config.h ieee1284.c backend-private.h
-test1284.o: ../cups/backend.h ../cups/versioning.h ../cups/sidechannel.h
-test1284.o: ../cups/ppd-private.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-test1284.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
-test1284.o: ../cups/debug.h ../cups/i18n.h ../cups/transcode.h
-test1284.o: ../cups/snmp-private.h
-testbackend.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
-testbackend.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
-testbackend.o: ../cups/array.h ../cups/file.h ../cups/language.h
+socket.o: ../cups/md5-private.h ../cups/ipp-private.h ../cups/ipp.h
+socket.o: backend-private.h ../cups/cups-private.h ../cups/cups.h
+socket.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h ../cups/http.h
+socket.o: ../cups/array.h ../cups/language.h ../cups/string-private.h
+socket.o: ../cups/debug-private.h ../cups/ppd-private.h ../cups/ppd.h
+socket.o: ../cups/cups.h ../cups/pwg-private.h ../cups/http-private.h
+socket.o: ../cups/language-private.h ../cups/transcode.h
+socket.o: ../cups/thread-private.h ../cups/snmp-private.h ../cups/backend.h
+socket.o: ../cups/sidechannel.h
+test1284.o: ../cups/string-private.h ../config.h ieee1284.c backend-private.h
+test1284.o: ../cups/cups-private.h ../cups/cups.h ../cups/file.h
+test1284.o: ../cups/versioning.h ../cups/ipp.h ../cups/http.h ../cups/array.h
+test1284.o: ../cups/language.h ../cups/string-private.h
+test1284.o: ../cups/debug-private.h ../cups/ppd-private.h ../cups/ppd.h
+test1284.o: ../cups/cups.h ../cups/pwg-private.h ../cups/http-private.h
+test1284.o: ../cups/http.h ../cups/md5-private.h ../cups/ipp-private.h
+test1284.o: ../cups/ipp.h ../cups/language-private.h ../cups/transcode.h
+test1284.o: ../cups/thread-private.h ../cups/snmp-private.h ../cups/backend.h
+test1284.o: ../cups/sidechannel.h
+testbackend.o: ../cups/string-private.h ../config.h ../cups/cups.h
+testbackend.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h
+testbackend.o: ../cups/http.h ../cups/array.h ../cups/language.h
testbackend.o: ../cups/sidechannel.h
-testsupplies.o: backend-private.h ../cups/backend.h ../cups/versioning.h
-testsupplies.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-testsupplies.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
-testsupplies.o: ../cups/file.h ../cups/language.h ../cups/debug.h
-testsupplies.o: ../cups/i18n.h ../cups/transcode.h ../cups/snmp-private.h
-testsupplies.o: ../cups/string.h ../config.h
-usb.o: backend-private.h ../cups/backend.h ../cups/versioning.h
-usb.o: ../cups/sidechannel.h ../cups/ppd-private.h ../cups/cups.h
-usb.o: ../cups/ipp.h ../cups/http.h ../cups/ppd.h ../cups/array.h
-usb.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/i18n.h
-usb.o: ../cups/transcode.h ../cups/snmp-private.h ../cups/string.h
-usb.o: ../config.h
+testsupplies.o: backend-private.h ../cups/cups-private.h ../cups/cups.h
+testsupplies.o: ../cups/file.h ../cups/versioning.h ../cups/ipp.h
+testsupplies.o: ../cups/http.h ../cups/array.h ../cups/language.h
+testsupplies.o: ../cups/string-private.h ../config.h ../cups/debug-private.h
+testsupplies.o: ../cups/ppd-private.h ../cups/ppd.h ../cups/cups.h
+testsupplies.o: ../cups/pwg-private.h ../cups/http-private.h ../cups/http.h
+testsupplies.o: ../cups/md5-private.h ../cups/ipp-private.h ../cups/ipp.h
+testsupplies.o: ../cups/language-private.h ../cups/transcode.h
+testsupplies.o: ../cups/thread-private.h ../cups/snmp-private.h
+testsupplies.o: ../cups/backend.h ../cups/sidechannel.h
+usb.o: backend-private.h ../cups/cups-private.h ../cups/cups.h ../cups/file.h
+usb.o: ../cups/versioning.h ../cups/ipp.h ../cups/http.h ../cups/array.h
+usb.o: ../cups/language.h ../cups/string-private.h ../config.h
+usb.o: ../cups/debug-private.h ../cups/ppd-private.h ../cups/ppd.h
+usb.o: ../cups/cups.h ../cups/pwg-private.h ../cups/http-private.h
+usb.o: ../cups/http.h ../cups/md5-private.h ../cups/ipp-private.h
+usb.o: ../cups/ipp.h ../cups/language-private.h ../cups/transcode.h
+usb.o: ../cups/thread-private.h ../cups/snmp-private.h ../cups/backend.h
+usb.o: ../cups/sidechannel.h
diff --git a/backend/Makefile b/backend/Makefile
index 16b66e2f..47feac9e 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -1,9 +1,9 @@
#
-# "$Id: Makefile 8400 2009-03-03 19:39:21Z mike $"
+# "$Id: Makefile 9737 2011-05-04 04:28:00Z mike $"
#
-# Backend makefile for the Common UNIX Printing System (CUPS).
+# Backend makefile for CUPS.
#
-# Copyright 2007-2009 by Apple Inc.
+# Copyright 2007-2011 by Apple Inc.
# Copyright 1997-2007 by Easy Software Products, all rights reserved.
#
# These coded instructions, statements, and computer programs are the
@@ -17,12 +17,16 @@
include ../Makedefs
+#
+# Object files...
+#
+
RBACKENDS = ipp lpd $(DNSSD_BACKEND)
-UBACKENDS = $(PAP) $(LEGACY_BACKENDS) serial snmp socket usb
+UBACKENDS = $(LEGACY_BACKENDS) serial snmp socket usb
UNITTESTS = test1284 testbackend testsupplies
TARGETS = libbackend.a $(RBACKENDS) $(UBACKENDS)
LIBOBJS = ieee1284.o network.o runloop.o snmp-supplies.o
-OBJS = ipp.o lpd.o dnssd.o pap.o parallel.o scsi.o serial.o snmp.o \
+OBJS = ipp.o lpd.o dnssd.o parallel.o serial.o snmp.o \
socket.o test1284.o testbackend.o testsupplies.o usb.o
@@ -81,7 +85,8 @@ install-data:
# Install programs...
#
-install-exec:
+install-exec: $(INSTALLXPC)
+ echo Installing backends in $(SERVERBIN)/backend
$(INSTALL_DIR) -m 755 $(SERVERBIN)/backend
for file in $(RBACKENDS); do \
$(LIBTOOL) $(INSTALL_BIN) -m 700 $$file $(SERVERBIN)/backend; \
@@ -89,8 +94,10 @@ install-exec:
for file in $(UBACKENDS); do \
$(INSTALL_BIN) $$file $(SERVERBIN)/backend; \
done
- $(RM) $(SERVERBIN)/backend/http
- $(LN) ipp $(SERVERBIN)/backend/http
+ for file in $(IPPALIASES); do \
+ $(RM) $(SERVERBIN)/backend/$$file; \
+ $(LN) ipp $(SERVERBIN)/backend/$$file; \
+ done
if test "x$(DNSSD_BACKEND)" != x; then \
$(RM) $(SERVERBIN)/backend/mdns; \
$(LN) $(DNSSD_BACKEND) $(SERVERBIN)/backend/mdns; \
@@ -102,6 +109,15 @@ install-exec:
done \
fi
+install-xpc: ipp
+ echo Installing XPC backends in $(SERVERBIN)/apple
+ $(INSTALL_DIR) -m 755 $(SERVERBIN)/apple
+ $(LIBTOOL) $(INSTALL_BIN) ipp $(SERVERBIN)/apple
+ for file in $(IPPALIASES); do \
+ $(RM) $(SERVERBIN)/apple/$$file; \
+ $(LN) ipp $(SERVERBIN)/apple/$$file; \
+ done
+
#
# Install headers...
@@ -122,10 +138,17 @@ install-libs:
#
uninstall:
+ $(RM) $(SERVERBIN)/apple/ipp
+ for file in $(IPPALIASES); do \
+ $(RM) $(SERVERBIN)/apple/$$file; \
+ done
+ -$(RMDIR) $(SERVERBIN)/apple
for file in $(RBACKENDS) $(UBACKENDS); do \
$(RM) $(SERVERBIN)/backend/$$file; \
done
- $(RM) $(SERVERBIN)/backend/http
+ for file in $(IPPALIASES); do \
+ $(RM) $(SERVERBIN)/backend/$$file; \
+ done
-$(RMDIR) $(SERVERBIN)/backend
-$(RMDIR) $(SERVERBIN)
@@ -134,9 +157,9 @@ uninstall:
# test1284
#
-test1284: test1284.o ../cups/libcups.a
+test1284: test1284.o ../cups/$(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o test1284 test1284.o ../cups/libcups.a \
+ $(CC) $(LDFLAGS) -o test1284 test1284.o ../cups/$(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -144,9 +167,9 @@ test1284: test1284.o ../cups/libcups.a
# testbackend
#
-testbackend: testbackend.o ../cups/libcups.a
+testbackend: testbackend.o ../cups/$(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o testbackend testbackend.o ../cups/libcups.a \
+ $(CC) $(LDFLAGS) -o testbackend testbackend.o ../cups/$(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -154,10 +177,10 @@ testbackend: testbackend.o ../cups/libcups.a
# testsupplies
#
-testsupplies: testsupplies.o libbackend.a ../cups/libcups.a
+testsupplies: testsupplies.o libbackend.a ../cups/$(LIBCUPSSTATIC)
echo Linking $@...
$(CC) $(LDFLAGS) -o testsupplies testsupplies.o libbackend.a \
- ../cups/libcups.a $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
+ ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \
$(COMMONLIBS) $(LIBZ)
@@ -204,15 +227,6 @@ lpd: lpd.o ../cups/$(LIBCUPS) libbackend.a
#
-# pap
-#
-
-pap: pap.o ../cups/$(LIBCUPS)
- echo Linking $@...
- $(CC) $(LDFLAGS) -o pap pap.o $(BACKLIBS) $(LIBS) -framework AppleTalk
-
-
-#
# parallel
#
@@ -222,17 +236,6 @@ parallel: parallel.o ../cups/$(LIBCUPS) libbackend.a
#
-# scsi
-#
-
-scsi: scsi.o ../cups/$(LIBCUPS)
- echo Linking $@...
- $(CC) $(LDFLAGS) -o scsi scsi.o $(LIBS)
-
-scsi.o: scsi.c scsi-irix.c scsi-linux.c
-
-
-#
# serial
#
@@ -278,5 +281,5 @@ include Dependencies
#
-# End of "$Id: Makefile 8400 2009-03-03 19:39:21Z mike $".
+# End of "$Id: Makefile 9737 2011-05-04 04:28:00Z mike $".
#
diff --git a/backend/backend-private.h b/backend/backend-private.h
index df08a2c9..95dc2d88 100644
--- a/backend/backend-private.h
+++ b/backend/backend-private.h
@@ -1,9 +1,9 @@
/*
- * "$Id: backend-private.h 8912 2009-12-08 02:13:42Z mike $"
+ * "$Id: backend-private.h 9577 2011-03-04 18:02:45Z mike $"
*
- * Backend support definitions for the Common UNIX Printing System (CUPS).
+ * Backend support definitions for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -23,15 +23,10 @@
* Include necessary headers.
*/
+# include <cups/cups-private.h>
+# include <cups/snmp-private.h>
# include <cups/backend.h>
# include <cups/sidechannel.h>
-# include <cups/ppd-private.h>
-# include <cups/debug.h>
-# include <cups/i18n.h>
-# include <cups/snmp-private.h>
-# include <stdlib.h>
-# include <errno.h>
-# include <cups/string.h>
# include <signal.h>
# ifdef __linux
@@ -282,6 +277,14 @@ extern "C" {
/*
+ * Types...
+ */
+
+typedef int (*_cups_sccb_t)(int print_fd, int device_fd, int snmp_fd,
+ http_addr_t *addr, int use_bc);
+
+
+/*
* Prototypes...
*/
@@ -300,16 +303,14 @@ extern int backendNetworkSideCB(int print_fd, int device_fd,
int snmp_fd, http_addr_t *addr,
int use_bc);
extern ssize_t backendRunLoop(int print_fd, int device_fd, int snmp_fd,
- http_addr_t *addr, int use_bc,
- int update_state,
- int (*side_cb)(int print_fd,
- int device_fd,
- int snmp_fd,
- http_addr_t *addr,
- int use_bc));
+ http_addr_t *addr, int use_bc,
+ int update_state, _cups_sccb_t side_cb);
extern int backendSNMPSupplies(int snmp_fd, http_addr_t *addr,
int *page_count,
int *printer_state);
+extern int backendWaitLoop(int snmp_fd, http_addr_t *addr,
+ int use_bc, _cups_sccb_t side_cb);
+
# ifdef __cplusplus
}
@@ -318,5 +319,5 @@ extern int backendSNMPSupplies(int snmp_fd, http_addr_t *addr,
/*
- * End of "$Id: backend-private.h 8912 2009-12-08 02:13:42Z mike $".
+ * End of "$Id: backend-private.h 9577 2011-03-04 18:02:45Z mike $".
*/
diff --git a/backend/dnssd.c b/backend/dnssd.c
index 32dff816..10af920a 100644
--- a/backend/dnssd.c
+++ b/backend/dnssd.c
@@ -1,9 +1,9 @@
/*
- * "$Id: dnssd.c 8758 2009-08-07 22:27:12Z mike $"
+ * "$Id: dnssd.c 9815 2011-06-05 16:58:33Z mike $"
*
- * DNS-SD discovery backend for the Common UNIX Printing System (CUPS).
+ * DNS-SD discovery backend for CUPS.
*
- * Copyright 2008-2009 by Apple Inc.
+ * Copyright 2008-2011 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -44,6 +44,7 @@ typedef enum
{
CUPS_DEVICE_PRINTER = 0, /* lpd://... */
CUPS_DEVICE_IPP, /* ipp://... */
+ CUPS_DEVICE_IPPS, /* ipps://... */
CUPS_DEVICE_FAX_IPP, /* ipp://... */
CUPS_DEVICE_PDL_DATASTREAM, /* socket://... */
CUPS_DEVICE_RIOUSBPRINT /* riousbprint://... */
@@ -123,9 +124,11 @@ main(int argc, /* I - Number of command-line args */
fax_ipp_ref, /* IPP fax service reference */
ipp_ref, /* IPP service reference */
ipp_tls_ref, /* IPP w/TLS service reference */
+ ipps_ref, /* IPP service reference */
local_fax_ipp_ref, /* Local IPP fax service reference */
local_ipp_ref, /* Local IPP service reference */
local_ipp_tls_ref, /* Local IPP w/TLS service reference */
+ local_ipps_ref, /* Local IPP service reference */
local_printer_ref, /* Local LPD service reference */
pdl_datastream_ref, /* AppSocket service reference */
printer_ref, /* LPD service reference */
@@ -167,8 +170,9 @@ main(int argc, /* I - Number of command-line args */
exec_backend(argv);
else if (argc != 1)
{
- fprintf(stderr, "Usage: %s job user title copies options [filename(s)]\n",
- argv[0]);
+ _cupsLangPrintf(stderr,
+ _("Usage: %s job-id user title copies options [file]"),
+ argv[0]);
return (1);
}
@@ -214,6 +218,10 @@ main(int argc, /* I - Number of command-line args */
DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0,
"_ipp-tls._tcp", NULL, browse_callback, devices);
+ ipps_ref = main_ref;
+ DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
+ "_ipps._tcp", NULL, browse_callback, devices);
+
local_fax_ipp_ref = main_ref;
DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection,
kDNSServiceInterfaceIndexLocalOnly,
@@ -229,12 +237,17 @@ main(int argc, /* I - Number of command-line args */
kDNSServiceInterfaceIndexLocalOnly,
"_ipp-tls._tcp", NULL, browse_local_callback, devices);
+ local_ipps_ref = main_ref;
+ DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
+ kDNSServiceInterfaceIndexLocalOnly,
+ "_ipps._tcp", NULL, browse_local_callback, devices);
+
local_printer_ref = main_ref;
DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection,
kDNSServiceInterfaceIndexLocalOnly,
"_printer._tcp", NULL, browse_local_callback, devices);
- pdl_datastream_ref = main_ref;
+ pdl_datastream_ref = main_ref;
DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0,
"_pdl-datastream._tcp", NULL, browse_callback, devices);
@@ -255,8 +268,8 @@ main(int argc, /* I - Number of command-line args */
FD_ZERO(&input);
FD_SET(fd, &input);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 250000;
if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
continue;
@@ -279,19 +292,26 @@ main(int argc, /* I - Number of command-line args */
cups_device_t *best; /* Best matching device */
char device_uri[1024]; /* Device URI */
int count; /* Number of queries */
-
+ int sent; /* Number of sent */
for (device = (cups_device_t *)cupsArrayFirst(devices),
- best = NULL, count = 0;
+ best = NULL, count = 0, sent = 0;
device;
device = (cups_device_t *)cupsArrayNext(devices))
+ {
+ if (device->sent)
+ sent ++;
+
+ if (device->ref)
+ count ++;
+
if (!device->ref && !device->sent)
{
/*
* Found the device, now get the TXT record(s) for it...
*/
- if (count < 10)
+ if (count < 20)
{
device->ref = main_ref;
@@ -324,8 +344,8 @@ main(int argc, /* I - Number of command-line args */
if (!best)
best = device;
- else if (strcasecmp(best->name, device->name) ||
- strcasecmp(best->domain, device->domain))
+ else if (_cups_strcasecmp(best->name, device->name) ||
+ _cups_strcasecmp(best->domain, device->domain))
{
unquote(uriName, best->fullName, sizeof(uriName));
@@ -337,6 +357,8 @@ main(int argc, /* I - Number of command-line args */
best->name, best->device_id, NULL);
best->sent = 1;
best = device;
+
+ sent ++;
}
else if (best->priority > device->priority ||
(best->priority == device->priority &&
@@ -344,10 +366,17 @@ main(int argc, /* I - Number of command-line args */
{
best->sent = 1;
best = device;
+
+ sent ++;
}
else
+ {
device->sent = 1;
+
+ sent ++;
+ }
}
+ }
if (best)
{
@@ -360,7 +389,11 @@ main(int argc, /* I - Number of command-line args */
cupsBackendReport("network", device_uri, best->make_and_model,
best->name, best->device_id, NULL);
best->sent = 1;
+ sent ++;
}
+
+ if (sent == cupsArrayCount(devices))
+ break;
}
}
@@ -491,8 +524,14 @@ exec_backend(char **argv) /* I - Command-line arguments */
job_canceled = -1;
- if ((resolved_uri = cupsBackendDeviceURI(argv)) == NULL)
- exit(CUPS_BACKEND_FAILED);
+ while ((resolved_uri = cupsBackendDeviceURI(argv)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ exit(CUPS_BACKEND_FAILED);
+ }
/*
* Extract the scheme from the URI...
@@ -551,9 +590,11 @@ get_device(cups_array_t *devices, /* I - Device array */
key.name = (char *)serviceName;
- if (!strcmp(regtype, "_ipp._tcp.") ||
- !strcmp(regtype, "_ipp-tls._tcp."))
+ if (!strcmp(regtype, "_ipp._tcp."))
key.type = CUPS_DEVICE_IPP;
+ else if (!strcmp(regtype, "_ipps._tcp.") ||
+ !strcmp(regtype, "_ipp-tls._tcp."))
+ key.type = CUPS_DEVICE_IPPS;
else if (!strcmp(regtype, "_fax-ipp._tcp."))
key.type = CUPS_DEVICE_FAX_IPP;
else if (!strcmp(regtype, "_printer._tcp."))
@@ -566,12 +607,12 @@ get_device(cups_array_t *devices, /* I - Device array */
for (device = cupsArrayFind(devices, &key);
device;
device = cupsArrayNext(devices))
- if (strcasecmp(device->name, key.name))
+ if (_cups_strcasecmp(device->name, key.name))
break;
else if (device->type == key.type)
{
- if (!strcasecmp(device->domain, "local.") &&
- strcasecmp(device->domain, replyDomain))
+ if (!_cups_strcasecmp(device->domain, "local.") &&
+ _cups_strcasecmp(device->domain, replyDomain))
{
/*
* Update the .local listing to use the "global" domain name instead.
@@ -673,9 +714,11 @@ query_callback(
if ((ptr = strstr(name, "._")) != NULL)
*ptr = '\0';
- if (strstr(fullName, "_ipp._tcp.") ||
- strstr(fullName, "_ipp-tls._tcp."))
+ if (strstr(fullName, "_ipp._tcp."))
dkey.type = CUPS_DEVICE_IPP;
+ else if (strstr(fullName, "_ipps._tcp.") ||
+ strstr(fullName, "_ipp-tls._tcp."))
+ dkey.type = CUPS_DEVICE_IPPS;
else if (strstr(fullName, "_fax-ipp._tcp."))
dkey.type = CUPS_DEVICE_FAX_IPP;
else if (strstr(fullName, "_printer._tcp."))
@@ -689,8 +732,8 @@ query_callback(
device;
device = cupsArrayNext(devices))
{
- if (strcasecmp(device->name, dkey.name) ||
- strcasecmp(device->domain, dkey.domain))
+ if (_cups_strcasecmp(device->name, dkey.name) ||
+ _cups_strcasecmp(device->domain, dkey.domain))
{
device = NULL;
break;
@@ -747,11 +790,18 @@ query_callback(
if (data < datanext)
memcpy(value, data, datanext - data);
value[datanext - data] = '\0';
+
+ fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
+ key, value);
}
else
+ {
+ fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
+ key);
continue;
+ }
- if (!strncasecmp(key, "usb_", 4))
+ if (!_cups_strncasecmp(key, "usb_", 4))
{
/*
* Add USB device ID information...
@@ -762,12 +812,12 @@ query_callback(
key + 4, value);
}
- if (!strcasecmp(key, "usb_MFG") || !strcasecmp(key, "usb_MANU") ||
- !strcasecmp(key, "usb_MANUFACTURER"))
+ if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") ||
+ !_cups_strcasecmp(key, "usb_MANUFACTURER"))
strcpy(make_and_model, value);
- else if (!strcasecmp(key, "usb_MDL") || !strcasecmp(key, "usb_MODEL"))
+ else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL"))
strcpy(model, value);
- else if (!strcasecmp(key, "product") && !strstr(value, "Ghostscript"))
+ else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript"))
{
if (value[0] == '(')
{
@@ -783,18 +833,19 @@ query_callback(
else
strcpy(model, value);
}
- else if (!strcasecmp(key, "ty"))
+ else if (!_cups_strcasecmp(key, "ty"))
{
strcpy(model, value);
if ((ptr = strchr(model, ',')) != NULL)
*ptr = '\0';
}
- else if (!strcasecmp(key, "priority"))
+ else if (!_cups_strcasecmp(key, "priority"))
device->priority = atoi(value);
else if ((device->type == CUPS_DEVICE_IPP ||
+ device->type == CUPS_DEVICE_IPPS ||
device->type == CUPS_DEVICE_PRINTER) &&
- !strcasecmp(key, "printer-type"))
+ !_cups_strcasecmp(key, "printer-type"))
{
/*
* This is a CUPS printer!
@@ -815,9 +866,9 @@ query_callback(
if (make_and_model[0])
snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;",
make_and_model, model);
- else if (!strncasecmp(model, "designjet ", 10))
+ else if (!_cups_strncasecmp(model, "designjet ", 10))
snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s", model + 10);
- else if (!strncasecmp(model, "stylus ", 7))
+ else if (!_cups_strncasecmp(model, "stylus ", 7))
snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s", model + 7);
else if ((ptr = strchr(model, ' ')) != NULL)
{
@@ -866,6 +917,8 @@ query_callback(
static void
sigterm_handler(int sig) /* I - Signal number (unused) */
{
+ (void)sig;
+
if (job_canceled)
exit(CUPS_BACKEND_OK);
else
@@ -908,5 +961,5 @@ unquote(char *dst, /* I - Destination buffer */
/*
- * End of "$Id: dnssd.c 8758 2009-08-07 22:27:12Z mike $".
+ * End of "$Id: dnssd.c 9815 2011-06-05 16:58:33Z mike $".
*/
diff --git a/backend/easysw-firewire-design.txt b/backend/easysw-firewire-design.txt
deleted file mode 100644
index 194c487e..00000000
--- a/backend/easysw-firewire-design.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-Preliminary Design for CUPS Firewire Printer Backend - 03/19/2002
------------------------------------------------------------------
-
-OVERVIEW
-
- Easy Software Products will develop an IEEE-1394, a.k.a.
- Firewire, printing interface for its Common UNIX Printing
- System ("CUPS") for initial use under the Linux operating
- system. A follow-on implementation for MacOS X is
- anticipated as well.
-
- The operating system interfaces for IEEE-1394 ports vary
- widely; the CUPS printing interface will abstract the OS
- layer to a simpler interface geared towards discovering,
- opening, reading from, writing to, and closing IEEE-1394
- printers.
-
- The initial development of the CUPS backend will be targeted
- at the EPSON Stylus Pro 10000 large format printer, which
- requires the bandwidth provided by Firewire in order to
- print at full speed. This printer supports printing via
- Serial Bus Protocol 2 (SBP-2) using the SCSI and PWG command
- sets. The CUPS backend will implement the PWG command set on
- LUN 0 only.
-
-
-OS ABSTRACTION LAYER
-
- The OS abstraction layer will be a thin client library that
- implements the following functions:
-
- ieee1394_list
- ieee1394_open
- ieee1394_close
- ieee1394_read
- ieee1394_write
- ieee1394_error
-
- The "ieee1394_list" function will list all of the available
- printer devices on the bus. The device information will
- consist of the device URI (ieee1394:/something) used to
- access the device and the make and model information, if
- available, for the device ("EPSON Stylus Printer").
-
- The "ieee1394_open" and "ieee1394_close" functions will open
- and close a connection to the printer, respectively.
-
- The "ieee1394_read" and "ieee1394_write" functions will read
- and write data to and from the printer, respectively. The
- read function will be non-blocking, returning data only if
- there is data coming back from the printer.
-
- The "ieee1394_error" function will return a string
- describing the last error or NULL if no error occurred.
-
- The library will be responsible for creating any background
- threads that are needed to monitor the connection to the
- printer.
-
-
-CUPS BACKEND
-
- The CUPS backend will use the OS abstraction layer to list
- and access the Firewire printers. The "main" function will
- read and write printer data, while the "list_devices"
- function will be called as necessary to identify the
- available devices.
-
- The CUPS 1.1 backend will record any status information in
- the error log file, while the 1.2 backend will supply it to
- the printer driver process.
diff --git a/backend/easysw-firewire-linux.txt b/backend/easysw-firewire-linux.txt
deleted file mode 100644
index a8e46118..00000000
--- a/backend/easysw-firewire-linux.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-Easy Software Products
-44141 Airport View Drive
-Suite 204
-Hollywood, Maryland 20636
-+1.301.373.9600
-March 8, 2002
-
-
-Subject: EPSON Firewire Printer Driver for Linux
-
-Currently, no Firewire printer support exists for Linux. Since
-the latest EPSON printer products depend on the Firewire
-interface to print at full speed, a solution is needed to
-support customers using Linux as their server platform.
-
-The Linux Firewire subsystem provides a user-mode driver
-interface that allows driver programs to access Firewire
-devices. Easy Software Products will utilize this interface to
-develop a "backend" program for the Common UNIX Printing System
-that will allow users to print to EPSON printers using the
-Firewire interface.
-
-After examining the Linux interface, we estimate that it will
-require approximately 30 hours of development time to write,
-test, and document the Firewire backend, for a total cost of
-$3,000. The new backend will become a standard part of the CUPS
-software distribution and will be included with at least the
-following Linux distributions:
-
- - Caldera Linux
- - Mandrake Linux
- - Red Hat Linux
- - SuSE Linux
-
-ESP will provide EPSON with binaries for Red Hat Linux 7.2.
diff --git a/backend/ieee1284.c b/backend/ieee1284.c
index d55c75a1..c95fbc7f 100644
--- a/backend/ieee1284.c
+++ b/backend/ieee1284.c
@@ -1,9 +1,9 @@
/*
- * "$Id: ieee1284.c 9098 2010-04-09 22:42:09Z mike $"
+ * "$Id: ieee1284.c 9828 2011-06-14 06:38:24Z mike $"
*
- * IEEE-1284 support functions for the Common UNIX Printing System (CUPS).
+ * IEEE-1284 support functions for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -26,6 +26,7 @@
*/
#include "backend-private.h"
+#include <cups/cups-private.h>
/*
@@ -45,6 +46,15 @@ backendGetDeviceID(
int uri_size) /* I - Size of buffer */
{
#ifdef __APPLE__ /* This function is a no-op */
+ (void)fd;
+ (void)device_id;
+ (void)device_id_size;
+ (void)make_model;
+ (void)make_model_size;
+ (void)scheme;
+ (void)uri;
+ (void)uri_size;
+
return (-1);
#else /* Get the device ID from the specified file descriptor... */
@@ -55,6 +65,7 @@ backendGetDeviceID(
# if defined(__sun) && defined(ECPPIOC_GETDEVID)
struct ecpp_device_id did; /* Device ID buffer */
# endif /* __sun && ECPPIOC_GETDEVID */
+ char *ptr; /* Pointer into device ID */
DEBUG_printf(("backendGetDeviceID(fd=%d, device_id=%p, device_id_size=%d, "
@@ -176,7 +187,7 @@ backendGetDeviceID(
* and then limit the length to the size of our buffer...
*/
- if (length > device_id_size)
+ if (length > device_id_size || length < 14)
length = (((unsigned)device_id[1] & 255) << 8) +
((unsigned)device_id[0] & 255);
@@ -214,11 +225,12 @@ backendGetDeviceID(
device_id[length] = '\0';
}
}
-# ifdef DEBUG
else
+ {
DEBUG_printf(("backendGetDeviceID: ioctl failed - %s\n",
strerror(errno)));
-# endif /* DEBUG */
+ *device_id = '\0';
+ }
# endif /* __linux */
# if defined(__sun) && defined(ECPPIOC_GETDEVID)
@@ -246,6 +258,22 @@ backendGetDeviceID(
# endif /* __sun && ECPPIOC_GETDEVID */
}
+ /*
+ * Check whether device ID is valid. Turn line breaks and tabs to spaces and
+ * reject device IDs with non-printable characters.
+ */
+
+ for (ptr = device_id; *ptr; ptr ++)
+ if (_cups_isspace(*ptr))
+ *ptr = ' ';
+ else if ((*ptr & 255) < ' ' || *ptr == 127)
+ {
+ DEBUG_printf(("backendGetDeviceID: Bad device_id character %d.",
+ *ptr & 255));
+ *device_id = '\0';
+ break;
+ }
+
DEBUG_printf(("backendGetDeviceID: device_id=\"%s\"\n", device_id));
if (scheme && uri)
@@ -280,7 +308,7 @@ backendGetDeviceID(
* Get the make, model, and serial numbers...
*/
- num_values = _ppdGet1284Values(device_id, &values);
+ num_values = _cupsGet1284Values(device_id, &values);
if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
@@ -294,9 +322,9 @@ backendGetDeviceID(
if (mfg)
{
- if (!strcasecmp(mfg, "Hewlett-Packard"))
+ if (!_cups_strcasecmp(mfg, "Hewlett-Packard"))
mfg = "HP";
- else if (!strcasecmp(mfg, "Lexmark International"))
+ else if (!_cups_strcasecmp(mfg, "Lexmark International"))
mfg = "Lexmark";
}
else
@@ -312,7 +340,7 @@ backendGetDeviceID(
if (!mdl)
mdl = "";
- if (!strncasecmp(mdl, mfg, strlen(mfg)))
+ if (!_cups_strncasecmp(mdl, mfg, strlen(mfg)))
{
mdl += strlen(mfg);
@@ -373,7 +401,7 @@ backendGetMakeModel(
* Look for the description field...
*/
- num_values = _ppdGet1284Values(device_id, &values);
+ num_values = _cupsGet1284Values(device_id, &values);
if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL)
mdl = cupsGetOption("MDL", num_values, values);
@@ -387,7 +415,7 @@ backendGetMakeModel(
if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL)
mfg = cupsGetOption("MFG", num_values, values);
- if (!mfg || !strncasecmp(mdl, mfg, strlen(mfg)))
+ if (!mfg || !_cups_strncasecmp(mdl, mfg, strlen(mfg)))
{
/*
* Just copy the model string, since it has the manufacturer...
@@ -403,10 +431,7 @@ backendGetMakeModel(
char temp[1024]; /* Temporary make and model */
- if (mfg)
- snprintf(temp, sizeof(temp), "%s %s", mfg, mdl);
- else
- snprintf(temp, sizeof(temp), "%s", mdl);
+ snprintf(temp, sizeof(temp), "%s %s", mfg, mdl);
_ppdNormalizeMakeAndModel(temp, make_model, make_model_size);
}
@@ -462,5 +487,5 @@ backendGetMakeModel(
/*
- * End of "$Id: ieee1284.c 9098 2010-04-09 22:42:09Z mike $".
+ * End of "$Id: ieee1284.c 9828 2011-06-14 06:38:24Z mike $".
*/
diff --git a/backend/ipp.c b/backend/ipp.c
index ef0fe0a9..be5fce37 100644
--- a/backend/ipp.c
+++ b/backend/ipp.c
@@ -1,9 +1,9 @@
/*
- * "$Id: ipp.c 8950 2010-01-14 22:40:19Z mike $"
+ * "$Id: ipp.c 9808 2011-05-26 12:03:28Z mike $"
*
- * IPP backend for the Common UNIX Printing System (CUPS).
+ * IPP backend for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -18,14 +18,16 @@
*
* main() - Send a file to the printer or server.
* cancel_job() - Cancel a print job.
- * check_printer_state() - Check the printer state...
- * compress_files() - Compress print files...
+ * check_printer_state() - Check the printer state.
+ * compress_files() - Compress print files.
+ * monitor_printer() - Monitor the printer state.
+ * new_request() - Create a new print creation or validation request.
* password_cb() - Disable the password prompt for
* cupsDoFileRequest().
* report_attr() - Report an IPP attribute value.
* report_printer_state() - Report the printer state.
- * run_pictwps_filter() - Convert PICT files to PostScript when printing
- * remotely.
+ * run_as_user() - Run the IPP backend as the printing user.
+ * timeout_cb() - Handle HTTP timeouts.
* sigterm_handler() - Handle 'terminate' signals that stop the backend.
*/
@@ -33,47 +35,136 @@
* Include necessary headers.
*/
-#include <cups/http-private.h>
#include "backend-private.h"
+#include <cups/array-private.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
+# include <xpc/xpc.h>
+# define kPMPrintUIToolAgent "com.apple.printuitool.agent"
+# define kPMStartJob 100
+# define kPMWaitForJob 101
+extern void xpc_connection_set_target_uid(xpc_connection_t connection,
+ uid_t uid);
+#endif /* HAVE_GSSAPI && HAVE_XPC */
+
+
+/*
+ * Types...
+ */
+
+typedef struct _cups_monitor_s /**** Monitoring data ****/
+{
+ const char *uri, /* Printer URI */
+ *hostname, /* Hostname */
+ *user, /* Username */
+ *resource; /* Resource path */
+ int port, /* Port number */
+ version, /* IPP version */
+ job_id; /* Job ID for submitted job */
+ http_encryption_t encryption; /* Use encryption? */
+ ipp_jstate_t job_state; /* Current job state */
+ ipp_pstate_t printer_state; /* Current printer state */
+} _cups_monitor_t;
+
/*
* Globals...
*/
-static char *password = NULL; /* Password for device URI */
-static int password_tries = 0; /* Password tries */
-static const char *auth_info_required = "none";
+static const char *auth_info_required;
/* New auth-info-required value */
-#ifdef __APPLE__
-static char pstmpname[1024] = ""; /* Temporary PostScript file name */
-#endif /* __APPLE__ */
-static char tmpfilename[1024] = ""; /* Temporary spool file name */
-static int job_cancelled = 0; /* Job cancelled? */
+#if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
+static int child_pid = 0; /* Child process ID */
+#endif /* HAVE_GSSAPI && HAVE_XPC */
+static const char * const jattrs[] = /* Job attributes we want */
+{
+ "job-impressions-completed",
+ "job-media-sheets-completed",
+ "job-state",
+ "job-state-reasons"
+};
+static int job_canceled = 0;
+ /* Job cancelled? */
+static char *password = NULL;
+ /* Password for device URI */
+static int password_tries = 0;
+ /* Password tries */
+static const char * const pattrs[] = /* Printer attributes we want */
+{
+ "copies-supported",
+ "cups-version",
+ "document-format-supported",
+ "marker-colors",
+ "marker-high-levels",
+ "marker-levels",
+ "marker-low-levels",
+ "marker-message",
+ "marker-names",
+ "marker-types",
+ "media-col-supported",
+ "multiple-document-handling-supported",
+ "operations-supported",
+ "printer-alert",
+ "printer-alert-description",
+ "printer-is-accepting-jobs",
+ "printer-state",
+ "printer-state-message",
+ "printer-state-reasons",
+};
+static const char * const remote_job_states[] =
+{ /* Remote job state keywords */
+ "+cups-remote-pending",
+ "+cups-remote-pending-held",
+ "+cups-remote-processing",
+ "+cups-remote-stopped",
+ "+cups-remote-canceled",
+ "+cups-remote-aborted",
+ "+cups-remote-completed"
+};
+static _cups_mutex_t report_mutex = _CUPS_MUTEX_INITIALIZER;
+ /* Mutex to control access */
+static int num_attr_cache = 0;
+ /* Number of cached attributes */
+static cups_option_t *attr_cache = NULL;
+ /* Cached attributes */
+static cups_array_t *state_reasons; /* Array of printe-state-reasons keywords */
+static char tmpfilename[1024] = "";
+ /* Temporary spool file name */
/*
* Local functions...
*/
-static void cancel_job(http_t *http, const char *uri, int id,
- const char *resource, const char *user, int version);
-static void check_printer_state(http_t *http, const char *uri,
- const char *resource, const char *user,
- int version, int job_id);
+static void cancel_job(http_t *http, const char *uri, int id,
+ const char *resource, const char *user,
+ int version);
+static ipp_pstate_t check_printer_state(http_t *http, const char *uri,
+ const char *resource,
+ const char *user, int version);
#ifdef HAVE_LIBZ
-static void compress_files(int num_files, char **files);
+static void compress_files(int num_files, char **files);
#endif /* HAVE_LIBZ */
-static const char *password_cb(const char *);
-static void report_attr(ipp_attribute_t *attr);
-static int report_printer_state(ipp_t *ipp, int job_id);
-
-#ifdef __APPLE__
-static int run_pictwps_filter(char **argv, const char *filename);
-#endif /* __APPLE__ */
-static void sigterm_handler(int sig);
+static void *monitor_printer(_cups_monitor_t *monitor);
+static ipp_t *new_request(ipp_op_t op, int version, const char *uri,
+ const char *user, const char *title,
+ int num_options, cups_option_t *options,
+ const char *compression, int copies,
+ const char *format, _ppd_cache_t *pc,
+ ipp_attribute_t *media_col_sup,
+ ipp_attribute_t *doc_handling_sup);
+static const char *password_cb(const char *);
+static void report_attr(ipp_attribute_t *attr);
+static void report_printer_state(ipp_t *ipp);
+#if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
+static int run_as_user(int argc, char *argv[], uid_t uid,
+ const char *device_uri, int fd);
+#endif /* HAVE_GSSAPI && HAVE_XPC */
+static void sigterm_handler(int sig);
+static int timeout_cb(http_t *http, void *user_data);
+static void update_reasons(ipp_attribute_t *attr, const char *s);
/*
@@ -102,65 +193,60 @@ main(int argc, /* I - Number of command-line args */
*name, /* Name of option */
*value, /* Value of option */
sep; /* Separator character */
+ http_addrlist_t *addrlist; /* Address of printer */
int snmp_fd, /* SNMP socket */
start_count, /* Page count via SNMP at start */
page_count, /* Page count via SNMP */
have_supplies; /* Printer supports supply levels? */
int num_files; /* Number of files to print */
char **files, /* Files to print */
- *filename; /* Pointer to single filename */
+ *compatfile = NULL; /* Compatibility filename */
+ off_t compatsize = 0; /* Size of compatibility file */
int port; /* Port number (not used) */
+ char portname[255]; /* Port name */
char uri[HTTP_MAX_URI]; /* Updated URI without user/pass */
+ http_status_t http_status; /* Status of HTTP request */
ipp_status_t ipp_status; /* Status of IPP request */
http_t *http; /* HTTP connection */
ipp_t *request, /* IPP request */
*response, /* IPP response */
*supported; /* get-printer-attributes response */
time_t start_time; /* Time of first connect */
- int recoverable; /* Recoverable error shown? */
int contimeout; /* Connection timeout */
- int delay; /* Delay for retries... */
- int compression, /* Do compression of the job data? */
- waitjob, /* Wait for job complete? */
+ int delay, /* Delay for retries */
+ prev_delay; /* Previous delay */
+ const char *compression; /* Compression mode */
+ int waitjob, /* Wait for job complete? */
waitprinter; /* Wait for printer ready? */
+ _cups_monitor_t monitor; /* Monitoring data */
ipp_attribute_t *job_id_attr; /* job-id attribute */
int job_id; /* job-id value */
ipp_attribute_t *job_sheets; /* job-media-sheets-completed */
ipp_attribute_t *job_state; /* job-state */
ipp_attribute_t *copies_sup; /* copies-supported */
+ ipp_attribute_t *cups_version; /* cups-version */
ipp_attribute_t *format_sup; /* document-format-supported */
+ ipp_attribute_t *media_col_sup; /* media-col-supported */
+ ipp_attribute_t *operations_sup; /* operations-supported */
+ ipp_attribute_t *doc_handling_sup; /* multiple-document-handling-supported */
ipp_attribute_t *printer_state; /* printer-state attribute */
ipp_attribute_t *printer_accepting; /* printer-is-accepting-jobs */
+ int validate_job; /* Does printer support Validate-Job? */
int copies, /* Number of copies for job */
copies_remaining; /* Number of copies remaining */
const char *content_type, /* CONTENT_TYPE environment variable */
- *final_content_type; /* FINAL_CONTENT_TYPE environment var */
+ *final_content_type, /* FINAL_CONTENT_TYPE environment var */
+ *document_format; /* document-format value */
+ int fd; /* File descriptor */
+ off_t bytes = 0; /* Bytes copied */
+ char buffer[16384]; /* Copy buffer */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
int version; /* IPP version */
- static const char * const pattrs[] =
- { /* Printer attributes we want */
- "com.apple.print.recoverable-message",
- "copies-supported",
- "document-format-supported",
- "marker-colors",
- "marker-high-levels",
- "marker-levels",
- "marker-low-levels",
- "marker-message",
- "marker-names",
- "marker-types",
- "printer-is-accepting-jobs",
- "printer-state",
- "printer-state-message",
- "printer-state-reasons",
- };
- static const char * const jattrs[] =
- { /* Job attributes we want */
- "job-media-sheets-completed",
- "job-state"
- };
+ ppd_file_t *ppd; /* PPD file */
+ _ppd_cache_t *pc; /* PPD cache and mapping data */
+ fd_set input; /* Input set for select() */
/*
@@ -211,12 +297,75 @@ main(int argc, /* I - Number of command-line args */
else if (argc < 6)
{
_cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
+ _("Usage: %s job-id user title copies options [file]"),
argv[0]);
return (CUPS_BACKEND_STOP);
}
/*
+ * Get the device URI...
+ */
+
+ while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ return (CUPS_BACKEND_FAILED);
+ }
+
+ if ((auth_info_required = getenv("AUTH_INFO_REQUIRED")) == NULL)
+ auth_info_required = "none";
+
+ state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS"));
+
+#ifdef HAVE_GSSAPI
+ /*
+ * For Kerberos, become the printing user (if we can) to get the credentials
+ * that way.
+ */
+
+ if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
+ {
+ uid_t uid = (uid_t)atoi(value);
+ /* User ID */
+
+# ifdef HAVE_XPC
+ if (uid > 0)
+ {
+ if (argc == 6)
+ return (run_as_user(argc, argv, uid, device_uri, 0));
+ else
+ {
+ int status = 0; /* Exit status */
+
+ for (i = 6; i < argc && !status && !job_canceled; i ++)
+ {
+ if ((fd = open(argv[i], O_RDONLY)) >= 0)
+ {
+ status = run_as_user(argc, argv, uid, device_uri, fd);
+ close(fd);
+ }
+ else
+ {
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
+ status = CUPS_BACKEND_FAILED;
+ }
+ }
+
+ return (status);
+ }
+ }
+
+# else /* No XPC, just try to run as the user ID */
+ if (uid > 0)
+ seteuid(uid);
+# endif /* HAVE_XPC */
+ }
+#endif /* HAVE_GSSAPI */
+
+ /*
* Get the (final) content type...
*/
@@ -235,9 +384,6 @@ main(int argc, /* I - Number of command-line args */
* Extract the hostname and printer name from the URI...
*/
- if ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
- return (CUPS_BACKEND_FAILED);
-
httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
username, sizeof(username), hostname, sizeof(hostname), &port,
resource, sizeof(resource));
@@ -254,8 +400,8 @@ main(int argc, /* I - Number of command-line args */
* See if there are any options...
*/
- compression = 0;
- version = 11;
+ compression = NULL;
+ version = 20;
waitjob = 1;
waitprinter = 1;
contimeout = 7 * 24 * 60 * 60;
@@ -308,48 +454,48 @@ main(int argc, /* I - Number of command-line args */
* Process the option...
*/
- if (!strcasecmp(name, "waitjob"))
+ if (!_cups_strcasecmp(name, "waitjob"))
{
/*
* Wait for job completion?
*/
- waitjob = !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "true");
+ waitjob = !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") ||
+ !_cups_strcasecmp(value, "true");
}
- else if (!strcasecmp(name, "waitprinter"))
+ else if (!_cups_strcasecmp(name, "waitprinter"))
{
/*
* Wait for printer idle?
*/
- waitprinter = !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "true");
+ waitprinter = !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") ||
+ !_cups_strcasecmp(value, "true");
}
- else if (!strcasecmp(name, "encryption"))
+ else if (!_cups_strcasecmp(name, "encryption"))
{
/*
* Enable/disable encryption?
*/
- if (!strcasecmp(value, "always"))
+ if (!_cups_strcasecmp(value, "always"))
cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
- else if (!strcasecmp(value, "required"))
+ else if (!_cups_strcasecmp(value, "required"))
cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
- else if (!strcasecmp(value, "never"))
+ else if (!_cups_strcasecmp(value, "never"))
cupsSetEncryption(HTTP_ENCRYPT_NEVER);
- else if (!strcasecmp(value, "ifrequested"))
+ else if (!_cups_strcasecmp(value, "ifrequested"))
cupsSetEncryption(HTTP_ENCRYPT_IF_REQUESTED);
else
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unknown encryption option value \"%s\"!\n"),
- value);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unknown encryption option value: \"%s\"."),
+ value);
}
}
- else if (!strcasecmp(name, "version"))
+ else if (!_cups_strcasecmp(name, "version"))
{
if (!strcmp(value, "1.0"))
version = 10;
@@ -359,23 +505,24 @@ main(int argc, /* I - Number of command-line args */
version = 20;
else if (!strcmp(value, "2.1"))
version = 21;
+ else if (!strcmp(value, "2.2"))
+ version = 22;
else
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unknown version option value \"%s\"!\n"),
- value);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unknown version option value: \"%s\"."),
+ value);
}
}
#ifdef HAVE_LIBZ
- else if (!strcasecmp(name, "compression"))
+ else if (!_cups_strcasecmp(name, "compression"))
{
- compression = !strcasecmp(value, "true") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "on") ||
- !strcasecmp(value, "gzip");
+ if (!_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "yes") ||
+ !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "gzip"))
+ compression = "gzip";
}
#endif /* HAVE_LIBZ */
- else if (!strcasecmp(name, "contimeout"))
+ else if (!_cups_strcasecmp(name, "contimeout"))
{
/*
* Set the connection timeout...
@@ -390,9 +537,9 @@ main(int argc, /* I - Number of command-line args */
* Unknown option...
*/
- _cupsLangPrintf(stderr,
- _("ERROR: Unknown option \"%s\" with value \"%s\"!\n"),
- name, value);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unknown option \"%s\" with value \"%s\"."),
+ name, value);
}
}
}
@@ -405,64 +552,13 @@ main(int argc, /* I - Number of command-line args */
if (argc == 6)
{
- /*
- * Copy stdin to a temporary file...
- */
+ num_files = 0;
+ files = NULL;
+ send_options = !_cups_strcasecmp(final_content_type, "application/pdf") ||
+ !_cups_strcasecmp(final_content_type, "application/vnd.cups-pdf") ||
+ !_cups_strncasecmp(final_content_type, "image/", 6);
- int fd; /* File descriptor */
- http_addrlist_t *addrlist; /* Address list */
- off_t tbytes; /* Total bytes copied */
-
-
- fputs("STATE: +connecting-to-device\n", stderr);
- fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
-
- if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, "1")) == NULL)
- {
- _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
- hostname);
- return (CUPS_BACKEND_STOP);
- }
-
- snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
-
- if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
- return (CUPS_BACKEND_FAILED);
- }
-
- _cupsLangPuts(stderr, _("INFO: Copying print data...\n"));
-
- tbytes = backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
- backendNetworkSideCB);
-
- if (snmp_fd >= 0)
- _cupsSNMPClose(snmp_fd);
-
- httpAddrFreeList(addrlist);
-
- close(fd);
-
- /*
- * Don't try printing files less than 2 bytes...
- */
-
- if (tbytes <= 1)
- {
- _cupsLangPuts(stderr, _("ERROR: Empty print file!\n"));
- unlink(tmpfilename);
- return (CUPS_BACKEND_FAILED);
- }
-
- /*
- * Point to the single file from stdin...
- */
-
- filename = tmpfilename;
- num_files = 1;
- files = &filename;
- send_options = 0;
+ fputs("DEBUG: Sending stdin for job...\n", stderr);
}
else
{
@@ -478,9 +574,9 @@ main(int argc, /* I - Number of command-line args */
if (compression)
compress_files(num_files, files);
#endif /* HAVE_LIBZ */
- }
- fprintf(stderr, "DEBUG: %d files to send in job...\n", num_files);
+ fprintf(stderr, "DEBUG: %d files to send in job...\n", num_files);
+ }
/*
* Set the authentication info, if any...
@@ -499,7 +595,7 @@ main(int argc, /* I - Number of command-line args */
cupsSetUser(username);
}
- else if (!getuid())
+ else
{
/*
* Try loading authentication information from the environment.
@@ -514,23 +610,75 @@ main(int argc, /* I - Number of command-line args */
}
/*
- * Try connecting to the remote server...
+ * Try finding the remote server...
*/
- delay = 5;
- recoverable = 0;
- start_time = time(NULL);
+ start_time = time(NULL);
+
+ sprintf(portname, "%d", port);
+
+ update_reasons(NULL, "+connecting-to-device");
+ fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
- fputs("STATE: +connecting-to-device\n", stderr);
+ while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to locate printer \"%s\"."), hostname);
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ {
+ update_reasons(NULL, "-connecting-to-device");
+ return (CUPS_BACKEND_STOP);
+ }
+ }
+
+ http = _httpCreate(hostname, port, addrlist, cupsEncryption(), AF_UNSPEC);
+ httpSetTimeout(http, 30.0, timeout_cb, NULL);
+
+ /*
+ * See if the printer supports SNMP...
+ */
+
+ if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0)
+ {
+ have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
+ &start_count, NULL);
+ }
+ else
+ have_supplies = start_count = 0;
+
+ /*
+ * Wait for data from the filter...
+ */
+
+ if (num_files == 0)
+ {
+ if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
+ return (CUPS_BACKEND_OK);
+ else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0)
+ return (CUPS_BACKEND_OK);
+ }
+
+ /*
+ * Try connecting to the remote server...
+ */
+
+ delay = _cupsNextDelay(0, &prev_delay);
do
{
fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
- _cupsLangPuts(stderr, _("INFO: Connecting to printer...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
- if ((http = httpConnectEncrypt(hostname, port, cupsEncryption())) == NULL)
+ if (httpReconnect(http))
{
- if (job_cancelled)
+ int error = errno; /* Connection error */
+
+ if (http->status == HTTP_PKI_ERROR)
+ update_reasons(NULL, "+cups-certificate-error");
+
+ if (job_canceled)
break;
if (getenv("CLASS") != NULL)
@@ -542,12 +690,9 @@ main(int argc, /* I - Number of command-line args */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
-
- if (tmpfilename[0])
- unlink(tmpfilename);
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -555,85 +700,73 @@ main(int argc, /* I - Number of command-line args */
sleep(5);
+ update_reasons(NULL, "-connecting-to-device");
+
return (CUPS_BACKEND_FAILED);
}
+ fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
+
if (errno == ECONNREFUSED || errno == EHOSTDOWN ||
errno == EHOSTUNREACH)
{
if (contimeout && (time(NULL) - start_time) > contimeout)
{
- _cupsLangPuts(stderr, _("ERROR: Printer not responding!\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
+ update_reasons(NULL, "-connecting-to-device");
return (CUPS_BACKEND_FAILED);
}
- recoverable = 1;
-
- _cupsLangPrintf(stderr,
- _("WARNING: recoverable: Network host \'%s\' is busy; "
- "will retry in %d seconds...\n"),
- hostname, delay);
+ switch (error)
+ {
+ case EHOSTDOWN :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer may not exist or "
+ "is unavailable at this time."));
+ break;
+
+ case EHOSTUNREACH :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer is unreachable at this "
+ "time."));
+ break;
+
+ case ECONNREFUSED :
+ default :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer is busy."));
+ break;
+ }
sleep(delay);
- if (delay < 30)
- delay += 5;
- }
- else if (h_errno)
- {
- _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
- hostname);
- return (CUPS_BACKEND_STOP);
+ delay = _cupsNextDelay(delay, &prev_delay);
}
else
{
- recoverable = 1;
-
- fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
- _cupsLangPuts(stderr,
- _("ERROR: recoverable: Unable to connect to printer; will "
- "retry in 30 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
sleep(30);
}
- if (job_cancelled)
+ if (job_canceled)
break;
}
+ else
+ update_reasons(NULL, "-cups-certificate-error");
}
- while (http == NULL);
-
- if (job_cancelled || !http)
- {
- if (tmpfilename[0])
- unlink(tmpfilename);
+ while (http->fd < 0);
+ if (job_canceled || !http)
return (CUPS_BACKEND_FAILED);
- }
- fputs("STATE: -connecting-to-device\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Connected to printer...\n"));
+ update_reasons(NULL, "-connecting-to-device");
+ _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
-#ifdef AF_INET6
- if (http->hostaddr->addr.sa_family == AF_INET6)
- fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n",
- httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
- ntohs(http->hostaddr->ipv6.sin6_port));
- else
-#endif /* AF_INET6 */
- if (http->hostaddr->addr.sa_family == AF_INET)
- fprintf(stderr, "DEBUG: Connected to %s:%d (IPv4)...\n",
- httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
- ntohs(http->hostaddr->ipv4.sin_port));
-
- /*
- * See if the printer supports SNMP...
- */
-
- if ((snmp_fd = _cupsSNMPOpen(http->hostaddr->addr.sa_family)) >= 0)
- have_supplies = !backendSNMPSupplies(snmp_fd, http->hostaddr, &start_count,
- NULL);
- else
- have_supplies = start_count = 0;
+ fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
+ httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
+ _httpAddrPort(http->hostaddr));
/*
* Build a URI for the printer and fill the standard IPP attributes for
@@ -646,13 +779,17 @@ main(int argc, /* I - Number of command-line args */
/*
* First validate the destination and see if the device supports multiple
- * copies. We have to do this because some IPP servers (e.g. HP JetDirect)
- * don't support the copies attribute...
+ * copies...
*/
- copies_sup = NULL;
- format_sup = NULL;
- supported = NULL;
+ copies_sup = NULL;
+ cups_version = NULL;
+ format_sup = NULL;
+ media_col_sup = NULL;
+ supported = NULL;
+ operations_sup = NULL;
+ doc_handling_sup = NULL;
+ validate_job = 0;
do
{
@@ -684,57 +821,73 @@ main(int argc, /* I - Number of command-line args */
fputs("DEBUG: Getting supported attributes...\n", stderr);
if (http->version < HTTP_1_1)
- httpReconnect(http);
+ {
+ fprintf(stderr, "DEBUG: Printer responded with HTTP version %d.%d.\n",
+ http->version / 100, http->version % 100);
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-wrong-http-version");
+ }
- if ((supported = cupsDoRequest(http, request, resource)) == NULL)
- ipp_status = cupsLastError();
- else
- ipp_status = supported->request.status.status_code;
+ supported = cupsDoRequest(http, request, resource);
+ ipp_status = cupsLastError();
+
+ fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
+ ippErrorString(ipp_status), cupsLastErrorString());
if (ipp_status > IPP_OK_CONFLICT)
{
+ fprintf(stderr, "DEBUG: Get-Printer-Attributes returned %s.\n",
+ ippErrorString(ipp_status));
+
if (ipp_status == IPP_PRINTER_BUSY ||
ipp_status == IPP_SERVICE_UNAVAILABLE)
{
if (contimeout && (time(NULL) - start_time) > contimeout)
{
- _cupsLangPuts(stderr, _("ERROR: Printer not responding!\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
return (CUPS_BACKEND_FAILED);
}
- recoverable = 1;
-
- _cupsLangPrintf(stderr,
- _("WARNING: recoverable: Network host \'%s\' is busy; "
- "will retry in %d seconds...\n"),
- hostname, delay);
+ _cupsLangPrintFilter(stderr, "INFO", _("The printer is busy."));
- report_printer_state(supported, 0);
+ report_printer_state(supported);
sleep(delay);
- if (delay < 30)
- delay += 5;
+ delay = _cupsNextDelay(delay, &prev_delay);
}
else if ((ipp_status == IPP_BAD_REQUEST ||
ipp_status == IPP_VERSION_NOT_SUPPORTED) && version > 10)
{
/*
- * Switch to IPP/1.0...
+ * Switch to IPP/1.1 or IPP/1.0...
*/
- _cupsLangPrintf(stderr,
- _("INFO: Printer does not support IPP/%d.%d, trying "
- "IPP/1.0...\n"), version / 10, version % 10);
- version = 10;
+ if (version >= 20)
+ {
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer does not support IPP/%d.%d, trying "
+ "IPP/%s."), version / 10, version % 10, "1.1");
+ version = 11;
+ }
+ else
+ {
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer does not support IPP/%d.%d, trying "
+ "IPP/%s."), version / 10, version % 10, "1.0");
+ version = 10;
+ }
+
httpReconnect(http);
}
else if (ipp_status == IPP_NOT_FOUND)
{
- _cupsLangPuts(stderr, _("ERROR: Destination printer does not exist!\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer URI is incorrect or no longer "
+ "exists."));
- if (supported)
- ippDelete(supported);
+ ippDelete(supported);
return (CUPS_BACKEND_STOP);
}
@@ -749,33 +902,92 @@ main(int argc, /* I - Number of command-line args */
}
else
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to get printer status (%s)!\n"),
- cupsLastErrorString());
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to get printer status."));
sleep(10);
}
- if (supported)
- ippDelete(supported);
-
+ ippDelete(supported);
+ supported = NULL;
continue;
}
- else if ((copies_sup = ippFindAttribute(supported, "copies-supported",
- IPP_TAG_RANGE)) != NULL)
+
+ if (!getenv("CLASS"))
+ {
+ /*
+ * Check printer-is-accepting-jobs = false and printer-state-reasons for the
+ * "spool-area-full" keyword...
+ */
+
+ int busy = 0;
+
+ if ((printer_accepting = ippFindAttribute(supported,
+ "printer-is-accepting-jobs",
+ IPP_TAG_BOOLEAN)) != NULL &&
+ !printer_accepting->values[0].boolean)
+ busy = 1;
+ else if (!printer_accepting)
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-printer-is-accepting-jobs");
+
+ if ((printer_state = ippFindAttribute(supported,
+ "printer-state-reasons",
+ IPP_TAG_KEYWORD)) != NULL && !busy)
+ {
+ for (i = 0; i < printer_state->num_values; i ++)
+ if (!strcmp(printer_state->values[0].string.text,
+ "spool-area-full") ||
+ !strncmp(printer_state->values[0].string.text, "spool-area-full-",
+ 16))
+ {
+ busy = 1;
+ break;
+ }
+ }
+ else
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-printer-state-reasons");
+
+ if (busy)
+ {
+ _cupsLangPrintFilter(stderr, "INFO", _("The printer is busy."));
+
+ report_printer_state(supported);
+
+ sleep(delay);
+
+ delay = _cupsNextDelay(delay, &prev_delay);
+
+ ippDelete(supported);
+ supported = NULL;
+ continue;
+ }
+ }
+
+ /*
+ * Check for supported attributes...
+ */
+
+ if ((copies_sup = ippFindAttribute(supported, "copies-supported",
+ IPP_TAG_RANGE)) != NULL)
{
/*
* Has the "copies-supported" attribute - does it have an upper
* bound > 1?
*/
+ fprintf(stderr, "DEBUG: copies-supported=%d-%d\n",
+ copies_sup->values[0].range.lower,
+ copies_sup->values[0].range.upper);
+
if (copies_sup->values[0].range.upper <= 1)
copies_sup = NULL; /* No */
}
- format_sup = ippFindAttribute(supported, "document-format-supported",
- IPP_TAG_MIMETYPE);
+ cups_version = ippFindAttribute(supported, "cups-version", IPP_TAG_TEXT);
- if (format_sup)
+ if ((format_sup = ippFindAttribute(supported, "document-format-supported",
+ IPP_TAG_MIMETYPE)) != NULL)
{
fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
format_sup->num_values);
@@ -784,7 +996,71 @@ main(int argc, /* I - Number of command-line args */
format_sup->values[i].string.text);
}
- report_printer_state(supported, 0);
+ if ((media_col_sup = ippFindAttribute(supported, "media-col-supported",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ fprintf(stderr, "DEBUG: media-col-supported (%d values)\n",
+ media_col_sup->num_values);
+ for (i = 0; i < media_col_sup->num_values; i ++)
+ fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
+ media_col_sup->values[i].string.text);
+ }
+
+ if ((operations_sup = ippFindAttribute(supported, "operations-supported",
+ IPP_TAG_ENUM)) != NULL)
+ {
+ for (i = 0; i < operations_sup->num_values; i ++)
+ if (operations_sup->values[i].integer == IPP_PRINT_JOB)
+ break;
+
+ if (i >= operations_sup->num_values)
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-print-job");
+
+ for (i = 0; i < operations_sup->num_values; i ++)
+ if (operations_sup->values[i].integer == IPP_CANCEL_JOB)
+ break;
+
+ if (i >= operations_sup->num_values)
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-cancel-job");
+
+ for (i = 0; i < operations_sup->num_values; i ++)
+ if (operations_sup->values[i].integer == IPP_GET_JOB_ATTRIBUTES)
+ break;
+
+ if (i >= operations_sup->num_values)
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-get-job-attributes");
+
+ for (i = 0; i < operations_sup->num_values; i ++)
+ if (operations_sup->values[i].integer == IPP_GET_PRINTER_ATTRIBUTES)
+ break;
+
+ if (i >= operations_sup->num_values)
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-get-printer-attributes");
+
+ for (i = 0; i < operations_sup->num_values; i ++)
+ if (operations_sup->values[i].integer == IPP_VALIDATE_JOB)
+ {
+ validate_job = 1;
+ break;
+ }
+
+ if (!validate_job)
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-validate-job");
+ }
+ else
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-operations-supported");
+
+ doc_handling_sup = ippFindAttribute(supported,
+ "multiple-document-handling-supported",
+ IPP_TAG_KEYWORD);
+
+ report_printer_state(supported);
}
while (ipp_status > IPP_OK_CONFLICT);
@@ -813,16 +1089,13 @@ main(int argc, /* I - Number of command-line args */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
ippDelete(supported);
httpClose(http);
- if (tmpfilename[0])
- unlink(tmpfilename);
-
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
*/
@@ -833,18 +1106,6 @@ main(int argc, /* I - Number of command-line args */
}
}
- if (recoverable)
- {
- /*
- * If we've shown a recoverable error make sure the printer proxies
- * have a chance to see the recovered message. Not pretty but
- * necessary for now...
- */
-
- fputs("INFO: recovered: \n", stderr);
- sleep(5);
- }
-
/*
* See if the printer supports multiple copies...
*/
@@ -855,201 +1116,296 @@ main(int argc, /* I - Number of command-line args */
{
copies_remaining = 1;
- if (argc < 7)
+ if (argc < 7 && !send_options)
copies = 1;
}
else
copies_remaining = copies;
/*
- * Then issue the print-job request...
+ * Prepare remaining printing options...
*/
- job_id = 0;
+ options = NULL;
+ pc = NULL;
- while (copies_remaining > 0)
+ if (send_options)
{
- /*
- * Check for side-channel requests...
- */
+ num_options = cupsParseOptions(argv[5], 0, &options);
- backendCheckSideChannel(snmp_fd, http->hostaddr);
+ if (!cups_version && media_col_sup)
+ {
+ /*
+ * Load the PPD file and generate PWG attribute mapping information...
+ */
- /*
- * Build the IPP request...
- */
+ ppd = ppdOpenFile(getenv("PPD"));
+ pc = _ppdCacheCreateWithPPD(ppd);
- if (job_cancelled)
- break;
+ ppdClose(ppd);
+ }
+ }
+ else
+ num_options = 0;
- if (num_files > 1)
- request = ippNewRequest(IPP_CREATE_JOB);
- else
- request = ippNewRequest(IPP_PRINT_JOB);
+ document_format = NULL;
- request->request.op.version[0] = version / 10;
- request->request.op.version[1] = version % 10;
+ if (format_sup != NULL)
+ {
+ for (i = 0; i < format_sup->num_values; i ++)
+ if (!_cups_strcasecmp(final_content_type, format_sup->values[i].string.text))
+ {
+ document_format = final_content_type;
+ break;
+ }
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ if (!document_format)
+ {
+ for (i = 0; i < format_sup->num_values; i ++)
+ if (!_cups_strcasecmp("application/octet-stream",
+ format_sup->values[i].string.text))
+ {
+ document_format = "application/octet-stream";
+ break;
+ }
+ }
+ }
- fprintf(stderr, "DEBUG: printer-uri = \"%s\"\n", uri);
+ /*
+ * If the printer does not support HTTP/1.1 (which IPP requires), copy stdin
+ * to a temporary file so that we can do a HTTP/1.0 submission...
+ *
+ * (I hate compatibility hacks!)
+ */
- if (argv[2][0])
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requesting-user-name", NULL, argv[2]);
+ if (http->version < HTTP_1_1 && num_files == 0)
+ {
+ if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
+ {
+ perror("DEBUG: Unable to create temporary file");
+ return (CUPS_BACKEND_FAILED);
+ }
- fprintf(stderr, "DEBUG: requesting-user-name = \"%s\"\n", argv[2]);
+ _cupsLangPrintFilter(stderr, "INFO", _("Copying print data."));
- /*
- * Only add a "job-name" attribute if the remote server supports
- * copy generation - some IPP implementations like HP's don't seem
- * to like UTF-8 job names (STR #1837)...
- */
+ compatsize = backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
+ backendNetworkSideCB);
- if (argv[3][0] && copies_sup)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
- argv[3]);
+ close(fd);
- fprintf(stderr, "DEBUG: job-name = \"%s\"\n", argv[3]);
+ compatfile = tmpfilename;
+ files = &compatfile;
+ num_files = 1;
+ }
+ else if (http->version < HTTP_1_1 && num_files == 1)
+ {
+ struct stat fileinfo; /* File information */
-#ifdef HAVE_LIBZ
- if (compression)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "compression", NULL, "gzip");
-#endif /* HAVE_LIBZ */
+ if (!stat(files[0], &fileinfo))
+ compatsize = fileinfo.st_size;
+ }
- /*
- * Handle options on the command-line...
- */
+ /*
+ * Start monitoring the printer in the background...
+ */
- options = NULL;
- num_options = cupsParseOptions(argv[5], 0, &options);
+ monitor.uri = uri;
+ monitor.hostname = hostname;
+ monitor.user = argv[2];
+ monitor.resource = resource;
+ monitor.port = port;
+ monitor.version = version;
+ monitor.job_id = 0;
+ monitor.encryption = cupsEncryption();
+ monitor.job_state = IPP_JOB_PENDING;
+ monitor.printer_state = IPP_PRINTER_IDLE;
-#ifdef __APPLE__
- if (!strcasecmp(final_content_type, "application/pictwps") &&
- num_files == 1)
- {
- if (format_sup != NULL)
- {
- for (i = 0; i < format_sup->num_values; i ++)
- if (!strcasecmp(final_content_type, format_sup->values[i].string.text))
- break;
- }
+ _cupsThreadCreate((_cups_thread_func_t)monitor_printer, &monitor);
- if (format_sup == NULL || i >= format_sup->num_values)
- {
- /*
- * Remote doesn't support "application/pictwps" (i.e. it's not MacOS X)
- * so convert the document to PostScript...
- */
+ /*
+ * Validate access to the printer...
+ */
- if (run_pictwps_filter(argv, files[0]))
- {
- if (pstmpname[0])
- unlink(pstmpname);
+ while (!job_canceled && validate_job)
+ {
+ request = new_request(IPP_VALIDATE_JOB, version, uri, argv[2], argv[3],
+ num_options, options, compression,
+ copies_sup ? copies : 1, document_format, pc,
+ media_col_sup, doc_handling_sup);
- if (tmpfilename[0])
- unlink(tmpfilename);
+ ippDelete(cupsDoRequest(http, request, resource));
- return (CUPS_BACKEND_FAILED);
- }
+ ipp_status = cupsLastError();
- files[0] = pstmpname;
+ fprintf(stderr, "DEBUG: Validate-Job: %s (%s)\n",
+ ippErrorString(ipp_status), cupsLastErrorString());
- /*
- * Change the MIME type to application/postscript and change the
- * number of copies to 1...
- */
+ if (job_canceled)
+ break;
- final_content_type = "application/postscript";
- copies = 1;
- copies_remaining = 1;
- send_options = 0;
- }
+ if (ipp_status == IPP_SERVICE_UNAVAILABLE || ipp_status == IPP_PRINTER_BUSY)
+ {
+ _cupsLangPrintFilter(stderr, "INFO", _("The printer is busy."));
+ sleep(10);
}
-#endif /* __APPLE__ */
-
- if (format_sup != NULL)
+ else if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
+ ipp_status == IPP_AUTHENTICATION_CANCELED)
{
- for (i = 0; i < format_sup->num_values; i ++)
- if (!strcasecmp(final_content_type, format_sup->values[i].string.text))
- break;
+ /*
+ * Update auth-info-required as needed...
+ */
- if (i < format_sup->num_values)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
- "document-format", NULL, final_content_type);
- }
+ fprintf(stderr, "DEBUG: WWW-Authenticate=\"%s\"\n",
+ httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE));
- if (copies_sup && version > 10 && send_options)
- {
/*
- * Only send options if the destination printer supports the copies
- * attribute and IPP/1.1. This is a hack for the HP and Lexmark
- * implementations of IPP, which do not accept extension attributes
- * and incorrectly report a client-error-bad-request error instead of
- * the successful-ok-unsupported-attributes status. In short, at least
- * some HP and Lexmark implementations of IPP are non-compliant.
+ * Normal authentication goes through the password callback, which sets
+ * auth_info_required to "username,password". Kerberos goes directly
+ * through GSSAPI, so look for Negotiate in the WWW-Authenticate header
+ * here and set auth_info_required as needed...
*/
- cupsEncodeOptions(request, num_options, options);
+ if (!strncmp(httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE),
+ "Negotiate", 9))
+ auth_info_required = "negotiate";
- ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies",
- copies);
+ goto cleanup;
}
+ else if (ipp_status == IPP_OPERATION_NOT_SUPPORTED)
+ {
+ /*
+ * This is all too common...
+ */
+
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-validate-job");
+ break;
+ }
+ else if (ipp_status < IPP_REDIRECTION_OTHER_SITE)
+ break;
+ }
- cupsFreeOptions(num_options, options);
+ /*
+ * Then issue the print-job request...
+ */
+ job_id = 0;
+
+ while (!job_canceled && copies_remaining > 0)
+ {
/*
- * If copies aren't supported, then we are likely dealing with an HP
- * JetDirect. The HP IPP implementation seems to close the connection
- * after every request - that is, it does *not* implement HTTP Keep-
- * Alive, which is REQUIRED by HTTP/1.1...
+ * Check for side-channel requests...
*/
- if (!copies_sup)
- httpReconnect(http);
+ backendCheckSideChannel(snmp_fd, http->hostaddr);
/*
- * Do the request...
+ * Build the IPP job creation request...
*/
- if (http->version < HTTP_1_1)
- httpReconnect(http);
+ if (job_canceled)
+ break;
+
+ request = new_request(num_files > 1 ? IPP_CREATE_JOB : IPP_PRINT_JOB,
+ version, uri, argv[2], argv[3], num_options, options,
+ compression, copies_sup ? copies : 1, document_format,
+ pc, media_col_sup, doc_handling_sup);
+
+ /*
+ * Do the request...
+ */
if (num_files > 1)
response = cupsDoRequest(http, request, resource);
else
- response = cupsDoFileRequest(http, request, resource, files[0]);
+ {
+ size_t length = 0; /* Length of request */
+
+ if (compatsize > 0)
+ {
+ fputs("DEBUG: Sending file using HTTP/1.0 Content-Length...\n", stderr);
+ length = ippLength(request) + (size_t)compatsize;
+ }
+ else
+ fputs("DEBUG: Sending file using HTTP/1.1 chunking...\n", stderr);
+
+ http_status = cupsSendRequest(http, request, resource, length);
+ if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
+ {
+ if (num_files == 1)
+ fd = open(files[0], O_RDONLY);
+ else
+ {
+ fd = 0;
+ http_status = cupsWriteRequestData(http, buffer, bytes);
+ }
+
+ while (http_status == HTTP_CONTINUE)
+ {
+ /*
+ * Check for side-channel requests and more print data...
+ */
+
+ FD_ZERO(&input);
+ FD_SET(fd, &input);
+ FD_SET(snmp_fd, &input);
+
+ while (select(fd > snmp_fd ? fd + 1 : snmp_fd + 1, &input, NULL, NULL,
+ NULL) <= 0 && !job_canceled);
+
+ if (FD_ISSET(snmp_fd, &input))
+ backendCheckSideChannel(snmp_fd, http->hostaddr);
+
+ if (FD_ISSET(fd, &input))
+ {
+ if ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ {
+ fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
+
+ if (cupsWriteRequestData(http, buffer, bytes) != HTTP_CONTINUE)
+ break;
+ }
+ else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
+ break;
+ }
+ }
+
+ if (num_files == 1)
+ close(fd);
+ }
+
+ response = cupsGetResponse(http, resource);
+ ippDelete(request);
+ }
ipp_status = cupsLastError();
+ fprintf(stderr, "DEBUG: %s: %s (%s)\n",
+ num_files > 1 ? "Create-Job" : "Print-Job",
+ ippErrorString(ipp_status), cupsLastErrorString());
+
if (ipp_status > IPP_OK_CONFLICT)
{
job_id = 0;
- if (job_cancelled)
+ if (job_canceled)
break;
if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
ipp_status == IPP_PRINTER_BUSY)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 10 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("The printer is busy."));
sleep(10);
- }
- else if ((ipp_status == IPP_BAD_REQUEST ||
- ipp_status == IPP_VERSION_NOT_SUPPORTED) && version > 10)
- {
- /*
- * Switch to IPP/1.0...
- */
- _cupsLangPrintf(stderr,
- _("INFO: Printer does not support IPP/%d.%d, trying "
- "IPP/1.0...\n"), version / 10, version % 10);
- version = 10;
- httpReconnect(http);
+ if (num_files == 0)
+ {
+ /*
+ * We can't re-submit when we have no files to print, so exit
+ * immediately with the right status code...
+ */
+
+ goto cleanup;
+ }
}
else
{
@@ -1057,8 +1413,8 @@ main(int argc, /* I - Number of command-line args */
* Update auth-info-required as needed...
*/
- _cupsLangPrintf(stderr, _("ERROR: Print file was not accepted (%s)!\n"),
- cupsLastErrorString());
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Print file was not accepted."));
if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN)
{
@@ -1076,25 +1432,39 @@ main(int argc, /* I - Number of command-line args */
"Negotiate", 9))
auth_info_required = "negotiate";
}
+ else
+ sleep(10);
+
+ if (num_files == 0)
+ {
+ /*
+ * We can't re-submit when we have no files to print, so exit
+ * immediately with the right status code...
+ */
+
+ goto cleanup;
+ }
}
}
else if ((job_id_attr = ippFindAttribute(response, "job-id",
IPP_TAG_INTEGER)) == NULL)
{
- _cupsLangPuts(stderr,
- _("NOTICE: Print file accepted - job ID unknown.\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Print file accepted - job ID unknown."));
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-job-id");
job_id = 0;
}
else
{
- job_id = job_id_attr->values[0].integer;
- _cupsLangPrintf(stderr, _("NOTICE: Print file accepted - job ID %d.\n"),
- job_id);
+ monitor.job_id = job_id = job_id_attr->values[0].integer;
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Print file accepted - job ID %d."), job_id);
}
ippDelete(response);
- if (job_cancelled)
+ if (job_canceled)
break;
if (job_id && num_files > 1)
@@ -1131,18 +1501,40 @@ main(int argc, /* I - Number of command-line args */
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
"document-format", NULL, content_type);
- if (http->version < HTTP_1_1)
- httpReconnect(http);
+ fprintf(stderr, "DEBUG: Sending file %d using chunking...\n", i + 1);
+ http_status = cupsSendRequest(http, request, resource, 0);
+ if (http_status == HTTP_CONTINUE && request->state == IPP_DATA &&
+ (fd = open(files[i], O_RDONLY)) >= 0)
+ {
+ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ {
+ if (cupsWriteRequestData(http, buffer, bytes) != HTTP_CONTINUE)
+ break;
+ else
+ {
+ /*
+ * Check for side-channel requests...
+ */
+
+ backendCheckSideChannel(snmp_fd, http->hostaddr);
+ }
+ }
+
+ close(fd);
+ }
- ippDelete(cupsDoFileRequest(http, request, resource, files[i]));
+ ippDelete(cupsGetResponse(http, resource));
+ ippDelete(request);
+
+ fprintf(stderr, "DEBUG: Send-Document: %s (%s)\n",
+ ippErrorString(cupsLastError()), cupsLastErrorString());
if (cupsLastError() > IPP_OK_CONFLICT)
{
ipp_status = cupsLastError();
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to add file %d to job: %s\n"),
- job_id, cupsLastErrorString());
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to add document to print job."));
break;
}
}
@@ -1166,9 +1558,9 @@ main(int argc, /* I - Number of command-line args */
if (!job_id || !waitjob)
continue;
- _cupsLangPuts(stderr, _("INFO: Waiting for job to complete...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Waiting for job to complete."));
- for (delay = 1; !job_cancelled;)
+ for (delay = _cupsNextDelay(0, &prev_delay); !job_canceled;)
{
/*
* Check for side-channel requests...
@@ -1202,9 +1594,7 @@ main(int argc, /* I - Number of command-line args */
* Do the request...
*/
- if (!copies_sup || http->version < HTTP_1_1)
- httpReconnect(http);
-
+ httpReconnect(http);
response = cupsDoRequest(http, request, resource);
ipp_status = cupsLastError();
@@ -1214,12 +1604,17 @@ main(int argc, /* I - Number of command-line args */
* Job has gone away and/or the server has no job history...
*/
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-job-history");
ippDelete(response);
ipp_status = IPP_OK;
break;
}
+ fprintf(stderr, "DEBUG: Get-Job-Attributes: %s (%s)\n",
+ ippErrorString(ipp_status), cupsLastErrorString());
+
if (ipp_status > IPP_OK_CONFLICT)
{
if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
@@ -1227,9 +1622,8 @@ main(int argc, /* I - Number of command-line args */
{
ippDelete(response);
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to get job %d attributes (%s)!\n"),
- job_id, cupsLastErrorString());
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to get print job status."));
break;
}
}
@@ -1239,18 +1633,34 @@ main(int argc, /* I - Number of command-line args */
if ((job_state = ippFindAttribute(response, "job-state",
IPP_TAG_ENUM)) != NULL)
{
+ /*
+ * Reflect the remote job state in the local queue...
+ */
+
+ if (cups_version &&
+ job_state->values[0].integer >= IPP_JOB_PENDING &&
+ job_state->values[0].integer <= IPP_JOB_COMPLETED)
+ update_reasons(NULL,
+ remote_job_states[job_state->values[0].integer -
+ IPP_JOB_PENDING]);
+
+ if ((job_sheets = ippFindAttribute(response,
+ "job-media-sheets-completed",
+ IPP_TAG_INTEGER)) == NULL)
+ job_sheets = ippFindAttribute(response,
+ "job-impressions-completed",
+ IPP_TAG_INTEGER);
+
+ if (job_sheets)
+ fprintf(stderr, "PAGE: total %d\n",
+ job_sheets->values[0].integer);
+
/*
* Stop polling if the job is finished or pending-held...
*/
if (job_state->values[0].integer > IPP_JOB_STOPPED)
{
- if ((job_sheets = ippFindAttribute(response,
- "job-media-sheets-completed",
- IPP_TAG_INTEGER)) != NULL)
- fprintf(stderr, "PAGE: total %d\n",
- job_sheets->values[0].integer);
-
ippDelete(response);
break;
}
@@ -1263,8 +1673,8 @@ main(int argc, /* I - Number of command-line args */
* the job...
*/
- fputs("DEBUG: No job-state available from printer - stopping queue.\n",
- stderr);
+ update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
+ "cups-ipp-missing-job-state");
ipp_status = IPP_INTERNAL_ERROR;
break;
}
@@ -1273,20 +1683,12 @@ main(int argc, /* I - Number of command-line args */
ippDelete(response);
/*
- * Check the printer state and report it if necessary...
- */
-
- check_printer_state(http, uri, resource, argv[2], version, job_id);
-
- /*
- * Wait 1-10 seconds before polling again...
+ * Wait before polling again...
*/
sleep(delay);
- delay ++;
- if (delay > 10)
- delay = 1;
+ delay = _cupsNextDelay(delay, &prev_delay);
}
}
@@ -1294,20 +1696,20 @@ main(int argc, /* I - Number of command-line args */
* Cancel the job as needed...
*/
- if (job_cancelled && job_id)
+ if (job_canceled && job_id)
cancel_job(http, uri, job_id, resource, argv[2], version);
/*
* Check the printer state and report it if necessary...
*/
- check_printer_state(http, uri, resource, argv[2], version, job_id);
+ check_printer_state(http, uri, resource, argv[2], version);
/*
* Collect the final page count as needed...
*/
- if (have_supplies &&
+ if (have_supplies &&
!backendSNMPSupplies(snmp_fd, http->hostaddr, &page_count, NULL) &&
page_count > start_count)
fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
@@ -1325,6 +1727,11 @@ main(int argc, /* I - Number of command-line args */
* Free memory...
*/
+ cleanup:
+
+ cupsFreeOptions(num_options, options);
+ _ppdCacheDestroy(pc);
+
httpClose(http);
ippDelete(supported);
@@ -1344,26 +1751,28 @@ main(int argc, /* I - Number of command-line args */
}
#endif /* HAVE_LIBZ */
-#ifdef __APPLE__
- if (pstmpname[0])
- unlink(pstmpname);
-#endif /* __APPLE__ */
-
/*
* Return the queue status...
*/
- fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
+ if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
+ ipp_status == IPP_AUTHENTICATION_CANCELED ||
+ ipp_status <= IPP_OK_CONFLICT)
+ fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
- if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN)
+ if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
+ ipp_status == IPP_AUTHENTICATION_CANCELED)
return (CUPS_BACKEND_AUTH_REQUIRED);
else if (ipp_status == IPP_INTERNAL_ERROR)
return (CUPS_BACKEND_STOP);
- else if (ipp_status > IPP_OK_CONFLICT)
+ else if (ipp_status == IPP_DOCUMENT_FORMAT ||
+ ipp_status == IPP_CONFLICT)
return (CUPS_BACKEND_FAILED);
+ else if (ipp_status > IPP_OK_CONFLICT)
+ return (CUPS_BACKEND_RETRY_CURRENT);
else
{
- _cupsLangPuts(stderr, _("INFO: Ready to print.\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Ready to print."));
return (CUPS_BACKEND_OK);
}
}
@@ -1384,7 +1793,7 @@ cancel_job(http_t *http, /* I - HTTP connection */
ipp_t *request; /* Cancel-Job request */
- _cupsLangPuts(stderr, _("INFO: Canceling print job...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Canceling print job."));
request = ippNewRequest(IPP_CANCEL_JOB);
request->request.op.version[0] = version / 10;
@@ -1402,47 +1811,34 @@ cancel_job(http_t *http, /* I - HTTP connection */
* Do the request...
*/
- if (http->version < HTTP_1_1)
- httpReconnect(http);
-
ippDelete(cupsDoRequest(http, request, resource));
if (cupsLastError() > IPP_OK_CONFLICT)
- _cupsLangPrintf(stderr, _("ERROR: Unable to cancel job %d: %s\n"), id,
- cupsLastErrorString());
+ _cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
}
/*
- * 'check_printer_state()' - Check the printer state...
+ * 'check_printer_state()' - Check the printer state.
*/
-static void
+static ipp_pstate_t /* O - Current printer-state */
check_printer_state(
http_t *http, /* I - HTTP connection */
const char *uri, /* I - Printer URI */
const char *resource, /* I - Resource path */
const char *user, /* I - Username, if any */
- int version, /* I - IPP version */
- int job_id) /* I - Current job ID */
-{
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- static const char * const attrs[] = /* Attributes we want */
- {
- "com.apple.print.recoverable-message",
- "marker-colors",
- "marker-levels",
- "marker-message",
- "marker-names",
- "marker-types",
- "printer-state-message",
- "printer-state-reasons"
- };
+ int version) /* I - IPP version */
+ {
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* Attribute in response */
+ ipp_pstate_t printer_state = IPP_PRINTER_STOPPED;
+ /* Current printer-state */
/*
- * Check on the printer state...
+ * Send a Get-Printer-Attributes request and log the results...
*/
request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
@@ -1450,34 +1846,41 @@ check_printer_state(
request->request.op.version[1] = version % 10;
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ NULL, uri);
if (user && user[0])
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requesting-user-name", NULL, user);
+ "requesting-user-name", NULL, user);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes",
- (int)(sizeof(attrs) / sizeof(attrs[0])), NULL, attrs);
-
- /*
- * Do the request...
- */
-
- if (http->version < HTTP_1_1)
- httpReconnect(http);
+ "requested-attributes",
+ (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
if ((response = cupsDoRequest(http, request, resource)) != NULL)
{
- report_printer_state(response, job_id);
+ report_printer_state(response);
+
+ if ((attr = ippFindAttribute(response, "printer-state",
+ IPP_TAG_ENUM)) != NULL)
+ printer_state = (ipp_pstate_t)attr->values[0].integer;
+
ippDelete(response);
}
+
+ fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
+ ippErrorString(cupsLastError()), cupsLastErrorString());
+
+ /*
+ * Return the printer-state value...
+ */
+
+ return (printer_state);
}
#ifdef HAVE_LIBZ
/*
- * 'compress_files()' - Compress print files...
+ * 'compress_files()' - Compress print files.
*/
static void
@@ -1500,25 +1903,19 @@ compress_files(int num_files, /* I - Number of files */
{
if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to create temporary compressed print "
- "file: %s\n"), strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to create compressed print file"));
exit(CUPS_BACKEND_FAILED);
}
if ((out = cupsFileOpenFd(fd, "w9")) == NULL)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open temporary compressed print "
- "file: %s\n"), strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open compressed print file"));
exit(CUPS_BACKEND_FAILED);
}
if ((in = cupsFileOpen(files[i], "r")) == NULL)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open print file \"%s\": %s\n"),
- files[i], strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
cupsFileClose(out);
exit(CUPS_BACKEND_FAILED);
}
@@ -1527,9 +1924,8 @@ compress_files(int num_files, /* I - Number of files */
while ((bytes = cupsFileRead(in, buffer, sizeof(buffer))) > 0)
if (cupsFileWrite(out, buffer, bytes) < bytes)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to write %d bytes to \"%s\": %s\n"),
- (int)bytes, filename, strerror(errno));
+ _cupsLangPrintError("ERROR",
+ _("Unable to generate compressed print file"));
cupsFileClose(in);
cupsFileClose(out);
exit(CUPS_BACKEND_FAILED);
@@ -1554,6 +1950,365 @@ compress_files(int num_files, /* I - Number of files */
/*
+ * 'monitor_printer()' - Monitor the printer state.
+ */
+
+static void * /* O - Thread exit code */
+monitor_printer(
+ _cups_monitor_t *monitor) /* I - Monitoring data */
+{
+ http_t *http; /* Connection to printer */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* Attribute in response */
+ int delay, /* Current delay */
+ prev_delay; /* Previous delay */
+
+
+ /*
+ * Make a copy of the printer connection...
+ */
+
+ http = _httpCreate(monitor->hostname, monitor->port, NULL, monitor->encryption,
+ AF_UNSPEC);
+ httpSetTimeout(http, 30.0, timeout_cb, NULL);
+ cupsSetPasswordCB(password_cb);
+
+ /*
+ * Loop until the job is canceled, aborted, or completed.
+ */
+
+ delay = _cupsNextDelay(0, &prev_delay);
+
+ while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled)
+ {
+ /*
+ * Reconnect to the printer...
+ */
+
+ if (!httpReconnect(http))
+ {
+ /*
+ * Connected, so check on the printer state...
+ */
+
+ monitor->printer_state = check_printer_state(http, monitor->uri,
+ monitor->resource,
+ monitor->user,
+ monitor->version);
+
+ if (monitor->job_id > 0)
+ {
+ /*
+ * Check the status of the job itself...
+ */
+
+ request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES);
+ request->request.op.version[0] = monitor->version / 10;
+ request->request.op.version[1] = monitor->version % 10;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, monitor->uri);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+ monitor->job_id);
+
+ if (monitor->user && monitor->user[0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, monitor->user);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ (int)(sizeof(jattrs) / sizeof(jattrs[0])), NULL, jattrs);
+
+ /*
+ * Do the request...
+ */
+
+ response = cupsDoRequest(http, request, monitor->resource);
+
+ fprintf(stderr, "DEBUG: Get-Job-Attributes: %s (%s)\n",
+ ippErrorString(cupsLastError()), cupsLastErrorString());
+
+ if ((attr = ippFindAttribute(response, "job-state",
+ IPP_TAG_ENUM)) != NULL)
+ monitor->job_state = (ipp_jstate_t)attr->values[0].integer;
+ else
+ monitor->job_state = IPP_JOB_COMPLETED;
+
+ ippDelete(response);
+ }
+
+ /*
+ * Disconnect from the printer - we'll reconnect on the next poll...
+ */
+
+ _httpDisconnect(http);
+ }
+
+ /*
+ * Sleep for N seconds...
+ */
+
+ sleep(delay);
+
+ delay = _cupsNextDelay(delay, &prev_delay);
+ }
+
+ /*
+ * Cleanup and return...
+ */
+
+ httpClose(http);
+
+ return (NULL);
+}
+
+
+/*
+ * 'new_request()' - Create a new print creation or validation request.
+ */
+
+static ipp_t * /* O - Request data */
+new_request(
+ ipp_op_t op, /* I - IPP operation code */
+ int version, /* I - IPP version number */
+ const char *uri, /* I - printer-uri value */
+ const char *user, /* I - requesting-user-name value */
+ const char *title, /* I - job-name value */
+ int num_options, /* I - Number of options to send */
+ cups_option_t *options, /* I - Options to send */
+ const char *compression, /* I - compression value or NULL */
+ int copies, /* I - copies value or 0 */
+ const char *format, /* I - documet-format value or NULL */
+ _ppd_cache_t *pc, /* I - PPD cache and mapping data */
+ ipp_attribute_t *media_col_sup, /* I - media-col-supported values */
+ ipp_attribute_t *doc_handling_sup) /* I - multiple-document-handling-supported values */
+{
+ int i; /* Looping var */
+ ipp_t *request; /* Request data */
+ const char *keyword; /* PWG keyword */
+ _pwg_size_t *size; /* PWG media size */
+ ipp_t *media_col, /* media-col value */
+ *media_size; /* media-size value */
+ const char *media_source, /* media-source value */
+ *media_type, /* media-type value */
+ *collate_str; /* multiple-document-handling value */
+
+
+ /*
+ * Create the IPP request...
+ */
+
+ request = ippNewRequest(op);
+ request->request.op.version[0] = version / 10;
+ request->request.op.version[1] = version % 10;
+
+ fprintf(stderr, "DEBUG: %s IPP/%d.%d\n",
+ ippOpString(request->request.op.operation_id),
+ request->request.op.version[0],
+ request->request.op.version[1]);
+
+ /*
+ * Add standard attributes...
+ */
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+ fprintf(stderr, "DEBUG: printer-uri=\"%s\"\n", uri);
+
+ if (user && *user)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
+ fprintf(stderr, "DEBUG: requesting-user-name=\"%s\"\n", user);
+ }
+
+ if (title && *title)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+ title);
+ fprintf(stderr, "DEBUG: job-name=\"%s\"\n", title);
+ }
+
+ if (format)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format);
+ fprintf(stderr, "DEBUG: document-format=\"%s\"\n", format);
+ }
+
+#ifdef HAVE_LIBZ
+ if (compression)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "compression", NULL, compression);
+ fprintf(stderr, "DEBUG: compression=\"%s\"\n", compression);
+ }
+#endif /* HAVE_LIBZ */
+
+ /*
+ * Handle options on the command-line...
+ */
+
+ if (num_options > 0)
+ {
+ if (pc)
+ {
+ /*
+ * Send standard IPP attributes...
+ */
+
+ if ((keyword = cupsGetOption("PageSize", num_options, options)) == NULL)
+ keyword = cupsGetOption("media", num_options, options);
+
+ if ((size = _ppdCacheGetSize(pc, keyword)) != NULL)
+ {
+ /*
+ * Add a media-col value...
+ */
+
+ media_size = ippNew();
+ ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER,
+ "x-dimension", size->width);
+ ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER,
+ "y-dimension", size->length);
+
+ media_col = ippNew();
+ ippAddCollection(media_col, IPP_TAG_ZERO, "media-size", media_size);
+
+ media_source = _ppdCacheGetSource(pc, cupsGetOption("InputSlot",
+ num_options,
+ options));
+ media_type = _ppdCacheGetType(pc, cupsGetOption("MediaType",
+ num_options,
+ options));
+
+ for (i = 0; i < media_col_sup->num_values; i ++)
+ {
+ if (!strcmp(media_col_sup->values[i].string.text,
+ "media-left-margin"))
+ ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
+ "media-left-margin", size->left);
+ else if (!strcmp(media_col_sup->values[i].string.text,
+ "media-bottom-margin"))
+ ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
+ "media-bottom-margin", size->left);
+ else if (!strcmp(media_col_sup->values[i].string.text,
+ "media-right-margin"))
+ ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
+ "media-right-margin", size->left);
+ else if (!strcmp(media_col_sup->values[i].string.text,
+ "media-top-margin"))
+ ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
+ "media-top-margin", size->left);
+ else if (!strcmp(media_col_sup->values[i].string.text,
+ "media-source") && media_source)
+ ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD,
+ "media-source", NULL, media_source);
+ else if (!strcmp(media_col_sup->values[i].string.text,
+ "media-type") && media_type)
+ ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD,
+ "media-type", NULL, media_type);
+ }
+
+ ippAddCollection(request, IPP_TAG_JOB, "media-col", media_col);
+ }
+
+ if ((keyword = cupsGetOption("output-bin", num_options,
+ options)) == NULL)
+ keyword = _ppdCacheGetBin(pc, cupsGetOption("OutputBin", num_options,
+ options));
+
+ if (keyword)
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-bin",
+ NULL, keyword);
+
+ if ((keyword = cupsGetOption("output-mode", num_options,
+ options)) != NULL)
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode",
+ NULL, keyword);
+ else if ((keyword = cupsGetOption("ColorModel", num_options,
+ options)) != NULL)
+ {
+ if (!_cups_strcasecmp(keyword, "Gray"))
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode",
+ NULL, "monochrome");
+ else
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode",
+ NULL, "color");
+ }
+
+ if ((keyword = cupsGetOption("print-quality", num_options,
+ options)) != NULL)
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
+ atoi(keyword));
+ else if ((keyword = cupsGetOption("cupsPrintQuality", num_options,
+ options)) != NULL)
+ {
+ if (!_cups_strcasecmp(keyword, "draft"))
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
+ IPP_QUALITY_DRAFT);
+ else if (!_cups_strcasecmp(keyword, "normal"))
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
+ IPP_QUALITY_NORMAL);
+ else if (!_cups_strcasecmp(keyword, "high"))
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
+ IPP_QUALITY_HIGH);
+ }
+
+ if ((keyword = cupsGetOption("sides", num_options, options)) != NULL)
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
+ NULL, keyword);
+ else if (pc->sides_option &&
+ (keyword = cupsGetOption(pc->sides_option, num_options,
+ options)) != NULL)
+ {
+ if (!_cups_strcasecmp(keyword, pc->sides_1sided))
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
+ NULL, "one-sided");
+ else if (!_cups_strcasecmp(keyword, pc->sides_2sided_long))
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
+ NULL, "two-sided-long-edge");
+ if (!_cups_strcasecmp(keyword, pc->sides_2sided_short))
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
+ NULL, "two-sided-short-edge");
+ }
+
+ if (doc_handling_sup &&
+ (keyword = cupsGetOption("collate", num_options, options)) != NULL)
+ {
+ if (!_cups_strcasecmp(keyword, "true"))
+ collate_str = "separate-documents-collated-copies";
+ else
+ collate_str = "separate-documents-uncollated-copies";
+
+ for (i = 0; i < doc_handling_sup->num_values; i ++)
+ if (!strcmp(doc_handling_sup->values[i].string.text, collate_str))
+ {
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "multiple-document-handling", NULL, collate_str);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * When talking to another CUPS server, send all options...
+ */
+
+ cupsEncodeOptions(request, num_options, options);
+ }
+
+ if (copies > 1)
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", copies);
+ }
+
+ return (request);
+}
+
+
+/*
* 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
*/
@@ -1592,10 +2347,11 @@ password_cb(const char *prompt) /* I - Prompt (not used) */
static void
report_attr(ipp_attribute_t *attr) /* I - Attribute */
{
- int i; /* Looping var */
- char value[1024], /* Value string */
- *valptr, /* Pointer into value string */
- *attrptr; /* Pointer into attribute value */
+ int i; /* Looping var */
+ char value[1024], /* Value string */
+ *valptr, /* Pointer into value string */
+ *attrptr; /* Pointer into attribute value */
+ const char *cached; /* Cached attribute */
/*
@@ -1645,11 +2401,21 @@ report_attr(ipp_attribute_t *attr) /* I - Attribute */
*valptr = '\0';
- /*
- * Tell the scheduler about the new values...
- */
+ _cupsMutexLock(&report_mutex);
+
+ if ((cached = cupsGetOption(attr->name, num_attr_cache,
+ attr_cache)) == NULL || strcmp(cached, value))
+ {
+ /*
+ * Tell the scheduler about the new values...
+ */
- fprintf(stderr, "ATTR: %s=%s\n", attr->name, value);
+ num_attr_cache = cupsAddOption(attr->name, value, num_attr_cache,
+ &attr_cache);
+ fprintf(stderr, "ATTR: %s=%s\n", attr->name, value);
+ }
+
+ _cupsMutexUnlock(&report_mutex);
}
@@ -1657,297 +2423,560 @@ report_attr(ipp_attribute_t *attr) /* I - Attribute */
* 'report_printer_state()' - Report the printer state.
*/
-static int /* O - Number of reasons shown */
-report_printer_state(ipp_t *ipp, /* I - IPP response */
- int job_id) /* I - Current job ID */
+static void
+report_printer_state(ipp_t *ipp) /* I - IPP response */
{
- int i; /* Looping var */
- int count; /* Count of reasons shown... */
- ipp_attribute_t *caprm, /* com.apple.print.recoverable-message */
+ ipp_attribute_t *pa, /* printer-alert */
+ *pam, /* printer-alert-message */
*psm, /* printer-state-message */
*reasons, /* printer-state-reasons */
*marker; /* marker-* attributes */
- const char *reason; /* Current reason */
- const char *prefix; /* Prefix for STATE: line */
- char state[1024]; /* State string */
- int saw_caprw; /* Saw com.apple.print.recoverable-warning state */
+ char value[1024], /* State/message string */
+ *valptr; /* Pointer into string */
+ static int ipp_supplies = -1;
+ /* Report supply levels? */
- if ((psm = ippFindAttribute(ipp, "printer-state-message",
- IPP_TAG_TEXT)) != NULL)
- fprintf(stderr, "INFO: %s\n", psm->values[0].string.text);
+ /*
+ * Report alerts and messages...
+ */
- if ((reasons = ippFindAttribute(ipp, "printer-state-reasons",
- IPP_TAG_KEYWORD)) == NULL)
- return (0);
+ if ((pa = ippFindAttribute(ipp, "printer-alert", IPP_TAG_TEXT)) != NULL)
+ report_attr(pa);
- saw_caprw = 0;
- state[0] = '\0';
- prefix = "STATE: ";
+ if ((pam = ippFindAttribute(ipp, "printer-alert-message",
+ IPP_TAG_TEXT)) != NULL)
+ report_attr(pam);
- for (i = 0, count = 0; i < reasons->num_values; i ++)
+ if ((psm = ippFindAttribute(ipp, "printer-state-message",
+ IPP_TAG_TEXT)) != NULL)
{
- reason = reasons->values[i].string.text;
+ char *ptr; /* Pointer into message */
- if (!strcmp(reason, "com.apple.print.recoverable-warning"))
- saw_caprw = 1;
- else if (strcmp(reason, "paused"))
+
+ strlcpy(value, "INFO: ", sizeof(value));
+ for (ptr = psm->values[0].string.text, valptr = value + 6;
+ *ptr && valptr < (value + sizeof(value) - 6);
+ ptr ++)
{
- strlcat(state, prefix, sizeof(state));
- strlcat(state, reason, sizeof(state));
+ if (*ptr < ' ' && *ptr > 0 && *ptr != '\t')
+ {
+ /*
+ * Substitute "<XX>" for the control character; sprintf is safe because
+ * we always leave 6 chars free at the end...
+ */
- prefix = ",";
+ sprintf(valptr, "<%02X>", *ptr);
+ valptr += 4;
+ }
+ else
+ *valptr++ = *ptr;
}
- }
- if (state[0])
- fprintf(stderr, "%s\n", state);
+ *valptr++ = '\n';
+ *valptr = '\0';
+
+ fputs(value, stderr);
+ }
/*
- * Relay com.apple.print.recoverable-message...
+ * Now report printer-state-reasons, filtering out some of the reasons we never
+ * want to set...
*/
- if ((caprm = ippFindAttribute(ipp, "com.apple.print.recoverable-message",
- IPP_TAG_TEXT)) != NULL)
- fprintf(stderr, "WARNING: %s: %s\n",
- saw_caprw ? "recoverable" : "recovered",
- caprm->values[0].string.text);
+ if ((reasons = ippFindAttribute(ipp, "printer-state-reasons",
+ IPP_TAG_KEYWORD)) == NULL)
+ return;
+
+ update_reasons(reasons, NULL);
/*
* Relay the current marker-* attribute values...
*/
- if ((marker = ippFindAttribute(ipp, "marker-colors", IPP_TAG_NAME)) != NULL)
- report_attr(marker);
- if ((marker = ippFindAttribute(ipp, "marker-high-levels",
- IPP_TAG_INTEGER)) != NULL)
- report_attr(marker);
- if ((marker = ippFindAttribute(ipp, "marker-levels",
- IPP_TAG_INTEGER)) != NULL)
- report_attr(marker);
- if ((marker = ippFindAttribute(ipp, "marker-low-levels",
- IPP_TAG_INTEGER)) != NULL)
- report_attr(marker);
- if ((marker = ippFindAttribute(ipp, "marker-message", IPP_TAG_TEXT)) != NULL)
- report_attr(marker);
- if ((marker = ippFindAttribute(ipp, "marker-names", IPP_TAG_NAME)) != NULL)
- report_attr(marker);
- if ((marker = ippFindAttribute(ipp, "marker-types", IPP_TAG_KEYWORD)) != NULL)
- report_attr(marker);
-
- return (count);
+ if (ipp_supplies < 0)
+ {
+ ppd_file_t *ppd; /* PPD file */
+ ppd_attr_t *ppdattr; /* Attribute in PPD file */
+
+ if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL &&
+ (ppdattr = ppdFindAttr(ppd, "cupsIPPSupplies", NULL)) != NULL &&
+ ppdattr->value && _cups_strcasecmp(ppdattr->value, "true"))
+ ipp_supplies = 0;
+ else
+ ipp_supplies = 1;
+
+ ppdClose(ppd);
+ }
+
+ if (ipp_supplies > 0)
+ {
+ if ((marker = ippFindAttribute(ipp, "marker-colors", IPP_TAG_NAME)) != NULL)
+ report_attr(marker);
+ if ((marker = ippFindAttribute(ipp, "marker-high-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ report_attr(marker);
+ if ((marker = ippFindAttribute(ipp, "marker-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ report_attr(marker);
+ if ((marker = ippFindAttribute(ipp, "marker-low-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ report_attr(marker);
+ if ((marker = ippFindAttribute(ipp, "marker-message",
+ IPP_TAG_TEXT)) != NULL)
+ report_attr(marker);
+ if ((marker = ippFindAttribute(ipp, "marker-names", IPP_TAG_NAME)) != NULL)
+ report_attr(marker);
+ if ((marker = ippFindAttribute(ipp, "marker-types",
+ IPP_TAG_KEYWORD)) != NULL)
+ report_attr(marker);
+ }
}
-#ifdef __APPLE__
+#if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
/*
- * 'run_pictwps_filter()' - Convert PICT files to PostScript when printing
- * remotely.
+ * 'run_as_user()' - Run the IPP backend as the printing user.
*
- * This step is required because the PICT format is not documented and
- * subject to change, so developing a filter for other OS's is infeasible.
- * Also, fonts required by the PICT file need to be embedded on the
- * client side (which has the fonts), so we run the filter to get a
- * PostScript file for printing...
+ * This function uses an XPC-based user agent to run the backend as the printing
+ * user. We need to do this in order to have access to the user's Kerberos
+ * credentials.
*/
-static int /* O - Exit status of filter */
-run_pictwps_filter(char **argv, /* I - Command-line arguments */
- const char *filename)/* I - Filename */
+static int /* O - Exit status */
+run_as_user(int argc, /* I - Number of command-line args */
+ char *argv[], /* I - Command-line arguments */
+ uid_t uid, /* I - User ID */
+ const char *device_uri, /* I - Device URI */
+ int fd) /* I - File to print */
{
- struct stat fileinfo; /* Print file information */
- const char *ppdfile; /* PPD file for destination printer */
- int pid; /* Child process ID */
- int fd; /* Temporary file descriptor */
- int status; /* Exit status of filter */
- const char *printer; /* PRINTER env var */
- static char ppdenv[1024]; /* PPD environment variable */
+ const char *auth_negotiate;/* AUTH_NEGOTIATE env var */
+ xpc_connection_t conn; /* Connection to XPC service */
+ xpc_object_t request; /* Request message dictionary */
+ __block xpc_object_t response; /* Response message dictionary */
+ dispatch_semaphore_t sem; /* Semaphore for waiting for response */
+ int status = CUPS_BACKEND_FAILED;
+ /* Status of request */
+ fprintf(stderr, "DEBUG: Running IPP backend as UID %d.\n", (int)uid);
+
/*
- * First get the PPD file for the printer...
+ * Connect to the user agent for the specified UID...
*/
- printer = getenv("PRINTER");
- if (!printer)
+ conn = xpc_connection_create_mach_service(kPMPrintUIToolAgent,
+ dispatch_get_global_queue(0, 0), 0);
+ if (!conn)
{
- _cupsLangPuts(stderr,
- _("ERROR: PRINTER environment variable not defined!\n"));
- return (-1);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to start backend process."));
+ fputs("DEBUG: Unable to create connection to agent.\n", stderr);
+ goto cleanup;
}
- if ((ppdfile = cupsGetPPD(printer)) == NULL)
+ xpc_connection_set_event_handler(conn,
+ ^(xpc_object_t event)
+ {
+ xpc_type_t messageType = xpc_get_type(event);
+
+ if (messageType == XPC_TYPE_ERROR)
+ {
+ if (event == XPC_ERROR_CONNECTION_INTERRUPTED)
+ fprintf(stderr, "DEBUG: Interrupted connection to service %s.\n",
+ xpc_connection_get_name(conn));
+ else if (event == XPC_ERROR_CONNECTION_INVALID)
+ fprintf(stderr, "DEBUG: Connection invalid for service %s.\n",
+ xpc_connection_get_name(conn));
+ else
+ fprintf(stderr, "DEBUG: Unxpected error for service %s: %s\n",
+ xpc_connection_get_name(conn),
+ xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
+ }
+ });
+ xpc_connection_set_target_uid(conn, uid);
+ xpc_connection_resume(conn);
+
+ /*
+ * Try starting the backend...
+ */
+
+ request = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_int64(request, "command", kPMStartJob);
+ xpc_dictionary_set_string(request, "device-uri", device_uri);
+ xpc_dictionary_set_string(request, "job-id", argv[1]);
+ xpc_dictionary_set_string(request, "user", argv[2]);
+ xpc_dictionary_set_string(request, "title", argv[3]);
+ xpc_dictionary_set_string(request, "copies", argv[4]);
+ xpc_dictionary_set_string(request, "options", argv[5]);
+ xpc_dictionary_set_string(request, "auth-info-required",
+ getenv("AUTH_INFO_REQUIRED"));
+ if ((auth_negotiate = getenv("AUTH_NEGOTIATE")) != NULL)
+ xpc_dictionary_set_string(request, "auth-negotiate", auth_negotiate);
+ xpc_dictionary_set_fd(request, "stdin", fd);
+ xpc_dictionary_set_fd(request, "stderr", 2);
+ xpc_dictionary_set_fd(request, "side-channel", CUPS_SC_FD);
+
+ sem = dispatch_semaphore_create(0);
+ response = NULL;
+
+ xpc_connection_send_message_with_reply(conn, request,
+ dispatch_get_global_queue(0,0),
+ ^(xpc_object_t reply)
+ {
+ /* Save the response and wake up */
+ if (xpc_get_type(reply)
+ == XPC_TYPE_DICTIONARY)
+ response = xpc_retain(reply);
+
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ xpc_release(request);
+ dispatch_release(sem);
+
+ if (response)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to get PPD file for printer \"%s\" - "
- "%s.\n"), printer, cupsLastErrorString());
+ child_pid = xpc_dictionary_get_int64(response, "child-pid");
+
+ xpc_release(response);
+
+ if (child_pid)
+ fprintf(stderr, "DEBUG: Child PID=%d.\n", child_pid);
+ else
+ {
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to start backend process."));
+ fputs("DEBUG: No child PID.\n", stderr);
+ goto cleanup;
+ }
}
else
{
- snprintf(ppdenv, sizeof(ppdenv), "PPD=%s", ppdfile);
- putenv(ppdenv);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to start backend process."));
+ fputs("DEBUG: No reply from agent.\n", stderr);
+ goto cleanup;
}
/*
- * Then create a temporary file for printing...
+ * Then wait for the backend to finish...
*/
- if ((fd = cupsTempFd(pstmpname, sizeof(pstmpname))) < 0)
+ request = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_int64(request, "command", kPMWaitForJob);
+ xpc_dictionary_set_fd(request, "stderr", 2);
+
+ sem = dispatch_semaphore_create(0);
+ response = NULL;
+
+ xpc_connection_send_message_with_reply(conn, request,
+ dispatch_get_global_queue(0,0),
+ ^(xpc_object_t reply)
+ {
+ /* Save the response and wake up */
+ if (xpc_get_type(reply)
+ == XPC_TYPE_DICTIONARY)
+ response = xpc_retain(reply);
+
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ xpc_release(request);
+ dispatch_release(sem);
+
+ if (response)
{
- _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
- if (ppdfile)
- unlink(ppdfile);
- return (-1);
- }
+ status = xpc_dictionary_get_int64(response, "status");
- /*
- * Get the owner of the spool file - it is owned by the user we want to run
- * as...
- */
+ if (status == SIGTERM || status == SIGKILL || status == SIGPIPE)
+ {
+ fprintf(stderr, "DEBUG: Child terminated on signal %d.\n", status);
+ status = CUPS_BACKEND_FAILED;
+ }
+ else if (WIFSIGNALED(status))
+ {
+ fprintf(stderr, "DEBUG: Child crashed on signal %d.\n", status);
+ status = CUPS_BACKEND_STOP;
+ }
+ else if (WIFEXITED(status))
+ {
+ status = WEXITSTATUS(status);
+ fprintf(stderr, "DEBUG: Child exited with status %d.\n", status);
+ }
- if (argv[6])
- stat(argv[6], &fileinfo);
+ xpc_release(response);
+ }
else
- {
- /*
- * Use the OSX defaults, as an up-stream filter created the PICT
- * file...
- */
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to get backend exit status."));
+
+ cleanup:
- fileinfo.st_uid = 1;
- fileinfo.st_gid = 80;
+ if (conn)
+ {
+ xpc_connection_suspend(conn);
+ xpc_connection_cancel(conn);
+ xpc_release(conn);
}
- if (ppdfile)
- chown(ppdfile, fileinfo.st_uid, fileinfo.st_gid);
+ return (status);
+}
+#endif /* HAVE_GSSAPI && HAVE_XPC */
- fchown(fd, fileinfo.st_uid, fileinfo.st_gid);
- /*
- * Finally, run the filter to convert the file...
- */
+/*
+ * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
+ */
- if ((pid = fork()) == 0)
+static void
+sigterm_handler(int sig) /* I - Signal */
+{
+ (void)sig; /* remove compiler warnings... */
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
+ if (child_pid)
+ {
+ kill(child_pid, sig);
+ child_pid = 0;
+ }
+#endif /* HAVE_GSSAPI && HAVE_XPC */
+
+ if (!job_canceled)
{
/*
- * Child process for pictwpstops... Redirect output of pictwpstops to a
- * file...
+ * Flag that the job should be canceled...
*/
- dup2(fd, 1);
- close(fd);
+ job_canceled = 1;
+ return;
+ }
- if (!getuid())
- {
- /*
- * Change to an unpriviledged user...
- */
+ /*
+ * The scheduler already tried to cancel us once, now just terminate
+ * after removing our temp file!
+ */
- if (setgid(fileinfo.st_gid))
- return (errno);
+ if (tmpfilename[0])
+ unlink(tmpfilename);
- if (setuid(fileinfo.st_uid))
- return (errno);
- }
+ exit(1);
+}
- execlp("pictwpstops", printer, argv[1], argv[2], argv[3], argv[4], argv[5],
- filename, NULL);
- _cupsLangPrintf(stderr, _("ERROR: Unable to exec pictwpstops: %s\n"),
- strerror(errno));
- return (errno);
- }
- close(fd);
+/*
+ * 'timeout_cb()' - Handle HTTP timeouts.
+ */
- if (pid < 0)
- {
- /*
- * Error!
- */
+static int /* O - 1 to continue, 0 to cancel */
+timeout_cb(http_t *http, /* I - Connection to server (unused) */
+ void *user_data) /* I - User data (unused) */
+{
+ (void)http;
+ (void)user_data;
- _cupsLangPrintf(stderr, _("ERROR: Unable to fork pictwpstops: %s\n"),
- strerror(errno));
- if (ppdfile)
- unlink(ppdfile);
- return (-1);
- }
+ return (!job_canceled);
+}
+
+
+/*
+ * 'update_reasons()' - Update the printer-state-reasons values.
+ */
+
+static void
+update_reasons(ipp_attribute_t *attr, /* I - printer-state-reasons or NULL */
+ const char *s) /* I - STATE: string or NULL */
+{
+ char op; /* Add (+), remove (-), replace (\0) */
+ cups_array_t *new_reasons; /* New reasons array */
+ char *reason, /* Current reason */
+ add[2048], /* Reasons added string */
+ *addptr, /* Pointer into add string */
+ rem[2048], /* Reasons removed string */
+ *remptr; /* Pointer into remove string */
+ const char *addprefix, /* Current add string prefix */
+ *remprefix; /* Current remove string prefix */
+
+
+ fprintf(stderr, "DEBUG: update_reasons(attr=%d(%s%s), s=\"%s\")\n",
+ attr ? attr->num_values : 0, attr ? attr->values[0].string.text : "",
+ attr && attr->num_values > 1 ? ",..." : "", s ? s : "(null)");
/*
- * Now wait for the filter to complete...
+ * Create an array of new reason keyword strings...
*/
- if (wait(&status) < 0)
+ if (attr)
{
- _cupsLangPrintf(stderr, _("ERROR: Unable to wait for pictwpstops: %s\n"),
- strerror(errno));
- close(fd);
- if (ppdfile)
- unlink(ppdfile);
- return (-1);
- }
-
- if (ppdfile)
- unlink(ppdfile);
+ int i; /* Looping var */
- close(fd);
+ new_reasons = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+ op = '\0';
- if (status)
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ reason = attr->values[i].string.text;
+
+ if (strcmp(reason, "none") &&
+ strcmp(reason, "none-report") &&
+ strcmp(reason, "paused") &&
+ strcmp(reason, "com.apple.print.recoverable-warning") &&
+ strncmp(reason, "cups-", 5))
+ cupsArrayAdd(new_reasons, reason);
+ }
+ }
+ else if (s)
{
- if (status >= 256)
- _cupsLangPrintf(stderr, _("ERROR: pictwpstops exited with status %d!\n"),
- status / 256);
+ if (*s == '+' || *s == '-')
+ op = *s++;
else
- _cupsLangPrintf(stderr, _("ERROR: pictwpstops exited on signal %d!\n"),
- status);
+ op = '\0';
- return (status);
+ new_reasons = _cupsArrayNewStrings(s);
}
+ else
+ return;
/*
- * Return with no errors..
+ * Compute the changes...
*/
- return (0);
-}
-#endif /* __APPLE__ */
+ add[0] = '\0';
+ addprefix = "STATE: +";
+ addptr = add;
+ rem[0] = '\0';
+ remprefix = "STATE: -";
+ remptr = rem;
+ fprintf(stderr, "DEBUG2: op='%c', new_reasons=%d, state_reasons=%d\n",
+ op ? op : ' ', cupsArrayCount(new_reasons),
+ cupsArrayCount(state_reasons));
-/*
- * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
- */
+ _cupsMutexLock(&report_mutex);
-static void
-sigterm_handler(int sig) /* I - Signal */
-{
- (void)sig; /* remove compiler warnings... */
+ if (op == '+')
+ {
+ /*
+ * Add reasons...
+ */
+
+ for (reason = (char *)cupsArrayFirst(new_reasons);
+ reason;
+ reason = (char *)cupsArrayNext(new_reasons))
+ {
+ if (!cupsArrayFind(state_reasons, reason))
+ {
+ if (!strncmp(reason, "cups-remote-", 12))
+ {
+ /*
+ * If we are setting cups-remote-xxx, remove all other cups-remote-xxx
+ * keywords...
+ */
+
+ char *temp; /* Current reason in state_reasons */
+
+ cupsArraySave(state_reasons);
+
+ for (temp = (char *)cupsArrayFirst(state_reasons);
+ temp;
+ temp = (char *)cupsArrayNext(state_reasons))
+ if (!strncmp(temp, "cups-remote-", 12))
+ {
+ snprintf(remptr, sizeof(rem) - (remptr - rem), "%s%s", remprefix,
+ temp);
+ remptr += strlen(remptr);
+ remprefix = ",";
+
+ cupsArrayRemove(state_reasons, temp);
+ break;
+ }
+
+ cupsArrayRestore(state_reasons);
+ }
+
+ cupsArrayAdd(state_reasons, reason);
- if (!job_cancelled)
+ snprintf(addptr, sizeof(add) - (addptr - add), "%s%s", addprefix,
+ reason);
+ addptr += strlen(addptr);
+ addprefix = ",";
+ }
+ }
+ }
+ else if (op == '-')
{
/*
- * Flag that the job should be cancelled...
+ * Remove reasons...
*/
- job_cancelled = 1;
- return;
+ for (reason = (char *)cupsArrayFirst(new_reasons);
+ reason;
+ reason = (char *)cupsArrayNext(new_reasons))
+ {
+ if (cupsArrayFind(state_reasons, reason))
+ {
+ snprintf(remptr, sizeof(rem) - (remptr - rem), "%s%s", remprefix,
+ reason);
+ remptr += strlen(remptr);
+ remprefix = ",";
+
+ cupsArrayRemove(state_reasons, reason);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Replace reasons...
+ */
+
+ for (reason = (char *)cupsArrayFirst(state_reasons);
+ reason;
+ reason = (char *)cupsArrayNext(state_reasons))
+ {
+ if (strncmp(reason, "cups-", 5) && !cupsArrayFind(new_reasons, reason))
+ {
+ snprintf(remptr, sizeof(rem) - (remptr - rem), "%s%s", remprefix,
+ reason);
+ remptr += strlen(remptr);
+ remprefix = ",";
+
+ cupsArrayRemove(state_reasons, reason);
+ }
+ }
+
+ for (reason = (char *)cupsArrayFirst(new_reasons);
+ reason;
+ reason = (char *)cupsArrayNext(new_reasons))
+ {
+ if (!cupsArrayFind(state_reasons, reason))
+ {
+ cupsArrayAdd(state_reasons, reason);
+
+ snprintf(addptr, sizeof(add) - (addptr - add), "%s%s", addprefix,
+ reason);
+ addptr += strlen(addptr);
+ addprefix = ",";
+ }
+ }
}
+ _cupsMutexUnlock(&report_mutex);
+
/*
- * The scheduler already tried to cancel us once, now just terminate
- * after removing our temp files!
+ * Report changes and return...
*/
- if (tmpfilename[0])
- unlink(tmpfilename);
-
-#ifdef __APPLE__
- if (pstmpname[0])
- unlink(pstmpname);
-#endif /* __APPLE__ */
-
- exit(1);
+ if (add[0] && rem[0])
+ fprintf(stderr, "%s\n%s\n", add, rem);
+ else if (add[0])
+ fprintf(stderr, "%s\n", add);
+ else if (rem[0])
+ fprintf(stderr, "%s\n", rem);
}
-
/*
- * End of "$Id: ipp.c 8950 2010-01-14 22:40:19Z mike $".
+ * End of "$Id: ipp.c 9808 2011-05-26 12:03:28Z mike $".
*/
diff --git a/backend/lpd.c b/backend/lpd.c
index ab95fb78..cd2edc1f 100644
--- a/backend/lpd.c
+++ b/backend/lpd.c
@@ -1,9 +1,9 @@
/*
- * "$Id: lpd.c 8938 2009-12-18 23:52:01Z mike $"
+ * "$Id: lpd.c 9793 2011-05-20 03:49:49Z mike $"
*
- * Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
+ * Line Printer Daemon backend for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -34,6 +34,7 @@
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdio.h>
#ifdef WIN32
# include <winsock.h>
@@ -87,11 +88,12 @@ static int abort_job = 0; /* Non-zero if we get SIGTERM */
*/
static int lpd_command(int lpd_fd, int timeout, char *format, ...);
-static int lpd_queue(const char *hostname, int port, const char *printer,
- int print_fd, int mode, const char *user,
- const char *title, int copies, int banner,
- int format, int order, int reserve,
- int manual_copies, int timeout, int contimeout);
+static int lpd_queue(const char *hostname, http_addrlist_t *addrlist,
+ const char *printer, int print_fd, int snmp_fd,
+ int mode, const char *user, const char *title,
+ int copies, int banner, int format, int order,
+ int reserve, int manual_copies, int timeout,
+ int contimeout);
static void lpd_timeout(int sig);
static int lpd_write(int lpd_fd, char *buffer, int length);
#ifndef HAVE_RRESVPORT_AF
@@ -124,6 +126,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
*filename, /* File to print */
title[256]; /* Title string */
int port; /* Port number */
+ char portname[256]; /* Port name (string) */
+ http_addrlist_t *addrlist; /* List of addresses for printer */
+ int snmp_fd; /* SNMP socket */
int fd; /* Print file */
int status; /* Status of LPD job */
int mode; /* Print mode */
@@ -136,6 +141,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
timeout, /* Timeout */
contimeout, /* Connection timeout */
copies; /* Number of copies */
+ ssize_t bytes = 0; /* Initial bytes read */
+ char buffer[16384]; /* Initial print buffer */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
@@ -181,7 +188,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
else if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
+ _("Usage: %s job-id user title copies options [file]"),
argv[0]);
return (CUPS_BACKEND_FAILED);
}
@@ -190,8 +197,14 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Extract the hostname and printer name from the URI...
*/
- if ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
- return (CUPS_BACKEND_FAILED);
+ while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ return (CUPS_BACKEND_FAILED);
+ }
httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
username, sizeof(username), hostname, sizeof(hostname), &port,
@@ -224,36 +237,15 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
#ifdef __APPLE__
/*
- * We want to pass utf-8 characters, not re-map them (3071945)
+ * We want to pass UTF-8 characters by default, not re-map them (3071945)
*/
sanitize_title = 0;
-
+#else
/*
- * Get the default timeout from a system preference...
+ * Otherwise we want to re-map UTF-8 to "safe" characters by default...
*/
- {
- CFPropertyListRef pvalue; /* Preference value */
- SInt32 toval; /* Timeout value */
-
-
- pvalue = CFPreferencesCopyValue(CFSTR("timeout"),
- CFSTR("com.apple.print.backends"),
- kCFPreferencesAnyUser,
- kCFPreferencesCurrentHost);
- if (pvalue)
- {
- if (CFGetTypeID(pvalue) == CFNumberGetTypeID())
- {
- CFNumberGetValue(pvalue, kCFNumberSInt32Type, &toval);
- contimeout = (int)toval;
- }
-
- CFRelease(pvalue);
- }
- }
-#else
sanitize_title = 1;
#endif /* __APPLE__ */
@@ -305,16 +297,16 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Process the option...
*/
- if (!strcasecmp(name, "banner"))
+ if (!_cups_strcasecmp(name, "banner"))
{
/*
* Set the banner...
*/
- banner = !value[0] || !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") || !strcasecmp(value, "true");
+ banner = !value[0] || !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
}
- else if (!strcasecmp(name, "format") && value[0])
+ else if (!_cups_strcasecmp(name, "format") && value[0])
{
/*
* Set output format...
@@ -323,71 +315,72 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (strchr("cdfglnoprtv", value[0]))
format = value[0];
else
- _cupsLangPrintf(stderr, _("ERROR: Unknown format character \"%c\"\n"),
- value[0]);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unknown format character: \"%c\"."),
+ value[0]);
}
- else if (!strcasecmp(name, "mode") && value[0])
+ else if (!_cups_strcasecmp(name, "mode") && value[0])
{
/*
* Set control/data order...
*/
- if (!strcasecmp(value, "standard"))
+ if (!_cups_strcasecmp(value, "standard"))
mode = MODE_STANDARD;
- else if (!strcasecmp(value, "stream"))
+ else if (!_cups_strcasecmp(value, "stream"))
mode = MODE_STREAM;
else
- _cupsLangPrintf(stderr, _("ERROR: Unknown print mode \"%s\"\n"),
- value);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unknown print mode: \"%s\"."), value);
}
- else if (!strcasecmp(name, "order") && value[0])
+ else if (!_cups_strcasecmp(name, "order") && value[0])
{
/*
* Set control/data order...
*/
- if (!strcasecmp(value, "control,data"))
+ if (!_cups_strcasecmp(value, "control,data"))
order = ORDER_CONTROL_DATA;
- else if (!strcasecmp(value, "data,control"))
+ else if (!_cups_strcasecmp(value, "data,control"))
order = ORDER_DATA_CONTROL;
else
- _cupsLangPrintf(stderr, _("ERROR: Unknown file order \"%s\"\n"),
- value);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unknown file order: \"%s\"."), value);
}
- else if (!strcasecmp(name, "reserve"))
+ else if (!_cups_strcasecmp(name, "reserve"))
{
/*
* Set port reservation mode...
*/
- if (!value[0] || !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") || !strcasecmp(value, "true") ||
- !strcasecmp(value, "rfc1179"))
+ if (!value[0] || !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true") ||
+ !_cups_strcasecmp(value, "rfc1179"))
reserve = RESERVE_RFC1179;
- else if (!strcasecmp(value, "any"))
+ else if (!_cups_strcasecmp(value, "any"))
reserve = RESERVE_ANY;
else
reserve = RESERVE_NONE;
}
- else if (!strcasecmp(name, "manual_copies"))
+ else if (!_cups_strcasecmp(name, "manual_copies"))
{
/*
* Set manual copies...
*/
- manual_copies = !value[0] || !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") || !strcasecmp(value, "true");
+ manual_copies = !value[0] || !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
}
- else if (!strcasecmp(name, "sanitize_title"))
+ else if (!_cups_strcasecmp(name, "sanitize_title"))
{
/*
* Set sanitize title...
*/
- sanitize_title = !value[0] || !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") || !strcasecmp(value, "true");
+ sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
}
- else if (!strcasecmp(name, "timeout"))
+ else if (!_cups_strcasecmp(name, "timeout"))
{
/*
* Set the timeout...
@@ -396,7 +389,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (atoi(value) > 0)
timeout = atoi(value);
}
- else if (!strcasecmp(name, "contimeout"))
+ else if (!_cups_strcasecmp(name, "contimeout"))
{
/*
* Set the connection timeout...
@@ -412,6 +405,43 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
order = ORDER_CONTROL_DATA;
/*
+ * Find the printer...
+ */
+
+ snprintf(portname, sizeof(portname), "%d", port);
+
+ fputs("STATE: +connecting-to-device\n", stderr);
+ fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
+
+ while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to locate printer \"%s\"."), hostname);
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ {
+ fputs("STATE: -connecting-to-device\n", stderr);
+ exit(CUPS_BACKEND_FAILED);
+ }
+ }
+
+ snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
+
+ /*
+ * Wait for data from the filter...
+ */
+
+ if (argc == 6)
+ {
+ if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
+ return (CUPS_BACKEND_OK);
+ else if (mode == MODE_STANDARD &&
+ (bytes = read(0, buffer, sizeof(buffer))) <= 0)
+ return (CUPS_BACKEND_OK);
+ }
+
+ /*
* If we have 7 arguments, print the file named on the command-line.
* Otherwise, copy stdin to a temporary file and print the temporary
* file.
@@ -423,37 +453,19 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Copy stdin to a temporary file...
*/
- http_addrlist_t *addrlist; /* Address list */
- int snmp_fd; /* SNMP socket */
-
-
- fputs("STATE: +connecting-to-device\n", stderr);
- fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
-
- if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, "1")) == NULL)
- {
- _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
- hostname);
- return (CUPS_BACKEND_STOP);
- }
-
- snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
-
if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
{
- _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
+ perror("DEBUG: Unable to create temporary file");
return (CUPS_BACKEND_FAILED);
}
- _cupsLangPuts(stderr, _("INFO: Copying print data...\n"));
-
- backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
- backendNetworkSideCB);
+ _cupsLangPrintFilter(stderr, "INFO", _("Copying print data."));
- if (snmp_fd >= 0)
- _cupsSNMPClose(snmp_fd);
+ if (bytes > 0)
+ write(fd, buffer, bytes);
- httpAddrFreeList(addrlist);
+ backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
+ backendNetworkSideCB);
}
else if (argc == 6)
{
@@ -471,8 +483,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (fd == -1)
{
- _cupsLangPrintf(stderr, _("ERROR: Unable to open print file %s: %s\n"),
- filename, strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
return (CUPS_BACKEND_FAILED);
}
}
@@ -514,18 +525,16 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
copies = atoi(argv[4]);
}
- status = lpd_queue(hostname, port, resource + 1, fd, mode,
- username, title, copies,
- banner, format, order, reserve, manual_copies,
- timeout, contimeout);
+ status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
+ username, title, copies, banner, format, order, reserve,
+ manual_copies, timeout, contimeout);
if (!status)
fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4]));
}
else
- status = lpd_queue(hostname, port, resource + 1, fd, mode,
- username, title, 1,
- banner, format, order, reserve, 1,
+ status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
+ username, title, 1, banner, format, order, reserve, 1,
timeout, contimeout);
/*
@@ -538,6 +547,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (fd)
close(fd);
+ if (snmp_fd >= 0)
+ _cupsSNMPClose(snmp_fd);
+
/*
* Return the queue status...
*/
@@ -563,7 +575,7 @@ lpd_command(int fd, /* I - Socket connection to LPD host */
/*
- * Don't try to send commands if the job has been cancelled...
+ * Don't try to send commands if the job has been canceled...
*/
if (abort_job)
@@ -587,7 +599,7 @@ lpd_command(int fd, /* I - Socket connection to LPD host */
if (lpd_write(fd, buf, bytes) < bytes)
{
- _cupsLangPrintError(_("ERROR: Unable to send LPD command"));
+ perror("DEBUG: Unable to send LPD command");
return (-1);
}
@@ -601,9 +613,9 @@ lpd_command(int fd, /* I - Socket connection to LPD host */
if (recv(fd, &status, 1, 0) < 1)
{
- _cupsLangPrintf(stderr,
- _("WARNING: Remote host did not respond with command "
- "status byte after %d seconds!\n"), timeout);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Printer did not respond after %d seconds."),
+ timeout);
status = errno;
}
@@ -620,21 +632,22 @@ lpd_command(int fd, /* I - Socket connection to LPD host */
*/
static int /* O - Zero on success, non-zero on failure */
-lpd_queue(const char *hostname, /* I - Host to connect to */
- int port, /* I - Port to connect on */
- const char *printer, /* I - Printer/queue name */
- int print_fd, /* I - File to print */
- int mode, /* I - Print mode */
- const char *user, /* I - Requesting user */
- const char *title, /* I - Job title */
- int copies, /* I - Number of copies */
- int banner, /* I - Print LPD banner? */
- int format, /* I - Format specifier */
- int order, /* I - Order of data/control files */
- int reserve, /* I - Reserve ports? */
- int manual_copies, /* I - Do copies by hand... */
- int timeout, /* I - Timeout... */
- int contimeout) /* I - Connection timeout */
+lpd_queue(const char *hostname, /* I - Host to connect to */
+ http_addrlist_t *addrlist, /* I - List of host addresses */
+ const char *printer, /* I - Printer/queue name */
+ int print_fd, /* I - File to print */
+ int snmp_fd, /* I - SNMP socket */
+ int mode, /* I - Print mode */
+ const char *user, /* I - Requesting user */
+ const char *title, /* I - Job title */
+ int copies, /* I - Number of copies */
+ int banner, /* I - Print LPD banner? */
+ int format, /* I - Format specifier */
+ int order, /* I - Order of data/control files */
+ int reserve, /* I - Reserve ports? */
+ int manual_copies,/* I - Do copies by hand... */
+ int timeout, /* I - Timeout... */
+ int contimeout) /* I - Connection timeout */
{
char localhost[255]; /* Local host name */
int error; /* Error number */
@@ -644,16 +657,12 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
char control[10240], /* LPD control 'file' */
*cptr; /* Pointer into control file string */
char status; /* Status byte from command */
- char portname[255]; /* Port name */
int delay; /* Delay for retries... */
char addrname[256]; /* Address name */
- http_addrlist_t *addrlist, /* Address list */
- *addr; /* Socket address */
- int snmp_fd, /* SNMP socket */
- have_supplies; /* Printer supports supply levels? */
+ http_addrlist_t *addr; /* Socket address */
+ int have_supplies; /* Printer supports supply levels? */
int copy; /* Copies written */
time_t start_time; /* Time of first connect */
- int recoverable; /* Recoverable error shown? */
size_t nbytes; /* Number of bytes written */
off_t tbytes; /* Total bytes written */
char buffer[32768]; /* Output buffer */
@@ -679,27 +688,10 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
#endif /* HAVE_SIGSET */
/*
- * Find the printer...
- */
-
- sprintf(portname, "%d", port);
-
- fputs("STATE: +connecting-to-device\n", stderr);
- fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
-
- if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
- {
- _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
- hostname);
- return (CUPS_BACKEND_STOP);
- }
-
- /*
* Remember when we started trying to connect to the printer...
*/
- recoverable = 0;
- start_time = time(NULL);
+ start_time = time(NULL);
/*
* Loop forever trying to print the file...
@@ -712,23 +704,19 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
*/
fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname,
- port, printer);
- _cupsLangPuts(stderr, _("INFO: Connecting to printer...\n"));
+ _httpAddrPort(&(addrlist->addr)), printer);
+ _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist,
delay = 5;;
addr = addr->next)
{
/*
- * Stop if this job has been cancelled...
+ * Stop if this job has been canceled...
*/
if (abort_job)
- {
- httpAddrFreeList(addrlist);
-
return (CUPS_BACKEND_FAILED);
- }
/*
* Choose the next priviledged port...
@@ -756,7 +744,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
{
- _cupsLangPrintError(_("ERROR: Unable to create socket"));
+ perror("DEBUG: Unable to create socket");
sleep(1);
continue;
@@ -773,7 +761,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if ((fd = rresvport_af(&lport, addr->addr.addr.sa_family)) < 0)
{
- _cupsLangPrintError(_("ERROR: Unable to reserve port"));
+ perror("DEBUG: Unable to reserve port");
sleep(1);
continue;
@@ -786,8 +774,6 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (abort_job)
{
- httpAddrFreeList(addrlist);
-
close(fd);
return (CUPS_BACKEND_FAILED);
@@ -811,11 +797,9 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
-
- httpAddrFreeList(addrlist);
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -826,20 +810,38 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
return (CUPS_BACKEND_FAILED);
}
+ fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));
+
if (error == ECONNREFUSED || error == EHOSTDOWN ||
error == EHOSTUNREACH)
{
if (contimeout && (time(NULL) - start_time) > contimeout)
{
- _cupsLangPuts(stderr, _("ERROR: Printer not responding!\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
return (CUPS_BACKEND_FAILED);
}
- recoverable = 1;
-
- _cupsLangPrintf(stderr,
- _("WARNING: recoverable: Network host \'%s\' is busy; "
- "will retry in %d seconds...\n"), hostname, delay);
+ switch (error)
+ {
+ case EHOSTDOWN :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer may not exist or "
+ "is unavailable at this time."));
+ break;
+
+ case EHOSTUNREACH :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer is unreachable at "
+ "this time."));
+ break;
+
+ case ECONNREFUSED :
+ default :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer is busy."));
+ break;
+ }
sleep(delay);
@@ -856,49 +858,26 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
}
else
{
- recoverable = 1;
-
- fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
- _cupsLangPuts(stderr,
- _("ERROR: recoverable: Unable to connect to printer; "
- "will retry in 30 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
sleep(30);
}
}
- if (recoverable)
- {
- /*
- * If we've shown a recoverable error make sure the printer proxies
- * have a chance to see the recovered message. Not pretty but
- * necessary for now...
- */
-
- fputs("INFO: recovered: \n", stderr);
- sleep(5);
- }
-
fputs("STATE: -connecting-to-device\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Connected to printer...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
-#ifdef AF_INET6
- if (addr->addr.addr.sa_family == AF_INET6)
- fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6) (local port %d)...\n",
- httpAddrString(&addr->addr, addrname, sizeof(addrname)),
- ntohs(addr->addr.ipv6.sin6_port), lport);
- else
-#endif /* AF_INET6 */
- if (addr->addr.addr.sa_family == AF_INET)
- fprintf(stderr, "DEBUG: Connected to %s:%d (IPv4) (local port %d)...\n",
- httpAddrString(&addr->addr, addrname, sizeof(addrname)),
- ntohs(addr->addr.ipv4.sin_port), lport);
+ fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n",
+ httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
+ _httpAddrPort(&(addr->addr)), lport);
/*
* See if the printer supports SNMP...
*/
- if ((snmp_fd = _cupsSNMPOpen(addr->addr.addr.sa_family)) >= 0)
- have_supplies = !backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL);
+ if (snmp_fd >= 0)
+ have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL,
+ NULL);
else
have_supplies = 0;
@@ -906,7 +885,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
* Check for side-channel requests...
*/
- backendCheckSideChannel(snmp_fd, &(addr->addr));
+ backendCheckSideChannel(snmp_fd, &(addrlist->addr));
/*
* Next, open the print file and figure out its size...
@@ -920,10 +899,9 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (fstat(print_fd, &filestats))
{
- httpAddrFreeList(addrlist);
close(fd);
- _cupsLangPrintError(_("ERROR: unable to stat print file"));
+ perror("DEBUG: unable to stat print file");
return (CUPS_BACKEND_FAILED);
}
@@ -951,7 +929,6 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (lpd_command(fd, timeout, "\002%s\n",
printer)) /* Receive print job(s) */
{
- httpAddrFreeList(addrlist);
close(fd);
return (CUPS_BACKEND_FAILED);
}
@@ -1004,19 +981,19 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
(int)getpid() % 1000, localhost))
{
- httpAddrFreeList(addrlist);
close(fd);
return (CUPS_BACKEND_FAILED);
}
- _cupsLangPrintf(stderr, _("INFO: Sending control file (%u bytes)\n"),
- (unsigned)strlen(control));
+ fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n",
+ (unsigned)strlen(control));
if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
{
status = errno;
- _cupsLangPrintError(_("ERROR: Unable to write control file"));
+ perror("DEBUG: Unable to write control file");
+
}
else
{
@@ -1024,9 +1001,9 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (read(fd, &status, 1) < 1)
{
- _cupsLangPrintf(stderr,
- _("WARNING: Remote host did not respond with control "
- "status byte after %d seconds!\n"), timeout);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Printer did not respond after %d seconds."),
+ timeout);
status = errno;
}
@@ -1034,11 +1011,12 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
}
if (status != 0)
- _cupsLangPrintf(stderr,
- _("ERROR: Remote host did not accept control file "
- "(%d)\n"), status);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Remote host did not accept control file (%d)."),
+ status);
else
- _cupsLangPuts(stderr, _("INFO: Control file sent successfully\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Control file sent successfully."));
}
else
status = 0;
@@ -1059,19 +1037,13 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
CUPS_LLCAST filestats.st_size, (int)getpid() % 1000,
localhost))
{
- httpAddrFreeList(addrlist);
close(fd);
return (CUPS_BACKEND_FAILED);
}
- _cupsLangPrintf(stderr,
-#ifdef HAVE_LONG_LONG
- _("INFO: Sending data file (%lld bytes)\n"),
-#else
- _("INFO: Sending data file (%ld bytes)\n"),
-#endif /* HAVE_LONG_LONG */
- CUPS_LLCAST filestats.st_size);
+ fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n",
+ CUPS_LLCAST filestats.st_size);
tbytes = 0;
for (copy = 0; copy < manual_copies; copy ++)
@@ -1080,13 +1052,13 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0)
{
- _cupsLangPrintf(stderr,
- _("INFO: Spooling LPR job, %.0f%% complete...\n"),
- 100.0 * tbytes / filestats.st_size);
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Spooling job, %.0f%% complete."),
+ 100.0 * tbytes / filestats.st_size);
if (lpd_write(fd, buffer, nbytes) < nbytes)
{
- _cupsLangPrintError(_("ERROR: Unable to send print file to printer"));
+ perror("DEBUG: Unable to send print file to printer");
break;
}
else
@@ -1100,7 +1072,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
status = errno;
else if (lpd_write(fd, "", 1) < 1)
{
- _cupsLangPrintError(_("ERROR: Unable to send trailing nul to printer"));
+ perror("DEBUG: Unable to send trailing nul to printer");
status = errno;
}
else
@@ -1116,9 +1088,9 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (recv(fd, &status, 1, 0) < 1)
{
- _cupsLangPrintf(stderr,
- _("WARNING: Remote host did not respond with data "
- "status byte after %d seconds!\n"), timeout);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Printer did not respond after %d seconds."),
+ timeout);
status = 0;
}
@@ -1129,11 +1101,12 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
status = 0;
if (status != 0)
- _cupsLangPrintf(stderr,
- _("ERROR: Remote host did not accept data file (%d)\n"),
- status);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Remote host did not accept data file (%d)."),
+ status);
else
- _cupsLangPuts(stderr, _("INFO: Data file sent successfully\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Data file sent successfully."));
}
if (status == 0 && order == ORDER_DATA_CONTROL)
@@ -1151,19 +1124,18 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
(int)getpid() % 1000, localhost))
{
- httpAddrFreeList(addrlist);
close(fd);
return (CUPS_BACKEND_FAILED);
}
- _cupsLangPrintf(stderr, _("INFO: Sending control file (%lu bytes)\n"),
- (unsigned long)strlen(control));
+ fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n",
+ (unsigned long)strlen(control));
if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
{
status = errno;
- _cupsLangPrintError(_("ERROR: Unable to write control file"));
+ perror("DEBUG: Unable to write control file");
}
else
{
@@ -1171,9 +1143,9 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
if (read(fd, &status, 1) < 1)
{
- _cupsLangPrintf(stderr,
- _("WARNING: Remote host did not respond with control "
- "status byte after %d seconds!\n"), timeout);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Printer did not respond after %d seconds."),
+ timeout);
status = errno;
}
@@ -1181,11 +1153,12 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
}
if (status != 0)
- _cupsLangPrintf(stderr,
- _("ERROR: Remote host did not accept control file "
- "(%d)\n"), status);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Remote host did not accept control file (%d)."),
+ status);
else
- _cupsLangPuts(stderr, _("INFO: Control file sent successfully\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Control file sent successfully."));
}
/*
@@ -1202,11 +1175,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
close(fd);
if (status == 0)
- {
- httpAddrFreeList(addrlist);
-
return (CUPS_BACKEND_OK);
- }
/*
* Waiting for a retry...
@@ -1215,10 +1184,8 @@ lpd_queue(const char *hostname, /* I - Host to connect to */
sleep(30);
}
- httpAddrFreeList(addrlist);
-
/*
- * If we get here, then the job has been cancelled...
+ * If we get here, then the job has been canceled...
*/
return (CUPS_BACKEND_FAILED);
@@ -1310,12 +1277,7 @@ rresvport_af(int *port, /* IO - Port number to bind to */
* Set the port number...
*/
-# ifdef AF_INET6
- if (family == AF_INET6)
- addr.ipv6.sin6_port = htons(*port);
- else
-# endif /* AF_INET6 */
- addr.ipv4.sin_port = htons(*port);
+ _httpAddrSetPort(&addr, *port);
/*
* Try binding the port to the socket; return if all is OK...
@@ -1376,5 +1338,5 @@ sigterm_handler(int sig) /* I - Signal */
/*
- * End of "$Id: lpd.c 8938 2009-12-18 23:52:01Z mike $".
+ * End of "$Id: lpd.c 9793 2011-05-20 03:49:49Z mike $".
*/
diff --git a/backend/network.c b/backend/network.c
index ee5ef5e1..d5827c46 100644
--- a/backend/network.c
+++ b/backend/network.c
@@ -1,9 +1,9 @@
/*
- * "$Id: network.c 8896 2009-11-20 01:27:57Z mike $"
+ * "$Id: network.c 9578 2011-03-04 18:44:47Z mike $"
*
- * Common network APIs for the Common UNIX Printing System (CUPS).
+ * Common backend network APIs for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 2006-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -279,6 +279,12 @@ backendNetworkSideCB(
break;
}
+ case CUPS_SC_CMD_GET_CONNECTED :
+ status = CUPS_SC_STATUS_OK;
+ data[0] = device_fd != -1;
+ datalen = 1;
+ break;
+
default :
status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
datalen = 0;
@@ -290,5 +296,5 @@ backendNetworkSideCB(
/*
- * End of "$Id: network.c 8896 2009-11-20 01:27:57Z mike $".
+ * End of "$Id: network.c 9578 2011-03-04 18:44:47Z mike $".
*/
diff --git a/backend/pap.c b/backend/pap.c
deleted file mode 100644
index c69bbaf5..00000000
--- a/backend/pap.c
+++ /dev/null
@@ -1,1696 +0,0 @@
-/*
-* "$Id: pap.c 8807 2009-08-31 18:45:43Z mike $"
-*
-* Copyright 2004-2008 Apple Inc. All rights reserved.
-*
-* IMPORTANT: This Apple software is supplied to you by Apple Computer,
-* Inc. ("Apple") in consideration of your agreement to the following
-* terms, and your use, installation, modification or redistribution of
-* this Apple software constitutes acceptance of these terms. If you do
-* not agree with these terms, please do not use, install, modify or
-* redistribute this Apple software.
-*
-* In consideration of your agreement to abide by the following terms, and
-* subject to these terms, Apple grants you a personal, non-exclusive
-* license, under AppleÕs copyrights in this original Apple software (the
-* "Apple Software"), to use, reproduce, modify and redistribute the Apple
-* Software, with or without modifications, in source and/or binary forms;
-* provided that if you redistribute the Apple Software in its entirety and
-* without modifications, you must retain this notice and the following
-* text and disclaimers in all such redistributions of the Apple Software.
-* Neither the name, trademarks, service marks or logos of Apple Computer,
-* Inc. may be used to endorse or promote products derived from the Apple
-* Software without specific prior written permission from Apple. Except
-* as expressly stated in this notice, no other rights or licenses, express
-* or implied, are granted by Apple herein, including but not limited to
-* any patent rights that may be infringed by your derivative works or by
-* other works in which the Apple Software may be incorporated.
-*
-* The Apple Software is provided by Apple on an "AS IS" basis. APPLE
-* MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
-* THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
-* FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
-* OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
-*
-* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
-* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
-* MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
-* AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
-* STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*
-*
-* This program implements the Printer Access Protocol (PAP) on top of AppleTalk
-* Transaction Protocol (ATP). If it were to use the blocking pap functions of
-* the AppleTalk library it would need seperate threads for reading, writing
-* and status.
-*
-* Contents:
-*
-* main() - Send a file to the specified Appletalk printer.
-* listDevices() - List all LaserWriter printers in the local zone.
-* printFile() - Print file.
-* papOpen() - Open a pap session to a printer.
-* papClose() - Close a pap session.
-* papWrite() - Write bytes to a printer.
-* papCloseResp() - Send a pap close response.
-* papSendRequest() - Fomrat and send a pap packet.
-* papCancelRequest() - Cancel a pending pap request.
-* sidechannel_request() - Handle side-channel requests.
-* statusUpdate() - Print printer status to stderr.
-* parseUri() - Extract the print name and zone from a uri.
-* addPercentEscapes() - Encode a string with percent escapes.
-* removePercentEscapes - Remove percent escape sequences from a string.
-* nbptuple_compare() - Compare routine for qsort.
-* okayToUseAppleTalk() - Returns true if AppleTalk is available and enabled.
-* packet_name() - Returns packet name string.
-* connectTimeout() - Returns the connect timeout preference value.
-* signalHandler() - handle SIGINT to close the session before quiting.
-*/
-
-/*
- * This backend uses deprecated APIs for AppleTalk; we know this, so
- * silence any warnings about it...
- */
-
-#ifdef MAC_OS_X_VERSION_MIN_REQUIRED
-# undef MAC_OS_X_VERSION_MIN_REQUIRED
-#endif /* MAX_OS_X_VERSION_MIN_REQUIRED */
-#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_0
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <termios.h>
-#include <unistd.h>
-#include <assert.h>
-#include <signal.h>
-
-#include <sys/fcntl.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/errno.h>
-
-#include <cups/cups.h>
-#include <cups/backend.h>
-#include <cups/sidechannel.h>
-#include <cups/i18n.h>
-
-#include <netat/appletalk.h>
-#include <netat/atp.h>
-#include <netat/ddp.h>
-#include <netat/nbp.h>
-#include <netat/pap.h>
-
-#include <libkern/OSByteOrder.h>
-
-#ifdef HAVE_APPLETALK_AT_PROTO_H
-# include <AppleTalk/at_proto.h>
-#else
-/* These definitions come from at_proto.h... */
-# define ZIP_DEF_INTERFACE NULL
-enum { RUNNING, NOTLOADED, LOADED, OTHERERROR };
-
-extern int atp_abort(int fd, at_inet_t *dest, u_short tid);
-extern int atp_close(int fd);
-extern int atp_getreq(int fd, at_inet_t *src, char *buf, int *len, int *userdata,
- int *xo, u_short *tid, u_char *bitmap, int nowait);
-extern int atp_getresp(int fd, u_short *tid, at_resp_t *resp);
-extern int atp_look(int fd);
-extern int atp_open(at_socket *sock);
-extern int atp_sendreq(int fd, at_inet_t *dest, char *buf, int len,
- int userdata, int xo, int xo_relt, u_short *tid,
- at_resp_t *resp, at_retry_t *retry, int nowait);
-extern int atp_sendrsp(int fd, at_inet_t *dest, int xo, u_short tid,
- at_resp_t *resp);
-extern int checkATStack();
-extern int nbp_lookup(at_entity_t *entity, at_nbptuple_t *buf, int max,
- at_retry_t *retry);
-extern int nbp_make_entity(at_entity_t *entity, char *obj, char *type,
- char *zone);
-extern int zip_getmyzone(char *ifName, at_nvestr_t *zone);
-#endif /* HAVE_APPLETALK_AT_PROTO_H */
-
-#include <CoreFoundation/CFURL.h>
-#include <CoreFoundation/CFNumber.h>
-#include <CoreFoundation/CFPreferences.h>
-
-/* Defines */
-#define MAX_PRINTERS 500 /* Max number of printers we can lookup */
-#define PAP_CONNID 0
-#define PAP_TYPE 1
-#define PAP_EOF 2
-
-#define CONNID_OF(p) (((u_char *)&p)[0])
-#define TYPE_OF(p) (((u_char *)&p)[1])
-#define SEQUENCE_NUM(p) (((u_char *)&p)[2])
-#define IS_PAP_EOF(p) (((u_char *)&p)[2])
-
-#ifndef true
-#define true 1
-#define false 0
-#endif
-
-/* Globals */
-int gSockfd = 0; /* Socket descriptor */
-at_inet_t gSessionAddr = { 0 }; /* Address of the session responding socket */
-u_char gConnID = 0; /* PAP session connection id */
-u_short gSendDataID = 0; /* Transaction id of pending send-data request */
-u_short gTickleID = 0; /* Transaction id of outstanding tickle request*/
-int gWaitEOF = false; /* Option: wait for a remote's EOF */
-int gStatusInterval= 5; /* Option: 0=off else seconds between status requests*/
-int gErrorlogged = false; /* If an error was logged don't send any more INFO messages */
-int gDebug = 0; /* Option: emit debugging info */
-
-/* Local functions */
-static int listDevices(void);
-static int printFile(char* name, char* type, char* zone, int fdin, int fdout,
- int fderr, int copies, int argc);
-static int papOpen(at_nbptuple_t* tuple, u_char* connID, int* fd,
- at_inet_t* pap_to, u_char* flowQuantum);
-static int papClose();
-static int papWrite(int sockfd, at_inet_t* dest, u_short tid, u_char connID,
- u_char flowQuantum, char* data, int len, int eof);
-static int papCloseResp(int sockfd, at_inet_t* dest, int xo, u_short tid,
- u_char connID);
-static int papSendRequest(int sockfd, at_inet_t* dest, u_char connID,
- int function, u_char bitmap, int xo, int seqno);
-static int papCancelRequest(int sockfd, u_short tid);
-static void sidechannel_request();
-static void statusUpdate(char* status, u_char statusLen);
-static int parseUri(const char* argv0, char* name, char* type, char* zone);
-static int addPercentEscapes(const char* src, char* dst, int dstMax);
-static int removePercentEscapes(const char* src, char* dst, int dstMax);
-static int nbptuple_compare(const void *p1, const void *p2);
-static int okayToUseAppleTalk(void);
-static const char *packet_name(u_char x);
-static int connectTimeout(void);
-static void signalHandler(int sigraised);
-
-
-/*!
- * @function main
- * @abstract Send a file to the specified AppleTalk PAP address.
- *
- * Usage: printer-uri job-id user title copies options [file]
- *
- * @param argc # of arguments
- * @param argv array of arguments
- *
- * @result A non-zero return value for errors
- */
-int main (int argc, const char * argv[])
-{
- int err = 0;
- FILE *fp; /* Print file */
- int copies; /* Number of copies to print */
- char name[NBP_NVE_STR_SIZE + 1]; /* +1 for a nul */
- char type[NBP_NVE_STR_SIZE + 1]; /* +1 for a nul */
- char zone[NBP_NVE_STR_SIZE + 1]; /* +1 for a nul */
-
- /* Make sure status messages are not buffered... */
- setbuf(stderr, NULL);
-
- if (argc == 1 || (argc == 2 && strcmp(argv[1], "-discover") == 0))
- {
- listDevices();
-
- return 0;
- }
-
- if (argc < 6 || argc > 7)
- {
- _cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
- argv[0]);
- return (CUPS_BACKEND_FAILED);
- }
-
- /* If we have 7 arguments, print the file named on the command-line.
- * Otherwise, send stdin instead...
- */
- if (argc == 6)
- {
- fp = stdin;
- copies = 1;
- }
- else
- {
- fprintf(stderr, "DEBUG: opening print file \"%s\"\n", argv[6]);
-
- /* Try to open the print file... */
- if ((fp = fopen(argv[6], "rb")) == NULL)
- {
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open print file \"%s\": %s\n"),
- argv[6], strerror(errno));
- return (CUPS_BACKEND_FAILED);
- }
-
- copies = atoi(argv[4]);
- }
-
- /* Extract the device name and options from the URI... */
- parseUri(cupsBackendDeviceURI((char **)argv), name, type, zone);
-
- err = printFile(name, type, zone, fileno(fp), STDOUT_FILENO, STDERR_FILENO, copies, argc);
-
- if (fp != stdin)
- fclose(fp);
-
- /* Only clear the last status if there wasn't an error */
- if (err == noErr && !gErrorlogged)
- fprintf(stderr, "INFO:\n");
-
- return err;
-}
-
-
-/*!
- * @function listDevices
- * @abstract Print a list of all LaserWriter type devices registered in the default zone.
- *
- * @result A non-zero return value for errors
- */
-static int listDevices(void)
-{
- int i;
- int numberFound;
-
- at_nvestr_t at_zone;
- at_entity_t entity;
- at_nbptuple_t buf[MAX_PRINTERS];
- at_retry_t retry;
- char name[NBP_NVE_STR_SIZE+1];
- char encodedName[(3 * NBP_NVE_STR_SIZE) + 1];
- char zone[NBP_NVE_STR_SIZE+1];
- char encodedZone[(3 * NBP_NVE_STR_SIZE) + 1];
-
- /* Make sure it's okay to use appletalk */
- if (!okayToUseAppleTalk())
- {
- _cupsLangPuts(stderr, _("INFO: AppleTalk disabled in System Preferences\n"));
- return -1; /* Network is down */
- }
-
- if (zip_getmyzone(ZIP_DEF_INTERFACE, &at_zone))
- {
- _cupsLangPrintError(_("ERROR: Unable to get default AppleTalk zone"));
- return -2;
- }
-
- memcpy(zone, at_zone.str, MIN(at_zone.len, sizeof(zone)-1));
- zone[MIN(at_zone.len, sizeof(zone)-1)] = '\0';
-
- _cupsLangPrintf(stderr, _("INFO: Using default AppleTalk zone \"%s\"\n"),
- zone);
-
- addPercentEscapes(zone, encodedZone, sizeof(encodedZone));
-
- /* Look up all the printers in our zone */
- nbp_make_entity(&entity, "=", "LaserWriter", zone);
- retry.retries = 1;
- retry.interval = 1;
- retry.backoff = 1;
-
- if ((numberFound = nbp_lookup(&entity, buf, MAX_PRINTERS, &retry)) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to lookup AppleTalk printers"));
- return numberFound;
- }
-
- if (numberFound >= MAX_PRINTERS)
- _cupsLangPrintf(stderr,
- _("WARNING: Adding only the first %d printers found"),
- MAX_PRINTERS);
-
- /* Not required but sort them so they look nice */
- qsort(buf, numberFound, sizeof(at_nbptuple_t), nbptuple_compare);
-
- for (i = 0; i < numberFound; i++)
- {
- memcpy(name, buf[i].enu_entity.object.str, MIN(buf[i].enu_entity.object.len, sizeof(name)-1));
- name[MIN(buf[i].enu_entity.object.len, sizeof(name)-1)] = '\0';
-
- if (addPercentEscapes(name, encodedName, sizeof(encodedName)) == 0)
- {
- /* Each line is of the form: "class URI "make model" "info" */
- char make_model[128], /* Make and model */
- *ptr;
-
-
- if ((ptr = strchr(name, ' ')) != NULL)
- {
- /*
- * If the printer name contains spaces, it is probably a make and
- * model...
- */
-
- if (!strncmp(name, "ET00", 4))
- {
- /*
- * Drop leading ethernet address info...
- */
-
- strlcpy(make_model, ptr + 1, sizeof(make_model));
- }
- else
- strlcpy(make_model, name, sizeof(make_model));
- }
- else
- strcpy(make_model, "Unknown");
-
- printf("network pap://%s/%s/LaserWriter \"%s\" \"%s AppleTalk\"\n",
- encodedZone, encodedName, make_model, name);
- }
- }
- return numberFound;
-}
-
-
-/*!
- * @function printFile
- * @abstract Open a PAP session and send the data from the input socket to the printer.
- *
- * @param name NBP name
- * @param zone NBP zone
- * @param type NBP type
- * @param fdin File descriptor to read data from
- * @param fdout File descriptor to write printer responses to
- * @param fderr File descriptor to write printer status to
- * @param copies # of copies to send (in case in the converter couldn't handle this for us).
- * @param argc # of command line arguments.
- *
- * @result A non-zero return value for errors
- */
-static int printFile(char* name, char* type, char* zone, int fdin, int fdout, int fderr, int copies, int argc)
-{
- int err;
- int rc;
- int val;
- int len, i;
-
- char fileBuffer[4096]; /* File buffer */
- int fileBufferNbytes;
- off_t fileTbytes;
- int fileEOFRead;
- int fileEOFSent;
-
- char sockBuffer[4096 + 1]; /* Socket buffer with room for nul */
- char atpReqBuf[AT_PAP_DATA_SIZE];
- fd_set readSet;
- int use_sidechannel; /* Use side channel? */
-
- at_nbptuple_t tuple;
- at_inet_t sendDataAddr;
- at_inet_t src;
- at_resp_t resp;
- int userdata, xo = 0, reqlen;
- u_short tid;
- u_char bitmap;
- int maxfdp1,
- nbp_failures = 0;
- struct timeval timeout, *timeoutPtr;
- u_char flowQuantum = 1;
- time_t now,
- start_time,
- elasped_time,
- sleep_time,
- connect_timeout = -1,
- nextStatusTime = 0;
- at_entity_t entity;
- at_retry_t retry;
-
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
- /*
- * Test the side channel descriptor before calling papOpen() since it may open
- * an unused fd 4 (a.k.a. CUPS_SC_FD)...
- */
-
- FD_ZERO(&readSet);
- FD_SET(CUPS_SC_FD, &readSet);
-
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
-
- if ((select(CUPS_SC_FD+1, &readSet, NULL, NULL, &timeout)) >= 0)
- use_sidechannel = 1;
- else
- use_sidechannel = 0;
-
- /* try to find our printer */
- if ((err = nbp_make_entity(&entity, name, type, zone)) != noErr)
- {
- _cupsLangPrintError(_("ERROR: Unable to make AppleTalk address"));
- goto Exit;
- }
-
- /*
- * Remember when we started looking for the printer.
- */
-
- start_time = time(NULL);
-
- retry.interval = 1;
- retry.retries = 5;
- retry.backoff = 0;
-
- fprintf(stderr, "STATE: +connecting-to-device\n");
-
- /* Loop forever trying to get an open session with the printer. */
- for (;;)
- {
- /* Make sure it's okay to use appletalk */
- if (okayToUseAppleTalk())
- {
- /* Clear this printer-state-reason in case we've set it */
- fprintf(stderr, "STATE: -apple-appletalk-disabled-warning\n");
-
- /* Resolve the name into an address. Returns the number found or an error */
- if ((err = nbp_lookup(&entity, &tuple, 1, &retry)) > 0)
- {
- if (err > 1)
- fprintf(stderr, "DEBUG: Found more than one printer with the name \"%s\"\n", name);
-
- if (nbp_failures)
- {
- fprintf(stderr, "STATE: -apple-nbp-lookup-warning\n");
- nbp_failures = 0;
- }
-
- /* Open a connection to the device */
- if ((err = papOpen(&tuple, &gConnID, &gSockfd, &gSessionAddr, &flowQuantum)) == 0)
- break;
-
- _cupsLangPrintf(stderr, _("WARNING: Unable to open \"%s:%s\": %s\n"),
- name, zone, strerror(err));
- }
- else
- {
- /* It's not unusual to have to call nbp_lookup() twice before it's sucessful... */
- if (++nbp_failures > 2)
- {
- retry.interval = 2;
- retry.retries = 3;
- fprintf(stderr, "STATE: +apple-nbp-lookup-warning\n");
- _cupsLangPuts(stderr, _("WARNING: Printer not responding\n"));
- }
- }
- }
- else
- {
- fprintf(stderr, "STATE: +apple-appletalk-disabled-warning\n");
- _cupsLangPuts(stderr,
- _("INFO: AppleTalk disabled in System Preferences.\n"));
- }
-
- elasped_time = time(NULL) - start_time;
-
- if (connect_timeout == -1)
- connect_timeout = connectTimeout();
-
- if (connect_timeout && elasped_time > connect_timeout)
- {
- _cupsLangPuts(stderr, _("ERROR: Printer not responding\n"));
- err = ETIMEDOUT;
- goto Exit; /* Waiting too long... */
- }
- else if (elasped_time < (30 * 60))
- sleep_time = 10; /* Waiting < 30 minutes */
- else if (elasped_time < (24 * 60 * 60))
- sleep_time = 30; /* Waiting < 24 hours */
- else
- sleep_time = 60; /* Waiting > 24 hours */
-
- fprintf(stderr, "DEBUG: sleeping %d seconds...\n", (int)sleep_time);
- sleep(sleep_time);
- }
-
- fprintf(stderr, "STATE: -connecting-to-device\n");
-
- /*
- * Now that we are connected to the printer ignore SIGTERM so that we
- * can finish out any page data the driver sends (e.g. to eject the
- * current page... if we are printing data from a file then catch the
- * signal so we can send a PAP Close packet (otherwise you can't cancel
- * raw jobs...)
- */
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
- sigset(SIGTERM, (argc < 7) ? SIG_IGN : signalHandler);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
-
- sigemptyset(&action.sa_mask);
- action.sa_handler = (argc < 7) ? SIG_IGN : signalHandler;
- sigaction(SIGTERM, &action, NULL);
-#else
- signal(SIGTERM, (argc < 7) ? SIG_IGN : signalHandler);
-
-#ifdef DEBUG
- /* Makes debugging easier; otherwise printer will be busy for several minutes */
- signal(SIGINT, signalHandler);
-#endif /* DEBUG */
-
-#endif /* HAVE_SIGSET */
-
- _cupsLangPuts(stderr, _("INFO: Sending data\n"));
-
- sendDataAddr = tuple.enu_addr;
-
- /* Start the tickle packets and set a timeout alarm */
- if ((err = papSendRequest(gSockfd, &gSessionAddr, gConnID, AT_PAP_TYPE_TICKLE, 0, false, false)) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to send PAP tickle request"));
- goto Exit;
- }
- signal(SIGALRM, signalHandler);
- alarm(PAP_TIMEOUT);
-
- /* Prime the pump with an initial send-data packet */
- if ((err = papSendRequest(gSockfd, &gSessionAddr, gConnID, AT_PAP_TYPE_SEND_DATA, 0xFF, true, true)) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to send initial PAP send data request"));
- goto Exit;
- }
-
- /* Set non-blocking mode on our data source descriptor */
- val = fcntl(fdin, F_GETFL, 0);
- fcntl(fdin, F_SETFL, val | O_NONBLOCK);
-
- fileBufferNbytes = 0;
- fileTbytes = 0;
- fileEOFRead = fileEOFSent = false;
-
- maxfdp1 = MAX(fdin, gSockfd) + 1;
-
- if (use_sidechannel && CUPS_SC_FD >= maxfdp1)
- maxfdp1 = CUPS_SC_FD + 1;
-
- if (gStatusInterval != 0)
- {
- timeout.tv_usec = 0;
- nextStatusTime = time(NULL) + gStatusInterval;
- timeoutPtr = &timeout;
- }
- else
- timeoutPtr = NULL;
-
-
- for (;;)
- {
- /* Set up our descriptors for the select */
- FD_ZERO(&readSet);
- FD_SET(gSockfd, &readSet);
-
- if (fileBufferNbytes == 0 && fileEOFRead == false)
- FD_SET(fdin, &readSet);
-
- if (use_sidechannel)
- FD_SET(CUPS_SC_FD, &readSet);
-
- /* Set the select timeout value based on the next status interval */
- if (gStatusInterval != 0)
- {
- now = time(NULL);
- timeout.tv_sec = (nextStatusTime > now) ? nextStatusTime - now : 1;
- }
-
- /* Wait here for something interesting to happen */
- if ((err = select(maxfdp1, &readSet, 0, 0, timeoutPtr)) < 0)
- {
- _cupsLangPrintError(_("ERROR: select() failed"));
- break;
- }
-
- if (err == 0 || (gStatusInterval != 0 && time(NULL) >= nextStatusTime))
- {
- /* Time to send a status request */
- if ((err = papSendRequest(gSockfd, &tuple.enu_addr, 0, AT_PAP_TYPE_SEND_STATUS, 0x01, false, false)) < 0)
- _cupsLangPrintError(_("WARNING: Unable to send PAP status request"));
-
- if (gStatusInterval)
- nextStatusTime = time(NULL) + gStatusInterval;
- }
-
- /*
- * Check if we have a side-channel request ready...
- */
-
- if (use_sidechannel && FD_ISSET(CUPS_SC_FD, &readSet))
- sidechannel_request();
-
- /* Was there an event on the input stream? */
- if (FD_ISSET(fdin, &readSet))
- {
- FD_CLR(fdin, &readSet);
-
- assert(fileBufferNbytes == 0);
- fileBufferNbytes = read(fdin, fileBuffer, MIN(sizeof(fileBuffer), AT_PAP_DATA_SIZE * flowQuantum));
- if (fileBufferNbytes == 0)
- fileEOFRead = true;
-
- if (fileEOFSent == false && fileBufferNbytes >= 0 && gSendDataID != 0)
- {
- fprintf(stderr, "DEBUG: -> PAP_DATA %d bytes %s\n", fileBufferNbytes, fileEOFRead ? "with EOF" : "");
- papWrite(gSockfd, &sendDataAddr, gSendDataID, gConnID, flowQuantum, fileBuffer, fileBufferNbytes, fileEOFRead);
-
- fileTbytes += fileBufferNbytes;
- if (argc > 6 && !gErrorlogged)
- fprintf(stderr, "DEBUG: Sending print file, %qd bytes\n", (off_t)fileTbytes);
-
- fileBufferNbytes = 0;
- gSendDataID = 0;
- if (fileEOFRead)
- {
- fileEOFSent = true;
- if (gWaitEOF == false || fileTbytes == 0)
- {
- err = 0;
- goto Exit;
- }
- }
- }
- }
-
- /* Was there an event on the output stream? */
- if (FD_ISSET(gSockfd, &readSet))
- {
- if ((rc = atp_look(gSockfd)) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to look for PAP response"));
- break;
- }
-
- if (rc > 0)
- {
- /* It's an ATP response */
- resp.resp[0].iov_base = sockBuffer;
- resp.resp[0].iov_len = sizeof(sockBuffer) - 1;
- resp.bitmap = 0x01;
-
- if ((err = atp_getresp(gSockfd, &tid, &resp)) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to get PAP response"));
- break;
- }
- userdata = resp.userdata[0];
- }
- else
- {
- /* It's an ATP request */
- reqlen = sizeof(atpReqBuf);
- if ((err = atp_getreq(gSockfd, &src, atpReqBuf, &reqlen, &userdata, &xo, &tid, &bitmap, 0)) < 0)
- {
- _cupsLangPrintError(_("ERROR: Unable to get PAP request"));
- break;
- }
- }
-
- fprintf(stderr, "DEBUG: <- %s\n", packet_name(TYPE_OF(userdata)));
-
- switch (TYPE_OF(userdata))
- {
- case AT_PAP_TYPE_SEND_STS_REPLY: /* Send-Status-Reply packet */
- if (resp.bitmap & 1)
- {
- char *iov_base = (char *)resp.resp[0].iov_base;
- statusUpdate(&iov_base[5], iov_base[4]);
- }
- break;
-
- case AT_PAP_TYPE_SEND_DATA: /* Send-Data packet */
- sendDataAddr.socket = src.socket;
- gSendDataID = tid;
- OSReadBigInt16(&SEQUENCE_NUM(userdata), 0);
-
- if ((fileBufferNbytes > 0 || fileEOFRead) && fileEOFSent == false)
- {
- fprintf(stderr, "DEBUG: -> PAP_DATA %d bytes %s\n", fileBufferNbytes, fileEOFRead ? "with EOF" : "");
- papWrite(gSockfd, &sendDataAddr, gSendDataID, gConnID, flowQuantum, fileBuffer, fileBufferNbytes, fileEOFRead);
-
- fileTbytes += fileBufferNbytes;
- if (argc > 6 && !gErrorlogged)
- fprintf(stderr, "DEBUG: Sending print file, %qd bytes\n", (off_t)fileTbytes);
-
- fileBufferNbytes = 0;
- gSendDataID = 0;
- if (fileEOFRead)
- {
- fileEOFSent = true;
- if (gWaitEOF == false)
- {
- err = 0;
- goto Exit;
- }
- }
- }
- break;
-
- case AT_PAP_TYPE_DATA: /* Data packet */
- for (len=0, i=0; i < ATP_TRESP_MAX; i++)
- {
- if (resp.bitmap & (1 << i))
- len += resp.resp[i].iov_len;
- }
-
- fprintf(stderr, "DEBUG: <- PAP_DATA %d bytes %s\n", len, IS_PAP_EOF(userdata) ? "with EOF" : "");
-
- if (len > 0)
- {
- char *pLineBegin, *pCommentEnd, *pChar;
- char *logLevel;
- char logstr[512];
- int logstrlen;
-
- cupsBackChannelWrite(sockBuffer, len, 1.0);
-
- sockBuffer[len] = '\0'; /* We always reserve room for the nul so we can use strstr() below*/
- pLineBegin = sockBuffer;
-
- /* If there are PostScript status comments in the buffer log them.
- *
- * This logic shouldn't be in the backend but until we get backchannel
- * data in CUPS 1.2 it has to live here.
- */
- while (pLineBegin < sockBuffer + len &&
- (pLineBegin = strstr(pLineBegin, "%%[")) != NULL &&
- (pCommentEnd = strstr(pLineBegin, "]%%")) != NULL)
- {
- pCommentEnd += 3; /* Skip past "]%%" */
- *pCommentEnd = '\0'; /* There's always room for the nul */
-
- /* Strip the CRs & LFs before writing it to stderr */
- for (pChar = pLineBegin; pChar < pCommentEnd; pChar++)
- if (*pChar == '\r' || *pChar == '\n')
- *pChar = ' ';
-
- if (strncasecmp(pLineBegin, "%%[ Error:", 10) == 0)
- {
- /* logLevel should be "ERROR" here but this causes PrintCenter
- * to pause the queue which in turn clears this error, which
- * restarts the job. So the job ends up in an infinite loop with
- * the queue being held/un-held. Just make it DEBUG for now until
- * we fix notifications later.
- */
- logLevel = "DEBUG";
- gErrorlogged = true;
- }
- else if (strncasecmp(pLineBegin, "%%[ Flushing", 12) == 0)
- logLevel = "DEBUG";
- else
- logLevel = "INFO";
-
- if ((logstrlen = snprintf(logstr, sizeof(logstr), "%s: %s\n", logLevel, pLineBegin)) >= sizeof(logstr))
- {
- /* If the string was trucnated make sure it has a linefeed before the nul */
- logstrlen = sizeof(logstr) - 1;
- logstr[logstrlen - 1] = '\n';
- }
-
- write(fderr, logstr, logstrlen);
-
- pLineBegin = pCommentEnd + 1;
- }
- }
-
- if (IS_PAP_EOF(userdata) != 0)
- {
- /* If this is EOF then were we expecting it? */
- if (fileEOFSent == true)
- goto Exit;
- else
- {
- _cupsLangPuts(stderr, _("WARNING: Printer sent unexpected EOF\n"));
- }
- }
-
- if ((err = papSendRequest(gSockfd, &gSessionAddr, gConnID, AT_PAP_TYPE_SEND_DATA, 0xFF, true, true)) < 0)
- {
- _cupsLangPrintf(stderr,
- _("ERROR: Error %d sending PAPSendData request: %s\n"),
- err, strerror(errno));
- goto Exit;
- }
- break;
-
- case AT_PAP_TYPE_TICKLE: /* Tickle packet */
- break;
-
- case AT_PAP_TYPE_CLOSE_CONN: /* Close-Connection packet */
- /* We shouldn't normally see this. */
- papCloseResp(gSockfd, &gSessionAddr, xo, tid, gConnID);
-
- /* If this is EOF then were we expecting it? */
- if (fileEOFSent == true)
- {
- _cupsLangPuts(stderr, _("WARNING: Printer sent unexpected EOF\n"));
- }
- else
- {
- _cupsLangPuts(stderr, _("ERROR: Printer sent unexpected EOF\n"));
- }
- goto Exit;
- break;
-
- case AT_PAP_TYPE_OPEN_CONN: /* Open-Connection packet */
- case AT_PAP_TYPE_OPEN_CONN_REPLY: /* Open-Connection-Reply packet */
- case AT_PAP_TYPE_SEND_STATUS: /* Send-Status packet */
- case AT_PAP_TYPE_CLOSE_CONN_REPLY: /* Close-Connection-Reply packet */
- _cupsLangPrintf(stderr, _("WARNING: Unexpected PAP packet of type %d\n"),
- TYPE_OF(userdata));
- break;
-
- default:
- _cupsLangPrintf(stderr, _("WARNING: Unknown PAP packet of type %d\n"),
- TYPE_OF(userdata));
- break;
- }
-
- if (CONNID_OF(userdata) == gConnID)
- {
- /* Reset tickle timer */
- alarm(0);
- alarm(PAP_TIMEOUT);
- }
- }
- }
-
-Exit:
- /*
- * Close the socket and return...
- */
- papClose();
-
- return err;
-}
-
-
-#pragma mark -
-/*!
- * @function papOpen
- * @abstract Open a pap session to a printer.
- *
- * @param tuple nbp address of printer
- * @param connID returned pap connection id
- * @param fd returned socket descriptor
- * @param sessionAddr returned session address
- * @param flowQuantum returned flow quantum (usually 8)
- *
- * @result A non-zero return value for errors
- */
-static int papOpen(at_nbptuple_t* tuple, u_char* connID, int* fd,
- at_inet_t* sessionAddr, u_char* flowQuantum)
-{
- int result,
- open_result,
- userdata;
- time_t tm,
- waitTime;
- char data[10],
- rdata[ATP_DATA_SIZE];
- u_char *puserdata;
- at_socket socketfd;
- at_resp_t resp;
- at_retry_t retry;
-
- result = 0;
- socketfd = 0;
- puserdata = (u_char *)&userdata;
-
- _cupsLangPuts(stderr, _("INFO: Opening connection\n"));
-
- if ((*fd = atp_open(&socketfd)) < 0)
- return -1;
-
- /*
- * Build the open connection request packet.
- */
-
- tm = time(NULL);
- srand(tm);
-
- *connID = (rand()&0xff) | 0x01;
- puserdata[0] = *connID;
- puserdata[1] = AT_PAP_TYPE_OPEN_CONN;
- puserdata[2] = 0;
- puserdata[3] = 0;
-
- retry.interval = 2;
- retry.retries = 5;
-
- resp.bitmap = 0x01;
- resp.resp[0].iov_base = rdata;
- resp.resp[0].iov_len = sizeof(rdata);
-
- data[0] = socketfd;
- data[1] = 8;
-
- for (;;)
- {
- waitTime = time(NULL) - tm;
- OSWriteBigInt16(&data[2], 0, (u_short)waitTime);
-
- fprintf(stderr, "DEBUG: -> %s\n", packet_name(AT_PAP_TYPE_OPEN_CONN));
-
- if (atp_sendreq(*fd, &tuple->enu_addr, data, 4, userdata, 1, 0,
- 0, &resp, &retry, 0) < 0)
- {
- statusUpdate("Destination unreachable", 23);
- result = EHOSTUNREACH;
- break;
- }
-
- puserdata = (u_char *)&resp.userdata[0];
- open_result = OSReadBigInt16(&rdata[2], 0);
-
- fprintf(stderr, "DEBUG: <- %s, status %d\n", packet_name(puserdata[1]),
- open_result);
-
- /*
- * Just for the sake of our sanity check the other fields in the packet
- */
-
- if (puserdata[1] != AT_PAP_TYPE_OPEN_CONN_REPLY ||
- (open_result == 0 && (puserdata[0] & 0xff) != *connID))
- {
- result = EINVAL;
- break;
- }
-
- statusUpdate(&rdata[5], rdata[4] & 0xff);
-
- /*
- * if the connection established okay exit from the loop
- */
-
- if (open_result == 0)
- break;
-
- sleep(1);
- }
-
- if (result == 0)
- {
- /* Update the session address
- */
- sessionAddr->net = tuple->enu_addr.net;
- sessionAddr->node = tuple->enu_addr.node;
- sessionAddr->socket = rdata[0];
- *flowQuantum = rdata[1];
- }
- else
- {
- atp_close(*fd);
- *fd = 0;
- sleep(1);
- }
-
- return result;
-}
-
-
-/*!
- * @function papClose
- * @abstract End a PAP session by canceling outstanding send-data & tickle
- * transactions and sending a PAP close request.
- *
- * @result A non-zero return value for errors
- */
-static int papClose()
-{
- int fd;
- u_short tmpID;
- unsigned char rdata[ATP_DATA_SIZE];
- int userdata;
- u_char *puserdata = (u_char *)&userdata;
- at_resp_t resp;
- at_retry_t retry;
-
- if (gSockfd != 0)
- {
- fd = gSockfd;
- gSockfd = 0;
-
- alarm(0);
-
- /* Cancel the pending send-data and tickle trnsactions
- */
- if (gSendDataID)
- {
- tmpID = gSendDataID;
- gSendDataID = 0;
- papCancelRequest(fd, tmpID);
- }
-
- if (gTickleID)
- {
- tmpID = gTickleID;
- gTickleID = 0;
- papCancelRequest(fd, tmpID);
- }
-
- /* This is a workaround for bug #2735145. The problem is papWrite()
- * returns before the ATP TRel arrives for it. If we send the pap close packet
- * before this release then the printer can drop the last data packets.
- * The effect on an Epson printer is the last page doesn't print, on HP it
- * doesn't close the pap session.
- */
- if (gWaitEOF == false)
- sleep(2);
-
- fprintf(stderr, "DEBUG: -> %s\n", packet_name(AT_PAP_TYPE_CLOSE_CONN));
-
- puserdata[0] = gConnID;
- puserdata[1] = AT_PAP_TYPE_CLOSE_CONN;
- puserdata[2] = 0;
- puserdata[3] = 0;
-
- retry.interval = 2;
- retry.retries = 5;
-
- resp.bitmap = 0x01;
- resp.resp[0].iov_base = rdata;
- resp.resp[0].iov_len = sizeof(rdata);
-
- atp_sendreq(fd, &gSessionAddr, 0, 0, userdata, 1, 0, 0, &resp, &retry, 0);
-
- close(fd);
- }
- return noErr;
-}
-
-
-/*!
- * @function papWrite
- * @abstract Write bytes to a printer.
- *
- * @param sockfd socket descriptor
- * @param dest destination address
- * @param tid transaction id
- * @param connID connection id
- * @param flowQuantum returned flow quantum (usually 8)
- * @param data pointer to the data
- * @param len number of bytes to send
- * @param eof pap eof flag
- *
- * @result A non-zero return value for errors
- */
-static int papWrite(int sockfd, at_inet_t* dest, u_short tid, u_char connID, u_char flowQuantum, char* data, int len, int eof)
-{
- int result;
- int i;
- u_char* puserdata;
- at_resp_t resp;
-
- /* fprintf(stderr, "DEBUG: papWrite(%d%s) to %d,%d,%d; %d\n", len, eof ? " EOF":"", dest->net, dest->node, dest->socket, connID); */
-
- if (len > AT_PAP_DATA_SIZE * flowQuantum)
- {
- fprintf(stderr, "DEBUG: papWrite() len of %d is too big!\n", len);
- errno = E2BIG;
- return -1;
- }
-
- /*
- * Break up the outgoing data into a set of
- * response packets to reply to an incoming
- * PAP 'SENDDATA' request
- */
- for (i = 0; i < flowQuantum; i++)
- {
- resp.userdata[i] = 0;
- puserdata = (u_char *)&resp.userdata[i];
-
- puserdata[PAP_CONNID] = connID;
- puserdata[PAP_TYPE] = AT_PAP_TYPE_DATA;
- puserdata[PAP_EOF] = eof ? 1 : 0;
-
- resp.resp[i].iov_base = (caddr_t)data;
-
- if (data)
- data += AT_PAP_DATA_SIZE;
-
- resp.resp[i].iov_len = MIN((int)len, (int)AT_PAP_DATA_SIZE);
- len -= resp.resp[i].iov_len;
- if (len == 0)
- break;
- }
- resp.bitmap = (1 << (i + 1)) - 1;
-
- /*
- * Write out the data as a PAP 'DATA' response
- */
- errno = 0;
- if ((result = atp_sendrsp(sockfd, dest, true, tid, &resp)) < 0)
- {
- fprintf(stderr, "DEBUG: atp_sendrsp() returns %d, errno %d \"%s\"\n", result, errno, strerror(errno));
- return -1;
- }
- return(0);
-}
-
-
-/*!
- * @function papCloseResp
- * @abstract Send a pap close response in the rare case we receive a close connection request.
- *
- * @param sockfd socket descriptor
- * @param dest destination address
- * @param tid transaction id
- * @param connID connection id
- *
- * @result A non-zero return value for errors
- */
-static int papCloseResp(int sockfd, at_inet_t* dest, int xo, u_short tid, u_char connID)
-{
- int result;
- at_resp_t resp;
-
- resp.bitmap = 1;
- resp.userdata[0] = 0;
-
- ((u_char*)&resp.userdata[0])[PAP_CONNID] = connID;
- ((u_char*)&resp.userdata[0])[PAP_TYPE] = AT_PAP_TYPE_CLOSE_CONN_REPLY;
-
- resp.resp[0].iov_base = NULL;
- resp.resp[0].iov_len = 0;
-
- if ((result = atp_sendrsp(sockfd, dest, xo, tid, &resp)) < 0)
- {
- fprintf(stderr, "DEBUG: atp_sendrsp() returns %d, errno %d \"%s\"\n", result, errno, strerror(errno));
- return -1;
- }
- return 0;
-}
-
-
-/*!
- * @function papSendRequest
- * @abstract Send a pap close response in the rare case we receive a close connection request.
- *
- * @param sockfd socket descriptor
- * @param dest destination address
- * @param function pap function
- * @param bitmap bitmap
- * @param xo exactly once
- * @param seqno sequence number
- *
- * @result A non-zero return value for errors
- */
-static int papSendRequest(int sockfd, at_inet_t* dest, u_char connID, int function, u_char bitmap, int xo, int seqno)
-{
- u_short tid;
- int err;
- sigset_t sv, osv;
- int userdata;
- u_char *puserdata = (u_char *)&userdata;
- at_retry_t retry;
- at_resp_t resp;
- static u_short pap_send_count = 0;
-
- fprintf(stderr, "DEBUG: -> %s\n", packet_name(function));
-
- puserdata[0] = connID;
- puserdata[1] = function;
- resp.bitmap = bitmap;
- retry.interval = 10;
- retry.retries = -1; /* was ATP_INFINITE_RETRIES */
- if (seqno)
- {
- pap_send_count++;
- if (pap_send_count == 0)
- pap_send_count = 1;
-
- OSWriteBigInt16(&puserdata[2], 0, pap_send_count);
- }
- else
- OSWriteBigInt16(&puserdata[2], 0, 0);
-
- sigemptyset(&sv);
- sigaddset(&sv, SIGIO);
- sigprocmask(SIG_SETMASK, &sv, &osv);
-
- err = atp_sendreq(sockfd, dest, 0, 0, userdata, xo, 0, &tid, &resp, &retry, 1);
-
- sigprocmask(SIG_SETMASK, &osv, NULL);
-
- return err;
-}
-
-
-/*!
- * @function papCancelRequest
- * @abstract Cancel a pending pap request.
- *
- * @param sockfd socket descriptor
- * @param tid transaction ID
- *
- * @result A non-zero return value for errors
- */
-int papCancelRequest(int sockfd, u_short tid)
-{
- sigset_t sv, osv;
-
- sigemptyset(&sv);
- sigaddset(&sv, SIGIO);
- sigprocmask(SIG_SETMASK, &sv, &osv);
-
- if (atp_abort(sockfd, NULL, tid) < 0)
- {
- sigprocmask(SIG_SETMASK, &osv, NULL);
- return -1;
- }
- sigprocmask(SIG_SETMASK, &osv, NULL);
-
- return 0;
-}
-
-
-/*
- * 'sidechannel_request()' - Handle side-channel requests.
- */
-
-static int
-sidechannel_request()
-{
- cups_sc_command_t command; /* Request command */
- cups_sc_status_t status; /* Request/response status */
- char data[2048]; /* Request/response data */
- int datalen; /* Request/response data size */
-
- datalen = sizeof(data);
-
- if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
- return (-1);
-
- switch (command)
- {
- case CUPS_SC_CMD_GET_BIDI: /* Is the connection bidirectional? */
- data[0] = 1;
- return (cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, 1, 1.0));
- break;
-
- case CUPS_SC_CMD_GET_STATE: /* Return device state */
- data[0] = CUPS_SC_STATE_ONLINE;
- return (cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, 1, 1.0));
- break;
-
- case CUPS_SC_CMD_DRAIN_OUTPUT: /* Drain all pending output */
- case CUPS_SC_CMD_SOFT_RESET: /* Do a soft reset */
- case CUPS_SC_CMD_GET_DEVICE_ID: /* Return IEEE-1284 device ID */
- default:
- return (cupsSideChannelWrite(command, CUPS_SC_STATUS_NOT_IMPLEMENTED,
- NULL, 0, 1.0));
- break;
- }
- return (0);
-}
-
-
-#pragma mark -
-/*!
- * @function statusUpdate
- * @abstract Format and print a PAP status response to stderr.
- *
- * @param status The status response string
- * @param statusLen The length of the status response string
- */
-void statusUpdate(char* status, u_char statusLen)
-{
- static char status_str[255];
- static u_char last_statusLen = 0xFF;
-
- /* Only send this if the status has changed */
- if (statusLen != last_statusLen || memcmp(status, status_str, statusLen) != 0)
- {
- if (statusLen > sizeof(status_str)-1)
- statusLen = sizeof(status_str)-1;
- last_statusLen = statusLen;
- memcpy(status_str, status, statusLen);
- status_str[(int)statusLen] = '\0';
-
- /*
- * Make sure the status string is in the form of a PostScript comment.
- */
-
- if (statusLen > 3 && memcmp(status, "%%[", 3) == 0)
- fprintf(stderr, "INFO: %s\n", status_str);
- else
- fprintf(stderr, "INFO: %%%%[ %s ]%%%%\n", status_str);
- }
- return;
-}
-
-
-/*!
- * @function parseUri
- * @abstract Parse a PAP URI into it's NBP components.
- *
- * @param argv0 The PAP URI to parse
- * @param name NBP name
- * @param zone NBP zone
- * @param type NBP type
- *
- * @result A non-zero return value for errors
- */
-static int parseUri(const char* argv0, char* name, char* type, char* zone)
-{
- char method[255], /* Method in URI */
- hostname[1024], /* Hostname */
- username[255], /* Username info (not used) */
- resource[1024], /* Resource info (device and options) */
- *resourcePtr,
- *typePtr,
- *options, /* Pointer to options */
- *optionName, /* Name of option */
- *value, /* Value of option */
- sep; /* Separator character */
- int port; /* Port number (not used) */
- int statusInterval; /* */
-
- /*
- * Extract the device name and options from the URI...
- */
- method[0] = username[0] = hostname[0] = resource[0] = '\0';
- port = 0;
-
- httpSeparateURI(HTTP_URI_CODING_NONE, argv0, method, sizeof(method),
- username, sizeof(username),
- hostname, sizeof(hostname), &port,
- resource, sizeof(resource));
-
- /*
- * See if there are any options...
- */
- if ((options = strchr(resource, '?')) != NULL)
- {
- /*
- * Yup, terminate the device name string and move to the first
- * character of the options...
- */
- *options++ = '\0';
-
- while (*options != '\0')
- {
- /*
- * Get the name...
- */
-
- optionName = options;
-
- while (*options && *options != '=' && *options != '+' && *options != '&')
- options ++;
-
- if ((sep = *options) != '\0')
- *options++ = '\0';
-
- if (sep == '=')
- {
- /*
- * Get the value...
- */
-
- value = options;
-
- while (*options && *options != '+' && *options != '&')
- options ++;
-
- if (*options)
- *options++ = '\0';
- }
- else
- value = (char *)"";
-
- /*
- * Process the option...
- */
-
- if (!strcasecmp(optionName, "waiteof"))
- {
- /*
- * Wait for the end of the print file?
- */
-
- if (!strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "true"))
- {
- gWaitEOF = true;
- }
- else if (!strcasecmp(value, "off") ||
- !strcasecmp(value, "no") ||
- !strcasecmp(value, "false"))
- {
- gWaitEOF = false;
- }
- else
- {
- _cupsLangPrintf(stderr,
- _("WARNING: Boolean expected for waiteof option \"%s\"\n"),
- value);
- }
- }
- else if (!strcasecmp(optionName, "status"))
- {
- /*
- * Set status reporting interval...
- */
-
- statusInterval = atoi(value);
- if (value[0] < '0' || value[0] > '9' || statusInterval < 0)
- {
- _cupsLangPrintf(stderr,
- _("WARNING: number expected for status option \"%s\"\n"),
- value);
- }
- else
- {
- gStatusInterval = statusInterval;
- }
- }
- }
- }
-
- resourcePtr = resource;
-
- if (*resourcePtr == '/')
- resourcePtr++;
-
- /* If the resource has a slash we assume the slash seperates the AppleTalk object
- * name from the AppleTalk type. If the slash is not present we assume the AppleTalk
- * type is LaserWriter.
- */
-
- typePtr = strchr(resourcePtr, '/');
- if (typePtr != NULL)
- {
- *typePtr++ = '\0';
- }
- else
- {
- typePtr = "LaserWriter";
- }
-
- removePercentEscapes(hostname, zone, NBP_NVE_STR_SIZE + 1);
- removePercentEscapes(resourcePtr, name, NBP_NVE_STR_SIZE + 1);
- removePercentEscapes(typePtr, type, NBP_NVE_STR_SIZE + 1);
-
- return 0;
-}
-
-
-/*!
- * @function addPercentEscapes
- * @abstract Encode a string with percent escapes
- *
- * @param src The source C string
- * @param dst Desination buffer
- * @param dstMax Size of desination buffer
- *
- * @result A non-zero return value for errors
- */
-static int addPercentEscapes(const char* src, char* dst, int dstMax)
-{
- char c;
- char *dstEnd = dst + dstMax - 1; /* -1 to leave room for the NUL */
-
- while (*src)
- {
- c = *src++;
-
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') || (c == '.' || c == '-' || c == '*' || c == '_'))
- {
- if (dst >= dstEnd)
- return -1;
-
- *dst++ = c;
- }
- else
- {
- if (dst >= dstEnd - 2)
- return -1;
-
- snprintf(dst, dstEnd - dst, "%%%02x", c);
- dst += 3;
- }
- }
-
- *dst = '\0';
- return 0;
-}
-
-
-/*!
- * @function removePercentEscapes
- * @abstract Returns a string with any percent escape sequences replaced with their equivalent character
- *
- * @param src Source buffer
- * @param srclen Number of bytes in source buffer
- * @param dst Desination buffer
- * @param dstMax Size of desination buffer
- *
- * @result A non-zero return value for errors
- */
-static int removePercentEscapes(const char* src, char* dst, int dstMax)
-{
- int c;
- const char *dstEnd = dst + dstMax;
-
- while (*src && dst < dstEnd)
- {
- c = *src++;
-
- if (c == '%')
- {
- sscanf(src, "%02x", &c);
- src += 2;
- }
- *dst++ = (char)c;
- }
-
- if (dst >= dstEnd)
- return -1;
-
- *dst = '\0';
- return 0;
-}
-
-
-/*!
- * @function nbptuple_compare
- * @abstract An NBP comparator for qsort.
- *
- * @result p1<p2: -1, p1=p2: 0, p1>p2: 1
- */
-int nbptuple_compare(const void *p1, const void *p2)
-{
- int result;
- int len = MIN(((at_nbptuple_t*)p1)->enu_entity.object.len,
- ((at_nbptuple_t*)p2)->enu_entity.object.len);
-
- if ((result = memcmp(((at_nbptuple_t*)p1)->enu_entity.object.str, ((at_nbptuple_t*)p2)->enu_entity.object.str, len)) == 0)
- {
- if (((at_nbptuple_t*)p1)->enu_entity.object.len < ((at_nbptuple_t*)p2)->enu_entity.object.len)
- result = -1;
- else if (((at_nbptuple_t*)p1)->enu_entity.object.len > ((at_nbptuple_t*)p2)->enu_entity.object.len)
- result = 1;
- else
- result = 0;
- }
- return result;
-}
-
-
-/*!
- * @function okayToUseAppleTalk
- * @abstract Returns true if AppleTalk is available and enabled.
- *
- * @result non-zero if AppleTalk is enabled
- */
-static int okayToUseAppleTalk()
-{
- int atStatus = checkATStack();
-
- /* I think the test should be:
- * return atStatus == RUNNING || atStatus == LOADED;
- * but when I disable AppleTalk from the network control panel and
- * reboot, AppleTalk shows up as loaded. The test empirically becomes
- * the following:
- */
- return atStatus == RUNNING;
-}
-
-
-/*!
- * @function packet_name
- * @abstract Returns packet name string.
- *
- * @result A string
- */
-static const char *packet_name(u_char x)
-{
- switch (x)
- {
- case AT_PAP_TYPE_OPEN_CONN: return "PAP_OPEN_CONN";
- case AT_PAP_TYPE_OPEN_CONN_REPLY: return "PAP_OPEN_CONN_REPLY";
- case AT_PAP_TYPE_SEND_DATA: return "PAP_SEND_DATA";
- case AT_PAP_TYPE_DATA: return "PAP_DATA";
- case AT_PAP_TYPE_TICKLE: return "PAP_TICKLE";
- case AT_PAP_TYPE_CLOSE_CONN: return "PAP_CLOSE_CONN";
- case AT_PAP_TYPE_CLOSE_CONN_REPLY: return "PAP_CLOSE_CONN_REPLY";
- case AT_PAP_TYPE_SEND_STATUS: return "PAP_SEND_STATUS";
- case AT_PAP_TYPE_SEND_STS_REPLY: return "PAP_SEND_STS_REPLY";
- case AT_PAP_TYPE_READ_LW: return "PAP_READ_LW";
- }
- return "<Unknown>";
-}
-
-
-/*!
- * @function connectTimeout
- * @abstract Returns the connect timeout preference value.
- */
-static int connectTimeout()
-{
- CFPropertyListRef value;
- SInt32 connect_timeout = (7 * 24 * 60 * 60); /* Default timeout is one week... */
-
- value = CFPreferencesCopyValue(CFSTR("timeout"), CFSTR("com.apple.print.backends"),
- kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
- if (value != NULL)
- {
- if (CFGetTypeID(value) == CFNumberGetTypeID())
- CFNumberGetValue(value, kCFNumberSInt32Type, &connect_timeout);
-
- CFRelease(value);
- }
-
- return connect_timeout;
-}
-
-
-/*!
- * @function signalHandler
- * @abstract A signal handler so we can clean up the pap session before exiting.
- *
- * @param sigraised The signal raised
- *
- * @result Never returns
- */
-static void signalHandler(int sigraised)
-{
- _cupsLangPuts(stderr, _("ERROR: There was a timeout error while sending data to the printer\n"));
-
- papClose();
-
- _exit(1);
-}
diff --git a/backend/parallel.c b/backend/parallel.c
index 0df2f457..a475f0e9 100644
--- a/backend/parallel.c
+++ b/backend/parallel.c
@@ -1,9 +1,9 @@
/*
- * "$Id: parallel.c 8896 2009-11-20 01:27:57Z mike $"
+ * "$Id: parallel.c 9774 2011-05-12 06:15:14Z mike $"
*
- * Parallel port backend for the Common UNIX Printing System (CUPS).
+ * Parallel port backend for CUPS.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -85,7 +85,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
device_fd, /* Parallel device */
use_bc; /* Read back-channel data? */
int copies; /* Number of copies to print */
- size_t tbytes; /* Total number of bytes written */
+ ssize_t tbytes; /* Total number of bytes written */
struct termios opts; /* Parallel port options */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
@@ -124,7 +124,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
else if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
+ _("Usage: %s job-id user title copies options [file]"),
argv[0]);
return (CUPS_BACKEND_FAILED);
}
@@ -147,9 +147,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if ((print_fd = open(argv[6], O_RDONLY)) < 0)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open print file \"%s\": %s\n"),
- argv[6], strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
return (CUPS_BACKEND_FAILED);
}
@@ -217,9 +215,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -232,22 +230,20 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (errno == EBUSY)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 30 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer busy; will retry in 30 seconds."));
sleep(30);
}
else if (errno == ENXIO || errno == EIO || errno == ENOENT)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer not connected; will retry in 30 "
- "seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer not connected; will retry in 30 "
+ "seconds."));
sleep(30);
}
else
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open device file \"%s\": %s\n"),
- resource, strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open device file"));
return (CUPS_BACKEND_FAILED);
}
}
@@ -287,13 +283,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, side_cb);
if (print_fd != 0 && tbytes >= 0)
- _cupsLangPrintf(stderr,
-#ifdef HAVE_LONG_LONG
- _("INFO: Sent print file, %lld bytes...\n"),
-#else
- _("INFO: Sent print file, %ld bytes...\n"),
-#endif /* HAVE_LONG_LONG */
- CUPS_LLCAST tbytes);
+ _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
}
/*
@@ -305,7 +295,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (print_fd != 0)
close(print_fd);
- return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
+ return (CUPS_BACKEND_OK);
}
@@ -682,5 +672,5 @@ side_cb(int print_fd, /* I - Print file */
/*
- * End of "$Id: parallel.c 8896 2009-11-20 01:27:57Z mike $".
+ * End of "$Id: parallel.c 9774 2011-05-12 06:15:14Z mike $".
*/
diff --git a/backend/pseudo b/backend/pseudo
new file mode 100755
index 00000000..3a82a522
--- /dev/null
+++ b/backend/pseudo
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Psuedo-backend for CUPS testing purposes.
+#
+# Copyright 2011 by Apple Inc.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Apple Inc. and are protected by Federal copyright
+# law. Distribution and use rights are outlined in the file "LICENSE.txt"
+# which should have been included with this file. If this file is
+# file is missing or damaged, see the license at "http://www.cups.org/".
+#
+# This file is subject to the Apple OS-Developed Software exception.
+#
+
+if test $# = 0; then
+ echo 'direct pseudo:///deskjet "HP DeskJet" "HP DeskJet (pseudo)" "MFG:HP;MDL:DeskJet;CMD:PCL;" "Nowhere"'
+ echo 'direct pseudo:///laserjet "HP LaserJet" "HP LaserJet (pseudo)" "MFG:HP;MDL:LaserJet;CMD:PCL;" "Nowhere"'
+ exit 0
+fi
+
+cat $6 >/dev/null
+sleep 5
+exit 0
+
+#
+# End of "$Id$".
+#
diff --git a/backend/runloop.c b/backend/runloop.c
index 6cc1b7be..21cf45df 100644
--- a/backend/runloop.c
+++ b/backend/runloop.c
@@ -1,9 +1,9 @@
/*
- * "$Id: runloop.c 9258 2010-08-13 01:34:04Z mike $"
+ * "$Id: runloop.c 9820 2011-06-10 22:06:26Z mike $"
*
- * Common run loop APIs for CUPS.
+ * Common run loop APIs for CUPS backends.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 2006-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -18,6 +18,8 @@
*
* backendDrainOutput() - Drain pending print data to the device.
* backendRunLoop() - Read and write print and back-channel data.
+ * backendWaitLoop() - Wait for input from stdin while handling
+ * side-channel queries.
*/
/*
@@ -90,7 +92,7 @@ backendDrainOutput(int print_fd, /* I - Print file descriptor */
if (errno != EAGAIN || errno != EINTR)
{
- perror("ERROR: Unable to read print data");
+ _cupsLangPrintError("ERROR", _("Unable to read print data"));
return (-1);
}
@@ -119,8 +121,7 @@ backendDrainOutput(int print_fd, /* I - Print file descriptor */
if (errno != ENOSPC && errno != ENXIO && errno != EAGAIN &&
errno != EINTR && errno != ENOTTY)
{
- _cupsLangPrintf(stderr, _("ERROR: Unable to write print data: %s\n"),
- strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to write print data"));
return (-1);
}
}
@@ -142,14 +143,13 @@ backendDrainOutput(int print_fd, /* I - Print file descriptor */
ssize_t /* O - Total bytes on success, -1 on error */
backendRunLoop(
- int print_fd, /* I - Print file descriptor */
- int device_fd, /* I - Device file descriptor */
- int snmp_fd, /* I - SNMP socket or -1 if none */
- http_addr_t *addr, /* I - Address of device */
- int use_bc, /* I - Use back-channel? */
- int update_state, /* I - Update printer-state-reasons? */
- int (*side_cb)(int, int, int, http_addr_t *, int))
- /* I - Side-channel callback */
+ int print_fd, /* I - Print file descriptor */
+ int device_fd, /* I - Device file descriptor */
+ int snmp_fd, /* I - SNMP socket or -1 if none */
+ http_addr_t *addr, /* I - Address of device */
+ int use_bc, /* I - Use back-channel? */
+ int update_state, /* I - Update printer-state-reasons? */
+ _cups_sccb_t side_cb) /* I - Side-channel callback */
{
int nfds; /* Maximum file descriptor value + 1 */
fd_set input, /* Input set for reading */
@@ -249,13 +249,14 @@ backendRunLoop(
if (errno == ENXIO && offline != 1 && update_state)
{
fputs("STATE: +offline-report\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is currently offline.\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer is not currently connected."));
offline = 1;
}
else if (errno == EINTR && total_bytes == 0)
{
fputs("DEBUG: Received an interrupt before any bytes were "
- "written, aborting!\n", stderr);
+ "written, aborting.\n", stderr);
return (0);
}
@@ -289,7 +290,7 @@ backendRunLoop(
if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
{
fprintf(stderr,
- "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n",
+ "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n",
CUPS_LLCAST bc_bytes);
cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0);
}
@@ -318,7 +319,7 @@ backendRunLoop(
if (errno != EAGAIN || errno != EINTR)
{
- perror("ERROR: Unable to read print data");
+ _cupsLangPrintError("ERROR", _("Unable to read print data"));
return (-1);
}
@@ -357,7 +358,7 @@ backendRunLoop(
if (paperout != 1 && update_state)
{
fputs("STATE: +media-empty-warning\n", stderr);
- _cupsLangPuts(stderr, _("ERROR: Out of paper!\n"));
+ fputs("DEBUG: Out of paper\n", stderr);
paperout = 1;
}
}
@@ -366,14 +367,14 @@ backendRunLoop(
if (offline != 1 && update_state)
{
fputs("STATE: +offline-report\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is currently off-line.\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer is not currently connected."));
offline = 1;
}
}
else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
{
- fprintf(stderr, _("ERROR: Unable to write print data: %s\n"),
- strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to write print data"));
return (-1);
}
}
@@ -388,7 +389,7 @@ backendRunLoop(
if (offline && update_state)
{
fputs("STATE: -offline-report\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is now online.\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Printer is now connected."));
offline = 0;
}
@@ -422,5 +423,101 @@ backendRunLoop(
/*
- * End of "$Id: runloop.c 9258 2010-08-13 01:34:04Z mike $".
+ * 'backendWaitLoop()' - Wait for input from stdin while handling side-channel
+ * queries.
+ */
+
+int /* O - 1 if data is ready, 0 if not */
+backendWaitLoop(
+ int snmp_fd, /* I - SNMP socket or -1 if none */
+ http_addr_t *addr, /* I - Address of device */
+ int use_bc, /* I - Use back-channel? */
+ _cups_sccb_t side_cb) /* I - Side-channel callback */
+{
+ fd_set input; /* Input set for reading */
+ time_t curtime, /* Current time */
+ snmp_update = 0; /* Last SNMP status update */
+
+
+ fprintf(stderr, "DEBUG: backendWaitLoop(snmp_fd=%d, addr=%p, side_cb=%p)\n",
+ snmp_fd, addr, side_cb);
+
+ /*
+ * Now loop until we receive data from stdin...
+ */
+
+ for (;;)
+ {
+ /*
+ * Use select() to determine whether we have data to copy around...
+ */
+
+ FD_ZERO(&input);
+ FD_SET(0, &input);
+ if (side_cb)
+ FD_SET(CUPS_SC_FD, &input);
+
+ if (select(CUPS_SC_FD + 1, &input, NULL, NULL, NULL) < 0)
+ {
+ /*
+ * Pause printing to clear any pending errors...
+ */
+
+ if (errno == EINTR)
+ {
+ fputs("DEBUG: Received an interrupt before any bytes were "
+ "written, aborting.\n", stderr);
+ return (0);
+ }
+
+ sleep(1);
+ continue;
+ }
+
+ /*
+ * Check for input on stdin...
+ */
+
+ if (FD_ISSET(0, &input))
+ break;
+
+ /*
+ * Check if we have a side-channel request ready...
+ */
+
+ if (side_cb && FD_ISSET(CUPS_SC_FD, &input))
+ {
+ /*
+ * Do the side-channel request, then start back over in the select
+ * loop since it may have read from print_fd...
+ */
+
+ if ((*side_cb)(0, -1, snmp_fd, addr, use_bc))
+ side_cb = NULL;
+ continue;
+ }
+
+ /*
+ * Do SNMP updates periodically...
+ */
+
+ if (snmp_fd >= 0 && time(&curtime) >= snmp_update)
+ {
+ if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
+ snmp_update = INT_MAX;
+ else
+ snmp_update = curtime + 5;
+ }
+ }
+
+ /*
+ * Return with success...
+ */
+
+ return (1);
+}
+
+
+/*
+ * End of "$Id: runloop.c 9820 2011-06-10 22:06:26Z mike $".
*/
diff --git a/backend/scsi-irix.c b/backend/scsi-irix.c
deleted file mode 100644
index ed6c99f2..00000000
--- a/backend/scsi-irix.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * "$Id: scsi-irix.c 8173 2008-12-08 21:44:15Z mike $"
- *
- * IRIX SCSI printer support for the Common UNIX Printing System (CUPS).
- *
- * Copyright 2007 by Apple Inc.
- * Copyright 2003-2005 by Easy Software Products, all rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the
- * following conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use
- * of this software must display the following
- * acknowledgement:
- *
- * This product includes software developed by Easy
- * Software Products.
- *
- * 4. The name of Easy Software Products may not be used to
- * endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * Contents:
- *
- * list_devices() - List the available SCSI printer devices.
- * print_device() - Print a file to a SCSI device.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include <bstring.h> /* memcpy() and friends */
-#include <sys/dsreq.h> /* SCSI interface stuff */
-
-
-/*
- * 'list_devices()' - List the available SCSI printer devices.
- */
-
-void
-list_devices(void)
-{
- printf("direct scsi \"Unknown\" \"%s\"\n",
- _cupsLangString(cupsLangDefault(), _("SCSI Printer")));
-}
-
-
-/*
- * 'print_device()' - Print a file to a SCSI device.
- */
-
-int /* O - Print status */
-print_device(const char *resource, /* I - SCSI device */
- int fd, /* I - File to print */
- int copies) /* I - Number of copies to print */
-{
- int scsi_fd; /* SCSI file descriptor */
- char buffer[8192]; /* Data buffer */
- int bytes; /* Number of bytes */
- int try; /* Current try */
- dsreq_t scsi_req; /* SCSI request */
- char scsi_cmd[6]; /* SCSI command data */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
- * Make sure we have a valid resource name...
- */
-
- if (strncmp(resource, "/dev/scsi/", 10) != 0)
- {
- _cupsLangPrintf(stderr, _("ERROR: Bad SCSI device file \"%s\"!\n"),
- resource);
- return (CUPS_BACKEND_STOP);
- }
-
- /*
- * Open the SCSI device file...
- */
-
- fputs("STATE: +connecting-to-device\n", stderr);
-
- do
- {
- if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
- {
- if (getenv("CLASS") != NULL)
- {
- /*
- * If the CLASS environment variable is set, the job was submitted
- * to a class and not to a specific queue. In this case, we want
- * to abort immediately so that the job can be requeued on the next
- * available printer in the class.
- */
-
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
-
- /*
- * Sleep 5 seconds to keep the job from requeuing too rapidly...
- */
-
- sleep(5);
-
- return (1);
- }
-
- if (errno != EAGAIN && errno != EBUSY)
- {
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open device file \"%s\": %s\n"),
- resource, strerror(errno));
- return (CUPS_BACKEND_FAILED);
- }
- else
- {
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 30 seconds...\n"));
- sleep(30);
- }
- }
- }
- while (scsi_fd == -1);
-
- fputs("STATE: -connecting-to-device\n", stderr);
-
- /*
- * 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 (fd != 0)
- {
-#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 */
- }
-
- /*
- * Copy the print file to the device...
- */
-
- while (copies > 0)
- {
- if (fd != 0)
- lseek(fd, 0, SEEK_SET);
-
- while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
- {
- memset(&scsi_req, 0, sizeof(scsi_req));
-
- scsi_req.ds_flags = DSRQ_WRITE;
- scsi_req.ds_time = 60 * 1000;
- scsi_req.ds_cmdbuf = scsi_cmd;
- scsi_req.ds_cmdlen = 6;
- scsi_req.ds_databuf = buffer;
- scsi_req.ds_datalen = bytes;
-
- scsi_cmd[0] = 0x0a; /* Group 0 print command */
- scsi_cmd[1] = 0x00;
- scsi_cmd[2] = bytes / 65536;
- scsi_cmd[3] = bytes / 256;
- scsi_cmd[4] = bytes;
- scsi_cmd[5] = 0x00;
-
- for (try = 0; try < 10; try ++)
- if (ioctl(scsi_fd, DS_ENTER, &scsi_req) < 0 ||
- scsi_req.ds_status != 0)
- {
- _cupsLangPrintf(stderr,
- _("WARNING: SCSI command timed out (%d); "
- "retrying...\n"), scsi_req.ds_status);
- sleep(try + 1);
- }
- else
- break;
-
- if (try >= 10)
- {
- _cupsLangPrintf(stderr, _("ERROR: Unable to send print data (%d)\n"),
- scsi_req.ds_status);
- close(scsi_fd);
- return (CUPS_BACKEND_FAILED);
- }
- }
-
- copies --;
- }
-
- /*
- * Close the device and return...
- */
-
- close(fd);
-
- return (CUPS_BACKEND_OK);
-}
-
-
-/*
- * End of "$Id: scsi-irix.c 8173 2008-12-08 21:44:15Z mike $".
- */
diff --git a/backend/scsi-linux.c b/backend/scsi-linux.c
deleted file mode 100644
index 93861e92..00000000
--- a/backend/scsi-linux.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * "$Id: scsi-linux.c 8173 2008-12-08 21:44:15Z mike $"
- *
- * Linux SCSI printer support for the Common UNIX Printing System (CUPS).
- *
- * Copyright 2007 by Apple Inc.
- * Copyright 2003-2005 by Easy Software Products, all rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the
- * following conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use
- * of this software must display the following
- * acknowledgement:
- *
- * This product includes software developed by Easy
- * Software Products.
- *
- * 4. The name of Easy Software Products may not be used to
- * endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * Contents:
- *
- * list_devices() - List the available SCSI printer devices.
- * print_device() - Print a file to a SCSI device.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include <scsi/sg.h>
-#include <cups/i18n.h>
-
-
-/*
- * We currently only support the Linux 2.4 generic SCSI interface.
- */
-
-#ifndef SG_DXFER_TO_DEV
-/*
- * Dummy functions that do nothing on unsupported platforms...
- */
-void list_devices(void) {}
-int print_device(const char *resource, int fd, int copies) { return (1); }
-#else
-
-
-/*
- * 'list_devices()' - List the available SCSI printer devices.
- */
-
-void
-list_devices(void)
-{
- printf("direct scsi \"Unknown\" \"%s\"\n",
- _cupsLangString(cupsLangDefault(), _("SCSI Printer")));
-}
-
-
-/*
- * 'print_device()' - Print a file to a SCSI device.
- */
-
-int /* O - Print status */
-print_device(const char *resource, /* I - SCSI device */
- int fd, /* I - File to print */
- int copies) /* I - Number of copies to print */
-{
- int scsi_fd; /* SCSI file descriptor */
- char buffer[8192]; /* Data buffer */
- int bytes; /* Number of bytes */
- int try; /* Current try */
- sg_io_hdr_t scsi_req; /* SCSI request */
- unsigned char scsi_cmd[6], /* SCSI command data */
- scsi_sense[32]; /* SCSI sense data */
-# if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-# endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
- * Make sure we have a valid resource name...
- */
-
- if (strncmp(resource, "/dev/sg", 7) != 0)
- {
- _cupsLangPrintf(stderr, _("ERROR: Bad SCSI device file \"%s\"!\n"),
- resource);
- return (CUPS_BACKEND_STOP);
- }
-
- /*
- * Open the SCSI device file...
- */
-
- fputs("STATE: +connecting-to-device\n", stderr);
-
- do
- {
- if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
- {
- if (getenv("CLASS") != NULL)
- {
- /*
- * If the CLASS environment variable is set, the job was submitted
- * to a class and not to a specific queue. In this case, we want
- * to abort immediately so that the job can be requeued on the next
- * available printer in the class.
- */
-
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
-
- /*
- * Sleep 5 seconds to keep the job from requeuing too rapidly...
- */
-
- sleep(5);
-
- return (CUPS_BACKEND_FAILED);
- }
-
- if (errno != EAGAIN && errno != EBUSY)
- {
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open device file \"%s\": %s\n"),
- resource, strerror(errno));
- return (CUPS_BACKEND_FAILED);
- }
- else
- {
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 30 seconds...\n"));
- sleep(30);
- }
- }
- }
- while (scsi_fd == -1);
-
- fputs("STATE: -connecting-to-device\n", stderr);
-
- /*
- * 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 (fd != 0)
- {
-# 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 */
- }
-
- /*
- * Copy the print file to the device...
- */
-
- while (copies > 0)
- {
- if (fd != 0)
- lseek(fd, 0, SEEK_SET);
-
- while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
- {
- memset(&scsi_req, 0, sizeof(scsi_req));
-
- scsi_req.interface_id = 'S';
- scsi_req.dxfer_direction = SG_DXFER_TO_DEV;
- scsi_req.cmd_len = 6;
- scsi_req.mx_sb_len = sizeof(scsi_sense);
- scsi_req.iovec_count = 0;
- scsi_req.dxfer_len = bytes;
- scsi_req.dxferp = buffer;
- scsi_req.cmdp = scsi_cmd;
- scsi_req.sbp = scsi_sense;
- scsi_req.timeout = 60 * 1000;
-
- scsi_cmd[0] = 0x0a; /* Group 0 print command */
- scsi_cmd[1] = 0x00;
- scsi_cmd[2] = bytes / 65536;
- scsi_cmd[3] = bytes / 256;
- scsi_cmd[4] = bytes;
- scsi_cmd[5] = 0x00;
-
- for (try = 0; try < 10; try ++)
- if (ioctl(scsi_fd, SG_IO, &scsi_req) < 0 ||
- scsi_req.status != 0)
- {
- _cupsLangPrintf(stderr,
- _("WARNING: SCSI command timed out (%d); "
- "retrying...\n"), scsi_req.status);
- sleep(try + 1);
- }
- else
- break;
-
- if (try >= 10)
- {
- _cupsLangPrintf(stderr, _("ERROR: Unable to send print data (%d)\n"),
- scsi_req.status);
- close(scsi_fd);
- return (CUPS_BACKEND_FAILED);
- }
- }
-
- copies --;
- }
-
- /*
- * Close the device and return...
- */
-
- close(fd);
-
- return (CUPS_BACKEND_OK);
-}
-#endif /* !SG_DXFER_TO_DEV */
-
-
-/*
- * End of "$Id: scsi-linux.c 8173 2008-12-08 21:44:15Z mike $".
- */
diff --git a/backend/scsi.c b/backend/scsi.c
deleted file mode 100644
index 7040d4bd..00000000
--- a/backend/scsi.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * "$Id: scsi.c 7193 2008-01-07 23:01:40Z mike $"
- *
- * SCSI printer backend for the Common UNIX Printing System (CUPS).
- *
- * Copyright 2007 by Apple Inc.
- * Copyright 2003-2006 by Easy Software Products, all rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the
- * following conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use
- * of this software must display the following
- * acknowledgement:
- *
- * This product includes software developed by Easy
- * Software Products.
- *
- * 4. The name of Easy Software Products may not be used to
- * endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * Contents:
- *
- * main() - Send a file to the specified SCSI printer.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include <cups/backend.h>
-#include <cups/cups.h>
-#include <cups/i18n.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <cups/string.h>
-#include <cups/i18n.h>
-#include <signal.h>
-
-#ifdef WIN32
-# include <io.h>
-#else
-# include <unistd.h>
-# include <fcntl.h>
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif /* HAVE_SYS_IOCTL_H */
-#endif /* WIN32 */
-
-
-/*
- * Local functions...
- */
-
-void list_devices(void);
-int print_device(const char *resource, int fd, int copies);
-
-
-#if defined(__linux__) && defined(HAVE_SCSI_SG_H)
-# include "scsi-linux.c"
-#elif defined(__sgi)
-# include "scsi-irix.c"
-#else
-/*
- * Dummy functions that do nothing on unsupported platforms...
- */
-void list_devices(void) {}
-int print_device(const char *resource, int fd, int copies) { return (CUPS_BACKEND_FAILED); }
-#endif /* __linux && HAVE_SCSI_SG_H */
-
-
-/*
- * 'main()' - Send a file to the specified SCSI printer.
- *
- * Usage:
- *
- * printer-uri job-id user title copies options [file]
- */
-
-int /* O - Exit status */
-main(int argc, /* I - Number of command-line arguments (6 or 7) */
- char *argv[]) /* I - Command-line arguments */
-{
- char method[255], /* Method in URI */
- hostname[1024], /* Hostname */
- username[255], /* Username info (not used) */
- resource[1024], /* Resource info (device and options) */
- *options; /* Pointer to options */
- int port; /* Port number (not used) */
- int fp; /* Print file */
- int copies; /* Number of copies to print */
- int status; /* Exit status */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
- * 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 (CUPS_BACKEND_OK);
- }
- else if (argc < 6 || argc > 7)
- {
- _cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
- argv[0]);
- return (CUPS_BACKEND_FAILED);
- }
-
- /*
- * 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
- {
- /*
- * Try to open the print file...
- */
-
- if ((fp = open(argv[6], O_RDONLY)) < 0)
- {
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open print file \"%s\": %s\n"),
- argv[6], strerror(errno));
- return (CUPS_BACKEND_FAILED);
- }
-
- copies = atoi(argv[4]);
- }
-
- /*
- * Extract the device name and options from the URI...
- */
-
- httpSeparateURI(HTTP_URI_CODING_ALL, cupsBackendDeviceURI(argv),
- method, sizeof(method), username, sizeof(username),
- hostname, sizeof(hostname), &port,
- resource, sizeof(resource));
-
- /*
- * See if there are any options...
- */
-
- if ((options = strchr(resource, '?')) != NULL)
- {
- /*
- * Yup, terminate the device name string and move to the first
- * character of the options...
- */
-
- *options++ = '\0';
- }
-
- /*
- * Finally, send the print file...
- */
-
- status = print_device(resource, fp, copies);
-
- /*
- * Close input file and return...
- */
-
- if (fp != 0)
- close(fp);
-
- return (status);
-}
-
-
-/*
- * End of "$Id: scsi.c 7193 2008-01-07 23:01:40Z mike $".
- */
diff --git a/backend/serial.c b/backend/serial.c
index 73ad9a0b..4f350a1f 100644
--- a/backend/serial.c
+++ b/backend/serial.c
@@ -1,9 +1,9 @@
/*
- * "$Id: serial.c 9282 2010-08-31 15:56:40Z mike $"
+ * "$Id: serial.c 9793 2011-05-20 03:49:49Z mike $"
*
- * Serial port backend for the Common UNIX Printing System (CUPS).
+ * Serial port backend for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -26,6 +26,7 @@
*/
#include "backend-private.h"
+#include <stdio.h>
#ifdef __hpux
# include <sys/modem.h>
@@ -163,7 +164,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
else if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
+ _("Usage: %s job-id user title copies options [file]"),
argv[0]);
return (CUPS_BACKEND_FAILED);
}
@@ -186,9 +187,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if ((print_fd = open(argv[6], O_RDONLY)) < 0)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open print file \"%s\": %s\n"),
- argv[6], strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
return (CUPS_BACKEND_FAILED);
}
@@ -238,9 +237,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -253,15 +252,13 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (errno == EBUSY)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 30 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer busy; will retry in 30 seconds."));
sleep(30);
}
else
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open device file \"%s\": %s\n"),
- resource, strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open device file"));
return (CUPS_BACKEND_FAILED);
}
}
@@ -321,7 +318,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Process the option...
*/
- if (!strcasecmp(name, "baud"))
+ if (!_cups_strcasecmp(name, "baud"))
{
/*
* Set the baud rate...
@@ -378,13 +375,13 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
break;
# endif /* B230400 */
default :
- _cupsLangPrintf(stderr, _("WARNING: Unsupported baud rate %s!\n"),
- value);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Unsupported baud rate: %s"), value);
break;
}
#endif /* B19200 == 19200 */
}
- else if (!strcasecmp(name, "bits"))
+ else if (!_cups_strcasecmp(name, "bits"))
{
/*
* Set number of data bits...
@@ -405,25 +402,25 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
break;
}
}
- else if (!strcasecmp(name, "parity"))
+ else if (!_cups_strcasecmp(name, "parity"))
{
/*
* Set parity checking...
*/
- if (!strcasecmp(value, "even"))
+ if (!_cups_strcasecmp(value, "even"))
{
opts.c_cflag |= PARENB;
opts.c_cflag &= ~PARODD;
}
- else if (!strcasecmp(value, "odd"))
+ else if (!_cups_strcasecmp(value, "odd"))
{
opts.c_cflag |= PARENB;
opts.c_cflag |= PARODD;
}
- else if (!strcasecmp(value, "none"))
+ else if (!_cups_strcasecmp(value, "none"))
opts.c_cflag &= ~PARENB;
- else if (!strcasecmp(value, "space"))
+ else if (!_cups_strcasecmp(value, "space"))
{
/*
* Note: we only support space parity with 7 bits per character...
@@ -433,7 +430,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
opts.c_cflag |= CS8;
opts.c_cflag &= ~PARENB;
}
- else if (!strcasecmp(value, "mark"))
+ else if (!_cups_strcasecmp(value, "mark"))
{
/*
* Note: we only support mark parity with 7 bits per character
@@ -446,29 +443,29 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
opts.c_cflag |= CSTOPB;
}
}
- else if (!strcasecmp(name, "flow"))
+ else if (!_cups_strcasecmp(name, "flow"))
{
/*
* Set flow control...
*/
- if (!strcasecmp(value, "none"))
+ if (!_cups_strcasecmp(value, "none"))
{
opts.c_iflag &= ~(IXON | IXOFF);
opts.c_cflag &= ~CRTSCTS;
}
- else if (!strcasecmp(value, "soft"))
+ else if (!_cups_strcasecmp(value, "soft"))
{
opts.c_iflag |= IXON | IXOFF;
opts.c_cflag &= ~CRTSCTS;
}
- else if (!strcasecmp(value, "hard") ||
- !strcasecmp(value, "rtscts"))
+ else if (!_cups_strcasecmp(value, "hard") ||
+ !_cups_strcasecmp(value, "rtscts"))
{
opts.c_iflag &= ~(IXON | IXOFF);
opts.c_cflag |= CRTSCTS;
}
- else if (!strcasecmp(value, "dtrdsr"))
+ else if (!_cups_strcasecmp(value, "dtrdsr"))
{
opts.c_iflag &= ~(IXON | IXOFF);
opts.c_cflag &= ~CRTSCTS;
@@ -476,7 +473,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
dtrdsr = 1;
}
}
- else if (!strcasecmp(name, "stop"))
+ else if (!_cups_strcasecmp(name, "stop"))
{
switch (atoi(value))
{
@@ -594,7 +591,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
{
fprintf(stderr,
- "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n",
+ "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n",
CUPS_LLCAST bc_bytes);
cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0);
}
@@ -614,7 +611,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (errno != EAGAIN || errno != EINTR)
{
- _cupsLangPrintError(_("ERROR: Unable to read print data"));
+ perror("DEBUG: Unable to read print data");
tcsetattr(device_fd, TCSADRAIN, &origopts);
@@ -690,7 +687,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
{
- _cupsLangPrintError(_("ERROR: Unable to write print data"));
+ perror("DEBUG: Unable to write print data");
tcsetattr(device_fd, TCSADRAIN, &origopts);
@@ -725,7 +722,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (print_fd != 0)
close(print_fd);
- return (total_bytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
+ return (CUPS_BACKEND_OK);
}
@@ -1220,11 +1217,11 @@ list_devices(void)
/* Check if hidden... */
- hiddenVal = IORegistryEntrySearchCFProperty(serialService,
+ hiddenVal = IORegistryEntrySearchCFProperty(serialService,
kIOServicePlane,
CFSTR("HiddenPort"),
kCFAllocatorDefault,
- kIORegistryIterateRecursively |
+ kIORegistryIterateRecursively |
kIORegistryIterateParents);
if (hiddenVal)
CFRelease(hiddenVal); /* This interface should not be used */
@@ -1240,7 +1237,7 @@ list_devices(void)
sizeof(serialName),
kCFStringEncodingASCII);
CFRelease(serialNameAsCFString);
-
+
if (result)
{
bsdPathAsCFString =
@@ -1253,7 +1250,7 @@ list_devices(void)
sizeof(bsdPath),
kCFStringEncodingASCII);
CFRelease(bsdPathAsCFString);
-
+
if (result)
printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
bsdPath, serialName);
@@ -1326,5 +1323,5 @@ side_cb(int print_fd, /* I - Print file */
/*
- * End of "$Id: serial.c 9282 2010-08-31 15:56:40Z mike $".
+ * End of "$Id: serial.c 9793 2011-05-20 03:49:49Z mike $".
*/
diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c
index 8d0dcd76..4d8e52e6 100644
--- a/backend/snmp-supplies.c
+++ b/backend/snmp-supplies.c
@@ -1,5 +1,5 @@
/*
- * "$Id: snmp-supplies.c 9853 2011-07-06 20:27:31Z mike $"
+ * "$Id: snmp-supplies.c 9793 2011-05-20 03:49:49Z mike $"
*
* SNMP supplies functions for CUPS.
*
@@ -40,12 +40,10 @@
#define CUPS_DEVELOPER_EMPTY 2
#define CUPS_MARKER_SUPPLY_LOW 4
#define CUPS_MARKER_SUPPLY_EMPTY 8
-#define CUPS_MARKER_WASTE_ALMOST_FULL 16
-#define CUPS_MARKER_WASTE_FULL 32
-#define CUPS_OPC_NEAR_EOL 64
-#define CUPS_OPC_LIFE_OVER 128
-#define CUPS_TONER_LOW 256
-#define CUPS_TONER_EMPTY 512
+#define CUPS_OPC_NEAR_EOL 16
+#define CUPS_OPC_LIFE_OVER 32
+#define CUPS_TONER_LOW 64
+#define CUPS_TONER_EMPTY 128
/*
@@ -172,8 +170,6 @@ static const backend_state_t const supply_states[] =
{ CUPS_DEVELOPER_EMPTY, "developer-empty-warning" },
{ CUPS_MARKER_SUPPLY_LOW, "marker-supply-low-report" },
{ CUPS_MARKER_SUPPLY_EMPTY, "marker-supply-empty-warning" },
- { CUPS_MARKER_WASTE_ALMOST_FULL, "marker-waste-almost-full-report" },
- { CUPS_MARKER_WASTE_FULL, "marker-waste-full-warning" },
{ CUPS_OPC_NEAR_EOL, "opc-near-eol-report" },
{ CUPS_OPC_LIFE_OVER, "opc-life-over-warning" },
{ CUPS_TONER_LOW, "toner-low-report" },
@@ -251,10 +247,6 @@ backendSNMPSupplies(
break;
case CUPS_TC_wasteToner :
case CUPS_TC_wasteInk :
- if (percent <= 1)
- new_supply_state |= CUPS_MARKER_WASTE_FULL;
- else
- new_supply_state |= CUPS_MARKER_WASTE_ALMOST_FULL;
break;
case CUPS_TC_ink :
case CUPS_TC_inkCartridge :
@@ -479,7 +471,7 @@ backend_init_supplies(
if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL ||
((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
- ppdattr->value && strcasecmp(ppdattr->value, "true")))
+ ppdattr->value && _cups_strcasecmp(ppdattr->value, "true")))
{
ppdClose(ppd);
return;
@@ -989,5 +981,5 @@ utf16_to_utf8(
/*
- * End of "$Id: snmp-supplies.c 9853 2011-07-06 20:27:31Z mike $".
+ * End of "$Id: snmp-supplies.c 9793 2011-05-20 03:49:49Z mike $".
*/
diff --git a/backend/snmp.c b/backend/snmp.c
index 692a0414..de967c8b 100644
--- a/backend/snmp.c
+++ b/backend/snmp.c
@@ -1,9 +1,9 @@
/*
- * "$Id: snmp.c 8912 2009-12-08 02:13:42Z mike $"
+ * "$Id: snmp.c 9838 2011-06-19 04:28:25Z mike $"
*
- * SNMP discovery backend for the Common UNIX Printing System (CUPS).
+ * SNMP discovery backend for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 2006-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -141,13 +141,6 @@ typedef struct snmp_cache_s /**** SNMP scan cache ****/
/*
- * Private CUPS API to set the last error...
- */
-
-extern void _cupsSetError(ipp_status_t status, const char *message);
-
-
-/*
* Local functions...
*/
@@ -171,7 +164,7 @@ static void probe_device(snmp_cache_t *device);
static void read_snmp_conf(const char *address);
static void read_snmp_response(int fd);
static double run_time(void);
-static void scan_devices(int fd);
+static void scan_devices(int ipv4, int ipv6);
static int try_connect(http_addr_t *addr, const char *addrname,
int port);
static void update_cache(snmp_cache_t *device, const char *uri,
@@ -209,7 +202,8 @@ int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments (6 or 7) */
char *argv[]) /* I - Command-line arguments */
{
- int fd; /* SNMP socket */
+ int ipv4, /* SNMP IPv4 socket */
+ ipv6; /* SNMP IPv6 socket */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
@@ -221,7 +215,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (argc > 2)
{
- fputs(_("Usage: snmp [host-or-ip-address]\n"), stderr);
+ _cupsLangPuts(stderr, _("Usage: snmp [host-or-ip-address]"));
return (1);
}
@@ -252,9 +246,16 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Open the SNMP socket...
*/
- if ((fd = _cupsSNMPOpen(AF_INET)) < 0)
+ if ((ipv4 = _cupsSNMPOpen(AF_INET)) < 0)
return (1);
+#ifdef AF_INET6
+ if ((ipv6 = _cupsSNMPOpen(AF_INET6)) < 0)
+ return (1);
+#else
+ ipv6 = -1;
+#endif /* AF_INET6 */
+
/*
* Read the configuration file and any cache data...
*/
@@ -269,13 +270,15 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Scan for devices...
*/
- scan_devices(fd);
+ scan_devices(ipv4, ipv6);
/*
* Close, free, and return with no errors...
*/
- _cupsSNMPClose(fd);
+ _cupsSNMPClose(ipv4);
+ if (ipv6 >= 0)
+ _cupsSNMPClose(ipv6);
free_array(Addresses);
free_array(Communities);
@@ -464,7 +467,7 @@ static int /* O - Result of comparison */
compare_cache(snmp_cache_t *a, /* I - First cache entry */
snmp_cache_t *b) /* I - Second cache entry */
{
- return (strcasecmp(a->addrname, b->addrname));
+ return (_cups_strcasecmp(a->addrname, b->addrname));
}
@@ -506,7 +509,7 @@ fix_make_model(
* that printer driver detection works better...
*/
- if (!strncasecmp(old_make_model, "Hewlett-Packard", 15))
+ if (!_cups_strncasecmp(old_make_model, "Hewlett-Packard", 15))
{
/*
* Strip leading Hewlett-Packard and hp prefixes and replace
@@ -518,7 +521,7 @@ fix_make_model(
while (isspace(*mmptr & 255))
mmptr ++;
- if (!strncasecmp(mmptr, "hp", 2))
+ if (!_cups_strncasecmp(mmptr, "hp", 2))
{
mmptr += 2;
@@ -531,11 +534,11 @@ fix_make_model(
make_model[2] = ' ';
strlcpy(make_model + 3, mmptr, make_model_size - 3);
}
- else if (!strncasecmp(old_make_model, "deskjet", 7))
+ else if (!_cups_strncasecmp(old_make_model, "deskjet", 7))
snprintf(make_model, make_model_size, "HP DeskJet%s", old_make_model + 7);
- else if (!strncasecmp(old_make_model, "officejet", 9))
+ else if (!_cups_strncasecmp(old_make_model, "officejet", 9))
snprintf(make_model, make_model_size, "HP OfficeJet%s", old_make_model + 9);
- else if (!strncasecmp(old_make_model, "stylus_pro_", 11))
+ else if (!_cups_strncasecmp(old_make_model, "stylus_pro_", 11))
snprintf(make_model, make_model_size, "EPSON Stylus Pro %s",
old_make_model + 11);
else
@@ -715,7 +718,7 @@ probe_device(snmp_cache_t *device) /* I - Device */
#ifdef __APPLE__
/*
- * TODO: Try an mDNS query first, and then fallback on direct probes...
+ * If the printer supports Bonjour/mDNS, don't report it from the SNMP backend.
*/
if (!try_connect(&(device->address), device->addrname, 5353))
@@ -841,16 +844,16 @@ read_snmp_conf(const char *address) /* I - Single address to probe */
if (!value)
fprintf(stderr, "ERROR: Missing value on line %d of %s!\n", linenum,
filename);
- else if (!strcasecmp(line, "Address"))
+ else if (!_cups_strcasecmp(line, "Address"))
{
if (!address)
add_array(Addresses, value);
}
- else if (!strcasecmp(line, "Community"))
+ else if (!_cups_strcasecmp(line, "Community"))
add_array(Communities, value);
- else if (!strcasecmp(line, "DebugLevel"))
+ else if (!_cups_strcasecmp(line, "DebugLevel"))
DebugLevel = atoi(value);
- else if (!strcasecmp(line, "DeviceURI"))
+ else if (!_cups_strcasecmp(line, "DeviceURI"))
{
if (*value != '\"')
fprintf(stderr,
@@ -859,12 +862,12 @@ read_snmp_conf(const char *address) /* I - Single address to probe */
else
add_device_uri(value);
}
- else if (!strcasecmp(line, "HostNameLookups"))
- HostNameLookups = !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "true") ||
- !strcasecmp(value, "double");
- else if (!strcasecmp(line, "MaxRunTime"))
+ else if (!_cups_strcasecmp(line, "HostNameLookups"))
+ HostNameLookups = !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") ||
+ !_cups_strcasecmp(value, "true") ||
+ !_cups_strcasecmp(value, "double");
+ else if (!_cups_strcasecmp(line, "MaxRunTime"))
MaxRunTime = atoi(value);
else
fprintf(stderr, "ERROR: Unknown directive %s on line %d of %s!\n",
@@ -945,7 +948,7 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */
debug_printf("DEBUG: request-id=%d\n", packet.request_id);
debug_printf("DEBUG: error-status=%d\n", packet.error_status);
- if (packet.error_status)
+ if (packet.error_status && packet.request_id != DEVICE_TYPE)
return;
/*
@@ -1153,8 +1156,11 @@ run_time(void)
*/
static void
-scan_devices(int fd) /* I - SNMP socket */
+scan_devices(int ipv4, /* I - SNMP IPv4 socket */
+ int ipv6) /* I - SNMP IPv6 socket */
{
+ int fd, /* File descriptor for this address */
+ busy; /* Are we busy processing something? */
char *address, /* Current address */
*community; /* Current community */
fd_set input; /* Input set for select() */
@@ -1163,6 +1169,7 @@ scan_devices(int fd) /* I - SNMP socket */
http_addrlist_t *addrs, /* List of addresses */
*addr; /* Current address */
snmp_cache_t *device; /* Current device */
+ char temp[1024]; /* Temporary address string */
gettimeofday(&StartTime, NULL);
@@ -1181,7 +1188,6 @@ scan_devices(int fd) /* I - SNMP socket */
{
char ifname[255]; /* Interface name */
-
strlcpy(ifname, address + 4, sizeof(ifname));
if (ifname[0])
ifname[strlen(ifname) - 1] = '\0';
@@ -1189,7 +1195,7 @@ scan_devices(int fd) /* I - SNMP socket */
addrs = get_interface_addresses(ifname);
}
else
- addrs = httpAddrGetList(address, AF_INET, NULL);
+ addrs = httpAddrGetList(address, AF_UNSPEC, NULL);
if (!addrs)
{
@@ -1205,8 +1211,20 @@ scan_devices(int fd) /* I - SNMP socket */
community, address);
for (addr = addrs; addr; addr = addr->next)
+ {
+#ifdef AF_INET6
+ if (_httpAddrFamily(&(addr->addr)) == AF_INET6)
+ fd = ipv6;
+ else
+#endif /* AF_INET6 */
+ fd = ipv4;
+
+ debug_printf("DEBUG: Sending get request to %s...\n",
+ httpAddrString(&(addr->addr), temp, sizeof(temp)));
+
_cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community,
CUPS_ASN1_GET_REQUEST, DEVICE_TYPE, DeviceTypeOID);
+ }
}
httpAddrFreeList(addrs);
@@ -1225,17 +1243,33 @@ scan_devices(int fd) /* I - SNMP socket */
timeout.tv_sec = 2;
timeout.tv_usec = 0;
- FD_SET(fd, &input);
+ FD_SET(ipv4, &input);
+ if (ipv6 >= 0)
+ FD_SET(ipv6, &input);
+
+ fd = ipv4 > ipv6 ? ipv4 : ipv6;
if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
{
- fprintf(stderr, "ERROR: %.3f select() for %d failed: %s\n", run_time(),
- fd, strerror(errno));
+ fprintf(stderr, "ERROR: %.3f select() for %d/%d failed: %s\n", run_time(),
+ ipv4, ipv6, strerror(errno));
break;
}
- if (FD_ISSET(fd, &input))
- read_snmp_response(fd);
- else
+ busy = 0;
+
+ if (FD_ISSET(ipv4, &input))
+ {
+ read_snmp_response(ipv4);
+ busy = 1;
+ }
+
+ if (ipv6 >= 0 && FD_ISSET(ipv6, &input))
+ {
+ read_snmp_response(ipv6);
+ busy = 1;
+ }
+
+ if (!busy)
{
/*
* List devices with complete information...
@@ -1281,14 +1315,14 @@ try_connect(http_addr_t *addr, /* I - Socket address */
debug_printf("DEBUG: %.3f Trying %s://%s:%d...\n", run_time(),
port == 515 ? "lpd" : "socket", addrname, port);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ if ((fd = socket(_httpAddrFamily(addr), SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "ERROR: Unable to create socket: %s\n",
strerror(errno));
return (-1);
}
- addr->ipv4.sin_port = htons(port);
+ _httpAddrSetPort(addr, port);
alarm(1);
@@ -1337,5 +1371,5 @@ update_cache(snmp_cache_t *device, /* I - Device */
/*
- * End of "$Id: snmp.c 8912 2009-12-08 02:13:42Z mike $".
+ * End of "$Id: snmp.c 9838 2011-06-19 04:28:25Z mike $".
*/
diff --git a/backend/socket.c b/backend/socket.c
index b7fec786..5e28fc89 100644
--- a/backend/socket.c
+++ b/backend/socket.c
@@ -1,9 +1,9 @@
/*
- * "$Id: socket.c 9454 2011-01-10 08:02:55Z mike $"
+ * "$Id: socket.c 9793 2011-05-20 03:49:49Z mike $"
*
- * AppSocket backend for the Common UNIX Printing System (CUPS).
+ * AppSocket backend for CUPS.
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -77,7 +77,6 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
time_t current_time, /* Current time */
wait_time; /* Time to wait before shutting down socket */
#endif /* __APPLE__ */
- int recoverable; /* Recoverable error shown? */
int contimeout; /* Connection timeout */
int waiteof; /* Wait for end-of-file? */
int port; /* Port number */
@@ -92,7 +91,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
start_count, /* Page count via SNMP at start */
page_count, /* Page count via SNMP */
have_supplies; /* Printer supports supply levels? */
- ssize_t tbytes; /* Total number of bytes written */
+ ssize_t bytes = 0, /* Initial bytes read */
+ tbytes; /* Total number of bytes written */
+ char buffer[1024]; /* Initial print buffer */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
@@ -131,7 +132,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
else if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
+ _("Usage: %s job-id user title copies options [file]"),
argv[0]);
return (CUPS_BACKEND_FAILED);
}
@@ -154,9 +155,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if ((print_fd = open(argv[6], O_RDONLY)) < 0)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open print file \"%s\": %s\n"),
- argv[6], strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
return (CUPS_BACKEND_FAILED);
}
@@ -167,8 +166,14 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Extract the hostname and port number from the URI...
*/
- if ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
- return (CUPS_BACKEND_FAILED);
+ while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ return (CUPS_BACKEND_FAILED);
+ }
httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
username, sizeof(username), hostname, sizeof(hostname), &port,
@@ -232,16 +237,16 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Process the option...
*/
- if (!strcasecmp(name, "waiteof"))
+ if (!_cups_strcasecmp(name, "waiteof"))
{
/*
* Set the wait-for-eof value...
*/
- waiteof = !value[0] || !strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") || !strcasecmp(value, "true");
+ waiteof = !value[0] || !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
}
- else if (!strcasecmp(name, "contimeout"))
+ else if (!_cups_strcasecmp(name, "contimeout"))
{
/*
* Set the connection timeout...
@@ -254,26 +259,59 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
}
/*
- * Then try to connect to the remote host...
+ * Then try finding the remote host...
*/
- recoverable = 0;
- start_time = time(NULL);
+ start_time = time(NULL);
sprintf(portname, "%d", port);
fputs("STATE: +connecting-to-device\n", stderr);
fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
- if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
+ while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
+ {
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to locate printer \"%s\"."), hostname);
+ sleep(10);
+
+ if (getenv("CLASS") != NULL)
+ {
+ fputs("STATE: -connecting-to-device\n", stderr);
+ return (CUPS_BACKEND_STOP);
+ }
+ }
+
+ /*
+ * See if the printer supports SNMP...
+ */
+
+ if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0)
+ {
+ have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
+ &start_count, NULL);
+ }
+ else
+ have_supplies = start_count = 0;
+
+ /*
+ * Wait for data from the filter...
+ */
+
+ if (print_fd == 0)
{
- _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
- hostname);
- return (CUPS_BACKEND_STOP);
+ if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 1, backendNetworkSideCB))
+ return (CUPS_BACKEND_OK);
+ else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0)
+ return (CUPS_BACKEND_OK);
}
+ /*
+ * Connect to the printer...
+ */
+
fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
- _cupsLangPuts(stderr, _("INFO: Connecting to printer...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
for (delay = 5;;)
{
@@ -291,9 +329,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -304,21 +342,38 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
return (CUPS_BACKEND_FAILED);
}
+ fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));
+
if (error == ECONNREFUSED || error == EHOSTDOWN ||
error == EHOSTUNREACH)
{
if (contimeout && (time(NULL) - start_time) > contimeout)
{
- _cupsLangPuts(stderr, _("ERROR: Printer not responding!\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
return (CUPS_BACKEND_FAILED);
}
- recoverable = 1;
-
- _cupsLangPrintf(stderr,
- _("WARNING: recoverable: Network host \'%s\' is busy; "
- "will retry in %d seconds...\n"),
- hostname, delay);
+ switch (error)
+ {
+ case EHOSTDOWN :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer may not exist or "
+ "is unavailable at this time."));
+ break;
+
+ case EHOSTUNREACH :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer is unreachable at this "
+ "time."));
+ break;
+
+ case ECONNREFUSED :
+ default :
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("The printer is busy."));
+ break;
+ }
sleep(delay);
@@ -327,13 +382,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
}
else
{
- recoverable = 1;
-
- _cupsLangPrintf(stderr, "DEBUG: Connection error: %s\n",
- strerror(errno));
- _cupsLangPuts(stderr,
- _("ERROR: recoverable: Unable to connect to printer; "
- "will retry in 30 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("The printer is not responding."));
sleep(30);
}
}
@@ -341,43 +391,12 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
break;
}
- if (recoverable)
- {
- /*
- * If we've shown a recoverable error make sure the printer proxies have a
- * chance to see the recovered message. Not pretty but necessary for now...
- */
-
- fputs("INFO: recovered: \n", stderr);
- sleep(5);
- }
-
fputs("STATE: -connecting-to-device\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Connected to printer...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
-#ifdef AF_INET6
- if (addr->addr.addr.sa_family == AF_INET6)
- fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n",
- httpAddrString(&addr->addr, addrname, sizeof(addrname)),
- ntohs(addr->addr.ipv6.sin6_port));
- else
-#endif /* AF_INET6 */
- if (addr->addr.addr.sa_family == AF_INET)
- fprintf(stderr, "DEBUG: Connected to %s:%d (IPv4)...\n",
- httpAddrString(&addr->addr, addrname, sizeof(addrname)),
- ntohs(addr->addr.ipv4.sin_port));
-
- /*
- * See if the printer supports SNMP...
- */
-
- if ((snmp_fd = _cupsSNMPOpen(addr->addr.addr.sa_family)) >= 0)
- {
- have_supplies = !backendSNMPSupplies(snmp_fd, &(addr->addr), &start_count,
- NULL);
- }
- else
- have_supplies = start_count = 0;
+ fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
+ httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
+ _httpAddrPort(&(addr->addr)));
/*
* Print everything...
@@ -385,6 +404,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
tbytes = 0;
+ if (bytes > 0)
+ tbytes += write(device_fd, buffer, bytes);
+
while (copies > 0 && tbytes >= 0)
{
copies --;
@@ -395,17 +417,11 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
lseek(print_fd, 0, SEEK_SET);
}
- tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addr->addr), 1, 0,
- backendNetworkSideCB);
+ tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1,
+ 0, backendNetworkSideCB);
if (print_fd != 0 && tbytes >= 0)
- _cupsLangPrintf(stderr,
-#ifdef HAVE_LONG_LONG
- _("INFO: Sent print file, %lld bytes...\n"),
-#else
- _("INFO: Sent print file, %ld bytes...\n"),
-#endif /* HAVE_LONG_LONG */
- CUPS_LLCAST tbytes);
+ _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
}
#ifdef __APPLE__
@@ -425,8 +441,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Shutdown the socket and wait for the other end to finish...
*/
- _cupsLangPuts(stderr,
- _("INFO: Print file sent, waiting for printer to finish...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Waiting for printer to finish."));
shutdown(device_fd, 1);
@@ -437,8 +452,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
* Collect the final page count as needed...
*/
- if (have_supplies &&
- !backendSNMPSupplies(snmp_fd, &(addr->addr), &page_count, NULL) &&
+ if (have_supplies &&
+ !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &page_count, NULL) &&
page_count > start_count)
fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
@@ -457,10 +472,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if (print_fd != 0)
close(print_fd);
- if (tbytes >= 0)
- _cupsLangPuts(stderr, _("INFO: Ready to print.\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Ready to print."));
- return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
+ return (CUPS_BACKEND_OK);
}
@@ -496,7 +510,7 @@ wait_bc(int device_fd, /* I - Socket */
if ((bytes = read(device_fd, buffer, sizeof(buffer))) > 0)
{
- fprintf(stderr, "DEBUG: Received %d bytes of back-channel data!\n",
+ fprintf(stderr, "DEBUG: Received %d bytes of back-channel data\n",
(int)bytes);
cupsBackChannelWrite(buffer, bytes, 1.0);
}
@@ -509,5 +523,5 @@ wait_bc(int device_fd, /* I - Socket */
/*
- * End of "$Id: socket.c 9454 2011-01-10 08:02:55Z mike $".
+ * End of "$Id: socket.c 9793 2011-05-20 03:49:49Z mike $".
*/
diff --git a/backend/test1284.c b/backend/test1284.c
index 5c9b9996..1080c195 100644
--- a/backend/test1284.c
+++ b/backend/test1284.c
@@ -1,10 +1,9 @@
/*
- * "$Id: test1284.c 7465 2008-04-18 16:20:11Z mike $"
+ * "$Id: test1284.c 9042 2010-03-24 00:45:34Z mike $"
*
- * IEEE-1284 support functions test program for the Common UNIX Printing
- * System (CUPS).
+ * IEEE-1284 support functions test program for CUPS.
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -24,9 +23,7 @@
* Include necessary headers.
*/
-#include <cups/string.h>
-#include <stdlib.h>
-#include <errno.h>
+#include <cups/string-private.h>
#ifdef WIN32
# include <io.h>
#else
@@ -83,5 +80,5 @@ main(int argc, /* I - Number of command-line args */
/*
- * End of "$Id: test1284.c 7465 2008-04-18 16:20:11Z mike $".
+ * End of "$Id: test1284.c 9042 2010-03-24 00:45:34Z mike $".
*/
diff --git a/backend/testbackend.c b/backend/testbackend.c
index 42d060e0..682b8aa2 100644
--- a/backend/testbackend.c
+++ b/backend/testbackend.c
@@ -1,9 +1,9 @@
/*
- * "$Id: testbackend.c 8689 2009-05-27 18:32:43Z mike $"
+ * "$Id: testbackend.c 9042 2010-03-24 00:45:34Z mike $"
*
- * Backend test program for the Common UNIX Printing System (CUPS).
+ * Backend test program for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -26,14 +26,11 @@
* Include necessary headers.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <cups/string.h>
+#include <cups/string-private.h>
#include <cups/cups.h>
#include <cups/sidechannel.h>
#include <unistd.h>
#include <fcntl.h>
-#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
@@ -650,5 +647,5 @@ walk_cb(const char *oid, /* I - OID */
/*
- * End of "$Id: testbackend.c 8689 2009-05-27 18:32:43Z mike $".
+ * End of "$Id: testbackend.c 9042 2010-03-24 00:45:34Z mike $".
*/
diff --git a/backend/testsupplies.c b/backend/testsupplies.c
index ef42ed6a..827cdf6f 100644
--- a/backend/testsupplies.c
+++ b/backend/testsupplies.c
@@ -1,9 +1,9 @@
/*
- * "$Id: testsupplies.c 7502 2008-04-28 21:30:12Z mike $"
+ * "$Id: testsupplies.c 9771 2011-05-12 05:21:56Z mike $"
*
- * SNMP supplies test program for the Common UNIX Printing System (CUPS).
+ * SNMP supplies test program for CUPS.
*
- * Copyright 2008 by Apple Inc.
+ * Copyright 2008-2011 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -79,5 +79,5 @@ main(int argc, /* I - Number of command-line args */
/*
- * End of "$Id: testsupplies.c 7502 2008-04-28 21:30:12Z mike $".
+ * End of "$Id: testsupplies.c 9771 2011-05-12 05:21:56Z mike $".
*/
diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c
index a9484c76..f2cb3d36 100644
--- a/backend/usb-darwin.c
+++ b/backend/usb-darwin.c
@@ -1,7 +1,7 @@
/*
-* "$Id: usb-darwin.c 9319 2010-09-28 19:10:26Z mike $"
+* "$Id: usb-darwin.c 9793 2011-05-20 03:49:49Z mike $"
*
-* Copyright 2005-2010 Apple Inc. All rights reserved.
+* Copyright 2005-2011 Apple Inc. All rights reserved.
*
* IMPORTANT: This Apple software is supplied to you by Apple Computer,
* Inc. ("Apple") in consideration of your agreement to the following
@@ -43,33 +43,32 @@
*
* Contents:
*
-* list_devices() - List all USB devices.
-* print_device() - Print a file to a USB device.
-* sidechannel_thread() - Thread to handle side-channel requests.
-* read_thread() - Thread to read the backchannel data on.
-* list_device_cb() - list_device iterator callback.
-* find_device_cb() - print_device iterator callback.
-* status_timer_cb() - Status timer callback.
-* iterate_printers() - Iterate over all the printers.
-* device_added() - Device added notifier.
-* copy_deviceinfo() - Copy strings from the 1284 device ID.
-* release_deviceinfo() - Release deviceinfo strings.
-* load_classdriver() - Load a classdriver.
-* unload_classdriver() - Unload a classdriver.
-* load_printerdriver() - Load vendor's classdriver.
-* registry_open() - Open a connection to the printer.
-* registry_close() - Close the connection to the printer.
-* copy_deviceid() - Copy the 1284 device id string.
-* copy_devicestring() - Copy the 1284 device id string.
-* copy_value_for_key() - Copy value string associated with a key.
-* cfstr_create_trim() - Create CFString and trim whitespace characters.
-* parse_options() - Parse uri options.
-* setup_cfLanguage() - Create AppleLanguages array from LANG environment var.
-* run_legacy_backend() - Re-exec backend as ppc or i386.
-* sigterm_handler() - SIGTERM handler.
-* next_line() - Find the next line in a buffer.
-* parse_pserror() - Scan the backchannel data for postscript errors.
-* get_device_id() - Return IEEE-1284 device ID.
+ * list_devices() - List all USB devices.
+ * print_device() - Print a file to a USB device.
+ * read_thread() - Thread to read the backchannel data on.
+ * sidechannel_thread() - Handle side-channel requests.
+ * iterate_printers() - Iterate over all the printers.
+ * device_added() - Device added notifier.
+ * list_device_cb() - list_device iterator callback.
+ * find_device_cb() - print_device iterator callback.
+ * status_timer_cb() - Status timer callback.
+ * copy_deviceinfo() - Copy strings from the 1284 device ID.
+ * release_deviceinfo() - Release deviceinfo strings.
+ * load_classdriver() - Load a classdriver.
+ * unload_classdriver() - Unload a classdriver.
+ * load_printerdriver() - Load vendor's classdriver.
+ * registry_open() - Open a connection to the printer.
+ * registry_close() - Close the connection to the printer.
+ * copy_deviceid() - Copy the 1284 device id string.
+ * copy_devicestring() - Copy the 1284 device id string.
+ * copy_value_for_key() - Copy value string associated with a key.
+ * cfstr_create_trim() - Create CFString and trim whitespace characters.
+ * parse_options() - Parse URI options.
+ * sigterm_handler() - SIGTERM handler.
+ * next_line() - Find the next line in a buffer.
+ * parse_pserror() - Scan the backchannel data for postscript errors.
+ * soft_reset() - Send a soft reset to the device.
+ * get_device_id() - Return IEEE-1284 device ID.
*/
/*
@@ -89,11 +88,11 @@
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <mach/mach_time.h>
-#include <cups/debug.h>
+#include <cups/debug-private.h>
+#include <cups/file-private.h>
#include <cups/sidechannel.h>
-#include <cups/i18n.h>
+#include <cups/language-private.h>
#include "backend-private.h"
-
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
@@ -132,7 +131,7 @@ extern char **environ;
#define kUSBClassDriverProperty CFSTR("USB Printing Class")
-#define kUSBGenericTOPrinterClassDriver CFSTR("/System/Library/Printers/Libraries/USBGenericTOPrintingClass.plugin")
+#define kUSBGenericTOPrinterClassDriver CFSTR("/System/Library/Printers/Libraries/USBGenericPrintingClass.plugin")
#define kUSBPrinterClassDeviceNotOpen -9664 /*kPMInvalidIOMContext*/
@@ -270,11 +269,11 @@ static Boolean find_device_cb(void *refcon, io_service_t obj);
static Boolean list_device_cb(void *refcon, io_service_t obj);
static CFStringRef cfstr_create_trim(const char *cstr);
static CFStringRef copy_value_for_key(CFStringRef deviceID, CFStringRef *keys);
-static kern_return_t load_classdriver(CFStringRef driverPath, printer_interface_t intf, classdriver_t ***printerDriver);
+static kern_return_t load_classdriver(CFStringRef driverPath, printer_interface_t interface, classdriver_t ***printerDriver);
static kern_return_t load_printerdriver(CFStringRef *driverBundlePath);
-static kern_return_t registry_close();
+static kern_return_t registry_close(void);
static kern_return_t registry_open(CFStringRef *driverBundlePath);
-static kern_return_t unload_classdriver();
+static kern_return_t unload_classdriver(classdriver_t ***classdriver);
static OSStatus copy_deviceid(classdriver_t **printer, CFStringRef *deviceID);
static void *read_thread(void *reference);
static void *sidechannel_thread(void *reference);
@@ -286,7 +285,7 @@ static void iterate_printers(iterator_callback_t callBack, void *userdata);
static void parse_options(char *options, char *serial, int serial_size, UInt32 *location, Boolean *wait_eof);
static void release_deviceinfo(CFStringRef *make, CFStringRef *model, CFStringRef *serial);
static void setup_cfLanguage(void);
-static void soft_reset();
+static void soft_reset(void);
static void status_timer_cb(CFRunLoopTimerRef timer, void *info);
#if defined(__i386__) || defined(__x86_64__)
@@ -343,10 +342,12 @@ print_device(const char *uri, /* I - Device URI */
ssize_t total_bytes; /* Total bytes written */
UInt32 bytes; /* Bytes written */
struct timeval *timeout, /* Timeout pointer */
- stimeout; /* Timeout for select() */
+ tv; /* Time value */
struct timespec cond_timeout; /* pthread condition timeout */
+ (void)uri;
+
/*
* See if the side-channel descriptor is valid...
*/
@@ -373,7 +374,9 @@ print_device(const char *uri, /* I - Device URI */
if (!g.make || !g.model)
{
- _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n"));
+ fprintf(stderr, "DEBUG: Fatal USB error.\n");
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("There was an unrecoverable USB error."));
if (!g.make)
fputs("DEBUG: USB make string is NULL\n", stderr);
@@ -431,7 +434,8 @@ print_device(const char *uri, /* I - Device URI */
strlcpy(print_buffer, "USB class driver", sizeof(print_buffer));
fputs("STATE: +apple-missing-usbclassdriver-error\n", stderr);
- _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("There was an unrecoverable USB error."));
fprintf(stderr, "DEBUG: Could not load %s\n", print_buffer);
if (driverBundlePath)
@@ -449,8 +453,8 @@ print_device(const char *uri, /* I - Device URI */
countdown -= PRINTER_POLLING_INTERVAL;
if (countdown <= 0)
{
- _cupsLangPuts(stderr,
- _("INFO: Waiting for printer to become available...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Waiting for printer to become available."));
fprintf(stderr, "DEBUG: USB printer status: 0x%08x\n", (int)status);
countdown = SUBSEQUENT_LOG_INTERVAL; /* subsequent log entries, every 15 seconds */
}
@@ -496,7 +500,9 @@ print_device(const char *uri, /* I - Device URI */
if (pthread_create(&sidechannel_thread_id, NULL, sidechannel_thread, NULL))
{
- _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n"));
+ fprintf(stderr, "DEBUG: Fatal USB error.\n");
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("There was an unrecoverable USB error."));
fputs("DEBUG: Couldn't create side-channel thread\n", stderr);
registry_close();
return (CUPS_BACKEND_STOP);
@@ -515,7 +521,9 @@ print_device(const char *uri, /* I - Device URI */
if (pthread_create(&read_thread_id, NULL, read_thread, NULL))
{
- _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n"));
+ fprintf(stderr, "DEBUG: Fatal USB error.\n");
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("There was an unrecoverable USB error."));
fputs("DEBUG: Couldn't create read thread\n", stderr);
registry_close();
return (CUPS_BACKEND_STOP);
@@ -532,7 +540,7 @@ print_device(const char *uri, /* I - Device URI */
while (status == noErr && copies-- > 0)
{
- _cupsLangPuts(stderr, _("INFO: Sending print data...\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Sending data to printer."));
if (print_fd != STDIN_FILENO)
{
@@ -556,15 +564,15 @@ print_device(const char *uri, /* I - Device URI */
if (g.print_bytes)
{
- stimeout.tv_sec = 0;
- stimeout.tv_usec = 100000; /* 100ms */
- timeout = &stimeout;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000; /* 100ms */
+ timeout = &tv;
}
else if (g.drain_output)
{
- stimeout.tv_sec = 0;
- stimeout.tv_usec = 0;
- timeout = &stimeout;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ timeout = &tv;
}
else
timeout = NULL;
@@ -601,7 +609,8 @@ print_device(const char *uri, /* I - Device URI */
}
else if (errno != EAGAIN && errno != EINTR)
{
- _cupsLangPuts(stderr, _("ERROR: Unable to read print data\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to read print data."));
perror("DEBUG: select");
registry_close();
return (CUPS_BACKEND_FAILED);
@@ -644,7 +653,8 @@ print_device(const char *uri, /* I - Device URI */
if (errno != EAGAIN && errno != EINTR)
{
- _cupsLangPuts(stderr, _("ERROR: Unable to read print data\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to read print data."));
perror("DEBUG: read");
registry_close();
return (CUPS_BACKEND_FAILED);
@@ -715,13 +725,14 @@ print_device(const char *uri, /* I - Device URI */
iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0);
}
- if (iostatus || bytes < 0)
+ if (iostatus)
{
/*
* Write error - bail if we don't see an error we can retry...
*/
- _cupsLangPuts(stderr, _("ERROR: Unable to send print data\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to send data to printer."));
fprintf(stderr, "DEBUG: USB class driver WritePipe returned %x\n",
iostatus);
@@ -755,7 +766,7 @@ print_device(const char *uri, /* I - Device URI */
/*
* Re-enable the SIGTERM handler so pthread_kill() will work...
*/
-
+
struct sigaction action; /* POSIX signal action */
memset(&action, 0, sizeof(action));
@@ -780,17 +791,22 @@ print_device(const char *uri, /* I - Device URI */
g.sidechannel_thread_stop = 1;
pthread_mutex_lock(&g.sidechannel_thread_mutex);
+
if (!g.sidechannel_thread_done)
{
- /*
- * Wait for the side-channel thread to exit...
- */
+ gettimeofday(&tv, NULL);
+ cond_timeout.tv_sec = tv.tv_sec + WAIT_SIDE_DELAY;
+ cond_timeout.tv_nsec = tv.tv_usec * 1000;
- cond_timeout.tv_sec = time(NULL) + WAIT_SIDE_DELAY;
- cond_timeout.tv_nsec = 0;
- if (pthread_cond_timedwait(&g.sidechannel_thread_cond,
- &g.sidechannel_thread_mutex,
- &cond_timeout) != 0)
+ while (!g.sidechannel_thread_done)
+ {
+ if (pthread_cond_timedwait(&g.sidechannel_thread_cond,
+ &g.sidechannel_thread_mutex,
+ &cond_timeout) != 0)
+ break;
+ }
+
+ if (!g.sidechannel_thread_done)
{
/*
* Force the side-channel thread to exit...
@@ -800,6 +816,7 @@ print_device(const char *uri, /* I - Device URI */
pthread_kill(sidechannel_thread_id, SIGTERM);
}
}
+
pthread_mutex_unlock(&g.sidechannel_thread_mutex);
pthread_join(sidechannel_thread_id, NULL);
@@ -826,11 +843,18 @@ print_device(const char *uri, /* I - Device URI */
if (!g.read_thread_done)
{
- cond_timeout.tv_sec = time(NULL) + WAIT_EOF_DELAY;
- cond_timeout.tv_nsec = 0;
+ gettimeofday(&tv, NULL);
+ cond_timeout.tv_sec = tv.tv_sec + WAIT_EOF_DELAY;
+ cond_timeout.tv_nsec = tv.tv_usec * 1000;
+
+ while (!g.read_thread_done)
+ {
+ if (pthread_cond_timedwait(&g.read_thread_cond, &g.read_thread_mutex,
+ &cond_timeout) != 0)
+ break;
+ }
- if (pthread_cond_timedwait(&g.read_thread_cond, &g.read_thread_mutex,
- &cond_timeout) != 0)
+ if (!g.read_thread_done)
{
/*
* Force the read thread to exit...
@@ -841,6 +865,7 @@ print_device(const char *uri, /* I - Device URI */
pthread_kill(read_thread_id, SIGTERM);
}
}
+
pthread_mutex_unlock(&g.read_thread_mutex);
pthread_join(read_thread_id, NULL); /* wait for the read thread to return */
@@ -886,6 +911,9 @@ static void *read_thread(void *reference)
uint64_t start,
delay;
+
+ (void)reference;
+
/* Calculate what 250 milliSeconds are in mach absolute time...
*/
mach_timebase_info(&timeBaseInfo);
@@ -961,6 +989,8 @@ sidechannel_thread(void *reference)
int datalen; /* Request/response data size */
+ (void)reference;
+
do
{
datalen = sizeof(data);
@@ -1152,6 +1182,9 @@ static Boolean list_device_cb(void *refcon,
{
Boolean keepRunning = (obj != 0x0);
+
+ (void)refcon;
+
if (keepRunning)
{
CFStringRef deviceIDString = NULL;
@@ -1278,7 +1311,7 @@ static Boolean find_device_cb(void *refcon,
if (!keepLooking && g.status_timer != NULL)
{
fputs("STATE: -offline-report\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is now online.\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Printer is now online."));
CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), g.status_timer, kCFRunLoopDefaultMode);
CFRelease(g.status_timer);
g.status_timer = NULL;
@@ -1295,8 +1328,11 @@ static Boolean find_device_cb(void *refcon,
static void status_timer_cb(CFRunLoopTimerRef timer,
void *info)
{
+ (void)timer;
+ (void)info;
+
fputs("STATE: +offline-report\n", stderr);
- _cupsLangPuts(stderr, _("INFO: Printer is offline.\n"));
+ _cupsLangPrintFilter(stderr, "INFO", _("Printer is offline."));
if (getenv("CLASS") != NULL)
{
@@ -1375,14 +1411,13 @@ static void release_deviceinfo(CFStringRef *make,
*/
static kern_return_t load_classdriver(CFStringRef driverPath,
- printer_interface_t intf,
+ printer_interface_t interface,
classdriver_t ***printerDriver)
{
kern_return_t kr = kUSBPrinterClassDeviceNotOpen;
classdriver_t **driver = NULL;
CFStringRef bundle = driverPath ? driverPath : kUSBGenericTOPrinterClassDriver;
char bundlestr[1024]; /* Bundle path */
- struct stat bundleinfo; /* File information for bundle */
CFURLRef url; /* URL for driver */
CFPlugInRef plugin = NULL; /* Plug-in address */
@@ -1393,21 +1428,14 @@ static kern_return_t load_classdriver(CFStringRef driverPath,
* Validate permissions for the class driver...
*/
- if (stat(bundlestr, &bundleinfo))
- {
- fprintf(stderr, "DEBUG: Unable to load class driver \"%s\": %s\n",
- bundlestr, strerror(errno));
- if (errno == ENOENT)
- return (load_classdriver(NULL, intf, printerDriver));
- else
- return (kr);
- }
- else if (bundleinfo.st_mode & S_IWOTH)
- {
- fprintf(stderr, "DEBUG: Unable to load class driver \"%s\": insecure file "
- "permissions (0%o)\n", bundlestr, bundleinfo.st_mode);
+ _cups_fc_result_t result = _cupsFileCheck(bundlestr,
+ _CUPS_FILE_CHECK_DIRECTORY, 1,
+ _cupsFileCheckFilter, NULL);
+
+ if (result && driverPath)
+ return (load_classdriver(NULL, interface, printerDriver));
+ else if (result)
return (kr);
- }
/*
* Try loading the class driver...
@@ -1437,15 +1465,15 @@ static kern_return_t load_classdriver(CFStringRef driverPath,
{
classdriver_t **genericDriver = NULL;
if (driverPath != NULL && CFStringCompare(driverPath, kUSBGenericTOPrinterClassDriver, 0) != kCFCompareEqualTo)
- kr = load_classdriver(NULL, intf, &genericDriver);
+ kr = load_classdriver(NULL, interface, &genericDriver);
if (kr == kIOReturnSuccess)
{
- (*driver)->interface = intf;
+ (*driver)->interface = interface;
(*driver)->Initialize(driver, genericDriver);
(*driver)->plugin = plugin;
- (*driver)->interface = intf;
+ (*driver)->interface = interface;
*printerDriver = driver;
}
}
@@ -1488,20 +1516,20 @@ static kern_return_t load_printerdriver(CFStringRef *driverBundlePath)
IOCFPlugInInterface **iodev = NULL;
SInt32 score;
kern_return_t kr;
- printer_interface_t intf;
+ printer_interface_t interface;
HRESULT res;
kr = IOCreatePlugInInterfaceForService(g.printer_obj, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score);
if (kr == kIOReturnSuccess)
{
- if ((res = (*iodev)->QueryInterface(iodev, USB_INTERFACE_KIND, (LPVOID *) &intf)) == noErr)
+ if ((res = (*iodev)->QueryInterface(iodev, USB_INTERFACE_KIND, (LPVOID *) &interface)) == noErr)
{
*driverBundlePath = IORegistryEntryCreateCFProperty(g.printer_obj, kUSBClassDriverProperty, NULL, kNilOptions);
- kr = load_classdriver(*driverBundlePath, intf, &g.classdriver);
+ kr = load_classdriver(*driverBundlePath, interface, &g.classdriver);
if (kr != kIOReturnSuccess)
- (*intf)->Release(intf);
+ (*interface)->Release(interface);
}
IODestroyPlugInInterface(iodev);
}
@@ -1552,7 +1580,7 @@ static kern_return_t registry_open(CFStringRef *driverBundlePath)
* 'registry_close()' - Close the connection to the printer.
*/
-static kern_return_t registry_close()
+static kern_return_t registry_close(void)
{
if (g.classdriver != NULL)
(*g.classdriver)->Close(g.classdriver);
@@ -1659,7 +1687,7 @@ static void copy_devicestring(io_service_t usbInterface,
IOCFPlugInInterface **iodev = NULL;
SInt32 score;
kern_return_t kr;
- printer_interface_t intf;
+ printer_interface_t interface;
HRESULT res;
classdriver_t **klassDriver = NULL;
CFStringRef driverBundlePath;
@@ -1670,19 +1698,19 @@ static void copy_devicestring(io_service_t usbInterface,
&iodev, &score)) == kIOReturnSuccess)
{
if ((res = (*iodev)->QueryInterface(iodev, USB_INTERFACE_KIND, (LPVOID *)
- &intf)) == noErr)
+ &interface)) == noErr)
{
- (*intf)->GetLocationID(intf, deviceLocation);
- (*intf)->GetInterfaceNumber(intf, interfaceNumber);
+ (*interface)->GetLocationID(interface, deviceLocation);
+ (*interface)->GetInterfaceNumber(interface, interfaceNumber);
driverBundlePath = IORegistryEntryCreateCFProperty(usbInterface,
kUSBClassDriverProperty,
NULL, kNilOptions);
- kr = load_classdriver(driverBundlePath, intf, &klassDriver);
+ kr = load_classdriver(driverBundlePath, interface, &klassDriver);
if (kr != kIOReturnSuccess && driverBundlePath != NULL)
- kr = load_classdriver(NULL, intf, &klassDriver);
+ kr = load_classdriver(NULL, interface, &klassDriver);
if (kr == kIOReturnSuccess && klassDriver != NULL)
kr = copy_deviceid(klassDriver, deviceID);
@@ -1692,7 +1720,7 @@ static void copy_devicestring(io_service_t usbInterface,
if (driverBundlePath != NULL)
CFRelease(driverBundlePath);
- /* (*intf)->Release(intf); */
+ /* (*interface)->Release(interface); */
}
IODestroyPlugInInterface(iodev);
}
@@ -1831,24 +1859,24 @@ static void parse_options(char *options,
* Process the option...
*/
- if (!strcasecmp(name, "waiteof"))
+ if (!_cups_strcasecmp(name, "waiteof"))
{
- if (!strcasecmp(value, "on") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "true"))
+ if (!_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "yes") ||
+ !_cups_strcasecmp(value, "true"))
*wait_eof = true;
- else if (!strcasecmp(value, "off") ||
- !strcasecmp(value, "no") ||
- !strcasecmp(value, "false"))
+ else if (!_cups_strcasecmp(value, "off") ||
+ !_cups_strcasecmp(value, "no") ||
+ !_cups_strcasecmp(value, "false"))
*wait_eof = false;
else
- _cupsLangPrintf(stderr,
- _("WARNING: Boolean expected for waiteof option "
- "\"%s\"\n"), value);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Boolean expected for waiteof option \"%s\"."),
+ value);
}
- else if (!strcasecmp(name, "serial"))
+ else if (!_cups_strcasecmp(name, "serial"))
strlcpy(serial, value, serial_size);
- else if (!strcasecmp(name, "location") && location)
+ else if (!_cups_strcasecmp(name, "location") && location)
*location = strtol(value, NULL, 16);
}
}
@@ -1981,7 +2009,8 @@ static void run_legacy_backend(int argc,
# else
perror("DEBUG: Unable to set binary preference to ppc");
# endif /* __x86_64__ */
- _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to use legacy USB class driver."));
exit(CUPS_BACKEND_STOP);
}
}
@@ -2004,7 +2033,8 @@ static void run_legacy_backend(int argc,
{
fprintf(stderr, "DEBUG: Unable to exec %s: %s\n", usbpath,
strerror(err));
- _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to use legacy USB class driver."));
exit(CUPS_BACKEND_STOP);
}
@@ -2145,9 +2175,9 @@ static void parse_pserror(char *sockBuffer,
pCommentEnd += 3; /* Skip past "]%%" */
*pCommentEnd = '\0'; /* There's always room for the nul */
- if (strncasecmp(pCommentBegin, "%%[ Error:", 10) == 0)
+ if (_cups_strncasecmp(pCommentBegin, "%%[ Error:", 10) == 0)
logLevel = "DEBUG";
- else if (strncasecmp(pCommentBegin, "%%[ Flushing", 12) == 0)
+ else if (_cups_strncasecmp(pCommentBegin, "%%[ Flushing", 12) == 0)
logLevel = "DEBUG";
else
logLevel = "INFO";
@@ -2174,10 +2204,10 @@ static void parse_pserror(char *sockBuffer,
* 'soft_reset()' - Send a soft reset to the device.
*/
-static void soft_reset()
+static void soft_reset(void)
{
fd_set input_set; /* Input set for select() */
- struct timeval stimeout; /* Timeout for select() */
+ struct timeval tv; /* Time value */
char buffer[2048]; /* Buffer */
struct timespec cond_timeout; /* pthread condition timeout */
@@ -2190,10 +2220,17 @@ static void soft_reset()
{
(*g.classdriver)->Abort(g.classdriver);
- cond_timeout.tv_sec = time(NULL) + 1;
- cond_timeout.tv_nsec = 0;
+ gettimeofday(&tv, NULL);
+ cond_timeout.tv_sec = tv.tv_sec + 1;
+ cond_timeout.tv_nsec = tv.tv_usec * 1000;
- pthread_cond_timedwait(&g.readwrite_lock_cond, &g.readwrite_lock_mutex, &cond_timeout);
+ while (g.readwrite_lock)
+ {
+ if (pthread_cond_timedwait(&g.readwrite_lock_cond,
+ &g.readwrite_lock_mutex,
+ &cond_timeout) != 0)
+ break;
+ }
}
g.readwrite_lock = 1;
@@ -2208,10 +2245,10 @@ static void soft_reset()
FD_ZERO(&input_set);
FD_SET(g.print_fd, &input_set);
- stimeout.tv_sec = 0;
- stimeout.tv_usec = 0;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
- while (select(g.print_fd+1, &input_set, NULL, NULL, &stimeout) > 0)
+ while (select(g.print_fd+1, &input_set, NULL, NULL, &tv) > 0)
if (read(g.print_fd, buffer, sizeof(buffer)) <= 0)
break;
@@ -2256,5 +2293,5 @@ static void get_device_id(cups_sc_status_t *status,
/*
- * End of "$Id: usb-darwin.c 9319 2010-09-28 19:10:26Z mike $".
+ * End of "$Id: usb-darwin.c 9793 2011-05-20 03:49:49Z mike $".
*/
diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c
index c3f0534e..f4341521 100644
--- a/backend/usb-libusb.c
+++ b/backend/usb-libusb.c
@@ -1,5 +1,5 @@
/*
- * "$Id: usb-libusb.c 9582 2011-03-04 19:28:38Z mike $"
+ * "$Id: usb-libusb.c 9831 2011-06-14 23:03:29Z mike $"
*
* Libusb interface code for CUPS.
*
@@ -31,6 +31,7 @@
#include <usb.h>
#include <poll.h>
+#include <cups/cups-private.h>
/*
@@ -113,8 +114,8 @@ print_device(const char *uri, /* I - Device URI */
while ((printer = find_device(print_cb, uri)) == NULL)
{
- _cupsLangPuts(stderr,
- _("INFO: Waiting for printer to become available...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Waiting for printer to become available."));
sleep(5);
}
@@ -174,9 +175,8 @@ print_device(const char *uri, /* I - Device URI */
if (usb_bulk_write(printer->handle, printer->write_endp, buffer,
bytes, 3600000) < 0)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to write %d bytes to printer!\n"),
- (int)bytes);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to send data to printer."));
tbytes = -1;
break;
}
@@ -505,6 +505,7 @@ make_device_uri(
*mdl, /* Model */
*des, /* Description */
*sern; /* Serial number */
+ size_t mfglen; /* Length of manufacturer string */
char tempmfg[256], /* Temporary manufacturer string */
tempsern[256], /* Temporary serial number string */
*tempptr; /* Pointer into temp string */
@@ -514,7 +515,7 @@ make_device_uri(
* Get the make, model, and serial numbers...
*/
- num_values = _ppdGet1284Values(device_id, &values);
+ num_values = _cupsGet1284Values(device_id, &values);
if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
@@ -558,9 +559,9 @@ make_device_uri(
if (mfg)
{
- if (!strcasecmp(mfg, "Hewlett-Packard"))
+ if (!_cups_strcasecmp(mfg, "Hewlett-Packard"))
mfg = "HP";
- else if (!strcasecmp(mfg, "Lexmark International"))
+ else if (!_cups_strcasecmp(mfg, "Lexmark International"))
mfg = "Lexmark";
}
else
@@ -584,6 +585,16 @@ make_device_uri(
mfg = tempmfg;
}
+ mfglen = strlen(mfg);
+
+ if (!strncasecmp(mdl, mfg, mfglen) && _cups_isspace(mdl[mfglen]))
+ {
+ mdl += mfglen + 1;
+
+ while (_cups_isspace(*mdl))
+ mdl ++;
+ }
+
/*
* Generate the device URI from the manufacturer, model, serial number,
* and interface number...
@@ -736,7 +747,87 @@ print_cb(usb_printer_t *printer, /* I - Printer */
const char *device_id, /* I - IEEE-1284 device ID */
const void *data) /* I - User data (make, model, S/N) */
{
- return (!strcmp((char *)data, device_uri));
+ char requested_uri[1024], /* Requested URI */
+ *requested_ptr, /* Pointer into requested URI */
+ detected_uri[1024], /* Detected URI */
+ *detected_ptr; /* Pointer into detected URI */
+
+
+ /*
+ * If we have an exact match, stop now...
+ */
+
+ if (!strcmp((char *)data, device_uri))
+ return (1);
+
+ /*
+ * Work on copies of the URIs...
+ */
+
+ strlcpy(requested_uri, (char *)data, sizeof(requested_uri));
+ strlcpy(detected_uri, device_uri, sizeof(detected_uri));
+
+ /*
+ * libusb-discovered URIs can have an "interface" specification and this
+ * never happens for usblp-discovered URIs, so remove the "interface"
+ * specification from the URI which we are checking currently. This way a
+ * queue for a usblp-discovered printer can now be accessed via libusb.
+ *
+ * Similarly, strip "?serial=NNN...NNN" as needed.
+ */
+
+ if ((requested_ptr = strstr(requested_uri, "?interface=")) == NULL)
+ requested_ptr = strstr(requested_uri, "&interface=");
+ if ((detected_ptr = strstr(detected_uri, "?interface=")) == NULL)
+ detected_ptr = strstr(detected_uri, "&interface=");
+
+ if (!requested_ptr && detected_ptr)
+ {
+ /*
+ * Strip "[?&]interface=nnn" from the detected printer.
+ */
+
+ *detected_ptr = '\0';
+ }
+ else if (requested_ptr && !detected_ptr)
+ {
+ /*
+ * Strip "[?&]interface=nnn" from the requested printer.
+ */
+
+ *requested_ptr = '\0';
+ }
+
+ if ((requested_ptr = strstr(requested_uri, "?serial=?")) != NULL)
+ {
+ /*
+ * Strip "?serial=?" from the requested printer. This is a special
+ * case, as "?serial=?" means no serial number and not the serial
+ * number '?'. This is not covered by the checks below...
+ */
+
+ *requested_ptr = '\0';
+ }
+
+ if ((requested_ptr = strstr(requested_uri, "?serial=")) == NULL &&
+ (detected_ptr = strstr(detected_uri, "?serial=")) != NULL)
+ {
+ /*
+ * Strip "?serial=nnn" from the detected printer.
+ */
+
+ *detected_ptr = '\0';
+ }
+ else if (requested_ptr && !detected_ptr)
+ {
+ /*
+ * Strip "?serial=nnn" from the requested printer.
+ */
+
+ *requested_ptr = '\0';
+ }
+
+ return (!strcmp(requested_uri, detected_uri));
}
@@ -777,9 +868,8 @@ side_cb(usb_printer_t *printer, /* I - Printer */
while (usb_bulk_write(printer->handle, printer->write_endp, buffer,
bytes, 5000) < 0)
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to write %d bytes to printer!\n"),
- (int)bytes);
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("Unable to send data to printer."));
tbytes = -1;
break;
}
@@ -830,6 +920,6 @@ side_cb(usb_printer_t *printer, /* I - Printer */
/*
- * End of "$Id: usb-libusb.c 9582 2011-03-04 19:28:38Z mike $".
+ * End of "$Id: usb-libusb.c 9831 2011-06-14 23:03:29Z mike $".
*/
diff --git a/backend/usb-unix.c b/backend/usb-unix.c
index 4e36d77b..1c280332 100644
--- a/backend/usb-unix.c
+++ b/backend/usb-unix.c
@@ -1,11 +1,11 @@
/*
- * "$Id: usb-unix.c 8912 2009-12-08 02:13:42Z mike $"
+ * "$Id: usb-unix.c 9793 2011-05-20 03:49:49Z mike $"
*
- * USB port backend for the Common UNIX Printing System (CUPS).
+ * USB port backend for CUPS.
*
* This file is included from "usb.c" when compiled on UNIX/Linux.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -56,7 +56,7 @@ print_device(const char *uri, /* I - Device URI */
{
int use_bc; /* Use backchannel path? */
int device_fd; /* USB device */
- size_t tbytes; /* Total number of bytes written */
+ ssize_t tbytes; /* Total number of bytes written */
struct termios opts; /* Parallel port options */
@@ -96,10 +96,10 @@ print_device(const char *uri, /* I - Device URI */
* a read request...
*/
- use_bc = strcasecmp(hostname, "Brother") &&
- strcasecmp(hostname, "Canon") &&
- strncasecmp(hostname, "Konica", 6) &&
- strncasecmp(hostname, "Minolta", 7);
+ use_bc = _cups_strcasecmp(hostname, "Brother") &&
+ _cups_strcasecmp(hostname, "Canon") &&
+ _cups_strncasecmp(hostname, "Konica", 6) &&
+ _cups_strncasecmp(hostname, "Minolta", 7);
#endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */
if ((device_fd = open_device(uri, &use_bc)) == -1)
@@ -113,9 +113,9 @@ print_device(const char *uri, /* I - Device URI */
* available printer in the class.
*/
- _cupsLangPuts(stderr,
- _("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -128,23 +128,21 @@ print_device(const char *uri, /* I - Device URI */
if (errno == EBUSY)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 10 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer busy, will retry in 10 seconds."));
sleep(10);
}
else if (errno == ENXIO || errno == EIO || errno == ENOENT ||
errno == ENODEV)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer not connected; will retry in 30 "
- "seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer not connected, will retry in 30 "
+ "seconds."));
sleep(30);
}
else
{
- _cupsLangPrintf(stderr,
- _("ERROR: Unable to open device file \"%s\": %s\n"),
- resource, strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open device file"));
return (CUPS_BACKEND_FAILED);
}
}
@@ -194,13 +192,7 @@ print_device(const char *uri, /* I - Device URI */
#endif /* __sun */
if (print_fd != 0 && tbytes >= 0)
- _cupsLangPrintf(stderr,
-#ifdef HAVE_LONG_LONG
- _("INFO: Sent print file, %lld bytes...\n"),
-#else
- _("INFO: Sent print file, %ld bytes...\n"),
-#endif /* HAVE_LONG_LONG */
- CUPS_LLCAST tbytes);
+ _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
}
/*
@@ -209,7 +201,7 @@ print_device(const char *uri, /* I - Device URI */
close(device_fd);
- return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
+ return (CUPS_BACKEND_OK);
}
@@ -433,8 +425,8 @@ open_device(const char *uri, /* I - Device URI */
*/
if (busy)
- _cupsLangPuts(stderr,
- _("INFO: Printer busy; will retry in 5 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer is busy, will retry in 5 seconds."));
sleep(5);
}
@@ -517,8 +509,8 @@ open_device(const char *uri, /* I - Device URI */
if (busy)
{
- _cupsLangPuts(stderr,
- _("INFO: Printer is busy; will retry in 5 seconds...\n"));
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer is busy, will retry in 5 seconds."));
sleep(5);
}
}
@@ -627,5 +619,5 @@ side_cb(int print_fd, /* I - Print file */
/*
- * End of "$Id: usb-unix.c 8912 2009-12-08 02:13:42Z mike $".
+ * End of "$Id: usb-unix.c 9793 2011-05-20 03:49:49Z mike $".
*/
diff --git a/backend/usb.c b/backend/usb.c
index fddd21d2..81736a1f 100644
--- a/backend/usb.c
+++ b/backend/usb.c
@@ -1,9 +1,9 @@
/*
- * "$Id: usb.c 7687 2008-06-24 01:28:36Z mike $"
+ * "$Id: usb.c 9771 2011-05-12 05:21:56Z mike $"
*
- * USB port backend for the Common UNIX Printing System (CUPS).
+ * USB port backend for CUPS.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -180,7 +180,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
else if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
- _("Usage: %s job-id user title copies options [file]\n"),
+ _("Usage: %s job-id user title copies options [file]"),
argv[0]);
return (CUPS_BACKEND_FAILED);
}
@@ -196,9 +196,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
hostname, sizeof(hostname), &port,
resource, sizeof(resource)) < HTTP_URI_OK)
{
- _cupsLangPuts(stderr,
- _("ERROR: No device URI found in argv[0] or in DEVICE_URI "
- "environment variable!\n"));
+ _cupsLangPrintFilter(stderr, "ERROR",
+ _("No device URI found in argv[0] or in DEVICE_URI "
+ "environment variable."));
return (1);
}
@@ -234,8 +234,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
if ((print_fd = open(argv[6], O_RDONLY)) < 0)
{
- _cupsLangPrintf(stderr, _("ERROR: Unable to open print file %s - %s\n"),
- argv[6], strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
return (CUPS_BACKEND_FAILED);
}
@@ -261,5 +260,5 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
/*
- * End of "$Id: usb.c 7687 2008-06-24 01:28:36Z mike $".
+ * End of "$Id: usb.c 9771 2011-05-12 05:21:56Z mike $".
*/