xref: /freebsd/contrib/sendmail/src/queue.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*
2  * Copyright (c) 1998-2001 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
19 static char id[] = "@(#)$Id: queue.c,v 8.343.4.55 2001/05/03 23:37:11 gshapiro Exp $ (with queueing)";
20 # else /* QUEUE */
21 static char id[] = "@(#)$Id: queue.c,v 8.343.4.55 2001/05/03 23:37:11 gshapiro 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 */
31 static 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 
41 struct 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 
52 typedef struct work	WORK;
53 
54 static WORK	*WorkQ;			/* queue of things to be done */
55 
56 static void	grow_wlist __P((int));
57 static int	orderq __P((int, bool));
58 static void	printctladdr __P((ADDRESS *, FILE *));
59 static int	print_single_queue __P((int));
60 static bool	readqf __P((ENVELOPE *));
61 static void	runqueueevent __P((void));
62 static int	run_single_queue __P((int, bool, bool));
63 static char	*strrev __P((char *));
64 static ADDRESS	*setctluser __P((char *, int));
65 static int	workcmpf0();
66 static int	workcmpf1();
67 static int	workcmpf2();
68 static int	workcmpf3();
69 static 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 
89 void
90 queueup(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 
556 static void
557 printctladdr(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 
628 static ENVELOPE	QueueEnvelope;		/* the queue run envelope */
629 int		NumQueues = 0;		/* number of queues */
630 static time_t	LastQueueTime = 0;	/* last time a queue ID assigned */
631 static pid_t	LastQueuePid = -1;	/* last PID which had a queue ID */
632 
633 struct qpaths_s
634 {
635 	char	*qp_name;	/* name of queue dir */
636 	short	qp_subdirs;	/* use subdirs? */
637 };
638 
639 typedef 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 
647 static QPATHS	*QPaths = NULL;		/* list of queue directories */
648 
649 bool
650 runqueue(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 
709 static bool
710 run_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 
797 		/* Reset global flags */
798 		RestartRequest = NULL;
799 		ShutdownRequest = NULL;
800 		PendingSignal = 0;
801 
802 		clrcontrol();
803 		proc_list_clear();
804 
805 		/* Add parent process as first child item */
806 		proc_list_add(getpid(), "Queue runner child process",
807 			      PROC_QUEUE_CHILD);
808 		(void) releasesignal(SIGCHLD);
809 		(void) setsignal(SIGCHLD, SIG_DFL);
810 		(void) setsignal(SIGHUP, SIG_DFL);
811 		(void) setsignal(SIGTERM, intsig);
812 	}
813 
814 	sm_setproctitle(TRUE, CurEnv, "running queue: %s",
815 			qid_printqueue(queuedir));
816 
817 	if (LogLevel > 69 || tTd(63, 99))
818 		sm_syslog(LOG_DEBUG, NOQID,
819 			  "runqueue %s, pid=%d, forkflag=%d",
820 			  qid_printqueue(queuedir), (int) getpid(), forkflag);
821 
822 	/*
823 	**  Release any resources used by the daemon code.
824 	*/
825 
826 # if DAEMON
827 	clrdaemon();
828 # endif /* DAEMON */
829 
830 	/* force it to run expensive jobs */
831 	NoConnect = FALSE;
832 
833 	/* drop privileges */
834 	if (geteuid() == (uid_t) 0)
835 		(void) drop_privileges(FALSE);
836 
837 	/*
838 	**  Create ourselves an envelope
839 	*/
840 
841 	CurEnv = &QueueEnvelope;
842 	e = newenvelope(&QueueEnvelope, CurEnv);
843 	e->e_flags = BlankEnvelope.e_flags;
844 	e->e_parent = NULL;
845 
846 	/* make sure we have disconnected from parent */
847 	if (forkflag)
848 	{
849 		disconnect(1, e);
850 		QuickAbort = FALSE;
851 	}
852 
853 	/*
854 	**  If we are running part of the queue, always ignore stored
855 	**  host status.
856 	*/
857 
858 	if (QueueLimitId != NULL || QueueLimitSender != NULL ||
859 	    QueueLimitRecipient != NULL)
860 	{
861 		IgnoreHostStatus = TRUE;
862 		MinQueueAge = 0;
863 	}
864 
865 	/*
866 	**  Start making passes through the queue.
867 	**	First, read and sort the entire queue.
868 	**	Then, process the work in that order.
869 	**		But if you take too long, start over.
870 	*/
871 
872 	/* order the existing work requests */
873 	njobs = orderq(queuedir, FALSE);
874 
875 
876 	/* process them once at a time */
877 	while (WorkQ != NULL)
878 	{
879 		WORK *w = WorkQ;
880 
881 		WorkQ = WorkQ->w_next;
882 		e->e_to = NULL;
883 
884 		/*
885 		**  Ignore jobs that are too expensive for the moment.
886 		**
887 		**	Get new load average every 30 seconds.
888 		*/
889 
890 		now = curtime();
891 		if (current_la_time < now - 30)
892 		{
893 			CurrentLA = sm_getla(e);
894 			current_la_time = now;
895 		}
896 		if (shouldqueue(WkRecipFact, current_la_time))
897 		{
898 			char *msg = "Aborting queue run: load average too high";
899 
900 			if (Verbose)
901 				message("%s", msg);
902 			if (LogLevel > 8)
903 				sm_syslog(LOG_INFO, NOQID,
904 					  "runqueue: %s",
905 					  msg);
906 			break;
907 		}
908 		sequenceno++;
909 		if (shouldqueue(w->w_pri, w->w_ctime))
910 		{
911 			if (Verbose)
912 				message("");
913 			if (QueueSortOrder == QSO_BYPRIORITY)
914 			{
915 				if (Verbose)
916 					message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue",
917 						qid_printqueue(queuedir),
918 						w->w_name + 2,
919 						sequenceno,
920 						njobs);
921 				if (LogLevel > 8)
922 					sm_syslog(LOG_INFO, NOQID,
923 						  "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)",
924 						  qid_printqueue(queuedir),
925 						  w->w_name + 2,
926 						  w->w_pri,
927 						  CurrentLA,
928 						  sequenceno,
929 						  njobs);
930 				break;
931 			}
932 			else if (Verbose)
933 				message("Skipping %s/%s (sequence %d of %d)",
934 					qid_printqueue(queuedir),
935 					w->w_name + 2,
936 					sequenceno, njobs);
937 		}
938 		else
939 		{
940 			pid_t pid;
941 
942 			if (Verbose)
943 			{
944 				message("");
945 				message("Running %s/%s (sequence %d of %d)",
946 					qid_printqueue(queuedir),
947 					w->w_name + 2,
948 					sequenceno, njobs);
949 			}
950 			if (tTd(63, 100))
951 				sm_syslog(LOG_DEBUG, NOQID,
952 					  "runqueue %s dowork(%s)",
953 					  qid_printqueue(queuedir),
954 					  w->w_name + 2);
955 
956 			pid = dowork(queuedir, w->w_name + 2,
957 				     ForkQueueRuns, FALSE, e);
958 			errno = 0;
959 			if (pid != 0)
960 				(void) waitfor(pid);
961 		}
962 		sm_free(w->w_name);
963 		if (w->w_host)
964 			sm_free(w->w_host);
965 		sm_free((char *) w);
966 	}
967 
968 	/* exit without the usual cleanup */
969 	e->e_id = NULL;
970 	if (forkflag)
971 		finis(TRUE, ExitStat);
972 	/* NOTREACHED */
973 	return TRUE;
974 }
975 
976 /*
977 **  RUNQUEUEEVENT -- stub for use in setevent
978 **
979 **	Parameters:
980 **		none.
981 **
982 **	Returns:
983 **		none.
984 **
985 **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
986 **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
987 **		DOING.
988 */
989 
990 static void
991 runqueueevent()
992 {
993 	DoQueueRun = TRUE;
994 }
995 /*
996 **  ORDERQ -- order the work queue.
997 **
998 **	Parameters:
999 **		queuedir -- the index of the queue directory.
1000 **		doall -- if set, include everything in the queue (even
1001 **			the jobs that cannot be run because the load
1002 **			average is too high).  Otherwise, exclude those
1003 **			jobs.
1004 **
1005 **	Returns:
1006 **		The number of request in the queue (not necessarily
1007 **		the number of requests in WorkQ however).
1008 **
1009 **	Side Effects:
1010 **		Sets WorkQ to the queue of available work, in order.
1011 */
1012 
1013 # define NEED_P		001
1014 # define NEED_T		002
1015 # define NEED_R		004
1016 # define NEED_S		010
1017 # define NEED_H		020
1018 
1019 static WORK	*WorkList = NULL;
1020 static int	WorkListSize = 0;
1021 
1022 static int
1023 orderq(queuedir, doall)
1024 	int queuedir;
1025 	bool doall;
1026 {
1027 	register struct dirent *d;
1028 	register WORK *w;
1029 	register char *p;
1030 	DIR *f;
1031 	register int i;
1032 	int wn = -1;
1033 	int wc;
1034 	QUEUE_CHAR *check;
1035 	char qd[MAXPATHLEN];
1036 	char qf[MAXPATHLEN];
1037 
1038 	if (queuedir == NOQDIR)
1039 		(void) strlcpy(qd, ".", sizeof qd);
1040 	else
1041 		(void) snprintf(qd, sizeof qd, "%s%s",
1042 				QPaths[queuedir].qp_name,
1043 				(bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : ""));
1044 
1045 	if (tTd(41, 1))
1046 	{
1047 		dprintf("orderq:\n");
1048 
1049 		check = QueueLimitId;
1050 		while (check != NULL)
1051 		{
1052 			dprintf("\tQueueLimitId = %s\n",
1053 				check->queue_match);
1054 			check = check->queue_next;
1055 		}
1056 
1057 		check = QueueLimitSender;
1058 		while (check != NULL)
1059 		{
1060 			dprintf("\tQueueLimitSender = %s\n",
1061 				check->queue_match);
1062 			check = check->queue_next;
1063 		}
1064 
1065 		check = QueueLimitRecipient;
1066 		while (check != NULL)
1067 		{
1068 			dprintf("\tQueueLimitRecipient = %s\n",
1069 				check->queue_match);
1070 			check = check->queue_next;
1071 		}
1072 	}
1073 
1074 	/* clear out old WorkQ */
1075 	for (w = WorkQ; w != NULL; )
1076 	{
1077 		register WORK *nw = w->w_next;
1078 
1079 		WorkQ = nw;
1080 		sm_free(w->w_name);
1081 		if (w->w_host != NULL)
1082 			sm_free(w->w_host);
1083 		sm_free((char *) w);
1084 		w = nw;
1085 	}
1086 
1087 	/* open the queue directory */
1088 	f = opendir(qd);
1089 	if (f == NULL)
1090 	{
1091 		syserr("orderq: cannot open \"%s\"", qid_printqueue(queuedir));
1092 		return 0;
1093 	}
1094 
1095 	/*
1096 	**  Read the work directory.
1097 	*/
1098 
1099 	while ((d = readdir(f)) != NULL)
1100 	{
1101 		FILE *cf;
1102 		int qfver = 0;
1103 		char lbuf[MAXNAME + 1];
1104 		struct stat sbuf;
1105 
1106 		if (tTd(41, 50))
1107 			dprintf("orderq: checking %s\n", d->d_name);
1108 
1109 		/* is this an interesting entry? */
1110 		if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
1111 			continue;
1112 
1113 		if (strlen(d->d_name) >= MAXQFNAME)
1114 		{
1115 			if (Verbose)
1116 				printf("orderq: %s too long, %d max characters\n",
1117 					d->d_name, MAXQFNAME);
1118 			if (LogLevel > 0)
1119 				sm_syslog(LOG_ALERT, NOQID,
1120 					  "orderq: %s too long, %d max characters",
1121 					  d->d_name, MAXQFNAME);
1122 			continue;
1123 		}
1124 
1125 		check = QueueLimitId;
1126 		while (check != NULL)
1127 		{
1128 			if (strcontainedin(check->queue_match, d->d_name))
1129 				break;
1130 			else
1131 				check = check->queue_next;
1132 		}
1133 		if (QueueLimitId != NULL && check == NULL)
1134 			continue;
1135 
1136 		/* grow work list if necessary */
1137 		if (++wn >= MaxQueueRun && MaxQueueRun > 0)
1138 		{
1139 			if (wn == MaxQueueRun && LogLevel > 0)
1140 				sm_syslog(LOG_WARNING, NOQID,
1141 					  "WorkList for %s maxed out at %d",
1142 					  qid_printqueue(queuedir),
1143 					  MaxQueueRun);
1144 			continue;
1145 		}
1146 		if (wn >= WorkListSize)
1147 		{
1148 			grow_wlist(queuedir);
1149 			if (wn >= WorkListSize)
1150 				continue;
1151 		}
1152 		w = &WorkList[wn];
1153 
1154 		(void) snprintf(qf, sizeof qf, "%s/%s", qd, d->d_name);
1155 		if (stat(qf, &sbuf) < 0)
1156 		{
1157 			if (errno != ENOENT)
1158 				sm_syslog(LOG_INFO, NOQID,
1159 					  "orderq: can't stat %s/%s",
1160 					  qid_printqueue(queuedir), d->d_name);
1161 			wn--;
1162 			continue;
1163 		}
1164 		if (!bitset(S_IFREG, sbuf.st_mode))
1165 		{
1166 			/* Yikes!  Skip it or we will hang on open! */
1167 			syserr("orderq: %s/%s is not a regular file",
1168 			       qid_printqueue(queuedir), d->d_name);
1169 			wn--;
1170 			continue;
1171 		}
1172 
1173 		/* avoid work if possible */
1174 		if (QueueSortOrder == QSO_BYFILENAME &&
1175 		    QueueLimitSender == NULL &&
1176 		    QueueLimitRecipient == NULL)
1177 		{
1178 			w->w_name = newstr(d->d_name);
1179 			w->w_host = NULL;
1180 			w->w_lock = w->w_tooyoung = FALSE;
1181 			w->w_pri = 0;
1182 			w->w_ctime = 0;
1183 			continue;
1184 		}
1185 
1186 		/* open control file */
1187 		cf = fopen(qf, "r");
1188 
1189 		if (cf == NULL)
1190 		{
1191 			/* this may be some random person sending hir msgs */
1192 			/* syserr("orderq: cannot open %s", cbuf); */
1193 			if (tTd(41, 2))
1194 				dprintf("orderq: cannot open %s: %s\n",
1195 					d->d_name, errstring(errno));
1196 			errno = 0;
1197 			wn--;
1198 			continue;
1199 		}
1200 		w->w_name = newstr(d->d_name);
1201 		w->w_host = NULL;
1202 		w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB);
1203 		w->w_tooyoung = FALSE;
1204 
1205 		/* make sure jobs in creation don't clog queue */
1206 		w->w_pri = 0x7fffffff;
1207 		w->w_ctime = 0;
1208 
1209 		/* extract useful information */
1210 		i = NEED_P | NEED_T;
1211 		if (QueueSortOrder == QSO_BYHOST)
1212 		{
1213 			/* need w_host set for host sort order */
1214 			i |= NEED_H;
1215 		}
1216 		if (QueueLimitSender != NULL)
1217 			i |= NEED_S;
1218 		if (QueueLimitRecipient != NULL)
1219 			i |= NEED_R;
1220 		while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
1221 		{
1222 			int c;
1223 			time_t age;
1224 
1225 			p = strchr(lbuf, '\n');
1226 			if (p != NULL)
1227 				*p = '\0';
1228 			else
1229 			{
1230 				/* flush rest of overly long line */
1231 				while ((c = getc(cf)) != EOF && c != '\n')
1232 					continue;
1233 			}
1234 
1235 			switch (lbuf[0])
1236 			{
1237 			  case 'V':
1238 				qfver = atoi(&lbuf[1]);
1239 				break;
1240 
1241 			  case 'P':
1242 				w->w_pri = atol(&lbuf[1]);
1243 				i &= ~NEED_P;
1244 				break;
1245 
1246 			  case 'T':
1247 				w->w_ctime = atol(&lbuf[1]);
1248 				i &= ~NEED_T;
1249 				break;
1250 
1251 			  case 'R':
1252 				if (w->w_host == NULL &&
1253 				    (p = strrchr(&lbuf[1], '@')) != NULL)
1254 				{
1255 					w->w_host = strrev(&p[1]);
1256 					makelower(w->w_host);
1257 					i &= ~NEED_H;
1258 				}
1259 				if (QueueLimitRecipient == NULL)
1260 				{
1261 					i &= ~NEED_R;
1262 					break;
1263 				}
1264 				if (qfver > 0)
1265 				{
1266 					p = strchr(&lbuf[1], ':');
1267 					if (p == NULL)
1268 						p = &lbuf[1];
1269 				}
1270 				else
1271 					p = &lbuf[1];
1272 				check = QueueLimitRecipient;
1273 				while (check != NULL)
1274 				{
1275 					if (strcontainedin(check->queue_match,
1276 							   p))
1277 						break;
1278 					else
1279 						check = check->queue_next;
1280 				}
1281 				if (check != NULL)
1282 					i &= ~NEED_R;
1283 				break;
1284 
1285 			  case 'S':
1286 				check = QueueLimitSender;
1287 				while (check != NULL)
1288 				{
1289 					if (strcontainedin(check->queue_match,
1290 							   &lbuf[1]))
1291 						break;
1292 					else
1293 						check = check->queue_next;
1294 				}
1295 				if (check != NULL)
1296 					i &= ~NEED_S;
1297 				break;
1298 
1299 			  case 'K':
1300 				age = curtime() - (time_t) atol(&lbuf[1]);
1301 				if (age >= 0 && MinQueueAge > 0 &&
1302 				    age < MinQueueAge)
1303 					w->w_tooyoung = TRUE;
1304 				break;
1305 
1306 			  case 'N':
1307 				if (atol(&lbuf[1]) == 0)
1308 					w->w_tooyoung = FALSE;
1309 				break;
1310 
1311 # if _FFR_QUEUEDELAY
1312 /*
1313 			  case 'G':
1314 				queuealg = atoi(lbuf[1]);
1315 				break;
1316 			  case 'Y':
1317 				queuedelay = (time_t) atol(&lbuf[1]);
1318 				break;
1319 */
1320 # endif /* _FFR_QUEUEDELAY */
1321 			}
1322 		}
1323 		(void) fclose(cf);
1324 
1325 		if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
1326 		    bitset(NEED_R|NEED_S, i))
1327 		{
1328 			/* don't even bother sorting this job in */
1329 			if (tTd(41, 49))
1330 				dprintf("skipping %s (%x)\n", w->w_name, i);
1331 			sm_free(w->w_name);
1332 			if (w->w_host)
1333 				sm_free(w->w_host);
1334 			wn--;
1335 		}
1336 	}
1337 	(void) closedir(f);
1338 	wn++;
1339 
1340 	WorkQ = NULL;
1341 	if (WorkList == NULL)
1342 		return 0;
1343 	wc = min(wn, WorkListSize);
1344 	if (wc > MaxQueueRun && MaxQueueRun > 0)
1345 		wc = MaxQueueRun;
1346 
1347 	if (QueueSortOrder == QSO_BYHOST)
1348 	{
1349 		/*
1350 		**  Sort the work directory for the first time,
1351 		**  based on host name, lock status, and priority.
1352 		*/
1353 
1354 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1);
1355 
1356 		/*
1357 		**  If one message to host is locked, "lock" all messages
1358 		**  to that host.
1359 		*/
1360 
1361 		i = 0;
1362 		while (i < wc)
1363 		{
1364 			if (!WorkList[i].w_lock)
1365 			{
1366 				i++;
1367 				continue;
1368 			}
1369 			w = &WorkList[i];
1370 			while (++i < wc)
1371 			{
1372 				if (WorkList[i].w_host == NULL &&
1373 				    w->w_host == NULL)
1374 					WorkList[i].w_lock = TRUE;
1375 				else if (WorkList[i].w_host != NULL &&
1376 					 w->w_host != NULL &&
1377 					 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0)
1378 					WorkList[i].w_lock = TRUE;
1379 				else
1380 					break;
1381 			}
1382 		}
1383 
1384 		/*
1385 		**  Sort the work directory for the second time,
1386 		**  based on lock status, host name, and priority.
1387 		*/
1388 
1389 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
1390 	}
1391 	else if (QueueSortOrder == QSO_BYTIME)
1392 	{
1393 		/*
1394 		**  Simple sort based on submission time only.
1395 		*/
1396 
1397 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
1398 	}
1399 	else if (QueueSortOrder == QSO_BYFILENAME)
1400 	{
1401 		/*
1402 		**  Sort based on qf filename.
1403 		*/
1404 
1405 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4);
1406 	}
1407 	else
1408 	{
1409 		/*
1410 		**  Simple sort based on queue priority only.
1411 		*/
1412 
1413 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
1414 	}
1415 
1416 	/*
1417 	**  Convert the work list into canonical form.
1418 	**	Should be turning it into a list of envelopes here perhaps.
1419 	*/
1420 
1421 	for (i = wc; --i >= 0; )
1422 	{
1423 		w = (WORK *) xalloc(sizeof *w);
1424 		w->w_name = WorkList[i].w_name;
1425 		w->w_host = WorkList[i].w_host;
1426 		w->w_lock = WorkList[i].w_lock;
1427 		w->w_tooyoung = WorkList[i].w_tooyoung;
1428 		w->w_pri = WorkList[i].w_pri;
1429 		w->w_ctime = WorkList[i].w_ctime;
1430 		w->w_next = WorkQ;
1431 		WorkQ = w;
1432 	}
1433 	if (WorkList != NULL)
1434 		sm_free(WorkList);
1435 	WorkList = NULL;
1436 	WorkListSize = 0;
1437 
1438 	if (tTd(40, 1))
1439 	{
1440 		for (w = WorkQ; w != NULL; w = w->w_next)
1441 		{
1442 			if (w->w_host != NULL)
1443 				dprintf("%22s: pri=%ld %s\n",
1444 					w->w_name, w->w_pri, w->w_host);
1445 			else
1446 				dprintf("%32s: pri=%ld\n",
1447 					w->w_name, w->w_pri);
1448 		}
1449 	}
1450 
1451 	return wn;
1452 }
1453 /*
1454 **  GROW_WLIST -- make the work list larger
1455 **
1456 **	Parameters:
1457 **		queuedir -- the index for the queue directory.
1458 **
1459 **	Returns:
1460 **		none.
1461 **
1462 **	Side Effects:
1463 **		Adds another QUEUESEGSIZE entries to WorkList if possible.
1464 **		It can fail if there isn't enough memory, so WorkListSize
1465 **		should be checked again upon return.
1466 */
1467 
1468 static void
1469 grow_wlist(queuedir)
1470 	int queuedir;
1471 {
1472 	if (tTd(41, 1))
1473 		dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize);
1474 	if (WorkList == NULL)
1475 	{
1476 		WorkList = (WORK *) xalloc((sizeof *WorkList) *
1477 					   (QUEUESEGSIZE + 1));
1478 		WorkListSize = QUEUESEGSIZE;
1479 	}
1480 	else
1481 	{
1482 		int newsize = WorkListSize + QUEUESEGSIZE;
1483 		WORK *newlist = (WORK *) xrealloc((char *)WorkList,
1484 						  (unsigned)sizeof(WORK) * (newsize + 1));
1485 
1486 		if (newlist != NULL)
1487 		{
1488 			WorkListSize = newsize;
1489 			WorkList = newlist;
1490 			if (LogLevel > 1)
1491 			{
1492 				sm_syslog(LOG_INFO, NOQID,
1493 					  "grew WorkList for %s to %d",
1494 					  qid_printqueue(queuedir),
1495 					  WorkListSize);
1496 			}
1497 		}
1498 		else if (LogLevel > 0)
1499 		{
1500 			sm_syslog(LOG_ALERT, NOQID,
1501 				  "FAILED to grow WorkList for %s to %d",
1502 				  qid_printqueue(queuedir), newsize);
1503 		}
1504 	}
1505 	if (tTd(41, 1))
1506 		dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize);
1507 }
1508 /*
1509 **  WORKCMPF0 -- simple priority-only compare function.
1510 **
1511 **	Parameters:
1512 **		a -- the first argument.
1513 **		b -- the second argument.
1514 **
1515 **	Returns:
1516 **		-1 if a < b
1517 **		 0 if a == b
1518 **		+1 if a > b
1519 **
1520 **	Side Effects:
1521 **		none.
1522 */
1523 
1524 static int
1525 workcmpf0(a, b)
1526 	register WORK *a;
1527 	register WORK *b;
1528 {
1529 	long pa = a->w_pri;
1530 	long pb = b->w_pri;
1531 
1532 	if (pa == pb)
1533 		return 0;
1534 	else if (pa > pb)
1535 		return 1;
1536 	else
1537 		return -1;
1538 }
1539 /*
1540 **  WORKCMPF1 -- first compare function for ordering work based on host name.
1541 **
1542 **	Sorts on host name, lock status, and priority in that order.
1543 **
1544 **	Parameters:
1545 **		a -- the first argument.
1546 **		b -- the second argument.
1547 **
1548 **	Returns:
1549 **		<0 if a < b
1550 **		 0 if a == b
1551 **		>0 if a > b
1552 **
1553 **	Side Effects:
1554 **		none.
1555 */
1556 
1557 static int
1558 workcmpf1(a, b)
1559 	register WORK *a;
1560 	register WORK *b;
1561 {
1562 	int i;
1563 
1564 	/* host name */
1565 	if (a->w_host != NULL && b->w_host == NULL)
1566 		return 1;
1567 	else if (a->w_host == NULL && b->w_host != NULL)
1568 		return -1;
1569 	if (a->w_host != NULL && b->w_host != NULL &&
1570 	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1571 		return i;
1572 
1573 	/* lock status */
1574 	if (a->w_lock != b->w_lock)
1575 		return b->w_lock - a->w_lock;
1576 
1577 	/* job priority */
1578 	return workcmpf0(a, b);
1579 }
1580 /*
1581 **  WORKCMPF2 -- second compare function for ordering work based on host name.
1582 **
1583 **	Sorts on lock status, host name, and priority in that order.
1584 **
1585 **	Parameters:
1586 **		a -- the first argument.
1587 **		b -- the second argument.
1588 **
1589 **	Returns:
1590 **		<0 if a < b
1591 **		 0 if a == b
1592 **		>0 if a > b
1593 **
1594 **	Side Effects:
1595 **		none.
1596 */
1597 
1598 static int
1599 workcmpf2(a, b)
1600 	register WORK *a;
1601 	register WORK *b;
1602 {
1603 	int i;
1604 
1605 	/* lock status */
1606 	if (a->w_lock != b->w_lock)
1607 		return a->w_lock - b->w_lock;
1608 
1609 	/* host name */
1610 	if (a->w_host != NULL && b->w_host == NULL)
1611 		return 1;
1612 	else if (a->w_host == NULL && b->w_host != NULL)
1613 		return -1;
1614 	if (a->w_host != NULL && b->w_host != NULL &&
1615 	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1616 		return i;
1617 
1618 	/* job priority */
1619 	return workcmpf0(a, b);
1620 }
1621 /*
1622 **  WORKCMPF3 -- simple submission-time-only compare function.
1623 **
1624 **	Parameters:
1625 **		a -- the first argument.
1626 **		b -- the second argument.
1627 **
1628 **	Returns:
1629 **		-1 if a < b
1630 **		 0 if a == b
1631 **		+1 if a > b
1632 **
1633 **	Side Effects:
1634 **		none.
1635 */
1636 
1637 static int
1638 workcmpf3(a, b)
1639 	register WORK *a;
1640 	register WORK *b;
1641 {
1642 	if (a->w_ctime > b->w_ctime)
1643 		return 1;
1644 	else if (a->w_ctime < b->w_ctime)
1645 		return -1;
1646 	else
1647 		return 0;
1648 }
1649 /*
1650 **  WORKCMPF4 -- compare based on file name
1651 **
1652 **	Parameters:
1653 **		a -- the first argument.
1654 **		b -- the second argument.
1655 **
1656 **	Returns:
1657 **		-1 if a < b
1658 **		 0 if a == b
1659 **		+1 if a > b
1660 **
1661 **	Side Effects:
1662 **		none.
1663 */
1664 
1665 static int
1666 workcmpf4(a, b)
1667 	register WORK *a;
1668 	register WORK *b;
1669 {
1670 	return strcmp(a->w_name, b->w_name);
1671 }
1672 /*
1673 **  STRREV -- reverse string
1674 **
1675 **	Returns a pointer to a new string that is the reverse of
1676 **	the string pointed to by fwd.  The space for the new
1677 **	string is obtained using xalloc().
1678 **
1679 **	Parameters:
1680 **		fwd -- the string to reverse.
1681 **
1682 **	Returns:
1683 **		the reversed string.
1684 */
1685 
1686 static char *
1687 strrev(fwd)
1688 	char *fwd;
1689 {
1690 	char *rev = NULL;
1691 	int len, cnt;
1692 
1693 	len = strlen(fwd);
1694 	rev = xalloc(len + 1);
1695 	for (cnt = 0; cnt < len; ++cnt)
1696 		rev[cnt] = fwd[len - cnt - 1];
1697 	rev[len] = '\0';
1698 	return rev;
1699 }
1700 /*
1701 **  DOWORK -- do a work request.
1702 **
1703 **	Parameters:
1704 **		queuedir -- the index of the queue directory for the job.
1705 **		id -- the ID of the job to run.
1706 **		forkflag -- if set, run this in background.
1707 **		requeueflag -- if set, reinstantiate the queue quickly.
1708 **			This is used when expanding aliases in the queue.
1709 **			If forkflag is also set, it doesn't wait for the
1710 **			child.
1711 **		e - the envelope in which to run it.
1712 **
1713 **	Returns:
1714 **		process id of process that is running the queue job.
1715 **
1716 **	Side Effects:
1717 **		The work request is satisfied if possible.
1718 */
1719 
1720 pid_t
1721 dowork(queuedir, id, forkflag, requeueflag, e)
1722 	int queuedir;
1723 	char *id;
1724 	bool forkflag;
1725 	bool requeueflag;
1726 	register ENVELOPE *e;
1727 {
1728 	register pid_t pid;
1729 
1730 	if (tTd(40, 1))
1731 		dprintf("dowork(%s/%s)\n", qid_printqueue(queuedir), id);
1732 
1733 	/*
1734 	**  Fork for work.
1735 	*/
1736 
1737 	if (forkflag)
1738 	{
1739 		/*
1740 		**  Since the delivery may happen in a child and the
1741 		**  parent does not wait, the parent may close the
1742 		**  maps thereby removing any shared memory used by
1743 		**  the map.  Therefore, close the maps now so the
1744 		**  child will dynamically open them if necessary.
1745 		*/
1746 
1747 		closemaps();
1748 
1749 		pid = fork();
1750 		if (pid < 0)
1751 		{
1752 			syserr("dowork: cannot fork");
1753 			return 0;
1754 		}
1755 		else if (pid > 0)
1756 		{
1757 			/* parent -- clean out connection cache */
1758 			mci_flush(FALSE, NULL);
1759 		}
1760 		else
1761 		{
1762 			/* child -- error messages to the transcript */
1763 			QuickAbort = OnlyOneError = FALSE;
1764 		}
1765 	}
1766 	else
1767 	{
1768 		pid = 0;
1769 	}
1770 
1771 	if (pid == 0)
1772 	{
1773 		/*
1774 		**  CHILD
1775 		**	Lock the control file to avoid duplicate deliveries.
1776 		**		Then run the file as though we had just read it.
1777 		**	We save an idea of the temporary name so we
1778 		**		can recover on interrupt.
1779 		*/
1780 
1781 		/* Reset global flags */
1782 		RestartRequest = NULL;
1783 		ShutdownRequest = NULL;
1784 		PendingSignal = 0;
1785 
1786 		/* set basic modes, etc. */
1787 		(void) alarm(0);
1788 		clearstats();
1789 		clearenvelope(e, FALSE);
1790 		e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
1791 		set_delivery_mode(SM_DELIVER, e);
1792 		e->e_errormode = EM_MAIL;
1793 		e->e_id = id;
1794 		e->e_queuedir = queuedir;
1795 		GrabTo = UseErrorsTo = FALSE;
1796 		ExitStat = EX_OK;
1797 		if (forkflag)
1798 		{
1799 			disconnect(1, e);
1800 			OpMode = MD_QUEUERUN;
1801 		}
1802 		sm_setproctitle(TRUE, e, "%s: from queue", qid_printname(e));
1803 		if (LogLevel > 76)
1804 			sm_syslog(LOG_DEBUG, e->e_id,
1805 				  "dowork, pid=%d",
1806 				  (int) getpid());
1807 
1808 		/* don't use the headers from sendmail.cf... */
1809 		e->e_header = NULL;
1810 
1811 		/* read the queue control file -- return if locked */
1812 		if (!readqf(e))
1813 		{
1814 			if (tTd(40, 4) && e->e_id != NULL)
1815 				dprintf("readqf(%s) failed\n",
1816 					qid_printname(e));
1817 			e->e_id = NULL;
1818 			if (forkflag)
1819 				finis(FALSE, EX_OK);
1820 			else
1821 				return 0;
1822 		}
1823 
1824 		e->e_flags |= EF_INQUEUE;
1825 		eatheader(e, requeueflag);
1826 
1827 		if (requeueflag)
1828 			queueup(e, FALSE);
1829 
1830 		/* do the delivery */
1831 		sendall(e, SM_DELIVER);
1832 
1833 		/* finish up and exit */
1834 		if (forkflag)
1835 			finis(TRUE, ExitStat);
1836 		else
1837 			dropenvelope(e, TRUE);
1838 	}
1839 	e->e_id = NULL;
1840 	return pid;
1841 }
1842 /*
1843 **  READQF -- read queue file and set up environment.
1844 **
1845 **	Parameters:
1846 **		e -- the envelope of the job to run.
1847 **
1848 **	Returns:
1849 **		TRUE if it successfully read the queue file.
1850 **		FALSE otherwise.
1851 **
1852 **	Side Effects:
1853 **		The queue file is returned locked.
1854 */
1855 
1856 static bool
1857 readqf(e)
1858 	register ENVELOPE *e;
1859 {
1860 	register FILE *qfp;
1861 	ADDRESS *ctladdr;
1862 	struct stat st, stf;
1863 	char *bp;
1864 	int qfver = 0;
1865 	long hdrsize = 0;
1866 	register char *p;
1867 	char *orcpt = NULL;
1868 	bool nomore = FALSE;
1869 	MODE_T qsafe;
1870 	char qf[MAXPATHLEN];
1871 	char buf[MAXLINE];
1872 
1873 	/*
1874 	**  Read and process the file.
1875 	*/
1876 
1877 	(void) strlcpy(qf, queuename(e, 'q'), sizeof qf);
1878 	qfp = fopen(qf, "r+");
1879 	if (qfp == NULL)
1880 	{
1881 		int save_errno = errno;
1882 
1883 		if (tTd(40, 8))
1884 			dprintf("readqf(%s): fopen failure (%s)\n",
1885 				qf, errstring(errno));
1886 		errno = save_errno;
1887 		if (errno != ENOENT
1888 		    )
1889 			syserr("readqf: no control file %s", qf);
1890 		return FALSE;
1891 	}
1892 
1893 	if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB))
1894 	{
1895 		/* being processed by another queuer */
1896 		if (Verbose)
1897 			printf("%s: locked\n", e->e_id);
1898 		if (tTd(40, 8))
1899 			dprintf("%s: locked\n", e->e_id);
1900 		if (LogLevel > 19)
1901 			sm_syslog(LOG_DEBUG, e->e_id, "locked");
1902 		(void) fclose(qfp);
1903 		return FALSE;
1904 	}
1905 
1906 	/*
1907 	**  Prevent locking race condition.
1908 	**
1909 	**  Process A: readqf(): qfp = fopen(qffile)
1910 	**  Process B: queueup(): rename(tf, qf)
1911 	**  Process B: unlocks(tf)
1912 	**  Process A: lockfile(qf);
1913 	**
1914 	**  Process A (us) has the old qf file (before the rename deleted
1915 	**  the directory entry) and will be delivering based on old data.
1916 	**  This can lead to multiple deliveries of the same recipients.
1917 	**
1918 	**  Catch this by checking if the underlying qf file has changed
1919 	**  *after* acquiring our lock and if so, act as though the file
1920 	**  was still locked (i.e., just return like the lockfile() case
1921 	**  above.
1922 	*/
1923 
1924 	if (stat(qf, &stf) < 0 ||
1925 	    fstat(fileno(qfp), &st) < 0)
1926 	{
1927 		/* must have been being processed by someone else */
1928 		if (tTd(40, 8))
1929 			dprintf("readqf(%s): [f]stat failure (%s)\n",
1930 				qf, errstring(errno));
1931 		(void) fclose(qfp);
1932 		return FALSE;
1933 	}
1934 
1935 	if (st.st_nlink != stf.st_nlink ||
1936 	    st.st_dev != stf.st_dev ||
1937 	    st.st_ino != stf.st_ino ||
1938 # if HAS_ST_GEN && 0		/* AFS returns garbage in st_gen */
1939 	    st.st_gen != stf.st_gen ||
1940 # endif /* HAS_ST_GEN && 0 */
1941 	    st.st_uid != stf.st_uid ||
1942 	    st.st_gid != stf.st_gid ||
1943 	    st.st_size != stf.st_size)
1944 	{
1945 		/* changed after opened */
1946 		if (Verbose)
1947 			printf("%s: changed\n", e->e_id);
1948 		if (tTd(40, 8))
1949 			dprintf("%s: changed\n", e->e_id);
1950 		if (LogLevel > 19)
1951 			sm_syslog(LOG_DEBUG, e->e_id, "changed");
1952 		(void) fclose(qfp);
1953 		return FALSE;
1954 	}
1955 
1956 	/*
1957 	**  Check the queue file for plausibility to avoid attacks.
1958 	*/
1959 
1960 	qsafe = S_IWOTH|S_IWGRP;
1961 #if _FFR_QUEUE_FILE_MODE
1962 	if (bitset(S_IWGRP, QueueFileMode))
1963 		qsafe &= ~S_IWGRP;
1964 #endif /* _FFR_QUEUE_FILE_MODE */
1965 
1966 	if ((st.st_uid != geteuid() &&
1967 	     st.st_uid != TrustedUid &&
1968 	     geteuid() != RealUid) ||
1969 	    bitset(qsafe, st.st_mode))
1970 	{
1971 		if (LogLevel > 0)
1972 		{
1973 			sm_syslog(LOG_ALERT, e->e_id,
1974 				  "bogus queue file, uid=%d, mode=%o",
1975 				  st.st_uid, st.st_mode);
1976 		}
1977 		if (tTd(40, 8))
1978 			dprintf("readqf(%s): bogus file\n", qf);
1979 		loseqfile(e, "bogus file uid in mqueue");
1980 		(void) fclose(qfp);
1981 		return FALSE;
1982 	}
1983 
1984 	if (st.st_size == 0)
1985 	{
1986 		/* must be a bogus file -- if also old, just remove it */
1987 		if (st.st_ctime + 10 * 60 < curtime())
1988 		{
1989 			(void) xunlink(queuename(e, 'd'));
1990 			(void) xunlink(queuename(e, 'q'));
1991 		}
1992 		(void) fclose(qfp);
1993 		return FALSE;
1994 	}
1995 
1996 	if (st.st_nlink == 0)
1997 	{
1998 		/*
1999 		**  Race condition -- we got a file just as it was being
2000 		**  unlinked.  Just assume it is zero length.
2001 		*/
2002 
2003 		(void) fclose(qfp);
2004 		return FALSE;
2005 	}
2006 
2007 	/* good file -- save this lock */
2008 	e->e_lockfp = qfp;
2009 
2010 	/* do basic system initialization */
2011 	initsys(e);
2012 	define('i', e->e_id, e);
2013 
2014 	LineNumber = 0;
2015 	e->e_flags |= EF_GLOBALERRS;
2016 	OpMode = MD_QUEUERUN;
2017 	ctladdr = NULL;
2018 	e->e_dfino = -1;
2019 	e->e_msgsize = -1;
2020 # if _FFR_QUEUEDELAY
2021 	e->e_queuealg = QD_LINEAR;
2022 	e->e_queuedelay = (time_t) 0;
2023 # endif /* _FFR_QUEUEDELAY */
2024 	while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
2025 	{
2026 		u_long qflags;
2027 		ADDRESS *q;
2028 		int mid;
2029 		time_t now;
2030 		auto char *ep;
2031 
2032 		if (tTd(40, 4))
2033 			dprintf("+++++ %s\n", bp);
2034 		if (nomore)
2035 		{
2036 			/* hack attack */
2037 			syserr("SECURITY ALERT: extra data in qf: %s", bp);
2038 			(void) fclose(qfp);
2039 			loseqfile(e, "bogus queue line");
2040 			return FALSE;
2041 		}
2042 		switch (bp[0])
2043 		{
2044 		  case 'V':		/* queue file version number */
2045 			qfver = atoi(&bp[1]);
2046 			if (qfver <= QF_VERSION)
2047 				break;
2048 			syserr("Version number in qf (%d) greater than max (%d)",
2049 				qfver, QF_VERSION);
2050 			(void) fclose(qfp);
2051 			loseqfile(e, "unsupported qf file version");
2052 			return FALSE;
2053 
2054 		  case 'C':		/* specify controlling user */
2055 			ctladdr = setctluser(&bp[1], qfver);
2056 			break;
2057 
2058 		  case 'Q':		/* original recipient */
2059 			orcpt = newstr(&bp[1]);
2060 			break;
2061 
2062 		  case 'R':		/* specify recipient */
2063 			p = bp;
2064 			qflags = 0;
2065 			if (qfver >= 1)
2066 			{
2067 				/* get flag bits */
2068 				while (*++p != '\0' && *p != ':')
2069 				{
2070 					switch (*p)
2071 					{
2072 					  case 'N':
2073 						qflags |= QHASNOTIFY;
2074 						break;
2075 
2076 					  case 'S':
2077 						qflags |= QPINGONSUCCESS;
2078 						break;
2079 
2080 					  case 'F':
2081 						qflags |= QPINGONFAILURE;
2082 						break;
2083 
2084 					  case 'D':
2085 						qflags |= QPINGONDELAY;
2086 						break;
2087 
2088 					  case 'P':
2089 						qflags |= QPRIMARY;
2090 						break;
2091 
2092 					  case 'A':
2093 						if (ctladdr != NULL)
2094 							ctladdr->q_flags |= QALIAS;
2095 						break;
2096 					}
2097 				}
2098 			}
2099 			else
2100 				qflags |= QPRIMARY;
2101 			q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e);
2102 			if (q != NULL)
2103 			{
2104 				q->q_alias = ctladdr;
2105 				if (qfver >= 1)
2106 					q->q_flags &= ~Q_PINGFLAGS;
2107 				q->q_flags |= qflags;
2108 				q->q_orcpt = orcpt;
2109 				(void) recipient(q, &e->e_sendqueue, 0, e);
2110 			}
2111 			orcpt = NULL;
2112 			break;
2113 
2114 		  case 'E':		/* specify error recipient */
2115 			/* no longer used */
2116 			break;
2117 
2118 		  case 'H':		/* header */
2119 			(void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e);
2120 			hdrsize += strlen(&bp[1]);
2121 			break;
2122 
2123 		  case 'L':		/* Solaris Content-Length: */
2124 		  case 'M':		/* message */
2125 			/* ignore this; we want a new message next time */
2126 			break;
2127 
2128 		  case 'S':		/* sender */
2129 			setsender(newstr(&bp[1]), e, NULL, '\0', TRUE);
2130 			break;
2131 
2132 		  case 'B':		/* body type */
2133 			e->e_bodytype = newstr(&bp[1]);
2134 			break;
2135 
2136 # if _FFR_SAVE_CHARSET
2137 		  case 'X':		/* character set */
2138 			e->e_charset = newstr(&bp[1]);
2139 			break;
2140 # endif /* _FFR_SAVE_CHARSET */
2141 
2142 		  case 'D':		/* data file name */
2143 			/* obsolete -- ignore */
2144 			break;
2145 
2146 		  case 'T':		/* init time */
2147 			e->e_ctime = atol(&bp[1]);
2148 			break;
2149 
2150 		  case 'I':		/* data file's inode number */
2151 			/* regenerated below */
2152 			break;
2153 
2154 		  case 'K':	/* time of last delivery attempt */
2155 			e->e_dtime = atol(&buf[1]);
2156 			break;
2157 
2158 # if _FFR_QUEUEDELAY
2159 		  case 'G':	/* queue delay algorithm */
2160 			e->e_queuealg = atoi(&buf[1]);
2161 			break;
2162 		  case 'Y':	/* current delay */
2163 			e->e_queuedelay = (time_t) atol(&buf[1]);
2164 			break;
2165 # endif /* _FFR_QUEUEDELAY */
2166 
2167 		  case 'N':		/* number of delivery attempts */
2168 			e->e_ntries = atoi(&buf[1]);
2169 
2170 			/* if this has been tried recently, let it be */
2171 			now = curtime();
2172 			if (e->e_ntries > 0 && e->e_dtime <= now &&
2173 			    now < e->e_dtime + queuedelay(e))
2174 			{
2175 				char *howlong;
2176 
2177 				howlong = pintvl(now - e->e_dtime, TRUE);
2178 				if (Verbose)
2179 					printf("%s: too young (%s)\n",
2180 					       e->e_id, howlong);
2181 				if (tTd(40, 8))
2182 					dprintf("%s: too young (%s)\n",
2183 						e->e_id, howlong);
2184 				if (LogLevel > 19)
2185 					sm_syslog(LOG_DEBUG, e->e_id,
2186 						  "too young (%s)",
2187 						  howlong);
2188 				e->e_id = NULL;
2189 				unlockqueue(e);
2190 				return FALSE;
2191 			}
2192 			define(macid("{ntries}", NULL), newstr(&buf[1]), e);
2193 
2194 # if NAMED_BIND
2195 			/* adjust BIND parameters immediately */
2196 			if (e->e_ntries == 0)
2197 			{
2198 				_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
2199 				_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
2200 			}
2201 			else
2202 			{
2203 				_res.retry = TimeOuts.res_retry[RES_TO_NORMAL];
2204 				_res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL];
2205 			}
2206 # endif /* NAMED_BIND */
2207 			break;
2208 
2209 		  case 'P':		/* message priority */
2210 			e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
2211 			break;
2212 
2213 		  case 'F':		/* flag bits */
2214 			if (strncmp(bp, "From ", 5) == 0)
2215 			{
2216 				/* we are being spoofed! */
2217 				syserr("SECURITY ALERT: bogus qf line %s", bp);
2218 				(void) fclose(qfp);
2219 				loseqfile(e, "bogus queue line");
2220 				return FALSE;
2221 			}
2222 			for (p = &bp[1]; *p != '\0'; p++)
2223 			{
2224 				switch (*p)
2225 				{
2226 				  case 'w':	/* warning sent */
2227 					e->e_flags |= EF_WARNING;
2228 					break;
2229 
2230 				  case 'r':	/* response */
2231 					e->e_flags |= EF_RESPONSE;
2232 					break;
2233 
2234 				  case '8':	/* has 8 bit data */
2235 					e->e_flags |= EF_HAS8BIT;
2236 					break;
2237 
2238 				  case 'b':	/* delete Bcc: header */
2239 					e->e_flags |= EF_DELETE_BCC;
2240 					break;
2241 
2242 				  case 'd':	/* envelope has DSN RET= */
2243 					e->e_flags |= EF_RET_PARAM;
2244 					break;
2245 
2246 				  case 'n':	/* don't return body */
2247 					e->e_flags |= EF_NO_BODY_RETN;
2248 					break;
2249 				}
2250 			}
2251 			break;
2252 
2253 		  case 'Z':		/* original envelope id from ESMTP */
2254 			e->e_envid = newstr(&bp[1]);
2255 			define(macid("{dsn_envid}", NULL), newstr(&bp[1]), e);
2256 			break;
2257 
2258 		  case 'A':		/* AUTH= parameter */
2259 			e->e_auth_param = newstr(&bp[1]);
2260 			break;
2261 
2262 		  case '$':		/* define macro */
2263 			{
2264 				char *p;
2265 
2266 				mid = macid(&bp[1], &ep);
2267 				if (mid == 0)
2268 					break;
2269 
2270 				p = newstr(ep);
2271 				define(mid, p, e);
2272 
2273 				/*
2274 				**  HACK ALERT: Unfortunately, 8.10 and
2275 				**  8.11 reused the ${if_addr} and
2276 				**  ${if_family} macros for both the incoming
2277 				**  interface address/family (getrequests())
2278 				**  and the outgoing interface address/family
2279 				**  (makeconnection()).  In order for D_BINDIF
2280 				**  to work properly, have to preserve the
2281 				**  incoming information in the queue file for
2282 				**  later delivery attempts.  The original
2283 				**  information is stored in the envelope
2284 				**  in readqf() so it can be stored in
2285 				**  queueup_macros().  This should be fixed
2286 				**  in 8.12.
2287 				*/
2288 
2289 				if (strcmp(macname(mid), "if_addr") == 0)
2290 					e->e_if_macros[EIF_ADDR] = p;
2291 			}
2292 			break;
2293 
2294 		  case '.':		/* terminate file */
2295 			nomore = TRUE;
2296 			break;
2297 
2298 		  default:
2299 			syserr("readqf: %s: line %d: bad line \"%s\"",
2300 				qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
2301 			(void) fclose(qfp);
2302 			loseqfile(e, "unrecognized line");
2303 			return FALSE;
2304 		}
2305 
2306 		if (bp != buf)
2307 			sm_free(bp);
2308 	}
2309 
2310 	/*
2311 	**  If we haven't read any lines, this queue file is empty.
2312 	**  Arrange to remove it without referencing any null pointers.
2313 	*/
2314 
2315 	if (LineNumber == 0)
2316 	{
2317 		errno = 0;
2318 		e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
2319 		return TRUE;
2320 	}
2321 
2322 	/* possibly set ${dsn_ret} macro */
2323 	if (bitset(EF_RET_PARAM, e->e_flags))
2324 	{
2325 		if (bitset(EF_NO_BODY_RETN, e->e_flags))
2326 			define(macid("{dsn_ret}", NULL), "hdrs", e);
2327 		else
2328 			define(macid("{dsn_ret}", NULL), "full", e);
2329 	}
2330 
2331 	/*
2332 	**  Arrange to read the data file.
2333 	*/
2334 
2335 	p = queuename(e, 'd');
2336 	e->e_dfp = fopen(p, "r");
2337 	if (e->e_dfp == NULL)
2338 	{
2339 		syserr("readqf: cannot open %s", p);
2340 	}
2341 	else
2342 	{
2343 		e->e_flags |= EF_HAS_DF;
2344 		if (fstat(fileno(e->e_dfp), &st) >= 0)
2345 		{
2346 			e->e_msgsize = st.st_size + hdrsize;
2347 			e->e_dfdev = st.st_dev;
2348 			e->e_dfino = st.st_ino;
2349 		}
2350 	}
2351 
2352 	return TRUE;
2353 }
2354 /*
2355 **  PRTSTR -- print a string, "unprintable" characters are shown as \oct
2356 **
2357 **	Parameters:
2358 **		s -- string to print
2359 **		ml -- maximum length of output
2360 **
2361 **	Returns:
2362 **		none.
2363 **
2364 **	Side Effects:
2365 **		Prints a string on stdout.
2366 */
2367 
2368 static void
2369 prtstr(s, ml)
2370 	char *s;
2371 	int ml;
2372 {
2373 	char c;
2374 
2375 	if (s == NULL)
2376 		return;
2377 	while (ml-- > 0 && ((c = *s++) != '\0'))
2378 	{
2379 		if (c == '\\')
2380 		{
2381 			if (ml-- > 0)
2382 			{
2383 				putchar(c);
2384 				putchar(c);
2385 			}
2386 		}
2387 		else if (isascii(c) && isprint(c))
2388 			putchar(c);
2389 		else
2390 		{
2391 			if ((ml -= 3) > 0)
2392 				printf("\\%03o", c);
2393 		}
2394 	}
2395 }
2396 /*
2397 **  PRINTQUEUE -- print out a representation of the mail queue
2398 **
2399 **	Parameters:
2400 **		none.
2401 **
2402 **	Returns:
2403 **		none.
2404 **
2405 **	Side Effects:
2406 **		Prints a listing of the mail queue on the standard output.
2407 */
2408 
2409 void
2410 printqueue()
2411 {
2412 	int i, nrequests = 0;
2413 
2414 	for (i = 0; i < NumQueues; i++)
2415 	{
2416 		if (StopRequest)
2417 			stop_sendmail();
2418 		nrequests += print_single_queue(i);
2419 	}
2420 	if (NumQueues > 1)
2421 		printf("\t\tTotal Requests: %d\n", nrequests);
2422 }
2423 /*
2424 **  PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue
2425 **
2426 **	Parameters:
2427 **		queuedir -- queue directory
2428 **
2429 **	Returns:
2430 **		number of entries
2431 **
2432 **	Side Effects:
2433 **		Prints a listing of the mail queue on the standard output.
2434 */
2435 
2436 static int
2437 print_single_queue(queuedir)
2438 	int queuedir;
2439 {
2440 	register WORK *w;
2441 	FILE *f;
2442 	int nrequests;
2443 	char qd[MAXPATHLEN];
2444 	char qddf[MAXPATHLEN];
2445 	char buf[MAXLINE];
2446 
2447 	if (queuedir == NOQDIR)
2448 	{
2449 		(void) strlcpy(qd, ".", sizeof qd);
2450 		(void) strlcpy(qddf, ".", sizeof qddf);
2451 	}
2452 	else
2453 	{
2454 		(void) snprintf(qd, sizeof qd, "%s%s",
2455 				QPaths[queuedir].qp_name,
2456 				(bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : ""));
2457 		(void) snprintf(qddf, sizeof qddf, "%s%s",
2458 				QPaths[queuedir].qp_name,
2459 				(bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : ""));
2460 	}
2461 
2462 	/*
2463 	**  Check for permission to print the queue
2464 	*/
2465 
2466 	if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
2467 	{
2468 		struct stat st;
2469 # ifdef NGROUPS_MAX
2470 		int n;
2471 		extern GIDSET_T InitialGidSet[NGROUPS_MAX];
2472 # endif /* NGROUPS_MAX */
2473 
2474 		if (stat(qd, &st) < 0)
2475 		{
2476 			syserr("Cannot stat %s", qid_printqueue(queuedir));
2477 			return 0;
2478 		}
2479 # ifdef NGROUPS_MAX
2480 		n = NGROUPS_MAX;
2481 		while (--n >= 0)
2482 		{
2483 			if (InitialGidSet[n] == st.st_gid)
2484 				break;
2485 		}
2486 		if (n < 0 && RealGid != st.st_gid)
2487 # else /* NGROUPS_MAX */
2488 		if (RealGid != st.st_gid)
2489 # endif /* NGROUPS_MAX */
2490 		{
2491 			usrerr("510 You are not permitted to see the queue");
2492 			setstat(EX_NOPERM);
2493 			return 0;
2494 		}
2495 	}
2496 
2497 	/*
2498 	**  Read and order the queue.
2499 	*/
2500 
2501 	nrequests = orderq(queuedir, TRUE);
2502 
2503 	/*
2504 	**  Print the work list that we have read.
2505 	*/
2506 
2507 	/* first see if there is anything */
2508 	if (nrequests <= 0)
2509 	{
2510 		printf("%s is empty\n", qid_printqueue(queuedir));
2511 		return 0;
2512 	}
2513 
2514 	CurrentLA = sm_getla(NULL);	/* get load average */
2515 
2516 	printf("\t\t%s (%d request%s", qid_printqueue(queuedir), nrequests,
2517 	       nrequests == 1 ? "" : "s");
2518 	if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
2519 		printf(", only %d printed", MaxQueueRun);
2520 	if (Verbose)
2521 		printf(")\n----Q-ID---- --Size-- -Priority- ---Q-Time--- ---------Sender/Recipient--------\n");
2522 	else
2523 		printf(")\n----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
2524 	for (w = WorkQ; w != NULL; w = w->w_next)
2525 	{
2526 		struct stat st;
2527 		auto time_t submittime = 0;
2528 		long dfsize;
2529 		int flags = 0;
2530 		int qfver;
2531 		char statmsg[MAXLINE];
2532 		char bodytype[MAXNAME + 1];
2533 		char qf[MAXPATHLEN];
2534 
2535 		if (StopRequest)
2536 			stop_sendmail();
2537 
2538 		printf("%12s", w->w_name + 2);
2539 		(void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name);
2540 		f = fopen(qf, "r");
2541 		if (f == NULL)
2542 		{
2543 			printf(" (job completed)\n");
2544 			errno = 0;
2545 			continue;
2546 		}
2547 		w->w_name[0] = 'd';
2548 		(void) snprintf(qf, sizeof qf, "%s/%s", qddf, w->w_name);
2549 		if (stat(qf, &st) >= 0)
2550 			dfsize = st.st_size;
2551 		else
2552 			dfsize = -1;
2553 		if (w->w_lock)
2554 			printf("*");
2555 		else if (w->w_tooyoung)
2556 			printf("-");
2557 		else if (shouldqueue(w->w_pri, w->w_ctime))
2558 			printf("X");
2559 		else
2560 			printf(" ");
2561 		errno = 0;
2562 
2563 		statmsg[0] = bodytype[0] = '\0';
2564 		qfver = 0;
2565 		while (fgets(buf, sizeof buf, f) != NULL)
2566 		{
2567 			register int i;
2568 			register char *p;
2569 
2570 			if (StopRequest)
2571 				stop_sendmail();
2572 
2573 			fixcrlf(buf, TRUE);
2574 			switch (buf[0])
2575 			{
2576 			  case 'V':	/* queue file version */
2577 				qfver = atoi(&buf[1]);
2578 				break;
2579 
2580 			  case 'M':	/* error message */
2581 				if ((i = strlen(&buf[1])) >= sizeof statmsg)
2582 					i = sizeof statmsg - 1;
2583 				memmove(statmsg, &buf[1], i);
2584 				statmsg[i] = '\0';
2585 				break;
2586 
2587 			  case 'B':	/* body type */
2588 				if ((i = strlen(&buf[1])) >= sizeof bodytype)
2589 					i = sizeof bodytype - 1;
2590 				memmove(bodytype, &buf[1], i);
2591 				bodytype[i] = '\0';
2592 				break;
2593 
2594 			  case 'S':	/* sender name */
2595 				if (Verbose)
2596 				{
2597 					printf("%8ld %10ld%c%.12s ",
2598 					       dfsize,
2599 					       w->w_pri,
2600 					       bitset(EF_WARNING, flags) ? '+' : ' ',
2601 					       ctime(&submittime) + 4);
2602 					prtstr(&buf[1], 78);
2603 				}
2604 				else
2605 				{
2606 					printf("%8ld %.16s ", dfsize,
2607 					    ctime(&submittime));
2608 					prtstr(&buf[1], 40);
2609 				}
2610 				if (statmsg[0] != '\0' || bodytype[0] != '\0')
2611 				{
2612 					printf("\n    %10.10s", bodytype);
2613 					if (statmsg[0] != '\0')
2614 						printf("   (%.*s)",
2615 						       Verbose ? 100 : 60,
2616 						       statmsg);
2617 				}
2618 				break;
2619 
2620 			  case 'C':	/* controlling user */
2621 				if (Verbose)
2622 					printf("\n\t\t\t\t      (---%.74s---)",
2623 					       &buf[1]);
2624 				break;
2625 
2626 			  case 'R':	/* recipient name */
2627 				p = &buf[1];
2628 				if (qfver >= 1)
2629 				{
2630 					p = strchr(p, ':');
2631 					if (p == NULL)
2632 						break;
2633 					p++;
2634 				}
2635 				if (Verbose)
2636 				{
2637 					printf("\n\t\t\t\t\t      ");
2638 					prtstr(p, 73);
2639 				}
2640 				else
2641 				{
2642 					printf("\n\t\t\t\t       ");
2643 					prtstr(p, 40);
2644 				}
2645 				break;
2646 
2647 			  case 'T':	/* creation time */
2648 				submittime = atol(&buf[1]);
2649 				break;
2650 
2651 			  case 'F':	/* flag bits */
2652 				for (p = &buf[1]; *p != '\0'; p++)
2653 				{
2654 					switch (*p)
2655 					{
2656 					  case 'w':
2657 						flags |= EF_WARNING;
2658 						break;
2659 					}
2660 				}
2661 			}
2662 		}
2663 		if (submittime == (time_t) 0)
2664 			printf(" (no control file)");
2665 		printf("\n");
2666 		(void) fclose(f);
2667 	}
2668 	return nrequests;
2669 }
2670 /*
2671 **  QUEUENAME -- build a file name in the queue directory for this envelope.
2672 **
2673 **	Parameters:
2674 **		e -- envelope to build it in/from.
2675 **		type -- the file type, used as the first character
2676 **			of the file name.
2677 **
2678 **	Returns:
2679 **		a pointer to the queue name (in a static buffer).
2680 **
2681 **	Side Effects:
2682 **		If no id code is already assigned, queuename() will
2683 **		assign an id code with assign_queueid().  If no queue
2684 **		directory is assigned, one will be set with setnewqueue().
2685 */
2686 
2687 char *
2688 queuename(e, type)
2689 	register ENVELOPE *e;
2690 	int type;
2691 {
2692 	char *sub = "";
2693 	static char buf[MAXPATHLEN];
2694 
2695 	/* Assign an ID if needed */
2696 	if (e->e_id == NULL)
2697 		assign_queueid(e);
2698 
2699 	/* Assign a queue directory if needed */
2700 	if (e->e_queuedir == NOQDIR)
2701 		setnewqueue(e);
2702 
2703 	if (e->e_queuedir == NOQDIR)
2704 		(void) snprintf(buf, sizeof buf, "%cf%s",
2705 				type, e->e_id);
2706 	else
2707 	{
2708 		switch (type)
2709 		{
2710 		  case 'd':
2711 			if (bitset(QP_SUBDF, QPaths[e->e_queuedir].qp_subdirs))
2712 				sub = "/df";
2713 			break;
2714 
2715 		  case TEMPQF_LETTER:
2716 		  case 't':
2717 		  case LOSEQF_LETTER:
2718 		  case 'q':
2719 			if (bitset(QP_SUBQF, QPaths[e->e_queuedir].qp_subdirs))
2720 				sub = "/qf";
2721 			break;
2722 
2723 		  case 'x':
2724 			if (bitset(QP_SUBXF, QPaths[e->e_queuedir].qp_subdirs))
2725 				sub = "/xf";
2726 			break;
2727 		}
2728 
2729 		(void) snprintf(buf, sizeof buf, "%s%s/%cf%s",
2730 				QPaths[e->e_queuedir].qp_name,
2731 				sub, type, e->e_id);
2732 	}
2733 
2734 	if (tTd(7, 2))
2735 		dprintf("queuename: %s\n", buf);
2736 	return buf;
2737 }
2738 /*
2739 **  ASSIGN_QUEUEID -- assign a queue ID for this envelope.
2740 **
2741 **	Assigns an id code if one does not already exist.
2742 **	This code assumes that nothing will remain in the queue for
2743 **	longer than 60 years.  It is critical that files with the given
2744 **	name not already exist in the queue.
2745 **	Also initializes e_queuedir to NOQDIR.
2746 **
2747 **	Parameters:
2748 **		e -- envelope to set it in.
2749 **
2750 **	Returns:
2751 **		none.
2752 */
2753 
2754 static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx";
2755 # define QIC_LEN	60
2756 
2757 void
2758 assign_queueid(e)
2759 	register ENVELOPE *e;
2760 {
2761 	pid_t pid = getpid();
2762 	static char cX = 0;
2763 	static long random_offset;
2764 	struct tm *tm;
2765 	char idbuf[MAXQFNAME - 2];
2766 
2767 	if (e->e_id != NULL)
2768 		return;
2769 
2770 	/* see if we need to get a new base time/pid */
2771 	if (cX >= QIC_LEN || LastQueueTime == 0 || LastQueuePid != pid)
2772 	{
2773 		time_t then = LastQueueTime;
2774 
2775 		/* if the first time through, pick a random offset */
2776 		if (LastQueueTime == 0)
2777 			random_offset = get_random();
2778 
2779 		while ((LastQueueTime = curtime()) == then &&
2780 		       LastQueuePid == pid)
2781 		{
2782 			(void) sleep(1);
2783 		}
2784 		LastQueuePid = getpid();
2785 		cX = 0;
2786 	}
2787 	if (tTd(7, 50))
2788 		dprintf("assign_queueid: random_offset = %ld (%d)\n",
2789 			random_offset, (int)(cX + random_offset) % QIC_LEN);
2790 
2791 	tm = gmtime(&LastQueueTime);
2792 	idbuf[0] = QueueIdChars[tm->tm_year % QIC_LEN];
2793 	idbuf[1] = QueueIdChars[tm->tm_mon];
2794 	idbuf[2] = QueueIdChars[tm->tm_mday];
2795 	idbuf[3] = QueueIdChars[tm->tm_hour];
2796 	idbuf[4] = QueueIdChars[tm->tm_min];
2797 	idbuf[5] = QueueIdChars[tm->tm_sec];
2798 	idbuf[6] = QueueIdChars[((int)cX++ + random_offset) % QIC_LEN];
2799 	(void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d",
2800 			(int) LastQueuePid);
2801 	e->e_id = newstr(idbuf);
2802 	define('i', e->e_id, e);
2803 	e->e_queuedir = NOQDIR;
2804 	if (tTd(7, 1))
2805 		dprintf("assign_queueid: assigned id %s, e=%lx\n",
2806 			e->e_id, (u_long) e);
2807 	if (LogLevel > 93)
2808 		sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
2809 }
2810 /*
2811 **  SYNC_QUEUE_TIME -- Assure exclusive PID in any given second
2812 **
2813 **	Make sure one PID can't be used by two processes in any one second.
2814 **
2815 **		If the system rotates PIDs fast enough, may get the
2816 **		same pid in the same second for two distinct processes.
2817 **		This will interfere with the queue file naming system.
2818 **
2819 **	Parameters:
2820 **		none
2821 **
2822 **	Returns:
2823 **		none
2824 */
2825 void
2826 sync_queue_time()
2827 {
2828 # if FAST_PID_RECYCLE
2829 	if (OpMode != MD_TEST &&
2830 	    OpMode != MD_VERIFY &&
2831 	    LastQueueTime > 0 &&
2832 	    LastQueuePid == getpid() &&
2833 	    curtime() == LastQueueTime)
2834 		(void) sleep(1);
2835 # endif /* FAST_PID_RECYCLE */
2836 }
2837 /*
2838 **  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
2839 **
2840 **	Parameters:
2841 **		e -- the envelope to unlock.
2842 **
2843 **	Returns:
2844 **		none
2845 **
2846 **	Side Effects:
2847 **		unlocks the queue for `e'.
2848 */
2849 
2850 void
2851 unlockqueue(e)
2852 	ENVELOPE *e;
2853 {
2854 	if (tTd(51, 4))
2855 		dprintf("unlockqueue(%s)\n",
2856 			e->e_id == NULL ? "NOQUEUE" : e->e_id);
2857 
2858 
2859 	/* if there is a lock file in the envelope, close it */
2860 	if (e->e_lockfp != NULL)
2861 		(void) fclose(e->e_lockfp);
2862 	e->e_lockfp = NULL;
2863 
2864 	/* don't create a queue id if we don't already have one */
2865 	if (e->e_id == NULL)
2866 		return;
2867 
2868 	/* remove the transcript */
2869 	if (LogLevel > 87)
2870 		sm_syslog(LOG_DEBUG, e->e_id, "unlock");
2871 	if (!tTd(51, 104))
2872 		xunlink(queuename(e, 'x'));
2873 
2874 }
2875 /*
2876 **  SETCTLUSER -- create a controlling address
2877 **
2878 **	Create a fake "address" given only a local login name; this is
2879 **	used as a "controlling user" for future recipient addresses.
2880 **
2881 **	Parameters:
2882 **		user -- the user name of the controlling user.
2883 **		qfver -- the version stamp of this qf file.
2884 **
2885 **	Returns:
2886 **		An address descriptor for the controlling user.
2887 **
2888 **	Side Effects:
2889 **		none.
2890 */
2891 
2892 static ADDRESS *
2893 setctluser(user, qfver)
2894 	char *user;
2895 	int qfver;
2896 {
2897 	register ADDRESS *a;
2898 	struct passwd *pw;
2899 	char *p;
2900 
2901 	/*
2902 	**  See if this clears our concept of controlling user.
2903 	*/
2904 
2905 	if (user == NULL || *user == '\0')
2906 		return NULL;
2907 
2908 	/*
2909 	**  Set up addr fields for controlling user.
2910 	*/
2911 
2912 	a = (ADDRESS *) xalloc(sizeof *a);
2913 	memset((char *) a, '\0', sizeof *a);
2914 
2915 	if (*user == '\0')
2916 	{
2917 		p = NULL;
2918 		a->q_user = newstr(DefUser);
2919 	}
2920 	else if (*user == ':')
2921 	{
2922 		p = &user[1];
2923 		a->q_user = newstr(p);
2924 	}
2925 	else
2926 	{
2927 		p = strtok(user, ":");
2928 		a->q_user = newstr(user);
2929 		if (qfver >= 2)
2930 		{
2931 			if ((p = strtok(NULL, ":")) != NULL)
2932 				a->q_uid = atoi(p);
2933 			if ((p = strtok(NULL, ":")) != NULL)
2934 				a->q_gid = atoi(p);
2935 			if ((p = strtok(NULL, ":")) != NULL)
2936 				a->q_flags |= QGOODUID;
2937 		}
2938 		else if ((pw = sm_getpwnam(user)) != NULL)
2939 		{
2940 			if (*pw->pw_dir == '\0')
2941 				a->q_home = NULL;
2942 			else if (strcmp(pw->pw_dir, "/") == 0)
2943 				a->q_home = "";
2944 			else
2945 				a->q_home = newstr(pw->pw_dir);
2946 			a->q_uid = pw->pw_uid;
2947 			a->q_gid = pw->pw_gid;
2948 			a->q_flags |= QGOODUID;
2949 		}
2950 	}
2951 
2952 	a->q_flags |= QPRIMARY;		/* flag as a "ctladdr" */
2953 	a->q_mailer = LocalMailer;
2954 	if (p == NULL)
2955 		a->q_paddr = newstr(a->q_user);
2956 	else
2957 		a->q_paddr = newstr(p);
2958 	return a;
2959 }
2960 /*
2961 **  LOSEQFILE -- save the qf as Qf and try to let someone know
2962 **
2963 **	Parameters:
2964 **		e -- the envelope (e->e_id will be used).
2965 **		why -- reported to whomever can hear.
2966 **
2967 **	Returns:
2968 **		none.
2969 */
2970 
2971 void
2972 loseqfile(e, why)
2973 	register ENVELOPE *e;
2974 	char *why;
2975 {
2976 	char *p;
2977 	char buf[MAXPATHLEN];
2978 
2979 	if (e == NULL || e->e_id == NULL)
2980 		return;
2981 	p = queuename(e, 'q');
2982 	if (strlen(p) >= (SIZE_T) sizeof buf)
2983 		return;
2984 	(void) strlcpy(buf, p, sizeof buf);
2985 	p = queuename(e, LOSEQF_LETTER);
2986 	if (rename(buf, p) < 0)
2987 		syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
2988 	else if (LogLevel > 0)
2989 		sm_syslog(LOG_ALERT, e->e_id,
2990 			  "Losing %s: %s", buf, why);
2991 }
2992 /*
2993 **  QID_PRINTNAME -- create externally printable version of queue id
2994 **
2995 **	Parameters:
2996 **		e -- the envelope.
2997 **
2998 **	Returns:
2999 **		a printable version
3000 */
3001 
3002 char *
3003 qid_printname(e)
3004 	ENVELOPE *e;
3005 {
3006 	char *id;
3007 	static char idbuf[MAXQFNAME + 34];
3008 
3009 	if (e == NULL)
3010 		return "";
3011 
3012 	if (e->e_id == NULL)
3013 		id = "";
3014 	else
3015 		id = e->e_id;
3016 
3017 	if (e->e_queuedir == NOQDIR)
3018 		return id;
3019 
3020 	(void) snprintf(idbuf, sizeof idbuf, "%.32s/%s",
3021 			QPaths[e->e_queuedir].qp_name, id);
3022 	return idbuf;
3023 }
3024 /*
3025 **  QID_PRINTQUEUE -- create full version of queue directory for df files
3026 **
3027 **	Parameters:
3028 **		queuedir -- the short version of the queue directory
3029 **
3030 **	Returns:
3031 **		the full pathname to the queue (static)
3032 */
3033 
3034 char *
3035 qid_printqueue(queuedir)
3036 	int queuedir;
3037 {
3038 	char *subdir;
3039 	static char dir[MAXPATHLEN];
3040 
3041 	if (queuedir == NOQDIR)
3042 		return QueueDir;
3043 
3044 	if (strcmp(QPaths[queuedir].qp_name, ".") == 0)
3045 		subdir = NULL;
3046 	else
3047 		subdir = QPaths[queuedir].qp_name;
3048 
3049 	(void) snprintf(dir, sizeof dir, "%s%s%s%s", QueueDir,
3050 			subdir == NULL ? "" : "/",
3051 			subdir == NULL ? "" : subdir,
3052 			(bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : ""));
3053 	return dir;
3054 }
3055 /*
3056 **  SETNEWQUEUE -- Sets a new queue directory
3057 **
3058 **	Assign a queue directory to an envelope and store the directory
3059 **	in e->e_queuedir.  The queue is chosen at random.
3060 **
3061 **	This routine may be improved in the future to allow for more
3062 **	elaborate queueing schemes.  Suggestions and code contributions
3063 **	are welcome.
3064 **
3065 **	Parameters:
3066 **		e -- envelope to assign a queue for.
3067 **
3068 **	Returns:
3069 **		none.
3070 */
3071 
3072 void
3073 setnewqueue(e)
3074 	ENVELOPE *e;
3075 {
3076 	int idx;
3077 
3078 	if (tTd(41, 20))
3079 		dprintf("setnewqueue: called\n");
3080 
3081 	if (e->e_queuedir != NOQDIR)
3082 	{
3083 		if (tTd(41, 20))
3084 			dprintf("setnewqueue: e_queuedir already assigned (%s)\n",
3085 				qid_printqueue(e->e_queuedir));
3086 		return;
3087 	}
3088 
3089 	if (NumQueues == 1)
3090 		idx = 0;
3091 	else
3092 	{
3093 #if RANDOMSHIFT
3094 		/* lower bits are not random "enough", select others */
3095 		idx = (get_random() >> RANDOMSHIFT) % NumQueues;
3096 #else /* RANDOMSHIFT */
3097 		idx = get_random() % NumQueues;
3098 #endif /* RANDOMSHIFT */
3099 		if (tTd(41, 15))
3100 			dprintf("setnewqueue: get_random() %% %d = %d\n",
3101 				NumQueues, idx);
3102 	}
3103 
3104 	e->e_queuedir = idx;
3105 	if (tTd(41, 3))
3106 		dprintf("setnewqueue: Assigned queue directory %s\n",
3107 			qid_printqueue(e->e_queuedir));
3108 }
3109 
3110 /*
3111 **  CHKQDIR -- check a queue directory
3112 **
3113 **	Parameters:
3114 **		name -- name of queue directory
3115 **		sff -- flags for safefile()
3116 **
3117 **	Returns:
3118 **		is it a queue directory?
3119 */
3120 
3121 static bool
3122 chkqdir(name, sff)
3123 	char *name;
3124 	long sff;
3125 {
3126 	struct stat statb;
3127 	int i;
3128 
3129 	/* skip over . and .. directories */
3130 	if (name[0] == '.' &&
3131 	    (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
3132 		return FALSE;
3133 # if HASLSTAT
3134 	if (lstat(name, &statb) < 0)
3135 # else /* HASLSTAT */
3136 	if (stat(name, &statb) < 0)
3137 # endif /* HASLSTAT */
3138 	{
3139 		if (tTd(41, 2))
3140 			dprintf("multiqueue_cache: stat(\"%s\"): %s\n",
3141 				name, errstring(errno));
3142 		return FALSE;
3143 	}
3144 # if HASLSTAT
3145 	if (S_ISLNK(statb.st_mode))
3146 	{
3147 		/*
3148 		**  For a symlink we need to make sure the
3149 		**  target is a directory
3150 		*/
3151 		if (stat(name, &statb) < 0)
3152 		{
3153 			if (tTd(41, 2))
3154 				dprintf("multiqueue_cache: stat(\"%s\"): %s\n",
3155 					name, errstring(errno));
3156 			return FALSE;
3157 		}
3158 	}
3159 # endif /* HASLSTAT */
3160 
3161 	if (!S_ISDIR(statb.st_mode))
3162 	{
3163 		if (tTd(41, 2))
3164 			dprintf("multiqueue_cache: \"%s\": Not a directory\n",
3165 				name);
3166 		return FALSE;
3167 	}
3168 
3169 	/* Print a warning if unsafe (but still use it) */
3170 	i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0);
3171 	if (i != 0 && tTd(41, 2))
3172 		dprintf("multiqueue_cache: \"%s\": Not safe: %s\n",
3173 			name, errstring(i));
3174 	return TRUE;
3175 }
3176 
3177 /*
3178 **  MULTIQUEUE_CACHE -- cache a list of paths to queues.
3179 **
3180 **	Each potential queue is checked as the cache is built.
3181 **	Thereafter, each is blindly trusted.
3182 **	Note that we can be called again after a timeout to rebuild
3183 **	(although code for that is not ready yet).
3184 **
3185 **	Parameters:
3186 **		none
3187 **
3188 **	Returns:
3189 **		none
3190 */
3191 
3192 void
3193 multiqueue_cache()
3194 {
3195 	register DIR *dp;
3196 	register struct dirent *d;
3197 	char *cp;
3198 	int i, len;
3199 	int slotsleft = 0;
3200 	long sff = SFF_ANYFILE;
3201 	char qpath[MAXPATHLEN];
3202 	char subdir[MAXPATHLEN];
3203 
3204 	if (tTd(41, 20))
3205 		dprintf("multiqueue_cache: called\n");
3206 
3207 	if (NumQueues != 0 && QPaths != NULL)
3208 	{
3209 		for (i = 0; i < NumQueues; i++)
3210 		{
3211 			if (QPaths[i].qp_name != NULL)
3212 				sm_free(QPaths[i].qp_name);
3213 		}
3214 		sm_free((char *)QPaths);
3215 		QPaths = NULL;
3216 		NumQueues = 0;
3217 	}
3218 
3219 	/* If running as root, allow safedirpath() checks to use privs */
3220 	if (RunAsUid == 0)
3221 		sff |= SFF_ROOTOK;
3222 
3223 	(void) snprintf(qpath, sizeof qpath, "%s", QueueDir);
3224 	len = strlen(qpath) - 1;
3225 	cp = &qpath[len];
3226 	if (*cp == '*')
3227 	{
3228 		*cp = '\0';
3229 		if ((cp = strrchr(qpath, '/')) == NULL)
3230 		{
3231 			syserr("QueueDirectory: can not wildcard relative path");
3232 			if (tTd(41, 2))
3233 				dprintf("multiqueue_cache: \"%s\": Can not wildcard relative path.\n",
3234 					qpath);
3235 			ExitStat = EX_CONFIG;
3236 			return;
3237 		}
3238 		if (cp == qpath)
3239 		{
3240 			/*
3241 			**  Special case of top level wildcard, like /foo*
3242 			*/
3243 
3244 			(void) snprintf(qpath + 1, sizeof qpath - 1,
3245 					"%s", qpath);
3246 			++cp;
3247 		}
3248 		*(cp++) = '\0';
3249 		len = strlen(cp);
3250 
3251 		if (tTd(41, 2))
3252 			dprintf("multiqueue_cache: prefix=\"%s\"\n", cp);
3253 
3254 		QueueDir = newstr(qpath);
3255 
3256 		/*
3257 		**  XXX Should probably wrap this whole loop in a timeout
3258 		**  in case some wag decides to NFS mount the queues.
3259 		*/
3260 
3261 		/* test path to get warning messages */
3262 		i= safedirpath(QueueDir, RunAsUid, RunAsGid, NULL, sff, 0, 0);
3263 		if (i != 0 && tTd(41, 2))
3264 			dprintf("multiqueue_cache: \"%s\": Not safe: %s\n",
3265 				QueueDir, errstring(i));
3266 
3267 		if (chdir(QueueDir) < 0)
3268 		{
3269 			syserr("can not chdir(%s)", QueueDir);
3270 			if (tTd(41, 2))
3271 				dprintf("multiqueue_cache: \"%s\": %s\n",
3272 					qpath, errstring(errno));
3273 			ExitStat = EX_CONFIG;
3274 			return;
3275 		}
3276 
3277 		if ((dp = opendir(".")) == NULL)
3278 		{
3279 			syserr("can not opendir(%s)", QueueDir);
3280 			if (tTd(41, 2))
3281 				dprintf("multiqueue_cache: opendir(\"%s\"): %s\n",
3282 					QueueDir, errstring(errno));
3283 			ExitStat = EX_CONFIG;
3284 			return;
3285 		}
3286 		while ((d = readdir(dp)) != NULL)
3287 		{
3288 			if (strncmp(d->d_name, cp, len) != 0)
3289 			{
3290 				if (tTd(41, 5))
3291 					dprintf("multiqueue_cache: \"%s\", skipped\n",
3292 						d->d_name);
3293 				continue;
3294 			}
3295 			if (!chkqdir(d->d_name, sff))
3296 				continue;
3297 
3298 			if (QPaths == NULL)
3299 			{
3300 				slotsleft = 20;
3301 				QPaths = (QPATHS *)xalloc((sizeof *QPaths) *
3302 							  slotsleft);
3303 				NumQueues = 0;
3304 			}
3305 			else if (slotsleft < 1)
3306 			{
3307 				QPaths = (QPATHS *)xrealloc((char *)QPaths,
3308 							    (sizeof *QPaths) *
3309 							    (NumQueues + 10));
3310 				if (QPaths == NULL)
3311 				{
3312 					(void) closedir(dp);
3313 					return;
3314 				}
3315 				slotsleft += 10;
3316 			}
3317 
3318 			/* check subdirs */
3319 			QPaths[NumQueues].qp_subdirs = QP_NOSUB;
3320 			(void) snprintf(subdir, sizeof subdir, "%s/%s/%s",
3321 					qpath, d->d_name, "qf");
3322 			if (chkqdir(subdir, sff))
3323 				QPaths[NumQueues].qp_subdirs |= QP_SUBQF;
3324 
3325 			(void) snprintf(subdir, sizeof subdir, "%s/%s/%s",
3326 					qpath, d->d_name, "df");
3327 			if (chkqdir(subdir, sff))
3328 				QPaths[NumQueues].qp_subdirs |= QP_SUBDF;
3329 
3330 			(void) snprintf(subdir, sizeof subdir, "%s/%s/%s",
3331 					qpath, d->d_name, "xf");
3332 			if (chkqdir(subdir, sff))
3333 				QPaths[NumQueues].qp_subdirs |= QP_SUBXF;
3334 
3335 			/* assert(strlen(d->d_name) < MAXPATHLEN - 14) */
3336 			/* maybe even - 17 (subdirs) */
3337 			QPaths[NumQueues].qp_name = newstr(d->d_name);
3338 			if (tTd(41, 2))
3339 				dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n",
3340 					NumQueues, d->d_name,
3341 					QPaths[NumQueues].qp_subdirs);
3342 			NumQueues++;
3343 			slotsleft--;
3344 		}
3345 		(void) closedir(dp);
3346 	}
3347 	if (NumQueues == 0)
3348 	{
3349 		if (*cp != '*' && tTd(41, 2))
3350 			dprintf("multiqueue_cache: \"%s\": No wildcard suffix character\n",
3351 				QueueDir);
3352 		QPaths = (QPATHS *)xalloc(sizeof *QPaths);
3353 		QPaths[0].qp_name = newstr(".");
3354 		QPaths[0].qp_subdirs = QP_NOSUB;
3355 		NumQueues = 1;
3356 
3357 		/* test path to get warning messages */
3358 		(void) safedirpath(QueueDir, RunAsUid, RunAsGid,
3359 				   NULL, sff, 0, 0);
3360 		if (chdir(QueueDir) < 0)
3361 		{
3362 			syserr("can not chdir(%s)", QueueDir);
3363 			if (tTd(41, 2))
3364 				dprintf("multiqueue_cache: \"%s\": %s\n",
3365 					QueueDir, errstring(errno));
3366 			ExitStat = EX_CONFIG;
3367 		}
3368 
3369 		/* check subdirs */
3370 		(void) snprintf(subdir, sizeof subdir, "%s/qf", QueueDir);
3371 		if (chkqdir(subdir, sff))
3372 			QPaths[0].qp_subdirs |= QP_SUBQF;
3373 
3374 		(void) snprintf(subdir, sizeof subdir, "%s/df",	QueueDir);
3375 		if (chkqdir(subdir, sff))
3376 			QPaths[0].qp_subdirs |= QP_SUBDF;
3377 
3378 		(void) snprintf(subdir, sizeof subdir, "%s/xf", QueueDir);
3379 		if (chkqdir(subdir, sff))
3380 			QPaths[0].qp_subdirs |= QP_SUBXF;
3381 	}
3382 }
3383 
3384 # if 0
3385 /*
3386 **  HASHFQN -- calculate a hash value for a fully qualified host name
3387 **
3388 **	Arguments:
3389 **		fqn -- an all lower-case host.domain string
3390 **		buckets -- the number of buckets (queue directories)
3391 **
3392 **	Returns:
3393 **		a bucket number (signed integer)
3394 **		-1 on error
3395 **
3396 **	Contributed by Exactis.com, Inc.
3397 */
3398 
3399 int
3400 hashfqn(fqn, buckets)
3401 	register char *fqn;
3402 	int buckets;
3403 {
3404 	register char *p;
3405 	register int h = 0, hash, cnt;
3406 #  define WATERINC (1000)
3407 
3408 	if (fqn == NULL)
3409 		return -1;
3410 
3411 	/*
3412 	**  A variation on the gdb hash
3413 	**  This is the best as of Feb 19, 1996 --bcx
3414 	*/
3415 
3416 	p = fqn;
3417 	h = 0x238F13AF * strlen(p);
3418 	for (cnt = 0; *p != 0; ++p, cnt++)
3419 	{
3420 		h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF;
3421 	}
3422 	h = (1103515243 * h + 12345) & 0x7FFFFFFF;
3423 	if (buckets < 2)
3424 		hash = 0;
3425 	else
3426 		hash = (h % buckets);
3427 
3428 	return hash;
3429 }
3430 # endif /* 0 */
3431 
3432 # if _FFR_QUEUEDELAY
3433 /*
3434 **  QUEUEDELAY -- compute queue delay time
3435 **
3436 **	Parameters:
3437 **		e -- the envelope to queue up.
3438 **
3439 **	Returns:
3440 **		queue delay time
3441 **
3442 **	Side Effects:
3443 **		may change e_queuedelay
3444 */
3445 
3446 static time_t
3447 queuedelay(e)
3448 	ENVELOPE *e;
3449 {
3450 	time_t qd;
3451 
3452 	if (e->e_queuealg == QD_EXP)
3453 	{
3454 		if (e->e_queuedelay == 0)
3455 			e->e_queuedelay = QueueInitDelay;
3456 		else
3457 		{
3458 			e->e_queuedelay *= 2;
3459 			if (e->e_queuedelay > QueueMaxDelay)
3460 				e->e_queuedelay = QueueMaxDelay;
3461 		}
3462 		qd = e->e_queuedelay;
3463 	}
3464 	else
3465 		qd = MinQueueAge;
3466 	return qd;
3467 }
3468 # endif /* _FFR_QUEUEDELAY */
3469 #endif /* QUEUE */
3470