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 (ctx, notmuch_config_t);
338 if (config == NULL) {
339 fprintf (stderr, "Out of memory.\n");
343 talloc_set_destructor (config, notmuch_config_destructor);
346 config->filename = talloc_strdup (config, filename);
347 } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) {
348 config->filename = talloc_strdup (config, notmuch_config_env);
350 config->filename = talloc_asprintf (config, "%s/.notmuch-config",
354 config->key_file = g_key_file_new ();
356 config->is_new = FALSE;
357 config->database_path = NULL;
358 config->user_name = NULL;
359 config->user_primary_email = NULL;
360 config->user_other_email = NULL;
361 config->user_other_email_length = 0;
362 config->new_tags = NULL;
363 config->new_tags_length = 0;
364 config->new_ignore = NULL;
365 config->new_ignore_length = 0;
366 config->maildir_synchronize_flags = TRUE;
367 config->search_exclude_tags = NULL;
368 config->search_exclude_tags_length = 0;
369 config->crypto_gpg_path = NULL;
371 if (! get_config_from_file (config, create_new)) {
372 talloc_free (config);
376 /* Whenever we know of configuration sections that don't appear in
377 * the configuration file, we add some comments to help the user
378 * understand what can be done.
380 * It would be convenient to just add those comments now, but
381 * apparently g_key_file will clear any comments when keys are
382 * added later that create the groups. So we have to check for the
383 * groups now, but add the comments only after setting all of our
386 file_had_database_group = g_key_file_has_group (config->key_file,
388 file_had_new_group = g_key_file_has_group (config->key_file, "new");
389 file_had_user_group = g_key_file_has_group (config->key_file, "user");
390 file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
391 file_had_search_group = g_key_file_has_group (config->key_file, "search");
392 file_had_crypto_group = g_key_file_has_group (config->key_file, "crypto");
394 if (notmuch_config_get_database_path (config) == NULL) {
395 char *path = getenv ("MAILDIR");
397 path = talloc_strdup (config, path);
399 path = talloc_asprintf (config, "%s/mail",
401 notmuch_config_set_database_path (config, path);
405 if (notmuch_config_get_user_name (config) == NULL) {
406 char *name = getenv ("NAME");
408 name = talloc_strdup (config, name);
410 name = get_name_from_passwd_file (config);
411 notmuch_config_set_user_name (config, name);
415 if (notmuch_config_get_user_primary_email (config) == NULL) {
416 char *email = getenv ("EMAIL");
418 notmuch_config_set_user_primary_email (config, email);
421 struct hostent *hostent;
422 const char *domainname;
424 char *username = get_username_from_passwd_file (config);
426 gethostname (hostname, 256);
427 hostname[255] = '\0';
429 hostent = gethostbyname (hostname);
430 if (hostent && (domainname = strchr (hostent->h_name, '.')))
433 domainname = "(none)";
435 email = talloc_asprintf (config, "%s@%s.%s",
436 username, hostname, domainname);
438 notmuch_config_set_user_primary_email (config, email);
440 talloc_free (username);
445 if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
446 const char *tags[] = { "unread", "inbox" };
447 notmuch_config_set_new_tags (config, tags, 2);
450 if (notmuch_config_get_new_ignore (config, &tmp) == NULL) {
451 notmuch_config_set_new_ignore (config, NULL, 0);
454 if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) {
455 if (config->is_new) {
456 const char *tags[] = { "deleted", "spam" };
457 notmuch_config_set_search_exclude_tags (config, tags, 2);
459 notmuch_config_set_search_exclude_tags (config, NULL, 0);
464 config->maildir_synchronize_flags =
465 g_key_file_get_boolean (config->key_file,
466 "maildir", "synchronize_flags", &error);
468 notmuch_config_set_maildir_synchronize_flags (config, TRUE);
469 g_error_free (error);
472 if (notmuch_config_get_crypto_gpg_path (config) == NULL) {
473 notmuch_config_set_crypto_gpg_path (config, "gpg");
476 /* Whenever we know of configuration sections that don't appear in
477 * the configuration file, we add some comments to help the user
478 * understand what can be done. */
480 g_key_file_set_comment (config->key_file, NULL, NULL,
481 toplevel_config_comment, NULL);
483 if (! file_had_database_group)
484 g_key_file_set_comment (config->key_file, "database", NULL,
485 database_config_comment, NULL);
487 if (! file_had_new_group)
488 g_key_file_set_comment (config->key_file, "new", NULL,
489 new_config_comment, NULL);
491 if (! file_had_user_group)
492 g_key_file_set_comment (config->key_file, "user", NULL,
493 user_config_comment, NULL);
495 if (! file_had_maildir_group)
496 g_key_file_set_comment (config->key_file, "maildir", NULL,
497 maildir_config_comment, NULL);
499 if (! file_had_search_group)
500 g_key_file_set_comment (config->key_file, "search", NULL,
501 search_config_comment, NULL);
503 if (! file_had_crypto_group)
504 g_key_file_set_comment (config->key_file, "crypto", NULL,
505 crypto_config_comment, NULL);
510 /* Close the given notmuch_config_t object, freeing all resources.
512 * Note: Any changes made to the configuration are *not* saved by this
513 * function. To save changes, call notmuch_config_save before
514 * notmuch_config_close.
517 notmuch_config_close (notmuch_config_t *config)
519 talloc_free (config);
522 /* Save any changes made to the notmuch configuration.
524 * Any comments originally in the file will be preserved.
526 * Returns 0 if successful, and 1 in case of any error, (after
527 * printing a description of the error to stderr).
530 notmuch_config_save (notmuch_config_t *config)
533 char *data, *filename;
534 GError *error = NULL;
536 data = g_key_file_to_data (config->key_file, &length, NULL);
538 fprintf (stderr, "Out of memory.\n");
542 /* Try not to overwrite symlinks. */
543 filename = canonicalize_file_name (config->filename);
545 if (errno == ENOENT) {
546 filename = strdup (config->filename);
548 fprintf (stderr, "Out of memory.\n");
553 fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename,
560 if (! g_file_set_contents (filename, data, length, &error)) {
561 if (strcmp (filename, config->filename) != 0) {
562 fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n",
563 config->filename, filename, error->message);
565 fprintf (stderr, "Error saving configuration to %s: %s\n",
566 filename, error->message);
568 g_error_free (error);
580 notmuch_config_is_new (notmuch_config_t *config)
582 return config->is_new;
586 _config_get (notmuch_config_t *config, char **field,
587 const char *group, const char *key)
589 /* read from config file and cache value, if not cached already */
590 if (*field == NULL) {
592 value = g_key_file_get_string (config->key_file, group, key, NULL);
594 *field = talloc_strdup (config, value);
602 _config_set (notmuch_config_t *config, char **field,
603 const char *group, const char *key, const char *value)
605 g_key_file_set_string (config->key_file, group, key, value);
607 /* drop the cached value */
608 talloc_free (*field);
613 _config_get_list (notmuch_config_t *config,
614 const char *section, const char *key,
615 const char ***outlist, size_t *list_length, size_t *ret_length)
619 /* read from config file and cache value, if not cached already */
620 if (*outlist == NULL) {
622 char **inlist = g_key_file_get_string_list (config->key_file,
623 section, key, list_length, NULL);
627 *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
629 for (i = 0; i < *list_length; i++)
630 (*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
632 (*outlist)[i] = NULL;
639 *ret_length = *list_length;
645 _config_set_list (notmuch_config_t *config,
646 const char *group, const char *name,
648 size_t length, const char ***config_var )
650 g_key_file_set_string_list (config->key_file, group, name, list, length);
652 /* drop the cached value */
653 talloc_free (*config_var);
658 notmuch_config_get_database_path (notmuch_config_t *config)
660 return _config_get (config, &config->database_path, "database", "path");
664 notmuch_config_set_database_path (notmuch_config_t *config,
665 const char *database_path)
667 _config_set (config, &config->database_path, "database", "path", database_path);
671 notmuch_config_get_user_name (notmuch_config_t *config)
673 return _config_get (config, &config->user_name, "user", "name");
677 notmuch_config_set_user_name (notmuch_config_t *config,
678 const char *user_name)
680 _config_set (config, &config->user_name, "user", "name", user_name);
684 notmuch_config_get_user_primary_email (notmuch_config_t *config)
686 return _config_get (config, &config->user_primary_email, "user", "primary_email");
690 notmuch_config_set_user_primary_email (notmuch_config_t *config,
691 const char *primary_email)
693 _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
697 notmuch_config_get_user_other_email (notmuch_config_t *config, size_t *length)
699 return _config_get_list (config, "user", "other_email",
700 &(config->user_other_email),
701 &(config->user_other_email_length), length);
705 notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length)
707 return _config_get_list (config, "new", "tags",
709 &(config->new_tags_length), length);
713 notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
715 return _config_get_list (config, "new", "ignore",
716 &(config->new_ignore),
717 &(config->new_ignore_length), length);
721 notmuch_config_set_user_other_email (notmuch_config_t *config,
725 _config_set_list (config, "user", "other_email", list, length,
726 &(config->user_other_email));
730 notmuch_config_set_new_tags (notmuch_config_t *config,
734 _config_set_list (config, "new", "tags", list, length,
735 &(config->new_tags));
739 notmuch_config_set_new_ignore (notmuch_config_t *config,
743 _config_set_list (config, "new", "ignore", list, length,
744 &(config->new_ignore));
748 notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
750 return _config_get_list (config, "search", "exclude_tags",
751 &(config->search_exclude_tags),
752 &(config->search_exclude_tags_length), length);
756 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
760 _config_set_list (config, "search", "exclude_tags", list, length,
761 &(config->search_exclude_tags));
765 notmuch_config_get_crypto_gpg_path (notmuch_config_t *config)
767 return _config_get (config, &config->crypto_gpg_path, "crypto", "gpg_path");
771 notmuch_config_set_crypto_gpg_path (notmuch_config_t *config,
772 const char *gpg_path)
774 _config_set (config, &config->crypto_gpg_path, "crypto", "gpg_path", gpg_path);
778 /* Given a configuration item of the form <group>.<key> return the
779 * component group and key. If any error occurs, print a message on
780 * stderr and return 1. Otherwise, return 0.
782 * Note: This function modifies the original 'item' string.
785 _item_split (char *item, char **group, char **key)
791 period = strchr (item, '.');
792 if (period == NULL || *(period+1) == '\0') {
794 "Invalid configuration name: %s\n"
795 "(Should be of the form <section>.<item>)\n", item);
805 #define BUILT_WITH_PREFIX "built_with."
806 #define QUERY_PREFIX "query."
809 _print_db_config(notmuch_config_t *config, const char *name)
811 notmuch_database_t *notmuch;
814 if (notmuch_database_open (notmuch_config_get_database_path (config),
815 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
818 /* XXX Handle UUID mismatch? */
820 if (print_status_database ("notmuch config", notmuch,
821 notmuch_database_get_config (notmuch, name, &val)))
830 notmuch_config_command_get (notmuch_config_t *config, char *item)
832 if (strcmp(item, "database.path") == 0) {
833 printf ("%s\n", notmuch_config_get_database_path (config));
834 } else if (strcmp(item, "user.name") == 0) {
835 printf ("%s\n", notmuch_config_get_user_name (config));
836 } else if (strcmp(item, "user.primary_email") == 0) {
837 printf ("%s\n", notmuch_config_get_user_primary_email (config));
838 } else if (strcmp(item, "user.other_email") == 0) {
839 const char **other_email;
842 other_email = notmuch_config_get_user_other_email (config, &length);
843 for (i = 0; i < length; i++)
844 printf ("%s\n", other_email[i]);
845 } else if (strcmp(item, "new.tags") == 0) {
849 tags = notmuch_config_get_new_tags (config, &length);
850 for (i = 0; i < length; i++)
851 printf ("%s\n", tags[i]);
852 } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
854 notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false");
855 } else if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
856 return _print_db_config (config, item);
862 if (_item_split (item, &group, &key))
865 value = g_key_file_get_string_list (config->key_file,
869 fprintf (stderr, "Unknown configuration item: %s.%s\n",
874 for (i = 0; i < length; i++)
875 printf ("%s\n", value[i]);
884 _set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv)
886 notmuch_database_t *notmuch;
887 const char *val = "";
890 /* XXX handle lists? */
891 fprintf (stderr, "notmuch config set: at most one value expected for %s\n", key);
899 if (notmuch_database_open (notmuch_config_get_database_path (config),
900 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
903 /* XXX Handle UUID mismatch? */
905 if (print_status_database ("notmuch config", notmuch,
906 notmuch_database_set_config (notmuch, key, val)))
909 if (print_status_database ("notmuch config", notmuch,
910 notmuch_database_close (notmuch)))
917 notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
921 if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
922 fprintf (stderr, "Error: read only option: %s\n", item);
926 if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
927 return _set_db_config (config, item, argc, argv);
930 if (_item_split (item, &group, &key))
933 /* With only the name of an item, we clear it from the
934 * configuration file.
936 * With a single value, we set it as a string.
938 * With multiple values, we set them as a string list.
942 g_key_file_remove_key (config->key_file, group, key, NULL);
945 g_key_file_set_string (config->key_file, group, key, argv[0]);
948 g_key_file_set_string_list (config->key_file, group, key,
949 (const gchar **) argv, argc);
953 return notmuch_config_save (config);
958 _notmuch_config_list_built_with ()
960 printf("%scompact=%s\n",
962 notmuch_built_with ("compact") ? "true" : "false");
963 printf("%sfield_processor=%s\n",
965 notmuch_built_with ("field_processor") ? "true" : "false");
966 printf("%sretry_lock=%s\n",
968 notmuch_built_with ("retry_lock") ? "true" : "false");
972 _list_db_config (notmuch_config_t *config)
974 notmuch_database_t *notmuch;
975 notmuch_config_list_t *list;
977 if (notmuch_database_open (notmuch_config_get_database_path (config),
978 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
981 /* XXX Handle UUID mismatch? */
984 if (print_status_database ("notmuch config", notmuch,
985 notmuch_database_get_config_list (notmuch, "", &list)))
988 for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
989 printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
991 notmuch_config_list_destroy (list);
997 notmuch_config_command_list (notmuch_config_t *config)
1000 size_t g, groups_length;
1002 groups = g_key_file_get_groups (config->key_file, &groups_length);
1006 for (g = 0; g < groups_length; g++) {
1008 size_t k, keys_length;
1010 keys = g_key_file_get_keys (config->key_file,
1011 groups[g], &keys_length, NULL);
1015 for (k = 0; k < keys_length; k++) {
1018 value = g_key_file_get_string (config->key_file,
1019 groups[g], keys[k], NULL);
1020 if (value != NULL) {
1021 printf ("%s.%s=%s\n", groups[g], keys[k], value);
1029 g_strfreev (groups);
1031 _notmuch_config_list_built_with ();
1032 return _list_db_config (config);
1036 notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
1041 opt_index = notmuch_minimal_options ("config", argc, argv);
1043 return EXIT_FAILURE;
1045 if (notmuch_requested_db_uuid)
1046 fprintf (stderr, "Warning: ignoring --uuid=%s\n",
1047 notmuch_requested_db_uuid);
1049 /* skip at least subcommand argument */
1054 fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
1055 return EXIT_FAILURE;
1058 if (strcmp (argv[0], "get") == 0) {
1060 fprintf (stderr, "Error: notmuch config get requires exactly "
1062 return EXIT_FAILURE;
1064 ret = notmuch_config_command_get (config, argv[1]);
1065 } else if (strcmp (argv[0], "set") == 0) {
1067 fprintf (stderr, "Error: notmuch config set requires at least "
1069 return EXIT_FAILURE;
1071 ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
1072 } else if (strcmp (argv[0], "list") == 0) {
1073 ret = notmuch_config_command_list (config);
1075 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
1077 return EXIT_FAILURE;
1080 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
1085 notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
1087 return config->maildir_synchronize_flags;
1091 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
1092 notmuch_bool_t synchronize_flags)
1094 g_key_file_set_boolean (config->key_file,
1095 "maildir", "synchronize_flags", synchronize_flags);
1096 config->maildir_synchronize_flags = synchronize_flags;