diff options
author | Peter Wemm <peter@FreeBSD.org> | 1997-06-27 14:53:01 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 1997-06-27 14:53:01 +0000 |
commit | f3a1fc342b4423150f71e23e50f24d073a6d238b (patch) | |
tree | a5e7dee2f9ff41f2d43580f859a6e8970722fa7d /usr.sbin/sendmail/src/queue.c | |
parent | 52c4d6f5d6bb1ffd8b30c0429fc18d371856a062 (diff) |
Notes
Diffstat (limited to 'usr.sbin/sendmail/src/queue.c')
-rw-r--r-- | usr.sbin/sendmail/src/queue.c | 242 |
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); } |