int modules_init(void) { register unsigned int i = 0; for (i = 0; static_modules[i]; i++) { module *m = static_modules[i]; if (pr_module_load(m) < 0) { pr_log_pri(PR_LOG_WARNING, "fatal: unable to load module 'mod_%s.c': %s", m->name, strerror(errno)); exit(1); } } return 0; }
static int dso_load_module(char *name) { int res; char *symbol_name, *path, *tmp; module *m; lt_ptr mh = NULL; lt_dladvise advise; if (name == NULL) { errno = EINVAL; return -1; } if (strncmp(name, "mod_", 4) != 0 || name[strlen(name)-2] != '.' || name[strlen(name)-1] != 'c') { errno = EINVAL; return -1; } pr_log_debug(DEBUG7, "loading '%s'", name); tmp = strrchr(name, '.'); if (tmp == NULL) { errno = EINVAL; return -1; } if (lt_dladvise_init(&advise) < 0) { pr_log_pri(PR_LOG_NOTICE, MOD_DSO_VERSION ": unable to initialise advise: %s", lt_dlerror()); errno = EPERM; return -1; } if (lt_dladvise_ext(&advise) < 0) { pr_log_pri(PR_LOG_NOTICE, MOD_DSO_VERSION ": unable to setting 'ext' advise hint: %s", lt_dlerror()); lt_dladvise_destroy(&advise); errno = EPERM; return -1; } if (lt_dladvise_global(&advise) < 0) { pr_log_pri(PR_LOG_NOTICE, MOD_DSO_VERSION ": unable to setting 'global' advise hint: %s", lt_dlerror()); lt_dladvise_destroy(&advise); errno = EPERM; return -1; } *tmp = '\0'; /* Load file: $prefix/libexec/<module> */ path = pdircat(dso_pool, dso_module_path, name, NULL); pr_trace_msg(trace_channel, 5, "loading module '%s'", path); mh = lt_dlopenadvise(path, advise); if (mh == NULL) { *tmp = '.'; pr_log_debug(DEBUG3, MOD_DSO_VERSION ": unable to dlopen '%s': %s (%s)", name, lt_dlerror(), strerror(errno)); pr_log_debug(DEBUG3, MOD_DSO_VERSION ": defaulting to 'self' for symbol resolution"); lt_dladvise_destroy(&advise); mh = lt_dlopen(NULL); if (mh == NULL) { pr_log_debug(DEBUG0, MOD_DSO_VERSION ": error loading 'self': %s", lt_dlerror()); if (errno == ENOENT) { pr_log_pri(PR_LOG_NOTICE, MOD_DSO_VERSION ": check to see if '%s.la' exists", path); } return -1; } } lt_dladvise_destroy(&advise); /* Tease name of the module structure out of the given name: * <module>.<ext> --> <module>_module */ *tmp = '\0'; symbol_name = pstrcat(dso_pool, name+4, "_module", NULL); /* Lookup module structure symbol by name. */ pr_trace_msg(trace_channel, 7, "looking for symbol '%s' in loaded module", symbol_name); m = (module *) lt_dlsym(mh, symbol_name); if (m == NULL) { *tmp = '.'; pr_log_debug(DEBUG1, MOD_DSO_VERSION ": unable to find module symbol '%s' in '%s'", symbol_name, mh ? name : "self"); pr_trace_msg(trace_channel, 1, "unable to find module symbol '%s' in '%s'", symbol_name, mh ? name : "self"); lt_dlclose(mh); mh = NULL; if (errno == ENOENT) { pr_log_pri(PR_LOG_NOTICE, MOD_DSO_VERSION ": check to see if '%s.la' exists", path); } return -1; } *tmp = '.'; m->handle = mh; /* Add the module to the core structures */ res = pr_module_load(m); if (res < 0) { if (errno == EEXIST) { pr_log_pri(PR_LOG_INFO, MOD_DSO_VERSION ": module 'mod_%s.c' already loaded", m->name); pr_trace_msg(trace_channel, 1, "module 'mod_%s.c' already loaded", m->name); } else if (errno == EACCES) { pr_log_pri(PR_LOG_ERR, MOD_DSO_VERSION ": module 'mod_%s.c' has wrong API version (0x%x), must be 0x%x", m->name, m->api_version, PR_MODULE_API_VERSION); pr_trace_msg(trace_channel, 1, "module 'mod_%s.c' has wrong API version (0x%x), must be 0x%x", m->name, m->api_version, PR_MODULE_API_VERSION); } else if (errno == EPERM) { pr_log_pri(PR_LOG_ERR, MOD_DSO_VERSION ": module 'mod_%s.c' failed to initialize", m->name); pr_trace_msg(trace_channel, 1, "module 'mod_%s.c' failed to initialize", m->name); } lt_dlclose(mh); mh = NULL; return -1; } pr_trace_msg(trace_channel, 8, "module '%s' successfully loaded", path); return 0; }
/* usage: ModuleOrder mod1 mod2 ... modN */ MODRET set_moduleorder(cmd_rec *cmd) { register unsigned int i; module *m, *mn, *module_list = NULL; if (cmd->argc-1 < 1) CONF_ERROR(cmd, "wrong number of parameters"); CHECK_CONF(cmd, CONF_ROOT); /* What about duplicate names in the list? * * What if the given list is longer than the one already in loaded_modules? * This will be caught by the existence check. Otherwise, the only way for * the list to be longer is if there are duplicates, which will be caught * by the duplicate check. */ /* Make sure the given module names exist. */ for (i = 1; i < cmd->argc; i++) { if (pr_module_get(cmd->argv[i]) == NULL) CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "no such module '", cmd->argv[i], "' loaded", NULL)); } /* Make sure there are no duplicate module names in the list. */ for (i = 1; i < cmd->argc; i++) { register unsigned int j; for (j = i + 1; j < cmd->argc; j++) { if (strcmp(cmd->argv[i], cmd->argv[j]) == 0) { char ibuf[4], jbuf[4]; snprintf(ibuf, sizeof(ibuf), "%u", i); ibuf[sizeof(ibuf)-1] = '\0'; snprintf(jbuf, sizeof(jbuf), "%u", j); jbuf[sizeof(jbuf)-1] = '\0'; CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "duplicate module name '", cmd->argv[i], "' as parameters ", ibuf, " and ", jbuf, NULL)); } } } pr_log_debug(DEBUG4, "%s: reordering modules", cmd->argv[0]); for (i = 1; i < cmd->argc; i++) { m = pr_module_get(cmd->argv[i]); if (module_list) { m->next = module_list; module_list->prev = m; module_list = m; } else module_list = m; } /* Now, unload all the modules in the loaded_modules list, then load * the modules in our module_list. */ for (m = loaded_modules; m;) { mn = m->next; if (pr_module_unload(m) < 0) { pr_log_debug(DEBUG0, "%s: error unloading module 'mod_%s.c': %s", cmd->argv[0], m->name, strerror(errno)); } m = mn; } for (m = module_list; m; m = m->next) { if (pr_module_load(m) < 0) { pr_log_debug(DEBUG0, "%s: error loading module 'mod_%s.c': %s", cmd->argv[0], m->name, strerror(errno)); exit(1); } } pr_log_pri(PR_LOG_NOTICE, "module order is now:"); for (m = loaded_modules; m; m = m->next) { pr_log_pri(PR_LOG_NOTICE, " mod_%s.c", m->name); } return PR_HANDLED(cmd); }