2013-05-01 16:03:48 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013 Joris Vink <joris@coders.se>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
|
|
#include "kore.h"
|
|
|
|
|
|
|
|
static void *mod_handle = NULL;
|
2013-05-03 00:04:06 +02:00
|
|
|
static char *mod_name = NULL;
|
2013-05-01 16:03:48 +02:00
|
|
|
static time_t mod_last_mtime = 0;
|
2013-05-30 21:26:39 +02:00
|
|
|
char *kore_module_onload = NULL;
|
2013-05-01 16:03:48 +02:00
|
|
|
|
|
|
|
void
|
|
|
|
kore_module_load(char *module_name)
|
|
|
|
{
|
|
|
|
struct stat st;
|
2013-05-30 21:26:39 +02:00
|
|
|
void (*onload)(void);
|
2013-05-01 16:03:48 +02:00
|
|
|
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("kore_module_load(%s)", module_name);
|
2013-05-01 16:03:48 +02:00
|
|
|
|
|
|
|
if (mod_handle != NULL)
|
|
|
|
fatal("site module already loaded, skipping %s", module_name);
|
|
|
|
|
|
|
|
if (stat(module_name, &st) == -1)
|
|
|
|
fatal("stat(%s): %s", module_name, errno_s);
|
|
|
|
|
|
|
|
mod_last_mtime = st.st_mtime;
|
|
|
|
mod_handle = dlopen(module_name, RTLD_NOW);
|
|
|
|
if (mod_handle == NULL)
|
2013-05-01 17:16:09 +02:00
|
|
|
fatal("%s", dlerror());
|
2013-05-01 16:03:48 +02:00
|
|
|
|
2013-05-29 14:29:46 +02:00
|
|
|
TAILQ_INIT(&domains);
|
2013-05-03 00:04:06 +02:00
|
|
|
mod_name = kore_strdup(module_name);
|
2013-05-30 21:26:39 +02:00
|
|
|
|
|
|
|
if (kore_module_onload != NULL) {
|
|
|
|
onload = dlsym(mod_handle, kore_module_onload);
|
|
|
|
if (onload == NULL)
|
|
|
|
fatal("onload '%s' not present", kore_module_onload);
|
|
|
|
onload();
|
|
|
|
}
|
2013-05-03 00:04:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kore_module_reload(void)
|
|
|
|
{
|
2013-06-24 11:32:45 +02:00
|
|
|
struct kore_domain *dom;
|
2013-05-03 00:04:06 +02:00
|
|
|
struct kore_module_handle *hdlr;
|
2013-05-30 21:26:39 +02:00
|
|
|
void (*onload)(void);
|
2013-05-03 00:04:06 +02:00
|
|
|
|
|
|
|
if (dlclose(mod_handle))
|
|
|
|
fatal("cannot close existing module: %s", dlerror());
|
|
|
|
|
|
|
|
mod_handle = dlopen(mod_name, RTLD_NOW);
|
|
|
|
if (mod_handle == NULL)
|
|
|
|
fatal("kore_module_reload(): %s", dlerror());
|
|
|
|
|
2013-05-29 14:29:46 +02:00
|
|
|
TAILQ_FOREACH(dom, &domains, list) {
|
|
|
|
TAILQ_FOREACH(hdlr, &(dom->handlers), list) {
|
2013-07-07 14:48:32 +02:00
|
|
|
hdlr->errors = 0;
|
2013-05-29 14:29:46 +02:00
|
|
|
hdlr->addr = dlsym(mod_handle, hdlr->func);
|
|
|
|
if (hdlr->func == NULL)
|
|
|
|
fatal("no function '%s' found", hdlr->func);
|
|
|
|
}
|
2013-05-03 00:04:06 +02:00
|
|
|
}
|
|
|
|
|
2013-05-30 21:26:39 +02:00
|
|
|
if (kore_module_onload != NULL) {
|
|
|
|
onload = dlsym(mod_handle, kore_module_onload);
|
|
|
|
if (onload == NULL)
|
|
|
|
fatal("onload '%s' not present", kore_module_onload);
|
|
|
|
onload();
|
|
|
|
}
|
|
|
|
|
2013-06-05 08:56:37 +02:00
|
|
|
kore_log(LOG_NOTICE, "reloaded '%s' module", mod_name);
|
2013-05-01 16:03:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kore_module_loaded(void)
|
|
|
|
{
|
|
|
|
return (mod_handle != NULL ? KORE_RESULT_OK : KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2013-05-02 13:30:13 +02:00
|
|
|
kore_module_handler_new(char *path, char *domain, char *func, int type)
|
2013-05-01 16:03:48 +02:00
|
|
|
{
|
|
|
|
void *addr;
|
2013-06-24 11:32:45 +02:00
|
|
|
struct kore_domain *dom;
|
2013-05-01 16:03:48 +02:00
|
|
|
struct kore_module_handle *hdlr;
|
|
|
|
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("kore_module_handler_new(%s, %s, %s, %d)", path,
|
2013-05-02 13:30:13 +02:00
|
|
|
domain, func, type);
|
2013-05-01 16:03:48 +02:00
|
|
|
|
|
|
|
addr = dlsym(mod_handle, func);
|
|
|
|
if (addr == NULL) {
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("function '%s' not found", func);
|
2013-05-01 16:03:48 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if ((dom = kore_domain_lookup(domain)) == NULL)
|
2013-05-29 14:29:46 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
2013-05-02 13:30:13 +02:00
|
|
|
|
2013-07-13 21:08:55 +02:00
|
|
|
hdlr = kore_malloc(sizeof(*hdlr));
|
2013-07-07 14:48:32 +02:00
|
|
|
hdlr->errors = 0;
|
2013-05-03 00:04:06 +02:00
|
|
|
hdlr->addr = addr;
|
2013-05-01 16:03:48 +02:00
|
|
|
hdlr->type = type;
|
2013-05-29 14:29:46 +02:00
|
|
|
hdlr->path = kore_strdup(path);
|
2013-05-03 00:04:06 +02:00
|
|
|
hdlr->func = kore_strdup(func);
|
2013-05-01 16:03:48 +02:00
|
|
|
|
2013-05-29 14:29:46 +02:00
|
|
|
if (hdlr->type == HANDLER_TYPE_DYNAMIC) {
|
|
|
|
if (regcomp(&(hdlr->rctx), hdlr->path, REG_NOSUB)) {
|
2013-06-27 08:43:07 +02:00
|
|
|
kore_mem_free(hdlr->func);
|
|
|
|
kore_mem_free(hdlr->path);
|
|
|
|
kore_mem_free(hdlr);
|
2013-06-04 16:30:53 +02:00
|
|
|
kore_debug("regcomp() on %s failed", path);
|
2013-05-29 14:29:46 +02:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&(dom->handlers), hdlr, list);
|
2013-05-01 16:03:48 +02:00
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
2013-07-07 14:48:32 +02:00
|
|
|
struct kore_module_handle *
|
2013-05-02 13:30:13 +02:00
|
|
|
kore_module_handler_find(char *domain, char *path)
|
2013-05-01 16:03:48 +02:00
|
|
|
{
|
2013-06-24 11:32:45 +02:00
|
|
|
struct kore_domain *dom;
|
2013-05-01 16:11:10 +02:00
|
|
|
struct kore_module_handle *hdlr;
|
2013-05-02 13:30:13 +02:00
|
|
|
|
2013-06-24 11:32:45 +02:00
|
|
|
if ((dom = kore_domain_lookup(domain)) == NULL)
|
2013-05-29 14:29:46 +02:00
|
|
|
return (NULL);
|
2013-05-01 16:11:10 +02:00
|
|
|
|
2013-05-29 14:29:46 +02:00
|
|
|
TAILQ_FOREACH(hdlr, &(dom->handlers), list) {
|
2013-05-29 13:33:32 +02:00
|
|
|
if (hdlr->type == HANDLER_TYPE_STATIC) {
|
2013-05-29 14:29:46 +02:00
|
|
|
if (!strcmp(hdlr->path, path))
|
2013-07-07 14:48:32 +02:00
|
|
|
return (hdlr);
|
2013-05-29 13:33:32 +02:00
|
|
|
} else {
|
2013-05-29 14:29:46 +02:00
|
|
|
if (!regexec(&(hdlr->rctx), path, 0, NULL, 0))
|
2013-07-07 14:48:32 +02:00
|
|
|
return (hdlr);
|
2013-05-29 13:33:32 +02:00
|
|
|
}
|
2013-05-01 16:11:10 +02:00
|
|
|
}
|
|
|
|
|
2013-05-01 16:03:48 +02:00
|
|
|
return (NULL);
|
|
|
|
}
|