From e00b005a05b3be11f59ddf676914233d38626b38 Mon Sep 17 00:00:00 2001 From: jlovell Date: Wed, 1 Feb 2006 23:41:32 +0000 Subject: [PATCH] Load cups into easysw/current. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@51 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES.txt | 5 +- Makedefs.in | 6 +- Makefile | 16 +- backend/Dependencies | 32 +- backend/Makefile | 14 +- berkeley/Dependencies | 16 +- cgi-bin/Dependencies | 72 +- config-scripts/cups-common.m4 | 24 +- config-scripts/cups-defaults.m4 | 12 + config.h.in | 12 +- cups/Dependencies | 71 +- cups/dir.c | 2 +- cups/file.c | 6 +- cups/http-support.c | 8 +- cups/usersys.c | 16 +- doc/cups.css | 5 + doc/help/standard.html.in | 4 + filter/Dependencies | 210 ++- init/cupsd-launchd.sh | 7 - packaging/cups.spec.in | 8 +- scheduler/auth.c | 14 +- scheduler/client.c | 6 +- scheduler/conf.c | 7 +- scheduler/cups-deviced.c | 126 +- scheduler/cupsd.h | 6 +- scheduler/dirsvc.c | 3050 ++++++++++++++++--------------- scheduler/dirsvc.h | 11 +- scheduler/env.c | 16 +- scheduler/ipp.c | 223 ++- scheduler/job.c | 111 +- scheduler/listen.c | 28 +- scheduler/main.c | 80 +- scheduler/network.c | 155 +- scheduler/network.h | 17 +- scheduler/printers.c | 60 +- scheduler/printers.h | 7 +- scheduler/process.c | 146 +- scheduler/statbuf.c | 8 +- scheduler/subscriptions.c | 102 +- scheduler/subscriptions.h | 27 +- templates/classes.tmpl | 4 +- templates/printers.tmpl | 8 +- test/ipptest.c | 101 +- tools/makesrcdist | 2 +- tools/testosx | 21 +- 45 files changed, 2801 insertions(+), 2081 deletions(-) delete mode 100755 init/cupsd-launchd.sh diff --git a/CHANGES.txt b/CHANGES.txt index 2e9f452f2..e820b917e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,11 @@ -CHANGES.txt - 01/18/2006 +CHANGES.txt - 01/29/2006 ------------------------ CHANGES IN CUPS V1.2.0b1 + - Added support for launchd on MacOS X. + - Added support for notify_post on MacOS X. + - Added support for DBUS on Linux. - All of the Berkeley (except for lpc) and System V commands now support specification of user, host, and port (STR #1028, STR #1029, STR #1087) diff --git a/Makedefs.in b/Makedefs.in index 4bc2e371d..c3cdf4bb7 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -1,5 +1,5 @@ # -# "$Id: Makedefs.in 5020 2006-01-28 13:36:15Z mike $" +# "$Id: Makedefs.in 5044 2006-02-01 21:35:30Z mike $" # # Common makefile definitions for the Common UNIX Printing System (CUPS). # @@ -46,7 +46,7 @@ STRIP = @STRIP@ # Installation programs... # -INSTALL_BIN = $(LIBTOOL) $(INSTALL) -m 755 -s +INSTALL_BIN = $(LIBTOOL) $(INSTALL) -m 755 INSTALL_CONFIG = $(INSTALL) -m @CUPS_CONFIG_FILE_PERM@ INSTALL_DATA = $(INSTALL) -m 644 INSTALL_DIR = $(INSTALL) -d @@ -208,5 +208,5 @@ DEFAULT_LAUNCHD_CONF = @DEFAULT_LAUNCHD_CONF@ # -# End of "$Id: Makedefs.in 5020 2006-01-28 13:36:15Z mike $" +# End of "$Id: Makedefs.in 5044 2006-02-01 21:35:30Z mike $" # diff --git a/Makefile b/Makefile index 99a042d5b..eb98a5dc6 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # -# "$Id: Makefile 5023 2006-01-29 14:39:44Z mike $" +# "$Id: Makefile 5045 2006-02-01 21:48:01Z mike $" # # Top-level Makefile for the Common UNIX Printing System (CUPS). # @@ -103,16 +103,12 @@ install: installhdrs if test "x$(INITDIR)" = "x" -a "x$(INITDDIR)" != "x"; then \ $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR); \ if test "$(INITDDIR)" = "/System/Library/StartupItems/PrintingServices"; then \ - $(INSTALL_SCRIPT) init/cups.osx $(BUILDROOT)$(INITDDIR)/PrintingServices; \ - $(INSTALL_DATA) init/cups.plist $(BUILDROOT)$(INITDDIR)/StartupParameters.plist; \ + $(INSTALL_SCRIPT) init/PrintingServices $(BUILDROOT)$(INITDDIR)/PrintingServices; \ + $(INSTALL_DATA) init/StartupParameters.plist $(BUILDROOT)$(INITDDIR)/StartupParameters.plist; \ $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj; \ - $(INSTALL_DATA) init/cups.strings $(BUILDROOT)$(INITDDIR)/Resources/English.lproj/Localizable.strings; \ + $(INSTALL_DATA) init/Localizable.strings $(BUILDROOT)$(INITDDIR)/Resources/English.lproj/Localizable.strings; \ elif test "$(INITDDIR)" = "/System/Library/LaunchDaemons"; then \ - $(INSTALL_DATA) init/cupsd-launchd.plist $(BUILDROOT)$(DEFAULT_LAUNCHD_CONF); \ - $(INSTALL_SCRIPT) init/cupsd-launchd.sh $(BUILDROOT)/System/Library/StartupItems/PrintingServices/PrintingServices; \ - $(INSTALL_DATA) init/cups.plist $(BUILDROOT)/System/Library/StartupItems/PrintingServices/StartupParameters.plist; \ - $(INSTALL_DIR) $(BUILDROOT)/System/Library/StartupItems/PrintingServices/Resources/English.lproj; \ - $(INSTALL_DATA) init/cups.strings $(BUILDROOT)/System/Library/StartupItems/PrintingServices/Resources/English.lproj/Localizable.strings; \ + $(INSTALL_DATA) init/org.cups.cupsd.plist $(BUILDROOT)$(DEFAULT_LAUNCHD_CONF); \ else \ $(INSTALL_SCRIPT) init/cups.sh $(BUILDROOT)$(INITDDIR)/cups; \ fi \ @@ -171,5 +167,5 @@ tardist: epm $(EPMFLAGS) -f tardist cups packaging/cups.list # -# End of "$Id: Makefile 5023 2006-01-29 14:39:44Z mike $". +# End of "$Id: Makefile 5045 2006-02-01 21:48:01Z mike $". # diff --git a/backend/Dependencies b/backend/Dependencies index 70897ad97..42ce66029 100644 --- a/backend/Dependencies +++ b/backend/Dependencies @@ -2,24 +2,28 @@ betest.o: ../cups/string.h ../config.h ipp.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/md5.h -ipp.o: ../cups/backend.h ../cups/cups.h ../cups/ipp.h ../cups/ppd.h -ipp.o: ../cups/file.h ../cups/language.h ../cups/array.h ../cups/string.h +ipp.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/backend.h ../cups/cups.h +ipp.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +ipp.o: ../cups/language.h ../cups/string.h lpd.o: ../cups/backend.h ../cups/http-private.h ../config.h ../cups/http.h -lpd.o: ../cups/md5.h ../cups/cups.h ../cups/ipp.h ../cups/ppd.h -lpd.o: ../cups/file.h ../cups/string.h +lpd.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h +lpd.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +lpd.o: ../cups/string.h parallel.o: ../cups/backend.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -parallel.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/string.h -parallel.o: ../config.h ieee1284.c ../cups/debug.h +parallel.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +parallel.o: ../cups/language.h ../cups/string.h ../config.h ieee1284.c +parallel.o: ../cups/debug.h scsi.o: ../cups/backend.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -scsi.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/string.h -scsi.o: ../config.h +scsi.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +scsi.o: ../cups/language.h ../cups/string.h ../config.h serial.o: ../cups/backend.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -serial.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/string.h -serial.o: ../config.h +serial.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +serial.o: ../cups/language.h ../cups/string.h ../config.h socket.o: ../cups/backend.h ../cups/http-private.h ../config.h ../cups/http.h -socket.o: ../cups/md5.h ../cups/cups.h ../cups/ipp.h ../cups/ppd.h -socket.o: ../cups/file.h ../cups/string.h +socket.o: ../cups/md5.h ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h +socket.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +socket.o: ../cups/string.h test1284.o: ../cups/string.h ../config.h ieee1284.c ../cups/debug.h usb.o: ../cups/backend.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -usb.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/string.h -usb.o: ../config.h +usb.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +usb.o: ../cups/language.h ../cups/string.h ../config.h diff --git a/backend/Makefile b/backend/Makefile index 26ce19b4f..92a721a7e 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,5 +1,5 @@ # -# "$Id: Makefile 4903 2006-01-10 20:02:46Z mike $" +# "$Id: Makefile 5044 2006-02-01 21:35:30Z mike $" # # Backend makefile for the Common UNIX Printing System (CUPS). # @@ -26,8 +26,9 @@ include ../Makedefs -BACKENDS = ipp lpd parallel scsi serial socket usb -TARGETS = betest test1284 $(BACKENDS) +RBACKENDS = lpd +UBACKENDS = ipp parallel scsi serial socket usb +TARGETS = betest test1284 $(RBACKENDS) $(UBACKENDS) OBJS = betest.o ipp.o lpd.o parallel.o scsi.o \ serial.o socket.o test1284.o usb.o @@ -61,7 +62,10 @@ depend: install: all $(INSTALL_DIR) $(SERVERBIN)/backend - for file in $(BACKENDS); do \ + for file in $(RBACKENDS); do \ + $(LIBTOOL) $(INSTALL) -m 700 $$file $(SERVERBIN)/backend; \ + done + for file in $(UBACKENDS); do \ $(INSTALL_BIN) $$file $(SERVERBIN)/backend; \ done $(RM) $(SERVERBIN)/backend/http @@ -174,5 +178,5 @@ include Dependencies # -# End of "$Id: Makefile 4903 2006-01-10 20:02:46Z mike $". +# End of "$Id: Makefile 5044 2006-02-01 21:35:30Z mike $". # diff --git a/berkeley/Dependencies b/berkeley/Dependencies index ceb85278c..d8db9344a 100644 --- a/berkeley/Dependencies +++ b/berkeley/Dependencies @@ -1,14 +1,14 @@ # DO NOT DELETE lpc.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -lpc.o: ../cups/ppd.h ../cups/file.h ../cups/i18n.h ../cups/language.h -lpc.o: ../cups/array.h ../cups/debug.h ../cups/string.h ../config.h +lpc.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +lpc.o: ../cups/i18n.h ../cups/debug.h ../cups/string.h ../config.h lpq.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h -lpq.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -lpq.o: ../cups/i18n.h ../cups/language.h ../cups/array.h ../cups/debug.h +lpq.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +lpq.o: ../cups/file.h ../cups/language.h ../cups/i18n.h ../cups/debug.h lpr.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h -lpr.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -lpr.o: ../cups/i18n.h ../cups/language.h ../cups/array.h +lpr.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +lpr.o: ../cups/file.h ../cups/language.h ../cups/i18n.h lprm.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -lprm.o: ../cups/ppd.h ../cups/file.h ../cups/i18n.h ../cups/language.h -lprm.o: ../cups/array.h ../cups/string.h ../config.h +lprm.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +lprm.o: ../cups/i18n.h ../cups/string.h ../config.h diff --git a/cgi-bin/Dependencies b/cgi-bin/Dependencies index 1bfd5141f..71c7c3869 100644 --- a/cgi-bin/Dependencies +++ b/cgi-bin/Dependencies @@ -1,50 +1,52 @@ # DO NOT DELETE help-index.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -help-index.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -help-index.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -help-index.o: ../cups/array.h ../cups/string.h ../config.h ../cups/dir.h +help-index.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +help-index.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +help-index.o: ../cups/i18n.h ../cups/string.h ../config.h ../cups/dir.h html.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -html.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -html.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -html.o: ../cups/array.h ../cups/string.h ../config.h +html.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +html.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +html.o: ../cups/i18n.h ../cups/string.h ../config.h ipp-var.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -ipp-var.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -ipp-var.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -ipp-var.o: ../cups/array.h ../cups/string.h ../config.h +ipp-var.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +ipp-var.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +ipp-var.o: ../cups/i18n.h ../cups/string.h ../config.h search.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -search.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -search.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -search.o: ../cups/array.h ../cups/string.h ../config.h +search.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +search.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +search.o: ../cups/i18n.h ../cups/string.h ../config.h template.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -template.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -template.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -template.o: ../cups/array.h ../cups/string.h ../config.h +template.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +template.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +template.o: ../cups/i18n.h ../cups/string.h ../config.h var.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -var.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -var.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -var.o: ../cups/array.h ../cups/string.h ../config.h +var.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +var.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +var.o: ../cups/i18n.h ../cups/string.h ../config.h admin.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -admin.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -admin.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -admin.o: ../cups/array.h ../cups/string.h ../config.h ../cups/file.h +admin.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +admin.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +admin.o: ../cups/i18n.h ../cups/string.h ../config.h ../cups/file.h classes.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -classes.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -classes.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -classes.o: ../cups/array.h ../cups/string.h ../config.h +classes.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +classes.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +classes.o: ../cups/i18n.h ../cups/string.h ../config.h help.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -help.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -help.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -help.o: ../cups/array.h ../cups/string.h ../config.h +help.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +help.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +help.o: ../cups/i18n.h ../cups/string.h ../config.h jobs.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -jobs.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -jobs.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -jobs.o: ../cups/array.h ../cups/string.h ../config.h +jobs.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +jobs.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +jobs.o: ../cups/i18n.h ../cups/string.h ../config.h printers.o: cgi-private.h cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -printers.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/array.h -printers.o: help-index.h ../cups/debug.h ../cups/i18n.h ../cups/language.h -printers.o: ../cups/array.h ../cups/string.h ../config.h +printers.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +printers.o: ../cups/language.h ../cups/array.h help-index.h ../cups/debug.h +printers.o: ../cups/i18n.h ../cups/string.h ../config.h testcgi.o: cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -testcgi.o: ../cups/ppd.h ../cups/file.h ../cups/array.h help-index.h +testcgi.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +testcgi.o: ../cups/array.h help-index.h testhi.o: cgi.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -testhi.o: ../cups/ppd.h ../cups/file.h ../cups/array.h help-index.h +testhi.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +testhi.o: ../cups/array.h help-index.h diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index 18d0bfff1..95ba2d9c5 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -1,5 +1,5 @@ dnl -dnl "$Id: cups-common.m4 5007 2006-01-27 18:25:42Z mike $" +dnl "$Id: cups-common.m4 5025 2006-01-30 03:49:12Z mike $" dnl dnl Common configuration stuff for the Common UNIX Printing System (CUPS). dnl @@ -213,6 +213,26 @@ case $uname in AC_CHECK_HEADER(notify.h,AC_DEFINE(HAVE_NOTIFY_H)) AC_CHECK_FUNCS(notify_post) ;; + + Linux*) + dnl Check for DBUS support + BACKLIBS="" + CUPSDLIBS="" + + AC_PATH_PROG(PKGCONFIG, pkg-config) + if test "x$PKGCONFIG" != x; then + AC_MSG_CHECKING(for DBUS) + if $PKGCONFIG --exists dbus-1; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DBUS) + CFLAGS="$CFLAGS `$PKGCONFIG --cflags dbus-1` -DDBUS_API_SUBJECT_TO_CHANGE" + CUPSDLIBS="`$PKGCONFIG --libs dbus-1`" + else + AC_MSG_RESULT(no) + fi + fi + ;; + *) BACKLIBS="" CUPSDLIBS="" @@ -231,5 +251,5 @@ AC_SUBST(DEFAULT_IPP_PORT) AC_DEFINE_UNQUOTED(CUPS_DEFAULT_IPP_PORT,$DEFAULT_IPP_PORT) dnl -dnl End of "$Id: cups-common.m4 5007 2006-01-27 18:25:42Z mike $". +dnl End of "$Id: cups-common.m4 5025 2006-01-30 03:49:12Z mike $". dnl diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4 index 6edee7473..4da730c2a 100644 --- a/config-scripts/cups-defaults.m4 +++ b/config-scripts/cups-defaults.m4 @@ -103,6 +103,18 @@ else fi AC_SUBST(CUPS_IMPLICIT_CLASSES) +dnl Default UseNetworkDefault +AC_ARG_ENABLE(network_default, [ --enable-use-network-default + enable UseNetworkDefault by default, default=yes]) +if test "x$enable_network_default" = xno; then + CUPS_USE_NETWORK_DEFAULT="No" + AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 0) +else + CUPS_USE_NETWORK_DEFAULT="Yes" + AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 1) +fi +AC_SUBST(CUPS_USE_NETWORK_DEFAULT) + dnl dnl End of "$Id$". diff --git a/config.h.in b/config.h.in index ee1e4bc34..032146ea6 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,5 @@ /* - * "$Id: config.h.in 5020 2006-01-28 13:36:15Z mike $" + * "$Id: config.h.in 5028 2006-01-31 01:16:43Z mike $" * * Configuration file for the Common UNIX Printing System (CUPS). * @@ -62,6 +62,7 @@ #define CUPS_DEFAULT_BROWSE_SHORT_NAMES 1 #define CUPS_DEFAULT_DEFAULT_SHARED 1 #define CUPS_DEFAULT_IMPLICIT_CLASSES 1 +#define CUPS_DEFAULT_USE_NETWORK_DEFAULT 1 /* @@ -409,8 +410,15 @@ #undef HAVE_NOTIFY_POST +/* + * Do we have DBUS? + */ + +#undef HAVE_DBUS + + #endif /* !_CUPS_CONFIG_H_ */ /* - * End of "$Id: config.h.in 5020 2006-01-28 13:36:15Z mike $". + * End of "$Id: config.h.in 5028 2006-01-31 01:16:43Z mike $". */ diff --git a/cups/Dependencies b/cups/Dependencies index fa951c4ef..f4b6f6787 100644 --- a/cups/Dependencies +++ b/cups/Dependencies @@ -3,68 +3,71 @@ array.o: array.h string.h ../config.h debug.h attr.o: ppd.h array.h file.h debug.h string.h ../config.h auth.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -auth.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +auth.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h backchannel.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h array.h -backchannel.o: file.h +backchannel.o: file.h language.h +backend.o: backend.h string.h ../config.h custom.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -custom.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +custom.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h dest.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -dest.o: array.h file.h i18n.h language.h normalize.h transcode.h +dest.o: array.h file.h language.h i18n.h normalize.h transcode.h dir.o: dir.h string.h ../config.h debug.h emit.o: ppd.h array.h file.h string.h ../config.h encode.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h array.h file.h -encode.o: debug.h -file.o: http-private.h ../config.h http.h string.h md5.h ../cups/debug.h -file.o: file.h +encode.o: language.h ipp-private.h debug.h +file.o: http-private.h ../config.h http.h string.h md5.h ipp-private.h ipp.h +file.o: ../cups/debug.h file.h getputfile.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h array.h getputfile.o: file.h language.h debug.h -globals.o: http-private.h ../config.h http.h string.h md5.h globals.h cups.h -globals.o: ipp.h ppd.h array.h file.h i18n.h language.h normalize.h -globals.o: transcode.h -http.o: http-private.h ../config.h http.h string.h md5.h globals.h cups.h -http.o: ipp.h ppd.h array.h file.h i18n.h language.h normalize.h transcode.h -http.o: debug.h +globals.o: http-private.h ../config.h http.h string.h md5.h ipp-private.h +globals.o: ipp.h globals.h cups.h ppd.h array.h file.h language.h i18n.h +globals.o: normalize.h transcode.h +http.o: http-private.h ../config.h http.h string.h md5.h ipp-private.h ipp.h +http.o: globals.h cups.h ppd.h array.h file.h language.h i18n.h normalize.h +http.o: transcode.h debug.h http-addr.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -http-addr.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h -http-addrlist.o: http-private.h ../config.h http.h string.h md5.h globals.h -http-addrlist.o: cups.h ipp.h ppd.h array.h file.h i18n.h language.h -http-addrlist.o: normalize.h transcode.h debug.h +http-addr.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h +http-addrlist.o: http-private.h ../config.h http.h string.h md5.h +http-addrlist.o: ipp-private.h ipp.h globals.h cups.h ppd.h array.h file.h +http-addrlist.o: language.h i18n.h normalize.h transcode.h debug.h http-support.o: debug.h globals.h string.h ../config.h cups.h ipp.h http.h -http-support.o: md5.h ppd.h array.h file.h i18n.h language.h normalize.h +http-support.o: md5.h ppd.h array.h file.h language.h i18n.h normalize.h http-support.o: transcode.h -ipp.o: http-private.h ../config.h http.h string.h md5.h globals.h cups.h -ipp.o: ipp.h ppd.h array.h file.h i18n.h language.h normalize.h transcode.h -ipp.o: debug.h +ipp.o: http-private.h ../config.h http.h string.h md5.h ipp-private.h ipp.h +ipp.o: globals.h cups.h ppd.h array.h file.h language.h i18n.h normalize.h +ipp.o: transcode.h debug.h ipp-support.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -ipp-support.o: array.h file.h i18n.h language.h normalize.h transcode.h +ipp-support.o: array.h file.h language.h i18n.h normalize.h transcode.h ipp-support.o: debug.h langprintf.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -langprintf.o: array.h file.h i18n.h language.h normalize.h transcode.h +langprintf.o: array.h file.h language.h i18n.h normalize.h transcode.h language.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -language.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +language.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h localize.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -localize.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +localize.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h mark.o: ppd.h array.h file.h string.h ../config.h debug.h md5.o: md5.h string.h ../config.h md5passwd.o: http.h string.h ../config.h md5.h normalize.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -normalize.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +normalize.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h +notify.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h +notify.o: array.h file.h language.h i18n.h normalize.h transcode.h options.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h array.h -options.o: file.h debug.h +options.o: file.h language.h debug.h page.o: ppd.h array.h file.h string.h ../config.h ppd.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h array.h -ppd.o: file.h i18n.h language.h normalize.h transcode.h debug.h +ppd.o: file.h language.h i18n.h normalize.h transcode.h debug.h snprintf.o: string.h ../config.h string.o: string.h ../config.h tempfile.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -tempfile.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +tempfile.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h transcode.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -transcode.o: array.h file.h i18n.h language.h normalize.h transcode.h -usersys.o: http-private.h ../config.h http.h string.h md5.h globals.h cups.h -usersys.o: ipp.h ppd.h array.h file.h i18n.h language.h normalize.h -usersys.o: transcode.h +transcode.o: array.h file.h language.h i18n.h normalize.h transcode.h +usersys.o: http-private.h ../config.h http.h string.h md5.h ipp-private.h +usersys.o: ipp.h globals.h cups.h ppd.h array.h file.h language.h i18n.h +usersys.o: normalize.h transcode.h util.o: globals.h string.h ../config.h cups.h ipp.h http.h md5.h ppd.h -util.o: array.h file.h i18n.h language.h normalize.h transcode.h debug.h +util.o: array.h file.h language.h i18n.h normalize.h transcode.h debug.h testarray.o: ../cups/string.h ../config.h string.h array.h dir.h debug.h testfile.o: string.h ../config.h file.h debug.h testhttp.o: http.h string.h ../config.h md5.h diff --git a/cups/dir.c b/cups/dir.c index e06edea91..ac684afee 100644 --- a/cups/dir.c +++ b/cups/dir.c @@ -391,7 +391,7 @@ cupsDirRead(cups_dir_t *dp) /* I - Directory */ strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename)); snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name); - if (stat(filename, &(dp->entry.fileinfo))) + if (lstat(filename, &(dp->entry.fileinfo))) { DEBUG_printf((" stat() failed for \"%s\" - %s...\n", filename, strerror(errno))); diff --git a/cups/file.c b/cups/file.c index daad1c372..e0c135c98 100644 --- a/cups/file.c +++ b/cups/file.c @@ -1,5 +1,5 @@ /* - * "$Id: file.c 4983 2006-01-25 21:53:43Z mike $" + * "$Id: file.c 5026 2006-01-30 21:59:02Z mike $" * * File functions for the Common UNIX Printing System (CUPS). * @@ -1421,7 +1421,7 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */ } if (bytes < 10 || fp->buf[0] != 0x1f || - (unsigned char)fp->buf[1] != 0x8b || + (fp->buf[1] & 255) != 0x8b || fp->buf[2] != 8 || (fp->buf[3] & 0xe0) != 0) { /* @@ -1770,5 +1770,5 @@ cups_write(cups_file_t *fp, /* I - CUPS file */ /* - * End of "$Id: file.c 4983 2006-01-25 21:53:43Z mike $". + * End of "$Id: file.c 5026 2006-01-30 21:59:02Z mike $". */ diff --git a/cups/http-support.c b/cups/http-support.c index 3103007aa..1ad095bae 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -1,5 +1,5 @@ /* - * "$Id: http-support.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: http-support.c 5035 2006-02-01 14:58:46Z mike $" * * HTTP support routines for the Common UNIX Printing System (CUPS) scheduler. * @@ -1192,7 +1192,9 @@ http_copy_decode(char *dst, /* O - Destination buffer */ * or the end of the string. */ - for (ptr = dst, end = dst + dstsize - 1; *src && !strchr(term, *src); src ++) + for (ptr = dst, end = dst + dstsize - 1; + *src && (!term || !strchr(term, *src)); + src ++) if (ptr < end) { if (*src == '%' && decode) @@ -1285,5 +1287,5 @@ http_copy_encode(char *dst, /* O - Destination buffer */ /* - * End of "$Id: http-support.c 5023 2006-01-29 14:39:44Z mike $". + * End of "$Id: http-support.c 5035 2006-02-01 14:58:46Z mike $". */ diff --git a/cups/usersys.c b/cups/usersys.c index 1b73cbdae..cb25863f3 100644 --- a/cups/usersys.c +++ b/cups/usersys.c @@ -1,5 +1,5 @@ /* - * "$Id: usersys.c 4918 2006-01-12 05:14:40Z mike $" + * "$Id: usersys.c 5041 2006-02-01 16:54:50Z mike $" * * User, system, and password routines for the Common UNIX Printing * System (CUPS). @@ -44,6 +44,7 @@ #include "http-private.h" #include "globals.h" #include +#include #ifdef WIN32 # include #endif /* WIN32 */ @@ -184,6 +185,9 @@ cupsServer(void) char line[1024], /* Line from file */ *value; /* Value on line */ int linenum; /* Line number in file */ +#ifdef CUPS_DEFAULT_DOMAINSOCKET + struct stat sockinfo; /* Domain socket information */ +#endif /* CUPS_DEFAULT_DOMAINSOCKET */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ @@ -218,7 +222,13 @@ cupsServer(void) } #ifdef CUPS_DEFAULT_DOMAINSOCKET - if (!access(CUPS_DEFAULT_DOMAINSOCKET, 0)) + /* + * If we are compiled with domain socket support, only use the + * domain socket if it exists and has the right permissions... + */ + + if (!stat(CUPS_DEFAULT_DOMAINSOCKET, &sockinfo) && + (sockinfo.st_mode & S_IRWXO) == S_IRWXO) server = CUPS_DEFAULT_DOMAINSOCKET; else #endif /* CUPS_DEFAULT_DOMAINSOCKET */ @@ -459,5 +469,5 @@ _cupsGetPassword(const char *prompt) /* I - Prompt string */ /* - * End of "$Id: usersys.c 4918 2006-01-12 05:14:40Z mike $". + * End of "$Id: usersys.c 5041 2006-02-01 16:54:50Z mike $". */ diff --git a/doc/cups.css b/doc/cups.css index a1981b58a..fe76ae633 100644 --- a/doc/cups.css +++ b/doc/cups.css @@ -226,3 +226,8 @@ P.summary { margin-left: 5em; font-family: monospace; } + +SPAN.message { + font-style: italic; + font-size: smaller; +} diff --git a/doc/help/standard.html.in b/doc/help/standard.html.in index 5003acec9..699239bc3 100644 --- a/doc/help/standard.html.in +++ b/doc/help/standard.html.in @@ -70,6 +70,10 @@ Basic authentication with membership in the group LogFilePerm @CUPS_LOG_FILE_PERM@ + + UseNetworkDefault + @CUPS_USE_NETWORK_DEFAULT@ + diff --git a/filter/Dependencies b/filter/Dependencies index c68bdd6dd..243dc3e9b 100644 --- a/filter/Dependencies +++ b/filter/Dependencies @@ -1,119 +1,143 @@ # DO NOT DELETE hpgl-attr.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -hpgl-attr.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -hpgl-attr.o: ../cups/array.h ../cups/string.h ../config.h +hpgl-attr.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +hpgl-attr.o: ../cups/language.h ../cups/language.h ../cups/string.h +hpgl-attr.o: ../config.h hpgl-config.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h -hpgl-config.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -hpgl-config.o: ../cups/language.h ../cups/array.h ../cups/string.h -hpgl-config.o: ../config.h +hpgl-config.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +hpgl-config.o: ../cups/file.h ../cups/language.h ../cups/language.h +hpgl-config.o: ../cups/string.h ../config.h hpgl-main.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -hpgl-main.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -hpgl-main.o: ../cups/array.h ../cups/string.h ../config.h +hpgl-main.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +hpgl-main.o: ../cups/language.h ../cups/language.h ../cups/string.h +hpgl-main.o: ../config.h hpgl-prolog.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h -hpgl-prolog.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -hpgl-prolog.o: ../cups/language.h ../cups/array.h ../cups/string.h -hpgl-prolog.o: ../config.h +hpgl-prolog.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +hpgl-prolog.o: ../cups/file.h ../cups/language.h ../cups/language.h +hpgl-prolog.o: ../cups/string.h ../config.h hpgl-char.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -hpgl-char.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -hpgl-char.o: ../cups/array.h ../cups/string.h ../config.h +hpgl-char.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +hpgl-char.o: ../cups/language.h ../cups/language.h ../cups/string.h +hpgl-char.o: ../config.h hpgl-input.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -hpgl-input.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -hpgl-input.o: ../cups/array.h ../cups/string.h ../config.h +hpgl-input.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +hpgl-input.o: ../cups/language.h ../cups/language.h ../cups/string.h +hpgl-input.o: ../config.h hpgl-polygon.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h -hpgl-polygon.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -hpgl-polygon.o: ../cups/language.h ../cups/array.h ../cups/string.h -hpgl-polygon.o: ../config.h +hpgl-polygon.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +hpgl-polygon.o: ../cups/file.h ../cups/language.h ../cups/language.h +hpgl-polygon.o: ../cups/string.h ../config.h hpgl-vector.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h -hpgl-vector.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -hpgl-vector.o: ../cups/language.h ../cups/array.h ../cups/string.h -hpgl-vector.o: ../config.h -image-bmp.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-bmp.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-bmp.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-colorspace.o: image-private.h image.h raster.h ../cups/ppd.h -image-colorspace.o: ../cups/file.h ../cups/cups.h ../cups/ipp.h -image-colorspace.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h +hpgl-vector.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +hpgl-vector.o: ../cups/file.h ../cups/language.h ../cups/language.h +hpgl-vector.o: ../cups/string.h ../config.h +image-bmp.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-bmp.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-bmp.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-bmp.o: ../cups/string.h ../config.h +image-colorspace.o: image-private.h image.h raster.h ../cups/cups.h +image-colorspace.o: ../cups/ipp.h ../cups/http.h ../cups/md5.h ../cups/ppd.h +image-colorspace.o: ../cups/array.h ../cups/file.h ../cups/language.h image-colorspace.o: ../cups/debug.h ../cups/string.h ../config.h -image-gif.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-gif.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-gif.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-jpeg.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-jpeg.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-jpeg.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-photocd.o: image-private.h image.h raster.h ../cups/ppd.h -image-photocd.o: ../cups/file.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -image-photocd.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/string.h -image-photocd.o: ../config.h -image-pix.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-pix.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-pix.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-png.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-png.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-png.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-pnm.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-pnm.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-pnm.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-sgi.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-sgi.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-sgi.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-sgi.o: image-sgi.h +image-gif.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-gif.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-gif.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-gif.o: ../cups/string.h ../config.h +image-jpeg.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-jpeg.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-jpeg.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-jpeg.o: ../cups/string.h ../config.h +image-photocd.o: image-private.h image.h raster.h ../cups/cups.h +image-photocd.o: ../cups/ipp.h ../cups/http.h ../cups/md5.h ../cups/ppd.h +image-photocd.o: ../cups/array.h ../cups/file.h ../cups/language.h +image-photocd.o: ../cups/debug.h ../cups/string.h ../config.h +image-pix.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-pix.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-pix.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-pix.o: ../cups/string.h ../config.h +image-png.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-png.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-png.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-png.o: ../cups/string.h ../config.h +image-pnm.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-pnm.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-pnm.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-pnm.o: ../cups/string.h ../config.h +image-sgi.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-sgi.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-sgi.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-sgi.o: ../cups/string.h ../config.h image-sgi.h image-sgilib.o: image-sgi.h -image-sun.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-sun.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-sun.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-tiff.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-tiff.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-tiff.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image-zoom.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image-zoom.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image-zoom.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -image.o: image-private.h image.h raster.h ../cups/ppd.h ../cups/file.h -image.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -image.o: ../cups/ppd.h ../cups/debug.h ../cups/string.h ../config.h -interpret.o: ../cups/ppd.h ../cups/file.h ../cups/string.h ../config.h -interpret.o: raster.h -raster.o: raster.h ../cups/ppd.h ../cups/file.h ../cups/string.h ../config.h +image-sun.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-sun.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-sun.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-sun.o: ../cups/string.h ../config.h +image-tiff.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-tiff.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-tiff.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-tiff.o: ../cups/string.h ../config.h +image-zoom.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image-zoom.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image-zoom.o: ../cups/file.h ../cups/language.h ../cups/debug.h +image-zoom.o: ../cups/string.h ../config.h +image.o: image-private.h image.h raster.h ../cups/cups.h ../cups/ipp.h +image.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +image.o: ../cups/file.h ../cups/language.h ../cups/debug.h ../cups/string.h +image.o: ../config.h +interpret.o: ../cups/string.h ../config.h raster.h ../cups/cups.h +interpret.o: ../cups/ipp.h ../cups/http.h ../cups/md5.h ../cups/ppd.h +interpret.o: ../cups/array.h ../cups/file.h ../cups/language.h +raster.o: raster.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +raster.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +raster.o: ../cups/string.h ../config.h form-main.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -form-main.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -form-main.o: ../cups/array.h ../cups/string.h ../config.h +form-main.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +form-main.o: ../cups/language.h ../cups/language.h ../cups/string.h +form-main.o: ../config.h form-ps.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -form-ps.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -form-ps.o: ../cups/array.h ../cups/string.h ../config.h +form-ps.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +form-ps.o: ../cups/language.h ../cups/language.h ../cups/string.h ../config.h form-tree.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -form-tree.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -form-tree.o: ../cups/array.h ../cups/string.h ../config.h +form-tree.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +form-tree.o: ../cups/language.h ../cups/language.h ../cups/string.h +form-tree.o: ../config.h imagetops.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -imagetops.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -imagetops.o: ../cups/array.h ../cups/string.h ../config.h image.h raster.h -imagetops.o: ../cups/ppd.h +imagetops.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +imagetops.o: ../cups/language.h ../cups/language.h ../cups/string.h +imagetops.o: ../config.h image.h raster.h imagetoraster.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -imagetoraster.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h -imagetoraster.o: ../cups/language.h ../cups/array.h ../cups/string.h -imagetoraster.o: ../config.h image-private.h image.h raster.h ../cups/ppd.h -imagetoraster.o: ../cups/debug.h +imagetoraster.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +imagetoraster.o: ../cups/language.h ../cups/language.h ../cups/string.h +imagetoraster.o: ../config.h image-private.h image.h raster.h ../cups/debug.h common.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -common.o: ../cups/ppd.h ../cups/file.h ../cups/language.h ../cups/array.h -common.o: ../cups/string.h ../config.h +common.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +common.o: ../cups/language.h ../cups/string.h ../config.h pstops.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -pstops.o: ../cups/ppd.h ../cups/file.h ../cups/language.h ../cups/array.h -pstops.o: ../cups/string.h ../config.h -raster.o: raster.h ../cups/ppd.h ../cups/file.h ../cups/string.h ../config.h +pstops.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +pstops.o: ../cups/language.h ../cups/string.h ../config.h +raster.o: raster.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h +raster.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +raster.o: ../cups/string.h ../config.h rastertolabel.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -rastertolabel.o: ../cups/ppd.h ../cups/file.h ../cups/string.h ../config.h -rastertolabel.o: raster.h ../cups/ppd.h +rastertolabel.o: ../cups/ppd.h ../cups/array.h ../cups/file.h +rastertolabel.o: ../cups/language.h ../cups/string.h ../config.h raster.h rastertoepson.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -rastertoepson.o: ../cups/ppd.h ../cups/file.h ../cups/ppd.h ../cups/string.h +rastertoepson.o: ../cups/ppd.h ../cups/array.h ../cups/file.h +rastertoepson.o: ../cups/language.h ../cups/ppd.h ../cups/string.h rastertoepson.o: ../config.h raster.h rastertohp.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h -rastertohp.o: ../cups/ppd.h ../cups/file.h ../cups/string.h ../config.h -rastertohp.o: raster.h ../cups/ppd.h +rastertohp.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h +rastertohp.o: ../cups/string.h ../config.h raster.h texttops.o: textcommon.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h -texttops.o: ../cups/md5.h ../cups/ppd.h ../cups/file.h ../cups/language.h -texttops.o: ../cups/array.h ../cups/string.h ../config.h +texttops.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +texttops.o: ../cups/language.h ../cups/language.h ../cups/string.h +texttops.o: ../config.h textcommon.o: textcommon.h common.h ../cups/cups.h ../cups/ipp.h -textcommon.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/file.h -textcommon.o: ../cups/language.h ../cups/array.h ../cups/string.h ../config.h -testraster.o: raster.h ../cups/ppd.h ../cups/file.h ../cups/string.h -testraster.o: ../config.h +textcommon.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/array.h +textcommon.o: ../cups/file.h ../cups/language.h ../cups/language.h +textcommon.o: ../cups/string.h ../config.h +testraster.o: raster.h ../cups/cups.h ../cups/ipp.h ../cups/http.h +testraster.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h +testraster.o: ../cups/language.h ../cups/string.h ../config.h gziptoany.o: ../cups/string.h ../config.h diff --git a/init/cupsd-launchd.sh b/init/cupsd-launchd.sh deleted file mode 100755 index c95622054..000000000 --- a/init/cupsd-launchd.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# This is a dummy script to ensure that the CUPS domain socket is world- -# writable. This works around a problem in launchd... - -if test -e /private/var/run/cupsd; then - chmod g+w,o+w /private/var/run/cupsd -fi diff --git a/packaging/cups.spec.in b/packaging/cups.spec.in index d551315cb..4dc600984 100644 --- a/packaging/cups.spec.in +++ b/packaging/cups.spec.in @@ -170,7 +170,13 @@ rm -rf $RPM_BUILD_ROOT /usr/bin/lp* %dir /usr/lib/cups %dir /usr/lib/cups/backend -/usr/lib/cups/backend/* +/usr/lib/cups/backend/http +/usr/lib/cups/backend/ipp +%attr(0700,root,root) /usr/lib/cups/backend/lpd +/usr/lib/cups/backend/parallel +/usr/lib/cups/backend/scsi +/usr/lib/cups/backend/serial +/usr/lib/cups/backend/usb %dir /usr/lib/cups/cgi-bin /usr/lib/cups/cgi-bin/* %dir /usr/lib/cups/daemon diff --git a/scheduler/auth.c b/scheduler/auth.c index 0c6cd85d9..e71cfaa40 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -1,5 +1,5 @@ ;/* - * "$Id: auth.c 4929 2006-01-13 16:38:43Z mike $" + * "$Id: auth.c 5043 2006-02-01 18:55:16Z mike $" * * Authorization routines for the Common UNIX Printing System (CUPS). * @@ -803,7 +803,9 @@ cupsdCheckAuth( cupsdNetIFUpdate(); - for (iface = NetIFList; iface != NULL; iface = iface->next) + for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); + iface; + iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) { /* * Only check local interfaces... @@ -848,9 +850,9 @@ cupsdCheckAuth( * Check the named interface... */ - for (iface = cupsdNetIFFind(masks->mask.name.name); - iface && !strcasecmp(masks->mask.name.name, iface->name); - iface = iface->next) + for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); + iface && !strcmp(masks->mask.name.name, iface->name); + iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) { if (iface->address.addr.sa_family == AF_INET) { @@ -2125,5 +2127,5 @@ to64(char *s, /* O - Output string */ /* - * End of "$Id: auth.c 4929 2006-01-13 16:38:43Z mike $". + * End of "$Id: auth.c 5043 2006-02-01 18:55:16Z mike $". */ diff --git a/scheduler/client.c b/scheduler/client.c index 47e80dd39..396b817d4 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -1,5 +1,5 @@ /* - * "$Id: client.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: client.c 5046 2006-02-01 22:11:58Z mike $" * * Client routines for the Common UNIX Printing System (CUPS) scheduler. * @@ -3205,7 +3205,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ int envc; /* Number of environment variables */ char argbuf[10240], /* Argument buffer */ *argv[100], /* Argument strings */ - *envp[100]; /* Environment variables */ + *envp[MAX_ENV]; /* Environment variables */ char content_length[1024], /* CONTENT_LENGTH environment variable */ content_type[1024], /* CONTENT_TYPE environment variable */ http_cookie[32768], /* HTTP_COOKIE environment variable */ @@ -3486,5 +3486,5 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ /* - * End of "$Id: client.c 5023 2006-01-29 14:39:44Z mike $". + * End of "$Id: client.c 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/conf.c b/scheduler/conf.c index 595cd825b..c70456561 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -1,5 +1,5 @@ /* - * "$Id: conf.c 5020 2006-01-28 13:36:15Z mike $" + * "$Id: conf.c 5028 2006-01-31 01:16:43Z mike $" * * Configuration routines for the Common UNIX Printing System (CUPS). * @@ -162,7 +162,8 @@ static cupsd_var_t variables[] = { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_STRING }, { "StateDir", &StateDir, CUPSD_VARTYPE_STRING }, { "TempDir", &TempDir, CUPSD_VARTYPE_STRING }, - { "Timeout", &Timeout, CUPSD_VARTYPE_INTEGER } + { "Timeout", &Timeout, CUPSD_VARTYPE_INTEGER }, + { "UseNetworkDefault", &UseNetworkDefault, CUPSD_VARTYPE_BOOLEAN } }; #define NUM_VARS (sizeof(variables) / sizeof(variables[0])) @@ -3123,5 +3124,5 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ /* - * End of "$Id: conf.c 5020 2006-01-28 13:36:15Z mike $". + * End of "$Id: conf.c 5028 2006-01-31 01:16:43Z mike $". */ diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c index 6617d911c..fd0101acd 100644 --- a/scheduler/cups-deviced.c +++ b/scheduler/cups-deviced.c @@ -1,5 +1,5 @@ /* - * "$Id: cups-deviced.c 4881 2005-12-15 22:03:40Z mike $" + * "$Id: cups-deviced.c 5044 2006-02-01 21:35:30Z mike $" * * Device scanning mini-daemon for the Common UNIX Printing System (CUPS). * @@ -58,6 +58,7 @@ typedef struct static int alarm_tripped; /* Non-zero if alarm was tripped */ static cups_array_t *devs; /* Device info */ +static int normal_user; /* Normal user ID */ /* @@ -87,6 +88,7 @@ main(int argc, /* I - Number of command-line args */ { const char *server_bin; /* CUPS_SERVERBIN environment variable */ char backends[1024]; /* Location of backends */ + int request_id; /* Request ID */ int count; /* Number of devices from backend */ int compat; /* Compatibility device? */ FILE *fp; /* Pipe to device backend */ @@ -113,17 +115,67 @@ main(int argc, /* I - Number of command-line args */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + setbuf(stderr, NULL); + /* * Check the command-line... */ - if (argc != 4) + if (argc > 1) + request_id = atoi(argv[1]); + else + request_id = 1; + + if (argc != 5) + { + fputs("Usage: cups-deviced request-id limit user-id options\n", stderr); + + cupsdSendIPPHeader(IPP_BAD_REQUEST, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", + "Bad command-line arguments passed to cups-deviced!"); + cupsdSendIPPTrailer(); + + return (1); + } + + if (request_id < 1) { - fputs("Usage: cups-deviced request_id limit options\n", stderr); + fprintf(stderr, "cups-deviced: Bad request ID %d!\n", request_id); + + cupsdSendIPPHeader(IPP_BAD_REQUEST, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", + "Bad request ID argument passed to cups-deviced!"); + cupsdSendIPPTrailer(); + return (1); } - num_options = cupsParseOptions(argv[3], 0, &options); + normal_user = atoi(argv[3]); + if (normal_user <= 0) + { + fprintf(stderr, "cups-deviced: Bad user %d!\n", normal_user); + + cupsdSendIPPHeader(IPP_BAD_REQUEST, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", + "Bad user ID argument passed to cups-deviced!"); + cupsdSendIPPTrailer(); + + return (1); + } + + num_options = cupsParseOptions(argv[4], 0, &options); requested = cupsGetOption("requested-attributes", num_options, options); if (!requested || strstr(requested, "all")) @@ -154,8 +206,19 @@ main(int argc, /* I - Number of command-line args */ if ((dir = cupsDirOpen(backends)) == NULL) { - fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory \"%s\": %s", - backends, strerror(errno)); + fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory " + "\"%s\": %s", backends, strerror(errno)); + + snprintf(line, sizeof(line), "Unable to open backend directory \"%s\": %s", + backends, strerror(errno)); + cupsdSendIPPHeader(IPP_BAD_REQUEST, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", line); + cupsdSendIPPTrailer(); + return (1); } @@ -171,6 +234,31 @@ main(int argc, /* I - Number of command-line args */ while ((dent = cupsDirRead(dir)) != NULL) { + /* + * Skip entries that are not executable files... + */ + + if (!S_ISREG(dent->fileinfo.st_mode) || + (dent->fileinfo.st_mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR)) + continue; + + /* + * Change effective users depending on the backend permissions... + */ + + if (!getuid()) + { + /* + * Backends without permissions for normal users run as root, + * all others run as the unprivileged user... + */ + + if (!(dent->fileinfo.st_mode & (S_IRWXG | S_IRWXO))) + seteuid(0); + else + seteuid(normal_user); + } + /* * Run the backend with no arguments and collect the output... */ @@ -250,7 +338,8 @@ main(int argc, /* I - Number of command-line args */ return (1); } - fprintf(stderr, "DEBUG: [cups-deviced] Added device \"%s\"...\n", uri); + fprintf(stderr, "DEBUG: [cups-deviced] Added device \"%s\"...\n", + uri); count ++; } } @@ -262,8 +351,8 @@ main(int argc, /* I - Number of command-line args */ alarm(0); if (alarm_tripped) - fprintf(stderr, "WARNING: [cups-deviced] Backend \"%s\" did not respond within 30 seconds!\n", - dent->filename); + fprintf(stderr, "WARNING: [cups-deviced] Backend \"%s\" did not " + "respond within 30 seconds!\n", dent->filename); pclose(fp); @@ -284,24 +373,31 @@ main(int argc, /* I - Number of command-line args */ return (1); } - fprintf(stderr, "DEBUG: [cups-deviced] Compatibility device \"%s\"...\n", - dent->filename); + fprintf(stderr, "DEBUG: [cups-deviced] Compatibility device " + "\"%s\"...\n", dent->filename); } } else - fprintf(stderr, "WARNING: [cups-deviced] Unable to execute \"%s\" backend: %s\n", - dent->filename, strerror(errno)); + fprintf(stderr, "WARNING: [cups-deviced] Unable to execute \"%s\" " + "backend: %s\n", dent->filename, strerror(errno)); } cupsDirClose(dir); + /* + * Switch back to root as needed... + */ + + if (!getuid() && geteuid()) + seteuid(0); + /* * Output the list of devices... */ puts("Content-Type: application/ipp\n"); - cupsdSendIPPHeader(IPP_OK, atoi(argv[1])); + cupsdSendIPPHeader(IPP_OK, request_id); cupsdSendIPPGroup(IPP_TAG_OPERATION); cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); @@ -437,5 +533,5 @@ sigalrm_handler(int sig) /* I - Signal number */ /* - * End of "$Id: cups-deviced.c 4881 2005-12-15 22:03:40Z mike $". + * End of "$Id: cups-deviced.c 5044 2006-02-01 21:35:30Z mike $". */ diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index 7380c3dcd..e6f0fa0ed 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -1,5 +1,5 @@ /* - * "$Id: cupsd.h 5007 2006-01-27 18:25:42Z mike $" + * "$Id: cupsd.h 5046 2006-02-01 22:11:58Z mike $" * * Main header file for the Common UNIX Printing System (CUPS) scheduler. * @@ -85,6 +85,7 @@ extern const char *cups_hstrerror(int); * Implementation limits... */ +#define MAX_ENV 100 /* Maximum number of environment strings */ #define MAX_USERPASS 33 /* Maximum size of username/password */ #define MAX_FILTERS 20 /* Maximum number of filters */ #define MAX_SYSTEM_GROUPS 32 /* Maximum number of system groups */ @@ -192,11 +193,12 @@ __attribute__ ((__format__ (__printf__, 2, 3))) ; extern int cupsdEndProcess(int pid, int force); +extern const char *cupsdFinishProcess(int pid, char *name, int namelen); extern int cupsdStartProcess(const char *command, char *argv[], char *envp[], int infd, int outfd, int errfd, int backfd, int root, int *pid); /* - * End of "$Id: cupsd.h 5007 2006-01-27 18:25:42Z mike $". + * End of "$Id: cupsd.h 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index dd63491d9..e48250d38 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -1,5 +1,5 @@ /* - * "$Id: dirsvc.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: dirsvc.c 5043 2006-02-01 18:55:16Z mike $" * * Directory services routines for the Common UNIX Printing System (CUPS). * @@ -24,8 +24,6 @@ * Contents: * * cupsdLoadRemoteCache() - Load the remote printer cache. - * cupsdProcessBrowseData() - Process new browse data. - * cupsdProcessImplicitClasses() - Create/update implicit classes as needed. * cupsdSaveRemoteCache() - Save the remote printer cache. * cupsdSendBrowseDelete() - Send a "browse delete" message for a * printer. @@ -43,6 +41,9 @@ * protocol. * cupsdUpdatePolling() - Read status messages from the poll daemons. * cupsdUpdateSLPBrowse() - Get browsing information via SLP. + * dequote() - Remote quotes from a string. + * process_browse_data() - Process new browse data. + * process_implicit_classes() - Create/update implicit classes as needed. * slp_attr_callback() - SLP attribute callback * slp_dereg_printer() - SLPDereg() the specified printer * slp_get_attr() - Get an attribute from an SLP registration. @@ -59,10 +60,22 @@ /* - * SLP definitions... + * Local functions... */ +static char *dequote(char *d, const char *s, int dlen); +static void process_browse_data(const char *uri, cups_ptype_t type, + ipp_pstate_t state, const char *location, + const char *info, const char *make_model, + int num_attrs, cups_option_t *attrs); +static void process_implicit_classes(void); + + #ifdef HAVE_LIBSLP +/* + * SLP definitions... + */ + /* * SLP service name for CUPS... */ @@ -419,2006 +432,2065 @@ cupsdLoadRemoteCache(void) * Do auto-classing if needed... */ - cupsdProcessImplicitClasses(); + process_implicit_classes(); } /* - * 'cupsdProcessBrowseData()' - Process new browse data. + * 'cupsdSaveRemoteCache()' - Save the remote printer cache. */ void -cupsdProcessBrowseData( - const char *uri, /* I - URI of printer/class */ - cups_ptype_t type, /* I - Printer type */ - ipp_pstate_t state, /* I - Printer state */ - const char *location, /* I - Printer location */ - const char *info, /* I - Printer information */ - const char *make_model, /* I - Printer make and model */ - int num_attrs, /* I - Number of attributes */ - cups_option_t *attrs) /* I - Attributes */ +cupsdSaveRemoteCache(void) { - int update; /* Update printer attributes? */ - char finaluri[HTTP_MAX_URI], /* Final URI for printer */ - method[HTTP_MAX_URI], /* Method portion of URI */ - username[HTTP_MAX_URI], /* Username portion of URI */ - host[HTTP_MAX_URI], /* Host portion of URI */ - resource[HTTP_MAX_URI]; /* Resource portion of URI */ - int port; /* Port portion of URI */ - char name[IPP_MAX_NAME], /* Name of printer */ - *hptr, /* Pointer into hostname */ - *sptr; /* Pointer into ServerName */ - char local_make_model[IPP_MAX_NAME]; - /* Local make and model */ - cupsd_printer_t *p; /* Printer information */ - const char *ipp_options; /* ipp-options value */ - - - /* - * Pull the URI apart to see if this is a local or remote printer... - */ + int i; /* Looping var */ + cups_file_t *fp; /* printers.conf file */ + char temp[1024]; /* Temporary string */ + cupsd_printer_t *printer; /* Current printer class */ + time_t curtime; /* Current time */ + struct tm *curdate; /* Current date */ - httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), username, - sizeof(username), host, sizeof(host), &port, resource, - sizeof(resource)); /* - * Determine if the URI contains any illegal characters in it... + * Create the remote.cache file... */ - if (strncmp(uri, "ipp://", 6) || !host[0] || - (strncmp(resource, "/printers/", 10) && - strncmp(resource, "/classes/", 9))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdProcessBrowseData: Bad printer URI in browse data: %s", - uri); - return; - } + snprintf(temp, sizeof(temp), "%s/remote.cache", CacheDir); - if (strchr(resource, '?') || - (!strncmp(resource, "/printers/", 10) && strchr(resource + 10, '/')) || - (!strncmp(resource, "/classes/", 9) && strchr(resource + 9, '/'))) + if ((fp = cupsFileOpen(temp, "w")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdProcessBrowseData: Bad resource in browse data: %s", - resource); + "Unable to save remote.cache - %s", strerror(errno)); return; } + else + cupsdLogMessage(CUPSD_LOG_INFO, "Saving remote.cache..."); /* - * OK, this isn't a local printer; add any remote options... + * Restrict access to the file... */ - ipp_options = cupsGetOption("ipp-options", num_attrs, attrs); - - if (BrowseRemoteOptions) - { - if (BrowseRemoteOptions[0] == '?') - { - /* - * Override server-supplied options... - */ - - snprintf(finaluri, sizeof(finaluri), "%s%s", uri, BrowseRemoteOptions); - } - else if (ipp_options) - { - /* - * Combine the server and local options... - */ - - snprintf(finaluri, sizeof(finaluri), "%s?%s+%s", uri, ipp_options, - BrowseRemoteOptions); - } - else - { - /* - * Just use the local options... - */ + fchown(cupsFileNumber(fp), getuid(), Group); + fchmod(cupsFileNumber(fp), ConfigFilePerm); - snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, BrowseRemoteOptions); - } + /* + * Write a small header to the file... + */ - uri = finaluri; - } - else if (ipp_options) - { - /* - * Just use the server-supplied options... - */ + curtime = time(NULL); + curdate = localtime(&curtime); + strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); - snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, ipp_options); - uri = finaluri; - } + cupsFilePuts(fp, "# Remote cache file for " CUPS_SVERSION "\n"); + cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); /* - * See if we already have it listed in the Printers list, and add it if not... + * Write each local printer known to the system... */ - type |= CUPS_PRINTER_REMOTE; - type &= ~CUPS_PRINTER_IMPLICIT; - update = 0; - hptr = strchr(host, '.'); - sptr = strchr(ServerName, '.'); - - if (sptr != NULL && hptr != NULL) + for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers); + printer; + printer = (cupsd_printer_t *)cupsArrayNext(Printers)) { /* - * Strip the common domain name components... + * Skip local destinations... */ - while (hptr != NULL) - { - if (!strcasecmp(hptr, sptr)) - { - *hptr = '\0'; - break; - } - else - hptr = strchr(hptr + 1, '.'); - } - } + if (!(printer->type & CUPS_PRINTER_REMOTE)) + continue; - if (type & CUPS_PRINTER_CLASS) - { /* - * Remote destination is a class... + * Write printers as needed... */ - if (!strncmp(resource, "/classes/", 9)) - snprintf(name, sizeof(name), "%s@%s", resource + 9, host); + if (printer == DefaultPrinter) + cupsFilePuts(fp, "hostname && strcasecmp(p->hostname, host)) - { - /* - * Nope, this isn't the same host; if the hostname isn't the local host, - * add it to the other class and then find a class using the full host - * name... - */ + if (printer->type & CUPS_PRINTER_CLASS) + cupsFilePrintf(fp, "Class %s>\n", printer->name); + else + cupsFilePrintf(fp, "Printer %s>\n", printer->name); - if (p->type & CUPS_PRINTER_REMOTE) - { - cupsdLogMessage(CUPSD_LOG_INFO, - "Renamed remote class \"%s\" to \"%s@%s\"...", - p->name, p->name, p->hostname); - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "Class \'%s\' deleted by directory services.", - p->name); + cupsFilePrintf(fp, "Type %d\n", printer->type); - cupsArrayRemove(Printers, p); - cupsdSetStringf(&p->name, "%s@%s", p->name, p->hostname); - cupsdSetPrinterAttrs(p); - cupsArrayAdd(Printers, p); + cupsFilePrintf(fp, "BrowseTime %d\n", (int)printer->browse_time); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "Class \'%s\' added by directory services.", - p->name); - } + if (printer->info) + cupsFilePrintf(fp, "Info %s\n", printer->info); - p = NULL; - } - else if (!p->hostname) - { - /* - * Hostname not set, so this must be a cached remote printer - * that was created for a pending print job... - */ + if (printer->make_model) + cupsFilePrintf(fp, "MakeModel %s\n", printer->make_model); - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); - update = 1; - } - } - else - { - /* - * Use the short name for this shared class. - */ + if (printer->location) + cupsFilePrintf(fp, "Location %s\n", printer->location); - strlcpy(name, resource + 9, sizeof(name)); - } - } - else if (p && !p->hostname) - { - /* - * Hostname not set, so this must be a cached remote printer - * that was created for a pending print job... - */ + if (printer->device_uri) + cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri); - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); - update = 1; + if (printer->state == IPP_PRINTER_STOPPED) + { + cupsFilePuts(fp, "State Stopped\n"); + cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message); } + else + cupsFilePuts(fp, "State Idle\n"); - if (!p) - { - /* - * Class doesn't exist; add it... - */ + if (printer->accepting) + cupsFilePuts(fp, "Accepting Yes\n"); + else + cupsFilePuts(fp, "Accepting No\n"); - p = cupsdAddClass(name); + cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0], + printer->job_sheets[1]); - cupsdLogMessage(CUPSD_LOG_INFO, "Added remote class \"%s\"...", name); + for (i = 0; i < printer->num_users; i ++) + cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow", + printer->users[i]); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "Class \'%s\' added by directory services.", name); + if (printer->type & CUPS_PRINTER_CLASS) + cupsFilePuts(fp, "\n"); + else + cupsFilePuts(fp, "\n"); + } - /* - * Force the URI to point to the real server... - */ + cupsFileClose(fp); +} - p->type = type & ~CUPS_PRINTER_REJECTING; - p->accepting = 1; - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); - cupsdSetString(&p->hostname, host); - update = 1; - } - } - else - { - /* - * Remote destination is a printer... - */ +/* + * 'cupsdSendBrowseDelete()' - Send a "browse delete" message for a printer. + */ - if (strncmp(resource, "/printers/", 10) == 0) - snprintf(name, sizeof(name), "%s@%s", resource + 10, host); - else - return; +void +cupsdSendBrowseDelete( + cupsd_printer_t *p) /* I - Printer to delete */ +{ + /* + * Only announce if browsing is enabled... + */ - if ((p = cupsdFindPrinter(name)) == NULL && BrowseShortNames) - { - if ((p = cupsdFindPrinter(resource + 10)) != NULL) - { - if (p->hostname && strcasecmp(p->hostname, host)) - { - /* - * Nope, this isn't the same host; if the hostname isn't the local host, - * add it to the other printer and then find a printer using the full host - * name... - */ + if (!Browsing || !p->shared) + return; - if (p->type & CUPS_PRINTER_REMOTE) - { - cupsdLogMessage(CUPSD_LOG_INFO, - "Renamed remote printer \"%s\" to \"%s@%s\"...", - p->name, p->name, p->hostname); - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "Printer \'%s\' deleted by directory services.", - p->name); + /* + * First mark the printer for deletion... + */ - cupsArrayRemove(Printers, p); - cupsdSetStringf(&p->name, "%s@%s", p->name, p->hostname); - cupsdSetPrinterAttrs(p); - cupsArrayAdd(Printers, p); + p->type |= CUPS_PRINTER_DELETE; - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "Printer \'%s\' added by directory services.", - p->name); - } + /* + * Announce the deletion... + */ - p = NULL; - } - else if (!p->hostname) - { - /* - * Hostname not set, so this must be a cached remote printer - * that was created for a pending print job... - */ + if (BrowseLocalProtocols & BROWSE_CUPS) + cupsdSendCUPSBrowse(p); +#ifdef HAVE_LIBSLP + if (BrowseLocalProtocols & BROWSE_SLP) + slp_dereg_printer(p); +#endif /* HAVE_LIBSLP */ +} - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); - update = 1; - } - } - else - { - /* - * Use the short name for this shared printer. - */ - strlcpy(name, resource + 10, sizeof(name)); - } - } - else if (p && !p->hostname) - { - /* - * Hostname not set, so this must be a cached remote printer - * that was created for a pending print job... - */ +/* + * 'cupsdSendBrowseList()' - Send new browsing information as necessary. + */ - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); - update = 1; - } +void +cupsdSendBrowseList(void) +{ + int count; /* Number of dests to update */ + cupsd_printer_t *p; /* Current printer */ + time_t ut, /* Minimum update time */ + to; /* Timeout time */ - if (!p) + + if (!Browsing || !BrowseLocalProtocols || !Printers) + return; + + /* + * Compute the update and timeout times... + */ + + ut = time(NULL) - BrowseInterval; + to = time(NULL) - BrowseTimeout; + + /* + * Figure out how many printers need an update... + */ + + if (BrowseInterval > 0) + { + int max_count; /* Maximum number to update */ + + + /* + * Throttle the number of printers we'll be updating this time + * around based on the number of queues that need updating and + * the maximum number of queues to update each second... + */ + + max_count = 2 * cupsArrayCount(Printers) / BrowseInterval + 1; + + for (count = 0, p = (cupsd_printer_t *)cupsArrayFirst(Printers); + count < max_count && p != NULL; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) && + p->shared && p->browse_time < ut) + count ++; + + /* + * Loop through all of the printers and send local updates as needed... + */ + + if (BrowseNext) + p = (cupsd_printer_t *)cupsArrayFind(Printers, BrowseNext); + else + p = (cupsd_printer_t *)cupsArrayFirst(Printers); + + for (; + count > 0; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) { /* - * Printer doesn't exist; add it... + * Check for wraparound... */ - p = cupsdAddPrinter(name); + if (!p) + p = (cupsd_printer_t *)cupsArrayFirst(Printers); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "Printer \'%s\' added by directory services.", name); + if (!p) + break; + else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) || + !p->shared) + continue; + else if (p->browse_time < ut) + { + /* + * Need to send an update... + */ - cupsdLogMessage(CUPSD_LOG_INFO, "Added remote printer \"%s\"...", name); + count --; - /* - * Force the URI to point to the real server... - */ + p->browse_time = time(NULL); - p->type = type & ~CUPS_PRINTER_REJECTING; - p->accepting = 1; - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); + if (BrowseLocalProtocols & BROWSE_CUPS) + cupsdSendCUPSBrowse(p); - update = 1; +#ifdef HAVE_LIBSLP + if (BrowseLocalProtocols & BROWSE_SLP) + cupsdSendSLPBrowse(p); +#endif /* HAVE_LIBSLP */ + } } + + /* + * Save where we left off so that all printers get updated... + */ + + BrowseNext = p; } /* - * Update the state... + * Loop through all of the printers and send local updates as needed... */ - p->state = state; - p->browse_time = time(NULL); - - if (type & CUPS_PRINTER_REJECTING) + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) { - type &= ~CUPS_PRINTER_REJECTING; + /* + * If this is a remote queue, see if it needs to be timed out... + */ - if (p->accepting) + if (p->type & CUPS_PRINTER_REMOTE) { - update = 1; - p->accepting = 0; + if (p->browse_time < to) + { + cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, + "%s \'%s\' deleted by directory services (timeout).", + (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer", + p->name); + + cupsdLogMessage(CUPSD_LOG_INFO, + "Remote destination \"%s\" has timed out; deleting it...", + p->name); + + cupsArraySave(Printers); + cupsdDeletePrinter(p, 1); + cupsArrayRestore(Printers); + } } } - else if (!p->accepting) - { - update = 1; - p->accepting = 1; - } +} - if (p->type != type) - { - p->type = type; - update = 1; - } - if (location && (!p->location || strcmp(p->location, location))) - { - cupsdSetString(&p->location, location); - update = 1; - } +/* + * 'cupsdSendCUPSBrowse()' - Send new browsing information using the CUPS protocol. + */ - if (info && (!p->info || strcmp(p->info, info))) - { - cupsdSetString(&p->info, info); - update = 1; - } - - if (!make_model || !make_model[0]) - { - if (type & CUPS_PRINTER_CLASS) - snprintf(local_make_model, sizeof(local_make_model), - "Remote Class on %s", host); - else - snprintf(local_make_model, sizeof(local_make_model), - "Remote Printer on %s", host); - } - else - snprintf(local_make_model, sizeof(local_make_model), - "%s on %s", make_model, host); - - if (!p->make_model || strcmp(p->make_model, local_make_model)) - { - cupsdSetString(&p->make_model, local_make_model); - update = 1; - } - - if (type & CUPS_PRINTER_DELETE) - { - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "%s \'%s\' deleted by directory services.", - (type & CUPS_PRINTER_CLASS) ? "Class" : "Printer", p->name); +void +cupsdSendCUPSBrowse(cupsd_printer_t *p) /* I - Printer to send */ +{ + int i; /* Looping var */ + cups_ptype_t type; /* Printer type */ + cupsd_dirsvc_addr_t *b; /* Browse address */ + int bytes; /* Length of packet */ + char packet[1453], /* Browse data packet */ + uri[1024], /* Printer URI */ + options[1024], /* Browse local options */ + location[1024], /* printer-location */ + info[1024], /* printer-info */ + make_model[1024]; + /* printer-make-and-model */ + cupsd_netif_t *iface; /* Network interface */ - cupsdExpireSubscriptions(p, NULL); - - cupsdDeletePrinter(p, 1); - cupsdUpdateImplicitClasses(); - } - else if (update) - { - cupsdSetPrinterAttrs(p); - cupsdUpdateImplicitClasses(); - } /* - * See if we have a default printer... If not, make the first printer the - * default. + * Figure out the printer type value... */ - if (DefaultPrinter == NULL && Printers != NULL) - DefaultPrinter = (cupsd_printer_t *)cupsArrayFirst(Printers); + type = p->type | CUPS_PRINTER_REMOTE; - /* - * Do auto-classing if needed... - */ + if (!p->accepting) + type |= CUPS_PRINTER_REJECTING; - cupsdProcessImplicitClasses(); + if (p == DefaultPrinter) + type |= CUPS_PRINTER_DEFAULT; /* - * Update the printcap file... + * Initialize the browse options... */ - cupsdWritePrintcap(); -} - - -/* - * 'cupsdProcessImplicitClasses()' - Create/update implicit classes as needed. - */ - -void -cupsdProcessImplicitClasses(void) -{ - int i; /* Looping var */ - int update; /* Update printer attributes? */ - char name[IPP_MAX_NAME], /* Name of printer */ - *hptr; /* Pointer into hostname */ - cupsd_printer_t *p, /* Printer information */ - *pclass, /* Printer class */ - *first; /* First printer in class */ - int offset, /* Offset of name */ - len; /* Length of name */ - - - if (!ImplicitClasses || !Printers) - return; + if (BrowseLocalOptions) + snprintf(options, sizeof(options), " ipp-options=%s", BrowseLocalOptions); + else + options[0] = '\0'; /* - * Loop through all available printers and create classes as needed... + * Remove quotes from printer-info, printer-location, and + * printer-make-and-model attributes... */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers), len = 0, offset = 0, - update = 0, pclass = NULL, first = NULL; - p != NULL; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - /* - * Skip implicit classes... - */ - - if (p->type & CUPS_PRINTER_IMPLICIT) - { - len = 0; - continue; - } - - /* - * If len == 0, get the length of this printer name up to the "@" - * sign (if any). - */ + dequote(location, p->location, sizeof(p->location)); + dequote(info, p->info, sizeof(p->info)); + dequote(make_model, p->make_model ? p->make_model : "Unknown", + sizeof(make_model)); - cupsArraySave(Printers); + /* + * Send a packet to each browse address... + */ - if (len > 0 && - strncasecmp(p->name, name + offset, len) == 0 && - (p->name[len] == '\0' || p->name[len] == '@')) + for (i = NumBrowsers, b = Browsers; i > 0; i --, b ++) + if (b->iface[0]) { /* - * We have more than one printer with the same name; see if - * we have a class, and if this printer is a member... + * Send the browse packet to one or more interfaces... */ - if (pclass && strcasecmp(pclass->name, name)) - { - if (update) - cupsdSetPrinterAttrs(pclass); - - update = 0; - pclass = NULL; - } - - if (!pclass && (pclass = cupsdFindDest(name)) == NULL) + if (!strcmp(b->iface, "*")) { /* - * Need to add the class... + * Send to all local interfaces... */ - pclass = cupsdAddPrinter(name); - cupsArrayAdd(ImplicitPrinters, pclass); + cupsdNetIFUpdate(); - pclass->type |= CUPS_PRINTER_IMPLICIT; - pclass->accepting = 1; - pclass->state = IPP_PRINTER_IDLE; + for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); + iface; + iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) + { + /* + * Only send to local, IPv4 interfaces... + */ - cupsdSetString(&pclass->location, p->location); - cupsdSetString(&pclass->info, p->info); + if (!iface->is_local || !iface->port || + iface->address.addr.sa_family != AF_INET) + continue; - update = 1; + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + iface->hostname, iface->port, + (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s%s" : + "/printers/%s", + p->name); + snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"%s\n", + type, p->state, uri, location, info, make_model, options); - cupsdLogMessage(CUPSD_LOG_INFO, "Added implicit class \"%s\"...", - name); - } + bytes = strlen(packet); - if (first != NULL) + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes, + iface->name, packet); + + iface->broadcast.ipv4.sin_port = htons(BrowsePort); + + sendto(BrowseSocket, packet, bytes, 0, + (struct sockaddr *)&(iface->broadcast), + sizeof(struct sockaddr_in)); + } + } + else if ((iface = cupsdNetIFFind(b->iface)) != NULL) { - for (i = 0; i < pclass->num_printers; i ++) - if (pclass->printers[i] == first) + /* + * Send to the named interface using the IPv4 address... + */ + + while (iface) + if (strcmp(b->iface, iface->name)) + { + iface = NULL; break; + } + else if (iface->address.addr.sa_family == AF_INET && iface->port) + break; + else + iface = (cupsd_netif_t *)cupsArrayNext(NetIFList); - if (i >= pclass->num_printers) + if (iface) { - first->in_implicit_class = 1; - cupsdAddPrinterToClass(pclass, first); - } + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + iface->hostname, iface->port, + (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s%s" : + "/printers/%s", + p->name); + snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"%s\n", + type, p->state, uri, location, info, make_model, options); - first = NULL; - } + bytes = strlen(packet); - for (i = 0; i < pclass->num_printers; i ++) - if (pclass->printers[i] == p) - break; + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes, + iface->name, packet); - if (i >= pclass->num_printers) - { - p->in_implicit_class = 1; - cupsdAddPrinterToClass(pclass, p); - update = 1; + iface->broadcast.ipv4.sin_port = htons(BrowsePort); + + sendto(BrowseSocket, packet, bytes, 0, + (struct sockaddr *)&(iface->broadcast), + sizeof(struct sockaddr_in)); + } } } else { /* - * First time around; just get name length and mark it as first - * in the list... + * Send the browse packet to the indicated address using + * the default server name... */ - if ((hptr = strchr(p->name, '@')) != NULL) - len = hptr - p->name; - else - len = strlen(p->name); + snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"%s\n", + type, p->state, p->uri, location, info, make_model, options); - strncpy(name, p->name, len); - name[len] = '\0'; - offset = 0; + bytes = strlen(packet); + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdSendBrowseList: (%d bytes) %s", bytes, packet); - if ((first = (hptr ? cupsdFindDest(name) : p)) != NULL && - !(first->type & CUPS_PRINTER_IMPLICIT)) + if (sendto(BrowseSocket, packet, bytes, 0, + (struct sockaddr *)&(b->to), + sizeof(struct sockaddr_in)) <= 0) { /* - * Can't use same name as a local printer; add "Any" to the - * front of the name, unless we have explicitly disabled - * the "ImplicitAnyClasses"... + * Unable to send browse packet, so remove this address from the + * list... */ - if (ImplicitAnyClasses && len < (sizeof(name) - 4)) - { - /* - * Add "Any" to the class name... - */ - - strcpy(name, "Any"); - strncpy(name + 3, p->name, len); - name[len + 3] = '\0'; - offset = 3; - } - else - { - /* - * Don't create an implicit class if we have a local printer - * with the same name... - */ + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdSendBrowseList: sendto failed for browser %d - %s.", + b - Browsers + 1, strerror(errno)); - len = 0; - cupsArrayRestore(Printers); - continue; - } - } + if (i > 1) + memcpy(b, b + 1, (i - 1) * sizeof(cupsd_dirsvc_addr_t)); - first = p; + b --; + NumBrowsers --; + } } - - cupsArrayRestore(Printers); - } - - /* - * Update the last printer class as needed... - */ - - if (pclass && update) - cupsdSetPrinterAttrs(pclass); } +#ifdef HAVE_LIBSLP /* - * 'cupsdSaveRemoteCache()' - Save the remote printer cache. + * 'cupsdSendSLPBrowse()' - Register the specified printer with SLP. */ -void -cupsdSaveRemoteCache(void) +void +cupsdSendSLPBrowse(cupsd_printer_t *p) /* I - Printer to register */ { - int i; /* Looping var */ - cups_file_t *fp; /* printers.conf file */ - char temp[1024]; /* Temporary string */ - cupsd_printer_t *printer; /* Current printer class */ - time_t curtime; /* Current time */ - struct tm *curdate; /* Current date */ - - - /* - * Create the remote.cache file... - */ - - snprintf(temp, sizeof(temp), "%s/remote.cache", CacheDir); - - if ((fp = cupsFileOpen(temp, "w")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to save remote.cache - %s", strerror(errno)); - return; - } - else - cupsdLogMessage(CUPSD_LOG_INFO, "Saving remote.cache..."); + char srvurl[HTTP_MAX_URI], /* Printer service URI */ + attrs[8192], /* Printer attributes */ + finishings[1024], /* Finishings to support */ + make_model[IPP_MAX_NAME * 2], + /* Make and model, quoted */ + location[IPP_MAX_NAME * 2], + /* Location, quoted */ + info[IPP_MAX_NAME * 2], /* Info, quoted */ + *src, /* Pointer to original string */ + *dst; /* Pointer to destination string */ + ipp_attribute_t *authentication; /* uri-authentication-supported value */ + SLPError error; /* SLP error, if any */ - /* - * Restrict access to the file... - */ - fchown(cupsFileNumber(fp), getuid(), Group); - fchmod(cupsFileNumber(fp), ConfigFilePerm); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSendSLPBrowse(%p = \"%s\")", p, + p->name); /* - * Write a small header to the file... + * Make the SLP service URL that conforms to the IANA + * 'printer:' template. */ - curtime = time(NULL); - curdate = localtime(&curtime); - strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); + snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri); - cupsFilePuts(fp, "# Remote cache file for " CUPS_SVERSION "\n"); - cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "Service URL = \"%s\"", srvurl); /* - * Write each local printer known to the system... + * Figure out the finishings string... */ - for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers); - printer; - printer = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - /* - * Skip local destinations... - */ + if (p->type & CUPS_PRINTER_STAPLE) + strcpy(finishings, "staple"); + else + finishings[0] = '\0'; - if (!(printer->type & CUPS_PRINTER_REMOTE)) - continue; + if (p->type & CUPS_PRINTER_BIND) + { + if (finishings[0]) + strlcat(finishings, ",bind", sizeof(finishings)); + else + strcpy(finishings, "bind"); + } - /* - * Write printers as needed... - */ + if (p->type & CUPS_PRINTER_PUNCH) + { + if (finishings[0]) + strlcat(finishings, ",punch", sizeof(finishings)); + else + strcpy(finishings, "punch"); + } - if (printer == DefaultPrinter) - cupsFilePuts(fp, "type & CUPS_PRINTER_COVER) + { + if (finishings[0]) + strlcat(finishings, ",cover", sizeof(finishings)); else - cupsFilePutChar(fp, '<'); + strcpy(finishings, "cover"); + } - if (printer->type & CUPS_PRINTER_CLASS) - cupsFilePrintf(fp, "Class %s>\n", printer->name); + if (p->type & CUPS_PRINTER_SORT) + { + if (finishings[0]) + strlcat(finishings, ",sort", sizeof(finishings)); else - cupsFilePrintf(fp, "Printer %s>\n", printer->name); + strcpy(finishings, "sort"); + } - cupsFilePrintf(fp, "Type %d\n", printer->type); + if (!finishings[0]) + strcpy(finishings, "none"); - cupsFilePrintf(fp, "BrowseTime %d\n", (int)printer->browse_time); + /* + * Quote any commas in the make and model, location, and info strings... + */ - if (printer->info) - cupsFilePrintf(fp, "Info %s\n", printer->info); + for (src = p->make_model, dst = make_model; + src && *src && dst < (make_model + sizeof(make_model) - 2);) + { + if (*src == ',' || *src == '\\' || *src == ')') + *dst++ = '\\'; - if (printer->make_model) - cupsFilePrintf(fp, "MakeModel %s\n", printer->make_model); + *dst++ = *src++; + } - if (printer->location) - cupsFilePrintf(fp, "Location %s\n", printer->location); + *dst = '\0'; - if (printer->device_uri) - cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri); + if (!make_model[0]) + strcpy(make_model, "Unknown"); - if (printer->state == IPP_PRINTER_STOPPED) - { - cupsFilePuts(fp, "State Stopped\n"); - cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message); - } - else - cupsFilePuts(fp, "State Idle\n"); + for (src = p->location, dst = location; + src && *src && dst < (location + sizeof(location) - 2);) + { + if (*src == ',' || *src == '\\' || *src == ')') + *dst++ = '\\'; - if (printer->accepting) - cupsFilePuts(fp, "Accepting Yes\n"); - else - cupsFilePuts(fp, "Accepting No\n"); + *dst++ = *src++; + } - cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0], - printer->job_sheets[1]); + *dst = '\0'; - for (i = 0; i < printer->num_users; i ++) - cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow", - printer->users[i]); + if (!location[0]) + strcpy(location, "Unknown"); - if (printer->type & CUPS_PRINTER_CLASS) - cupsFilePuts(fp, "\n"); - else - cupsFilePuts(fp, "\n"); - } + for (src = p->info, dst = info; + src && *src && dst < (info + sizeof(info) - 2);) + { + if (*src == ',' || *src == '\\' || *src == ')') + *dst++ = '\\'; - cupsFileClose(fp); -} + *dst++ = *src++; + } + *dst = '\0'; -/* - * 'cupsdSendBrowseDelete()' - Send a "browse delete" message for a printer. - */ + if (!info[0]) + strcpy(info, "Unknown"); -void -cupsdSendBrowseDelete( - cupsd_printer_t *p) /* I - Printer to delete */ -{ /* - * Only announce if browsing is enabled... + * Get the authentication value... */ - if (!Browsing || !p->shared) - return; + authentication = ippFindAttribute(p->attrs, "uri-authentication-supported", + IPP_TAG_KEYWORD); /* - * First mark the printer for deletion... + * Make the SLP attribute string list that conforms to + * the IANA 'printer:' template. */ - p->type |= CUPS_PRINTER_DELETE; + snprintf(attrs, sizeof(attrs), + "(printer-uri-supported=%s)," + "(uri-authentication-supported=%s>)," +#ifdef HAVE_SSL + "(uri-security-supported=tls>)," +#else + "(uri-security-supported=none>)," +#endif /* HAVE_SSL */ + "(printer-name=%s)," + "(printer-location=%s)," + "(printer-info=%s)," + "(printer-more-info=%s)," + "(printer-make-and-model=%s)," + "(charset-supported=utf-8)," + "(natural-language-configured=%s)," + "(natural-language-supported=de,en,es,fr,it)," + "(color-supported=%s)," + "(finishings-supported=%s)," + "(sides-supported=one-sided%s)," + "(multiple-document-jobs-supported=true)" + "(ipp-versions-supported=1.0,1.1)", + p->uri, authentication->values[0].string.text, p->name, location, + info, p->uri, make_model, DefaultLanguage, + p->type & CUPS_PRINTER_COLOR ? "true" : "false", + finishings, + p->type & CUPS_PRINTER_DUPLEX ? + ",two-sided-long-edge,two-sided-short-edge" : ""); + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "Attributes = \"%s\"", attrs); /* - * Announce the deletion... + * Register the printer with the SLP server... */ - if (BrowseLocalProtocols & BROWSE_CUPS) - cupsdSendCUPSBrowse(p); -#ifdef HAVE_LIBSLP - if (BrowseLocalProtocols & BROWSE_SLP) - slp_dereg_printer(p); -#endif /* HAVE_LIBSLP */ -} - + error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout, + SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, slp_reg_callback, 0); -/* - * 'cupsdSendBrowseList()' - Send new browsing information as necessary. + if (error != SLP_OK) + cupsdLogMessage(CUPSD_LOG_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name, + error); +} +#endif /* HAVE_LIBSLP */ + + +/* + * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information. */ void -cupsdSendBrowseList(void) +cupsdStartBrowsing(void) { - int count; /* Number of dests to update */ - cupsd_printer_t *p; /* Current printer */ - time_t ut, /* Minimum update time */ - to; /* Timeout time */ + int val; /* Socket option value */ + struct sockaddr_in addr; /* Broadcast address */ - if (!Browsing || !BrowseLocalProtocols || !Printers) - return; + BrowseNext = NULL; - /* - * Compute the update and timeout times... - */ + if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols)) + return; - ut = time(NULL) - BrowseInterval; - to = time(NULL) - BrowseTimeout; + if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) + { + if (BrowseSocket < 0) + { + /* + * Create the broadcast socket... + */ - /* - * Figure out how many printers need an update... - */ + if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdStartBrowsing: Unable to create broadcast " + "socket - %s.", strerror(errno)); + BrowseLocalProtocols &= ~BROWSE_CUPS; + BrowseRemoteProtocols &= ~BROWSE_CUPS; + return; + } - if (BrowseInterval > 0) - { - int max_count; /* Maximum number to update */ + /* + * Bind the socket to browse port... + */ + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_family = AF_INET; + addr.sin_port = htons(BrowsePort); - /* - * Throttle the number of printers we'll be updating this time - * around based on the number of queues that need updating and - * the maximum number of queues to update each second... - */ + if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr))) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdStartBrowsing: Unable to bind broadcast " + "socket - %s.", strerror(errno)); - max_count = 2 * cupsArrayCount(Printers) / BrowseInterval + 1; +#ifdef WIN32 + closesocket(BrowseSocket); +#else + close(BrowseSocket); +#endif /* WIN32 */ - for (count = 0, p = (cupsd_printer_t *)cupsArrayFirst(Printers); - count < max_count && p != NULL; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) && - p->shared && p->browse_time < ut) - count ++; + BrowseSocket = -1; + BrowseLocalProtocols &= ~BROWSE_CUPS; + BrowseRemoteProtocols &= ~BROWSE_CUPS; + return; + } + } /* - * Loop through all of the printers and send local updates as needed... + * Set the "broadcast" flag... */ - if (BrowseNext) - p = (cupsd_printer_t *)cupsArrayFind(Printers, BrowseNext); - else - p = (cupsd_printer_t *)cupsArrayFirst(Printers); - - for (; - count > 0; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) + val = 1; + if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) { - /* - * Check for wraparound... - */ - - if (!p) - p = (cupsd_printer_t *)cupsArrayFirst(Printers); - - if (!p) - break; - else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) || - !p->shared) - continue; - else if (p->browse_time < ut) - { - /* - * Need to send an update... - */ + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdStartBrowsing: Unable to set broadcast mode - %s.", + strerror(errno)); - count --; +#ifdef WIN32 + closesocket(BrowseSocket); +#else + close(BrowseSocket); +#endif /* WIN32 */ - p->browse_time = time(NULL); + BrowseSocket = -1; + BrowseLocalProtocols &= ~BROWSE_CUPS; + BrowseRemoteProtocols &= ~BROWSE_CUPS; + return; + } - if (BrowseLocalProtocols & BROWSE_CUPS) - cupsdSendCUPSBrowse(p); + /* + * Close the socket on exec... + */ -#ifdef HAVE_LIBSLP - if (BrowseLocalProtocols & BROWSE_SLP) - cupsdSendSLPBrowse(p); -#endif /* HAVE_LIBSLP */ - } - } + fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC); /* - * Save where we left off so that all printers get updated... + * Finally, add the socket to the input selection set... */ - BrowseNext = p; - } + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdStartBrowsing: Adding fd %d to InputSet...", + BrowseSocket); - /* - * Loop through all of the printers and send local updates as needed... - */ + FD_SET(BrowseSocket, InputSet); + } + else + BrowseSocket = -1; - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) +#ifdef HAVE_LIBSLP + if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) { - /* - * If this is a remote queue, see if it needs to be timed out... + /* + * Open SLP handle... */ - if (p->type & CUPS_PRINTER_REMOTE) + if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK) { - if (p->browse_time < to) - { - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "%s \'%s\' deleted by directory services (timeout).", - (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer", - p->name); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Remote destination \"%s\" has timed out; deleting it...", - p->name); - - cupsArraySave(Printers); - cupsdDeletePrinter(p, 1); - cupsArrayRestore(Printers); - } + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to open an SLP handle; disabling SLP browsing!"); + BrowseLocalProtocols &= ~BROWSE_SLP; + BrowseRemoteProtocols &= ~BROWSE_SLP; } + + BrowseSLPRefresh = 0; } +#endif /* HAVE_LIBSLP */ } /* - * 'cupsdSendCUPSBrowse()' - Send new browsing information using the CUPS protocol. + * 'cupsdStartPolling()' - Start polling servers as needed. */ void -cupsdSendCUPSBrowse(cupsd_printer_t *p) /* I - Printer to send */ +cupsdStartPolling(void) { int i; /* Looping var */ - cups_ptype_t type; /* Printer type */ - cupsd_dirsvc_addr_t *b; /* Browse address */ - int bytes; /* Length of packet */ - char packet[1453]; /* Browse data packet */ - char uri[1024]; /* Printer URI */ - char options[1024]; /* Browse local options */ - cupsd_netif_t *iface; /* Network interface */ + cupsd_dirsvc_poll_t *pollp; /* Current polling server */ + char polld[1024]; /* Poll daemon path */ + char sport[10]; /* Server port */ + char bport[10]; /* Browser port */ + char interval[10]; /* Poll interval */ + int statusfds[2]; /* Status pipe */ + char *argv[6]; /* Arguments */ + char *envp[100]; /* Environment */ /* - * Figure out the printer type value... + * Don't do anything if we aren't polling... */ - type = p->type | CUPS_PRINTER_REMOTE; - - if (!p->accepting) - type |= CUPS_PRINTER_REJECTING; + if (NumPolled == 0) + { + PollPipe = -1; + PollStatusBuffer = NULL; + return; + } /* - * Initialize the browse options... + * Setup string arguments for polld, port and interval options. */ - if (BrowseLocalOptions) - snprintf(options, sizeof(options), " ipp-options=%s", BrowseLocalOptions); - else - options[0] = '\0'; + snprintf(polld, sizeof(polld), "%s/daemon/cups-polld", ServerBin); - /* - * Send a packet to each browse address... - */ + sprintf(bport, "%d", BrowsePort); - for (i = NumBrowsers, b = Browsers; i > 0; i --, b ++) - if (b->iface[0]) - { - /* - * Send the browse packet to one or more interfaces... - */ + if (BrowseInterval) + sprintf(interval, "%d", BrowseInterval); + else + strcpy(interval, "30"); - if (strcmp(b->iface, "*") == 0) - { - /* - * Send to all local interfaces... - */ + argv[0] = "cups-polld"; + argv[2] = sport; + argv[3] = interval; + argv[4] = bport; + argv[5] = NULL; - cupsdNetIFUpdate(); + cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); - for (iface = NetIFList; iface != NULL; iface = iface->next) - { - /* - * Only send to local, IPv4 interfaces... - */ + /* + * Create a pipe that receives the status messages from each + * polling daemon... + */ - if (!iface->is_local || !iface->port || - iface->address.addr.sa_family != AF_INET) - continue; - - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - iface->hostname, iface->port, - (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s%s" : - "/printers/%s", - p->name); - snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"%s\n", - type, p->state, uri, p->location ? p->location : "", - p->info ? p->info : "", - p->make_model ? p->make_model : "Unknown", options); - - bytes = strlen(packet); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes, - iface->name, packet); - - iface->broadcast.ipv4.sin_port = htons(BrowsePort); - - sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(iface->broadcast), - sizeof(struct sockaddr_in)); - } - } - else if ((iface = cupsdNetIFFind(b->iface)) != NULL) - { - /* - * Send to the named interface using the IPv4 address... - */ - - while (iface) - if (strcasecmp(b->iface, iface->name)) - { - iface = NULL; - break; - } - else if (iface->address.addr.sa_family == AF_INET && iface->port) - break; - else - iface = iface->next; + if (cupsdOpenPipe(statusfds)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to create polling status pipes - %s.", + strerror(errno)); + PollPipe = -1; + PollStatusBuffer = NULL; + return; + } - if (iface) - { - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - iface->hostname, iface->port, - (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s%s" : - "/printers/%s", - p->name); - snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"%s\n", - type, p->state, uri, p->location ? p->location : "", - p->info ? p->info : "", - p->make_model ? p->make_model : "Unknown", options); + PollPipe = statusfds[0]; + PollStatusBuffer = cupsdStatBufNew(PollPipe, "[Poll]"); - bytes = strlen(packet); + /* + * Run each polling daemon, redirecting stderr to the polling pipe... + */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes, - iface->name, packet); + for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) + { + sprintf(sport, "%d", pollp->port); - iface->broadcast.ipv4.sin_port = htons(BrowsePort); + argv[1] = pollp->hostname; - sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(iface->broadcast), - sizeof(struct sockaddr_in)); - } - } + if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, + 0, &(pollp->pid)) < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdStartPolling: Unable to fork polling daemon - %s", + strerror(errno)); + pollp->pid = 0; + break; } else - { - /* - * Send the browse packet to the indicated address using - * the default server name... - */ - - snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"%s\n", - type, p->state, p->uri, - p->location ? p->location : "", - p->info ? p->info : "", - p->make_model ? p->make_model : "Unknown", options); - - bytes = strlen(packet); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendBrowseList: (%d bytes) %s", bytes, packet); + cupsdLogMessage(CUPSD_LOG_DEBUG, + "cupsdStartPolling: Started polling daemon for %s:%d, pid = %d", + pollp->hostname, pollp->port, pollp->pid); + } - if (sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(b->to), - sizeof(struct sockaddr_in)) <= 0) - { - /* - * Unable to send browse packet, so remove this address from the - * list... - */ + close(statusfds[1]); - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdSendBrowseList: sendto failed for browser %d - %s.", - b - Browsers + 1, strerror(errno)); + /* + * Finally, add the pipe to the input selection set... + */ - if (i > 1) - memcpy(b, b + 1, (i - 1) * sizeof(cupsd_dirsvc_addr_t)); + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdStartPolling: Adding fd %d to InputSet...", PollPipe); - b --; - NumBrowsers --; - } - } + FD_SET(PollPipe, InputSet); } -#ifdef HAVE_LIBSLP /* - * 'cupsdSendSLPBrowse()' - Register the specified printer with SLP. + * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information. */ -void -cupsdSendSLPBrowse(cupsd_printer_t *p) /* I - Printer to register */ +void +cupsdStopBrowsing(void) { - char srvurl[HTTP_MAX_URI], /* Printer service URI */ - attrs[8192], /* Printer attributes */ - finishings[1024], /* Finishings to support */ - make_model[IPP_MAX_NAME * 2], - /* Make and model, quoted */ - location[IPP_MAX_NAME * 2], - /* Location, quoted */ - info[IPP_MAX_NAME * 2], /* Info, quoted */ - *src, /* Pointer to original string */ - *dst; /* Pointer to destination string */ - ipp_attribute_t *authentication; /* uri-authentication-supported value */ - SLPError error; /* SLP error, if any */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSendSLPBrowse(%p = \"%s\")", p, - p->name); - - /* - * Make the SLP service URL that conforms to the IANA - * 'printer:' template. - */ - - snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri); + if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols)) + return; - cupsdLogMessage(CUPSD_LOG_DEBUG2, "Service URL = \"%s\"", srvurl); + if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) && + BrowseSocket >= 0) + { + /* + * Close the socket and remove it from the input selection set. + */ - /* - * Figure out the finishings string... - */ +#ifdef WIN32 + closesocket(BrowseSocket); +#else + close(BrowseSocket); +#endif /* WIN32 */ - if (p->type & CUPS_PRINTER_STAPLE) - strcpy(finishings, "staple"); - else - finishings[0] = '\0'; + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdStopBrowsing: Removing fd %d from InputSet...", + BrowseSocket); - if (p->type & CUPS_PRINTER_BIND) - { - if (finishings[0]) - strlcat(finishings, ",bind", sizeof(finishings)); - else - strcpy(finishings, "bind"); + FD_CLR(BrowseSocket, InputSet); + BrowseSocket = -1; } - if (p->type & CUPS_PRINTER_PUNCH) +#ifdef HAVE_LIBSLP + if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) { - if (finishings[0]) - strlcat(finishings, ",punch", sizeof(finishings)); - else - strcpy(finishings, "punch"); - } + /* + * Close SLP handle... + */ - if (p->type & CUPS_PRINTER_COVER) - { - if (finishings[0]) - strlcat(finishings, ",cover", sizeof(finishings)); - else - strcpy(finishings, "cover"); + SLPClose(BrowseSLPHandle); } +#endif /* HAVE_LIBSLP */ +} - if (p->type & CUPS_PRINTER_SORT) - { - if (finishings[0]) - strlcat(finishings, ",sort", sizeof(finishings)); - else - strcpy(finishings, "sort"); - } - if (!finishings[0]) - strcpy(finishings, "none"); +/* + * 'cupsdStopPolling()' - Stop polling servers as needed. + */ - /* - * Quote any commas in the make and model, location, and info strings... - */ +void +cupsdStopPolling(void) +{ + int i; /* Looping var */ + cupsd_dirsvc_poll_t *pollp; /* Current polling server */ - for (src = p->make_model, dst = make_model; - src && *src && dst < (make_model + sizeof(make_model) - 2);) + + if (PollPipe >= 0) { - if (*src == ',' || *src == '\\' || *src == ')') - *dst++ = '\\'; + cupsdStatBufDelete(PollStatusBuffer); + close(PollPipe); - *dst++ = *src++; - } + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdStopPolling: removing fd %d from InputSet.", PollPipe); + FD_CLR(PollPipe, InputSet); - *dst = '\0'; + PollPipe = -1; + PollStatusBuffer = NULL; + } - if (!make_model[0]) - strcpy(make_model, "Unknown"); + for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) + if (pollp->pid) + cupsdEndProcess(pollp->pid, 0); +} - for (src = p->location, dst = location; - src && *src && dst < (location + sizeof(location) - 2);) - { - if (*src == ',' || *src == '\\' || *src == ')') - *dst++ = '\\'; - *dst++ = *src++; - } +/* + * 'cupsdUpdateCUPSBrowse()' - Update the browse lists using the CUPS protocol. + */ - *dst = '\0'; +void +cupsdUpdateCUPSBrowse(void) +{ + int i; /* Looping var */ + int auth; /* Authorization status */ + int len; /* Length of name string */ + int bytes; /* Number of bytes left */ + char packet[1541], /* Broadcast packet */ + *pptr; /* Pointer into packet */ + socklen_t srclen; /* Length of source address */ + http_addr_t srcaddr; /* Source address */ + char srcname[1024]; /* Source hostname */ + unsigned address[4]; /* Source address */ + unsigned type; /* Printer type */ + unsigned state; /* Printer state */ + char uri[HTTP_MAX_URI], /* Printer URI */ + method[HTTP_MAX_URI], /* Method portion of URI */ + username[HTTP_MAX_URI], /* Username portion of URI */ + host[HTTP_MAX_URI], /* Host portion of URI */ + resource[HTTP_MAX_URI], /* Resource portion of URI */ + info[IPP_MAX_NAME], /* Information string */ + location[IPP_MAX_NAME], /* Location string */ + make_model[IPP_MAX_NAME];/* Make and model string */ + int port; /* Port portion of URI */ + cupsd_netif_t *iface; /* Network interface */ + int num_attrs; /* Number of attributes */ + cups_option_t *attrs; /* Attributes */ - if (!location[0]) - strcpy(location, "Unknown"); - for (src = p->info, dst = info; - src && *src && dst < (info + sizeof(info) - 2);) - { - if (*src == ',' || *src == '\\' || *src == ')') - *dst++ = '\\'; + /* + * Read a packet from the browse socket... + */ - *dst++ = *src++; - } + srclen = sizeof(srcaddr); + if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0, + (struct sockaddr *)&srcaddr, &srclen)) < 0) + { + /* + * "Connection refused" is returned under Linux if the destination port + * or address is unreachable from a previous sendto(); check for the + * error here and ignore it for now... + */ - *dst = '\0'; + if (errno != ECONNREFUSED && errno != EAGAIN) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Browse recv failed - %s.", + strerror(errno)); + cupsdLogMessage(CUPSD_LOG_ERROR, "Browsing turned off."); - if (!info[0]) - strcpy(info, "Unknown"); + cupsdStopBrowsing(); + Browsing = 0; + } - /* - * Get the authentication value... - */ + return; + } - authentication = ippFindAttribute(p->attrs, "uri-authentication-supported", - IPP_TAG_KEYWORD); + packet[bytes] = '\0'; /* - * Make the SLP attribute string list that conforms to - * the IANA 'printer:' template. + * If we're about to sleep, ignore incoming browse packets. */ - snprintf(attrs, sizeof(attrs), - "(printer-uri-supported=%s)," - "(uri-authentication-supported=%s>)," -#ifdef HAVE_SSL - "(uri-security-supported=tls>)," -#else - "(uri-security-supported=none>)," -#endif /* HAVE_SSL */ - "(printer-name=%s)," - "(printer-location=%s)," - "(printer-info=%s)," - "(printer-more-info=%s)," - "(printer-make-and-model=%s)," - "(charset-supported=utf-8)," - "(natural-language-configured=%s)," - "(natural-language-supported=de,en,es,fr,it)," - "(color-supported=%s)," - "(finishings-supported=%s)," - "(sides-supported=one-sided%s)," - "(multiple-document-jobs-supported=true)" - "(ipp-versions-supported=1.0,1.1)", - p->uri, authentication->values[0].string.text, p->name, location, - info, p->uri, make_model, DefaultLanguage, - p->type & CUPS_PRINTER_COLOR ? "true" : "false", - finishings, - p->type & CUPS_PRINTER_DUPLEX ? - ",two-sided-long-edge,two-sided-short-edge" : ""); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "Attributes = \"%s\"", attrs); + if (Sleeping) + return; /* - * Register the printer with the SLP server... + * Figure out where it came from... */ - error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout, - SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, slp_reg_callback, 0); - - if (error != SLP_OK) - cupsdLogMessage(CUPSD_LOG_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name, - error); -} -#endif /* HAVE_LIBSLP */ - - -/* - * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information. - */ - -void -cupsdStartBrowsing(void) -{ - int val; /* Socket option value */ - struct sockaddr_in addr; /* Broadcast address */ +#ifdef AF_INET6 + if (srcaddr.addr.sa_family == AF_INET6) + { + address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]); + address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]); + address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]); + address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]); + } + else +#endif /* AF_INET6 */ + { + address[0] = 0; + address[1] = 0; + address[2] = 0; + address[3] = ntohl(srcaddr.ipv4.sin_addr.s_addr); + } + if (HostNameLookups) + httpAddrLookup(&srcaddr, srcname, sizeof(srcname)); + else + httpAddrString(&srcaddr, srcname, sizeof(srcname)); - BrowseNext = NULL; + len = strlen(srcname); - if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols)) - return; + /* + * Do ACL stuff... + */ - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) + if (BrowseACL) { - if (BrowseSocket < 0) + if (httpAddrLocalhost(&srcaddr) || !strcasecmp(srcname, "localhost")) { /* - * Create the broadcast socket... + * Access from localhost (127.0.0.1) is always allowed... */ - if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdStartBrowsing: Unable to create broadcast " - "socket - %s.", strerror(errno)); - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - return; - } - + auth = AUTH_ALLOW; + } + else + { /* - * Bind the socket to browse port... + * Do authorization checks on the domain/address... */ - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_family = AF_INET; - addr.sin_port = htons(BrowsePort); - - if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr))) + switch (BrowseACL->order_type) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdStartBrowsing: Unable to bind broadcast " - "socket - %s.", strerror(errno)); + default : + auth = AUTH_DENY; /* anti-compiler-warning-code */ + break; -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ + case AUTH_ALLOW : /* Order Deny,Allow */ + auth = AUTH_ALLOW; - BrowseSocket = -1; - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - return; - } - } + if (cupsdCheckAuth(address, srcname, len, + BrowseACL->num_deny, BrowseACL->deny)) + auth = AUTH_DENY; - /* - * Set the "broadcast" flag... - */ + if (cupsdCheckAuth(address, srcname, len, + BrowseACL->num_allow, BrowseACL->allow)) + auth = AUTH_ALLOW; + break; - val = 1; - if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdStartBrowsing: Unable to set broadcast mode - %s.", - strerror(errno)); + case AUTH_DENY : /* Order Allow,Deny */ + auth = AUTH_DENY; -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ + if (cupsdCheckAuth(address, srcname, len, + BrowseACL->num_allow, BrowseACL->allow)) + auth = AUTH_ALLOW; - BrowseSocket = -1; - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - return; + if (cupsdCheckAuth(address, srcname, len, + BrowseACL->num_deny, BrowseACL->deny)) + auth = AUTH_DENY; + break; + } } - - /* - * Close the socket on exec... - */ - - fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC); - - /* - * Finally, add the socket to the input selection set... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStartBrowsing: Adding fd %d to InputSet...", - BrowseSocket); - - FD_SET(BrowseSocket, InputSet); } else - BrowseSocket = -1; + auth = AUTH_ALLOW; -#ifdef HAVE_LIBSLP - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) + if (auth == AUTH_DENY) { - /* - * Open SLP handle... - */ - - if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to open an SLP handle; disabling SLP browsing!"); - BrowseLocalProtocols &= ~BROWSE_SLP; - BrowseRemoteProtocols &= ~BROWSE_SLP; - } - - BrowseSLPRefresh = 0; + cupsdLogMessage(CUPSD_LOG_DEBUG, + "cupsdUpdateCUPSBrowse: Refused %d bytes from %s", bytes, + srcname); + return; } -#endif /* HAVE_LIBSLP */ -} - - -/* - * 'cupsdStartPolling()' - Start polling servers as needed. - */ - -void -cupsdStartPolling(void) -{ - int i; /* Looping var */ - cupsd_dirsvc_poll_t *pollp; /* Current polling server */ - char polld[1024]; /* Poll daemon path */ - char sport[10]; /* Server port */ - char bport[10]; /* Browser port */ - char interval[10]; /* Poll interval */ - int statusfds[2]; /* Status pipe */ - char *argv[6]; /* Arguments */ - char *envp[100]; /* Environment */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "cupsdUpdateCUPSBrowse: (%d bytes from %s) %s", bytes, + srcname, packet); /* - * Don't do anything if we aren't polling... + * Parse packet... */ - if (NumPolled == 0) + if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3) { - PollPipe = -1; - PollStatusBuffer = NULL; + cupsdLogMessage(CUPSD_LOG_WARN, + "cupsdUpdateCUPSBrowse: Garbled browse packet - %s", packet); return; } - /* - * Setup string arguments for polld, port and interval options. - */ + strcpy(location, "Location Unknown"); + strcpy(info, "No Information Available"); + make_model[0] = '\0'; + num_attrs = 0; + attrs = NULL; - snprintf(polld, sizeof(polld), "%s/daemon/cups-polld", ServerBin); + if ((pptr = strchr(packet, '\"')) != NULL) + { + /* + * Have extended information; can't use sscanf for it because not all + * sscanf's allow empty strings with %[^\"]... + */ - sprintf(bport, "%d", BrowsePort); + for (i = 0, pptr ++; + i < (sizeof(location) - 1) && *pptr && *pptr != '\"'; + i ++, pptr ++) + location[i] = *pptr; - if (BrowseInterval) - sprintf(interval, "%d", BrowseInterval); - else - strcpy(interval, "30"); + if (i) + location[i] = '\0'; - argv[0] = "cups-polld"; - argv[2] = sport; - argv[3] = interval; - argv[4] = bport; - argv[5] = NULL; + if (*pptr == '\"') + pptr ++; - cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); + while (*pptr && isspace(*pptr & 255)) + pptr ++; + + if (*pptr == '\"') + { + for (i = 0, pptr ++; + i < (sizeof(info) - 1) && *pptr && *pptr != '\"'; + i ++, pptr ++) + info[i] = *pptr; + + info[i] = '\0'; + + if (*pptr == '\"') + pptr ++; + + while (*pptr && isspace(*pptr & 255)) + pptr ++; + + if (*pptr == '\"') + { + for (i = 0, pptr ++; + i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"'; + i ++, pptr ++) + make_model[i] = *pptr; + + if (*pptr == '\"') + pptr ++; + + make_model[i] = '\0'; + + if (*pptr) + num_attrs = cupsParseOptions(pptr, num_attrs, &attrs); + } + } + } + + DEBUG_puts(packet); + DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n" + "location=\"%s\", info=\"%s\", make_model=\"%s\"\n", + type, state, uri, location, info, make_model)); /* - * Create a pipe that receives the status messages from each - * polling daemon... + * Pull the URI apart to see if this is a local or remote printer... */ - if (cupsdOpenPipe(statusfds)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create polling status pipes - %s.", - strerror(errno)); - PollPipe = -1; - PollStatusBuffer = NULL; - return; - } + httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), username, + sizeof(username), host, sizeof(host), &port, resource, + sizeof(resource)); - PollPipe = statusfds[0]; - PollStatusBuffer = cupsdStatBufNew(PollPipe, "[Poll]"); + DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName)); /* - * Run each polling daemon, redirecting stderr to the polling pipe... + * Check for packets from the local server... */ - for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) + if (!strcasecmp(host, ServerName) && port == LocalPort) { - sprintf(sport, "%d", pollp->port); + cupsFreeOptions(num_attrs, attrs); + return; + } - argv[1] = pollp->hostname; + cupsdNetIFUpdate(); - if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, - 0, &(pollp->pid)) < 0) + for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); + iface; + iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) + if (!strcasecmp(host, iface->hostname) && port == iface->port) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdStartPolling: Unable to fork polling daemon - %s", - strerror(errno)); - pollp->pid = 0; - break; + cupsFreeOptions(num_attrs, attrs); + return; } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdStartPolling: Started polling daemon for %s:%d, pid = %d", - pollp->hostname, pollp->port, pollp->pid); - } - - close(statusfds[1]); /* - * Finally, add the pipe to the input selection set... + * Do relaying... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStartPolling: Adding fd %d to InputSet...", PollPipe); + for (i = 0; i < NumRelays; i ++) + if (cupsdCheckAuth(address, srcname, len, 1, &(Relays[i].from))) + if (sendto(BrowseSocket, packet, bytes, 0, + (struct sockaddr *)&(Relays[i].to), + sizeof(http_addr_t)) <= 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdUpdateCUPSBrowse: sendto failed for relay %d - %s.", + i + 1, strerror(errno)); + cupsFreeOptions(num_attrs, attrs); + return; + } - FD_SET(PollPipe, InputSet); + /* + * Process the browse data... + */ + + process_browse_data(uri, (cups_ptype_t)type, (ipp_pstate_t)state, location, + info, make_model, num_attrs, attrs); + cupsFreeOptions(num_attrs, attrs); } /* - * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information. + * 'cupsdUpdatePolling()' - Read status messages from the poll daemons. */ void -cupsdStopBrowsing(void) +cupsdUpdatePolling(void) { - if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols)) - return; - - if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) && - BrowseSocket >= 0) - { - /* - * Close the socket and remove it from the input selection set. - */ - -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ + char *ptr, /* Pointer to end of line in buffer */ + message[1024]; /* Pointer to message text */ + int loglevel; /* Log level for message */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStopBrowsing: Removing fd %d from InputSet...", - BrowseSocket); - FD_CLR(BrowseSocket, InputSet); - BrowseSocket = -1; - } + while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel, + message, sizeof(message))) != NULL) + if (!strchr(PollStatusBuffer->buffer, '\n')) + break; -#ifdef HAVE_LIBSLP - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) + if (ptr == NULL) { - /* - * Close SLP handle... + /* + * All polling processes have died; stop polling... */ - SLPClose(BrowseSLPHandle); + cupsdLogMessage(CUPSD_LOG_ERROR, + "cupsdUpdatePolling: all polling processes have exited!"); + cupsdStopPolling(); } -#endif /* HAVE_LIBSLP */ } +#ifdef HAVE_LIBSLP /* - * 'cupsdStopPolling()' - Stop polling servers as needed. + * 'cupsdUpdateSLPBrowse()' - Get browsing information via SLP. */ void -cupsdStopPolling(void) +cupsdUpdateSLPBrowse(void) { - int i; /* Looping var */ - cupsd_dirsvc_poll_t *pollp; /* Current polling server */ + slpsrvurl_t *s, /* Temporary list of service URLs */ + *next; /* Next service in list */ + cupsd_printer_t p; /* Printer information */ + const char *uri; /* Pointer to printer URI */ + char method[HTTP_MAX_URI], + /* Method portion of URI */ + username[HTTP_MAX_URI], + /* Username portion of URI */ + host[HTTP_MAX_URI], + /* Host portion of URI */ + resource[HTTP_MAX_URI]; + /* Resource portion of URI */ + int port; /* Port portion of URI */ - if (PollPipe >= 0) - { - cupsdStatBufDelete(PollStatusBuffer); - close(PollPipe); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdUpdateSLPBrowse() Start..."); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdStopPolling: removing fd %d from InputSet.", PollPipe); - FD_CLR(PollPipe, InputSet); + /* + * Reset the refresh time... + */ - PollPipe = -1; - PollStatusBuffer = NULL; + BrowseSLPRefresh = time(NULL) + BrowseInterval; + + /* + * Poll for remote printers using SLP... + */ + + s = NULL; + + SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "", + slp_url_callback, &s); + + /* + * Loop through the list of available printers... + */ + + for (; s; s = next) + { + /* + * Save the "next" pointer... + */ + + next = s->next; + + /* + * Load a cupsd_printer_t structure with the SLP service attributes... + */ + + SLPFindAttrs(BrowseSLPHandle, s->url, "", "", slp_attr_callback, &p); + + /* + * Process this printer entry... + */ + + uri = s->url + SLP_CUPS_SRVLEN + 1; + + if (!strncmp(uri, "http://", 7) || !strncmp(uri, "ipp://", 6)) + { + /* + * Pull the URI apart to see if this is a local or remote printer... + */ + + httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), + username, sizeof(username), host, sizeof(host), &port, + resource, sizeof(resource)); + + if (!strcasecmp(host, ServerName)) + continue; + + /* + * OK, at least an IPP printer, see if it is a CUPS printer or + * class... + */ + + if (strstr(uri, "/printers/") != NULL) + process_browse_data(uri, p.type, IPP_PRINTER_IDLE, p.location, + p.info, p.make_model, 0, NULL); + else if (strstr(uri, "/classes/") != NULL) + process_browse_data(uri, p.type | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE, + p.location, p.info, p.make_model, 0, NULL); + } + + /* + * Free this listing... + */ + + free(s); + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdUpdateSLPBrowse() End..."); +} +#endif /* HAVE_LIBSLP */ + + +/* + * 'dequote()' - Remote quotes from a string. + */ + +static char * /* O - Dequoted string */ +dequote(char *d, /* I - Destination string */ + const char *s, /* I - Source string */ + int dlen) /* I - Destination length */ +{ + char *dptr; /* Pointer into destination */ + + + if (s) + { + for (dptr = d, dlen --; *s && dlen > 0; s ++) + if (*s != '\"') + { + *dptr++ = *s; + dlen --; + } + + *dptr = '\0'; } + else + *d = '\0'; - for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) - if (pollp->pid) - cupsdEndProcess(pollp->pid, 0); + return (d); } /* - * 'cupsdUpdateCUPSBrowse()' - Update the browse lists using the CUPS protocol. + * 'process_browse_data()' - Process new browse data. */ -void -cupsdUpdateCUPSBrowse(void) +static void +process_browse_data( + const char *uri, /* I - URI of printer/class */ + cups_ptype_t type, /* I - Printer type */ + ipp_pstate_t state, /* I - Printer state */ + const char *location, /* I - Printer location */ + const char *info, /* I - Printer information */ + const char *make_model, /* I - Printer make and model */ + int num_attrs, /* I - Number of attributes */ + cups_option_t *attrs) /* I - Attributes */ { - int i; /* Looping var */ - int auth; /* Authorization status */ - int len; /* Length of name string */ - int bytes; /* Number of bytes left */ - char packet[1541], /* Broadcast packet */ - *pptr; /* Pointer into packet */ - socklen_t srclen; /* Length of source address */ - http_addr_t srcaddr; /* Source address */ - char srcname[1024]; /* Source hostname */ - unsigned address[4]; /* Source address */ - unsigned type; /* Printer type */ - unsigned state; /* Printer state */ - char uri[HTTP_MAX_URI], /* Printer URI */ + int update; /* Update printer attributes? */ + char finaluri[HTTP_MAX_URI], /* Final URI for printer */ method[HTTP_MAX_URI], /* Method portion of URI */ username[HTTP_MAX_URI], /* Username portion of URI */ host[HTTP_MAX_URI], /* Host portion of URI */ - resource[HTTP_MAX_URI], /* Resource portion of URI */ - info[IPP_MAX_NAME], /* Information string */ - location[IPP_MAX_NAME], /* Location string */ - make_model[IPP_MAX_NAME];/* Make and model string */ + resource[HTTP_MAX_URI]; /* Resource portion of URI */ int port; /* Port portion of URI */ - cupsd_netif_t *iface; /* Network interface */ - int num_attrs; /* Number of attributes */ - cups_option_t *attrs; /* Attributes */ + char name[IPP_MAX_NAME], /* Name of printer */ + *hptr, /* Pointer into hostname */ + *sptr; /* Pointer into ServerName */ + char local_make_model[IPP_MAX_NAME]; + /* Local make and model */ + cupsd_printer_t *p; /* Printer information */ + const char *ipp_options; /* ipp-options value */ /* - * Read a packet from the browse socket... + * Pull the URI apart to see if this is a local or remote printer... */ - srclen = sizeof(srcaddr); - if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0, - (struct sockaddr *)&srcaddr, &srclen)) < 0) + httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), username, + sizeof(username), host, sizeof(host), &port, resource, + sizeof(resource)); + + /* + * Determine if the URI contains any illegal characters in it... + */ + + if (strncmp(uri, "ipp://", 6) || !host[0] || + (strncmp(resource, "/printers/", 10) && + strncmp(resource, "/classes/", 9))) { - /* - * "Connection refused" is returned under Linux if the destination port - * or address is unreachable from a previous sendto(); check for the - * error here and ignore it for now... - */ + cupsdLogMessage(CUPSD_LOG_ERROR, + "process_browse_data: Bad printer URI in browse data: %s", + uri); + return; + } - if (errno != ECONNREFUSED && errno != EAGAIN) + if (strchr(resource, '?') || + (!strncmp(resource, "/printers/", 10) && strchr(resource + 10, '/')) || + (!strncmp(resource, "/classes/", 9) && strchr(resource + 9, '/'))) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "process_browse_data: Bad resource in browse data: %s", + resource); + return; + } + + /* + * OK, this isn't a local printer; add any remote options... + */ + + ipp_options = cupsGetOption("ipp-options", num_attrs, attrs); + + if (BrowseRemoteOptions) + { + if (BrowseRemoteOptions[0] == '?') { - cupsdLogMessage(CUPSD_LOG_ERROR, "Browse recv failed - %s.", - strerror(errno)); - cupsdLogMessage(CUPSD_LOG_ERROR, "Browsing turned off."); + /* + * Override server-supplied options... + */ - cupsdStopBrowsing(); - Browsing = 0; + snprintf(finaluri, sizeof(finaluri), "%s%s", uri, BrowseRemoteOptions); + } + else if (ipp_options) + { + /* + * Combine the server and local options... + */ + + snprintf(finaluri, sizeof(finaluri), "%s?%s+%s", uri, ipp_options, + BrowseRemoteOptions); + } + else + { + /* + * Just use the local options... + */ + + snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, BrowseRemoteOptions); } - return; + uri = finaluri; } + else if (ipp_options) + { + /* + * Just use the server-supplied options... + */ - packet[bytes] = '\0'; + snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, ipp_options); + uri = finaluri; + } /* - * If we're about to sleep, ignore incoming browse packets. + * See if we already have it listed in the Printers list, and add it if not... */ - if (Sleeping) - return; + type |= CUPS_PRINTER_REMOTE; + type &= ~CUPS_PRINTER_IMPLICIT; + update = 0; + hptr = strchr(host, '.'); + sptr = strchr(ServerName, '.'); - /* - * Figure out where it came from... - */ + if (sptr != NULL && hptr != NULL) + { + /* + * Strip the common domain name components... + */ -#ifdef AF_INET6 - if (srcaddr.addr.sa_family == AF_INET6) + while (hptr != NULL) + { + if (!strcasecmp(hptr, sptr)) + { + *hptr = '\0'; + break; + } + else + hptr = strchr(hptr + 1, '.'); + } + } + + if (type & CUPS_PRINTER_CLASS) { - address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]); - address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]); - address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]); - address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]); + /* + * Remote destination is a class... + */ + + if (!strncmp(resource, "/classes/", 9)) + snprintf(name, sizeof(name), "%s@%s", resource + 9, host); + else + return; + + if ((p = cupsdFindClass(name)) == NULL && BrowseShortNames) + { + if ((p = cupsdFindClass(resource + 9)) != NULL) + { + if (p->hostname && strcasecmp(p->hostname, host)) + { + /* + * Nope, this isn't the same host; if the hostname isn't the local host, + * add it to the other class and then find a class using the full host + * name... + */ + + if (p->type & CUPS_PRINTER_REMOTE) + { + cupsdLogMessage(CUPSD_LOG_INFO, + "Renamed remote class \"%s\" to \"%s@%s\"...", + p->name, p->name, p->hostname); + cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, + "Class \'%s\' deleted by directory services.", + p->name); + + cupsArrayRemove(Printers, p); + cupsdSetStringf(&p->name, "%s@%s", p->name, p->hostname); + cupsdSetPrinterAttrs(p); + cupsArrayAdd(Printers, p); + + cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, + "Class \'%s\' added by directory services.", + p->name); + } + + p = NULL; + } + else if (!p->hostname) + { + /* + * Hostname not set, so this must be a cached remote printer + * that was created for a pending print job... + */ + + cupsdSetString(&p->hostname, host); + cupsdSetString(&p->uri, uri); + cupsdSetString(&p->device_uri, uri); + update = 1; + } + } + else + { + /* + * Use the short name for this shared class. + */ + + strlcpy(name, resource + 9, sizeof(name)); + } + } + else if (p && !p->hostname) + { + /* + * Hostname not set, so this must be a cached remote printer + * that was created for a pending print job... + */ + + cupsdSetString(&p->hostname, host); + cupsdSetString(&p->uri, uri); + cupsdSetString(&p->device_uri, uri); + update = 1; + } + + if (!p) + { + /* + * Class doesn't exist; add it... + */ + + p = cupsdAddClass(name); + + cupsdLogMessage(CUPSD_LOG_INFO, "Added remote class \"%s\"...", name); + + cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, + "Class \'%s\' added by directory services.", name); + + /* + * Force the URI to point to the real server... + */ + + p->type = type & ~CUPS_PRINTER_REJECTING; + p->accepting = 1; + cupsdSetString(&p->uri, uri); + cupsdSetString(&p->device_uri, uri); + cupsdSetString(&p->hostname, host); + + update = 1; + } } else -#endif /* AF_INET6 */ { - address[0] = 0; - address[1] = 0; - address[2] = 0; - address[3] = ntohl(srcaddr.ipv4.sin_addr.s_addr); - } + /* + * Remote destination is a printer... + */ + + if (!strncmp(resource, "/printers/", 10)) + snprintf(name, sizeof(name), "%s@%s", resource + 10, host); + else + return; + + if ((p = cupsdFindPrinter(name)) == NULL && BrowseShortNames) + { + if ((p = cupsdFindPrinter(resource + 10)) != NULL) + { + if (p->hostname && strcasecmp(p->hostname, host)) + { + /* + * Nope, this isn't the same host; if the hostname isn't the local host, + * add it to the other printer and then find a printer using the full host + * name... + */ - if (HostNameLookups) - httpAddrLookup(&srcaddr, srcname, sizeof(srcname)); - else - httpAddrString(&srcaddr, srcname, sizeof(srcname)); + if (p->type & CUPS_PRINTER_REMOTE) + { + cupsdLogMessage(CUPSD_LOG_INFO, + "Renamed remote printer \"%s\" to \"%s@%s\"...", + p->name, p->name, p->hostname); + cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, + "Printer \'%s\' deleted by directory services.", + p->name); - len = strlen(srcname); + cupsArrayRemove(Printers, p); + cupsdSetStringf(&p->name, "%s@%s", p->name, p->hostname); + cupsdSetPrinterAttrs(p); + cupsArrayAdd(Printers, p); - /* - * Do ACL stuff... - */ + cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, + "Printer \'%s\' added by directory services.", + p->name); + } - if (BrowseACL) - { - if (httpAddrLocalhost(&srcaddr) || !strcasecmp(srcname, "localhost")) + p = NULL; + } + else if (!p->hostname) + { + /* + * Hostname not set, so this must be a cached remote printer + * that was created for a pending print job... + */ + + cupsdSetString(&p->hostname, host); + cupsdSetString(&p->uri, uri); + cupsdSetString(&p->device_uri, uri); + update = 1; + } + } + else + { + /* + * Use the short name for this shared printer. + */ + + strlcpy(name, resource + 10, sizeof(name)); + } + } + else if (p && !p->hostname) { /* - * Access from localhost (127.0.0.1) is always allowed... + * Hostname not set, so this must be a cached remote printer + * that was created for a pending print job... */ - auth = AUTH_ALLOW; + cupsdSetString(&p->hostname, host); + cupsdSetString(&p->uri, uri); + cupsdSetString(&p->device_uri, uri); + update = 1; } - else + + if (!p) { /* - * Do authorization checks on the domain/address... + * Printer doesn't exist; add it... */ - switch (BrowseACL->order_type) - { - default : - auth = AUTH_DENY; /* anti-compiler-warning-code */ - break; - - case AUTH_ALLOW : /* Order Deny,Allow */ - auth = AUTH_ALLOW; + p = cupsdAddPrinter(name); - if (cupsdCheckAuth(address, srcname, len, - BrowseACL->num_deny, BrowseACL->deny)) - auth = AUTH_DENY; + cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, + "Printer \'%s\' added by directory services.", name); - if (cupsdCheckAuth(address, srcname, len, - BrowseACL->num_allow, BrowseACL->allow)) - auth = AUTH_ALLOW; - break; + cupsdLogMessage(CUPSD_LOG_INFO, "Added remote printer \"%s\"...", name); - case AUTH_DENY : /* Order Allow,Deny */ - auth = AUTH_DENY; + /* + * Force the URI to point to the real server... + */ - if (cupsdCheckAuth(address, srcname, len, - BrowseACL->num_allow, BrowseACL->allow)) - auth = AUTH_ALLOW; + p->type = type & ~CUPS_PRINTER_REJECTING; + p->accepting = 1; + cupsdSetString(&p->hostname, host); + cupsdSetString(&p->uri, uri); + cupsdSetString(&p->device_uri, uri); - if (cupsdCheckAuth(address, srcname, len, - BrowseACL->num_deny, BrowseACL->deny)) - auth = AUTH_DENY; - break; - } + update = 1; } } - else - auth = AUTH_ALLOW; - - if (auth == AUTH_DENY) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdUpdateCUPSBrowse: Refused %d bytes from %s", bytes, - srcname); - return; - } - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdUpdateCUPSBrowse: (%d bytes from %s) %s", bytes, - srcname, packet); /* - * Parse packet... + * Update the state... */ - if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3) - { - cupsdLogMessage(CUPSD_LOG_WARN, - "cupsdUpdateCUPSBrowse: Garbled browse packet - %s", packet); - return; - } - - strcpy(location, "Location Unknown"); - strcpy(info, "No Information Available"); - make_model[0] = '\0'; - num_attrs = 0; - attrs = NULL; + p->state = state; + p->browse_time = time(NULL); - if ((pptr = strchr(packet, '\"')) != NULL) + if (type & CUPS_PRINTER_REJECTING) { - /* - * Have extended information; can't use sscanf for it because not all - * sscanf's allow empty strings with %[^\"]... - */ - - for (i = 0, pptr ++; - i < (sizeof(location) - 1) && *pptr && *pptr != '\"'; - i ++, pptr ++) - location[i] = *pptr; - - if (i) - location[i] = '\0'; - - if (*pptr == '\"') - pptr ++; - - while (*pptr && isspace(*pptr & 255)) - pptr ++; + type &= ~CUPS_PRINTER_REJECTING; - if (*pptr == '\"') + if (p->accepting) { - for (i = 0, pptr ++; - i < (sizeof(info) - 1) && *pptr && *pptr != '\"'; - i ++, pptr ++) - info[i] = *pptr; - - info[i] = '\0'; - - if (*pptr == '\"') - pptr ++; - - while (*pptr && isspace(*pptr & 255)) - pptr ++; - - if (*pptr == '\"') - { - for (i = 0, pptr ++; - i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"'; - i ++, pptr ++) - make_model[i] = *pptr; - - if (*pptr == '\"') - pptr ++; - - make_model[i] = '\0'; - - if (*pptr) - num_attrs = cupsParseOptions(pptr, num_attrs, &attrs); - } + update = 1; + p->accepting = 0; } } + else if (!p->accepting) + { + update = 1; + p->accepting = 1; + } - DEBUG_puts(packet); - DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n" - "location=\"%s\", info=\"%s\", make_model=\"%s\"\n", - type, state, uri, location, info, make_model)); - - /* - * Pull the URI apart to see if this is a local or remote printer... - */ + if (p->type != type) + { + p->type = type; + update = 1; + } - httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), username, - sizeof(username), host, sizeof(host), &port, resource, - sizeof(resource)); + if (location && (!p->location || strcmp(p->location, location))) + { + cupsdSetString(&p->location, location); + update = 1; + } - DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName)); + if (info && (!p->info || strcmp(p->info, info))) + { + cupsdSetString(&p->info, info); + update = 1; + } - /* - * Check for packets from the local server... - */ + if (!make_model || !make_model[0]) + { + if (type & CUPS_PRINTER_CLASS) + snprintf(local_make_model, sizeof(local_make_model), + "Remote Class on %s", host); + else + snprintf(local_make_model, sizeof(local_make_model), + "Remote Printer on %s", host); + } + else + snprintf(local_make_model, sizeof(local_make_model), + "%s on %s", make_model, host); - if (!strcasecmp(host, ServerName) && port == LocalPort) + if (!p->make_model || strcmp(p->make_model, local_make_model)) { - cupsFreeOptions(num_attrs, attrs); - return; + cupsdSetString(&p->make_model, local_make_model); + update = 1; } - cupsdNetIFUpdate(); + if (type & CUPS_PRINTER_DELETE) + { + cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, + "%s \'%s\' deleted by directory services.", + (type & CUPS_PRINTER_CLASS) ? "Class" : "Printer", p->name); - for (iface = NetIFList; iface != NULL; iface = iface->next) - if (!strcasecmp(host, iface->hostname) && port == iface->port) - { - cupsFreeOptions(num_attrs, attrs); - return; - } + cupsdExpireSubscriptions(p, NULL); + + cupsdDeletePrinter(p, 1); + cupsdUpdateImplicitClasses(); + } + else if (update) + { + cupsdSetPrinterAttrs(p); + cupsdUpdateImplicitClasses(); + } /* - * Do relaying... + * See if we have a default printer... If not, make the first printer the + * default. */ - for (i = 0; i < NumRelays; i ++) - if (cupsdCheckAuth(address, srcname, len, 1, &(Relays[i].from))) - if (sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(Relays[i].to), - sizeof(http_addr_t)) <= 0) + if (DefaultPrinter == NULL && Printers != NULL && UseNetworkDefault) + { + /* + * Find the first network default printer and use it... + */ + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (p->type & CUPS_PRINTER_DEFAULT) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdUpdateCUPSBrowse: sendto failed for relay %d - %s.", - i + 1, strerror(errno)); - cupsFreeOptions(num_attrs, attrs); - return; + DefaultPrinter = p; + break; } + } /* - * Process the browse data... + * Do auto-classing if needed... */ - cupsdProcessBrowseData(uri, (cups_ptype_t)type, (ipp_pstate_t)state, location, - info, make_model, num_attrs, attrs); - cupsFreeOptions(num_attrs, attrs); + process_implicit_classes(); + + /* + * Update the printcap file... + */ + + cupsdWritePrintcap(); } /* - * 'cupsdUpdatePolling()' - Read status messages from the poll daemons. + * 'process_implicit_classes()' - Create/update implicit classes as needed. */ -void -cupsdUpdatePolling(void) +static void +process_implicit_classes(void) { - char *ptr, /* Pointer to end of line in buffer */ - message[1024]; /* Pointer to message text */ - int loglevel; /* Log level for message */ + int i; /* Looping var */ + int update; /* Update printer attributes? */ + char name[IPP_MAX_NAME], /* Name of printer */ + *hptr; /* Pointer into hostname */ + cupsd_printer_t *p, /* Printer information */ + *pclass, /* Printer class */ + *first; /* First printer in class */ + int offset, /* Offset of name */ + len; /* Length of name */ - while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel, - message, sizeof(message))) != NULL) - if (!strchr(PollStatusBuffer->buffer, '\n')) - break; + if (!ImplicitClasses || !Printers) + return; - if (ptr == NULL) + /* + * Loop through all available printers and create classes as needed... + */ + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers), len = 0, offset = 0, + update = 0, pclass = NULL, first = NULL; + p != NULL; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) { /* - * All polling processes have died; stop polling... + * Skip implicit classes... */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdUpdatePolling: all polling processes have exited!"); - cupsdStopPolling(); - } -} - - -#ifdef HAVE_LIBSLP -/* - * 'cupsdUpdateSLPBrowse()' - Get browsing information via SLP. - */ + if (p->type & CUPS_PRINTER_IMPLICIT) + { + len = 0; + continue; + } -void -cupsdUpdateSLPBrowse(void) -{ - slpsrvurl_t *s, /* Temporary list of service URLs */ - *next; /* Next service in list */ - cupsd_printer_t p; /* Printer information */ - const char *uri; /* Pointer to printer URI */ - char method[HTTP_MAX_URI], - /* Method portion of URI */ - username[HTTP_MAX_URI], - /* Username portion of URI */ - host[HTTP_MAX_URI], - /* Host portion of URI */ - resource[HTTP_MAX_URI]; - /* Resource portion of URI */ - int port; /* Port portion of URI */ + /* + * If len == 0, get the length of this printer name up to the "@" + * sign (if any). + */ + cupsArraySave(Printers); - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdUpdateSLPBrowse() Start..."); + if (len > 0 && + !strncasecmp(p->name, name + offset, len) && + (p->name[len] == '\0' || p->name[len] == '@')) + { + /* + * We have more than one printer with the same name; see if + * we have a class, and if this printer is a member... + */ - /* - * Reset the refresh time... - */ + if (pclass && strcasecmp(pclass->name, name)) + { + if (update) + cupsdSetPrinterAttrs(pclass); - BrowseSLPRefresh = time(NULL) + BrowseInterval; + update = 0; + pclass = NULL; + } - /* - * Poll for remote printers using SLP... - */ + if (!pclass && (pclass = cupsdFindDest(name)) == NULL) + { + /* + * Need to add the class... + */ - s = NULL; + pclass = cupsdAddPrinter(name); + cupsArrayAdd(ImplicitPrinters, pclass); - SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "", - slp_url_callback, &s); + pclass->type |= CUPS_PRINTER_IMPLICIT; + pclass->accepting = 1; + pclass->state = IPP_PRINTER_IDLE; - /* - * Loop through the list of available printers... - */ + cupsdSetString(&pclass->location, p->location); + cupsdSetString(&pclass->info, p->info); - for (; s; s = next) - { - /* - * Save the "next" pointer... - */ + update = 1; - next = s->next; + cupsdLogMessage(CUPSD_LOG_INFO, "Added implicit class \"%s\"...", + name); + } - /* - * Load a cupsd_printer_t structure with the SLP service attributes... - */ + if (first != NULL) + { + for (i = 0; i < pclass->num_printers; i ++) + if (pclass->printers[i] == first) + break; - SLPFindAttrs(BrowseSLPHandle, s->url, "", "", slp_attr_callback, &p); + if (i >= pclass->num_printers) + { + first->in_implicit_class = 1; + cupsdAddPrinterToClass(pclass, first); + } - /* - * Process this printer entry... - */ + first = NULL; + } - uri = s->url + SLP_CUPS_SRVLEN + 1; + for (i = 0; i < pclass->num_printers; i ++) + if (pclass->printers[i] == p) + break; - if (!strncmp(uri, "http://", 7) || !strncmp(uri, "ipp://", 6)) + if (i >= pclass->num_printers) + { + p->in_implicit_class = 1; + cupsdAddPrinterToClass(pclass, p); + update = 1; + } + } + else { /* - * Pull the URI apart to see if this is a local or remote printer... + * First time around; just get name length and mark it as first + * in the list... */ - httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), - username, sizeof(username), host, sizeof(host), &port, - resource, sizeof(resource)); + if ((hptr = strchr(p->name, '@')) != NULL) + len = hptr - p->name; + else + len = strlen(p->name); - if (strcasecmp(host, ServerName) == 0) - continue; + strncpy(name, p->name, len); + name[len] = '\0'; + offset = 0; - /* - * OK, at least an IPP printer, see if it is a CUPS printer or - * class... - */ + if ((first = (hptr ? cupsdFindDest(name) : p)) != NULL && + !(first->type & CUPS_PRINTER_IMPLICIT)) + { + /* + * Can't use same name as a local printer; add "Any" to the + * front of the name, unless we have explicitly disabled + * the "ImplicitAnyClasses"... + */ - if (strstr(uri, "/printers/") != NULL) - cupsdProcessBrowseData(uri, p.type, IPP_PRINTER_IDLE, p.location, - p.info, p.make_model, 0, NULL); - else if (strstr(uri, "/classes/") != NULL) - cupsdProcessBrowseData(uri, p.type | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE, - p.location, p.info, p.make_model, 0, NULL); + if (ImplicitAnyClasses && len < (sizeof(name) - 4)) + { + /* + * Add "Any" to the class name... + */ + + strcpy(name, "Any"); + strncpy(name + 3, p->name, len); + name[len + 3] = '\0'; + offset = 3; + } + else + { + /* + * Don't create an implicit class if we have a local printer + * with the same name... + */ + + len = 0; + cupsArrayRestore(Printers); + continue; + } + } + + first = p; } - /* - * Free this listing... - */ + cupsArrayRestore(Printers); + } - free(s); - } + /* + * Update the last printer class as needed... + */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdUpdateSLPBrowse() End..."); + if (pclass && update) + cupsdSetPrinterAttrs(pclass); } +#ifdef HAVE_LIBSLP /* * 'slp_attr_callback()' - SLP attribute callback */ @@ -2464,7 +2536,7 @@ slp_attr_callback( if (slp_get_attr(attrlist, "(color-supported=", &tmp)) return (SLP_FALSE); - if (strcasecmp(tmp, "true") == 0) + if (!strcasecmp(tmp, "true")) p->type |= CUPS_PRINTER_COLOR; if (slp_get_attr(attrlist, "(finishings-supported=", &tmp)) @@ -2642,5 +2714,5 @@ slp_url_callback( /* - * End of "$Id: dirsvc.c 5023 2006-01-29 14:39:44Z mike $". + * End of "$Id: dirsvc.c 5043 2006-02-01 18:55:16Z mike $". */ diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h index ff659e580..951407efe 100644 --- a/scheduler/dirsvc.h +++ b/scheduler/dirsvc.h @@ -1,5 +1,5 @@ /* - * "$Id: dirsvc.h 5020 2006-01-28 13:36:15Z mike $" + * "$Id: dirsvc.h 5031 2006-01-31 03:05:32Z mike $" * * Directory services definitions for the Common UNIX Printing System * (CUPS) scheduler. @@ -99,6 +99,8 @@ VAR int Browsing VALUE(TRUE), /* Broadcast interval in seconds */ BrowseTimeout VALUE(DEFAULT_TIMEOUT), /* Time out for printers in seconds */ + UseNetworkDefault VALUE(CUPS_DEFAULT_USE_NETWORK_DEFAULT), + /* Use the network default printer? */ NumBrowsers VALUE(0); /* Number of broadcast addresses */ VAR char *BrowseLocalOptions @@ -139,11 +141,6 @@ VAR time_t BrowseSLPRefresh VALUE(0); */ extern void cupsdLoadRemoteCache(void); -extern void cupsdProcessBrowseData(const char *uri, cups_ptype_t type, - ipp_pstate_t state, const char *location, - const char *info, const char *make_model, - int num_attrs, cups_option_t *attrs); -extern void cupsdProcessImplicitClasses(void); extern void cupsdSaveRemoteCache(void); extern void cupsdSendBrowseDelete(cupsd_printer_t *p); extern void cupsdSendBrowseList(void); @@ -159,5 +156,5 @@ extern void cupsdUpdateSLPBrowse(void); /* - * End of "$Id: dirsvc.h 5020 2006-01-28 13:36:15Z mike $". + * End of "$Id: dirsvc.h 5031 2006-01-31 03:05:32Z mike $". */ diff --git a/scheduler/env.c b/scheduler/env.c index 39a0c6ccb..ec3a8817d 100644 --- a/scheduler/env.c +++ b/scheduler/env.c @@ -1,9 +1,9 @@ /* - * "$Id: env.c 4961 2006-01-20 22:19:13Z mike $" + * "$Id: env.c 5046 2006-02-01 22:11:58Z mike $" * * Environment management routines for the Common UNIX Printing System (CUPS). * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -43,7 +43,7 @@ */ static int num_common_env = 0; /* Number of common env vars */ -static char *common_env[100]; /* Common env vars */ +static char *common_env[MAX_ENV]; /* Common env vars */ /* @@ -76,15 +76,15 @@ cupsdInitEnv(void) cupsdClearEnv(); -#ifdef __APPLE__ +#if defined(__APPLE__) && __GNUC__ > 3 /* - * Add special voodoo magic for MacOS X - this allows MacOS X programs - * to access their bundle resources properly... + * Add special voodoo magic for MacOS X 10.4 and later - this allows MacOS + * X programs to access their bundle resources properly... */ cupsdSetString(common_env, ""); num_common_env = 1; -#endif /* __APPLE__ */ +#endif /* __APPLE__ && __GNUC__ > 3 */ /* * Set common variables... @@ -222,5 +222,5 @@ cupsdSetEnvf(const char *name, /* I - Name of variable */ /* - * End of "$Id: env.c 4961 2006-01-20 22:19:13Z mike $". + * End of "$Id: env.c 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 8dccbcfa1..0c96cf7b1 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -1,5 +1,5 @@ /* - * "$Id: ipp.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: ipp.c 5046 2006-02-01 22:11:58Z mike $" * * IPP routines for the Common UNIX Printing System (CUPS) scheduler. * @@ -65,6 +65,7 @@ * get_printers() - Get a list of printers. * get_subscription_attrs() - Get subscription attributes. * get_subscriptions() - Get subscriptions. + * get_username() - Get the username associated with a request. * hold_job() - Hold a print job. * move_job() - Move a job to a new destination. * ppd_add_default() - Add a PPD default choice. @@ -160,6 +161,7 @@ static void get_printers(cupsd_client_t *con, int type); static void get_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri); static void get_subscription_attrs(cupsd_client_t *con, int sub_id); static void get_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri); +static const char *get_username(cupsd_client_t *con); static void hold_job(cupsd_client_t *con, ipp_attribute_t *uri); static void move_job(cupsd_client_t *con, ipp_attribute_t *uri); static int ppd_add_default(const char *option, const char *choice, @@ -722,7 +724,7 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdSaveAllPrinters(); cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" now accepting jobs (\"%s\").", name, - con->username); + get_username(con)); /* * Everything was ok, so return OK status... @@ -753,6 +755,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */ const char *dest; /* Printer or class name */ ipp_attribute_t *attr; /* Printer attribute */ int modify; /* Non-zero if we just modified */ + int need_restart_job; /* Need to restart job? */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", con, @@ -883,6 +886,8 @@ add_class(cupsd_client_t *con, /* I - Client connection */ * Look for attributes and copy them over as needed... */ + need_restart_job = 0; + if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL) cupsdSetString(&pclass->location, attr->values[0].string.text); @@ -932,7 +937,10 @@ add_class(cupsd_client_t *con, /* I - Client connection */ if (attr->values[0].integer == IPP_PRINTER_STOPPED) cupsdStopPrinter(pclass, 0); else + { cupsdSetPrinterState(pclass, (ipp_pstate_t)(attr->values[0].integer), 0); + need_restart_job = 1; + } } if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) != NULL) @@ -1049,6 +1057,8 @@ add_class(cupsd_client_t *con, /* I - Client connection */ * Clear the printer array as needed... */ + need_restart_job = 1; + if (pclass->num_printers > 0) { free(pclass->printers); @@ -1094,7 +1104,23 @@ add_class(cupsd_client_t *con, /* I - Client connection */ cupsdSetPrinterAttrs(pclass); cupsdSaveAllClasses(); - cupsdCheckJobs(); + + if (need_restart_job && pclass->job) + { + cupsd_job_t *job; + + /* + * Stop the current job and then restart it below... + */ + + job = (cupsd_job_t *)pclass->job; + + cupsdStopJob(job, 1); + job->state->values[0].integer = IPP_JOB_PENDING; + } + + if (need_restart_job) + cupsdCheckJobs(); cupsdWritePrintcap(); @@ -1102,10 +1128,10 @@ add_class(cupsd_client_t *con, /* I - Client connection */ { cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, pclass, NULL, "Class \"%s\" modified by \"%s\".", pclass->name, - con->username); + get_username(con)); cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" modified by \"%s\".", - pclass->name, con->username); + pclass->name, get_username(con)); } else { @@ -1113,10 +1139,10 @@ add_class(cupsd_client_t *con, /* I - Client connection */ cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, pclass, NULL, "New class \"%s\" added by \"%s\".", pclass->name, - con->username); + get_username(con)); cupsdLogMessage(CUPSD_LOG_INFO, "New class \"%s\" added by \"%s\".", - pclass->name, con->username); + pclass->name, get_username(con)); } con->response->request.status.status_code = IPP_OK; @@ -1443,6 +1469,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ char srcfile[1024], /* Source Script/PPD file */ dstfile[1024]; /* Destination Script/PPD file */ int modify; /* Non-zero if we are modifying */ + int need_restart_job; /* Need to restart job? */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", con, @@ -1572,6 +1599,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ * Look for attributes and copy them over as needed... */ + need_restart_job = 0; + if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL) cupsdSetString(&printer->location, attr->values[0].string.text); @@ -1587,6 +1616,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ * Do we have a valid device URI? */ + need_restart_job = 1; + httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, method, sizeof(method), username, sizeof(username), host, sizeof(host), &port, resource, sizeof(resource)); @@ -1647,6 +1678,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ ipp_attribute_t *supported; /* port-monitor-supported attribute */ + need_restart_job = 1; + supported = ippFindAttribute(printer->attrs, "port-monitor-supported", IPP_TAG_KEYWORD); for (i = 0; i < supported->num_values; i ++) @@ -1713,7 +1746,10 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ if (attr->values[0].integer == IPP_PRINTER_STOPPED) cupsdStopPrinter(printer, 0); else + { + need_restart_job = 1; cupsdSetPrinterState(printer, (ipp_pstate_t)(attr->values[0].integer), 0); + } } if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) != NULL) @@ -1826,7 +1862,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ */ if (!printer->device_uri) - cupsdSetString(&printer->device_uri, "file:/dev/null"); + cupsdSetString(&printer->device_uri, "file:///dev/null"); /* * See if we have an interface script or PPD file attached to the request... @@ -1834,6 +1870,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ if (con->filename) { + need_restart_job = 1; + strlcpy(srcfile, con->filename, sizeof(srcfile)); if ((fp = cupsFileOpen(srcfile, "rb"))) @@ -1922,6 +1960,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ else if ((attr = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME)) != NULL) { + need_restart_job = 1; + if (!strcmp(attr->values[0].string.text, "raw")) { /* @@ -1963,13 +2003,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ } } - /* - * Make this printer the default if there is none... - */ - - if (!DefaultPrinter) - DefaultPrinter = printer; - /* * Update the printer attributes and return... */ @@ -1977,7 +2010,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdSetPrinterAttrs(printer); cupsdSaveAllPrinters(); - if (printer->job) + if (need_restart_job && printer->job) { cupsd_job_t *job; @@ -1991,7 +2024,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ job->state->values[0].integer = IPP_JOB_PENDING; } - cupsdCheckJobs(); + if (need_restart_job) + cupsdCheckJobs(); cupsdWritePrintcap(); @@ -1999,10 +2033,10 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ { cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL, "Printer \"%s\" modified by \"%s\".", printer->name, - con->username); + get_username(con)); cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" modified by \"%s\".", - printer->name, con->username); + printer->name, get_username(con)); } else { @@ -2010,10 +2044,10 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, printer, NULL, "New printer \"%s\" added by \"%s\".", printer->name, - con->username); + get_username(con)); cupsdLogMessage(CUPSD_LOG_INFO, "New printer \"%s\" added by \"%s\".", - printer->name, con->username); + printer->name, get_username(con)); } con->response->request.status.status_code = IPP_OK; @@ -2343,7 +2377,7 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdCancelJobs(NULL, username, purge); cupsdLogMessage(CUPSD_LOG_INFO, "All jobs were %s by \"%s\".", - purge ? "purged" : "cancelled", con->username); + purge ? "purged" : "cancelled", get_username(con)); } else { @@ -2364,7 +2398,7 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdCancelJobs(dest, username, purge); cupsdLogMessage(CUPSD_LOG_INFO, "All jobs on \"%s\" were %s by \"%s\".", - dest, purge ? "purged" : "cancelled", con->username); + dest, purge ? "purged" : "cancelled", get_username(con)); } con->response->request.status.status_code = IPP_OK; @@ -2569,7 +2603,6 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */ cupsd_printer_t *p) /* I - Printer or class */ { int i; /* Looping var */ - ipp_attribute_t *attr; /* Current attribute */ char username[33]; /* Username */ cupsd_quota_t *q; /* Quota data */ struct passwd *pw; /* User password data */ @@ -2589,20 +2622,7 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */ * Figure out who is printing... */ - attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME); - - if (con->username[0]) - strlcpy(username, con->username, sizeof(username)); - else if (attr) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "check_quotas: requesting-user-name = \"%s\"", - attr->values[0].string.text); - - strlcpy(username, attr->values[0].string.text, sizeof(username)); - } - else - strcpy(username, "anonymous"); + strlcpy(username, get_username(con), sizeof(username)); /* * Check global active job limits for printers and users... @@ -3243,7 +3263,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ int temppid; /* Process ID of cups-driverd */ int temppipe[2]; /* Temporary pipes */ char *argv[4], /* Command-line arguments */ - *envp[100]; /* Environment */ + *envp[MAX_ENV]; /* Environment */ cups_file_t *src, /* Source file */ *dst; /* Destination file */ int bytes, /* Bytes from pipe */ @@ -3305,6 +3325,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ if (!cupsdStartProcess(buffer, argv, envp, -1, temppipe[1], CGIPipes[1], -1, 0, &temppid)) { + free(input); close(tempfd); unlink(tempfile); return (-1); @@ -3377,6 +3398,8 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ close(temppipe[0]); close(tempfd); + free(input); + if (!total) { /* @@ -3674,6 +3697,14 @@ copy_printer_attrs( curtime = time(NULL); +#ifdef __APPLE__ + if ((!ra || cupsArrayFind(ra, "com.apple.print.recoverable-message")) && + printer->recoverable) + ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, + "com.apple.print.recoverable-message", NULL, + printer->recoverable); +#endif /* __APPLE__ */ + if (!ra || cupsArrayFind(ra, "printer-current-time")) ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time", ippTimeToDate(curtime)); @@ -3726,6 +3757,30 @@ copy_printer_attrs( if (!ra || cupsArrayFind(ra, "printer-state-reasons")) add_printer_state_reasons(con, printer); + if (!ra || cupsArrayFind(ra, "printer-type")) + { + int type; /* printer-type value */ + + + /* + * Add the CUPS-specific printer-type attribute... + */ + + type = printer->type; + + if (printer == DefaultPrinter) + type |= CUPS_PRINTER_DEFAULT; + + if (!printer->accepting) + type |= CUPS_PRINTER_REJECTING; + + if (!printer->shared) + type |= CUPS_PRINTER_NOT_SHARED; + + ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", + type); + } + if (!ra || cupsArrayFind(ra, "printer-up-time")) ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-up-time", curtime); @@ -4648,19 +4703,7 @@ create_subscription( * Get the user that is requesting the subscription... */ - if (con->username[0]) - username = con->username; - else if ((attr = ippFindAttribute(con->request, "requesting-user-name", - IPP_TAG_NAME)) != NULL) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "create_subscription: requesting-user-name = \"%s\"", - attr->values[0].string.text); - - username = attr->values[0].string.text; - } - else - username = "anonymous"; + username = get_username(con); /* * Find the first subscription group attribute; return if we have @@ -4900,7 +4943,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */ cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, printer, NULL, "%s \"%s\" deleted by \"%s\".", (dtype & CUPS_PRINTER_CLASS) ? "Class" : "Printer", - dest, con->username); + dest, get_username(con)); cupsdExpireSubscriptions(printer, NULL); @@ -4917,7 +4960,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */ if (dtype & CUPS_PRINTER_CLASS) { cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" deleted by \"%s\".", dest, - con->username); + get_username(con)); cupsdDeletePrinter(printer, 0); cupsdSaveAllClasses(); @@ -4925,7 +4968,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */ else { cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" deleted by \"%s\".", dest, - con->username); + get_username(con)); cupsdDeletePrinter(printer, 0); cupsdSaveAllPrinters(); @@ -5056,9 +5099,9 @@ get_devices(cupsd_client_t *con) /* I - Client connection */ snprintf(command, sizeof(command), "%s/daemon/cups-deviced", ServerBin); snprintf(options, sizeof(options), - "cups-deviced %d+%d+requested-attributes=%s", + "cups-deviced %d+%d+%d+requested-attributes=%s", con->request->request.op.request_id, - limit ? limit->values[0].integer : 0, + limit ? limit->values[0].integer : 0, User, attrs); if (cupsdSendCommand(con, command, options, 1)) @@ -5324,15 +5367,7 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL && attr->values[0].boolean) - { - if (con->username[0]) - strlcpy(username, con->username, sizeof(username)); - else if ((attr = ippFindAttribute(con->request, "requesting-user-name", - IPP_TAG_NAME)) != NULL) - strlcpy(username, attr->values[0].string.text, sizeof(username)); - else - strcpy(username, "anonymous"); - } + strlcpy(username, get_username(con), sizeof(username)); else username[0] = '\0'; @@ -5902,15 +5937,7 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "my-subscriptions", IPP_TAG_BOOLEAN)) != NULL && attr->values[0].boolean) - { - if (con->username[0]) - strlcpy(username, con->username, sizeof(username)); - else if ((attr = ippFindAttribute(con->request, "requesting-user-name", - IPP_TAG_NAME)) != NULL) - strlcpy(username, attr->values[0].string.text, sizeof(username)); - else - strcpy(username, "anonymous"); - } + strlcpy(username, get_username(con), sizeof(username)); else username[0] = '\0'; @@ -5937,6 +5964,26 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */ } +/* + * 'get_username()' - Get the username associated with a request. + */ + +static const char * /* O - Username */ +get_username(cupsd_client_t *con) /* I - Connection */ +{ + ipp_attribute_t *attr; /* Attribute */ + + + if (con->username[0]) + return (con->username); + else if ((attr = ippFindAttribute(con->request, "requesting-user-name", + IPP_TAG_NAME)) != NULL) + return (attr->values[0].string.text); + else + return ("anonymous"); +} + + /* * 'hold_job()' - Hold a print job. */ @@ -7417,14 +7464,14 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdSaveAllClasses(); cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" rejecting jobs (\"%s\").", - name, con->username); + name, get_username(con)); } else { cupsdSaveAllPrinters(); cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" rejecting jobs (\"%s\").", - name, con->username); + name, get_username(con)); } /* @@ -8296,7 +8343,7 @@ set_default(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_INFO, "Default destination set to \"%s\" by \"%s\".", name, - con->username); + get_username(con)); /* * Everything was ok, so return OK status... @@ -8704,9 +8751,10 @@ start_printer(cupsd_client_t *con, /* I - Client connection */ if (dtype & CUPS_PRINTER_CLASS) cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" started by \"%s\".", name, - con->username); + get_username(con)); + else cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" started by \"%s\".", name, - con->username); + get_username(con)); cupsdCheckJobs(); @@ -8791,10 +8839,10 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */ if (dtype & CUPS_PRINTER_CLASS) cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" stopped by \"%s\".", name, - con->username); + get_username(con)); else cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" stopped by \"%s\".", name, - con->username); + get_username(con)); /* * Everything was ok, so return OK status... @@ -8994,7 +9042,6 @@ validate_user(cupsd_job_t *job, /* I - Job */ char *username, /* O - Authenticated username */ int userlen) /* I - Length of username */ { - ipp_attribute_t *attr; /* requesting-user-name attribute */ cupsd_printer_t *printer; /* Printer for job */ @@ -9015,13 +9062,7 @@ validate_user(cupsd_job_t *job, /* I - Job */ * Get the best authenticated username that is available. */ - if (con->username[0]) - strlcpy(username, con->username, userlen); - else if ((attr = ippFindAttribute(con->request, "requesting-user-name", - IPP_TAG_NAME)) != NULL) - strlcpy(username, attr->values[0].string.text, userlen); - else - strlcpy(username, "anonymous", userlen); + strlcpy(username, get_username(con), userlen); /* * Check the username against the owner... @@ -9038,5 +9079,5 @@ validate_user(cupsd_job_t *job, /* I - Job */ /* - * End of "$Id: ipp.c 5023 2006-01-29 14:39:44Z mike $". + * End of "$Id: ipp.c 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/job.c b/scheduler/job.c index 13c1260dd..3905c408b 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -1,9 +1,9 @@ /* - * "$Id: job.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: job.c 5046 2006-02-01 22:11:58Z mike $" * * Job management routines for the Common UNIX Printing System (CUPS). * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -426,14 +426,14 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */ job->status_buffer = NULL; } + printer = job->printer; + if (job->status < 0) { /* * Backend had errors; stop it... */ - printer = job->printer; - switch (-job->status) { default : @@ -540,29 +540,15 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */ else if (job->status > 0) { /* - * Filter had errors; cancel it... + * Filter had errors; stop job... */ - if (job->current_file < job->num_files) - cupsdStartJob(job, job->printer); - else - { - cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job, - "Job aborted due to filter errors; please consult the " - "error_log file for details."); - - job_history = JobHistory && !(job->dtype & CUPS_PRINTER_REMOTE); - - cupsdCancelJob(job, 0); - - if (job_history) - { - job->state->values[0].integer = IPP_JOB_ABORTED; - cupsdSaveJob(job); - } - - cupsdCheckJobs(); - } + cupsdStopJob(job, 1); + cupsdSaveJob(job); + cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, job->printer, job, + "Job stopped due to filter errors; please consult the " + "error_log file for details."); + cupsdCheckJobs(); } else { @@ -572,11 +558,19 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */ if (job->current_file < job->num_files) { + /* + * Start the next file in the job... + */ + FilterLevel -= job->cost; cupsdStartJob(job, job->printer); } else { + /* + * Close out this job... + */ + cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job, "Job completed successfully."); @@ -590,6 +584,12 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */ cupsdSaveJob(job); } + /* + * Clear the printer's state_message and move on... + */ + + printer->state_message[0] = '\0'; + cupsdCheckJobs(); } } @@ -1334,6 +1334,8 @@ cupsdStartJob(cupsd_job_t *job, /* I - Job ID */ *optptr, /* Pointer to options */ *valptr; /* Pointer in value string */ ipp_attribute_t *attr; /* Current attribute */ + struct stat backinfo; /* Backend file information */ + int backroot; /* Run backend as root? */ int pid; /* Process ID of new filter process */ int banner_page; /* 1 if banner page, 0 otherwise */ int statusfds[2], /* Pipes used between the filters and scheduler */ @@ -1347,7 +1349,7 @@ cupsdStartJob(cupsd_job_t *job, /* I - Job ID */ title[IPP_MAX_NAME], /* Job title string */ copies[255], /* # copies string */ - *envp[100], /* Environment variables */ + *envp[MAX_ENV], /* Environment variables */ charset[255], /* CHARSET environment variable */ class_name[255],/* CLASS environment variable */ classification[1024], @@ -2145,6 +2147,17 @@ cupsdStartJob(cupsd_job_t *job, /* I - Job ID */ sscanf(printer->device_uri, "%254[^:]", method); snprintf(command, sizeof(command), "%s/backend/%s", ServerBin, method); + /* + * See if the backend needs to run as root... + */ + + if (RunUser) + backroot = 0; + else if (lstat(command, &backinfo)) + backroot = 0; + else + backroot = !(backinfo.st_mode & (S_IRWXG | S_IRWXO)); + argv[0] = sani_uri; filterfds[slot][0] = -1; @@ -2179,7 +2192,7 @@ cupsdStartJob(cupsd_job_t *job, /* I - Job ID */ pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0], filterfds[slot][1], statusfds[1], - job->back_pipes[1], 1, + job->back_pipes[1], backroot, &(job->backend)); if (pid == 0) @@ -2262,6 +2275,9 @@ cupsdStartJob(cupsd_job_t *job, /* I - Job ID */ job->status_buffer->fd); FD_SET(job->status_buffer->fd, InputSet); + + cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job, "Job #%d started.", + job->id); } @@ -2426,7 +2442,10 @@ cupsdUpdateJob(cupsd_job_t *job) /* I - Job to check */ "Printed %d page(s).", job->sheets->values[0].integer); } else if (loglevel == CUPSD_LOG_STATE) + { cupsdSetPrinterReasons(job->printer, message); + cupsdAddPrinterHistory(job->printer); + } else if (loglevel == CUPSD_LOG_ATTR) { /* @@ -2435,6 +2454,42 @@ cupsdUpdateJob(cupsd_job_t *job) /* I - Job to check */ /**** TODO ****/ } +#ifdef __APPLE__ + else if (!strncmp(message, "recoverable:", 12)) + { + cupsdSetPrinterReasons(job->printer, + "+com.apple.print.recoverable-warning"); + + ptr = message + 12; + while (isspace(*ptr & 255)) + ptr ++; + + cupsdSetString(&job->printer->recoverable, ptr); + cupsdAddPrinterHistory(job->printer); + } + else if (!strncmp(message, "recovered:", 10)) + { + cupsdSetPrinterReasons(job->printer, + "-com.apple.print.recoverable-warning"); + + ptr = message + 10; + while (isspace(*ptr & 255)) + ptr ++; + + cupsdSetString(&job->printer->recoverable, ptr); + cupsdAddPrinterHistory(job->printer); + } +#endif /* __APPLE__ */ + else + { + /* + * Some message to show in the printer-state-message attribute... + */ + + strlcpy(job->printer->state_message, message, + sizeof(job->printer->state_message)); + cupsdAddPrinterHistory(job->printer); + } if (!strchr(job->status_buffer->buffer, '\n')) break; @@ -2686,5 +2741,5 @@ set_hold_until(cupsd_job_t *job, /* I - Job to update */ /* - * End of "$Id: job.c 5023 2006-01-29 14:39:44Z mike $". + * End of "$Id: job.c 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/listen.c b/scheduler/listen.c index 6c2522148..d5b9ea579 100644 --- a/scheduler/listen.c +++ b/scheduler/listen.c @@ -1,5 +1,5 @@ /* - * "$Id: listen.c 5020 2006-01-28 13:36:15Z mike $" + * "$Id: listen.c 5041 2006-02-01 16:54:50Z mike $" * * Server listening routines for the Common UNIX Printing System (CUPS) * scheduler. @@ -193,20 +193,20 @@ cupsdStartListening(void) */ val = 1; - #ifdef __sun +#ifdef __sun setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); - #else +#else setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - #endif /* __sun */ +#endif /* __sun */ /* * Bind to the port we found... */ - #ifdef AF_INET6 +#ifdef AF_INET6 if (lis->address.addr.sa_family == AF_INET6) { - # ifdef IPV6_V6ONLY +# ifdef IPV6_V6ONLY /* * Accept only IPv6 connections on this socket, to avoid * potential security issues and to make all platforms behave @@ -214,19 +214,19 @@ cupsdStartListening(void) */ val = 1; - # ifdef __sun +# ifdef __sun setsockopt(lis->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val)); - # else +# else setsockopt(lis->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)); - # endif /* __sun */ - # endif /* IPV6_V6ONLY */ +# endif /* __sun */ +# endif /* IPV6_V6ONLY */ status = bind(lis->fd, (struct sockaddr *)&(lis->address), httpAddrLength(&(lis->address))); } else - #endif /* AF_INET6 */ - #ifdef AF_LOCAL +#endif /* AF_INET6 */ +#ifdef AF_LOCAL if (lis->address.addr.sa_family == AF_LOCAL) { mode_t mask; /* Umask setting */ @@ -258,7 +258,7 @@ cupsdStartListening(void) umask(mask); } else - #endif /* AF_LOCAL */ +#endif /* AF_LOCAL */ status = bind(lis->fd, (struct sockaddr *)&(lis->address), sizeof(lis->address.ipv4)); @@ -405,5 +405,5 @@ cupsdStopListening(void) /* - * End of "$Id: listen.c 5020 2006-01-28 13:36:15Z mike $". + * End of "$Id: listen.c 5041 2006-02-01 16:54:50Z mike $". */ diff --git a/scheduler/main.c b/scheduler/main.c index 365453657..7016fa6e8 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -1,5 +1,5 @@ /* - * "$Id: main.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: main.c 5042 2006-02-01 18:17:34Z mike $" * * Scheduler main loop for the Common UNIX Printing System (CUPS). * @@ -1021,14 +1021,14 @@ main(int argc, /* I - Number of command-line arguments */ #ifdef HAVE_NOTIFY_POST if (LastEvent & CUPSD_EVENT_PRINTER_CHANGED) { - cupsdLogMessage(CUPSD_LOG_DEBUG, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerListChange\")"); notify_post("com.apple.printerListChange"); } if (LastEvent & CUPSD_EVENT_PRINTER_STATE_CHANGED) { - cupsdLogMessage(CUPSD_LOG_DEBUG, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerHistoryChange\")"); notify_post("com.apple.printerHistoryChange"); } @@ -1037,7 +1037,7 @@ main(int argc, /* I - Number of command-line arguments */ CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_PROGRESS)) { - cupsdLogMessage(CUPSD_LOG_DEBUG, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.jobChange\")"); notify_post("com.apple.jobChange"); } @@ -1692,22 +1692,28 @@ launchd_sync_conf(void) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) != NULL) { - CFDictionaryAddValue(cupsd_dict, CFSTR("Label"), CFSTR("org.cups.cupsd")); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_LABEL), + CFSTR("org.cups.cupsd")); CFDictionaryAddValue(cupsd_dict, CFSTR("Enabled"), kCFBooleanTrue); - CFDictionaryAddValue(cupsd_dict, CFSTR("OnDemand"), kCFBooleanTrue); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_ONDEMAND), + kCFBooleanTrue); if ((Browsing && BrowseLocalProtocols && cupsArrayCount(Printers)) || cupsArrayCount(ActiveJobs)) - CFDictionaryAddValue(cupsd_dict, CFSTR("RunAtLoad"), kCFBooleanTrue); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD), + kCFBooleanTrue); else - CFDictionaryAddValue(cupsd_dict, CFSTR("RunAtLoad"), kCFBooleanFalse); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD), + kCFBooleanFalse); - CFDictionaryAddValue(cupsd_dict, CFSTR("ServiceIPC"), kCFBooleanTrue); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SERVICEIPC), + kCFBooleanTrue); if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 2, &kCFTypeArrayCallBacks)) != NULL) { - CFDictionaryAddValue(cupsd_dict, CFSTR("ProgramArguments"), array); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS), + array); CFArrayAppendValue(array, CFSTR("/usr/sbin/cupsd")); CFArrayAppendValue(array, CFSTR("-l")); CFRelease(array); @@ -1722,7 +1728,7 @@ launchd_sync_conf(void) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) != NULL) { - CFDictionaryAddValue(cupsd_dict, CFSTR("Sockets"), sockets); + CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SOCKETS), sockets); /* * Add a Listeners array to the sockets dictionary... @@ -1752,7 +1758,8 @@ launchd_sync_conf(void) lis->address.un.sun_path, kCFStringEncodingUTF8))) { - CFDictionaryAddValue(listener, CFSTR("SockPathName"), + CFDictionaryAddValue(listener, + CFSTR(LAUNCH_JOBSOCKETKEY_PATHNAME), socket_path); CFRelease(socket_path); } @@ -1772,14 +1779,16 @@ launchd_sync_conf(void) # ifdef AF_INET6 if (lis->address.addr.sa_family == AF_INET6) { - CFDictionaryAddValue(listener, CFSTR("SockFamily"), + CFDictionaryAddValue(listener, + CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY), CFSTR("IPv6")); portnum = lis->address.ipv6.sin6_port; } else # endif /* AF_INET6 */ { - CFDictionaryAddValue(listener, CFSTR("SockFamily"), + CFDictionaryAddValue(listener, + CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY), CFSTR("IPv4")); portnum = lis->address.ipv4.sin_port; } @@ -1794,7 +1803,9 @@ launchd_sync_conf(void) if (value) { - CFDictionaryAddValue(listener, CFSTR("SockServiceName"), value); + CFDictionaryAddValue(listener, + CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME), + value); CFRelease(value); } @@ -1802,7 +1813,9 @@ launchd_sync_conf(void) if ((value = CFStringCreateWithCString(kCFAllocatorDefault, temp, kCFStringEncodingUTF8))) { - CFDictionaryAddValue(listener, CFSTR("SockNodeName"), value); + CFDictionaryAddValue(listener, + CFSTR(LAUNCH_JOBSOCKETKEY_NODENAME), + value); CFRelease(value); } } @@ -1831,8 +1844,10 @@ launchd_sync_conf(void) { CFArrayAppendValue(array, listener); - CFDictionaryAddValue(listener, CFSTR("SockFamily"), CFSTR("IPv4")); - CFDictionaryAddValue(listener, CFSTR("SockType"), CFSTR("dgram")); + CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY), + CFSTR("IPv4")); + CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_TYPE), + CFSTR("dgram")); if ((service = getservbyport(BrowsePort, NULL))) value = CFStringCreateWithCString(kCFAllocatorDefault, @@ -1842,7 +1857,8 @@ launchd_sync_conf(void) value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &BrowsePort); - CFDictionaryAddValue(listener, CFSTR("SockServiceName"), value); + CFDictionaryAddValue(listener, + CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME), value); CFRelease(value); CFRelease(listener); @@ -1920,6 +1936,7 @@ process_children(void) int pid; /* Process ID of child */ cupsd_job_t *job; /* Current job */ int i; /* Looping var */ + char name[1024]; /* Process name */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "process_children()"); @@ -1942,31 +1959,31 @@ process_children(void) if ((pid = wait(&status)) > 0) #endif /* HAVE_WAITPID */ { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "process_children: pid = %d, status = %d\n", pid, status); - /* * Ignore SIGTERM errors - that comes when a job is cancelled... */ + cupsdFinishProcess(pid, name, sizeof(name)); + if (status == SIGTERM) status = 0; if (status) { if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d stopped with status %d!", pid, - WEXITSTATUS(status)); + cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) stopped with status %d!", + pid, name, WEXITSTATUS(status)); else - cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d crashed on signal %d!", pid, - WTERMSIG(status)); + cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) crashed on signal %d!", + pid, name, WTERMSIG(status)); if (LogLevel < CUPSD_LOG_DEBUG) cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Try setting the LogLevel to \"debug\" to find out more."); } else - cupsdLogMessage(CUPSD_LOG_DEBUG2, "PID %d exited with no errors.", pid); + cupsdLogMessage(CUPSD_LOG_DEBUG, "PID %d (%s) exited with no errors.", + pid, name); /* * Delete certificates for CGI processes... @@ -2014,6 +2031,13 @@ process_children(void) job->status = status; /* Filter failed */ else job->status = -status; /* Backend failed */ + + if (job->printer && !(job->printer->type & CUPS_PRINTER_FAX)) + { + snprintf(job->printer->state_message, + sizeof(job->printer->state_message), "%s failed", name); + cupsdAddPrinterHistory(job->printer); + } } /* @@ -2292,5 +2316,5 @@ usage(int status) /* O - Exit status */ /* - * End of "$Id: main.c 5023 2006-01-29 14:39:44Z mike $". + * End of "$Id: main.c 5042 2006-02-01 18:17:34Z mike $". */ diff --git a/scheduler/network.c b/scheduler/network.c index 0065dc09c..1c2875f4f 100644 --- a/scheduler/network.c +++ b/scheduler/network.c @@ -1,10 +1,10 @@ /* - * "$Id: network.c 4779 2005-10-12 19:44:42Z mike $" + * "$Id: network.c 5043 2006-02-01 18:55:16Z mike $" * * Network interface functions for the Common UNIX Printing System * (CUPS) scheduler. * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -27,6 +27,7 @@ * cupsdNetIFFind() - Find a network interface. * cupsdNetIFFree() - Free the current network interface list. * cupsdNetIFUpdate() - Update the network interface list as needed... + * compare_netif() - Compare two network interfaces. * getifaddrs() - Get a list of network interfaces on the system. * freeifaddrs() - Free an interface list... */ @@ -39,6 +40,15 @@ #include + +/* + * Local functions... + */ + +static void cupsdNetIFFree(void); +static int compare_netif(cupsd_netif_t *a, cupsd_netif_t *b); + + #ifdef HAVE_GETIFADDRS /* * Use native getifaddrs() function... @@ -72,8 +82,8 @@ struct ifaddrs /**** Interface Structure ****/ void *ifa_data; /* Interface statistics */ }; -int getifaddrs(struct ifaddrs **addrs); -void freeifaddrs(struct ifaddrs *addrs); +static int getifaddrs(struct ifaddrs **addrs); +static void freeifaddrs(struct ifaddrs *addrs); #endif /* HAVE_GETIFADDRS */ @@ -84,7 +94,7 @@ void freeifaddrs(struct ifaddrs *addrs); cupsd_netif_t * /* O - Network interface data */ cupsdNetIFFind(const char *name) /* I - Name of interface */ { - cupsd_netif_t *temp; /* Current network interface */ + cupsd_netif_t key; /* Search key */ /* @@ -97,11 +107,9 @@ cupsdNetIFFind(const char *name) /* I - Name of interface */ * Search for the named interface... */ - for (temp = NetIFList; temp != NULL; temp = temp->next) - if (!strcasecmp(name, temp->name)) - return (temp); + strlcpy(key.name, name, sizeof(key.name)); - return (NULL); + return ((cupsd_netif_t *)cupsArrayFind(NetIFList, &key)); } @@ -109,23 +117,22 @@ cupsdNetIFFind(const char *name) /* I - Name of interface */ * 'cupsdNetIFFree()' - Free the current network interface list. */ -void +static void cupsdNetIFFree(void) { - cupsd_netif_t *next; /* Next interface in list */ + cupsd_netif_t *current; /* Current interface in array */ /* * Loop through the interface list and free all the records... */ - while (NetIFList != NULL) + for (current = (cupsd_netif_t *)cupsArrayFirst(NetIFList); + current; + current = (cupsd_netif_t *)cupsArrayNext(NetIFList)) { - next = NetIFList->next; - - free(NetIFList); - - NetIFList = next; + cupsArrayRemove(NetIFList, current); + free(current); } } @@ -140,12 +147,11 @@ cupsdNetIFUpdate(void) int i, /* Looping var */ match; /* Matching address? */ cupsd_listener_t *lis; /* Listen address */ - cupsd_netif_t *temp, /* New interface */ - *prev, /* Previous interface */ - *current; /* Current interface */ + cupsd_netif_t *temp; /* New interface */ struct ifaddrs *addrs, /* Interface address list */ *addr; /* Current interface address */ http_addrlist_t *saddr; /* Current server address */ + char hostname[1024]; /* Hostname for address */ /* @@ -164,6 +170,16 @@ cupsdNetIFUpdate(void) cupsdNetIFFree(); + /* + * Make sure we have an array... + */ + + if (!NetIFList) + NetIFList = cupsArrayNew((cups_array_func_t)compare_netif, NULL); + + if (!NetIFList) + return; + /* * Grab a new list of interfaces... */ @@ -187,37 +203,50 @@ cupsdNetIFUpdate(void) continue; /* - * OK, we have an IPv4/6 address, so create a new list node... + * Try looking up the hostname for the address as needed... */ - if ((temp = calloc(1, sizeof(cupsd_netif_t))) == NULL) - break; + if (HostNameLookups) + httpAddrLookup((http_addr_t *)(addr->ifa_addr), hostname, + sizeof(hostname)); + else + { + /* + * Map the default server address and localhost to the server name + * and localhost, respectively; for all other addresses, use the + * dotted notation... + */ - /* - * Insert the node in sorted order; since we don't expect to - * have a lot of network interfaces, we just do a simple linear - * search... - */ + if (httpAddrLocalhost((http_addr_t *)(addr->ifa_addr))) + strcpy(hostname, "localhost"); + else + { + for (saddr = ServerAddrs; saddr; saddr = saddr->next) + if (httpAddrEqual((http_addr_t *)(addr->ifa_addr), &(saddr->addr))) + break; - for (current = NetIFList, prev = NULL; - current; - prev = current, current = current->next) - if (strcasecmp(addr->ifa_name, current->name) <= 0) - break; + if (saddr) + strlcpy(hostname, ServerName, sizeof(hostname)); + else + httpAddrString((http_addr_t *)(addr->ifa_addr), hostname, + sizeof(hostname)); + } + } - if (current) - temp->next = current; + /* + * Create a new address element... + */ - if (prev) - prev->next = temp; - else - NetIFList = temp; + if ((temp = calloc(1, sizeof(cupsd_netif_t) + + strlen(hostname))) == NULL) + break; /* - * Then copy all of the information... + * Copy all of the information... */ strlcpy(temp->name, addr->ifa_name, sizeof(temp->name)); + strcpy(temp->hostname, hostname); /* Safe because hostname is allocated */ if (addr->ifa_addr->sa_family == AF_INET) { @@ -299,34 +328,10 @@ cupsdNetIFUpdate(void) } /* - * Finally, try looking up the hostname for the address as needed... + * Add it to the array... */ - if (HostNameLookups) - httpAddrLookup(&(temp->address), temp->hostname, sizeof(temp->hostname)); - else - { - /* - * Map the default server address and localhost to the server name - * and localhost, respectively; for all other addresses, use the - * dotted notation... - */ - - if (httpAddrLocalhost(&(temp->address))) - strcpy(temp->hostname, "localhost"); - else - { - for (saddr = ServerAddrs; saddr; saddr = saddr->next) - if (httpAddrEqual(&(temp->address), &(saddr->addr))) - break; - - if (saddr) - strlcpy(temp->hostname, ServerName, sizeof(temp->hostname)); - else - httpAddrString(&(temp->address), temp->hostname, - sizeof(temp->hostname)); - } - } + cupsArrayAdd(NetIFList, temp); cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: \"%s\" = %s...", temp->name, temp->hostname); @@ -336,12 +341,24 @@ cupsdNetIFUpdate(void) } +/* + * 'compare_netif()' - Compare two network interfaces. + */ + +static int /* O - Result of comparison */ +compare_netif(cupsd_netif_t *a, /* I - First network interface */ + cupsd_netif_t *b) /* I - Second network interface */ +{ + return (strcmp(a->name, b->name)); +} + + #ifndef HAVE_GETIFADDRS /* * 'getifaddrs()' - Get a list of network interfaces on the system. */ -int /* O - 0 on success, -1 on error */ +static int /* O - 0 on success, -1 on error */ getifaddrs(struct ifaddrs **addrs) /* O - List of interfaces */ { int sock; /* Socket */ @@ -517,7 +534,7 @@ getifaddrs(struct ifaddrs **addrs) /* O - List of interfaces */ * 'freeifaddrs()' - Free an interface list... */ -void +static void freeifaddrs(struct ifaddrs *addrs) /* I - Interface list to free */ { struct ifaddrs *next; /* Next interface in list */ @@ -572,5 +589,5 @@ freeifaddrs(struct ifaddrs *addrs) /* I - Interface list to free */ /* - * End of "$Id: network.c 4779 2005-10-12 19:44:42Z mike $". + * End of "$Id: network.c 5043 2006-02-01 18:55:16Z mike $". */ diff --git a/scheduler/network.h b/scheduler/network.h index a04b539fd..21e810c3c 100644 --- a/scheduler/network.h +++ b/scheduler/network.h @@ -1,10 +1,10 @@ /* - * "$Id: network.h 4719 2005-09-28 21:12:44Z mike $" + * "$Id: network.h 5043 2006-02-01 18:55:16Z mike $" * * Network interface definitions for the Common UNIX Printing System * (CUPS) scheduler. * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -29,15 +29,13 @@ typedef struct cupsd_netif_s /**** Network interface data ****/ { - struct cupsd_netif_s *next; /* Next interface in list */ - char name[32], /* Network interface name */ - hostname[HTTP_MAX_HOST]; - /* Hostname associated with interface */ int is_local, /* Local (not point-to-point) interface? */ port; /* Listen port */ http_addr_t address, /* Network address */ mask, /* Network mask */ broadcast; /* Broadcast address */ + char name[32], /* Network interface name */ + hostname[1]; /* Hostname associated with interface */ } cupsd_netif_t; @@ -47,18 +45,17 @@ typedef struct cupsd_netif_s /**** Network interface data ****/ VAR time_t NetIFTime VALUE(0); /* Network interface list time */ -VAR cupsd_netif_t *NetIFList VALUE(NULL); - /* List of network interfaces */ +VAR cups_array_t *NetIFList VALUE(NULL); + /* Array of network interfaces */ /* * Prototypes... */ extern cupsd_netif_t *cupsdNetIFFind(const char *name); -extern void cupsdNetIFFree(void); extern void cupsdNetIFUpdate(void); /* - * End of "$Id: network.h 4719 2005-09-28 21:12:44Z mike $". + * End of "$Id: network.h 5043 2006-02-01 18:55:16Z mike $". */ diff --git a/scheduler/printers.c b/scheduler/printers.c index 74a893b3c..801606b4d 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -1,5 +1,5 @@ /* - * "$Id: printers.c 4989 2006-01-26 00:59:45Z mike $" + * "$Id: printers.c 5039 2006-02-01 16:29:57Z mike $" * * Printer routines for the Common UNIX Printing System (CUPS). * @@ -242,6 +242,11 @@ cupsdAddPrinterHistory( ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-shared", p->shared); ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message", NULL, p->state_message); +#ifdef __APPLE__ + if (p->recoverable) + ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, + "com.apple.print.recoverable-message", NULL, p->recoverable); +#endif /* __APPLE__ */ if (p->num_reasons == 0) ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "printer-state-reasons", NULL, @@ -719,12 +724,32 @@ cupsdDeletePrinter( #endif /* __sgi */ /* - * If p is the default printer, assign the next one... - * TODO: use next network default printer or NULL... + * If p is the default printer, assign a different one... */ if (p == DefaultPrinter) - DefaultPrinter = (cupsd_printer_t *)cupsArrayFirst(Printers); + { + DefaultPrinter = NULL; + + if (UseNetworkDefault) + { + /* + * Find the first network default printer and use it... + */ + + cupsd_printer_t *dp; /* New default printer */ + + + for (dp = (cupsd_printer_t *)cupsArrayFirst(Printers); + dp; + dp = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (dp != p && (dp->type & CUPS_PRINTER_DEFAULT)) + { + DefaultPrinter = p; + break; + } + } + } /* * Remove this printer from any classes and send a browse delete message... @@ -776,6 +801,10 @@ cupsdDeletePrinter( cupsdClearString(&p->op_policy); cupsdClearString(&p->error_policy); +#ifdef __APPLE__ + cupsdClearString(&p->recoverable); +#endif /* __APPLE__ */ + free(p); /* @@ -1422,8 +1451,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ int num_media; /* Number of media options */ cupsd_location_t *auth; /* Pointer to authentication element */ const char *auth_supported;/* Authentication supported */ - cups_ptype_t cupsd_printer_type; - /* Printer type data */ + cups_ptype_t printer_type; /* Printer type data */ ppd_file_t *ppd; /* PPD file data */ ppd_option_t *input_slot, /* InputSlot options */ *media_type, /* MediaType options */ @@ -1549,7 +1577,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ } } - cupsd_printer_type = p->type; + printer_type = p->type; p->raw = 0; @@ -1894,7 +1922,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ ppdClose(ppd); - cupsd_printer_type = p->type; + printer_type = p->type; } else if (!access(filename, 0)) { @@ -1958,7 +1986,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ * Tell the client this is really a hard-wired remote printer. */ - cupsd_printer_type |= CUPS_PRINTER_REMOTE; + printer_type |= CUPS_PRINTER_REMOTE; /* * Point the printer-uri-supported attribute to the @@ -2002,18 +2030,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ } } - /* - * Add the CUPS-specific printer-type attribute... - */ - - if (!p->shared) - p->type |= CUPS_PRINTER_NOT_SHARED; - else - p->type &= ~CUPS_PRINTER_NOT_SHARED; - - ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", - cupsd_printer_type); - DEBUG_printf(("cupsdSetPrinterAttrs: leaving name = %s, type = %x\n", p->name, p->type)); @@ -2882,5 +2898,5 @@ write_irix_state(cupsd_printer_t *p) /* I - Printer to update */ /* - * End of "$Id: printers.c 4989 2006-01-26 00:59:45Z mike $". + * End of "$Id: printers.c 5039 2006-02-01 16:29:57Z mike $". */ diff --git a/scheduler/printers.h b/scheduler/printers.h index 9149952bc..b11b96068 100644 --- a/scheduler/printers.h +++ b/scheduler/printers.h @@ -1,5 +1,5 @@ /* - * "$Id: printers.h 4970 2006-01-24 14:05:45Z mike $" + * "$Id: printers.h 5039 2006-02-01 16:29:57Z mike $" * * Printer definitions for the Common UNIX Printing System (CUPS) scheduler. * @@ -80,6 +80,9 @@ typedef struct cupsd_printer_s int num_history; /* Number of history collections */ ipp_t **history; /* History data */ int sequence_number; /* Increasing sequence number */ +#ifdef __APPLE__ + char *recoverable; /* com.apple.print.recoverable-message */ +#endif /* __APPLE__ */ } cupsd_printer_t; @@ -141,5 +144,5 @@ extern char *cupsdSanitizeURI(const char *uri, char *buffer, /* - * End of "$Id: printers.h 4970 2006-01-24 14:05:45Z mike $". + * End of "$Id: printers.h 5039 2006-02-01 16:29:57Z mike $". */ diff --git a/scheduler/process.c b/scheduler/process.c index cba826f50..614ee7ad2 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -1,9 +1,9 @@ /* - * "$Id: process.c 4719 2005-09-28 21:12:44Z mike $" + * "$Id: process.c 5046 2006-02-01 22:11:58Z mike $" * * Process management routines for the Common UNIX Printing System (CUPS). * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -23,8 +23,10 @@ * * Contents: * - * cupsdEndProcess() - End a process. - * cupsdStartProcess() - Start a process. + * cupsdEndProcess() - End a process. + * cupsdFinishProcess() - Finish a process and get its name. + * cupsdStartProcess() - Start a process. + * compare_procs() - Compare two processes. */ /* @@ -35,6 +37,31 @@ #include +/* + * Process structure... + */ + +typedef struct +{ + int pid; /* Process ID */ + char name[1]; /* Name of process */ +} cupsd_proc_t; + + +/* + * Local globals... + */ + +static cups_array_t *process_array = NULL; + + +/* + * Local functions... + */ + +static int compare_procs(cupsd_proc_t *a, cupsd_proc_t *b); + + /* * 'cupsdEndProcess()' - End a process. */ @@ -50,6 +77,34 @@ cupsdEndProcess(int pid, /* I - Process ID */ } +/* + * 'cupsdFinishProcess()' - Finish a process and get its name. + */ + +const char * /* O - Process name */ +cupsdFinishProcess(int pid, /* I - Process ID */ + char *name, /* I - Name buffer */ + int namelen) /* I - Size of name buffer */ +{ + cupsd_proc_t key, /* Search key */ + *proc; /* Matching process */ + + + key.pid = pid; + + if ((proc = (cupsd_proc_t *)cupsArrayFind(process_array, &key)) != NULL) + { + strlcpy(name, proc->name, namelen); + cupsArrayRemove(process_array, proc); + free(proc); + + return (name); + } + else + return ("unknown"); +} + + /* * 'cupsdStartProcess()' - Start a process. */ @@ -66,15 +121,61 @@ cupsdStartProcess( int root, /* I - Run as root? */ int *pid) /* O - Process ID */ { + cupsd_proc_t *proc; /* New process record */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* POSIX signal handler */ + struct sigaction action; /* POSIX signal handler */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +#if defined(__APPLE__) && __GNUC__ < 4 + int envc; /* Number of environment variables */ + char processPath[1024], /* CFProcessPath environment variable */ + linkpath[1024]; /* Link path for symlinks... */ + int linkbytes; /* Bytes for link path */ +#endif /* __APPLE__ && __GNUC__ < 4 */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess(\"%s\", %p, %p, %d, %d, %d)", command, argv, envp, infd, outfd, errfd); +#if defined(__APPLE__) && __GNUC__ < 4 + /* + * Add special voodoo magic for MacOS X 10.3 and earlier - this allows + * MacOS X programs to access their bundle resources properly... + */ + + for (envc = 0; envc < MAX_ENV && envp[envc]; envc ++); + /* All callers pass in a MAX_ENV element array of environment strings */ + + if (envc < (MAX_ENV - 1)) + { + /* + * We have room, try to read the symlink path for this command... + */ + + if ((linkbytes = readlink(linkpath, sizeof(linkpath) - 1)) > 0) + { + /* + * Yes, this is a symlink to the actual program, nul-terminate and + * use it... + */ + + linkpath[linkbytes] = '\0'; + + if (linkpath[0] == '/') + snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", + linkpath); + else + snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s", + dirname(command), linkpath); + } + else + snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command); + + envp[envc++] = processPath; + envp[envc] = NULL; + } +#endif /* __APPLE__ && __GNUC__ > 3 */ + /* * Block signals before forking... */ @@ -142,10 +243,10 @@ cupsdStartProcess( */ if (setgid(Group)) - exit(errno); + exit(errno); if (setgroups(1, &Group)) - exit(errno); + exit(errno); if (setuid(User)) exit(errno); @@ -156,6 +257,7 @@ cupsdStartProcess( * Reset group membership to just the main one we belong to. */ + setgid(Group); setgroups(1, &Group); } @@ -212,6 +314,22 @@ cupsdStartProcess( *pid = 0; } + else + { + if (!process_array) + process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL); + + if (process_array) + { + if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL) + { + proc->pid = *pid; + strcpy(proc->name, command); + + cupsArrayAdd(process_array, proc); + } + } + } cupsdReleaseSignals(); @@ -220,5 +338,17 @@ cupsdStartProcess( /* - * End of "$Id: process.c 4719 2005-09-28 21:12:44Z mike $". + * 'compare_procs()' - Compare two processes. + */ + +static int /* O - Result of comparison */ +compare_procs(cupsd_proc_t *a, /* I - First process */ + cupsd_proc_t *b) /* I - Second process */ +{ + return (a->pid - b->pid); +} + + +/* + * End of "$Id: process.c 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/statbuf.c b/scheduler/statbuf.c index eedec49c3..3161de5f8 100644 --- a/scheduler/statbuf.c +++ b/scheduler/statbuf.c @@ -1,10 +1,10 @@ /* - * "$Id: statbuf.c 4719 2005-09-28 21:12:44Z mike $" + * "$Id: statbuf.c 5038 2006-02-01 16:03:02Z mike $" * * Status buffer routines for the Common UNIX Printing System (CUPS) * scheduler. * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -304,6 +304,8 @@ cupsdStatBufUpdate(cupsd_statbuf_t *sb, /* I - Status buffer */ else cupsdLogMessage(*loglevel, "%s %s", sb->prefix, message); } + else if (*loglevel < CUPSD_LOG_NONE && LogLevel == CUPSD_LOG_DEBUG2) + cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s %s", sb->prefix, sb->buffer); /* * Copy the message to the line buffer... @@ -326,5 +328,5 @@ cupsdStatBufUpdate(cupsd_statbuf_t *sb, /* I - Status buffer */ /* - * End of "$Id: statbuf.c 4719 2005-09-28 21:12:44Z mike $". + * End of "$Id: statbuf.c 5038 2006-02-01 16:03:02Z mike $". */ diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c index 2d8d43fb7..d77b33f78 100644 --- a/scheduler/subscriptions.c +++ b/scheduler/subscriptions.c @@ -1,5 +1,5 @@ /* - * "$Id: subscriptions.c 4993 2006-01-26 19:27:40Z mike $" + * "$Id: subscriptions.c 5046 2006-02-01 22:11:58Z mike $" * * Subscription routines for the Common UNIX Printing System (CUPS) scheduler. * @@ -39,6 +39,7 @@ * cupsdUpdateNotifierStatus() - Read messages from notifiers. * cupsd_compare_subscriptions() - Compare two subscriptions. * cupsd_delete_event() - Delete a single event... + * cupsd_send_dbus() - Send a DBUS notification... * cupsd_start_notifier() - Start a notifier subprocess... */ @@ -47,6 +48,9 @@ */ #include "cupsd.h" +#ifdef HAVE_DBUS +# include +#endif /* HAVE_DBUS */ /* @@ -57,6 +61,10 @@ static int cupsd_compare_subscriptions(cupsd_subscription_t *first, cupsd_subscription_t *second, void *unused); static void cupsd_delete_event(cupsd_event_t *event); +#ifdef HAVE_DBUS +static void cupsd_send_dbus(cupsd_eventmask_t event, cupsd_printer_t *dest, + cupsd_job_t *job); +#endif /* HAVE_DBUS */ static void cupsd_start_notifier(cupsd_subscription_t *sub); @@ -79,8 +87,16 @@ cupsdAddEvent( cupsd_subscription_t *sub; /* Current subscription */ + /* + * Keep track of events with any OS-supplied notification mechanisms... + */ + LastEvent |= event; +#ifdef HAVE_DBUS + cupsd_send_dbus(event, dest, job); +#endif /* HAVE_DBUS */ + /* * Return if we aren't keeping events... */ @@ -1408,6 +1424,86 @@ cupsd_delete_event(cupsd_event_t *event)/* I - Event to delete */ } +#ifdef HAVE_DBUS +/* + * 'cupsd_send_dbus()' - Send a DBUS notification... + */ + +static void +cupsd_send_dbus(cupsd_eventmask_t event,/* I - Event to send */ + cupsd_printer_t *dest,/* I - Destination, if any */ + cupsd_job_t *job) /* I - Job, if any */ +{ + DBusError error; /* Error, if any */ + DBusMessage *message; /* Message to send */ + DBusMessageIter iter; /* Iterator for message data */ + const char *what; /* What to send */ + static DBusConnection *con = NULL; /* Connection to DBUS server */ + + + /* + * Figure out what to send, if anything... + */ + + if (event & CUPSD_EVENT_PRINTER_ADDED) + what = "PrinterAdded"; + else if (event & CUPSD_EVENT_PRINTER_DELETED) + what = "PrinterRemoved"; + else if (event & CUPSD_EVENT_PRINTER_CHANGED) + what = "QueueChanged"; + else if (event & CUPSD_EVENT_JOB_CREATED) + what = "JobQueuedLocal"; + else if ((event & CUPSD_EVENT_JOB_STATE) && job && + job->state->values[0].integer == IPP_JOB_PROCESSING) + what = "JobStartedLocal"; + else + return; + + /* + * Verify connection to DBUS server... + */ + + if (con && !dbus_connection_get_is_connected(con)) + { + dbus_connection_unref(con); + con = NULL; + } + + if (!con) + { + dbus_error_init(&error); + + con = dbus_bus_get(getuid() ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &error); + if (!con) + { + dbus_error_free(&error); + return; + } + } + + /* + * Create and send the new message... + */ + + message = dbus_message_new_signal("/com/redhat/PrinterSpooler", + "com.redhat.PrinterSpooler", what); + + dbus_message_iter_init_append(message, &iter); + if (dest) + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &(dest->name)); + if (job) + { + dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &(job->id)); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &(job->username)); + } + + dbus_connection_send(con, message, NULL); + dbus_connection_flush(con); + dbus_message_unref(message); +} +#endif /* HAVE_DBUS */ + + /* * 'cupsd_start_notifier()' - Start a notifier subprocess... */ @@ -1420,7 +1516,7 @@ cupsd_start_notifier( int fds[2]; /* Pipe file descriptors */ int envc; /* Number of environment variables */ char *argv[4], /* Command-line arguments */ - *envp[100], /* Environment variables */ + *envp[MAX_ENV], /* Environment variables */ user_data[128], /* Base-64 encoded user data */ scheme[256], /* notify-recipient-uri scheme */ *ptr, /* Pointer into scheme */ @@ -1536,5 +1632,5 @@ cupsd_start_notifier( /* - * End of "$Id: subscriptions.c 4993 2006-01-26 19:27:40Z mike $". + * End of "$Id: subscriptions.c 5046 2006-02-01 22:11:58Z mike $". */ diff --git a/scheduler/subscriptions.h b/scheduler/subscriptions.h index ffe0123ab..fb6308cea 100644 --- a/scheduler/subscriptions.h +++ b/scheduler/subscriptions.h @@ -1,5 +1,5 @@ /* - * "$Id: subscriptions.h 4993 2006-01-26 19:27:40Z mike $" + * "$Id: subscriptions.h 5025 2006-01-30 03:49:12Z mike $" * * Subscription definitions for the Common UNIX Printing System (CUPS) scheduler. * @@ -49,22 +49,23 @@ typedef enum CUPSD_EVENT_PRINTER_CHANGED = 0x00ff, /* All of the above */ /* Individual job events... */ - CUPSD_EVENT_JOB_CREATED = 0x0100, /* Send after job is created */ - CUPSD_EVENT_JOB_COMPLETED = 0x0200, /* Sent after job is completed */ - CUPSD_EVENT_JOB_STOPPED = 0x0400, /* Sent after job is stopped */ - CUPSD_EVENT_JOB_CONFIG_CHANGED = 0x0800, + CUPSD_EVENT_JOB_STATE = 0x0100, /* Any state change */ + CUPSD_EVENT_JOB_CREATED = 0x0200, /* Send after job is created */ + CUPSD_EVENT_JOB_COMPLETED = 0x0400, /* Sent after job is completed */ + CUPSD_EVENT_JOB_STOPPED = 0x0800, /* Sent after job is stopped */ + CUPSD_EVENT_JOB_CONFIG_CHANGED = 0x1000, /* Sent after set-job-attributes */ - CUPSD_EVENT_JOB_PROGRESS = 0x1000, /* Sent for each page */ + CUPSD_EVENT_JOB_PROGRESS = 0x2000, /* Sent for each page */ /* Convenience job event grouping... */ - CUPSD_EVENT_JOB_STATE_CHANGED = 0x0700, - /* CREATED + COMPLETED + STOPPED */ + CUPSD_EVENT_JOB_STATE_CHANGED = 0x0f00, + /* Any state change + CREATED + COMPLETED + STOPPED */ /* Server events... */ - CUPSD_EVENT_SERVER_RESTARTED = 0x2000,/* Sent after server restarts */ - CUPSD_EVENT_SERVER_STARTED = 0x4000, /* Sent when server first starts */ - CUPSD_EVENT_SERVER_STOPPED = 0x8000, /* Sent when server is stopped */ - CUPSD_EVENT_SERVER_AUDIT = 0x10000, /* Security-related stuff */ + CUPSD_EVENT_SERVER_RESTARTED = 0x4000,/* Sent after server restarts */ + CUPSD_EVENT_SERVER_STARTED = 0x8000, /* Sent when server first starts */ + CUPSD_EVENT_SERVER_STOPPED = 0x10000, /* Sent when server is stopped */ + CUPSD_EVENT_SERVER_AUDIT = 0x20000, /* Security-related stuff */ /* Everything and nothing... */ CUPSD_EVENT_NONE = 0, /* Nothing */ @@ -174,5 +175,5 @@ extern void cupsdUpdateNotifierStatus(void); /* - * End of "$Id: subscriptions.h 4993 2006-01-26 19:27:40Z mike $". + * End of "$Id: subscriptions.h 5025 2006-01-30 03:49:12Z mike $". */ diff --git a/templates/classes.tmpl b/templates/classes.tmpl index 4a5a92f04..64f0b9431 100644 --- a/templates/classes.tmpl +++ b/templates/classes.tmpl @@ -1,6 +1,7 @@ {#printer_name=0?: {[printer_name] -

{printer_name}{default_name={printer_name}? (Default Printer):}

+

{printer_name}{default_name={printer_name}? (Default Printer):} +{?printer_state_message=?:"{printer_state_message}"}

@@ -10,7 +11,6 @@ Location: {printer_location}
Class State: {printer_state=3?idle:{printer_state=4?processing:stopped}}, {printer_is_accepting_jobs=0?rejecting jobs:accepting jobs}, {printer_is_shared=0?not:} published. -{?printer_state_message=?:
"{printer_state_message}"} {?member_uris=?:
Members: {member_uris}}

diff --git a/templates/printers.tmpl b/templates/printers.tmpl index d13997f48..0520b5afc 100644 --- a/templates/printers.tmpl +++ b/templates/printers.tmpl @@ -1,6 +1,7 @@ {#printer_name=0?: {[printer_name] -

{printer_name}{default_name={printer_name}? (Default Printer):}

+

{printer_name}{default_name={printer_name}? (Default Printer):} +{?printer_state_message=?:"{printer_state_message}"}

@@ -12,11 +13,6 @@ Make and Model: {printer_make_and_model}
Printer State: {printer_state=3?idle:{printer_state=4?processing:stopped}}, {printer_is_accepting_jobs=0?rejecting jobs:accepting jobs}, {printer_is_shared=0?not:} published. -{?printer_state_message=?:
"{printer_state_message}"} -{?printer_state_history2.printer_state_message=?:
"{printer_state_history2.printer_state_message}"} -{?printer_state_history3.printer_state_message=?:
"{printer_state_history3.printer_state_message}"} -{?printer_state_history4.printer_state_message=?:
"{printer_state_history4.printer_state_message}"} -{?printer_state_history5.printer_state_message=?:
"{printer_state_history5.printer_state_message}"} {?device_uri=?:
Device URI: {device_uri}}

diff --git a/test/ipptest.c b/test/ipptest.c index fa73d0fcc..199ebe44f 100644 --- a/test/ipptest.c +++ b/test/ipptest.c @@ -1,5 +1,5 @@ /* - * "$Id: ipptest.c 5023 2006-01-29 14:39:44Z mike $" + * "$Id: ipptest.c 5037 2006-02-01 15:19:59Z mike $" * * IPP test command for the Common UNIX Printing System (CUPS). * @@ -23,11 +23,12 @@ * * Contents: * - * main() - Parse options and do tests. - * do_tests() - Do tests as specified in the test file. - * get_tag() - Get an IPP value or group tag from a name... - * get_token() - Get a token from a file. - * print_attr() - Print an attribute on the screen. + * main() - Parse options and do tests. + * do_tests() - Do tests as specified in the test file. + * get_tag() - Get an IPP value or group tag from a name... + * get_token() - Get a token from a file. + * print_attr() - Print an attribute on the screen. + * usage() - Show program usage. */ /* @@ -44,6 +45,13 @@ #include +/* + * Globals... + */ + +int Verbosity = 0; /* Show all attributes? */ + + /* * Local functions... */ @@ -54,6 +62,7 @@ ipp_status_t ippErrorValue(const char *); ipp_tag_t get_tag(const char *); char *get_token(FILE *, char *, int, int *linenum); void print_attr(ipp_attribute_t *); +void usage(const char *option); /* @@ -66,6 +75,8 @@ main(int argc, /* I - Number of command-line arguments */ { int i; /* Looping var */ int status; /* Status of tests... */ + const char *uri; /* URI to use */ + const char *testfile; /* Test file to use */ /* @@ -74,24 +85,54 @@ main(int argc, /* I - Number of command-line arguments */ * testipp URL testfile */ - if (argc < 3) + uri = NULL; + testfile = NULL; + status = 0; + + for (i = 1; i < argc; i ++) { - fputs("Usage: ipptest URL testfile [ ... testfileN ]\n", stderr); - return (1); - } + if (argv[i][0] == '-') + { + if (!strcmp(argv[i], "-v")) + Verbosity ++; + else + usage(argv[i]); + } + else if (!strncmp(argv[i], "ipp://", 6) || + !strncmp(argv[i], "http://", 7) || + !strncmp(argv[i], "https://", 8)) + { + /* + * Set URI... + */ - /* - * Run tests... - */ + if (!testfile && uri) + usage(NULL); + + uri = argv[i]; + testfile = NULL; + } + else + { + /* + * Run test... + */ + + testfile = argv[i]; + + if (!do_tests(uri, testfile)) + status ++; + } + } - for (i = 2, status = 1; status && i < argc; i ++) - status = status && do_tests(argv[1], argv[i]); + if (!uri || !testfile) + usage(NULL); /* * Exit... */ - return (!status); + return (status); } @@ -525,7 +566,12 @@ do_tests(const char *uri, /* I - URI to connect on */ printf(" RECEIVED: %lu bytes in response\n", (unsigned long)ippLength(response)); - if (num_displayed > 0) + if (Verbosity) + { + for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next) + print_attr(attrptr); + } + else if (num_displayed > 0) { for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next) if (attrptr->name) @@ -786,5 +832,24 @@ print_attr(ipp_attribute_t *attr) /* I - Attribute to print */ /* - * End of "$Id: ipptest.c 5023 2006-01-29 14:39:44Z mike $". + * 'usage()' - Show program usage. + */ + +void +usage(const char *option) /* I - Option string or NULL */ +{ + if (option) + fprintf(stderr, "ipptest: Unknown option \"%s\"!\n", option); + + fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr); + fputs("Options:\n", stderr); + fputs("\n", stderr); + fputs("-v Show all attributes in response, even on success.\n", stderr); + + exit(1); +} + + +/* + * End of "$Id: ipptest.c 5037 2006-02-01 15:19:59Z mike $". */ diff --git a/tools/makesrcdist b/tools/makesrcdist index b0cb5dfe1..de9355472 100755 --- a/tools/makesrcdist +++ b/tools/makesrcdist @@ -41,7 +41,7 @@ svn export $url /tmp/cups-$version echo Updating version information... cd /tmp/cups-$version/config-scripts -sed -e '1,$s/^CUPS_VERSION=.*/CUPS_VERSION='$version'/' \ +sed -e '1,$s/^CUPS_VERSION=.*/CUPS_VERSION='$fileversion'/' \ cups-common.m4.new mv cups-common.m4.new cups-common.m4 cd .. diff --git a/tools/testosx b/tools/testosx index af37a0975..58aa52160 100755 --- a/tools/testosx +++ b/tools/testosx @@ -34,15 +34,26 @@ killall cupsd || exit 0 EOF chmod 755 $pkgdir/Resources/preflight -cat >$pkgdir/Resources/postflight <$pkgdir/Resources/postflight <$pkgdir/Resources/postflight <