X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch-config.c;h=a564bcae362f6b0b9304ade15e580faa67f84437;hp=247fbe4ba1e394c0d4dc34b7142dd2c2f9da3f57;hb=4e2c351c588ad74f4800ca0344232be90387c54a;hpb=e76f6517de020783d828be59f461f1d4f465c4b4 diff --git a/notmuch-config.c b/notmuch-config.c index 247fbe4b..a564bcae 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -217,9 +217,10 @@ get_username_from_passwd_file (void *ctx) * These default configuration settings are determined as * follows: * - * database_path: $HOME/mail + * database_path: $MAILDIR, otherwise $HOME/mail * - * user_name: From /etc/passwd + * user_name: $NAME variable if set, otherwise + * read from /etc/passwd * * user_primary_mail: $EMAIL variable if set, otherwise * constructed from the username and @@ -282,16 +283,22 @@ notmuch_config_open (void *ctx, G_KEY_FILE_KEEP_COMMENTS, &error)) { - /* If create_new is true, then the caller is prepared for a - * default configuration file in the case of FILE NOT - * FOUND. Otherwise, any read failure is an error. - */ - if (create_new && - error->domain == G_FILE_ERROR && - error->code == G_FILE_ERROR_NOENT) - { - g_error_free (error); - config->is_new = TRUE; + if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) { + /* If create_new is true, then the caller is prepared for a + * default configuration file in the case of FILE NOT + * FOUND. + */ + if (create_new) { + g_error_free (error); + config->is_new = TRUE; + } else { + fprintf (stderr, "Configuration file %s not found.\n" + "Try running 'notmuch setup' to create a configuration.\n", + config->filename); + talloc_free (config); + g_error_free (error); + return NULL; + } } else { @@ -322,14 +329,22 @@ notmuch_config_open (void *ctx, if (notmuch_config_get_database_path (config) == NULL) { - char *path = talloc_asprintf (config, "%s/mail", - getenv ("HOME")); + char *path = getenv ("MAILDIR"); + if (path) + path = talloc_strdup (config, path); + else + path = talloc_asprintf (config, "%s/mail", + getenv ("HOME")); notmuch_config_set_database_path (config, path); talloc_free (path); } if (notmuch_config_get_user_name (config) == NULL) { - char *name = get_name_from_passwd_file (config); + char *name = getenv ("NAME"); + if (name) + name = talloc_strdup (config, name); + else + name = get_name_from_passwd_file (config); notmuch_config_set_user_name (config, name); talloc_free (name); } @@ -395,39 +410,28 @@ notmuch_config_open (void *ctx, * the configuration file, we add some comments to help the user * understand what can be done. */ if (config->is_new) - { g_key_file_set_comment (config->key_file, NULL, NULL, toplevel_config_comment, NULL); - } if (! file_had_database_group) - { g_key_file_set_comment (config->key_file, "database", NULL, database_config_comment, NULL); - } if (! file_had_new_group) - { g_key_file_set_comment (config->key_file, "new", NULL, new_config_comment, NULL); - } if (! file_had_user_group) - { g_key_file_set_comment (config->key_file, "user", NULL, user_config_comment, NULL); - } if (! file_had_maildir_group) - { g_key_file_set_comment (config->key_file, "maildir", NULL, maildir_config_comment, NULL); - } - if (! file_had_search_group) { + if (! file_had_search_group) g_key_file_set_comment (config->key_file, "search", NULL, search_config_comment, NULL); - } return config; } @@ -455,7 +459,7 @@ int notmuch_config_save (notmuch_config_t *config) { size_t length; - char *data; + char *data, *filename; GError *error = NULL; data = g_key_file_to_data (config->key_file, &length, NULL); @@ -464,14 +468,39 @@ notmuch_config_save (notmuch_config_t *config) return 1; } - if (! g_file_set_contents (config->filename, data, length, &error)) { - fprintf (stderr, "Error saving configuration to %s: %s\n", - config->filename, error->message); + /* Try not to overwrite symlinks. */ + filename = canonicalize_file_name (config->filename); + if (! filename) { + if (errno == ENOENT) { + filename = strdup (config->filename); + if (! filename) { + fprintf (stderr, "Out of memory.\n"); + g_free (data); + return 1; + } + } else { + fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename, + strerror (errno)); + g_free (data); + return 1; + } + } + + if (! g_file_set_contents (filename, data, length, &error)) { + if (strcmp (filename, config->filename) != 0) { + fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n", + config->filename, filename, error->message); + } else { + fprintf (stderr, "Error saving configuration to %s: %s\n", + filename, error->message); + } g_error_free (error); + free (filename); g_free (data); return 1; } + free (filename); g_free (data); return 0; } @@ -482,6 +511,32 @@ notmuch_config_is_new (notmuch_config_t *config) return config->is_new; } +static const char * +_config_get (notmuch_config_t *config, char **field, + const char *group, const char *key) +{ + /* read from config file and cache value, if not cached already */ + if (*field == NULL) { + char *value; + value = g_key_file_get_string (config->key_file, group, key, NULL); + if (value) { + *field = talloc_strdup (config, value); + free (value); + } + } + return *field; +} + +static void +_config_set (notmuch_config_t *config, char **field, + const char *group, const char *key, const char *value) +{ + g_key_file_set_string (config->key_file, group, key, value); + + /* drop the cached value */ + talloc_free (*field); + *field = NULL; +} static const char ** _config_get_list (notmuch_config_t *config, @@ -490,6 +545,7 @@ _config_get_list (notmuch_config_t *config, { assert(outlist); + /* read from config file and cache value, if not cached already */ if (*outlist == NULL) { char **inlist = g_key_file_get_string_list (config->key_file, @@ -521,6 +577,8 @@ _config_set_list (notmuch_config_t *config, size_t length, const char ***config_var ) { g_key_file_set_string_list (config->key_file, group, name, list, length); + + /* drop the cached value */ talloc_free (*config_var); *config_var = NULL; } @@ -528,85 +586,40 @@ _config_set_list (notmuch_config_t *config, const char * notmuch_config_get_database_path (notmuch_config_t *config) { - char *path; - - if (config->database_path == NULL) { - path = g_key_file_get_string (config->key_file, - "database", "path", NULL); - if (path) { - config->database_path = talloc_strdup (config, path); - free (path); - } - } - - return config->database_path; + return _config_get (config, &config->database_path, "database", "path"); } void notmuch_config_set_database_path (notmuch_config_t *config, const char *database_path) { - g_key_file_set_string (config->key_file, - "database", "path", database_path); - - talloc_free (config->database_path); - config->database_path = NULL; + _config_set (config, &config->database_path, "database", "path", database_path); } const char * notmuch_config_get_user_name (notmuch_config_t *config) { - char *name; - - if (config->user_name == NULL) { - name = g_key_file_get_string (config->key_file, - "user", "name", NULL); - if (name) { - config->user_name = talloc_strdup (config, name); - free (name); - } - } - - return config->user_name; + return _config_get (config, &config->user_name, "user", "name"); } void notmuch_config_set_user_name (notmuch_config_t *config, const char *user_name) { - g_key_file_set_string (config->key_file, - "user", "name", user_name); - - talloc_free (config->user_name); - config->user_name = NULL; + _config_set (config, &config->user_name, "user", "name", user_name); } const char * notmuch_config_get_user_primary_email (notmuch_config_t *config) { - char *email; - - if (config->user_primary_email == NULL) { - email = g_key_file_get_string (config->key_file, - "user", "primary_email", NULL); - if (email) { - config->user_primary_email = talloc_strdup (config, email); - free (email); - } - } - - return config->user_primary_email; + return _config_get (config, &config->user_primary_email, "user", "primary_email"); } void notmuch_config_set_user_primary_email (notmuch_config_t *config, const char *primary_email) { - g_key_file_set_string (config->key_file, - "user", "primary_email", primary_email); - - talloc_free (config->user_primary_email); - config->user_primary_email = NULL; + _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email); } const char ** @@ -690,7 +703,7 @@ _item_split (char *item, char **group, char **key) *group = item; - period = index (item, '.'); + period = strchr (item, '.'); if (period == NULL || *(period+1) == '\0') { fprintf (stderr, "Invalid configuration name: %s\n" @@ -705,14 +718,8 @@ _item_split (char *item, char **group, char **key) } static int -notmuch_config_command_get (void *ctx, char *item) +notmuch_config_command_get (notmuch_config_t *config, char *item) { - notmuch_config_t *config; - - config = notmuch_config_open (ctx, NULL, FALSE); - if (config == NULL) - return 1; - if (strcmp(item, "database.path") == 0) { printf ("%s\n", notmuch_config_get_database_path (config)); } else if (strcmp(item, "user.name") == 0) { @@ -756,25 +763,17 @@ notmuch_config_command_get (void *ctx, char *item) g_strfreev (value); } - notmuch_config_close (config); - return 0; } static int -notmuch_config_command_set (void *ctx, char *item, int argc, char *argv[]) +notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[]) { - notmuch_config_t *config; char *group, *key; - int ret; if (_item_split (item, &group, &key)) return 1; - config = notmuch_config_open (ctx, NULL, FALSE); - if (config == NULL) - return 1; - /* With only the name of an item, we clear it from the * configuration file. * @@ -795,23 +794,15 @@ notmuch_config_command_set (void *ctx, char *item, int argc, char *argv[]) break; } - ret = notmuch_config_save (config); - notmuch_config_close (config); - - return ret; + return notmuch_config_save (config); } static int -notmuch_config_command_list (void *ctx) +notmuch_config_command_list (notmuch_config_t *config) { - notmuch_config_t *config; char **groups; size_t g, groups_length; - config = notmuch_config_open (ctx, NULL, FALSE); - if (config == NULL) - return 1; - groups = g_key_file_get_groups (config->key_file, &groups_length); if (groups == NULL) return 1; @@ -841,42 +832,45 @@ notmuch_config_command_list (void *ctx) g_strfreev (groups); - notmuch_config_close (config); - return 0; } int -notmuch_config_command (void *ctx, int argc, char *argv[]) +notmuch_config_command (notmuch_config_t *config, int argc, char *argv[]) { + int ret; + argc--; argv++; /* skip subcommand argument */ if (argc < 1) { fprintf (stderr, "Error: notmuch config requires at least one argument.\n"); - return 1; + return EXIT_FAILURE; } if (strcmp (argv[0], "get") == 0) { if (argc != 2) { fprintf (stderr, "Error: notmuch config get requires exactly " "one argument.\n"); - return 1; + return EXIT_FAILURE; } - return notmuch_config_command_get (ctx, argv[1]); + ret = notmuch_config_command_get (config, argv[1]); } else if (strcmp (argv[0], "set") == 0) { if (argc < 2) { fprintf (stderr, "Error: notmuch config set requires at least " "one argument.\n"); - return 1; + return EXIT_FAILURE; } - return notmuch_config_command_set (ctx, argv[1], argc - 2, argv + 2); + ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2); } else if (strcmp (argv[0], "list") == 0) { - return notmuch_config_command_list (ctx); + ret = notmuch_config_command_list (config); + } else { + fprintf (stderr, "Unrecognized argument for notmuch config: %s\n", + argv[0]); + return EXIT_FAILURE; } - fprintf (stderr, "Unrecognized argument for notmuch config: %s\n", - argv[0]); - return 1; + return ret ? EXIT_FAILURE : EXIT_SUCCESS; + } notmuch_bool_t