Revert introduction of alloc_insecure_tainted_data
[exim.git] / src / src / log.c
index dff7d321190d03ce8430a063a9fa153f8ce6e4af..7a73b154a303ebf0884cf659885314983a7cefbc 100644 (file)
@@ -3,7 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for writing log files. The code for maintaining datestamped
@@ -497,11 +497,15 @@ switch (type)
     Ustrcpy(mainlog_name, buffer);
     if (string_datestamp_offset > 0)
       mainlog_datestamp = mainlog_name + string_datestamp_offset;
+    break;
+
   case lt_reject:
     /* Ditto for the reject log */
     Ustrcpy(rejectlog_name, buffer);
     if (string_datestamp_offset > 0)
       rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
+    break;
+
   case lt_debug:
     /* and deal with the debug log (which keeps the datestamp, but does not
     update it) */
@@ -514,6 +518,8 @@ switch (type)
       if (ok2)
         Ustrcpy(debuglog_name, buffer);
       }
+    break;
+
   default:
     /* Remove any datestamp if this is the panic log. This is rare, so there's no
   need to optimize getting the datestamp length. We remove one non-alphanumeric
@@ -534,6 +540,7 @@ switch (type)
       due to overlap we must use memmove() not Ustrcpy(). */
       memmove(from, to, Ustrlen(to)+1);
       }
+    break;
   }
 
 /* If the file name is too long, it is an unrecoverable disaster */
@@ -544,12 +551,8 @@ if (!ok)
 
 /* We now have the file name. After a successful open, return. */
 
-*fd = log_open_as_exim(buffer);
-
-if (*fd >= 0)
-  {
+if ((*fd = log_open_as_exim(buffer)) >= 0)
   return;
-  }
 
 euid = geteuid();
 
@@ -701,36 +704,18 @@ return total_written;
 }
 
 
-void
-set_file_path(BOOL *multiple)
+
+static void
+set_file_path(void)
 {
-uschar *s;
 int sep = ':';              /* Fixed separator - outside use */
-const uschar *ss = *log_file_path ? log_file_path : US LOG_FILE_PATH;
-
-logging_mode = 0;
-while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
+uschar *t;
+const uschar *tt = US LOG_FILE_PATH;
+while ((t = string_nextinlist(&tt, &sep, log_buffer, LOG_BUFFER_SIZE)))
   {
-  if (Ustrcmp(s, "syslog") == 0)
-    logging_mode |= LOG_MODE_SYSLOG;
-  else if (logging_mode & LOG_MODE_FILE)  /* we know a file already */
-    {
-    if (multiple) *multiple = TRUE;
-    }
-  else
-    {
-    logging_mode |= LOG_MODE_FILE;
-
-    /* If a non-empty path is given, use it */
-
-    if (*s)
-      file_path = string_copy(s);
-
-    /* If the path is empty, we want to use the first non-empty, non-
-    syslog item in LOG_FILE_PATH, if there is one, since the value of
-    log_file_path may have been set at runtime. If there is no such item,
-    use the ultimate default in the spool directory. */
-    }
+  if (Ustrcmp(t, "syslog") == 0 || t[0] == 0) continue;
+  file_path = string_copy(t);
+  break;
   }
 }
 
@@ -738,11 +723,7 @@ while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
 void
 mainlog_close(void)
 {
-/* avoid closing it if it is closed already or if we do not see a chance
-to open the file mainlog later again */
-if (mainlogfd < 0 /* already closed */
-   || !(geteuid() == 0 || geteuid() == exim_uid))
-  return;
+if (mainlogfd < 0) return;
 (void)close(mainlogfd);
 mainlogfd = -1;
 mainlog_inode = 0;
@@ -857,7 +838,38 @@ if (!path_inspected)
   /* If nothing has been set, don't waste effort... the default values for the
   statics are file_path="" and logging_mode = LOG_MODE_FILE. */
 
-  if (*log_file_path) set_file_path(&multiple);
+  if (*log_file_path)
+    {
+    int sep = ':';              /* Fixed separator - outside use */
+    uschar *s;
+    const uschar *ss = log_file_path;
+
+    logging_mode = 0;
+    while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
+      {
+      if (Ustrcmp(s, "syslog") == 0)
+        logging_mode |= LOG_MODE_SYSLOG;
+      else if (logging_mode & LOG_MODE_FILE)
+       multiple = TRUE;
+      else
+        {
+        logging_mode |= LOG_MODE_FILE;
+
+        /* If a non-empty path is given, use it */
+
+        if (*s)
+          file_path = string_copy(s);
+
+        /* If the path is empty, we want to use the first non-empty, non-
+        syslog item in LOG_FILE_PATH, if there is one, since the value of
+        log_file_path may have been set at runtime. If there is no such item,
+        use the ultimate default in the spool directory. */
+
+        else
+         set_file_path();  /* Empty item in log_file_path */
+        }    /* First non-syslog item in log_file_path */
+      }      /* Scan of log_file_path */
+    }
 
   /* If no modes have been selected, it is a major disaster */
 
@@ -881,6 +893,11 @@ if (!path_inspected)
       "More than one path given in log_file_path: using %s", file_path);
   }
 
+/* Optionally trigger debug */
+
+if (flags & LOG_PANIC && dtrigger_selector & BIT(DTi_panictrigger))
+  debug_trigger_fire();
+
 /* If debugging, show all log entries, but don't show headers. Do it all
 in one go so that it doesn't get split when multi-processing. */
 
@@ -1445,13 +1462,15 @@ misconfiguration.
 
 The first use of this is in ACL logic, "control = debug/tag=foo/opts=+expand"
 which can be combined with conditions, etc, to activate extra logging only
-for certain sources. The second use is inetd wait mode debug preservation. */
+for certain sources. The second use is inetd wait mode debug preservation.
+
+It might be nice, in ACL-initiated pretrigger mode, to not create the file
+immediately but only upon a trigger - but we'd need another cmdline option
+to pass the name through child_exxec_exim(). */
 
 void
 debug_logging_activate(uschar *tag_name, uschar *opts)
 {
-int fd = -1;
-
 if (debug_file)
   {
   debug_printf("DEBUGGING ACTIVATED FROM WITHIN CONFIG.\n"
@@ -1459,7 +1478,7 @@ if (debug_file)
   return;
   }
 
-if (tag_name != NULL && (Ustrchr(tag_name, '/') != NULL))
+if (tag_name && (Ustrchr(tag_name, '/') != NULL))
   {
   log_write(0, LOG_MAIN|LOG_PANIC, "debug tag may not contain a '/' in: %s",
       tag_name);
@@ -1475,34 +1494,29 @@ if (opts)
 resulting in certain setup not having been done.  Hack this for now so we
 do not segfault; note that nondefault log locations will not work */
 
-if (!*file_path) set_file_path(NULL);
+if (!*file_path) set_file_path();
 
-open_log(&fd, lt_debug, tag_name);
+open_log(&debug_fd, lt_debug, tag_name);
 
-if (fd != -1)
-  debug_file = fdopen(fd, "w");
+if (debug_fd != -1)
+  debug_file = fdopen(debug_fd, "w");
 else
   log_write(0, LOG_MAIN|LOG_PANIC, "unable to open debug log");
 }
 
 
 void
-debug_logging_stop(void)
+debug_logging_stop(BOOL kill)
 {
+debug_pretrigger_discard();
 if (!debug_file || !debuglog_name[0]) return;
 
 debug_selector = 0;
 fclose(debug_file);
 debug_file = NULL;
-unlink_log(lt_debug);
+debug_fd = -1;
+if (kill) unlink_log(lt_debug);
 }
 
-void
-open_logs(void)
-{
-set_file_path(NULL);
-open_log(&mainlogfd, lt_main, 0);
-open_log(&rejectlogfd, lt_reject, 0);
-}
 
 /* End of log.c */