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