#include "jabberd.h"
typedef void (*load_init)(instance id, xmlnode x);
xmlnode load__cache = NULL;
int load_ref__count = 0;
#ifdef STATIC
void *jsm();
void *pthsock_client();
void *xdb_file();
void *dnsrv();
void *dialback();
void *mod_admin();
void *mod_agents();
void *mod_browse();
void *mod_filter();
void *mod_echo();
void *mod_groups();
void *mod_roster();
void *mod_time();
void *mod_vcard();
void *mod_version();
void *mod_announce();
void *mod_private();
void *mod_presence();
void *mod_auth_plain();
void *mod_auth_digest();
void *mod_auth_0k();
void *mod_register();
void *mod_log();
void *mod_xml();
void *mod_last();
void *mod_offline();
void *load_symbol(char *func, char *file)
{
if(j_strcmp(func,"jsm") == 0) return (void (*)(instance,xmlnode))jsm;
if(j_strcmp(func,"pthsock_client") == 0) return (void (*)(instance,xmlnode))pthsock_client;
if(j_strcmp(func,"xdb_file") == 0) return (void (*)(instance,xmlnode))xdb_file;
if(j_strcmp(func,"dnsrv") == 0) return (void (*)(instance,xmlnode))dnsrv;
if(j_strcmp(func,"dialback") == 0) return (void (*)(instance,xmlnode))dialback;
if(j_strcmp(func,"mod_browse") == 0) return (void (*)(void))mod_browse;
if(j_strcmp(func,"mod_echo") == 0) return (void (*)(void))mod_echo;
if(j_strcmp(func,"mod_groups") == 0) return (void (*)(void))mod_groups;
if(j_strcmp(func,"mod_roster") == 0) return (void (*)(void))mod_roster;
if(j_strcmp(func,"mod_time") == 0) return (void (*)(void))mod_time;
if(j_strcmp(func,"mod_vcard") == 0) return (void (*)(void))mod_vcard;
if(j_strcmp(func,"mod_version") == 0) return (void (*)(void))mod_version;
if(j_strcmp(func,"mod_announce") == 0) return (void (*)(void))mod_announce;
if(j_strcmp(func,"mod_agents") == 0) return (void (*)(void))mod_agents;
if(j_strcmp(func,"mod_admin") == 0) return (void (*)(void))mod_admin;
if(j_strcmp(func,"mod_filter") == 0) return (void (*)(void))mod_filter;
if(j_strcmp(func,"mod_presence") == 0) return (void (*)(void))mod_presence;
if(j_strcmp(func,"mod_auth_plain") == 0) return (void (*)(void))mod_auth_plain;
if(j_strcmp(func,"mod_auth_digest") == 0) return (void (*)(void))mod_auth_digest;
if(j_strcmp(func,"mod_auth_crammd5digest") == 0) return (void (*)(void))mod_auth_crammd5digest;
if(j_strcmp(func,"mod_auth_0k") == 0) return (void (*)(void))mod_auth_0k;
if(j_strcmp(func,"mod_register") == 0) return (void (*)(void))mod_register;
if(j_strcmp(func,"mod_log") == 0) return (void (*)(void))mod_log;
if(j_strcmp(func,"mod_xml") == 0) return (void (*)(void))mod_xml;
if(j_strcmp(func,"mod_last") == 0) return (void (*)(void))mod_last;
if(j_strcmp(func,"mod_offline") == 0) return (void (*)(void))mod_offline;
return NULL;
}
#else
#include <dlfcn.h>
void *load_loader(char *file)
{
void *so_h;
const char *dlerr;
char message[MAX_LOG_SIZE];
so_h = dlopen(file,RTLD_LAZY);
if(!so_h)
{
dlerr = dlerror();
snprintf(message, MAX_LOG_SIZE, "Loading %s failed: '%s'\n",file,dlerr);
fprintf(stderr, "%s\n", message);
return NULL;
}
xmlnode_put_vattrib(load__cache, file, so_h);
return so_h;
}
void *load_symbol(char *func, char *file)
{
void (*func_h)(instance i, void *arg);
void *so_h;
const char *dlerr;
char *func2;
char message[MAX_LOG_SIZE];
if(func == NULL || file == NULL)
return NULL;
if((so_h = xmlnode_get_vattrib(load__cache, file)) == NULL && (so_h = load_loader(file)) == NULL)
return NULL;
func_h = dlsym(so_h, func);
dlerr = dlerror();
if(dlerr != NULL)
{
snprintf(message, MAX_LOG_SIZE, "Executing %s() in %s failed: '%s'\n",func,file,dlerr);
func2 = malloc(strlen(func) + 2);
func2[0] = '_';
func2[1] = '\0';
strcat(func2,func);
func_h = dlsym(so_h, func2);
free(func2);
if(dlerror() != NULL)
{
fprintf(stderr, "%s\n", message);
return NULL;
}
}
return func_h;
}
#endif
void load_shutdown(void *arg)
{
load_ref__count--;
if(load_ref__count != 0)
return;
xmlnode_free(load__cache);
load__cache = NULL;
}
result load_config(instance id, xmlnode x, void *arg)
{
xmlnode so;
char *init = xmlnode_get_attrib(x,"main");
void *f;
int flag = 0;
if(load__cache == NULL)
load__cache = xmlnode_new_tag("so_cache");
if(id != NULL)
{
load_ref__count++;
pool_cleanup(id->p, load_shutdown, NULL);
f = xmlnode_get_vattrib(x, init);
((load_init)f)(id, x);
return r_PASS;
}
log_debug(ZONE,"dynamic loader processing configuration %s\n",xmlnode2str(x));
for(so = xmlnode_get_firstchild(x); so != NULL; so = xmlnode_get_nextsibling(so))
{
if(xmlnode_get_type(so) != NTYPE_TAG) continue;
if(init == NULL && flag)
return r_ERR;
f = load_symbol(xmlnode_get_name(so), xmlnode_get_data(so));
if(f == NULL)
return r_ERR;
xmlnode_put_vattrib(x, xmlnode_get_name(so), f);
flag = 1;
if(init == NULL)
xmlnode_put_attrib(x,"main",xmlnode_get_name(so));
}
if(!flag) return r_ERR;
return r_PASS;
}
void dynamic_init(void)
{
log_debug(ZONE,"dynamic component loader initializing...\n");
register_config("load",load_config,NULL);
}