summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2019-10-24 23:34:19 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2019-10-25 00:55:45 +0100
commitfc7bae7f2fa3668ada9bd173e9f24c7166e1dd13 (patch)
tree8efa3fd97a1cfc91694497fbca1cd44b25c810d3 /src
parent444163417b289354b53d4708760f31d947ac6fd1 (diff)
Support moving messages across named queues. Bug 2456
Diffstat (limited to 'src')
-rw-r--r--src/src/exim.c25
-rw-r--r--src/src/functions.h21
-rw-r--r--src/src/globals.c1
-rw-r--r--src/src/globals.h1
-rw-r--r--src/src/macros.h2
-rw-r--r--src/src/queue.c8
-rw-r--r--src/src/spool_out.c26
7 files changed, 58 insertions, 26 deletions
diff --git a/src/src/exim.c b/src/src/exim.c
index 2b6297bf5..3290d6346 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -2787,6 +2787,11 @@ for (i = 1; i < argc; i++)
msg_action = MSG_DELIVER;
deliver_give_up = TRUE;
}
+ else if (Ustrcmp(argrest, "G") == 0)
+ {
+ msg_action = MSG_SETQUEUE;
+ queue_name_dest = argv[++i];
+ }
else if (Ustrcmp(argrest, "mad") == 0)
{
msg_action = MSG_MARK_ALL_DELIVERED;
@@ -4064,11 +4069,13 @@ count. Only an admin user can use the test interface to scan for email
if (!f.admin_user)
{
BOOL debugset = (debug_selector & ~D_v) != 0;
- if (deliver_give_up || f.daemon_listen || malware_test_file ||
- (count_queue && queue_list_requires_admin) ||
- (list_queue && queue_list_requires_admin) ||
- (queue_interval >= 0 && prod_requires_admin) ||
- (debugset && !f.running_in_test_harness))
+ if ( deliver_give_up || f.daemon_listen || malware_test_file
+ || count_queue && queue_list_requires_admin
+ || list_queue && queue_list_requires_admin
+ || queue_interval >= 0 && prod_requires_admin
+ || queue_name_dest && prod_requires_admin
+ || debugset && !f.running_in_test_harness
+ )
exim_fail("exim:%s permission denied\n", debugset? " debugging" : "");
}
@@ -4165,13 +4172,9 @@ now for those OS that require the first call to os_getloadavg() to be done as
root. There will be further calls later for each message received. */
#ifdef LOAD_AVG_NEEDS_ROOT
-if (receiving_message &&
- (queue_only_load >= 0 ||
- (f.is_inetd && smtp_load_reserve >= 0)
- ))
- {
+if ( receiving_message
+ && (queue_only_load >= 0 || (f.is_inetd && smtp_load_reserve >= 0)))
load_average = OS_GETLOADAVG();
- }
#endif
/* The queue_only configuration option can be overridden by -odx on the command
diff --git a/src/src/functions.h b/src/src/functions.h
index 8905d02a2..3b3a12b18 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -878,20 +878,33 @@ return string_sprintf("%s/%s/%s/%s",
# endif
static inline uschar *
-spool_sname(const uschar * purpose, uschar * subdir)
+spool_q_sname(const uschar * purpose, const uschar * q, uschar * subdir)
{
return string_sprintf("%s%s%s%s%s",
- queue_name, *queue_name ? "/" : "",
+ q, *q ? "/" : "",
purpose,
*subdir ? "/" : "", subdir);
}
static inline uschar *
+spool_sname(const uschar * purpose, uschar * subdir)
+{
+return spool_q_sname(purpose, queue_name, subdir);
+}
+
+static inline uschar *
+spool_q_fname(const uschar * purpose, const uschar * q,
+ const uschar * subdir, const uschar * fname, const uschar * suffix)
+{
+return string_sprintf("%s/%s/%s/%s/%s%s",
+ spool_directory, q, purpose, subdir, fname, suffix);
+}
+
+static inline uschar *
spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname,
const uschar * suffix)
{
-return string_sprintf("%s/%s/%s/%s/%s%s",
- spool_directory, queue_name, purpose, subdir, fname, suffix);
+return spool_q_fname(purpose, queue_name, subdir, fname, suffix);
}
static inline void
diff --git a/src/src/globals.c b/src/src/globals.c
index 677c03e77..07665bf75 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1194,6 +1194,7 @@ uschar *qualify_domain_sender = NULL;
uschar *queue_domains = NULL;
int queue_interval = -1;
uschar *queue_name = US"";
+uschar *queue_name_dest = NULL;
uschar *queue_only_file = NULL;
int queue_only_load = -1;
uschar *queue_run_max = US"5";
diff --git a/src/src/globals.h b/src/src/globals.h
index e4725a719..0466da500 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -787,6 +787,7 @@ extern pid_t queue_run_pid; /* PID of the queue running process or 0
extern int queue_run_pipe; /* Pipe for synchronizing */
extern int queue_interval; /* Queue running interval */
extern uschar *queue_name; /* Name of queue, if nondefault spooling */
+extern uschar *queue_name_dest; /* Destination queue, for moving messages */
extern BOOL queue_only; /* TRUE to disable immediate delivery */
extern int queue_only_load; /* Max load before auto-queue */
extern BOOL queue_only_load_latch; /* Latch queue_only_load TRUE */
diff --git a/src/src/macros.h b/src/src/macros.h
index e36c09c47..76913d64e 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -845,7 +845,7 @@ enum {
enum { MSG_DELIVER, MSG_FREEZE, MSG_REMOVE, MSG_THAW, MSG_ADD_RECIPIENT,
MSG_MARK_ALL_DELIVERED, MSG_MARK_DELIVERED, MSG_EDIT_SENDER,
- MSG_SHOW_COPY, MSG_LOAD,
+ MSG_SHOW_COPY, MSG_LOAD, MSG_SETQUEUE,
/* These ones must be last: a test for >= MSG_SHOW_BODY is used
to test for actions that list individual spool files. */
MSG_SHOW_BODY, MSG_SHOW_HEADER, MSG_SHOW_LOG };
diff --git a/src/src/queue.c b/src/src/queue.c
index 670f51c45..d9ff13375 100644
--- a/src/src/queue.c
+++ b/src/src/queue.c
@@ -1265,6 +1265,14 @@ switch(action)
}
+ case MSG_SETQUEUE:
+ /* The global "queue_name_dest" is used as destination, "queue_name"
+ as source */
+
+ spool_move_message(id, message_subdir, US"", US"");
+ break;
+
+
case MSG_MARK_ALL_DELIVERED:
for (int i = 0; i < recipients_count; i++)
tree_add_nonrecipient(recipients_list[i].address);
diff --git a/src/src/spool_out.c b/src/src/spool_out.c
index acc6c7b5f..463961f57 100644
--- a/src/src/spool_out.c
+++ b/src/src/spool_out.c
@@ -417,6 +417,7 @@ start-up time.
Arguments:
dir base directory name
+ dq destiinationqueue name
subdir subdirectory name
id message id
suffix suffix to add to id
@@ -429,11 +430,11 @@ Returns: TRUE if all went well
*/
static BOOL
-make_link(uschar *dir, uschar *subdir, uschar *id, uschar *suffix, uschar *from,
- uschar *to, BOOL noentok)
+make_link(uschar *dir, uschar * dq, uschar *subdir, uschar *id, uschar *suffix,
+ uschar *from, uschar *to, BOOL noentok)
{
uschar * fname = spool_fname(string_sprintf("%s%s", from, dir), subdir, id, suffix);
-uschar * tname = spool_fname(string_sprintf("%s%s", to, dir), subdir, id, suffix);
+uschar * tname = spool_q_fname(string_sprintf("%s%s", to, dir), dq, subdir, id, suffix);
if (Ulink(fname, tname) < 0 && (!noentok || errno != ENOENT))
{
log_write(0, LOG_MAIN|LOG_PANIC, "link(\"%s\", \"%s\") failed while moving "
@@ -503,13 +504,15 @@ Returns: TRUE if all is well
BOOL
spool_move_message(uschar *id, uschar *subdir, uschar *from, uschar *to)
{
+uschar * dest_qname = queue_name_dest ? queue_name_dest : queue_name;
+
/* Create any output directories that do not exist. */
(void) directory_make(spool_directory,
- spool_sname(string_sprintf("%sinput", to), subdir),
+ spool_q_sname(string_sprintf("%sinput", to), dest_qname, subdir),
INPUT_DIRECTORY_MODE, TRUE);
(void) directory_make(spool_directory,
- spool_sname(string_sprintf("%smsglog", to), subdir),
+ spool_q_sname(string_sprintf("%smsglog", to), dest_qname, subdir),
INPUT_DIRECTORY_MODE, TRUE);
/* Move the message by first creating new hard links for all the files, and
@@ -521,9 +524,9 @@ rule of waiting for a -H file before doing anything. When moving messages off
the mail spool, the -D file should be open and locked at the time, thus keeping
Exim's hands off. */
-if (!make_link(US"msglog", subdir, id, US"", from, to, TRUE) ||
- !make_link(US"input", subdir, id, US"-D", from, to, FALSE) ||
- !make_link(US"input", subdir, id, US"-H", from, to, FALSE))
+if (!make_link(US"msglog", dest_qname, subdir, id, US"", from, to, TRUE) ||
+ !make_link(US"input", dest_qname, subdir, id, US"-D", from, to, FALSE) ||
+ !make_link(US"input", dest_qname, subdir, id, US"-H", from, to, FALSE))
return FALSE;
if (!break_link(US"input", subdir, id, US"-H", from, FALSE) ||
@@ -531,8 +534,11 @@ if (!break_link(US"input", subdir, id, US"-H", from, FALSE) ||
!break_link(US"msglog", subdir, id, US"", from, TRUE))
return FALSE;
-log_write(0, LOG_MAIN, "moved from %sinput, %smsglog to %sinput, %smsglog",
- from, from, to, to);
+log_write(0, LOG_MAIN, "moved from %s%s%s%sinput, %smsglog to %s%s%s%sinput, %smsglog",
+ *queue_name?"(":"", *queue_name?queue_name:US"", *queue_name?") ":"",
+ from, from,
+ *dest_qname?"(":"", *dest_qname?dest_qname:US"", *dest_qname?") ":"",
+ to, to);
return TRUE;
}