diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/config.c | 201 | ||||
-rw-r--r-- | src/mail.c | 5 | ||||
-rw-r--r-- | src/module.c | 236 | ||||
-rw-r--r-- | src/tcpwrap.c | 8 | ||||
-rw-r--r-- | src/wydawca.c | 1 | ||||
-rw-r--r-- | src/wydawca.h | 26 |
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 @@ -35,6 +35,7 @@ wydawca_SOURCES=\ job.c\ lock.c\ meta.c\ + module.c\ net.c\ pidfile.c\ process.c\ @@ -67,12 +68,13 @@ SUFFIXES=.opt .c .h incdir=$(pkgdatadir)/$(VERSION)/include 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= \ -I$(top_srcdir)/grecs/src/ @MAILUTILS_INCLUDES@\ -DSYSCONFDIR=\"$(sysconfdir)\"\ -DLOCALSTATEDIR=\"$(localstatedir)\"\ + -DWYDAWCA_MODDIR=\"$(WYDAWCA_MODDIR)\"\ -DDEFAULT_VERSION_INCLUDE_DIR=\"$(incdir)\"\ -DDEFAULT_INCLUDE_DIR=\"$(pkgdatadir)/include\"\ -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 @@ -230,10 +230,10 @@ 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; } value = value->v.arg.v[n]; @@ -246,12 +246,13 @@ 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)) return 1; rc = mu_mailer_create(&mailer, value->v.string); @@ -264,12 +265,13 @@ 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) { int rc = 1; mu_address_t addr = NULL; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; struct grecs_list_entry *ep; switch (value->type) { @@ -315,13 +317,14 @@ 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) { int rc; time_t interval; const char *endp; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; /* FIXME 1: Support arrays */ if (assert_string_arg(locus, cmd, value)) @@ -340,10 +343,12 @@ cb_interval(enum grecs_callback_command cmd, 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; /* FIXME 1: Support arrays */ if (assert_string_arg(locus, cmd, value)) @@ -360,11 +365,13 @@ cb_absolute_name(enum grecs_callback_command cmd, 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) { char *p; mode_t m; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; if (assert_string_arg(locus, cmd, value)) return 1; @@ -474,20 +481,20 @@ 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); } 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) { struct sqlconn *pconn = varptr; char *p; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; if (assert_string_arg(locus, cmd, value)) return 1; @@ -524,12 +531,13 @@ 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) { struct sqlconn *pconn; void **pdata = cb_data; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; switch (cmd) { case grecs_callback_section_begin: @@ -586,10 +594,12 @@ 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)) return 1; @@ -601,11 +611,12 @@ 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; if (cmd != grecs_callback_set_value) { grecs_error(locus, 0, _("Unexpected block statement")); @@ -684,11 +695,12 @@ 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; if (assert_string_arg(locus, cmd, value)) return 1; @@ -710,12 +722,13 @@ 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) { struct archive_descr *arch = varptr; void **pdata = cb_data; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; switch (cmd) { case grecs_callback_section_begin: @@ -783,11 +796,12 @@ 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; if (assert_string_arg(locus, cmd, value)) return 1; @@ -796,11 +810,12 @@ 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; if (assert_string_arg(locus, cmd, value)) return 1; @@ -826,26 +841,34 @@ static struct grecs_keyword notify_event_kw[] = { N_("Sign message with this key"), grecs_type_string, GRECS_DFLT, 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 } }; 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) { struct notification *ntf; void **pdata = cb_data; + grecs_locus_t *locus = &node->locus; switch (cmd) { case grecs_callback_section_begin: ntf = grecs_zalloc(sizeof(*ntf)); + ntf->modnode = grecs_find_node(node->down, "module-config"); *pdata = ntf; break; case grecs_callback_section_end: ntf = *pdata; - if (!ntf->msg) + if (!ntf->msg && !ntf->modname) grecs_error(locus, 0, _("missing message definition")); else { struct notification **p = @@ -876,11 +899,12 @@ 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; if (assert_string_arg(locus, cmd, value)) return 1; @@ -892,12 +916,13 @@ 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) { struct dictionary *meth = varptr; size_t size; + 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")); @@ -968,13 +993,14 @@ 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) { struct dictionary **pmeth, *meth; void **pdata = cb_data; enum dictionary_id id; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; switch (cmd) { case grecs_callback_section_begin: @@ -1023,12 +1049,13 @@ 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) { mu_url_t *purl = varptr, url; int rc; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; if (assert_string_arg(locus, cmd, value)) return 1; @@ -1079,18 +1106,18 @@ static struct grecs_keyword spool_kw[] = { { "check-script", NULL, N_("A /bin/sh script to verify the tarball"), grecs_type_string, GRECS_DFLT, NULL, offsetof(struct spool, check_script) }, - { NULL } }; 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) { struct spool *spool; void **pdata = cb_data; int rc, ec, i; + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; switch (cmd) { case grecs_callback_section_begin: @@ -1165,11 +1192,12 @@ 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; if (assert_string_arg(locus, cmd, value)) return 1; @@ -1187,10 +1215,12 @@ 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) { grecs_error(locus, 0, _("Unexpected block statement")); return 1; @@ -1244,10 +1274,12 @@ 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) { if (!value || value->type != GRECS_TYPE_STRING) { grecs_error(value ? &value->locus : locus, 0, @@ -1261,11 +1293,12 @@ 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; if (assert_string_arg(locus, cmd, value)) return 1; @@ -1300,6 +1333,20 @@ static struct grecs_keyword wydawca_kw[] = { { "pidfile", N_("file"), N_("Set pid file name"), grecs_type_string, GRECS_DFLT, &pidfile }, + { "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"), grecs_type_bool, GRECS_DFLT, &inotify_enable }, @@ -509,6 +509,11 @@ do_notify(struct file_triplet *trp, enum notification_event ev, const char *errp; const char *msg; + if (ntf->modname) { + module_notify(ntf->modname, ntf->modcfg, ev, trp); + return; + } + switch (ntf->tgt) { case notify_read: rcpt = NULL; 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 @@ -26,10 +26,12 @@ int deny_severity = LOG_INFO; 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)) return 1; diff --git a/src/wydawca.c b/src/wydawca.c index 42fcea9..f6767b8 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -358,6 +358,7 @@ main(int argc, char **argv) exit(EX_CONFIG); config_finish(tree); + modules_load(); grecs_tree_free(tree); if (lint_mode) diff --git a/src/wydawca.h b/src/wydawca.h index 9e4b2be..8e2f155 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -291,6 +291,9 @@ struct notification { enum notification_target tgt; const char *sign_keys; const char *msg; + char *modname; + void *modcfg; + grecs_node_t *modnode; }; void register_message_template(const char *name, const char *text); @@ -316,6 +319,27 @@ void meta_free(struct metadef *def); const char *expand_email_admin(struct metadef *def, void *data); 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 */ extern char *program_name; extern uid_t wydawca_uid; @@ -483,6 +507,8 @@ void config_finish(struct grecs_node *); void config_help(void); 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); + /* vtab.c */ int url_to_vtab(mu_url_t url, struct virt_tab *vtab); |