* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2014 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for reading the configuration file, and for displaying
#include "exim.h"
static void fn_smtp_receive_timeout(const uschar * name, const uschar * str);
-
+static void save_config_line(const uschar* line);
+static void save_config_position(const uschar *file, int line);
+static void print_config(BOOL admin);
#define CSTATE_STACK_SIZE 10
int lineno;
} config_file_item;
+/* Structure for chain of configuration lines (-bP config) */
+
+typedef struct config_line_item {
+ struct config_line_item *next;
+ uschar *line;
+} config_line_item;
+
+static config_line_item* config_lines;
+
/* Structure of table of conditional words and their state transitions */
typedef struct cond_item {
int value;
} syslog_fac_item;
+/* constants */
+static const char * const hidden = "<value not displayable>";
/* Static variables */
{ "dns_ipv4_lookup", opt_stringptr, &dns_ipv4_lookup },
{ "dns_retrans", opt_time, &dns_retrans },
{ "dns_retry", opt_int, &dns_retry },
+ { "dns_trust_aa", opt_stringptr, &dns_trust_aa },
{ "dns_use_edns0", opt_int, &dns_use_edns0 },
/* This option is now a no-op, retained for compability */
{ "drop_cr", opt_bool, &drop_cr },
{ "rfc1413_hosts", opt_stringptr, &rfc1413_hosts },
{ "rfc1413_query_timeout", opt_time, &rfc1413_query_timeout },
{ "sender_unqualified_hosts", opt_stringptr, &sender_unqualified_hosts },
+ { "slow_lookup_log", opt_int, &slow_lookup_log },
{ "smtp_accept_keepalive", opt_bool, &smtp_accept_keepalive },
{ "smtp_accept_max", opt_int, &smtp_accept_max },
{ "smtp_accept_max_nonmail", opt_int, &smtp_accept_max_nonmail },
#endif
{ "timeout_frozen_after", opt_time, &timeout_frozen_after },
{ "timezone", opt_stringptr, &timezone_string },
-#ifdef SUPPORT_TLS
{ "tls_advertise_hosts", opt_stringptr, &tls_advertise_hosts },
+#ifdef SUPPORT_TLS
{ "tls_certificate", opt_stringptr, &tls_certificate },
{ "tls_crl", opt_stringptr, &tls_crl },
{ "tls_dh_max_bits", opt_int, &tls_dh_max_bits },
{ "tls_dhparam", opt_stringptr, &tls_dhparam },
+ { "tls_eccurve", opt_stringptr, &tls_eccurve },
# ifndef DISABLE_OCSP
{ "tls_ocsp_file", opt_stringptr, &tls_ocsp_file },
# endif
config_filename = config_file_stack->filename;
config_lineno = config_file_stack->lineno;
config_file_stack = config_file_stack->next;
+ if (config_lines)
+ save_config_position(config_filename, config_lineno);
continue;
}
config_lineno++;
newlen = len + Ustrlen(big_buffer + len);
+ if (config_lines && config_lineno == 1)
+ save_config_position(config_filename, config_lineno);
+
/* Handle pathologically long physical lines - yes, it did happen - by
extending big_buffer at this point. The code also copes with very long
logical lines. */
if (include_if_exists != 0 && (Ustat(ss, &statbuf) != 0)) continue;
+ if (config_lines)
+ save_config_position(config_filename, config_lineno);
save = store_get(sizeof(config_file_item));
save->next = config_file_stack;
config_file_stack = save;
section names do fit. Leave space for pluralizing. */
s = big_buffer + startoffset; /* First non-space character */
+
+if (config_lines)
+ save_config_line(s);
+
if (strncmpic(s, US"begin ", 6) == 0)
{
s += 6;
if (!admin_user && (ol->type & opt_secure) != 0)
{
- const char * const hidden = "<value not displayable>";
if (no_labels)
printf("%s\n", hidden);
else
second argument is NULL. There are some special values:
all print all main configuration options
- configure_file print the name of the configuration file
+ config_file print the name of the configuration file
+ (configure_file will still work, for backward
+ compatibility)
routers print the routers' configurations
transports print the transports' configuration
authenticators print the authenticators' configuration
macro_list print a list of macro names
+name print a named list item
local_scan print the local_scan options
+ config print the configuration as it is parsed
If the second argument is not NULL, it must be one of "router", "transport",
"authenticator" or "macro" in which case the first argument identifies the
return;
}
- if (Ustrcmp(name, "configure_file") == 0)
+ if ( Ustrcmp(name, "configure_file") == 0
+ ||Ustrcmp(name, "config_file") == 0)
{
printf("%s\n", CS config_main_filename);
return;
return;
}
+ if (Ustrcmp(name, "config") == 0)
+ {
+ print_config(admin_user);
+ return;
+ }
+
if (Ustrcmp(name, "routers") == 0)
{
type = US"router";
int rc, status;
void (*oldsignal)(int);
+/* If TLS will never be used, no point checking ciphers */
+
+if ( !tls_advertise_hosts
+ || !*tls_advertise_hosts
+ || Ustrcmp(tls_advertise_hosts, ":") == 0
+ )
+ return TRUE;
+else if (!tls_certificate)
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "Warning: No server certificate defined; TLS connections will fail.\n"
+ " Suggested action: either install a certificate or change tls_advertise_hosts option");
+
oldsignal = signal(SIGCHLD, SIG_DFL);
fflush(NULL);
config_filename = config_main_filename = string_copy(filename);
p = Ustrrchr(filename, '/');
- config_main_directory = p ? string_copyn(filename, p - filename)
+ config_main_directory = p ? string_copyn(filename, p - filename)
: string_copy(US".");
}
else
(void)fclose(config_file);
}
+/* Init the storage for the pre-parsed config lines */
+void
+readconf_save_config(const uschar *s)
+{
+ save_config_line(string_sprintf("# Exim Configuration (%s)",
+ running_in_test_harness ? US"X" : s));
+}
+
+static void
+save_config_position(const uschar *file, int line)
+{
+ save_config_line(string_sprintf("# %d \"%s\"", line, file));
+}
+
+/* Append a pre-parsed logical line to the config lines store,
+this operates on a global (static) list that holds all the pre-parsed
+config lines, we do no further processing here, output formatting and
+honouring of <hide> or macros will be done during output */
+static void
+save_config_line(const uschar* line)
+{
+static config_line_item *current;
+config_line_item *next;
+
+next = (config_line_item*) store_get(sizeof(config_line_item));
+next->line = string_copy(line);
+next->next = NULL;
+
+if (!config_lines) config_lines = next;
+else current->next = next;
+
+current = next;
+}
+
+/* List the parsed config lines, care about nice formatting and
+hide the <hide> values unless we're the admin user */
+void
+print_config(BOOL admin)
+{
+config_line_item *i;
+const int TS = 2;
+int indent = 0;
+
+for (i = config_lines; i; i = i->next)
+ {
+ const uschar *current;
+ uschar *p;
+
+ /* skip over to the first non-space */
+ for (current = i->line; *current && isspace(*current); ++current)
+ ;
+
+ if (*current == '\0')
+ continue;
+
+ /* TODO: Collapse or insert spaces around the first '=' */
+
+ /* # lines */
+ if (current[0] == '#')
+ {
+ puts(current);
+ continue;
+ }
+
+ /* begin lines are left aligned */
+ if (strncmp(current, "begin", 5) == 0 && isspace(current[5]))
+ {
+ puts(current);
+ indent = TS;
+ continue;
+ }
+
+ /* router/acl/transport block names */
+ if (current[strlen(current)-1] == ':' && !strchr(current, '='))
+ {
+ printf("%*s%s\n", TS, "", current);
+ indent = 2 * TS;
+ continue;
+ }
+
+ /* hidden lines (MACROS or prefixed with hide) */
+ if (!admin && (isupper(*current)
+ || (strncmp(current, "hide", 4) == 0 && isspace(current[4]))))
+ {
+ if (p = strchr(current, '='))
+ {
+ *p = '\0';
+ printf("%*s%s = %s\n", indent, "", current, hidden);
+ }
+ /* e.g.: hide split_spool_directory */
+ else printf("%*s\n", indent, hidden);
+ continue;
+ }
+
+ /* rest is public */
+ printf("%*s%s\n", indent, "", current);
+ continue;
+ }
+}
+
/* vi: aw ai sw=2
*/
/* End of readconf.c */