*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for writing log files. The code for maintaining datestamped
US"Local-only delivery",
US"Domain in queue_domains",
US"Transport concurrency limit",
+ US"Event requests alternate response",
};
static void
write_syslog(int priority, const uschar *s)
{
-int len, pass;
+int len;
int linecount = 0;
if (!syslog_pid && LOGGING(pid))
/* First do a scan through the message in order to determine how many lines
it is going to end up as. Then rescan to output it. */
-for (pass = 0; pass < 2; pass++)
+for (int pass = 0; pass < 2; pass++)
{
- int i;
- int tlen;
const uschar * ss = s;
- for (i = 1, tlen = len; tlen > 0; i++)
+ for (int i = 1, tlen = len; tlen > 0; i++)
{
int plen = tlen;
uschar *nlptr = Ustrchr(ss, '\n');
}
if (f.receive_call_bombout) receive_bomb_out(NULL, s2); /* does not return */
if (smtp_input) smtp_closedown(s2);
-exim_exit(EXIT_FAILURE, NULL);
+exim_exit(EXIT_FAILURE);
}
int
log_create_as_exim(uschar *name)
{
-pid_t pid = fork();
+pid_t pid = exim_fork(US"logfile-create");
int status = 1;
int fd = -1;
just bombing out, force the log to stderr and carry on if stderr is available.
*/
-if (euid != root_uid && euid != exim_uid && log_stderr != NULL)
+if (euid != root_uid && euid != exim_uid && log_stderr)
{
*fd = fileno(log_stderr);
return;
/* Otherwise this is a disaster. This call is deliberately ONLY to the panic
log. If possible, save a copy of the original line that was being logged. If we
are recursing (can't open the panic log either), the pointer will already be
-set. */
+set. Also, when we had to use a subprocess for the create we didn't retrieve
+errno from it, so get the error from the open attempt above (which is often
+meaningful enough, so leave it). */
if (!panic_save_buffer)
if ((panic_save_buffer = US malloc(LOG_BUFFER_SIZE)))
void
log_write(unsigned int selector, int flags, const char *format, ...)
{
-uschar * ptr;
int paniclogfd;
ssize_t written_len;
gstring gs = { .size = LOG_BUFFER_SIZE-1, .ptr = 0, .s = 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, NULL);
+ exim_exit(EXIT_FAILURE);
}
/* If we haven't already done so, inspect the setting of log_file_path to
if (flags & LOG_CONFIG) g = log_config_info(g, flags);
+ /* We want to be able to log tainted info, but log_buffer is directly
+ malloc'd. So use deliberately taint-nonchecking routines to build into
+ it, trusting that we will never expand the results. */
+
va_start(ap, format);
i = g->ptr;
- if (!string_vformat(g, FALSE, format, ap))
+ if (!string_vformat(g, SVFMT_TAINT_NOCHK, format, ap))
{
g->ptr = i;
g = string_cat(g, US"**** log string overflowed log buffer ****");
va_start(ap, format);
{
int i = g->ptr;
- if (!string_vformat(g, FALSE, format, ap))
+
+ /* We want to be able to log tainted info, but log_buffer is directly
+ malloc'd. So use deliberately taint-nonchecking routines to build into
+ it, trusting that we will never expand the results. */
+
+ if (!string_vformat(g, SVFMT_TAINT_NOCHK, format, ap))
{
g->ptr = i;
g = string_cat(g, US"**** log string overflowed log buffer ****\n");
if ( flags & LOG_SENDER
&& g->ptr < LOG_BUFFER_SIZE - 10 - Ustrlen(raw_sender))
- g = string_fmt_append(g, " from <%s>", raw_sender);
+ g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " from <%s>", raw_sender);
/* Add list of recipients to the message if required; the raw list,
before rewriting, was saved in raw_recipients. There may be none, if an ACL
&& raw_recipients_count > 0)
{
int i;
- g = string_fmt_append(g, " for");
+ g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " for", NULL);
for (i = 0; i < raw_recipients_count; i++)
{
uschar * s = raw_recipients[i];
if (LOG_BUFFER_SIZE - g->ptr < Ustrlen(s) + 3) break;
- g = string_fmt_append(g, " %s", s);
+ g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " %s", s);
}
}
else
fprintf(log_stderr, "%s", CS log_buffer);
- if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE, US"");
+ if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE);
return;
}
if (flags & LOG_REJECT)
{
- header_line *h;
-
if (header_list && LOGGING(rejected_header))
{
- uschar * p = g->s + g->ptr;
+ gstring * g2;
int i;
if (recipients_count > 0)
{
/* List the sender */
- string_format(p, LOG_BUFFER_SIZE - g->ptr,
- "Envelope-from: <%s>\n", sender_address);
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ "Envelope-from: <%s>\n", sender_address);
+ if (g2) g = g2;
/* List up to 5 recipients */
- string_format(p, LOG_BUFFER_SIZE - g->ptr,
- "Envelope-to: <%s>\n", recipients_list[0].address);
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ "Envelope-to: <%s>\n", recipients_list[0].address);
+ if (g2) g = g2;
for (i = 1; i < recipients_count && i < 5; i++)
{
- string_format(p, LOG_BUFFER_SIZE - g->ptr, " <%s>\n",
- recipients_list[i].address);
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ " <%s>\n", recipients_list[i].address);
+ if (g2) g = g2;
}
if (i < recipients_count)
{
- string_format(p, LOG_BUFFER_SIZE - g->ptr,
- " ...\n");
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " ...\n", NULL);
+ if (g2) g = g2;
}
}
/* A header with a NULL text is an unfilled in Received: header */
- for (h = header_list; h; h = h->next) if (h->text)
+ for (header_line * h = header_list; h; h = h->next) if (h->text)
{
- BOOL fitted = string_format(p, LOG_BUFFER_SIZE - g->ptr,
- "%c %s", h->type, h->text);
- while (*p) p++;
- g->ptr = p - g->s;
- if (!fitted) /* Buffer is full; truncate */
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ "%c %s", h->type, h->text);
+ if (g2)
+ g = g2;
+ else /* Buffer is full; truncate */
{
g->ptr -= 100; /* For message and separator */
if (g->s[g->ptr-1] == '\n') g->ptr--;
uschar *string, bit_table *options, int count, uschar *which, int flags)
{
uschar *errmsg;
-if (string == NULL) return;
+if (!string) return;
if (*string == '=')
{
char *end; /* Not uschar */
memset(selector, 0, sizeof(*selector)*selsize);
*selector = strtoul(CS string+1, &end, 0);
- if (*end == 0) return;
+ if (!*end) return;
errmsg = string_sprintf("malformed numeric %s_selector setting: %s", which,
string);
goto ERROR_RETURN;
int len;
bit_table *start, *end;
- while (isspace(*string)) string++;
- if (*string == 0) return;
+ Uskip_whitespace(&string);
+ if (!*string) return;
if (*string != '+' && *string != '-')
{
bit_table *middle = start + (end - start)/2;
int c = Ustrncmp(s, middle->name, len);
if (c == 0)
- {
if (middle->name[len] != 0) c = -1; else
{
unsigned int bit = middle->bit;
break; /* Out of loop to match selector name */
}
- }
if (c < 0) end = middle; else start = middle + 1;
} /* Loop to match selector name */