int notmuch_setup_command (unused (void *ctx), unused (int argc), unused (char *argv[])) { char *response = NULL; size_t response_size = 0; notmuch_config_t *config; const char **old_other_emails; size_t old_other_emails_len; GPtrArray *other_emails; unsigned int i; int is_new; const char **new_tags; size_t new_tags_len; #define prompt(format, ...) \ do { \ printf (format, ##__VA_ARGS__); \ fflush (stdout); \ if (getline (&response, &response_size, stdin) < 0) { \ printf ("Exiting.\n"); \ exit (1); \ } \ chomp_newline (response); \ } while (0) config = notmuch_config_open (ctx, NULL, &is_new); if (is_new) welcome_message_pre_setup (); prompt ("Your full name [%s]: ", notmuch_config_get_user_name (config)); if (strlen (response)) notmuch_config_set_user_name (config, response); prompt ("Your primary email address [%s]: ", notmuch_config_get_user_primary_email (config)); if (strlen (response)) notmuch_config_set_user_primary_email (config, response); other_emails = g_ptr_array_new (); old_other_emails = notmuch_config_get_user_other_email (config, &old_other_emails_len); for (i = 0; i < old_other_emails_len; i++) { prompt ("Additional email address [%s]: ", old_other_emails[i]); if (strlen (response)) g_ptr_array_add (other_emails, talloc_strdup (ctx, response)); else g_ptr_array_add (other_emails, talloc_strdup (ctx, old_other_emails[i])); } do { prompt ("Additional email address [Press 'Enter' if none]: "); if (strlen (response)) g_ptr_array_add (other_emails, talloc_strdup (ctx, response)); } while (strlen (response)); if (other_emails->len) notmuch_config_set_user_other_email (config, (const char **) other_emails->pdata, other_emails->len); g_ptr_array_free (other_emails, TRUE); prompt ("Top-level directory of your email archive [%s]: ", notmuch_config_get_database_path (config)); if (strlen (response)) { const char *absolute_path; absolute_path = make_path_absolute (ctx, response); notmuch_config_set_database_path (config, absolute_path); } new_tags = notmuch_config_get_new_tags (config, &new_tags_len); printf ("Tags to apply to all new messages (separated by spaces) ["); for (i = 0; i < new_tags_len; i++) { if (i != 0) printf (" "); printf ("%s", new_tags[i]); } prompt ("]: "); if (strlen (response)) { GPtrArray *tags = g_ptr_array_new (); char *tag = response; char *space; while (tag && *tag) { space = strchr (tag, ' '); if (space) g_ptr_array_add (tags, talloc_strndup (ctx, tag, space - tag)); else g_ptr_array_add (tags, talloc_strdup (ctx, tag)); tag = space; while (tag && *tag == ' ') tag++; } notmuch_config_set_new_tags (config, (const char **) tags->pdata, tags->len); g_ptr_array_free (tags, TRUE); } if (! notmuch_config_save (config)) { if (is_new) welcome_message_post_setup (); return 0; } else { return 1; } }
int notmuch_setup_command (notmuch_config_t *config, unused (int argc), unused (char *argv[])) { char *response = NULL; size_t response_size = 0; const char **old_other_emails; size_t old_other_emails_len; GPtrArray *other_emails; unsigned int i; const char **new_tags; size_t new_tags_len; const char **search_exclude_tags; size_t search_exclude_tags_len; #define prompt(format, ...) \ do { \ printf (format, ##__VA_ARGS__); \ fflush (stdout); \ if (getline (&response, &response_size, stdin) < 0) { \ printf ("Exiting.\n"); \ exit (EXIT_FAILURE); \ } \ chomp_newline (response); \ } while (0) if (notmuch_config_is_new (config)) welcome_message_pre_setup (); prompt ("Your full name [%s]: ", notmuch_config_get_user_name (config)); if (strlen (response)) notmuch_config_set_user_name (config, response); prompt ("Your primary email address [%s]: ", notmuch_config_get_user_primary_email (config)); if (strlen (response)) notmuch_config_set_user_primary_email (config, response); other_emails = g_ptr_array_new (); old_other_emails = notmuch_config_get_user_other_email (config, &old_other_emails_len); for (i = 0; i < old_other_emails_len; i++) { prompt ("Additional email address [%s]: ", old_other_emails[i]); if (strlen (response)) g_ptr_array_add (other_emails, talloc_strdup (config, response)); else g_ptr_array_add (other_emails, talloc_strdup (config, old_other_emails[i])); } do { prompt ("Additional email address [Press 'Enter' if none]: "); if (strlen (response)) g_ptr_array_add (other_emails, talloc_strdup (config, response)); } while (strlen (response)); if (other_emails->len) notmuch_config_set_user_other_email (config, (const char **) other_emails->pdata, other_emails->len); g_ptr_array_free (other_emails, TRUE); prompt ("Top-level directory of your email archive [%s]: ", notmuch_config_get_database_path (config)); if (strlen (response)) { const char *absolute_path; absolute_path = make_path_absolute (config, response); notmuch_config_set_database_path (config, absolute_path); } new_tags = notmuch_config_get_new_tags (config, &new_tags_len); printf ("Tags to apply to all new messages (separated by spaces) ["); print_tag_list (new_tags, new_tags_len); prompt ("]: "); if (strlen (response)) { GPtrArray *tags = parse_tag_list (config, response); notmuch_config_set_new_tags (config, (const char **) tags->pdata, tags->len); g_ptr_array_free (tags, TRUE); } search_exclude_tags = notmuch_config_get_search_exclude_tags (config, &search_exclude_tags_len); printf ("Tags to exclude when searching messages (separated by spaces) ["); print_tag_list (search_exclude_tags, search_exclude_tags_len); prompt ("]: "); if (strlen (response)) { GPtrArray *tags = parse_tag_list (config, response); notmuch_config_set_search_exclude_tags (config, (const char **) tags->pdata, tags->len); g_ptr_array_free (tags, TRUE); } if (notmuch_config_save (config)) return EXIT_FAILURE; if (notmuch_config_is_new (config)) welcome_message_post_setup (); return EXIT_SUCCESS; }
/* Open the named notmuch configuration file. If the filename is NULL, * the value of the environment variable $NOTMUCH_CONFIG will be used. * If $NOTMUCH_CONFIG is unset, the default configuration file * ($HOME/.notmuch-config) will be used. * * If any error occurs, (out of memory, or a permission-denied error, * etc.), this function will print a message to stderr and return * NULL. * * FILE NOT FOUND: When the specified configuration file (whether from * 'filename' or the $NOTMUCH_CONFIG environment variable) does not * exist, the behavior of this function depends on the 'is_new_ret' * variable. * * If is_new_ret is NULL, then a "file not found" message will be * printed to stderr and NULL will be returned. * If is_new_ret is non-NULL then a default configuration will be * returned and *is_new_ret will be set to 1 on return so that * the caller can recognize this case. * * These default configuration settings are determined as * follows: * * database_path: $HOME/mail * * user_name: From /etc/passwd * * user_primary_mail: $EMAIL variable if set, otherwise * constructed from the username and * hostname of the current machine. * * user_other_email: Not set. * * The default configuration also contains comments to guide the * user in editing the file directly. */ notmuch_config_t * notmuch_config_open (void *ctx, const char *filename, notmuch_bool_t *is_new_ret) { GError *error = NULL; int is_new = 0; size_t tmp; char *notmuch_config_env = NULL; int file_had_database_group; int file_had_new_group; int file_had_user_group; int file_had_maildir_group; int file_had_search_group; if (is_new_ret) *is_new_ret = 0; notmuch_config_t *config = talloc (ctx, notmuch_config_t); if (config == NULL) { fprintf (stderr, "Out of memory.\n"); return NULL; } talloc_set_destructor (config, notmuch_config_destructor); if (filename) { config->filename = talloc_strdup (config, filename); } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) { config->filename = talloc_strdup (config, notmuch_config_env); } else { config->filename = talloc_asprintf (config, "%s/.notmuch-config", getenv ("HOME")); } config->key_file = g_key_file_new (); config->database_path = NULL; config->user_name = NULL; config->user_primary_email = NULL; config->user_other_email = NULL; config->user_other_email_length = 0; config->new_tags = NULL; config->new_tags_length = 0; config->new_ignore = NULL; config->new_ignore_length = 0; config->maildir_synchronize_flags = TRUE; config->search_exclude_tags = NULL; config->search_exclude_tags_length = 0; if (! g_key_file_load_from_file (config->key_file, config->filename, G_KEY_FILE_KEEP_COMMENTS, &error)) { /* If the caller passed a non-NULL value for is_new_ret, 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 (is_new_ret && error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) { g_error_free (error); is_new = 1; } else { fprintf (stderr, "Error reading configuration file %s: %s\n", config->filename, error->message); talloc_free (config); g_error_free (error); return NULL; } } /* Whenever we know of configuration sections that don't appear in * the configuration file, we add some comments to help the user * understand what can be done. * * It would be convenient to just add those comments now, but * apparently g_key_file will clear any comments when keys are * added later that create the groups. So we have to check for the * groups now, but add the comments only after setting all of our * values. */ file_had_database_group = g_key_file_has_group (config->key_file, "database"); file_had_new_group = g_key_file_has_group (config->key_file, "new"); file_had_user_group = g_key_file_has_group (config->key_file, "user"); file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir"); file_had_search_group = g_key_file_has_group (config->key_file, "search"); if (notmuch_config_get_database_path (config) == NULL) { char *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); notmuch_config_set_user_name (config, name); talloc_free (name); } if (notmuch_config_get_user_primary_email (config) == NULL) { char *email = getenv ("EMAIL"); if (email) { notmuch_config_set_user_primary_email (config, email); } else { char hostname[256]; struct hostent *hostent; const char *domainname; char *username = get_username_from_passwd_file (config); gethostname (hostname, 256); hostname[255] = '\0'; hostent = gethostbyname (hostname); if (hostent && (domainname = strchr (hostent->h_name, '.'))) domainname += 1; else domainname = "(none)"; email = talloc_asprintf (config, "%s@%s.%s", username, hostname, domainname); notmuch_config_set_user_primary_email (config, email); talloc_free (username); talloc_free (email); } } if (notmuch_config_get_new_tags (config, &tmp) == NULL) { const char *tags[] = { "unread", "inbox" }; notmuch_config_set_new_tags (config, tags, 2); } if (notmuch_config_get_new_ignore (config, &tmp) == NULL) { notmuch_config_set_new_ignore (config, NULL, 0); } if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) { if (is_new) { const char *tags[] = { "deleted", "spam" }; notmuch_config_set_search_exclude_tags (config, tags, 2); } else { notmuch_config_set_search_exclude_tags (config, NULL, 0); } } error = NULL; config->maildir_synchronize_flags = g_key_file_get_boolean (config->key_file, "maildir", "synchronize_flags", &error); if (error) { notmuch_config_set_maildir_synchronize_flags (config, TRUE); g_error_free (error); } /* Whenever we know of configuration sections that don't appear in * the configuration file, we add some comments to help the user * understand what can be done. */ if (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) { g_key_file_set_comment (config->key_file, "search", NULL, search_config_comment, NULL); } if (is_new_ret) *is_new_ret = is_new; return config; }