diff options
Diffstat (limited to 'contrib/sendmail/src/queue.c')
-rw-r--r-- | contrib/sendmail/src/queue.c | 136 |
1 files changed, 68 insertions, 68 deletions
diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c index 26e73f0..a0ce797 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.863.2.6 2002/08/16 16:27:37 gshapiro Exp $") +SM_RCSID("@(#)$Id: queue.c,v 8.863.2.22 2002/12/19 18:00:39 ca Exp $") #include <dirent.h> @@ -27,8 +27,10 @@ SM_RCSID("@(#)$Id: queue.c,v 8.863.2.6 2002/08/16 16:27:37 gshapiro Exp $") /* ** Historical notes: -** QF_VERSION==4 was sendmail 8.10/8.11 without _FFR_QUEUEDELAY -** QF_VERSION==5 was sendmail 8.10/8.11 with _FFR_QUEUEDELAY +** QF_VERSION == 4 was sendmail 8.10/8.11 without _FFR_QUEUEDELAY +** QF_VERSION == 5 was sendmail 8.10/8.11 with _FFR_QUEUEDELAY +** QF_VERSION == 6 is sendmail 8.12 without _FFR_QUEUEDELAY +** QF_VERSION == 7 is sendmail 8.12 with _FFR_QUEUEDELAY */ #if _FFR_QUEUEDELAY @@ -134,6 +136,7 @@ static int workcmpf1(); static int workcmpf2(); static int workcmpf3(); static int workcmpf4(); +static int randi = 3; /* index for workcmpf5() */ static int workcmpf5(); static int workcmpf6(); #if _FFR_RHS @@ -198,6 +201,7 @@ static void *Pshm; /* pointer to shared memory */ static FILESYS *PtrFileSys; /* pointer to queue file system array */ int ShmId = SM_SHM_NO_ID; /* shared memory id */ static QUEUE_SHM_T *QShm; /* pointer to shared queue data */ +static size_t shms; # define SHM_OFF_PID(p) (((char *) (p)) + sizeof(int)) # define SHM_OFF_TAG(p) (((char *) (p)) + sizeof(pid_t) + sizeof(int)) @@ -255,6 +259,7 @@ hash_q(p, h) return h; } + #else /* SM_CONF_SHM */ # define FILE_SYS(i) FileSys[i] #endif /* SM_CONF_SHM */ @@ -265,6 +270,7 @@ hash_q(p, h) #define FILE_SYS_BLKSIZE(i) FILE_SYS(i).fs_blksize #define FILE_SYS_DEV(i) FILE_SYS(i).fs_dev + /* ** Current qf file field assignments: ** @@ -1200,7 +1206,7 @@ restart_work_group(wgrp) { /* avoid overflow; increment here */ WorkGrp[wgrp].wg_restartcnt++; - (void) run_work_group(wgrp, true, false, true, true); + (void) run_work_group(wgrp, RWG_FORK|RWG_PERSISTENT|RWG_RUNALL); } else { @@ -1438,6 +1444,8 @@ runqueue(forkflag, verbose, persistent, runall) for (i = 0; i < NumWorkGroups && !NoMoreRunners; i++) { + int rwgflags = RWG_NONE; + /* ** If MaxQueueChildren active then test whether the start ** of the next queue group's additional queue runners (maximum) @@ -1477,8 +1485,15 @@ runqueue(forkflag, verbose, persistent, runall) */ CurRunners += WorkGrp[curnum].wg_maxact; - ret = run_work_group(curnum, forkflag, verbose, persistent, - runall); + if (forkflag) + rwgflags |= RWG_FORK; + if (verbose) + rwgflags |= RWG_VERBOSE; + if (persistent) + rwgflags |= RWG_PERSISTENT; + if (runall) + rwgflags |= RWG_RUNALL; + ret = run_work_group(curnum, rwgflags); /* ** Failure means a message was printed for ETRN @@ -1676,7 +1691,7 @@ runner_work(e, sequenceno, didfork, skip, njobs) w->w_name + 2); (void) dowork(w->w_qgrp, w->w_qdir, w->w_name + 2, - false, false, e); + ForkQueueRuns , false, e); errno = 0; } sm_free(w->w_name); /* XXX */ @@ -1711,12 +1726,7 @@ runner_work(e, sequenceno, didfork, skip, njobs) ** ** Parameters: ** wgrp -- work group to process. -** forkflag -- true if the queue scanning should be done in -** a child process. We double-fork so it is not our -** child and we don't have to clean up after it. -** verbose -- if true, print out status information. -** persistent -- persistent queue runner? -** runall -- true: run all of the queue groups in this work group +** flags -- RWG_* flags ** ** Returns: ** true if the queue run successfully began. @@ -1729,12 +1739,9 @@ runner_work(e, sequenceno, didfork, skip, njobs) #define MIN_SLEEP_TIME 5 bool -run_work_group(wgrp, forkflag, verbose, persistent, runall) +run_work_group(wgrp, flags) int wgrp; - bool forkflag; - bool verbose; - bool persistent; - bool runall; + int flags; { register ENVELOPE *e; int njobs, qdir; @@ -1758,11 +1765,12 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) sm_getla(); /* get load average */ current_la_time = curtime(); - if (!persistent && shouldqueue(WkRecipFact, current_la_time)) + if (!bitset(RWG_PERSISTENT, flags) && + shouldqueue(WkRecipFact, current_la_time)) { char *msg = "Skipping queue run -- load average too high"; - if (verbose) + if (bitset(RWG_VERBOSE, flags)) message("458 %s\n", msg); if (LogLevel > 8) sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg); @@ -1773,12 +1781,14 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) ** See if we already have too many children. */ - if (forkflag && WorkGrp[wgrp].wg_lowqintvl > 0 && !persistent && + if (bitset(RWG_FORK, flags) && + WorkGrp[wgrp].wg_lowqintvl > 0 && + !bitset(RWG_PERSISTENT, flags) && MaxChildren > 0 && CurChildren >= MaxChildren) { char *msg = "Skipping queue run -- too many children"; - if (verbose) + if (bitset(RWG_VERBOSE, flags)) message("458 %s (%d)\n", msg, CurChildren); if (LogLevel > 8) sm_syslog(LOG_INFO, NOQID, "runqueue: %s (%d)", @@ -1790,7 +1800,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) ** See if we want to go off and do other useful work. */ - if (forkflag) + if (bitset(RWG_FORK, flags)) { pid_t pid; @@ -1803,7 +1813,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) const char *msg = "Skipping queue run -- fork() failed"; const char *err = sm_errstring(errno); - if (verbose) + if (bitset(RWG_VERBOSE, flags)) message("458 %s: %s\n", msg, err); if (LogLevel > 8) sm_syslog(LOG_INFO, NOQID, "runqueue: %s: %s", @@ -1819,7 +1829,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) /* wgrp only used when queue runners are persistent */ proc_list_add(pid, "Queue runner", PROC_QUEUE, WorkGrp[wgrp].wg_maxact, - persistent ? wgrp : -1); + bitset(RWG_PERSISTENT, flags) ? wgrp : -1); (void) sm_releasesignal(SIGALRM); (void) sm_releasesignal(SIGCHLD); return true; @@ -1876,7 +1886,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) e->e_parent = NULL; /* make sure we have disconnected from parent */ - if (forkflag) + if (bitset(RWG_FORK, flags)) { disconnect(1, e); QuickAbort = false; @@ -1908,7 +1918,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) /* ** Run a queue group if: - ** runall is set or the bit for this group is set. + ** RWG_RUNALL bit is set or the bit for this group is set. */ now = curtime(); @@ -1922,14 +1932,14 @@ 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 || + if (bitset(RWG_RUNALL, flags) || (Queue[qgrp]->qg_nextrun <= now && Queue[qgrp]->qg_nextrun != (time_t) -1)) break; if (endgrp == WorkGrp[wgrp].wg_curqgrp) { e->e_id = NULL; - if (forkflag) + if (bitset(RWG_FORK, flags)) finis(true, true, ExitStat); return true; /* we're done */ } @@ -1958,7 +1968,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) sm_syslog(LOG_DEBUG, NOQID, "runqueue %s, pid=%d, forkflag=%d", qid_printqueue(qgrp, qdir), (int) CurrentPid, - forkflag); + bitset(RWG_FORK, flags)); /* ** Start making passes through the queue. @@ -2015,24 +2025,6 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) maxrunners = njobs; for (loop = 0; loop < maxrunners; loop++) { -#if _FFR_NONSTOP_PERSISTENCE - /* - ** Require a free "slot" before processing - ** this queue runner. - */ - - while (MaxQueueChildren > 0 && - CurChildren > MaxQueueChildren) - { - int status; - pid_t ret; - - while ((ret = sm_wait(&status)) <= 0) - continue; - proc_list_drop(ret, status, NULL); - } -#endif /* _FFR_NONSTOP_PERSISTENCE */ - /* ** Since the delivery may happen in a child and the ** parent does not wait, the parent may close the @@ -2116,7 +2108,6 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) sm_releasesignal(SIGCHLD); -#if !_FFR_NONSTOP_PERSISTENCE /* ** Wait until all of the runners have completed before ** seeing if there is another queue group in the @@ -2135,9 +2126,8 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) continue; proc_list_drop(ret, status, NULL); } -#endif /* !_FFR_NONSTOP_PERSISTENCE */ } - else + else if (Queue[qgrp]->qg_maxqrun > 0 || bitset(RWG_FORCE, flags)) { /* ** When current process will not fork children to do the work, @@ -2162,7 +2152,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) } /* No more queues in work group to process. Now check persistent. */ - if (persistent) + if (bitset(RWG_PERSISTENT, flags)) { sequenceno = 1; sm_setproctitle(true, CurEnv, "running queue: %s", @@ -2244,7 +2234,7 @@ run_work_group(wgrp, forkflag, verbose, persistent, runall) /* exit without the usual cleanup */ e->e_id = NULL; - if (forkflag) + if (bitset(RWG_FORK, flags)) finis(true, true, ExitStat); /* NOTREACHED */ return true; @@ -2918,12 +2908,14 @@ sortq(max) else if (QueueSortOrder == QSO_RANDOM) { /* - ** Sort randomly. - ** workcmpf5() returns a random 1 or -1. - ** As long as nobody does a verification pass over the - ** sorted list, we should be golden. + ** Sort randomly. To avoid problems with an instable sort, + ** use a random index into the queue file name to start + ** comparison. */ + randi = get_rand_mod(MAXQFNAME); + if (randi < 2) + randi = 3; qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf5); } else if (QueueSortOrder == QSO_BYMODTIME) @@ -3226,7 +3218,9 @@ workcmpf5(a, b) register WORK *a; register WORK *b; { - return (get_rand_mod(2)) ? 1 : -1; + if (strlen(a->w_name) < randi || strlen(b->w_name) < randi) + return -1; + return a->w_name[randi] - b->w_name[randi]; } /* ** WORKCMPF6 -- simple modification-time-only compare function. @@ -3452,6 +3446,7 @@ dowork(qgrp, qdir, id, forkflag, requeueflag, e) ** handler for child process. */ + /* Reset global flags */ RestartRequest = NULL; RestartWorkGroup = false; @@ -3638,6 +3633,7 @@ doworklist(el, forkflag, requeueflag) ** handler for child process. */ + /* Reset global flags */ RestartRequest = NULL; RestartWorkGroup = false; @@ -6476,7 +6472,7 @@ write_key_file(keypath, key) 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); + keyf = safefopen(keypath, O_WRONLY|O_TRUNC, FileMode, sff); if (keyf == NULL) { sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s", @@ -6486,7 +6482,7 @@ write_key_file(keypath, key) { 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); + ok = (sm_io_close(keyf, SM_TIME_DEFAULT) != SM_IO_EOF) && ok; } return ok; } @@ -6514,9 +6510,9 @@ read_key_file(keypath, key) if (keypath == NULL || *keypath == '\0') return key; sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY; - if (TrustedUid != 0 && RealUid == TrustedUid) + if (RealUid == 0 || (TrustedUid != 0 && RealUid == TrustedUid)) sff |= SFF_OPENASROOT; - keyf = safefopen(keypath, O_RDONLY, 0644, sff); + keyf = safefopen(keypath, O_RDONLY, FileMode, sff); if (keyf == NULL) { sm_syslog(LOG_ERR, NOQID, "unable to read %s: %s", @@ -6577,7 +6573,6 @@ init_shm(qn, owner, hash) { int count; int save_errno; - size_t shms; count = 0; shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T); @@ -8012,6 +8007,8 @@ split_within_queue(e) e->e_sibling = firstsibling; for (i = 0; i < nrcpt - 1; ++i) addrs[i]->q_next = addrs[i + 1]; + if (lsplits != NULL) + sm_free(lsplits); return SM_SPLIT_FAIL; } @@ -8054,12 +8051,15 @@ split_within_queue(e) break; i += maxrcpt; } - if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL && nsplit > 0) + if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) { - sm_syslog(LOG_NOTICE, e->e_id, - "split: maxrcpts=%d, rcpts=%d, count=%d, id%s=%s", - maxrcpt, nrcpt - ndead, nsplit, - nsplit > 1 ? "s" : "", lsplits); + if (nsplit > 0) + { + sm_syslog(LOG_NOTICE, e->e_id, + "split: maxrcpts=%d, rcpts=%d, count=%d, id%s=%s", + maxrcpt, nrcpt - ndead, nsplit, + nsplit > 1 ? "s" : "", lsplits); + } sm_free(lsplits); } return SM_SPLIT_NEW(nsplit); |