1/*
2 * Copyright (c) 1998-2009, 2011, 2012, 2014 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
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.
7 *
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.
11 *
12 */
13
14#include <sendmail.h>
15#include <sm/sem.h>
16
17SM_RCSID("@(#)$Id: queue.c,v 8.1000 2013-11-22 20:51:56 ca Exp $")
18
19#include <dirent.h>
20
21# define RELEASE_QUEUE	(void) 0
22# define ST_INODE(st)	(st).st_ino
23
24#  define sm_file_exists(errno) ((errno) == EEXIST)
25
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)
29# else
30#  define TF_OPEN_FLAGS (O_CREAT|O_WRONLY|O_EXCL)
31# endif
32
33#ifndef SM_OPEN_EXLOCK
34# define SM_OPEN_EXLOCK 0
35#endif
36
37/*
38**  Historical notes:
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
44*/
45
46#define QF_VERSION	8	/* version number of this queue format */
47
48static char	queue_letter __P((ENVELOPE *, int));
49static bool	quarantine_queue_item __P((int, int, ENVELOPE *, char *));
50
51/* Naming convention: qgrp: index of queue group, qg: QUEUEGROUP */
52
53/*
54**  Work queue.
55*/
56
57struct work
58{
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 */
69};
70
71typedef struct work	WORK;
72
73static WORK	*WorkQ;		/* queue of things to be done */
74static int	NumWorkGroups;	/* number of work groups */
75static time_t	Current_LA_time = 0;
76
77/* Get new load average every 30 seconds. */
78#define GET_NEW_LA_TIME	30
79
80#define SM_GET_LA(now)	\
81	do							\
82	{							\
83		now = curtime();				\
84		if (Current_LA_time < now - GET_NEW_LA_TIME)	\
85		{						\
86			sm_getla();				\
87			Current_LA_time = now;			\
88		}						\
89	} while (0)
90
91/*
92**  DoQueueRun indicates that a queue run is needed.
93**	Notice: DoQueueRun is modified in a signal handler!
94*/
95
96static bool	volatile DoQueueRun; /* non-interrupt time queue run needed */
97
98/*
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.
105*/
106
107struct workgrp
108{
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 */
117};
118
119typedef struct workgrp WORKGRP;
120
121static WORKGRP	volatile WorkGrp[MAXWORKGROUPS + 1];	/* work groups */
122
123#if SM_HEAP_CHECK
124static SM_DEBUG_T DebugLeakQ = SM_DEBUG_INITIALIZER("leak_q",
125	"@(#)$Debug: leak_q - trace memory leaks during queue processing $");
126#endif
127
128static void	grow_wlist __P((int, int));
129static int	multiqueue_cache __P((char *, int, QUEUEGRP *, int, unsigned int *));
130static int	gatherq __P((int, int, bool, bool *, bool *, int *));
131static int	sortq __P((int));
132static void	printctladdr __P((ADDRESS *, SM_FILE_T *));
133static bool	readqf __P((ENVELOPE *, bool));
134static void	restart_work_group __P((int));
135static void	runner_work __P((ENVELOPE *, int, bool, int, int));
136static void	schedule_queue_runs __P((bool, int, bool));
137static char	*strrev __P((char *));
138static ADDRESS	*setctluser __P((char *, int, ENVELOPE *));
139#if _FFR_RHS
140static int	sm_strshufflecmp __P((char *, char *));
141static void	init_shuffle_alphabet __P(());
142#endif
143
144/*
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 *))
148*/
149
150static int	workcmpf0();
151static int	workcmpf1();
152static int	workcmpf2();
153static int	workcmpf3();
154static int	workcmpf4();
155static int	randi = 3;	/* index for workcmpf5() */
156static int	workcmpf5();
157static int	workcmpf6();
158#if _FFR_RHS
159static int	workcmpf7();
160#endif
161
162#if RANDOMSHIFT
163# define get_rand_mod(m)	((get_random() >> RANDOMSHIFT) % (m))
164#else
165# define get_rand_mod(m)	(get_random() % (m))
166#endif
167
168/*
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.
172*/
173
174typedef struct filesys_shared	FILESYS;
175
176struct filesys_shared
177{
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 */
181};
182
183/* probably kept in shared memory */
184static FILESYS	FileSys[MAXFILESYS];	/* queue file systems */
185static const char *FSPath[MAXFILESYS];	/* pathnames for file systems */
186
187#if SM_CONF_SHM
188# include <ratectrl.h>
189
190/*
191**  Shared memory data
192**
193**  Current layout:
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.
202**	[OCC -- ...]
203**	QShm -- (array of) structure for information about queue directories.
204**		this must be last as the size is depending on the config.
205*/
206
207/*
208**  Queue data in shared memory
209*/
210
211typedef struct queue_shared	QUEUE_SHM_T;
212
213struct queue_shared
214{
215	int	qs_entries;	/* number of entries */
216	/* XXX more to follow? */
217};
218
219static void	*Pshm;		/* pointer to shared memory */
220static FILESYS	*PtrFileSys;	/* pointer to queue file system array */
221int		ShmId = SM_SHM_NO_ID;	/* shared memory id */
222static QUEUE_SHM_T	*QShm;		/* pointer to shared queue data */
223static size_t shms;
224
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)
228
229/* how to access FileSys */
230# define FILE_SYS(i)	(PtrFileSys[i])
231
232/* first entry is a tag, for now just the size */
233# define OFF_FILE_SYS(p)	(((char *) (p)) + SHM_OFF_HEAD)
234
235/* offset for PNumFileSys */
236# define OFF_NUM_FILE_SYS(p)	(((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys))
237
238/* offset for PRSATmpCnt */
239# define OFF_RSA_TMP_CNT(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int))
240int	*PRSATmpCnt;
241
242# if _FFR_OCC
243#  define OFF_OCC_SHM(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2)
244#  define OCC_SIZE (sizeof(CHash_T) * CPMHSIZE)
245static CHash_T *occ = NULL;
246# else
247#  define OCC_SIZE 0
248# endif
249
250/* offset for queue_shm */
251# define OFF_QUEUE_SHM(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2 + OCC_SIZE)
252
253# define QSHM_ENTRIES(i)	QShm[i].qs_entries
254
255/* basic size of shared memory segment */
256# define SM_T_SIZE	(SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2 + OCC_SIZE)
257
258static unsigned int	hash_q __P((char *, unsigned int));
259
260/*
261**  HASH_Q -- simple hash function
262**
263**	Parameters:
264**		p -- string to hash.
265**		h -- hash start value (from previous run).
266**
267**	Returns:
268**		hash value.
269*/
270
271static unsigned int
272hash_q(p, h)
273	char *p;
274	unsigned int h;
275{
276	int c, d;
277
278	while (*p != '\0')
279	{
280		d = *p++;
281		c = d;
282		c ^= c<<6;
283		h += (c<<11) ^ (c>>1);
284		h ^= (d<<14) + (d<<7) + (d<<4) + d;
285	}
286	return h;
287}
288
289#else /* SM_CONF_SHM */
290# define FILE_SYS(i)	FileSys[i]
291#endif /* SM_CONF_SHM */
292
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
298
299
300/*
301**  Current qf file field assignments:
302**
303**	A	AUTH= parameter
304**	B	body type
305**	C	controlling user
306**	D	data file name (obsolete)
307**	d	data file directory name (added in 8.12)
308**	E	error recipient
309**	F	flag bits
310**	H	header
311**	I	data file's inode number
312**	K	time of last delivery attempt
313**	L	Solaris Content-Length: header (obsolete)
314**	M	message
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)
320**	R	recipient
321**	S	sender
322**	T	init time
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)
327**	$	define macro
328**	.	terminate file
329*/
330
331/*
332**  QUEUEUP -- queue a message up for future transmission.
333**
334**	Parameters:
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.
338**
339**	Returns:
340**		none.
341**
342**	Side Effects:
343**		The current request is saved in a control file.
344**		The queue file is left locked.
345*/
346
347void
348queueup(e, announce, msync)
349	register ENVELOPE *e;
350	bool announce;
351	bool msync;
352{
353	register SM_FILE_T *tfp;
354	register HDR *h;
355	register ADDRESS *q;
356	int tfd = -1;
357	int i;
358	bool newid;
359	register char *p;
360	MAILER nullmailer;
361	MCI mcibuf;
362	char qf[MAXPATHLEN];
363	char tf[MAXPATHLEN];
364	char df[MAXPATHLEN];
365	char buf[MAXLINE];
366
367	/*
368	**  Create control file.
369	*/
370
371#define OPEN_TF	do							\
372		{							\
373			MODE_T oldumask = 0;				\
374									\
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);			\
380		} while (0)
381
382
383	newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
384	(void) sm_strlcpy(tf, queuename(e, NEWQFL_LETTER), sizeof(tf));
385	tfp = e->e_lockfp;
386	if (tfp == NULL && newid)
387	{
388		/*
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).
392		*/
393
394		(void) sm_strlcpy(tf, queuename(e, ANYQFL_LETTER), sizeof(tf));
395		OPEN_TF;
396		if (tfd < 0 ||
397#if !SM_OPEN_EXLOCK
398		    !lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB) ||
399#endif
400		    (tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
401					 (void *) &tfd, SM_IO_WRONLY,
402					 NULL)) == NULL)
403		{
404			int save_errno = errno;
405
406			printopenfds(true);
407			errno = save_errno;
408			syserr("!queueup: cannot create queue file %s, euid=%ld, fd=%d, fp=%p",
409				tf, (long) geteuid(), tfd, (void *)tfp);
410			/* NOTREACHED */
411		}
412		e->e_lockfp = tfp;
413		upd_qs(e, 1, 0, "queueup");
414	}
415
416	/* if newid, write the queue file directly (instead of temp file) */
417	if (!newid)
418	{
419		/* get a locked tf file */
420		for (i = 0; i < 128; i++)
421		{
422			if (tfd < 0)
423			{
424				OPEN_TF;
425				if (tfd < 0)
426				{
427					if (errno != EEXIST)
428						break;
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));
434				}
435#if SM_OPEN_EXLOCK
436				else
437					break;
438#endif
439			}
440			if (tfd >= 0)
441			{
442#if SM_OPEN_EXLOCK
443				/* file is locked by open() */
444				break;
445#else
446				if (lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB))
447					break;
448				else
449#endif
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));
454				if ((i % 32) == 31)
455				{
456					(void) close(tfd);
457					tfd = -1;
458				}
459			}
460
461			if ((i % 32) == 31)
462			{
463				/* save the old temp file away */
464				(void) rename(tf, queuename(e, TEMPQF_LETTER));
465			}
466			else
467				(void) sleep(i % 32);
468		}
469		if (tfd < 0 || (tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
470						 (void *) &tfd, SM_IO_WRONLY_B,
471						 NULL)) == NULL)
472		{
473			int save_errno = errno;
474
475			printopenfds(true);
476			errno = save_errno;
477			syserr("!queueup: cannot create queue temp file %s, uid=%ld",
478				tf, (long) geteuid());
479		}
480	}
481
482	if (tTd(40, 1))
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)" : "");
487	if (tTd(40, 3))
488	{
489		sm_dprintf("  e_flags=");
490		printenvflags(e);
491	}
492	if (tTd(40, 32))
493	{
494		sm_dprintf("  sendq=");
495		printaddr(sm_debug_file(), e->e_sendqueue, true);
496	}
497	if (tTd(40, 9))
498	{
499		sm_dprintf("  tfp=");
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");
504		else
505			dumpfd(sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL),
506			       true, false);
507	}
508
509	/*
510	**  If there is no data file yet, create one.
511	*/
512
513	(void) sm_strlcpy(df, queuename(e, DATAFL_LETTER), sizeof(df));
514	if (bitset(EF_HAS_DF, e->e_flags))
515	{
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 &&
520		    errno != EINVAL)
521		{
522			syserr("!queueup: cannot commit data file %s, uid=%ld",
523			       queuename(e, DATAFL_LETTER), (long) geteuid());
524		}
525		if (e->e_dfp != NULL &&
526		    SuperSafe == SAFE_INTERACTIVE && msync)
527		{
528			if (tTd(40,32))
529				sm_syslog(LOG_INFO, e->e_id,
530					  "queueup: fsync(e->e_dfp)");
531
532			if (fsync(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD,
533						NULL)) < 0)
534			{
535				if (newid)
536					syserr("!552 Error writing data file %s",
537					       df);
538				else
539					syserr("!452 Error writing data file %s",
540					       df);
541			}
542		}
543	}
544	else
545	{
546		int dfd;
547		MODE_T oldumask = 0;
548		register SM_FILE_T *dfp = NULL;
549		struct stat stbuf;
550
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");
554
555		if (bitset(S_IWGRP, QueueFileMode))
556			oldumask = umask(002);
557		dfd = open(df, O_WRONLY|O_CREAT|O_TRUNC|QF_O_EXTRA,
558			   QueueFileMode);
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,
563						 NULL)) == NULL)
564			syserr("!queueup: cannot create data temp file %s, uid=%ld",
565				df, (long) geteuid());
566		if (fstat(dfd, &stbuf) < 0)
567			e->e_dfino = -1;
568		else
569		{
570			e->e_dfdev = stbuf.st_dev;
571			e->e_dfino = ST_INODE(stbuf);
572		}
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);
578
579		if (SuperSafe == SAFE_REALLY ||
580		    SuperSafe == SAFE_REALLY_POSTMILTER ||
581		    (SuperSafe == SAFE_INTERACTIVE && msync))
582		{
583			if (tTd(40,32))
584				sm_syslog(LOG_INFO, e->e_id,
585					  "queueup: fsync(dfp)");
586
587			if (fsync(sm_io_getinfo(dfp, SM_IO_WHAT_FD, NULL)) < 0)
588			{
589				if (newid)
590					syserr("!552 Error writing data file %s",
591					       df);
592				else
593					syserr("!452 Error writing data file %s",
594					       df);
595			}
596		}
597
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;
602	}
603
604	/*
605	**  Output future work requests.
606	**	Priority and creation time should be first, since
607	**	they are required by gatherq.
608	*/
609
610	/* output queue version number (must be first!) */
611	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "V%d\n", QF_VERSION);
612
613	/* output creation time */
614	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "T%ld\n", (long) e->e_ctime);
615
616	/* output last delivery time */
617	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "K%ld\n", (long) e->e_dtime);
618
619	/* output number of delivery attempts */
620	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "N%d\n", e->e_ntries);
621
622	/* output message priority */
623	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "P%ld\n", e->e_msgpriority);
624
625	/*
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.
628	*/
629
630	if (e->e_dfqgrp != e->e_qgrp)
631	{
632		(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "d%s\n",
633			Queue[e->e_dfqgrp]->qg_qpaths[e->e_dfqdir].qp_name);
634	}
635
636	/* output inode number of data file */
637	if (e->e_dfino != -1)
638	{
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);
643	}
644
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));
649
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));
654
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));
659
660	/* send various flag bits through */
661	p = buf;
662	if (bitset(EF_WARNING, e->e_flags))
663		*p++ = 'w';
664	if (bitset(EF_RESPONSE, e->e_flags))
665		*p++ = 'r';
666	if (bitset(EF_HAS8BIT, e->e_flags))
667		*p++ = '8';
668	if (bitset(EF_DELETE_BCC, e->e_flags))
669		*p++ = 'b';
670	if (bitset(EF_RET_PARAM, e->e_flags))
671		*p++ = 'd';
672	if (bitset(EF_NO_BODY_RETN, e->e_flags))
673		*p++ = 'n';
674	if (bitset(EF_SPLIT, e->e_flags))
675		*p++ = 's';
676#if _FFR_EAI
677	if (e->e_smtputf8)
678		*p++ = 'e';
679#endif
680	*p++ = '\0';
681	if (buf[0] != '\0')
682		(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "F%s\n", buf);
683
684	/* save $={persistentMacros} macro values */
685	queueup_macros(macid("{persistentMacros}"), tfp, e);
686
687	/* output name of sender */
688	if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
689		p = e->e_sender;
690	else
691		p = e->e_from.q_paddr;
692	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "S%s\n",
693			     denlstring(p, true, false));
694
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));
699
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);
707
708	/* output list of recipient addresses */
709	printctladdr(NULL, NULL);
710	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
711	{
712		q->q_flags &= ~QQUEUED;
713		if (!QS_IS_UNDELIVERED(q->q_state))
714			continue;
715
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,
720							false));
721
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,
726							false));
727		if (q->q_finalrcpt != NULL)
728			(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "r%s\n",
729					     denlstring(q->q_finalrcpt, true,
730							false));
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');
747
748		/* _FFR_RCPTFLAGS */
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));
754		if (announce)
755		{
756			char *tag = "queued";
757
758			if (e->e_quarmsg != NULL)
759				tag = "quarantined";
760
761			e->e_to = q->q_paddr;
762			message("%s", tag);
763			if (LogLevel > 8)
764				logdelivery(q->q_mailer, NULL, q->q_status,
765					    tag, NULL, (time_t) 0, e, q, EX_OK);
766			e->e_to = NULL;
767		}
768
769		/*
770		**  This is only "valid" when the msg is safely in the queue,
771		**  i.e., EF_INQUEUE needs to be set.
772		*/
773
774		q->q_flags |= QQUEUED;
775
776		if (tTd(40, 1))
777		{
778			sm_dprintf("queueing ");
779			printaddr(sm_debug_file(), q, false);
780		}
781	}
782
783	/*
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.
791	*/
792
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;
800
801	macdefine(&e->e_macro, A_PERM, 'g', "\201f");
802	for (h = e->e_header; h != NULL; h = h->h_link)
803	{
804		if (h->h_value == NULL)
805			continue;
806
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))
810			continue;
811
812		/* expand macros; if null, don't output header at all */
813		if (bitset(H_DEFAULT, h->h_flags))
814		{
815			(void) expand(h->h_value, buf, sizeof(buf), e);
816			if (buf[0] == '\0')
817				continue;
818			if (buf[0] == ' ' && buf[1] == '\0')
819				continue;
820		}
821
822		/* output this header */
823		(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "H?");
824
825		/* output conditional macro if present */
826		if (h->h_macro != '\0')
827		{
828			if (bitset(0200, h->h_macro))
829				(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT,
830						     "${%s}",
831						      macname(bitidx(h->h_macro)));
832			else
833				(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT,
834						     "$%c", h->h_macro);
835		}
836		else if (!bitzerop(h->h_mflags) &&
837			 bitset(H_CHECK|H_ACHECK, h->h_flags))
838		{
839			int j;
840
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,
845							  j);
846		}
847		(void) sm_io_putc(tfp, SM_TIME_DEFAULT, '?');
848
849		/* output the header: expand macros, convert addresses */
850		if (bitset(H_DEFAULT, h->h_flags) &&
851		    !bitset(H_BINDLATE, h->h_flags))
852		{
853			(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s:%s\n",
854					     h->h_field,
855					     denlstring(buf, false, true));
856		}
857		else if (bitset(H_FROM|H_RCPT, h->h_flags) &&
858			 !bitset(H_BINDLATE, h->h_flags))
859		{
860			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
861			SM_FILE_T *savetrace = TrafficLogFile;
862
863			TrafficLogFile = NULL;
864
865			if (bitset(H_FROM, h->h_flags))
866				oldstyle = false;
867			commaize(h, h->h_value, oldstyle, &mcibuf, e,
868				 PXLF_HEADER);
869
870			TrafficLogFile = savetrace;
871		}
872		else
873		{
874			(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s:%s\n",
875					     h->h_field,
876					     denlstring(h->h_value, false,
877							true));
878		}
879	}
880
881	/*
882	**  Clean up.
883	**
884	**	Write a terminator record -- this is to prevent
885	**	scurrilous crackers from appending any data.
886	*/
887
888	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, ".\n");
889
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) ||
895	    sm_io_error(tfp))
896	{
897		if (newid)
898			syserr("!552 Error writing control file %s", tf);
899		else
900			syserr("!452 Error writing control file %s", tf);
901	}
902
903	if (!newid)
904	{
905		char new = queue_letter(e, ANYQFL_LETTER);
906
907		/* rename (locked) tf to be (locked) [qh]f */
908		(void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER),
909				  sizeof(qf));
910		if (rename(tf, qf) < 0)
911			syserr("cannot rename(%s, %s), uid=%ld",
912				tf, qf, (long) geteuid());
913		else
914		{
915			/*
916			**  Check if type has changed and only
917			**  remove the old item if the rename above
918			**  succeeded.
919			*/
920
921			if (e->e_qfletter != '\0' &&
922			    e->e_qfletter != new)
923			{
924				if (tTd(40, 5))
925				{
926					sm_dprintf("type changed from %c to %c\n",
927						   e->e_qfletter, new);
928				}
929
930				if (unlink(queuename(e, e->e_qfletter)) < 0)
931				{
932					/* XXX: something more drastic? */
933					if (LogLevel > 0)
934						sm_syslog(LOG_ERR, e->e_id,
935							  "queueup: unlink(%s) failed: %s",
936							  queuename(e, e->e_qfletter),
937							  sm_errstring(errno));
938				}
939			}
940		}
941		e->e_qfletter = new;
942
943		/*
944		**  fsync() after renaming to make sure metadata is
945		**  written to disk on filesystems in which renames are
946		**  not guaranteed.
947		*/
948
949		if (SuperSafe != SAFE_NO)
950		{
951			/* for softupdates */
952			if (tfd >= 0 && fsync(tfd) < 0)
953			{
954				syserr("!queueup: cannot fsync queue temp file %s",
955				       tf);
956			}
957			SYNC_DIR(qf, true);
958		}
959
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);
963		e->e_lockfp = tfp;
964
965		/* save log info */
966		if (LogLevel > 79)
967			sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", qf);
968	}
969	else
970	{
971		/* save log info */
972		if (LogLevel > 79)
973			sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", tf);
974
975		e->e_qfletter = queue_letter(e, ANYQFL_LETTER);
976	}
977
978	errno = 0;
979	e->e_flags |= EF_INQUEUE;
980
981	if (tTd(40, 1))
982		sm_dprintf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
983	return;
984}
985
986/*
987**  PRINTCTLADDR -- print control address to file.
988**
989**	Parameters:
990**		a -- address.
991**		tfp -- file pointer.
992**
993**	Returns:
994**		none.
995**
996**	Side Effects:
997**		The control address (if changed) is printed to the file.
998**		The last control address and uid are saved.
999*/
1000
1001static void
1002printctladdr(a, tfp)
1003	register ADDRESS *a;
1004	SM_FILE_T *tfp;
1005{
1006	char *user;
1007	register ADDRESS *q;
1008	uid_t uid;
1009	gid_t gid;
1010	static ADDRESS *lastctladdr = NULL;
1011	static uid_t lastuid;
1012
1013	/* initialization */
1014	if (a == NULL || a->q_alias == NULL || tfp == NULL)
1015	{
1016		if (lastctladdr != NULL && tfp != NULL)
1017			(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C\n");
1018		lastctladdr = NULL;
1019		lastuid = 0;
1020		return;
1021	}
1022
1023	/* find the active uid */
1024	q = getctladdr(a);
1025	if (q == NULL)
1026	{
1027		user = NULL;
1028		uid = 0;
1029		gid = 0;
1030	}
1031	else
1032	{
1033		user = q->q_ruser != NULL ? q->q_ruser : q->q_user;
1034		uid = q->q_uid;
1035		gid = q->q_gid;
1036	}
1037	a = a->q_alias;
1038
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)
1042		return;
1043	lastuid = uid;
1044	lastctladdr = a;
1045
1046	if (uid == 0 || user == NULL || user[0] == '\0')
1047		(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C");
1048	else
1049		(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C%s:%ld:%ld",
1050				     denlstring(user, true, false), (long) uid,
1051				     (long) gid);
1052	(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, ":%s\n",
1053			     denlstring(a->q_paddr, true, false));
1054}
1055
1056/*
1057**  RUNNERS_SIGTERM -- propagate a SIGTERM to queue runner process
1058**
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
1067**	BlockOldsh.
1068**
1069**	Parameters:
1070**		sig -- the signal number being sent
1071**
1072**	Returns:
1073**		none.
1074**
1075**	Side Effects:
1076**		Sets the NoMoreRunners boolean to true to stop more runners
1077**		from being started in runqueue().
1078**
1079**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
1080**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1081**		DOING.
1082*/
1083
1084static bool		volatile NoMoreRunners = false;
1085static sigfunc_t	Oldsh_term = SIG_DFL;
1086static sigfunc_t	Oldsh_hup = SIG_DFL;
1087static sigfunc_t	volatile Oldsh = SIG_DFL;
1088static bool		BlockOldsh = false;
1089static int		volatile Oldsig = 0;
1090static SIGFUNC_DECL	runners_sigterm __P((int));
1091static SIGFUNC_DECL	runners_sighup __P((int));
1092
1093static SIGFUNC_DECL
1094runners_sigterm(sig)
1095	int sig;
1096{
1097	int save_errno = errno;
1098
1099	FIX_SYSV_SIGNAL(sig, runners_sigterm);
1100	errno = save_errno;
1101	CHECK_CRITICAL(sig);
1102	NoMoreRunners = true;
1103	Oldsh = Oldsh_term;
1104	Oldsig = sig;
1105	proc_list_signal(PROC_QUEUE, sig);
1106
1107	if (!BlockOldsh || getppid() <= 1)
1108	{
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)
1112			(*Oldsh_term)(sig);
1113	}
1114	errno = save_errno;
1115	return SIGFUNC_RETURN;
1116}
1117/*
1118**  RUNNERS_SIGHUP -- propagate a SIGHUP to queue runner process
1119**
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
1128**	BlockOldsh.
1129**
1130**	Parameters:
1131**		sig -- the signal number being sent
1132**
1133**	Returns:
1134**		none.
1135**
1136**	Side Effects:
1137**		Sets the NoMoreRunners boolean to true to stop more runners
1138**		from being started in runqueue().
1139**
1140**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
1141**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1142**		DOING.
1143*/
1144
1145static SIGFUNC_DECL
1146runners_sighup(sig)
1147	int sig;
1148{
1149	int save_errno = errno;
1150
1151	FIX_SYSV_SIGNAL(sig, runners_sighup);
1152	errno = save_errno;
1153	CHECK_CRITICAL(sig);
1154	NoMoreRunners = true;
1155	Oldsh = Oldsh_hup;
1156	Oldsig = sig;
1157	proc_list_signal(PROC_QUEUE, sig);
1158
1159	if (!BlockOldsh || getppid() <= 1)
1160	{
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)
1164			(*Oldsh_hup)(sig);
1165	}
1166	errno = save_errno;
1167	return SIGFUNC_RETURN;
1168}
1169/*
1170**  MARK_WORK_GROUP_RESTART -- mark a work group as needing a restart
1171**
1172**  Sets a workgroup for restarting.
1173**
1174**	Parameters:
1175**		wgrp -- the work group id to restart.
1176**		reason -- why (signal?), -1 to turn off restart
1177**
1178**	Returns:
1179**		none.
1180**
1181**	Side effects:
1182**		May set global RestartWorkGroup to true.
1183**
1184**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
1185**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1186**		DOING.
1187*/
1188
1189void
1190mark_work_group_restart(wgrp, reason)
1191	int wgrp;
1192	int reason;
1193{
1194	if (wgrp < 0 || wgrp > NumWorkGroups)
1195		return;
1196
1197	WorkGrp[wgrp].wg_restart = reason;
1198	if (reason >= 0)
1199		RestartWorkGroup = true;
1200}
1201/*
1202**  RESTART_MARKED_WORK_GROUPS -- restart work groups marked as needing restart
1203**
1204**  Restart any workgroup marked as needing a restart provided more
1205**  runners are allowed.
1206**
1207**	Parameters:
1208**		none.
1209**
1210**	Returns:
1211**		none.
1212**
1213**	Side effects:
1214**		Sets global RestartWorkGroup to false.
1215*/
1216
1217void
1218restart_marked_work_groups()
1219{
1220	int i;
1221	int wasblocked;
1222
1223	if (NoMoreRunners)
1224		return;
1225
1226	/* Block SIGCHLD so reapchild() doesn't mess with us */
1227	wasblocked = sm_blocksignal(SIGCHLD);
1228
1229	for (i = 0; i < NumWorkGroups; i++)
1230	{
1231		if (WorkGrp[i].wg_restart >= 0)
1232		{
1233			if (LogLevel > 8)
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);
1238		}
1239	}
1240	RestartWorkGroup = false;
1241
1242	if (wasblocked == 0)
1243		(void) sm_releasesignal(SIGCHLD);
1244}
1245/*
1246**  RESTART_WORK_GROUP -- restart a specific work group
1247**
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.
1251**
1252**	Parameters:
1253**		wgrp -- the work group id to restart
1254**
1255**	Returns:
1256**		none.
1257**
1258**	Side Effects:
1259**		starts another process doing the work of wgrp
1260*/
1261
1262#define MAX_PERSIST_RESTART	10	/* max allowed number of restarts */
1263
1264static void
1265restart_work_group(wgrp)
1266	int wgrp;
1267{
1268	if (NoMoreRunners ||
1269	    wgrp < 0 || wgrp > NumWorkGroups)
1270		return;
1271
1272	WorkGrp[wgrp].wg_restart = -1;
1273	if (WorkGrp[wgrp].wg_restartcnt < MAX_PERSIST_RESTART)
1274	{
1275		/* avoid overflow; increment here */
1276		WorkGrp[wgrp].wg_restartcnt++;
1277		(void) run_work_group(wgrp, RWG_FORK|RWG_PERSISTENT|RWG_RUNALL);
1278	}
1279	else
1280	{
1281		sm_syslog(LOG_ERR, NOQID,
1282			  "ERROR: persistent queue runner=%d restarted too many times, queue runner lost",
1283			  wgrp);
1284	}
1285}
1286/*
1287**  SCHEDULE_QUEUE_RUNS -- schedule the next queue run for a work group.
1288**
1289**	Parameters:
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.
1293**
1294**	Returns:
1295**		nothing
1296*/
1297
1298#define INCR_MOD(v, m)	if (++v >= m)	\
1299				v = 0;	\
1300			else
1301
1302static void
1303schedule_queue_runs(runall, wgrp, didit)
1304	bool runall;
1305	int wgrp;
1306	bool didit;
1307{
1308	int qgrp, cgrp, endgrp;
1309#if _FFR_QUEUE_SCHED_DBG
1310	time_t lastsched;
1311	bool sched;
1312#endif
1313	time_t now;
1314	time_t minqintvl;
1315
1316	/*
1317	**  This is a bit ugly since we have to duplicate the
1318	**  code that "walks" through a work queue group.
1319	*/
1320
1321	now = curtime();
1322	minqintvl = 0;
1323	cgrp = endgrp = WorkGrp[wgrp].wg_curqgrp;
1324	do
1325	{
1326		time_t qintvl;
1327
1328#if _FFR_QUEUE_SCHED_DBG
1329		lastsched = 0;
1330		sched = false;
1331#endif
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;
1337		else
1338			qintvl = (time_t) 0;
1339#if _FFR_QUEUE_SCHED_DBG
1340		lastsched = Queue[qgrp]->qg_nextrun;
1341#endif
1342		if ((runall || Queue[qgrp]->qg_nextrun <= now) && qintvl > 0)
1343		{
1344#if _FFR_QUEUE_SCHED_DBG
1345			sched = true;
1346#endif
1347			if (minqintvl == 0 || qintvl < minqintvl)
1348				minqintvl = qintvl;
1349
1350			/*
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
1354			**  call.
1355			*/
1356
1357			if (didit)
1358				Queue[qgrp]->qg_nextrun += qintvl;
1359		}
1360#if _FFR_QUEUE_SCHED_DBG
1361		if (tTd(69, 10))
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",
1364				wgrp, cgrp, qgrp,
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);
1371	if (minqintvl > 0)
1372		(void) sm_setevent(minqintvl, runqueueevent, 0);
1373}
1374
1375#if _FFR_QUEUE_RUN_PARANOIA
1376/*
1377**  CHECKQUEUERUNNER -- check whether a queue group hasn't been run.
1378**
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.
1381**
1382**	Parameters:
1383**		none.
1384**
1385**	Returns:
1386**		true if a queue run is necessary.
1387**
1388**	Side Effects:
1389**		may schedule a queue run.
1390*/
1391
1392bool
1393checkqueuerunner()
1394{
1395	int qgrp;
1396	time_t now, minqintvl;
1397
1398	now = curtime();
1399	minqintvl = 0;
1400	for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++)
1401	{
1402		time_t qintvl;
1403
1404		if (Queue[qgrp]->qg_queueintvl > 0)
1405			qintvl = Queue[qgrp]->qg_queueintvl;
1406		else if (QueueIntvl > 0)
1407			qintvl = QueueIntvl;
1408		else
1409			qintvl = (time_t) 0;
1410		if (Queue[qgrp]->qg_nextrun <= now - qintvl)
1411		{
1412			if (minqintvl == 0 || qintvl < minqintvl)
1413				minqintvl = qintvl;
1414			if (LogLevel > 1)
1415				sm_syslog(LOG_WARNING, NOQID,
1416					"checkqueuerunner: queue %d should have been run at %s, queue interval %ld",
1417					qgrp,
1418					arpadate(ctime(&Queue[qgrp]->qg_nextrun)),
1419					(long) qintvl);
1420		}
1421	}
1422	if (minqintvl > 0)
1423	{
1424		(void) sm_setevent(minqintvl, runqueueevent, 0);
1425		return true;
1426	}
1427	return false;
1428}
1429#endif /* _FFR_QUEUE_RUN_PARANOIA */
1430
1431/*
1432**  RUNQUEUE -- run the jobs in the queue.
1433**
1434**	Gets the stuff out of the queue in some presumably logical
1435**	order and processes them.
1436**
1437**	Parameters:
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)?
1445**
1446**	Returns:
1447**		true if the queue run successfully began.
1448**
1449**	Side Effects:
1450**		runs things in the mail queue using run_work_group().
1451**		maybe schedules next queue run.
1452*/
1453
1454static ENVELOPE	QueueEnvelope;		/* the queue run envelope */
1455static time_t	LastQueueTime = 0;	/* last time a queue ID assigned */
1456static pid_t	LastQueuePid = -1;	/* last PID which had a queue ID */
1457
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 */
1463
1464bool
1465runqueue(forkflag, verbose, persistent, runall)
1466	bool forkflag;
1467	bool verbose;
1468	bool persistent;
1469	bool runall;
1470{
1471	int i;
1472	bool ret = true;
1473	static int curnum = 0;
1474	sigfunc_t cursh;
1475#if SM_HEAP_CHECK
1476	SM_NONVOLATILE int oldgroup = 0;
1477
1478	if (sm_debug_active(&DebugLeakQ, 1))
1479	{
1480		oldgroup = sm_heap_group();
1481		sm_heap_newgroup();
1482		sm_dprintf("runqueue() heap group #%d\n", sm_heap_group());
1483	}
1484#endif /* SM_HEAP_CHECK */
1485
1486	/* queue run has been started, don't do any more this time */
1487	DoQueueRun = false;
1488
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))
1493		forkflag = true;
1494
1495	/*
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.
1505	*/
1506
1507	cursh = sm_signal(SIGTERM, runners_sigterm);
1508	if (cursh != runners_sigterm)
1509		Oldsh_term = cursh;
1510	cursh = sm_signal(SIGHUP, runners_sighup);
1511	if (cursh != runners_sighup)
1512		Oldsh_hup = cursh;
1513
1514	for (i = 0; i < NumWorkGroups && !NoMoreRunners; i++)
1515	{
1516		int rwgflags = RWG_NONE;
1517		int wasblocked;
1518
1519		/*
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.
1523		**
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.
1527		*/
1528
1529#if _FFR_QUEUE_SCHED_DBG
1530		if (tTd(69, 10))
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)
1538			break;
1539
1540		/*
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.
1544		**
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.
1552		*/
1553
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);
1559		if (forkflag)
1560			rwgflags |= RWG_FORK;
1561		if (verbose)
1562			rwgflags |= RWG_VERBOSE;
1563		if (persistent)
1564			rwgflags |= RWG_PERSISTENT;
1565		if (runall)
1566			rwgflags |= RWG_RUNALL;
1567		ret = run_work_group(curnum, rwgflags);
1568
1569		/*
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.
1574		*/
1575
1576		if (!ret)
1577		{
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);
1585			break;
1586		}
1587
1588		if (!persistent)
1589			schedule_queue_runs(runall, curnum, true);
1590		INCR_MOD(curnum, NumWorkGroups);
1591	}
1592
1593	/* schedule left over queue runs */
1594	if (i < NumWorkGroups && !NoMoreRunners && !persistent)
1595	{
1596		int h;
1597
1598		for (h = curnum; i < NumWorkGroups; i++)
1599		{
1600			schedule_queue_runs(runall, h, false);
1601			INCR_MOD(h, NumWorkGroups);
1602		}
1603	}
1604
1605
1606#if SM_HEAP_CHECK
1607	if (sm_debug_active(&DebugLeakQ, 1))
1608		sm_heap_setgroup(oldgroup);
1609#endif
1610	return ret;
1611}
1612
1613#if _FFR_SKIP_DOMAINS
1614/*
1615**  SKIP_DOMAINS -- Skip 'skip' number of domains in the WorkQ.
1616**
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.
1620**
1621**	Parameters:
1622**		skip -- number of domains in WorkQ to skip.
1623**
1624**	Returns:
1625**		total number of messages skipped.
1626**
1627**	Side Effects:
1628**		may change WorkQ
1629*/
1630
1631static int
1632skip_domains(skip)
1633	int skip;
1634{
1635	int n, seqjump;
1636
1637	for (n = 0, seqjump = 0; n < skip && WorkQ != NULL; seqjump++)
1638	{
1639		if (WorkQ->w_next != NULL)
1640		{
1641			if (WorkQ->w_host != NULL &&
1642			    WorkQ->w_next->w_host != NULL)
1643			{
1644				if (sm_strcasecmp(WorkQ->w_host,
1645						WorkQ->w_next->w_host) != 0)
1646					n++;
1647			}
1648			else
1649			{
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))
1654					     n++;
1655			}
1656		}
1657		WorkQ = WorkQ->w_next;
1658	}
1659	return seqjump;
1660}
1661#endif /* _FFR_SKIP_DOMAINS */
1662
1663/*
1664**  RUNNER_WORK -- have a queue runner do its work
1665**
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).
1672**
1673**	Parameters:
1674**		e -- envelope.
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.
1679**
1680**	Returns:
1681**		none.
1682**
1683**	Side Effects:
1684**		runs things in the mail queue.
1685*/
1686
1687static void
1688runner_work(e, sequenceno, didfork, skip, njobs)
1689	register ENVELOPE *e;
1690	int sequenceno;
1691	bool didfork;
1692	int skip;
1693	int njobs;
1694{
1695	int n, seqjump;
1696	WORK *w;
1697	time_t now;
1698
1699	SM_GET_LA(now);
1700
1701	/*
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.
1706	*/
1707
1708	BlockOldsh = true;
1709	seqjump = skip;
1710
1711	/* process them once at a time */
1712	while (WorkQ != NULL)
1713	{
1714#if SM_HEAP_CHECK
1715		SM_NONVOLATILE int oldgroup = 0;
1716
1717		if (sm_debug_active(&DebugLeakQ, 1))
1718		{
1719			oldgroup = sm_heap_group();
1720			sm_heap_newgroup();
1721			sm_dprintf("run_queue_group() heap group #%d\n",
1722				sm_heap_group());
1723		}
1724#endif /* SM_HEAP_CHECK */
1725
1726		/* do no more work */
1727		if (NoMoreRunners)
1728		{
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)
1733				(*Oldsh)(Oldsig);
1734			break;
1735		}
1736
1737		w = WorkQ; /* assign current work item */
1738
1739		/*
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.
1747#endif
1748		*/
1749
1750#if _FFR_SKIP_DOMAINS
1751		if (QueueSortOrder == QSO_BYHOST)
1752		{
1753			seqjump = 1;
1754			if (WorkQ->w_next != NULL)
1755			{
1756				if (WorkQ->w_host != NULL &&
1757				    WorkQ->w_next->w_host != NULL)
1758				{
1759					if (sm_strcasecmp(WorkQ->w_host,
1760							WorkQ->w_next->w_host)
1761								!= 0)
1762						seqjump = skip_domains(skip);
1763					else
1764						WorkQ = WorkQ->w_next;
1765				}
1766				else
1767				{
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);
1773					else
1774						WorkQ = WorkQ->w_next;
1775				}
1776			}
1777			else
1778				WorkQ = WorkQ->w_next;
1779		}
1780		else
1781#endif /* _FFR_SKIP_DOMAINS */
1782		{
1783			for (n = 0; n < skip && WorkQ != NULL; n++)
1784				WorkQ = WorkQ->w_next;
1785		}
1786
1787		e->e_to = NULL;
1788
1789		/*
1790		**  Ignore jobs that are too expensive for the moment.
1791		**
1792		**	Get new load average every GET_NEW_LA_TIME seconds.
1793		*/
1794
1795		SM_GET_LA(now);
1796		if (shouldqueue(WkRecipFact, Current_LA_time))
1797		{
1798			char *msg = "Aborting queue run: load average too high";
1799
1800			if (Verbose)
1801				message("%s", msg);
1802			if (LogLevel > 8)
1803				sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg);
1804			break;
1805		}
1806		if (shouldqueue(w->w_pri, w->w_ctime))
1807		{
1808			if (Verbose)
1809				message("%s", "");
1810			if (QueueSortOrder == QSO_BYPRIORITY)
1811			{
1812				if (Verbose)
1813					message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue",
1814						qid_printqueue(w->w_qgrp,
1815							       w->w_qdir),
1816						w->w_name + 2, sequenceno,
1817						njobs);
1818				if (LogLevel > 8)
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,
1822								 w->w_qdir),
1823						  w->w_name + 2, w->w_pri,
1824						  CurrentLA, sequenceno,
1825						  njobs);
1826				break;
1827			}
1828			else if (Verbose)
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);
1832		}
1833		else
1834		{
1835			if (Verbose)
1836			{
1837				message("%s", "");
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);
1841			}
1842			if (didfork && MaxQueueChildren > 0)
1843			{
1844				sm_blocksignal(SIGCHLD);
1845				(void) sm_signal(SIGCHLD, reapchild);
1846			}
1847			if (tTd(63, 100))
1848				sm_syslog(LOG_DEBUG, NOQID,
1849					  "runqueue %s dowork(%s)",
1850					  qid_printqueue(w->w_qgrp, w->w_qdir),
1851					  w->w_name + 2);
1852
1853			(void) dowork(w->w_qgrp, w->w_qdir, w->w_name + 2,
1854				      ForkQueueRuns, false, e);
1855			errno = 0;
1856		}
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 */
1862#if SM_HEAP_CHECK
1863		if (sm_debug_active(&DebugLeakQ, 1))
1864			sm_heap_setgroup(oldgroup);
1865#endif
1866#if _FFR_TESTS
1867		if (tTd(76, 101))
1868		{
1869			int sl;
1870
1871			sl = tTdlevel(76) - 100;
1872			sm_dprintf("run_work_group: sleep=%d\n", sl);
1873			sleep(sl);
1874		}
1875#endif
1876	}
1877
1878	BlockOldsh = false;
1879
1880	/* check the signals didn't happen during the revert */
1881	if (NoMoreRunners)
1882	{
1883		/* Check that a valid signal handler is callable */
1884		if (Oldsh != SIG_DFL && Oldsh != SIG_IGN &&
1885		    Oldsh != runners_sighup && Oldsh != runners_sigterm)
1886			(*Oldsh)(Oldsig);
1887	}
1888
1889	Oldsh = SIG_DFL; /* after the NoMoreRunners check */
1890}
1891/*
1892**  RUN_WORK_GROUP -- run the jobs in a queue group from a work group.
1893**
1894**	Gets the stuff out of the queue in some presumably logical
1895**	order and processes them.
1896**
1897**	Parameters:
1898**		wgrp -- work group to process.
1899**		flags -- RWG_* flags
1900**
1901**	Returns:
1902**		true if the queue run successfully began.
1903**
1904**	Side Effects:
1905**		runs things in the mail queue.
1906*/
1907
1908/* Minimum sleep time for persistent queue runners */
1909#define MIN_SLEEP_TIME	5
1910
1911bool
1912run_work_group(wgrp, flags)
1913	int wgrp;
1914	int flags;
1915{
1916	register ENVELOPE *e;
1917	int njobs, qdir;
1918	int sequenceno = 1;
1919	int qgrp, endgrp, h, i;
1920	time_t now;
1921	bool full, more;
1922	SM_RPOOL_T *rpool;
1923	extern ENVELOPE BlankEnvelope;
1924	extern SIGFUNC_DECL reapchild __P((int));
1925
1926	if (wgrp < 0)
1927		return false;
1928
1929	/*
1930	**  If no work will ever be selected, don't even bother reading
1931	**  the queue.
1932	*/
1933
1934	SM_GET_LA(now);
1935
1936	if (!bitset(RWG_PERSISTENT, flags) &&
1937	    shouldqueue(WkRecipFact, Current_LA_time))
1938	{
1939		char *msg = "Skipping queue run -- load average too high";
1940
1941		if (bitset(RWG_VERBOSE, flags))
1942			message("458 %s\n", msg);
1943		if (LogLevel > 8)
1944			sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg);
1945		return false;
1946	}
1947
1948	/*
1949	**  See if we already have too many children.
1950	*/
1951
1952	if (bitset(RWG_FORK, flags) &&
1953	    WorkGrp[wgrp].wg_lowqintvl > 0 &&
1954	    !bitset(RWG_PERSISTENT, flags) &&
1955	    MaxChildren > 0 && CurChildren >= MaxChildren)
1956	{
1957		char *msg = "Skipping queue run -- too many children";
1958
1959		if (bitset(RWG_VERBOSE, flags))
1960			message("458 %s (%d)\n", msg, CurChildren);
1961		if (LogLevel > 8)
1962			sm_syslog(LOG_INFO, NOQID, "runqueue: %s (%d)",
1963				  msg, CurChildren);
1964		return false;
1965	}
1966
1967	/*
1968	**  See if we want to go off and do other useful work.
1969	*/
1970
1971	if (bitset(RWG_FORK, flags))
1972	{
1973		pid_t pid;
1974
1975		(void) sm_blocksignal(SIGCHLD);
1976		(void) sm_signal(SIGCHLD, reapchild);
1977
1978		pid = dofork();
1979		if (pid == -1)
1980		{
1981			const char *msg = "Skipping queue run -- fork() failed";
1982			const char *err = sm_errstring(errno);
1983
1984			if (bitset(RWG_VERBOSE, flags))
1985				message("458 %s: %s\n", msg, err);
1986			if (LogLevel > 8)
1987				sm_syslog(LOG_INFO, NOQID, "runqueue: %s: %s",
1988					  msg, err);
1989			(void) sm_releasesignal(SIGCHLD);
1990			return false;
1991		}
1992		if (pid != 0)
1993		{
1994			/* parent -- pick up intermediate zombie */
1995			(void) sm_blocksignal(SIGALRM);
1996
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,
2001				      NULL);
2002			(void) sm_releasesignal(SIGALRM);
2003			(void) sm_releasesignal(SIGCHLD);
2004			return true;
2005		}
2006
2007		/* child -- clean up signals */
2008
2009		/* Reset global flags */
2010		RestartRequest = NULL;
2011		RestartWorkGroup = false;
2012		ShutdownRequest = NULL;
2013		PendingSignal = 0;
2014		CurrentPid = getpid();
2015		close_sendmail_pid();
2016
2017		/*
2018		**  Initialize exception stack and default exception
2019		**  handler for child process.
2020		*/
2021
2022		sm_exc_newthread(fatal_error);
2023		clrcontrol();
2024		proc_list_clear();
2025
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);
2033	}
2034
2035	/*
2036	**  Release any resources used by the daemon code.
2037	*/
2038
2039	clrdaemon();
2040
2041	/* force it to run expensive jobs */
2042	NoConnect = false;
2043
2044	/* drop privileges */
2045	if (geteuid() == (uid_t) 0)
2046		(void) drop_privileges(false);
2047
2048	/*
2049	**  Create ourselves an envelope
2050	*/
2051
2052	CurEnv = &QueueEnvelope;
2053	rpool = sm_rpool_new_x(NULL);
2054	e = newenvelope(&QueueEnvelope, CurEnv, rpool);
2055	e->e_flags = BlankEnvelope.e_flags;
2056	e->e_parent = NULL;
2057
2058	/* make sure we have disconnected from parent */
2059	if (bitset(RWG_FORK, flags))
2060	{
2061		disconnect(1, e);
2062		QuickAbort = false;
2063	}
2064
2065	/*
2066	**  If we are running part of the queue, always ignore stored
2067	**  host status.
2068	*/
2069
2070	if (QueueLimitId != NULL || QueueLimitSender != NULL ||
2071	    QueueLimitQuarantine != NULL ||
2072	    QueueLimitRecipient != NULL)
2073	{
2074		IgnoreHostStatus = true;
2075		MinQueueAge = 0;
2076		MaxQueueAge = 0;
2077	}
2078
2079	/*
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.
2082	*/
2083
2084	endgrp = WorkGrp[wgrp].wg_curqgrp; /* to not spin endlessly */
2085
2086  domorework:
2087
2088	/*
2089	**  Run a queue group if:
2090	**  RWG_RUNALL bit is set or the bit for this group is set.
2091	*/
2092
2093	now = curtime();
2094	for (;;)
2095	{
2096		/*
2097		**  Find the next queue group within the work group that
2098		**  has been marked as needing a run.
2099		*/
2100
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))
2107			break;
2108		if (endgrp == WorkGrp[wgrp].wg_curqgrp)
2109		{
2110			e->e_id = NULL;
2111			if (bitset(RWG_FORK, flags))
2112				finis(true, true, ExitStat);
2113			return true; /* we're done */
2114		}
2115	}
2116
2117	qdir = Queue[qgrp]->qg_curnum; /* round-robin init of queue position */
2118#if _FFR_QUEUE_SCHED_DBG
2119	if (tTd(69, 12))
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 */
2125
2126#if HASNICE
2127	/* tweak niceness of queue runs */
2128	if (Queue[qgrp]->qg_nice > 0)
2129		(void) nice(Queue[qgrp]->qg_nice);
2130#endif
2131
2132	/* XXX running queue group... */
2133	sm_setproctitle(true, CurEnv, "running queue: %s",
2134			qid_printqueue(qgrp, qdir));
2135
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));
2141
2142	/*
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.
2147	*/
2148
2149	for (i = 0; i < Queue[qgrp]->qg_numqueues; i++)
2150	{
2151		(void) gatherq(qgrp, qdir, false, &full, &more, &h);
2152#if SM_CONF_SHM
2153		if (ShmId != SM_SHM_NO_ID)
2154			QSHM_ENTRIES(Queue[qgrp]->qg_qpaths[qdir].qp_idx) = h;
2155#endif
2156		/* If there are no more items in this queue advance */
2157		if (!more)
2158		{
2159			/* A round-robin advance */
2160			qdir++;
2161			qdir %= Queue[qgrp]->qg_numqueues;
2162		}
2163
2164		/* Has the WorkList reached the limit? */
2165		if (full)
2166			break; /* don't try to gather more */
2167	}
2168
2169	/* order the existing work requests */
2170	njobs = sortq(Queue[qgrp]->qg_maxlist);
2171	Queue[qgrp]->qg_curnum = qdir; /* update */
2172
2173
2174	if (!Verbose && bitnset(QD_FORK, Queue[qgrp]->qg_flags))
2175	{
2176		int loop, maxrunners;
2177		pid_t pid;
2178
2179		/*
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.
2188		*/
2189
2190		maxrunners = Queue[qgrp]->qg_maxqrun;
2191
2192		/*
2193		**  If no runners are configured for this group but
2194		**  the queue is "forced" then lets use 1 runner.
2195		*/
2196
2197		if (maxrunners == 0 && bitset(RWG_FORCE, flags))
2198			maxrunners = 1;
2199
2200		/* No need to have more runners then there are jobs */
2201		if (maxrunners > njobs)
2202			maxrunners = njobs;
2203		for (loop = 0; loop < maxrunners; loop++)
2204		{
2205			/*
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.
2211			*/
2212
2213			closemaps(false);
2214
2215			pid = fork();
2216			if (pid < 0)
2217			{
2218				syserr("run_work_group: cannot fork");
2219				return false;
2220			}
2221			else if (pid > 0)
2222			{
2223				/* parent -- clean out connection cache */
2224				mci_flush(false, NULL);
2225#if _FFR_SKIP_DOMAINS
2226				if (QueueSortOrder == QSO_BYHOST)
2227				{
2228					sequenceno += skip_domains(1);
2229				}
2230				else
2231#endif /* _FFR_SKIP_DOMAINS */
2232				{
2233					/* for the skip */
2234					WorkQ = WorkQ->w_next;
2235					sequenceno++;
2236				}
2237				proc_list_add(pid, "Queue child runner process",
2238					      PROC_QUEUE_CHILD, 0, -1, NULL);
2239
2240				/* No additional work, no additional runners */
2241				if (WorkQ == NULL)
2242					break;
2243			}
2244			else
2245			{
2246				/* child -- Reset global flags */
2247				RestartRequest = NULL;
2248				RestartWorkGroup = false;
2249				ShutdownRequest = NULL;
2250				PendingSignal = 0;
2251				CurrentPid = getpid();
2252				close_sendmail_pid();
2253
2254				/*
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.
2259				*/
2260
2261				sm_exc_newthread(fatal_error);
2262
2263				/*
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
2274				**  sm_wait().
2275				*/
2276
2277				if (OpMode == MD_SMTP ||
2278				    OpMode == MD_DAEMON ||
2279				    MaxQueueChildren > 0)
2280				{
2281					proc_list_clear();
2282					sm_releasesignal(SIGCHLD);
2283					(void) sm_signal(SIGCHLD, SIG_DFL);
2284				}
2285
2286				/* child -- error messages to the transcript */
2287				QuickAbort = OnlyOneError = false;
2288				runner_work(e, sequenceno, true,
2289					    maxrunners, njobs);
2290
2291				/* This child is done */
2292				finis(true, true, ExitStat);
2293				/* NOTREACHED */
2294			}
2295		}
2296
2297		sm_releasesignal(SIGCHLD);
2298
2299		/*
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.
2306		*/
2307
2308		while (CurChildren > 0)
2309		{
2310			int status;
2311			pid_t ret;
2312
2313			while ((ret = sm_wait(&status)) <= 0)
2314				continue;
2315			proc_list_drop(ret, status, NULL);
2316		}
2317	}
2318	else if (Queue[qgrp]->qg_maxqrun > 0 || bitset(RWG_FORCE, flags))
2319	{
2320		/*
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.
2324		*/
2325
2326		runner_work(e, sequenceno, false, 1, njobs);
2327	}
2328
2329	/* free memory allocated by newenvelope() above */
2330	sm_rpool_free(rpool);
2331	QueueEnvelope.e_rpool = NULL;
2332
2333	/* Are there still more queues in the work group to process? */
2334	if (endgrp != WorkGrp[wgrp].wg_curqgrp)
2335	{
2336		rpool = sm_rpool_new_x(NULL);
2337		e = newenvelope(&QueueEnvelope, CurEnv, rpool);
2338		e->e_flags = BlankEnvelope.e_flags;
2339		goto domorework;
2340	}
2341
2342	/* No more queues in work group to process. Now check persistent. */
2343	if (bitset(RWG_PERSISTENT, flags))
2344	{
2345		sequenceno = 1;
2346		sm_setproctitle(true, NULL, "running queue: %s",
2347				qid_printqueue(qgrp, qdir));
2348
2349		/*
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.
2353		*/
2354
2355		closemaps(true);
2356
2357		/* Close any cached connections. */
2358		mci_flush(true, NULL);
2359
2360		/* Clean out expired related entries. */
2361		rmexpstab();
2362
2363#if NAMED_BIND
2364		/* Update MX records for FallbackMX. */
2365		if (FallbackMX != NULL)
2366			(void) getfallbackmxrr(FallbackMX);
2367#endif
2368
2369#if USERDB
2370		/* close UserDatabase */
2371		_udbx_close();
2372#endif
2373
2374#if SM_HEAP_CHECK
2375		if (sm_debug_active(&SmHeapCheck, 2)
2376		    && access("memdump", F_OK) == 0
2377		   )
2378		{
2379			SM_FILE_T *out;
2380
2381			remove("memdump");
2382			out = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
2383					 "memdump.out", SM_IO_APPEND, NULL);
2384			if (out != NULL)
2385			{
2386				(void) sm_io_fprintf(out, SM_TIME_DEFAULT, "----------------------\n");
2387				sm_heap_report(out,
2388					sm_debug_level(&SmHeapCheck) - 1);
2389				(void) sm_io_close(out, SM_TIME_DEFAULT);
2390			}
2391		}
2392#endif /* SM_HEAP_CHECK */
2393
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);
2399		else
2400			sleep(WorkGrp[wgrp].wg_lowqintvl);
2401
2402		/*
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.
2409		*/
2410
2411		if (njobs == 0)
2412			SM_GET_LA(now);
2413		rpool = sm_rpool_new_x(NULL);
2414		e = newenvelope(&QueueEnvelope, CurEnv, rpool);
2415		e->e_flags = BlankEnvelope.e_flags;
2416		goto domorework;
2417	}
2418
2419	/* exit without the usual cleanup */
2420	e->e_id = NULL;
2421	if (bitset(RWG_FORK, flags))
2422		finis(true, true, ExitStat);
2423	/* NOTREACHED */
2424	return true;
2425}
2426
2427/*
2428**  DOQUEUERUN -- do a queue run?
2429*/
2430
2431bool
2432doqueuerun()
2433{
2434	return DoQueueRun;
2435}
2436
2437/*
2438**  RUNQUEUEEVENT -- Sets a flag to indicate that a queue run should be done.
2439**
2440**	Parameters:
2441**		none.
2442**
2443**	Returns:
2444**		none.
2445**
2446**	Side Effects:
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).
2455**
2456**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2457**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2458**		DOING.
2459*/
2460
2461void
2462runqueueevent(ignore)
2463	int ignore;
2464{
2465	int save_errno = errno;
2466
2467	/*
2468	**  Set the general bit that we want a queue run,
2469	**  tested in doqueuerun()
2470	*/
2471
2472	DoQueueRun = true;
2473#if _FFR_QUEUE_SCHED_DBG
2474	if (tTd(69, 10))
2475		sm_syslog(LOG_INFO, NOQID, "rqe: done");
2476#endif
2477
2478	errno = save_errno;
2479	if (errno == EINTR)
2480		errno = ETIMEDOUT;
2481}
2482/*
2483**  GATHERQ -- gather messages from the message queue(s) the work queue.
2484**
2485**	Parameters:
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
2496**
2497**	Returns:
2498**		The number of request in the queue (not necessarily
2499**		the number of requests in WorkList however).
2500**
2501**	Side Effects:
2502**		prepares available work into WorkList
2503*/
2504
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 */
2512
2513static WORK	*WorkList = NULL;	/* list of unsort work */
2514static int	WorkListSize = 0;	/* current max size of WorkList */
2515static int	WorkListCount = 0;	/* # of work items in WorkList */
2516
2517static int
2518gatherq(qgrp, qdir, doall, full, more, pnentries)
2519	int qgrp;
2520	int qdir;
2521	bool doall;
2522	bool *full;
2523	bool *more;
2524	int *pnentries;
2525{
2526	register struct dirent *d;
2527	register WORK *w;
2528	register char *p;
2529	DIR *f;
2530	int i, num_ent, wn, nentries;
2531	QUEUE_CHAR *check;
2532	char qd[MAXPATHLEN];
2533	char qf[MAXPATHLEN];
2534
2535	wn = WorkListCount - 1;
2536	num_ent = 0;
2537	nentries = 0;
2538	if (qdir == NOQDIR)
2539		(void) sm_strlcpy(qd, ".", sizeof(qd));
2540	else
2541		(void) sm_strlcpyn(qd, sizeof(qd), 2,
2542			Queue[qgrp]->qg_qpaths[qdir].qp_name,
2543			(bitset(QP_SUBQF,
2544				Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
2545					? "/qf" : ""));
2546
2547	if (tTd(41, 1))
2548	{
2549		sm_dprintf("gatherq: %s\n", qd);
2550
2551		check = QueueLimitId;
2552		while (check != NULL)
2553		{
2554			sm_dprintf("\tQueueLimitId = %s%s\n",
2555				check->queue_negate ? "!" : "",
2556				check->queue_match);
2557			check = check->queue_next;
2558		}
2559
2560		check = QueueLimitSender;
2561		while (check != NULL)
2562		{
2563			sm_dprintf("\tQueueLimitSender = %s%s\n",
2564				check->queue_negate ? "!" : "",
2565				check->queue_match);
2566			check = check->queue_next;
2567		}
2568
2569		check = QueueLimitRecipient;
2570		while (check != NULL)
2571		{
2572			sm_dprintf("\tQueueLimitRecipient = %s%s\n",
2573				check->queue_negate ? "!" : "",
2574				check->queue_match);
2575			check = check->queue_next;
2576		}
2577
2578		if (QueueMode == QM_QUARANTINE)
2579		{
2580			check = QueueLimitQuarantine;
2581			while (check != NULL)
2582			{
2583				sm_dprintf("\tQueueLimitQuarantine = %s%s\n",
2584					   check->queue_negate ? "!" : "",
2585					   check->queue_match);
2586				check = check->queue_next;
2587			}
2588		}
2589	}
2590
2591	/* open the queue directory */
2592	f = opendir(qd);
2593	if (f == NULL)
2594	{
2595		syserr("gatherq: cannot open \"%s\"",
2596			qid_printqueue(qgrp, qdir));
2597		if (full != NULL)
2598			*full = WorkListCount >= MaxQueueRun && MaxQueueRun > 0;
2599		if (more != NULL)
2600			*more = false;
2601		return 0;
2602	}
2603
2604	/*
2605	**  Read the work directory.
2606	*/
2607
2608	while ((d = readdir(f)) != NULL)
2609	{
2610		SM_FILE_T *cf;
2611		int qfver = 0;
2612		char lbuf[MAXNAME + 1];
2613		struct stat sbuf;
2614
2615		if (tTd(41, 50))
2616			sm_dprintf("gatherq: checking %s..", d->d_name);
2617
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'))
2626		{
2627			if (tTd(41, 50))
2628				sm_dprintf("  skipping\n");
2629			continue;
2630		}
2631		if (tTd(41, 50))
2632			sm_dprintf("\n");
2633
2634		if (strlen(d->d_name) >= MAXQFNAME)
2635		{
2636			if (Verbose)
2637				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2638						     "gatherq: %s too long, %d max characters\n",
2639						     d->d_name, MAXQFNAME);
2640			if (LogLevel > 0)
2641				sm_syslog(LOG_ALERT, NOQID,
2642					  "gatherq: %s too long, %d max characters",
2643					  d->d_name, MAXQFNAME);
2644			continue;
2645		}
2646
2647		++nentries;
2648		check = QueueLimitId;
2649		while (check != NULL)
2650		{
2651			if (strcontainedin(false, check->queue_match,
2652					   d->d_name) != check->queue_negate)
2653				break;
2654			else
2655				check = check->queue_next;
2656		}
2657		if (QueueLimitId != NULL && check == NULL)
2658			continue;
2659
2660		/* grow work list if necessary */
2661		if (++wn >= MaxQueueRun && MaxQueueRun > 0)
2662		{
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),
2667					  MaxQueueRun);
2668			if (doall)
2669				continue;	/* just count entries */
2670			break;
2671		}
2672		if (wn >= WorkListSize)
2673		{
2674			grow_wlist(qgrp, qdir);
2675			if (wn >= WorkListSize)
2676				continue;
2677		}
2678		SM_ASSERT(wn >= 0);
2679		w = &WorkList[wn];
2680
2681		(void) sm_strlcpyn(qf, sizeof(qf), 3, qd, "/", d->d_name);
2682		if (stat(qf, &sbuf) < 0)
2683		{
2684			if (errno != ENOENT)
2685				sm_syslog(LOG_INFO, NOQID,
2686					  "gatherq: can't stat %s/%s",
2687					  qid_printqueue(qgrp, qdir),
2688					  d->d_name);
2689			wn--;
2690			continue;
2691		}
2692		if (!bitset(S_IFREG, sbuf.st_mode))
2693		{
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);
2703			wn--;
2704			continue;
2705		}
2706
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)
2715		{
2716			w->w_qgrp = qgrp;
2717			w->w_qdir = qdir;
2718			w->w_name = newstr(d->d_name);
2719			w->w_host = NULL;
2720			w->w_lock = w->w_tooyoung = false;
2721			w->w_pri = 0;
2722			w->w_ctime = 0;
2723			w->w_mtime = sbuf.st_mtime;
2724			++num_ent;
2725			continue;
2726		}
2727
2728		/* open control file */
2729		cf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B,
2730				NULL);
2731		if (cf == NULL && OpMode != MD_PRINT)
2732		{
2733			/* this may be some random person sending hir msgs */
2734			if (tTd(41, 2))
2735				sm_dprintf("gatherq: cannot open %s: %s\n",
2736					d->d_name, sm_errstring(errno));
2737			errno = 0;
2738			wn--;
2739			continue;
2740		}
2741		w->w_qgrp = qgrp;
2742		w->w_qdir = qdir;
2743		w->w_name = newstr(d->d_name);
2744		w->w_host = NULL;
2745		if (cf != NULL)
2746		{
2747			w->w_lock = !lockfile(sm_io_getinfo(cf, SM_IO_WHAT_FD,
2748							    NULL),
2749					      w->w_name, NULL,
2750					      LOCK_SH|LOCK_NB);
2751		}
2752		w->w_tooyoung = false;
2753
2754		/* make sure jobs in creation don't clog queue */
2755		w->w_pri = 0x7fffffff;
2756		w->w_ctime = 0;
2757		w->w_mtime = sbuf.st_mtime;
2758
2759		/* extract useful information */
2760		i = NEED_P|NEED_T;
2761		if (QueueSortOrder == QSO_BYHOST
2762#if _FFR_RHS
2763		    || QueueSortOrder == QSO_BYSHUFFLE
2764#endif
2765		   )
2766		{
2767			/* need w_host set for host sort order */
2768			i |= NEED_H;
2769		}
2770		if (QueueLimitSender != NULL)
2771			i |= NEED_S;
2772		if (QueueLimitRecipient != NULL)
2773			i |= NEED_R;
2774		if (QueueLimitQuarantine != NULL)
2775			i |= NEED_QUARANTINE;
2776		while (cf != NULL && i != 0 &&
2777		       sm_io_fgets(cf, SM_TIME_DEFAULT, lbuf,
2778				   sizeof(lbuf)) >= 0)
2779		{
2780			int c;
2781			time_t age;
2782
2783			p = strchr(lbuf, '\n');
2784			if (p != NULL)
2785				*p = '\0';
2786			else
2787			{
2788				/* flush rest of overly long line */
2789				while ((c = sm_io_getc(cf, SM_TIME_DEFAULT))
2790				       != SM_IO_EOF && c != '\n')
2791					continue;
2792			}
2793
2794			switch (lbuf[0])
2795			{
2796			  case 'V':
2797				qfver = atoi(&lbuf[1]);
2798				break;
2799
2800			  case 'P':
2801				w->w_pri = atol(&lbuf[1]);
2802				i &= ~NEED_P;
2803				break;
2804
2805			  case 'T':
2806				w->w_ctime = atol(&lbuf[1]);
2807				i &= ~NEED_T;
2808				break;
2809
2810			  case 'q':
2811				if (QueueMode != QM_QUARANTINE &&
2812				    QueueMode != QM_LOST)
2813				{
2814					if (tTd(41, 49))
2815						sm_dprintf("%s not marked as quarantined but has a 'q' line\n",
2816							   w->w_name);
2817					i |= HAS_QUARANTINE;
2818				}
2819				else if (QueueMode == QM_QUARANTINE)
2820				{
2821					if (QueueLimitQuarantine == NULL)
2822					{
2823						i &= ~NEED_QUARANTINE;
2824						break;
2825					}
2826					p = &lbuf[1];
2827					check = QueueLimitQuarantine;
2828					while (check != NULL)
2829					{
2830						if (strcontainedin(false,
2831								   check->queue_match,
2832								   p) !=
2833						    check->queue_negate)
2834							break;
2835						else
2836							check = check->queue_next;
2837					}
2838					if (check != NULL)
2839						i &= ~NEED_QUARANTINE;
2840				}
2841				break;
2842
2843			  case 'R':
2844				if (w->w_host == NULL &&
2845				    (p = strrchr(&lbuf[1], '@')) != NULL)
2846				{
2847#if _FFR_RHS
2848					if (QueueSortOrder == QSO_BYSHUFFLE)
2849						w->w_host = newstr(&p[1]);
2850					else
2851#endif
2852						w->w_host = strrev(&p[1]);
2853					makelower(w->w_host);
2854					i &= ~NEED_H;
2855				}
2856				if (QueueLimitRecipient == NULL)
2857				{
2858					i &= ~NEED_R;
2859					break;
2860				}
2861				if (qfver > 0)
2862				{
2863					p = strchr(&lbuf[1], ':');
2864					if (p == NULL)
2865						p = &lbuf[1];
2866					else
2867						++p; /* skip over ':' */
2868				}
2869				else
2870					p = &lbuf[1];
2871				check = QueueLimitRecipient;
2872				while (check != NULL)
2873				{
2874					if (strcontainedin(true,
2875							   check->queue_match,
2876							   p) !=
2877					    check->queue_negate)
2878						break;
2879					else
2880						check = check->queue_next;
2881				}
2882				if (check != NULL)
2883					i &= ~NEED_R;
2884				break;
2885
2886			  case 'S':
2887				check = QueueLimitSender;
2888				while (check != NULL)
2889				{
2890					if (strcontainedin(true,
2891							   check->queue_match,
2892							   &lbuf[1]) !=
2893					    check->queue_negate)
2894						break;
2895					else
2896						check = check->queue_next;
2897				}
2898				if (check != NULL)
2899					i &= ~NEED_S;
2900				break;
2901
2902			  case 'K':
2903				if (MaxQueueAge > 0)
2904				{
2905					time_t lasttry, delay;
2906
2907					lasttry = (time_t) atol(&lbuf[1]);
2908					delay = MIN(lasttry - w->w_ctime,
2909						    MaxQueueAge);
2910					age = curtime() - lasttry;
2911					if (age < delay)
2912						w->w_tooyoung = true;
2913					break;
2914				}
2915
2916				age = curtime() - (time_t) atol(&lbuf[1]);
2917				if (age >= 0 && MinQueueAge > 0 &&
2918				    age < MinQueueAge)
2919					w->w_tooyoung = true;
2920				break;
2921
2922			  case 'N':
2923				if (atol(&lbuf[1]) == 0)
2924					w->w_tooyoung = false;
2925				break;
2926			}
2927		}
2928		if (cf != NULL)
2929			(void) sm_io_close(cf, SM_TIME_DEFAULT);
2930
2931		if ((!doall && (shouldqueue(w->w_pri, w->w_ctime) ||
2932		    w->w_tooyoung)) ||
2933		    bitset(HAS_QUARANTINE, i) ||
2934		    bitset(NEED_QUARANTINE, i) ||
2935		    bitset(NEED_R|NEED_S, i))
2936		{
2937			/* don't even bother sorting this job in */
2938			if (tTd(41, 49))
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 */
2943			wn--;
2944		}
2945		else
2946			++num_ent;
2947	}
2948	(void) closedir(f);
2949	wn++;
2950
2951	i = wn - WorkListCount;
2952	WorkListCount += SM_MIN(num_ent, WorkListSize);
2953
2954	if (more != NULL)
2955		*more = WorkListCount < wn;
2956
2957	if (full != NULL)
2958		*full = (wn >= MaxQueueRun && MaxQueueRun > 0) ||
2959			(WorkList == NULL && wn > 0);
2960
2961	if (pnentries != NULL)
2962		*pnentries = nentries;
2963	return i;
2964}
2965/*
2966**  SORTQ -- sort the work list
2967**
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
2972**	are moved.
2973**
2974**	Parameters:
2975**		max -- maximum number of items to be placed in WorkQ
2976**
2977**	Returns:
2978**		the number of items in WorkQ
2979**
2980**	Side Effects:
2981**		WorkQ gets released and filled with new work. WorkList
2982**		gets released. Work items get sorted in order.
2983*/
2984
2985static int
2986sortq(max)
2987	int max;
2988{
2989	register int i;			/* local counter */
2990	register WORK *w;		/* tmp item pointer */
2991	int wc = WorkListCount;		/* trim size for WorkQ */
2992
2993	if (WorkQ != NULL)
2994	{
2995		WORK *nw;
2996
2997		/* Clear out old WorkQ. */
2998		for (w = WorkQ; w != NULL; w = nw)
2999		{
3000			nw = w->w_next;
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 */
3005		}
3006		WorkQ = NULL;
3007	}
3008
3009	if (WorkList == NULL || wc <= 0)
3010		return 0;
3011
3012	/*
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.
3017	*/
3018
3019	if (QueueSortOrder == QSO_BYHOST)
3020	{
3021		/*
3022		**  Sort the work directory for the first time,
3023		**  based on host name, lock status, and priority.
3024		*/
3025
3026		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf1);
3027
3028		/*
3029		**  If one message to host is locked, "lock" all messages
3030		**  to that host.
3031		*/
3032
3033		i = 0;
3034		while (i < wc)
3035		{
3036			if (!WorkList[i].w_lock)
3037			{
3038				i++;
3039				continue;
3040			}
3041			w = &WorkList[i];
3042			while (++i < wc)
3043			{
3044				if (WorkList[i].w_host == NULL &&
3045				    w->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,
3050						       w->w_host) == 0)
3051					WorkList[i].w_lock = true;
3052				else
3053					break;
3054			}
3055		}
3056
3057		/*
3058		**  Sort the work directory for the second time,
3059		**  based on lock status, host name, and priority.
3060		*/
3061
3062		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf2);
3063	}
3064	else if (QueueSortOrder == QSO_BYTIME)
3065	{
3066		/*
3067		**  Simple sort based on submission time only.
3068		*/
3069
3070		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf3);
3071	}
3072	else if (QueueSortOrder == QSO_BYFILENAME)
3073	{
3074		/*
3075		**  Sort based on queue filename.
3076		*/
3077
3078		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf4);
3079	}
3080	else if (QueueSortOrder == QSO_RANDOM)
3081	{
3082		/*
3083		**  Sort randomly.  To avoid problems with an instable sort,
3084		**  use a random index into the queue file name to start
3085		**  comparison.
3086		*/
3087
3088		randi = get_rand_mod(MAXQFNAME);
3089		if (randi < 2)
3090			randi = 3;
3091		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf5);
3092	}
3093	else if (QueueSortOrder == QSO_BYMODTIME)
3094	{
3095		/*
3096		**  Simple sort based on modification time of queue file.
3097		**  This puts the oldest items first.
3098		*/
3099
3100		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf6);
3101	}
3102#if _FFR_RHS
3103	else if (QueueSortOrder == QSO_BYSHUFFLE)
3104	{
3105		/*
3106		**  Simple sort based on shuffled host name.
3107		*/
3108
3109		init_shuffle_alphabet();
3110		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf7);
3111	}
3112#endif /* _FFR_RHS */
3113	else if (QueueSortOrder == QSO_BYPRIORITY)
3114	{
3115		/*
3116		**  Simple sort based on queue priority only.
3117		*/
3118
3119		qsort((char *) WorkList, wc, sizeof(*WorkList), workcmpf0);
3120	}
3121	/* else don't sort at all */
3122
3123	/* Check if the per queue group item limit will be exceeded */
3124	if (wc > max && max > 0)
3125		wc = max;
3126
3127	/*
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
3131	**  maximum.
3132	*/
3133
3134	for (i = wc; --i >= 0; )
3135	{
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;
3146		w->w_next = WorkQ;
3147		WorkQ = w;
3148	}
3149
3150	/* free the rest of the list */
3151	for (i = WorkListCount; --i >= wc; )
3152	{
3153		sm_free(WorkList[i].w_name);
3154		if (WorkList[i].w_host != NULL)
3155			sm_free(WorkList[i].w_host);
3156	}
3157
3158	if (WorkList != NULL)
3159		sm_free(WorkList); /* XXX */
3160	WorkList = NULL;
3161	WorkListSize = 0;
3162	WorkListCount = 0;
3163
3164	if (tTd(40, 1))
3165	{
3166		for (w = WorkQ; w != NULL; w = w->w_next)
3167		{
3168			if (w->w_host != NULL)
3169				sm_dprintf("%22s: pri=%ld %s\n",
3170					w->w_name, w->w_pri, w->w_host);
3171			else
3172				sm_dprintf("%32s: pri=%ld\n",
3173					w->w_name, w->w_pri);
3174		}
3175	}
3176
3177	return wc; /* return number of WorkQ items */
3178}
3179/*
3180**  GROW_WLIST -- make the work list larger
3181**
3182**	Parameters:
3183**		qgrp -- the index for the queue group.
3184**		qdir -- the index for the queue directory.
3185**
3186**	Returns:
3187**		none.
3188**
3189**	Side Effects:
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.
3193*/
3194
3195static void
3196grow_wlist(qgrp, qdir)
3197	int qgrp;
3198	int qdir;
3199{
3200	if (tTd(41, 1))
3201		sm_dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize);
3202	if (WorkList == NULL)
3203	{
3204		WorkList = (WORK *) xalloc((sizeof(*WorkList)) *
3205					   (QUEUESEGSIZE + 1));
3206		WorkListSize = QUEUESEGSIZE;
3207	}
3208	else
3209	{
3210		int newsize = WorkListSize + QUEUESEGSIZE;
3211		WORK *newlist = (WORK *) sm_realloc((char *) WorkList,
3212					  (unsigned) sizeof(WORK) * (newsize + 1));
3213
3214		if (newlist != NULL)
3215		{
3216			WorkListSize = newsize;
3217			WorkList = newlist;
3218			if (LogLevel > 1)
3219			{
3220				sm_syslog(LOG_INFO, NOQID,
3221					  "grew WorkList for %s to %d",
3222					  qid_printqueue(qgrp, qdir),
3223					  WorkListSize);
3224			}
3225		}
3226		else if (LogLevel > 0)
3227		{
3228			sm_syslog(LOG_ALERT, NOQID,
3229				  "FAILED to grow WorkList for %s to %d",
3230				  qid_printqueue(qgrp, qdir), newsize);
3231		}
3232	}
3233	if (tTd(41, 1))
3234		sm_dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize);
3235}
3236/*
3237**  WORKCMPF0 -- simple priority-only compare function.
3238**
3239**	Parameters:
3240**		a -- the first argument.
3241**		b -- the second argument.
3242**
3243**	Returns:
3244**		-1 if a < b
3245**		 0 if a == b
3246**		+1 if a > b
3247**
3248*/
3249
3250static int
3251workcmpf0(a, b)
3252	register WORK *a;
3253	register WORK *b;
3254{
3255	long pa = a->w_pri;
3256	long pb = b->w_pri;
3257
3258	if (pa == pb)
3259		return 0;
3260	else if (pa > pb)
3261		return 1;
3262	else
3263		return -1;
3264}
3265/*
3266**  WORKCMPF1 -- first compare function for ordering work based on host name.
3267**
3268**	Sorts on host name, lock status, and priority in that order.
3269**
3270**	Parameters:
3271**		a -- the first argument.
3272**		b -- the second argument.
3273**
3274**	Returns:
3275**		<0 if a < b
3276**		 0 if a == b
3277**		>0 if a > b
3278**
3279*/
3280
3281static int
3282workcmpf1(a, b)
3283	register WORK *a;
3284	register WORK *b;
3285{
3286	int i;
3287
3288	/* host name */
3289	if (a->w_host != NULL && b->w_host == NULL)
3290		return 1;
3291	else if (a->w_host == NULL && b->w_host != NULL)
3292		return -1;
3293	if (a->w_host != NULL && b->w_host != NULL &&
3294	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
3295		return i;
3296
3297	/* lock status */
3298	if (a->w_lock != b->w_lock)
3299		return b->w_lock - a->w_lock;
3300
3301	/* job priority */
3302	return workcmpf0(a, b);
3303}
3304/*
3305**  WORKCMPF2 -- second compare function for ordering work based on host name.
3306**
3307**	Sorts on lock status, host name, and priority in that order.
3308**
3309**	Parameters:
3310**		a -- the first argument.
3311**		b -- the second argument.
3312**
3313**	Returns:
3314**		<0 if a < b
3315**		 0 if a == b
3316**		>0 if a > b
3317**
3318*/
3319
3320static int
3321workcmpf2(a, b)
3322	register WORK *a;
3323	register WORK *b;
3324{
3325	int i;
3326
3327	/* lock status */
3328	if (a->w_lock != b->w_lock)
3329		return a->w_lock - b->w_lock;
3330
3331	/* host name */
3332	if (a->w_host != NULL && b->w_host == NULL)
3333		return 1;
3334	else if (a->w_host == NULL && b->w_host != NULL)
3335		return -1;
3336	if (a->w_host != NULL && b->w_host != NULL &&
3337	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
3338		return i;
3339
3340	/* job priority */
3341	return workcmpf0(a, b);
3342}
3343/*
3344**  WORKCMPF3 -- simple submission-time-only compare function.
3345**
3346**	Parameters:
3347**		a -- the first argument.
3348**		b -- the second argument.
3349**
3350**	Returns:
3351**		-1 if a < b
3352**		 0 if a == b
3353**		+1 if a > b
3354**
3355*/
3356
3357static int
3358workcmpf3(a, b)
3359	register WORK *a;
3360	register WORK *b;
3361{
3362	if (a->w_ctime > b->w_ctime)
3363		return 1;
3364	else if (a->w_ctime < b->w_ctime)
3365		return -1;
3366	else
3367		return 0;
3368}
3369/*
3370**  WORKCMPF4 -- compare based on file name
3371**
3372**	Parameters:
3373**		a -- the first argument.
3374**		b -- the second argument.
3375**
3376**	Returns:
3377**		-1 if a < b
3378**		 0 if a == b
3379**		+1 if a > b
3380**
3381*/
3382
3383static int
3384workcmpf4(a, b)
3385	register WORK *a;
3386	register WORK *b;
3387{
3388	return strcmp(a->w_name, b->w_name);
3389}
3390/*
3391**  WORKCMPF5 -- compare based on assigned random number
3392**
3393**	Parameters:
3394**		a -- the first argument.
3395**		b -- the second argument.
3396**
3397**	Returns:
3398**		randomly 1/-1
3399*/
3400
3401/* ARGSUSED0 */
3402static int
3403workcmpf5(a, b)
3404	register WORK *a;
3405	register WORK *b;
3406{
3407	if (strlen(a->w_name) < randi || strlen(b->w_name) < randi)
3408		return -1;
3409	return a->w_name[randi] - b->w_name[randi];
3410}
3411/*
3412**  WORKCMPF6 -- simple modification-time-only compare function.
3413**
3414**	Parameters:
3415**		a -- the first argument.
3416**		b -- the second argument.
3417**
3418**	Returns:
3419**		-1 if a < b
3420**		 0 if a == b
3421**		+1 if a > b
3422**
3423*/
3424
3425static int
3426workcmpf6(a, b)
3427	register WORK *a;
3428	register WORK *b;
3429{
3430	if (a->w_mtime > b->w_mtime)
3431		return 1;
3432	else if (a->w_mtime < b->w_mtime)
3433		return -1;
3434	else
3435		return 0;
3436}
3437#if _FFR_RHS
3438/*
3439**  WORKCMPF7 -- compare function for ordering work based on shuffled host name.
3440**
3441**	Sorts on lock status, host name, and priority in that order.
3442**
3443**	Parameters:
3444**		a -- the first argument.
3445**		b -- the second argument.
3446**
3447**	Returns:
3448**		<0 if a < b
3449**		 0 if a == b
3450**		>0 if a > b
3451**
3452*/
3453
3454static int
3455workcmpf7(a, b)
3456	register WORK *a;
3457	register WORK *b;
3458{
3459	int i;
3460
3461	/* lock status */
3462	if (a->w_lock != b->w_lock)
3463		return a->w_lock - b->w_lock;
3464
3465	/* host name */
3466	if (a->w_host != NULL && b->w_host == NULL)
3467		return 1;
3468	else if (a->w_host == NULL && b->w_host != NULL)
3469		return -1;
3470	if (a->w_host != NULL && b->w_host != NULL &&
3471	    (i = sm_strshufflecmp(a->w_host, b->w_host)) != 0)
3472		return i;
3473
3474	/* job priority */
3475	return workcmpf0(a, b);
3476}
3477#endif /* _FFR_RHS */
3478/*
3479**  STRREV -- reverse string
3480**
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().
3484**
3485**	Parameters:
3486**		fwd -- the string to reverse.
3487**
3488**	Returns:
3489**		the reversed string.
3490*/
3491
3492static char *
3493strrev(fwd)
3494	char *fwd;
3495{
3496	char *rev = NULL;
3497	int len, cnt;
3498
3499	len = strlen(fwd);
3500	rev = xalloc(len + 1);
3501	for (cnt = 0; cnt < len; ++cnt)
3502		rev[cnt] = fwd[len - cnt - 1];
3503	rev[len] = '\0';
3504	return rev;
3505}
3506
3507#if _FFR_RHS
3508
3509# define NASCII	128
3510# define NCHAR	256
3511
3512static unsigned char ShuffledAlphabet[NCHAR];
3513
3514void
3515init_shuffle_alphabet()
3516{
3517	static bool init = false;
3518	int i;
3519
3520	if (init)
3521		return;
3522
3523	/* fill the ShuffledAlphabet */
3524	for (i = 0; i < NASCII; i++)
3525		ShuffledAlphabet[i] = i;
3526
3527	/* mix it */
3528	for (i = 1; i < NASCII; i++)
3529	{
3530		register int j = get_random() % NASCII;
3531		register int tmp;
3532
3533		tmp = ShuffledAlphabet[j];
3534		ShuffledAlphabet[j] = ShuffledAlphabet[i];
3535		ShuffledAlphabet[i] = tmp;
3536	}
3537
3538	/* make it case insensitive */
3539	for (i = 'A'; i <= 'Z'; i++)
3540		ShuffledAlphabet[i] = ShuffledAlphabet[i + 'a' - 'A'];
3541
3542	/* fill the upper part */
3543	for (i = 0; i < NASCII; i++)
3544		ShuffledAlphabet[i + NASCII] = ShuffledAlphabet[i];
3545	init = true;
3546}
3547
3548static int
3549sm_strshufflecmp(a, b)
3550	char *a;
3551	char *b;
3552{
3553	const unsigned char *us1 = (const unsigned char *) a;
3554	const unsigned char *us2 = (const unsigned char *) b;
3555
3556	while (ShuffledAlphabet[*us1] == ShuffledAlphabet[*us2++])
3557	{
3558		if (*us1++ == '\0')
3559			return 0;
3560	}
3561	return (ShuffledAlphabet[*us1] - ShuffledAlphabet[*--us2]);
3562}
3563#endif /* _FFR_RHS */
3564
3565/*
3566**  DOWORK -- do a work request.
3567**
3568**	Parameters:
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
3576**			child.
3577**		e - the envelope in which to run it.
3578**
3579**	Returns:
3580**		process id of process that is running the queue job.
3581**
3582**	Side Effects:
3583**		The work request is satisfied if possible.
3584*/
3585
3586pid_t
3587dowork(qgrp, qdir, id, forkflag, requeueflag, e)
3588	int qgrp;
3589	int qdir;
3590	char *id;
3591	bool forkflag;
3592	bool requeueflag;
3593	register ENVELOPE *e;
3594{
3595	register pid_t pid;
3596	SM_RPOOL_T *rpool;
3597
3598	if (tTd(40, 1))
3599		sm_dprintf("dowork(%s/%s)\n", qid_printqueue(qgrp, qdir), id);
3600
3601	/*
3602	**  Fork for work.
3603	*/
3604
3605	if (forkflag)
3606	{
3607		/*
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.
3613		*/
3614
3615		closemaps(false);
3616
3617		pid = fork();
3618		if (pid < 0)
3619		{
3620			syserr("dowork: cannot fork");
3621			return 0;
3622		}
3623		else if (pid > 0)
3624		{
3625			/* parent -- clean out connection cache */
3626			mci_flush(false, NULL);
3627		}
3628		else
3629		{
3630			/*
3631			**  Initialize exception stack and default exception
3632			**  handler for child process.
3633			*/
3634
3635			/* Reset global flags */
3636			RestartRequest = NULL;
3637			RestartWorkGroup = false;
3638			ShutdownRequest = NULL;
3639			PendingSignal = 0;
3640			CurrentPid = getpid();
3641			sm_exc_newthread(fatal_error);
3642
3643			/*
3644			**  See note above about SMTP processes and SIGCHLD.
3645			*/
3646
3647			if (OpMode == MD_SMTP ||
3648			    OpMode == MD_DAEMON ||
3649			    MaxQueueChildren > 0)
3650			{
3651				proc_list_clear();
3652				sm_releasesignal(SIGCHLD);
3653				(void) sm_signal(SIGCHLD, SIG_DFL);
3654			}
3655
3656			/* child -- error messages to the transcript */
3657			QuickAbort = OnlyOneError = false;
3658		}
3659	}
3660	else
3661	{
3662		pid = 0;
3663	}
3664
3665	if (pid == 0)
3666	{
3667		/*
3668		**  CHILD
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.
3673		*/
3674
3675		if (forkflag)
3676		{
3677			/* Reset global flags */
3678			RestartRequest = NULL;
3679			RestartWorkGroup = false;
3680			ShutdownRequest = NULL;
3681			PendingSignal = 0;
3682		}
3683
3684		/* set basic modes, etc. */
3685		sm_clear_events();
3686		clearstats();
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;
3692		e->e_id = id;
3693		e->e_qgrp = qgrp;
3694		e->e_qdir = qdir;
3695		GrabTo = UseErrorsTo = false;
3696		ExitStat = EX_OK;
3697		if (forkflag)
3698		{
3699			disconnect(1, e);
3700			set_op_mode(MD_QUEUERUN);
3701		}
3702		sm_setproctitle(true, e, "%s from queue", qid_printname(e));
3703		if (LogLevel > 76)
3704			sm_syslog(LOG_DEBUG, e->e_id, "dowork, pid=%d",
3705				  (int) CurrentPid);
3706
3707		/* don't use the headers from sendmail.cf... */
3708		e->e_header = NULL;
3709
3710		/* read the queue control file -- return if locked */
3711		if (!readqf(e, false))
3712		{
3713			if (tTd(40, 4) && e->e_id != NULL)
3714				sm_dprintf("readqf(%s) failed\n",
3715					qid_printname(e));
3716			e->e_id = NULL;
3717			if (forkflag)
3718				finis(false, true, EX_OK);
3719			else
3720			{
3721				/* adding this frees 8 bytes */
3722				clearenvelope(e, false, rpool);
3723
3724				/* adding this frees 12 bytes */
3725				sm_rpool_free(rpool);
3726				e->e_rpool = NULL;
3727				return 0;
3728			}
3729		}
3730
3731		e->e_flags |= EF_INQUEUE;
3732		eatheader(e, requeueflag, true);
3733
3734		if (requeueflag)
3735			queueup(e, false, false);
3736
3737		/* do the delivery */
3738		sendall(e, SM_DELIVER);
3739
3740		/* finish up and exit */
3741		if (forkflag)
3742			finis(true, true, ExitStat);
3743		else
3744		{
3745			(void) dropenvelope(e, true, false);
3746			sm_rpool_free(rpool);
3747			e->e_rpool = NULL;
3748			e->e_message = NULL;
3749		}
3750	}
3751	e->e_id = NULL;
3752	return pid;
3753}
3754
3755/*
3756**  DOWORKLIST -- process a list of envelopes as work requests
3757**
3758**	Similar to dowork(), except that after forking, it processes an
3759**	envelope and its siblings, treating each envelope as a work request.
3760**
3761**	Parameters:
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
3767**			child.
3768**
3769**	Returns:
3770**		process id of process that is running the queue job.
3771**
3772**	Side Effects:
3773**		The work request is satisfied if possible.
3774*/
3775
3776pid_t
3777doworklist(el, forkflag, requeueflag)
3778	ENVELOPE *el;
3779	bool forkflag;
3780	bool requeueflag;
3781{
3782	register pid_t pid;
3783	ENVELOPE *ei;
3784
3785	if (tTd(40, 1))
3786		sm_dprintf("doworklist()\n");
3787
3788	/*
3789	**  Fork for work.
3790	*/
3791
3792	if (forkflag)
3793	{
3794		/*
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.
3800		*/
3801
3802		closemaps(false);
3803
3804		pid = fork();
3805		if (pid < 0)
3806		{
3807			syserr("doworklist: cannot fork");
3808			return 0;
3809		}
3810		else if (pid > 0)
3811		{
3812			/* parent -- clean out connection cache */
3813			mci_flush(false, NULL);
3814		}
3815		else
3816		{
3817			/*
3818			**  Initialize exception stack and default exception
3819			**  handler for child process.
3820			*/
3821
3822			/* Reset global flags */
3823			RestartRequest = NULL;
3824			RestartWorkGroup = false;
3825			ShutdownRequest = NULL;
3826			PendingSignal = 0;
3827			CurrentPid = getpid();
3828			sm_exc_newthread(fatal_error);
3829
3830			/*
3831			**  See note above about SMTP processes and SIGCHLD.
3832			*/
3833
3834			if (OpMode == MD_SMTP ||
3835			    OpMode == MD_DAEMON ||
3836			    MaxQueueChildren > 0)
3837			{
3838				proc_list_clear();
3839				sm_releasesignal(SIGCHLD);
3840				(void) sm_signal(SIGCHLD, SIG_DFL);
3841			}
3842
3843			/* child -- error messages to the transcript */
3844			QuickAbort = OnlyOneError = false;
3845		}
3846	}
3847	else
3848	{
3849		pid = 0;
3850	}
3851
3852	if (pid != 0)
3853		return pid;
3854
3855	/*
3856	**  IN CHILD
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.
3861	*/
3862
3863	if (forkflag)
3864	{
3865		/* Reset global flags */
3866		RestartRequest = NULL;
3867		RestartWorkGroup = false;
3868		ShutdownRequest = NULL;
3869		PendingSignal = 0;
3870	}
3871
3872	/* set basic modes, etc. */
3873	sm_clear_events();
3874	clearstats();
3875	GrabTo = UseErrorsTo = false;
3876	ExitStat = EX_OK;
3877	if (forkflag)
3878	{
3879		disconnect(1, el);
3880		set_op_mode(MD_QUEUERUN);
3881	}
3882	if (LogLevel > 76)
3883		sm_syslog(LOG_DEBUG, el->e_id, "doworklist, pid=%d",
3884			  (int) CurrentPid);
3885
3886	for (ei = el; ei != NULL; ei = ei->e_sibling)
3887	{
3888		ENVELOPE e;
3889		SM_RPOOL_T *rpool;
3890
3891		if (WILL_BE_QUEUED(ei->e_sendmode))
3892			continue;
3893		else if (QueueMode != QM_QUARANTINE &&
3894			 ei->e_quarmsg != NULL)
3895			continue;
3896
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;
3902		e.e_id = ei->e_id;
3903		e.e_qgrp = ei->e_qgrp;
3904		e.e_qdir = ei->e_qdir;
3905		openxscript(&e);
3906		sm_setproctitle(true, &e, "%s from queue", qid_printname(&e));
3907
3908		/* don't use the headers from sendmail.cf... */
3909		e.e_header = NULL;
3910		CurEnv = &e;
3911
3912		/* read the queue control file -- return if locked */
3913		if (readqf(&e, false))
3914		{
3915			e.e_flags |= EF_INQUEUE;
3916			eatheader(&e, requeueflag, true);
3917
3918			if (requeueflag)
3919				queueup(&e, false, false);
3920
3921			/* do the delivery */
3922			sendall(&e, SM_DELIVER);
3923			(void) dropenvelope(&e, true, false);
3924		}
3925		else
3926		{
3927			if (tTd(40, 4) && e.e_id != NULL)
3928				sm_dprintf("readqf(%s) failed\n",
3929					qid_printname(&e));
3930		}
3931		sm_rpool_free(rpool);
3932		ei->e_id = NULL;
3933	}
3934
3935	/* restore CurEnv */
3936	CurEnv = el;
3937
3938	/* finish up and exit */
3939	if (forkflag)
3940		finis(true, true, ExitStat);
3941	return 0;
3942}
3943/*
3944**  READQF -- read queue file and set up environment.
3945**
3946**	Parameters:
3947**		e -- the envelope of the job to run.
3948**		openonly -- only open the qf (returned as e_lockfp)
3949**
3950**	Returns:
3951**		true if it successfully read the queue file.
3952**		false otherwise.
3953**
3954**	Side Effects:
3955**		The queue file is returned locked.
3956*/
3957
3958static bool
3959readqf(e, openonly)
3960	register ENVELOPE *e;
3961	bool openonly;
3962{
3963	register SM_FILE_T *qfp;
3964	ADDRESS *ctladdr;
3965	struct stat st, stf;
3966	char *bp;
3967	int qfver = 0;
3968	long hdrsize = 0;
3969	register char *p;
3970	char *frcpt = NULL;
3971	char *orcpt = NULL;
3972	bool nomore = false;
3973	bool bogus = false;
3974	MODE_T qsafe;
3975	char *err;
3976	char qf[MAXPATHLEN];
3977	char buf[MAXLINE];
3978	int bufsize;
3979
3980	/*
3981	**  Read and process the file.
3982	*/
3983
3984	SM_REQUIRE(e != NULL);
3985	bp = 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);
3988	if (qfp == NULL)
3989	{
3990		int save_errno = errno;
3991
3992		if (tTd(40, 8))
3993			sm_dprintf("readqf(%s): sm_io_open failure (%s)\n",
3994				qf, sm_errstring(errno));
3995		errno = save_errno;
3996		if (errno != ENOENT
3997		    )
3998			syserr("readqf: no control file %s", qf);
3999		RELEASE_QUEUE;
4000		return false;
4001	}
4002
4003	if (!lockfile(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), qf, NULL,
4004		      LOCK_EX|LOCK_NB))
4005	{
4006		/* being processed by another queuer */
4007		if (Verbose)
4008			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4009					     "%s: locked\n", e->e_id);
4010		if (tTd(40, 8))
4011			sm_dprintf("%s: locked\n", e->e_id);
4012		if (LogLevel > 19)
4013			sm_syslog(LOG_DEBUG, e->e_id, "locked");
4014		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4015		RELEASE_QUEUE;
4016		return false;
4017	}
4018
4019	RELEASE_QUEUE;
4020
4021	/*
4022	**  Prevent locking race condition.
4023	**
4024	**  Process A: readqf(): qfp = fopen(qffile)
4025	**  Process B: queueup(): rename(tf, qf)
4026	**  Process B: unlocks(tf)
4027	**  Process A: lockfile(qf);
4028	**
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.
4032	**
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
4036	**  above.
4037	*/
4038
4039	if (stat(qf, &stf) < 0 ||
4040	    fstat(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), &st) < 0)
4041	{
4042		/* must have been being processed by someone else */
4043		if (tTd(40, 8))
4044			sm_dprintf("readqf(%s): [f]stat failure (%s)\n",
4045				qf, sm_errstring(errno));
4046		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4047		return false;
4048	}
4049
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 ||
4055#endif
4056	    st.st_uid != stf.st_uid ||
4057	    st.st_gid != stf.st_gid ||
4058	    st.st_size != stf.st_size)
4059	{
4060		/* changed after opened */
4061		if (Verbose)
4062			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4063					     "%s: changed\n", e->e_id);
4064		if (tTd(40, 8))
4065			sm_dprintf("%s: changed\n", e->e_id);
4066		if (LogLevel > 19)
4067			sm_syslog(LOG_DEBUG, e->e_id, "changed");
4068		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4069		return false;
4070	}
4071
4072	/*
4073	**  Check the queue file for plausibility to avoid attacks.
4074	*/
4075
4076	qsafe = S_IWOTH|S_IWGRP;
4077	if (bitset(S_IWGRP, QueueFileMode))
4078		qsafe &= ~S_IWGRP;
4079
4080	bogus = st.st_uid != geteuid() &&
4081		st.st_uid != TrustedUid &&
4082		geteuid() != RealUid;
4083
4084	/*
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
4090	**  run the queue!
4091	*/
4092
4093	if (bogus && st.st_gid == getegid() && UseMSP)
4094	{
4095		char delim;
4096		struct stat dst;
4097
4098		bp = SM_LAST_DIR_DELIM(qf);
4099		if (bp == NULL)
4100			delim = '\0';
4101		else
4102		{
4103			delim = *bp;
4104			*bp = '\0';
4105		}
4106		if (stat(delim == '\0' ? "." : qf, &dst) < 0)
4107			syserr("readqf: cannot stat directory %s",
4108				delim == '\0' ? "." : qf);
4109		else
4110		{
4111			bogus = !(bitset(S_IWGRP, QueueFileMode) &&
4112				  bitset(S_IWGRP, dst.st_mode) &&
4113				  dst.st_gid == st.st_gid);
4114		}
4115		if (delim != '\0')
4116			*bp = delim;
4117		bp = NULL;
4118	}
4119	if (!bogus)
4120		bogus = bitset(qsafe, st.st_mode);
4121	if (bogus)
4122	{
4123		if (LogLevel > 0)
4124		{
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);
4129		}
4130		if (tTd(40, 8))
4131			sm_dprintf("readqf(%s): bogus file\n", qf);
4132		e->e_flags |= EF_INQUEUE;
4133		if (!openonly)
4134			loseqfile(e, "bogus file uid/gid in mqueue");
4135		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4136		return false;
4137	}
4138
4139	if (st.st_size == 0)
4140	{
4141		/* must be a bogus file -- if also old, just remove it */
4142		if (!openonly && st.st_ctime + 10 * 60 < curtime())
4143		{
4144			(void) xunlink(queuename(e, DATAFL_LETTER));
4145			(void) xunlink(queuename(e, ANYQFL_LETTER));
4146		}
4147		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4148		return false;
4149	}
4150
4151	if (st.st_nlink == 0)
4152	{
4153		/*
4154		**  Race condition -- we got a file just as it was being
4155		**  unlinked.  Just assume it is zero length.
4156		*/
4157
4158		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4159		return false;
4160	}
4161
4162#if _FFR_TRUSTED_QF
4163	/*
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.
4167	*/
4168
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 */
4176
4177	/* good file -- save this lock */
4178	e->e_lockfp = qfp;
4179
4180	/* Just wanted the open file */
4181	if (openonly)
4182		return true;
4183
4184	/* do basic system initialization */
4185	initsys(e);
4186	macdefine(&e->e_macro, A_PERM, 'i', e->e_id);
4187
4188	LineNumber = 0;
4189	e->e_flags |= EF_GLOBALERRS;
4190	set_op_mode(MD_QUEUERUN);
4191	ctladdr = NULL;
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));
4198#endif
4199	e->e_dfino = -1;
4200	e->e_msgsize = -1;
4201	while (bufsize = sizeof(buf),
4202	       (bp = fgetfolded(buf, &bufsize, qfp)) != NULL)
4203	{
4204		unsigned long qflags;
4205		ADDRESS *q;
4206		int r;
4207		time_t now;
4208		auto char *ep;
4209
4210		if (tTd(40, 4))
4211			sm_dprintf("+++++ %s\n", bp);
4212		if (nomore)
4213		{
4214			/* hack attack */
4215  hackattack:
4216			syserr("SECURITY ALERT: extra or bogus data in queue file: %s",
4217			       bp);
4218			err = "bogus queue line";
4219			goto fail;
4220		}
4221		switch (bp[0])
4222		{
4223		  case 'A':		/* AUTH= parameter */
4224			if (!xtextok(&bp[1]))
4225				goto hackattack;
4226			e->e_auth_param = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4227			break;
4228
4229		  case 'B':		/* body type */
4230			r = check_bodytype(&bp[1]);
4231			if (!BODYTYPE_VALID(r))
4232				goto hackattack;
4233			e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4234			break;
4235
4236		  case 'C':		/* specify controlling user */
4237			ctladdr = setctluser(&bp[1], qfver, e);
4238			break;
4239
4240		  case 'D':		/* data file name */
4241			/* obsolete -- ignore */
4242			break;
4243
4244		  case 'd':		/* data file directory name */
4245			{
4246				int qgrp, qdir;
4247
4248#if _FFR_MSP_PARANOIA
4249				/* forbid queue groups in MSP? */
4250				if (UseMSP)
4251					goto hackattack;
4252#endif
4253				for (qgrp = 0;
4254				     qgrp < NumQueue && Queue[qgrp] != NULL;
4255				     ++qgrp)
4256				{
4257					for (qdir = 0;
4258					     qdir < Queue[qgrp]->qg_numqueues;
4259					     ++qdir)
4260					{
4261						if (strcmp(&bp[1],
4262							   Queue[qgrp]->qg_qpaths[qdir].qp_name)
4263						    == 0)
4264						{
4265							e->e_dfqgrp = qgrp;
4266							e->e_dfqdir = qdir;
4267							goto done;
4268						}
4269					}
4270				}
4271				err = "bogus queue file directory";
4272				goto fail;
4273			  done:
4274				break;
4275			}
4276
4277		  case 'E':		/* specify error recipient */
4278			/* no longer used */
4279			break;
4280
4281		  case 'F':		/* flag bits */
4282			if (strncmp(bp, "From ", 5) == 0)
4283			{
4284				/* we are being spoofed! */
4285				syserr("SECURITY ALERT: bogus qf line %s", bp);
4286				err = "bogus queue line";
4287				goto fail;
4288			}
4289			for (p = &bp[1]; *p != '\0'; p++)
4290			{
4291				switch (*p)
4292				{
4293				  case '8':	/* has 8 bit data */
4294					e->e_flags |= EF_HAS8BIT;
4295					break;
4296
4297				  case 'b':	/* delete Bcc: header */
4298					e->e_flags |= EF_DELETE_BCC;
4299					break;
4300
4301				  case 'd':	/* envelope has DSN RET= */
4302					e->e_flags |= EF_RET_PARAM;
4303					break;
4304
4305				  case 'n':	/* don't return body */
4306					e->e_flags |= EF_NO_BODY_RETN;
4307					break;
4308
4309				  case 'r':	/* response */
4310					e->e_flags |= EF_RESPONSE;
4311					break;
4312
4313				  case 's':	/* split */
4314					e->e_flags |= EF_SPLIT;
4315					break;
4316
4317				  case 'w':	/* warning sent */
4318					e->e_flags |= EF_WARNING;
4319					break;
4320
4321#if _FFR_EAI
4322				  case 'e':	/* message requires EAI */
4323					e->e_smtputf8 = true;
4324					break;
4325#endif /* _FFR_EAI */
4326				}
4327			}
4328			break;
4329
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);
4334			break;
4335
4336		  case 'H':		/* header */
4337
4338			/*
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.
4342			*/
4343
4344			hdrsize += strlen(bp) - 3;
4345			(void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e);
4346			break;
4347
4348		  case 'I':		/* data file's inode number */
4349			/* regenerated below */
4350			break;
4351
4352		  case 'K':		/* time of last delivery attempt */
4353			e->e_dtime = atol(&buf[1]);
4354			break;
4355
4356		  case 'L':		/* Solaris Content-Length: */
4357		  case 'M':		/* message */
4358			/* ignore this; we want a new message next time */
4359			break;
4360
4361		  case 'N':		/* number of delivery attempts */
4362			e->e_ntries = atoi(&buf[1]);
4363
4364			/* if this has been tried recently, let it be */
4365			now = curtime();
4366			if (e->e_ntries > 0 && e->e_dtime <= now &&
4367			    now < e->e_dtime + MinQueueAge)
4368			{
4369				char *howlong;
4370
4371				howlong = pintvl(now - e->e_dtime, true);
4372				if (Verbose)
4373					(void) sm_io_fprintf(smioout,
4374							     SM_TIME_DEFAULT,
4375							     "%s: too young (%s)\n",
4376							     e->e_id, howlong);
4377				if (tTd(40, 8))
4378					sm_dprintf("%s: too young (%s)\n",
4379						e->e_id, howlong);
4380				if (LogLevel > 19)
4381					sm_syslog(LOG_DEBUG, e->e_id,
4382						  "too young (%s)",
4383						  howlong);
4384				e->e_id = NULL;
4385				unlockqueue(e);
4386				if (bp != buf)
4387					sm_free(bp);
4388				return false;
4389			}
4390			macdefine(&e->e_macro, A_TEMP,
4391				macid("{ntries}"), &buf[1]);
4392
4393#if NAMED_BIND
4394			/* adjust BIND parameters immediately */
4395			if (e->e_ntries == 0)
4396			{
4397				_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
4398				_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
4399			}
4400			else
4401			{
4402				_res.retry = TimeOuts.res_retry[RES_TO_NORMAL];
4403				_res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL];
4404			}
4405#endif /* NAMED_BIND */
4406			break;
4407
4408		  case 'P':		/* message priority */
4409			e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
4410			break;
4411
4412		  case 'Q':		/* original recipient */
4413			orcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4414			break;
4415
4416		  case 'r':		/* final recipient */
4417			frcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
4418			break;
4419
4420		  case 'R':		/* specify recipient */
4421			p = bp;
4422			qflags = 0;
4423			if (qfver >= 1)
4424			{
4425				/* get flag bits */
4426				while (*++p != '\0' && *p != ':')
4427				{
4428					switch (*p)
4429					{
4430					  case 'N':
4431						qflags |= QHASNOTIFY;
4432						break;
4433
4434					  case 'S':
4435						qflags |= QPINGONSUCCESS;
4436						break;
4437
4438					  case 'F':
4439						qflags |= QPINGONFAILURE;
4440						break;
4441
4442					  case 'D':
4443						qflags |= QPINGONDELAY;
4444						break;
4445
4446					  case 'P':
4447						qflags |= QPRIMARY;
4448						break;
4449
4450					  case 'A':
4451						if (ctladdr != NULL)
4452							ctladdr->q_flags |= QALIAS;
4453						break;
4454
4455					  case 'B':
4456						qflags |= QINTBCC;
4457						break;
4458
4459					  case QDYNMAILFLG:
4460						qflags |= QDYNMAILER;
4461						break;
4462
4463					  default: /* ignore or complain? */
4464						break;
4465					}
4466				}
4467			}
4468			else
4469				qflags |= QPRIMARY;
4470			macdefine(&e->e_macro, A_PERM, macid("{addr_type}"),
4471				((qflags & QINTBCC) != 0) ? "e b" : "e r");
4472			if (*p != '\0')
4473				q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0',
4474						NULL, e, true);
4475			else
4476				q = NULL;
4477			if (q != NULL)
4478			{
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;
4483				if (qfver >= 1)
4484					q->q_flags &= ~Q_PINGFLAGS;
4485				q->q_flags |= qflags;
4486				q->q_finalrcpt = frcpt;
4487				q->q_orcpt = orcpt;
4488#if _FFR_RCPTFLAGS
4489				if (bitset(QDYNMAILER, qflags))
4490					newmodmailer(q, QDYNMAILFLG);
4491#endif
4492				(void) recipient(q, &e->e_sendqueue, 0, e);
4493			}
4494			frcpt = NULL;
4495			orcpt = NULL;
4496			macdefine(&e->e_macro, A_PERM, macid("{addr_type}"),
4497				NULL);
4498			break;
4499
4500		  case 'S':		/* sender */
4501			setsender(sm_rpool_strdup_x(e->e_rpool, &bp[1]),
4502				  e, NULL, '\0', true);
4503			break;
4504
4505		  case 'T':		/* init time */
4506			e->e_ctime = atol(&bp[1]);
4507			break;
4508
4509		  case 'V':		/* queue file version number */
4510			qfver = atoi(&bp[1]);
4511			if (qfver <= QF_VERSION)
4512				break;
4513			syserr("Version number in queue file (%d) greater than max (%d)",
4514				qfver, QF_VERSION);
4515			err = "unsupported queue file version";
4516			goto fail;
4517			/* NOTREACHED */
4518			break;
4519
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);
4524			break;
4525
4526		  case '!':		/* deliver by */
4527
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);
4531
4532		  case '$':		/* define macro */
4533			{
4534				r = macid_parse(&bp[1], &ep);
4535				if (r == 0)
4536					break;
4537				macdefine(&e->e_macro, A_PERM, r,
4538					sm_rpool_strdup_x(e->e_rpool, ep));
4539			}
4540			break;
4541
4542		  case '.':		/* terminate file */
4543			nomore = true;
4544			break;
4545
4546		  default:
4547			syserr("readqf: %s: line %d: bad line \"%s\"",
4548				qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
4549			err = "unrecognized line";
4550			goto fail;
4551		}
4552
4553		if (bp != buf)
4554			SM_FREE(bp);
4555	}
4556
4557	/*
4558	**  If we haven't read any lines, this queue file is empty.
4559	**  Arrange to remove it without referencing any null pointers.
4560	*/
4561
4562	if (LineNumber == 0)
4563	{
4564		errno = 0;
4565		e->e_flags |= EF_CLRQUEUE|EF_FATALERRS|EF_RESPONSE;
4566		return true;
4567	}
4568
4569	/* Check to make sure we have a complete queue file read */
4570	if (!nomore)
4571	{
4572		syserr("readqf: %s: incomplete queue file read", qf);
4573		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4574		return false;
4575	}
4576
4577#if _FFR_QF_PARANOIA
4578	/* Check to make sure key fields were read */
4579	if (e->e_from.q_mailer == NULL)
4580	{
4581		syserr("readqf: %s: sender not specified in queue file", qf);
4582		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4583		return false;
4584	}
4585	/* other checks? */
4586#endif /* _FFR_QF_PARANOIA */
4587
4588#if _FFR_EAI
4589	/*
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.
4594	*/
4595
4596	if (!e->e_smtputf8)
4597	{
4598		ADDRESS *q;
4599
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;
4605	}
4606#endif /* _FFR_EAI */
4607
4608	/* possibly set ${dsn_ret} macro */
4609	if (bitset(EF_RET_PARAM, e->e_flags))
4610	{
4611		if (bitset(EF_NO_BODY_RETN, e->e_flags))
4612			macdefine(&e->e_macro, A_PERM,
4613				macid("{dsn_ret}"), "hdrs");
4614		else
4615			macdefine(&e->e_macro, A_PERM,
4616				macid("{dsn_ret}"), "full");
4617	}
4618
4619	/*
4620	**  Arrange to read the data file.
4621	*/
4622
4623	p = queuename(e, DATAFL_LETTER);
4624	e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, p, SM_IO_RDONLY_B,
4625			      NULL);
4626	if (e->e_dfp == NULL)
4627	{
4628		syserr("readqf: cannot open %s", p);
4629	}
4630	else
4631	{
4632		e->e_flags |= EF_HAS_DF;
4633		if (fstat(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, NULL), &st)
4634		    >= 0)
4635		{
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}"),
4642				  buf);
4643		}
4644	}
4645
4646	return true;
4647
4648  fail:
4649	/*
4650	**  There was some error reading the qf file (reason is in err var.)
4651	**  Cleanup:
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.
4656	*/
4657
4658	if (bp != buf)
4659		SM_FREE(bp);
4660	if (qfp != NULL)
4661		(void) sm_io_close(qfp, SM_TIME_DEFAULT);
4662	e->e_lockfp = NULL;
4663	e->e_flags |= EF_INQUEUE;
4664	loseqfile(e, err);
4665	return false;
4666}
4667/*
4668**  PRTSTR -- print a string, "unprintable" characters are shown as \oct
4669**
4670**	Parameters:
4671**		s -- string to print
4672**		ml -- maximum length of output
4673**
4674**	Returns:
4675**		number of entries
4676**
4677**	Side Effects:
4678**		Prints a string on stdout.
4679*/
4680
4681static void prtstr __P((char *, int));
4682
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))	\
4687			continue;
4688#else
4689# define IS_BOUNCE_QUEUE(i) false
4690# define SKIP_BOUNCE_QUEUE(i)
4691#endif
4692
4693static void
4694prtstr(s, ml)
4695	char *s;
4696	int ml;
4697{
4698	int c;
4699
4700	if (s == NULL)
4701		return;
4702	while (ml-- > 0 && ((c = *s++) != '\0'))
4703	{
4704		if (c == '\\')
4705		{
4706			if (ml-- > 0)
4707			{
4708				(void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
4709				(void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
4710			}
4711		}
4712		else if (isascii(c) && isprint(c))
4713			(void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
4714		else
4715		{
4716			if ((ml -= 3) > 0)
4717				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4718						     "\\%03o", c & 0xFF);
4719		}
4720	}
4721}
4722/*
4723**  PRINTNQE -- print out number of entries in the mail queue
4724**
4725**	Parameters:
4726**		out -- output file pointer.
4727**		prefix -- string to output in front of each line.
4728**
4729**	Returns:
4730**		none.
4731*/
4732
4733void
4734printnqe(out, prefix)
4735	SM_FILE_T *out;
4736	char *prefix;
4737{
4738#if SM_CONF_SHM
4739	int i, k = 0, nrequests = 0;
4740	bool unknown = false;
4741
4742	if (ShmId == SM_SHM_NO_ID)
4743	{
4744		if (prefix == NULL)
4745			(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4746					"Data unavailable: shared memory not updated\n");
4747		else
4748			(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4749					"%sNOTCONFIGURED:-1\r\n", prefix);
4750		return;
4751	}
4752	for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
4753	{
4754		int j;
4755
4756		SKIP_BOUNCE_QUEUE(i)
4757		k++;
4758		for (j = 0; j < Queue[i]->qg_numqueues; j++)
4759		{
4760			int n;
4761
4762			if (StopRequest)
4763				stop_sendmail();
4764
4765			n = QSHM_ENTRIES(Queue[i]->qg_qpaths[j].qp_idx);
4766			if (prefix != NULL)
4767				(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4768					"%s%s:%d\r\n",
4769					prefix, qid_printqueue(i, j), n);
4770			else if (n < 0)
4771			{
4772				(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4773					"%s: unknown number of entries\n",
4774					qid_printqueue(i, j));
4775				unknown = true;
4776			}
4777			else if (n == 0)
4778			{
4779				(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4780					"%s is empty\n",
4781					qid_printqueue(i, j));
4782			}
4783			else if (n > 0)
4784			{
4785				(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4786					"%s: entries=%d\n",
4787					qid_printqueue(i, j), n);
4788				nrequests += n;
4789				k++;
4790			}
4791		}
4792	}
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 */
4798	if (prefix == NULL)
4799		(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4800			     "Data unavailable without shared memory support\n");
4801	else
4802		(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
4803			     "%sNOTAVAILABLE:-1\r\n", prefix);
4804#endif /* SM_CONF_SHM */
4805}
4806/*
4807**  PRINTQUEUE -- print out a representation of the mail queue
4808**
4809**	Parameters:
4810**		none.
4811**
4812**	Returns:
4813**		none.
4814**
4815**	Side Effects:
4816**		Prints a listing of the mail queue on the standard output.
4817*/
4818
4819void
4820printqueue()
4821{
4822	int i, k = 0, nrequests = 0;
4823
4824	for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
4825	{
4826		int j;
4827
4828		k++;
4829		for (j = 0; j < Queue[i]->qg_numqueues; j++)
4830		{
4831			if (StopRequest)
4832				stop_sendmail();
4833			nrequests += print_single_queue(i, j);
4834			k++;
4835		}
4836	}
4837	if (k > 1)
4838		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4839				     "\t\tTotal requests: %d\n",
4840				     nrequests);
4841}
4842/*
4843**  PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue
4844**
4845**	Parameters:
4846**		qgrp -- the index of the queue group.
4847**		qdir -- the queue directory.
4848**
4849**	Returns:
4850**		number of requests in mail queue.
4851**
4852**	Side Effects:
4853**		Prints a listing of the mail queue on the standard output.
4854*/
4855
4856int
4857print_single_queue(qgrp, qdir)
4858	int qgrp;
4859	int qdir;
4860{
4861	register WORK *w;
4862	SM_FILE_T *f;
4863	int nrequests;
4864	char qd[MAXPATHLEN];
4865	char qddf[MAXPATHLEN];
4866	char buf[MAXLINE];
4867
4868	if (qdir == NOQDIR)
4869	{
4870		(void) sm_strlcpy(qd, ".", sizeof(qd));
4871		(void) sm_strlcpy(qddf, ".", sizeof(qddf));
4872	}
4873	else
4874	{
4875		(void) sm_strlcpyn(qd, sizeof(qd), 2,
4876			Queue[qgrp]->qg_qpaths[qdir].qp_name,
4877			(bitset(QP_SUBQF,
4878				Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
4879					? "/qf" : ""));
4880		(void) sm_strlcpyn(qddf, sizeof(qddf), 2,
4881			Queue[qgrp]->qg_qpaths[qdir].qp_name,
4882			(bitset(QP_SUBDF,
4883				Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
4884					? "/df" : ""));
4885	}
4886
4887	/*
4888	**  Check for permission to print the queue
4889	*/
4890
4891	if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
4892	{
4893		struct stat st;
4894#ifdef NGROUPS_MAX
4895		int n;
4896		extern GIDSET_T InitialGidSet[NGROUPS_MAX];
4897#endif
4898
4899		if (stat(qd, &st) < 0)
4900		{
4901			syserr("Cannot stat %s",
4902				qid_printqueue(qgrp, qdir));
4903			return 0;
4904		}
4905#ifdef NGROUPS_MAX
4906		n = NGROUPS_MAX;
4907		while (--n >= 0)
4908		{
4909			if (InitialGidSet[n] == st.st_gid)
4910				break;
4911		}
4912		if (n < 0 && RealGid != st.st_gid)
4913#else /* NGROUPS_MAX */
4914		if (RealGid != st.st_gid)
4915#endif /* NGROUPS_MAX */
4916		{
4917			usrerr("510 You are not permitted to see the queue");
4918			setstat(EX_NOPERM);
4919			return 0;
4920		}
4921	}
4922
4923	/*
4924	**  Read and order the queue.
4925	*/
4926
4927	nrequests = gatherq(qgrp, qdir, true, NULL, NULL, NULL);
4928	(void) sortq(Queue[qgrp]->qg_maxlist);
4929
4930	/*
4931	**  Print the work list that we have read.
4932	*/
4933
4934	/* first see if there is anything */
4935	if (nrequests <= 0)
4936	{
4937		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s is empty\n",
4938				     qid_printqueue(qgrp, qdir));
4939		return 0;
4940	}
4941
4942	sm_getla();	/* get load average */
4943
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);
4950	if (Verbose)
4951		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4952			")\n-----Q-ID----- --Size-- -Priority- ---Q-Time--- --------Sender/Recipient--------\n");
4953	else
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)
4957	{
4958		struct stat st;
4959		auto time_t submittime = 0;
4960		long dfsize;
4961		int flags = 0;
4962		int qfver;
4963		char quarmsg[MAXLINE];
4964		char statmsg[MAXLINE];
4965		char bodytype[MAXNAME + 1];
4966		char qf[MAXPATHLEN];
4967
4968		if (StopRequest)
4969			stop_sendmail();
4970
4971		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%13s",
4972				     w->w_name + 2);
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,
4975			       NULL);
4976		if (f == NULL)
4977		{
4978			if (errno == EPERM)
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");
4984			else
4985				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4986						     " (%s)\n",
4987						     sm_errstring(errno));
4988			errno = 0;
4989			continue;
4990		}
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;
4995		else
4996		{
4997			ENVELOPE e;
4998
4999			/*
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.
5003			*/
5004
5005			newenvelope(&e, &BlankEnvelope, sm_rpool_new_x(NULL));
5006			e.e_id = w->w_name + 2;
5007			e.e_qgrp = qgrp;
5008			e.e_qdir = qdir;
5009			dfsize = -1;
5010			if (readqf(&e, false))
5011			{
5012				char *df = queuename(&e, DATAFL_LETTER);
5013				if (stat(df, &st) >= 0)
5014					dfsize = st.st_size;
5015			}
5016			if (e.e_lockfp != NULL)
5017			{
5018				(void) sm_io_close(e.e_lockfp, SM_TIME_DEFAULT);
5019				e.e_lockfp = NULL;
5020			}
5021			clearenvelope(&e, false, e.e_rpool);
5022			sm_rpool_free(e.e_rpool);
5023		}
5024		if (w->w_lock)
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");
5032		else
5033			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " ");
5034
5035		errno = 0;
5036
5037		quarmsg[0] = '\0';
5038		statmsg[0] = bodytype[0] = '\0';
5039		qfver = 0;
5040		while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
5041		{
5042			register int i;
5043			register char *p;
5044
5045			if (StopRequest)
5046				stop_sendmail();
5047
5048			fixcrlf(buf, true);
5049			switch (buf[0])
5050			{
5051			  case 'V':	/* queue file version */
5052				qfver = atoi(&buf[1]);
5053				break;
5054
5055			  case 'M':	/* error message */
5056				if ((i = strlen(&buf[1])) >= sizeof(statmsg))
5057					i = sizeof(statmsg) - 1;
5058				memmove(statmsg, &buf[1], i);
5059				statmsg[i] = '\0';
5060				break;
5061
5062			  case 'q':	/* quarantine reason */
5063				if ((i = strlen(&buf[1])) >= sizeof(quarmsg))
5064					i = sizeof(quarmsg) - 1;
5065				memmove(quarmsg, &buf[1], i);
5066				quarmsg[i] = '\0';
5067				break;
5068
5069			  case 'B':	/* body type */
5070				if ((i = strlen(&buf[1])) >= sizeof(bodytype))
5071					i = sizeof(bodytype) - 1;
5072				memmove(bodytype, &buf[1], i);
5073				bodytype[i] = '\0';
5074				break;
5075
5076			  case 'S':	/* sender name */
5077				if (Verbose)
5078				{
5079					(void) sm_io_fprintf(smioout,
5080						SM_TIME_DEFAULT,
5081						"%8ld %10ld%c%.12s ",
5082						dfsize,
5083						w->w_pri,
5084						bitset(EF_WARNING, flags)
5085							? '+' : ' ',
5086						ctime(&submittime) + 4);
5087					prtstr(&buf[1], 78);
5088				}
5089				else
5090				{
5091					(void) sm_io_fprintf(smioout,
5092						SM_TIME_DEFAULT,
5093						"%8ld %.16s ",
5094						dfsize,
5095						ctime(&submittime));
5096					prtstr(&buf[1], 39);
5097				}
5098
5099				if (quarmsg[0] != '\0')
5100				{
5101					(void) sm_io_fprintf(smioout,
5102							     SM_TIME_DEFAULT,
5103							     "\n     QUARANTINE: %.*s",
5104							     Verbose ? 100 : 60,
5105							     quarmsg);
5106					quarmsg[0] = '\0';
5107				}
5108
5109				if (statmsg[0] != '\0' || bodytype[0] != '\0')
5110				{
5111					(void) sm_io_fprintf(smioout,
5112						SM_TIME_DEFAULT,
5113						"\n    %10.10s",
5114						bodytype);
5115					if (statmsg[0] != '\0')
5116						(void) sm_io_fprintf(smioout,
5117							SM_TIME_DEFAULT,
5118							"   (%.*s)",
5119							Verbose ? 100 : 60,
5120							statmsg);
5121					statmsg[0] = '\0';
5122				}
5123				break;
5124
5125			  case 'C':	/* controlling user */
5126				if (Verbose)
5127					(void) sm_io_fprintf(smioout,
5128						SM_TIME_DEFAULT,
5129						"\n\t\t\t\t\t\t(---%.64s---)",
5130						&buf[1]);
5131				break;
5132
5133			  case 'R':	/* recipient name */
5134				p = &buf[1];
5135				if (qfver >= 1)
5136				{
5137					p = strchr(p, ':');
5138					if (p == NULL)
5139						break;
5140					p++;
5141				}
5142				if (Verbose)
5143				{
5144					(void) sm_io_fprintf(smioout,
5145							SM_TIME_DEFAULT,
5146							"\n\t\t\t\t\t\t");
5147					prtstr(p, 71);
5148				}
5149				else
5150				{
5151					(void) sm_io_fprintf(smioout,
5152							SM_TIME_DEFAULT,
5153							"\n\t\t\t\t\t ");
5154					prtstr(p, 38);
5155				}
5156				if (Verbose && statmsg[0] != '\0')
5157				{
5158					(void) sm_io_fprintf(smioout,
5159							SM_TIME_DEFAULT,
5160							"\n\t\t (%.100s)",
5161							statmsg);
5162					statmsg[0] = '\0';
5163				}
5164				break;
5165
5166			  case 'T':	/* creation time */
5167				submittime = atol(&buf[1]);
5168				break;
5169
5170			  case 'F':	/* flag bits */
5171				for (p = &buf[1]; *p != '\0'; p++)
5172				{
5173					switch (*p)
5174					{
5175					  case 'w':
5176						flags |= EF_WARNING;
5177						break;
5178					}
5179				}
5180			}
5181		}
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);
5187	}
5188	return nrequests;
5189}
5190
5191/*
5192**  QUEUE_LETTER -- get the proper queue letter for the current QueueMode.
5193**
5194**	Parameters:
5195**		e -- envelope to build it in/from.
5196**		type -- the file type, used as the first character
5197**			of the file name.
5198**
5199**	Returns:
5200**		the letter to use
5201*/
5202
5203static char
5204queue_letter(e, type)
5205	ENVELOPE *e;
5206	int type;
5207{
5208	/* Change type according to QueueMode */
5209	if (type == ANYQFL_LETTER)
5210	{
5211		if (e->e_quarmsg != NULL)
5212			type = QUARQF_LETTER;
5213		else
5214		{
5215			switch (QueueMode)
5216			{
5217			  case QM_NORMAL:
5218				type = NORMQF_LETTER;
5219				break;
5220
5221			  case QM_QUARANTINE:
5222				type = QUARQF_LETTER;
5223				break;
5224
5225			  case QM_LOST:
5226				type = LOSEQF_LETTER;
5227				break;
5228
5229			  default:
5230				/* should never happen */
5231				abort();
5232				/* NOTREACHED */
5233			}
5234		}
5235	}
5236	return type;
5237}
5238
5239/*
5240**  QUEUENAME -- build a file name in the queue directory for this envelope.
5241**
5242**	Parameters:
5243**		e -- envelope to build it in/from.
5244**		type -- the file type, used as the first character
5245**			of the file name.
5246**
5247**	Returns:
5248**		a pointer to the queue name (in a static buffer).
5249**
5250**	Side Effects:
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().
5254*/
5255
5256char *
5257queuename(e, type)
5258	register ENVELOPE *e;
5259	int type;
5260{
5261	int qd, qg;
5262	char *sub = "/";
5263	char pref[3];
5264	static char buf[MAXPATHLEN];
5265
5266	/* Assign an ID if needed */
5267	if (e->e_id == NULL)
5268	{
5269		if (IntSig)
5270			return NULL;
5271		assign_queueid(e);
5272	}
5273	type = queue_letter(e, type);
5274
5275	/* begin of filename */
5276	pref[0] = (char) type;
5277	pref[1] = 'f';
5278	pref[2] = '\0';
5279
5280	/* Assign a queue group/directory if needed */
5281	if (type == XSCRPT_LETTER)
5282	{
5283		/*
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.
5289		*/
5290
5291		if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR)
5292		{
5293			if (e->e_qgrp != NOQGRP && e->e_qdir != NOQDIR)
5294			{
5295				e->e_xfqgrp = e->e_qgrp;
5296				e->e_xfqdir = e->e_qdir;
5297			}
5298			else
5299			{
5300				e->e_xfqgrp = 0;
5301				if (Queue[e->e_xfqgrp]->qg_numqueues <= 1)
5302					e->e_xfqdir = 0;
5303				else
5304				{
5305					e->e_xfqdir = get_rand_mod(
5306					      Queue[e->e_xfqgrp]->qg_numqueues);
5307				}
5308			}
5309		}
5310		qd = e->e_xfqdir;
5311		qg = e->e_xfqgrp;
5312	}
5313	else
5314	{
5315		if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR)
5316		{
5317			if (IntSig)
5318				return NULL;
5319			(void) setnewqueue(e);
5320		}
5321		if (type ==  DATAFL_LETTER)
5322		{
5323			qd = e->e_dfqdir;
5324			qg = e->e_dfqgrp;
5325		}
5326		else
5327		{
5328			qd = e->e_qdir;
5329			qg = e->e_qgrp;
5330		}
5331	}
5332
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);
5336	else
5337	{
5338		switch (type)
5339		{
5340		  case DATAFL_LETTER:
5341			if (bitset(QP_SUBDF, Queue[qg]->qg_qpaths[qd].qp_subdirs))
5342				sub = "/df/";
5343			break;
5344
5345		  case QUARQF_LETTER:
5346		  case TEMPQF_LETTER:
5347		  case NEWQFL_LETTER:
5348		  case LOSEQF_LETTER:
5349		  case NORMQF_LETTER:
5350			if (bitset(QP_SUBQF, Queue[qg]->qg_qpaths[qd].qp_subdirs))
5351				sub = "/qf/";
5352			break;
5353
5354		  case XSCRPT_LETTER:
5355			if (bitset(QP_SUBXF, Queue[qg]->qg_qpaths[qd].qp_subdirs))
5356				sub = "/xf/";
5357			break;
5358
5359		  default:
5360			if (IntSig)
5361				return NULL;
5362			sm_abort("queuename: bad queue file type %d", type);
5363		}
5364
5365		(void) sm_strlcpyn(buf, sizeof(buf), 4,
5366				Queue[qg]->qg_qpaths[qd].qp_name,
5367				sub, pref, e->e_id);
5368	}
5369
5370	if (tTd(7, 2))
5371		sm_dprintf("queuename: %s\n", buf);
5372	return buf;
5373}
5374
5375/*
5376**  INIT_QID_ALG -- Initialize the (static) parameters that are used to
5377**	generate a queue ID.
5378**
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.
5389**
5390**	Parameters:
5391**		none
5392**
5393**	Returns:
5394**		none.
5395*/
5396
5397void
5398init_qid_alg()
5399{
5400	LastQueueTime = 0;
5401	LastQueuePid = -1;
5402}
5403
5404/*
5405**  ASSIGN_QUEUEID -- assign a queue ID for this envelope.
5406**
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.]
5412**
5413**	Parameters:
5414**		e -- envelope to set it in.
5415**
5416**	Returns:
5417**		none.
5418*/
5419
5420static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
5421# define QIC_LEN	60
5422# define QIC_LEN_R	62
5423
5424/*
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
5429**		leap seconds.
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.
5432*/
5433
5434# define queuenextid() CurrentPid
5435#define QIC_LEN_SQR	(QIC_LEN * QIC_LEN)
5436
5437void
5438assign_queueid(e)
5439	register ENVELOPE *e;
5440{
5441	pid_t pid = queuenextid();
5442	static unsigned int cX = 0;
5443	static unsigned int random_offset;
5444	struct tm *tm;
5445	char idbuf[MAXQFNAME - 2];
5446	unsigned int seq;
5447
5448	if (e->e_id != NULL)
5449		return;
5450
5451	/* see if we need to get a new base time/pid */
5452	if (cX >= QIC_LEN_SQR || LastQueueTime == 0 || LastQueuePid != pid)
5453	{
5454		time_t then = LastQueueTime;
5455
5456		/* if the first time through, pick a random offset */
5457		if (LastQueueTime == 0)
5458			random_offset = ((unsigned int)get_random())
5459					% QIC_LEN_SQR;
5460
5461		while ((LastQueueTime = curtime()) == then &&
5462		       LastQueuePid == pid)
5463		{
5464			(void) sleep(1);
5465		}
5466		LastQueuePid = queuenextid();
5467		cX = 0;
5468	}
5469
5470	/*
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.
5475	*/
5476
5477	seq = (cX + random_offset) % QIC_LEN_SQR;
5478	++cX;
5479	if (tTd(7, 50))
5480		sm_dprintf("assign_queueid: random_offset=%u (%u)\n",
5481			random_offset, seq);
5482
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);
5496#if 0
5497	/* XXX: inherited from MainEnvelope */
5498	e->e_qgrp = NOQGRP;  /* too early to do anything else */
5499	e->e_qdir = NOQDIR;
5500	e->e_xfqgrp = NOQGRP;
5501#endif /* 0 */
5502
5503	/* New ID means it's not on disk yet */
5504	e->e_qfletter = '\0';
5505
5506	if (tTd(7, 1))
5507		sm_dprintf("assign_queueid: assigned id %s, e=%p\n",
5508			e->e_id, (void *)e);
5509	if (LogLevel > 93)
5510		sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
5511}
5512/*
5513**  SYNC_QUEUE_TIME -- Assure exclusive PID in any given second
5514**
5515**	Make sure one PID can't be used by two processes in any one second.
5516**
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.
5520**
5521**	Parameters:
5522**		none
5523**
5524**	Returns:
5525**		none
5526*/
5527
5528void
5529sync_queue_time()
5530{
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)
5538		(void) sleep(1);
5539#endif /* FAST_PID_RECYCLE */
5540}
5541/*
5542**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
5543**
5544**	Parameters:
5545**		e -- the envelope to unlock.
5546**
5547**	Returns:
5548**		none
5549**
5550**	Side Effects:
5551**		unlocks the queue for `e'.
5552*/
5553
5554void
5555unlockqueue(e)
5556	ENVELOPE *e;
5557{
5558	if (tTd(51, 4))
5559		sm_dprintf("unlockqueue(%s)\n",
5560			e->e_id == NULL ? "NOQUEUE" : e->e_id);
5561
5562
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);
5566	e->e_lockfp = NULL;
5567
5568	/* don't create a queue id if we don't already have one */
5569	if (e->e_id == NULL)
5570		return;
5571
5572	/* remove the transcript */
5573	if (LogLevel > 87)
5574		sm_syslog(LOG_DEBUG, e->e_id, "unlock");
5575	if (!tTd(51, 104))
5576		(void) xunlink(queuename(e, XSCRPT_LETTER));
5577}
5578/*
5579**  SETCTLUSER -- create a controlling address
5580**
5581**	Create a fake "address" given only a local login name; this is
5582**	used as a "controlling user" for future recipient addresses.
5583**
5584**	Parameters:
5585**		user -- the user name of the controlling user.
5586**		qfver -- the version stamp of this queue file.
5587**		e -- envelope
5588**
5589**	Returns:
5590**		An address descriptor for the controlling user,
5591**		using storage allocated from e->e_rpool.
5592**
5593*/
5594
5595static ADDRESS *
5596setctluser(user, qfver, e)
5597	char *user;
5598	int qfver;
5599	ENVELOPE *e;
5600{
5601	register ADDRESS *a;
5602	struct passwd *pw;
5603	char *p;
5604
5605	/*
5606	**  See if this clears our concept of controlling user.
5607	*/
5608
5609	if (user == NULL || *user == '\0')
5610		return NULL;
5611
5612	/*
5613	**  Set up addr fields for controlling user.
5614	*/
5615
5616	a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof(*a));
5617	memset((char *) a, '\0', sizeof(*a));
5618
5619	if (*user == ':')
5620	{
5621		p = &user[1];
5622		a->q_user = sm_rpool_strdup_x(e->e_rpool, p);
5623	}
5624	else
5625	{
5626		p = strtok(user, ":");
5627		a->q_user = sm_rpool_strdup_x(e->e_rpool, user);
5628		if (qfver >= 2)
5629		{
5630			if ((p = strtok(NULL, ":")) != NULL)
5631				a->q_uid = atoi(p);
5632			if ((p = strtok(NULL, ":")) != NULL)
5633				a->q_gid = atoi(p);
5634			if ((p = strtok(NULL, ":")) != NULL)
5635			{
5636				char *o;
5637
5638				a->q_flags |= QGOODUID;
5639
5640				/* if there is another ':': restore it */
5641				if ((o = strtok(NULL, ":")) != NULL && o > p)
5642					o[-1] = ':';
5643			}
5644		}
5645		else if ((pw = sm_getpwnam(user)) != NULL)
5646		{
5647			if (*pw->pw_dir == '\0')
5648				a->q_home = NULL;
5649			else if (strcmp(pw->pw_dir, "/") == 0)
5650				a->q_home = "";
5651			else
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;
5656		}
5657	}
5658
5659	a->q_flags |= QPRIMARY;		/* flag as a "ctladdr" */
5660	a->q_mailer = LocalMailer;
5661	if (p == NULL)
5662		a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user);
5663	else
5664		a->q_paddr = sm_rpool_strdup_x(e->e_rpool, p);
5665	return a;
5666}
5667/*
5668**  LOSEQFILE -- rename queue file with LOSEQF_LETTER & try to let someone know
5669**
5670**	Parameters:
5671**		e -- the envelope (e->e_id will be used).
5672**		why -- reported to whomever can hear.
5673**
5674**	Returns:
5675**		none.
5676*/
5677
5678void
5679loseqfile(e, why)
5680	register ENVELOPE *e;
5681	char *why;
5682{
5683	bool loseit = true;
5684	char *p;
5685	char buf[MAXPATHLEN];
5686
5687	if (e == NULL || e->e_id == NULL)
5688		return;
5689	p = queuename(e, ANYQFL_LETTER);
5690	if (sm_strlcpy(buf, p, sizeof(buf)) >= sizeof(buf))
5691		return;
5692	if (!bitset(EF_INQUEUE, e->e_flags))
5693		queueup(e, false, true);
5694	else if (QueueMode == QM_LOST)
5695		loseit = false;
5696
5697	/* if already lost, no need to re-lose */
5698	if (loseit)
5699	{
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);
5707	}
5708	if (e->e_dfp != NULL)
5709	{
5710		(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
5711		e->e_dfp = NULL;
5712	}
5713	e->e_flags &= ~EF_HAS_DF;
5714}
5715/*
5716**  NAME2QID -- translate a queue group name to a queue group id
5717**
5718**	Parameters:
5719**		queuename -- name of queue group.
5720**
5721**	Returns:
5722**		queue group id if found.
5723**		NOQGRP otherwise.
5724*/
5725
5726int
5727name2qid(queuename)
5728	char *queuename;
5729{
5730	register STAB *s;
5731
5732	s = stab(queuename, ST_QUEUE, ST_FIND);
5733	if (s == NULL)
5734		return NOQGRP;
5735	return s->s_quegrp->qg_index;
5736}
5737/*
5738**  QID_PRINTNAME -- create externally printable version of queue id
5739**
5740**	Parameters:
5741**		e -- the envelope.
5742**
5743**	Returns:
5744**		a printable version
5745*/
5746
5747char *
5748qid_printname(e)
5749	ENVELOPE *e;
5750{
5751	char *id;
5752	static char idbuf[MAXQFNAME + 34];
5753
5754	if (e == NULL)
5755		return "";
5756
5757	if (e->e_id == NULL)
5758		id = "";
5759	else
5760		id = e->e_id;
5761
5762	if (e->e_qdir == NOQDIR)
5763		return id;
5764
5765	(void) sm_snprintf(idbuf, sizeof(idbuf), "%.32s/%s",
5766			   Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_name,
5767			   id);
5768	return idbuf;
5769}
5770/*
5771**  QID_PRINTQUEUE -- create full version of queue directory for data files
5772**
5773**	Parameters:
5774**		qgrp -- index in queue group.
5775**		qdir -- the short version of the queue directory
5776**
5777**	Returns:
5778**		the full pathname to the queue (might point to a static var)
5779*/
5780
5781char *
5782qid_printqueue(qgrp, qdir)
5783	int qgrp;
5784	int qdir;
5785{
5786	char *subdir;
5787	static char dir[MAXPATHLEN];
5788
5789	if (qdir == NOQDIR)
5790		return Queue[qgrp]->qg_qdir;
5791
5792	if (strcmp(Queue[qgrp]->qg_qpaths[qdir].qp_name, ".") == 0)
5793		subdir = NULL;
5794	else
5795		subdir = Queue[qgrp]->qg_qpaths[qdir].qp_name;
5796
5797	(void) sm_strlcpyn(dir, sizeof(dir), 4,
5798			Queue[qgrp]->qg_qdir,
5799			subdir == NULL ? "" : "/",
5800			subdir == NULL ? "" : subdir,
5801			(bitset(QP_SUBDF,
5802				Queue[qgrp]->qg_qpaths[qdir].qp_subdirs)
5803					? "/df" : ""));
5804	return dir;
5805}
5806
5807/*
5808**  PICKQDIR -- Pick a queue directory from a queue group
5809**
5810**	Parameters:
5811**		qg -- queue group
5812**		fsize -- file size in bytes
5813**		e -- envelope, or NULL
5814**
5815**	Result:
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.
5823**
5824**	Side Effects:
5825**		If the request fails and e != NULL then sm_syslog is called.
5826*/
5827
5828int
5829pickqdir(qg, fsize, e)
5830	QUEUEGRP *qg;
5831	long fsize;
5832	ENVELOPE *e;
5833{
5834	int qdir;
5835	int i;
5836	long avail = 0;
5837
5838	/* Pick a random directory, as a starting point. */
5839	if (qg->qg_numqueues <= 1)
5840		qdir = 0;
5841	else
5842		qdir = get_rand_mod(qg->qg_numqueues);
5843
5844#if _FFR_TESTS
5845	if (tTd(4, 101))
5846		return NOQDIR;
5847#endif
5848	if (MinBlocksFree <= 0 && fsize <= 0)
5849		return qdir;
5850
5851	/*
5852	**  Now iterate over the queue directories,
5853	**  looking for a directory with enough space for this message.
5854	*/
5855
5856	i = qdir;
5857	do
5858	{
5859		QPATHS *qp = &qg->qg_qpaths[i];
5860		long needed = 0;
5861		long fsavail = 0;
5862
5863		if (fsize > 0)
5864			needed += fsize / FILE_SYS_BLKSIZE(qp->qp_fsysidx)
5865				  + ((fsize % FILE_SYS_BLKSIZE(qp->qp_fsysidx)
5866				      > 0) ? 1 : 0);
5867		if (MinBlocksFree > 0)
5868			needed += MinBlocksFree;
5869		fsavail = FILE_SYS_AVAIL(qp->qp_fsysidx);
5870#if SM_CONF_SHM
5871		if (fsavail <= 0)
5872		{
5873			long blksize;
5874
5875			/*
5876			**  might be not correctly updated,
5877			**  let's try to get the info directly.
5878			*/
5879
5880			fsavail = freediskspace(FILE_SYS_NAME(qp->qp_fsysidx),
5881						&blksize);
5882			if (fsavail < 0)
5883				fsavail = 0;
5884		}
5885#endif /* SM_CONF_SHM */
5886		if (needed <= fsavail)
5887			return i;
5888		if (avail < fsavail)
5889			avail = fsavail;
5890
5891		if (qg->qg_numqueues > 0)
5892			i = (i + 1) % qg->qg_numqueues;
5893	} while (i != qdir);
5894
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);
5901	return NOQDIR;
5902}
5903/*
5904**  SETNEWQUEUE -- Sets a new queue group and directory
5905**
5906**	Assign a queue group and directory to an envelope and store the
5907**	directory in e->e_qdir.
5908**
5909**	Parameters:
5910**		e -- envelope to assign a queue for.
5911**
5912**	Returns:
5913**		true if successful
5914**		false otherwise
5915**
5916**	Side Effects:
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).
5921*/
5922
5923bool
5924setnewqueue(e)
5925	ENVELOPE *e;
5926{
5927	if (tTd(41, 20))
5928		sm_dprintf("setnewqueue: called\n");
5929
5930	/* not set somewhere else */
5931	if (e->e_qgrp == NOQGRP)
5932	{
5933		ADDRESS *q;
5934
5935		/*
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
5940		**  queue group.
5941		**  Notice: "first" depends on the sorting of sendqueue
5942		**  in recipient().
5943		**  To avoid problems with "bad" recipients look
5944		**  for a valid address first.
5945		*/
5946
5947		q = e->e_sendqueue;
5948		while (q != NULL &&
5949		       (QS_IS_BADADDR(q->q_state) || QS_IS_DEAD(q->q_state)))
5950		{
5951			q = q->q_next;
5952		}
5953		if (q == NULL)
5954			e->e_qgrp = 0;
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;
5960		else
5961			e->e_qgrp = 0;
5962		e->e_dfqgrp = e->e_qgrp;
5963	}
5964
5965	if (ISVALIDQDIR(e->e_qdir) && ISVALIDQDIR(e->e_dfqdir))
5966	{
5967		if (tTd(41, 20))
5968			sm_dprintf("setnewqueue: e_qdir already assigned (%s)\n",
5969				qid_printqueue(e->e_qgrp, e->e_qdir));
5970		return true;
5971	}
5972
5973	filesys_update();
5974	e->e_qdir = pickqdir(Queue[e->e_qgrp], e->e_msgsize, e);
5975	if (e->e_qdir == NOQDIR)
5976	{
5977		e->e_qgrp = NOQGRP;
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;
5981		return false;
5982	}
5983
5984	if (tTd(41, 3))
5985		sm_dprintf("setnewqueue: Assigned queue directory %s\n",
5986			qid_printqueue(e->e_qgrp, e->e_qdir));
5987
5988	if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR)
5989	{
5990		e->e_xfqgrp = e->e_qgrp;
5991		e->e_xfqdir = e->e_qdir;
5992	}
5993	e->e_dfqdir = e->e_qdir;
5994	return true;
5995}
5996/*
5997**  CHKQDIR -- check a queue directory
5998**
5999**	Parameters:
6000**		name -- name of queue directory
6001**		sff -- flags for safefile()
6002**
6003**	Returns:
6004**		is it a queue directory?
6005*/
6006
6007static bool chkqdir __P((char *, long));
6008
6009static bool
6010chkqdir(name, sff)
6011	char *name;
6012	long sff;
6013{
6014	struct stat statb;
6015	int i;
6016
6017	/* skip over . and .. directories */
6018	if (name[0] == '.' &&
6019	    (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
6020		return false;
6021#if HASLSTAT
6022	if (lstat(name, &statb) < 0)
6023#else
6024	if (stat(name, &statb) < 0)
6025#endif
6026	{
6027		if (tTd(41, 2))
6028			sm_dprintf("chkqdir: stat(\"%s\"): %s\n",
6029				   name, sm_errstring(errno));
6030		return false;
6031	}
6032#if HASLSTAT
6033	if (S_ISLNK(statb.st_mode))
6034	{
6035		/*
6036		**  For a symlink we need to make sure the
6037		**  target is a directory
6038		*/
6039
6040		if (stat(name, &statb) < 0)
6041		{
6042			if (tTd(41, 2))
6043				sm_dprintf("chkqdir: stat(\"%s\"): %s\n",
6044					   name, sm_errstring(errno));
6045			return false;
6046		}
6047	}
6048#endif /* HASLSTAT */
6049
6050	if (!S_ISDIR(statb.st_mode))
6051	{
6052		if (tTd(41, 2))
6053			sm_dprintf("chkqdir: \"%s\": Not a directory\n",
6054				name);
6055		return false;
6056	}
6057
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);
6061	if (i != 0)
6062	{
6063		if (tTd(41, 2))
6064			sm_dprintf("chkqdir: \"%s\": Not safe: %s\n",
6065				   name, sm_errstring(i));
6066#if _FFR_CHK_QUEUE
6067		if (LogLevel > 8)
6068			sm_syslog(LOG_WARNING, NOQID,
6069				  "queue directory \"%s\": Not safe: %s",
6070				  name, sm_errstring(i));
6071#endif /* _FFR_CHK_QUEUE */
6072	}
6073	return true;
6074}
6075/*
6076**  MULTIQUEUE_CACHE -- cache a list of paths to queues.
6077**
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).
6082**
6083**	Parameters:
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.
6089#if SM_CONF_SHM
6090**			only used if shared memory is active.
6091#endif * SM_CONF_SHM *
6092**
6093**	Returns:
6094**		new number of queue directories.
6095*/
6096
6097#define INITIAL_SLOTS	20
6098#define ADD_SLOTS	10
6099
6100static int
6101multiqueue_cache(basedir, blen, qg, qn, phash)
6102	char *basedir;
6103	int blen;
6104	QUEUEGRP *qg;
6105	int qn;
6106	unsigned int *phash;
6107{
6108	char *cp;
6109	int i, len;
6110	int slotsleft = 0;
6111	long sff = SFF_ANYFILE;
6112	char qpath[MAXPATHLEN];
6113	char subdir[MAXPATHLEN];
6114	char prefix[MAXPATHLEN];	/* dir relative to basedir */
6115
6116	if (tTd(41, 20))
6117		sm_dprintf("multiqueue_cache: called\n");
6118
6119	/* Initialize to current directory */
6120	prefix[0] = '.';
6121	prefix[1] = '\0';
6122	if (qg->qg_numqueues != 0 && qg->qg_qpaths != NULL)
6123	{
6124		for (i = 0; i < qg->qg_numqueues; i++)
6125		{
6126			if (qg->qg_qpaths[i].qp_name != NULL)
6127				(void) sm_free(qg->qg_qpaths[i].qp_name); /* XXX */
6128		}
6129		(void) sm_free((char *) qg->qg_qpaths); /* XXX */
6130		qg->qg_qpaths = NULL;
6131		qg->qg_numqueues = 0;
6132	}
6133
6134	/* If running as root, allow safedirpath() checks to use privs */
6135	if (RunAsUid == 0)
6136		sff |= SFF_ROOTOK;
6137#if _FFR_CHK_QUEUE
6138	sff |= SFF_SAFEDIRPATH|SFF_NOWWFILES;
6139	if (!UseMSP)
6140		sff |= SFF_NOGWFILES;
6141#endif
6142
6143	if (!SM_IS_DIR_START(qg->qg_qdir))
6144	{
6145		/*
6146		**  XXX we could add basedir, but then we have to realloc()
6147		**  the string... Maybe another time.
6148		*/
6149
6150		syserr("QueuePath %s not absolute", qg->qg_qdir);
6151		ExitStat = EX_CONFIG;
6152		return qn;
6153	}
6154
6155	/* qpath: directory of current workgroup */
6156	len = sm_strlcpy(qpath, qg->qg_qdir, sizeof(qpath));
6157	if (len >= sizeof(qpath))
6158	{
6159		syserr("QueuePath %.256s too long (%d max)",
6160		       qg->qg_qdir, (int) sizeof(qpath));
6161		ExitStat = EX_CONFIG;
6162		return qn;
6163	}
6164
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))
6168	{
6169		syserr("QueuePath %s not subpath of QueueDirectory %s",
6170			qpath, basedir);
6171		ExitStat = EX_CONFIG;
6172		return qn;
6173	}
6174
6175	/* Do we have a nested subdirectory? */
6176	if (blen < len && SM_FIRST_DIR_DELIM(qg->qg_qdir + blen) != NULL)
6177	{
6178
6179		/* Copy subdirectory into prefix for later use */
6180		if (sm_strlcpy(prefix, qg->qg_qdir + blen, sizeof(prefix)) >=
6181		    sizeof(prefix))
6182		{
6183			syserr("QueuePath %.256s too long (%d max)",
6184				qg->qg_qdir, (int) sizeof(qpath));
6185			ExitStat = EX_CONFIG;
6186			return qn;
6187		}
6188		cp = SM_LAST_DIR_DELIM(prefix);
6189		SM_ASSERT(cp != NULL);
6190		*cp = '\0';	/* cut off trailing / */
6191	}
6192
6193	/* This is guaranteed by the basedir check above */
6194	SM_ASSERT(len >= blen - 1);
6195	cp = &qpath[len - 1];
6196	if (*cp == '*')
6197	{
6198		register DIR *dp;
6199		register struct dirent *d;
6200		int off;
6201		char *delim;
6202		char relpath[MAXPATHLEN];
6203
6204		*cp = '\0';	/* Overwrite wildcard */
6205		if ((cp = SM_LAST_DIR_DELIM(qpath)) == NULL)
6206		{
6207			syserr("QueueDirectory: can not wildcard relative path");
6208			if (tTd(41, 2))
6209				sm_dprintf("multiqueue_cache: \"%s*\": Can not wildcard relative path.\n",
6210					qpath);
6211			ExitStat = EX_CONFIG;
6212			return qn;
6213		}
6214		if (cp == qpath)
6215		{
6216			/*
6217			**  Special case of top level wildcard, like /foo*
6218			**	Change to //foo*
6219			*/
6220
6221			(void) sm_strlcpy(qpath + 1, qpath, sizeof(qpath) - 1);
6222			++cp;
6223		}
6224		delim = cp;
6225		*(cp++) = '\0';		/* Replace / with \0 */
6226		len = strlen(cp);	/* Last component of queue directory */
6227
6228		/*
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().
6232		*/
6233
6234		off = sm_strlcpyn(relpath, sizeof(relpath), 2, prefix, "/");
6235		SM_ASSERT(off < sizeof(relpath));
6236
6237		if (tTd(41, 2))
6238			sm_dprintf("multiqueue_cache: prefix=\"%s%s\"\n",
6239				   relpath, cp);
6240
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 / */
6245
6246		/*
6247		**  XXX Should probably wrap this whole loop in a timeout
6248		**  in case some wag decides to NFS mount the queues.
6249		*/
6250
6251		/* Test path to get warning messages. */
6252		if (qn == 0)
6253		{
6254			/*  XXX qg_runasuid and qg_runasgid for specials? */
6255			i = safedirpath(basedir, RunAsUid, RunAsGid, NULL,
6256					sff, 0, 0);
6257			if (i != 0 && tTd(41, 2))
6258				sm_dprintf("multiqueue_cache: \"%s\": Not safe: %s\n",
6259					   basedir, sm_errstring(i));
6260		}
6261
6262		if ((dp = opendir(prefix)) == NULL)
6263		{
6264			syserr("can not opendir(%s/%s)", qg->qg_qdir, prefix);
6265			if (tTd(41, 2))
6266				sm_dprintf("multiqueue_cache: opendir(\"%s/%s\"): %s\n",
6267					   qg->qg_qdir, prefix,
6268					   sm_errstring(errno));
6269			ExitStat = EX_CONFIG;
6270			return qn;
6271		}
6272		while ((d = readdir(dp)) != NULL)
6273		{
6274			/* Skip . and .. directories */
6275			if (strcmp(d->d_name, ".") == 0 ||
6276			    strcmp(d->d_name, "..") == 0)
6277				continue;
6278
6279			i = strlen(d->d_name);
6280			if (i < len || strncmp(d->d_name, cp, len) != 0)
6281			{
6282				if (tTd(41, 5))
6283					sm_dprintf("multiqueue_cache: \"%s\", skipped\n",
6284						d->d_name);
6285				continue;
6286			}
6287
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 */
6292
6293			if (!chkqdir(relpath, sff))
6294				continue;
6295
6296			if (qg->qg_qpaths == NULL)
6297			{
6298				slotsleft = INITIAL_SLOTS;
6299				qg->qg_qpaths = (QPATHS *)xalloc((sizeof(*qg->qg_qpaths)) *
6300								slotsleft);
6301				qg->qg_numqueues = 0;
6302			}
6303			else if (slotsleft < 1)
6304			{
6305				qg->qg_qpaths = (QPATHS *)sm_realloc((char *)qg->qg_qpaths,
6306							  (sizeof(*qg->qg_qpaths)) *
6307							  (qg->qg_numqueues +
6308							   ADD_SLOTS));
6309				if (qg->qg_qpaths == NULL)
6310				{
6311					(void) closedir(dp);
6312					return qn;
6313				}
6314				slotsleft += ADD_SLOTS;
6315			}
6316
6317			/* check subdirs */
6318			qg->qg_qpaths[qg->qg_numqueues].qp_subdirs = QP_NOSUB;
6319
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;	\
6324	else
6325
6326
6327			CHKRSUBDIR("qf", QP_SUBQF);
6328			CHKRSUBDIR("df", QP_SUBDF);
6329			CHKRSUBDIR("xf", QP_SUBXF);
6330
6331			/* assert(strlen(d->d_name) < MAXPATHLEN - 14) */
6332			/* maybe even - 17 (subdirs) */
6333
6334			if (prefix[0] != '.')
6335				qg->qg_qpaths[qg->qg_numqueues].qp_name =
6336					newstr(relpath);
6337			else
6338				qg->qg_qpaths[qg->qg_numqueues].qp_name =
6339					newstr(d->d_name);
6340
6341			if (tTd(41, 2))
6342				sm_dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n",
6343					qg->qg_numqueues, relpath,
6344					qg->qg_qpaths[qg->qg_numqueues].qp_subdirs);
6345#if SM_CONF_SHM
6346			qg->qg_qpaths[qg->qg_numqueues].qp_idx = qn;
6347			*phash = hash_q(relpath, *phash);
6348#endif
6349			qg->qg_numqueues++;
6350			++qn;
6351			slotsleft--;
6352		}
6353		(void) closedir(dp);
6354
6355		/* undo damage */
6356		*delim = '/';
6357	}
6358	if (qg->qg_numqueues == 0)
6359	{
6360		qg->qg_qpaths = (QPATHS *) xalloc(sizeof(*qg->qg_qpaths));
6361
6362		/* test path to get warning messages */
6363		i = safedirpath(qpath, RunAsUid, RunAsGid, NULL, sff, 0, 0);
6364		if (i == ENOENT)
6365		{
6366			syserr("can not opendir(%s)", qpath);
6367			if (tTd(41, 2))
6368				sm_dprintf("multiqueue_cache: opendir(\"%s\"): %s\n",
6369					   qpath, sm_errstring(i));
6370			ExitStat = EX_CONFIG;
6371			return qn;
6372		}
6373
6374		qg->qg_qpaths[0].qp_subdirs = QP_NOSUB;
6375		qg->qg_numqueues = 1;
6376
6377		/* check subdirs */
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;	\
6382	else
6383
6384		CHKSUBDIR("qf", QP_SUBQF);
6385		CHKSUBDIR("df", QP_SUBDF);
6386		CHKSUBDIR("xf", QP_SUBXF);
6387
6388		if (qg->qg_qdir[blen - 1] != '\0' &&
6389		    qg->qg_qdir[blen] != '\0')
6390		{
6391			/*
6392			**  Copy the last component into qpaths and
6393			**  cut off qdir
6394			*/
6395
6396			qg->qg_qpaths[0].qp_name = newstr(qg->qg_qdir + blen);
6397			qg->qg_qdir[blen - 1] = '\0';
6398		}
6399		else
6400			qg->qg_qpaths[0].qp_name = newstr(".");
6401
6402#if SM_CONF_SHM
6403		qg->qg_qpaths[0].qp_idx = qn;
6404		*phash = hash_q(qg->qg_qpaths[0].qp_name, *phash);
6405#endif
6406		++qn;
6407	}
6408	return qn;
6409}
6410
6411/*
6412**  FILESYS_FIND -- find entry in FileSys table, or add new one
6413**
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.
6419**
6420**	Parameters:
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.
6424**
6425**	Returns:
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
6431*/
6432
6433static short filesys_find __P((const char *, const char *, bool));
6434
6435#define FSF_NOT_FOUND	(-1)
6436#define FSF_STAT_FAIL	(-2)
6437#define FSF_TOO_MANY	(-3)
6438
6439static short
6440filesys_find(name, path, add)
6441	const char *name;
6442	const char *path;
6443	bool add;
6444{
6445	struct stat st;
6446	short i;
6447
6448	if (stat(path, &st) < 0)
6449	{
6450		syserr("cannot stat queue directory %s", path);
6451		return FSF_STAT_FAIL;
6452	}
6453	for (i = 0; i < NumFileSys; ++i)
6454	{
6455		if (FILE_SYS_DEV(i) == st.st_dev)
6456		{
6457			/*
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.
6463			*/
6464
6465			if (NULL == FILE_SYS_NAME(i))
6466				FILE_SYS_NAME(i) = name;
6467			return i;
6468		}
6469	}
6470	if (i >= MAXFILESYS)
6471	{
6472		syserr("too many queue file systems (%d max)", MAXFILESYS);
6473		return FSF_TOO_MANY;
6474	}
6475	if (!add)
6476		return FSF_NOT_FOUND;
6477
6478	++NumFileSys;
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 */
6483	return i;
6484}
6485
6486/*
6487**  FILESYS_SETUP -- set up mapping from queue directories to file systems
6488**
6489**	This data structure is used to efficiently check the amount of
6490**	free space available in a set of queue directories.
6491**
6492**	Parameters:
6493**		add -- initialize structure if necessary.
6494**
6495**	Returns:
6496**		0: success
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())
6501*/
6502
6503static int filesys_setup __P((bool));
6504
6505static int
6506filesys_setup(add)
6507	bool add;
6508{
6509	int i, j;
6510	short fs;
6511	int ret;
6512
6513	ret = 0;
6514	for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
6515	{
6516		for (j = 0; j < Queue[i]->qg_numqueues; ++j)
6517		{
6518			QPATHS *qp = &Queue[i]->qg_qpaths[j];
6519			char qddf[MAXPATHLEN];
6520
6521			(void) sm_strlcpyn(qddf, sizeof(qddf), 2, qp->qp_name,
6522					(bitset(QP_SUBDF, qp->qp_subdirs)
6523						? "/df" : ""));
6524			fs = filesys_find(qp->qp_name, qddf, add);
6525			if (fs >= 0)
6526				qp->qp_fsysidx = fs;
6527			else
6528				qp->qp_fsysidx = 0;
6529			if (fs < ret)
6530				ret = fs;
6531		}
6532	}
6533	return ret;
6534}
6535
6536/*
6537**  FILESYS_UPDATE -- update amount of free space on all file systems
6538**
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.
6542**
6543**	Parameters:
6544**		none.
6545**
6546**	Returns:
6547**		none.
6548**
6549**	Side Effects:
6550**		Updates FileSys table.
6551*/
6552
6553void
6554filesys_update()
6555{
6556	int i;
6557	long avail, blksize;
6558	time_t now;
6559	static time_t nextupdate = 0;
6560
6561#if SM_CONF_SHM
6562	/*
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.
6566	*/
6567
6568	if (ShmId != SM_SHM_NO_ID && DaemonPid != CurrentPid)
6569		return;
6570#endif /* SM_CONF_SHM */
6571	now = curtime();
6572	if (now < nextupdate)
6573		return;
6574	nextupdate = now + FILESYS_UPDATE_INTERVAL;
6575	for (i = 0; i < NumFileSys; ++i)
6576	{
6577		FILESYS *fs = &FILE_SYS(i);
6578
6579		avail = freediskspace(FILE_SYS_NAME(i), &blksize);
6580		if (avail < 0 || blksize <= 0)
6581		{
6582			if (LogLevel > 5)
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);
6587			fs->fs_avail = 0;
6588			fs->fs_blksize = 1024; /* avoid divide by zero */
6589			nextupdate = now + 2; /* let's do this soon again */
6590		}
6591		else
6592		{
6593			fs->fs_avail = avail;
6594			fs->fs_blksize = blksize;
6595		}
6596	}
6597}
6598
6599#if _FFR_ANY_FREE_FS
6600/*
6601**  FILESYS_FREE -- check whether there is at least one fs with enough space.
6602**
6603**	Parameters:
6604**		fsize -- file size in bytes
6605**
6606**	Returns:
6607**		true iff there is one fs with more than fsize bytes free.
6608*/
6609
6610bool
6611filesys_free(fsize)
6612	long fsize;
6613{
6614	int i;
6615
6616	if (fsize <= 0)
6617		return true;
6618	for (i = 0; i < NumFileSys; ++i)
6619	{
6620		long needed = 0;
6621
6622		if (FILE_SYS_AVAIL(i) < 0 || FILE_SYS_BLKSIZE(i) <= 0)
6623			continue;
6624		needed += fsize / FILE_SYS_BLKSIZE(i)
6625			  + ((fsize % FILE_SYS_BLKSIZE(i)
6626			      > 0) ? 1 : 0)
6627			  + MinBlocksFree;
6628		if (needed <= FILE_SYS_AVAIL(i))
6629			return true;
6630	}
6631	return false;
6632}
6633#endif /* _FFR_ANY_FREE_FS */
6634
6635/*
6636**  DISK_STATUS -- show amount of free space in queue directories
6637**
6638**	Parameters:
6639**		out -- output file pointer.
6640**		prefix -- string to output in front of each line.
6641**
6642**	Returns:
6643**		none.
6644*/
6645
6646void
6647disk_status(out, prefix)
6648	SM_FILE_T *out;
6649	char *prefix;
6650{
6651	int i;
6652	long avail, blksize;
6653	long free;
6654
6655	for (i = 0; i < NumFileSys; ++i)
6656	{
6657		avail = freediskspace(FILE_SYS_NAME(i), &blksize);
6658		if (avail >= 0 && blksize > 0)
6659		{
6660			free = (long)((double) avail *
6661				((double) blksize / 1024));
6662		}
6663		else
6664			free = -1;
6665		(void) sm_io_fprintf(out, SM_TIME_DEFAULT,
6666				"%s%d/%s/%ld\r\n",
6667				prefix, i,
6668				FILE_SYS_NAME(i),
6669					free);
6670	}
6671}
6672
6673#if SM_CONF_SHM
6674
6675/*
6676**  INIT_SEM -- initialize semaphore system
6677**
6678**	Parameters:
6679**		owner -- is this the owner of semaphores?
6680**
6681**	Returns:
6682**		none.
6683*/
6684
6685#if _FFR_USE_SEM_LOCKING && SM_CONF_SEM
6686static int SemId = -1;		/* Semaphore Id */
6687int SemKey = SM_SEM_KEY;
6688#  define SEM_LOCK(r)	\
6689	do	\
6690	{	\
6691		if (SemId >= 0)	\
6692			r = sm_sem_acq(SemId, 0, 1);	\
6693	} while (0)
6694# define SEM_UNLOCK(r)	\
6695	do	\
6696	{	\
6697		if (SemId >= 0 && r >= 0)	\
6698			r = sm_sem_rel(SemId, 0, 1);	\
6699	} while (0)
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 */
6704
6705static void init_sem __P((bool));
6706
6707static void
6708init_sem(owner)
6709	bool owner;
6710{
6711#if _FFR_USE_SEM_LOCKING
6712#if SM_CONF_SEM
6713	SemId = sm_sem_start(SemKey, 1, 0, owner);
6714	if (SemId < 0)
6715	{
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));
6719		return;
6720	}
6721	if (owner && RunAsUid != 0)
6722	{
6723		int r;
6724
6725		r = sm_semsetowner(SemId, RunAsUid, RunAsGid, 0660);
6726		if (r != 0)
6727			sm_syslog(LOG_ERR, NOQID,
6728				"key=%ld, sm_semsetowner=%d, RunAsUid=%ld, RunAsGid=%ld",
6729				(long) SemKey, r, (long) RunAsUid, (long) RunAsGid);
6730	}
6731#endif /* SM_CONF_SEM */
6732#endif /* _FFR_USE_SEM_LOCKING */
6733	return;
6734}
6735
6736/*
6737**  STOP_SEM -- stop semaphore system
6738**
6739**	Parameters:
6740**		owner -- is this the owner of semaphores?
6741**
6742**	Returns:
6743**		none.
6744*/
6745
6746static void stop_sem __P((bool));
6747
6748static void
6749stop_sem(owner)
6750	bool owner;
6751{
6752#if _FFR_USE_SEM_LOCKING
6753#if SM_CONF_SEM
6754	if (owner && SemId >= 0)
6755		sm_sem_stop(SemId);
6756#endif
6757#endif /* _FFR_USE_SEM_LOCKING */
6758	return;
6759}
6760
6761# if _FFR_OCC
6762/*
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)
6767*/
6768
6769/*
6770**  OCC_EXCEEDED -- is an outgoing connection limit exceeded?
6771**
6772**	Parameters:
6773**		e -- envelope
6774**		mci -- mail connection information
6775**		host -- name of host
6776**		addr -- address of host
6777**
6778**	Returns:
6779**		true iff an outgoing connection limit is exceeded
6780*/
6781
6782bool
6783occ_exceeded(e, mci, host, addr)
6784	ENVELOPE *e;
6785	MCI *mci;
6786	const char *host;
6787	SOCKADDR *addr;
6788{
6789	time_t now;
6790	bool exc;
6791	int r, ratelimit, conclimit;
6792	char *limit; /* allocated from e_rpool by rscheck(), no need to free() */
6793
6794/* if necessary, some error checking for a number could be done here */
6795#define STR2INT(r, limit, val)	\
6796	do \
6797	{	\
6798		if ((r) == EX_OK && (limit) != NULL)	\
6799			(val) = atoi((limit));	\
6800	} while (0);
6801
6802	if (occ == NULL || e == NULL)
6803		return false;
6804	ratelimit = conclimit = 0;
6805	limit = NULL;
6806	r = rscheck("oc_rate", host, anynet_ntoa(addr), e, RSF_ADDR,
6807		12, NULL, NOQID, NULL, &limit);
6808	STR2INT(r, limit, ratelimit);
6809	limit = NULL;
6810	r = rscheck("oc_conc", host, anynet_ntoa(addr), e, RSF_ADDR,
6811		12, NULL, NOQID, NULL, &limit);
6812	STR2INT(r, limit, conclimit);
6813	now = curtime();
6814
6815	/* lock occ: lock entire shared memory segment */
6816	SEM_LOCK(r);
6817	exc = (bool) conn_limits(e, now, addr, SM_CLFL_EXC, occ, ratelimit,
6818				conclimit);
6819	SEM_UNLOCK(r);
6820	if (!exc && mci != NULL)
6821		mci->mci_flags |= MCIF_OCC_INCR;
6822	return exc;
6823}
6824
6825/*
6826**  OCC_CLOSE -- "close" an outgoing connection: up connection status
6827**
6828**	Parameters:
6829**		e -- envelope
6830**		mci -- mail connection information
6831**		host -- name of host
6832**		addr -- address of host
6833**
6834**	Returns:
6835**		true after successful update
6836*/
6837
6838bool
6839occ_close(e, mci, host, addr)
6840	ENVELOPE *e;
6841	MCI *mci;
6842	const char *host;
6843	SOCKADDR *addr;
6844{
6845	time_t now;
6846#  if _FFR_USE_SEM_LOCKING && SM_CONF_SEM
6847	int r;
6848#  endif
6849
6850	if (occ == NULL || e == NULL)
6851		return false;
6852	if (mci == NULL || mci->mci_state == MCIS_CLOSED ||
6853	    bitset(MCIF_CACHED, mci->mci_flags) ||
6854	    !bitset(MCIF_OCC_INCR, mci->mci_flags))
6855		return false;
6856	mci->mci_flags &= ~MCIF_OCC_INCR;
6857
6858	now = curtime();
6859
6860	/* lock occ: lock entire shared memory segment */
6861	SEM_LOCK(r);
6862	(void) conn_limits(e, now, addr, SM_CLFL_EXC, occ, -1, -1);
6863	SEM_UNLOCK(r);
6864	return true;
6865}
6866# endif /* _FFR_OCC */
6867
6868/*
6869**  UPD_QS -- update information about queue when adding/deleting an entry
6870**
6871**	Parameters:
6872**		e -- envelope.
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)
6877**
6878**	Returns:
6879**		none.
6880**
6881**	Side Effects:
6882**		Modifies available space in filesystem.
6883**		Changes number of entries in queue directory.
6884*/
6885
6886void
6887upd_qs(e, count, space, where)
6888	ENVELOPE *e;
6889	int count;
6890	int space;
6891	char *where;
6892{
6893	short fidx;
6894	int idx;
6895# if _FFR_USE_SEM_LOCKING
6896	int r;
6897# endif
6898	long s;
6899
6900	if (ShmId == SM_SHM_NO_ID || e == NULL)
6901		return;
6902	if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR)
6903		return;
6904	idx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_idx;
6905	if (tTd(73,2))
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));
6908
6909	/* XXX in theory this needs to be protected with a mutex */
6910	if (QSHM_ENTRIES(idx) >= 0 && count != 0)
6911	{
6912		SEM_LOCK(r);
6913		QSHM_ENTRIES(idx) += count;
6914		SEM_UNLOCK(r);
6915	}
6916
6917	fidx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_fsysidx;
6918	if (fidx < 0)
6919		return;
6920
6921	/* update available space also?  (might be loseqfile) */
6922	if (space == 0)
6923		return;
6924
6925	/* convert size to blocks; this causes rounding errors */
6926	s = e->e_msgsize / FILE_SYS_BLKSIZE(fidx);
6927	if (s == 0)
6928		return;
6929
6930	/* XXX in theory this needs to be protected with a mutex */
6931	if (space > 0)
6932		FILE_SYS_AVAIL(fidx) += s;
6933	else
6934		FILE_SYS_AVAIL(fidx) -= s;
6935
6936}
6937
6938static bool write_key_file __P((char *, long));
6939static long read_key_file __P((char *, long));
6940
6941/*
6942**  WRITE_KEY_FILE -- record some key into a file.
6943**
6944**	Parameters:
6945**		keypath -- file name.
6946**		key -- key to write.
6947**
6948**	Returns:
6949**		true iff file could be written.
6950**
6951**	Side Effects:
6952**		writes file.
6953*/
6954
6955static bool
6956write_key_file(keypath, key)
6957	char *keypath;
6958	long key;
6959{
6960	bool ok;
6961	long sff;
6962	SM_FILE_T *keyf;
6963
6964	ok = false;
6965	if (keypath == NULL || *keypath == '\0')
6966		return ok;
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);
6971	if (keyf == NULL)
6972	{
6973		sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s",
6974			  keypath, sm_errstring(errno));
6975	}
6976	else
6977	{
6978		if (geteuid() == 0 && RunAsUid != 0)
6979		{
6980#  if HASFCHOWN
6981			int fd;
6982
6983			fd = keyf->f_file;
6984			if (fd >= 0 && fchown(fd, RunAsUid, -1) < 0)
6985			{
6986				int err = errno;
6987
6988				sm_syslog(LOG_ALERT, NOQID,
6989					  "ownership change on %s to %ld failed: %s",
6990					  keypath, (long) RunAsUid, sm_errstring(err));
6991			}
6992#  endif /* HASFCHOWN */
6993		}
6994		ok = sm_io_fprintf(keyf, SM_TIME_DEFAULT, "%ld\n", key) !=
6995		     SM_IO_EOF;
6996		ok = (sm_io_close(keyf, SM_TIME_DEFAULT) != SM_IO_EOF) && ok;
6997	}
6998	return ok;
6999}
7000
7001/*
7002**  READ_KEY_FILE -- read a key from a file.
7003**
7004**	Parameters:
7005**		keypath -- file name.
7006**		key -- default key.
7007**
7008**	Returns:
7009**		key.
7010*/
7011
7012static long
7013read_key_file(keypath, key)
7014	char *keypath;
7015	long key;
7016{
7017	int r;
7018	long sff, n;
7019	SM_FILE_T *keyf;
7020
7021	if (keypath == NULL || *keypath == '\0')
7022		return key;
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);
7027	if (keyf == NULL)
7028	{
7029		sm_syslog(LOG_ERR, NOQID, "unable to read %s: %s",
7030			  keypath, sm_errstring(errno));
7031	}
7032	else
7033	{
7034		r = sm_io_fscanf(keyf, SM_TIME_DEFAULT, "%ld", &n);
7035		if (r == 1)
7036			key = n;
7037		(void) sm_io_close(keyf, SM_TIME_DEFAULT);
7038	}
7039	return key;
7040}
7041
7042/*
7043**  INIT_SHM -- initialize shared memory structure
7044**
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.
7050**
7051**	Parameters:
7052**		qn -- number of queue directories.
7053**		owner -- owner of shared memory.
7054**		hash -- identifies data that is stored in shared memory.
7055**
7056**	Returns:
7057**		none.
7058*/
7059
7060static void init_shm __P((int, bool, unsigned int));
7061
7062static void
7063init_shm(qn, owner, hash)
7064	int qn;
7065	bool owner;
7066	unsigned int hash;
7067{
7068	int i;
7069	int count;
7070	int save_errno;
7071	bool keyselect;
7072
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
7078
7079	/* This allows us to disable shared memory at runtime. */
7080	if (ShmKey == 0)
7081		return;
7082
7083	count = 0;
7084	shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T);
7085	keyselect = ShmKey == SEL_SHM_KEY;
7086	if (keyselect)
7087	{
7088		if (owner)
7089			ShmKey = FIRST_SHM_KEY;
7090		else
7091		{
7092			errno = 0;
7093			ShmKey = read_key_file(ShmKeyFile, ShmKey);
7094			keyselect = false;
7095			if (ShmKey == SEL_SHM_KEY)
7096			{
7097				save_errno = (errno != 0) ? errno : EINVAL;
7098				goto error;
7099			}
7100		}
7101	}
7102	for (;;)
7103	{
7104		/* allow read/write access for group? */
7105		Pshm = sm_shmstart(ShmKey, shms,
7106				SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3),
7107				&ShmId, owner);
7108		save_errno = errno;
7109		if (Pshm != NULL || !sm_file_exists(save_errno))
7110			break;
7111		if (++count >= 3)
7112		{
7113			if (keyselect)
7114			{
7115				++ShmKey;
7116
7117				/* back where we started? */
7118				if (ShmKey == SEL_SHM_KEY)
7119					break;
7120				continue;
7121			}
7122			break;
7123		}
7124
7125		/* only sleep if we are at the first key */
7126		if (!keyselect || ShmKey == SEL_SHM_KEY)
7127			sleep(count);
7128	}
7129	if (Pshm != NULL)
7130	{
7131		int *p;
7132
7133		if (keyselect)
7134			(void) write_key_file(ShmKeyFile, (long) ShmKey);
7135		if (owner && RunAsUid != 0)
7136		{
7137			i = sm_shmsetowner(ShmId, RunAsUid, RunAsGid, 0660);
7138			if (i != 0)
7139				sm_syslog(LOG_ERR, NOQID,
7140					"key=%ld, sm_shmsetowner=%d, RunAsUid=%ld, RunAsGid=%ld",
7141					(long) ShmKey, i, (long) RunAsUid, (long) RunAsGid);
7142		}
7143		p = (int *) Pshm;
7144		if (owner)
7145		{
7146			*p = (int) shms;
7147			*((pid_t *) SHM_OFF_PID(Pshm)) = CurrentPid;
7148			p = (int *) SHM_OFF_TAG(Pshm);
7149			*p = hash;
7150		}
7151		else
7152		{
7153			if (*p != (int) shms)
7154			{
7155				save_errno = EINVAL;
7156				cleanup_shm(false);
7157				goto error;
7158			}
7159			p = (int *) SHM_OFF_TAG(Pshm);
7160			if (*p != (int) hash)
7161			{
7162				save_errno = EINVAL;
7163				cleanup_shm(false);
7164				goto error;
7165			}
7166
7167			/*
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.
7173			*/
7174		}
7175
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);
7180		*PRSATmpCnt = 0;
7181# if _FFR_OCC
7182		occ = (CHash_T *) OFF_OCC_SHM(Pshm);
7183# endif
7184		if (owner)
7185		{
7186			/* initialize values in shared memory */
7187			NumFileSys = 0;
7188			for (i = 0; i < qn; i++)
7189				QShm[i].qs_entries = -1;
7190# if _FFR_OCC
7191			memset(occ, 0, OCC_SIZE);
7192# endif
7193		}
7194		init_sem(owner);
7195		return;
7196	}
7197  error:
7198	if (LogLevel > (owner ? 8 : 11))
7199	{
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));
7204	}
7205}
7206#endif /* SM_CONF_SHM */
7207
7208
7209/*
7210**  SETUP_QUEUES -- set up all queue groups
7211**
7212**	Parameters:
7213**		owner -- owner of shared memory?
7214**
7215**	Returns:
7216**		none.
7217**
7218#if SM_CONF_SHM
7219**	Side Effects:
7220**		attaches shared memory.
7221#endif * SM_CONF_SHM *
7222*/
7223
7224void
7225setup_queues(owner)
7226	bool owner;
7227{
7228	int i, qn, len;
7229	unsigned int hashval;
7230	time_t now;
7231	char basedir[MAXPATHLEN];
7232	struct stat st;
7233
7234	/*
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 /
7239	*/
7240
7241	hashval = 0;
7242	errno = 0;
7243	len = sm_strlcpy(basedir, QueueDir, sizeof(basedir));
7244
7245	/* Provide space for trailing '/' */
7246	if (len >= sizeof(basedir) - 1)
7247	{
7248		syserr("QueueDirectory: path too long: %d,  max %d",
7249			len, (int) sizeof(basedir) - 1);
7250		ExitStat = EX_CONFIG;
7251		return;
7252	}
7253	SM_ASSERT(len > 0);
7254	if (basedir[len - 1] == '*')
7255	{
7256		char *cp;
7257
7258		cp = SM_LAST_DIR_DELIM(basedir);
7259		if (cp == NULL)
7260		{
7261			syserr("QueueDirectory: can not wildcard relative path \"%s\"",
7262				QueueDir);
7263			if (tTd(41, 2))
7264				sm_dprintf("setup_queues: \"%s\": Can not wildcard relative path.\n",
7265					QueueDir);
7266			ExitStat = EX_CONFIG;
7267			return;
7268		}
7269
7270		/* cut off wildcard pattern */
7271		*++cp = '\0';
7272		len = cp - basedir;
7273	}
7274	else if (!SM_IS_DIR_DELIM(basedir[len - 1]))
7275	{
7276		/* append trailing slash since it is a directory */
7277		basedir[len] = '/';
7278		basedir[++len] = '\0';
7279	}
7280
7281	/* len counts up to the last directory delimiter */
7282	SM_ASSERT(basedir[len - 1] == '/');
7283
7284	if (chdir(basedir) < 0)
7285	{
7286		int save_errno = errno;
7287
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");
7292		if (tTd(41, 2))
7293			sm_dprintf("setup_queues: \"%s\": %s\n",
7294				   basedir, sm_errstring(errno));
7295		ExitStat = EX_CONFIG;
7296		return;
7297	}
7298#if SM_CONF_SHM
7299	hashval = hash_q(basedir, hashval);
7300#endif
7301
7302	/* initialize for queue runs */
7303	DoQueueRun = false;
7304	now = curtime();
7305	for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
7306		Queue[i]->qg_nextrun = now;
7307
7308
7309	if (UseMSP && OpMode != MD_TEST)
7310	{
7311		long sff = SFF_CREAT;
7312
7313		if (stat(".", &st) < 0)
7314		{
7315			syserr("can not stat(%s)", basedir);
7316			if (tTd(41, 2))
7317				sm_dprintf("setup_queues: \"%s\": %s\n",
7318					   basedir, sm_errstring(errno));
7319			ExitStat = EX_CONFIG;
7320			return;
7321		}
7322		if (RunAsUid == 0)
7323			sff |= SFF_ROOTOK;
7324
7325		/*
7326		**  Check queue directory permissions.
7327		**	Can we write to a group writable queue directory?
7328		*/
7329
7330		if (bitset(S_IWGRP, QueueFileMode) &&
7331		    bitset(S_IWGRP, st.st_mode) &&
7332		    safefile(" ", RunAsUid, RunAsGid, RunAsUserName, sff,
7333			     QueueFileMode, NULL) != 0)
7334		{
7335			syserr("can not write to queue directory %s (RunAsGid=%ld, required=%ld)",
7336				basedir, (long) RunAsGid, (long) st.st_gid);
7337		}
7338		if (bitset(S_IWOTH|S_IXOTH, st.st_mode))
7339		{
7340#if _FFR_MSP_PARANOIA
7341			syserr("dangerous permissions=%o on queue directory %s",
7342				(unsigned int) st.st_mode, basedir);
7343#else
7344			if (LogLevel > 0)
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 */
7349		}
7350#if _FFR_MSP_PARANOIA
7351		if (NumQueue > 1)
7352			syserr("can not use multiple queues for MSP");
7353#endif
7354	}
7355
7356	/* initial number of queue directories */
7357	qn = 0;
7358	for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
7359		qn = multiqueue_cache(basedir, len, Queue[i], qn, &hashval);
7360
7361#if SM_CONF_SHM
7362	init_shm(qn, owner, hashval);
7363	i = filesys_setup(owner || ShmId == SM_SHM_NO_ID);
7364	if (i == FSF_NOT_FOUND)
7365	{
7366		/*
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.
7370		*/
7371
7372		SM_ASSERT(!owner);
7373		cleanup_shm(false);	/* release shared memory */
7374		i = filesys_setup(false);
7375		if (i < 0)
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");
7380	}
7381#else /* SM_CONF_SHM */
7382	i = filesys_setup(true);
7383#endif /* SM_CONF_SHM */
7384	if (i < 0)
7385		ExitStat = EX_CONFIG;
7386}
7387
7388#if SM_CONF_SHM
7389/*
7390**  CLEANUP_SHM -- do some cleanup work for shared memory etc
7391**
7392**	Parameters:
7393**		owner -- owner of shared memory?
7394**
7395**	Returns:
7396**		none.
7397**
7398**	Side Effects:
7399**		detaches shared memory.
7400*/
7401
7402void
7403cleanup_shm(owner)
7404	bool owner;
7405{
7406	if (ShmId != SM_SHM_NO_ID)
7407	{
7408		if (sm_shmstop(Pshm, ShmId, owner) < 0 && LogLevel > 8)
7409			sm_syslog(LOG_INFO, NOQID, "sm_shmstop failed=%s",
7410				  sm_errstring(errno));
7411		Pshm = NULL;
7412		ShmId = SM_SHM_NO_ID;
7413	}
7414	stop_sem(owner);
7415}
7416#endif /* SM_CONF_SHM */
7417
7418/*
7419**  CLEANUP_QUEUES -- do some cleanup work for queues
7420**
7421**	Parameters:
7422**		none.
7423**
7424**	Returns:
7425**		none.
7426**
7427*/
7428
7429void
7430cleanup_queues()
7431{
7432	sync_queue_time();
7433}
7434/*
7435**  SET_DEF_QUEUEVAL -- set default values for a queue group.
7436**
7437**	Parameters:
7438**		qg -- queue group
7439**		all -- set all values (true for default group)?
7440**
7441**	Returns:
7442**		none.
7443**
7444**	Side Effects:
7445**		sets default values for the queue group.
7446*/
7447
7448void
7449set_def_queueval(qg, all)
7450	QUEUEGRP *qg;
7451	bool all;
7452{
7453	if (bitnset(QD_DEFINED, qg->qg_flags))
7454		return;
7455	if (all)
7456		qg->qg_qdir = QueueDir;
7457#if _FFR_QUEUE_GROUP_SORTORDER
7458	qg->qg_sortorder = QueueSortOrder;
7459#endif
7460	qg->qg_maxqrun = all ? MaxRunnersPerQueue : -1;
7461	qg->qg_nice = NiceQueueRun;
7462}
7463/*
7464**  MAKEQUEUE -- define a new queue.
7465**
7466**	Parameters:
7467**		line -- description of queue.  This is in labeled fields.
7468**			The fields are:
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
7480**
7481**	Returns:
7482**		none.
7483**
7484**	Side Effects:
7485**		enters the queue into the queue table.
7486*/
7487
7488void
7489makequeue(line, qdef)
7490	char *line;
7491	bool qdef;
7492{
7493	register char *p;
7494	register QUEUEGRP *qg;
7495	register STAB *s;
7496	int i;
7497	char fcode;
7498
7499	/* allocate a queue and set up defaults */
7500	qg = (QUEUEGRP *) xalloc(sizeof(*qg));
7501	memset((char *) qg, '\0', sizeof(*qg));
7502
7503	if (line[0] == '\0')
7504	{
7505		syserr("name required for queue");
7506		return;
7507	}
7508
7509	/* collect the queue name */
7510	for (p = line;
7511	     *p != '\0' && *p != ',' && !(SM_ISSPACE(*p));
7512	     p++)
7513		continue;
7514	if (*p != '\0')
7515		*p++ = '\0';
7516	qg->qg_name = newstr(line);
7517
7518	/* set default values, can be overridden below */
7519	set_def_queueval(qg, false);
7520
7521	/* now scan through and assign info from the fields */
7522	while (*p != '\0')
7523	{
7524		auto char *delimptr;
7525
7526		while (*p != '\0' && (*p == ',' || (SM_ISSPACE(*p))))
7527			p++;
7528
7529		/* p now points to field code */
7530		fcode = *p;
7531		while (*p != '\0' && *p != '=' && *p != ',')
7532			p++;
7533		if (*p++ != '=')
7534		{
7535			syserr("queue %s: `=' expected", qg->qg_name);
7536			return;
7537		}
7538		while (SM_ISSPACE(*p))
7539			p++;
7540
7541		/* p now points to the field body */
7542		p = munchstring(p, &delimptr, ',');
7543
7544		/* install the field into the queue struct */
7545		switch (fcode)
7546		{
7547		  case 'P':		/* pathname */
7548			if (*p == '\0')
7549				syserr("queue %s: empty path name",
7550					qg->qg_name);
7551			else
7552				qg->qg_qdir = newstr(p);
7553			break;
7554
7555		  case 'F':		/* flags */
7556			for (; *p != '\0'; p++)
7557				if (!(SM_ISSPACE(*p)))
7558					setbitn(*p, qg->qg_flags);
7559			break;
7560
7561			/*
7562			**  Do we need two intervals here:
7563			**  One for persistent queue runners,
7564			**  one for "normal" queue runs?
7565			*/
7566
7567		  case 'I':	/* interval between running the queue */
7568			qg->qg_queueintvl = convtime(p, 'm');
7569			break;
7570
7571		  case 'N':		/* run niceness */
7572			qg->qg_nice = atoi(p);
7573			break;
7574
7575		  case 'R':		/* maximum # of runners for the group */
7576			i = atoi(p);
7577
7578			/* can't have more runners than allowed total */
7579			if (MaxQueueChildren > 0 && i > MaxQueueChildren)
7580			{
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",
7584						     qg->qg_name, i,
7585						     MaxQueueChildren);
7586			}
7587			else
7588				qg->qg_maxqrun = i;
7589			break;
7590
7591		  case 'J':		/* maximum # of jobs in work list */
7592			qg->qg_maxlist = atoi(p);
7593			break;
7594
7595		  case 'r':		/* max recipients per envelope */
7596			qg->qg_maxrcpt = atoi(p);
7597			break;
7598
7599#if _FFR_QUEUE_GROUP_SORTORDER
7600		  case 'S':		/* queue sorting order */
7601			switch (*p)
7602			{
7603			  case 'h':	/* Host first */
7604			  case 'H':
7605				qg->qg_sortorder = QSO_BYHOST;
7606				break;
7607
7608			  case 'p':	/* Priority order */
7609			  case 'P':
7610				qg->qg_sortorder = QSO_BYPRIORITY;
7611				break;
7612
7613			  case 't':	/* Submission time */
7614			  case 'T':
7615				qg->qg_sortorder = QSO_BYTIME;
7616				break;
7617
7618			  case 'f':	/* File name */
7619			  case 'F':
7620				qg->qg_sortorder = QSO_BYFILENAME;
7621				break;
7622
7623			  case 'm':	/* Modification time */
7624			  case 'M':
7625				qg->qg_sortorder = QSO_BYMODTIME;
7626				break;
7627
7628			  case 'r':	/* Random */
7629			  case 'R':
7630				qg->qg_sortorder = QSO_RANDOM;
7631				break;
7632
7633# if _FFR_RHS
7634			  case 's':	/* Shuffled host name */
7635			  case 'S':
7636				qg->qg_sortorder = QSO_BYSHUFFLE;
7637				break;
7638# endif /* _FFR_RHS */
7639
7640			  case 'n':	/* none */
7641			  case 'N':
7642				qg->qg_sortorder = QSO_NONE;
7643				break;
7644
7645			  default:
7646				syserr("Invalid queue sort order \"%s\"", p);
7647			}
7648			break;
7649#endif /* _FFR_QUEUE_GROUP_SORTORDER */
7650
7651		  default:
7652			syserr("Q%s: unknown queue equate %c=",
7653			       qg->qg_name, fcode);
7654			break;
7655		}
7656
7657		p = delimptr;
7658	}
7659
7660#if !HASNICE
7661	if (qg->qg_nice != NiceQueueRun)
7662	{
7663		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
7664				     "Q%s: Warning: N= set on system that doesn't support nice()\n",
7665				     qg->qg_name);
7666	}
7667#endif /* !HASNICE */
7668
7669	/* do some rationality checking */
7670	if (NumQueue >= MAXQUEUEGROUPS)
7671	{
7672		syserr("too many queue groups defined (%d max)",
7673			MAXQUEUEGROUPS);
7674		return;
7675	}
7676
7677	if (qg->qg_qdir == NULL)
7678	{
7679		if (QueueDir == NULL || *QueueDir == '\0')
7680		{
7681			syserr("QueueDir must be defined before queue groups");
7682			return;
7683		}
7684		qg->qg_qdir = newstr(QueueDir);
7685	}
7686
7687	if (qg->qg_maxqrun > 1 && !bitnset(QD_FORK, qg->qg_flags))
7688	{
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);
7692	}
7693
7694	/* enter the queue into the symbol table */
7695	if (tTd(37, 8))
7696		sm_syslog(LOG_INFO, NOQID,
7697			  "Adding %s to stab, path: %s", qg->qg_name,
7698			  qg->qg_qdir);
7699	s = stab(qg->qg_name, ST_QUEUE, ST_ENTER);
7700	if (s->s_quegrp != NULL)
7701	{
7702		i = s->s_quegrp->qg_index;
7703
7704		/* XXX what about the pointers inside this struct? */
7705		sm_free(s->s_quegrp); /* XXX */
7706	}
7707	else
7708		i = NumQueue++;
7709	Queue[i] = s->s_quegrp = qg;
7710	qg->qg_index = i;
7711
7712	/* set default value for max queue runners */
7713	if (qg->qg_maxqrun < 0)
7714	{
7715		if (MaxRunnersPerQueue > 0)
7716			qg->qg_maxqrun = MaxRunnersPerQueue;
7717		else
7718			qg->qg_maxqrun = 1;
7719	}
7720	if (qdef)
7721		setbitn(QD_DEFINED, qg->qg_flags);
7722}
7723#if 0
7724/*
7725**  HASHFQN -- calculate a hash value for a fully qualified host name
7726**
7727**	Arguments:
7728**		fqn -- an all lower-case host.domain string
7729**		buckets -- the number of buckets (queue directories)
7730**
7731**	Returns:
7732**		a bucket number (signed integer)
7733**		-1 on error
7734**
7735**	Contributed by Exactis.com, Inc.
7736*/
7737
7738int
7739hashfqn(fqn, buckets)
7740	register char *fqn;
7741	int buckets;
7742{
7743	register char *p;
7744	register int h = 0, hash, cnt;
7745
7746	if (fqn == NULL)
7747		return -1;
7748
7749	/*
7750	**  A variation on the gdb hash
7751	**  This is the best as of Feb 19, 1996 --bcx
7752	*/
7753
7754	p = fqn;
7755	h = 0x238F13AF * strlen(p);
7756	for (cnt = 0; *p != 0; ++p, cnt++)
7757	{
7758		h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF;
7759	}
7760	h = (1103515243 * h + 12345) & 0x7FFFFFFF;
7761	if (buckets < 2)
7762		hash = 0;
7763	else
7764		hash = (h % buckets);
7765
7766	return hash;
7767}
7768#endif /* 0 */
7769
7770/*
7771**  A structure for sorting Queue according to maxqrun without
7772**	screwing up Queue itself.
7773*/
7774
7775struct sortqgrp
7776{
7777	int sg_idx;		/* original index */
7778	int sg_maxqrun;		/* max queue runners */
7779};
7780typedef struct sortqgrp	SORTQGRP_T;
7781static int cmpidx __P((const void *, const void *));
7782
7783static int
7784cmpidx(a, b)
7785	const void *a;
7786	const void *b;
7787{
7788	/* The sort is highest to lowest, so the comparison is reversed */
7789	if (((SORTQGRP_T *)a)->sg_maxqrun < ((SORTQGRP_T *)b)->sg_maxqrun)
7790		return 1;
7791	else if (((SORTQGRP_T *)a)->sg_maxqrun > ((SORTQGRP_T *)b)->sg_maxqrun)
7792		return -1;
7793	else
7794		return 0;
7795}
7796
7797/*
7798**  MAKEWORKGROUPS -- balance queue groups into work groups per MaxQueueChildren
7799**
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.
7808**
7809**	Parameters:
7810**		none.
7811**
7812**	Returns:
7813**		nothing.
7814**
7815**	Side Effects:
7816**		Sets up WorkGrp structure.
7817*/
7818
7819void
7820makeworkgroups()
7821{
7822	int i, j, total_runners, dir, h;
7823	SORTQGRP_T si[MAXQUEUEGROUPS + 1];
7824
7825	total_runners = 0;
7826	if (NumQueue == 1 && strcmp(Queue[0]->qg_name, "mqueue") == 0)
7827	{
7828		/*
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).
7837		*/
7838
7839		NumWorkGroups = 1;
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;
7846		else
7847			WorkGrp[0].wg_runners = Queue[0]->qg_numqueues;
7848
7849		Queue[0]->qg_wgrp = 0;
7850
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;
7857		return;
7858	}
7859
7860	for (i = 0; i < NumQueue; i++)
7861	{
7862		si[i].sg_maxqrun = Queue[i]->qg_maxqrun;
7863		si[i].sg_idx = i;
7864
7865		/* Hack to make sure BounceQueue ends up last */
7866		if (IS_BOUNCE_QUEUE(i))
7867			si[i].sg_maxqrun = INT_MIN;
7868	}
7869	qsort(si, NumQueue, sizeof(si[0]), cmpidx);
7870
7871	NumWorkGroups = 0;
7872	for (i = 0; i < NumQueue; i++)
7873	{
7874		SKIP_BOUNCE_QUEUE(i)
7875		total_runners += si[i].sg_maxqrun;
7876		if (MaxQueueChildren <= 0 || total_runners <= MaxQueueChildren)
7877			NumWorkGroups++;
7878		else
7879			break;
7880	}
7881
7882	if (NumWorkGroups < 1)
7883		NumWorkGroups = 1; /* gotta have one at least */
7884	else if (NumWorkGroups > MAXWORKGROUPS)
7885		NumWorkGroups = MAXWORKGROUPS; /* the limit */
7886
7887	/*
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.
7894	*/
7895
7896	j = 0;
7897	dir = 1;
7898	for (i = 0; i < NumQueue; i++)
7899	{
7900		h = si[i].sg_idx;
7901		if (tTd(41, 49))
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);
7905
7906		/* a to-and-fro packing scheme, continue from last position */
7907		if (j >= NumWorkGroups)
7908		{
7909			dir = -1;
7910			j = NumWorkGroups - 1;
7911		}
7912		else if (j < 0)
7913		{
7914			j = 0;
7915			dir = 1;
7916		}
7917
7918		if (WorkGrp[j].wg_qgs == NULL)
7919			WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_malloc(sizeof(QUEUEGRP *) *
7920							(WorkGrp[j].wg_numqgrp + 1));
7921		else
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)
7926		{
7927			syserr("!cannot allocate memory for work queues, need %d bytes",
7928			       (int) (sizeof(QUEUEGRP *) *
7929				      (WorkGrp[j].wg_numqgrp + 1)));
7930		}
7931
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;
7936
7937		if (WorkGrp[j].wg_maxact == 0)
7938		{
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;
7944		}
7945
7946		/*
7947		**  XXX: must wg_lowqintvl be the GCD?
7948		**  qg1: 2m, qg2: 3m, minimum: 2m, when do queue runs for
7949		**  qg2 occur?
7950		*/
7951
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;
7956		j += dir;
7957	}
7958	if (tTd(41, 9))
7959	{
7960		for (i = 0; i < NumWorkGroups; i++)
7961		{
7962			sm_dprintf("Workgroup[%d]=", i);
7963			for (j = 0; j < WorkGrp[i].wg_numqgrp; j++)
7964			{
7965				sm_dprintf("%s, ",
7966					WorkGrp[i].wg_qgs[j]->qg_name);
7967			}
7968			if (tTd(41, 12))
7969				sm_dprintf("lowqintvl=%d",
7970					(int) WorkGrp[i].wg_lowqintvl);
7971			sm_dprintf("\n");
7972		}
7973	}
7974}
7975
7976/*
7977**  DUP_DF -- duplicate envelope data file
7978**
7979**	Copy the data file from the 'old' envelope to the 'new' envelope
7980**	in the most efficient way possible.
7981**
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.
7987**
7988**	Parameters:
7989**		old -- old envelope.
7990**		new -- new envelope.
7991**
7992**	Results:
7993**		Returns true on success, false on failure.
7994**
7995**	Side Effects:
7996**		On success, the new data file is created.
7997**		On fatal failure, EF_FATALERRS is set in old->e_flags.
7998*/
7999
8000static bool	dup_df __P((ENVELOPE *, ENVELOPE *));
8001
8002static bool
8003dup_df(old, new)
8004	ENVELOPE *old;
8005	ENVELOPE *new;
8006{
8007	int ofs, nfs, r;
8008	char opath[MAXPATHLEN];
8009	char npath[MAXPATHLEN];
8010
8011	if (!bitset(EF_HAS_DF, old->e_flags))
8012	{
8013		/*
8014		**  this can happen if: SuperSafe != True
8015		**  and a bounce mail is sent that is split.
8016		*/
8017
8018		queueup(old, false, true);
8019	}
8020	SM_REQUIRE(ISVALIDQGRP(old->e_qgrp) && ISVALIDQDIR(old->e_qdir));
8021	SM_REQUIRE(ISVALIDQGRP(new->e_qgrp) && ISVALIDQDIR(new->e_qdir));
8022
8023	(void) sm_strlcpy(opath, queuename(old, DATAFL_LETTER), sizeof(opath));
8024	(void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof(npath));
8025
8026	if (old->e_dfp != NULL)
8027	{
8028		r = sm_io_setinfo(old->e_dfp, SM_BF_COMMIT, NULL);
8029		if (r < 0 && errno != EINVAL)
8030		{
8031			syserr("@can't commit %s", opath);
8032			old->e_flags |= EF_FATALERRS;
8033			return false;
8034		}
8035	}
8036
8037	/*
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.
8040	**
8041	**  Don't waste time attempting a hard link unless old and new
8042	**  are on the same file system.
8043	*/
8044
8045	SM_REQUIRE(ISVALIDQGRP(old->e_dfqgrp) && ISVALIDQDIR(old->e_dfqdir));
8046	SM_REQUIRE(ISVALIDQGRP(new->e_dfqgrp) && ISVALIDQDIR(new->e_dfqdir));
8047
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))
8051	{
8052		if (link(opath, npath) == 0)
8053		{
8054			new->e_flags |= EF_HAS_DF;
8055			SYNC_DIR(npath, true);
8056			return true;
8057		}
8058		goto error;
8059	}
8060
8061	/*
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.
8065	*/
8066
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)
8071	{
8072		new->e_flags |= EF_HAS_DF;
8073		SYNC_DIR(npath, true);
8074		return true;
8075	}
8076
8077  error:
8078	if (LogLevel > 0)
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));
8082	return false;
8083}
8084
8085/*
8086**  SPLIT_ENV -- Allocate a new envelope based on a given envelope.
8087**
8088**	Parameters:
8089**		e -- envelope.
8090**		sendqueue -- sendqueue for new envelope.
8091**		qgrp -- index of queue group.
8092**		qdir -- queue directory.
8093**
8094**	Results:
8095**		new envelope.
8096**
8097*/
8098
8099static ENVELOPE	*split_env __P((ENVELOPE *, ADDRESS *, int, int));
8100
8101static ENVELOPE *
8102split_env(e, sendqueue, qgrp, qdir)
8103	ENVELOPE *e;
8104	ADDRESS *sendqueue;
8105	int qgrp;
8106	int qdir;
8107{
8108	ENVELOPE *ee;
8109
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? */
8113	ee->e_id = NULL;
8114	assign_queueid(ee);
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;
8120	ee->e_dfp = NULL;
8121	ee->e_lockfp = NULL;
8122	if (e->e_xfp != NULL)
8123		ee->e_xfp = sm_io_dup(e->e_xfp);
8124
8125	/* failed to dup e->e_xfp, start a new transcript */
8126	if (ee->e_xfp == NULL)
8127		openxscript(ee);
8128
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,
8135						  e->e_quarmsg);
8136
8137	/*
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.
8143	*/
8144
8145	ee->e_header = copyheader(e->e_header, ee->e_rpool);
8146	ee->e_errorqueue = copyqueue(e->e_errorqueue, ee->e_rpool);
8147
8148	return ee;
8149}
8150
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))
8155
8156/*
8157**  SPLIT_ACROSS_QUEUE_GROUPS
8158**
8159**	This function splits an envelope across multiple queue groups
8160**	based on the queue group of each recipient.
8161**
8162**	Parameters:
8163**		e -- envelope.
8164**
8165**	Results:
8166**		SM_SPLIT_FAIL on failure
8167**		SM_SPLIT_NONE if no splitting occurred,
8168**		or 1 + the number of additional envelopes created.
8169**
8170**	Side Effects:
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.
8174**
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.
8179*/
8180
8181static int	q_qgrp_compare __P((const void *, const void *));
8182static int	e_filesys_compare __P((const void *, const void *));
8183
8184static int
8185q_qgrp_compare(p1, p2)
8186	const void *p1;
8187	const void *p2;
8188{
8189	ADDRESS **pq1 = (ADDRESS **) p1;
8190	ADDRESS **pq2 = (ADDRESS **) p2;
8191
8192	return (*pq1)->q_qgrp - (*pq2)->q_qgrp;
8193}
8194
8195static int
8196e_filesys_compare(p1, p2)
8197	const void *p1;
8198	const void *p2;
8199{
8200	ENVELOPE **pe1 = (ENVELOPE **) p1;
8201	ENVELOPE **pe2 = (ENVELOPE **) p2;
8202	int fs1, fs2;
8203
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))
8207		return -1;
8208	if (FILE_SYS_DEV(fs1) > FILE_SYS_DEV(fs2))
8209		return 1;
8210	return 0;
8211}
8212
8213static int split_across_queue_groups __P((ENVELOPE *));
8214static int
8215split_across_queue_groups(e)
8216	ENVELOPE *e;
8217{
8218	int naddrs, nsplits, i;
8219	bool changed;
8220	char **pvp;
8221	ADDRESS *q, **addrs;
8222	ENVELOPE *ee, *es;
8223	ENVELOPE *splits[MAXQUEUEGROUPS];
8224	char pvpbuf[PSBUFSIZE];
8225
8226	SM_REQUIRE(ISVALIDQGRP(e->e_qgrp));
8227
8228	/* Count addresses and assign queue groups. */
8229	naddrs = 0;
8230	changed = false;
8231	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
8232	{
8233		if (QS_IS_DEAD(q->q_state))
8234			continue;
8235		++naddrs;
8236
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))
8242		{
8243			/* call ruleset which should return a queue group */
8244			i = rscap(RS_QUEUEGROUP, q->q_user, NULL, e, &pvp,
8245				  pvpbuf, sizeof(pvpbuf));
8246			if (i == EX_OK &&
8247			    pvp != NULL && pvp[0] != NULL &&
8248			    (pvp[0][0] & 0377) == CANONNET &&
8249			    pvp[1] != NULL && pvp[1][0] != '\0')
8250			{
8251				i = name2qid(pvp[1]);
8252				if (ISVALIDQGRP(i))
8253				{
8254					q->q_qgrp = i;
8255					changed = true;
8256					if (tTd(20, 4))
8257						sm_syslog(LOG_INFO, NOQID,
8258							"queue group name %s -> %d",
8259							pvp[1], i);
8260					continue;
8261				}
8262				else if (LogLevel > 10)
8263					sm_syslog(LOG_INFO, NOQID,
8264						"can't find queue group name %s, selection ignored",
8265						pvp[1]);
8266			}
8267			if (q->q_mailer != NULL &&
8268			    ISVALIDQGRP(q->q_mailer->m_qgrp))
8269			{
8270				changed = true;
8271				q->q_qgrp = q->q_mailer->m_qgrp;
8272			}
8273			else if (ISVALIDQGRP(e->e_qgrp))
8274				q->q_qgrp = e->e_qgrp;
8275			else
8276				q->q_qgrp = 0;
8277		}
8278	}
8279
8280	/* only one address? nothing to split. */
8281	if (naddrs <= 1 && !changed)
8282		return SM_SPLIT_NONE;
8283
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)
8287	{
8288		if (QS_IS_DEAD(q->q_state))
8289			continue;
8290		addrs[i++] = q;
8291	}
8292	qsort(addrs, naddrs, sizeof(ADDRESS *), q_qgrp_compare);
8293
8294	/* split into multiple envelopes, by queue group */
8295	nsplits = 0;
8296	es = NULL;
8297	e->e_sendqueue = NULL;
8298	for (i = 0; i < naddrs; ++i)
8299	{
8300		if (i == naddrs - 1 || addrs[i]->q_qgrp != addrs[i + 1]->q_qgrp)
8301			addrs[i]->q_next = NULL;
8302		else
8303			addrs[i]->q_next = addrs[i + 1];
8304
8305		/* same queue group as original envelope? */
8306		if (addrs[i]->q_qgrp == e->e_qgrp)
8307		{
8308			if (e->e_sendqueue == NULL)
8309				e->e_sendqueue = addrs[i];
8310			continue;
8311		}
8312
8313		/* different queue group than original envelope */
8314		if (es == NULL || addrs[i]->q_qgrp != es->e_qgrp)
8315		{
8316			ee = split_env(e, addrs[i], addrs[i]->q_qgrp, NOQDIR);
8317			es = ee;
8318			splits[nsplits++] = ee;
8319		}
8320	}
8321
8322	/* no splits? return right now. */
8323	if (nsplits <= 0)
8324		return SM_SPLIT_NONE;
8325
8326	/* assign a queue directory to each additional envelope */
8327	for (i = 0; i < nsplits; ++i)
8328	{
8329		es = splits[i];
8330#if 0
8331		es->e_qdir = pickqdir(Queue[es->e_qgrp], es->e_msgsize, es);
8332#endif
8333		if (!setnewqueue(es))
8334			goto failure;
8335	}
8336
8337	/* sort the additional envelopes by queue file system */
8338	qsort(splits, nsplits, sizeof(ENVELOPE *), e_filesys_compare);
8339
8340	/* create data files for each additional envelope */
8341	if (!dup_df(e, splits[0]))
8342	{
8343		i = 0;
8344		goto failure;
8345	}
8346	for (i = 1; i < nsplits; ++i)
8347	{
8348		/* copy or link to the previous data file */
8349		if (!dup_df(splits[i - 1], splits[i]))
8350			goto failure;
8351	}
8352
8353	/* success: prepend the new envelopes to the e->e_sibling list */
8354	for (i = 0; i < nsplits; ++i)
8355	{
8356		es = splits[i];
8357		es->e_sibling = e->e_sibling;
8358		e->e_sibling = es;
8359	}
8360	return SM_SPLIT_NEW(nsplits);
8361
8362	/* failure: clean up */
8363  failure:
8364	if (i > 0)
8365	{
8366		int j;
8367
8368		for (j = 0; j < i; j++)
8369			(void) unlink(queuename(splits[j], DATAFL_LETTER));
8370	}
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;
8376}
8377
8378/*
8379**  SPLIT_WITHIN_QUEUE
8380**
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.
8384**
8385**	Parameters:
8386**		e -- envelope.
8387**
8388**	Results:
8389**		SM_SPLIT_FAIL on failure
8390**		SM_SPLIT_NONE if no splitting occurred,
8391**		or 1 + the number of additional envelopes created.
8392*/
8393
8394#define SPLIT_LOG_LEVEL	8
8395
8396static int	split_within_queue __P((ENVELOPE *));
8397
8398static int
8399split_within_queue(e)
8400	ENVELOPE *e;
8401{
8402	int maxrcpt, nrcpt, ndead, nsplit, i;
8403	int j, l;
8404	char *lsplits;
8405	ADDRESS *q, **addrs;
8406	ENVELOPE *ee, *firstsibling;
8407
8408	if (!ISVALIDQGRP(e->e_qgrp) || bitset(EF_SPLIT, e->e_flags))
8409		return SM_SPLIT_NONE;
8410
8411	/* don't bother if there is no recipient limit */
8412	maxrcpt = Queue[e->e_qgrp]->qg_maxrcpt;
8413	if (maxrcpt <= 0)
8414		return SM_SPLIT_NONE;
8415
8416	/* count recipients */
8417	nrcpt = 0;
8418	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
8419	{
8420		if (QS_IS_DEAD(q->q_state))
8421			continue;
8422		++nrcpt;
8423	}
8424	if (nrcpt <= maxrcpt)
8425		return SM_SPLIT_NONE;
8426
8427	/*
8428	**  Preserve the recipient list
8429	**  so that we can restore it in case of error.
8430	**  (But we discard dead addresses.)
8431	*/
8432
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)
8435	{
8436		if (QS_IS_DEAD(q->q_state))
8437			continue;
8438		addrs[i++] = q;
8439	}
8440
8441	/*
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.
8446	*/
8447
8448	ndead = 0;
8449	for (i = 0; i < nrcpt; ++i)
8450	{
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 */
8454		{
8455			if (i > ndead)
8456			{
8457				ADDRESS *tmp = addrs[i];
8458
8459				addrs[i] = addrs[ndead];
8460				addrs[ndead] = tmp;
8461			}
8462			++ndead;
8463		}
8464	}
8465
8466	/* Check if no splitting required. */
8467	if (nrcpt - ndead <= maxrcpt)
8468		return SM_SPLIT_NONE;
8469
8470	/* fix links */
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];
8475
8476	/* prepare buffer for logging */
8477	if (LogLevel > SPLIT_LOG_LEVEL)
8478	{
8479		l = MAXLINE;
8480		lsplits = sm_malloc(l);
8481		if (lsplits != NULL)
8482			*lsplits = '\0';
8483		j = 0;
8484	}
8485	else
8486	{
8487		/* get rid of stupid compiler warnings */
8488		lsplits = NULL;
8489		j = l = 0;
8490	}
8491
8492	/* split the envelope */
8493	firstsibling = e->e_sibling;
8494	i = maxrcpt + ndead;
8495	nsplit = 0;
8496	for (;;)
8497	{
8498		addrs[i - 1]->q_next = NULL;
8499		ee = split_env(e, addrs[i], e->e_qgrp, e->e_qdir);
8500		if (!dup_df(e, ee))
8501		{
8502
8503			ee = firstsibling;
8504			while (ee != NULL)
8505			{
8506				(void) unlink(queuename(ee, DATAFL_LETTER));
8507				ee = ee->e_sibling;
8508			}
8509
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)
8515				sm_free(lsplits);
8516			return SM_SPLIT_FAIL;
8517		}
8518
8519		/* prepend the new envelope to e->e_sibling */
8520		ee->e_sibling = e->e_sibling;
8521		e->e_sibling = ee;
8522		++nsplit;
8523		if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL)
8524		{
8525			if (j >= l - strlen(ee->e_id) - 3)
8526			{
8527				char *p;
8528
8529				l += MAXLINE;
8530				p = sm_realloc(lsplits, l);
8531				if (p == NULL)
8532				{
8533					/* let's try to get this done */
8534					sm_free(lsplits);
8535					lsplits = NULL;
8536				}
8537				else
8538					lsplits = p;
8539			}
8540			if (lsplits != NULL)
8541			{
8542				if (j == 0)
8543					j += sm_strlcat(lsplits + j,
8544							ee->e_id,
8545							l - j);
8546				else
8547					j += sm_strlcat2(lsplits + j,
8548							 "; ",
8549							 ee->e_id,
8550							 l - j);
8551				SM_ASSERT(j < l);
8552			}
8553		}
8554		if (nrcpt - i <= maxrcpt)
8555			break;
8556		i += maxrcpt;
8557	}
8558	if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL)
8559	{
8560		if (nsplit > 0)
8561		{
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);
8566		}
8567		sm_free(lsplits);
8568	}
8569	return SM_SPLIT_NEW(nsplit);
8570}
8571/*
8572**  SPLIT_BY_RECIPIENT
8573**
8574**	Split an envelope with multiple recipients into multiple
8575**	envelopes as required by the sendmail configuration.
8576**
8577**	Parameters:
8578**		e -- envelope.
8579**
8580**	Results:
8581**		Returns true on success, false on failure.
8582**
8583**	Side Effects:
8584**		see split_across_queue_groups(), split_within_queue(e)
8585*/
8586
8587bool
8588split_by_recipient(e)
8589	ENVELOPE *e;
8590{
8591	int split, n, i, j, l;
8592	char *lsplits;
8593	ENVELOPE *ee, *next, *firstsibling;
8594
8595	if (OpMode == SM_VERIFY || !ISVALIDQGRP(e->e_qgrp) ||
8596	    bitset(EF_SPLIT, e->e_flags))
8597		return true;
8598	n = split_across_queue_groups(e);
8599	if (n == SM_SPLIT_FAIL)
8600		return false;
8601	firstsibling = ee = e->e_sibling;
8602	if (n > 1 && LogLevel > SPLIT_LOG_LEVEL)
8603	{
8604		l = MAXLINE;
8605		lsplits = sm_malloc(l);
8606		if (lsplits != NULL)
8607			*lsplits = '\0';
8608		j = 0;
8609	}
8610	else
8611	{
8612		/* get rid of stupid compiler warnings */
8613		lsplits = NULL;
8614		j = l = 0;
8615	}
8616	for (i = 1; i < n; ++i)
8617	{
8618		next = ee->e_sibling;
8619		if (split_within_queue(ee) == SM_SPLIT_FAIL)
8620		{
8621			e->e_sibling = firstsibling;
8622			SM_FREE(lsplits);
8623			return false;
8624		}
8625		ee->e_flags |= EF_SPLIT;
8626		if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL)
8627		{
8628			if (j >= l - strlen(ee->e_id) - 3)
8629			{
8630				char *p;
8631
8632				l += MAXLINE;
8633				p = sm_realloc(lsplits, l);
8634				if (p == NULL)
8635				{
8636					/* let's try to get this done */
8637					SM_FREE(lsplits);
8638				}
8639				else
8640					lsplits = p;
8641			}
8642			if (lsplits != NULL)
8643			{
8644				if (j == 0)
8645					j += sm_strlcat(lsplits + j,
8646							ee->e_id, l - j);
8647				else
8648					j += sm_strlcat2(lsplits + j, "; ",
8649							 ee->e_id, l - j);
8650				SM_ASSERT(j < l);
8651			}
8652		}
8653		ee = next;
8654	}
8655	if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL && n > 1)
8656	{
8657		sm_syslog(LOG_NOTICE, e->e_id, "split: count=%d, id%s=%s",
8658			  n - 1, n > 2 ? "s" : "", lsplits);
8659		SM_FREE(lsplits);
8660	}
8661	split = split_within_queue(e) != SM_SPLIT_FAIL;
8662	if (split)
8663		e->e_flags |= EF_SPLIT;
8664	return split;
8665}
8666
8667/*
8668**  QUARANTINE_QUEUE_ITEM -- {un,}quarantine a single envelope
8669**
8670**	Add/remove quarantine reason and requeue appropriately.
8671**
8672**	Parameters:
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.
8677**
8678**	Results:
8679**		true if item changed, false otherwise
8680**
8681**	Side Effects:
8682**		Changes quarantine tag in queue file and renames it.
8683*/
8684
8685static bool
8686quarantine_queue_item(qgrp, qdir, e, reason)
8687	int qgrp;
8688	int qdir;
8689	ENVELOPE *e;
8690	char *reason;
8691{
8692	bool dirty = false;
8693	bool failing = false;
8694	bool foundq = false;
8695	bool finished = false;
8696	int fd;
8697	int flags;
8698	int oldtype;
8699	int newtype;
8700	int save_errno;
8701	MODE_T oldumask = 0;
8702	SM_FILE_T *oldqfp, *tempqfp;
8703	char *bp;
8704	int bufsize;
8705	char oldqf[MAXPATHLEN];
8706	char tempqf[MAXPATHLEN];
8707	char newqf[MAXPATHLEN];
8708	char buf[MAXLINE];
8709
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));
8713
8714	/*
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
8720	**  we are done.
8721	*/
8722
8723	if (!readqf(e, true))
8724	{
8725		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8726				     "Skipping %s\n", qid_printname(e));
8727		return false;
8728	}
8729	oldqfp = e->e_lockfp;
8730
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);
8738	RELEASE_QUEUE;
8739
8740	if (fd < 0)
8741	{
8742		save_errno = errno;
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);
8748		return false;
8749	}
8750	if (!lockfile(fd, tempqf, NULL, LOCK_EX|LOCK_NB))
8751	{
8752		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8753				     "Skipping %s: Could not lock %s\n",
8754				     qid_printname(e), tempqf);
8755		(void) close(fd);
8756		(void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
8757		return false;
8758	}
8759
8760	tempqfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, (void *) &fd,
8761			     SM_IO_WRONLY_B, NULL);
8762	if (tempqfp == NULL)
8763	{
8764		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8765				     "Skipping %s: Could not lock %s\n",
8766				     qid_printname(e), tempqf);
8767		(void) close(fd);
8768		(void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
8769		return false;
8770	}
8771
8772	/* Copy the data over, changing the quarantine reason */
8773	while (bufsize = sizeof(buf),
8774	       (bp = fgetfolded(buf, &bufsize, oldqfp)) != NULL)
8775	{
8776		if (tTd(40, 4))
8777			sm_dprintf("+++++ %s\n", bp);
8778		switch (bp[0])
8779		{
8780		  case 'q':		/* quarantine reason */
8781			foundq = true;
8782			if (reason == NULL)
8783			{
8784				if (Verbose)
8785				{
8786					(void) sm_io_fprintf(smioout,
8787							     SM_TIME_DEFAULT,
8788							     "%s: Removed quarantine of \"%s\"\n",
8789							     e->e_id, &bp[1]);
8790				}
8791				sm_syslog(LOG_INFO, e->e_id, "unquarantine");
8792				dirty = true;
8793			}
8794			else if (strcmp(reason, &bp[1]) == 0)
8795			{
8796				if (Verbose)
8797				{
8798					(void) sm_io_fprintf(smioout,
8799							     SM_TIME_DEFAULT,
8800							     "%s: Already quarantined with \"%s\"\n",
8801							     e->e_id, reason);
8802				}
8803				(void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8804						     "q%s\n", reason);
8805			}
8806			else
8807			{
8808				if (Verbose)
8809				{
8810					(void) sm_io_fprintf(smioout,
8811							     SM_TIME_DEFAULT,
8812							     "%s: Quarantine changed from \"%s\" to \"%s\"\n",
8813							     e->e_id, &bp[1],
8814							     reason);
8815				}
8816				(void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8817						     "q%s\n", reason);
8818				sm_syslog(LOG_INFO, e->e_id, "quarantine=%s",
8819					  reason);
8820				dirty = true;
8821			}
8822			break;
8823
8824		  case 'S':
8825			/*
8826			**  If we are quarantining an unquarantined item,
8827			**  need to put in a new 'q' line before it's
8828			**  too late.
8829			*/
8830
8831			if (!foundq && reason != NULL)
8832			{
8833				if (Verbose)
8834				{
8835					(void) sm_io_fprintf(smioout,
8836							     SM_TIME_DEFAULT,
8837							     "%s: Quarantined with \"%s\"\n",
8838							     e->e_id, reason);
8839				}
8840				(void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8841						     "q%s\n", reason);
8842				sm_syslog(LOG_INFO, e->e_id, "quarantine=%s",
8843					  reason);
8844				foundq = true;
8845				dirty = true;
8846			}
8847
8848			/* Copy the line to the new file */
8849			(void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8850					     "%s\n", bp);
8851			break;
8852
8853		  case '.':
8854			finished = true;
8855			/* FALLTHROUGH */
8856
8857		  default:
8858			/* Copy the line to the new file */
8859			(void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT,
8860					     "%s\n", bp);
8861			break;
8862		}
8863		if (bp != buf)
8864			sm_free(bp);
8865	}
8866
8867	/* Make sure we read the whole old file */
8868	errno = sm_io_error(tempqfp);
8869	if (errno != 0 && errno != SM_IO_EOF)
8870	{
8871		save_errno = errno;
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));
8876		failing = true;
8877	}
8878
8879	if (!failing && !finished)
8880	{
8881		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8882				     "Skipping %s: Incomplete file: %s\n",
8883				     qid_printname(e), oldqf);
8884		failing = true;
8885	}
8886
8887	/* Check if we actually changed anything or we can just bail now */
8888	if (!dirty)
8889	{
8890		/* pretend we failed, even though we technically didn't */
8891		failing = true;
8892	}
8893
8894	/* Make sure we wrote things out safely */
8895	if (!failing &&
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)))
8902	{
8903		save_errno = errno;
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));
8908		failing = true;
8909	}
8910
8911
8912	/* Figure out the new filename */
8913	newtype = (reason == NULL ? NORMQF_LETTER : QUARQF_LETTER);
8914	if (oldtype == newtype)
8915	{
8916		/* going to rename tempqf to oldqf */
8917		(void) sm_strlcpy(newqf, oldqf, sizeof(newqf));
8918	}
8919	else
8920	{
8921		/* going to rename tempqf to new name based on newtype */
8922		(void) sm_strlcpy(newqf, queuename(e, newtype), sizeof(newqf));
8923	}
8924
8925	save_errno = 0;
8926
8927	/* rename tempqf to newqf */
8928	if (!failing &&
8929	    rename(tempqf, newqf) < 0)
8930		save_errno = (errno == 0) ? EINVAL : errno;
8931
8932	/* Check rename() success */
8933	if (!failing && save_errno != 0)
8934	{
8935		sm_syslog(LOG_DEBUG, e->e_id,
8936			  "quarantine_queue_item: rename(%s, %s): %s",
8937			  tempqf, newqf, sm_errstring(save_errno));
8938
8939		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8940				     "Error renaming %s to %s: %s\n",
8941				     tempqf, newqf,
8942				     sm_errstring(save_errno));
8943		if (oldtype == newtype)
8944		{
8945			/*
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.
8949			*/
8950
8951			RELEASE_QUEUE;
8952			errno = save_errno;
8953			syserr("!452 Error renaming control file %s", tempqf);
8954			/* NOTREACHED */
8955		}
8956		else
8957		{
8958			/* remove new file (if rename() half completed) */
8959			if (xunlink(newqf) < 0)
8960			{
8961				save_errno = errno;
8962				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8963						     "Error removing %s: %s\n",
8964						     newqf,
8965						     sm_errstring(save_errno));
8966			}
8967
8968			/* tempqf removed below */
8969			failing = true;
8970		}
8971
8972	}
8973
8974	/* If changing file types, need to remove old type */
8975	if (!failing && oldtype != newtype)
8976	{
8977		if (xunlink(oldqf) < 0)
8978		{
8979			save_errno = errno;
8980			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
8981					     "Error removing %s: %s\n",
8982					     oldqf, sm_errstring(save_errno));
8983		}
8984	}
8985
8986	/* see if anything above failed */
8987	if (failing)
8988	{
8989		/* Something failed: remove new file, old file still there */
8990		(void) xunlink(tempqf);
8991	}
8992
8993	/*
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.
8997	*/
8998
8999	if (SuperSafe != SAFE_NO)
9000	{
9001		/* for soft-updates */
9002		(void) fsync(sm_io_getinfo(tempqfp,
9003					   SM_IO_WHAT_FD, NULL));
9004
9005		if (!failing)
9006		{
9007			/* for soft-updates */
9008			(void) fsync(sm_io_getinfo(oldqfp,
9009						   SM_IO_WHAT_FD, NULL));
9010		}
9011
9012		/* for other odd filesystems */
9013		SYNC_DIR(tempqf, false);
9014	}
9015
9016	/* Close up shop */
9017	RELEASE_QUEUE;
9018	if (tempqfp != NULL)
9019		(void) sm_io_close(tempqfp, SM_TIME_DEFAULT);
9020	if (oldqfp != NULL)
9021		(void) sm_io_close(oldqfp, SM_TIME_DEFAULT);
9022
9023	/* All went well */
9024	return !failing;
9025}
9026
9027/*
9028**  QUARANTINE_QUEUE -- {un,}quarantine matching items in the queue
9029**
9030**	Read all matching queue items, add/remove quarantine
9031**	reason, and requeue appropriately.
9032**
9033**	Parameters:
9034**		reason -- quarantine reason, "." means unquarantine.
9035**		qgrplimit -- limit to single queue group unless NOQGRP
9036**
9037**	Results:
9038**		none.
9039**
9040**	Side Effects:
9041**		Lots of changes to the queue.
9042*/
9043
9044void
9045quarantine_queue(reason, qgrplimit)
9046	char *reason;
9047	int qgrplimit;
9048{
9049	int changed = 0;
9050	int qgrp;
9051
9052	/* Convert internal representation of unquarantine */
9053	if (reason != NULL && reason[0] == '.' && reason[1] == '\0')
9054		reason = NULL;
9055
9056	if (reason != NULL)
9057	{
9058		/* clean it */
9059		reason = newstr(denlstring(reason, true, true));
9060	}
9061
9062	for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++)
9063	{
9064		int qdir;
9065
9066		if (qgrplimit != NOQGRP && qgrplimit != qgrp)
9067			continue;
9068
9069		for (qdir = 0; qdir < Queue[qgrp]->qg_numqueues; qdir++)
9070		{
9071			int i;
9072			int nrequests;
9073
9074			if (StopRequest)
9075				stop_sendmail();
9076
9077			nrequests = gatherq(qgrp, qdir, true, NULL, NULL, NULL);
9078
9079			/* first see if there is anything */
9080			if (nrequests <= 0)
9081			{
9082				if (Verbose)
9083				{
9084					(void) sm_io_fprintf(smioout,
9085							     SM_TIME_DEFAULT, "%s: no matches\n",
9086							     qid_printqueue(qgrp, qdir));
9087				}
9088				continue;
9089			}
9090
9091			if (Verbose)
9092			{
9093				(void) sm_io_fprintf(smioout,
9094						     SM_TIME_DEFAULT, "Processing %s:\n",
9095						     qid_printqueue(qgrp, qdir));
9096			}
9097
9098			for (i = 0; i < WorkListCount; i++)
9099			{
9100				ENVELOPE e;
9101
9102				if (StopRequest)
9103					stop_sendmail();
9104
9105				/* setup envelope */
9106				clearenvelope(&e, true, sm_rpool_new_x(NULL));
9107				e.e_id = WorkList[i].w_name + 2;
9108				e.e_qgrp = qgrp;
9109				e.e_qdir = qdir;
9110
9111				if (tTd(70, 101))
9112				{
9113					sm_io_fprintf(smioout, SM_TIME_DEFAULT,
9114						      "Would do %s\n", e.e_id);
9115					changed++;
9116				}
9117				else if (quarantine_queue_item(qgrp, qdir,
9118							       &e, reason))
9119					changed++;
9120
9121				/* clean up */
9122				sm_rpool_free(e.e_rpool);
9123				e.e_rpool = NULL;
9124			}
9125			if (WorkList != NULL)
9126				sm_free(WorkList); /* XXX */
9127			WorkList = NULL;
9128			WorkListSize = 0;
9129			WorkListCount = 0;
9130		}
9131	}
9132	if (Verbose)
9133	{
9134		if (changed == 0)
9135			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
9136					     "No changes\n");
9137		else
9138			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
9139					     "%d change%s\n",
9140					     changed,
9141					     changed == 1 ? "" : "s");
9142	}
9143}
9144