Copyright updates:
[exim.git] / src / src / log.c
index 0a41cd35adaf50a824a78fffee972aa7ee982ba7..af6e8b01b4f25b4de046e0922a3c58a3203edd94 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 - 2021 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* Functions for writing log files. The code for maintaining datestamped
 log files was originally contributed by Tony Sheen. */
@@ -12,7 +13,6 @@ log files was originally contributed by Tony Sheen. */
 
 #include "exim.h"
 
-#define LOG_NAME_SIZE 256
 #define MAX_SYSLOG_LEN 870
 
 #define LOG_MODE_FILE   1
@@ -30,7 +30,6 @@ static uschar *log_names[] = { US"main", US"reject", US"panic", US"debug" };
 
 static uschar mainlog_name[LOG_NAME_SIZE];
 static uschar rejectlog_name[LOG_NAME_SIZE];
-static uschar debuglog_name[LOG_NAME_SIZE];
 
 static uschar *mainlog_datestamp = NULL;
 static uschar *rejectlog_datestamp = NULL;
@@ -268,7 +267,7 @@ Returns:       a file descriptor, or < 0 on failure (errno set)
 */
 
 static int
-log_open_already_exim(uschar * const name)
+log_open_already_exim(const uschar * const name)
 {
 int fd = -1;
 const int flags = O_WRONLY | O_APPEND | O_CREAT | O_NONBLOCK;
@@ -392,7 +391,7 @@ Returns:       a file descriptor, or < 0 on failure (errno set)
 */
 
 int
-log_open_as_exim(uschar * const name)
+log_open_as_exim(const uschar * const name)
 {
 int fd = -1;
 const uid_t euid = geteuid();
@@ -475,7 +474,7 @@ Returns:   nothing
 */
 
 static void
-open_log(int *fd, int type, uschar *tag)
+open_log(int * fd, int type, const uschar * tag)
 {
 uid_t euid;
 BOOL ok, ok2;
@@ -531,8 +530,8 @@ switch (type)
 
   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
-  char afterwards if at the start, otherwise one before. */
+    need to optimize getting the datestamp length. We remove one non-alphanumeric
+    char afterwards if at the start, otherwise one before. */
     if (string_datestamp_offset >= 0)
       {
       uschar * from = buffer + string_datestamp_offset;
@@ -685,11 +684,11 @@ Returns:
   length actually written, persisting an errno from write()
 */
 ssize_t
-write_to_fd_buf(int fd, const uschar *buf, size_t length)
+write_to_fd_buf(int fd, const uschar * buf, size_t length)
 {
 ssize_t wrote;
 size_t total_written = 0;
-const uschar *p = buf;
+const uschar * p = buf;
 size_t left = length;
 
 while (1)
@@ -712,6 +711,12 @@ while (1)
 return total_written;
 }
 
+static inline ssize_t
+write_gstring_to_fd_buf(int fd, const gstring * g)
+{
+return write_to_fd_buf(fd, g->s, g->ptr);
+}
+
 
 
 static void
@@ -807,7 +812,7 @@ log_write(unsigned int selector, int flags, const char *format, ...)
 {
 int paniclogfd;
 ssize_t written_len;
-gstring gs = { .size = LOG_BUFFER_SIZE-1, .ptr = 0, .s = log_buffer };
+gstring gs = { .size = LOG_BUFFER_SIZE-2, .ptr = 0, .s = log_buffer };
 gstring * g;
 va_list ap;
 
@@ -953,11 +958,9 @@ DEBUG(D_any|D_v)
     }
   va_end(ap);
 
-  g->size = LOG_BUFFER_SIZE;
-  g = string_catn(g, US"\n", 1);
-  debug_printf("%s", string_from_gstring(g));
+  debug_printf("%Y\n", g);
 
-  gs.size = LOG_BUFFER_SIZE-1; /* Having used the buffer for debug output, */
+  gs.size = LOG_BUFFER_SIZE-2; /* Having used the buffer for debug output, */
   gs.ptr = 0;                  /* reset it for the real use. */
   gs.s = log_buffer;
   }
@@ -992,7 +995,7 @@ if (LOGGING(pid))
   if (!syslog_pid) pid_position[1] = g->ptr;           /*  … and end+1 of the PID */
   }
 
-if (f.really_exim && message_id[0] != 0)
+if (f.really_exim && message_id[0])
   g = string_fmt_append(g, "%s ", message_id);
 
 if (flags & LOG_CONFIG)
@@ -1039,6 +1042,8 @@ if (  flags & LOG_RECIPIENTS
     }
   }
 
+/* actual size, now we are placing the newline (and space for NUL) */
+gs.size = LOG_BUFFER_SIZE;
 g = string_catn(g, US"\n", 1);
 string_from_gstring(g);
 
@@ -1113,7 +1118,7 @@ if (  flags & LOG_MAIN
 
     /* Failing to write to the log is disastrous */
 
-    written_len = write_to_fd_buf(mainlogfd, g->s, g->ptr);
+    written_len = write_gstring_to_fd_buf(mainlogfd, g);
     if (written_len != g->ptr)
       {
       log_write_failed(US"main log", g->ptr, written_len);
@@ -1172,8 +1177,8 @@ if (flags & LOG_REJECT)
        g = g2;
       else             /* Buffer is full; truncate */
         {
-        g->ptr -= 100;        /* For message and separator */
-        if (g->s[g->ptr-1] == '\n') g->ptr--;
+       gstring_trim(g, 100);        /* For message and separator */
+       gstring_trim_trailing(g, '\n');
         g = string_cat(g, US"\n*** truncated ***\n");
         break;
         }
@@ -1228,7 +1233,7 @@ if (flags & LOG_REJECT)
       if (fstat(rejectlogfd, &statbuf) >= 0) rejectlog_inode = statbuf.st_ino;
       }
 
-    written_len = write_to_fd_buf(rejectlogfd, g->s, g->ptr);
+    written_len = write_gstring_to_fd_buf(rejectlogfd, g);
     if (written_len != g->ptr)
       {
       log_write_failed(US"reject log", g->ptr, written_len);
@@ -1263,7 +1268,7 @@ if (flags & LOG_PANIC)
     if (panic_save_buffer)
       (void) write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer));
 
-    written_len = write_to_fd_buf(paniclogfd, g->s, g->ptr);
+    written_len = write_gstring_to_fd_buf(paniclogfd, g);
     if (written_len != g->ptr)
       {
       int save_errno = errno;
@@ -1280,7 +1285,10 @@ if (flags & LOG_PANIC)
   /* Give up if the DIE flag is set */
 
   if ((flags & LOG_PANIC_DIE) != LOG_PANIC)
-    die(NULL, US"Unexpected failure, please try later");
+    if (panic_coredump)
+      kill(getpid(), SIGSEGV); /* deliberate trap */
+    else
+      die(NULL, US"Unexpected failure, please try later");
   }
 }
 
@@ -1365,8 +1373,9 @@ Returns:         nothing on success - bomb out on failure
 */
 
 void
-decode_bits(unsigned int *selector, size_t selsize, int *notall,
-  uschar *string, bit_table *options, int count, uschar *which, int flags)
+decode_bits(unsigned int * selector, size_t selsize, int * notall,
+  const uschar * string, bit_table * options, int count, uschar * which,
+  int flags)
 {
 uschar *errmsg;
 if (!string) return;
@@ -1375,7 +1384,7 @@ if (*string == '=')
   {
   char *end;    /* Not uschar */
   memset(selector, 0, sizeof(*selector)*selsize);
-  *selector = strtoul(CS string+1, &end, 0);
+  *selector = strtoul(CCS string+1, &end, 0);
   if (!*end) return;
   errmsg = string_sprintf("malformed numeric %s_selector setting: %s", which,
     string);
@@ -1387,9 +1396,9 @@ if (*string == '=')
 else for(;;)
   {
   BOOL adding;
-  uschar *s;
+  const uschar * s;
   int len;
-  bit_table *start, *end;
+  bit_table * start, * end;
 
   Uskip_whitespace(&string);
   if (!*string) return;
@@ -1485,7 +1494,7 @@ 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)
+debug_logging_activate(const uschar * tag_name, const uschar * opts)
 {
 if (debug_file)
   {
@@ -1521,9 +1530,27 @@ else
 }
 
 
+void
+debug_logging_from_spool(const uschar * filename)
+{
+if (debug_fd < 0)
+  {
+  Ustrncpy(debuglog_name, filename, sizeof(debuglog_name));
+  if ((debug_fd = log_open_as_exim(filename)) >= 0)
+    debug_file = fdopen(debug_fd, "w");
+  DEBUG(D_deliver) debug_printf("debug enabled by spoolfile\n");
+  }
+/*
+else DEBUG(D_deliver)
+  debug_printf("debug already active; ignoring spoolfile '%s'\n", filename);
+*/
+}
+
+
 void
 debug_logging_stop(BOOL kill)
 {
+debug_printf("debug terminated by %s\n", kill ? "kill" : "stop");
 debug_pretrigger_discard();
 if (!debug_file || !debuglog_name[0]) return;