aboutsummaryrefslogtreecommitdiff
path: root/libpkgconf/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpkgconf/client.c')
-rw-r--r--libpkgconf/client.c141
1 files changed, 115 insertions, 26 deletions
diff --git a/libpkgconf/client.c b/libpkgconf/client.c
index 4fe36ecd9af9..be64950a4a92 100644
--- a/libpkgconf/client.c
+++ b/libpkgconf/client.c
@@ -2,6 +2,8 @@
* client.c
* libpkgconf consumer lifecycle management
*
+ * SPDX-License-Identifier: pkgconf
+ *
* Copyright (c) 2016 pkgconf authors (see AUTHORS).
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -60,7 +62,7 @@ trace_path_list(const pkgconf_client_t *client, const char *desc, pkgconf_list_t
void
pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality)
{
- pkgconf_path_build_from_environ("PKG_CONFIG_PATH", NULL, &client->dir_list, true);
+ pkgconf_path_build_from_environ(client, "PKG_CONFIG_PATH", NULL, &client->dir_list, true);
if (!(client->flags & PKGCONF_PKG_PKGF_ENV_ONLY))
{
@@ -72,10 +74,10 @@ pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_pers
(void) pkgconf_path_build_from_registry(HKEY_LOCAL_MACHINE, &client->dir_list, true);
#endif
- if (getenv("PKG_CONFIG_LIBDIR") != NULL)
+ if (pkgconf_client_getenv(client, "PKG_CONFIG_LIBDIR") != NULL)
{
/* PKG_CONFIG_LIBDIR= should empty the search path entirely. */
- (void) pkgconf_path_build_from_environ("PKG_CONFIG_LIBDIR", NULL, &dir_list, true);
+ (void) pkgconf_path_build_from_environ(client, "PKG_CONFIG_LIBDIR", NULL, &dir_list, true);
prepend_list = &dir_list;
}
@@ -87,7 +89,7 @@ pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_pers
/*
* !doc
*
- * .. c:function:: void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
+ * .. c:function:: void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler)
*
* Initialise a pkgconf client object.
*
@@ -95,11 +97,16 @@ pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_pers
* :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
* :param void* error_handler_data: user data passed to optional error handler
* :param pkgconf_cross_personality_t* personality: the cross-compile personality to use for defaults
+ * :param void* client_data: user data associated with the client
+ * :param pkgconf_environ_lookup_handler_func_t environ_lookup_handler: the lookup handler to use for environment variables
* :return: nothing
*/
void
-pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
+pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler)
{
+ client->personality = personality;
+ client->client_data = client_data;
+ client->environ_lookup_handler = environ_lookup_handler;
client->error_handler_data = error_handler_data;
client->error_handler = error_handler;
client->auditf = NULL;
@@ -121,36 +128,38 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
pkgconf_client_set_buildroot_dir(client, NULL);
pkgconf_client_set_prefix_varname(client, NULL);
- if(getenv("PKG_CONFIG_SYSTEM_LIBRARY_PATH") == NULL)
+ if(pkgconf_client_getenv(client, "PKG_CONFIG_SYSTEM_LIBRARY_PATH") == NULL)
pkgconf_path_copy_list(&client->filter_libdirs, &personality->filter_libdirs);
else
- pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_LIBRARY_PATH", NULL, &client->filter_libdirs, false);
+ pkgconf_path_build_from_environ(client, "PKG_CONFIG_SYSTEM_LIBRARY_PATH", NULL, &client->filter_libdirs, false);
- if(getenv("PKG_CONFIG_SYSTEM_INCLUDE_PATH") == NULL)
+ if(pkgconf_client_getenv(client, "PKG_CONFIG_SYSTEM_INCLUDE_PATH") == NULL)
pkgconf_path_copy_list(&client->filter_includedirs, &personality->filter_includedirs);
else
- pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
+ pkgconf_path_build_from_environ(client, "PKG_CONFIG_SYSTEM_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
/* GCC uses these environment variables to define system include paths, so we should check them. */
#ifdef __HAIKU__
- pkgconf_path_build_from_environ("BELIBRARIES", NULL, &client->filter_libdirs, false);
+ pkgconf_path_build_from_environ(client, "BELIBRARIES", NULL, &client->filter_libdirs, false);
#else
- pkgconf_path_build_from_environ("LIBRARY_PATH", NULL, &client->filter_libdirs, false);
+ pkgconf_path_build_from_environ(client, "LIBRARY_PATH", NULL, &client->filter_libdirs, false);
#endif
- pkgconf_path_build_from_environ("CPATH", NULL, &client->filter_includedirs, false);
- pkgconf_path_build_from_environ("C_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
- pkgconf_path_build_from_environ("CPLUS_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
- pkgconf_path_build_from_environ("OBJC_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
+ pkgconf_path_build_from_environ(client, "CPATH", NULL, &client->filter_includedirs, false);
+ pkgconf_path_build_from_environ(client, "C_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
+ pkgconf_path_build_from_environ(client, "CPLUS_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
+ pkgconf_path_build_from_environ(client, "OBJC_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
#ifdef _WIN32
/* also use the path lists that MSVC uses on windows */
- pkgconf_path_build_from_environ("INCLUDE", NULL, &client->filter_includedirs, false);
+ pkgconf_path_build_from_environ(client, "INCLUDE", NULL, &client->filter_includedirs, false);
#endif
PKGCONF_TRACE(client, "initialized client @%p", client);
trace_path_list(client, "filtered library paths", &client->filter_libdirs);
trace_path_list(client, "filtered include paths", &client->filter_includedirs);
+
+ client->output = pkgconf_output_default();
}
/*
@@ -163,17 +172,19 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
* :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
* :param void* error_handler_data: user data passed to optional error handler
* :param pkgconf_cross_personality_t* personality: cross-compile personality to use
+ * :param void* client_data: user data associated with the client
+ * :param pkgconf_environ_lookup_handler_func_t environ_lookup_handler: the lookup handler to use for environment variables
* :return: A pkgconf client object.
* :rtype: pkgconf_client_t*
*/
pkgconf_client_t *
-pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
+pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler)
{
pkgconf_client_t *out = calloc(1, sizeof(pkgconf_client_t));
if (out == NULL)
return NULL;
- pkgconf_client_init(out, error_handler, error_handler_data, personality);
+ pkgconf_client_init(out, error_handler, error_handler_data, personality, client_data, environ_lookup_handler);
return out;
}
@@ -182,7 +193,7 @@ unref_preload_list(pkgconf_client_t *client)
{
pkgconf_node_t *n, *tn;
- PKGCONF_FOREACH_LIST_ENTRY_SAFE(client->preloaded_pkgs.head, n, tn)
+ PKGCONF_FOREACH_LIST_ENTRY_SAFE(client->preloaded_pkgs.head, tn, n)
{
pkgconf_pkg_t *pkg = n->data;
pkgconf_pkg_unref(client, pkg);
@@ -221,6 +232,10 @@ pkgconf_client_deinit(pkgconf_client_t *client)
pkgconf_tuple_free_global(client);
pkgconf_path_free(&client->dir_list);
pkgconf_cache_free(client);
+
+ pkgconf_buffer_finalize(&client->_scratch_buffer);
+
+ memset(client, '\0', sizeof(*client));
}
/*
@@ -274,6 +289,12 @@ pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client)
void
pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir)
{
+ if (sysroot_dir != NULL && (!strcmp(sysroot_dir, "/") || !strcmp(sysroot_dir, ".")))
+ {
+ pkgconf_warn(client, "ignoring bogus sysroot_dir: %s", sysroot_dir);
+ sysroot_dir = NULL;
+ }
+
if (client->sysroot_dir != NULL)
free(client->sysroot_dir);
@@ -281,7 +302,7 @@ pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir
PKGCONF_TRACE(client, "set sysroot_dir to: %s", client->sysroot_dir != NULL ? client->sysroot_dir : "<default>");
- pkgconf_tuple_add_global(client, "pc_sysrootdir", client->sysroot_dir != NULL ? client->sysroot_dir : "/");
+ pkgconf_tuple_add_global(client, "pc_sysrootdir", client->sysroot_dir != NULL ? client->sysroot_dir : "");
}
/*
@@ -463,12 +484,18 @@ pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t linen
finallen = snprintf(NULL, 0, "%s %s\n", prefix, errbuf);
if (finallen < 0)
+ {
+ free(errbuf);
return false;
+ }
finallen++;
finalbuf = calloc(1, finallen);
if (finalbuf == NULL)
+ {
+ free(errbuf);
return false;
+ }
snprintf(finalbuf, finallen, "%s %s\n", prefix, errbuf);
ret = client->trace_handler(finalbuf, client, client->trace_handler_data);
@@ -753,6 +780,31 @@ pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler
/*
* !doc
*
+ * .. c:function:: bool pkgconf_client_preload_one(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+ *
+ * Adds a package to the preloaded packages set.
+ *
+ * :param pkgconf_client_t* client: The client object for preloading.
+ * :param pkgconf_pkg_t* pkg: The package to preload.
+ * :return: true on success, false on error
+ * :rtype: bool
+ */
+bool
+pkgconf_client_preload_one(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
+{
+ PKGCONF_TRACE(client, "preloading pkg %s@%p", pkg->id, pkg);
+
+ pkg->flags |= PKGCONF_PKG_PROPF_PRELOADED;
+
+ pkgconf_pkg_ref(client, pkg);
+ pkgconf_node_insert_tail(&pkg->preload_node, pkg, &client->preloaded_pkgs);
+
+ return true;
+}
+
+/*
+ * !doc
+ *
* .. c:function:: bool pkgconf_client_preload_path(pkgconf_client_t *client, const char *path)
*
* Loads a pkg-config file into the preloaded packages set.
@@ -769,10 +821,7 @@ pkgconf_client_preload_path(pkgconf_client_t *client, const char *path)
if (pkg == NULL)
return false;
- pkgconf_pkg_ref(client, pkg);
- pkgconf_node_insert_tail(&pkg->preload_node, pkg, &client->preloaded_pkgs);
-
- return true;
+ return pkgconf_client_preload_one(client, pkg);
}
/*
@@ -794,9 +843,9 @@ pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env)
const char *data;
pkgconf_list_t pathlist = PKGCONF_LIST_INITIALIZER;
pkgconf_node_t *n;
- bool ret;
+ bool ret = true;
- data = getenv(env);
+ data = pkgconf_client_getenv(client, env);
if (data == NULL)
return true;
@@ -815,3 +864,43 @@ pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env)
return ret;
}
+
+/*
+ * !doc
+ *
+ * .. c:function:: void pkgconf_client_set_output(pkgconf_client_t *client, pkgconf_output_t *output)
+ *
+ * Sets the client's output object. This is mainly a convenience function for clients
+ * to use.
+ *
+ * :param pkgconf_client_t* client: The client object to set the output object for.
+ * :param pkgconf_output_t* output: The output object to use.
+ * :return: nothing
+ */
+void
+pkgconf_client_set_output(pkgconf_client_t *client, pkgconf_output_t *output)
+{
+ client->output = output;
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: const char *pkgconf_client_getenv(const pkgconf_client_t *client, const char *key)
+ *
+ * Looks up an environmental variable which may be mocked, otherwise fetches
+ * from the main environment.
+ *
+ * :param pkgconf_client_t* client: yhe client object to use for looking up environmental variables.
+ * :param char* key: the environmental variable to look up.
+ * :return: the environmental variable contents else NULL
+ * :rtype: const char*
+ */
+const char *
+pkgconf_client_getenv(const pkgconf_client_t *client, const char *key)
+{
+ if (client != NULL && client->environ_lookup_handler != NULL)
+ return client->environ_lookup_handler(client, key);
+
+ return getenv(key);
+}