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