Re: [PATCH v2 1/7] cli: allow query to come from stdin
authorMark Walters <markwalters1009@gmail.com>
Mon, 26 Nov 2012 10:15:06 +0000 (10:15 +0000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:51:01 +0000 (09:51 -0800)
20/df52574b30c0546348d5738b0ce33e1e28fc25 [new file with mode: 0644]

diff --git a/20/df52574b30c0546348d5738b0ce33e1e28fc25 b/20/df52574b30c0546348d5738b0ce33e1e28fc25
new file mode 100644 (file)
index 0000000..82bd34c
--- /dev/null
@@ -0,0 +1,243 @@
+Return-Path: <m.walters@qmul.ac.uk>\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 37899431FAF\r
+       for <notmuch@notmuchmail.org>; Mon, 26 Nov 2012 02:15:16 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -1.098\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-1.098 tagged_above=-999 required=5\r
+       tests=[DKIM_ADSP_CUSTOM_MED=0.001, FREEMAIL_FROM=0.001,\r
+       NML_ADSP_CUSTOM_MED=1.2, RCVD_IN_DNSWL_MED=-2.3] 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 sr-mR+LyCRUR for <notmuch@notmuchmail.org>;\r
+       Mon, 26 Nov 2012 02:15:14 -0800 (PST)\r
+Received: from mail2.qmul.ac.uk (mail2.qmul.ac.uk [138.37.6.6])\r
+       (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id 98A76431FAE\r
+       for <notmuch@notmuchmail.org>; Mon, 26 Nov 2012 02:15:14 -0800 (PST)\r
+Received: from smtp.qmul.ac.uk ([138.37.6.40])\r
+       by mail2.qmul.ac.uk with esmtp (Exim 4.71)\r
+       (envelope-from <m.walters@qmul.ac.uk>)\r
+       id 1TcviW-0002AG-2M; Mon, 26 Nov 2012 10:15:10 +0000\r
+Received: from 93-97-24-31.zone5.bethere.co.uk ([93.97.24.31] helo=localhost)\r
+       by smtp.qmul.ac.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69)\r
+       (envelope-from <m.walters@qmul.ac.uk>)\r
+       id 1TcviV-0004MC-LJ; Mon, 26 Nov 2012 10:15:07 +0000\r
+From: Mark Walters <markwalters1009@gmail.com>\r
+To: Austin Clements <amdragon@MIT.EDU>\r
+Subject: Re: [PATCH v2 1/7] cli: allow query to come from stdin\r
+In-Reply-To: <20121124174134.GH4562@mit.edu>\r
+References: <1353763256-32336-1-git-send-email-markwalters1009@gmail.com>\r
+       <1353763256-32336-2-git-send-email-markwalters1009@gmail.com>\r
+       <20121124174134.GH4562@mit.edu>\r
+User-Agent: Notmuch/0.14+81~g9730584 (http://notmuchmail.org) Emacs/23.4.1\r
+       (i486-pc-linux-gnu)\r
+Date: Mon, 26 Nov 2012 10:15:06 +0000\r
+Message-ID: <87mwy4smad.fsf@qmul.ac.uk>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=us-ascii\r
+X-Sender-Host-Address: 93.97.24.31\r
+X-QM-SPAM-Info: Sender has good ham record.  :)\r
+X-QM-Body-MD5: 3b216b42eab5445ef9a4d9355be19837 (of first 20000 bytes)\r
+X-SpamAssassin-Score: -1.7\r
+X-SpamAssassin-SpamBar: -\r
+X-SpamAssassin-Report: The QM spam filters have analysed this message to\r
+       determine if it is\r
+       spam. We require at least 5.0 points to mark a message as spam.\r
+       This message scored -1.7 points.\r
+       Summary of the scoring: \r
+       * -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/,\r
+       *      medium trust\r
+       *      [138.37.6.40 listed in list.dnswl.org]\r
+       * 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail\r
+       provider *      (markwalters1009[at]gmail.com)\r
+       *  0.6 AWL AWL: From: address is in the auto white-list\r
+X-QM-Scan-Virus: ClamAV says the message is clean\r
+Cc: notmuch@notmuchmail.org\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: Mon, 26 Nov 2012 10:15:16 -0000\r
+\r
+\r
+Hi\r
+\r
+Many thanks for all the reviews: I have incorporated most of your and\r
+Tomi's suggestions in my latest version. However, for this patch I\r
+wonder whether just using David's batch tagging would be sufficient. It\r
+does mean that I can't construct the list of possible tag removals\r
+correctly for a large query but I can just return all tags in this\r
+case. I think this is probably an acceptable trade off: you don't get\r
+the correct list of possible completions if you are tagging more than\r
+5000 messages at once.\r
+\r
+This patch is not very complicated but it does add another\r
+feature/option to the command line so if it is not needed I am inclined\r
+not to add it. If people think that being able to do searches for\r
+queries in excess of ARGMAX (possible 2MB or so) is useful then we could\r
+add it.\r
+\r
+Incidentally for the tag completions: my view is the correct thing is to\r
+offer completions (for tag removal) based on what tags the buffer shows\r
+(ie what was there when the query was run) rather than what is actually\r
+tags are present now: this would be easy to add if anyone cared\r
+sufficiently.\r
+\r
+Any thoughts?\r
+\r
+Best wishes\r
+\r
+Mark\r
+\r
+Austin Clements <amdragon@MIT.EDU> writes:\r
+\r
+> Quoth markwalters1009 on Nov 24 at  1:20 pm:\r
+>> From: Mark Walters <markwalters1009@gmail.com>\r
+>> \r
+>> After this series there will be times when a caller will want to pass\r
+>> a very large query string to notmuch (eg a list of 10,000 message-ids)\r
+>> and this can exceed the size of ARG_MAX. Hence allow notmuch to take\r
+>> the query from stdin (if the query is -).\r
+>> ---\r
+>>  query-string.c |   41 +++++++++++++++++++++++++++++++++++++++++\r
+>>  1 files changed, 41 insertions(+), 0 deletions(-)\r
+>> \r
+>> diff --git a/query-string.c b/query-string.c\r
+>> index 6536512..b1fbdeb 100644\r
+>> --- a/query-string.c\r
+>> +++ b/query-string.c\r
+>> @@ -20,6 +20,44 @@\r
+>>  \r
+>>  #include "notmuch-client.h"\r
+>>  \r
+>> +/* Read a single query string from STDIN, using\r
+>> + * 'ctx' as the talloc owner for all allocations.\r
+>> + *\r
+>> + * This function returns NULL in case of insufficient memory or read\r
+>> + * errors.\r
+>> + */\r
+>> +static char *\r
+>> +query_string_from_stdin (void *ctx)\r
+>> +{\r
+>> +    char *query_string;\r
+>> +    char buf[4096];\r
+>> +    ssize_t remain;\r
+>> +\r
+>> +    query_string = talloc_strdup (ctx, "");\r
+>> +    if (query_string == NULL)\r
+>> +   return NULL;\r
+>> +\r
+>> +    for (;;) {\r
+>> +   remain = read (STDIN_FILENO, buf, sizeof(buf) - 1);\r
+>> +   if (remain == 0)\r
+>> +       break;\r
+>> +   if (remain < 0) {\r
+>> +       if (errno == EINTR)\r
+>> +           continue;\r
+>> +       fprintf (stderr, "Error: reading from standard input: %s\n",\r
+>> +                strerror (errno));\r
+>\r
+> talloc_free (query_string) ?\r
+>\r
+>> +       return NULL;\r
+>> +   }\r
+>> +\r
+>> +   buf[remain] = '\0';\r
+>> +   query_string = talloc_strdup_append (query_string, buf);\r
+>\r
+> Eliminate the NUL in buf and instead\r
+>  talloc_strndup_append (query_string, buf, remain) ?\r
+>\r
+> Should there be some (large) bound on the size of the query string to\r
+> prevent runaway?\r
+>\r
+>> +   if (query_string == NULL)\r
+>\r
+> Technically it would be good to talloc_free the old pointer here, too.\r
+>\r
+>> +       return NULL;\r
+>> +    }\r
+>> +\r
+>> +    return query_string;\r
+>> +}\r
+>> +\r
+>\r
+> This whole approach is O(n^2), which might actually matter for large\r
+> query strings.  How about (tested, but only a little):\r
+>\r
+> #define MAX_QUERY_STRING_LENGTH (16 * 1024 * 1024)\r
+>\r
+> /* Read a single query string from STDIN, using 'ctx' as the talloc\r
+>  * owner for all allocations.\r
+>  *\r
+>  * This function returns NULL in case of insufficient memory or read\r
+>  * errors.\r
+>  */\r
+> static char *\r
+> query_string_from_stdin (void *ctx)\r
+> {\r
+>     char *query_string = NULL, *new_qs;\r
+>     size_t pos = 0, end = 0;\r
+>     ssize_t got;\r
+>\r
+>     for (;;) {\r
+>      if (end - pos < 512) {\r
+>          end = MAX(end * 2, 1024);\r
+>          if (end >= MAX_QUERY_STRING_LENGTH) {\r
+>              fprintf (stderr, "Error: query too long\n");\r
+>              goto FAIL;\r
+>          }\r
+>          new_qs = talloc_realloc (ctx, query_string, char, end);\r
+>          if (new_qs == NULL)\r
+>              goto FAIL;\r
+>          query_string = new_qs;\r
+>      }\r
+>\r
+>      got = read (STDIN_FILENO, query_string + pos, end - pos - 1);\r
+>      if (got == 0)\r
+>          break;\r
+>      if (got < 0) {\r
+>         if (errno == EINTR)\r
+>             continue;\r
+>         fprintf (stderr, "Error: reading from standard input: %s\n",\r
+>                  strerror (errno));\r
+>         goto FAIL;\r
+>      }\r
+>      pos += got;\r
+>     }\r
+>\r
+>     query_string[pos] = '\0';\r
+>     return query_string;\r
+>\r
+>  FAIL:\r
+>     talloc_free (query_string);\r
+>     return NULL;\r
+> }\r
+>\r
+>>  /* Construct a single query string from the passed arguments, using\r
+>>   * 'ctx' as the talloc owner for all allocations.\r
+>>   *\r
+>> @@ -35,6 +73,9 @@ query_string_from_args (void *ctx, int argc, char *argv[])\r
+>>      char *query_string;\r
+>>      int i;\r
+>>  \r
+>> +    if ((argc == 1) && (strcmp ("-", argv[0]) == 0))\r
+>> +   return query_string_from_stdin (ctx);\r
+>> +\r
+>>      query_string = talloc_strdup (ctx, "");\r
+>>      if (query_string == NULL)\r
+>>     return NULL;\r