summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/queue.c
diff options
context:
space:
mode:
authorgshapiro <gshapiro@FreeBSD.org>2002-04-10 03:05:00 +0000
committergshapiro <gshapiro@FreeBSD.org>2002-04-10 03:05:00 +0000
commit9e3bd35cd79720a6547b183a6a6fb97ab1ae7b84 (patch)
tree348e6162af337e0b74db963f6e4dcc567e2f99e9 /contrib/sendmail/src/queue.c
parent1a7e50d796833cbb4346a251bc88555ea2c58e94 (diff)
downloadFreeBSD-src-9e3bd35cd79720a6547b183a6a6fb97ab1ae7b84.zip
FreeBSD-src-9e3bd35cd79720a6547b183a6a6fb97ab1ae7b84.tar.gz
Import sendmail 8.12.3
Diffstat (limited to 'contrib/sendmail/src/queue.c')
-rw-r--r--contrib/sendmail/src/queue.c436
1 files changed, 347 insertions, 89 deletions
diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c
index 6a2da9c..cb40c98 100644
--- a/contrib/sendmail/src/queue.c
+++ b/contrib/sendmail/src/queue.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: queue.c,v 8.834 2002/01/08 23:04:58 ca Exp $")
+SM_RCSID("@(#)$Id: queue.c,v 8.857 2002/04/02 16:43:25 ca Exp $")
#include <dirent.h>
@@ -71,13 +71,11 @@ static WORK *WorkQ; /* queue of things to be done */
static int NumWorkGroups; /* number of work groups */
/*
-** use of DoQueueRun:
-** NumQueue: indicates that a queue run is needed, look at individual bits
-** 0 - NumQueue-1: indicates that a queue run for this queue group
-** is needed.
+** DoQueueRun indicates that a queue run is needed.
+** Notice: DoQueueRun is modified in a signal handler!
*/
-static BITMAP256 volatile DoQueueRun; /* non-interrupt time queue run needed */
+static bool volatile DoQueueRun; /* non-interrupt time queue run needed */
/*
** Work group definition structure.
@@ -124,7 +122,7 @@ static void printctladdr __P((ADDRESS *, SM_FILE_T *));
static bool readqf __P((ENVELOPE *, bool));
static void restart_work_group __P((int));
static void runner_work __P((ENVELOPE *, int, bool, int, int));
-static void schedule_queue_runs __P((bool, int));
+static void schedule_queue_runs __P((bool, int, bool));
static char *strrev __P((char *));
static ADDRESS *setctluser __P((char *, int, ENVELOPE *));
#if _FFR_RHS
@@ -1217,6 +1215,7 @@ restart_work_group(wgrp)
** Parameters:
** runall -- schedule even if individual bit is not set.
** wgrp -- the work group id to schedule.
+** didit -- the queue run was performed for this work group.
**
** Returns:
** nothing
@@ -1227,22 +1226,35 @@ restart_work_group(wgrp)
else
static void
-schedule_queue_runs(runall, wgrp)
+schedule_queue_runs(runall, wgrp, didit)
bool runall;
int wgrp;
+ bool didit;
{
int qgrp, cgrp, endgrp;
+#if _FFR_QUEUE_SCHED_DBG
+ time_t lastsched;
+ bool sched;
+#endif /* _FFR_QUEUE_SCHED_DBG */
+ time_t now;
+ time_t minqintvl;
/*
** This is a bit ugly since we have to duplicate the
** code that "walks" through a work queue group.
*/
+ now = curtime();
+ minqintvl = 0;
cgrp = endgrp = WorkGrp[wgrp].wg_curqgrp;
do
{
time_t qintvl;
+#if _FFR_QUEUE_SCHED_DBG
+ lastsched = 0;
+ sched = false;
+#endif /* _FFR_QUEUE_SCHED_DBG */
qgrp = WorkGrp[wgrp].wg_qgs[cgrp]->qg_index;
if (Queue[qgrp]->qg_queueintvl > 0)
qintvl = Queue[qgrp]->qg_queueintvl;
@@ -1250,21 +1262,97 @@ schedule_queue_runs(runall, wgrp)
qintvl = QueueIntvl;
else
qintvl = (time_t) 0;
- if ((runall || bitnset(qgrp, DoQueueRun)) && qintvl > 0)
- (void) sm_setevent(qintvl, runqueueevent, qgrp);
+#if _FFR_QUEUE_SCHED_DBG
+ lastsched = Queue[qgrp]->qg_nextrun;
+#endif /* _FFR_QUEUE_SCHED_DBG */
+ if ((runall || Queue[qgrp]->qg_nextrun <= now) && qintvl > 0)
+ {
+#if _FFR_QUEUE_SCHED_DBG
+ sched = true;
+#endif /* _FFR_QUEUE_SCHED_DBG */
+ if (minqintvl == 0 || qintvl < minqintvl)
+ minqintvl = qintvl;
+
+ /*
+ ** Only set a new time if a queue run was performed
+ ** for this queue group. If the queue was not run,
+ ** we could starve it by setting a new time on each
+ ** call.
+ */
+
+ if (didit)
+ Queue[qgrp]->qg_nextrun += qintvl;
+ }
#if _FFR_QUEUE_SCHED_DBG
if (tTd(69, 10))
sm_syslog(LOG_INFO, NOQID,
- "sqr: wgrp=%d, cgrp=%d, qgrp=%d, intvl=%ld, QI=%ld, runall=%d, bit=%d, sched=%d",
+ "sqr: wgrp=%d, cgrp=%d, qgrp=%d, intvl=%ld, QI=%ld, runall=%d, lastrun=%ld, nextrun=%ld, sched=%d",
wgrp, cgrp, qgrp, Queue[qgrp]->qg_queueintvl,
- QueueIntvl, runall, bitnset(qgrp, DoQueueRun),
- (runall || bitnset(qgrp, DoQueueRun)) &&
- qintvl > 0);
+ QueueIntvl, runall, lastsched,
+ Queue[qgrp]->qg_nextrun, sched);
#endif /* _FFR_QUEUE_SCHED_DBG */
- clrbitn(qgrp, DoQueueRun);
INCR_MOD(cgrp, WorkGrp[wgrp].wg_numqgrp);
} while (endgrp != cgrp);
+ if (minqintvl > 0)
+ (void) sm_setevent(minqintvl, runqueueevent, 0);
}
+
+#if _FFR_QUEUE_RUN_PARANOIA
+/*
+** CHECKQUEUERUNNER -- check whether a queue group hasn't been run.
+**
+** Use this if events may get lost and hence queue runners may not
+** be started and mail will pile up in a queue.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** true if a queue run is necessary.
+**
+** Side Effects:
+** may schedule a queue run.
+*/
+
+bool
+checkqueuerunner()
+{
+ int qgrp;
+ time_t now, minqintvl;
+
+ now = curtime();
+ minqintvl = 0;
+ for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++)
+ {
+ time_t qintvl;
+
+ if (Queue[qgrp]->qg_queueintvl > 0)
+ qintvl = Queue[qgrp]->qg_queueintvl;
+ else if (QueueIntvl > 0)
+ qintvl = QueueIntvl;
+ else
+ qintvl = (time_t) 0;
+ if (Queue[qgrp]->qg_nextrun <= now - qintvl)
+ {
+ if (minqintvl == 0 || qintvl < minqintvl)
+ minqintvl = qintvl;
+ if (LogLevel > 1)
+ sm_syslog(LOG_WARNING, NOQID,
+ "checkqueuerunner: queue %d should have been run at %s, queue interval %ld",
+ qgrp,
+ arpadate(ctime(&Queue[qgrp]->qg_nextrun)),
+ qintvl);
+ }
+ }
+ if (minqintvl > 0)
+ {
+ (void) sm_setevent(minqintvl, runqueueevent, 0);
+ return true;
+ }
+ return false;
+}
+#endif /* _FFR_QUEUE_RUN_PARANOIA */
+
/*
** RUNQUEUE -- run the jobs in the queue.
**
@@ -1286,7 +1374,6 @@ schedule_queue_runs(runall, wgrp)
** Side Effects:
** runs things in the mail queue using run_work_group().
** maybe schedules next queue run.
-**
*/
static ENVELOPE QueueEnvelope; /* the queue run envelope */
@@ -1322,7 +1409,7 @@ runqueue(forkflag, verbose, persistent, runall)
#endif /* SM_HEAP_CHECK */
/* queue run has been started, don't do any more this time */
- clrbitn(NumQueue, DoQueueRun);
+ DoQueueRun = false;
/* more than one queue or more than one directory per queue */
if (!forkflag && !verbose &&
@@ -1392,7 +1479,7 @@ runqueue(forkflag, verbose, persistent, runall)
/* Success means the runner count needs to be updated. */
CurRunners += WorkGrp[curnum].wg_maxact;
if (!persistent)
- schedule_queue_runs(runall, curnum);
+ schedule_queue_runs(runall, curnum, true);
INCR_MOD(curnum, NumWorkGroups);
}
@@ -1403,7 +1490,7 @@ runqueue(forkflag, verbose, persistent, runall)
for (h = curnum; i < NumWorkGroups; i++)
{
- schedule_queue_runs(runall, h);
+ schedule_queue_runs(runall, h, false);
INCR_MOD(h, NumWorkGroups);
}
}
@@ -1638,7 +1725,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall)
int njobs, qdir;
int sequenceno = 1;
int qgrp, endgrp, h, i;
- time_t current_la_time;
+ time_t current_la_time, now;
bool full, more;
SM_RPOOL_T *rpool;
extern void rmexpstab __P((void));
@@ -1809,6 +1896,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall)
** runall is set or the bit for this group is set.
*/
+ now = curtime();
for (;;)
{
/*
@@ -1819,7 +1907,9 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall)
qgrp = WorkGrp[wgrp].wg_qgs[WorkGrp[wgrp].wg_curqgrp]->qg_index;
WorkGrp[wgrp].wg_curqgrp++; /* advance */
WorkGrp[wgrp].wg_curqgrp %= WorkGrp[wgrp].wg_numqgrp; /* wrap */
- if (runall || bitnset(qgrp, DoQueueRun))
+ if (runall ||
+ (Queue[qgrp]->qg_nextrun <= now &&
+ Queue[qgrp]->qg_nextrun != (time_t) -1))
break;
if (endgrp == WorkGrp[wgrp].wg_curqgrp)
{
@@ -2039,8 +2129,6 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall)
/* No more queues in work group to process. Now check persistent. */
if (persistent)
{
- time_t now;
-
sequenceno = 1;
sm_setproctitle(true, CurEnv, "running queue: %s",
qid_printqueue(qgrp, qdir));
@@ -2134,25 +2222,19 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall)
bool
doqueuerun()
{
- return bitnset(NumQueue, DoQueueRun);
+ return DoQueueRun;
}
/*
-** RUNQUEUEEVENT -- stub for use in sm_setevent
-**
-** Sets the bit to indicate that on the next run this queue should be
-** processed. The work group that the queue group is a member of has its
-** count of queue's to process updated.
+** RUNQUEUEEVENT -- Sets a flag to indicate that a queue run should be done.
**
** Parameters:
-** qgrp -- the index of the queue group.
+** none.
**
** Returns:
** none.
**
** Side Effects:
-** The work group that the queue group is a member of has its
-** count of queues to process updated.
** The invocation of this function via an alarm may interrupt
** a set of actions. Thus errno may be set in that context.
** We need to restore errno at the end of this function to ensure
@@ -2168,10 +2250,8 @@ doqueuerun()
*/
void
-runqueueevent(qgrp)
- int qgrp;
+runqueueevent()
{
- int i;
int save_errno = errno;
/*
@@ -2179,23 +2259,12 @@ runqueueevent(qgrp)
** tested in doqueuerun()
*/
- setbitn(NumQueue, DoQueueRun);
-
- /* if it is a specific group: set that bit */
- if (qgrp != NOQGRP)
- {
- setbitn(qgrp, DoQueueRun);
- goto ret;
- }
-
- /* for all others: set the bit if it doesn't have a queue interval */
- for (i = 0; i < NumQueue; i++)
- {
- if (Queue[i]->qg_queueintvl <= 0)
- setbitn(i, DoQueueRun);
- }
+ DoQueueRun = true;
+#if _FFR_QUEUE_SCHED_DBG
+ if (tTd(69, 10))
+ sm_syslog(LOG_INFO, NOQID, "rqe: done");
+#endif /* _FFR_QUEUE_SCHED_DBG */
- ret:
errno = save_errno;
if (errno == EINTR)
errno = ETIMEDOUT;
@@ -2374,7 +2443,7 @@ gatherq(qgrp, qdir, doall, full, more)
check = QueueLimitId;
while (check != NULL)
{
- if (strcontainedin(true, check->queue_match,
+ if (strcontainedin(false, check->queue_match,
d->d_name) != check->queue_negate)
break;
else
@@ -3689,6 +3758,7 @@ readqf(e, openonly)
bool nomore = false;
bool bogus = false;
MODE_T qsafe;
+ char *err;
char qf[MAXPATHLEN];
char buf[MAXLINE];
@@ -3934,13 +4004,8 @@ readqf(e, openonly)
hackattack:
syserr("SECURITY ALERT: extra or bogus data in queue file: %s",
bp);
- (void) sm_io_close(qfp, SM_TIME_DEFAULT);
-
- /* the file is already on disk */
- e->e_flags |= EF_INQUEUE;
- loseqfile(e, "bogus queue line");
- RELEASE_QUEUE;
- return false;
+ err = "bogus queue line";
+ goto fail;
}
switch (bp[0])
{
@@ -3992,9 +4057,8 @@ readqf(e, openonly)
}
}
}
- loseqfile(e, "bogus queue file directory");
- RELEASE_QUEUE;
- return false;
+ err = "bogus queue file directory";
+ goto fail;
done:
break;
}
@@ -4008,10 +4072,8 @@ readqf(e, openonly)
{
/* we are being spoofed! */
syserr("SECURITY ALERT: bogus qf line %s", bp);
- (void) sm_io_close(qfp, SM_TIME_DEFAULT);
- loseqfile(e, "bogus queue line");
- RELEASE_QUEUE;
- return false;
+ err = "bogus queue line";
+ goto fail;
}
for (p = &bp[1]; *p != '\0'; p++)
{
@@ -4063,8 +4125,15 @@ readqf(e, openonly)
#endif /* _FFR_QUARANTINE */
case 'H': /* header */
+
+ /*
+ ** count size before chompheader() destroys the line.
+ ** this isn't accurate due to macro expansion, but
+ ** better than before. "+3" to skip H?? at least.
+ */
+
+ hdrsize += strlen(bp + 3);
(void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e);
- hdrsize += strlen(&bp[1]);
break;
case 'I': /* data file's inode number */
@@ -4184,6 +4253,9 @@ readqf(e, openonly)
true);
if (q != NULL)
{
+ /* make sure we keep the current qgrp */
+ if (ISVALIDQGRP(e->e_qgrp))
+ q->q_qgrp = e->e_qgrp;
q->q_alias = ctladdr;
if (qfver >= 1)
q->q_flags &= ~Q_PINGFLAGS;
@@ -4215,10 +4287,8 @@ readqf(e, openonly)
break;
syserr("Version number in queue file (%d) greater than max (%d)",
qfver, QF_VERSION);
- (void) sm_io_close(qfp, SM_TIME_DEFAULT);
- loseqfile(e, "unsupported queue file version");
- RELEASE_QUEUE;
- return false;
+ err = "unsupported queue file version";
+ goto fail;
/* NOTREACHED */
break;
@@ -4260,10 +4330,8 @@ readqf(e, openonly)
default:
syserr("readqf: %s: line %d: bad line \"%s\"",
qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
- (void) sm_io_close(qfp, SM_TIME_DEFAULT);
- loseqfile(e, "unrecognized line");
- RELEASE_QUEUE;
- return false;
+ err = "unrecognized line";
+ goto fail;
}
if (bp != buf)
@@ -4328,6 +4396,24 @@ readqf(e, openonly)
RELEASE_QUEUE;
return true;
+
+ fail:
+ /*
+ ** There was some error reading the qf file (reason is in err var.)
+ ** Cleanup:
+ ** close file; clear e_lockfp since it is the same as qfp,
+ ** hence it is invalid (as file) after qfp is closed;
+ ** the qf file is on disk, so set the flag to avoid calling
+ ** queueup() with bogus data.
+ */
+
+ if (qfp != NULL)
+ (void) sm_io_close(qfp, SM_TIME_DEFAULT);
+ e->e_lockfp = NULL;
+ e->e_flags |= EF_INQUEUE;
+ loseqfile(e, err);
+ RELEASE_QUEUE;
+ return false;
}
/*
** PRTSTR -- print a string, "unprintable" characters are shown as \oct
@@ -4987,7 +5073,8 @@ queuename(e, type)
}
}
- if (e->e_qdir == NOQDIR)
+ /* xf files always have a valid qd and qg picked above */
+ if (e->e_qdir == NOQDIR && type != XSCRPT_LETTER)
(void) sm_strlcpyn(buf, sizeof buf, 2, pref, e->e_id);
else
{
@@ -6289,6 +6376,98 @@ upd_qs(e, delete, avail)
FILE_SYS_AVAIL(fidx) -= s;
}
+
+#if _FFR_SELECT_SHM
+
+static bool write_key_file __P((char *, long));
+static long read_key_file __P((char *, long));
+
+/*
+** WRITE_KEY_FILE -- record some key into a file.
+**
+** Parameters:
+** keypath -- file name.
+** key -- key to write.
+**
+** Returns:
+** true iff file could be written.
+**
+** Side Effects:
+** writes file.
+*/
+
+static bool
+write_key_file(keypath, key)
+ char *keypath;
+ long key;
+{
+ bool ok;
+ long sff;
+ SM_FILE_T *keyf;
+
+ ok = false;
+ if (keypath == NULL || *keypath == '\0')
+ return ok;
+ sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
+ if (TrustedUid != 0 && RealUid == TrustedUid)
+ sff |= SFF_OPENASROOT;
+ keyf = safefopen(keypath, O_WRONLY|O_TRUNC, 0644, sff);
+ if (keyf == NULL)
+ {
+ sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s",
+ keypath, sm_errstring(errno));
+ }
+ else
+ {
+ ok = sm_io_fprintf(keyf, SM_TIME_DEFAULT, "%ld\n", key) !=
+ SM_IO_EOF;
+ ok = ok && (sm_io_close(keyf, SM_TIME_DEFAULT) != SM_IO_EOF);
+ }
+ return ok;
+}
+
+/*
+** READ_KEY_FILE -- read a key from a file.
+**
+** Parameters:
+** keypath -- file name.
+** key -- default key.
+**
+** Returns:
+** key.
+*/
+
+static long
+read_key_file(keypath, key)
+ char *keypath;
+ long key;
+{
+ int r;
+ long sff, n;
+ SM_FILE_T *keyf;
+
+ if (keypath == NULL || *keypath == '\0')
+ return key;
+ sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY;
+ if (TrustedUid != 0 && RealUid == TrustedUid)
+ sff |= SFF_OPENASROOT;
+ keyf = safefopen(keypath, O_RDONLY, 0644, sff);
+ if (keyf == NULL)
+ {
+ sm_syslog(LOG_ERR, NOQID, "unable to read %s: %s",
+ keypath, sm_errstring(errno));
+ }
+ else
+ {
+ r = sm_io_fscanf(keyf, SM_TIME_DEFAULT, "%ld", &n);
+ if (r == 1)
+ key = n;
+ (void) sm_io_close(keyf, SM_TIME_DEFAULT);
+ }
+ return key;
+}
+#endif /* _FFR_SELECT_SHM */
+
/*
** INIT_SHM -- initialize shared memory structure
**
@@ -6316,9 +6495,17 @@ init_shm(qn, owner, hash)
unsigned int hash;
{
int i;
+#if _FFR_SELECT_SHM
+ bool keyselect;
+#endif /* _FFR_SELECT_SHM */
PtrFileSys = &FileSys[0];
PNumFileSys = &Numfilesys;
+#if _FFR_SELECT_SHM
+/* if this "key" is specified: select one yourself */
+# define SEL_SHM_KEY ((key_t) -1)
+# define FIRST_SHM_KEY 25
+#endif /* _FFR_SELECT_SHM */
/* This allows us to disable shared memory at runtime. */
if (ShmKey != 0)
@@ -6329,6 +6516,21 @@ init_shm(qn, owner, hash)
count = 0;
shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T);
+#if _FFR_SELECT_SHM
+ keyselect = ShmKey == SEL_SHM_KEY;
+ if (keyselect)
+ {
+ if (owner)
+ ShmKey = FIRST_SHM_KEY;
+ else
+ {
+ ShmKey = read_key_file(ShmKeyFile, ShmKey);
+ keyselect = false;
+ if (ShmKey == SEL_SHM_KEY)
+ goto error;
+ }
+ }
+#endif /* _FFR_SELECT_SHM */
for (;;)
{
/* XXX: maybe allow read access for group? */
@@ -6338,13 +6540,34 @@ init_shm(qn, owner, hash)
if (Pshm != NULL || save_errno != EEXIST)
break;
if (++count >= 3)
+ {
+#if _FFR_SELECT_SHM
+ if (keyselect)
+ {
+ ++ShmKey;
+
+ /* back where we started? */
+ if (ShmKey == SEL_SHM_KEY)
+ break;
+ continue;
+ }
+#endif /* _FFR_SELECT_SHM */
break;
+ }
+#if _FFR_SELECT_SHM
+ /* only sleep if we are at the first key */
+ if (!keyselect || ShmKey == SEL_SHM_KEY)
+#endif /* _FFR_SELECT_SHM */
sleep(count);
}
if (Pshm != NULL)
{
int *p;
+#if _FFR_SELECT_SHM
+ if (keyselect)
+ (void) write_key_file(ShmKeyFile, (long) ShmKey);
+#endif /* _FFR_SELECT_SHM */
p = (int *) Pshm;
if (owner)
{
@@ -6425,6 +6648,7 @@ setup_queues(owner)
{
int i, qn, len;
unsigned int hashval;
+ time_t now;
char basedir[MAXPATHLEN];
struct stat st;
@@ -6494,8 +6718,11 @@ setup_queues(owner)
hashval = hash_q(basedir, hashval);
#endif /* SM_CONF_SHM */
- /* initialize map for queue runs */
- clrbitmap(DoQueueRun);
+ /* initialize for queue runs */
+ DoQueueRun = false;
+ now = curtime();
+ for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
+ Queue[i]->qg_nextrun = now;
if (UseMSP && OpMode != MD_TEST)
@@ -6645,9 +6872,9 @@ set_def_queueval(qg, all)
return;
if (all)
qg->qg_qdir = QueueDir;
-#if 0
+#if _FFR_QUEUE_GROUP_SORTORDER
qg->qg_sortorder = QueueSortOrder;
-#endif /* 0 */
+#endif /* _FFR_QUEUE_GROUP_SORTORDER */
qg->qg_maxqrun = all ? MaxRunnersPerQueue : -1;
qg->qg_nice = NiceQueueRun;
}
@@ -6788,7 +7015,7 @@ makequeue(line, qdef)
qg->qg_maxrcpt = atoi(p);
break;
-#if 0
+#if _FFR_QUEUE_GROUP_SORTORDER
case 'S': /* queue sorting order */
switch (*p)
{
@@ -6814,14 +7041,26 @@ makequeue(line, qdef)
case 'm': /* Modification time */
case 'M':
- qgrp->qg_sortorder = QSO_BYMODTIME;
+ qg->qg_sortorder = QSO_BYMODTIME;
+ break;
+
+ case 'r': /* Random */
+ case 'R':
+ qg->qg_sortorder = QSO_RANDOM;
+ break;
+
+# if _FFR_RHS
+ case 's': /* Shuffled host name */
+ case 'S':
+ qg->qg_sortorder = QSO_BYSHUFFLE;
break;
+# endif /* _FFR_RHS */
default:
syserr("Invalid queue sort order \"%s\"", p);
}
break;
-#endif /* 0 */
+#endif /* _FFR_QUEUE_GROUP_SORTORDER */
default:
syserr("Q%s: unknown queue equate %c=",
@@ -7117,12 +7356,16 @@ makeworkgroups()
dir = 1;
}
- WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_realloc(WorkGrp[j].wg_qgs,
- sizeof(QUEUEGRP *) *
- (WorkGrp[j].wg_numqgrp + 1));
+ if (WorkGrp[j].wg_qgs == NULL)
+ WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_malloc(sizeof(QUEUEGRP *) *
+ (WorkGrp[j].wg_numqgrp + 1));
+ else
+ WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_realloc(WorkGrp[j].wg_qgs,
+ sizeof(QUEUEGRP *) *
+ (WorkGrp[j].wg_numqgrp + 1));
if (WorkGrp[j].wg_qgs == NULL)
{
- syserr("@cannot allocate memory for work queues, need %d bytes",
+ syserr("!cannot allocate memory for work queues, need %d bytes",
(int) (sizeof(QUEUEGRP *) *
(WorkGrp[j].wg_numqgrp + 1)));
}
@@ -7203,7 +7446,15 @@ dup_df(old, new)
char opath[MAXPATHLEN];
char npath[MAXPATHLEN];
- SM_REQUIRE(bitset(EF_HAS_DF, old->e_flags));
+ if (!bitset(EF_HAS_DF, old->e_flags))
+ {
+ /*
+ ** this can happen if: SuperSafe != True
+ ** and a bounce mail is sent that is split.
+ */
+
+ queueup(old, false, true);
+ }
SM_REQUIRE(ISVALIDQGRP(old->e_qgrp) && ISVALIDQDIR(old->e_qdir));
SM_REQUIRE(ISVALIDQGRP(new->e_qgrp) && ISVALIDQDIR(new->e_qdir));
@@ -7305,6 +7556,11 @@ split_env(e, sendqueue, qgrp, qdir)
ee->e_lockfp = NULL;
if (e->e_xfp != NULL)
ee->e_xfp = sm_io_dup(e->e_xfp);
+
+ /* failed to dup e->e_xfp, start a new transcript */
+ if (ee->e_xfp == NULL)
+ openxscript(ee);
+
ee->e_qgrp = ee->e_dfqgrp = qgrp;
ee->e_qdir = ee->e_dfqdir = qdir;
ee->e_errormode = EM_MAIL;
@@ -7317,7 +7573,7 @@ split_env(e, sendqueue, qgrp, qdir)
/*
** XXX Not sure if this copying is necessary.
- ** sendall() does this copying, but I don't know if that is
+ ** sendall() does this copying, but I (dm) don't know if that is
** because of the storage management discipline we were using
** before rpools were introduced, or if it is because these lists
** can be modified later.
@@ -7444,6 +7700,8 @@ split_across_queue_groups(e)
if (q->q_mailer != NULL &&
ISVALIDQGRP(q->q_mailer->m_qgrp))
q->q_qgrp = q->q_mailer->m_qgrp;
+ else if (ISVALIDQGRP(e->e_qgrp))
+ q->q_qgrp = e->e_qgrp;
else
q->q_qgrp = 0;
}
OpenPOWER on IntegriCloud