1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci */
24d4afb5ceSopenharmony_ci
25d4afb5ceSopenharmony_ci#if !defined(NO_GNU_SOURCE_THIS_TIME)
26d4afb5ceSopenharmony_ci#define NO_GNU_SOURCE_THIS_TIME
27d4afb5ceSopenharmony_ci#endif
28d4afb5ceSopenharmony_ci#if !defined(_DARWIN_C_SOURCE)
29d4afb5ceSopenharmony_ci#define _DARWIN_C_SOURCE
30d4afb5ceSopenharmony_ci#endif
31d4afb5ceSopenharmony_ci
32d4afb5ceSopenharmony_ci#include "private-lib-core.h"
33d4afb5ceSopenharmony_ci#include <string.h>
34d4afb5ceSopenharmony_ci#include <stdio.h>
35d4afb5ceSopenharmony_ci
36d4afb5ceSopenharmony_ci#include <sys/stat.h>
37d4afb5ceSopenharmony_ci#if defined(WIN32)
38d4afb5ceSopenharmony_ci#include <direct.h>
39d4afb5ceSopenharmony_ci#define read _read
40d4afb5ceSopenharmony_ci#define open _open
41d4afb5ceSopenharmony_ci#define close _close
42d4afb5ceSopenharmony_ci#define write _write
43d4afb5ceSopenharmony_ci#define mkdir(x,y) _mkdir(x)
44d4afb5ceSopenharmony_ci#define rmdir _rmdir
45d4afb5ceSopenharmony_ci#define unlink _unlink
46d4afb5ceSopenharmony_ci#define HAVE_STRUCT_TIMESPEC
47d4afb5ceSopenharmony_ci#if defined(pid_t)
48d4afb5ceSopenharmony_ci#undef pid_t
49d4afb5ceSopenharmony_ci#endif
50d4afb5ceSopenharmony_ci#endif /* win32 */
51d4afb5ceSopenharmony_ci
52d4afb5ceSopenharmony_ci#define COMBO_SIZEOF 512
53d4afb5ceSopenharmony_ci
54d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS)
55d4afb5ceSopenharmony_ci
56d4afb5ceSopenharmony_ci#if defined(WIN32)
57d4afb5ceSopenharmony_ci#include "../../win32port/dirent/dirent-win32.h"
58d4afb5ceSopenharmony_ci#else
59d4afb5ceSopenharmony_ci#include <dirent.h>
60d4afb5ceSopenharmony_ci#endif
61d4afb5ceSopenharmony_ci
62d4afb5ceSopenharmony_cistatic int filter(const struct dirent *ent)
63d4afb5ceSopenharmony_ci{
64d4afb5ceSopenharmony_ci	if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
65d4afb5ceSopenharmony_ci		return 0;
66d4afb5ceSopenharmony_ci
67d4afb5ceSopenharmony_ci	return 1;
68d4afb5ceSopenharmony_ci}
69d4afb5ceSopenharmony_ci
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ci#if !defined(WIN32)
72d4afb5ceSopenharmony_cistatic char csep = '/';
73d4afb5ceSopenharmony_ci#else
74d4afb5ceSopenharmony_cistatic char csep = '\\';
75d4afb5ceSopenharmony_ci#endif
76d4afb5ceSopenharmony_ci
77d4afb5ceSopenharmony_cistatic void
78d4afb5ceSopenharmony_cilws_dir_via_stat(char *combo, size_t l, const char *path, struct lws_dir_entry *lde)
79d4afb5ceSopenharmony_ci{
80d4afb5ceSopenharmony_ci        struct stat s;
81d4afb5ceSopenharmony_ci
82d4afb5ceSopenharmony_ci        lws_strncpy(combo + l, path, COMBO_SIZEOF - l);
83d4afb5ceSopenharmony_ci
84d4afb5ceSopenharmony_ci        lde->type = LDOT_UNKNOWN;
85d4afb5ceSopenharmony_ci
86d4afb5ceSopenharmony_ci        if (!stat(combo, &s)) {
87d4afb5ceSopenharmony_ci		switch (s.st_mode & S_IFMT) {
88d4afb5ceSopenharmony_ci		case S_IFBLK:
89d4afb5ceSopenharmony_ci			lde->type = LDOT_BLOCK;
90d4afb5ceSopenharmony_ci			break;
91d4afb5ceSopenharmony_ci		case S_IFCHR:
92d4afb5ceSopenharmony_ci			lde->type = LDOT_CHAR;
93d4afb5ceSopenharmony_ci			break;
94d4afb5ceSopenharmony_ci		case S_IFDIR:
95d4afb5ceSopenharmony_ci			lde->type = LDOT_DIR;
96d4afb5ceSopenharmony_ci			break;
97d4afb5ceSopenharmony_ci		case S_IFIFO:
98d4afb5ceSopenharmony_ci			lde->type = LDOT_FIFO;
99d4afb5ceSopenharmony_ci			break;
100d4afb5ceSopenharmony_ci#if !defined(WIN32)
101d4afb5ceSopenharmony_ci		case S_IFLNK:
102d4afb5ceSopenharmony_ci			lde->type = LDOT_LINK;
103d4afb5ceSopenharmony_ci			break;
104d4afb5ceSopenharmony_ci#endif
105d4afb5ceSopenharmony_ci		case S_IFREG:
106d4afb5ceSopenharmony_ci			lde->type = LDOT_FILE;
107d4afb5ceSopenharmony_ci			break;
108d4afb5ceSopenharmony_ci		default:
109d4afb5ceSopenharmony_ci			break;
110d4afb5ceSopenharmony_ci		}
111d4afb5ceSopenharmony_ci        }
112d4afb5ceSopenharmony_ci}
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ciint
115d4afb5ceSopenharmony_cilws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
116d4afb5ceSopenharmony_ci{
117d4afb5ceSopenharmony_ci	struct lws_dir_entry lde;
118d4afb5ceSopenharmony_ci	struct dirent **namelist;
119d4afb5ceSopenharmony_ci	int n, i, ret = 1;
120d4afb5ceSopenharmony_ci	char combo[COMBO_SIZEOF];
121d4afb5ceSopenharmony_ci	size_t l;
122d4afb5ceSopenharmony_ci
123d4afb5ceSopenharmony_ci	l = (size_t)(ssize_t)lws_snprintf(combo, COMBO_SIZEOF - 2, "%s", dirpath);
124d4afb5ceSopenharmony_ci	combo[l++] = csep;
125d4afb5ceSopenharmony_ci	combo[l] = '\0';
126d4afb5ceSopenharmony_ci
127d4afb5ceSopenharmony_ci	n = scandir((char *)dirpath, &namelist, filter, alphasort);
128d4afb5ceSopenharmony_ci	if (n < 0) {
129d4afb5ceSopenharmony_ci		lwsl_err("Scandir on '%s' failed, errno %d\n", dirpath, LWS_ERRNO);
130d4afb5ceSopenharmony_ci		return 1;
131d4afb5ceSopenharmony_ci	}
132d4afb5ceSopenharmony_ci
133d4afb5ceSopenharmony_ci	for (i = 0; i < n; i++) {
134d4afb5ceSopenharmony_ci#if !defined(__sun) && !defined(__QNX__)
135d4afb5ceSopenharmony_ci		unsigned int type = namelist[i]->d_type;
136d4afb5ceSopenharmony_ci#endif
137d4afb5ceSopenharmony_ci		if (strchr(namelist[i]->d_name, '~'))
138d4afb5ceSopenharmony_ci			goto skip;
139d4afb5ceSopenharmony_ci		lde.name = namelist[i]->d_name;
140d4afb5ceSopenharmony_ci
141d4afb5ceSopenharmony_ci		/*
142d4afb5ceSopenharmony_ci		 * some filesystems don't report this (ZFS) and tell that
143d4afb5ceSopenharmony_ci		 * files are LDOT_UNKNOWN
144d4afb5ceSopenharmony_ci		 */
145d4afb5ceSopenharmony_ci
146d4afb5ceSopenharmony_ci#if defined(__sun) || defined(__QNX__)
147d4afb5ceSopenharmony_ci		lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde);
148d4afb5ceSopenharmony_ci#else
149d4afb5ceSopenharmony_ci		/*
150d4afb5ceSopenharmony_ci		 * XFS on Linux doesn't fill in d_type at all, always zero.
151d4afb5ceSopenharmony_ci		 */
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci		if (DT_BLK != DT_UNKNOWN && type == DT_BLK)
154d4afb5ceSopenharmony_ci			lde.type = LDOT_BLOCK;
155d4afb5ceSopenharmony_ci		else if (DT_CHR != DT_UNKNOWN && type == DT_CHR)
156d4afb5ceSopenharmony_ci			lde.type = LDOT_CHAR;
157d4afb5ceSopenharmony_ci		else if (DT_DIR != DT_UNKNOWN && type == DT_DIR)
158d4afb5ceSopenharmony_ci			lde.type = LDOT_DIR;
159d4afb5ceSopenharmony_ci		else if (DT_FIFO != DT_UNKNOWN && type == DT_FIFO)
160d4afb5ceSopenharmony_ci			lde.type = LDOT_FIFO;
161d4afb5ceSopenharmony_ci		else if (DT_LNK != DT_UNKNOWN && type == DT_LNK)
162d4afb5ceSopenharmony_ci			lde.type = LDOT_LINK;
163d4afb5ceSopenharmony_ci		else if (DT_REG != DT_UNKNOWN && type == DT_REG)
164d4afb5ceSopenharmony_ci			lde.type = LDOT_FILE;
165d4afb5ceSopenharmony_ci		else if (DT_SOCK != DT_UNKNOWN && type == DT_SOCK)
166d4afb5ceSopenharmony_ci			lde.type = LDOTT_SOCKET;
167d4afb5ceSopenharmony_ci		else {
168d4afb5ceSopenharmony_ci			lde.type = LDOT_UNKNOWN;
169d4afb5ceSopenharmony_ci			lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde);
170d4afb5ceSopenharmony_ci		}
171d4afb5ceSopenharmony_ci#endif
172d4afb5ceSopenharmony_ci		if (cb(dirpath, user, &lde)) {
173d4afb5ceSopenharmony_ci			while (i < n)
174d4afb5ceSopenharmony_ci				free(namelist[i++]);
175d4afb5ceSopenharmony_ci			ret = 0; /* told to stop by cb */
176d4afb5ceSopenharmony_ci			goto bail;
177d4afb5ceSopenharmony_ci		}
178d4afb5ceSopenharmony_ciskip:
179d4afb5ceSopenharmony_ci		free(namelist[i]);
180d4afb5ceSopenharmony_ci	}
181d4afb5ceSopenharmony_ci
182d4afb5ceSopenharmony_cibail:
183d4afb5ceSopenharmony_ci	free(namelist);
184d4afb5ceSopenharmony_ci
185d4afb5ceSopenharmony_ci	return ret;
186d4afb5ceSopenharmony_ci}
187d4afb5ceSopenharmony_ci
188d4afb5ceSopenharmony_ci/*
189d4afb5ceSopenharmony_ci * Check filename against one globby filter
190d4afb5ceSopenharmony_ci *
191d4afb5ceSopenharmony_ci * We can support things like "*.rpm"
192d4afb5ceSopenharmony_ci */
193d4afb5ceSopenharmony_ci
194d4afb5ceSopenharmony_cistatic int
195d4afb5ceSopenharmony_cilws_dir_glob_check(const char *nm, const char *filt)
196d4afb5ceSopenharmony_ci{
197d4afb5ceSopenharmony_ci	while (*nm) {
198d4afb5ceSopenharmony_ci		if (*filt == '*') {
199d4afb5ceSopenharmony_ci			if (!strcmp(nm, filt + 1))
200d4afb5ceSopenharmony_ci				return 1;
201d4afb5ceSopenharmony_ci		} else {
202d4afb5ceSopenharmony_ci			if (*nm != *filt)
203d4afb5ceSopenharmony_ci				return 0;
204d4afb5ceSopenharmony_ci			filt++;
205d4afb5ceSopenharmony_ci		}
206d4afb5ceSopenharmony_ci		nm++;
207d4afb5ceSopenharmony_ci	}
208d4afb5ceSopenharmony_ci
209d4afb5ceSopenharmony_ci	return 0;
210d4afb5ceSopenharmony_ci}
211d4afb5ceSopenharmony_ci
212d4afb5ceSopenharmony_ci/*
213d4afb5ceSopenharmony_ci * We get passed a single filter string, like "*.txt" or "mydir/\*.rpm" or so.
214d4afb5ceSopenharmony_ci */
215d4afb5ceSopenharmony_ci
216d4afb5ceSopenharmony_ciint
217d4afb5ceSopenharmony_cilws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
218d4afb5ceSopenharmony_ci{
219d4afb5ceSopenharmony_ci	lws_dir_glob_t *filter = (lws_dir_glob_t*)user;
220d4afb5ceSopenharmony_ci	char path[384];
221d4afb5ceSopenharmony_ci
222d4afb5ceSopenharmony_ci	if (!strcmp(lde->name, ".") || !strcmp(lde->name, ".."))
223d4afb5ceSopenharmony_ci		return 0;
224d4afb5ceSopenharmony_ci
225d4afb5ceSopenharmony_ci	if (lde->type == LDOT_DIR)
226d4afb5ceSopenharmony_ci		return 0;
227d4afb5ceSopenharmony_ci
228d4afb5ceSopenharmony_ci	if (lws_dir_glob_check(lde->name, filter->filter)) {
229d4afb5ceSopenharmony_ci		lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep,
230d4afb5ceSopenharmony_ci							   lde->name);
231d4afb5ceSopenharmony_ci		filter->cb(filter->user, path);
232d4afb5ceSopenharmony_ci	}
233d4afb5ceSopenharmony_ci
234d4afb5ceSopenharmony_ci	return 0;
235d4afb5ceSopenharmony_ci}
236d4afb5ceSopenharmony_ci
237d4afb5ceSopenharmony_ciint
238d4afb5ceSopenharmony_cilws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
239d4afb5ceSopenharmony_ci{
240d4afb5ceSopenharmony_ci	char path[384];
241d4afb5ceSopenharmony_ci
242d4afb5ceSopenharmony_ci	if (!strcmp(lde->name, ".") || !strcmp(lde->name, ".."))
243d4afb5ceSopenharmony_ci		return 0;
244d4afb5ceSopenharmony_ci
245d4afb5ceSopenharmony_ci	lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, lde->name);
246d4afb5ceSopenharmony_ci
247d4afb5ceSopenharmony_ci	if (lde->type == LDOT_DIR) {
248d4afb5ceSopenharmony_ci#if !defined(WIN32) && !defined(_WIN32) && !defined(__COVERITY__)
249d4afb5ceSopenharmony_ci		char dummy[8];
250d4afb5ceSopenharmony_ci		/*
251d4afb5ceSopenharmony_ci		 * hm... eg, recursive dir symlinks can show up a LDOT_DIR
252d4afb5ceSopenharmony_ci		 * here.  If it's a symlink, don't recurse into it.
253d4afb5ceSopenharmony_ci		 *
254d4afb5ceSopenharmony_ci		 * Notice we immediately discard dummy without looking in it.
255d4afb5ceSopenharmony_ci		 * There is no way to get into trouble from its lack of NUL
256d4afb5ceSopenharmony_ci		 * termination in dummy[].  We just wanted to know if it was
257d4afb5ceSopenharmony_ci		 * a symlink at all.
258d4afb5ceSopenharmony_ci		 *
259d4afb5ceSopenharmony_ci		 * Hide this from Coverity since it flags any use of readlink()
260d4afb5ceSopenharmony_ci		 * even if safe.
261d4afb5ceSopenharmony_ci		 */
262d4afb5ceSopenharmony_ci		if (readlink(path, dummy, sizeof(dummy)) < 0)
263d4afb5ceSopenharmony_ci#endif
264d4afb5ceSopenharmony_ci			lws_dir(path, NULL, lws_dir_rm_rf_cb);
265d4afb5ceSopenharmony_ci
266d4afb5ceSopenharmony_ci		if (rmdir(path))
267d4afb5ceSopenharmony_ci			lwsl_warn("%s: rmdir %s failed %d\n", __func__, path, errno);
268d4afb5ceSopenharmony_ci	} else {
269d4afb5ceSopenharmony_ci		if (unlink(path)) {
270d4afb5ceSopenharmony_ci#if defined(WIN32)
271d4afb5ceSopenharmony_ci			SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
272d4afb5ceSopenharmony_ci			if (unlink(path))
273d4afb5ceSopenharmony_ci#else
274d4afb5ceSopenharmony_ci			if (rmdir(path))
275d4afb5ceSopenharmony_ci#endif
276d4afb5ceSopenharmony_ci			lwsl_warn("%s: unlink %s failed %d (type %d)\n",
277d4afb5ceSopenharmony_ci					__func__, path, errno, lde->type);
278d4afb5ceSopenharmony_ci		}
279d4afb5ceSopenharmony_ci	}
280d4afb5ceSopenharmony_ci
281d4afb5ceSopenharmony_ci	return 0;
282d4afb5ceSopenharmony_ci}
283d4afb5ceSopenharmony_ci
284d4afb5ceSopenharmony_ci
285d4afb5ceSopenharmony_ci#endif
286d4afb5ceSopenharmony_ci
287d4afb5ceSopenharmony_ci#if defined(LWS_WITH_PLUGINS_API)
288d4afb5ceSopenharmony_ci
289d4afb5ceSopenharmony_cistruct lws_plugins_args {
290d4afb5ceSopenharmony_ci	struct lws_plugin	**pplugin;
291d4afb5ceSopenharmony_ci	const char		*_class;
292d4afb5ceSopenharmony_ci	const char		*filter;
293d4afb5ceSopenharmony_ci	each_plugin_cb_t	each;
294d4afb5ceSopenharmony_ci	void			*each_user;
295d4afb5ceSopenharmony_ci};
296d4afb5ceSopenharmony_ci
297d4afb5ceSopenharmony_cistatic int
298d4afb5ceSopenharmony_cilws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
299d4afb5ceSopenharmony_ci{
300d4afb5ceSopenharmony_ci	struct lws_plugins_args *pa = (struct lws_plugins_args *)user;
301d4afb5ceSopenharmony_ci	char path[256], base[64], *q = base;
302d4afb5ceSopenharmony_ci	const lws_plugin_header_t *pl;
303d4afb5ceSopenharmony_ci	const char *p;
304d4afb5ceSopenharmony_ci
305d4afb5ceSopenharmony_ci	if (strlen(lde->name) < 7)
306d4afb5ceSopenharmony_ci		return 0; /* keep going */
307d4afb5ceSopenharmony_ci
308d4afb5ceSopenharmony_ci	/*
309d4afb5ceSopenharmony_ci	 * The actual plugin names for protocol plugins look like
310d4afb5ceSopenharmony_ci	 * "libprotocol_lws_ssh_base.so" and for event libs
311d4afb5ceSopenharmony_ci	 * "libwebsockets-evlib_ev.so"... to recover the base name of
312d4afb5ceSopenharmony_ci	 * "lws_ssh_base" and "evlib_ev" we strip from the left to after the
313d4afb5ceSopenharmony_ci	 * first _ or -, and then truncate at the first .
314d4afb5ceSopenharmony_ci	 */
315d4afb5ceSopenharmony_ci
316d4afb5ceSopenharmony_ci	p = lde->name;
317d4afb5ceSopenharmony_ci	while (*p && *p != '_' && *p != '-')
318d4afb5ceSopenharmony_ci		p++;
319d4afb5ceSopenharmony_ci	if (!*p)
320d4afb5ceSopenharmony_ci		return 0;
321d4afb5ceSopenharmony_ci	p++;
322d4afb5ceSopenharmony_ci	while (*p && *p != '.' && lws_ptr_diff(q, base) < (int)sizeof(base) - 1)
323d4afb5ceSopenharmony_ci		*q++ = *p++;
324d4afb5ceSopenharmony_ci	*q = '\0';
325d4afb5ceSopenharmony_ci
326d4afb5ceSopenharmony_ci	/* if he's given a filter, only match if base matches it */
327d4afb5ceSopenharmony_ci	if (pa->filter && strcmp(base, pa->filter))
328d4afb5ceSopenharmony_ci		return 0; /* keep going */
329d4afb5ceSopenharmony_ci
330d4afb5ceSopenharmony_ci	lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
331d4afb5ceSopenharmony_ci
332d4afb5ceSopenharmony_ci	pl = lws_plat_dlopen(pa->pplugin, path, base, pa->_class,
333d4afb5ceSopenharmony_ci			     pa->each, pa->each_user);
334d4afb5ceSopenharmony_ci
335d4afb5ceSopenharmony_ci	/*
336d4afb5ceSopenharmony_ci	 * If we were looking for a specific plugin, finding it should make
337d4afb5ceSopenharmony_ci	 * us stop looking (eg, to account for directory precedence of the
338d4afb5ceSopenharmony_ci	 * same plugin).  If scanning for plugins in a dir, we always keep
339d4afb5ceSopenharmony_ci	 * going.
340d4afb5ceSopenharmony_ci	 */
341d4afb5ceSopenharmony_ci
342d4afb5ceSopenharmony_ci	return pa->filter && pl;
343d4afb5ceSopenharmony_ci}
344d4afb5ceSopenharmony_ci
345d4afb5ceSopenharmony_ciint
346d4afb5ceSopenharmony_cilws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
347d4afb5ceSopenharmony_ci		 const char *_class, const char *filter,
348d4afb5ceSopenharmony_ci		 each_plugin_cb_t each, void *each_user)
349d4afb5ceSopenharmony_ci{
350d4afb5ceSopenharmony_ci	struct lws_plugins_args pa;
351d4afb5ceSopenharmony_ci	char *ld_env;
352d4afb5ceSopenharmony_ci	int ret = 1;
353d4afb5ceSopenharmony_ci
354d4afb5ceSopenharmony_ci	pa.pplugin = pplugin;
355d4afb5ceSopenharmony_ci	pa._class = _class;
356d4afb5ceSopenharmony_ci	pa.each = each;
357d4afb5ceSopenharmony_ci	pa.each_user = each_user;
358d4afb5ceSopenharmony_ci	pa.filter = filter;
359d4afb5ceSopenharmony_ci
360d4afb5ceSopenharmony_ci	/*
361d4afb5ceSopenharmony_ci	 * Check LD_LIBRARY_PATH override path first if present
362d4afb5ceSopenharmony_ci	 */
363d4afb5ceSopenharmony_ci
364d4afb5ceSopenharmony_ci	ld_env = getenv("LD_LIBRARY_PATH");
365d4afb5ceSopenharmony_ci	if (ld_env) {
366d4afb5ceSopenharmony_ci		char temp[128];
367d4afb5ceSopenharmony_ci		struct lws_tokenize ts;
368d4afb5ceSopenharmony_ci
369d4afb5ceSopenharmony_ci		memset(&ts, 0, sizeof(ts));
370d4afb5ceSopenharmony_ci		ts.start = ld_env;
371d4afb5ceSopenharmony_ci		ts.len = strlen(ld_env);
372d4afb5ceSopenharmony_ci		ts.flags = LWS_TOKENIZE_F_SLASH_NONTERM |
373d4afb5ceSopenharmony_ci			   LWS_TOKENIZE_F_DOT_NONTERM |
374d4afb5ceSopenharmony_ci			   LWS_TOKENIZE_F_MINUS_NONTERM |
375d4afb5ceSopenharmony_ci			   LWS_TOKENIZE_F_NO_INTEGERS |
376d4afb5ceSopenharmony_ci			   LWS_TOKENIZE_F_NO_FLOATS;
377d4afb5ceSopenharmony_ci
378d4afb5ceSopenharmony_ci		do {
379d4afb5ceSopenharmony_ci			ts.e = (int8_t)lws_tokenize(&ts);
380d4afb5ceSopenharmony_ci			if (ts.e != LWS_TOKZE_TOKEN)
381d4afb5ceSopenharmony_ci				continue;
382d4afb5ceSopenharmony_ci
383d4afb5ceSopenharmony_ci			lws_strnncpy(temp, ts.token,
384d4afb5ceSopenharmony_ci				     ts.token_len,
385d4afb5ceSopenharmony_ci				     sizeof(temp));
386d4afb5ceSopenharmony_ci
387d4afb5ceSopenharmony_ci			lwsl_info("%s: trying %s\n", __func__, temp);
388d4afb5ceSopenharmony_ci			if (!lws_dir(temp, &pa, lws_plugins_dir_cb))
389d4afb5ceSopenharmony_ci				ret = 0;
390d4afb5ceSopenharmony_ci
391d4afb5ceSopenharmony_ci		} while (ts.e > 0);
392d4afb5ceSopenharmony_ci	}
393d4afb5ceSopenharmony_ci
394d4afb5ceSopenharmony_ci	while (d && *d) {
395d4afb5ceSopenharmony_ci		lwsl_info("%s: trying %s\n", __func__, *d);
396d4afb5ceSopenharmony_ci		if (!lws_dir(*d, &pa, lws_plugins_dir_cb))
397d4afb5ceSopenharmony_ci			ret = 0;
398d4afb5ceSopenharmony_ci
399d4afb5ceSopenharmony_ci		d++;
400d4afb5ceSopenharmony_ci	}
401d4afb5ceSopenharmony_ci
402d4afb5ceSopenharmony_ci	return ret;
403d4afb5ceSopenharmony_ci}
404d4afb5ceSopenharmony_ci
405d4afb5ceSopenharmony_ciint
406d4afb5ceSopenharmony_cilws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
407d4afb5ceSopenharmony_ci		    void *each_user)
408d4afb5ceSopenharmony_ci{
409d4afb5ceSopenharmony_ci	struct lws_plugin *p = *pplugin, *p1;
410d4afb5ceSopenharmony_ci
411d4afb5ceSopenharmony_ci	while (p) {
412d4afb5ceSopenharmony_ci		if (each)
413d4afb5ceSopenharmony_ci			each(p, each_user);
414d4afb5ceSopenharmony_ci		lws_plat_destroy_dl(p);
415d4afb5ceSopenharmony_ci		p1 = p->list;
416d4afb5ceSopenharmony_ci		p->list = NULL;
417d4afb5ceSopenharmony_ci		lws_free(p);
418d4afb5ceSopenharmony_ci		p = p1;
419d4afb5ceSopenharmony_ci	}
420d4afb5ceSopenharmony_ci
421d4afb5ceSopenharmony_ci	*pplugin = NULL;
422d4afb5ceSopenharmony_ci
423d4afb5ceSopenharmony_ci	return 0;
424d4afb5ceSopenharmony_ci}
425d4afb5ceSopenharmony_ci#endif
426