Logging: server pipelining offer but no uptake
[exim.git] / src / src / exim.c
index 354cdf7a807c41037e189d382579c407065c7ead..1410359bc821a71318765bbd0b72eed599a370d9 100644 (file)
@@ -187,7 +187,15 @@ DEBUG(D_process_info) debug_printf("set_process_info: %s", process_info);
 va_end(ap);
 }
 
+/***********************************************
+*            Handler for SIGTERM               *
+***********************************************/
 
+static void
+term_handler(int sig)
+{
+  exit(1);
+}
 
 
 /*************************************************
@@ -542,9 +550,9 @@ close_unwanted(void)
 {
 if (smtp_input)
   {
-  #ifdef SUPPORT_TLS
-  tls_close(TRUE, FALSE);      /* Shut down the TLS library */
-  #endif
+#ifdef SUPPORT_TLS
+  tls_close(NULL, TLS_NO_SHUTDOWN);      /* Shut down the TLS library */
+#endif
   (void)close(fileno(smtp_in));
   (void)close(fileno(smtp_out));
   smtp_in = NULL;
@@ -832,6 +840,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
@@ -872,12 +883,12 @@ fprintf(f, "Support for:");
 #ifdef EXPERIMENTAL_SRS
   fprintf(f, " Experimental_SRS");
 #endif
+#ifdef EXPERIMENTAL_ARC
+  fprintf(f, " Experimental_ARC");
+#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
@@ -887,6 +898,9 @@ fprintf(f, "Support for:");
 #ifdef EXPERIMENTAL_DSN_INFO
   fprintf(f, " Experimental_DSN_info");
 #endif
+#ifdef EXPERIMENTAL_REQUIRETLS
+  fprintf(f, " Experimental_REQUIRETLS");
+#endif
 fprintf(f, "\n");
 
 fprintf(f, "Lookups (built-in):");
@@ -1295,32 +1309,6 @@ exit(EXIT_FAILURE);
 *    Validate that the macros given are okay     *
 *************************************************/
 
-#ifdef WHITELIST_D_MACROS
-static void
-wlist_check(uschar * name, uschar * val, void * ctx)
-{
-uschar ** w, ** whites = ctx;
-unsigned len;
-int n;
-
-for (w = whites; *w; ++w)
-  if (Ustrcmp(*w, name) == 0) break;
-if (*w) 
-  {
-  if (!val || !*val) return;
-  len = Ustrlen(val);
-  if ((n = pcre_exec(regex_whitelisted_macro, NULL, CS val, len,
-                   0, PCRE_EOPT, NULL, 0)) >= 0)
-    return;
-  if (n != PCRE_ERROR_NOMATCH)
-    debug_printf("macros_trusted checking %s returned %d\n", name, n);
-  }
-*whites = NULL;
-return;
-}
-#endif
-
-
 /* Typically, Exim will drop privileges if macros are supplied.  In some
 cases, we want to not do so.
 
@@ -1333,7 +1321,7 @@ macros_trusted(BOOL opt_D_used)
 {
 #ifdef WHITELIST_D_MACROS
 macro_item *m;
-uschar *whitelisted, *end, *p, **whites;
+uschar *whitelisted, *end, *p, **whites, **w;
 int white_count, i, n;
 size_t len;
 BOOL prev_char_item, found;
@@ -1396,9 +1384,32 @@ for (p = whitelisted, i = 0; (p != end) && (i < white_count); ++p)
   }
 whites[i] = NULL;
 
-tree_walk(tree_macros, wlist_check, whites);
-if (!*whites) return FALSE;
-
+/* The list of commandline macros should be very short.
+Accept the N*M complexity. */
+for (m = macros_user; m; m = m->next) if (m->command_line)
+  {
+  found = FALSE;
+  for (w = whites; *w; ++w)
+    if (Ustrcmp(*w, m->name) == 0)
+      {
+      found = TRUE;
+      break;
+      }
+  if (!found)
+    return FALSE;
+  if (!m->replacement)
+    continue;
+  if ((len = m->replen) == 0)
+    continue;
+  n = pcre_exec(regex_whitelisted_macro, NULL, CS m->replacement, len,
+   0, PCRE_EOPT, NULL, 0);
+  if (n < 0)
+    {
+    if (n != PCRE_ERROR_NOMATCH)
+      debug_printf("macros_trusted checking %s returned %d\n", m->name, n);
+    return FALSE;
+    }
+  }
 DEBUG(D_any) debug_printf("macros_trusted overridden to true by whitelisting\n");
 return TRUE;
 #endif
@@ -1430,10 +1441,7 @@ len = Ustrlen(big_buffer);
 if (isupper(big_buffer[0]))
   {
   if (macro_read_assignment(big_buffer))
-    {
-    uschar * s = Ustrchr(big_buffer, '=');
-    printf("Defined macro '%.*s'\n", (int)(s - big_buffer), big_buffer);
-    }
+    printf("Defined macro '%s'\n", mlast->name);
   }
 else
   if ((line = expand_string(big_buffer))) printf("%s\n", CS line);
@@ -1627,6 +1635,8 @@ testing harness; do a fast initial check, and then the whole thing. */
 
 running_in_test_harness =
   *running_status == '<' && Ustrcmp(running_status, "<<<testing>>>") == 0;
+if (running_in_test_harness)
+  debug_store = TRUE;
 
 /* The C standard says that the equivalent of setlocale(LC_ALL, "C") is obeyed
 at the start of a program; however, it seems that some environments do not
@@ -1679,6 +1689,10 @@ descriptive text. */
 set_process_info("initializing");
 os_restarting_signal(SIGUSR1, usr1_handler);
 
+/* If running in a dockerized environment, the TERM signal is only
+delegated to the PID 1 if we request it by setting an signal handler */
+if (getpid() == 1) signal(SIGTERM, term_handler);
+
 /* SIGHUP is used to get the daemon to reconfigure. It gets set as appropriate
 in the daemon code. For the rest of Exim's uses, we ignore it. */
 
@@ -2428,11 +2442,12 @@ for (i = 1; i < argc; i++)
         while (isspace(*s)) s++;
         }
 
-      if (macro_search(name))
-        {
-        fprintf(stderr, "exim: duplicated -D in command line\n");
-        exit(EXIT_FAILURE);
-        }
+      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(name, s, TRUE);
 
@@ -2441,8 +2456,8 @@ for (i = 1; i < argc; i++)
         fprintf(stderr, "exim: too many -D options on command line\n");
         exit(EXIT_FAILURE);
         }
-      clmacros[clmacro_count++] = string_sprintf("-D%s=%s",
-       m->tnode.name, m->tnode.data.ptr);
+      clmacros[clmacro_count++] = string_sprintf("-D%s=%s", m->name,
+        m->replacement);
       }
     #endif
     break;
@@ -2771,9 +2786,19 @@ for (i = 1; i < argc; i++)
 
        default:  badarg = TRUE; break;
        }
-       break;
+      break;
       }
 
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+    /* -MS   set REQUIRETLS on (new) message */
+
+    else if (*argrest == 'S')
+      {
+      tls_requiretls |= REQUIRETLS_MSG;
+      break;
+      }
+#endif
+
     /* -M[x]: various operations on the following list of message ids:
        -M    deliver the messages, ignoring next retry times and thawing
        -Mc   deliver the messages, checking next retry times, no thawing
@@ -4071,16 +4096,24 @@ a debugging feature for finding out what arguments certain MUAs actually use.
 Don't attempt it if logging is disabled, or if listing variables or if
 verifying/testing addresses or expansions. */
 
-if (((debug_selector & D_any) != 0 || LOGGING(arguments))
-      && really_exim && !list_options && !checking)
+if (  (debug_selector & D_any  ||  LOGGING(arguments))
+   && really_exim && !list_options && !checking)
   {
   int i;
   uschar *p = big_buffer;
   Ustrcpy(p, "cwd= (failed)");
 
-  Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);
+  if (!initial_cwd)
+    p += 13;
+  else
+    {
+    Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);
+    p += 4 + Ustrlen(initial_cwd);
+    /* in case p is near the end and we don't provide enough space for
+     * string_format to be willing to write. */
+    *p = '\0';
+    }
 
-  while (*p) p++;
   (void)string_format(p, big_buffer_size - (p - big_buffer), " %d args:", argc);
   while (*p) p++;
   for (i = 0; i < argc; i++)
@@ -4993,7 +5026,7 @@ if (expansion_test)
 
   /* Only admin users may see config-file macros this way */
 
-  if (!admin_user) tree_macros = NULL;
+  if (!admin_user) macros_user = macros = mlast = NULL;
 
   /* Allow $recipients for this testing */
 
@@ -5140,6 +5173,8 @@ if (recipients_arg >= argc && !extract_recipients && !smtp_input)
   {
   if (version_printed)
     {
+    if (Ustrchr(config_main_filelist, ':'))
+      printf("Configuration file search path is %s\n", config_main_filelist);
     printf("Configuration file is %s\n", config_main_filename);
     return EXIT_SUCCESS;
     }
@@ -5213,7 +5248,7 @@ already been done (which it will have been for inetd). This caters for the
 case when it is forced by -oMa. However, we must flag that it isn't a socket,
 so that the test for IP options is skipped for -bs input. */
 
-if (sender_host_address != NULL && sender_fullhost == NULL)
+if (sender_host_address && !sender_fullhost)
   {
   host_build_sender_fullhost();
   set_process_info("handling incoming connection from %s via -oMa",