diff --git a/common/shlibs b/common/shlibs
index 64afaa6331..1c241a6148 100644
--- a/common/shlibs
+++ b/common/shlibs
@@ -973,3 +973,9 @@ libutempter.so.0		libutempter		libutempter-devel
 libxatracker.so.1		MesaLib			MesaLib-devel
 libtumbler-1.so.0		tumbler			tumbler-devel
 libwebrtc_audio_processing.so.0	webrtc-audio-processing	webrtc-audio-processing-devel
+libcupsmime.so.1		libcups			cups-devel
+libcupsppdc.so.1		libcups			cups-devel
+libcupscgi.so.1			libcups			cups-devel
+libcupsdriver.so.1		libcups			cups-devel
+libcups.so.2			libcups			cups-devel
+libcupsimage.so.2		libcups			cups-devel
diff --git a/srcpkgs/cups-devel b/srcpkgs/cups-devel
new file mode 120000
index 0000000000..a1fadc2f3a
--- /dev/null
+++ b/srcpkgs/cups-devel
@@ -0,0 +1 @@
+cups
\ No newline at end of file
diff --git a/srcpkgs/cups/cups-devel.template b/srcpkgs/cups/cups-devel.template
new file mode 100644
index 0000000000..d27f6890af
--- /dev/null
+++ b/srcpkgs/cups/cups-devel.template
@@ -0,0 +1,13 @@
+# Template file for 'cups-devel'.
+#
+short_desc="${short_desc} -- development files"
+long_desc="${long_desc}
+
+ This package contains files for development, headers, static libs, etc."
+
+Add_dependency run libcups ">=${version}"
+
+do_install() {
+	vmove usr/include usr
+	vmove usr/bin/cups-config usr/bin
+}
diff --git a/srcpkgs/cups/cups.rshlibs b/srcpkgs/cups/cups.rshlibs
new file mode 100644
index 0000000000..2845847eb7
--- /dev/null
+++ b/srcpkgs/cups/cups.rshlibs
@@ -0,0 +1,22 @@
+libcupsimage.so.2
+libcups.so.2
+libpthread.so.0
+libc.so.6
+libm.so.6
+libcupsdriver.so.1
+libusb-1.0.so.0
+libcupscgi.so.1
+libdbus-1.so.3
+libcupsppdc.so.1
+libstdc++.so.6
+libgcc_s.so.1
+libcupsmime.so.1
+libssl.so.1
+libcrypto.so.1
+libpam.so.0
+libacl.so.1
+libgssapi_krb5.so.2
+libkrb5.so.3
+libavahi-common.so.3
+libavahi-client.so.3
+libsystemd-daemon.so.0
diff --git a/srcpkgs/cups/depends b/srcpkgs/cups/depends
new file mode 100644
index 0000000000..c5ed341a13
--- /dev/null
+++ b/srcpkgs/cups/depends
@@ -0,0 +1,2 @@
+abi_depends=">=1.5.3"
+api_depends="${abi_depends}"
diff --git a/srcpkgs/cups/files/cups.logrotate b/srcpkgs/cups/files/cups.logrotate
new file mode 100644
index 0000000000..773c70fd2a
--- /dev/null
+++ b/srcpkgs/cups/files/cups.logrotate
@@ -0,0 +1,5 @@
+/var/log/cups/*_log {
+    missingok
+    notifempty
+    sharedscripts
+}
diff --git a/srcpkgs/cups/files/cups.pam b/srcpkgs/cups/files/cups.pam
new file mode 100644
index 0000000000..53724d1f86
--- /dev/null
+++ b/srcpkgs/cups/files/cups.pam
@@ -0,0 +1,3 @@
+auth		required	pam_unix.so
+account		required	pam_unix.so
+session		required	pam_unix.so
diff --git a/srcpkgs/cups/libcups.rshlibs b/srcpkgs/cups/libcups.rshlibs
new file mode 100644
index 0000000000..43018ab065
--- /dev/null
+++ b/srcpkgs/cups/libcups.rshlibs
@@ -0,0 +1,15 @@
+libgssapi_krb5.so.2
+libssl.so.1
+libcrypto.so.1
+libpthread.so.0
+libm.so.6
+libz.so.1
+libc.so.6
+libtiff.so.5
+libpng14.so.14
+libjpeg.so.8
+libcrypt.so.1
+libstdc++.so.6
+libgcc_s.so.1
+libavahi-common.so.3
+libavahi-client.so.3
diff --git a/srcpkgs/cups/libcups.template b/srcpkgs/cups/libcups.template
new file mode 100644
index 0000000000..1b59033d49
--- /dev/null
+++ b/srcpkgs/cups/libcups.template
@@ -0,0 +1,10 @@
+# Template file for 'libcups'.
+#
+short_desc="${short_desc} -- runtime shared libraries"
+long_desc="${long_desc}
+
+ This package contains the runtime shared libraries."
+
+do_install() {
+	vmove "usr/lib/*.so*" usr/lib
+}
diff --git a/srcpkgs/cups/patches/cups-0755.patch b/srcpkgs/cups/patches/cups-0755.patch
new file mode 100644
index 0000000000..dcb625527e
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-0755.patch
@@ -0,0 +1,33 @@
+diff -up cups-1.5.3/Makedefs.in.0755 cups-1.5.3/Makedefs.in
+--- cups-1.5.3/Makedefs.in.0755	2012-05-15 16:51:31.000000000 +0200
++++ cups-1.5.3/Makedefs.in	2012-05-15 16:52:59.246906315 +0200
+@@ -41,14 +41,14 @@ SHELL		=	/bin/sh
+ # Installation programs...
+ #
+ 
+-INSTALL_BIN	=	$(LIBTOOL) $(INSTALL) -c -m 555 @INSTALL_STRIP@
++INSTALL_BIN	=	$(LIBTOOL) $(INSTALL) -c -m 755 @INSTALL_STRIP@
+ INSTALL_CONFIG	=	$(INSTALL) -c -m @CUPS_CONFIG_FILE_PERM@
+ INSTALL_COMPDATA =	$(INSTALL) -c -m 444 @INSTALL_GZIP@
+ INSTALL_DATA	=	$(INSTALL) -c -m 444
+ INSTALL_DIR	=	$(INSTALL) -d
+-INSTALL_LIB	=	$(LIBTOOL) $(INSTALL) -c -m 555 @INSTALL_STRIP@
++INSTALL_LIB	=	$(LIBTOOL) $(INSTALL) -c -m 755 @INSTALL_STRIP@
+ INSTALL_MAN	=	$(INSTALL) -c -m 444
+-INSTALL_SCRIPT	=	$(INSTALL) -c -m 555
++INSTALL_SCRIPT	=	$(INSTALL) -c -m 755
+ 
+ #
+ # Default user, group, and system groups for the scheduler...
+diff -up cups-1.5.3/scheduler/Makefile.0755 cups-1.5.3/scheduler/Makefile
+--- cups-1.5.3/scheduler/Makefile.0755	2011-05-12 00:17:34.000000000 +0200
++++ cups-1.5.3/scheduler/Makefile	2012-05-15 16:51:31.703516547 +0200
+@@ -213,7 +213,7 @@ install-data:
+ install-exec:
+ 	echo Installing programs in $(SBINDIR)...
+ 	$(INSTALL_DIR) -m 755 $(SBINDIR)
+-	$(INSTALL_BIN) -m 500 cupsd $(SBINDIR)
++	$(INSTALL_BIN) -m 755 cupsd $(SBINDIR)
+ 	$(INSTALL_BIN) cupsfilter $(SBINDIR)
+ 	-if test "x`uname`" = xDarwin; then \
+ 		$(INSTALL_DIR) $(BUILDROOT)/System/Library/Printers/Libraries; \
diff --git a/srcpkgs/cups/patches/cups-avahi-1-config.patch b/srcpkgs/cups/patches/cups-avahi-1-config.patch
new file mode 100644
index 0000000000..516e01fa94
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-avahi-1-config.patch
@@ -0,0 +1,42 @@
+diff -up cups-1.5.2/config.h.in.avahi-1-config cups-1.5.2/config.h.in
+--- cups-1.5.2/config.h.in.avahi-1-config	2011-06-16 21:12:16.000000000 +0100
++++ cups-1.5.2/config.h.in	2012-03-14 15:04:51.365347165 +0000
+@@ -390,6 +390,13 @@
+ 
+ 
+ /*
++ * Do we have Avahi for DNS Service Discovery?
++ */
++
++#undef HAVE_AVAHI
++
++
++/*
+  * Do we have <sys/ioctl.h>?
+  */
+ 
+diff -up cups-1.5.2/config-scripts/cups-dnssd.m4.avahi-1-config cups-1.5.2/config-scripts/cups-dnssd.m4
+--- cups-1.5.2/config-scripts/cups-dnssd.m4.avahi-1-config	2011-05-12 06:21:56.000000000 +0100
++++ cups-1.5.2/config-scripts/cups-dnssd.m4	2012-03-14 15:04:51.365347165 +0000
+@@ -23,6 +23,21 @@ AC_ARG_WITH(dnssd-includes, [  --with-dn
+ DNSSDLIBS=""
+ DNSSD_BACKEND=""
+ 
++AC_ARG_ENABLE(avahi, [  --enable-avahi          turn on DNS Service Discovery support, default=no],
++	      [if test x$enable_avahi = xyes; then
++		       AC_MSG_CHECKING(for Avahi)
++		       if $PKGCONFIG --exists avahi-client; then
++			       AC_MSG_RESULT(yes)
++			       CFLAGS="$CFLAGS `$PKGCONFIG --cflags avahi-client`"
++			       DNSSDLIBS="`$PKGCONFIG --libs avahi-client`"
++			       DNSSD_BACKEND="dnssd"
++			       AC_DEFINE(HAVE_AVAHI)
++			       enable_dnssd=no
++		       else
++			       AC_MSG_RESULT(no)
++		       fi
++	       fi])
++
+ if test x$enable_dnssd != xno; then
+ 	AC_CHECK_HEADER(dns_sd.h, [
+ 		case "$uname" in
diff --git a/srcpkgs/cups/patches/cups-avahi-2-backend.patch b/srcpkgs/cups/patches/cups-avahi-2-backend.patch
new file mode 100644
index 0000000000..9fa367729a
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-avahi-2-backend.patch
@@ -0,0 +1,1118 @@
+diff -up cups-1.5.3/backend/dnssd.c.avahi-2-backend cups-1.5.3/backend/dnssd.c
+--- cups-1.5.3/backend/dnssd.c.avahi-2-backend	2012-05-15 16:53:18.164774446 +0200
++++ cups-1.5.3/backend/dnssd.c	2012-05-15 17:09:07.684155704 +0200
+@@ -15,14 +15,21 @@
+  *
+  * Contents:
+  *
++ *   next_txt_record()       - Get next TXT record from a cups_txt_records_t.
++ *   parse_txt_record_pair() - Read key/value pair in cups_txt_records_t.
+  *   main()                  - Browse for printers.
+  *   browse_callback()       - Browse devices.
+  *   browse_local_callback() - Browse local devices.
+  *   compare_devices()       - Compare two devices.
+  *   exec_backend()          - Execute the backend that corresponds to the
+  *                             resolved service name.
++ *   device_type()           - Get DNS-SD type enumeration from string.
+  *   get_device()            - Create or update a device.
+  *   query_callback()        - Process query data.
++ *   avahi_client_callback() - Avahi client callback function.
++ *   avahi_query_callback()  - Avahi query callback function.
++ *   avahi_browse_callback() - Avahi browse callback function.
++ *   find_device()           - Find a device from its name and domain.
+  *   sigterm_handler()       - Handle termination signals...
+  *   unquote()               - Unquote a name string.
+  */
+@@ -33,7 +40,18 @@
+ 
+ #include "backend-private.h"
+ #include <cups/array.h>
+-#include <dns_sd.h>
++#ifdef HAVE_DNSSD
++#  include <dns_sd.h>
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++#  include <avahi-client/client.h>
++#  include <avahi-client/lookup.h>
++#  include <avahi-common/simple-watch.h>
++#  include <avahi-common/domain.h>
++#  include <avahi-common/error.h>
++#  include <avahi-common/malloc.h>
++#define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
++#endif /* HAVE_AVAHI */
+ 
+ 
+ /*
+@@ -53,7 +71,12 @@ typedef enum
+ 
+ typedef struct
+ {
++#ifdef HAVE_DNSSD
+   DNSServiceRef	ref;			/* Service reference for resolve */
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  int		resolved;		/* Did we resolve the device? */
++#endif /* HAVE_AVAHI */
+   char		*name,			/* Service name */
+ 		*domain,		/* Domain name */
+ 		*fullName,		/* Full name */
+@@ -65,6 +88,20 @@ typedef struct
+ 		sent;			/* Did we list the device? */
+ } cups_device_t;
+ 
++typedef struct
++{
++  char key[256];
++  char value[256];
++
++#ifdef HAVE_DNSSD
++  const uint8_t *data;
++  const uint8_t *datanext;
++  const uint8_t *dataend;
++#else /* HAVE_AVAHI */
++  AvahiStringList *txt;
++#endif /* HAVE_DNSSD */
++} cups_txt_records_t;
++
+ 
+ /*
+  * Local globals...
+@@ -78,6 +115,7 @@ static int		job_canceled = 0;
+  * Local functions...
+  */
+ 
++#ifdef HAVE_DNSSD
+ static void		browse_callback(DNSServiceRef sdRef,
+ 			                DNSServiceFlags flags,
+ 				        uint32_t interfaceIndex,
+@@ -95,13 +133,6 @@ static void		browse_local_callback(DNSSe
+ 					      const char *replyDomain,
+ 					      void *context)
+ 					      __attribute__((nonnull(1,5,6,7,8)));
+-static int		compare_devices(cups_device_t *a, cups_device_t *b);
+-static void		exec_backend(char **argv);
+-static cups_device_t	*get_device(cups_array_t *devices,
+-			            const char *serviceName,
+-			            const char *regtype,
+-				    const char *replyDomain)
+-				    __attribute__((nonnull(1,2,3,4)));
+ static void		query_callback(DNSServiceRef sdRef,
+ 			               DNSServiceFlags flags,
+ 				       uint32_t interfaceIndex,
+@@ -111,10 +142,119 @@ static void		query_callback(DNSServiceRe
+ 				       const void *rdata, uint32_t ttl,
+ 				       void *context)
+ 				       __attribute__((nonnull(1,5,9,11)));
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++static void		avahi_client_callback (AvahiClient *client,
++					       AvahiClientState state,
++					       void *context);
++static void		avahi_browse_callback (AvahiServiceBrowser *browser,
++					       AvahiIfIndex interface,
++					       AvahiProtocol protocol,
++					       AvahiBrowserEvent event,
++					       const char *serviceName,
++					       const char *regtype,
++					       const char *replyDomain,
++					       AvahiLookupResultFlags flags,
++					       void *context);
++#endif /* HAVE_AVAHI */
++static cups_device_t *	find_device (cups_array_t *devices,
++				     cups_txt_records_t *txt,
++				     cups_device_t *dkey);
++static int		compare_devices(cups_device_t *a, cups_device_t *b);
++static void		exec_backend(char **argv);
++static cups_device_t	*get_device(cups_array_t *devices,
++			            const char *serviceName,
++			            const char *regtype,
++				    const char *replyDomain)
++				    __attribute__((nonnull(1,2,3,4)));
+ static void		sigterm_handler(int sig);
+ static void		unquote(char *dst, const char *src, size_t dstsize)
+ 			    __attribute__((nonnull(1,2)));
+ 
++#ifdef HAVE_AVAHI
++static AvahiSimplePoll *simple_poll = NULL;
++static int avahi_got_callback;
++#endif /* HAVE_AVAHI */
++
++
++/*
++ * 'next_txt_record()' - Get next TXT record from a cups_txt_records_t.
++ */
++
++static cups_txt_records_t *
++next_txt_record (cups_txt_records_t *txt)
++{
++#ifdef HAVE_DNSSD
++  txt->data = txt->datanext;
++#else /* HAVE_AVAHI */
++  txt->txt = avahi_string_list_get_next (txt->txt);
++  if (txt->txt == NULL)
++    return NULL;
++#endif /* HAVE_DNSSD */
++
++  return txt;
++}
++
++
++/*
++ * 'parse_txt_record_pair()' - Read key/value pair in cups_txt_records_t.
++ */
++
++static int
++parse_txt_record_pair (cups_txt_records_t *txt)
++{
++#ifdef HAVE_DNSSD
++  uint8_t	datalen;
++  uint8_t	*data = txt->data;
++  char		*ptr;
++
++ /*
++  * Read a key/value pair starting with an 8-bit length.  Since the
++  * length is 8 bits and the size of the key/value buffers is 256, we
++  * don't need to check for overflow...
++  */
++
++  datalen = *data++;
++  if (!datalen || (data + datalen) > txt->dataend)
++    return NULL;
++  txt->datanext = data + datalen;
++
++  for (ptr = txt->key; data < txt->datanext && *data != '='; data ++)
++    *ptr++ = *data;
++  *ptr = '\0';
++
++  if (data < txt->datanext && *data == '=')
++  {
++    data++;
++
++    if (data < datanext)
++      memcpy (txt->value, data, txt->datanext - data);
++    value[txt->datanext - data] = '\0';
++  }
++  else
++    return 1;
++#else /* HAVE_AVAHI */
++  char *key, *value;
++  size_t len;
++  avahi_string_list_get_pair (txt->txt, &key, &value, &len);
++  if (len > sizeof (txt->value) - 1)
++    len = sizeof (txt->value) - 1;
++
++  memcpy (txt->value, value, len);
++  txt->value[len] = '\0';
++  len = strlen (key);
++  if (len > sizeof (txt->key) - 1)
++    len = sizeof (txt->key) - 1;
++
++  memcpy (txt->key, key, len);
++  txt->key[len] = '\0';
++  avahi_free (key);
++  avahi_free (value);
++#endif /* HAVE_AVAHI */
++
++  return 0;
++}
++
+ 
+ /*
+  * 'main()' - Browse for printers.
+@@ -125,6 +265,13 @@ main(int  argc,				/* I - Number of comm
+      char *argv[])			/* I - Command-line arguments */
+ {
+   const char	*name;			/* Backend name */
++  cups_array_t	*devices;		/* Device array */
++  cups_device_t	*device;		/* Current device */
++  char		uriName[1024];		/* Unquoted fullName for URI */
++#ifdef HAVE_DNSSD
++  int		fd;			/* Main file descriptor */
++  fd_set	input;			/* Input set for select() */
++  struct timeval timeout;		/* Timeout for select() */
+   DNSServiceRef	main_ref,		/* Main service reference */
+ 		fax_ipp_ref,		/* IPP fax service reference */
+ 		ipp_ref,		/* IPP service reference */
+@@ -138,12 +285,11 @@ main(int  argc,				/* I - Number of comm
+ 		pdl_datastream_ref,	/* AppSocket service reference */
+ 		printer_ref,		/* LPD service reference */
+ 		riousbprint_ref;	/* Remote IO service reference */
+-  int		fd;			/* Main file descriptor */
+-  fd_set	input;			/* Input set for select() */
+-  struct timeval timeout;		/* Timeout for select() */
+-  cups_array_t	*devices;		/* Device array */
+-  cups_device_t	*device;		/* Current device */
+-  char		uriName[1024];		/* Unquoted fullName for URI */
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  AvahiClient	*client;
++  int		error;
++#endif /* HAVE_AVAHI */
+ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+   struct sigaction action;		/* Actions for POSIX signals */
+ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+@@ -203,6 +349,49 @@ main(int  argc,				/* I - Number of comm
+   * Browse for different kinds of printers...
+   */
+ 
++#ifdef HAVE_AVAHI
++  if ((simple_poll = avahi_simple_poll_new ()) == NULL)
++  {
++    perror ("ERROR: Unable to create avahi simple poll object");
++    return (1);
++  }
++
++  client = avahi_client_new (avahi_simple_poll_get (simple_poll),
++			     0, avahi_client_callback, NULL, &error);
++  if (!client)
++  {
++    perror ("DEBUG: Unable to create avahi client");
++    return (0);
++  }
++
++  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
++			     AVAHI_PROTO_UNSPEC,
++			     "_fax-ipp._tcp", NULL, 0,
++			     avahi_browse_callback, devices);
++  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
++			     AVAHI_PROTO_UNSPEC,
++			     "_ipp._tcp", NULL, 0,
++			     avahi_browse_callback, devices);
++  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
++			     AVAHI_PROTO_UNSPEC,
++			     "_ipp-tls._tcp", NULL, 0,
++			     avahi_browse_callback, devices);
++  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
++			     AVAHI_PROTO_UNSPEC,
++			     "_pdl-datastream._tcp",
++			     NULL, 0,
++			     avahi_browse_callback,
++			     devices);
++  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
++			     AVAHI_PROTO_UNSPEC,
++			     "_printer._tcp", NULL, 0,
++			     avahi_browse_callback, devices);
++  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
++			     AVAHI_PROTO_UNSPEC,
++			     "_riousbprint._tcp", NULL, 0,
++			     avahi_browse_callback, devices);
++#endif /* HAVE_AVAHI */
++#ifdef HAVE_DNSSD
+   if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
+   {
+     perror("ERROR: Unable to create service connection");
+@@ -263,6 +452,7 @@ main(int  argc,				/* I - Number of comm
+   riousbprint_ref = main_ref;
+   DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
+                    "_riousbprint._tcp", NULL, browse_callback, devices);
++#endif /* HAVE_DNSSD */
+ 
+  /*
+   * Loop until we are killed...
+@@ -270,6 +460,9 @@ main(int  argc,				/* I - Number of comm
+ 
+   while (!job_canceled)
+   {
++    int announce = 0;
++
++#ifdef HAVE_DNSSD
+     FD_ZERO(&input);
+     FD_SET(fd, &input);
+ 
+@@ -289,11 +482,35 @@ main(int  argc,				/* I - Number of comm
+     }
+     else
+     {
++      announce = 1;
++    }
++#else /* HAVE_AVAHI */
++    int r;
++    avahi_got_callback = 0;
++    r = avahi_simple_poll_iterate (simple_poll, 1);
++    if (r != 0 && r != EINTR)
++    {
++     /*
++      * We've been told to exit the loop.  Perhaps the connection to
++      * avahi failed.
++      */
++
++      break;
++    }
++
++    if (avahi_got_callback)
++      announce = 1;
++#endif /* HAVE_DNSSD */
++
++    if (announce)
++    {
+      /*
+       * Announce any devices we've found...
+       */
+ 
++#ifdef HAVE_DNSSD
+       DNSServiceErrorType status;	/* DNS query status */
++#endif /* HAVE_DNSSD */
+       cups_device_t *best;		/* Best matching device */
+       char	device_uri[1024];	/* Device URI */
+       int	count;			/* Number of queries */
+@@ -307,6 +524,7 @@ main(int  argc,				/* I - Number of comm
+         if (device->sent)
+ 	  sent ++;
+ 
++#ifdef HAVE_DNSSD
+         if (device->ref)
+ 	  count ++;
+ 
+@@ -338,14 +556,23 @@ main(int  argc,				/* I - Number of comm
+ 	      count ++;
+           }
+ 	}
+-	else if (!device->sent)
++	else
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++	if (!device->resolved)
++	  continue;
++        else
++#endif /* HAVE_AVAHI */
++	if (!device->sent)
+ 	{
++#ifdef HAVE_DNSSD
+ 	 /*
+ 	  * Got the TXT records, now report the device...
+ 	  */
+ 
+ 	  DNSServiceRefDeallocate(device->ref);
+ 	  device->ref = 0;
++#endif /* HAVE_DNSSD */
+ 
+           if (!best)
+ 	    best = device;
+@@ -406,6 +633,7 @@ main(int  argc,				/* I - Number of comm
+ }
+ 
+ 
++#ifdef HAVE_DNSSD
+ /*
+  * 'browse_callback()' - Browse devices.
+  */
+@@ -494,6 +722,7 @@ browse_local_callback(
+ 	  device->fullName);
+   device->sent = 1;
+ }
++#endif /* HAVE_DNSSD */
+ 
+ 
+ /*
+@@ -574,6 +803,41 @@ exec_backend(char **argv)		/* I - Comman
+ 
+ 
+ /*
++ * 'device_type()' - Get DNS-SD type enumeration from string.
++ */
++
++static int
++device_type (const char *regtype)
++{
++#ifdef HAVE_AVAHI
++  if (!strcmp(regtype, "_ipp._tcp"))
++    return (CUPS_DEVICE_IPP);
++  else if (!strcmp(regtype, "_ipps._tcp") ||
++	   !strcmp(regtype, "_ipp-tls._tcp"))
++    return (CUPS_DEVICE_IPPS);
++  else if (!strcmp(regtype, "_fax-ipp._tcp"))
++    return (CUPS_DEVICE_FAX_IPP);
++  else if (!strcmp(regtype, "_printer._tcp"))
++    return (CUPS_DEVICE_PDL_DATASTREAM);
++#else
++  if (!strcmp(regtype, "_ipp._tcp."))
++    return (CUPS_DEVICE_IPP);
++  else if (!strcmp(regtype, "_ipps._tcp.") ||
++	   !strcmp(regtype, "_ipp-tls._tcp."))
++    return (CUPS_DEVICE_IPPS);
++  else if (!strcmp(regtype, "_fax-ipp._tcp."))
++    return (CUPS_DEVICE_FAX_IPP);
++  else if (!strcmp(regtype, "_printer._tcp."))
++    return (CUPS_DEVICE_PRINTER);
++  else if (!strcmp(regtype, "_pdl-datastream._tcp."))
++    return (CUPS_DEVICE_PDL_DATASTREAM);
++#endif /* HAVE_AVAHI */
++
++  return (CUPS_DEVICE_RIOUSBPRINT);
++}
++
++
++/*
+  * 'get_device()' - Create or update a device.
+  */
+ 
+@@ -594,20 +858,7 @@ get_device(cups_array_t *devices,	/* I -
+   */
+ 
+   key.name = (char *)serviceName;
+-
+-  if (!strcmp(regtype, "_ipp._tcp."))
+-    key.type = CUPS_DEVICE_IPP;
+-  else if (!strcmp(regtype, "_ipps._tcp.") ||
+-	   !strcmp(regtype, "_ipp-tls._tcp."))
+-    key.type = CUPS_DEVICE_IPPS;
+-  else if (!strcmp(regtype, "_fax-ipp._tcp."))
+-    key.type = CUPS_DEVICE_FAX_IPP;
+-  else if (!strcmp(regtype, "_printer._tcp."))
+-    key.type = CUPS_DEVICE_PRINTER;
+-  else if (!strcmp(regtype, "_pdl-datastream._tcp."))
+-    key.type = CUPS_DEVICE_PDL_DATASTREAM;
+-  else
+-    key.type = CUPS_DEVICE_RIOUSBPRINT;
++  key.type = device_type (regtype);
+ 
+   for (device = cupsArrayFind(devices, &key);
+        device;
+@@ -627,8 +878,14 @@ get_device(cups_array_t *devices,	/* I -
+         free(device->domain);
+ 	device->domain = strdup(replyDomain);
+ 
++#ifdef HAVE_DNSSD
+ 	DNSServiceConstructFullName(fullName, device->name, regtype,
+ 	                            replyDomain);
++#else /* HAVE_AVAHI */
++	avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
++				 serviceName, regtype, replyDomain);
++#endif /* HAVE_DNSSD */
++
+ 	free(device->fullName);
+ 	device->fullName = strdup(fullName);
+       }
+@@ -648,6 +905,9 @@ get_device(cups_array_t *devices,	/* I -
+   device->domain   = strdup(replyDomain);
+   device->type     = key.type;
+   device->priority = 50;
++#ifdef HAVE_AVAHI
++  device->resolved = 0;
++#endif /* HAVE_AVAHI */
+ 
+   cupsArrayAdd(devices, device);
+ 
+@@ -655,13 +915,20 @@ get_device(cups_array_t *devices,	/* I -
+   * Set the "full name" of this service, which is used for queries...
+   */
+ 
++#ifdef HAVE_DNSSD
+   DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
++#else /* HAVE_AVAHI */
++  avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
++			   serviceName, regtype, replyDomain);
++#endif /* HAVE_DNSSD */
++
+   device->fullName = strdup(fullName);
+ 
+   return (device);
+ }
+ 
+ 
++#ifdef HAVE_DNSSD
+ /*
+  * 'query_callback()' - Process query data.
+  */
+@@ -685,7 +952,7 @@ query_callback(
+ 		*ptr;			/* Pointer into string */
+   cups_device_t	dkey,			/* Search key */
+ 		*device;		/* Device */
+-
++  cups_txt_records_t txt;
+ 
+   fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
+                   "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
+@@ -719,94 +986,233 @@ query_callback(
+   if ((ptr = strstr(name, "._")) != NULL)
+     *ptr = '\0';
+ 
+-  if (strstr(fullName, "_ipp._tcp."))
+-    dkey.type = CUPS_DEVICE_IPP;
+-  else if (strstr(fullName, "_ipps._tcp.") ||
+-           strstr(fullName, "_ipp-tls._tcp."))
+-    dkey.type = CUPS_DEVICE_IPPS;
+-  else if (strstr(fullName, "_fax-ipp._tcp."))
+-    dkey.type = CUPS_DEVICE_FAX_IPP;
+-  else if (strstr(fullName, "_printer._tcp."))
+-    dkey.type = CUPS_DEVICE_PRINTER;
+-  else if (strstr(fullName, "_pdl-datastream._tcp."))
+-    dkey.type = CUPS_DEVICE_PDL_DATASTREAM;
++  dkey.type = device_type (fullName);
++
++  txt.data = rdata;
++  txt.dataend = rdata + rdlen;
++  device = find_device ((cups_array_t *) context, &txt, &dkey);
++  if (!device)
++    fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
++}
++#endif /* HAVE_DNSSD */
++
++
++#ifdef HAVE_AVAHI
++/*
++ * 'avahi_client_callback()' - Avahi client callback function.
++ */
++
++static void
++avahi_client_callback(AvahiClient *client,
++		      AvahiClientState state,
++		      void *context)
++{
++ /*
++  * If the connection drops, quit.
++  */
++
++  if (state == AVAHI_CLIENT_FAILURE)
++  {
++    fprintf (stderr, "ERROR: Avahi connection failed\n");
++    avahi_simple_poll_quit (simple_poll);
++  }
++}
++
++
++/*
++ * 'avahi_query_callback()' - Avahi query callback function.
++ */
++
++static void
++avahi_query_callback(AvahiServiceResolver *resolver,
++		     AvahiIfIndex interface,
++		     AvahiProtocol protocol,
++		     AvahiResolverEvent event,
++		     const char *name,
++		     const char *type,
++		     const char *domain,
++		     const char *host_name,
++		     const AvahiAddress *address,
++		     uint16_t port,
++		     AvahiStringList *txt,
++		     AvahiLookupResultFlags flags,
++		     void *context)
++{
++  AvahiClient		*client;
++  cups_device_t		key,
++			*device;
++  char			uqname[1024],
++			*ptr;
++  cups_txt_records_t	txtr;
++
++  client = avahi_service_resolver_get_client (resolver);
++  if (event != AVAHI_RESOLVER_FOUND)
++  {
++    if (event == AVAHI_RESOLVER_FAILURE)
++    {
++      fprintf (stderr, "ERROR: %s\n",
++	       avahi_strerror (avahi_client_errno (client)));
++    }
++
++    avahi_service_resolver_free (resolver);
++    return;
++  }
++
++ /*
++  * Set search key for device.
++  */
++
++  key.name = uqname;
++  unquote (uqname, name, sizeof (uqname));
++  if ((ptr = strstr(name, "._")) != NULL)
++    *ptr = '\0';
++
++  key.domain = (char *) domain;
++  key.type = device_type (type);
++
++ /*
++  * Find the device and the the TXT information.
++  */
++
++  txtr.txt = txt;
++  device = find_device ((cups_array_t *) context, &txtr, &key);
++  if (device)
++  {
++   /*
++    * Let the main loop know to announce the device.
++    */
++
++    device->resolved = 1;
++    avahi_got_callback = 1;
++  }
+   else
+-    dkey.type = CUPS_DEVICE_RIOUSBPRINT;
++    fprintf (stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", name);
+ 
+-  for (device = cupsArrayFind(devices, &dkey);
++  avahi_service_resolver_free (resolver);
++}
++
++
++/*
++ * 'avahi_browse_callback()' - Avahi browse callback function.
++ */
++
++static void
++avahi_browse_callback(AvahiServiceBrowser *browser,
++		      AvahiIfIndex interface,
++		      AvahiProtocol protocol,
++		      AvahiBrowserEvent event,
++		      const char *name,
++		      const char *type,
++		      const char *domain,
++		      AvahiLookupResultFlags flags,
++		      void *context)
++{
++  AvahiClient *client = avahi_service_browser_get_client (browser);
++
++  switch (event)
++  {
++  case AVAHI_BROWSER_FAILURE:
++    fprintf (stderr, "ERROR: %s\n",
++	     avahi_strerror (avahi_client_errno (client)));
++    avahi_simple_poll_quit (simple_poll);
++    return;
++
++  case AVAHI_BROWSER_NEW:
++   /*
++    * This object is new on the network.
++    */
++
++    if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
++    {
++     /*
++      * This comes from the local machine so ignore it.
++      */
++
++      fprintf (stderr, "DEBUG: ignoring local service %s\n", name);
++    }
++    else
++    {
++     /*
++      * Create a device entry for it if it doesn't yet exist.
++      */
++
++      get_device ((cups_array_t *)context, name, type, domain);
++
++     /*
++      * Now look for a TXT entry.
++      */
++
++      if (avahi_service_resolver_new (client, interface, protocol,
++				      name, type, domain,
++				      AVAHI_PROTO_UNSPEC, 0,
++				      avahi_query_callback, context) == NULL)
++      {
++	fprintf (stderr, "ERROR: failed to resolve service %s: %s\n",
++		 name, avahi_strerror (avahi_client_errno (client)));
++      }
++    }
++
++    break;
++
++  case AVAHI_BROWSER_REMOVE:
++  case AVAHI_BROWSER_ALL_FOR_NOW:
++  case AVAHI_BROWSER_CACHE_EXHAUSTED:
++    break;
++  }
++}
++#endif /* HAVE_AVAHI */
++
++
++/*
++ * 'find_device()' - Find a device from its name and domain.
++ */
++
++static cups_device_t *
++find_device (cups_array_t *devices,
++	     cups_txt_records_t *txt,
++	     cups_device_t *dkey)
++{
++  cups_device_t	*device;
++  char		*ptr;
++
++  for (device = cupsArrayFind(devices, dkey);
+        device;
+        device = cupsArrayNext(devices))
+   {
+-    if (_cups_strcasecmp(device->name, dkey.name) ||
+-        _cups_strcasecmp(device->domain, dkey.domain))
++    if (_cups_strcasecmp(device->name, dkey->name) ||
++        _cups_strcasecmp(device->domain, dkey->domain))
+     {
+       device = NULL;
+       break;
+     }
+-    else if (device->type == dkey.type)
++    else if (device->type == dkey->type)
+     {
+      /*
+       * Found it, pull out the priority and make and model from the TXT
+       * record and save it...
+       */
+ 
+-      const uint8_t	*data,		/* Pointer into data */
+-			*datanext,	/* Next key/value pair */
+-			*dataend;	/* End of entire TXT record */
+-      uint8_t		datalen;	/* Length of current key/value pair */
+-      char		key[256],	/* Key string */
+-			value[256],	/* Value string */
+-			make_and_model[512],
++      char		make_and_model[512],
+ 				      	/* Manufacturer and model */
+ 			model[256],	/* Model */
+-			device_id[2048];/* 1284 device ID */
+-
++			device_id[2048]; /* 1284 device ID */
+ 
+       device_id[0]      = '\0';
+       make_and_model[0] = '\0';
+ 
+       strcpy(model, "Unknown");
+ 
+-      for (data = rdata, dataend = data + rdlen;
+-           data < dataend;
+-           data = datanext)
++      for (;;)
+       {
+-       /*
+-        * Read a key/value pair starting with an 8-bit length.  Since the
+-	* length is 8 bits and the size of the key/value buffers is 256, we
+-	* don't need to check for overflow...
+-	*/
+-
+-        datalen = *data++;
+-
+-        if (!datalen || (data + datalen) > dataend)
+-	  break;
+-
+-        datanext = data + datalen;
+-
+-        for (ptr = key; data < datanext && *data != '='; data ++)
+-	  *ptr++ = *data;
+-	*ptr = '\0';
++	char *key;
++	char *value;
+ 
+-	if (data < datanext && *data == '=')
+-	{
+-	  data ++;
+-
+-	  if (data < datanext)
+-	    memcpy(value, data, datanext - data);
+-	  value[datanext - data] = '\0';
++	if (parse_txt_record_pair (txt))
++	  goto next;
+ 
+-	  fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
+-	          key, value);
+-	}
+-	else
+-	{
+-	  fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
+-	          key);
+-	  continue;
+-	}
+-
+-        if (!_cups_strncasecmp(key, "usb_", 4))
++	key = txt->key;
++	value = txt->value;
++        if (!strncasecmp(key, "usb_", 4))
+ 	{
+ 	 /*
+ 	  * Add USB device ID information...
+@@ -861,6 +1267,10 @@ query_callback(
+ 	  if (device->type == CUPS_DEVICE_PRINTER)
+ 	    device->sent = 1;
+ 	}
++
++      next:
++	if (next_txt_record (txt) == NULL)
++	  break;
+       }
+ 
+       if (device->device_id)
+@@ -917,11 +1327,9 @@ query_callback(
+     }
+   }
+ 
+-  if (!device)
+-    fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
++  return device;
+ }
+ 
+-
+ /*
+  * 'sigterm_handler()' - Handle termination signals...
+  */
+diff -up cups-1.5.3/cups/http-support.c.avahi-2-backend cups-1.5.3/cups/http-support.c
+--- cups-1.5.3/cups/http-support.c.avahi-2-backend	2012-02-15 02:06:12.000000000 +0100
++++ cups-1.5.3/cups/http-support.c	2012-05-15 17:04:51.045944634 +0200
+@@ -43,6 +43,10 @@
+  *   http_copy_decode()   - Copy and decode a URI.
+  *   http_copy_encode()   - Copy and encode a URI.
+  *   http_resolve_cb()    - Build a device URI for the given service name.
++ *   avahi_resolve_uri_client_cb()
++ *                        - Avahi client callback for resolving URI.
++ *   avahi_resolve_uri_resolver_cb()
++ *                        - Avahi resolver callback for resolving URI.
+  */
+ 
+ /*
+@@ -60,6 +64,11 @@
+ #    include <sys/select.h>
+ #  endif /* WIN32 */
+ #endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++#  include <avahi-client/client.h>
++#  include <avahi-client/lookup.h>
++#  include <avahi-common/simple-watch.h>
++#endif /* HAVE_AVAHI */
+ 
+ 
+ /*
+@@ -127,6 +136,24 @@ static void DNSSD_API	http_resolve_cb(DN
+ 					void *context);
+ #endif /* HAVE_DNSSD */
+ 
++#ifdef HAVE_AVAHI
++static void	avahi_resolve_uri_client_cb(AvahiClient *client,
++					    AvahiClientState state,
++					    void *simple_poll);
++static void	avahi_resolve_uri_resolver_cb(AvahiServiceResolver *resolver,
++					      AvahiIfIndex interface,
++					      AvahiProtocol protocol,
++					      AvahiResolverEvent event,
++					      const char *name,
++					      const char *type,
++					      const char *domain,
++					      const char *host_name,
++					      const AvahiAddress *address,
++					      uint16_t port,
++					      AvahiStringList *txt,
++					      AvahiLookupResultFlags flags,
++					      void *context);
++#endif /* HAVE_AVAHI */
+ 
+ /*
+  * 'httpAssembleURI()' - Assemble a uniform resource identifier from its
+@@ -1434,6 +1461,9 @@ _httpResolveURI(
+ 
+   if (strstr(hostname, "._tcp"))
+   {
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
++    char		*regtype,	/* Pointer to type in hostname */
++			*domain;	/* Pointer to domain in hostname */
+ #ifdef HAVE_DNSSD
+ #  ifdef WIN32
+ #    pragma comment(lib, "dnssd.lib")
+@@ -1452,6 +1482,17 @@ _httpResolveURI(
+     fd_set		input_set;	/* Input set for select() */
+     struct timeval	stimeout;	/* Timeout value for select() */
+ #endif /* HAVE_POLL */
++#else /* HAVE_AVAHI */
++    AvahiSimplePoll	*simple_poll;
++    AvahiClient		*client;
++    int			error;
++    struct
++    {
++      AvahiSimplePoll	*poll;
++      _http_uribuf_t	uribuf;
++    } user_data;
++#endif /* HAVE_DNSSD */
++
+ 
+     if (options & _HTTP_RESOLVE_STDERR)
+       fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname);
+@@ -1488,9 +1529,16 @@ _httpResolveURI(
+     if (domain)
+       *domain++ = '\0';
+ 
++#ifdef HAVE_DNSSD
+     uribuf.buffer   = resolved_uri;
+     uribuf.bufsize  = resolved_size;
+     uribuf.options  = options;
++#else
++    user_data.uribuf.buffer = resolved_uri;
++    user_data.uribuf.bufsize = resolved_size;
++    user_data.uribuf.options = options;
++#endif
++
+     resolved_uri[0] = '\0';
+ 
+     DEBUG_printf(("6_httpResolveURI: Resolving hostname=\"%s\", regtype=\"%s\", "
+@@ -1504,6 +1552,7 @@ _httpResolveURI(
+ 
+     uri = NULL;
+ 
++#ifdef HAVE_DNSSD
+     if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
+     {
+       localref = ref;
+@@ -1611,6 +1660,36 @@ _httpResolveURI(
+ 
+       DNSServiceRefDeallocate(ref);
+     }
++#else /* HAVE_AVAHI */
++    if ((simple_poll = avahi_simple_poll_new ()) != NULL)
++    {
++      if ((client = avahi_client_new (avahi_simple_poll_get (simple_poll),
++				      0, avahi_resolve_uri_client_cb,
++				      &simple_poll, &error)) != NULL)
++      {
++	user_data.poll = simple_poll;
++	if (avahi_service_resolver_new (client, AVAHI_IF_UNSPEC,
++					AVAHI_PROTO_UNSPEC, hostname,
++					regtype, domain, AVAHI_PROTO_UNSPEC, 0,
++					avahi_resolve_uri_resolver_cb,
++					&user_data) != NULL)
++	{
++	  avahi_simple_poll_loop (simple_poll);
++
++	 /*
++	  * Collect the result.
++	  */
++
++	  if (resolved_uri[0])
++	    uri = resolved_uri;
++	}
++
++	avahi_client_free (client);
++      }
++
++      avahi_simple_poll_free (simple_poll);
++    }
++#endif /* HAVE_DNSSD */
+ 
+     if (options & _HTTP_RESOLVE_STDERR)
+     {
+@@ -1622,13 +1701,13 @@ _httpResolveURI(
+       fputs("STATE: -connecting-to-device,offline-report\n", stderr);
+     }
+ 
+-#else
++#else /* HAVE_DNSSD || HAVE_AVAHI */
+    /*
+     * No DNS-SD support...
+     */
+ 
+     uri = NULL;
+-#endif /* HAVE_DNSSD */
++#endif /* HAVE_DNSSD || HAVE_AVAHI */
+ 
+     if ((options & _HTTP_RESOLVE_STDERR) && !uri)
+       _cupsLangPrintFilter(stderr, "ERROR", _("Unable to find printer."));
+@@ -1916,6 +1995,115 @@ http_resolve_cb(
+ }
+ #endif /* HAVE_DNSSD */
+ 
++#ifdef HAVE_AVAHI
++/*
++ * 'avahi_resolve_uri_client_cb()' - Avahi client callback for resolving URI.
++ */
++
++static void
++avahi_resolve_uri_client_cb (AvahiClient *client,
++			     AvahiClientState state,
++			     void *simple_poll)
++{
++  DEBUG_printf(("avahi_resolve_uri_client_callback(client=%p, state=%d, "
++		"simple_poll=%p)\n", client, state, simple_poll));
++
++  /*
++   * If the connection drops, quit.
++   */
++
++  if (state == AVAHI_CLIENT_FAILURE)
++    avahi_simple_poll_quit (simple_poll);
++}
++
++
++/*
++ * 'avahi_resolve_uri_resolver_cb()' - Avahi resolver callback for resolving
++ *                                     URI.
++ */
++
++static void
++avahi_resolve_uri_resolver_cb (AvahiServiceResolver *resolver,
++			       AvahiIfIndex interface,
++			       AvahiProtocol protocol,
++			       AvahiResolverEvent event,
++			       const char *name,
++			       const char *type,
++			       const char *domain,
++			       const char *host_name,
++			       const AvahiAddress *address,
++			       uint16_t port,
++			       AvahiStringList *txt,
++			       AvahiLookupResultFlags flags,
++			       void *context)
++{
++  const char		*scheme;	/* URI scheme */
++  char			rp[256];	/* Remote printer */
++  AvahiStringList	*pair;
++  char			*value;
++  size_t		valueLen = 0;
++  char			addr[AVAHI_ADDRESS_STR_MAX];
++  struct
++  {
++    AvahiSimplePoll	*poll;
++    _http_uribuf_t	uribuf;
++  }		*poll_uribuf = context;
++
++  DEBUG_printf(("avahi_resolve_uri_resolver_callback(resolver=%p, "
++		"interface=%d, protocol=%d, event=%d, name=\"%s\", "
++		"type=\"%s\", domain=\"%s\", host_name=\"%s\", address=%p, "
++		"port=%d, txt=%p, flags=%d, context=%p)\n",
++		resolver, interface, protocol, event, name, type, domain,
++		host_name, address, port, txt, flags, context));
++
++  if (event != AVAHI_RESOLVER_FOUND)
++  {
++    avahi_service_resolver_free (resolver);
++    avahi_simple_poll_quit (poll_uribuf->poll);
++    return;
++  }
++
++ /*
++  * Figure out the scheme from the full name...
++  */
++
++  if (strstr(type, "_ipp."))
++    scheme = "ipp";
++  else if (strstr(type, "_printer."))
++    scheme = "lpd";
++  else if (strstr(type, "_pdl-datastream."))
++    scheme = "socket";
++  else
++    scheme = "riousbprint";
++
++ /*
++  * Extract the "remote printer key from the TXT record...
++  */
++
++  if ((pair = avahi_string_list_find (txt, "rp")) != NULL)
++  {
++    avahi_string_list_get_pair (pair, NULL, &value, &valueLen);
++    rp[0] = '/';
++    memcpy (rp + 1, value, valueLen);
++    rp[valueLen + 1] = '\0';
++  }
++  else
++    rp[0] = '\0';
++
++ /*
++  * Assemble the final device URI...
++  */
++
++  avahi_address_snprint (addr, AVAHI_ADDRESS_STR_MAX, address);
++  httpAssembleURI(HTTP_URI_CODING_ALL, poll_uribuf->uribuf.buffer,
++		  poll_uribuf->uribuf.bufsize, scheme, NULL,
++		  addr, port, rp);
++  DEBUG_printf(("avahi_resolve_uri_resolver_callback: Resolved URI is \"%s\"\n",
++		poll_uribuf->uribuf.buffer));
++  avahi_simple_poll_quit (poll_uribuf->poll);
++}
++#endif /* HAVE_AVAHI */
++
+ 
+ /*
+  * End of "$Id: http-support.c 10284 2012-02-15 01:06:12Z mike $".
diff --git a/srcpkgs/cups/patches/cups-avahi-3-timeouts.patch b/srcpkgs/cups/patches/cups-avahi-3-timeouts.patch
new file mode 100644
index 0000000000..daf852a0fd
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-avahi-3-timeouts.patch
@@ -0,0 +1,381 @@
+diff -up cups-1.5.2/scheduler/cupsd.h.avahi-3-timeouts cups-1.5.2/scheduler/cupsd.h
+--- cups-1.5.2/scheduler/cupsd.h.avahi-3-timeouts	2011-05-11 23:17:34.000000000 +0100
++++ cups-1.5.2/scheduler/cupsd.h	2012-03-14 15:06:36.509476983 +0000
+@@ -140,6 +140,15 @@ extern const char *cups_hstrerror(int);
+ 
+ typedef void (*cupsd_selfunc_t)(void *data);
+ 
++#ifdef HAVE_AVAHI
++/*
++ * Timeout callback function type...
++ */
++
++typedef struct _cupsd_timeout_s cupsd_timeout_t;
++typedef void (*cupsd_timeoutfunc_t)(cupsd_timeout_t *timeout, void *data);
++#endif /* HAVE_AVAHI */
++
+ 
+ /*
+  * Globals...
+@@ -173,6 +182,11 @@ VAR int			Launchd		VALUE(0);
+ 					/* Running from launchd */
+ #endif /* HAVE_LAUNCH_H */
+ 
++#ifdef HAVE_AVAHI
++VAR cups_array_t *Timeouts;		/* Timed callbacks for main loop */
++#endif /* HAVE_AVAHI */
++
++
+ 
+ /*
+  * Prototypes...
+@@ -242,6 +256,20 @@ extern void		cupsdStopSelect(void);
+ extern void		cupsdStartServer(void);
+ extern void		cupsdStopServer(void);
+ 
++#ifdef HAVE_AVAHI
++extern void     cupsdInitTimeouts(void);
++extern cupsd_timeout_t *cupsdAddTimeout (const struct timeval *tv,
++					 cupsd_timeoutfunc_t cb,
++					 void *data);
++extern cupsd_timeout_t *cupsdNextTimeout (long *delay);
++extern void     cupsdRunTimeout (cupsd_timeout_t *timeout);
++extern void     cupsdUpdateTimeout (cupsd_timeout_t *timeout,
++				    const struct timeval *tv);
++extern void     cupsdRemoveTimeout (cupsd_timeout_t *timeout);
++#endif /* HAVE_AVAHI */
++
++extern int	cupsdRemoveFile(const char *filename);
++
+ 
+ /*
+  * End of "$Id: cupsd.h 9766 2011-05-11 22:17:34Z mike $".
+diff -up cups-1.5.2/scheduler/main.c.avahi-3-timeouts cups-1.5.2/scheduler/main.c
+--- cups-1.5.2/scheduler/main.c.avahi-3-timeouts	2012-03-14 15:04:17.655305548 +0000
++++ cups-1.5.2/scheduler/main.c	2012-03-14 15:06:36.511476986 +0000
+@@ -146,6 +146,10 @@ main(int  argc,				/* I - Number of comm
+   int			launchd_idle_exit;
+ 					/* Idle exit on select timeout? */
+ #endif	/* HAVE_LAUNCHD */
++#ifdef HAVE_AVAHI
++  cupsd_timeout_t	*tmo;		/* Next scheduled timed callback */
++  long			tmo_delay;	/* Time before it must be called */
++#endif /* HAVE_AVAHI */
+ 
+ 
+ #ifdef HAVE_GETEUID
+@@ -535,6 +539,14 @@ main(int  argc,				/* I - Number of comm
+ 
+   httpInitialize();
+ 
++#ifdef HAVE_AVAHI
++ /*
++  * Initialize timed callback structures.
++  */
++
++  cupsdInitTimeouts();
++#endif /* HAVE_AVAHI */
++
+   cupsdStartServer();
+ 
+  /*
+@@ -874,6 +886,16 @@ main(int  argc,				/* I - Number of comm
+     }
+ #endif /* __APPLE__ */
+ 
++#ifdef HAVE_AVAHI
++   /*
++    * If a timed callback is due, run it.
++    */
++
++    tmo = cupsdNextTimeout (&tmo_delay);
++    if (tmo && tmo_delay == 0)
++      cupsdRunTimeout (tmo);
++#endif /* HAVE_AVAHI */
++
+ #ifndef __APPLE__
+    /*
+     * Update the network interfaces once a minute...
+@@ -1787,6 +1809,10 @@ select_timeout(int fds)			/* I - Number
+   cupsd_job_t		*job;		/* Job information */
+   cupsd_subscription_t	*sub;		/* Subscription information */
+   const char		*why;		/* Debugging aid */
++#ifdef HAVE_AVAHI
++  cupsd_timeout_t	*tmo;		/* Timed callback */
++  long			tmo_delay;	/* Seconds before calling it */
++#endif /* HAVE_AVAHI */
+ 
+ 
+  /*
+@@ -1829,6 +1855,19 @@ select_timeout(int fds)			/* I - Number
+   }
+ #endif /* __APPLE__ */
+ 
++#ifdef HAVE_AVAHI
++ /*
++  * See if there are any scheduled timed callbacks to run.
++  */
++
++  if ((tmo = cupsdNextTimeout(&tmo_delay)) != NULL &&
++      (now + tmo_delay) < timeout)
++  {
++    timeout = tmo_delay;
++    why = "run a timed callback";
++  }
++#endif /* HAVE_AVAHI */
++
+  /*
+   * Check whether we are accepting new connections...
+   */
+diff -up cups-1.5.2/scheduler/Makefile.avahi-3-timeouts cups-1.5.2/scheduler/Makefile
+--- cups-1.5.2/scheduler/Makefile.avahi-3-timeouts	2012-03-14 15:04:17.685305586 +0000
++++ cups-1.5.2/scheduler/Makefile	2012-03-14 15:06:36.508476980 +0000
+@@ -39,7 +39,8 @@ CUPSDOBJS =	\
+ 		server.o \
+ 		statbuf.o \
+ 		subscriptions.o \
+-		sysman.o
++		sysman.o \
++		timeout.o
+ LIBOBJS =	\
+ 		filter.o \
+ 		mime.o \
+diff -up cups-1.5.2/scheduler/timeout.c.avahi-3-timeouts cups-1.5.2/scheduler/timeout.c
+--- cups-1.5.2/scheduler/timeout.c.avahi-3-timeouts	2012-03-14 15:06:36.552477037 +0000
++++ cups-1.5.2/scheduler/timeout.c	2012-03-14 15:06:36.552477037 +0000
+@@ -0,0 +1,235 @@
++/*
++ * "$Id$"
++ *
++ *   Timeout functions for the Common UNIX Printing System (CUPS).
++ *
++ *   Copyright (C) 2010, 2011 Red Hat, Inc.
++ *   Authors:
++ *     Tim Waugh <twaugh@redhat.com>
++ *
++ *   Redistribution and use in source and binary forms, with or without
++ *   modification, are permitted provided that the following conditions
++ *   are met:
++ *
++ *   Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ *   Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ *
++ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ *   OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Contents:
++ *
++ *   cupsdInitTimeouts()  - Initialise timeout structure.
++ *   cupsdAddTimeout()    - Add a timed callback.
++ *   cupsdNextTimeout()   - Find the next enabled timed callback.
++ *   cupsdUpdateTimeout() - Adjust the time of a timed callback or disable it.
++ *   cupsdRemoveTimeout() - Discard a timed callback.
++ *   compare_timeouts()   - Compare timed callbacks for array sorting.
++ */
++
++#include <config.h>
++
++#ifdef HAVE_AVAHI /* Applies to entire file... */
++
++/*
++ * Include necessary headers...
++ */
++
++#include "cupsd.h"
++
++#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
++#  include <malloc.h>
++#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
++
++#ifdef HAVE_AVAHI
++#  include <avahi-common/timeval.h>
++#endif /* HAVE_AVAHI */
++
++
++struct _cupsd_timeout_s
++{
++  struct timeval when;
++  int enabled;
++  cupsd_timeoutfunc_t callback;
++  void *data;
++};
++
++/*
++ * Local functions...
++ */
++
++/*
++ * 'compare_timeouts()' - Compare timed callbacks for array sorting.
++ */
++
++static int
++compare_addrs (void *p0, void *p1)
++{
++  if (p0 == p1)
++    return (0);
++  if (p0 < p1)
++    return (-1);
++  return (1);
++}
++
++static int
++compare_timeouts (cupsd_timeout_t *p0, cupsd_timeout_t *p1)
++{
++  int addrsdiff = compare_addrs (p0, p1);
++  int tvdiff;
++
++  if (addrsdiff == 0)
++    return (0);
++
++  if (!p0->enabled || !p1->enabled)
++  {
++    if (!p0->enabled && !p1->enabled)
++      return (addrsdiff);
++
++    return (p0->enabled ? -1 : 1);
++  }
++
++  tvdiff = avahi_timeval_compare (&p0->when, &p1->when);
++  if (tvdiff != 0)
++    return (tvdiff);
++
++  return (addrsdiff);
++}
++
++
++/*
++ * 'cupsdInitTimeouts()' - Initialise timeout structures.
++ */
++
++void
++cupsdInitTimeouts(void)
++{
++  Timeouts = cupsArrayNew ((cups_array_func_t)compare_timeouts, NULL);
++}
++
++
++/*
++ * 'cupsdAddTimeout()' - Add a timed callback.
++ */
++
++cupsd_timeout_t *				/* O - Timeout handle */
++cupsdAddTimeout(const struct timeval *tv,	/* I - Absolute time */
++		cupsd_timeoutfunc_t cb,		/* I - Callback function */
++		void *data)			/* I - User data */
++{
++  cupsd_timeout_t *timeout;
++
++  timeout = malloc (sizeof(cupsd_timeout_t));
++  if (timeout != NULL)
++  {
++    timeout->enabled = (tv != NULL);
++    if (tv)
++    {
++      timeout->when.tv_sec = tv->tv_sec;
++      timeout->when.tv_usec = tv->tv_usec;
++    }
++
++    timeout->callback = cb;
++    timeout->data = data;
++    cupsArrayAdd (Timeouts, timeout);
++  }
++
++  return timeout;
++}
++
++
++/*
++ * 'cupsdNextTimeout()' - Find the next enabled timed callback.
++ */
++
++cupsd_timeout_t *		/* O - Next enabled timeout or NULL */
++cupsdNextTimeout(long *delay)	/* O - Seconds before scheduled */
++{
++  cupsd_timeout_t *first = cupsArrayFirst (Timeouts);
++  struct timeval curtime;
++
++  if (first && !first->enabled)
++    first = NULL;
++
++  if (first && delay)
++  {
++    gettimeofday (&curtime, NULL);
++    if (avahi_timeval_compare (&curtime, &first->when) > 0)
++    {
++      *delay = 0;
++    } else {
++      *delay = 1 + first->when.tv_sec - curtime.tv_sec;
++      if (first->when.tv_usec < curtime.tv_usec)
++	(*delay)--;
++    }
++  }
++
++  return (first);
++}
++
++
++/*
++ * 'cupsdRunTimeout()' - Run a timed callback.
++ */
++
++void
++cupsdRunTimeout(cupsd_timeout_t *timeout)	/* I - Timeout */
++{
++  if (!timeout)
++    return;
++  timeout->enabled = 0;
++  if (!timeout->callback)
++    return;
++  timeout->callback (timeout, timeout->data);
++}
++
++/*
++ * 'cupsdUpdateTimeout()' - Adjust the time of a timed callback or disable it.
++ */
++
++void
++cupsdUpdateTimeout(cupsd_timeout_t *timeout,	/* I - Timeout */
++		   const struct timeval *tv)	/* I - Absolute time or NULL */
++{
++  cupsArrayRemove (Timeouts, timeout);
++  timeout->enabled = (tv != NULL);
++  if (tv)
++  {
++    timeout->when.tv_sec = tv->tv_sec;
++    timeout->when.tv_usec = tv->tv_usec;
++  }
++  cupsArrayAdd (Timeouts, timeout);
++}
++
++
++/*
++ * 'cupsdRemoveTimeout()' - Discard a timed callback.
++ */
++
++void
++cupsdRemoveTimeout(cupsd_timeout_t *timeout)	/* I - Timeout */
++{
++  cupsArrayRemove (Timeouts, timeout);
++  free (timeout);
++}
++
++
++#endif /* HAVE_AVAHI ... from top of file */
++
++/*
++ * End of "$Id$".
++ */
diff --git a/srcpkgs/cups/patches/cups-avahi-4-poll.patch b/srcpkgs/cups/patches/cups-avahi-4-poll.patch
new file mode 100644
index 0000000000..d7fa5fd563
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-avahi-4-poll.patch
@@ -0,0 +1,529 @@
+diff -up cups-1.5.2/scheduler/avahi.c.avahi-4-poll cups-1.5.2/scheduler/avahi.c
+--- cups-1.5.2/scheduler/avahi.c.avahi-4-poll	2012-03-14 15:07:29.477542381 +0000
++++ cups-1.5.2/scheduler/avahi.c	2012-03-14 15:07:29.477542381 +0000
+@@ -0,0 +1,441 @@
++/*
++ * "$Id$"
++ *
++ *   Avahi poll implementation for the CUPS scheduler.
++ *
++ *   Copyright (C) 2010, 2011 Red Hat, Inc.
++ *   Authors:
++ *    Tim Waugh <twaugh@redhat.com>
++ *
++ *   Redistribution and use in source and binary forms, with or without
++ *   modification, are permitted provided that the following conditions
++ *   are met:
++ *
++ *   Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ *   Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ *
++ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ *   OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Contents:
++ *
++ *   watch_read_cb         - Read callback for file descriptor
++ *   watch_write_cb        - Write callback for file descriptor
++ *   watched_fd_add_select() - Call cupsdAddSelect() as needed
++ *   watch_new()           - Create a new file descriptor watch
++ *   watch_free()          - Free a file descriptor watch
++ *   watch_update()        - Update watched events for a file descriptor
++ *   watch_get_events()    - Get events that happened for a file descriptor
++ *   timeout_cb()          - Run a timed Avahi callback
++ *   timeout_new()         - Set a wakeup time
++ *   timeout_update()      - Update the expiration time for a timeout
++ *   timeout_free()        - Free a timeout
++ *   compare_watched_fds() - Compare watched file descriptors for array sorting
++ *   avahi_cups_poll_new() - Create a new Avahi main loop object for CUPS
++ *   avahi_cups_poll_free() - Free an Avahi main loop object for CUPS
++ *   avahi_cups_poll_get() - Get the abstract poll API structure
++ */
++
++#include <config.h>
++
++#ifdef HAVE_AVAHI /* Applies to entire file... */
++
++/*
++ * Include necessary headers...
++ */
++
++#include "cupsd.h"
++
++#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
++#  include <malloc.h>
++#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
++
++#ifdef HAVE_AVAHI
++#  include <avahi-common/timeval.h>
++#endif /* HAVE_AVAHI */
++
++
++typedef struct
++{
++  AvahiCupsPoll *cups_poll;
++
++  int fd;
++  AvahiWatchEvent occurred;
++  cups_array_t *watches;
++} cupsd_watched_fd_t;
++
++struct AvahiWatch
++{
++  cupsd_watched_fd_t *watched_fd;
++
++  AvahiWatchEvent events;
++  AvahiWatchCallback callback;
++  void *userdata;
++};
++
++struct AvahiTimeout
++{
++  AvahiCupsPoll *cups_poll;
++  AvahiTimeoutCallback callback;
++  void *userdata;
++  cupsd_timeout_t *cupsd_timeout;
++};
++
++/*
++ * Local functions...
++ */
++
++static AvahiWatch *	watch_new(const AvahiPoll *api,
++				  int fd,
++				  AvahiWatchEvent events,
++				  AvahiWatchCallback callback,
++				  void *userdata);
++static void		watch_free(AvahiWatch *watch);
++static void		watch_update(AvahiWatch *watch,
++				     AvahiWatchEvent events);
++static AvahiWatchEvent	watch_get_events(AvahiWatch *watch);
++
++
++/*
++ * 'watch_read_cb' - Read callback for file descriptor
++ */
++
++static void
++watch_read_cb (void *userdata)
++{
++  AvahiWatch *watch;
++  cupsd_watched_fd_t *watched_fd = userdata;
++  watched_fd->occurred |= AVAHI_WATCH_IN;
++  for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches);
++       watch;
++       watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches))
++  {
++    if (watch->events & watched_fd->occurred)
++    {
++      (watch->callback) (watch, watched_fd->fd,
++			 AVAHI_WATCH_IN, watch->userdata);
++      watched_fd->occurred &= ~AVAHI_WATCH_IN;
++      break;
++    }
++  }
++}
++
++
++/*
++ * 'watch_write_cb' - Write callback for file descriptor
++ */
++
++static void
++watch_write_cb (void *userdata)
++{
++  AvahiWatch *watch;
++  cupsd_watched_fd_t *watched_fd = userdata;
++  watched_fd->occurred |= AVAHI_WATCH_OUT;
++  for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches);
++       watch;
++       watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches))
++  {
++    if (watch->events & watched_fd->occurred)
++    {
++      (watch->callback) (watch, watched_fd->fd,
++			 AVAHI_WATCH_OUT, watch->userdata);
++      watched_fd->occurred &= ~AVAHI_WATCH_OUT;
++      break;
++    }
++  }
++}
++
++
++/*
++ * 'watched_fd_add_select' - Call cupsdAddSelect() as needed
++ */
++
++static int						/* O - Watches? */
++watched_fd_add_select (cupsd_watched_fd_t *watched_fd)
++{
++  AvahiWatch *watch;
++  cupsd_selfunc_t read_cb = NULL, write_cb = NULL;
++  int any_watches = 0;
++
++  for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches);
++       watch;
++       watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches))
++  {
++    any_watches = 1;
++    if (watch->events & (AVAHI_WATCH_IN |
++			     AVAHI_WATCH_ERR |
++			     AVAHI_WATCH_HUP))
++    {
++      read_cb = (cupsd_selfunc_t)watch_read_cb;
++      if (write_cb != NULL)
++	break;
++    }
++
++    if (watch->events & AVAHI_WATCH_OUT)
++    {
++      write_cb = (cupsd_selfunc_t)watch_write_cb;
++      if (read_cb != NULL)
++	break;
++    }
++  }
++
++  if (read_cb || write_cb)
++    cupsdAddSelect (watched_fd->fd, read_cb, write_cb, watched_fd);
++  else
++    cupsdRemoveSelect (watched_fd->fd);
++
++  return (any_watches);
++}
++
++/*
++ * 'watch_new' - Create a new file descriptor watch
++ */
++
++static AvahiWatch *
++watch_new (const AvahiPoll *api,
++	   int fd,
++	   AvahiWatchEvent events,
++	   AvahiWatchCallback callback,
++	   void *userdata)
++{
++  cupsd_watched_fd_t key, *watched_fd;
++  AvahiCupsPoll *cups_poll = api->userdata;
++  AvahiWatch *watch = malloc(sizeof(AvahiWatch));
++  if (watch == NULL)
++    return (NULL);
++
++  watch->events = events;
++  watch->callback = callback;
++  watch->userdata = userdata;
++
++  key.fd = fd;
++  watched_fd = cupsArrayFind (cups_poll->watched_fds, &key);
++  if (watched_fd == NULL)
++  {
++    watched_fd = malloc(sizeof(cupsd_watched_fd_t));
++    if (watched_fd == NULL)
++    {
++      free (watch);
++      return (NULL);
++    }
++
++    watched_fd->fd = fd;
++    watched_fd->occurred = 0;
++    watched_fd->cups_poll = cups_poll;
++    watched_fd->watches = cupsArrayNew (NULL, NULL);
++    cupsArrayAdd (cups_poll->watched_fds, watched_fd);
++  }
++
++  watch->watched_fd = watched_fd;
++  cupsArrayAdd(watched_fd->watches, watch);
++  watched_fd_add_select (watched_fd);
++  return (watch);
++}
++
++
++/*
++ * 'watch_free' - Free a file descriptor watch
++ */
++
++static void
++watch_free (AvahiWatch *watch)
++{
++  cupsd_watched_fd_t *watched_fd = watch->watched_fd;
++  AvahiCupsPoll *cups_poll = watched_fd->cups_poll;
++
++  cupsArrayRemove (watched_fd->watches, watch);
++  free (watch);
++
++  if (!watched_fd_add_select (watched_fd))
++  {
++    /* No more watches */
++    cupsArrayRemove (cups_poll->watched_fds, watched_fd);
++    free (watched_fd);
++  }
++}
++
++
++/*
++ * 'watch_update' - Update watched events for a file descriptor
++ */
++
++static void
++watch_update (AvahiWatch *watch,
++	      AvahiWatchEvent events)
++{
++  watch->events = events;
++  watched_fd_add_select (watch->watched_fd);
++}
++
++
++/*
++ * 'watch_get_events' - Get events that happened for a file descriptor
++ */
++
++static AvahiWatchEvent
++watch_get_events (AvahiWatch *watch)
++{
++  return (watch->watched_fd->occurred);
++}
++
++
++/*
++ * 'timeout_cb()' - Run a timed Avahi callback
++ */
++
++static void
++timeout_cb (cupsd_timeout_t *cupsd_timeout, void *userdata)
++{
++  AvahiTimeout *timeout = userdata;
++  (timeout->callback) (timeout, timeout->userdata);
++}
++
++
++/*
++ * 'timeout_new' - Set a wakeup time
++ */
++
++static AvahiTimeout *
++timeout_new (const AvahiPoll *api,
++	     const struct timeval *tv,
++	     AvahiTimeoutCallback callback,
++	     void *userdata)
++{
++  AvahiTimeout *timeout;
++  AvahiCupsPoll *cups_poll = api->userdata;
++
++  timeout = malloc(sizeof(AvahiTimeout));
++  if (timeout == NULL)
++    return (NULL);
++
++  timeout->cups_poll = cups_poll;
++  timeout->callback = callback;
++  timeout->userdata = userdata;
++  timeout->cupsd_timeout = cupsdAddTimeout (tv,
++					    (cupsd_timeoutfunc_t)timeout_cb,
++					    timeout);
++  cupsArrayAdd (cups_poll->timeouts, timeout);
++  return (timeout);
++}
++
++
++/*
++ * 'timeout_update' - Update the expiration time for a timeout
++ */
++
++static void
++timeout_update (AvahiTimeout *timeout,
++		const struct timeval *tv)
++{
++  cupsdUpdateTimeout (timeout->cupsd_timeout, tv);
++}
++
++
++/*
++ * ' timeout_free' - Free a timeout
++ */
++
++static void
++timeout_free (AvahiTimeout *timeout)
++{
++  cupsArrayRemove (timeout->cups_poll->timeouts, timeout);
++  cupsdRemoveTimeout (timeout->cupsd_timeout);
++  free (timeout);
++}
++
++
++/*
++ * 'compare_watched_fds' - Compare watched file descriptors for array sorting
++ */
++static int
++compare_watched_fds(cupsd_watched_fd_t *p0,
++		    cupsd_watched_fd_t *p1)
++{
++  /*
++   * Compare by fd (no two elements have the same fd)
++   */
++
++  if (p0->fd == p1->fd)
++    return 0;
++
++  return (p0->fd < p1->fd ? -1 : 1);
++}
++
++
++/*
++ * 'avahi_cups_poll_new' - Create a new Avahi main loop object for CUPS
++ */
++
++AvahiCupsPoll *
++avahi_cups_poll_new (void)
++{
++  AvahiCupsPoll *cups_poll = malloc(sizeof(AvahiCupsPoll));
++  if (cups_poll == NULL)
++    return (NULL);
++
++  cups_poll->watched_fds = cupsArrayNew ((cups_array_func_t)compare_watched_fds,
++					 NULL);
++  cups_poll->timeouts = cupsArrayNew (NULL, NULL);
++
++  cups_poll->api.userdata = cups_poll;
++  cups_poll->api.watch_new = watch_new;
++  cups_poll->api.watch_free = watch_free;
++  cups_poll->api.watch_update = watch_update;
++  cups_poll->api.watch_get_events = watch_get_events;
++
++  cups_poll->api.timeout_new = timeout_new;
++  cups_poll->api.timeout_update = timeout_update;
++  cups_poll->api.timeout_free = timeout_free;
++
++  return (cups_poll);
++}
++
++
++/*
++ * 'avahi_cups_poll_free' - Free an Avahi main loop object for CUPS
++ */
++void
++avahi_cups_poll_free (AvahiCupsPoll *cups_poll)
++{
++  cupsd_watched_fd_t *watched_fd;
++
++  for (watched_fd = (cupsd_watched_fd_t*)cupsArrayFirst(cups_poll->watched_fds);
++       watched_fd;
++       watched_fd = (cupsd_watched_fd_t*)cupsArrayNext(cups_poll->watched_fds))
++    cupsArrayClear (watched_fd->watches);
++
++  cupsArrayClear (cups_poll->watched_fds);
++  cupsArrayClear (cups_poll->timeouts);
++}
++
++
++/*
++ * 'avahi_cups_poll_get' - Get the abstract poll API structure
++ */
++
++const AvahiPoll *
++avahi_cups_poll_get (AvahiCupsPoll *cups_poll)
++{
++  return (&cups_poll->api);
++}
++
++
++#endif /* HAVE_AVAHI ... from top of file */
++
++/*
++ * End of "$Id$".
++ */
+diff -up cups-1.5.2/scheduler/avahi.h.avahi-4-poll cups-1.5.2/scheduler/avahi.h
+--- cups-1.5.2/scheduler/avahi.h.avahi-4-poll	2012-03-14 15:07:29.477542381 +0000
++++ cups-1.5.2/scheduler/avahi.h	2012-03-14 15:07:29.477542381 +0000
+@@ -0,0 +1,69 @@
++/*
++ * "$Id$"
++ *
++ *   Avahi poll implementation for the CUPS scheduler.
++ *
++ *   Copyright (C) 2010, 2011 Red Hat, Inc.
++ *   Authors:
++ *    Tim Waugh <twaugh@redhat.com>
++ *
++ *   Redistribution and use in source and binary forms, with or without
++ *   modification, are permitted provided that the following conditions
++ *   are met:
++ *
++ *   Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ *   Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ *
++ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ *   OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <config.h>
++
++#ifdef HAVE_AVAHI
++#  include <avahi-client/client.h>
++#  include <avahi-client/publish.h>
++#endif /* HAVE_AVAHI */
++
++#ifdef HAVE_AUTHORIZATION_H
++#  include <Security/Authorization.h>
++#endif /* HAVE_AUTHORIZATION_H */
++
++
++#ifdef HAVE_AVAHI
++typedef struct
++{
++    AvahiPoll api;
++    cups_array_t *watched_fds;
++    cups_array_t *timeouts;
++} AvahiCupsPoll;
++#endif /* HAVE_AVAHI */
++
++/*
++ * Prototypes...
++ */
++
++#ifdef HAVE_AVAHI
++extern AvahiCupsPoll *	avahi_cups_poll_new(void);
++extern void		avahi_cups_poll_free(AvahiCupsPoll *cups_poll);
++extern const AvahiPoll *avahi_cups_poll_get(AvahiCupsPoll *cups_poll);
++#endif /* HAVE_AVAHI */
++
++
++/*
++ * End of "$Id$".
++ */
+diff -up cups-1.5.2/scheduler/Makefile.avahi-4-poll cups-1.5.2/scheduler/Makefile
+--- cups-1.5.2/scheduler/Makefile.avahi-4-poll	2012-03-14 15:06:36.508476980 +0000
++++ cups-1.5.2/scheduler/Makefile	2012-03-14 15:07:29.476542380 +0000
+@@ -17,6 +17,7 @@ include ../Makedefs
+ 
+ CUPSDOBJS =	\
+ 		auth.o \
++		avahi.o \
+ 		banners.o \
+ 		cert.o \
+ 		classes.o \
diff --git a/srcpkgs/cups/patches/cups-avahi-5-services.patch b/srcpkgs/cups/patches/cups-avahi-5-services.patch
new file mode 100644
index 0000000000..820b3c32b9
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-avahi-5-services.patch
@@ -0,0 +1,1272 @@
+diff -up cups-1.5.2/cgi-bin/admin.c.avahi-5-services cups-1.5.2/cgi-bin/admin.c
+--- cups-1.5.2/cgi-bin/admin.c.avahi-5-services	2011-08-17 22:01:53.000000000 +0100
++++ cups-1.5.2/cgi-bin/admin.c	2012-03-14 15:08:25.701611799 +0000
+@@ -1643,7 +1643,7 @@ do_config_server(http_t *http)		/* I - H
+       else
+ 	local_protocols[0] = '\0';
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+       if (cgiGetVariable("BROWSE_LOCAL_DNSSD"))
+       {
+ 	if (local_protocols[0])
+@@ -1651,7 +1651,7 @@ do_config_server(http_t *http)		/* I - H
+ 	else
+ 	  strcat(local_protocols, "dnssd");
+       }
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ #ifdef HAVE_LDAP
+       if (cgiGetVariable("BROWSE_LOCAL_LDAP"))
+@@ -2718,9 +2718,9 @@ do_menu(http_t *http)			/* I - HTTP conn
+ #endif /* HAVE_GSSAPI */
+   cgiSetVariable("KERBEROS", "");
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   cgiSetVariable("HAVE_DNSSD", "1");
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ #ifdef HAVE_LDAP
+   cgiSetVariable("HAVE_LDAP", "1");
+diff -up cups-1.5.2/scheduler/avahi.h.avahi-5-services cups-1.5.2/scheduler/avahi.h
+--- cups-1.5.2/scheduler/avahi.h.avahi-5-services	2012-03-14 15:07:29.477542381 +0000
++++ cups-1.5.2/scheduler/avahi.h	2012-03-14 15:08:25.701611799 +0000
+@@ -3,7 +3,7 @@
+  *
+  *   Avahi poll implementation for the CUPS scheduler.
+  *
+- *   Copyright (C) 2010, 2011 Red Hat, Inc.
++ *   Copyright (C) 2010, 2011, 2012 Red Hat, Inc.
+  *   Authors:
+  *    Tim Waugh <twaugh@redhat.com>
+  *
+@@ -32,37 +32,40 @@
+  *   OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-#include <config.h>
++#ifndef _CUPS_AVAHI_H_
++#  define _CUPS_AVAHI_H_
+ 
+-#ifdef HAVE_AVAHI
+-#  include <avahi-client/client.h>
+-#  include <avahi-client/publish.h>
+-#endif /* HAVE_AVAHI */
++/*
++ * Include necessary headers...
++ */
+ 
+-#ifdef HAVE_AUTHORIZATION_H
+-#  include <Security/Authorization.h>
+-#endif /* HAVE_AUTHORIZATION_H */
++#  include <config.h>
+ 
++#  ifdef HAVE_AVAHI
++#    include <avahi-client/client.h>
++#    include <avahi-client/publish.h>
++#  endif /* HAVE_AVAHI */
+ 
+-#ifdef HAVE_AVAHI
++#  ifdef HAVE_AVAHI
+ typedef struct
+ {
+     AvahiPoll api;
+     cups_array_t *watched_fds;
+     cups_array_t *timeouts;
+ } AvahiCupsPoll;
+-#endif /* HAVE_AVAHI */
++#  endif /* HAVE_AVAHI */
+ 
+ /*
+  * Prototypes...
+  */
+ 
+-#ifdef HAVE_AVAHI
++#  ifdef HAVE_AVAHI
+ extern AvahiCupsPoll *	avahi_cups_poll_new(void);
+ extern void		avahi_cups_poll_free(AvahiCupsPoll *cups_poll);
+ extern const AvahiPoll *avahi_cups_poll_get(AvahiCupsPoll *cups_poll);
+-#endif /* HAVE_AVAHI */
++#  endif /* HAVE_AVAHI */
+ 
++#endif /* !_CUPS_AVAHI_H_ */
+ 
+ /*
+  * End of "$Id$".
+diff -up cups-1.5.2/scheduler/client.c.avahi-5-services cups-1.5.2/scheduler/client.c
+--- cups-1.5.2/scheduler/client.c.avahi-5-services	2012-01-13 23:00:22.000000000 +0000
++++ cups-1.5.2/scheduler/client.c	2012-03-14 15:08:25.703611797 +0000
+@@ -4989,7 +4989,7 @@ valid_host(cupsd_client_t *con)		/* I -
+ 	    !strncmp(host, "[::1]:", 6));
+   }
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+  /*
+   * Check if the hostname is something.local (Bonjour); if so, allow it.
+   */
+@@ -4998,7 +4998,7 @@ valid_host(cupsd_client_t *con)		/* I -
+       (!_cups_strcasecmp(end, ".local") || !_cups_strncasecmp(end, ".local:", 7) ||
+        !_cups_strcasecmp(end, ".local.") || !_cups_strncasecmp(end, ".local.:", 8)))
+     return (1);
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+  /*
+   * Check if the hostname is an IP address...
+diff -up cups-1.5.2/scheduler/conf.c.avahi-5-services cups-1.5.2/scheduler/conf.c
+--- cups-1.5.2/scheduler/conf.c.avahi-5-services	2012-03-14 15:04:17.636305526 +0000
++++ cups-1.5.2/scheduler/conf.c	2012-03-14 15:08:25.706611803 +0000
+@@ -652,7 +652,7 @@ cupsdReadConfiguration(void)
+   Browsing                 = CUPS_DEFAULT_BROWSING;
+   DefaultShared            = CUPS_DEFAULT_DEFAULT_SHARED;
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   cupsdSetString(&DNSSDRegType, "_ipp._tcp,_cups");
+ #endif /* HAVE_DNSSD */
+ 
+diff -up cups-1.5.2/scheduler/dirsvc.c.avahi-5-services cups-1.5.2/scheduler/dirsvc.c
+--- cups-1.5.2/scheduler/dirsvc.c.avahi-5-services	2012-03-14 15:04:17.674305572 +0000
++++ cups-1.5.2/scheduler/dirsvc.c	2012-03-14 15:08:25.709611806 +0000
+@@ -27,6 +27,7 @@
+  *   ldap_connect()             - Start new LDAP connection
+  *   ldap_reconnect()           - Reconnect to LDAP Server
+  *   ldap_disconnect()          - Disconnect from LDAP Server
++ *   cupsdStartAvahiClient()    - Start an Avahi client if needed
+  *   cupsdStartBrowsing()       - Start sending and receiving broadcast
+  *                                information.
+  *   cupsdStartPolling()        - Start polling servers as needed.
+@@ -40,11 +41,12 @@
+  *   dequote()                  - Remote quotes from a string.
+  *   dnssdAddAlias()            - Add a DNS-SD alias name.
+  *   dnssdBuildTxtRecord()      - Build a TXT record from printer info.
+- *   dnssdComparePrinters()     - Compare the registered names of two printers.
+  *   dnssdDeregisterPrinter()   - Stop sending broadcast information for a
+  *                                printer.
+  *   dnssdPackTxtRecord()       - Pack an array of key/value pairs into the TXT
+  *                                record format.
++ *   avahiPackTxtRecord()       - Pack an array of key/value pairs into an
++ *                                AvahiStringList.
+  *   dnssdRegisterCallback()    - DNSServiceRegister callback.
+  *   dnssdRegisterPrinter()     - Start sending broadcast information for a
+  *                                printer or update the broadcast contents.
+@@ -83,6 +85,7 @@
+  */
+ 
+ #include "cupsd.h"
++#include <assert.h>
+ #include <grp.h>
+ 
+ #ifdef HAVE_DNSSD
+@@ -97,6 +100,17 @@
+ #    endif /* HAVE_SYSTEMCONFIGURATION */
+ #  endif /* __APPLE__ */
+ #endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++#  include <avahi-common/domain.h>
++#endif /* HAVE_AVAHI */
++
++
++#ifdef HAVE_DNSSD
++typedef char *cupsd_txt_record_t;
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++typedef AvahiStringList *cupsd_txt_record_t;
++#endif /* HAVE_AVAHI */
+ 
+ 
+ /*
+@@ -159,27 +173,38 @@ static void	update_polling(void);
+ static void	update_smb(int onoff);
+ 
+ 
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
++static cupsd_txt_record_t dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
++					      int for_lpd);
++static void	dnssdDeregisterPrinter(cupsd_printer_t *p);
++static void	dnssdRegisterPrinter(cupsd_printer_t *p);
++static void	dnssdStop(void);
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
++
+ #ifdef HAVE_DNSSD
+ #  ifdef HAVE_COREFOUNDATION
+ static void	dnssdAddAlias(const void *key, const void *value,
+ 		              void *context);
+ #  endif /* HAVE_COREFOUNDATION */
+-static char	*dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
+-		                     int for_lpd);
+-static int	dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
+-static void	dnssdDeregisterPrinter(cupsd_printer_t *p);
+-static char	*dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
+-		                    int count);
+ static void	dnssdRegisterCallback(DNSServiceRef sdRef,
+ 		                      DNSServiceFlags flags,
+ 				      DNSServiceErrorType errorCode,
+ 				      const char *name, const char *regtype,
+ 				      const char *domain, void *context);
+-static void	dnssdRegisterPrinter(cupsd_printer_t *p);
+-static void	dnssdStop(void);
+ static void	dnssdUpdate(void);
+ #endif /* HAVE_DNSSD */
+ 
++#ifdef HAVE_AVAHI
++static AvahiStringList *avahiPackTxtRecord(char *keyvalue[][2],
++					   int count);
++static void	avahi_entry_group_cb (AvahiEntryGroup *group,
++				      AvahiEntryGroupState state,
++				      void *userdata);
++static void	avahi_client_cb (AvahiClient *client,
++				 AvahiClientState state,
++				 void *userdata);
++#endif /* HAVE_AVAHI */
++
+ #ifdef HAVE_LDAP
+ static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
+ 		{
+@@ -283,10 +308,10 @@ cupsdDeregisterPrinter(
+     ldap_dereg_printer(p);
+ #endif /* HAVE_LDAP */
+ 
+-#ifdef HAVE_DNSSD
+-  if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
++  if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD))
+     dnssdDeregisterPrinter(p);
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ }
+ 
+ 
+@@ -702,10 +727,10 @@ cupsdRegisterPrinter(cupsd_printer_t *p)
+     slpRegisterPrinter(p); */
+ #endif /* HAVE_LIBSLP */
+ 
+-#ifdef HAVE_DNSSD
+-  if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
++  if ((BrowseLocalProtocols & BROWSE_DNSSD))
+     dnssdRegisterPrinter(p);
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ }
+ 
+ 
+@@ -1419,6 +1444,36 @@ ldap_disconnect(LDAP *ld)		/* I - LDAP h
+ #endif /* HAVE_LDAP */
+ 
+ 
++#ifdef HAVE_AVAHI
++/*
++ * 'cupsdStartAvahiClient()' - Start an Avahi client if needed
++ */
++
++void
++cupsdStartAvahiClient(void)
++{
++  int error = 0;
++
++  if (!AvahiCupsClient && !AvahiCupsClientConnecting)
++  {
++    if (!AvahiCupsPollHandle)
++      AvahiCupsPollHandle = avahi_cups_poll_new ();
++
++    if (AvahiCupsPollHandle)
++    {
++      if (avahi_client_new (avahi_cups_poll_get (AvahiCupsPollHandle),
++			    AVAHI_CLIENT_NO_FAIL,
++			    avahi_client_cb, NULL,
++			    &error) != NULL)
++	AvahiCupsClientConnecting = 1;
++      else
++	cupsdLogMessage (CUPSD_LOG_WARN, "Avahi client failed: %d", error);
++    }
++  }
++}
++#endif /* HAVE_AVAHI */
++
++  
+ /*
+  * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
+  */
+@@ -1542,13 +1597,16 @@ cupsdStartBrowsing(void)
+   else
+     BrowseSocket = -1;
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD)
+   {
++#ifdef HAVE_DNSSD
+     DNSServiceErrorType error;		/* Error from service creation */
++#endif /* HAVE_DNSSD */
+     cupsd_listener_t	*lis;		/* Current listening socket */
+ 
+ 
++#ifdef HAVE_DNSSD
+    /*
+     * First create a "master" connection for all registrations...
+     */
+@@ -1573,6 +1631,7 @@ cupsdStartBrowsing(void)
+       fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ 
+       cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
++#endif /* HAVE_DNSSD */
+ 
+      /*
+       * Then get the port we use for registrations.  If we are not listening
+@@ -1598,17 +1657,23 @@ cupsdStartBrowsing(void)
+       */
+ 
+       if (BrowseRemoteProtocols & BROWSE_DNSSD)
+-        DNSSDPrinters = cupsArrayNew((cups_array_func_t)dnssdComparePrinters,
+-	                             NULL);
++	  DNSSDPrinters = cupsArrayNew(NULL, NULL);
+ 
+      /*
+       * Set the computer name and register the web interface...
+       */
+ 
+       cupsdUpdateDNSSDName();
++
++#ifdef HAVE_AVAHI
++      cupsdStartAvahiClient ();
++#endif /* HAVE_AVAHI */
++
++#ifdef HAVE_DNSSD
+     }
+-  }
+ #endif /* HAVE_DNSSD */
++  }
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ #ifdef HAVE_LIBSLP
+   if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP)
+@@ -1834,10 +1899,10 @@ cupsdStopBrowsing(void)
+     BrowseSocket = -1;
+   }
+ 
+-#ifdef HAVE_DNSSD
+-  if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
++  if ((BrowseLocalProtocols & BROWSE_DNSSD))
+     dnssdStop();
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ #ifdef HAVE_LIBSLP
+   if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) &&
+@@ -1902,7 +1967,7 @@ cupsdStopPolling(void)
+ }
+ 
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ /*
+  * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
+  */
+@@ -1910,8 +1975,14 @@ cupsdStopPolling(void)
+ void
+ cupsdUpdateDNSSDName(void)
+ {
++#ifdef HAVE_DNSSD
+   DNSServiceErrorType error;		/* Error from service creation */
+   char		webif[1024];		/* Web interface share name */
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  int		ret;			/* Error from service creation */
++  char		webif[AVAHI_LABEL_MAX];	/* Web interface share name */
++#endif /* HAVE_AVAHI */
+ #  ifdef HAVE_SYSTEMCONFIGURATION
+   SCDynamicStoreRef sc;			/* Context for dynamic store */
+   CFDictionaryRef btmm;			/* Back-to-My-Mac domains */
+@@ -2042,6 +2113,7 @@ cupsdUpdateDNSSDName(void)
+     else
+       strlcpy(webif, "CUPS Web Interface", sizeof(webif));
+ 
++#ifdef HAVE_DNSSD
+     if (WebIFRef)
+       DNSServiceRefDeallocate(WebIFRef);
+ 
+@@ -2054,9 +2126,45 @@ cupsdUpdateDNSSDName(void)
+ 				    NULL)) != kDNSServiceErr_NoError)
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+ 		      "DNS-SD web interface registration failed: %d", error);
++#endif /* HAVE_DNSSD */
++
++#ifdef HAVE_AVAHI
++    if (!AvahiCupsClient)
++     /*
++      * Client not yet running.
++      */
++      return;
++
++    if (AvahiWebIFGroup)
++      avahi_entry_group_reset (AvahiWebIFGroup);
++    else
++      AvahiWebIFGroup = avahi_entry_group_new (AvahiCupsClient,
++					       avahi_entry_group_cb,
++					       NULL);
++
++    if (AvahiWebIFGroup)
++    {
++      ret = avahi_entry_group_add_service (AvahiWebIFGroup,
++					   AVAHI_IF_UNSPEC,
++					   AVAHI_PROTO_UNSPEC,
++					   0, /* flags */
++					   webif, /* name */
++					   "_http._tcp", /* type */
++					   NULL, /* domain */
++					   NULL, /* host */
++					   DNSSDPort, /* port */
++					   "path=/", NULL);
++      if (ret == 0)
++	ret = avahi_entry_group_commit (AvahiWebIFGroup);
++
++      if (ret != 0)
++	cupsdLogMessage (CUPSD_LOG_ERROR,
++			 "Avahi web interface registration failed: %d", ret);
++    }
++#endif /* HAVE_AVAHI */
+   }
+ }
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ 
+ #ifdef HAVE_LDAP
+@@ -2334,13 +2442,15 @@ dnssdAddAlias(const void *key,		/* I - K
+                     "Bad Back to My Mac domain in dynamic store!");
+ }
+ #  endif /* HAVE_COREFOUNDATION */
++#endif /* HAVE_DNSSD */
+ 
+ 
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ /*
+  * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
+  */
+ 
+-static char *				/* O - TXT record */
++static cupsd_txt_record_t		/* O - TXT record */
+ dnssdBuildTxtRecord(
+     int             *txt_len,		/* O - TXT record length */
+     cupsd_printer_t *p,			/* I - Printer information */
+@@ -2379,7 +2489,12 @@ dnssdBuildTxtRecord(
+   keyvalue[i  ][0] = "ty";
+   keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown";
+ 
+-  snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
++  snprintf(admin_hostname, sizeof(admin_hostname),
++	   "%s.local"
++#ifdef HAVE_DNSSD
++	   "." /* terminating dot no good for Avahi */
++#endif /* HAVE_DNSSD */
++	   , DNSSDHostName);
+   httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
+                    "http", NULL, admin_hostname, DNSSDPort, "/%s/%s",
+ 		   (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
+@@ -2462,19 +2577,12 @@ dnssdBuildTxtRecord(
+   * Then pack them into a proper txt record...
+   */
+ 
++#ifdef HAVE_DNSSD
+   return (dnssdPackTxtRecord(txt_len, keyvalue, i));
+-}
+-
+-
+-/*
+- * 'dnssdComparePrinters()' - Compare the registered names of two printers.
+- */
+-
+-static int				/* O - Result of comparison */
+-dnssdComparePrinters(cupsd_printer_t *a,/* I - First printer */
+-                     cupsd_printer_t *b)/* I - Second printer */
+-{
+-  return (_cups_strcasecmp(a->reg_name, b->reg_name));
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  return (avahiPackTxtRecord(keyvalue, i));
++#endif /* HAVE_AVAHI */
+ }
+ 
+ 
+@@ -2489,6 +2597,10 @@ dnssdDeregisterPrinter(
+ {
+   cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
+ 
++#ifdef HAVE_DNSSD
++  if (!DNSSDRef)
++    return;
++
+  /*
+   * Closing the socket deregisters the service
+   */
+@@ -2524,6 +2636,24 @@ dnssdDeregisterPrinter(
+     free(p->printer_txt);
+     p->printer_txt = NULL;
+   }
++#endif /* HAVE_DNSSD */
++
++#ifdef HAVE_AVAHI
++  if (p->avahi_group)
++    {
++      avahi_entry_group_reset (p->avahi_group);
++      avahi_entry_group_free (p->avahi_group);
++      p->avahi_group = NULL;
++
++      if (p->ipp_txt)
++	avahi_string_list_free (p->ipp_txt);
++
++      if (p->printer_txt)
++	avahi_string_list_free (p->printer_txt);
++
++      p->ipp_txt = p->printer_txt = NULL;
++    }
++#endif /* HAVE_AVAHI */
+ 
+  /*
+   * Remove the printer from the array of DNS-SD printers, then clear the
+@@ -2533,8 +2663,10 @@ dnssdDeregisterPrinter(
+   cupsArrayRemove(DNSSDPrinters, p);
+   cupsdClearString(&p->reg_name);
+ }
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ 
++#ifdef HAVE_DNSSD
+ /*
+  * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
+  *                          TXT record format.
+@@ -2644,8 +2776,10 @@ dnssdRegisterCallback(
+     LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
+   }
+ }
++#endif /* HAVE_DNSSD */
+ 
+ 
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ /*
+  * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
+  *		              or update the broadcast contents.
+@@ -2654,20 +2788,40 @@ dnssdRegisterCallback(
+ static void
+ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
+ {
++#ifdef HAVE_DNSSD
+   DNSServiceErrorType	se;		/* dnssd errors */
+   char			*ipp_txt,	/* IPP TXT record buffer */
+ 			*printer_txt,	/* LPD TXT record buffer */
+-			name[1024],	/* Service name */
+-			*nameptr;	/* Pointer into name */
++			name[1024];	/* Service name */
+   int			ipp_len,	/* IPP TXT record length */
+ 			printer_len,	/* LPD TXT record length */
+ 			printer_port;	/* LPD port number */
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  int			ret;		/* Error code */
++  AvahiStringList	*ipp_txt,	/* IPP TXT record */
++			*printer_txt;	/* LPD TXT record */
++  char			name[AVAHI_LABEL_MAX],	/* Service name */
++			fullsubtype[AVAHI_LABEL_MAX]; /* Full subtype */
++  char			*regtype_copy,	/* Writeable copy of reg type */
++			*subtype,	/* Current service sub type */
++			*nextsubtype;	/* Next service sub type */
++#endif /* HAVE_AVAHI */
++  char			*nameptr;	/* Pointer into name */
+   const char		*regtype;	/* Registration type */
+ 
+ 
++#ifdef HAVE_DNSSD
++  if (!DNSSDRef)
++    return;
++
+   cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
+                   !p->ipp_ref ? "new" : "update");
+-
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
++		  !p->avahi_group ? "new" : "update");
++#endif /* HAVE_AVAHI */
+  /*
+   * If per-printer sharing was just disabled make sure we're not
+   * registered before returning.
+@@ -2686,12 +2840,36 @@ dnssdRegisterPrinter(cupsd_printer_t *p)
+   if (p->info && strlen(p->info) > 0)
+   {
+     if (DNSSDComputerName)
+-      snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
++    {
++     /*
++      * Make sure there is room for at least 15 characters of
++      * DNSSDComputerName.
++      */
++
++      assert(sizeof(name) >= 15 + 4);
++      nameptr = name + strlcpy(name, p->info,
++			       sizeof(name) - 4 -
++			       strnlen(DNSSDComputerName, 15));
++      nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
++      strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
++    }
+     else
+       strlcpy(name, p->info, sizeof(name));
+   }
+   else if (DNSSDComputerName)
+-    snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
++  {
++   /*
++    * Make sure there is room for at least 15 characters of
++    * DNSSDComputerName.
++    */
++
++    assert(sizeof(name) >= 15 + 4);
++    nameptr = name + strlcpy(name, p->info,
++			     sizeof(name) - 4 -
++			     strnlen(DNSSDComputerName, 15));
++    nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
++    strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
++  }
+   else
+     strlcpy(name, p->name, sizeof(name));
+ 
+@@ -2712,6 +2890,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)
+   * Register IPP and (optionally) LPD...
+   */
+ 
++#ifdef HAVE_DNSSD
+   ipp_len = 0;				/* anti-compiler-warning-code */
+   ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
+ 
+@@ -2884,6 +3063,209 @@ dnssdRegisterPrinter(cupsd_printer_t *p)
+ 
+   if (printer_txt)
+     free(printer_txt);
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  if (!AvahiCupsClient)
++   /*
++    * Client not running yet.  The client callback will call us again later.
++    */
++    return;
++
++  ipp_txt = dnssdBuildTxtRecord(NULL, p, 0);
++  printer_txt = dnssdBuildTxtRecord(NULL, p, 1);
++  regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType;
++
++  if (p->avahi_group && p->ipp_txt && ipp_txt &&
++      !avahi_string_list_equal (p->ipp_txt, ipp_txt))
++  {
++   /*
++    * Update the existing registration...
++    */
++
++    avahi_string_list_free (p->ipp_txt);
++
++    if (p->printer_txt)
++      avahi_string_list_free (p->printer_txt);
++
++   /*
++    * Update the service group entry.
++    */
++
++    regtype_copy = strdup (regtype);
++    subtype = strchr (regtype_copy, ',');
++    if (subtype)
++      *subtype = '\0';
++
++    cupsdLogMessage (CUPSD_LOG_DEBUG,
++		     "Updating TXT record for %s (%s)", name, regtype_copy);
++    ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
++						       AVAHI_IF_UNSPEC,
++						       AVAHI_PROTO_UNSPEC,
++						       0, name,
++						       regtype_copy,
++						       NULL, ipp_txt);
++    free (regtype_copy);
++
++    if (ret < 0)
++      goto update_failed;
++
++    p->ipp_txt = ipp_txt;
++    ipp_txt = NULL;
++
++    if (BrowseLocalProtocols & BROWSE_LPD)
++    {
++      ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
++							 AVAHI_IF_UNSPEC,
++							 AVAHI_PROTO_UNSPEC,
++							 0, name,
++							 "_printer._tcp", NULL,
++							 printer_txt);
++      if (ret < 0)
++	goto update_failed;
++
++      p->printer_txt = printer_txt;
++      printer_txt = NULL;
++    }
++
++    ret = avahi_entry_group_commit (p->avahi_group);
++    if (ret < 0)
++    {
++    update_failed:
++      cupsdLogMessage (CUPSD_LOG_ERROR,
++		       "Failed to update TXT record for %s: %d",
++		       name, ret);
++      avahi_entry_group_reset (p->avahi_group);
++      avahi_entry_group_free (p->avahi_group);
++      p->avahi_group = NULL;
++      ipp_txt = p->ipp_txt;
++      p->ipp_txt = NULL;
++    }
++  }
++
++  if (!p->avahi_group)
++  {
++   /*
++    * Initial registration.  Use the _fax subtype for fax queues...
++    */
++
++    p->avahi_group = avahi_entry_group_new (AvahiCupsClient,
++					    avahi_entry_group_cb,
++					    p);
++
++    cupsdLogMessage(CUPSD_LOG_DEBUG,
++		    "Registering Avahi printer %s with name \"%s\" and "
++		    "type \"%s\"", p->name, name, regtype);
++
++    if (!p->avahi_group)
++    {
++      ret = 0;
++      goto add_failed;
++    }
++
++   /*
++    * Add each service type (DNSSDRegType may contain several,
++    * separated by commas).
++    */
++
++    subtype = regtype_copy = strdup (regtype);
++    while (subtype && *subtype)
++    {
++      nextsubtype = strchr (subtype, ',');
++      if (nextsubtype)
++	*nextsubtype++ = '\0';
++
++      if (subtype == regtype_copy)
++      {
++       /*
++	* Main type entry.
++	*/
++
++	cupsdLogMessage (CUPSD_LOG_DEBUG,
++			 "Adding TXT record for %s (%s)", name, regtype_copy);
++	ret = avahi_entry_group_add_service_strlst (p->avahi_group,
++						    AVAHI_IF_UNSPEC,
++						    AVAHI_PROTO_UNSPEC,
++						    0, name, regtype_copy,
++						    NULL, NULL,
++						    DNSSDPort,
++						    ipp_txt);
++      }
++      else
++      {
++       /*
++	* Sub-type entry.
++	*/
++
++	snprintf (fullsubtype, sizeof(fullsubtype),
++		  "%s._sub.%s", subtype, regtype_copy);
++	cupsdLogMessage (CUPSD_LOG_DEBUG,
++			 "Adding TXT record for %s (%s)", name, fullsubtype);
++	ret = avahi_entry_group_add_service_subtype (p->avahi_group,
++						     AVAHI_IF_UNSPEC,
++						     AVAHI_PROTO_UNSPEC,
++						     0, name,
++						     regtype_copy,
++						     NULL, fullsubtype);
++      }
++
++      if (ret < 0)
++      {
++	free (regtype_copy);
++	goto add_failed;
++      }
++
++      subtype = nextsubtype;
++    }
++
++    free (regtype_copy);
++    p->ipp_txt = ipp_txt;
++    ipp_txt = NULL;
++
++    if (BrowseLocalProtocols & BROWSE_LPD)
++    {
++      cupsdLogMessage(CUPSD_LOG_DEBUG,
++		      "Registering Avahi printer %s with name \"%s\" and "
++		      "type \"_printer._tcp\"", p->name, name);
++
++      ret = avahi_entry_group_add_service_strlst (p->avahi_group,
++						  AVAHI_IF_UNSPEC,
++						  AVAHI_PROTO_UNSPEC,
++						  0, name,
++						  "_printer._tcp", NULL, NULL,
++						  515,
++						  printer_txt);
++      if (ret < 0)
++	goto add_failed;
++
++      p->printer_txt = printer_txt;
++      printer_txt = NULL;
++    }
++
++    ret = avahi_entry_group_commit (p->avahi_group);
++
++    if (ret < 0)
++    {
++    add_failed:
++      cupsdLogMessage (CUPSD_LOG_ERROR,
++		       "Failed to add Avahi entry for %s: %d",
++		       name, ret);
++      if (p->avahi_group)
++      {
++	avahi_entry_group_reset (p->avahi_group);
++	avahi_entry_group_free (p->avahi_group);
++	p->avahi_group = NULL;
++      }
++      ipp_txt = p->ipp_txt;
++      p->ipp_txt = NULL;
++    }
++  }
++
++  if (ipp_txt)
++    avahi_string_list_free (ipp_txt);
++
++  if (printer_txt)
++    avahi_string_list_free (printer_txt);
++#endif /* HAVE_AVAHI */
+ }
+ 
+ 
+@@ -2896,6 +3278,10 @@ dnssdStop(void)
+ {
+   cupsd_printer_t	*p;		/* Current printer */
+ 
++#ifdef HAVE_DNSSD
++  if (!DNSSDRef)
++    return;
++#endif /* HAVE_DNSSD */
+ 
+  /*
+   * De-register the individual printers
+@@ -2910,12 +3296,23 @@ dnssdStop(void)
+   * Shutdown the rest of the service refs...
+   */
+ 
++#ifdef HAVE_DNSSD
+   if (WebIFRef)
+   {
+     DNSServiceRefDeallocate(WebIFRef);
+     WebIFRef = NULL;
+   }
++#endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  if (AvahiWebIFGroup)
++  {
++    avahi_entry_group_reset (AvahiWebIFGroup);
++    avahi_entry_group_free (AvahiWebIFGroup);
++    AvahiWebIFGroup = NULL;
++  }
++#endif /* HAVE_AVAHI */
+ 
++#ifdef HAVE_DNSSD
+   if (RemoteRef)
+   {
+     DNSServiceRefDeallocate(RemoteRef);
+@@ -2926,14 +3323,17 @@ dnssdStop(void)
+ 
+   DNSServiceRefDeallocate(DNSSDRef);
+   DNSSDRef = NULL;
++#endif /* HAVE_DNSSD */
+ 
+   cupsArrayDelete(DNSSDPrinters);
+   DNSSDPrinters = NULL;
+ 
+   DNSSDPort = 0;
+ }
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+ 
++#ifdef HAVE_DNSSD
+ /*
+  * 'dnssdUpdate()' - Handle DNS-SD queries.
+  */
+@@ -2955,6 +3355,153 @@ dnssdUpdate(void)
+ #endif /* HAVE_DNSSD */
+ 
+ 
++#ifdef HAVE_AVAHI
++/*
++ * 'avahiPackTxtRecord()' - Pack an array of key/value pairs into an
++ *                          AvahiStringList.
++ */
++
++static AvahiStringList *		/* O - new string list */
++avahiPackTxtRecord(char *keyvalue[][2],	/* I - Table of key value pairs */
++		   int count)		/* I - Number of items in table */
++{
++  AvahiStringList *strlst = NULL;
++  char **elements;
++  size_t len;
++  int i = 0;
++
++  elements = malloc ((1 + count) * sizeof (char *));
++  if (!elements)
++    goto cleanup;
++
++  for (i = 0; i < count; i++)
++    {
++      len = (1 + strlen (keyvalue[i][0]) +
++	     (keyvalue[i][1] ? 1 + strlen (keyvalue[i][1]) : 1));
++      elements[i] = malloc (len * sizeof (char));
++      if (!elements[i])
++	goto cleanup;
++
++      snprintf (elements[i], len, "%s=%s", keyvalue[i][0], keyvalue[i][1]);
++    }
++
++  strlst = avahi_string_list_new_from_array ((const char **) elements, count);
++
++cleanup:
++  while (--i >= 0)
++    free (elements[i]);
++
++  free (elements);
++  return (strlst);
++}
++
++
++/*
++ * 'avahi_entry_group_cb()' - Avahi entry group callback function.
++ */
++static void
++avahi_entry_group_cb (AvahiEntryGroup *group,
++		      AvahiEntryGroupState state,
++		      void *userdata)
++{
++  char *name;
++
++  if (userdata)
++    name = ((cupsd_printer_t *) userdata)->reg_name;
++  else
++    name = "CUPS web interface";
++
++  switch (state)
++  {
++  case AVAHI_ENTRY_GROUP_UNCOMMITED:
++  case AVAHI_ENTRY_GROUP_REGISTERING:
++    break;
++
++  case AVAHI_ENTRY_GROUP_ESTABLISHED:
++    cupsdLogMessage (CUPSD_LOG_DEBUG,
++		     "Avahi entry group established for %s", name);
++    break;
++
++  default:
++    cupsdLogMessage (CUPSD_LOG_DEBUG,
++		     "Avahi entry group %s has state %d",
++		     name, state);
++    break;
++  }
++}
++
++
++/*
++ * 'avahi_client_cb()' - Avahi client callback function.
++ */
++static void
++avahi_client_cb (AvahiClient *client,
++		 AvahiClientState state,
++		 void *userdata)
++{
++  cupsd_printer_t *printer;
++  switch (state)
++  {
++  case AVAHI_CLIENT_S_RUNNING:
++   /*
++    * Avahi client started successfully.
++    */
++    AvahiCupsClient = client;
++    AvahiCupsClientConnecting = 0;
++    cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client started");
++
++    cupsdUpdateDNSSDName ();
++
++    for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
++	 printer;
++	 printer = (cupsd_printer_t *)cupsArrayNext(Printers))
++      if (Browsing && (BrowseLocalProtocols & BROWSE_DNSSD) &&
++	  (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
++			      CUPS_PRINTER_SCANNER))) && printer->shared)
++	dnssdRegisterPrinter (printer);
++
++    break;
++
++  case AVAHI_CLIENT_CONNECTING:
++   /*
++    * No Avahi daemon, client is waiting.
++    */
++    cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client connecting");
++    break;
++
++  case AVAHI_CLIENT_S_REGISTERING:
++    /*
++     * Not yet registered.
++     */
++    cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client registering");
++    break;
++
++  case AVAHI_CLIENT_FAILURE:
++   /*
++    * Avahi client failed, close it to allow a clean restart.
++    */
++    cupsdLogMessage (CUPSD_LOG_ERROR,
++		     "Avahi client failed, "
++		     "closing client to allow a clean restart");
++
++    for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
++	 printer;
++	 printer = (cupsd_printer_t *)cupsArrayNext(Printers))
++      dnssdDeregisterPrinter (printer);
++
++    avahi_client_free(client);
++    AvahiCupsClientConnecting = 0;
++    AvahiCupsClient = NULL;
++
++    break;
++
++  default:
++    cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client state: %d", state);
++  }
++}
++#endif /* HAVE_AVAHI */
++
++
+ /*
+  * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
+  */
+diff -up cups-1.5.2/scheduler/dirsvc.h.avahi-5-services cups-1.5.2/scheduler/dirsvc.h
+--- cups-1.5.2/scheduler/dirsvc.h.avahi-5-services	2011-03-21 02:12:14.000000000 +0000
++++ cups-1.5.2/scheduler/dirsvc.h	2012-03-14 15:08:25.711611808 +0000
+@@ -31,6 +31,10 @@
+ #  endif /* HAVE_LDAP_SSL_H */
+ #endif /* HAVE_LDAP */
+ 
++#ifdef HAVE_AVAHI
++#  include <avahi-client/publish.h>
++#endif /* HAVE_AVAHI */
++
+ /*
+  * Browse protocols...
+  */
+@@ -131,19 +135,22 @@ VAR int			PollPipe	VALUE(0);
+ VAR cupsd_statbuf_t	*PollStatusBuffer VALUE(NULL);
+ 					/* Status buffer for pollers */
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ VAR char		*DNSSDComputerName VALUE(NULL),
+ 					/* Computer/server name */
+ 			*DNSSDHostName	VALUE(NULL),
+ 					/* Hostname */
+ 			*DNSSDRegType VALUE(NULL);
+ 					/* Bonjour registration type */
+-VAR cups_array_t	*DNSSDAlias	VALUE(NULL);
+-					/* List of dynamic ServerAlias's */
+ VAR int			DNSSDPort	VALUE(0);
+ 					/* Port number to register */
+ VAR cups_array_t	*DNSSDPrinters	VALUE(NULL);
+ 					/* Printers we have registered */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
++
++#ifdef HAVE_DNSSD
++VAR cups_array_t	*DNSSDAlias	VALUE(NULL);
++					/* List of dynamic ServerAlias's */
+ VAR DNSServiceRef	DNSSDRef	VALUE(NULL),
+ 					/* Master DNS-SD service reference */
+ 			WebIFRef	VALUE(NULL),
+@@ -152,6 +159,17 @@ VAR DNSServiceRef	DNSSDRef	VALUE(NULL),
+ 					/* Remote printer browse reference */
+ #endif /* HAVE_DNSSD */
+ 
++#ifdef HAVE_AVAHI
++VAR AvahiCupsPoll	*AvahiCupsPollHandle	VALUE(NULL);
++					/* AvahiCupsPoll object */
++VAR AvahiClient		*AvahiCupsClient	VALUE(NULL);
++					/* AvahiClient object */
++VAR int			AvahiCupsClientConnecting	VALUE(0);
++					/* Is AvahiClient object connecting? */
++VAR AvahiEntryGroup	*AvahiWebIFGroup	VALUE(NULL);
++					/* Web interface entry group */
++#endif /* HAVE_AVAHI */
++
+ #ifdef HAVE_LIBSLP
+ VAR SLPHandle		BrowseSLPHandle	VALUE(NULL);
+ 					/* SLP API handle */
+@@ -195,13 +213,14 @@ extern void	cupsdRegisterPrinter(cupsd_p
+ extern void	cupsdRestartPolling(void);
+ extern void	cupsdSaveRemoteCache(void);
+ extern void	cupsdSendBrowseList(void);
++extern void	cupsdStartAvahiClient(void);
+ extern void	cupsdStartBrowsing(void);
+ extern void	cupsdStartPolling(void);
+ extern void	cupsdStopBrowsing(void);
+ extern void	cupsdStopPolling(void);
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ extern void	cupsdUpdateDNSSDName(void);
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ #ifdef HAVE_LDAP
+ extern void	cupsdUpdateLDAPBrowse(void);
+ #endif /* HAVE_LDAP */
+diff -up cups-1.5.2/scheduler/ipp.c.avahi-5-services cups-1.5.2/scheduler/ipp.c
+--- cups-1.5.2/scheduler/ipp.c.avahi-5-services	2012-03-14 15:04:17.665305560 +0000
++++ cups-1.5.2/scheduler/ipp.c	2012-03-14 15:08:25.715611813 +0000
+@@ -6099,7 +6099,7 @@ copy_printer_attrs(
+     ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
+                ippTimeToDate(curtime));
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
+   {
+     if (printer->reg_name)
+@@ -6109,7 +6109,7 @@ copy_printer_attrs(
+       ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE,
+                    "printer-dns-sd-name", 0);
+   }
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+   if (!ra || cupsArrayFind(ra, "printer-error-policy"))
+     ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
+diff -up cups-1.5.2/scheduler/main.c.avahi-5-services cups-1.5.2/scheduler/main.c
+--- cups-1.5.2/scheduler/main.c.avahi-5-services	2012-03-14 15:06:36.511476986 +0000
++++ cups-1.5.2/scheduler/main.c	2012-03-14 15:08:25.718611817 +0000
+@@ -120,6 +120,10 @@ main(int  argc,				/* I - Number of comm
+   cupsd_listener_t	*lis;		/* Current listener */
+   time_t		current_time,	/* Current time */
+ 			activity,	/* Client activity timer */
++#ifdef HAVE_AVAHI
++			avahi_client_time, /* Time for next Avahi client
++					      check */
++#endif /* HAVE_AVAHI */
+ 			browse_time,	/* Next browse send time */
+ 			senddoc_time,	/* Send-Document time */
+ 			expire_time,	/* Subscription expire time */
+@@ -672,6 +676,9 @@ main(int  argc,				/* I - Number of comm
+   */
+ 
+   current_time  = time(NULL);
++#ifdef HAVE_AVAHI
++  avahi_client_time = current_time;
++#endif /* HAVE_AVAHI */
+   browse_time   = current_time;
+   event_time    = current_time;
+   expire_time   = current_time;
+@@ -894,6 +901,16 @@ main(int  argc,				/* I - Number of comm
+     tmo = cupsdNextTimeout (&tmo_delay);
+     if (tmo && tmo_delay == 0)
+       cupsdRunTimeout (tmo);
++
++   /*
++    * Try to restart the Avahi client every 10 seconds if needed...
++    */
++
++    if ((current_time - avahi_client_time) >= 10)
++    {
++      avahi_client_time = current_time;
++      cupsdStartAvahiClient();
++    }
+ #endif /* HAVE_AVAHI */
+ 
+ #ifndef __APPLE__
+diff -up cups-1.5.2/scheduler/printers.c.avahi-5-services cups-1.5.2/scheduler/printers.c
+--- cups-1.5.2/scheduler/printers.c.avahi-5-services	2012-03-14 15:04:17.646305537 +0000
++++ cups-1.5.2/scheduler/printers.c	2012-03-14 15:08:25.720611819 +0000
+@@ -883,9 +883,9 @@ cupsdDeletePrinter(
+   cupsdClearString(&p->alert);
+   cupsdClearString(&p->alert_description);
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   cupsdClearString(&p->pdl);
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ 
+   cupsArrayDelete(p->filetypes);
+ 
+@@ -3787,7 +3787,7 @@ add_printer_formats(cupsd_printer_t *p)
+     attr->values[i].string.text = _cupsStrAlloc(mimetype);
+   }
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   {
+     char		pdl[1024];	/* Buffer to build pdl list */
+     mime_filter_t	*filter;	/* MIME filter looping var */
+@@ -3843,7 +3843,7 @@ add_printer_formats(cupsd_printer_t *p)
+ 
+     cupsdSetString(&p->pdl, pdl);
+   }
+-#endif /* HAVE_DNSSD */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
+ }
+ 
+ 
+diff -up cups-1.5.2/scheduler/printers.h.avahi-5-services cups-1.5.2/scheduler/printers.h
+--- cups-1.5.2/scheduler/printers.h.avahi-5-services	2011-03-18 18:42:46.000000000 +0000
++++ cups-1.5.2/scheduler/printers.h	2012-03-14 15:08:25.721611820 +0000
+@@ -16,6 +16,9 @@
+ #ifdef HAVE_DNSSD
+ #  include <dns_sd.h>
+ #endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++#  include "avahi.h"
++#endif /* HAVE_AVAHI */
+ #include <cups/pwg-private.h>
+ 
+ 
+@@ -95,16 +98,23 @@ struct cupsd_printer_s
+   time_t	marker_time;		/* Last time marker attributes were updated */
+   _ppd_cache_t	*pc;			/* PPD cache and mapping data */
+ 
+-#ifdef HAVE_DNSSD
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+   char		*reg_name,		/* Name used for service registration */
+-		*pdl,			/* pdl value for TXT record */
+-		*ipp_txt,		/* IPP TXT record contents */
++		*pdl;			/* pdl value for TXT record */
++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
++#ifdef HAVE_DNSSD
++  char		*ipp_txt,		/* IPP TXT record contents */
+ 		*printer_txt;		/* LPD TXT record contents */
+   int		ipp_len,		/* IPP TXT record length */
+ 		printer_len;		/* LPD TXT record length */
+   DNSServiceRef	ipp_ref,		/* Reference for _ipp._tcp,_cups */
+ 		printer_ref;		/* Reference for _printer._tcp */
+ #endif /* HAVE_DNSSD */
++#ifdef HAVE_AVAHI
++  AvahiStringList *ipp_txt,		/* IPP TXT record */
++		*printer_txt;		/* LPD TXT record */
++  AvahiEntryGroup *avahi_group;		/* Avahi entry group */
++#endif /* HAVE_AVAHI */
+ };
+ 
+ 
diff --git a/srcpkgs/cups/patches/cups-banners.patch b/srcpkgs/cups/patches/cups-banners.patch
new file mode 100644
index 0000000000..aa19282af5
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-banners.patch
@@ -0,0 +1,12 @@
+diff -up cups-1.5b1/scheduler/banners.c.banners cups-1.5b1/scheduler/banners.c
+--- cups-1.5b1/scheduler/banners.c.banners	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/scheduler/banners.c	2011-05-23 17:35:30.000000000 +0200
+@@ -110,6 +110,8 @@ cupsdLoadBanners(const char *d)		/* I - 
+     if ((ext = strrchr(dent->filename, '.')) != NULL)
+       if (!strcmp(ext, ".bck") ||
+           !strcmp(ext, ".bak") ||
++          !strcmp(ext, ".rpmnew") ||
++          !strcmp(ext, ".rpmsave") ||
+ 	  !strcmp(ext, ".sav"))
+ 	continue;
+ 
diff --git a/srcpkgs/cups/patches/cups-build.patch b/srcpkgs/cups/patches/cups-build.patch
new file mode 100644
index 0000000000..c229a76637
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-build.patch
@@ -0,0 +1,42 @@
+diff -up cups-1.5b1/Makedefs.in.build cups-1.5b1/Makedefs.in
+--- cups-1.5b1/Makedefs.in.build	2011-05-04 06:28:00.000000000 +0200
++++ cups-1.5b1/Makedefs.in	2011-05-24 15:54:03.000000000 +0200
+@@ -138,7 +138,7 @@ BACKLIBS	=	@BACKLIBS@
+ BANNERTOPS	=	@BANNERTOPS@
+ BUILDDIRS	=	@BUILDDIRS@
+ CFLAGS		=	@CPPFLAGS@ @CFLAGS@
+-COMMONLIBS	=	@LIBS@
++COMMONLIBS	=	@LIBS@ $(DNSSDLIBS)
+ CXXFLAGS	=	@CPPFLAGS@ @CXXFLAGS@
+ CXXLIBS		=	@CXXLIBS@
+ DBUS_NOTIFIER	=	@DBUS_NOTIFIER@
+diff -up cups-1.5b1/scheduler/dirsvc.c.build cups-1.5b1/scheduler/dirsvc.c
+--- cups-1.5b1/scheduler/dirsvc.c.build	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/scheduler/dirsvc.c	2011-05-24 15:55:26.000000000 +0200
+@@ -2047,7 +2047,7 @@ cupsdUpdateDNSSDName(void)
+ 
+     WebIFRef = DNSSDRef;
+     if ((error = DNSServiceRegister(&WebIFRef,
+-				    kDNSServiceFlagsShareConnection,
++				    0,
+ 				    0, webif, "_http._tcp", NULL,
+ 				    NULL, htons(DNSSDPort), 7,
+ 				    "\006path=/", dnssdRegisterCallback,
+@@ -2769,7 +2769,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)
+     do
+     {
+       p->ipp_ref = DNSSDRef;
+-      if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
++      if ((se = DNSServiceRegister(&p->ipp_ref, 0,
+                                    0, name, regtype, NULL, NULL,
+ 				   htons(DNSSDPort), ipp_len, ipp_txt,
+ 				   dnssdRegisterCallback,
+@@ -2866,7 +2866,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)
+ 
+     p->printer_ref = DNSSDRef;
+     if ((se = DNSServiceRegister(&p->printer_ref,
+-				 kDNSServiceFlagsShareConnection,
++				 0,
+ 				 0, name, "_printer._tcp", NULL, NULL,
+ 				 htons(printer_port), printer_len, printer_txt,
+ 				 dnssdRegisterCallback,
diff --git a/srcpkgs/cups/patches/cups-cups-get-classes.patch b/srcpkgs/cups/patches/cups-cups-get-classes.patch
new file mode 100644
index 0000000000..c998852b28
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-cups-get-classes.patch
@@ -0,0 +1,89 @@
+diff -up cups-1.5.0/cups/dest.c.cups-get-classes cups-1.5.0/cups/dest.c
+--- cups-1.5.0/cups/dest.c.cups-get-classes	2011-05-20 04:49:49.000000000 +0100
++++ cups-1.5.0/cups/dest.c	2011-09-14 12:10:05.111635428 +0100
+@@ -534,6 +534,7 @@ _cupsGetDests(http_t      *http,	/* I - 
+   char		uri[1024];		/* printer-uri value */
+   int		num_options;		/* Number of options */
+   cups_option_t	*options;		/* Options */
++  int		get_classes;		/* Whether we need to fetch class */
+ #ifdef __APPLE__
+   char		media_default[41];	/* Default paper size */
+ #endif /* __APPLE__ */
+@@ -590,6 +591,8 @@ _cupsGetDests(http_t      *http,	/* I - 
+   *    printer-uri [for IPP_GET_PRINTER_ATTRIBUTES]
+   */
+ 
++  get_classes = (op == CUPS_GET_PRINTERS);
++
+   request = ippNewRequest(op);
+ 
+   ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+@@ -647,6 +650,23 @@ _cupsGetDests(http_t      *http,	/* I - 
+ 	    attr->value_tag != IPP_TAG_URI)
+           continue;
+ 
++	if (get_classes &&
++
++	    /* Is this a class? */
++	    ((attr->value_tag == IPP_TAG_ENUM &&
++	      !strcmp(attr->name, "printer-type") &&
++	      (attr->values[0].integer & CUPS_PRINTER_CLASS)) ||
++
++	     /* Or, is this an attribute from CUPS 1.2 or later? */
++	     !strcmp(attr->name, "auth-info-required") ||
++	     !strncmp(attr->name, "marker-", 7) ||
++	     !strcmp(attr->name, "printer-commands") ||
++	     !strcmp(attr->name, "printer-is-shared")))
++	 /* We are talking to a recent enough CUPS server that
++	  * CUPS_GET_PRINTERS returns classes as well.
++	  */
++	  get_classes = 0;
++
+         if (!strcmp(attr->name, "auth-info-required") ||
+ 	    !strcmp(attr->name, "device-uri") ||
+ 	    !strcmp(attr->name, "marker-change-time") ||
+@@ -738,6 +758,28 @@ _cupsGetDests(http_t      *http,	/* I - 
+           continue;
+       }
+ 
++     /*
++      * If we sent a CUPS_GET_CLASSES request, check whether
++      * CUPS_GET_PRINTERS already gave us this destination and exit
++      * early if so.
++      */
++
++      if (op == CUPS_GET_CLASSES && num_dests > 0)
++      {
++	int diff;
++	cups_find_dest (printer_name, NULL, num_dests, *dests, 0, &diff);
++	if (diff == 0)
++	{
++         /*
++	  * Found it.  The CUPS server already gave us the classes in
++	  * its CUPS_GET_PRINTERS response.
++	  */
++
++	  cupsFreeOptions(num_options, options);
++	  break;
++	}
++      }
++
+       if ((dest = cups_add_dest(printer_name, NULL, &num_dests, dests)) != NULL)
+       {
+         dest->num_options = num_options;
+@@ -754,6 +796,15 @@ _cupsGetDests(http_t      *http,	/* I - 
+   }
+ 
+  /*
++  * If this is a CUPS_GET_PRINTERS request but we didn't see any
++  * classes we might be talking to an older CUPS server that requires
++  * CUPS_GET_CLASSES as well.
++  */
++
++  if (get_classes)
++    num_dests = _cupsGetDests (http, CUPS_GET_CLASSES, name, dests);
++
++ /*
+   * Return the count...
+   */
+ 
diff --git a/srcpkgs/cups/patches/cups-direct-usb.patch b/srcpkgs/cups/patches/cups-direct-usb.patch
new file mode 100644
index 0000000000..4e25ce7db4
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-direct-usb.patch
@@ -0,0 +1,27 @@
+diff -up cups-1.5b1/backend/usb-unix.c.direct-usb cups-1.5b1/backend/usb-unix.c
+--- cups-1.5b1/backend/usb-unix.c.direct-usb	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/backend/usb-unix.c	2011-05-23 17:52:14.000000000 +0200
+@@ -102,6 +102,9 @@ print_device(const char *uri,		/* I - De
+              _cups_strncasecmp(hostname, "Minolta", 7);
+ #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */
+ 
++    if (use_bc && !strncmp(uri, "usb:/dev/", 9))
++      use_bc = 0;
++
+     if ((device_fd = open_device(uri, &use_bc)) == -1)
+     {
+       if (getenv("CLASS") != NULL)
+@@ -331,12 +334,7 @@ open_device(const char *uri,		/* I - Dev
+   if (!strncmp(uri, "usb:/dev/", 9))
+ #ifdef __linux
+   {
+-   /*
+-    * Do not allow direct devices anymore...
+-    */
+-
+-    errno = ENODEV;
+-    return (-1);
++    return (open(uri + 4, O_RDWR | O_EXCL));
+   }
+   else if (!strncmp(uri, "usb://", 6))
+   {
diff --git a/srcpkgs/cups/patches/cups-dnssd-deviceid.patch b/srcpkgs/cups/patches/cups-dnssd-deviceid.patch
new file mode 100644
index 0000000000..dedbcb2838
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-dnssd-deviceid.patch
@@ -0,0 +1,38 @@
+diff -up cups-1.5b1/backend/dnssd.c.dnssd-deviceid cups-1.5b1/backend/dnssd.c
+--- cups-1.5b1/backend/dnssd.c.dnssd-deviceid	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/backend/dnssd.c	2011-05-24 17:28:18.000000000 +0200
+@@ -817,15 +817,22 @@ query_callback(
+       if (device->device_id)
+         free(device->device_id);
+ 
++      if (device_id[0])
++      {
++	  /* Mark this as the real device ID. */
++	  ptr = device_id + strlen(device_id);
++	  snprintf(ptr, sizeof(device_id) - (ptr - device_id), "FZY:0;");
++      }
++
+       if (!device_id[0] && strcmp(model, "Unknown"))
+       {
+         if (make_and_model[0])
+-	  snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;",
++	  snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;FZY:1;",
+ 	           make_and_model, model);
+         else if (!_cups_strncasecmp(model, "designjet ", 10))
+-	  snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s", model + 10);
++	  snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;FZY:1;", model + 10);
+         else if (!_cups_strncasecmp(model, "stylus ", 7))
+-	  snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s", model + 7);
++	  snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;FZY:1;", model + 7);
+         else if ((ptr = strchr(model, ' ')) != NULL)
+ 	{
+ 	 /*
+@@ -835,7 +842,7 @@ query_callback(
+           memcpy(make_and_model, model, ptr - model);
+ 	  make_and_model[ptr - model] = '\0';
+ 
+-	  snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s",
++	  snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;FZY:1;",
+ 		   make_and_model, ptr + 1);
+         }
+       }
diff --git a/srcpkgs/cups/patches/cups-driverd-timeout.patch b/srcpkgs/cups/patches/cups-driverd-timeout.patch
new file mode 100644
index 0000000000..cb9e5cf726
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-driverd-timeout.patch
@@ -0,0 +1,21 @@
+diff -up cups-1.5.0/scheduler/ipp.c.driverd-timeout cups-1.5.0/scheduler/ipp.c
+--- cups-1.5.0/scheduler/ipp.c.driverd-timeout	2011-10-10 17:03:41.801690962 +0100
++++ cups-1.5.0/scheduler/ipp.c	2011-10-10 17:03:41.861689834 +0100
+@@ -5723,7 +5723,7 @@ copy_model(cupsd_client_t *con,		/* I -
+   close(temppipe[1]);
+ 
+  /*
+-  * Wait up to 30 seconds for the PPD file to be copied...
++  * Wait up to 70 seconds for the PPD file to be copied...
+   */
+ 
+   total = 0;
+@@ -5743,7 +5743,7 @@ copy_model(cupsd_client_t *con,		/* I -
+     FD_SET(temppipe[0], &input);
+     FD_SET(CGIPipes[0], &input);
+ 
+-    timeout.tv_sec  = 30;
++    timeout.tv_sec  = 70;
+     timeout.tv_usec = 0;
+ 
+     if ((i = select(maxfd, &input, NULL, NULL, &timeout)) < 0)
diff --git a/srcpkgs/cups/patches/cups-eggcups.patch b/srcpkgs/cups/patches/cups-eggcups.patch
new file mode 100644
index 0000000000..981d920172
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-eggcups.patch
@@ -0,0 +1,130 @@
+diff -up cups-1.5.3/backend/ipp.c.eggcups cups-1.5.3/backend/ipp.c
+--- cups-1.5.3/backend/ipp.c.eggcups	2012-05-05 01:00:01.000000000 +0200
++++ cups-1.5.3/backend/ipp.c	2012-05-15 16:50:41.142868986 +0200
+@@ -138,6 +138,70 @@ static cups_array_t	*state_reasons;	/* A
+ static char		tmpfilename[1024] = "";
+ 					/* Temporary spool file name */
+ 
++#if HAVE_DBUS
++#include <dbus/dbus.h>
++
++static DBusConnection *dbus_connection = NULL;
++
++static int
++init_dbus (void)
++{
++  DBusConnection *connection;
++  DBusError error;
++
++  if (dbus_connection &&
++      !dbus_connection_get_is_connected (dbus_connection)) {
++    dbus_connection_unref (dbus_connection);
++    dbus_connection = NULL;
++  }
++  
++  dbus_error_init (&error);
++  connection = dbus_bus_get (getuid () ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &error);
++  if (connection == NULL) {
++    dbus_error_free (&error);
++    return -1;
++  }
++
++  dbus_connection = connection;
++  return 0;
++}
++
++int
++dbus_broadcast_queued_remote (const char *printer_uri,
++			      ipp_status_t status,
++			      unsigned int local_job_id,
++			      unsigned int remote_job_id,
++			      const char *username,
++			      const char *printer_name)
++{
++  DBusMessage *message;
++  DBusMessageIter iter;
++  const char *errstr;
++
++  if (!dbus_connection || !dbus_connection_get_is_connected (dbus_connection)) {
++    if (init_dbus () || !dbus_connection)
++      return -1;
++  }
++
++  errstr = ippErrorString (status);
++  message = dbus_message_new_signal ("/com/redhat/PrinterSpooler",
++				     "com.redhat.PrinterSpooler",
++				     "JobQueuedRemote");
++  dbus_message_iter_init_append (message, &iter);
++  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &printer_uri);
++  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &errstr);
++  dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &local_job_id);
++  dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &remote_job_id);
++  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &username);
++  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &printer_name);
++
++  dbus_connection_send (dbus_connection, message, NULL);
++  dbus_connection_flush (dbus_connection);
++  dbus_message_unref (message);
++  
++  return 0;
++}
++#endif /* HAVE_DBUS */
+ 
+ /*
+  * Local functions...
+@@ -1520,6 +1584,15 @@ main(int  argc,				/* I - Number of comm
+                            _("Print file accepted - job ID %d."), job_id);
+     }
+ 
++#if HAVE_DBUS
++    dbus_broadcast_queued_remote (argv[0],
++				  ipp_status,
++				  atoi (argv[1]),
++				  job_id,
++				  argv[2],
++				  getenv ("PRINTER"));
++#endif /* HAVE_DBUS */
++
+     fprintf(stderr, "DEBUG: job-id=%d\n", job_id);
+     ippDelete(response);
+ 
+diff -up cups-1.5.3/backend/Makefile.eggcups cups-1.5.3/backend/Makefile
+--- cups-1.5.3/backend/Makefile.eggcups	2012-04-23 19:42:12.000000000 +0200
++++ cups-1.5.3/backend/Makefile	2012-05-15 16:48:17.253871982 +0200
+@@ -212,7 +212,7 @@ dnssd:	dnssd.o ../cups/$(LIBCUPS) libbac
+ 
+ ipp:	ipp.o ../cups/$(LIBCUPS) libbackend.a
+ 	echo Linking $@...
+-	$(CC) $(LDFLAGS) -o ipp ipp.o libbackend.a $(LIBS)
++	$(CC) $(LDFLAGS) -o ipp ipp.o libbackend.a $(LIBS) $(SERVERLIBS)
+ 	$(RM) http
+ 	$(LN) ipp http
+ 
+diff -up cups-1.5.3/scheduler/subscriptions.c.eggcups cups-1.5.3/scheduler/subscriptions.c
+--- cups-1.5.3/scheduler/subscriptions.c.eggcups	2012-02-12 06:48:09.000000000 +0100
++++ cups-1.5.3/scheduler/subscriptions.c	2012-05-15 16:48:17.253871982 +0200
+@@ -1314,13 +1314,13 @@ cupsd_send_dbus(cupsd_eventmask_t event,
+     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_value == IPP_JOB_PROCESSING)
+     what = "JobStartedLocal";
++  else if (event & (CUPSD_EVENT_PRINTER_CHANGED|CUPSD_EVENT_JOB_STATE_CHANGED|CUPSD_EVENT_PRINTER_STATE_CHANGED))
++    what = "QueueChanged";
+   else
+     return;
+ 
+@@ -1356,7 +1356,7 @@ cupsd_send_dbus(cupsd_eventmask_t event,
+   dbus_message_append_iter_init(message, &iter);
+   if (dest)
+     dbus_message_iter_append_string(&iter, dest->name);
+-  if (job)
++  if (job && strcmp (what, "QueueChanged") != 0)
+   {
+     dbus_message_iter_append_uint32(&iter, job->id);
+     dbus_message_iter_append_string(&iter, job->username);
diff --git a/srcpkgs/cups/patches/cups-filter-debug.patch b/srcpkgs/cups/patches/cups-filter-debug.patch
new file mode 100644
index 0000000000..2a42343677
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-filter-debug.patch
@@ -0,0 +1,32 @@
+diff -up cups-1.5b1/scheduler/job.c.filter-debug cups-1.5b1/scheduler/job.c
+--- cups-1.5b1/scheduler/job.c.filter-debug	2011-05-24 15:58:07.000000000 +0200
++++ cups-1.5b1/scheduler/job.c	2011-05-24 15:58:07.000000000 +0200
+@@ -557,10 +557,28 @@ cupsdContinueJob(cupsd_job_t *job)	/* I 
+ 
+     if (!filters)
+     {
++      mime_filter_t *current;
++
+       cupsdLogJob(job, CUPSD_LOG_ERROR,
+ 		  "Unable to convert file %d to printable format!",
+ 		  job->current_file);
+ 
++      cupsdLogJob(job, CUPSD_LOG_ERROR,
++		  "Required: %s/%s -> %s/%s",
++		  job->filetypes[job->current_file]->super,
++		  job->filetypes[job->current_file]->type,
++		  job->printer->filetype->super,
++		  job->printer->filetype->type);
++
++      for (current = (mime_filter_t *)cupsArrayFirst(MimeDatabase->srcs);
++	   current;
++	   current = (mime_filter_t *)cupsArrayNext(MimeDatabase->srcs))
++	  cupsdLogJob(job, CUPSD_LOG_ERROR,
++		      "Available: %s/%s -> %s/%s (%s)",
++		      current->src->super, current->src->type,
++		      current->dst->super, current->dst->type,
++		      current->filter);
++
+       abort_message = "Aborting job because it cannot be printed.";
+       abort_state   = IPP_JOB_ABORTED;
+ 
diff --git a/srcpkgs/cups/patches/cups-getpass.patch b/srcpkgs/cups/patches/cups-getpass.patch
new file mode 100644
index 0000000000..7b089a7239
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-getpass.patch
@@ -0,0 +1,50 @@
+diff -up cups-1.5b1/cups/usersys.c.getpass cups-1.5b1/cups/usersys.c
+--- cups-1.5b1/cups/usersys.c.getpass	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/cups/usersys.c	2011-05-24 15:41:33.000000000 +0200
+@@ -43,6 +43,8 @@
+ #include "cups-private.h"
+ #include <stdlib.h>
+ #include <sys/stat.h>
++#include <termios.h>
++#include <signal.h>
+ #ifdef WIN32
+ #  include <windows.h>
+ #else
+@@ -501,13 +503,31 @@ _cupsGetPassword(const char *prompt)	/* 
+   * empty password is treated as canceling the authentication request.
+   */
+ 
+-  const char	*password = getpass(prompt);
+-					/* Password string */
+-
+-  if (!password || !password[0])
+-    return (NULL);
+-  else
++  static char password[100];
++  struct termios oldtio, newtio;
++  sigset_t oldset, newset;
++  int nread;
++  sigprocmask (SIG_BLOCK, NULL, &newset);
++  sigaddset (&newset, SIGINT);
++  sigaddset (&newset, SIGTSTP);
++  sigprocmask (SIG_BLOCK, &newset, &oldset);
++  tcgetattr (STDIN_FILENO, &oldtio);
++  newtio = oldtio;
++  newtio.c_lflag &= ~ECHO;
++  tcsetattr (STDIN_FILENO, TCSAFLUSH, &newtio);
++  fputs (prompt, stdout);
++  fflush (stdout);
++  nread = read (STDIN_FILENO, password, sizeof (password));
++  tcsetattr (STDIN_FILENO, TCSAFLUSH, &oldtio);
++  fputc ('\n', stdout);
++  sigprocmask (SIG_SETMASK, &oldset, NULL);
++  if (nread > 0)
++  {
++    password[nread - 1] = '\0';
+     return (password);
++  }
++  else
++    return (NULL);
+ #endif /* WIN32 */
+ }
+ 
diff --git a/srcpkgs/cups/patches/cups-hp-deviceid-oid.patch b/srcpkgs/cups/patches/cups-hp-deviceid-oid.patch
new file mode 100644
index 0000000000..da5136a812
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-hp-deviceid-oid.patch
@@ -0,0 +1,21 @@
+diff -up cups-1.5b1/backend/snmp.c.hp-deviceid-oid cups-1.5b1/backend/snmp.c
+--- cups-1.5b1/backend/snmp.c.hp-deviceid-oid	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/backend/snmp.c	2011-05-24 17:24:48.000000000 +0200
+@@ -187,6 +187,7 @@ static const int	UriOID[] = { CUPS_OID_p
+ static const int	LexmarkProductOID[] = { 1,3,6,1,4,1,641,2,1,2,1,2,1,-1 };
+ static const int	LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 };
+ static const int	LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 };
++static const int	HPDeviceIdOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 };
+ static const int	XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 };
+ static cups_array_t	*DeviceURIs = NULL;
+ static int		HostNameLookups = 0;
+@@ -1006,6 +1007,9 @@ read_snmp_response(int fd)		/* I - SNMP 
+ 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ 	               packet.community, CUPS_ASN1_GET_REQUEST,
+ 		       DEVICE_PRODUCT, XeroxProductOID);
++	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
++		       packet.community, CUPS_ASN1_GET_REQUEST,
++		       DEVICE_ID, HPDeviceIdOID);
+         break;
+ 
+     case DEVICE_DESCRIPTION :
diff --git a/srcpkgs/cups/patches/cups-icc.patch b/srcpkgs/cups/patches/cups-icc.patch
new file mode 100644
index 0000000000..db4ae225a9
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-icc.patch
@@ -0,0 +1,1042 @@
+From db29c24e3ff75938775aa1f4072e346aeb7f6a9c Mon Sep 17 00:00:00 2001
+From: Richard Hughes <richard@hughsie.com>
+Date: Tue, 1 Mar 2011 16:05:48 +0000
+Subject: [PATCH] Add colord support to CUPS which allows Linux printers to be
+ color managed
+
+This functionality is possible because of lots of help from Tim Waugh -- thanks!
+---
+ scheduler/Makefile   |    1 +
+ scheduler/colord.c   |  784 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ scheduler/colord.h   |   41 +++
+ scheduler/ipp.c      |   18 +-
+ scheduler/printers.c |   69 +++++
+ scheduler/printers.h |    4 +
+ 6 files changed, 914 insertions(+), 3 deletions(-)
+ create mode 100644 scheduler/colord.c
+ create mode 100644 scheduler/colord.h
+
+diff --git a/scheduler/Makefile b/scheduler/Makefile
+index 3c7da8e..b9c47d3 100644
+--- a/scheduler/Makefile
++++ b/scheduler/Makefile
+@@ -27,6 +27,7 @@ CUPSDOBJS =	\
+ 		file.o \
+ 		main.o \
+ 		ipp.o \
++		colord.o \
+ 		listen.o \
+ 		job.o \
+ 		log.o \
+diff --git a/scheduler/colord.c b/scheduler/colord.c
+new file mode 100644
+index 0000000..bd06e1c
+--- /dev/null
++++ b/scheduler/colord.c
+@@ -0,0 +1,784 @@
++/*
++ * "$Id$"
++ *
++ *   colord integration for the CUPS scheduler.
++ *
++ *   Copyright 2011 Red Hat, Inc.
++ *
++ *   Redistribution and use in source and binary forms, with or without
++ *   modification, are permitted provided that the following conditions
++ *   are met:
++ *
++ *   Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ *   Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ *
++ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ *   OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Contents:
++ *
++ *   colordRegisterPrinter()    - Register profiles for a printer.
++ *   colordUnregisterPrinter()  - Unregister profiles for a printer.
++ *   colordStart()              - Get a connection to the system bus.
++ *   colordStop()               - Release any connection to the system bus
++ *                                so that added profiles and devices are
++ *                                automatically removed.
++ */
++
++/*
++ * Include necessary headers...
++ */
++
++#include "cupsd.h"
++
++#ifdef HAVE_DBUS
++
++#include <dbus/dbus.h>
++#include <cups/ppd-private.h>
++
++/*
++ * Defines used by colord. See the reference docs for further details:
++ * http://colord.hughsie.com/api/ref-dbus.html
++ */
++#define COLORD_SCOPE_NORMAL   "normal"    /* System scope */
++#define COLORD_SCOPE_TEMP     "temp"      /* Process scope */
++#define COLORD_SCOPE_DISK     "disk"      /* Lives forever, as stored in DB */
++
++#define COLORD_RELATION_SOFT  "soft"      /* Mapping is not default */
++#define COLORD_RELATION_HARD  "hard"      /* Explicitly mapped profile */
++
++#define COLORD_SPACE_RGB      "rgb"       /* RGB colorspace */
++#define COLORD_SPACE_CMYK     "cmyk"      /* CMYK colorspace */
++#define COLORD_SPACE_GRAY     "gray"      /* Gray colorspace */
++#define COLORD_SPACE_UNKNOWN  "unknown"   /* Unknown colorspace */
++
++#define COLORD_MODE_PHYSICAL  "physical"  /* Actual device */
++#define COLORD_MODE_VIRTUAL   "virtual"   /* Virtual device with no hardware */
++
++#define COLORD_KIND_PRINTER   "printer"   /* printing output device */
++
++/* the timeout for connecting to colord */
++#define COLORD_DBUS_TIMEOUT   5000        /* ms */
++
++/* This is static */
++static DBusConnection *con = NULL;
++
++/*
++ * 'colordStart()' - Get a connection to the system bus.
++ */
++
++void
++colordStart(void)
++{
++  if (con)
++    return;
++  con = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
++}
++
++/*
++ * 'colordStop()' - Release any connection to the system bus so that
++ *                  added profiles and devices are automatically removed.
++ */
++
++void
++colordStop(void)
++{
++  if (con == NULL)
++    return;
++  dbus_connection_unref(con);
++  con = NULL;
++}
++
++/*
++ * 'message_dict_add_strings()' - add two strings to a dictionary.
++ */
++
++static void
++message_dict_add_strings (DBusMessageIter *dict,
++                          const char *key,
++                          const char *value)
++{
++        DBusMessageIter entry;
++        dbus_message_iter_open_container(dict,
++                                         DBUS_TYPE_DICT_ENTRY,
++                                         NULL,
++                                         &entry);
++        dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
++        dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
++        dbus_message_iter_close_container(dict, &entry);
++}
++
++/*
++ * 'colordCreateProfile()' - Create a color profile for a printer.
++ *
++ * Notes: When creating the device, we can create
++ */
++
++static void
++colordCreateProfile (cups_array_t *profiles,    /* I - Profiles array */
++                     const char *printer_name,  /* I - Printer name */
++                     const char *qualifier,     /* I - Profile qualifier */
++                     const char *colorspace,    /* I - Profile colorspace */
++                     const char **format,       /* I - Profile qualifier format */
++                     const char *iccfile,       /* I - ICC filename */
++                     const char *scope)         /* I - The scope of the profile, e.g.
++                                                       'normal', 'temp' or 'disk' */
++{
++  DBusMessage           *message = NULL;        /* D-Bus request */
++  DBusMessage           *reply = NULL;          /* D-Bus reply */
++  DBusMessageIter       args;                   /* D-Bus method arguments */
++  DBusMessageIter       dict;                   /* D-Bus method arguments */
++  DBusError             error;                  /* D-Bus error */
++  char                  *idstr;                 /* Profile ID string */
++  size_t                idstrlen;               /* Profile ID allocated length */
++  const char            *profile_path;          /* Device object path */
++  char                  format_str[1024];       /* Qualifier format as a string */
++
++ /*
++  * Create the profile...
++  */
++
++  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++                                         "/org/freedesktop/ColorManager",
++                                         "org.freedesktop.ColorManager",
++                                         "CreateProfile");
++
++  /* create a profile id */
++  idstrlen = strlen (printer_name) + 1 + strlen (qualifier) + 1;
++  idstr = malloc (idstrlen);
++  if (!idstr)
++      goto out;
++  snprintf (idstr, idstrlen, "%s-%s", printer_name, qualifier);
++  cupsdLogMessage(CUPSD_LOG_DEBUG, "Using profile id of %s",
++                  idstr);
++
++  dbus_message_iter_init_append(message, &args);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &idstr);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);
++
++  /* mush the qualifier format into a simple string */
++  snprintf(format_str, sizeof(format_str), "%s.%s.%s",
++           format[0],
++           format[1],
++           format[2]);
++
++  /* set initial properties */
++  dbus_message_iter_open_container(&args,
++                                   DBUS_TYPE_ARRAY,
++                                   "{ss}",
++                                   &dict);
++  message_dict_add_strings(&dict, "Qualifier", qualifier);
++  message_dict_add_strings(&dict, "Format", format_str);
++  message_dict_add_strings(&dict, "Colorspace", colorspace);
++  if (iccfile != NULL)
++    message_dict_add_strings(&dict, "Filename", iccfile);
++  dbus_message_iter_close_container(&args, &dict);
++
++  /* send syncronous */
++  dbus_error_init(&error);
++  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%s)",
++                  idstr, scope);
++  reply = dbus_connection_send_with_reply_and_block(con,
++                                                    message,
++                                                    COLORD_DBUS_TIMEOUT,
++                                                    &error);
++  if (reply == NULL)
++  {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "failed to CreateProfile: %s:%s",
++                        error.name, error.message);
++        dbus_error_free(&error);
++        goto out;
++  }
++
++  /* get reply data */
++  dbus_message_iter_init(reply, &args);
++  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
++  {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "incorrect reply type");
++        goto out;
++  }
++  dbus_message_iter_get_basic(&args, &profile_path);
++  cupsdLogMessage(CUPSD_LOG_DEBUG,
++                  "created profile %s",
++                  profile_path);
++  cupsArrayAdd(profiles, strdup(profile_path));
++
++out:
++  if (message != NULL)
++    dbus_message_unref(message);
++  if (reply != NULL)
++    dbus_message_unref(reply);
++  free (idstr);
++}
++
++/*
++ * 'colordDeviceAddProfile()' - Assign a profile to a device.
++ */
++
++static void
++colordDeviceAddProfile (const char *device_path,       /* I - Device object path */
++                        const char *profile_path,      /* I - Profile object path */
++                        const char *relation)          /* I - Device relation, either 'soft' or 'hard' */
++{
++  DBusMessage           *message = NULL;        /* D-Bus request */
++  DBusMessage           *reply = NULL;          /* D-Bus reply */
++  DBusMessageIter       args;                   /* D-Bus method arguments */
++  DBusError             error;                  /* D-Bus error */
++
++  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++                                         device_path,
++                                         "org.freedesktop.ColorManager.Device",
++                                         "AddProfile");
++
++  /* send profile path as the argument */
++  dbus_message_iter_init_append(message, &args);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &relation);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &profile_path);
++  cupsdLogMessage(CUPSD_LOG_DEBUG,
++                  "Calling %s:AddProfile(%s) [%s]",
++                  device_path, profile_path, relation);
++
++  /* send syncronous */
++  dbus_error_init(&error);
++  reply = dbus_connection_send_with_reply_and_block(con,
++                                                    message,
++                                                    COLORD_DBUS_TIMEOUT,
++                                                    &error);
++  if (reply == NULL)
++  {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "failed to AddProfile: %s:%s",
++                        error.name, error.message);
++        dbus_error_free(&error);
++        goto out;
++  }
++out:
++  if (message != NULL)
++    dbus_message_unref(message);
++  if (reply != NULL)
++    dbus_message_unref(reply);
++}
++
++/*
++ * 'colordCreateDevice()' - Create a device and register profiles.
++ */
++
++static void
++colordCreateDevice (cupsd_printer_t *p,         /* I - Printer */
++                    ppd_file_t *ppd,            /* I - PPD file */
++                    cups_array_t *profiles,     /* I - Profiles array */
++                    const char *colorspace,     /* I - Device colorspace, e.g. 'rgb' */
++                    char **format,              /* I - Device qualifier format */
++                    const char *relation,       /* I - Profile relation, either 'soft' or 'hard' */
++                    const char *scope)          /* I - The scope of the device, e.g.
++                                                       'normal', 'temp' or 'disk' */
++{
++  DBusMessage           *message = NULL;        /* D-Bus request */
++  DBusMessage           *reply = NULL;          /* D-Bus reply */
++  DBusMessageIter       args;                   /* D-Bus method arguments */
++  DBusMessageIter       dict;                   /* D-Bus method arguments */
++  DBusError             error;                  /* D-Bus error */
++  const char            *device_path;           /* Device object path */
++  const char            *profile_path;          /* Profile path */
++  char                  *default_profile_path = NULL;
++                                                /* Default profile path */
++  char                  device_id[1024];        /* Device ID as understood by colord */
++  char                  format_str[1024];       /* Qualifier format as a string */
++
++ /*
++  * Create the device...
++  */
++
++  snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
++  device_path = device_id;
++
++  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++                                         "/org/freedesktop/ColorManager",
++                                         "org.freedesktop.ColorManager",
++                                         "CreateDevice");
++
++  dbus_message_iter_init_append(message, &args);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_path);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);
++
++  /* mush the qualifier format into a simple string */
++  snprintf(format_str, sizeof(format_str), "%s.%s.%s",
++           format[0],
++           format[1],
++           format[2]);
++
++  /* set initial properties */
++  dbus_message_iter_open_container(&args,
++                                 DBUS_TYPE_ARRAY,
++                                 "{ss}",
++                                 &dict);
++  message_dict_add_strings(&dict, "Colorspace", colorspace);
++  message_dict_add_strings(&dict, "Mode", COLORD_MODE_PHYSICAL);
++  if (ppd->manufacturer != NULL)
++    message_dict_add_strings(&dict, "Vendor", ppd->manufacturer);
++  if (ppd->modelname != NULL)
++    message_dict_add_strings(&dict, "Model", ppd->modelname);
++  if (p->sanitized_device_uri != NULL)
++    message_dict_add_strings(&dict, "Serial", p->sanitized_device_uri);
++  message_dict_add_strings(&dict, "Format", format_str);
++  message_dict_add_strings(&dict, "Kind", COLORD_KIND_PRINTER);
++  dbus_message_iter_close_container(&args, &dict);
++
++  /* send syncronous */
++  dbus_error_init(&error);
++  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateDevice(%s,%s)",
++                  device_id, scope);
++  reply = dbus_connection_send_with_reply_and_block(con,
++                                                    message,
++                                                    COLORD_DBUS_TIMEOUT,
++                                                    &error);
++  if (reply == NULL)
++  {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "failed to CreateDevice: %s:%s",
++                        error.name, error.message);
++        dbus_error_free(&error);
++        goto out;
++  }
++
++  /* get reply data */
++  dbus_message_iter_init(reply, &args);
++  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
++  {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "incorrect reply type");
++        goto out;
++  }
++  dbus_message_iter_get_basic(&args, &device_path);
++  cupsdLogMessage(CUPSD_LOG_DEBUG,
++                  "created device %s",
++                  device_path);
++
++  /* add profiles */
++  for (profile_path = cupsArrayFirst(profiles);
++       profile_path;
++       profile_path = cupsArrayNext(profiles))
++  {
++    colordDeviceAddProfile (device_path, profile_path, relation);
++  }
++
++out:
++  free(default_profile_path);
++  if (message != NULL)
++    dbus_message_unref(message);
++  if (reply != NULL)
++    dbus_message_unref(reply);
++}
++
++/*
++ * 'colordFindDeviceById()' - Finds a device
++ */
++
++static char *
++colordFindDeviceById (const char *device_id)      /* I - Device ID string */
++{
++  DBusMessage           *message = NULL;        /* D-Bus request */
++  DBusMessage           *reply = NULL;          /* D-Bus reply */
++  DBusMessageIter       args;                   /* D-Bus method arguments */
++  DBusError             error;                  /* D-Bus error */
++  const char           *device_path_tmp;        /* Device object path */
++  char                 *device_path = NULL;     /* Device object path */
++
++  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++                                         "/org/freedesktop/ColorManager",
++                                         "org.freedesktop.ColorManager",
++                                         "FindDeviceById");
++
++  dbus_message_iter_init_append(message, &args);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_id);
++
++  /* send syncronous */
++  dbus_error_init(&error);
++  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling FindDeviceById(%s)", device_id);
++  reply = dbus_connection_send_with_reply_and_block(con,
++                                                    message,
++                                                    COLORD_DBUS_TIMEOUT,
++                                                    &error);
++  if (reply == NULL)
++  {
++        /* this can happen normally on start-up */
++        cupsdLogMessage(CUPSD_LOG_DEBUG,
++                        "failed to DeleteDevice: %s:%s",
++                        error.name, error.message);
++        dbus_error_free(&error);
++        goto out;
++  }
++
++  /* get reply data */
++  dbus_message_iter_init(reply, &args);
++  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
++  {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "incorrect reply type");
++        goto out;
++  }
++  dbus_message_iter_get_basic(&args, &device_path_tmp);
++  if (device_path_tmp != NULL)
++    device_path = strdup (device_path_tmp);
++out:
++  if (message != NULL)
++    dbus_message_unref(message);
++  if (reply != NULL)
++    dbus_message_unref(reply);
++  return device_path;
++}
++
++/*
++ * 'colordDeleteDevice()' - Delete a device
++ */
++
++static void
++colordDeleteDevice (const char *device_id)      /* I - Device ID string */
++{
++  DBusMessage           *message = NULL;        /* D-Bus request */
++  DBusMessage           *reply = NULL;          /* D-Bus reply */
++  DBusMessageIter       args;                   /* D-Bus method arguments */
++  DBusError             error;                  /* D-Bus error */
++  char                 *device_path;            /* Device object path */
++
++ /*
++  * Find the device...
++  */
++
++  device_path = colordFindDeviceById (device_id);
++  if (device_path == NULL)
++  {
++        /* this can happen normally on start-up */
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "failed to find device: %s",
++                        device_id);
++        goto out;
++  }
++
++ /*
++  * Delete the device...
++  */
++
++  message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++                                         "/org/freedesktop/ColorManager",
++                                         "org.freedesktop.ColorManager",
++                                         "DeleteDevice");
++
++  dbus_message_iter_init_append(message, &args);
++  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_id);
++
++  /* send syncronous */
++  dbus_error_init(&error);
++  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling DeleteDevice(%s)", device_id);
++  reply = dbus_connection_send_with_reply_and_block(con,
++                                                    message,
++                                                    COLORD_DBUS_TIMEOUT,
++                                                    &error);
++  if (reply == NULL)
++  {
++        /* this can happen normally on start-up */
++        cupsdLogMessage(CUPSD_LOG_DEBUG,
++                        "failed to DeleteDevice: %s:%s",
++                        error.name, error.message);
++        dbus_error_free(&error);
++        goto out;
++  }
++out:
++  free (device_path);
++  if (message != NULL)
++    dbus_message_unref(message);
++  if (reply != NULL)
++    dbus_message_unref(reply);
++}
++
++/*
++ * 'colordGetQualifierFormat()' - Get the qualifier format.
++ *
++ * Notes: Returns a value of "ColorSpace.MediaType.Resolution" by default
++ */
++
++char **
++colordGetQualifierFormat(ppd_file_t *ppd)
++{
++  char                  **format;       /* Qualifier format tuple */
++  const char            *tmp;           /* Temporary string */
++  ppd_attr_t            *attr;          /* Profile attributes */
++
++  /* create 3-tuple */
++  format = calloc(3, sizeof(char*));
++
++  /* get 1st section */
++  tmp = "cupsICCQualifier1";
++  attr = ppdFindAttr(ppd, tmp, NULL);
++  if (attr != NULL)
++    tmp = attr->value;
++  else
++  {
++    tmp = "DefaultColorSpace";
++    attr = ppdFindAttr(ppd, tmp, NULL);
++  }
++  if (attr == NULL)
++  {
++    tmp = "DefaultColorModel";
++    attr = ppdFindAttr(ppd, tmp, NULL);
++  }
++  if (attr == NULL)
++  {
++    tmp = "";
++  }
++  if (strncmp(tmp, "Default", 7) == 0)
++    tmp += 7;
++  format[0] = strdup(tmp);
++
++  /* get 2nd section */
++  tmp = "cupsICCQualifier2";
++  attr = ppdFindAttr(ppd, tmp, NULL);
++  if (attr != NULL)
++    tmp = attr->value;
++  else
++  {
++    tmp = "DefaultMediaType";
++    attr = ppdFindAttr(ppd, tmp, NULL);
++  }
++  if (attr == NULL)
++  {
++    tmp = "";
++  }
++  if (strncmp(tmp, "Default", 7) == 0)
++    tmp += 7;
++  format[1] = strdup(tmp);
++
++  /* get 3rd section */
++  tmp = "cupsICCQualifier3";
++  attr = ppdFindAttr(ppd, tmp, NULL);
++  if (attr != NULL)
++    tmp = attr->value;
++  else
++  {
++    tmp = "DefaultResolution";
++    attr = ppdFindAttr(ppd, tmp, NULL);
++  }
++  if (attr == NULL)
++  {
++    tmp = "";
++  }
++  if (strncmp(tmp, "Default", 7) == 0)
++    tmp += 7;
++  format[2] = strdup(tmp);
++
++  return format;
++}
++
++/*
++ * 'colordRegisterPrinter()' - Register profiles for a printer.
++ */
++
++void
++colordRegisterPrinter(cupsd_printer_t *p)    /* I - printer */
++{
++  char                  ppdfile[1024],  /* PPD filename */
++                        iccfile[1024];  /* ICC filename */
++  ppd_file_t            *ppd;           /* PPD file */
++  cups_array_t          *profiles;      /* Profile paths array */
++  const char            *profile_key;   /* Profile keyword */
++  ppd_attr_t            *attr;          /* Profile attributes */
++  const char            *device_colorspace;   /* Device colorspace */
++  char                  **format;       /* Qualifier format tuple */
++  int                   i;              /* Loop counter */
++
++ /*
++  * Do nothing for discovered printers as they will have local color
++  * correction
++  */
++
++  if (p->type & CUPS_PRINTER_DISCOVERED)
++    return;
++
++ /*
++  * Ensure we have a DBus connection
++  */
++
++  colordStart();
++  if (con == NULL)
++    return;
++
++ /*
++  * Try opening the PPD file for this printer...
++  */
++
++  snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
++  if ((ppd = ppdOpenFile(ppdfile)) == NULL)
++  {
++    cupsdLogMessage(CUPSD_LOG_DEBUG,
++                    "cannot open %s",
++                    ppdfile);
++    return;
++  }
++
++ /*
++  * Find out the qualifier format
++  */
++
++  format = colordGetQualifierFormat(ppd);
++
++ /*
++  * See if we have any embedded profiles...
++  */
++
++  profiles = cupsArrayNew3 (NULL, NULL, NULL, 0, NULL,
++                            (cups_afree_func_t) free);
++  profile_key = "cupsICCProfile";
++  attr = ppdFindAttr(ppd, profile_key, NULL);
++  for (; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL))
++    if (attr->spec[0] && attr->value && attr->value[0])
++    {
++      if (attr->value[0] != '/')
++        snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
++                 attr->value);
++      else
++        strlcpy(iccfile, attr->value, sizeof(iccfile));
++
++      if (access(iccfile, 0))
++      {
++        cupsdLogMessage(CUPSD_LOG_WARN,
++                        "no access to %s",
++                        iccfile);
++        continue;
++      }
++
++      colordCreateProfile(profiles,
++                          p->name,
++                          attr->spec,
++                          COLORD_SPACE_UNKNOWN,
++                          (const char **)format,
++                          iccfile,
++                          COLORD_SCOPE_TEMP);
++    }
++
++ /*
++  * Add the grayscale profile first.  We always have a grayscale profile.
++  */
++
++  colordCreateProfile(profiles,
++                      p->name,
++                      "Gray..",
++                      COLORD_SPACE_GRAY,
++                      (const char **)format,
++                      NULL,
++                      COLORD_SCOPE_TEMP);
++
++ /*
++  * Then add the RGB/CMYK/DeviceN color profile...
++  */
++
++  device_colorspace = "unknown";
++  switch (ppd->colorspace)
++  {
++    case PPD_CS_RGB :
++    case PPD_CS_CMY :
++        device_colorspace = COLORD_SPACE_RGB;
++        colordCreateProfile(profiles,
++                            p->name,
++                            "RGB..",
++                            COLORD_SPACE_RGB,
++                            (const char **)format,
++                            NULL,
++                            COLORD_SCOPE_TEMP);
++        break;
++    case PPD_CS_RGBK :
++    case PPD_CS_CMYK :
++        device_colorspace = COLORD_SPACE_CMYK;
++        colordCreateProfile(profiles,
++                            p->name,
++                            "CMYK..",
++                            COLORD_SPACE_CMYK,
++                            (const char **)format,
++                            NULL,
++                            COLORD_SCOPE_TEMP);
++        break;
++    case PPD_CS_GRAY :
++        device_colorspace = COLORD_SPACE_GRAY;
++        break;
++    case PPD_CS_N :
++        colordCreateProfile(profiles,
++                            p->name,
++                            "DeviceN..",
++                            COLORD_SPACE_UNKNOWN,
++                            (const char **)format,
++                            NULL,
++                            COLORD_SCOPE_TEMP);
++        break;
++  }
++
++ /*
++  * Register the device with colord.
++  */
++
++  cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
++                  p->name);
++  colordCreateDevice (p,
++                      ppd,
++                      profiles,
++                      device_colorspace,
++                      format,
++                      COLORD_RELATION_SOFT,
++                      COLORD_SCOPE_TEMP);
++
++ /*
++  * Free any memory we used...
++  */
++
++  cupsArrayDelete(profiles);
++  for (i=0; i<3; i++)
++    free(format[i]);
++  free(format);
++
++  ppdClose(ppd);
++}
++
++/*
++ * 'colordUnregisterPrinter()' - Unregister profiles for a printer.
++ */
++
++void
++colordUnregisterPrinter(cupsd_printer_t *p)  /* I - printer */
++{
++  char                  device_id[1024];        /* Device ID as understood by colord */
++
++ /*
++  * Ensure we have a DBus connection
++  */
++
++  colordStart();
++  if (con == NULL)
++    return;
++
++ /*
++  * Just delete the device itself, and leave the profiles registered
++  */
++
++  snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
++  colordDeleteDevice(device_id);
++}
++
++#endif /* HAVE_DBUS */
++
++/*
++ * End of "$Id$".
++ */
+diff --git a/scheduler/colord.h b/scheduler/colord.h
+new file mode 100644
+index 0000000..75bdd3b
+--- /dev/null
++++ b/scheduler/colord.h
+@@ -0,0 +1,41 @@
++/*
++ * "$Id$"
++ *
++ *   colord integration for the CUPS scheduler.
++ *
++ *   Copyright 2011 Red Hat, Inc.
++ *
++ *   Redistribution and use in source and binary forms, with or without
++ *   modification, are permitted provided that the following conditions
++ *   are met:
++ *
++ *   Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ *   Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ *
++ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ *   OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++void	colordRegisterPrinter(cupsd_printer_t *p);
++void	colordUnregisterPrinter(cupsd_printer_t *p);
++void	colordStart(void);
++void	colordStop(void);
++
++/*
++ * End of "$Id$".
++ */
+diff --git a/scheduler/ipp.c b/scheduler/ipp.c
+index b9903d1..b5af36f 100644
+--- a/scheduler/ipp.c
++++ b/scheduler/ipp.c
+@@ -2921,17 +2921,23 @@ add_printer(cupsd_client_t  *con,	/* I - Client connection */
+ 
+     cupsdSetPrinterReasons(printer, "none");
+ 
+-#ifdef __APPLE__
+    /*
+     * (Re)register color profiles...
+     */
+ 
+     if (!RunUser)
+     {
++      cupsdCmsRegisterPrinter(printer);
++#ifdef __APPLE__
++     /*
++      * FIXME: ideally the ColorSync stuff would be moved to colorsync.c
++      * and the colorsyncRegisterProfiles() would be called from
++      * cupsdCmsRegisterPrinter() in printers.c
++      */
+       apple_unregister_profiles(printer);
+       apple_register_profiles(printer);
+-    }
+ #endif /* __APPLE__ */
++    }
+   }
+ 
+  /*
+@@ -7028,11 +7034,17 @@ delete_printer(cupsd_client_t  *con,	/* I - Client connection */
+   snprintf(filename, sizeof(filename), "%s/%s.data", CacheDir, printer->name);
+   unlink(filename);
+ 
+-#ifdef __APPLE__
+  /*
+   * Unregister color profiles...
+   */
+ 
++  cupsdCmsUnregisterPrinter(printer);
++#ifdef __APPLE__
++ /*
++  * FIXME: ideally the ColorSync stuff would be moved to colorsync.c
++  * and the colorsyncUnregisterPrinter() would be called from
++  * cupsdCmsUnregisterPrinter() in printers.c
++  */
+   apple_unregister_profiles(printer);
+ #endif /* __APPLE__ */
+ 
+diff --git a/scheduler/printers.c b/scheduler/printers.c
+index 6920801..e830499 100644
+--- a/scheduler/printers.c
++++ b/scheduler/printers.c
+@@ -80,6 +80,9 @@
+ #  include <asl.h>
+ #endif /* __APPLE__ */
+ 
++#ifdef HAVE_DBUS
++# include "colord.h"
++#endif /* HAVE_DBUS */
+ 
+ /*
+  * Local functions...
+@@ -712,6 +715,53 @@ cupsdDeleteAllPrinters(void)
+   }
+ }
+ 
++/*
++ * 'cupsdCmsRegisterPrinter()' - Registers a printer and profiles with the CMS
++ */
++
++void
++cupsdCmsRegisterPrinter(cupsd_printer_t *p)
++{
++#if defined(HAVE_DBUS)
++  colordRegisterPrinter(p);
++#endif /* defined(HAVE_DBUS) */
++}
++
++/*
++ * 'cupsdCmsUnregisterPrinter()' - Unregisters a printer and profiles with the CMS
++ */
++
++void
++cupsdCmsUnregisterPrinter(cupsd_printer_t *p)
++{
++#if defined(HAVE_DBUS)
++  colordUnregisterPrinter(p);
++#endif /* defined(HAVE_DBUS) */
++}
++
++/*
++ * 'cupsdCmsStart()' - Starts the CMS
++ */
++
++void
++cupsdCmsStart(void)
++{
++#if defined(HAVE_DBUS)
++  colordStart();
++#endif /* defined(HAVE_DBUS) */
++}
++
++/*
++ * 'cupsdCmsStop()' - Stops the CMS
++ */
++
++void
++cupsdCmsStop(void)
++{
++#if defined(HAVE_DBUS)
++  colordStop();
++#endif /* defined(HAVE_DBUS) */
++}
+ 
+ /*
+  * 'cupsdDeletePrinter()' - Delete a printer from the system.
+@@ -752,6 +802,12 @@ cupsdDeletePrinter(
+ 		              "Job stopped.");
+ 
+  /*
++  * Unregister profiles...
++  */
++
++  cupsdCmsUnregisterPrinter(p);
++
++ /*
+   * If this printer is the next for browsing, point to the next one...
+   */
+ 
+@@ -1418,6 +1474,12 @@ cupsdRenamePrinter(
+   }
+ 
+  /*
++  * Unregister profiles...
++  */
++
++  cupsdCmsUnregisterPrinter(p);
++
++ /*
+   * Rename the printer...
+   */
+ 
+@@ -2644,6 +2706,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
+ #endif /* __sgi */
+ 
+  /*
++  * Re-register profiles...
++  */
++
++  cupsdCmsUnregisterPrinter(p);
++  cupsdCmsRegisterPrinter(p);
++
++ /*
+   * Let the browse protocols reflect the change
+   */
+ 
+diff --git a/scheduler/printers.h b/scheduler/printers.h
+index 1751578..3820428 100644
+--- a/scheduler/printers.h
++++ b/scheduler/printers.h
+@@ -170,6 +170,10 @@ extern const char	*cupsdValidateDest(const char *uri,
+ 			        	   cups_ptype_t *dtype,
+ 					   cupsd_printer_t **printer);
+ extern void		cupsdWritePrintcap(void);
++extern void		cupsdCmsRegisterPrinter(cupsd_printer_t *p);
++extern void		cupsdCmsUnregisterPrinter(cupsd_printer_t *p);
++extern void		cupsdCmsStart(void);
++extern void		cupsdCmsStop(void);
+ 
+ 
+ /*
+-- 
+1.7.6.2
+
diff --git a/srcpkgs/cups/patches/cups-logrotate.patch b/srcpkgs/cups/patches/cups-logrotate.patch
new file mode 100644
index 0000000000..a6485a9b7a
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-logrotate.patch
@@ -0,0 +1,63 @@
+diff -up cups-1.5b1/scheduler/log.c.logrotate cups-1.5b1/scheduler/log.c
+--- cups-1.5b1/scheduler/log.c.logrotate	2011-05-14 01:04:16.000000000 +0200
++++ cups-1.5b1/scheduler/log.c	2011-05-24 15:47:20.000000000 +0200
+@@ -32,6 +32,9 @@
+ #include "cupsd.h"
+ #include <stdarg.h>
+ #include <syslog.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
+ 
+ 
+ /*
+@@ -71,12 +74,10 @@ cupsdCheckLogFile(cups_file_t **lf,	/* I
+     return (1);
+ 
+  /*
+-  * Format the filename as needed...
++  * Format the filename...
+   */
+ 
+-  if (!*lf ||
+-      (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize &&
+-       MaxLogSize > 0))
++  if (strncmp(logname, "/dev/", 5))
+   {
+    /*
+     * Handle format strings...
+@@ -186,6 +187,34 @@ cupsdCheckLogFile(cups_file_t **lf,	/* I
+   }
+ 
+  /*
++  * Has someone else (i.e. logrotate) already rotated the log for us?
++  */
++  else if (strncmp(filename, "/dev/", 5))
++  {
++    struct stat st;
++    if (stat(filename, &st) || st.st_size == 0)
++    {
++      /* File is either missing or has zero size. */
++
++      cupsFileClose(*lf);
++      if ((*lf = cupsFileOpen(filename, "a")) == NULL)
++      {
++	syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
++             strerror(errno));
++
++	return (0);
++      }
++
++     /*
++      * Change ownership and permissions of non-device logs...
++      */
++
++      fchown(cupsFileNumber(*lf), RunUser, Group);
++      fchmod(cupsFileNumber(*lf), LogFilePerm);
++    }
++  }
++
++ /*
+   * Do we need to rotate the log?
+   */
+ 
diff --git a/srcpkgs/cups/patches/cups-lpr-help.patch b/srcpkgs/cups/patches/cups-lpr-help.patch
new file mode 100644
index 0000000000..c42434dbcf
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-lpr-help.patch
@@ -0,0 +1,48 @@
+diff -up cups-1.5b1/berkeley/lpr.c.lpr-help cups-1.5b1/berkeley/lpr.c
+--- cups-1.5b1/berkeley/lpr.c.lpr-help	2011-03-21 23:02:00.000000000 +0100
++++ cups-1.5b1/berkeley/lpr.c	2011-05-23 17:58:06.000000000 +0200
+@@ -24,6 +24,31 @@
+ #include <cups/cups-private.h>
+ 
+ 
++static void
++usage (const char *name)
++{
++  _cupsLangPrintf(stdout,
++"Usage: %s [OPTION] [ file(s) ]\n"
++"Print files.\n\n"
++"  -E                       force encryption\n"
++"  -H server[:port]         specify alternate server\n"
++"  -C title, -J title, -T title\n"
++"                           set the job name\n\n"
++"  -P destination/instance  print to named printer\n"
++"  -U username              specify alternate username\n"
++"  -# num-copies            set number of copies\n"
++"  -h                       disable banner printing\n"
++"  -l                       print without filtering\n"
++"  -m                       send email on completion\n"
++"  -o option[=value]        set a job option\n"
++"  -p                       format text file with header\n"
++"  -q                       hold job for printing\n"
++"  -r                       delete files after printing\n"
++"\nWith no file given, read standard input.\n"
++, name);
++}
++
++
+ /*
+  * 'main()' - Parse options and send files for printing.
+  */
+@@ -270,6 +294,12 @@ main(int  argc,				/* I - Number of comm
+ 	    break;
+ 
+ 	default :
++	    if (!strcmp (argv[i], "--help"))
++	    {
++	      usage (argv[0]);
++	      return (0);
++	    }
++
+ 	    _cupsLangPrintf(stderr,
+ 	                    _("%s: Error - unknown option \"%c\"."), argv[0],
+ 			    argv[i][1]);
diff --git a/srcpkgs/cups/patches/cups-multilib.patch b/srcpkgs/cups/patches/cups-multilib.patch
new file mode 100644
index 0000000000..3c6bc397ab
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-multilib.patch
@@ -0,0 +1,16 @@
+diff -up cups-1.5b1/cups-config.in.multilib cups-1.5b1/cups-config.in
+--- cups-1.5b1/cups-config.in.multilib	2010-06-16 02:48:25.000000000 +0200
++++ cups-1.5b1/cups-config.in	2011-05-23 17:33:31.000000000 +0200
+@@ -22,8 +22,10 @@ prefix=@prefix@
+ exec_prefix=@exec_prefix@
+ bindir=@bindir@
+ includedir=@includedir@
+-libdir=@libdir@
+-imagelibdir=@libdir@
++# Fetch libdir from gnutls's pkg-config script.  This is a bit
++# of a cheat, but the cups-devel package requires gnutls-devel anyway.
++libdir=`pkg-config --variable=libdir gnutls`
++imagelibdir=`pkg-config --variable=libdir gnutls`
+ datarootdir=@datadir@
+ datadir=@datadir@
+ sysconfdir=@sysconfdir@
diff --git a/srcpkgs/cups/patches/cups-no-export-ssllibs.patch b/srcpkgs/cups/patches/cups-no-export-ssllibs.patch
new file mode 100644
index 0000000000..de277d81f1
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-no-export-ssllibs.patch
@@ -0,0 +1,12 @@
+diff -up cups-1.5.3/config-scripts/cups-ssl.m4.no-export-ssllibs cups-1.5.3/config-scripts/cups-ssl.m4
+--- cups-1.5.3/config-scripts/cups-ssl.m4.no-export-ssllibs	2012-03-21 05:45:48.000000000 +0100
++++ cups-1.5.3/config-scripts/cups-ssl.m4	2012-05-15 16:47:13.753314620 +0200
+@@ -173,7 +173,7 @@ AC_SUBST(IPPALIASES)
+ AC_SUBST(SSLFLAGS)
+ AC_SUBST(SSLLIBS)
+ 
+-EXPORT_SSLLIBS="$SSLLIBS"
++EXPORT_SSLLIBS=""
+ AC_SUBST(EXPORT_SSLLIBS)
+ 
+ dnl
diff --git a/srcpkgs/cups/patches/cups-no-gcrypt.patch b/srcpkgs/cups/patches/cups-no-gcrypt.patch
new file mode 100644
index 0000000000..42f71d0d47
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-no-gcrypt.patch
@@ -0,0 +1,38 @@
+diff -ruN cups-1.4.7.orig//config-scripts/cups-ssl.m4 cups-1.4.7/config-scripts/cups-ssl.m4
+--- cups-1.5.0.orig//config-scripts/cups-ssl.m4	2011-01-11 08:05:58.000000000 +0100
++++ cups-1.5.0/config-scripts/cups-ssl.m4	2011-08-02 10:44:26.011047900 +0200
+@@ -96,7 +96,6 @@
+     dnl Then look for GNU TLS...
+     if test $have_ssl = 0 -a "x$enable_gnutls" != "xno" -a "x$PKGCONFIG" != x; then
+     	AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config)
+-    	AC_PATH_PROG(LIBGCRYPTCONFIG,libgcrypt-config)
+ 	if $PKGCONFIG --exists gnutls; then
+ 	    have_ssl=1
+ 	    SSLLIBS=`$PKGCONFIG --libs gnutls`
+@@ -110,16 +109,6 @@
+ 	    AC_DEFINE(HAVE_SSL)
+ 	    AC_DEFINE(HAVE_GNUTLS)
+ 	fi
+-
+-	if test $have_ssl = 1; then
+-            if $PKGCONFIG --exists gcrypt; then
+-	        SSLLIBS="$SSLLIBS `$PKGCONFIG --libs gcrypt`"
+-	        SSLFLAGS="$SSLFLAGS `$PKGCONFIG --cflags gcrypt`"
+-	    elif test "x$LIBGCRYPTCONFIG" != x; then
+-	        SSLLIBS="$SSLLIBS `$LIBGCRYPTCONFIG --libs`"
+-	        SSLFLAGS="$SSLFLAGS `$LIBGCRYPTCONFIG --cflags`"
+-	    fi
+-	fi
+     fi
+ 
+     dnl Check for the OpenSSL library last...
+--- cups-1.5.0.orig//cups/http-private.h	2011-01-22 01:07:22.000000000 +0100
++++ cups-1.5.0/cups/http-private.h	2011-08-02 10:42:43.341604107 +0200
+@@ -93,7 +93,6 @@
+ #  elif defined HAVE_GNUTLS
+ #    include <gnutls/gnutls.h>
+ #    include <gnutls/x509.h>
+-#    include <gcrypt.h>
+ #  elif defined(HAVE_CDSASSL)
+ #    include <CoreFoundation/CoreFoundation.h>
+ #    include <Security/Security.h>
diff --git a/srcpkgs/cups/patches/cups-no-gzip-man.patch b/srcpkgs/cups/patches/cups-no-gzip-man.patch
new file mode 100644
index 0000000000..6786c44303
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-no-gzip-man.patch
@@ -0,0 +1,18 @@
+diff -up cups-1.5b1/config-scripts/cups-manpages.m4.no-gzip-man cups-1.5b1/config-scripts/cups-manpages.m4
+--- cups-1.5b1/config-scripts/cups-manpages.m4.no-gzip-man	2011-05-12 07:21:56.000000000 +0200
++++ cups-1.5b1/config-scripts/cups-manpages.m4	2011-05-23 17:25:50.000000000 +0200
+@@ -69,10 +69,10 @@ case "$uname" in
+ 		;;
+ 	Linux* | GNU* | Darwin*)
+ 		# Linux, GNU Hurd, and Mac OS X
+-		MAN1EXT=1.gz
+-		MAN5EXT=5.gz
+-		MAN7EXT=7.gz
+-		MAN8EXT=8.gz
++		MAN1EXT=1
++		MAN5EXT=5
++		MAN7EXT=7
++		MAN8EXT=8
+ 		MAN8DIR=8
+ 		;;
+ 	*)
diff --git a/srcpkgs/cups/patches/cups-peercred.patch b/srcpkgs/cups/patches/cups-peercred.patch
new file mode 100644
index 0000000000..a106abbd05
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-peercred.patch
@@ -0,0 +1,11 @@
+diff -up cups-1.5b1/scheduler/auth.c.peercred cups-1.5b1/scheduler/auth.c
+--- cups-1.5b1/scheduler/auth.c.peercred	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/scheduler/auth.c	2011-05-23 18:00:18.000000000 +0200
+@@ -52,6 +52,7 @@
+  * Include necessary headers...
+  */
+ 
++#define _GNU_SOURCE
+ #include "cupsd.h"
+ #include <grp.h>
+ #ifdef HAVE_SHADOW_H
diff --git a/srcpkgs/cups/patches/cups-pid.patch b/srcpkgs/cups/patches/cups-pid.patch
new file mode 100644
index 0000000000..23ffd47064
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-pid.patch
@@ -0,0 +1,37 @@
+diff -up cups-1.5b1/scheduler/main.c.pid cups-1.5b1/scheduler/main.c
+--- cups-1.5b1/scheduler/main.c.pid	2011-05-18 22:44:16.000000000 +0200
++++ cups-1.5b1/scheduler/main.c	2011-05-23 18:01:20.000000000 +0200
+@@ -311,6 +311,8 @@ main(int  argc,				/* I - Number of comm
+     * Setup signal handlers for the parent...
+     */
+ 
++    pid_t pid;
++
+ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+     sigset(SIGUSR1, parent_handler);
+     sigset(SIGCHLD, parent_handler);
+@@ -334,7 +336,7 @@ main(int  argc,				/* I - Number of comm
+     signal(SIGHUP, SIG_IGN);
+ #endif /* HAVE_SIGSET */
+ 
+-    if (fork() > 0)
++    if ((pid = fork()) > 0)
+     {
+      /*
+       * OK, wait for the child to startup and send us SIGUSR1 or to crash
+@@ -346,7 +348,15 @@ main(int  argc,				/* I - Number of comm
+         sleep(1);
+ 
+       if (parent_signal == SIGUSR1)
++      {
++        FILE *f = fopen ("/var/run/cupsd.pid", "w");
++        if (f)
++        {
++          fprintf (f, "%d\n", pid);
++          fclose (f);
++        }
+         return (0);
++      }
+ 
+       if (wait(&i) < 0)
+       {
diff --git a/srcpkgs/cups/patches/cups-res_init.patch b/srcpkgs/cups/patches/cups-res_init.patch
new file mode 100644
index 0000000000..1dc110e0b0
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-res_init.patch
@@ -0,0 +1,26 @@
+diff -up cups-1.5b1/cups/http-addr.c.res_init cups-1.5b1/cups/http-addr.c
+--- cups-1.5b1/cups/http-addr.c.res_init	2011-04-16 01:38:13.000000000 +0200
++++ cups-1.5b1/cups/http-addr.c	2011-05-24 15:56:50.000000000 +0200
+@@ -256,7 +256,8 @@ httpAddrLookup(
+ 
+     if (error)
+     {
+-      if (error == EAI_FAIL)
++      if (error == EAI_FAIL || error == EAI_AGAIN || error == EAI_NODATA ||
++          error == EAI_NONAME)
+         cg->need_res_init = 1;
+ 
+       return (httpAddrString(addr, name, namelen));
+diff -up cups-1.5b1/cups/http-addrlist.c.res_init cups-1.5b1/cups/http-addrlist.c
+--- cups-1.5b1/cups/http-addrlist.c.res_init	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/cups/http-addrlist.c	2011-05-24 15:56:50.000000000 +0200
+@@ -386,7 +386,8 @@ httpAddrGetList(const char *hostname,	/*
+ 
+       freeaddrinfo(results);
+     }
+-    else if (error == EAI_FAIL)
++    else if (error == EAI_FAIL || error == EAI_AGAIN || error == EAI_NODATA ||
++             error == EAI_NONAME)
+       cg->need_res_init = 1;
+ 
+ #else
diff --git a/srcpkgs/cups/patches/cups-ricoh-deviceid-oid.patch b/srcpkgs/cups/patches/cups-ricoh-deviceid-oid.patch
new file mode 100644
index 0000000000..c148f9539b
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-ricoh-deviceid-oid.patch
@@ -0,0 +1,21 @@
+diff -up cups-1.5b1/backend/snmp.c.ricoh-deviceid-oid cups-1.5b1/backend/snmp.c
+--- cups-1.5b1/backend/snmp.c.ricoh-deviceid-oid	2011-05-24 17:29:48.000000000 +0200
++++ cups-1.5b1/backend/snmp.c	2011-05-24 17:29:48.000000000 +0200
+@@ -188,6 +188,7 @@ static const int	LexmarkProductOID[] = {
+ static const int	LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 };
+ static const int	LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 };
+ static const int	HPDeviceIdOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 };
++static const int	RicohDeviceIdOID[] = { 1,3,6,1,4,1,367,3,2,1,1,1,11,0,-1 };
+ static const int	XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 };
+ static cups_array_t	*DeviceURIs = NULL;
+ static int		HostNameLookups = 0;
+@@ -1005,6 +1006,9 @@ read_snmp_response(int fd)		/* I - SNMP 
+ 	               packet.community, CUPS_ASN1_GET_REQUEST,
+ 		       DEVICE_ID, LexmarkDeviceIdOID);
+ 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
++		       packet.community, CUPS_ASN1_GET_REQUEST,
++		       DEVICE_ID, RicohDeviceIdOID);
++	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
+ 	               packet.community, CUPS_ASN1_GET_REQUEST,
+ 		       DEVICE_PRODUCT, XeroxProductOID);
+ 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
diff --git a/srcpkgs/cups/patches/cups-serial.patch b/srcpkgs/cups/patches/cups-serial.patch
new file mode 100644
index 0000000000..d17c9cb02a
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-serial.patch
@@ -0,0 +1,11 @@
+diff -up cups-1.5b1/backend/serial.c.serial cups-1.5b1/backend/serial.c
+--- cups-1.5b1/backend/serial.c.serial	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/backend/serial.c	2011-05-23 17:34:33.000000000 +0200
+@@ -75,6 +75,7 @@
+ #endif /* __APPLE__ */
+ 
+ #if defined(__linux) && defined(TIOCGSERIAL)
++#  include <linux/types.h>
+ #  include <linux/serial.h>
+ #  include <linux/ioctl.h>
+ #endif /* __linux && TIOCGSERIAL */
diff --git a/srcpkgs/cups/patches/cups-serverbin-compat.patch b/srcpkgs/cups/patches/cups-serverbin-compat.patch
new file mode 100644
index 0000000000..0ca72fd370
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-serverbin-compat.patch
@@ -0,0 +1,190 @@
+diff -up cups-1.5b1/scheduler/conf.c.serverbin-compat cups-1.5b1/scheduler/conf.c
+--- cups-1.5b1/scheduler/conf.c.serverbin-compat	2011-05-20 06:24:54.000000000 +0200
++++ cups-1.5b1/scheduler/conf.c	2011-05-23 17:20:33.000000000 +0200
+@@ -491,6 +491,9 @@ cupsdReadConfiguration(void)
+   cupsdClearString(&ServerName);
+   cupsdClearString(&ServerAdmin);
+   cupsdSetString(&ServerBin, CUPS_SERVERBIN);
++#ifdef __x86_64__
++  cupsdSetString(&ServerBin_compat, "/usr/lib64/cups");
++#endif /* __x86_64__ */
+   cupsdSetString(&RequestRoot, CUPS_REQUESTS);
+   cupsdSetString(&CacheDir, CUPS_CACHEDIR);
+   cupsdSetString(&DataDir, CUPS_DATADIR);
+@@ -1378,7 +1381,12 @@ cupsdReadConfiguration(void)
+     * Read the MIME type and conversion database...
+     */
+ 
++#ifdef __x86_64__
++    snprintf(temp, sizeof(temp), "%s/filter:%s/filter", ServerBin,
++	     ServerBin_compat);
++#else
+     snprintf(temp, sizeof(temp), "%s/filter", ServerBin);
++#endif
+     snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
+ 
+     MimeDatabase = mimeNew();
+diff -up cups-1.5b1/scheduler/conf.h.serverbin-compat cups-1.5b1/scheduler/conf.h
+--- cups-1.5b1/scheduler/conf.h.serverbin-compat	2011-04-22 19:47:03.000000000 +0200
++++ cups-1.5b1/scheduler/conf.h	2011-05-23 15:34:25.000000000 +0200
+@@ -105,6 +105,10 @@ VAR char		*ConfigurationFile	VALUE(NULL)
+ 					/* Root directory for scheduler */
+ 			*ServerBin		VALUE(NULL),
+ 					/* Root directory for binaries */
++#ifdef __x86_64__
++			*ServerBin_compat	VALUE(NULL),
++					/* Compat directory for binaries */
++#endif /* __x86_64__ */
+ 			*StateDir		VALUE(NULL),
+ 					/* Root directory for state data */
+ 			*RequestRoot		VALUE(NULL),
+diff -up cups-1.5b1/scheduler/env.c.serverbin-compat cups-1.5b1/scheduler/env.c
+--- cups-1.5b1/scheduler/env.c.serverbin-compat	2011-01-11 04:48:42.000000000 +0100
++++ cups-1.5b1/scheduler/env.c	2011-05-23 17:07:17.000000000 +0200
+@@ -218,8 +218,13 @@ cupsdUpdateEnv(void)
+   set_if_undefined("LD_PRELOAD", NULL);
+   set_if_undefined("NLSPATH", NULL);
+   if (find_env("PATH") < 0)
++#ifdef __x86_64__
++    cupsdSetEnvf("PATH", "%s/filter:%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR
++                         ":/bin:/usr/bin", ServerBin, ServerBin_compat);
++#else /* ! defined(__x86_64__) */
+     cupsdSetEnvf("PATH", "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR
+ 			 ":/bin:/usr/bin", ServerBin);
++#endif
+   set_if_undefined("SERVER_ADMIN", ServerAdmin);
+   set_if_undefined("SHLIB_PATH", NULL);
+   set_if_undefined("SOFTWARE", CUPS_MINIMAL);
+diff -up cups-1.5b1/scheduler/ipp.c.serverbin-compat cups-1.5b1/scheduler/ipp.c
+--- cups-1.5b1/scheduler/ipp.c.serverbin-compat	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/scheduler/ipp.c	2011-05-23 16:09:57.000000000 +0200
+@@ -2586,9 +2586,18 @@ add_printer(cupsd_client_t  *con,	/* I -
+         * Could not find device in list!
+ 	*/
+ 
++#ifdef __x86_64__
++	snprintf(srcfile, sizeof(srcfile), "%s/backend/%s", ServerBin_compat,
++		 scheme);
++	if (access(srcfile, X_OK))
++	{
++#endif /* __x86_64__ */
+ 	send_ipp_status(con, IPP_NOT_POSSIBLE,
+                         _("Bad device-uri scheme \"%s\"."), scheme);
+ 	return;
++#ifdef __x86_64__
++	}
++#endif /* __x86_64__ */
+       }
+     }
+ 
+diff -up cups-1.5b1/scheduler/job.c.serverbin-compat cups-1.5b1/scheduler/job.c
+--- cups-1.5b1/scheduler/job.c.serverbin-compat	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/scheduler/job.c	2011-05-23 16:18:57.000000000 +0200
+@@ -1047,8 +1047,32 @@ cupsdContinueJob(cupsd_job_t *job)	/* I 
+        i ++, filter = (mime_filter_t *)cupsArrayNext(filters))
+   {
+     if (filter->filter[0] != '/')
+-      snprintf(command, sizeof(command), "%s/filter/%s", ServerBin,
+-               filter->filter);
++      {
++	snprintf(command, sizeof(command), "%s/filter/%s", ServerBin,
++		 filter->filter);
++#ifdef __x86_64__
++	if (access(command, F_OK))
++	  {
++	    snprintf(command, sizeof(command), "%s/filter/%s",
++		     ServerBin_compat, filter->filter);
++	    if (!access(command, F_OK))
++	      {
++		/* Not in the correct directory, but found it in the compat
++		 * directory.  Issue a warning. */
++		cupsdLogMessage(CUPSD_LOG_INFO,
++				"Filter '%s' not in %s/filter!",
++				filter->filter, ServerBin);
++	      }
++	    else
++	      {
++		/* Not in the compat directory either; make any error
++		 * messages use the correct directory name then. */
++		snprintf(command, sizeof(command), "%s/filter/%s", ServerBin,
++			 filter->filter);
++	      }
++	  }
++#endif /* __x86_64__ */
++      }
+     else
+       strlcpy(command, filter->filter, sizeof(command));
+ 
+@@ -1199,6 +1223,28 @@ cupsdContinueJob(cupsd_job_t *job)	/* I 
+     {
+       cupsdClosePipe(job->back_pipes);
+       cupsdClosePipe(job->side_pipes);
++#ifdef __x86_64__
++      if (access(command, F_OK))
++	{
++	  snprintf(command, sizeof(command), "%s/backend/%s", ServerBin_compat,
++		   scheme);
++	  if (!access(command, F_OK))
++	    {
++	      /* Not in the correct directory, but we found it in the compat
++	       * directory.  Issue a warning. */
++	      cupsdLogMessage(CUPSD_LOG_INFO,
++			      "Backend '%s' not in %s/backend!", scheme,
++			      ServerBin);
++	    }
++	  else
++	    {
++	      /* Not in the compat directory either; make any error
++		 messages use the correct directory name then. */
++	      snprintf(command, sizeof(command), "%s/backend/%s", ServerBin,
++		       scheme);
++	    }
++	}
++#endif /* __x86_64__ */
+ 
+       close(job->status_pipes[1]);
+       job->status_pipes[1] = -1;
+diff -up cups-1.5b1/scheduler/printers.c.serverbin-compat cups-1.5b1/scheduler/printers.c
+--- cups-1.5b1/scheduler/printers.c.serverbin-compat	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/scheduler/printers.c	2011-05-23 17:09:04.000000000 +0200
+@@ -1030,9 +1030,19 @@ cupsdLoadAllPrinters(void)
+ 	    * Backend does not exist, stop printer...
+ 	    */
+ 
++#ifdef __x86_64__
++	    snprintf(line, sizeof(line), "%s/backend/%s", ServerBin_compat,
++		     p->device_uri);
++	    if (access(line, 0))
++	      {
++#endif /* __x86_64__ */
++
+ 	    p->state = IPP_PRINTER_STOPPED;
+ 	    snprintf(p->state_message, sizeof(p->state_message),
+ 	             "Backend %s does not exist!", line);
++#ifdef __x86_64__
++	      }
++#endif /* __x86_64__ */
+ 	  }
+         }
+ 
+@@ -3621,8 +3631,20 @@ add_printer_filter(
+     else
+       snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);
+ 
++#ifdef __x86_64__
++    if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !RunUser,
++                       cupsdLogFCMessage, p) == _CUPS_FILE_CHECK_MISSING) {
++      snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin_compat,
++               program);
++      if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !RunUser,
++                         cupsdLogFCMessage, p) == _CUPS_FILE_CHECK_MISSING)
++        snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin,
++                 program);
++    }
++#else /* ! defined(__x86_64__) */
+     _cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !RunUser,
+                    cupsdLogFCMessage, p);
++#endif 
+   }
+ 
+  /*
diff --git a/srcpkgs/cups/patches/cups-snmp-quirks.patch b/srcpkgs/cups/patches/cups-snmp-quirks.patch
new file mode 100644
index 0000000000..535f6c0bec
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-snmp-quirks.patch
@@ -0,0 +1,115 @@
+diff -up cups-1.5.2/backend/snmp-supplies.c.snmp-quirks cups-1.5.2/backend/snmp-supplies.c
+--- cups-1.5.2/backend/snmp-supplies.c.snmp-quirks	2011-10-07 23:41:07.000000000 +0200
++++ cups-1.5.2/backend/snmp-supplies.c	2012-02-06 10:48:47.543906526 +0100
+@@ -47,6 +47,13 @@
+ 
+ 
+ /*
++ * Printer quirks...
++ */
++
++#define QUIRK_CAPACITY	(1<<0)
++
++
++/*
+  * Local structures...
+  */
+ 
+@@ -66,6 +73,12 @@ typedef struct				/**** Printer state ta
+   const char	*keyword;		/* IPP printer-state-reasons keyword */
+ } backend_state_t;
+ 
++typedef struct				/**** Quirk names table ****/
++{
++  int		bit;			/* Quirk bit */
++  const char	*keyword;		/* cupsSNMPQuirks keyword */
++} quirk_name_t;
++
+ 
+ /*
+  * Local globals...
+@@ -77,6 +90,7 @@ static int		current_state = -1;
+ static int		charset = -1;	/* Character set for supply names */
+ static int		num_supplies = 0;
+ 					/* Number of supplies found */
++static int		quirks = 0;	/* Printer quirks */
+ static backend_supplies_t supplies[CUPS_MAX_SUPPLIES];
+ 					/* Supply information */
+ static int		supply_state = -1;
+@@ -176,6 +190,15 @@ static const backend_state_t const suppl
+ 			  { CUPS_TONER_EMPTY, "toner-empty-warning" }
+ 			};
+ 
++static const quirk_name_t const quirk_names[] =
++			{
++			 /*
++			  * The prtMarkerSuppliesLevel values are
++			  * percentages, not levels relative to the
++			  * stated capacity.
++			  */
++			  { QUIRK_CAPACITY, "capacity" }
++			};
+ 
+ /*
+  * Local functions...
+@@ -229,6 +252,9 @@ backendSNMPSupplies(
+ 
+     for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
+     {
++      if (quirks & QUIRK_CAPACITY)
++	supplies[i].max_capacity = 100;
++
+       if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
+ 	percent = 100 * supplies[i].level / supplies[i].max_capacity;
+       else
+@@ -401,6 +427,7 @@ backend_init_supplies(
+     http_addr_t *addr)			/* I - Printer address */
+ {
+   int		i,			/* Looping var */
++		len,			/* Quirk name length */
+ 		type;			/* Current marker type */
+   cups_file_t	*cachefile;		/* Cache file */
+   const char	*cachedir;		/* CUPS_CACHEDIR value */
+@@ -462,6 +489,7 @@ backend_init_supplies(
+   current_state = -1;
+   num_supplies  = -1;
+   charset       = -1;
++  quirks	= 0;
+ 
+   memset(supplies, 0, sizeof(supplies));
+ 
+@@ -477,6 +505,34 @@ backend_init_supplies(
+     return;
+   }
+ 
++  if (ppd &&
++      (ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL &&
++      ppdattr->value)
++  {
++    ptr = ppdattr->value;
++    while (*ptr != '\0')
++    {
++     /*
++      * Match keyword against quirk_names table.
++      */
++
++      for (i = 0; i < sizeof (quirk_names) / sizeof (quirk_names[0]); i++)
++      {
++	len = strlen (quirk_names[i].keyword);
++	if (!strncmp (ptr, quirk_names[i].keyword, len) &&
++	    (ptr[len] == '\0' || ptr[len] == ' '))
++	  quirks |= quirk_names[i].bit;
++      }
++
++     /*
++      * Advance to next keyword.
++      */
++
++      ptr += strcspn (ptr, " ");
++      ptr += strspn (ptr, " ");
++    }
++  }
++
+   ppdClose(ppd);
+ 
+  /*
diff --git a/srcpkgs/cups/patches/cups-str3382.patch b/srcpkgs/cups/patches/cups-str3382.patch
new file mode 100644
index 0000000000..2e8736d048
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-str3382.patch
@@ -0,0 +1,64 @@
+diff -up cups-1.5b1/cups/tempfile.c.str3382 cups-1.5b1/cups/tempfile.c
+--- cups-1.5b1/cups/tempfile.c.str3382	2010-03-24 01:45:34.000000000 +0100
++++ cups-1.5b1/cups/tempfile.c	2011-05-24 16:04:47.000000000 +0200
+@@ -33,6 +33,7 @@
+ #  include <io.h>
+ #else
+ #  include <unistd.h>
++#  include <sys/types.h>
+ #endif /* WIN32 || __EMX__ */
+ 
+ 
+@@ -54,7 +55,7 @@ cupsTempFd(char *filename,		/* I - Point
+   char		tmppath[1024];		/* Windows temporary directory */
+   DWORD		curtime;		/* Current time */
+ #else
+-  struct timeval curtime;		/* Current time */
++  mode_t	old_umask;		/* Old umask before using mkstemp() */
+ #endif /* WIN32 */
+ 
+ 
+@@ -105,33 +106,25 @@ cupsTempFd(char *filename,		/* I - Point
+ 
+     snprintf(filename, len - 1, "%s/%05lx%08lx", tmpdir,
+              GetCurrentProcessId(), curtime);
+-#else
+-   /*
+-    * Get the current time of day...
+-    */
+-
+-    gettimeofday(&curtime, NULL);
+-
+-   /*
+-    * Format a string using the hex time values...
+-    */
+-
+-    snprintf(filename, len - 1, "%s/%05x%08x", tmpdir, (unsigned)getpid(),
+-             (unsigned)(curtime.tv_sec + curtime.tv_usec + tries));
+-#endif /* WIN32 */
+ 
+    /*
+     * Open the file in "exclusive" mode, making sure that we don't
+     * stomp on an existing file or someone's symlink crack...
+     */
+ 
+-#ifdef WIN32
+     fd = open(filename, _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY,
+               _S_IREAD | _S_IWRITE);
+-#elif defined(O_NOFOLLOW)
+-    fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
+ #else
+-    fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
++
++   /*
++    * Use the standard mkstemp() call to make a temporary filename
++    * securely.  -- andrew.wood@jdplc.com
++    */
++    snprintf(filename, len - 1, "%s/cupsXXXXXX", tmpdir);
++
++    old_umask = umask(0077);
++    fd = mkstemp(filename);
++    umask(old_umask);
+ #endif /* WIN32 */
+ 
+     if (fd < 0 && errno != EEXIST)
diff --git a/srcpkgs/cups/patches/cups-strict-ppd-line-length.patch b/srcpkgs/cups/patches/cups-strict-ppd-line-length.patch
new file mode 100644
index 0000000000..b2697ec318
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-strict-ppd-line-length.patch
@@ -0,0 +1,30 @@
+diff -up cups-1.5b1/cups/ppd.c.strict-ppd-line-length cups-1.5b1/cups/ppd.c
+--- cups-1.5b1/cups/ppd.c.strict-ppd-line-length	2011-05-20 05:49:49.000000000 +0200
++++ cups-1.5b1/cups/ppd.c	2011-05-24 15:46:13.000000000 +0200
+@@ -2786,7 +2786,7 @@ ppd_read(cups_file_t    *fp,		/* I - Fil
+ 	*lineptr++ = ch;
+ 	col ++;
+ 
+-	if (col > (PPD_MAX_LINE - 1))
++	if (col > (PPD_MAX_LINE - 1) && cg->ppd_conform == PPD_CONFORM_STRICT)
+ 	{
+ 	 /*
+           * Line is too long...
+@@ -2847,7 +2847,7 @@ ppd_read(cups_file_t    *fp,		/* I - Fil
+ 	{
+ 	  col ++;
+ 
+-	  if (col > (PPD_MAX_LINE - 1))
++	  if (col > (PPD_MAX_LINE - 1) && cg->ppd_conform == PPD_CONFORM_STRICT)
+ 	  {
+ 	   /*
+             * Line is too long...
+@@ -2906,7 +2906,7 @@ ppd_read(cups_file_t    *fp,		/* I - Fil
+ 	{
+ 	  col ++;
+ 
+-	  if (col > (PPD_MAX_LINE - 1))
++	  if (col > (PPD_MAX_LINE - 1) && cg->ppd_conform == PPD_CONFORM_STRICT)
+ 	  {
+ 	   /*
+             * Line is too long...
diff --git a/srcpkgs/cups/patches/cups-system-auth.patch b/srcpkgs/cups/patches/cups-system-auth.patch
new file mode 100644
index 0000000000..60117a9c83
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-system-auth.patch
@@ -0,0 +1,38 @@
+diff -up cups-1.5b1/conf/cups.password-auth.system-auth cups-1.5b1/conf/cups.password-auth
+--- cups-1.5b1/conf/cups.password-auth.system-auth	2011-05-23 17:27:27.000000000 +0200
++++ cups-1.5b1/conf/cups.password-auth	2011-05-23 17:27:27.000000000 +0200
+@@ -0,0 +1,4 @@
++#%PAM-1.0
++# Use password-auth common PAM configuration for the daemon
++auth        include     password-auth
++account     include     password-auth
+diff -up cups-1.5b1/conf/cups.system-auth.system-auth cups-1.5b1/conf/cups.system-auth
+--- cups-1.5b1/conf/cups.system-auth.system-auth	2011-05-23 17:27:27.000000000 +0200
++++ cups-1.5b1/conf/cups.system-auth	2011-05-23 17:27:27.000000000 +0200
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++auth	include		system-auth
++account	include		system-auth
+diff -up cups-1.5b1/conf/Makefile.system-auth cups-1.5b1/conf/Makefile
+--- cups-1.5b1/conf/Makefile.system-auth	2011-05-12 07:21:56.000000000 +0200
++++ cups-1.5b1/conf/Makefile	2011-05-23 17:27:27.000000000 +0200
+@@ -90,10 +90,16 @@ install-data:
+ 	done
+ 	-if test x$(PAMDIR) != x; then \
+ 		$(INSTALL_DIR) -m 755 $(BUILDROOT)$(PAMDIR); \
+-		if test -r $(BUILDROOT)$(PAMDIR)/cups ; then \
+-			$(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups.N ; \
++		if test -f /etc/pam.d/password-auth; then \
++			$(INSTALL_DATA) cups.password-auth $(BUILDROOT)$(PAMDIR)/cups; \
++		elif test -f /etc/pam.d/system-auth; then \
++			$(INSTALL_DATA) cups.system-auth $(BUILDROOT)$(PAMDIR)/cups; \
+ 		else \
+-			$(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups ; \
++			if test -r $(BUILDROOT)$(PAMDIR)/cups ; then \
++				$(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups.N ; \
++			else \
++				$(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups ; \
++			fi ; \
+ 		fi ; \
+ 	fi
+ 
diff --git a/srcpkgs/cups/patches/cups-systemd-socket.patch b/srcpkgs/cups/patches/cups-systemd-socket.patch
new file mode 100644
index 0000000000..09d17d415c
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-systemd-socket.patch
@@ -0,0 +1,527 @@
+diff -up cups-1.5.2/config.h.in.systemd-socket cups-1.5.2/config.h.in
+--- cups-1.5.2/config.h.in.systemd-socket	2012-03-16 14:50:57.089449755 +0000
++++ cups-1.5.2/config.h.in	2012-03-16 14:50:57.146449787 +0000
+@@ -503,6 +503,13 @@
+ 
+ 
+ /*
++ * Do we have systemd support?
++ */
++
++#undef HAVE_SYSTEMD
++
++
++/*
+  * Various scripting languages...
+  */
+ 
+diff -up cups-1.5.2/config-scripts/cups-systemd.m4.systemd-socket cups-1.5.2/config-scripts/cups-systemd.m4
+--- cups-1.5.2/config-scripts/cups-systemd.m4.systemd-socket	2012-03-16 14:50:57.146449787 +0000
++++ cups-1.5.2/config-scripts/cups-systemd.m4	2012-03-16 14:50:57.146449787 +0000
+@@ -0,0 +1,36 @@
++dnl
++dnl "$Id$"
++dnl
++dnl   systemd stuff for CUPS.
++
++dnl Find whether systemd is available
++
++SDLIBS=""
++AC_ARG_WITH([systemdsystemunitdir],
++        AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
++        [], [with_systemdsystemunitdir=$($PKGCONFIG --variable=systemdsystemunitdir systemd)])
++if test "x$with_systemdsystemunitdir" != xno; then
++        AC_MSG_CHECKING(for libsystemd-daemon)
++        if $PKGCONFIG --exists libsystemd-daemon; then
++		AC_MSG_RESULT(yes)
++        	SDCFLAGS=`$PKGCONFIG --cflags libsystemd-daemon`
++        	SDLIBS=`$PKGCONFIG --libs libsystemd-daemon`
++		AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
++		AC_DEFINE(HAVE_SYSTEMD)
++	else
++		AC_MSG_RESULT(no)
++	fi
++fi
++
++if test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ; then
++        SYSTEMD_UNITS="cups.service cups.socket cups.path"
++else
++        SYSTEMD_UNITS=""
++fi
++
++AC_SUBST(SYSTEMD_UNITS)
++AC_SUBST(SDLIBS)
++
++dnl
++dnl "$Id$"
++dnl
+diff -up cups-1.5.2/configure.in.systemd-socket cups-1.5.2/configure.in
+--- cups-1.5.2/configure.in.systemd-socket	2011-08-31 02:36:33.000000000 +0100
++++ cups-1.5.2/configure.in	2012-03-16 14:50:57.146449787 +0000
+@@ -37,6 +37,7 @@ sinclude(config-scripts/cups-pam.m4)
+ sinclude(config-scripts/cups-largefile.m4)
+ sinclude(config-scripts/cups-dnssd.m4)
+ sinclude(config-scripts/cups-launchd.m4)
++sinclude(config-scripts/cups-systemd.m4)
+ sinclude(config-scripts/cups-defaults.m4)
+ sinclude(config-scripts/cups-pdf.m4)
+ sinclude(config-scripts/cups-scripting.m4)
+@@ -71,6 +72,9 @@ AC_OUTPUT(Makedefs
+ 	  conf/snmp.conf
+ 	  cups-config
+ 	  data/testprint
++          data/cups.service
++          data/cups.socket
++          data/cups.path
+ 	  desktop/cups.desktop
+ 	  doc/help/ref-cupsd-conf.html
+ 	  doc/help/standard.html
+diff -up cups-1.5.2/cups/usersys.c.systemd-socket cups-1.5.2/cups/usersys.c
+--- cups-1.5.2/cups/usersys.c.systemd-socket	2012-03-16 14:50:57.054449734 +0000
++++ cups-1.5.2/cups/usersys.c	2012-03-16 14:50:57.148449788 +0000
+@@ -778,7 +778,7 @@ cups_read_client_conf(
+     struct stat	sockinfo;		/* Domain socket information */
+ 
+     if (!stat(CUPS_DEFAULT_DOMAINSOCKET, &sockinfo) &&
+-	(sockinfo.st_mode & S_IRWXO) == S_IRWXO)
++	(sockinfo.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH))
+       cups_server = CUPS_DEFAULT_DOMAINSOCKET;
+     else
+ #endif /* CUPS_DEFAULT_DOMAINSOCKET */
+diff -up cups-1.5.2/data/cups.path.in.systemd-socket cups-1.5.2/data/cups.path.in
+--- cups-1.5.2/data/cups.path.in.systemd-socket	2012-03-16 14:50:57.148449788 +0000
++++ cups-1.5.2/data/cups.path.in	2012-03-16 14:50:57.148449788 +0000
+@@ -0,0 +1,8 @@
++[Unit]
++Description=CUPS Printer Service Spool
++
++[Path]
++PathExistsGlob=@CUPS_REQUESTS@/d*
++
++[Install]
++WantedBy=multi-user.target
+diff -up cups-1.5.2/data/cups.service.in.systemd-socket cups-1.5.2/data/cups.service.in
+--- cups-1.5.2/data/cups.service.in.systemd-socket	2012-03-16 14:50:57.149449788 +0000
++++ cups-1.5.2/data/cups.service.in	2012-03-16 14:50:57.149449788 +0000
+@@ -0,0 +1,10 @@
++[Unit]
++Description=CUPS Printing Service
++
++[Service]
++ExecStart=@sbindir@/cupsd -f
++PrivateTmp=true
++
++[Install]
++Also=cups.socket cups.path
++WantedBy=printer.target
+diff -up cups-1.5.2/data/cups.socket.in.systemd-socket cups-1.5.2/data/cups.socket.in
+--- cups-1.5.2/data/cups.socket.in.systemd-socket	2012-03-16 14:50:57.150449788 +0000
++++ cups-1.5.2/data/cups.socket.in	2012-03-16 14:50:57.150449788 +0000
+@@ -0,0 +1,11 @@
++[Unit]
++Description=CUPS Printing Service Sockets
++
++[Socket]
++ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@
++ListenStream=631
++ListenDatagram=0.0.0.0:631
++BindIPv6Only=ipv6-only
++
++[Install]
++WantedBy=sockets.target
+diff -up cups-1.5.2/data/Makefile.systemd-socket cups-1.5.2/data/Makefile
+--- cups-1.5.2/data/Makefile.systemd-socket	2011-05-12 06:21:56.000000000 +0100
++++ cups-1.5.2/data/Makefile	2012-03-16 14:50:57.151449789 +0000
+@@ -112,6 +112,12 @@ install-data:
+ 		$(INSTALL_DATA) $$file $(DATADIR)/ppdc; \
+ 	done
+ 	$(INSTALL_DIR) -m 755 $(DATADIR)/profiles
++	if test "x$(SYSTEMD_UNITS)" != "x" ; then \
++		$(INSTALL_DIR) -m 755 $(SYSTEMDUNITDIR); \
++		for file in $(SYSTEMD_UNITS); do \
++			$(INSTALL_DATA) $$file $(SYSTEMDUNITDIR); \
++		done; \
++	fi
+ 
+ 
+ #
+@@ -159,6 +165,9 @@ uninstall:
+ 	-$(RMDIR) $(DATADIR)/charsets
+ 	-$(RMDIR) $(DATADIR)/banners
+ 	-$(RMDIR) $(DATADIR)
++	for file in $(SYSTEMD_UNITS); do \
++		$(RM) $(SYSTEMDUNITDIR)/$$file; \
++	done
+ 
+ 
+ #
+diff -up cups-1.5.2/Makedefs.in.systemd-socket cups-1.5.2/Makedefs.in
+--- cups-1.5.2/Makedefs.in.systemd-socket	2012-03-16 14:50:57.081449751 +0000
++++ cups-1.5.2/Makedefs.in	2012-03-16 14:50:57.152449790 +0000
+@@ -143,6 +143,7 @@ CXXFLAGS	=	@CPPFLAGS@ @CXXFLAGS@
+ CXXLIBS		=	@CXXLIBS@
+ DBUS_NOTIFIER	=	@DBUS_NOTIFIER@
+ DBUS_NOTIFIERLIBS =	@DBUS_NOTIFIERLIBS@
++SYSTEMD_UNITS   =       @SYSTEMD_UNITS@
+ DNSSD_BACKEND	=	@DNSSD_BACKEND@
+ DSOFLAGS	=	-L../cups @DSOFLAGS@
+ DSOLIBS		=	@DSOLIBS@ $(COMMONLIBS)
+@@ -151,6 +152,7 @@ FONTS		=	@FONTS@
+ IMGLIBS		=	@IMGLIBS@
+ IMGFILTERS	=	@IMGFILTERS@
+ LAUNCHDLIBS	=	@LAUNCHDLIBS@
++SDLIBS		=	@SDLIBS@
+ LDFLAGS		=	-L../cgi-bin -L../cups -L../filter -L../ppdc \
+ 			-L../scheduler @LDARCHFLAGS@ \
+ 			@LDFLAGS@ @RELROFLAGS@ @PIEFLAGS@ $(OPTIM)
+@@ -267,6 +269,7 @@ PAMFILE		=	@PAMFILE@
+ 
+ DEFAULT_LAUNCHD_CONF =	@DEFAULT_LAUNCHD_CONF@
+ DBUSDIR		=	@DBUSDIR@
++SYSTEMDUNITDIR  =       $(BUILDROOT)@systemdsystemunitdir@
+ 
+ 
+ #
+diff -up cups-1.5.2/scheduler/client.h.systemd-socket cups-1.5.2/scheduler/client.h
+--- cups-1.5.2/scheduler/client.h.systemd-socket	2011-03-25 21:25:38.000000000 +0000
++++ cups-1.5.2/scheduler/client.h	2012-03-16 14:50:57.153449791 +0000
+@@ -75,6 +75,9 @@ typedef struct
+   int			fd;		/* File descriptor for this server */
+   http_addr_t		address;	/* Bind address of socket */
+   http_encryption_t	encryption;	/* To encrypt or not to encrypt... */
++#ifdef HAVE_SYSTEMD
++  int			is_systemd;	/* Is this a systemd socket? */
++#endif /* HAVE_SYSTEMD */
+ } cupsd_listener_t;
+ 
+ 
+diff -up cups-1.5.2/scheduler/dirsvc.c.systemd-socket cups-1.5.2/scheduler/dirsvc.c
+--- cups-1.5.2/scheduler/dirsvc.c.systemd-socket	2012-03-16 14:50:57.112449768 +0000
++++ cups-1.5.2/scheduler/dirsvc.c	2012-03-16 14:50:57.155449792 +0000
+@@ -1512,7 +1512,7 @@ cupsdStartBrowsing(void)
+       }
+     }
+ 
+-    if (BrowseSocket >= 0)
++    if (BrowseSocket >= 0 && !BrowseSocketIsSystemd)
+     {
+      /*
+       * Bind the socket to browse port...
+@@ -1556,13 +1556,17 @@ cupsdStartBrowsing(void)
+ 	cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set broadcast mode - %s.",
+ 			strerror(errno));
+ 
++	if (!BrowseSocketIsSystemd)
++	{
+ #ifdef WIN32
+-	closesocket(BrowseSocket);
++	  closesocket(BrowseSocket);
+ #else
+-	close(BrowseSocket);
++	  close(BrowseSocket);
+ #endif /* WIN32 */
+ 
+-	BrowseSocket = -1;
++	  BrowseSocket = -1;
++	}
++
+ 	BrowseLocalProtocols &= ~BROWSE_CUPS;
+ 	BrowseRemoteProtocols &= ~BROWSE_CUPS;
+ 
+@@ -1885,15 +1889,22 @@ cupsdStopBrowsing(void)
+   if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) &&
+       BrowseSocket >= 0)
+   {
+-   /*
+-    * Close the socket and remove it from the input selection set.
+-    */
++    if (!BrowseSocketIsSystemd)
++    {
++     /*
++      * Close the socket.
++      */
+ 
+ #ifdef WIN32
+-    closesocket(BrowseSocket);
++      closesocket(BrowseSocket);
+ #else
+-    close(BrowseSocket);
++      close(BrowseSocket);
+ #endif /* WIN32 */
++    }
++
++   /*
++    * Remove it from the input selection set.
++    */
+ 
+     cupsdRemoveSelect(BrowseSocket);
+     BrowseSocket = -1;
+@@ -5693,11 +5704,14 @@ update_cups_browse(void)
+                       strerror(errno));
+       cupsdLogMessage(CUPSD_LOG_ERROR, "CUPS browsing turned off.");
+ 
++      if (!BrowseSocketIsSystemd)
++      {
+ #ifdef WIN32
+-      closesocket(BrowseSocket);
++	closesocket(BrowseSocket);
+ #else
+-      close(BrowseSocket);
++	close(BrowseSocket);
+ #endif /* WIN32 */
++      }
+ 
+       cupsdRemoveSelect(BrowseSocket);
+       BrowseSocket = -1;
+diff -up cups-1.5.2/scheduler/dirsvc.h.systemd-socket cups-1.5.2/scheduler/dirsvc.h
+--- cups-1.5.2/scheduler/dirsvc.h.systemd-socket	2012-03-16 14:50:57.113449769 +0000
++++ cups-1.5.2/scheduler/dirsvc.h	2012-03-16 14:50:57.157449792 +0000
+@@ -100,6 +100,8 @@ VAR int			Browsing	VALUE(TRUE),
+ 					/* Short names for remote printers? */
+ 			BrowseSocket	VALUE(-1),
+ 					/* Socket for browsing */
++			BrowseSocketIsSystemd	VALUE(0),
++					/* BrowseSocket is systemd-provided? */
+ 			BrowsePort	VALUE(IPP_PORT),
+ 					/* Port number for broadcasts */
+ 			BrowseInterval	VALUE(DEFAULT_INTERVAL),
+diff -up cups-1.5.2/scheduler/listen.c.systemd-socket cups-1.5.2/scheduler/listen.c
+--- cups-1.5.2/scheduler/listen.c.systemd-socket	2011-04-16 00:38:13.000000000 +0100
++++ cups-1.5.2/scheduler/listen.c	2012-03-16 14:50:57.158449792 +0000
+@@ -401,7 +401,11 @@ cupsdStopListening(void)
+        lis;
+        lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+   {
+-    if (lis->fd != -1)
++    if (lis->fd != -1
++#ifdef HAVE_SYSTEMD
++        && !lis->is_systemd
++#endif /* HAVE_SYSTEMD */
++        )
+     {
+ #ifdef WIN32
+       closesocket(lis->fd);
+diff -up cups-1.5.2/scheduler/main.c.systemd-socket cups-1.5.2/scheduler/main.c
+--- cups-1.5.2/scheduler/main.c.systemd-socket	2012-03-16 14:50:57.121449773 +0000
++++ cups-1.5.2/scheduler/main.c	2012-03-16 14:51:55.409483636 +0000
+@@ -26,6 +26,8 @@
+  *   launchd_checkin()     - Check-in with launchd and collect the listening
+  *                           fds.
+  *   launchd_checkout()    - Update the launchd KeepAlive file as needed.
++ *   systemd_checkin()     - Check-in with systemd and collect the
++ *                           listening fds.
+  *   parent_handler()      - Catch USR1/CHLD signals...
+  *   process_children()    - Process all dead children...
+  *   select_timeout()      - Calculate the select timeout value.
+@@ -62,6 +64,10 @@
+ #  endif /* !LAUNCH_JOBKEY_SERVICEIPC */
+ #endif /* HAVE_LAUNCH_H */
+ 
++#ifdef HAVE_SYSTEMD
++#include <systemd/sd-daemon.h>
++#endif /* HAVE_SYSTEMD */
++
+ #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
+ #  include <malloc.h>
+ #endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
+@@ -78,6 +84,9 @@
+ static void		launchd_checkin(void);
+ static void		launchd_checkout(void);
+ #endif /* HAVE_LAUNCHD */
++#ifdef HAVE_SYSTEMD
++static void		systemd_checkin(void);
++#endif /* HAVE_SYSTEMD */
+ static void		parent_handler(int sig);
+ static void		process_children(void);
+ static void		sigchld_handler(int sig);
+@@ -537,6 +546,13 @@ main(int  argc,				/* I - Number of comm
+   }
+ #endif /* HAVE_LAUNCHD */
+ 
++#ifdef HAVE_SYSTEMD
++ /*
++  * If we were started by systemd get the listen sockets file descriptors...
++  */
++  systemd_checkin();
++#endif /* HAVE_SYSTEMD */
++
+  /*
+   * Startup the server...
+   */
+@@ -759,6 +775,15 @@ main(int  argc,				/* I - Number of comm
+ 	}
+ #endif /* HAVE_LAUNCHD */
+ 
++#ifdef HAVE_SYSTEMD
++       /*
++	* If we were started by systemd get the listen sockets file
++	* descriptors...
++        */
++
++        systemd_checkin();
++#endif /* HAVE_SYSTEMD */
++
+        /*
+         * Startup the server...
+         */
+@@ -1584,6 +1609,139 @@ launchd_checkout(void)
+ }
+ #endif /* HAVE_LAUNCHD */
+ 
++#ifdef HAVE_SYSTEMD
++static void
++systemd_checkin(void)
++{
++  int n, fd;
++
++  n = sd_listen_fds(0);
++  if (n < 0)
++  {
++    cupsdLogMessage(CUPSD_LOG_ERROR,
++           "systemd_checkin: Failed to acquire sockets from systemd - %s",
++           strerror(-n));
++    exit(EXIT_FAILURE);
++    return;
++  }
++
++  if (n == 0)
++    return;
++
++  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
++  {
++    http_addr_t addr;
++    socklen_t addrlen = sizeof (addr);
++    int r;
++    cupsd_listener_t *lis;
++    char s[256];
++
++    r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1);
++    if (r < 0)
++    {
++      cupsdLogMessage(CUPSD_LOG_ERROR,
++             "systemd_checkin: Unable to verify socket type - %s",
++             strerror(-r));
++      continue;
++    }
++
++    if (!r)
++    {
++      if (Browsing &&
++	  ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS))
++      {
++	r = sd_is_socket(fd, AF_UNSPEC, SOCK_DGRAM, 0);
++	if (r < 0)
++	{
++	  cupsdLogMessage(CUPSD_LOG_ERROR,
++			  "systemd_checkin: Unable to verify socket type - %s",
++			  strerror(-r));
++	  continue;
++	}
++
++	if (r)
++	{
++	 /*
++	  * This is the browse socket.
++	  */
++
++	  char addrstr[256];
++	  if (getsockname(fd, (struct sockaddr*) &addr, &addrlen))
++	  {
++	    cupsdLogMessage(CUPSD_LOG_ERROR,
++			    "systemd_checkin: Unable to get local address - %s",
++			    strerror(errno));
++	    continue;
++	  }
++
++	  httpAddrString (&addr, addrstr, sizeof (addrstr));
++	  BrowseSocket = fd;
++	  BrowseSocketIsSystemd = 1;
++	  cupsdLogMessage(CUPSD_LOG_DEBUG,
++			  "systemd_checkin: Matched browse (port %d) with fd %d:%s...",
++			  BrowsePort, fd, addrstr);
++	  continue;
++	}
++
++      }
++      cupsdLogMessage(CUPSD_LOG_ERROR,
++             "systemd_checkin: Socket not of the right type");
++      continue;
++    }
++
++    if (getsockname(fd, (struct sockaddr*) &addr, &addrlen))
++    {
++      cupsdLogMessage(CUPSD_LOG_ERROR,
++             "systemd_checkin: Unable to get local address - %s",
++             strerror(errno));
++      continue;
++    }
++
++   /*
++    * Try to match the systemd socket address to one of the listeners...
++    */
++
++    for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
++       lis;
++       lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
++      if (httpAddrEqual(&lis->address, &addr))
++	break;
++
++    if (lis)
++    {
++      cupsdLogMessage(CUPSD_LOG_DEBUG,
++                      "systemd_checkin: Matched existing listener %s with fd %d...",
++                      httpAddrString(&(lis->address), s, sizeof(s)), fd);
++    }
++    else
++    {
++      cupsdLogMessage(CUPSD_LOG_DEBUG,
++                      "systemd_checkin: Adding new listener %s with fd %d...",
++                      httpAddrString(&addr, s, sizeof(s)), fd);
++
++      if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
++      {
++        cupsdLogMessage(CUPSD_LOG_ERROR,
++                        "systemd_checkin: Unable to allocate listener - "
++                        "%s.", strerror(errno));
++        exit(EXIT_FAILURE);
++      }
++
++      cupsArrayAdd(Listeners, lis);
++
++      memcpy(&lis->address, &addr, sizeof(lis->address));
++    }
++
++    lis->fd = fd;
++    lis->is_systemd = 1;
++
++#  ifdef HAVE_SSL
++    if (_httpAddrPort(&(lis->address)) == 443)
++      lis->encryption = HTTP_ENCRYPT_ALWAYS;
++#  endif /* HAVE_SSL */
++  }
++}
++#endif /* HAVE_SYSTEMD */
+ 
+ /*
+  * 'parent_handler()' - Catch USR1/CHLD signals...
+diff -up cups-1.5.2/scheduler/Makefile.systemd-socket cups-1.5.2/scheduler/Makefile
+--- cups-1.5.2/scheduler/Makefile.systemd-socket	2012-03-16 14:50:57.130449778 +0000
++++ cups-1.5.2/scheduler/Makefile	2012-03-16 14:50:57.160449794 +0000
+@@ -382,7 +382,7 @@ cupsd:	$(CUPSDOBJS) $(LIBCUPSMIME) ../cu
+ 	$(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) -L. -lcupsmime \
+ 		$(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
+ 		$(LIBPAPER) $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBS) \
+-		$(LIBGSSAPI) $(LIBWRAP)
++		$(LIBGSSAPI) $(LIBWRAP) $(SDLIBS)
+ 
+ cupsd-static:	$(CUPSDOBJS) libcupsmime.a ../cups/$(LIBCUPSSTATIC)
+ 	echo Linking $@...
+@@ -390,7 +390,7 @@ cupsd-static:	$(CUPSDOBJS) libcupsmime.a
+ 		$(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
+ 		../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \
+ 		$(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \
+-		$(LIBWRAP)
++		$(LIBWRAP) $(SDLIBS)
+ 
+ 
+ #
diff --git a/srcpkgs/cups/patches/cups-uri-compat.patch b/srcpkgs/cups/patches/cups-uri-compat.patch
new file mode 100644
index 0000000000..2520a5bec6
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-uri-compat.patch
@@ -0,0 +1,51 @@
+diff -up cups-1.5b1/backend/usb-unix.c.uri-compat cups-1.5b1/backend/usb-unix.c
+--- cups-1.5b1/backend/usb-unix.c.uri-compat	2011-05-24 15:59:05.000000000 +0200
++++ cups-1.5b1/backend/usb-unix.c	2011-05-24 16:02:03.000000000 +0200
+@@ -63,11 +63,34 @@ print_device(const char *uri,		/* I - De
+   int		device_fd;		/* USB device */
+   ssize_t	tbytes;			/* Total number of bytes written */
+   struct termios opts;			/* Parallel port options */
++  char		*fixed_uri = strdup (uri);
++  char		*p;
+ 
+ 
+   (void)argc;
+   (void)argv;
+ 
++  p = strchr (fixed_uri, ':');
++  if (p++ != NULL)
++  {
++    char *e;
++    p += strspn (p, "/");
++    e = strchr (p, '/');
++    if (e > p)
++    {
++      size_t mfrlen = e - p;
++      e++;
++      if (!strncasecmp (e, p, mfrlen))
++      {
++	char *x = e + mfrlen;
++	if (!strncmp (x, "%20", 3))
++	  /* Take mfr name out of mdl name for compatibility with
++	   * Fedora 11 before bug #507244 was fixed. */
++	  strcpy (e, x + 3); puts(fixed_uri);
++      }
++    }
++  }
++
+  /*
+   * Open the USB port device...
+   */
+@@ -107,10 +130,10 @@ print_device(const char *uri,		/* I - De
+              _cups_strncasecmp(hostname, "Minolta", 7);
+ #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */
+ 
+-    if (use_bc && !strncmp(uri, "usb:/dev/", 9))
++    if (use_bc && !strncmp(fixed_uri, "usb:/dev/", 9))
+       use_bc = 0;
+ 
+-    if ((device_fd = open_device(uri, &use_bc)) == -1)
++    if ((device_fd = open_device(fixed_uri, &use_bc)) == -1)
+     {
+       if (getenv("CLASS") != NULL)
+       {
diff --git a/srcpkgs/cups/patches/cups-usb-paperout.patch b/srcpkgs/cups/patches/cups-usb-paperout.patch
new file mode 100644
index 0000000000..f1f73f0a32
--- /dev/null
+++ b/srcpkgs/cups/patches/cups-usb-paperout.patch
@@ -0,0 +1,52 @@
+diff -up cups-1.5b1/backend/usb-unix.c.usb-paperout cups-1.5b1/backend/usb-unix.c
+--- cups-1.5b1/backend/usb-unix.c.usb-paperout	2011-05-24 15:51:39.000000000 +0200
++++ cups-1.5b1/backend/usb-unix.c	2011-05-24 15:51:39.000000000 +0200
+@@ -30,6 +30,11 @@
+ 
+ #include <sys/select.h>
+ 
++#ifdef __linux
++#include <sys/ioctl.h>
++#include <linux/lp.h>
++#endif /* __linux */
++
+ 
+ /*
+  * Local functions...
+@@ -334,7 +339,19 @@ open_device(const char *uri,		/* I - Dev
+   if (!strncmp(uri, "usb:/dev/", 9))
+ #ifdef __linux
+   {
+-    return (open(uri + 4, O_RDWR | O_EXCL));
++    fd = open(uri + 4, O_RDWR | O_EXCL);
++
++    if (fd != -1)
++    {
++     /*
++      * Tell the driver to return from write() with errno==ENOSPACE
++      * on paper-out.
++      */
++      unsigned int t = 1;
++      ioctl (fd, LPABORT, &t);
++    }
++
++    return fd;
+   }
+   else if (!strncmp(uri, "usb://", 6))
+   {
+@@ -400,7 +417,14 @@ open_device(const char *uri,		/* I - Dev
+         if (!strcmp(uri, device_uri))
+ 	{
+ 	 /*
+-	  * Yes, return this file descriptor...
++	  * Yes, tell the driver to return from write() with
++	  * errno==ENOSPACE on paper-out.
++	  */
++	  unsigned int t = 1;
++	  ioctl (fd, LPABORT, &t);
++
++	 /*
++	  * Return this file descriptor...
+ 	  */
+ 
+ 	  fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n",
diff --git a/srcpkgs/cups/template b/srcpkgs/cups/template
new file mode 100644
index 0000000000..c4453b9a13
--- /dev/null
+++ b/srcpkgs/cups/template
@@ -0,0 +1,93 @@
+# Template file for 'cups'
+pkgname=cups
+version=1.5.3
+patch_args="-Np1"
+homepage="http://www.cups.org/"
+license="GPL-2"
+distfiles="ftp://ftp.easysw.com/pub/cups/${version}/cups-${version}-source.tar.bz2"
+short_desc="Common Unix Printing System"
+maintainer="Juan RP <xtraeme@gmail.com>"
+checksum=9d716a8ffcefdaff1c37f4a4b590f1d74ff9ff72383a18f3c883c9235907f93d
+long_desc="
+ The Common UNIX Printing System (or CUPS(tm)) is a printing system and general
+ replacement for lpd and the like. It supports the Internet Printing Protocol
+ (IPP), and has its own filtering driver model for handling various document types."
+
+make_dirs="
+/var/cache/cups/rss 	0750 root root
+/var/run/cups/certs 	0750 root root
+/var/log/cups 		0750 root root
+/var/spool/cups/tmp 	0750 root root
+/etc/cups/ssl 		0700 root lp"
+
+systemd_services="cups.service on"
+gtk_iconcache_dirs="/usr/share/icons/hicolor"
+
+conf_files="
+/etc/cups/cups.conf
+/etc/cups/snmp.conf
+/etc/cups/printers.conf
+/etc/cups/classes.conf
+/etc/cups/client.conf
+/etc/cups/subscriptions.conf
+/etc/dbus-1/system.d/cups.conf
+/etc/logrotate.d/cups
+/etc/pam.d/cups"
+
+subpackages="libcups cups-devel"
+
+Add_dependency build automake
+Add_dependency build acl-devel
+Add_dependency build jpeg-devel
+Add_dependency build libpng-devel
+Add_dependency build tiff-devel
+Add_dependency build openssl-devel
+Add_dependency build pam-devel
+Add_dependency build mit-krb5-devel
+Add_dependency build poppler-devel
+Add_dependency build libusb-devel
+Add_dependency build avahi-libs-devel
+Add_dependency build systemd-devel
+
+pre_configure() {
+	aclocal -I config-scripts
+	autoconf -I config-scripts
+}
+
+do_configure() {
+	./configure ${CONFIGURE_SHARED_ARGS} --libdir=/usr/lib \
+		--enable-acl --enable-dbus --enable-raw-printing \
+		--disable-gnutls --enable-threads --with-logdir=/var/log/cups \
+		--with-docdir=/usr/share/cups/doc --with-cups-user=daemon \
+		--with-cups-group=lp --enable-pam=yes --disable-ldap \
+		--enable-avahi --enable-pam --enable-ssl \
+		--with-systemdsystemunitdir=/lib/systemd/system
+}
+
+do_build() {
+	make ${makejobs}
+}
+
+do_install() {
+	make BUILDROOT=${DESTDIR} install
+	# Remove sysvinit scripts.
+	rm -rf ${DESTDIR}/etc/rc.d
+	# Serial backend needs to run as root (Fedora bug #212577).
+	chmod 700 ${DESTDIR}/usr/lib/cups/backend/serial
+	# compress some driver files, adopted from Fedora
+	find ${DESTDIR}/usr/share/cups/model -name "*.ppd"|xargs gzip -n9f
+	# install some more configuration files that will get filled by cupsd
+	for f in printers classes client subscriptions; do
+		touch ${DESTDIR}/etc/cups/${f}.conf
+	done
+	echo "# see 'man client.conf'" >> ${DESTDIR}/etc/cups/client.conf
+	echo "ServerName /var/run/cups/cups.sock" >> ${DESTDIR}/etc/cups/client.conf
+	echo "# alternative: ServerName hostname-or-ip-address[:port] of a remote server" >> \
+		${DESTDIR}/etc/cups/client.conf
+	# fix .desktop file
+	sed -i 's|^Exec=htmlview http://localhost:631/|Exec=xdg-open http://localhost:631/|g' \
+		${DESTDIR}/usr/share/applications/cups.desktop
+	# Install pam and logrotate files.
+	vinstall ${FILESDIR}/cups.pam 644 etc/pam.d cups
+	vinstall ${FILESDIR}/cups.logrotate 644 etc/logrotate.d cups
+}
diff --git a/srcpkgs/libcups b/srcpkgs/libcups
new file mode 120000
index 0000000000..a1fadc2f3a
--- /dev/null
+++ b/srcpkgs/libcups
@@ -0,0 +1 @@
+cups
\ No newline at end of file