--- /dev/null
+Return-Path: <neil@linux.intel.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 62B17431FAF\r
+ for <notmuch@notmuchmail.org>; Sun, 7 Jul 2013 04:13:40 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -5\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-5 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_HI=-5] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id C4ffbisR8eQa for <notmuch@notmuchmail.org>;\r
+ Sun, 7 Jul 2013 04:13:35 -0700 (PDT)\r
+Received: from mga09.intel.com (mga09.intel.com [134.134.136.24])\r
+ by olra.theworths.org (Postfix) with ESMTP id 300AB431FB6\r
+ for <notmuch@notmuchmail.org>; Sun, 7 Jul 2013 04:13:30 -0700 (PDT)\r
+Received: from orsmga002.jf.intel.com ([10.7.209.21])\r
+ by orsmga102.jf.intel.com with ESMTP; 07 Jul 2013 04:10:56 -0700\r
+X-ExtLoop1: 1\r
+X-IronPort-AV: E=Sophos;i="4.87,1013,1363158000"; d="scan'208";a="365957330"\r
+Received: from unknown (HELO neilpc.config) ([10.252.122.25])\r
+ by orsmga002.jf.intel.com with ESMTP; 07 Jul 2013 04:13:21 -0700\r
+From: Neil Roberts <neil@linux.intel.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 2/2] emacs: crypto: Handle prompting for passwords\r
+Date: Sun, 7 Jul 2013 12:14:32 +0100\r
+Message-Id: <1373195672-9338-3-git-send-email-neil@linux.intel.com>\r
+X-Mailer: git-send-email 1.7.11.3.g3c3efa5\r
+In-Reply-To: <1373195672-9338-1-git-send-email-neil@linux.intel.com>\r
+References: <1373195672-9338-1-git-send-email-neil@linux.intel.com>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sun, 07 Jul 2013 11:13:40 -0000\r
+\r
+This makes the Emacs client handle prompting for passwords when\r
+decrypting PGP messages via the new --status-fd and --command-fd\r
+options to the show and reply commands.\r
+\r
+The prompting is handled directly in notmuch-call-notmuch-sexp.\r
+Instead of calling call-process to invoke notmuch synchronously it is\r
+now run asynchronously via notmuch-start-notmuch so that it can\r
+install a process filter to handle the status messages. The function\r
+then runs a loop calling accept-process-output so that it can block\r
+until the process actually completes.\r
+\r
+Emacs doesn't support having multiple file descriptors to talk to a\r
+child process apart from stdin/out so the --status-fd is set to 1 and\r
+the --command-fd is set to 0. This means that the status messages will\r
+actually be interleaved with the sexp output. I think this shouldn't\r
+be a problem because both the sexp output and the status messages are\r
+split into lines and it shouldn't be possible for a sexp message to\r
+begin with [NOTMUCH:] so it is easy to separate out the two types of\r
+message.\r
+\r
+The process filter collects the output into a temporary buffer.\r
+Whenever it receives a line beginning with [NOTMUCH:] it will process\r
+the command and remove the line so that the final buffer only contains\r
+the sexp. The only handler currently is for GET_HIDDEN which just\r
+calls read-passwd to prompt for the password and then writes it back\r
+out to the stdin of the notmuch process.\r
+\r
+This is based on similar functionality in epg.el which handles\r
+invoking GPG.\r
+---\r
+ emacs/notmuch-lib.el | 66 +++++++++++++++++++++++++++++++++++++++++++-------\r
+ emacs/notmuch-mua.el | 2 +-\r
+ emacs/notmuch-query.el | 3 ++-\r
+ 3 files changed, 60 insertions(+), 11 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el\r
+index 8deb7de..0cc23fe 100644\r
+--- a/emacs/notmuch-lib.el\r
++++ b/emacs/notmuch-lib.el\r
+@@ -467,6 +467,48 @@ You may need to restart Emacs or upgrade your notmuch package."))\r
+ ;; `notmuch-logged-error' does not return.\r
+ ))))\r
+ \r
++(defun notmuch--status-GET_HIDDEN (process args)\r
++ ;; The args string should be readable by emacs if it is made into a list\r
++ (let* ((args-list (read (concat "(" args ")")))\r
++ (prompt (nth 1 args-list))\r
++ (pwd (read-passwd (if prompt\r
++ (concat prompt ": ")\r
++ "GPG password: "))))\r
++ (process-send-string process (concat pwd "\n"))\r
++ (clear-string pwd)))\r
++\r
++(defun notmuch--process-filter (process string)\r
++ "Callback used by `notmuch-call-notmuch-sexp` used to handle the status fd."\r
++\r
++ (when (buffer-live-p (process-buffer process))\r
++ (with-current-buffer (process-buffer process)\r
++\r
++ (goto-char (point-max))\r
++\r
++ (let ((insertion-point (point)))\r
++ (insert string)\r
++\r
++ ;; Check if the string contains any status lines\r
++ (goto-char insertion-point)\r
++ (beginning-of-line)\r
++\r
++ (while (re-search-forward "^\\[NOTMUCH:\\].*\n" nil t)\r
++ (let ((line-beginning (match-beginning 0))\r
++ (line-end (match-end 0)))\r
++ (goto-char (+ line-beginning 10))\r
++ (when (looking-at " *\\([A-Z_]+\\)")\r
++ ;; If there is a function defined that looks like it is made\r
++ ;; to handle this particular status then call it passing the\r
++ ;; remainder of the line as an argument\r
++ (let ((symbol (intern-soft (concat "notmuch--status-"\r
++ (match-string 1)))))\r
++ (when (and symbol (fboundp symbol))\r
++ (funcall symbol\r
++ process\r
++ (buffer-substring (match-end 0) line-end)))))\r
++ ;; Remove the status so that it won't form part of the sexp\r
++ (delete-region line-beginning line-end)))))))\r
++\r
+ (defun notmuch-call-notmuch-sexp (&rest args)\r
+ "Invoke `notmuch-command' with ARGS and return the parsed S-exp output.\r
+ \r
+@@ -474,15 +516,21 @@ If notmuch exits with a non-zero status, this will pop up a\r
+ buffer containing notmuch's output and signal an error."\r
+ \r
+ (with-temp-buffer\r
+- (let ((err-file (make-temp-file "nmerr")))\r
+- (unwind-protect\r
+- (let ((status (apply #'call-process\r
+- notmuch-command nil (list t err-file) nil args)))\r
+- (notmuch-check-exit-status status (cons notmuch-command args)\r
+- (buffer-string) err-file)\r
+- (goto-char (point-min))\r
+- (read (current-buffer)))\r
+- (delete-file err-file)))))\r
++ (let ((proc (apply #'notmuch-start-notmuch\r
++ "notmuch"\r
++ (current-buffer) nil args)))\r
++ (set-process-filter proc #'notmuch--process-filter)\r
++\r
++ ;; Synchronously wait until the process completes\r
++ (while (eq (process-status proc) 'run)\r
++ (accept-process-output proc 1))\r
++\r
++ ;; According to similar code in epg-wait-for-completion, this is\r
++ ;; needed to run the process filter right now.\r
++ (sleep-for 0.1)\r
++\r
++ (goto-char (point-min))\r
++ (read (current-buffer)))))\r
+ \r
+ (defun notmuch-start-notmuch (name buffer sentinel &rest args)\r
+ "Start and return an asynchronous notmuch command.\r
+diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el\r
+index 329d342..af7dd03 100644\r
+--- a/emacs/notmuch-mua.el\r
++++ b/emacs/notmuch-mua.el\r
+@@ -150,7 +150,7 @@ list."\r
+ reply\r
+ original)\r
+ (when notmuch-show-process-crypto\r
+- (setq args (append args '("--decrypt"))))\r
++ (setq args (append args '("--decrypt" "--status-fd=1" "--command-fd=0"))))\r
+ \r
+ (if reply-all\r
+ (setq args (append args '("--reply-to=all")))\r
+diff --git a/emacs/notmuch-query.el b/emacs/notmuch-query.el\r
+index 51d427f..0788e8c 100644\r
+--- a/emacs/notmuch-query.el\r
++++ b/emacs/notmuch-query.el\r
+@@ -31,7 +31,8 @@ is a possibly empty forest of replies.\r
+ "\r
+ (let ((args '("show" "--format=sexp" "--format-version=1")))\r
+ (if notmuch-show-process-crypto\r
+- (setq args (append args '("--decrypt"))))\r
++ (setq args (append args\r
++ '("--decrypt" "--status-fd=1" "--command-fd=0"))))\r
+ (setq args (append args search-terms))\r
+ (apply #'notmuch-call-notmuch-sexp args)))\r
+ \r
+-- \r
+1.7.11.3.g3c3efa5\r
+\r