static int notmuch_config_command_get (void *ctx, char *item) { notmuch_config_t *config; config = notmuch_config_open (ctx, NULL, NULL); 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) { printf ("%s\n", notmuch_config_get_user_name (config)); } else if (strcmp(item, "user.primary_email") == 0) { printf ("%s\n", notmuch_config_get_user_primary_email (config)); } else if (strcmp(item, "user.other_email") == 0) { const char **other_email; size_t i, length; other_email = notmuch_config_get_user_other_email (config, &length); for (i = 0; i < length; i++) printf ("%s\n", other_email[i]); } else if (strcmp(item, "new.tags") == 0) { const char **tags; size_t i, length; tags = notmuch_config_get_new_tags (config, &length); for (i = 0; i < length; i++) printf ("%s\n", tags[i]); } else { char **value; size_t i, length; char *group, *key; if (_item_split (item, &group, &key)) return 1; value = g_key_file_get_string_list (config->key_file, group, key, &length, NULL); if (value == NULL) { fprintf (stderr, "Unknown configuration item: %s.%s\n", group, key); return 1; } for (i = 0; i < length; i++) printf ("%s\n", value[i]); g_strfreev (value); } notmuch_config_close (config); return 0; }
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; }
int notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) { notmuch_status_t status, close_status; notmuch_database_t *notmuch; struct sigaction action; const char *db_path; const char **new_tags; size_t new_tags_length; tag_op_list_t *tag_ops; char *query_string = NULL; const char *folder = NULL; notmuch_bool_t create_folder = FALSE; notmuch_bool_t keep = FALSE; notmuch_bool_t no_hooks = FALSE; notmuch_bool_t synchronize_flags; const char *maildir; char *newpath; int opt_index; unsigned int i; notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_STRING, &folder, "folder", 0, 0 }, { NOTMUCH_OPT_BOOLEAN, &create_folder, "create-folder", 0, 0 }, { NOTMUCH_OPT_BOOLEAN, &keep, "keep", 0, 0 }, { NOTMUCH_OPT_BOOLEAN, &no_hooks, "no-hooks", 'n', 0 }, { NOTMUCH_OPT_INHERIT, (void *) ¬much_shared_options, NULL, 0, 0 }, { NOTMUCH_OPT_END, 0, 0, 0, 0 } }; opt_index = parse_arguments (argc, argv, options, 1); if (opt_index < 0) return EXIT_FAILURE; notmuch_process_shared_options (argv[0]); db_path = notmuch_config_get_database_path (config); new_tags = notmuch_config_get_new_tags (config, &new_tags_length); synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); return EXIT_FAILURE; } for (i = 0; i < new_tags_length; i++) { const char *error_msg; error_msg = illegal_tag (new_tags[i], FALSE); if (error_msg) { fprintf (stderr, "Error: tag '%s' in new.tags: %s\n", new_tags[i], error_msg); return EXIT_FAILURE; } if (tag_op_list_append (tag_ops, new_tags[i], FALSE)) return EXIT_FAILURE; } if (parse_tag_command_line (config, argc - opt_index, argv + opt_index, &query_string, tag_ops)) return EXIT_FAILURE; if (*query_string != '\0') { fprintf (stderr, "Error: unexpected query string: %s\n", query_string); return EXIT_FAILURE; } if (folder == NULL) { maildir = db_path; } else { if (! is_valid_folder_name (folder)) { fprintf (stderr, "Error: invalid folder name: '%s'\n", folder); return EXIT_FAILURE; } maildir = talloc_asprintf (config, "%s/%s", db_path, folder); if (! maildir) { fprintf (stderr, "Out of memory\n"); return EXIT_FAILURE; } if (create_folder && ! maildir_create_folder (config, maildir)) return EXIT_FAILURE; } /* Set up our handler for SIGINT. We do not set SA_RESTART so that copying * from standard input may be interrupted. */ memset (&action, 0, sizeof (struct sigaction)); action.sa_handler = handle_sigint; sigemptyset (&action.sa_mask); action.sa_flags = 0; sigaction (SIGINT, &action, NULL); /* Write the message to the Maildir new directory. */ newpath = maildir_write_new (config, STDIN_FILENO, maildir); if (! newpath) { return EXIT_FAILURE; } status = notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much); if (status) return keep ? NOTMUCH_STATUS_SUCCESS : status_to_exit (status); notmuch_exit_if_unmatched_db_uuid (notmuch); /* Index the message. */ status = add_file (notmuch, newpath, tag_ops, synchronize_flags, keep); /* Commit changes. */ close_status = notmuch_database_destroy (notmuch); if (close_status) { /* Hold on to the first error, if any. */ if (! status) status = close_status; fprintf (stderr, "%s: failed to commit database changes: %s\n", keep ? "Warning" : "Error", notmuch_status_to_string (close_status)); } if (status) { if (keep) { status = NOTMUCH_STATUS_SUCCESS; } else { /* If maildir flag sync failed, this might fail. */ if (unlink (newpath)) { fprintf (stderr, "Warning: failed to remove '%s' from maildir " "after errors: %s. Please run 'notmuch new' to fix.\n", newpath, strerror (errno)); } } } if (! no_hooks && status == NOTMUCH_STATUS_SUCCESS) { /* Ignore hook failures. */ notmuch_run_hook (db_path, "post-insert"); } return status_to_exit (status); }
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; } }
/* 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; }
int notmuch_new_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; add_files_state_t add_files_state; double elapsed; struct timeval tv_now, tv_start; int ret = 0; struct stat st; const char *db_path; char *dot_notmuch_path; struct sigaction action; _filename_node_t *f; int renamed_files, removed_files; notmuch_status_t status; int i; notmuch_bool_t timer_is_active = FALSE; add_files_state.verbose = 0; add_files_state.output_is_a_tty = isatty (fileno (stdout)); for (i = 0; i < argc && argv[i][0] == '-'; i++) { if (STRNCMP_LITERAL (argv[i], "--verbose") == 0) { add_files_state.verbose = 1; } else { fprintf (stderr, "Unrecognized option: %s\n", argv[i]); return 1; } } config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; add_files_state.new_tags = notmuch_config_get_new_tags (config, &add_files_state.new_tags_length); add_files_state.synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); add_files_state.message_ids_to_sync = _filename_list_create (ctx); db_path = notmuch_config_get_database_path (config); dot_notmuch_path = talloc_asprintf (ctx, "%s/%s", db_path, ".notmuch"); if (stat (dot_notmuch_path, &st)) { int count; count = 0; count_files (db_path, &count); if (interrupted) return 1; printf ("Found %d total files (that's not much mail).\n", count); notmuch = notmuch_database_create (db_path); add_files_state.total_files = count; } else { notmuch = notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE); if (notmuch == NULL) return 1; if (notmuch_database_needs_upgrade (notmuch)) { printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n"); gettimeofday (&add_files_state.tv_start, NULL); notmuch_database_upgrade (notmuch, upgrade_print_progress, &add_files_state); printf ("Your notmuch database has now been upgraded to database format version %u.\n", notmuch_database_get_version (notmuch)); } add_files_state.total_files = 0; } if (notmuch == NULL) return 1; /* Setup our handler for SIGINT. We do this after having * potentially done a database upgrade we this interrupt handler * won't support. */ memset (&action, 0, sizeof (struct sigaction)); action.sa_handler = handle_sigint; sigemptyset (&action.sa_mask); action.sa_flags = SA_RESTART; sigaction (SIGINT, &action, NULL); talloc_free (dot_notmuch_path); dot_notmuch_path = NULL; add_files_state.processed_files = 0; add_files_state.added_messages = 0; gettimeofday (&add_files_state.tv_start, NULL); add_files_state.removed_files = _filename_list_create (ctx); add_files_state.removed_directories = _filename_list_create (ctx); if (! debugger_is_active () && add_files_state.output_is_a_tty && ! add_files_state.verbose) { setup_progress_printing_timer (); timer_is_active = TRUE; } ret = add_files (notmuch, db_path, &add_files_state); removed_files = 0; renamed_files = 0; gettimeofday (&tv_start, NULL); for (f = add_files_state.removed_files->head; f; f = f->next) { status = notmuch_database_remove_message (notmuch, f->filename); if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) renamed_files++; else removed_files++; if (do_print_progress) { do_print_progress = 0; generic_print_progress ("Cleaned up", "messages", tv_start, removed_files + renamed_files, add_files_state.removed_files->count); } } gettimeofday (&tv_start, NULL); for (f = add_files_state.removed_directories->head, i = 0; f; f = f->next, i++) { _remove_directory (ctx, notmuch, f->filename, &renamed_files, &removed_files); if (do_print_progress) { do_print_progress = 0; generic_print_progress ("Cleaned up", "directories", tv_start, i, add_files_state.removed_directories->count); } } talloc_free (add_files_state.removed_files); talloc_free (add_files_state.removed_directories); /* Now that removals are done (hence the database is aware of all * renames), we can synchronize maildir_flags to tags for all * messages that had new filenames appear on this run. */ gettimeofday (&tv_start, NULL); if (add_files_state.synchronize_flags) { _filename_node_t *node; notmuch_message_t *message; for (node = add_files_state.message_ids_to_sync->head, i = 0; node; node = node->next, i++) { message = notmuch_database_find_message (notmuch, node->filename); notmuch_message_maildir_flags_to_tags (message); notmuch_message_destroy (message); if (do_print_progress) { do_print_progress = 0; generic_print_progress ( "Synchronized tags for", "messages", tv_start, i, add_files_state.message_ids_to_sync->count); } } } talloc_free (add_files_state.message_ids_to_sync); add_files_state.message_ids_to_sync = NULL; if (timer_is_active) stop_progress_printing_timer (); gettimeofday (&tv_now, NULL); elapsed = notmuch_time_elapsed (add_files_state.tv_start, tv_now); if (add_files_state.processed_files) { printf ("Processed %d %s in ", add_files_state.processed_files, add_files_state.processed_files == 1 ? "file" : "total files"); notmuch_time_print_formatted_seconds (elapsed); if (elapsed > 1) { printf (" (%d files/sec.).\033[K\n", (int) (add_files_state.processed_files / elapsed)); } else { printf (".\033[K\n"); } } if (add_files_state.added_messages) { printf ("Added %d new %s to the database.", add_files_state.added_messages, add_files_state.added_messages == 1 ? "message" : "messages"); } else { printf ("No new mail."); } if (removed_files) { printf (" Removed %d %s.", removed_files, removed_files == 1 ? "message" : "messages"); } if (renamed_files) { printf (" Detected %d file %s.", renamed_files, renamed_files == 1 ? "rename" : "renames"); } printf ("\n"); if (ret) { printf ("\nNote: At least one error was encountered: %s\n", notmuch_status_to_string (ret)); } notmuch_database_close (notmuch); return ret || interrupted; }
int notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) { notmuch_database_t *notmuch; struct sigaction action; const char *db_path; const char **new_tags; size_t new_tags_length; tag_op_list_t *tag_ops; char *query_string = NULL; const char *folder = NULL; notmuch_bool_t create_folder = FALSE; const char *maildir; int opt_index; unsigned int i; notmuch_bool_t ret; notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_STRING, &folder, "folder", 0, 0 }, { NOTMUCH_OPT_BOOLEAN, &create_folder, "create-folder", 0, 0 }, { NOTMUCH_OPT_END, 0, 0, 0, 0 } }; opt_index = parse_arguments (argc, argv, options, 1); if (opt_index < 0) { /* diagnostics already printed */ return 1; } db_path = notmuch_config_get_database_path (config); new_tags = notmuch_config_get_new_tags (config, &new_tags_length); tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } for (i = 0; i < new_tags_length; i++) { if (tag_op_list_append (tag_ops, new_tags[i], FALSE)) return 1; } if (parse_tag_command_line (config, argc - opt_index, argv + opt_index, &query_string, tag_ops)) return 1; if (*query_string != '\0') { fprintf (stderr, "Error: unexpected query string: %s\n", query_string); return 1; } if (folder == NULL) { maildir = db_path; } else { if (! check_folder_name (folder)) { fprintf (stderr, "Error: bad folder name: %s\n", folder); return 1; } maildir = talloc_asprintf (config, "%s/%s", db_path, folder); if (! maildir) { fprintf (stderr, "Out of memory\n"); return 1; } if (create_folder && ! maildir_create_folder (config, maildir)) { fprintf (stderr, "Error: creating maildir %s: %s\n", maildir, strerror (errno)); return 1; } } /* Setup our handler for SIGINT. We do not set SA_RESTART so that copying * from standard input may be interrupted. */ memset (&action, 0, sizeof (struct sigaction)); action.sa_handler = handle_sigint; sigemptyset (&action.sa_mask); action.sa_flags = 0; sigaction (SIGINT, &action, NULL); if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return 1; ret = insert_message (config, notmuch, STDIN_FILENO, maildir, tag_ops); notmuch_database_destroy (notmuch); return (ret) ? 0 : 1; }