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 (errno == ENOENT) {
219 /* If create_new is true, then the caller is prepared for a
220 * default configuration file in the case of FILE NOT FOUND.
223 config->is_new = TRUE;
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 config->filename, strerror(errno));
237 config_str = talloc_zero_array (config, char, config_bufsize);
238 if (config_str == NULL) {
239 fprintf (stderr, "Error reading '%s': Out of memory\n", config->filename);
243 while ((len = fread (config_str + config_len, 1,
244 config_bufsize - config_len, fp)) > 0) {
246 if (config_len == config_bufsize) {
247 config_bufsize += BUF_SIZE;
248 config_str = talloc_realloc (config, config_str, char, config_bufsize);
249 if (config_str == NULL) {
250 fprintf (stderr, "Error reading '%s': Failed to reallocate memory\n",
258 fprintf (stderr, "Error reading '%s': I/O error\n", config->filename);
262 if (g_key_file_load_from_data (config->key_file, config_str, config_len,
263 G_KEY_FILE_KEEP_COMMENTS, &error)) {
268 fprintf (stderr, "Error parsing config file '%s': %s\n",
269 config->filename, error->message);
271 g_error_free (error);
278 talloc_free(config_str);
283 /* Open the named notmuch configuration file. If the filename is NULL,
284 * the value of the environment variable $NOTMUCH_CONFIG will be used.
285 * If $NOTMUCH_CONFIG is unset, the default configuration file
286 * ($HOME/.notmuch-config) will be used.
288 * If any error occurs, (out of memory, or a permission-denied error,
289 * etc.), this function will print a message to stderr and return
292 * FILE NOT FOUND: When the specified configuration file (whether from
293 * 'filename' or the $NOTMUCH_CONFIG environment variable) does not
294 * exist, the behavior of this function depends on the 'is_new_ret'
297 * If is_new_ret is NULL, then a "file not found" message will be
298 * printed to stderr and NULL will be returned.
300 * If is_new_ret is non-NULL then a default configuration will be
301 * returned and *is_new_ret will be set to 1 on return so that
302 * the caller can recognize this case.
304 * These default configuration settings are determined as
307 * database_path: $MAILDIR, otherwise $HOME/mail
309 * user_name: $NAME variable if set, otherwise
310 * read from /etc/passwd
312 * user_primary_mail: $EMAIL variable if set, otherwise
313 * constructed from the username and
314 * hostname of the current machine.
316 * user_other_email: Not set.
318 * The default configuration also contains comments to guide the
319 * user in editing the file directly.
322 notmuch_config_open (void *ctx,
323 const char *filename,
324 notmuch_config_mode_t config_mode)
326 GError *error = NULL;
328 char *notmuch_config_env = NULL;
329 int file_had_database_group;
330 int file_had_new_group;
331 int file_had_user_group;
332 int file_had_maildir_group;
333 int file_had_search_group;
334 int file_had_crypto_group;
336 notmuch_config_t *config = talloc_zero (ctx, notmuch_config_t);
337 if (config == NULL) {
338 fprintf (stderr, "Out of memory.\n");
342 talloc_set_destructor (config, notmuch_config_destructor);
344 /* non-zero defaults */
345 config->maildir_synchronize_flags = TRUE;
348 config->filename = talloc_strdup (config, filename);
349 } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) {
350 config->filename = talloc_strdup (config, notmuch_config_env);
352 config->filename = talloc_asprintf (config, "%s/.notmuch-config",
356 config->key_file = g_key_file_new ();
358 if (config_mode & NOTMUCH_CONFIG_OPEN) {
359 notmuch_bool_t create_new = (config_mode & NOTMUCH_CONFIG_CREATE) != 0;
361 if (! get_config_from_file (config, create_new)) {
362 talloc_free (config);
367 /* Whenever we know of configuration sections that don't appear in
368 * the configuration file, we add some comments to help the user
369 * understand what can be done.
371 * It would be convenient to just add those comments now, but
372 * apparently g_key_file will clear any comments when keys are
373 * added later that create the groups. So we have to check for the
374 * groups now, but add the comments only after setting all of our
377 file_had_database_group = g_key_file_has_group (config->key_file,
379 file_had_new_group = g_key_file_has_group (config->key_file, "new");
380 file_had_user_group = g_key_file_has_group (config->key_file, "user");
381 file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
382 file_had_search_group = g_key_file_has_group (config->key_file, "search");
383 file_had_crypto_group = g_key_file_has_group (config->key_file, "crypto");
385 if (notmuch_config_get_database_path (config) == NULL) {
386 char *path = getenv ("MAILDIR");
388 path = talloc_strdup (config, path);
390 path = talloc_asprintf (config, "%s/mail",
392 notmuch_config_set_database_path (config, path);
396 if (notmuch_config_get_user_name (config) == NULL) {
397 char *name = getenv ("NAME");
399 name = talloc_strdup (config, name);
401 name = get_name_from_passwd_file (config);
402 notmuch_config_set_user_name (config, name);
406 if (notmuch_config_get_user_primary_email (config) == NULL) {
407 char *email = getenv ("EMAIL");
409 notmuch_config_set_user_primary_email (config, email);
412 struct hostent *hostent;
413 const char *domainname;
415 char *username = get_username_from_passwd_file (config);
417 gethostname (hostname, 256);
418 hostname[255] = '\0';
420 hostent = gethostbyname (hostname);
421 if (hostent && (domainname = strchr (hostent->h_name, '.')))
424 domainname = "(none)";
426 email = talloc_asprintf (config, "%s@%s.%s",
427 username, hostname, domainname);
429 notmuch_config_set_user_primary_email (config, email);
431 talloc_free (username);
436 if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
437 const char *tags[] = { "unread", "inbox" };
438 notmuch_config_set_new_tags (config, tags, 2);
441 if (notmuch_config_get_new_ignore (config, &tmp) == NULL) {
442 notmuch_config_set_new_ignore (config, NULL, 0);
445 if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) {
446 if (config->is_new) {
447 const char *tags[] = { "deleted", "spam" };
448 notmuch_config_set_search_exclude_tags (config, tags, 2);
450 notmuch_config_set_search_exclude_tags (config, NULL, 0);
455 config->maildir_synchronize_flags =
456 g_key_file_get_boolean (config->key_file,
457 "maildir", "synchronize_flags", &error);
459 notmuch_config_set_maildir_synchronize_flags (config, TRUE);
460 g_error_free (error);
463 if (notmuch_config_get_crypto_gpg_path (config) == NULL) {
464 notmuch_config_set_crypto_gpg_path (config, "gpg");
467 /* Whenever we know of configuration sections that don't appear in
468 * the configuration file, we add some comments to help the user
469 * understand what can be done. */
471 g_key_file_set_comment (config->key_file, NULL, NULL,
472 toplevel_config_comment, NULL);
474 if (! file_had_database_group)
475 g_key_file_set_comment (config->key_file, "database", NULL,
476 database_config_comment, NULL);
478 if (! file_had_new_group)
479 g_key_file_set_comment (config->key_file, "new", NULL,
480 new_config_comment, NULL);
482 if (! file_had_user_group)
483 g_key_file_set_comment (config->key_file, "user", NULL,
484 user_config_comment, NULL);
486 if (! file_had_maildir_group)
487 g_key_file_set_comment (config->key_file, "maildir", NULL,
488 maildir_config_comment, NULL);
490 if (! file_had_search_group)
491 g_key_file_set_comment (config->key_file, "search", NULL,
492 search_config_comment, NULL);
494 if (! file_had_crypto_group)
495 g_key_file_set_comment (config->key_file, "crypto", NULL,
496 crypto_config_comment, NULL);
501 /* Close the given notmuch_config_t object, freeing all resources.
503 * Note: Any changes made to the configuration are *not* saved by this
504 * function. To save changes, call notmuch_config_save before
505 * notmuch_config_close.
508 notmuch_config_close (notmuch_config_t *config)
510 talloc_free (config);
513 /* Save any changes made to the notmuch configuration.
515 * Any comments originally in the file will be preserved.
517 * Returns 0 if successful, and 1 in case of any error, (after
518 * printing a description of the error to stderr).
521 notmuch_config_save (notmuch_config_t *config)
524 char *data, *filename;
525 GError *error = NULL;
527 data = g_key_file_to_data (config->key_file, &length, NULL);
529 fprintf (stderr, "Out of memory.\n");
533 /* Try not to overwrite symlinks. */
534 filename = canonicalize_file_name (config->filename);
536 if (errno == ENOENT) {
537 filename = strdup (config->filename);
539 fprintf (stderr, "Out of memory.\n");
544 fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename,
551 if (! g_file_set_contents (filename, data, length, &error)) {
552 if (strcmp (filename, config->filename) != 0) {
553 fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n",
554 config->filename, filename, error->message);
556 fprintf (stderr, "Error saving configuration to %s: %s\n",
557 filename, error->message);
559 g_error_free (error);
571 notmuch_config_is_new (notmuch_config_t *config)
573 return config->is_new;
577 _config_get (notmuch_config_t *config, char **field,
578 const char *group, const char *key)
580 /* read from config file and cache value, if not cached already */
581 if (*field == NULL) {
583 value = g_key_file_get_string (config->key_file, group, key, NULL);
585 *field = talloc_strdup (config, value);
593 _config_set (notmuch_config_t *config, char **field,
594 const char *group, const char *key, const char *value)
596 g_key_file_set_string (config->key_file, group, key, value);
598 /* drop the cached value */
599 talloc_free (*field);
604 _config_get_list (notmuch_config_t *config,
605 const char *section, const char *key,
606 const char ***outlist, size_t *list_length, size_t *ret_length)
610 /* read from config file and cache value, if not cached already */
611 if (*outlist == NULL) {
613 char **inlist = g_key_file_get_string_list (config->key_file,
614 section, key, list_length, NULL);
618 *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
620 for (i = 0; i < *list_length; i++)
621 (*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
623 (*outlist)[i] = NULL;
630 *ret_length = *list_length;
636 _config_set_list (notmuch_config_t *config,
637 const char *group, const char *key,
639 size_t length, const char ***config_var )
641 g_key_file_set_string_list (config->key_file, group, key, list, length);
643 /* drop the cached value */
644 talloc_free (*config_var);
649 notmuch_config_get_database_path (notmuch_config_t *config)
651 return _config_get (config, &config->database_path, "database", "path");
655 notmuch_config_set_database_path (notmuch_config_t *config,
656 const char *database_path)
658 _config_set (config, &config->database_path, "database", "path", database_path);
662 notmuch_config_get_user_name (notmuch_config_t *config)
664 return _config_get (config, &config->user_name, "user", "name");
668 notmuch_config_set_user_name (notmuch_config_t *config,
669 const char *user_name)
671 _config_set (config, &config->user_name, "user", "name", user_name);
675 notmuch_config_get_user_primary_email (notmuch_config_t *config)
677 return _config_get (config, &config->user_primary_email, "user", "primary_email");
681 notmuch_config_set_user_primary_email (notmuch_config_t *config,
682 const char *primary_email)
684 _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
688 notmuch_config_get_user_other_email (notmuch_config_t *config, size_t *length)
690 return _config_get_list (config, "user", "other_email",
691 &(config->user_other_email),
692 &(config->user_other_email_length), length);
696 notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length)
698 return _config_get_list (config, "new", "tags",
700 &(config->new_tags_length), length);
704 notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
706 return _config_get_list (config, "new", "ignore",
707 &(config->new_ignore),
708 &(config->new_ignore_length), length);
712 notmuch_config_set_user_other_email (notmuch_config_t *config,
716 _config_set_list (config, "user", "other_email", list, length,
717 &(config->user_other_email));
721 notmuch_config_set_new_tags (notmuch_config_t *config,
725 _config_set_list (config, "new", "tags", list, length,
726 &(config->new_tags));
730 notmuch_config_set_new_ignore (notmuch_config_t *config,
734 _config_set_list (config, "new", "ignore", list, length,
735 &(config->new_ignore));
739 notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
741 return _config_get_list (config, "search", "exclude_tags",
742 &(config->search_exclude_tags),
743 &(config->search_exclude_tags_length), length);
747 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
751 _config_set_list (config, "search", "exclude_tags", list, length,
752 &(config->search_exclude_tags));
756 notmuch_config_get_crypto_gpg_path (notmuch_config_t *config)
758 return _config_get (config, &config->crypto_gpg_path, "crypto", "gpg_path");
762 notmuch_config_set_crypto_gpg_path (notmuch_config_t *config,
763 const char *gpg_path)
765 _config_set (config, &config->crypto_gpg_path, "crypto", "gpg_path", gpg_path);
769 /* Given a configuration item of the form <group>.<key> return the
770 * component group and key. If any error occurs, print a message on
771 * stderr and return 1. Otherwise, return 0.
773 * Note: This function modifies the original 'item' string.
776 _item_split (char *item, char **group, char **key)
782 period = strchr (item, '.');
783 if (period == NULL || *(period+1) == '\0') {
785 "Invalid configuration name: %s\n"
786 "(Should be of the form <section>.<item>)\n", item);
796 #define BUILT_WITH_PREFIX "built_with."
797 #define QUERY_PREFIX "query."
800 _print_db_config(notmuch_config_t *config, const char *name)
802 notmuch_database_t *notmuch;
805 if (notmuch_database_open (notmuch_config_get_database_path (config),
806 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
809 /* XXX Handle UUID mismatch? */
811 if (print_status_database ("notmuch config", notmuch,
812 notmuch_database_get_config (notmuch, name, &val)))
821 notmuch_config_command_get (notmuch_config_t *config, char *item)
823 if (strcmp(item, "database.path") == 0) {
824 printf ("%s\n", notmuch_config_get_database_path (config));
825 } else if (strcmp(item, "user.name") == 0) {
826 printf ("%s\n", notmuch_config_get_user_name (config));
827 } else if (strcmp(item, "user.primary_email") == 0) {
828 printf ("%s\n", notmuch_config_get_user_primary_email (config));
829 } else if (strcmp(item, "user.other_email") == 0) {
830 const char **other_email;
833 other_email = notmuch_config_get_user_other_email (config, &length);
834 for (i = 0; i < length; i++)
835 printf ("%s\n", other_email[i]);
836 } else if (strcmp(item, "new.tags") == 0) {
840 tags = notmuch_config_get_new_tags (config, &length);
841 for (i = 0; i < length; i++)
842 printf ("%s\n", tags[i]);
843 } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
845 notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false");
846 } else if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
847 return _print_db_config (config, item);
853 if (_item_split (item, &group, &key))
856 value = g_key_file_get_string_list (config->key_file,
860 fprintf (stderr, "Unknown configuration item: %s.%s\n",
865 for (i = 0; i < length; i++)
866 printf ("%s\n", value[i]);
875 _set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv)
877 notmuch_database_t *notmuch;
878 const char *val = "";
881 /* XXX handle lists? */
882 fprintf (stderr, "notmuch config set: at most one value expected for %s\n", key);
890 if (notmuch_database_open (notmuch_config_get_database_path (config),
891 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
894 /* XXX Handle UUID mismatch? */
896 if (print_status_database ("notmuch config", notmuch,
897 notmuch_database_set_config (notmuch, key, val)))
900 if (print_status_database ("notmuch config", notmuch,
901 notmuch_database_close (notmuch)))
908 notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
912 if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
913 fprintf (stderr, "Error: read only option: %s\n", item);
917 if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
918 return _set_db_config (config, item, argc, argv);
921 if (_item_split (item, &group, &key))
924 /* With only the name of an item, we clear it from the
925 * configuration file.
927 * With a single value, we set it as a string.
929 * With multiple values, we set them as a string list.
933 g_key_file_remove_key (config->key_file, group, key, NULL);
936 g_key_file_set_string (config->key_file, group, key, argv[0]);
939 g_key_file_set_string_list (config->key_file, group, key,
940 (const gchar **) argv, argc);
944 return notmuch_config_save (config);
949 _notmuch_config_list_built_with ()
951 printf("%scompact=%s\n",
953 notmuch_built_with ("compact") ? "true" : "false");
954 printf("%sfield_processor=%s\n",
956 notmuch_built_with ("field_processor") ? "true" : "false");
957 printf("%sretry_lock=%s\n",
959 notmuch_built_with ("retry_lock") ? "true" : "false");
963 _list_db_config (notmuch_config_t *config)
965 notmuch_database_t *notmuch;
966 notmuch_config_list_t *list;
968 if (notmuch_database_open (notmuch_config_get_database_path (config),
969 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
972 /* XXX Handle UUID mismatch? */
975 if (print_status_database ("notmuch config", notmuch,
976 notmuch_database_get_config_list (notmuch, "", &list)))
979 for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
980 printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
982 notmuch_config_list_destroy (list);
988 notmuch_config_command_list (notmuch_config_t *config)
991 size_t g, groups_length;
993 groups = g_key_file_get_groups (config->key_file, &groups_length);
997 for (g = 0; g < groups_length; g++) {
999 size_t k, keys_length;
1001 keys = g_key_file_get_keys (config->key_file,
1002 groups[g], &keys_length, NULL);
1006 for (k = 0; k < keys_length; k++) {
1009 value = g_key_file_get_string (config->key_file,
1010 groups[g], keys[k], NULL);
1011 if (value != NULL) {
1012 printf ("%s.%s=%s\n", groups[g], keys[k], value);
1020 g_strfreev (groups);
1022 _notmuch_config_list_built_with ();
1023 return _list_db_config (config);
1027 notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
1032 opt_index = notmuch_minimal_options ("config", argc, argv);
1034 return EXIT_FAILURE;
1036 if (notmuch_requested_db_uuid)
1037 fprintf (stderr, "Warning: ignoring --uuid=%s\n",
1038 notmuch_requested_db_uuid);
1040 /* skip at least subcommand argument */
1045 fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
1046 return EXIT_FAILURE;
1049 if (strcmp (argv[0], "get") == 0) {
1051 fprintf (stderr, "Error: notmuch config get requires exactly "
1053 return EXIT_FAILURE;
1055 ret = notmuch_config_command_get (config, argv[1]);
1056 } else if (strcmp (argv[0], "set") == 0) {
1058 fprintf (stderr, "Error: notmuch config set requires at least "
1060 return EXIT_FAILURE;
1062 ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
1063 } else if (strcmp (argv[0], "list") == 0) {
1064 ret = notmuch_config_command_list (config);
1066 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
1068 return EXIT_FAILURE;
1071 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
1076 notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
1078 return config->maildir_synchronize_flags;
1082 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
1083 notmuch_bool_t synchronize_flags)
1085 g_key_file_set_boolean (config->key_file,
1086 "maildir", "synchronize_flags", synchronize_flags);
1087 config->maildir_synchronize_flags = synchronize_flags;