X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch-config.c;h=959410cce7b81b95a29969b67f41840610dc9f12;hp=934827874b1eb3548fa6b9fa1fdf4d9955174ee6;hb=80aeaf7f59e250f034ecc99aa7fcd1e6dd14d9bb;hpb=243d7e30dcd80041760307d8d0d2a1839f36eca2 diff --git a/notmuch-config.c b/notmuch-config.c index 93482787..959410cc 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/ . + * along with this program. If not, see https://www.gnu.org/licenses/ . * * Author: Carl Worth */ @@ -27,7 +27,7 @@ static const char toplevel_config_comment[] = " .notmuch-config - Configuration file for the notmuch mail system\n" "\n" - " For more information about notmuch, see http://notmuchmail.org"; + " For more information about notmuch, see https://notmuchmail.org"; static const char database_config_comment[] = " Database configuration\n" @@ -202,6 +202,85 @@ get_username_from_passwd_file (void *ctx) return name; } +static notmuch_bool_t +get_config_from_file (notmuch_config_t *config, notmuch_bool_t create_new) +{ + #define BUF_SIZE 4096 + char *config_str = NULL; + int config_len = 0; + int config_bufsize = BUF_SIZE; + size_t len; + GError *error = NULL; + notmuch_bool_t ret = FALSE; + + FILE *fp = fopen(config->filename, "r"); + if (fp == NULL) { + /* If create_new is true, then the caller is prepared for a + * default configuration file in the case of FILE NOT FOUND. + */ + if (create_new) { + config->is_new = TRUE; + ret = TRUE; + goto out; + } else if (errno == ENOENT) { + fprintf (stderr, "Configuration file %s not found.\n" + "Try running 'notmuch setup' to create a configuration.\n", + config->filename); + goto out; + } else { + fprintf (stderr, "Error opening config file '%s': %s\n" + "Try running 'notmuch setup' to create a configuration.\n", + config->filename, strerror(errno)); + goto out; + } + } + + config_str = talloc_zero_array (config, char, config_bufsize); + if (config_str == NULL) { + fprintf (stderr, "Error reading '%s': Out of memory\n", config->filename); + goto out; + } + + while ((len = fread (config_str + config_len, 1, + config_bufsize - config_len, fp)) > 0) { + config_len += len; + if (config_len == config_bufsize) { + config_bufsize += BUF_SIZE; + config_str = talloc_realloc (config, config_str, char, config_bufsize); + if (config_str == NULL) { + fprintf (stderr, "Error reading '%s': Failed to reallocate memory\n", + config->filename); + goto out; + } + } + } + + if (ferror (fp)) { + fprintf (stderr, "Error reading '%s': I/O error\n", config->filename); + goto out; + } + + if (g_key_file_load_from_data (config->key_file, config_str, config_len, + G_KEY_FILE_KEEP_COMMENTS, &error)) { + ret = TRUE; + goto out; + } + + fprintf (stderr, "Error parsing config file '%s': %s\n", + config->filename, error->message); + + g_error_free (error); + +out: + if (fp) + fclose(fp); + + if (config_str) + talloc_free(config_str); + + return ret; +} + /* Open the named notmuch configuration file. If the filename is NULL, * the value of the environment variable $NOTMUCH_CONFIG will be used. * If $NOTMUCH_CONFIG is unset, the default configuration file @@ -243,7 +322,7 @@ get_username_from_passwd_file (void *ctx) notmuch_config_t * notmuch_config_open (void *ctx, const char *filename, - notmuch_bool_t create_new) + notmuch_config_mode_t config_mode) { GError *error = NULL; size_t tmp; @@ -255,7 +334,7 @@ notmuch_config_open (void *ctx, int file_had_search_group; int file_had_crypto_group; - notmuch_config_t *config = talloc (ctx, notmuch_config_t); + notmuch_config_t *config = talloc_zero (ctx, notmuch_config_t); if (config == NULL) { fprintf (stderr, "Out of memory.\n"); return NULL; @@ -263,6 +342,9 @@ notmuch_config_open (void *ctx, talloc_set_destructor (config, notmuch_config_destructor); + /* non-zero defaults */ + config->maildir_synchronize_flags = TRUE; + if (filename) { config->filename = talloc_strdup (config, filename); } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) { @@ -274,49 +356,11 @@ notmuch_config_open (void *ctx, config->key_file = g_key_file_new (); - config->is_new = FALSE; - config->database_path = NULL; - config->user_name = NULL; - config->user_primary_email = NULL; - config->user_other_email = NULL; - config->user_other_email_length = 0; - config->new_tags = NULL; - config->new_tags_length = 0; - config->new_ignore = NULL; - config->new_ignore_length = 0; - config->maildir_synchronize_flags = TRUE; - config->search_exclude_tags = NULL; - config->search_exclude_tags_length = 0; - config->crypto_gpg_path = NULL; - - if (! g_key_file_load_from_file (config->key_file, - config->filename, - G_KEY_FILE_KEEP_COMMENTS, - &error)) - { - if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) { - /* If create_new is true, then the caller is prepared for a - * default configuration file in the case of FILE NOT - * FOUND. - */ - if (create_new) { - g_error_free (error); - config->is_new = TRUE; - } else { - fprintf (stderr, "Configuration file %s not found.\n" - "Try running 'notmuch setup' to create a configuration.\n", - config->filename); - talloc_free (config); - g_error_free (error); - return NULL; - } - } - else - { - fprintf (stderr, "Error reading configuration file %s: %s\n", - config->filename, error->message); + if (config_mode & NOTMUCH_CONFIG_OPEN) { + notmuch_bool_t create_new = (config_mode & NOTMUCH_CONFIG_CREATE) != 0; + + if (! get_config_from_file (config, create_new)) { talloc_free (config); - g_error_free (error); return NULL; } } @@ -591,11 +635,11 @@ _config_get_list (notmuch_config_t *config, static void _config_set_list (notmuch_config_t *config, - const char *group, const char *name, + const char *group, const char *key, const char *list[], size_t length, const char ***config_var ) { - g_key_file_set_string_list (config->key_file, group, name, list, length); + g_key_file_set_string_list (config->key_file, group, key, list, length); /* drop the cached value */ talloc_free (*config_var); @@ -750,6 +794,30 @@ _item_split (char *item, char **group, char **key) return 0; } +#define BUILT_WITH_PREFIX "built_with." +#define QUERY_PREFIX "query." + +static int +_print_db_config(notmuch_config_t *config, const char *name) +{ + notmuch_database_t *notmuch; + char *val; + + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) + return EXIT_FAILURE; + + /* XXX Handle UUID mismatch? */ + + if (print_status_database ("notmuch config", notmuch, + notmuch_database_get_config (notmuch, name, &val))) + return EXIT_FAILURE; + + puts (val); + + return EXIT_SUCCESS; +} + static int notmuch_config_command_get (notmuch_config_t *config, char *item) { @@ -773,6 +841,11 @@ notmuch_config_command_get (notmuch_config_t *config, char *item) tags = notmuch_config_get_new_tags (config, &length); for (i = 0; i < length; i++) printf ("%s\n", tags[i]); + } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) { + printf ("%s\n", + notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false"); + } else if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) { + return _print_db_config (config, item); } else { char **value; size_t i, length; @@ -799,11 +872,53 @@ notmuch_config_command_get (notmuch_config_t *config, char *item) return 0; } +static int +_set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv) +{ + notmuch_database_t *notmuch; + const char *val = ""; + + if (argc > 1) { + /* XXX handle lists? */ + fprintf (stderr, "notmuch config set: at most one value expected for %s\n", key); + return EXIT_FAILURE; + } + + if (argc > 0) { + val = argv[0]; + } + + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) + return EXIT_FAILURE; + + /* XXX Handle UUID mismatch? */ + + if (print_status_database ("notmuch config", notmuch, + notmuch_database_set_config (notmuch, key, val))) + return EXIT_FAILURE; + + if (print_status_database ("notmuch config", notmuch, + notmuch_database_close (notmuch))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + static int notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[]) { char *group, *key; + if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) { + fprintf (stderr, "Error: read only option: %s\n", item); + return 1; + } + + if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) { + return _set_db_config (config, item, argc, argv); + } + if (_item_split (item, &group, &key)) return 1; @@ -830,6 +945,46 @@ notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char return notmuch_config_save (config); } +static +void +_notmuch_config_list_built_with () +{ + printf("%scompact=%s\n", + BUILT_WITH_PREFIX, + notmuch_built_with ("compact") ? "true" : "false"); + printf("%sfield_processor=%s\n", + BUILT_WITH_PREFIX, + notmuch_built_with ("field_processor") ? "true" : "false"); + printf("%sretry_lock=%s\n", + BUILT_WITH_PREFIX, + notmuch_built_with ("retry_lock") ? "true" : "false"); +} + +static int +_list_db_config (notmuch_config_t *config) +{ + notmuch_database_t *notmuch; + notmuch_config_list_t *list; + + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) + return EXIT_FAILURE; + + /* XXX Handle UUID mismatch? */ + + + if (print_status_database ("notmuch config", notmuch, + notmuch_database_get_config_list (notmuch, "", &list))) + return EXIT_FAILURE; + + for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) { + printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list)); + } + notmuch_config_list_destroy (list); + + return EXIT_SUCCESS; +} + static int notmuch_config_command_list (notmuch_config_t *config) { @@ -865,7 +1020,8 @@ notmuch_config_command_list (notmuch_config_t *config) g_strfreev (groups); - return 0; + _notmuch_config_list_built_with (); + return _list_db_config (config); } int @@ -878,6 +1034,10 @@ notmuch_config_command (notmuch_config_t *config, int argc, char *argv[]) if (opt_index < 0) return EXIT_FAILURE; + if (notmuch_requested_db_uuid) + fprintf (stderr, "Warning: ignoring --uuid=%s\n", + notmuch_requested_db_uuid); + /* skip at least subcommand argument */ argc-= opt_index; argv+= opt_index;