*************************************************/
/* 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
ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]);
-/* Save the name of the mainlog for rollover processing. Without a datestamp,
-it gets statted to see if it has been cycled. With a datestamp, the datestamp
-will be compared. The static slot for saving it is the same size as buffer,
-and the text has been checked above to fit, so this use of strcpy() is OK. */
-
-if (type == lt_main)
- {
- Ustrcpy(mainlog_name, buffer);
- if (string_datestamp_offset > 0)
- mainlog_datestamp = mainlog_name + string_datestamp_offset;
- }
-
-/* Ditto for the reject log */
-
-else if (type == lt_reject)
+switch (type)
{
- Ustrcpy(rejectlog_name, buffer);
- if (string_datestamp_offset > 0)
- rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
- }
-
-/* and deal with the debug log (which keeps the datestamp, but does not
-update it) */
+ case lt_main:
+ /* Save the name of the mainlog for rollover processing. Without a datestamp,
+ it gets statted to see if it has been cycled. With a datestamp, the datestamp
+ will be compared. The static slot for saving it is the same size as buffer,
+ and the text has been checked above to fit, so this use of strcpy() is OK. */
+ Ustrcpy(mainlog_name, buffer);
+ if (string_datestamp_offset > 0)
+ mainlog_datestamp = mainlog_name + string_datestamp_offset;
+ break;
-else if (type == lt_debug)
- {
- Ustrcpy(debuglog_name, buffer);
- if (tag)
- {
- /* this won't change the offset of the datestamp */
- ok2 = string_format(buffer, sizeof(buffer), "%s%s",
- debuglog_name, tag);
- if (ok2)
- Ustrcpy(debuglog_name, buffer);
- }
- }
+ 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;
-/* 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. */
+ case lt_debug:
+ /* and deal with the debug log (which keeps the datestamp, but does not
+ update it) */
+ Ustrcpy(debuglog_name, buffer);
+ if (tag)
+ {
+ /* this won't change the offset of the datestamp */
+ ok2 = string_format(buffer, sizeof(buffer), "%s%s",
+ debuglog_name, tag);
+ if (ok2)
+ Ustrcpy(debuglog_name, buffer);
+ }
+ break;
-else if (string_datestamp_offset >= 0)
- {
- uschar * from = buffer + string_datestamp_offset;
- uschar * to = from + string_datestamp_length;
+ 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. */
+ if (string_datestamp_offset >= 0)
+ {
+ uschar * from = buffer + string_datestamp_offset;
+ uschar * to = from + string_datestamp_length;
- if (from == buffer || from[-1] == '/')
- {
- if (!isalnum(*to)) to++;
- }
- else
- if (!isalnum(from[-1])) from--;
+ if (from == buffer || from[-1] == '/')
+ {
+ if (!isalnum(*to)) to++;
+ }
+ else
+ if (!isalnum(from[-1])) from--;
- /* This copy is ok, because we know that to is a substring of from. But
- due to overlap we must use memmove() not Ustrcpy(). */
- memmove(from, to, Ustrlen(to)+1);
+ /* This copy is ok, because we know that to is a substring of from. But
+ 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 */
/* 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();
"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. */
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"
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);
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);
}