* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for writing log files. The code for maintaining datestamped
static uschar *file_path = US"";
-
+/* These should be kept in-step with the private delivery error
+number definitions in macros.h */
+
+static const uschar * exim_errstrings[] = {
+ US"",
+ US"unknown error",
+ US"user slash",
+ US"exist race",
+ US"not regular",
+ US"not directory",
+ US"bad ugid",
+ US"bad mode",
+ US"inode changed",
+ US"lock failed",
+ US"bad address2",
+ US"forbid pipe",
+ US"forbid file",
+ US"forbid reply",
+ US"missing pipe",
+ US"missing file",
+ US"missing reply",
+ US"bad redirect",
+ US"smtp closed",
+ US"smtp format",
+ US"spool format",
+ US"not absolute",
+ US"Exim-imposed quota",
+ US"held",
+ US"Delivery filter process failure",
+ US"Delivery add/remove header failure",
+ US"Delivery write incomplete error",
+ US"Some expansion failed",
+ US"Failed to get gid",
+ US"Failed to get uid",
+ US"Unset or non-existent transport",
+ US"MBX length mismatch",
+ US"Lookup failed routing or in smtp tpt",
+ US"Can't match format in appendfile",
+ US"Creation outside home in appendfile",
+ US"Can't check a list; lookup defer",
+ US"DNS lookup defer",
+ US"Failed to start TLS session",
+ US"Mandatory TLS session not started",
+ US"Failed to chown a file",
+ US"Failed to create a pipe",
+ US"When verifying",
+ US"When required by client",
+ US"Used internally in smtp transport",
+ US"RCPT gave 4xx error",
+ US"MAIL gave 4xx error",
+ US"DATA gave 4xx error",
+ US"Negotiation failed for proxy configured host",
+ US"Authenticator 'other' failure",
+ US"target not supporting SMTPUTF8",
+ US"",
+
+ US"Not time for routing",
+ US"Not time for local delivery",
+ US"Not time for any remote host",
+ US"Local-only delivery",
+ US"Domain in queue_domains",
+ US"Transport concurrency limit",
+};
+
+
+/************************************************/
+const uschar *
+exim_errstr(int err)
+{
+return err < 0 ? exim_errstrings[-err] : CUS strerror(err);
+}
/*************************************************
* Write to syslog *
int
log_create(uschar *name)
{
-int fd = Uopen(name, O_CREAT|O_APPEND|O_WRONLY, LOG_MODE);
+int fd = Uopen(name,
+#ifdef O_CLOEXEC
+ O_CLOEXEC |
+#endif
+ O_CREAT|O_APPEND|O_WRONLY, LOG_MODE);
/* If creation failed, attempt to build a log directory in case that is the
problem. */
DEBUG(D_any) debug_printf("%s log directory %s\n",
created? "created" : "failed to create", name);
*lastslash = '/';
- if (created) fd = Uopen(name, O_CREAT|O_APPEND|O_WRONLY, LOG_MODE);
+ if (created) fd = Uopen(name,
+#ifdef O_CLOEXEC
+ O_CLOEXEC |
+#endif
+ O_CREAT|O_APPEND|O_WRONLY, LOG_MODE);
}
return fd;
/* If we created a subprocess, wait for it. If it succeeded, try the open. */
while (pid > 0 && waitpid(pid, &status, 0) != pid);
-if (status == 0) fd = Uopen(name, O_APPEND|O_WRONLY, LOG_MODE);
+if (status == 0) fd = Uopen(name,
+#ifdef O_CLOEXEC
+ O_CLOEXEC |
+#endif
+ O_APPEND|O_WRONLY, LOG_MODE);
/* If we failed to create a subprocess, we are in a bad way. We return
with fd still < 0, and errno set, letting the caller handle the error. */
/* We now have the file name. Try to open an existing file. After a successful
open, arrange for automatic closure on exec(), and then return. */
-*fd = Uopen(buffer, O_APPEND|O_WRONLY, LOG_MODE);
+*fd = Uopen(buffer,
+#ifdef O_CLOEXEC
+ O_CLOEXEC |
+#endif
+ O_APPEND|O_WRONLY, LOG_MODE);
if (*fd >= 0)
{
+#ifndef O_CLOEXEC
(void)fcntl(*fd, F_SETFD, fcntl(*fd, F_GETFD) | FD_CLOEXEC);
+#endif
return;
}
if (*fd >= 0)
{
+#ifndef O_CLOEXEC
(void)fcntl(*fd, F_SETFD, fcntl(*fd, F_GETFD) | FD_CLOEXEC);
+#endif
return;
}
are recursing (can't open the panic log either), the pointer will already be
set. */
-if (panic_save_buffer == NULL)
- {
- panic_save_buffer = (uschar *)malloc(LOG_BUFFER_SIZE);
- if (panic_save_buffer != NULL)
+if (!panic_save_buffer)
+ if ((panic_save_buffer = US malloc(LOG_BUFFER_SIZE)))
memcpy(panic_save_buffer, log_buffer, LOG_BUFFER_SIZE);
- }
log_write(0, LOG_PANIC_DIE, "Cannot open %s log file \"%s\": %s: "
"euid=%d egid=%d", log_names[type], buffer, strerror(errno), euid, getegid());
}
+static void
+unlink_log(int type)
+{
+if (type == lt_debug) unlink(CS debuglog_name);
+}
+
+
/*************************************************
* Add configuration file info to log line *
{
int save_errno = errno;
-if (panic_save_buffer == NULL)
- {
- panic_save_buffer = (uschar *)malloc(LOG_BUFFER_SIZE);
- if (panic_save_buffer != NULL)
+if (!panic_save_buffer)
+ if ((panic_save_buffer = US malloc(LOG_BUFFER_SIZE)))
memcpy(panic_save_buffer, log_buffer, LOG_BUFFER_SIZE);
- }
log_write(0, LOG_PANIC_DIE, "failed to write to %s: length=%d result=%d "
"errno=%d (%s)", name, length, rc, save_errno,
/* Ensure we have a buffer (see comment above); this should never be obeyed
when running Exim proper, only when running utilities. */
-if (log_buffer == NULL)
- {
- log_buffer = (uschar *)malloc(LOG_BUFFER_SIZE);
- if (log_buffer == NULL)
+if (!log_buffer)
+ if (!(log_buffer = US malloc(LOG_BUFFER_SIZE)))
{
fprintf(stderr, "exim: failed to get store for log buffer\n");
exim_exit(EXIT_FAILURE);
}
- }
/* If we haven't already done so, inspect the setting of log_file_path to
determine whether to log to files and/or to syslog. Bits in logging_mode
if (debug_file)
{
debug_printf("DEBUGGING ACTIVATED FROM WITHIN CONFIG.\n"
- "DEBUG: Tag=\"%s\" Opts=\"%s\"\n", tag_name, opts ? opts : US"");
+ "DEBUG: Tag=\"%s\" opts=\"%s\"\n", tag_name, opts ? opts : US"");
return;
}
}
+void
+debug_logging_stop(void)
+{
+if (!debug_file || !debuglog_name[0]) return;
+
+debug_selector = 0;
+fclose(debug_file);
+debug_file = NULL;
+unlink_log(lt_debug);
+}
+
+
/* End of log.c */