1 /* 2 * client.c 3 * libpkgconf consumer lifecycle management 4 * 5 * Copyright (c) 2016 pkgconf authors (see AUTHORS). 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * This software is provided 'as is' and without any warranty, express or 12 * implied. In no event shall the authors be liable for any damages arising 13 * from the use of this software. 14 */ 15 16 #include <libpkgconf/config.h> 17 #include <libpkgconf/stdinc.h> 18 #include <libpkgconf/libpkgconf.h> 19 20 /* 21 * !doc 22 * 23 * libpkgconf `client` module 24 * ========================== 25 * 26 * The libpkgconf `client` module implements the `pkgconf_client_t` "client" object. 27 * Client objects store all necessary state for libpkgconf allowing for multiple instances to run 28 * in parallel. 29 * 30 * Client objects are not thread safe, in other words, a client object should not be shared across 31 * thread boundaries. 32 */ 33 34 static void 35 trace_path_list(const pkgconf_client_t *client, const char *desc, pkgconf_list_t *list) 36 { 37 const pkgconf_node_t *n; 38 39 PKGCONF_TRACE(client, "%s:", desc); 40 PKGCONF_FOREACH_LIST_ENTRY(list->head, n) 41 { 42 const pkgconf_path_t *p = n->data; 43 44 PKGCONF_TRACE(client, " - '%s'", p->path); 45 } 46 } 47 48 /* 49 * !doc 50 * 51 * .. c:function:: void pkgconf_client_dir_list_build(pkgconf_client_t *client) 52 * 53 * Bootstraps the package search paths. If the ``PKGCONF_PKG_PKGF_ENV_ONLY`` `flag` is set on the client, 54 * then only the ``PKG_CONFIG_PATH`` environment variable will be used, otherwise both the 55 * ``PKG_CONFIG_PATH`` and ``PKG_CONFIG_LIBDIR`` environment variables will be used. 56 * 57 * :param pkgconf_client_t* client: The pkgconf client object to bootstrap. 58 * :return: nothing 59 */ 60 void 61 pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality) 62 { 63 pkgconf_path_build_from_environ("PKG_CONFIG_PATH", NULL, &client->dir_list, true); 64 65 if (!(client->flags & PKGCONF_PKG_PKGF_ENV_ONLY)) 66 { 67 pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER; 68 const pkgconf_list_t *prepend_list = &personality->dir_list; 69 70 #ifdef _WIN32 71 (void) pkgconf_path_build_from_registry(HKEY_CURRENT_USER, &client->dir_list, true); 72 (void) pkgconf_path_build_from_registry(HKEY_LOCAL_MACHINE, &client->dir_list, true); 73 #endif 74 75 if (getenv("PKG_CONFIG_LIBDIR") != NULL) 76 { 77 /* PKG_CONFIG_LIBDIR= should empty the search path entirely. */ 78 (void) pkgconf_path_build_from_environ("PKG_CONFIG_LIBDIR", NULL, &dir_list, true); 79 prepend_list = &dir_list; 80 } 81 82 pkgconf_path_copy_list(&client->dir_list, prepend_list); 83 pkgconf_path_free(&dir_list); 84 } 85 } 86 87 /* 88 * !doc 89 * 90 * .. 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) 91 * 92 * Initialise a pkgconf client object. 93 * 94 * :param pkgconf_client_t* client: The client to initialise. 95 * :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors. 96 * :param void* error_handler_data: user data passed to optional error handler 97 * :param pkgconf_cross_personality_t* personality: the cross-compile personality to use for defaults 98 * :return: nothing 99 */ 100 void 101 pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality) 102 { 103 client->error_handler_data = error_handler_data; 104 client->error_handler = error_handler; 105 client->auditf = NULL; 106 client->cache_table = NULL; 107 client->cache_count = 0; 108 109 #ifndef PKGCONF_LITE 110 if (client->trace_handler == NULL) 111 pkgconf_client_set_trace_handler(client, NULL, NULL); 112 #endif 113 114 if (client->unveil_handler == NULL) 115 pkgconf_client_set_unveil_handler(client, NULL); 116 117 pkgconf_client_set_error_handler(client, error_handler, error_handler_data); 118 pkgconf_client_set_warn_handler(client, NULL, NULL); 119 120 pkgconf_client_set_sysroot_dir(client, personality->sysroot_dir); 121 pkgconf_client_set_buildroot_dir(client, NULL); 122 pkgconf_client_set_prefix_varname(client, NULL); 123 124 if(getenv("PKG_CONFIG_SYSTEM_LIBRARY_PATH") == NULL) 125 pkgconf_path_copy_list(&client->filter_libdirs, &personality->filter_libdirs); 126 else 127 pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_LIBRARY_PATH", NULL, &client->filter_libdirs, false); 128 129 if(getenv("PKG_CONFIG_SYSTEM_INCLUDE_PATH") == NULL) 130 pkgconf_path_copy_list(&client->filter_includedirs, &personality->filter_includedirs); 131 else 132 pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_INCLUDE_PATH", NULL, &client->filter_includedirs, false); 133 134 /* GCC uses these environment variables to define system include paths, so we should check them. */ 135 #ifdef __HAIKU__ 136 pkgconf_path_build_from_environ("BELIBRARIES", NULL, &client->filter_libdirs, false); 137 #else 138 pkgconf_path_build_from_environ("LIBRARY_PATH", NULL, &client->filter_libdirs, false); 139 #endif 140 pkgconf_path_build_from_environ("CPATH", NULL, &client->filter_includedirs, false); 141 pkgconf_path_build_from_environ("C_INCLUDE_PATH", NULL, &client->filter_includedirs, false); 142 pkgconf_path_build_from_environ("CPLUS_INCLUDE_PATH", NULL, &client->filter_includedirs, false); 143 pkgconf_path_build_from_environ("OBJC_INCLUDE_PATH", NULL, &client->filter_includedirs, false); 144 145 #ifdef _WIN32 146 /* also use the path lists that MSVC uses on windows */ 147 pkgconf_path_build_from_environ("INCLUDE", NULL, &client->filter_includedirs, false); 148 #endif 149 150 PKGCONF_TRACE(client, "initialized client @%p", client); 151 152 trace_path_list(client, "filtered library paths", &client->filter_libdirs); 153 trace_path_list(client, "filtered include paths", &client->filter_includedirs); 154 } 155 156 /* 157 * !doc 158 * 159 * .. c:function:: pkgconf_client_t* pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality) 160 * 161 * Allocate and initialise a pkgconf client object. 162 * 163 * :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors. 164 * :param void* error_handler_data: user data passed to optional error handler 165 * :param pkgconf_cross_personality_t* personality: cross-compile personality to use 166 * :return: A pkgconf client object. 167 * :rtype: pkgconf_client_t* 168 */ 169 pkgconf_client_t * 170 pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality) 171 { 172 pkgconf_client_t *out = calloc(1, sizeof(pkgconf_client_t)); 173 if (out == NULL) 174 return NULL; 175 176 pkgconf_client_init(out, error_handler, error_handler_data, personality); 177 return out; 178 } 179 180 static void 181 unref_preload_list(pkgconf_client_t *client) 182 { 183 pkgconf_node_t *n, *tn; 184 185 PKGCONF_FOREACH_LIST_ENTRY_SAFE(client->preloaded_pkgs.head, n, tn) 186 { 187 pkgconf_pkg_t *pkg = n->data; 188 pkgconf_pkg_unref(client, pkg); 189 } 190 } 191 192 /* 193 * !doc 194 * 195 * .. c:function:: void pkgconf_client_deinit(pkgconf_client_t *client) 196 * 197 * Release resources belonging to a pkgconf client object. 198 * 199 * :param pkgconf_client_t* client: The client to deinitialise. 200 * :return: nothing 201 */ 202 void 203 pkgconf_client_deinit(pkgconf_client_t *client) 204 { 205 PKGCONF_TRACE(client, "deinit @%p", client); 206 207 unref_preload_list(client); 208 209 if (client->prefix_varname != NULL) 210 free(client->prefix_varname); 211 212 if (client->sysroot_dir != NULL) 213 free(client->sysroot_dir); 214 215 if (client->buildroot_dir != NULL) 216 free(client->buildroot_dir); 217 218 pkgconf_path_free(&client->filter_libdirs); 219 pkgconf_path_free(&client->filter_includedirs); 220 221 pkgconf_tuple_free_global(client); 222 pkgconf_path_free(&client->dir_list); 223 pkgconf_cache_free(client); 224 } 225 226 /* 227 * !doc 228 * 229 * .. c:function:: void pkgconf_client_free(pkgconf_client_t *client) 230 * 231 * Release resources belonging to a pkgconf client object and then free the client object itself. 232 * 233 * :param pkgconf_client_t* client: The client to deinitialise and free. 234 * :return: nothing 235 */ 236 void 237 pkgconf_client_free(pkgconf_client_t *client) 238 { 239 pkgconf_client_deinit(client); 240 free(client); 241 } 242 243 /* 244 * !doc 245 * 246 * .. c:function:: const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client) 247 * 248 * Retrieves the client's sysroot directory (if any). 249 * 250 * :param pkgconf_client_t* client: The client object being accessed. 251 * :return: A string containing the sysroot directory or NULL. 252 * :rtype: const char * 253 */ 254 const char * 255 pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client) 256 { 257 return client->sysroot_dir; 258 } 259 260 /* 261 * !doc 262 * 263 * .. c:function:: void pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir) 264 * 265 * Sets or clears the sysroot directory on a client object. Any previous sysroot directory setting is 266 * automatically released if one was previously set. 267 * 268 * Additionally, the global tuple ``$(pc_sysrootdir)`` is set as appropriate based on the new setting. 269 * 270 * :param pkgconf_client_t* client: The client object being modified. 271 * :param char* sysroot_dir: The sysroot directory to set or NULL to unset. 272 * :return: nothing 273 */ 274 void 275 pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir) 276 { 277 if (client->sysroot_dir != NULL) 278 free(client->sysroot_dir); 279 280 client->sysroot_dir = sysroot_dir != NULL ? strdup(sysroot_dir) : NULL; 281 282 PKGCONF_TRACE(client, "set sysroot_dir to: %s", client->sysroot_dir != NULL ? client->sysroot_dir : "<default>"); 283 284 pkgconf_tuple_add_global(client, "pc_sysrootdir", client->sysroot_dir != NULL ? client->sysroot_dir : "/"); 285 } 286 287 /* 288 * !doc 289 * 290 * .. c:function:: const char *pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client) 291 * 292 * Retrieves the client's buildroot directory (if any). 293 * 294 * :param pkgconf_client_t* client: The client object being accessed. 295 * :return: A string containing the buildroot directory or NULL. 296 * :rtype: const char * 297 */ 298 const char * 299 pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client) 300 { 301 return client->buildroot_dir; 302 } 303 304 /* 305 * !doc 306 * 307 * .. c:function:: void pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir) 308 * 309 * Sets or clears the buildroot directory on a client object. Any previous buildroot directory setting is 310 * automatically released if one was previously set. 311 * 312 * Additionally, the global tuple ``$(pc_top_builddir)`` is set as appropriate based on the new setting. 313 * 314 * :param pkgconf_client_t* client: The client object being modified. 315 * :param char* buildroot_dir: The buildroot directory to set or NULL to unset. 316 * :return: nothing 317 */ 318 void 319 pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir) 320 { 321 if (client->buildroot_dir != NULL) 322 free(client->buildroot_dir); 323 324 client->buildroot_dir = buildroot_dir != NULL ? strdup(buildroot_dir) : NULL; 325 326 PKGCONF_TRACE(client, "set buildroot_dir to: %s", client->buildroot_dir != NULL ? client->buildroot_dir : "<default>"); 327 328 pkgconf_tuple_add_global(client, "pc_top_builddir", client->buildroot_dir != NULL ? client->buildroot_dir : "$(top_builddir)"); 329 } 330 331 /* 332 * !doc 333 * 334 * .. c:function:: bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...) 335 * 336 * Report an error to a client-registered error handler. 337 * 338 * :param pkgconf_client_t* client: The pkgconf client object to report the error to. 339 * :param char* format: A printf-style format string to use for formatting the error message. 340 * :return: true if the error handler processed the message, else false. 341 * :rtype: bool 342 */ 343 bool 344 pkgconf_error(const pkgconf_client_t *client, const char *format, ...) 345 { 346 char *errbuf; 347 ssize_t msgsize = 0; 348 bool ret; 349 va_list va; 350 351 va_start(va, format); 352 msgsize = vsnprintf(NULL, 0, format, va); 353 va_end(va); 354 355 if (msgsize < 0) 356 return false; 357 358 msgsize++; 359 360 errbuf = calloc(1, msgsize); 361 if (errbuf == NULL) 362 return false; 363 364 va_start(va, format); 365 vsnprintf(errbuf, msgsize, format, va); 366 va_end(va); 367 368 ret = client->error_handler(errbuf, client, client->error_handler_data); 369 free(errbuf); 370 371 return ret; 372 } 373 374 /* 375 * !doc 376 * 377 * .. c:function:: bool pkgconf_warn(const pkgconf_client_t *client, const char *format, ...) 378 * 379 * Report an error to a client-registered warn handler. 380 * 381 * :param pkgconf_client_t* client: The pkgconf client object to report the error to. 382 * :param char* format: A printf-style format string to use for formatting the warning message. 383 * :return: true if the warn handler processed the message, else false. 384 * :rtype: bool 385 */ 386 bool 387 pkgconf_warn(const pkgconf_client_t *client, const char *format, ...) 388 { 389 char *errbuf; 390 ssize_t msgsize = 0; 391 bool ret; 392 va_list va; 393 394 va_start(va, format); 395 msgsize = vsnprintf(NULL, 0, format, va); 396 va_end(va); 397 398 if (msgsize < 0) 399 return false; 400 401 msgsize++; 402 403 errbuf = calloc(1, msgsize); 404 if (errbuf == NULL) 405 return false; 406 407 va_start(va, format); 408 vsnprintf(errbuf, msgsize, format, va); 409 va_end(va); 410 411 ret = client->warn_handler(errbuf, client, client->warn_handler_data); 412 free(errbuf); 413 414 return ret; 415 } 416 417 /* 418 * !doc 419 * 420 * .. c:function:: bool pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t len, const char *funcname, const char *format, ...) 421 * 422 * Report a message to a client-registered trace handler. 423 * 424 * :param pkgconf_client_t* client: The pkgconf client object to report the trace message to. 425 * :param char* filename: The file the function is in. 426 * :param size_t lineno: The line number currently being executed. 427 * :param char* funcname: The function name to use. 428 * :param char* format: A printf-style format string to use for formatting the trace message. 429 * :return: true if the trace handler processed the message, else false. 430 * :rtype: bool 431 */ 432 bool 433 pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t lineno, const char *funcname, const char *format, ...) 434 { 435 char prefix[PKGCONF_ITEM_SIZE]; 436 char *errbuf = NULL; 437 ssize_t errlen; 438 char *finalbuf = NULL; 439 ssize_t finallen; 440 bool ret; 441 va_list va; 442 443 if (client == NULL || client->trace_handler == NULL) 444 return false; 445 446 snprintf(prefix, sizeof prefix, "%s:" SIZE_FMT_SPECIFIER " [%s]:", filename, lineno, funcname); 447 448 va_start(va, format); 449 errlen = vsnprintf(NULL, 0, format, va); 450 va_end(va); 451 452 if (errlen < 0) 453 return false; 454 455 errlen++; 456 errbuf = calloc(1, errlen); 457 if (errbuf == NULL) 458 return false; 459 460 va_start(va, format); 461 vsnprintf(errbuf, errlen, format, va); 462 va_end(va); 463 464 finallen = snprintf(NULL, 0, "%s %s\n", prefix, errbuf); 465 if (finallen < 0) 466 return false; 467 468 finallen++; 469 finalbuf = calloc(1, finallen); 470 if (finalbuf == NULL) 471 return false; 472 473 snprintf(finalbuf, finallen, "%s %s\n", prefix, errbuf); 474 ret = client->trace_handler(finalbuf, client, client->trace_handler_data); 475 free(errbuf); 476 free(finalbuf); 477 478 return ret; 479 } 480 481 /* 482 * !doc 483 * 484 * .. c:function:: bool pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, const void *data) 485 * 486 * The default pkgconf error handler. 487 * 488 * :param char* msg: The error message to handle. 489 * :param pkgconf_client_t* client: The client object the error originated from. 490 * :param void* data: An opaque pointer to extra data associated with the client for error handling. 491 * :return: true (the function does nothing to process the message) 492 * :rtype: bool 493 */ 494 bool 495 pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, void *data) 496 { 497 (void) msg; 498 (void) client; 499 (void) data; 500 501 return true; 502 } 503 504 static void 505 default_unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions) 506 { 507 (void) client; 508 (void) path; 509 (void) permissions; 510 } 511 512 /* 513 * !doc 514 * 515 * .. c:function:: unsigned int pkgconf_client_get_flags(const pkgconf_client_t *client) 516 * 517 * Retrieves resolver-specific flags associated with a client object. 518 * 519 * :param pkgconf_client_t* client: The client object to retrieve the resolver-specific flags from. 520 * :return: a bitfield of resolver-specific flags 521 * :rtype: uint 522 */ 523 unsigned int 524 pkgconf_client_get_flags(const pkgconf_client_t *client) 525 { 526 return client->flags; 527 } 528 529 /* 530 * !doc 531 * 532 * .. c:function:: void pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags) 533 * 534 * Sets resolver-specific flags associated with a client object. 535 * 536 * :param pkgconf_client_t* client: The client object to set the resolver-specific flags on. 537 * :return: nothing 538 */ 539 void 540 pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags) 541 { 542 client->flags = flags; 543 } 544 545 /* 546 * !doc 547 * 548 * .. c:function:: const char *pkgconf_client_get_prefix_varname(const pkgconf_client_t *client) 549 * 550 * Retrieves the name of the variable that should contain a module's prefix. 551 * In some cases, it is necessary to override this variable to allow proper path relocation. 552 * 553 * :param pkgconf_client_t* client: The client object to retrieve the prefix variable name from. 554 * :return: the prefix variable name as a string 555 * :rtype: const char * 556 */ 557 const char * 558 pkgconf_client_get_prefix_varname(const pkgconf_client_t *client) 559 { 560 return client->prefix_varname; 561 } 562 563 /* 564 * !doc 565 * 566 * .. c:function:: void pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname) 567 * 568 * Sets the name of the variable that should contain a module's prefix. 569 * If the variable name is ``NULL``, then the default variable name (``prefix``) is used. 570 * 571 * :param pkgconf_client_t* client: The client object to set the prefix variable name on. 572 * :param char* prefix_varname: The prefix variable name to set. 573 * :return: nothing 574 */ 575 void 576 pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname) 577 { 578 if (prefix_varname == NULL) 579 prefix_varname = "prefix"; 580 581 if (client->prefix_varname != NULL) 582 free(client->prefix_varname); 583 584 client->prefix_varname = strdup(prefix_varname); 585 586 PKGCONF_TRACE(client, "set prefix_varname to: %s", client->prefix_varname); 587 } 588 589 /* 590 * !doc 591 * 592 * .. c:function:: pkgconf_client_get_warn_handler(const pkgconf_client_t *client) 593 * 594 * Returns the warning handler if one is set, else ``NULL``. 595 * 596 * :param pkgconf_client_t* client: The client object to get the warn handler from. 597 * :return: a function pointer to the warn handler or ``NULL`` 598 */ 599 pkgconf_error_handler_func_t 600 pkgconf_client_get_warn_handler(const pkgconf_client_t *client) 601 { 602 return client->warn_handler; 603 } 604 605 /* 606 * !doc 607 * 608 * .. c:function:: pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data) 609 * 610 * Sets a warn handler on a client object or uninstalls one if set to ``NULL``. 611 * 612 * :param pkgconf_client_t* client: The client object to set the warn handler on. 613 * :param pkgconf_error_handler_func_t warn_handler: The warn handler to set. 614 * :param void* warn_handler_data: Optional data to associate with the warn handler. 615 * :return: nothing 616 */ 617 void 618 pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data) 619 { 620 client->warn_handler = warn_handler; 621 client->warn_handler_data = warn_handler_data; 622 623 if (client->warn_handler == NULL) 624 { 625 PKGCONF_TRACE(client, "installing default warn handler"); 626 client->warn_handler = pkgconf_default_error_handler; 627 } 628 } 629 630 /* 631 * !doc 632 * 633 * .. c:function:: pkgconf_client_get_error_handler(const pkgconf_client_t *client) 634 * 635 * Returns the error handler if one is set, else ``NULL``. 636 * 637 * :param pkgconf_client_t* client: The client object to get the error handler from. 638 * :return: a function pointer to the error handler or ``NULL`` 639 */ 640 pkgconf_error_handler_func_t 641 pkgconf_client_get_error_handler(const pkgconf_client_t *client) 642 { 643 return client->error_handler; 644 } 645 646 /* 647 * !doc 648 * 649 * .. c:function:: pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data) 650 * 651 * Sets a warn handler on a client object or uninstalls one if set to ``NULL``. 652 * 653 * :param pkgconf_client_t* client: The client object to set the error handler on. 654 * :param pkgconf_error_handler_func_t error_handler: The error handler to set. 655 * :param void* error_handler_data: Optional data to associate with the error handler. 656 * :return: nothing 657 */ 658 void 659 pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data) 660 { 661 client->error_handler = error_handler; 662 client->error_handler_data = error_handler_data; 663 664 if (client->error_handler == NULL) 665 { 666 PKGCONF_TRACE(client, "installing default error handler"); 667 client->error_handler = pkgconf_default_error_handler; 668 } 669 } 670 671 /* 672 * !doc 673 * 674 * .. c:function:: pkgconf_client_get_unveil_handler(const pkgconf_client_t *client) 675 * 676 * Returns the unveil handler if one is set, else ``NULL``. 677 * 678 * :param pkgconf_client_t* client: The client object to get the unveil handler from. 679 * :return: a function pointer to the error handler or ``NULL`` 680 */ 681 pkgconf_unveil_handler_func_t 682 pkgconf_client_get_unveil_handler(const pkgconf_client_t *client) 683 { 684 return client->unveil_handler; 685 } 686 687 /* 688 * !doc 689 * 690 * .. c:function:: pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler) 691 * 692 * Sets an unveil handler on a client object or uninstalls one if set to ``NULL``. 693 * 694 * :param pkgconf_client_t* client: The client object to set the error handler on. 695 * :param pkgconf_unveil_handler_func_t unveil_handler: The unveil handler to set. 696 * :return: nothing 697 */ 698 void 699 pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler) 700 { 701 client->unveil_handler = unveil_handler; 702 703 if (client->unveil_handler == NULL) 704 { 705 PKGCONF_TRACE(client, "installing default unveil handler"); 706 client->unveil_handler = default_unveil_handler; 707 } 708 } 709 710 #ifndef PKGCONF_LITE 711 /* 712 * !doc 713 * 714 * .. c:function:: pkgconf_client_get_trace_handler(const pkgconf_client_t *client) 715 * 716 * Returns the error handler if one is set, else ``NULL``. 717 * 718 * :param pkgconf_client_t* client: The client object to get the error handler from. 719 * :return: a function pointer to the error handler or ``NULL`` 720 */ 721 pkgconf_error_handler_func_t 722 pkgconf_client_get_trace_handler(const pkgconf_client_t *client) 723 { 724 return client->trace_handler; 725 } 726 727 /* 728 * !doc 729 * 730 * .. c:function:: pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data) 731 * 732 * Sets a warn handler on a client object or uninstalls one if set to ``NULL``. 733 * 734 * :param pkgconf_client_t* client: The client object to set the error handler on. 735 * :param pkgconf_error_handler_func_t trace_handler: The error handler to set. 736 * :param void* trace_handler_data: Optional data to associate with the error handler. 737 * :return: nothing 738 */ 739 void 740 pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data) 741 { 742 client->trace_handler = trace_handler; 743 client->trace_handler_data = trace_handler_data; 744 745 if (client->trace_handler == NULL) 746 { 747 client->trace_handler = pkgconf_default_error_handler; 748 PKGCONF_TRACE(client, "installing default trace handler"); 749 } 750 } 751 #endif 752 753 /* 754 * !doc 755 * 756 * .. c:function:: bool pkgconf_client_preload_path(pkgconf_client_t *client, const char *path) 757 * 758 * Loads a pkg-config file into the preloaded packages set. 759 * 760 * :param pkgconf_client_t* client: The client object for preloading. 761 * :param char* path: The path to the pkg-config file to preload. 762 * :return: true on success, false on error 763 * :rtype: bool 764 */ 765 bool 766 pkgconf_client_preload_path(pkgconf_client_t *client, const char *path) 767 { 768 pkgconf_pkg_t *pkg = pkgconf_pkg_new_from_path(client, path, PKGCONF_PKG_PROPF_PRELOADED); 769 if (pkg == NULL) 770 return false; 771 772 pkgconf_pkg_ref(client, pkg); 773 pkgconf_node_insert_tail(&pkg->preload_node, pkg, &client->preloaded_pkgs); 774 775 return true; 776 } 777 778 /* 779 * !doc 780 * 781 * .. c:function:: bool pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env) 782 * 783 * Loads zero or more pkg-config files specified in the given environmental 784 * variable. 785 * 786 * :param pkgconf_client_t* client: The client object for preloading. 787 * :param char* environ: The environment variable to use for preloading. 788 * :return: true on success, false on error 789 * :rtype: bool 790 */ 791 bool 792 pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env) 793 { 794 const char *data; 795 pkgconf_list_t pathlist = PKGCONF_LIST_INITIALIZER; 796 pkgconf_node_t *n; 797 bool ret; 798 799 data = getenv(env); 800 if (data == NULL) 801 return true; 802 803 pkgconf_path_split(data, &pathlist, true); 804 805 PKGCONF_FOREACH_LIST_ENTRY(pathlist.head, n) 806 { 807 pkgconf_path_t *pn = n->data; 808 809 ret = pkgconf_client_preload_path(client, pn->path); 810 if (!ret) 811 break; 812 } 813 814 pkgconf_path_free(&pathlist); 815 816 return ret; 817 } 818