From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id 74B1B6DE0999 for ; Thu, 8 Dec 2016 04:26:46 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: 0.553 X-Spam-Level: X-Spam-Status: No, score=0.553 tagged_above=-999 required=5 tests=[AWL=-0.418, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_SOFTFAIL=0.972] autolearn=disabled Received: from arlo.cworth.org ([127.0.0.1]) by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 763eF520MYe0 for ; Thu, 8 Dec 2016 04:26:46 -0800 (PST) Received: from ni.com (skprod3.natinst.com [130.164.80.24]) by arlo.cworth.org (Postfix) with ESMTPS id 4611D6DE0943 for ; Thu, 8 Dec 2016 04:26:44 -0800 (PST) Received: from us-aus-exch2.ni.corp.natinst.com (us-aus-exch2.ni.corp.natinst.com [130.164.68.12]) by us-aus-skprod3.natinst.com (8.15.0.59/8.15.0.59) with ESMTPS id uB8CQXrf008331 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 8 Dec 2016 06:26:33 -0600 Received: from us-aus-exhub2.ni.corp.natinst.com (130.164.68.32) by us-aus-exch2.ni.corp.natinst.com (130.164.68.12) with Microsoft SMTP Server (TLS) id 15.0.1156.6; Thu, 8 Dec 2016 06:26:33 -0600 Received: from adi-pc-linux.natinst.com (130.164.49.7) by us-aus-exhub2.ni.corp.natinst.com (130.164.68.32) with Microsoft SMTP Server id 15.0.1156.6 via Frontend Transport; Thu, 8 Dec 2016 06:26:32 -0600 From: Ioan-Adrian Ratiu To: , Subject: [PATCH v5 2/2] notmuch-config: replace config reading function Date: Thu, 8 Dec 2016 14:24:45 +0200 Message-ID: <20161208122445.30918-3-adi@adirat.com> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161208122445.30918-1-adi@adirat.com> References: <20161208122445.30918-1-adi@adirat.com> MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-12-08_06:, , signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=25 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1609300000 definitions=main-1612080197 X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Dec 2016 12:26:46 -0000 Config files are currently read using glib's g_key_file_load_from_file function which is very inconvenient because it's limited by design to read only from "regular data files" in a filesystem. Because of this limitation notmuch can't read configs from pipes, fifos, sockets, stdin, etc. Not even "notmuch --config=/dev/stdin" works: Error reading configuration file /dev/stdin: Not a regular file So replace g_key_file_load_from_file with g_key_file_load_from_data which gives us much more freedom to read configs from multiple sources. This also helps the more security sensitive users: If someone has private information in the config file, it can be encrypted on disk, then decrypted in RAM and passed through a pipe directly to notmuch without the use of intermediate plain text files. Signed-off-by: Ioan-Adrian Ratiu --- notmuch-config.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/notmuch-config.c b/notmuch-config.c index bd52790..30823cb 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -205,32 +205,74 @@ get_username_from_passwd_file (void *ctx) static notmuch_bool_t get_config_from_file (notmuch_config_t *config, notmuch_bool_t create_new) { + #define BUF_SIZE 4096 + char *config_str = NULL; + int config_len = 0; + int config_bufsize = BUF_SIZE; + size_t len; GError *error = NULL; notmuch_bool_t ret = FALSE; - if (g_key_file_load_from_file (config->key_file, config->filename, - G_KEY_FILE_KEEP_COMMENTS, &error)) - return TRUE; - - if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) { + FILE *fp = fopen(config->filename, "r"); + if (fp == NULL) { /* If create_new is true, then the caller is prepared for a * default configuration file in the case of FILE NOT FOUND. */ if (create_new) { config->is_new = TRUE; ret = TRUE; + goto out; } else { - fprintf (stderr, "Configuration file %s not found.\n" + fprintf (stderr, "Error opening config file '%s': %s\n" "Try running 'notmuch setup' to create a configuration.\n", - config->filename); + config->filename, strerror(errno)); + goto out; + } + } + + config_str = talloc_zero_array (config, char, config_bufsize); + if (config_str == NULL) { + fprintf (stderr, "Error reading '%s': Out of memory\n", config->filename); + goto out; + } + + while ((len = fread (config_str + config_len, 1, + config_bufsize - config_len, fp)) > 0) { + config_len += len; + if (config_len == config_bufsize) { + config_bufsize += BUF_SIZE; + config_str = talloc_realloc (config, config_str, char, config_bufsize); + if (config_str == NULL) { + fprintf (stderr, "Error reading '%s': Failed to reallocate memory\n", + config->filename); + goto out; + } } - } else { - fprintf (stderr, "Error reading configuration file %s: %s\n", - config->filename, error->message); } + if (ferror (fp)) { + fprintf (stderr, "Error reading '%s': I/O error\n", config->filename); + goto out; + } + + if (g_key_file_load_from_data (config->key_file, config_str, config_len, + G_KEY_FILE_KEEP_COMMENTS, &error)) { + ret = TRUE; + goto out; + } + + fprintf (stderr, "Error parsing config file '%s': %s\n", + config->filename, error->message); + g_error_free (error); +out: + if (fp) + fclose(fp); + + if (config_str) + talloc_free(config_str); + return ret; } -- 2.10.2