|
|
|
@ -8,25 +8,69 @@ static plugin* plugin_new(const gchar *name) {
|
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void plugin_free(plugin *p) { |
|
|
|
|
static void plugin_free_options(server *srv, plugin *p) { |
|
|
|
|
size_t i; |
|
|
|
|
const plugin_option *po; |
|
|
|
|
server_option *so; |
|
|
|
|
|
|
|
|
|
if (!p->options) return; |
|
|
|
|
for (i = 0; (po = &p->options[i])->name; i++) { |
|
|
|
|
if (NULL == (so = g_hash_table_lookup(srv->options, po->name))) break; |
|
|
|
|
if (so->p != p) break; |
|
|
|
|
g_hash_table_remove(srv->options, po->name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void plugin_free_actions(server *srv, plugin *p) { |
|
|
|
|
size_t i; |
|
|
|
|
const plugin_action *pa; |
|
|
|
|
server_action *sa; |
|
|
|
|
|
|
|
|
|
if (!p->actions) return; |
|
|
|
|
for (i = 0; (pa = &p->actions[i])->name; i++) { |
|
|
|
|
if (NULL == (sa = g_hash_table_lookup(srv->actions, pa->name))) break; |
|
|
|
|
if (sa->p != p) break; |
|
|
|
|
g_hash_table_remove(srv->actions, pa->name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void plugin_free_setups(server *srv, plugin *p) { |
|
|
|
|
size_t i; |
|
|
|
|
const plugin_setup *ps; |
|
|
|
|
server_setup *ss; |
|
|
|
|
|
|
|
|
|
if (!p->setups) return; |
|
|
|
|
for (i = 0; (ps = &p->setups[i])->name; i++) { |
|
|
|
|
if (NULL == (ss = g_hash_table_lookup(srv->setups, ps->name))) break; |
|
|
|
|
if (ss->p != p) break; |
|
|
|
|
g_hash_table_remove(srv->setups, ps->name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void plugin_free(server *srv, plugin *p) { |
|
|
|
|
if (!p) return; |
|
|
|
|
|
|
|
|
|
g_hash_table_remove(srv->plugins, p->name); |
|
|
|
|
plugin_free_options(srv, p); |
|
|
|
|
plugin_free_actions(srv, p); |
|
|
|
|
plugin_free_setups(srv, p); |
|
|
|
|
|
|
|
|
|
g_slice_free(plugin, p); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static server_option* find_option(server *srv, const char *key) { |
|
|
|
|
return (server_option*) g_hash_table_lookup(srv->options, key); |
|
|
|
|
static server_option* find_option(server *srv, const char *name) { |
|
|
|
|
return (server_option*) g_hash_table_lookup(srv->options, name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gboolean parse_option(server *srv, const char *key, option *opt, option_set *mark) { |
|
|
|
|
gboolean parse_option(server *srv, const char *name, option *opt, option_set *mark) { |
|
|
|
|
server_option *sopt; |
|
|
|
|
|
|
|
|
|
if (!srv || !key || !mark) return FALSE; |
|
|
|
|
if (!srv || !name || !mark) return FALSE; |
|
|
|
|
|
|
|
|
|
sopt = find_option(srv, key); |
|
|
|
|
sopt = find_option(srv, name); |
|
|
|
|
if (!sopt) { |
|
|
|
|
ERROR(srv, "Unknown option '%s'", key); |
|
|
|
|
ERROR(srv, "Unknown option '%s'", name); |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -102,13 +146,14 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) {
|
|
|
|
|
server_option *so; |
|
|
|
|
const plugin_option *po; |
|
|
|
|
|
|
|
|
|
for (i = 0; (po = &p->options[i])->key; i++) { |
|
|
|
|
if (NULL != (so = (server_option*)g_hash_table_lookup(srv->options, po->key))) { |
|
|
|
|
for (i = 0; (po = &p->options[i])->name; i++) { |
|
|
|
|
if (NULL != (so = (server_option*)g_hash_table_lookup(srv->options, po->name))) { |
|
|
|
|
ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'", |
|
|
|
|
po->key, |
|
|
|
|
po->name, |
|
|
|
|
so->p ? so->p->name : "<none>", |
|
|
|
|
p->name); |
|
|
|
|
break; |
|
|
|
|
plugin_free(srv, p); |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
so = g_slice_new0(server_option); |
|
|
|
|
so->type = po->type; |
|
|
|
@ -117,19 +162,49 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) {
|
|
|
|
|
so->index = g_hash_table_size(srv->options); |
|
|
|
|
so->module_index = i; |
|
|
|
|
so->p = p; |
|
|
|
|
g_hash_table_insert(srv->options, (gchar*) po->key, so); |
|
|
|
|
g_hash_table_insert(srv->options, (gchar*) po->name, so); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (po->key) { |
|
|
|
|
while (i-- > 0) { |
|
|
|
|
po = &p->options[i]; |
|
|
|
|
g_slice_free(server_option, g_hash_table_lookup(srv->options, po->key)); |
|
|
|
|
g_hash_table_remove(srv->options, po->key); |
|
|
|
|
if (p->actions) { |
|
|
|
|
size_t i; |
|
|
|
|
server_action *sa; |
|
|
|
|
const plugin_action *pa; |
|
|
|
|
|
|
|
|
|
for (i = 0; (pa = &p->actions[i])->name; i++) { |
|
|
|
|
if (NULL != (sa = (server_action*)g_hash_table_lookup(srv->actions, pa->name))) { |
|
|
|
|
ERROR(srv, "Action '%s' already registered by plugin '%s', unloading '%s'", |
|
|
|
|
pa->name, |
|
|
|
|
sa->p ? sa->p->name : "<none>", |
|
|
|
|
p->name); |
|
|
|
|
plugin_free(srv, p); |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
g_hash_table_remove(srv->plugins, p->name); |
|
|
|
|
if (p->free) p->free(srv, p); |
|
|
|
|
plugin_free(p); |
|
|
|
|
return FALSE; |
|
|
|
|
sa = g_slice_new0(server_action); |
|
|
|
|
sa->create_action = pa->create_action; |
|
|
|
|
sa->p = p; |
|
|
|
|
g_hash_table_insert(srv->actions, (gchar*) pa->name, sa); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (p->setups) { |
|
|
|
|
size_t i; |
|
|
|
|
server_setup *ss; |
|
|
|
|
const plugin_setup *ps; |
|
|
|
|
|
|
|
|
|
for (i = 0; (ps = &p->setups[i])->name; i++) { |
|
|
|
|
if (NULL != (ss = (server_setup*)g_hash_table_lookup(srv->setups, ps->name))) { |
|
|
|
|
ERROR(srv, "Setup '%s' already registered by plugin '%s', unloading '%s'", |
|
|
|
|
ps->name, |
|
|
|
|
ss->p ? ss->p->name : "<none>", |
|
|
|
|
p->name); |
|
|
|
|
plugin_free(srv, p); |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
ss = g_slice_new0(server_setup); |
|
|
|
|
ss->setup = ps->setup; |
|
|
|
|
ss->p = p; |
|
|
|
|
g_hash_table_insert(srv->setups, (gchar*) ps->name, ss); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|