]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Load cups into easysw/current.
authorjlovell <jlovell@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 1 Feb 2006 23:41:32 +0000 (23:41 +0000)
committerjlovell <jlovell@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 1 Feb 2006 23:41:32 +0000 (23:41 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@51 a1ca3aef-8c08-0410-bb20-df032aa958be

45 files changed:
CHANGES.txt
Makedefs.in
Makefile
backend/Dependencies
backend/Makefile
berkeley/Dependencies
cgi-bin/Dependencies
config-scripts/cups-common.m4
config-scripts/cups-defaults.m4
config.h.in
cups/Dependencies
cups/dir.c
cups/file.c
cups/http-support.c
cups/usersys.c
doc/cups.css
doc/help/standard.html.in
filter/Dependencies
init/cupsd-launchd.sh [deleted file]
packaging/cups.spec.in
scheduler/auth.c
scheduler/client.c
scheduler/conf.c
scheduler/cups-deviced.c
scheduler/cupsd.h
scheduler/dirsvc.c
scheduler/dirsvc.h
scheduler/env.c
scheduler/ipp.c
scheduler/job.c
scheduler/listen.c
scheduler/main.c
scheduler/network.c
scheduler/network.h
scheduler/printers.c
scheduler/printers.h
scheduler/process.c
scheduler/statbuf.c
scheduler/subscriptions.c
scheduler/subscriptions.h
templates/classes.tmpl
templates/printers.tmpl
test/ipptest.c
tools/makesrcdist
tools/testosx

index 2e9f452f2b44cd281d3d0d8ab0d6726460017901..e820b917e47117d59a920c806cb754f9905f1660 100644 (file)
@@ -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)
index 4bc2e371d0f432541bfd7b3e616b4baf6381d9a4..c3cdf4bb72745a0494395e922d8eff6673813a29 100644 (file)
@@ -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 $"
 #
index 99a042d5b98e71a37b0658a3b4af20879049b4a5..eb98a5dc695de4bab81032b8c84fc990679b698c 100644 (file)
--- 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 $".
 #
index 70897ad972db097717396af640cdf52b5ed4415a..42ce66029aee5820d29478e79f2551ce35bbb621 100644 (file)
@@ -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
index 26ce19b4f9d193696a68ef42062f32e8a39e0edc..92a721a7e5c72ceccdfc44fb71cf50da3fc3f463 100644 (file)
@@ -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 $".
 #
index ceb85278cf3d301b583b9a02653b783b6a085b64..d8db9344af24c7627e0160c6dad1dd0e38a2f2e0 100644 (file)
@@ -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
index 1bfd5141fade9dfe8cac8691a52f65f9406a8d7a..71c7c38694d1bca9a567a39289cd878f964dd41e 100644 (file)
@@ -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
index 18d0bfff127c61e03e5efa3cbbea35fee0ad0ac5..95ba2d9c5b6c0c573b36d6abaec696a57dea9bce 100644 (file)
@@ -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
index 6edee7473ccd9da675899496849d0bf0a38dc422..4da730c2ad229860f09fc321f831ce0cb7bc31eb 100644 (file)
@@ -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$".
index ee1e4bc3468327e1060fc95d1e3be58b310f8f43..032146ea62720faddf6a7c80050dd19c1b4451b5 100644 (file)
@@ -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
 
 
 /*
 #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 $".
  */
index fa951c4ef2bc780a908063b8b993b0bd11130e2b..f4b6f6787b098b25e194c795db4acb8b482c91cb 100644 (file)
@@ -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
index e06edea91ccc34c20a6874c579b446fab0960ada..ac684afeefe5f2ec7f8f5530e6a1972e5923d539 100644 (file)
@@ -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)));
index daad1c3725f8d2fc1aa185945b120e7d9f09494a..e0c135c98172abea2660f16411c6a96554415beb 100644 (file)
@@ -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 $".
  */
index 3103007aadd9a8d1078f6d207a48dbc12e34fd1a..1ad095baed52435105e223e8e2600ec3ad354288 100644 (file)
@@ -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 $".
  */
index 1b73cbdae3734a42aa241ad1b283b9e39548f783..cb25863f34f32acfdc12aad34d9210820b87ddf8 100644 (file)
@@ -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 <stdlib.h>
+#include <sys/stat.h>
 #ifdef WIN32
 #  include <windows.h>
 #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 $".
  */
index a1981b58ae8a038f67218a6ff21493152477d2f7..fe76ae63355da6290275284eb98d404112fe2b55 100644 (file)
@@ -226,3 +226,8 @@ P.summary {
   margin-left: 5em;
   font-family: monospace;
 }
+
+SPAN.message {
+  font-style: italic;
+  font-size: smaller;
+}
index 5003acec90a9c4914e7b310b870249c658a70bc6..699239bc37cd40d04cda96dae9b8ab0f30dec769 100644 (file)
@@ -70,6 +70,10 @@ Basic authentication with membership in the group
        <TD><CODE><A HREF="cupsd-conf-reference.html#LogFilePerm">LogFilePerm</A></CODE></TD>
        <TD><CODE>@CUPS_LOG_FILE_PERM@</CODE></TD>
 </TR>
+<TR>
+       <TD><CODE><A HREF="cupsd-conf-reference.html#UseNetworkDefault">UseNetworkDefault</A></CODE></TD>
+       <TD><CODE>@CUPS_USE_NETWORK_DEFAULT@</CODE></TD>
+</TR>
 </TABLE></DIV>
 
 
index c68bdd6dda6b14b289cf6e13c8351e4aa5f0f4a8..243dc3e9baf491fb6bc9de8fd4e6b12f6aa681c2 100644 (file)
 # 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 (executable)
index c956220..0000000
+++ /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
index d551315cb1e8d322ae0e204073f8532d437b3328..4dc600984c64e8d9b5962452ec59768bf2102da3 100644 (file)
@@ -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
index 0c6cd85d965cb5a74aebfd405333050bb5874ff4..e71cfaa403173f57af6296d4347703c918fc18a9 100644 (file)
@@ -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 $".
  */
index 47e80dd39d71259269b2e14e6629c20cc1f3ad05..396b817d40afb7fe0a21bdf0054f2235af27372e 100644 (file)
@@ -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 $".
  */
index 595cd825bc590c3fc6865f2e4d5d6754036baecb..c7045656170f1097ce4ee9837cbb5d9a5781c5ce 100644 (file)
@@ -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 $".
  */
index 6617d911c7ba8a1ef9ef2a2530a5f8d7b071e1f9..fd0101acd48564f5d719d7ebd18dd4234b1de6c3 100644 (file)
@@ -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 $".
  */
index 7380c3dcd50c32877686bf444b5886fc0ee50402..e6f0fa0ed05f401ffe864bf8cfd903cb170dff90 100644 (file)
@@ -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 $".
  */
index dd63491d96472125dbacb3b3b1fc7cf977e701d8..e48250d3857ccf99a0d03b4f86bc6b9da1de0af9 100644 (file)
@@ -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.
 
 
 /*
- * 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, "<Default");
     else
-      return;
+      cupsFilePutChar(fp, '<');
 
-    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 (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, "</Class>\n");
+    else
+      cupsFilePuts(fp, "</Printer>\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, "<Default");
+  if (p->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, "</Class>\n");
-    else
-      cupsFilePuts(fp, "</Printer>\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 $".
  */
index ff659e5806f3f3a8434c86d3074dc6883d915545..951407efe90044c9df63cfdcf20caab196ba91ac 100644 (file)
@@ -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 $".
  */
index 39a0c6ccb5ec096a107a0d2d122c6274353ae1d8..ec3a8817ddc3770c198404daa3fdaa93300c7b45 100644 (file)
@@ -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, "<CFProcessPath>");
   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 $".
  */
index 8dccbcfa1846423125dd8039a1afca18a7895e21..0c96cf7b117be751957108e442cbc6007035b427 100644 (file)
@@ -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 $".
  */
index 13c1260dd32cec064f9496c4b980a69a7414dc74..3905c408befb68c885b155b69757e6e7f551350d 100644 (file)
@@ -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 $".
  */
index 6c25221486f94bec8cfce66905ddd83f9a33cce3..d5b9ea579a1f832dec63c7563019d6cc4d823c65 100644 (file)
@@ -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 $".
  */
index 365453657dc320950bb372a850255629bd2e1702..7016fa6e80e4d3048d1970003896e6c61e09e354 100644 (file)
@@ -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 $".
  */
index 0065dc09c14cfd28af2c0bbfcd20c3274a6e233f..1c2875f4fb9079de305ab2e4a44c9ce438cb5d72 100644 (file)
@@ -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...
  */
 
 #include <net/if.h>
 
+
+/*
+ * 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 $".
  */
index a04b539fdf25f160f5cd9ba729a8ce0e67b310e7..21e810c3c81a757eb8063078e52a31badc7f7007 100644 (file)
@@ -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
 
 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 $".
  */
index 74a893b3c2f1364ca0aa569260744fe7a9c8869a..801606b4da193417ed3530641f2e206c16cd3b7d 100644 (file)
@@ -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 $".
  */
index 9149952bc869ceb55f64b1dc54b2734349b7c4b3..b11b96068aa6933854c7251fc926b0516ec346ba 100644 (file)
@@ -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 $".
  */
index cba826f50be29cc115cff8959472a8a7bcdfcaa2..614ee7ad2b8c80b7b3fb5de5ad23b799f32eeb4f 100644 (file)
@@ -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
  *
  * 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.
  */
 
 /*
 #include <grp.h>
 
 
+/*
+ * 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 $".
  */
index eedec49c316f599e5a9cc7c3bbc601aa33ff1a0a..3161de5f8ffb38ab7e406879b579a84649f38888 100644 (file)
@@ -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 $".
  */
index 2d8d43fb7fb7b126efc569d43c2692c757a2745a..d77b33f78c8d5b57b35a798dd29680e0a3bfee66 100644 (file)
@@ -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 <dbus/dbus.h>
+#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 $".
  */
index ffe0123ab96568e3b5f0b02291b93025c64feb9f..fb6308ceafa9d57e4d6dc33c624893f11c9b5d86 100644 (file)
@@ -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 $".
  */
index 4a5a92f04d787ccd5e6a0c6677b7a89eac28fdf3..64f0b9431249b992fde2c03136889fdc7e2c3e3d 100644 (file)
@@ -1,6 +1,7 @@
 {#printer_name=0?:
 {[printer_name]
-<H2 CLASS="title"><A HREF="{printer_uri_supported}">{printer_name}</A>{default_name={printer_name}? (Default Printer):}</H2>
+<H2 CLASS="title"><A HREF="{printer_uri_supported}">{printer_name}</A>{default_name={printer_name}? (Default Printer):}
+{?printer_state_message=?:<SPAN CLASS="message">"{printer_state_message}"</SPAN>}</H2>
 
 <TABLE WIDTH="100%" CLASS="button" CELLSPACING="0" CELLPADDING="0">
 <TR>
@@ -10,7 +11,6 @@
 <B>Location:</B> {printer_location}<BR>
 <B>Class State:</B> {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=?:<BR><I>"{printer_state_message}"</I>}
 {?member_uris=?:<BR>Members: {member_uris}}
 
 <P>
index d13997f482564fd455a202b20fa57d0ec9866d5b..0520b5afc9c57a1530d8abb3ae1c28d44f95b3b6 100644 (file)
@@ -1,6 +1,7 @@
 {#printer_name=0?:
 {[printer_name]
-<H2 CLASS="title"><A HREF="{printer_uri_supported}">{printer_name}</A>{default_name={printer_name}? (Default Printer):}</H2>
+<H2 CLASS="title"><A HREF="{printer_uri_supported}">{printer_name}</A>{default_name={printer_name}? (Default Printer):}
+{?printer_state_message=?:<SPAN CLASS="message">"{printer_state_message}"</SPAN>}</H2>
 
 <TABLE WIDTH="100%" CLASS="button" CELLSPACING="0" CELLPADDING="0">
 <TR>
 <B>Make and Model:</B> {printer_make_and_model}<BR>
 <B>Printer State:</B> {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=?:<BR><I>"{printer_state_message}"</I>}
-{?printer_state_history2.printer_state_message=?:<BR><I>"{printer_state_history2.printer_state_message}"</I>}
-{?printer_state_history3.printer_state_message=?:<BR><I>"{printer_state_history3.printer_state_message}"</I>}
-{?printer_state_history4.printer_state_message=?:<BR><I>"{printer_state_history4.printer_state_message}"</I>}
-{?printer_state_history5.printer_state_message=?:<BR><I>"{printer_state_history5.printer_state_message}"</I>}
 {?device_uri=?:<BR><B>Device URI:</B> {device_uri}}
 
 <P>
index fa73d0fcc5cc53fc16aa5fd34399c72911d30842..199ebe44f618304ae5c014b59b9d618bc35228f2 100644 (file)
@@ -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).
  *
  *
  * 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.
  */
 
 /*
 #include <cups/language.h>
 
 
+/*
+ * 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 $".
  */
index b0cb5dfe1a776bbf9c7dd175997b5c05735f5e65..de93554722e66ee0140a5a8a666225930fc96b0f 100755 (executable)
@@ -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 >cups-common.m4.new
 mv cups-common.m4.new cups-common.m4
 cd ..
index af37a09750b75554b4e5c36ca25bd73fe9fb7532..58aa52160c62060aed3195bc4fa08c3c5e45e84a 100755 (executable)
@@ -34,15 +34,26 @@ killall cupsd || exit 0
 EOF
 chmod 755 $pkgdir/Resources/preflight
 
-cat >$pkgdir/Resources/postflight <<EOF
+if test -x /bin/launchctl; then
+       cat >$pkgdir/Resources/postflight <<EOF
 #!/bin/sh
+
+# Remove old startup item, we use launchd now...
+rm -f /System/Library/StartupItems/PrintingServices/PrintingServices
+
+# Tell launchd to reload cupsd...
 launchctl unload /System/Library/LaunchDaemons/org.cups.cupsd.plist || exit 0
 launchctl load /System/Library/LaunchDaemons/org.cups.cupsd.plist
-sleep 1
-if test -e /private/var/run/cupsd; then
-        chmod g+w,o+w /private/var/run/cupsd
-fi
 EOF
+else
+       cat >$pkgdir/Resources/postflight <<EOF
+#!/bin/sh
+
+# Start cupsd...
+/usr/sbin/cupsd
+EOF
+fi
+
 chmod 755 $pkgdir/Resources/postflight
 
 # Tag the current revision in the plist and web interface files...