Integrated SPF Best Guess. Fixes: bug #521
[exim.git] / src / src / log.c
index 44adcc2db6c353ae467d0cc974986f31b96343a6..ac351c44477b671d8bafd44d6853e9b421a4fde9 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/log.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/log.c,v 1.13 2007/08/22 10:10:23 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for writing log files. The code for maintaining datestamped
@@ -57,7 +57,9 @@ static uschar *file_path = US"";
 
 /* The given string is split into sections according to length, or at embedded
 newlines, and syslogged as a numbered sequence if it is overlong or if there is
-more than one line.
+more than one line. However, if we are running in the test harness, do not do
+anything. (The test harness doesn't use syslog - for obvious reasons - but we
+can get here if there is a failure to open the panic log.)
 
 Arguments:
   priority       syslog priority
@@ -72,6 +74,8 @@ write_syslog(int priority, uschar *s)
 int len, pass;
 int linecount = 0;
 
+if (running_in_test_harness) return;
+
 if (!syslog_timestamp) s += log_timezone? 26 : 20;
 
 len = Ustrlen(s);
@@ -131,9 +135,11 @@ for (pass = 0; pass < 2; pass++)
 /* This is called when Exim is dying as a result of something going wrong in
 the logging, or after a log call with LOG_PANIC_DIE set. Optionally write a
 message to debug_file or a stderr file, if they exist. Then, if in the middle
-of accepting a message, throw it away tidily; this will attempt to send an SMTP
-response if appropriate. Otherwise, try to close down an outstanding SMTP call
-tidily.
+of accepting a message, throw it away tidily by calling receive_bomb_out();
+this will attempt to send an SMTP response if appropriate. Passing NULL as the
+first argument stops it trying to run the NOTQUIT ACL (which might try further
+logging and thus cause problems). Otherwise, try to close down an outstanding
+SMTP call tidily.
 
 Arguments:
   s1         Error message to write to debug_file and/or stderr and syslog
@@ -151,7 +157,7 @@ if (s1 != NULL)
   if (log_stderr != NULL && log_stderr != debug_file)
     fprintf(log_stderr, "%s\n", s1);
   }
-if (receive_call_bombout) receive_bomb_out(s2);  /* does not return */
+if (receive_call_bombout) receive_bomb_out(NULL, s2);  /* does not return */
 if (smtp_input) smtp_closedown(s2);
 exim_exit(EXIT_FAILURE);
 }
@@ -314,15 +320,16 @@ open, arrange for automatic closure on exec(), and then return. */
 
 if (*fd >= 0)
   {
-  fcntl(*fd, F_SETFD, fcntl(*fd, F_GETFD) | FD_CLOEXEC);
+  (void)fcntl(*fd, F_SETFD, fcntl(*fd, F_GETFD) | FD_CLOEXEC);
   return;
   }
 
 /* Open was not successful: try creating the file. If this is a root process,
 we must do the creating in a subprocess set to exim:exim in order to ensure
 that the file is created with the right ownership. Otherwise, there can be a
-race if an exim process is trying to write to the log at the same time. The use
-of SIGUSR1 by the exiwhat utility can provoke a lot of simultaneous writing. */
+race if another Exim process is trying to write to the log at the same time.
+The use of SIGUSR1 by the exiwhat utility can provoke a lot of simultaneous
+writing. */
 
 euid = geteuid();
 
@@ -350,17 +357,23 @@ else if (euid == root_uid)
     _exit((create_log(buffer) < 0)? 1 : 0);
     }
 
-  /* Wait for the subprocess. If it succeeded retry the open. */
+  /* If we created a subprocess, wait for it. If it succeeded retry the open. */
 
-  while (waitpid(pid, &status, 0) != pid);
-  if (status == 0) *fd = Uopen(buffer, O_APPEND|O_WRONLY, LOG_MODE);
+  if (pid > 0)
+    {
+    while (waitpid(pid, &status, 0) != pid);
+    if (status == 0) *fd = Uopen(buffer, O_APPEND|O_WRONLY, LOG_MODE);
+    }
+
+  /* If we failed to create a subprocess, we are in a bad way. We fall through
+  with *fd still < 0, and errno set, letting the code below handle the error. */
   }
 
 /* If we now have an open file, set the close-on-exec flag and return. */
 
 if (*fd >= 0)
   {
-  fcntl(*fd, F_SETFD, fcntl(*fd, F_GETFD) | FD_CLOEXEC);
+  (void)fcntl(*fd, F_SETFD, fcntl(*fd, F_GETFD) | FD_CLOEXEC);
   return;
   }
 
@@ -713,15 +726,29 @@ if (disable_logging)
   return;
   }
 
+/* Handle disabled reject log */
+
+if (!write_rejectlog) flags &= ~LOG_REJECT;
+
 /* Create the main message in the log buffer, including the message
 id except for the process log and when called by a utility. */
 
 ptr = log_buffer;
+sprintf(CS ptr, "%s ", tod_stamp(tod_log));
+while(*ptr) ptr++;
+
+if ((log_extra_selector & LX_pid) != 0)
+  {
+  sprintf(CS ptr, "[%d] ", (int)getpid());
+  while (*ptr) ptr++;
+  }
+
 if (really_exim && (flags & LOG_PROCESS) == 0 && message_id[0] != 0)
-  sprintf(CS ptr, "%s %s ", tod_stamp(tod_log), message_id);
-else sprintf(CS ptr, "%s ", tod_stamp(tod_log));
+  {
+  sprintf(CS ptr, "%s ", message_id);
+  while(*ptr) ptr++;
+  }
 
-while(*ptr) ptr++;
 if ((flags & LOG_CONFIG) != 0) ptr = log_config_info(ptr, flags);
 
 va_start(ap, format);
@@ -734,7 +761,7 @@ va_end(ap);
 this way because it kind of fits with LOG_RECIPIENTS. */
 
 if ((flags & LOG_SENDER) != 0 &&
-    ptr < log_buffer + LOG_BUFFER_SIZE - 8 - Ustrlen(raw_sender))
+    ptr < log_buffer + LOG_BUFFER_SIZE - 10 - Ustrlen(raw_sender))
   {
   sprintf(CS ptr, " from <%s>", raw_sender);
   while (*ptr) ptr++;
@@ -807,7 +834,7 @@ if ((flags & LOG_MAIN) != 0 &&
       uschar *nowstamp = tod_stamp(tod_log_datestamp);
       if (Ustrncmp (mainlog_datestamp, nowstamp, Ustrlen(nowstamp)) != 0)
         {
-        close(mainlogfd);             /* Close the file */
+        (void)close(mainlogfd);       /* Close the file */
         mainlogfd = -1;               /* Clear the file descriptor */
         mainlog_inode = 0;            /* Unset the inode */
         mainlog_datestamp = NULL;     /* Clear the datestamp */
@@ -823,7 +850,7 @@ if ((flags & LOG_MAIN) != 0 &&
       {
       if (Ustat(mainlog_name, &statbuf) < 0 || statbuf.st_ino != mainlog_inode)
         {
-        close(mainlogfd);
+        (void)close(mainlogfd);
         mainlogfd = -1;
         mainlog_inode = 0;
         }
@@ -847,11 +874,12 @@ if ((flags & LOG_MAIN) != 0 &&
     }
   }
 
-/* Handle the log for rejected messages. This can be globally disabled. If
-there are any header lines (i.e. if the rejection is happening after the DATA
-phase), log the recipients and the headers. */
+/* Handle the log for rejected messages. This can be globally disabled, in
+which case the flags are altered above. If there are any header lines (i.e. if
+the rejection is happening after the DATA phase), log the recipients and the
+headers. */
 
-if (write_rejectlog && (flags & LOG_REJECT) != 0)
+if ((flags & LOG_REJECT) != 0)
   {
   header_line *h;
 
@@ -929,7 +957,7 @@ if (write_rejectlog && (flags & LOG_REJECT) != 0)
       uschar *nowstamp = tod_stamp(tod_log_datestamp);
       if (Ustrncmp (rejectlog_datestamp, nowstamp, Ustrlen(nowstamp)) != 0)
         {
-        close(rejectlogfd);             /* Close the file */
+        (void)close(rejectlogfd);       /* Close the file */
         rejectlogfd = -1;               /* Clear the file descriptor */
         rejectlog_inode = 0;            /* Unset the inode */
         rejectlog_datestamp = NULL;     /* Clear the datestamp */
@@ -946,7 +974,7 @@ if (write_rejectlog && (flags & LOG_REJECT) != 0)
       if (Ustat(rejectlog_name, &statbuf) < 0 ||
            statbuf.st_ino != rejectlog_inode)
         {
-        close(rejectlogfd);
+        (void)close(rejectlogfd);
         rejectlogfd = -1;
         rejectlog_inode = 0;
         }
@@ -990,11 +1018,11 @@ if ((flags & LOG_PROCESS) != 0)
 /* Handle the panic log, which is not kept open like the others. If it fails to
 open, there will be a recursive call to log_write(). We detect this above and
 attempt to write to the system log as a last-ditch try at telling somebody. In
-all cases, try to write to log_stderr. */
+all cases except mua_wrapper, try to write to log_stderr. */
 
 if ((flags & LOG_PANIC) != 0)
   {
-  if (log_stderr != NULL && log_stderr != debug_file)
+  if (log_stderr != NULL && log_stderr != debug_file && !mua_wrapper)
     fprintf(log_stderr, "%s", CS log_buffer);
 
   if ((logging_mode & LOG_MODE_SYSLOG) != 0)
@@ -1024,7 +1052,7 @@ if ((flags & LOG_PANIC) != 0)
       flags |= LOG_PANIC_DIE;
       }
 
-    close(paniclogfd);
+    (void)close(paniclogfd);
     }
 
   /* Give up if the DIE flag is set */
@@ -1044,9 +1072,9 @@ void
 log_close_all(void)
 {
 if (mainlogfd >= 0)
-  { close(mainlogfd); mainlogfd = -1; }
+  { (void)close(mainlogfd); mainlogfd = -1; }
 if (rejectlogfd >= 0)
-  { close(rejectlogfd); rejectlogfd = -1; }
+  { (void)close(rejectlogfd); rejectlogfd = -1; }
 closelog();
 syslog_open = FALSE;
 }