aboutsummaryrefslogtreecommitdiffstats
path: root/ircd/modules.c
diff options
context:
space:
mode:
Diffstat (limited to 'ircd/modules.c')
-rw-r--r--ircd/modules.c198
1 files changed, 133 insertions, 65 deletions
diff --git a/ircd/modules.c b/ircd/modules.c
index 93e43acc..e6bf7693 100644
--- a/ircd/modules.c
+++ b/ircd/modules.c
@@ -44,28 +44,14 @@
# error "Solanum requires loadable module support."
#endif
+struct module_dentry
+{
+ char name[PATH_MAX];
+};
+
rb_dlink_list module_list;
rb_dlink_list mod_paths;
-static const char *core_module_table[] = {
- "m_ban",
- "m_die",
- "m_error",
- "m_identified",
- "m_join",
- "m_kick",
- "m_kill",
- "m_message",
- "m_mode",
- "m_modules",
- "m_nick",
- "m_part",
- "m_quit",
- "m_server",
- "m_squit",
- NULL
-};
-
#define MOD_WARN_DELTA (90 * 86400) /* time in seconds, 86400 seconds in a day */
void
@@ -199,69 +185,138 @@ findmodule_byname(const char *name)
return NULL;
}
-/* load_all_modules()
+/* module_dentry_sort_cb()
*
- * input -
- * output -
- * side effects -
+ * Helper function for load_all_modules_dir()
+ *
+ * input - 2 module file names
+ * output - file name sorting order
+ * side effects - the array of modules is sorted according to the return value
*/
-void
-load_all_modules(bool warn)
+static int
+module_dentry_sort_cb(const void *ptr1, const void *ptr2)
{
- DIR *system_module_dir = NULL;
- struct dirent *ldirent = NULL;
- char module_fq_name[PATH_MAX + 1];
- size_t module_ext_len = strlen(LT_MODULE_EXT);
+ const struct module_dentry *mod1 = ptr1;
+ const struct module_dentry *mod2 = ptr2;
+
+ return strcmp(mod1->name, mod2->name);
+}
- system_module_dir = opendir(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]);
+/* load_all_modules_dir()
+ *
+ * Helper function for load_all_modules()
+ *
+ * input - Module directory, whether this directory is for core modules or not,
+ * whether to warn about module loading
+ * output - None
+ * side effects - Loads every module located in the directory. If it is a core module
+ * and it fails to load, the process exits in failure.
+ */
+static void
+load_all_modules_dir(const char *path, bool core, bool warn)
+{
+ const size_t module_ext_len = strlen(LT_MODULE_EXT);
+ struct module_dentry *dentries = NULL;
+ size_t dentries_length = 0;
+ size_t dentries_used = 0;
+ char modpath[PATH_MAX + 1];
+ struct dirent *dirent;
+ struct stat statbuf;
+ DIR *moddir;
+ size_t len;
- if(system_module_dir == NULL)
+ if ((moddir = opendir(path)) == NULL)
{
- ilog(L_MAIN, "Could not load modules from %s: %s", ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], strerror(errno));
- return;
+ if (! core)
+ {
+ ilog(L_MAIN, "Could not load modules from %s (%s)", path, strerror(errno));
+ return;
+ }
+
+ ilog(L_MAIN, "Could not load core modules from %s (%s); terminating ircd", path, strerror(errno));
+ exit(EXIT_FAILURE);
}
- while ((ldirent = readdir(system_module_dir)) != NULL)
+ while ((dirent = readdir(moddir)) != NULL)
{
- size_t len = strlen(ldirent->d_name);
+ // File name length is not greater than the size of required extension (e.g. ".so")
+ if ((len = strlen(dirent->d_name)) <= module_ext_len)
+ continue;
+
+ // File name does not end with required extension
+ if (strncasecmp(dirent->d_name + (len - module_ext_len), LT_MODULE_EXT, module_ext_len) != 0)
+ continue;
- if(len > module_ext_len &&
- rb_strncasecmp(ldirent->d_name + (len - module_ext_len), LT_MODULE_EXT, module_ext_len) == 0)
+ // Unable to obtain dentry info or dentry is not actually a file?
+ snprintf(modpath, sizeof modpath, "%s/%s", path, dirent->d_name);
+ if (! (stat(modpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode)))
+ continue;
+
+ // Extend the modules array if it is not long enough
+ if (dentries_used == dentries_length)
{
- (void) snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
- ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], ldirent->d_name);
- (void) load_a_module(module_fq_name, warn, MAPI_ORIGIN_CORE, false);
+ dentries_length += 32;
+ dentries = rb_realloc(dentries, dentries_length * sizeof *dentries);
}
+ // Add this module to the array of modules to load
+ rb_strlcpy(dentries[dentries_used].name, dirent->d_name, sizeof dentries[dentries_used].name);
+
+ // Advance
+ dentries_used++;
}
- (void) closedir(system_module_dir);
-}
-/* load_core_modules()
- *
- * input -
- * output -
- * side effects - core modules are loaded, if any fail, kill ircd
- */
-void
-load_core_modules(bool warn)
-{
- char module_name[PATH_MAX];
- int i;
+ closedir(moddir);
+
+ if (! dentries_used)
+ {
+ if (core)
+ {
+ ilog(L_MAIN, "Could not load core modules from %s (empty); terminating ircd", path);
+ exit(EXIT_FAILURE);
+ }
+
+ return;
+ }
+ // Sort the array of modules to load based on their file name
+ qsort(dentries, dentries_used, sizeof(struct module_dentry), &module_dentry_sort_cb);
- for (i = 0; core_module_table[i]; i++)
+ // Attempt to load each module
+ for (size_t i = 0; i < dentries_used; i++)
{
- snprintf(module_name, sizeof(module_name), "%s/%s", ircd_paths[IRCD_PATH_MODULES], core_module_table[i]);
+ char modpath[PATH_MAX + 1];
- if(load_a_module(module_name, warn, MAPI_ORIGIN_CORE, true) == false)
+ snprintf(modpath, sizeof modpath, "%s/%s", path, dentries[i].name);
+
+ if (load_a_module(modpath, warn, MAPI_ORIGIN_CORE, core))
+ continue;
+
+ if (core)
{
- ilog(L_MAIN,
- "Error loading core module %s: terminating ircd",
- core_module_table[i]);
+ ilog(L_MAIN, "Error while loading core module %s; terminating ircd", dentries[i].name);
exit(EXIT_FAILURE);
}
+
+ ilog(L_MAIN, "Error while loading module %s", dentries[i].name);
}
+
+ // Clean up
+ rb_free(dentries);
+}
+
+/* load_all_modules()
+ *
+ * input -
+ * output -
+ * side effects - Loads every core module, then every module in the autoload directory.
+ * If a core module fails to load, the process exits in failure.
+ */
+void
+load_all_modules(bool warn)
+{
+ load_all_modules_dir(ircd_paths[IRCD_PATH_MODULES], true, warn);
+ load_all_modules_dir(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], false, warn);
}
/* load_one_module()
@@ -276,10 +331,7 @@ load_one_module(const char *path, int origin, bool coremodule)
char modpath[PATH_MAX];
rb_dlink_node *pathst;
- if (server_state_foreground)
- inotice("loading module %s ...", path);
-
- if(coremodule)
+ if (coremodule)
origin = MAPI_ORIGIN_CORE;
RB_DLINK_FOREACH(pathst, mod_paths.head)
@@ -452,6 +504,7 @@ unload_one_module(const char *name, bool warn)
bool
load_a_module(const char *path, bool warn, int origin, bool core)
{
+ const char *modpath = path;
struct module *mod;
lt_dlhandle tmpptr;
char *mod_displayname, *c;
@@ -459,6 +512,22 @@ load_a_module(const char *path, bool warn, int origin, bool core)
int *mapi_version;
+ if (server_state_foreground)
+ {
+ // Trim off the module installation prefix if the path matches it
+ if (strncmp(path, ircd_paths[IRCD_PATH_MODULES], strlen(ircd_paths[IRCD_PATH_MODULES])) == 0)
+ {
+ modpath += strlen(ircd_paths[IRCD_PATH_MODULES]);
+
+ if (*modpath == '/')
+ modpath++;
+ else
+ modpath = path;
+ }
+
+ inotice("loading module %s ...", modpath);
+ }
+
mod_displayname = rb_basename(path);
/* Trim off the ending for the display name if we have to */
@@ -690,7 +759,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
mod->mapi_version = MAPI_VERSION(*mapi_version);
mod->origin = origin;
mod->path = rb_strdup(path);
- rb_dlinkAdd(mod, &mod->node, &module_list);
+ rb_dlinkAddTail(mod, &mod->node, &module_list);
if(warn)
{
@@ -797,7 +866,6 @@ modules_do_restart(void *unused)
}
load_all_modules(false);
- load_core_modules(false);
rehash(false);
mod_notify_clicaps();