DANE: move to mainline
[exim.git] / src / src / exim.c
index 7dd08453419d84f31aac4cdb6432c6d34af69c15..f95c107478041761fa5dc3fe4a8b9700dc6fb8f3 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2017 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -743,26 +743,26 @@ else
 *          Show supported features               *
 *************************************************/
 
-/* This function is called for -bV/--version and for -d to output the optional
-features of the current Exim binary.
-
-Arguments:  a FILE for printing
-Returns:    nothing
-*/
-
 static void
-show_whats_supported(FILE *f)
+show_db_version(FILE * f)
 {
-  auth_info *authi;
-
 #ifdef DB_VERSION_STRING
-fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING);
+DEBUG(D_any)
+  {
+  fprintf(f, "Library version: BDB: Compile: %s\n", DB_VERSION_STRING);
+  fprintf(f, "                      Runtime: %s\n",
+    db_version(NULL, NULL, NULL));
+  }
+else
+  fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING);
+
 #elif defined(BTREEVERSION) && defined(HASHVERSION)
   #ifdef USE_DB
   fprintf(f, "Probably Berkeley DB version 1.8x (native mode)\n");
   #else
   fprintf(f, "Probably Berkeley DB version 1.8x (compatibility mode)\n");
   #endif
+
 #elif defined(_DBM_RDONLY) || defined(dbm_dirfno)
 fprintf(f, "Probably ndbm\n");
 #elif defined(USE_TDB)
@@ -774,6 +774,22 @@ fprintf(f, "Using tdb\n");
   fprintf(f, "Probably GDBM (compatibility mode)\n");
   #endif
 #endif
+}
+
+
+/* This function is called for -bV/--version and for -d to output the optional
+features of the current Exim binary.
+
+Arguments:  a FILE for printing
+Returns:    nothing
+*/
+
+static void
+show_whats_supported(FILE * f)
+{
+auth_info * authi;
+
+DEBUG(D_any) {} else show_db_version(f);
 
 fprintf(f, "Support for:");
 #ifdef SUPPORT_CRYPTEQ
@@ -801,11 +817,11 @@ fprintf(f, "Support for:");
   fprintf(f, " TCPwrappers");
 #endif
 #ifdef SUPPORT_TLS
-  #ifdef USE_GNUTLS
+ifdef USE_GNUTLS
   fprintf(f, " GnuTLS");
-  #else
+else
   fprintf(f, " OpenSSL");
-  #endif
+endif
 #endif
 #ifdef SUPPORT_TRANSLATE_IP_ADDRESS
   fprintf(f, " translate_ip_address");
@@ -816,6 +832,9 @@ fprintf(f, "Support for:");
 #ifdef WITH_CONTENT_SCAN
   fprintf(f, " Content_Scanning");
 #endif
+#ifdef SUPPORT_DANE
+  fprintf(f, " DANE");
+#endif
 #ifndef DISABLE_DKIM
   fprintf(f, " DKIM");
 #endif
@@ -840,6 +859,9 @@ fprintf(f, "Support for:");
 #ifdef SUPPORT_SOCKS
   fprintf(f, " SOCKS");
 #endif
+#ifdef SUPPORT_SPF
+  fprintf(f, " SPF");
+#endif
 #ifdef TCP_FASTOPEN
   deliver_init();
   if (tcp_fastopen_ok) fprintf(f, " TCP_Fast_Open");
@@ -850,18 +872,12 @@ fprintf(f, "Support for:");
 #ifdef EXPERIMENTAL_QUEUEFILE
   fprintf(f, " Experimental_QUEUEFILE");
 #endif
-#ifdef EXPERIMENTAL_SPF
-  fprintf(f, " Experimental_SPF");
-#endif
 #ifdef EXPERIMENTAL_SRS
   fprintf(f, " Experimental_SRS");
 #endif
 #ifdef EXPERIMENTAL_BRIGHTMAIL
   fprintf(f, " Experimental_Brightmail");
 #endif
-#ifdef EXPERIMENTAL_DANE
-  fprintf(f, " Experimental_DANE");
-#endif
 #ifdef EXPERIMENTAL_DCC
   fprintf(f, " Experimental_DCC");
 #endif
@@ -930,86 +946,13 @@ fprintf(f, "Lookups (built-in):");
 #endif
 fprintf(f, "\n");
 
-fprintf(f, "Authenticators:");
-#ifdef AUTH_CRAM_MD5
-  fprintf(f, " cram_md5");
-#endif
-#ifdef AUTH_CYRUS_SASL
-  fprintf(f, " cyrus_sasl");
-#endif
-#ifdef AUTH_DOVECOT
-  fprintf(f, " dovecot");
-#endif
-#ifdef AUTH_GSASL
-  fprintf(f, " gsasl");
-#endif
-#ifdef AUTH_HEIMDAL_GSSAPI
-  fprintf(f, " heimdal_gssapi");
-#endif
-#ifdef AUTH_PLAINTEXT
-  fprintf(f, " plaintext");
-#endif
-#ifdef AUTH_SPA
-  fprintf(f, " spa");
-#endif
-#ifdef AUTH_TLS
-  fprintf(f, " tls");
-#endif
-fprintf(f, "\n");
+auth_show_supported(f);
+route_show_supported(f);
+transport_show_supported(f);
 
-fprintf(f, "Routers:");
-#ifdef ROUTER_ACCEPT
-  fprintf(f, " accept");
-#endif
-#ifdef ROUTER_DNSLOOKUP
-  fprintf(f, " dnslookup");
-#endif
-#ifdef ROUTER_IPLITERAL
-  fprintf(f, " ipliteral");
-#endif
-#ifdef ROUTER_IPLOOKUP
-  fprintf(f, " iplookup");
-#endif
-#ifdef ROUTER_MANUALROUTE
-  fprintf(f, " manualroute");
-#endif
-#ifdef ROUTER_QUERYPROGRAM
-  fprintf(f, " queryprogram");
-#endif
-#ifdef ROUTER_REDIRECT
-  fprintf(f, " redirect");
-#endif
-fprintf(f, "\n");
-
-fprintf(f, "Transports:");
-#ifdef TRANSPORT_APPENDFILE
-  fprintf(f, " appendfile");
-  #ifdef SUPPORT_MAILDIR
-    fprintf(f, "/maildir");
-  #endif
-  #ifdef SUPPORT_MAILSTORE
-    fprintf(f, "/mailstore");
-  #endif
-  #ifdef SUPPORT_MBX
-    fprintf(f, "/mbx");
-  #endif
-#endif
-#ifdef TRANSPORT_AUTOREPLY
-  fprintf(f, " autoreply");
-#endif
-#ifdef TRANSPORT_LMTP
-  fprintf(f, " lmtp");
-#endif
-#ifdef TRANSPORT_PIPE
-  fprintf(f, " pipe");
-#endif
-#ifdef EXPERIMENTAL_QUEUEFILE
-  fprintf(f, " queuefile");
-#endif
-#ifdef TRANSPORT_SMTP
-  fprintf(f, " smtp");
+#ifdef WITH_CONTENT_SCAN
+malware_show_supported(f);
 #endif
-fprintf(f, "\n");
 
 if (fixed_never_users[0] > 0)
   {
@@ -1053,6 +996,8 @@ DEBUG(D_any) do {
                gnu_get_libc_version());
 #endif
 
+show_db_version(f);
+
 #ifdef SUPPORT_TLS
   tls_version_report(f);
 #endif
@@ -1120,8 +1065,8 @@ switch(request)
 "If the string is not recognised, you'll get this help (on stderr).\n"
 "\n"
 "  exim -bI:help    this information\n"
-"  exim -bI:dscp    dscp value keywords known\n"
-"  exim -bI:sieve   list of supported sieve extensions, one per line.\n"
+"  exim -bI:dscp    list of known dscp value keywords\n"
+"  exim -bI:sieve   list of supported sieve extensions\n"
 );
     return;
   case CMDINFO_SIEVE:
@@ -1427,7 +1372,7 @@ whites[i] = NULL;
 
 /* The list of commandline macros should be very short.
 Accept the N*M complexity. */
-for (m = macros; m; m = m->next) if (m->command_line)
+for (m = macros_user; m; m = m->next) if (m->command_line)
   {
   found = FALSE;
   for (w = whites; *w; ++w)
@@ -1457,6 +1402,39 @@ return TRUE;
 }
 
 
+/*************************************************
+*          Expansion testing                    *
+*************************************************/
+
+/* Expand and print one item, doing macro-processing.
+
+Arguments:
+  item         line for expansion
+*/
+
+static void
+expansion_test_line(uschar * line)
+{
+int len;
+BOOL dummy_macexp;
+
+Ustrncpy(big_buffer, line, big_buffer_size);
+big_buffer[big_buffer_size-1] = '\0';
+len = Ustrlen(big_buffer);
+
+(void) macros_expand(0, &len, &dummy_macexp);
+
+if (isupper(big_buffer[0]))
+  {
+  if (macro_read_assignment(big_buffer))
+    printf("Defined macro '%s'\n", mlast->name);
+  }
+else
+  if ((line = expand_string(big_buffer))) printf("%s\n", CS line);
+  else printf("Failed: %s\n", expand_string_message);
+}
+
+
 /*************************************************
 *          Entry point and high-level code       *
 *************************************************/
@@ -2444,14 +2422,14 @@ for (i = 1; i < argc; i++)
         while (isspace(*s)) s++;
         }
 
-      for (m = macros; m; m = m->next)
+      for (m = macros_user; m; m = m->next)
         if (Ustrcmp(m->name, name) == 0)
           {
           fprintf(stderr, "exim: duplicated -D in command line\n");
           exit(EXIT_FAILURE);
           }
 
-      m = macro_create(string_copy(name), string_copy(s), TRUE);
+      m = macro_create(name, s, TRUE);
 
       if (clmacro_count >= MAX_CLMACROS)
         {
@@ -3815,9 +3793,6 @@ defined) */
 
 readconf_main(checking || list_options);
 
-if (builtin_macros_create_trigger) DEBUG(D_any)
-  debug_printf("Builtin macros created (expensive) due to config line '%.*s'\n",
-    Ustrlen(builtin_macros_create_trigger)-1, builtin_macros_create_trigger);
 
 /* Now in directory "/" */
 
@@ -4593,30 +4568,33 @@ if (test_retry_arg >= 0)
 
 if (list_options)
   {
+  BOOL fail = FALSE;
   set_process_info("listing variables");
-  if (recipients_arg >= argc) readconf_print(US"all", NULL, flag_n);
-    else for (i = recipients_arg; i < argc; i++)
+  if (recipients_arg >= argc)
+    fail = !readconf_print(US"all", NULL, flag_n);
+  else for (i = recipients_arg; i < argc; i++)
+    {
+    if (i < argc - 1 &&
+       (Ustrcmp(argv[i], "router") == 0 ||
+        Ustrcmp(argv[i], "transport") == 0 ||
+        Ustrcmp(argv[i], "authenticator") == 0 ||
+        Ustrcmp(argv[i], "macro") == 0 ||
+        Ustrcmp(argv[i], "environment") == 0))
       {
-      if (i < argc - 1 &&
-          (Ustrcmp(argv[i], "router") == 0 ||
-           Ustrcmp(argv[i], "transport") == 0 ||
-           Ustrcmp(argv[i], "authenticator") == 0 ||
-           Ustrcmp(argv[i], "macro") == 0 ||
-           Ustrcmp(argv[i], "environment") == 0))
-        {
-        readconf_print(argv[i+1], argv[i], flag_n);
-        i++;
-        }
-      else readconf_print(argv[i], NULL, flag_n);
+      fail |= !readconf_print(argv[i+1], argv[i], flag_n);
+      i++;
       }
-  exim_exit(EXIT_SUCCESS, US"main");
+    else
+      fail = !readconf_print(argv[i], NULL, flag_n);
+    }
+  exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS, US"main");
   }
 
 if (list_config)
   {
   set_process_info("listing config");
-  readconf_print(US"config", NULL, flag_n);
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(readconf_print(US"config", NULL, flag_n)
+               ? EXIT_SUCCESS : EXIT_FAILURE, US"main");
   }
 
 
@@ -4988,7 +4966,7 @@ if (expansion_test)
   /* Read a test message from a file. We fudge it up to be on stdin, saving
   stdin itself for later reading of expansion strings. */
 
-  else if (expansion_test_message != NULL)
+  else if (expansion_test_message)
     {
     int save_stdin = dup(0);
     int fd = Uopen(expansion_test_message, O_RDONLY, 0);
@@ -5008,6 +4986,10 @@ if (expansion_test)
     clearerr(stdin);               /* Required by Darwin */
     }
 
+  /* Only admin users may see config-file macros this way */
+
+  if (!admin_user) macros_user = macros = mlast = NULL;
+
   /* Allow $recipients for this testing */
 
   enable_dollar_recipients = TRUE;
@@ -5015,15 +4997,8 @@ if (expansion_test)
   /* Expand command line items */
 
   if (recipients_arg < argc)
-    {
     while (recipients_arg < argc)
-      {
-      uschar *s = argv[recipients_arg++];
-      uschar *ss = expand_string(s);
-      if (ss == NULL) printf ("Failed: %s\n", expand_string_message);
-      else printf("%s\n", CS ss);
-      }
-    }
+      expansion_test_line(argv[recipients_arg++]);
 
   /* Read stdin */
 
@@ -5031,25 +5006,18 @@ if (expansion_test)
     {
     char *(*fn_readline)(const char *) = NULL;
     void (*fn_addhist)(const char *) = NULL;
+    uschar * s;
 
-    #ifdef USE_READLINE
+#ifdef USE_READLINE
     void *dlhandle = set_readline(&fn_readline, &fn_addhist);
-    #endif
+#endif
 
-    for (;;)
-      {
-      uschar *ss;
-      uschar *source = get_stdinput(fn_readline, fn_addhist);
-      if (source == NULL) break;
-      ss = expand_string(source);
-      if (ss == NULL)
-        printf ("Failed: %s\n", expand_string_message);
-      else printf("%s\n", CS ss);
-      }
+    while (s = get_stdinput(fn_readline, fn_addhist))
+      expansion_test_line(s);
 
-    #ifdef USE_READLINE
-    if (dlhandle != NULL) dlclose(dlhandle);
-    #endif
+#ifdef USE_READLINE
+    if (dlhandle) dlclose(dlhandle);
+#endif
     }
 
   /* The data file will be open after -Mset */
@@ -5060,7 +5028,7 @@ if (expansion_test)
     deliver_datafile = -1;
     }
 
-  exim_exit(EXIT_SUCCESS, US"main");
+  exim_exit(EXIT_SUCCESS, US"main: expansion test");
   }