* Exim - an Internet mail transport agent *
*************************************************/
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../exim.h"
#else /*!MACRO_PREDEF*/
-/* Default private options block for the autoreply transport. */
+/* Default private options block for the autoreply transport.
+All non-mentioned lements zero/null/false. */
autoreply_transport_options_block autoreply_transport_option_defaults = {
- NULL, /* from */
- NULL, /* reply_to */
- NULL, /* to */
- NULL, /* cc */
- NULL, /* bcc */
- NULL, /* subject */
- NULL, /* headers */
- NULL, /* text */
- NULL, /* file */
- NULL, /* logfile */
- NULL, /* oncelog */
- NULL, /* once_repeat */
- NULL, /* never_mail */
- 0600, /* mode */
- 0, /* once_file_size */
- FALSE, /* file_expand */
- FALSE, /* file_optional */
- FALSE /* return message */
+ .mode = 0600,
};
list. Any that are found are removed.
Arguments:
- listptr points to the list of addresses
+ list list of addresses to be checked
never_mail an address list, already expanded
-Returns: nothing
+Returns: edited replacement address list, or NULL, or original
*/
-static void
-check_never_mail(uschar **listptr, const uschar *never_mail)
+static uschar *
+check_never_mail(uschar * list, const uschar * never_mail)
{
-uschar *s = *listptr;
+rmark reset_point = store_mark();
+uschar * newlist = string_copy(list);
+uschar * s = newlist;
+BOOL hit = FALSE;
-while (*s != 0)
+while (*s)
{
uschar *error, *next;
uschar *e = parse_find_address_end(s, FALSE);
{
DEBUG(D_transport)
debug_printf("discarding recipient %s (matched never_mail)\n", next);
+ hit = TRUE;
if (terminator == ',') e++;
memmove(s, e, Ustrlen(e) + 1);
}
}
}
+/* If no addresses were removed, retrieve the memory used and return
+the original. */
+
+if (!hit)
+ {
+ store_reset(reset_point);
+ return list;
+ }
+
/* Check to see if we removed the last address, leaving a terminating comma
that needs to be removed */
-s = *listptr + Ustrlen(*listptr);
-while (s > *listptr && (isspace(s[-1]) || s[-1] == ',')) s--;
+s = newlist + Ustrlen(newlist);
+while (s > newlist && (isspace(s[-1]) || s[-1] == ',')) s--;
*s = 0;
-/* Check to see if there any addresses left; if not, set NULL */
+/* Check to see if there any addresses left; if not, return NULL */
+
+s = newlist;
+while (s && isspace(*s)) s++;
+if (*s)
+ return newlist;
-s = *listptr;
-while (s != 0 && isspace(*s)) s++;
-if (*s == 0) *listptr = NULL;
+store_reset(reset_point);
+return NULL;
}
int cache_fd = -1;
int cache_size = 0;
int add_size = 0;
-EXIM_DB *dbm_file = NULL;
+EXIM_DB * dbm_file = NULL;
BOOL file_expand, return_message;
uschar *from, *reply_to, *to, *cc, *bcc, *subject, *headers, *text, *file;
uschar *logfile, *oncelog;
return FALSE;
if (oncerepeat)
- {
- once_repeat_sec = readconf_readtime(oncerepeat, 0, FALSE);
- if (once_repeat_sec < 0)
+ if ((once_repeat_sec = readconf_readtime(oncerepeat, 0, FALSE)) < 0)
{
addr->transport_return = FAIL;
addr->message = string_sprintf("Invalid time value \"%s\" for "
"\"once_repeat\" in %s transport", oncerepeat, tblock->name);
return FALSE;
}
- }
}
/* If the never_mail option is set, we have to scan all the recipients and
return FALSE;
}
- if (to) check_never_mail(&to, never_mail);
- if (cc) check_never_mail(&cc, never_mail);
- if (bcc) check_never_mail(&bcc, never_mail);
+ if (to) to = check_never_mail(to, never_mail);
+ if (cc) cc = check_never_mail(cc, never_mail);
+ if (bcc) bcc = check_never_mail(bcc, never_mail);
if (!to && !cc && !bcc)
{
if (oncelog && *oncelog && to)
{
- uschar *m;
time_t then = 0;
- if ((m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
- " not permitted", oncelog, tblock->name)))
+ if (is_tainted(oncelog))
{
addr->transport_return = DEFER;
addr->basic_errno = EACCES;
- addr->message = m;
+ addr->message = string_sprintf("Tainted '%s' (once file for %s transport)"
+ " not permitted", oncelog, tblock->name);
goto END_OFF;
}
cache_size = statbuf.st_size;
add_size = sizeof(time_t) + Ustrlen(to) + 1;
- cache_buff = store_get(cache_size + add_size, is_tainted(oncelog));
+ cache_buff = store_get(cache_size + add_size, oncelog);
if (read(cache_fd, cache_buff, cache_size) != cache_size)
{
dirname = (s = Ustrrchr(oncelog, '/'))
? string_copyn(oncelog, s - oncelog) : NULL;
- EXIM_DBOPEN(oncelog, dirname, O_RDWR|O_CREAT, ob->mode, &dbm_file);
- if (!dbm_file)
+ if (!(dbm_file = exim_dbopen(oncelog, dirname, O_RDWR|O_CREAT, ob->mode)))
{
addr->transport_return = DEFER;
addr->basic_errno = errno;
goto END_OFF;
}
- EXIM_DATUM_INIT(key_datum); /* Some DBM libraries need datums */
- EXIM_DATUM_INIT(result_datum); /* to be cleared */
- EXIM_DATUM_DATA(key_datum) = CS to;
- EXIM_DATUM_SIZE(key_datum) = Ustrlen(to) + 1;
+ exim_datum_init(&key_datum); /* Some DBM libraries need datums */
+ exim_datum_init(&result_datum); /* to be cleared */
+ exim_datum_data_set(&key_datum, (void *) to);
+ exim_datum_size_set(&key_datum, Ustrlen(to) + 1);
- if (EXIM_DBGET(dbm_file, key_datum, result_datum))
+ if (exim_dbget(dbm_file, &key_datum, &result_datum))
{
/* If the datum size is that of a binary time, we are in the new world
where messages are sent periodically. Otherwise the file is an old one,
introduced at Exim 3.00. In a couple of years' time the test on the size
can be abolished. */
- if (EXIM_DATUM_SIZE(result_datum) == sizeof(time_t))
- memcpy(&then, EXIM_DATUM_DATA(result_datum), sizeof(time_t));
+ if (exim_datum_size_get(&result_datum) == sizeof(time_t))
+ memcpy(&then, exim_datum_data_get(&result_datum), sizeof(time_t));
else
then = now;
}
if (then != 0 && (once_repeat_sec <= 0 || now - then < once_repeat_sec))
{
- uschar *m;
int log_fd;
- if ((m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
- " not permitted", logfile, tblock->name)))
+ if (is_tainted(logfile))
{
addr->transport_return = DEFER;
addr->basic_errno = EACCES;
- addr->message = m;
+ addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)"
+ " not permitted", logfile, tblock->name);
goto END_OFF;
}
/* We are going to send a message. Ensure any requested file is available. */
if (file)
{
- uschar *m;
- if ((m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
- " not permitted", file, tblock->name)))
+ if (is_tainted(file))
{
addr->transport_return = DEFER;
addr->basic_errno = EACCES;
- addr->message = m;
+ addr->message = string_sprintf("Tainted '%s' (file for %s transport)"
+ " not permitted", file, tblock->name);
return FALSE;
}
if (!(ff = Ufopen(file, "rb")) && !ob->file_optional)
addr->message = string_sprintf("Failed to create child process to send "
"message from %s transport: %s", tblock->name, strerror(errno));
DEBUG(D_transport) debug_printf("%s\n", addr->message);
- if (dbm_file) EXIM_DBCLOSE(dbm_file);
+ if (dbm_file) exim_dbclose(dbm_file);
return FALSE;
}
if (return_message)
{
- uschar *rubric = (tblock->headers_only)?
- US"------ This is a copy of the message's header lines.\n"
- : (tblock->body_only)?
- US"------ This is a copy of the body of the message, without the headers.\n"
- :
- US"------ This is a copy of the message, including all the headers.\n";
+ uschar *rubric = tblock->headers_only
+ ? US"------ This is a copy of the message's header lines.\n"
+ : tblock->body_only
+ ? US"------ This is a copy of the body of the message, without the headers.\n"
+ : US"------ This is a copy of the message, including all the headers.\n";
transport_ctx tctx = {
.u = {.fd = fileno(fp)},
.tblock = tblock,
else if (dbm_file)
{
EXIM_DATUM key_datum, value_datum;
- EXIM_DATUM_INIT(key_datum); /* Some DBM libraries need to have */
- EXIM_DATUM_INIT(value_datum); /* cleared datums. */
- EXIM_DATUM_DATA(key_datum) = CS to;
- EXIM_DATUM_SIZE(key_datum) = Ustrlen(to) + 1;
+ exim_datum_init(&key_datum); /* Some DBM libraries need to have */
+ exim_datum_init(&value_datum); /* cleared datums. */
+ exim_datum_data_set(&key_datum, to);
+ exim_datum_size_set(&key_datum, Ustrlen(to) + 1);
/* Many OS define the datum value, sensibly, as a void *. However, there
are some which still have char *. By casting this address to a char * we
can avoid warning messages from the char * systems. */
- EXIM_DATUM_DATA(value_datum) = CS (&now);
- EXIM_DATUM_SIZE(value_datum) = (int)sizeof(time_t);
- EXIM_DBPUT(dbm_file, key_datum, value_datum);
+ exim_datum_data_set(&value_datum, &now);
+ exim_datum_size_set(&value_datum, sizeof(time_t));
+ exim_dbput(dbm_file, &key_datum, &value_datum);
}
/* If sending failed, defer to try again - but if once is set the next
}
END_OFF:
-if (dbm_file) EXIM_DBCLOSE(dbm_file);
+if (dbm_file) exim_dbclose(dbm_file);
if (cache_fd > 0) (void)close(cache_fd);
DEBUG(D_transport) debug_printf("%s transport succeeded\n", tblock->name);