Callout/hold: fix uninitialized variable
[exim.git] / src / src / exim.c
index 1f450c533826a2c232f4b3ec360010bae143b1b4..3dfe5db94388170f20f819ac13f0c6da79dcaea9 100644 (file)
@@ -12,7 +12,7 @@ Also a few functions that don't naturally fit elsewhere. */
 
 #include "exim.h"
 
-#ifdef __GLIBC__
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 # include <gnu/libc-version.h>
 #endif
 
@@ -1044,7 +1044,7 @@ DEBUG(D_any) do {
   fprintf(f, "Compiler: <unknown>\n");
 #endif
 
-#ifdef __GLIBC__
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
   fprintf(f, "Library version: Glibc: Compile: %d.%d\n",
                __GLIBC__, __GLIBC_MINOR__);
   if (__GLIBC_PREREQ(2, 1))
@@ -2294,7 +2294,7 @@ for (i = 1; i < argc; i++)
       #ifdef ALT_CONFIG_PREFIX
       int sep = 0;
       int len = Ustrlen(ALT_CONFIG_PREFIX);
-      uschar *list = argrest;
+      const uschar *list = argrest;
       uschar *filename;
       while((filename = string_nextinlist(&list, &sep, big_buffer,
              big_buffer_size)) != NULL)
@@ -2708,18 +2708,19 @@ for (i = 1; i < argc; i++)
         return EXIT_FAILURE;
         }
 
-      /* Set up $sending_ip_address and $sending_port */
+      /* Set up $sending_ip_address and $sending_port, unless proxied */
 
-      if (getsockname(fileno(stdin), (struct sockaddr *)(&interface_sock),
-          &size) == 0)
-        sending_ip_address = host_ntoa(-1, &interface_sock, NULL,
-          &sending_port);
-      else
-        {
-        fprintf(stderr, "exim: getsockname() failed after -MC option: %s\n",
-          strerror(errno));
-        return EXIT_FAILURE;
-        }
+      if (!continue_proxy_cipher)
+       if (getsockname(fileno(stdin), (struct sockaddr *)(&interface_sock),
+           &size) == 0)
+         sending_ip_address = host_ntoa(-1, &interface_sock, NULL,
+           &sending_port);
+       else
+         {
+         fprintf(stderr, "exim: getsockname() failed after -MC option: %s\n",
+           strerror(errno));
+         return EXIT_FAILURE;
+         }
 
       if (running_in_test_harness) millisleep(500);
       break;
@@ -2727,7 +2728,7 @@ for (i = 1; i < argc; i++)
 
     else if (*argrest == 'C' && argrest[1] && !argrest[2])
       {
-       switch(argrest[1])
+      switch(argrest[1])
        {
     /* -MCA: set the smtp_authenticated flag; this is useful only when it
     precedes -MC (see above). The flag indicates that the host to which
@@ -2771,6 +2772,19 @@ for (i = 1; i < argc; i++)
        case 'S': smtp_peer_options |= PEER_OFFERED_SIZE; break;
 
 #ifdef SUPPORT_TLS
+    /* -MCt: similar to -MCT below but the connection is still open
+    via a proxy proces which handles the TLS context and coding.
+    Require three arguments for the proxied local address and port,
+    and the TLS cipher.  */
+
+       case 't': if (++i < argc) sending_ip_address = argv[i];
+                 else badarg = TRUE;
+                 if (++i < argc) sending_port = (int)(Uatol(argv[i]));
+                 else badarg = TRUE;
+                 if (++i < argc) continue_proxy_cipher = argv[i];
+                 else badarg = TRUE;
+                 /*FALLTHROUGH*/
+
     /* -MCT: set the tls_offered flag; this is useful only when it
     precedes -MC (see above). The flag indicates that the host to which
     Exim is connected has offered TLS support. */
@@ -4338,11 +4352,8 @@ if (!unprivileged &&                      /* originally had root AND */
         (msg_action_arg < 0 ||            /*       and               */
           msg_action != MSG_DELIVER) &&   /* not delivering and      */
         (!checking || !address_test_mode) /* not address checking    */
-        )
-      ))
-  {
+   )  ) )
   exim_setugid(exim_uid, exim_gid, TRUE, US"privilege not needed");
-  }
 
 /* When we are retaining a privileged uid, we still change to the exim gid. */
 
@@ -4356,7 +4367,6 @@ else
   there's no security risk.  For me, it's { exim -bV } on a just-built binary,
   no need to complain then. */
   if (rv == -1)
-    {
     if (!(unprivileged || removed_privilege))
       {
       fprintf(stderr,
@@ -4366,7 +4376,6 @@ else
     else
       DEBUG(D_any) debug_printf("changing group to %ld failed: %s\n",
           (long int)exim_gid, strerror(errno));
-    }
   }
 
 /* Handle a request to scan a file for malware */
@@ -5315,15 +5324,13 @@ if (smtp_input)
 else
   {
   thismessage_size_limit = expand_string_integer(message_size_limit, TRUE);
-  if (expand_string_message != NULL)
-    {
+  if (expand_string_message)
     if (thismessage_size_limit == -1)
       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand "
         "message_size_limit: %s", expand_string_message);
     else
       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "invalid value for "
         "message_size_limit: %s", expand_string_message);
-    }
   }
 
 /* Loop for several messages when reading SMTP input. If we fork any child
@@ -5420,6 +5427,7 @@ while (more)
       more = receive_msg(extract_recipients);
       if (message_id[0] == 0)
         {
+       cancel_cutthrough_connection(TRUE, US"receive dropped");
         if (more) goto moreloop;
         smtp_log_no_mail();               /* Log no mail if configured */
         exim_exit(EXIT_FAILURE);
@@ -5427,6 +5435,7 @@ while (more)
       }
     else
       {
+      cancel_cutthrough_connection(TRUE, US"message setup dropped");
       smtp_log_no_mail();               /* Log no mail if configured */
       exim_exit((rc == 0)? EXIT_SUCCESS : EXIT_FAILURE);
       }
@@ -5702,21 +5711,28 @@ while (more)
   not if queue_only is set (case 0). Case 1 doesn't happen here (too many
   connections). */
 
-  if (local_queue_only) switch(queue_only_reason)
+  if (local_queue_only)
     {
-    case 2:
-    log_write(L_delay_delivery,
-              LOG_MAIN, "no immediate delivery: more than %d messages "
-      "received in one connection", smtp_accept_queue_per_connection);
-    break;
+    cancel_cutthrough_connection(TRUE, US"no delivery; queueing");
+    switch(queue_only_reason)
+      {
+      case 2:
+       log_write(L_delay_delivery,
+               LOG_MAIN, "no immediate delivery: more than %d messages "
+         "received in one connection", smtp_accept_queue_per_connection);
+       break;
 
-    case 3:
-    log_write(L_delay_delivery,
-              LOG_MAIN, "no immediate delivery: load average %.2f",
-              (double)load_average/1000.0);
-    break;
+      case 3:
+       log_write(L_delay_delivery,
+               LOG_MAIN, "no immediate delivery: load average %.2f",
+               (double)load_average/1000.0);
+      break;
+      }
     }
 
+  else if (queue_only_policy || deliver_freeze)
+    cancel_cutthrough_connection(TRUE, US"no delivery; queueing");
+
   /* Else do the delivery unless the ACL or local_scan() called for queue only
   or froze the message. Always deliver in a separate process. A fork failure is
   not a disaster, as the delivery will eventually happen on a subsequent queue
@@ -5725,7 +5741,7 @@ while (more)
   thereby defer the delivery if it tries to use (for example) a cached ldap
   connection that the parent has called unbind on. */
 
-  else if (!queue_only_policy && !deliver_freeze)
+  else
     {
     pid_t pid;
     search_tidyup();
@@ -5741,8 +5757,7 @@ while (more)
 
       if (geteuid() != root_uid && !deliver_drop_privilege && !unprivileged)
         {
-        (void)child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE,
-               2, US"-Mc", message_id);
+       delivery_re_exec(CEE_EXEC_EXIT);
         /* Control does not return here. */
         }
 
@@ -5756,22 +5771,27 @@ while (more)
 
     if (pid < 0)
       {
+      cancel_cutthrough_connection(TRUE, US"delivery fork failed");
       log_write(0, LOG_MAIN|LOG_PANIC, "failed to fork automatic delivery "
         "process: %s", strerror(errno));
       }
+    else
+      {
+      release_cutthrough_connection(US"msg passed for delivery");
 
-    /* In the parent, wait if synchronous delivery is required. This will
-    always be the case in MUA wrapper mode. */
+      /* In the parent, wait if synchronous delivery is required. This will
+      always be the case in MUA wrapper mode. */
 
-    else if (synchronous_delivery)
-      {
-      int status;
-      while (wait(&status) != pid);
-      if ((status & 0x00ff) != 0)
-        log_write(0, LOG_MAIN|LOG_PANIC,
-          "process %d crashed with signal %d while delivering %s",
-          (int)pid, status & 0x00ff, message_id);
-      if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE);
+      if (synchronous_delivery)
+       {
+       int status;
+       while (wait(&status) != pid);
+       if ((status & 0x00ff) != 0)
+         log_write(0, LOG_MAIN|LOG_PANIC,
+           "process %d crashed with signal %d while delivering %s",
+           (int)pid, status & 0x00ff, message_id);
+       if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE);
+       }
       }
     }