diff --git a/src/plugin.c b/src/plugin.c index a9281e0..351dfe3 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -2,6 +2,19 @@ #include "plugin.h" #include "log.h" +static plugin* plugin_new(const gchar *name) { + plugin *p = g_slice_new0(plugin); + p->name = name; + return p; +} + +void plugin_free(plugin *p) { + if (!p) return; + + 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); } @@ -65,3 +78,60 @@ void release_option(server *srv, option_set *mark) { /** Does not free the optio } mark->value = NULL; } + +gboolean plugin_register(server *srv, const gchar *name, PluginInit init) { + plugin *p; + + if (!init) { + ERROR(srv, "Module '%s' needs an init function", name); + return FALSE; + } + + if (g_hash_table_lookup(srv->plugins, name)) { + ERROR(srv, "Module '%s' already registered", name); + return FALSE; + } + + p = plugin_new(name); + g_hash_table_insert(srv->plugins, (gchar*) p->name, p); + + init(srv, p); + + if (p->options) { + size_t i; + 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))) { + ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'", + po->key, + so->p ? so->p->name : "", + p->name); + break; + } + so = g_slice_new0(server_option); + so->type = po->type; + so->parse_option = po->parse_option; + so->free_option = po->free_option; + 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); + } + + 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); + } + g_hash_table_remove(srv->plugins, p->name); + if (p->free) p->free(srv, p); + plugin_free(p); + return FALSE; + } + } + + return TRUE; +} diff --git a/src/plugin.h b/src/plugin.h index 030a216..a92ab65 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -28,13 +28,13 @@ typedef void (*PluginFreeOption) (server *srv, gpointer p_d, size_t ndx, gp struct plugin { size_t version; - const char *name; /**< name of the plugin */ + const gchar *name; /**< name of the plugin */ gpointer data; /**< private plugin data */ - PluginFree *free; /**< called before plugin is unloaded */ + PluginFree free; /**< called before plugin is unloaded */ - plugin_option *options; + const plugin_option *options; }; struct plugin_option { @@ -61,7 +61,8 @@ struct server_option { option_type type; }; -LI_API gboolean plugin_register(server *srv, const gchar *name, PluginInit *init); +LI_API void plugin_free(plugin *p); +LI_API gboolean plugin_register(server *srv, const gchar *name, PluginInit init); LI_API gboolean parse_option(server *srv, const char *key, option *opt, option_set *mark); LI_API void release_option(server *srv, option_set *mark); /**< Does not free the option_set memory */ diff --git a/src/server.h b/src/server.h index 5ed970a..d1de9b4 100644 --- a/src/server.h +++ b/src/server.h @@ -24,7 +24,6 @@ struct server { }; - server* server_new(); void server_free(server* srv);