You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
5.6 KiB
C
242 lines
5.6 KiB
C
/*
|
|
* Yet another daemon library especially designed to be used
|
|
* with libsxmp based daemons.
|
|
*
|
|
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
|
|
*
|
|
* libsxmp is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* libsxmp 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.";
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <pthread.h>
|
|
#include <ctype.h>
|
|
#include <dlfcn.h>
|
|
|
|
#include <tdata/usrtc.h>
|
|
#include <sexpr/sexp.h>
|
|
|
|
#include <ydaemon/ydaemon.h>
|
|
|
|
int yd_mod_add(yd_context_t *ctx, const char *name, yd_mod_type_t type)
|
|
{
|
|
yd_mod_t *mod = malloc(sizeof(yd_mod_t));
|
|
usrtc_node_t *node = NULL;
|
|
int r = 0;
|
|
|
|
if(!mod) return ENOMEM;
|
|
else if(!(mod->name = strdup(name))) {
|
|
free(mod);
|
|
return ENOMEM;
|
|
}
|
|
mod->type = type;
|
|
usrtc_node_init(&mod->node, mod);
|
|
|
|
yd_mod_ctx_wrlock(ctx);
|
|
node = usrtc_lookup(ctx->modules, mod->name);
|
|
if(node) r = EEXIST;
|
|
else usrtc_insert(ctx->modules, &mod->node, mod->name);
|
|
yd_mod_ctx_unlock(ctx);
|
|
|
|
return r;
|
|
}
|
|
|
|
int yd_mod_load(yd_context_t *ctx, yd_mod_t *mod)
|
|
{
|
|
char buf[256];
|
|
int r = 0;
|
|
|
|
/* let's try to find it and load */
|
|
if(!mod->pathname || !mod->name) return EINVAL;
|
|
|
|
if(!(mod->dlhandle = dlopen(mod->pathname, RTLD_LAZY|RTLD_GLOBAL)))
|
|
return ENOENT;
|
|
|
|
/* ok now we can resolve all symbols */
|
|
snprintf(buf, 256, "%s_preinit", mod->prefix);
|
|
mod->preinit = dlsym(mod->dlhandle, buf);
|
|
if(!mod->preinit) {
|
|
__einval:
|
|
dlclose(mod->dlhandle);
|
|
return EINVAL;
|
|
}
|
|
|
|
snprintf(buf, 256, "%s_init", mod->prefix);
|
|
if(!(mod->init = dlsym(mod->dlhandle, buf))) goto __einval;
|
|
snprintf(buf, 256, "%s_run", mod->prefix);
|
|
if(!(mod->run = dlsym(mod->dlhandle, buf))) goto __einval;
|
|
snprintf(buf, 256, "%s_shutdown", mod->prefix);
|
|
if(!(mod->shutdown = dlsym(mod->dlhandle, buf))) goto __einval;
|
|
snprintf(buf, 256, "%s_getobject", mod->prefix);
|
|
if(!(mod->getobject = dlsym(mod->dlhandle, buf))) goto __einval;
|
|
|
|
if((r = mod->preinit(ctx))) {
|
|
blub;
|
|
__fail:
|
|
dlclose(mod->dlhandle);
|
|
return r;
|
|
}
|
|
|
|
if(mod->cnfname) {
|
|
blub;
|
|
r = yd_eval_ctx(ctx, (const char *)mod->cnfname);
|
|
if(r) goto __fail;
|
|
}
|
|
|
|
if((r = mod->init(ctx))) goto __fail;
|
|
|
|
if(mod->type == YD_SERVICE_MUX) {
|
|
if((r = mod->run(ctx))) goto __fail;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int yd_mod_get(yd_context_t *ctx, const char *name, yd_mod_t **rmod)
|
|
{
|
|
int r = 0;
|
|
usrtc_node_t *node;
|
|
|
|
yd_mod_ctx_rdlock(ctx);
|
|
node = usrtc_lookup(ctx->modules, name);
|
|
if(!node) r = ENOENT;
|
|
else *rmod = (yd_mod_t *)usrtc_node_getdata(node);
|
|
yd_mod_ctx_unlock(ctx);
|
|
|
|
return r;
|
|
}
|
|
|
|
int yd_mod_run(yd_context_t *ctx, yd_mod_t *mod)
|
|
{
|
|
return mod->run(ctx);
|
|
}
|
|
|
|
int yd_mod_shutdown(yd_context_t *ctx, yd_mod_t *mod)
|
|
{
|
|
return mod->shutdown(ctx);
|
|
}
|
|
|
|
void *yd_mod_getobject(yd_context_t *ctx, yd_mod_t *mod,
|
|
void *priv, const char *name)
|
|
{
|
|
return mod->getobject(priv, name);
|
|
}
|
|
|
|
void *yd_mod_getsym(yd_context_t *ctx, yd_mod_t *mod, const char *name)
|
|
{
|
|
return dlsym(mod->dlhandle, name);
|
|
}
|
|
|
|
/* object store */
|
|
|
|
static long __cmp_cstr(const void *a, const void *b)
|
|
{
|
|
return strcmp((const char *)a, (const char *)b);
|
|
}
|
|
|
|
#define __obs_wrlock(s) pthread_rwlock_wrlock(&((s)->rwlock))
|
|
#define __obs_rdlock(s) pthread_rwlock_rdlock(&((s)->rwlock))
|
|
#define __obs_unlock(s) pthread_rwlock_unlock(&((s)->rwlock))
|
|
#define __obs_tree(s) &((s)->objects)
|
|
|
|
int obj_store_init(obj_store_t *st)
|
|
{
|
|
usrtc_t *tree = &st->objects;
|
|
|
|
if(pthread_rwlock_init(&(st->rwlock), NULL)) return ENOMEM;
|
|
else usrtc_init(tree, USRTC_SPLAY, MAX_OBJECTS, __cmp_cstr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int obj_store_set(obj_store_t *st, const char *nm, void *od)
|
|
{
|
|
usrtc_node_t *node = NULL;
|
|
obj_store_node_t *onode = NULL;
|
|
|
|
__obs_rdlock(st);
|
|
node = usrtc_lookup(__obs_tree(st), nm);
|
|
__obs_unlock(st);
|
|
|
|
if(!node) {
|
|
if(!(onode = malloc(sizeof(obj_store_node_t)))) return ENOMEM;
|
|
else memset(onode, 0, sizeof(obj_store_node_t));
|
|
|
|
if(!(onode->name = strdup(nm))) {
|
|
free(onode);
|
|
return ENOMEM;
|
|
}
|
|
|
|
onode->objdata = od;
|
|
node = &(onode->node);
|
|
usrtc_node_init(node, onode);
|
|
|
|
__obs_wrlock(st);
|
|
usrtc_insert(__obs_tree(st), node, (const void *)onode->name);
|
|
__obs_unlock(st);
|
|
} else {
|
|
onode = (obj_store_node_t *)usrtc_node_getdata(node);
|
|
|
|
__obs_wrlock(st);
|
|
onode->objdata = od;
|
|
__obs_unlock(st);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int obj_store_get(obj_store_t *st, const char *nm, void **rod)
|
|
{
|
|
usrtc_node_t *node = NULL;
|
|
obj_store_node_t *onode = NULL;
|
|
|
|
__obs_rdlock(st);
|
|
node = usrtc_lookup(__obs_tree(st), nm);
|
|
__obs_unlock(st);
|
|
|
|
if(!node) return ENOENT;
|
|
else onode = (obj_store_node_t *)usrtc_node_getdata(node);
|
|
|
|
*rod = onode->objdata;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int obj_store_remove(obj_store_t *st, const char *nm)
|
|
{
|
|
usrtc_node_t *node = NULL;
|
|
obj_store_node_t *onode = NULL;
|
|
|
|
__obs_rdlock(st);
|
|
node = usrtc_lookup(__obs_tree(st), nm);
|
|
__obs_unlock(st);
|
|
|
|
if(!node) return ENOENT;
|
|
else {
|
|
__obs_wrlock(st);
|
|
usrtc_delete(__obs_tree(st), node);
|
|
__obs_unlock(st);
|
|
|
|
onode = (obj_store_node_t *)usrtc_node_getdata(node);
|
|
if(onode->name) free(onode->name);
|
|
free(onode);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|