changeset 982:0e9e09941f5a

irccd: improve plugin warnings
author David Demelier <markand@malikania.fr>
date Tue, 09 Feb 2021 22:03:07 +0100
parents e4fc051e2d94
children d5aa6aba8959
files irccd/dl-plugin.c irccd/dl-plugin.h irccd/js-plugin.c irccd/js-plugin.h lib/irccd/irccd.c lib/irccd/plugin.c lib/irccd/plugin.h
diffstat 7 files changed, 85 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/irccd/dl-plugin.c	Tue Feb 09 21:15:51 2021 +0100
+++ b/irccd/dl-plugin.c	Tue Feb 09 22:03:07 2021 +0100
@@ -175,11 +175,13 @@
 }
 
 static struct self *
-init(const char *path)
+init(const char *name, const char *path)
 {
 	struct self self;
 	struct stat st;
 
+	strlcpy(self.plugin.name, name, sizeof (self.plugin.name));
+
 	/*
 	 * It's not possible to get the exact error code when loading a plugin
 	 * using dlopen, since we're trying a lot of files that potentially not
@@ -210,19 +212,19 @@
 }
 
 static struct irc_plugin *
-wrap_open(struct irc_plugin_loader *ldr, const char *path)
+wrap_open(struct irc_plugin_loader *ldr, const char *name, const char *path)
 {
 	(void)ldr;
 
-	return dl_plugin_open(path);
+	return dl_plugin_open(name, path);
 }
 
 struct irc_plugin *
-dl_plugin_open(const char *path)
+dl_plugin_open(const char *name, const char *path)
 {
 	struct self *self;
 
-	if (!(self = init(path)))
+	if (!(self = init(name, path)))
 		return false;
 
 	/* Data and all callbacks. */
--- a/irccd/dl-plugin.h	Tue Feb 09 21:15:51 2021 +0100
+++ b/irccd/dl-plugin.h	Tue Feb 09 22:03:07 2021 +0100
@@ -23,7 +23,7 @@
 struct irc_plugin_loader;
 
 struct irc_plugin *
-dl_plugin_open(const char *);
+dl_plugin_open(const char *, const char *);
 
 struct irc_plugin_loader *
 dl_plugin_loader_new(void);
--- a/irccd/js-plugin.c	Tue Feb 09 21:15:51 2021 +0100
+++ b/irccd/js-plugin.c	Tue Feb 09 22:03:07 2021 +0100
@@ -16,10 +16,13 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <compat.h>
+
 #include <sys/stat.h>
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
@@ -49,6 +52,7 @@
 struct self {
 	struct irc_plugin plugin;
 	duk_context *ctx;
+	char location[PATH_MAX];
 	char **options;
 	char **templates;
 	char **paths;
@@ -138,6 +142,35 @@
 	duk_put_prop_string(ctx, -2, "channels");
 }
 
+static void
+log_trace(struct self *self)
+{
+	const char *name, *message;
+	char *stack, *token, *p;
+	int linenumber;
+
+	duk_get_prop_string(self->ctx, -1, "name");
+	name = duk_get_string(self->ctx, -1);
+	duk_pop(self->ctx);
+	duk_get_prop_string(self->ctx, -1, "message");
+	message = duk_get_string(self->ctx, -1);
+	duk_pop(self->ctx);
+	duk_get_prop_string(self->ctx, -1, "stack");
+	stack = strdup(duk_opt_string(self->ctx, -1, ""));
+	duk_pop(self->ctx);
+	duk_get_prop_string(self->ctx, -1, "lineNumber");
+	linenumber = duk_get_int(self->ctx, -1);
+	duk_pop(self->ctx);
+
+	irc_log_warn("plugin %s: %s:%d", self->plugin.name, self->location, linenumber);
+
+	/* We can't put a '\n' in irc_log_warn so loop for them. */
+	for (p = stack; *stack && (token = strtok_r(p, "\n", &p)); )
+		irc_log_warn("plugin %s: %s", self->plugin.name, token);
+
+	free(stack);
+}
+
 static const char **
 get_table(duk_context *ctx, const char *name, char ***ptable)
 {
@@ -294,7 +327,7 @@
 	}
 
 	if (duk_pcall(self->ctx, nargs) != 0)
-		irc_log_warn("plugin %s: %s\n", duk_to_string(self->ctx, -1));
+		log_trace(plg->data);
 
 	duk_pop(self->ctx);
 }
@@ -433,12 +466,16 @@
 }
 
 static struct self *
-init(const char *path, const char *script)
+init(const char *name, const char *path, const char *script)
 {
 	struct self *js;
 
 	js = irc_util_calloc(1, sizeof (*js));
 	js->ctx = duk_create_heap(wrap_malloc, wrap_realloc, wrap_free, NULL, NULL);
+	strlcpy(js->plugin.name, name, sizeof (js->plugin.name));
+
+	/* Copy path because Duktape has no notions of it. */
+	strlcpy(js->location, path, sizeof (js->location));
 
 	/* Tables used to retrieve data. */
 	duk_push_object(js->ctx);
@@ -465,7 +502,7 @@
 
 	/* Finally execute the script. */
 	if (duk_peval_string(js->ctx, script) != 0) {
-		irc_log_warn("plugin: %s: %s", path, duk_to_string(js->ctx, -1));
+		log_trace(js);
 		duk_destroy_heap(js->ctx);
 		free(js);
 		return NULL;
@@ -517,11 +554,11 @@
 }
 
 static struct irc_plugin *
-wrap_open(struct irc_plugin_loader *ldr, const char *path)
+wrap_open(struct irc_plugin_loader *ldr, const char *name, const char *path)
 {
 	(void)ldr;
 
-	return js_plugin_open(path);
+	return js_plugin_open(name, path);
 }
 
 duk_context *
@@ -533,7 +570,7 @@
 }
 
 struct irc_plugin *
-js_plugin_open(const char *path)
+js_plugin_open(const char *name, const char *path)
 {
 	assert(path);
 
@@ -546,13 +583,13 @@
 	 */
 	if (!(script = eat(path))) {
 		if (errno != ENOENT)
-			irc_log_warn("irccd: %s: %s", path, strerror(errno));
+			irc_log_warn("plugin: %s: %s", path, strerror(errno));
 
 		return NULL;
 	}
 
 	/* Init already log errors. */
-	if (!(self = init(path, script))) {
+	if (!(self = init(name, path, script))) {
 		free(script);
 		return NULL;
 	}
--- a/irccd/js-plugin.h	Tue Feb 09 21:15:51 2021 +0100
+++ b/irccd/js-plugin.h	Tue Feb 09 22:03:07 2021 +0100
@@ -27,7 +27,7 @@
 js_plugin_get_context(struct irc_plugin *);
 
 struct irc_plugin *
-js_plugin_open(const char *);
+js_plugin_open(const char *, const char *);
 
 struct irc_plugin_loader *
 js_plugin_loader_new(void);
--- a/lib/irccd/irccd.c	Tue Feb 09 21:15:51 2021 +0100
+++ b/lib/irccd/irccd.c	Tue Feb 09 22:03:07 2021 +0100
@@ -198,7 +198,7 @@
 		snprintf(path, sizeof (path), "%s/%s.%s", base, name, ext);
 		irc_log_info("irccd: trying %s", path);
 
-		if ((p = irc_plugin_loader_open(ldr, path)))
+		if ((p = irc_plugin_loader_open(ldr, name, path)))
 			return p;
 	}
 
@@ -206,9 +206,9 @@
 }
 
 static inline struct irc_plugin *
-open_plugin(struct irc_plugin_loader *ldr, const char *path)
+open_plugin(struct irc_plugin_loader *ldr, const char *name, const char *path)
 {
-	return irc_plugin_loader_open(ldr, path);
+	return irc_plugin_loader_open(ldr, name, path);
 }
 
 static void
@@ -234,6 +234,26 @@
 		    sinfo->si_pid, WEXITSTATUS(status));
 }
 
+static inline int
+is_extension_valid(const struct irc_plugin_loader *ldr, const char *path)
+{
+	char exts[IRC_EXTENSIONS_LEN], *token, *p, *ext;
+
+	strlcpy(exts, ldr->extensions, sizeof (exts));
+
+	/* If we're unable to find an extension, assume it's allowed. */
+	if (!(ext = strrchr(path, '.')))
+		return 1;
+
+	ext++;
+
+	for (p = exts; (token = strtok_r(p, ":", &p)); )
+		if (strcmp(token, ext) == 0)
+			return 1;
+
+	return 0;
+}
+
 void
 irc_bot_init(void)
 {
@@ -336,7 +356,9 @@
 
 	SLIST_FOREACH(ldr, &irc.plugin_loaders, link) {
 		if (path) {
-			if ((p = open_plugin(ldr, path)))
+			if (!is_extension_valid(ldr, path))
+				continue;
+			if ((p = open_plugin(ldr, name, path)))
 				break;
 		} else {
 			/* Copy the paths to tokenize it. */
@@ -354,9 +376,7 @@
 	}
 
 	if (!p)
-		irc_log_warn("irccd: could not find plugin %s", name);
-
-	strlcpy(p->name, name, sizeof (p->name));
+		return irc_log_warn("irccd: could not find plugin %s", name), NULL;
 
 	/* Set default paths if they are not set. */
 	irc_plugin_set_path(p, "cache", irc_util_printf(pathbuf, sizeof (pathbuf),
--- a/lib/irccd/plugin.c	Tue Feb 09 21:15:51 2021 +0100
+++ b/lib/irccd/plugin.c	Tue Feb 09 22:03:07 2021 +0100
@@ -170,12 +170,12 @@
 }
 
 struct irc_plugin *
-irc_plugin_loader_open(struct irc_plugin_loader *ldr, const char *path)
+irc_plugin_loader_open(struct irc_plugin_loader *ldr, const char *name, const char *path)
 {
 	assert(ldr);
 	assert(path);
 
-	return ldr->open(ldr, path);
+	return ldr->open(ldr, name, path);
 }
 
 void
--- a/lib/irccd/plugin.h	Tue Feb 09 21:15:51 2021 +0100
+++ b/lib/irccd/plugin.h	Tue Feb 09 22:03:07 2021 +0100
@@ -60,7 +60,7 @@
 struct irc_plugin_loader {
 	char paths[IRC_PATHS_LEN];
 	char extensions[IRC_EXTENSIONS_LEN];
-	struct irc_plugin *(*open)(struct irc_plugin_loader *, const char *);
+	struct irc_plugin *(*open)(struct irc_plugin_loader *, const char *, const char *);
 	void (*finish)(struct irc_plugin_loader *);
 	void *data;
 	SLIST_ENTRY(irc_plugin_loader) link;
@@ -111,7 +111,7 @@
 irc_plugin_finish(struct irc_plugin *);
 
 struct irc_plugin *
-irc_plugin_loader_open(struct irc_plugin_loader *, const char *);
+irc_plugin_loader_open(struct irc_plugin_loader *, const char *, const char *);
 
 void
 irc_plugin_loader_finish(struct irc_plugin_loader *);