This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats/dl.c
fishwaldo ace89c422f Major Updates. Linked List libary now used in Main Code. Should fix a lot of
Memory Leaks... Better flexibility for Modules... Lots of Updates, long long
overdue -- Been travelling for 5 weeks :)
2000-06-10 08:48:54 +00:00

714 lines
18 KiB
C

/*
* dl.c
* dynamic runtime library loading routines
*/
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dl.h"
#include "stats.h"
#include "config.h"
LD_Path *ld_path_list;
void __init_mod_list() {
int i;
Mod_Timer *t, *Tprev;
Mod_User *u, *Uprev;
Sock_List *s, *Sprev;
DLL_Return ExitCode;
segv_loc("__init_mod_list");
/* Create the Modules Linked List */
if (DLl_CreateList(&LL_Mods) == NULL) {
log("Error, Could not Create ModList");
exit(-1);
}
if ((ExitCode = DLL_InitializeList(LL_Mods, sizeof(Module))) != DLL_NORMAL) {
if (ExitCode == DLL_ZERO_INFO) log("Error, Module Structure is 0");
if (ExitCode == DLL_NULL_LIST) log("Error, Module Structure is NULL");
exit(-1);
}
CurMod = smalloc(sizeof(Module));
/* Create the Events List */
if (DLl_CreateList(&LL_Mods_Evnts) == NULL) {
log("Error, Could not Create ModListEvnts");
exit(-1);
}
if ((ExitCode = DLL_InitializeList(LL_Mods, sizeof(EventFnList))) != DLL_NORMAL) {
if (ExitCode == DLL_ZERO_INFO) log("Error, Module Structure is 0");
if (ExitCode == DLL_NULL_LIST) log("Error, Module Structure is NULL");
exit(-1);
}
CurModEvnts = smalloc(sizeof(EventFnList));
/* Create the Functions list */
if (DLl_CreateList(&LL_Mods_Fncts) == NULL) {
log("Error, Could not Create ModListFncts");
exit(-1);
}
if ((ExitCode = DLL_InitializeList(LL_Mods, sizeof(Functions))) != DLL_NORMAL) {
if (ExitCode == DLL_ZERO_INFO) log("Error, Module Structure is 0");
if (ExitCode == DLL_NULL_LIST) log("Error, Module Structure is NULL");
exit(-1);
}
CurModFncts = smalloc(sizeof(Functions));
/* Path is Simple, so Leave it as it is */
ld_path_list = (LD_Path *)malloc(sizeof(LD_Path));
bzero(ld_path_list, sizeof(LD_Path));
ld_path_list->prev = NULL;
ld_path_list->next = NULL;
/* Bot lists are Linked Lists as well */
for (i = 0; i < B_TABLE_SIZE; i++) {
u = module_bot_lists[i];
while (u) {
Uprev = u->next;
free(u);
u = Uprev;
}
module_bot_lists[i] = NULL;
}
bzero((char *)module_bot_lists, sizeof(module_bot_lists));
/* As are Timer Lists */
for (i = 0; i < T_TABLE_SIZE; i++) {
t = module_timer_lists[i];
while (t) {
Tprev = t->next;
free(t);
t = Tprev;
}
module_timer_lists[i] = NULL;
}
bzero((char *)module_timer_lists, sizeof(module_timer_lists));
/* Socket Lists are also Linked Lists */
for (i = 0; i < MAX_SOCKS; i++) {
s = Socket_lists[i];
while (s) {
Sprev = s->next;
free(s);
s = Sprev;
}
Socket_lists[i] = NULL;
}
bzero((char *)Socket_lists, sizeof(Socket_lists));
};
int add_ld_path(char *path) {
LD_Path *path_ent, *list;
segv_loc("add_ld_path");
path_ent = (LD_Path *)malloc(sizeof(LD_Path));
bzero(path_ent, sizeof(LD_Path));
strncpy(path_ent->dl_path, path, 100);
list = ld_path_list;
while (list->next != NULL) list = list->next;
list->next = path_ent;
path_ent->prev = list;
return 0;
}
static void add_timer_to_hash_table(char *timer_name, Mod_Timer *t) {
t->hash = HASH(timer_name, T_TABLE_SIZE);
t->next = module_timer_lists[t->hash];
module_timer_lists[t->hash] = (void *)t;
}
static void del_timer_from_hash_table(char *timer_name, Mod_Timer *t) {
Mod_Timer *tmp, *prev = NULL;
for (tmp = module_timer_lists[t->hash]; tmp; tmp = tmp->next) {
if (tmp == t) {
if (prev)
prev->next = tmp->next;
else
module_timer_lists[t->hash] = tmp->next;
tmp->next = NULL;
return;
}
prev = tmp;
}
}
static Mod_Timer *new_timer(char *timer_name)
{
Mod_Timer *t;
#ifdef DEBUG
log("New Timer: %s", timer_name);
#endif
t = smalloc(sizeof(Mod_Timer));
if (!timer_name)
timer_name="";
t->timername = timer_name;
add_timer_to_hash_table(timer_name, t);
return t;
}
Mod_Timer *findtimer(char *timer_name) {
Mod_Timer *t;
t = module_timer_lists[HASH(timer_name, T_TABLE_SIZE)];
while (t && strcasecmp(t->timername, timer_name) != 0)
t = t->next;
return t;
}
int add_mod_timer(char *func_name, char *timer_name, char *mod_name, int interval) {
Mod_Timer *Mod_timer_list;
Module *list_ptr;
segv_loc("add_mod_timer");
Mod_timer_list = new_timer(timer_name);
Mod_timer_list->interval = interval;
Mod_timer_list->lastrun = time(NULL);
Mod_timer_list->modname = sstrdup(mod_name);
list_ptr = module_list->next;
while (list_ptr != NULL) {
if (!strcasecmp(list_ptr->info->module_name, mod_name)) {
/* Check to see if the function exists */
if (dlsym(list_ptr->dl_handle, func_name) == NULL) {
log("Oh Oh, the Timer function doesn't exist");
del_mod_timer(Mod_timer_list->timername);
return -1;
}
Mod_timer_list->function = dlsym(list_ptr->dl_handle, func_name);
#ifdef DEBUG
log("Registered Module %s with timer for Function %s", list_ptr->info->module_name, func_name);
#endif
return 1;
}
list_ptr = list_ptr->next;
}
return 0;
}
int del_mod_timer(char *timer_name) {
Mod_Timer *list;
segv_loc("del_mod_timer");
list = findtimer(timer_name);
if (list) {
#ifdef DEBUG
log("Unregistered Timer function %s from Module %s", timer_name, list->modname);
#endif
del_timer_from_hash_table(timer_name, list);
free(list);
return 1;
}
return -1;
}
void list_module_timer(User *u) {
Mod_Timer *mod_ptr = NULL;
register int j;
segv_loc("list_module_timer");
privmsg(u->nick,s_Services,"Module timer List:");
for (j = 0; j < T_TABLE_SIZE; j++) {
for (mod_ptr = module_timer_lists[j]; mod_ptr; mod_ptr = mod_ptr->next) {
privmsg(u->nick,s_Services,"%s:--------------------------------",mod_ptr->modname);
privmsg(u->nick,s_Services,"Module Timer Name: %s",mod_ptr->timername);
privmsg(u->nick,s_Services,"Module Interval: %d",mod_ptr->interval);
privmsg(u->nick,s_Services,"Time till next Run: %d", mod_ptr->interval - (time(NULL) - mod_ptr->lastrun));
}
}
privmsg(u->nick,s_Services,"End of Module timer List");
free(mod_ptr);
}
static void add_sock_to_hash_table(char *sockname, Sock_List *s) {
s->hash = HASH(sockname, MAX_SOCKS);
s->next = Socket_lists[s->hash];
Socket_lists[s->hash] = (void *)s;
}
static void del_sock_from_hash_table(char *sockname, Sock_List *s) {
Sock_List *tmp = NULL, *prev = NULL;
for (tmp = Socket_lists[s->hash]; tmp; tmp = tmp->next) {
if (tmp == s) {
if (prev)
prev->next = tmp->next;
else
Socket_lists[s->hash] = tmp->next;
tmp->next = NULL;
return;
}
prev = tmp;
}
}
static Sock_List *new_sock(char *sock_name)
{
Sock_List *s;
#ifdef DEBUG
log("New Socket: %s", sock_name);
#endif
s = smalloc(sizeof(Sock_List));
if (!sock_name)
sock_name="";
s->sockname = sock_name;
add_sock_to_hash_table(sock_name, s);
return s;
}
Sock_List *findsock(char *sock_name) {
Sock_List *s;
s = Socket_lists[HASH(sock_name, MAX_SOCKS)];
while (s && strcmp(s->sockname, sock_name) != 0)
s = s->next;
return s;
}
int add_socket(char *func_name, char *sock_name, int socknum, char *mod_name) {
Sock_List *Sockets_mod_list;
Module *list_ptr;
segv_loc("add_Socket");
Sockets_mod_list = new_sock(sock_name);
Sockets_mod_list->sock_no = socknum;
Sockets_mod_list->modname = sstrdup(mod_name);
list_ptr = module_list->next;
while (list_ptr != NULL) {
if (!strcasecmp(list_ptr->info->module_name, mod_name)) {
/* Check to see if the function exists */
if (dlsym(list_ptr->dl_handle, func_name) == NULL) {
log("Oh Oh, the Socket function doesn't exist");
del_socket(Sockets_mod_list->sockname);
return -1;
}
Sockets_mod_list->function = dlsym(list_ptr->dl_handle, func_name);
#ifdef DEBUG
log("Registered Module %s with Socket for Function %s", list_ptr->info->module_name, func_name);
#endif
return 1;
}
list_ptr = list_ptr->next;
}
return 0;
}
int del_socket(char *sock_name) {
Sock_List *list;
segv_loc("del_mod_timer");
#ifdef DEBUG
log("Del_Sock");
#endif
list = findsock(sock_name);
if (list) {
#ifdef DEBUG
log("Unregistered Socket function %s from Module %s", sock_name, list->modname);
#endif
del_sock_from_hash_table(sock_name, list);
free(list);
return 1;
}
return -1;
}
void list_sockets(User *u) {
Sock_List *mod_ptr = NULL;
register int j;
segv_loc("list_sockets");
privmsg(u->nick,s_Services,"Sockets List:");
for (j = 0; j < MAX_SOCKS; j++) {
for (mod_ptr = Socket_lists[j]; mod_ptr; mod_ptr = mod_ptr->next) {
privmsg(u->nick,s_Services,"%s:--------------------------------",mod_ptr->modname);
privmsg(u->nick,s_Services,"Socket Name: %s",mod_ptr->sockname);
privmsg(u->nick,s_Services,"Socket Number: %d",mod_ptr->sock_no);
}
}
privmsg(u->nick,s_Services,"End of Socket List");
free(mod_ptr);
}
static void add_bot_to_hash_table(char *bot_name, Mod_User *u) {
u->hash = HASH(bot_name, B_TABLE_SIZE);
u->next = module_bot_lists[u->hash];
module_bot_lists[u->hash] = (void *)u;
}
static void del_bot_from_hash_table(char *bot_name, Mod_User *u) {
Mod_User *tmp, *prev = NULL;
for (tmp = module_bot_lists[u->hash]; tmp; tmp = tmp->next) {
if (tmp == u) {
if (prev)
prev->next = tmp->next;
else
module_bot_lists[u->hash] = tmp->next;
tmp->next = NULL;
return;
}
prev = tmp;
}
}
static Mod_User *new_bot(char *bot_name)
{
Mod_User *u;
#ifdef DEBUG
log("New Bot: %s", bot_name);
#endif
u = smalloc(sizeof(Mod_User));
if (!bot_name)
bot_name="";
u->nick = sstrdup(bot_name);
add_bot_to_hash_table(bot_name, u);
return u;
}
Mod_User *findbot(char *bot_name) {
Mod_User *u;
int i;
for (i = 0; i < B_TABLE_SIZE; i++) {
for (u = module_bot_lists[i]; u; u = u->next) {
if (!strcasecmp(u->nick, bot_name))
return u;
}
}
return NULL;
}
int del_mod_user(char *bot_name) {
Mod_User *list;
segv_loc("del_mod_user");
list = findbot(bot_name);
if (list) {
del_bot_from_hash_table(bot_name, list);
free(list);
return 1;
}
return -1;
}
int bot_nick_change(char *oldnick, char *newnick)
{
User *u;
Mod_User *mod_tmp, *mod_ptr = NULL;
segv_loc("bot_nick_change");
/* First, try to find out if the newnick is unique! */
#ifdef DEBUG
log("oldnick %s newnick %s",oldnick,newnick);
#endif
u = finduser(oldnick);
if (!u) {
log("A non-registered bot(%s) attempted to change its nick to %s",oldnick, newnick);
return -1;
}
u = finduser(newnick);
if (!u) {
mod_ptr = findbot(oldnick);
if (!u) {
#ifdef DEBUG
log("Bot %s Changed its nick to %s", oldnick, newnick);
#endif
mod_tmp = new_bot(newnick);
/* add a brand new user */
mod_tmp->nick = sstrdup(newnick);
mod_tmp->modname = sstrdup(mod_ptr->modname);
mod_tmp->function = mod_ptr->function;
/* Now Delete the Old bot nick */
del_mod_user(oldnick);
Change_User(finduser(oldnick), newnick);
sts(":%s NICK %s", oldnick, newnick);
return 1;
}
}
log("Couldn't find Bot Nick %s in Bot list", oldnick);
return -1;
}
int add_mod_user(char *nick, char *mod_name) {
Mod_User *Mod_Usr_list;
Module *list_ptr;
segv_loc("add_mod_user");
Mod_Usr_list = new_bot(nick);
/* add a brand new user */
Mod_Usr_list->nick = sstrdup(nick);
Mod_Usr_list->modname = sstrdup(mod_name);
list_ptr = module_list->next;
while (list_ptr != NULL) {
if (!strcasecmp(list_ptr->info->module_name, mod_name)) {
Mod_Usr_list->function = dlsym(list_ptr->dl_handle, "__Bot_Message");
return 1;
}
list_ptr = list_ptr->next;
}
return 0;
}
void list_module_bots(User *u) {
Mod_User *mod_ptr = NULL;
register int j;
segv_loc("list_module_bots");
privmsg(u->nick,s_Services,"Module Bot List:");
for (j = 0; j < B_TABLE_SIZE; j++) {
for (mod_ptr = module_bot_lists[j]; mod_ptr; mod_ptr = mod_ptr->next) {
privmsg(u->nick,s_Services,"Module: %s",mod_ptr->modname);
privmsg(u->nick,s_Services,"Module Bots: %s",mod_ptr->nick);
}
}
privmsg(u->nick,s_Services,"End of Module Bot List");
}
Module Find_Module(char *name) {
#ifdef DEBUGLL
log("DEBUGLL: FindModule: %s", name);
#endif
DLL_SetSearchModes(LL_Mods, DLL_HEAD, DLL_DOWN);
switch(DLL_FindRecord(LL_Mods, CurMod, name, strcasecmp(mod->module_name, name))) {
case DLL_NORMAL:
#ifdef DEBUGLL
log("DEBUGLL: FindModule Found %s", CurMod->info->module_name);
#endif;
return CurMod;
break;
default:
return NULL;
}
}
int load_module(char *path1, User *u) {
char *dl_error = NULL;
void *dl_handle;
int do_msg;
char *path = NULL;
Module_Info * (*mod_get_info)() = NULL;
Functions * (*mod_get_funcs)() = NULL;
EventFnList * (*mod_get_events)() = NULL;
Module_Info *mod_info_ptr = NULL;
Functions *mod_funcs_ptr = NULL;
EventFnList *event_fn_ptr = NULL;
Module *mod_ptr = NULL, *list_ptr = NULL;
segv_loc("load_module");
if (u == NULL) {
do_msg = 0;
} else {
do_msg = 1;
}
path = sstrdup(path1);
path = strcat(path,".so");
dl_handle = dlopen(path, RTLD_NOW);
if (!dl_handle) {
LD_Path *list;
list = ld_path_list->next;
while (list != NULL) {
char p[255];
snprintf(p, 255, "%s/%s", list->dl_path, path);
dl_handle = dlopen(p, RTLD_NOW);
if (!dl_handle) {
list = list->next;
} else {
list = NULL;
}
}
if (!dl_handle) {
if (do_msg) privmsg(u->nick, s_Services, "Error, Couldn't Load Module");
if (do_msg) privmsg(u->nick, s_Services, "%s",dlerror());
return -1;
}
}
mod_get_info = dlsym(dl_handle, "__module_get_info");
if ((dl_error = dlerror()) != NULL) {
if (do_msg) privmsg(u->nick, s_Services, "Error, Couldn't Load Module");
if (do_msg) privmsg(u->nick, s_Services, "%s",dl_error);
dlclose(dl_handle);
return -1;
}
mod_get_funcs = dlsym(dl_handle, "__module_get_functions");
if ((dl_error = dlerror()) != NULL) {
if (do_msg) privmsg(u->nick, s_Services, "Error, Couldn't Load Module");
if (do_msg) privmsg(u->nick, s_Services, "%s",dl_error);
dlclose(dl_handle);
return -1;
}
mod_get_events = dlsym(dl_handle, "__module_get_events");
/* no error check here - this one isn't essential to the functioning of the module */
mod_info_ptr = (*mod_get_info)();
mod_funcs_ptr = (*mod_get_funcs)();
if (mod_get_events) event_fn_ptr = (*mod_get_events)();
if (mod_info_ptr == NULL || mod_funcs_ptr == NULL) {
dlclose(dl_handle);
log("%s: Could not load dynamic library %s!\n", __PRETTY_FUNCTION__, path);
return -1;
}
/* Check that the Module hasn't already been loaded */
/* search for Modname */
if (Find_Module(mod_info_ptr->module_name) == NULL) {
dlclose(dl_handle);
if (do_msg) privmsg(u->nick,s_Services,"Module %s already Loaded, Can't Load 2 Copies",mod_info_ptr->module_name);
return -1;
}
mod_ptr = (Module *)malloc(sizeof(Module));
if (mod_ptr == NULL) {
fprintf(stderr, "%s: Out of memory!\n", __PRETTY_FUNCTION__);
dlclose(dl_handle);
exit(1);
}
log("internal module name: %s", mod_info_ptr->module_name);
log("module description: %s", mod_info_ptr->module_description);
mod_ptr->info = mod_info_ptr;
mod_ptr->dl_handle = dl_handle;
event_fn_ptr->module_name = mod_info_ptr->module_name;
mod_funcs_ptr->module_name = mod_info_ptr->module_name;
/* add them to the Linked Lists */
if (DLL_AddRecord(LL_Mods, mod_ptr, NULL) == DLL_MEM_ERROR) {
log("Error, Couldn't addmod, Out of Memory");
exit(-1);
}
if (DLL_AddRecord(LL_Mods_Evnts, event_fn_ptr, NULL) == DLL_MEM_ERROR) {
log("Error, Couldn't AddmodEvnts, Out of Memory");
exit(-1);
}
if (DLL_AddRecord(LL_Mods_fncts, mod_funcs_ptr, NULL) == DLL_MEM_ERROR) {
log("Error, Couldn't AddModFncts, Out of Memory");
exit(-1);
}
/* Let this module know we are online if we are! */
if (me.onchan == 1) {
Module_Event("ONLINE", me.s) {
if (do_msg) privmsg(u->nick,s_Services,"Module %s Loaded, Description: %s",mod_info_ptr->module_name,mod_info_ptr->module_description);
return 0;
};
void list_module(User *u) {
Module *mod_ptr = NULL;
segv_loc("list_module");
mod_ptr = module_list->next;
privmsg(u->nick,s_Services,"Module List:");
while(mod_ptr != NULL) {
privmsg(u->nick,s_Services,"Module: %s (%s)",mod_ptr->info->module_name, mod_ptr->info->module_version);
privmsg(u->nick,s_Services,"Module Description: %s",mod_ptr->info->module_description);
mod_ptr = mod_ptr->next;
}
privmsg(u->nick,s_Services,"End of Module List");
free(mod_ptr);
}
int unload_module(char *module_name, User *u) {
Module *list;
Mod_User *mod_ptr = NULL;
Mod_Timer *mod_tmr = NULL;
register int j;
segv_loc("unload_module");
/* Check to see if this Module has any timers registered.... */
for (j = 0; j < T_TABLE_SIZE; j++ ) {
for (mod_tmr = module_timer_lists[j]; mod_tmr; mod_tmr = mod_tmr->next) {
#ifdef DEBUG
log("Timers %s", mod_tmr->timername);
#endif
if (!strcasecmp(mod_tmr->modname, module_name)) {
del_mod_timer(mod_tmr->timername);
break;
}
}
}
/* now, see if this Module has any bots with it */
for (j = 0; j < B_TABLE_SIZE; j++) {
for (mod_ptr = module_bot_lists[j]; mod_ptr; mod_ptr = mod_ptr->next) {
if (!strcasecmp(mod_ptr->modname, module_name)) {
notice(s_Services,"Module %s had bot %s Registered. Deleting..",module_name,mod_ptr->nick);
del_bot(mod_ptr->nick, "Module Unloaded");
break;
}
}
}
list = module_list->next;
while (list != NULL) {
if (!strcasecmp(list->info->module_name, module_name)) {
dlclose(list->dl_handle);
if (list->next != NULL) {
(list->prev)->next = list->next;
(list->next)->prev = list->prev;
} else {
(list->prev)->next = NULL;
}
free(list);
return 0;
}
list = list->next;
}
privmsg(u->nick,s_Services,"Couldn't Find Module %s Loaded, Try /msg %s modlist",module_name,s_Services);
notice(s_Services,"%s tried to Unload %s but its not loaded",u->nick,module_name);
return -1;
}
void Module_Event(char *event, void *data) {
Module *module_ptr;
EventFnList *ev_list;
DLL_Return ExitCode;
segv_loc("Module_Event");
#ifdef DEBUGLL
log("DEBUGLL: ModEvent %s", event);
#endif
/* To Start with, we have to start at the top of the list */
DLL_SetSearchModes(LL_Mods_Evnts, DLL_HEAD, DLL_DOWN);
While (DLL_FindRecord(LL_Mods_Evnts, CurModEvnts, event, strcasecmp(tmp->cmd_name, event)) == DLL_NORMAL) {
#ifdef DEBUG
log("Running Module %s for Comamnd %s -> %s",module_ptr->info->module_name, event, ev_list->cmd_name);
#endif
segv_loc(CurModEvnts->module_name);
CurModEvnts->function(data);
segv_loc("Module_Event_Return");
/* now we search from the Current Record */
DLL_SetSearchModes(LL_Mods_Evnts, DLL_CURRENT, DLL_DOWN);
}
}