Make BOOL unsigned; fix resulting latent bugs
[exim.git] / src / src / readconf.c
index e52f45fcaa268b3c6abcdc78533f0355e2229d02..fb9d47a099f33f16126105e9a1286698468f2071 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for reading the configuration file, and for displaying
@@ -11,10 +11,13 @@ implementation of the conditional .ifdef etc. */
 
 #include "exim.h"
 
+extern char **environ;
+
 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);
+static void print_config(BOOL admin, BOOL terse);
+
 
 #define CSTATE_STACK_SIZE 10
 
@@ -178,6 +181,7 @@ static optionlist optionlist_config[] = {
   { "acl_smtp_starttls",        opt_stringptr,   &acl_smtp_starttls },
 #endif
   { "acl_smtp_vrfy",            opt_stringptr,   &acl_smtp_vrfy },
+  { "add_environment",          opt_stringptr,   &add_environment },
   { "admin_groups",             opt_gidlist,     &admin_groups },
   { "allow_domain_literals",    opt_bool,        &allow_domain_literals },
   { "allow_mx_to_ip",           opt_bool,        &allow_mx_to_ip },
@@ -194,6 +198,7 @@ static optionlist optionlist_config[] = {
   { "bounce_message_file",      opt_stringptr,   &bounce_message_file },
   { "bounce_message_text",      opt_stringptr,   &bounce_message_text },
   { "bounce_return_body",       opt_bool,        &bounce_return_body },
+  { "bounce_return_linesize_limit", opt_mkint,   &bounce_return_linesize_limit },
   { "bounce_return_message",    opt_bool,        &bounce_return_message },
   { "bounce_return_size_limit", opt_mkint,       &bounce_return_size_limit },
   { "bounce_sender_authentication",opt_stringptr,&bounce_sender_authentication },
@@ -207,6 +212,7 @@ static optionlist optionlist_config[] = {
   { "check_rfc2047_length",     opt_bool,        &check_rfc2047_length },
   { "check_spool_inodes",       opt_int,         &check_spool_inodes },
   { "check_spool_space",        opt_Kint,        &check_spool_space },
+  { "chunking_advertise_hosts", opt_stringptr,  &chunking_advertise_hosts },
   { "daemon_smtp_port",         opt_stringptr|opt_hidden, &daemon_smtp_port },
   { "daemon_smtp_ports",        opt_stringptr,   &daemon_smtp_port },
   { "daemon_startup_retries",   opt_int,         &daemon_startup_retries },
@@ -266,11 +272,6 @@ static optionlist optionlist_config[] = {
 #ifdef SUPPORT_TLS
   { "gnutls_allow_auto_pkcs11", opt_bool,        &gnutls_allow_auto_pkcs11 },
   { "gnutls_compat_mode",       opt_bool,        &gnutls_compat_mode },
-  /* These three gnutls_require_* options stopped working in Exim 4.80 */
-  /* From 4.83 we log a warning; a future relase will remove them */
-  { "gnutls_require_kx",        opt_stringptr,   &gnutls_require_kx },
-  { "gnutls_require_mac",       opt_stringptr,   &gnutls_require_mac },
-  { "gnutls_require_protocols", opt_stringptr,   &gnutls_require_proto },
 #endif
   { "header_line_maxsize",      opt_int,         &header_line_maxsize },
   { "header_maxsize",           opt_int,         &header_maxsize },
@@ -295,6 +296,7 @@ static optionlist optionlist_config[] = {
   { "ignore_bounce_errors_after", opt_time,      &ignore_bounce_errors_after },
   { "ignore_fromline_hosts",    opt_stringptr,   &ignore_fromline_hosts },
   { "ignore_fromline_local",    opt_bool,        &ignore_fromline_local },
+  { "keep_environment",         opt_stringptr,   &keep_environment },
   { "keep_malformed",           opt_time,        &keep_malformed },
 #ifdef LOOKUP_LDAP
   { "ldap_ca_cert_dir",         opt_stringptr,   &eldap_ca_cert_dir },
@@ -343,6 +345,7 @@ static optionlist optionlist_config[] = {
 #ifdef EXIM_PERL
   { "perl_at_start",            opt_bool,        &opt_perl_at_start },
   { "perl_startup",             opt_stringptr,   &opt_perl_startup },
+  { "perl_taintmode",           opt_bool,        &opt_perl_taintmode },
 #endif
 #ifdef LOOKUP_PGSQL
   { "pgsql_servers",            opt_stringptr,   &pgsql_servers },
@@ -367,7 +370,7 @@ static optionlist optionlist_config[] = {
   { "queue_only_load_latch",    opt_bool,        &queue_only_load_latch },
   { "queue_only_override",      opt_bool,        &queue_only_override },
   { "queue_run_in_order",       opt_bool,        &queue_run_in_order },
-  { "queue_run_max",            opt_int,         &queue_run_max },
+  { "queue_run_max",            opt_stringptr,   &queue_run_max },
   { "queue_smtp_domains",       opt_stringptr,   &queue_smtp_domains },
   { "receive_timeout",          opt_time,        &receive_timeout },
   { "received_header_text",     opt_stringptr,   &received_header_text },
@@ -929,10 +932,10 @@ for (;;)
     save->filename = config_filename;
     save->lineno = config_lineno;
 
-    config_file = Ufopen(ss, "rb");
-    if (config_file == NULL)
+    if (!(config_file = Ufopen(ss, "rb")))
       log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "failed to open included "
         "configuration file %s", ss);
+
     config_filename = string_copy(ss);
     config_lineno = 0;
     continue;
@@ -1982,7 +1985,7 @@ switch (type)
   inttype = US"octal ";
 
   /*  Integer: a simple(ish) case; allow octal and hex formats, and
-  suffixes K and M. The different types affect output, not input. */
+  suffixes K, M and G. The different types affect output, not input. */
 
   case opt_mkint:
   case opt_int:
@@ -1998,7 +2001,6 @@ switch (type)
         inttype, name);
 
     if (errno != ERANGE)
-      {
       if (tolower(*endptr) == 'k')
         {
         if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024) errno = ERANGE;
@@ -2012,7 +2014,13 @@ switch (type)
         else lvalue *= 1024*1024;
         endptr++;
         }
-      }
+      else if (tolower(*endptr) == 'g')
+        {
+        if (lvalue > INT_MAX/(1024*1024*1024) || lvalue < INT_MIN/(1024*1024*1024))
+          errno = ERANGE;
+        else lvalue *= 1024*1024*1024;
+        endptr++;
+        }
 
     if (errno == ERANGE || lvalue > INT_MAX || lvalue < INT_MIN)
       log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
@@ -2031,8 +2039,9 @@ switch (type)
     *((int *)((uschar *)data_block + (long int)(ol->value))) = value;
   break;
 
-  /*  Integer held in K: again, allow octal and hex formats, and suffixes K and
-  M. */
+  /*  Integer held in K: again, allow octal and hex formats, and suffixes K, M
+  and G. */
+  /*XXX consider moving to int_eximarith_t (but mind the overflow test 0415) */
 
   case opt_Kint:
     {
@@ -2045,22 +2054,26 @@ switch (type)
         inttype, name);
 
     if (errno != ERANGE)
-      {
-      if (tolower(*endptr) == 'm')
+      if (tolower(*endptr) == 'g')
         {
-        if (value > INT_MAX/1024 || value < INT_MIN/1024) errno = ERANGE;
-          else value *= 1024;
+        if (value > INT_MAX/(1024*1024) || value < INT_MIN/(1024*1024))
+         errno = ERANGE;
+       else
+         value *= 1024*1024;
         endptr++;
         }
-      else if (tolower(*endptr) == 'k')
+      else if (tolower(*endptr) == 'm')
         {
+        if (value > INT_MAX/1024 || value < INT_MIN/1024)
+         errno = ERANGE;
+       else
+         value *= 1024;
         endptr++;
         }
+      else if (tolower(*endptr) == 'k')
+        endptr++;
       else
-        {
         value = (value + 512)/1024;
-        }
-      }
 
     if (errno == ERANGE) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
       "absolute value of integer \"%s\" is too large (overflow)", s);
@@ -2548,6 +2561,7 @@ second argument is NULL. There are some special values:
   +name              print a named list item
   local_scan         print the local_scan options
   config             print the configuration as it is parsed
+  environment        print the used execution environment
 
 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
@@ -2641,7 +2655,7 @@ if (type == NULL)
 
   if (Ustrcmp(name, "config") == 0)
     {
-    print_config(admin_user);
+    print_config(admin_user, no_labels);
     return;
     }
 
@@ -2696,6 +2710,24 @@ if (type == NULL)
     names_only = TRUE;
     }
 
+  else if (Ustrcmp(name, "environment") == 0)
+    {
+    if (environ)
+      {
+      uschar ** p;
+      for (p = USS environ; *p; p++) ;
+      qsort(environ, p - USS environ, sizeof(*p), string_compare_by_pointer);
+
+      for (p = USS environ; *p; p++)
+        {
+       uschar * q;
+        if (no_labels && (q = Ustrchr(*p, '='))) *q  = '\0';
+        puts(CS *p);
+        }
+      }
+    return;
+    }
+
   else
     {
     print_ol(find_option(name, optionlist_config, optionlist_config_size),
@@ -2921,7 +2953,7 @@ Returns:  bool for "okay"; false will cause caller to immediately exit.
 
 #ifdef SUPPORT_TLS
 static BOOL
-tls_dropprivs_validate_require_cipher(void)
+tls_dropprivs_validate_require_cipher(BOOL nowarn)
 {
 const uschar *errmsg;
 pid_t pid;
@@ -2935,9 +2967,9 @@ if (  !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"
+else if (!nowarn && !tls_certificate)
+  log_write(0, LOG_MAIN,
+    "Warning: No server certificate defined; will use a selfsigned one.\n"
     " Suggested action: either install a certificate or change tls_advertise_hosts option");
 
 oldsignal = signal(SIGCHLD, SIG_DFL);
@@ -2980,6 +3012,234 @@ return status == 0;
 
 
 
+/*************************************************/
+/* Create compile-time feature macros */
+static void
+readconf_features(void)
+{
+/* Probably we could work out a static initialiser for wherever
+macros are stored, but this will do for now. Some names are awkward
+due to conflicts with other common macros. */
+
+#ifdef SUPPORT_CRYPTEQ
+  read_macro_assignment("_HAVE_CRYPTEQ=y");
+#endif
+#if HAVE_ICONV
+  read_macro_assignment("_HAVE_ICONV=y");
+#endif
+#if HAVE_IPV6
+  read_macro_assignment("_HAVE_IPV6=y");
+#endif
+#ifdef HAVE_SETCLASSRESOURCES
+  read_macro_assignment("_HAVE_SETCLASSRESOURCES=y");
+#endif
+#ifdef SUPPORT_PAM
+  read_macro_assignment("_HAVE_PAM=y");
+#endif
+#ifdef EXIM_PERL
+  read_macro_assignment("_HAVE_PERL=y");
+#endif
+#ifdef EXPAND_DLFUNC
+  read_macro_assignment("_HAVE_DLFUNC=y");
+#endif
+#ifdef USE_TCP_WRAPPERS
+  read_macro_assignment("_HAVE_TCPWRAPPERS=y");
+#endif
+#ifdef SUPPORT_TLS
+  read_macro_assignment("_HAVE_TLS=y");
+# ifdef USE_GNUTLS
+  read_macro_assignment("_HAVE_GNUTLS=y");
+# else
+  read_macro_assignment("_HAVE_OPENSSL=y");
+# endif
+#endif
+#ifdef SUPPORT_TRANSLATE_IP_ADDRESS
+  read_macro_assignment("_HAVE_TRANSLATE_IP_ADDRESS=y");
+#endif
+#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
+  read_macro_assignment("_HAVE_MOVE_FROZEN_MESSAGES=y");
+#endif
+#ifdef WITH_CONTENT_SCAN
+  read_macro_assignment("_HAVE_CONTENT_SCANNING=y");
+#endif
+#ifndef DISABLE_DKIM
+  read_macro_assignment("_HAVE_DKIM=y");
+#endif
+#ifndef DISABLE_DNSSEC
+  read_macro_assignment("_HAVE_DNSSEC=y");
+#endif
+#ifndef DISABLE_EVENT
+  read_macro_assignment("_HAVE_Event=y");
+#endif
+#ifdef SUPPORT_I18N
+  read_macro_assignment("_HAVE_I18N=y");
+#endif
+#ifndef DISABLE_OCSP
+  read_macro_assignment("_HAVE_OCSP=y");
+#endif
+#ifndef DISABLE_PRDR
+  read_macro_assignment("_HAVE_PRDR=y");
+#endif
+#ifdef SUPPORT_PROXY
+  read_macro_assignment("_HAVE_PROXY=y");
+#endif
+#ifdef SUPPORT_SOCKS
+  read_macro_assignment("_HAVE_SOCKS=y");
+#endif
+#ifdef EXPERIMENTAL_LMDB
+  read_macro_assignment("_HAVE_LMDB=y");
+#endif
+#ifdef EXPERIMENTAL_SPF
+  read_macro_assignment("_HAVE_SPF=y");
+#endif
+#ifdef EXPERIMENTAL_SRS
+  read_macro_assignment("_HAVE_SRS=y");
+#endif
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+  read_macro_assignment("_HAVE_BRIGHTMAIL=y");
+#endif
+#ifdef EXPERIMENTAL_DANE
+  read_macro_assignment("_HAVE_DANE=y");
+#endif
+#ifdef EXPERIMENTAL_DCC
+  read_macro_assignment("_HAVE_DCC=y");
+#endif
+#ifdef EXPERIMENTAL_DMARC
+  read_macro_assignment("_HAVE_DMARC=y");
+#endif
+#ifdef EXPERIMENTAL_DSN_INFO
+  read_macro_assignment("_HAVE_DSN_INFO=y");
+#endif
+
+#ifdef LOOKUP_LSEARCH
+  read_macro_assignment("_HAVE_LKUP_LSEARCH=y");
+#endif
+#ifdef LOOKUP_CDB
+  read_macro_assignment("_HAVE_LKUP_CDB=y");
+#endif
+#ifdef LOOKUP_DBM
+  read_macro_assignment("_HAVE_LKUP_DBM=y");
+#endif
+#ifdef LOOKUP_DNSDB
+  read_macro_assignment("_HAVE_LKUP_DNSDB=y");
+#endif
+#ifdef LOOKUP_DSEARCH
+  read_macro_assignment("_HAVE_LKUP_DSEARCH=y");
+#endif
+#ifdef LOOKUP_IBASE
+  read_macro_assignment("_HAVE_LKUP_IBASE=y");
+#endif
+#ifdef LOOKUP_LDAP
+  read_macro_assignment("_HAVE_LKUP_LDAP=y");
+#endif
+#ifdef EXPERIMENTAL_LMDB
+  read_macro_assignment("_HAVE_LKUP_LMDB=y");
+#endif
+#ifdef LOOKUP_MYSQL
+  read_macro_assignment("_HAVE_LKUP_MYSQL=y");
+#endif
+#ifdef LOOKUP_NIS
+  read_macro_assignment("_HAVE_LKUP_NIS=y");
+#endif
+#ifdef LOOKUP_NISPLUS
+  read_macro_assignment("_HAVE_LKUP_NISPLUS=y");
+#endif
+#ifdef LOOKUP_ORACLE
+  read_macro_assignment("_HAVE_LKUP_ORACLE=y");
+#endif
+#ifdef LOOKUP_PASSWD
+  read_macro_assignment("_HAVE_LKUP_PASSWD=y");
+#endif
+#ifdef LOOKUP_PGSQL
+  read_macro_assignment("_HAVE_LKUP_PGSQL=y");
+#endif
+#ifdef LOOKUP_REDIS
+  read_macro_assignment("_HAVE_LKUP_REDIS=y");
+#endif
+#ifdef LOOKUP_SQLITE
+  read_macro_assignment("_HAVE_LKUP_SQLITE=y");
+#endif
+#ifdef LOOKUP_TESTDB
+  read_macro_assignment("_HAVE_LKUP_TESTDB=y");
+#endif
+#ifdef LOOKUP_WHOSON
+  read_macro_assignment("_HAVE_LKUP_WHOSON=y");
+#endif
+
+#ifdef AUTH_CRAM_MD5
+  read_macro_assignment("_HAVE_AUTH_CRAM_MD5=y");
+#endif
+#ifdef AUTH_CYRUS_SASL
+  read_macro_assignment("_HAVE_AUTH_CYRUS_SASL=y");
+#endif
+#ifdef AUTH_DOVECOT
+  read_macro_assignment("_HAVE_AUTH_DOVECOT=y");
+#endif
+#ifdef AUTH_GSASL
+  read_macro_assignment("_HAVE_AUTH_GSASL=y");
+#endif
+#ifdef AUTH_HEIMDAL_GSSAPI
+  read_macro_assignment("_HAVE_AUTH_HEIMDAL_GSSAPI=y");
+#endif
+#ifdef AUTH_PLAINTEXT
+  read_macro_assignment("_HAVE_AUTH_PLAINTEXT=y");
+#endif
+#ifdef AUTH_SPA
+  read_macro_assignment("_HAVE_AUTH_SPA=y");
+#endif
+#ifdef AUTH_TLS
+  read_macro_assignment("_HAVE_AUTH_TLS=y");
+#endif
+
+#ifdef ROUTER_ACCEPT
+  read_macro_assignment("_HAVE_RTR_ACCEPT=y");
+#endif
+#ifdef ROUTER_DNSLOOKUP
+  read_macro_assignment("_HAVE_RTR_DNSLOOKUP=y");
+#endif
+#ifdef ROUTER_IPLITERAL
+  read_macro_assignment("_HAVE_RTR_IPLITERAL=y");
+#endif
+#ifdef ROUTER_IPLOOKUP
+  read_macro_assignment("_HAVE_RTR_IPLOOKUP=y");
+#endif
+#ifdef ROUTER_MANUALROUTE
+  read_macro_assignment("_HAVE_RTR_MANUALROUTE=y");
+#endif
+#ifdef ROUTER_QUERYPROGRAM
+  read_macro_assignment("_HAVE_RTR_QUERYPROGRAM=y");
+#endif
+#ifdef ROUTER_REDIRECT
+  read_macro_assignment("_HAVE_RTR_REDRCT=y");
+#endif
+
+#ifdef TRANSPORT_APPENDFILE
+  read_macro_assignment("_HAVE_TPT_APPENDFILE=y");
+# ifdef SUPPORT_MAILDIR
+  read_macro_assignment("_HAVE_TPT_APPEND_MAILDR=y");
+# endif
+# ifdef SUPPORT_MAILSTORE
+  read_macro_assignment("_HAVE_TPT_APPEND_MAILSTORE=y");
+# endif
+# ifdef SUPPORT_MBX
+  read_macro_assignment("_HAVE_TPT_APPEND_MBX=y");
+# endif
+#endif
+#ifdef TRANSPORT_AUTOREPLY
+  read_macro_assignment("_HAVE_TPT_AUTOREPLY=y");
+#endif
+#ifdef TRANSPORT_LMTP
+  read_macro_assignment("_HAVE_TPT_LMTP=y");
+#endif
+#ifdef TRANSPORT_PIPE
+  read_macro_assignment("_HAVE_TPT_PIPE=y");
+#endif
+#ifdef TRANSPORT_SMTP
+  read_macro_assignment("_HAVE_TPT_SMTP=y");
+#endif
+}
+
+
 /*************************************************
 *         Read main configuration options        *
 *************************************************/
@@ -3009,18 +3269,22 @@ systems. Therefore they are available only when requested by compile-time
 options. */
 
 void
-readconf_main(void)
+readconf_main(BOOL nowarn)
 {
 int sep = 0;
 struct stat statbuf;
 uschar *s, *filename;
 const uschar *list = config_main_filelist;
 
+/* First create compile-time feature macros */
+readconf_features();
+
 /* Loop through the possible file names */
 
 while((filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
        != NULL)
   {
+
   /* Cut out all the fancy processing unless specifically wanted */
 
   #if defined(CONFIGURE_FILE_USE_NODE) || defined(CONFIGURE_FILE_USE_EUID)
@@ -3074,6 +3338,15 @@ while((filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
   if (config_file != NULL || errno != ENOENT) break;
   }
 
+/* Now, once we found and opened our configuration file, we change the directory
+to a safe place. Later we change to $spool_directory. */
+
+if (Uchdir("/") < 0)
+  {
+  perror("exim: chdir `/': ");
+  exit(EXIT_FAILURE);
+  }
+
 /* On success, save the name for verification; config_filename is used when
 logging configuration errors (it changes for .included files) whereas
 config_main_filename is the name shown by -bP. Failure to open a configuration
@@ -3437,7 +3710,7 @@ if ((tls_verify_hosts != NULL || tls_try_verify_hosts != NULL) &&
 
 /* This also checks that the library linkage is working and we can call
 routines in it, so call even if tls_require_ciphers is unset */
-if (!tls_dropprivs_validate_require_cipher())
+if (!tls_dropprivs_validate_require_cipher(nowarn))
   exit(1);
 
 /* Magic number: at time of writing, 1024 has been the long-standing value
@@ -3460,12 +3733,12 @@ if (openssl_options != NULL)
       "openssl_options parse error: %s", openssl_options);
 # endif
   }
-
-if (gnutls_require_kx || gnutls_require_mac || gnutls_require_proto)
-  log_write(0, LOG_MAIN, "WARNING: main options"
-      " gnutls_require_kx, gnutls_require_mac and gnutls_require_protocols"
-      " are obsolete\n");
 #endif /*SUPPORT_TLS*/
+
+if (!nowarn && !keep_environment && environ && *environ)
+  log_write(0, LOG_MAIN,
+      "Warning: purging the environment.\n"
+      " Suggested action: use keep_environment.");
 }
 
 
@@ -3578,9 +3851,9 @@ while ((buffer = get_config_line()) != NULL)
 
   if (isupper(*name) && *s == '=')
     {
-    if (d != NULL)
+    if (d)
       {
-      if (d->driver_name == NULL)
+      if (!d->driver_name)
         log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
           "no driver defined for %s \"%s\"", class, d->name);
       (d->info->init)(d);
@@ -3600,9 +3873,9 @@ while ((buffer = get_config_line()) != NULL)
 
     /* Finish off initializing the previous driver. */
 
-    if (d != NULL)
+    if (d)
       {
-      if (d->driver_name == NULL)
+      if (!d->driver_name)
         log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
           "no driver defined for %s \"%s\"", class, d->name);
       (d->info->init)(d);
@@ -3610,7 +3883,7 @@ while ((buffer = get_config_line()) != NULL)
 
     /* Check that we haven't already got a driver of this name */
 
-    for (d = *anchor; d != NULL; d = d->next)
+    for (d = *anchor; d; d = d->next)
       if (Ustrcmp(name, d->name) == 0)
         log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
           "there are two %ss called \"%s\"", class, name);
@@ -3621,7 +3894,7 @@ while ((buffer = get_config_line()) != NULL)
     d = store_get(instance_size);
     memcpy(d, instance_default, instance_size);
     *p = d;
-    p = &(d->next);
+    p = &d->next;
     d->name = string_copy(name);
 
     /* Clear out the "set" bits in the generic options */
@@ -3639,8 +3912,8 @@ while ((buffer = get_config_line()) != NULL)
   /* Not the start of a new driver. Give an error if we have not set up a
   current driver yet. */
 
-  if (d == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
-    "%s name missing", class);
+  if (!d)
+    log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%s name missing", class);
 
   /* First look to see if this is a generic option; if it is "driver",
   initialize the driver. If is it not a generic option, we can look for a
@@ -3649,7 +3922,7 @@ while ((buffer = get_config_line()) != NULL)
   if (readconf_handle_option(buffer, driver_optionlist,
         driver_optionlist_count, d, NULL))
     {
-    if (d->info == NULL && d->driver_name != NULL)
+    if (!d->info && d->driver_name)
       init_driver(d, drivers_available, size_of_info, class);
     }
 
@@ -3657,11 +3930,9 @@ while ((buffer = get_config_line()) != NULL)
   live therein. A flag with each option indicates if it is in the public
   block. */
 
-  else if (d->info != NULL)
-    {
+  else if (d->info)
     readconf_handle_option(buffer, d->info->options,
       *(d->info->options_count), d, US"option \"%s\" unknown");
-    }
 
   /* The option is not generic and the driver name has not yet been given. */
 
@@ -3671,9 +3942,9 @@ while ((buffer = get_config_line()) != NULL)
 
 /* Run the initialization function for the final driver. */
 
-if (d != NULL)
+if (d)
   {
-  if (d->driver_name == NULL)
+  if (!d->driver_name)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "no driver defined for %s \"%s\"", class, d->name);
   (d->info->init)(d);
@@ -4032,22 +4303,19 @@ readconf_driver_init(US"authenticator",
   optionlist_auths,                  /* generic options */
   optionlist_auths_size);
 
-for (au = auths; au != NULL; au = au->next)
+for (au = auths; au; au = au->next)
   {
-  if (au->public_name == NULL)
+  if (!au->public_name)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "no public name specified for "
       "the %s authenticator", au->name);
-  for (bu = au->next; bu != NULL; bu = bu->next)
-    {
+
+  for (bu = au->next; bu; bu = bu->next)
     if (strcmpic(au->public_name, bu->public_name) == 0)
-      {
       if ((au->client && bu->client) || (au->server && bu->server))
         log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "two %s authenticators "
           "(%s and %s) have the same public name (%s)",
-          (au->client)? US"client" : US"server", au->name, bu->name,
+          au->client ? US"client" : US"server", au->name, bu->name,
           au->public_name);
-      }
-    }
   }
 }
 
@@ -4267,10 +4535,10 @@ 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)
+print_config(BOOL admin, BOOL terse)
 {
 config_line_item *i;
-const int TS = 2;
+const int TS = terse ? 0 : 2;
 int indent = 0;
 
 for (i = config_lines; i; i = i->next)
@@ -4297,7 +4565,7 @@ for (i = config_lines; i; i = i->next)
       ;
 
     if (next - p > 1)
-      memmove(p+1, next, strlen(next)+1);
+      memmove(p+1, next, Ustrlen(next)+1);
 
     if (*next == '"' || *next == '\'' || *next == '$')
       break;
@@ -4310,7 +4578,7 @@ for (i = config_lines; i; i = i->next)
   /* begin lines are left aligned */
   else if (Ustrncmp(current, "begin", 5) == 0 && isspace(current[5]))
     {
-    puts("");
+    if (!terse) puts("");
     puts(CCS current);
     indent = TS;
     }
@@ -4318,7 +4586,8 @@ for (i = config_lines; i; i = i->next)
   /* router/acl/transport block names */
   else if (current[Ustrlen(current)-1] == ':' && !Ustrchr(current, '='))
     {
-    printf("\n%*s%s\n", TS, "", current);
+    if (!terse) puts("");
+    printf("%*s%s\n", TS, "", current);
     indent = 2 * TS;
     }