2 * Copyright (c) 1998-2009, 2011, 2012, 2014 Proofpoint, Inc. and its suppliers.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
17 SM_RCSID("@(#)$Id: queue.c,v 8.1000 2013-11-22 20:51:56 ca Exp $")
21 # define RELEASE_QUEUE (void) 0
22 # define ST_INODE(st) (st).st_ino
24 # define sm_file_exists(errno) ((errno) == EEXIST)
26 # if HASFLOCK && defined(O_EXLOCK)
27 # define SM_OPEN_EXLOCK 1
28 # define TF_OPEN_FLAGS (O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK)
30 # define TF_OPEN_FLAGS (O_CREAT|O_WRONLY|O_EXCL)
33 #ifndef SM_OPEN_EXLOCK
34 # define SM_OPEN_EXLOCK 0
39 ** QF_VERSION == 4 was sendmail 8.10/8.11 without _FFR_QUEUEDELAY
40 ** QF_VERSION == 5 was sendmail 8.10/8.11 with _FFR_QUEUEDELAY
41 ** QF_VERSION == 6 was sendmail 8.12 without _FFR_QUEUEDELAY
42 ** QF_VERSION == 7 was sendmail 8.12 with _FFR_QUEUEDELAY
43 ** QF_VERSION == 8 is sendmail 8.13
46 #define QF_VERSION 8 /* version number of this queue format */
48 static char queue_letter __P((ENVELOPE *, int));
49 static bool quarantine_queue_item __P((int, int, ENVELOPE *, char *));
51 /* Naming convention: qgrp: index of queue group, qg: QUEUEGROUP */
59 char *w_name; /* name of control file */
60 char *w_host; /* name of recipient host */
61 bool w_lock; /* is message locked? */
62 bool w_tooyoung; /* is it too young to run? */
63 long w_pri; /* priority of message, see below */
64 time_t w_ctime; /* creation time */
65 time_t w_mtime; /* modification time */
66 int w_qgrp; /* queue group located in */
67 int w_qdir; /* queue directory located in */
68 struct work *w_next; /* next in queue */
71 typedef struct work WORK;
73 static WORK *WorkQ; /* queue of things to be done */
74 static int NumWorkGroups; /* number of work groups */
75 static time_t Current_LA_time = 0;
77 /* Get new load average every 30 seconds. */
78 #define GET_NEW_LA_TIME 30
80 #define SM_GET_LA(now) \
84 if (Current_LA_time < now - GET_NEW_LA_TIME) \
87 Current_LA_time = now; \
92 ** DoQueueRun indicates that a queue run is needed.
93 ** Notice: DoQueueRun is modified in a signal handler!
96 static bool volatile DoQueueRun; /* non-interrupt time queue run needed */
99 ** Work group definition structure.
100 ** Each work group contains one or more queue groups. This is done
101 ** to manage the number of queue group runners active at the same time
102 ** to be within the constraints of MaxQueueChildren (if it is set).
103 ** The number of queue groups that can be run on the next work run
104 ** is kept track of. The queue groups are run in a round robin.
109 int wg_numqgrp; /* number of queue groups in work grp */
110 int wg_runners; /* total runners */
111 int wg_curqgrp; /* current queue group */
112 QUEUEGRP **wg_qgs; /* array of queue groups */
113 int wg_maxact; /* max # of active runners */
114 time_t wg_lowqintvl; /* lowest queue interval */
115 int wg_restart; /* needs restarting? */
116 int wg_restartcnt; /* count of times restarted */
119 typedef struct workgrp WORKGRP;
121 static WORKGRP volatile WorkGrp[MAXWORKGROUPS + 1]; /* work groups */
124 static SM_DEBUG_T DebugLeakQ = SM_DEBUG_INITIALIZER("leak_q",
125 "@(#)$Debug: leak_q - trace memory leaks during queue processing $");
128 static void grow_wlist __P((int, int));
129 static int multiqueue_cache __P((char *, int, QUEUEGRP *, int, unsigned int *));
130 static int gatherq __P((int, int, bool, bool *, bool *, int *));
131 static int sortq __P((int));
132 static void printctladdr __P((ADDRESS *, SM_FILE_T *));
133 static bool readqf __P((ENVELOPE *, bool));
134 static void restart_work_group __P((int));
135 static void runner_work __P((ENVELOPE *, int, bool, int, int));
136 static void schedule_queue_runs __P((bool, int, bool));
137 static char *strrev __P((char *));
138 static ADDRESS *setctluser __P((char *, int, ENVELOPE *));
140 static int sm_strshufflecmp __P((char *, char *));
141 static void init_shuffle_alphabet __P(());
145 ** Note: workcmpf?() don't use a prototype because it will cause a conflict
146 ** with the qsort() call (which expects something like
147 ** int (*compar)(const void *, const void *), not (WORK *, WORK *))
150 static int workcmpf0();
151 static int workcmpf1();
152 static int workcmpf2();
153 static int workcmpf3();
154 static int workcmpf4();
155 static int randi = 3; /* index for workcmpf5() */
156 static int workcmpf5();
157 static int workcmpf6();
159 static int workcmpf7();
163 # define get_rand_mod(m) ((get_random() >> RANDOMSHIFT) % (m))
165 # define get_rand_mod(m) (get_random() % (m))
169 ** File system definition.
170 ** Used to keep track of how much free space is available
171 ** on a file system in which one or more queue directories reside.
174 typedef struct filesys_shared FILESYS;
176 struct filesys_shared
178 dev_t fs_dev; /* unique device id */
179 long fs_avail; /* number of free blocks available */
180 long fs_blksize; /* block size, in bytes */
183 /* probably kept in shared memory */
184 static FILESYS FileSys[MAXFILESYS]; /* queue file systems */
185 static const char *FSPath[MAXFILESYS]; /* pathnames for file systems */
188 # include <ratectrl.h>
191 ** Shared memory data
194 ** size -- size of shared memory segment
195 ** pid -- pid of owner, should be a unique id to avoid misinterpretations
196 ** by other processes.
197 ** tag -- should be a unique id to avoid misinterpretations by others.
198 ** idea: hash over configuration data that will be stored here.
199 ** NumFileSys -- number of file systems.
200 ** FileSys -- (array of) structure for used file systems.
201 ** RSATmpCnt -- counter for number of uses of ephemeral RSA key.
203 ** QShm -- (array of) structure for information about queue directories.
204 ** this must be last as the size is depending on the config.
208 ** Queue data in shared memory
211 typedef struct queue_shared QUEUE_SHM_T;
215 int qs_entries; /* number of entries */
216 /* XXX more to follow? */
219 static void *Pshm; /* pointer to shared memory */
220 static FILESYS *PtrFileSys; /* pointer to queue file system array */
221 int ShmId = SM_SHM_NO_ID; /* shared memory id */
222 static QUEUE_SHM_T *QShm; /* pointer to shared queue data */
225 # define SHM_OFF_PID(p) (((char *) (p)) + sizeof(int))
226 # define SHM_OFF_TAG(p) (((char *) (p)) + sizeof(pid_t) + sizeof(int))
227 # define SHM_OFF_HEAD (sizeof(pid_t) + sizeof(int) * 2)
229 /* how to access FileSys */
230 # define FILE_SYS(i) (PtrFileSys[i])
232 /* first entry is a tag, for now just the size */
233 # define OFF_FILE_SYS(p) (((char *) (p)) + SHM_OFF_HEAD)
235 /* offset for PNumFileSys */
236 # define OFF_NUM_FILE_SYS(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys))
238 /* offset for PRSATmpCnt */
239 # define OFF_RSA_TMP_CNT(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int))
243 # define OFF_OCC_SHM(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2)
244 # define OCC_SIZE (sizeof(CHash_T) * CPMHSIZE)
245 static CHash_T *occ = NULL;
250 /* offset for queue_shm */
251 # define OFF_QUEUE_SHM(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2 + OCC_SIZE)
253 # define QSHM_ENTRIES(i) QShm[i].qs_entries
255 /* basic size of shared memory segment */
256 # define SM_T_SIZE (SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2 + OCC_SIZE)
258 static unsigned int hash_q __P((char *, unsigned int));
261 ** HASH_Q -- simple hash function
264 ** p -- string to hash.
265 ** h -- hash start value (from previous run).
283 h += (c<<11) ^ (c>>1);
284 h ^= (d<<14) + (d<<7) + (d<<4) + d;
289 #else /* SM_CONF_SHM */
290 # define FILE_SYS(i) FileSys[i]
291 #endif /* SM_CONF_SHM */
293 /* access to the various components of file system data */
294 #define FILE_SYS_NAME(i) FSPath[i]
295 #define FILE_SYS_AVAIL(i) FILE_SYS(i).fs_avail
296 #define FILE_SYS_BLKSIZE(i) FILE_SYS(i).fs_blksize
297 #define FILE_SYS_DEV(i) FILE_SYS(i).fs_dev
301 ** Current qf file field assignments:
305 ** C controlling user
306 ** D data file name (obsolete)
307 ** d data file directory name (added in 8.12)
311 ** I data file's inode number
312 ** K time of last delivery attempt
313 ** L Solaris Content-Length: header (obsolete)
315 ** N number of delivery attempts
316 ** P message priority
317 ** q quarantine reason
318 ** Q original recipient (ORCPT=)
319 ** r final recipient (Final-Recipient: DSN field)
323 ** V queue file version
324 ** X free (was: character set if _FFR_SAVE_CHARSET)
325 ** Z original envelope id from ESMTP
326 ** ! deliver by (added in 8.12)
332 ** QUEUEUP -- queue a message up for future transmission.
335 ** e -- the envelope to queue up.
336 ** announce -- if true, tell when you are queueing up.
337 ** msync -- if true, then fsync() if SuperSafe interactive mode.
343 ** The current request is saved in a control file.
344 ** The queue file is left locked.
348 queueup(e, announce, msync)
349 register ENVELOPE *e;
353 register SM_FILE_T *tfp;
368 ** Create control file.
373 MODE_T oldumask = 0; \
375 if (bitset(S_IWGRP, QueueFileMode)) \
376 oldumask = umask(002); \
377 tfd = open(tf, TF_OPEN_FLAGS, QueueFileMode); \
378 if (bitset(S_IWGRP, QueueFileMode)) \
379 (void) umask(oldumask); \
383 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
384 (void) sm_strlcpy(tf, queuename(e, NEWQFL_LETTER), sizeof(tf));
386 if (tfp == NULL && newid)
389 ** open qf file directly: this will give an error if the file
390 ** already exists and hence prevent problems if a queue-id
391 ** is reused (e.g., because the clock is set back).
394 (void) sm_strlcpy(tf, queuename(e, ANYQFL_LETTER), sizeof(tf));
398 !lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB) ||
400 (tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
401 (void *) &tfd, SM_IO_WRONLY,
404 int save_errno = errno;
408 syserr("!queueup: cannot create queue file %s, euid=%ld, fd=%d, fp=%p",
409 tf, (long) geteuid(), tfd, (void *)tfp);
413 upd_qs(e, 1, 0, "queueup");
416 /* if newid, write the queue file directly (instead of temp file) */
419 /* get a locked tf file */
420 for (i = 0; i < 128; i++)
429 if (LogLevel > 0 && (i % 32) == 0)
430 sm_syslog(LOG_ALERT, e->e_id,
431 "queueup: cannot create %s, euid=%ld: %s",
432 tf, (long) geteuid(),
433 sm_errstring(errno));
443 /* file is locked by open() */
446 if (lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB))
450 if (LogLevel > 0 && (i % 32) == 0)
451 sm_syslog(LOG_ALERT, e->e_id,
452 "queueup: cannot lock %s: %s",
453 tf, sm_errstring(errno));
463 /* save the old temp file away */
464 (void) rename(tf, queuename(e, TEMPQF_LETTER));
467 (void) sleep(i % 32);
469 if (tfd < 0 || (tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
470 (void *) &tfd, SM_IO_WRONLY_B,
473 int save_errno = errno;
477 syserr("!queueup: cannot create queue temp file %s, uid=%ld",
478 tf, (long) geteuid());
483 sm_dprintf("\n>>>>> queueing %s/%s%s >>>>>\n",
484 qid_printqueue(e->e_qgrp, e->e_qdir),
485 queuename(e, ANYQFL_LETTER),
486 newid ? " (new id)" : "");
489 sm_dprintf(" e_flags=");
494 sm_dprintf(" sendq=");
495 printaddr(sm_debug_file(), e->e_sendqueue, true);
500 dumpfd(sm_io_getinfo(tfp, SM_IO_WHAT_FD, NULL), true, false);
501 sm_dprintf(" lockfp=");
502 if (e->e_lockfp == NULL)
503 sm_dprintf("NULL\n");
505 dumpfd(sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL),
510 ** If there is no data file yet, create one.
513 (void) sm_strlcpy(df, queuename(e, DATAFL_LETTER), sizeof(df));
514 if (bitset(EF_HAS_DF, e->e_flags))
516 if (e->e_dfp != NULL &&
517 SuperSafe != SAFE_REALLY &&
518 SuperSafe != SAFE_REALLY_POSTMILTER &&
519 sm_io_setinfo(e->e_dfp, SM_BF_COMMIT, NULL) < 0 &&
522 syserr("!queueup: cannot commit data file %s, uid=%ld",
523 queuename(e, DATAFL_LETTER), (long) geteuid());
525 if (e->e_dfp != NULL &&
526 SuperSafe == SAFE_INTERACTIVE && msync)
529 sm_syslog(LOG_INFO, e->e_id,
530 "queueup: fsync(e->e_dfp)");
532 if (fsync(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD,
536 syserr("!552 Error writing data file %s",
539 syserr("!452 Error writing data file %s",
548 register SM_FILE_T *dfp = NULL;
551 if (e->e_dfp != NULL &&
552 sm_io_getinfo(e->e_dfp, SM_IO_WHAT_ISTYPE, BF_FILE_TYPE))
553 syserr("committing over bf file");
555 if (bitset(S_IWGRP, QueueFileMode))
556 oldumask = umask(002);
557 dfd = open(df, O_WRONLY|O_CREAT|O_TRUNC|QF_O_EXTRA,
559 if (bitset(S_IWGRP, QueueFileMode))
560 (void) umask(oldumask);
561 if (dfd < 0 || (dfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
562 (void *) &dfd, SM_IO_WRONLY_B,
564 syserr("!queueup: cannot create data temp file %s, uid=%ld",
565 df, (long) geteuid());
566 if (fstat(dfd, &stbuf) < 0)
570 e->e_dfdev = stbuf.st_dev;
571 e->e_dfino = ST_INODE(stbuf);
573 e->e_flags |= EF_HAS_DF;
574 memset(&mcibuf, '\0', sizeof(mcibuf));
575 mcibuf.mci_out = dfp;
576 mcibuf.mci_mailer = FileMailer;
577 (*e->e_putbody)(&mcibuf, e, NULL);
579 if (SuperSafe == SAFE_REALLY ||
580 SuperSafe == SAFE_REALLY_POSTMILTER ||
581 (SuperSafe == SAFE_INTERACTIVE && msync))
584 sm_syslog(LOG_INFO, e->e_id,
585 "queueup: fsync(dfp)");
587 if (fsync(sm_io_getinfo(dfp, SM_IO_WHAT_FD, NULL)) < 0)
590 syserr("!552 Error writing data file %s",
593 syserr("!452 Error writing data file %s",
598 if (sm_io_close(dfp, SM_TIME_DEFAULT) < 0)
599 syserr("!queueup: cannot save data temp file %s, uid=%ld",
600 df, (long) geteuid());
601 e->e_putbody = putbody;
605 ** Output future work requests.
606 ** Priority and creation time should be first, since
607 ** they are required by gatherq.
610 /* output queue version number (must be first!) */
611 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "V%d\n", QF_VERSION);
613 /* output creation time */
614 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "T%ld\n", (long) e->e_ctime);
616 /* output last delivery time */
617 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "K%ld\n", (long) e->e_dtime);
619 /* output number of delivery attempts */
620 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "N%d\n", e->e_ntries);
622 /* output message priority */
623 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "P%ld\n", e->e_msgpriority);
626 ** If data file is in a different directory than the queue file,
627 ** output a "d" record naming the directory of the data file.
630 if (e->e_dfqgrp != e->e_qgrp)
632 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "d%s\n",
633 Queue[e->e_dfqgrp]->qg_qpaths[e->e_dfqdir].qp_name);
636 /* output inode number of data file */
637 if (e->e_dfino != -1)
639 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "I%ld/%ld/%llu\n",
640 (long) major(e->e_dfdev),
641 (long) minor(e->e_dfdev),
642 (ULONGLONG_T) e->e_dfino);
645 /* output body type */
646 if (e->e_bodytype != NULL)
647 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "B%s\n",
648 denlstring(e->e_bodytype, true, false));
650 /* quarantine reason */
651 if (e->e_quarmsg != NULL)
652 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "q%s\n",
653 denlstring(e->e_quarmsg, true, false));
655 /* message from envelope, if it exists */
656 if (e->e_message != NULL)
657 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "M%s\n",
658 denlstring(e->e_message, true, false));
660 /* send various flag bits through */
662 if (bitset(EF_WARNING, e->e_flags))
664 if (bitset(EF_RESPONSE, e->e_flags))
666 if (bitset(EF_HAS8BIT, e->e_flags))
668 if (bitset(EF_DELETE_BCC, e->e_flags))
670 if (bitset(EF_RET_PARAM, e->e_flags))
672 if (bitset(EF_NO_BODY_RETN, e->e_flags))
674 if (bitset(EF_SPLIT, e->e_flags))
682 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "F%s\n", buf);
684 /* save $={persistentMacros} macro values */
685 queueup_macros(macid("{persistentMacros}"), tfp, e);
687 /* output name of sender */
688 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
691 p = e->e_from.q_paddr;
692 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "S%s\n",
693 denlstring(p, true, false));
695 /* output ESMTP-supplied "original" information */
696 if (e->e_envid != NULL)
697 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "Z%s\n",
698 denlstring(e->e_envid, true, false));
700 /* output AUTH= parameter */
701 if (e->e_auth_param != NULL)
702 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "A%s\n",
703 denlstring(e->e_auth_param, true, false));
704 if (e->e_dlvr_flag != 0)
705 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "!%c %ld\n",
706 (char) e->e_dlvr_flag, e->e_deliver_by);
708 /* output list of recipient addresses */
709 printctladdr(NULL, NULL);
710 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
712 q->q_flags &= ~QQUEUED;
713 if (!QS_IS_UNDELIVERED(q->q_state))
716 /* message for this recipient, if it exists */
717 if (q->q_message != NULL)
718 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "M%s\n",
719 denlstring(q->q_message, true,
722 printctladdr(q, tfp);
723 if (q->q_orcpt != NULL)
724 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "Q%s\n",
725 denlstring(q->q_orcpt, true,
727 if (q->q_finalrcpt != NULL)
728 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "r%s\n",
729 denlstring(q->q_finalrcpt, true,
731 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'R');
732 if (bitset(QPRIMARY, q->q_flags))
733 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'P');
734 if (bitset(QHASNOTIFY, q->q_flags))
735 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'N');
736 if (bitset(QPINGONSUCCESS, q->q_flags))
737 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'S');
738 if (bitset(QPINGONFAILURE, q->q_flags))
739 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'F');
740 if (bitset(QPINGONDELAY, q->q_flags))
741 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'D');
742 if (bitset(QINTBCC, q->q_flags))
743 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'B');
744 if (q->q_alias != NULL &&
745 bitset(QALIAS, q->q_alias->q_flags))
746 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'A');
749 if (bitset(QDYNMAILER, q->q_flags))
750 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, QDYNMAILFLG);
751 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, ':');
752 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s\n",
753 denlstring(q->q_paddr, true, false));
756 char *tag = "queued";
758 if (e->e_quarmsg != NULL)
761 e->e_to = q->q_paddr;
764 logdelivery(q->q_mailer, NULL, q->q_status,
765 tag, NULL, (time_t) 0, e, q, EX_OK);
770 ** This is only "valid" when the msg is safely in the queue,
771 ** i.e., EF_INQUEUE needs to be set.
774 q->q_flags |= QQUEUED;
778 sm_dprintf("queueing ");
779 printaddr(sm_debug_file(), q, false);
784 ** Output headers for this message.
785 ** Expand macros completely here. Queue run will deal with
786 ** everything as absolute headers.
787 ** All headers that must be relative to the recipient
788 ** can be cracked later.
789 ** We set up a "null mailer" -- i.e., a mailer that will have
790 ** no effect on the addresses as they are output.
793 memset((char *) &nullmailer, '\0', sizeof(nullmailer));
794 nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
795 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
796 nullmailer.m_eol = "\n";
797 memset(&mcibuf, '\0', sizeof(mcibuf));
798 mcibuf.mci_mailer = &nullmailer;
799 mcibuf.mci_out = tfp;
801 macdefine(&e->e_macro, A_PERM, 'g', "\201f");
802 for (h = e->e_header; h != NULL; h = h->h_link)
804 if (h->h_value == NULL)
807 /* don't output resent headers on non-resent messages */
808 if (bitset(H_RESENT, h->h_flags) &&
809 !bitset(EF_RESENT, e->e_flags))
812 /* expand macros; if null, don't output header at all */
813 if (bitset(H_DEFAULT, h->h_flags))
815 (void) expand(h->h_value, buf, sizeof(buf), e);
818 if (buf[0] == ' ' && buf[1] == '\0')
822 /* output this header */
823 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "H?");
825 /* output conditional macro if present */
826 if (h->h_macro != '\0')
828 if (bitset(0200, h->h_macro))
829 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT,
831 macname(bitidx(h->h_macro)));
833 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT,
836 else if (!bitzerop(h->h_mflags) &&
837 bitset(H_CHECK|H_ACHECK, h->h_flags))
841 /* if conditional, output the set of conditions */
842 for (j = '\0'; j <= '\177'; j++)
843 if (bitnset(j, h->h_mflags))
844 (void) sm_io_putc(tfp, SM_TIME_DEFAULT,
847 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, '?');
849 /* output the header: expand macros, convert addresses */
850 if (bitset(H_DEFAULT, h->h_flags) &&
851 !bitset(H_BINDLATE, h->h_flags))
853 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s:%s\n",
855 denlstring(buf, false, true));
857 else if (bitset(H_FROM|H_RCPT, h->h_flags) &&
858 !bitset(H_BINDLATE, h->h_flags))
860 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
861 SM_FILE_T *savetrace = TrafficLogFile;
863 TrafficLogFile = NULL;
865 if (bitset(H_FROM, h->h_flags))
867 commaize(h, h->h_value, oldstyle, &mcibuf, e,
870 TrafficLogFile = savetrace;
874 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s:%s\n",
876 denlstring(h->h_value, false,
884 ** Write a terminator record -- this is to prevent
885 ** scurrilous crackers from appending any data.
888 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, ".\n");
890 if (sm_io_flush(tfp, SM_TIME_DEFAULT) != 0 ||
891 ((SuperSafe == SAFE_REALLY ||
892 SuperSafe == SAFE_REALLY_POSTMILTER ||
893 (SuperSafe == SAFE_INTERACTIVE && msync)) &&
894 fsync(sm_io_getinfo(tfp, SM_IO_WHAT_FD, NULL)) < 0) ||
898 syserr("!552 Error writing control file %s", tf);
900 syserr("!452 Error writing control file %s", tf);
905 char new = queue_letter(e, ANYQFL_LETTER);
907 /* rename (locked) tf to be (locked) [qh]f */
908 (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER),
910 if (rename(tf, qf) < 0)
911 syserr("cannot rename(%s, %s), uid=%ld",
912 tf, qf, (long) geteuid());
916 ** Check if type has changed and only
917 ** remove the old item if the rename above
921 if (e->e_qfletter != '\0' &&
922 e->e_qfletter != new)
926 sm_dprintf("type changed from %c to %c\n",
930 if (unlink(queuename(e, e->e_qfletter)) < 0)
932 /* XXX: something more drastic? */
934 sm_syslog(LOG_ERR, e->e_id,
935 "queueup: unlink(%s) failed: %s",
936 queuename(e, e->e_qfletter),
937 sm_errstring(errno));
944 ** fsync() after renaming to make sure metadata is
945 ** written to disk on filesystems in which renames are
949 if (SuperSafe != SAFE_NO)
951 /* for softupdates */
952 if (tfd >= 0 && fsync(tfd) < 0)
954 syserr("!queueup: cannot fsync queue temp file %s",
960 /* close and unlock old (locked) queue file */
961 if (e->e_lockfp != NULL)
962 (void) sm_io_close(e->e_lockfp, SM_TIME_DEFAULT);
967 sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", qf);
973 sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", tf);
975 e->e_qfletter = queue_letter(e, ANYQFL_LETTER);
979 e->e_flags |= EF_INQUEUE;
982 sm_dprintf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
987 ** PRINTCTLADDR -- print control address to file.
991 ** tfp -- file pointer.
997 ** The control address (if changed) is printed to the file.
998 ** The last control address and uid are saved.
1002 printctladdr(a, tfp)
1003 register ADDRESS *a;
1007 register ADDRESS *q;
1010 static ADDRESS *lastctladdr = NULL;
1011 static uid_t lastuid;
1013 /* initialization */
1014 if (a == NULL || a->q_alias == NULL || tfp == NULL)
1016 if (lastctladdr != NULL && tfp != NULL)
1017 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C\n");
1023 /* find the active uid */
1033 user = q->q_ruser != NULL ? q->q_ruser : q->q_user;
1039 /* check to see if this is the same as last time */
1040 if (lastctladdr != NULL && uid == lastuid &&
1041 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0)
1046 if (uid == 0 || user == NULL || user[0] == '\0')
1047 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C");
1049 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C%s:%ld:%ld",
1050 denlstring(user, true, false), (long) uid,
1052 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, ":%s\n",
1053 denlstring(a->q_paddr, true, false));
1057 ** RUNNERS_SIGTERM -- propagate a SIGTERM to queue runner process
1059 ** This propagates the signal to the child processes that are queue
1060 ** runners. This is for a queue runner "cleanup". After all of the
1061 ** child queue runner processes are signaled (it should be SIGTERM
1062 ** being the sig) then the old signal handler (Oldsh) is called
1063 ** to handle any cleanup set for this process (provided it is not
1064 ** SIG_DFL or SIG_IGN). The signal may not be handled immediately
1065 ** if the BlockOldsh flag is set. If the current process doesn't
1066 ** have a parent then handle the signal immediately, regardless of
1070 ** sig -- the signal number being sent
1076 ** Sets the NoMoreRunners boolean to true to stop more runners
1077 ** from being started in runqueue().
1079 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
1080 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1084 static bool volatile NoMoreRunners = false;
1085 static sigfunc_t Oldsh_term = SIG_DFL;
1086 static sigfunc_t Oldsh_hup = SIG_DFL;
1087 static sigfunc_t volatile Oldsh = SIG_DFL;
1088 static bool BlockOldsh = false;
1089 static int volatile Oldsig = 0;
1090 static SIGFUNC_DECL runners_sigterm __P((int));
1091 static SIGFUNC_DECL runners_sighup __P((int));
1094 runners_sigterm(sig)
1097 int save_errno = errno;
1099 FIX_SYSV_SIGNAL(sig, runners_sigterm);
1101 CHECK_CRITICAL(sig);
1102 NoMoreRunners = true;
1105 proc_list_signal(PROC_QUEUE, sig);
1107 if (!BlockOldsh || getppid() <= 1)
1109 /* Check that a valid 'old signal handler' is callable */
1110 if (Oldsh_term != SIG_DFL && Oldsh_term != SIG_IGN &&
1111 Oldsh_term != runners_sigterm)
1115 return SIGFUNC_RETURN;
1118 ** RUNNERS_SIGHUP -- propagate a SIGHUP to queue runner process
1120 ** This propagates the signal to the child processes that are queue
1121 ** runners. This is for a queue runner "cleanup". After all of the
1122 ** child queue runner processes are signaled (it should be SIGHUP
1123 ** being the sig) then the old signal handler (Oldsh) is called to
1124 ** handle any cleanup set for this process (provided it is not SIG_DFL
1125 ** or SIG_IGN). The signal may not be handled immediately if the
1126 ** BlockOldsh flag is set. If the current process doesn't have
1127 ** a parent then handle the signal immediately, regardless of
1131 ** sig -- the signal number being sent
1137 ** Sets the NoMoreRunners boolean to true to stop more runners
1138 ** from being started in runqueue().
1140 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
1141 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1149 int save_errno = errno;
1151 FIX_SYSV_SIGNAL(sig, runners_sighup);
1153 CHECK_CRITICAL(sig);
1154 NoMoreRunners = true;
1157 proc_list_signal(PROC_QUEUE, sig);
1159 if (!BlockOldsh || getppid() <= 1)
1161 /* Check that a valid 'old signal handler' is callable */
1162 if (Oldsh_hup != SIG_DFL && Oldsh_hup != SIG_IGN &&
1163 Oldsh_hup != runners_sighup)
1167 return SIGFUNC_RETURN;
1170 ** MARK_WORK_GROUP_RESTART -- mark a work group as needing a restart
1172 ** Sets a workgroup for restarting.
1175 ** wgrp -- the work group id to restart.
1176 ** reason -- why (signal?), -1 to turn off restart
1182 ** May set global RestartWorkGroup to true.
1184 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
1185 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1190 mark_work_group_restart(wgrp, reason)
1194 if (wgrp < 0 || wgrp > NumWorkGroups)
1197 WorkGrp[wgrp].wg_restart = reason;
1199 RestartWorkGroup = true;
1202 ** RESTART_MARKED_WORK_GROUPS -- restart work groups marked as needing restart
1204 ** Restart any workgroup marked as needing a restart provided more
1205 ** runners are allowed.
1214 ** Sets global RestartWorkGroup to false.
1218 restart_marked_work_groups()
1226 /* Block SIGCHLD so reapchild() doesn't mess with us */
1227 wasblocked = sm_blocksignal(SIGCHLD);
1229 for (i = 0; i < NumWorkGroups; i++)
1231 if (WorkGrp[i].wg_restart >= 0)
1234 sm_syslog(LOG_ERR, NOQID,
1235 "restart queue runner=%d due to signal 0x%x",
1236 i, WorkGrp[i].wg_restart);
1237 restart_work_group(i);
1240 RestartWorkGroup = false;
1242 if (wasblocked == 0)
1243 (void) sm_releasesignal(SIGCHLD);
1246 ** RESTART_WORK_GROUP -- restart a specific work group
1248 ** Restart a specific workgroup provided more runners are allowed.
1249 ** If the requested work group has been restarted too many times log
1250 ** this and refuse to restart.
1253 ** wgrp -- the work group id to restart
1259 ** starts another process doing the work of wgrp
1262 #define MAX_PERSIST_RESTART 10 /* max allowed number of restarts */
1265 restart_work_group(wgrp)
1268 if (NoMoreRunners ||
1269 wgrp < 0 || wgrp > NumWorkGroups)
1272 WorkGrp[wgrp].wg_restart = -1;
1273 if (WorkGrp[wgrp].wg_restartcnt < MAX_PERSIST_RESTART)
1275 /* avoid overflow; increment here */
1276 WorkGrp[wgrp].wg_restartcnt++;
1277 (void) run_work_group(wgrp, RWG_FORK|RWG_PERSISTENT|RWG_RUNALL);
1281 sm_syslog(LOG_ERR, NOQID,
1282 "ERROR: persistent queue runner=%d restarted too many times, queue runner lost",
1287 ** SCHEDULE_QUEUE_RUNS -- schedule the next queue run for a work group.
1290 ** runall -- schedule even if individual bit is not set.
1291 ** wgrp -- the work group id to schedule.
1292 ** didit -- the queue run was performed for this work group.
1298 #define INCR_MOD(v, m) if (++v >= m) \
1303 schedule_queue_runs(runall, wgrp, didit)
1308 int qgrp, cgrp, endgrp;
1309 #if _FFR_QUEUE_SCHED_DBG
1317 ** This is a bit ugly since we have to duplicate the
1318 ** code that "walks" through a work queue group.
1323 cgrp = endgrp = WorkGrp[wgrp].wg_curqgrp;
1328 #if _FFR_QUEUE_SCHED_DBG
1332 qgrp = WorkGrp[wgrp].wg_qgs[cgrp]->qg_index;
1333 if (Queue[qgrp]->qg_queueintvl > 0)
1334 qintvl = Queue[qgrp]->qg_queueintvl;
1335 else if (QueueIntvl > 0)
1336 qintvl = QueueIntvl;
1338 qintvl = (time_t) 0;
1339 #if _FFR_QUEUE_SCHED_DBG
1340 lastsched = Queue[qgrp]->qg_nextrun;
1342 if ((runall || Queue[qgrp]->qg_nextrun <= now) && qintvl > 0)
1344 #if _FFR_QUEUE_SCHED_DBG
1347 if (minqintvl == 0 || qintvl < minqintvl)
1351 ** Only set a new time if a queue run was performed
1352 ** for this queue group. If the queue was not run,
1353 ** we could starve it by setting a new time on each
1358 Queue[qgrp]->qg_nextrun += qintvl;
1360 #if _FFR_QUEUE_SCHED_DBG
1362 sm_syslog(LOG_INFO, NOQID,
1363 "sqr: wgrp=%d, cgrp=%d, qgrp=%d, intvl=%ld, QI=%ld, runall=%d, lastrun=%ld, nextrun=%ld, sched=%d",
1365 (long) Queue[qgrp]->qg_queueintvl,
1366 (long) QueueIntvl, runall, (long) lastsched,
1367 (long) Queue[qgrp]->qg_nextrun, sched);
1368 #endif /* _FFR_QUEUE_SCHED_DBG */
1369 INCR_MOD(cgrp, WorkGrp[wgrp].wg_numqgrp);
1370 } while (endgrp != cgrp);
1372 (void) sm_setevent(minqintvl, runqueueevent, 0);
1375 #if _FFR_QUEUE_RUN_PARANOIA
1377 ** CHECKQUEUERUNNER -- check whether a queue group hasn't been run.
1379 ** Use this if events may get lost and hence queue runners may not
1380 ** be started and mail will pile up in a queue.
1386 ** true if a queue run is necessary.
1389 ** may schedule a queue run.
1396 time_t now, minqintvl;
1400 for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++)
1404 if (Queue[qgrp]->qg_queueintvl > 0)
1405 qintvl = Queue[qgrp]->qg_queueintvl;
1406 else if (QueueIntvl > 0)
1407 qintvl = QueueIntvl;
1409 qintvl = (time_t) 0;
1410 if (Queue[qgrp]->qg_nextrun <= now - qintvl)
1412 if (minqintvl == 0 || qintvl < minqintvl)
1415 sm_syslog(LOG_WARNING, NOQID,
1416 "checkqueuerunner: queue %d should have been run at %s, queue interval %ld",
1418 arpadate(ctime(&Queue[qgrp]->qg_nextrun)),
1424 (void) sm_setevent(minqintvl, runqueueevent, 0);
1429 #endif /* _FFR_QUEUE_RUN_PARANOIA */
1432 ** RUNQUEUE -- run the jobs in the queue.
1434 ** Gets the stuff out of the queue in some presumably logical
1435 ** order and processes them.
1438 ** forkflag -- true if the queue scanning should be done in
1439 ** a child process. We double-fork so it is not our
1440 ** child and we don't have to clean up after it.
1441 ** false can be ignored if we have multiple queues.
1442 ** verbose -- if true, print out status information.
1443 ** persistent -- persistent queue runner?
1444 ** runall -- run all groups or only a subset (DoQueueRun)?
1447 ** true if the queue run successfully began.
1450 ** runs things in the mail queue using run_work_group().
1451 ** maybe schedules next queue run.
1454 static ENVELOPE QueueEnvelope; /* the queue run envelope */
1455 static time_t LastQueueTime = 0; /* last time a queue ID assigned */
1456 static pid_t LastQueuePid = -1; /* last PID which had a queue ID */
1458 /* values for qp_supdirs */
1459 #define QP_NOSUB 0x0000 /* No subdirectories */
1460 #define QP_SUBDF 0x0001 /* "df" subdirectory */
1461 #define QP_SUBQF 0x0002 /* "qf" subdirectory */
1462 #define QP_SUBXF 0x0004 /* "xf" subdirectory */
1465 runqueue(forkflag, verbose, persistent, runall)
1473 static int curnum = 0;
1476 SM_NONVOLATILE int oldgroup = 0;
1478 if (sm_debug_active(&DebugLeakQ, 1))
1480 oldgroup = sm_heap_group();
1482 sm_dprintf("runqueue() heap group #%d\n", sm_heap_group());
1484 #endif /* SM_HEAP_CHECK */
1486 /* queue run has been started, don't do any more this time */
1489 /* more than one queue or more than one directory per queue */
1490 if (!forkflag && !verbose &&
1491 (WorkGrp[0].wg_qgs[0]->qg_numqueues > 1 || NumWorkGroups > 1 ||
1492 WorkGrp[0].wg_numqgrp > 1))
1496 ** For controlling queue runners via signals sent to this process.
1497 ** Oldsh* will get called too by runners_sig* (if it is not SIG_IGN
1498 ** or SIG_DFL) to preserve cleanup behavior. Now that this process
1499 ** will have children (and perhaps grandchildren) this handler will
1500 ** be left in place. This is because this process, once it has
1501 ** finished spinning off queue runners, may go back to doing something
1502 ** else (like being a daemon). And we still want on a SIG{TERM,HUP} to
1503 ** clean up the child queue runners. Only install 'runners_sig*' once
1504 ** else we'll get stuck looping forever.
1507 cursh = sm_signal(SIGTERM, runners_sigterm);
1508 if (cursh != runners_sigterm)
1510 cursh = sm_signal(SIGHUP, runners_sighup);
1511 if (cursh != runners_sighup)
1514 for (i = 0; i < NumWorkGroups && !NoMoreRunners; i++)
1516 int rwgflags = RWG_NONE;
1520 ** If MaxQueueChildren active then test whether the start
1521 ** of the next queue group's additional queue runners (maximum)
1522 ** will result in MaxQueueChildren being exceeded.
1524 ** Note: do not use continue; even though another workgroup
1525 ** may have fewer queue runners, this would be "unfair",
1526 ** i.e., this work group might "starve" then.
1529 #if _FFR_QUEUE_SCHED_DBG
1531 sm_syslog(LOG_INFO, NOQID,
1532 "rq: curnum=%d, MaxQueueChildren=%d, CurRunners=%d, WorkGrp[curnum].wg_maxact=%d",
1533 curnum, MaxQueueChildren, CurRunners,
1534 WorkGrp[curnum].wg_maxact);
1535 #endif /* _FFR_QUEUE_SCHED_DBG */
1536 if (MaxQueueChildren > 0 &&
1537 CurRunners + WorkGrp[curnum].wg_maxact > MaxQueueChildren)
1541 ** Pick up where we left off (curnum), in case we
1542 ** used up all the children last time without finishing.
1543 ** This give a round-robin fairness to queue runs.
1545 ** Increment CurRunners before calling run_work_group()
1546 ** to avoid a "race condition" with proc_list_drop() which
1547 ** decrements CurRunners if the queue runners terminate.
1548 ** Notice: CurRunners is an upper limit, in some cases
1549 ** (too few jobs in the queue) this value is larger than
1550 ** the actual number of queue runners. The discrepancy can
1551 ** increase if some queue runners "hang" for a long time.
1554 /* don't let proc_list_drop() change CurRunners */
1555 wasblocked = sm_blocksignal(SIGCHLD);
1556 CurRunners += WorkGrp[curnum].wg_maxact;
1557 if (wasblocked == 0)
1558 (void) sm_releasesignal(SIGCHLD);
1560 rwgflags |= RWG_FORK;
1562 rwgflags |= RWG_VERBOSE;
1564 rwgflags |= RWG_PERSISTENT;
1566 rwgflags |= RWG_RUNALL;
1567 ret = run_work_group(curnum, rwgflags);
1570 ** Failure means a message was printed for ETRN
1571 ** and subsequent queues are likely to fail as well.
1572 ** Decrement CurRunners in that case because
1573 ** none have been started.
1578 /* don't let proc_list_drop() change CurRunners */
1579 wasblocked = sm_blocksignal(SIGCHLD);
1580 CurRunners -= WorkGrp[curnum].wg_maxact;
1581 CHK_CUR_RUNNERS("runqueue", curnum,
1582 WorkGrp[curnum].wg_maxact);
1583 if (wasblocked == 0)
1584 (void) sm_releasesignal(SIGCHLD);
1589 schedule_queue_runs(runall, curnum, true);
1590 INCR_MOD(curnum, NumWorkGroups);
1593 /* schedule left over queue runs */
1594 if (i < NumWorkGroups && !NoMoreRunners && !persistent)
1598 for (h = curnum; i < NumWorkGroups; i++)
1600 schedule_queue_runs(runall, h, false);
1601 INCR_MOD(h, NumWorkGroups);
1607 if (sm_debug_active(&DebugLeakQ, 1))
1608 sm_heap_setgroup(oldgroup);
1613 #if _FFR_SKIP_DOMAINS
1615 ** SKIP_DOMAINS -- Skip 'skip' number of domains in the WorkQ.
1617 ** Added by Stephen Frost <sfrost@snowman.net> to support
1618 ** having each runner process every N'th domain instead of
1619 ** every N'th message.
1622 ** skip -- number of domains in WorkQ to skip.
1625 ** total number of messages skipped.
1637 for (n = 0, seqjump = 0; n < skip && WorkQ != NULL; seqjump++)
1639 if (WorkQ->w_next != NULL)
1641 if (WorkQ->w_host != NULL &&
1642 WorkQ->w_next->w_host != NULL)
1644 if (sm_strcasecmp(WorkQ->w_host,
1645 WorkQ->w_next->w_host) != 0)
1650 if ((WorkQ->w_host != NULL &&
1651 WorkQ->w_next->w_host == NULL) ||
1652 (WorkQ->w_host == NULL &&
1653 WorkQ->w_next->w_host != NULL))
1657 WorkQ = WorkQ->w_next;
1661 #endif /* _FFR_SKIP_DOMAINS */
1664 ** RUNNER_WORK -- have a queue runner do its work
1666 ** Have a queue runner do its work a list of entries.
1667 ** When work isn't directly being done then this process can take a signal
1668 ** and terminate immediately (in a clean fashion of course).
1669 ** When work is directly being done, it's not to be interrupted
1670 ** immediately: the work should be allowed to finish at a clean point
1671 ** before termination (in a clean fashion of course).
1675 ** sequenceno -- 'th process to run WorkQ.
1676 ** didfork -- did the calling process fork()?
1677 ** skip -- process only each skip'th item.
1678 ** njobs -- number of jobs in WorkQ.
1684 ** runs things in the mail queue.
1688 runner_work(e, sequenceno, didfork, skip, njobs)
1689 register ENVELOPE *e;
1702 ** Here we temporarily block the second calling of the handlers.
1703 ** This allows us to handle the signal without terminating in the
1704 ** middle of direct work. If a signal does come, the test for
1705 ** NoMoreRunners will find it.
1711 /* process them once at a time */
1712 while (WorkQ != NULL)
1715 SM_NONVOLATILE int oldgroup = 0;
1717 if (sm_debug_active(&DebugLeakQ, 1))
1719 oldgroup = sm_heap_group();
1721 sm_dprintf("run_queue_group() heap group #%d\n",
1724 #endif /* SM_HEAP_CHECK */
1726 /* do no more work */
1729 /* Check that a valid signal handler is callable */
1730 if (Oldsh != SIG_DFL && Oldsh != SIG_IGN &&
1731 Oldsh != runners_sighup &&
1732 Oldsh != runners_sigterm)
1737 w = WorkQ; /* assign current work item */
1740 ** Set the head of the WorkQ to the next work item.
1741 ** It is set 'skip' ahead (the number of parallel queue
1742 ** runners working on WorkQ together) since each runner
1743 ** works on every 'skip'th (N-th) item.
1744 #if _FFR_SKIP_DOMAINS
1745 ** In the case of the BYHOST Queue Sort Order, the 'item'
1746 ** is a domain, so we work on every 'skip'th (N-th) domain.
1750 #if _FFR_SKIP_DOMAINS
1751 if (QueueSortOrder == QSO_BYHOST)
1754 if (WorkQ->w_next != NULL)
1756 if (WorkQ->w_host != NULL &&
1757 WorkQ->w_next->w_host != NULL)
1759 if (sm_strcasecmp(WorkQ->w_host,
1760 WorkQ->w_next->w_host)
1762 seqjump = skip_domains(skip);
1764 WorkQ = WorkQ->w_next;
1768 if ((WorkQ->w_host != NULL &&
1769 WorkQ->w_next->w_host == NULL) ||
1770 (WorkQ->w_host == NULL &&
1771 WorkQ->w_next->w_host != NULL))
1772 seqjump = skip_domains(skip);
1774 WorkQ = WorkQ->w_next;
1778 WorkQ = WorkQ->w_next;
1781 #endif /* _FFR_SKIP_DOMAINS */
1783 for (n = 0; n < skip && WorkQ != NULL; n++)
1784 WorkQ = WorkQ->w_next;
1790 ** Ignore jobs that are too expensive for the moment.
1792 ** Get new load average every GET_NEW_LA_TIME seconds.
1796 if (shouldqueue(WkRecipFact, Current_LA_time))
1798 char *msg = "Aborting queue run: load average too high";
1803 sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg);
1806 if (shouldqueue(w->w_pri, w->w_ctime))
1810 if (QueueSortOrder == QSO_BYPRIORITY)
1813 message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue",
1814 qid_printqueue(w->w_qgrp,
1816 w->w_name + 2, sequenceno,
1819 sm_syslog(LOG_INFO, NOQID,
1820 "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)",
1821 qid_printqueue(w->w_qgrp,
1823 w->w_name + 2, w->w_pri,
1824 CurrentLA, sequenceno,
1829 message("Skipping %s/%s (sequence %d of %d)",
1830 qid_printqueue(w->w_qgrp, w->w_qdir),
1831 w->w_name + 2, sequenceno, njobs);
1838 message("Running %s/%s (sequence %d of %d)",
1839 qid_printqueue(w->w_qgrp, w->w_qdir),
1840 w->w_name + 2, sequenceno, njobs);
1842 if (didfork && MaxQueueChildren > 0)
1844 sm_blocksignal(SIGCHLD);
1845 (void) sm_signal(SIGCHLD, reapchild);
1848 sm_syslog(LOG_DEBUG, NOQID,
1849 "runqueue %s dowork(%s)",
1850 qid_printqueue(w->w_qgrp, w->w_qdir),
1853 (void) dowork(w->w_qgrp, w->w_qdir, w->w_name + 2,
1854 ForkQueueRuns, false, e);
1857 sm_free(w->w_name); /* XXX */
1858 if (w->w_host != NULL)
1859 sm_free(w->w_host); /* XXX */
1860 sm_free((char *) w); /* XXX */
1861 sequenceno += seqjump; /* next sequence number */
1863 if (sm_debug_active(&DebugLeakQ, 1))
1864 sm_heap_setgroup(oldgroup);
1871 sl = tTdlevel(76) - 100;
1872 sm_dprintf("run_work_group: sleep=%d\n", sl);
1880 /* check the signals didn't happen during the revert */
1883 /* Check that a valid signal handler is callable */
1884 if (Oldsh != SIG_DFL && Oldsh != SIG_IGN &&
1885 Oldsh != runners_sighup && Oldsh != runners_sigterm)
1889 Oldsh = SIG_DFL; /* after the NoMoreRunners check */
1892 ** RUN_WORK_GROUP -- run the jobs in a queue group from a work group.
1894 ** Gets the stuff out of the queue in some presumably logical
1895 ** order and processes them.
1898 ** wgrp -- work group to process.
1899 ** flags -- RWG_* flags
1902 ** true if the queue run successfully began.
1905 ** runs things in the mail queue.
1908 /* Minimum sleep time for persistent queue runners */
1909 #define MIN_SLEEP_TIME 5
1912 run_work_group(wgrp, flags)
1916 register ENVELOPE *e;
1919 int qgrp, endgrp, h, i;
1923 extern ENVELOPE BlankEnvelope;
1924 extern SIGFUNC_DECL reapchild __P((int));
1930 ** If no work will ever be selected, don't even bother reading
1936 if (!bitset(RWG_PERSISTENT, flags) &&
1937 shouldqueue(WkRecipFact, Current_LA_time))
1939 char *msg = "Skipping queue run -- load average too high";
1941 if (bitset(RWG_VERBOSE, flags))
1942 message("458 %s\n", msg);
1944 sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg);
1949 ** See if we already have too many children.
1952 if (bitset(RWG_FORK, flags) &&
1953 WorkGrp[wgrp].wg_lowqintvl > 0 &&
1954 !bitset(RWG_PERSISTENT, flags) &&
1955 MaxChildren > 0 && CurChildren >= MaxChildren)
1957 char *msg = "Skipping queue run -- too many children";
1959 if (bitset(RWG_VERBOSE, flags))
1960 message("458 %s (%d)\n", msg, CurChildren);
1962 sm_syslog(LOG_INFO, NOQID, "runqueue: %s (%d)",
1968 ** See if we want to go off and do other useful work.
1971 if (bitset(RWG_FORK, flags))
1975 (void) sm_blocksignal(SIGCHLD);
1976 (void) sm_signal(SIGCHLD, reapchild);
1981 const char *msg = "Skipping queue run -- fork() failed";
1982 const char *err = sm_errstring(errno);
1984 if (bitset(RWG_VERBOSE, flags))
1985 message("458 %s: %s\n", msg, err);
1987 sm_syslog(LOG_INFO, NOQID, "runqueue: %s: %s",
1989 (void) sm_releasesignal(SIGCHLD);
1994 /* parent -- pick up intermediate zombie */
1995 (void) sm_blocksignal(SIGALRM);
1997 /* wgrp only used when queue runners are persistent */
1998 proc_list_add(pid, "Queue runner", PROC_QUEUE,
1999 WorkGrp[wgrp].wg_maxact,
2000 bitset(RWG_PERSISTENT, flags) ? wgrp : -1,
2002 (void) sm_releasesignal(SIGALRM);
2003 (void) sm_releasesignal(SIGCHLD);
2007 /* child -- clean up signals */
2009 /* Reset global flags */
2010 RestartRequest = NULL;
2011 RestartWorkGroup = false;
2012 ShutdownRequest = NULL;
2014 CurrentPid = getpid();
2015 close_sendmail_pid();
2018 ** Initialize exception stack and default exception
2019 ** handler for child process.
2022 sm_exc_newthread(fatal_error);
2026 /* Add parent process as first child item */
2027 proc_list_add(CurrentPid, "Queue runner child process",
2028 PROC_QUEUE_CHILD, 0, -1, NULL);
2029 (void) sm_releasesignal(SIGCHLD);
2030 (void) sm_signal(SIGCHLD, SIG_DFL);
2031 (void) sm_signal(SIGHUP, SIG_DFL);
2032 (void) sm_signal(SIGTERM, intsig);
2036 ** Release any resources used by the daemon code.
2041 /* force it to run expensive jobs */
2044 /* drop privileges */
2045 if (geteuid() == (uid_t) 0)
2046 (void) drop_privileges(false);
2049 ** Create ourselves an envelope
2052 CurEnv = &QueueEnvelope;
2053 rpool = sm_rpool_new_x(NULL);
2054 e = newenvelope(&QueueEnvelope, CurEnv, rpool);
2055 e->e_flags = BlankEnvelope.e_flags;
2058 /* make sure we have disconnected from parent */
2059 if (bitset(RWG_FORK, flags))
2066 ** If we are running part of the queue, always ignore stored
2070 if (QueueLimitId != NULL || QueueLimitSender != NULL ||
2071 QueueLimitQuarantine != NULL ||
2072 QueueLimitRecipient != NULL)
2074 IgnoreHostStatus = true;
2080 ** Here is where we choose the queue group from the work group.
2081 ** The caller of the "domorework" label must setup a new envelope.
2084 endgrp = WorkGrp[wgrp].wg_curqgrp; /* to not spin endlessly */
2089 ** Run a queue group if:
2090 ** RWG_RUNALL bit is set or the bit for this group is set.
2097 ** Find the next queue group within the work group that
2098 ** has been marked as needing a run.
2101 qgrp = WorkGrp[wgrp].wg_qgs[WorkGrp[wgrp].wg_curqgrp]->qg_index;
2102 WorkGrp[wgrp].wg_curqgrp++; /* advance */
2103 WorkGrp[wgrp].wg_curqgrp %= WorkGrp[wgrp].wg_numqgrp; /* wrap */
2104 if (bitset(RWG_RUNALL, flags) ||
2105 (Queue[qgrp]->qg_nextrun <= now &&
2106 Queue[qgrp]->qg_nextrun != (time_t) -1))
2108 if (endgrp == WorkGrp[wgrp].wg_curqgrp)
2111 if (bitset(RWG_FORK, flags))
2112 finis(true, true, ExitStat);
2113 return true; /* we're done */
2117 qdir = Queue[qgrp]->qg_curnum; /* round-robin init of queue position */
2118 #if _FFR_QUEUE_SCHED_DBG
2120 sm_syslog(LOG_INFO, NOQID,
2121 "rwg: wgrp=%d, qgrp=%d, qdir=%d, name=%s, curqgrp=%d, numgrps=%d",
2122 wgrp, qgrp, qdir, qid_printqueue(qgrp, qdir),
2123 WorkGrp[wgrp].wg_curqgrp, WorkGrp[wgrp].wg_numqgrp);
2124 #endif /* _FFR_QUEUE_SCHED_DBG */
2127 /* tweak niceness of queue runs */
2128 if (Queue[qgrp]->qg_nice > 0)
2129 (void) nice(Queue[qgrp]->qg_nice);
2132 /* XXX running queue group... */
2133 sm_setproctitle(true, CurEnv, "running queue: %s",
2134 qid_printqueue(qgrp, qdir));
2136 if (LogLevel > 69 || tTd(63, 99))
2137 sm_syslog(LOG_DEBUG, NOQID,
2138 "runqueue %s, pid=%d, forkflag=%d",
2139 qid_printqueue(qgrp, qdir), (int) CurrentPid,
2140 bitset(RWG_FORK, flags));
2143 ** Start making passes through the queue.
2144 ** First, read and sort the entire queue.
2145 ** Then, process the work in that order.
2146 ** But if you take too long, start over.
2149 for (i = 0; i < Queue[qgrp]->qg_numqueues; i++)
2151 (void) gatherq(qgrp, qdir, false, &full, &more, &h);
2153 if (ShmId != SM_SHM_NO_ID)
2154 QSHM_ENTRIES(Queue[qgrp]->qg_qpaths[qdir].qp_idx) = h;
2156 /* If there are no more items in this queue advance */
2159 /* A round-robin advance */
2161 qdir %= Queue[qgrp]->qg_numqueues;
2164 /* Has the WorkList reached the limit? */
2166 break; /* don't try to gather more */
2169 /* order the existing work requests */
2170 njobs = sortq(Queue[qgrp]->qg_maxlist);
2171 Queue[qgrp]->qg_curnum = qdir; /* update */
2174 if (!Verbose && bitnset(QD_FORK, Queue[qgrp]->qg_flags))
2176 int loop, maxrunners;
2180 ** For this WorkQ we want to fork off N children (maxrunners)
2181 ** at this point. Each child has a copy of WorkQ. Each child
2182 ** will process every N-th item. The parent will wait for all
2183 ** of the children to finish before moving on to the next
2184 ** queue group within the work group. This saves us forking
2185 ** a new runner-child for each work item.
2186 ** It's valid for qg_maxqrun == 0 since this may be an
2187 ** explicit "don't run this queue" setting.
2190 maxrunners = Queue[qgrp]->qg_maxqrun;
2193 ** If no runners are configured for this group but
2194 ** the queue is "forced" then lets use 1 runner.
2197 if (maxrunners == 0 && bitset(RWG_FORCE, flags))
2200 /* No need to have more runners then there are jobs */
2201 if (maxrunners > njobs)
2203 for (loop = 0; loop < maxrunners; loop++)
2206 ** Since the delivery may happen in a child and the
2207 ** parent does not wait, the parent may close the
2208 ** maps thereby removing any shared memory used by
2209 ** the map. Therefore, close the maps now so the
2210 ** child will dynamically open them if necessary.
2218 syserr("run_work_group: cannot fork");
2223 /* parent -- clean out connection cache */
2224 mci_flush(false, NULL);
2225 #if _FFR_SKIP_DOMAINS
2226 if (QueueSortOrder == QSO_BYHOST)
2228 sequenceno += skip_domains(1);
2231 #endif /* _FFR_SKIP_DOMAINS */
2234 WorkQ = WorkQ->w_next;
2237 proc_list_add(pid, "Queue child runner process",
2238 PROC_QUEUE_CHILD, 0, -1, NULL);
2240 /* No additional work, no additional runners */
2246 /* child -- Reset global flags */
2247 RestartRequest = NULL;
2248 RestartWorkGroup = false;
2249 ShutdownRequest = NULL;
2251 CurrentPid = getpid();
2252 close_sendmail_pid();
2255 ** Initialize exception stack and default
2256 ** exception handler for child process.
2257 ** When fork()'d the child now has a private
2258 ** copy of WorkQ at its current position.
2261 sm_exc_newthread(fatal_error);
2264 ** SMTP processes (whether -bd or -bs) set
2265 ** SIGCHLD to reapchild to collect
2266 ** children status. However, at delivery
2267 ** time, that status must be collected
2268 ** by sm_wait() to be dealt with properly
2269 ** (check success of delivery based
2270 ** on status code, etc). Therefore, if we
2271 ** are an SMTP process, reset SIGCHLD
2272 ** back to the default so reapchild
2273 ** doesn't collect status before
2277 if (OpMode == MD_SMTP ||
2278 OpMode == MD_DAEMON ||
2279 MaxQueueChildren > 0)
2282 sm_releasesignal(SIGCHLD);
2283 (void) sm_signal(SIGCHLD, SIG_DFL);
2286 /* child -- error messages to the transcript */
2287 QuickAbort = OnlyOneError = false;
2288 runner_work(e, sequenceno, true,
2291 /* This child is done */
2292 finis(true, true, ExitStat);
2297 sm_releasesignal(SIGCHLD);
2300 ** Wait until all of the runners have completed before
2301 ** seeing if there is another queue group in the
2302 ** work group to process.
2303 ** XXX Future enhancement: don't wait() for all children
2304 ** here, just go ahead and make sure that overall the number
2305 ** of children is not exceeded.
2308 while (CurChildren > 0)
2313 while ((ret = sm_wait(&status)) <= 0)
2315 proc_list_drop(ret, status, NULL);
2318 else if (Queue[qgrp]->qg_maxqrun > 0 || bitset(RWG_FORCE, flags))
2321 ** When current process will not fork children to do the work,
2322 ** it will do the work itself. The 'skip' will be 1 since
2323 ** there are no child runners to divide the work across.
2326 runner_work(e, sequenceno, false, 1, njobs);
2329 /* free memory allocated by newenvelope() above */
2330 sm_rpool_free(rpool);
2331 QueueEnvelope.e_rpool = NULL;
2333 /* Are there still more queues in the work group to process? */
2334 if (endgrp != WorkGrp[wgrp].wg_curqgrp)
2336 rpool = sm_rpool_new_x(NULL);
2337 e = newenvelope(&QueueEnvelope, CurEnv, rpool);
2338 e->e_flags = BlankEnvelope.e_flags;
2342 /* No more queues in work group to process. Now check persistent. */
2343 if (bitset(RWG_PERSISTENT, flags))
2346 sm_setproctitle(true, NULL, "running queue: %s",
2347 qid_printqueue(qgrp, qdir));
2350 ** close bogus maps, i.e., maps which caused a tempfail,
2351 ** so we get fresh map connections on the next lookup.
2352 ** closemaps() is also called when children are started.
2357 /* Close any cached connections. */
2358 mci_flush(true, NULL);
2360 /* Clean out expired related entries. */
2364 /* Update MX records for FallbackMX. */
2365 if (FallbackMX != NULL)
2366 (void) getfallbackmxrr(FallbackMX);
2370 /* close UserDatabase */
2375 if (sm_debug_active(&SmHeapCheck, 2)
2376 && access("memdump", F_OK) == 0
2382 out = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
2383 "memdump.out", SM_IO_APPEND, NULL);
2386 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "----------------------\n");
2388 sm_debug_level(&SmHeapCheck) - 1);
2389 (void) sm_io_close(out, SM_TIME_DEFAULT);
2392 #endif /* SM_HEAP_CHECK */
2394 /* let me rest for a second to catch my breath */
2395 if (njobs == 0 && WorkGrp[wgrp].wg_lowqintvl < MIN_SLEEP_TIME)
2396 sleep(MIN_SLEEP_TIME);
2397 else if (WorkGrp[wgrp].wg_lowqintvl <= 0)
2398 sleep(QueueIntvl > 0 ? QueueIntvl : MIN_SLEEP_TIME);
2400 sleep(WorkGrp[wgrp].wg_lowqintvl);
2403 ** Get the LA outside the WorkQ loop if necessary.
2404 ** In a persistent queue runner the code is repeated over
2405 ** and over but gatherq() may ignore entries due to
2406 ** shouldqueue() (do we really have to do this twice?).
2407 ** Hence the queue runners would just idle around when once
2408 ** CurrentLA caused all entries in a queue to be ignored.
2413 rpool = sm_rpool_new_x(NULL);
2414 e = newenvelope(&QueueEnvelope, CurEnv, rpool);
2415 e->e_flags = BlankEnvelope.e_flags;
2419 /* exit without the usual cleanup */
2421 if (bitset(RWG_FORK, flags))
2422 finis(true, true, ExitStat);
2428 ** DOQUEUERUN -- do a queue run?
2438 ** RUNQUEUEEVENT -- Sets a flag to indicate that a queue run should be done.
2447 ** The invocation of this function via an alarm may interrupt
2448 ** a set of actions. Thus errno may be set in that context.
2449 ** We need to restore errno at the end of this function to ensure
2450 ** that any work done here that sets errno doesn't return a
2451 ** misleading/false errno value. Errno may be EINTR upon entry to
2452 ** this function because of non-restartable/continuable system
2453 ** API was active. Iff this is true we will override errno as
2454 ** a timeout (as a more accurate error message).
2456 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
2457 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2462 runqueueevent(ignore)
2465 int save_errno = errno;
2468 ** Set the general bit that we want a queue run,
2469 ** tested in doqueuerun()
2473 #if _FFR_QUEUE_SCHED_DBG
2475 sm_syslog(LOG_INFO, NOQID, "rqe: done");
2483 ** GATHERQ -- gather messages from the message queue(s) the work queue.
2486 ** qgrp -- the index of the queue group.
2487 ** qdir -- the index of the queue directory.
2488 ** doall -- if set, include everything in the queue (even
2489 ** the jobs that cannot be run because the load
2490 ** average is too high, or MaxQueueRun is reached).
2491 ** Otherwise, exclude those jobs.
2492 ** full -- (optional) to be set 'true' if WorkList is full
2493 ** more -- (optional) to be set 'true' if there are still more
2494 ** messages in this queue not added to WorkList
2495 ** pnentries -- (optional) total nuber of entries in queue
2498 ** The number of request in the queue (not necessarily
2499 ** the number of requests in WorkList however).
2502 ** prepares available work into WorkList
2505 #define NEED_P 0001 /* 'P': priority */
2506 #define NEED_T 0002 /* 'T': time */
2507 #define NEED_R 0004 /* 'R': recipient */
2508 #define NEED_S 0010 /* 'S': sender */
2509 #define NEED_H 0020 /* host */
2510 #define HAS_QUARANTINE 0040 /* has an unexpected 'q' line */
2511 #define NEED_QUARANTINE 0100 /* 'q': reason */
2513 static WORK *WorkList = NULL; /* list of unsort work */
2514 static int WorkListSize = 0; /* current max size of WorkList */
2515 static int WorkListCount = 0; /* # of work items in WorkList */
2518 gatherq(qgrp, qdir, doall, full, more, pnentries)
2526 register struct dirent *d;
2530 int i, num_ent, wn, nentries;
2532 char qd[MAXPATHLEN];
2533 char qf[MAXPATHLEN];
2535 wn = WorkListCount - 1;
2539 (void) sm_strlcpy(qd, ".", sizeof(qd));
2541 (void) sm_strlcpyn(qd, sizeof(qd), 2,
2542 Queue[qgrp]->qg_qpaths[qdir].qp_name,
2544 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
2549 sm_dprintf("gatherq: %s\n", qd);
2551 check = QueueLimitId;
2552 while (check != NULL)
2554 sm_dprintf("\tQueueLimitId = %s%s\n",
2555 check->queue_negate ? "!" : "",
2556 check->queue_match);
2557 check = check->queue_next;
2560 check = QueueLimitSender;
2561 while (check != NULL)
2563 sm_dprintf("\tQueueLimitSender = %s%s\n",
2564 check->queue_negate ? "!" : "",
2565 check->queue_match);
2566 check = check->queue_next;
2569 check = QueueLimitRecipient;
2570 while (check != NULL)
2572 sm_dprintf("\tQueueLimitRecipient = %s%s\n",
2573 check->queue_negate ? "!" : "",
2574 check->queue_match);
2575 check = check->queue_next;
2578 if (QueueMode == QM_QUARANTINE)
2580 check = QueueLimitQuarantine;
2581 while (check != NULL)
2583 sm_dprintf("\tQueueLimitQuarantine = %s%s\n",
2584 check->queue_negate ? "!" : "",
2585 check->queue_match);
2586 check = check->queue_next;
2591 /* open the queue directory */
2595 syserr("gatherq: cannot open \"%s\"",
2596 qid_printqueue(qgrp, qdir));
2598 *full = WorkListCount >= MaxQueueRun && MaxQueueRun > 0;
2605 ** Read the work directory.
2608 while ((d = readdir(f)) != NULL)
2612 char lbuf[MAXNAME + 1];
2616 sm_dprintf("gatherq: checking %s..", d->d_name);
2618 /* is this an interesting entry? */
2619 if (!(((QueueMode == QM_NORMAL &&
2620 d->d_name[0] == NORMQF_LETTER) ||
2621 (QueueMode == QM_QUARANTINE &&
2622 d->d_name[0] == QUARQF_LETTER) ||
2623 (QueueMode == QM_LOST &&
2624 d->d_name[0] == LOSEQF_LETTER)) &&
2625 d->d_name[1] == 'f'))
2628 sm_dprintf(" skipping\n");
2634 if (strlen(d->d_name) >= MAXQFNAME)
2637 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2638 "gatherq: %s too long, %d max characters\n",
2639 d->d_name, MAXQFNAME);
2641 sm_syslog(LOG_ALERT, NOQID,
2642 "gatherq: %s too long, %d max characters",
2643 d->d_name, MAXQFNAME);
2648 check = QueueLimitId;
2649 while (check != NULL)
2651 if (strcontainedin(false, check->queue_match,
2652 d->d_name) != check->queue_negate)
2655 check = check->queue_next;
2657 if (QueueLimitId != NULL && check == NULL)
2660 /* grow work list if necessary */
2661 if (++wn >= MaxQueueRun && MaxQueueRun > 0)
2663 if (wn == MaxQueueRun && LogLevel > 0)
2664 sm_syslog(LOG_WARNING, NOQID,
2665 "WorkList for %s maxed out at %d",
2666 qid_printqueue(qgrp, qdir),
2669 continue; /* just count entries */
2672 if (wn >= WorkListSize)
2674 grow_wlist(qgrp, qdir);
2675 if (wn >= WorkListSize)
2681 (void) sm_strlcpyn(qf, sizeof(qf), 3, qd, "/", d->d_name);
2682 if (stat(qf, &sbuf) < 0)
2684 if (errno != ENOENT)
2685 sm_syslog(LOG_INFO, NOQID,
2686 "gatherq: can't stat %s/%s",
2687 qid_printqueue(qgrp, qdir),
2692 if (!bitset(S_IFREG, sbuf.st_mode))
2694 /* Yikes! Skip it or we will hang on open! */
2695 if (!((d->d_name[0] == DATAFL_LETTER ||
2696 d->d_name[0] == NORMQF_LETTER ||
2697 d->d_name[0] == QUARQF_LETTER ||
2698 d->d_name[0] == LOSEQF_LETTER ||
2699 d->d_name[0] == XSCRPT_LETTER) &&
2700 d->d_name[1] == 'f' && d->d_name[2] == '\0'))
2701 syserr("gatherq: %s/%s is not a regular file",
2702 qid_printqueue(qgrp, qdir), d->d_name);
2707 /* avoid work if possible */
2708 if ((QueueSortOrder == QSO_BYFILENAME ||
2709 QueueSortOrder == QSO_BYMODTIME ||
2710 QueueSortOrder == QSO_NONE ||
2711 QueueSortOrder == QSO_RANDOM) &&
2712 QueueLimitQuarantine == NULL &&
2713 QueueLimitSender == NULL &&
2714 QueueLimitRecipient == NULL)
2718 w->w_name = newstr(d->d_name);
2720 w->w_lock = w->w_tooyoung = false;
2723 w->w_mtime = sbuf.st_mtime;
2728 /* open control file */
2729 cf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B,
2731 if (cf == NULL && OpMode != MD_PRINT)
2733 /* this may be some random person sending hir msgs */
2735 sm_dprintf("gatherq: cannot open %s: %s\n",
2736 d->d_name, sm_errstring(errno));
2743 w->w_name = newstr(d->d_name);
2747 w->w_lock = !lockfile(sm_io_getinfo(cf, SM_IO_WHAT_FD,
2752 w->w_tooyoung = false;
2754 /* make sure jobs in creation don't clog queue */
2755 w->w_pri = 0x7fffffff;
2757 w->w_mtime = sbuf.st_mtime;
2759 /* extract useful information */
2761 if (QueueSortOrder == QSO_BYHOST
2763 || QueueSortOrder == QSO_BYSHUFFLE
2767 /* need w_host set for host sort order */
2770 if (QueueLimitSender != NULL)
2772 if (QueueLimitRecipient != NULL)
2774 if (QueueLimitQuarantine != NULL)
2775 i |= NEED_QUARANTINE;
2776 while (cf != NULL && i != 0 &&
2777 sm_io_fgets(cf, SM_TIME_DEFAULT, lbuf,
2783 p = strchr(lbuf, '\n');
2788 /* flush rest of overly long line */
2789 while ((c = sm_io_getc(cf, SM_TIME_DEFAULT))
2790 != SM_IO_EOF && c != '\n')
2797 qfver = atoi(&lbuf[1]);
2801 w->w_pri = atol(&lbuf[1]);
2806 w->w_ctime = atol(&lbuf[1]);
2811 if (QueueMode != QM_QUARANTINE &&
2812 QueueMode != QM_LOST)
2815 sm_dprintf("%s not marked as quarantined but has a 'q' line\n",
2817 i |= HAS_QUARANTINE;
2819 else if (QueueMode == QM_QUARANTINE)
2821 if (QueueLimitQuarantine == NULL)
2823 i &= ~NEED_QUARANTINE;
2827 check = QueueLimitQuarantine;
2828 while (check != NULL)
2830 if (strcontainedin(false,
2833 check->queue_negate)
2836 check = check->queue_next;
2839 i &= ~NEED_QUARANTINE;
2844 if (w->w_host == NULL &&
2845 (p = strrchr(&lbuf[1], '@')) != NULL)
2848 if (QueueSortOrder == QSO_BYSHUFFLE)
2849 w->w_host = newstr(&p[1]);
2852 w->w_host = strrev(&p[1]);
2853 makelower(w->w_host);
2856 if (QueueLimitRecipient == NULL)
2863 p = strchr(&lbuf[1], ':');
2867 ++p; /* skip over ':' */
2871 check = QueueLimitRecipient;
2872 while (check != NULL)
2874 if (strcontainedin(true,
2877 check->queue_negate)
2880 check = check->queue_next;
2887 check = QueueLimitSender;
2888 while (check != NULL)
2890 if (strcontainedin(true,
2893 check->queue_negate)
2896 check = check->queue_next;
2903 if (MaxQueueAge > 0)
2905 time_t lasttry, delay;
2907 lasttry = (time_t) atol(&lbuf[1]);
2908 delay = MIN(lasttry - w->w_ctime,
2910 age = curtime() - lasttry;
2912 w->w_tooyoung = true;
2916 age = curtime() - (time_t) atol(&lbuf[1]);
2917 if (age >= 0 && MinQueueAge > 0 &&
2919 w->w_tooyoung = true;
2923 if (atol(&lbuf[1]) == 0)
2924 w->w_tooyoung = false;
2929 (void) sm_io_close(cf, SM_TIME_DEFAULT);
2931 if ((!doall && (shouldqueue(w->w_pri, w->w_ctime) ||
2933 bitset(HAS_QUARANTINE, i) ||
2934 bitset(NEED_QUARANTINE, i) ||
2935 bitset(NEED_R|NEED_S, i))
2937 /* don't even bother sorting this job in */
2939 sm_dprintf("skipping %s (%x)\n", w->w_name, i);
2940 sm_free(w->w_name); /* XXX */
2941 if (w->w_host != NULL)
2942 sm_free(w->w_host); /* XXX */
2951 i = wn - WorkListCount;
2952 WorkListCount += SM_MIN(num_ent, WorkListSize);
2955 *more = WorkListCount < wn;
2958 *full = (wn >= MaxQueueRun && MaxQueueRun > 0) ||
2959 (WorkList == NULL && wn > 0);
2961 if (pnentries != NULL)
2962 *pnentries = nentries;
2966 ** SORTQ -- sort the work list
2968 ** First the old WorkQ is cleared away. Then the WorkList is sorted
2969 ** for all items so that important (higher sorting value) items are not
2970 ** truncated off. Then the most important items are moved from
2971 ** WorkList to WorkQ. The lower count of 'max' or MaxListCount items
2975 ** max -- maximum number of items to be placed in WorkQ
2978 ** the number of items in WorkQ
2981 ** WorkQ gets released and filled with new work. WorkList
2982 ** gets released. Work items get sorted in order.
2989 register int i; /* local counter */
2990 register WORK *w; /* tmp item pointer */
2991 int wc = WorkListCount; /* trim size for WorkQ */
2997 /* Clear out old WorkQ. */
2998 for (w = WorkQ; w != NULL; w = nw)
3001 sm_free(w->w_name); /* XXX */
3002 if (w->w_host != NULL)
3003 sm_free(w->w_host); /* XXX */
3004 sm_free((char *) w); /* XXX */
3009 if (WorkList == NULL || wc <= 0)
3013 ** The sort now takes place using all of the items in WorkList.
3014 ** The list gets trimmed to the most important items after the sort.
3015 ** If the trim were to happen before the sort then one or more
3016 ** important items might get truncated off -- not what we want.
3019 if (QueueSortOrder == QSO_BYHOST)
3022 ** Sort the work directory for the first time,
3023 ** based on host name, lock status, and priority.
3026 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf1);
3029 ** If one message to host is locked, "lock" all messages
3036 if (!WorkList[i].w_lock)
3044 if (WorkList[i].w_host == NULL &&
3046 WorkList[i].w_lock = true;
3047 else if (WorkList[i].w_host != NULL &&
3048 w->w_host != NULL &&
3049 sm_strcasecmp(WorkList[i].w_host,
3051 WorkList[i].w_lock = true;
3058 ** Sort the work directory for the second time,
3059 ** based on lock status, host name, and priority.
3062 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf2);
3064 else if (QueueSortOrder == QSO_BYTIME)
3067 ** Simple sort based on submission time only.
3070 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf3);
3072 else if (QueueSortOrder == QSO_BYFILENAME)
3075 ** Sort based on queue filename.
3078 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf4);
3080 else if (QueueSortOrder == QSO_RANDOM)
3083 ** Sort randomly. To avoid problems with an instable sort,
3084 ** use a random index into the queue file name to start
3088 randi = get_rand_mod(MAXQFNAME);
3091 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf5);
3093 else if (QueueSortOrder == QSO_BYMODTIME)
3096 ** Simple sort based on modification time of queue file.
3097 ** This puts the oldest items first.
3100 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf6);
3103 else if (QueueSortOrder == QSO_BYSHUFFLE)
3106 ** Simple sort based on shuffled host name.
3109 init_shuffle_alphabet();
3110 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf7);
3112 #endif /* _FFR_RHS */
3113 else if (QueueSortOrder == QSO_BYPRIORITY)
3116 ** Simple sort based on queue priority only.
3119 qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf0);
3121 /* else don't sort at all */
3123 /* Check if the per queue group item limit will be exceeded */
3124 if (wc > max && max > 0)
3128 ** Convert the work list into canonical form.
3129 ** Should be turning it into a list of envelopes here perhaps.
3130 ** Only take the most important items up to the per queue group
3134 for (i = wc; --i >= 0; )
3136 w = (WORK *) xalloc(sizeof(*w));
3137 w->w_qgrp = WorkList[i].w_qgrp;
3138 w->w_qdir = WorkList[i].w_qdir;
3139 w->w_name = WorkList[i].w_name;
3140 w->w_host = WorkList[i].w_host;
3141 w->w_lock = WorkList[i].w_lock;
3142 w->w_tooyoung = WorkList[i].w_tooyoung;
3143 w->w_pri = WorkList[i].w_pri;
3144 w->w_ctime = WorkList[i].w_ctime;
3145 w->w_mtime = WorkList[i].w_mtime;
3150 /* free the rest of the list */
3151 for (i = WorkListCount; --i >= wc; )
3153 sm_free(WorkList[i].w_name);
3154 if (WorkList[i].w_host != NULL)
3155 sm_free(WorkList[i].w_host);
3158 if (WorkList != NULL)
3159 sm_free(WorkList); /* XXX */
3166 for (w = WorkQ; w != NULL; w = w->w_next)
3168 if (w->w_host != NULL)
3169 sm_dprintf("%22s: pri=%ld %s\n",
3170 w->w_name, w->w_pri, w->w_host);
3172 sm_dprintf("%32s: pri=%ld\n",
3173 w->w_name, w->w_pri);
3177 return wc; /* return number of WorkQ items */
3180 ** GROW_WLIST -- make the work list larger
3183 ** qgrp -- the index for the queue group.
3184 ** qdir -- the index for the queue directory.
3190 ** Adds another QUEUESEGSIZE entries to WorkList if possible.
3191 ** It can fail if there isn't enough memory, so WorkListSize
3192 ** should be checked again upon return.
3196 grow_wlist(qgrp, qdir)
3201 sm_dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize);
3202 if (WorkList == NULL)
3204 WorkList = (WORK *) xalloc((sizeof(*WorkList)) *
3205 (QUEUESEGSIZE + 1));
3206 WorkListSize = QUEUESEGSIZE;
3210 int newsize = WorkListSize + QUEUESEGSIZE;
3211 WORK *newlist = (WORK *) sm_realloc((char *) WorkList,
3212 (unsigned) sizeof(WORK) * (newsize + 1));
3214 if (newlist != NULL)
3216 WorkListSize = newsize;
3220 sm_syslog(LOG_INFO, NOQID,
3221 "grew WorkList for %s to %d",
3222 qid_printqueue(qgrp, qdir),
3226 else if (LogLevel > 0)
3228 sm_syslog(LOG_ALERT, NOQID,
3229 "FAILED to grow WorkList for %s to %d",
3230 qid_printqueue(qgrp, qdir), newsize);
3234 sm_dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize);
3237 ** WORKCMPF0 -- simple priority-only compare function.
3240 ** a -- the first argument.
3241 ** b -- the second argument.
3266 ** WORKCMPF1 -- first compare function for ordering work based on host name.
3268 ** Sorts on host name, lock status, and priority in that order.
3271 ** a -- the first argument.
3272 ** b -- the second argument.
3289 if (a->w_host != NULL && b->w_host == NULL)
3291 else if (a->w_host == NULL && b->w_host != NULL)
3293 if (a->w_host != NULL && b->w_host != NULL &&
3294 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
3298 if (a->w_lock != b->w_lock)
3299 return b->w_lock - a->w_lock;
3302 return workcmpf0(a, b);
3305 ** WORKCMPF2 -- second compare function for ordering work based on host name.
3307 ** Sorts on lock status, host name, and priority in that order.
3310 ** a -- the first argument.
3311 ** b -- the second argument.
3328 if (a->w_lock != b->w_lock)
3329 return a->w_lock - b->w_lock;
3332 if (a->w_host != NULL && b->w_host == NULL)
3334 else if (a->w_host == NULL && b->w_host != NULL)
3336 if (a->w_host != NULL && b->w_host != NULL &&
3337 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
3341 return workcmpf0(a, b);
3344 ** WORKCMPF3 -- simple submission-time-only compare function.
3347 ** a -- the first argument.
3348 ** b -- the second argument.
3362 if (a->w_ctime > b->w_ctime)
3364 else if (a->w_ctime < b->w_ctime)
3370 ** WORKCMPF4 -- compare based on file name
3373 ** a -- the first argument.
3374 ** b -- the second argument.
3388 return strcmp(a->w_name, b->w_name);
3391 ** WORKCMPF5 -- compare based on assigned random number
3394 ** a -- the first argument.
3395 ** b -- the second argument.
3407 if (strlen(a->w_name) < randi || strlen(b->w_name) < randi)
3409 return a->w_name[randi] - b->w_name[randi];
3412 ** WORKCMPF6 -- simple modification-time-only compare function.
3415 ** a -- the first argument.
3416 ** b -- the second argument.
3430 if (a->w_mtime > b->w_mtime)
3432 else if (a->w_mtime < b->w_mtime)
3439 ** WORKCMPF7 -- compare function for ordering work based on shuffled host name.
3441 ** Sorts on lock status, host name, and priority in that order.
3444 ** a -- the first argument.
3445 ** b -- the second argument.
3462 if (a->w_lock != b->w_lock)
3463 return a->w_lock - b->w_lock;
3466 if (a->w_host != NULL && b->w_host == NULL)
3468 else if (a->w_host == NULL && b->w_host != NULL)
3470 if (a->w_host != NULL && b->w_host != NULL &&
3471 (i = sm_strshufflecmp(a->w_host, b->w_host)) != 0)
3475 return workcmpf0(a, b);
3477 #endif /* _FFR_RHS */
3479 ** STRREV -- reverse string
3481 ** Returns a pointer to a new string that is the reverse of
3482 ** the string pointed to by fwd. The space for the new
3483 ** string is obtained using xalloc().
3486 ** fwd -- the string to reverse.
3489 ** the reversed string.
3500 rev = xalloc(len + 1);
3501 for (cnt = 0; cnt < len; ++cnt)
3502 rev[cnt] = fwd[len - cnt - 1];
3512 static unsigned char ShuffledAlphabet[NCHAR];
3515 init_shuffle_alphabet()
3517 static bool init = false;
3523 /* fill the ShuffledAlphabet */
3524 for (i = 0; i < NASCII; i++)
3525 ShuffledAlphabet[i] = i;
3528 for (i = 1; i < NASCII; i++)
3530 register int j = get_random() % NASCII;
3533 tmp = ShuffledAlphabet[j];
3534 ShuffledAlphabet[j] = ShuffledAlphabet[i];
3535 ShuffledAlphabet[i] = tmp;
3538 /* make it case insensitive */
3539 for (i = 'A'; i <= 'Z'; i++)
3540 ShuffledAlphabet[i] = ShuffledAlphabet[i + 'a' - 'A'];
3542 /* fill the upper part */
3543 for (i = 0; i < NASCII; i++)
3544 ShuffledAlphabet[i + NASCII] = ShuffledAlphabet[i];
3549 sm_strshufflecmp(a, b)
3553 const unsigned char *us1 = (const unsigned char *) a;
3554 const unsigned char *us2 = (const unsigned char *) b;
3556 while (ShuffledAlphabet[*us1] == ShuffledAlphabet[*us2++])
3561 return (ShuffledAlphabet[*us1] - ShuffledAlphabet[*--us2]);
3563 #endif /* _FFR_RHS */
3566 ** DOWORK -- do a work request.
3569 ** qgrp -- the index of the queue group for the job.
3570 ** qdir -- the index of the queue directory for the job.
3571 ** id -- the ID of the job to run.
3572 ** forkflag -- if set, run this in background.
3573 ** requeueflag -- if set, reinstantiate the queue quickly.
3574 ** This is used when expanding aliases in the queue.
3575 ** If forkflag is also set, it doesn't wait for the
3577 ** e - the envelope in which to run it.
3580 ** process id of process that is running the queue job.
3583 ** The work request is satisfied if possible.
3587 dowork(qgrp, qdir, id, forkflag, requeueflag, e)
3593 register ENVELOPE *e;
3599 sm_dprintf("dowork(%s/%s)\n", qid_printqueue(qgrp, qdir), id);
3608 ** Since the delivery may happen in a child and the
3609 ** parent does not wait, the parent may close the
3610 ** maps thereby removing any shared memory used by
3611 ** the map. Therefore, close the maps now so the
3612 ** child will dynamically open them if necessary.
3620 syserr("dowork: cannot fork");
3625 /* parent -- clean out connection cache */
3626 mci_flush(false, NULL);
3631 ** Initialize exception stack and default exception
3632 ** handler for child process.
3635 /* Reset global flags */
3636 RestartRequest = NULL;
3637 RestartWorkGroup = false;
3638 ShutdownRequest = NULL;
3640 CurrentPid = getpid();
3641 sm_exc_newthread(fatal_error);
3644 ** See note above about SMTP processes and SIGCHLD.
3647 if (OpMode == MD_SMTP ||
3648 OpMode == MD_DAEMON ||
3649 MaxQueueChildren > 0)
3652 sm_releasesignal(SIGCHLD);
3653 (void) sm_signal(SIGCHLD, SIG_DFL);
3656 /* child -- error messages to the transcript */
3657 QuickAbort = OnlyOneError = false;
3669 ** Lock the control file to avoid duplicate deliveries.
3670 ** Then run the file as though we had just read it.
3671 ** We save an idea of the temporary name so we
3672 ** can recover on interrupt.
3677 /* Reset global flags */
3678 RestartRequest = NULL;
3679 RestartWorkGroup = false;
3680 ShutdownRequest = NULL;
3684 /* set basic modes, etc. */
3687 rpool = sm_rpool_new_x(NULL);
3688 clearenvelope(e, false, rpool);
3689 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
3690 set_delivery_mode(SM_DELIVER, e);
3691 e->e_errormode = EM_MAIL;
3695 GrabTo = UseErrorsTo = false;
3700 set_op_mode(MD_QUEUERUN);
3702 sm_setproctitle(true, e, "%s from queue", qid_printname(e));
3704 sm_syslog(LOG_DEBUG, e->e_id, "dowork, pid=%d",
3707 /* don't use the headers from sendmail.cf... */
3710 /* read the queue control file -- return if locked */
3711 if (!readqf(e, false))
3713 if (tTd(40, 4) && e->e_id != NULL)
3714 sm_dprintf("readqf(%s) failed\n",
3718 finis(false, true, EX_OK);
3721 /* adding this frees 8 bytes */
3722 clearenvelope(e, false, rpool);
3724 /* adding this frees 12 bytes */
3725 sm_rpool_free(rpool);
3731 e->e_flags |= EF_INQUEUE;
3732 eatheader(e, requeueflag, true);
3735 queueup(e, false, false);
3737 /* do the delivery */
3738 sendall(e, SM_DELIVER);
3740 /* finish up and exit */
3742 finis(true, true, ExitStat);
3745 (void) dropenvelope(e, true, false);
3746 sm_rpool_free(rpool);
3748 e->e_message = NULL;
3756 ** DOWORKLIST -- process a list of envelopes as work requests
3758 ** Similar to dowork(), except that after forking, it processes an
3759 ** envelope and its siblings, treating each envelope as a work request.
3762 ** el -- envelope to be processed including its siblings.
3763 ** forkflag -- if set, run this in background.
3764 ** requeueflag -- if set, reinstantiate the queue quickly.
3765 ** This is used when expanding aliases in the queue.
3766 ** If forkflag is also set, it doesn't wait for the
3770 ** process id of process that is running the queue job.
3773 ** The work request is satisfied if possible.
3777 doworklist(el, forkflag, requeueflag)
3786 sm_dprintf("doworklist()\n");
3795 ** Since the delivery may happen in a child and the
3796 ** parent does not wait, the parent may close the
3797 ** maps thereby removing any shared memory used by
3798 ** the map. Therefore, close the maps now so the
3799 ** child will dynamically open them if necessary.
3807 syserr("doworklist: cannot fork");
3812 /* parent -- clean out connection cache */
3813 mci_flush(false, NULL);
3818 ** Initialize exception stack and default exception
3819 ** handler for child process.
3822 /* Reset global flags */
3823 RestartRequest = NULL;
3824 RestartWorkGroup = false;
3825 ShutdownRequest = NULL;
3827 CurrentPid = getpid();
3828 sm_exc_newthread(fatal_error);
3831 ** See note above about SMTP processes and SIGCHLD.
3834 if (OpMode == MD_SMTP ||
3835 OpMode == MD_DAEMON ||
3836 MaxQueueChildren > 0)
3839 sm_releasesignal(SIGCHLD);
3840 (void) sm_signal(SIGCHLD, SIG_DFL);
3843 /* child -- error messages to the transcript */
3844 QuickAbort = OnlyOneError = false;
3857 ** Lock the control file to avoid duplicate deliveries.
3858 ** Then run the file as though we had just read it.
3859 ** We save an idea of the temporary name so we
3860 ** can recover on interrupt.
3865 /* Reset global flags */
3866 RestartRequest = NULL;
3867 RestartWorkGroup = false;
3868 ShutdownRequest = NULL;
3872 /* set basic modes, etc. */
3875 GrabTo = UseErrorsTo = false;
3880 set_op_mode(MD_QUEUERUN);
3883 sm_syslog(LOG_DEBUG, el->e_id, "doworklist, pid=%d",
3886 for (ei = el; ei != NULL; ei = ei->e_sibling)
3891 if (WILL_BE_QUEUED(ei->e_sendmode))
3893 else if (QueueMode != QM_QUARANTINE &&
3894 ei->e_quarmsg != NULL)
3897 rpool = sm_rpool_new_x(NULL);
3898 clearenvelope(&e, true, rpool);
3899 e.e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
3900 set_delivery_mode(SM_DELIVER, &e);
3901 e.e_errormode = EM_MAIL;
3903 e.e_qgrp = ei->e_qgrp;
3904 e.e_qdir = ei->e_qdir;
3906 sm_setproctitle(true, &e, "%s from queue", qid_printname(&e));
3908 /* don't use the headers from sendmail.cf... */
3912 /* read the queue control file -- return if locked */
3913 if (readqf(&e, false))
3915 e.e_flags |= EF_INQUEUE;
3916 eatheader(&e, requeueflag, true);
3919 queueup(&e, false, false);
3921 /* do the delivery */
3922 sendall(&e, SM_DELIVER);
3923 (void) dropenvelope(&e, true, false);
3927 if (tTd(40, 4) && e.e_id != NULL)
3928 sm_dprintf("readqf(%s) failed\n",
3931 sm_rpool_free(rpool);
3935 /* restore CurEnv */
3938 /* finish up and exit */
3940 finis(true, true, ExitStat);
3944 ** READQF -- read queue file and set up environment.
3947 ** e -- the envelope of the job to run.
3948 ** openonly -- only open the qf (returned as e_lockfp)
3951 ** true if it successfully read the queue file.
3955 ** The queue file is returned locked.
3960 register ENVELOPE *e;
3963 register SM_FILE_T *qfp;
3965 struct stat st, stf;
3972 bool nomore = false;
3976 char qf[MAXPATHLEN];
3981 ** Read and process the file.
3984 SM_REQUIRE(e != NULL);
3986 (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), sizeof(qf));
3987 qfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDWR_B, NULL);
3990 int save_errno = errno;
3993 sm_dprintf("readqf(%s): sm_io_open failure (%s)\n",
3994 qf, sm_errstring(errno));
3998 syserr("readqf: no control file %s", qf);
4003 if (!lockfile(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), qf, NULL,
4006 /* being processed by another queuer */
4008 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4009 "%s: locked\n", e->e_id);
4011 sm_dprintf("%s: locked\n", e->e_id);
4013 sm_syslog(LOG_DEBUG, e->e_id, "locked");
4014 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4022 ** Prevent locking race condition.
4024 ** Process A: readqf(): qfp = fopen(qffile)
4025 ** Process B: queueup(): rename(tf, qf)
4026 ** Process B: unlocks(tf)
4027 ** Process A: lockfile(qf);
4029 ** Process A (us) has the old qf file (before the rename deleted
4030 ** the directory entry) and will be delivering based on old data.
4031 ** This can lead to multiple deliveries of the same recipients.
4033 ** Catch this by checking if the underlying qf file has changed
4034 ** *after* acquiring our lock and if so, act as though the file
4035 ** was still locked (i.e., just return like the lockfile() case
4039 if (stat(qf, &stf) < 0 ||
4040 fstat(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), &st) < 0)
4042 /* must have been being processed by someone else */
4044 sm_dprintf("readqf(%s): [f]stat failure (%s)\n",
4045 qf, sm_errstring(errno));
4046 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4050 if (st.st_nlink != stf.st_nlink ||
4051 st.st_dev != stf.st_dev ||
4052 ST_INODE(st) != ST_INODE(stf) ||
4053 #if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */
4054 st.st_gen != stf.st_gen ||
4056 st.st_uid != stf.st_uid ||
4057 st.st_gid != stf.st_gid ||
4058 st.st_size != stf.st_size)
4060 /* changed after opened */
4062 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4063 "%s: changed\n", e->e_id);
4065 sm_dprintf("%s: changed\n", e->e_id);
4067 sm_syslog(LOG_DEBUG, e->e_id, "changed");
4068 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4073 ** Check the queue file for plausibility to avoid attacks.
4076 qsafe = S_IWOTH|S_IWGRP;
4077 if (bitset(S_IWGRP, QueueFileMode))
4080 bogus = st.st_uid != geteuid() &&
4081 st.st_uid != TrustedUid &&
4082 geteuid() != RealUid;
4085 ** If this qf file results from a set-group-ID binary, then
4086 ** we check whether the directory is group-writable,
4087 ** the queue file mode contains the group-writable bit, and
4088 ** the groups are the same.
4089 ** Notice: this requires that the set-group-ID binary is used to
4093 if (bogus && st.st_gid == getegid() && UseMSP)
4098 bp = SM_LAST_DIR_DELIM(qf);
4106 if (stat(delim == '\0' ? "." : qf, &dst) < 0)
4107 syserr("readqf: cannot stat directory %s",
4108 delim == '\0' ? "." : qf);
4111 bogus = !(bitset(S_IWGRP, QueueFileMode) &&
4112 bitset(S_IWGRP, dst.st_mode) &&
4113 dst.st_gid == st.st_gid);
4120 bogus = bitset(qsafe, st.st_mode);
4125 sm_syslog(LOG_ALERT, e->e_id,
4126 "bogus queue file, uid=%ld, gid=%ld, mode=%o",
4127 (long) st.st_uid, (long) st.st_gid,
4128 (unsigned int) st.st_mode);
4131 sm_dprintf("readqf(%s): bogus file\n", qf);
4132 e->e_flags |= EF_INQUEUE;
4134 loseqfile(e, "bogus file uid/gid in mqueue");
4135 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4139 if (st.st_size == 0)
4141 /* must be a bogus file -- if also old, just remove it */
4142 if (!openonly && st.st_ctime + 10 * 60 < curtime())
4144 (void) xunlink(queuename(e, DATAFL_LETTER));
4145 (void) xunlink(queuename(e, ANYQFL_LETTER));
4147 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4151 if (st.st_nlink == 0)
4154 ** Race condition -- we got a file just as it was being
4155 ** unlinked. Just assume it is zero length.
4158 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4164 ** If we don't own the file mark it as unsafe.
4165 ** However, allow TrustedUser to own it as well
4166 ** in case TrustedUser manipulates the queue.
4169 if (st.st_uid != geteuid() && st.st_uid != TrustedUid)
4170 e->e_flags |= EF_UNSAFE;
4171 #else /* _FFR_TRUSTED_QF */
4172 /* If we don't own the file mark it as unsafe */
4173 if (st.st_uid != geteuid())
4174 e->e_flags |= EF_UNSAFE;
4175 #endif /* _FFR_TRUSTED_QF */
4177 /* good file -- save this lock */
4180 /* Just wanted the open file */
4184 /* do basic system initialization */
4186 macdefine(&e->e_macro, A_PERM, 'i', e->e_id);
4189 e->e_flags |= EF_GLOBALERRS;
4190 set_op_mode(MD_QUEUERUN);
4192 e->e_qfletter = queue_letter(e, ANYQFL_LETTER);
4193 e->e_dfqgrp = e->e_qgrp;
4194 e->e_dfqdir = e->e_qdir;
4195 #if _FFR_QUEUE_MACRO
4196 macdefine(&e->e_macro, A_TEMP, macid("{queue}"),
4197 qid_printqueue(e->e_qgrp, e->e_qdir));
4201 while (bufsize = sizeof(buf),
4202 (bp = fgetfolded(buf, &bufsize, qfp)) != NULL)
4204 unsigned long qflags;
4211 sm_dprintf("+++++ %s\n", bp);
4216 syserr("SECURITY ALERT: extra or bogus data in queue file: %s",
4218 err = "bogus queue line";
4223 case 'A': /* AUTH= parameter */
4224 if (!xtextok(&bp[1]))
4226 e->e_auth_param = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4229 case 'B': /* body type */
4230 r = check_bodytype(&bp[1]);
4231 if (!BODYTYPE_VALID(r))
4233 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4236 case 'C': /* specify controlling user */
4237 ctladdr = setctluser(&bp[1], qfver, e);
4240 case 'D': /* data file name */
4241 /* obsolete -- ignore */
4244 case 'd': /* data file directory name */
4248 #if _FFR_MSP_PARANOIA
4249 /* forbid queue groups in MSP? */
4254 qgrp < NumQueue && Queue[qgrp] != NULL;
4258 qdir < Queue[qgrp]->qg_numqueues;
4262 Queue[qgrp]->qg_qpaths[qdir].qp_name)
4271 err = "bogus queue file directory";
4277 case 'E': /* specify error recipient */
4278 /* no longer used */
4281 case 'F': /* flag bits */
4282 if (strncmp(bp, "From ", 5) == 0)
4284 /* we are being spoofed! */
4285 syserr("SECURITY ALERT: bogus qf line %s", bp);
4286 err = "bogus queue line";
4289 for (p = &bp[1]; *p != '\0'; p++)
4293 case '8': /* has 8 bit data */
4294 e->e_flags |= EF_HAS8BIT;
4297 case 'b': /* delete Bcc: header */
4298 e->e_flags |= EF_DELETE_BCC;
4301 case 'd': /* envelope has DSN RET= */
4302 e->e_flags |= EF_RET_PARAM;
4305 case 'n': /* don't return body */
4306 e->e_flags |= EF_NO_BODY_RETN;
4309 case 'r': /* response */
4310 e->e_flags |= EF_RESPONSE;
4313 case 's': /* split */
4314 e->e_flags |= EF_SPLIT;
4317 case 'w': /* warning sent */
4318 e->e_flags |= EF_WARNING;
4322 case 'e': /* message requires EAI */
4323 e->e_smtputf8 = true;
4325 #endif /* _FFR_EAI */
4330 case 'q': /* quarantine reason */
4331 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4332 macdefine(&e->e_macro, A_PERM,
4333 macid("{quarantine}"), e->e_quarmsg);
4336 case 'H': /* header */
4339 ** count size before chompheader() destroys the line.
4340 ** this isn't accurate due to macro expansion, but
4341 ** better than before. "-3" to skip H?? at least.
4344 hdrsize += strlen(bp) - 3;
4345 (void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e);
4348 case 'I': /* data file's inode number */
4349 /* regenerated below */
4352 case 'K': /* time of last delivery attempt */
4353 e->e_dtime = atol(&buf[1]);
4356 case 'L': /* Solaris Content-Length: */
4357 case 'M': /* message */
4358 /* ignore this; we want a new message next time */
4361 case 'N': /* number of delivery attempts */
4362 e->e_ntries = atoi(&buf[1]);
4364 /* if this has been tried recently, let it be */
4366 if (e->e_ntries > 0 && e->e_dtime <= now &&
4367 now < e->e_dtime + MinQueueAge)
4371 howlong = pintvl(now - e->e_dtime, true);
4373 (void) sm_io_fprintf(smioout,
4375 "%s: too young (%s)\n",
4378 sm_dprintf("%s: too young (%s)\n",
4381 sm_syslog(LOG_DEBUG, e->e_id,
4390 macdefine(&e->e_macro, A_TEMP,
4391 macid("{ntries}"), &buf[1]);
4394 /* adjust BIND parameters immediately */
4395 if (e->e_ntries == 0)
4397 _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
4398 _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
4402 _res.retry = TimeOuts.res_retry[RES_TO_NORMAL];
4403 _res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL];
4405 #endif /* NAMED_BIND */
4408 case 'P': /* message priority */
4409 e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
4412 case 'Q': /* original recipient */
4413 orcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4416 case 'r': /* final recipient */
4417 frcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4420 case 'R': /* specify recipient */
4426 while (*++p != '\0' && *p != ':')
4431 qflags |= QHASNOTIFY;
4435 qflags |= QPINGONSUCCESS;
4439 qflags |= QPINGONFAILURE;
4443 qflags |= QPINGONDELAY;
4451 if (ctladdr != NULL)
4452 ctladdr->q_flags |= QALIAS;
4460 qflags |= QDYNMAILER;
4463 default: /* ignore or complain? */
4470 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"),
4471 ((qflags & QINTBCC) != 0) ? "e b" : "e r");
4473 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0',
4479 /* make sure we keep the current qgrp */
4480 if (ISVALIDQGRP(e->e_qgrp))
4481 q->q_qgrp = e->e_qgrp;
4482 q->q_alias = ctladdr;
4484 q->q_flags &= ~Q_PINGFLAGS;
4485 q->q_flags |= qflags;
4486 q->q_finalrcpt = frcpt;
4489 if (bitset(QDYNMAILER, qflags))
4490 newmodmailer(q, QDYNMAILFLG);
4492 (void) recipient(q, &e->e_sendqueue, 0, e);
4496 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"),
4500 case 'S': /* sender */
4501 setsender(sm_rpool_strdup_x(e->e_rpool, &bp[1]),
4502 e, NULL, '\0', true);
4505 case 'T': /* init time */
4506 e->e_ctime = atol(&bp[1]);
4509 case 'V': /* queue file version number */
4510 qfver = atoi(&bp[1]);
4511 if (qfver <= QF_VERSION)
4513 syserr("Version number in queue file (%d) greater than max (%d)",
4515 err = "unsupported queue file version";
4520 case 'Z': /* original envelope id from ESMTP */
4521 e->e_envid = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4522 macdefine(&e->e_macro, A_PERM,
4523 macid("{dsn_envid}"), e->e_envid);
4526 case '!': /* deliver by */
4528 /* format: flag (1 char) space long-integer */
4529 e->e_dlvr_flag = buf[1];
4530 e->e_deliver_by = strtol(&buf[3], NULL, 10);
4532 case '$': /* define macro */
4534 r = macid_parse(&bp[1], &ep);
4537 macdefine(&e->e_macro, A_PERM, r,
4538 sm_rpool_strdup_x(e->e_rpool, ep));
4542 case '.': /* terminate file */
4547 syserr("readqf: %s: line %d: bad line \"%s\"",
4548 qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
4549 err = "unrecognized line";
4558 ** If we haven't read any lines, this queue file is empty.
4559 ** Arrange to remove it without referencing any null pointers.
4562 if (LineNumber == 0)
4565 e->e_flags |= EF_CLRQUEUE|EF_FATALERRS|EF_RESPONSE;
4569 /* Check to make sure we have a complete queue file read */
4572 syserr("readqf: %s: incomplete queue file read", qf);
4573 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4577 #if _FFR_QF_PARANOIA
4578 /* Check to make sure key fields were read */
4579 if (e->e_from.q_mailer == NULL)
4581 syserr("readqf: %s: sender not specified in queue file", qf);
4582 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4586 #endif /* _FFR_QF_PARANOIA */
4590 ** If this message originates from something other than
4591 ** srvrsmtp.c, then it might use UTF8 addresses but not be
4592 ** marked. We'll just add the mark so we're sure that it
4593 ** either can be delivered or will be returned.
4600 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
4601 if (!addr_is_ascii(q->q_paddr) && !e->e_smtputf8)
4602 e->e_smtputf8 = true;
4603 if (!addr_is_ascii(e->e_from.q_paddr) && !e->e_smtputf8)
4604 e->e_smtputf8 = true;
4606 #endif /* _FFR_EAI */
4608 /* possibly set ${dsn_ret} macro */
4609 if (bitset(EF_RET_PARAM, e->e_flags))
4611 if (bitset(EF_NO_BODY_RETN, e->e_flags))
4612 macdefine(&e->e_macro, A_PERM,
4613 macid("{dsn_ret}"), "hdrs");
4615 macdefine(&e->e_macro, A_PERM,
4616 macid("{dsn_ret}"), "full");
4620 ** Arrange to read the data file.
4623 p = queuename(e, DATAFL_LETTER);
4624 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, p, SM_IO_RDONLY_B,
4626 if (e->e_dfp == NULL)
4628 syserr("readqf: cannot open %s", p);
4632 e->e_flags |= EF_HAS_DF;
4633 if (fstat(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, NULL), &st)
4636 e->e_msgsize = st.st_size + hdrsize;
4637 e->e_dfdev = st.st_dev;
4638 e->e_dfino = ST_INODE(st);
4639 (void) sm_snprintf(buf, sizeof(buf), "%ld",
4640 PRT_NONNEGL(e->e_msgsize));
4641 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"),
4650 ** There was some error reading the qf file (reason is in err var.)
4652 ** close file; clear e_lockfp since it is the same as qfp,
4653 ** hence it is invalid (as file) after qfp is closed;
4654 ** the qf file is on disk, so set the flag to avoid calling
4655 ** queueup() with bogus data.
4661 (void) sm_io_close(qfp, SM_TIME_DEFAULT);
4663 e->e_flags |= EF_INQUEUE;
4668 ** PRTSTR -- print a string, "unprintable" characters are shown as \oct
4671 ** s -- string to print
4672 ** ml -- maximum length of output
4675 ** number of entries
4678 ** Prints a string on stdout.
4681 static void prtstr __P((char *, int));
4683 #if _FFR_BOUNCE_QUEUE
4684 # define IS_BOUNCE_QUEUE(i) ((i) == BounceQueue)
4685 # define SKIP_BOUNCE_QUEUE(i) \
4686 if (IS_BOUNCE_QUEUE(i)) \
4689 # define IS_BOUNCE_QUEUE(i) false
4690 # define SKIP_BOUNCE_QUEUE(i)
4702 while (ml-- > 0 && ((c = *s++) != '\0'))
4708 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
4709 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
4712 else if (isascii(c) && isprint(c))
4713 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
4717 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4718 "\\%03o", c & 0xFF);
4723 ** PRINTNQE -- print out number of entries in the mail queue
4726 ** out -- output file pointer.
4727 ** prefix -- string to output in front of each line.
4734 printnqe(out, prefix)
4739 int i, k = 0, nrequests = 0;
4740 bool unknown = false;
4742 if (ShmId == SM_SHM_NO_ID)
4745 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4746 "Data unavailable: shared memory not updated\n");
4748 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4749 "%sNOTCONFIGURED:-1\r\n", prefix);
4752 for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
4756 SKIP_BOUNCE_QUEUE(i)
4758 for (j = 0; j < Queue[i]->qg_numqueues; j++)
4765 n = QSHM_ENTRIES(Queue[i]->qg_qpaths[j].qp_idx);
4767 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4769 prefix, qid_printqueue(i, j), n);
4772 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4773 "%s: unknown number of entries\n",
4774 qid_printqueue(i, j));
4779 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4781 qid_printqueue(i, j));
4785 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4787 qid_printqueue(i, j), n);
4793 if (prefix == NULL && k > 1)
4794 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4795 "\t\tTotal requests: %d%s\n",
4796 nrequests, unknown ? " (about)" : "");
4797 #else /* SM_CONF_SHM */
4799 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4800 "Data unavailable without shared memory support\n");
4802 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4803 "%sNOTAVAILABLE:-1\r\n", prefix);
4804 #endif /* SM_CONF_SHM */
4807 ** PRINTQUEUE -- print out a representation of the mail queue
4816 ** Prints a listing of the mail queue on the standard output.
4822 int i, k = 0, nrequests = 0;
4824 for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
4829 for (j = 0; j < Queue[i]->qg_numqueues; j++)
4833 nrequests += print_single_queue(i, j);
4838 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4839 "\t\tTotal requests: %d\n",
4843 ** PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue
4846 ** qgrp -- the index of the queue group.
4847 ** qdir -- the queue directory.
4850 ** number of requests in mail queue.
4853 ** Prints a listing of the mail queue on the standard output.
4857 print_single_queue(qgrp, qdir)
4864 char qd[MAXPATHLEN];
4865 char qddf[MAXPATHLEN];
4870 (void) sm_strlcpy(qd, ".", sizeof(qd));
4871 (void) sm_strlcpy(qddf, ".", sizeof(qddf));
4875 (void) sm_strlcpyn(qd, sizeof(qd), 2,
4876 Queue[qgrp]->qg_qpaths[qdir].qp_name,
4878 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
4880 (void) sm_strlcpyn(qddf, sizeof(qddf), 2,
4881 Queue[qgrp]->qg_qpaths[qdir].qp_name,
4883 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
4888 ** Check for permission to print the queue
4891 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
4896 extern GIDSET_T InitialGidSet[NGROUPS_MAX];
4899 if (stat(qd, &st) < 0)
4901 syserr("Cannot stat %s",
4902 qid_printqueue(qgrp, qdir));
4909 if (InitialGidSet[n] == st.st_gid)
4912 if (n < 0 && RealGid != st.st_gid)
4913 #else /* NGROUPS_MAX */
4914 if (RealGid != st.st_gid)
4915 #endif /* NGROUPS_MAX */
4917 usrerr("510 You are not permitted to see the queue");
4924 ** Read and order the queue.
4927 nrequests = gatherq(qgrp, qdir, true, NULL, NULL, NULL);
4928 (void) sortq(Queue[qgrp]->qg_maxlist);
4931 ** Print the work list that we have read.
4934 /* first see if there is anything */
4937 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s is empty\n",
4938 qid_printqueue(qgrp, qdir));
4942 sm_getla(); /* get load average */
4944 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\t\t%s (%d request%s",
4945 qid_printqueue(qgrp, qdir),
4946 nrequests, nrequests == 1 ? "" : "s");
4947 if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
4948 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4949 ", only %d printed", MaxQueueRun);
4951 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4952 ")\n-----Q-ID----- --Size-- -Priority- ---Q-Time--- --------Sender/Recipient--------\n");
4954 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4955 ")\n-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------\n");
4956 for (w = WorkQ; w != NULL; w = w->w_next)
4959 auto time_t submittime = 0;
4963 char quarmsg[MAXLINE];
4964 char statmsg[MAXLINE];
4965 char bodytype[MAXNAME + 1];
4966 char qf[MAXPATHLEN];
4971 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%13s",
4973 (void) sm_strlcpyn(qf, sizeof(qf), 3, qd, "/", w->w_name);
4974 f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B,
4979 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4980 " (permission denied)\n");
4981 else if (errno == ENOENT)
4982 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4983 " (job completed)\n");
4985 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4987 sm_errstring(errno));
4991 w->w_name[0] = DATAFL_LETTER;
4992 (void) sm_strlcpyn(qf, sizeof(qf), 3, qddf, "/", w->w_name);
4993 if (stat(qf, &st) >= 0)
4994 dfsize = st.st_size;
5000 ** Maybe the df file can't be statted because
5001 ** it is in a different directory than the qf file.
5002 ** In order to find out, we must read the qf file.
5005 newenvelope(&e, &BlankEnvelope, sm_rpool_new_x(NULL));
5006 e.e_id = w->w_name + 2;
5010 if (readqf(&e, false))
5012 char *df = queuename(&e, DATAFL_LETTER);
5013 if (stat(df, &st) >= 0)
5014 dfsize = st.st_size;
5016 if (e.e_lockfp != NULL)
5018 (void) sm_io_close(e.e_lockfp, SM_TIME_DEFAULT);
5021 clearenvelope(&e, false, e.e_rpool);
5022 sm_rpool_free(e.e_rpool);
5025 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "*");
5026 else if (QueueMode == QM_LOST)
5027 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "?");
5028 else if (w->w_tooyoung)
5029 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "-");
5030 else if (shouldqueue(w->w_pri, w->w_ctime))
5031 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "X");
5033 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " ");
5038 statmsg[0] = bodytype[0] = '\0';
5040 while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
5051 case 'V': /* queue file version */
5052 qfver = atoi(&buf[1]);
5055 case 'M': /* error message */
5056 if ((i = strlen(&buf[1])) >= sizeof(statmsg))
5057 i = sizeof(statmsg) - 1;
5058 memmove(statmsg, &buf[1], i);
5062 case 'q': /* quarantine reason */
5063 if ((i = strlen(&buf[1])) >= sizeof(quarmsg))
5064 i = sizeof(quarmsg) - 1;
5065 memmove(quarmsg, &buf[1], i);
5069 case 'B': /* body type */
5070 if ((i = strlen(&buf[1])) >= sizeof(bodytype))
5071 i = sizeof(bodytype) - 1;
5072 memmove(bodytype, &buf[1], i);
5076 case 'S': /* sender name */
5079 (void) sm_io_fprintf(smioout,
5081 "%8ld %10ld%c%.12s ",
5084 bitset(EF_WARNING, flags)
5086 ctime(&submittime) + 4);
5087 prtstr(&buf[1], 78);
5091 (void) sm_io_fprintf(smioout,
5095 ctime(&submittime));
5096 prtstr(&buf[1], 39);
5099 if (quarmsg[0] != '\0')
5101 (void) sm_io_fprintf(smioout,
5103 "\n QUARANTINE: %.*s",
5109 if (statmsg[0] != '\0' || bodytype[0] != '\0')
5111 (void) sm_io_fprintf(smioout,
5115 if (statmsg[0] != '\0')
5116 (void) sm_io_fprintf(smioout,
5125 case 'C': /* controlling user */
5127 (void) sm_io_fprintf(smioout,
5129 "\n\t\t\t\t\t\t(---%.64s---)",
5133 case 'R': /* recipient name */
5144 (void) sm_io_fprintf(smioout,
5151 (void) sm_io_fprintf(smioout,
5156 if (Verbose && statmsg[0] != '\0')
5158 (void) sm_io_fprintf(smioout,
5166 case 'T': /* creation time */
5167 submittime = atol(&buf[1]);
5170 case 'F': /* flag bits */
5171 for (p = &buf[1]; *p != '\0'; p++)
5176 flags |= EF_WARNING;
5182 if (submittime == (time_t) 0)
5183 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
5184 " (no control file)");
5185 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n");
5186 (void) sm_io_close(f, SM_TIME_DEFAULT);
5192 ** QUEUE_LETTER -- get the proper queue letter for the current QueueMode.
5195 ** e -- envelope to build it in/from.
5196 ** type -- the file type, used as the first character
5197 ** of the file name.
5200 ** the letter to use
5204 queue_letter(e, type)
5208 /* Change type according to QueueMode */
5209 if (type == ANYQFL_LETTER)
5211 if (e->e_quarmsg != NULL)
5212 type = QUARQF_LETTER;
5218 type = NORMQF_LETTER;
5222 type = QUARQF_LETTER;
5226 type = LOSEQF_LETTER;
5230 /* should never happen */
5240 ** QUEUENAME -- build a file name in the queue directory for this envelope.
5243 ** e -- envelope to build it in/from.
5244 ** type -- the file type, used as the first character
5245 ** of the file name.
5248 ** a pointer to the queue name (in a static buffer).
5251 ** If no id code is already assigned, queuename() will
5252 ** assign an id code with assign_queueid(). If no queue
5253 ** directory is assigned, one will be set with setnewqueue().
5258 register ENVELOPE *e;
5264 static char buf[MAXPATHLEN];
5266 /* Assign an ID if needed */
5267 if (e->e_id == NULL)
5273 type = queue_letter(e, type);
5275 /* begin of filename */
5276 pref[0] = (char) type;
5280 /* Assign a queue group/directory if needed */
5281 if (type == XSCRPT_LETTER)
5284 ** We don't want to call setnewqueue() if we are fetching
5285 ** the pathname of the transcript file, because setnewqueue
5286 ** chooses a queue, and sometimes we need to write to the
5287 ** transcript file before we have gathered enough information
5288 ** to choose a queue.
5291 if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR)
5293 if (e->e_qgrp != NOQGRP && e->e_qdir != NOQDIR)
5295 e->e_xfqgrp = e->e_qgrp;
5296 e->e_xfqdir = e->e_qdir;
5301 if (Queue[e->e_xfqgrp]->qg_numqueues <= 1)
5305 e->e_xfqdir = get_rand_mod(
5306 Queue[e->e_xfqgrp]->qg_numqueues);
5315 if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR)
5319 (void) setnewqueue(e);
5321 if (type == DATAFL_LETTER)
5333 /* xf files always have a valid qd and qg picked above */
5334 if ((qd == NOQDIR || qg == NOQGRP) && type != XSCRPT_LETTER)
5335 (void) sm_strlcpyn(buf, sizeof(buf), 2, pref, e->e_id);
5341 if (bitset(QP_SUBDF, Queue[qg]->qg_qpaths[qd].qp_subdirs))
5350 if (bitset(QP_SUBQF, Queue[qg]->qg_qpaths[qd].qp_subdirs))
5355 if (bitset(QP_SUBXF, Queue[qg]->qg_qpaths[qd].qp_subdirs))
5362 sm_abort("queuename: bad queue file type %d", type);
5365 (void) sm_strlcpyn(buf, sizeof(buf), 4,
5366 Queue[qg]->qg_qpaths[qd].qp_name,
5367 sub, pref, e->e_id);
5371 sm_dprintf("queuename: %s\n", buf);
5376 ** INIT_QID_ALG -- Initialize the (static) parameters that are used to
5377 ** generate a queue ID.
5379 ** This function is called by the daemon to reset
5380 ** LastQueueTime and LastQueuePid which are used by assign_queueid().
5381 ** Otherwise the algorithm may cause problems because
5382 ** LastQueueTime and LastQueuePid are set indirectly by main()
5383 ** before the daemon process is started, hence LastQueuePid is not
5384 ** the pid of the daemon and therefore a child of the daemon can
5385 ** actually have the same pid as LastQueuePid which means the section
5386 ** in assign_queueid():
5387 ** * see if we need to get a new base time/pid *
5388 ** is NOT triggered which will cause the same queue id to be generated.
5405 ** ASSIGN_QUEUEID -- assign a queue ID for this envelope.
5407 ** Assigns an id code if one does not already exist.
5408 ** This code assumes that nothing will remain in the queue for
5409 ** longer than 60 years. It is critical that files with the given
5410 ** name do not already exist in the queue.
5411 ** [No longer initializes e_qdir to NOQDIR.]
5414 ** e -- envelope to set it in.
5420 static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
5422 # define QIC_LEN_R 62
5425 ** Note: the length is "officially" 60 because minutes and seconds are
5426 ** usually only 0-59. However (Linux):
5427 ** tm_sec The number of seconds after the minute, normally in
5428 ** the range 0 to 59, but can be up to 61 to allow for
5430 ** Hence the real length of the string is 62 to take this into account.
5431 ** Alternatively % QIC_LEN can (should) be used for access everywhere.
5434 # define queuenextid() CurrentPid
5435 #define QIC_LEN_SQR (QIC_LEN * QIC_LEN)
5439 register ENVELOPE *e;
5441 pid_t pid = queuenextid();
5442 static unsigned int cX = 0;
5443 static unsigned int random_offset;
5445 char idbuf[MAXQFNAME - 2];
5448 if (e->e_id != NULL)
5451 /* see if we need to get a new base time/pid */
5452 if (cX >= QIC_LEN_SQR || LastQueueTime == 0 || LastQueuePid != pid)
5454 time_t then = LastQueueTime;
5456 /* if the first time through, pick a random offset */
5457 if (LastQueueTime == 0)
5458 random_offset = ((unsigned int)get_random())
5461 while ((LastQueueTime = curtime()) == then &&
5462 LastQueuePid == pid)
5466 LastQueuePid = queuenextid();
5471 ** Generate a new sequence number between 0 and QIC_LEN_SQR-1.
5472 ** This lets us generate up to QIC_LEN_SQR unique queue ids
5473 ** per second, per process. With envelope splitting,
5474 ** a single message can consume many queue ids.
5477 seq = (cX + random_offset) % QIC_LEN_SQR;
5480 sm_dprintf("assign_queueid: random_offset=%u (%u)\n",
5481 random_offset, seq);
5483 tm = gmtime(&LastQueueTime);
5484 idbuf[0] = QueueIdChars[tm->tm_year % QIC_LEN];
5485 idbuf[1] = QueueIdChars[tm->tm_mon];
5486 idbuf[2] = QueueIdChars[tm->tm_mday];
5487 idbuf[3] = QueueIdChars[tm->tm_hour];
5488 idbuf[4] = QueueIdChars[tm->tm_min % QIC_LEN_R];
5489 idbuf[5] = QueueIdChars[tm->tm_sec % QIC_LEN_R];
5490 idbuf[6] = QueueIdChars[seq / QIC_LEN];
5491 idbuf[7] = QueueIdChars[seq % QIC_LEN];
5492 (void) sm_snprintf(&idbuf[8], sizeof(idbuf) - 8, "%06d",
5493 (int) LastQueuePid);
5494 e->e_id = sm_rpool_strdup_x(e->e_rpool, idbuf);
5495 macdefine(&e->e_macro, A_PERM, 'i', e->e_id);
5497 /* XXX: inherited from MainEnvelope */
5498 e->e_qgrp = NOQGRP; /* too early to do anything else */
5500 e->e_xfqgrp = NOQGRP;
5503 /* New ID means it's not on disk yet */
5504 e->e_qfletter = '\0';
5507 sm_dprintf("assign_queueid: assigned id %s, e=%p\n",
5508 e->e_id, (void *)e);
5510 sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
5513 ** SYNC_QUEUE_TIME -- Assure exclusive PID in any given second
5515 ** Make sure one PID can't be used by two processes in any one second.
5517 ** If the system rotates PIDs fast enough, may get the
5518 ** same pid in the same second for two distinct processes.
5519 ** This will interfere with the queue file naming system.
5531 #if FAST_PID_RECYCLE
5532 if (OpMode != MD_TEST &&
5533 OpMode != MD_CHECKCONFIG &&
5534 OpMode != MD_VERIFY &&
5535 LastQueueTime > 0 &&
5536 LastQueuePid == CurrentPid &&
5537 curtime() == LastQueueTime)
5539 #endif /* FAST_PID_RECYCLE */
5542 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope
5545 ** e -- the envelope to unlock.
5551 ** unlocks the queue for `e'.
5559 sm_dprintf("unlockqueue(%s)\n",
5560 e->e_id == NULL ? "NOQUEUE" : e->e_id);
5563 /* if there is a lock file in the envelope, close it */
5564 if (e->e_lockfp != NULL)
5565 (void) sm_io_close(e->e_lockfp, SM_TIME_DEFAULT);
5568 /* don't create a queue id if we don't already have one */
5569 if (e->e_id == NULL)
5572 /* remove the transcript */
5574 sm_syslog(LOG_DEBUG, e->e_id, "unlock");
5576 (void) xunlink(queuename(e, XSCRPT_LETTER));
5579 ** SETCTLUSER -- create a controlling address
5581 ** Create a fake "address" given only a local login name; this is
5582 ** used as a "controlling user" for future recipient addresses.
5585 ** user -- the user name of the controlling user.
5586 ** qfver -- the version stamp of this queue file.
5590 ** An address descriptor for the controlling user,
5591 ** using storage allocated from e->e_rpool.
5596 setctluser(user, qfver, e)
5601 register ADDRESS *a;
5606 ** See if this clears our concept of controlling user.
5609 if (user == NULL || *user == '\0')
5613 ** Set up addr fields for controlling user.
5616 a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof(*a));
5617 memset((char *) a, '\0', sizeof(*a));
5622 a->q_user = sm_rpool_strdup_x(e->e_rpool, p);
5626 p = strtok(user, ":");
5627 a->q_user = sm_rpool_strdup_x(e->e_rpool, user);
5630 if ((p = strtok(NULL, ":")) != NULL)
5632 if ((p = strtok(NULL, ":")) != NULL)
5634 if ((p = strtok(NULL, ":")) != NULL)
5638 a->q_flags |= QGOODUID;
5640 /* if there is another ':': restore it */
5641 if ((o = strtok(NULL, ":")) != NULL && o > p)
5645 else if ((pw = sm_getpwnam(user)) != NULL)
5647 if (*pw->pw_dir == '\0')
5649 else if (strcmp(pw->pw_dir, "/") == 0)
5652 a->q_home = sm_rpool_strdup_x(e->e_rpool, pw->pw_dir);
5653 a->q_uid = pw->pw_uid;
5654 a->q_gid = pw->pw_gid;
5655 a->q_flags |= QGOODUID;
5659 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */
5660 a->q_mailer = LocalMailer;
5662 a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user);
5664 a->q_paddr = sm_rpool_strdup_x(e->e_rpool, p);
5668 ** LOSEQFILE -- rename queue file with LOSEQF_LETTER & try to let someone know
5671 ** e -- the envelope (e->e_id will be used).
5672 ** why -- reported to whomever can hear.
5680 register ENVELOPE *e;
5685 char buf[MAXPATHLEN];
5687 if (e == NULL || e->e_id == NULL)
5689 p = queuename(e, ANYQFL_LETTER);
5690 if (sm_strlcpy(buf, p, sizeof(buf)) >= sizeof(buf))
5692 if (!bitset(EF_INQUEUE, e->e_flags))
5693 queueup(e, false, true);
5694 else if (QueueMode == QM_LOST)
5697 /* if already lost, no need to re-lose */
5700 p = queuename(e, LOSEQF_LETTER);
5701 if (rename(buf, p) < 0)
5702 syserr("cannot rename(%s, %s), uid=%ld",
5703 buf, p, (long) geteuid());
5704 else if (LogLevel > 0)
5705 sm_syslog(LOG_ALERT, e->e_id,
5706 "Losing %s: %s", buf, why);
5708 if (e->e_dfp != NULL)
5710 (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
5713 e->e_flags &= ~EF_HAS_DF;
5716 ** NAME2QID -- translate a queue group name to a queue group id
5719 ** queuename -- name of queue group.
5722 ** queue group id if found.
5723 ** NOQGRP otherwise.
5732 s = stab(queuename, ST_QUEUE, ST_FIND);
5735 return s->s_quegrp->qg_index;
5738 ** QID_PRINTNAME -- create externally printable version of queue id
5741 ** e -- the envelope.
5744 ** a printable version
5752 static char idbuf[MAXQFNAME + 34];
5757 if (e->e_id == NULL)
5762 if (e->e_qdir == NOQDIR)
5765 (void) sm_snprintf(idbuf, sizeof(idbuf), "%.32s/%s",
5766 Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_name,
5771 ** QID_PRINTQUEUE -- create full version of queue directory for data files
5774 ** qgrp -- index in queue group.
5775 ** qdir -- the short version of the queue directory
5778 ** the full pathname to the queue (might point to a static var)
5782 qid_printqueue(qgrp, qdir)
5787 static char dir[MAXPATHLEN];
5790 return Queue[qgrp]->qg_qdir;
5792 if (strcmp(Queue[qgrp]->qg_qpaths[qdir].qp_name, ".") == 0)
5795 subdir = Queue[qgrp]->qg_qpaths[qdir].qp_name;
5797 (void) sm_strlcpyn(dir, sizeof(dir), 4,
5798 Queue[qgrp]->qg_qdir,
5799 subdir == NULL ? "" : "/",
5800 subdir == NULL ? "" : subdir,
5802 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
5808 ** PICKQDIR -- Pick a queue directory from a queue group
5811 ** qg -- queue group
5812 ** fsize -- file size in bytes
5813 ** e -- envelope, or NULL
5816 ** NOQDIR if no queue directory in qg has enough free space to
5817 ** hold a file of size 'fsize', otherwise the index of
5818 ** a randomly selected queue directory which resides on a
5819 ** file system with enough disk space.
5820 ** XXX This could be extended to select a queuedir with
5821 ** a few (the fewest?) number of entries. That data
5822 ** is available if shared memory is used.
5825 ** If the request fails and e != NULL then sm_syslog is called.
5829 pickqdir(qg, fsize, e)
5838 /* Pick a random directory, as a starting point. */
5839 if (qg->qg_numqueues <= 1)
5842 qdir = get_rand_mod(qg->qg_numqueues);
5848 if (MinBlocksFree <= 0 && fsize <= 0)
5852 ** Now iterate over the queue directories,
5853 ** looking for a directory with enough space for this message.
5859 QPATHS *qp = &qg->qg_qpaths[i];
5864 needed += fsize / FILE_SYS_BLKSIZE(qp->qp_fsysidx)
5865 + ((fsize % FILE_SYS_BLKSIZE(qp->qp_fsysidx)
5867 if (MinBlocksFree > 0)
5868 needed += MinBlocksFree;
5869 fsavail = FILE_SYS_AVAIL(qp->qp_fsysidx);
5876 ** might be not correctly updated,
5877 ** let's try to get the info directly.
5880 fsavail = freediskspace(FILE_SYS_NAME(qp->qp_fsysidx),
5885 #endif /* SM_CONF_SHM */
5886 if (needed <= fsavail)
5888 if (avail < fsavail)
5891 if (qg->qg_numqueues > 0)
5892 i = (i + 1) % qg->qg_numqueues;
5893 } while (i != qdir);
5895 if (e != NULL && LogLevel > 0)
5896 sm_syslog(LOG_ALERT, e->e_id,
5897 "low on space (%s needs %ld bytes + %ld blocks in %s), max avail: %ld",
5898 CurHostName == NULL ? "SMTP-DAEMON" : CurHostName,
5899 fsize, MinBlocksFree,
5900 qg->qg_qdir, avail);
5904 ** SETNEWQUEUE -- Sets a new queue group and directory
5906 ** Assign a queue group and directory to an envelope and store the
5907 ** directory in e->e_qdir.
5910 ** e -- envelope to assign a queue for.
5913 ** true if successful
5917 ** On success, e->e_qgrp and e->e_qdir are non-negative.
5918 ** On failure (not enough disk space),
5919 ** e->qgrp = NOQGRP, e->e_qdir = NOQDIR
5920 ** and usrerr() is invoked (which could raise an exception).
5928 sm_dprintf("setnewqueue: called\n");
5930 /* not set somewhere else */
5931 if (e->e_qgrp == NOQGRP)
5936 ** Use the queue group of the "first" recipient, as set by
5937 ** the "queuegroup" rule set. If that is not defined, then
5938 ** use the queue group of the mailer of the first recipient.
5939 ** If that is not defined either, then use the default
5941 ** Notice: "first" depends on the sorting of sendqueue
5943 ** To avoid problems with "bad" recipients look
5944 ** for a valid address first.
5949 (QS_IS_BADADDR(q->q_state) || QS_IS_DEAD(q->q_state)))
5955 else if (q->q_qgrp >= 0)
5956 e->e_qgrp = q->q_qgrp;
5957 else if (q->q_mailer != NULL &&
5958 ISVALIDQGRP(q->q_mailer->m_qgrp))
5959 e->e_qgrp = q->q_mailer->m_qgrp;
5962 e->e_dfqgrp = e->e_qgrp;
5965 if (ISVALIDQDIR(e->e_qdir) && ISVALIDQDIR(e->e_dfqdir))
5968 sm_dprintf("setnewqueue: e_qdir already assigned (%s)\n",
5969 qid_printqueue(e->e_qgrp, e->e_qdir));
5974 e->e_qdir = pickqdir(Queue[e->e_qgrp], e->e_msgsize, e);
5975 if (e->e_qdir == NOQDIR)
5978 if (!bitset(EF_FATALERRS, e->e_flags))
5979 usrerr("452 4.4.5 Insufficient disk space; try again later");
5980 e->e_flags |= EF_FATALERRS;
5985 sm_dprintf("setnewqueue: Assigned queue directory %s\n",
5986 qid_printqueue(e->e_qgrp, e->e_qdir));
5988 if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR)
5990 e->e_xfqgrp = e->e_qgrp;
5991 e->e_xfqdir = e->e_qdir;
5993 e->e_dfqdir = e->e_qdir;
5997 ** CHKQDIR -- check a queue directory
6000 ** name -- name of queue directory
6001 ** sff -- flags for safefile()
6004 ** is it a queue directory?
6007 static bool chkqdir __P((char *, long));
6017 /* skip over . and .. directories */
6018 if (name[0] == '.' &&
6019 (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
6022 if (lstat(name, &statb) < 0)
6024 if (stat(name, &statb) < 0)
6028 sm_dprintf("chkqdir: stat(\"%s\"): %s\n",
6029 name, sm_errstring(errno));
6033 if (S_ISLNK(statb.st_mode))
6036 ** For a symlink we need to make sure the
6037 ** target is a directory
6040 if (stat(name, &statb) < 0)
6043 sm_dprintf("chkqdir: stat(\"%s\"): %s\n",
6044 name, sm_errstring(errno));
6048 #endif /* HASLSTAT */
6050 if (!S_ISDIR(statb.st_mode))
6053 sm_dprintf("chkqdir: \"%s\": Not a directory\n",
6058 /* Print a warning if unsafe (but still use it) */
6059 /* XXX do this only if we want the warning? */
6060 i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0);
6064 sm_dprintf("chkqdir: \"%s\": Not safe: %s\n",
6065 name, sm_errstring(i));
6068 sm_syslog(LOG_WARNING, NOQID,
6069 "queue directory \"%s\": Not safe: %s",
6070 name, sm_errstring(i));
6071 #endif /* _FFR_CHK_QUEUE */
6076 ** MULTIQUEUE_CACHE -- cache a list of paths to queues.
6078 ** Each potential queue is checked as the cache is built.
6079 ** Thereafter, each is blindly trusted.
6080 ** Note that we can be called again after a timeout to rebuild
6081 ** (although code for that is not ready yet).
6084 ** basedir -- base of all queue directories.
6085 ** blen -- strlen(basedir).
6086 ** qg -- queue group.
6087 ** qn -- number of queue directories already cached.
6088 ** phash -- pointer to hash value over queue dirs.
6090 ** only used if shared memory is active.
6091 #endif * SM_CONF_SHM *
6094 ** new number of queue directories.
6097 #define INITIAL_SLOTS 20
6098 #define ADD_SLOTS 10
6101 multiqueue_cache(basedir, blen, qg, qn, phash)
6106 unsigned int *phash;
6111 long sff = SFF_ANYFILE;
6112 char qpath[MAXPATHLEN];
6113 char subdir[MAXPATHLEN];
6114 char prefix[MAXPATHLEN]; /* dir relative to basedir */
6117 sm_dprintf("multiqueue_cache: called\n");
6119 /* Initialize to current directory */
6122 if (qg->qg_numqueues != 0 && qg->qg_qpaths != NULL)
6124 for (i = 0; i < qg->qg_numqueues; i++)
6126 if (qg->qg_qpaths[i].qp_name != NULL)
6127 (void) sm_free(qg->qg_qpaths[i].qp_name); /* XXX */
6129 (void) sm_free((char *) qg->qg_qpaths); /* XXX */
6130 qg->qg_qpaths = NULL;
6131 qg->qg_numqueues = 0;
6134 /* If running as root, allow safedirpath() checks to use privs */
6138 sff |= SFF_SAFEDIRPATH|SFF_NOWWFILES;
6140 sff |= SFF_NOGWFILES;
6143 if (!SM_IS_DIR_START(qg->qg_qdir))
6146 ** XXX we could add basedir, but then we have to realloc()
6147 ** the string... Maybe another time.
6150 syserr("QueuePath %s not absolute", qg->qg_qdir);
6151 ExitStat = EX_CONFIG;
6155 /* qpath: directory of current workgroup */
6156 len = sm_strlcpy(qpath, qg->qg_qdir, sizeof(qpath));
6157 if (len >= sizeof(qpath))
6159 syserr("QueuePath %.256s too long (%d max)",
6160 qg->qg_qdir, (int) sizeof(qpath));
6161 ExitStat = EX_CONFIG;
6165 /* begin of qpath must be same as basedir */
6166 if (strncmp(basedir, qpath, blen) != 0 &&
6167 (strncmp(basedir, qpath, blen - 1) != 0 || len != blen - 1))
6169 syserr("QueuePath %s not subpath of QueueDirectory %s",
6171 ExitStat = EX_CONFIG;
6175 /* Do we have a nested subdirectory? */
6176 if (blen < len && SM_FIRST_DIR_DELIM(qg->qg_qdir + blen) != NULL)
6179 /* Copy subdirectory into prefix for later use */
6180 if (sm_strlcpy(prefix, qg->qg_qdir + blen, sizeof(prefix)) >=
6183 syserr("QueuePath %.256s too long (%d max)",
6184 qg->qg_qdir, (int) sizeof(qpath));
6185 ExitStat = EX_CONFIG;
6188 cp = SM_LAST_DIR_DELIM(prefix);
6189 SM_ASSERT(cp != NULL);
6190 *cp = '\0'; /* cut off trailing / */
6193 /* This is guaranteed by the basedir check above */
6194 SM_ASSERT(len >= blen - 1);
6195 cp = &qpath[len - 1];
6199 register struct dirent *d;
6202 char relpath[MAXPATHLEN];
6204 *cp = '\0'; /* Overwrite wildcard */
6205 if ((cp = SM_LAST_DIR_DELIM(qpath)) == NULL)
6207 syserr("QueueDirectory: can not wildcard relative path");
6209 sm_dprintf("multiqueue_cache: \"%s*\": Can not wildcard relative path.\n",
6211 ExitStat = EX_CONFIG;
6217 ** Special case of top level wildcard, like /foo*
6221 (void) sm_strlcpy(qpath + 1, qpath, sizeof(qpath) - 1);
6225 *(cp++) = '\0'; /* Replace / with \0 */
6226 len = strlen(cp); /* Last component of queue directory */
6229 ** Path relative to basedir, with trailing /
6230 ** It will be modified below to specify the subdirectories
6231 ** so they can be opened without chdir().
6234 off = sm_strlcpyn(relpath, sizeof(relpath), 2, prefix, "/");
6235 SM_ASSERT(off < sizeof(relpath));
6238 sm_dprintf("multiqueue_cache: prefix=\"%s%s\"\n",
6241 /* It is always basedir: we don't need to store it per group */
6242 /* XXX: optimize this! -> one more global? */
6243 qg->qg_qdir = newstr(basedir);
6244 qg->qg_qdir[blen - 1] = '\0'; /* cut off trailing / */
6247 ** XXX Should probably wrap this whole loop in a timeout
6248 ** in case some wag decides to NFS mount the queues.
6251 /* Test path to get warning messages. */
6254 /* XXX qg_runasuid and qg_runasgid for specials? */
6255 i = safedirpath(basedir, RunAsUid, RunAsGid, NULL,
6257 if (i != 0 && tTd(41, 2))
6258 sm_dprintf("multiqueue_cache: \"%s\": Not safe: %s\n",
6259 basedir, sm_errstring(i));
6262 if ((dp = opendir(prefix)) == NULL)
6264 syserr("can not opendir(%s/%s)", qg->qg_qdir, prefix);
6266 sm_dprintf("multiqueue_cache: opendir(\"%s/%s\"): %s\n",
6267 qg->qg_qdir, prefix,
6268 sm_errstring(errno));
6269 ExitStat = EX_CONFIG;
6272 while ((d = readdir(dp)) != NULL)
6274 /* Skip . and .. directories */
6275 if (strcmp(d->d_name, ".") == 0 ||
6276 strcmp(d->d_name, "..") == 0)
6279 i = strlen(d->d_name);
6280 if (i < len || strncmp(d->d_name, cp, len) != 0)
6283 sm_dprintf("multiqueue_cache: \"%s\", skipped\n",
6288 /* Create relative pathname: prefix + local directory */
6289 i = sizeof(relpath) - off;
6290 if (sm_strlcpy(relpath + off, d->d_name, i) >= i)
6291 continue; /* way too long */
6293 if (!chkqdir(relpath, sff))
6296 if (qg->qg_qpaths == NULL)
6298 slotsleft = INITIAL_SLOTS;
6299 qg->qg_qpaths = (QPATHS *)xalloc((sizeof(*qg->qg_qpaths)) *
6301 qg->qg_numqueues = 0;
6303 else if (slotsleft < 1)
6305 qg->qg_qpaths = (QPATHS *)sm_realloc((char *)qg->qg_qpaths,
6306 (sizeof(*qg->qg_qpaths)) *
6309 if (qg->qg_qpaths == NULL)
6311 (void) closedir(dp);
6314 slotsleft += ADD_SLOTS;
6318 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs = QP_NOSUB;
6320 #define CHKRSUBDIR(name, flag) \
6321 (void) sm_strlcpyn(subdir, sizeof(subdir), 3, relpath, "/", name); \
6322 if (chkqdir(subdir, sff)) \
6323 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs |= flag; \
6327 CHKRSUBDIR("qf", QP_SUBQF);
6328 CHKRSUBDIR("df", QP_SUBDF);
6329 CHKRSUBDIR("xf", QP_SUBXF);
6331 /* assert(strlen(d->d_name) < MAXPATHLEN - 14) */
6332 /* maybe even - 17 (subdirs) */
6334 if (prefix[0] != '.')
6335 qg->qg_qpaths[qg->qg_numqueues].qp_name =
6338 qg->qg_qpaths[qg->qg_numqueues].qp_name =
6342 sm_dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n",
6343 qg->qg_numqueues, relpath,
6344 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs);
6346 qg->qg_qpaths[qg->qg_numqueues].qp_idx = qn;
6347 *phash = hash_q(relpath, *phash);
6353 (void) closedir(dp);
6358 if (qg->qg_numqueues == 0)
6360 qg->qg_qpaths = (QPATHS *) xalloc(sizeof(*qg->qg_qpaths));
6362 /* test path to get warning messages */
6363 i = safedirpath(qpath, RunAsUid, RunAsGid, NULL, sff, 0, 0);
6366 syserr("can not opendir(%s)", qpath);
6368 sm_dprintf("multiqueue_cache: opendir(\"%s\"): %s\n",
6369 qpath, sm_errstring(i));
6370 ExitStat = EX_CONFIG;
6374 qg->qg_qpaths[0].qp_subdirs = QP_NOSUB;
6375 qg->qg_numqueues = 1;
6378 #define CHKSUBDIR(name, flag) \
6379 (void) sm_strlcpyn(subdir, sizeof(subdir), 3, qg->qg_qdir, "/", name); \
6380 if (chkqdir(subdir, sff)) \
6381 qg->qg_qpaths[0].qp_subdirs |= flag; \
6384 CHKSUBDIR("qf", QP_SUBQF);
6385 CHKSUBDIR("df", QP_SUBDF);
6386 CHKSUBDIR("xf", QP_SUBXF);
6388 if (qg->qg_qdir[blen - 1] != '\0' &&
6389 qg->qg_qdir[blen] != '\0')
6392 ** Copy the last component into qpaths and
6396 qg->qg_qpaths[0].qp_name = newstr(qg->qg_qdir + blen);
6397 qg->qg_qdir[blen - 1] = '\0';
6400 qg->qg_qpaths[0].qp_name = newstr(".");
6403 qg->qg_qpaths[0].qp_idx = qn;
6404 *phash = hash_q(qg->qg_qpaths[0].qp_name, *phash);
6412 ** FILESYS_FIND -- find entry in FileSys table, or add new one
6414 ** Given the pathname of a directory, determine the file system
6415 ** in which that directory resides, and return a pointer to the
6416 ** entry in the FileSys table that describes the file system.
6417 ** A new entry is added if necessary (and requested).
6418 ** If the directory does not exist, -1 is returned.
6421 ** name -- name of directory (must be persistent!)
6422 ** path -- pathname of directory (name plus maybe "/df")
6423 ** add -- add to structure if not found.
6426 ** >=0: found: index in file system table
6427 ** <0: some error, i.e.,
6428 ** FSF_TOO_MANY: too many filesystems (-> syserr())
6429 ** FSF_STAT_FAIL: can't stat() filesystem (-> syserr())
6430 ** FSF_NOT_FOUND: not in list
6433 static short filesys_find __P((const char *, const char *, bool));
6435 #define FSF_NOT_FOUND (-1)
6436 #define FSF_STAT_FAIL (-2)
6437 #define FSF_TOO_MANY (-3)
6440 filesys_find(name, path, add)
6448 if (stat(path, &st) < 0)
6450 syserr("cannot stat queue directory %s", path);
6451 return FSF_STAT_FAIL;
6453 for (i = 0; i < NumFileSys; ++i)
6455 if (FILE_SYS_DEV(i) == st.st_dev)
6458 ** Make sure the file system (FS) name is set:
6459 ** even though the source code indicates that
6460 ** FILE_SYS_DEV() is only set below, it could be
6461 ** set via shared memory, hence we need to perform
6462 ** this check/assignment here.
6465 if (NULL == FILE_SYS_NAME(i))
6466 FILE_SYS_NAME(i) = name;
6470 if (i >= MAXFILESYS)
6472 syserr("too many queue file systems (%d max)", MAXFILESYS);
6473 return FSF_TOO_MANY;
6476 return FSF_NOT_FOUND;
6479 FILE_SYS_NAME(i) = name;
6480 FILE_SYS_DEV(i) = st.st_dev;
6481 FILE_SYS_AVAIL(i) = 0;
6482 FILE_SYS_BLKSIZE(i) = 1024; /* avoid divide by zero */
6487 ** FILESYS_SETUP -- set up mapping from queue directories to file systems
6489 ** This data structure is used to efficiently check the amount of
6490 ** free space available in a set of queue directories.
6493 ** add -- initialize structure if necessary.
6497 ** <0: some error, i.e.,
6498 ** FSF_NOT_FOUND: not in list
6499 ** FSF_STAT_FAIL: can't stat() filesystem (-> syserr())
6500 ** FSF_TOO_MANY: too many filesystems (-> syserr())
6503 static int filesys_setup __P((bool));
6514 for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
6516 for (j = 0; j < Queue[i]->qg_numqueues; ++j)
6518 QPATHS *qp = &Queue[i]->qg_qpaths[j];
6519 char qddf[MAXPATHLEN];
6521 (void) sm_strlcpyn(qddf, sizeof(qddf), 2, qp->qp_name,
6522 (bitset(QP_SUBDF, qp->qp_subdirs)
6524 fs = filesys_find(qp->qp_name, qddf, add);
6526 qp->qp_fsysidx = fs;
6537 ** FILESYS_UPDATE -- update amount of free space on all file systems
6539 ** The FileSys table is used to cache the amount of free space
6540 ** available on all queue directory file systems.
6541 ** This function updates the cached information if it has expired.
6550 ** Updates FileSys table.
6557 long avail, blksize;
6559 static time_t nextupdate = 0;
6563 ** Only the daemon updates the shared memory, i.e.,
6564 ** if shared memory is available but the pid is not the
6565 ** one of the daemon, then don't do anything.
6568 if (ShmId != SM_SHM_NO_ID && DaemonPid != CurrentPid)
6570 #endif /* SM_CONF_SHM */
6572 if (now < nextupdate)
6574 nextupdate = now + FILESYS_UPDATE_INTERVAL;
6575 for (i = 0; i < NumFileSys; ++i)
6577 FILESYS *fs = &FILE_SYS(i);
6579 avail = freediskspace(FILE_SYS_NAME(i), &blksize);
6580 if (avail < 0 || blksize <= 0)
6583 sm_syslog(LOG_ERR, NOQID,
6584 "filesys_update failed: %s, fs=%s, avail=%ld, blocksize=%ld",
6585 sm_errstring(errno),
6586 FILE_SYS_NAME(i), avail, blksize);
6588 fs->fs_blksize = 1024; /* avoid divide by zero */
6589 nextupdate = now + 2; /* let's do this soon again */
6593 fs->fs_avail = avail;
6594 fs->fs_blksize = blksize;
6599 #if _FFR_ANY_FREE_FS
6601 ** FILESYS_FREE -- check whether there is at least one fs with enough space.
6604 ** fsize -- file size in bytes
6607 ** true iff there is one fs with more than fsize bytes free.
6618 for (i = 0; i < NumFileSys; ++i)
6622 if (FILE_SYS_AVAIL(i) < 0 || FILE_SYS_BLKSIZE(i) <= 0)
6624 needed += fsize / FILE_SYS_BLKSIZE(i)
6625 + ((fsize % FILE_SYS_BLKSIZE(i)
6628 if (needed <= FILE_SYS_AVAIL(i))
6633 #endif /* _FFR_ANY_FREE_FS */
6636 ** DISK_STATUS -- show amount of free space in queue directories
6639 ** out -- output file pointer.
6640 ** prefix -- string to output in front of each line.
6647 disk_status(out, prefix)
6652 long avail, blksize;
6655 for (i = 0; i < NumFileSys; ++i)
6657 avail = freediskspace(FILE_SYS_NAME(i), &blksize);
6658 if (avail >= 0 && blksize > 0)
6660 free = (long)((double) avail *
6661 ((double) blksize / 1024));
6665 (void) sm_io_fprintf(out, SM_TIME_DEFAULT,
6676 ** INIT_SEM -- initialize semaphore system
6679 ** owner -- is this the owner of semaphores?
6685 #if _FFR_USE_SEM_LOCKING && SM_CONF_SEM
6686 static int SemId = -1; /* Semaphore Id */
6687 int SemKey = SM_SEM_KEY;
6688 # define SEM_LOCK(r) \
6692 r = sm_sem_acq(SemId, 0, 1); \
6694 # define SEM_UNLOCK(r) \
6697 if (SemId >= 0 && r >= 0) \
6698 r = sm_sem_rel(SemId, 0, 1); \
6700 #else /* _FFR_USE_SEM_LOCKING && SM_CONF_SEM */
6701 # define SEM_LOCK(r)
6702 # define SEM_UNLOCK(r)
6703 #endif /* _FFR_USE_SEM_LOCKING && SM_CONF_SEM */
6705 static void init_sem __P((bool));
6711 #if _FFR_USE_SEM_LOCKING
6713 SemId = sm_sem_start(SemKey, 1, 0, owner);
6716 sm_syslog(LOG_ERR, NOQID,
6717 "func=init_sem, sem_key=%ld, sm_sem_start=%d, error=%s",
6718 (long) SemKey, SemId, sm_errstring(-SemId));
6721 if (owner && RunAsUid != 0)
6725 r = sm_semsetowner(SemId, RunAsUid, RunAsGid, 0660);
6727 sm_syslog(LOG_ERR, NOQID,
6728 "key=%ld, sm_semsetowner=%d, RunAsUid=%ld, RunAsGid=%ld",
6729 (long) SemKey, r, (long) RunAsUid, (long) RunAsGid);
6731 #endif /* SM_CONF_SEM */
6732 #endif /* _FFR_USE_SEM_LOCKING */
6737 ** STOP_SEM -- stop semaphore system
6740 ** owner -- is this the owner of semaphores?
6746 static void stop_sem __P((bool));
6752 #if _FFR_USE_SEM_LOCKING
6754 if (owner && SemId >= 0)
6757 #endif /* _FFR_USE_SEM_LOCKING */
6763 ** Todo: call occ_close()
6764 ** when closing a connection to decrease #open connections (and rate!)
6765 ** (currently done as hack in deliver())
6766 ** must also be done if connection couldn't be opened (see daemon.c: OCC_CLOSE)
6770 ** OCC_EXCEEDED -- is an outgoing connection limit exceeded?
6774 ** mci -- mail connection information
6775 ** host -- name of host
6776 ** addr -- address of host
6779 ** true iff an outgoing connection limit is exceeded
6783 occ_exceeded(e, mci, host, addr)
6791 int r, ratelimit, conclimit;
6792 char *limit; /* allocated from e_rpool by rscheck(), no need to free() */
6794 /* if necessary, some error checking for a number could be done here */
6795 #define STR2INT(r, limit, val) \
6798 if ((r) == EX_OK && (limit) != NULL) \
6799 (val) = atoi((limit)); \
6802 if (occ == NULL || e == NULL)
6804 ratelimit = conclimit = 0;
6806 r = rscheck("oc_rate", host, anynet_ntoa(addr), e, RSF_ADDR,
6807 12, NULL, NOQID, NULL, &limit);
6808 STR2INT(r, limit, ratelimit);
6810 r = rscheck("oc_conc", host, anynet_ntoa(addr), e, RSF_ADDR,
6811 12, NULL, NOQID, NULL, &limit);
6812 STR2INT(r, limit, conclimit);
6815 /* lock occ: lock entire shared memory segment */
6817 exc = (bool) conn_limits(e, now, addr, SM_CLFL_EXC, occ, ratelimit,
6820 if (!exc && mci != NULL)
6821 mci->mci_flags |= MCIF_OCC_INCR;
6826 ** OCC_CLOSE -- "close" an outgoing connection: up connection status
6830 ** mci -- mail connection information
6831 ** host -- name of host
6832 ** addr -- address of host
6835 ** true after successful update
6839 occ_close(e, mci, host, addr)
6846 # if _FFR_USE_SEM_LOCKING && SM_CONF_SEM
6850 if (occ == NULL || e == NULL)
6852 if (mci == NULL || mci->mci_state == MCIS_CLOSED ||
6853 bitset(MCIF_CACHED, mci->mci_flags) ||
6854 !bitset(MCIF_OCC_INCR, mci->mci_flags))
6856 mci->mci_flags &= ~MCIF_OCC_INCR;
6860 /* lock occ: lock entire shared memory segment */
6862 (void) conn_limits(e, now, addr, SM_CLFL_EXC, occ, -1, -1);
6866 # endif /* _FFR_OCC */
6869 ** UPD_QS -- update information about queue when adding/deleting an entry
6873 ** count -- add/remove entry (+1/0/-1: add/no change/remove)
6874 ** space -- update the space available as well.
6875 ** (>0/0/<0: add/no change/remove)
6876 ** where -- caller (for logging)
6882 ** Modifies available space in filesystem.
6883 ** Changes number of entries in queue directory.
6887 upd_qs(e, count, space, where)
6895 # if _FFR_USE_SEM_LOCKING
6900 if (ShmId == SM_SHM_NO_ID || e == NULL)
6902 if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR)
6904 idx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_idx;
6906 sm_dprintf("func=upd_qs, count=%d, space=%d, where=%s, idx=%d, entries=%d\n",
6907 count, space, where, idx, QSHM_ENTRIES(idx));
6909 /* XXX in theory this needs to be protected with a mutex */
6910 if (QSHM_ENTRIES(idx) >= 0 && count != 0)
6913 QSHM_ENTRIES(idx) += count;
6917 fidx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_fsysidx;
6921 /* update available space also? (might be loseqfile) */
6925 /* convert size to blocks; this causes rounding errors */
6926 s = e->e_msgsize / FILE_SYS_BLKSIZE(fidx);
6930 /* XXX in theory this needs to be protected with a mutex */
6932 FILE_SYS_AVAIL(fidx) += s;
6934 FILE_SYS_AVAIL(fidx) -= s;
6938 static bool write_key_file __P((char *, long));
6939 static long read_key_file __P((char *, long));
6942 ** WRITE_KEY_FILE -- record some key into a file.
6945 ** keypath -- file name.
6946 ** key -- key to write.
6949 ** true iff file could be written.
6956 write_key_file(keypath, key)
6965 if (keypath == NULL || *keypath == '\0')
6967 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
6968 if (TrustedUid != 0 && RealUid == TrustedUid)
6969 sff |= SFF_OPENASROOT;
6970 keyf = safefopen(keypath, O_WRONLY|O_TRUNC, FileMode, sff);
6973 sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s",
6974 keypath, sm_errstring(errno));
6978 if (geteuid() == 0 && RunAsUid != 0)
6984 if (fd >= 0 && fchown(fd, RunAsUid, -1) < 0)
6988 sm_syslog(LOG_ALERT, NOQID,
6989 "ownership change on %s to %ld failed: %s",
6990 keypath, (long) RunAsUid, sm_errstring(err));
6992 # endif /* HASFCHOWN */
6994 ok = sm_io_fprintf(keyf, SM_TIME_DEFAULT, "%ld\n", key) !=
6996 ok = (sm_io_close(keyf, SM_TIME_DEFAULT) != SM_IO_EOF) && ok;
7002 ** READ_KEY_FILE -- read a key from a file.
7005 ** keypath -- file name.
7006 ** key -- default key.
7013 read_key_file(keypath, key)
7021 if (keypath == NULL || *keypath == '\0')
7023 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY;
7024 if (RealUid == 0 || (TrustedUid != 0 && RealUid == TrustedUid))
7025 sff |= SFF_OPENASROOT;
7026 keyf = safefopen(keypath, O_RDONLY, FileMode, sff);
7029 sm_syslog(LOG_ERR, NOQID, "unable to read %s: %s",
7030 keypath, sm_errstring(errno));
7034 r = sm_io_fscanf(keyf, SM_TIME_DEFAULT, "%ld", &n);
7037 (void) sm_io_close(keyf, SM_TIME_DEFAULT);
7043 ** INIT_SHM -- initialize shared memory structure
7045 ** Initialize or attach to shared memory segment.
7046 ** Currently it is not a fatal error if this doesn't work.
7047 ** However, it causes us to have a "fallback" storage location
7048 ** for everything that is supposed to be in the shared memory,
7049 ** which makes the code slightly ugly.
7052 ** qn -- number of queue directories.
7053 ** owner -- owner of shared memory.
7054 ** hash -- identifies data that is stored in shared memory.
7060 static void init_shm __P((int, bool, unsigned int));
7063 init_shm(qn, owner, hash)
7073 PtrFileSys = &FileSys[0];
7074 PNumFileSys = &Numfilesys;
7075 /* if this "key" is specified: select one yourself */
7076 #define SEL_SHM_KEY ((key_t) -1)
7077 #define FIRST_SHM_KEY 25
7079 /* This allows us to disable shared memory at runtime. */
7084 shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T);
7085 keyselect = ShmKey == SEL_SHM_KEY;
7089 ShmKey = FIRST_SHM_KEY;
7093 ShmKey = read_key_file(ShmKeyFile, ShmKey);
7095 if (ShmKey == SEL_SHM_KEY)
7097 save_errno = (errno != 0) ? errno : EINVAL;
7104 /* allow read/write access for group? */
7105 Pshm = sm_shmstart(ShmKey, shms,
7106 SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3),
7109 if (Pshm != NULL || !sm_file_exists(save_errno))
7117 /* back where we started? */
7118 if (ShmKey == SEL_SHM_KEY)
7125 /* only sleep if we are at the first key */
7126 if (!keyselect || ShmKey == SEL_SHM_KEY)
7134 (void) write_key_file(ShmKeyFile, (long) ShmKey);
7135 if (owner && RunAsUid != 0)
7137 i = sm_shmsetowner(ShmId, RunAsUid, RunAsGid, 0660);
7139 sm_syslog(LOG_ERR, NOQID,
7140 "key=%ld, sm_shmsetowner=%d, RunAsUid=%ld, RunAsGid=%ld",
7141 (long) ShmKey, i, (long) RunAsUid, (long) RunAsGid);
7147 *((pid_t *) SHM_OFF_PID(Pshm)) = CurrentPid;
7148 p = (int *) SHM_OFF_TAG(Pshm);
7153 if (*p != (int) shms)
7155 save_errno = EINVAL;
7159 p = (int *) SHM_OFF_TAG(Pshm);
7160 if (*p != (int) hash)
7162 save_errno = EINVAL;
7168 ** XXX how to check the pid?
7169 ** Read it from the pid-file? That does
7170 ** not need to exist.
7171 ** We could disable shm if we can't confirm
7172 ** that it is the right one.
7176 PtrFileSys = (FILESYS *) OFF_FILE_SYS(Pshm);
7177 PNumFileSys = (int *) OFF_NUM_FILE_SYS(Pshm);
7178 QShm = (QUEUE_SHM_T *) OFF_QUEUE_SHM(Pshm);
7179 PRSATmpCnt = (int *) OFF_RSA_TMP_CNT(Pshm);
7182 occ = (CHash_T *) OFF_OCC_SHM(Pshm);
7186 /* initialize values in shared memory */
7188 for (i = 0; i < qn; i++)
7189 QShm[i].qs_entries = -1;
7191 memset(occ, 0, OCC_SIZE);
7198 if (LogLevel > (owner ? 8 : 11))
7200 sm_syslog(owner ? LOG_ERR : LOG_NOTICE, NOQID,
7201 "can't %s shared memory, key=%ld: %s",
7202 owner ? "initialize" : "attach to",
7203 (long) ShmKey, sm_errstring(save_errno));
7206 #endif /* SM_CONF_SHM */
7210 ** SETUP_QUEUES -- set up all queue groups
7213 ** owner -- owner of shared memory?
7220 ** attaches shared memory.
7221 #endif * SM_CONF_SHM *
7229 unsigned int hashval;
7231 char basedir[MAXPATHLEN];
7235 ** Determine basedir for all queue directories.
7236 ** All queue directories must be (first level) subdirectories
7237 ** of the basedir. The basedir is the QueueDir
7238 ** without wildcards, but with trailing /
7243 len = sm_strlcpy(basedir, QueueDir, sizeof(basedir));
7245 /* Provide space for trailing '/' */
7246 if (len >= sizeof(basedir) - 1)
7248 syserr("QueueDirectory: path too long: %d, max %d",
7249 len, (int) sizeof(basedir) - 1);
7250 ExitStat = EX_CONFIG;
7254 if (basedir[len - 1] == '*')
7258 cp = SM_LAST_DIR_DELIM(basedir);
7261 syserr("QueueDirectory: can not wildcard relative path \"%s\"",
7264 sm_dprintf("setup_queues: \"%s\": Can not wildcard relative path.\n",
7266 ExitStat = EX_CONFIG;
7270 /* cut off wildcard pattern */
7274 else if (!SM_IS_DIR_DELIM(basedir[len - 1]))
7276 /* append trailing slash since it is a directory */
7278 basedir[++len] = '\0';
7281 /* len counts up to the last directory delimiter */
7282 SM_ASSERT(basedir[len - 1] == '/');
7284 if (chdir(basedir) < 0)
7286 int save_errno = errno;
7288 syserr("can not chdir(%s)", basedir);
7289 if (save_errno == EACCES)
7290 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
7291 "Program mode requires special privileges, e.g., root or TrustedUser.\n");
7293 sm_dprintf("setup_queues: \"%s\": %s\n",
7294 basedir, sm_errstring(errno));
7295 ExitStat = EX_CONFIG;
7299 hashval = hash_q(basedir, hashval);
7302 /* initialize for queue runs */
7305 for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
7306 Queue[i]->qg_nextrun = now;
7309 if (UseMSP && OpMode != MD_TEST)
7311 long sff = SFF_CREAT;
7313 if (stat(".", &st) < 0)
7315 syserr("can not stat(%s)", basedir);
7317 sm_dprintf("setup_queues: \"%s\": %s\n",
7318 basedir, sm_errstring(errno));
7319 ExitStat = EX_CONFIG;
7326 ** Check queue directory permissions.
7327 ** Can we write to a group writable queue directory?
7330 if (bitset(S_IWGRP, QueueFileMode) &&
7331 bitset(S_IWGRP, st.st_mode) &&
7332 safefile(" ", RunAsUid, RunAsGid, RunAsUserName, sff,
7333 QueueFileMode, NULL) != 0)
7335 syserr("can not write to queue directory %s (RunAsGid=%ld, required=%ld)",
7336 basedir, (long) RunAsGid, (long) st.st_gid);
7338 if (bitset(S_IWOTH|S_IXOTH, st.st_mode))
7340 #if _FFR_MSP_PARANOIA
7341 syserr("dangerous permissions=%o on queue directory %s",
7342 (unsigned int) st.st_mode, basedir);
7345 sm_syslog(LOG_ERR, NOQID,
7346 "dangerous permissions=%o on queue directory %s",
7347 (unsigned int) st.st_mode, basedir);
7348 #endif /* _FFR_MSP_PARANOIA */
7350 #if _FFR_MSP_PARANOIA
7352 syserr("can not use multiple queues for MSP");
7356 /* initial number of queue directories */
7358 for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
7359 qn = multiqueue_cache(basedir, len, Queue[i], qn, &hashval);
7362 init_shm(qn, owner, hashval);
7363 i = filesys_setup(owner || ShmId == SM_SHM_NO_ID);
7364 if (i == FSF_NOT_FOUND)
7367 ** We didn't get the right filesystem data
7368 ** This may happen if we don't have the right shared memory.
7369 ** So let's do this without shared memory.
7373 cleanup_shm(false); /* release shared memory */
7374 i = filesys_setup(false);
7376 syserr("filesys_setup failed twice, result=%d", i);
7377 else if (LogLevel > 8)
7378 sm_syslog(LOG_WARNING, NOQID,
7379 "shared memory does not contain expected data, ignored");
7381 #else /* SM_CONF_SHM */
7382 i = filesys_setup(true);
7383 #endif /* SM_CONF_SHM */
7385 ExitStat = EX_CONFIG;
7390 ** CLEANUP_SHM -- do some cleanup work for shared memory etc
7393 ** owner -- owner of shared memory?
7399 ** detaches shared memory.
7406 if (ShmId != SM_SHM_NO_ID)
7408 if (sm_shmstop(Pshm, ShmId, owner) < 0 && LogLevel > 8)
7409 sm_syslog(LOG_INFO, NOQID, "sm_shmstop failed=%s",
7410 sm_errstring(errno));
7412 ShmId = SM_SHM_NO_ID;
7416 #endif /* SM_CONF_SHM */
7419 ** CLEANUP_QUEUES -- do some cleanup work for queues
7435 ** SET_DEF_QUEUEVAL -- set default values for a queue group.
7438 ** qg -- queue group
7439 ** all -- set all values (true for default group)?
7445 ** sets default values for the queue group.
7449 set_def_queueval(qg, all)
7453 if (bitnset(QD_DEFINED, qg->qg_flags))
7456 qg->qg_qdir = QueueDir;
7457 #if _FFR_QUEUE_GROUP_SORTORDER
7458 qg->qg_sortorder = QueueSortOrder;
7460 qg->qg_maxqrun = all ? MaxRunnersPerQueue : -1;
7461 qg->qg_nice = NiceQueueRun;
7464 ** MAKEQUEUE -- define a new queue.
7467 ** line -- description of queue. This is in labeled fields.
7469 ** F -- the flags associated with the queue
7470 ** I -- the interval between running the queue
7471 ** J -- the maximum # of jobs in work list
7472 ** [M -- the maximum # of jobs in a queue run]
7473 ** N -- the niceness at which to run
7474 ** P -- the path to the queue
7475 ** S -- the queue sorting order
7476 ** R -- number of parallel queue runners
7477 ** r -- max recipients per envelope
7478 ** The first word is the canonical name of the queue.
7479 ** qdef -- this is a 'Q' definition from .cf
7485 ** enters the queue into the queue table.
7489 makequeue(line, qdef)
7494 register QUEUEGRP *qg;
7499 /* allocate a queue and set up defaults */
7500 qg = (QUEUEGRP *) xalloc(sizeof(*qg));
7501 memset((char *) qg, '\0', sizeof(*qg));
7503 if (line[0] == '\0')
7505 syserr("name required for queue");
7509 /* collect the queue name */
7511 *p != '\0' && *p != ',' && !(SM_ISSPACE(*p));
7516 qg->qg_name = newstr(line);
7518 /* set default values, can be overridden below */
7519 set_def_queueval(qg, false);
7521 /* now scan through and assign info from the fields */
7524 auto char *delimptr;
7526 while (*p != '\0' && (*p == ',' || (SM_ISSPACE(*p))))
7529 /* p now points to field code */
7531 while (*p != '\0' && *p != '=' && *p != ',')
7535 syserr("queue %s: `=' expected", qg->qg_name);
7538 while (SM_ISSPACE(*p))
7541 /* p now points to the field body */
7542 p = munchstring(p, &delimptr, ',');
7544 /* install the field into the queue struct */
7547 case 'P': /* pathname */
7549 syserr("queue %s: empty path name",
7552 qg->qg_qdir = newstr(p);
7555 case 'F': /* flags */
7556 for (; *p != '\0'; p++)
7557 if (!(SM_ISSPACE(*p)))
7558 setbitn(*p, qg->qg_flags);
7562 ** Do we need two intervals here:
7563 ** One for persistent queue runners,
7564 ** one for "normal" queue runs?
7567 case 'I': /* interval between running the queue */
7568 qg->qg_queueintvl = convtime(p, 'm');
7571 case 'N': /* run niceness */
7572 qg->qg_nice = atoi(p);
7575 case 'R': /* maximum # of runners for the group */
7578 /* can't have more runners than allowed total */
7579 if (MaxQueueChildren > 0 && i > MaxQueueChildren)
7581 qg->qg_maxqrun = MaxQueueChildren;
7582 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
7583 "Q=%s: R=%d exceeds MaxQueueChildren=%d, set to MaxQueueChildren\n",
7591 case 'J': /* maximum # of jobs in work list */
7592 qg->qg_maxlist = atoi(p);
7595 case 'r': /* max recipients per envelope */
7596 qg->qg_maxrcpt = atoi(p);
7599 #if _FFR_QUEUE_GROUP_SORTORDER
7600 case 'S': /* queue sorting order */
7603 case 'h': /* Host first */
7605 qg->qg_sortorder = QSO_BYHOST;
7608 case 'p': /* Priority order */
7610 qg->qg_sortorder = QSO_BYPRIORITY;
7613 case 't': /* Submission time */
7615 qg->qg_sortorder = QSO_BYTIME;
7618 case 'f': /* File name */
7620 qg->qg_sortorder = QSO_BYFILENAME;
7623 case 'm': /* Modification time */
7625 qg->qg_sortorder = QSO_BYMODTIME;
7628 case 'r': /* Random */
7630 qg->qg_sortorder = QSO_RANDOM;
7634 case 's': /* Shuffled host name */
7636 qg->qg_sortorder = QSO_BYSHUFFLE;
7638 # endif /* _FFR_RHS */
7640 case 'n': /* none */
7642 qg->qg_sortorder = QSO_NONE;
7646 syserr("Invalid queue sort order \"%s\"", p);
7649 #endif /* _FFR_QUEUE_GROUP_SORTORDER */
7652 syserr("Q%s: unknown queue equate %c=",
7653 qg->qg_name, fcode);
7661 if (qg->qg_nice != NiceQueueRun)
7663 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
7664 "Q%s: Warning: N= set on system that doesn't support nice()\n",
7667 #endif /* !HASNICE */
7669 /* do some rationality checking */
7670 if (NumQueue >= MAXQUEUEGROUPS)
7672 syserr("too many queue groups defined (%d max)",
7677 if (qg->qg_qdir == NULL)
7679 if (QueueDir == NULL || *QueueDir == '\0')
7681 syserr("QueueDir must be defined before queue groups");
7684 qg->qg_qdir = newstr(QueueDir);
7687 if (qg->qg_maxqrun > 1 && !bitnset(QD_FORK, qg->qg_flags))
7689 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
7690 "Warning: Q=%s: R=%d: multiple queue runners specified\n\tbut flag '%c' is not set\n",
7691 qg->qg_name, qg->qg_maxqrun, QD_FORK);
7694 /* enter the queue into the symbol table */
7696 sm_syslog(LOG_INFO, NOQID,
7697 "Adding %s to stab, path: %s", qg->qg_name,
7699 s = stab(qg->qg_name, ST_QUEUE, ST_ENTER);
7700 if (s->s_quegrp != NULL)
7702 i = s->s_quegrp->qg_index;
7704 /* XXX what about the pointers inside this struct? */
7705 sm_free(s->s_quegrp); /* XXX */
7709 Queue[i] = s->s_quegrp = qg;
7712 /* set default value for max queue runners */
7713 if (qg->qg_maxqrun < 0)
7715 if (MaxRunnersPerQueue > 0)
7716 qg->qg_maxqrun = MaxRunnersPerQueue;
7721 setbitn(QD_DEFINED, qg->qg_flags);
7725 ** HASHFQN -- calculate a hash value for a fully qualified host name
7728 ** fqn -- an all lower-case host.domain string
7729 ** buckets -- the number of buckets (queue directories)
7732 ** a bucket number (signed integer)
7735 ** Contributed by Exactis.com, Inc.
7739 hashfqn(fqn, buckets)
7744 register int h = 0, hash, cnt;
7750 ** A variation on the gdb hash
7751 ** This is the best as of Feb 19, 1996 --bcx
7755 h = 0x238F13AF * strlen(p);
7756 for (cnt = 0; *p != 0; ++p, cnt++)
7758 h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF;
7760 h = (1103515243 * h + 12345) & 0x7FFFFFFF;
7764 hash = (h % buckets);
7771 ** A structure for sorting Queue according to maxqrun without
7772 ** screwing up Queue itself.
7777 int sg_idx; /* original index */
7778 int sg_maxqrun; /* max queue runners */
7780 typedef struct sortqgrp SORTQGRP_T;
7781 static int cmpidx __P((const void *, const void *));
7788 /* The sort is highest to lowest, so the comparison is reversed */
7789 if (((SORTQGRP_T *)a)->sg_maxqrun < ((SORTQGRP_T *)b)->sg_maxqrun)
7791 else if (((SORTQGRP_T *)a)->sg_maxqrun > ((SORTQGRP_T *)b)->sg_maxqrun)
7798 ** MAKEWORKGROUPS -- balance queue groups into work groups per MaxQueueChildren
7800 ** Take the now defined queue groups and assign them to work groups.
7801 ** This is done to balance out the number of concurrently active
7802 ** queue runners such that MaxQueueChildren is not exceeded. This may
7803 ** result in more than one queue group per work group. In such a case
7804 ** the number of running queue groups in that work group will have no
7805 ** more than the work group maximum number of runners (a "fair" portion
7806 ** of MaxQueueRunners). All queue groups within a work group will get a
7807 ** chance at running.
7816 ** Sets up WorkGrp structure.
7822 int i, j, total_runners, dir, h;
7823 SORTQGRP_T si[MAXQUEUEGROUPS + 1];
7826 if (NumQueue == 1 && strcmp(Queue[0]->qg_name, "mqueue") == 0)
7829 ** There is only the "mqueue" queue group (a default)
7830 ** containing all of the queues. We want to provide to
7831 ** this queue group the maximum allowable queue runners.
7832 ** To match older behavior (8.10/8.11) we'll try for
7833 ** 1 runner per queue capping it at MaxQueueChildren.
7834 ** So if there are N queues, then there will be N runners
7835 ** for the "mqueue" queue group (where N is kept less than
7836 ** MaxQueueChildren).
7840 WorkGrp[0].wg_numqgrp = 1;
7841 WorkGrp[0].wg_qgs = (QUEUEGRP **) xalloc(sizeof(QUEUEGRP *));
7842 WorkGrp[0].wg_qgs[0] = Queue[0];
7843 if (MaxQueueChildren > 0 &&
7844 Queue[0]->qg_numqueues > MaxQueueChildren)
7845 WorkGrp[0].wg_runners = MaxQueueChildren;
7847 WorkGrp[0].wg_runners = Queue[0]->qg_numqueues;
7849 Queue[0]->qg_wgrp = 0;
7851 /* can't have more runners than allowed total */
7852 if (MaxQueueChildren > 0 &&
7853 Queue[0]->qg_maxqrun > MaxQueueChildren)
7854 Queue[0]->qg_maxqrun = MaxQueueChildren;
7855 WorkGrp[0].wg_maxact = Queue[0]->qg_maxqrun;
7856 WorkGrp[0].wg_lowqintvl = Queue[0]->qg_queueintvl;
7860 for (i = 0; i < NumQueue; i++)
7862 si[i].sg_maxqrun = Queue[i]->qg_maxqrun;
7865 /* Hack to make sure BounceQueue ends up last */
7866 if (IS_BOUNCE_QUEUE(i))
7867 si[i].sg_maxqrun = INT_MIN;
7869 qsort(si, NumQueue, sizeof(si[0]), cmpidx);
7872 for (i = 0; i < NumQueue; i++)
7874 SKIP_BOUNCE_QUEUE(i)
7875 total_runners += si[i].sg_maxqrun;
7876 if (MaxQueueChildren <= 0 || total_runners <= MaxQueueChildren)
7882 if (NumWorkGroups < 1)
7883 NumWorkGroups = 1; /* gotta have one at least */
7884 else if (NumWorkGroups > MAXWORKGROUPS)
7885 NumWorkGroups = MAXWORKGROUPS; /* the limit */
7888 ** We now know the number of work groups to pack the queue groups
7889 ** into. The queue groups in 'Queue' are sorted from highest
7890 ** to lowest for the number of runners per queue group.
7891 ** We put the queue groups with the largest number of runners
7892 ** into work groups first. Then the smaller ones are fitted in
7893 ** where it looks best.
7898 for (i = 0; i < NumQueue; i++)
7902 sm_dprintf("sortqg: i=%d, j=%d, h=%d, skip=%d\n",
7903 i, j, h, IS_BOUNCE_QUEUE(h));
7904 SKIP_BOUNCE_QUEUE(h);
7906 /* a to-and-fro packing scheme, continue from last position */
7907 if (j >= NumWorkGroups)
7910 j = NumWorkGroups - 1;
7918 if (WorkGrp[j].wg_qgs == NULL)
7919 WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_malloc(sizeof(QUEUEGRP *) *
7920 (WorkGrp[j].wg_numqgrp + 1));
7922 WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_realloc(WorkGrp[j].wg_qgs,
7923 sizeof(QUEUEGRP *) *
7924 (WorkGrp[j].wg_numqgrp + 1));
7925 if (WorkGrp[j].wg_qgs == NULL)
7927 syserr("!cannot allocate memory for work queues, need %d bytes",
7928 (int) (sizeof(QUEUEGRP *) *
7929 (WorkGrp[j].wg_numqgrp + 1)));
7932 WorkGrp[j].wg_qgs[WorkGrp[j].wg_numqgrp] = Queue[h];
7933 WorkGrp[j].wg_numqgrp++;
7934 WorkGrp[j].wg_runners += Queue[h]->qg_maxqrun;
7935 Queue[h]->qg_wgrp = j;
7937 if (WorkGrp[j].wg_maxact == 0)
7939 /* can't have more runners than allowed total */
7940 if (MaxQueueChildren > 0 &&
7941 Queue[h]->qg_maxqrun > MaxQueueChildren)
7942 Queue[h]->qg_maxqrun = MaxQueueChildren;
7943 WorkGrp[j].wg_maxact = Queue[h]->qg_maxqrun;
7947 ** XXX: must wg_lowqintvl be the GCD?
7948 ** qg1: 2m, qg2: 3m, minimum: 2m, when do queue runs for
7952 /* keep track of the lowest interval for a persistent runner */
7953 if (Queue[h]->qg_queueintvl > 0 &&
7954 WorkGrp[j].wg_lowqintvl < Queue[h]->qg_queueintvl)
7955 WorkGrp[j].wg_lowqintvl = Queue[h]->qg_queueintvl;
7960 for (i = 0; i < NumWorkGroups; i++)
7962 sm_dprintf("Workgroup[%d]=", i);
7963 for (j = 0; j < WorkGrp[i].wg_numqgrp; j++)
7966 WorkGrp[i].wg_qgs[j]->qg_name);
7969 sm_dprintf("lowqintvl=%d",
7970 (int) WorkGrp[i].wg_lowqintvl);
7977 ** DUP_DF -- duplicate envelope data file
7979 ** Copy the data file from the 'old' envelope to the 'new' envelope
7980 ** in the most efficient way possible.
7982 ** Create a hard link from the 'old' data file to the 'new' data file.
7983 ** If the old and new queue directories are on different file systems,
7984 ** then the new data file link is created in the old queue directory,
7985 ** and the new queue file will contain a 'd' record pointing to the
7986 ** directory containing the new data file.
7989 ** old -- old envelope.
7990 ** new -- new envelope.
7993 ** Returns true on success, false on failure.
7996 ** On success, the new data file is created.
7997 ** On fatal failure, EF_FATALERRS is set in old->e_flags.
8000 static bool dup_df __P((ENVELOPE *, ENVELOPE *));
8008 char opath[MAXPATHLEN];
8009 char npath[MAXPATHLEN];
8011 if (!bitset(EF_HAS_DF, old->e_flags))
8014 ** this can happen if: SuperSafe != True
8015 ** and a bounce mail is sent that is split.
8018 queueup(old, false, true);
8020 SM_REQUIRE(ISVALIDQGRP(old->e_qgrp) && ISVALIDQDIR(old->e_qdir));
8021 SM_REQUIRE(ISVALIDQGRP(new->e_qgrp) && ISVALIDQDIR(new->e_qdir));
8023 (void) sm_strlcpy(opath, queuename(old, DATAFL_LETTER), sizeof(opath));
8024 (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof(npath));
8026 if (old->e_dfp != NULL)
8028 r = sm_io_setinfo(old->e_dfp, SM_BF_COMMIT, NULL);
8029 if (r < 0 && errno != EINVAL)
8031 syserr("@can't commit %s", opath);
8032 old->e_flags |= EF_FATALERRS;
8038 ** Attempt to create a hard link, if we think both old and new
8039 ** are on the same file system, otherwise copy the file.
8041 ** Don't waste time attempting a hard link unless old and new
8042 ** are on the same file system.
8045 SM_REQUIRE(ISVALIDQGRP(old->e_dfqgrp) && ISVALIDQDIR(old->e_dfqdir));
8046 SM_REQUIRE(ISVALIDQGRP(new->e_dfqgrp) && ISVALIDQDIR(new->e_dfqdir));
8048 ofs = Queue[old->e_dfqgrp]->qg_qpaths[old->e_dfqdir].qp_fsysidx;
8049 nfs = Queue[new->e_dfqgrp]->qg_qpaths[new->e_dfqdir].qp_fsysidx;
8050 if (FILE_SYS_DEV(ofs) == FILE_SYS_DEV(nfs))
8052 if (link(opath, npath) == 0)
8054 new->e_flags |= EF_HAS_DF;
8055 SYNC_DIR(npath, true);
8062 ** Can't link across queue directories, so try to create a hard
8063 ** link in the same queue directory as the old df file.
8064 ** The qf file will refer to the new df file using a 'd' record.
8067 new->e_dfqgrp = old->e_dfqgrp;
8068 new->e_dfqdir = old->e_dfqdir;
8069 (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof(npath));
8070 if (link(opath, npath) == 0)
8072 new->e_flags |= EF_HAS_DF;
8073 SYNC_DIR(npath, true);
8079 sm_syslog(LOG_ERR, old->e_id,
8080 "dup_df: can't link %s to %s, error=%s, envelope splitting failed",
8081 opath, npath, sm_errstring(errno));
8086 ** SPLIT_ENV -- Allocate a new envelope based on a given envelope.
8090 ** sendqueue -- sendqueue for new envelope.
8091 ** qgrp -- index of queue group.
8092 ** qdir -- queue directory.
8099 static ENVELOPE *split_env __P((ENVELOPE *, ADDRESS *, int, int));
8102 split_env(e, sendqueue, qgrp, qdir)
8110 ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool, sizeof(*ee));
8111 STRUCTCOPY(*e, *ee);
8112 ee->e_message = NULL; /* XXX use original message? */
8115 ee->e_sendqueue = sendqueue;
8116 ee->e_flags &= ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS
8117 |EF_SENDRECEIPT|EF_RET_PARAM|EF_HAS_DF);
8118 ee->e_flags |= EF_NORECEIPT; /* XXX really? */
8119 ee->e_from.q_state = QS_SENDER;
8121 ee->e_lockfp = NULL;
8122 if (e->e_xfp != NULL)
8123 ee->e_xfp = sm_io_dup(e->e_xfp);
8125 /* failed to dup e->e_xfp, start a new transcript */
8126 if (ee->e_xfp == NULL)
8129 ee->e_qgrp = ee->e_dfqgrp = qgrp;
8130 ee->e_qdir = ee->e_dfqdir = qdir;
8131 ee->e_errormode = EM_MAIL;
8132 ee->e_statmsg = NULL;
8133 if (e->e_quarmsg != NULL)
8134 ee->e_quarmsg = sm_rpool_strdup_x(ee->e_rpool,
8138 ** XXX Not sure if this copying is necessary.
8139 ** sendall() does this copying, but I (dm) don't know if that is
8140 ** because of the storage management discipline we were using
8141 ** before rpools were introduced, or if it is because these lists
8142 ** can be modified later.
8145 ee->e_header = copyheader(e->e_header, ee->e_rpool);
8146 ee->e_errorqueue = copyqueue(e->e_errorqueue, ee->e_rpool);
8151 /* return values from split functions, check also below! */
8152 #define SM_SPLIT_FAIL (0)
8153 #define SM_SPLIT_NONE (1)
8154 #define SM_SPLIT_NEW(n) (1 + (n))
8157 ** SPLIT_ACROSS_QUEUE_GROUPS
8159 ** This function splits an envelope across multiple queue groups
8160 ** based on the queue group of each recipient.
8166 ** SM_SPLIT_FAIL on failure
8167 ** SM_SPLIT_NONE if no splitting occurred,
8168 ** or 1 + the number of additional envelopes created.
8171 ** On success, e->e_sibling points to a list of zero or more
8172 ** additional envelopes, and the associated data files exist
8173 ** on disk. But the queue files are not created.
8175 ** On failure, e->e_sibling is not changed.
8176 ** The order of recipients in e->e_sendqueue is permuted.
8177 ** Abandoned data files for additional envelopes that failed
8178 ** to be created may exist on disk.
8181 static int q_qgrp_compare __P((const void *, const void *));
8182 static int e_filesys_compare __P((const void *, const void *));
8185 q_qgrp_compare(p1, p2)
8189 ADDRESS **pq1 = (ADDRESS **) p1;
8190 ADDRESS **pq2 = (ADDRESS **) p2;
8192 return (*pq1)->q_qgrp - (*pq2)->q_qgrp;
8196 e_filesys_compare(p1, p2)
8200 ENVELOPE **pe1 = (ENVELOPE **) p1;
8201 ENVELOPE **pe2 = (ENVELOPE **) p2;
8204 fs1 = Queue[(*pe1)->e_qgrp]->qg_qpaths[(*pe1)->e_qdir].qp_fsysidx;
8205 fs2 = Queue[(*pe2)->e_qgrp]->qg_qpaths[(*pe2)->e_qdir].qp_fsysidx;
8206 if (FILE_SYS_DEV(fs1) < FILE_SYS_DEV(fs2))
8208 if (FILE_SYS_DEV(fs1) > FILE_SYS_DEV(fs2))
8213 static int split_across_queue_groups __P((ENVELOPE *));
8215 split_across_queue_groups(e)
8218 int naddrs, nsplits, i;
8221 ADDRESS *q, **addrs;
8223 ENVELOPE *splits[MAXQUEUEGROUPS];
8224 char pvpbuf[PSBUFSIZE];
8226 SM_REQUIRE(ISVALIDQGRP(e->e_qgrp));
8228 /* Count addresses and assign queue groups. */
8231 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
8233 if (QS_IS_DEAD(q->q_state))
8237 /* bad addresses and those already sent stay put */
8238 if (QS_IS_BADADDR(q->q_state) ||
8239 QS_IS_SENT(q->q_state))
8240 q->q_qgrp = e->e_qgrp;
8241 else if (!ISVALIDQGRP(q->q_qgrp))
8243 /* call ruleset which should return a queue group */
8244 i = rscap(RS_QUEUEGROUP, q->q_user, NULL, e, &pvp,
8245 pvpbuf, sizeof(pvpbuf));
8247 pvp != NULL && pvp[0] != NULL &&
8248 (pvp[0][0] & 0377) == CANONNET &&
8249 pvp[1] != NULL && pvp[1][0] != '\0')
8251 i = name2qid(pvp[1]);
8257 sm_syslog(LOG_INFO, NOQID,
8258 "queue group name %s -> %d",
8262 else if (LogLevel > 10)
8263 sm_syslog(LOG_INFO, NOQID,
8264 "can't find queue group name %s, selection ignored",
8267 if (q->q_mailer != NULL &&
8268 ISVALIDQGRP(q->q_mailer->m_qgrp))
8271 q->q_qgrp = q->q_mailer->m_qgrp;
8273 else if (ISVALIDQGRP(e->e_qgrp))
8274 q->q_qgrp = e->e_qgrp;
8280 /* only one address? nothing to split. */
8281 if (naddrs <= 1 && !changed)
8282 return SM_SPLIT_NONE;
8284 /* sort the addresses by queue group */
8285 addrs = sm_rpool_malloc_x(e->e_rpool, naddrs * sizeof(ADDRESS *));
8286 for (i = 0, q = e->e_sendqueue; q != NULL; q = q->q_next)
8288 if (QS_IS_DEAD(q->q_state))
8292 qsort(addrs, naddrs, sizeof(ADDRESS *), q_qgrp_compare);
8294 /* split into multiple envelopes, by queue group */
8297 e->e_sendqueue = NULL;
8298 for (i = 0; i < naddrs; ++i)
8300 if (i == naddrs - 1 || addrs[i]->q_qgrp != addrs[i + 1]->q_qgrp)
8301 addrs[i]->q_next = NULL;
8303 addrs[i]->q_next = addrs[i + 1];
8305 /* same queue group as original envelope? */
8306 if (addrs[i]->q_qgrp == e->e_qgrp)
8308 if (e->e_sendqueue == NULL)
8309 e->e_sendqueue = addrs[i];
8313 /* different queue group than original envelope */
8314 if (es == NULL || addrs[i]->q_qgrp != es->e_qgrp)
8316 ee = split_env(e, addrs[i], addrs[i]->q_qgrp, NOQDIR);
8318 splits[nsplits++] = ee;
8322 /* no splits? return right now. */
8324 return SM_SPLIT_NONE;
8326 /* assign a queue directory to each additional envelope */
8327 for (i = 0; i < nsplits; ++i)
8331 es->e_qdir = pickqdir(Queue[es->e_qgrp], es->e_msgsize, es);
8333 if (!setnewqueue(es))
8337 /* sort the additional envelopes by queue file system */
8338 qsort(splits, nsplits, sizeof(ENVELOPE *), e_filesys_compare);
8340 /* create data files for each additional envelope */
8341 if (!dup_df(e, splits[0]))
8346 for (i = 1; i < nsplits; ++i)
8348 /* copy or link to the previous data file */
8349 if (!dup_df(splits[i - 1], splits[i]))
8353 /* success: prepend the new envelopes to the e->e_sibling list */
8354 for (i = 0; i < nsplits; ++i)
8357 es->e_sibling = e->e_sibling;
8360 return SM_SPLIT_NEW(nsplits);
8362 /* failure: clean up */
8368 for (j = 0; j < i; j++)
8369 (void) unlink(queuename(splits[j], DATAFL_LETTER));
8371 e->e_sendqueue = addrs[0];
8372 for (i = 0; i < naddrs - 1; ++i)
8373 addrs[i]->q_next = addrs[i + 1];
8374 addrs[naddrs - 1]->q_next = NULL;
8375 return SM_SPLIT_FAIL;
8379 ** SPLIT_WITHIN_QUEUE
8381 ** Split an envelope with multiple recipients into several
8382 ** envelopes within the same queue directory, if the number of
8383 ** recipients exceeds the limit for the queue group.
8389 ** SM_SPLIT_FAIL on failure
8390 ** SM_SPLIT_NONE if no splitting occurred,
8391 ** or 1 + the number of additional envelopes created.
8394 #define SPLIT_LOG_LEVEL 8
8396 static int split_within_queue __P((ENVELOPE *));
8399 split_within_queue(e)
8402 int maxrcpt, nrcpt, ndead, nsplit, i;
8405 ADDRESS *q, **addrs;
8406 ENVELOPE *ee, *firstsibling;
8408 if (!ISVALIDQGRP(e->e_qgrp) || bitset(EF_SPLIT, e->e_flags))
8409 return SM_SPLIT_NONE;
8411 /* don't bother if there is no recipient limit */
8412 maxrcpt = Queue[e->e_qgrp]->qg_maxrcpt;
8414 return SM_SPLIT_NONE;
8416 /* count recipients */
8418 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
8420 if (QS_IS_DEAD(q->q_state))
8424 if (nrcpt <= maxrcpt)
8425 return SM_SPLIT_NONE;
8428 ** Preserve the recipient list
8429 ** so that we can restore it in case of error.
8430 ** (But we discard dead addresses.)
8433 addrs = sm_rpool_malloc_x(e->e_rpool, nrcpt * sizeof(ADDRESS *));
8434 for (i = 0, q = e->e_sendqueue; q != NULL; q = q->q_next)
8436 if (QS_IS_DEAD(q->q_state))
8442 ** Partition the recipient list so that bad and sent addresses
8443 ** come first. These will go with the original envelope, and
8444 ** do not count towards the maxrcpt limit.
8445 ** addrs[] does not contain QS_IS_DEAD() addresses.
8449 for (i = 0; i < nrcpt; ++i)
8451 if (QS_IS_BADADDR(addrs[i]->q_state) ||
8452 QS_IS_SENT(addrs[i]->q_state) ||
8453 QS_IS_DEAD(addrs[i]->q_state)) /* for paranoia's sake */
8457 ADDRESS *tmp = addrs[i];
8459 addrs[i] = addrs[ndead];
8466 /* Check if no splitting required. */
8467 if (nrcpt - ndead <= maxrcpt)
8468 return SM_SPLIT_NONE;
8471 for (i = 0; i < nrcpt - 1; ++i)
8472 addrs[i]->q_next = addrs[i + 1];
8473 addrs[nrcpt - 1]->q_next = NULL;
8474 e->e_sendqueue = addrs[0];
8476 /* prepare buffer for logging */
8477 if (LogLevel > SPLIT_LOG_LEVEL)
8480 lsplits = sm_malloc(l);
8481 if (lsplits != NULL)
8487 /* get rid of stupid compiler warnings */
8492 /* split the envelope */
8493 firstsibling = e->e_sibling;
8494 i = maxrcpt + ndead;
8498 addrs[i - 1]->q_next = NULL;
8499 ee = split_env(e, addrs[i], e->e_qgrp, e->e_qdir);
8506 (void) unlink(queuename(ee, DATAFL_LETTER));
8510 /* Error. Restore e's sibling & recipient lists. */
8511 e->e_sibling = firstsibling;
8512 for (i = 0; i < nrcpt - 1; ++i)
8513 addrs[i]->q_next = addrs[i + 1];
8514 if (lsplits != NULL)
8516 return SM_SPLIT_FAIL;
8519 /* prepend the new envelope to e->e_sibling */
8520 ee->e_sibling = e->e_sibling;
8523 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL)
8525 if (j >= l - strlen(ee->e_id) - 3)
8530 p = sm_realloc(lsplits, l);
8533 /* let's try to get this done */
8540 if (lsplits != NULL)
8543 j += sm_strlcat(lsplits + j,
8547 j += sm_strlcat2(lsplits + j,
8554 if (nrcpt - i <= maxrcpt)
8558 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL)
8562 sm_syslog(LOG_NOTICE, e->e_id,
8563 "split: maxrcpts=%d, rcpts=%d, count=%d, id%s=%s",
8564 maxrcpt, nrcpt - ndead, nsplit,
8565 nsplit > 1 ? "s" : "", lsplits);
8569 return SM_SPLIT_NEW(nsplit);
8572 ** SPLIT_BY_RECIPIENT
8574 ** Split an envelope with multiple recipients into multiple
8575 ** envelopes as required by the sendmail configuration.
8581 ** Returns true on success, false on failure.
8584 ** see split_across_queue_groups(), split_within_queue(e)
8588 split_by_recipient(e)
8591 int split, n, i, j, l;
8593 ENVELOPE *ee, *next, *firstsibling;
8595 if (OpMode == SM_VERIFY || !ISVALIDQGRP(e->e_qgrp) ||
8596 bitset(EF_SPLIT, e->e_flags))
8598 n = split_across_queue_groups(e);
8599 if (n == SM_SPLIT_FAIL)
8601 firstsibling = ee = e->e_sibling;
8602 if (n > 1 && LogLevel > SPLIT_LOG_LEVEL)
8605 lsplits = sm_malloc(l);
8606 if (lsplits != NULL)
8612 /* get rid of stupid compiler warnings */
8616 for (i = 1; i < n; ++i)
8618 next = ee->e_sibling;
8619 if (split_within_queue(ee) == SM_SPLIT_FAIL)
8621 e->e_sibling = firstsibling;
8625 ee->e_flags |= EF_SPLIT;
8626 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL)
8628 if (j >= l - strlen(ee->e_id) - 3)
8633 p = sm_realloc(lsplits, l);
8636 /* let's try to get this done */
8642 if (lsplits != NULL)
8645 j += sm_strlcat(lsplits + j,
8648 j += sm_strlcat2(lsplits + j, "; ",
8655 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL && n > 1)
8657 sm_syslog(LOG_NOTICE, e->e_id, "split: count=%d, id%s=%s",
8658 n - 1, n > 2 ? "s" : "", lsplits);
8661 split = split_within_queue(e) != SM_SPLIT_FAIL;
8663 e->e_flags |= EF_SPLIT;
8668 ** QUARANTINE_QUEUE_ITEM -- {un,}quarantine a single envelope
8670 ** Add/remove quarantine reason and requeue appropriately.
8673 ** qgrp -- queue group for the item
8674 ** qdir -- queue directory in the given queue group
8675 ** e -- envelope information for the item
8676 ** reason -- quarantine reason, NULL means unquarantine.
8679 ** true if item changed, false otherwise
8682 ** Changes quarantine tag in queue file and renames it.
8686 quarantine_queue_item(qgrp, qdir, e, reason)
8693 bool failing = false;
8694 bool foundq = false;
8695 bool finished = false;
8701 MODE_T oldumask = 0;
8702 SM_FILE_T *oldqfp, *tempqfp;
8705 char oldqf[MAXPATHLEN];
8706 char tempqf[MAXPATHLEN];
8707 char newqf[MAXPATHLEN];
8710 oldtype = queue_letter(e, ANYQFL_LETTER);
8711 (void) sm_strlcpy(oldqf, queuename(e, ANYQFL_LETTER), sizeof(oldqf));
8712 (void) sm_strlcpy(tempqf, queuename(e, NEWQFL_LETTER), sizeof(tempqf));
8715 ** Instead of duplicating all the open
8716 ** and lock code here, tell readqf() to
8717 ** do that work and return the open
8718 ** file pointer in e_lockfp. Note that
8719 ** we must release the locks properly when
8723 if (!readqf(e, true))
8725 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8726 "Skipping %s\n", qid_printname(e));
8729 oldqfp = e->e_lockfp;
8731 /* open the new queue file */
8732 flags = O_CREAT|O_WRONLY|O_EXCL;
8733 if (bitset(S_IWGRP, QueueFileMode))
8734 oldumask = umask(002);
8735 fd = open(tempqf, flags, QueueFileMode);
8736 if (bitset(S_IWGRP, QueueFileMode))
8737 (void) umask(oldumask);
8743 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8744 "Skipping %s: Could not open %s: %s\n",
8745 qid_printname(e), tempqf,
8746 sm_errstring(save_errno));
8747 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
8750 if (!lockfile(fd, tempqf, NULL, LOCK_EX|LOCK_NB))
8752 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8753 "Skipping %s: Could not lock %s\n",
8754 qid_printname(e), tempqf);
8756 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
8760 tempqfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, (void *) &fd,
8761 SM_IO_WRONLY_B, NULL);
8762 if (tempqfp == NULL)
8764 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8765 "Skipping %s: Could not lock %s\n",
8766 qid_printname(e), tempqf);
8768 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
8772 /* Copy the data over, changing the quarantine reason */
8773 while (bufsize = sizeof(buf),
8774 (bp = fgetfolded(buf, &bufsize, oldqfp)) != NULL)
8777 sm_dprintf("+++++ %s\n", bp);
8780 case 'q': /* quarantine reason */
8786 (void) sm_io_fprintf(smioout,
8788 "%s: Removed quarantine of \"%s\"\n",
8791 sm_syslog(LOG_INFO, e->e_id, "unquarantine");
8794 else if (strcmp(reason, &bp[1]) == 0)
8798 (void) sm_io_fprintf(smioout,
8800 "%s: Already quarantined with \"%s\"\n",
8803 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8810 (void) sm_io_fprintf(smioout,
8812 "%s: Quarantine changed from \"%s\" to \"%s\"\n",
8816 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8818 sm_syslog(LOG_INFO, e->e_id, "quarantine=%s",
8826 ** If we are quarantining an unquarantined item,
8827 ** need to put in a new 'q' line before it's
8831 if (!foundq && reason != NULL)
8835 (void) sm_io_fprintf(smioout,
8837 "%s: Quarantined with \"%s\"\n",
8840 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8842 sm_syslog(LOG_INFO, e->e_id, "quarantine=%s",
8848 /* Copy the line to the new file */
8849 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8858 /* Copy the line to the new file */
8859 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8867 /* Make sure we read the whole old file */
8868 errno = sm_io_error(tempqfp);
8869 if (errno != 0 && errno != SM_IO_EOF)
8872 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8873 "Skipping %s: Error reading %s: %s\n",
8874 qid_printname(e), oldqf,
8875 sm_errstring(save_errno));
8879 if (!failing && !finished)
8881 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8882 "Skipping %s: Incomplete file: %s\n",
8883 qid_printname(e), oldqf);
8887 /* Check if we actually changed anything or we can just bail now */
8890 /* pretend we failed, even though we technically didn't */
8894 /* Make sure we wrote things out safely */
8896 (sm_io_flush(tempqfp, SM_TIME_DEFAULT) != 0 ||
8897 ((SuperSafe == SAFE_REALLY ||
8898 SuperSafe == SAFE_REALLY_POSTMILTER ||
8899 SuperSafe == SAFE_INTERACTIVE) &&
8900 fsync(sm_io_getinfo(tempqfp, SM_IO_WHAT_FD, NULL)) < 0) ||
8901 ((errno = sm_io_error(tempqfp)) != 0)))
8904 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8905 "Skipping %s: Error writing %s: %s\n",
8906 qid_printname(e), tempqf,
8907 sm_errstring(save_errno));
8912 /* Figure out the new filename */
8913 newtype = (reason == NULL ? NORMQF_LETTER : QUARQF_LETTER);
8914 if (oldtype == newtype)
8916 /* going to rename tempqf to oldqf */
8917 (void) sm_strlcpy(newqf, oldqf, sizeof(newqf));
8921 /* going to rename tempqf to new name based on newtype */
8922 (void) sm_strlcpy(newqf, queuename(e, newtype), sizeof(newqf));
8927 /* rename tempqf to newqf */
8929 rename(tempqf, newqf) < 0)
8930 save_errno = (errno == 0) ? EINVAL : errno;
8932 /* Check rename() success */
8933 if (!failing && save_errno != 0)
8935 sm_syslog(LOG_DEBUG, e->e_id,
8936 "quarantine_queue_item: rename(%s, %s): %s",
8937 tempqf, newqf, sm_errstring(save_errno));
8939 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8940 "Error renaming %s to %s: %s\n",
8942 sm_errstring(save_errno));
8943 if (oldtype == newtype)
8946 ** Bail here since we don't know the state of
8947 ** the filesystem and may need to keep tempqf
8948 ** for the user to rescue us.
8953 syserr("!452 Error renaming control file %s", tempqf);
8958 /* remove new file (if rename() half completed) */
8959 if (xunlink(newqf) < 0)
8962 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8963 "Error removing %s: %s\n",
8965 sm_errstring(save_errno));
8968 /* tempqf removed below */
8974 /* If changing file types, need to remove old type */
8975 if (!failing && oldtype != newtype)
8977 if (xunlink(oldqf) < 0)
8980 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8981 "Error removing %s: %s\n",
8982 oldqf, sm_errstring(save_errno));
8986 /* see if anything above failed */
8989 /* Something failed: remove new file, old file still there */
8990 (void) xunlink(tempqf);
8994 ** fsync() after file operations to make sure metadata is
8995 ** written to disk on filesystems in which renames are
8996 ** not guaranteed. It's ok if they fail, mail won't be lost.
8999 if (SuperSafe != SAFE_NO)
9001 /* for soft-updates */
9002 (void) fsync(sm_io_getinfo(tempqfp,
9003 SM_IO_WHAT_FD, NULL));
9007 /* for soft-updates */
9008 (void) fsync(sm_io_getinfo(oldqfp,
9009 SM_IO_WHAT_FD, NULL));
9012 /* for other odd filesystems */
9013 SYNC_DIR(tempqf, false);
9018 if (tempqfp != NULL)
9019 (void) sm_io_close(tempqfp, SM_TIME_DEFAULT);
9021 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
9028 ** QUARANTINE_QUEUE -- {un,}quarantine matching items in the queue
9030 ** Read all matching queue items, add/remove quarantine
9031 ** reason, and requeue appropriately.
9034 ** reason -- quarantine reason, "." means unquarantine.
9035 ** qgrplimit -- limit to single queue group unless NOQGRP
9041 ** Lots of changes to the queue.
9045 quarantine_queue(reason, qgrplimit)
9052 /* Convert internal representation of unquarantine */
9053 if (reason != NULL && reason[0] == '.' && reason[1] == '\0')
9059 reason = newstr(denlstring(reason, true, true));
9062 for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++)
9066 if (qgrplimit != NOQGRP && qgrplimit != qgrp)
9069 for (qdir = 0; qdir < Queue[qgrp]->qg_numqueues; qdir++)
9077 nrequests = gatherq(qgrp, qdir, true, NULL, NULL, NULL);
9079 /* first see if there is anything */
9084 (void) sm_io_fprintf(smioout,
9085 SM_TIME_DEFAULT, "%s: no matches\n",
9086 qid_printqueue(qgrp, qdir));
9093 (void) sm_io_fprintf(smioout,
9094 SM_TIME_DEFAULT, "Processing %s:\n",
9095 qid_printqueue(qgrp, qdir));
9098 for (i = 0; i < WorkListCount; i++)
9105 /* setup envelope */
9106 clearenvelope(&e, true, sm_rpool_new_x(NULL));
9107 e.e_id = WorkList[i].w_name + 2;
9113 sm_io_fprintf(smioout, SM_TIME_DEFAULT,
9114 "Would do %s\n", e.e_id);
9117 else if (quarantine_queue_item(qgrp, qdir,
9122 sm_rpool_free(e.e_rpool);
9125 if (WorkList != NULL)
9126 sm_free(WorkList); /* XXX */
9135 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
9138 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
9141 changed == 1 ? "" : "s");