#include "../lib/sstring.h"
#include "../lib/irc_string.h"
#include "../lib/splitline.h"
+#include "../lib/strlfunc.h"
#include "config.h"
#include "error.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include "schedule.h"
#define DEPFILE "modules.dep"
* At the end of the second pass we should have a correctly filled in array!
*/
+sstring *safereload_str;
+schedule *safereload_sched;
+
struct module_dep {
sstring *name;
unsigned int numparents;
unsigned int i;
for (i=0;i<knownmodules;i++) {
- free(moduledeps[i].parents);
- free(moduledeps[i].children);
+ freesstring(moduledeps[i].name);
+ if (moduledeps[i].parents) {
+ free(moduledeps[i].parents);
+ moduledeps[i].parents=NULL;
+ }
+ if (moduledeps[i].children) {
+ free(moduledeps[i].children);
+ moduledeps[i].children=NULL;
+ }
}
knownmodules=0;
char *largv[100];
char largc;
char *ch;
- struct module_dep *mdp, *tmdp, *mdps;
+ struct module_dep *mdp, *tmdp;
unsigned int i,j;
sprintf(buf,"%s/%s",moddir->content,DEPFILE);
/* Add us to the array */
i=knownmodules++;
if (i>=MAXMODULES) {
- Error("core",ERR_FATAL,"Too many modules in dependency file; rebuild with higher MAXMODULES.\n");
+ Error("core",ERR_ERROR,
+ "Too many modules in dependency file; rebuild with higher MAXMODULES. Module dependencies disabled.\n");
+ clearmoduledeps();
return;
}
/* Fill in the parents array */
for (i=0;i<(largc-1);i++) {
if (!(mdp->parents[i]=getmoduledep(largv[i+1]))) {
- Error("core",ERR_WARNING,"Couldn't find parent module %s of %s.",largv[i+1],largv[0]);
- continue;
+ Error("core",ERR_WARNING,"Couldn't find parent module %s of %s. Module dependencies disabled.",
+ largv[i+1],largv[0]);
+ clearmoduledeps();
+ return;
}
mdp->parents[i]->numchildren++; /* break the bad news */
}
}
int insmod(char *modulename) {
- int i, n;
+ int i;
module *mods;
- char buf[1024];
- const char *(*verinfo)(void);
+ char buf[1024], modulebuf[1024];
+ const char *(*verinfo)(const char **);
struct module_dep *mdp;
- delchars(modulename,"./\\;");
+ strlcpy(modulebuf, modulename, sizeof(modulebuf));
+ delchars(modulebuf,"./\\;");
- if (isloaded(modulename)) {
- Error("core",ERR_DEBUG,"Tried to load already loaded module: %s",modulename);
+ if (isloaded(modulebuf)) {
+ Error("core",ERR_DEBUG,"Tried to load already loaded module: %s",modulebuf);
return 1;
}
- if (strlen(modulename)>100) {
- Error("core",ERR_WARNING,"Module name too long: %s",modulename);
+ if (strlen(modulebuf)>100) {
+ Error("core",ERR_WARNING,"Module name too long: %s",modulebuf);
return 1;
}
- if ((mdp=getmoduledep(modulename))) {
+ if ((mdp=getmoduledep(modulebuf))) {
for (i=0;i<mdp->numparents;i++) {
if (!isloaded(mdp->parents[i]->name->content)) {
if (insmod(mdp->parents[i]->name->content)) {
Error("core",ERR_WARNING,"Error loading dependant module %s (needed by %s)",
- mdp->parents[i]->name->content,modulename);
+ mdp->parents[i]->name->content,modulebuf);
return 1;
}
}
}
} else {
- Error("core",ERR_WARNING,"Loading module %s without dependency information.",modulename);
+ Error("core",ERR_WARNING,"Loading module %s without dependency information.",modulebuf);
}
i=array_getfreeslot(&modules);
mods=(module *)(modules.content);
- sprintf(buf,"%s/%s%s",moddir->content,modulename,modsuffix->content);
+ sprintf(buf,"%s/%s%s",moddir->content,modulebuf,modsuffix->content);
mods[i].handle=dlopen(buf,RTLD_NOW|RTLD_GLOBAL);
if(mods[i].handle==NULL) {
- Error("core",ERR_ERROR,"Loading module %s failed: %s",modulename,dlerror());
+ Error("core",ERR_ERROR,"Loading module %s failed: %s",modulebuf,dlerror());
array_delslot(&modules,i);
return -1;
}
- mods[i].name=getsstring(modulename,MODULENAMELEN);
+ mods[i].name=getsstring(modulebuf,MODULENAMELEN);
verinfo=dlsym(mods[i].handle,"_version");
if(verinfo) {
- mods[i].version=verinfo();
- } else {
+ mods[i].buildid=verinfo(&mods[i].version);
+ } else {
mods[i].version=NULL;
+ mods[i].buildid=NULL;
}
- Error("core",ERR_INFO,"Loaded module %s OK.",modulename);
+ mods[i].loadedsince = time(NULL);
+ Error("core",ERR_INFO,"Loaded module %s OK.",modulebuf);
return 0;
}
return -1;
}
-char *lsmod(int index) {
+char *lsmod(int index, const char **ver, const char **buildid, time_t *t) {
module *mods;
if (index < 0 || index >= modules.cursi)
return NULL;
mods=(module *)(modules.content);
- return mods[index].name->content;
-}
-
-const char *lsmodver(int index) {
- module *mods;
+ if(ver)
+ *ver=mods[index].version;
+ if(buildid)
+ *buildid=mods[index].buildid;
+ if(t)
+ *t=mods[index].loadedsince;
- if (index < 0 || index >= modules.cursi)
- return NULL;
-
- mods=(module *)(modules.content);
- return mods[index].version;
+ return mods[index].name->content;
}
int isloaded(char *modulename) {
int i,j;
module *mods;
struct module_dep *mdp;
+ char modulebuf[1024];
+
+ strlcpy(modulebuf, modulename, sizeof(modulebuf));
+ delchars(modulebuf,"./\\;");
- delchars(modulename,"./\\;");
-
- i=getindex(modulename);
+ i=getindex(modulebuf);
if (i<0)
return 1;
- if ((mdp=getmoduledep(modulename))) {
+ if ((mdp=getmoduledep(modulebuf))) {
for (j=0;j<mdp->numchildren;j++) {
if (isloaded(mdp->children[j]->name->content)) {
if (rmmod(mdp->children[j]->name->content)) {
Error("core",ERR_WARNING,"Unable to remove child module %s (depends on %s)",
- mdp->children[j]->name->content, modulename);
+ mdp->children[j]->name->content, modulebuf);
return 1;
}
}
}
/* We may have removed other modules - reaquire the index number in case it has changed. */
- i=getindex(modulename);
+ i=getindex(modulebuf);
if (i<0)
return 1;
} else {
- Error("core",ERR_WARNING,"Removing module %s without dependency information",modulename);
+ Error("core",ERR_WARNING,"Removing module %s without dependency information",modulebuf);
}
mods=(module *)(modules.content);
freesstring(mods[i].name);
array_delslot(&modules,i);
- Error("core",ERR_INFO,"Removed module %s.",modulename);
+ Error("core",ERR_INFO,"Removed module %s.",modulebuf);
return 0;
}
void preparereload(char *modulename) {
unsigned int i;
struct module_dep *mdp;
-
- delchars(modulename,"./\\;");
+ char modulebuf[1024];
+
+ strlcpy(modulebuf, modulename, sizeof(modulebuf));
+ delchars(modulebuf,"./\\;");
/* First, clear the mark off all dependant modules */
for (i=0;i<knownmodules;i++)
moduledeps[i].reloading=0;
/* Do nothing if this module is not loaded */
- i=getindex(modulename);
- if (i<0)
+ if (getindex(modulebuf)<0)
return;
- if ((mdp=getmoduledep(modulename))) {
+ if ((mdp=getmoduledep(modulebuf))) {
setreloadmark(mdp);
}
}
}
}
}
+
+void safereloadcallback(void *arg) {
+ safereload_sched=NULL;
+
+ if (!safereload_str)
+ return;
+
+ preparereload(safereload_str->content);
+ rmmod(safereload_str->content);
+ insmod(safereload_str->content);
+ reloadmarked();
+
+ freesstring(safereload_str);
+ safereload_str=NULL;
+}
+
+void safereload(char *themodule) {
+ if (safereload_str)
+ freesstring(safereload_str);
+
+ safereload_str=getsstring(themodule, 100);
+
+ if (safereload_sched)
+ deleteschedule(safereload_sched, safereloadcallback, NULL);
+
+ scheduleoneshot(1, safereloadcallback, NULL);
+}
+
+void newserv_shutdown() {
+ module *mods;
+ char buf[1024];
+
+ while (modules.cursi) {
+ mods=(module *)(modules.content);
+
+ strlcpy(buf, mods[0].name->content, sizeof(buf));
+ rmmod(buf);
+ }
+
+ clearmoduledeps();
+
+ if (moddir!=NULL)
+ freesstring(moddir);
+
+ if (modsuffix!=NULL)
+ freesstring(modsuffix);
+
+ Error("core",ERR_INFO,"All modules removed. Exiting.");
+}
+
+/* very slow, make sure you cache the pointer! */
+void *ndlsym(char *modulename, char *fn) {
+ module *mods=(module *)(modules.content);
+ int i=getindex(modulename);
+
+ if (i<0)
+ return NULL;
+
+ return dlsym(mods[i].handle, fn);
+}