From 06d5d4b03ec446b9eb7a7351c32ef2fdca29d3c8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 24 Sep 2009 21:40:07 +0200 Subject: conf: handle fatal errors with GError Don't call g_error(), which will abort the process and dump core. This patch does not affect all the config_get_X() functions. These need some more refactoring. --- src/cmdline.c | 13 +++-- src/conf.c | 147 +++++++++++++++++++++++++++++++++++++---------------- src/conf.h | 9 ++-- test/read_conf.c | 9 +++- test/run_encoder.c | 2 +- test/run_filter.c | 7 ++- test/run_output.c | 7 ++- 7 files changed, 136 insertions(+), 58 deletions(-) diff --git a/src/cmdline.c b/src/cmdline.c index 44b3ff507..9e3919152 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -152,21 +152,20 @@ parse_cmdline(int argc, char **argv, struct options *options, path2 = g_build_filename(g_get_home_dir(), USER_CONFIG_FILE_LOCATION2, NULL); if (g_file_test(path1, G_FILE_TEST_IS_REGULAR)) - config_read_file(path1); + ret = config_read_file(path1, error_r); else if (g_file_test(path2, G_FILE_TEST_IS_REGULAR)) - config_read_file(path2); + ret = config_read_file(path2, error_r); else if (g_file_test(SYSTEM_CONFIG_FILE_LOCATION, G_FILE_TEST_IS_REGULAR)) - config_read_file(SYSTEM_CONFIG_FILE_LOCATION); + ret = config_read_file(SYSTEM_CONFIG_FILE_LOCATION, + error_r); g_free(path1); g_free(path2); - return true; + return ret; } else if (argc == 2) { /* specified configuration file */ - config_read_file(argv[1]); - - return true; + return config_read_file(argv[1], error_r); } else { g_set_error(error_r, cmdline_quark(), 0, "too many arguments"); diff --git a/src/conf.c b/src/conf.c index fe4b39fc3..d78f44760 100644 --- a/src/conf.c +++ b/src/conf.c @@ -221,17 +221,20 @@ void config_global_check(void) } } -void +bool config_add_block_param(struct config_param * param, const char *name, - const char *value, int line) + const char *value, int line, GError **error_r) { struct block_param *bp; bp = config_get_block_param(param, name); - if (bp != NULL) - g_error("\"%s\" first defined on line %i, and " - "redefined on line %i\n", name, - bp->line, line); + if (bp != NULL) { + g_set_error(error_r, config_quark(), 0, + "\"%s\" first defined on line %i, and " + "redefined on line %i\n", name, + bp->line, line); + return false; + } param->num_block_params++; @@ -245,21 +248,28 @@ config_add_block_param(struct config_param * param, const char *name, bp->value = g_strdup(value); bp->line = line; bp->used = false; + + return true; } static struct config_param * -config_read_block(FILE *fp, int *count, char *string) +config_read_block(FILE *fp, int *count, char *string, GError **error_r) { struct config_param *ret = config_new_param(NULL, *count); + GError *error = NULL; + bool success; while (true) { char *line; const char *name, *value; - GError *error = NULL; line = fgets(string, MAX_STRING_SIZE, fp); - if (line == NULL) - g_error("Expected '}' before end-of-file"); + if (line == NULL) { + config_param_free(ret); + g_set_error(error_r, config_quark(), 0, + "Expected '}' before end-of-file"); + return NULL; + } (*count)++; line = g_strchug(line); @@ -271,9 +281,13 @@ config_read_block(FILE *fp, int *count, char *string) (and from this "while" loop) */ line = g_strchug(line + 1); - if (*line != 0 && *line != CONF_COMMENT) - g_error("line %i: Unknown tokens after '}'", - *count); + if (*line != 0 && *line != CONF_COMMENT) { + config_param_free(ret); + g_set_error(error_r, config_quark(), 0, + "line %i: Unknown tokens after '}'", + *count); + return false; + } return ret; } @@ -283,25 +297,44 @@ config_read_block(FILE *fp, int *count, char *string) name = tokenizer_next_word(&line, &error); if (name == NULL) { assert(*line != 0); - g_error("line %i: %s", *count, error->message); + config_param_free(ret); + g_propagate_prefixed_error(error_r, error, + "line %i: ", *count); + return NULL; } value = tokenizer_next_string(&line, &error); if (value == NULL) { + config_param_free(ret); if (*line == 0) - g_error("line %i: Value missing", *count); + g_set_error(error_r, config_quark(), 0, + "line %i: Value missing", *count); else - g_error("line %i: %s", *count, error->message); + g_propagate_prefixed_error(error_r, error, + "line %i: ", + *count); + return NULL; } - if (*line != 0 && *line != CONF_COMMENT) - g_error("line %i: Unknown tokens after value", *count); + if (*line != 0 && *line != CONF_COMMENT) { + config_param_free(ret); + g_set_error(error_r, config_quark(), 0, + "line %i: Unknown tokens after value", + *count); + return NULL; + } - config_add_block_param(ret, name, value, *count); + success = config_add_block_param(ret, name, value, *count, + error_r); + if (!success) { + config_param_free(ret); + return false; + } } } -void config_read_file(const char *file) +bool +config_read_file(const char *file, GError **error_r) { FILE *fp; char string[MAX_STRING_SIZE + 1]; @@ -312,8 +345,10 @@ void config_read_file(const char *file) g_debug("loading file %s", file); if (!(fp = fopen(file, "r"))) { - g_error("problems opening file %s for reading: %s\n", - file, strerror(errno)); + g_set_error(error_r, config_quark(), errno, + "Failed to open %s: %s", + file, strerror(errno)); + return false; } while (fgets(string, MAX_STRING_SIZE, fp)) { @@ -333,22 +368,29 @@ void config_read_file(const char *file) name = tokenizer_next_word(&line, &error); if (name == NULL) { assert(*line != 0); - g_error("line %i: %s", count, error->message); + g_propagate_prefixed_error(error_r, error, + "line %i: ", count); + return false; } /* get the definition of that option, and check the "repeatable" flag */ entry = config_entry_get(name); - if (entry == NULL) - g_error("unrecognized parameter in config file at " - "line %i: %s\n", count, name); + if (entry == NULL) { + g_set_error(error_r, config_quark(), 0, + "unrecognized parameter in config file at " + "line %i: %s\n", count, name); + return false; + } if (entry->params != NULL && !entry->repeatable) { param = entry->params->data; - g_error("config parameter \"%s\" is first defined on " - "line %i and redefined on line %i\n", - name, param->line, count); + g_set_error(error_r, config_quark(), 0, + "config parameter \"%s\" is first defined " + "on line %i and redefined on line %i\n", + name, param->line, count); + return false; } /* now parse the block or the value */ @@ -356,31 +398,48 @@ void config_read_file(const char *file) if (entry->block) { /* it's a block, call config_read_block() */ - if (*line != '{') - g_error("line %i: '{' expected", count); + if (*line != '{') { + g_set_error(error_r, config_quark(), 0, + "line %i: '{' expected", count); + return false; + } line = g_strchug(line + 1); - if (*line != 0 && *line != CONF_COMMENT) - g_error("line %i: Unknown tokens after '{'", - count); + if (*line != 0 && *line != CONF_COMMENT) { + g_set_error(error_r, config_quark(), 0, + "line %i: Unknown tokens after '{'", + count); + return false; + } - param = config_read_block(fp, &count, string); + param = config_read_block(fp, &count, string, error_r); + if (param == NULL) + return false; } else { /* a string value */ value = tokenizer_next_string(&line, &error); if (value == NULL) { if (*line == 0) - g_error("line %i: Value missing", - count); - else - g_error("line %i: %s", count, - error->message); + g_set_error(error_r, config_quark(), 0, + "line %i: Value missing", + count); + else { + g_set_error(error_r, config_quark(), 0, + "line %i: %s", count, + error->message); + g_error_free(error); + } + + return false; } - if (*line != 0 && *line != CONF_COMMENT) - g_error("line %i: Unknown tokens after value", - count); + if (*line != 0 && *line != CONF_COMMENT) { + g_set_error(error_r, config_quark(), 0, + "line %i: Unknown tokens after value", + count); + return false; + } param = config_new_param(value, count); } @@ -388,6 +447,8 @@ void config_read_file(const char *file) entry->params = g_slist_append(entry->params, param); } fclose(fp); + + return true; } struct config_param * diff --git a/src/conf.h b/src/conf.h index a153b7157..ef10b9f82 100644 --- a/src/conf.h +++ b/src/conf.h @@ -116,7 +116,8 @@ void config_global_finish(void); */ void config_global_check(void); -void config_read_file(const char *file); +bool +config_read_file(const char *file, GError **error_r); /* don't free the returned value set _last_ to NULL to get first entry */ @@ -192,8 +193,8 @@ config_get_block_bool(const struct config_param *param, const char *name, struct config_param * config_new_param(const char *value, int line); -void -config_add_block_param(struct config_param *param, const char *name, - const char *value, int line); +bool +config_add_block_param(struct config_param * param, const char *name, + const char *value, int line, GError **error_r); #endif diff --git a/test/read_conf.c b/test/read_conf.c index 286ec2c77..92fcbba99 100644 --- a/test/read_conf.c +++ b/test/read_conf.c @@ -37,6 +37,8 @@ my_log_func(G_GNUC_UNUSED const gchar *log_domain, int main(int argc, char **argv) { const char *path, *name, *value; + GError *error = NULL; + bool success; int ret; if (argc != 3) { @@ -50,7 +52,12 @@ int main(int argc, char **argv) g_log_set_default_handler(my_log_func, NULL); config_global_init(); - config_read_file(path); + success = config_read_file(path, &error); + if (!success) { + g_printerr("%s:", error->message); + g_error_free(error); + return 1; + } value = config_get_string(name, NULL); if (value != NULL) { diff --git a/test/run_encoder.c b/test/run_encoder.c index a9b00e95e..787fb03cf 100644 --- a/test/run_encoder.c +++ b/test/run_encoder.c @@ -73,7 +73,7 @@ int main(int argc, char **argv) } param = config_new_param(NULL, -1); - config_add_block_param(param, "quality", "5.0", -1); + config_add_block_param(param, "quality", "5.0", -1, NULL); encoder = encoder_init(plugin, param, &error); if (encoder == NULL) { diff --git a/test/run_filter.c b/test/run_filter.c index 3c98491ab..ed2b904cf 100644 --- a/test/run_filter.c +++ b/test/run_filter.c @@ -90,7 +90,12 @@ int main(int argc, char **argv) /* read configuration file (mpd.conf) */ config_global_init(); - config_read_file(argv[1]); + success = config_read_file(argv[1], &error); + if (!success) { + g_printerr("%s:", error->message); + g_error_free(error); + return 1; + } /* parse the audio format */ diff --git a/test/run_output.c b/test/run_output.c index 594c4cd64..5ab9625e8 100644 --- a/test/run_output.c +++ b/test/run_output.c @@ -122,7 +122,12 @@ int main(int argc, char **argv) /* read configuration file (mpd.conf) */ config_global_init(); - config_read_file(argv[1]); + success = config_read_file(argv[1], &error); + if (!success) { + g_printerr("%s:", error->message); + g_error_free(error); + return 1; + } /* initialize the audio output */ -- cgit v1.2.3