jcs's openbsd hax
openbsd
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
78static pkgconf_client_t pkg_client;
79static const pkgconf_fragment_render_ops_t *want_render_ops = NULL;
80
81static uint64_t want_flags;
82static int verbosity = 0;
83static int maximum_traverse_depth = 2000;
84static size_t maximum_package_count = 0;
85
86static char *want_variable = NULL;
87static char *want_fragment_filter = NULL;
88
89FILE *error_msgout = NULL;
90FILE *logfile_out = NULL;
91
92static bool
93error_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
101static bool
102print_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
114static bool
115print_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
127static bool
128filter_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
148static bool
149filter_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
171static void
172print_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
184static void
185print_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
202static void
203print_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
220static void
221print_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
238static bool
239apply_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
258static void
259print_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
301static bool
302apply_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
332static void
333print_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
341static bool
342apply_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
352static bool
353apply_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
392static bool
393apply_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
411static bool
412apply_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
432static bool
433apply_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
455static bool
456apply_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
482out:
483 pkgconf_fragment_free(&unfiltered_list);
484 pkgconf_fragment_free(&filtered_list);
485
486 return true;
487}
488
489static void
490maybe_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
529static void
530apply_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
577static bool
578apply_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
602static bool
603apply_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
625out:
626 pkgconf_fragment_free(&unfiltered_list);
627 pkgconf_fragment_free(&filtered_list);
628
629 return true;
630}
631
632static bool
633apply_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
654out:
655 pkgconf_fragment_free(&unfiltered_list);
656 pkgconf_fragment_free(&filtered_list);
657
658 return true;
659}
660
661static bool
662apply_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
680static bool
681apply_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
698static void
699check_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
708static bool
709apply_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
722static void
723print_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
753static bool
754apply_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
767static void
768print_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
788static bool
789apply_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
810static void
811print_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
823static bool
824apply_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
836static void
837version(void)
838{
839 printf("%s\n", PACKAGE_VERSION);
840}
841
842static void
843about(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
857static void
858usage(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
955static void
956relocate_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
967static void
968dump_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
1003static pkgconf_cross_personality_t *
1004deduce_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
1034int
1035main(int argc, char *argv[])
1036{
1037 int ret;
1038 pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER;
1039 pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER;
1040 char *builddir;
1041 char *sysroot_dir;
1042 char *env_traverse_depth;
1043 char *required_pkgconfig_version = NULL;
1044 char *required_exact_module_version = NULL;
1045 char *required_max_module_version = NULL;
1046 char *required_module_version = NULL;
1047 char *logfile_arg = NULL;
1048 char *want_env_prefix = NULL;
1049 unsigned int want_client_flags = PKGCONF_PKG_PKGF_NONE;
1050 pkgconf_cross_personality_t *personality = NULL;
1051 bool opened_error_msgout = false;
1052 pkgconf_pkg_t world = {
1053 .id = "virtual:world",
1054 .realname = "virtual world package",
1055 .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
1056 };
1057
1058 if (pkgconf_pledge("stdio rpath wpath cpath", NULL) == -1)
1059 {
1060 fprintf(stderr, "pkgconf: pledge failed: %s\n", strerror(errno));
1061 return EXIT_FAILURE;
1062 }
1063
1064 want_flags = 0;
1065
1066#ifdef _WIN32
1067 /* When running regression tests in cygwin, and building native
1068 * executable, tests fail unless native executable outputs unix
1069 * line endings. Come to think of it, this will probably help
1070 * real people who use cygwin build environments but native pkgconf, too.
1071 */
1072 _setmode(fileno(stdout), O_BINARY);
1073 _setmode(fileno(stderr), O_BINARY);
1074#endif
1075
1076 struct pkg_option options[] = {
1077 { "version", no_argument, &want_flags, PKG_VERSION|PKG_PRINT_ERRORS, },
1078 { "about", no_argument, &want_flags, PKG_ABOUT|PKG_PRINT_ERRORS, },
1079 { "atleast-version", required_argument, NULL, 2, },
1080 { "atleast-pkgconfig-version", required_argument, NULL, 3, },
1081 { "libs", no_argument, &want_flags, PKG_LIBS|PKG_PRINT_ERRORS, },
1082 { "cflags", no_argument, &want_flags, PKG_CFLAGS|PKG_PRINT_ERRORS, },
1083 { "modversion", no_argument, &want_flags, PKG_MODVERSION|PKG_PRINT_ERRORS, },
1084 { "variable", required_argument, NULL, 7, },
1085 { "exists", no_argument, &want_flags, PKG_EXISTS, },
1086 { "print-errors", no_argument, &want_flags, PKG_PRINT_ERRORS, },
1087 { "short-errors", no_argument, &want_flags, PKG_SHORT_ERRORS, },
1088 { "maximum-traverse-depth", required_argument, NULL, 11, },
1089 { "static", no_argument, &want_flags, PKG_STATIC, },
1090 { "shared", no_argument, &want_flags, PKG_SHARED, },
1091 { "pure", no_argument, &want_flags, PKG_PURE, },
1092 { "print-requires", no_argument, &want_flags, PKG_REQUIRES, },
1093 { "print-variables", no_argument, &want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, },
1094#ifndef PKGCONF_LITE
1095 { "digraph", no_argument, &want_flags, PKG_DIGRAPH, },
1096 { "solution", no_argument, &want_flags, PKG_SOLUTION, },
1097#endif
1098 { "help", no_argument, &want_flags, PKG_HELP, },
1099 { "env-only", no_argument, &want_flags, PKG_ENV_ONLY, },
1100 { "print-requires-private", no_argument, &want_flags, PKG_REQUIRES_PRIVATE, },
1101 { "cflags-only-I", no_argument, &want_flags, PKG_CFLAGS_ONLY_I|PKG_PRINT_ERRORS, },
1102 { "cflags-only-other", no_argument, &want_flags, PKG_CFLAGS_ONLY_OTHER|PKG_PRINT_ERRORS, },
1103 { "libs-only-L", no_argument, &want_flags, PKG_LIBS_ONLY_LDPATH|PKG_PRINT_ERRORS, },
1104 { "libs-only-l", no_argument, &want_flags, PKG_LIBS_ONLY_LIBNAME|PKG_PRINT_ERRORS, },
1105 { "libs-only-other", no_argument, &want_flags, PKG_LIBS_ONLY_OTHER|PKG_PRINT_ERRORS, },
1106 { "uninstalled", no_argument, &want_flags, PKG_UNINSTALLED, },
1107 { "no-uninstalled", no_argument, &want_flags, PKG_NO_UNINSTALLED, },
1108 { "keep-system-cflags", no_argument, &want_flags, PKG_KEEP_SYSTEM_CFLAGS, },
1109 { "keep-system-libs", no_argument, &want_flags, PKG_KEEP_SYSTEM_LIBS, },
1110 { "define-variable", required_argument, NULL, 27, },
1111 { "exact-version", required_argument, NULL, 28, },
1112 { "max-version", required_argument, NULL, 29, },
1113 { "ignore-conflicts", no_argument, &want_flags, PKG_IGNORE_CONFLICTS, },
1114 { "errors-to-stdout", no_argument, &want_flags, PKG_ERRORS_ON_STDOUT, },
1115 { "silence-errors", no_argument, &want_flags, PKG_SILENCE_ERRORS, },
1116 { "list-all", no_argument, &want_flags, PKG_LIST|PKG_PRINT_ERRORS, },
1117 { "list-package-names", no_argument, &want_flags, PKG_LIST_PACKAGE_NAMES|PKG_PRINT_ERRORS, },
1118#ifndef PKGCONF_LITE
1119 { "simulate", no_argument, &want_flags, PKG_SIMULATE, },
1120#endif
1121 { "no-cache", no_argument, &want_flags, PKG_NO_CACHE, },
1122 { "print-provides", no_argument, &want_flags, PKG_PROVIDES, },
1123 { "no-provides", no_argument, &want_flags, PKG_NO_PROVIDES, },
1124 { "debug", no_argument, &want_flags, PKG_DEBUG|PKG_PRINT_ERRORS, },
1125 { "validate", no_argument, &want_flags, PKG_VALIDATE|PKG_PRINT_ERRORS|PKG_ERRORS_ON_STDOUT },
1126 { "log-file", required_argument, NULL, 40 },
1127 { "path", no_argument, &want_flags, PKG_PATH },
1128 { "with-path", required_argument, NULL, 42 },
1129 { "prefix-variable", required_argument, NULL, 43 },
1130 { "define-prefix", no_argument, &want_flags, PKG_DEFINE_PREFIX },
1131 { "relocate", required_argument, NULL, 45 },
1132 { "dont-define-prefix", no_argument, &want_flags, PKG_DONT_DEFINE_PREFIX },
1133 { "dont-relocate-paths", no_argument, &want_flags, PKG_DONT_RELOCATE_PATHS },
1134 { "env", required_argument, NULL, 48 },
1135#ifndef PKGCONF_LITE
1136 { "msvc-syntax", no_argument, &want_flags, PKG_MSVC_SYNTAX },
1137#endif
1138 { "fragment-filter", required_argument, NULL, 50 },
1139 { "internal-cflags", no_argument, &want_flags, PKG_INTERNAL_CFLAGS },
1140#ifndef PKGCONF_LITE
1141 { "dump-personality", no_argument, &want_flags, PKG_DUMP_PERSONALITY },
1142 { "personality", required_argument, NULL, 53 },
1143#endif
1144 { "license", no_argument, &want_flags, PKG_DUMP_LICENSE },
1145 { "verbose", no_argument, NULL, 55 },
1146 { "exists-cflags", no_argument, &want_flags, PKG_EXISTS_CFLAGS },
1147 { "fragment-tree", no_argument, &want_flags, PKG_FRAGMENT_TREE },
1148 { NULL, 0, NULL, 0 }
1149 };
1150
1151#ifndef PKGCONF_LITE
1152 if (getenv("PKG_CONFIG_EARLY_TRACE"))
1153 {
1154 error_msgout = stderr;
1155 pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL);
1156 }
1157#endif
1158
1159 while ((ret = pkg_getopt_long_only(argc, argv, "", options, NULL)) != -1)
1160 {
1161 switch (ret)
1162 {
1163 case 2:
1164 required_module_version = pkg_optarg;
1165 break;
1166 case 3:
1167 required_pkgconfig_version = pkg_optarg;
1168 break;
1169 case 7:
1170 want_variable = pkg_optarg;
1171 break;
1172 case 11:
1173 maximum_traverse_depth = atoi(pkg_optarg);
1174 break;
1175 case 27:
1176 pkgconf_tuple_define_global(&pkg_client, pkg_optarg);
1177 break;
1178 case 28:
1179 required_exact_module_version = pkg_optarg;
1180 break;
1181 case 29:
1182 required_max_module_version = pkg_optarg;
1183 break;
1184 case 40:
1185 logfile_arg = pkg_optarg;
1186 break;
1187 case 42:
1188 pkgconf_path_prepend(pkg_optarg, &dir_list, true);
1189 break;
1190 case 43:
1191 pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg);
1192 break;
1193 case 45:
1194 relocate_path(pkg_optarg);
1195 return EXIT_SUCCESS;
1196 case 48:
1197 want_env_prefix = pkg_optarg;
1198 break;
1199 case 50:
1200 want_fragment_filter = pkg_optarg;
1201 break;
1202#ifndef PKGCONF_LITE
1203 case 53:
1204 personality = pkgconf_cross_personality_find(pkg_optarg);
1205 break;
1206#endif
1207 case 55:
1208 verbosity++;
1209 break;
1210 case '?':
1211 case ':':
1212 ret = EXIT_FAILURE;
1213 goto out;
1214 default:
1215 break;
1216 }
1217 }
1218
1219 if (personality == NULL) {
1220#ifndef PKGCONF_LITE
1221 personality = deduce_personality(argv);
1222#else
1223 personality = pkgconf_cross_personality_default();
1224#endif
1225 }
1226
1227 pkgconf_path_copy_list(&personality->dir_list, &dir_list);
1228 pkgconf_path_free(&dir_list);
1229
1230#ifndef PKGCONF_LITE
1231 if ((want_flags & PKG_DUMP_PERSONALITY) == PKG_DUMP_PERSONALITY)
1232 {
1233 dump_personality(personality);
1234 return EXIT_SUCCESS;
1235 }
1236#endif
1237
1238 /* now, bring up the client. settings are preserved since the client is prealloced */
1239 pkgconf_client_init(&pkg_client, error_handler, NULL, personality);
1240
1241#ifndef PKGCONF_LITE
1242 if ((want_flags & PKG_MSVC_SYNTAX) == PKG_MSVC_SYNTAX || getenv("PKG_CONFIG_MSVC_SYNTAX") != NULL)
1243 want_render_ops = msvc_renderer_get();
1244#endif
1245
1246 if ((env_traverse_depth = getenv("PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH")) != NULL)
1247 maximum_traverse_depth = atoi(env_traverse_depth);
1248
1249 if ((want_flags & PKG_PRINT_ERRORS) != PKG_PRINT_ERRORS)
1250 want_flags |= (PKG_SILENCE_ERRORS);
1251
1252 if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS && !getenv("PKG_CONFIG_DEBUG_SPEW"))
1253 want_flags |= (PKG_SILENCE_ERRORS);
1254 else
1255 want_flags &= ~(PKG_SILENCE_ERRORS);
1256
1257 if (getenv("PKG_CONFIG_DONT_RELOCATE_PATHS"))
1258 want_flags |= (PKG_DONT_RELOCATE_PATHS);
1259
1260 if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE || (want_flags & PKG_DEBUG) == PKG_DEBUG)
1261 pkgconf_client_set_warn_handler(&pkg_client, error_handler, NULL);
1262
1263#ifndef PKGCONF_LITE
1264 if ((want_flags & PKG_DEBUG) == PKG_DEBUG)
1265 pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL);
1266#endif
1267
1268 if ((want_flags & PKG_ABOUT) == PKG_ABOUT)
1269 {
1270 about();
1271
1272 ret = EXIT_SUCCESS;
1273 goto out;
1274 }
1275
1276 if ((want_flags & PKG_VERSION) == PKG_VERSION)
1277 {
1278 version();
1279
1280 ret = EXIT_SUCCESS;
1281 goto out;
1282 }
1283
1284 if ((want_flags & PKG_HELP) == PKG_HELP)
1285 {
1286 usage();
1287
1288 ret = EXIT_SUCCESS;
1289 goto out;
1290 }
1291
1292 if (getenv("PKG_CONFIG_FDO_SYSROOT_RULES"))
1293 want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES;
1294
1295 if (getenv("PKG_CONFIG_PKGCONF1_SYSROOT_RULES"))
1296 want_client_flags |= PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES;
1297
1298 if ((want_flags & PKG_SHORT_ERRORS) == PKG_SHORT_ERRORS)
1299 want_client_flags |= PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS;
1300
1301 if ((want_flags & PKG_DONT_RELOCATE_PATHS) == PKG_DONT_RELOCATE_PATHS)
1302 want_client_flags |= PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS;
1303
1304 error_msgout = stderr;
1305 if ((want_flags & PKG_ERRORS_ON_STDOUT) == PKG_ERRORS_ON_STDOUT)
1306 error_msgout = stdout;
1307 if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS) {
1308 error_msgout = fopen(PATH_DEV_NULL, "w");
1309 opened_error_msgout = true;
1310 }
1311
1312 if ((want_flags & PKG_IGNORE_CONFLICTS) == PKG_IGNORE_CONFLICTS || getenv("PKG_CONFIG_IGNORE_CONFLICTS") != NULL)
1313 want_client_flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS;
1314
1315 if ((want_flags & PKG_STATIC) == PKG_STATIC || personality->want_default_static)
1316 want_client_flags |= (PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS);
1317
1318 if ((want_flags & PKG_SHARED) == PKG_SHARED)
1319 want_client_flags &= ~(PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS);
1320
1321 /* if --static and --pure are both specified, then disable merge-back.
1322 * this allows for a --static which searches private modules, but has the same fragment behaviour as if
1323 * --static were disabled. see <https://github.com/pkgconf/pkgconf/issues/83> for rationale.
1324 */
1325 if ((want_flags & PKG_PURE) == PKG_PURE || getenv("PKG_CONFIG_PURE_DEPGRAPH") != NULL || personality->want_default_pure)
1326 want_client_flags &= ~PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS;
1327
1328 if ((want_flags & PKG_ENV_ONLY) == PKG_ENV_ONLY)
1329 want_client_flags |= PKGCONF_PKG_PKGF_ENV_ONLY;
1330
1331 if ((want_flags & PKG_NO_CACHE) == PKG_NO_CACHE)
1332 want_client_flags |= PKGCONF_PKG_PKGF_NO_CACHE;
1333
1334/* On Windows we want to always redefine the prefix by default
1335 * but allow that behavior to be manually disabled */
1336#if !defined(_WIN32) && !defined(_WIN64)
1337 if ((want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX || getenv("PKG_CONFIG_RELOCATE_PATHS") != NULL)
1338#endif
1339 want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX;
1340
1341 if ((want_flags & PKG_NO_UNINSTALLED) == PKG_NO_UNINSTALLED || getenv("PKG_CONFIG_DISABLE_UNINSTALLED") != NULL)
1342 want_client_flags |= PKGCONF_PKG_PKGF_NO_UNINSTALLED;
1343
1344 if ((want_flags & PKG_NO_PROVIDES) == PKG_NO_PROVIDES)
1345 want_client_flags |= PKGCONF_PKG_PKGF_SKIP_PROVIDES;
1346
1347 if ((want_flags & PKG_DONT_DEFINE_PREFIX) == PKG_DONT_DEFINE_PREFIX || getenv("PKG_CONFIG_DONT_DEFINE_PREFIX") != NULL)
1348 want_client_flags &= ~PKGCONF_PKG_PKGF_REDEFINE_PREFIX;
1349
1350 if ((want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS)
1351 want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS;
1352
1353 /* if these selectors are used, it means that we are querying metadata.
1354 * so signal to libpkgconf that we only want to walk the flattened dependency set.
1355 */
1356 if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION ||
1357 (want_flags & PKG_REQUIRES) == PKG_REQUIRES ||
1358 (want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE ||
1359 (want_flags & PKG_PROVIDES) == PKG_PROVIDES ||
1360 (want_flags & PKG_VARIABLES) == PKG_VARIABLES ||
1361 (want_flags & PKG_PATH) == PKG_PATH ||
1362 want_variable != NULL)
1363 maximum_traverse_depth = 1;
1364
1365 /* if we are asking for a variable, path or list of variables, this only makes sense
1366 * for a single package.
1367 */
1368 if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES ||
1369 (want_flags & PKG_PATH) == PKG_PATH ||
1370 want_variable != NULL)
1371 maximum_package_count = 1;
1372
1373 if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL)
1374 want_flags |= PKG_KEEP_SYSTEM_CFLAGS;
1375
1376 if (getenv("PKG_CONFIG_ALLOW_SYSTEM_LIBS") != NULL)
1377 want_flags |= PKG_KEEP_SYSTEM_LIBS;
1378
1379 if ((builddir = getenv("PKG_CONFIG_TOP_BUILD_DIR")) != NULL)
1380 pkgconf_client_set_buildroot_dir(&pkg_client, builddir);
1381
1382 if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE ||
1383 (want_flags & PKG_CFLAGS))
1384 {
1385 want_client_flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
1386 }
1387
1388 if ((sysroot_dir = getenv("PKG_CONFIG_SYSROOT_DIR")) != NULL)
1389 {
1390 const char *destdir;
1391
1392 pkgconf_client_set_sysroot_dir(&pkg_client, sysroot_dir);
1393
1394 if ((destdir = getenv("DESTDIR")) != NULL)
1395 {
1396 if (!strcmp(destdir, sysroot_dir))
1397 want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES;
1398 }
1399 }
1400
1401 /* we have determined what features we want most likely. in some cases, we override later. */
1402 pkgconf_client_set_flags(&pkg_client, want_client_flags);
1403
1404 /* at this point, want_client_flags should be set, so build the dir list */
1405 pkgconf_client_dir_list_build(&pkg_client, personality);
1406
1407 if (required_pkgconfig_version != NULL)
1408 {
1409 if (pkgconf_compare_version(PACKAGE_VERSION, required_pkgconfig_version) >= 0)
1410 ret = EXIT_SUCCESS;
1411 else
1412 ret = EXIT_FAILURE;
1413
1414 goto out;
1415 }
1416
1417 if ((want_flags & PKG_LIST) == PKG_LIST)
1418 {
1419 pkgconf_scan_all(&pkg_client, NULL, print_list_entry);
1420 ret = EXIT_SUCCESS;
1421 goto out;
1422 }
1423
1424 if ((want_flags & PKG_LIST_PACKAGE_NAMES) == PKG_LIST_PACKAGE_NAMES)
1425 {
1426 pkgconf_scan_all(&pkg_client, NULL, print_package_entry);
1427 ret = EXIT_SUCCESS;
1428 goto out;
1429 }
1430
1431 if (logfile_arg == NULL)
1432 logfile_arg = getenv("PKG_CONFIG_LOG");
1433
1434 if (logfile_arg != NULL)
1435 {
1436 logfile_out = fopen(logfile_arg, "w");
1437 pkgconf_audit_set_log(&pkg_client, logfile_out);
1438 }
1439
1440 if (required_module_version != NULL)
1441 {
1442 pkgconf_pkg_t *pkg = NULL;
1443 pkgconf_node_t *node;
1444 pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER;
1445
1446 while (argv[pkg_optind])
1447 {
1448 pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0);
1449 pkg_optind++;
1450 }
1451
1452 PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node)
1453 {
1454 pkgconf_dependency_t *pkgiter = node->data;
1455
1456 pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package);
1457 if (pkg == NULL)
1458 {
1459 if (want_flags & PKG_PRINT_ERRORS)
1460 pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
1461
1462 ret = EXIT_FAILURE;
1463 goto cleanup;
1464 }
1465
1466 if (pkgconf_compare_version(pkg->version, required_module_version) >= 0)
1467 {
1468 ret = EXIT_SUCCESS;
1469 goto cleanup;
1470 }
1471 }
1472
1473 ret = EXIT_FAILURE;
1474cleanup:
1475 if (pkg != NULL)
1476 pkgconf_pkg_unref(&pkg_client, pkg);
1477 pkgconf_dependency_free(&deplist);
1478 goto out;
1479 }
1480 else if (required_exact_module_version != NULL)
1481 {
1482 pkgconf_pkg_t *pkg = NULL;
1483 pkgconf_node_t *node;
1484 pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER;
1485
1486 while (argv[pkg_optind])
1487 {
1488 pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0);
1489 pkg_optind++;
1490 }
1491
1492 PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node)
1493 {
1494 pkgconf_dependency_t *pkgiter = node->data;
1495
1496 pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package);
1497 if (pkg == NULL)
1498 {
1499 if (want_flags & PKG_PRINT_ERRORS)
1500 pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
1501
1502 ret = EXIT_FAILURE;
1503 goto cleanup2;
1504 }
1505
1506 if (pkgconf_compare_version(pkg->version, required_exact_module_version) == 0)
1507 {
1508 ret = EXIT_SUCCESS;
1509 goto cleanup2;
1510 }
1511 }
1512
1513 ret = EXIT_FAILURE;
1514cleanup2:
1515 if (pkg != NULL)
1516 pkgconf_pkg_unref(&pkg_client, pkg);
1517 pkgconf_dependency_free(&deplist);
1518 goto out;
1519 }
1520 else if (required_max_module_version != NULL)
1521 {
1522 pkgconf_pkg_t *pkg = NULL;
1523 pkgconf_node_t *node;
1524 pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER;
1525
1526 while (argv[pkg_optind])
1527 {
1528 pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0);
1529 pkg_optind++;
1530 }
1531
1532 PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node)
1533 {
1534 pkgconf_dependency_t *pkgiter = node->data;
1535
1536 pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package);
1537 if (pkg == NULL)
1538 {
1539 if (want_flags & PKG_PRINT_ERRORS)
1540 pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
1541
1542 ret = EXIT_FAILURE;
1543 goto cleanup3;
1544 }
1545
1546 if (pkgconf_compare_version(pkg->version, required_max_module_version) <= 0)
1547 {
1548 ret = EXIT_SUCCESS;
1549 goto cleanup3;
1550 }
1551 }
1552
1553 ret = EXIT_FAILURE;
1554cleanup3:
1555 if (pkg != NULL)
1556 pkgconf_pkg_unref(&pkg_client, pkg);
1557 pkgconf_dependency_free(&deplist);
1558 goto out;
1559 }
1560
1561 while (1)
1562 {
1563 char *package = argv[pkg_optind];
1564 char *end;
1565
1566 if (package == NULL)
1567 break;
1568
1569 /* check if there is a limit to the number of packages allowed to be included, if so and we have hit
1570 * the limit, stop adding packages to the queue.
1571 */
1572 if (maximum_package_count > 0 && pkgq.length >= maximum_package_count)
1573 break;
1574
1575 while (isspace((unsigned char)package[0]))
1576 package++;
1577
1578 /* skip empty packages */
1579 if (package[0] == '\0') {
1580 pkg_optind++;
1581 continue;
1582 }
1583
1584 end = package + strlen(package) - 1;
1585 while(end > package && isspace((unsigned char)end[0])) end--;
1586 end[1] = '\0';
1587
1588 if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
1589 {
1590 pkgconf_queue_push(&pkgq, package);
1591 pkg_optind++;
1592 }
1593 else if (argv[pkg_optind + 2] == NULL)
1594 {
1595 char packagebuf[PKGCONF_BUFSIZE];
1596
1597 snprintf(packagebuf, sizeof packagebuf, "%s %s", package, argv[pkg_optind + 1]);
1598 pkg_optind += 2;
1599
1600 pkgconf_queue_push(&pkgq, packagebuf);
1601 }
1602 else
1603 {
1604 char packagebuf[PKGCONF_BUFSIZE];
1605
1606 snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]);
1607 pkg_optind += 3;
1608
1609 pkgconf_queue_push(&pkgq, packagebuf);
1610 }
1611 }
1612
1613 if (pkgq.head == NULL)
1614 {
1615 fprintf(stderr, "Please specify at least one package name on the command line.\n");
1616 ret = EXIT_FAILURE;
1617 goto out;
1618 }
1619
1620 ret = EXIT_SUCCESS;
1621
1622 if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth))
1623 {
1624 ret = EXIT_FAILURE;
1625 goto out;
1626 }
1627
1628#ifndef PKGCONF_LITE
1629 if ((want_flags & PKG_SIMULATE) == PKG_SIMULATE)
1630 {
1631 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1632
1633 pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ERRORS);
1634 apply_simulate(&pkg_client, &world, NULL, -1);
1635 }
1636#endif
1637
1638 if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE)
1639 goto out;
1640
1641 if ((want_flags & PKG_DUMP_LICENSE) == PKG_DUMP_LICENSE)
1642 {
1643 apply_license(&pkg_client, &world, &ret, 2);
1644 goto out;
1645 }
1646
1647 if ((want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED)
1648 {
1649 ret = EXIT_FAILURE;
1650 apply_uninstalled(&pkg_client, &world, &ret, 2);
1651 goto out;
1652 }
1653
1654 if (want_env_prefix != NULL)
1655 {
1656 apply_env(&pkg_client, &world, want_env_prefix, 2);
1657 goto out;
1658 }
1659
1660 if ((want_flags & PKG_PROVIDES) == PKG_PROVIDES)
1661 {
1662 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1663 apply_provides(&pkg_client, &world, NULL, 2);
1664 }
1665
1666#ifndef PKGCONF_LITE
1667 if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH)
1668 {
1669 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1670 apply_digraph(&pkg_client, &world, &pkgq, 2);
1671 }
1672
1673 if ((want_flags & PKG_SOLUTION) == PKG_SOLUTION)
1674 {
1675 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1676 apply_print_solution(&pkg_client, &world, NULL, 2);
1677 }
1678#endif
1679
1680 if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION)
1681 {
1682 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1683 apply_modversion(&pkg_client, &world, &pkgq, 2);
1684 }
1685
1686 if ((want_flags & PKG_PATH) == PKG_PATH)
1687 {
1688 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1689
1690 pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL);
1691 apply_path(&pkg_client, &world, NULL, 2);
1692 }
1693
1694 if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES)
1695 {
1696 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1697 apply_variables(&pkg_client, &world, NULL, 2);
1698 }
1699
1700 if (want_variable)
1701 {
1702 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1703
1704 pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL);
1705 apply_variable(&pkg_client, &world, want_variable, 2);
1706 }
1707
1708 if ((want_flags & PKG_REQUIRES) == PKG_REQUIRES)
1709 {
1710 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1711 apply_requires(&pkg_client, &world, NULL, 2);
1712 }
1713
1714 if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE)
1715 {
1716 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1717
1718 apply_requires_private(&pkg_client, &world, NULL, 2);
1719 }
1720
1721 if ((want_flags & PKG_FRAGMENT_TREE))
1722 {
1723 want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
1724
1725 apply_fragment_tree(&pkg_client, &world, NULL, 2);
1726 }
1727
1728 if ((want_flags & PKG_CFLAGS))
1729 {
1730 apply_cflags(&pkg_client, &world, NULL, 2);
1731 }
1732
1733 if ((want_flags & PKG_LIBS))
1734 {
1735 if (want_flags & PKG_CFLAGS)
1736 printf(" ");
1737
1738 if (!(want_flags & PKG_STATIC))
1739 pkgconf_client_set_flags(&pkg_client, pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE);
1740
1741 apply_libs(&pkg_client, &world, NULL, 2);
1742 }
1743
1744 if (want_flags & (PKG_CFLAGS|PKG_LIBS))
1745 printf("\n");
1746
1747out:
1748 pkgconf_solution_free(&pkg_client, &world);
1749 pkgconf_queue_free(&pkgq);
1750 pkgconf_cross_personality_deinit(personality);
1751 pkgconf_client_deinit(&pkg_client);
1752
1753 if (logfile_out != NULL)
1754 fclose(logfile_out);
1755 if (opened_error_msgout)
1756 fclose(error_msgout);
1757
1758 return ret;
1759}