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_config_mode_t config_mode)
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 (config_mode & NOTMUCH_CONFIG_OPEN) {
360 notmuch_bool_t create_new = (config_mode & NOTMUCH_CONFIG_CREATE) != 0;
362 if (! get_config_from_file (config, create_new)) {
363 talloc_free (config);
368 /* Whenever we know of configuration sections that don't appear in
369 * the configuration file, we add some comments to help the user
370 * understand what can be done.
372 * It would be convenient to just add those comments now, but
373 * apparently g_key_file will clear any comments when keys are
374 * added later that create the groups. So we have to check for the
375 * groups now, but add the comments only after setting all of our
378 file_had_database_group = g_key_file_has_group (config->key_file,
380 file_had_new_group = g_key_file_has_group (config->key_file, "new");
381 file_had_user_group = g_key_file_has_group (config->key_file, "user");
382 file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
383 file_had_search_group = g_key_file_has_group (config->key_file, "search");
384 file_had_crypto_group = g_key_file_has_group (config->key_file, "crypto");
386 if (notmuch_config_get_database_path (config) == NULL) {
387 char *path = getenv ("MAILDIR");
389 path = talloc_strdup (config, path);
391 path = talloc_asprintf (config, "%s/mail",
393 notmuch_config_set_database_path (config, path);
397 if (notmuch_config_get_user_name (config) == NULL) {
398 char *name = getenv ("NAME");
400 name = talloc_strdup (config, name);
402 name = get_name_from_passwd_file (config);
403 notmuch_config_set_user_name (config, name);
407 if (notmuch_config_get_user_primary_email (config) == NULL) {
408 char *email = getenv ("EMAIL");
410 notmuch_config_set_user_primary_email (config, email);
413 struct hostent *hostent;
414 const char *domainname;
416 char *username = get_username_from_passwd_file (config);
418 gethostname (hostname, 256);
419 hostname[255] = '\0';
421 hostent = gethostbyname (hostname);
422 if (hostent && (domainname = strchr (hostent->h_name, '.')))
425 domainname = "(none)";
427 email = talloc_asprintf (config, "%s@%s.%s",
428 username, hostname, domainname);
430 notmuch_config_set_user_primary_email (config, email);
432 talloc_free (username);
437 if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
438 const char *tags[] = { "unread", "inbox" };
439 notmuch_config_set_new_tags (config, tags, 2);
442 if (notmuch_config_get_new_ignore (config, &tmp) == NULL) {
443 notmuch_config_set_new_ignore (config, NULL, 0);
446 if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) {
447 if (config->is_new) {
448 const char *tags[] = { "deleted", "spam" };
449 notmuch_config_set_search_exclude_tags (config, tags, 2);
451 notmuch_config_set_search_exclude_tags (config, NULL, 0);
456 config->maildir_synchronize_flags =
457 g_key_file_get_boolean (config->key_file,
458 "maildir", "synchronize_flags", &error);
460 notmuch_config_set_maildir_synchronize_flags (config, TRUE);
461 g_error_free (error);
464 if (notmuch_config_get_crypto_gpg_path (config) == NULL) {
465 notmuch_config_set_crypto_gpg_path (config, "gpg");
468 /* Whenever we know of configuration sections that don't appear in
469 * the configuration file, we add some comments to help the user
470 * understand what can be done. */
472 g_key_file_set_comment (config->key_file, NULL, NULL,
473 toplevel_config_comment, NULL);
475 if (! file_had_database_group)
476 g_key_file_set_comment (config->key_file, "database", NULL,
477 database_config_comment, NULL);
479 if (! file_had_new_group)
480 g_key_file_set_comment (config->key_file, "new", NULL,
481 new_config_comment, NULL);
483 if (! file_had_user_group)
484 g_key_file_set_comment (config->key_file, "user", NULL,
485 user_config_comment, NULL);
487 if (! file_had_maildir_group)
488 g_key_file_set_comment (config->key_file, "maildir", NULL,
489 maildir_config_comment, NULL);
491 if (! file_had_search_group)
492 g_key_file_set_comment (config->key_file, "search", NULL,
493 search_config_comment, NULL);
495 if (! file_had_crypto_group)
496 g_key_file_set_comment (config->key_file, "crypto", NULL,
497 crypto_config_comment, NULL);
502 /* Close the given notmuch_config_t object, freeing all resources.
504 * Note: Any changes made to the configuration are *not* saved by this
505 * function. To save changes, call notmuch_config_save before
506 * notmuch_config_close.
509 notmuch_config_close (notmuch_config_t *config)
511 talloc_free (config);
514 /* Save any changes made to the notmuch configuration.
516 * Any comments originally in the file will be preserved.
518 * Returns 0 if successful, and 1 in case of any error, (after
519 * printing a description of the error to stderr).
522 notmuch_config_save (notmuch_config_t *config)
525 char *data, *filename;
526 GError *error = NULL;
528 data = g_key_file_to_data (config->key_file, &length, NULL);
530 fprintf (stderr, "Out of memory.\n");
534 /* Try not to overwrite symlinks. */
535 filename = canonicalize_file_name (config->filename);
537 if (errno == ENOENT) {
538 filename = strdup (config->filename);
540 fprintf (stderr, "Out of memory.\n");
545 fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename,
552 if (! g_file_set_contents (filename, data, length, &error)) {
553 if (strcmp (filename, config->filename) != 0) {
554 fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n",
555 config->filename, filename, error->message);
557 fprintf (stderr, "Error saving configuration to %s: %s\n",
558 filename, error->message);
560 g_error_free (error);
572 notmuch_config_is_new (notmuch_config_t *config)
574 return config->is_new;
578 _config_get (notmuch_config_t *config, char **field,
579 const char *group, const char *key)
581 /* read from config file and cache value, if not cached already */
582 if (*field == NULL) {
584 value = g_key_file_get_string (config->key_file, group, key, NULL);
586 *field = talloc_strdup (config, value);
594 _config_set (notmuch_config_t *config, char **field,
595 const char *group, const char *key, const char *value)
597 g_key_file_set_string (config->key_file, group, key, value);
599 /* drop the cached value */
600 talloc_free (*field);
605 _config_get_list (notmuch_config_t *config,
606 const char *section, const char *key,
607 const char ***outlist, size_t *list_length, size_t *ret_length)
611 /* read from config file and cache value, if not cached already */
612 if (*outlist == NULL) {
614 char **inlist = g_key_file_get_string_list (config->key_file,
615 section, key, list_length, NULL);
619 *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
621 for (i = 0; i < *list_length; i++)
622 (*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
624 (*outlist)[i] = NULL;
631 *ret_length = *list_length;
637 _config_set_list (notmuch_config_t *config,
638 const char *group, const char *key,
640 size_t length, const char ***config_var )
642 g_key_file_set_string_list (config->key_file, group, key, list, length);
644 /* drop the cached value */
645 talloc_free (*config_var);
650 notmuch_config_get_database_path (notmuch_config_t *config)
652 return _config_get (config, &config->database_path, "database", "path");
656 notmuch_config_set_database_path (notmuch_config_t *config,
657 const char *database_path)
659 _config_set (config, &config->database_path, "database", "path", database_path);
663 notmuch_config_get_user_name (notmuch_config_t *config)
665 return _config_get (config, &config->user_name, "user", "name");
669 notmuch_config_set_user_name (notmuch_config_t *config,
670 const char *user_name)
672 _config_set (config, &config->user_name, "user", "name", user_name);
676 notmuch_config_get_user_primary_email (notmuch_config_t *config)
678 return _config_get (config, &config->user_primary_email, "user", "primary_email");
682 notmuch_config_set_user_primary_email (notmuch_config_t *config,
683 const char *primary_email)
685 _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
689 notmuch_config_get_user_other_email (notmuch_config_t *config, size_t *length)
691 return _config_get_list (config, "user", "other_email",
692 &(config->user_other_email),
693 &(config->user_other_email_length), length);
697 notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length)
699 return _config_get_list (config, "new", "tags",
701 &(config->new_tags_length), length);
705 notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
707 return _config_get_list (config, "new", "ignore",
708 &(config->new_ignore),
709 &(config->new_ignore_length), length);
713 notmuch_config_set_user_other_email (notmuch_config_t *config,
717 _config_set_list (config, "user", "other_email", list, length,
718 &(config->user_other_email));
722 notmuch_config_set_new_tags (notmuch_config_t *config,
726 _config_set_list (config, "new", "tags", list, length,
727 &(config->new_tags));
731 notmuch_config_set_new_ignore (notmuch_config_t *config,
735 _config_set_list (config, "new", "ignore", list, length,
736 &(config->new_ignore));
740 notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
742 return _config_get_list (config, "search", "exclude_tags",
743 &(config->search_exclude_tags),
744 &(config->search_exclude_tags_length), length);
748 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
752 _config_set_list (config, "search", "exclude_tags", list, length,
753 &(config->search_exclude_tags));
757 notmuch_config_get_crypto_gpg_path (notmuch_config_t *config)
759 return _config_get (config, &config->crypto_gpg_path, "crypto", "gpg_path");
763 notmuch_config_set_crypto_gpg_path (notmuch_config_t *config,
764 const char *gpg_path)
766 _config_set (config, &config->crypto_gpg_path, "crypto", "gpg_path", gpg_path);
770 /* Given a configuration item of the form <group>.<key> return the
771 * component group and key. If any error occurs, print a message on
772 * stderr and return 1. Otherwise, return 0.
774 * Note: This function modifies the original 'item' string.
777 _item_split (char *item, char **group, char **key)
783 period = strchr (item, '.');
784 if (period == NULL || *(period+1) == '\0') {
786 "Invalid configuration name: %s\n"
787 "(Should be of the form <section>.<item>)\n", item);
797 #define BUILT_WITH_PREFIX "built_with."
798 #define QUERY_PREFIX "query."
801 _print_db_config(notmuch_config_t *config, const char *name)
803 notmuch_database_t *notmuch;
806 if (notmuch_database_open (notmuch_config_get_database_path (config),
807 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
810 /* XXX Handle UUID mismatch? */
812 if (print_status_database ("notmuch config", notmuch,
813 notmuch_database_get_config (notmuch, name, &val)))
822 notmuch_config_command_get (notmuch_config_t *config, char *item)
824 if (strcmp(item, "database.path") == 0) {
825 printf ("%s\n", notmuch_config_get_database_path (config));
826 } else if (strcmp(item, "user.name") == 0) {
827 printf ("%s\n", notmuch_config_get_user_name (config));
828 } else if (strcmp(item, "user.primary_email") == 0) {
829 printf ("%s\n", notmuch_config_get_user_primary_email (config));
830 } else if (strcmp(item, "user.other_email") == 0) {
831 const char **other_email;
834 other_email = notmuch_config_get_user_other_email (config, &length);
835 for (i = 0; i < length; i++)
836 printf ("%s\n", other_email[i]);
837 } else if (strcmp(item, "new.tags") == 0) {
841 tags = notmuch_config_get_new_tags (config, &length);
842 for (i = 0; i < length; i++)
843 printf ("%s\n", tags[i]);
844 } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
846 notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false");
847 } else if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
848 return _print_db_config (config, item);
854 if (_item_split (item, &group, &key))
857 value = g_key_file_get_string_list (config->key_file,
861 fprintf (stderr, "Unknown configuration item: %s.%s\n",
866 for (i = 0; i < length; i++)
867 printf ("%s\n", value[i]);
876 _set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv)
878 notmuch_database_t *notmuch;
879 const char *val = "";
882 /* XXX handle lists? */
883 fprintf (stderr, "notmuch config set: at most one value expected for %s\n", key);
891 if (notmuch_database_open (notmuch_config_get_database_path (config),
892 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
895 /* XXX Handle UUID mismatch? */
897 if (print_status_database ("notmuch config", notmuch,
898 notmuch_database_set_config (notmuch, key, val)))
901 if (print_status_database ("notmuch config", notmuch,
902 notmuch_database_close (notmuch)))
909 notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
913 if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
914 fprintf (stderr, "Error: read only option: %s\n", item);
918 if (STRNCMP_LITERAL (item, QUERY_PREFIX) == 0) {
919 return _set_db_config (config, item, argc, argv);
922 if (_item_split (item, &group, &key))
925 /* With only the name of an item, we clear it from the
926 * configuration file.
928 * With a single value, we set it as a string.
930 * With multiple values, we set them as a string list.
934 g_key_file_remove_key (config->key_file, group, key, NULL);
937 g_key_file_set_string (config->key_file, group, key, argv[0]);
940 g_key_file_set_string_list (config->key_file, group, key,
941 (const gchar **) argv, argc);
945 return notmuch_config_save (config);
950 _notmuch_config_list_built_with ()
952 printf("%scompact=%s\n",
954 notmuch_built_with ("compact") ? "true" : "false");
955 printf("%sfield_processor=%s\n",
957 notmuch_built_with ("field_processor") ? "true" : "false");
958 printf("%sretry_lock=%s\n",
960 notmuch_built_with ("retry_lock") ? "true" : "false");
964 _list_db_config (notmuch_config_t *config)
966 notmuch_database_t *notmuch;
967 notmuch_config_list_t *list;
969 if (notmuch_database_open (notmuch_config_get_database_path (config),
970 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
973 /* XXX Handle UUID mismatch? */
976 if (print_status_database ("notmuch config", notmuch,
977 notmuch_database_get_config_list (notmuch, "", &list)))
980 for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
981 printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
983 notmuch_config_list_destroy (list);
989 notmuch_config_command_list (notmuch_config_t *config)
992 size_t g, groups_length;
994 groups = g_key_file_get_groups (config->key_file, &groups_length);
998 for (g = 0; g < groups_length; g++) {
1000 size_t k, keys_length;
1002 keys = g_key_file_get_keys (config->key_file,
1003 groups[g], &keys_length, NULL);
1007 for (k = 0; k < keys_length; k++) {
1010 value = g_key_file_get_string (config->key_file,
1011 groups[g], keys[k], NULL);
1012 if (value != NULL) {
1013 printf ("%s.%s=%s\n", groups[g], keys[k], value);
1021 g_strfreev (groups);
1023 _notmuch_config_list_built_with ();
1024 return _list_db_config (config);
1028 notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
1033 opt_index = notmuch_minimal_options ("config", argc, argv);
1035 return EXIT_FAILURE;
1037 if (notmuch_requested_db_uuid)
1038 fprintf (stderr, "Warning: ignoring --uuid=%s\n",
1039 notmuch_requested_db_uuid);
1041 /* skip at least subcommand argument */
1046 fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
1047 return EXIT_FAILURE;
1050 if (strcmp (argv[0], "get") == 0) {
1052 fprintf (stderr, "Error: notmuch config get requires exactly "
1054 return EXIT_FAILURE;
1056 ret = notmuch_config_command_get (config, argv[1]);
1057 } else if (strcmp (argv[0], "set") == 0) {
1059 fprintf (stderr, "Error: notmuch config set requires at least "
1061 return EXIT_FAILURE;
1063 ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
1064 } else if (strcmp (argv[0], "list") == 0) {
1065 ret = notmuch_config_command_list (config);
1067 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
1069 return EXIT_FAILURE;
1072 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
1077 notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
1079 return config->maildir_synchronize_flags;
1083 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
1084 notmuch_bool_t synchronize_flags)
1086 g_key_file_set_boolean (config->key_file,
1087 "maildir", "synchronize_flags", synchronize_flags);
1088 config->maildir_synchronize_flags = synchronize_flags;