]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/dnssd.c
Changelog.
[thirdparty/cups.git] / backend / dnssd.c
index 1ef00323ab05d5dcd41d90dfbdeb22204a58b627..9cea92e037d2849655532afe16caa033699760c1 100644 (file)
@@ -94,8 +94,7 @@ static int            job_canceled = 0;
 #ifdef HAVE_AVAHI
 static AvahiSimplePoll *simple_poll = NULL;
                                        /* Poll information */
-static int             got_callback = 0;
-                                       /* Got a callback? */
+static int             got_data = 0;   /* Got data from poll? */
 #endif /* HAVE_AVAHI */
 
 
@@ -154,8 +153,10 @@ static void                query_callback(DNSServiceRef sdRef,
                                       const void *rdata, uint32_t ttl,
                                       void *context)
                                       __attribute__((nonnull(1,5,9,11)));
-#endif /* HAVE_DNSSD */
-#ifdef HAVE_AVAHI
+#elif defined(HAVE_AVAHI)
+static int             poll_callback(struct pollfd *pollfds,
+                                     unsigned int num_pollfds, int timeout,
+                                     void *context);
 static void            query_callback(AvahiRecordBrowser *browser,
                                       AvahiIfIndex interface,
                                       AvahiProtocol protocol,
@@ -165,7 +166,7 @@ static void         query_callback(AvahiRecordBrowser *browser,
                                       size_t rdlen,
                                       AvahiLookupResultFlags flags,
                                       void *context);
-#endif /* HAVE_AVAHI */
+#endif /* HAVE_DNSSD */
 static void            sigterm_handler(int sig);
 static void            unquote(char *dst, const char *src, size_t dstsize)
                            __attribute__((nonnull(1,2)));
@@ -330,15 +331,17 @@ main(int  argc,                           /* I - Number of command-line args */
 #ifdef HAVE_AVAHI
   if ((simple_poll = avahi_simple_poll_new()) == NULL)
   {
-    fputs("DEBUG: Unable to create avahi simple poll object.\n", stderr);
+    fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr);
     return (1);
   }
 
+  avahi_simple_poll_set_func(simple_poll, poll_callback, NULL);
+
   client = avahi_client_new(avahi_simple_poll_get(simple_poll),
                            0, client_callback, simple_poll, &error);
   if (!client)
   {
-    fputs("DEBUG: Unable to create avahi client.\n", stderr);
+    fputs("DEBUG: Unable to create Avahi client.\n", stderr);
     return (1);
   }
 
@@ -383,7 +386,7 @@ main(int  argc,                             /* I - Number of command-line args */
     FD_SET(fd, &input);
 
     timeout.tv_sec  = 0;
-    timeout.tv_usec = 250000;
+    timeout.tv_usec = 500000;
 
     if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
       continue;
@@ -400,10 +403,9 @@ main(int  argc,                            /* I - Number of command-line args */
       announce = 1;
 
 #elif defined(HAVE_AVAHI)
-    got_callback = 0;
+    got_data = 0;
 
-    if ((error = avahi_simple_poll_iterate(simple_poll, 3)) != 0 &&
-        errno != EINTR)
+    if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0)
     {
      /*
       * We've been told to exit the loop.  Perhaps the connection to
@@ -413,10 +415,12 @@ main(int  argc,                           /* I - Number of command-line args */
       break;
     }
 
-    if (got_callback)
+    if (!got_data)
       announce = 1;
 #endif /* HAVE_DNSSD */
 
+/*    fprintf(stderr, "DEBUG: announce=%d\n", announce);*/
+
     if (announce)
     {
      /*
@@ -448,7 +452,7 @@ main(int  argc,                             /* I - Number of command-line args */
          * Found the device, now get the TXT record(s) for it...
          */
 
-          if (count < 20)
+          if (count < 50)
          {
            fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName);
 
@@ -552,6 +556,8 @@ main(int  argc,                             /* I - Number of command-line args */
        sent ++;
       }
 
+      fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count);
+
       if (sent == cupsArrayCount(devices))
        break;
     }
@@ -581,10 +587,7 @@ browse_callback(
                   "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
                  "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
           sdRef, flags, interfaceIndex, errorCode,
-         serviceName ? serviceName : "(null)",
-         regtype ? regtype : "(null)",
-         replyDomain ? replyDomain : "(null)",
-         context);
+         serviceName, regtype, replyDomain, context);
 
  /*
   * Only process "add" data...
@@ -623,10 +626,7 @@ browse_local_callback(
                   "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
                  "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
           sdRef, flags, interfaceIndex, errorCode,
-         serviceName ? serviceName : "(null)",
-         regtype ? regtype : "(null)",
-         replyDomain ? replyDomain : "(null)",
-         context);
+         serviceName, regtype, replyDomain, context);
 
  /*
   * Only process "add" data...
@@ -706,7 +706,6 @@ browse_callback(
          */
 
          get_device((cups_array_t *)context, name, type, domain);
-         got_callback = 1;
        }
        break;
 
@@ -902,7 +901,7 @@ get_device(cups_array_t *devices,   /* I - Device array */
                                    replyDomain);
 #else /* HAVE_AVAHI */
        avahi_service_name_join(fullName, kDNSServiceMaxDomainName,
-                                serviceName, regtype, replyDomain);
+                               serviceName, regtype, replyDomain);
 #endif /* HAVE_DNSSD */
 
        free(device->fullName);
@@ -944,6 +943,40 @@ get_device(cups_array_t *devices,  /* I - Device array */
 }
 
 
+#ifdef HAVE_AVAHI
+/*
+ * 'poll_callback()' - Wait for input on the specified file descriptors.
+ *
+ * Note: This function is needed because avahi_simple_poll_iterate is broken
+ *       and always uses a timeout of 0 (!) milliseconds.
+ *       (Avahi Ticket #364)
+ */
+
+static int                             /* O - Number of file descriptors matching */
+poll_callback(
+    struct pollfd *pollfds,            /* I - File descriptors */
+    unsigned int  num_pollfds,         /* I - Number of file descriptors */
+    int           timeout,             /* I - Timeout in milliseconds (unused) */
+    void          *context)            /* I - User data (unused) */
+{
+  int  val;                            /* Return value */
+
+
+  (void)timeout;
+  (void)context;
+
+  val = poll(pollfds, num_pollfds, 500);
+
+  if (val < 0)
+    fprintf(stderr, "DEBUG: poll_callback: %s\n", strerror(errno));
+  else if (val > 0)
+    got_data = 1;
+
+  return (val);
+}
+#endif /* HAVE_AVAHI */
+
+
 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 #  ifdef HAVE_DNSSD
 /*
@@ -998,6 +1031,7 @@ query_callback(
                value[256],             /* Value string */
                make_and_model[512],    /* Manufacturer and model */
                model[256],             /* Model */
+               pdl[256],               /* PDL */
                device_id[2048];        /* 1284 device ID */
 
 
@@ -1046,8 +1080,9 @@ query_callback(
 
   device_id[0]      = '\0';
   make_and_model[0] = '\0';
+  pdl[0]            = '\0';
 
-  strcpy(model, "Unknown");
+  strlcpy(model, "Unknown", sizeof(model));
 
   for (data = rdata, dataend = data + rdlen;
        data < dataend;
@@ -1101,9 +1136,9 @@ query_callback(
 
     if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") ||
        !_cups_strcasecmp(key, "usb_MANUFACTURER"))
-      strcpy(make_and_model, value);
+      strlcpy(make_and_model, value, sizeof(make_and_model));
     else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL"))
-      strcpy(model, value);
+      strlcpy(model, value, sizeof(model));
     else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript"))
     {
       if (value[0] == '(')
@@ -1115,18 +1150,20 @@ query_callback(
        if ((ptr = value + strlen(value) - 1) > value && *ptr == ')')
          *ptr = '\0';
 
-       strcpy(model, value + 1);
+       strlcpy(model, value + 1, sizeof(model));
       }
       else
-       strcpy(model, value);
+       strlcpy(model, value, sizeof(model));
     }
     else if (!_cups_strcasecmp(key, "ty"))
     {
-      strcpy(model, value);
+      strlcpy(model, value, sizeof(model));
 
       if ((ptr = strchr(model, ',')) != NULL)
        *ptr = '\0';
     }
+    else if (!_cups_strcasecmp(key, "pdl"))
+      strlcpy(pdl, value, sizeof(pdl));
     else if (!_cups_strcasecmp(key, "priority"))
       device->priority = atoi(value);
     else if ((device->type == CUPS_DEVICE_IPP ||
@@ -1171,6 +1208,46 @@ query_callback(
     }
   }
 
+  if (device_id[0] &&
+      !strstr(device_id, "CMD:") &&
+      !strstr(device_id, "COMMAND SET:") &&
+      (strstr(pdl, "application/pdf") ||
+       strstr(pdl, "application/postscript") ||
+       strstr(pdl, "application/vnd.hp-PCL") ||
+       strstr(pdl, "image/")))
+  {
+    value[0] = '\0';
+    if (strstr(pdl, "application/pdf"))
+      strlcat(value, ",PDF", sizeof(value));
+    if (strstr(pdl, "application/postscript"))
+      strlcat(value, ",PS", sizeof(value));
+    if (strstr(pdl, "application/vnd.hp-PCL"))
+      strlcat(value, ",PCL", sizeof(value));
+    for (ptr = strstr(pdl, "image/"); ptr; ptr = strstr(ptr, "image/"))
+    {
+      char *valptr = value + strlen(value);
+                                       /* Pointer into value */
+
+      if (valptr < (value + sizeof(value) - 1))
+        *valptr++ = ',';
+
+      ptr += 6;
+      while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.')
+      {
+        if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1))
+          *valptr++ = toupper(*ptr++ & 255);
+        else
+          break;
+      }
+
+      *valptr = '\0';
+    }
+
+    ptr = device_id + strlen(device_id);
+    snprintf(ptr, sizeof(device_id) - (ptr - device_id), "CMD:%s;",
+            value + 1);
+  }
+
   if (device_id[0])
     device->device_id = strdup(device_id);
   else
@@ -1188,10 +1265,6 @@ query_callback(
   }
   else
     device->make_and_model = strdup(model);
-
-#  ifdef HAVE_AVAHI
-  got_callback = 1;
-#  endif /* HAVE_AVAHI */
 }
 #endif /* HAVE_DNSSD || HAVE_AVAHI */