[PATCH 4/4] Add 'cat' subcommand

Michal Sojka sojkam1 at fel.cvut.cz
Thu Apr 8 07:42:46 PDT 2010


This command dumps raw message identified by filename to standard
output. It uses mail store interface to get the message from the right
place.

notmuch.el was modified to use this command to access the raw message
content (view/save attachments, view raw message and pipe message to
command).

With this patch, it is straightforward to use notmuch emacs interface
remotely over SSH. To do this, it is sufficient to redefine
notmuch-command variable to contain the name of a script containing:

    ssh user at host notmuch "$@"

Signed-off-by: Michal Sojka <sojkam1 at fel.cvut.cz>
---
 NEWS                  |    3 ++
 emacs/notmuch-show.el |   11 ++++++--
 notmuch-client.h      |    3 ++
 notmuch-show.c        |   62 +++++++++++++++++++++++++++++++++++++++++++++++++
 notmuch.c             |    4 +++
 5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index f29ac27..3bd21fa 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+A new subcommand 'cat' was added, which simplifies use of Emacs
+interface with remote database (accessed over SSH).
+
 Notmuch 0.1 (2010-04-05)
 ========================
 This is the first release of the notmuch mail system.
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 6f5a55d..45d49d1 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -328,7 +328,11 @@ buffer."
 (defun notmuch-show-view-raw-message ()
   "View the raw email of the current message."
   (interactive)
-  (view-file (notmuch-show-get-filename)))
+  (let ((filename (notmuch-show-get-filename)))
+    (let ((buf (get-buffer-create (concat "*notmuch-raw-" filename "*"))))
+      (switch-to-buffer buf)
+      (save-excursion
+	(call-process notmuch-command nil t nil "cat" filename)))))
 
 (defmacro with-current-notmuch-show-message (&rest body)
   "Evaluate body with current buffer set to the text of current message"
@@ -336,7 +340,7 @@ buffer."
      (let ((filename (notmuch-show-get-filename)))
        (let ((buf (generate-new-buffer (concat "*notmuch-msg-" filename "*"))))
          (with-current-buffer buf
-           (insert-file-contents filename nil nil nil t)
+	    (call-process notmuch-command nil t nil "cat" filename)
            , at body)
 	 (kill-buffer buf)))))
 
@@ -390,7 +394,8 @@ current email message as stdin. Anything printed by the command
 to stdout or stderr will appear in the *Messages* buffer."
   (interactive "sPipe message to command: ")
   (apply 'start-process-shell-command "notmuch-pipe-command" "*notmuch-pipe*"
-	 (list command " < " (shell-quote-argument (notmuch-show-get-filename)))))
+	 (list notmuch-command "cat"
+	       (shell-quote-argument (notmuch-show-get-filename) " | " command))))
 
 (defun notmuch-show-move-to-current-message-summary-line ()
   "Move to the beginning of the one-line summary of the current message.
diff --git a/notmuch-client.h b/notmuch-client.h
index 728e448..666e70d 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -111,6 +111,9 @@ int
 notmuch_search_tags_command (void *ctx, int argc, char *argv[]);
 
 int
+notmuch_cat_command (void *ctx, int argc, char *argv[]);
+
+int
 notmuch_part_command (void *ctx, int argc, char *argv[]);
 
 const char *
diff --git a/notmuch-show.c b/notmuch-show.c
index 66fd773..dbab9a7 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -515,6 +515,68 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 }
 
 int
+notmuch_cat_command (void *ctx, unused (int argc), unused (char *argv[]))
+{
+    notmuch_config_t *config;
+    notmuch_database_t *notmuch;
+    notmuch_mailstore_t *mailstore;
+    int i;
+    FILE *file;
+    const char *filename;
+    size_t size;
+    char buf[4096];
+
+    for (i = 0; i < argc && argv[i][0] == '-'; i++) {
+/* 	if (STRNCMP_LITERAL (argv[i], "--part=") == 0) { */
+/* 	    part = atoi(argv[i] + sizeof ("--part=") - 1); */
+/* 	} else { */
+	    fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
+/* 	    return 1; */
+/* 	} */
+    }
+
+    argc -= i;
+    argv += i;
+
+    if (argc == 0) {
+	fprintf (stderr, "Error: No filename given\n");
+	return 1;
+    }
+    filename = argv[0];
+
+    config = notmuch_config_open (ctx, NULL, NULL);
+    if (config == NULL)
+	return 1;
+
+    mailstore = notmuch_config_get_mailstore (config);
+
+    if (mailstore == NULL) {
+	fprintf (stderr, "Error: I have no mailstore\n");
+	return 1;
+    }
+
+    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
+				     NOTMUCH_DATABASE_MODE_READ_ONLY,
+				     mailstore);
+
+    file = notmuch_mailstore_open_file(mailstore, filename);
+    if (file == NULL) {
+	fprintf (stderr, "Error: Cannot open %s in %s: %s\n", filename,
+		 notmuch_mailstore_get_type (mailstore), strerror (errno));
+	return 1;
+    }
+    while  (!feof (file)) {
+	size = fread(buf, 1, sizeof(buf), file);
+	fwrite (buf, size, 1, stdout);
+    }
+    fclose (file);
+
+    notmuch_database_close (notmuch);
+
+    return 0;
+}
+
+int
 notmuch_part_command (void *ctx, unused (int argc), unused (char *argv[]))
 {
 	notmuch_config_t *config;
diff --git a/notmuch.c b/notmuch.c
index f5669fc..bcebcdc 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -294,6 +294,10 @@ command_t commands[] = {
       "\tcontain tags only from messages that match the search-term(s).\n"
       "\n"
       "\tIn both cases the list will be alphabetically sorted." },
+    { "cat", notmuch_cat_command,
+      "<path>",
+      "Dump raw message identified by path to standard output.",
+      "" },
     { "part", notmuch_part_command,
       "--part=<num> <search-terms>",
       "Output a single MIME part of a message.",
-- 
1.7.0.2



More information about the notmuch mailing list