summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/queue.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1997-06-27 14:53:01 +0000
committerPeter Wemm <peter@FreeBSD.org>1997-06-27 14:53:01 +0000
commitf3a1fc342b4423150f71e23e50f24d073a6d238b (patch)
treea5e7dee2f9ff41f2d43580f859a6e8970722fa7d /usr.sbin/sendmail/src/queue.c
parent52c4d6f5d6bb1ffd8b30c0429fc18d371856a062 (diff)
Notes
Diffstat (limited to 'usr.sbin/sendmail/src/queue.c')
-rw-r--r--usr.sbin/sendmail/src/queue.c242
1 files changed, 157 insertions, 85 deletions
diff --git a/usr.sbin/sendmail/src/queue.c b/usr.sbin/sendmail/src/queue.c
index 2afa73dcf744b..13965de01be2a 100644
--- a/usr.sbin/sendmail/src/queue.c
+++ b/usr.sbin/sendmail/src/queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if QUEUE
-static char sccsid[] = "@(#)queue.c 8.153 (Berkeley) 1/14/97 (with queueing)";
+static char sccsid[] = "@(#)queue.c 8.169 (Berkeley) 6/14/97 (with queueing)";
#else
-static char sccsid[] = "@(#)queue.c 8.153 (Berkeley) 1/14/97 (without queueing)";
+static char sccsid[] = "@(#)queue.c 8.169 (Berkeley) 6/14/97 (without queueing)";
#endif
#endif /* not lint */
@@ -99,7 +99,8 @@ queueup(e, announce)
register char *p;
MAILER nullmailer;
MCI mcibuf;
- char buf[MAXLINE], tf[MAXLINE];
+ char tf[MAXQFNAME];
+ char buf[MAXLINE];
extern void printctladdr __P((ADDRESS *, FILE *));
/*
@@ -125,21 +126,19 @@ queueup(e, announce)
{
if (errno != EEXIST)
break;
-#ifdef LOG
if (LogLevel > 0 && (i % 32) == 0)
- syslog(LOG_ALERT, "queueup: cannot create %s, uid=%d: %s",
+ sm_syslog(LOG_ALERT, e->e_id,
+ "queueup: cannot create %s, uid=%d: %s",
tf, geteuid(), errstring(errno));
-#endif
}
else
{
if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))
break;
-#ifdef LOG
else if (LogLevel > 0 && (i % 32) == 0)
- syslog(LOG_ALERT, "queueup: cannot lock %s: %s",
+ sm_syslog(LOG_ALERT, e->e_id,
+ "queueup: cannot lock %s: %s",
tf, errstring(errno));
-#endif
close(fd);
}
@@ -192,7 +191,7 @@ queueup(e, announce)
if (!bitset(EF_HAS_DF, e->e_flags))
{
register FILE *dfp = NULL;
- char dfname[20];
+ char dfname[MAXQFNAME];
struct stat stbuf;
strcpy(dfname, queuename(e, 'd'));
@@ -247,6 +246,11 @@ queueup(e, announce)
if (e->e_bodytype != NULL)
fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE));
+#if _FFR_SAVE_CHARSET
+ if (e->e_charset != NULL)
+ fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE));
+#endif
+
/* message from envelope, if it exists */
if (e->e_message != NULL)
fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE));
@@ -296,9 +300,9 @@ queueup(e, announce)
{
#if XDEBUG
if (bitset(QQUEUEUP, q->q_flags))
- syslog(LOG_DEBUG,
- "dropenvelope: %s: q_flags = %x, paddr = %s",
- e->e_id, q->q_flags, q->q_paddr);
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "dropenvelope: q_flags = %x, paddr = %s",
+ q->q_flags, q->q_paddr);
#endif
continue;
}
@@ -453,11 +457,9 @@ queueup(e, announce)
errno = 0;
e->e_flags |= EF_INQUEUE;
-# ifdef LOG
/* save log info */
if (LogLevel > 79)
- syslog(LOG_DEBUG, "%s: queueup, qf=%s", e->e_id, qf);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf);
if (tTd(40, 1))
printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
@@ -537,6 +539,7 @@ printctladdr(a, tfp)
*/
ENVELOPE QueueEnvelope; /* the queue run envelope */
+extern int get_num_procs_online __P((void));
bool
runqueue(forkflag, verbose)
@@ -546,30 +549,45 @@ runqueue(forkflag, verbose)
register ENVELOPE *e;
int njobs;
int sequenceno = 0;
+ time_t current_la_time;
extern ENVELOPE BlankEnvelope;
extern void clrdaemon __P((void));
- extern void runqueueevent __P((bool));
+ extern void runqueueevent __P((void));
extern void drop_privileges __P((void));
+ DoQueueRun = FALSE;
+
/*
** If no work will ever be selected, don't even bother reading
** the queue.
*/
CurrentLA = getla(); /* get load average */
+ current_la_time = curtime();
- if (CurrentLA >= QueueLA)
+ if (shouldqueue(WkRecipFact, current_la_time))
{
char *msg = "Skipping queue run -- load average too high";
if (verbose)
message("458 %s\n", msg);
-#ifdef LOG
if (LogLevel > 8)
- syslog(LOG_INFO, "runqueue: %s", msg);
-#endif
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: %s",
+ msg);
if (forkflag && QueueIntvl != 0)
- (void) setevent(QueueIntvl, runqueueevent, TRUE);
+ (void) setevent(QueueIntvl, runqueueevent, 0);
+ return FALSE;
+ }
+
+ /*
+ ** See if we already have too many children.
+ */
+
+ if (forkflag && QueueIntvl != 0 &&
+ MaxChildren > 0 && CurChildren >= MaxChildren)
+ {
+ (void) setevent(QueueIntvl, runqueueevent, 0);
return FALSE;
}
@@ -596,12 +614,12 @@ runqueue(forkflag, verbose)
if (verbose)
message("458 %s: %s\n", msg, err);
-#ifdef LOG
if (LogLevel > 8)
- syslog(LOG_INFO, "runqueue: %s: %s", msg, err);
-#endif
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: %s: %s",
+ msg, err);
if (QueueIntvl != 0)
- (void) setevent(QueueIntvl, runqueueevent, TRUE);
+ (void) setevent(QueueIntvl, runqueueevent, 0);
(void) releasesignal(SIGCHLD);
return FALSE;
}
@@ -617,7 +635,7 @@ runqueue(forkflag, verbose)
releasesignal(SIGCHLD);
#endif /* SIGCHLD */
if (QueueIntvl != 0)
- (void) setevent(QueueIntvl, runqueueevent, TRUE);
+ (void) setevent(QueueIntvl, runqueueevent, 0);
return TRUE;
}
/* child -- double fork and clean up signals */
@@ -634,11 +652,10 @@ runqueue(forkflag, verbose)
setproctitle("running queue: %s", QueueDir);
-# ifdef LOG
if (LogLevel > 69)
- syslog(LOG_DEBUG, "runqueue %s, pid=%d, forkflag=%d",
+ sm_syslog(LOG_DEBUG, NOQID,
+ "runqueue %s, pid=%d, forkflag=%d",
QueueDir, getpid(), forkflag);
-# endif /* LOG */
/*
** Release any resources used by the daemon code.
@@ -665,7 +682,10 @@ runqueue(forkflag, verbose)
/* make sure we have disconnected from parent */
if (forkflag)
+ {
disconnect(1, e);
+ OnlyOneError = QuickAbort = FALSE;
+ }
/*
** Make sure the alias database is open.
@@ -705,17 +725,52 @@ runqueue(forkflag, verbose)
/*
** Ignore jobs that are too expensive for the moment.
+ **
+ ** Get new load average every 30 seconds.
*/
+ if (current_la_time < curtime() - 30)
+ {
+ CurrentLA = getla();
+ current_la_time = curtime();
+ }
+ if (shouldqueue(WkRecipFact, current_la_time))
+ {
+ char *msg = "Aborting queue run: load average too high";
+
+ if (Verbose)
+ message("%s", msg);
+ if (LogLevel > 8)
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: %s",
+ msg);
+ break;
+ }
sequenceno++;
if (shouldqueue(w->w_pri, w->w_ctime))
{
if (Verbose)
- {
message("");
+ if (QueueSortOrder == QS_BYPRIORITY)
+ {
+ if (Verbose)
+ message("Skipping %s (sequence %d of %d) and flushing rest of queue",
+ w->w_name + 2,
+ sequenceno,
+ njobs);
+ if (LogLevel > 8)
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: Flushing queue from %s (pri %ld, LA %d, %d of %d)",
+ w->w_name + 2,
+ w->w_pri,
+ CurrentLA,
+ sequenceno,
+ njobs);
+ break;
+ }
+ else if (Verbose)
message("Skipping %s (sequence %d of %d)",
w->w_name + 2, sequenceno, njobs);
- }
}
else
{
@@ -752,10 +807,9 @@ runqueue(forkflag, verbose)
*/
void
-runqueueevent(forkflag)
- bool forkflag;
+runqueueevent()
{
- (void) runqueue(forkflag, FALSE);
+ DoQueueRun = TRUE;
}
/*
** ORDERQ -- order the work queue.
@@ -843,6 +897,9 @@ orderq(doall)
if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
continue;
+ if (strlen(d->d_name) > MAXQFNAME)
+ continue;
+
if (QueueLimitId != NULL &&
!strcontainedin(QueueLimitId, d->d_name))
continue;
@@ -866,11 +923,10 @@ orderq(doall)
{
if (Verbose)
printf("orderq: bogus qf name %s\n", d->d_name);
-# ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "orderq: bogus qf name %s",
+ sm_syslog(LOG_ALERT, NOQID,
+ "orderq: bogus qf name %s",
d->d_name);
-# endif
if (strlen(d->d_name) > (SIZE_T) MAXNAME)
d->d_name[MAXNAME] = '\0';
strcpy(lbuf, d->d_name);
@@ -883,11 +939,10 @@ orderq(doall)
/* open control file (if not too many files) */
if (++wn >= MaxQueueRun && MaxQueueRun > 0)
{
-# ifdef LOG
if (wn == MaxQueueRun && LogLevel > 0)
- syslog(LOG_ALERT, "WorkList for %s maxed out at %d",
- QueueDir, MaxQueueRun);
-# endif
+ sm_syslog(LOG_ALERT, NOQID,
+ "WorkList for %s maxed out at %d",
+ QueueDir, MaxQueueRun);
continue;
}
if (wn >= WorkListSize)
@@ -930,8 +985,20 @@ orderq(doall)
while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
{
int qfver = 0;
+ char *p;
+ int c;
extern bool strcontainedin();
+ p = strchr(lbuf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ else
+ {
+ /* flush rest of overly long line */
+ while ((c = getc(cf)) != EOF && c != '\n')
+ continue;
+ }
+
switch (lbuf[0])
{
case 'V':
@@ -1140,18 +1207,18 @@ grow_wlist()
{
WorkListSize = newsize;
WorkList = newlist;
-# ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_NOTICE, "grew WorkList for %s to %d",
- QueueDir, WorkListSize);
+ sm_syslog(LOG_NOTICE, NOQID,
+ "grew WorkList for %s to %d",
+ QueueDir, WorkListSize);
}
}
else if (LogLevel > 0)
{
- syslog(LOG_ALERT, "FAILED to grow WorkList for %s to %d",
- QueueDir, newsize);
-# endif
+ sm_syslog(LOG_ALERT, NOQID,
+ "FAILED to grow WorkList for %s to %d",
+ QueueDir, newsize);
}
}
if (tTd(41, 1))
@@ -1347,6 +1414,11 @@ dowork(id, forkflag, requeueflag, e)
/* parent -- clean out connection cache */
mci_flush(FALSE, NULL);
}
+ else
+ {
+ /* child -- error messages to the transcript */
+ QuickAbort = OnlyOneError = FALSE;
+ }
}
else
{
@@ -1378,11 +1450,10 @@ dowork(id, forkflag, requeueflag, e)
OpMode = MD_DELIVER;
}
setproctitle("%s: from queue", id);
-# ifdef LOG
if (LogLevel > 76)
- syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id,
- getpid());
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "dowork, pid=%d",
+ getpid());
/* don't use the headers from sendmail.cf... */
e->e_header = NULL;
@@ -1443,7 +1514,7 @@ readqf(e)
register char *p;
char *orcpt = NULL;
bool nomore = FALSE;
- char qf[20];
+ char qf[MAXQFNAME];
char buf[MAXLINE];
extern ADDRESS *setctluser __P((char *, int));
@@ -1468,10 +1539,8 @@ readqf(e)
/* being processed by another queuer */
if (Verbose || tTd(40, 8))
printf("%s: locked\n", e->e_id);
-# ifdef LOG
if (LogLevel > 19)
- syslog(LOG_DEBUG, "%s: locked", e->e_id);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "locked");
(void) fclose(qfp);
return FALSE;
}
@@ -1493,13 +1562,12 @@ readqf(e)
if ((st.st_uid != geteuid() && geteuid() != RealUid) ||
bitset(S_IWOTH|S_IWGRP, st.st_mode))
{
-# ifdef LOG
if (LogLevel > 0)
{
- syslog(LOG_ALERT, "%s: bogus queue file, uid=%d, mode=%o",
- e->e_id, st.st_uid, st.st_mode);
+ sm_syslog(LOG_ALERT, e->e_id,
+ "bogus queue file, uid=%d, mode=%o",
+ st.st_uid, st.st_mode);
}
-# endif /* LOG */
if (tTd(40, 8))
printf("readqf(%s): bogus file\n", qf);
loseqfile(e, "bogus file uid in mqueue");
@@ -1509,11 +1577,14 @@ 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);
+ /* must be a bogus file -- if also old, just remove it */
+ if (st.st_ctime + 10 * 60 < curtime())
+ {
+ qf[0] = 'd';
+ (void) unlink(qf);
+ qf[0] = 'q';
+ (void) unlink(qf);
+ }
fclose(qfp);
return FALSE;
}
@@ -1636,6 +1707,7 @@ readqf(e)
hdrsize += strlen(&bp[1]);
break;
+ case 'L': /* Solaris Content-Length: */
case 'M': /* message */
/* ignore this; we want a new message next time */
break;
@@ -1648,6 +1720,12 @@ readqf(e)
e->e_bodytype = newstr(&bp[1]);
break;
+#if _FFR_SAVE_CHARSET
+ case 'X': /* character set */
+ e->e_charset = newstr(&bp[1]);
+ break;
+#endif
+
case 'D': /* data file name */
/* obsolete -- ignore */
break;
@@ -1669,7 +1747,7 @@ readqf(e)
/* if this has been tried recently, let it be */
if (e->e_ntries > 0 &&
- (curtime() - e->e_dtime) < MinQueueAge)
+ curtime() < e->e_dtime + MinQueueAge)
{
char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
extern void unlockqueue();
@@ -1677,11 +1755,10 @@ readqf(e)
if (Verbose || tTd(40, 8))
printf("%s: too young (%s)\n",
e->e_id, howlong);
-#ifdef LOG
if (LogLevel > 19)
- syslog(LOG_DEBUG, "%s: too young (%s)",
- e->e_id, howlong);
-#endif
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "too young (%s)",
+ howlong);
e->e_id = NULL;
unlockqueue(e);
return FALSE;
@@ -1822,7 +1899,7 @@ printqueue()
struct stat st;
# ifdef NGROUPS_MAX
int n;
- GIDSET_T gidset[NGROUPS_MAX];
+ extern GIDSET_T InitialGidSet[NGROUPS_MAX];
# endif
if (stat(QueueDir, &st) < 0)
@@ -1831,10 +1908,10 @@ printqueue()
return;
}
# ifdef NGROUPS_MAX
- n = getgroups(NGROUPS_MAX, gidset);
+ n = NGROUPS_MAX;
while (--n >= 0)
{
- if (gidset[n] == st.st_gid)
+ if (InitialGidSet[n] == st.st_gid)
break;
}
if (n < 0 && RealGid != st.st_gid)
@@ -2037,7 +2114,7 @@ queuename(e, type)
if (e->e_id == NULL)
{
- char qf[20];
+ char qf[MAXQFNAME];
/* find a unique id */
if (pid != getpid())
@@ -2100,10 +2177,8 @@ queuename(e, type)
printf(" lockfd=");
dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
}
-# ifdef LOG
if (LogLevel > 93)
- syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
}
if (type == '\0')
@@ -2144,10 +2219,8 @@ unlockqueue(e)
return;
/* remove the transcript */
-# ifdef LOG
if (LogLevel > 87)
- syslog(LOG_DEBUG, "%s: unlock", e->e_id);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "unlock");
if (!tTd(51, 104))
xunlink(queuename(e, 'x'));
@@ -2252,7 +2325,7 @@ loseqfile(e, why)
char *why;
{
char *p;
- char buf[40];
+ char buf[MAXQFNAME];
if (e == NULL || e->e_id == NULL)
return;
@@ -2262,8 +2335,7 @@ loseqfile(e, why)
p = queuename(e, 'Q');
if (rename(buf, p) < 0)
syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
-#ifdef LOG
else if (LogLevel > 0)
- syslog(LOG_ALERT, "Losing %s: %s", buf, why);
-#endif
+ sm_syslog(LOG_ALERT, e->e_id,
+ "Losing %s: %s", buf, why);
}