diff --git a/common.c b/common.c index 282916c..4bbebd9 100644 --- a/common.c +++ b/common.c @@ -108,79 +108,11 @@ xwrite (int fd, const char *data, size_t len, struct error **e) if (res >= 0) written += res; else if (errno != EINTR) - FAIL ("%s", strerror (errno)); + return error_set (e, "%s", strerror (errno)); } return true; } -// --- Simple network I/O ------------------------------------------------------ - -// TODO: move to liberty and remove from dwmstatus.c as well - -#define SOCKET_IO_OVERFLOW (8 << 20) ///< How large a read buffer can be - -enum socket_io_result -{ - SOCKET_IO_OK, ///< Completed successfully - SOCKET_IO_EOF, ///< Connection shut down by peer - SOCKET_IO_ERROR ///< Connection error -}; - -static enum socket_io_result -socket_io_try_read (int socket_fd, struct str *rb, struct error **e) -{ - // We allow buffering of a fair amount of data, however within reason, - // so that it's not so easy to flood us and cause an allocation failure - ssize_t n_read; - while (rb->len < SOCKET_IO_OVERFLOW) - { - str_ensure_space (rb, 4096); - n_read = recv (socket_fd, rb->str + rb->len, - rb->alloc - rb->len - 1 /* null byte */, 0); - - if (n_read > 0) - { - rb->str[rb->len += n_read] = '\0'; - continue; - } - if (n_read == 0) - return SOCKET_IO_EOF; - - if (errno == EAGAIN) - return SOCKET_IO_OK; - if (errno == EINTR) - continue; - - error_set (e, "%s", strerror (errno)); - return SOCKET_IO_ERROR; - } - return SOCKET_IO_OK; -} - -static enum socket_io_result -socket_io_try_write (int socket_fd, struct str *wb, struct error **e) -{ - ssize_t n_written; - while (wb->len) - { - n_written = send (socket_fd, wb->str, wb->len, 0); - if (n_written >= 0) - { - str_remove_slice (wb, 0, n_written); - continue; - } - - if (errno == EAGAIN) - return SOCKET_IO_OK; - if (errno == EINTR) - continue; - - error_set (e, "%s", strerror (errno)); - return SOCKET_IO_ERROR; - } - return SOCKET_IO_OK; -} - // --- Logging ----------------------------------------------------------------- static void diff --git a/degesch.c b/degesch.c index 58fd303..2295006 100644 --- a/degesch.c +++ b/degesch.c @@ -4904,7 +4904,7 @@ on_irc_autojoin_timeout (void *user_data) { struct str_vector v; str_vector_init (&v); - cstr_split (autojoin, ",", &v); + cstr_split (autojoin, ",", true, &v); for (size_t i = 0; i < v.len; i++) { irc_send (s, "JOIN :%s", v.vector[i]); @@ -5060,28 +5060,20 @@ on_irc_ready (const struct pollfd *pfd, struct server *s) static enum socket_io_result transport_plain_try_read (struct server *s) { - struct error *e = NULL; enum socket_io_result result = - socket_io_try_read (s->socket, &s->read_buffer, &e); - if (e) - { - print_debug ("%s: %s", __func__, e->message); - error_free (e); - } + socket_io_try_read (s->socket, &s->read_buffer); + if (result == SOCKET_IO_ERROR) + print_debug ("%s: %s", __func__, strerror (errno)); return result; } static enum socket_io_result transport_plain_try_write (struct server *s) { - struct error *e = NULL; enum socket_io_result result = - socket_io_try_write (s->socket, &s->write_buffer, &e); - if (e) - { - print_debug ("%s: %s", __func__, e->message); - error_free (e); - } + socket_io_try_write (s->socket, &s->write_buffer); + if (result == SOCKET_IO_ERROR) + print_debug ("%s: %s", __func__, strerror (errno)); return result; } @@ -5152,12 +5144,14 @@ transport_tls_init_ca_set (SSL_CTX *ssl_ctx, const char *file, const char *path, if (SSL_CTX_load_verify_locations (ssl_ctx, file, path)) return true; - FAIL ("%s: %s", "Failed to set locations for the CA certificate bundle", + return error_set (e, "%s: %s", + "Failed to set locations for the CA certificate bundle", ERR_reason_error_string (ERR_get_error ())); } if (!SSL_CTX_set_default_verify_paths (ssl_ctx)) - FAIL ("%s: %s", "Couldn't load the default CA certificate bundle", + return error_set (e, "%s: %s", + "Couldn't load the default CA certificate bundle", ERR_reason_error_string (ERR_get_error ())); return true; } @@ -5445,7 +5439,10 @@ irc_autofill_user_info (struct server *s, struct error **e) // Read POSIX user info and fill the configuration if needed struct passwd *pwd = getpwuid (geteuid ()); if (!pwd) - FAIL ("cannot retrieve user information: %s", strerror (errno)); + { + return error_set (e, + "cannot retrieve user information: %s", strerror (errno)); + } // FIXME: set_config_strings() writes errors on its own if (!nicks || !*nicks) @@ -5474,7 +5471,7 @@ irc_fetch_next_nickname (struct server *s) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (get_config_string (s->config, "nicks"), ',', &v); + cstr_split (get_config_string (s->config, "nicks"), ",", true, &v); char *result = NULL; if (s->nick_counter >= 0 && (size_t) s->nick_counter < v.len) @@ -5565,6 +5562,7 @@ irc_finish_connection (struct server *s, int socket, const char *hostname) static void irc_split_host_port (char *s, char **host, char **port) { + // FIXME: this won't work if this is an IPv6 address w/o a port char *colon = strrchr (s, ':'); if (colon) { @@ -5689,7 +5687,7 @@ irc_setup_connector_socks (struct server *s, // The SOCKS connector can have already failed; we mustn't return true then if (!s->socks_conn) - FAIL ("SOCKS connection failed"); + return error_set (e, "SOCKS connection failed"); return true; } @@ -5711,7 +5709,7 @@ irc_initiate_connect (struct server *s) struct str_vector servers; str_vector_init (&servers); - cstr_split_ignore_empty (addresses, ',', &servers); + cstr_split (addresses, ",", true, &servers); struct error *e = NULL; if (!irc_setup_connector_socks (s, &servers, &e) && !e) @@ -6292,7 +6290,7 @@ irc_handle_cap (struct server *s, const struct irc_message *msg) const char *args = ""; if (msg->params.len > 2) - cstr_split_ignore_empty ((args = msg->params.vector[2]), ' ', &v); + cstr_split ((args = msg->params.vector[2]), " ", true, &v); const char *subcommand = msg->params.vector[1]; if (!strcasecmp_ascii (subcommand, "ACK")) @@ -6327,8 +6325,8 @@ irc_handle_cap (struct server *s, const struct irc_message *msg) struct str_vector chosen; str_vector_init (&chosen); struct str_vector use; str_vector_init (&use); - cstr_split_ignore_empty - (get_config_string (s->config, "capabilities"), ',', &use); + cstr_split (get_config_string (s->config, "capabilities"), + ",", true, &use); // Filter server capabilities for ones we can make use of for (size_t i = 0; i < v.len; i++) @@ -7027,7 +7025,7 @@ irc_try_parse_welcome_for_userhost (struct server *s, const char *m) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (m, ' ', &v); + cstr_split (m, " ", true, &v); for (size_t i = 0; i < v.len; i++) if (irc_try_parse_word_for_userhost (s, v.vector[i])) break; @@ -7077,7 +7075,7 @@ irc_handle_rpl_userhost (struct server *s, const struct irc_message *msg) const char *response = msg->params.vector[1]; struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (response, ' ', &v); + cstr_split (response, " ", true, &v); for (size_t i = 0; i < v.len; i++) { @@ -7134,7 +7132,7 @@ irc_handle_rpl_namreply (struct server *s, const struct irc_message *msg) // Just push the nicknames to a string vector to process later struct channel *channel = str_map_find (&s->irc_channels, channel_name); if (channel) - cstr_split_ignore_empty (nicks, ' ', &channel->names_buf); + cstr_split (nicks, " ", true, &channel->names_buf); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7483,7 +7481,7 @@ irc_handle_isupport_idchan (struct server *s, char *value) struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (value, ',', &v); + cstr_split (value, ",", true, &v); for (size_t i = 0; i < v.len; i++) { // Not using or validating the numeric part @@ -7510,7 +7508,7 @@ irc_handle_isupport_chanmodes (struct server *s, char *value) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (value, ',', &v); + cstr_split (value, ",", true, &v); if (v.len >= 4) { free (s->irc_chanmodes_list); @@ -8250,7 +8248,7 @@ lua_plugin_process_error (struct lua_plugin *self, const char *message, { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (message, '\n', &v); + cstr_split (message, "\n", true, &v); if (v.len < 2) error_set (e, "%s", message); @@ -8303,12 +8301,12 @@ lua_plugin_handle_string_filter_result (struct lua_plugin *self, return true; } if (!lua_isstring (L, -1)) - FAIL ("must return either a string or nil"); + return error_set (e, "must return either a string or nil"); size_t len; const char *processed = lua_tolstring (L, -1, &len); if (utf8 && !utf8_validate (processed, len)) - FAIL ("must return valid UTF-8"); + return error_set (e, "must return valid UTF-8"); // Only replace the string if it's different if (strcmp (processed, *original)) @@ -8837,12 +8835,15 @@ lua_completion_hook_process_value (lua_State *L, struct str_vector *output, struct error **e) { if (lua_type (L, -1) != LUA_TSTRING) - FAIL ("%s: %s", "invalid type", lua_typename (L, lua_type (L, -1))); + { + return error_set (e, + "%s: %s", "invalid type", lua_typename (L, lua_type (L, -1))); + } size_t len; const char *value = lua_tolstring (L, -1, &len); if (!utf8_validate (value, len)) - FAIL ("must be valid UTF-8"); + return error_set (e, "must be valid UTF-8"); str_vector_add (output, value); return true; @@ -8855,7 +8856,7 @@ lua_completion_hook_process (lua_State *L, struct str_vector *output, if (lua_isnil (L, -1)) return true; if (!lua_istable (L, -1)) - FAIL ("must return either a table or nil"); + return error_set (e, "must return either a table or nil"); bool success = true; for (lua_Integer i = 1; success && lua_rawgeti (L, -1, i); i++) @@ -9415,16 +9416,15 @@ lua_connection_invoke_on_eof (struct lua_connection *self, struct error **e) static bool lua_connection_invoke_on_error (struct lua_connection *self, - struct error *error, struct error **e) + const char *error, struct error **e) { if (!self->closing && lua_connection_cb_lookup (self, "on_error", e) && !lua_connection_eat_nil (self)) { - lua_pushstring (self->plugin->L, error->message); + lua_pushstring (self->plugin->L, error); lua_plugin_call (self->plugin, 1, 0, e); } - error_free (error); return false; } @@ -9436,19 +9436,15 @@ lua_connection_try_read (struct lua_connection *self, struct error **e) if (self->closing || self->got_eof) return true; - struct error *error = NULL; enum socket_io_result read_result = - socket_io_try_read (self->socket_fd, &self->read_buffer, &error); + socket_io_try_read (self->socket_fd, &self->read_buffer); + const char *error = strerror (errno); // Dispatch any data that we got before an EOF or any error if (self->read_buffer.len) { if (!lua_connection_invoke_on_data (self, e)) - { - if (error) - error_free (error); return false; - } str_reset (&self->read_buffer); } @@ -9466,9 +9462,9 @@ lua_connection_try_read (struct lua_connection *self, struct error **e) static bool lua_connection_try_write (struct lua_connection *self, struct error **e) { - struct error *error = NULL; enum socket_io_result write_result = - socket_io_try_write (self->socket_fd, &self->write_buffer, &error); + socket_io_try_write (self->socket_fd, &self->write_buffer); + const char *error = strerror (errno); if (write_result == SOCKET_IO_ERROR) return lua_connection_invoke_on_error (self, error, e); @@ -9853,7 +9849,10 @@ plugin_load_from_filename (struct app_context *ctx, const char *filename, if (error) error_propagate (e, error); else if (!plugin) - FAIL ("no plugin handler for \"%s\"", filename); + { + error_set (e, "no plugin handler for \"%s\"", filename); + return NULL; + } return plugin; } @@ -9884,14 +9883,20 @@ plugin_load_by_name (struct app_context *ctx, const char *name, { struct plugin *plugin = plugin_find (ctx, name); if (plugin) - FAIL ("plugin already loaded"); + { + error_set (e, "plugin already loaded"); + return NULL; + } // As a side effect, a plugin can be loaded multiple times by giving // various relative or non-relative paths to the function; this is not // supposed to be fool-proof though, that requires other mechanisms char *filename = resolve_filename (name, plugin_resolve_relative_filename); if (!filename) - FAIL ("file not found"); + { + error_set (e, "file not found"); + return NULL; + } plugin = plugin_load_from_filename (ctx, filename, e); free (filename); @@ -9944,7 +9949,7 @@ load_plugins (struct app_context *ctx) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (plugins, ',', &v); + cstr_split (plugins, ",", true, &v); for (size_t i = 0; i < v.len; i++) plugin_load (ctx, v.vector[i]); str_vector_free (&v); @@ -10230,7 +10235,7 @@ handle_command_set_add struct str_vector items; str_vector_init (&items); if (item->type != CONFIG_ITEM_NULL) - cstr_split (item->value.string.str, ",", &items); + cstr_split (item->value.string.str, ",", false, &items); if (items.len == 1 && !*items.vector[0]) str_vector_reset (&items); @@ -10255,7 +10260,7 @@ handle_command_set_remove struct str_vector items; str_vector_init (&items); if (item->type != CONFIG_ITEM_NULL) - cstr_split (item->value.string.str, ",", &items); + cstr_split (item->value.string.str, ",", false, &items); if (items.len == 1 && !*items.vector[0]) str_vector_reset (&items); @@ -10623,7 +10628,7 @@ handle_command_part (struct handler_args *a) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (cut_word (&a->arguments), ' ', &v); + cstr_split (cut_word (&a->arguments), ",", true, &v); for (size_t i = 0; i < v.len; i++) part_channel (a->s, v.vector[i], a->arguments); str_vector_free (&v); @@ -10666,7 +10671,7 @@ handle_command_cycle (struct handler_args *a) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (cut_word (&a->arguments), ' ', &v); + cstr_split (cut_word (&a->arguments), ",", true, &v); for (size_t i = 0; i < v.len; i++) cycle_channel (a->s, v.vector[i], a->arguments); str_vector_free (&v); @@ -10790,7 +10795,7 @@ mass_channel_mode_mask_list { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (a->arguments, ' ', &v); + cstr_split (a->arguments, " ", true, &v); // XXX: this may be a bit too trivial; we could also map nicknames // to information from WHO polling or userhost-in-names @@ -10833,7 +10838,7 @@ handle_command_invite (struct handler_args *a) { struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (a->arguments, ' ', &v); + cstr_split (a->arguments, " ", true, &v); bool result = !!v.len; for (size_t i = 0; i < v.len; i++) @@ -11088,7 +11093,7 @@ handle_command_channel_mode struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (a->arguments, ' ', &v); + cstr_split (a->arguments, " ", true, &v); mass_channel_mode (a->s, a->channel_name, adding, mode_char, &v); str_vector_free (&v); return true; @@ -11428,7 +11433,7 @@ expand_alias_escape (const char *p, const char *arguments, struct str *output) { struct str_vector words; str_vector_init (&words); - cstr_split_ignore_empty (arguments, ' ', &words); + cstr_split (arguments, " ", true, &words); // TODO: eventually also add support for argument ranges if (*p >= '1' && *p <= '9') @@ -11619,7 +11624,7 @@ process_input (struct app_context *ctx, char *user_input) str_vector_init (&lines); // XXX: this interprets commands in pasted text - cstr_split (input, "\r\n", &lines); + cstr_split (input, "\r\n", false, &lines); for (size_t i = 0; i < lines.len; i++) (void) process_input_utf8 (ctx, ctx->current_buffer, lines.vector[i], 0); @@ -12098,7 +12103,7 @@ dump_input_to_file (struct app_context *ctx, char *template, struct error **e) (void) umask (mask); if (fd < 0) - FAIL ("%s", strerror (errno)); + return error_set (e, "%s", strerror (errno)); char *input = CALL (ctx->input, get_line); bool success = xwrite (fd, input, strlen (input), e); @@ -12803,14 +12808,14 @@ load_configuration (struct app_context *ctx) char *filename = resolve_filename (PROGRAM_NAME ".conf", resolve_relative_config_filename); if (filename) - root = load_configuration_file (filename, &e); + root = config_read_from_file (filename, &e); else log_global_error (ctx, "Configuration file not found"); free (filename); if (e) { - log_global_error (ctx, "#s", e->message); + log_global_error (ctx, "Cannot load configuration: #s", e->message); log_global_error (ctx, "Please either fix the configuration file or remove it", filename); error_free (e); diff --git a/kike.c b/kike.c index e47c9aa..affb4ed 100644 --- a/kike.c +++ b/kike.c @@ -1403,7 +1403,7 @@ irc_handle_cap (const struct irc_message *msg, struct client *c) if (msg->params.len > 1) { args.full_params = msg->params.vector[1]; - cstr_split_ignore_empty (args.full_params, ' ', &args.params); + cstr_split (args.full_params, " ", true, &args.params); } struct irc_cap_command *cmd = @@ -2186,7 +2186,7 @@ irc_handle_list (const struct irc_message *msg, struct client *c) { struct str_vector channels; str_vector_init (&channels); - cstr_split_ignore_empty (msg->params.vector[0], ',', &channels); + cstr_split (msg->params.vector[0], ",", true, &channels); for (size_t i = 0; i < channels.len; i++) if ((chan = str_map_find (&c->ctx->channels, channels.vector[i])) && (!(chan->modes & IRC_CHAN_MODE_SECRET) @@ -2317,7 +2317,7 @@ irc_handle_names (const struct irc_message *msg, struct client *c) { struct str_vector channels; str_vector_init (&channels); - cstr_split_ignore_empty (msg->params.vector[0], ',', &channels); + cstr_split (msg->params.vector[0], ",", true, &channels); for (size_t i = 0; i < channels.len; i++) if ((chan = str_map_find (&c->ctx->channels, channels.vector[i])) && (!(chan->modes & IRC_CHAN_MODE_SECRET) @@ -2480,7 +2480,7 @@ irc_handle_whois (const struct irc_message *msg, struct client *c) struct str_vector masks; str_vector_init (&masks); const char *masks_str = msg->params.vector[msg->params.len > 1]; - cstr_split_ignore_empty (masks_str, ',', &masks); + cstr_split (masks_str, ",", true, &masks); for (size_t i = 0; i < masks.len; i++) { const char *mask = masks.vector[i]; @@ -2521,7 +2521,7 @@ irc_handle_whowas (const struct irc_message *msg, struct client *c) struct str_vector nicks; str_vector_init (&nicks); - cstr_split_ignore_empty (msg->params.vector[0], ',', &nicks); + cstr_split (msg->params.vector[0], ",", true, &nicks); for (size_t i = 0; i < nicks.len; i++) { @@ -2641,7 +2641,7 @@ irc_handle_part (const struct irc_message *msg, struct client *c) const char *reason = msg->params.len > 1 ? msg->params.vector[1] : NULL; struct str_vector channels; str_vector_init (&channels); - cstr_split_ignore_empty (msg->params.vector[0], ',', &channels); + cstr_split (msg->params.vector[0], ",", true, &channels); for (size_t i = 0; i < channels.len; i++) irc_try_part (c, channels.vector[i], reason); str_vector_free (&channels); @@ -2692,8 +2692,8 @@ irc_handle_kick (const struct irc_message *msg, struct client *c) struct str_vector users; str_vector_init (&channels); str_vector_init (&users); - cstr_split_ignore_empty (msg->params.vector[0], ',', &channels); - cstr_split_ignore_empty (msg->params.vector[1], ',', &users); + cstr_split (msg->params.vector[0], ",", true, &channels); + cstr_split (msg->params.vector[1], ",", true, &users); if (channels.len == 1) for (size_t i = 0; i < users.len; i++) @@ -2821,9 +2821,9 @@ irc_handle_join (const struct irc_message *msg, struct client *c) struct str_vector keys; str_vector_init (&channels); str_vector_init (&keys); - cstr_split_ignore_empty (msg->params.vector[0], ',', &channels); + cstr_split (msg->params.vector[0], ",", true, &channels); if (msg->params.len > 1) - cstr_split_ignore_empty (msg->params.vector[1], ',', &keys); + cstr_split (msg->params.vector[1], ",", true, &keys); for (size_t i = 0; i < channels.len; i++) irc_try_join (c, channels.vector[i], @@ -3744,7 +3744,7 @@ irc_parse_config (struct server_context *ctx, struct error **e) str_vector_init (&fingerprints); const char *operators = str_map_find (&ctx->config, "operators"); if (operators) - cstr_split_ignore_empty (operators, ',', &fingerprints); + cstr_split (operators, ",", true, &fingerprints); for (size_t i = 0; i < fingerprints.len; i++) { const char *key = fingerprints.vector[i]; @@ -3905,7 +3905,7 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e) struct str_vector ports; str_vector_init (&ports); - cstr_split_ignore_empty (bind_port, ',', &ports); + cstr_split (bind_port, ",", true, &ports); ctx->listen_fds = xcalloc (ports.len, sizeof *ctx->listen_fds); ctx->listen_events = xcalloc (ports.len, sizeof *ctx->listen_events); for (size_t i = 0; i < ports.len; i++) diff --git a/liberty b/liberty index 365aed4..2a15b1d 160000 --- a/liberty +++ b/liberty @@ -1 +1 @@ -Subproject commit 365aed456e7ce31ba08e7d46bbb2402afc8256cf +Subproject commit 2a15b1de700eb4e20c6bebb9742c8e20fffc9687 diff --git a/zyklonb.c b/zyklonb.c index c7ab8c7..53cb6f3 100644 --- a/zyklonb.c +++ b/zyklonb.c @@ -310,7 +310,7 @@ irc_get_boolean_from_config if (set_boolean_if_valid (value, str)) return true; - FAIL ("invalid configuration value for `%s'", name); + return error_set (e, "invalid configuration value for `%s'", name); } static bool @@ -324,12 +324,14 @@ irc_initialize_ca_set (SSL_CTX *ssl_ctx, const char *file, const char *path, if (SSL_CTX_load_verify_locations (ssl_ctx, file, path)) return true; - FAIL ("%s: %s", "failed to set locations for the CA certificate bundle", + return error_set (e, "%s: %s", + "failed to set locations for the CA certificate bundle", ERR_reason_error_string (ERR_get_error ())); } if (!SSL_CTX_set_default_verify_paths (ssl_ctx)) - FAIL ("%s: %s", "couldn't load the default CA certificate bundle", + return error_set (e, "%s: %s", + "couldn't load the default CA certificate bundle", ERR_reason_error_string (ERR_get_error ())); return true; } @@ -442,7 +444,7 @@ error_ssl_1: // multiple errors on the OpenSSL stack. if (!error_info) error_info = ERR_error_string (ERR_get_error (), NULL); - FAIL ("%s: %s", "could not initialize TLS", error_info); + return error_set (e, "%s: %s", "could not initialize TLS", error_info); } static bool @@ -455,7 +457,7 @@ irc_establish_connection (struct bot_context *ctx, int err = getaddrinfo (host, port, &gai_hints, &gai_result); if (err) - FAIL ("%s: %s: %s", "connection failed", + return error_set (e, "%s: %s: %s", "connection failed", "getaddrinfo", gai_strerror (err)); int sockfd; @@ -497,7 +499,7 @@ irc_establish_connection (struct bot_context *ctx, freeaddrinfo (gai_result); if (!gai_iter) - FAIL ("connection failed"); + return error_set (e, "connection failed"); ctx->irc_fd = sockfd; return true; @@ -1117,9 +1119,9 @@ static bool plugin_load (struct bot_context *ctx, const char *name, struct error **e) { if (!is_valid_plugin_name (name)) - FAIL ("invalid plugin name"); + return error_set (e, "invalid plugin name"); if (str_map_find (&ctx->plugins_by_name, name)) - FAIL ("the plugin has already been loaded"); + return error_set (e, "the plugin has already been loaded"); struct plugin *plugin; if (!(plugin = plugin_launch (ctx, name, e))) @@ -1149,7 +1151,7 @@ plugin_unload (struct bot_context *ctx, const char *name, struct error **e) struct plugin *plugin = str_map_find (&ctx->plugins_by_name, name); if (!plugin) - FAIL ("no such plugin is loaded"); + return error_set (e, "no such plugin is loaded"); plugin_zombify (plugin); @@ -1168,7 +1170,7 @@ plugin_load_all_from_config (struct bot_context *ctx) struct str_vector plugins; str_vector_init (&plugins); - cstr_split_ignore_empty (plugin_list, ',', &plugins); + cstr_split (plugin_list, ",", true, &plugins); for (size_t i = 0; i < plugins.len; i++) { char *name = cstr_strip_in_place (plugins.vector[i], " "); @@ -1208,7 +1210,7 @@ parse_bot_command (const char *s, const char *command, const char **following) static void split_bot_command_argument_list (const char *arguments, struct str_vector *out) { - cstr_split_ignore_empty (arguments, ',', out); + cstr_split (arguments, ",", true, out); for (size_t i = 0; i < out->len; ) { if (!*cstr_strip_in_place (out->vector[i], " \t")) @@ -1778,7 +1780,7 @@ irc_connect (struct bot_context *ctx, struct error **e) // TODO: again, get rid of `struct error' in here. The question is: how // do we tell our caller that he should not try to reconnect? if (!irc_host) - FAIL ("no hostname specified in configuration"); + return error_set (e, "no hostname specified in configuration"); bool use_tls; if (!irc_get_boolean_from_config (ctx, "tls", &use_tls, e)) @@ -1823,7 +1825,10 @@ parse_config (struct bot_context *ctx, struct error **e) const char *delay_str = str_map_find (&ctx->config, "reconnect_delay"); hard_assert (delay_str != NULL); // We have a default value for this if (!xstrtoul (&ctx->reconnect_delay, delay_str, 10)) - FAIL ("invalid configuration value for `%s'", "reconnect_delay"); + { + return error_set (e, + "invalid configuration value for `%s'", "reconnect_delay"); + } hard_assert (!ctx->admin_re); const char *admin = str_map_find (&ctx->config, "admin");