changeset 968:5ded2b4994af

irccd: bring back support to config, templates and paths to plugins
author David Demelier <markand@malikania.fr>
date Wed, 03 Feb 2021 11:19:31 +0100
parents 8becffd7617a
children d7501067de95
files irccd/conf.y irccd/js-plugin.c irccd/jsapi-plugin.c irccd/jsapi-server.c irccd/main.c irccd/peer.c lib/irccd/config.h.in lib/irccd/irccd.c lib/irccd/irccd.h lib/irccd/util.c lib/irccd/util.h
diffstat 11 files changed, 168 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/irccd/conf.y	Tue Feb 02 13:51:39 2021 +0100
+++ b/irccd/conf.y	Wed Feb 03 11:19:31 2021 +0100
@@ -514,18 +514,20 @@
 	{
 		struct irc_plugin *p;
 		struct pair *kv;
+		const char *location = $3 ? $3->location : NULL;
 
-		if (!(p = irc_bot_plugin_find($2)))
+		if (!(p = irc_bot_plugin_find($2, location)))
 			goto cleanup;
 
-		if ($3) {
+		if ($3 && $3->templates)
 			SLIST_FOREACH(kv, $3->templates, link)
 				irc_plugin_set_template(p, kv->key, kv->value);
+		if ($3 && $3->config)
 			SLIST_FOREACH(kv, $3->config, link)
 				irc_plugin_set_option(p, kv->key, kv->value);
+		if ($3 && $3->paths)
 			SLIST_FOREACH(kv, $3->paths, link)
 				irc_plugin_set_path(p, kv->key, kv->value);
-		}
 
 		irc_bot_plugin_add(p);
 
--- a/irccd/js-plugin.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/irccd/js-plugin.c	Wed Feb 03 11:19:31 2021 +0100
@@ -443,6 +443,15 @@
 	js = irc_util_calloc(1, sizeof (*js));
 	js->ctx = duk_create_heap(wrap_malloc, wrap_realloc, wrap_free, NULL, NULL);
 
+	/* Tables used to retrieve data. */
+	duk_push_object(js->ctx);
+	duk_put_global_string(js->ctx, JSAPI_PLUGIN_PROP_OPTIONS);
+	duk_push_object(js->ctx);
+	duk_put_global_string(js->ctx, JSAPI_PLUGIN_PROP_TEMPLATES);
+	duk_push_object(js->ctx);
+	duk_put_global_string(js->ctx, JSAPI_PLUGIN_PROP_PATHS);
+
+	/* Load Javascript APIs. */
 	jsapi_load(js->ctx);
 	jsapi_chrono_load(js->ctx);
 	jsapi_directory_load(js->ctx);
@@ -455,6 +464,7 @@
 	jsapi_unicode_load(js->ctx);
 	jsapi_util_load(js->ctx);
 
+	/* 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));
 		duk_destroy_heap(js->ctx);
--- a/irccd/jsapi-plugin.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/irccd/jsapi-plugin.c	Wed Feb 03 11:19:31 2021 +0100
@@ -81,12 +81,6 @@
 	return 0;
 }
 
-/*
- * get
- * ------------------------------------------------------------------
- *
- * Get the Irccd.Plugin.(config|templates|paths) property.
- */
 static duk_ret_t
 get(duk_context *ctx, const char *name)
 {
--- a/irccd/jsapi-server.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/irccd/jsapi-server.c	Wed Feb 03 11:19:31 2021 +0100
@@ -504,7 +504,7 @@
 Server_find(duk_context *ctx)
 {
 	const char *name = duk_require_string(ctx, 0);
-	struct irc_server *s = irc_bot_server_find(name);
+	struct irc_server *s = irc_bot_server_get(name);
 
 	if (!s)
 		return 0;
--- a/irccd/main.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/irccd/main.c	Wed Feb 03 11:19:31 2021 +0100
@@ -20,6 +20,7 @@
 #include <compat.h>
 
 #include <err.h>
+#include <errno.h>
 #include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,10 +38,16 @@
 #include "js-plugin.h"
 #include "peer.h"
 
+struct pollables {
+	struct pollfd *fds;
+	size_t fdsz;
+	size_t botsz;
+	size_t localsz;
+};
+
 static const char *config = IRCCD_SYSCONFDIR "/irccd.conf";
 static struct peers peers;
 static int running = 1;
-static int has_transport;
 
 /* conf.y */
 void
@@ -66,9 +73,6 @@
 	struct peer *p;
 	size_t i = 1;
 
-	if (!has_transport)
-		return 0;
-
 	LIST_FOREACH(p, &peers, link)
 		++i;
 
@@ -98,13 +102,12 @@
 }
 
 static void
-prepare(struct pollfd *fd)
+prepare(struct pollables *pb)
 {
 	struct peer *p;
+	struct pollfd *fd = pb->fds + pb->botsz;
 
-	if (!has_transport)
-		return;
-
+	irc_bot_prepare(pb->fds);
 	transport_prepare(fd++);
 
 	LIST_FOREACH(p, &peers, link)
@@ -112,13 +115,12 @@
 }
 
 static void
-flush(const struct pollfd *fd)
+flush(const struct pollables *pb)
 {
 	struct peer *peer, *tmp;
+	struct pollfd *fd = pb->fds + pb->botsz;
 
-	if (!has_transport)
-		return;
-
+	irc_bot_flush(pb->fds);
 	transport_flush(fd++);
 
 	LIST_FOREACH_SAFE(peer, &peers, link, tmp) {
@@ -135,37 +137,40 @@
 	config_open(config);
 }
 
+static struct pollables
+pollables(void)
+{
+	struct pollables pb = {0};
+
+	pb.botsz = irc_bot_poll_count();
+	pb.localsz = poll_count();
+	pb.fdsz = pb.botsz + pb.localsz;
+	pb.fds = irc_util_calloc(pb.fdsz, sizeof (*pb.fds));
+
+	prepare(&pb);
+
+	return pb;
+}
+
 static void
 loop(void)
 {
-#if 0
+	struct pollables pb;
 	struct irc_event ev;
-	struct pollfd *fds;
-	size_t botcount, owncount;
 
 	while (running) {
-		/*
-		 * Compute how much fd the bot requires and append our own
-		 * transport and peers.
-		 */
-		botcount = irc_bot_poll_count();
-		owncount = poll_count();
-		fds = irc_util_calloc(botcount + owncount, sizeof (*fds));
+		pb = pollables();
 
-		irc_bot_prepare(fds);
-		prepare(&fds[botcount]);
+		if (poll(pb.fds, pb.fdsz, 1000) < 0 && errno != EINTR)
+			err(1, "poll");
 
-		if (poll(fds,
-
-		irc_bot_flush(fds);
-		flush(&fds[botcount]);
+		flush(&pb);
 
 		while (irc_bot_dequeue(&ev))
 			broadcast(&ev);
 
-		free(fds);
+		free(pb.fds);
 	}
-#endif
 }
 
 static inline void
@@ -177,6 +182,7 @@
 		peer_finish(peer);
 
 	transport_finish();
+	irc_bot_finish();
 }
 
 static void
--- a/irccd/peer.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/irccd/peer.c	Wed Feb 03 11:19:31 2021 +0100
@@ -68,7 +68,7 @@
 {
 	struct irc_server *s;
 
-	if (!(s = irc_bot_server_find(id))) {
+	if (!(s = irc_bot_server_get(id))) {
 		peer_send(p, "server %s not found", id);
 		return NULL;
 	}
--- a/lib/irccd/config.h.in	Tue Feb 02 13:51:39 2021 +0100
+++ b/lib/irccd/config.h.in	Wed Feb 03 11:19:31 2021 +0100
@@ -24,8 +24,10 @@
 #define IRCCD_VERSION_PATCH     @IRCCD_VERSION_PATCH@
 #define IRCCD_VERSION           "@IRCCD_VERSION_MAJOR@.@IRCCD_VERSION_MINOR@.@IRCCD_VERSION_PATCH@"
 
+#define IRCCD_CACHEDIR          "@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/cache/irccd"
 #define IRCCD_SYSCONFDIR        "@CMAKE_INSTALL_FULL_SYSCONFDIR@"
 #define IRCCD_LIBDIR            "@CMAKE_INSTALL_FULL_LIBDIR@"
+#define IRCCD_DATADIR           "@CMAKE_INSTALL_FULL_DATADIR@/irccd"
 
 #cmakedefine IRCCD_WITH_JS
 #cmakedefine IRCCD_WITH_SSL
--- a/lib/irccd/irccd.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/lib/irccd/irccd.c	Wed Feb 03 11:19:31 2021 +0100
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <config.h>
+
 #include <assert.h>
 #include <ctype.h>
 #include <err.h>
@@ -182,55 +184,30 @@
 	df.exec(df.data);
 }
 
-#if 0
-static void
-process(struct pkg *pkg)
+static struct irc_plugin *
+find_plugin(struct irc_plugin_loader *ldr, const char *base, const char *name)
 {
-	struct irc_server *s;
-	struct irc_peer *p, *ptmp;
-	struct irc_event ev;
-
-	if (poll(pkg->fds, pkg->fdsz, 1000) < 0 && errno != EINTR)
-		err(1, "poll");
+	char path[PATH_MAX], buf[IRC_EXTENSIONS_LEN], *t, *ext;
+	struct irc_plugin *p;
 
-	/*
-	 * We can't to what file descriptors belong to so pass every file to
-	 * all services and they must check if they are associated to it or
-	 * not.
-	 */
-	for (size_t i = 0; i < pkg->fdsz; ++i) {
-		pipe_flush(&pkg->fds[i]);
-
-		LIST_FOREACH(s, &irc.servers, link)
-			irc_server_flush(s, &pkg->fds[i]);
+	strlcpy(buf, ldr->extensions, sizeof (buf));
 
-		/* Accept new transport client. */
-		if ((p = irc_transport_flush(&pkg->fds[i])))
-			LIST_INSERT_HEAD(&irc.peers, p, link);
+	for (t = buf; (ext = strtok_r(t, ":", &t)); ) {
+		snprintf(path, sizeof (path), "%s/%s.%s", base, name, ext);
+		irc_log_info("irccd: trying %s", path);
 
-		/* Flush clients. */
-		LIST_FOREACH_SAFE(p, &irc.peers, link, ptmp) {
-			if (!irc_peer_flush(p, &pkg->fds[i])) {
-				irc_peer_finish(p);
-				LIST_REMOVE(p, link);
-			}
-		}
+		if ((p = irc_plugin_loader_open(ldr, path)))
+			return p;
 	}
 
-	/*
-	 * For every server, poll any kind of new event and pass them to the
-	 * plugin unless the rules explicitly disallow us to do so.
-	 */
-	LIST_FOREACH(s, &irc.servers, link) {
-		while (irc_server_poll(s, &ev)) {
-			broadcast(&ev);
-			invoke(&ev);
-			irc_event_finish(&ev);
-		}
-	}
+	return NULL;
 }
 
-#endif
+static inline struct irc_plugin *
+open_plugin(struct irc_plugin_loader *ldr, const char *path)
+{
+	return irc_plugin_loader_open(ldr, path);
+}
 
 static inline size_t
 rulescount(void)
@@ -258,6 +235,8 @@
 {
 	assert(s);
 
+	irc_log_info("irccd: added new server: %s", s->name);
+
 	irc_server_incref(s);
 	irc_server_connect(s);
 
@@ -265,7 +244,7 @@
 }
 
 struct irc_server *
-irc_bot_server_find(const char *name)
+irc_bot_server_get(const char *name)
 {
 	struct irc_server *s;
 
@@ -281,7 +260,7 @@
 {
 	struct irc_server *s;
 
-	if (!(s = irc_bot_server_find(name)))
+	if (!(s = irc_bot_server_get(name)))
 		return;
 
 	irc_server_disconnect(s);
@@ -303,6 +282,7 @@
 
 	LIST_FOREACH_SAFE(s, &irc.servers, link, tmp)
 		irc_bot_server_remove(s->name);
+	LIST_INIT(&irc.servers);
 }
 
 void
@@ -312,58 +292,59 @@
 
 	LIST_INSERT_HEAD(&irc.plugins, p, link);
 
-	irc_log_info("plugin %s: %s", p->name, p->description);
-	irc_log_info("plugin %s: version %s, from %s (%s license)", p->name,
+	irc_log_info("irccd: add new plugin: %s", p->name, p->description);
+	irc_log_info("irccd: %s: version %s, from %s (%s license)", p->name,
 	    p->version, p->author, p->license);
 
 	irc_plugin_load(p);
 }
 
-static struct irc_plugin *
-find_plugin(struct irc_plugin_loader *ldr, const char *base, const char *name)
+struct irc_plugin *
+irc_bot_plugin_find(const char *name, const char *path)
 {
-	char path[PATH_MAX], buf[IRC_EXTENSIONS_LEN], *t, *ext;
-	struct irc_plugin *p;
-
-	strlcpy(buf, ldr->extensions, sizeof (buf));
-
-	for (t = buf; (ext = strtok_r(t, ":", &t)); ) {
-		snprintf(path, sizeof (path), "%s/%s.%s", base, name, ext);
-		irc_log_info("irccd: trying %s", path);
+	assert(name);
 
-		if ((p = irc_plugin_loader_open(ldr, path)))
-			return p;
-	}
-
-	return NULL;
-}
-
-struct irc_plugin *
-irc_bot_plugin_find(const char *name)
-{
-	char buf[IRC_PATHS_LEN], *t, *token;
+	char buf[IRC_PATHS_LEN], pathbuf[PATH_MAX], *t, *token;
 	struct irc_plugin *p = NULL;
 	struct irc_plugin_loader *ldr;
 
-	irc_log_info("irccd: trying to find plugin %s", name);
+	if (!path)
+		irc_log_info("irccd: trying to find plugin %s", name);
+	else
+		irc_log_info("irccd: opening plugin %s", name);
 
 	SLIST_FOREACH(ldr, &irc.plugin_loaders, link) {
-		/* Copy the paths to tokenize it. */
-		strlcpy(buf, ldr->paths, sizeof (buf));
+		if (path) {
+			if ((p = open_plugin(ldr, path)))
+				break;
+		} else {
+			/* Copy the paths to tokenize it. */
+			strlcpy(buf, ldr->paths, sizeof (buf));
 
-		/*
-		 * For every directory (separated by colon) call find_plugin
-		 * which will append the extension and try to open it.
-		 */
-		for (t = buf; (token = strtok_r(t, ":", &t)); ) {
-			if ((p = find_plugin(ldr, token, name)))
-				break;
+			/*
+			 * For every directory (separated by colon) call find_plugin
+			 * which will append the extension and try to open it.
+			 */
+			for (t = buf; (token = strtok_r(t, ":", &t)); ) {
+				if ((p = find_plugin(ldr, token, name)))
+					break;
+			}
 		}
 	}
 
 	if (!p)
 		irc_log_warn("irccd: could not find plugin %s", name);
 
+	strlcpy(p->name, name, sizeof (p->name));
+
+	/* Set default paths if they are not set. */
+	irc_plugin_set_path(p, "cache", irc_util_printf(pathbuf, sizeof (pathbuf),
+	    "%s/plugin/%s", IRCCD_CACHEDIR, p->name));
+	irc_plugin_set_path(p, "data", irc_util_printf(pathbuf, sizeof (pathbuf),
+	    "%s/plugin/%s", IRCCD_DATADIR, p->name));
+	irc_plugin_set_path(p, "config", irc_util_printf(pathbuf, sizeof (pathbuf),
+	    "%s/irccd/plugin/%s", IRCCD_SYSCONFDIR, p->name));
+
 	return p;
 }
 
@@ -402,6 +383,16 @@
 }
 
 void
+irc_bot_plugin_clear(void)
+{
+	struct irc_plugin *p, *tmp;
+
+	LIST_FOREACH_SAFE(p, &irc.plugins, link, tmp)
+		irc_bot_plugin_remove(p->name);
+	LIST_INIT(&irc.plugins);
+}
+
+void
 irc_bot_rule_insert(struct irc_rule *rule, size_t index)
 {
 	assert(rule);
@@ -507,3 +498,20 @@
 	if (write(pipes[1], &df, sizeof (df)) != sizeof (df))
 		err(1, "write");
 }
+
+void
+irc_bot_finish(void)
+{
+	struct irc_plugin_loader *ld, *ldtmp;
+
+	/*
+	 * First remove all loaders to mkae sure plugins won't try to load
+	 * new plugins.
+	 */
+	SLIST_FOREACH_SAFE(ld, &irc.plugin_loaders, link, ldtmp)
+		irc_plugin_loader_finish(ld);
+
+	irc_bot_server_clear();
+	irc_bot_plugin_clear();
+	irc_bot_rule_clear();
+}
--- a/lib/irccd/irccd.h	Tue Feb 02 13:51:39 2021 +0100
+++ b/lib/irccd/irccd.h	Wed Feb 03 11:19:31 2021 +0100
@@ -39,7 +39,7 @@
 irc_bot_server_add(struct irc_server *);
 
 struct irc_server *
-irc_bot_server_find(const char *);
+irc_bot_server_get(const char *);
 
 void
 irc_bot_server_remove(const char *);
@@ -51,7 +51,7 @@
 irc_bot_plugin_add(struct irc_plugin *);
 
 struct irc_plugin *
-irc_bot_plugin_find(const char *);
+irc_bot_plugin_find(const char *, const char *);
 
 struct irc_plugin *
 irc_bot_plugin_get(const char *);
@@ -60,6 +60,9 @@
 irc_bot_plugin_remove(const char *);
 
 void
+irc_bot_plugin_clear(void);
+
+void
 irc_bot_plugin_loader_add(struct irc_plugin_loader *);
 
 void
@@ -86,4 +89,7 @@
 void
 irc_bot_post(void (*)(void *), void *);
 
+void
+irc_bot_finish(void);
+
 #endif /* !IRCCD_H */
--- a/lib/irccd/util.c	Tue Feb 02 13:51:39 2021 +0100
+++ b/lib/irccd/util.c	Wed Feb 03 11:19:31 2021 +0100
@@ -16,9 +16,11 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <assert.h>
 #include <err.h>
 #include <libgen.h>
 #include <limits.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -139,3 +141,19 @@
 
 	return idx;
 }
+
+char *
+irc_util_printf(char *buf, size_t bufsz, const char *fmt, ...)
+{
+	assert(buf);
+	assert(bufsz);
+	assert(fmt);
+
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsnprintf(buf, bufsz, fmt, ap);
+	va_end(ap);
+
+	return buf;
+}
--- a/lib/irccd/util.h	Tue Feb 02 13:51:39 2021 +0100
+++ b/lib/irccd/util.h	Wed Feb 03 11:19:31 2021 +0100
@@ -53,4 +53,7 @@
 size_t
 irc_util_split(char *, const char **, size_t);
 
+char *
+irc_util_printf(char *, size_t, const char *, ...);
+
 #endif /* !IRCCD_UTIL_H */