#include <netdb.h>
#include <assert.h>
+#include "path-util.h"
#include "unicode-util.h"
static const char toplevel_config_comment[] =
"\n"
" For more information about notmuch, see https://notmuchmail.org";
-struct config_group {
+static const struct config_group {
const char *group_name;
const char *comment;
} group_comment_table [] = {
},
};
-struct _notmuch_config {
+struct _notmuch_conffile {
char *filename;
GKeyFile *key_file;
bool is_new;
-
- char *database_path;
- char *user_name;
- char *user_primary_email;
- const char **user_other_email;
- size_t user_other_email_length;
- const char **new_tags;
- size_t new_tags_length;
- const char **new_ignore;
- size_t new_ignore_length;
- bool maildir_synchronize_flags;
- const char **search_exclude_tags;
- size_t search_exclude_tags_length;
};
static int
-notmuch_config_destructor (notmuch_config_t *config)
+notmuch_conffile_destructor (notmuch_conffile_t *config)
{
if (config->key_file)
g_key_file_free (config->key_file);
return 0;
}
-
static bool
-get_config_from_file (notmuch_config_t *config, bool create_new)
+get_config_from_file (notmuch_conffile_t *config, bool create_new)
{
#define BUF_SIZE 4096
char *config_str = NULL;
* The default configuration also contains comments to guide the
* user in editing the file directly.
*/
-notmuch_config_t *
-notmuch_config_open (notmuch_database_t *notmuch,
- const char *filename,
- notmuch_command_mode_t config_mode)
+notmuch_conffile_t *
+notmuch_conffile_open (notmuch_database_t *notmuch,
+ const char *filename,
+ bool create)
{
char *notmuch_config_env = NULL;
- notmuch_config_t *config = talloc_zero (notmuch, notmuch_config_t);
+ notmuch_conffile_t *config = talloc_zero (notmuch, notmuch_conffile_t);
if (config == NULL) {
fprintf (stderr, "Out of memory.\n");
return NULL;
}
- talloc_set_destructor (config, notmuch_config_destructor);
-
- /* non-zero defaults */
- config->maildir_synchronize_flags = true;
+ talloc_set_destructor (config, notmuch_conffile_destructor);
if (filename) {
config->filename = talloc_strdup (config, filename);
config->key_file = g_key_file_new ();
- if (config_mode & NOTMUCH_COMMAND_CONFIG_OPEN) {
- bool create_new = (config_mode & NOTMUCH_COMMAND_CONFIG_CREATE) != 0;
-
- if (! get_config_from_file (config, create_new)) {
- talloc_free (config);
- return NULL;
- }
+ if (! get_config_from_file (config, create)) {
+ talloc_free (config);
+ return NULL;
}
if (config->is_new)
return config;
}
-/* Close the given notmuch_config_t object, freeing all resources.
+/* Close the given notmuch_conffile_t object, freeing all resources.
*
* Note: Any changes made to the configuration are *not* saved by this
- * function. To save changes, call notmuch_config_save before
- * notmuch_config_close.
+ * function. To save changes, call notmuch_conffile_save before
+ * notmuch_conffile_close.
*/
void
-notmuch_config_close (notmuch_config_t *config)
+notmuch_conffile_close (notmuch_conffile_t *config)
{
talloc_free (config);
}
-const char *
-_notmuch_config_get_path (notmuch_config_t *config)
-{
- return config->filename;
-}
/* Save any changes made to the notmuch configuration.
*
* Any comments originally in the file will be preserved.
* printing a description of the error to stderr).
*/
int
-notmuch_config_save (notmuch_config_t *config)
+notmuch_conffile_save (notmuch_conffile_t *config)
{
size_t length;
char *data, *filename;
}
/* Try not to overwrite symlinks. */
- filename = canonicalize_file_name (config->filename);
+ filename = notmuch_canonicalize_file_name (config->filename);
if (! filename) {
if (errno == ENOENT) {
filename = strdup (config->filename);
}
bool
-notmuch_config_is_new (notmuch_config_t *config)
+notmuch_conffile_is_new (notmuch_conffile_t *config)
{
return config->is_new;
}
-static const char *
-_config_get (notmuch_config_t *config, char **field,
- const char *group, const char *key)
-{
- /* read from config file and cache value, if not cached already */
- if (*field == NULL) {
- char *value;
- value = g_key_file_get_string (config->key_file, group, key, NULL);
- if (value) {
- *field = talloc_strdup (config, value);
- free (value);
- }
- }
- return *field;
-}
-
static void
-_config_set (notmuch_config_t *config, char **field,
+_config_set (notmuch_conffile_t *config,
const char *group, const char *key, const char *value)
{
g_key_file_set_string (config->key_file, group, key, value);
-
- /* drop the cached value */
- talloc_free (*field);
- *field = NULL;
-}
-
-static const char **
-_config_get_list (notmuch_config_t *config,
- const char *section, const char *key,
- const char ***outlist, size_t *list_length, size_t *ret_length)
-{
- assert (outlist);
-
- /* read from config file and cache value, if not cached already */
- if (*outlist == NULL) {
-
- char **inlist = g_key_file_get_string_list (config->key_file,
- section, key, list_length, NULL);
- if (inlist) {
- unsigned int i;
-
- *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
-
- for (i = 0; i < *list_length; i++)
- (*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
-
- (*outlist)[i] = NULL;
-
- g_strfreev (inlist);
- }
- }
-
- if (ret_length)
- *ret_length = *list_length;
-
- return *outlist;
}
static void
-_config_set_list (notmuch_config_t *config,
+_config_set_list (notmuch_conffile_t *config,
const char *group, const char *key,
const char *list[],
- size_t length, const char ***config_var )
+ size_t length)
{
g_key_file_set_string_list (config->key_file, group, key, list, length);
-
- /* drop the cached value */
- talloc_free (*config_var);
- *config_var = NULL;
-}
-
-const char *
-notmuch_config_get_database_path (notmuch_config_t *config)
-{
- char *db_path = (char *) _config_get (config, &config->database_path, "database", "path");
-
- if (db_path && *db_path != '/') {
- /* If the path in the configuration file begins with any
- * character other than /, presume that it is relative to
- * $HOME and update as appropriate.
- */
- char *abs_path = talloc_asprintf (config, "%s/%s", getenv ("HOME"), db_path);
- talloc_free (db_path);
- db_path = config->database_path = abs_path;
- }
-
- return db_path;
-}
-
-void
-notmuch_config_set_database_path (notmuch_config_t *config,
- const char *database_path)
-{
- _config_set (config, &config->database_path, "database", "path", database_path);
-}
-
-const char *
-notmuch_config_get_user_name (notmuch_config_t *config)
-{
- return _config_get (config, &config->user_name, "user", "name");
}
void
-notmuch_config_set_user_name (notmuch_config_t *config,
- const char *user_name)
+notmuch_conffile_set_database_path (notmuch_conffile_t *config,
+ const char *database_path)
{
- _config_set (config, &config->user_name, "user", "name", user_name);
-}
-
-const char *
-notmuch_config_get_user_primary_email (notmuch_config_t *config)
-{
- return _config_get (config, &config->user_primary_email, "user", "primary_email");
+ _config_set (config, "database", "path", database_path);
}
void
-notmuch_config_set_user_primary_email (notmuch_config_t *config,
- const char *primary_email)
-{
- _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
-}
-
-const char **
-notmuch_config_get_user_other_email (notmuch_config_t *config, size_t *length)
-{
- return _config_get_list (config, "user", "other_email",
- &(config->user_other_email),
- &(config->user_other_email_length), length);
-}
-
-const char **
-notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length)
-{
- return _config_get_list (config, "new", "tags",
- &(config->new_tags),
- &(config->new_tags_length), length);
-}
-
-const char **
-notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
+notmuch_conffile_set_user_name (notmuch_conffile_t *config,
+ const char *user_name)
{
- return _config_get_list (config, "new", "ignore",
- &(config->new_ignore),
- &(config->new_ignore_length), length);
+ _config_set (config, "user", "name", user_name);
}
void
-notmuch_config_set_user_other_email (notmuch_config_t *config,
- const char *list[],
- size_t length)
+notmuch_conffile_set_user_primary_email (notmuch_conffile_t *config,
+ const char *primary_email)
{
- _config_set_list (config, "user", "other_email", list, length,
- &(config->user_other_email));
+ _config_set (config, "user", "primary_email", primary_email);
}
void
-notmuch_config_set_new_tags (notmuch_config_t *config,
- const char *list[],
- size_t length)
+notmuch_conffile_set_user_other_email (notmuch_conffile_t *config,
+ const char *list[],
+ size_t length)
{
- _config_set_list (config, "new", "tags", list, length,
- &(config->new_tags));
+ _config_set_list (config, "user", "other_email", list, length);
}
void
-notmuch_config_set_new_ignore (notmuch_config_t *config,
+notmuch_conffile_set_new_tags (notmuch_conffile_t *config,
const char *list[],
size_t length)
{
- _config_set_list (config, "new", "ignore", list, length,
- &(config->new_ignore));
+ _config_set_list (config, "new", "tags", list, length);
}
-const char **
-notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
+void
+notmuch_conffile_set_new_ignore (notmuch_conffile_t *config,
+ const char *list[],
+ size_t length)
{
- return _config_get_list (config, "search", "exclude_tags",
- &(config->search_exclude_tags),
- &(config->search_exclude_tags_length), length);
+ _config_set_list (config, "new", "ignore", list, length);
}
void
-notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
- const char *list[],
- size_t length)
+notmuch_conffile_set_search_exclude_tags (notmuch_conffile_t *config,
+ const char *list[],
+ size_t length)
{
- _config_set_list (config, "search", "exclude_tags", list, length,
- &(config->search_exclude_tags));
+ _config_set_list (config, "search", "exclude_tags", list, length);
}
typedef struct config_key {
const char *name;
- bool in_db;
bool prefix;
bool (*validate)(const char *);
} config_key_info_t;
-static struct config_key
+static const struct config_key
config_key_table[] = {
- { "index.decrypt", true, false, NULL },
- { "index.header.", true, true, validate_field_name },
- { "query.", true, true, NULL },
+ { "index.decrypt", false, NULL },
+ { "index.header.", true, validate_field_name },
+ { "query.", true, NULL },
+ { "squery.", true, validate_field_name },
};
-static config_key_info_t *
+static const config_key_info_t *
_config_key_info (const char *item)
{
for (size_t i = 0; i < ARRAY_SIZE (config_key_table); i++) {
{
notmuch_config_values_t *list;
- for (list = notmuch_config_get_values_string (notmuch, item);
- notmuch_config_values_valid (list);
- notmuch_config_values_move_to_next (list)) {
- const char *val = notmuch_config_values_get (list);
- puts (val);
+ if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
+ if (notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)))
+ puts ("true");
+ else
+ puts ("false");
+ } else {
+ for (list = notmuch_config_get_values_string (notmuch, item);
+ notmuch_config_values_valid (list);
+ notmuch_config_values_move_to_next (list)) {
+ const char *val = notmuch_config_values_get (list);
+ puts (val);
+ }
}
return EXIT_SUCCESS;
}
}
static int
-notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuch, char *item,
+notmuch_config_command_set (notmuch_database_t *notmuch,
int argc, char *argv[])
{
char *group, *key;
- config_key_info_t *key_info;
+ const config_key_info_t *key_info;
+ notmuch_conffile_t *config;
+ bool update_database = false;
+ int opt_index, ret;
+ char *item;
+
+ notmuch_opt_desc_t options[] = {
+ { .opt_bool = &update_database, .name = "database" },
+ { }
+ };
+
+ opt_index = parse_arguments (argc, argv, options, 1);
+ if (opt_index < 0)
+ return EXIT_FAILURE;
+
+ argc -= opt_index;
+ argv += opt_index;
+
+ if (argc < 1) {
+ fprintf (stderr, "Error: notmuch config set requires at least "
+ "one argument.\n");
+ return EXIT_FAILURE;
+ }
+
+ item = argv[0];
+ argv++;
+ argc--;
if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
fprintf (stderr, "Error: read only option: %s\n", item);
if (key_info && key_info->validate && (! key_info->validate (item)))
return 1;
- if (key_info && key_info->in_db) {
+ if (update_database) {
return _set_db_config (notmuch, item, argc, argv);
}
if (_item_split (item, &group, &key))
return 1;
+ config = notmuch_conffile_open (notmuch,
+ notmuch_config_path (notmuch), false);
+ if (! config)
+ return 1;
+
/* With only the name of an item, we clear it from the
* configuration file.
*
break;
}
- return notmuch_config_save (config);
+ ret = notmuch_conffile_save (config);
+
+ notmuch_conffile_close (config);
+
+ return ret;
}
static
printf ("%sretry_lock=%s\n",
BUILT_WITH_PREFIX,
notmuch_built_with ("retry_lock") ? "true" : "false");
+ printf ("%ssexp_queries=%s\n",
+ BUILT_WITH_PREFIX,
+ notmuch_built_with ("sexp_queries") ? "true" : "false");
}
static int
}
int
-notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
- int argc, char *argv[])
+notmuch_config_command (notmuch_database_t *notmuch, int argc, char *argv[])
{
int ret;
int opt_index;
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;
}
ret = notmuch_config_command_get (notmuch, argv[1]);
} else if (strcmp (argv[0], "set") == 0) {
- if (argc < 2) {
- fprintf (stderr, "Error: notmuch config set requires at least "
- "one argument.\n");
- return EXIT_FAILURE;
- }
- ret = notmuch_config_command_set (config, notmuch, argv[1], argc - 2, argv + 2);
+ ret = notmuch_config_command_set (notmuch, argc, argv);
} else if (strcmp (argv[0], "list") == 0) {
ret = notmuch_config_command_list (notmuch);
} else {
}
-bool
-notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
-{
- return config->maildir_synchronize_flags;
-}
-
void
-notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
- bool synchronize_flags)
+notmuch_conffile_set_maildir_synchronize_flags (notmuch_conffile_t *config,
+ bool synchronize_flags)
{
g_key_file_set_boolean (config->key_file,
"maildir", "synchronize_flags", synchronize_flags);
- config->maildir_synchronize_flags = synchronize_flags;
}