diff options
Diffstat (limited to 'cli/main.c')
| -rw-r--r-- | cli/main.c | 1639 |
1 files changed, 169 insertions, 1470 deletions
diff --git a/cli/main.c b/cli/main.c index 53eee4c87443..7959737b9913 100644 --- a/cli/main.c +++ b/cli/main.c @@ -1,9 +1,10 @@ /* * main.c - * main() routine, printer functions + * main() routine * - * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 - * pkgconf authors (see AUTHORS). + * SPDX-License-Identifier: pkgconf + * + * Copyright (c) 2011-2025 pkgconf authors (see AUTHORS). * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,820 +19,97 @@ #include <libpkgconf/stdinc.h> #include <libpkgconf/libpkgconf.h> #include "getopt_long.h" -#ifndef PKGCONF_LITE -#include "renderer-msvc.h" -#endif -#ifdef _WIN32 -#include <io.h> /* for _setmode() */ -#include <fcntl.h> -#endif - -#define PKG_CFLAGS_ONLY_I (((uint64_t) 1) << 2) -#define PKG_CFLAGS_ONLY_OTHER (((uint64_t) 1) << 3) -#define PKG_CFLAGS (PKG_CFLAGS_ONLY_I|PKG_CFLAGS_ONLY_OTHER) -#define PKG_LIBS_ONLY_LDPATH (((uint64_t) 1) << 5) -#define PKG_LIBS_ONLY_LIBNAME (((uint64_t) 1) << 6) -#define PKG_LIBS_ONLY_OTHER (((uint64_t) 1) << 7) -#define PKG_LIBS (PKG_LIBS_ONLY_LDPATH|PKG_LIBS_ONLY_LIBNAME|PKG_LIBS_ONLY_OTHER) -#define PKG_MODVERSION (((uint64_t) 1) << 8) -#define PKG_REQUIRES (((uint64_t) 1) << 9) -#define PKG_REQUIRES_PRIVATE (((uint64_t) 1) << 10) -#define PKG_VARIABLES (((uint64_t) 1) << 11) -#define PKG_DIGRAPH (((uint64_t) 1) << 12) -#define PKG_KEEP_SYSTEM_CFLAGS (((uint64_t) 1) << 13) -#define PKG_KEEP_SYSTEM_LIBS (((uint64_t) 1) << 14) -#define PKG_VERSION (((uint64_t) 1) << 15) -#define PKG_ABOUT (((uint64_t) 1) << 16) -#define PKG_ENV_ONLY (((uint64_t) 1) << 17) -#define PKG_ERRORS_ON_STDOUT (((uint64_t) 1) << 18) -#define PKG_SILENCE_ERRORS (((uint64_t) 1) << 19) -#define PKG_IGNORE_CONFLICTS (((uint64_t) 1) << 20) -#define PKG_STATIC (((uint64_t) 1) << 21) -#define PKG_NO_UNINSTALLED (((uint64_t) 1) << 22) -#define PKG_UNINSTALLED (((uint64_t) 1) << 23) -#define PKG_LIST (((uint64_t) 1) << 24) -#define PKG_HELP (((uint64_t) 1) << 25) -#define PKG_PRINT_ERRORS (((uint64_t) 1) << 26) -#define PKG_SIMULATE (((uint64_t) 1) << 27) -#define PKG_NO_CACHE (((uint64_t) 1) << 28) -#define PKG_PROVIDES (((uint64_t) 1) << 29) -#define PKG_VALIDATE (((uint64_t) 1) << 30) -#define PKG_LIST_PACKAGE_NAMES (((uint64_t) 1) << 31) -#define PKG_NO_PROVIDES (((uint64_t) 1) << 32) -#define PKG_PURE (((uint64_t) 1) << 33) -#define PKG_PATH (((uint64_t) 1) << 34) -#define PKG_DEFINE_PREFIX (((uint64_t) 1) << 35) -#define PKG_DONT_DEFINE_PREFIX (((uint64_t) 1) << 36) -#define PKG_DONT_RELOCATE_PATHS (((uint64_t) 1) << 37) -#define PKG_DEBUG (((uint64_t) 1) << 38) -#define PKG_SHORT_ERRORS (((uint64_t) 1) << 39) -#define PKG_EXISTS (((uint64_t) 1) << 40) -#define PKG_MSVC_SYNTAX (((uint64_t) 1) << 41) -#define PKG_INTERNAL_CFLAGS (((uint64_t) 1) << 42) -#define PKG_DUMP_PERSONALITY (((uint64_t) 1) << 43) -#define PKG_SHARED (((uint64_t) 1) << 44) -#define PKG_DUMP_LICENSE (((uint64_t) 1) << 45) -#define PKG_SOLUTION (((uint64_t) 1) << 46) -#define PKG_EXISTS_CFLAGS (((uint64_t) 1) << 47) -#define PKG_FRAGMENT_TREE (((uint64_t) 1) << 48) - -static pkgconf_client_t pkg_client; -static const pkgconf_fragment_render_ops_t *want_render_ops = NULL; - -static uint64_t want_flags; -static int verbosity = 0; -static int maximum_traverse_depth = 2000; -static size_t maximum_package_count = 0; - -static char *want_variable = NULL; -static char *want_fragment_filter = NULL; - -FILE *error_msgout = NULL; -FILE *logfile_out = NULL; - -static bool -error_handler(const char *msg, const pkgconf_client_t *client, void *data) -{ - (void) client; - (void) data; - fprintf(error_msgout, "%s", msg); - return true; -} - -static bool -print_list_entry(const pkgconf_pkg_t *entry, void *data) -{ - (void) data; - - if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED) - return false; - - printf("%-30s %s - %s\n", entry->id, entry->realname, entry->description); +#include "core.h" - return false; -} - -static bool -print_package_entry(const pkgconf_pkg_t *entry, void *data) +static const char * +environ_lookup_handler(const pkgconf_client_t *client, const char *key) { - (void) data; - - if (entry->flags & PKGCONF_PKG_PROPF_UNINSTALLED) - return false; - - printf("%s\n", entry->id); - - return false; -} - -static bool -filter_cflags(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data) -{ - int got_flags = 0; (void) client; - (void) data; - - if (!(want_flags & PKG_KEEP_SYSTEM_CFLAGS) && pkgconf_fragment_has_system_dir(client, frag)) - return false; - if (want_fragment_filter != NULL && (strchr(want_fragment_filter, frag->type) == NULL || !frag->type)) - return false; - - if (frag->type == 'I') - got_flags = PKG_CFLAGS_ONLY_I; - else - got_flags = PKG_CFLAGS_ONLY_OTHER; - - return (want_flags & got_flags) != 0; + return getenv(key); } static bool -filter_libs(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data) +error_handler(const char *msg, const pkgconf_client_t *client, void *data) { - int got_flags = 0; - (void) client; (void) data; + pkgconf_cli_state_t *state = client->client_data; - if (!(want_flags & PKG_KEEP_SYSTEM_LIBS) && pkgconf_fragment_has_system_dir(client, frag)) - return false; - - if (want_fragment_filter != NULL && (strchr(want_fragment_filter, frag->type) == NULL || !frag->type)) - return false; - - switch (frag->type) - { - case 'L': got_flags = PKG_LIBS_ONLY_LDPATH; break; - case 'l': got_flags = PKG_LIBS_ONLY_LIBNAME; break; - default: got_flags = PKG_LIBS_ONLY_OTHER; break; - } - - return (want_flags & got_flags) != 0; -} - -static void -print_variables(pkgconf_pkg_t *pkg) -{ - pkgconf_node_t *node; - - PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, node) - { - pkgconf_tuple_t *tuple = node->data; - - printf("%s\n", tuple->key); - } -} - -static void -print_requires(pkgconf_pkg_t *pkg) -{ - pkgconf_node_t *node; - - PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node) - { - pkgconf_dependency_t *dep = node->data; - - printf("%s", dep->package); - - if (dep->version != NULL) - printf(" %s %s", pkgconf_pkg_get_comparator(dep), dep->version); - - printf("\n"); - } -} - -static void -print_requires_private(pkgconf_pkg_t *pkg) -{ - pkgconf_node_t *node; - - PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node) - { - pkgconf_dependency_t *dep = node->data; - - printf("%s", dep->package); - - if (dep->version != NULL) - printf(" %s %s", pkgconf_pkg_get_comparator(dep), dep->version); - - printf("\n"); - } -} - -static void -print_provides(pkgconf_pkg_t *pkg) -{ - pkgconf_node_t *node; - - PKGCONF_FOREACH_LIST_ENTRY(pkg->provides.head, node) - { - pkgconf_dependency_t *dep = node->data; - - printf("%s", dep->package); - - if (dep->version != NULL) - printf(" %s %s", pkgconf_pkg_get_comparator(dep), dep->version); - - printf("\n"); - } -} - -static bool -apply_provides(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) client; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_provides(pkg); - } - - return true; -} - -#ifndef PKGCONF_LITE -static void -print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - pkgconf_node_t *node; - (void) client; - pkgconf_pkg_t **last_seen = data; - - if(pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) - return; - - if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) - printf("\"%s\" [fontname=Sans fontsize=8 fontcolor=gray color=gray]\n", pkg->id); - else - printf("\"%s\" [fontname=Sans fontsize=8]\n", pkg->id); - - if (last_seen != NULL) - { - if (*last_seen != NULL) - printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=red]\n", (*last_seen)->id, pkg->id); - - *last_seen = pkg; - } - - PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node) - { - pkgconf_dependency_t *dep = node->data; - const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package; - - if ((dep->flags & PKGCONF_PKG_DEPF_PRIVATE) == 0) - printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg->id, dep_id); - else - printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id); - } - - PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node) - { - pkgconf_dependency_t *dep = node->data; - const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package; - - printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id); - } -} - -static bool -apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - pkgconf_list_t *list = data; - pkgconf_pkg_t *last_seen = NULL; - pkgconf_node_t *iter; - - printf("digraph deptree {\n"); - printf("edge [color=blue len=7.5 fontname=Sans fontsize=8]\n"); - printf("node [fontname=Sans fontsize=8]\n"); - printf("\"user:request\" [fontname=Sans fontsize=8]\n"); - - PKGCONF_FOREACH_LIST_ENTRY(list->head, iter) - { - pkgconf_queue_t *pkgq = iter->data; - pkgconf_pkg_t *pkg = pkgconf_pkg_find(client, pkgq->package); - printf("\"user:request\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg == NULL ? pkgq->package : pkg->id); - if (pkg != NULL) - pkgconf_pkg_unref(client, pkg); - } - - eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, &last_seen, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - printf("}\n"); - return true; -} - -static void -print_solution_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused) -{ - (void) client; - (void) unused; - - printf("%s (%"PRIu64")%s\n", pkg->id, pkg->identifier, (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) == PKGCONF_PKG_PROPF_VISITED_PRIVATE ? " [private]" : ""); -} - -static bool -apply_print_solution(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_solution_node, unused, maxdepth, 0); - - return eflag == PKGCONF_PKG_ERRF_OK; -} -#endif - -static bool -apply_modversion(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - pkgconf_node_t *queue_iter; - pkgconf_list_t *pkgq = data; - (void) client; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(pkgq->head, queue_iter) - { - pkgconf_node_t *world_iter; - pkgconf_queue_t *queue_node = queue_iter->data; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) - { - pkgconf_dependency_t *dep = world_iter->data; - pkgconf_pkg_t *pkg = dep->match; - - const size_t name_len = strlen(pkg->why); - if (name_len > strlen(queue_node->package) || - strncmp(pkg->why, queue_node->package, name_len) || - (queue_node->package[name_len] != 0 && - !isspace((unsigned char)queue_node->package[name_len]) && - !PKGCONF_IS_OPERATOR_CHAR(queue_node->package[name_len]))) - continue; - - if (pkg->version != NULL) { - if (verbosity) - printf("%s: ", pkg->id); - - printf("%s\n", pkg->version); - } - - break; - } - } - - return true; -} - -static bool -apply_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) client; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_variables(pkg); - } - - return true; -} - -static bool -apply_path(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) client; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - /* a module entry with no filename is either virtual, static (builtin) or synthesized. */ - if (pkg->filename != NULL) - printf("%s\n", pkg->filename); - } - - return true; -} - -static bool -apply_variable(pkgconf_client_t *client, pkgconf_pkg_t *world, void *variable, int maxdepth) -{ - pkgconf_node_t *iter; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - const char *var; - - var = pkgconf_tuple_find(client, &pkg->vars, variable); - - if (var != NULL) - printf("%s%s", iter->prev != NULL ? " " : "", var); - } - - printf("\n"); - - return true; -} - -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)) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; - unsigned int eflag; - char *render_buf; - - eflag = collect_fn(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_fn, NULL); - - if (postprocess_fn != NULL) - postprocess_fn(client, world, &filtered_list); - - if (filtered_list.head == NULL) - goto out; - - render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops); - printf("%s='%s'\n", prefix, render_buf); - free(render_buf); - -out: - pkgconf_fragment_free(&unfiltered_list); - pkgconf_fragment_free(&filtered_list); + if (state->error_msgout == NULL) + return true; + pkgconf_output_file_fmt(state->error_msgout, "%s", msg); return true; } static void -maybe_add_module_definitions(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list) -{ - pkgconf_node_t *world_iter; - - if ((want_flags & PKG_EXISTS_CFLAGS) != PKG_EXISTS_CFLAGS) - return; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) - { - pkgconf_dependency_t *dep = world_iter->data; - char havebuf[PKGCONF_ITEM_SIZE]; - char *p; - - if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY) - continue; - - if (dep->match == NULL) - continue; - - snprintf(havebuf, sizeof havebuf, "HAVE_%s", dep->match->id); - - for (p = havebuf; *p; p++) - { - switch (*p) - { - case ' ': - case '-': - *p = '_'; - break; - - default: - *p = toupper((unsigned char) *p); - } - } - - pkgconf_fragment_insert(client, fragment_list, 'D', havebuf, false); - } -} - -static void -apply_env_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, const char *env_prefix) -{ - (void) client; - pkgconf_node_t *world_iter; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter) - { - pkgconf_dependency_t *dep = world_iter->data; - pkgconf_pkg_t *pkg = dep->match; - pkgconf_node_t *tuple_iter; - - if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY) - continue; - - if (dep->match == NULL) - continue; - - PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, tuple_iter) - { - pkgconf_tuple_t *tuple = tuple_iter->data; - char havebuf[PKGCONF_ITEM_SIZE]; - char *p; - - if (want_variable != NULL && strcmp(want_variable, tuple->key)) - continue; - - snprintf(havebuf, sizeof havebuf, "%s_%s", env_prefix, tuple->key); - - for (p = havebuf; *p; p++) - { - switch (*p) - { - case ' ': - case '-': - *p = '_'; - break; - - default: - *p = toupper((unsigned char) *p); - } - } - - printf("%s='%s'\n", havebuf, tuple->value); - } - } -} - -static bool -apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, int maxdepth) -{ - const char *want_env_prefix = env_prefix_p, *it; - char workbuf[PKGCONF_ITEM_SIZE]; - - for (it = want_env_prefix; *it != '\0'; it++) - if (!isalpha((unsigned char)*it) && - !isdigit((unsigned char)*it)) - return false; - - snprintf(workbuf, sizeof workbuf, "%s_CFLAGS", want_env_prefix); - if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_cflags, filter_cflags, maybe_add_module_definitions)) - return false; - - snprintf(workbuf, sizeof workbuf, "%s_LIBS", want_env_prefix); - if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_libs, filter_libs, NULL)) - return false; - - if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES || want_variable != NULL) - apply_env_variables(client, world, want_env_prefix); - - return true; -} - -static bool -apply_cflags(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; - int eflag; - char *render_buf; - (void) unused; - - eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_cflags, NULL); - maybe_add_module_definitions(client, world, &filtered_list); - - if (filtered_list.head == NULL) - goto out; - - render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops); - printf("%s", render_buf); - free(render_buf); - -out: - pkgconf_fragment_free(&unfiltered_list); - pkgconf_fragment_free(&filtered_list); - - return true; -} - -static bool -apply_libs(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; - int eflag; - char *render_buf; - (void) unused; - - eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_libs, NULL); - - if (filtered_list.head == NULL) - goto out; - - render_buf = pkgconf_fragment_render(&filtered_list, true, want_render_ops); - printf("%s", render_buf); - free(render_buf); - -out: - pkgconf_fragment_free(&unfiltered_list); - pkgconf_fragment_free(&filtered_list); - - return true; -} - -static bool -apply_requires(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) -{ - pkgconf_node_t *iter; - (void) client; - (void) unused; - (void) maxdepth; - - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) - { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_requires(pkg); - } - - return true; -} - -static bool -apply_requires_private(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth) +unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions) { - pkgconf_node_t *iter; (void) client; - (void) unused; - (void) maxdepth; - PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) + if (pkgconf_unveil(path, permissions) == -1 && errno != ENOENT) { - pkgconf_dependency_t *dep = iter->data; - pkgconf_pkg_t *pkg = dep->match; - - print_requires_private(pkg); + pkgconf_output_file_fmt(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); } - return true; } static void -check_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - int *retval = data; - (void) client; - - if (pkg->flags & PKGCONF_PKG_PROPF_UNINSTALLED) - *retval = EXIT_SUCCESS; -} - -static bool -apply_uninstalled(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +relocate_path(const char *path) { - int eflag; + pkgconf_buffer_t pathbuf = PKGCONF_BUFFER_INITIALIZER; - eflag = pkgconf_pkg_traverse(client, world, check_uninstalled, data, maxdepth, 0); + pkgconf_buffer_append(&pathbuf, path); + pkgconf_path_relocate(&pathbuf); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; + printf("%s\n", pkgconf_buffer_str(&pathbuf)); - return true; + pkgconf_buffer_finalize(&pathbuf); } #ifndef PKGCONF_LITE -static void -print_graph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) -{ - pkgconf_node_t *n; - - (void) client; - (void) data; - - printf("node '%s' {\n", pkg->id); - - if (pkg->version != NULL) - printf(" version = '%s';\n", pkg->version); - - PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, n) - { - pkgconf_dependency_t *dep = n->data; - printf(" dependency '%s'", dep->package); - if (dep->compare != PKGCONF_CMP_ANY) - { - printf(" {\n"); - printf(" comparator = '%s';\n", pkgconf_pkg_get_comparator(dep)); - printf(" version = '%s';\n", dep->version); - printf(" };\n"); - } - else - printf(";\n"); - } - - printf("};\n"); -} - -static bool -apply_simulate(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) +static pkgconf_cross_personality_t * +deduce_personality(char *argv[]) { - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_graph_node, data, maxdepth, 0); + const char *argv0 = argv[0]; + char *i, *prefix; + pkgconf_cross_personality_t *out; - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; + i = strrchr(argv0, '/'); + if (i != NULL) + argv0 = i + 1; - return true; -} +#if defined(_WIN32) || defined(_WIN64) + i = strrchr(argv0, '\\'); + if (i != NULL) + argv0 = i + 1; #endif -static void -print_fragment_tree_branch(pkgconf_list_t *fragment_list, int indent) -{ - pkgconf_node_t *iter; - - PKGCONF_FOREACH_LIST_ENTRY(fragment_list->head, iter) - { - pkgconf_fragment_t *frag = iter->data; - - if (frag->type) - printf("%*s'-%c%s' [type %c]\n", indent, "", frag->type, frag->data, frag->type); - else - printf("%*s'%s' [untyped]\n", indent, "", frag->data); + i = strstr(argv0, "-pkg"); + if (i == NULL) + return pkgconf_cross_personality_default(); - print_fragment_tree_branch(&frag->children, indent + 2); - } + prefix = pkgconf_strndup(argv0, i - argv0); + out = pkgconf_cross_personality_find(prefix); + free(prefix); + if (out == NULL) + return pkgconf_cross_personality_default(); - if (fragment_list->head != NULL) - printf("\n"); + return out; } +#endif -static bool -apply_fragment_tree(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; - int eflag; - - (void) data; - - eflag = pkgconf_pkg_cflags(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - eflag = pkgconf_pkg_libs(client, world, &unfiltered_list, maxdepth); - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - print_fragment_tree_branch(&unfiltered_list, 0); - pkgconf_fragment_free(&unfiltered_list); - - return true; -} +#ifdef _WIN32 +static UINT original_console_cp; +static UINT original_console_out_cp; static void -print_license(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) +restore_console_code_page(void) { - (void) client; - (void) data; - - if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) - return; - - /* NOASSERTION is the default when the license is unknown, per SPDX spec ยง 3.15 */ - printf("%s: %s\n", pkg->id, pkg->license != NULL ? pkg->license : "NOASSERTION"); -} - -static bool -apply_license(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) -{ - int eflag; - - eflag = pkgconf_pkg_traverse(client, world, print_license, data, maxdepth, 0); - - if (eflag != PKGCONF_PKG_ERRF_OK) - return false; - - return true; + SetConsoleCP(original_console_cp); + SetConsoleOutputCP(original_console_out_cp); } +#endif static void version(void) @@ -931,6 +209,7 @@ usage(void) printf(" --print-variables print all known variables in module to stdout\n"); #ifndef PKGCONF_LITE printf(" --digraph print entire dependency graph in graphviz 'dot' format\n"); + printf(" --print-digraph-query-nodes also print query nodes in 'dot' format\n"); printf(" --solution print dependency graph solution in a simple format\n"); #endif printf(" --keep-system-cflags keep -I%s entries in cflags output\n", SYSTEM_INCLUDEDIR); @@ -939,6 +218,8 @@ usage(void) printf(" --modversion print the specified module's version to stdout\n"); printf(" --internal-cflags do not filter 'internal' cflags from output\n"); printf(" --license print the specified module's license to stdout if known\n"); + printf(" --link-abi print the link ABIs (e.g. c, c++) the module must be linked against\n"); + printf(" --source print the specified module's source code location to stdout if known\n"); printf(" --exists-cflags add -DHAVE_FOO fragments to cflags for each found module\n"); printf("\nfiltering output:\n\n"); @@ -948,162 +229,44 @@ usage(void) printf(" --fragment-filter=types filter output fragments to the specified types\n"); printf(" --env=prefix print output as shell-compatible environmental variables\n"); printf(" --fragment-tree visualize printed CFLAGS/LIBS fragments as a tree\n"); + printf(" --newlines use newlines for whitespace between fragments\n"); printf("\nreport bugs to <%s>.\n", PACKAGE_BUGREPORT); } -static void -relocate_path(const char *path) -{ - char buf[PKGCONF_BUFSIZE]; - - pkgconf_strlcpy(buf, path, sizeof buf); - pkgconf_path_relocate(buf, sizeof buf); - - printf("%s\n", buf); -} - -#ifndef PKGCONF_LITE -static void -dump_personality(const pkgconf_cross_personality_t *p) +int +main(int argc, char *argv[]) { - pkgconf_node_t *n; - - printf("Triplet: %s\n", p->name); - - if (p->sysroot_dir) - printf("SysrootDir: %s\n", p->sysroot_dir); - - printf("DefaultSearchPaths: "); - PKGCONF_FOREACH_LIST_ENTRY(p->dir_list.head, n) - { - pkgconf_path_t *pn = n->data; - printf("%s ", pn->path); - } - - printf("\n"); - printf("SystemIncludePaths: "); - PKGCONF_FOREACH_LIST_ENTRY(p->filter_includedirs.head, n) - { - pkgconf_path_t *pn = n->data; - printf("%s ", pn->path); - } - - printf("\n"); - printf("SystemLibraryPaths: "); - PKGCONF_FOREACH_LIST_ENTRY(p->filter_libdirs.head, n) +#ifdef _WIN32 + // When activeCodePage is set to UTF-8 in the application manifest (requires Windows 1903+), + // GetACP() returns CP_UTF8 but the console code pages are not automatically updated to match. + // Detect this condition via GetACP() == CP_UTF8 and align the console code pages accordingly. + // Restoring on exit is safe: if ACP is already CP_UTF8, resetting to the saved values is a no-op. + if (GetACP() == CP_UTF8) { - pkgconf_path_t *pn = n->data; - printf("%s ", pn->path); + original_console_cp = GetConsoleCP(); + original_console_out_cp = GetConsoleOutputCP(); + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + atexit(restore_console_code_page); } - - printf("\n"); -} - -static pkgconf_cross_personality_t * -deduce_personality(char *argv[]) -{ - const char *argv0 = argv[0]; - char *i, *prefix; - pkgconf_cross_personality_t *out; - - i = strrchr(argv0, '/'); - if (i != NULL) - argv0 = i + 1; - -#if defined(_WIN32) || defined(_WIN64) - i = strrchr(argv0, '\\'); - if (i != NULL) - argv0 = i + 1; -#endif - - i = strstr(argv0, "-pkg"); - if (i == NULL) - return pkgconf_cross_personality_default(); - - prefix = pkgconf_strndup(argv0, i - argv0); - out = pkgconf_cross_personality_find(prefix); - free(prefix); - if (out == NULL) - return pkgconf_cross_personality_default(); - - return out; -} #endif -static void -unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions) -{ - (void) client; - - if (pkgconf_unveil(path, permissions) == -1) - { - fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } -} - -static bool -unveil_search_paths(const pkgconf_client_t *client, const pkgconf_cross_personality_t *personality) -{ - pkgconf_node_t *n; - - if (pkgconf_unveil("/dev/null", "rwc") == -1) - return false; - - PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n) - { - pkgconf_path_t *pn = n->data; - - if (pkgconf_unveil(pn->path, "r") == -1) - return false; - } - - PKGCONF_FOREACH_LIST_ENTRY(personality->dir_list.head, n) - { - pkgconf_path_t *pn = n->data; - - if (pkgconf_unveil(pn->path, "r") == -1) - return false; - } - - pkgconf_client_set_unveil_handler(&pkg_client, unveil_handler); - - return true; -} - -int -main(int argc, char *argv[]) -{ int ret; - pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER; + pkgconf_cli_state_t state = { + .want_flags = 0, + }; pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER; - char *builddir; - char *sysroot_dir; char *env_traverse_depth; - char *required_pkgconfig_version = NULL; - char *required_exact_module_version = NULL; - char *required_max_module_version = NULL; - char *required_module_version = NULL; char *logfile_arg = NULL; - char *want_env_prefix = NULL; - unsigned int want_client_flags = PKGCONF_PKG_PKGF_NONE; pkgconf_cross_personality_t *personality = NULL; - bool opened_error_msgout = false; - pkgconf_pkg_t world = { - .id = "virtual:world", - .realname = "virtual world package", - .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL, - }; if (pkgconf_pledge("stdio rpath wpath cpath unveil", NULL) == -1) { - fprintf(stderr, "pkgconf: pledge failed: %s\n", strerror(errno)); + pkgconf_output_file_fmt(stderr, "pkgconf: pledge failed: %s\n", strerror(errno)); return EXIT_FAILURE; } - want_flags = 0; - #ifdef _WIN32 /* When running regression tests in cygwin, and building native * executable, tests fail unless native executable outputs unix @@ -1115,85 +278,92 @@ main(int argc, char *argv[]) #endif struct pkg_option options[] = { - { "version", no_argument, &want_flags, PKG_VERSION|PKG_PRINT_ERRORS, }, - { "about", no_argument, &want_flags, PKG_ABOUT|PKG_PRINT_ERRORS, }, + { "version", no_argument, &state.want_flags, PKG_VERSION|PKG_PRINT_ERRORS, }, + { "about", no_argument, &state.want_flags, PKG_ABOUT|PKG_PRINT_ERRORS, }, { "atleast-version", required_argument, NULL, 2, }, { "atleast-pkgconfig-version", required_argument, NULL, 3, }, - { "libs", no_argument, &want_flags, PKG_LIBS|PKG_PRINT_ERRORS, }, - { "cflags", no_argument, &want_flags, PKG_CFLAGS|PKG_PRINT_ERRORS, }, - { "modversion", no_argument, &want_flags, PKG_MODVERSION|PKG_PRINT_ERRORS, }, + { "libs", no_argument, &state.want_flags, PKG_LIBS|PKG_PRINT_ERRORS, }, + { "cflags", no_argument, &state.want_flags, PKG_CFLAGS|PKG_PRINT_ERRORS, }, + { "modversion", no_argument, &state.want_flags, PKG_MODVERSION|PKG_PRINT_ERRORS, }, { "variable", required_argument, NULL, 7, }, - { "exists", no_argument, &want_flags, PKG_EXISTS, }, - { "print-errors", no_argument, &want_flags, PKG_PRINT_ERRORS, }, - { "short-errors", no_argument, &want_flags, PKG_SHORT_ERRORS, }, + { "exists", no_argument, &state.want_flags, PKG_EXISTS, }, + { "print-errors", no_argument, &state.want_flags, PKG_PRINT_ERRORS, }, + { "short-errors", no_argument, &state.want_flags, PKG_SHORT_ERRORS, }, { "maximum-traverse-depth", required_argument, NULL, 11, }, - { "static", no_argument, &want_flags, PKG_STATIC, }, - { "shared", no_argument, &want_flags, PKG_SHARED, }, - { "pure", no_argument, &want_flags, PKG_PURE, }, - { "print-requires", no_argument, &want_flags, PKG_REQUIRES, }, - { "print-variables", no_argument, &want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, }, + { "static", no_argument, &state.want_flags, PKG_STATIC, }, + { "shared", no_argument, &state.want_flags, PKG_SHARED, }, + { "pure", no_argument, &state.want_flags, PKG_PURE, }, + { "print-requires", no_argument, &state.want_flags, PKG_REQUIRES, }, + { "print-variables", no_argument, &state.want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, }, #ifndef PKGCONF_LITE - { "digraph", no_argument, &want_flags, PKG_DIGRAPH, }, - { "solution", no_argument, &want_flags, PKG_SOLUTION, }, + { "digraph", no_argument, &state.want_flags, PKG_DIGRAPH, }, + { "solution", no_argument, &state.want_flags, PKG_SOLUTION, }, #endif - { "help", no_argument, &want_flags, PKG_HELP, }, - { "env-only", no_argument, &want_flags, PKG_ENV_ONLY, }, - { "print-requires-private", no_argument, &want_flags, PKG_REQUIRES_PRIVATE, }, - { "cflags-only-I", no_argument, &want_flags, PKG_CFLAGS_ONLY_I|PKG_PRINT_ERRORS, }, - { "cflags-only-other", no_argument, &want_flags, PKG_CFLAGS_ONLY_OTHER|PKG_PRINT_ERRORS, }, - { "libs-only-L", no_argument, &want_flags, PKG_LIBS_ONLY_LDPATH|PKG_PRINT_ERRORS, }, - { "libs-only-l", no_argument, &want_flags, PKG_LIBS_ONLY_LIBNAME|PKG_PRINT_ERRORS, }, - { "libs-only-other", no_argument, &want_flags, PKG_LIBS_ONLY_OTHER|PKG_PRINT_ERRORS, }, - { "uninstalled", no_argument, &want_flags, PKG_UNINSTALLED, }, - { "no-uninstalled", no_argument, &want_flags, PKG_NO_UNINSTALLED, }, - { "keep-system-cflags", no_argument, &want_flags, PKG_KEEP_SYSTEM_CFLAGS, }, - { "keep-system-libs", no_argument, &want_flags, PKG_KEEP_SYSTEM_LIBS, }, + { "help", no_argument, &state.want_flags, PKG_HELP, }, + { "env-only", no_argument, &state.want_flags, PKG_ENV_ONLY, }, + { "print-requires-private", no_argument, &state.want_flags, PKG_REQUIRES_PRIVATE, }, + { "cflags-only-I", no_argument, &state.want_flags, PKG_CFLAGS_ONLY_I|PKG_PRINT_ERRORS, }, + { "cflags-only-other", no_argument, &state.want_flags, PKG_CFLAGS_ONLY_OTHER|PKG_PRINT_ERRORS, }, + { "libs-only-L", no_argument, &state.want_flags, PKG_LIBS_ONLY_LDPATH|PKG_PRINT_ERRORS, }, + { "libs-only-l", no_argument, &state.want_flags, PKG_LIBS_ONLY_LIBNAME|PKG_PRINT_ERRORS, }, + { "libs-only-other", no_argument, &state.want_flags, PKG_LIBS_ONLY_OTHER|PKG_PRINT_ERRORS, }, + { "uninstalled", no_argument, &state.want_flags, PKG_UNINSTALLED, }, + { "no-uninstalled", no_argument, &state.want_flags, PKG_NO_UNINSTALLED, }, + { "keep-system-cflags", no_argument, &state.want_flags, PKG_KEEP_SYSTEM_CFLAGS, }, + { "keep-system-libs", no_argument, &state.want_flags, PKG_KEEP_SYSTEM_LIBS, }, { "define-variable", required_argument, NULL, 27, }, { "exact-version", required_argument, NULL, 28, }, { "max-version", required_argument, NULL, 29, }, - { "ignore-conflicts", no_argument, &want_flags, PKG_IGNORE_CONFLICTS, }, - { "errors-to-stdout", no_argument, &want_flags, PKG_ERRORS_ON_STDOUT, }, - { "silence-errors", no_argument, &want_flags, PKG_SILENCE_ERRORS, }, - { "list-all", no_argument, &want_flags, PKG_LIST|PKG_PRINT_ERRORS, }, - { "list-package-names", no_argument, &want_flags, PKG_LIST_PACKAGE_NAMES|PKG_PRINT_ERRORS, }, + { "ignore-conflicts", no_argument, &state.want_flags, PKG_IGNORE_CONFLICTS, }, + { "errors-to-stdout", no_argument, &state.want_flags, PKG_ERRORS_ON_STDOUT, }, + { "silence-errors", no_argument, &state.want_flags, PKG_SILENCE_ERRORS, }, + { "list-all", no_argument, &state.want_flags, PKG_LIST|PKG_PRINT_ERRORS, }, + { "list-package-names", no_argument, &state.want_flags, PKG_LIST_PACKAGE_NAMES|PKG_PRINT_ERRORS, }, #ifndef PKGCONF_LITE - { "simulate", no_argument, &want_flags, PKG_SIMULATE, }, + { "simulate", no_argument, &state.want_flags, PKG_SIMULATE, }, #endif - { "no-cache", no_argument, &want_flags, PKG_NO_CACHE, }, - { "print-provides", no_argument, &want_flags, PKG_PROVIDES, }, - { "no-provides", no_argument, &want_flags, PKG_NO_PROVIDES, }, - { "debug", no_argument, &want_flags, PKG_DEBUG|PKG_PRINT_ERRORS, }, - { "validate", no_argument, &want_flags, PKG_VALIDATE|PKG_PRINT_ERRORS|PKG_ERRORS_ON_STDOUT }, + { "no-cache", no_argument, &state.want_flags, PKG_NO_CACHE, }, + { "print-provides", no_argument, &state.want_flags, PKG_PROVIDES, }, + { "no-provides", no_argument, &state.want_flags, PKG_NO_PROVIDES, }, + { "debug", no_argument, &state.want_flags, PKG_DEBUG|PKG_PRINT_ERRORS, }, + { "validate", no_argument, &state.want_flags, PKG_VALIDATE|PKG_PRINT_ERRORS|PKG_ERRORS_ON_STDOUT }, { "log-file", required_argument, NULL, 40 }, - { "path", no_argument, &want_flags, PKG_PATH }, + { "path", no_argument, &state.want_flags, PKG_PATH }, { "with-path", required_argument, NULL, 42 }, { "prefix-variable", required_argument, NULL, 43 }, - { "define-prefix", no_argument, &want_flags, PKG_DEFINE_PREFIX }, + { "define-prefix", no_argument, &state.want_flags, PKG_DEFINE_PREFIX }, { "relocate", required_argument, NULL, 45 }, - { "dont-define-prefix", no_argument, &want_flags, PKG_DONT_DEFINE_PREFIX }, - { "dont-relocate-paths", no_argument, &want_flags, PKG_DONT_RELOCATE_PATHS }, + { "dont-define-prefix", no_argument, &state.want_flags, PKG_DONT_DEFINE_PREFIX }, + { "dont-relocate-paths", no_argument, &state.want_flags, PKG_DONT_RELOCATE_PATHS }, { "env", required_argument, NULL, 48 }, #ifndef PKGCONF_LITE - { "msvc-syntax", no_argument, &want_flags, PKG_MSVC_SYNTAX }, + { "msvc-syntax", no_argument, &state.want_flags, PKG_MSVC_SYNTAX }, #endif { "fragment-filter", required_argument, NULL, 50 }, - { "internal-cflags", no_argument, &want_flags, PKG_INTERNAL_CFLAGS }, + { "internal-cflags", no_argument, &state.want_flags, PKG_INTERNAL_CFLAGS }, #ifndef PKGCONF_LITE - { "dump-personality", no_argument, &want_flags, PKG_DUMP_PERSONALITY }, + { "dump-personality", no_argument, &state.want_flags, PKG_DUMP_PERSONALITY }, { "personality", required_argument, NULL, 53 }, #endif - { "license", no_argument, &want_flags, PKG_DUMP_LICENSE }, + { "license", no_argument, &state.want_flags, PKG_DUMP_LICENSE }, + { "license-file", no_argument, &state.want_flags, PKG_DUMP_LICENSE_FILE }, + { "link-abi", no_argument, &state.want_flags, PKG_LINK_ABI }, { "verbose", no_argument, NULL, 55 }, - { "exists-cflags", no_argument, &want_flags, PKG_EXISTS_CFLAGS }, - { "fragment-tree", no_argument, &want_flags, PKG_FRAGMENT_TREE }, + { "exists-cflags", no_argument, &state.want_flags, PKG_EXISTS_CFLAGS }, + { "fragment-tree", no_argument, &state.want_flags, PKG_FRAGMENT_TREE }, + { "source", no_argument, &state.want_flags, PKG_DUMP_SOURCE }, + { "newlines", no_argument, &state.want_flags, PKG_NEWLINES }, +#ifndef PKGCONF_LITE + { "print-digraph-query-nodes", no_argument, &state.want_flags, PKG_PRINT_DIGRAPH_QUERY_NODES }, +#endif { NULL, 0, NULL, 0 } }; #ifndef PKGCONF_LITE if (getenv("PKG_CONFIG_EARLY_TRACE")) { - error_msgout = stderr; - pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL); + state.error_msgout = stderr; + pkgconf_client_set_trace_handler(&state.pkg_client, error_handler, NULL); } #endif @@ -1202,25 +372,25 @@ main(int argc, char *argv[]) switch (ret) { case 2: - required_module_version = pkg_optarg; + state.required_module_version = pkg_optarg; break; case 3: - required_pkgconfig_version = pkg_optarg; + state.required_pkgconfig_version = pkg_optarg; break; case 7: - want_variable = pkg_optarg; + state.want_variable = pkg_optarg; break; case 11: - maximum_traverse_depth = atoi(pkg_optarg); + state.maximum_traverse_depth = atoi(pkg_optarg); break; case 27: - pkgconf_tuple_define_global(&pkg_client, pkg_optarg); + pkgconf_tuple_define_global(&state.pkg_client, pkg_optarg); break; case 28: - required_exact_module_version = pkg_optarg; + state.required_exact_module_version = pkg_optarg; break; case 29: - required_max_module_version = pkg_optarg; + state.required_max_module_version = pkg_optarg; break; case 40: logfile_arg = pkg_optarg; @@ -1229,16 +399,16 @@ main(int argc, char *argv[]) pkgconf_path_prepend(pkg_optarg, &dir_list, true); break; case 43: - pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg); + pkgconf_client_set_prefix_varname(&state.pkg_client, pkg_optarg); break; case 45: relocate_path(pkg_optarg); return EXIT_SUCCESS; case 48: - want_env_prefix = pkg_optarg; + state.want_env_prefix = pkg_optarg; break; case 50: - want_fragment_filter = pkg_optarg; + state.want_fragment_filter = pkg_optarg; break; #ifndef PKGCONF_LITE case 53: @@ -1246,7 +416,7 @@ main(int argc, char *argv[]) break; #endif case 55: - verbosity++; + state.verbosity++; break; case '?': case ':': @@ -1265,55 +435,41 @@ main(int argc, char *argv[]) #endif } -#ifndef PKGCONF_LITE - if ((want_flags & PKG_DUMP_PERSONALITY) == PKG_DUMP_PERSONALITY) - { - dump_personality(personality); - return EXIT_SUCCESS; - } -#endif - /* now, bring up the client. settings are preserved since the client is prealloced */ - pkgconf_client_init(&pkg_client, error_handler, NULL, personality); - - /* unveil the entire search path now that we have loaded the personality data. */ - if (!unveil_search_paths(&pkg_client, personality)) - { - fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); - return EXIT_FAILURE; - } + pkgconf_client_init(&state.pkg_client, error_handler, &state, personality, &state, environ_lookup_handler); + pkgconf_client_set_unveil_handler(&state.pkg_client, unveil_handler); #ifndef PKGCONF_LITE - if ((want_flags & PKG_MSVC_SYNTAX) == PKG_MSVC_SYNTAX || getenv("PKG_CONFIG_MSVC_SYNTAX") != NULL) - want_render_ops = msvc_renderer_get(); + if (getenv("PKG_CONFIG_MSVC_SYNTAX") != NULL) + state.want_flags |= PKG_MSVC_SYNTAX; #endif if ((env_traverse_depth = getenv("PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH")) != NULL) - maximum_traverse_depth = atoi(env_traverse_depth); + state.maximum_traverse_depth = atoi(env_traverse_depth); - if ((want_flags & PKG_PRINT_ERRORS) != PKG_PRINT_ERRORS) - want_flags |= (PKG_SILENCE_ERRORS); + if ((state.want_flags & PKG_PRINT_ERRORS) != PKG_PRINT_ERRORS) + state.want_flags |= (PKG_SILENCE_ERRORS); - if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS && !getenv("PKG_CONFIG_DEBUG_SPEW")) - want_flags |= (PKG_SILENCE_ERRORS); + if ((state.want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS && !getenv("PKG_CONFIG_DEBUG_SPEW")) + state.want_flags |= (PKG_SILENCE_ERRORS); else - want_flags &= ~(PKG_SILENCE_ERRORS); + state.want_flags &= ~(PKG_SILENCE_ERRORS); if (getenv("PKG_CONFIG_DONT_RELOCATE_PATHS")) - want_flags |= (PKG_DONT_RELOCATE_PATHS); + state.want_flags |= (PKG_DONT_RELOCATE_PATHS); - if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE || (want_flags & PKG_DEBUG) == PKG_DEBUG) - pkgconf_client_set_warn_handler(&pkg_client, error_handler, NULL); + if ((state.want_flags & PKG_VALIDATE) == PKG_VALIDATE || (state.want_flags & PKG_DEBUG) == PKG_DEBUG) + pkgconf_client_set_warn_handler(&state.pkg_client, error_handler, NULL); #ifndef PKGCONF_LITE - if ((want_flags & PKG_DEBUG) == PKG_DEBUG) - pkgconf_client_set_trace_handler(&pkg_client, error_handler, NULL); + if ((state.want_flags & PKG_DEBUG) == PKG_DEBUG) + pkgconf_client_set_trace_handler(&state.pkg_client, error_handler, NULL); #endif - pkgconf_path_prepend_list(&pkg_client.dir_list, &dir_list); + pkgconf_path_prepend_list(&state.pkg_client.dir_list, &dir_list); pkgconf_path_free(&dir_list); - if ((want_flags & PKG_ABOUT) == PKG_ABOUT) + if ((state.want_flags & PKG_ABOUT) == PKG_ABOUT) { about(); @@ -1321,7 +477,7 @@ main(int argc, char *argv[]) goto out; } - if ((want_flags & PKG_VERSION) == PKG_VERSION) + if ((state.want_flags & PKG_VERSION) == PKG_VERSION) { version(); @@ -1329,7 +485,7 @@ main(int argc, char *argv[]) goto out; } - if ((want_flags & PKG_HELP) == PKG_HELP) + if ((state.want_flags & PKG_HELP) == PKG_HELP) { usage(); @@ -1337,148 +493,6 @@ main(int argc, char *argv[]) goto out; } - if (getenv("PKG_CONFIG_FDO_SYSROOT_RULES")) - want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES; - - if (getenv("PKG_CONFIG_PKGCONF1_SYSROOT_RULES")) - want_client_flags |= PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES; - - if ((want_flags & PKG_SHORT_ERRORS) == PKG_SHORT_ERRORS) - want_client_flags |= PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS; - - if ((want_flags & PKG_DONT_RELOCATE_PATHS) == PKG_DONT_RELOCATE_PATHS) - want_client_flags |= PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS; - - error_msgout = stderr; - if ((want_flags & PKG_ERRORS_ON_STDOUT) == PKG_ERRORS_ON_STDOUT) - error_msgout = stdout; - if ((want_flags & PKG_SILENCE_ERRORS) == PKG_SILENCE_ERRORS) { - error_msgout = fopen(PATH_DEV_NULL, "w"); - opened_error_msgout = true; - } - - if ((want_flags & PKG_IGNORE_CONFLICTS) == PKG_IGNORE_CONFLICTS || getenv("PKG_CONFIG_IGNORE_CONFLICTS") != NULL) - want_client_flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS; - - if ((want_flags & PKG_STATIC) == PKG_STATIC || personality->want_default_static) - want_client_flags |= (PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS); - - if ((want_flags & PKG_SHARED) == PKG_SHARED) - want_client_flags &= ~(PKGCONF_PKG_PKGF_SEARCH_PRIVATE | PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS); - - /* if --static and --pure are both specified, then disable merge-back. - * this allows for a --static which searches private modules, but has the same fragment behaviour as if - * --static were disabled. see <https://github.com/pkgconf/pkgconf/issues/83> for rationale. - */ - if ((want_flags & PKG_PURE) == PKG_PURE || getenv("PKG_CONFIG_PURE_DEPGRAPH") != NULL || personality->want_default_pure) - want_client_flags &= ~PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS; - - if ((want_flags & PKG_ENV_ONLY) == PKG_ENV_ONLY) - want_client_flags |= PKGCONF_PKG_PKGF_ENV_ONLY; - - if ((want_flags & PKG_NO_CACHE) == PKG_NO_CACHE) - want_client_flags |= PKGCONF_PKG_PKGF_NO_CACHE; - -/* On Windows we want to always redefine the prefix by default - * but allow that behavior to be manually disabled */ -#if !defined(_WIN32) && !defined(_WIN64) - if ((want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX || getenv("PKG_CONFIG_RELOCATE_PATHS") != NULL) -#endif - want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX; - - if ((want_flags & PKG_NO_UNINSTALLED) == PKG_NO_UNINSTALLED || getenv("PKG_CONFIG_DISABLE_UNINSTALLED") != NULL) - want_client_flags |= PKGCONF_PKG_PKGF_NO_UNINSTALLED; - - if ((want_flags & PKG_NO_PROVIDES) == PKG_NO_PROVIDES) - want_client_flags |= PKGCONF_PKG_PKGF_SKIP_PROVIDES; - - if ((want_flags & PKG_DONT_DEFINE_PREFIX) == PKG_DONT_DEFINE_PREFIX || getenv("PKG_CONFIG_DONT_DEFINE_PREFIX") != NULL) - want_client_flags &= ~PKGCONF_PKG_PKGF_REDEFINE_PREFIX; - - if ((want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS) - want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS; - - /* if these selectors are used, it means that we are querying metadata. - * so signal to libpkgconf that we only want to walk the flattened dependency set. - */ - if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION || - (want_flags & PKG_REQUIRES) == PKG_REQUIRES || - (want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || - (want_flags & PKG_PROVIDES) == PKG_PROVIDES || - (want_flags & PKG_VARIABLES) == PKG_VARIABLES || - (want_flags & PKG_PATH) == PKG_PATH || - want_variable != NULL) - maximum_traverse_depth = 1; - - /* if we are asking for a variable, path or list of variables, this only makes sense - * for a single package. - */ - if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES || - (want_flags & PKG_PATH) == PKG_PATH || - want_variable != NULL) - maximum_package_count = 1; - - if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL) - want_flags |= PKG_KEEP_SYSTEM_CFLAGS; - - if (getenv("PKG_CONFIG_ALLOW_SYSTEM_LIBS") != NULL) - want_flags |= PKG_KEEP_SYSTEM_LIBS; - - if ((builddir = getenv("PKG_CONFIG_TOP_BUILD_DIR")) != NULL) - pkgconf_client_set_buildroot_dir(&pkg_client, builddir); - - if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || - (want_flags & PKG_CFLAGS)) - { - want_client_flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE; - } - - if ((sysroot_dir = getenv("PKG_CONFIG_SYSROOT_DIR")) != NULL) - { - const char *destdir; - - pkgconf_client_set_sysroot_dir(&pkg_client, sysroot_dir); - - if ((destdir = getenv("DESTDIR")) != NULL) - { - if (!strcmp(destdir, sysroot_dir)) - want_client_flags |= PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES; - } - } - - /* we have determined what features we want most likely. in some cases, we override later. */ - pkgconf_client_set_flags(&pkg_client, want_client_flags); - - /* at this point, want_client_flags should be set, so build the dir list */ - pkgconf_client_dir_list_build(&pkg_client, personality); - - /* preload any files in PKG_CONFIG_PRELOADED_FILES */ - pkgconf_client_preload_from_environ(&pkg_client, "PKG_CONFIG_PRELOADED_FILES"); - - if (required_pkgconfig_version != NULL) - { - if (pkgconf_compare_version(PACKAGE_VERSION, required_pkgconfig_version) >= 0) - ret = EXIT_SUCCESS; - else - ret = EXIT_FAILURE; - - goto out; - } - - if ((want_flags & PKG_LIST) == PKG_LIST) - { - pkgconf_scan_all(&pkg_client, NULL, print_list_entry); - ret = EXIT_SUCCESS; - goto out; - } - - if ((want_flags & PKG_LIST_PACKAGE_NAMES) == PKG_LIST_PACKAGE_NAMES) - { - pkgconf_scan_all(&pkg_client, NULL, print_package_entry); - ret = EXIT_SUCCESS; - goto out; - } - if (logfile_arg == NULL) logfile_arg = getenv("PKG_CONFIG_LOG"); @@ -1486,338 +500,23 @@ main(int argc, char *argv[]) { if (pkgconf_unveil(logfile_arg, "rwc") == -1) { - fprintf(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); + pkgconf_output_file_fmt(stderr, "pkgconf: unveil failed: %s\n", strerror(errno)); return EXIT_FAILURE; } - logfile_out = fopen(logfile_arg, "w"); - pkgconf_audit_set_log(&pkg_client, logfile_out); - } - - if (required_module_version != NULL) - { - pkgconf_pkg_t *pkg = NULL; - pkgconf_node_t *node; - pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; - - while (argv[pkg_optind]) - { - pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0); - pkg_optind++; - } - - PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) - { - pkgconf_dependency_t *pkgiter = node->data; - - pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package); - if (pkg == NULL) - { - if (want_flags & PKG_PRINT_ERRORS) - pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); - - ret = EXIT_FAILURE; - goto cleanup; - } - - if (pkgconf_compare_version(pkg->version, required_module_version) >= 0) - { - ret = EXIT_SUCCESS; - goto cleanup; - } - } - - ret = EXIT_FAILURE; -cleanup: - if (pkg != NULL) - pkgconf_pkg_unref(&pkg_client, pkg); - pkgconf_dependency_free(&deplist); - goto out; - } - else if (required_exact_module_version != NULL) - { - pkgconf_pkg_t *pkg = NULL; - pkgconf_node_t *node; - pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; - - while (argv[pkg_optind]) - { - pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0); - pkg_optind++; - } - - PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) - { - pkgconf_dependency_t *pkgiter = node->data; - - pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package); - if (pkg == NULL) - { - if (want_flags & PKG_PRINT_ERRORS) - pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); - - ret = EXIT_FAILURE; - goto cleanup2; - } - - if (pkgconf_compare_version(pkg->version, required_exact_module_version) == 0) - { - ret = EXIT_SUCCESS; - goto cleanup2; - } - } - - ret = EXIT_FAILURE; -cleanup2: - if (pkg != NULL) - pkgconf_pkg_unref(&pkg_client, pkg); - pkgconf_dependency_free(&deplist); - goto out; - } - else if (required_max_module_version != NULL) - { - pkgconf_pkg_t *pkg = NULL; - pkgconf_node_t *node; - pkgconf_list_t deplist = PKGCONF_LIST_INITIALIZER; - - while (argv[pkg_optind]) - { - pkgconf_dependency_parse_str(&pkg_client, &deplist, argv[pkg_optind], 0); - pkg_optind++; - } - - PKGCONF_FOREACH_LIST_ENTRY(deplist.head, node) - { - pkgconf_dependency_t *pkgiter = node->data; - - pkg = pkgconf_pkg_find(&pkg_client, pkgiter->package); - if (pkg == NULL) - { - if (want_flags & PKG_PRINT_ERRORS) - pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); - - ret = EXIT_FAILURE; - goto cleanup3; - } - - if (pkgconf_compare_version(pkg->version, required_max_module_version) <= 0) - { - ret = EXIT_SUCCESS; - goto cleanup3; - } - } - - ret = EXIT_FAILURE; -cleanup3: - if (pkg != NULL) - pkgconf_pkg_unref(&pkg_client, pkg); - pkgconf_dependency_free(&deplist); - goto out; - } - - while (1) - { - char *package = argv[pkg_optind]; - char *end; - - if (package == NULL) - break; - - /* check if there is a limit to the number of packages allowed to be included, if so and we have hit - * the limit, stop adding packages to the queue. - */ - if (maximum_package_count > 0 && pkgq.length >= maximum_package_count) - break; - - while (isspace((unsigned char)package[0])) - package++; - - /* skip empty packages */ - if (package[0] == '\0') { - pkg_optind++; - continue; - } - - end = package + strlen(package) - 1; - while(end > package && isspace((unsigned char)end[0])) end--; - end[1] = '\0'; - - if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1]))) - { - pkgconf_queue_push(&pkgq, package); - pkg_optind++; - } - else if (argv[pkg_optind + 2] == NULL) - { - char packagebuf[PKGCONF_BUFSIZE]; - - snprintf(packagebuf, sizeof packagebuf, "%s %s", package, argv[pkg_optind + 1]); - pkg_optind += 2; - - pkgconf_queue_push(&pkgq, packagebuf); - } - else - { - char packagebuf[PKGCONF_BUFSIZE]; - - snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]); - pkg_optind += 3; - - pkgconf_queue_push(&pkgq, packagebuf); - } - } - - if (pkgq.head == NULL) - { - fprintf(stderr, "Please specify at least one package name on the command line.\n"); - ret = EXIT_FAILURE; - goto out; - } - - ret = EXIT_SUCCESS; - - if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth)) - { - ret = EXIT_FAILURE; - goto out; - } - - /* we shouldn't need to unveil any more filesystem accesses from this point, so lock it down */ - if (pkgconf_unveil(NULL, NULL) == -1) - { - fprintf(stderr, "pkgconf: unveil lockdown failed: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - -#ifndef PKGCONF_LITE - if ((want_flags & PKG_SIMULATE) == PKG_SIMULATE) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ERRORS); - apply_simulate(&pkg_client, &world, NULL, -1); + state.logfile_out = fopen(logfile_arg, "a"); + pkgconf_audit_set_log(&state.pkg_client, state.logfile_out); } -#endif - - if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE) - goto out; - if ((want_flags & PKG_DUMP_LICENSE) == PKG_DUMP_LICENSE) - { - apply_license(&pkg_client, &world, &ret, 2); - goto out; - } - - if ((want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED) - { - ret = EXIT_FAILURE; - apply_uninstalled(&pkg_client, &world, &ret, 2); - goto out; - } - - if (want_env_prefix != NULL) - { - apply_env(&pkg_client, &world, want_env_prefix, 2); - goto out; - } - - if ((want_flags & PKG_PROVIDES) == PKG_PROVIDES) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_provides(&pkg_client, &world, NULL, 2); - } - -#ifndef PKGCONF_LITE - if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_digraph(&pkg_client, &world, &pkgq, 2); - } - - if ((want_flags & PKG_SOLUTION) == PKG_SOLUTION) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_print_solution(&pkg_client, &world, NULL, 2); - } -#endif - - if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_modversion(&pkg_client, &world, &pkgq, 2); - } - - if ((want_flags & PKG_PATH) == PKG_PATH) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL); - apply_path(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_variables(&pkg_client, &world, NULL, 2); - } - - if (want_variable) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - pkgconf_client_set_flags(&pkg_client, want_client_flags | PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL); - apply_variable(&pkg_client, &world, want_variable, 2); - } - - if ((want_flags & PKG_REQUIRES) == PKG_REQUIRES) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - apply_requires(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - apply_requires_private(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_FRAGMENT_TREE)) - { - want_flags &= ~(PKG_CFLAGS|PKG_LIBS); - - apply_fragment_tree(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_CFLAGS)) - { - apply_cflags(&pkg_client, &world, NULL, 2); - } - - if ((want_flags & PKG_LIBS)) - { - if (want_flags & PKG_CFLAGS) - printf(" "); - - if (!(want_flags & PKG_STATIC)) - pkgconf_client_set_flags(&pkg_client, pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE); + if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL) + state.want_flags |= PKG_KEEP_SYSTEM_CFLAGS; - apply_libs(&pkg_client, &world, NULL, 2); - } + if (getenv("PKG_CONFIG_ALLOW_SYSTEM_LIBS") != NULL) + state.want_flags |= PKG_KEEP_SYSTEM_LIBS; - if (want_flags & (PKG_CFLAGS|PKG_LIBS)) - printf("\n"); + return pkgconf_cli_run(&state, argc, argv, pkg_optind); out: - pkgconf_solution_free(&pkg_client, &world); - pkgconf_queue_free(&pkgq); - pkgconf_cross_personality_deinit(personality); - pkgconf_client_deinit(&pkg_client); - - if (logfile_out != NULL) - fclose(logfile_out); - if (opened_error_msgout) - fclose(error_msgout); - + pkgconf_cli_state_reset(&state); return ret; } |
