int notmuch_search_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; char *query_str; char *opt; notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST; const search_format_t *format = &format_text; int i, ret; output_t output = OUTPUT_SUMMARY; int offset = 0; int limit = -1; /* unlimited */ argc--; argv++; /* skip subcommand argument */ for (i = 0; i < argc && argv[i][0] == '-'; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } if (STRNCMP_LITERAL (argv[i], "--sort=") == 0) { opt = argv[i] + sizeof ("--sort=") - 1; if (strcmp (opt, "oldest-first") == 0) { sort = NOTMUCH_SORT_OLDEST_FIRST; } else if (strcmp (opt, "newest-first") == 0) { sort = NOTMUCH_SORT_NEWEST_FIRST; } else { fprintf (stderr, "Invalid value for --sort: %s\n", opt); return 1; } } else if (STRNCMP_LITERAL (argv[i], "--offset=") == 0) { char *p; opt = argv[i] + sizeof ("--offset=") - 1; offset = strtol (opt, &p, 10); if (*opt == '\0' || p == opt || *p != '\0') { fprintf (stderr, "Invalid value for --offset: %s\n", opt); return 1; } } else if (STRNCMP_LITERAL (argv[i], "--limit=") == 0) { char *p; opt = argv[i] + sizeof ("--limit=") - 1; limit = strtoul (opt, &p, 10); if (*opt == '\0' || p == opt || *p != '\0') { fprintf (stderr, "Invalid value for --limit: %s\n", opt); return 1; } } else if (STRNCMP_LITERAL (argv[i], "--format=") == 0) { opt = argv[i] + sizeof ("--format=") - 1; if (strcmp (opt, "text") == 0) { format = &format_text; } else if (strcmp (opt, "json") == 0) { format = &format_json; } else { fprintf (stderr, "Invalid value for --format: %s\n", opt); return 1; } } else if (STRNCMP_LITERAL (argv[i], "--output=") == 0) { opt = argv[i] + sizeof ("--output=") - 1; if (strcmp (opt, "summary") == 0) { output = OUTPUT_SUMMARY; } else if (strcmp (opt, "threads") == 0) { output = OUTPUT_THREADS; } else if (strcmp (opt, "messages") == 0) { output = OUTPUT_MESSAGES; } else if (strcmp (opt, "files") == 0) { output = OUTPUT_FILES; } else if (strcmp (opt, "tags") == 0) { output = OUTPUT_TAGS; } else { fprintf (stderr, "Invalid value for --output: %s\n", opt); return 1; } } else { fprintf (stderr, "Unrecognized option: %s\n", argv[i]); return 1; } } argc -= i; argv += i; config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; notmuch = notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_ONLY); if (notmuch == NULL) return 1; query_str = query_string_from_args (notmuch, argc, argv); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } if (*query_str == '\0') { fprintf (stderr, "Error: notmuch search requires at least one search term.\n"); return 1; } query = notmuch_query_create (notmuch, query_str); if (query == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } notmuch_query_set_sort (query, sort); switch (output) { default: case OUTPUT_SUMMARY: case OUTPUT_THREADS: ret = do_search_threads (format, query, sort, output, offset, limit); break; case OUTPUT_MESSAGES: case OUTPUT_FILES: ret = do_search_messages (format, query, output, offset, limit); break; case OUTPUT_TAGS: ret = do_search_tags (notmuch, format, query); break; } notmuch_query_destroy (query); notmuch_database_close (notmuch); return ret; }
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_END, 0, 0, 0, 0 } }; opt_index = parse_arguments (argc, argv, options, 1); if (opt_index < 0) return EXIT_FAILURE; 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; } /* 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 EXIT_FAILURE; /* Write the message to the Maildir new directory. */ newpath = maildir_write_new (config, STDIN_FILENO, maildir); if (! newpath) { notmuch_database_destroy (notmuch); return EXIT_FAILURE; } /* 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 ? EXIT_FAILURE : EXIT_SUCCESS; }