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 old option is now ignored:\n"
110 "\t\tThis option was used by older builds of notmuch to choose\n"
111 "\t\tthe version of gpg to use.\n"
112 "\t\tSetting $PATH is a better approach.\n";
114 struct _notmuch_config {
120 char *crypto_gpg_path;
122 char *user_primary_email;
123 const char **user_other_email;
124 size_t user_other_email_length;
125 const char **new_tags;
126 size_t new_tags_length;
127 const char **new_ignore;
128 size_t new_ignore_length;
129 bool maildir_synchronize_flags;
130 const char **search_exclude_tags;
131 size_t search_exclude_tags_length;
135 notmuch_config_destructor (notmuch_config_t *config)
137 if (config->key_file)
138 g_key_file_free (config->key_file);
144 get_name_from_passwd_file (void *ctx)
148 struct passwd passwd, *ignored;
152 pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
153 if (pw_buf_size == -1) pw_buf_size = 64;
154 pw_buf = talloc_size (ctx, pw_buf_size);
156 while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
157 pw_buf_size, &ignored)) == ERANGE) {
158 pw_buf_size = pw_buf_size * 2;
159 pw_buf = talloc_zero_size(ctx, pw_buf_size);
163 char *comma = strchr (passwd.pw_gecos, ',');
165 name = talloc_strndup (ctx, passwd.pw_gecos,
166 comma - passwd.pw_gecos);
168 name = talloc_strdup (ctx, passwd.pw_gecos);
170 name = talloc_strdup (ctx, "");
173 talloc_free (pw_buf);
179 get_username_from_passwd_file (void *ctx)
183 struct passwd passwd, *ignored;
187 pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
188 if (pw_buf_size == -1) pw_buf_size = 64;
189 pw_buf = talloc_zero_size (ctx, pw_buf_size);
191 while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
192 pw_buf_size, &ignored)) == ERANGE) {
193 pw_buf_size = pw_buf_size * 2;
194 pw_buf = talloc_zero_size(ctx, pw_buf_size);
198 name = talloc_strdup (ctx, passwd.pw_name);
200 name = talloc_strdup (ctx, "");
202 talloc_free (pw_buf);
208 get_config_from_file (notmuch_config_t *config, bool create_new)
210 #define BUF_SIZE 4096
211 char *config_str = NULL;
213 int config_bufsize = BUF_SIZE;
215 GError *error = NULL;
218 FILE *fp = fopen(config->filename, "r");
220 if (errno == ENOENT) {
221 /* If create_new is true, then the caller is prepared for a
222 * default configuration file in the case of FILE NOT FOUND.
225 config->is_new = true;
228 fprintf (stderr, "Configuration file %s not found.\n"
229 "Try running 'notmuch setup' to create a configuration.\n",
233 fprintf (stderr, "Error opening config file '%s': %s\n",
234 config->filename, strerror(errno));
239 config_str = talloc_zero_array (config, char, config_bufsize);
240 if (config_str == NULL) {
241 fprintf (stderr, "Error reading '%s': Out of memory\n", config->filename);
245 while ((len = fread (config_str + config_len, 1,
246 config_bufsize - config_len, fp)) > 0) {
248 if (config_len == config_bufsize) {
249 config_bufsize += BUF_SIZE;
250 config_str = talloc_realloc (config, config_str, char, config_bufsize);
251 if (config_str == NULL) {
252 fprintf (stderr, "Error reading '%s': Failed to reallocate memory\n",
260 fprintf (stderr, "Error reading '%s': I/O error\n", config->filename);
264 if (g_key_file_load_from_data (config->key_file, config_str, config_len,
265 G_KEY_FILE_KEEP_COMMENTS, &error)) {
270 fprintf (stderr, "Error parsing config file '%s': %s\n",
271 config->filename, error->message);
273 g_error_free (error);
280 talloc_free(config_str);
285 /* Open the named notmuch configuration file. If the filename is NULL,
286 * the value of the environment variable $NOTMUCH_CONFIG will be used.
287 * If $NOTMUCH_CONFIG is unset, the default configuration file
288 * ($HOME/.notmuch-config) will be used.
290 * If any error occurs, (out of memory, or a permission-denied error,
291 * etc.), this function will print a message to stderr and return
294 * FILE NOT FOUND: When the specified configuration file (whether from
295 * 'filename' or the $NOTMUCH_CONFIG environment variable) does not
296 * exist, the behavior of this function depends on the 'is_new_ret'
299 * If is_new_ret is NULL, then a "file not found" message will be
300 * printed to stderr and NULL will be returned.
302 * If is_new_ret is non-NULL then a default configuration will be
303 * returned and *is_new_ret will be set to 1 on return so that
304 * the caller can recognize this case.
306 * These default configuration settings are determined as
309 * database_path: $MAILDIR, otherwise $HOME/mail
311 * user_name: $NAME variable if set, otherwise
312 * read from /etc/passwd
314 * user_primary_mail: $EMAIL variable if set, otherwise
315 * constructed from the username and
316 * hostname of the current machine.
318 * user_other_email: Not set.
320 * The default configuration also contains comments to guide the
321 * user in editing the file directly.
324 notmuch_config_open (void *ctx,
325 const char *filename,
326 notmuch_config_mode_t config_mode)
328 GError *error = NULL;
330 char *notmuch_config_env = NULL;
331 int file_had_database_group;
332 int file_had_new_group;
333 int file_had_user_group;
334 int file_had_maildir_group;
335 int file_had_search_group;
336 int file_had_crypto_group;
338 notmuch_config_t *config = talloc_zero (ctx, notmuch_config_t);
339 if (config == NULL) {
340 fprintf (stderr, "Out of memory.\n");
344 talloc_set_destructor (config, notmuch_config_destructor);
346 /* non-zero defaults */
347 config->maildir_synchronize_flags = true;
350 config->filename = talloc_strdup (config, filename);
351 } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) {
352 config->filename = talloc_strdup (config, notmuch_config_env);
354 config->filename = talloc_asprintf (config, "%s/.notmuch-config",
358 config->key_file = g_key_file_new ();
360 if (config_mode & NOTMUCH_CONFIG_OPEN) {
361 bool create_new = (config_mode & NOTMUCH_CONFIG_CREATE) != 0;
363 if (! get_config_from_file (config, create_new)) {
364 talloc_free (config);
369 /* Whenever we know of configuration sections that don't appear in
370 * the configuration file, we add some comments to help the user
371 * understand what can be done.
373 * It would be convenient to just add those comments now, but
374 * apparently g_key_file will clear any comments when keys are
375 * added later that create the groups. So we have to check for the
376 * groups now, but add the comments only after setting all of our
379 file_had_database_group = g_key_file_has_group (config->key_file,
381 file_had_new_group = g_key_file_has_group (config->key_file, "new");
382 file_had_user_group = g_key_file_has_group (config->key_file, "user");
383 file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
384 file_had_search_group = g_key_file_has_group (config->key_file, "search");
385 file_had_crypto_group = g_key_file_has_group (config->key_file, "crypto");
387 if (notmuch_config_get_database_path (config) == NULL) {
388 char *path = getenv ("MAILDIR");
390 path = talloc_strdup (config, path);
392 path = talloc_asprintf (config, "%s/mail",
394 notmuch_config_set_database_path (config, path);
398 if (notmuch_config_get_user_name (config) == NULL) {
399 char *name = getenv ("NAME");
401 name = talloc_strdup (config, name);
403 name = get_name_from_passwd_file (config);
404 notmuch_config_set_user_name (config, name);
408 if (notmuch_config_get_user_primary_email (config) == NULL) {
409 char *email = getenv ("EMAIL");
411 notmuch_config_set_user_primary_email (config, email);
414 struct hostent *hostent;
415 const char *domainname;
417 char *username = get_username_from_passwd_file (config);
419 gethostname (hostname, 256);
420 hostname[255] = '\0';
422 hostent = gethostbyname (hostname);
423 if (hostent && (domainname = strchr (hostent->h_name, '.')))
426 domainname = "(none)";
428 email = talloc_asprintf (config, "%s@%s.%s",
429 username, hostname, domainname);
431 notmuch_config_set_user_primary_email (config, email);
433 talloc_free (username);
438 if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
439 const char *tags[] = { "unread", "inbox" };
440 notmuch_config_set_new_tags (config, tags, 2);
443 if (notmuch_config_get_new_ignore (config, &tmp) == NULL) {
444 notmuch_config_set_new_ignore (config, NULL, 0);
447 if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) {
448 if (config->is_new) {
449 const char *tags[] = { "deleted", "spam" };
450 notmuch_config_set_search_exclude_tags (config, tags, 2);
452 notmuch_config_set_search_exclude_tags (config, NULL, 0);
457 config->maildir_synchronize_flags =
458 g_key_file_get_boolean (config->key_file,
459 "maildir", "synchronize_flags", &error);
461 notmuch_config_set_maildir_synchronize_flags (config, true);
462 g_error_free (error);
465 /* Whenever we know of configuration sections that don't appear in
466 * the configuration file, we add some comments to help the user
467 * understand what can be done. */
469 g_key_file_set_comment (config->key_file, NULL, NULL,
470 toplevel_config_comment, NULL);
472 if (! file_had_database_group)
473 g_key_file_set_comment (config->key_file, "database", NULL,
474 database_config_comment, NULL);
476 if (! file_had_new_group)
477 g_key_file_set_comment (config->key_file, "new", NULL,
478 new_config_comment, NULL);
480 if (! file_had_user_group)
481 g_key_file_set_comment (config->key_file, "user", NULL,
482 user_config_comment, NULL);
484 if (! file_had_maildir_group)
485 g_key_file_set_comment (config->key_file, "maildir", NULL,
486 maildir_config_comment, NULL);
488 if (! file_had_search_group)
489 g_key_file_set_comment (config->key_file, "search", NULL,
490 search_config_comment, NULL);
492 if (! file_had_crypto_group)
493 g_key_file_set_comment (config->key_file, "crypto", NULL,
494 crypto_config_comment, NULL);
499 /* Close the given notmuch_config_t object, freeing all resources.
501 * Note: Any changes made to the configuration are *not* saved by this
502 * function. To save changes, call notmuch_config_save before
503 * notmuch_config_close.
506 notmuch_config_close (notmuch_config_t *config)
508 talloc_free (config);
511 /* Save any changes made to the notmuch configuration.
513 * Any comments originally in the file will be preserved.
515 * Returns 0 if successful, and 1 in case of any error, (after
516 * printing a description of the error to stderr).
519 notmuch_config_save (notmuch_config_t *config)
522 char *data, *filename;
523 GError *error = NULL;
525 data = g_key_file_to_data (config->key_file, &length, NULL);
527 fprintf (stderr, "Out of memory.\n");
531 /* Try not to overwrite symlinks. */
532 filename = canonicalize_file_name (config->filename);
534 if (errno == ENOENT) {
535 filename = strdup (config->filename);
537 fprintf (stderr, "Out of memory.\n");
542 fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename,
549 if (! g_file_set_contents (filename, data, length, &error)) {
550 if (strcmp (filename, config->filename) != 0) {
551 fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n",
552 config->filename, filename, error->message);
554 fprintf (stderr, "Error saving configuration to %s: %s\n",
555 filename, error->message);
557 g_error_free (error);
569 notmuch_config_is_new (notmuch_config_t *config)
571 return config->is_new;
575 _config_get (notmuch_config_t *config, char **field,
576 const char *group, const char *key)
578 /* read from config file and cache value, if not cached already */
579 if (*field == NULL) {
581 value = g_key_file_get_string (config->key_file, group, key, NULL);
583 *field = talloc_strdup (config, value);
591 _config_set (notmuch_config_t *config, char **field,
592 const char *group, const char *key, const char *value)
594 g_key_file_set_string (config->key_file, group, key, value);
596 /* drop the cached value */
597 talloc_free (*field);
602 _config_get_list (notmuch_config_t *config,
603 const char *section, const char *key,
604 const char ***outlist, size_t *list_length, size_t *ret_length)
608 /* read from config file and cache value, if not cached already */
609 if (*outlist == NULL) {
611 char **inlist = g_key_file_get_string_list (config->key_file,
612 section, key, list_length, NULL);
616 *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
618 for (i = 0; i < *list_length; i++)
619 (*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
621 (*outlist)[i] = NULL;
628 *ret_length = *list_length;
634 _config_set_list (notmuch_config_t *config,
635 const char *group, const char *key,
637 size_t length, const char ***config_var )
639 g_key_file_set_string_list (config->key_file, group, key, list, length);
641 /* drop the cached value */
642 talloc_free (*config_var);
647 notmuch_config_get_database_path (notmuch_config_t *config)
649 char *db_path = (char *)_config_get (config, &config->database_path, "database", "path");
651 if (db_path && *db_path != '/') {
652 /* If the path in the configuration file begins with any
653 * character other than /, presume that it is relative to
654 * $HOME and update as appropriate.
656 char *abs_path = talloc_asprintf (config, "%s/%s", getenv ("HOME"), db_path);
657 talloc_free (db_path);
658 db_path = config->database_path = abs_path;
665 notmuch_config_set_database_path (notmuch_config_t *config,
666 const char *database_path)
668 _config_set (config, &config->database_path, "database", "path", database_path);
672 notmuch_config_get_user_name (notmuch_config_t *config)
674 return _config_get (config, &config->user_name, "user", "name");
678 notmuch_config_set_user_name (notmuch_config_t *config,
679 const char *user_name)
681 _config_set (config, &config->user_name, "user", "name", user_name);
685 notmuch_config_get_user_primary_email (notmuch_config_t *config)
687 return _config_get (config, &config->user_primary_email, "user", "primary_email");
691 notmuch_config_set_user_primary_email (notmuch_config_t *config,
692 const char *primary_email)
694 _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
698 notmuch_config_get_user_other_email (notmuch_config_t *config, size_t *length)
700 return _config_get_list (config, "user", "other_email",
701 &(config->user_other_email),
702 &(config->user_other_email_length), length);
706 notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length)
708 return _config_get_list (config, "new", "tags",
710 &(config->new_tags_length), length);
714 notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
716 return _config_get_list (config, "new", "ignore",
717 &(config->new_ignore),
718 &(config->new_ignore_length), length);
722 notmuch_config_set_user_other_email (notmuch_config_t *config,
726 _config_set_list (config, "user", "other_email", list, length,
727 &(config->user_other_email));
731 notmuch_config_set_new_tags (notmuch_config_t *config,
735 _config_set_list (config, "new", "tags", list, length,
736 &(config->new_tags));
740 notmuch_config_set_new_ignore (notmuch_config_t *config,
744 _config_set_list (config, "new", "ignore", list, length,
745 &(config->new_ignore));
749 notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
751 return _config_get_list (config, "search", "exclude_tags",
752 &(config->search_exclude_tags),
753 &(config->search_exclude_tags_length), length);
757 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
761 _config_set_list (config, "search", "exclude_tags", list, length,
762 &(config->search_exclude_tags));
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."
796 _stored_in_db (const char *item)
798 const char * db_configs[] = {
801 if (STRNCMP_LITERAL (item, "query.") == 0)
803 for (size_t i = 0; i < ARRAY_SIZE (db_configs); i++)
804 if (strcmp (item, db_configs[i]) == 0)
810 _print_db_config(notmuch_config_t *config, const char *name)
812 notmuch_database_t *notmuch;
815 if (notmuch_database_open (notmuch_config_get_database_path (config),
816 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
819 /* XXX Handle UUID mismatch? */
821 if (print_status_database ("notmuch config", notmuch,
822 notmuch_database_get_config (notmuch, name, &val)))
831 notmuch_config_command_get (notmuch_config_t *config, char *item)
833 if (strcmp(item, "database.path") == 0) {
834 printf ("%s\n", notmuch_config_get_database_path (config));
835 } else if (strcmp(item, "user.name") == 0) {
836 printf ("%s\n", notmuch_config_get_user_name (config));
837 } else if (strcmp(item, "user.primary_email") == 0) {
838 printf ("%s\n", notmuch_config_get_user_primary_email (config));
839 } else if (strcmp(item, "user.other_email") == 0) {
840 const char **other_email;
843 other_email = notmuch_config_get_user_other_email (config, &length);
844 for (i = 0; i < length; i++)
845 printf ("%s\n", other_email[i]);
846 } else if (strcmp(item, "new.tags") == 0) {
850 tags = notmuch_config_get_new_tags (config, &length);
851 for (i = 0; i < length; i++)
852 printf ("%s\n", tags[i]);
853 } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
855 notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false");
856 } else if (_stored_in_db (item)) {
857 return _print_db_config (config, item);
863 if (_item_split (item, &group, &key))
866 value = g_key_file_get_string_list (config->key_file,
870 fprintf (stderr, "Unknown configuration item: %s.%s\n",
875 for (i = 0; i < length; i++)
876 printf ("%s\n", value[i]);
885 _set_db_config(notmuch_config_t *config, const char *key, int argc, char **argv)
887 notmuch_database_t *notmuch;
888 const char *val = "";
891 /* XXX handle lists? */
892 fprintf (stderr, "notmuch config set: at most one value expected for %s\n", key);
900 if (notmuch_database_open (notmuch_config_get_database_path (config),
901 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
904 /* XXX Handle UUID mismatch? */
906 if (print_status_database ("notmuch config", notmuch,
907 notmuch_database_set_config (notmuch, key, val)))
910 if (print_status_database ("notmuch config", notmuch,
911 notmuch_database_close (notmuch)))
918 notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
922 if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
923 fprintf (stderr, "Error: read only option: %s\n", item);
927 if (_stored_in_db (item)) {
928 return _set_db_config (config, item, argc, argv);
931 if (_item_split (item, &group, &key))
934 /* With only the name of an item, we clear it from the
935 * configuration file.
937 * With a single value, we set it as a string.
939 * With multiple values, we set them as a string list.
943 g_key_file_remove_key (config->key_file, group, key, NULL);
946 g_key_file_set_string (config->key_file, group, key, argv[0]);
949 g_key_file_set_string_list (config->key_file, group, key,
950 (const gchar **) argv, argc);
954 return notmuch_config_save (config);
959 _notmuch_config_list_built_with ()
961 printf("%scompact=%s\n",
963 notmuch_built_with ("compact") ? "true" : "false");
964 printf("%sfield_processor=%s\n",
966 notmuch_built_with ("field_processor") ? "true" : "false");
967 printf("%sretry_lock=%s\n",
969 notmuch_built_with ("retry_lock") ? "true" : "false");
973 _list_db_config (notmuch_config_t *config)
975 notmuch_database_t *notmuch;
976 notmuch_config_list_t *list;
978 if (notmuch_database_open (notmuch_config_get_database_path (config),
979 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
982 /* XXX Handle UUID mismatch? */
985 if (print_status_database ("notmuch config", notmuch,
986 notmuch_database_get_config_list (notmuch, "", &list)))
989 for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
990 printf("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
992 notmuch_config_list_destroy (list);
998 notmuch_config_command_list (notmuch_config_t *config)
1001 size_t g, groups_length;
1003 groups = g_key_file_get_groups (config->key_file, &groups_length);
1007 for (g = 0; g < groups_length; g++) {
1009 size_t k, keys_length;
1011 keys = g_key_file_get_keys (config->key_file,
1012 groups[g], &keys_length, NULL);
1016 for (k = 0; k < keys_length; k++) {
1019 value = g_key_file_get_string (config->key_file,
1020 groups[g], keys[k], NULL);
1021 if (value != NULL) {
1022 printf ("%s.%s=%s\n", groups[g], keys[k], value);
1030 g_strfreev (groups);
1032 _notmuch_config_list_built_with ();
1033 return _list_db_config (config);
1037 notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
1042 opt_index = notmuch_minimal_options ("config", argc, argv);
1044 return EXIT_FAILURE;
1046 if (notmuch_requested_db_uuid)
1047 fprintf (stderr, "Warning: ignoring --uuid=%s\n",
1048 notmuch_requested_db_uuid);
1050 /* skip at least subcommand argument */
1055 fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
1056 return EXIT_FAILURE;
1059 if (strcmp (argv[0], "get") == 0) {
1061 fprintf (stderr, "Error: notmuch config get requires exactly "
1063 return EXIT_FAILURE;
1065 ret = notmuch_config_command_get (config, argv[1]);
1066 } else if (strcmp (argv[0], "set") == 0) {
1068 fprintf (stderr, "Error: notmuch config set requires at least "
1070 return EXIT_FAILURE;
1072 ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
1073 } else if (strcmp (argv[0], "list") == 0) {
1074 ret = notmuch_config_command_list (config);
1076 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
1078 return EXIT_FAILURE;
1081 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
1086 notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
1088 return config->maildir_synchronize_flags;
1092 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
1093 bool synchronize_flags)
1095 g_key_file_set_boolean (config->key_file,
1096 "maildir", "synchronize_flags", synchronize_flags);
1097 config->maildir_synchronize_flags = synchronize_flags;