queue.c revision 71345
1/*
2 * Copyright (c) 1998-2000 Sendmail, 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
15#include <sendmail.h>
16
17#ifndef lint
18# if QUEUE
19static char id[] = "@(#)$Id: queue.c,v 8.343.4.38 2000/12/08 14:33:02 ca Exp $ (with queueing)";
20# else /* QUEUE */
21static char id[] = "@(#)$Id: queue.c,v 8.343.4.38 2000/12/08 14:33:02 ca Exp $ (without queueing)";
22# endif /* QUEUE */
23#endif /* ! lint */
24
25# include <dirent.h>
26
27#if QUEUE
28
29# if _FFR_QUEUEDELAY
30#  define QF_VERSION	5	/* version number of this queue format */
31static time_t	queuedelay __P((ENVELOPE *));
32# else /* _FFR_QUEUEDELAY */
33#  define QF_VERSION	4	/* version number of this queue format */
34#  define queuedelay(e)	MinQueueAge
35# endif /* _FFR_QUEUEDELAY */
36
37/*
38**  Work queue.
39*/
40
41struct work
42{
43	char		*w_name;	/* name of control file */
44	char		*w_host;	/* name of recipient host */
45	bool		w_lock;		/* is message locked? */
46	bool		w_tooyoung;	/* is it too young to run? */
47	long		w_pri;		/* priority of message, see below */
48	time_t		w_ctime;	/* creation time of message */
49	struct work	*w_next;	/* next in queue */
50};
51
52typedef struct work	WORK;
53
54static WORK	*WorkQ;			/* queue of things to be done */
55
56static void	grow_wlist __P((int));
57static int	orderq __P((int, bool));
58static void	printctladdr __P((ADDRESS *, FILE *));
59static int	print_single_queue __P((int));
60static bool	readqf __P((ENVELOPE *));
61static void	runqueueevent __P((void));
62static int	run_single_queue __P((int, bool, bool));
63static char	*strrev __P((char *));
64static ADDRESS	*setctluser __P((char *, int));
65static int	workcmpf0();
66static int	workcmpf1();
67static int	workcmpf2();
68static int	workcmpf3();
69static int	workcmpf4();
70
71/*
72**  QUEUEUP -- queue a message up for future transmission.
73**
74**	Parameters:
75**		e -- the envelope to queue up.
76**		announce -- if TRUE, tell when you are queueing up.
77**
78**	Returns:
79**		none.
80**
81**	Side Effects:
82**		The current request are saved in a control file.
83**		The queue file is left locked.
84*/
85
86# define TEMPQF_LETTER 'T'
87# define LOSEQF_LETTER 'Q'
88
89void
90queueup(e, announce)
91	register ENVELOPE *e;
92	bool announce;
93{
94	char *qf;
95	register FILE *tfp;
96	register HDR *h;
97	register ADDRESS *q;
98	int tfd = -1;
99	int i;
100	bool newid;
101	register char *p;
102	MAILER nullmailer;
103	MCI mcibuf;
104	char tf[MAXPATHLEN];
105	char buf[MAXLINE];
106
107	/*
108	**  Create control file.
109	*/
110
111	newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
112
113	/* if newid, queuename will create a locked qf file in e->lockfp */
114	(void) strlcpy(tf, queuename(e, 't'), sizeof tf);
115	tfp = e->e_lockfp;
116	if (tfp == NULL)
117		newid = FALSE;
118
119	/* if newid, just write the qf file directly (instead of tf file) */
120	if (!newid)
121	{
122		int flags;
123
124		flags = O_CREAT|O_WRONLY|O_EXCL;
125
126		/* get a locked tf file */
127		for (i = 0; i < 128; i++)
128		{
129			if (tfd < 0)
130			{
131#if _FFR_QUEUE_FILE_MODE
132				MODE_T oldumask;
133
134				if (bitset(S_IWGRP, QueueFileMode))
135					oldumask = umask(002);
136				tfd = open(tf, flags, QueueFileMode);
137				if (bitset(S_IWGRP, QueueFileMode))
138					(void) umask(oldumask);
139#else /* _FFR_QUEUE_FILE_MODE */
140				tfd = open(tf, flags, FileMode);
141#endif /* _FFR_QUEUE_FILE_MODE */
142
143				if (tfd < 0)
144				{
145					if (errno != EEXIST)
146						break;
147					if (LogLevel > 0 && (i % 32) == 0)
148						sm_syslog(LOG_ALERT, e->e_id,
149							  "queueup: cannot create %s, uid=%d: %s",
150							  tf, geteuid(), errstring(errno));
151				}
152			}
153			if (tfd >= 0)
154			{
155				if (lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB))
156					break;
157				else if (LogLevel > 0 && (i % 32) == 0)
158					sm_syslog(LOG_ALERT, e->e_id,
159						  "queueup: cannot lock %s: %s",
160						  tf, errstring(errno));
161				if ((i % 32) == 31)
162				{
163					(void) close(tfd);
164					tfd = -1;
165				}
166			}
167
168			if ((i % 32) == 31)
169			{
170				/* save the old temp file away */
171				(void) rename(tf, queuename(e, TEMPQF_LETTER));
172			}
173			else
174				(void) sleep(i % 32);
175		}
176		if (tfd < 0 || (tfp = fdopen(tfd, "w")) == NULL)
177		{
178			int save_errno = errno;
179
180			printopenfds(TRUE);
181			errno = save_errno;
182			syserr("!queueup: cannot create queue temp file %s, uid=%d",
183				tf, geteuid());
184		}
185	}
186
187	if (tTd(40, 1))
188		dprintf("\n>>>>> queueing %s/qf%s%s >>>>>\n",
189			qid_printqueue(e->e_queuedir), e->e_id,
190			newid ? " (new id)" : "");
191	if (tTd(40, 3))
192	{
193		dprintf("  e_flags=");
194		printenvflags(e);
195	}
196	if (tTd(40, 32))
197	{
198		dprintf("  sendq=");
199		printaddr(e->e_sendqueue, TRUE);
200	}
201	if (tTd(40, 9))
202	{
203		dprintf("  tfp=");
204		dumpfd(fileno(tfp), TRUE, FALSE);
205		dprintf("  lockfp=");
206		if (e->e_lockfp == NULL)
207			dprintf("NULL\n");
208		else
209			dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
210	}
211
212	/*
213	**  If there is no data file yet, create one.
214	*/
215
216	if (bitset(EF_HAS_DF, e->e_flags))
217	{
218		if (e->e_dfp != NULL && bfcommit(e->e_dfp) < 0)
219			syserr("!queueup: cannot commit data file %s, uid=%d",
220				queuename(e, 'd'), geteuid());
221	}
222	else
223	{
224		int dfd;
225		register FILE *dfp = NULL;
226		char dfname[MAXPATHLEN];
227		struct stat stbuf;
228
229		if (e->e_dfp != NULL && bftest(e->e_dfp))
230			syserr("committing over bf file");
231
232		(void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname);
233#if _FFR_QUEUE_FILE_MODE
234		{
235			MODE_T oldumask;
236
237			if (bitset(S_IWGRP, QueueFileMode))
238				oldumask = umask(002);
239			dfd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC,
240				   QueueFileMode);
241			if (bitset(S_IWGRP, QueueFileMode))
242				(void) umask(oldumask);
243		}
244#else /* _FFR_QUEUE_FILE_MODE */
245		dfd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode);
246#endif /* _FFR_QUEUE_FILE_MODE */
247		if (dfd < 0 || (dfp = fdopen(dfd, "w")) == NULL)
248			syserr("!queueup: cannot create data temp file %s, uid=%d",
249				dfname, geteuid());
250		if (fstat(dfd, &stbuf) < 0)
251			e->e_dfino = -1;
252		else
253		{
254			e->e_dfdev = stbuf.st_dev;
255			e->e_dfino = stbuf.st_ino;
256		}
257		e->e_flags |= EF_HAS_DF;
258		memset(&mcibuf, '\0', sizeof mcibuf);
259		mcibuf.mci_out = dfp;
260		mcibuf.mci_mailer = FileMailer;
261		(*e->e_putbody)(&mcibuf, e, NULL);
262		if (fclose(dfp) < 0)
263			syserr("!queueup: cannot save data temp file %s, uid=%d",
264				dfname, geteuid());
265		e->e_putbody = putbody;
266	}
267
268	/*
269	**  Output future work requests.
270	**	Priority and creation time should be first, since
271	**	they are required by orderq.
272	*/
273
274	/* output queue version number (must be first!) */
275	fprintf(tfp, "V%d\n", QF_VERSION);
276
277	/* output creation time */
278	fprintf(tfp, "T%ld\n", (long) e->e_ctime);
279
280	/* output last delivery time */
281# if _FFR_QUEUEDELAY
282	fprintf(tfp, "K%ld\n", (long) e->e_dtime);
283	fprintf(tfp, "G%d\n", e->e_queuealg);
284	fprintf(tfp, "Y%ld\n", (long) e->e_queuedelay);
285	if (tTd(40, 64))
286		sm_syslog(LOG_INFO, e->e_id,
287			"queue alg: %d delay %ld next: %ld (now: %ld)\n",
288			e->e_queuealg, e->e_queuedelay, e->e_dtime, curtime());
289# else /* _FFR_QUEUEDELAY */
290	fprintf(tfp, "K%ld\n", (long) e->e_dtime);
291# endif /* _FFR_QUEUEDELAY */
292
293	/* output number of delivery attempts */
294	fprintf(tfp, "N%d\n", e->e_ntries);
295
296	/* output message priority */
297	fprintf(tfp, "P%ld\n", e->e_msgpriority);
298
299	/* output inode number of data file */
300	/* XXX should probably include device major/minor too */
301	if (e->e_dfino != -1)
302	{
303		/*CONSTCOND*/
304		if (sizeof e->e_dfino > sizeof(long))
305			fprintf(tfp, "I%ld/%ld/%s\n",
306				(long) major(e->e_dfdev),
307				(long) minor(e->e_dfdev),
308				quad_to_string(e->e_dfino));
309		else
310			fprintf(tfp, "I%ld/%ld/%lu\n",
311				(long) major(e->e_dfdev),
312				(long) minor(e->e_dfdev),
313				(unsigned long) e->e_dfino);
314	}
315
316	/* output body type */
317	if (e->e_bodytype != NULL)
318		fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE));
319
320# if _FFR_SAVE_CHARSET
321	if (e->e_charset != NULL)
322		fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE));
323# endif /* _FFR_SAVE_CHARSET */
324
325	/* message from envelope, if it exists */
326	if (e->e_message != NULL)
327		fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE));
328
329	/* send various flag bits through */
330	p = buf;
331	if (bitset(EF_WARNING, e->e_flags))
332		*p++ = 'w';
333	if (bitset(EF_RESPONSE, e->e_flags))
334		*p++ = 'r';
335	if (bitset(EF_HAS8BIT, e->e_flags))
336		*p++ = '8';
337	if (bitset(EF_DELETE_BCC, e->e_flags))
338		*p++ = 'b';
339	if (bitset(EF_RET_PARAM, e->e_flags))
340		*p++ = 'd';
341	if (bitset(EF_NO_BODY_RETN, e->e_flags))
342		*p++ = 'n';
343	*p++ = '\0';
344	if (buf[0] != '\0')
345		fprintf(tfp, "F%s\n", buf);
346
347	/* save $={persistentMacros} macro values */
348	queueup_macros(macid("{persistentMacros}", NULL), tfp, e);
349
350	/* output name of sender */
351	if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
352		p = e->e_sender;
353	else
354		p = e->e_from.q_paddr;
355	fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE));
356
357	/* output ESMTP-supplied "original" information */
358	if (e->e_envid != NULL)
359		fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE));
360
361	/* output AUTH= parameter */
362	if (e->e_auth_param != NULL)
363		fprintf(tfp, "A%s\n", denlstring(e->e_auth_param,
364						 TRUE, FALSE));
365
366	/* output list of recipient addresses */
367	printctladdr(NULL, NULL);
368	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
369	{
370		if (!QS_IS_UNDELIVERED(q->q_state))
371			continue;
372
373		printctladdr(q, tfp);
374		if (q->q_orcpt != NULL)
375			fprintf(tfp, "Q%s\n",
376				denlstring(q->q_orcpt, TRUE, FALSE));
377		(void) putc('R', tfp);
378		if (bitset(QPRIMARY, q->q_flags))
379			(void) putc('P', tfp);
380		if (bitset(QHASNOTIFY, q->q_flags))
381			(void) putc('N', tfp);
382		if (bitset(QPINGONSUCCESS, q->q_flags))
383			(void) putc('S', tfp);
384		if (bitset(QPINGONFAILURE, q->q_flags))
385			(void) putc('F', tfp);
386		if (bitset(QPINGONDELAY, q->q_flags))
387			(void) putc('D', tfp);
388		if (q->q_alias != NULL &&
389		    bitset(QALIAS, q->q_alias->q_flags))
390			(void) putc('A', tfp);
391		(void) putc(':', tfp);
392		(void) fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
393		if (announce)
394		{
395			e->e_to = q->q_paddr;
396			message("queued");
397			if (LogLevel > 8)
398				logdelivery(q->q_mailer, NULL, q->q_status,
399					    "queued", NULL, (time_t) 0, e);
400			e->e_to = NULL;
401		}
402		if (tTd(40, 1))
403		{
404			dprintf("queueing ");
405			printaddr(q, FALSE);
406		}
407	}
408
409	/*
410	**  Output headers for this message.
411	**	Expand macros completely here.  Queue run will deal with
412	**	everything as absolute headers.
413	**		All headers that must be relative to the recipient
414	**		can be cracked later.
415	**	We set up a "null mailer" -- i.e., a mailer that will have
416	**	no effect on the addresses as they are output.
417	*/
418
419	memset((char *) &nullmailer, '\0', sizeof nullmailer);
420	nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
421			nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
422	nullmailer.m_eol = "\n";
423	memset(&mcibuf, '\0', sizeof mcibuf);
424	mcibuf.mci_mailer = &nullmailer;
425	mcibuf.mci_out = tfp;
426
427	define('g', "\201f", e);
428	for (h = e->e_header; h != NULL; h = h->h_link)
429	{
430		if (h->h_value == NULL)
431			continue;
432
433		/* don't output resent headers on non-resent messages */
434		if (bitset(H_RESENT, h->h_flags) &&
435		    !bitset(EF_RESENT, e->e_flags))
436			continue;
437
438		/* expand macros; if null, don't output header at all */
439		if (bitset(H_DEFAULT, h->h_flags))
440		{
441			(void) expand(h->h_value, buf, sizeof buf, e);
442			if (buf[0] == '\0')
443				continue;
444		}
445
446		/* output this header */
447		fprintf(tfp, "H?");
448
449		/* output conditional macro if present */
450		if (h->h_macro != '\0')
451		{
452			if (bitset(0200, h->h_macro))
453				fprintf(tfp, "${%s}",
454					macname(bitidx(h->h_macro)));
455			else
456				fprintf(tfp, "$%c", h->h_macro);
457		}
458		else if (!bitzerop(h->h_mflags) &&
459			 bitset(H_CHECK|H_ACHECK, h->h_flags))
460		{
461			int j;
462
463			/* if conditional, output the set of conditions */
464			for (j = '\0'; j <= '\177'; j++)
465				if (bitnset(j, h->h_mflags))
466					(void) putc(j, tfp);
467		}
468		(void) putc('?', tfp);
469
470		/* output the header: expand macros, convert addresses */
471		if (bitset(H_DEFAULT, h->h_flags) &&
472		    !bitset(H_BINDLATE, h->h_flags))
473		{
474			fprintf(tfp, "%s: %s\n",
475				h->h_field,
476				denlstring(buf, FALSE, TRUE));
477		}
478		else if (bitset(H_FROM|H_RCPT, h->h_flags) &&
479			 !bitset(H_BINDLATE, h->h_flags))
480		{
481			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
482			FILE *savetrace = TrafficLogFile;
483
484			TrafficLogFile = NULL;
485
486			if (bitset(H_FROM, h->h_flags))
487				oldstyle = FALSE;
488
489			commaize(h, h->h_value, oldstyle, &mcibuf, e);
490
491			TrafficLogFile = savetrace;
492		}
493		else
494		{
495			fprintf(tfp, "%s: %s\n",
496				h->h_field,
497				denlstring(h->h_value, FALSE, TRUE));
498		}
499	}
500
501	/*
502	**  Clean up.
503	**
504	**	Write a terminator record -- this is to prevent
505	**	scurrilous crackers from appending any data.
506	*/
507
508	fprintf(tfp, ".\n");
509
510	if (fflush(tfp) < 0 ||
511	    (SuperSafe && fsync(fileno(tfp)) < 0) ||
512	    ferror(tfp))
513	{
514		if (newid)
515			syserr("!552 Error writing control file %s", tf);
516		else
517			syserr("!452 Error writing control file %s", tf);
518	}
519
520	if (!newid)
521	{
522		/* rename (locked) tf to be (locked) qf */
523		qf = queuename(e, 'q');
524		if (rename(tf, qf) < 0)
525			syserr("cannot rename(%s, %s), uid=%d",
526				tf, qf, geteuid());
527		/*
528		**  fsync() after renaming to make sure
529		**  metadata is written to disk on
530		**  filesystems in which renames are
531		**  not guaranteed such as softupdates.
532		*/
533
534		if (tfd >= 0 && SuperSafe && fsync(tfd) < 0)
535			syserr("!queueup: cannot fsync queue temp file %s", tf);
536
537		/* close and unlock old (locked) qf */
538		if (e->e_lockfp != NULL)
539			(void) fclose(e->e_lockfp);
540		e->e_lockfp = tfp;
541	}
542	else
543		qf = tf;
544	errno = 0;
545	e->e_flags |= EF_INQUEUE;
546
547	/* save log info */
548	if (LogLevel > 79)
549		sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf);
550
551	if (tTd(40, 1))
552		dprintf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
553	return;
554}
555
556static void
557printctladdr(a, tfp)
558	register ADDRESS *a;
559	FILE *tfp;
560{
561	char *user;
562	register ADDRESS *q;
563	uid_t uid;
564	gid_t gid;
565	static ADDRESS *lastctladdr = NULL;
566	static uid_t lastuid;
567
568	/* initialization */
569	if (a == NULL || a->q_alias == NULL || tfp == NULL)
570	{
571		if (lastctladdr != NULL && tfp != NULL)
572			fprintf(tfp, "C\n");
573		lastctladdr = NULL;
574		lastuid = 0;
575		return;
576	}
577
578	/* find the active uid */
579	q = getctladdr(a);
580	if (q == NULL)
581	{
582		user = NULL;
583		uid = 0;
584		gid = 0;
585	}
586	else
587	{
588		user = q->q_ruser != NULL ? q->q_ruser : q->q_user;
589		uid = q->q_uid;
590		gid = q->q_gid;
591	}
592	a = a->q_alias;
593
594	/* check to see if this is the same as last time */
595	if (lastctladdr != NULL && uid == lastuid &&
596	    strcmp(lastctladdr->q_paddr, a->q_paddr) == 0)
597		return;
598	lastuid = uid;
599	lastctladdr = a;
600
601	if (uid == 0 || user == NULL || user[0] == '\0')
602		fprintf(tfp, "C");
603	else
604		fprintf(tfp, "C%s:%ld:%ld",
605			denlstring(user, TRUE, FALSE), (long) uid, (long) gid);
606	fprintf(tfp, ":%s\n", denlstring(a->q_paddr, TRUE, FALSE));
607}
608/*
609**  RUNQUEUE -- run the jobs in the queue.
610**
611**	Gets the stuff out of the queue in some presumably logical
612**	order and processes them.
613**
614**	Parameters:
615**		forkflag -- TRUE if the queue scanning should be done in
616**			a child process.  We double-fork so it is not our
617**			child and we don't have to clean up after it.
618**			FALSE can be ignored if we have multiple queues.
619**		verbose -- if TRUE, print out status information.
620**
621**	Returns:
622**		TRUE if the queue run successfully began.
623**
624**	Side Effects:
625**		runs things in the mail queue.
626*/
627
628static ENVELOPE	QueueEnvelope;		/* the queue run envelope */
629int		NumQueues = 0;		/* number of queues */
630static time_t	LastQueueTime = 0;	/* last time a queue ID assigned */
631static pid_t	LastQueuePid = -1;	/* last PID which had a queue ID */
632
633struct qpaths_s
634{
635	char	*qp_name;	/* name of queue dir */
636	short	qp_subdirs;	/* use subdirs? */
637};
638
639typedef struct qpaths_s QPATHS;
640
641/* values for qp_supdirs */
642#define QP_NOSUB	0x0000	/* No subdirectories */
643#define QP_SUBDF	0x0001	/* "df" subdirectory */
644#define QP_SUBQF	0x0002	/* "qf" subdirectory */
645#define QP_SUBXF	0x0004	/* "xf" subdirectory */
646
647static QPATHS	*QPaths = NULL;		/* list of queue directories */
648
649bool
650runqueue(forkflag, verbose)
651	bool forkflag;
652	bool verbose;
653{
654	int i;
655	bool ret = TRUE;
656	static int curnum = 0;
657
658	DoQueueRun = FALSE;
659
660
661	if (!forkflag && NumQueues > 1 && !verbose)
662		forkflag = TRUE;
663
664	for (i = 0; i < NumQueues; i++)
665	{
666		/*
667		**  Pick up where we left off, in case we
668		**  used up all the children last time
669		**  without finishing.
670		*/
671
672		ret = run_single_queue(curnum, forkflag, verbose);
673
674		/*
675		**  Failure means a message was printed for ETRN
676		**  and subsequent queues are likely to fail as well.
677		*/
678
679		if (!ret)
680			break;
681
682		if (++curnum >= NumQueues)
683			curnum = 0;
684	}
685	if (QueueIntvl != 0)
686		(void) setevent(QueueIntvl, runqueueevent, 0);
687	return ret;
688}
689/*
690**  RUN_SINGLE_QUEUE -- run the jobs in a single queue.
691**
692**	Gets the stuff out of the queue in some presumably logical
693**	order and processes them.
694**
695**	Parameters:
696**		queuedir -- queue to process
697**		forkflag -- TRUE if the queue scanning should be done in
698**			a child process.  We double-fork so it is not our
699**			child and we don't have to clean up after it.
700**		verbose -- if TRUE, print out status information.
701**
702**	Returns:
703**		TRUE if the queue run successfully began.
704**
705**	Side Effects:
706**		runs things in the mail queue.
707*/
708
709static bool
710run_single_queue(queuedir, forkflag, verbose)
711	int queuedir;
712	bool forkflag;
713	bool verbose;
714{
715	register ENVELOPE *e;
716	int njobs;
717	int sequenceno = 0;
718	time_t current_la_time, now;
719	extern ENVELOPE BlankEnvelope;
720
721	/*
722	**  If no work will ever be selected, don't even bother reading
723	**  the queue.
724	*/
725
726	CurrentLA = sm_getla(NULL);	/* get load average */
727	current_la_time = curtime();
728
729	if (shouldqueue(WkRecipFact, current_la_time))
730	{
731		char *msg = "Skipping queue run -- load average too high";
732
733		if (verbose)
734			message("458 %s\n", msg);
735		if (LogLevel > 8)
736			sm_syslog(LOG_INFO, NOQID,
737				  "runqueue: %s",
738				  msg);
739		return FALSE;
740	}
741
742	/*
743	**  See if we already have too many children.
744	*/
745
746	if (forkflag && QueueIntvl != 0 &&
747	    MaxChildren > 0 && CurChildren >= MaxChildren)
748	{
749		char *msg = "Skipping queue run -- too many children";
750
751		if (verbose)
752			message("458 %s (%d)\n", msg, CurChildren);
753		if (LogLevel > 8)
754			sm_syslog(LOG_INFO, NOQID,
755				  "runqueue: %s (%d)",
756				  msg, CurChildren);
757		return FALSE;
758	}
759
760	/*
761	**  See if we want to go off and do other useful work.
762	*/
763
764	if (forkflag)
765	{
766		pid_t pid;
767
768		(void) blocksignal(SIGCHLD);
769		(void) setsignal(SIGCHLD, reapchild);
770
771		pid = dofork();
772		if (pid == -1)
773		{
774			const char *msg = "Skipping queue run -- fork() failed";
775			const char *err = errstring(errno);
776
777			if (verbose)
778				message("458 %s: %s\n", msg, err);
779			if (LogLevel > 8)
780				sm_syslog(LOG_INFO, NOQID,
781					  "runqueue: %s: %s",
782					  msg, err);
783			(void) releasesignal(SIGCHLD);
784			return FALSE;
785		}
786		if (pid != 0)
787		{
788			/* parent -- pick up intermediate zombie */
789			(void) blocksignal(SIGALRM);
790			proc_list_add(pid, "Queue runner", PROC_QUEUE);
791			(void) releasesignal(SIGALRM);
792			(void) releasesignal(SIGCHLD);
793			return TRUE;
794		}
795		/* child -- clean up signals */
796		clrcontrol();
797		proc_list_clear();
798
799		/* Add parent process as first child item */
800		proc_list_add(getpid(), "Queue runner child process",
801			      PROC_QUEUE_CHILD);
802		(void) releasesignal(SIGCHLD);
803		(void) setsignal(SIGCHLD, SIG_DFL);
804		(void) setsignal(SIGHUP, intsig);
805
806	}
807
808	sm_setproctitle(TRUE, CurEnv, "running queue: %s",
809			qid_printqueue(queuedir));
810
811	if (LogLevel > 69 || tTd(63, 99))
812		sm_syslog(LOG_DEBUG, NOQID,
813			  "runqueue %s, pid=%d, forkflag=%d",
814			  qid_printqueue(queuedir), getpid(), forkflag);
815
816	/*
817	**  Release any resources used by the daemon code.
818	*/
819
820# if DAEMON
821	clrdaemon();
822# endif /* DAEMON */
823
824	/* force it to run expensive jobs */
825	NoConnect = FALSE;
826
827	/* drop privileges */
828	if (geteuid() == (uid_t) 0)
829		(void) drop_privileges(FALSE);
830
831	/*
832	**  Create ourselves an envelope
833	*/
834
835	CurEnv = &QueueEnvelope;
836	e = newenvelope(&QueueEnvelope, CurEnv);
837	e->e_flags = BlankEnvelope.e_flags;
838
839	/* make sure we have disconnected from parent */
840	if (forkflag)
841	{
842		disconnect(1, e);
843		QuickAbort = FALSE;
844	}
845
846	/*
847	**  If we are running part of the queue, always ignore stored
848	**  host status.
849	*/
850
851	if (QueueLimitId != NULL || QueueLimitSender != NULL ||
852	    QueueLimitRecipient != NULL)
853	{
854		IgnoreHostStatus = TRUE;
855		MinQueueAge = 0;
856	}
857
858	/*
859	**  Start making passes through the queue.
860	**	First, read and sort the entire queue.
861	**	Then, process the work in that order.
862	**		But if you take too long, start over.
863	*/
864
865	/* order the existing work requests */
866	njobs = orderq(queuedir, FALSE);
867
868
869	/* process them once at a time */
870	while (WorkQ != NULL)
871	{
872		WORK *w = WorkQ;
873
874		WorkQ = WorkQ->w_next;
875		e->e_to = NULL;
876
877		/*
878		**  Ignore jobs that are too expensive for the moment.
879		**
880		**	Get new load average every 30 seconds.
881		*/
882
883		now = curtime();
884		if (current_la_time < now - 30)
885		{
886			CurrentLA = sm_getla(e);
887			current_la_time = now;
888		}
889		if (shouldqueue(WkRecipFact, current_la_time))
890		{
891			char *msg = "Aborting queue run: load average too high";
892
893			if (Verbose)
894				message("%s", msg);
895			if (LogLevel > 8)
896				sm_syslog(LOG_INFO, NOQID,
897					  "runqueue: %s",
898					  msg);
899			break;
900		}
901		sequenceno++;
902		if (shouldqueue(w->w_pri, w->w_ctime))
903		{
904			if (Verbose)
905				message("");
906			if (QueueSortOrder == QSO_BYPRIORITY)
907			{
908				if (Verbose)
909					message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue",
910						qid_printqueue(queuedir),
911						w->w_name + 2,
912						sequenceno,
913						njobs);
914				if (LogLevel > 8)
915					sm_syslog(LOG_INFO, NOQID,
916						  "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)",
917						  qid_printqueue(queuedir),
918						  w->w_name + 2,
919						  w->w_pri,
920						  CurrentLA,
921						  sequenceno,
922						  njobs);
923				break;
924			}
925			else if (Verbose)
926				message("Skipping %s/%s (sequence %d of %d)",
927					qid_printqueue(queuedir),
928					w->w_name + 2,
929					sequenceno, njobs);
930		}
931		else
932		{
933			pid_t pid;
934
935			if (Verbose)
936			{
937				message("");
938				message("Running %s/%s (sequence %d of %d)",
939					qid_printqueue(queuedir),
940					w->w_name + 2,
941					sequenceno, njobs);
942			}
943			if (tTd(63, 100))
944				sm_syslog(LOG_DEBUG, NOQID,
945					  "runqueue %s dowork(%s)",
946					  qid_printqueue(queuedir),
947					  w->w_name + 2);
948
949			pid = dowork(queuedir, w->w_name + 2,
950				     ForkQueueRuns, FALSE, e);
951			errno = 0;
952			if (pid != 0)
953				(void) waitfor(pid);
954		}
955		free(w->w_name);
956		if (w->w_host)
957			free(w->w_host);
958		free((char *) w);
959	}
960
961	/* exit without the usual cleanup */
962	e->e_id = NULL;
963	if (forkflag)
964		finis(TRUE, ExitStat);
965	/* NOTREACHED */
966	return TRUE;
967}
968
969/*
970**  RUNQUEUEEVENT -- stub for use in setevent
971*/
972
973static void
974runqueueevent()
975{
976	DoQueueRun = TRUE;
977}
978/*
979**  ORDERQ -- order the work queue.
980**
981**	Parameters:
982**		queuedir -- the index of the queue directory.
983**		doall -- if set, include everything in the queue (even
984**			the jobs that cannot be run because the load
985**			average is too high).  Otherwise, exclude those
986**			jobs.
987**
988**	Returns:
989**		The number of request in the queue (not necessarily
990**		the number of requests in WorkQ however).
991**
992**	Side Effects:
993**		Sets WorkQ to the queue of available work, in order.
994*/
995
996# define NEED_P		001
997# define NEED_T		002
998# define NEED_R		004
999# define NEED_S		010
1000# define NEED_H		020
1001
1002static WORK	*WorkList = NULL;
1003static int	WorkListSize = 0;
1004
1005static int
1006orderq(queuedir, doall)
1007	int queuedir;
1008	bool doall;
1009{
1010	register struct dirent *d;
1011	register WORK *w;
1012	register char *p;
1013	DIR *f;
1014	register int i;
1015	int wn = -1;
1016	int wc;
1017	QUEUE_CHAR *check;
1018	char qd[MAXPATHLEN];
1019	char qf[MAXPATHLEN];
1020
1021	if (queuedir == NOQDIR)
1022		(void) strlcpy(qd, ".", sizeof qd);
1023	else
1024		(void) snprintf(qd, sizeof qd, "%s%s",
1025				QPaths[queuedir].qp_name,
1026				(bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : ""));
1027
1028	if (tTd(41, 1))
1029	{
1030		dprintf("orderq:\n");
1031
1032		check = QueueLimitId;
1033		while (check != NULL)
1034		{
1035			dprintf("\tQueueLimitId = %s\n",
1036				check->queue_match);
1037			check = check->queue_next;
1038		}
1039
1040		check = QueueLimitSender;
1041		while (check != NULL)
1042		{
1043			dprintf("\tQueueLimitSender = %s\n",
1044				check->queue_match);
1045			check = check->queue_next;
1046		}
1047
1048		check = QueueLimitRecipient;
1049		while (check != NULL)
1050		{
1051			dprintf("\tQueueLimitRecipient = %s\n",
1052				check->queue_match);
1053			check = check->queue_next;
1054		}
1055	}
1056
1057	/* clear out old WorkQ */
1058	for (w = WorkQ; w != NULL; )
1059	{
1060		register WORK *nw = w->w_next;
1061
1062		WorkQ = nw;
1063		free(w->w_name);
1064		if (w->w_host != NULL)
1065			free(w->w_host);
1066		free((char *) w);
1067		w = nw;
1068	}
1069
1070	/* open the queue directory */
1071	f = opendir(qd);
1072	if (f == NULL)
1073	{
1074		syserr("orderq: cannot open \"%s\"", qid_printqueue(queuedir));
1075		return 0;
1076	}
1077
1078	/*
1079	**  Read the work directory.
1080	*/
1081
1082	while ((d = readdir(f)) != NULL)
1083	{
1084		FILE *cf;
1085		int qfver = 0;
1086		char lbuf[MAXNAME + 1];
1087		struct stat sbuf;
1088
1089		if (tTd(41, 50))
1090			dprintf("orderq: checking %s\n", d->d_name);
1091
1092		/* is this an interesting entry? */
1093		if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
1094			continue;
1095
1096		if (strlen(d->d_name) >= MAXQFNAME)
1097		{
1098			if (Verbose)
1099				printf("orderq: %s too long, %d max characters\n",
1100					d->d_name, MAXQFNAME);
1101			if (LogLevel > 0)
1102				sm_syslog(LOG_ALERT, NOQID,
1103					  "orderq: %s too long, %d max characters",
1104					  d->d_name, MAXQFNAME);
1105			continue;
1106		}
1107
1108		check = QueueLimitId;
1109		while (check != NULL)
1110		{
1111			if (strcontainedin(check->queue_match, d->d_name))
1112				break;
1113			else
1114				check = check->queue_next;
1115		}
1116		if (QueueLimitId != NULL && check == NULL)
1117			continue;
1118
1119		/* grow work list if necessary */
1120		if (++wn >= MaxQueueRun && MaxQueueRun > 0)
1121		{
1122			if (wn == MaxQueueRun && LogLevel > 0)
1123				sm_syslog(LOG_WARNING, NOQID,
1124					  "WorkList for %s maxed out at %d",
1125					  qid_printqueue(queuedir),
1126					  MaxQueueRun);
1127			continue;
1128		}
1129		if (wn >= WorkListSize)
1130		{
1131			grow_wlist(queuedir);
1132			if (wn >= WorkListSize)
1133				continue;
1134		}
1135		w = &WorkList[wn];
1136
1137		(void) snprintf(qf, sizeof qf, "%s/%s", qd, d->d_name);
1138		if (stat(qf, &sbuf) < 0)
1139		{
1140			if (errno != ENOENT)
1141				sm_syslog(LOG_INFO, NOQID,
1142					  "orderq: can't stat %s/%s",
1143					  qid_printqueue(queuedir), d->d_name);
1144			wn--;
1145			continue;
1146		}
1147		if (!bitset(S_IFREG, sbuf.st_mode))
1148		{
1149			/* Yikes!  Skip it or we will hang on open! */
1150			syserr("orderq: %s/%s is not a regular file",
1151			       qid_printqueue(queuedir), d->d_name);
1152			wn--;
1153			continue;
1154		}
1155
1156		/* avoid work if possible */
1157		if (QueueSortOrder == QSO_BYFILENAME &&
1158		    QueueLimitSender == NULL &&
1159		    QueueLimitRecipient == NULL)
1160		{
1161			w->w_name = newstr(d->d_name);
1162			w->w_host = NULL;
1163			w->w_lock = w->w_tooyoung = FALSE;
1164			w->w_pri = 0;
1165			w->w_ctime = 0;
1166			continue;
1167		}
1168
1169		/* open control file */
1170		cf = fopen(qf, "r");
1171
1172		if (cf == NULL)
1173		{
1174			/* this may be some random person sending hir msgs */
1175			/* syserr("orderq: cannot open %s", cbuf); */
1176			if (tTd(41, 2))
1177				dprintf("orderq: cannot open %s: %s\n",
1178					d->d_name, errstring(errno));
1179			errno = 0;
1180			wn--;
1181			continue;
1182		}
1183		w->w_name = newstr(d->d_name);
1184		w->w_host = NULL;
1185		w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB);
1186		w->w_tooyoung = FALSE;
1187
1188		/* make sure jobs in creation don't clog queue */
1189		w->w_pri = 0x7fffffff;
1190		w->w_ctime = 0;
1191
1192		/* extract useful information */
1193		i = NEED_P | NEED_T;
1194		if (QueueSortOrder == QSO_BYHOST)
1195		{
1196			/* need w_host set for host sort order */
1197			i |= NEED_H;
1198		}
1199		if (QueueLimitSender != NULL)
1200			i |= NEED_S;
1201		if (QueueLimitRecipient != NULL)
1202			i |= NEED_R;
1203		while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
1204		{
1205			int c;
1206			time_t age;
1207
1208			p = strchr(lbuf, '\n');
1209			if (p != NULL)
1210				*p = '\0';
1211			else
1212			{
1213				/* flush rest of overly long line */
1214				while ((c = getc(cf)) != EOF && c != '\n')
1215					continue;
1216			}
1217
1218			switch (lbuf[0])
1219			{
1220			  case 'V':
1221				qfver = atoi(&lbuf[1]);
1222				break;
1223
1224			  case 'P':
1225				w->w_pri = atol(&lbuf[1]);
1226				i &= ~NEED_P;
1227				break;
1228
1229			  case 'T':
1230				w->w_ctime = atol(&lbuf[1]);
1231				i &= ~NEED_T;
1232				break;
1233
1234			  case 'R':
1235				if (w->w_host == NULL &&
1236				    (p = strrchr(&lbuf[1], '@')) != NULL)
1237				{
1238					w->w_host = strrev(&p[1]);
1239					makelower(w->w_host);
1240					i &= ~NEED_H;
1241				}
1242				if (QueueLimitRecipient == NULL)
1243				{
1244					i &= ~NEED_R;
1245					break;
1246				}
1247				if (qfver > 0)
1248				{
1249					p = strchr(&lbuf[1], ':');
1250					if (p == NULL)
1251						p = &lbuf[1];
1252				}
1253				else
1254					p = &lbuf[1];
1255				check = QueueLimitRecipient;
1256				while (check != NULL)
1257				{
1258					if (strcontainedin(check->queue_match,
1259							   p))
1260						break;
1261					else
1262						check = check->queue_next;
1263				}
1264				if (check != NULL)
1265					i &= ~NEED_R;
1266				break;
1267
1268			  case 'S':
1269				check = QueueLimitSender;
1270				while (check != NULL)
1271				{
1272					if (strcontainedin(check->queue_match,
1273							   &lbuf[1]))
1274						break;
1275					else
1276						check = check->queue_next;
1277				}
1278				if (check != NULL)
1279					i &= ~NEED_S;
1280				break;
1281
1282			  case 'K':
1283				age = curtime() - (time_t) atol(&lbuf[1]);
1284				if (age >= 0 && MinQueueAge > 0 &&
1285				    age < MinQueueAge)
1286					w->w_tooyoung = TRUE;
1287				break;
1288
1289			  case 'N':
1290				if (atol(&lbuf[1]) == 0)
1291					w->w_tooyoung = FALSE;
1292				break;
1293
1294# if _FFR_QUEUEDELAY
1295/*
1296			  case 'G':
1297				queuealg = atoi(lbuf[1]);
1298				break;
1299			  case 'Y':
1300				queuedelay = (time_t) atol(&lbuf[1]);
1301				break;
1302*/
1303# endif /* _FFR_QUEUEDELAY */
1304			}
1305		}
1306		(void) fclose(cf);
1307
1308		if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
1309		    bitset(NEED_R|NEED_S, i))
1310		{
1311			/* don't even bother sorting this job in */
1312			if (tTd(41, 49))
1313				dprintf("skipping %s (%x)\n", w->w_name, i);
1314			free(w->w_name);
1315			if (w->w_host)
1316				free(w->w_host);
1317			wn--;
1318		}
1319	}
1320	(void) closedir(f);
1321	wn++;
1322
1323	WorkQ = NULL;
1324	if (WorkList == NULL)
1325		return 0;
1326	wc = min(wn, WorkListSize);
1327	if (wc > MaxQueueRun && MaxQueueRun > 0)
1328		wc = MaxQueueRun;
1329
1330	if (QueueSortOrder == QSO_BYHOST)
1331	{
1332		/*
1333		**  Sort the work directory for the first time,
1334		**  based on host name, lock status, and priority.
1335		*/
1336
1337		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1);
1338
1339		/*
1340		**  If one message to host is locked, "lock" all messages
1341		**  to that host.
1342		*/
1343
1344		i = 0;
1345		while (i < wc)
1346		{
1347			if (!WorkList[i].w_lock)
1348			{
1349				i++;
1350				continue;
1351			}
1352			w = &WorkList[i];
1353			while (++i < wc)
1354			{
1355				if (WorkList[i].w_host == NULL &&
1356				    w->w_host == NULL)
1357					WorkList[i].w_lock = TRUE;
1358				else if (WorkList[i].w_host != NULL &&
1359					 w->w_host != NULL &&
1360					 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0)
1361					WorkList[i].w_lock = TRUE;
1362				else
1363					break;
1364			}
1365		}
1366
1367		/*
1368		**  Sort the work directory for the second time,
1369		**  based on lock status, host name, and priority.
1370		*/
1371
1372		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
1373	}
1374	else if (QueueSortOrder == QSO_BYTIME)
1375	{
1376		/*
1377		**  Simple sort based on submission time only.
1378		*/
1379
1380		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
1381	}
1382	else if (QueueSortOrder == QSO_BYFILENAME)
1383	{
1384		/*
1385		**  Sort based on qf filename.
1386		*/
1387
1388		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4);
1389	}
1390	else
1391	{
1392		/*
1393		**  Simple sort based on queue priority only.
1394		*/
1395
1396		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
1397	}
1398
1399	/*
1400	**  Convert the work list into canonical form.
1401	**	Should be turning it into a list of envelopes here perhaps.
1402	*/
1403
1404	for (i = wc; --i >= 0; )
1405	{
1406		w = (WORK *) xalloc(sizeof *w);
1407		w->w_name = WorkList[i].w_name;
1408		w->w_host = WorkList[i].w_host;
1409		w->w_lock = WorkList[i].w_lock;
1410		w->w_tooyoung = WorkList[i].w_tooyoung;
1411		w->w_pri = WorkList[i].w_pri;
1412		w->w_ctime = WorkList[i].w_ctime;
1413		w->w_next = WorkQ;
1414		WorkQ = w;
1415	}
1416	if (WorkList != NULL)
1417		free(WorkList);
1418	WorkList = NULL;
1419	WorkListSize = 0;
1420
1421	if (tTd(40, 1))
1422	{
1423		for (w = WorkQ; w != NULL; w = w->w_next)
1424		{
1425			if (w->w_host != NULL)
1426				dprintf("%22s: pri=%ld %s\n",
1427					w->w_name, w->w_pri, w->w_host);
1428			else
1429				dprintf("%32s: pri=%ld\n",
1430					w->w_name, w->w_pri);
1431		}
1432	}
1433
1434	return wn;
1435}
1436/*
1437**  GROW_WLIST -- make the work list larger
1438**
1439**	Parameters:
1440**		queuedir -- the index for the queue directory.
1441**
1442**	Returns:
1443**		none.
1444**
1445**	Side Effects:
1446**		Adds another QUEUESEGSIZE entries to WorkList if possible.
1447**		It can fail if there isn't enough memory, so WorkListSize
1448**		should be checked again upon return.
1449*/
1450
1451static void
1452grow_wlist(queuedir)
1453	int queuedir;
1454{
1455	if (tTd(41, 1))
1456		dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize);
1457	if (WorkList == NULL)
1458	{
1459		WorkList = (WORK *) xalloc((sizeof *WorkList) *
1460					   (QUEUESEGSIZE + 1));
1461		WorkListSize = QUEUESEGSIZE;
1462	}
1463	else
1464	{
1465		int newsize = WorkListSize + QUEUESEGSIZE;
1466		WORK *newlist = (WORK *) realloc((char *)WorkList,
1467					  (unsigned)sizeof(WORK) * (newsize + 1));
1468
1469		if (newlist != NULL)
1470		{
1471			WorkListSize = newsize;
1472			WorkList = newlist;
1473			if (LogLevel > 1)
1474			{
1475				sm_syslog(LOG_INFO, NOQID,
1476					  "grew WorkList for %s to %d",
1477					  qid_printqueue(queuedir),
1478					  WorkListSize);
1479			}
1480		}
1481		else if (LogLevel > 0)
1482		{
1483			sm_syslog(LOG_ALERT, NOQID,
1484				  "FAILED to grow WorkList for %s to %d",
1485				  qid_printqueue(queuedir), newsize);
1486		}
1487	}
1488	if (tTd(41, 1))
1489		dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize);
1490}
1491/*
1492**  WORKCMPF0 -- simple priority-only compare function.
1493**
1494**	Parameters:
1495**		a -- the first argument.
1496**		b -- the second argument.
1497**
1498**	Returns:
1499**		-1 if a < b
1500**		 0 if a == b
1501**		+1 if a > b
1502**
1503**	Side Effects:
1504**		none.
1505*/
1506
1507static int
1508workcmpf0(a, b)
1509	register WORK *a;
1510	register WORK *b;
1511{
1512	long pa = a->w_pri;
1513	long pb = b->w_pri;
1514
1515	if (pa == pb)
1516		return 0;
1517	else if (pa > pb)
1518		return 1;
1519	else
1520		return -1;
1521}
1522/*
1523**  WORKCMPF1 -- first compare function for ordering work based on host name.
1524**
1525**	Sorts on host name, lock status, and priority in that order.
1526**
1527**	Parameters:
1528**		a -- the first argument.
1529**		b -- the second argument.
1530**
1531**	Returns:
1532**		<0 if a < b
1533**		 0 if a == b
1534**		>0 if a > b
1535**
1536**	Side Effects:
1537**		none.
1538*/
1539
1540static int
1541workcmpf1(a, b)
1542	register WORK *a;
1543	register WORK *b;
1544{
1545	int i;
1546
1547	/* host name */
1548	if (a->w_host != NULL && b->w_host == NULL)
1549		return 1;
1550	else if (a->w_host == NULL && b->w_host != NULL)
1551		return -1;
1552	if (a->w_host != NULL && b->w_host != NULL &&
1553	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1554		return i;
1555
1556	/* lock status */
1557	if (a->w_lock != b->w_lock)
1558		return b->w_lock - a->w_lock;
1559
1560	/* job priority */
1561	return a->w_pri - b->w_pri;
1562}
1563/*
1564**  WORKCMPF2 -- second compare function for ordering work based on host name.
1565**
1566**	Sorts on lock status, host name, and priority in that order.
1567**
1568**	Parameters:
1569**		a -- the first argument.
1570**		b -- the second argument.
1571**
1572**	Returns:
1573**		<0 if a < b
1574**		 0 if a == b
1575**		>0 if a > b
1576**
1577**	Side Effects:
1578**		none.
1579*/
1580
1581static int
1582workcmpf2(a, b)
1583	register WORK *a;
1584	register WORK *b;
1585{
1586	int i;
1587
1588	/* lock status */
1589	if (a->w_lock != b->w_lock)
1590		return a->w_lock - b->w_lock;
1591
1592	/* host name */
1593	if (a->w_host != NULL && b->w_host == NULL)
1594		return 1;
1595	else if (a->w_host == NULL && b->w_host != NULL)
1596		return -1;
1597	if (a->w_host != NULL && b->w_host != NULL &&
1598	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1599		return i;
1600
1601	/* job priority */
1602	return a->w_pri - b->w_pri;
1603}
1604/*
1605**  WORKCMPF3 -- simple submission-time-only compare function.
1606**
1607**	Parameters:
1608**		a -- the first argument.
1609**		b -- the second argument.
1610**
1611**	Returns:
1612**		-1 if a < b
1613**		 0 if a == b
1614**		+1 if a > b
1615**
1616**	Side Effects:
1617**		none.
1618*/
1619
1620static int
1621workcmpf3(a, b)
1622	register WORK *a;
1623	register WORK *b;
1624{
1625	if (a->w_ctime > b->w_ctime)
1626		return 1;
1627	else if (a->w_ctime < b->w_ctime)
1628		return -1;
1629	else
1630		return 0;
1631}
1632/*
1633**  WORKCMPF4 -- compare based on file name
1634**
1635**	Parameters:
1636**		a -- the first argument.
1637**		b -- the second argument.
1638**
1639**	Returns:
1640**		-1 if a < b
1641**		 0 if a == b
1642**		+1 if a > b
1643**
1644**	Side Effects:
1645**		none.
1646*/
1647
1648static int
1649workcmpf4(a, b)
1650	register WORK *a;
1651	register WORK *b;
1652{
1653	return strcmp(a->w_name, b->w_name);
1654}
1655/*
1656**  STRREV -- reverse string
1657**
1658**	Returns a pointer to a new string that is the reverse of
1659**	the string pointed to by fwd.  The space for the new
1660**	string is obtained using xalloc().
1661**
1662**	Parameters:
1663**		fwd -- the string to reverse.
1664**
1665**	Returns:
1666**		the reversed string.
1667*/
1668
1669static char *
1670strrev(fwd)
1671	char *fwd;
1672{
1673	char *rev = NULL;
1674	int len, cnt;
1675
1676	len = strlen(fwd);
1677	rev = xalloc(len + 1);
1678	for (cnt = 0; cnt < len; ++cnt)
1679		rev[cnt] = fwd[len - cnt - 1];
1680	rev[len] = '\0';
1681	return rev;
1682}
1683/*
1684**  DOWORK -- do a work request.
1685**
1686**	Parameters:
1687**		queuedir -- the index of the queue directory for the job.
1688**		id -- the ID of the job to run.
1689**		forkflag -- if set, run this in background.
1690**		requeueflag -- if set, reinstantiate the queue quickly.
1691**			This is used when expanding aliases in the queue.
1692**			If forkflag is also set, it doesn't wait for the
1693**			child.
1694**		e - the envelope in which to run it.
1695**
1696**	Returns:
1697**		process id of process that is running the queue job.
1698**
1699**	Side Effects:
1700**		The work request is satisfied if possible.
1701*/
1702
1703pid_t
1704dowork(queuedir, id, forkflag, requeueflag, e)
1705	int queuedir;
1706	char *id;
1707	bool forkflag;
1708	bool requeueflag;
1709	register ENVELOPE *e;
1710{
1711	register pid_t pid;
1712
1713	if (tTd(40, 1))
1714		dprintf("dowork(%s/%s)\n", qid_printqueue(queuedir), id);
1715
1716	/*
1717	**  Fork for work.
1718	*/
1719
1720	if (forkflag)
1721	{
1722		/*
1723		**  Since the delivery may happen in a child and the
1724		**  parent does not wait, the parent may close the
1725		**  maps thereby removing any shared memory used by
1726		**  the map.  Therefore, close the maps now so the
1727		**  child will dynamically open them if necessary.
1728		*/
1729
1730		closemaps();
1731
1732		pid = fork();
1733		if (pid < 0)
1734		{
1735			syserr("dowork: cannot fork");
1736			return 0;
1737		}
1738		else if (pid > 0)
1739		{
1740			/* parent -- clean out connection cache */
1741			mci_flush(FALSE, NULL);
1742		}
1743		else
1744		{
1745			/* child -- error messages to the transcript */
1746			QuickAbort = OnlyOneError = FALSE;
1747		}
1748	}
1749	else
1750	{
1751		pid = 0;
1752	}
1753
1754	if (pid == 0)
1755	{
1756		/*
1757		**  CHILD
1758		**	Lock the control file to avoid duplicate deliveries.
1759		**		Then run the file as though we had just read it.
1760		**	We save an idea of the temporary name so we
1761		**		can recover on interrupt.
1762		*/
1763
1764		/* set basic modes, etc. */
1765		(void) alarm(0);
1766		clearstats();
1767		clearenvelope(e, FALSE);
1768		e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
1769		set_delivery_mode(SM_DELIVER, e);
1770		e->e_errormode = EM_MAIL;
1771		e->e_id = id;
1772		e->e_queuedir = queuedir;
1773		GrabTo = UseErrorsTo = FALSE;
1774		ExitStat = EX_OK;
1775		if (forkflag)
1776		{
1777			disconnect(1, e);
1778			OpMode = MD_QUEUERUN;
1779		}
1780		sm_setproctitle(TRUE, e, "%s: from queue", qid_printname(e));
1781		if (LogLevel > 76)
1782			sm_syslog(LOG_DEBUG, e->e_id,
1783				  "dowork, pid=%d",
1784				  getpid());
1785
1786		/* don't use the headers from sendmail.cf... */
1787		e->e_header = NULL;
1788
1789		/* read the queue control file -- return if locked */
1790		if (!readqf(e))
1791		{
1792			if (tTd(40, 4) && e->e_id != NULL)
1793				dprintf("readqf(%s) failed\n",
1794					qid_printname(e));
1795			e->e_id = NULL;
1796			if (forkflag)
1797				finis(FALSE, EX_OK);
1798			else
1799				return 0;
1800		}
1801
1802		e->e_flags |= EF_INQUEUE;
1803		eatheader(e, requeueflag);
1804
1805		if (requeueflag)
1806			queueup(e, FALSE);
1807
1808		/* do the delivery */
1809		sendall(e, SM_DELIVER);
1810
1811		/* finish up and exit */
1812		if (forkflag)
1813			finis(TRUE, ExitStat);
1814		else
1815			dropenvelope(e, TRUE);
1816	}
1817	e->e_id = NULL;
1818	return pid;
1819}
1820/*
1821**  READQF -- read queue file and set up environment.
1822**
1823**	Parameters:
1824**		e -- the envelope of the job to run.
1825**
1826**	Returns:
1827**		TRUE if it successfully read the queue file.
1828**		FALSE otherwise.
1829**
1830**	Side Effects:
1831**		The queue file is returned locked.
1832*/
1833
1834static bool
1835readqf(e)
1836	register ENVELOPE *e;
1837{
1838	register FILE *qfp;
1839	ADDRESS *ctladdr;
1840	struct stat st;
1841	char *bp;
1842	int qfver = 0;
1843	long hdrsize = 0;
1844	register char *p;
1845	char *orcpt = NULL;
1846	bool nomore = FALSE;
1847	MODE_T qsafe;
1848	char qf[MAXPATHLEN];
1849	char buf[MAXLINE];
1850
1851	/*
1852	**  Read and process the file.
1853	*/
1854
1855	(void) strlcpy(qf, queuename(e, 'q'), sizeof qf);
1856	qfp = fopen(qf, "r+");
1857	if (qfp == NULL)
1858	{
1859		int save_errno = errno;
1860
1861		if (tTd(40, 8))
1862			dprintf("readqf(%s): fopen failure (%s)\n",
1863				qf, errstring(errno));
1864		errno = save_errno;
1865		if (errno != ENOENT
1866		    )
1867			syserr("readqf: no control file %s", qf);
1868		return FALSE;
1869	}
1870
1871	if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB))
1872	{
1873		/* being processed by another queuer */
1874		if (Verbose)
1875			printf("%s: locked\n", e->e_id);
1876		if (tTd(40, 8))
1877			dprintf("%s: locked\n", e->e_id);
1878		if (LogLevel > 19)
1879			sm_syslog(LOG_DEBUG, e->e_id, "locked");
1880		(void) fclose(qfp);
1881		return FALSE;
1882	}
1883
1884	/*
1885	**  Check the queue file for plausibility to avoid attacks.
1886	*/
1887
1888	if (fstat(fileno(qfp), &st) < 0)
1889	{
1890		/* must have been being processed by someone else */
1891		if (tTd(40, 8))
1892			dprintf("readqf(%s): fstat failure (%s)\n",
1893				qf, errstring(errno));
1894		(void) fclose(qfp);
1895		return FALSE;
1896	}
1897
1898	qsafe = S_IWOTH|S_IWGRP;
1899#if _FFR_QUEUE_FILE_MODE
1900	if (bitset(S_IWGRP, QueueFileMode))
1901		qsafe &= ~S_IWGRP;
1902#endif /* _FFR_QUEUE_FILE_MODE */
1903
1904	if ((st.st_uid != geteuid() &&
1905	     st.st_uid != TrustedUid &&
1906	     geteuid() != RealUid) ||
1907	    bitset(qsafe, st.st_mode))
1908	{
1909		if (LogLevel > 0)
1910		{
1911			sm_syslog(LOG_ALERT, e->e_id,
1912				  "bogus queue file, uid=%d, mode=%o",
1913				  st.st_uid, st.st_mode);
1914		}
1915		if (tTd(40, 8))
1916			dprintf("readqf(%s): bogus file\n", qf);
1917		loseqfile(e, "bogus file uid in mqueue");
1918		(void) fclose(qfp);
1919		return FALSE;
1920	}
1921
1922	if (st.st_size == 0)
1923	{
1924		/* must be a bogus file -- if also old, just remove it */
1925		if (st.st_ctime + 10 * 60 < curtime())
1926		{
1927			(void) xunlink(queuename(e, 'd'));
1928			(void) xunlink(queuename(e, 'q'));
1929		}
1930		(void) fclose(qfp);
1931		return FALSE;
1932	}
1933
1934	if (st.st_nlink == 0)
1935	{
1936		/*
1937		**  Race condition -- we got a file just as it was being
1938		**  unlinked.  Just assume it is zero length.
1939		*/
1940
1941		(void) fclose(qfp);
1942		return FALSE;
1943	}
1944
1945	/* good file -- save this lock */
1946	e->e_lockfp = qfp;
1947
1948	/* do basic system initialization */
1949	initsys(e);
1950	define('i', e->e_id, e);
1951
1952	LineNumber = 0;
1953	e->e_flags |= EF_GLOBALERRS;
1954	OpMode = MD_QUEUERUN;
1955	ctladdr = NULL;
1956	e->e_dfino = -1;
1957	e->e_msgsize = -1;
1958# if _FFR_QUEUEDELAY
1959	e->e_queuealg = QD_LINEAR;
1960	e->e_queuedelay = (time_t) 0;
1961# endif /* _FFR_QUEUEDELAY */
1962	while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
1963	{
1964		u_long qflags;
1965		ADDRESS *q;
1966		int mid;
1967		time_t now;
1968		auto char *ep;
1969
1970		if (tTd(40, 4))
1971			dprintf("+++++ %s\n", bp);
1972		if (nomore)
1973		{
1974			/* hack attack */
1975			syserr("SECURITY ALERT: extra data in qf: %s", bp);
1976			(void) fclose(qfp);
1977			loseqfile(e, "bogus queue line");
1978			return FALSE;
1979		}
1980		switch (bp[0])
1981		{
1982		  case 'V':		/* queue file version number */
1983			qfver = atoi(&bp[1]);
1984			if (qfver <= QF_VERSION)
1985				break;
1986			syserr("Version number in qf (%d) greater than max (%d)",
1987				qfver, QF_VERSION);
1988			(void) fclose(qfp);
1989			loseqfile(e, "unsupported qf file version");
1990			return FALSE;
1991
1992		  case 'C':		/* specify controlling user */
1993			ctladdr = setctluser(&bp[1], qfver);
1994			break;
1995
1996		  case 'Q':		/* original recipient */
1997			orcpt = newstr(&bp[1]);
1998			break;
1999
2000		  case 'R':		/* specify recipient */
2001			p = bp;
2002			qflags = 0;
2003			if (qfver >= 1)
2004			{
2005				/* get flag bits */
2006				while (*++p != '\0' && *p != ':')
2007				{
2008					switch (*p)
2009					{
2010					  case 'N':
2011						qflags |= QHASNOTIFY;
2012						break;
2013
2014					  case 'S':
2015						qflags |= QPINGONSUCCESS;
2016						break;
2017
2018					  case 'F':
2019						qflags |= QPINGONFAILURE;
2020						break;
2021
2022					  case 'D':
2023						qflags |= QPINGONDELAY;
2024						break;
2025
2026					  case 'P':
2027						qflags |= QPRIMARY;
2028						break;
2029
2030					  case 'A':
2031						if (ctladdr != NULL)
2032							ctladdr->q_flags |= QALIAS;
2033						break;
2034					}
2035				}
2036			}
2037			else
2038				qflags |= QPRIMARY;
2039			q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e);
2040			if (q != NULL)
2041			{
2042				q->q_alias = ctladdr;
2043				if (qfver >= 1)
2044					q->q_flags &= ~Q_PINGFLAGS;
2045				q->q_flags |= qflags;
2046				q->q_orcpt = orcpt;
2047				(void) recipient(q, &e->e_sendqueue, 0, e);
2048			}
2049			orcpt = NULL;
2050			break;
2051
2052		  case 'E':		/* specify error recipient */
2053			/* no longer used */
2054			break;
2055
2056		  case 'H':		/* header */
2057			(void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e);
2058			hdrsize += strlen(&bp[1]);
2059			break;
2060
2061		  case 'L':		/* Solaris Content-Length: */
2062		  case 'M':		/* message */
2063			/* ignore this; we want a new message next time */
2064			break;
2065
2066		  case 'S':		/* sender */
2067			setsender(newstr(&bp[1]), e, NULL, '\0', TRUE);
2068			break;
2069
2070		  case 'B':		/* body type */
2071			e->e_bodytype = newstr(&bp[1]);
2072			break;
2073
2074# if _FFR_SAVE_CHARSET
2075		  case 'X':		/* character set */
2076			e->e_charset = newstr(&bp[1]);
2077			break;
2078# endif /* _FFR_SAVE_CHARSET */
2079
2080		  case 'D':		/* data file name */
2081			/* obsolete -- ignore */
2082			break;
2083
2084		  case 'T':		/* init time */
2085			e->e_ctime = atol(&bp[1]);
2086			break;
2087
2088		  case 'I':		/* data file's inode number */
2089			/* regenerated below */
2090			break;
2091
2092		  case 'K':	/* time of last delivery attempt */
2093			e->e_dtime = atol(&buf[1]);
2094			break;
2095
2096# if _FFR_QUEUEDELAY
2097		  case 'G':	/* queue delay algorithm */
2098			e->e_queuealg = atoi(&buf[1]);
2099			break;
2100		  case 'Y':	/* current delay */
2101			e->e_queuedelay = (time_t) atol(&buf[1]);
2102			break;
2103# endif /* _FFR_QUEUEDELAY */
2104
2105		  case 'N':		/* number of delivery attempts */
2106			e->e_ntries = atoi(&buf[1]);
2107
2108			/* if this has been tried recently, let it be */
2109			now = curtime();
2110			if (e->e_ntries > 0 && e->e_dtime <= now &&
2111			    now < e->e_dtime + queuedelay(e))
2112			{
2113				char *howlong;
2114
2115				howlong = pintvl(now - e->e_dtime, TRUE);
2116				if (Verbose)
2117					printf("%s: too young (%s)\n",
2118					       e->e_id, howlong);
2119				if (tTd(40, 8))
2120					dprintf("%s: too young (%s)\n",
2121						e->e_id, howlong);
2122				if (LogLevel > 19)
2123					sm_syslog(LOG_DEBUG, e->e_id,
2124						  "too young (%s)",
2125						  howlong);
2126				e->e_id = NULL;
2127				unlockqueue(e);
2128				return FALSE;
2129			}
2130			define(macid("{ntries}", NULL), newstr(&buf[1]), e);
2131
2132# if NAMED_BIND
2133			/* adjust BIND parameters immediately */
2134			if (e->e_ntries == 0)
2135			{
2136				_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
2137				_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
2138			}
2139			else
2140			{
2141				_res.retry = TimeOuts.res_retry[RES_TO_NORMAL];
2142				_res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL];
2143			}
2144# endif /* NAMED_BIND */
2145			break;
2146
2147		  case 'P':		/* message priority */
2148			e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
2149			break;
2150
2151		  case 'F':		/* flag bits */
2152			if (strncmp(bp, "From ", 5) == 0)
2153			{
2154				/* we are being spoofed! */
2155				syserr("SECURITY ALERT: bogus qf line %s", bp);
2156				(void) fclose(qfp);
2157				loseqfile(e, "bogus queue line");
2158				return FALSE;
2159			}
2160			for (p = &bp[1]; *p != '\0'; p++)
2161			{
2162				switch (*p)
2163				{
2164				  case 'w':	/* warning sent */
2165					e->e_flags |= EF_WARNING;
2166					break;
2167
2168				  case 'r':	/* response */
2169					e->e_flags |= EF_RESPONSE;
2170					break;
2171
2172				  case '8':	/* has 8 bit data */
2173					e->e_flags |= EF_HAS8BIT;
2174					break;
2175
2176				  case 'b':	/* delete Bcc: header */
2177					e->e_flags |= EF_DELETE_BCC;
2178					break;
2179
2180				  case 'd':	/* envelope has DSN RET= */
2181					e->e_flags |= EF_RET_PARAM;
2182					break;
2183
2184				  case 'n':	/* don't return body */
2185					e->e_flags |= EF_NO_BODY_RETN;
2186					break;
2187				}
2188			}
2189			break;
2190
2191		  case 'Z':		/* original envelope id from ESMTP */
2192			e->e_envid = newstr(&bp[1]);
2193			define(macid("{dsn_envid}", NULL), newstr(&bp[1]), e);
2194			break;
2195
2196		  case 'A':		/* AUTH= parameter */
2197			e->e_auth_param = newstr(&bp[1]);
2198			break;
2199
2200		  case '$':		/* define macro */
2201			{
2202				char *p;
2203
2204				mid = macid(&bp[1], &ep);
2205				if (mid == 0)
2206					break;
2207
2208				p = newstr(ep);
2209				define(mid, p, e);
2210
2211				/*
2212				**  HACK ALERT: Unfortunately, 8.10 and
2213				**  8.11 reused the ${if_addr} and
2214				**  ${if_family} macros for both the incoming
2215				**  interface address/family (getrequests())
2216				**  and the outgoing interface address/family
2217				**  (makeconnection()).  In order for D_BINDIF
2218				**  to work properly, have to preserve the
2219				**  incoming information in the queue file for
2220				**  later delivery attempts.  The original
2221				**  information is stored in the envelope
2222				**  in readqf() so it can be stored in
2223				**  queueup_macros().  This should be fixed
2224				**  in 8.12.
2225				*/
2226
2227				if (strcmp(macname(mid), "if_addr") == 0)
2228					e->e_if_macros[EIF_ADDR] = p;
2229			}
2230			break;
2231
2232		  case '.':		/* terminate file */
2233			nomore = TRUE;
2234			break;
2235
2236		  default:
2237			syserr("readqf: %s: line %d: bad line \"%s\"",
2238				qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
2239			(void) fclose(qfp);
2240			loseqfile(e, "unrecognized line");
2241			return FALSE;
2242		}
2243
2244		if (bp != buf)
2245			free(bp);
2246	}
2247
2248	/*
2249	**  If we haven't read any lines, this queue file is empty.
2250	**  Arrange to remove it without referencing any null pointers.
2251	*/
2252
2253	if (LineNumber == 0)
2254	{
2255		errno = 0;
2256		e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
2257		return TRUE;
2258	}
2259
2260	/* possibly set ${dsn_ret} macro */
2261	if (bitset(EF_RET_PARAM, e->e_flags))
2262	{
2263		if (bitset(EF_NO_BODY_RETN, e->e_flags))
2264			define(macid("{dsn_ret}", NULL), "hdrs", e);
2265		else
2266			define(macid("{dsn_ret}", NULL), "full", e);
2267	}
2268
2269	/*
2270	**  Arrange to read the data file.
2271	*/
2272
2273	p = queuename(e, 'd');
2274	e->e_dfp = fopen(p, "r");
2275	if (e->e_dfp == NULL)
2276	{
2277		syserr("readqf: cannot open %s", p);
2278	}
2279	else
2280	{
2281		e->e_flags |= EF_HAS_DF;
2282		if (fstat(fileno(e->e_dfp), &st) >= 0)
2283		{
2284			e->e_msgsize = st.st_size + hdrsize;
2285			e->e_dfdev = st.st_dev;
2286			e->e_dfino = st.st_ino;
2287		}
2288	}
2289
2290	return TRUE;
2291}
2292/*
2293**  PRTSTR -- print a string, "unprintable" characters are shown as \oct
2294**
2295**	Parameters:
2296**		s -- string to print
2297**		ml -- maximum length of output
2298**
2299**	Returns:
2300**		none.
2301**
2302**	Side Effects:
2303**		Prints a string on stdout.
2304*/
2305
2306static void
2307prtstr(s, ml)
2308	char *s;
2309	int ml;
2310{
2311	char c;
2312
2313	if (s == NULL)
2314		return;
2315	while (ml-- > 0 && ((c = *s++) != '\0'))
2316	{
2317		if (c == '\\')
2318		{
2319			if (ml-- > 0)
2320			{
2321				putchar(c);
2322				putchar(c);
2323			}
2324		}
2325		else if (isascii(c) && isprint(c))
2326			putchar(c);
2327		else
2328		{
2329			if ((ml -= 3) > 0)
2330				printf("\\%03o", c);
2331		}
2332	}
2333}
2334/*
2335**  PRINTQUEUE -- print out a representation of the mail queue
2336**
2337**	Parameters:
2338**		none.
2339**
2340**	Returns:
2341**		none.
2342**
2343**	Side Effects:
2344**		Prints a listing of the mail queue on the standard output.
2345*/
2346
2347void
2348printqueue()
2349{
2350	int i, nrequests = 0;
2351
2352	for (i = 0; i < NumQueues; i++)
2353		nrequests += print_single_queue(i);
2354	if (NumQueues > 1)
2355		printf("\t\tTotal Requests: %d\n", nrequests);
2356}
2357/*
2358**  PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue
2359**
2360**	Parameters:
2361**		queuedir -- queue directory
2362**
2363**	Returns:
2364**		number of entries
2365**
2366**	Side Effects:
2367**		Prints a listing of the mail queue on the standard output.
2368*/
2369
2370static int
2371print_single_queue(queuedir)
2372	int queuedir;
2373{
2374	register WORK *w;
2375	FILE *f;
2376	int nrequests;
2377	char qd[MAXPATHLEN];
2378	char qddf[MAXPATHLEN];
2379	char buf[MAXLINE];
2380
2381	if (queuedir == NOQDIR)
2382	{
2383		(void) strlcpy(qd, ".", sizeof qd);
2384		(void) strlcpy(qddf, ".", sizeof qddf);
2385	}
2386	else
2387	{
2388		(void) snprintf(qd, sizeof qd, "%s%s",
2389				QPaths[queuedir].qp_name,
2390				(bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : ""));
2391		(void) snprintf(qddf, sizeof qddf, "%s%s",
2392				QPaths[queuedir].qp_name,
2393				(bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : ""));
2394	}
2395
2396	/*
2397	**  Check for permission to print the queue
2398	*/
2399
2400	if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
2401	{
2402		struct stat st;
2403# ifdef NGROUPS_MAX
2404		int n;
2405		extern GIDSET_T InitialGidSet[NGROUPS_MAX];
2406# endif /* NGROUPS_MAX */
2407
2408		if (stat(qd, &st) < 0)
2409		{
2410			syserr("Cannot stat %s", qid_printqueue(queuedir));
2411			return 0;
2412		}
2413# ifdef NGROUPS_MAX
2414		n = NGROUPS_MAX;
2415		while (--n >= 0)
2416		{
2417			if (InitialGidSet[n] == st.st_gid)
2418				break;
2419		}
2420		if (n < 0 && RealGid != st.st_gid)
2421# else /* NGROUPS_MAX */
2422		if (RealGid != st.st_gid)
2423# endif /* NGROUPS_MAX */
2424		{
2425			usrerr("510 You are not permitted to see the queue");
2426			setstat(EX_NOPERM);
2427			return 0;
2428		}
2429	}
2430
2431	/*
2432	**  Read and order the queue.
2433	*/
2434
2435	nrequests = orderq(queuedir, TRUE);
2436
2437	/*
2438	**  Print the work list that we have read.
2439	*/
2440
2441	/* first see if there is anything */
2442	if (nrequests <= 0)
2443	{
2444		printf("%s is empty\n", qid_printqueue(queuedir));
2445		return 0;
2446	}
2447
2448	CurrentLA = sm_getla(NULL);	/* get load average */
2449
2450	printf("\t\t%s (%d request%s", qid_printqueue(queuedir), nrequests,
2451	       nrequests == 1 ? "" : "s");
2452	if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
2453		printf(", only %d printed", MaxQueueRun);
2454	if (Verbose)
2455		printf(")\n----Q-ID---- --Size-- -Priority- ---Q-Time--- ---------Sender/Recipient--------\n");
2456	else
2457		printf(")\n----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
2458	for (w = WorkQ; w != NULL; w = w->w_next)
2459	{
2460		struct stat st;
2461		auto time_t submittime = 0;
2462		long dfsize;
2463		int flags = 0;
2464		int qfver;
2465		char statmsg[MAXLINE];
2466		char bodytype[MAXNAME + 1];
2467		char qf[MAXPATHLEN];
2468
2469		printf("%12s", w->w_name + 2);
2470		(void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name);
2471		f = fopen(qf, "r");
2472		if (f == NULL)
2473		{
2474			printf(" (job completed)\n");
2475			errno = 0;
2476			continue;
2477		}
2478		w->w_name[0] = 'd';
2479		(void) snprintf(qf, sizeof qf, "%s/%s", qddf, w->w_name);
2480		if (stat(qf, &st) >= 0)
2481			dfsize = st.st_size;
2482		else
2483			dfsize = -1;
2484		if (w->w_lock)
2485			printf("*");
2486		else if (w->w_tooyoung)
2487			printf("-");
2488		else if (shouldqueue(w->w_pri, w->w_ctime))
2489			printf("X");
2490		else
2491			printf(" ");
2492		errno = 0;
2493
2494		statmsg[0] = bodytype[0] = '\0';
2495		qfver = 0;
2496		while (fgets(buf, sizeof buf, f) != NULL)
2497		{
2498			register int i;
2499			register char *p;
2500
2501			fixcrlf(buf, TRUE);
2502			switch (buf[0])
2503			{
2504			  case 'V':	/* queue file version */
2505				qfver = atoi(&buf[1]);
2506				break;
2507
2508			  case 'M':	/* error message */
2509				if ((i = strlen(&buf[1])) >= sizeof statmsg)
2510					i = sizeof statmsg - 1;
2511				memmove(statmsg, &buf[1], i);
2512				statmsg[i] = '\0';
2513				break;
2514
2515			  case 'B':	/* body type */
2516				if ((i = strlen(&buf[1])) >= sizeof bodytype)
2517					i = sizeof bodytype - 1;
2518				memmove(bodytype, &buf[1], i);
2519				bodytype[i] = '\0';
2520				break;
2521
2522			  case 'S':	/* sender name */
2523				if (Verbose)
2524				{
2525					printf("%8ld %10ld%c%.12s ",
2526					       dfsize,
2527					       w->w_pri,
2528					       bitset(EF_WARNING, flags) ? '+' : ' ',
2529					       ctime(&submittime) + 4);
2530					prtstr(&buf[1], 78);
2531				}
2532				else
2533				{
2534					printf("%8ld %.16s ", dfsize,
2535					    ctime(&submittime));
2536					prtstr(&buf[1], 40);
2537				}
2538				if (statmsg[0] != '\0' || bodytype[0] != '\0')
2539				{
2540					printf("\n    %10.10s", bodytype);
2541					if (statmsg[0] != '\0')
2542						printf("   (%.*s)",
2543						       Verbose ? 100 : 60,
2544						       statmsg);
2545				}
2546				break;
2547
2548			  case 'C':	/* controlling user */
2549				if (Verbose)
2550					printf("\n\t\t\t\t      (---%.74s---)",
2551					       &buf[1]);
2552				break;
2553
2554			  case 'R':	/* recipient name */
2555				p = &buf[1];
2556				if (qfver >= 1)
2557				{
2558					p = strchr(p, ':');
2559					if (p == NULL)
2560						break;
2561					p++;
2562				}
2563				if (Verbose)
2564				{
2565					printf("\n\t\t\t\t\t      ");
2566					prtstr(p, 73);
2567				}
2568				else
2569				{
2570					printf("\n\t\t\t\t       ");
2571					prtstr(p, 40);
2572				}
2573				break;
2574
2575			  case 'T':	/* creation time */
2576				submittime = atol(&buf[1]);
2577				break;
2578
2579			  case 'F':	/* flag bits */
2580				for (p = &buf[1]; *p != '\0'; p++)
2581				{
2582					switch (*p)
2583					{
2584					  case 'w':
2585						flags |= EF_WARNING;
2586						break;
2587					}
2588				}
2589			}
2590		}
2591		if (submittime == (time_t) 0)
2592			printf(" (no control file)");
2593		printf("\n");
2594		(void) fclose(f);
2595	}
2596	return nrequests;
2597}
2598/*
2599**  QUEUENAME -- build a file name in the queue directory for this envelope.
2600**
2601**	Parameters:
2602**		e -- envelope to build it in/from.
2603**		type -- the file type, used as the first character
2604**			of the file name.
2605**
2606**	Returns:
2607**		a pointer to the queue name (in a static buffer).
2608**
2609**	Side Effects:
2610**		If no id code is already assigned, queuename() will
2611**		assign an id code with assign_queueid().  If no queue
2612**		directory is assigned, one will be set with setnewqueue().
2613*/
2614
2615char *
2616queuename(e, type)
2617	register ENVELOPE *e;
2618	int type;
2619{
2620	char *sub = "";
2621	static char buf[MAXPATHLEN];
2622
2623	/* Assign an ID if needed */
2624	if (e->e_id == NULL)
2625		assign_queueid(e);
2626
2627	/* Assign a queue directory if needed */
2628	if (e->e_queuedir == NOQDIR)
2629		setnewqueue(e);
2630
2631	if (e->e_queuedir == NOQDIR)
2632		(void) snprintf(buf, sizeof buf, "%cf%s",
2633				type, e->e_id);
2634	else
2635	{
2636		switch (type)
2637		{
2638		  case 'd':
2639			if (bitset(QP_SUBDF, QPaths[e->e_queuedir].qp_subdirs))
2640				sub = "/df";
2641			break;
2642
2643		  case TEMPQF_LETTER:
2644		  case 't':
2645		  case LOSEQF_LETTER:
2646		  case 'q':
2647			if (bitset(QP_SUBQF, QPaths[e->e_queuedir].qp_subdirs))
2648				sub = "/qf";
2649			break;
2650
2651		  case 'x':
2652			if (bitset(QP_SUBXF, QPaths[e->e_queuedir].qp_subdirs))
2653				sub = "/xf";
2654			break;
2655		}
2656
2657		(void) snprintf(buf, sizeof buf, "%s%s/%cf%s",
2658				QPaths[e->e_queuedir].qp_name,
2659				sub, type, e->e_id);
2660	}
2661
2662	if (tTd(7, 2))
2663		dprintf("queuename: %s\n", buf);
2664	return buf;
2665}
2666/*
2667**  ASSIGN_QUEUEID -- assign a queue ID for this envelope.
2668**
2669**	Assigns an id code if one does not already exist.
2670**	This code assumes that nothing will remain in the queue for
2671**	longer than 60 years.  It is critical that files with the given
2672**	name not already exist in the queue.
2673**	Also initializes e_queuedir to NOQDIR.
2674**
2675**	Parameters:
2676**		e -- envelope to set it in.
2677**
2678**	Returns:
2679**		none.
2680*/
2681
2682static char	Base60Code[] =	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx";
2683
2684void
2685assign_queueid(e)
2686	register ENVELOPE *e;
2687{
2688	pid_t pid = getpid();
2689	static char cX = 0;
2690	static long random_offset;
2691	struct tm *tm;
2692	char idbuf[MAXQFNAME - 2];
2693
2694	if (e->e_id != NULL)
2695		return;
2696
2697	/* see if we need to get a new base time/pid */
2698	if (cX >= 60 || LastQueueTime == 0 || LastQueuePid != pid)
2699	{
2700		time_t then = LastQueueTime;
2701
2702		/* if the first time through, pick a random offset */
2703		if (LastQueueTime == 0)
2704			random_offset = get_random();
2705
2706		while ((LastQueueTime = curtime()) == then &&
2707		       LastQueuePid == pid)
2708		{
2709			(void) sleep(1);
2710		}
2711		LastQueuePid = getpid();
2712		cX = 0;
2713	}
2714	if (tTd(7, 50))
2715		dprintf("assign_queueid: random_offset = %ld (%d)\n",
2716			random_offset, (int)(cX + random_offset) % 60);
2717
2718	tm = gmtime(&LastQueueTime);
2719	idbuf[0] = Base60Code[tm->tm_year % 60];
2720	idbuf[1] = Base60Code[tm->tm_mon];
2721	idbuf[2] = Base60Code[tm->tm_mday];
2722	idbuf[3] = Base60Code[tm->tm_hour];
2723	idbuf[4] = Base60Code[tm->tm_min];
2724	idbuf[5] = Base60Code[tm->tm_sec];
2725	idbuf[6] = Base60Code[((int)cX++ + random_offset) % 60];
2726	(void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d",
2727			(int) LastQueuePid);
2728	e->e_id = newstr(idbuf);
2729	define('i', e->e_id, e);
2730	e->e_queuedir = NOQDIR;
2731	if (tTd(7, 1))
2732		dprintf("assign_queueid: assigned id %s, e=%lx\n",
2733			e->e_id, (u_long) e);
2734	if (LogLevel > 93)
2735		sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
2736}
2737/*
2738**  SYNC_QUEUE_TIME -- Assure exclusive PID in any given second
2739**
2740**	Make sure one PID can't be used by two processes in any one second.
2741**
2742**		If the system rotates PIDs fast enough, may get the
2743**		same pid in the same second for two distinct processes.
2744**		This will interfere with the queue file naming system.
2745**
2746**	Parameters:
2747**		none
2748**
2749**	Returns:
2750**		none
2751*/
2752void
2753sync_queue_time()
2754{
2755# if FAST_PID_RECYCLE
2756	if (OpMode != MD_TEST &&
2757	    OpMode != MD_VERIFY &&
2758	    LastQueueTime > 0 &&
2759	    LastQueuePid == getpid() &&
2760	    curtime() == LastQueueTime)
2761		(void) sleep(1);
2762# endif /* FAST_PID_RECYCLE */
2763}
2764/*
2765**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
2766**
2767**	Parameters:
2768**		e -- the envelope to unlock.
2769**
2770**	Returns:
2771**		none
2772**
2773**	Side Effects:
2774**		unlocks the queue for `e'.
2775*/
2776
2777void
2778unlockqueue(e)
2779	ENVELOPE *e;
2780{
2781	if (tTd(51, 4))
2782		dprintf("unlockqueue(%s)\n",
2783			e->e_id == NULL ? "NOQUEUE" : e->e_id);
2784
2785
2786	/* if there is a lock file in the envelope, close it */
2787	if (e->e_lockfp != NULL)
2788		(void) fclose(e->e_lockfp);
2789	e->e_lockfp = NULL;
2790
2791	/* don't create a queue id if we don't already have one */
2792	if (e->e_id == NULL)
2793		return;
2794
2795	/* remove the transcript */
2796	if (LogLevel > 87)
2797		sm_syslog(LOG_DEBUG, e->e_id, "unlock");
2798	if (!tTd(51, 104))
2799		xunlink(queuename(e, 'x'));
2800
2801}
2802/*
2803**  SETCTLUSER -- create a controlling address
2804**
2805**	Create a fake "address" given only a local login name; this is
2806**	used as a "controlling user" for future recipient addresses.
2807**
2808**	Parameters:
2809**		user -- the user name of the controlling user.
2810**		qfver -- the version stamp of this qf file.
2811**
2812**	Returns:
2813**		An address descriptor for the controlling user.
2814**
2815**	Side Effects:
2816**		none.
2817*/
2818
2819static ADDRESS *
2820setctluser(user, qfver)
2821	char *user;
2822	int qfver;
2823{
2824	register ADDRESS *a;
2825	struct passwd *pw;
2826	char *p;
2827
2828	/*
2829	**  See if this clears our concept of controlling user.
2830	*/
2831
2832	if (user == NULL || *user == '\0')
2833		return NULL;
2834
2835	/*
2836	**  Set up addr fields for controlling user.
2837	*/
2838
2839	a = (ADDRESS *) xalloc(sizeof *a);
2840	memset((char *) a, '\0', sizeof *a);
2841
2842	if (*user == '\0')
2843	{
2844		p = NULL;
2845		a->q_user = newstr(DefUser);
2846	}
2847	else if (*user == ':')
2848	{
2849		p = &user[1];
2850		a->q_user = newstr(p);
2851	}
2852	else
2853	{
2854		p = strtok(user, ":");
2855		a->q_user = newstr(user);
2856		if (qfver >= 2)
2857		{
2858			if ((p = strtok(NULL, ":")) != NULL)
2859				a->q_uid = atoi(p);
2860			if ((p = strtok(NULL, ":")) != NULL)
2861				a->q_gid = atoi(p);
2862			if ((p = strtok(NULL, ":")) != NULL)
2863				a->q_flags |= QGOODUID;
2864		}
2865		else if ((pw = sm_getpwnam(user)) != NULL)
2866		{
2867			if (*pw->pw_dir == '\0')
2868				a->q_home = NULL;
2869			else if (strcmp(pw->pw_dir, "/") == 0)
2870				a->q_home = "";
2871			else
2872				a->q_home = newstr(pw->pw_dir);
2873			a->q_uid = pw->pw_uid;
2874			a->q_gid = pw->pw_gid;
2875			a->q_flags |= QGOODUID;
2876		}
2877	}
2878
2879	a->q_flags |= QPRIMARY;		/* flag as a "ctladdr" */
2880	a->q_mailer = LocalMailer;
2881	if (p == NULL)
2882		a->q_paddr = newstr(a->q_user);
2883	else
2884		a->q_paddr = newstr(p);
2885	return a;
2886}
2887/*
2888**  LOSEQFILE -- save the qf as Qf and try to let someone know
2889**
2890**	Parameters:
2891**		e -- the envelope (e->e_id will be used).
2892**		why -- reported to whomever can hear.
2893**
2894**	Returns:
2895**		none.
2896*/
2897
2898void
2899loseqfile(e, why)
2900	register ENVELOPE *e;
2901	char *why;
2902{
2903	char *p;
2904	char buf[MAXPATHLEN];
2905
2906	if (e == NULL || e->e_id == NULL)
2907		return;
2908	p = queuename(e, 'q');
2909	if (strlen(p) >= (SIZE_T) sizeof buf)
2910		return;
2911	(void) strlcpy(buf, p, sizeof buf);
2912	p = queuename(e, LOSEQF_LETTER);
2913	if (rename(buf, p) < 0)
2914		syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
2915	else if (LogLevel > 0)
2916		sm_syslog(LOG_ALERT, e->e_id,
2917			  "Losing %s: %s", buf, why);
2918}
2919/*
2920**  QID_PRINTNAME -- create externally printable version of queue id
2921**
2922**	Parameters:
2923**		e -- the envelope.
2924**
2925**	Returns:
2926**		a printable version
2927*/
2928
2929char *
2930qid_printname(e)
2931	ENVELOPE *e;
2932{
2933	char *id;
2934	static char idbuf[MAXQFNAME + 34];
2935
2936	if (e == NULL)
2937		return "";
2938
2939	if (e->e_id == NULL)
2940		id = "";
2941	else
2942		id = e->e_id;
2943
2944	if (e->e_queuedir == NOQDIR)
2945		return id;
2946
2947	(void) snprintf(idbuf, sizeof idbuf, "%.32s/%s",
2948			QPaths[e->e_queuedir].qp_name, id);
2949	return idbuf;
2950}
2951/*
2952**  QID_PRINTQUEUE -- create full version of queue directory for df files
2953**
2954**	Parameters:
2955**		queuedir -- the short version of the queue directory
2956**
2957**	Returns:
2958**		the full pathname to the queue (static)
2959*/
2960
2961char *
2962qid_printqueue(queuedir)
2963	int queuedir;
2964{
2965	char *subdir;
2966	static char dir[MAXPATHLEN];
2967
2968	if (queuedir == NOQDIR)
2969		return QueueDir;
2970
2971	if (strcmp(QPaths[queuedir].qp_name, ".") == 0)
2972		subdir = NULL;
2973	else
2974		subdir = QPaths[queuedir].qp_name;
2975
2976	(void) snprintf(dir, sizeof dir, "%s%s%s%s", QueueDir,
2977			subdir == NULL ? "" : "/",
2978			subdir == NULL ? "" : subdir,
2979			(bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : ""));
2980	return dir;
2981}
2982/*
2983**  SETNEWQUEUE -- Sets a new queue directory
2984**
2985**	Assign a queue directory to an envelope and store the directory
2986**	in e->e_queuedir.  The queue is chosen at random.
2987**
2988**	This routine may be improved in the future to allow for more
2989**	elaborate queueing schemes.  Suggestions and code contributions
2990**	are welcome.
2991**
2992**	Parameters:
2993**		e -- envelope to assign a queue for.
2994**
2995**	Returns:
2996**		none.
2997*/
2998
2999void
3000setnewqueue(e)
3001	ENVELOPE *e;
3002{
3003	int idx;
3004
3005	if (tTd(41, 20))
3006		dprintf("setnewqueue: called\n");
3007
3008	if (e->e_queuedir != NOQDIR)
3009	{
3010		if (tTd(41, 20))
3011			dprintf("setnewqueue: e_queuedir already assigned (%s)\n",
3012				qid_printqueue(e->e_queuedir));
3013		return;
3014	}
3015
3016	if (NumQueues == 1)
3017		idx = 0;
3018	else
3019	{
3020#if RANDOMSHIFT
3021		/* lower bits are not random "enough", select others */
3022		idx = (get_random() >> RANDOMSHIFT) % NumQueues;
3023#else /* RANDOMSHIFT */
3024		idx = get_random() % NumQueues;
3025#endif /* RANDOMSHIFT */
3026		if (tTd(41, 15))
3027			dprintf("setnewqueue: get_random() %% %d = %d\n",
3028				NumQueues, idx);
3029	}
3030
3031	e->e_queuedir = idx;
3032	if (tTd(41, 3))
3033		dprintf("setnewqueue: Assigned queue directory %s\n",
3034			qid_printqueue(e->e_queuedir));
3035}
3036
3037/*
3038**  CHKQDIR -- check a queue directory
3039**
3040**	Parameters:
3041**		name -- name of queue directory
3042**		sff -- flags for safefile()
3043**
3044**	Returns:
3045**		is it a queue directory?
3046*/
3047
3048static bool
3049chkqdir(name, sff)
3050	char *name;
3051	long sff;
3052{
3053	struct stat statb;
3054	int i;
3055
3056	/* skip over . and .. directories */
3057	if (name[0] == '.' &&
3058	    (name[1] == '\0' || (name[2] == '.' && name[3] == '\0')))
3059		return FALSE;
3060# if HASLSTAT
3061	if (lstat(name, &statb) < 0)
3062# else /* HASLSTAT */
3063	if (stat(name, &statb) < 0)
3064# endif /* HASLSTAT */
3065	{
3066		if (tTd(41, 2))
3067			dprintf("multiqueue_cache: stat(\"%s\"): %s\n",
3068				name, errstring(errno));
3069		return FALSE;
3070	}
3071# if HASLSTAT
3072	if (S_ISLNK(statb.st_mode))
3073	{
3074		/*
3075		**  For a symlink we need to make sure the
3076		**  target is a directory
3077		*/
3078		if (stat(name, &statb) < 0)
3079		{
3080			if (tTd(41, 2))
3081				dprintf("multiqueue_cache: stat(\"%s\"): %s\n",
3082					name, errstring(errno));
3083			return FALSE;
3084		}
3085	}
3086# endif /* HASLSTAT */
3087
3088	if (!S_ISDIR(statb.st_mode))
3089	{
3090		if (tTd(41, 2))
3091			dprintf("multiqueue_cache: \"%s\": Not a directory\n",
3092				name);
3093		return FALSE;
3094	}
3095
3096	/* Print a warning if unsafe (but still use it) */
3097	i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0);
3098	if (i != 0 && tTd(41, 2))
3099		dprintf("multiqueue_cache: \"%s\": Not safe: %s\n",
3100			name, errstring(i));
3101	return TRUE;
3102}
3103
3104/*
3105**  MULTIQUEUE_CACHE -- cache a list of paths to queues.
3106**
3107**	Each potential queue is checked as the cache is built.
3108**	Thereafter, each is blindly trusted.
3109**	Note that we can be called again after a timeout to rebuild
3110**	(although code for that is not ready yet).
3111**
3112**	Parameters:
3113**		none
3114**
3115**	Returns:
3116**		none
3117*/
3118
3119void
3120multiqueue_cache()
3121{
3122	register DIR *dp;
3123	register struct dirent *d;
3124	char *cp;
3125	int i, len;
3126	int slotsleft = 0;
3127	long sff = SFF_ANYFILE;
3128	char qpath[MAXPATHLEN];
3129	char subdir[MAXPATHLEN];
3130
3131	if (tTd(41, 20))
3132		dprintf("multiqueue_cache: called\n");
3133
3134	if (NumQueues != 0 && QPaths != NULL)
3135	{
3136		for (i = 0; i < NumQueues; i++)
3137		{
3138			if (QPaths[i].qp_name != NULL)
3139				(void) free(QPaths[i].qp_name);
3140		}
3141		(void) free((char *)QPaths);
3142		QPaths = NULL;
3143		NumQueues = 0;
3144	}
3145
3146	/* If running as root, allow safedirpath() checks to use privs */
3147	if (RunAsUid == 0)
3148		sff |= SFF_ROOTOK;
3149
3150	(void) snprintf(qpath, sizeof qpath, "%s", QueueDir);
3151	len = strlen(qpath) - 1;
3152	cp = &qpath[len];
3153	if (*cp == '*')
3154	{
3155		*cp = '\0';
3156		if ((cp = strrchr(qpath, '/')) == NULL)
3157		{
3158			syserr("QueueDirectory: can not wildcard relative path");
3159			if (tTd(41, 2))
3160				dprintf("multiqueue_cache: \"%s\": Can not wildcard relative path.\n",
3161					qpath);
3162			ExitStat = EX_CONFIG;
3163			return;
3164		}
3165		if (cp == qpath)
3166		{
3167			/*
3168			**  Special case of top level wildcard, like /foo*
3169			*/
3170
3171			(void) snprintf(qpath + 1, sizeof qpath - 1,
3172					"%s", qpath);
3173			++cp;
3174		}
3175		*(cp++) = '\0';
3176		len = strlen(cp);
3177
3178		if (tTd(41, 2))
3179			dprintf("multiqueue_cache: prefix=\"%s\"\n", cp);
3180
3181		QueueDir = newstr(qpath);
3182
3183		/*
3184		**  XXX Should probably wrap this whole loop in a timeout
3185		**  in case some wag decides to NFS mount the queues.
3186		*/
3187
3188		/* test path to get warning messages */
3189		i= safedirpath(QueueDir, RunAsUid, RunAsGid, NULL, sff, 0, 0);
3190		if (i != 0 && tTd(41, 2))
3191			dprintf("multiqueue_cache: \"%s\": Not safe: %s\n",
3192				QueueDir, errstring(i));
3193
3194		if (chdir(QueueDir) < 0)
3195		{
3196			syserr("can not chdir(%s)", QueueDir);
3197			if (tTd(41, 2))
3198				dprintf("multiqueue_cache: \"%s\": %s\n",
3199					qpath, errstring(errno));
3200			ExitStat = EX_CONFIG;
3201			return;
3202		}
3203
3204		if ((dp = opendir(".")) == NULL)
3205		{
3206			syserr("can not opendir(%s)", QueueDir);
3207			if (tTd(41, 2))
3208				dprintf("multiqueue_cache: opendir(\"%s\"): %s\n",
3209					QueueDir, errstring(errno));
3210			ExitStat = EX_CONFIG;
3211			return;
3212		}
3213		while ((d = readdir(dp)) != NULL)
3214		{
3215			if (strncmp(d->d_name, cp, len) != 0)
3216			{
3217				if (tTd(41, 5))
3218					dprintf("multiqueue_cache: \"%s\", skipped\n",
3219						d->d_name);
3220				continue;
3221			}
3222			if (!chkqdir(d->d_name, sff))
3223				continue;
3224
3225			if (QPaths == NULL)
3226			{
3227				slotsleft = 20;
3228				QPaths = (QPATHS *)xalloc((sizeof *QPaths) *
3229							  slotsleft);
3230				NumQueues = 0;
3231			}
3232			else if (slotsleft < 1)
3233			{
3234				QPaths = (QPATHS *)realloc((char *)QPaths,
3235							  (sizeof *QPaths) *
3236							  (NumQueues + 10));
3237				if (QPaths == NULL)
3238				{
3239					(void) closedir(dp);
3240					return;
3241				}
3242				slotsleft += 10;
3243			}
3244
3245			/* check subdirs */
3246			QPaths[NumQueues].qp_subdirs = QP_NOSUB;
3247			(void) snprintf(subdir, sizeof subdir, "%s/%s/%s",
3248					qpath, d->d_name, "qf");
3249			if (chkqdir(subdir, sff))
3250				QPaths[NumQueues].qp_subdirs |= QP_SUBQF;
3251
3252			(void) snprintf(subdir, sizeof subdir, "%s/%s/%s",
3253					qpath, d->d_name, "df");
3254			if (chkqdir(subdir, sff))
3255				QPaths[NumQueues].qp_subdirs |= QP_SUBDF;
3256
3257			(void) snprintf(subdir, sizeof subdir, "%s/%s/%s",
3258					qpath, d->d_name, "xf");
3259			if (chkqdir(subdir, sff))
3260				QPaths[NumQueues].qp_subdirs |= QP_SUBXF;
3261
3262			/* assert(strlen(d->d_name) < MAXPATHLEN - 14) */
3263			/* maybe even - 17 (subdirs) */
3264			QPaths[NumQueues].qp_name = newstr(d->d_name);
3265			if (tTd(41, 2))
3266				dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n",
3267					NumQueues, d->d_name,
3268					QPaths[NumQueues].qp_subdirs);
3269			NumQueues++;
3270			slotsleft--;
3271		}
3272		(void) closedir(dp);
3273	}
3274	if (NumQueues == 0)
3275	{
3276		if (*cp != '*' && tTd(41, 2))
3277			dprintf("multiqueue_cache: \"%s\": No wildcard suffix character\n",
3278				QueueDir);
3279		QPaths = (QPATHS *)xalloc(sizeof *QPaths);
3280		QPaths[0].qp_name = newstr(".");
3281		QPaths[0].qp_subdirs = QP_NOSUB;
3282		NumQueues = 1;
3283
3284		/* test path to get warning messages */
3285		(void) safedirpath(QueueDir, RunAsUid, RunAsGid,
3286				   NULL, sff, 0, 0);
3287		if (chdir(QueueDir) < 0)
3288		{
3289			syserr("can not chdir(%s)", QueueDir);
3290			if (tTd(41, 2))
3291				dprintf("multiqueue_cache: \"%s\": %s\n",
3292					QueueDir, errstring(errno));
3293			ExitStat = EX_CONFIG;
3294		}
3295
3296		/* check subdirs */
3297		(void) snprintf(subdir, sizeof subdir, "%s/qf", QueueDir);
3298		if (chkqdir(subdir, sff))
3299			QPaths[0].qp_subdirs |= QP_SUBQF;
3300
3301		(void) snprintf(subdir, sizeof subdir, "%s/df",	QueueDir);
3302		if (chkqdir(subdir, sff))
3303			QPaths[0].qp_subdirs |= QP_SUBDF;
3304
3305		(void) snprintf(subdir, sizeof subdir, "%s/xf", QueueDir);
3306		if (chkqdir(subdir, sff))
3307			QPaths[0].qp_subdirs |= QP_SUBXF;
3308	}
3309}
3310
3311# if 0
3312/*
3313**  HASHFQN -- calculate a hash value for a fully qualified host name
3314**
3315**	Arguments:
3316**		fqn -- an all lower-case host.domain string
3317**		buckets -- the number of buckets (queue directories)
3318**
3319**	Returns:
3320**		a bucket number (signed integer)
3321**		-1 on error
3322**
3323**	Contributed by Exactis.com, Inc.
3324*/
3325
3326int
3327hashfqn(fqn, buckets)
3328	register char *fqn;
3329	int buckets;
3330{
3331	register char *p;
3332	register int h = 0, hash, cnt;
3333#  define WATERINC (1000)
3334
3335	if (fqn == NULL)
3336		return -1;
3337
3338	/*
3339	**  A variation on the gdb hash
3340	**  This is the best as of Feb 19, 1996 --bcx
3341	*/
3342
3343	p = fqn;
3344	h = 0x238F13AF * strlen(p);
3345	for (cnt = 0; *p != 0; ++p, cnt++)
3346	{
3347		h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF;
3348	}
3349	h = (1103515243 * h + 12345) & 0x7FFFFFFF;
3350	if (buckets < 2)
3351		hash = 0;
3352	else
3353		hash = (h % buckets);
3354
3355	return hash;
3356}
3357# endif /* 0 */
3358
3359# if _FFR_QUEUEDELAY
3360/*
3361**  QUEUEDELAY -- compute queue delay time
3362**
3363**	Parameters:
3364**		e -- the envelope to queue up.
3365**
3366**	Returns:
3367**		queue delay time
3368**
3369**	Side Effects:
3370**		may change e_queuedelay
3371*/
3372
3373static time_t
3374queuedelay(e)
3375	ENVELOPE *e;
3376{
3377	time_t qd;
3378
3379	if (e->e_queuealg == QD_EXP)
3380	{
3381		if (e->e_queuedelay == 0)
3382			e->e_queuedelay = QueueInitDelay;
3383		else
3384		{
3385			e->e_queuedelay *= 2;
3386			if (e->e_queuedelay > QueueMaxDelay)
3387				e->e_queuedelay = QueueMaxDelay;
3388		}
3389		qd = e->e_queuedelay;
3390	}
3391	else
3392		qd = MinQueueAge;
3393	return qd;
3394}
3395# endif /* _FFR_QUEUEDELAY */
3396#endif /* QUEUE */
3397