tag_parse_status_t parse_tag_command_line (void *ctx, int argc, char **argv, char **query_str, tag_op_list_t *tag_ops) { int i; tag_op_list_reset (tag_ops); for (i = 0; i < argc; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } if (argv[i][0] != '+' && argv[i][0] != '-') break; notmuch_bool_t is_remove = argv[i][0] == '-'; const char *msg; msg = illegal_tag (argv[i] + 1, is_remove); if (msg) { fprintf (stderr, "Error: %s", msg); return TAG_PARSE_INVALID; } tag_op_list_append (tag_ops, argv[i] + 1, is_remove); } *query_str = query_string_from_args (ctx, argc - i, &argv[i]); if (*query_str == NULL || **query_str == '\0') { fprintf (stderr, "Error: notmuch tag requires at least one search term.\n"); return TAG_PARSE_INVALID; } return TAG_PARSE_SUCCESS; }
int notmuch_count_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; char *query_str; int i; notmuch_bool_t output_messages = TRUE; 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], "--output=") == 0) { const char *opt = argv[i] + sizeof ("--output=") - 1; if (strcmp (opt, "threads") == 0) { output_messages = FALSE; } else if (strcmp (opt, "messages") == 0) { output_messages = TRUE; } 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 (ctx, argc, argv); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } if (*query_str == '\0') { query_str = talloc_strdup (ctx, ""); } query = notmuch_query_create (notmuch, query_str); if (query == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } if (output_messages) printf ("%u\n", notmuch_query_count_messages (query)); else printf ("%u\n", notmuch_query_count_threads (query)); notmuch_query_destroy (query); notmuch_database_close (notmuch); return 0; }
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; 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], "--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); break; case OUTPUT_MESSAGES: case OUTPUT_FILES: ret = do_search_messages (format, query, output); break; case OUTPUT_TAGS: ret = do_search_tags (notmuch, format, query); break; } notmuch_query_destroy (query); notmuch_database_close (notmuch); return ret; }
int notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[])) { int *add_tags, *remove_tags; int add_tags_count = 0; int remove_tags_count = 0; char *query_string; notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; notmuch_messages_t *messages; notmuch_message_t *message; struct sigaction action; int i; /* Setup our handler for SIGINT */ memset (&action, 0, sizeof (struct sigaction)); action.sa_handler = handle_sigint; sigemptyset (&action.sa_mask); action.sa_flags = SA_RESTART; sigaction (SIGINT, &action, NULL); add_tags = talloc_size (ctx, argc * sizeof (int)); if (add_tags == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } remove_tags = talloc_size (ctx, argc * sizeof (int)); if (remove_tags == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } for (i = 0; i < argc; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } if (argv[i][0] == '+') { add_tags[add_tags_count++] = i; } else if (argv[i][0] == '-') { remove_tags[remove_tags_count++] = i; } else { break; } } if (add_tags_count == 0 && remove_tags_count == 0) { fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to add or remove.\n"); return 1; } query_string = query_string_from_args (ctx, argc - i, &argv[i]); if (*query_string == '\0') { fprintf (stderr, "Error: notmuch tag requires at least one search term.\n"); return 1; } 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_WRITE); if (notmuch == NULL) return 1; query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } /* tagging is not interested in any special sort order */ notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED); for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages) && !interrupted; notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); notmuch_message_freeze (message); for (i = 0; i < remove_tags_count; i++) notmuch_message_remove_tag (message, argv[remove_tags[i]] + 1); for (i = 0; i < add_tags_count; i++) notmuch_message_add_tag (message, argv[add_tags[i]] + 1); notmuch_message_thaw (message); notmuch_message_destroy (message); } notmuch_query_destroy (query); notmuch_database_close (notmuch); return interrupted; }
int notmuch_count_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; char *query_str; int i; #if 0 char *opt, *end; int i, first = 0, max_threads = -1; notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST; #endif for (i = 0; i < argc && argv[i][0] == '-'; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } #if 0 if (STRNCMP_LITERAL (argv[i], "--first=") == 0) { opt = argv[i] + sizeof ("--first=") - 1; first = strtoul (opt, &end, 10); if (*opt == '\0' || *end != '\0') { fprintf (stderr, "Invalid value for --first: %s\n", opt); return 1; } } else if (STRNCMP_LITERAL (argv[i], "--max-threads=") == 0) { opt = argv[i] + sizeof ("--max-threads=") - 1; max_threads = strtoul (opt, &end, 10); if (*opt == '\0' || *end != '\0') { fprintf (stderr, "Invalid value for --max-threads: %s\n", opt); return 1; } } else 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 #endif { 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 (ctx, argc, argv); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } if (*query_str == '\0') { fprintf (stderr, "Error: notmuch count requires at least one count term.\n"); return 1; } query = notmuch_query_create (notmuch, query_str); if (query == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } printf ("%u\n", notmuch_query_count_messages(query)); notmuch_query_destroy (query); notmuch_database_close (notmuch); return 0; }
int notmuch_reply_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; char *opt, *query_string; int i, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params); notmuch_show_params_t params; reply_format_func = notmuch_reply_format_default; params.part = -1; params.cryptoctx = NULL; 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], "--format=") == 0) { opt = argv[i] + sizeof ("--format=") - 1; if (strcmp (opt, "default") == 0) { reply_format_func = notmuch_reply_format_default; } else if (strcmp (opt, "headers-only") == 0) { reply_format_func = notmuch_reply_format_headers_only; } else { fprintf (stderr, "Invalid value for --format: %s\n", opt); return 1; } } else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { if (params.cryptoctx == NULL) { GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) fprintf (stderr, "Failed to construct gpg context.\n"); else g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); g_object_unref (session); session = NULL; } } 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; query_string = query_string_from_args (ctx, argc, argv); if (query_string == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } if (*query_string == '\0') { fprintf (stderr, "Error: notmuch reply requires at least one search term.\n"); return 1; } notmuch = notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_ONLY); if (notmuch == NULL) return 1; query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } if (reply_format_func (ctx, config, query, ¶ms) != 0) return 1; notmuch_query_destroy (query); notmuch_database_close (notmuch); if (params.cryptoctx) g_object_unref(params.cryptoctx); return ret; }
int notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; char *query_string; char *opt; const notmuch_show_format_t *format = &format_text; notmuch_show_params_t params; int mbox = 0; int format_specified = 0; int i; params.entire_thread = 0; params.raw = 0; params.part = -1; params.cryptoctx = NULL; params.decrypt = 0; 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], "--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; params.entire_thread = 1; } else if (strcmp (opt, "mbox") == 0) { format = &format_mbox; mbox = 1; } else if (strcmp (opt, "raw") == 0) { format = &format_raw; params.raw = 1; } else { fprintf (stderr, "Invalid value for --format: %s\n", opt); return 1; } format_specified = 1; } else if (STRNCMP_LITERAL (argv[i], "--part=") == 0) { params.part = atoi(argv[i] + sizeof ("--part=") - 1); } else if (STRNCMP_LITERAL (argv[i], "--entire-thread") == 0) { params.entire_thread = 1; } else if ((STRNCMP_LITERAL (argv[i], "--verify") == 0) || (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { if (params.cryptoctx == NULL) { GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) fprintf (stderr, "Failed to construct gpg context.\n"); else g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); g_object_unref (session); session = NULL; } if (STRNCMP_LITERAL (argv[i], "--decrypt") == 0) params.decrypt = 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; query_string = query_string_from_args (ctx, argc, argv); if (query_string == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } if (mbox && params.part > 0) { fprintf (stderr, "Error: specifying parts is incompatible with mbox output format.\n"); return 1; } if (*query_string == '\0') { fprintf (stderr, "Error: notmuch show requires at least one search term.\n"); return 1; } notmuch = notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_ONLY); if (notmuch == NULL) return 1; query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } /* if part was requested and format was not specified, use format=raw */ if (params.part >= 0 && !format_specified) format = &format_raw; /* If --format=raw specified without specifying part, we can only * output single message, so set part=0 */ if (params.raw && params.part < 0) params.part = 0; if (params.part >= 0) return do_show_single (ctx, query, format, ¶ms); else return do_show (ctx, query, format, ¶ms); notmuch_query_destroy (query); notmuch_database_close (notmuch); if (params.cryptoctx) g_object_unref(params.cryptoctx); return 0; }
static int _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int argc, char *argv[]) { char *query_str; unsigned int i; char *status_string = NULL; switch (ctx->format_sel) { case NOTMUCH_FORMAT_TEXT: ctx->format = sprinter_text_create (config, stdout); break; case NOTMUCH_FORMAT_TEXT0: if (ctx->output == OUTPUT_SUMMARY) { fprintf (stderr, "Error: --format=text0 is not compatible with --output=summary.\n"); return EXIT_FAILURE; } ctx->format = sprinter_text0_create (config, stdout); break; case NOTMUCH_FORMAT_JSON: ctx->format = sprinter_json_create (config, stdout); break; case NOTMUCH_FORMAT_SEXP: ctx->format = sprinter_sexp_create (config, stdout); break; default: /* this should never happen */ INTERNAL_ERROR("no output format selected"); } notmuch_exit_if_unsupported_format (); if (notmuch_database_open_verbose ( notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_ONLY, &ctx->notmuch, &status_string)) { if (status_string) { fputs (status_string, stderr); free (status_string); } return EXIT_FAILURE; } notmuch_exit_if_unmatched_db_uuid (ctx->notmuch); query_str = query_string_from_args (ctx->notmuch, argc, argv); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); return EXIT_FAILURE; } if (*query_str == '\0') { fprintf (stderr, "Error: notmuch search requires at least one search term.\n"); return EXIT_FAILURE; } ctx->query = notmuch_query_create (ctx->notmuch, query_str); if (ctx->query == NULL) { fprintf (stderr, "Out of memory\n"); return EXIT_FAILURE; } notmuch_query_set_sort (ctx->query, ctx->sort); if (ctx->exclude == NOTMUCH_EXCLUDE_FLAG && ctx->output != OUTPUT_SUMMARY) { /* If we are not doing summary output there is nowhere to * print the excluded flag so fall back on including the * excluded messages. */ fprintf (stderr, "Warning: this output format cannot flag excluded messages.\n"); ctx->exclude = NOTMUCH_EXCLUDE_FALSE; } if (ctx->exclude != NOTMUCH_EXCLUDE_FALSE) { const char **search_exclude_tags; size_t search_exclude_tags_length; search_exclude_tags = notmuch_config_get_search_exclude_tags (config, &search_exclude_tags_length); for (i = 0; i < search_exclude_tags_length; i++) notmuch_query_add_tag_exclude (ctx->query, search_exclude_tags[i]); notmuch_query_set_omit_excluded (ctx->query, ctx->exclude); } return 0; }