1 /* notmuch - Not much of an email program, (just index and search)
3 * Copyright © 2009 Carl Worth
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see https://www.gnu.org/licenses/ .
18 * Author: Carl Worth <cworth@cworth.org>
21 #include "notmuch-client.h"
27 static const char toplevel_config_comment[] =
28 " .notmuch-config - Configuration file for the notmuch mail system\n"
30 " For more information about notmuch, see https://notmuchmail.org";
32 static const char database_config_comment[] =
33 " Database configuration\n"
35 " The only value supported here is 'path' which should be the top-level\n"
36 " directory where your mail currently exists and to where mail will be\n"
37 " delivered in the future. Files should be individual email messages.\n"
38 " Notmuch will store its database within a sub-directory of the path\n"
39 " configured here named \".notmuch\".\n";
41 static const char new_config_comment[] =
42 " Configuration for \"notmuch new\"\n"
44 " The following options are supported here:\n"
46 "\ttags A list (separated by ';') of the tags that will be\n"
47 "\t added to all messages incorporated by \"notmuch new\".\n"
49 "\tignore A list (separated by ';') of file and directory names\n"
50 "\t that will not be searched for messages by \"notmuch new\".\n"
52 "\t NOTE: *Every* file/directory that goes by one of those\n"
53 "\t names will be ignored, independent of its depth/location\n"
54 "\t in the mail store.\n";
56 static const char user_config_comment[] =
57 " User configuration\n"
59 " Here is where you can let notmuch know how you would like to be\n"
60 " addressed. Valid settings are\n"
62 "\tname Your full name.\n"
63 "\tprimary_email Your primary email address.\n"
64 "\tother_email A list (separated by ';') of other email addresses\n"
65 "\t at which you receive email.\n"
67 " Notmuch will use the various email addresses configured here when\n"
68 " formatting replies. It will avoid including your own addresses in the\n"
69 " recipient list of replies, and will set the From address based on the\n"
70 " address to which the original email was addressed.\n";
72 static const char maildir_config_comment[] =
73 " Maildir compatibility configuration\n"
75 " The following option is supported here:\n"
77 "\tsynchronize_flags Valid values are true and false.\n"
79 "\tIf true, then the following maildir flags (in message filenames)\n"
80 "\twill be synchronized with the corresponding notmuch tags:\n"
88 "\t\tS unread (added when 'S' flag is not present)\n"
90 "\tThe \"notmuch new\" command will notice flag changes in filenames\n"
91 "\tand update tags, while the \"notmuch tag\" and \"notmuch restore\"\n"
92 "\tcommands will notice tag changes and update flags in filenames\n";
94 static const char search_config_comment[] =
95 " Search configuration\n"
97 " The following option is supported here:\n"
100 "\t\tA ;-separated list of tags that will be excluded from\n"
101 "\t\tsearch results by default. Using an excluded tag in a\n"
102 "\t\tquery will override that exclusion.\n";
104 static const char crypto_config_comment[] =
105 " Cryptography related configuration\n"
107 " The following option is supported here:\n"
110 "\t\tbinary name or full path to invoke gpg.\n";
112 struct _notmuch_config {
115 notmuch_bool_t is_new;
118 char *crypto_gpg_path;
120 char *user_primary_email;
121 const char **user_other_email;
122 size_t user_other_email_length;
123 const char **new_tags;
124 size_t new_tags_length;
125 const char **new_ignore;
126 size_t new_ignore_length;
127 notmuch_bool_t maildir_synchronize_flags;
128 const char **search_exclude_tags;
129 size_t search_exclude_tags_length;
133 notmuch_config_destructor (notmuch_config_t *config)
135 if (config->key_file)
136 g_key_file_free (config->key_file);
142 get_name_from_passwd_file (void *ctx)
146 struct passwd passwd, *ignored;
150 pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
151 if (pw_buf_size == -1) pw_buf_size = 64;
152 pw_buf = talloc_size (ctx, pw_buf_size);
154 while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
155 pw_buf_size, &ignored)) == ERANGE) {
156 pw_buf_size = pw_buf_size * 2;
157 pw_buf = talloc_zero_size(ctx, pw_buf_size);
161 char *comma = strchr (passwd.pw_gecos, ',');
163 name = talloc_strndup (ctx, passwd.pw_gecos,
164 comma - passwd.pw_gecos);
166 name = talloc_strdup (ctx, passwd.pw_gecos);
168 name = talloc_strdup (ctx, "");
171 talloc_free (pw_buf);
177 get_username_from_passwd_file (void *ctx)
181 struct passwd passwd, *ignored;
185 pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
186 if (pw_buf_size == -1) pw_buf_size = 64;
187 pw_buf = talloc_zero_size (ctx, pw_buf_size);
189 while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
190 pw_buf_size, &ignored)) == ERANGE) {
191 pw_buf_size = pw_buf_size * 2;
192 pw_buf = talloc_zero_size(ctx, pw_buf_size);
196 name = talloc_strdup (ctx, passwd.pw_name);
198 name = talloc_strdup (ctx, "");
200 talloc_free (pw_buf);
205 static notmuch_bool_t
206 get_config_from_file (notmuch_config_t *config, notmuch_bool_t create_new)
208 #define BUF_SIZE 4096
209 char *config_str = NULL;
211 int config_bufsize = BUF_SIZE;
213 GError *error = NULL;
214 notmuch_bool_t ret = FALSE;
216 FILE *fp = fopen(config->filename, "r");
218 /* If create_new is true, then the caller is prepared for a
219 * default configuration file in the case of FILE NOT FOUND.
222 config->is_new = TRUE;
225 } else if (errno == ENOENT) {
226 fprintf (stderr, "Configuration file %s not found.\n"
227 "Try running 'notmuch setup' to create a configuration.\n",
231 fprintf (stderr, "Error opening config file '%s': %s\n"
232 "Try running 'notmuch setup' to create a configuration.\n",
233 config->filename, strerror(errno));
238 config_str = talloc_zero_array (config, char, config_bufsize);
239 if (config_str == NULL) {
240 fprintf (stderr, "Error reading '%s': Out of memory\n", config->filename);
244 while ((len = fread (config_str + config_len, 1,
245 config_bufsize - config_len, fp)) > 0) {
247 if (config_len == config_bufsize) {
248 config_bufsize += BUF_SIZE;
249 config_str = talloc_realloc (config, config_str, char, config_bufsize);
250 if (config_str == NULL) {
251 fprintf (stderr, "Error reading '%s': Failed to reallocate memory\n",
259 fprintf (stderr, "Error reading '%s': I/O error\n", config->filename);
263 if (g_key_file_load_from_data (config->key_file, config_str, config_len,
264 G_KEY_FILE_KEEP_COMMENTS, &error)) {
269 fprintf (stderr, "Error parsing config file '%s': %s\n",
270 config->filename, error->message);
272 g_error_free (error);
279 talloc_free(config_str);
284 /* Open the named notmuch configuration file. If the filename is NULL,
285 * the value of the environment variable $NOTMUCH_CONFIG will be used.
286 * If $NOTMUCH_CONFIG is unset, the default configuration file
287 * ($HOME/.notmuch-config) will be used.
289 * If any error occurs, (out of memory, or a permission-denied error,
290 * etc.), this function will print a message to stderr and return
293 * FILE NOT FOUND: When the specified configuration file (whether from
294 * 'filename' or the $NOTMUCH_CONFIG environment variable) does not
295 * exist, the behavior of this function depends on the 'is_new_ret'
298 * If is_new_ret is NULL, then a "file not found" message will be
299 * printed to stderr and NULL will be returned.
301 * If is_new_ret is non-NULL then a default configuration will be
302 * returned and *is_new_ret will be set to 1 on return so that
303 * the caller can recognize this case.
305 * These default configuration settings are determined as
308 * database_path: $MAILDIR, otherwise $HOME/mail
310 * user_name: $NAME variable if set, otherwise
311 * read from /etc/passwd
313 * user_primary_mail: $EMAIL variable if set, otherwise
314 * constructed from the username and
315 * hostname of the current machine.
317 * user_other_email: Not set.
319 * The default configuration also contains comments to guide the
320 * user in editing the file directly.
323 notmuch_config_open (void *ctx,
324 const char *filename,
325 notmuch_bool_t create_new)
327 GError *error = NULL;
329 char *notmuch_config_env = NULL;
330 int file_had_database_group;
331 int file_had_new_group;
332 int file_had_user_group;
333 int file_had_maildir_group;
334 int file_had_search_group;
335 int file_had_crypto_group;
337 notmuch_config_t *config = talloc_zero (ctx, notmuch_config_t);
338 if (config == NULL) {
339 fprintf (stderr, "Out of memory.\n");
343 talloc_set_destructor (config, notmuch_config_destructor);
345 /* non-zero defaults */
346 config->maildir_synchronize_flags = TRUE;
349 config->filename = talloc_strdup (config, filename);
350 } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) {
351 config->filename = talloc_strdup (config, notmuch_config_env);
353 config->filename = talloc_asprintf (config, "%s/.notmuch-config",
357 config->key_file = g_key_file_new ();
359 if (! get_config_from_file (config, create_new)) {
360 talloc_free (config);
364 /* Whenever we know of configuration sections that don't appear in
365 * the configuration file, we add some comments to help the user
366 * understand what can be done.
368 * It would be convenient to just add those comments now, but
369 * apparently g_key_file will clear any comments when keys are
370 * added later that create the groups. So we have to check for the
371 * groups now, but add the comments only after setting all of our
374 file_had_database_group = g_key_file_has_group (config->key_file,
376 file_had_new_group = g_key_file_has_group (config->key_file, "new");
377 file_had_user_group = g_key_file_has_group (config->key_file, "user");
378 file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
379 file_had_search_group = g_key_file_has_group (config->key_file, "search");
380 file_had_crypto_group = g_key_file_has_group (config->key_file, "crypto");
382 if (notmuch_config_get_database_path (config) == NULL) {
383 char *path = getenv ("MAILDIR");
385 path = talloc_strdup (config, path);
387 path = talloc_asprintf (config, "%s/mail",
389 notmuch_config_set_database_path (config, path);
393 if (notmuch_config_get_user_name (config) == NULL) {
394 char *name = getenv ("NAME");
396 name = talloc_strdup (config, name);
398 name = get_name_from_passwd_file (config);
399 notmuch_config_set_user_name (config, name);
403 if (notmuch_config_get_user_primary_email (config) == NULL) {
404 char *email = getenv ("EMAIL");
406 notmuch_config_set_user_primary_email (config, email);
409 struct hostent *hostent;
410 const char *domainname;
412 char *username = get_username_from_passwd_file (config);
414 gethostname (hostname, 256);
415 hostname[255] = '\0';
417 hostent = gethostbyname (hostname);
418 if (hostent && (domainname = strchr (hostent->h_name, '.')))
421 domainname = "(none)";
423 email = talloc_asprintf (config, "%s@%s.%s",
424 username, hostname, domainname);
426 notmuch_config_set_user_primary_email (config, email);
428 talloc_free (username);
433 if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
434 const char *tags[] = { "unread", "inbox" };
435 notmuch_config_set_new_tags (config, tags, 2);
438 if (notmuch_config_get_new_ignore (config, &tmp) == NULL) {
439 notmuch_config_set_new_ignore (config, NULL, 0);
442 if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) {
443 if (config->is_new) {
444 const char *tags[] = { "deleted", "spam" };
445 notmuch_config_set_search_exclude_tags (config, tags, 2);
447 notmuch_config_set_search_exclude_tags (config, NULL, 0);
452 config->maildir_synchronize_flags =
453 g_key_file_get_boolean (config->key_file,
454 "maildir", "synchronize_flags", &error);
456 notmuch_config_set_maildir_synchronize_flags (config, TRUE);
457 g_error_free (error);
460 if (notmuch_config_get_crypto_gpg_path (config) == NULL) {
461 notmuch_config_set_crypto_gpg_path (config, "gpg");
464 /* Whenever we know of configuration sections that don't appear in
465 * the configuration file, we add some comments to help the user
466 * understand what can be done. */
468 g_key_file_set_comment (config->key_file, NULL, NULL,
469 toplevel_config_comment, NULL);
471 if (! file_had_database_group)
472 g_key_file_set_comment (config->key_file, "database", NULL,
473 database_config_comment, NULL);
475 if (! file_had_new_group)
476 g_key_file_set_comment (config->key_file, "new", NULL,
477 new_config_comment, NULL);
479 if (! file_had_user_group)
480 g_key_file_set_comment (config->key_file, "user", NULL,
481 user_config_comment, NULL);
483 if (! file_had_maildir_group)
484 g_key_file_set_comment (config->key_file, "maildir", NULL,
485 maildir_config_comment, NULL);
487 if (! file_had_search_group)
488 g_key_file_set_comment (config->key_file, "search", NULL,
489 search_config_comment, NULL);
491 if (! file_had_crypto_group)
492 g_key_file_set_comment (config->key_file, "crypto", NULL,
493 crypto_config_comment, NULL);
498 /* Close the given notmuch_config_t object, freeing all resources.
500 * Note: Any changes made to the configuration are *not* saved by this
501 * function. To save changes, call notmuch_config_save before
502 * notmuch_config_close.
505 notmuch_config_close (notmuch_config_t *config)
507 talloc_free (config);
510 /* Save any changes made to the notmuch configuration.
512 * Any comments originally in the file will be preserved.
514 * Returns 0 if successful, and 1 in case of any error, (after
515 * printing a description of the error to stderr).
518 notmuch_config_save (notmuch_config_t *config)
521 char *data, *filename;
522 GError *error = NULL;
524 data = g_key_file_to_data (config->key_file, &length, NULL);
526 fprintf (stderr, "Out of memory.\n");
530 /* Try not to overwrite symlinks. */
531 filename = canonicalize_file_name (config->filename);
533 if (errno == ENOENT) {
534 filename = strdup (config->filename);
536 fprintf (stderr, "Out of memory.\n");
541 fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename,
548 if (! g_file_set_contents (filename, data, length, &error)) {
549 if (strcmp (filename, config->filename) != 0) {
550 fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n",
551 config->filename, filename, error->message);
553 fprintf (stderr, "Error saving configuration to %s: %s\n",
554 filename, error->message);
556 g_error_free (error);
568 notmuch_config_is_new (notmuch_config_t *config)
570 return config->is_new;
574 _config_get (notmuch_config_t *config, char **field,
575 const char *group, const char *key)
577 /* read from config file and cache value, if not cached already */
578 if (*field == NULL) {
580 value = g_key_file_get_string (config->key_file, group, key, NULL);
582 *field = talloc_strdup (config, value);
590 _config_set (notmuch_config_t *config, char **field,
591 const char *group, const char *key, const char *value)
593 g_key_file_set_string (config->key_file, group, key, value);
595 /* drop the cached value */
596 talloc_free (*field);
601 _config_get_list (notmuch_config_t *config,
602 const char *section, const char *key,
603 const char ***outlist, size_t *list_length, size_t *ret_length)
607 /* read from config file and cache value, if not cached already */
608 if (*outlist == NULL) {
610 char **inlist = g_key_file_get_string_list (config->key_file,
611 section, key, list_length, NULL);
615 *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
617 for (i = 0; i < *list_length; i++)
618 (*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
620 (*outlist)[i] = NULL;
627 *ret_length = *list_length;
633 _config_set_list (notmuch_config_t *config,
634 const char *group, const char *key,
636 size_t length, const char ***config_var )
638 g_key_file_set_string_list (config->key_file, group, key, list, length);
640 /* drop the cached value */
641 talloc_free (*config_var);
646 notmuch_config_get_database_path (notmuch_config_t *config)
648 return _config_get (config, &config->database_path, "database", "path");
652 notmuch_config_set_database_path (notmuch_config_t *config,
653 const char *database_path)
655 _config_set (config, &config->database_path, "database", "path", database_path);
659 notmuch_config_get_user_name (notmuch_config_t *config)
661 return _config_get (config, &config->user_name, "user", "name");
665 notmuch_config_set_user_name (notmuch_config_t *config,
666 const char *user_name)
668 _config_set (config, &config->user_name, "user", "name", user_name);
672 notmuch_config_get_user_primary_email (notmuch_config_t *config)
674 return _config_get (config, &config->user_primary_email, "user", "primary_email");
678 notmuch_config_set_user_primary_email (notmuch_config_t *config,
679 const char *primary_email)
681 _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
685 notmuch_config_get_user_other_email (notmuch_config_t *config, size_t *length)
687 return _config_get_list (config, "user", "other_email",
688 &(config->user_other_email),
689 &(config->user_other_email_length), length);
693 notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length)
695 return _config_get_list (config, "new", "tags",
697 &(config->new_tags_length), length);
701 notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
703 return _config_get_list (config, "new", "ignore",
704 &(config->new_ignore),
705 &(config->new_ignore_length), length);
709 notmuch_config_set_user_other_email (notmuch_config_t *config,
713 _config_set_list (config, "user", "other_email", list, length,
714 &(config->user_other_email));
718 notmuch_config_set_new_tags (notmuch_config_t *config,
722 _config_set_list (config, "new", "tags", list, length,
723 &(config->new_tags));
727 notmuch_config_set_new_ignore (notmuch_config_t *config,
731 _config_set_list (config, "new", "ignore", list, length,
732 &(config->new_ignore));
736 notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
738 return _config_get_list (config, "search", "exclude_tags",
739 &(config->search_exclude_tags),
740 &(config->search_exclude_tags_length), length);
744 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
748 _config_set_list (config, "search", "exclude_tags", list, length,
749 &(config->search_exclude_tags));
753 notmuch_config_get_crypto_gpg_path (notmuch_config_t *config)
755 return _config_get (config, &config->crypto_gpg_path, "crypto", "gpg_path");
759 notmuch_config_set_crypto_gpg_path (notmuch_config_t *config,
760 const char *gpg_path)
762 _config_set (config, &config->crypto_gpg_path, "crypto", "gpg_path", gpg_path);
766 /* Given a configuration item of the form <group>.<key> return the
767 * component group and key. If any error occurs, print a message on
768 * stderr and return 1. Otherwise, return 0.
770 * Note: This function modifies the original 'item' string.
773 _item_split (char *item, char **group, char **key)
779 period = strchr (item, '.');
780 if (period == NULL || *(period+1) == '\0') {
782 "Invalid configuration name: %s\n"
783 "(Should be of the form <section>.<item>)\n", item);
793 #define BUILT_WITH_PREFIX "built_with."
794 #define QUERY_PREFIX "query."
797 _print_db_config(notmuch_config_t *config, const char *name)
799 notmuch_database_t *notmuch;
802 if (notmuch_database_open (notmuch_config_get_database_path (config),
803 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
806 /* XXX Handle UUID mismatch? */
808 if (print_status_database ("notmuch config", notmuch,
809 notmuch_database_get_config (notmuch, name, &val)))
818 notmuch_config_command_get (notmuch_config_t *config, char *item)
820 if (strcmp(item, "database.path") == 0) {
821 printf ("%s\n", notmuch_config_get_database_path (config));
822 } else if (strcmp(item, "user.name") == 0) {
823 printf ("%s\n", notmuch_config_get_user_name (config));
824 } else if (strcmp(item, "user.primary_email") == 0) {
825 printf ("%s\n", notmuch_config_get_user_primary_email (config));
826 } else if (strcmp(item, "user.other_email") == 0) {
827 const char **other_email;
830 other_email = notmuch_config_get_user_other_email (config, &length);
831 for (i = 0; i < length; i++)
832 printf ("%s\n", other_email[i]);
833 } else if (strcmp(item, "new.tags") == 0) {
837 tags = notmuch_config_get_new_tags (config, &length);
838 for (i = 0; i < length; i++)
839 printf ("%s\n", tags[i]);
840 } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
842 notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false");
843 } else if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
844 return _print_db_config (config, item);
850 if (_item_split (item, &group, &key))
853 value = g_key_file_get_string_list (config->key_file,
857 fprintf (stderr, "Unknown configuration item: %s.%s\n",
862 for (i = 0; i < length; i++)
863 printf ("%s\n", value[i]);
872 _set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv)
874 notmuch_database_t *notmuch;
875 const char *val = "";
878 /* XXX handle lists? */
879 fprintf (stderr, "notmuch config set: at most one value expected for %s\n", key);
887 if (notmuch_database_open (notmuch_config_get_database_path (config),
888 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
891 /* XXX Handle UUID mismatch? */
893 if (print_status_database ("notmuch config", notmuch,
894 notmuch_database_set_config (notmuch, key, val)))
897 if (print_status_database ("notmuch config", notmuch,
898 notmuch_database_close (notmuch)))
905 notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
909 if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
910 fprintf (stderr, "Error: read only option: %s\n", item);
914 if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
915 return _set_db_config (config, item, argc, argv);
918 if (_item_split (item, &group, &key))
921 /* With only the name of an item, we clear it from the
922 * configuration file.
924 * With a single value, we set it as a string.
926 * With multiple values, we set them as a string list.
930 g_key_file_remove_key (config->key_file, group, key, NULL);
933 g_key_file_set_string (config->key_file, group, key, argv[0]);
936 g_key_file_set_string_list (config->key_file, group, key,
937 (const gchar **) argv, argc);
941 return notmuch_config_save (config);
946 _notmuch_config_list_built_with ()
948 printf("%scompact=%s\n",
950 notmuch_built_with ("compact") ? "true" : "false");
951 printf("%sfield_processor=%s\n",
953 notmuch_built_with ("field_processor") ? "true" : "false");
954 printf("%sretry_lock=%s\n",
956 notmuch_built_with ("retry_lock") ? "true" : "false");
960 _list_db_config (notmuch_config_t *config)
962 notmuch_database_t *notmuch;
963 notmuch_config_list_t *list;
965 if (notmuch_database_open (notmuch_config_get_database_path (config),
966 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
969 /* XXX Handle UUID mismatch? */
972 if (print_status_database ("notmuch config", notmuch,
973 notmuch_database_get_config_list (notmuch, "", &list)))
976 for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
977 printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
979 notmuch_config_list_destroy (list);
985 notmuch_config_command_list (notmuch_config_t *config)
988 size_t g, groups_length;
990 groups = g_key_file_get_groups (config->key_file, &groups_length);
994 for (g = 0; g < groups_length; g++) {
996 size_t k, keys_length;
998 keys = g_key_file_get_keys (config->key_file,
999 groups[g], &keys_length, NULL);
1003 for (k = 0; k < keys_length; k++) {
1006 value = g_key_file_get_string (config->key_file,
1007 groups[g], keys[k], NULL);
1008 if (value != NULL) {
1009 printf ("%s.%s=%s\n", groups[g], keys[k], value);
1017 g_strfreev (groups);
1019 _notmuch_config_list_built_with ();
1020 return _list_db_config (config);
1024 notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
1029 opt_index = notmuch_minimal_options ("config", argc, argv);
1031 return EXIT_FAILURE;
1033 if (notmuch_requested_db_uuid)
1034 fprintf (stderr, "Warning: ignoring --uuid=%s\n",
1035 notmuch_requested_db_uuid);
1037 /* skip at least subcommand argument */
1042 fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
1043 return EXIT_FAILURE;
1046 if (strcmp (argv[0], "get") == 0) {
1048 fprintf (stderr, "Error: notmuch config get requires exactly "
1050 return EXIT_FAILURE;
1052 ret = notmuch_config_command_get (config, argv[1]);
1053 } else if (strcmp (argv[0], "set") == 0) {
1055 fprintf (stderr, "Error: notmuch config set requires at least "
1057 return EXIT_FAILURE;
1059 ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
1060 } else if (strcmp (argv[0], "list") == 0) {
1061 ret = notmuch_config_command_list (config);
1063 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
1065 return EXIT_FAILURE;
1068 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
1073 notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
1075 return config->maildir_synchronize_flags;
1079 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
1080 notmuch_bool_t synchronize_flags)
1082 g_key_file_set_boolean (config->key_file,
1083 "maildir", "synchronize_flags", synchronize_flags);
1084 config->maildir_synchronize_flags = synchronize_flags;