diff --git a/lib/core/context.c b/lib/core/context.c index 04c818197..1d7f97286 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -361,7 +361,8 @@ static const struct lws_evlib_map { { LWS_SERVER_OPTION_LIBEV, "evlib_ev" }, }; static const char * const dlist[] = { - LWS_INSTALL_LIBDIR, + ".", /* Priority 1: plugins in cwd */ + LWS_INSTALL_LIBDIR, /* Priority 2: plugins in install dir */ NULL }; #endif @@ -398,6 +399,7 @@ lws_create_context(const struct lws_context_creation_info *info) const lws_plugin_evlib_t *plev = NULL; #if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS) struct lws_plugin *evlib_plugin_list = NULL; + char *ld_env; #endif if (lpf) { @@ -464,15 +466,61 @@ lws_create_context(const struct lws_context_creation_info *info) * the context object, so we can overallocate it correctly */ - lwsl_info("%s: ev lib path %s\n", __func__, LWS_INSTALL_LIBDIR); + ld_env = getenv("LD_LIBRARY_PATH"); + lwsl_info("%s: ev lib path %s, '%s'\n", __func__, + LWS_INSTALL_LIBDIR, ld_env); for (n = 0; n < (int)LWS_ARRAY_SIZE(map); n++) { + char ok = 0; + if (!lws_check_opt(info->options, map[n].flag)) continue; if (lws_plugins_init(&evlib_plugin_list, dlist, "lws_evlib_plugin", map[n].name, NULL, NULL)) { + + /* + * No joy in the canned paths, try LD_LIBRARY_PATH + */ + + if (ld_env) { + char temp[128]; + struct lws_tokenize ts; + const char * tok[2] = { temp, NULL }; + + memset(&ts, 0, sizeof(ts)); + ts.start = ld_env; + ts.len = strlen(ld_env); + ts.flags = LWS_TOKENIZE_F_SLASH_NONTERM | + LWS_TOKENIZE_F_DOT_NONTERM | + LWS_TOKENIZE_F_NO_INTEGERS | + LWS_TOKENIZE_F_NO_FLOATS; + + do { + ts.e = lws_tokenize(&ts); + if (ts.e != LWS_TOKZE_TOKEN) + continue; + + lws_strnncpy(temp, ts.token, + ts.token_len, + sizeof(temp)); + + if (!lws_plugins_init( + &evlib_plugin_list, tok, + "lws_evlib_plugin", + map[n].name, + NULL, NULL)) { + ok = 1; + break; + } + + } while (ts.e > 0); + } + } else + ok = 1; + + if (!ok) { lwsl_err("%s: failed to load %s\n", __func__, map[n].name); goto bail; diff --git a/lib/misc/dir.c b/lib/misc/dir.c index 07e3c52fc..5af02eebb 100644 --- a/lib/misc/dir.c +++ b/lib/misc/dir.c @@ -170,14 +170,13 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) if (cb(dirpath, user, &lde)) { while (++i < n) free(namelist[i]); + ret = 0; /* told to stop by cb */ goto bail; } skip: free(namelist[i]); } - ret = 0; - bail: free(namelist); @@ -298,10 +297,11 @@ lws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) { struct lws_plugins_args *pa = (struct lws_plugins_args *)user; char path[256], base[64], *q = base; + const lws_plugin_header_t *pl; const char *p; if (strlen(lde->name) < 7) - return 0; + return 0; /* keep going */ /* * The actual plugin names for protocol plugins look like @@ -323,13 +323,22 @@ lws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) /* if he's given a filter, only match if base matches it */ if (pa->filter && strcmp(base, pa->filter)) - return 0; + return 0; /* keep going */ lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name); lwsl_notice(" %s\n", path); - return !lws_plat_dlopen(pa->pplugin, path, base, pa->_class, - pa->each, pa->each_user); + pl = lws_plat_dlopen(pa->pplugin, path, base, pa->_class, + pa->each, pa->each_user); + + /* + * If we were looking for a specific plugin, finding it should make + * us stop looking (eg, to account for directory precedence of the + * same plugin). If scanning for plugins in a dir, we always keep + * going. + */ + + return pa->filter && pl; } int @@ -338,6 +347,7 @@ lws_plugins_init(struct lws_plugin **pplugin, const char * const *d, each_plugin_cb_t each, void *each_user) { struct lws_plugins_args pa; + int ret = 1; pa.pplugin = pplugin; pa._class = _class; @@ -346,11 +356,14 @@ lws_plugins_init(struct lws_plugin **pplugin, const char * const *d, pa.filter = filter; while (d && *d) { - lws_dir(*d, &pa, lws_plugins_dir_cb); + lwsl_info("%s: trying %s\n", __func__, *d); + if (!lws_dir(*d, &pa, lws_plugins_dir_cb)) + ret = 0; + d++; } - return 0; + return ret; } int