--- /dev/null
+Return-Path: <dkg@fifthhorseman.net>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 99EC46DE1601\r
+ for <notmuch@notmuchmail.org>; Wed, 9 Dec 2015 19:40:15 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.033\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.033 tagged_above=-999 required=5\r
+ tests=[AWL=-0.033] autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id sMav7f67XOXL for <notmuch@notmuchmail.org>;\r
+ Wed, 9 Dec 2015 19:40:13 -0800 (PST)\r
+Received: from che.mayfirst.org (che.mayfirst.org [209.234.253.108])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 9D7606DE18EC\r
+ for <notmuch@notmuchmail.org>; Wed, 9 Dec 2015 19:40:06 -0800 (PST)\r
+Received: from fifthhorseman.net (unknown [38.109.115.130])\r
+ by che.mayfirst.org (Postfix) with ESMTPSA id 5965FF989\r
+ for <notmuch@notmuchmail.org>; Wed, 9 Dec 2015 22:40:04 -0500 (EST)\r
+Received: by fifthhorseman.net (Postfix, from userid 1000)\r
+ id BC38D21227; Wed, 9 Dec 2015 22:40:03 -0500 (EST)\r
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>\r
+To: Notmuch Mail <notmuch@notmuchmail.org>\r
+Subject: [PATCH 7/9] add a gpg_path value for notmuch_database_t\r
+Date: Wed, 9 Dec 2015 22:39:44 -0500\r
+Message-Id: <1449718786-28000-8-git-send-email-dkg@fifthhorseman.net>\r
+X-Mailer: git-send-email 2.6.2\r
+In-Reply-To: <1449718786-28000-1-git-send-email-dkg@fifthhorseman.net>\r
+References: <1449718786-28000-1-git-send-email-dkg@fifthhorseman.net>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://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: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Thu, 10 Dec 2015 03:40:16 -0000\r
+\r
+Exposing this to the user of the library lets the user point to\r
+arbitrary gpg executables when trying to decrypt.\r
+---\r
+ lib/database-private.h | 3 ++\r
+ lib/database.cc | 93 +++++++++++++++++++++++++++++++++++++++++++-------\r
+ lib/notmuch.h | 31 +++++++++++++++++\r
+ 3 files changed, 115 insertions(+), 12 deletions(-)\r
+\r
+diff --git a/lib/database-private.h b/lib/database-private.h\r
+index 1bf76c5..9a35044 100644\r
+--- a/lib/database-private.h\r
++++ b/lib/database-private.h\r
+@@ -171,6 +171,9 @@ struct _notmuch_database {\r
+ * notmuch_database_new_revision. */\r
+ unsigned long revision;\r
+ const char *uuid;\r
++\r
++ /* can be NULL, meaning "try to find gpg2 or gpg if possible" */\r
++ char *gpg_path;\r
+ GMimeCryptoContext *gpg_crypto_ctx;\r
+ \r
+ Xapian::QueryParser *query_parser;\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index d0e8800..c40ce77 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -996,6 +996,7 @@ notmuch_database_open_verbose (const char *path,\r
+ notmuch, notmuch->xapian_db->get_uuid ().c_str ());\r
+ \r
+ notmuch->gpg_crypto_ctx = NULL;\r
++ notmuch->gpg_path = NULL;\r
+ \r
+ notmuch->query_parser = new Xapian::QueryParser;\r
+ notmuch->term_gen = new Xapian::TermGenerator;\r
+@@ -1096,6 +1097,10 @@ notmuch_database_close (notmuch_database_t *notmuch)\r
+ g_object_unref (notmuch->gpg_crypto_ctx);\r
+ notmuch->gpg_crypto_ctx = NULL;\r
+ }\r
++ if (notmuch->gpg_path) {\r
++ talloc_free(notmuch->gpg_path);\r
++ notmuch->gpg_path = NULL;\r
++ }\r
+ \r
+ return status;\r
+ }\r
+@@ -2393,17 +2398,6 @@ _notmuch_database_link_message (notmuch_database_t *notmuch,\r
+ return status;\r
+ }\r
+ \r
+-static const char*\r
+-_notmuch_database_get_gpg_path (notmuch_database_t *notmuch)\r
+-{\r
+-#define try_gpg_path(z) if (!access(z, X_OK)) return z\r
+- try_gpg_path("/usr/bin/gpg2");\r
+- try_gpg_path("/bin/gpg2");\r
+- try_gpg_path("/usr/bin/gpg");\r
+- try_gpg_path("/bin/gpg");\r
+- return NULL;\r
+-}\r
+-\r
+ notmuch_private_status_t\r
+ _notmuch_database_get_crypto_for_protocol (notmuch_database_t *notmuch,\r
+ const char *protocol,\r
+@@ -2425,7 +2419,7 @@ _notmuch_database_get_crypto_for_protocol (notmuch_database_t *notmuch,\r
+ * here? how would this config get into the library? Is\r
+ * this an option we can set on the database object? Or\r
+ * elsewhere? */\r
+- notmuch->gpg_crypto_ctx = g_mime_gpg_context_new (NULL, _notmuch_database_get_gpg_path(notmuch));\r
++ notmuch->gpg_crypto_ctx = g_mime_gpg_context_new (NULL, notmuch_database_get_gpg_path(notmuch));\r
+ if (! notmuch->gpg_crypto_ctx)\r
+ return NOTMUCH_PRIVATE_STATUS_FAILED_CRYPTO_CONTEXT_CREATION;\r
+ \r
+@@ -2752,3 +2746,78 @@ notmuch_database_status_string (const notmuch_database_t *notmuch)\r
+ {\r
+ return notmuch->status_string;\r
+ }\r
++\r
++\r
++static notmuch_bool_t\r
++_find_in_path(const char* path)\r
++{\r
++ char *c = NULL, *save = NULL, *tok;\r
++ size_t n;\r
++ int dfd = -1;\r
++ notmuch_bool_t ret = FALSE;\r
++ \r
++ n = confstr(_CS_PATH, NULL, 0);\r
++ c = (char*)talloc_size(NULL, n);\r
++ if (!c)\r
++ return FALSE;\r
++ confstr(_CS_PATH, c, n);\r
++\r
++ tok = strtok_r(c, ":", &save);\r
++ while (tok) {\r
++ dfd = open(tok, O_DIRECTORY | O_RDONLY);\r
++ if (dfd != -1) {\r
++ if (!faccessat(dfd, path, X_OK, 0)) {\r
++ ret = TRUE;\r
++ goto done;\r
++ }\r
++ close(dfd);\r
++ }\r
++ tok = strtok_r(NULL, ":", &save);\r
++ }\r
++done:\r
++ if (dfd != -1)\r
++ close(dfd);\r
++ if (c)\r
++ talloc_free(c);\r
++ return ret;\r
++}\r
++\r
++notmuch_status_t\r
++notmuch_database_set_gpg_path (notmuch_database_t *notmuch, const char* path)\r
++{\r
++ /* return success if this matches what is already configured */\r
++ if ((!path && !notmuch->gpg_path) ||\r
++ (path && notmuch->gpg_path && 0 == strcmp(path, notmuch->gpg_path)))\r
++ return NOTMUCH_STATUS_SUCCESS;\r
++ \r
++ if (!path && !_find_in_path(path))\r
++ return NOTMUCH_STATUS_FILE_ERROR;\r
++\r
++ /* clear any existing gpg_crypto_ctx, since things are changing */\r
++ if (notmuch->gpg_crypto_ctx) {\r
++ g_object_unref (notmuch->gpg_crypto_ctx);\r
++ notmuch->gpg_crypto_ctx = NULL;\r
++ }\r
++\r
++ if (notmuch->gpg_path) {\r
++ talloc_free(notmuch->gpg_path);\r
++ notmuch->gpg_path = NULL;\r
++ }\r
++\r
++ if (path)\r
++ notmuch->gpg_path = talloc_strdup (notmuch, path);\r
++ \r
++ return NOTMUCH_STATUS_SUCCESS;\r
++}\r
++\r
++const char*\r
++notmuch_database_get_gpg_path (const notmuch_database_t *notmuch)\r
++{\r
++ if (notmuch->gpg_path)\r
++ return notmuch->gpg_path;\r
++\r
++#define try_gpg_path(z) if (_find_in_path(z)) return z\r
++ try_gpg_path("gpg2");\r
++ try_gpg_path("gpg");\r
++ return NULL;\r
++}\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 809a2ea..e9cfed3 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -591,6 +591,37 @@ notmuch_database_add_message_try_decrypt (notmuch_database_t *database,\r
+ notmuch_message_t **message);\r
+ \r
+ /**\r
++ * Tell the notmuch database where to find GnuPG.\r
++ *\r
++ * This is only useful when notmuch might try to use GnuPG to decrypt\r
++ * MIME parts (see for example\r
++ * notmuch_database_add_message_try_decrypt). The argument needs to\r
++ * be an executable version of gpg.\r
++ * \r
++ * If this function has never been invoked, notmuch will try to find\r
++ * gpg in reasonable places.\r
++ *\r
++ * This value is not currently stored in the database on disk, it is\r
++ * only used for this notmuch_database_t while it exists.\r
++ *\r
++ * Return value:\r
++ *\r
++ * NOTMUCH_STATUS_SUCCESS: the path was accepted and will be used.\r
++ * \r
++ * NOTMUCH_STATUS_FILE_ERROR: the path given either wasn't found or\r
++ * wasn't executable.\r
++ */\r
++notmuch_status_t\r
++notmuch_database_set_gpg_path (notmuch_database_t *database, const char* path);\r
++ \r
++/**\r
++ * Find out where the notmuch database will try to find gpg if it\r
++ * needs to use it.\r
++ */\r
++const char*\r
++notmuch_database_get_gpg_path (const notmuch_database_t *database);\r
++\r
++/**\r
+ * Remove a message filename from the given notmuch database. If the\r
+ * message has no more filenames, remove the message.\r
+ *\r
+-- \r
+2.6.2\r
+\r