1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Utility to find IPP printers via Bonjour/DNS-SD and optionally run
3*5e7646d2SAndroid Build Coastguard Worker * commands such as IPP and Bonjour conformance tests. This tool is
4*5e7646d2SAndroid Build Coastguard Worker * inspired by the UNIX "find" command, thus its name.
5*5e7646d2SAndroid Build Coastguard Worker *
6*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2021 by OpenPrinting.
7*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2020 by the IEEE-ISTO Printer Working Group
8*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2008-2018 by Apple Inc.
9*5e7646d2SAndroid Build Coastguard Worker *
10*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
11*5e7646d2SAndroid Build Coastguard Worker * information.
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker /*
15*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
16*5e7646d2SAndroid Build Coastguard Worker */
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_NO_DEPRECATED
19*5e7646d2SAndroid Build Coastguard Worker #include <cups/cups-private.h>
20*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
21*5e7646d2SAndroid Build Coastguard Worker # include <process.h>
22*5e7646d2SAndroid Build Coastguard Worker # include <sys/timeb.h>
23*5e7646d2SAndroid Build Coastguard Worker #else
24*5e7646d2SAndroid Build Coastguard Worker # include <sys/wait.h>
25*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
26*5e7646d2SAndroid Build Coastguard Worker #include <regex.h>
27*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
28*5e7646d2SAndroid Build Coastguard Worker # include <dns_sd.h>
29*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
30*5e7646d2SAndroid Build Coastguard Worker # include <avahi-client/client.h>
31*5e7646d2SAndroid Build Coastguard Worker # include <avahi-client/lookup.h>
32*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/simple-watch.h>
33*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/domain.h>
34*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/error.h>
35*5e7646d2SAndroid Build Coastguard Worker # include <avahi-common/malloc.h>
36*5e7646d2SAndroid Build Coastguard Worker # define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
37*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
38*5e7646d2SAndroid Build Coastguard Worker
39*5e7646d2SAndroid Build Coastguard Worker #ifndef _WIN32
40*5e7646d2SAndroid Build Coastguard Worker extern char **environ; /* Process environment variables */
41*5e7646d2SAndroid Build Coastguard Worker #endif /* !_WIN32 */
42*5e7646d2SAndroid Build Coastguard Worker
43*5e7646d2SAndroid Build Coastguard Worker
44*5e7646d2SAndroid Build Coastguard Worker /*
45*5e7646d2SAndroid Build Coastguard Worker * Structures...
46*5e7646d2SAndroid Build Coastguard Worker */
47*5e7646d2SAndroid Build Coastguard Worker
48*5e7646d2SAndroid Build Coastguard Worker typedef enum ippfind_exit_e /* Exit codes */
49*5e7646d2SAndroid Build Coastguard Worker {
50*5e7646d2SAndroid Build Coastguard Worker IPPFIND_EXIT_TRUE = 0, /* OK and result is true */
51*5e7646d2SAndroid Build Coastguard Worker IPPFIND_EXIT_FALSE, /* OK but result is false*/
52*5e7646d2SAndroid Build Coastguard Worker IPPFIND_EXIT_BONJOUR, /* Browse/resolve failure */
53*5e7646d2SAndroid Build Coastguard Worker IPPFIND_EXIT_SYNTAX, /* Bad option or syntax error */
54*5e7646d2SAndroid Build Coastguard Worker IPPFIND_EXIT_MEMORY /* Out of memory */
55*5e7646d2SAndroid Build Coastguard Worker } ippfind_exit_t;
56*5e7646d2SAndroid Build Coastguard Worker
57*5e7646d2SAndroid Build Coastguard Worker typedef enum ippfind_op_e /* Operations for expressions */
58*5e7646d2SAndroid Build Coastguard Worker {
59*5e7646d2SAndroid Build Coastguard Worker /* "Evaluation" operations */
60*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_NONE, /* No operation */
61*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_AND, /* Logical AND of all children */
62*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_OR, /* Logical OR of all children */
63*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_TRUE, /* Always true */
64*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_FALSE, /* Always false */
65*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_IS_LOCAL, /* Is a local service */
66*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_IS_REMOTE, /* Is a remote service */
67*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_DOMAIN_REGEX, /* Domain matches regular expression */
68*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_NAME_REGEX, /* Name matches regular expression */
69*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_NAME_LITERAL, /* Name matches literal string */
70*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_HOST_REGEX, /* Hostname matches regular expression */
71*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_PORT_RANGE, /* Port matches range */
72*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_PATH_REGEX, /* Path matches regular expression */
73*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_TXT_EXISTS, /* TXT record key exists */
74*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_TXT_REGEX, /* TXT record key matches regular expression */
75*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_URI_REGEX, /* URI matches regular expression */
76*5e7646d2SAndroid Build Coastguard Worker
77*5e7646d2SAndroid Build Coastguard Worker /* "Output" operations */
78*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_EXEC, /* Execute when true */
79*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_LIST, /* List when true */
80*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_PRINT_NAME, /* Print URI when true */
81*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_PRINT_URI, /* Print name when true */
82*5e7646d2SAndroid Build Coastguard Worker IPPFIND_OP_QUIET /* No output when true */
83*5e7646d2SAndroid Build Coastguard Worker } ippfind_op_t;
84*5e7646d2SAndroid Build Coastguard Worker
85*5e7646d2SAndroid Build Coastguard Worker typedef struct ippfind_expr_s /* Expression */
86*5e7646d2SAndroid Build Coastguard Worker {
87*5e7646d2SAndroid Build Coastguard Worker struct ippfind_expr_s
88*5e7646d2SAndroid Build Coastguard Worker *prev, /* Previous expression */
89*5e7646d2SAndroid Build Coastguard Worker *next, /* Next expression */
90*5e7646d2SAndroid Build Coastguard Worker *parent, /* Parent expressions */
91*5e7646d2SAndroid Build Coastguard Worker *child; /* Child expressions */
92*5e7646d2SAndroid Build Coastguard Worker ippfind_op_t op; /* Operation code (see above) */
93*5e7646d2SAndroid Build Coastguard Worker int invert; /* Invert the result */
94*5e7646d2SAndroid Build Coastguard Worker char *name; /* TXT record key or literal name */
95*5e7646d2SAndroid Build Coastguard Worker regex_t re; /* Regular expression for matching */
96*5e7646d2SAndroid Build Coastguard Worker int range[2]; /* Port number range */
97*5e7646d2SAndroid Build Coastguard Worker int num_args; /* Number of arguments for exec */
98*5e7646d2SAndroid Build Coastguard Worker char **args; /* Arguments for exec */
99*5e7646d2SAndroid Build Coastguard Worker } ippfind_expr_t;
100*5e7646d2SAndroid Build Coastguard Worker
101*5e7646d2SAndroid Build Coastguard Worker typedef struct ippfind_srv_s /* Service information */
102*5e7646d2SAndroid Build Coastguard Worker {
103*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
104*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef ref; /* Service reference for query */
105*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
106*5e7646d2SAndroid Build Coastguard Worker AvahiServiceResolver *ref; /* Resolver */
107*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
108*5e7646d2SAndroid Build Coastguard Worker char *name, /* Service name */
109*5e7646d2SAndroid Build Coastguard Worker *domain, /* Domain name */
110*5e7646d2SAndroid Build Coastguard Worker *regtype, /* Registration type */
111*5e7646d2SAndroid Build Coastguard Worker *fullName, /* Full name */
112*5e7646d2SAndroid Build Coastguard Worker *host, /* Hostname */
113*5e7646d2SAndroid Build Coastguard Worker *resource, /* Resource path */
114*5e7646d2SAndroid Build Coastguard Worker *uri; /* URI */
115*5e7646d2SAndroid Build Coastguard Worker int num_txt; /* Number of TXT record keys */
116*5e7646d2SAndroid Build Coastguard Worker cups_option_t *txt; /* TXT record keys */
117*5e7646d2SAndroid Build Coastguard Worker int port, /* Port number */
118*5e7646d2SAndroid Build Coastguard Worker is_local, /* Is a local service? */
119*5e7646d2SAndroid Build Coastguard Worker is_processed, /* Did we process the service? */
120*5e7646d2SAndroid Build Coastguard Worker is_resolved; /* Got the resolve data? */
121*5e7646d2SAndroid Build Coastguard Worker } ippfind_srv_t;
122*5e7646d2SAndroid Build Coastguard Worker
123*5e7646d2SAndroid Build Coastguard Worker
124*5e7646d2SAndroid Build Coastguard Worker /*
125*5e7646d2SAndroid Build Coastguard Worker * Local globals...
126*5e7646d2SAndroid Build Coastguard Worker */
127*5e7646d2SAndroid Build Coastguard Worker
128*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
129*5e7646d2SAndroid Build Coastguard Worker static DNSServiceRef dnssd_ref; /* Master service reference */
130*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
131*5e7646d2SAndroid Build Coastguard Worker static AvahiClient *avahi_client = NULL;/* Client information */
132*5e7646d2SAndroid Build Coastguard Worker static int avahi_got_data = 0; /* Got data from poll? */
133*5e7646d2SAndroid Build Coastguard Worker static AvahiSimplePoll *avahi_poll = NULL;
134*5e7646d2SAndroid Build Coastguard Worker /* Poll information */
135*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
136*5e7646d2SAndroid Build Coastguard Worker
137*5e7646d2SAndroid Build Coastguard Worker static int address_family = AF_UNSPEC;
138*5e7646d2SAndroid Build Coastguard Worker /* Address family for LIST */
139*5e7646d2SAndroid Build Coastguard Worker static int bonjour_error = 0; /* Error browsing/resolving? */
140*5e7646d2SAndroid Build Coastguard Worker static double bonjour_timeout = 1.0; /* Timeout in seconds */
141*5e7646d2SAndroid Build Coastguard Worker static int ipp_version = 20; /* IPP version for LIST */
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker
144*5e7646d2SAndroid Build Coastguard Worker /*
145*5e7646d2SAndroid Build Coastguard Worker * Local functions...
146*5e7646d2SAndroid Build Coastguard Worker */
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
149*5e7646d2SAndroid Build Coastguard Worker static void DNSSD_API 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);
150*5e7646d2SAndroid Build Coastguard Worker static void DNSSD_API 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);
151*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
152*5e7646d2SAndroid Build Coastguard Worker static void browse_callback(AvahiServiceBrowser *browser,
153*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface,
154*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol,
155*5e7646d2SAndroid Build Coastguard Worker AvahiBrowserEvent event,
156*5e7646d2SAndroid Build Coastguard Worker const char *serviceName,
157*5e7646d2SAndroid Build Coastguard Worker const char *regtype,
158*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain,
159*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags,
160*5e7646d2SAndroid Build Coastguard Worker void *context);
161*5e7646d2SAndroid Build Coastguard Worker static void client_callback(AvahiClient *client,
162*5e7646d2SAndroid Build Coastguard Worker AvahiClientState state,
163*5e7646d2SAndroid Build Coastguard Worker void *context);
164*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker static int compare_services(ippfind_srv_t *a, ippfind_srv_t *b);
167*5e7646d2SAndroid Build Coastguard Worker static const char *dnssd_error_string(int error);
168*5e7646d2SAndroid Build Coastguard Worker static int eval_expr(ippfind_srv_t *service,
169*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *expressions);
170*5e7646d2SAndroid Build Coastguard Worker static int exec_program(ippfind_srv_t *service, int num_args,
171*5e7646d2SAndroid Build Coastguard Worker char **args);
172*5e7646d2SAndroid Build Coastguard Worker static ippfind_srv_t *get_service(cups_array_t *services, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4);
173*5e7646d2SAndroid Build Coastguard Worker static double get_time(void);
174*5e7646d2SAndroid Build Coastguard Worker static int list_service(ippfind_srv_t *service);
175*5e7646d2SAndroid Build Coastguard Worker static ippfind_expr_t *new_expr(ippfind_op_t op, int invert,
176*5e7646d2SAndroid Build Coastguard Worker const char *value, const char *regex,
177*5e7646d2SAndroid Build Coastguard Worker char **args);
178*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
179*5e7646d2SAndroid Build Coastguard Worker static void DNSSD_API resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullName, const char *hostTarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) _CUPS_NONNULL(1,5,6,9, 10);
180*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
181*5e7646d2SAndroid Build Coastguard Worker static int poll_callback(struct pollfd *pollfds,
182*5e7646d2SAndroid Build Coastguard Worker unsigned int num_pollfds, int timeout,
183*5e7646d2SAndroid Build Coastguard Worker void *context);
184*5e7646d2SAndroid Build Coastguard Worker static void resolve_callback(AvahiServiceResolver *res,
185*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface,
186*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol,
187*5e7646d2SAndroid Build Coastguard Worker AvahiResolverEvent event,
188*5e7646d2SAndroid Build Coastguard Worker const char *serviceName,
189*5e7646d2SAndroid Build Coastguard Worker const char *regtype,
190*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain,
191*5e7646d2SAndroid Build Coastguard Worker const char *host_name,
192*5e7646d2SAndroid Build Coastguard Worker const AvahiAddress *address,
193*5e7646d2SAndroid Build Coastguard Worker uint16_t port,
194*5e7646d2SAndroid Build Coastguard Worker AvahiStringList *txt,
195*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags,
196*5e7646d2SAndroid Build Coastguard Worker void *context);
197*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
198*5e7646d2SAndroid Build Coastguard Worker static void set_service_uri(ippfind_srv_t *service);
199*5e7646d2SAndroid Build Coastguard Worker static void show_usage(void) _CUPS_NORETURN;
200*5e7646d2SAndroid Build Coastguard Worker static void show_version(void) _CUPS_NORETURN;
201*5e7646d2SAndroid Build Coastguard Worker
202*5e7646d2SAndroid Build Coastguard Worker
203*5e7646d2SAndroid Build Coastguard Worker /*
204*5e7646d2SAndroid Build Coastguard Worker * 'main()' - Browse for printers.
205*5e7646d2SAndroid Build Coastguard Worker */
206*5e7646d2SAndroid Build Coastguard Worker
207*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit status */
main(int argc,char * argv[])208*5e7646d2SAndroid Build Coastguard Worker main(int argc, /* I - Number of command-line args */
209*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
210*5e7646d2SAndroid Build Coastguard Worker {
211*5e7646d2SAndroid Build Coastguard Worker int i, /* Looping var */
212*5e7646d2SAndroid Build Coastguard Worker have_output = 0,/* Have output expression */
213*5e7646d2SAndroid Build Coastguard Worker status = IPPFIND_EXIT_FALSE;
214*5e7646d2SAndroid Build Coastguard Worker /* Exit status */
215*5e7646d2SAndroid Build Coastguard Worker const char *opt, /* Option character */
216*5e7646d2SAndroid Build Coastguard Worker *search; /* Current browse/resolve string */
217*5e7646d2SAndroid Build Coastguard Worker cups_array_t *searches; /* Things to browse/resolve */
218*5e7646d2SAndroid Build Coastguard Worker cups_array_t *services; /* Service array */
219*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t *service; /* Current service */
220*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *expressions = NULL,
221*5e7646d2SAndroid Build Coastguard Worker /* Expression tree */
222*5e7646d2SAndroid Build Coastguard Worker *temp = NULL, /* New expression */
223*5e7646d2SAndroid Build Coastguard Worker *parent = NULL, /* Parent expression */
224*5e7646d2SAndroid Build Coastguard Worker *current = NULL,/* Current expression */
225*5e7646d2SAndroid Build Coastguard Worker *parens[100]; /* Markers for parenthesis */
226*5e7646d2SAndroid Build Coastguard Worker int num_parens = 0; /* Number of parenthesis */
227*5e7646d2SAndroid Build Coastguard Worker ippfind_op_t logic = IPPFIND_OP_AND;
228*5e7646d2SAndroid Build Coastguard Worker /* Logic for next expression */
229*5e7646d2SAndroid Build Coastguard Worker int invert = 0; /* Invert expression? */
230*5e7646d2SAndroid Build Coastguard Worker int err; /* DNS-SD error */
231*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
232*5e7646d2SAndroid Build Coastguard Worker fd_set sinput; /* Input set for select() */
233*5e7646d2SAndroid Build Coastguard Worker struct timeval stimeout; /* Timeout for select() */
234*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
235*5e7646d2SAndroid Build Coastguard Worker double endtime; /* End time */
236*5e7646d2SAndroid Build Coastguard Worker static const char * const ops[] = /* Node operation names */
237*5e7646d2SAndroid Build Coastguard Worker {
238*5e7646d2SAndroid Build Coastguard Worker "NONE",
239*5e7646d2SAndroid Build Coastguard Worker "AND",
240*5e7646d2SAndroid Build Coastguard Worker "OR",
241*5e7646d2SAndroid Build Coastguard Worker "TRUE",
242*5e7646d2SAndroid Build Coastguard Worker "FALSE",
243*5e7646d2SAndroid Build Coastguard Worker "IS_LOCAL",
244*5e7646d2SAndroid Build Coastguard Worker "IS_REMOTE",
245*5e7646d2SAndroid Build Coastguard Worker "DOMAIN_REGEX",
246*5e7646d2SAndroid Build Coastguard Worker "NAME_REGEX",
247*5e7646d2SAndroid Build Coastguard Worker "NAME_LITERAL",
248*5e7646d2SAndroid Build Coastguard Worker "HOST_REGEX",
249*5e7646d2SAndroid Build Coastguard Worker "PORT_RANGE",
250*5e7646d2SAndroid Build Coastguard Worker "PATH_REGEX",
251*5e7646d2SAndroid Build Coastguard Worker "TXT_EXISTS",
252*5e7646d2SAndroid Build Coastguard Worker "TXT_REGEX",
253*5e7646d2SAndroid Build Coastguard Worker "URI_REGEX",
254*5e7646d2SAndroid Build Coastguard Worker "EXEC",
255*5e7646d2SAndroid Build Coastguard Worker "LIST",
256*5e7646d2SAndroid Build Coastguard Worker "PRINT_NAME",
257*5e7646d2SAndroid Build Coastguard Worker "PRINT_URI",
258*5e7646d2SAndroid Build Coastguard Worker "QUIET"
259*5e7646d2SAndroid Build Coastguard Worker };
260*5e7646d2SAndroid Build Coastguard Worker
261*5e7646d2SAndroid Build Coastguard Worker
262*5e7646d2SAndroid Build Coastguard Worker /*
263*5e7646d2SAndroid Build Coastguard Worker * Initialize the locale...
264*5e7646d2SAndroid Build Coastguard Worker */
265*5e7646d2SAndroid Build Coastguard Worker
266*5e7646d2SAndroid Build Coastguard Worker _cupsSetLocale(argv);
267*5e7646d2SAndroid Build Coastguard Worker
268*5e7646d2SAndroid Build Coastguard Worker /*
269*5e7646d2SAndroid Build Coastguard Worker * Create arrays to track services and things we want to browse/resolve...
270*5e7646d2SAndroid Build Coastguard Worker */
271*5e7646d2SAndroid Build Coastguard Worker
272*5e7646d2SAndroid Build Coastguard Worker searches = cupsArrayNew(NULL, NULL);
273*5e7646d2SAndroid Build Coastguard Worker services = cupsArrayNew((cups_array_func_t)compare_services, NULL);
274*5e7646d2SAndroid Build Coastguard Worker
275*5e7646d2SAndroid Build Coastguard Worker /*
276*5e7646d2SAndroid Build Coastguard Worker * Parse command-line...
277*5e7646d2SAndroid Build Coastguard Worker */
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
280*5e7646d2SAndroid Build Coastguard Worker for (i = 1; i < argc; i ++)
281*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "argv[%d]=\"%s\"\n", i, argv[i]);
282*5e7646d2SAndroid Build Coastguard Worker
283*5e7646d2SAndroid Build Coastguard Worker for (i = 1; i < argc; i ++)
284*5e7646d2SAndroid Build Coastguard Worker {
285*5e7646d2SAndroid Build Coastguard Worker if (argv[i][0] == '-')
286*5e7646d2SAndroid Build Coastguard Worker {
287*5e7646d2SAndroid Build Coastguard Worker if (argv[i][1] == '-')
288*5e7646d2SAndroid Build Coastguard Worker {
289*5e7646d2SAndroid Build Coastguard Worker /*
290*5e7646d2SAndroid Build Coastguard Worker * Parse --option options...
291*5e7646d2SAndroid Build Coastguard Worker */
292*5e7646d2SAndroid Build Coastguard Worker
293*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(argv[i], "--and"))
294*5e7646d2SAndroid Build Coastguard Worker {
295*5e7646d2SAndroid Build Coastguard Worker if (logic == IPPFIND_OP_OR)
296*5e7646d2SAndroid Build Coastguard Worker {
297*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("ippfind: Cannot use --and after --or."));
298*5e7646d2SAndroid Build Coastguard Worker show_usage();
299*5e7646d2SAndroid Build Coastguard Worker }
300*5e7646d2SAndroid Build Coastguard Worker
301*5e7646d2SAndroid Build Coastguard Worker if (!current)
302*5e7646d2SAndroid Build Coastguard Worker {
303*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr,
304*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing expression before \"--and\"."));
305*5e7646d2SAndroid Build Coastguard Worker show_usage();
306*5e7646d2SAndroid Build Coastguard Worker }
307*5e7646d2SAndroid Build Coastguard Worker
308*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
309*5e7646d2SAndroid Build Coastguard Worker }
310*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--domain"))
311*5e7646d2SAndroid Build Coastguard Worker {
312*5e7646d2SAndroid Build Coastguard Worker i ++;
313*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
314*5e7646d2SAndroid Build Coastguard Worker {
315*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
316*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after %s."),
317*5e7646d2SAndroid Build Coastguard Worker "--domain");
318*5e7646d2SAndroid Build Coastguard Worker show_usage();
319*5e7646d2SAndroid Build Coastguard Worker }
320*5e7646d2SAndroid Build Coastguard Worker
321*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_DOMAIN_REGEX, invert, NULL, argv[i],
322*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
323*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
324*5e7646d2SAndroid Build Coastguard Worker }
325*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--exec"))
326*5e7646d2SAndroid Build Coastguard Worker {
327*5e7646d2SAndroid Build Coastguard Worker i ++;
328*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
329*5e7646d2SAndroid Build Coastguard Worker {
330*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Expected program after %s."),
331*5e7646d2SAndroid Build Coastguard Worker "--exec");
332*5e7646d2SAndroid Build Coastguard Worker show_usage();
333*5e7646d2SAndroid Build Coastguard Worker }
334*5e7646d2SAndroid Build Coastguard Worker
335*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_EXEC, invert, NULL, NULL,
336*5e7646d2SAndroid Build Coastguard Worker argv + i)) == NULL)
337*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
338*5e7646d2SAndroid Build Coastguard Worker
339*5e7646d2SAndroid Build Coastguard Worker while (i < argc)
340*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(argv[i], ";"))
341*5e7646d2SAndroid Build Coastguard Worker break;
342*5e7646d2SAndroid Build Coastguard Worker else
343*5e7646d2SAndroid Build Coastguard Worker i ++;
344*5e7646d2SAndroid Build Coastguard Worker
345*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
346*5e7646d2SAndroid Build Coastguard Worker {
347*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Expected semi-colon after %s."),
348*5e7646d2SAndroid Build Coastguard Worker "--exec");
349*5e7646d2SAndroid Build Coastguard Worker show_usage();
350*5e7646d2SAndroid Build Coastguard Worker }
351*5e7646d2SAndroid Build Coastguard Worker
352*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
353*5e7646d2SAndroid Build Coastguard Worker }
354*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--false"))
355*5e7646d2SAndroid Build Coastguard Worker {
356*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_FALSE, invert, NULL, NULL,
357*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
358*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
359*5e7646d2SAndroid Build Coastguard Worker }
360*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--help"))
361*5e7646d2SAndroid Build Coastguard Worker {
362*5e7646d2SAndroid Build Coastguard Worker show_usage();
363*5e7646d2SAndroid Build Coastguard Worker }
364*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--host"))
365*5e7646d2SAndroid Build Coastguard Worker {
366*5e7646d2SAndroid Build Coastguard Worker i ++;
367*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
368*5e7646d2SAndroid Build Coastguard Worker {
369*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
370*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after %s."),
371*5e7646d2SAndroid Build Coastguard Worker "--host");
372*5e7646d2SAndroid Build Coastguard Worker show_usage();
373*5e7646d2SAndroid Build Coastguard Worker }
374*5e7646d2SAndroid Build Coastguard Worker
375*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_HOST_REGEX, invert, NULL, argv[i],
376*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
377*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
378*5e7646d2SAndroid Build Coastguard Worker }
379*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--ls"))
380*5e7646d2SAndroid Build Coastguard Worker {
381*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_LIST, invert, NULL, NULL,
382*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
383*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
384*5e7646d2SAndroid Build Coastguard Worker
385*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
386*5e7646d2SAndroid Build Coastguard Worker }
387*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--local"))
388*5e7646d2SAndroid Build Coastguard Worker {
389*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_IS_LOCAL, invert, NULL, NULL,
390*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
391*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
392*5e7646d2SAndroid Build Coastguard Worker }
393*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--literal-name"))
394*5e7646d2SAndroid Build Coastguard Worker {
395*5e7646d2SAndroid Build Coastguard Worker i ++;
396*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
397*5e7646d2SAndroid Build Coastguard Worker {
398*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Missing name after %s."), "--literal-name");
399*5e7646d2SAndroid Build Coastguard Worker show_usage();
400*5e7646d2SAndroid Build Coastguard Worker }
401*5e7646d2SAndroid Build Coastguard Worker
402*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_NAME_LITERAL, invert, argv[i], NULL, NULL)) == NULL)
403*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
404*5e7646d2SAndroid Build Coastguard Worker }
405*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--name"))
406*5e7646d2SAndroid Build Coastguard Worker {
407*5e7646d2SAndroid Build Coastguard Worker i ++;
408*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
409*5e7646d2SAndroid Build Coastguard Worker {
410*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
411*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after %s."),
412*5e7646d2SAndroid Build Coastguard Worker "--name");
413*5e7646d2SAndroid Build Coastguard Worker show_usage();
414*5e7646d2SAndroid Build Coastguard Worker }
415*5e7646d2SAndroid Build Coastguard Worker
416*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_NAME_REGEX, invert, NULL, argv[i],
417*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
418*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
419*5e7646d2SAndroid Build Coastguard Worker }
420*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--not"))
421*5e7646d2SAndroid Build Coastguard Worker {
422*5e7646d2SAndroid Build Coastguard Worker invert = 1;
423*5e7646d2SAndroid Build Coastguard Worker }
424*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--or"))
425*5e7646d2SAndroid Build Coastguard Worker {
426*5e7646d2SAndroid Build Coastguard Worker if (!current)
427*5e7646d2SAndroid Build Coastguard Worker {
428*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr,
429*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing expression before \"--or\"."));
430*5e7646d2SAndroid Build Coastguard Worker show_usage();
431*5e7646d2SAndroid Build Coastguard Worker }
432*5e7646d2SAndroid Build Coastguard Worker
433*5e7646d2SAndroid Build Coastguard Worker logic = IPPFIND_OP_OR;
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker if (parent && parent->op == IPPFIND_OP_OR)
436*5e7646d2SAndroid Build Coastguard Worker {
437*5e7646d2SAndroid Build Coastguard Worker /*
438*5e7646d2SAndroid Build Coastguard Worker * Already setup to do "foo --or bar --or baz"...
439*5e7646d2SAndroid Build Coastguard Worker */
440*5e7646d2SAndroid Build Coastguard Worker
441*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
442*5e7646d2SAndroid Build Coastguard Worker }
443*5e7646d2SAndroid Build Coastguard Worker else if (!current->prev && parent)
444*5e7646d2SAndroid Build Coastguard Worker {
445*5e7646d2SAndroid Build Coastguard Worker /*
446*5e7646d2SAndroid Build Coastguard Worker * Change parent node into an OR node...
447*5e7646d2SAndroid Build Coastguard Worker */
448*5e7646d2SAndroid Build Coastguard Worker
449*5e7646d2SAndroid Build Coastguard Worker parent->op = IPPFIND_OP_OR;
450*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
451*5e7646d2SAndroid Build Coastguard Worker }
452*5e7646d2SAndroid Build Coastguard Worker else if (!current->prev)
453*5e7646d2SAndroid Build Coastguard Worker {
454*5e7646d2SAndroid Build Coastguard Worker /*
455*5e7646d2SAndroid Build Coastguard Worker * Need to group "current" in a new OR node...
456*5e7646d2SAndroid Build Coastguard Worker */
457*5e7646d2SAndroid Build Coastguard Worker
458*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_OR, 0, NULL, NULL,
459*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
460*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
461*5e7646d2SAndroid Build Coastguard Worker
462*5e7646d2SAndroid Build Coastguard Worker temp->parent = parent;
463*5e7646d2SAndroid Build Coastguard Worker temp->child = current;
464*5e7646d2SAndroid Build Coastguard Worker current->parent = temp;
465*5e7646d2SAndroid Build Coastguard Worker
466*5e7646d2SAndroid Build Coastguard Worker if (parent)
467*5e7646d2SAndroid Build Coastguard Worker parent->child = temp;
468*5e7646d2SAndroid Build Coastguard Worker else
469*5e7646d2SAndroid Build Coastguard Worker expressions = temp;
470*5e7646d2SAndroid Build Coastguard Worker
471*5e7646d2SAndroid Build Coastguard Worker parent = temp;
472*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
473*5e7646d2SAndroid Build Coastguard Worker }
474*5e7646d2SAndroid Build Coastguard Worker else
475*5e7646d2SAndroid Build Coastguard Worker {
476*5e7646d2SAndroid Build Coastguard Worker /*
477*5e7646d2SAndroid Build Coastguard Worker * Need to group previous expressions in an AND node, and then
478*5e7646d2SAndroid Build Coastguard Worker * put that in an OR node...
479*5e7646d2SAndroid Build Coastguard Worker */
480*5e7646d2SAndroid Build Coastguard Worker
481*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
482*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
483*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
484*5e7646d2SAndroid Build Coastguard Worker
485*5e7646d2SAndroid Build Coastguard Worker while (current->prev)
486*5e7646d2SAndroid Build Coastguard Worker {
487*5e7646d2SAndroid Build Coastguard Worker current->parent = temp;
488*5e7646d2SAndroid Build Coastguard Worker current = current->prev;
489*5e7646d2SAndroid Build Coastguard Worker }
490*5e7646d2SAndroid Build Coastguard Worker
491*5e7646d2SAndroid Build Coastguard Worker current->parent = temp;
492*5e7646d2SAndroid Build Coastguard Worker temp->child = current;
493*5e7646d2SAndroid Build Coastguard Worker current = temp;
494*5e7646d2SAndroid Build Coastguard Worker
495*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_OR, 0, NULL, NULL,
496*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
497*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
498*5e7646d2SAndroid Build Coastguard Worker
499*5e7646d2SAndroid Build Coastguard Worker temp->parent = parent;
500*5e7646d2SAndroid Build Coastguard Worker current->parent = temp;
501*5e7646d2SAndroid Build Coastguard Worker
502*5e7646d2SAndroid Build Coastguard Worker if (parent)
503*5e7646d2SAndroid Build Coastguard Worker parent->child = temp;
504*5e7646d2SAndroid Build Coastguard Worker else
505*5e7646d2SAndroid Build Coastguard Worker expressions = temp;
506*5e7646d2SAndroid Build Coastguard Worker
507*5e7646d2SAndroid Build Coastguard Worker parent = temp;
508*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
509*5e7646d2SAndroid Build Coastguard Worker }
510*5e7646d2SAndroid Build Coastguard Worker }
511*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--path"))
512*5e7646d2SAndroid Build Coastguard Worker {
513*5e7646d2SAndroid Build Coastguard Worker i ++;
514*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
515*5e7646d2SAndroid Build Coastguard Worker {
516*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
517*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after %s."),
518*5e7646d2SAndroid Build Coastguard Worker "--path");
519*5e7646d2SAndroid Build Coastguard Worker show_usage();
520*5e7646d2SAndroid Build Coastguard Worker }
521*5e7646d2SAndroid Build Coastguard Worker
522*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PATH_REGEX, invert, NULL, argv[i],
523*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
524*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
525*5e7646d2SAndroid Build Coastguard Worker }
526*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--port"))
527*5e7646d2SAndroid Build Coastguard Worker {
528*5e7646d2SAndroid Build Coastguard Worker i ++;
529*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
530*5e7646d2SAndroid Build Coastguard Worker {
531*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
532*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Expected port range after %s."),
533*5e7646d2SAndroid Build Coastguard Worker "--port");
534*5e7646d2SAndroid Build Coastguard Worker show_usage();
535*5e7646d2SAndroid Build Coastguard Worker }
536*5e7646d2SAndroid Build Coastguard Worker
537*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PORT_RANGE, invert, argv[i], NULL,
538*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
539*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
540*5e7646d2SAndroid Build Coastguard Worker }
541*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--print"))
542*5e7646d2SAndroid Build Coastguard Worker {
543*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PRINT_URI, invert, NULL, NULL,
544*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
545*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
546*5e7646d2SAndroid Build Coastguard Worker
547*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
548*5e7646d2SAndroid Build Coastguard Worker }
549*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--print-name"))
550*5e7646d2SAndroid Build Coastguard Worker {
551*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PRINT_NAME, invert, NULL, NULL,
552*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
553*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
554*5e7646d2SAndroid Build Coastguard Worker
555*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
556*5e7646d2SAndroid Build Coastguard Worker }
557*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--quiet"))
558*5e7646d2SAndroid Build Coastguard Worker {
559*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_QUIET, invert, NULL, NULL,
560*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
561*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
562*5e7646d2SAndroid Build Coastguard Worker
563*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
564*5e7646d2SAndroid Build Coastguard Worker }
565*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--remote"))
566*5e7646d2SAndroid Build Coastguard Worker {
567*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_IS_REMOTE, invert, NULL, NULL,
568*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
569*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
570*5e7646d2SAndroid Build Coastguard Worker }
571*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--true"))
572*5e7646d2SAndroid Build Coastguard Worker {
573*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_TRUE, invert, NULL, argv[i],
574*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
575*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
576*5e7646d2SAndroid Build Coastguard Worker }
577*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--txt"))
578*5e7646d2SAndroid Build Coastguard Worker {
579*5e7646d2SAndroid Build Coastguard Worker i ++;
580*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
581*5e7646d2SAndroid Build Coastguard Worker {
582*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Expected key name after %s."),
583*5e7646d2SAndroid Build Coastguard Worker "--txt");
584*5e7646d2SAndroid Build Coastguard Worker show_usage();
585*5e7646d2SAndroid Build Coastguard Worker }
586*5e7646d2SAndroid Build Coastguard Worker
587*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_TXT_EXISTS, invert, argv[i], NULL,
588*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
589*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
590*5e7646d2SAndroid Build Coastguard Worker }
591*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(argv[i], "--txt-", 6))
592*5e7646d2SAndroid Build Coastguard Worker {
593*5e7646d2SAndroid Build Coastguard Worker const char *key = argv[i] + 6;/* TXT key */
594*5e7646d2SAndroid Build Coastguard Worker
595*5e7646d2SAndroid Build Coastguard Worker i ++;
596*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
597*5e7646d2SAndroid Build Coastguard Worker {
598*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
599*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after %s."),
600*5e7646d2SAndroid Build Coastguard Worker argv[i - 1]);
601*5e7646d2SAndroid Build Coastguard Worker show_usage();
602*5e7646d2SAndroid Build Coastguard Worker }
603*5e7646d2SAndroid Build Coastguard Worker
604*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_TXT_REGEX, invert, key, argv[i],
605*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
606*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
607*5e7646d2SAndroid Build Coastguard Worker }
608*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--uri"))
609*5e7646d2SAndroid Build Coastguard Worker {
610*5e7646d2SAndroid Build Coastguard Worker i ++;
611*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
612*5e7646d2SAndroid Build Coastguard Worker {
613*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
614*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after %s."),
615*5e7646d2SAndroid Build Coastguard Worker "--uri");
616*5e7646d2SAndroid Build Coastguard Worker show_usage();
617*5e7646d2SAndroid Build Coastguard Worker }
618*5e7646d2SAndroid Build Coastguard Worker
619*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_URI_REGEX, invert, NULL, argv[i],
620*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
621*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
622*5e7646d2SAndroid Build Coastguard Worker }
623*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "--version"))
624*5e7646d2SAndroid Build Coastguard Worker {
625*5e7646d2SAndroid Build Coastguard Worker show_version();
626*5e7646d2SAndroid Build Coastguard Worker }
627*5e7646d2SAndroid Build Coastguard Worker else
628*5e7646d2SAndroid Build Coastguard Worker {
629*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("%s: Unknown option \"%s\"."),
630*5e7646d2SAndroid Build Coastguard Worker "ippfind", argv[i]);
631*5e7646d2SAndroid Build Coastguard Worker show_usage();
632*5e7646d2SAndroid Build Coastguard Worker }
633*5e7646d2SAndroid Build Coastguard Worker
634*5e7646d2SAndroid Build Coastguard Worker if (temp)
635*5e7646d2SAndroid Build Coastguard Worker {
636*5e7646d2SAndroid Build Coastguard Worker /*
637*5e7646d2SAndroid Build Coastguard Worker * Add new expression...
638*5e7646d2SAndroid Build Coastguard Worker */
639*5e7646d2SAndroid Build Coastguard Worker
640*5e7646d2SAndroid Build Coastguard Worker if (logic == IPPFIND_OP_AND &&
641*5e7646d2SAndroid Build Coastguard Worker current && current->prev &&
642*5e7646d2SAndroid Build Coastguard Worker parent && parent->op != IPPFIND_OP_AND)
643*5e7646d2SAndroid Build Coastguard Worker {
644*5e7646d2SAndroid Build Coastguard Worker /*
645*5e7646d2SAndroid Build Coastguard Worker * Need to re-group "current" in a new AND node...
646*5e7646d2SAndroid Build Coastguard Worker */
647*5e7646d2SAndroid Build Coastguard Worker
648*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *tempand; /* Temporary AND node */
649*5e7646d2SAndroid Build Coastguard Worker
650*5e7646d2SAndroid Build Coastguard Worker if ((tempand = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
651*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
652*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
653*5e7646d2SAndroid Build Coastguard Worker
654*5e7646d2SAndroid Build Coastguard Worker /*
655*5e7646d2SAndroid Build Coastguard Worker * Replace "current" with new AND node at the end of this list...
656*5e7646d2SAndroid Build Coastguard Worker */
657*5e7646d2SAndroid Build Coastguard Worker
658*5e7646d2SAndroid Build Coastguard Worker current->prev->next = tempand;
659*5e7646d2SAndroid Build Coastguard Worker tempand->prev = current->prev;
660*5e7646d2SAndroid Build Coastguard Worker tempand->parent = parent;
661*5e7646d2SAndroid Build Coastguard Worker
662*5e7646d2SAndroid Build Coastguard Worker /*
663*5e7646d2SAndroid Build Coastguard Worker * Add "current to the new AND node...
664*5e7646d2SAndroid Build Coastguard Worker */
665*5e7646d2SAndroid Build Coastguard Worker
666*5e7646d2SAndroid Build Coastguard Worker tempand->child = current;
667*5e7646d2SAndroid Build Coastguard Worker current->parent = tempand;
668*5e7646d2SAndroid Build Coastguard Worker current->prev = NULL;
669*5e7646d2SAndroid Build Coastguard Worker parent = tempand;
670*5e7646d2SAndroid Build Coastguard Worker }
671*5e7646d2SAndroid Build Coastguard Worker
672*5e7646d2SAndroid Build Coastguard Worker /*
673*5e7646d2SAndroid Build Coastguard Worker * Add the new node at current level...
674*5e7646d2SAndroid Build Coastguard Worker */
675*5e7646d2SAndroid Build Coastguard Worker
676*5e7646d2SAndroid Build Coastguard Worker temp->parent = parent;
677*5e7646d2SAndroid Build Coastguard Worker temp->prev = current;
678*5e7646d2SAndroid Build Coastguard Worker
679*5e7646d2SAndroid Build Coastguard Worker if (current)
680*5e7646d2SAndroid Build Coastguard Worker current->next = temp;
681*5e7646d2SAndroid Build Coastguard Worker else if (parent)
682*5e7646d2SAndroid Build Coastguard Worker parent->child = temp;
683*5e7646d2SAndroid Build Coastguard Worker else
684*5e7646d2SAndroid Build Coastguard Worker expressions = temp;
685*5e7646d2SAndroid Build Coastguard Worker
686*5e7646d2SAndroid Build Coastguard Worker current = temp;
687*5e7646d2SAndroid Build Coastguard Worker invert = 0;
688*5e7646d2SAndroid Build Coastguard Worker logic = IPPFIND_OP_AND;
689*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
690*5e7646d2SAndroid Build Coastguard Worker }
691*5e7646d2SAndroid Build Coastguard Worker }
692*5e7646d2SAndroid Build Coastguard Worker else
693*5e7646d2SAndroid Build Coastguard Worker {
694*5e7646d2SAndroid Build Coastguard Worker /*
695*5e7646d2SAndroid Build Coastguard Worker * Parse -o options
696*5e7646d2SAndroid Build Coastguard Worker */
697*5e7646d2SAndroid Build Coastguard Worker
698*5e7646d2SAndroid Build Coastguard Worker for (opt = argv[i] + 1; *opt; opt ++)
699*5e7646d2SAndroid Build Coastguard Worker {
700*5e7646d2SAndroid Build Coastguard Worker switch (*opt)
701*5e7646d2SAndroid Build Coastguard Worker {
702*5e7646d2SAndroid Build Coastguard Worker case '4' :
703*5e7646d2SAndroid Build Coastguard Worker address_family = AF_INET;
704*5e7646d2SAndroid Build Coastguard Worker break;
705*5e7646d2SAndroid Build Coastguard Worker
706*5e7646d2SAndroid Build Coastguard Worker case '6' :
707*5e7646d2SAndroid Build Coastguard Worker address_family = AF_INET6;
708*5e7646d2SAndroid Build Coastguard Worker break;
709*5e7646d2SAndroid Build Coastguard Worker
710*5e7646d2SAndroid Build Coastguard Worker case 'N' : /* Literal name */
711*5e7646d2SAndroid Build Coastguard Worker i ++;
712*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
713*5e7646d2SAndroid Build Coastguard Worker {
714*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Missing name after %s."), "-N");
715*5e7646d2SAndroid Build Coastguard Worker show_usage();
716*5e7646d2SAndroid Build Coastguard Worker }
717*5e7646d2SAndroid Build Coastguard Worker
718*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_NAME_LITERAL, invert, argv[i], NULL, NULL)) == NULL)
719*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
720*5e7646d2SAndroid Build Coastguard Worker break;
721*5e7646d2SAndroid Build Coastguard Worker
722*5e7646d2SAndroid Build Coastguard Worker case 'P' :
723*5e7646d2SAndroid Build Coastguard Worker i ++;
724*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
725*5e7646d2SAndroid Build Coastguard Worker {
726*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
727*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Expected port range after %s."),
728*5e7646d2SAndroid Build Coastguard Worker "-P");
729*5e7646d2SAndroid Build Coastguard Worker show_usage();
730*5e7646d2SAndroid Build Coastguard Worker }
731*5e7646d2SAndroid Build Coastguard Worker
732*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PORT_RANGE, invert, argv[i],
733*5e7646d2SAndroid Build Coastguard Worker NULL, NULL)) == NULL)
734*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
735*5e7646d2SAndroid Build Coastguard Worker break;
736*5e7646d2SAndroid Build Coastguard Worker
737*5e7646d2SAndroid Build Coastguard Worker case 'T' :
738*5e7646d2SAndroid Build Coastguard Worker i ++;
739*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
740*5e7646d2SAndroid Build Coastguard Worker {
741*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
742*5e7646d2SAndroid Build Coastguard Worker _("%s: Missing timeout for \"-T\"."),
743*5e7646d2SAndroid Build Coastguard Worker "ippfind");
744*5e7646d2SAndroid Build Coastguard Worker show_usage();
745*5e7646d2SAndroid Build Coastguard Worker }
746*5e7646d2SAndroid Build Coastguard Worker
747*5e7646d2SAndroid Build Coastguard Worker bonjour_timeout = atof(argv[i]);
748*5e7646d2SAndroid Build Coastguard Worker break;
749*5e7646d2SAndroid Build Coastguard Worker
750*5e7646d2SAndroid Build Coastguard Worker case 'V' :
751*5e7646d2SAndroid Build Coastguard Worker i ++;
752*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
753*5e7646d2SAndroid Build Coastguard Worker {
754*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
755*5e7646d2SAndroid Build Coastguard Worker _("%s: Missing version for \"-V\"."),
756*5e7646d2SAndroid Build Coastguard Worker "ippfind");
757*5e7646d2SAndroid Build Coastguard Worker show_usage();
758*5e7646d2SAndroid Build Coastguard Worker }
759*5e7646d2SAndroid Build Coastguard Worker
760*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(argv[i], "1.1"))
761*5e7646d2SAndroid Build Coastguard Worker ipp_version = 11;
762*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "2.0"))
763*5e7646d2SAndroid Build Coastguard Worker ipp_version = 20;
764*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "2.1"))
765*5e7646d2SAndroid Build Coastguard Worker ipp_version = 21;
766*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "2.2"))
767*5e7646d2SAndroid Build Coastguard Worker ipp_version = 22;
768*5e7646d2SAndroid Build Coastguard Worker else
769*5e7646d2SAndroid Build Coastguard Worker {
770*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("%s: Bad version %s for \"-V\"."),
771*5e7646d2SAndroid Build Coastguard Worker "ippfind", argv[i]);
772*5e7646d2SAndroid Build Coastguard Worker show_usage();
773*5e7646d2SAndroid Build Coastguard Worker }
774*5e7646d2SAndroid Build Coastguard Worker break;
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker case 'd' :
777*5e7646d2SAndroid Build Coastguard Worker i ++;
778*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
779*5e7646d2SAndroid Build Coastguard Worker {
780*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
781*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after "
782*5e7646d2SAndroid Build Coastguard Worker "%s."), "-d");
783*5e7646d2SAndroid Build Coastguard Worker show_usage();
784*5e7646d2SAndroid Build Coastguard Worker }
785*5e7646d2SAndroid Build Coastguard Worker
786*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_DOMAIN_REGEX, invert, NULL,
787*5e7646d2SAndroid Build Coastguard Worker argv[i], NULL)) == NULL)
788*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
789*5e7646d2SAndroid Build Coastguard Worker break;
790*5e7646d2SAndroid Build Coastguard Worker
791*5e7646d2SAndroid Build Coastguard Worker case 'h' :
792*5e7646d2SAndroid Build Coastguard Worker i ++;
793*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
794*5e7646d2SAndroid Build Coastguard Worker {
795*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
796*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after "
797*5e7646d2SAndroid Build Coastguard Worker "%s."), "-h");
798*5e7646d2SAndroid Build Coastguard Worker show_usage();
799*5e7646d2SAndroid Build Coastguard Worker }
800*5e7646d2SAndroid Build Coastguard Worker
801*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_HOST_REGEX, invert, NULL,
802*5e7646d2SAndroid Build Coastguard Worker argv[i], NULL)) == NULL)
803*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
804*5e7646d2SAndroid Build Coastguard Worker break;
805*5e7646d2SAndroid Build Coastguard Worker
806*5e7646d2SAndroid Build Coastguard Worker case 'l' :
807*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_LIST, invert, NULL, NULL,
808*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
809*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
810*5e7646d2SAndroid Build Coastguard Worker
811*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
812*5e7646d2SAndroid Build Coastguard Worker break;
813*5e7646d2SAndroid Build Coastguard Worker
814*5e7646d2SAndroid Build Coastguard Worker case 'n' :
815*5e7646d2SAndroid Build Coastguard Worker i ++;
816*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
817*5e7646d2SAndroid Build Coastguard Worker {
818*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
819*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after "
820*5e7646d2SAndroid Build Coastguard Worker "%s."), "-n");
821*5e7646d2SAndroid Build Coastguard Worker show_usage();
822*5e7646d2SAndroid Build Coastguard Worker }
823*5e7646d2SAndroid Build Coastguard Worker
824*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_NAME_REGEX, invert, NULL,
825*5e7646d2SAndroid Build Coastguard Worker argv[i], NULL)) == NULL)
826*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
827*5e7646d2SAndroid Build Coastguard Worker break;
828*5e7646d2SAndroid Build Coastguard Worker
829*5e7646d2SAndroid Build Coastguard Worker case 'p' :
830*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PRINT_URI, invert, NULL, NULL,
831*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
832*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
833*5e7646d2SAndroid Build Coastguard Worker
834*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
835*5e7646d2SAndroid Build Coastguard Worker break;
836*5e7646d2SAndroid Build Coastguard Worker
837*5e7646d2SAndroid Build Coastguard Worker case 'q' :
838*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_QUIET, invert, NULL, NULL,
839*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
840*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
841*5e7646d2SAndroid Build Coastguard Worker
842*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
843*5e7646d2SAndroid Build Coastguard Worker break;
844*5e7646d2SAndroid Build Coastguard Worker
845*5e7646d2SAndroid Build Coastguard Worker case 'r' :
846*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_IS_REMOTE, invert, NULL, NULL,
847*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
848*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
849*5e7646d2SAndroid Build Coastguard Worker break;
850*5e7646d2SAndroid Build Coastguard Worker
851*5e7646d2SAndroid Build Coastguard Worker case 's' :
852*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PRINT_NAME, invert, NULL, NULL,
853*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
854*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
855*5e7646d2SAndroid Build Coastguard Worker
856*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
857*5e7646d2SAndroid Build Coastguard Worker break;
858*5e7646d2SAndroid Build Coastguard Worker
859*5e7646d2SAndroid Build Coastguard Worker case 't' :
860*5e7646d2SAndroid Build Coastguard Worker i ++;
861*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
862*5e7646d2SAndroid Build Coastguard Worker {
863*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
864*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing key name after %s."),
865*5e7646d2SAndroid Build Coastguard Worker "-t");
866*5e7646d2SAndroid Build Coastguard Worker show_usage();
867*5e7646d2SAndroid Build Coastguard Worker }
868*5e7646d2SAndroid Build Coastguard Worker
869*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_TXT_EXISTS, invert, argv[i],
870*5e7646d2SAndroid Build Coastguard Worker NULL, NULL)) == NULL)
871*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
872*5e7646d2SAndroid Build Coastguard Worker break;
873*5e7646d2SAndroid Build Coastguard Worker
874*5e7646d2SAndroid Build Coastguard Worker case 'u' :
875*5e7646d2SAndroid Build Coastguard Worker i ++;
876*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
877*5e7646d2SAndroid Build Coastguard Worker {
878*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
879*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing regular expression after "
880*5e7646d2SAndroid Build Coastguard Worker "%s."), "-u");
881*5e7646d2SAndroid Build Coastguard Worker show_usage();
882*5e7646d2SAndroid Build Coastguard Worker }
883*5e7646d2SAndroid Build Coastguard Worker
884*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_URI_REGEX, invert, NULL,
885*5e7646d2SAndroid Build Coastguard Worker argv[i], NULL)) == NULL)
886*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
887*5e7646d2SAndroid Build Coastguard Worker break;
888*5e7646d2SAndroid Build Coastguard Worker
889*5e7646d2SAndroid Build Coastguard Worker case 'x' :
890*5e7646d2SAndroid Build Coastguard Worker i ++;
891*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
892*5e7646d2SAndroid Build Coastguard Worker {
893*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
894*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing program after %s."),
895*5e7646d2SAndroid Build Coastguard Worker "-x");
896*5e7646d2SAndroid Build Coastguard Worker show_usage();
897*5e7646d2SAndroid Build Coastguard Worker }
898*5e7646d2SAndroid Build Coastguard Worker
899*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_EXEC, invert, NULL, NULL,
900*5e7646d2SAndroid Build Coastguard Worker argv + i)) == NULL)
901*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
902*5e7646d2SAndroid Build Coastguard Worker
903*5e7646d2SAndroid Build Coastguard Worker while (i < argc)
904*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(argv[i], ";"))
905*5e7646d2SAndroid Build Coastguard Worker break;
906*5e7646d2SAndroid Build Coastguard Worker else
907*5e7646d2SAndroid Build Coastguard Worker i ++;
908*5e7646d2SAndroid Build Coastguard Worker
909*5e7646d2SAndroid Build Coastguard Worker if (i >= argc)
910*5e7646d2SAndroid Build Coastguard Worker {
911*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
912*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing semi-colon after %s."),
913*5e7646d2SAndroid Build Coastguard Worker "-x");
914*5e7646d2SAndroid Build Coastguard Worker show_usage();
915*5e7646d2SAndroid Build Coastguard Worker }
916*5e7646d2SAndroid Build Coastguard Worker
917*5e7646d2SAndroid Build Coastguard Worker have_output = 1;
918*5e7646d2SAndroid Build Coastguard Worker break;
919*5e7646d2SAndroid Build Coastguard Worker
920*5e7646d2SAndroid Build Coastguard Worker default :
921*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("%s: Unknown option \"-%c\"."),
922*5e7646d2SAndroid Build Coastguard Worker "ippfind", *opt);
923*5e7646d2SAndroid Build Coastguard Worker show_usage();
924*5e7646d2SAndroid Build Coastguard Worker }
925*5e7646d2SAndroid Build Coastguard Worker
926*5e7646d2SAndroid Build Coastguard Worker if (temp)
927*5e7646d2SAndroid Build Coastguard Worker {
928*5e7646d2SAndroid Build Coastguard Worker /*
929*5e7646d2SAndroid Build Coastguard Worker * Add new expression...
930*5e7646d2SAndroid Build Coastguard Worker */
931*5e7646d2SAndroid Build Coastguard Worker
932*5e7646d2SAndroid Build Coastguard Worker if (logic == IPPFIND_OP_AND &&
933*5e7646d2SAndroid Build Coastguard Worker current && current->prev &&
934*5e7646d2SAndroid Build Coastguard Worker parent && parent->op != IPPFIND_OP_AND)
935*5e7646d2SAndroid Build Coastguard Worker {
936*5e7646d2SAndroid Build Coastguard Worker /*
937*5e7646d2SAndroid Build Coastguard Worker * Need to re-group "current" in a new AND node...
938*5e7646d2SAndroid Build Coastguard Worker */
939*5e7646d2SAndroid Build Coastguard Worker
940*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *tempand; /* Temporary AND node */
941*5e7646d2SAndroid Build Coastguard Worker
942*5e7646d2SAndroid Build Coastguard Worker if ((tempand = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
943*5e7646d2SAndroid Build Coastguard Worker NULL)) == NULL)
944*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
945*5e7646d2SAndroid Build Coastguard Worker
946*5e7646d2SAndroid Build Coastguard Worker /*
947*5e7646d2SAndroid Build Coastguard Worker * Replace "current" with new AND node at the end of this list...
948*5e7646d2SAndroid Build Coastguard Worker */
949*5e7646d2SAndroid Build Coastguard Worker
950*5e7646d2SAndroid Build Coastguard Worker current->prev->next = tempand;
951*5e7646d2SAndroid Build Coastguard Worker tempand->prev = current->prev;
952*5e7646d2SAndroid Build Coastguard Worker tempand->parent = parent;
953*5e7646d2SAndroid Build Coastguard Worker
954*5e7646d2SAndroid Build Coastguard Worker /*
955*5e7646d2SAndroid Build Coastguard Worker * Add "current to the new AND node...
956*5e7646d2SAndroid Build Coastguard Worker */
957*5e7646d2SAndroid Build Coastguard Worker
958*5e7646d2SAndroid Build Coastguard Worker tempand->child = current;
959*5e7646d2SAndroid Build Coastguard Worker current->parent = tempand;
960*5e7646d2SAndroid Build Coastguard Worker current->prev = NULL;
961*5e7646d2SAndroid Build Coastguard Worker parent = tempand;
962*5e7646d2SAndroid Build Coastguard Worker }
963*5e7646d2SAndroid Build Coastguard Worker
964*5e7646d2SAndroid Build Coastguard Worker /*
965*5e7646d2SAndroid Build Coastguard Worker * Add the new node at current level...
966*5e7646d2SAndroid Build Coastguard Worker */
967*5e7646d2SAndroid Build Coastguard Worker
968*5e7646d2SAndroid Build Coastguard Worker temp->parent = parent;
969*5e7646d2SAndroid Build Coastguard Worker temp->prev = current;
970*5e7646d2SAndroid Build Coastguard Worker
971*5e7646d2SAndroid Build Coastguard Worker if (current)
972*5e7646d2SAndroid Build Coastguard Worker current->next = temp;
973*5e7646d2SAndroid Build Coastguard Worker else if (parent)
974*5e7646d2SAndroid Build Coastguard Worker parent->child = temp;
975*5e7646d2SAndroid Build Coastguard Worker else
976*5e7646d2SAndroid Build Coastguard Worker expressions = temp;
977*5e7646d2SAndroid Build Coastguard Worker
978*5e7646d2SAndroid Build Coastguard Worker current = temp;
979*5e7646d2SAndroid Build Coastguard Worker invert = 0;
980*5e7646d2SAndroid Build Coastguard Worker logic = IPPFIND_OP_AND;
981*5e7646d2SAndroid Build Coastguard Worker temp = NULL;
982*5e7646d2SAndroid Build Coastguard Worker }
983*5e7646d2SAndroid Build Coastguard Worker }
984*5e7646d2SAndroid Build Coastguard Worker }
985*5e7646d2SAndroid Build Coastguard Worker }
986*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "("))
987*5e7646d2SAndroid Build Coastguard Worker {
988*5e7646d2SAndroid Build Coastguard Worker if (num_parens >= 100)
989*5e7646d2SAndroid Build Coastguard Worker {
990*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("ippfind: Too many parenthesis."));
991*5e7646d2SAndroid Build Coastguard Worker show_usage();
992*5e7646d2SAndroid Build Coastguard Worker }
993*5e7646d2SAndroid Build Coastguard Worker
994*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_AND, invert, NULL, NULL, NULL)) == NULL)
995*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
996*5e7646d2SAndroid Build Coastguard Worker
997*5e7646d2SAndroid Build Coastguard Worker parens[num_parens++] = temp;
998*5e7646d2SAndroid Build Coastguard Worker
999*5e7646d2SAndroid Build Coastguard Worker if (current)
1000*5e7646d2SAndroid Build Coastguard Worker {
1001*5e7646d2SAndroid Build Coastguard Worker temp->parent = current->parent;
1002*5e7646d2SAndroid Build Coastguard Worker current->next = temp;
1003*5e7646d2SAndroid Build Coastguard Worker temp->prev = current;
1004*5e7646d2SAndroid Build Coastguard Worker }
1005*5e7646d2SAndroid Build Coastguard Worker else
1006*5e7646d2SAndroid Build Coastguard Worker expressions = temp;
1007*5e7646d2SAndroid Build Coastguard Worker
1008*5e7646d2SAndroid Build Coastguard Worker parent = temp;
1009*5e7646d2SAndroid Build Coastguard Worker current = NULL;
1010*5e7646d2SAndroid Build Coastguard Worker invert = 0;
1011*5e7646d2SAndroid Build Coastguard Worker logic = IPPFIND_OP_AND;
1012*5e7646d2SAndroid Build Coastguard Worker }
1013*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], ")"))
1014*5e7646d2SAndroid Build Coastguard Worker {
1015*5e7646d2SAndroid Build Coastguard Worker if (num_parens <= 0)
1016*5e7646d2SAndroid Build Coastguard Worker {
1017*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("ippfind: Missing open parenthesis."));
1018*5e7646d2SAndroid Build Coastguard Worker show_usage();
1019*5e7646d2SAndroid Build Coastguard Worker }
1020*5e7646d2SAndroid Build Coastguard Worker
1021*5e7646d2SAndroid Build Coastguard Worker current = parens[--num_parens];
1022*5e7646d2SAndroid Build Coastguard Worker parent = current->parent;
1023*5e7646d2SAndroid Build Coastguard Worker invert = 0;
1024*5e7646d2SAndroid Build Coastguard Worker logic = IPPFIND_OP_AND;
1025*5e7646d2SAndroid Build Coastguard Worker }
1026*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(argv[i], "!"))
1027*5e7646d2SAndroid Build Coastguard Worker {
1028*5e7646d2SAndroid Build Coastguard Worker invert = 1;
1029*5e7646d2SAndroid Build Coastguard Worker }
1030*5e7646d2SAndroid Build Coastguard Worker else
1031*5e7646d2SAndroid Build Coastguard Worker {
1032*5e7646d2SAndroid Build Coastguard Worker /*
1033*5e7646d2SAndroid Build Coastguard Worker * _regtype._tcp[,subtype][.domain]
1034*5e7646d2SAndroid Build Coastguard Worker *
1035*5e7646d2SAndroid Build Coastguard Worker * OR
1036*5e7646d2SAndroid Build Coastguard Worker *
1037*5e7646d2SAndroid Build Coastguard Worker * service-name[._regtype._tcp[.domain]]
1038*5e7646d2SAndroid Build Coastguard Worker */
1039*5e7646d2SAndroid Build Coastguard Worker
1040*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(searches, argv[i]);
1041*5e7646d2SAndroid Build Coastguard Worker }
1042*5e7646d2SAndroid Build Coastguard Worker }
1043*5e7646d2SAndroid Build Coastguard Worker
1044*5e7646d2SAndroid Build Coastguard Worker if (num_parens > 0)
1045*5e7646d2SAndroid Build Coastguard Worker {
1046*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("ippfind: Missing close parenthesis."));
1047*5e7646d2SAndroid Build Coastguard Worker show_usage();
1048*5e7646d2SAndroid Build Coastguard Worker }
1049*5e7646d2SAndroid Build Coastguard Worker
1050*5e7646d2SAndroid Build Coastguard Worker if (!have_output)
1051*5e7646d2SAndroid Build Coastguard Worker {
1052*5e7646d2SAndroid Build Coastguard Worker /*
1053*5e7646d2SAndroid Build Coastguard Worker * Add an implicit --print-uri to the end...
1054*5e7646d2SAndroid Build Coastguard Worker */
1055*5e7646d2SAndroid Build Coastguard Worker
1056*5e7646d2SAndroid Build Coastguard Worker if ((temp = new_expr(IPPFIND_OP_PRINT_URI, 0, NULL, NULL, NULL)) == NULL)
1057*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_MEMORY);
1058*5e7646d2SAndroid Build Coastguard Worker
1059*5e7646d2SAndroid Build Coastguard Worker if (current)
1060*5e7646d2SAndroid Build Coastguard Worker {
1061*5e7646d2SAndroid Build Coastguard Worker while (current->parent)
1062*5e7646d2SAndroid Build Coastguard Worker current = current->parent;
1063*5e7646d2SAndroid Build Coastguard Worker
1064*5e7646d2SAndroid Build Coastguard Worker current->next = temp;
1065*5e7646d2SAndroid Build Coastguard Worker temp->prev = current;
1066*5e7646d2SAndroid Build Coastguard Worker }
1067*5e7646d2SAndroid Build Coastguard Worker else
1068*5e7646d2SAndroid Build Coastguard Worker expressions = temp;
1069*5e7646d2SAndroid Build Coastguard Worker }
1070*5e7646d2SAndroid Build Coastguard Worker
1071*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayCount(searches) == 0)
1072*5e7646d2SAndroid Build Coastguard Worker {
1073*5e7646d2SAndroid Build Coastguard Worker /*
1074*5e7646d2SAndroid Build Coastguard Worker * Add an implicit browse for IPP printers ("_ipp._tcp")...
1075*5e7646d2SAndroid Build Coastguard Worker */
1076*5e7646d2SAndroid Build Coastguard Worker
1077*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(searches, "_ipp._tcp");
1078*5e7646d2SAndroid Build Coastguard Worker }
1079*5e7646d2SAndroid Build Coastguard Worker
1080*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
1081*5e7646d2SAndroid Build Coastguard Worker {
1082*5e7646d2SAndroid Build Coastguard Worker int indent = 4; /* Indentation */
1083*5e7646d2SAndroid Build Coastguard Worker
1084*5e7646d2SAndroid Build Coastguard Worker puts("Expression tree:");
1085*5e7646d2SAndroid Build Coastguard Worker current = expressions;
1086*5e7646d2SAndroid Build Coastguard Worker while (current)
1087*5e7646d2SAndroid Build Coastguard Worker {
1088*5e7646d2SAndroid Build Coastguard Worker /*
1089*5e7646d2SAndroid Build Coastguard Worker * Print the current node...
1090*5e7646d2SAndroid Build Coastguard Worker */
1091*5e7646d2SAndroid Build Coastguard Worker
1092*5e7646d2SAndroid Build Coastguard Worker printf("%*s%s%s\n", indent, "", current->invert ? "!" : "",
1093*5e7646d2SAndroid Build Coastguard Worker ops[current->op]);
1094*5e7646d2SAndroid Build Coastguard Worker
1095*5e7646d2SAndroid Build Coastguard Worker /*
1096*5e7646d2SAndroid Build Coastguard Worker * Advance to the next node...
1097*5e7646d2SAndroid Build Coastguard Worker */
1098*5e7646d2SAndroid Build Coastguard Worker
1099*5e7646d2SAndroid Build Coastguard Worker if (current->child)
1100*5e7646d2SAndroid Build Coastguard Worker {
1101*5e7646d2SAndroid Build Coastguard Worker current = current->child;
1102*5e7646d2SAndroid Build Coastguard Worker indent += 4;
1103*5e7646d2SAndroid Build Coastguard Worker }
1104*5e7646d2SAndroid Build Coastguard Worker else if (current->next)
1105*5e7646d2SAndroid Build Coastguard Worker current = current->next;
1106*5e7646d2SAndroid Build Coastguard Worker else if (current->parent)
1107*5e7646d2SAndroid Build Coastguard Worker {
1108*5e7646d2SAndroid Build Coastguard Worker while (current->parent)
1109*5e7646d2SAndroid Build Coastguard Worker {
1110*5e7646d2SAndroid Build Coastguard Worker indent -= 4;
1111*5e7646d2SAndroid Build Coastguard Worker current = current->parent;
1112*5e7646d2SAndroid Build Coastguard Worker if (current->next)
1113*5e7646d2SAndroid Build Coastguard Worker break;
1114*5e7646d2SAndroid Build Coastguard Worker }
1115*5e7646d2SAndroid Build Coastguard Worker
1116*5e7646d2SAndroid Build Coastguard Worker current = current->next;
1117*5e7646d2SAndroid Build Coastguard Worker }
1118*5e7646d2SAndroid Build Coastguard Worker else
1119*5e7646d2SAndroid Build Coastguard Worker current = NULL;
1120*5e7646d2SAndroid Build Coastguard Worker }
1121*5e7646d2SAndroid Build Coastguard Worker
1122*5e7646d2SAndroid Build Coastguard Worker puts("\nSearch items:");
1123*5e7646d2SAndroid Build Coastguard Worker for (search = (const char *)cupsArrayFirst(searches);
1124*5e7646d2SAndroid Build Coastguard Worker search;
1125*5e7646d2SAndroid Build Coastguard Worker search = (const char *)cupsArrayNext(searches))
1126*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", search);
1127*5e7646d2SAndroid Build Coastguard Worker }
1128*5e7646d2SAndroid Build Coastguard Worker
1129*5e7646d2SAndroid Build Coastguard Worker /*
1130*5e7646d2SAndroid Build Coastguard Worker * Start up browsing/resolving...
1131*5e7646d2SAndroid Build Coastguard Worker */
1132*5e7646d2SAndroid Build Coastguard Worker
1133*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1134*5e7646d2SAndroid Build Coastguard Worker if ((err = DNSServiceCreateConnection(&dnssd_ref)) != kDNSServiceErr_NoError)
1135*5e7646d2SAndroid Build Coastguard Worker {
1136*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to use Bonjour: %s"),
1137*5e7646d2SAndroid Build Coastguard Worker dnssd_error_string(err));
1138*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1139*5e7646d2SAndroid Build Coastguard Worker }
1140*5e7646d2SAndroid Build Coastguard Worker
1141*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
1142*5e7646d2SAndroid Build Coastguard Worker if ((avahi_poll = avahi_simple_poll_new()) == NULL)
1143*5e7646d2SAndroid Build Coastguard Worker {
1144*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to use Bonjour: %s"),
1145*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
1146*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1147*5e7646d2SAndroid Build Coastguard Worker }
1148*5e7646d2SAndroid Build Coastguard Worker
1149*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_set_func(avahi_poll, poll_callback, NULL);
1150*5e7646d2SAndroid Build Coastguard Worker
1151*5e7646d2SAndroid Build Coastguard Worker avahi_client = avahi_client_new(avahi_simple_poll_get(avahi_poll),
1152*5e7646d2SAndroid Build Coastguard Worker 0, client_callback, avahi_poll, &err);
1153*5e7646d2SAndroid Build Coastguard Worker if (!avahi_client)
1154*5e7646d2SAndroid Build Coastguard Worker {
1155*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to use Bonjour: %s"),
1156*5e7646d2SAndroid Build Coastguard Worker dnssd_error_string(err));
1157*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1158*5e7646d2SAndroid Build Coastguard Worker }
1159*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1160*5e7646d2SAndroid Build Coastguard Worker
1161*5e7646d2SAndroid Build Coastguard Worker for (search = (const char *)cupsArrayFirst(searches);
1162*5e7646d2SAndroid Build Coastguard Worker search;
1163*5e7646d2SAndroid Build Coastguard Worker search = (const char *)cupsArrayNext(searches))
1164*5e7646d2SAndroid Build Coastguard Worker {
1165*5e7646d2SAndroid Build Coastguard Worker char buf[1024], /* Full name string */
1166*5e7646d2SAndroid Build Coastguard Worker *name = NULL, /* Service instance name */
1167*5e7646d2SAndroid Build Coastguard Worker *regtype, /* Registration type */
1168*5e7646d2SAndroid Build Coastguard Worker *domain; /* Domain, if any */
1169*5e7646d2SAndroid Build Coastguard Worker
1170*5e7646d2SAndroid Build Coastguard Worker strlcpy(buf, search, sizeof(buf));
1171*5e7646d2SAndroid Build Coastguard Worker
1172*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(buf, "_http._", 7) || !strncmp(buf, "_https._", 8) || !strncmp(buf, "_ipp._", 6) || !strncmp(buf, "_ipps._", 7))
1173*5e7646d2SAndroid Build Coastguard Worker {
1174*5e7646d2SAndroid Build Coastguard Worker regtype = buf;
1175*5e7646d2SAndroid Build Coastguard Worker }
1176*5e7646d2SAndroid Build Coastguard Worker else if ((regtype = strstr(buf, "._")) != NULL)
1177*5e7646d2SAndroid Build Coastguard Worker {
1178*5e7646d2SAndroid Build Coastguard Worker if (strcmp(regtype, "._tcp"))
1179*5e7646d2SAndroid Build Coastguard Worker {
1180*5e7646d2SAndroid Build Coastguard Worker /*
1181*5e7646d2SAndroid Build Coastguard Worker * "something._protocol._tcp" -> search for something with the given
1182*5e7646d2SAndroid Build Coastguard Worker * protocol...
1183*5e7646d2SAndroid Build Coastguard Worker */
1184*5e7646d2SAndroid Build Coastguard Worker
1185*5e7646d2SAndroid Build Coastguard Worker name = buf;
1186*5e7646d2SAndroid Build Coastguard Worker *regtype++ = '\0';
1187*5e7646d2SAndroid Build Coastguard Worker }
1188*5e7646d2SAndroid Build Coastguard Worker else
1189*5e7646d2SAndroid Build Coastguard Worker {
1190*5e7646d2SAndroid Build Coastguard Worker /*
1191*5e7646d2SAndroid Build Coastguard Worker * "_protocol._tcp" -> search for everything with the given protocol...
1192*5e7646d2SAndroid Build Coastguard Worker */
1193*5e7646d2SAndroid Build Coastguard Worker
1194*5e7646d2SAndroid Build Coastguard Worker /* name = NULL; */
1195*5e7646d2SAndroid Build Coastguard Worker regtype = buf;
1196*5e7646d2SAndroid Build Coastguard Worker }
1197*5e7646d2SAndroid Build Coastguard Worker }
1198*5e7646d2SAndroid Build Coastguard Worker else
1199*5e7646d2SAndroid Build Coastguard Worker {
1200*5e7646d2SAndroid Build Coastguard Worker /*
1201*5e7646d2SAndroid Build Coastguard Worker * "something" -> search for something with IPP protocol...
1202*5e7646d2SAndroid Build Coastguard Worker */
1203*5e7646d2SAndroid Build Coastguard Worker
1204*5e7646d2SAndroid Build Coastguard Worker name = buf;
1205*5e7646d2SAndroid Build Coastguard Worker regtype = "_ipp._tcp";
1206*5e7646d2SAndroid Build Coastguard Worker }
1207*5e7646d2SAndroid Build Coastguard Worker
1208*5e7646d2SAndroid Build Coastguard Worker for (domain = regtype; *domain; domain ++)
1209*5e7646d2SAndroid Build Coastguard Worker {
1210*5e7646d2SAndroid Build Coastguard Worker if (*domain == '.' && domain[1] != '_')
1211*5e7646d2SAndroid Build Coastguard Worker {
1212*5e7646d2SAndroid Build Coastguard Worker *domain++ = '\0';
1213*5e7646d2SAndroid Build Coastguard Worker break;
1214*5e7646d2SAndroid Build Coastguard Worker }
1215*5e7646d2SAndroid Build Coastguard Worker }
1216*5e7646d2SAndroid Build Coastguard Worker
1217*5e7646d2SAndroid Build Coastguard Worker if (!*domain)
1218*5e7646d2SAndroid Build Coastguard Worker domain = NULL;
1219*5e7646d2SAndroid Build Coastguard Worker
1220*5e7646d2SAndroid Build Coastguard Worker if (name)
1221*5e7646d2SAndroid Build Coastguard Worker {
1222*5e7646d2SAndroid Build Coastguard Worker /*
1223*5e7646d2SAndroid Build Coastguard Worker * Resolve the given service instance name, regtype, and domain...
1224*5e7646d2SAndroid Build Coastguard Worker */
1225*5e7646d2SAndroid Build Coastguard Worker
1226*5e7646d2SAndroid Build Coastguard Worker if (!domain)
1227*5e7646d2SAndroid Build Coastguard Worker domain = "local.";
1228*5e7646d2SAndroid Build Coastguard Worker
1229*5e7646d2SAndroid Build Coastguard Worker service = get_service(services, name, regtype, domain);
1230*5e7646d2SAndroid Build Coastguard Worker
1231*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
1232*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "Resolving name=\"%s\", regtype=\"%s\", domain=\"%s\"\n", name, regtype, domain);
1233*5e7646d2SAndroid Build Coastguard Worker
1234*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1235*5e7646d2SAndroid Build Coastguard Worker service->ref = dnssd_ref;
1236*5e7646d2SAndroid Build Coastguard Worker err = DNSServiceResolve(&(service->ref),
1237*5e7646d2SAndroid Build Coastguard Worker kDNSServiceFlagsShareConnection, 0, name,
1238*5e7646d2SAndroid Build Coastguard Worker regtype, domain, resolve_callback,
1239*5e7646d2SAndroid Build Coastguard Worker service);
1240*5e7646d2SAndroid Build Coastguard Worker
1241*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
1242*5e7646d2SAndroid Build Coastguard Worker service->ref = avahi_service_resolver_new(avahi_client, AVAHI_IF_UNSPEC,
1243*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC, name,
1244*5e7646d2SAndroid Build Coastguard Worker regtype, domain,
1245*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC, 0,
1246*5e7646d2SAndroid Build Coastguard Worker resolve_callback, service);
1247*5e7646d2SAndroid Build Coastguard Worker if (service->ref)
1248*5e7646d2SAndroid Build Coastguard Worker err = 0;
1249*5e7646d2SAndroid Build Coastguard Worker else
1250*5e7646d2SAndroid Build Coastguard Worker err = avahi_client_errno(avahi_client);
1251*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1252*5e7646d2SAndroid Build Coastguard Worker }
1253*5e7646d2SAndroid Build Coastguard Worker else
1254*5e7646d2SAndroid Build Coastguard Worker {
1255*5e7646d2SAndroid Build Coastguard Worker /*
1256*5e7646d2SAndroid Build Coastguard Worker * Browse for services of the given type...
1257*5e7646d2SAndroid Build Coastguard Worker */
1258*5e7646d2SAndroid Build Coastguard Worker
1259*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
1260*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "Browsing for regtype=\"%s\", domain=\"%s\"\n", regtype, domain);
1261*5e7646d2SAndroid Build Coastguard Worker
1262*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1263*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef ref; /* Browse reference */
1264*5e7646d2SAndroid Build Coastguard Worker
1265*5e7646d2SAndroid Build Coastguard Worker ref = dnssd_ref;
1266*5e7646d2SAndroid Build Coastguard Worker err = DNSServiceBrowse(&ref, kDNSServiceFlagsShareConnection, 0, regtype,
1267*5e7646d2SAndroid Build Coastguard Worker domain, browse_callback, services);
1268*5e7646d2SAndroid Build Coastguard Worker
1269*5e7646d2SAndroid Build Coastguard Worker if (!err)
1270*5e7646d2SAndroid Build Coastguard Worker {
1271*5e7646d2SAndroid Build Coastguard Worker ref = dnssd_ref;
1272*5e7646d2SAndroid Build Coastguard Worker err = DNSServiceBrowse(&ref, kDNSServiceFlagsShareConnection,
1273*5e7646d2SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexLocalOnly, regtype,
1274*5e7646d2SAndroid Build Coastguard Worker domain, browse_local_callback, services);
1275*5e7646d2SAndroid Build Coastguard Worker }
1276*5e7646d2SAndroid Build Coastguard Worker
1277*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
1278*5e7646d2SAndroid Build Coastguard Worker char *subtype, /* Sub-type, if any */
1279*5e7646d2SAndroid Build Coastguard Worker subtype_buf[256]; /* Sub-type buffer */
1280*5e7646d2SAndroid Build Coastguard Worker
1281*5e7646d2SAndroid Build Coastguard Worker if ((subtype = strstr(regtype, ",_")) != NULL)
1282*5e7646d2SAndroid Build Coastguard Worker {
1283*5e7646d2SAndroid Build Coastguard Worker *subtype++ = '\0';
1284*5e7646d2SAndroid Build Coastguard Worker snprintf(subtype_buf, sizeof(subtype_buf), "%s._sub.%s", subtype, regtype);
1285*5e7646d2SAndroid Build Coastguard Worker regtype = subtype_buf;
1286*5e7646d2SAndroid Build Coastguard Worker }
1287*5e7646d2SAndroid Build Coastguard Worker
1288*5e7646d2SAndroid Build Coastguard Worker if (avahi_service_browser_new(avahi_client, AVAHI_IF_UNSPEC,
1289*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC, regtype, domain, 0,
1290*5e7646d2SAndroid Build Coastguard Worker browse_callback, services))
1291*5e7646d2SAndroid Build Coastguard Worker err = 0;
1292*5e7646d2SAndroid Build Coastguard Worker else
1293*5e7646d2SAndroid Build Coastguard Worker err = avahi_client_errno(avahi_client);
1294*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1295*5e7646d2SAndroid Build Coastguard Worker }
1296*5e7646d2SAndroid Build Coastguard Worker
1297*5e7646d2SAndroid Build Coastguard Worker if (err)
1298*5e7646d2SAndroid Build Coastguard Worker {
1299*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to browse or resolve: %s"),
1300*5e7646d2SAndroid Build Coastguard Worker dnssd_error_string(err));
1301*5e7646d2SAndroid Build Coastguard Worker
1302*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1303*5e7646d2SAndroid Build Coastguard Worker }
1304*5e7646d2SAndroid Build Coastguard Worker }
1305*5e7646d2SAndroid Build Coastguard Worker
1306*5e7646d2SAndroid Build Coastguard Worker /*
1307*5e7646d2SAndroid Build Coastguard Worker * Process browse/resolve requests...
1308*5e7646d2SAndroid Build Coastguard Worker */
1309*5e7646d2SAndroid Build Coastguard Worker
1310*5e7646d2SAndroid Build Coastguard Worker if (bonjour_timeout > 1.0)
1311*5e7646d2SAndroid Build Coastguard Worker endtime = get_time() + bonjour_timeout;
1312*5e7646d2SAndroid Build Coastguard Worker else
1313*5e7646d2SAndroid Build Coastguard Worker endtime = get_time() + 300.0;
1314*5e7646d2SAndroid Build Coastguard Worker
1315*5e7646d2SAndroid Build Coastguard Worker while (get_time() < endtime)
1316*5e7646d2SAndroid Build Coastguard Worker {
1317*5e7646d2SAndroid Build Coastguard Worker int process = 0; /* Process services? */
1318*5e7646d2SAndroid Build Coastguard Worker
1319*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1320*5e7646d2SAndroid Build Coastguard Worker int fd = DNSServiceRefSockFD(dnssd_ref);
1321*5e7646d2SAndroid Build Coastguard Worker /* File descriptor for DNS-SD */
1322*5e7646d2SAndroid Build Coastguard Worker
1323*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&sinput);
1324*5e7646d2SAndroid Build Coastguard Worker FD_SET(fd, &sinput);
1325*5e7646d2SAndroid Build Coastguard Worker
1326*5e7646d2SAndroid Build Coastguard Worker stimeout.tv_sec = 0;
1327*5e7646d2SAndroid Build Coastguard Worker stimeout.tv_usec = 500000;
1328*5e7646d2SAndroid Build Coastguard Worker
1329*5e7646d2SAndroid Build Coastguard Worker if (select(fd + 1, &sinput, NULL, NULL, &stimeout) < 0)
1330*5e7646d2SAndroid Build Coastguard Worker continue;
1331*5e7646d2SAndroid Build Coastguard Worker
1332*5e7646d2SAndroid Build Coastguard Worker if (FD_ISSET(fd, &sinput))
1333*5e7646d2SAndroid Build Coastguard Worker {
1334*5e7646d2SAndroid Build Coastguard Worker /*
1335*5e7646d2SAndroid Build Coastguard Worker * Process responses...
1336*5e7646d2SAndroid Build Coastguard Worker */
1337*5e7646d2SAndroid Build Coastguard Worker
1338*5e7646d2SAndroid Build Coastguard Worker DNSServiceProcessResult(dnssd_ref);
1339*5e7646d2SAndroid Build Coastguard Worker }
1340*5e7646d2SAndroid Build Coastguard Worker else
1341*5e7646d2SAndroid Build Coastguard Worker {
1342*5e7646d2SAndroid Build Coastguard Worker /*
1343*5e7646d2SAndroid Build Coastguard Worker * Time to process services...
1344*5e7646d2SAndroid Build Coastguard Worker */
1345*5e7646d2SAndroid Build Coastguard Worker
1346*5e7646d2SAndroid Build Coastguard Worker process = 1;
1347*5e7646d2SAndroid Build Coastguard Worker }
1348*5e7646d2SAndroid Build Coastguard Worker
1349*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
1350*5e7646d2SAndroid Build Coastguard Worker avahi_got_data = 0;
1351*5e7646d2SAndroid Build Coastguard Worker
1352*5e7646d2SAndroid Build Coastguard Worker if (avahi_simple_poll_iterate(avahi_poll, 500) > 0)
1353*5e7646d2SAndroid Build Coastguard Worker {
1354*5e7646d2SAndroid Build Coastguard Worker /*
1355*5e7646d2SAndroid Build Coastguard Worker * We've been told to exit the loop. Perhaps the connection to
1356*5e7646d2SAndroid Build Coastguard Worker * Avahi failed.
1357*5e7646d2SAndroid Build Coastguard Worker */
1358*5e7646d2SAndroid Build Coastguard Worker
1359*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1360*5e7646d2SAndroid Build Coastguard Worker }
1361*5e7646d2SAndroid Build Coastguard Worker
1362*5e7646d2SAndroid Build Coastguard Worker if (!avahi_got_data)
1363*5e7646d2SAndroid Build Coastguard Worker {
1364*5e7646d2SAndroid Build Coastguard Worker /*
1365*5e7646d2SAndroid Build Coastguard Worker * Time to process services...
1366*5e7646d2SAndroid Build Coastguard Worker */
1367*5e7646d2SAndroid Build Coastguard Worker
1368*5e7646d2SAndroid Build Coastguard Worker process = 1;
1369*5e7646d2SAndroid Build Coastguard Worker }
1370*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1371*5e7646d2SAndroid Build Coastguard Worker
1372*5e7646d2SAndroid Build Coastguard Worker if (process)
1373*5e7646d2SAndroid Build Coastguard Worker {
1374*5e7646d2SAndroid Build Coastguard Worker /*
1375*5e7646d2SAndroid Build Coastguard Worker * Process any services that we have found...
1376*5e7646d2SAndroid Build Coastguard Worker */
1377*5e7646d2SAndroid Build Coastguard Worker
1378*5e7646d2SAndroid Build Coastguard Worker int active = 0, /* Number of active resolves */
1379*5e7646d2SAndroid Build Coastguard Worker resolved = 0, /* Number of resolved services */
1380*5e7646d2SAndroid Build Coastguard Worker processed = 0; /* Number of processed services */
1381*5e7646d2SAndroid Build Coastguard Worker
1382*5e7646d2SAndroid Build Coastguard Worker for (service = (ippfind_srv_t *)cupsArrayFirst(services);
1383*5e7646d2SAndroid Build Coastguard Worker service;
1384*5e7646d2SAndroid Build Coastguard Worker service = (ippfind_srv_t *)cupsArrayNext(services))
1385*5e7646d2SAndroid Build Coastguard Worker {
1386*5e7646d2SAndroid Build Coastguard Worker if (service->is_processed)
1387*5e7646d2SAndroid Build Coastguard Worker processed ++;
1388*5e7646d2SAndroid Build Coastguard Worker
1389*5e7646d2SAndroid Build Coastguard Worker if (service->is_resolved)
1390*5e7646d2SAndroid Build Coastguard Worker resolved ++;
1391*5e7646d2SAndroid Build Coastguard Worker
1392*5e7646d2SAndroid Build Coastguard Worker if (!service->ref && !service->is_resolved)
1393*5e7646d2SAndroid Build Coastguard Worker {
1394*5e7646d2SAndroid Build Coastguard Worker /*
1395*5e7646d2SAndroid Build Coastguard Worker * Found a service, now resolve it (but limit to 50 active resolves...)
1396*5e7646d2SAndroid Build Coastguard Worker */
1397*5e7646d2SAndroid Build Coastguard Worker
1398*5e7646d2SAndroid Build Coastguard Worker if (active < 50)
1399*5e7646d2SAndroid Build Coastguard Worker {
1400*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1401*5e7646d2SAndroid Build Coastguard Worker service->ref = dnssd_ref;
1402*5e7646d2SAndroid Build Coastguard Worker err = DNSServiceResolve(&(service->ref),
1403*5e7646d2SAndroid Build Coastguard Worker kDNSServiceFlagsShareConnection, 0,
1404*5e7646d2SAndroid Build Coastguard Worker service->name, service->regtype,
1405*5e7646d2SAndroid Build Coastguard Worker service->domain, resolve_callback,
1406*5e7646d2SAndroid Build Coastguard Worker service);
1407*5e7646d2SAndroid Build Coastguard Worker
1408*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
1409*5e7646d2SAndroid Build Coastguard Worker service->ref = avahi_service_resolver_new(avahi_client,
1410*5e7646d2SAndroid Build Coastguard Worker AVAHI_IF_UNSPEC,
1411*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC,
1412*5e7646d2SAndroid Build Coastguard Worker service->name,
1413*5e7646d2SAndroid Build Coastguard Worker service->regtype,
1414*5e7646d2SAndroid Build Coastguard Worker service->domain,
1415*5e7646d2SAndroid Build Coastguard Worker AVAHI_PROTO_UNSPEC, 0,
1416*5e7646d2SAndroid Build Coastguard Worker resolve_callback,
1417*5e7646d2SAndroid Build Coastguard Worker service);
1418*5e7646d2SAndroid Build Coastguard Worker if (service->ref)
1419*5e7646d2SAndroid Build Coastguard Worker err = 0;
1420*5e7646d2SAndroid Build Coastguard Worker else
1421*5e7646d2SAndroid Build Coastguard Worker err = avahi_client_errno(avahi_client);
1422*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1423*5e7646d2SAndroid Build Coastguard Worker
1424*5e7646d2SAndroid Build Coastguard Worker if (err)
1425*5e7646d2SAndroid Build Coastguard Worker {
1426*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
1427*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Unable to browse or resolve: %s"),
1428*5e7646d2SAndroid Build Coastguard Worker dnssd_error_string(err));
1429*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1430*5e7646d2SAndroid Build Coastguard Worker }
1431*5e7646d2SAndroid Build Coastguard Worker
1432*5e7646d2SAndroid Build Coastguard Worker active ++;
1433*5e7646d2SAndroid Build Coastguard Worker }
1434*5e7646d2SAndroid Build Coastguard Worker }
1435*5e7646d2SAndroid Build Coastguard Worker else if (service->is_resolved && !service->is_processed)
1436*5e7646d2SAndroid Build Coastguard Worker {
1437*5e7646d2SAndroid Build Coastguard Worker /*
1438*5e7646d2SAndroid Build Coastguard Worker * Resolved, not process this service against the expressions...
1439*5e7646d2SAndroid Build Coastguard Worker */
1440*5e7646d2SAndroid Build Coastguard Worker
1441*5e7646d2SAndroid Build Coastguard Worker if (service->ref)
1442*5e7646d2SAndroid Build Coastguard Worker {
1443*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1444*5e7646d2SAndroid Build Coastguard Worker DNSServiceRefDeallocate(service->ref);
1445*5e7646d2SAndroid Build Coastguard Worker #else
1446*5e7646d2SAndroid Build Coastguard Worker avahi_service_resolver_free(service->ref);
1447*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1448*5e7646d2SAndroid Build Coastguard Worker
1449*5e7646d2SAndroid Build Coastguard Worker service->ref = NULL;
1450*5e7646d2SAndroid Build Coastguard Worker }
1451*5e7646d2SAndroid Build Coastguard Worker
1452*5e7646d2SAndroid Build Coastguard Worker if (eval_expr(service, expressions))
1453*5e7646d2SAndroid Build Coastguard Worker status = IPPFIND_EXIT_TRUE;
1454*5e7646d2SAndroid Build Coastguard Worker
1455*5e7646d2SAndroid Build Coastguard Worker service->is_processed = 1;
1456*5e7646d2SAndroid Build Coastguard Worker }
1457*5e7646d2SAndroid Build Coastguard Worker else if (service->ref)
1458*5e7646d2SAndroid Build Coastguard Worker active ++;
1459*5e7646d2SAndroid Build Coastguard Worker }
1460*5e7646d2SAndroid Build Coastguard Worker
1461*5e7646d2SAndroid Build Coastguard Worker /*
1462*5e7646d2SAndroid Build Coastguard Worker * If we have processed all services we have discovered, then we are done.
1463*5e7646d2SAndroid Build Coastguard Worker */
1464*5e7646d2SAndroid Build Coastguard Worker
1465*5e7646d2SAndroid Build Coastguard Worker if (processed == cupsArrayCount(services) && bonjour_timeout <= 1.0)
1466*5e7646d2SAndroid Build Coastguard Worker break;
1467*5e7646d2SAndroid Build Coastguard Worker }
1468*5e7646d2SAndroid Build Coastguard Worker }
1469*5e7646d2SAndroid Build Coastguard Worker
1470*5e7646d2SAndroid Build Coastguard Worker if (bonjour_error)
1471*5e7646d2SAndroid Build Coastguard Worker return (IPPFIND_EXIT_BONJOUR);
1472*5e7646d2SAndroid Build Coastguard Worker else
1473*5e7646d2SAndroid Build Coastguard Worker return (status);
1474*5e7646d2SAndroid Build Coastguard Worker }
1475*5e7646d2SAndroid Build Coastguard Worker
1476*5e7646d2SAndroid Build Coastguard Worker
1477*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
1478*5e7646d2SAndroid Build Coastguard Worker /*
1479*5e7646d2SAndroid Build Coastguard Worker * 'browse_callback()' - Browse devices.
1480*5e7646d2SAndroid Build Coastguard Worker */
1481*5e7646d2SAndroid Build Coastguard Worker
1482*5e7646d2SAndroid Build Coastguard Worker static void DNSSD_API
browse_callback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regtype,const char * replyDomain,void * context)1483*5e7646d2SAndroid Build Coastguard Worker browse_callback(
1484*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef sdRef, /* I - Service reference */
1485*5e7646d2SAndroid Build Coastguard Worker DNSServiceFlags flags, /* I - Option flags */
1486*5e7646d2SAndroid Build Coastguard Worker uint32_t interfaceIndex, /* I - Interface number */
1487*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType errorCode, /* I - Error, if any */
1488*5e7646d2SAndroid Build Coastguard Worker const char *serviceName, /* I - Name of service/device */
1489*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Type of service */
1490*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain, /* I - Service domain */
1491*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Services array */
1492*5e7646d2SAndroid Build Coastguard Worker {
1493*5e7646d2SAndroid Build Coastguard Worker /*
1494*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
1495*5e7646d2SAndroid Build Coastguard Worker */
1496*5e7646d2SAndroid Build Coastguard Worker
1497*5e7646d2SAndroid Build Coastguard Worker (void)sdRef;
1498*5e7646d2SAndroid Build Coastguard Worker (void)interfaceIndex;
1499*5e7646d2SAndroid Build Coastguard Worker
1500*5e7646d2SAndroid Build Coastguard Worker if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
1501*5e7646d2SAndroid Build Coastguard Worker return;
1502*5e7646d2SAndroid Build Coastguard Worker
1503*5e7646d2SAndroid Build Coastguard Worker /*
1504*5e7646d2SAndroid Build Coastguard Worker * Get the device...
1505*5e7646d2SAndroid Build Coastguard Worker */
1506*5e7646d2SAndroid Build Coastguard Worker
1507*5e7646d2SAndroid Build Coastguard Worker get_service((cups_array_t *)context, serviceName, regtype, replyDomain);
1508*5e7646d2SAndroid Build Coastguard Worker }
1509*5e7646d2SAndroid Build Coastguard Worker
1510*5e7646d2SAndroid Build Coastguard Worker
1511*5e7646d2SAndroid Build Coastguard Worker /*
1512*5e7646d2SAndroid Build Coastguard Worker * 'browse_local_callback()' - Browse local devices.
1513*5e7646d2SAndroid Build Coastguard Worker */
1514*5e7646d2SAndroid Build Coastguard Worker
1515*5e7646d2SAndroid Build Coastguard Worker static void DNSSD_API
browse_local_callback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regtype,const char * replyDomain,void * context)1516*5e7646d2SAndroid Build Coastguard Worker browse_local_callback(
1517*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef sdRef, /* I - Service reference */
1518*5e7646d2SAndroid Build Coastguard Worker DNSServiceFlags flags, /* I - Option flags */
1519*5e7646d2SAndroid Build Coastguard Worker uint32_t interfaceIndex, /* I - Interface number */
1520*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType errorCode, /* I - Error, if any */
1521*5e7646d2SAndroid Build Coastguard Worker const char *serviceName, /* I - Name of service/device */
1522*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Type of service */
1523*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain, /* I - Service domain */
1524*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Services array */
1525*5e7646d2SAndroid Build Coastguard Worker {
1526*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t *service; /* Service */
1527*5e7646d2SAndroid Build Coastguard Worker
1528*5e7646d2SAndroid Build Coastguard Worker
1529*5e7646d2SAndroid Build Coastguard Worker /*
1530*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
1531*5e7646d2SAndroid Build Coastguard Worker */
1532*5e7646d2SAndroid Build Coastguard Worker
1533*5e7646d2SAndroid Build Coastguard Worker (void)sdRef;
1534*5e7646d2SAndroid Build Coastguard Worker (void)interfaceIndex;
1535*5e7646d2SAndroid Build Coastguard Worker
1536*5e7646d2SAndroid Build Coastguard Worker if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
1537*5e7646d2SAndroid Build Coastguard Worker return;
1538*5e7646d2SAndroid Build Coastguard Worker
1539*5e7646d2SAndroid Build Coastguard Worker /*
1540*5e7646d2SAndroid Build Coastguard Worker * Get the device...
1541*5e7646d2SAndroid Build Coastguard Worker */
1542*5e7646d2SAndroid Build Coastguard Worker
1543*5e7646d2SAndroid Build Coastguard Worker service = get_service((cups_array_t *)context, serviceName, regtype,
1544*5e7646d2SAndroid Build Coastguard Worker replyDomain);
1545*5e7646d2SAndroid Build Coastguard Worker service->is_local = 1;
1546*5e7646d2SAndroid Build Coastguard Worker }
1547*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
1548*5e7646d2SAndroid Build Coastguard Worker
1549*5e7646d2SAndroid Build Coastguard Worker
1550*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
1551*5e7646d2SAndroid Build Coastguard Worker /*
1552*5e7646d2SAndroid Build Coastguard Worker * 'browse_callback()' - Browse devices.
1553*5e7646d2SAndroid Build Coastguard Worker */
1554*5e7646d2SAndroid Build Coastguard Worker
1555*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)1556*5e7646d2SAndroid Build Coastguard Worker browse_callback(
1557*5e7646d2SAndroid Build Coastguard Worker AvahiServiceBrowser *browser, /* I - Browser */
1558*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface, /* I - Interface index (unused) */
1559*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol, /* I - Network protocol (unused) */
1560*5e7646d2SAndroid Build Coastguard Worker AvahiBrowserEvent event, /* I - What happened */
1561*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Service name */
1562*5e7646d2SAndroid Build Coastguard Worker const char *type, /* I - Registration type */
1563*5e7646d2SAndroid Build Coastguard Worker const char *domain, /* I - Domain */
1564*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags, /* I - Flags */
1565*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Services array */
1566*5e7646d2SAndroid Build Coastguard Worker {
1567*5e7646d2SAndroid Build Coastguard Worker AvahiClient *client = avahi_service_browser_get_client(browser);
1568*5e7646d2SAndroid Build Coastguard Worker /* Client information */
1569*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t *service; /* Service information */
1570*5e7646d2SAndroid Build Coastguard Worker
1571*5e7646d2SAndroid Build Coastguard Worker
1572*5e7646d2SAndroid Build Coastguard Worker (void)interface;
1573*5e7646d2SAndroid Build Coastguard Worker (void)protocol;
1574*5e7646d2SAndroid Build Coastguard Worker (void)context;
1575*5e7646d2SAndroid Build Coastguard Worker
1576*5e7646d2SAndroid Build Coastguard Worker switch (event)
1577*5e7646d2SAndroid Build Coastguard Worker {
1578*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_FAILURE:
1579*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: browse_callback: %s\n",
1580*5e7646d2SAndroid Build Coastguard Worker avahi_strerror(avahi_client_errno(client)));
1581*5e7646d2SAndroid Build Coastguard Worker bonjour_error = 1;
1582*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_quit(avahi_poll);
1583*5e7646d2SAndroid Build Coastguard Worker break;
1584*5e7646d2SAndroid Build Coastguard Worker
1585*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_NEW:
1586*5e7646d2SAndroid Build Coastguard Worker /*
1587*5e7646d2SAndroid Build Coastguard Worker * This object is new on the network. Create a device entry for it if
1588*5e7646d2SAndroid Build Coastguard Worker * it doesn't yet exist.
1589*5e7646d2SAndroid Build Coastguard Worker */
1590*5e7646d2SAndroid Build Coastguard Worker
1591*5e7646d2SAndroid Build Coastguard Worker service = get_service((cups_array_t *)context, name, type, domain);
1592*5e7646d2SAndroid Build Coastguard Worker
1593*5e7646d2SAndroid Build Coastguard Worker if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
1594*5e7646d2SAndroid Build Coastguard Worker service->is_local = 1;
1595*5e7646d2SAndroid Build Coastguard Worker break;
1596*5e7646d2SAndroid Build Coastguard Worker
1597*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_REMOVE:
1598*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_ALL_FOR_NOW:
1599*5e7646d2SAndroid Build Coastguard Worker case AVAHI_BROWSER_CACHE_EXHAUSTED:
1600*5e7646d2SAndroid Build Coastguard Worker break;
1601*5e7646d2SAndroid Build Coastguard Worker }
1602*5e7646d2SAndroid Build Coastguard Worker }
1603*5e7646d2SAndroid Build Coastguard Worker
1604*5e7646d2SAndroid Build Coastguard Worker
1605*5e7646d2SAndroid Build Coastguard Worker /*
1606*5e7646d2SAndroid Build Coastguard Worker * 'client_callback()' - Avahi client callback function.
1607*5e7646d2SAndroid Build Coastguard Worker */
1608*5e7646d2SAndroid Build Coastguard Worker
1609*5e7646d2SAndroid Build Coastguard Worker static void
client_callback(AvahiClient * client,AvahiClientState state,void * context)1610*5e7646d2SAndroid Build Coastguard Worker client_callback(
1611*5e7646d2SAndroid Build Coastguard Worker AvahiClient *client, /* I - Client information (unused) */
1612*5e7646d2SAndroid Build Coastguard Worker AvahiClientState state, /* I - Current state */
1613*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - User data (unused) */
1614*5e7646d2SAndroid Build Coastguard Worker {
1615*5e7646d2SAndroid Build Coastguard Worker (void)client;
1616*5e7646d2SAndroid Build Coastguard Worker (void)context;
1617*5e7646d2SAndroid Build Coastguard Worker
1618*5e7646d2SAndroid Build Coastguard Worker /*
1619*5e7646d2SAndroid Build Coastguard Worker * If the connection drops, quit.
1620*5e7646d2SAndroid Build Coastguard Worker */
1621*5e7646d2SAndroid Build Coastguard Worker
1622*5e7646d2SAndroid Build Coastguard Worker if (state == AVAHI_CLIENT_FAILURE)
1623*5e7646d2SAndroid Build Coastguard Worker {
1624*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Avahi connection failed.\n", stderr);
1625*5e7646d2SAndroid Build Coastguard Worker bonjour_error = 1;
1626*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_quit(avahi_poll);
1627*5e7646d2SAndroid Build Coastguard Worker }
1628*5e7646d2SAndroid Build Coastguard Worker }
1629*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
1630*5e7646d2SAndroid Build Coastguard Worker
1631*5e7646d2SAndroid Build Coastguard Worker
1632*5e7646d2SAndroid Build Coastguard Worker /*
1633*5e7646d2SAndroid Build Coastguard Worker * 'compare_services()' - Compare two devices.
1634*5e7646d2SAndroid Build Coastguard Worker */
1635*5e7646d2SAndroid Build Coastguard Worker
1636*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
compare_services(ippfind_srv_t * a,ippfind_srv_t * b)1637*5e7646d2SAndroid Build Coastguard Worker compare_services(ippfind_srv_t *a, /* I - First device */
1638*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t *b) /* I - Second device */
1639*5e7646d2SAndroid Build Coastguard Worker {
1640*5e7646d2SAndroid Build Coastguard Worker return (strcmp(a->name, b->name));
1641*5e7646d2SAndroid Build Coastguard Worker }
1642*5e7646d2SAndroid Build Coastguard Worker
1643*5e7646d2SAndroid Build Coastguard Worker
1644*5e7646d2SAndroid Build Coastguard Worker /*
1645*5e7646d2SAndroid Build Coastguard Worker * 'dnssd_error_string()' - Return an error string for an error code.
1646*5e7646d2SAndroid Build Coastguard Worker */
1647*5e7646d2SAndroid Build Coastguard Worker
1648*5e7646d2SAndroid Build Coastguard Worker static const char * /* O - Error message */
dnssd_error_string(int error)1649*5e7646d2SAndroid Build Coastguard Worker dnssd_error_string(int error) /* I - Error number */
1650*5e7646d2SAndroid Build Coastguard Worker {
1651*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_DNSSD
1652*5e7646d2SAndroid Build Coastguard Worker switch (error)
1653*5e7646d2SAndroid Build Coastguard Worker {
1654*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoError :
1655*5e7646d2SAndroid Build Coastguard Worker return ("OK.");
1656*5e7646d2SAndroid Build Coastguard Worker
1657*5e7646d2SAndroid Build Coastguard Worker default :
1658*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Unknown :
1659*5e7646d2SAndroid Build Coastguard Worker return ("Unknown error.");
1660*5e7646d2SAndroid Build Coastguard Worker
1661*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchName :
1662*5e7646d2SAndroid Build Coastguard Worker return ("Service not found.");
1663*5e7646d2SAndroid Build Coastguard Worker
1664*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoMemory :
1665*5e7646d2SAndroid Build Coastguard Worker return ("Out of memory.");
1666*5e7646d2SAndroid Build Coastguard Worker
1667*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadParam :
1668*5e7646d2SAndroid Build Coastguard Worker return ("Bad parameter.");
1669*5e7646d2SAndroid Build Coastguard Worker
1670*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadReference :
1671*5e7646d2SAndroid Build Coastguard Worker return ("Bad service reference.");
1672*5e7646d2SAndroid Build Coastguard Worker
1673*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadState :
1674*5e7646d2SAndroid Build Coastguard Worker return ("Bad state.");
1675*5e7646d2SAndroid Build Coastguard Worker
1676*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadFlags :
1677*5e7646d2SAndroid Build Coastguard Worker return ("Bad flags.");
1678*5e7646d2SAndroid Build Coastguard Worker
1679*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Unsupported :
1680*5e7646d2SAndroid Build Coastguard Worker return ("Unsupported.");
1681*5e7646d2SAndroid Build Coastguard Worker
1682*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NotInitialized :
1683*5e7646d2SAndroid Build Coastguard Worker return ("Not initialized.");
1684*5e7646d2SAndroid Build Coastguard Worker
1685*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_AlreadyRegistered :
1686*5e7646d2SAndroid Build Coastguard Worker return ("Already registered.");
1687*5e7646d2SAndroid Build Coastguard Worker
1688*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NameConflict :
1689*5e7646d2SAndroid Build Coastguard Worker return ("Name conflict.");
1690*5e7646d2SAndroid Build Coastguard Worker
1691*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Invalid :
1692*5e7646d2SAndroid Build Coastguard Worker return ("Invalid name.");
1693*5e7646d2SAndroid Build Coastguard Worker
1694*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Firewall :
1695*5e7646d2SAndroid Build Coastguard Worker return ("Firewall prevents registration.");
1696*5e7646d2SAndroid Build Coastguard Worker
1697*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Incompatible :
1698*5e7646d2SAndroid Build Coastguard Worker return ("Client library incompatible.");
1699*5e7646d2SAndroid Build Coastguard Worker
1700*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadInterfaceIndex :
1701*5e7646d2SAndroid Build Coastguard Worker return ("Bad interface index.");
1702*5e7646d2SAndroid Build Coastguard Worker
1703*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Refused :
1704*5e7646d2SAndroid Build Coastguard Worker return ("Server prevents registration.");
1705*5e7646d2SAndroid Build Coastguard Worker
1706*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchRecord :
1707*5e7646d2SAndroid Build Coastguard Worker return ("Record not found.");
1708*5e7646d2SAndroid Build Coastguard Worker
1709*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoAuth :
1710*5e7646d2SAndroid Build Coastguard Worker return ("Authentication required.");
1711*5e7646d2SAndroid Build Coastguard Worker
1712*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchKey :
1713*5e7646d2SAndroid Build Coastguard Worker return ("Encryption key not found.");
1714*5e7646d2SAndroid Build Coastguard Worker
1715*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NATTraversal :
1716*5e7646d2SAndroid Build Coastguard Worker return ("Unable to traverse NAT boundary.");
1717*5e7646d2SAndroid Build Coastguard Worker
1718*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_DoubleNAT :
1719*5e7646d2SAndroid Build Coastguard Worker return ("Unable to traverse double-NAT boundary.");
1720*5e7646d2SAndroid Build Coastguard Worker
1721*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadTime :
1722*5e7646d2SAndroid Build Coastguard Worker return ("Bad system time.");
1723*5e7646d2SAndroid Build Coastguard Worker
1724*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadSig :
1725*5e7646d2SAndroid Build Coastguard Worker return ("Bad signature.");
1726*5e7646d2SAndroid Build Coastguard Worker
1727*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_BadKey :
1728*5e7646d2SAndroid Build Coastguard Worker return ("Bad encryption key.");
1729*5e7646d2SAndroid Build Coastguard Worker
1730*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Transient :
1731*5e7646d2SAndroid Build Coastguard Worker return ("Transient error occurred - please try again.");
1732*5e7646d2SAndroid Build Coastguard Worker
1733*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_ServiceNotRunning :
1734*5e7646d2SAndroid Build Coastguard Worker return ("Server not running.");
1735*5e7646d2SAndroid Build Coastguard Worker
1736*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NATPortMappingUnsupported :
1737*5e7646d2SAndroid Build Coastguard Worker return ("NAT doesn't support NAT-PMP or UPnP.");
1738*5e7646d2SAndroid Build Coastguard Worker
1739*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NATPortMappingDisabled :
1740*5e7646d2SAndroid Build Coastguard Worker return ("NAT supports NAT-PNP or UPnP but it is disabled.");
1741*5e7646d2SAndroid Build Coastguard Worker
1742*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_NoRouter :
1743*5e7646d2SAndroid Build Coastguard Worker return ("No Internet/default router configured.");
1744*5e7646d2SAndroid Build Coastguard Worker
1745*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_PollingMode :
1746*5e7646d2SAndroid Build Coastguard Worker return ("Service polling mode error.");
1747*5e7646d2SAndroid Build Coastguard Worker
1748*5e7646d2SAndroid Build Coastguard Worker #ifndef _WIN32
1749*5e7646d2SAndroid Build Coastguard Worker case kDNSServiceErr_Timeout :
1750*5e7646d2SAndroid Build Coastguard Worker return ("Service timeout.");
1751*5e7646d2SAndroid Build Coastguard Worker #endif /* !_WIN32 */
1752*5e7646d2SAndroid Build Coastguard Worker }
1753*5e7646d2SAndroid Build Coastguard Worker
1754*5e7646d2SAndroid Build Coastguard Worker # elif defined(HAVE_AVAHI)
1755*5e7646d2SAndroid Build Coastguard Worker return (avahi_strerror(error));
1756*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_DNSSD */
1757*5e7646d2SAndroid Build Coastguard Worker }
1758*5e7646d2SAndroid Build Coastguard Worker
1759*5e7646d2SAndroid Build Coastguard Worker
1760*5e7646d2SAndroid Build Coastguard Worker /*
1761*5e7646d2SAndroid Build Coastguard Worker * 'eval_expr()' - Evaluate the expressions against the specified service.
1762*5e7646d2SAndroid Build Coastguard Worker *
1763*5e7646d2SAndroid Build Coastguard Worker * Returns 1 for true and 0 for false.
1764*5e7646d2SAndroid Build Coastguard Worker */
1765*5e7646d2SAndroid Build Coastguard Worker
1766*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of evaluation */
eval_expr(ippfind_srv_t * service,ippfind_expr_t * expressions)1767*5e7646d2SAndroid Build Coastguard Worker eval_expr(ippfind_srv_t *service, /* I - Service */
1768*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *expressions) /* I - Expressions */
1769*5e7646d2SAndroid Build Coastguard Worker {
1770*5e7646d2SAndroid Build Coastguard Worker ippfind_op_t logic; /* Logical operation */
1771*5e7646d2SAndroid Build Coastguard Worker int result; /* Result of current expression */
1772*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *expression; /* Current expression */
1773*5e7646d2SAndroid Build Coastguard Worker const char *val; /* TXT value */
1774*5e7646d2SAndroid Build Coastguard Worker
1775*5e7646d2SAndroid Build Coastguard Worker /*
1776*5e7646d2SAndroid Build Coastguard Worker * Loop through the expressions...
1777*5e7646d2SAndroid Build Coastguard Worker */
1778*5e7646d2SAndroid Build Coastguard Worker
1779*5e7646d2SAndroid Build Coastguard Worker if (expressions && expressions->parent)
1780*5e7646d2SAndroid Build Coastguard Worker logic = expressions->parent->op;
1781*5e7646d2SAndroid Build Coastguard Worker else
1782*5e7646d2SAndroid Build Coastguard Worker logic = IPPFIND_OP_AND;
1783*5e7646d2SAndroid Build Coastguard Worker
1784*5e7646d2SAndroid Build Coastguard Worker for (expression = expressions; expression; expression = expression->next)
1785*5e7646d2SAndroid Build Coastguard Worker {
1786*5e7646d2SAndroid Build Coastguard Worker switch (expression->op)
1787*5e7646d2SAndroid Build Coastguard Worker {
1788*5e7646d2SAndroid Build Coastguard Worker default :
1789*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_AND :
1790*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_OR :
1791*5e7646d2SAndroid Build Coastguard Worker if (expression->child)
1792*5e7646d2SAndroid Build Coastguard Worker result = eval_expr(service, expression->child);
1793*5e7646d2SAndroid Build Coastguard Worker else
1794*5e7646d2SAndroid Build Coastguard Worker result = expression->op == IPPFIND_OP_AND;
1795*5e7646d2SAndroid Build Coastguard Worker break;
1796*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_TRUE :
1797*5e7646d2SAndroid Build Coastguard Worker result = 1;
1798*5e7646d2SAndroid Build Coastguard Worker break;
1799*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_FALSE :
1800*5e7646d2SAndroid Build Coastguard Worker result = 0;
1801*5e7646d2SAndroid Build Coastguard Worker break;
1802*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_IS_LOCAL :
1803*5e7646d2SAndroid Build Coastguard Worker result = service->is_local;
1804*5e7646d2SAndroid Build Coastguard Worker break;
1805*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_IS_REMOTE :
1806*5e7646d2SAndroid Build Coastguard Worker result = !service->is_local;
1807*5e7646d2SAndroid Build Coastguard Worker break;
1808*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_DOMAIN_REGEX :
1809*5e7646d2SAndroid Build Coastguard Worker result = !regexec(&(expression->re), service->domain, 0, NULL, 0);
1810*5e7646d2SAndroid Build Coastguard Worker break;
1811*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_NAME_REGEX :
1812*5e7646d2SAndroid Build Coastguard Worker result = !regexec(&(expression->re), service->name, 0, NULL, 0);
1813*5e7646d2SAndroid Build Coastguard Worker break;
1814*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_NAME_LITERAL :
1815*5e7646d2SAndroid Build Coastguard Worker result = !_cups_strcasecmp(expression->name, service->name);
1816*5e7646d2SAndroid Build Coastguard Worker break;
1817*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_HOST_REGEX :
1818*5e7646d2SAndroid Build Coastguard Worker result = !regexec(&(expression->re), service->host, 0, NULL, 0);
1819*5e7646d2SAndroid Build Coastguard Worker break;
1820*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_PORT_RANGE :
1821*5e7646d2SAndroid Build Coastguard Worker result = service->port >= expression->range[0] &&
1822*5e7646d2SAndroid Build Coastguard Worker service->port <= expression->range[1];
1823*5e7646d2SAndroid Build Coastguard Worker break;
1824*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_PATH_REGEX :
1825*5e7646d2SAndroid Build Coastguard Worker result = !regexec(&(expression->re), service->resource, 0, NULL, 0);
1826*5e7646d2SAndroid Build Coastguard Worker break;
1827*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_TXT_EXISTS :
1828*5e7646d2SAndroid Build Coastguard Worker result = cupsGetOption(expression->name, service->num_txt,
1829*5e7646d2SAndroid Build Coastguard Worker service->txt) != NULL;
1830*5e7646d2SAndroid Build Coastguard Worker break;
1831*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_TXT_REGEX :
1832*5e7646d2SAndroid Build Coastguard Worker val = cupsGetOption(expression->name, service->num_txt,
1833*5e7646d2SAndroid Build Coastguard Worker service->txt);
1834*5e7646d2SAndroid Build Coastguard Worker if (val)
1835*5e7646d2SAndroid Build Coastguard Worker result = !regexec(&(expression->re), val, 0, NULL, 0);
1836*5e7646d2SAndroid Build Coastguard Worker else
1837*5e7646d2SAndroid Build Coastguard Worker result = 0;
1838*5e7646d2SAndroid Build Coastguard Worker
1839*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
1840*5e7646d2SAndroid Build Coastguard Worker printf("TXT_REGEX of \"%s\": %d\n", val, result);
1841*5e7646d2SAndroid Build Coastguard Worker break;
1842*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_URI_REGEX :
1843*5e7646d2SAndroid Build Coastguard Worker result = !regexec(&(expression->re), service->uri, 0, NULL, 0);
1844*5e7646d2SAndroid Build Coastguard Worker break;
1845*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_EXEC :
1846*5e7646d2SAndroid Build Coastguard Worker result = exec_program(service, expression->num_args,
1847*5e7646d2SAndroid Build Coastguard Worker expression->args);
1848*5e7646d2SAndroid Build Coastguard Worker break;
1849*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_LIST :
1850*5e7646d2SAndroid Build Coastguard Worker result = list_service(service);
1851*5e7646d2SAndroid Build Coastguard Worker break;
1852*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_PRINT_NAME :
1853*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stdout, service->name);
1854*5e7646d2SAndroid Build Coastguard Worker result = 1;
1855*5e7646d2SAndroid Build Coastguard Worker break;
1856*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_PRINT_URI :
1857*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stdout, service->uri);
1858*5e7646d2SAndroid Build Coastguard Worker result = 1;
1859*5e7646d2SAndroid Build Coastguard Worker break;
1860*5e7646d2SAndroid Build Coastguard Worker case IPPFIND_OP_QUIET :
1861*5e7646d2SAndroid Build Coastguard Worker result = 1;
1862*5e7646d2SAndroid Build Coastguard Worker break;
1863*5e7646d2SAndroid Build Coastguard Worker }
1864*5e7646d2SAndroid Build Coastguard Worker
1865*5e7646d2SAndroid Build Coastguard Worker if (expression->invert)
1866*5e7646d2SAndroid Build Coastguard Worker result = !result;
1867*5e7646d2SAndroid Build Coastguard Worker
1868*5e7646d2SAndroid Build Coastguard Worker if (logic == IPPFIND_OP_AND && !result)
1869*5e7646d2SAndroid Build Coastguard Worker return (0);
1870*5e7646d2SAndroid Build Coastguard Worker else if (logic == IPPFIND_OP_OR && result)
1871*5e7646d2SAndroid Build Coastguard Worker return (1);
1872*5e7646d2SAndroid Build Coastguard Worker }
1873*5e7646d2SAndroid Build Coastguard Worker
1874*5e7646d2SAndroid Build Coastguard Worker return (logic == IPPFIND_OP_AND);
1875*5e7646d2SAndroid Build Coastguard Worker }
1876*5e7646d2SAndroid Build Coastguard Worker
1877*5e7646d2SAndroid Build Coastguard Worker
1878*5e7646d2SAndroid Build Coastguard Worker /*
1879*5e7646d2SAndroid Build Coastguard Worker * 'exec_program()' - Execute a program for a service.
1880*5e7646d2SAndroid Build Coastguard Worker */
1881*5e7646d2SAndroid Build Coastguard Worker
1882*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 if program terminated
1883*5e7646d2SAndroid Build Coastguard Worker successfully, 0 otherwise. */
exec_program(ippfind_srv_t * service,int num_args,char ** args)1884*5e7646d2SAndroid Build Coastguard Worker exec_program(ippfind_srv_t *service, /* I - Service */
1885*5e7646d2SAndroid Build Coastguard Worker int num_args, /* I - Number of command-line args */
1886*5e7646d2SAndroid Build Coastguard Worker char **args) /* I - Command-line arguments */
1887*5e7646d2SAndroid Build Coastguard Worker {
1888*5e7646d2SAndroid Build Coastguard Worker char **myargv, /* Command-line arguments */
1889*5e7646d2SAndroid Build Coastguard Worker **myenvp, /* Environment variables */
1890*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into variable */
1891*5e7646d2SAndroid Build Coastguard Worker domain[1024], /* IPPFIND_SERVICE_DOMAIN */
1892*5e7646d2SAndroid Build Coastguard Worker hostname[1024], /* IPPFIND_SERVICE_HOSTNAME */
1893*5e7646d2SAndroid Build Coastguard Worker name[256], /* IPPFIND_SERVICE_NAME */
1894*5e7646d2SAndroid Build Coastguard Worker port[32], /* IPPFIND_SERVICE_PORT */
1895*5e7646d2SAndroid Build Coastguard Worker regtype[256], /* IPPFIND_SERVICE_REGTYPE */
1896*5e7646d2SAndroid Build Coastguard Worker scheme[128], /* IPPFIND_SERVICE_SCHEME */
1897*5e7646d2SAndroid Build Coastguard Worker uri[1024], /* IPPFIND_SERVICE_URI */
1898*5e7646d2SAndroid Build Coastguard Worker txt[100][256]; /* IPPFIND_TXT_foo */
1899*5e7646d2SAndroid Build Coastguard Worker int i, /* Looping var */
1900*5e7646d2SAndroid Build Coastguard Worker myenvc, /* Number of environment variables */
1901*5e7646d2SAndroid Build Coastguard Worker status; /* Exit status of program */
1902*5e7646d2SAndroid Build Coastguard Worker #ifndef _WIN32
1903*5e7646d2SAndroid Build Coastguard Worker char program[1024]; /* Program to execute */
1904*5e7646d2SAndroid Build Coastguard Worker int pid; /* Process ID */
1905*5e7646d2SAndroid Build Coastguard Worker #endif /* !_WIN32 */
1906*5e7646d2SAndroid Build Coastguard Worker
1907*5e7646d2SAndroid Build Coastguard Worker
1908*5e7646d2SAndroid Build Coastguard Worker /*
1909*5e7646d2SAndroid Build Coastguard Worker * Environment variables...
1910*5e7646d2SAndroid Build Coastguard Worker */
1911*5e7646d2SAndroid Build Coastguard Worker
1912*5e7646d2SAndroid Build Coastguard Worker snprintf(domain, sizeof(domain), "IPPFIND_SERVICE_DOMAIN=%s",
1913*5e7646d2SAndroid Build Coastguard Worker service->domain);
1914*5e7646d2SAndroid Build Coastguard Worker snprintf(hostname, sizeof(hostname), "IPPFIND_SERVICE_HOSTNAME=%s",
1915*5e7646d2SAndroid Build Coastguard Worker service->host);
1916*5e7646d2SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "IPPFIND_SERVICE_NAME=%s", service->name);
1917*5e7646d2SAndroid Build Coastguard Worker snprintf(port, sizeof(port), "IPPFIND_SERVICE_PORT=%d", service->port);
1918*5e7646d2SAndroid Build Coastguard Worker snprintf(regtype, sizeof(regtype), "IPPFIND_SERVICE_REGTYPE=%s",
1919*5e7646d2SAndroid Build Coastguard Worker service->regtype);
1920*5e7646d2SAndroid Build Coastguard Worker snprintf(scheme, sizeof(scheme), "IPPFIND_SERVICE_SCHEME=%s",
1921*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_http._tcp", 10) ? "http" :
1922*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_https._tcp", 11) ? "https" :
1923*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_ipp._tcp", 9) ? "ipp" :
1924*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_ipps._tcp", 10) ? "ipps" : "lpd");
1925*5e7646d2SAndroid Build Coastguard Worker snprintf(uri, sizeof(uri), "IPPFIND_SERVICE_URI=%s", service->uri);
1926*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < service->num_txt && i < 100; i ++)
1927*5e7646d2SAndroid Build Coastguard Worker {
1928*5e7646d2SAndroid Build Coastguard Worker snprintf(txt[i], sizeof(txt[i]), "IPPFIND_TXT_%s=%s", service->txt[i].name,
1929*5e7646d2SAndroid Build Coastguard Worker service->txt[i].value);
1930*5e7646d2SAndroid Build Coastguard Worker for (ptr = txt[i] + 12; *ptr && *ptr != '='; ptr ++)
1931*5e7646d2SAndroid Build Coastguard Worker *ptr = (char)_cups_toupper(*ptr);
1932*5e7646d2SAndroid Build Coastguard Worker }
1933*5e7646d2SAndroid Build Coastguard Worker
1934*5e7646d2SAndroid Build Coastguard Worker for (i = 0, myenvc = 7 + service->num_txt; environ[i]; i ++)
1935*5e7646d2SAndroid Build Coastguard Worker if (strncmp(environ[i], "IPPFIND_", 8))
1936*5e7646d2SAndroid Build Coastguard Worker myenvc ++;
1937*5e7646d2SAndroid Build Coastguard Worker
1938*5e7646d2SAndroid Build Coastguard Worker if ((myenvp = calloc(sizeof(char *), (size_t)(myenvc + 1))) == NULL)
1939*5e7646d2SAndroid Build Coastguard Worker {
1940*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("ippfind: Out of memory."));
1941*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_MEMORY);
1942*5e7646d2SAndroid Build Coastguard Worker }
1943*5e7646d2SAndroid Build Coastguard Worker
1944*5e7646d2SAndroid Build Coastguard Worker for (i = 0, myenvc = 0; environ[i]; i ++)
1945*5e7646d2SAndroid Build Coastguard Worker if (strncmp(environ[i], "IPPFIND_", 8))
1946*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = environ[i];
1947*5e7646d2SAndroid Build Coastguard Worker
1948*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = domain;
1949*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = hostname;
1950*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = name;
1951*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = port;
1952*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = regtype;
1953*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = scheme;
1954*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = uri;
1955*5e7646d2SAndroid Build Coastguard Worker
1956*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < service->num_txt && i < 100; i ++)
1957*5e7646d2SAndroid Build Coastguard Worker myenvp[myenvc++] = txt[i];
1958*5e7646d2SAndroid Build Coastguard Worker
1959*5e7646d2SAndroid Build Coastguard Worker /*
1960*5e7646d2SAndroid Build Coastguard Worker * Allocate and copy command-line arguments...
1961*5e7646d2SAndroid Build Coastguard Worker */
1962*5e7646d2SAndroid Build Coastguard Worker
1963*5e7646d2SAndroid Build Coastguard Worker if ((myargv = calloc(sizeof(char *), (size_t)(num_args + 1))) == NULL)
1964*5e7646d2SAndroid Build Coastguard Worker {
1965*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("ippfind: Out of memory."));
1966*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_MEMORY);
1967*5e7646d2SAndroid Build Coastguard Worker }
1968*5e7646d2SAndroid Build Coastguard Worker
1969*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_args; i ++)
1970*5e7646d2SAndroid Build Coastguard Worker {
1971*5e7646d2SAndroid Build Coastguard Worker if (strchr(args[i], '{'))
1972*5e7646d2SAndroid Build Coastguard Worker {
1973*5e7646d2SAndroid Build Coastguard Worker char temp[2048], /* Temporary string */
1974*5e7646d2SAndroid Build Coastguard Worker *tptr, /* Pointer into temporary string */
1975*5e7646d2SAndroid Build Coastguard Worker keyword[256], /* {keyword} */
1976*5e7646d2SAndroid Build Coastguard Worker *kptr; /* Pointer into keyword */
1977*5e7646d2SAndroid Build Coastguard Worker
1978*5e7646d2SAndroid Build Coastguard Worker for (ptr = args[i], tptr = temp; *ptr; ptr ++)
1979*5e7646d2SAndroid Build Coastguard Worker {
1980*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '{')
1981*5e7646d2SAndroid Build Coastguard Worker {
1982*5e7646d2SAndroid Build Coastguard Worker /*
1983*5e7646d2SAndroid Build Coastguard Worker * Do a {var} substitution...
1984*5e7646d2SAndroid Build Coastguard Worker */
1985*5e7646d2SAndroid Build Coastguard Worker
1986*5e7646d2SAndroid Build Coastguard Worker for (kptr = keyword, ptr ++; *ptr && *ptr != '}'; ptr ++)
1987*5e7646d2SAndroid Build Coastguard Worker if (kptr < (keyword + sizeof(keyword) - 1))
1988*5e7646d2SAndroid Build Coastguard Worker *kptr++ = *ptr;
1989*5e7646d2SAndroid Build Coastguard Worker
1990*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '}')
1991*5e7646d2SAndroid Build Coastguard Worker {
1992*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr,
1993*5e7646d2SAndroid Build Coastguard Worker _("ippfind: Missing close brace in substitution."));
1994*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_SYNTAX);
1995*5e7646d2SAndroid Build Coastguard Worker }
1996*5e7646d2SAndroid Build Coastguard Worker
1997*5e7646d2SAndroid Build Coastguard Worker *kptr = '\0';
1998*5e7646d2SAndroid Build Coastguard Worker if (!keyword[0] || !strcmp(keyword, "service_uri"))
1999*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, service->uri, sizeof(temp) - (size_t)(tptr - temp));
2000*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "service_domain"))
2001*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, service->domain, sizeof(temp) - (size_t)(tptr - temp));
2002*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "service_hostname"))
2003*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, service->host, sizeof(temp) - (size_t)(tptr - temp));
2004*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "service_name"))
2005*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, service->name, sizeof(temp) - (size_t)(tptr - temp));
2006*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "service_path"))
2007*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, service->resource, sizeof(temp) - (size_t)(tptr - temp));
2008*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "service_port"))
2009*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, port + 21, sizeof(temp) - (size_t)(tptr - temp));
2010*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "service_scheme"))
2011*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, scheme + 22, sizeof(temp) - (size_t)(tptr - temp));
2012*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(keyword, "txt_", 4))
2013*5e7646d2SAndroid Build Coastguard Worker {
2014*5e7646d2SAndroid Build Coastguard Worker const char *val = cupsGetOption(keyword + 4, service->num_txt, service->txt);
2015*5e7646d2SAndroid Build Coastguard Worker if (val)
2016*5e7646d2SAndroid Build Coastguard Worker strlcpy(tptr, val, sizeof(temp) - (size_t)(tptr - temp));
2017*5e7646d2SAndroid Build Coastguard Worker else
2018*5e7646d2SAndroid Build Coastguard Worker *tptr = '\0';
2019*5e7646d2SAndroid Build Coastguard Worker }
2020*5e7646d2SAndroid Build Coastguard Worker else
2021*5e7646d2SAndroid Build Coastguard Worker {
2022*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unknown variable \"{%s}\"."),
2023*5e7646d2SAndroid Build Coastguard Worker keyword);
2024*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_SYNTAX);
2025*5e7646d2SAndroid Build Coastguard Worker }
2026*5e7646d2SAndroid Build Coastguard Worker
2027*5e7646d2SAndroid Build Coastguard Worker tptr += strlen(tptr);
2028*5e7646d2SAndroid Build Coastguard Worker }
2029*5e7646d2SAndroid Build Coastguard Worker else if (tptr < (temp + sizeof(temp) - 1))
2030*5e7646d2SAndroid Build Coastguard Worker *tptr++ = *ptr;
2031*5e7646d2SAndroid Build Coastguard Worker }
2032*5e7646d2SAndroid Build Coastguard Worker
2033*5e7646d2SAndroid Build Coastguard Worker *tptr = '\0';
2034*5e7646d2SAndroid Build Coastguard Worker myargv[i] = strdup(temp);
2035*5e7646d2SAndroid Build Coastguard Worker }
2036*5e7646d2SAndroid Build Coastguard Worker else
2037*5e7646d2SAndroid Build Coastguard Worker myargv[i] = strdup(args[i]);
2038*5e7646d2SAndroid Build Coastguard Worker }
2039*5e7646d2SAndroid Build Coastguard Worker
2040*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
2041*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
2042*5e7646d2SAndroid Build Coastguard Worker {
2043*5e7646d2SAndroid Build Coastguard Worker printf("\nProgram:\n %s\n", args[0]);
2044*5e7646d2SAndroid Build Coastguard Worker puts("\nArguments:");
2045*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_args; i ++)
2046*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", myargv[i]);
2047*5e7646d2SAndroid Build Coastguard Worker puts("\nEnvironment:");
2048*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < myenvc; i ++)
2049*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", myenvp[i]);
2050*5e7646d2SAndroid Build Coastguard Worker }
2051*5e7646d2SAndroid Build Coastguard Worker
2052*5e7646d2SAndroid Build Coastguard Worker status = _spawnvpe(_P_WAIT, args[0], myargv, myenvp);
2053*5e7646d2SAndroid Build Coastguard Worker
2054*5e7646d2SAndroid Build Coastguard Worker #else
2055*5e7646d2SAndroid Build Coastguard Worker /*
2056*5e7646d2SAndroid Build Coastguard Worker * Execute the program...
2057*5e7646d2SAndroid Build Coastguard Worker */
2058*5e7646d2SAndroid Build Coastguard Worker
2059*5e7646d2SAndroid Build Coastguard Worker if (strchr(args[0], '/') && !access(args[0], X_OK))
2060*5e7646d2SAndroid Build Coastguard Worker strlcpy(program, args[0], sizeof(program));
2061*5e7646d2SAndroid Build Coastguard Worker else if (!cupsFileFind(args[0], getenv("PATH"), 1, program, sizeof(program)))
2062*5e7646d2SAndroid Build Coastguard Worker {
2063*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to execute \"%s\": %s"),
2064*5e7646d2SAndroid Build Coastguard Worker args[0], strerror(ENOENT));
2065*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_SYNTAX);
2066*5e7646d2SAndroid Build Coastguard Worker }
2067*5e7646d2SAndroid Build Coastguard Worker
2068*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
2069*5e7646d2SAndroid Build Coastguard Worker {
2070*5e7646d2SAndroid Build Coastguard Worker printf("\nProgram:\n %s\n", program);
2071*5e7646d2SAndroid Build Coastguard Worker puts("\nArguments:");
2072*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_args; i ++)
2073*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", myargv[i]);
2074*5e7646d2SAndroid Build Coastguard Worker puts("\nEnvironment:");
2075*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < myenvc; i ++)
2076*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", myenvp[i]);
2077*5e7646d2SAndroid Build Coastguard Worker }
2078*5e7646d2SAndroid Build Coastguard Worker
2079*5e7646d2SAndroid Build Coastguard Worker if ((pid = fork()) == 0)
2080*5e7646d2SAndroid Build Coastguard Worker {
2081*5e7646d2SAndroid Build Coastguard Worker /*
2082*5e7646d2SAndroid Build Coastguard Worker * Child comes here...
2083*5e7646d2SAndroid Build Coastguard Worker */
2084*5e7646d2SAndroid Build Coastguard Worker
2085*5e7646d2SAndroid Build Coastguard Worker execve(program, myargv, myenvp);
2086*5e7646d2SAndroid Build Coastguard Worker exit(1);
2087*5e7646d2SAndroid Build Coastguard Worker }
2088*5e7646d2SAndroid Build Coastguard Worker else if (pid < 0)
2089*5e7646d2SAndroid Build Coastguard Worker {
2090*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to execute \"%s\": %s"),
2091*5e7646d2SAndroid Build Coastguard Worker args[0], strerror(errno));
2092*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_SYNTAX);
2093*5e7646d2SAndroid Build Coastguard Worker }
2094*5e7646d2SAndroid Build Coastguard Worker else
2095*5e7646d2SAndroid Build Coastguard Worker {
2096*5e7646d2SAndroid Build Coastguard Worker /*
2097*5e7646d2SAndroid Build Coastguard Worker * Wait for it to complete...
2098*5e7646d2SAndroid Build Coastguard Worker */
2099*5e7646d2SAndroid Build Coastguard Worker
2100*5e7646d2SAndroid Build Coastguard Worker while (wait(&status) != pid)
2101*5e7646d2SAndroid Build Coastguard Worker ;
2102*5e7646d2SAndroid Build Coastguard Worker }
2103*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
2104*5e7646d2SAndroid Build Coastguard Worker
2105*5e7646d2SAndroid Build Coastguard Worker /*
2106*5e7646d2SAndroid Build Coastguard Worker * Free memory...
2107*5e7646d2SAndroid Build Coastguard Worker */
2108*5e7646d2SAndroid Build Coastguard Worker
2109*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_args; i ++)
2110*5e7646d2SAndroid Build Coastguard Worker free(myargv[i]);
2111*5e7646d2SAndroid Build Coastguard Worker
2112*5e7646d2SAndroid Build Coastguard Worker free(myargv);
2113*5e7646d2SAndroid Build Coastguard Worker free(myenvp);
2114*5e7646d2SAndroid Build Coastguard Worker
2115*5e7646d2SAndroid Build Coastguard Worker /*
2116*5e7646d2SAndroid Build Coastguard Worker * Return whether the program succeeded or crashed...
2117*5e7646d2SAndroid Build Coastguard Worker */
2118*5e7646d2SAndroid Build Coastguard Worker
2119*5e7646d2SAndroid Build Coastguard Worker if (getenv("IPPFIND_DEBUG"))
2120*5e7646d2SAndroid Build Coastguard Worker {
2121*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
2122*5e7646d2SAndroid Build Coastguard Worker printf("Exit Status: %d\n", status);
2123*5e7646d2SAndroid Build Coastguard Worker #else
2124*5e7646d2SAndroid Build Coastguard Worker if (WIFEXITED(status))
2125*5e7646d2SAndroid Build Coastguard Worker printf("Exit Status: %d\n", WEXITSTATUS(status));
2126*5e7646d2SAndroid Build Coastguard Worker else
2127*5e7646d2SAndroid Build Coastguard Worker printf("Terminating Signal: %d\n", WTERMSIG(status));
2128*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
2129*5e7646d2SAndroid Build Coastguard Worker }
2130*5e7646d2SAndroid Build Coastguard Worker
2131*5e7646d2SAndroid Build Coastguard Worker return (status == 0);
2132*5e7646d2SAndroid Build Coastguard Worker }
2133*5e7646d2SAndroid Build Coastguard Worker
2134*5e7646d2SAndroid Build Coastguard Worker
2135*5e7646d2SAndroid Build Coastguard Worker /*
2136*5e7646d2SAndroid Build Coastguard Worker * 'get_service()' - Create or update a device.
2137*5e7646d2SAndroid Build Coastguard Worker */
2138*5e7646d2SAndroid Build Coastguard Worker
2139*5e7646d2SAndroid Build Coastguard Worker static ippfind_srv_t * /* O - Service */
get_service(cups_array_t * services,const char * serviceName,const char * regtype,const char * replyDomain)2140*5e7646d2SAndroid Build Coastguard Worker get_service(cups_array_t *services, /* I - Service array */
2141*5e7646d2SAndroid Build Coastguard Worker const char *serviceName, /* I - Name of service/device */
2142*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Type of service */
2143*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain) /* I - Service domain */
2144*5e7646d2SAndroid Build Coastguard Worker {
2145*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t key, /* Search key */
2146*5e7646d2SAndroid Build Coastguard Worker *service; /* Service */
2147*5e7646d2SAndroid Build Coastguard Worker char fullName[kDNSServiceMaxDomainName];
2148*5e7646d2SAndroid Build Coastguard Worker /* Full name for query */
2149*5e7646d2SAndroid Build Coastguard Worker
2150*5e7646d2SAndroid Build Coastguard Worker
2151*5e7646d2SAndroid Build Coastguard Worker /*
2152*5e7646d2SAndroid Build Coastguard Worker * See if this is a new device...
2153*5e7646d2SAndroid Build Coastguard Worker */
2154*5e7646d2SAndroid Build Coastguard Worker
2155*5e7646d2SAndroid Build Coastguard Worker key.name = (char *)serviceName;
2156*5e7646d2SAndroid Build Coastguard Worker key.regtype = (char *)regtype;
2157*5e7646d2SAndroid Build Coastguard Worker
2158*5e7646d2SAndroid Build Coastguard Worker for (service = cupsArrayFind(services, &key);
2159*5e7646d2SAndroid Build Coastguard Worker service;
2160*5e7646d2SAndroid Build Coastguard Worker service = cupsArrayNext(services))
2161*5e7646d2SAndroid Build Coastguard Worker if (_cups_strcasecmp(service->name, key.name))
2162*5e7646d2SAndroid Build Coastguard Worker break;
2163*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(service->regtype, key.regtype))
2164*5e7646d2SAndroid Build Coastguard Worker return (service);
2165*5e7646d2SAndroid Build Coastguard Worker
2166*5e7646d2SAndroid Build Coastguard Worker /*
2167*5e7646d2SAndroid Build Coastguard Worker * Yes, add the service...
2168*5e7646d2SAndroid Build Coastguard Worker */
2169*5e7646d2SAndroid Build Coastguard Worker
2170*5e7646d2SAndroid Build Coastguard Worker service = calloc(sizeof(ippfind_srv_t), 1);
2171*5e7646d2SAndroid Build Coastguard Worker service->name = strdup(serviceName);
2172*5e7646d2SAndroid Build Coastguard Worker service->domain = strdup(replyDomain);
2173*5e7646d2SAndroid Build Coastguard Worker service->regtype = strdup(regtype);
2174*5e7646d2SAndroid Build Coastguard Worker
2175*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(services, service);
2176*5e7646d2SAndroid Build Coastguard Worker
2177*5e7646d2SAndroid Build Coastguard Worker /*
2178*5e7646d2SAndroid Build Coastguard Worker * Set the "full name" of this service, which is used for queries and
2179*5e7646d2SAndroid Build Coastguard Worker * resolves...
2180*5e7646d2SAndroid Build Coastguard Worker */
2181*5e7646d2SAndroid Build Coastguard Worker
2182*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
2183*5e7646d2SAndroid Build Coastguard Worker DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
2184*5e7646d2SAndroid Build Coastguard Worker #else /* HAVE_AVAHI */
2185*5e7646d2SAndroid Build Coastguard Worker avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName,
2186*5e7646d2SAndroid Build Coastguard Worker regtype, replyDomain);
2187*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
2188*5e7646d2SAndroid Build Coastguard Worker
2189*5e7646d2SAndroid Build Coastguard Worker service->fullName = strdup(fullName);
2190*5e7646d2SAndroid Build Coastguard Worker
2191*5e7646d2SAndroid Build Coastguard Worker return (service);
2192*5e7646d2SAndroid Build Coastguard Worker }
2193*5e7646d2SAndroid Build Coastguard Worker
2194*5e7646d2SAndroid Build Coastguard Worker
2195*5e7646d2SAndroid Build Coastguard Worker /*
2196*5e7646d2SAndroid Build Coastguard Worker * 'get_time()' - Get the current time-of-day in seconds.
2197*5e7646d2SAndroid Build Coastguard Worker */
2198*5e7646d2SAndroid Build Coastguard Worker
2199*5e7646d2SAndroid Build Coastguard Worker static double
get_time(void)2200*5e7646d2SAndroid Build Coastguard Worker get_time(void)
2201*5e7646d2SAndroid Build Coastguard Worker {
2202*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
2203*5e7646d2SAndroid Build Coastguard Worker struct _timeb curtime; /* Current Windows time */
2204*5e7646d2SAndroid Build Coastguard Worker
2205*5e7646d2SAndroid Build Coastguard Worker _ftime(&curtime);
2206*5e7646d2SAndroid Build Coastguard Worker
2207*5e7646d2SAndroid Build Coastguard Worker return (curtime.time + 0.001 * curtime.millitm);
2208*5e7646d2SAndroid Build Coastguard Worker
2209*5e7646d2SAndroid Build Coastguard Worker #else
2210*5e7646d2SAndroid Build Coastguard Worker struct timeval curtime; /* Current UNIX time */
2211*5e7646d2SAndroid Build Coastguard Worker
2212*5e7646d2SAndroid Build Coastguard Worker if (gettimeofday(&curtime, NULL))
2213*5e7646d2SAndroid Build Coastguard Worker return (0.0);
2214*5e7646d2SAndroid Build Coastguard Worker else
2215*5e7646d2SAndroid Build Coastguard Worker return (curtime.tv_sec + 0.000001 * curtime.tv_usec);
2216*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
2217*5e7646d2SAndroid Build Coastguard Worker }
2218*5e7646d2SAndroid Build Coastguard Worker
2219*5e7646d2SAndroid Build Coastguard Worker
2220*5e7646d2SAndroid Build Coastguard Worker /*
2221*5e7646d2SAndroid Build Coastguard Worker * 'list_service()' - List the contents of a service.
2222*5e7646d2SAndroid Build Coastguard Worker */
2223*5e7646d2SAndroid Build Coastguard Worker
2224*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 if successful, 0 otherwise */
list_service(ippfind_srv_t * service)2225*5e7646d2SAndroid Build Coastguard Worker list_service(ippfind_srv_t *service) /* I - Service */
2226*5e7646d2SAndroid Build Coastguard Worker {
2227*5e7646d2SAndroid Build Coastguard Worker http_addrlist_t *addrlist; /* Address(es) of service */
2228*5e7646d2SAndroid Build Coastguard Worker char port[10]; /* Port number of service */
2229*5e7646d2SAndroid Build Coastguard Worker
2230*5e7646d2SAndroid Build Coastguard Worker
2231*5e7646d2SAndroid Build Coastguard Worker snprintf(port, sizeof(port), "%d", service->port);
2232*5e7646d2SAndroid Build Coastguard Worker
2233*5e7646d2SAndroid Build Coastguard Worker if ((addrlist = httpAddrGetList(service->host, address_family, port)) == NULL)
2234*5e7646d2SAndroid Build Coastguard Worker {
2235*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unreachable", service->uri);
2236*5e7646d2SAndroid Build Coastguard Worker return (0);
2237*5e7646d2SAndroid Build Coastguard Worker }
2238*5e7646d2SAndroid Build Coastguard Worker
2239*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(service->regtype, "_ipp._tcp", 9) ||
2240*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_ipps._tcp", 10))
2241*5e7646d2SAndroid Build Coastguard Worker {
2242*5e7646d2SAndroid Build Coastguard Worker /*
2243*5e7646d2SAndroid Build Coastguard Worker * IPP/IPPS printer
2244*5e7646d2SAndroid Build Coastguard Worker */
2245*5e7646d2SAndroid Build Coastguard Worker
2246*5e7646d2SAndroid Build Coastguard Worker http_t *http; /* HTTP connection */
2247*5e7646d2SAndroid Build Coastguard Worker ipp_t *request, /* IPP request */
2248*5e7646d2SAndroid Build Coastguard Worker *response; /* IPP response */
2249*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* IPP attribute */
2250*5e7646d2SAndroid Build Coastguard Worker int i, /* Looping var */
2251*5e7646d2SAndroid Build Coastguard Worker count, /* Number of values */
2252*5e7646d2SAndroid Build Coastguard Worker version, /* IPP version */
2253*5e7646d2SAndroid Build Coastguard Worker paccepting; /* printer-is-accepting-jobs value */
2254*5e7646d2SAndroid Build Coastguard Worker ipp_pstate_t pstate; /* printer-state value */
2255*5e7646d2SAndroid Build Coastguard Worker char preasons[1024], /* Comma-delimited printer-state-reasons */
2256*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into reasons */
2257*5e7646d2SAndroid Build Coastguard Worker *end; /* End of reasons buffer */
2258*5e7646d2SAndroid Build Coastguard Worker static const char * const rattrs[] =/* Requested attributes */
2259*5e7646d2SAndroid Build Coastguard Worker {
2260*5e7646d2SAndroid Build Coastguard Worker "printer-is-accepting-jobs",
2261*5e7646d2SAndroid Build Coastguard Worker "printer-state",
2262*5e7646d2SAndroid Build Coastguard Worker "printer-state-reasons"
2263*5e7646d2SAndroid Build Coastguard Worker };
2264*5e7646d2SAndroid Build Coastguard Worker
2265*5e7646d2SAndroid Build Coastguard Worker /*
2266*5e7646d2SAndroid Build Coastguard Worker * Connect to the printer...
2267*5e7646d2SAndroid Build Coastguard Worker */
2268*5e7646d2SAndroid Build Coastguard Worker
2269*5e7646d2SAndroid Build Coastguard Worker http = httpConnect2(service->host, service->port, addrlist, address_family,
2270*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_ipps._tcp", 10) ?
2271*5e7646d2SAndroid Build Coastguard Worker HTTP_ENCRYPTION_ALWAYS :
2272*5e7646d2SAndroid Build Coastguard Worker HTTP_ENCRYPTION_IF_REQUESTED,
2273*5e7646d2SAndroid Build Coastguard Worker 1, 30000, NULL);
2274*5e7646d2SAndroid Build Coastguard Worker
2275*5e7646d2SAndroid Build Coastguard Worker httpAddrFreeList(addrlist);
2276*5e7646d2SAndroid Build Coastguard Worker
2277*5e7646d2SAndroid Build Coastguard Worker if (!http)
2278*5e7646d2SAndroid Build Coastguard Worker {
2279*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unavailable", service->uri);
2280*5e7646d2SAndroid Build Coastguard Worker return (0);
2281*5e7646d2SAndroid Build Coastguard Worker }
2282*5e7646d2SAndroid Build Coastguard Worker
2283*5e7646d2SAndroid Build Coastguard Worker /*
2284*5e7646d2SAndroid Build Coastguard Worker * Get the current printer state...
2285*5e7646d2SAndroid Build Coastguard Worker */
2286*5e7646d2SAndroid Build Coastguard Worker
2287*5e7646d2SAndroid Build Coastguard Worker response = NULL;
2288*5e7646d2SAndroid Build Coastguard Worker version = ipp_version;
2289*5e7646d2SAndroid Build Coastguard Worker
2290*5e7646d2SAndroid Build Coastguard Worker do
2291*5e7646d2SAndroid Build Coastguard Worker {
2292*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
2293*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
2294*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
2295*5e7646d2SAndroid Build Coastguard Worker service->uri);
2296*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2297*5e7646d2SAndroid Build Coastguard Worker "requesting-user-name", NULL, cupsUser());
2298*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2299*5e7646d2SAndroid Build Coastguard Worker "requested-attributes",
2300*5e7646d2SAndroid Build Coastguard Worker (int)(sizeof(rattrs) / sizeof(rattrs[0])), NULL, rattrs);
2301*5e7646d2SAndroid Build Coastguard Worker
2302*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, service->resource);
2303*5e7646d2SAndroid Build Coastguard Worker
2304*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST && version > 11)
2305*5e7646d2SAndroid Build Coastguard Worker version = 11;
2306*5e7646d2SAndroid Build Coastguard Worker }
2307*5e7646d2SAndroid Build Coastguard Worker while (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE && version > 11);
2308*5e7646d2SAndroid Build Coastguard Worker
2309*5e7646d2SAndroid Build Coastguard Worker /*
2310*5e7646d2SAndroid Build Coastguard Worker * Show results...
2311*5e7646d2SAndroid Build Coastguard Worker */
2312*5e7646d2SAndroid Build Coastguard Worker
2313*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE)
2314*5e7646d2SAndroid Build Coastguard Worker {
2315*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s: unavailable", service->uri);
2316*5e7646d2SAndroid Build Coastguard Worker return (0);
2317*5e7646d2SAndroid Build Coastguard Worker }
2318*5e7646d2SAndroid Build Coastguard Worker
2319*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "printer-state",
2320*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
2321*5e7646d2SAndroid Build Coastguard Worker pstate = (ipp_pstate_t)ippGetInteger(attr, 0);
2322*5e7646d2SAndroid Build Coastguard Worker else
2323*5e7646d2SAndroid Build Coastguard Worker pstate = IPP_PSTATE_STOPPED;
2324*5e7646d2SAndroid Build Coastguard Worker
2325*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
2326*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL)
2327*5e7646d2SAndroid Build Coastguard Worker paccepting = ippGetBoolean(attr, 0);
2328*5e7646d2SAndroid Build Coastguard Worker else
2329*5e7646d2SAndroid Build Coastguard Worker paccepting = 0;
2330*5e7646d2SAndroid Build Coastguard Worker
2331*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "printer-state-reasons",
2332*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
2333*5e7646d2SAndroid Build Coastguard Worker {
2334*5e7646d2SAndroid Build Coastguard Worker strlcpy(preasons, ippGetString(attr, 0, NULL), sizeof(preasons));
2335*5e7646d2SAndroid Build Coastguard Worker
2336*5e7646d2SAndroid Build Coastguard Worker for (i = 1, count = ippGetCount(attr), ptr = preasons + strlen(preasons),
2337*5e7646d2SAndroid Build Coastguard Worker end = preasons + sizeof(preasons) - 1;
2338*5e7646d2SAndroid Build Coastguard Worker i < count && ptr < end;
2339*5e7646d2SAndroid Build Coastguard Worker i ++, ptr += strlen(ptr))
2340*5e7646d2SAndroid Build Coastguard Worker {
2341*5e7646d2SAndroid Build Coastguard Worker *ptr++ = ',';
2342*5e7646d2SAndroid Build Coastguard Worker strlcpy(ptr, ippGetString(attr, i, NULL), (size_t)(end - ptr + 1));
2343*5e7646d2SAndroid Build Coastguard Worker }
2344*5e7646d2SAndroid Build Coastguard Worker }
2345*5e7646d2SAndroid Build Coastguard Worker else
2346*5e7646d2SAndroid Build Coastguard Worker strlcpy(preasons, "none", sizeof(preasons));
2347*5e7646d2SAndroid Build Coastguard Worker
2348*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2349*5e7646d2SAndroid Build Coastguard Worker httpClose(http);
2350*5e7646d2SAndroid Build Coastguard Worker
2351*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s %s %s %s", service->uri, ippEnumString("printer-state", (int)pstate), paccepting ? "accepting-jobs" : "not-accepting-jobs", preasons);
2352*5e7646d2SAndroid Build Coastguard Worker }
2353*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(service->regtype, "_http._tcp", 10) ||
2354*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_https._tcp", 11))
2355*5e7646d2SAndroid Build Coastguard Worker {
2356*5e7646d2SAndroid Build Coastguard Worker /*
2357*5e7646d2SAndroid Build Coastguard Worker * HTTP/HTTPS web page
2358*5e7646d2SAndroid Build Coastguard Worker */
2359*5e7646d2SAndroid Build Coastguard Worker
2360*5e7646d2SAndroid Build Coastguard Worker http_t *http; /* HTTP connection */
2361*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* HEAD status */
2362*5e7646d2SAndroid Build Coastguard Worker
2363*5e7646d2SAndroid Build Coastguard Worker
2364*5e7646d2SAndroid Build Coastguard Worker /*
2365*5e7646d2SAndroid Build Coastguard Worker * Connect to the web server...
2366*5e7646d2SAndroid Build Coastguard Worker */
2367*5e7646d2SAndroid Build Coastguard Worker
2368*5e7646d2SAndroid Build Coastguard Worker http = httpConnect2(service->host, service->port, addrlist, address_family,
2369*5e7646d2SAndroid Build Coastguard Worker !strncmp(service->regtype, "_ipps._tcp", 10) ?
2370*5e7646d2SAndroid Build Coastguard Worker HTTP_ENCRYPTION_ALWAYS :
2371*5e7646d2SAndroid Build Coastguard Worker HTTP_ENCRYPTION_IF_REQUESTED,
2372*5e7646d2SAndroid Build Coastguard Worker 1, 30000, NULL);
2373*5e7646d2SAndroid Build Coastguard Worker
2374*5e7646d2SAndroid Build Coastguard Worker httpAddrFreeList(addrlist);
2375*5e7646d2SAndroid Build Coastguard Worker
2376*5e7646d2SAndroid Build Coastguard Worker if (!http)
2377*5e7646d2SAndroid Build Coastguard Worker {
2378*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unavailable", service->uri);
2379*5e7646d2SAndroid Build Coastguard Worker return (0);
2380*5e7646d2SAndroid Build Coastguard Worker }
2381*5e7646d2SAndroid Build Coastguard Worker
2382*5e7646d2SAndroid Build Coastguard Worker if (httpGet(http, service->resource))
2383*5e7646d2SAndroid Build Coastguard Worker {
2384*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unavailable", service->uri);
2385*5e7646d2SAndroid Build Coastguard Worker return (0);
2386*5e7646d2SAndroid Build Coastguard Worker }
2387*5e7646d2SAndroid Build Coastguard Worker
2388*5e7646d2SAndroid Build Coastguard Worker do
2389*5e7646d2SAndroid Build Coastguard Worker {
2390*5e7646d2SAndroid Build Coastguard Worker status = httpUpdate(http);
2391*5e7646d2SAndroid Build Coastguard Worker }
2392*5e7646d2SAndroid Build Coastguard Worker while (status == HTTP_STATUS_CONTINUE);
2393*5e7646d2SAndroid Build Coastguard Worker
2394*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
2395*5e7646d2SAndroid Build Coastguard Worker httpClose(http);
2396*5e7646d2SAndroid Build Coastguard Worker
2397*5e7646d2SAndroid Build Coastguard Worker if (status >= HTTP_STATUS_BAD_REQUEST)
2398*5e7646d2SAndroid Build Coastguard Worker {
2399*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unavailable", service->uri);
2400*5e7646d2SAndroid Build Coastguard Worker return (0);
2401*5e7646d2SAndroid Build Coastguard Worker }
2402*5e7646d2SAndroid Build Coastguard Worker
2403*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s available", service->uri);
2404*5e7646d2SAndroid Build Coastguard Worker }
2405*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(service->regtype, "_printer._tcp", 13))
2406*5e7646d2SAndroid Build Coastguard Worker {
2407*5e7646d2SAndroid Build Coastguard Worker /*
2408*5e7646d2SAndroid Build Coastguard Worker * LPD printer
2409*5e7646d2SAndroid Build Coastguard Worker */
2410*5e7646d2SAndroid Build Coastguard Worker
2411*5e7646d2SAndroid Build Coastguard Worker int sock; /* Socket */
2412*5e7646d2SAndroid Build Coastguard Worker
2413*5e7646d2SAndroid Build Coastguard Worker
2414*5e7646d2SAndroid Build Coastguard Worker if (!httpAddrConnect(addrlist, &sock))
2415*5e7646d2SAndroid Build Coastguard Worker {
2416*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unavailable", service->uri);
2417*5e7646d2SAndroid Build Coastguard Worker httpAddrFreeList(addrlist);
2418*5e7646d2SAndroid Build Coastguard Worker return (0);
2419*5e7646d2SAndroid Build Coastguard Worker }
2420*5e7646d2SAndroid Build Coastguard Worker
2421*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s available", service->uri);
2422*5e7646d2SAndroid Build Coastguard Worker httpAddrFreeList(addrlist);
2423*5e7646d2SAndroid Build Coastguard Worker
2424*5e7646d2SAndroid Build Coastguard Worker httpAddrClose(NULL, sock);
2425*5e7646d2SAndroid Build Coastguard Worker }
2426*5e7646d2SAndroid Build Coastguard Worker else
2427*5e7646d2SAndroid Build Coastguard Worker {
2428*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stdout, "%s unsupported", service->uri);
2429*5e7646d2SAndroid Build Coastguard Worker httpAddrFreeList(addrlist);
2430*5e7646d2SAndroid Build Coastguard Worker return (0);
2431*5e7646d2SAndroid Build Coastguard Worker }
2432*5e7646d2SAndroid Build Coastguard Worker
2433*5e7646d2SAndroid Build Coastguard Worker return (1);
2434*5e7646d2SAndroid Build Coastguard Worker }
2435*5e7646d2SAndroid Build Coastguard Worker
2436*5e7646d2SAndroid Build Coastguard Worker
2437*5e7646d2SAndroid Build Coastguard Worker /*
2438*5e7646d2SAndroid Build Coastguard Worker * 'new_expr()' - Create a new expression.
2439*5e7646d2SAndroid Build Coastguard Worker */
2440*5e7646d2SAndroid Build Coastguard Worker
2441*5e7646d2SAndroid Build Coastguard Worker static ippfind_expr_t * /* O - New expression */
new_expr(ippfind_op_t op,int invert,const char * value,const char * regex,char ** args)2442*5e7646d2SAndroid Build Coastguard Worker new_expr(ippfind_op_t op, /* I - Operation */
2443*5e7646d2SAndroid Build Coastguard Worker int invert, /* I - Invert result? */
2444*5e7646d2SAndroid Build Coastguard Worker const char *value, /* I - TXT key or port range */
2445*5e7646d2SAndroid Build Coastguard Worker const char *regex, /* I - Regular expression */
2446*5e7646d2SAndroid Build Coastguard Worker char **args) /* I - Pointer to argument strings */
2447*5e7646d2SAndroid Build Coastguard Worker {
2448*5e7646d2SAndroid Build Coastguard Worker ippfind_expr_t *temp; /* New expression */
2449*5e7646d2SAndroid Build Coastguard Worker
2450*5e7646d2SAndroid Build Coastguard Worker
2451*5e7646d2SAndroid Build Coastguard Worker if ((temp = calloc(1, sizeof(ippfind_expr_t))) == NULL)
2452*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2453*5e7646d2SAndroid Build Coastguard Worker
2454*5e7646d2SAndroid Build Coastguard Worker temp->op = op;
2455*5e7646d2SAndroid Build Coastguard Worker temp->invert = invert;
2456*5e7646d2SAndroid Build Coastguard Worker
2457*5e7646d2SAndroid Build Coastguard Worker if (op == IPPFIND_OP_TXT_EXISTS || op == IPPFIND_OP_TXT_REGEX || op == IPPFIND_OP_NAME_LITERAL)
2458*5e7646d2SAndroid Build Coastguard Worker temp->name = (char *)value;
2459*5e7646d2SAndroid Build Coastguard Worker else if (op == IPPFIND_OP_PORT_RANGE)
2460*5e7646d2SAndroid Build Coastguard Worker {
2461*5e7646d2SAndroid Build Coastguard Worker /*
2462*5e7646d2SAndroid Build Coastguard Worker * Pull port number range of the form "number", "-number" (0-number),
2463*5e7646d2SAndroid Build Coastguard Worker * "number-" (number-65535), and "number-number".
2464*5e7646d2SAndroid Build Coastguard Worker */
2465*5e7646d2SAndroid Build Coastguard Worker
2466*5e7646d2SAndroid Build Coastguard Worker if (*value == '-')
2467*5e7646d2SAndroid Build Coastguard Worker {
2468*5e7646d2SAndroid Build Coastguard Worker temp->range[1] = atoi(value + 1);
2469*5e7646d2SAndroid Build Coastguard Worker }
2470*5e7646d2SAndroid Build Coastguard Worker else if (strchr(value, '-'))
2471*5e7646d2SAndroid Build Coastguard Worker {
2472*5e7646d2SAndroid Build Coastguard Worker if (sscanf(value, "%d-%d", temp->range, temp->range + 1) == 1)
2473*5e7646d2SAndroid Build Coastguard Worker temp->range[1] = 65535;
2474*5e7646d2SAndroid Build Coastguard Worker }
2475*5e7646d2SAndroid Build Coastguard Worker else
2476*5e7646d2SAndroid Build Coastguard Worker {
2477*5e7646d2SAndroid Build Coastguard Worker temp->range[0] = temp->range[1] = atoi(value);
2478*5e7646d2SAndroid Build Coastguard Worker }
2479*5e7646d2SAndroid Build Coastguard Worker }
2480*5e7646d2SAndroid Build Coastguard Worker
2481*5e7646d2SAndroid Build Coastguard Worker if (regex)
2482*5e7646d2SAndroid Build Coastguard Worker {
2483*5e7646d2SAndroid Build Coastguard Worker int err = regcomp(&(temp->re), regex, REG_NOSUB | REG_ICASE | REG_EXTENDED);
2484*5e7646d2SAndroid Build Coastguard Worker
2485*5e7646d2SAndroid Build Coastguard Worker if (err)
2486*5e7646d2SAndroid Build Coastguard Worker {
2487*5e7646d2SAndroid Build Coastguard Worker char message[256]; /* Error message */
2488*5e7646d2SAndroid Build Coastguard Worker
2489*5e7646d2SAndroid Build Coastguard Worker regerror(err, &(temp->re), message, sizeof(message));
2490*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Bad regular expression: %s"),
2491*5e7646d2SAndroid Build Coastguard Worker message);
2492*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_SYNTAX);
2493*5e7646d2SAndroid Build Coastguard Worker }
2494*5e7646d2SAndroid Build Coastguard Worker }
2495*5e7646d2SAndroid Build Coastguard Worker
2496*5e7646d2SAndroid Build Coastguard Worker if (args)
2497*5e7646d2SAndroid Build Coastguard Worker {
2498*5e7646d2SAndroid Build Coastguard Worker int num_args; /* Number of arguments */
2499*5e7646d2SAndroid Build Coastguard Worker
2500*5e7646d2SAndroid Build Coastguard Worker for (num_args = 1; args[num_args]; num_args ++)
2501*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(args[num_args], ";"))
2502*5e7646d2SAndroid Build Coastguard Worker break;
2503*5e7646d2SAndroid Build Coastguard Worker
2504*5e7646d2SAndroid Build Coastguard Worker temp->num_args = num_args;
2505*5e7646d2SAndroid Build Coastguard Worker temp->args = malloc((size_t)num_args * sizeof(char *));
2506*5e7646d2SAndroid Build Coastguard Worker memcpy(temp->args, args, (size_t)num_args * sizeof(char *));
2507*5e7646d2SAndroid Build Coastguard Worker }
2508*5e7646d2SAndroid Build Coastguard Worker
2509*5e7646d2SAndroid Build Coastguard Worker return (temp);
2510*5e7646d2SAndroid Build Coastguard Worker }
2511*5e7646d2SAndroid Build Coastguard Worker
2512*5e7646d2SAndroid Build Coastguard Worker
2513*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_AVAHI
2514*5e7646d2SAndroid Build Coastguard Worker /*
2515*5e7646d2SAndroid Build Coastguard Worker * 'poll_callback()' - Wait for input on the specified file descriptors.
2516*5e7646d2SAndroid Build Coastguard Worker *
2517*5e7646d2SAndroid Build Coastguard Worker * Note: This function is needed because avahi_simple_poll_iterate is broken
2518*5e7646d2SAndroid Build Coastguard Worker * and always uses a timeout of 0 (!) milliseconds.
2519*5e7646d2SAndroid Build Coastguard Worker * (Avahi Ticket #364)
2520*5e7646d2SAndroid Build Coastguard Worker */
2521*5e7646d2SAndroid Build Coastguard Worker
2522*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)2523*5e7646d2SAndroid Build Coastguard Worker poll_callback(
2524*5e7646d2SAndroid Build Coastguard Worker struct pollfd *pollfds, /* I - File descriptors */
2525*5e7646d2SAndroid Build Coastguard Worker unsigned int num_pollfds, /* I - Number of file descriptors */
2526*5e7646d2SAndroid Build Coastguard Worker int timeout, /* I - Timeout in milliseconds (unused) */
2527*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - User data (unused) */
2528*5e7646d2SAndroid Build Coastguard Worker {
2529*5e7646d2SAndroid Build Coastguard Worker int val; /* Return value */
2530*5e7646d2SAndroid Build Coastguard Worker
2531*5e7646d2SAndroid Build Coastguard Worker
2532*5e7646d2SAndroid Build Coastguard Worker (void)timeout;
2533*5e7646d2SAndroid Build Coastguard Worker (void)context;
2534*5e7646d2SAndroid Build Coastguard Worker
2535*5e7646d2SAndroid Build Coastguard Worker val = poll(pollfds, num_pollfds, 500);
2536*5e7646d2SAndroid Build Coastguard Worker
2537*5e7646d2SAndroid Build Coastguard Worker if (val > 0)
2538*5e7646d2SAndroid Build Coastguard Worker avahi_got_data = 1;
2539*5e7646d2SAndroid Build Coastguard Worker
2540*5e7646d2SAndroid Build Coastguard Worker return (val);
2541*5e7646d2SAndroid Build Coastguard Worker }
2542*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_AVAHI */
2543*5e7646d2SAndroid Build Coastguard Worker
2544*5e7646d2SAndroid Build Coastguard Worker
2545*5e7646d2SAndroid Build Coastguard Worker /*
2546*5e7646d2SAndroid Build Coastguard Worker * 'resolve_callback()' - Process resolve data.
2547*5e7646d2SAndroid Build Coastguard Worker */
2548*5e7646d2SAndroid Build Coastguard Worker
2549*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_DNSSD
2550*5e7646d2SAndroid Build Coastguard Worker static void DNSSD_API
resolve_callback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * fullName,const char * hostTarget,uint16_t port,uint16_t txtLen,const unsigned char * txtRecord,void * context)2551*5e7646d2SAndroid Build Coastguard Worker resolve_callback(
2552*5e7646d2SAndroid Build Coastguard Worker DNSServiceRef sdRef, /* I - Service reference */
2553*5e7646d2SAndroid Build Coastguard Worker DNSServiceFlags flags, /* I - Data flags */
2554*5e7646d2SAndroid Build Coastguard Worker uint32_t interfaceIndex, /* I - Interface */
2555*5e7646d2SAndroid Build Coastguard Worker DNSServiceErrorType errorCode, /* I - Error, if any */
2556*5e7646d2SAndroid Build Coastguard Worker const char *fullName, /* I - Full service name */
2557*5e7646d2SAndroid Build Coastguard Worker const char *hostTarget, /* I - Hostname */
2558*5e7646d2SAndroid Build Coastguard Worker uint16_t port, /* I - Port number (network byte order) */
2559*5e7646d2SAndroid Build Coastguard Worker uint16_t txtLen, /* I - Length of TXT record data */
2560*5e7646d2SAndroid Build Coastguard Worker const unsigned char *txtRecord, /* I - TXT record data */
2561*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Service */
2562*5e7646d2SAndroid Build Coastguard Worker {
2563*5e7646d2SAndroid Build Coastguard Worker char key[256], /* TXT key value */
2564*5e7646d2SAndroid Build Coastguard Worker *value; /* Value from TXT record */
2565*5e7646d2SAndroid Build Coastguard Worker const unsigned char *txtEnd; /* End of TXT record */
2566*5e7646d2SAndroid Build Coastguard Worker uint8_t valueLen; /* Length of value */
2567*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t *service = (ippfind_srv_t *)context;
2568*5e7646d2SAndroid Build Coastguard Worker /* Service */
2569*5e7646d2SAndroid Build Coastguard Worker
2570*5e7646d2SAndroid Build Coastguard Worker
2571*5e7646d2SAndroid Build Coastguard Worker /*
2572*5e7646d2SAndroid Build Coastguard Worker * Only process "add" data...
2573*5e7646d2SAndroid Build Coastguard Worker */
2574*5e7646d2SAndroid Build Coastguard Worker
2575*5e7646d2SAndroid Build Coastguard Worker (void)sdRef;
2576*5e7646d2SAndroid Build Coastguard Worker (void)flags;
2577*5e7646d2SAndroid Build Coastguard Worker (void)interfaceIndex;
2578*5e7646d2SAndroid Build Coastguard Worker (void)fullName;
2579*5e7646d2SAndroid Build Coastguard Worker
2580*5e7646d2SAndroid Build Coastguard Worker if (errorCode != kDNSServiceErr_NoError)
2581*5e7646d2SAndroid Build Coastguard Worker {
2582*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ippfind: Unable to browse or resolve: %s"),
2583*5e7646d2SAndroid Build Coastguard Worker dnssd_error_string(errorCode));
2584*5e7646d2SAndroid Build Coastguard Worker bonjour_error = 1;
2585*5e7646d2SAndroid Build Coastguard Worker return;
2586*5e7646d2SAndroid Build Coastguard Worker }
2587*5e7646d2SAndroid Build Coastguard Worker
2588*5e7646d2SAndroid Build Coastguard Worker service->is_resolved = 1;
2589*5e7646d2SAndroid Build Coastguard Worker service->host = strdup(hostTarget);
2590*5e7646d2SAndroid Build Coastguard Worker service->port = ntohs(port);
2591*5e7646d2SAndroid Build Coastguard Worker
2592*5e7646d2SAndroid Build Coastguard Worker value = service->host + strlen(service->host) - 1;
2593*5e7646d2SAndroid Build Coastguard Worker if (value >= service->host && *value == '.')
2594*5e7646d2SAndroid Build Coastguard Worker *value = '\0';
2595*5e7646d2SAndroid Build Coastguard Worker
2596*5e7646d2SAndroid Build Coastguard Worker /*
2597*5e7646d2SAndroid Build Coastguard Worker * Loop through the TXT key/value pairs and add them to an array...
2598*5e7646d2SAndroid Build Coastguard Worker */
2599*5e7646d2SAndroid Build Coastguard Worker
2600*5e7646d2SAndroid Build Coastguard Worker for (txtEnd = txtRecord + txtLen; txtRecord < txtEnd; txtRecord += valueLen)
2601*5e7646d2SAndroid Build Coastguard Worker {
2602*5e7646d2SAndroid Build Coastguard Worker /*
2603*5e7646d2SAndroid Build Coastguard Worker * Ignore bogus strings...
2604*5e7646d2SAndroid Build Coastguard Worker */
2605*5e7646d2SAndroid Build Coastguard Worker
2606*5e7646d2SAndroid Build Coastguard Worker valueLen = *txtRecord++;
2607*5e7646d2SAndroid Build Coastguard Worker
2608*5e7646d2SAndroid Build Coastguard Worker memcpy(key, txtRecord, valueLen);
2609*5e7646d2SAndroid Build Coastguard Worker key[valueLen] = '\0';
2610*5e7646d2SAndroid Build Coastguard Worker
2611*5e7646d2SAndroid Build Coastguard Worker if ((value = strchr(key, '=')) == NULL)
2612*5e7646d2SAndroid Build Coastguard Worker continue;
2613*5e7646d2SAndroid Build Coastguard Worker
2614*5e7646d2SAndroid Build Coastguard Worker *value++ = '\0';
2615*5e7646d2SAndroid Build Coastguard Worker
2616*5e7646d2SAndroid Build Coastguard Worker /*
2617*5e7646d2SAndroid Build Coastguard Worker * Add to array of TXT values...
2618*5e7646d2SAndroid Build Coastguard Worker */
2619*5e7646d2SAndroid Build Coastguard Worker
2620*5e7646d2SAndroid Build Coastguard Worker service->num_txt = cupsAddOption(key, value, service->num_txt,
2621*5e7646d2SAndroid Build Coastguard Worker &(service->txt));
2622*5e7646d2SAndroid Build Coastguard Worker }
2623*5e7646d2SAndroid Build Coastguard Worker
2624*5e7646d2SAndroid Build Coastguard Worker set_service_uri(service);
2625*5e7646d2SAndroid Build Coastguard Worker }
2626*5e7646d2SAndroid Build Coastguard Worker
2627*5e7646d2SAndroid Build Coastguard Worker
2628*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_AVAHI)
2629*5e7646d2SAndroid Build Coastguard Worker static void
resolve_callback(AvahiServiceResolver * resolver,AvahiIfIndex interface,AvahiProtocol protocol,AvahiResolverEvent event,const char * serviceName,const char * regtype,const char * replyDomain,const char * hostTarget,const AvahiAddress * address,uint16_t port,AvahiStringList * txt,AvahiLookupResultFlags flags,void * context)2630*5e7646d2SAndroid Build Coastguard Worker resolve_callback(
2631*5e7646d2SAndroid Build Coastguard Worker AvahiServiceResolver *resolver, /* I - Resolver */
2632*5e7646d2SAndroid Build Coastguard Worker AvahiIfIndex interface, /* I - Interface */
2633*5e7646d2SAndroid Build Coastguard Worker AvahiProtocol protocol, /* I - Address protocol */
2634*5e7646d2SAndroid Build Coastguard Worker AvahiResolverEvent event, /* I - Event */
2635*5e7646d2SAndroid Build Coastguard Worker const char *serviceName,/* I - Service name */
2636*5e7646d2SAndroid Build Coastguard Worker const char *regtype, /* I - Registration type */
2637*5e7646d2SAndroid Build Coastguard Worker const char *replyDomain,/* I - Domain name */
2638*5e7646d2SAndroid Build Coastguard Worker const char *hostTarget, /* I - FQDN */
2639*5e7646d2SAndroid Build Coastguard Worker const AvahiAddress *address, /* I - Address */
2640*5e7646d2SAndroid Build Coastguard Worker uint16_t port, /* I - Port number */
2641*5e7646d2SAndroid Build Coastguard Worker AvahiStringList *txt, /* I - TXT records */
2642*5e7646d2SAndroid Build Coastguard Worker AvahiLookupResultFlags flags, /* I - Lookup flags */
2643*5e7646d2SAndroid Build Coastguard Worker void *context) /* I - Service */
2644*5e7646d2SAndroid Build Coastguard Worker {
2645*5e7646d2SAndroid Build Coastguard Worker char key[256], /* TXT key */
2646*5e7646d2SAndroid Build Coastguard Worker *value; /* TXT value */
2647*5e7646d2SAndroid Build Coastguard Worker ippfind_srv_t *service = (ippfind_srv_t *)context;
2648*5e7646d2SAndroid Build Coastguard Worker /* Service */
2649*5e7646d2SAndroid Build Coastguard Worker AvahiStringList *current; /* Current TXT key/value pair */
2650*5e7646d2SAndroid Build Coastguard Worker
2651*5e7646d2SAndroid Build Coastguard Worker
2652*5e7646d2SAndroid Build Coastguard Worker (void)address;
2653*5e7646d2SAndroid Build Coastguard Worker
2654*5e7646d2SAndroid Build Coastguard Worker if (event != AVAHI_RESOLVER_FOUND)
2655*5e7646d2SAndroid Build Coastguard Worker {
2656*5e7646d2SAndroid Build Coastguard Worker bonjour_error = 1;
2657*5e7646d2SAndroid Build Coastguard Worker
2658*5e7646d2SAndroid Build Coastguard Worker avahi_service_resolver_free(resolver);
2659*5e7646d2SAndroid Build Coastguard Worker avahi_simple_poll_quit(avahi_poll);
2660*5e7646d2SAndroid Build Coastguard Worker return;
2661*5e7646d2SAndroid Build Coastguard Worker }
2662*5e7646d2SAndroid Build Coastguard Worker
2663*5e7646d2SAndroid Build Coastguard Worker service->is_resolved = 1;
2664*5e7646d2SAndroid Build Coastguard Worker service->host = strdup(hostTarget);
2665*5e7646d2SAndroid Build Coastguard Worker service->port = port;
2666*5e7646d2SAndroid Build Coastguard Worker
2667*5e7646d2SAndroid Build Coastguard Worker value = service->host + strlen(service->host) - 1;
2668*5e7646d2SAndroid Build Coastguard Worker if (value >= service->host && *value == '.')
2669*5e7646d2SAndroid Build Coastguard Worker *value = '\0';
2670*5e7646d2SAndroid Build Coastguard Worker
2671*5e7646d2SAndroid Build Coastguard Worker /*
2672*5e7646d2SAndroid Build Coastguard Worker * Loop through the TXT key/value pairs and add them to an array...
2673*5e7646d2SAndroid Build Coastguard Worker */
2674*5e7646d2SAndroid Build Coastguard Worker
2675*5e7646d2SAndroid Build Coastguard Worker for (current = txt; current; current = current->next)
2676*5e7646d2SAndroid Build Coastguard Worker {
2677*5e7646d2SAndroid Build Coastguard Worker /*
2678*5e7646d2SAndroid Build Coastguard Worker * Ignore bogus strings...
2679*5e7646d2SAndroid Build Coastguard Worker */
2680*5e7646d2SAndroid Build Coastguard Worker
2681*5e7646d2SAndroid Build Coastguard Worker if (current->size > (sizeof(key) - 1))
2682*5e7646d2SAndroid Build Coastguard Worker continue;
2683*5e7646d2SAndroid Build Coastguard Worker
2684*5e7646d2SAndroid Build Coastguard Worker memcpy(key, current->text, current->size);
2685*5e7646d2SAndroid Build Coastguard Worker key[current->size] = '\0';
2686*5e7646d2SAndroid Build Coastguard Worker
2687*5e7646d2SAndroid Build Coastguard Worker if ((value = strchr(key, '=')) == NULL)
2688*5e7646d2SAndroid Build Coastguard Worker continue;
2689*5e7646d2SAndroid Build Coastguard Worker
2690*5e7646d2SAndroid Build Coastguard Worker *value++ = '\0';
2691*5e7646d2SAndroid Build Coastguard Worker
2692*5e7646d2SAndroid Build Coastguard Worker /*
2693*5e7646d2SAndroid Build Coastguard Worker * Add to array of TXT values...
2694*5e7646d2SAndroid Build Coastguard Worker */
2695*5e7646d2SAndroid Build Coastguard Worker
2696*5e7646d2SAndroid Build Coastguard Worker service->num_txt = cupsAddOption(key, value, service->num_txt,
2697*5e7646d2SAndroid Build Coastguard Worker &(service->txt));
2698*5e7646d2SAndroid Build Coastguard Worker }
2699*5e7646d2SAndroid Build Coastguard Worker
2700*5e7646d2SAndroid Build Coastguard Worker set_service_uri(service);
2701*5e7646d2SAndroid Build Coastguard Worker }
2702*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD */
2703*5e7646d2SAndroid Build Coastguard Worker
2704*5e7646d2SAndroid Build Coastguard Worker
2705*5e7646d2SAndroid Build Coastguard Worker /*
2706*5e7646d2SAndroid Build Coastguard Worker * 'set_service_uri()' - Set the URI of the service.
2707*5e7646d2SAndroid Build Coastguard Worker */
2708*5e7646d2SAndroid Build Coastguard Worker
2709*5e7646d2SAndroid Build Coastguard Worker static void
set_service_uri(ippfind_srv_t * service)2710*5e7646d2SAndroid Build Coastguard Worker set_service_uri(ippfind_srv_t *service) /* I - Service */
2711*5e7646d2SAndroid Build Coastguard Worker {
2712*5e7646d2SAndroid Build Coastguard Worker char uri[1024]; /* URI */
2713*5e7646d2SAndroid Build Coastguard Worker const char *path, /* Resource path */
2714*5e7646d2SAndroid Build Coastguard Worker *scheme; /* URI scheme */
2715*5e7646d2SAndroid Build Coastguard Worker
2716*5e7646d2SAndroid Build Coastguard Worker
2717*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(service->regtype, "_http.", 6))
2718*5e7646d2SAndroid Build Coastguard Worker {
2719*5e7646d2SAndroid Build Coastguard Worker scheme = "http";
2720*5e7646d2SAndroid Build Coastguard Worker path = cupsGetOption("path", service->num_txt, service->txt);
2721*5e7646d2SAndroid Build Coastguard Worker }
2722*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(service->regtype, "_https.", 7))
2723*5e7646d2SAndroid Build Coastguard Worker {
2724*5e7646d2SAndroid Build Coastguard Worker scheme = "https";
2725*5e7646d2SAndroid Build Coastguard Worker path = cupsGetOption("path", service->num_txt, service->txt);
2726*5e7646d2SAndroid Build Coastguard Worker }
2727*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(service->regtype, "_ipp.", 5))
2728*5e7646d2SAndroid Build Coastguard Worker {
2729*5e7646d2SAndroid Build Coastguard Worker scheme = "ipp";
2730*5e7646d2SAndroid Build Coastguard Worker path = cupsGetOption("rp", service->num_txt, service->txt);
2731*5e7646d2SAndroid Build Coastguard Worker }
2732*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(service->regtype, "_ipps.", 6))
2733*5e7646d2SAndroid Build Coastguard Worker {
2734*5e7646d2SAndroid Build Coastguard Worker scheme = "ipps";
2735*5e7646d2SAndroid Build Coastguard Worker path = cupsGetOption("rp", service->num_txt, service->txt);
2736*5e7646d2SAndroid Build Coastguard Worker }
2737*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(service->regtype, "_printer.", 9))
2738*5e7646d2SAndroid Build Coastguard Worker {
2739*5e7646d2SAndroid Build Coastguard Worker scheme = "lpd";
2740*5e7646d2SAndroid Build Coastguard Worker path = cupsGetOption("rp", service->num_txt, service->txt);
2741*5e7646d2SAndroid Build Coastguard Worker }
2742*5e7646d2SAndroid Build Coastguard Worker else
2743*5e7646d2SAndroid Build Coastguard Worker return;
2744*5e7646d2SAndroid Build Coastguard Worker
2745*5e7646d2SAndroid Build Coastguard Worker if (!path || !*path)
2746*5e7646d2SAndroid Build Coastguard Worker path = "/";
2747*5e7646d2SAndroid Build Coastguard Worker
2748*5e7646d2SAndroid Build Coastguard Worker if (*path == '/')
2749*5e7646d2SAndroid Build Coastguard Worker {
2750*5e7646d2SAndroid Build Coastguard Worker service->resource = strdup(path);
2751*5e7646d2SAndroid Build Coastguard Worker }
2752*5e7646d2SAndroid Build Coastguard Worker else
2753*5e7646d2SAndroid Build Coastguard Worker {
2754*5e7646d2SAndroid Build Coastguard Worker snprintf(uri, sizeof(uri), "/%s", path);
2755*5e7646d2SAndroid Build Coastguard Worker service->resource = strdup(uri);
2756*5e7646d2SAndroid Build Coastguard Worker }
2757*5e7646d2SAndroid Build Coastguard Worker
2758*5e7646d2SAndroid Build Coastguard Worker httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), scheme, NULL,
2759*5e7646d2SAndroid Build Coastguard Worker service->host, service->port, service->resource);
2760*5e7646d2SAndroid Build Coastguard Worker service->uri = strdup(uri);
2761*5e7646d2SAndroid Build Coastguard Worker }
2762*5e7646d2SAndroid Build Coastguard Worker
2763*5e7646d2SAndroid Build Coastguard Worker
2764*5e7646d2SAndroid Build Coastguard Worker /*
2765*5e7646d2SAndroid Build Coastguard Worker * 'show_usage()' - Show program usage.
2766*5e7646d2SAndroid Build Coastguard Worker */
2767*5e7646d2SAndroid Build Coastguard Worker
2768*5e7646d2SAndroid Build Coastguard Worker static void
show_usage(void)2769*5e7646d2SAndroid Build Coastguard Worker show_usage(void)
2770*5e7646d2SAndroid Build Coastguard Worker {
2771*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("Usage: ippfind [options] regtype[,subtype]"
2772*5e7646d2SAndroid Build Coastguard Worker "[.domain.] ... [expression]\n"
2773*5e7646d2SAndroid Build Coastguard Worker " ippfind [options] name[.regtype[.domain.]] "
2774*5e7646d2SAndroid Build Coastguard Worker "... [expression]\n"
2775*5e7646d2SAndroid Build Coastguard Worker " ippfind --help\n"
2776*5e7646d2SAndroid Build Coastguard Worker " ippfind --version"));
2777*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("Options:"));
2778*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-4 Connect using IPv4"));
2779*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-6 Connect using IPv6"));
2780*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-T seconds Set the browse timeout in seconds"));
2781*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-V version Set default IPP version"));
2782*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--version Show program version"));
2783*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("Expressions:"));
2784*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-P number[-number] Match port to number or range"));
2785*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-d regex Match domain to regular expression"));
2786*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-h regex Match hostname to regular expression"));
2787*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-l List attributes"));
2788*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-n regex Match service name to regular expression"));
2789*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-N name Match service name to literal name value"));
2790*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-p Print URI if true"));
2791*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-q Quietly report match via exit code"));
2792*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-r True if service is remote"));
2793*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-s Print service name if true"));
2794*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-t key True if the TXT record contains the key"));
2795*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-u regex Match URI to regular expression"));
2796*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("-x utility [argument ...] ;\n"
2797*5e7646d2SAndroid Build Coastguard Worker " Execute program if true"));
2798*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--domain regex Match domain to regular expression"));
2799*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--exec utility [argument ...] ;\n"
2800*5e7646d2SAndroid Build Coastguard Worker " Execute program if true"));
2801*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--host regex Match hostname to regular expression"));
2802*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--literal-name name Match service name to literal name value"));
2803*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--local True if service is local"));
2804*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--ls List attributes"));
2805*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--name regex Match service name to regular expression"));
2806*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--path regex Match resource path to regular expression"));
2807*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--port number[-number] Match port to number or range"));
2808*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--print Print URI if true"));
2809*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--print-name Print service name if true"));
2810*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--quiet Quietly report match via exit code"));
2811*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--remote True if service is remote"));
2812*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--txt key True if the TXT record contains the key"));
2813*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--txt-* regex Match TXT record key to regular expression"));
2814*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--uri regex Match URI to regular expression"));
2815*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("Modifiers:"));
2816*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("( expressions ) Group expressions"));
2817*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("! expression Unary NOT of expression"));
2818*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--not expression Unary NOT of expression"));
2819*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--false Always false"));
2820*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("--true Always true"));
2821*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("expression expression Logical AND"));
2822*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("expression --and expression\n"
2823*5e7646d2SAndroid Build Coastguard Worker " Logical AND"));
2824*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("expression --or expression\n"
2825*5e7646d2SAndroid Build Coastguard Worker " Logical OR"));
2826*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("Substitutions:"));
2827*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{} URI"));
2828*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_domain} Domain name"));
2829*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_hostname} Fully-qualified domain name"));
2830*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_name} Service instance name"));
2831*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_port} Port number"));
2832*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_regtype} DNS-SD registration type"));
2833*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_scheme} URI scheme"));
2834*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{service_uri} URI"));
2835*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("{txt_*} Value of TXT record key"));
2836*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("Environment Variables:"));
2837*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_DOMAIN Domain name"));
2838*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_HOSTNAME\n"
2839*5e7646d2SAndroid Build Coastguard Worker " Fully-qualified domain name"));
2840*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_NAME Service instance name"));
2841*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_PORT Port number"));
2842*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_REGTYPE DNS-SD registration type"));
2843*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_SCHEME URI scheme"));
2844*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_SERVICE_URI URI"));
2845*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, _("IPPFIND_TXT_* Value of TXT record key"));
2846*5e7646d2SAndroid Build Coastguard Worker
2847*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_TRUE);
2848*5e7646d2SAndroid Build Coastguard Worker }
2849*5e7646d2SAndroid Build Coastguard Worker
2850*5e7646d2SAndroid Build Coastguard Worker
2851*5e7646d2SAndroid Build Coastguard Worker /*
2852*5e7646d2SAndroid Build Coastguard Worker * 'show_version()' - Show program version.
2853*5e7646d2SAndroid Build Coastguard Worker */
2854*5e7646d2SAndroid Build Coastguard Worker
2855*5e7646d2SAndroid Build Coastguard Worker static void
show_version(void)2856*5e7646d2SAndroid Build Coastguard Worker show_version(void)
2857*5e7646d2SAndroid Build Coastguard Worker {
2858*5e7646d2SAndroid Build Coastguard Worker _cupsLangPuts(stderr, CUPS_SVERSION);
2859*5e7646d2SAndroid Build Coastguard Worker
2860*5e7646d2SAndroid Build Coastguard Worker exit(IPPFIND_EXIT_TRUE);
2861*5e7646d2SAndroid Build Coastguard Worker }
2862