diff --git a/cups-avahi.patch b/cups-avahi.patch index cf1056a..b1fc75c 100644 --- a/cups-avahi.patch +++ b/cups-avahi.patch @@ -1,15 +1,29 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c ---- cups-1.4.5/backend/dnssd.c.avahi 2009-08-08 00:27:12.000000000 +0200 -+++ cups-1.4.5/backend/dnssd.c 2010-11-12 13:13:31.000000000 +0100 -@@ -22,6 +22,7 @@ +--- cups-1.4.5/backend/dnssd.c.avahi 2010-12-24 13:11:33.760461375 +0000 ++++ cups-1.4.5/backend/dnssd.c 2010-12-24 13:11:38.325341226 +0000 +@@ -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. -+* find_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 +34,18 @@ + */ +@@ -33,7 +40,18 @@ #include "backend-private.h" #include @@ -29,7 +43,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c /* -@@ -52,7 +64,12 @@ typedef enum +@@ -52,7 +70,12 @@ typedef enum typedef struct { @@ -42,7 +56,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c char *name, /* Service name */ *domain, /* Domain name */ *fullName, /* Full name */ -@@ -64,6 +81,20 @@ typedef struct +@@ -64,6 +87,20 @@ typedef struct sent; /* Did we list the device? */ } cups_device_t; @@ -63,7 +77,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c /* * Local globals... -@@ -77,6 +108,7 @@ static int job_canceled = 0; +@@ -77,6 +114,7 @@ static int job_canceled = 0; * Local functions... */ @@ -71,7 +85,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c static void browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, -@@ -92,12 +124,6 @@ static void browse_local_callback(DNSSe +@@ -92,12 +130,6 @@ static void browse_local_callback(DNSSe const char *regtype, const char *replyDomain, void *context); @@ -84,7 +98,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c static void query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, -@@ -106,9 +132,111 @@ static void query_callback(DNSServiceRe +@@ -106,9 +138,118 @@ static void query_callback(DNSServiceRe uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context); @@ -123,8 +137,9 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + + +/* -+ * cups_txt_records_t access functions ++ * '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) +{ @@ -139,6 +154,11 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + 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) +{ @@ -193,10 +213,11 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + + return 0; +} ++ /* * 'main()' - Browse for printers. -@@ -119,6 +247,13 @@ main(int argc, /* I - Number of comm +@@ -119,6 +260,13 @@ main(int argc, /* I - Number of comm char *argv[]) /* I - Command-line arguments */ { const char *name; /* Backend name */ @@ -210,7 +231,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c DNSServiceRef main_ref, /* Main service reference */ fax_ipp_ref, /* IPP fax service reference */ ipp_ref, /* IPP service reference */ -@@ -130,12 +265,11 @@ main(int argc, /* I - Number of comm +@@ -130,12 +278,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 */ @@ -228,7 +249,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ -@@ -194,6 +328,49 @@ main(int argc, /* I - Number of comm +@@ -194,6 +341,49 @@ main(int argc, /* I - Number of comm * Browse for different kinds of printers... */ @@ -278,7 +299,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError) { perror("ERROR: Unable to create service connection"); -@@ -245,6 +422,7 @@ main(int argc, /* I - Number of comm +@@ -245,6 +435,7 @@ main(int argc, /* I - Number of comm riousbprint_ref = main_ref; DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0, "_riousbprint._tcp", NULL, browse_callback, devices); @@ -286,7 +307,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c /* * Loop until we are killed... -@@ -252,6 +430,9 @@ main(int argc, /* I - Number of comm +@@ -252,6 +443,9 @@ main(int argc, /* I - Number of comm while (!job_canceled) { @@ -296,7 +317,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c FD_ZERO(&input); FD_SET(fd, &input); -@@ -271,11 +452,35 @@ main(int argc, /* I - Number of comm +@@ -271,11 +465,35 @@ main(int argc, /* I - Number of comm } else { @@ -332,7 +353,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c cups_device_t *best; /* Best matching device */ char device_uri[1024]; /* Device URI */ int count; /* Number of queries */ -@@ -285,6 +490,7 @@ main(int argc, /* I - Number of comm +@@ -285,6 +503,7 @@ main(int argc, /* I - Number of comm best = NULL, count = 0; device; device = (cups_device_t *)cupsArrayNext(devices)) @@ -340,7 +361,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c if (!device->ref && !device->sent) { /* -@@ -313,14 +519,23 @@ main(int argc, /* I - Number of comm +@@ -313,14 +532,23 @@ main(int argc, /* I - Number of comm count ++; } } @@ -365,30 +386,15 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c if (!best) best = device; -@@ -372,6 +587,7 @@ main(int argc, /* I - Number of comm - * 'browse_callback()' - Browse devices. - */ - -+#ifdef HAVE_DNSSD - static void - browse_callback( - DNSServiceRef sdRef, /* I - Service reference */ -@@ -405,12 +621,14 @@ browse_callback( - - get_device((cups_array_t *)context, serviceName, regtype, replyDomain); +@@ -368,6 +596,7 @@ main(int argc, /* I - Number of comm } -+#endif /* HAVE_DNSSD */ ++#ifdef HAVE_DNSSD /* - * 'browse_local_callback()' - Browse local devices. + * 'browse_callback()' - Browse devices. */ - -+#ifdef HAVE_DNSSD - static void - browse_local_callback( - DNSServiceRef sdRef, /* I - Service reference */ -@@ -456,6 +674,7 @@ browse_local_callback( +@@ -456,6 +685,7 @@ browse_local_callback( device->fullName); device->sent = 1; } @@ -396,10 +402,13 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c /* -@@ -528,6 +747,32 @@ exec_backend(char **argv) /* I - Comman - exit(CUPS_BACKEND_STOP); - } +@@ -530,6 +760,37 @@ exec_backend(char **argv) /* I - Comman + + /* ++ * 'device_type()' - Get DNS-SD type enumeration from string. ++ */ ++ +static int +device_type (const char *regtype) +{ @@ -426,10 +435,12 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + return (CUPS_DEVICE_RIOUSBPRINT); +} + - - /* ++ ++/* * 'get_device()' - Create or update a device. -@@ -550,18 +795,7 @@ get_device(cups_array_t *devices, /* I - + */ + +@@ -550,18 +811,7 @@ get_device(cups_array_t *devices, /* I - */ key.name = (char *)serviceName; @@ -449,7 +460,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c for (device = cupsArrayFind(devices, &key); device; -@@ -581,8 +815,14 @@ get_device(cups_array_t *devices, /* I - +@@ -581,8 +831,14 @@ get_device(cups_array_t *devices, /* I - free(device->domain); device->domain = strdup(replyDomain); @@ -464,7 +475,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c free(device->fullName); device->fullName = strdup(fullName); } -@@ -602,6 +842,9 @@ get_device(cups_array_t *devices, /* I - +@@ -602,6 +858,9 @@ get_device(cups_array_t *devices, /* I - device->domain = strdup(replyDomain); device->type = key.type; device->priority = 50; @@ -474,7 +485,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c cupsArrayAdd(devices, device); -@@ -609,7 +852,13 @@ get_device(cups_array_t *devices, /* I - +@@ -609,13 +868,20 @@ get_device(cups_array_t *devices, /* I - * Set the "full name" of this service, which is used for queries... */ @@ -488,15 +499,14 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c device->fullName = strdup(fullName); return (device); -@@ -620,6 +869,7 @@ get_device(cups_array_t *devices, /* I - - * 'query_callback()' - Process query data. - */ + } + +#ifdef HAVE_DNSSD - static void - query_callback( - DNSServiceRef sdRef, /* I - Service reference */ -@@ -639,7 +889,7 @@ query_callback( + /* + * 'query_callback()' - Process query data. + */ +@@ -639,7 +905,7 @@ query_callback( *ptr; /* Pointer into string */ cups_device_t dkey, /* Search key */ *device; /* Device */ @@ -505,7 +515,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, " "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", " -@@ -673,84 +923,212 @@ query_callback( +@@ -673,84 +939,232 @@ query_callback( if ((ptr = strstr(name, "._")) != NULL) *ptr = '\0'; @@ -528,7 +538,12 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c +} +#endif /* HAVE_DNSSD */ + ++ +#ifdef HAVE_AVAHI ++/* ++ * 'avahi_client_callback()' - Avahi client callback function. ++ */ ++ +static void +avahi_client_callback(AvahiClient *client, + AvahiClientState state, @@ -545,6 +560,11 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + } +} + ++ ++/* ++ * 'avahi_query_callback()' - Avahi query callback function. ++ */ ++ +static void +avahi_query_callback(AvahiServiceResolver *resolver, + AvahiIfIndex interface, @@ -614,6 +634,11 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + avahi_service_resolver_free (resolver); +} + ++ ++/* ++ * 'avahi_browse_callback()' - Avahi browse callback function. ++ */ ++ +static void +avahi_browse_callback(AvahiServiceBrowser *browser, + AvahiIfIndex interface, @@ -626,7 +651,8 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + void *context) +{ + AvahiClient *client = avahi_service_browser_get_client (browser); -+ + +- for (device = cupsArrayFind(devices, &dkey); + switch (event) + { + case AVAHI_BROWSER_FAILURE: @@ -671,16 +697,20 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c + } + + break; - -- for (device = cupsArrayFind(devices, &dkey); ++ + 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, @@ -743,11 +773,11 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c - - if (!datalen || (data + datalen) >= dataend) - break; -- -- datanext = data + datalen; + char *key; + char *value; +- datanext = data + datalen; +- - for (ptr = key; data < datanext && *data != '='; data ++) - *ptr++ = *data; - *ptr = '\0'; @@ -770,7 +800,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c if (!strncasecmp(key, "usb_", 4)) { /* -@@ -805,6 +1183,10 @@ query_callback( +@@ -805,6 +1219,10 @@ query_callback( if (device->type == CUPS_DEVICE_PRINTER) device->sent = 1; } @@ -781,7 +811,7 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c } if (device->device_id) -@@ -854,11 +1236,9 @@ query_callback( +@@ -861,11 +1279,9 @@ query_callback( } } @@ -795,8 +825,8 @@ diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c * 'sigterm_handler()' - Handle termination signals... */ diff -up cups-1.4.5/config.h.in.avahi cups-1.4.5/config.h.in ---- cups-1.4.5/config.h.in.avahi 2010-08-13 06:11:46.000000000 +0200 -+++ cups-1.4.5/config.h.in 2010-11-12 13:13:31.000000000 +0100 +--- cups-1.4.5/config.h.in.avahi 2010-08-13 05:11:46.000000000 +0100 ++++ cups-1.4.5/config.h.in 2010-12-24 13:11:38.327341170 +0000 @@ -344,6 +344,13 @@ @@ -812,8 +842,8 @@ diff -up cups-1.4.5/config.h.in.avahi cups-1.4.5/config.h.in */ diff -up cups-1.4.5/config-scripts/cups-dnssd.m4.avahi cups-1.4.5/config-scripts/cups-dnssd.m4 ---- cups-1.4.5/config-scripts/cups-dnssd.m4.avahi 2009-08-29 00:54:34.000000000 +0200 -+++ cups-1.4.5/config-scripts/cups-dnssd.m4 2010-11-12 13:13:31.000000000 +0100 +--- cups-1.4.5/config-scripts/cups-dnssd.m4.avahi 2009-08-28 23:54:34.000000000 +0100 ++++ cups-1.4.5/config-scripts/cups-dnssd.m4 2010-12-24 13:11:38.326341199 +0000 @@ -27,6 +27,21 @@ AC_ARG_WITH(dnssd-includes, [ --with-dn DNSSDLIBS="" DNSSD_BACKEND="" @@ -837,9 +867,20 @@ diff -up cups-1.4.5/config-scripts/cups-dnssd.m4.avahi cups-1.4.5/config-scripts AC_CHECK_HEADER(dns_sd.h, [ case "$uname" in diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c ---- cups-1.4.5/cups/http-support.c.avahi 2010-10-02 00:40:38.000000000 +0200 -+++ cups-1.4.5/cups/http-support.c 2010-11-12 13:28:45.000000000 +0100 -@@ -55,6 +55,11 @@ +--- cups-1.4.5/cups/http-support.c.avahi 2010-10-01 23:40:38.000000000 +0100 ++++ cups-1.4.5/cups/http-support.c 2010-12-24 13:11:38.330341093 +0000 +@@ -41,6 +41,10 @@ + * http_copy_decode() - Copy and decode a URI. + * http_copy_encode() - Copy and encode a URI. + * resolve_callback() - 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. + */ + + /* +@@ -55,6 +59,11 @@ # include # include #endif /* HAVE_DNSSD */ @@ -851,7 +892,7 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c /* -@@ -121,6 +126,24 @@ static void resolve_callback(DNSService +@@ -121,6 +130,24 @@ static void resolve_callback(DNSService void *context); #endif /* HAVE_DNSSD */ @@ -876,7 +917,7 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c /* * 'httpAssembleURI()' - Assemble a uniform resource identifier from its -@@ -1351,16 +1374,27 @@ _httpResolveURI( +@@ -1351,6 +1378,9 @@ _httpResolveURI( if (strstr(hostname, "._tcp")) { @@ -886,11 +927,8 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c #ifdef HAVE_DNSSD DNSServiceRef ref, /* DNS-SD master service reference */ domainref, /* DNS-SD service reference for domain */ - localref; /* DNS-SD service reference for .local */ - int domainsent = 0, /* Send the domain resolve? */ - offline = 0; /* offline-report state set? */ -- char *regtype, /* Pointer to type in hostname */ -- *domain; /* Pointer to domain in hostname */ +@@ -1361,6 +1391,16 @@ _httpResolveURI( + *domain; /* Pointer to domain in hostname */ _http_uribuf_t uribuf; /* URI buffer */ struct pollfd polldata; /* Polling data */ +#else /* HAVE_AVAHI */ @@ -906,7 +944,7 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c if (logit) -@@ -1398,8 +1432,13 @@ _httpResolveURI( +@@ -1398,8 +1438,13 @@ _httpResolveURI( if (domain) *domain++ = '\0'; @@ -920,7 +958,7 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c resolved_uri[0] = '\0'; -@@ -1414,6 +1453,7 @@ _httpResolveURI( +@@ -1414,6 +1459,7 @@ _httpResolveURI( uri = NULL; @@ -928,7 +966,7 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError) { localref = ref; -@@ -1500,6 +1540,36 @@ _httpResolveURI( +@@ -1500,6 +1546,36 @@ _httpResolveURI( DNSServiceRefDeallocate(ref); } @@ -965,7 +1003,7 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c if (logit) { -@@ -1511,13 +1581,13 @@ _httpResolveURI( +@@ -1511,13 +1587,13 @@ _httpResolveURI( fputs("STATE: -connecting-to-device,offline-report\n", stderr); } @@ -981,11 +1019,15 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c if (logit && !uri) _cupsLangPuts(stderr, _("Unable to find printer!\n")); -@@ -1722,6 +1792,105 @@ resolve_callback( - } +@@ -1723,6 +1799,116 @@ resolve_callback( #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, @@ -1002,6 +1044,12 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c + 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, @@ -1084,6 +1132,2207 @@ diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c +} +#endif /* HAVE_AVAHI */ + - ++ /* * End of "$Id: http-support.c 9322 2010-10-01 22:40:38Z mike $". + */ +diff -up cups-1.4.5/scheduler/avahi.c.avahi cups-1.4.5/scheduler/avahi.c +--- cups-1.4.5/scheduler/avahi.c.avahi 2010-12-24 13:11:38.333341014 +0000 ++++ cups-1.4.5/scheduler/avahi.c 2010-12-24 13:11:38.333341014 +0000 +@@ -0,0 +1,441 @@ ++/* ++ * "$Id$" ++ * ++ * Avahi poll implementation for the CUPS scheduler. ++ * ++ * Copyright (C) 2010 Red Hat, Inc. ++ * Authors: ++ * Tim Waugh ++ * ++ * Distribution and use rights are outlined in the file "LICENSE.txt" ++ * "LICENSE" which should have been included with this file. If this ++ * file is missing or damaged, see the license at "http://www.cups.org/". ++ * ++ * 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 ++ * compare_timeouts() - Compare timeouts 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 ++ ++#ifdef HAVE_AVAHI /* Applies to entire file... */ ++ ++/* ++ * Include necessary headers... ++ */ ++ ++#include "cupsd.h" ++ ++#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) ++# include ++#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ ++ ++#ifdef HAVE_AVAHI ++# include ++#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); ++static int compare_watches(AvahiWatch *p0, ++ AvahiWatch *p1); ++ ++ ++/* ++ * '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; ++ ++ for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); ++ watch; ++ watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) { ++ 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 (read_cb || write_cb); ++} ++ ++/* ++ * '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) ++ return (NULL); ++ ++ watched_fd->fd = fd; ++ watched_fd->occurred = 0; ++ watched_fd->watches = cupsArrayNew ((cups_array_func_t)compare_watches, ++ NULL); ++ } ++ ++ 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); ++} ++ ++ ++/* ++ * 'compare_watches' - Compare watches for array sorting ++ */ ++ ++static int ++compare_watches (AvahiWatch *p0, ++ AvahiWatch *p1) ++{ ++ if (p0->watched_fd->fd < p1->watched_fd->fd) ++ return (-1); ++ ++ return ((p0->watched_fd->fd == p1->watched_fd->fd) ? 0 : 1); ++} ++ ++ ++/* ++ * '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) ++{ ++ if (p0->fd != p1->fd) ++ return (p0->fd < p1->fd ? -1 : 1); ++ ++ if (p0 == p1) ++ return (0); ++ ++ return (p0 < p1 ? -1 : 1); ++} ++ ++ ++/* ++ * 'compare_timeouts' - Compare timeouts for array sorting ++ */ ++static int ++compare_timeouts(AvahiTimeout *p0, ++ AvahiTimeout *p1) ++{ ++ /* ++ * Just compare pointers to make it a stable sort. ++ */ ++ ++ if (p0->cupsd_timeout < p1->cupsd_timeout) ++ return (-1); ++ return ((p0->cupsd_timeout == p1->cupsd_timeout) ? 0 : 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 ((cups_array_func_t)compare_timeouts, ++ 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.4.5/scheduler/avahi.h.avahi cups-1.4.5/scheduler/avahi.h +--- cups-1.4.5/scheduler/avahi.h.avahi 2010-12-24 13:11:38.334340988 +0000 ++++ cups-1.4.5/scheduler/avahi.h 2010-12-24 13:11:38.334340988 +0000 +@@ -0,0 +1,49 @@ ++/* ++ * "$Id$" ++ * ++ * Avahi poll implementation for the CUPS scheduler. ++ * ++ * Copyright (C) 2010 Red Hat, Inc. ++ * Authors: ++ * Tim Waugh ++ * ++ * Distribution and use rights are outlined in the file "LICENSE.txt" ++ * which should have been included with this file. If this file is ++ * file is missing or damaged, see the license at "http://www.cups.org/". ++ */ ++ ++#include ++ ++#ifdef HAVE_AVAHI ++# include ++# include ++#endif /* HAVE_AVAHI */ ++ ++#ifdef HAVE_AUTHORIZATION_H ++# include ++#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.4.5/scheduler/cupsd.h.avahi cups-1.4.5/scheduler/cupsd.h +--- cups-1.4.5/scheduler/cupsd.h.avahi 2010-09-21 23:34:57.000000000 +0100 ++++ cups-1.4.5/scheduler/cupsd.h 2010-12-24 13:11:38.335340961 +0000 +@@ -147,6 +147,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... +@@ -188,6 +197,9 @@ VAR PSQUpdateQuotaProcPtr PSQUpdateQuota + /* Apple PrintService quota function */ + #endif /* __APPLE__ && HAVE_DLFCN_H */ + ++#ifdef HAVE_AVAHI ++VAR cups_array_t *Timeouts; /* Timed callbacks for main loop */ ++#endif /* HAVE_AVAHI */ + + + +@@ -240,6 +252,18 @@ extern void cupsdRemoveSelect(int fd); + extern void cupsdStartSelect(void); + extern void cupsdStopSelect(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); + + +diff -up cups-1.4.5/scheduler/dirsvc.c.avahi cups-1.4.5/scheduler/dirsvc.c +--- cups-1.4.5/scheduler/dirsvc.c.avahi 2010-12-24 13:11:33.679463507 +0000 ++++ cups-1.4.5/scheduler/dirsvc.c 2010-12-24 13:11:38.343340751 +0000 +@@ -99,6 +99,13 @@ + #endif /* HAVE_DNSSD */ + + ++#ifdef HAVE_DNSSD ++typedef char *cupsd_txt_record_t; ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++typedef AvahiStringList *cupsd_txt_record_t; ++#endif /* HAVE_AVAHI */ ++ + /* + * Local functions... + */ +@@ -159,15 +166,20 @@ 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 int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b); ++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, +@@ -175,11 +187,20 @@ static void dnssdRegisterCallback(DNSSer + 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 +304,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) */ + } + + +@@ -694,10 +715,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) */ + } + + +@@ -1535,13 +1556,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... + */ +@@ -1566,6 +1590,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 +@@ -1607,9 +1632,20 @@ cupsdStartBrowsing(void) + */ + + cupsdUpdateDNSSDName(); ++#ifdef HAVE_DNSSD + } +- } + #endif /* HAVE_DNSSD */ ++ } ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ ++ ++#ifdef HAVE_AVAHI ++ if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD) ++ { ++ AvahiCupsPollHandle = avahi_cups_poll_new (); ++ avahi_client_new (avahi_cups_poll_get (AvahiCupsPollHandle), ++ 0, avahi_client_cb, NULL, NULL); ++ } ++#endif /* HAVE_AVAHI */ + + #ifdef HAVE_LIBSLP + if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) +@@ -1835,10 +1871,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) && +@@ -1903,7 +1939,7 @@ cupsdStopPolling(void) + } + + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + /* + * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing... + */ +@@ -1911,7 +1947,12 @@ cupsdStopPolling(void) + void + cupsdUpdateDNSSDName(void) + { ++#ifdef HAVE_DNSSD + DNSServiceErrorType error; /* Error from service creation */ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ int ret; /* Error from service creation */ ++#endif /* HAVE_AVAHI */ + char webif[1024]; /* Web interface share name */ + #ifdef HAVE_COREFOUNDATION_H + SCDynamicStoreRef sc; /* Context for dynamic store */ +@@ -2043,6 +2084,7 @@ cupsdUpdateDNSSDName(void) + else + strlcpy(webif, "CUPS Web Interface", sizeof(webif)); + ++#ifdef HAVE_DNSSD + if (WebIFRef) + DNSServiceRefDeallocate(WebIFRef); + +@@ -2055,6 +2097,42 @@ 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 */ ++ htons(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 */ +@@ -2300,162 +2378,7 @@ dequote(char *d, /* I - Destinat + } + + +-#ifdef HAVE_DNSSD +-# ifdef HAVE_COREFOUNDATION +-/* +- * 'dnssdAddAlias()' - Add a DNS-SD alias name. +- */ +- +-static void +-dnssdAddAlias(const void *key, /* I - Key */ +- const void *value, /* I - Value (domain) */ +- void *context) /* I - Unused */ +-{ +- char valueStr[1024], /* Domain string */ +- hostname[1024]; /* Complete hostname */ +- +- +- (void)context; +- +- if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && +- CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), +- kCFStringEncodingUTF8)) +- { +- snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); +- if (!DNSSDAlias) +- DNSSDAlias = cupsArrayNew(NULL, NULL); +- +- cupsdAddAlias(DNSSDAlias, hostname); +- cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", +- hostname); +- } +- else +- cupsdLogMessage(CUPSD_LOG_ERROR, +- "Bad Back to My Mac domain in dynamic store!"); +-} +-# endif /* HAVE_COREFOUNDATION */ +- +- +-/* +- * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. +- */ +- +-static char * /* O - TXT record */ +-dnssdBuildTxtRecord( +- int *txt_len, /* O - TXT record length */ +- cupsd_printer_t *p, /* I - Printer information */ +- int for_lpd) /* I - 1 = LPD, 0 = IPP */ +-{ +- int i; /* Looping var */ +- char adminurl_str[256], /* URL for th admin page */ +- type_str[32], /* Type to string buffer */ +- state_str[32], /* State to string buffer */ +- rp_str[1024], /* Queue name string buffer */ +- air_str[1024], /* auth-info-required string buffer */ +- *keyvalue[32][2]; /* Table of key/value pairs */ +- +- +- /* +- * Load up the key value pairs... +- */ +- +- i = 0; +- +- keyvalue[i ][0] = "txtvers"; +- keyvalue[i++][1] = "1"; +- +- keyvalue[i ][0] = "qtotal"; +- keyvalue[i++][1] = "1"; +- +- keyvalue[i ][0] = "rp"; +- keyvalue[i++][1] = rp_str; +- if (for_lpd) +- strlcpy(rp_str, p->name, sizeof(rp_str)); +- else +- snprintf(rp_str, sizeof(rp_str), "%s/%s", +- (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); +- +- keyvalue[i ][0] = "ty"; +- keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown"; +- +- httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), +- "http", NULL, DNSSDHostName, DNSSDPort, "/%s/%s", +- (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", +- p->name); +- keyvalue[i ][0] = "adminurl"; +- keyvalue[i++][1] = adminurl_str; +- +- keyvalue[i ][0] = "note"; +- keyvalue[i++][1] = p->location ? p->location : ""; +- +- keyvalue[i ][0] = "priority"; +- keyvalue[i++][1] = for_lpd ? "100" : "0"; +- +- keyvalue[i ][0] = "product"; +- keyvalue[i++][1] = p->product ? p->product : "Unknown"; +- +- snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); +- snprintf(state_str, sizeof(state_str), "%d", p->state); +- +- keyvalue[i ][0] = "printer-state"; +- keyvalue[i++][1] = state_str; +- +- keyvalue[i ][0] = "printer-type"; +- keyvalue[i++][1] = type_str; +- +- keyvalue[i ][0] = "Transparent"; +- keyvalue[i++][1] = "T"; +- +- keyvalue[i ][0] = "Binary"; +- keyvalue[i++][1] = "T"; +- +- keyvalue[i ][0] = "Fax"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; +- +- keyvalue[i ][0] = "Color"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; +- +- keyvalue[i ][0] = "Duplex"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; +- +- keyvalue[i ][0] = "Staple"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; +- +- keyvalue[i ][0] = "Copies"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; +- +- keyvalue[i ][0] = "Collate"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; +- +- keyvalue[i ][0] = "Punch"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; +- +- keyvalue[i ][0] = "Bind"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; +- +- keyvalue[i ][0] = "Sort"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; +- +- keyvalue[i ][0] = "Scan"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; +- +- keyvalue[i ][0] = "pdl"; +- keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript"; +- +- if (get_auth_info_required(p, air_str, sizeof(air_str))) +- { +- keyvalue[i ][0] = "air"; +- keyvalue[i++][1] = air_str; +- } +- +- /* +- * Then pack them into a proper txt record... +- */ +- +- return (dnssdPackTxtRecord(txt_len, keyvalue, i)); +-} +- +- ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + /* + * 'dnssdComparePrinters()' - Compare the registered names of two printers. + */ +@@ -2479,6 +2402,10 @@ dnssdDeregisterPrinter( + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name); + ++#ifdef HAVE_DNSSD ++ if (!DNSSDRef) ++ return; ++ + /* + * Closing the socket deregisters the service + */ +@@ -2514,6 +2441,23 @@ 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 +@@ -2526,140 +2470,53 @@ dnssdDeregisterPrinter( + + + /* +- * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the +- * TXT record format. ++ * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer ++ * or update the broadcast contents. + */ + +-static char * /* O - TXT record */ +-dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */ +- char *keyvalue[][2], /* I - Table of key value pairs */ +- int count) /* I - Items in table */ ++static void ++dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ + { +- int i; /* Looping var */ +- int length; /* Length of TXT record */ +- int length2; /* Length of value */ +- char *txtRecord; /* TXT record buffer */ +- char *cursor; /* Looping pointer */ ++#ifdef HAVE_DNSSD ++ DNSServiceErrorType se; /* dnssd errors */ ++ char *ipp_txt, /* IPP TXT record buffer */ ++ *printer_txt, /* LPD TXT record buffer */ ++ *nameptr; /* Pointer into name */ ++ int ipp_len, /* IPP TXT record length */ ++ printer_len; /* LPD TXT record length */ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ int ret; /* Error code */ ++ AvahiStringList *ipp_txt, /* IPP TXT record list */ ++ *printer_txt; /* LPD TXT record buffer */ ++#endif /* HAVE_AVAHI */ ++ char name[1024]; /* Service name */ ++ const char *regtype; /* Registration type */ + + +- /* +- * Calculate the buffer size +- */ ++#ifdef HAVE_DNSSD ++ if (!DNSSDRef) ++ return; + +- for (length = i = 0; i < count; i++) +- length += 1 + strlen(keyvalue[i][0]) + +- (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0); ++ 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 */ + + /* +- * Allocate and fill it ++ * If per-printer sharing was just disabled make sure we're not ++ * registered before returning. + */ + +- txtRecord = malloc(length); +- if (txtRecord) ++ if (!p->shared) + { +- *txt_len = length; +- +- for (cursor = txtRecord, i = 0; i < count; i++) +- { +- /* +- * Drop in the p-string style length byte followed by the data +- */ +- +- length = strlen(keyvalue[i][0]); +- length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0; +- +- *cursor++ = (unsigned char)(length + length2); +- +- memcpy(cursor, keyvalue[i][0], length); +- cursor += length; +- +- if (length2) +- { +- length2 --; +- *cursor++ = '='; +- memcpy(cursor, keyvalue[i][1], length2); +- cursor += length2; +- } +- } +- } +- +- return (txtRecord); +-} +- +- +-/* +- * 'dnssdRegisterCallback()' - DNSServiceRegister callback. +- */ +- +-static void +-dnssdRegisterCallback( +- DNSServiceRef sdRef, /* I - DNS Service reference */ +- DNSServiceFlags flags, /* I - Reserved for future use */ +- DNSServiceErrorType errorCode, /* I - Error code */ +- const char *name, /* I - Service name */ +- const char *regtype, /* I - Service type */ +- const char *domain, /* I - Domain. ".local" for now */ +- void *context) /* I - User-defined context */ +-{ +- cupsd_printer_t *p = (cupsd_printer_t *)context; +- /* Current printer */ +- +- +- cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", +- name, regtype, p ? p->name : "Web Interface", +- p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); +- +- if (errorCode) +- { +- cupsdLogMessage(CUPSD_LOG_ERROR, +- "DNSServiceRegister failed with error %d", (int)errorCode); +- return; +- } +- else if (p && (!p->reg_name || strcasecmp(name, p->reg_name))) +- { +- cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"", +- name, p->name); +- +- cupsArrayRemove(DNSSDPrinters, p); +- cupsdSetString(&p->reg_name, name); +- cupsArrayAdd(DNSSDPrinters, p); +- +- LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; +- } +-} +- +- +-/* +- * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer +- * or update the broadcast contents. +- */ +- +-static void +-dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ +-{ +- 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 */ +- int ipp_len, /* IPP TXT record length */ +- printer_len; /* LPD TXT record length */ +- const char *regtype; /* Registration type */ +- +- +- cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, +- !p->ipp_ref ? "new" : "update"); +- +- /* +- * If per-printer sharing was just disabled make sure we're not +- * registered before returning. +- */ +- +- if (!p->shared) +- { +- dnssdDeregisterPrinter(p); +- return; +- } ++ dnssdDeregisterPrinter(p); ++ return; ++ } + + /* + * The registered name takes the form of " @ "... +@@ -2694,6 +2551,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); + +@@ -2860,6 +2718,140 @@ 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" : "_ipp._tcp"; ++ ++ 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); ++ ++ ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, name, regtype, NULL, ++ ipp_txt); ++ 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); ++ ++ ret = avahi_entry_group_add_service_strlst (p->avahi_group, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, name, regtype, NULL, NULL, ++ htons(DNSSDPort), ++ ipp_txt); ++ if (ret < 0) ++ goto add_failed; ++ ++ 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, ++ htons(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); ++ 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 */ + } + + +@@ -2872,6 +2864,10 @@ dnssdStop(void) + { + cupsd_printer_t *p; /* Current printer */ + ++#ifdef HAVE_DNSSD ++ if (!DNSSDRef) ++ return; ++#endif /* HAVE_DNSSD */ + + /* + * De-register the individual printers +@@ -2882,6 +2878,7 @@ dnssdStop(void) + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + dnssdDeregisterPrinter(p); + ++#ifdef HAVE_DNSSD + /* + * Shutdown the rest of the service refs... + */ +@@ -2902,6 +2899,7 @@ dnssdStop(void) + + DNSServiceRefDeallocate(DNSSDRef); + DNSSDRef = NULL; ++#endif /* HAVE_DNSSD */ + + cupsArrayDelete(DNSSDPrinters); + DNSSDPrinters = NULL; +@@ -2911,6 +2909,272 @@ dnssdStop(void) + + + /* ++ * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. ++ */ ++ ++static cupsd_txt_record_t /* O - TXT record */ ++dnssdBuildTxtRecord( ++ int *txt_len, /* O - TXT record length */ ++ cupsd_printer_t *p, /* I - Printer information */ ++ int for_lpd) /* I - 1 = LPD, 0 = IPP */ ++{ ++ int i; /* Looping var */ ++ char adminurl_str[256], /* URL for th admin page */ ++ type_str[32], /* Type to string buffer */ ++ state_str[32], /* State to string buffer */ ++ rp_str[1024], /* Queue name string buffer */ ++ air_str[1024], /* auth-info-required string buffer */ ++ *keyvalue[32][2]; /* Table of key/value pairs */ ++ ++ ++ /* ++ * Load up the key value pairs... ++ */ ++ ++ i = 0; ++ ++ keyvalue[i ][0] = "txtvers"; ++ keyvalue[i++][1] = "1"; ++ ++ keyvalue[i ][0] = "qtotal"; ++ keyvalue[i++][1] = "1"; ++ ++ keyvalue[i ][0] = "rp"; ++ keyvalue[i++][1] = rp_str; ++ if (for_lpd) ++ strlcpy(rp_str, p->name, sizeof(rp_str)); ++ else ++ snprintf(rp_str, sizeof(rp_str), "%s/%s", ++ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); ++ ++ keyvalue[i ][0] = "ty"; ++ keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown"; ++ ++ httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), ++ "http", NULL, DNSSDHostName, DNSSDPort, "/%s/%s", ++ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", ++ p->name); ++ keyvalue[i ][0] = "adminurl"; ++ keyvalue[i++][1] = adminurl_str; ++ ++ keyvalue[i ][0] = "note"; ++ keyvalue[i++][1] = p->location ? p->location : ""; ++ ++ keyvalue[i ][0] = "priority"; ++ keyvalue[i++][1] = for_lpd ? "100" : "0"; ++ ++ keyvalue[i ][0] = "product"; ++ keyvalue[i++][1] = p->product ? p->product : "Unknown"; ++ ++ snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); ++ snprintf(state_str, sizeof(state_str), "%d", p->state); ++ ++ keyvalue[i ][0] = "printer-state"; ++ keyvalue[i++][1] = state_str; ++ ++ keyvalue[i ][0] = "printer-type"; ++ keyvalue[i++][1] = type_str; ++ ++ keyvalue[i ][0] = "Transparent"; ++ keyvalue[i++][1] = "T"; ++ ++ keyvalue[i ][0] = "Binary"; ++ keyvalue[i++][1] = "T"; ++ ++ keyvalue[i ][0] = "Fax"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Color"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Duplex"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Staple"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Copies"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Collate"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Punch"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Bind"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Sort"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Scan"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "pdl"; ++ keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript"; ++ ++ if (get_auth_info_required(p, air_str, sizeof(air_str))) ++ { ++ keyvalue[i ][0] = "air"; ++ keyvalue[i++][1] = air_str; ++ } ++ ++ /* ++ * Then pack them into a proper txt record... ++ */ ++ ++#ifdef HAVE_DNSSD ++ return (dnssdPackTxtRecord(txt_len, keyvalue, i)); ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ return (avahiPackTxtRecord(keyvalue, i)); ++#endif /* HAVE_AVAHI */ ++} ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ ++ ++ ++#ifdef HAVE_DNSSD ++# ifdef HAVE_COREFOUNDATION ++/* ++ * 'dnssdAddAlias()' - Add a DNS-SD alias name. ++ */ ++ ++static void ++dnssdAddAlias(const void *key, /* I - Key */ ++ const void *value, /* I - Value (domain) */ ++ void *context) /* I - Unused */ ++{ ++ char valueStr[1024], /* Domain string */ ++ hostname[1024]; /* Complete hostname */ ++ ++ ++ (void)context; ++ ++ if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && ++ CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), ++ kCFStringEncodingUTF8)) ++ { ++ snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); ++ if (!DNSSDAlias) ++ DNSSDAlias = cupsArrayNew(NULL, NULL); ++ ++ cupsdAddAlias(DNSSDAlias, hostname); ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", ++ hostname); ++ } ++ else ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "Bad Back to My Mac domain in dynamic store!"); ++} ++# endif /* HAVE_COREFOUNDATION */ ++ ++ ++/* ++ * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the ++ * TXT record format. ++ */ ++ ++static char * /* O - TXT record */ ++dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */ ++ char *keyvalue[][2], /* I - Table of key value pairs */ ++ int count) /* I - Items in table */ ++{ ++ int i; /* Looping var */ ++ int length; /* Length of TXT record */ ++ int length2; /* Length of value */ ++ char *txtRecord; /* TXT record buffer */ ++ char *cursor; /* Looping pointer */ ++ ++ ++ /* ++ * Calculate the buffer size ++ */ ++ ++ for (length = i = 0; i < count; i++) ++ length += 1 + strlen(keyvalue[i][0]) + ++ (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0); ++ ++ /* ++ * Allocate and fill it ++ */ ++ ++ txtRecord = malloc(length); ++ if (txtRecord) ++ { ++ *txt_len = length; ++ ++ for (cursor = txtRecord, i = 0; i < count; i++) ++ { ++ /* ++ * Drop in the p-string style length byte followed by the data ++ */ ++ ++ length = strlen(keyvalue[i][0]); ++ length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0; ++ ++ *cursor++ = (unsigned char)(length + length2); ++ ++ memcpy(cursor, keyvalue[i][0], length); ++ cursor += length; ++ ++ if (length2) ++ { ++ length2 --; ++ *cursor++ = '='; ++ memcpy(cursor, keyvalue[i][1], length2); ++ cursor += length2; ++ } ++ } ++ } ++ ++ return (txtRecord); ++} ++ ++ ++/* ++ * 'dnssdRegisterCallback()' - DNSServiceRegister callback. ++ */ ++ ++static void ++dnssdRegisterCallback( ++ DNSServiceRef sdRef, /* I - DNS Service reference */ ++ DNSServiceFlags flags, /* I - Reserved for future use */ ++ DNSServiceErrorType errorCode, /* I - Error code */ ++ const char *name, /* I - Service name */ ++ const char *regtype, /* I - Service type */ ++ const char *domain, /* I - Domain. ".local" for now */ ++ void *context) /* I - User-defined context */ ++{ ++ cupsd_printer_t *p = (cupsd_printer_t *)context; ++ /* Current printer */ ++ ++ ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", ++ name, regtype, p ? p->name : "Web Interface", ++ p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); ++ ++ if (errorCode) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "DNSServiceRegister failed with error %d", (int)errorCode); ++ return; ++ } ++ else if (p && (!p->reg_name || strcasecmp(name, p->reg_name))) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"", ++ name, p->name); ++ ++ cupsArrayRemove(DNSSDPrinters, p); ++ cupsdSetString(&p->reg_name, name); ++ cupsArrayAdd(DNSSDPrinters, p); ++ ++ LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; ++ } ++} ++ ++ ++/* + * 'dnssdUpdate()' - Handle DNS-SD queries. + */ + +@@ -2931,6 +3195,126 @@ 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 - Items in table */ ++{ ++ AvahiStringList *strlst = NULL; ++ char **elements; ++ size_t len; ++ int i; ++ ++ 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; ++ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client started"); ++ ++ cupsdUpdateDNSSDName (); ++ ++ for (printer = (cupsd_printer_t *)cupsArrayFirst(DNSSDPrinters); ++ printer; ++ printer = (cupsd_printer_t *)cupsArrayNext(DNSSDPrinters)) ++ { ++ if (!printer->avahi_group) ++ dnssdRegisterPrinter (printer); ++ } ++ ++ break; ++ ++ case AVAHI_CLIENT_CONNECTING: ++ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client connecting"); ++ break; ++ ++ case AVAHI_CLIENT_FAILURE: ++ cupsdLogMessage (CUPSD_LOG_ERROR, "Avahi client failed"); ++ 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.4.5/scheduler/dirsvc.h.avahi cups-1.4.5/scheduler/dirsvc.h +--- cups-1.4.5/scheduler/dirsvc.h.avahi 2009-05-14 18:54:37.000000000 +0100 ++++ cups-1.4.5/scheduler/dirsvc.h 2010-12-24 13:11:38.344340724 +0000 +@@ -32,6 +32,10 @@ + # endif /* HAVE_LDAP_SSL_H */ + #endif /* HAVE_LDAP */ + ++#ifdef HAVE_AVAHI ++# include ++#endif /* HAVE_AVAHI */ ++ + /* + * Browse protocols... + */ +@@ -132,17 +136,20 @@ 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 int DNSSDPort VALUE(0); ++ /* Port number to register */ + VAR char *DNSSDComputerName VALUE(NULL), + /* Computer/server name */ + *DNSSDHostName VALUE(NULL); + /* Hostname */ +-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 /* HAVE_DNSSD || 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), +@@ -151,6 +158,15 @@ 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 AvahiEntryGroup *AvahiWebIFGroup VALUE(NULL); ++ /* Web interface entry group */ ++#endif /* HAVE_AVAHI */ ++ + #ifdef HAVE_LIBSLP + VAR SLPHandle BrowseSLPHandle VALUE(NULL); + /* SLP API handle */ +@@ -198,9 +214,9 @@ 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.4.5/scheduler/main.c.avahi cups-1.4.5/scheduler/main.c +--- cups-1.4.5/scheduler/main.c.avahi 2010-12-24 13:11:33.633464718 +0000 ++++ cups-1.4.5/scheduler/main.c 2010-12-24 13:11:38.348340619 +0000 +@@ -161,6 +161,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 +@@ -561,6 +565,14 @@ main(int argc, /* I - Number of comm + + httpInitialize(); + ++#ifdef HAVE_AVAHI ++ /* ++ * Initialize timed callback structures. ++ */ ++ ++ cupsdInitTimeouts(); ++#endif /* HAVE_AVAHI */ ++ + cupsdStartServer(); + + /* +@@ -900,6 +912,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... +@@ -1925,6 +1947,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 */ + + + /* +@@ -1967,6 +1993,19 @@ select_timeout(int fds) /* I - Number + } + #endif /* __APPLE__ */ + ++#ifdef HAVE_AVAHI ++ /* ++ * See if there are any scheduled timed callbacks to run. ++ */ ++ ++ tmo = cupsdNextTimeout (&tmo_delay); ++ if (tmo) ++ { ++ timeout = tmo_delay; ++ why = "run a timed callback"; ++ } ++#endif /* HAVE_AVAHI */ ++ + /* + * Check whether we are accepting new connections... + */ +diff -up cups-1.4.5/scheduler/Makefile.avahi cups-1.4.5/scheduler/Makefile +--- cups-1.4.5/scheduler/Makefile.avahi 2010-12-24 13:11:33.739461928 +0000 ++++ cups-1.4.5/scheduler/Makefile 2010-12-24 13:11:38.332341040 +0000 +@@ -17,6 +17,7 @@ include ../Makedefs + + CUPSDOBJS = \ + auth.o \ ++ avahi.o \ + banners.o \ + cert.o \ + classes.o \ +@@ -39,7 +40,8 @@ CUPSDOBJS = \ + server.o \ + statbuf.o \ + subscriptions.o \ +- sysman.o ++ sysman.o \ ++ timeout.o + LIBOBJS = \ + filter.o \ + mime.o \ +diff -up cups-1.4.5/scheduler/printers.c.avahi cups-1.4.5/scheduler/printers.c +--- cups-1.4.5/scheduler/printers.c.avahi 2010-12-24 13:11:33.784460744 +0000 ++++ cups-1.4.5/scheduler/printers.c 2010-12-24 13:11:38.356340409 +0000 +@@ -929,10 +929,10 @@ cupsdDeletePrinter( + cupsdClearString(&p->alert); + cupsdClearString(&p->alert_description); + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + cupsdClearString(&p->product); + cupsdClearString(&p->pdl); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + cupsArrayDelete(p->filetypes); + +@@ -1301,9 +1301,9 @@ cupsdLoadAllPrinters(void) + { + if (value) + { +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + p->product = _cupsStrAlloc(value); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, +@@ -1717,10 +1717,10 @@ cupsdSaveAllPrinters(void) + + cupsFilePrintf(fp, "Type %d\n", printer->type); + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + if (printer->product) + cupsFilePutConf(fp, "Product", printer->product); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + for (ptr = (char *)cupsArrayFirst(printer->filters); + ptr; +@@ -3860,7 +3860,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 */ +@@ -3914,7 +3914,7 @@ add_printer_formats(cupsd_printer_t *p) + + cupsdSetString(&p->pdl, pdl); + } +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + } + + +@@ -4951,9 +4951,9 @@ load_ppd(cupsd_printer_t *p) /* I - Pri + attr->values[i].string.text = _cupsStrAlloc("bcp"); + } + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + cupsdSetString(&p->product, ppd->product); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + if (ppdFindAttr(ppd, "APRemoteQueueID", NULL)) + p->type |= CUPS_PRINTER_REMOTE; +diff -up cups-1.4.5/scheduler/printers.h.avahi cups-1.4.5/scheduler/printers.h +--- cups-1.4.5/scheduler/printers.h.avahi 2010-03-30 23:07:33.000000000 +0100 ++++ cups-1.4.5/scheduler/printers.h 2010-12-24 13:11:38.357340382 +0000 +@@ -16,6 +16,9 @@ + #ifdef HAVE_DNSSD + # include + #endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++# include "avahi.h" ++#endif /* HAVE_AVAHI */ + #include + + +@@ -99,17 +102,24 @@ typedef struct cupsd_printer_s + char *recoverable; /* com.apple.print.recoverable-message */ + _pwg_t *pwg; /* PWG<->PPD mapping data */ + ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++ char *reg_name; /* Name used for service registration */ ++ char *product, /* PPD Product string */ ++ *pdl; /* pdl value for TXT record */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + #ifdef HAVE_DNSSD +- char *reg_name, /* Name used for service registration */ +- *product, /* PPD Product string */ +- *pdl, /* pdl value for TXT record */ +- *ipp_txt, /* IPP TXT record contents */ ++ 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 */ + } cupsd_printer_t; + + +diff -up cups-1.4.5/scheduler/timeout.c.avahi cups-1.4.5/scheduler/timeout.c +--- cups-1.4.5/scheduler/timeout.c.avahi 2010-12-24 13:11:38.358340356 +0000 ++++ cups-1.4.5/scheduler/timeout.c 2010-12-24 13:11:38.358340356 +0000 +@@ -0,0 +1,191 @@ ++/* ++ * "$Id$" ++ * ++ * Timeout functions for the Common UNIX Printing System (CUPS). ++ * ++ * Copyright (C) 2010 Red Hat, Inc. ++ * Authors: ++ * Tim Waugh ++ * ++ * Distribution and use rights are outlined in the file "LICENSE.txt" ++ * which should have been included with this file. If this file is ++ * file is missing or damaged, see the license at "http://www.cups.org/". ++ * ++ * 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 ++ ++#ifdef HAVE_AVAHI /* Applies to entire file... */ ++ ++/* ++ * Include necessary headers... ++ */ ++ ++#include "cupsd.h" ++ ++#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) ++# include ++#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ ++ ++#ifdef HAVE_AVAHI ++# include ++#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_timeouts (cupsd_timeout_t *p0, cupsd_timeout_t *p1) ++{ ++ if (!p0->enabled || !p1->enabled) ++ { ++ if (!p0->enabled && !p1->enabled) ++ return (0); ++ ++ return (p0->enabled ? -1 : 1); ++ } ++ ++ return (avahi_timeval_compare (&p0->when, &p1->when)); ++} ++ ++ ++/* ++ * '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 */ ++{ ++ timeout->enabled = 0; ++ 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/cups-lspp.patch b/cups-lspp.patch index 2f8296d..380b55d 100644 --- a/cups-lspp.patch +++ b/cups-lspp.patch @@ -1,6 +1,6 @@ diff -up cups-1.4.5/config.h.in.lspp cups-1.4.5/config.h.in ---- cups-1.4.5/config.h.in.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/config.h.in 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/config.h.in.lspp 2010-12-24 13:21:31.134859403 +0000 ++++ cups-1.4.5/config.h.in 2010-12-24 13:21:31.173858387 +0000 @@ -672,6 +672,12 @@ #undef HAVE_SYS_STATVFS_H #undef HAVE_SYS_VFS_H @@ -15,8 +15,8 @@ diff -up cups-1.4.5/config.h.in.lspp cups-1.4.5/config.h.in #endif /* !_CUPS_CONFIG_H_ */ diff -up cups-1.4.5/config-scripts/cups-lspp.m4.lspp cups-1.4.5/config-scripts/cups-lspp.m4 ---- cups-1.4.5/config-scripts/cups-lspp.m4.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/config-scripts/cups-lspp.m4 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/config-scripts/cups-lspp.m4.lspp 2010-12-24 13:21:31.174858361 +0000 ++++ cups-1.4.5/config-scripts/cups-lspp.m4 2010-12-24 13:21:31.174858361 +0000 @@ -0,0 +1,36 @@ +dnl +dnl LSPP code for the Common UNIX Printing System (CUPS). @@ -55,8 +55,8 @@ diff -up cups-1.4.5/config-scripts/cups-lspp.m4.lspp cups-1.4.5/config-scripts/c + esac +fi diff -up cups-1.4.5/configure.in.lspp cups-1.4.5/configure.in ---- cups-1.4.5/configure.in.lspp 2010-06-22 23:42:44.000000000 +0200 -+++ cups-1.4.5/configure.in 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/configure.in.lspp 2010-06-22 22:42:44.000000000 +0100 ++++ cups-1.4.5/configure.in 2010-12-24 13:21:31.174858362 +0000 @@ -42,6 +42,8 @@ sinclude(config-scripts/cups-pap.m4) sinclude(config-scripts/cups-pdf.m4) sinclude(config-scripts/cups-scripting.m4) @@ -67,8 +67,8 @@ diff -up cups-1.4.5/configure.in.lspp cups-1.4.5/configure.in UNINSTALL_LANGUAGES="" LANGFILES="" diff -up cups-1.4.5/cups/cups.h.lspp cups-1.4.5/cups/cups.h ---- cups-1.4.5/cups/cups.h.lspp 2010-06-22 05:18:27.000000000 +0200 -+++ cups-1.4.5/cups/cups.h 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/cups/cups.h.lspp 2010-06-22 04:18:27.000000000 +0100 ++++ cups-1.4.5/cups/cups.h 2010-12-24 13:21:31.176858307 +0000 @@ -15,6 +15,9 @@ * This file is subject to the Apple OS-Developed Software exception. */ @@ -93,8 +93,8 @@ diff -up cups-1.4.5/cups/cups.h.lspp cups-1.4.5/cups/cups.h * Types and structures... */ diff -up cups-1.4.5/data/Makefile.lspp cups-1.4.5/data/Makefile ---- cups-1.4.5/data/Makefile.lspp 2008-11-12 20:30:57.000000000 +0100 -+++ cups-1.4.5/data/Makefile 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/data/Makefile.lspp 2008-11-12 19:30:57.000000000 +0000 ++++ cups-1.4.5/data/Makefile 2010-12-24 13:21:31.177858282 +0000 @@ -25,7 +25,10 @@ BANNERS = \ secret \ standard \ @@ -108,8 +108,8 @@ diff -up cups-1.4.5/data/Makefile.lspp cups-1.4.5/data/Makefile CHARMAPS = \ euc-cn.txt \ diff -up cups-1.4.5/data/mls.lspp cups-1.4.5/data/mls ---- cups-1.4.5/data/mls.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/data/mls 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/data/mls.lspp 2010-12-24 13:21:31.177858282 +0000 ++++ cups-1.4.5/data/mls 2010-12-24 13:21:31.178858258 +0000 @@ -0,0 +1,261 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 @@ -373,8 +373,8 @@ diff -up cups-1.4.5/data/mls.lspp cups-1.4.5/data/mls +% +%%EOF diff -up cups-1.4.5/data/selinux.lspp cups-1.4.5/data/selinux ---- cups-1.4.5/data/selinux.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/data/selinux 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/data/selinux.lspp 2010-12-24 13:21:31.178858258 +0000 ++++ cups-1.4.5/data/selinux 2010-12-24 13:21:31.179858233 +0000 @@ -0,0 +1,261 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 @@ -638,8 +638,8 @@ diff -up cups-1.4.5/data/selinux.lspp cups-1.4.5/data/selinux +% +%%EOF diff -up cups-1.4.5/data/te.lspp cups-1.4.5/data/te ---- cups-1.4.5/data/te.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/data/te 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/data/te.lspp 2010-12-24 13:21:31.179858233 +0000 ++++ cups-1.4.5/data/te 2010-12-24 13:21:31.180858207 +0000 @@ -0,0 +1,261 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 0 0 612 792 @@ -903,8 +903,8 @@ diff -up cups-1.4.5/data/te.lspp cups-1.4.5/data/te +% +%%EOF diff -up cups-1.4.5/filter/common.c.lspp cups-1.4.5/filter/common.c ---- cups-1.4.5/filter/common.c.lspp 2007-07-11 23:46:42.000000000 +0200 -+++ cups-1.4.5/filter/common.c 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/filter/common.c.lspp 2007-07-11 22:46:42.000000000 +0100 ++++ cups-1.4.5/filter/common.c 2010-12-24 13:21:31.181858180 +0000 @@ -30,6 +30,12 @@ * Include necessary headers... */ @@ -1074,8 +1074,8 @@ diff -up cups-1.4.5/filter/common.c.lspp cups-1.4.5/filter/common.c /* diff -up cups-1.4.5/filter/pstops.c.lspp cups-1.4.5/filter/pstops.c ---- cups-1.4.5/filter/pstops.c.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/filter/pstops.c 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/filter/pstops.c.lspp 2010-12-24 13:21:30.960863932 +0000 ++++ cups-1.4.5/filter/pstops.c 2010-12-24 13:21:31.186858049 +0000 @@ -3335,6 +3335,18 @@ write_label_prolog(pstops_doc_t *doc, /* { const char *classification; /* CLASSIFICATION environment variable */ @@ -1232,8 +1232,8 @@ diff -up cups-1.4.5/filter/pstops.c.lspp cups-1.4.5/filter/pstops.c /* diff -up cups-1.4.5/Makedefs.in.lspp cups-1.4.5/Makedefs.in ---- cups-1.4.5/Makedefs.in.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/Makedefs.in 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/Makedefs.in.lspp 2010-12-24 13:21:31.073860989 +0000 ++++ cups-1.4.5/Makedefs.in 2010-12-24 13:21:31.187858023 +0000 @@ -146,7 +146,7 @@ LIBCUPSORDER = @LIBCUPSORDER@ LIBCUPSIMAGEORDER = @LIBCUPSIMAGEORDER@ LINKCUPS = @LINKCUPS@ $(SSLLIBS) $(DNSSDLIBS) @@ -1253,8 +1253,8 @@ diff -up cups-1.4.5/Makedefs.in.lspp cups-1.4.5/Makedefs.in .c.o: diff -up cups-1.4.5/scheduler/client.c.lspp cups-1.4.5/scheduler/client.c ---- cups-1.4.5/scheduler/client.c.lspp 2010-10-17 06:13:56.000000000 +0200 -+++ cups-1.4.5/scheduler/client.c 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/client.c.lspp 2010-10-17 05:13:56.000000000 +0100 ++++ cups-1.4.5/scheduler/client.c 2010-12-24 13:21:31.194857839 +0000 @@ -44,6 +44,7 @@ * valid_host() - Is the Host: field valid? * write_file() - Send a file via HTTP. @@ -1476,8 +1476,8 @@ diff -up cups-1.4.5/scheduler/client.c.lspp cups-1.4.5/scheduler/client.c * 'pipe_command()' - Pipe the output of a command to the remote client. */ diff -up cups-1.4.5/scheduler/client.h.lspp cups-1.4.5/scheduler/client.h ---- cups-1.4.5/scheduler/client.h.lspp 2009-05-27 00:01:23.000000000 +0200 -+++ cups-1.4.5/scheduler/client.h 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/client.h.lspp 2009-05-26 23:01:23.000000000 +0100 ++++ cups-1.4.5/scheduler/client.h 2010-12-24 13:21:31.195857813 +0000 @@ -18,6 +18,13 @@ #endif /* HAVE_AUTHORIZATION_H */ @@ -1514,8 +1514,8 @@ diff -up cups-1.4.5/scheduler/client.h.lspp cups-1.4.5/scheduler/client.h /* diff -up cups-1.4.5/scheduler/conf.c.lspp cups-1.4.5/scheduler/conf.c ---- cups-1.4.5/scheduler/conf.c.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/scheduler/conf.c 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/conf.c.lspp 2010-12-24 13:21:30.897865572 +0000 ++++ cups-1.4.5/scheduler/conf.c 2010-12-24 13:21:31.200857684 +0000 @@ -29,6 +29,7 @@ * read_configuration() - Read a configuration file. * read_location() - Read a definition. @@ -1626,8 +1626,8 @@ diff -up cups-1.4.5/scheduler/conf.c.lspp cups-1.4.5/scheduler/conf.c /* * 'read_policy()' - Read a definition. diff -up cups-1.4.5/scheduler/conf.h.lspp cups-1.4.5/scheduler/conf.h ---- cups-1.4.5/scheduler/conf.h.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/scheduler/conf.h 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/conf.h.lspp 2010-12-24 13:21:30.897865572 +0000 ++++ cups-1.4.5/scheduler/conf.h 2010-12-24 13:21:31.202857632 +0000 @@ -250,6 +250,12 @@ VAR char *ServerKey VALUE(NULL); VAR int SSLOptions VALUE(CUPSD_SSL_NONE); /* SSL/TLS options */ @@ -1652,8 +1652,8 @@ diff -up cups-1.4.5/scheduler/conf.h.lspp cups-1.4.5/scheduler/conf.h /* * Prototypes... diff -up cups-1.4.5/scheduler/ipp.c.lspp cups-1.4.5/scheduler/ipp.c ---- cups-1.4.5/scheduler/ipp.c.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/scheduler/ipp.c 2010-12-13 15:01:43.000000000 +0100 +--- cups-1.4.5/scheduler/ipp.c.lspp 2010-12-24 13:21:31.114859924 +0000 ++++ cups-1.4.5/scheduler/ipp.c 2010-12-24 13:21:31.217857242 +0000 @@ -41,6 +41,7 @@ * cancel_all_jobs() - Cancel all print jobs. * cancel_job() - Cancel a print job. @@ -2252,8 +2252,8 @@ diff -up cups-1.4.5/scheduler/ipp.c.lspp cups-1.4.5/scheduler/ipp.c * Check the username against the owner... */ diff -up cups-1.4.5/scheduler/job.c.lspp cups-1.4.5/scheduler/job.c ---- cups-1.4.5/scheduler/job.c.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/scheduler/job.c 2010-12-13 15:02:11.000000000 +0100 +--- cups-1.4.5/scheduler/job.c.lspp 2010-12-24 13:21:31.028862162 +0000 ++++ cups-1.4.5/scheduler/job.c 2010-12-24 13:21:31.224857060 +0000 @@ -66,6 +66,9 @@ * update_job_attrs() - Update the job-printer-* attributes. */ @@ -2649,8 +2649,8 @@ diff -up cups-1.4.5/scheduler/job.c.lspp cups-1.4.5/scheduler/job.c * Now start the first file in the job... */ diff -up cups-1.4.5/scheduler/job.h.lspp cups-1.4.5/scheduler/job.h ---- cups-1.4.5/scheduler/job.h.lspp 2009-05-12 00:46:01.000000000 +0200 -+++ cups-1.4.5/scheduler/job.h 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/job.h.lspp 2009-05-11 23:46:01.000000000 +0100 ++++ cups-1.4.5/scheduler/job.h 2010-12-24 13:21:31.225857034 +0000 @@ -13,6 +13,13 @@ * file is missing or damaged, see the license at "http://www.cups.org/". */ @@ -2677,8 +2677,8 @@ diff -up cups-1.4.5/scheduler/job.h.lspp cups-1.4.5/scheduler/job.h typedef struct cupsd_joblog_s /**** Job log message ****/ diff -up cups-1.4.5/scheduler/main.c.lspp cups-1.4.5/scheduler/main.c ---- cups-1.4.5/scheduler/main.c.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/scheduler/main.c 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/main.c.lspp 2010-12-24 13:21:31.158858778 +0000 ++++ cups-1.4.5/scheduler/main.c 2010-12-24 13:22:10.827825881 +0000 @@ -37,6 +37,8 @@ * usage() - Show scheduler usage. */ @@ -2698,17 +2698,17 @@ diff -up cups-1.4.5/scheduler/main.c.lspp cups-1.4.5/scheduler/main.c /* * Local functions... -@@ -161,6 +166,9 @@ main(int argc, /* I - Number of comm - int launchd_idle_exit; - /* Idle exit on select timeout? */ - #endif /* HAVE_LAUNCHD */ +@@ -145,6 +150,9 @@ main(int argc, /* I - Number of comm + #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ + #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +#if WITH_LSPP + auditfail_t failmode; /* Action for audit_open failure */ +#endif /* WITH_LSPP */ - - - #ifdef HAVE_GETEUID -@@ -470,6 +478,25 @@ main(int argc, /* I - Number of comm + #ifdef __sgi + cups_file_t *fp; /* Fake lpsched lock file */ + struct stat statbuf; /* Needed for checking lpsched FIFO */ +@@ -474,6 +482,25 @@ main(int argc, /* I - Number of comm #endif /* DEBUG */ } @@ -2734,7 +2734,7 @@ diff -up cups-1.4.5/scheduler/main.c.lspp cups-1.4.5/scheduler/main.c /* * Set the timezone info... */ -@@ -1219,6 +1246,11 @@ main(int argc, /* I - Number of comm +@@ -1241,6 +1268,11 @@ main(int argc, /* I - Number of comm cupsdStopSelect(); @@ -2747,8 +2747,8 @@ diff -up cups-1.4.5/scheduler/main.c.lspp cups-1.4.5/scheduler/main.c } diff -up cups-1.4.5/scheduler/printers.c.lspp cups-1.4.5/scheduler/printers.c ---- cups-1.4.5/scheduler/printers.c.lspp 2010-12-13 14:51:01.000000000 +0100 -+++ cups-1.4.5/scheduler/printers.c 2010-12-13 14:51:01.000000000 +0100 +--- cups-1.4.5/scheduler/printers.c.lspp 2010-12-24 13:21:31.168858518 +0000 ++++ cups-1.4.5/scheduler/printers.c 2010-12-24 13:21:31.236856747 +0000 @@ -59,6 +59,8 @@ * write_xml_string() - Write a string with XML escaping. */ @@ -2769,7 +2769,7 @@ diff -up cups-1.4.5/scheduler/printers.c.lspp cups-1.4.5/scheduler/printers.c /* * 'cupsdAddPrinter()' - Add a printer to the system. -@@ -2266,6 +2272,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) +@@ -2267,6 +2273,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) "username", "password" }; @@ -2783,7 +2783,7 @@ diff -up cups-1.4.5/scheduler/printers.c.lspp cups-1.4.5/scheduler/printers.c DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name, -@@ -2396,6 +2409,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) +@@ -2397,6 +2410,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) attr->values[1].string.text = _cupsStrAlloc(Classification ? Classification : p->job_sheets[1]); } @@ -2829,7 +2829,7 @@ diff -up cups-1.4.5/scheduler/printers.c.lspp cups-1.4.5/scheduler/printers.c } p->raw = 0; -@@ -5535,7 +5587,6 @@ write_irix_state(cupsd_printer_t *p) /* +@@ -5536,7 +5588,6 @@ write_irix_state(cupsd_printer_t *p) /* } #endif /* __sgi */ diff --git a/cups.spec b/cups.spec index 441a2bf..62aa1f2 100644 --- a/cups.spec +++ b/cups.spec @@ -8,7 +8,7 @@ Summary: Common Unix Printing System Name: cups Version: 1.4.5 -Release: 8%{?dist} +Release: 9%{?dist} License: GPLv2 Group: System Environment/Daemons Source: http://ftp.easysw.com/pub/cups/%{version}/cups-%{version}-source.tar.bz2 @@ -54,7 +54,6 @@ Patch20: cups-res_init.patch Patch21: cups-filter-debug.patch Patch22: cups-uri-compat.patch Patch23: cups-cups-get-classes.patch -Patch24: cups-avahi.patch Patch25: cups-str3382.patch Patch26: cups-force-gnutls.patch Patch27: cups-serialize-gnutls.patch @@ -68,6 +67,7 @@ Patch36: cups-ricoh-deviceid-oid.patch Patch37: cups-texttops-rotate-page.patch Patch38: cups-autotype-crash.patch Patch39: cups-str3754.patch +Patch40: cups-avahi.patch Patch100: cups-lspp.patch @@ -251,8 +251,6 @@ module. %patch22 -p1 -b .uri-compat # Fix support for older CUPS servers in cupsGetDests. %patch23 -p1 -b .cups-get-classes -# Avahi support in the dnssd backend. -%patch24 -p1 -b .avahi # Fix temporary filename creation. %patch25 -p1 -b .str3382 # Force the use of gnutls despite thread-safety concerns (bug #607159). @@ -284,6 +282,9 @@ module. # Don't crash when job queued for printer that times out (bug #660604). %patch39 -p1 -b .str3754 +# Avahi support in the dnssd backend. +%patch40 -p1 -b .avahi + %if %lspp # LSPP support. %patch100 -p1 -b .lspp @@ -598,6 +599,9 @@ rm -rf $RPM_BUILD_ROOT %{php_extdir}/phpcups.so %changelog +* Fri Dec 24 2010 Tim Waugh 1:1.4.5-9 +- Native Avahi support for announcing printers on the network. + * Wed Dec 22 2010 Tim Waugh 1:1.4.5-8 - Don't crash when job queued for browsed printer that times out (bug #660604).