Permalink
Browse files

Add module unloading code.

Improve module loading code.
Add module control commands to the core module.
  • Loading branch information...
1 parent c24b049 commit 1e0b92e5e8d33bd585609952035f7ac4d2db65fd @tm512 committed Feb 17, 2012
Showing with 93 additions and 4 deletions.
  1. +55 −2 src/module.c
  2. +1 −0 src/module.h
  3. +37 −2 src/modules/core/main.c
View
@@ -17,13 +17,14 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <dlfcn.h>
#include "prints.h"
#include "irc.h"
#include "module.h"
-typedef void (*modinit_f) (void *mod, listener_t **privmsg); // TODO: More listeners, of course...
+typedef void (*modinit_f) (void *mod);
listener_t *privmsgListeners = NULL;
@@ -50,11 +51,63 @@ int module_load (char *path)
return 2;
}
- init (mod, &privmsgListeners);
+ init (mod);
return 0;
}
+#define MAX(a,b) ((a < b) ? b : a)
+
+int module_unload (char *name, listener_t **lp)
+{
+ listener_t *it = *lp;
+ void *mod = NULL;
+
+ if (!strncmp ("core", name, MAX (4, strlen (it->modname))))
+ return 1; // Do not unload the core module
+
+ if (!strncmp (name, it->modname, MAX (strlen (name), strlen (it->modname))))
+ {
+ (*lp) = it->next;
+ mod = it->mod;
+ free (it);
+ }
+
+ while (1)
+ {
+ if (!it->next)
+ break;
+
+ if (!strncmp (name, it->next->modname, MAX (strlen (name), strlen (it->next->modname))))
+ {
+ listener_t *next = it->next->next;
+
+ if (mod && mod != it->next->mod) // Huh?
+ dlclose (mod);
+
+ mod = it->next->mod;
+
+ free (it->next);
+ it->next = next;
+ }
+ }
+
+ if (mod)
+ {
+ iprint ("Unloaded module: %s", name);
+ dlclose (mod);
+ }
+ else
+ {
+ eprint (0, "Module %s doesn't appear to be loaded", name);
+ return 2;
+ }
+
+ return 0;
+}
+
+#undef MAX
+
void module_registerfunc (listener_t **lp, void *func, void *mod, const char *modname)
{
listener_t *l = *lp;
View
@@ -29,6 +29,7 @@ typedef struct listener_s
} listener_t;
int module_load (char *path);
+int module_unload (char *name, listener_t **lp);
void module_registerfunc (listener_t **l, void *func, void *mod, const char *modname);
extern listener_t *privmsgListeners;
View
@@ -26,6 +26,7 @@
#include "version.h"
+#include "prints.h"
#include "irc.h"
#include "config.h"
#include "module.h"
@@ -68,6 +69,40 @@ void corePrivmsg (ircclient_t *cl, char *nick, char *host, char *source, char *m
return;
}
+ if ((strstr (buf, "module ") == buf || strstr (buf, "mod ") == buf) && irc_isowner (cl, host))
+ {
+ strtok_r (buf, " ", &tokbuf);
+ char *modcmd = strtok_r (NULL, " ", &tokbuf);
+ char *modname = modcmd + strlen (modcmd) + 1;;
+
+ dprint ("%s %s", modcmd, modname);
+
+ if (!strlen (modname))
+ {
+ irc_notice (cl, nick, "No module name specified!");
+ return;
+ }
+
+ if (strstr (modcmd, "load") == modcmd)
+ {
+ char filepath [strlen (globalcfg.modpath) + strlen (modname) + 4];
+ sprintf (filepath, "%s/%s.so", globalcfg.modpath, modname);
+ if (!module_load (filepath))
+ irc_notice (cl, nick, "Loaded module: %s", filepath);
+ else
+ irc_notice (cl, nick, "Failed to load module: %s", filepath);
+ }
+ else if (strstr (modcmd, "unload") == modcmd)
+ {
+ if (!module_unload (modname, &privmsgListeners))
+ irc_notice (cl, nick, "Unloaded module: %s", modname);
+ else
+ irc_notice (cl, nick, "Failed to unload module: %s", modname);
+ }
+
+ return;
+ }
+
if ((strstr (buf, "part ") == buf || strstr (buf, "p ") == buf) && irc_isowner (cl, host))
{
strtok_r (buf, " ", &tokbuf);
@@ -100,8 +135,8 @@ void corePrivmsg (ircclient_t *cl, char *nick, char *host, char *source, char *m
return;
}
-void init (void *mod, listener_t **privmsg)
+void init (void *mod)
{
- module_registerfunc (privmsg, corePrivmsg, mod, modname);
+ module_registerfunc (&privmsgListeners, corePrivmsg, mod, modname);
return;
}

0 comments on commit 1e0b92e

Please sign in to comment.