xref: /freebsd/contrib/sendmail/src/queue.c (revision 6e8394b8baa7d5d9153ab90de6824bcd19b3b4e1)
1 /*
2  * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4  * Copyright (c) 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * By using this file, you agree to the terms and conditions set
8  * forth in the LICENSE file which can be found at the top level of
9  * the sendmail distribution.
10  *
11  */
12 
13 # include "sendmail.h"
14 
15 #ifndef lint
16 #if QUEUE
17 static char sccsid[] = "@(#)queue.c	8.211 (Berkeley) 1/25/1999 (with queueing)";
18 #else
19 static char sccsid[] = "@(#)queue.c	8.211 (Berkeley) 1/25/1999 (without queueing)";
20 #endif
21 #endif /* not lint */
22 
23 # include <errno.h>
24 # include <dirent.h>
25 
26 # if QUEUE
27 
28 /*
29 **  Work queue.
30 */
31 
32 struct work
33 {
34 	char		*w_name;	/* name of control file */
35 	char		*w_host;	/* name of recipient host */
36 	bool		w_lock;		/* is message locked? */
37 	bool		w_tooyoung;	/* is it too young to run? */
38 	long		w_pri;		/* priority of message, see below */
39 	time_t		w_ctime;	/* creation time of message */
40 	struct work	*w_next;	/* next in queue */
41 };
42 
43 typedef struct work	WORK;
44 
45 WORK	*WorkQ;			/* queue of things to be done */
46 
47 #define QF_VERSION	2	/* version number of this queue format */
48 
49 extern int orderq __P((bool));
50 /*
51 **  QUEUEUP -- queue a message up for future transmission.
52 **
53 **	Parameters:
54 **		e -- the envelope to queue up.
55 **		announce -- if TRUE, tell when you are queueing up.
56 **
57 **	Returns:
58 **		none.
59 **
60 **	Side Effects:
61 **		The current request are saved in a control file.
62 **		The queue file is left locked.
63 */
64 
65 void
66 queueup(e, announce)
67 	register ENVELOPE *e;
68 	bool announce;
69 {
70 	char *qf;
71 	register FILE *tfp;
72 	register HDR *h;
73 	register ADDRESS *q;
74 	int fd;
75 	int i;
76 	bool newid;
77 	register char *p;
78 	MAILER nullmailer;
79 	MCI mcibuf;
80 	char tf[MAXQFNAME];
81 	char buf[MAXLINE];
82 	extern void printctladdr __P((ADDRESS *, FILE *));
83 
84 	/*
85 	**  Create control file.
86 	*/
87 
88 	newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
89 
90 	/* if newid, queuename will create a locked qf file in e->lockfp */
91 	strcpy(tf, queuename(e, 't'));
92 	tfp = e->e_lockfp;
93 	if (tfp == NULL)
94 		newid = FALSE;
95 
96 	/* if newid, just write the qf file directly (instead of tf file) */
97 	if (!newid)
98 	{
99 		/* get a locked tf file */
100 		for (i = 0; i < 128; i++)
101 		{
102 			fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
103 			if (fd < 0)
104 			{
105 				if (errno != EEXIST)
106 					break;
107 				if (LogLevel > 0 && (i % 32) == 0)
108 					sm_syslog(LOG_ALERT, e->e_id,
109 						"queueup: cannot create %s, uid=%d: %s",
110 						tf, geteuid(), errstring(errno));
111 			}
112 			else
113 			{
114 				if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))
115 					break;
116 				else if (LogLevel > 0 && (i % 32) == 0)
117 					sm_syslog(LOG_ALERT, e->e_id,
118 						"queueup: cannot lock %s: %s",
119 						tf, errstring(errno));
120 				close(fd);
121 			}
122 
123 			if ((i % 32) == 31)
124 			{
125 				/* save the old temp file away */
126 				(void) rename(tf, queuename(e, 'T'));
127 			}
128 			else
129 				sleep(i % 32);
130 		}
131 		if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL)
132 		{
133 			printopenfds(TRUE);
134 			syserr("!queueup: cannot create queue temp file %s, uid=%d",
135 				tf, geteuid());
136 		}
137 	}
138 
139 	if (tTd(40, 1))
140 		printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id,
141 			newid ? " (new id)" : "");
142 	if (tTd(40, 3))
143 	{
144 		extern void printenvflags __P((ENVELOPE *));
145 
146 		printf("  e_flags=");
147 		printenvflags(e);
148 	}
149 	if (tTd(40, 32))
150 	{
151 		printf("  sendq=");
152 		printaddr(e->e_sendqueue, TRUE);
153 	}
154 	if (tTd(40, 9))
155 	{
156 		printf("  tfp=");
157 		dumpfd(fileno(tfp), TRUE, FALSE);
158 		printf("  lockfp=");
159 		if (e->e_lockfp == NULL)
160 			printf("NULL\n");
161 		else
162 			dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
163 	}
164 
165 	/*
166 	**  If there is no data file yet, create one.
167 	*/
168 
169 	if (!bitset(EF_HAS_DF, e->e_flags))
170 	{
171 		register FILE *dfp = NULL;
172 		char dfname[MAXQFNAME];
173 		struct stat stbuf;
174 
175 		strcpy(dfname, queuename(e, 'd'));
176 		fd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode);
177 		if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL)
178 			syserr("!queueup: cannot create data temp file %s, uid=%d",
179 				dfname, geteuid());
180 		if (fstat(fd, &stbuf) < 0)
181 			e->e_dfino = -1;
182 		else
183 		{
184 			e->e_dfdev = stbuf.st_dev;
185 			e->e_dfino = stbuf.st_ino;
186 		}
187 		e->e_flags |= EF_HAS_DF;
188 		bzero(&mcibuf, sizeof mcibuf);
189 		mcibuf.mci_out = dfp;
190 		mcibuf.mci_mailer = FileMailer;
191 		(*e->e_putbody)(&mcibuf, e, NULL);
192 		(void) xfclose(dfp, "queueup dfp", e->e_id);
193 		e->e_putbody = putbody;
194 	}
195 
196 	/*
197 	**  Output future work requests.
198 	**	Priority and creation time should be first, since
199 	**	they are required by orderq.
200 	*/
201 
202 	/* output queue version number (must be first!) */
203 	fprintf(tfp, "V%d\n", QF_VERSION);
204 
205 	/* output creation time */
206 	fprintf(tfp, "T%ld\n", (long) e->e_ctime);
207 
208 	/* output last delivery time */
209 	fprintf(tfp, "K%ld\n", (long) e->e_dtime);
210 
211 	/* output number of delivery attempts */
212 	fprintf(tfp, "N%d\n", e->e_ntries);
213 
214 	/* output message priority */
215 	fprintf(tfp, "P%ld\n", e->e_msgpriority);
216 
217 	/* output inode number of data file */
218 	/* XXX should probably include device major/minor too */
219 	if (e->e_dfino != -1)
220 	{
221 		if (sizeof e->e_dfino > sizeof(long))
222 			fprintf(tfp, "I%d/%d/%s\n",
223 				major(e->e_dfdev), minor(e->e_dfdev),
224 				quad_to_string(e->e_dfino));
225 		else
226 			fprintf(tfp, "I%d/%d/%lu\n",
227 				major(e->e_dfdev), minor(e->e_dfdev),
228 				(unsigned long) e->e_dfino);
229 	}
230 
231 	/* output body type */
232 	if (e->e_bodytype != NULL)
233 		fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE));
234 
235 #if _FFR_SAVE_CHARSET
236 	if (e->e_charset != NULL)
237 		fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE));
238 #endif
239 
240 	/* message from envelope, if it exists */
241 	if (e->e_message != NULL)
242 		fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE));
243 
244 	/* send various flag bits through */
245 	p = buf;
246 	if (bitset(EF_WARNING, e->e_flags))
247 		*p++ = 'w';
248 	if (bitset(EF_RESPONSE, e->e_flags))
249 		*p++ = 'r';
250 	if (bitset(EF_HAS8BIT, e->e_flags))
251 		*p++ = '8';
252 	if (bitset(EF_DELETE_BCC, e->e_flags))
253 		*p++ = 'b';
254 	if (bitset(EF_RET_PARAM, e->e_flags))
255 		*p++ = 'd';
256 	if (bitset(EF_NO_BODY_RETN, e->e_flags))
257 		*p++ = 'n';
258 	*p++ = '\0';
259 	if (buf[0] != '\0')
260 		fprintf(tfp, "F%s\n", buf);
261 
262 	/* $r and $s and $_ macro values */
263 	if ((p = macvalue('r', e)) != NULL)
264 		fprintf(tfp, "$r%s\n", denlstring(p, TRUE, FALSE));
265 	if ((p = macvalue('s', e)) != NULL)
266 		fprintf(tfp, "$s%s\n", denlstring(p, TRUE, FALSE));
267 	if ((p = macvalue('_', e)) != NULL)
268 		fprintf(tfp, "$_%s\n", denlstring(p, TRUE, FALSE));
269 
270 	/* output name of sender */
271 	if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
272 		p = e->e_sender;
273 	else
274 		p = e->e_from.q_paddr;
275 	fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE));
276 
277 	/* output ESMTP-supplied "original" information */
278 	if (e->e_envid != NULL)
279 		fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE));
280 
281 	/* output list of recipient addresses */
282 	printctladdr(NULL, NULL);
283 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
284 	{
285 		if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
286 		{
287 #if XDEBUG
288 			if (bitset(QQUEUEUP, q->q_flags))
289 				sm_syslog(LOG_DEBUG, e->e_id,
290 					"dropenvelope: q_flags = %x, paddr = %s",
291 					q->q_flags, q->q_paddr);
292 #endif
293 			continue;
294 		}
295 		printctladdr(q, tfp);
296 		if (q->q_orcpt != NULL)
297 			fprintf(tfp, "Q%s\n",
298 				denlstring(q->q_orcpt, TRUE, FALSE));
299 		putc('R', tfp);
300 		if (bitset(QPRIMARY, q->q_flags))
301 			putc('P', tfp);
302 		if (bitset(QHASNOTIFY, q->q_flags))
303 			putc('N', tfp);
304 		if (bitset(QPINGONSUCCESS, q->q_flags))
305 			putc('S', tfp);
306 		if (bitset(QPINGONFAILURE, q->q_flags))
307 			putc('F', tfp);
308 		if (bitset(QPINGONDELAY, q->q_flags))
309 			putc('D', tfp);
310 		putc(':', tfp);
311 		fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
312 		if (announce)
313 		{
314 			e->e_to = q->q_paddr;
315 			message("queued");
316 			if (LogLevel > 8)
317 				logdelivery(q->q_mailer, NULL, "queued",
318 					    NULL, (time_t) 0, e);
319 			e->e_to = NULL;
320 		}
321 		if (tTd(40, 1))
322 		{
323 			printf("queueing ");
324 			printaddr(q, FALSE);
325 		}
326 	}
327 
328 	/*
329 	**  Output headers for this message.
330 	**	Expand macros completely here.  Queue run will deal with
331 	**	everything as absolute headers.
332 	**		All headers that must be relative to the recipient
333 	**		can be cracked later.
334 	**	We set up a "null mailer" -- i.e., a mailer that will have
335 	**	no effect on the addresses as they are output.
336 	*/
337 
338 	bzero((char *) &nullmailer, sizeof nullmailer);
339 	nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
340 			nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
341 	nullmailer.m_eol = "\n";
342 	bzero(&mcibuf, sizeof mcibuf);
343 	mcibuf.mci_mailer = &nullmailer;
344 	mcibuf.mci_out = tfp;
345 
346 	define('g', "\201f", e);
347 	for (h = e->e_header; h != NULL; h = h->h_link)
348 	{
349 		extern bool bitzerop __P((BITMAP));
350 
351 		if (h->h_value == NULL)
352 			continue;
353 
354 		/* don't output resent headers on non-resent messages */
355 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
356 			continue;
357 
358 		/* expand macros; if null, don't output header at all */
359 		if (bitset(H_DEFAULT, h->h_flags))
360 		{
361 			(void) expand(h->h_value, buf, sizeof buf, e);
362 			if (buf[0] == '\0')
363 				continue;
364 		}
365 
366 		/* output this header */
367 		fprintf(tfp, "H");
368 
369 		/* if conditional, output the set of conditions */
370 		if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags))
371 		{
372 			int j;
373 
374 			(void) putc('?', tfp);
375 			for (j = '\0'; j <= '\177'; j++)
376 				if (bitnset(j, h->h_mflags))
377 					(void) putc(j, tfp);
378 			(void) putc('?', tfp);
379 		}
380 
381 		/* output the header: expand macros, convert addresses */
382 		if (bitset(H_DEFAULT, h->h_flags))
383 		{
384 			fprintf(tfp, "%s: %s\n",
385 				h->h_field,
386 				denlstring(buf, FALSE, TRUE));
387 		}
388 		else if (bitset(H_FROM|H_RCPT, h->h_flags))
389 		{
390 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
391 			FILE *savetrace = TrafficLogFile;
392 
393 			TrafficLogFile = NULL;
394 
395 			if (bitset(H_FROM, h->h_flags))
396 				oldstyle = FALSE;
397 
398 			commaize(h, h->h_value, oldstyle, &mcibuf, e);
399 
400 			TrafficLogFile = savetrace;
401 		}
402 		else
403 		{
404 			fprintf(tfp, "%s: %s\n",
405 				h->h_field,
406 				denlstring(h->h_value, FALSE, TRUE));
407 		}
408 	}
409 
410 	/*
411 	**  Clean up.
412 	**
413 	**	Write a terminator record -- this is to prevent
414 	**	scurrilous crackers from appending any data.
415 	*/
416 
417 	fprintf(tfp, ".\n");
418 
419 	if (fflush(tfp) < 0 ||
420 	    (SuperSafe && fsync(fileno(tfp)) < 0) ||
421 	    ferror(tfp))
422 	{
423 		if (newid)
424 			syserr("!552 Error writing control file %s", tf);
425 		else
426 			syserr("!452 Error writing control file %s", tf);
427 	}
428 
429 	if (!newid)
430 	{
431 		/* rename (locked) tf to be (locked) qf */
432 		qf = queuename(e, 'q');
433 		if (rename(tf, qf) < 0)
434 			syserr("cannot rename(%s, %s), uid=%d",
435 				tf, qf, geteuid());
436 
437 		/* close and unlock old (locked) qf */
438 		if (e->e_lockfp != NULL)
439 			(void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id);
440 		e->e_lockfp = tfp;
441 	}
442 	else
443 		qf = tf;
444 	errno = 0;
445 	e->e_flags |= EF_INQUEUE;
446 
447 	/* save log info */
448 	if (LogLevel > 79)
449 		sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf);
450 
451 	if (tTd(40, 1))
452 		printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
453 	return;
454 }
455 
456 void
457 printctladdr(a, tfp)
458 	register ADDRESS *a;
459 	FILE *tfp;
460 {
461 	char *uname;
462 	register ADDRESS *q;
463 	uid_t uid;
464 	gid_t gid;
465 	static ADDRESS *lastctladdr = NULL;
466 	static uid_t lastuid;
467 
468 	/* initialization */
469 	if (a == NULL || a->q_alias == NULL || tfp == NULL)
470 	{
471 		if (lastctladdr != NULL && tfp != NULL)
472 			fprintf(tfp, "C\n");
473 		lastctladdr = NULL;
474 		lastuid = 0;
475 		return;
476 	}
477 
478 	/* find the active uid */
479 	q = getctladdr(a);
480 	if (q == NULL)
481 	{
482 		uname = NULL;
483 		uid = 0;
484 		gid = 0;
485 	}
486 	else
487 	{
488 		uname = q->q_ruser != NULL ? q->q_ruser : q->q_user;
489 		uid = q->q_uid;
490 		gid = q->q_gid;
491 	}
492 	a = a->q_alias;
493 
494 	/* check to see if this is the same as last time */
495 	if (lastctladdr != NULL && uid == lastuid &&
496 	    strcmp(lastctladdr->q_paddr, a->q_paddr) == 0)
497 		return;
498 	lastuid = uid;
499 	lastctladdr = a;
500 
501 	if (uid == 0 || uname == NULL || uname[0] == '\0')
502 		fprintf(tfp, "C");
503 	else
504 		fprintf(tfp, "C%s:%ld:%ld",
505 			denlstring(uname, TRUE, FALSE), (long) uid, (long) gid);
506 	fprintf(tfp, ":%s\n", denlstring(a->q_paddr, TRUE, FALSE));
507 }
508 /*
509 **  RUNQUEUE -- run the jobs in the queue.
510 **
511 **	Gets the stuff out of the queue in some presumably logical
512 **	order and processes them.
513 **
514 **	Parameters:
515 **		forkflag -- TRUE if the queue scanning should be done in
516 **			a child process.  We double-fork so it is not our
517 **			child and we don't have to clean up after it.
518 **		verbose -- if TRUE, print out status information.
519 **
520 **	Returns:
521 **		TRUE if the queue run successfully began.
522 **
523 **	Side Effects:
524 **		runs things in the mail queue.
525 */
526 
527 ENVELOPE	QueueEnvelope;		/* the queue run envelope */
528 extern int	get_num_procs_online __P((void));
529 
530 bool
531 runqueue(forkflag, verbose)
532 	bool forkflag;
533 	bool verbose;
534 {
535 	register ENVELOPE *e;
536 	int njobs;
537 	int sequenceno = 0;
538 	time_t current_la_time;
539 	extern ENVELOPE BlankEnvelope;
540 	extern void clrdaemon __P((void));
541 	extern void runqueueevent __P((void));
542 
543 	DoQueueRun = FALSE;
544 
545 	/*
546 	**  If no work will ever be selected, don't even bother reading
547 	**  the queue.
548 	*/
549 
550 	CurrentLA = getla();	/* get load average */
551 	current_la_time = curtime();
552 
553 	if (shouldqueue(WkRecipFact, current_la_time))
554 	{
555 		char *msg = "Skipping queue run -- load average too high";
556 
557 		if (verbose)
558 			message("458 %s\n", msg);
559 		if (LogLevel > 8)
560 			sm_syslog(LOG_INFO, NOQID,
561 				"runqueue: %s",
562 				msg);
563 		if (forkflag && QueueIntvl != 0)
564 			(void) setevent(QueueIntvl, runqueueevent, 0);
565 		return FALSE;
566 	}
567 
568 	/*
569 	**  See if we already have too many children.
570 	*/
571 
572 	if (forkflag && QueueIntvl != 0 &&
573 	    MaxChildren > 0 && CurChildren >= MaxChildren)
574 	{
575 		(void) setevent(QueueIntvl, runqueueevent, 0);
576 		return FALSE;
577 	}
578 
579 	/*
580 	**  See if we want to go off and do other useful work.
581 	*/
582 
583 	if (forkflag)
584 	{
585 		pid_t pid;
586 		extern SIGFUNC_DECL intsig __P((int));
587 		extern SIGFUNC_DECL reapchild __P((int));
588 
589 		blocksignal(SIGCHLD);
590 		(void) setsignal(SIGCHLD, reapchild);
591 
592 		pid = dofork();
593 		if (pid == -1)
594 		{
595 			const char *msg = "Skipping queue run -- fork() failed";
596 			const char *err = errstring(errno);
597 
598 			if (verbose)
599 				message("458 %s: %s\n", msg, err);
600 			if (LogLevel > 8)
601 				sm_syslog(LOG_INFO, NOQID,
602 					"runqueue: %s: %s",
603 					msg, err);
604 			if (QueueIntvl != 0)
605 				(void) setevent(QueueIntvl, runqueueevent, 0);
606 			(void) releasesignal(SIGCHLD);
607 			return FALSE;
608 		}
609 		if (pid != 0)
610 		{
611 			/* parent -- pick up intermediate zombie */
612 			(void) blocksignal(SIGALRM);
613 			proc_list_add(pid, "Queue runner");
614 			(void) releasesignal(SIGALRM);
615 			releasesignal(SIGCHLD);
616 			if (QueueIntvl != 0)
617 				(void) setevent(QueueIntvl, runqueueevent, 0);
618 			return TRUE;
619 		}
620 		/* child -- double fork and clean up signals */
621 		clrcontrol();
622 		proc_list_clear();
623 
624 		/* Add parent process as first child item */
625 		proc_list_add(getpid(), "Queue runner child process");
626 		releasesignal(SIGCHLD);
627 		(void) setsignal(SIGCHLD, SIG_DFL);
628 		(void) setsignal(SIGHUP, intsig);
629 	}
630 
631 	sm_setproctitle(TRUE, "running queue: %s", QueueDir);
632 
633 	if (LogLevel > 69)
634 		sm_syslog(LOG_DEBUG, NOQID,
635 			"runqueue %s, pid=%d, forkflag=%d",
636 			QueueDir, getpid(), forkflag);
637 
638 	/*
639 	**  Release any resources used by the daemon code.
640 	*/
641 
642 # if DAEMON
643 	clrdaemon();
644 # endif /* DAEMON */
645 
646 	/* force it to run expensive jobs */
647 	NoConnect = FALSE;
648 
649 	/* drop privileges */
650 	if (geteuid() == (uid_t) 0)
651 		(void) drop_privileges(FALSE);
652 
653 	/*
654 	**  Create ourselves an envelope
655 	*/
656 
657 	CurEnv = &QueueEnvelope;
658 	e = newenvelope(&QueueEnvelope, CurEnv);
659 	e->e_flags = BlankEnvelope.e_flags;
660 
661 	/* make sure we have disconnected from parent */
662 	if (forkflag)
663 	{
664 		disconnect(1, e);
665 		QuickAbort = FALSE;
666 	}
667 
668 	/*
669 	**  Make sure the alias database is open.
670 	*/
671 
672 	initmaps(FALSE, e);
673 
674 	/*
675 	**  If we are running part of the queue, always ignore stored
676 	**  host status.
677 	*/
678 
679 	if (QueueLimitId != NULL || QueueLimitSender != NULL ||
680 	    QueueLimitRecipient != NULL)
681 	{
682 		IgnoreHostStatus = TRUE;
683 		MinQueueAge = 0;
684 	}
685 
686 	/*
687 	**  Start making passes through the queue.
688 	**	First, read and sort the entire queue.
689 	**	Then, process the work in that order.
690 	**		But if you take too long, start over.
691 	*/
692 
693 	/* order the existing work requests */
694 	njobs = orderq(FALSE);
695 
696 	/* process them once at a time */
697 	while (WorkQ != NULL)
698 	{
699 		WORK *w = WorkQ;
700 
701 		WorkQ = WorkQ->w_next;
702 		e->e_to = NULL;
703 
704 		/*
705 		**  Ignore jobs that are too expensive for the moment.
706 		**
707 		**	Get new load average every 30 seconds.
708 		*/
709 
710 		if (current_la_time < curtime() - 30)
711 		{
712 			CurrentLA = getla();
713 			current_la_time = curtime();
714 		}
715 		if (shouldqueue(WkRecipFact, current_la_time))
716 		{
717 			char *msg = "Aborting queue run: load average too high";
718 
719 			if (Verbose)
720 				message("%s", msg);
721 			if (LogLevel > 8)
722 				sm_syslog(LOG_INFO, NOQID,
723 					"runqueue: %s",
724 					msg);
725 			break;
726 		}
727 		sequenceno++;
728 		if (shouldqueue(w->w_pri, w->w_ctime))
729 		{
730 			if (Verbose)
731 				message("");
732 			if (QueueSortOrder == QS_BYPRIORITY)
733 			{
734 				if (Verbose)
735 					message("Skipping %s (sequence %d of %d) and flushing rest of queue",
736 						w->w_name + 2,
737 						sequenceno,
738 						njobs);
739 				if (LogLevel > 8)
740 					sm_syslog(LOG_INFO, NOQID,
741 						"runqueue: Flushing queue from %s (pri %ld, LA %d, %d of %d)",
742 						w->w_name + 2,
743 						w->w_pri,
744 						CurrentLA,
745 						sequenceno,
746 						njobs);
747 				break;
748 			}
749 			else if (Verbose)
750 				message("Skipping %s (sequence %d of %d)",
751 					w->w_name + 2, sequenceno, njobs);
752 		}
753 		else
754 		{
755 			pid_t pid;
756 
757 			if (Verbose)
758 			{
759 				message("");
760 				message("Running %s (sequence %d of %d)",
761 					w->w_name + 2, sequenceno, njobs);
762 			}
763 			pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
764 			errno = 0;
765 			if (pid != 0)
766 				(void) waitfor(pid);
767 		}
768 		free(w->w_name);
769 		if (w->w_host)
770 			free(w->w_host);
771 		free((char *) w);
772 	}
773 
774 	/* exit without the usual cleanup */
775 	e->e_id = NULL;
776 	finis(TRUE, ExitStat);
777 	/*NOTREACHED*/
778 	return TRUE;
779 }
780 
781 
782 /*
783 **  RUNQUEUEEVENT -- stub for use in setevent
784 */
785 
786 void
787 runqueueevent()
788 {
789 	DoQueueRun = TRUE;
790 }
791 /*
792 **  ORDERQ -- order the work queue.
793 **
794 **	Parameters:
795 **		doall -- if set, include everything in the queue (even
796 **			the jobs that cannot be run because the load
797 **			average is too high).  Otherwise, exclude those
798 **			jobs.
799 **
800 **	Returns:
801 **		The number of request in the queue (not necessarily
802 **		the number of requests in WorkQ however).
803 **
804 **	Side Effects:
805 **		Sets WorkQ to the queue of available work, in order.
806 */
807 
808 # define NEED_P		001
809 # define NEED_T		002
810 # define NEED_R		004
811 # define NEED_S		010
812 
813 static WORK	*WorkList = NULL;
814 static int	WorkListSize = 0;
815 
816 int
817 orderq(doall)
818 	bool doall;
819 {
820 	register struct dirent *d;
821 	register WORK *w;
822 	register char *p;
823 	DIR *f;
824 	register int i;
825 	int wn = -1;
826 	int wc;
827 	QUEUE_CHAR *check;
828 
829 	if (tTd(41, 1))
830 	{
831 		printf("orderq:\n");
832 
833 		check = QueueLimitId;
834 		while (check != NULL)
835 		{
836 			printf("\tQueueLimitId = %s\n",
837 			       check->queue_match);
838 			check = check->queue_next;
839 		}
840 
841 		check = QueueLimitSender;
842 		while (check != NULL)
843 		{
844 			printf("\tQueueLimitSender = %s\n",
845 			       check->queue_match);
846 			check = check->queue_next;
847 		}
848 
849 		check = QueueLimitRecipient;
850 		while (check != NULL)
851 		{
852 			printf("\tQueueLimitRecipient = %s\n",
853 			       check->queue_match);
854 			check = check->queue_next;
855 		}
856 	}
857 
858 	/* clear out old WorkQ */
859 	for (w = WorkQ; w != NULL; )
860 	{
861 		register WORK *nw = w->w_next;
862 
863 		WorkQ = nw;
864 		free(w->w_name);
865 		if (w->w_host)
866 			free(w->w_host);
867 		free((char *) w);
868 		w = nw;
869 	}
870 
871 	/* open the queue directory */
872 	f = opendir(".");
873 	if (f == NULL)
874 	{
875 		syserr("orderq: cannot open \"%s\" as \".\"", QueueDir);
876 		return (0);
877 	}
878 
879 	/*
880 	**  Read the work directory.
881 	*/
882 
883 	while ((d = readdir(f)) != NULL)
884 	{
885 		FILE *cf;
886 		int qfver = 0;
887 		char lbuf[MAXNAME + 1];
888 		extern bool strcontainedin __P((char *, char *));
889 
890 		if (tTd(41, 50))
891 			printf("orderq: checking %s\n", d->d_name);
892 
893 		/* is this an interesting entry? */
894 		if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
895 			continue;
896 
897 		if (strlen(d->d_name) > MAXQFNAME)
898 		{
899 			if (Verbose)
900 				printf("orderq: %s too long, %d max characters\n",
901 					d->d_name, MAXQFNAME);
902 			if (LogLevel > 0)
903 				sm_syslog(LOG_ALERT, NOQID,
904 					"orderq: %s too long, %d max characters",
905 					d->d_name, MAXQFNAME);
906 			continue;
907 		}
908 
909 		check = QueueLimitId;
910 		while (check != NULL)
911 		{
912 			if (strcontainedin(check->queue_match, d->d_name))
913 				break;
914 			else
915 				check = check->queue_next;
916 		}
917 		if (QueueLimitId != NULL && check == NULL)
918 			continue;
919 
920 #ifdef PICKY_QF_NAME_CHECK
921 		/*
922 		**  Check queue name for plausibility.  This handles
923 		**  both old and new type ids.
924 		*/
925 
926 		p = d->d_name + 2;
927 		if (isupper(p[0]) && isupper(p[2]))
928 			p += 3;
929 		else if (isupper(p[1]))
930 			p += 2;
931 		else
932 			p = d->d_name;
933 		for (i = 0; isdigit(*p); p++)
934 			i++;
935 		if (i < 5 || *p != '\0')
936 		{
937 			if (Verbose)
938 				printf("orderq: bogus qf name %s\n", d->d_name);
939 			if (LogLevel > 0)
940 				sm_syslog(LOG_ALERT, NOQID,
941 					"orderq: bogus qf name %s",
942 					d->d_name);
943 			if (strlen(d->d_name) > (SIZE_T) MAXNAME)
944 				d->d_name[MAXNAME] = '\0';
945 			strcpy(lbuf, d->d_name);
946 			lbuf[0] = 'Q';
947 			(void) rename(d->d_name, lbuf);
948 			continue;
949 		}
950 #endif
951 
952 		/* open control file (if not too many files) */
953 		if (++wn >= MaxQueueRun && MaxQueueRun > 0)
954 		{
955 			if (wn == MaxQueueRun && LogLevel > 0)
956 				sm_syslog(LOG_ALERT, NOQID,
957 					"WorkList for %s maxed out at %d",
958 					QueueDir, MaxQueueRun);
959 			continue;
960 		}
961 		if (wn >= WorkListSize)
962 		{
963 			extern void grow_wlist __P((void));
964 
965 			grow_wlist();
966 			if (wn >= WorkListSize)
967 				continue;
968 		}
969 
970 		cf = fopen(d->d_name, "r");
971 		if (cf == NULL)
972 		{
973 			/* this may be some random person sending hir msgs */
974 			/* syserr("orderq: cannot open %s", cbuf); */
975 			if (tTd(41, 2))
976 				printf("orderq: cannot open %s: %s\n",
977 					d->d_name, errstring(errno));
978 			errno = 0;
979 			wn--;
980 			continue;
981 		}
982 		w = &WorkList[wn];
983 		w->w_name = newstr(d->d_name);
984 		w->w_host = NULL;
985 		w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB);
986 		w->w_tooyoung = FALSE;
987 
988 		/* make sure jobs in creation don't clog queue */
989 		w->w_pri = 0x7fffffff;
990 		w->w_ctime = 0;
991 
992 		/* extract useful information */
993 		i = NEED_P | NEED_T;
994 		if (QueueLimitSender != NULL)
995 			i |= NEED_S;
996 		if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL)
997 			i |= NEED_R;
998 		while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
999 		{
1000 			int c;
1001 			time_t age;
1002 			extern bool strcontainedin __P((char *, char *));
1003 
1004 			p = strchr(lbuf, '\n');
1005 			if (p != NULL)
1006 				*p = '\0';
1007 			else
1008 			{
1009 				/* flush rest of overly long line */
1010 				while ((c = getc(cf)) != EOF && c != '\n')
1011 					continue;
1012 			}
1013 
1014 			switch (lbuf[0])
1015 			{
1016 			  case 'V':
1017 				qfver = atoi(&lbuf[1]);
1018 				break;
1019 
1020 			  case 'P':
1021 				w->w_pri = atol(&lbuf[1]);
1022 				i &= ~NEED_P;
1023 				break;
1024 
1025 			  case 'T':
1026 				w->w_ctime = atol(&lbuf[1]);
1027 				i &= ~NEED_T;
1028 				break;
1029 
1030 			  case 'R':
1031 				if (w->w_host == NULL &&
1032 				    (p = strrchr(&lbuf[1], '@')) != NULL)
1033 					w->w_host = newstr(&p[1]);
1034 				if (QueueLimitRecipient == NULL)
1035 				{
1036 					i &= ~NEED_R;
1037 					break;
1038 				}
1039 				if (qfver > 0)
1040 				{
1041 					p = strchr(&lbuf[1], ':');
1042 					if (p == NULL)
1043 						p = &lbuf[1];
1044 				}
1045 				else
1046 					p = &lbuf[1];
1047 				check = QueueLimitRecipient;
1048 				while (check != NULL)
1049 				{
1050 					if (strcontainedin(check->queue_match,
1051 							   p))
1052 						break;
1053 					else
1054 						check = check->queue_next;
1055 				}
1056 				if (check != NULL)
1057 					i &= ~NEED_R;
1058 				break;
1059 
1060 			  case 'S':
1061 				  check = QueueLimitSender;
1062 				  while (check != NULL)
1063 				  {
1064 					  if (strcontainedin(check->queue_match,
1065 							     &lbuf[1]))
1066 						  break;
1067 					  else
1068 						  check = check->queue_next;
1069 				  }
1070 				  if (check != NULL)
1071 					  i &= ~NEED_S;
1072 				break;
1073 
1074 			  case 'K':
1075 				age = curtime() - (time_t) atol(&lbuf[1]);
1076 				if (age >= 0 && MinQueueAge > 0 &&
1077 				    age < MinQueueAge)
1078 					w->w_tooyoung = TRUE;
1079 				break;
1080 
1081 			  case 'N':
1082 				if (atol(&lbuf[1]) == 0)
1083 					w->w_tooyoung = FALSE;
1084 				break;
1085 			}
1086 		}
1087 		(void) fclose(cf);
1088 
1089 		if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
1090 		    bitset(NEED_R|NEED_S, i))
1091 		{
1092 			/* don't even bother sorting this job in */
1093 			if (tTd(41, 49))
1094 				printf("skipping %s (%x)\n", w->w_name, i);
1095 			free(w->w_name);
1096 			if (w->w_host)
1097 				free(w->w_host);
1098 			wn--;
1099 		}
1100 	}
1101 	(void) closedir(f);
1102 	wn++;
1103 
1104 	wc = min(wn, WorkListSize);
1105 	if (wc > MaxQueueRun && MaxQueueRun > 0)
1106 		wc = MaxQueueRun;
1107 
1108 	if (QueueSortOrder == QS_BYHOST)
1109 	{
1110 		extern int workcmpf1();
1111 		extern int workcmpf2();
1112 
1113 		/*
1114 		**  Sort the work directory for the first time,
1115 		**  based on host name, lock status, and priority.
1116 		*/
1117 
1118 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1);
1119 
1120 		/*
1121 		**  If one message to host is locked, "lock" all messages
1122 		**  to that host.
1123 		*/
1124 
1125 		i = 0;
1126 		while (i < wc)
1127 		{
1128 			if (!WorkList[i].w_lock)
1129 			{
1130 				i++;
1131 				continue;
1132 			}
1133 			w = &WorkList[i];
1134 			while (++i < wc)
1135 			{
1136 				extern int sm_strcasecmp __P((char *, char *));
1137 
1138 				if (WorkList[i].w_host == NULL &&
1139 				    w->w_host == NULL)
1140 					WorkList[i].w_lock = TRUE;
1141 				else if (WorkList[i].w_host != NULL &&
1142 					 w->w_host != NULL &&
1143 					 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0)
1144 					WorkList[i].w_lock = TRUE;
1145 				else
1146 					break;
1147 			}
1148 		}
1149 
1150 		/*
1151 		**  Sort the work directory for the second time,
1152 		**  based on lock status, host name, and priority.
1153 		*/
1154 
1155 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
1156 	}
1157 	else if (QueueSortOrder == QS_BYTIME)
1158 	{
1159 		extern int workcmpf3();
1160 
1161 		/*
1162 		**  Simple sort based on submission time only.
1163 		*/
1164 
1165 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
1166 	}
1167 	else
1168 	{
1169 		extern int workcmpf0();
1170 
1171 		/*
1172 		**  Simple sort based on queue priority only.
1173 		*/
1174 
1175 		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
1176 	}
1177 
1178 	/*
1179 	**  Convert the work list into canonical form.
1180 	**	Should be turning it into a list of envelopes here perhaps.
1181 	*/
1182 
1183 	WorkQ = NULL;
1184 	for (i = wc; --i >= 0; )
1185 	{
1186 		w = (WORK *) xalloc(sizeof *w);
1187 		w->w_name = WorkList[i].w_name;
1188 		w->w_host = WorkList[i].w_host;
1189 		w->w_lock = WorkList[i].w_lock;
1190 		w->w_tooyoung = WorkList[i].w_tooyoung;
1191 		w->w_pri = WorkList[i].w_pri;
1192 		w->w_ctime = WorkList[i].w_ctime;
1193 		w->w_next = WorkQ;
1194 		WorkQ = w;
1195 	}
1196 	if (WorkList != NULL)
1197 		free(WorkList);
1198 	WorkList = NULL;
1199 	WorkListSize = 0;
1200 
1201 	if (tTd(40, 1))
1202 	{
1203 		for (w = WorkQ; w != NULL; w = w->w_next)
1204 			printf("%32s: pri=%ld\n", w->w_name, w->w_pri);
1205 	}
1206 
1207 	return (wn);
1208 }
1209 /*
1210 **  GROW_WLIST -- make the work list larger
1211 **
1212 **	Parameters:
1213 **		none.
1214 **
1215 **	Returns:
1216 **		none.
1217 **
1218 **	Side Effects:
1219 **		Adds another QUEUESEGSIZE entries to WorkList if possible.
1220 **		It can fail if there isn't enough memory, so WorkListSize
1221 **		should be checked again upon return.
1222 */
1223 
1224 void
1225 grow_wlist()
1226 {
1227 	if (tTd(41, 1))
1228 		printf("grow_wlist: WorkListSize=%d\n", WorkListSize);
1229 	if (WorkList == NULL)
1230 	{
1231 		WorkList = (WORK *) xalloc(sizeof(WORK) * (QUEUESEGSIZE + 1));
1232 		WorkListSize = QUEUESEGSIZE;
1233 	}
1234 	else
1235 	{
1236 		int newsize = WorkListSize + QUEUESEGSIZE;
1237 		WORK *newlist = (WORK *) realloc((char *)WorkList,
1238 					  (unsigned)sizeof(WORK) * (newsize + 1));
1239 
1240 		if (newlist != NULL)
1241 		{
1242 			WorkListSize = newsize;
1243 			WorkList = newlist;
1244 			if (LogLevel > 1)
1245 			{
1246 				sm_syslog(LOG_NOTICE, NOQID,
1247 					"grew WorkList for %s to %d",
1248 					QueueDir, WorkListSize);
1249 			}
1250 		}
1251 		else if (LogLevel > 0)
1252 		{
1253 			sm_syslog(LOG_ALERT, NOQID,
1254 				"FAILED to grow WorkList for %s to %d",
1255 				QueueDir, newsize);
1256 		}
1257 	}
1258 	if (tTd(41, 1))
1259 		printf("grow_wlist: WorkListSize now %d\n", WorkListSize);
1260 }
1261 /*
1262 **  WORKCMPF0 -- simple priority-only compare function.
1263 **
1264 **	Parameters:
1265 **		a -- the first argument.
1266 **		b -- the second argument.
1267 **
1268 **	Returns:
1269 **		-1 if a < b
1270 **		 0 if a == b
1271 **		+1 if a > b
1272 **
1273 **	Side Effects:
1274 **		none.
1275 */
1276 
1277 int
1278 workcmpf0(a, b)
1279 	register WORK *a;
1280 	register WORK *b;
1281 {
1282 	long pa = a->w_pri;
1283 	long pb = b->w_pri;
1284 
1285 	if (pa == pb)
1286 		return 0;
1287 	else if (pa > pb)
1288 		return 1;
1289 	else
1290 		return -1;
1291 }
1292 /*
1293 **  WORKCMPF1 -- first compare function for ordering work based on host name.
1294 **
1295 **	Sorts on host name, lock status, and priority in that order.
1296 **
1297 **	Parameters:
1298 **		a -- the first argument.
1299 **		b -- the second argument.
1300 **
1301 **	Returns:
1302 **		<0 if a < b
1303 **		 0 if a == b
1304 **		>0 if a > b
1305 **
1306 **	Side Effects:
1307 **		none.
1308 */
1309 
1310 int
1311 workcmpf1(a, b)
1312 	register WORK *a;
1313 	register WORK *b;
1314 {
1315 	int i;
1316 	extern int sm_strcasecmp __P((char *, char *));
1317 
1318 	/* host name */
1319 	if (a->w_host != NULL && b->w_host == NULL)
1320 		return 1;
1321 	else if (a->w_host == NULL && b->w_host != NULL)
1322 		return -1;
1323 	if (a->w_host != NULL && b->w_host != NULL &&
1324 	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1325 		return i;
1326 
1327 	/* lock status */
1328 	if (a->w_lock != b->w_lock)
1329 		return b->w_lock - a->w_lock;
1330 
1331 	/* job priority */
1332 	return a->w_pri - b->w_pri;
1333 }
1334 /*
1335 **  WORKCMPF2 -- second compare function for ordering work based on host name.
1336 **
1337 **	Sorts on lock status, host name, and priority in that order.
1338 **
1339 **	Parameters:
1340 **		a -- the first argument.
1341 **		b -- the second argument.
1342 **
1343 **	Returns:
1344 **		<0 if a < b
1345 **		 0 if a == b
1346 **		>0 if a > b
1347 **
1348 **	Side Effects:
1349 **		none.
1350 */
1351 
1352 int
1353 workcmpf2(a, b)
1354 	register WORK *a;
1355 	register WORK *b;
1356 {
1357 	int i;
1358 	extern int sm_strcasecmp __P((char *, char *));
1359 
1360 	/* lock status */
1361 	if (a->w_lock != b->w_lock)
1362 		return a->w_lock - b->w_lock;
1363 
1364 	/* host name */
1365 	if (a->w_host != NULL && b->w_host == NULL)
1366 		return 1;
1367 	else if (a->w_host == NULL && b->w_host != NULL)
1368 		return -1;
1369 	if (a->w_host != NULL && b->w_host != NULL &&
1370 	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1371 		return i;
1372 
1373 	/* job priority */
1374 	return a->w_pri - b->w_pri;
1375 }
1376 /*
1377 **  WORKCMPF3 -- simple submission-time-only compare function.
1378 **
1379 **	Parameters:
1380 **		a -- the first argument.
1381 **		b -- the second argument.
1382 **
1383 **	Returns:
1384 **		-1 if a < b
1385 **		 0 if a == b
1386 **		+1 if a > b
1387 **
1388 **	Side Effects:
1389 **		none.
1390 */
1391 
1392 int
1393 workcmpf3(a, b)
1394 	register WORK *a;
1395 	register WORK *b;
1396 {
1397 	if (a->w_ctime > b->w_ctime)
1398 		return 1;
1399 	else if (a->w_ctime < b->w_ctime)
1400 		return -1;
1401 	else
1402 		return 0;
1403 }
1404 /*
1405 **  DOWORK -- do a work request.
1406 **
1407 **	Parameters:
1408 **		id -- the ID of the job to run.
1409 **		forkflag -- if set, run this in background.
1410 **		requeueflag -- if set, reinstantiate the queue quickly.
1411 **			This is used when expanding aliases in the queue.
1412 **			If forkflag is also set, it doesn't wait for the
1413 **			child.
1414 **		e - the envelope in which to run it.
1415 **
1416 **	Returns:
1417 **		process id of process that is running the queue job.
1418 **
1419 **	Side Effects:
1420 **		The work request is satisfied if possible.
1421 */
1422 
1423 pid_t
1424 dowork(id, forkflag, requeueflag, e)
1425 	char *id;
1426 	bool forkflag;
1427 	bool requeueflag;
1428 	register ENVELOPE *e;
1429 {
1430 	register pid_t pid;
1431 	extern bool readqf __P((ENVELOPE *));
1432 
1433 	if (tTd(40, 1))
1434 		printf("dowork(%s)\n", id);
1435 
1436 	/*
1437 	**  Fork for work.
1438 	*/
1439 
1440 	if (forkflag)
1441 	{
1442 		pid = fork();
1443 		if (pid < 0)
1444 		{
1445 			syserr("dowork: cannot fork");
1446 			return 0;
1447 		}
1448 		else if (pid > 0)
1449 		{
1450 			/* parent -- clean out connection cache */
1451 			mci_flush(FALSE, NULL);
1452 		}
1453 		else
1454 		{
1455 			/* child -- error messages to the transcript */
1456 			QuickAbort = OnlyOneError = FALSE;
1457 
1458 			/*
1459 			**  Since the delivery may happen in a child and the
1460 			**  parent does not wait, the parent may close the
1461 			**  maps thereby removing any shared memory used by
1462 			**  the map.  Therefore, open a copy of the maps for
1463 			**  the delivery process.
1464 			*/
1465 
1466 			initmaps(FALSE, e);
1467 		}
1468 	}
1469 	else
1470 	{
1471 		pid = 0;
1472 	}
1473 
1474 	if (pid == 0)
1475 	{
1476 		/*
1477 		**  CHILD
1478 		**	Lock the control file to avoid duplicate deliveries.
1479 		**		Then run the file as though we had just read it.
1480 		**	We save an idea of the temporary name so we
1481 		**		can recover on interrupt.
1482 		*/
1483 
1484 		/* set basic modes, etc. */
1485 		(void) alarm(0);
1486 		clearenvelope(e, FALSE);
1487 		e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
1488 		e->e_sendmode = SM_DELIVER;
1489 		e->e_errormode = EM_MAIL;
1490 		e->e_id = id;
1491 		GrabTo = UseErrorsTo = FALSE;
1492 		ExitStat = EX_OK;
1493 		if (forkflag)
1494 		{
1495 			disconnect(1, e);
1496 			OpMode = MD_DELIVER;
1497 		}
1498 		sm_setproctitle(TRUE, "%s: from queue", id);
1499 		if (LogLevel > 76)
1500 			sm_syslog(LOG_DEBUG, e->e_id,
1501 				"dowork, pid=%d",
1502 				getpid());
1503 
1504 		/* don't use the headers from sendmail.cf... */
1505 		e->e_header = NULL;
1506 
1507 		/* read the queue control file -- return if locked */
1508 		if (!readqf(e))
1509 		{
1510 			if (tTd(40, 4) && e->e_id != NULL)
1511 				printf("readqf(%s) failed\n", e->e_id);
1512 			e->e_id = NULL;
1513 			if (forkflag)
1514 				finis(FALSE, EX_OK);
1515 			else
1516 				return 0;
1517 		}
1518 
1519 		e->e_flags |= EF_INQUEUE;
1520 		eatheader(e, requeueflag);
1521 
1522 		if (requeueflag)
1523 			queueup(e, FALSE);
1524 
1525 		/* do the delivery */
1526 		sendall(e, SM_DELIVER);
1527 
1528 		/* finish up and exit */
1529 		if (forkflag)
1530 			finis(TRUE, ExitStat);
1531 		else
1532 			dropenvelope(e, TRUE);
1533 	}
1534 	e->e_id = NULL;
1535 	return pid;
1536 }
1537 /*
1538 **  READQF -- read queue file and set up environment.
1539 **
1540 **	Parameters:
1541 **		e -- the envelope of the job to run.
1542 **
1543 **	Returns:
1544 **		TRUE if it successfully read the queue file.
1545 **		FALSE otherwise.
1546 **
1547 **	Side Effects:
1548 **		The queue file is returned locked.
1549 */
1550 
1551 bool
1552 readqf(e)
1553 	register ENVELOPE *e;
1554 {
1555 	register FILE *qfp;
1556 	ADDRESS *ctladdr;
1557 	struct stat st;
1558 	char *bp;
1559 	int qfver = 0;
1560 	long hdrsize = 0;
1561 	register char *p;
1562 	char *orcpt = NULL;
1563 	bool nomore = FALSE;
1564 	char qf[MAXQFNAME];
1565 	char buf[MAXLINE];
1566 	extern ADDRESS *setctluser __P((char *, int));
1567 
1568 	/*
1569 	**  Read and process the file.
1570 	*/
1571 
1572 	strcpy(qf, queuename(e, 'q'));
1573 	qfp = fopen(qf, "r+");
1574 	if (qfp == NULL)
1575 	{
1576 		if (tTd(40, 8))
1577 			printf("readqf(%s): fopen failure (%s)\n",
1578 				qf, errstring(errno));
1579 		if (errno != ENOENT)
1580 			syserr("readqf: no control file %s", qf);
1581 		return FALSE;
1582 	}
1583 
1584 	if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB))
1585 	{
1586 		/* being processed by another queuer */
1587 		if (Verbose || tTd(40, 8))
1588 			printf("%s: locked\n", e->e_id);
1589 		if (LogLevel > 19)
1590 			sm_syslog(LOG_DEBUG, e->e_id, "locked");
1591 		(void) fclose(qfp);
1592 		return FALSE;
1593 	}
1594 
1595 	/*
1596 	**  Check the queue file for plausibility to avoid attacks.
1597 	*/
1598 
1599 	if (fstat(fileno(qfp), &st) < 0)
1600 	{
1601 		/* must have been being processed by someone else */
1602 		if (tTd(40, 8))
1603 			printf("readqf(%s): fstat failure (%s)\n",
1604 				qf, errstring(errno));
1605 		fclose(qfp);
1606 		return FALSE;
1607 	}
1608 
1609 	if ((st.st_uid != geteuid() && geteuid() != RealUid) ||
1610 	    bitset(S_IWOTH|S_IWGRP, st.st_mode))
1611 	{
1612 		if (LogLevel > 0)
1613 		{
1614 			sm_syslog(LOG_ALERT, e->e_id,
1615 				"bogus queue file, uid=%d, mode=%o",
1616 				st.st_uid, st.st_mode);
1617 		}
1618 		if (tTd(40, 8))
1619 			printf("readqf(%s): bogus file\n", qf);
1620 		loseqfile(e, "bogus file uid in mqueue");
1621 		fclose(qfp);
1622 		return FALSE;
1623 	}
1624 
1625 	if (st.st_size == 0)
1626 	{
1627 		/* must be a bogus file -- if also old, just remove it */
1628 		if (st.st_ctime + 10 * 60 < curtime())
1629 		{
1630 			qf[0] = 'd';
1631 			(void) unlink(qf);
1632 			qf[0] = 'q';
1633 			(void) unlink(qf);
1634 		}
1635 		fclose(qfp);
1636 		return FALSE;
1637 	}
1638 
1639 	if (st.st_nlink == 0)
1640 	{
1641 		/*
1642 		**  Race condition -- we got a file just as it was being
1643 		**  unlinked.  Just assume it is zero length.
1644 		*/
1645 
1646 		fclose(qfp);
1647 		return FALSE;
1648 	}
1649 
1650 	/* good file -- save this lock */
1651 	e->e_lockfp = qfp;
1652 
1653 	/* do basic system initialization */
1654 	initsys(e);
1655 	define('i', e->e_id, e);
1656 
1657 	LineNumber = 0;
1658 	e->e_flags |= EF_GLOBALERRS;
1659 	OpMode = MD_DELIVER;
1660 	ctladdr = NULL;
1661 	e->e_dfino = -1;
1662 	e->e_msgsize = -1;
1663 	while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
1664 	{
1665 		register char *p;
1666 		u_long qflags;
1667 		ADDRESS *q;
1668 		int mid;
1669 		auto char *ep;
1670 
1671 		if (tTd(40, 4))
1672 			printf("+++++ %s\n", bp);
1673 		if (nomore)
1674 		{
1675 			/* hack attack */
1676 			syserr("SECURITY ALERT: extra data in qf: %s", bp);
1677 			fclose(qfp);
1678 			loseqfile(e, "bogus queue line");
1679 			return FALSE;
1680 		}
1681 		switch (bp[0])
1682 		{
1683 		  case 'V':		/* queue file version number */
1684 			qfver = atoi(&bp[1]);
1685 			if (qfver <= QF_VERSION)
1686 				break;
1687 			syserr("Version number in qf (%d) greater than max (%d)",
1688 				qfver, QF_VERSION);
1689 			fclose(qfp);
1690 			loseqfile(e, "unsupported qf file version");
1691 			return FALSE;
1692 
1693 		  case 'C':		/* specify controlling user */
1694 			ctladdr = setctluser(&bp[1], qfver);
1695 			break;
1696 
1697 		  case 'Q':		/* original recipient */
1698 			orcpt = newstr(&bp[1]);
1699 			break;
1700 
1701 		  case 'R':		/* specify recipient */
1702 			p = bp;
1703 			qflags = 0;
1704 			if (qfver >= 1)
1705 			{
1706 				/* get flag bits */
1707 				while (*++p != '\0' && *p != ':')
1708 				{
1709 					switch (*p)
1710 					{
1711 					  case 'N':
1712 						qflags |= QHASNOTIFY;
1713 						break;
1714 
1715 					  case 'S':
1716 						qflags |= QPINGONSUCCESS;
1717 						break;
1718 
1719 					  case 'F':
1720 						qflags |= QPINGONFAILURE;
1721 						break;
1722 
1723 					  case 'D':
1724 						qflags |= QPINGONDELAY;
1725 						break;
1726 
1727 					  case 'P':
1728 						qflags |= QPRIMARY;
1729 						break;
1730 					}
1731 				}
1732 			}
1733 			else
1734 				qflags |= QPRIMARY;
1735 			q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e);
1736 			if (q != NULL)
1737 			{
1738 				q->q_alias = ctladdr;
1739 				if (qfver >= 1)
1740 					q->q_flags &= ~Q_PINGFLAGS;
1741 				q->q_flags |= qflags;
1742 				q->q_orcpt = orcpt;
1743 				(void) recipient(q, &e->e_sendqueue, 0, e);
1744 			}
1745 			orcpt = NULL;
1746 			break;
1747 
1748 		  case 'E':		/* specify error recipient */
1749 			/* no longer used */
1750 			break;
1751 
1752 		  case 'H':		/* header */
1753 			(void) chompheader(&bp[1], FALSE, NULL, e);
1754 			hdrsize += strlen(&bp[1]);
1755 			break;
1756 
1757 		  case 'L':		/* Solaris Content-Length: */
1758 		  case 'M':		/* message */
1759 			/* ignore this; we want a new message next time */
1760 			break;
1761 
1762 		  case 'S':		/* sender */
1763 			setsender(newstr(&bp[1]), e, NULL, '\0', TRUE);
1764 			break;
1765 
1766 		  case 'B':		/* body type */
1767 			e->e_bodytype = newstr(&bp[1]);
1768 			break;
1769 
1770 #if _FFR_SAVE_CHARSET
1771 		  case 'X':		/* character set */
1772 			e->e_charset = newstr(&bp[1]);
1773 			break;
1774 #endif
1775 
1776 		  case 'D':		/* data file name */
1777 			/* obsolete -- ignore */
1778 			break;
1779 
1780 		  case 'T':		/* init time */
1781 			e->e_ctime = atol(&bp[1]);
1782 			break;
1783 
1784 		  case 'I':		/* data file's inode number */
1785 			/* regenerated below */
1786 			break;
1787 
1788 		  case 'K':		/* time of last deliver attempt */
1789 			e->e_dtime = atol(&buf[1]);
1790 			break;
1791 
1792 		  case 'N':		/* number of delivery attempts */
1793 			e->e_ntries = atoi(&buf[1]);
1794 
1795 			/* if this has been tried recently, let it be */
1796 			if (e->e_ntries > 0 &&
1797 			    MinQueueAge > 0 && e->e_dtime <= curtime() &&
1798 			    curtime() < e->e_dtime + MinQueueAge)
1799 			{
1800 				char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
1801 
1802 				if (Verbose || tTd(40, 8))
1803 					printf("%s: too young (%s)\n",
1804 						e->e_id, howlong);
1805 				if (LogLevel > 19)
1806 					sm_syslog(LOG_DEBUG, e->e_id,
1807 						"too young (%s)",
1808 						howlong);
1809 				e->e_id = NULL;
1810 				unlockqueue(e);
1811 				return FALSE;
1812 			}
1813 			break;
1814 
1815 		  case 'P':		/* message priority */
1816 			e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
1817 			break;
1818 
1819 		  case 'F':		/* flag bits */
1820 			if (strncmp(bp, "From ", 5) == 0)
1821 			{
1822 				/* we are being spoofed! */
1823 				syserr("SECURITY ALERT: bogus qf line %s", bp);
1824 				fclose(qfp);
1825 				loseqfile(e, "bogus queue line");
1826 				return FALSE;
1827 			}
1828 			for (p = &bp[1]; *p != '\0'; p++)
1829 			{
1830 				switch (*p)
1831 				{
1832 				  case 'w':	/* warning sent */
1833 					e->e_flags |= EF_WARNING;
1834 					break;
1835 
1836 				  case 'r':	/* response */
1837 					e->e_flags |= EF_RESPONSE;
1838 					break;
1839 
1840 				  case '8':	/* has 8 bit data */
1841 					e->e_flags |= EF_HAS8BIT;
1842 					break;
1843 
1844 				  case 'b':	/* delete Bcc: header */
1845 					e->e_flags |= EF_DELETE_BCC;
1846 					break;
1847 
1848 				  case 'd':	/* envelope has DSN RET= */
1849 					e->e_flags |= EF_RET_PARAM;
1850 					break;
1851 
1852 				  case 'n':	/* don't return body */
1853 					e->e_flags |= EF_NO_BODY_RETN;
1854 					break;
1855 				}
1856 			}
1857 			break;
1858 
1859 		  case 'Z':		/* original envelope id from ESMTP */
1860 			e->e_envid = newstr(&bp[1]);
1861 			break;
1862 
1863 		  case '$':		/* define macro */
1864 			mid = macid(&bp[1], &ep);
1865 			define(mid, newstr(ep), e);
1866 			break;
1867 
1868 		  case '.':		/* terminate file */
1869 			nomore = TRUE;
1870 			break;
1871 
1872 		  default:
1873 			syserr("readqf: %s: line %d: bad line \"%s\"",
1874 				qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
1875 			fclose(qfp);
1876 			loseqfile(e, "unrecognized line");
1877 			return FALSE;
1878 		}
1879 
1880 		if (bp != buf)
1881 			free(bp);
1882 	}
1883 
1884 	/*
1885 	**  If we haven't read any lines, this queue file is empty.
1886 	**  Arrange to remove it without referencing any null pointers.
1887 	*/
1888 
1889 	if (LineNumber == 0)
1890 	{
1891 		errno = 0;
1892 		e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
1893 		return TRUE;
1894 	}
1895 
1896 	/*
1897 	**  Arrange to read the data file.
1898 	*/
1899 
1900 	p = queuename(e, 'd');
1901 	e->e_dfp = fopen(p, "r");
1902 	if (e->e_dfp == NULL)
1903 	{
1904 		syserr("readqf: cannot open %s", p);
1905 	}
1906 	else
1907 	{
1908 		e->e_flags |= EF_HAS_DF;
1909 		if (fstat(fileno(e->e_dfp), &st) >= 0)
1910 		{
1911 			e->e_msgsize = st.st_size + hdrsize;
1912 			e->e_dfdev = st.st_dev;
1913 			e->e_dfino = st.st_ino;
1914 		}
1915 	}
1916 
1917 	return TRUE;
1918 }
1919 /*
1920 **  PRINTQUEUE -- print out a representation of the mail queue
1921 **
1922 **	Parameters:
1923 **		none.
1924 **
1925 **	Returns:
1926 **		none.
1927 **
1928 **	Side Effects:
1929 **		Prints a listing of the mail queue on the standard output.
1930 */
1931 
1932 void
1933 printqueue()
1934 {
1935 	register WORK *w;
1936 	FILE *f;
1937 	int nrequests;
1938 	char buf[MAXLINE];
1939 
1940 	/*
1941 	**  Check for permission to print the queue
1942 	*/
1943 
1944 	if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
1945 	{
1946 		struct stat st;
1947 # ifdef NGROUPS_MAX
1948 		int n;
1949 		extern GIDSET_T InitialGidSet[NGROUPS_MAX];
1950 # endif
1951 
1952 		if (stat(QueueDir, &st) < 0)
1953 		{
1954 			syserr("Cannot stat %s", QueueDir);
1955 			return;
1956 		}
1957 # ifdef NGROUPS_MAX
1958 		n = NGROUPS_MAX;
1959 		while (--n >= 0)
1960 		{
1961 			if (InitialGidSet[n] == st.st_gid)
1962 				break;
1963 		}
1964 		if (n < 0 && RealGid != st.st_gid)
1965 # else
1966 		if (RealGid != st.st_gid)
1967 # endif
1968 		{
1969 			usrerr("510 You are not permitted to see the queue");
1970 			setstat(EX_NOPERM);
1971 			return;
1972 		}
1973 	}
1974 
1975 	/*
1976 	**  Read and order the queue.
1977 	*/
1978 
1979 	nrequests = orderq(TRUE);
1980 
1981 	/*
1982 	**  Print the work list that we have read.
1983 	*/
1984 
1985 	/* first see if there is anything */
1986 	if (nrequests <= 0)
1987 	{
1988 		printf("Mail queue is empty\n");
1989 		return;
1990 	}
1991 
1992 	CurrentLA = getla();	/* get load average */
1993 
1994 	printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
1995 	if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
1996 		printf(", only %d printed", MaxQueueRun);
1997 	if (Verbose)
1998 		printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
1999 	else
2000 		printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
2001 	for (w = WorkQ; w != NULL; w = w->w_next)
2002 	{
2003 		struct stat st;
2004 		auto time_t submittime = 0;
2005 		long dfsize;
2006 		int flags = 0;
2007 		int qfver;
2008 		char statmsg[MAXLINE];
2009 		char bodytype[MAXNAME + 1];
2010 
2011 		printf("%8s", w->w_name + 2);
2012 		f = fopen(w->w_name, "r");
2013 		if (f == NULL)
2014 		{
2015 			printf(" (job completed)\n");
2016 			errno = 0;
2017 			continue;
2018 		}
2019 		w->w_name[0] = 'd';
2020 		if (stat(w->w_name, &st) >= 0)
2021 			dfsize = st.st_size;
2022 		else
2023 			dfsize = -1;
2024 		if (w->w_lock)
2025 			printf("*");
2026 		else if (w->w_tooyoung)
2027 			printf("-");
2028 		else if (shouldqueue(w->w_pri, w->w_ctime))
2029 			printf("X");
2030 		else
2031 			printf(" ");
2032 		errno = 0;
2033 
2034 		statmsg[0] = bodytype[0] = '\0';
2035 		qfver = 0;
2036 		while (fgets(buf, sizeof buf, f) != NULL)
2037 		{
2038 			register int i;
2039 			register char *p;
2040 
2041 			fixcrlf(buf, TRUE);
2042 			switch (buf[0])
2043 			{
2044 			  case 'V':	/* queue file version */
2045 				qfver = atoi(&buf[1]);
2046 				break;
2047 
2048 			  case 'M':	/* error message */
2049 				if ((i = strlen(&buf[1])) >= sizeof statmsg)
2050 					i = sizeof statmsg - 1;
2051 				bcopy(&buf[1], statmsg, i);
2052 				statmsg[i] = '\0';
2053 				break;
2054 
2055 			  case 'B':	/* body type */
2056 				if ((i = strlen(&buf[1])) >= sizeof bodytype)
2057 					i = sizeof bodytype - 1;
2058 				bcopy(&buf[1], bodytype, i);
2059 				bodytype[i] = '\0';
2060 				break;
2061 
2062 			  case 'S':	/* sender name */
2063 				if (Verbose)
2064 					printf("%8ld %10ld%c%.12s %.78s",
2065 					    dfsize,
2066 					    w->w_pri,
2067 					    bitset(EF_WARNING, flags) ? '+' : ' ',
2068 					    ctime(&submittime) + 4,
2069 					    &buf[1]);
2070 				else
2071 					printf("%8ld %.16s %.45s", dfsize,
2072 					    ctime(&submittime), &buf[1]);
2073 				if (statmsg[0] != '\0' || bodytype[0] != '\0')
2074 				{
2075 					printf("\n    %10.10s", bodytype);
2076 					if (statmsg[0] != '\0')
2077 						printf("   (%.*s)",
2078 							Verbose ? 100 : 60,
2079 							statmsg);
2080 				}
2081 				break;
2082 
2083 			  case 'C':	/* controlling user */
2084 				if (Verbose)
2085 					printf("\n\t\t\t\t      (---%.74s---)",
2086 						&buf[1]);
2087 				break;
2088 
2089 			  case 'R':	/* recipient name */
2090 				p = &buf[1];
2091 				if (qfver >= 1)
2092 				{
2093 					p = strchr(p, ':');
2094 					if (p == NULL)
2095 						break;
2096 					p++;
2097 				}
2098 				if (Verbose)
2099 					printf("\n\t\t\t\t\t  %.78s", p);
2100 				else
2101 					printf("\n\t\t\t\t   %.45s", p);
2102 				break;
2103 
2104 			  case 'T':	/* creation time */
2105 				submittime = atol(&buf[1]);
2106 				break;
2107 
2108 			  case 'F':	/* flag bits */
2109 				for (p = &buf[1]; *p != '\0'; p++)
2110 				{
2111 					switch (*p)
2112 					{
2113 					  case 'w':
2114 						flags |= EF_WARNING;
2115 						break;
2116 					}
2117 				}
2118 			}
2119 		}
2120 		if (submittime == (time_t) 0)
2121 			printf(" (no control file)");
2122 		printf("\n");
2123 		(void) fclose(f);
2124 	}
2125 }
2126 
2127 # endif /* QUEUE */
2128 /*
2129 **  QUEUENAME -- build a file name in the queue directory for this envelope.
2130 **
2131 **	Assigns an id code if one does not already exist.
2132 **	This code is very careful to avoid trashing existing files
2133 **	under any circumstances.
2134 **
2135 **	Parameters:
2136 **		e -- envelope to build it in/from.
2137 **		type -- the file type, used as the first character
2138 **			of the file name.
2139 **
2140 **	Returns:
2141 **		a pointer to the new file name (in a static buffer).
2142 **
2143 **	Side Effects:
2144 **		If no id code is already assigned, queuename will
2145 **		assign an id code, create a qf file, and leave a
2146 **		locked, open-for-write file pointer in the envelope.
2147 */
2148 
2149 #ifndef ENOLCK
2150 # define ENOLCK		-1
2151 #endif
2152 #ifndef ENOSPC
2153 # define ENOSPC		-1
2154 #endif
2155 
2156 char *
2157 queuename(e, type)
2158 	register ENVELOPE *e;
2159 	int type;
2160 {
2161 	static pid_t pid = -1;
2162 	static char c0;
2163 	static char c1;
2164 	static char c2;
2165 	time_t now;
2166 	struct tm *tm;
2167 	static char buf[MAXNAME + 1];
2168 
2169 	if (e->e_id == NULL)
2170 	{
2171 		char qf[MAXQFNAME];
2172 
2173 		/* find a unique id */
2174 		if (pid != getpid())
2175 		{
2176 			/* new process -- start back at "AA" */
2177 			pid = getpid();
2178 			now = curtime();
2179 			tm = localtime(&now);
2180 			c0 = 'A' + tm->tm_hour;
2181 			c1 = 'A';
2182 			c2 = 'A' - 1;
2183 		}
2184 		(void) snprintf(qf, sizeof qf, "qf%cAA%05d", c0, pid);
2185 
2186 		while (c1 < '~' || c2 < 'Z')
2187 		{
2188 			int i;
2189 			int attempts = 0;
2190 
2191 			if (c2 >= 'Z')
2192 			{
2193 				c1++;
2194 				c2 = 'A' - 1;
2195 			}
2196 			qf[3] = c1;
2197 			qf[4] = ++c2;
2198 			if (tTd(7, 20))
2199 				printf("queuename: trying \"%s\"\n", qf);
2200 
2201 			i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
2202 			if (i < 0)
2203 			{
2204 				if (errno == EEXIST)
2205 					continue;
2206 				syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
2207 					qf, QueueDir, geteuid());
2208 				finis(FALSE, EX_UNAVAILABLE);
2209 			}
2210 			do
2211 			{
2212 				if (attempts > 0)
2213 					sleep(attempts);
2214 				e->e_lockfp = 0;
2215 				if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB))
2216 				{
2217 					e->e_lockfp = fdopen(i, "w");
2218 					break;
2219 				}
2220 			} while ((errno == ENOLCK || errno == ENOSPC) &&
2221 				 attempts++ < 4);
2222 
2223 			/* Successful lock */
2224 			if (e->e_lockfp != 0)
2225 				break;
2226 
2227 #if !HASFLOCK
2228 			if (errno != EAGAIN && errno != EACCES)
2229 #else
2230 			if (errno != EWOULDBLOCK)
2231 #endif
2232 			{
2233 				syserr("queuename: Cannot lock \"%s\" in \"%s\" (euid=%d)",
2234 					qf, QueueDir, geteuid());
2235 				finis(FALSE, EX_OSERR);
2236 			}
2237 
2238 			/* a reader got the file; abandon it and try again */
2239 			(void) close(i);
2240 		}
2241 		if (c1 >= '~' && c2 >= 'Z')
2242 		{
2243 			syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
2244 				qf, QueueDir, geteuid());
2245 			finis(FALSE, EX_OSERR);
2246 		}
2247 		e->e_id = newstr(&qf[2]);
2248 		define('i', e->e_id, e);
2249 		if (tTd(7, 1))
2250 			printf("queuename: assigned id %s, env=%lx\n",
2251 			       e->e_id, (u_long) e);
2252 		if (tTd(7, 9))
2253 		{
2254 			printf("  lockfd=");
2255 			dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
2256 		}
2257 		if (LogLevel > 93)
2258 			sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
2259 	}
2260 
2261 	if (type == '\0')
2262 		return (NULL);
2263 	(void) snprintf(buf, sizeof buf, "%cf%s", type, e->e_id);
2264 	if (tTd(7, 2))
2265 		printf("queuename: %s\n", buf);
2266 	return (buf);
2267 }
2268 /*
2269 **  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
2270 **
2271 **	Parameters:
2272 **		e -- the envelope to unlock.
2273 **
2274 **	Returns:
2275 **		none
2276 **
2277 **	Side Effects:
2278 **		unlocks the queue for `e'.
2279 */
2280 
2281 void
2282 unlockqueue(e)
2283 	ENVELOPE *e;
2284 {
2285 	if (tTd(51, 4))
2286 		printf("unlockqueue(%s)\n",
2287 			e->e_id == NULL ? "NOQUEUE" : e->e_id);
2288 
2289 	/* if there is a lock file in the envelope, close it */
2290 	if (e->e_lockfp != NULL)
2291 		xfclose(e->e_lockfp, "unlockqueue", e->e_id);
2292 	e->e_lockfp = NULL;
2293 
2294 	/* don't create a queue id if we don't already have one */
2295 	if (e->e_id == NULL)
2296 		return;
2297 
2298 	/* remove the transcript */
2299 	if (LogLevel > 87)
2300 		sm_syslog(LOG_DEBUG, e->e_id, "unlock");
2301 	if (!tTd(51, 104))
2302 		xunlink(queuename(e, 'x'));
2303 
2304 }
2305 /*
2306 **  SETCTLUSER -- create a controlling address
2307 **
2308 **	Create a fake "address" given only a local login name; this is
2309 **	used as a "controlling user" for future recipient addresses.
2310 **
2311 **	Parameters:
2312 **		user -- the user name of the controlling user.
2313 **		qfver -- the version stamp of this qf file.
2314 **
2315 **	Returns:
2316 **		An address descriptor for the controlling user.
2317 **
2318 **	Side Effects:
2319 **		none.
2320 */
2321 
2322 ADDRESS *
2323 setctluser(user, qfver)
2324 	char *user;
2325 	int qfver;
2326 {
2327 	register ADDRESS *a;
2328 	struct passwd *pw;
2329 	char *p;
2330 
2331 	/*
2332 	**  See if this clears our concept of controlling user.
2333 	*/
2334 
2335 	if (user == NULL || *user == '\0')
2336 		return NULL;
2337 
2338 	/*
2339 	**  Set up addr fields for controlling user.
2340 	*/
2341 
2342 	a = (ADDRESS *) xalloc(sizeof *a);
2343 	bzero((char *) a, sizeof *a);
2344 
2345 	if (*user == '\0')
2346 	{
2347 		p = NULL;
2348 		a->q_user = newstr(DefUser);
2349 	}
2350 	else if (*user == ':')
2351 	{
2352 		p = &user[1];
2353 		a->q_user = newstr(p);
2354 	}
2355 	else
2356 	{
2357 		p = strtok(user, ":");
2358 		a->q_user = newstr(user);
2359 		if (qfver >= 2)
2360 		{
2361 			if ((p = strtok(NULL, ":")) != NULL)
2362 				a->q_uid = atoi(p);
2363 			if ((p = strtok(NULL, ":")) != NULL)
2364 				a->q_gid = atoi(p);
2365 			if ((p = strtok(NULL, ":")) != NULL)
2366 				a->q_flags |= QGOODUID;
2367 		}
2368 		else if ((pw = sm_getpwnam(user)) != NULL)
2369 		{
2370 			if (strcmp(pw->pw_dir, "/") == 0)
2371 				a->q_home = "";
2372 			else
2373 				a->q_home = newstr(pw->pw_dir);
2374 			a->q_uid = pw->pw_uid;
2375 			a->q_gid = pw->pw_gid;
2376 			a->q_flags |= QGOODUID;
2377 		}
2378 	}
2379 
2380 	a->q_flags |= QPRIMARY;		/* flag as a "ctladdr"  */
2381 	a->q_mailer = LocalMailer;
2382 	if (p == NULL)
2383 		a->q_paddr = a->q_user;
2384 	else
2385 		a->q_paddr = newstr(p);
2386 	return a;
2387 }
2388 /*
2389 **  LOSEQFILE -- save the qf as Qf and try to let someone know
2390 **
2391 **	Parameters:
2392 **		e -- the envelope (e->e_id will be used).
2393 **		why -- reported to whomever can hear.
2394 **
2395 **	Returns:
2396 **		none.
2397 */
2398 
2399 void
2400 loseqfile(e, why)
2401 	register ENVELOPE *e;
2402 	char *why;
2403 {
2404 	char *p;
2405 	char buf[MAXQFNAME + 1];
2406 
2407 	if (e == NULL || e->e_id == NULL)
2408 		return;
2409 	p = queuename(e, 'q');
2410 	if (strlen(p) > MAXQFNAME)
2411 	{
2412 		syserr("loseqfile: queuename (%s) too long", p);
2413 		return;
2414 	}
2415 	strcpy(buf, p);
2416 	p = queuename(e, 'Q');
2417 	if (rename(buf, p) < 0)
2418 		syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
2419 	else if (LogLevel > 0)
2420 		sm_syslog(LOG_ALERT, e->e_id,
2421 			"Losing %s: %s", buf, why);
2422 }
2423