static void dynmasq_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_dynmasq.c", (const char *) event_data) == 0) { pr_event_unregister(&dynmasq_module, NULL, NULL); # ifdef PR_USE_CTRLS /* Unregister any control actions. */ pr_ctrls_unregister(&dynmasq_module, "dynmasq"); destroy_pool(dynmasq_act_pool); dynmasq_act_pool = NULL; # endif /* PR_USE_CTRLS */ pr_timer_remove(dynmasq_timer_id, &dynmasq_module); dynmasq_timer_id = -1; } }
char *pr_ctrls_unregister_module_actions(ctrls_acttab_t *acttab, char **actions, module *mod) { register unsigned int i = 0; /* First, sanity check the given actions against the actions supported by * this module. */ for (i = 0; actions[i]; i++) { register unsigned int j = 0; unsigned char valid_action = FALSE; for (j = 0; acttab[j].act_action; j++) { if (strcmp(actions[i], acttab[j].act_action) == 0) { valid_action = TRUE; break; } } if (!valid_action) return actions[i]; } /* Next, iterate through both lists again, looking for actions of the * module _not_ in the given list. */ for (i = 0; acttab[i].act_action; i++) { register unsigned int j = 0; unsigned char have_action = FALSE; for (j = 0; actions[j]; j++) { if (strcmp(acttab[i].act_action, actions[j]) == 0) { have_action = TRUE; break; } } if (have_action) { pr_trace_msg(trace_channel, 4, "mod_%s.c: removing '%s' control", mod->name, acttab[i].act_action); pr_ctrls_unregister(mod, acttab[i].act_action); destroy_pool(acttab[i].act_acl->acl_pool); } } return NULL; }
int pr_module_unload(module *m) { char buf[256]; if (m == NULL || m->name == NULL) { errno = EINVAL; return -1; } /* Make sure this module has been loaded. We can't unload a module that * has not been loaded, now can we? */ memset(buf, '\0', sizeof(buf)); snprintf(buf, sizeof(buf), "mod_%s.c", m->name); buf[sizeof(buf)-1] = '\0'; if (pr_module_get(buf) == NULL) { errno = ENOENT; return -1; } /* Generate an event. */ pr_event_generate("core.module-unload", buf); /* Remove the module from the loaded_modules list. */ if (m->prev) { m->prev->next = m->next; } else { /* This module is the start of the loaded_modules list (prev is NULL), * so we need to update that pointer, too. */ loaded_modules = m->next; } if (m->next) m->next->prev = m->prev; m->prev = m->next = NULL; /* Remove the module's config, cmd, and auth tables. */ if (m->conftable) { conftable *conftab; for (conftab = m->conftable; conftab->directive; conftab++) { pr_stash_remove_symbol(PR_SYM_CONF, conftab->directive, conftab->m); } } if (m->cmdtable) { cmdtable *cmdtab; for (cmdtab = m->cmdtable; cmdtab->command; cmdtab++) { if (cmdtab->cmd_type == HOOK) { pr_stash_remove_symbol(PR_SYM_HOOK, cmdtab->command, cmdtab->m); } else { /* All other cmd_types are for CMDs: PRE_CMD, CMD, POST_CMD, etc. */ pr_stash_remove_symbol(PR_SYM_CMD, cmdtab->command, cmdtab->m); } } } if (m->authtable) { authtable *authtab; for (authtab = m->authtable; authtab->name; authtab++) { pr_stash_remove_symbol(PR_SYM_AUTH, authtab->name, authtab->m); } } /* Remove any callbacks that the module may have registered, i.e.: * * ctrls * events * timers * * Ideally we would also automatically unregister other callbacks that * the module may have registered, such as FSIO, NetIO, variables, and * response handlers. However, these APIs do not yet allow for * removal of all callbacks for a given module. */ #ifdef PR_USE_CTRLS pr_ctrls_unregister(m, NULL); #endif /* PR_USE_CTRLS */ pr_event_unregister(m, NULL, NULL); pr_timer_remove(-1, m); return 0; }