xref: /aosp_15_r20/external/libcups/tools/ippfind.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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