+
+/* Set the reload mark on the indicated module, if loaded, and all its
+ * children */
+void setreloadmark(struct module_dep *mdp) {
+ unsigned int i;
+
+ if (!isloaded(mdp->name->content))
+ return;
+
+ for (i=0;i<mdp->numchildren;i++)
+ setreloadmark(mdp->children[i]);
+
+ mdp->reloading=1;
+}
+
+/* preparereload: this function marks in the dependency tree all the
+ * modules which will be unloaded if this one is removed. */
+void preparereload(char *modulename) {
+ unsigned int i;
+ struct module_dep *mdp;
+ 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 */
+ if (getindex(modulebuf)<0)
+ return;
+
+ if ((mdp=getmoduledep(modulebuf))) {
+ setreloadmark(mdp);
+ }
+}
+
+/* reloadmarked: this function loads all the modules marked for reloading.
+ * The way the array is ordered means we will do this in the "right" order.
+ * This means we won't do an isloaded() check for each one - we shouldn't
+ * get any "already loaded" warnings so let them come out if they happen.
+ */
+void reloadmarked(void) {
+ unsigned int i;
+
+ for (i=0;i<knownmodules;i++) {
+ if (moduledeps[i].reloading) {
+ insmod(moduledeps[i].name->content);
+ }
+ }
+}
+
+void safereloadcallback(void *arg) {
+ safereload_sched=NULL;
+
+ if (!safereload_str)
+ return;
+
+ preparereload(safereload_str->content);
+ rmmod(safereload_str->content, 1);
+ 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));
+
+ /* Unload the module unless we're running on Valgrind -
+ * in which case unloading the module would invalidate
+ * stacktraces Valgrind has captured so far. */
+ rmmod(buf, !RUNNING_ON_VALGRIND);
+ }
+
+ 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);
+}