diff --git a/common.c b/common.c index 951055c..102cbd6 100644 --- a/common.c +++ b/common.c @@ -1131,7 +1131,6 @@ config_schema_accepts_type && config_item_type_is_string (type)) return true; return !self->default_ && type == CONFIG_ITEM_NULL; - } static bool @@ -2008,6 +2007,7 @@ config_load (struct config *self, struct config_item_ *root) subtree = config_item_object (); str_map_set (&root->value.object, module->name, subtree); } - module->loader (subtree, module->user_data); + if (module->loader) + module->loader (subtree, module->user_data); } } diff --git a/degesch.c b/degesch.c index 8cd192b..b56f36b 100644 --- a/degesch.c +++ b/degesch.c @@ -1573,18 +1573,11 @@ static struct config_schema g_config_attributes[] = // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void -load_config_server (struct config_item_ *subtree, void *user_data) -{ - (void) user_data; - // This will eventually iterate over the object and create servers - config_schema_apply_to_object (g_config_server, subtree); -} - static void load_config_behaviour (struct config_item_ *subtree, void *user_data) { (void) user_data; + // TODO: assign user_data to all the subitems config_schema_apply_to_object (g_config_behaviour, subtree); } @@ -1592,6 +1585,7 @@ static void load_config_attributes (struct config_item_ *subtree, void *user_data) { (void) user_data; + // TODO: assign user_data to all the subitems config_schema_apply_to_object (g_config_attributes, subtree); } @@ -1599,12 +1593,10 @@ static void register_config_modules (struct app_context *ctx) { struct config *config = &ctx->config; - config_register_module (config, - "server", load_config_server, ctx); - config_register_module (config, - "behaviour", load_config_behaviour, ctx); - config_register_module (config, - "attributes", load_config_attributes, ctx); + // The servers are loaded later when we can create buffers for them + config_register_module (config, "servers", NULL, NULL); + config_register_module (config, "behaviour", load_config_behaviour, ctx); + config_register_module (config, "attributes", load_config_attributes, ctx); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2930,13 +2922,14 @@ buffer_get_index (struct app_context *ctx, struct buffer *buffer) } static void -init_buffers (struct app_context *ctx) +init_global_buffer (struct app_context *ctx) { struct buffer *global = ctx->global_buffer = buffer_new (); global->type = BUFFER_GLOBAL; global->name = xstrdup (PROGRAM_NAME); buffer_add (ctx, global); + buffer_activate (ctx, global); } // --- Users, channels --------------------------------------------------------- @@ -8388,6 +8381,75 @@ load_configuration (struct app_context *ctx) get_config_boolean (ctx->config.root, "behaviour.isolate_buffers"); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static void +load_server_from_config (struct app_context *ctx, + const char *name, struct config_item_ *subtree) +{ + // They're case-insensitive in the application but not so in the config + if (str_map_find (&ctx->servers, name)) + { + log_global_error (ctx, "Error in configuration: " + "ignoring server `#s' as it collides with another one", name); + return; + } + + struct server *s = xmalloc (sizeof *s); + server_init (s, &ctx->poller); + + // TODO: assign user_data (s) to all the subitems + config_schema_apply_to_object (g_config_server, subtree); + + s->ctx = ctx; + s->name = xstrdup (name); + str_map_set (&ctx->servers, s->name, s); + s->config = subtree; + + // Add a buffer and activate it + struct buffer *buffer = s->buffer = buffer_new (); + buffer->type = BUFFER_SERVER; + buffer->name = xstrdup (s->name); + buffer->server = s; + + buffer_add (ctx, buffer); + buffer_activate (ctx, buffer); + + // XXX: is this desirable in here? I think we should do it only when + // actually creating a new server instead of every time we load them. + struct error *e = NULL; + if (!irc_autofill_user_info (s, &e)) + { + log_server_error (s, s->buffer, + "#s: #s", "Failed to fill in user details", e->message); + error_free (e); + } + + // Connect to the server ASAP + // TODO: make this configurable ("autoconnect") + poller_timer_set (&s->reconnect_tmr, 0); +} + +static void +init_servers (struct app_context *ctx) +{ + struct config_item_ *servers = + config_item_get (ctx->config.root, "servers", NULL); + + struct str_map_iter iter; + str_map_iter_init (&iter, &servers->value.object); + + struct config_item_ *s; + while ((s = str_map_iter_next (&iter))) + { + if (s->type != CONFIG_ITEM_OBJECT) + log_global_error (ctx, "Error in configuration: " + "ignoring server `#s' as it's not an object", iter.link->key); + else + load_server_from_config (ctx, iter.link->key, s); + } +} + // --- Signals ----------------------------------------------------------------- static int g_signal_pipe[2]; ///< A pipe used to signal... signals @@ -8603,40 +8665,6 @@ display_logo (void) str_vector_free (&v); } -static void -create_server (struct app_context *ctx) -{ - struct server *s = xmalloc (sizeof *s); - server_init (s, &ctx->poller); - - s->ctx = ctx; - s->name = xstrdup ("server"); - str_map_set (&ctx->servers, s->name, s); - - // Load configuration - s->config = config_item_get (ctx->config.root, "server", NULL); - hard_assert (s->config != NULL); - - struct error *e = NULL; - if (!irc_autofill_user_info (s, &e)) - { - print_error ("%s: %s", "failed to fill in user details", e->message); - error_free (e); - } - - // Add a buffer and activate it - struct buffer *buffer = s->buffer = buffer_new (); - buffer->type = BUFFER_SERVER; - buffer->name = xstrdup (s->name); - buffer->server = s; - - buffer_add (ctx, buffer); - buffer_activate (ctx, buffer); - - // Connect to the server ASAP - poller_timer_set (&s->reconnect_tmr, 0); -} - int main (int argc, char *argv[]) { @@ -8695,14 +8723,12 @@ main (int argc, char *argv[]) init_colors (&ctx); init_poller_events (&ctx); - init_buffers (&ctx); + init_global_buffer (&ctx); + init_servers (&ctx); refresh_prompt (&ctx); input_start (&ctx.input, argv[0]); - // TODO: finish multi-server - create_server (&ctx); - ctx.polling = true; while (ctx.polling) poller_run (&ctx.poller);