|
5 | 5 | * SPDX-License-Identifier: BSD-3-Clause
|
6 | 6 | */
|
7 | 7 |
|
| 8 | +#define _GNU_SOURCE /* For dladdr */ |
8 | 9 | #include "na_plugin.h"
|
9 | 10 |
|
10 | 11 | #include "mercury_atomic_queue.h"
|
|
20 | 21 | # include <Windows.h>
|
21 | 22 | # else
|
22 | 23 | # include <dirent.h>
|
| 24 | +# include <dlfcn.h> |
| 25 | +# include <limits.h> |
| 26 | +# include <link.h> |
23 | 27 | # endif
|
24 | 28 | #endif
|
25 | 29 |
|
@@ -260,20 +264,68 @@ na_finalize(void) NA_DESTRUCTOR;
|
260 | 264 |
|
261 | 265 | /*---------------------------------------------------------------------------*/
|
262 | 266 | #ifdef NA_HAS_DYNAMIC_PLUGINS
|
| 267 | +# ifdef _WIN32 |
| 268 | +# define resolve_plugin_path(offset) NULL |
| 269 | +# else |
| 270 | +static char * |
| 271 | +resolve_plugin_path(const char *offset) |
| 272 | +{ |
| 273 | + Dl_info info; |
| 274 | + char *libdir; |
| 275 | + char *libpath; |
| 276 | + char *slash; |
| 277 | + int rc; |
| 278 | + |
| 279 | + if (!dladdr(resolve_plugin_path, &info)) { |
| 280 | + return NULL; |
| 281 | + } |
| 282 | + |
| 283 | + libpath = realpath(info.dli_fname, NULL); |
| 284 | + if (libpath == NULL) { |
| 285 | + return NULL; |
| 286 | + } |
| 287 | + |
| 288 | + slash = strrchr(libpath, '/'); |
| 289 | + if (slash == NULL) { |
| 290 | + free(libpath); |
| 291 | + return NULL; |
| 292 | + } |
| 293 | + |
| 294 | + *slash = '\0'; |
| 295 | + rc = asprintf(&libdir, "%s/%s", libpath, offset); |
| 296 | + free(libpath); |
| 297 | + if (rc != -1) { |
| 298 | + return libdir; |
| 299 | + } |
| 300 | + |
| 301 | + return NULL; |
| 302 | +} |
| 303 | +# endif |
| 304 | + |
263 | 305 | static void
|
264 | 306 | na_initialize(void)
|
265 | 307 | {
|
266 | 308 | const char *plugin_path = getenv("NA_PLUGIN_PATH");
|
| 309 | + char *relative_plugin_path = NULL; |
267 | 310 | na_return_t ret;
|
268 |
| - |
269 |
| - if (plugin_path == NULL) |
270 |
| - plugin_path = NA_DEFAULT_PLUGIN_PATH; |
| 311 | + if (plugin_path == NULL) { |
| 312 | + relative_plugin_path = resolve_plugin_path(NA_PLUGIN_PATH_OFFSET); |
| 313 | + if (relative_plugin_path == NULL) { |
| 314 | + plugin_path = NA_DEFAULT_PLUGIN_PATH; |
| 315 | + } else { |
| 316 | + plugin_path = relative_plugin_path; |
| 317 | + } |
| 318 | + } |
271 | 319 |
|
272 | 320 | ret = na_plugin_scan_path(plugin_path, &na_plugin_dynamic_g);
|
273 | 321 | NA_CHECK_FATAL_DONE(ret != NA_SUCCESS,
|
274 | 322 | "No usable plugin found in path (%s), consider setting NA_PLUGIN_PATH "
|
275 | 323 | "if path indicated is not valid.",
|
276 | 324 | plugin_path);
|
| 325 | + |
| 326 | + if (relative_plugin_path) { |
| 327 | + free(relative_plugin_path); |
| 328 | + } |
277 | 329 | }
|
278 | 330 |
|
279 | 331 | /*---------------------------------------------------------------------------*/
|
|
0 commit comments