/*
* modules.c - support for code modules in eggdrop
* by Darrin Smith (beldin@light.iinet.net.au)
*/
/*
This file is part of the eggdrop source code
copyright (c) 1997 Robey Pointer
and is distributed according to the GNU general public license.
For full details, read the top of 'main.c' or the file called
COPYING that was distributed with this code.
*/
#include "modules.h"
#ifndef STATIC
#ifdef HPUX_HACKS
#include
#else
#ifdef OSF1_HACKS
#include
#else
#if DLOPEN_1
char *dlerror();
void *dlopen (const char *, int);
int dlclose (void *);
void * dlsym (void *,char *);
#define DLFLAGS 1
#else
#include
#ifdef RTLD_GLOBAL
#define DLFLAGS RTLD_NOW|RTLD_GLOBAL
#else
#define DLFLAGS RTLD_NOW
#endif /* RTLD_GLOBAL */
#endif /* DLOPEN_1 */
#endif /* OSF1_HACKS */
#endif /* HPUX_HACKS */
#endif /* STATIC */
extern struct dcc_t * dcc;
#include "users.h"
int cmd_note();
/* from other areas */
extern int egg_numver;
extern Tcl_Interp *interp;
extern struct userrec *userlist;
extern int dcc_total;
extern char tempdir[];
extern char botnetnick[];
extern int reserved_port;
extern char botname[];
extern time_t now;
/* only used here, we'll cheat */
int check_validity (char *, Function);
/* the null functions */
void null_func()
{
}
char *charp_func()
{
return NULL;
}
int minus_func()
{
return -1;
}
/* various hooks & things */
/* the REAL hooks, when these are called, a return of 0 indicates unhandled
* 1 is handled */
struct hook_entry {
struct hook_entry *next;
int (*func) ();
} *hook_list[REAL_HOOKS];
static void null_share (int idx, char * x) {
tprintf(dcc[idx].sock, "share uf-no Not sharing userfile.\n");
}
/* these are obscure ones that I hope to neaten eventually :/ */
void (*kill_all_assoc) () = null_func;
void (*dump_bot_assoc) (int) = null_func;
char *(*get_assoc_name) (int) = charp_func;
int (*get_assoc) (char *) = minus_func;
void (*do_bot_assoc) (int, char *) = null_func;
void (*encrypt_pass) (char *, char *) = 0;
void (*shareout)() = null_func;
void (*sharein)(int,char *) = null_share;
module_entry *module_list;
dependancy * dependancy_list = NULL;
void init_modules(int x)
{
int i;
context;
if (x) {
module_list = nmalloc(sizeof(module_entry));
module_list->name = nmalloc(8);
strcpy(module_list->name, "eggdrop");
module_list->major = (egg_numver) / 10000;
module_list->minor = ((egg_numver) / 100) % 100;
#ifndef STATIC
module_list->hand = NULL;
#endif
module_list->next = NULL;
module_list->funcs = NULL;
}
for (i = 0; i < REAL_HOOKS; i++)
hook_list[i] = NULL;
}
int expmem_modules(int y)
{
int c = 0;
int i;
module_entry *p = module_list;
dependancy *d = dependancy_list;
Function *f;
context;
for (i = 0; i < REAL_HOOKS; i++) {
struct hook_entry *q = hook_list[i];
while (q) {
c += sizeof(struct hook_entry);
q = q->next;
}
}
while (d) {
c += sizeof(dependancy);
d = d->next;
}
while (p) {
c += sizeof(module_entry);
c += strlen(p->name) + 1;
f = p->funcs;
if ((f != NULL) && !y)
c += (int) (f[MODCALL_EXPMEM] ());
p = p->next;
}
return c;
}
void mod_context (char * module, char * file, int line)
{
char x[100];
sprintf(x, "%s:%s", module, file);
x[30] = 0;
#ifdef EBUG
cx_ptr = ((cx_ptr + 1) & 15);
strcpy(cx_file[cx_ptr], x);
cx_line[cx_ptr] = line;
#else
strcpy(cx_file, x);
cx_line = line;
#endif
}
int module_register (char * name, Function * funcs,
int major, int minor)
{
module_entry *p = module_list;
#ifdef STATIC
p = nmalloc(sizeof(module_entry));
if (p == NULL)
return 0;
p->next = module_list;
module_list = p;
module_list->name = nmalloc(strlen(name) + 1);
strcpy(module_list->name, name);
module_list->major = 0;
module_list->minor = 0;
check_tcl_load(name);
putlog(LOG_MISC, "*", "%s %s", MOD_LOADED, name);
#endif
context;
while (p) {
if ((p->name != NULL) && (strcasecmp(name, p->name) == 0)) {
p->major = major;
p->minor = minor;
p->funcs = funcs;
return 1;
}
p = p->next;
}
return 0;
}
const char *module_load (char * name)
{
#ifndef STATIC
module_entry *p;
char workbuf[1024];
#ifdef HPUX_HACKS
shl_t hand;
#else
#ifdef OSF1_HACKS
ldr_module_t hand;
#else
void *hand;
#endif
#endif
char *e;
Function f;
context;
if (module_find(name, 0, 0) != NULL)
return MOD_ALREADYLOAD;
if (getcwd(workbuf, 1024) == NULL)
return MOD_BADCWD;
sprintf(&(workbuf[strlen(workbuf)]), "/modules/%s.so", name);
#ifdef HPUX_HACKS
hand = shl_load(workbuf, BIND_IMMEDIATE, 0);
if (!hand)
return "Can't load module.";
#else
#ifdef OSF1_HACKS
hand = (Tcl_PackageInitProc *) load (workbuf, LDR_NOFLAGS);
if (hand == LDR_NULL_MODULE)
return "Can't load module.";
#else
hand = dlopen(workbuf, DLFLAGS);
if (!hand)
return dlerror();
#endif
#endif
sprintf(workbuf, "%s_start", name);
#ifdef HPUX_HACKS
if (!shl_findsym(hand, procname, (short) TYPE_PROCEDURE, (void *)f))
f = NULL;
#else
#ifdef OSF1_HACKS
f = ldr_lookup_package(hand, workbuf);
#else
f = dlsym(hand, workbuf);
#endif
#endif
if (f == NULL) { /* some OS's need the _ */
sprintf(workbuf, "_%s_start", name);
#ifdef HPUX_HACKS
if (!shl_findsym(hand, procname, (short) TYPE_PROCEDURE, (void *)f))
f = NULL;
#else
#ifdef OSF1_HACKS
f = ldr_lookup_package(hand, workbuf);
#else
f = dlsym(hand, workbuf);
#endif
#endif
if (f == NULL) {
return MOD_NOSTARTDEF;
}
}
p = nmalloc(sizeof(module_entry));
if (p == NULL)
return "Malloc error";
p->next = module_list;
module_list = p;
module_list->name = nmalloc(strlen(name) + 1);
strcpy(module_list->name, name);
module_list->major = 0;
module_list->minor = 0;
module_list->hand = hand;
e = (((char *(*)())f)(0));
if (e != NULL)
return e;
check_tcl_load(name);
putlog(LOG_MISC, "*", "%s %s", MOD_LOADED, name);
return NULL;
#else
return "Can't load modules, statically linked.";
#endif
}
char *module_unload (char * name,char * user)
{
#ifndef STATIC
module_entry *p = module_list, *o = NULL;
char *e;
Function *f;
context;
while (p) {
if ((p->name != NULL) && (strcmp(name, p->name) == 0)) {
dependancy *d = dependancy_list;
while (d!=NULL) {
if (d->needed == p) {
return MOD_NEEDED;
}
d=d->next;
}
f = p->funcs;
if ((f != NULL) && (f[MODCALL_CLOSE] == NULL))
return MOD_NOCLOSEDEF;
if (f != NULL) {
check_tcl_unld(name);
e = (((char *(*)())f[MODCALL_CLOSE]) (user));
if (e != NULL)
return e;
#ifdef HPUX_HACKS
shl_unload(hand);
#else
#ifdef OSF1_HACKS
#else
dlclose(p->hand);
#endif
#endif
}
nfree(p->name);
if (o == NULL) {
module_list = p->next;
} else {
o->next = p->next;
}
nfree(p);
putlog(LOG_MISC, "*", "%s %s", MOD_UNLOADED, name);
return NULL;
}
o = p;
p = p->next;
}
return MOD_NOSUCH;
#else
return "Can't unload modules, statically linked.";
#endif /* STATIC */
}
module_entry *module_find (char * name, int major, int minor)
{
module_entry *p = module_list;
while (p) {
if ((p->name != NULL) && (strcasecmp(name, p->name) == 0) &&
((major == p->major) || (major == 0))
&& (minor <= p->minor))
return p;
p = p->next;
}
return NULL;
}
int module_depend (char * name1, char * name2, int major, int minor)
{
module_entry *p = module_find(name2, major, minor);
module_entry *o = module_find(name1, 0, 0);
dependancy *d;
context;
#ifndef STATIC
if (p == NULL) {
if (module_load(name2) != NULL)
return 0;
p = module_find(name2, major, minor);
}
#endif
if ((p == NULL) || (o == NULL))
return 0;
d = nmalloc(sizeof(dependancy));
d->needed = p;
d->needing = o;
d->next = dependancy_list;
d->major = major;
d->minor = minor;
dependancy_list = d;
return 1;
}
int module_undepend (char * name1)
{
int ok = 0;
#ifndef STATIC
module_entry *p = module_find(name1, 0, 0);
dependancy *d = dependancy_list, *o = NULL;
context;
if (p == NULL)
return 0;
while (d!=NULL) {
if (d->needing == p) {
if (o == NULL) {
dependancy_list = d->next;
} else {
o->next = d->next;
}
nfree(d);
if (o == NULL)
d = dependancy_list;
else
d = o->next;
ok++;
} else {
o = d;
d = d->next;
}
}
#endif
return ok;
}
void *mod_malloc (int size, char * modname, char * filename, int line)
{
char x[100];
sprintf(x, "%s:%s", modname, filename);
x[15] = 0;
return n_malloc(size, x, line);
}
void mod_free (void * ptr, char * modname, char * filename, int line)
{
char x[100];
sprintf(x, "%s:%s", modname, filename);
x[15] = 0;
n_free(ptr, x, line);
}
/* hooks, various tables of functions to call on ceratin events */
void add_hook (int hook_num, void * func)
{
context;
if (hook_num < REAL_HOOKS) {
struct hook_entry *p = nmalloc(sizeof(struct hook_entry));
p->next = hook_list[hook_num];
hook_list[hook_num] = p;
p->func = func;
} else
switch (hook_num) {
case HOOK_GET_ASSOC_NAME:
get_assoc_name = func;
break;
case HOOK_GET_ASSOC:
get_assoc = func;
break;
case HOOK_DUMP_ASSOC_BOT:
dump_bot_assoc = func;
break;
case HOOK_KILL_ASSOCS:
kill_all_assoc = func;
break;
case HOOK_BOT_ASSOC:
do_bot_assoc = func;
break;
case HOOK_ENCRYPT_PASS:
encrypt_pass = func;
break;
case HOOK_SHAREOUT:
shareout = func;
break;
case HOOK_SHAREIN:
sharein = func;
break;
} /* ignore unsupported stuff a.t.m. :) */
}
void del_hook (int hook_num, void * func)
{
context;
if (hook_num < REAL_HOOKS) {
struct hook_entry *p = hook_list[hook_num], *o = NULL;
while (p) {
if (p->func == func) {
if (o == NULL)
hook_list[hook_num] = p->next;
else
o->next = p->next;
nfree(p);
break;
}
o = p;
p = p->next;
}
} else
switch (hook_num) {
case HOOK_GET_ASSOC_NAME:
if (get_assoc_name == func)
get_assoc_name = charp_func;
break;
case HOOK_GET_ASSOC:
if (get_assoc == func)
get_assoc = minus_func;
break;
case HOOK_DUMP_ASSOC_BOT:
if (dump_bot_assoc == func)
dump_bot_assoc = null_func;
break;
case HOOK_KILL_ASSOCS:
if (kill_all_assoc == func)
kill_all_assoc = null_func;
break;
case HOOK_BOT_ASSOC:
if (do_bot_assoc == func)
do_bot_assoc = null_func;
break;
case HOOK_ENCRYPT_PASS:
if (encrypt_pass == func)
encrypt_pass = null_func;
break;
case HOOK_SHAREOUT:
if (shareout == func)
shareout = null_func;
break;
case HOOK_SHAREIN:
if (sharein == func)
sharein = null_share;
break;
} /* ignore unsupported stuff a.t.m. :) */
}
void *get_next_hook (int hook_num, void * func)
{
return NULL;
/* we dont use this YET */
}
int call_hook (int hooknum)
{
struct hook_entry *p;
if (hooknum >= REAL_HOOKS)
return 0;
p = hook_list[hooknum];
context;
while (p != NULL) {
p->func();
p = p->next;
}
return 0;
}
int call_hook_cccc (int hooknum, char * a, char * b, char * c, char * d)
{
struct hook_entry *p;
int f = 0;
if (hooknum >= REAL_HOOKS)
return 0;
p = hook_list[hooknum];
context;
while ((p != NULL) && !f) {
f = p->func(a, b, c, d);
p = p->next;
}
return f;
}
void do_module_report (int idx)
{
module_entry *p = module_list;
if (p != NULL)
#ifdef STATIC
dprintf(idx, "MODULES STATICALLY LINKED:\n");
#else
dprintf(idx, "MODULES LOADED:\n");
#endif
while (p) {
dependancy *d = dependancy_list;
dprintf(idx, "Module: %s, v %d.%d\n", p->name ? p->name : "CORE",
p->major, p->minor);
while (d != NULL) {
if (d->needing == p)
dprintf(idx, " requires: %s, v %d.%d\n", d->needed->name,
d->major, d->minor);
d = d->next;
}
if (p->funcs != NULL) {
Function f = p->funcs[MODCALL_REPORT];
if (f != NULL)
f(idx);
}
p = p->next;
}
}