Fix previous attempt to remove "memory" from debug "all".
[exim.git] / src / src / exim.c
index 46dcd9100e46e3522e6164d3271bb1dc814d0088..4c83669514ba2d15d43d916920178d78ad827759 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/exim.c,v 1.10 2004/11/25 13:54:31 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.21 2005/06/27 14:29:04 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2005 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -406,10 +406,10 @@ for (i = 0; i <= 2; i++)
     if (devnull < 0) devnull = open("/dev/null", O_RDWR);
     if (devnull < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
       string_open_failed(errno, "/dev/null"));
-    if (devnull != i) dup2(devnull, i);
+    if (devnull != i) (void)dup2(devnull, i);
     }
   }
-if (devnull > 2) close(devnull);
+if (devnull > 2) (void)close(devnull);
 }
 
 
@@ -459,19 +459,19 @@ if (smtp_input)
   #ifdef SUPPORT_TLS
   tls_close(FALSE);      /* Shut down the TLS library */
   #endif
-  close(fileno(smtp_in));
-  close(fileno(smtp_out));
+  (void)close(fileno(smtp_in));
+  (void)close(fileno(smtp_out));
   smtp_in = NULL;
   }
 else
   {
-  close(0);                                           /* stdin */
-  if ((debug_selector & D_resolver) == 0)  close(1);  /* stdout */
-  if (debug_selector == 0)                            /* stderr */
+  (void)close(0);                                          /* stdin */
+  if ((debug_selector & D_resolver) == 0) (void)close(1);  /* stdout */
+  if (debug_selector == 0)                                 /* stderr */
     {
     if (!synchronous_delivery)
       {
-      close(2);
+      (void)close(2);
       log_stderr = NULL;
       }
     (void)setsid();
@@ -586,7 +586,8 @@ exit(rc);
 *************************************************/
 
 /* Called to extract the port from the values given to -oMa and -oMi.
-It also checks the syntax of the address.
+It also checks the syntax of the address, and terminates it before the
+port data when a port is extracted.
 
 Argument:
   address   the address, with possible port on the end
@@ -599,7 +600,7 @@ static int
 check_port(uschar *address)
 {
 int port = host_extract_port(address);
-if (!string_is_ip_address(address, NULL))
+if (string_is_ip_address(address, NULL) == 0)
   {
   fprintf(stderr, "exim abandoned: \"%s\" is not an IP address\n", address);
   exit(EXIT_FAILURE);
@@ -622,7 +623,7 @@ Arguments:
   flags        flag bits for verify_address()
   exit_value   to be set for failures
 
-Returns:       nothint
+Returns:       nothing
 */
 
 static void
@@ -662,6 +663,10 @@ The log options are held in two unsigned ints (because there became too many
 for one). The top bit in the table means "put in 2nd selector". This does not
 yet apply to debug options, so the "=" facility sets only the first selector.
 
+The "all" selector, which must be equal to 0xffffffff, is recognized specially.
+It sets all the bits in both selectors. However, there is a facility for then
+unsetting certain bits, because we want to turn off "memory" in the debug case.
+
 A bad value for a debug setting is treated as an unknown option - error message
 to stderr and die. For log settings, which come from the configuration file,
 we write to the log on the way out...
@@ -669,6 +674,8 @@ we write to the log on the way out...
 Arguments:
   selector1      address of the first bit string
   selector2      address of the second bit string, or NULL
+  notall1        bits to exclude from "all" for selector1
+  notall2        bits to exclude from "all" for selector2
   string         the configured string
   options        the table of option names
   count          size of table
@@ -678,8 +685,8 @@ Returns:         nothing on success - bomb out on failure
 */
 
 static void
-decode_bits(unsigned int *selector1, unsigned int *selector2, uschar *string,
-  bit_table *options, int count, uschar *which)
+decode_bits(unsigned int *selector1, unsigned int *selector2, int notall1,
+  int notall2, uschar *string, bit_table *options, int count, uschar *which)
 {
 uschar *errmsg;
 if (string == NULL) return;
@@ -732,14 +739,23 @@ else for(;;)
         unsigned int bit = middle->bit;
         unsigned int *selector;
 
-        /* The value with all bits set means "set all bits in both selectors"
+        /* The value with all bits set means "force all bits in both selectors"
         in the case where two are being handled. However, the top bit in the
-        second selector is never set. */
+        second selector is never set. When setting, some bits can be excluded.
+        */
 
         if (bit == 0xffffffff)
           {
-          *selector1 = adding? bit : 0;
-          if (selector2 != NULL) *selector2 = adding? 0x7fffffff : 0;
+          if (adding)
+            {
+            *selector1 = 0xffffffff ^ notall1;
+            if (selector2 != NULL) *selector2 = 0x7fffffff ^ notall2;
+            }
+          else
+            {
+            *selector1 = 0;
+            if (selector2 != NULL) *selector2 = 0;
+            }
           }
 
         /* Otherwise, the 0x80000000 bit means "this value, without the top
@@ -829,6 +845,9 @@ fprintf(f, "Support for:");
 #ifdef EXIM_PERL
   fprintf(f, " Perl");
 #endif
+#ifdef EXPAND_DLFUNC
+  fprintf(f, " Expand_dlfunc");
+#endif
 #ifdef USE_TCP_WRAPPERS
   fprintf(f, " TCPwrappers");
 #endif
@@ -839,6 +858,24 @@ fprintf(f, "Support for:");
   fprintf(f, " OpenSSL");
   #endif
 #endif
+#ifdef WITH_CONTENT_SCAN
+  fprintf(f, " Content_Scanning");
+#endif
+#ifdef WITH_OLD_DEMIME
+  fprintf(f, " Old_Demime");
+#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_DOMAINKEYS
+  fprintf(f, " Experimental_DomainKeys");
+#endif
 fprintf(f, "\n");
 
 fprintf(f, "Lookups:");
@@ -1875,7 +1912,7 @@ for (i = 1; i < argc; i++)
     break;
 
     /* -d: Set debug level (see also -v below) or set the drop_cr option.
-    The latter is now a no-op, retained for compatibility only. If -dd is used, 
+    The latter is now a no-op, retained for compatibility only. If -dd is used,
     debugging subprocesses of the daemon is disabled. */
 
     case 'd':
@@ -1898,7 +1935,7 @@ for (i = 1; i < argc; i++)
         argrest++;
         }
       if (*argrest != 0)
-        decode_bits(&selector, NULL, argrest, debug_options,
+        decode_bits(&selector, NULL, D_memory, 0, argrest, debug_options,
           debug_options_count, US"debug");
       debug_selector = selector;
       }
@@ -3019,7 +3056,7 @@ readconf_main();
 
 /* Handle the decoding of logging options. */
 
-decode_bits(&log_write_selector, &log_extra_selector, log_selector_string,
+decode_bits(&log_write_selector, &log_extra_selector, 0, 0, log_selector_string,
   log_options, log_options_count, US"log");
 
 DEBUG(D_any)
@@ -3216,8 +3253,8 @@ 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 ((log_extra_selector & LX_arguments) != 0 && really_exim
-     && !list_options && !checking)
+if (((debug_selector & D_any) != 0 || (log_extra_selector & LX_arguments) != 0)
+      && really_exim && !list_options && !checking)
   {
   int i;
   uschar *p = big_buffer;
@@ -3249,7 +3286,11 @@ if ((log_extra_selector & LX_arguments) != 0 && really_exim
       (p - big_buffer) - 4), printing, quote);
     while (*p) p++;
     }
-  log_write(0, LOG_MAIN, "%s", big_buffer);
+
+  if ((log_extra_selector & LX_arguments) != 0)
+    log_write(0, LOG_MAIN, "%s", big_buffer);
+  else
+    debug_printf("%s\n", big_buffer);
   }
 
 /* Set the working directory to be the top-level spool directory. We don't rely
@@ -3272,7 +3313,7 @@ script. */
 
 if (bi_option)
   {
-  fclose(config_file);
+  (void)fclose(config_file);
   if (bi_command != NULL)
     {
     int i = 0;
@@ -3432,7 +3473,7 @@ barf. */
 if (smtp_input)
   {
   union sockaddr_46 inetd_sock;
-  SOCKLEN_T size = sizeof(inetd_sock);
+  EXIM_SOCKLEN_T size = sizeof(inetd_sock);
   if (getpeername(0, (struct sockaddr *)(&inetd_sock), &size) == 0)
     {
     int family = ((struct sockaddr *)(&inetd_sock))->sa_family;
@@ -4117,17 +4158,17 @@ call to find the ident for. */
 
 if (host_checking)
   {
-  int x[4]; 
+  int x[4];
   int size;
-    
+
   sender_ident = NULL;
   if (running_in_test_harness && sender_host_port != 0 &&
       interface_address != NULL && interface_port != 0)
     verify_get_ident(1413);
-    
+
   /* In case the given address is a non-canonical IPv6 address, canonicize
   it. The code works for both IPv4 and IPv6, as it happens. */
-  
+
   size = host_aton(sender_host_address, x);
   sender_host_address = store_get(48);  /* large enough for full IPv6 */
   (void)host_nmtoa(size, x, -1, sender_host_address, ':');
@@ -4229,7 +4270,7 @@ sender_ident. */
 
 else if (is_inetd)
   {
-  fclose(stderr);
+  (void)fclose(stderr);
   exim_nullstd();                       /* Re-open to /dev/null */
   verify_get_ident(IDENT_PORT);
   host_build_sender_fullhost();
@@ -4259,7 +4300,7 @@ else if (!is_inetd) sender_host_unknown = TRUE;
 if exim is started from inetd. In this case fd 0 will be set to the socket,
 but fd 1 will not be set. This also happens for passed SMTP channels. */
 
-if (fstat(1, &statbuf) < 0) dup2(0, 1);
+if (fstat(1, &statbuf) < 0) (void)dup2(0, 1);
 
 /* Set up the incoming protocol name and the state of the program. Root
 is allowed to force received protocol via the -oMr option above, and if we are
@@ -4585,27 +4626,27 @@ while (more)
     if (ftest_prefix != NULL) printf("Prefix    = %s\n", ftest_prefix);
     if (ftest_suffix != NULL) printf("Suffix    = %s\n", ftest_suffix);
 
-    chdir("/");   /* Get away from wherever the user is running this from */
-    
-    /* Now we run either a system filter test, or a user filter test, or both. 
-    In the latter case, headers added by the system filter will persist and be 
-    available to the user filter. We need to copy the filter variables 
+    (void)chdir("/");   /* Get away from wherever the user is running this from */
+
+    /* Now we run either a system filter test, or a user filter test, or both.
+    In the latter case, headers added by the system filter will persist and be
+    available to the user filter. We need to copy the filter variables
     explicitly. */
-    
+
     if ((filter_test & FTEST_SYSTEM) != 0)
       {
       if (!filter_runtest(filter_sfd, filter_test_sfile, TRUE, more))
         exim_exit(EXIT_FAILURE);
-      }      
-      
+      }
+
     memcpy(filter_sn, filter_n, sizeof(filter_sn));
-      
+
     if ((filter_test & FTEST_USER) != 0)
       {
       if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more))
         exim_exit(EXIT_FAILURE);
-      }      
-      
+      }
+
     exim_exit(EXIT_SUCCESS);
     }
 
@@ -4678,6 +4719,12 @@ while (more)
       close_unwanted();      /* Close unwanted file descriptors and TLS */
       exim_nullstd();        /* Ensure std{in,out,err} exist */
 
+      /* Occasionally in the test harness we don't have synchronous delivery
+      set (can happen with bounces). In that case, let the old process finish
+      before continuing, to keep the debug output the same. */
+
+      if (running_in_test_harness && !synchronous_delivery) millisleep(100);
+
       /* Re-exec Exim if we need to regain privilege (note: in mua_wrapper
       mode, deliver_drop_privilege is forced TRUE). */