summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/queue.c')
-rw-r--r--usr.sbin/sendmail/src/queue.c155
1 files changed, 132 insertions, 23 deletions
diff --git a/usr.sbin/sendmail/src/queue.c b/usr.sbin/sendmail/src/queue.c
index eb5176eade91..75263b7007bb 100644
--- a/usr.sbin/sendmail/src/queue.c
+++ b/usr.sbin/sendmail/src/queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#ifdef QUEUE
-static char sccsid[] = "@(#)queue.c 8.98.1.3 (Berkeley) 9/16/96 (with queueing)";
+static char sccsid[] = "@(#)queue.c 8.125 (Berkeley) 10/12/96 (with queueing)";
#else
-static char sccsid[] = "@(#)queue.c 8.98.1.3 (Berkeley) 9/16/96 (without queueing)";
+static char sccsid[] = "@(#)queue.c 8.125 (Berkeley) 10/12/96 (without queueing)";
#endif
#endif /* not lint */
@@ -71,6 +71,8 @@ WORK *WorkQ; /* queue of things to be done */
#if !defined(NGROUPS_MAX) && defined(NGROUPS)
# define NGROUPS_MAX NGROUPS /* POSIX naming convention */
#endif
+
+extern int orderq __P((bool));
/*
** QUEUEUP -- queue a message up for future transmission.
**
@@ -261,6 +263,12 @@ queueup(e, announce)
*p++ = 'r';
if (bitset(EF_HAS8BIT, e->e_flags))
*p++ = '8';
+ if (bitset(EF_DELETE_BCC, e->e_flags))
+ *p++ = 'b';
+ if (bitset(EF_RET_PARAM, e->e_flags))
+ *p++ = 'd';
+ if (bitset(EF_NO_BODY_RETN, e->e_flags))
+ *p++ = 'n';
*p++ = '\0';
if (buf[0] != '\0')
fprintf(tfp, "F%s\n", buf);
@@ -298,6 +306,8 @@ queueup(e, announce)
putc('R', tfp);
if (bitset(QPRIMARY, q->q_flags))
putc('P', tfp);
+ if (bitset(QHASNOTIFY, q->q_flags))
+ putc('N', tfp);
if (bitset(QPINGONSUCCESS, q->q_flags))
putc('S', tfp);
if (bitset(QPINGONFAILURE, q->q_flags))
@@ -534,6 +544,7 @@ runqueue(forkflag)
int njobs;
int sequenceno = 0;
extern ENVELOPE BlankEnvelope;
+ extern void clrdaemon __P((void));
/*
** If no work will ever be selected, don't even bother reading
@@ -578,7 +589,7 @@ runqueue(forkflag)
#ifndef SIGCHLD
(void) waitfor(pid);
#else
- CurChildren++;
+ proc_list_add(pid);
#endif /* SIGCHLD */
if (QueueIntvl != 0)
(void) setevent(QueueIntvl, runqueue, TRUE);
@@ -592,6 +603,7 @@ runqueue(forkflag)
(void) setsignal(SIGCHLD, SIG_DFL);
#endif /* SIGCHLD */
(void) setsignal(SIGHUP, intsig);
+ Verbose = FALSE;
}
setproctitle("running queue: %s", QueueDir);
@@ -628,6 +640,15 @@ runqueue(forkflag)
initmaps(FALSE, e);
/*
+ ** If we are running part of the queue, always ignore stored
+ ** host status.
+ */
+
+ if (QueueLimitId != NULL || QueueLimitSender != NULL ||
+ QueueLimitRecipient != NULL)
+ HostStatDir = NULL;
+
+ /*
** Start making passes through the queue.
** First, read and sort the entire queue.
** Then, process the work in that order.
@@ -643,6 +664,7 @@ runqueue(forkflag)
WORK *w = WorkQ;
WorkQ = WorkQ->w_next;
+ e->e_to = NULL;
/*
** Ignore jobs that are too expensive for the moment.
@@ -652,8 +674,11 @@ runqueue(forkflag)
if (shouldqueue(w->w_pri, w->w_ctime))
{
if (Verbose)
- printf("\nSkipping %s (sequence %d of %d)\n",
+ {
+ message("");
+ message("Skipping %s (sequence %d of %d)",
w->w_name + 2, sequenceno, njobs);
+ }
}
else
{
@@ -661,8 +686,11 @@ runqueue(forkflag)
extern pid_t dowork();
if (Verbose)
- printf("\nRunning %s (sequence %d of %d)\n",
+ {
+ message("");
+ message("Running %s (sequence %d of %d)",
w->w_name + 2, sequenceno, njobs);
+ }
pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
errno = 0;
if (pid != 0)
@@ -850,10 +878,15 @@ orderq(doall)
i |= NEED_R;
while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
{
+ int qfver = 0;
extern bool strcontainedin();
switch (lbuf[0])
{
+ case 'V':
+ qfver = atoi(&lbuf[1]);
+ break;
+
case 'P':
w->w_pri = atol(&lbuf[1]);
i &= ~NEED_P;
@@ -868,8 +901,20 @@ orderq(doall)
if (w->w_host == NULL &&
(p = strrchr(&lbuf[1], '@')) != NULL)
w->w_host = newstr(&p[1]);
- if (QueueLimitRecipient == NULL ||
- strcontainedin(QueueLimitRecipient, &lbuf[1]))
+ if (QueueLimitRecipient == NULL)
+ {
+ i &= ~NEED_R;
+ break;
+ }
+ if (qfver > 0)
+ {
+ p = strchr(&lbuf[1], ':');
+ if (p == NULL)
+ p = &lbuf[1];
+ }
+ else
+ p = &lbuf[1];
+ if (strcontainedin(QueueLimitRecipient, p))
i &= ~NEED_R;
break;
@@ -958,6 +1003,16 @@ orderq(doall)
qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
}
+ else if (QueueSortOrder == QS_BYTIME)
+ {
+ extern workcmpf3();
+
+ /*
+ ** Simple sort based on submission time only.
+ */
+
+ qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
+ }
else
{
extern workcmpf0();
@@ -1165,6 +1220,34 @@ workcmpf2(a, b)
return a->w_pri - b->w_pri;
}
/*
+** WORKCMPF3 -- simple submission-time-only compare function.
+**
+** Parameters:
+** a -- the first argument.
+** b -- the second argument.
+**
+** Returns:
+** -1 if a < b
+** 0 if a == b
+** +1 if a > b
+**
+** Side Effects:
+** none.
+*/
+
+int
+workcmpf3(a, b)
+ register WORK *a;
+ register WORK *b;
+{
+ if (a->w_ctime > b->w_ctime)
+ return 1;
+ else if (a->w_ctime < b->w_ctime)
+ return 1;
+ else
+ return 0;
+}
+ /*
** DOWORK -- do a work request.
**
** Parameters:
@@ -1276,7 +1359,7 @@ dowork(id, forkflag, requeueflag, e)
if (forkflag)
finis();
else
- dropenvelope(e);
+ dropenvelope(e, TRUE);
}
e->e_id = NULL;
return pid;
@@ -1310,7 +1393,6 @@ readqf(e)
char qf[20];
char buf[MAXLINE];
extern ADDRESS *setctluser __P((char *, int));
- extern void loseqfile();
/*
** Read and process the file.
@@ -1355,7 +1437,8 @@ readqf(e)
return FALSE;
}
- if (st.st_uid != geteuid() || bitset(S_IWOTH|S_IWGRP, st.st_mode))
+ if ((st.st_uid != geteuid() && geteuid() != RealUid) ||
+ bitset(S_IWOTH|S_IWGRP, st.st_mode))
{
# ifdef LOG
if (LogLevel > 0)
@@ -1374,6 +1457,9 @@ readqf(e)
if (st.st_size == 0)
{
/* must be a bogus file -- just remove it */
+ qf[0] = 'd';
+ (void) unlink(qf);
+ qf[0] = 'q';
(void) unlink(qf);
fclose(qfp);
return FALSE;
@@ -1408,6 +1494,8 @@ readqf(e)
register char *p;
u_long qflags;
ADDRESS *q;
+ int mid;
+ auto char *ep;
if (tTd(40, 4))
printf("+++++ %s\n", bp);
@@ -1448,6 +1536,10 @@ readqf(e)
{
switch (*p)
{
+ case 'N':
+ qflags |= QHASNOTIFY;
+ break;
+
case 'S':
qflags |= QPINGONSUCCESS;
break;
@@ -1472,6 +1564,8 @@ readqf(e)
if (q != NULL)
{
q->q_alias = ctladdr;
+ if (qfver >= 1)
+ q->q_flags &= ~Q_PINGFLAGS;
q->q_flags |= qflags;
q->q_orcpt = orcpt;
(void) recipient(q, &e->e_sendqueue, 0, e);
@@ -1508,8 +1602,7 @@ readqf(e)
break;
case 'I': /* data file's inode number */
- if (e->e_dfino == -1)
- e->e_dfino = atol(&buf[1]);
+ /* regenerated below */
break;
case 'K': /* time of last deliver attempt */
@@ -1548,6 +1641,18 @@ readqf(e)
case '8': /* has 8 bit data */
e->e_flags |= EF_HAS8BIT;
break;
+
+ case 'b': /* delete Bcc: header */
+ e->e_flags |= EF_DELETE_BCC;
+ break;
+
+ case 'd': /* envelope has DSN RET= */
+ e->e_flags |= EF_RET_PARAM;
+ break;
+
+ case 'n': /* don't return body */
+ e->e_flags |= EF_NO_BODY_RETN;
+ break;
}
}
break;
@@ -1557,7 +1662,8 @@ readqf(e)
break;
case '$': /* define macro */
- define(bp[1], newstr(&bp[2]), e);
+ mid = macid(&bp[1], &ep);
+ define(mid, newstr(ep), e);
break;
case '.': /* terminate file */
@@ -1566,7 +1672,7 @@ readqf(e)
default:
syserr("readqf: %s: line %d: bad line \"%s\"",
- qf, LineNumber, bp);
+ qf, LineNumber, shortenstring(bp, 203));
fclose(qfp);
loseqfile(e, "unrecognized line");
return FALSE;
@@ -1706,8 +1812,8 @@ printqueue()
CurrentLA = getla(); /* get load average */
printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
- if (nrequests > WorkListSize)
- printf(", only %d printed", WorkListSize);
+ if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
+ printf(", only %d printed", MaxQueueRun);
if (Verbose)
printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
else
@@ -1775,7 +1881,7 @@ printqueue()
case 'S': /* sender name */
if (Verbose)
- printf("%8ld %10ld%c%.12s %.38s",
+ printf("%8ld %10ld%c%.12s %.78s",
dfsize,
w->w_pri,
bitset(EF_WARNING, flags) ? '+' : ' ',
@@ -1788,13 +1894,15 @@ printqueue()
{
printf("\n %10.10s", bodytype);
if (statmsg[0] != '\0')
- printf(" (%.60s)", statmsg);
+ printf(" (%.*s)",
+ Verbose ? 100 : 60,
+ statmsg);
}
break;
case 'C': /* controlling user */
if (Verbose)
- printf("\n\t\t\t\t (---%.34s---)",
+ printf("\n\t\t\t\t (---%.74s---)",
&buf[1]);
break;
@@ -1808,7 +1916,7 @@ printqueue()
p++;
}
if (Verbose)
- printf("\n\t\t\t\t\t %.38s", p);
+ printf("\n\t\t\t\t\t %.78s", p);
else
printf("\n\t\t\t\t %.45s", p);
break;
@@ -1966,7 +2074,8 @@ unlockqueue(e)
ENVELOPE *e;
{
if (tTd(51, 4))
- printf("unlockqueue(%s)\n", e->e_id);
+ printf("unlockqueue(%s)\n",
+ e->e_id == NULL ? "NOQUEUE" : e->e_id);
/* if there is a lock file in the envelope, close it */
if (e->e_lockfp != NULL)
@@ -2090,7 +2199,7 @@ loseqfile(e, why)
if (e == NULL || e->e_id == NULL)
return;
- if (strlen(e->e_id) > sizeof buf - 4)
+ if (strlen(e->e_id) > (SIZE_T) sizeof buf - 4)
return;
strcpy(buf, queuename(e, 'q'));
p = queuename(e, 'Q');