/* * Yet another daemon library especially designed to be used * with libsxmp based daemons. * * (c) Alexander Vdolainen 2016 * * 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 ."; * */ #include #include #include #include #include #include #include #include #include #include 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; }