improve the config module futher, now the module_desc interface uses structured config_value's
--- a/src/config.c Tue Mar 31 23:35:24 2009 +0300
+++ b/src/config.c Tue Mar 31 23:36:05 2009 +0300
@@ -1,21 +1,140 @@
#include "config.h"
#include <string.h>
+#include <assert.h>
-err_t config_apply (struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err)
+const struct config_option* config_lookup (const struct config_option *options, const char *name, struct error_info *err)
{
- struct config_option *option;
+ const struct config_option *option;
// find the matching config opt
for (option = options; option->name && option->type; option++) {
if (strcmp(option->name, name) == 0)
+ return option;
+ }
+
+ // not found
+ SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown configuration option");
+
+ return NULL;
+}
+
+/**
+ * Parse a raw value for a CONFIG_IRC_CHAN into an irc_chan
+ */
+static struct irc_chan* config_parse_irc_chan (struct nexus *nexus, char *raw_value, struct error_info *err)
+{
+ const char *network, *channel;
+ struct irc_chan *chan;
+
+ // parse required args
+ if ((network = strsep(&raw_value, "/")) == NULL)
+ JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid <network> for CONFIG_IRC_CHAN value");
+
+ if ((channel = strsep(&raw_value, "/")) == NULL)
+ JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid <channel> for CONFIG_IRC_CHAN value");
+
+ // extraneous stuff?
+ if (raw_value)
+ JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "trailing data for CONFIG_IRC_CHAN value");
+
+ // get the channel?
+ if ((chan = irc_client_get_chan(nexus->client, network, channel)) == NULL)
+ JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown network/channel name for CONFIG_IRC_CHAN value");
+
+ // ok
+ return chan;
+
+error:
+ return NULL;
+}
+
+err_t config_parse (const struct config_option *option, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err)
+{
+ // parse the value
+ switch (option->type) {
+ case CONFIG_STRING:
+ // simple!
+ value->string = raw_value;
break;
+
+ case CONFIG_IRC_CHAN:
+ // parse the value
+ if (!(value->irc_chan = config_parse_irc_chan(nexus, raw_value, err)))
+ return ERROR_CODE(err);
+
+ break;
+
+ default:
+ NOT_REACHED();
}
+ // copy the type
+ value->type = option->type;
+
+ // ok
+ return SUCCESS;
+}
+
+err_t config_apply_opt (const struct config_option *option, void *ctx, const struct config_value *value, struct error_info *err)
+{
+ // wrong type?
+ if (option->type != value->type)
+ // XXX: info about type names
+ return SET_ERROR(err, ERR_CONFIG_TYPE);
+
+ // null?
+ if (!value)
+ RETURN_SET_ERROR_STR(err, ERR_CONFIG_REQUIRED, option->name);
+
+ // call the handler
+ switch (option->type) {
+ case CONFIG_STRING: return option->func.string(ctx, value->string, err);
+ case CONFIG_IRC_CHAN: return option->func.irc_chan(ctx, value->irc_chan, err);
+ default: NOT_REACHED();
+ }
+}
+
+err_t config_apply (const struct config_option *options, void *ctx, const char *name, const struct config_value *value, struct error_info *err)
+{
+ const struct config_option *option;
+
// no matching option found?
- if (!option)
- RETURN_SET_ERROR_STR(err, ERR_CONFIG_NAME, name);
+ if (!(option = config_lookup(options, name, err)))
+ return ERROR_CODE(err);
+
+ // apply it
+ return config_apply_opt(option, ctx, value, err);
+}
- // call the handler
- return option->func(ctx, value, err);
+err_t config_apply_string (const struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err)
+{
+ struct config_value conf_value = { CONFIG_STRING, { .string = value } };
+
+ return config_apply(options, ctx, name, &conf_value, err);
}
+
+err_t config_apply_irc_chan (const struct config_option *options, void *ctx, const char *name, struct irc_chan *value, struct error_info *err)
+{
+ struct config_value conf_value = { CONFIG_STRING, { .irc_chan = value } };
+
+ return config_apply(options, ctx, name, &conf_value, err);
+}
+
+err_t config_apply_raw (const struct config_option *options, struct nexus *nexus, void *ctx, const char *name, char *raw_value, struct error_info *err)
+{
+ const struct config_option *option;
+ struct config_value value;
+
+ // no matching option found?
+ if (!(option = config_lookup(options, name, err)))
+ return ERROR_CODE(err);
+
+ // parse it
+ if (config_parse(option, nexus, &value, raw_value, err))
+ return ERROR_CODE(err);
+
+ // apply it
+ return config_apply_opt(option, ctx, &value, err);
+}
+
--- a/src/config.h Tue Mar 31 23:35:24 2009 +0300
+++ b/src/config.h Tue Mar 31 23:36:05 2009 +0300
@@ -16,6 +16,26 @@
/** A plain NUL-terminated string */
CONFIG_STRING,
+
+ /** An IRC channel */
+ CONFIG_IRC_CHAN,
+};
+
+/**
+ * Structure to hold a value as defined by config_type
+ */
+struct config_value {
+ /** The type of the value */
+ enum config_type type;
+
+ /** The typed value */
+ union {
+ /** Value for CONFIG_STRING */
+ char *string;
+
+ /** Value for CONFIG_IRC_CHAN */
+ struct irc_chan *irc_chan;
+ };
};
/**
@@ -25,11 +45,14 @@
/** The name of the config option */
const char *name;
- /** The type of the value, XXX: unused */
+ /** The type of the value expected */
enum config_type type;
- /** The value handler func */
- err_t (*func) (void *ctx, char *value, struct error_info *err);
+ /** The value handler func, by type */
+ union {
+ err_t (*string) (void *ctx, char *value, struct error_info *err);
+ err_t (*irc_chan) (void *ctx, struct irc_chan *chan, struct error_info *err);
+ } func;
/** The value description */
const char *description;
@@ -38,11 +61,102 @@
const char *help;
};
+#define CONFIG_OPT_STRING(name, func, desc, help) \
+ { name, CONFIG_STRING, { .string = func }, desc, help }
+
+#define CONFIG_OPT_IRC_CHAN(name, func, desc, help) \
+ { name, CONFIG_IRC_CHAN, { .irc_chan = func }, desc, help }
+
+#define CONFIG_OPT_END \
+ { NULL, CONFIG_INVALID, { NULL }, NULL, NULL }
+
/**
- * Apply a configuration name/value to an array of config_option's.
+ * Lookup a config option by name.
*
- * This finds the appropriate config_option and calls its func.
+ * @param options a CONFIG_OPT_END-terminated array of config_option's
+ * @param name the config_option::name to look up
+ * @param err returned error info if not found
+ * @return a direct pointer to the config_option if found
*/
-err_t config_apply (struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err);
+const struct config_option* config_lookup (const struct config_option *options, const char *name, struct error_info *err);
+
+// XXX: move this into nexus
+#include "nexus.h"
+/**
+ * Parse a raw value into a suitable configuration value, based on the config option type.
+ *
+ * Since this needs to access the application state, you need to pass in the nexus as an argument.
+ *
+ * Formats supported:
+ * CONFIG_IRC_CHAN - uses a '<network>/<channel>' format and irc_client_get_chan
+ *
+ * @param option the option to parse the value for, use config_lookup to find it
+ * @param nexus the application state
+ * @param value the returned value, if succesfull
+ * @param raw_value the raw value to parse based on the type
+ * @param err returned error info
+ */
+err_t config_parse (const struct config_option *option, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err);
+
+/**
+ * Apply a parsed configuration value to the given option.
+ *
+ * The config option handlers take a context argument; the value of this depends on the implementor of the config_option.
+ *
+ * @param option the option to apply
+ * @param ctx the context pointer for the option handler
+ * @param value the parsed value
+ * @param err returned error info
+ */
+err_t config_apply_opt (const struct config_option *option, void *ctx, const struct config_value *value, struct error_info *err);
+
+/**
+ * Apply a parsed configuration value for the named config opt.
+ *
+ * @param options a CONFIG_OPT_END-terminated array of config_option's
+ * @param ctx the context pointer for the option handler
+ * @param name the config_option::name to look up
+ * @param value the parsed value
+ * @param err returned error info
+ */
+err_t config_apply (const struct config_option *options, void *ctx, const char *name, const struct config_value *value, struct error_info *err);
+
+/**
+ * Apply a string value for the named config opt.
+ *
+ * @param options a CONFIG_OPT_END-terminated array of config_option's
+ * @param ctx the context pointer for the option handler
+ * @param name the config_option::name to look up
+ * @param value the string value
+ * @param err returned error info
+ */
+err_t config_apply_string (const struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err);
+
+/**
+ * Apply an irc_chan value for the named config opt.
+ *
+ * @param options a CONFIG_OPT_END-terminated array of config_option's
+ * @param ctx the context pointer for the option handler
+ * @param name the config_option::name to look up
+ * @param value the irc_chan value
+ * @param err returned error info
+ */
+err_t config_apply_irc_chan (const struct config_option *options, void *ctx, const char *name, struct irc_chan *value, struct error_info *err);
+
+/**
+ * Parse and apply a configuration value for the named config opt.
+ *
+ * See config_parse() for more info.
+ *
+ * @param options a CONFIG_OPT_END-terminated array of config_option's
+ * @param nexus the application state
+ * @param ctx the context pointer for the option handler
+ * @param name the config_option::name to look up
+ * @param raw_value the raw value to parse
+ * @param err returned error info
+ *
+ * @see config_parse
+ */
+err_t config_apply_raw (const struct config_option *options, struct nexus *nexus, void *ctx, const char *name, char *raw_value, struct error_info *err);
#endif
--- a/src/error.c Tue Mar 31 23:35:24 2009 +0300
+++ b/src/error.c Tue Mar 31 23:36:05 2009 +0300
@@ -19,7 +19,6 @@
{ ERR_EVENT_ADD, "event_add", ERR_EXTRA_NONE },
{ ERR_EVSQL_NEW_PQ, "evsql_new_pq", ERR_EXTRA_NONE },
{ ERR_EVSQL_QUERY_EXEC, "evsql_query_exec", ERR_EXTRA_NONE },
- { ERR_CONFIG_NAME, "no matching config name", ERR_EXTRA_STR },
{ ERR_CMD_OPT, "argv", ERR_EXTRA_STR },
{ _ERR_INVALID, NULL, 0 }
@@ -45,18 +44,44 @@
{ ERR_GNUTLS_RECORD_GET_DIRECTION, "gnutls_record_get_direction", ERR_EXTRA_GNUTLS },
{ _ERR_INVALID, NULL, 0 }
-}, _irc_proto_error_desc[] = {
+}, _irc_error_desc[] = {
{ ERR_LINE_TOO_LONG, "IRC line is too long", ERR_EXTRA_NONE },
{ ERR_LINE_INVALID_TOKEN, "Illegal token value for IRC line", ERR_EXTRA_NONE },
{ ERR_INVALID_NM, "Invalid nickmask", ERR_EXTRA_NONE },
{ ERR_INVALID_NICK_LENGTH, "Nickname is too long", ERR_EXTRA_NONE },
+
+ // extra: the name of the invalid field
+ { ERR_IRC_NET_INFO, "invalid irc_net_info", ERR_EXTRA_STR },
+ { ERR_IRC_NET_STATE, "invalid irc_net state for operation", ERR_EXTRA_NONE },
+ { ERR_IRC_CHAN_STATE, "invalid irc_chan state for operation", ERR_EXTRA_NONE },
+
{ _ERR_INVALID, NULL, 0 }
+
+}, _config_error_desc[] = {
+ // extra: the (unknown) config field name
+ { ERR_CONFIG_NAME, "no matching config name", ERR_EXTRA_STR },
+
+ // XXX: extra: the mismatching types
+ { ERR_CONFIG_TYPE, "wrong config type", ERR_EXTRA_NONE },
+
+ // extra: the name of the field with missing value
+ { ERR_CONFIG_REQUIRED, "missing required value", ERR_EXTRA_STR },
+
+ { _ERR_INVALID, NULL, 0 }
+
}, _module_error_desc[] = {
{ ERR_MODULE_OPEN, "module dlopen() failed", ERR_EXTRA_STR },
{ ERR_MODULE_NAME, "invalid module name", ERR_EXTRA_NONE },
{ ERR_MODULE_INIT_FUNC, "invalid module init func", ERR_EXTRA_STR },
{ ERR_MODULE_CONF, "module_conf", ERR_EXTRA_STR },
{ _ERR_INVALID, NULL, 0 }
+
+}, _lua_error_desc[] = {
+ { ERR_LUA_MEM, "lua: out of memory", ERR_EXTRA_NONE },
+ { ERR_LUA_SYNTAX, "lua: syntax error", ERR_EXTRA_NONE },
+ { ERR_LUA_RUN, "lua: runtime error", ERR_EXTRA_NONE },
+ { ERR_LUA_ERR, "lua: error handling error", ERR_EXTRA_NONE },
+ { _ERR_INVALID, NULL, 0 }
};
/**
@@ -66,8 +91,9 @@
_core_error_desc,
_sock_error_desc,
_sock_gnutls_error_desc,
- _irc_proto_error_desc,
+ _irc_error_desc,
_module_error_desc,
+ _lua_error_desc,
NULL
};
--- a/src/error.h Tue Mar 31 23:35:24 2009 +0300
+++ b/src/error.h Tue Mar 31 23:36:05 2009 +0300
@@ -90,6 +90,8 @@
/** config errors */
_ERR_CONFIG = 0x000b00,
ERR_CONFIG_NAME,
+ ERR_CONFIG_TYPE,
+ ERR_CONFIG_REQUIRED,
/** lua errors */
_ERR_LUA = 0x000c00,
@@ -209,4 +211,9 @@
#define JUMP_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); goto error; } while (0)
#define JUMP_SET_ERROR_STR(err_info_ptr, err_code, err_str) do { _SET_ERROR_STR(err_info_ptr, err_code, err_str); goto error; } while (0)
+/**
+ * Macro used to mark code segments that should never be executed (e.g. switch-default), kind of like assert
+ */
+#define NOT_REACHED() assert(false)
+
#endif
--- a/src/irc_client.c Tue Mar 31 23:35:24 2009 +0300
+++ b/src/irc_client.c Tue Mar 31 23:36:05 2009 +0300
@@ -58,18 +58,28 @@
};
// combine _net_info and defaults to get net_info
- if (
- _net_info->raw_sock
- || (net_info.network = _net_info->network) == NULL
- || (net_info.hostname = _net_info->hostname) == NULL
- || (net_info.service = (_net_info->service ? _net_info->service : (
+ if (_net_info->raw_sock)
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "raw_sock");
+
+ if ((net_info.network = _net_info->network) == NULL)
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "network");
+
+ if ((net_info.hostname = _net_info->hostname) == NULL)
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "hostname");
+
+ if ((net_info.service = (_net_info->service ? _net_info->service : (
_net_info->use_ssl ? client->defaults.service_ssl : client->defaults.service
- ))) == NULL
- || APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, nickname)
- || APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, username)
- || APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, realname)
- )
- return SET_ERROR(err, ERR_IRC_NET_INFO);
+ ))) == NULL)
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "service");
+
+ if (APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, nickname))
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "nickname");
+
+ if (APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, username))
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "username");
+
+ if (APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, realname))
+ RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "realname");
// create the new irc_chan struct
if (irc_net_create(&net, &net_info, err))
--- a/src/irc_log.c Tue Mar 31 23:35:24 2009 +0300
+++ b/src/irc_log.c Tue Mar 31 23:36:05 2009 +0300
@@ -440,31 +440,14 @@
* Fails if the value is invalid, we don't have a database connected, the channel doesn't exist, adding our command
* handlers/callbacks fails, or sending the initial INSERT-OPEN query fails.
*/
-static err_t irc_log_conf_channel (void *_ctx, char *value, struct error_info *err)
+static err_t irc_log_conf_channel (void *_ctx, struct irc_chan *chan, struct error_info *err)
{
struct irc_log_ctx *ctx = _ctx;
- const char *network, *channel;
- struct irc_chan *chan;
- // parse required args
- if ((network = strsep(&value, ":")) == NULL)
- RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid <network> for irc_log.channel");
-
- if ((channel = strsep(&value, ":")) == NULL)
- RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid <channel> for irc_log.channel");
-
- // extraneous stuff?
- if (value)
- RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "trailing data for irc_log.channel");
-
// have a db configured?
if (!ctx->db)
RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "irc_log.channel used without any irc_log.db_info");
- // get the channel?
- if ((chan = irc_client_get_chan(ctx->nexus->client, network, channel)) == NULL)
- RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown channel name");
-
// begin logging it
if (irc_log_chan(ctx, chan, err))
return ERROR_CODE(err);
@@ -477,25 +460,11 @@
* Our configuration options
*/
struct config_option irc_log_config_options[] = {
- { "db_info", CONFIG_STRING, &irc_log_conf_db_info, "[<key>=<value> [...]]", "set database connection info, see libpq docs" },
- { "channel", CONFIG_STRING, &irc_log_conf_channel, "<network>:<channel>", "log the given channel" },
- { NULL, 0, NULL, NULL, NULL }
-};
+ CONFIG_OPT_STRING( "db_info", &irc_log_conf_db_info, "[<key>=<value> [...]]", "set database connection info, see libpq docs" ),
+ CONFIG_OPT_IRC_CHAN( "channel", &irc_log_conf_channel, "<channel>", "log the given channel" ),
-/**
- * Set a config option
- */
-static err_t irc_log_conf (void *_ctx, const char *name, char *value, struct error_info *err)
-{
- struct irc_log_ctx *ctx = _ctx;
-
- // wrong state
- if (ctx->unloading)
- RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module is being unloaded");
-
- // apply it
- return config_apply(irc_log_config_options, ctx, name, value, err);
-}
+ CONFIG_OPT_END
+};
/**
* Deinitialize, logging CLOSE events for all channels, and removing any hooks we've added
@@ -520,9 +489,8 @@
/**
* The module function table
*/
-struct module_funcs irc_log_funcs = {
+struct module_desc irc_log_module = {
.init = &irc_log_init,
- .conf = &irc_log_conf,
.config_options = irc_log_config_options,
.unload = &irc_log_unload,
};
--- a/src/irc_proto.h Tue Mar 31 23:35:24 2009 +0300
+++ b/src/irc_proto.h Tue Mar 31 23:36:05 2009 +0300
@@ -10,6 +10,16 @@
#include <stddef.h>
/**
+ * Default TCP port for normal connections
+ */
+#define IRC_PORT "6667"
+
+/**
+ * Default TCP port for SSL connections
+ */
+#define IRC_SSL_PORT "6697"
+
+/**
* Maximum length of an IRC nickname including terminating NUL.
*/
#define IRC_NICK_MAX (30 + 1)
--- a/src/module.c Tue Mar 31 23:35:24 2009 +0300
+++ b/src/module.c Tue Mar 31 23:36:05 2009 +0300
@@ -72,11 +72,11 @@
JUMP_SET_ERROR_STR(err, ERR_MODULE_OPEN, dlerror());
// load the funcs symbol
- if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->funcs, "funcs")))
+ if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->desc, "module")))
JUMP_SET_ERROR_STR(err, ERROR_CODE(err), dlerror());
// call the init func
- if ((module->funcs->init(modules->nexus, &module->ctx, err)))
+ if ((module->desc->init(modules->nexus, &module->ctx, err)))
goto error;
// add to modules list
@@ -110,19 +110,52 @@
return NULL;
}
-err_t module_conf (struct module *module, const char *name, char *value, struct error_info *err)
+err_t module_conf_raw (struct module *module, const char *name, char *value, struct error_info *err)
{
- // call the conf func
- return module->funcs->conf(module->ctx, name, value, err);
+ if (!module->desc->config_options)
+ RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module does not have any config options");
+
+ // wrong state
+ if (module->unloading)
+ RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module is being unloaded");
+
+ // parse/apply using the module's stuff
+ return config_apply_raw(module->desc->config_options, module->modules->nexus, module->ctx, name, value, err);
+}
+
+const struct config_option* module_conf_lookup (struct module *module, const char *name, struct error_info *err)
+{
+ if (!module->desc->config_options)
+ JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "module does not have any config options");
+
+ // direct lookup
+ return config_lookup(module->desc->config_options, name, err);
+
+error:
+ return NULL;
+}
+
+err_t module_conf (struct module *module, const struct config_option *opt, const struct config_value *value, struct error_info *err)
+{
+ // wrong state
+ if (module->unloading)
+ RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module is being unloaded");
+
+ // apply with the module's ctx
+ return config_apply_opt(opt, module->ctx, value, err);
}
err_t module_unload (struct module *module)
{
err_t err;
-
+
// invoke the unload func
- if ((err = module->funcs->unload(module->ctx)))
+ if ((err = module->desc->unload(module->ctx)))
return err;
+
+ // update status
+ // XXX: before or after?
+ module->unloading = true;
// ok
return SUCCESS;
--- a/src/module.h Tue Mar 31 23:35:24 2009 +0300
+++ b/src/module.h Tue Mar 31 23:36:05 2009 +0300
@@ -28,12 +28,10 @@
};
/**
- * A table of (function) pointers defining a module's behaviour. This is dynamically resolved from the module DSO
- * using the "<mod_name>_funcs" symbol.
- *
- * XXX: this also includes non-functions now...
+ * A table of (function/other) pointers defining a module's behaviour. This is dynamically resolved from the module DSO
+ * using the "<mod_name>_module" symbol.
*/
-struct module_funcs {
+struct module_desc {
/**
* Initialize the module, returning an opaque context pointer that is stored in the module state, and supplied for
* subsequent calls. The supplied nexus arg can be used to access the global state.
@@ -45,23 +43,10 @@
err_t (*init) (struct nexus *nexus, void **ctx_ptr, struct error_info *err);
/**
- * Set a configuration option with the given name and value, given by the user. Configuration settings are not
- * regarded as unique-per-name, but rather, several invocations of 'conf' with the same name and different values
- * could set up a multitude of things.
- *
- * The given value is either a NUL-terminated string value (which may be mutated, using e.g. strsep), or NULL if
- * no value was given (flag option).
+ * A module may define a set of available configuration parameters for use by module_conf, by setting this to an
+ * array of config_option's.
*
- * @param ctx the module's context pointer as returned by init
- * @param name the name of the configuration setting
- * @param value the value of the configuration setting
- * @param err returned error info
- */
- err_t (*conf) (void *ctx, const char *name, char *value, struct error_info *err);
-
- /**
- * Optionally, a module may also provide some kind of list of available configuration parameters, by setting this
- * to a pointer to an array of those.
+ * The handler functions will recieve the module's context pointer as their ctx argument.
*/
const struct config_option *config_options;
@@ -86,8 +71,8 @@
/** The dlopen handle */
void *handle;
- /** The resolved function table */
- struct module_funcs *funcs;
+ /** The module entry point */
+ struct module_desc *desc;
/** The module context object */
void *ctx;
@@ -95,6 +80,11 @@
/** Reference back to modules struct used to load this module */
struct modules *modules;
+ /**
+ * Is the module currently being unloaded?
+ */
+ bool unloading;
+
/** Our entry in the list of modules */
TAILQ_ENTRY(module) modules_list;
};
@@ -164,9 +154,19 @@
struct module* module_get (struct modules *modules, const char *name);
/**
- * Set a module configuration option
+ * Look up a module configuration option by name
*/
-err_t module_conf (struct module *module, const char *name, char *value, struct error_info *err);
+const struct config_option* module_conf_lookup (struct module *module, const char *name, struct error_info *err);
+
+/**
+ * Apply a module configuration option using a structured value
+ */
+err_t module_conf (struct module *module, const struct config_option *opt, const struct config_value *value, struct error_info *err);
+
+/**
+ * Set a module configuration option using a raw value
+ */
+err_t module_conf_raw (struct module *module, const char *name, char *value, struct error_info *err);
/**
* Unload a module. This means calling its 'unload' func, which will then go about shutting down the module. This might
--- a/src/nexus.c Tue Mar 31 23:35:24 2009 +0300
+++ b/src/nexus.c Tue Mar 31 23:36:05 2009 +0300
@@ -9,10 +9,6 @@
#include <signal.h>
#include <string.h>
-#define DEFAULT_HOST "irc.fixme.fi"
-#define DEFAULT_PORT "6667"
-#define DEFAULT_PORT_SSL "6697"
-
/**
* Command-line option codes
*/
@@ -75,10 +71,11 @@
printf("\n");
printf("%s:\n", module->info.name);
- if (module->funcs->config_options) {
+ // XXX: shouldn't be accessing directly
+ if (module->desc->config_options) {
const struct config_option *opt;
- for (opt = module->funcs->config_options; opt->name && opt->type; opt++) {
+ for (opt = module->desc->config_options; opt->name && opt->type; opt++) {
printf(" --config %s:%s:%s\t\t%s\n", module->info.name, opt->name, opt->description, opt->help);
}
@@ -96,8 +93,8 @@
{
struct irc_client_defaults defaults = {
.register_info = { NULL, NULL, NULL },
- .service = DEFAULT_PORT,
- .service_ssl = DEFAULT_PORT_SSL,
+ .service = IRC_PORT,
+ .service_ssl = IRC_SSL_PORT,
};
// parse the required fields
@@ -260,7 +257,7 @@
// do the config
log_info("applying module '%s' config name '%s' with value: %s", module->info.name, conf_name, conf_value);
- if (module_conf(module, conf_name, conf_value, err))
+ if (module_conf_raw(module, conf_name, conf_value, err))
return ERROR_CODE(err);
// ok