aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-02-26 16:24:03 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2013-02-26 16:36:32 +0200
commit5b29f3ecc4e2edb172d50b23732a588b7a71ce62 (patch)
tree79b94cbcd5b3a5456ad2a2b2c410886b7e1fb143 /src
parent1eeab02e9de4d54178279b347296e98fd97e2a00 (diff)
downloadwydawca-5b29f3ecc4e2edb172d50b23732a588b7a71ce62.tar.gz
wydawca-5b29f3ecc4e2edb172d50b23732a588b7a71ce62.tar.bz2
Introduce loadable modules.
* .gitignore: Update. * configure.ac: Require libtool Require Grecs tree-api. * Makefile.am: Incorporate libtool * bootstrap: Create m4 if it does not exist. * doc/Makefile.am: Use texi2html * grecs: Upgrade * src/module.c: New file. * src/Makefile.am (wydawca_SOURCES): Add module.c * src/config.c: Switch callbacks to tree-api. Add statements for working with modules: module-load-path, module-prepend-load-path and module in the global scope and module and module-config in notify-event blocks. * src/mail.c (do_notify): Call module_notify if a module is configured. * src/tcpwrap.c: Switch callbacks to tree-api. * src/wydawca.c (main): Load modules. * src/wydawca.h (notification) <modname> <modcfg,modnode>: New members. (module): New struct. (cb_module,modules_load,module_notify): New functions. (module_load_path) (module_prepend_load_path): New globals.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/config.c201
-rw-r--r--src/mail.c5
-rw-r--r--src/module.c236
-rw-r--r--src/tcpwrap.c8
-rw-r--r--src/wydawca.c1
-rw-r--r--src/wydawca.h26
7 files changed, 401 insertions, 82 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2c8f3c4..d7241e9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,2 +37,3 @@ wydawca_SOURCES=\
meta.c\
+ module.c\
net.c\
@@ -69,3 +70,3 @@ inc_DATA = $(PP_SETUP_FILE)
-LDADD=../grecs/src/libgrecs.a @SQLLIB@ @GPGMELIB@ @MAILUTILS_LIBS@
+LDADD=../grecs/src/libgrecs.a @SQLLIB@ @GPGMELIB@ @MAILUTILS_LIBS@ @LIBLTDL@
AM_CPPFLAGS= \
@@ -74,2 +75,3 @@ AM_CPPFLAGS= \
-DLOCALSTATEDIR=\"$(localstatedir)\"\
+ -DWYDAWCA_MODDIR=\"$(WYDAWCA_MODDIR)\"\
-DDEFAULT_VERSION_INCLUDE_DIR=\"$(incdir)\"\
@@ -77,2 +79,2 @@ AM_CPPFLAGS= \
-DDEFAULT_PREPROCESSOR="$(DEFAULT_PREPROCESSOR)"
-
+AM_LDFLAGS=-export-dynamic
diff --git a/src/config.c b/src/config.c
index d6f6a89..b381834 100644
--- a/src/config.c
+++ b/src/config.c
@@ -232,6 +232,6 @@ assert_string_arg(grecs_locus_t *locus,
grecs_value_t *
-get_arg(grecs_locus_t *locus, grecs_value_t *value, unsigned n, int type)
+get_arg(grecs_value_t *value, unsigned n, int type)
{
- if (n >= value->v.arg.c) {
- grecs_error(locus, 0, _("not enough arguments"));
+ if (!value || value->type != GRECS_TYPE_ARRAY || n >= value->v.arg.c) {
+ grecs_error(&value->locus, 0, _("not enough arguments"));
return NULL;
@@ -248,8 +248,9 @@ get_arg(grecs_locus_t *locus, grecs_value_t *value, unsigned n, int type)
static int
-cb_mailer(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_mailer(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
int rc;
-
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+
if (assert_string_arg(locus, cmd, value))
@@ -266,5 +267,4 @@ cb_mailer(enum grecs_callback_command cmd,
static int
-cb_email_address(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_email_address(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -272,2 +272,4 @@ cb_email_address(enum grecs_callback_command cmd,
mu_address_t addr = NULL;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
struct grecs_list_entry *ep;
@@ -317,5 +319,4 @@ cb_email_address(enum grecs_callback_command cmd,
static int
-cb_interval(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_interval(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -324,2 +325,4 @@ cb_interval(enum grecs_callback_command cmd,
const char *endp;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -342,6 +345,8 @@ static int
cb_absolute_name(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+ grecs_node_t *node,
+ void *varptr, void *cb_data)
{
char *word;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -362,4 +367,4 @@ static int
cb_set_umask(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+ grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -367,2 +372,4 @@ cb_set_umask(enum grecs_callback_command cmd,
mode_t m;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -476,7 +483,6 @@ parse_statmask(grecs_locus_t *loc, grecs_value_t *val, unsigned long *pmask)
static int
-cb_statistics(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_statistics(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
- return parse_statmask(locus, value, varptr);
+ return parse_statmask(&node->locus, node->v.value, varptr);
}
@@ -484,5 +490,4 @@ cb_statistics(enum grecs_callback_command cmd,
static int
-cb_sql_host(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_sql_host(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -490,2 +495,4 @@ cb_sql_host(enum grecs_callback_command cmd,
char *p;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -526,5 +533,4 @@ cb_sql_host(enum grecs_callback_command cmd,
static int
-cb_sql(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_sql(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -532,2 +538,4 @@ cb_sql(enum grecs_callback_command cmd,
void **pdata = cb_data;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -588,6 +596,8 @@ static struct grecs_keyword sql_kw[] = {
static int
-cb_syslog_facility(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_syslog_facility(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+
if (assert_string_arg(locus, cmd, value))
@@ -603,7 +613,8 @@ cb_syslog_facility(enum grecs_callback_command cmd,
static int
-cb_define_message(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_define_message(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
const char *ident;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -686,7 +697,8 @@ get_backup_version(grecs_locus_t *locus, const char *ctx, const char *version)
static int
-cb_backup(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_backup(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
enum backup_type *ptype = varptr;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -712,5 +724,4 @@ static struct grecs_keyword archive_kw[] = {
static int
-cb_archive(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_archive(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -718,2 +729,4 @@ cb_archive(enum grecs_callback_command cmd,
void **pdata = cb_data;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -785,7 +798,8 @@ static struct grecs_keyword mail_statistics_kw[] = {
static int
-cb_event(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_event(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
enum notification_event *pev = varptr;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -798,7 +812,8 @@ cb_event(enum grecs_callback_command cmd,
static int
-cb_recipient(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_recipient(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
enum notification_target *tgt = varptr;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -828,2 +843,9 @@ static struct grecs_keyword notify_event_kw[] = {
NULL, offsetof(struct notification, sign_keys) },
+ { "module", N_("name"),
+ N_("Name of the module to invoke on event"),
+ grecs_type_string, GRECS_DFLT,
+ NULL, offsetof(struct notification, modname) },
+ { "module-config", NULL,
+ N_("Module-specific configuration data"),
+ grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL, NULL },
{ NULL }
@@ -832,5 +854,4 @@ static struct grecs_keyword notify_event_kw[] = {
static int
-cb_notify_event(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_notify_event(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -838,2 +859,3 @@ cb_notify_event(enum grecs_callback_command cmd,
void **pdata = cb_data;
+ grecs_locus_t *locus = &node->locus;
@@ -842,2 +864,3 @@ cb_notify_event(enum grecs_callback_command cmd,
ntf = grecs_zalloc(sizeof(*ntf));
+ ntf->modnode = grecs_find_node(node->down, "module-config");
*pdata = ntf;
@@ -847,3 +870,3 @@ cb_notify_event(enum grecs_callback_command cmd,
ntf = *pdata;
- if (!ntf->msg)
+ if (!ntf->msg && !ntf->modname)
grecs_error(locus, 0, _("missing message definition"));
@@ -878,7 +901,8 @@ string_to_dictionary_type(const char *str)
static int
-cb_dictionary_type(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_dictionary_type(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
enum dictionary_type *ptype = varptr;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -894,5 +918,4 @@ cb_dictionary_type(enum grecs_callback_command cmd,
static int
-cb_dictionary_params(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_dictionary_params(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -900,2 +923,4 @@ cb_dictionary_params(enum grecs_callback_command cmd,
size_t size;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -970,5 +995,4 @@ string_to_dictionary_id(grecs_locus_t *locus,
static int
-cb_dictionary(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_dictionary(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -977,2 +1001,4 @@ cb_dictionary(enum grecs_callback_command cmd,
enum dictionary_id id;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -1025,5 +1051,4 @@ cb_dictionary(enum grecs_callback_command cmd,
static int
-cb_url(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_url(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -1031,2 +1056,4 @@ cb_url(enum grecs_callback_command cmd,
int rc;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -1081,3 +1108,2 @@ static struct grecs_keyword spool_kw[] = {
NULL, offsetof(struct spool, check_script) },
-
{ NULL }
@@ -1086,5 +1112,4 @@ static struct grecs_keyword spool_kw[] = {
static int
-cb_spool(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_spool(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
@@ -1093,2 +1118,4 @@ cb_spool(enum grecs_callback_command cmd,
int rc, ec, i;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -1167,7 +1194,8 @@ cb_spool(enum grecs_callback_command cmd,
static int
-cb_user(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_user(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
struct passwd *pw;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -1189,6 +1217,8 @@ cb_user(enum grecs_callback_command cmd,
static int
-cb_supp_groups(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_supp_groups(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+
if (cmd != grecs_callback_set_value) {
@@ -1246,6 +1276,8 @@ static struct grecs_keyword locking_kw[] = {
static int
-cb_locking(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_locking(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+
if (cmd == grecs_callback_set_value) {
@@ -1263,7 +1295,8 @@ cb_locking(enum grecs_callback_command cmd,
static int
-cb_upload_version(enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+cb_upload_version(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
unsigned *pversion = varptr, n;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
@@ -1302,2 +1335,16 @@ static struct grecs_keyword wydawca_kw[] = {
+ { "module-prepend-load-path", N_("path"),
+ N_("List of directories searched for modules prior to "
+ "the default module directory"),
+ grecs_type_string, GRECS_LIST,
+ &module_prepend_load_path },
+ { "module-load-path", N_("path"),
+ N_("List of directories searched for database modules."),
+ grecs_type_string, GRECS_LIST,
+ &module_load_path },
+
+ { "module", N_("name: string> <path: string"),
+ N_("Load the specified module"),
+ grecs_type_string, GRECS_MULT, NULL, 0, cb_module },
+
{ "inotify", NULL, N_("Enable or disable inotify support"),
diff --git a/src/mail.c b/src/mail.c
index 2b64501..dd16510 100644
--- a/src/mail.c
+++ b/src/mail.c
@@ -511,2 +511,7 @@ do_notify(struct file_triplet *trp, enum notification_event ev,
+ if (ntf->modname) {
+ module_notify(ntf->modname, ntf->modcfg, ev, trp);
+ return;
+ }
+
switch (ntf->tgt) {
diff --git a/src/module.c b/src/module.c
new file mode 100644
index 0000000..41bbb39
--- /dev/null
+++ b/src/module.c
@@ -0,0 +1,236 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007-2012 Sergey Poznyakoff
+
+ Wydawca is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ Wydawca is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+#include <ltdl.h>
+
+static struct grecs_symtab *modtab;
+struct grecs_list *module_load_path, *module_prepend_load_path;
+
+static void
+modfree(void *p)
+{
+ struct module *mod = p;
+ free(mod->locus.beg.file);
+ free(mod->locus.end.file);
+ free(mod->path);
+ free(mod->name);
+ free(mod);
+}
+
+static struct module *
+modinstall(const char *name, const char *path, grecs_locus_t *loc)
+{
+ struct module key;
+ struct module *ent;
+ int install = 1;
+
+ if (!modtab) {
+ modtab = grecs_symtab_create(sizeof(struct module),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ modfree);
+ if (!modtab)
+ grecs_alloc_die();
+ }
+
+ key.name = (char*) name;
+ ent = grecs_symtab_lookup_or_install(modtab, &key, &install);
+ if (!ent)
+ grecs_alloc_die();
+ if (install == 0) {
+ grecs_error(loc, 0, _("module %s already declared"), name);
+ grecs_error(&ent->locus, 0, _("previously declared here"));
+ return NULL;
+ }
+ ent->path = grecs_strdup(path);
+ ent->locus.beg.file = grecs_strdup(loc->beg.file);
+ ent->locus.beg.line = loc->beg.line;
+ ent->locus.beg.col = loc->beg.col;
+ ent->locus.end.file = grecs_strdup(loc->end.file);
+ ent->locus.end.line = loc->end.line;
+ ent->locus.end.col = loc->end.col;
+ return ent;
+}
+
+static struct module *
+modlookup(const char *name)
+{
+ struct module key;
+
+ if (!modtab)
+ return NULL;
+
+ key.name = (char*) name;
+ return grecs_symtab_lookup_or_install(modtab, &key, NULL);
+}
+
+int
+cb_module(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
+{
+ grecs_value_t *name;
+ grecs_value_t *path;
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+
+ if (cmd != grecs_callback_set_value) {
+ grecs_error(locus, 0, _("Unexpected block statement"));
+ return 1;
+ }
+
+ if (!(name = get_arg(value, 0, GRECS_TYPE_STRING)))
+ return 1;
+ if (!(path = get_arg(value, 1, GRECS_TYPE_STRING)))
+ return 1;
+
+ modinstall(name->v.string, path->v.string, locus);
+
+ return 0;
+};
+
+static void *
+resolve_sym(struct module *mod, const char *name)
+{
+ void *sym = lt_dlsym(mod->handle, name);
+ if (!sym) {
+ grecs_error(&mod->locus, 0,
+ _("module \"%s\" does not define symbol \"%s\""),
+ mod->name, name);
+ }
+ return sym;
+}
+
+static int
+modload(void *sym, void *data)
+{
+ struct module *mod = sym;
+ lt_dlhandle handle = NULL;
+ lt_dladvise advise = data;
+
+ if (mod->handle) {
+ grecs_error(&mod->locus, 0, _("already loaded"));
+ return 0;
+ }
+
+ handle = lt_dlopenadvise(mod->path, advise);
+
+ if (!handle) {
+ grecs_error(&mod->locus, 0,
+ _("cannot load module %s: %s"), mod->path,
+ lt_dlerror());
+ return 1;
+ }
+ mod->handle = handle;
+ mod->config = resolve_sym(mod, "config");
+ mod->notify = resolve_sym(mod, "notify");
+
+ return 0;
+}
+
+static int
+spoolmodcfg(struct spool *spool, void *unused)
+{
+ struct notification *np;
+
+ for (np = spool->notification; np; np = np->next) {
+ if (np->modname) {
+ struct module *mod = modlookup(np->modname);
+ if (!mod) {
+ logmsg(LOG_ERR, "spool %s: no such module: %s",
+ spool->tag, np->modname);
+ return 1;
+ }
+ if (mod->config) {
+ np->modcfg = mod->config(np->modnode);
+ if (!np->modcfg) {
+ logmsg(LOG_ERR,
+ "spool %s: failed to configure "
+ "module \"%s\"",
+ spool->tag, np->modname);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void
+modules_load()
+{
+ lt_dladvise advise = NULL;
+ struct grecs_list_entry *ep;
+
+ if (lt_dlinit()) {
+ logmsg(LOG_ERR, _("failed to initialize libtool"));
+ return;
+ }
+
+ /* Prepare load path */
+ if (module_prepend_load_path)
+ for (ep = module_prepend_load_path->head; ep; ep = ep->next)
+ lt_dladdsearchdir(ep->data);
+ lt_dladdsearchdir(WYDAWCA_MODDIR);
+ if (module_load_path)
+ for (ep = module_load_path->head; ep; ep = ep->next)
+ lt_dladdsearchdir(ep->data);
+
+
+ if (lt_dladvise_init(&advise))
+ logmsg(LOG_ERR, "lt_dladvise_init: %s", lt_dlerror());
+ else {
+ if (lt_dladvise_ext(&advise))
+ logmsg(LOG_ERR, "lt_dladvise_ext: %s", lt_dlerror());
+ if (lt_dladvise_global(&advise))
+ logmsg(LOG_ERR, "lt_dladvise_global: %s",
+ lt_dlerror());
+ }
+ if (grecs_symtab_enumerate(modtab, modload, NULL)) {
+ logmsg(LOG_CRIT, _("some modules failed to load, exiting"));
+ exit(EX_UNAVAILABLE);
+ }
+ lt_dladvise_destroy(&advise);
+
+ if (for_each_spool(spoolmodcfg, NULL)) {
+ logmsg(LOG_CRIT,
+ _("some modules failed to configure, exiting"));
+ exit(EX_UNAVAILABLE);
+ }
+}
+
+static char *
+getfn(void *trp, const char *fmt)
+{
+ return triplet_expand_param(fmt, trp);
+}
+
+void
+module_notify(const char *name, void *modcfg,
+ enum notification_event ev, struct file_triplet *trp)
+{
+ struct module *mod = modlookup(name);
+
+ if (!mod) {
+ logmsg(LOG_ERR, "no such module: %s", name);
+ return;
+ }
+ if (mod->notify)
+ mod->notify(modcfg, ev, getfn, trp);
+}
+
diff --git a/src/tcpwrap.c b/src/tcpwrap.c
index 907bc20..4a3e59b 100644
--- a/src/tcpwrap.c
+++ b/src/tcpwrap.c
@@ -28,6 +28,8 @@ int allow_severity = LOG_INFO;
static int
-cb_syslog_priority(enum grecs_callback_command cmd,
- grecs_locus_t * locus,
- void *varptr, grecs_value_t * value, void *cb_data)
+cb_syslog_priority(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data)
{
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+
if (assert_string_arg(locus, cmd, value))
diff --git a/src/wydawca.c b/src/wydawca.c
index 42fcea9..f6767b8 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -360,2 +360,3 @@ main(int argc, char **argv)
config_finish(tree);
+ modules_load();
grecs_tree_free(tree);
diff --git a/src/wydawca.h b/src/wydawca.h
index 9e4b2be..8e2f155 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -293,2 +293,5 @@ struct notification {
const char *msg;
+ char *modname;
+ void *modcfg;
+ grecs_node_t *modnode;
};
@@ -318,2 +321,23 @@ const char *expand_email_owner(struct metadef *def, void *data);
+/* Modules */
+typedef char *(*format_fn)(void *, const char *);
+
+struct module {
+ char *name;
+ char *path;
+ grecs_locus_t locus;
+ void *handle;
+ void *(*config) (grecs_node_t *);
+ int (*notify) (void *, int, format_fn, void *);
+};
+
+int cb_module(enum grecs_callback_command cmd, grecs_node_t *node,
+ void *varptr, void *cb_data);
+void modules_load(void);
+
+extern struct grecs_list *module_load_path, *module_prepend_load_path;
+void module_notify(const char *name, void *modcfg,
+ enum notification_event ev, struct file_triplet *tpl);
+
+
/* Global variables */
@@ -485,2 +509,4 @@ int assert_string_arg(grecs_locus_t *, enum grecs_callback_command,
const grecs_value_t *);
+grecs_value_t *get_arg(grecs_value_t *value, unsigned n, int type);
+

Return to:

Send suggestions and report system problems to the System administrator.