4 * DNS-SD discovery backend for CUPS.
6 * Copyright 2008-2011 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged, see the license at "http://www.cups.org/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * main() - Browse for printers.
19 * browse_callback() - Browse devices.
20 * browse_local_callback() - Browse local devices.
21 * compare_devices() - Compare two devices.
22 * exec_backend() - Execute the backend that corresponds to the
23 * resolved service name.
24 * get_device() - Create or update a device.
25 * query_callback() - Process query data.
26 * sigterm_handler() - Handle termination signals...
27 * unquote() - Unquote a name string.
31 * Include necessary headers.
34 #include "backend-private.h"
35 #include <cups/array.h>
45 CUPS_DEVICE_PRINTER
= 0, /* lpd://... */
46 CUPS_DEVICE_IPP
, /* ipp://... */
47 CUPS_DEVICE_IPPS
, /* ipps://... */
48 CUPS_DEVICE_FAX_IPP
, /* ipp://... */
49 CUPS_DEVICE_PDL_DATASTREAM
, /* socket://... */
50 CUPS_DEVICE_RIOUSBPRINT
/* riousbprint://... */
56 DNSServiceRef ref
; /* Service reference for resolve */
57 char *name
, /* Service name */
58 *domain
, /* Domain name */
59 *fullName
, /* Full name */
60 *make_and_model
, /* Make and model from TXT record */
61 *device_id
; /* 1284 device ID from TXT record */
62 cups_devtype_t type
; /* Device registration type */
63 int priority
, /* Priority associated with type */
64 cups_shared
, /* CUPS shared printer? */
65 sent
; /* Did we list the device? */
73 static int job_canceled
= 0;
74 /* Set to 1 on SIGTERM */
81 static void browse_callback(DNSServiceRef sdRef
,
82 DNSServiceFlags flags
,
83 uint32_t interfaceIndex
,
84 DNSServiceErrorType errorCode
,
85 const char *serviceName
,
87 const char *replyDomain
, void *context
);
88 static void browse_local_callback(DNSServiceRef sdRef
,
89 DNSServiceFlags flags
,
90 uint32_t interfaceIndex
,
91 DNSServiceErrorType errorCode
,
92 const char *serviceName
,
94 const char *replyDomain
,
96 static int compare_devices(cups_device_t
*a
, cups_device_t
*b
);
97 static void exec_backend(char **argv
);
98 static cups_device_t
*get_device(cups_array_t
*devices
,
99 const char *serviceName
,
101 const char *replyDomain
);
102 static void query_callback(DNSServiceRef sdRef
,
103 DNSServiceFlags flags
,
104 uint32_t interfaceIndex
,
105 DNSServiceErrorType errorCode
,
106 const char *fullName
, uint16_t rrtype
,
107 uint16_t rrclass
, uint16_t rdlen
,
108 const void *rdata
, uint32_t ttl
,
110 static void sigterm_handler(int sig
);
111 static void unquote(char *dst
, const char *src
, size_t dstsize
);
115 * 'main()' - Browse for printers.
118 int /* O - Exit status */
119 main(int argc
, /* I - Number of command-line args */
120 char *argv
[]) /* I - Command-line arguments */
122 const char *name
; /* Backend name */
123 DNSServiceRef main_ref
, /* Main service reference */
124 fax_ipp_ref
, /* IPP fax service reference */
125 ipp_ref
, /* IPP service reference */
126 ipp_tls_ref
, /* IPP w/TLS service reference */
127 ipps_ref
, /* IPP service reference */
128 local_fax_ipp_ref
, /* Local IPP fax service reference */
129 local_ipp_ref
, /* Local IPP service reference */
130 local_ipp_tls_ref
, /* Local IPP w/TLS service reference */
131 local_ipps_ref
, /* Local IPP service reference */
132 local_printer_ref
, /* Local LPD service reference */
133 pdl_datastream_ref
, /* AppSocket service reference */
134 printer_ref
, /* LPD service reference */
135 riousbprint_ref
; /* Remote IO service reference */
136 int fd
; /* Main file descriptor */
137 fd_set input
; /* Input set for select() */
138 struct timeval timeout
; /* Timeout for select() */
139 cups_array_t
*devices
; /* Device array */
140 cups_device_t
*device
; /* Current device */
141 char uriName
[1024]; /* Unquoted fullName for URI */
142 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
143 struct sigaction action
; /* Actions for POSIX signals */
144 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
148 * Don't buffer stderr, and catch SIGTERM...
151 setbuf(stderr
, NULL
);
153 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
154 sigset(SIGTERM
, sigterm_handler
);
155 #elif defined(HAVE_SIGACTION)
156 memset(&action
, 0, sizeof(action
));
158 sigemptyset(&action
.sa_mask
);
159 action
.sa_handler
= sigterm_handler
;
160 sigaction(SIGTERM
, &action
, NULL
);
162 signal(SIGTERM
, sigterm_handler
);
163 #endif /* HAVE_SIGSET */
166 * Check command-line...
173 _cupsLangPrintf(stderr
,
174 _("Usage: %s job-id user title copies options [file]"),
180 * Only do discovery when run as "dnssd"...
183 if ((name
= strrchr(argv
[0], '/')) != NULL
)
188 if (strcmp(name
, "dnssd"))
192 * Create an array to track devices...
195 devices
= cupsArrayNew((cups_array_func_t
)compare_devices
, NULL
);
198 * Browse for different kinds of printers...
201 if (DNSServiceCreateConnection(&main_ref
) != kDNSServiceErr_NoError
)
203 perror("ERROR: Unable to create service connection");
207 fd
= DNSServiceRefSockFD(main_ref
);
209 fax_ipp_ref
= main_ref
;
210 DNSServiceBrowse(&fax_ipp_ref
, kDNSServiceFlagsShareConnection
, 0,
211 "_fax-ipp._tcp", NULL
, browse_callback
, devices
);
214 DNSServiceBrowse(&ipp_ref
, kDNSServiceFlagsShareConnection
, 0,
215 "_ipp._tcp", NULL
, browse_callback
, devices
);
217 ipp_tls_ref
= main_ref
;
218 DNSServiceBrowse(&ipp_tls_ref
, kDNSServiceFlagsShareConnection
, 0,
219 "_ipp-tls._tcp", NULL
, browse_callback
, devices
);
222 DNSServiceBrowse(&ipps_ref
, kDNSServiceFlagsShareConnection
, 0,
223 "_ipps._tcp", NULL
, browse_callback
, devices
);
225 local_fax_ipp_ref
= main_ref
;
226 DNSServiceBrowse(&local_fax_ipp_ref
, kDNSServiceFlagsShareConnection
,
227 kDNSServiceInterfaceIndexLocalOnly
,
228 "_fax-ipp._tcp", NULL
, browse_local_callback
, devices
);
230 local_ipp_ref
= main_ref
;
231 DNSServiceBrowse(&local_ipp_ref
, kDNSServiceFlagsShareConnection
,
232 kDNSServiceInterfaceIndexLocalOnly
,
233 "_ipp._tcp", NULL
, browse_local_callback
, devices
);
235 local_ipp_tls_ref
= main_ref
;
236 DNSServiceBrowse(&local_ipp_tls_ref
, kDNSServiceFlagsShareConnection
,
237 kDNSServiceInterfaceIndexLocalOnly
,
238 "_ipp-tls._tcp", NULL
, browse_local_callback
, devices
);
240 local_ipps_ref
= main_ref
;
241 DNSServiceBrowse(&local_ipps_ref
, kDNSServiceFlagsShareConnection
,
242 kDNSServiceInterfaceIndexLocalOnly
,
243 "_ipps._tcp", NULL
, browse_local_callback
, devices
);
245 local_printer_ref
= main_ref
;
246 DNSServiceBrowse(&local_printer_ref
, kDNSServiceFlagsShareConnection
,
247 kDNSServiceInterfaceIndexLocalOnly
,
248 "_printer._tcp", NULL
, browse_local_callback
, devices
);
250 pdl_datastream_ref
= main_ref
;
251 DNSServiceBrowse(&pdl_datastream_ref
, kDNSServiceFlagsShareConnection
, 0,
252 "_pdl-datastream._tcp", NULL
, browse_callback
, devices
);
254 printer_ref
= main_ref
;
255 DNSServiceBrowse(&printer_ref
, kDNSServiceFlagsShareConnection
, 0,
256 "_printer._tcp", NULL
, browse_callback
, devices
);
258 riousbprint_ref
= main_ref
;
259 DNSServiceBrowse(&riousbprint_ref
, kDNSServiceFlagsShareConnection
, 0,
260 "_riousbprint._tcp", NULL
, browse_callback
, devices
);
263 * Loop until we are killed...
266 while (!job_canceled
)
272 timeout
.tv_usec
= 250000;
274 if (select(fd
+ 1, &input
, NULL
, NULL
, &timeout
) < 0)
277 if (FD_ISSET(fd
, &input
))
280 * Process results of our browsing...
283 DNSServiceProcessResult(main_ref
);
288 * Announce any devices we've found...
291 DNSServiceErrorType status
; /* DNS query status */
292 cups_device_t
*best
; /* Best matching device */
293 char device_uri
[1024]; /* Device URI */
294 int count
; /* Number of queries */
295 int sent
; /* Number of sent */
297 for (device
= (cups_device_t
*)cupsArrayFirst(devices
),
298 best
= NULL
, count
= 0, sent
= 0;
300 device
= (cups_device_t
*)cupsArrayNext(devices
))
308 if (!device
->ref
&& !device
->sent
)
311 * Found the device, now get the TXT record(s) for it...
316 device
->ref
= main_ref
;
318 fprintf(stderr
, "DEBUG: Querying \"%s\"...\n", device
->fullName
);
320 status
= DNSServiceQueryRecord(&(device
->ref
),
321 kDNSServiceFlagsShareConnection
,
324 kDNSServiceClass_IN
, query_callback
,
326 if (status
!= kDNSServiceErr_NoError
)
328 fputs("ERROR: Unable to query for TXT records!\n", stderr
);
329 fprintf(stderr
, "DEBUG: DNSServiceQueryRecord returned %d\n",
336 else if (!device
->sent
)
339 * Got the TXT records, now report the device...
342 DNSServiceRefDeallocate(device
->ref
);
347 else if (_cups_strcasecmp(best
->name
, device
->name
) ||
348 _cups_strcasecmp(best
->domain
, device
->domain
))
350 unquote(uriName
, best
->fullName
, sizeof(uriName
));
352 httpAssembleURI(HTTP_URI_CODING_ALL
, device_uri
, sizeof(device_uri
),
353 "dnssd", NULL
, uriName
, 0,
354 best
->cups_shared
? "/cups" : "/");
356 cupsBackendReport("network", device_uri
, best
->make_and_model
,
357 best
->name
, best
->device_id
, NULL
);
363 else if (best
->priority
> device
->priority
||
364 (best
->priority
== device
->priority
&&
365 best
->type
< device
->type
))
383 unquote(uriName
, best
->fullName
, sizeof(uriName
));
385 httpAssembleURI(HTTP_URI_CODING_ALL
, device_uri
, sizeof(device_uri
),
386 "dnssd", NULL
, uriName
, 0,
387 best
->cups_shared
? "/cups" : "/");
389 cupsBackendReport("network", device_uri
, best
->make_and_model
,
390 best
->name
, best
->device_id
, NULL
);
395 if (sent
== cupsArrayCount(devices
))
400 return (CUPS_BACKEND_OK
);
405 * 'browse_callback()' - Browse devices.
410 DNSServiceRef sdRef
, /* I - Service reference */
411 DNSServiceFlags flags
, /* I - Option flags */
412 uint32_t interfaceIndex
, /* I - Interface number */
413 DNSServiceErrorType errorCode
, /* I - Error, if any */
414 const char *serviceName
, /* I - Name of service/device */
415 const char *regtype
, /* I - Type of service */
416 const char *replyDomain
, /* I - Service domain */
417 void *context
) /* I - Devices array */
419 fprintf(stderr
, "DEBUG2: browse_callback(sdRef=%p, flags=%x, "
420 "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
421 "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
422 sdRef
, flags
, interfaceIndex
, errorCode
,
423 serviceName
? serviceName
: "(null)",
424 regtype
? regtype
: "(null)",
425 replyDomain
? replyDomain
: "(null)",
429 * Only process "add" data...
432 if (errorCode
!= kDNSServiceErr_NoError
|| !(flags
& kDNSServiceFlagsAdd
))
439 get_device((cups_array_t
*)context
, serviceName
, regtype
, replyDomain
);
444 * 'browse_local_callback()' - Browse local devices.
448 browse_local_callback(
449 DNSServiceRef sdRef
, /* I - Service reference */
450 DNSServiceFlags flags
, /* I - Option flags */
451 uint32_t interfaceIndex
, /* I - Interface number */
452 DNSServiceErrorType errorCode
, /* I - Error, if any */
453 const char *serviceName
, /* I - Name of service/device */
454 const char *regtype
, /* I - Type of service */
455 const char *replyDomain
, /* I - Service domain */
456 void *context
) /* I - Devices array */
458 cups_device_t
*device
; /* Device */
461 fprintf(stderr
, "DEBUG2: browse_local_callback(sdRef=%p, flags=%x, "
462 "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
463 "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
464 sdRef
, flags
, interfaceIndex
, errorCode
,
465 serviceName
? serviceName
: "(null)",
466 regtype
? regtype
: "(null)",
467 replyDomain
? replyDomain
: "(null)",
471 * Only process "add" data...
474 if (errorCode
!= kDNSServiceErr_NoError
|| !(flags
& kDNSServiceFlagsAdd
))
481 device
= get_device((cups_array_t
*)context
, serviceName
, regtype
,
485 * Hide locally-registered devices...
488 fprintf(stderr
, "DEBUG: Hiding local printer \"%s\"...\n",
495 * 'compare_devices()' - Compare two devices.
498 static int /* O - Result of comparison */
499 compare_devices(cups_device_t
*a
, /* I - First device */
500 cups_device_t
*b
) /* I - Second device */
502 return (strcmp(a
->name
, b
->name
));
507 * 'exec_backend()' - Execute the backend that corresponds to the
508 * resolved service name.
512 exec_backend(char **argv
) /* I - Command-line arguments */
514 const char *resolved_uri
, /* Resolved device URI */
515 *cups_serverbin
; /* Location of programs */
516 char scheme
[1024], /* Scheme from URI */
517 *ptr
, /* Pointer into scheme */
518 filename
[1024]; /* Backend filename */
522 * Resolve the device URI...
527 while ((resolved_uri
= cupsBackendDeviceURI(argv
)) == NULL
)
529 _cupsLangPrintFilter(stderr
, "INFO", _("Unable to locate printer."));
532 if (getenv("CLASS") != NULL
)
533 exit(CUPS_BACKEND_FAILED
);
537 * Extract the scheme from the URI...
540 strlcpy(scheme
, resolved_uri
, sizeof(scheme
));
541 if ((ptr
= strchr(scheme
, ':')) != NULL
)
545 * Get the filename of the backend...
548 if ((cups_serverbin
= getenv("CUPS_SERVERBIN")) == NULL
)
549 cups_serverbin
= CUPS_SERVERBIN
;
551 snprintf(filename
, sizeof(filename
), "%s/backend/%s", cups_serverbin
, scheme
);
554 * Overwrite the device URI and run the new backend...
557 setenv("DEVICE_URI", resolved_uri
, 1);
559 argv
[0] = (char *)resolved_uri
;
561 fprintf(stderr
, "DEBUG: Executing backend \"%s\"...\n", filename
);
563 execv(filename
, argv
);
565 fprintf(stderr
, "ERROR: Unable to execute backend \"%s\": %s\n", filename
,
567 exit(CUPS_BACKEND_STOP
);
572 * 'get_device()' - Create or update a device.
575 static cups_device_t
* /* O - Device */
576 get_device(cups_array_t
*devices
, /* I - Device array */
577 const char *serviceName
, /* I - Name of service/device */
578 const char *regtype
, /* I - Type of service */
579 const char *replyDomain
) /* I - Service domain */
581 cups_device_t key
, /* Search key */
582 *device
; /* Device */
583 char fullName
[kDNSServiceMaxDomainName
];
584 /* Full name for query */
588 * See if this is a new device...
591 key
.name
= (char *)serviceName
;
593 if (!strcmp(regtype
, "_ipp._tcp."))
594 key
.type
= CUPS_DEVICE_IPP
;
595 else if (!strcmp(regtype
, "_ipps._tcp.") ||
596 !strcmp(regtype
, "_ipp-tls._tcp."))
597 key
.type
= CUPS_DEVICE_IPPS
;
598 else if (!strcmp(regtype
, "_fax-ipp._tcp."))
599 key
.type
= CUPS_DEVICE_FAX_IPP
;
600 else if (!strcmp(regtype
, "_printer._tcp."))
601 key
.type
= CUPS_DEVICE_PRINTER
;
602 else if (!strcmp(regtype
, "_pdl-datastream._tcp."))
603 key
.type
= CUPS_DEVICE_PDL_DATASTREAM
;
605 key
.type
= CUPS_DEVICE_RIOUSBPRINT
;
607 for (device
= cupsArrayFind(devices
, &key
);
609 device
= cupsArrayNext(devices
))
610 if (_cups_strcasecmp(device
->name
, key
.name
))
612 else if (device
->type
== key
.type
)
614 if (!_cups_strcasecmp(device
->domain
, "local.") &&
615 _cups_strcasecmp(device
->domain
, replyDomain
))
618 * Update the .local listing to use the "global" domain name instead.
619 * The backend will try local lookups first, then the global domain name.
622 free(device
->domain
);
623 device
->domain
= strdup(replyDomain
);
625 DNSServiceConstructFullName(fullName
, device
->name
, regtype
,
627 free(device
->fullName
);
628 device
->fullName
= strdup(fullName
);
635 * Yes, add the device...
638 fprintf(stderr
, "DEBUG: Found \"%s.%s%s\"...\n", serviceName
, regtype
,
641 device
= calloc(sizeof(cups_device_t
), 1);
642 device
->name
= strdup(serviceName
);
643 device
->domain
= strdup(replyDomain
);
644 device
->type
= key
.type
;
645 device
->priority
= 50;
647 cupsArrayAdd(devices
, device
);
650 * Set the "full name" of this service, which is used for queries...
653 DNSServiceConstructFullName(fullName
, serviceName
, regtype
, replyDomain
);
654 device
->fullName
= strdup(fullName
);
661 * 'query_callback()' - Process query data.
666 DNSServiceRef sdRef
, /* I - Service reference */
667 DNSServiceFlags flags
, /* I - Data flags */
668 uint32_t interfaceIndex
, /* I - Interface */
669 DNSServiceErrorType errorCode
, /* I - Error, if any */
670 const char *fullName
, /* I - Full service name */
671 uint16_t rrtype
, /* I - Record type */
672 uint16_t rrclass
, /* I - Record class */
673 uint16_t rdlen
, /* I - Length of record data */
674 const void *rdata
, /* I - Record data */
675 uint32_t ttl
, /* I - Time-to-live */
676 void *context
) /* I - Devices array */
678 cups_array_t
*devices
; /* Device array */
679 char name
[1024], /* Service name */
680 *ptr
; /* Pointer into string */
681 cups_device_t dkey
, /* Search key */
682 *device
; /* Device */
685 fprintf(stderr
, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
686 "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
687 "rrtype=%u, rrclass=%u, rdlen=%u, rdata=%p, ttl=%u, "
689 sdRef
, flags
, interfaceIndex
, errorCode
,
690 fullName
? fullName
: "(null)", rrtype
, rrclass
, rdlen
, rdata
, ttl
,
694 * Only process "add" data...
697 if (errorCode
!= kDNSServiceErr_NoError
|| !(flags
& kDNSServiceFlagsAdd
))
701 * Lookup the service in the devices array.
704 devices
= (cups_array_t
*)context
;
707 unquote(name
, fullName
, sizeof(name
));
709 if ((dkey
.domain
= strstr(name
, "._tcp.")) != NULL
)
712 dkey
.domain
= (char *)"local.";
714 if ((ptr
= strstr(name
, "._")) != NULL
)
717 if (strstr(fullName
, "_ipp._tcp."))
718 dkey
.type
= CUPS_DEVICE_IPP
;
719 else if (strstr(fullName
, "_ipps._tcp.") ||
720 strstr(fullName
, "_ipp-tls._tcp."))
721 dkey
.type
= CUPS_DEVICE_IPPS
;
722 else if (strstr(fullName
, "_fax-ipp._tcp."))
723 dkey
.type
= CUPS_DEVICE_FAX_IPP
;
724 else if (strstr(fullName
, "_printer._tcp."))
725 dkey
.type
= CUPS_DEVICE_PRINTER
;
726 else if (strstr(fullName
, "_pdl-datastream._tcp."))
727 dkey
.type
= CUPS_DEVICE_PDL_DATASTREAM
;
729 dkey
.type
= CUPS_DEVICE_RIOUSBPRINT
;
731 for (device
= cupsArrayFind(devices
, &dkey
);
733 device
= cupsArrayNext(devices
))
735 if (_cups_strcasecmp(device
->name
, dkey
.name
) ||
736 _cups_strcasecmp(device
->domain
, dkey
.domain
))
741 else if (device
->type
== dkey
.type
)
744 * Found it, pull out the priority and make and model from the TXT
745 * record and save it...
748 const uint8_t *data
, /* Pointer into data */
749 *datanext
, /* Next key/value pair */
750 *dataend
; /* End of entire TXT record */
751 uint8_t datalen
; /* Length of current key/value pair */
752 char key
[256], /* Key string */
753 value
[256], /* Value string */
755 /* Manufacturer and model */
756 model
[256], /* Model */
757 device_id
[2048];/* 1284 device ID */
761 make_and_model
[0] = '\0';
763 strcpy(model
, "Unknown");
765 for (data
= rdata
, dataend
= data
+ rdlen
;
770 * Read a key/value pair starting with an 8-bit length. Since the
771 * length is 8 bits and the size of the key/value buffers is 256, we
772 * don't need to check for overflow...
777 if (!datalen
|| (data
+ datalen
) > dataend
)
780 datanext
= data
+ datalen
;
782 for (ptr
= key
; data
< datanext
&& *data
!= '='; data
++)
786 if (data
< datanext
&& *data
== '=')
791 memcpy(value
, data
, datanext
- data
);
792 value
[datanext
- data
] = '\0';
794 fprintf(stderr
, "DEBUG2: query_callback: \"%s=%s\".\n",
799 fprintf(stderr
, "DEBUG2: query_callback: \"%s\" with no value.\n",
804 if (!_cups_strncasecmp(key
, "usb_", 4))
807 * Add USB device ID information...
810 ptr
= device_id
+ strlen(device_id
);
811 snprintf(ptr
, sizeof(device_id
) - (ptr
- device_id
), "%s:%s;",
815 if (!_cups_strcasecmp(key
, "usb_MFG") || !_cups_strcasecmp(key
, "usb_MANU") ||
816 !_cups_strcasecmp(key
, "usb_MANUFACTURER"))
817 strcpy(make_and_model
, value
);
818 else if (!_cups_strcasecmp(key
, "usb_MDL") || !_cups_strcasecmp(key
, "usb_MODEL"))
819 strcpy(model
, value
);
820 else if (!_cups_strcasecmp(key
, "product") && !strstr(value
, "Ghostscript"))
825 * Strip parenthesis...
828 if ((ptr
= value
+ strlen(value
) - 1) > value
&& *ptr
== ')')
831 strcpy(model
, value
+ 1);
834 strcpy(model
, value
);
836 else if (!_cups_strcasecmp(key
, "ty"))
838 strcpy(model
, value
);
840 if ((ptr
= strchr(model
, ',')) != NULL
)
843 else if (!_cups_strcasecmp(key
, "priority"))
844 device
->priority
= atoi(value
);
845 else if ((device
->type
== CUPS_DEVICE_IPP
||
846 device
->type
== CUPS_DEVICE_IPPS
||
847 device
->type
== CUPS_DEVICE_PRINTER
) &&
848 !_cups_strcasecmp(key
, "printer-type"))
851 * This is a CUPS printer!
854 device
->cups_shared
= 1;
856 if (device
->type
== CUPS_DEVICE_PRINTER
)
861 if (device
->device_id
)
862 free(device
->device_id
);
864 if (!device_id
[0] && strcmp(model
, "Unknown"))
866 if (make_and_model
[0])
867 snprintf(device_id
, sizeof(device_id
), "MFG:%s;MDL:%s;",
868 make_and_model
, model
);
869 else if (!_cups_strncasecmp(model
, "designjet ", 10))
870 snprintf(device_id
, sizeof(device_id
), "MFG:HP;MDL:%s", model
+ 10);
871 else if (!_cups_strncasecmp(model
, "stylus ", 7))
872 snprintf(device_id
, sizeof(device_id
), "MFG:EPSON;MDL:%s", model
+ 7);
873 else if ((ptr
= strchr(model
, ' ')) != NULL
)
876 * Assume the first word is the make...
879 memcpy(make_and_model
, model
, ptr
- model
);
880 make_and_model
[ptr
- model
] = '\0';
882 snprintf(device_id
, sizeof(device_id
), "MFG:%s;MDL:%s",
883 make_and_model
, ptr
+ 1);
888 device
->device_id
= strdup(device_id
);
890 device
->device_id
= NULL
;
892 if (device
->make_and_model
)
893 free(device
->make_and_model
);
895 if (make_and_model
[0])
897 strlcat(make_and_model
, " ", sizeof(make_and_model
));
898 strlcat(make_and_model
, model
, sizeof(make_and_model
));
900 device
->make_and_model
= strdup(make_and_model
);
903 device
->make_and_model
= strdup(model
);
909 fprintf(stderr
, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName
);
914 * 'sigterm_handler()' - Handle termination signals...
918 sigterm_handler(int sig
) /* I - Signal number (unused) */
923 exit(CUPS_BACKEND_OK
);
930 * 'unquote()' - Unquote a name string.
934 unquote(char *dst
, /* I - Destination buffer */
935 const char *src
, /* I - Source string */
936 size_t dstsize
) /* I - Size of destination buffer */
938 char *dstend
= dst
+ dstsize
- 1; /* End of destination buffer */
941 while (*src
&& dst
< dstend
)
946 if (isdigit(src
[0] & 255) && isdigit(src
[1] & 255) &&
947 isdigit(src
[2] & 255))
949 *dst
++ = ((((src
[0] - '0') * 10) + src
[1] - '0') * 10) + src
[2] - '0';