1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * DNS-SD discovery backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2008-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker *
6*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
7*5e7646d2SAndroid Build Coastguard Worker * information.
8*5e7646d2SAndroid Build Coastguard Worker */
9*5e7646d2SAndroid Build Coastguard Worker
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include <cups/array.h>
16*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
17*5e7646d2SAndroid Build Coastguard Worker # include <dns_sd.h>
18*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
19*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
20*5e7646d2SAndroid Build Coastguard Worker # include <avahi-client/client.h>
21*5e7646d2SAndroid Build Coastguard Worker # include <avahi-client/lookup.h>
22*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/simple-watch.h>
23*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/domain.h>
24*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/error.h>
25*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/malloc.h>
26*5e7646d2SAndroid Build Coastguard Worker #define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
27*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker
30*5e7646d2SAndroid Build Coastguard Worker /*
31*5e7646d2SAndroid Build Coastguard Worker * Device structure...
32*5e7646d2SAndroid Build Coastguard Worker */
33*5e7646d2SAndroid Build Coastguard Worker
34*5e7646d2SAndroid Build Coastguard Worker typedef enum
35*5e7646d2SAndroid Build Coastguard Worker {
36*5e7646d2SAndroid Build Coastguard Worker CUPS_DEVICE_PRINTER = 0, /* lpd://... */
37*5e7646d2SAndroid Build Coastguard Worker CUPS_DEVICE_IPPS, /* ipps://... */
38*5e7646d2SAndroid Build Coastguard Worker CUPS_DEVICE_IPP, /* ipp://... */
39*5e7646d2SAndroid Build Coastguard Worker CUPS_DEVICE_FAX_IPP, /* ipp://... */
40*5e7646d2SAndroid Build Coastguard Worker CUPS_DEVICE_PDL_DATASTREAM, /* socket://... */
41*5e7646d2SAndroid Build Coastguard Worker CUPS_DEVICE_RIOUSBPRINT /* riousbprint://... */
42*5e7646d2SAndroid Build Coastguard Worker } cups_devtype_t;
43*5e7646d2SAndroid Build Coastguard Worker
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker typedef struct
46*5e7646d2SAndroid Build Coastguard Worker {
47*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
48*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef ref; /* Service reference for query */
49*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
50*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
51*5e7646d2SAndroid Build Coastguard Worker AvahiRecordBrowser *ref; /* Browser for query */
52*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
53*5e7646d2SAndroid Build Coastguard Worker char *name, /* Service name */
54*5e7646d2SAndroid Build Coastguard Worker *domain, /* Domain name */
55*5e7646d2SAndroid Build Coastguard Worker *fullName, /* Full name */
56*5e7646d2SAndroid Build Coastguard Worker *make_and_model, /* Make and model from TXT record */
57*5e7646d2SAndroid Build Coastguard Worker *device_id, /* 1284 device ID from TXT record */
58*5e7646d2SAndroid Build Coastguard Worker *uuid; /* UUID from TXT record */
59*5e7646d2SAndroid Build Coastguard Worker cups_devtype_t type; /* Device registration type */
60*5e7646d2SAndroid Build Coastguard Worker int priority, /* Priority associated with type */
61*5e7646d2SAndroid Build Coastguard Worker cups_shared, /* CUPS shared printer? */
62*5e7646d2SAndroid Build Coastguard Worker sent; /* Did we list the device? */
63*5e7646d2SAndroid Build Coastguard Worker } cups_device_t;
64*5e7646d2SAndroid Build Coastguard Worker
65*5e7646d2SAndroid Build Coastguard Worker
66*5e7646d2SAndroid Build Coastguard Worker /*
67*5e7646d2SAndroid Build Coastguard Worker * Local globals...
68*5e7646d2SAndroid Build Coastguard Worker */
69*5e7646d2SAndroid Build Coastguard Worker
70*5e7646d2SAndroid Build Coastguard Worker static int job_canceled = 0;
71*5e7646d2SAndroid Build Coastguard Worker /* Set to 1 on SIGTERM */
72*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
73*5e7646d2SAndroid Build Coastguard Worker static AvahiSimplePoll *simple_poll = NULL;
74*5e7646d2SAndroid Build Coastguard Worker /* Poll information */
75*5e7646d2SAndroid Build Coastguard Worker static int got_data = 0; /* Got data from poll? */
76*5e7646d2SAndroid Build Coastguard Worker static int browsers = 0; /* Number of running browsers */
77*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
78*5e7646d2SAndroid Build Coastguard Worker
79*5e7646d2SAndroid Build Coastguard Worker
80*5e7646d2SAndroid Build Coastguard Worker /*
81*5e7646d2SAndroid Build Coastguard Worker * Local functions...
82*5e7646d2SAndroid Build Coastguard Worker */
83*5e7646d2SAndroid Build Coastguard Worker
84*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
85*5e7646d2SAndroid Build Coastguard Worker static void browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8);
86*5e7646d2SAndroid Build Coastguard Worker static void browse_local_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8);
87*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
88*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
89*5e7646d2SAndroid Build Coastguard Worker static void browse_callback(AvahiServiceBrowser *browser,
90*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface,
91*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol,
92*5e7646d2SAndroid Build Coastguard Worker AvahiBrowserEvent event,
93*5e7646d2SAndroid Build Coastguard Worker const char *serviceName,
94*5e7646d2SAndroid Build Coastguard Worker const char *regtype,
95*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain,
96*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags,
97*5e7646d2SAndroid Build Coastguard Worker void *context);
98*5e7646d2SAndroid Build Coastguard Worker static void client_callback(AvahiClient *client,
99*5e7646d2SAndroid Build Coastguard Worker AvahiClientState state,
100*5e7646d2SAndroid Build Coastguard Worker void *context);
101*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
102*5e7646d2SAndroid Build Coastguard Worker
103*5e7646d2SAndroid Build Coastguard Worker static int compare_devices(cups_device_t *a, cups_device_t *b);
104*5e7646d2SAndroid Build Coastguard Worker static void exec_backend(char **argv) _CUPS_NORETURN;
105*5e7646d2SAndroid Build Coastguard Worker static cups_device_t *get_device(cups_array_t *devices, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4);
106*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
107*5e7646d2SAndroid Build Coastguard Worker static void query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullName, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) _CUPS_NONNULL(1,5,9,11);
108*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
109*5e7646d2SAndroid Build Coastguard Worker static int poll_callback(struct pollfd *pollfds,
110*5e7646d2SAndroid Build Coastguard Worker unsigned int num_pollfds, int timeout,
111*5e7646d2SAndroid Build Coastguard Worker void *context);
112*5e7646d2SAndroid Build Coastguard Worker static void query_callback(AvahiRecordBrowser *browser,
113*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface,
114*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol,
115*5e7646d2SAndroid Build Coastguard Worker AvahiBrowserEvent event,
116*5e7646d2SAndroid Build Coastguard Worker const char *name, uint16_t rrclass,
117*5e7646d2SAndroid Build Coastguard Worker uint16_t rrtype, const void *rdata,
118*5e7646d2SAndroid Build Coastguard Worker size_t rdlen,
119*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags,
120*5e7646d2SAndroid Build Coastguard Worker void *context);
121*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
122*5e7646d2SAndroid Build Coastguard Worker static void sigterm_handler(int sig);
123*5e7646d2SAndroid Build Coastguard Worker static void unquote(char *dst, const char *src, size_t dstsize) _CUPS_NONNULL(1,2);
124*5e7646d2SAndroid Build Coastguard Worker
125*5e7646d2SAndroid Build Coastguard Worker
126*5e7646d2SAndroid Build Coastguard Worker /*
127*5e7646d2SAndroid Build Coastguard Worker * 'main()' - Browse for printers.
128*5e7646d2SAndroid Build Coastguard Worker */
129*5e7646d2SAndroid Build Coastguard Worker
130*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit status */
main(int argc,char * argv[])131*5e7646d2SAndroid Build Coastguard Worker main(int argc, /* I - Number of command-line args */
132*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
133*5e7646d2SAndroid Build Coastguard Worker {
134*5e7646d2SAndroid Build Coastguard Worker const char *name; /* Backend name */
135*5e7646d2SAndroid Build Coastguard Worker cups_array_t *devices; /* Device array */
136*5e7646d2SAndroid Build Coastguard Worker cups_device_t *device; /* Current device */
137*5e7646d2SAndroid Build Coastguard Worker char uriName[1024]; /* Unquoted fullName for URI */
138*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
139*5e7646d2SAndroid Build Coastguard Worker int fd; /* Main file descriptor */
140*5e7646d2SAndroid Build Coastguard Worker fd_set input; /* Input set for select() */
141*5e7646d2SAndroid Build Coastguard Worker struct timeval timeout; /* Timeout for select() */
142*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef main_ref, /* Main service reference */
143*5e7646d2SAndroid Build Coastguard Worker fax_ipp_ref, /* IPP fax service reference */
144*5e7646d2SAndroid Build Coastguard Worker ipp_ref, /* IPP service reference */
145*5e7646d2SAndroid Build Coastguard Worker ipp_tls_ref, /* IPP w/TLS service reference */
146*5e7646d2SAndroid Build Coastguard Worker ipps_ref, /* IPP service reference */
147*5e7646d2SAndroid Build Coastguard Worker local_fax_ipp_ref, /* Local IPP fax service reference */
148*5e7646d2SAndroid Build Coastguard Worker local_ipp_ref, /* Local IPP service reference */
149*5e7646d2SAndroid Build Coastguard Worker local_ipp_tls_ref, /* Local IPP w/TLS service reference */
150*5e7646d2SAndroid Build Coastguard Worker local_ipps_ref, /* Local IPP service reference */
151*5e7646d2SAndroid Build Coastguard Worker local_printer_ref, /* Local LPD service reference */
152*5e7646d2SAndroid Build Coastguard Worker pdl_datastream_ref, /* AppSocket service reference */
153*5e7646d2SAndroid Build Coastguard Worker printer_ref, /* LPD service reference */
154*5e7646d2SAndroid Build Coastguard Worker riousbprint_ref; /* Remote IO service reference */
155*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
156*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
157*5e7646d2SAndroid Build Coastguard Worker AvahiClient *client; /* Client information */
158*5e7646d2SAndroid Build Coastguard Worker int error; /* Error code, if any */
159*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
160*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
161*5e7646d2SAndroid Build Coastguard Worker struct sigaction action; /* Actions for POSIX signals */
162*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
163*5e7646d2SAndroid Build Coastguard Worker
164*5e7646d2SAndroid Build Coastguard Worker
165*5e7646d2SAndroid Build Coastguard Worker /*
166*5e7646d2SAndroid Build Coastguard Worker * Don't buffer stderr, and catch SIGTERM...
167*5e7646d2SAndroid Build Coastguard Worker */
168*5e7646d2SAndroid Build Coastguard Worker
169*5e7646d2SAndroid Build Coastguard Worker setbuf(stderr, NULL);
170*5e7646d2SAndroid Build Coastguard Worker
171*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
172*5e7646d2SAndroid Build Coastguard Worker sigset(SIGTERM, sigterm_handler);
173*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
174*5e7646d2SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
175*5e7646d2SAndroid Build Coastguard Worker
176*5e7646d2SAndroid Build Coastguard Worker sigemptyset(&action.sa_mask);
177*5e7646d2SAndroid Build Coastguard Worker action.sa_handler = sigterm_handler;
178*5e7646d2SAndroid Build Coastguard Worker sigaction(SIGTERM, &action, NULL);
179*5e7646d2SAndroid Build Coastguard Worker #else
180*5e7646d2SAndroid Build Coastguard Worker signal(SIGTERM, sigterm_handler);
181*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
182*5e7646d2SAndroid Build Coastguard Worker
183*5e7646d2SAndroid Build Coastguard Worker /*
184*5e7646d2SAndroid Build Coastguard Worker * Check command-line...
185*5e7646d2SAndroid Build Coastguard Worker */
186*5e7646d2SAndroid Build Coastguard Worker
187*5e7646d2SAndroid Build Coastguard Worker if (argc >= 6)
188*5e7646d2SAndroid Build Coastguard Worker exec_backend(argv);
189*5e7646d2SAndroid Build Coastguard Worker else if (argc != 1)
190*5e7646d2SAndroid Build Coastguard Worker {
191*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
192*5e7646d2SAndroid Build Coastguard Worker _("Usage: %s job-id user title copies options [file]"),
193*5e7646d2SAndroid Build Coastguard Worker argv[0]);
194*5e7646d2SAndroid Build Coastguard Worker return (1);
195*5e7646d2SAndroid Build Coastguard Worker }
196*5e7646d2SAndroid Build Coastguard Worker
197*5e7646d2SAndroid Build Coastguard Worker /*
198*5e7646d2SAndroid Build Coastguard Worker * Only do discovery when run as "dnssd"...
199*5e7646d2SAndroid Build Coastguard Worker */
200*5e7646d2SAndroid Build Coastguard Worker
201*5e7646d2SAndroid Build Coastguard Worker if ((name = strrchr(argv[0], '/')) != NULL)
202*5e7646d2SAndroid Build Coastguard Worker name ++;
203*5e7646d2SAndroid Build Coastguard Worker else
204*5e7646d2SAndroid Build Coastguard Worker name = argv[0];
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker if (strcmp(name, "dnssd"))
207*5e7646d2SAndroid Build Coastguard Worker return (0);
208*5e7646d2SAndroid Build Coastguard Worker
209*5e7646d2SAndroid Build Coastguard Worker /*
210*5e7646d2SAndroid Build Coastguard Worker * Create an array to track devices...
211*5e7646d2SAndroid Build Coastguard Worker */
212*5e7646d2SAndroid Build Coastguard Worker
213*5e7646d2SAndroid Build Coastguard Worker devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);
214*5e7646d2SAndroid Build Coastguard Worker
215*5e7646d2SAndroid Build Coastguard Worker /*
216*5e7646d2SAndroid Build Coastguard Worker * Browse for different kinds of printers...
217*5e7646d2SAndroid Build Coastguard Worker */
218*5e7646d2SAndroid Build Coastguard Worker
219*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
220*5e7646d2SAndroid Build Coastguard Worker if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
221*5e7646d2SAndroid Build Coastguard Worker {
222*5e7646d2SAndroid Build Coastguard Worker perror("ERROR: Unable to create service connection");
223*5e7646d2SAndroid Build Coastguard Worker return (1);
224*5e7646d2SAndroid Build Coastguard Worker }
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker fd = DNSServiceRefSockFD(main_ref);
227*5e7646d2SAndroid Build Coastguard Worker
228*5e7646d2SAndroid Build Coastguard Worker fax_ipp_ref = main_ref;
229*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0,
230*5e7646d2SAndroid Build Coastguard Worker "_fax-ipp._tcp", NULL, browse_callback, devices);
231*5e7646d2SAndroid Build Coastguard Worker
232*5e7646d2SAndroid Build Coastguard Worker ipp_ref = main_ref;
233*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
234*5e7646d2SAndroid Build Coastguard Worker "_ipp._tcp", NULL, browse_callback, devices);
235*5e7646d2SAndroid Build Coastguard Worker
236*5e7646d2SAndroid Build Coastguard Worker ipp_tls_ref = main_ref;
237*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0,
238*5e7646d2SAndroid Build Coastguard Worker "_ipp-tls._tcp", NULL, browse_callback, devices);
239*5e7646d2SAndroid Build Coastguard Worker
240*5e7646d2SAndroid Build Coastguard Worker ipps_ref = main_ref;
241*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0,
242*5e7646d2SAndroid Build Coastguard Worker "_ipps._tcp", NULL, browse_callback, devices);
243*5e7646d2SAndroid Build Coastguard Worker
244*5e7646d2SAndroid Build Coastguard Worker local_fax_ipp_ref = main_ref;
245*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection,
246*5e7646d2SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexLocalOnly,
247*5e7646d2SAndroid Build Coastguard Worker "_fax-ipp._tcp", NULL, browse_local_callback, devices);
248*5e7646d2SAndroid Build Coastguard Worker
249*5e7646d2SAndroid Build Coastguard Worker local_ipp_ref = main_ref;
250*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
251*5e7646d2SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexLocalOnly,
252*5e7646d2SAndroid Build Coastguard Worker "_ipp._tcp", NULL, browse_local_callback, devices);
253*5e7646d2SAndroid Build Coastguard Worker
254*5e7646d2SAndroid Build Coastguard Worker local_ipp_tls_ref = main_ref;
255*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection,
256*5e7646d2SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexLocalOnly,
257*5e7646d2SAndroid Build Coastguard Worker "_ipp-tls._tcp", NULL, browse_local_callback, devices);
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker local_ipps_ref = main_ref;
260*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection,
261*5e7646d2SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexLocalOnly,
262*5e7646d2SAndroid Build Coastguard Worker "_ipps._tcp", NULL, browse_local_callback, devices);
263*5e7646d2SAndroid Build Coastguard Worker
264*5e7646d2SAndroid Build Coastguard Worker local_printer_ref = main_ref;
265*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection,
266*5e7646d2SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexLocalOnly,
267*5e7646d2SAndroid Build Coastguard Worker "_printer._tcp", NULL, browse_local_callback, devices);
268*5e7646d2SAndroid Build Coastguard Worker
269*5e7646d2SAndroid Build Coastguard Worker pdl_datastream_ref = main_ref;
270*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0,
271*5e7646d2SAndroid Build Coastguard Worker "_pdl-datastream._tcp", NULL, browse_callback, devices);
272*5e7646d2SAndroid Build Coastguard Worker
273*5e7646d2SAndroid Build Coastguard Worker printer_ref = main_ref;
274*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0,
275*5e7646d2SAndroid Build Coastguard Worker "_printer._tcp", NULL, browse_callback, devices);
276*5e7646d2SAndroid Build Coastguard Worker
277*5e7646d2SAndroid Build Coastguard Worker riousbprint_ref = main_ref;
278*5e7646d2SAndroid Build Coastguard Worker DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
279*5e7646d2SAndroid Build Coastguard Worker "_riousbprint._tcp", NULL, browse_callback, devices);
280*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
281*5e7646d2SAndroid Build Coastguard Worker
282*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
283*5e7646d2SAndroid Build Coastguard Worker if ((simple_poll = avahi_simple_poll_new()) == NULL)
284*5e7646d2SAndroid Build Coastguard Worker {
285*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr);
286*5e7646d2SAndroid Build Coastguard Worker return (0);
287*5e7646d2SAndroid Build Coastguard Worker }
288*5e7646d2SAndroid Build Coastguard Worker
289*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_set_func(simple_poll, poll_callback, NULL);
290*5e7646d2SAndroid Build Coastguard Worker
291*5e7646d2SAndroid Build Coastguard Worker client = avahi_client_new(avahi_simple_poll_get(simple_poll),
292*5e7646d2SAndroid Build Coastguard Worker 0, client_callback, simple_poll, &error);
293*5e7646d2SAndroid Build Coastguard Worker if (!client)
294*5e7646d2SAndroid Build Coastguard Worker {
295*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Unable to create Avahi client.\n", stderr);
296*5e7646d2SAndroid Build Coastguard Worker return (0);
297*5e7646d2SAndroid Build Coastguard Worker }
298*5e7646d2SAndroid Build Coastguard Worker
299*5e7646d2SAndroid Build Coastguard Worker browsers = 6;
300*5e7646d2SAndroid Build Coastguard Worker avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
301*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
302*5e7646d2SAndroid Build Coastguard Worker "_fax-ipp._tcp", NULL, 0,
303*5e7646d2SAndroid Build Coastguard Worker browse_callback, devices);
304*5e7646d2SAndroid Build Coastguard Worker avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
305*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
306*5e7646d2SAndroid Build Coastguard Worker "_ipp._tcp", NULL, 0,
307*5e7646d2SAndroid Build Coastguard Worker browse_callback, devices);
308*5e7646d2SAndroid Build Coastguard Worker avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
309*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
310*5e7646d2SAndroid Build Coastguard Worker "_ipp-tls._tcp", NULL, 0,
311*5e7646d2SAndroid Build Coastguard Worker browse_callback, devices);
312*5e7646d2SAndroid Build Coastguard Worker avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
313*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
314*5e7646d2SAndroid Build Coastguard Worker "_ipps._tcp", NULL, 0,
315*5e7646d2SAndroid Build Coastguard Worker browse_callback, devices);
316*5e7646d2SAndroid Build Coastguard Worker avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
317*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
318*5e7646d2SAndroid Build Coastguard Worker "_pdl-datastream._tcp",
319*5e7646d2SAndroid Build Coastguard Worker NULL, 0,
320*5e7646d2SAndroid Build Coastguard Worker browse_callback,
321*5e7646d2SAndroid Build Coastguard Worker devices);
322*5e7646d2SAndroid Build Coastguard Worker avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
323*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
324*5e7646d2SAndroid Build Coastguard Worker "_printer._tcp", NULL, 0,
325*5e7646d2SAndroid Build Coastguard Worker browse_callback, devices);
326*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
327*5e7646d2SAndroid Build Coastguard Worker
328*5e7646d2SAndroid Build Coastguard Worker /*
329*5e7646d2SAndroid Build Coastguard Worker * Loop until we are killed...
330*5e7646d2SAndroid Build Coastguard Worker */
331*5e7646d2SAndroid Build Coastguard Worker
332*5e7646d2SAndroid Build Coastguard Worker while (!job_canceled)
333*5e7646d2SAndroid Build Coastguard Worker {
334*5e7646d2SAndroid Build Coastguard Worker int announce = 0; /* Announce printers? */
335*5e7646d2SAndroid Build Coastguard Worker
336*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
337*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&input);
338*5e7646d2SAndroid Build Coastguard Worker FD_SET(fd, &input);
339*5e7646d2SAndroid Build Coastguard Worker
340*5e7646d2SAndroid Build Coastguard Worker timeout.tv_sec = 0;
341*5e7646d2SAndroid Build Coastguard Worker timeout.tv_usec = 500000;
342*5e7646d2SAndroid Build Coastguard Worker
343*5e7646d2SAndroid Build Coastguard Worker if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
344*5e7646d2SAndroid Build Coastguard Worker continue;
345*5e7646d2SAndroid Build Coastguard Worker
346*5e7646d2SAndroid Build Coastguard Worker if (FD_ISSET(fd, &input))
347*5e7646d2SAndroid Build Coastguard Worker {
348*5e7646d2SAndroid Build Coastguard Worker /*
349*5e7646d2SAndroid Build Coastguard Worker * Process results of our browsing...
350*5e7646d2SAndroid Build Coastguard Worker */
351*5e7646d2SAndroid Build Coastguard Worker
352*5e7646d2SAndroid Build Coastguard Worker DNSServiceProcessResult(main_ref);
353*5e7646d2SAndroid Build Coastguard Worker }
354*5e7646d2SAndroid Build Coastguard Worker else
355*5e7646d2SAndroid Build Coastguard Worker announce = 1;
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
358*5e7646d2SAndroid Build Coastguard Worker got_data = 0;
359*5e7646d2SAndroid Build Coastguard Worker
360*5e7646d2SAndroid Build Coastguard Worker if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0)
361*5e7646d2SAndroid Build Coastguard Worker {
362*5e7646d2SAndroid Build Coastguard Worker /*
363*5e7646d2SAndroid Build Coastguard Worker * We've been told to exit the loop. Perhaps the connection to
364*5e7646d2SAndroid Build Coastguard Worker * Avahi failed.
365*5e7646d2SAndroid Build Coastguard Worker */
366*5e7646d2SAndroid Build Coastguard Worker
367*5e7646d2SAndroid Build Coastguard Worker break;
368*5e7646d2SAndroid Build Coastguard Worker }
369*5e7646d2SAndroid Build Coastguard Worker
370*5e7646d2SAndroid Build Coastguard Worker if (!got_data)
371*5e7646d2SAndroid Build Coastguard Worker announce = 1;
372*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
373*5e7646d2SAndroid Build Coastguard Worker
374*5e7646d2SAndroid Build Coastguard Worker /* fprintf(stderr, "DEBUG: announce=%d\n", announce);*/
375*5e7646d2SAndroid Build Coastguard Worker
376*5e7646d2SAndroid Build Coastguard Worker if (announce)
377*5e7646d2SAndroid Build Coastguard Worker {
378*5e7646d2SAndroid Build Coastguard Worker /*
379*5e7646d2SAndroid Build Coastguard Worker * Announce any devices we've found...
380*5e7646d2SAndroid Build Coastguard Worker */
381*5e7646d2SAndroid Build Coastguard Worker
382*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
383*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType status; /* DNS query status */
384*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
385*5e7646d2SAndroid Build Coastguard Worker cups_device_t *best; /* Best matching device */
386*5e7646d2SAndroid Build Coastguard Worker char device_uri[1024]; /* Device URI */
387*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of queries */
388*5e7646d2SAndroid Build Coastguard Worker int sent; /* Number of sent */
389*5e7646d2SAndroid Build Coastguard Worker
390*5e7646d2SAndroid Build Coastguard Worker for (device = (cups_device_t *)cupsArrayFirst(devices),
391*5e7646d2SAndroid Build Coastguard Worker best = NULL, count = 0, sent = 0;
392*5e7646d2SAndroid Build Coastguard Worker device;
393*5e7646d2SAndroid Build Coastguard Worker device = (cups_device_t *)cupsArrayNext(devices))
394*5e7646d2SAndroid Build Coastguard Worker {
395*5e7646d2SAndroid Build Coastguard Worker if (device->sent)
396*5e7646d2SAndroid Build Coastguard Worker sent ++;
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker if (device->ref)
399*5e7646d2SAndroid Build Coastguard Worker count ++;
400*5e7646d2SAndroid Build Coastguard Worker
401*5e7646d2SAndroid Build Coastguard Worker if (!device->ref && !device->sent)
402*5e7646d2SAndroid Build Coastguard Worker {
403*5e7646d2SAndroid Build Coastguard Worker /*
404*5e7646d2SAndroid Build Coastguard Worker * Found the device, now get the TXT record(s) for it...
405*5e7646d2SAndroid Build Coastguard Worker */
406*5e7646d2SAndroid Build Coastguard Worker
407*5e7646d2SAndroid Build Coastguard Worker if (count < 50)
408*5e7646d2SAndroid Build Coastguard Worker {
409*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName);
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
412*5e7646d2SAndroid Build Coastguard Worker device->ref = main_ref;
413*5e7646d2SAndroid Build Coastguard Worker
414*5e7646d2SAndroid Build Coastguard Worker status = DNSServiceQueryRecord(&(device->ref),
415*5e7646d2SAndroid Build Coastguard Worker kDNSServiceFlagsShareConnection,
416*5e7646d2SAndroid Build Coastguard Worker 0, device->fullName,
417*5e7646d2SAndroid Build Coastguard Worker kDNSServiceType_TXT,
418*5e7646d2SAndroid Build Coastguard Worker kDNSServiceClass_IN, query_callback,
419*5e7646d2SAndroid Build Coastguard Worker device);
420*5e7646d2SAndroid Build Coastguard Worker if (status != kDNSServiceErr_NoError)
421*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
422*5e7646d2SAndroid Build Coastguard Worker "ERROR: Unable to query \"%s\" for TXT records: %d\n",
423*5e7646d2SAndroid Build Coastguard Worker device->fullName, status);
424*5e7646d2SAndroid Build Coastguard Worker /* Users never see this */
425*5e7646d2SAndroid Build Coastguard Worker else
426*5e7646d2SAndroid Build Coastguard Worker count ++;
427*5e7646d2SAndroid Build Coastguard Worker
428*5e7646d2SAndroid Build Coastguard Worker #else
429*5e7646d2SAndroid Build Coastguard Worker if ((device->ref = avahi_record_browser_new(client, AVAHI_IF_UNSPEC,
430*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
431*5e7646d2SAndroid Build Coastguard Worker device->fullName,
432*5e7646d2SAndroid Build Coastguard Worker AVAHI_DNS_CLASS_IN,
433*5e7646d2SAndroid Build Coastguard Worker AVAHI_DNS_TYPE_TXT,
434*5e7646d2SAndroid Build Coastguard Worker 0,
435*5e7646d2SAndroid Build Coastguard Worker query_callback,
436*5e7646d2SAndroid Build Coastguard Worker device)) == NULL)
437*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
438*5e7646d2SAndroid Build Coastguard Worker "ERROR: Unable to query \"%s\" for TXT records: %s\n",
439*5e7646d2SAndroid Build Coastguard Worker device->fullName,
440*5e7646d2SAndroid Build Coastguard Worker avahi_strerror(avahi_client_errno(client)));
441*5e7646d2SAndroid Build Coastguard Worker /* Users never see this */
442*5e7646d2SAndroid Build Coastguard Worker else
443*5e7646d2SAndroid Build Coastguard Worker count ++;
444*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
445*5e7646d2SAndroid Build Coastguard Worker }
446*5e7646d2SAndroid Build Coastguard Worker }
447*5e7646d2SAndroid Build Coastguard Worker else if (!device->sent)
448*5e7646d2SAndroid Build Coastguard Worker {
449*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
450*5e7646d2SAndroid Build Coastguard Worker /*
451*5e7646d2SAndroid Build Coastguard Worker * Got the TXT records, now report the device...
452*5e7646d2SAndroid Build Coastguard Worker */
453*5e7646d2SAndroid Build Coastguard Worker
454*5e7646d2SAndroid Build Coastguard Worker DNSServiceRefDeallocate(device->ref);
455*5e7646d2SAndroid Build Coastguard Worker #else
456*5e7646d2SAndroid Build Coastguard Worker avahi_record_browser_free(device->ref);
457*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
458*5e7646d2SAndroid Build Coastguard Worker
459*5e7646d2SAndroid Build Coastguard Worker device->ref = NULL;
460*5e7646d2SAndroid Build Coastguard Worker
461*5e7646d2SAndroid Build Coastguard Worker if (!best)
462*5e7646d2SAndroid Build Coastguard Worker best = device;
463*5e7646d2SAndroid Build Coastguard Worker else if (_cups_strcasecmp(best->name, device->name) ||
464*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(best->domain, device->domain))
465*5e7646d2SAndroid Build Coastguard Worker {
466*5e7646d2SAndroid Build Coastguard Worker unquote(uriName, best->fullName, sizeof(uriName));
467*5e7646d2SAndroid Build Coastguard Worker
468*5e7646d2SAndroid Build Coastguard Worker if (best->uuid)
469*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
470*5e7646d2SAndroid Build Coastguard Worker sizeof(device_uri), "dnssd", NULL, uriName, 0,
471*5e7646d2SAndroid Build Coastguard Worker best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
472*5e7646d2SAndroid Build Coastguard Worker best->uuid);
473*5e7646d2SAndroid Build Coastguard Worker else
474*5e7646d2SAndroid Build Coastguard Worker httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
475*5e7646d2SAndroid Build Coastguard Worker sizeof(device_uri), "dnssd", NULL, uriName, 0,
476*5e7646d2SAndroid Build Coastguard Worker best->cups_shared ? "/cups" : "/");
477*5e7646d2SAndroid Build Coastguard Worker
478*5e7646d2SAndroid Build Coastguard Worker cupsBackendReport("network", device_uri, best->make_and_model,
479*5e7646d2SAndroid Build Coastguard Worker best->name, best->device_id, NULL);
480*5e7646d2SAndroid Build Coastguard Worker best->sent = 1;
481*5e7646d2SAndroid Build Coastguard Worker best = device;
482*5e7646d2SAndroid Build Coastguard Worker
483*5e7646d2SAndroid Build Coastguard Worker sent ++;
484*5e7646d2SAndroid Build Coastguard Worker }
485*5e7646d2SAndroid Build Coastguard Worker else if (best->priority > device->priority ||
486*5e7646d2SAndroid Build Coastguard Worker (best->priority == device->priority &&
487*5e7646d2SAndroid Build Coastguard Worker best->type < device->type))
488*5e7646d2SAndroid Build Coastguard Worker {
489*5e7646d2SAndroid Build Coastguard Worker best->sent = 1;
490*5e7646d2SAndroid Build Coastguard Worker best = device;
491*5e7646d2SAndroid Build Coastguard Worker
492*5e7646d2SAndroid Build Coastguard Worker sent ++;
493*5e7646d2SAndroid Build Coastguard Worker }
494*5e7646d2SAndroid Build Coastguard Worker else
495*5e7646d2SAndroid Build Coastguard Worker {
496*5e7646d2SAndroid Build Coastguard Worker device->sent = 1;
497*5e7646d2SAndroid Build Coastguard Worker
498*5e7646d2SAndroid Build Coastguard Worker sent ++;
499*5e7646d2SAndroid Build Coastguard Worker }
500*5e7646d2SAndroid Build Coastguard Worker }
501*5e7646d2SAndroid Build Coastguard Worker }
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker if (best)
504*5e7646d2SAndroid Build Coastguard Worker {
505*5e7646d2SAndroid Build Coastguard Worker unquote(uriName, best->fullName, sizeof(uriName));
506*5e7646d2SAndroid Build Coastguard Worker
507*5e7646d2SAndroid Build Coastguard Worker if (best->uuid)
508*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
509*5e7646d2SAndroid Build Coastguard Worker sizeof(device_uri), "dnssd", NULL, uriName, 0,
510*5e7646d2SAndroid Build Coastguard Worker best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
511*5e7646d2SAndroid Build Coastguard Worker best->uuid);
512*5e7646d2SAndroid Build Coastguard Worker else
513*5e7646d2SAndroid Build Coastguard Worker httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
514*5e7646d2SAndroid Build Coastguard Worker sizeof(device_uri), "dnssd", NULL, uriName, 0,
515*5e7646d2SAndroid Build Coastguard Worker best->cups_shared ? "/cups" : "/");
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker cupsBackendReport("network", device_uri, best->make_and_model,
518*5e7646d2SAndroid Build Coastguard Worker best->name, best->device_id, NULL);
519*5e7646d2SAndroid Build Coastguard Worker best->sent = 1;
520*5e7646d2SAndroid Build Coastguard Worker sent ++;
521*5e7646d2SAndroid Build Coastguard Worker }
522*5e7646d2SAndroid Build Coastguard Worker
523*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count);
524*5e7646d2SAndroid Build Coastguard Worker
525*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
526*5e7646d2SAndroid Build Coastguard Worker if (sent == cupsArrayCount(devices) && browsers == 0)
527*5e7646d2SAndroid Build Coastguard Worker #else
528*5e7646d2SAndroid Build Coastguard Worker if (sent == cupsArrayCount(devices))
529*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
530*5e7646d2SAndroid Build Coastguard Worker break;
531*5e7646d2SAndroid Build Coastguard Worker }
532*5e7646d2SAndroid Build Coastguard Worker }
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
535*5e7646d2SAndroid Build Coastguard Worker }
536*5e7646d2SAndroid Build Coastguard Worker
537*5e7646d2SAndroid Build Coastguard Worker
538*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
539*5e7646d2SAndroid Build Coastguard Worker /*
540*5e7646d2SAndroid Build Coastguard Worker * 'browse_callback()' - Browse devices.
541*5e7646d2SAndroid Build Coastguard Worker */
542*5e7646d2SAndroid Build Coastguard Worker
543*5e7646d2SAndroid Build Coastguard Worker static void
browse_callback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regtype,const char * replyDomain,void * context)544*5e7646d2SAndroid Build Coastguard Worker browse_callback(
545*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef sdRef, /* I - Service reference */
546*5e7646d2SAndroid Build Coastguard Worker DNSServiceFlags flags, /* I - Option flags */
547*5e7646d2SAndroid Build Coastguard Worker uint32_t interfaceIndex, /* I - Interface number */
548*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType errorCode, /* I - Error, if any */
549*5e7646d2SAndroid Build Coastguard Worker const char *serviceName, /* I - Name of service/device */
550*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Type of service */
551*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain, /* I - Service domain */
552*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Devices array */
553*5e7646d2SAndroid Build Coastguard Worker {
554*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: browse_callback(sdRef=%p, flags=%x, "
555*5e7646d2SAndroid Build Coastguard Worker "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
556*5e7646d2SAndroid Build Coastguard Worker "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
557*5e7646d2SAndroid Build Coastguard Worker sdRef, flags, interfaceIndex, errorCode,
558*5e7646d2SAndroid Build Coastguard Worker serviceName, regtype, replyDomain, context);
559*5e7646d2SAndroid Build Coastguard Worker
560*5e7646d2SAndroid Build Coastguard Worker /*
561*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
562*5e7646d2SAndroid Build Coastguard Worker */
563*5e7646d2SAndroid Build Coastguard Worker
564*5e7646d2SAndroid Build Coastguard Worker if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
565*5e7646d2SAndroid Build Coastguard Worker return;
566*5e7646d2SAndroid Build Coastguard Worker
567*5e7646d2SAndroid Build Coastguard Worker /*
568*5e7646d2SAndroid Build Coastguard Worker * Get the device...
569*5e7646d2SAndroid Build Coastguard Worker */
570*5e7646d2SAndroid Build Coastguard Worker
571*5e7646d2SAndroid Build Coastguard Worker get_device((cups_array_t *)context, serviceName, regtype, replyDomain);
572*5e7646d2SAndroid Build Coastguard Worker }
573*5e7646d2SAndroid Build Coastguard Worker
574*5e7646d2SAndroid Build Coastguard Worker
575*5e7646d2SAndroid Build Coastguard Worker /*
576*5e7646d2SAndroid Build Coastguard Worker * 'browse_local_callback()' - Browse local devices.
577*5e7646d2SAndroid Build Coastguard Worker */
578*5e7646d2SAndroid Build Coastguard Worker
579*5e7646d2SAndroid Build Coastguard Worker static void
browse_local_callback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regtype,const char * replyDomain,void * context)580*5e7646d2SAndroid Build Coastguard Worker browse_local_callback(
581*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef sdRef, /* I - Service reference */
582*5e7646d2SAndroid Build Coastguard Worker DNSServiceFlags flags, /* I - Option flags */
583*5e7646d2SAndroid Build Coastguard Worker uint32_t interfaceIndex, /* I - Interface number */
584*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType errorCode, /* I - Error, if any */
585*5e7646d2SAndroid Build Coastguard Worker const char *serviceName, /* I - Name of service/device */
586*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Type of service */
587*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain, /* I - Service domain */
588*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Devices array */
589*5e7646d2SAndroid Build Coastguard Worker {
590*5e7646d2SAndroid Build Coastguard Worker cups_device_t *device; /* Device */
591*5e7646d2SAndroid Build Coastguard Worker
592*5e7646d2SAndroid Build Coastguard Worker
593*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: browse_local_callback(sdRef=%p, flags=%x, "
594*5e7646d2SAndroid Build Coastguard Worker "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
595*5e7646d2SAndroid Build Coastguard Worker "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
596*5e7646d2SAndroid Build Coastguard Worker sdRef, flags, interfaceIndex, errorCode,
597*5e7646d2SAndroid Build Coastguard Worker serviceName, regtype, replyDomain, context);
598*5e7646d2SAndroid Build Coastguard Worker
599*5e7646d2SAndroid Build Coastguard Worker /*
600*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
601*5e7646d2SAndroid Build Coastguard Worker */
602*5e7646d2SAndroid Build Coastguard Worker
603*5e7646d2SAndroid Build Coastguard Worker if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
604*5e7646d2SAndroid Build Coastguard Worker return;
605*5e7646d2SAndroid Build Coastguard Worker
606*5e7646d2SAndroid Build Coastguard Worker /*
607*5e7646d2SAndroid Build Coastguard Worker * Get the device...
608*5e7646d2SAndroid Build Coastguard Worker */
609*5e7646d2SAndroid Build Coastguard Worker
610*5e7646d2SAndroid Build Coastguard Worker device = get_device((cups_array_t *)context, serviceName, regtype,
611*5e7646d2SAndroid Build Coastguard Worker replyDomain);
612*5e7646d2SAndroid Build Coastguard Worker
613*5e7646d2SAndroid Build Coastguard Worker /*
614*5e7646d2SAndroid Build Coastguard Worker * Hide locally-registered devices...
615*5e7646d2SAndroid Build Coastguard Worker */
616*5e7646d2SAndroid Build Coastguard Worker
617*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Hiding local printer \"%s\"...\n",
618*5e7646d2SAndroid Build Coastguard Worker device->fullName);
619*5e7646d2SAndroid Build Coastguard Worker device->sent = 1;
620*5e7646d2SAndroid Build Coastguard Worker }
621*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
622*5e7646d2SAndroid Build Coastguard Worker
623*5e7646d2SAndroid Build Coastguard Worker
624*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
625*5e7646d2SAndroid Build Coastguard Worker /*
626*5e7646d2SAndroid Build Coastguard Worker * 'browse_callback()' - Browse devices.
627*5e7646d2SAndroid Build Coastguard Worker */
628*5e7646d2SAndroid Build Coastguard Worker
629*5e7646d2SAndroid Build Coastguard Worker static void
browse_callback(AvahiServiceBrowser * browser,AvahiIfIndex interface,AvahiProtocol protocol,AvahiBrowserEvent event,const char * name,const char * type,const char * domain,AvahiLookupResultFlags flags,void * context)630*5e7646d2SAndroid Build Coastguard Worker browse_callback(
631*5e7646d2SAndroid Build Coastguard Worker AvahiServiceBrowser *browser, /* I - Browser */
632*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface, /* I - Interface index (unused) */
633*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol, /* I - Network protocol (unused) */
634*5e7646d2SAndroid Build Coastguard Worker AvahiBrowserEvent event, /* I - What happened */
635*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Service name */
636*5e7646d2SAndroid Build Coastguard Worker const char *type, /* I - Registration type */
637*5e7646d2SAndroid Build Coastguard Worker const char *domain, /* I - Domain */
638*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags, /* I - Flags */
639*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Devices array */
640*5e7646d2SAndroid Build Coastguard Worker {
641*5e7646d2SAndroid Build Coastguard Worker AvahiClient *client = avahi_service_browser_get_client(browser);
642*5e7646d2SAndroid Build Coastguard Worker /* Client information */
643*5e7646d2SAndroid Build Coastguard Worker
644*5e7646d2SAndroid Build Coastguard Worker
645*5e7646d2SAndroid Build Coastguard Worker (void)interface;
646*5e7646d2SAndroid Build Coastguard Worker (void)protocol;
647*5e7646d2SAndroid Build Coastguard Worker (void)context;
648*5e7646d2SAndroid Build Coastguard Worker
649*5e7646d2SAndroid Build Coastguard Worker switch (event)
650*5e7646d2SAndroid Build Coastguard Worker {
651*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_FAILURE:
652*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: browse_callback: %s\n",
653*5e7646d2SAndroid Build Coastguard Worker avahi_strerror(avahi_client_errno(client)));
654*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_quit(simple_poll);
655*5e7646d2SAndroid Build Coastguard Worker break;
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_NEW:
658*5e7646d2SAndroid Build Coastguard Worker /*
659*5e7646d2SAndroid Build Coastguard Worker * This object is new on the network.
660*5e7646d2SAndroid Build Coastguard Worker */
661*5e7646d2SAndroid Build Coastguard Worker
662*5e7646d2SAndroid Build Coastguard Worker if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
663*5e7646d2SAndroid Build Coastguard Worker {
664*5e7646d2SAndroid Build Coastguard Worker /*
665*5e7646d2SAndroid Build Coastguard Worker * This comes from the local machine so ignore it.
666*5e7646d2SAndroid Build Coastguard Worker */
667*5e7646d2SAndroid Build Coastguard Worker
668*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Ignoring local service %s.\n", name);
669*5e7646d2SAndroid Build Coastguard Worker }
670*5e7646d2SAndroid Build Coastguard Worker else
671*5e7646d2SAndroid Build Coastguard Worker {
672*5e7646d2SAndroid Build Coastguard Worker /*
673*5e7646d2SAndroid Build Coastguard Worker * Create a device entry for it if it doesn't yet exist.
674*5e7646d2SAndroid Build Coastguard Worker */
675*5e7646d2SAndroid Build Coastguard Worker
676*5e7646d2SAndroid Build Coastguard Worker get_device((cups_array_t *)context, name, type, domain);
677*5e7646d2SAndroid Build Coastguard Worker }
678*5e7646d2SAndroid Build Coastguard Worker break;
679*5e7646d2SAndroid Build Coastguard Worker
680*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_REMOVE:
681*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_CACHE_EXHAUSTED:
682*5e7646d2SAndroid Build Coastguard Worker break;
683*5e7646d2SAndroid Build Coastguard Worker
684*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_ALL_FOR_NOW:
685*5e7646d2SAndroid Build Coastguard Worker browsers--;
686*5e7646d2SAndroid Build Coastguard Worker break;
687*5e7646d2SAndroid Build Coastguard Worker }
688*5e7646d2SAndroid Build Coastguard Worker }
689*5e7646d2SAndroid Build Coastguard Worker
690*5e7646d2SAndroid Build Coastguard Worker
691*5e7646d2SAndroid Build Coastguard Worker /*
692*5e7646d2SAndroid Build Coastguard Worker * 'client_callback()' - Avahi client callback function.
693*5e7646d2SAndroid Build Coastguard Worker */
694*5e7646d2SAndroid Build Coastguard Worker
695*5e7646d2SAndroid Build Coastguard Worker static void
client_callback(AvahiClient * client,AvahiClientState state,void * context)696*5e7646d2SAndroid Build Coastguard Worker client_callback(
697*5e7646d2SAndroid Build Coastguard Worker AvahiClient *client, /* I - Client information (unused) */
698*5e7646d2SAndroid Build Coastguard Worker AvahiClientState state, /* I - Current state */
699*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - User data (unused) */
700*5e7646d2SAndroid Build Coastguard Worker {
701*5e7646d2SAndroid Build Coastguard Worker (void)client;
702*5e7646d2SAndroid Build Coastguard Worker (void)context;
703*5e7646d2SAndroid Build Coastguard Worker
704*5e7646d2SAndroid Build Coastguard Worker /*
705*5e7646d2SAndroid Build Coastguard Worker * If the connection drops, quit.
706*5e7646d2SAndroid Build Coastguard Worker */
707*5e7646d2SAndroid Build Coastguard Worker
708*5e7646d2SAndroid Build Coastguard Worker if (state == AVAHI_CLIENT_FAILURE)
709*5e7646d2SAndroid Build Coastguard Worker {
710*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Avahi connection failed.\n", stderr);
711*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_quit(simple_poll);
712*5e7646d2SAndroid Build Coastguard Worker }
713*5e7646d2SAndroid Build Coastguard Worker }
714*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
715*5e7646d2SAndroid Build Coastguard Worker
716*5e7646d2SAndroid Build Coastguard Worker
717*5e7646d2SAndroid Build Coastguard Worker /*
718*5e7646d2SAndroid Build Coastguard Worker * 'compare_devices()' - Compare two devices.
719*5e7646d2SAndroid Build Coastguard Worker */
720*5e7646d2SAndroid Build Coastguard Worker
721*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
compare_devices(cups_device_t * a,cups_device_t * b)722*5e7646d2SAndroid Build Coastguard Worker compare_devices(cups_device_t *a, /* I - First device */
723*5e7646d2SAndroid Build Coastguard Worker cups_device_t *b) /* I - Second device */
724*5e7646d2SAndroid Build Coastguard Worker {
725*5e7646d2SAndroid Build Coastguard Worker return (strcmp(a->name, b->name));
726*5e7646d2SAndroid Build Coastguard Worker }
727*5e7646d2SAndroid Build Coastguard Worker
728*5e7646d2SAndroid Build Coastguard Worker
729*5e7646d2SAndroid Build Coastguard Worker /*
730*5e7646d2SAndroid Build Coastguard Worker * 'exec_backend()' - Execute the backend that corresponds to the
731*5e7646d2SAndroid Build Coastguard Worker * resolved service name.
732*5e7646d2SAndroid Build Coastguard Worker */
733*5e7646d2SAndroid Build Coastguard Worker
734*5e7646d2SAndroid Build Coastguard Worker static void
exec_backend(char ** argv)735*5e7646d2SAndroid Build Coastguard Worker exec_backend(char **argv) /* I - Command-line arguments */
736*5e7646d2SAndroid Build Coastguard Worker {
737*5e7646d2SAndroid Build Coastguard Worker const char *resolved_uri, /* Resolved device URI */
738*5e7646d2SAndroid Build Coastguard Worker *cups_serverbin; /* Location of programs */
739*5e7646d2SAndroid Build Coastguard Worker char scheme[1024], /* Scheme from URI */
740*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into scheme */
741*5e7646d2SAndroid Build Coastguard Worker filename[1024]; /* Backend filename */
742*5e7646d2SAndroid Build Coastguard Worker
743*5e7646d2SAndroid Build Coastguard Worker
744*5e7646d2SAndroid Build Coastguard Worker /*
745*5e7646d2SAndroid Build Coastguard Worker * Resolve the device URI...
746*5e7646d2SAndroid Build Coastguard Worker */
747*5e7646d2SAndroid Build Coastguard Worker
748*5e7646d2SAndroid Build Coastguard Worker job_canceled = -1;
749*5e7646d2SAndroid Build Coastguard Worker
750*5e7646d2SAndroid Build Coastguard Worker while ((resolved_uri = cupsBackendDeviceURI(argv)) == NULL)
751*5e7646d2SAndroid Build Coastguard Worker {
752*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
753*5e7646d2SAndroid Build Coastguard Worker sleep(10);
754*5e7646d2SAndroid Build Coastguard Worker
755*5e7646d2SAndroid Build Coastguard Worker if (getenv("CLASS") != NULL)
756*5e7646d2SAndroid Build Coastguard Worker exit(CUPS_BACKEND_FAILED);
757*5e7646d2SAndroid Build Coastguard Worker }
758*5e7646d2SAndroid Build Coastguard Worker
759*5e7646d2SAndroid Build Coastguard Worker /*
760*5e7646d2SAndroid Build Coastguard Worker * Extract the scheme from the URI...
761*5e7646d2SAndroid Build Coastguard Worker */
762*5e7646d2SAndroid Build Coastguard Worker
763*5e7646d2SAndroid Build Coastguard Worker strlcpy(scheme, resolved_uri, sizeof(scheme));
764*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strchr(scheme, ':')) != NULL)
765*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
766*5e7646d2SAndroid Build Coastguard Worker
767*5e7646d2SAndroid Build Coastguard Worker /*
768*5e7646d2SAndroid Build Coastguard Worker * Get the filename of the backend...
769*5e7646d2SAndroid Build Coastguard Worker */
770*5e7646d2SAndroid Build Coastguard Worker
771*5e7646d2SAndroid Build Coastguard Worker if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
772*5e7646d2SAndroid Build Coastguard Worker cups_serverbin = CUPS_SERVERBIN;
773*5e7646d2SAndroid Build Coastguard Worker
774*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/backend/%s", cups_serverbin, scheme);
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker /*
777*5e7646d2SAndroid Build Coastguard Worker * Overwrite the device URI and run the new backend...
778*5e7646d2SAndroid Build Coastguard Worker */
779*5e7646d2SAndroid Build Coastguard Worker
780*5e7646d2SAndroid Build Coastguard Worker setenv("DEVICE_URI", resolved_uri, 1);
781*5e7646d2SAndroid Build Coastguard Worker
782*5e7646d2SAndroid Build Coastguard Worker argv[0] = (char *)resolved_uri;
783*5e7646d2SAndroid Build Coastguard Worker
784*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Executing backend \"%s\"...\n", filename);
785*5e7646d2SAndroid Build Coastguard Worker
786*5e7646d2SAndroid Build Coastguard Worker execv(filename, argv);
787*5e7646d2SAndroid Build Coastguard Worker
788*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Unable to execute backend \"%s\": %s\n", filename,
789*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
790*5e7646d2SAndroid Build Coastguard Worker exit(CUPS_BACKEND_STOP);
791*5e7646d2SAndroid Build Coastguard Worker }
792*5e7646d2SAndroid Build Coastguard Worker
793*5e7646d2SAndroid Build Coastguard Worker
794*5e7646d2SAndroid Build Coastguard Worker /*
795*5e7646d2SAndroid Build Coastguard Worker * 'device_type()' - Get DNS-SD type enumeration from string.
796*5e7646d2SAndroid Build Coastguard Worker */
797*5e7646d2SAndroid Build Coastguard Worker
798*5e7646d2SAndroid Build Coastguard Worker static cups_devtype_t /* O - Device type */
device_type(const char * regtype)799*5e7646d2SAndroid Build Coastguard Worker device_type(const char *regtype) /* I - Service registration type */
800*5e7646d2SAndroid Build Coastguard Worker {
801*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
802*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(regtype, "_ipp._tcp"))
803*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_IPP);
804*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_ipps._tcp") ||
805*5e7646d2SAndroid Build Coastguard Worker !strcmp(regtype, "_ipp-tls._tcp"))
806*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_IPPS);
807*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_fax-ipp._tcp"))
808*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_FAX_IPP);
809*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_printer._tcp"))
810*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_PDL_DATASTREAM);
811*5e7646d2SAndroid Build Coastguard Worker #else
812*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(regtype, "_ipp._tcp."))
813*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_IPP);
814*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_ipps._tcp.") ||
815*5e7646d2SAndroid Build Coastguard Worker !strcmp(regtype, "_ipp-tls._tcp."))
816*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_IPPS);
817*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_fax-ipp._tcp."))
818*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_FAX_IPP);
819*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_printer._tcp."))
820*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_PRINTER);
821*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(regtype, "_pdl-datastream._tcp."))
822*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_PDL_DATASTREAM);
823*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
824*5e7646d2SAndroid Build Coastguard Worker
825*5e7646d2SAndroid Build Coastguard Worker return (CUPS_DEVICE_RIOUSBPRINT);
826*5e7646d2SAndroid Build Coastguard Worker }
827*5e7646d2SAndroid Build Coastguard Worker
828*5e7646d2SAndroid Build Coastguard Worker
829*5e7646d2SAndroid Build Coastguard Worker /*
830*5e7646d2SAndroid Build Coastguard Worker * 'get_device()' - Create or update a device.
831*5e7646d2SAndroid Build Coastguard Worker */
832*5e7646d2SAndroid Build Coastguard Worker
833*5e7646d2SAndroid Build Coastguard Worker static cups_device_t * /* O - Device */
get_device(cups_array_t * devices,const char * serviceName,const char * regtype,const char * replyDomain)834*5e7646d2SAndroid Build Coastguard Worker get_device(cups_array_t *devices, /* I - Device array */
835*5e7646d2SAndroid Build Coastguard Worker const char *serviceName, /* I - Name of service/device */
836*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Type of service */
837*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain) /* I - Service domain */
838*5e7646d2SAndroid Build Coastguard Worker {
839*5e7646d2SAndroid Build Coastguard Worker cups_device_t key, /* Search key */
840*5e7646d2SAndroid Build Coastguard Worker *device; /* Device */
841*5e7646d2SAndroid Build Coastguard Worker char fullName[kDNSServiceMaxDomainName];
842*5e7646d2SAndroid Build Coastguard Worker /* Full name for query */
843*5e7646d2SAndroid Build Coastguard Worker
844*5e7646d2SAndroid Build Coastguard Worker
845*5e7646d2SAndroid Build Coastguard Worker /*
846*5e7646d2SAndroid Build Coastguard Worker * See if this is a new device...
847*5e7646d2SAndroid Build Coastguard Worker */
848*5e7646d2SAndroid Build Coastguard Worker
849*5e7646d2SAndroid Build Coastguard Worker key.name = (char *)serviceName;
850*5e7646d2SAndroid Build Coastguard Worker key.type = device_type(regtype);
851*5e7646d2SAndroid Build Coastguard Worker
852*5e7646d2SAndroid Build Coastguard Worker for (device = cupsArrayFind(devices, &key);
853*5e7646d2SAndroid Build Coastguard Worker device;
854*5e7646d2SAndroid Build Coastguard Worker device = cupsArrayNext(devices))
855*5e7646d2SAndroid Build Coastguard Worker if (_cups_strcasecmp(device->name, key.name))
856*5e7646d2SAndroid Build Coastguard Worker break;
857*5e7646d2SAndroid Build Coastguard Worker else if (device->type == key.type)
858*5e7646d2SAndroid Build Coastguard Worker {
859*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(device->domain, "local.") &&
860*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(device->domain, replyDomain))
861*5e7646d2SAndroid Build Coastguard Worker {
862*5e7646d2SAndroid Build Coastguard Worker /*
863*5e7646d2SAndroid Build Coastguard Worker * Update the .local listing to use the "global" domain name instead.
864*5e7646d2SAndroid Build Coastguard Worker * The backend will try local lookups first, then the global domain name.
865*5e7646d2SAndroid Build Coastguard Worker */
866*5e7646d2SAndroid Build Coastguard Worker
867*5e7646d2SAndroid Build Coastguard Worker free(device->domain);
868*5e7646d2SAndroid Build Coastguard Worker device->domain = strdup(replyDomain);
869*5e7646d2SAndroid Build Coastguard Worker
870*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
871*5e7646d2SAndroid Build Coastguard Worker DNSServiceConstructFullName(fullName, device->name, regtype,
872*5e7646d2SAndroid Build Coastguard Worker replyDomain);
873*5e7646d2SAndroid Build Coastguard Worker #else /* HAVE_AVAHI */
874*5e7646d2SAndroid Build Coastguard Worker avahi_service_name_join(fullName, kDNSServiceMaxDomainName,
875*5e7646d2SAndroid Build Coastguard Worker serviceName, regtype, replyDomain);
876*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
877*5e7646d2SAndroid Build Coastguard Worker
878*5e7646d2SAndroid Build Coastguard Worker free(device->fullName);
879*5e7646d2SAndroid Build Coastguard Worker device->fullName = strdup(fullName);
880*5e7646d2SAndroid Build Coastguard Worker }
881*5e7646d2SAndroid Build Coastguard Worker
882*5e7646d2SAndroid Build Coastguard Worker return (device);
883*5e7646d2SAndroid Build Coastguard Worker }
884*5e7646d2SAndroid Build Coastguard Worker
885*5e7646d2SAndroid Build Coastguard Worker /*
886*5e7646d2SAndroid Build Coastguard Worker * Yes, add the device...
887*5e7646d2SAndroid Build Coastguard Worker */
888*5e7646d2SAndroid Build Coastguard Worker
889*5e7646d2SAndroid Build Coastguard Worker device = calloc(sizeof(cups_device_t), 1);
890*5e7646d2SAndroid Build Coastguard Worker device->name = strdup(serviceName);
891*5e7646d2SAndroid Build Coastguard Worker device->domain = strdup(replyDomain);
892*5e7646d2SAndroid Build Coastguard Worker device->type = key.type;
893*5e7646d2SAndroid Build Coastguard Worker device->priority = 50;
894*5e7646d2SAndroid Build Coastguard Worker
895*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(devices, device);
896*5e7646d2SAndroid Build Coastguard Worker
897*5e7646d2SAndroid Build Coastguard Worker /*
898*5e7646d2SAndroid Build Coastguard Worker * Set the "full name" of this service, which is used for queries...
899*5e7646d2SAndroid Build Coastguard Worker */
900*5e7646d2SAndroid Build Coastguard Worker
901*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
902*5e7646d2SAndroid Build Coastguard Worker DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
903*5e7646d2SAndroid Build Coastguard Worker #else /* HAVE_AVAHI */
904*5e7646d2SAndroid Build Coastguard Worker avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName, regtype, replyDomain);
905*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
906*5e7646d2SAndroid Build Coastguard Worker
907*5e7646d2SAndroid Build Coastguard Worker device->fullName = strdup(fullName);
908*5e7646d2SAndroid Build Coastguard Worker
909*5e7646d2SAndroid Build Coastguard Worker return (device);
910*5e7646d2SAndroid Build Coastguard Worker }
911*5e7646d2SAndroid Build Coastguard Worker
912*5e7646d2SAndroid Build Coastguard Worker
913*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
914*5e7646d2SAndroid Build Coastguard Worker /*
915*5e7646d2SAndroid Build Coastguard Worker * 'poll_callback()' - Wait for input on the specified file descriptors.
916*5e7646d2SAndroid Build Coastguard Worker *
917*5e7646d2SAndroid Build Coastguard Worker * Note: This function is needed because avahi_simple_poll_iterate is broken
918*5e7646d2SAndroid Build Coastguard Worker * and always uses a timeout of 0 (!) milliseconds.
919*5e7646d2SAndroid Build Coastguard Worker * (https://github.com/lathiat/avahi/issues/127)
920*5e7646d2SAndroid Build Coastguard Worker */
921*5e7646d2SAndroid Build Coastguard Worker
922*5e7646d2SAndroid Build Coastguard Worker static int /* O - Number of file descriptors matching */
poll_callback(struct pollfd * pollfds,unsigned int num_pollfds,int timeout,void * context)923*5e7646d2SAndroid Build Coastguard Worker poll_callback(
924*5e7646d2SAndroid Build Coastguard Worker struct pollfd *pollfds, /* I - File descriptors */
925*5e7646d2SAndroid Build Coastguard Worker unsigned int num_pollfds, /* I - Number of file descriptors */
926*5e7646d2SAndroid Build Coastguard Worker int timeout, /* I - Timeout in milliseconds (unused) */
927*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - User data (unused) */
928*5e7646d2SAndroid Build Coastguard Worker {
929*5e7646d2SAndroid Build Coastguard Worker int val; /* Return value */
930*5e7646d2SAndroid Build Coastguard Worker
931*5e7646d2SAndroid Build Coastguard Worker
932*5e7646d2SAndroid Build Coastguard Worker (void)timeout;
933*5e7646d2SAndroid Build Coastguard Worker (void)context;
934*5e7646d2SAndroid Build Coastguard Worker
935*5e7646d2SAndroid Build Coastguard Worker val = poll(pollfds, num_pollfds, 500);
936*5e7646d2SAndroid Build Coastguard Worker
937*5e7646d2SAndroid Build Coastguard Worker if (val < 0)
938*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: poll_callback: %s\n", strerror(errno));
939*5e7646d2SAndroid Build Coastguard Worker else if (val > 0)
940*5e7646d2SAndroid Build Coastguard Worker got_data = 1;
941*5e7646d2SAndroid Build Coastguard Worker
942*5e7646d2SAndroid Build Coastguard Worker return (val);
943*5e7646d2SAndroid Build Coastguard Worker }
944*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
945*5e7646d2SAndroid Build Coastguard Worker
946*5e7646d2SAndroid Build Coastguard Worker
947*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
948*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_DNSSD
949*5e7646d2SAndroid Build Coastguard Worker /*
950*5e7646d2SAndroid Build Coastguard Worker * 'query_callback()' - Process query data.
951*5e7646d2SAndroid Build Coastguard Worker */
952*5e7646d2SAndroid Build Coastguard Worker
953*5e7646d2SAndroid Build Coastguard Worker static void
query_callback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * fullName,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)954*5e7646d2SAndroid Build Coastguard Worker query_callback(
955*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef sdRef, /* I - Service reference */
956*5e7646d2SAndroid Build Coastguard Worker DNSServiceFlags flags, /* I - Data flags */
957*5e7646d2SAndroid Build Coastguard Worker uint32_t interfaceIndex, /* I - Interface */
958*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType errorCode, /* I - Error, if any */
959*5e7646d2SAndroid Build Coastguard Worker const char *fullName, /* I - Full service name */
960*5e7646d2SAndroid Build Coastguard Worker uint16_t rrtype, /* I - Record type */
961*5e7646d2SAndroid Build Coastguard Worker uint16_t rrclass, /* I - Record class */
962*5e7646d2SAndroid Build Coastguard Worker uint16_t rdlen, /* I - Length of record data */
963*5e7646d2SAndroid Build Coastguard Worker const void *rdata, /* I - Record data */
964*5e7646d2SAndroid Build Coastguard Worker uint32_t ttl, /* I - Time-to-live */
965*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Device */
966*5e7646d2SAndroid Build Coastguard Worker {
967*5e7646d2SAndroid Build Coastguard Worker # else
968*5e7646d2SAndroid Build Coastguard Worker /*
969*5e7646d2SAndroid Build Coastguard Worker * 'query_callback()' - Process query data.
970*5e7646d2SAndroid Build Coastguard Worker */
971*5e7646d2SAndroid Build Coastguard Worker
972*5e7646d2SAndroid Build Coastguard Worker static void
973*5e7646d2SAndroid Build Coastguard Worker query_callback(
974*5e7646d2SAndroid Build Coastguard Worker AvahiRecordBrowser *browser, /* I - Record browser */
975*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interfaceIndex,
976*5e7646d2SAndroid Build Coastguard Worker /* I - Interface index (unused) */
977*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol, /* I - Network protocol (unused) */
978*5e7646d2SAndroid Build Coastguard Worker AvahiBrowserEvent event, /* I - What happened? */
979*5e7646d2SAndroid Build Coastguard Worker const char *fullName, /* I - Service name */
980*5e7646d2SAndroid Build Coastguard Worker uint16_t rrclass, /* I - Record class */
981*5e7646d2SAndroid Build Coastguard Worker uint16_t rrtype, /* I - Record type */
982*5e7646d2SAndroid Build Coastguard Worker const void *rdata, /* I - TXT record */
983*5e7646d2SAndroid Build Coastguard Worker size_t rdlen, /* I - Length of TXT record */
984*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags, /* I - Flags */
985*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Device */
986*5e7646d2SAndroid Build Coastguard Worker {
987*5e7646d2SAndroid Build Coastguard Worker AvahiClient *client = avahi_record_browser_get_client(browser);
988*5e7646d2SAndroid Build Coastguard Worker /* Client information */
989*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_DNSSD */
990*5e7646d2SAndroid Build Coastguard Worker char *ptr; /* Pointer into string */
991*5e7646d2SAndroid Build Coastguard Worker cups_device_t *device = (cups_device_t *)context;
992*5e7646d2SAndroid Build Coastguard Worker /* Device */
993*5e7646d2SAndroid Build Coastguard Worker const uint8_t *data, /* Pointer into data */
994*5e7646d2SAndroid Build Coastguard Worker *datanext, /* Next key/value pair */
995*5e7646d2SAndroid Build Coastguard Worker *dataend; /* End of entire TXT record */
996*5e7646d2SAndroid Build Coastguard Worker uint8_t datalen; /* Length of current key/value pair */
997*5e7646d2SAndroid Build Coastguard Worker char key[256], /* Key string */
998*5e7646d2SAndroid Build Coastguard Worker value[256], /* Value string */
999*5e7646d2SAndroid Build Coastguard Worker make_and_model[512], /* Manufacturer and model */
1000*5e7646d2SAndroid Build Coastguard Worker model[256], /* Model */
1001*5e7646d2SAndroid Build Coastguard Worker pdl[256], /* PDL */
1002*5e7646d2SAndroid Build Coastguard Worker device_id[2048]; /* 1284 device ID */
1003*5e7646d2SAndroid Build Coastguard Worker
1004*5e7646d2SAndroid Build Coastguard Worker
1005*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_DNSSD
1006*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
1007*5e7646d2SAndroid Build Coastguard Worker "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
1008*5e7646d2SAndroid Build Coastguard Worker "rrtype=%u, rrclass=%u, rdlen=%u, rdata=%p, ttl=%u, "
1009*5e7646d2SAndroid Build Coastguard Worker "context=%p)\n",
1010*5e7646d2SAndroid Build Coastguard Worker sdRef, flags, interfaceIndex, errorCode, fullName, rrtype, rrclass, rdlen, rdata, ttl, context);
1011*5e7646d2SAndroid Build Coastguard Worker
1012*5e7646d2SAndroid Build Coastguard Worker /*
1013*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
1014*5e7646d2SAndroid Build Coastguard Worker */
1015*5e7646d2SAndroid Build Coastguard Worker
1016*5e7646d2SAndroid Build Coastguard Worker if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
1017*5e7646d2SAndroid Build Coastguard Worker return;
1018*5e7646d2SAndroid Build Coastguard Worker
1019*5e7646d2SAndroid Build Coastguard Worker # else
1020*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: query_callback(browser=%p, interfaceIndex=%d, "
1021*5e7646d2SAndroid Build Coastguard Worker "protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, "
1022*5e7646d2SAndroid Build Coastguard Worker "rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)\n",
1023*5e7646d2SAndroid Build Coastguard Worker browser, interfaceIndex, protocol, event, fullName, rrclass, rrtype, rdata, (unsigned)rdlen, flags, context);
1024*5e7646d2SAndroid Build Coastguard Worker
1025*5e7646d2SAndroid Build Coastguard Worker /*
1026*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
1027*5e7646d2SAndroid Build Coastguard Worker */
1028*5e7646d2SAndroid Build Coastguard Worker
1029*5e7646d2SAndroid Build Coastguard Worker if (event != AVAHI_BROWSER_NEW)
1030*5e7646d2SAndroid Build Coastguard Worker {
1031*5e7646d2SAndroid Build Coastguard Worker if (event == AVAHI_BROWSER_FAILURE)
1032*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: %s\n",
1033*5e7646d2SAndroid Build Coastguard Worker avahi_strerror(avahi_client_errno(client)));
1034*5e7646d2SAndroid Build Coastguard Worker
1035*5e7646d2SAndroid Build Coastguard Worker return;
1036*5e7646d2SAndroid Build Coastguard Worker }
1037*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_DNSSD */
1038*5e7646d2SAndroid Build Coastguard Worker
1039*5e7646d2SAndroid Build Coastguard Worker /*
1040*5e7646d2SAndroid Build Coastguard Worker * Pull out the priority and make and model from the TXT
1041*5e7646d2SAndroid Build Coastguard Worker * record and save it...
1042*5e7646d2SAndroid Build Coastguard Worker */
1043*5e7646d2SAndroid Build Coastguard Worker
1044*5e7646d2SAndroid Build Coastguard Worker device_id[0] = '\0';
1045*5e7646d2SAndroid Build Coastguard Worker make_and_model[0] = '\0';
1046*5e7646d2SAndroid Build Coastguard Worker pdl[0] = '\0';
1047*5e7646d2SAndroid Build Coastguard Worker
1048*5e7646d2SAndroid Build Coastguard Worker strlcpy(model, "Unknown", sizeof(model));
1049*5e7646d2SAndroid Build Coastguard Worker
1050*5e7646d2SAndroid Build Coastguard Worker for (data = rdata, dataend = data + rdlen;
1051*5e7646d2SAndroid Build Coastguard Worker data < dataend;
1052*5e7646d2SAndroid Build Coastguard Worker data = datanext)
1053*5e7646d2SAndroid Build Coastguard Worker {
1054*5e7646d2SAndroid Build Coastguard Worker /*
1055*5e7646d2SAndroid Build Coastguard Worker * Read a key/value pair starting with an 8-bit length. Since the
1056*5e7646d2SAndroid Build Coastguard Worker * length is 8 bits and the size of the key/value buffers is 256, we
1057*5e7646d2SAndroid Build Coastguard Worker * don't need to check for overflow...
1058*5e7646d2SAndroid Build Coastguard Worker */
1059*5e7646d2SAndroid Build Coastguard Worker
1060*5e7646d2SAndroid Build Coastguard Worker datalen = *data++;
1061*5e7646d2SAndroid Build Coastguard Worker
1062*5e7646d2SAndroid Build Coastguard Worker if (!datalen || (data + datalen) > dataend)
1063*5e7646d2SAndroid Build Coastguard Worker break;
1064*5e7646d2SAndroid Build Coastguard Worker
1065*5e7646d2SAndroid Build Coastguard Worker datanext = data + datalen;
1066*5e7646d2SAndroid Build Coastguard Worker
1067*5e7646d2SAndroid Build Coastguard Worker for (ptr = key; data < datanext && *data != '='; data ++)
1068*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)*data;
1069*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
1070*5e7646d2SAndroid Build Coastguard Worker
1071*5e7646d2SAndroid Build Coastguard Worker if (data < datanext && *data == '=')
1072*5e7646d2SAndroid Build Coastguard Worker {
1073*5e7646d2SAndroid Build Coastguard Worker data ++;
1074*5e7646d2SAndroid Build Coastguard Worker
1075*5e7646d2SAndroid Build Coastguard Worker if (data < datanext)
1076*5e7646d2SAndroid Build Coastguard Worker memcpy(value, data, (size_t)(datanext - data));
1077*5e7646d2SAndroid Build Coastguard Worker value[datanext - data] = '\0';
1078*5e7646d2SAndroid Build Coastguard Worker
1079*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
1080*5e7646d2SAndroid Build Coastguard Worker key, value);
1081*5e7646d2SAndroid Build Coastguard Worker }
1082*5e7646d2SAndroid Build Coastguard Worker else
1083*5e7646d2SAndroid Build Coastguard Worker {
1084*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
1085*5e7646d2SAndroid Build Coastguard Worker key);
1086*5e7646d2SAndroid Build Coastguard Worker continue;
1087*5e7646d2SAndroid Build Coastguard Worker }
1088*5e7646d2SAndroid Build Coastguard Worker
1089*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(key, "usb_", 4))
1090*5e7646d2SAndroid Build Coastguard Worker {
1091*5e7646d2SAndroid Build Coastguard Worker /*
1092*5e7646d2SAndroid Build Coastguard Worker * Add USB device ID information...
1093*5e7646d2SAndroid Build Coastguard Worker */
1094*5e7646d2SAndroid Build Coastguard Worker
1095*5e7646d2SAndroid Build Coastguard Worker ptr = device_id + strlen(device_id);
1096*5e7646d2SAndroid Build Coastguard Worker snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "%s:%s;", key + 4, value);
1097*5e7646d2SAndroid Build Coastguard Worker }
1098*5e7646d2SAndroid Build Coastguard Worker
1099*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") ||
1100*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(key, "usb_MANUFACTURER"))
1101*5e7646d2SAndroid Build Coastguard Worker strlcpy(make_and_model, value, sizeof(make_and_model));
1102*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL"))
1103*5e7646d2SAndroid Build Coastguard Worker strlcpy(model, value, sizeof(model));
1104*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript"))
1105*5e7646d2SAndroid Build Coastguard Worker {
1106*5e7646d2SAndroid Build Coastguard Worker if (value[0] == '(')
1107*5e7646d2SAndroid Build Coastguard Worker {
1108*5e7646d2SAndroid Build Coastguard Worker /*
1109*5e7646d2SAndroid Build Coastguard Worker * Strip parenthesis...
1110*5e7646d2SAndroid Build Coastguard Worker */
1111*5e7646d2SAndroid Build Coastguard Worker
1112*5e7646d2SAndroid Build Coastguard Worker if ((ptr = value + strlen(value) - 1) > value && *ptr == ')')
1113*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
1114*5e7646d2SAndroid Build Coastguard Worker
1115*5e7646d2SAndroid Build Coastguard Worker strlcpy(model, value + 1, sizeof(model));
1116*5e7646d2SAndroid Build Coastguard Worker }
1117*5e7646d2SAndroid Build Coastguard Worker else
1118*5e7646d2SAndroid Build Coastguard Worker strlcpy(model, value, sizeof(model));
1119*5e7646d2SAndroid Build Coastguard Worker }
1120*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(key, "ty"))
1121*5e7646d2SAndroid Build Coastguard Worker {
1122*5e7646d2SAndroid Build Coastguard Worker strlcpy(model, value, sizeof(model));
1123*5e7646d2SAndroid Build Coastguard Worker
1124*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strchr(model, ',')) != NULL)
1125*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
1126*5e7646d2SAndroid Build Coastguard Worker }
1127*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(key, "pdl"))
1128*5e7646d2SAndroid Build Coastguard Worker strlcpy(pdl, value, sizeof(pdl));
1129*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(key, "priority"))
1130*5e7646d2SAndroid Build Coastguard Worker device->priority = atoi(value);
1131*5e7646d2SAndroid Build Coastguard Worker else if ((device->type == CUPS_DEVICE_IPP ||
1132*5e7646d2SAndroid Build Coastguard Worker device->type == CUPS_DEVICE_IPPS ||
1133*5e7646d2SAndroid Build Coastguard Worker device->type == CUPS_DEVICE_PRINTER) &&
1134*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(key, "printer-type"))
1135*5e7646d2SAndroid Build Coastguard Worker {
1136*5e7646d2SAndroid Build Coastguard Worker /*
1137*5e7646d2SAndroid Build Coastguard Worker * This is a CUPS printer!
1138*5e7646d2SAndroid Build Coastguard Worker */
1139*5e7646d2SAndroid Build Coastguard Worker
1140*5e7646d2SAndroid Build Coastguard Worker device->cups_shared = 1;
1141*5e7646d2SAndroid Build Coastguard Worker
1142*5e7646d2SAndroid Build Coastguard Worker if (device->type == CUPS_DEVICE_PRINTER)
1143*5e7646d2SAndroid Build Coastguard Worker device->sent = 1;
1144*5e7646d2SAndroid Build Coastguard Worker }
1145*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(key, "UUID"))
1146*5e7646d2SAndroid Build Coastguard Worker device->uuid = strdup(value);
1147*5e7646d2SAndroid Build Coastguard Worker }
1148*5e7646d2SAndroid Build Coastguard Worker
1149*5e7646d2SAndroid Build Coastguard Worker if (device->device_id)
1150*5e7646d2SAndroid Build Coastguard Worker free(device->device_id);
1151*5e7646d2SAndroid Build Coastguard Worker
1152*5e7646d2SAndroid Build Coastguard Worker if (!device_id[0] && strcmp(model, "Unknown"))
1153*5e7646d2SAndroid Build Coastguard Worker {
1154*5e7646d2SAndroid Build Coastguard Worker if (make_and_model[0])
1155*5e7646d2SAndroid Build Coastguard Worker snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;",
1156*5e7646d2SAndroid Build Coastguard Worker make_and_model, model);
1157*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strncasecmp(model, "designjet ", 10))
1158*5e7646d2SAndroid Build Coastguard Worker snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;", model + 10);
1159*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strncasecmp(model, "stylus ", 7))
1160*5e7646d2SAndroid Build Coastguard Worker snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;", model + 7);
1161*5e7646d2SAndroid Build Coastguard Worker else if ((ptr = strchr(model, ' ')) != NULL)
1162*5e7646d2SAndroid Build Coastguard Worker {
1163*5e7646d2SAndroid Build Coastguard Worker /*
1164*5e7646d2SAndroid Build Coastguard Worker * Assume the first word is the make...
1165*5e7646d2SAndroid Build Coastguard Worker */
1166*5e7646d2SAndroid Build Coastguard Worker
1167*5e7646d2SAndroid Build Coastguard Worker memcpy(make_and_model, model, (size_t)(ptr - model));
1168*5e7646d2SAndroid Build Coastguard Worker make_and_model[ptr - model] = '\0';
1169*5e7646d2SAndroid Build Coastguard Worker
1170*5e7646d2SAndroid Build Coastguard Worker snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;",
1171*5e7646d2SAndroid Build Coastguard Worker make_and_model, ptr + 1);
1172*5e7646d2SAndroid Build Coastguard Worker }
1173*5e7646d2SAndroid Build Coastguard Worker }
1174*5e7646d2SAndroid Build Coastguard Worker
1175*5e7646d2SAndroid Build Coastguard Worker if (device_id[0] &&
1176*5e7646d2SAndroid Build Coastguard Worker !strstr(device_id, "CMD:") &&
1177*5e7646d2SAndroid Build Coastguard Worker !strstr(device_id, "COMMAND SET:") &&
1178*5e7646d2SAndroid Build Coastguard Worker (strstr(pdl, "application/pdf") ||
1179*5e7646d2SAndroid Build Coastguard Worker strstr(pdl, "application/postscript") ||
1180*5e7646d2SAndroid Build Coastguard Worker strstr(pdl, "application/vnd.hp-PCL") ||
1181*5e7646d2SAndroid Build Coastguard Worker strstr(pdl, "image/")))
1182*5e7646d2SAndroid Build Coastguard Worker {
1183*5e7646d2SAndroid Build Coastguard Worker value[0] = '\0';
1184*5e7646d2SAndroid Build Coastguard Worker if (strstr(pdl, "application/pdf"))
1185*5e7646d2SAndroid Build Coastguard Worker strlcat(value, ",PDF", sizeof(value));
1186*5e7646d2SAndroid Build Coastguard Worker if (strstr(pdl, "application/postscript"))
1187*5e7646d2SAndroid Build Coastguard Worker strlcat(value, ",PS", sizeof(value));
1188*5e7646d2SAndroid Build Coastguard Worker if (strstr(pdl, "application/vnd.hp-PCL"))
1189*5e7646d2SAndroid Build Coastguard Worker strlcat(value, ",PCL", sizeof(value));
1190*5e7646d2SAndroid Build Coastguard Worker for (ptr = strstr(pdl, "image/"); ptr; ptr = strstr(ptr, "image/"))
1191*5e7646d2SAndroid Build Coastguard Worker {
1192*5e7646d2SAndroid Build Coastguard Worker char *valptr = value + strlen(value);
1193*5e7646d2SAndroid Build Coastguard Worker /* Pointer into value */
1194*5e7646d2SAndroid Build Coastguard Worker
1195*5e7646d2SAndroid Build Coastguard Worker if (valptr < (value + sizeof(value) - 1))
1196*5e7646d2SAndroid Build Coastguard Worker *valptr++ = ',';
1197*5e7646d2SAndroid Build Coastguard Worker
1198*5e7646d2SAndroid Build Coastguard Worker ptr += 6;
1199*5e7646d2SAndroid Build Coastguard Worker while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.')
1200*5e7646d2SAndroid Build Coastguard Worker {
1201*5e7646d2SAndroid Build Coastguard Worker if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1))
1202*5e7646d2SAndroid Build Coastguard Worker *valptr++ = (char)toupper(*ptr++ & 255);
1203*5e7646d2SAndroid Build Coastguard Worker else
1204*5e7646d2SAndroid Build Coastguard Worker break;
1205*5e7646d2SAndroid Build Coastguard Worker }
1206*5e7646d2SAndroid Build Coastguard Worker
1207*5e7646d2SAndroid Build Coastguard Worker *valptr = '\0';
1208*5e7646d2SAndroid Build Coastguard Worker }
1209*5e7646d2SAndroid Build Coastguard Worker
1210*5e7646d2SAndroid Build Coastguard Worker ptr = device_id + strlen(device_id);
1211*5e7646d2SAndroid Build Coastguard Worker snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "CMD:%s;", value + 1);
1212*5e7646d2SAndroid Build Coastguard Worker }
1213*5e7646d2SAndroid Build Coastguard Worker
1214*5e7646d2SAndroid Build Coastguard Worker if (device_id[0])
1215*5e7646d2SAndroid Build Coastguard Worker device->device_id = strdup(device_id);
1216*5e7646d2SAndroid Build Coastguard Worker else
1217*5e7646d2SAndroid Build Coastguard Worker device->device_id = NULL;
1218*5e7646d2SAndroid Build Coastguard Worker
1219*5e7646d2SAndroid Build Coastguard Worker if (device->make_and_model)
1220*5e7646d2SAndroid Build Coastguard Worker free(device->make_and_model);
1221*5e7646d2SAndroid Build Coastguard Worker
1222*5e7646d2SAndroid Build Coastguard Worker if (make_and_model[0])
1223*5e7646d2SAndroid Build Coastguard Worker {
1224*5e7646d2SAndroid Build Coastguard Worker strlcat(make_and_model, " ", sizeof(make_and_model));
1225*5e7646d2SAndroid Build Coastguard Worker strlcat(make_and_model, model, sizeof(make_and_model));
1226*5e7646d2SAndroid Build Coastguard Worker
1227*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(make_and_model, "EPSON EPSON ", 12))
1228*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(make_and_model, make_and_model + 6);
1229*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strncasecmp(make_and_model, "HP HP ", 6))
1230*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(make_and_model, make_and_model + 3);
1231*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strncasecmp(make_and_model, "Lexmark International Lexmark ", 30))
1232*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(make_and_model, make_and_model + 22);
1233*5e7646d2SAndroid Build Coastguard Worker
1234*5e7646d2SAndroid Build Coastguard Worker device->make_and_model = strdup(make_and_model);
1235*5e7646d2SAndroid Build Coastguard Worker }
1236*5e7646d2SAndroid Build Coastguard Worker else
1237*5e7646d2SAndroid Build Coastguard Worker device->make_and_model = strdup(model);
1238*5e7646d2SAndroid Build Coastguard Worker }
1239*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD || HAVE_AVAHI */
1240*5e7646d2SAndroid Build Coastguard Worker
1241*5e7646d2SAndroid Build Coastguard Worker
1242*5e7646d2SAndroid Build Coastguard Worker /*
1243*5e7646d2SAndroid Build Coastguard Worker * 'sigterm_handler()' - Handle termination signals.
1244*5e7646d2SAndroid Build Coastguard Worker */
1245*5e7646d2SAndroid Build Coastguard Worker
1246*5e7646d2SAndroid Build Coastguard Worker static void
1247*5e7646d2SAndroid Build Coastguard Worker sigterm_handler(int sig) /* I - Signal number (unused) */
1248*5e7646d2SAndroid Build Coastguard Worker {
1249*5e7646d2SAndroid Build Coastguard Worker (void)sig;
1250*5e7646d2SAndroid Build Coastguard Worker
1251*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1252*5e7646d2SAndroid Build Coastguard Worker _exit(CUPS_BACKEND_OK);
1253*5e7646d2SAndroid Build Coastguard Worker else
1254*5e7646d2SAndroid Build Coastguard Worker job_canceled = 1;
1255*5e7646d2SAndroid Build Coastguard Worker }
1256*5e7646d2SAndroid Build Coastguard Worker
1257*5e7646d2SAndroid Build Coastguard Worker
1258*5e7646d2SAndroid Build Coastguard Worker /*
1259*5e7646d2SAndroid Build Coastguard Worker * 'unquote()' - Unquote a name string.
1260*5e7646d2SAndroid Build Coastguard Worker */
1261*5e7646d2SAndroid Build Coastguard Worker
1262*5e7646d2SAndroid Build Coastguard Worker static void
1263*5e7646d2SAndroid Build Coastguard Worker unquote(char *dst, /* I - Destination buffer */
1264*5e7646d2SAndroid Build Coastguard Worker const char *src, /* I - Source string */
1265*5e7646d2SAndroid Build Coastguard Worker size_t dstsize) /* I - Size of destination buffer */
1266*5e7646d2SAndroid Build Coastguard Worker {
1267*5e7646d2SAndroid Build Coastguard Worker char *dstend = dst + dstsize - 1; /* End of destination buffer */
1268*5e7646d2SAndroid Build Coastguard Worker
1269*5e7646d2SAndroid Build Coastguard Worker
1270*5e7646d2SAndroid Build Coastguard Worker while (*src && dst < dstend)
1271*5e7646d2SAndroid Build Coastguard Worker {
1272*5e7646d2SAndroid Build Coastguard Worker if (*src == '\\')
1273*5e7646d2SAndroid Build Coastguard Worker {
1274*5e7646d2SAndroid Build Coastguard Worker src ++;
1275*5e7646d2SAndroid Build Coastguard Worker if (isdigit(src[0] & 255) && isdigit(src[1] & 255) &&
1276*5e7646d2SAndroid Build Coastguard Worker isdigit(src[2] & 255))
1277*5e7646d2SAndroid Build Coastguard Worker {
1278*5e7646d2SAndroid Build Coastguard Worker *dst++ = ((((src[0] - '0') * 10) + src[1] - '0') * 10) + src[2] - '0';
1279*5e7646d2SAndroid Build Coastguard Worker src += 3;
1280*5e7646d2SAndroid Build Coastguard Worker }
1281*5e7646d2SAndroid Build Coastguard Worker else
1282*5e7646d2SAndroid Build Coastguard Worker *dst++ = *src++;
1283*5e7646d2SAndroid Build Coastguard Worker }
1284*5e7646d2SAndroid Build Coastguard Worker else
1285*5e7646d2SAndroid Build Coastguard Worker *dst++ = *src ++;
1286*5e7646d2SAndroid Build Coastguard Worker }
1287*5e7646d2SAndroid Build Coastguard Worker
1288*5e7646d2SAndroid Build Coastguard Worker *dst = '\0';
1289*5e7646d2SAndroid Build Coastguard Worker }
1290