xref: /freebsd/contrib/pkgconf/cli/main.c (revision a3cefe7f2b4df0f70ff92d4570ce18e517af43ec)
1 /*
2  * main.c
3  * main() routine, printer functions
4  *
5  * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
6  *     pkgconf authors (see AUTHORS).
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * This software is provided 'as is' and without any warranty, express or
13  * implied.  In no event shall the authors be liable for any damages arising
14  * from the use of this software.
15  */
16 
17 #include "libpkgconf/config.h"
18 #include <libpkgconf/stdinc.h>
19 #include <libpkgconf/libpkgconf.h>
20 #include "getopt_long.h"
21 #ifndef PKGCONF_LITE
22 #include "renderer-msvc.h"
23 #endif
24 #ifdef _WIN32
25 #include <io.h>     /* for _setmode() */
26 #include <fcntl.h>
27 #endif
28 
29 #define PKG_CFLAGS_ONLY_I		(((uint64_t) 1) << 2)
30 #define PKG_CFLAGS_ONLY_OTHER		(((uint64_t) 1) << 3)
31 #define PKG_CFLAGS			(PKG_CFLAGS_ONLY_I|PKG_CFLAGS_ONLY_OTHER)
32 #define PKG_LIBS_ONLY_LDPATH		(((uint64_t) 1) << 5)
33 #define PKG_LIBS_ONLY_LIBNAME		(((uint64_t) 1) << 6)
34 #define PKG_LIBS_ONLY_OTHER		(((uint64_t) 1) << 7)
35 #define PKG_LIBS			(PKG_LIBS_ONLY_LDPATH|PKG_LIBS_ONLY_LIBNAME|PKG_LIBS_ONLY_OTHER)
36 #define PKG_MODVERSION			(((uint64_t) 1) << 8)
37 #define PKG_REQUIRES			(((uint64_t) 1) << 9)
38 #define PKG_REQUIRES_PRIVATE		(((uint64_t) 1) << 10)
39 #define PKG_VARIABLES			(((uint64_t) 1) << 11)
40 #define PKG_DIGRAPH			(((uint64_t) 1) << 12)
41 #define PKG_KEEP_SYSTEM_CFLAGS		(((uint64_t) 1) << 13)
42 #define PKG_KEEP_SYSTEM_LIBS		(((uint64_t) 1) << 14)
43 #define PKG_VERSION			(((uint64_t) 1) << 15)
44 #define PKG_ABOUT			(((uint64_t) 1) << 16)
45 #define PKG_ENV_ONLY			(((uint64_t) 1) << 17)
46 #define PKG_ERRORS_ON_STDOUT		(((uint64_t) 1) << 18)
47 #define PKG_SILENCE_ERRORS		(((uint64_t) 1) << 19)
48 #define PKG_IGNORE_CONFLICTS		(((uint64_t) 1) << 20)
49 #define PKG_STATIC			(((uint64_t) 1) << 21)
50 #define PKG_NO_UNINSTALLED		(((uint64_t) 1) << 22)
51 #define PKG_UNINSTALLED			(((uint64_t) 1) << 23)
52 #define PKG_LIST			(((uint64_t) 1) << 24)
53 #define PKG_HELP			(((uint64_t) 1) << 25)
54 #define PKG_PRINT_ERRORS		(((uint64_t) 1) << 26)
55 #define PKG_SIMULATE			(((uint64_t) 1) << 27)
56 #define PKG_NO_CACHE			(((uint64_t) 1) << 28)
57 #define PKG_PROVIDES			(((uint64_t) 1) << 29)
58 #define PKG_VALIDATE			(((uint64_t) 1) << 30)
59 #define PKG_LIST_PACKAGE_NAMES		(((uint64_t) 1) << 31)
60 #define PKG_NO_PROVIDES			(((uint64_t) 1) << 32)
61 #define PKG_PURE			(((uint64_t) 1) << 33)
62 #define PKG_PATH			(((uint64_t) 1) << 34)
63 #define PKG_DEFINE_PREFIX		(((uint64_t) 1) << 35)
64 #define PKG_DONT_DEFINE_PREFIX		(((uint64_t) 1) << 36)
65 #define PKG_DONT_RELOCATE_PATHS		(((uint64_t) 1) << 37)
66 #define PKG_DEBUG			(((uint64_t) 1) << 38)
67 #define PKG_SHORT_ERRORS		(((uint64_t) 1) << 39)
68 #define PKG_EXISTS			(((uint64_t) 1) << 40)
69 #define PKG_MSVC_SYNTAX			(((uint64_t) 1) << 41)
70 #define PKG_INTERNAL_CFLAGS		(((uint64_t) 1) << 42)
71 #define PKG_DUMP_PERSONALITY		(((uint64_t) 1) << 43)
72 #define PKG_SHARED			(((uint64_t) 1) << 44)
73 #define PKG_DUMP_LICENSE		(((uint64_t) 1) << 45)
74 #define PKG_SOLUTION			(((uint64_t) 1) << 46)
75 #define PKG_EXISTS_CFLAGS		(((uint64_t) 1) << 47)
76 #define PKG_FRAGMENT_TREE		(((uint64_t) 1) << 48)
77 
78 static pkgconf_client_t pkg_client;
79 static const pkgconf_fragment_render_ops_t *want_render_ops = NULL;
80 
81 static uint64_t want_flags;
82 static int verbosity = 0;
83 static int maximum_traverse_depth = 2000;
84 static size_t maximum_package_count = 0;
85 
86 static char *want_variable = NULL;
87 static char *want_fragment_filter = NULL;
88 
89 FILE *error_msgout = NULL;
90 FILE *logfile_out = NULL;
91 
92 static bool
error_handler(const char * msg,const pkgconf_client_t * client,void * data)93 error_handler(const char *msg, const pkgconf_client_t *client, void *data)
94 {
95 	(void) client;
96 	(void) data;
97 	fprintf(error_msgout, "%s", msg);
98 	return true;
99 }
100 
101 static bool
print_list_entry(const pkgconf_pkg_t * entry,void * data)102 print_list_entry(const pkgconf_pkg_t *entry, void *data)
103 {
104 	(void) data;
105 
106 	if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED)
107 		return false;
108 
109 	printf("%-30s %s - %s\n", entry->id, entry->realname, entry->description);
110 
111 	return false;
112 }
113 
114 static bool
print_package_entry(const pkgconf_pkg_t * entry,void * data)115 print_package_entry(const pkgconf_pkg_t *entry, void *data)
116 {
117 	(void) data;
118 
119 	if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED)
120 		return false;
121 
122 	printf("%s\n", entry->id);
123 
124 	return false;
125 }
126 
127 static bool
filter_cflags(const pkgconf_client_t * client,const pkgconf_fragment_t * frag,void * data)128 filter_cflags(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data)
129 {
130 	int got_flags = 0;
131 	(void) client;
132 	(void) data;
133 
134 	if (!(want_flags & PKG_KEEP_SYSTEM_CFLAGS) && pkgconf_fragment_has_system_dir(client, frag))
135 		return false;
136 
137 	if (want_fragment_filter != NULL && (strchr(want_fragment_filter, frag->type) == NULL || !frag->type))
138 		return false;
139 
140 	if (frag->type == 'I')
141 		got_flags = PKG_CFLAGS_ONLY_I;
142 	else
143 		got_flags = PKG_CFLAGS_ONLY_OTHER;
144 
145 	return (want_flags & got_flags) != 0;
146 }
147 
148 static bool
filter_libs(const pkgconf_client_t * client,const pkgconf_fragment_t * frag,void * data)149 filter_libs(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data)
150 {
151 	int got_flags = 0;
152 	(void) client;
153 	(void) data;
154 
155 	if (!(want_flags & PKG_KEEP_SYSTEM_LIBS) && pkgconf_fragment_has_system_dir(client, frag))
156 		return false;
157 
158 	if (want_fragment_filter != NULL && (strchr(want_fragment_filter, frag->type) == NULL || !frag->type))
159 		return false;
160 
161 	switch (frag->type)
162 	{
163 		case 'L': got_flags = PKG_LIBS_ONLY_LDPATH; break;
164 		case 'l': got_flags = PKG_LIBS_ONLY_LIBNAME; break;
165 		default: got_flags = PKG_LIBS_ONLY_OTHER; break;
166 	}
167 
168 	return (want_flags & got_flags) != 0;
169 }
170 
171 static void
print_variables(pkgconf_pkg_t * pkg)172 print_variables(pkgconf_pkg_t *pkg)
173 {
174 	pkgconf_node_t *node;
175 
176 	PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, node)
177 	{
178 		pkgconf_tuple_t *tuple = node->data;
179 
180 		printf("%s\n", tuple->key);
181 	}
182 }
183 
184 static void
print_requires(pkgconf_pkg_t * pkg)185 print_requires(pkgconf_pkg_t *pkg)
186 {
187 	pkgconf_node_t *node;
188 
189 	PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
190 	{
191 		pkgconf_dependency_t *dep = node->data;
192 
193 		printf("%s", dep->package);
194 
195 		if (dep->version != NULL)
196 			printf(" %s %s", pkgconf_pkg_get_comparator(dep), dep->version);
197 
198 		printf("\n");
199 	}
200 }
201 
202 static void
print_requires_private(pkgconf_pkg_t * pkg)203 print_requires_private(pkgconf_pkg_t *pkg)
204 {
205 	pkgconf_node_t *node;
206 
207 	PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
208 	{
209 		pkgconf_dependency_t *dep = node->data;
210 
211 		printf("%s", dep->package);
212 
213 		if (dep->version != NULL)
214 			printf(" %s %s", pkgconf_pkg_get_comparator(dep), dep->version);
215 
216 		printf("\n");
217 	}
218 }
219 
220 static void
print_provides(pkgconf_pkg_t * pkg)221 print_provides(pkgconf_pkg_t *pkg)
222 {
223 	pkgconf_node_t *node;
224 
225 	PKGCONF_FOREACH_LIST_ENTRY(pkg->provides.head, node)
226 	{
227 		pkgconf_dependency_t *dep = node->data;
228 
229 		printf("%s", dep->package);
230 
231 		if (dep->version != NULL)
232 			printf(" %s %s", pkgconf_pkg_get_comparator(dep), dep->version);
233 
234 		printf("\n");
235 	}
236 }
237 
238 static bool
apply_provides(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)239 apply_provides(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
240 {
241 	pkgconf_node_t *iter;
242 	(void) client;
243 	(void) unused;
244 	(void) maxdepth;
245 
246 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
247 	{
248 		pkgconf_dependency_t *dep = iter->data;
249 		pkgconf_pkg_t *pkg = dep->match;
250 
251 		print_provides(pkg);
252 	}
253 
254 	return true;
255 }
256 
257 #ifndef PKGCONF_LITE
258 static void
print_digraph_node(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * data)259 print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
260 {
261 	pkgconf_node_t *node;
262 	(void) client;
263 	pkgconf_pkg_t **last_seen = data;
264 
265 	if(pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
266 		return;
267 
268 	if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE)
269 		printf("\"%s\" [fontname=Sans fontsize=8 fontcolor=gray color=gray]\n", pkg->id);
270 	else
271 		printf("\"%s\" [fontname=Sans fontsize=8]\n", pkg->id);
272 
273 	if (last_seen != NULL)
274 	{
275 		if (*last_seen != NULL)
276 			printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=red]\n", (*last_seen)->id, pkg->id);
277 
278 		*last_seen = pkg;
279 	}
280 
281 	PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
282 	{
283 		pkgconf_dependency_t *dep = node->data;
284 		const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package;
285 
286 		if ((dep->flags & PKGCONF_PKG_DEPF_PRIVATE) == 0)
287 			printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg->id, dep_id);
288 		else
289 			printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id);
290 	}
291 
292 	PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
293 	{
294 		pkgconf_dependency_t *dep = node->data;
295 		const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package;
296 
297 		printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id);
298 	}
299 }
300 
301 static bool
apply_digraph(pkgconf_client_t * client,pkgconf_pkg_t * world,void * data,int maxdepth)302 apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
303 {
304 	int eflag;
305 	pkgconf_list_t *list = data;
306 	pkgconf_pkg_t *last_seen = NULL;
307 	pkgconf_node_t *iter;
308 
309 	printf("digraph deptree {\n");
310 	printf("edge [color=blue len=7.5 fontname=Sans fontsize=8]\n");
311 	printf("node [fontname=Sans fontsize=8]\n");
312 	printf("\"user:request\" [fontname=Sans fontsize=8]\n");
313 
314 	PKGCONF_FOREACH_LIST_ENTRY(list->head, iter)
315 	{
316 		pkgconf_queue_t *pkgq = iter->data;
317 		pkgconf_pkg_t *pkg = pkgconf_pkg_find(client, pkgq->package);
318 		printf("\"user:request\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg == NULL ? pkgq->package : pkg->id);
319 		if (pkg != NULL)
320 			pkgconf_pkg_unref(client, pkg);
321 	}
322 
323 	eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, &last_seen, maxdepth, 0);
324 
325 	if (eflag != PKGCONF_PKG_ERRF_OK)
326 		return false;
327 
328 	printf("}\n");
329 	return true;
330 }
331 
332 static void
print_solution_node(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * unused)333 print_solution_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
334 {
335 	(void) client;
336 	(void) unused;
337 
338 	printf("%s (%"PRIu64")%s\n", pkg->id, pkg->identifier, (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) == PKGCONF_PKG_PROPF_VISITED_PRIVATE ? " [private]" : "");
339 }
340 
341 static bool
apply_print_solution(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)342 apply_print_solution(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
343 {
344 	int eflag;
345 
346 	eflag = pkgconf_pkg_traverse(client, world, print_solution_node, unused, maxdepth, 0);
347 
348 	return eflag == PKGCONF_PKG_ERRF_OK;
349 }
350 #endif
351 
352 static bool
apply_modversion(pkgconf_client_t * client,pkgconf_pkg_t * world,void * data,int maxdepth)353 apply_modversion(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
354 {
355 	pkgconf_node_t *queue_iter;
356 	pkgconf_list_t *pkgq = data;
357 	(void) client;
358 	(void) maxdepth;
359 
360 	PKGCONF_FOREACH_LIST_ENTRY(pkgq->head, queue_iter)
361 	{
362 		pkgconf_node_t *world_iter;
363 		pkgconf_queue_t *queue_node = queue_iter->data;
364 
365 		PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter)
366 		{
367 			pkgconf_dependency_t *dep = world_iter->data;
368 			pkgconf_pkg_t *pkg = dep->match;
369 
370 			const size_t name_len = strlen(pkg->why);
371 			if (name_len > strlen(queue_node->package) ||
372 			    strncmp(pkg->why, queue_node->package, name_len) ||
373 			    (queue_node->package[name_len] != 0 &&
374 			     !isspace((unsigned char)queue_node->package[name_len]) &&
375 			     !PKGCONF_IS_OPERATOR_CHAR(queue_node->package[name_len])))
376 				continue;
377 
378 			if (pkg->version != NULL) {
379 				if (verbosity)
380 					printf("%s: ", pkg->id);
381 
382 				printf("%s\n", pkg->version);
383 			}
384 
385 			break;
386 		}
387 	}
388 
389 	return true;
390 }
391 
392 static bool
apply_variables(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)393 apply_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
394 {
395 	pkgconf_node_t *iter;
396 	(void) client;
397 	(void) unused;
398 	(void) maxdepth;
399 
400 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
401 	{
402 		pkgconf_dependency_t *dep = iter->data;
403 		pkgconf_pkg_t *pkg = dep->match;
404 
405 		print_variables(pkg);
406 	}
407 
408 	return true;
409 }
410 
411 static bool
apply_path(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)412 apply_path(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
413 {
414 	pkgconf_node_t *iter;
415 	(void) client;
416 	(void) unused;
417 	(void) maxdepth;
418 
419 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
420 	{
421 		pkgconf_dependency_t *dep = iter->data;
422 		pkgconf_pkg_t *pkg = dep->match;
423 
424 		/* a module entry with no filename is either virtual, static (builtin) or synthesized. */
425 		if (pkg->filename != NULL)
426 			printf("%s\n", pkg->filename);
427 	}
428 
429 	return true;
430 }
431 
432 static bool
apply_variable(pkgconf_client_t * client,pkgconf_pkg_t * world,void * variable,int maxdepth)433 apply_variable(pkgconf_client_t *client, pkgconf_pkg_t *world, void *variable, int maxdepth)
434 {
435 	pkgconf_node_t *iter;
436 	(void) maxdepth;
437 
438 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
439 	{
440 		pkgconf_dependency_t *dep = iter->data;
441 		pkgconf_pkg_t *pkg = dep->match;
442 		const char *var;
443 
444 		var = pkgconf_tuple_find(client, &pkg->vars, variable);
445 
446 		if (var != NULL)
447 			printf("%s%s", iter->prev != NULL ? " " : "", var);
448 	}
449 
450 	printf("\n");
451 
452 	return true;
453 }
454 
455 static bool
apply_env_var(const char * prefix,pkgconf_client_t * client,pkgconf_pkg_t * world,int maxdepth,unsigned int (* collect_fn)(pkgconf_client_t * client,pkgconf_pkg_t * world,pkgconf_list_t * list,int maxdepth),bool (* filter_fn)(const pkgconf_client_t * client,const pkgconf_fragment_t * frag,void * data),void (* postprocess_fn)(pkgconf_client_t * client,pkgconf_pkg_t * world,pkgconf_list_t * fragment_list))456 apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth,
457 	unsigned int (*collect_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth),
458 	bool (*filter_fn)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data),
459 	void (*postprocess_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list))
460 {
461 	pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER;
462 	pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER;
463 	unsigned int eflag;
464 	char *render_buf;
465 
466 	eflag = collect_fn(client, world, &unfiltered_list, maxdepth);
467 	if (eflag != PKGCONF_PKG_ERRF_OK)
468 		return false;
469 
470 	pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_fn, NULL);
471 
472 	if (postprocess_fn != NULL)
473 		postprocess_fn(client, world, &filtered_list);
474 
475 	if (filtered_list.head == NULL)
476 		goto out;
477 
478 	render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops);
479 	printf("%s='%s'\n", prefix, render_buf);
480 	free(render_buf);
481 
482 out:
483 	pkgconf_fragment_free(&unfiltered_list);
484 	pkgconf_fragment_free(&filtered_list);
485 
486 	return true;
487 }
488 
489 static void
maybe_add_module_definitions(pkgconf_client_t * client,pkgconf_pkg_t * world,pkgconf_list_t * fragment_list)490 maybe_add_module_definitions(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list)
491 {
492 	pkgconf_node_t *world_iter;
493 
494 	if ((want_flags & PKG_EXISTS_CFLAGS) != PKG_EXISTS_CFLAGS)
495 		return;
496 
497 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter)
498 	{
499 		pkgconf_dependency_t *dep = world_iter->data;
500 		char havebuf[PKGCONF_ITEM_SIZE];
501 		char *p;
502 
503 		if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
504 			continue;
505 
506 		if (dep->match == NULL)
507 			continue;
508 
509 		snprintf(havebuf, sizeof havebuf, "HAVE_%s", dep->match->id);
510 
511 		for (p = havebuf; *p; p++)
512 		{
513 			switch (*p)
514 			{
515 				case ' ':
516 				case '-':
517 					*p = '_';
518 					break;
519 
520 				default:
521 					*p = toupper((unsigned char) *p);
522 			}
523 		}
524 
525 		pkgconf_fragment_insert(client, fragment_list, 'D', havebuf, false);
526 	}
527 }
528 
529 static void
apply_env_variables(pkgconf_client_t * client,pkgconf_pkg_t * world,const char * env_prefix)530 apply_env_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, const char *env_prefix)
531 {
532 	(void) client;
533 	pkgconf_node_t *world_iter;
534 
535 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter)
536 	{
537 		pkgconf_dependency_t *dep = world_iter->data;
538 		pkgconf_pkg_t *pkg = dep->match;
539 		pkgconf_node_t *tuple_iter;
540 
541 		if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
542 			continue;
543 
544 		if (dep->match == NULL)
545 			continue;
546 
547 		PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, tuple_iter)
548 		{
549 			pkgconf_tuple_t *tuple = tuple_iter->data;
550 			char havebuf[PKGCONF_ITEM_SIZE];
551 			char *p;
552 
553 			if (want_variable != NULL && strcmp(want_variable, tuple->key))
554 				continue;
555 
556 			snprintf(havebuf, sizeof havebuf, "%s_%s", env_prefix, tuple->key);
557 
558 			for (p = havebuf; *p; p++)
559 			{
560 				switch (*p)
561 				{
562 					case ' ':
563 					case '-':
564 						*p = '_';
565 						break;
566 
567 					default:
568 						*p = toupper((unsigned char) *p);
569 				}
570 			}
571 
572 			printf("%s='%s'\n", havebuf, tuple->value);
573 		}
574 	}
575 }
576 
577 static bool
apply_env(pkgconf_client_t * client,pkgconf_pkg_t * world,void * env_prefix_p,int maxdepth)578 apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, int maxdepth)
579 {
580 	const char *want_env_prefix = env_prefix_p, *it;
581 	char workbuf[PKGCONF_ITEM_SIZE];
582 
583 	for (it = want_env_prefix; *it != '\0'; it++)
584 		if (!isalpha((unsigned char)*it) &&
585 		    !isdigit((unsigned char)*it))
586 			return false;
587 
588 	snprintf(workbuf, sizeof workbuf, "%s_CFLAGS", want_env_prefix);
589 	if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_cflags, filter_cflags, maybe_add_module_definitions))
590 		return false;
591 
592 	snprintf(workbuf, sizeof workbuf, "%s_LIBS", want_env_prefix);
593 	if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_libs, filter_libs, NULL))
594 		return false;
595 
596 	if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES || want_variable != NULL)
597 		apply_env_variables(client, world, want_env_prefix);
598 
599 	return true;
600 }
601 
602 static bool
apply_cflags(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)603 apply_cflags(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
604 {
605 	pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER;
606 	pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER;
607 	int eflag;
608 	char *render_buf;
609 	(void) unused;
610 
611 	eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth);
612 	if (eflag != PKGCONF_PKG_ERRF_OK)
613 		return false;
614 
615 	pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_cflags, NULL);
616 	maybe_add_module_definitions(client, world, &filtered_list);
617 
618 	if (filtered_list.head == NULL)
619 		goto out;
620 
621 	render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops);
622 	printf("%s", render_buf);
623 	free(render_buf);
624 
625 out:
626 	pkgconf_fragment_free(&unfiltered_list);
627 	pkgconf_fragment_free(&filtered_list);
628 
629 	return true;
630 }
631 
632 static bool
apply_libs(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)633 apply_libs(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
634 {
635 	pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER;
636 	pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER;
637 	int eflag;
638 	char *render_buf;
639 	(void) unused;
640 
641 	eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth);
642 	if (eflag != PKGCONF_PKG_ERRF_OK)
643 		return false;
644 
645 	pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_libs, NULL);
646 
647 	if (filtered_list.head == NULL)
648 		goto out;
649 
650 	render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops);
651 	printf("%s", render_buf);
652 	free(render_buf);
653 
654 out:
655 	pkgconf_fragment_free(&unfiltered_list);
656 	pkgconf_fragment_free(&filtered_list);
657 
658 	return true;
659 }
660 
661 static bool
apply_requires(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)662 apply_requires(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
663 {
664 	pkgconf_node_t *iter;
665 	(void) client;
666 	(void) unused;
667 	(void) maxdepth;
668 
669 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
670 	{
671 		pkgconf_dependency_t *dep = iter->data;
672 		pkgconf_pkg_t *pkg = dep->match;
673 
674 		print_requires(pkg);
675 	}
676 
677 	return true;
678 }
679 
680 static bool
apply_requires_private(pkgconf_client_t * client,pkgconf_pkg_t * world,void * unused,int maxdepth)681 apply_requires_private(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
682 {
683 	pkgconf_node_t *iter;
684 	(void) client;
685 	(void) unused;
686 	(void) maxdepth;
687 
688 	PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
689 	{
690 		pkgconf_dependency_t *dep = iter->data;
691 		pkgconf_pkg_t *pkg = dep->match;
692 
693 		print_requires_private(pkg);
694 	}
695 	return true;
696 }
697 
698 static void
check_uninstalled(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * data)699 check_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
700 {
701 	int *retval = data;
702 	(void) client;
703 
704 	if (pkg->flags & PKGCONF_PKG_PROPF_UNINSTALLED)
705 		*retval = EXIT_SUCCESS;
706 }
707 
708 static bool
apply_uninstalled(pkgconf_client_t * client,pkgconf_pkg_t * world,void * data,int maxdepth)709 apply_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
710 {
711 	int eflag;
712 
713 	eflag = pkgconf_pkg_traverse(client, world, check_uninstalled, data, maxdepth, 0);
714 
715 	if (eflag != PKGCONF_PKG_ERRF_OK)
716 		return false;
717 
718 	return true;
719 }
720 
721 #ifndef PKGCONF_LITE
722 static void
print_graph_node(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * data)723 print_graph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
724 {
725 	pkgconf_node_t *n;
726 
727 	(void) client;
728 	(void) data;
729 
730 	printf("node '%s' {\n", pkg->id);
731 
732 	if (pkg->version != NULL)
733 		printf("    version = '%s';\n", pkg->version);
734 
735 	PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, n)
736 	{
737 		pkgconf_dependency_t *dep = n->data;
738 		printf("    dependency '%s'", dep->package);
739 		if (dep->compare != PKGCONF_CMP_ANY)
740 		{
741 			printf(" {\n");
742 			printf("        comparator = '%s';\n", pkgconf_pkg_get_comparator(dep));
743 			printf("        version = '%s';\n", dep->version);
744 			printf("    };\n");
745 		}
746 		else
747 			printf(";\n");
748 	}
749 
750 	printf("};\n");
751 }
752 
753 static bool
apply_simulate(pkgconf_client_t * client,pkgconf_pkg_t * world,void * data,int maxdepth)754 apply_simulate(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
755 {
756 	int eflag;
757 
758 	eflag = pkgconf_pkg_traverse(client, world, print_graph_node, data, maxdepth, 0);
759 
760 	if (eflag != PKGCONF_PKG_ERRF_OK)
761 		return false;
762 
763 	return true;
764 }
765 #endif
766 
767 static void
print_fragment_tree_branch(pkgconf_list_t * fragment_list,int indent)768 print_fragment_tree_branch(pkgconf_list_t *fragment_list, int indent)
769 {
770 	pkgconf_node_t *iter;
771 
772 	PKGCONF_FOREACH_LIST_ENTRY(fragment_list->head, iter)
773 	{
774 		pkgconf_fragment_t *frag = iter->data;
775 
776 		if (frag->type)
777 			printf("%*s'-%c%s' [type %c]\n", indent, "", frag->type, frag->data, frag->type);
778 		else
779 			printf("%*s'%s' [untyped]\n", indent, "", frag->data);
780 
781 		print_fragment_tree_branch(&frag->children, indent + 2);
782 	}
783 
784 	if (fragment_list->head != NULL)
785 		printf("\n");
786 }
787 
788 static bool
apply_fragment_tree(pkgconf_client_t * client,pkgconf_pkg_t * world,void * data,int maxdepth)789 apply_fragment_tree(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
790 {
791 	pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER;
792 	int eflag;
793 
794 	(void) data;
795 
796 	eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth);
797 	if (eflag != PKGCONF_PKG_ERRF_OK)
798 		return false;
799 
800 	eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth);
801 	if (eflag != PKGCONF_PKG_ERRF_OK)
802 		return false;
803 
804 	print_fragment_tree_branch(&unfiltered_list, 0);
805 	pkgconf_fragment_free(&unfiltered_list);
806 
807 	return true;
808 }
809 
810 static void
print_license(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * data)811 print_license(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
812 {
813 	(void) client;
814 	(void) data;
815 
816 	if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
817 		return;
818 
819 	/* NOASSERTION is the default when the license is unknown, per SPDX spec § 3.15 */
820 	printf("%s: %s\n", pkg->id, pkg->license != NULL ? pkg->license : "NOASSERTION");
821 }
822 
823 static bool
apply_license(pkgconf_client_t * client,pkgconf_pkg_t * world,void * data,int maxdepth)824 apply_license(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
825 {
826 	int eflag;
827 
828 	eflag = pkgconf_pkg_traverse(client, world, print_license, data, maxdepth, 0);
829 
830 	if (eflag != PKGCONF_PKG_ERRF_OK)
831 		return false;
832 
833 	return true;
834 }
835 
836 static void
version(void)837 version(void)
838 {
839 	printf("%s\n", PACKAGE_VERSION);
840 }
841 
842 static void
about(void)843 about(void)
844 {
845 	printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
846 	printf("Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021\n");
847 	printf("    pkgconf authors (see AUTHORS in documentation directory).\n\n");
848 	printf("Permission to use, copy, modify, and/or distribute this software for any\n");
849 	printf("purpose with or without fee is hereby granted, provided that the above\n");
850 	printf("copyright notice and this permission notice appear in all copies.\n\n");
851 	printf("This software is provided 'as is' and without any warranty, express or\n");
852 	printf("implied.  In no event shall the authors be liable for any damages arising\n");
853 	printf("from the use of this software.\n\n");
854 	printf("Report bugs at <%s>.\n", PACKAGE_BUGREPORT);
855 }
856 
857 static void
usage(void)858 usage(void)
859 {
860 	printf("usage: %s [OPTIONS] [LIBRARIES]\n", PACKAGE_NAME);
861 
862 	printf("\nbasic options:\n\n");
863 
864 	printf("  --help                            this message\n");
865 	printf("  --about                           print pkgconf version and license to stdout\n");
866 	printf("  --version                         print supported pkg-config version to stdout\n");
867 	printf("  --verbose                         print additional information\n");
868 	printf("  --atleast-pkgconfig-version       check whether or not pkgconf is compatible\n");
869 	printf("                                    with a specified pkg-config version\n");
870 	printf("  --errors-to-stdout                print all errors on stdout instead of stderr\n");
871 	printf("  --print-errors                    ensure all errors are printed\n");
872 	printf("  --short-errors                    be less verbose about some errors\n");
873 	printf("  --silence-errors                  explicitly be silent about errors\n");
874 	printf("  --list-all                        list all known packages\n");
875 	printf("  --list-package-names              list all known package names\n");
876 #ifndef PKGCONF_LITE
877 	printf("  --simulate                        simulate walking the calculated dependency graph\n");
878 #endif
879 	printf("  --no-cache                        do not cache already seen packages when\n");
880 	printf("                                    walking the dependency graph\n");
881 	printf("  --log-file=filename               write an audit log to a specified file\n");
882 	printf("  --with-path=path                  adds a directory to the search path\n");
883 	printf("  --define-prefix                   override the prefix variable with one that is guessed based on\n");
884 	printf("                                    the location of the .pc file\n");
885 	printf("  --dont-define-prefix              do not override the prefix variable under any circumstances\n");
886 	printf("  --prefix-variable=varname         sets the name of the variable that pkgconf considers\n");
887 	printf("                                    to be the package prefix\n");
888 	printf("  --relocate=path                   relocates a path and exits (mostly for testsuite)\n");
889 	printf("  --dont-relocate-paths             disables path relocation support\n");
890 
891 #ifndef PKGCONF_LITE
892 	printf("\ncross-compilation personality support:\n\n");
893 	printf("  --personality=triplet|filename    sets the personality to 'triplet' or a file named 'filename'\n");
894 	printf("  --dump-personality                dumps details concerning selected personality\n");
895 #endif
896 
897 	printf("\nchecking specific pkg-config database entries:\n\n");
898 
899 	printf("  --atleast-version                 require a specific version of a module\n");
900 	printf("  --exact-version                   require an exact version of a module\n");
901 	printf("  --max-version                     require a maximum version of a module\n");
902 	printf("  --exists                          check whether or not a module exists\n");
903 	printf("  --uninstalled                     check whether or not an uninstalled module will be used\n");
904 	printf("  --no-uninstalled                  never use uninstalled modules when satisfying dependencies\n");
905 	printf("  --no-provides                     do not use 'provides' rules to resolve dependencies\n");
906 	printf("  --maximum-traverse-depth          maximum allowed depth for dependency graph\n");
907 	printf("  --static                          be more aggressive when computing dependency graph\n");
908 	printf("                                    (for static linking)\n");
909 	printf("  --shared                          use a simplified dependency graph (usually default)\n");
910 	printf("  --pure                            optimize a static dependency graph as if it were a normal\n");
911 	printf("                                    dependency graph\n");
912 	printf("  --env-only                        look only for package entries in PKG_CONFIG_PATH\n");
913 	printf("  --ignore-conflicts                ignore 'conflicts' rules in modules\n");
914 	printf("  --validate                        validate specific .pc files for correctness\n");
915 
916 	printf("\nquerying specific pkg-config database fields:\n\n");
917 
918 	printf("  --define-variable=varname=value   define variable 'varname' as 'value'\n");
919 	printf("  --variable=varname                print specified variable entry to stdout\n");
920 	printf("  --cflags                          print required CFLAGS to stdout\n");
921 	printf("  --cflags-only-I                   print required include-dir CFLAGS to stdout\n");
922 	printf("  --cflags-only-other               print required non-include-dir CFLAGS to stdout\n");
923 	printf("  --libs                            print required linker flags to stdout\n");
924 	printf("  --libs-only-L                     print required LDPATH linker flags to stdout\n");
925 	printf("  --libs-only-l                     print required LIBNAME linker flags to stdout\n");
926 	printf("  --libs-only-other                 print required other linker flags to stdout\n");
927 	printf("  --print-requires                  print required dependency frameworks to stdout\n");
928 	printf("  --print-requires-private          print required dependency frameworks for static\n");
929 	printf("                                    linking to stdout\n");
930 	printf("  --print-provides                  print provided dependencies to stdout\n");
931 	printf("  --print-variables                 print all known variables in module to stdout\n");
932 #ifndef PKGCONF_LITE
933 	printf("  --digraph                         print entire dependency graph in graphviz 'dot' format\n");
934 	printf("  --solution                        print dependency graph solution in a simple format\n");
935 #endif
936 	printf("  --keep-system-cflags              keep -I%s entries in cflags output\n", SYSTEM_INCLUDEDIR);
937 	printf("  --keep-system-libs                keep -L%s entries in libs output\n", SYSTEM_LIBDIR);
938 	printf("  --path                            show the exact filenames for any matching .pc files\n");
939 	printf("  --modversion                      print the specified module's version to stdout\n");
940 	printf("  --internal-cflags                 do not filter 'internal' cflags from output\n");
941 	printf("  --license                         print the specified module's license to stdout if known\n");
942 	printf("  --exists-cflags                   add -DHAVE_FOO fragments to cflags for each found module\n");
943 
944 	printf("\nfiltering output:\n\n");
945 #ifndef PKGCONF_LITE
946 	printf("  --msvc-syntax                     print translatable fragments in MSVC syntax\n");
947 #endif
948 	printf("  --fragment-filter=types           filter output fragments to the specified types\n");
949 	printf("  --env=prefix                      print output as shell-compatible environmental variables\n");
950 	printf("  --fragment-tree                   visualize printed CFLAGS/LIBS fragments as a tree\n");
951 
952 	printf("\nreport bugs to <%s>.\n", PACKAGE_BUGREPORT);
953 }
954 
955 static void
relocate_path(const char * path)956 relocate_path(const char *path)
957 {
958 	char buf[PKGCONF_BUFSIZE];
959 
960 	pkgconf_strlcpy(buf, path, sizeof buf);
961 	pkgconf_path_relocate(buf, sizeof buf);
962 
963 	printf("%s\n", buf);
964 }
965 
966 #ifndef PKGCONF_LITE
967 static void
dump_personality(const pkgconf_cross_personality_t * p)968 dump_personality(const pkgconf_cross_personality_t *p)
969 {
970 	pkgconf_node_t *n;
971 
972 	printf("Triplet: %s\n", p->name);
973 
974 	if (p->sysroot_dir)
975 		printf("SysrootDir: %s\n", p->sysroot_dir);
976 
977 	printf("DefaultSearchPaths: ");
978 	PKGCONF_FOREACH_LIST_ENTRY(p->dir_list.head, n)
979 	{
980 		pkgconf_path_t *pn = n->data;
981 		printf("%s ", pn->path);
982 	}
983 
984 	printf("\n");
985 	printf("SystemIncludePaths: ");
986 	PKGCONF_FOREACH_LIST_ENTRY(p->filter_includedirs.head, n)
987 	{
988 		pkgconf_path_t *pn = n->data;
989 		printf("%s ", pn->path);
990 	}
991 
992 	printf("\n");
993 	printf("SystemLibraryPaths: ");
994 	PKGCONF_FOREACH_LIST_ENTRY(p->filter_libdirs.head, n)
995 	{
996 		pkgconf_path_t *pn = n->data;
997 		printf("%s ", pn->path);
998 	}
999 
1000 	printf("\n");
1001 }
1002 
1003 static pkgconf_cross_personality_t *
deduce_personality(char * argv[])1004 deduce_personality(char *argv[])
1005 {
1006 	const char *argv0 = argv[0];
1007 	char *i, *prefix;
1008 	pkgconf_cross_personality_t *out;
1009 
1010 	i = strrchr(argv0, '/');
1011 	if (i != NULL)
1012 		argv0 = i + 1;
1013 
1014 #if defined(_WIN32) || defined(_WIN64)
1015 	i = strrchr(argv0, '\\');
1016 	if (i != NULL)
1017 		argv0 = i + 1;
1018 #endif
1019 
1020 	i = strstr(argv0, "-pkg");
1021 	if (i == NULL)
1022 		return pkgconf_cross_personality_default();
1023 
1024 	prefix = pkgconf_strndup(argv0, i - argv0);
1025 	out = pkgconf_cross_personality_find(prefix);
1026 	free(prefix);
1027 	if (out == NULL)
1028 		return pkgconf_cross_personality_default();
1029 
1030 	return out;
1031 }
1032 #endif
1033 
1034 static void
unveil_handler(const pkgconf_client_t * client,const char * path,const char * permissions)1035 unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions)
1036 {
1037 	(void) client;
1038 
1039 	if (pkgconf_unveil(path, permissions) == -1)
1040 	{
1041 		fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno));
1042 		exit(EXIT_FAILURE);
1043 	}
1044 }
1045 
1046 static bool
unveil_search_paths(const pkgconf_client_t * client,const pkgconf_cross_personality_t * personality)1047 unveil_search_paths(const pkgconf_client_t *client, const pkgconf_cross_personality_t *personality)
1048 {
1049 	pkgconf_node_t *n;
1050 
1051 	if (pkgconf_unveil("/dev/null", "rwc") == -1)
1052 		return false;
1053 
1054 	PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n)
1055 	{
1056 		pkgconf_path_t *pn = n->data;
1057 
1058 		if (pkgconf_unveil(pn->path, "r") == -1)
1059 			return false;
1060 	}
1061 
1062 	PKGCONF_FOREACH_LIST_ENTRY(personality->dir_list.head, n)
1063 	{
1064 		pkgconf_path_t *pn = n->data;
1065 
1066 		if (pkgconf_unveil(pn->path, "r") == -1)
1067 			return false;
1068 	}
1069 
1070 	pkgconf_client_set_unveil_handler(&pkg_client, unveil_handler);
1071 
1072 	return true;
1073 }
1074 
1075 int
main(int argc,char * argv[])1076 main(int argc, char *argv[])
1077 {
1078 	int ret;
1079 	pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER;
1080 	pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER;
1081 	char *builddir;
1082 	char *sysroot_dir;
1083 	char *env_traverse_depth;
1084 	char *required_pkgconfig_version = NULL;
1085 	char *required_exact_module_version = NULL;
1086 	char *required_max_module_version = NULL;
1087 	char *required_module_version = NULL;
1088 	char *logfile_arg = NULL;
1089 	char *want_env_prefix = NULL;
1090 	unsigned int want_client_flags = PKGCONF_PKG_PKGF_NONE;
1091 	pkgconf_cross_personality_t *personality = NULL;
1092 	bool opened_error_msgout = false;
1093 	pkgconf_pkg_t world = {
1094 		.id = "virtual:world",
1095 		.realname = "virtual world package",
1096 		.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
1097 	};
1098 
1099 	if (pkgconf_pledge("stdio rpath wpath cpath unveil", NULL) == -1)
1100 	{
1101 		fprintf(stderr, "pkgconf: pledge failed: %s\n", strerror(errno));
1102 		return EXIT_FAILURE;
1103 	}
1104 
1105 	want_flags = 0;
1106 
1107 #ifdef _WIN32
1108 	/* When running regression tests in cygwin, and building native
1109 	 * executable, tests fail unless native executable outputs unix
1110 	 * line endings.  Come to think of it, this will probably help
1111 	 * real people who use cygwin build environments but native pkgconf, too.
1112 	 */
1113 	_setmode(fileno(stdout), O_BINARY);
1114 	_setmode(fileno(stderr), O_BINARY);
1115 #endif
1116 
1117 	struct pkg_option options[] = {
1118 		{ "version", no_argument, &want_flags, PKG_VERSION|PKG_PRINT_ERRORS, },
1119 		{ "about", no_argument, &want_flags, PKG_ABOUT|PKG_PRINT_ERRORS, },
1120 		{ "atleast-version", required_argument, NULL, 2, },
1121 		{ "atleast-pkgconfig-version", required_argument, NULL, 3, },
1122 		{ "libs", no_argument, &want_flags, PKG_LIBS|PKG_PRINT_ERRORS, },
1123 		{ "cflags", no_argument, &want_flags, PKG_CFLAGS|PKG_PRINT_ERRORS, },
1124 		{ "modversion", no_argument, &want_flags, PKG_MODVERSION|PKG_PRINT_ERRORS, },
1125 		{ "variable", required_argument, NULL, 7, },
1126 		{ "exists", no_argument, &want_flags, PKG_EXISTS, },
1127 		{ "print-errors", no_argument, &want_flags, PKG_PRINT_ERRORS, },
1128 		{ "short-errors", no_argument, &want_flags, PKG_SHORT_ERRORS, },
1129 		{ "maximum-traverse-depth", required_argument, NULL, 11, },
1130 		{ "static", no_argument, &want_flags, PKG_STATIC, },
1131 		{ "shared", no_argument, &want_flags, PKG_SHARED, },
1132 		{ "pure", no_argument, &want_flags, PKG_PURE, },
1133 		{ "print-requires", no_argument, &want_flags, PKG_REQUIRES, },
1134 		{ "print-variables", no_argument, &want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, },
1135 #ifndef PKGCONF_LITE
1136 		{ "digraph", no_argument, &want_flags, PKG_DIGRAPH, },
1137 		{ "solution", no_argument, &want_flags, PKG_SOLUTION, },
1138 #endif
1139 		{ "help", no_argument, &want_flags, PKG_HELP, },
1140 		{ "env-only", no_argument, &want_flags, PKG_ENV_ONLY, },
1141 		{ "print-requires-private", no_argument, &want_flags, PKG_REQUIRES_PRIVATE, },
1142 		{ "cflags-only-I", no_argument, &want_flags, PKG_CFLAGS_ONLY_I|PKG_PRINT_ERRORS, },
1143 		{ "cflags-only-other", no_argument, &want_flags, PKG_CFLAGS_ONLY_OTHER|PKG_PRINT_ERRORS, },
1144 		{ "libs-only-L", no_argument, &want_flags, PKG_LIBS_ONLY_LDPATH|PKG_PRINT_ERRORS, },
1145 		{ "libs-only-l", no_argument, &want_flags, PKG_LIBS_ONLY_LIBNAME|PKG_PRINT_ERRORS, },
1146 		{ "libs-only-other", no_argument, &want_flags, PKG_LIBS_ONLY_OTHER|PKG_PRINT_ERRORS, },
1147 		{ "uninstalled", no_argument, &want_flags, PKG_UNINSTALLED, },
1148 		{ "no-uninstalled", no_argument, &want_flags, PKG_NO_UNINSTALLED, },
1149 		{ "keep-system-cflags", no_argument, &want_flags, PKG_KEEP_SYSTEM_CFLAGS, },
1150 		{ "keep-system-libs", no_argument, &want_flags, PKG_KEEP_SYSTEM_LIBS, },
1151 		{ "define-variable", required_argument, NULL, 27, },
1152 		{ "exact-version", required_argument, NULL, 28, },
1153 		{ "max-version", required_argument, NULL, 29, },
1154 		{ "ignore-conflicts", no_argument, &want_flags, PKG_IGNORE_CONFLICTS, },
1155 		{ "errors-to-stdout", no_argument, &want_flags, PKG_ERRORS_ON_STDOUT, },
1156 		{ "silence-errors", no_argument, &want_flags, PKG_SILENCE_ERRORS, },
1157 		{ "list-all", no_argument, &want_flags, PKG_LIST|PKG_PRINT_ERRORS, },
1158 		{ "list-package-names", no_argument, &want_flags, PKG_LIST_PACKAGE_NAMES|PKG_PRINT_ERRORS, },
1159 #ifndef PKGCONF_LITE
1160 		{ "simulate", no_argument, &want_flags, PKG_SIMULATE, },
1161 #endif
1162 		{ "no-cache", no_argument, &want_flags, PKG_NO_CACHE, },
1163 		{ "print-provides", no_argument, &want_flags, PKG_PROVIDES, },
1164 		{ "no-provides", no_argument, &want_flags, PKG_NO_PROVIDES, },
1165 		{ "debug", no_argument, &want_flags, PKG_DEBUG|PKG_PRINT_ERRORS, },
1166 		{ "validate", no_argument, &want_flags, PKG_VALIDATE|PKG_PRINT_ERRORS|PKG_ERRORS_ON_STDOUT },
1167 		{ "log-file", required_argument, NULL, 40 },
1168 		{ "path", no_argument, &want_flags, PKG_PATH },
1169 		{ "with-path", required_argument, NULL, 42 },
1170 		{ "prefix-variable", required_argument, NULL, 43 },
1171 		{ "define-prefix", no_argument, &want_flags, PKG_DEFINE_PREFIX },
1172 		{ "relocate", required_argument, NULL, 45 },
1173 		{ "dont-define-prefix", no_argument, &want_flags, PKG_DONT_DEFINE_PREFIX },
1174 		{ "dont-relocate-paths", no_argument, &want_flags, PKG_DONT_RELOCATE_PATHS },
1175 		{ "env", required_argument, NULL, 48 },
1176 #ifndef PKGCONF_LITE
1177 		{ "msvc-syntax", no_argument, &want_flags, PKG_MSVC_SYNTAX },
1178 #endif
1179 		{ "fragment-filter", required_argument, NULL, 50 },
1180 		{ "internal-cflags", no_argument, &want_flags, PKG_INTERNAL_CFLAGS },
1181 #ifndef PKGCONF_LITE
1182 		{ "dump-personality", no_argument, &want_flags, PKG_DUMP_PERSONALITY },
1183 		{ "personality", required_argument, NULL, 53 },
1184 #endif
1185 		{ "license", no_argument, &want_flags, PKG_DUMP_LICENSE },
1186 		{ "verbose", no_argument, NULL, 55 },
1187 		{ "exists-cflags", no_argument, &want_flags, PKG_EXISTS_CFLAGS },
1188 		{ "fragment-tree", no_argument, &want_flags, PKG_FRAGMENT_TREE },
1189 		{ NULL, 0, NULL, 0 }
1190 	};
1191 
1192 #ifndef PKGCONF_LITE
1193 	if (getenv("PKG_CONFIG_EARLY_TRACE"))
1194 	{
1195 		error_msgout = stderr;
1196 		pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL);
1197 	}
1198 #endif
1199 
1200 	while ((ret = pkg_getopt_long_only(argc, argv, "", options, NULL)) != -1)
1201 	{
1202 		switch (ret)
1203 		{
1204 		case 2:
1205 			required_module_version = pkg_optarg;
1206 			break;
1207 		case 3:
1208 			required_pkgconfig_version = pkg_optarg;
1209 			break;
1210 		case 7:
1211 			want_variable = pkg_optarg;
1212 			break;
1213 		case 11:
1214 			maximum_traverse_depth = atoi(pkg_optarg);
1215 			break;
1216 		case 27:
1217 			pkgconf_tuple_define_global(&pkg_client, pkg_optarg);
1218 			break;
1219 		case 28:
1220 			required_exact_module_version = pkg_optarg;
1221 			break;
1222 		case 29:
1223 			required_max_module_version = pkg_optarg;
1224 			break;
1225 		case 40:
1226 			logfile_arg = pkg_optarg;
1227 			break;
1228 		case 42:
1229 			pkgconf_path_prepend(pkg_optarg, &dir_list, true);
1230 			break;
1231 		case 43:
1232 			pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg);
1233 			break;
1234 		case 45:
1235 			relocate_path(pkg_optarg);
1236 			return EXIT_SUCCESS;
1237 		case 48:
1238 			want_env_prefix = pkg_optarg;
1239 			break;
1240 		case 50:
1241 			want_fragment_filter = pkg_optarg;
1242 			break;
1243 #ifndef PKGCONF_LITE
1244 		case 53:
1245 			personality = pkgconf_cross_personality_find(pkg_optarg);
1246 			break;
1247 #endif
1248 		case 55:
1249 			verbosity++;
1250 			break;
1251 		case '?':
1252 		case ':':
1253 			ret = EXIT_FAILURE;
1254 			goto out;
1255 		default:
1256 			break;
1257 		}
1258 	}
1259 
1260 	if (personality == NULL) {
1261 #ifndef PKGCONF_LITE
1262 		personality = deduce_personality(argv);
1263 #else
1264 		personality = pkgconf_cross_personality_default();
1265 #endif
1266 	}
1267 
1268 #ifndef PKGCONF_LITE
1269 	if ((want_flags & PKG_DUMP_PERSONALITY) == PKG_DUMP_PERSONALITY)
1270 	{
1271 		dump_personality(personality);
1272 		return EXIT_SUCCESS;
1273 	}
1274 #endif
1275 
1276 	/* now, bring up the client.  settings are preserved since the client is prealloced */
1277 	pkgconf_client_init(&pkg_client, error_handler, NULL, personality);
1278 
1279 	/* unveil the entire search path now that we have loaded the personality data. */
1280 	if (!unveil_search_paths(&pkg_client, personality))
1281 	{
1282 		fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno));
1283 		return EXIT_FAILURE;
1284 	}
1285 
1286 #ifndef PKGCONF_LITE
1287 	if ((want_flags & PKG_MSVC_SYNTAX) == PKG_MSVC_SYNTAX || getenv("PKG_CONFIG_MSVC_SYNTAX") != NULL)
1288 		want_render_ops = msvc_renderer_get();
1289 #endif
1290 
1291 	if ((env_traverse_depth = getenv("PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH")) != NULL)
1292 		maximum_traverse_depth = atoi(env_traverse_depth);
1293 
1294 	if ((want_flags & PKG_PRINT_ERRORS) != PKG_PRINT_ERRORS)
1295 		want_flags |= (PKG_SILENCE_ERRORS);
1296 
1297 	if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS && !getenv("PKG_CONFIG_DEBUG_SPEW"))
1298 		want_flags |= (PKG_SILENCE_ERRORS);
1299 	else
1300 		want_flags &= ~(PKG_SILENCE_ERRORS);
1301 
1302 	if (getenv("PKG_CONFIG_DONT_RELOCATE_PATHS"))
1303 		want_flags |= (PKG_DONT_RELOCATE_PATHS);
1304 
1305 	if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE || (want_flags & PKG_DEBUG) == PKG_DEBUG)
1306 		pkgconf_client_set_warn_handler(&pkg_client, error_handler, NULL);
1307 
1308 #ifndef PKGCONF_LITE
1309 	if ((want_flags & PKG_DEBUG) == PKG_DEBUG)
1310 		pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL);
1311 #endif
1312 
1313 	pkgconf_path_prepend_list(&pkg_client.dir_list, &dir_list);
1314 	pkgconf_path_free(&dir_list);
1315 
1316 	if ((want_flags & PKG_ABOUT) == PKG_ABOUT)
1317 	{
1318 		about();
1319 
1320 		ret = EXIT_SUCCESS;
1321 		goto out;
1322 	}
1323 
1324 	if ((want_flags & PKG_VERSION) == PKG_VERSION)
1325 	{
1326 		version();
1327 
1328 		ret = EXIT_SUCCESS;
1329 		goto out;
1330 	}
1331 
1332 	if ((want_flags & PKG_HELP) == PKG_HELP)
1333 	{
1334 		usage();
1335 
1336 		ret = EXIT_SUCCESS;
1337 		goto out;
1338 	}
1339 
1340 	if (getenv("PKG_CONFIG_FDO_SYSROOT_RULES"))
1341 		want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES;
1342 
1343 	if (getenv("PKG_CONFIG_PKGCONF1_SYSROOT_RULES"))
1344 		want_client_flags |= PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES;
1345 
1346 	if ((want_flags & PKG_SHORT_ERRORS) == PKG_SHORT_ERRORS)
1347 		want_client_flags |= PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS;
1348 
1349 	if ((want_flags & PKG_DONT_RELOCATE_PATHS) == PKG_DONT_RELOCATE_PATHS)
1350 		want_client_flags |= PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS;
1351 
1352 	error_msgout = stderr;
1353 	if ((want_flags & PKG_ERRORS_ON_STDOUT) == PKG_ERRORS_ON_STDOUT)
1354 		error_msgout = stdout;
1355 	if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS) {
1356 		error_msgout = fopen(PATH_DEV_NULL, "w");
1357 		opened_error_msgout = true;
1358 	}
1359 
1360 	if ((want_flags & PKG_IGNORE_CONFLICTS) == PKG_IGNORE_CONFLICTS || getenv("PKG_CONFIG_IGNORE_CONFLICTS") != NULL)
1361 		want_client_flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS;
1362 
1363 	if ((want_flags & PKG_STATIC) == PKG_STATIC || personality->want_default_static)
1364 		want_client_flags |= (PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS);
1365 
1366 	if ((want_flags & PKG_SHARED) == PKG_SHARED)
1367 		want_client_flags &= ~(PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS);
1368 
1369 	/* if --static and --pure are both specified, then disable merge-back.
1370 	 * this allows for a --static which searches private modules, but has the same fragment behaviour as if
1371 	 * --static were disabled.  see <https://github.com/pkgconf/pkgconf/issues/83> for rationale.
1372 	 */
1373 	if ((want_flags & PKG_PURE) == PKG_PURE || getenv("PKG_CONFIG_PURE_DEPGRAPH") != NULL || personality->want_default_pure)
1374 		want_client_flags &= ~PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS;
1375 
1376 	if ((want_flags & PKG_ENV_ONLY) == PKG_ENV_ONLY)
1377 		want_client_flags |= PKGCONF_PKG_PKGF_ENV_ONLY;
1378 
1379 	if ((want_flags & PKG_NO_CACHE) == PKG_NO_CACHE)
1380 		want_client_flags |= PKGCONF_PKG_PKGF_NO_CACHE;
1381 
1382 /* On Windows we want to always redefine the prefix by default
1383  * but allow that behavior to be manually disabled */
1384 #if !defined(_WIN32) && !defined(_WIN64)
1385 	if ((want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX || getenv("PKG_CONFIG_RELOCATE_PATHS") != NULL)
1386 #endif
1387 		want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX;
1388 
1389 	if ((want_flags & PKG_NO_UNINSTALLED) == PKG_NO_UNINSTALLED || getenv("PKG_CONFIG_DISABLE_UNINSTALLED") != NULL)
1390 		want_client_flags |= PKGCONF_PKG_PKGF_NO_UNINSTALLED;
1391 
1392 	if ((want_flags & PKG_NO_PROVIDES) == PKG_NO_PROVIDES)
1393 		want_client_flags |= PKGCONF_PKG_PKGF_SKIP_PROVIDES;
1394 
1395 	if ((want_flags & PKG_DONT_DEFINE_PREFIX) == PKG_DONT_DEFINE_PREFIX  || getenv("PKG_CONFIG_DONT_DEFINE_PREFIX") != NULL)
1396 		want_client_flags &= ~PKGCONF_PKG_PKGF_REDEFINE_PREFIX;
1397 
1398 	if ((want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS)
1399 		want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS;
1400 
1401 	/* if these selectors are used, it means that we are querying metadata.
1402 	 * so signal to libpkgconf that we only want to walk the flattened dependency set.
1403 	 */
1404 	if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION ||
1405 	    (want_flags & PKG_REQUIRES) == PKG_REQUIRES ||
1406 	    (want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE ||
1407 	    (want_flags & PKG_PROVIDES) == PKG_PROVIDES ||
1408 	    (want_flags & PKG_VARIABLES) == PKG_VARIABLES ||
1409 	    (want_flags & PKG_PATH) == PKG_PATH ||
1410 	    want_variable != NULL)
1411 		maximum_traverse_depth = 1;
1412 
1413 	/* if we are asking for a variable, path or list of variables, this only makes sense
1414 	 * for a single package.
1415 	 */
1416 	if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES ||
1417 	    (want_flags & PKG_PATH) == PKG_PATH ||
1418 	    want_variable != NULL)
1419 		maximum_package_count = 1;
1420 
1421 	if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL)
1422 		want_flags |= PKG_KEEP_SYSTEM_CFLAGS;
1423 
1424 	if (getenv("PKG_CONFIG_ALLOW_SYSTEM_LIBS") != NULL)
1425 		want_flags |= PKG_KEEP_SYSTEM_LIBS;
1426 
1427 	if ((builddir = getenv("PKG_CONFIG_TOP_BUILD_DIR")) != NULL)
1428 		pkgconf_client_set_buildroot_dir(&pkg_client, builddir);
1429 
1430 	if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE ||
1431 		(want_flags & PKG_CFLAGS))
1432 	{
1433 		want_client_flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
1434 	}
1435 
1436 	if ((sysroot_dir = getenv("PKG_CONFIG_SYSROOT_DIR")) != NULL)
1437 	{
1438 		const char *destdir;
1439 
1440 		pkgconf_client_set_sysroot_dir(&pkg_client, sysroot_dir);
1441 
1442 		if ((destdir = getenv("DESTDIR")) != NULL)
1443 		{
1444 			if (!strcmp(destdir, sysroot_dir))
1445 				want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES;
1446 		}
1447 	}
1448 
1449 	/* we have determined what features we want most likely.  in some cases, we override later. */
1450 	pkgconf_client_set_flags(&pkg_client, want_client_flags);
1451 
1452 	/* at this point, want_client_flags should be set, so build the dir list */
1453 	pkgconf_client_dir_list_build(&pkg_client, personality);
1454 
1455 	/* preload any files in PKG_CONFIG_PRELOADED_FILES */
1456 	pkgconf_client_preload_from_environ(&pkg_client, "PKG_CONFIG_PRELOADED_FILES");
1457 
1458 	if (required_pkgconfig_version != NULL)
1459 	{
1460 		if (pkgconf_compare_version(PACKAGE_VERSION, required_pkgconfig_version) >= 0)
1461 			ret = EXIT_SUCCESS;
1462 		else
1463 			ret = EXIT_FAILURE;
1464 
1465 		goto out;
1466 	}
1467 
1468 	if ((want_flags & PKG_LIST) == PKG_LIST)
1469 	{
1470 		pkgconf_scan_all(&pkg_client, NULL, print_list_entry);
1471 		ret = EXIT_SUCCESS;
1472 		goto out;
1473 	}
1474 
1475 	if ((want_flags & PKG_LIST_PACKAGE_NAMES) == PKG_LIST_PACKAGE_NAMES)
1476 	{
1477 		pkgconf_scan_all(&pkg_client, NULL, print_package_entry);
1478 		ret = EXIT_SUCCESS;
1479 		goto out;
1480 	}
1481 
1482 	if (logfile_arg == NULL)
1483 		logfile_arg = getenv("PKG_CONFIG_LOG");
1484 
1485 	if (logfile_arg != NULL)
1486 	{
1487 		if (pkgconf_unveil(logfile_arg, "rwc") == -1)
1488 		{
1489 			fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno));
1490 			return EXIT_FAILURE;
1491 		}
1492 
1493 		logfile_out = fopen(logfile_arg, "w");
1494 		pkgconf_audit_set_log(&pkg_client, logfile_out);
1495 	}
1496 
1497 	if (required_module_version != NULL)
1498 	{
1499 		pkgconf_pkg_t *pkg = NULL;
1500 		pkgconf_node_t *node;
1501 		pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER;
1502 
1503 		while (argv[pkg_optind])
1504 		{
1505 			pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0);
1506 			pkg_optind++;
1507 		}
1508 
1509 		PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node)
1510 		{
1511 			pkgconf_dependency_t *pkgiter = node->data;
1512 
1513 			pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package);
1514 			if (pkg == NULL)
1515 			{
1516 				if (want_flags & PKG_PRINT_ERRORS)
1517 					pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
1518 
1519 				ret = EXIT_FAILURE;
1520 				goto cleanup;
1521 			}
1522 
1523 			if (pkgconf_compare_version(pkg->version, required_module_version) >= 0)
1524 			{
1525 				ret = EXIT_SUCCESS;
1526 				goto cleanup;
1527 			}
1528 		}
1529 
1530 		ret = EXIT_FAILURE;
1531 cleanup:
1532 		if (pkg != NULL)
1533 			pkgconf_pkg_unref(&pkg_client, pkg);
1534 		pkgconf_dependency_free(&deplist);
1535 		goto out;
1536 	}
1537 	else if (required_exact_module_version != NULL)
1538 	{
1539 		pkgconf_pkg_t *pkg = NULL;
1540 		pkgconf_node_t *node;
1541 		pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER;
1542 
1543 		while (argv[pkg_optind])
1544 		{
1545 			pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0);
1546 			pkg_optind++;
1547 		}
1548 
1549 		PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node)
1550 		{
1551 			pkgconf_dependency_t *pkgiter = node->data;
1552 
1553 			pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package);
1554 			if (pkg == NULL)
1555 			{
1556 				if (want_flags & PKG_PRINT_ERRORS)
1557 					pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
1558 
1559 				ret = EXIT_FAILURE;
1560 				goto cleanup2;
1561 			}
1562 
1563 			if (pkgconf_compare_version(pkg->version, required_exact_module_version) == 0)
1564 			{
1565 				ret = EXIT_SUCCESS;
1566 				goto cleanup2;
1567 			}
1568 		}
1569 
1570 		ret = EXIT_FAILURE;
1571 cleanup2:
1572 		if (pkg != NULL)
1573 			pkgconf_pkg_unref(&pkg_client, pkg);
1574 		pkgconf_dependency_free(&deplist);
1575 		goto out;
1576 	}
1577 	else if (required_max_module_version != NULL)
1578 	{
1579 		pkgconf_pkg_t *pkg = NULL;
1580 		pkgconf_node_t *node;
1581 		pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER;
1582 
1583 		while (argv[pkg_optind])
1584 		{
1585 			pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0);
1586 			pkg_optind++;
1587 		}
1588 
1589 		PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node)
1590 		{
1591 			pkgconf_dependency_t *pkgiter = node->data;
1592 
1593 			pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package);
1594 			if (pkg == NULL)
1595 			{
1596 				if (want_flags & PKG_PRINT_ERRORS)
1597 					pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
1598 
1599 				ret = EXIT_FAILURE;
1600 				goto cleanup3;
1601 			}
1602 
1603 			if (pkgconf_compare_version(pkg->version, required_max_module_version) <= 0)
1604 			{
1605 				ret = EXIT_SUCCESS;
1606 				goto cleanup3;
1607 			}
1608 		}
1609 
1610 		ret = EXIT_FAILURE;
1611 cleanup3:
1612 		if (pkg != NULL)
1613 			pkgconf_pkg_unref(&pkg_client, pkg);
1614 		pkgconf_dependency_free(&deplist);
1615 		goto out;
1616 	}
1617 
1618 	while (1)
1619 	{
1620 		char *package = argv[pkg_optind];
1621 		char *end;
1622 
1623 		if (package == NULL)
1624 			break;
1625 
1626 		/* check if there is a limit to the number of packages allowed to be included, if so and we have hit
1627 		 * the limit, stop adding packages to the queue.
1628 		 */
1629 		if (maximum_package_count > 0 && pkgq.length >= maximum_package_count)
1630 			break;
1631 
1632 		while (isspace((unsigned char)package[0]))
1633 			package++;
1634 
1635 		/* skip empty packages */
1636 		if (package[0] == '\0') {
1637 			pkg_optind++;
1638 			continue;
1639 		}
1640 
1641 		end = package + strlen(package) - 1;
1642 		while(end > package && isspace((unsigned char)end[0])) end--;
1643 		end[1] = '\0';
1644 
1645 		if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
1646 		{
1647 			pkgconf_queue_push(&pkgq, package);
1648 			pkg_optind++;
1649 		}
1650 		else if (argv[pkg_optind + 2] == NULL)
1651 		{
1652 			char packagebuf[PKGCONF_BUFSIZE];
1653 
1654 			snprintf(packagebuf, sizeof packagebuf, "%s %s", package, argv[pkg_optind + 1]);
1655 			pkg_optind += 2;
1656 
1657 			pkgconf_queue_push(&pkgq, packagebuf);
1658 		}
1659 		else
1660 		{
1661 			char packagebuf[PKGCONF_BUFSIZE];
1662 
1663 			snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]);
1664 			pkg_optind += 3;
1665 
1666 			pkgconf_queue_push(&pkgq, packagebuf);
1667 		}
1668 	}
1669 
1670 	if (pkgq.head == NULL)
1671 	{
1672 		fprintf(stderr, "Please specify at least one package name on the command line.\n");
1673 		ret = EXIT_FAILURE;
1674 		goto out;
1675 	}
1676 
1677 	ret = EXIT_SUCCESS;
1678 
1679 	if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth))
1680 	{
1681 		ret = EXIT_FAILURE;
1682 		goto out;
1683 	}
1684 
1685 	/* we shouldn't need to unveil any more filesystem accesses from this point, so lock it down */
1686 	if (pkgconf_unveil(NULL, NULL) == -1)
1687 	{
1688 		fprintf(stderr, "pkgconf: unveil lockdown failed: %s\n", strerror(errno));
1689 		return EXIT_FAILURE;
1690 	}
1691 
1692 #ifndef PKGCONF_LITE
1693 	if ((want_flags & PKG_SIMULATE) == PKG_SIMULATE)
1694 	{
1695 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1696 
1697 		pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ERRORS);
1698 		apply_simulate(&pkg_client, &world, NULL, -1);
1699 	}
1700 #endif
1701 
1702 	if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE)
1703 		goto out;
1704 
1705 	if ((want_flags & PKG_DUMP_LICENSE) == PKG_DUMP_LICENSE)
1706 	{
1707 		apply_license(&pkg_client, &world, &ret, 2);
1708 		goto out;
1709 	}
1710 
1711 	if ((want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED)
1712 	{
1713 		ret = EXIT_FAILURE;
1714 		apply_uninstalled(&pkg_client, &world, &ret, 2);
1715 		goto out;
1716 	}
1717 
1718 	if (want_env_prefix != NULL)
1719 	{
1720 		apply_env(&pkg_client, &world, want_env_prefix, 2);
1721 		goto out;
1722 	}
1723 
1724 	if ((want_flags & PKG_PROVIDES) == PKG_PROVIDES)
1725 	{
1726 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1727 		apply_provides(&pkg_client, &world, NULL, 2);
1728 	}
1729 
1730 #ifndef PKGCONF_LITE
1731 	if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH)
1732 	{
1733 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1734 		apply_digraph(&pkg_client, &world, &pkgq, 2);
1735 	}
1736 
1737 	if ((want_flags & PKG_SOLUTION) == PKG_SOLUTION)
1738 	{
1739 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1740 		apply_print_solution(&pkg_client, &world, NULL, 2);
1741 	}
1742 #endif
1743 
1744 	if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION)
1745 	{
1746 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1747 		apply_modversion(&pkg_client, &world, &pkgq, 2);
1748 	}
1749 
1750 	if ((want_flags & PKG_PATH) == PKG_PATH)
1751 	{
1752 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1753 
1754 		pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL);
1755 		apply_path(&pkg_client, &world, NULL, 2);
1756 	}
1757 
1758 	if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES)
1759 	{
1760 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1761 		apply_variables(&pkg_client, &world, NULL, 2);
1762 	}
1763 
1764 	if (want_variable)
1765 	{
1766 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1767 
1768 		pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL);
1769 		apply_variable(&pkg_client, &world, want_variable, 2);
1770 	}
1771 
1772 	if ((want_flags & PKG_REQUIRES) == PKG_REQUIRES)
1773 	{
1774 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1775 		apply_requires(&pkg_client, &world, NULL, 2);
1776 	}
1777 
1778 	if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE)
1779 	{
1780 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1781 
1782 		apply_requires_private(&pkg_client, &world, NULL, 2);
1783 	}
1784 
1785 	if ((want_flags & PKG_FRAGMENT_TREE))
1786 	{
1787 		want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1788 
1789 		apply_fragment_tree(&pkg_client, &world, NULL, 2);
1790 	}
1791 
1792 	if ((want_flags & PKG_CFLAGS))
1793 	{
1794 		apply_cflags(&pkg_client, &world, NULL, 2);
1795 	}
1796 
1797 	if ((want_flags & PKG_LIBS))
1798 	{
1799 		if (want_flags & PKG_CFLAGS)
1800 			printf(" ");
1801 
1802 		if (!(want_flags & PKG_STATIC))
1803 			pkgconf_client_set_flags(&pkg_client, pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE);
1804 
1805 		apply_libs(&pkg_client, &world, NULL, 2);
1806 	}
1807 
1808 	if (want_flags & (PKG_CFLAGS|PKG_LIBS))
1809 		printf("\n");
1810 
1811 out:
1812 	pkgconf_solution_free(&pkg_client, &world);
1813 	pkgconf_queue_free(&pkgq);
1814 	pkgconf_cross_personality_deinit(personality);
1815 	pkgconf_client_deinit(&pkg_client);
1816 
1817 	if (logfile_out != NULL)
1818 		fclose(logfile_out);
1819 	if (opened_error_msgout)
1820 		fclose(error_msgout);
1821 
1822 	return ret;
1823 }
1824