xref: /freebsd/contrib/sendmail/src/envelope.c (revision 13d882686343bf9a76ffdfa83854043d808703dd)
1c2aa98e2SPeter Wemm /*
2e92d3f3fSGregory Neil Shapiro  * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5c2aa98e2SPeter Wemm  * Copyright (c) 1988, 1993
6c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
7c2aa98e2SPeter Wemm  *
8c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm  * the sendmail distribution.
11c2aa98e2SPeter Wemm  *
12c2aa98e2SPeter Wemm  */
13c2aa98e2SPeter Wemm 
1406f25ae9SGregory Neil Shapiro #include <sendmail.h>
1506f25ae9SGregory Neil Shapiro 
1613d88268SGregory Neil Shapiro SM_RCSID("@(#)$Id: envelope.c,v 8.294 2005/02/16 23:38:51 ca Exp $")
1713bd1963SGregory Neil Shapiro 
1813bd1963SGregory Neil Shapiro /*
1913bd1963SGregory Neil Shapiro **  CLRSESSENVELOPE -- clear session oriented data in an envelope
2013bd1963SGregory Neil Shapiro **
2113bd1963SGregory Neil Shapiro **	Parameters:
2213bd1963SGregory Neil Shapiro **		e -- the envelope to clear.
2313bd1963SGregory Neil Shapiro **
2413bd1963SGregory Neil Shapiro **	Returns:
2513bd1963SGregory Neil Shapiro **		none.
2613bd1963SGregory Neil Shapiro */
2713bd1963SGregory Neil Shapiro 
2813bd1963SGregory Neil Shapiro void
2913bd1963SGregory Neil Shapiro clrsessenvelope(e)
3013bd1963SGregory Neil Shapiro 	ENVELOPE *e;
3113bd1963SGregory Neil Shapiro {
3213bd1963SGregory Neil Shapiro #if SASL
3313bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{auth_type}"), "");
3413bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{auth_authen}"), "");
3513bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{auth_author}"), "");
3613bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{auth_ssf}"), "");
3713bd1963SGregory Neil Shapiro #endif /* SASL */
3813bd1963SGregory Neil Shapiro #if STARTTLS
3913bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{cert_issuer}"), "");
4013bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{cert_subject}"), "");
4113bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{cipher_bits}"), "");
4213bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{cipher}"), "");
4313bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{tls_version}"), "");
4413bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{verify}"), "");
4513bd1963SGregory Neil Shapiro # if _FFR_TLS_1
4613bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{alg_bits}"), "");
4713bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{cn_issuer}"), "");
4813bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{cn_subject}"), "");
4913bd1963SGregory Neil Shapiro # endif /* _FFR_TLS_1 */
5013bd1963SGregory Neil Shapiro #endif /* STARTTLS */
5113bd1963SGregory Neil Shapiro }
52c2aa98e2SPeter Wemm 
53c2aa98e2SPeter Wemm /*
5440266059SGregory Neil Shapiro **  NEWENVELOPE -- fill in a new envelope
55c2aa98e2SPeter Wemm **
56c2aa98e2SPeter Wemm **	Supports inheritance.
57c2aa98e2SPeter Wemm **
58c2aa98e2SPeter Wemm **	Parameters:
59c2aa98e2SPeter Wemm **		e -- the new envelope to fill in.
60c2aa98e2SPeter Wemm **		parent -- the envelope to be the parent of e.
6140266059SGregory Neil Shapiro **		rpool -- either NULL, or a pointer to a resource pool
6240266059SGregory Neil Shapiro **			from which envelope memory is allocated, and
6340266059SGregory Neil Shapiro **			to which envelope resources are attached.
64c2aa98e2SPeter Wemm **
65c2aa98e2SPeter Wemm **	Returns:
66c2aa98e2SPeter Wemm **		e.
67c2aa98e2SPeter Wemm **
68c2aa98e2SPeter Wemm **	Side Effects:
69c2aa98e2SPeter Wemm **		none.
70c2aa98e2SPeter Wemm */
71c2aa98e2SPeter Wemm 
72c2aa98e2SPeter Wemm ENVELOPE *
7340266059SGregory Neil Shapiro newenvelope(e, parent, rpool)
74c2aa98e2SPeter Wemm 	register ENVELOPE *e;
75c2aa98e2SPeter Wemm 	register ENVELOPE *parent;
7640266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
77c2aa98e2SPeter Wemm {
7840266059SGregory Neil Shapiro 	/*
7940266059SGregory Neil Shapiro 	**  This code used to read:
8040266059SGregory Neil Shapiro 	**	if (e == parent && e->e_parent != NULL)
8140266059SGregory Neil Shapiro 	**		parent = e->e_parent;
8240266059SGregory Neil Shapiro 	**  So if e == parent && e->e_parent == NULL then we would
8340266059SGregory Neil Shapiro 	**  set e->e_parent = e, which creates a loop in the e_parent chain.
8440266059SGregory Neil Shapiro 	**  This meant macvalue() could go into an infinite loop.
8540266059SGregory Neil Shapiro 	*/
8640266059SGregory Neil Shapiro 
8740266059SGregory Neil Shapiro 	if (e == parent)
88c2aa98e2SPeter Wemm 		parent = e->e_parent;
8940266059SGregory Neil Shapiro 	clearenvelope(e, true, rpool);
90c2aa98e2SPeter Wemm 	if (e == CurEnv)
9106f25ae9SGregory Neil Shapiro 		memmove((char *) &e->e_from,
9206f25ae9SGregory Neil Shapiro 			(char *) &NullAddress,
9306f25ae9SGregory Neil Shapiro 			sizeof e->e_from);
94c2aa98e2SPeter Wemm 	else
9506f25ae9SGregory Neil Shapiro 		memmove((char *) &e->e_from,
9606f25ae9SGregory Neil Shapiro 			(char *) &CurEnv->e_from,
9706f25ae9SGregory Neil Shapiro 			sizeof e->e_from);
98c2aa98e2SPeter Wemm 	e->e_parent = parent;
9906f25ae9SGregory Neil Shapiro 	assign_queueid(e);
100c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
101c2aa98e2SPeter Wemm 	if (parent != NULL)
10240266059SGregory Neil Shapiro 	{
103c2aa98e2SPeter Wemm 		e->e_msgpriority = parent->e_msgsize;
10440266059SGregory Neil Shapiro 		if (parent->e_quarmsg == NULL)
10540266059SGregory Neil Shapiro 		{
10640266059SGregory Neil Shapiro 			e->e_quarmsg = NULL;
10740266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM,
10840266059SGregory Neil Shapiro 				  macid("{quarantine}"), "");
10940266059SGregory Neil Shapiro 		}
11040266059SGregory Neil Shapiro 		else
11140266059SGregory Neil Shapiro 		{
11240266059SGregory Neil Shapiro 			e->e_quarmsg = sm_rpool_strdup_x(rpool,
11340266059SGregory Neil Shapiro 							 parent->e_quarmsg);
11440266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM,
11540266059SGregory Neil Shapiro 				  macid("{quarantine}"), e->e_quarmsg);
11640266059SGregory Neil Shapiro 		}
11740266059SGregory Neil Shapiro 	}
118c2aa98e2SPeter Wemm 	e->e_puthdr = putheader;
119c2aa98e2SPeter Wemm 	e->e_putbody = putbody;
120c2aa98e2SPeter Wemm 	if (CurEnv->e_xfp != NULL)
12140266059SGregory Neil Shapiro 		(void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT);
122c2aa98e2SPeter Wemm 
12306f25ae9SGregory Neil Shapiro 	return e;
124c2aa98e2SPeter Wemm }
12540266059SGregory Neil Shapiro 
12640266059SGregory Neil Shapiro /* values for msg_timeout, see also IS_* below for usage (bit layout) */
12740266059SGregory Neil Shapiro #define MSG_T_O		0x01	/* normal timeout */
12840266059SGregory Neil Shapiro #define MSG_T_O_NOW	0x02	/* NOW timeout */
12940266059SGregory Neil Shapiro #define MSG_NOT_BY	0x04	/* Deliver-By time exceeded, mode R */
13040266059SGregory Neil Shapiro #define MSG_WARN	0x10	/* normal queue warning */
13140266059SGregory Neil Shapiro #define MSG_WARN_BY	0x20	/* Deliver-By time exceeded, mode N */
13240266059SGregory Neil Shapiro 
13340266059SGregory Neil Shapiro #define IS_MSG_ERR(x)	(((x) & 0x0f) != 0)	/* return an error */
13440266059SGregory Neil Shapiro 
13540266059SGregory Neil Shapiro /* immediate return */
13640266059SGregory Neil Shapiro #define IS_IMM_RET(x)	(((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0)
13740266059SGregory Neil Shapiro #define IS_MSG_WARN(x)	(((x) & 0xf0) != 0)	/* return a warning */
13840266059SGregory Neil Shapiro 
13940266059SGregory Neil Shapiro /*
140c2aa98e2SPeter Wemm **  DROPENVELOPE -- deallocate an envelope.
141c2aa98e2SPeter Wemm **
142c2aa98e2SPeter Wemm **	Parameters:
143c2aa98e2SPeter Wemm **		e -- the envelope to deallocate.
144c2aa98e2SPeter Wemm **		fulldrop -- if set, do return receipts.
14540266059SGregory Neil Shapiro **		split -- if true, split by recipient if message is queued up
146c2aa98e2SPeter Wemm **
147c2aa98e2SPeter Wemm **	Returns:
148c2aa98e2SPeter Wemm **		none.
149c2aa98e2SPeter Wemm **
150c2aa98e2SPeter Wemm **	Side Effects:
151c2aa98e2SPeter Wemm **		housekeeping necessary to dispose of an envelope.
152c2aa98e2SPeter Wemm **		Unlocks this queue file.
153c2aa98e2SPeter Wemm */
154c2aa98e2SPeter Wemm 
155c2aa98e2SPeter Wemm void
15640266059SGregory Neil Shapiro dropenvelope(e, fulldrop, split)
157c2aa98e2SPeter Wemm 	register ENVELOPE *e;
158c2aa98e2SPeter Wemm 	bool fulldrop;
15940266059SGregory Neil Shapiro 	bool split;
160c2aa98e2SPeter Wemm {
16140266059SGregory Neil Shapiro 	bool panic = false;
16240266059SGregory Neil Shapiro 	bool queueit = false;
16340266059SGregory Neil Shapiro 	int msg_timeout = 0;
16440266059SGregory Neil Shapiro 	bool failure_return = false;
16540266059SGregory Neil Shapiro 	bool delay_return = false;
16640266059SGregory Neil Shapiro 	bool success_return = false;
16706f25ae9SGregory Neil Shapiro 	bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags);
16840266059SGregory Neil Shapiro 	bool done = false;
169c2aa98e2SPeter Wemm 	register ADDRESS *q;
170c2aa98e2SPeter Wemm 	char *id = e->e_id;
171193538b7SGregory Neil Shapiro 	time_t now;
172c2aa98e2SPeter Wemm 	char buf[MAXLINE];
173c2aa98e2SPeter Wemm 
174c2aa98e2SPeter Wemm 	if (tTd(50, 1))
175c2aa98e2SPeter Wemm 	{
17640266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope %p: id=", e);
177e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), e->e_id);
17840266059SGregory Neil Shapiro 		sm_dprintf(", flags=");
179c2aa98e2SPeter Wemm 		printenvflags(e);
180c2aa98e2SPeter Wemm 		if (tTd(50, 10))
181c2aa98e2SPeter Wemm 		{
18240266059SGregory Neil Shapiro 			sm_dprintf("sendq=");
183e92d3f3fSGregory Neil Shapiro 			printaddr(sm_debug_file(), e->e_sendqueue, true);
184c2aa98e2SPeter Wemm 		}
185c2aa98e2SPeter Wemm 	}
186c2aa98e2SPeter Wemm 
187c2aa98e2SPeter Wemm 	if (LogLevel > 84)
188c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, id,
18906f25ae9SGregory Neil Shapiro 			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
19040266059SGregory Neil Shapiro 			  e->e_flags, OpMode, (int) CurrentPid);
191c2aa98e2SPeter Wemm 
192c2aa98e2SPeter Wemm 	/* we must have an id to remove disk files */
193c2aa98e2SPeter Wemm 	if (id == NULL)
194c2aa98e2SPeter Wemm 		return;
195c2aa98e2SPeter Wemm 
196c2aa98e2SPeter Wemm 	/* if verify-only mode, we can skip most of this */
197c2aa98e2SPeter Wemm 	if (OpMode == MD_VERIFY)
198c2aa98e2SPeter Wemm 		goto simpledrop;
199c2aa98e2SPeter Wemm 
200c2aa98e2SPeter Wemm 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
201c2aa98e2SPeter Wemm 		logsender(e, NULL);
202c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_LOGSENDER;
203c2aa98e2SPeter Wemm 
204c2aa98e2SPeter Wemm 	/* post statistics */
205c2aa98e2SPeter Wemm 	poststats(StatFile);
206c2aa98e2SPeter Wemm 
207c2aa98e2SPeter Wemm 	/*
208c2aa98e2SPeter Wemm 	**  Extract state information from dregs of send list.
209c2aa98e2SPeter Wemm 	*/
210c2aa98e2SPeter Wemm 
211193538b7SGregory Neil Shapiro 	now = curtime();
2128774250cSGregory Neil Shapiro 	if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
21340266059SGregory Neil Shapiro 		msg_timeout = MSG_T_O;
21440266059SGregory Neil Shapiro 	if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 &&
21540266059SGregory Neil Shapiro 	    now >= e->e_ctime + e->e_deliver_by &&
21606f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags))
21706f25ae9SGregory Neil Shapiro 	{
21840266059SGregory Neil Shapiro 		msg_timeout = MSG_NOT_BY;
21940266059SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22040266059SGregory Neil Shapiro 	}
22140266059SGregory Neil Shapiro 	else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
22240266059SGregory Neil Shapiro 		 !bitset(EF_RESPONSE, e->e_flags))
22340266059SGregory Neil Shapiro 	{
22440266059SGregory Neil Shapiro 		msg_timeout = MSG_T_O_NOW;
22506f25ae9SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22606f25ae9SGregory Neil Shapiro 	}
22706f25ae9SGregory Neil Shapiro 
228c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_QUEUERUN;
229c2aa98e2SPeter Wemm 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
230c2aa98e2SPeter Wemm 	{
23106f25ae9SGregory Neil Shapiro 		if (QS_IS_UNDELIVERED(q->q_state))
23240266059SGregory Neil Shapiro 			queueit = true;
233c2aa98e2SPeter Wemm 
234c2aa98e2SPeter Wemm 		/* see if a notification is needed */
235c2aa98e2SPeter Wemm 		if (bitset(QPINGONFAILURE, q->q_flags) &&
23640266059SGregory Neil Shapiro 		    ((IS_MSG_ERR(msg_timeout) &&
23740266059SGregory Neil Shapiro 		      QS_IS_UNDELIVERED(q->q_state)) ||
23806f25ae9SGregory Neil Shapiro 		     QS_IS_BADADDR(q->q_state) ||
23940266059SGregory Neil Shapiro 		     IS_IMM_RET(msg_timeout)))
240c2aa98e2SPeter Wemm 		{
24140266059SGregory Neil Shapiro 			failure_return = true;
24206f25ae9SGregory Neil Shapiro 			if (!done && q->q_owner == NULL &&
24306f25ae9SGregory Neil Shapiro 			    !emptyaddr(&e->e_from))
24406f25ae9SGregory Neil Shapiro 			{
245c2aa98e2SPeter Wemm 				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
246c2aa98e2SPeter Wemm 						  &e->e_errorqueue, 0, e);
24740266059SGregory Neil Shapiro 				done = true;
24806f25ae9SGregory Neil Shapiro 			}
249c2aa98e2SPeter Wemm 		}
25040266059SGregory Neil Shapiro 		else if ((bitset(QPINGONSUCCESS, q->q_flags) &&
25106f25ae9SGregory Neil Shapiro 			  ((QS_IS_SENT(q->q_state) &&
252c2aa98e2SPeter Wemm 			    bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
25340266059SGregory Neil Shapiro 			   bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) ||
25440266059SGregory Neil Shapiro 			  bitset(QBYTRACE, q->q_flags) ||
25540266059SGregory Neil Shapiro 			  bitset(QBYNRELAY, q->q_flags))
256c2aa98e2SPeter Wemm 		{
25740266059SGregory Neil Shapiro 			success_return = true;
258c2aa98e2SPeter Wemm 		}
259c2aa98e2SPeter Wemm 	}
260c2aa98e2SPeter Wemm 
261c2aa98e2SPeter Wemm 	if (e->e_class < 0)
262c2aa98e2SPeter Wemm 		e->e_flags |= EF_NO_BODY_RETN;
263c2aa98e2SPeter Wemm 
264c2aa98e2SPeter Wemm 	/*
265c2aa98e2SPeter Wemm 	**  See if the message timed out.
266c2aa98e2SPeter Wemm 	*/
267c2aa98e2SPeter Wemm 
268c2aa98e2SPeter Wemm 	if (!queueit)
26906f25ae9SGregory Neil Shapiro 		/* EMPTY */
270c2aa98e2SPeter Wemm 		/* nothing to do */ ;
27140266059SGregory Neil Shapiro 	else if (IS_MSG_ERR(msg_timeout))
272c2aa98e2SPeter Wemm 	{
273c2aa98e2SPeter Wemm 		if (failure_return)
274c2aa98e2SPeter Wemm 		{
27540266059SGregory Neil Shapiro 			if (msg_timeout == MSG_NOT_BY)
27640266059SGregory Neil Shapiro 			{
27740266059SGregory Neil Shapiro 				(void) sm_snprintf(buf, sizeof buf,
27840266059SGregory Neil Shapiro 					"delivery time expired %lds",
27940266059SGregory Neil Shapiro 					e->e_deliver_by);
28040266059SGregory Neil Shapiro 			}
28140266059SGregory Neil Shapiro 			else
28240266059SGregory Neil Shapiro 			{
28340266059SGregory Neil Shapiro 				(void) sm_snprintf(buf, sizeof buf,
28406f25ae9SGregory Neil Shapiro 					"Cannot send message for %s",
28540266059SGregory Neil Shapiro 					pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
28640266059SGregory Neil Shapiro 						false));
28740266059SGregory Neil Shapiro 			}
28840266059SGregory Neil Shapiro 
28940266059SGregory Neil Shapiro 			/* don't free, allocated from e_rpool */
29040266059SGregory Neil Shapiro 			e->e_message = sm_rpool_strdup_x(e->e_rpool, buf);
291c2aa98e2SPeter Wemm 			message(buf);
292c2aa98e2SPeter Wemm 			e->e_flags |= EF_CLRQUEUE;
293c2aa98e2SPeter Wemm 		}
29440266059SGregory Neil Shapiro 		if (msg_timeout == MSG_NOT_BY)
29540266059SGregory Neil Shapiro 		{
29640266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
29740266059SGregory Neil Shapiro 				"Delivery time (%lds) expired\n",
29840266059SGregory Neil Shapiro 				e->e_deliver_by);
29940266059SGregory Neil Shapiro 		}
30040266059SGregory Neil Shapiro 		else
30140266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30240266059SGregory Neil Shapiro 				"Message could not be delivered for %s\n",
30340266059SGregory Neil Shapiro 				pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
30440266059SGregory Neil Shapiro 					false));
30540266059SGregory Neil Shapiro 		(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30640266059SGregory Neil Shapiro 			"Message will be deleted from queue\n");
307c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
308c2aa98e2SPeter Wemm 		{
30906f25ae9SGregory Neil Shapiro 			if (QS_IS_UNDELIVERED(q->q_state))
310c2aa98e2SPeter Wemm 			{
31106f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
31240266059SGregory Neil Shapiro 				if (msg_timeout == MSG_NOT_BY)
31340266059SGregory Neil Shapiro 					q->q_status = "5.4.7";
31440266059SGregory Neil Shapiro 				else
315c2aa98e2SPeter Wemm 					q->q_status = "4.4.7";
316c2aa98e2SPeter Wemm 			}
317c2aa98e2SPeter Wemm 		}
318c2aa98e2SPeter Wemm 	}
31940266059SGregory Neil Shapiro 	else
32040266059SGregory Neil Shapiro 	{
32140266059SGregory Neil Shapiro 		if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
32240266059SGregory Neil Shapiro 		    now >= e->e_ctime +
32340266059SGregory Neil Shapiro 				TimeOuts.to_q_warning[e->e_timeoutclass])
32440266059SGregory Neil Shapiro 			msg_timeout = MSG_WARN;
32540266059SGregory Neil Shapiro 		else if (IS_DLVR_NOTIFY(e) &&
32640266059SGregory Neil Shapiro 			 e->e_deliver_by > 0 &&
32740266059SGregory Neil Shapiro 			 now >= e->e_ctime + e->e_deliver_by)
32840266059SGregory Neil Shapiro 			msg_timeout = MSG_WARN_BY;
32940266059SGregory Neil Shapiro 
33040266059SGregory Neil Shapiro 		if (IS_MSG_WARN(msg_timeout))
331c2aa98e2SPeter Wemm 		{
332c2aa98e2SPeter Wemm 			if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
333c2aa98e2SPeter Wemm 			    e->e_class >= 0 &&
334c2aa98e2SPeter Wemm 			    e->e_from.q_paddr != NULL &&
335c2aa98e2SPeter Wemm 			    strcmp(e->e_from.q_paddr, "<>") != 0 &&
33640266059SGregory Neil Shapiro 			    sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
33740266059SGregory Neil Shapiro 			    (strlen(e->e_from.q_paddr) <= 8 ||
33840266059SGregory Neil Shapiro 			     sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8],
33940266059SGregory Neil Shapiro 					   "-request") != 0))
340c2aa98e2SPeter Wemm 			{
34140266059SGregory Neil Shapiro 				for (q = e->e_sendqueue; q != NULL;
34240266059SGregory Neil Shapiro 				     q = q->q_next)
343c2aa98e2SPeter Wemm 				{
34440266059SGregory Neil Shapiro 					if (QS_IS_UNDELIVERED(q->q_state)
34506f25ae9SGregory Neil Shapiro #if _FFR_NODELAYDSN_ON_HOLD
34640266059SGregory Neil Shapiro 					    && !bitnset(M_HOLD,
34740266059SGregory Neil Shapiro 							q->q_mailer->m_flags)
34806f25ae9SGregory Neil Shapiro #endif /* _FFR_NODELAYDSN_ON_HOLD */
34940266059SGregory Neil Shapiro 					   )
35040266059SGregory Neil Shapiro 					{
35140266059SGregory Neil Shapiro 						if (msg_timeout ==
35240266059SGregory Neil Shapiro 						    MSG_WARN_BY &&
35340266059SGregory Neil Shapiro 						    (bitset(QPINGONDELAY,
35440266059SGregory Neil Shapiro 							    q->q_flags) ||
35540266059SGregory Neil Shapiro 						    !bitset(QHASNOTIFY,
35640266059SGregory Neil Shapiro 							    q->q_flags))
35740266059SGregory Neil Shapiro 						   )
35840266059SGregory Neil Shapiro 						{
35940266059SGregory Neil Shapiro 							q->q_flags |= QBYNDELAY;
36040266059SGregory Neil Shapiro 							delay_return = true;
36140266059SGregory Neil Shapiro 						}
36240266059SGregory Neil Shapiro 						if (bitset(QPINGONDELAY,
36340266059SGregory Neil Shapiro 							   q->q_flags))
364c2aa98e2SPeter Wemm 						{
365c2aa98e2SPeter Wemm 							q->q_flags |= QDELAYED;
36640266059SGregory Neil Shapiro 							delay_return = true;
36740266059SGregory Neil Shapiro 						}
368c2aa98e2SPeter Wemm 					}
369c2aa98e2SPeter Wemm 				}
370c2aa98e2SPeter Wemm 			}
371c2aa98e2SPeter Wemm 			if (delay_return)
372c2aa98e2SPeter Wemm 			{
37340266059SGregory Neil Shapiro 				if (msg_timeout == MSG_WARN_BY)
37440266059SGregory Neil Shapiro 				{
37540266059SGregory Neil Shapiro 					(void) sm_snprintf(buf, sizeof buf,
37640266059SGregory Neil Shapiro 						"Warning: Delivery time (%lds) exceeded",
37740266059SGregory Neil Shapiro 						e->e_deliver_by);
37840266059SGregory Neil Shapiro 				}
37940266059SGregory Neil Shapiro 				else
38040266059SGregory Neil Shapiro 					(void) sm_snprintf(buf, sizeof buf,
381c2aa98e2SPeter Wemm 						"Warning: could not send message for past %s",
38240266059SGregory Neil Shapiro 						pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
38340266059SGregory Neil Shapiro 							false));
38440266059SGregory Neil Shapiro 
38540266059SGregory Neil Shapiro 				/* don't free, allocated from e_rpool */
38640266059SGregory Neil Shapiro 				e->e_message = sm_rpool_strdup_x(e->e_rpool,
38740266059SGregory Neil Shapiro 								 buf);
388c2aa98e2SPeter Wemm 				message(buf);
389c2aa98e2SPeter Wemm 				e->e_flags |= EF_WARNING;
390c2aa98e2SPeter Wemm 			}
39140266059SGregory Neil Shapiro 			if (msg_timeout == MSG_WARN_BY)
39240266059SGregory Neil Shapiro 			{
39340266059SGregory Neil Shapiro 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
39440266059SGregory Neil Shapiro 					"Warning: Delivery time (%lds) exceeded\n",
39540266059SGregory Neil Shapiro 					e->e_deliver_by);
39640266059SGregory Neil Shapiro 			}
39740266059SGregory Neil Shapiro 			else
39840266059SGregory Neil Shapiro 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
399c2aa98e2SPeter Wemm 					"Warning: message still undelivered after %s\n",
40040266059SGregory Neil Shapiro 					pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
40140266059SGregory Neil Shapiro 					     false));
40240266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
40340266059SGregory Neil Shapiro 				      "Will keep trying until message is %s old\n",
40440266059SGregory Neil Shapiro 				      pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
40540266059SGregory Neil Shapiro 					     false));
40640266059SGregory Neil Shapiro 		}
407c2aa98e2SPeter Wemm 	}
408c2aa98e2SPeter Wemm 
409c2aa98e2SPeter Wemm 	if (tTd(50, 2))
41040266059SGregory Neil Shapiro 		sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
411c2aa98e2SPeter Wemm 			failure_return, delay_return, success_return, queueit);
412c2aa98e2SPeter Wemm 
413c2aa98e2SPeter Wemm 	/*
414c2aa98e2SPeter Wemm 	**  If we had some fatal error, but no addresses are marked as
415c2aa98e2SPeter Wemm 	**  bad, mark them _all_ as bad.
416c2aa98e2SPeter Wemm 	*/
417c2aa98e2SPeter Wemm 
418c2aa98e2SPeter Wemm 	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
419c2aa98e2SPeter Wemm 	{
420c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
421c2aa98e2SPeter Wemm 		{
42206f25ae9SGregory Neil Shapiro 			if ((QS_IS_OK(q->q_state) ||
42306f25ae9SGregory Neil Shapiro 			     QS_IS_VERIFIED(q->q_state)) &&
424c2aa98e2SPeter Wemm 			    bitset(QPINGONFAILURE, q->q_flags))
425c2aa98e2SPeter Wemm 			{
42640266059SGregory Neil Shapiro 				failure_return = true;
42706f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
428c2aa98e2SPeter Wemm 			}
429c2aa98e2SPeter Wemm 		}
430c2aa98e2SPeter Wemm 	}
431c2aa98e2SPeter Wemm 
432c2aa98e2SPeter Wemm 	/*
433c2aa98e2SPeter Wemm 	**  Send back return receipts as requested.
434c2aa98e2SPeter Wemm 	*/
435c2aa98e2SPeter Wemm 
436c2aa98e2SPeter Wemm 	if (success_return && !failure_return && !delay_return && fulldrop &&
437c2aa98e2SPeter Wemm 	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
438c2aa98e2SPeter Wemm 	    strcmp(e->e_from.q_paddr, "<>") != 0)
439c2aa98e2SPeter Wemm 	{
440c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
441c2aa98e2SPeter Wemm 
442c2aa98e2SPeter Wemm 		if (tTd(50, 8))
44340266059SGregory Neil Shapiro 			sm_dprintf("dropenvelope(%s): sending return receipt\n",
44406f25ae9SGregory Neil Shapiro 				id);
445c2aa98e2SPeter Wemm 		e->e_flags |= EF_SENDRECEIPT;
446c2aa98e2SPeter Wemm 		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
447c2aa98e2SPeter Wemm 		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
448c2aa98e2SPeter Wemm 	}
449c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_SENDRECEIPT;
450c2aa98e2SPeter Wemm 
451c2aa98e2SPeter Wemm 	/*
452c2aa98e2SPeter Wemm 	**  Arrange to send error messages if there are fatal errors.
453c2aa98e2SPeter Wemm 	*/
454c2aa98e2SPeter Wemm 
455c2aa98e2SPeter Wemm 	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
456c2aa98e2SPeter Wemm 	{
457c2aa98e2SPeter Wemm 		if (tTd(50, 8))
45840266059SGregory Neil Shapiro 			sm_dprintf("dropenvelope(%s): saving mail\n", id);
45940266059SGregory Neil Shapiro 		panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
460c2aa98e2SPeter Wemm 	}
461c2aa98e2SPeter Wemm 
462c2aa98e2SPeter Wemm 	/*
463c2aa98e2SPeter Wemm 	**  Arrange to send warning messages to postmaster as requested.
464c2aa98e2SPeter Wemm 	*/
465c2aa98e2SPeter Wemm 
46606f25ae9SGregory Neil Shapiro 	if ((failure_return || pmnotify) &&
467c2aa98e2SPeter Wemm 	    PostMasterCopy != NULL &&
46806f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags) &&
46906f25ae9SGregory Neil Shapiro 	    e->e_class >= 0)
470c2aa98e2SPeter Wemm 	{
471c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
47206f25ae9SGregory Neil Shapiro 		char pcopy[MAXNAME];
47306f25ae9SGregory Neil Shapiro 
47406f25ae9SGregory Neil Shapiro 		if (failure_return)
47506f25ae9SGregory Neil Shapiro 		{
47606f25ae9SGregory Neil Shapiro 			expand(PostMasterCopy, pcopy, sizeof pcopy, e);
477c2aa98e2SPeter Wemm 
478c2aa98e2SPeter Wemm 			if (tTd(50, 8))
47940266059SGregory Neil Shapiro 				sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
48006f25ae9SGregory Neil Shapiro 					id, pcopy);
48106f25ae9SGregory Neil Shapiro 			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
48206f25ae9SGregory Neil Shapiro 		}
48306f25ae9SGregory Neil Shapiro 		if (pmnotify)
48406f25ae9SGregory Neil Shapiro 			(void) sendtolist("postmaster", NULLADDR,
48506f25ae9SGregory Neil Shapiro 					  &rlist, 0, e);
48606f25ae9SGregory Neil Shapiro 		(void) returntosender(e->e_message, rlist,
48706f25ae9SGregory Neil Shapiro 				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
488c2aa98e2SPeter Wemm 	}
489c2aa98e2SPeter Wemm 
490c2aa98e2SPeter Wemm 	/*
491c2aa98e2SPeter Wemm 	**  Instantiate or deinstantiate the queue.
492c2aa98e2SPeter Wemm 	*/
493c2aa98e2SPeter Wemm 
494c2aa98e2SPeter Wemm simpledrop:
495c2aa98e2SPeter Wemm 	if (tTd(50, 8))
49640266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
497c2aa98e2SPeter Wemm 			id, queueit);
498c2aa98e2SPeter Wemm 	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
499c2aa98e2SPeter Wemm 	{
500c2aa98e2SPeter Wemm 		if (tTd(50, 1))
501c2aa98e2SPeter Wemm 		{
50240266059SGregory Neil Shapiro 			sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=",
503c2aa98e2SPeter Wemm 				e->e_id, queueit);
504c2aa98e2SPeter Wemm 			printenvflags(e);
505c2aa98e2SPeter Wemm 		}
50640266059SGregory Neil Shapiro 		if (!panic)
50740266059SGregory Neil Shapiro 			(void) xunlink(queuename(e, DATAFL_LETTER));
50840266059SGregory Neil Shapiro 		if (panic && QueueMode == QM_LOST)
50940266059SGregory Neil Shapiro 		{
51040266059SGregory Neil Shapiro 			/*
51140266059SGregory Neil Shapiro 			**  leave the Qf file behind as
51240266059SGregory Neil Shapiro 			**  the delivery attempt failed.
51340266059SGregory Neil Shapiro 			*/
51440266059SGregory Neil Shapiro 
51540266059SGregory Neil Shapiro 			/* EMPTY */
51640266059SGregory Neil Shapiro 		}
51740266059SGregory Neil Shapiro 		else
51840266059SGregory Neil Shapiro 		if (xunlink(queuename(e, ANYQFL_LETTER)) == 0)
51940266059SGregory Neil Shapiro 		{
52040266059SGregory Neil Shapiro 			/* add to available space in filesystem */
52113d88268SGregory Neil Shapiro 			updfs(e, -1, panic ? 0 : -1, "dropenvelope");
52240266059SGregory Neil Shapiro 		}
523c2aa98e2SPeter Wemm 
52406f25ae9SGregory Neil Shapiro 		if (e->e_ntries > 0 && LogLevel > 9)
52506f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
52640266059SGregory Neil Shapiro 				  pintvl(curtime() - e->e_ctime, true),
52706f25ae9SGregory Neil Shapiro 				  e->e_ntries);
528c2aa98e2SPeter Wemm 	}
529c2aa98e2SPeter Wemm 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
530c2aa98e2SPeter Wemm 	{
53140266059SGregory Neil Shapiro 		if (!split)
53240266059SGregory Neil Shapiro 			queueup(e, false, true);
53340266059SGregory Neil Shapiro 		else
53440266059SGregory Neil Shapiro 		{
53540266059SGregory Neil Shapiro 			ENVELOPE *oldsib;
53640266059SGregory Neil Shapiro 			ENVELOPE *ee;
53740266059SGregory Neil Shapiro 
53840266059SGregory Neil Shapiro 			/*
53940266059SGregory Neil Shapiro 			**  Save old sibling and set it to NULL to avoid
54040266059SGregory Neil Shapiro 			**  queueing up the same envelopes again.
54140266059SGregory Neil Shapiro 			**  This requires that envelopes in that list have
54240266059SGregory Neil Shapiro 			**  been take care of before (or at some other place).
54340266059SGregory Neil Shapiro 			*/
54440266059SGregory Neil Shapiro 
54540266059SGregory Neil Shapiro 			oldsib = e->e_sibling;
54640266059SGregory Neil Shapiro 			e->e_sibling = NULL;
54740266059SGregory Neil Shapiro 			if (!split_by_recipient(e) &&
54840266059SGregory Neil Shapiro 			    bitset(EF_FATALERRS, e->e_flags))
54940266059SGregory Neil Shapiro 			{
55040266059SGregory Neil Shapiro 				syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d",
55140266059SGregory Neil Shapiro 					e->e_id, queuename(e, DATAFL_LETTER),
55294c01205SGregory Neil Shapiro 					(int) geteuid());
55340266059SGregory Neil Shapiro 			}
55440266059SGregory Neil Shapiro 			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
55540266059SGregory Neil Shapiro 				queueup(ee, false, true);
55640266059SGregory Neil Shapiro 			queueup(e, false, true);
55740266059SGregory Neil Shapiro 
55840266059SGregory Neil Shapiro 			/* clean up */
55940266059SGregory Neil Shapiro 			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
56040266059SGregory Neil Shapiro 			{
56140266059SGregory Neil Shapiro 				/* now unlock the job */
56240266059SGregory Neil Shapiro 				if (tTd(50, 8))
56340266059SGregory Neil Shapiro 					sm_dprintf("dropenvelope(%s): unlocking job\n",
56440266059SGregory Neil Shapiro 						   ee->e_id);
56540266059SGregory Neil Shapiro 				closexscript(ee);
56640266059SGregory Neil Shapiro 				unlockqueue(ee);
56740266059SGregory Neil Shapiro 
56840266059SGregory Neil Shapiro 				/* this envelope is marked unused */
56940266059SGregory Neil Shapiro 				if (ee->e_dfp != NULL)
57040266059SGregory Neil Shapiro 				{
57140266059SGregory Neil Shapiro 					(void) sm_io_close(ee->e_dfp,
57240266059SGregory Neil Shapiro 							   SM_TIME_DEFAULT);
57340266059SGregory Neil Shapiro 					ee->e_dfp = NULL;
57440266059SGregory Neil Shapiro 				}
57540266059SGregory Neil Shapiro 				ee->e_id = NULL;
57640266059SGregory Neil Shapiro 				ee->e_flags &= ~EF_HAS_DF;
57740266059SGregory Neil Shapiro 			}
57840266059SGregory Neil Shapiro 			e->e_sibling = oldsib;
57940266059SGregory Neil Shapiro 		}
580c2aa98e2SPeter Wemm 	}
581c2aa98e2SPeter Wemm 
582c2aa98e2SPeter Wemm 	/* now unlock the job */
583c2aa98e2SPeter Wemm 	if (tTd(50, 8))
58440266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope(%s): unlocking job\n", id);
585c2aa98e2SPeter Wemm 	closexscript(e);
586c2aa98e2SPeter Wemm 	unlockqueue(e);
587c2aa98e2SPeter Wemm 
588c2aa98e2SPeter Wemm 	/* make sure that this envelope is marked unused */
589c2aa98e2SPeter Wemm 	if (e->e_dfp != NULL)
59040266059SGregory Neil Shapiro 	{
59140266059SGregory Neil Shapiro 		(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
592c2aa98e2SPeter Wemm 		e->e_dfp = NULL;
59340266059SGregory Neil Shapiro 	}
594c2aa98e2SPeter Wemm 	e->e_id = NULL;
595c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_HAS_DF;
596c2aa98e2SPeter Wemm }
59740266059SGregory Neil Shapiro /*
598c2aa98e2SPeter Wemm **  CLEARENVELOPE -- clear an envelope without unlocking
599c2aa98e2SPeter Wemm **
600c2aa98e2SPeter Wemm **	This is normally used by a child process to get a clean
601c2aa98e2SPeter Wemm **	envelope without disturbing the parent.
602c2aa98e2SPeter Wemm **
603c2aa98e2SPeter Wemm **	Parameters:
604c2aa98e2SPeter Wemm **		e -- the envelope to clear.
605c2aa98e2SPeter Wemm **		fullclear - if set, the current envelope is total
606c2aa98e2SPeter Wemm **			garbage and should be ignored; otherwise,
607c2aa98e2SPeter Wemm **			release any resources it may indicate.
60840266059SGregory Neil Shapiro **		rpool -- either NULL, or a pointer to a resource pool
60940266059SGregory Neil Shapiro **			from which envelope memory is allocated, and
61040266059SGregory Neil Shapiro **			to which envelope resources are attached.
611c2aa98e2SPeter Wemm **
612c2aa98e2SPeter Wemm **	Returns:
613c2aa98e2SPeter Wemm **		none.
614c2aa98e2SPeter Wemm **
615c2aa98e2SPeter Wemm **	Side Effects:
616c2aa98e2SPeter Wemm **		Closes files associated with the envelope.
617c2aa98e2SPeter Wemm **		Marks the envelope as unallocated.
618c2aa98e2SPeter Wemm */
619c2aa98e2SPeter Wemm 
620c2aa98e2SPeter Wemm void
62140266059SGregory Neil Shapiro clearenvelope(e, fullclear, rpool)
622c2aa98e2SPeter Wemm 	register ENVELOPE *e;
623c2aa98e2SPeter Wemm 	bool fullclear;
62440266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
625c2aa98e2SPeter Wemm {
626c2aa98e2SPeter Wemm 	register HDR *bh;
627c2aa98e2SPeter Wemm 	register HDR **nhp;
628c2aa98e2SPeter Wemm 	extern ENVELOPE BlankEnvelope;
62940266059SGregory Neil Shapiro 	char **p;
630c2aa98e2SPeter Wemm 
631c2aa98e2SPeter Wemm 	if (!fullclear)
632c2aa98e2SPeter Wemm 	{
633c2aa98e2SPeter Wemm 		/* clear out any file information */
634c2aa98e2SPeter Wemm 		if (e->e_xfp != NULL)
63540266059SGregory Neil Shapiro 			(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
636c2aa98e2SPeter Wemm 		if (e->e_dfp != NULL)
63740266059SGregory Neil Shapiro 			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
638c2aa98e2SPeter Wemm 		e->e_xfp = e->e_dfp = NULL;
639c2aa98e2SPeter Wemm 	}
640c2aa98e2SPeter Wemm 
64140266059SGregory Neil Shapiro 	/*
64240266059SGregory Neil Shapiro 	**  Copy BlankEnvelope into *e.
64340266059SGregory Neil Shapiro 	**  It is not safe to simply copy pointers to strings;
64440266059SGregory Neil Shapiro 	**  the strings themselves must be copied (or set to NULL).
64540266059SGregory Neil Shapiro 	**  The problem is that when we assign a new string value to
64640266059SGregory Neil Shapiro 	**  a member of BlankEnvelope, we free the old string.
64740266059SGregory Neil Shapiro 	**  We did not need to do this copying in sendmail 8.11 :-(
64840266059SGregory Neil Shapiro 	**  and it is a potential performance hit.  Reference counted
64940266059SGregory Neil Shapiro 	**  strings are one way out.
65040266059SGregory Neil Shapiro 	*/
65140266059SGregory Neil Shapiro 
65240266059SGregory Neil Shapiro 	*e = BlankEnvelope;
653c2aa98e2SPeter Wemm 	e->e_message = NULL;
65440266059SGregory Neil Shapiro 	e->e_qfletter = '\0';
65540266059SGregory Neil Shapiro 	e->e_quarmsg = NULL;
65640266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
65740266059SGregory Neil Shapiro 
65840266059SGregory Neil Shapiro 	/*
65940266059SGregory Neil Shapiro 	**  Copy the macro table.
66040266059SGregory Neil Shapiro 	**  We might be able to avoid this by zeroing the macro table
66140266059SGregory Neil Shapiro 	**  and always searching BlankEnvelope.e_macro after e->e_macro
66240266059SGregory Neil Shapiro 	**  in macvalue().
66340266059SGregory Neil Shapiro 	*/
66440266059SGregory Neil Shapiro 
66540266059SGregory Neil Shapiro 	for (p = &e->e_macro.mac_table[0];
66640266059SGregory Neil Shapiro 	     p <= &e->e_macro.mac_table[MAXMACROID];
66740266059SGregory Neil Shapiro 	     ++p)
66840266059SGregory Neil Shapiro 	{
66940266059SGregory Neil Shapiro 		if (*p != NULL)
67040266059SGregory Neil Shapiro 			*p = sm_rpool_strdup_x(rpool, *p);
67140266059SGregory Neil Shapiro 	}
67240266059SGregory Neil Shapiro 
67340266059SGregory Neil Shapiro 	/*
67440266059SGregory Neil Shapiro 	**  XXX There are many strings in the envelope structure
67540266059SGregory Neil Shapiro 	**  XXX that we are not attempting to copy here.
67640266059SGregory Neil Shapiro 	**  XXX Investigate this further.
67740266059SGregory Neil Shapiro 	*/
67840266059SGregory Neil Shapiro 
67940266059SGregory Neil Shapiro 	e->e_rpool = rpool;
68040266059SGregory Neil Shapiro 	e->e_macro.mac_rpool = rpool;
681c2aa98e2SPeter Wemm 	if (Verbose)
68206f25ae9SGregory Neil Shapiro 		set_delivery_mode(SM_DELIVER, e);
683c2aa98e2SPeter Wemm 	bh = BlankEnvelope.e_header;
684c2aa98e2SPeter Wemm 	nhp = &e->e_header;
685c2aa98e2SPeter Wemm 	while (bh != NULL)
686c2aa98e2SPeter Wemm 	{
68740266059SGregory Neil Shapiro 		*nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof *bh);
68806f25ae9SGregory Neil Shapiro 		memmove((char *) *nhp, (char *) bh, sizeof *bh);
689c2aa98e2SPeter Wemm 		bh = bh->h_link;
690c2aa98e2SPeter Wemm 		nhp = &(*nhp)->h_link;
691c2aa98e2SPeter Wemm 	}
692c2aa98e2SPeter Wemm }
69340266059SGregory Neil Shapiro /*
694c2aa98e2SPeter Wemm **  INITSYS -- initialize instantiation of system
695c2aa98e2SPeter Wemm **
696c2aa98e2SPeter Wemm **	In Daemon mode, this is done in the child.
697c2aa98e2SPeter Wemm **
698c2aa98e2SPeter Wemm **	Parameters:
69906f25ae9SGregory Neil Shapiro **		e -- the envelope to use.
700c2aa98e2SPeter Wemm **
701c2aa98e2SPeter Wemm **	Returns:
702c2aa98e2SPeter Wemm **		none.
703c2aa98e2SPeter Wemm **
704c2aa98e2SPeter Wemm **	Side Effects:
705c2aa98e2SPeter Wemm **		Initializes the system macros, some global variables,
706c2aa98e2SPeter Wemm **		etc.  In particular, the current time in various
707c2aa98e2SPeter Wemm **		forms is set.
708c2aa98e2SPeter Wemm */
709c2aa98e2SPeter Wemm 
710c2aa98e2SPeter Wemm void
711c2aa98e2SPeter Wemm initsys(e)
712c2aa98e2SPeter Wemm 	register ENVELOPE *e;
713c2aa98e2SPeter Wemm {
71440266059SGregory Neil Shapiro 	char buf[10];
715c2aa98e2SPeter Wemm #ifdef TTYNAME
716c2aa98e2SPeter Wemm 	static char ybuf[60];			/* holds tty id */
717c2aa98e2SPeter Wemm 	register char *p;
718c2aa98e2SPeter Wemm 	extern char *ttyname();
719c2aa98e2SPeter Wemm #endif /* TTYNAME */
720c2aa98e2SPeter Wemm 
721c2aa98e2SPeter Wemm 	/*
722c2aa98e2SPeter Wemm 	**  Give this envelope a reality.
723c2aa98e2SPeter Wemm 	**	I.e., an id, a transcript, and a creation time.
72440266059SGregory Neil Shapiro 	**  We don't select the queue until all of the recipients are known.
725c2aa98e2SPeter Wemm 	*/
726c2aa98e2SPeter Wemm 
727c2aa98e2SPeter Wemm 	openxscript(e);
728c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
72940266059SGregory Neil Shapiro 	e->e_qfletter = '\0';
730c2aa98e2SPeter Wemm 
731c2aa98e2SPeter Wemm 	/*
732c2aa98e2SPeter Wemm 	**  Set OutChannel to something useful if stdout isn't it.
733c2aa98e2SPeter Wemm 	**	This arranges that any extra stuff the mailer produces
734c2aa98e2SPeter Wemm 	**	gets sent back to the user on error (because it is
735c2aa98e2SPeter Wemm 	**	tucked away in the transcript).
736c2aa98e2SPeter Wemm 	*/
737c2aa98e2SPeter Wemm 
738c2aa98e2SPeter Wemm 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
739c2aa98e2SPeter Wemm 	    e->e_xfp != NULL)
740c2aa98e2SPeter Wemm 		OutChannel = e->e_xfp;
741c2aa98e2SPeter Wemm 
742c2aa98e2SPeter Wemm 	/*
743c2aa98e2SPeter Wemm 	**  Set up some basic system macros.
744c2aa98e2SPeter Wemm 	*/
745c2aa98e2SPeter Wemm 
746c2aa98e2SPeter Wemm 	/* process id */
74740266059SGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%d", (int) CurrentPid);
74840266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'p', buf);
749c2aa98e2SPeter Wemm 
750c2aa98e2SPeter Wemm 	/* hop count */
75140266059SGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount);
75240266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'c', buf);
753c2aa98e2SPeter Wemm 
754c2aa98e2SPeter Wemm 	/* time as integer, unix time, arpa time */
755c2aa98e2SPeter Wemm 	settime(e);
756c2aa98e2SPeter Wemm 
75706f25ae9SGregory Neil Shapiro 	/* Load average */
75840266059SGregory Neil Shapiro 	sm_getla();
75906f25ae9SGregory Neil Shapiro 
760c2aa98e2SPeter Wemm #ifdef TTYNAME
761c2aa98e2SPeter Wemm 	/* tty name */
762c2aa98e2SPeter Wemm 	if (macvalue('y', e) == NULL)
763c2aa98e2SPeter Wemm 	{
764c2aa98e2SPeter Wemm 		p = ttyname(2);
765c2aa98e2SPeter Wemm 		if (p != NULL)
766c2aa98e2SPeter Wemm 		{
767c2aa98e2SPeter Wemm 			if (strrchr(p, '/') != NULL)
768c2aa98e2SPeter Wemm 				p = strrchr(p, '/') + 1;
76940266059SGregory Neil Shapiro 			(void) sm_strlcpy(ybuf, sizeof ybuf, p);
77040266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM, 'y', ybuf);
771c2aa98e2SPeter Wemm 		}
772c2aa98e2SPeter Wemm 	}
773c2aa98e2SPeter Wemm #endif /* TTYNAME */
774c2aa98e2SPeter Wemm }
77540266059SGregory Neil Shapiro /*
776c2aa98e2SPeter Wemm **  SETTIME -- set the current time.
777c2aa98e2SPeter Wemm **
778c2aa98e2SPeter Wemm **	Parameters:
77906f25ae9SGregory Neil Shapiro **		e -- the envelope in which the macros should be set.
780c2aa98e2SPeter Wemm **
781c2aa98e2SPeter Wemm **	Returns:
782c2aa98e2SPeter Wemm **		none.
783c2aa98e2SPeter Wemm **
784c2aa98e2SPeter Wemm **	Side Effects:
785c2aa98e2SPeter Wemm **		Sets the various time macros -- $a, $b, $d, $t.
786c2aa98e2SPeter Wemm */
787c2aa98e2SPeter Wemm 
788c2aa98e2SPeter Wemm void
789c2aa98e2SPeter Wemm settime(e)
790c2aa98e2SPeter Wemm 	register ENVELOPE *e;
791c2aa98e2SPeter Wemm {
792c2aa98e2SPeter Wemm 	register char *p;
793c2aa98e2SPeter Wemm 	auto time_t now;
79440266059SGregory Neil Shapiro 	char buf[30];
795c2aa98e2SPeter Wemm 	register struct tm *tm;
796c2aa98e2SPeter Wemm 
797c2aa98e2SPeter Wemm 	now = curtime();
798e92d3f3fSGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%ld", (long) now);
799e92d3f3fSGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf);
800c2aa98e2SPeter Wemm 	tm = gmtime(&now);
80140266059SGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%04d%02d%02d%02d%02d",
80240266059SGregory Neil Shapiro 			   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
80340266059SGregory Neil Shapiro 			   tm->tm_hour, tm->tm_min);
80440266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 't', buf);
80540266059SGregory Neil Shapiro 	(void) sm_strlcpy(buf, ctime(&now), sizeof buf);
80640266059SGregory Neil Shapiro 	p = strchr(buf, '\n');
807c2aa98e2SPeter Wemm 	if (p != NULL)
808c2aa98e2SPeter Wemm 		*p = '\0';
80940266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'd', buf);
81040266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf));
811c2aa98e2SPeter Wemm 	if (macvalue('a', e) == NULL)
81240266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e));
813c2aa98e2SPeter Wemm }
81440266059SGregory Neil Shapiro /*
815c2aa98e2SPeter Wemm **  OPENXSCRIPT -- Open transcript file
816c2aa98e2SPeter Wemm **
817c2aa98e2SPeter Wemm **	Creates a transcript file for possible eventual mailing or
818c2aa98e2SPeter Wemm **	sending back.
819c2aa98e2SPeter Wemm **
820c2aa98e2SPeter Wemm **	Parameters:
821c2aa98e2SPeter Wemm **		e -- the envelope to create the transcript in/for.
822c2aa98e2SPeter Wemm **
823c2aa98e2SPeter Wemm **	Returns:
824c2aa98e2SPeter Wemm **		none
825c2aa98e2SPeter Wemm **
826c2aa98e2SPeter Wemm **	Side Effects:
827c2aa98e2SPeter Wemm **		Creates the transcript file.
828c2aa98e2SPeter Wemm */
829c2aa98e2SPeter Wemm 
830c2aa98e2SPeter Wemm #ifndef O_APPEND
831c2aa98e2SPeter Wemm # define O_APPEND	0
83206f25ae9SGregory Neil Shapiro #endif /* ! O_APPEND */
833c2aa98e2SPeter Wemm 
834c2aa98e2SPeter Wemm void
835c2aa98e2SPeter Wemm openxscript(e)
836c2aa98e2SPeter Wemm 	register ENVELOPE *e;
837c2aa98e2SPeter Wemm {
838c2aa98e2SPeter Wemm 	register char *p;
839c2aa98e2SPeter Wemm 
840c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
841c2aa98e2SPeter Wemm 		return;
84206f25ae9SGregory Neil Shapiro 
84306f25ae9SGregory Neil Shapiro #if 0
84406f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
84506f25ae9SGregory Neil Shapiro 		syserr("openxscript: job not locked");
84606f25ae9SGregory Neil Shapiro #endif /* 0 */
84706f25ae9SGregory Neil Shapiro 
84840266059SGregory Neil Shapiro 	p = queuename(e, XSCRPT_LETTER);
84906f25ae9SGregory Neil Shapiro 	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
85006f25ae9SGregory Neil Shapiro 			  SFF_NOTEXCL|SFF_OPENASROOT);
85106f25ae9SGregory Neil Shapiro 
85206f25ae9SGregory Neil Shapiro 	if (e->e_xfp == NULL)
853c2aa98e2SPeter Wemm 	{
854c2aa98e2SPeter Wemm 		syserr("Can't create transcript file %s", p);
85540266059SGregory Neil Shapiro 		e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
85640266059SGregory Neil Shapiro 				      SM_PATH_DEVNULL, SM_IO_RDWR, NULL);
85706f25ae9SGregory Neil Shapiro 		if (e->e_xfp == NULL)
85840266059SGregory Neil Shapiro 			syserr("!Can't open %s", SM_PATH_DEVNULL);
859c2aa98e2SPeter Wemm 	}
86040266059SGregory Neil Shapiro 	(void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0);
861c2aa98e2SPeter Wemm 	if (tTd(46, 9))
862c2aa98e2SPeter Wemm 	{
86340266059SGregory Neil Shapiro 		sm_dprintf("openxscript(%s):\n  ", p);
86440266059SGregory Neil Shapiro 		dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true,
86540266059SGregory Neil Shapiro 		       false);
866c2aa98e2SPeter Wemm 	}
867c2aa98e2SPeter Wemm }
86840266059SGregory Neil Shapiro /*
869c2aa98e2SPeter Wemm **  CLOSEXSCRIPT -- close the transcript file.
870c2aa98e2SPeter Wemm **
871c2aa98e2SPeter Wemm **	Parameters:
872c2aa98e2SPeter Wemm **		e -- the envelope containing the transcript to close.
873c2aa98e2SPeter Wemm **
874c2aa98e2SPeter Wemm **	Returns:
875c2aa98e2SPeter Wemm **		none.
876c2aa98e2SPeter Wemm **
877c2aa98e2SPeter Wemm **	Side Effects:
878c2aa98e2SPeter Wemm **		none.
879c2aa98e2SPeter Wemm */
880c2aa98e2SPeter Wemm 
881c2aa98e2SPeter Wemm void
882c2aa98e2SPeter Wemm closexscript(e)
883c2aa98e2SPeter Wemm 	register ENVELOPE *e;
884c2aa98e2SPeter Wemm {
885c2aa98e2SPeter Wemm 	if (e->e_xfp == NULL)
886c2aa98e2SPeter Wemm 		return;
88706f25ae9SGregory Neil Shapiro #if 0
88806f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL)
88906f25ae9SGregory Neil Shapiro 		syserr("closexscript: job not locked");
89006f25ae9SGregory Neil Shapiro #endif /* 0 */
89140266059SGregory Neil Shapiro 	(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
892c2aa98e2SPeter Wemm 	e->e_xfp = NULL;
893c2aa98e2SPeter Wemm }
89440266059SGregory Neil Shapiro /*
895c2aa98e2SPeter Wemm **  SETSENDER -- set the person who this message is from
896c2aa98e2SPeter Wemm **
897c2aa98e2SPeter Wemm **	Under certain circumstances allow the user to say who
898c2aa98e2SPeter Wemm **	s/he is (using -f or -r).  These are:
899c2aa98e2SPeter Wemm **	1.  The user's uid is zero (root).
900c2aa98e2SPeter Wemm **	2.  The user's login name is in an approved list (typically
901c2aa98e2SPeter Wemm **	    from a network server).
902c2aa98e2SPeter Wemm **	3.  The address the user is trying to claim has a
903c2aa98e2SPeter Wemm **	    "!" character in it (since #2 doesn't do it for
904c2aa98e2SPeter Wemm **	    us if we are dialing out for UUCP).
905c2aa98e2SPeter Wemm **	A better check to replace #3 would be if the
906c2aa98e2SPeter Wemm **	effective uid is "UUCP" -- this would require me
907c2aa98e2SPeter Wemm **	to rewrite getpwent to "grab" uucp as it went by,
908c2aa98e2SPeter Wemm **	make getname more nasty, do another passwd file
909c2aa98e2SPeter Wemm **	scan, or compile the UID of "UUCP" into the code,
910c2aa98e2SPeter Wemm **	all of which are reprehensible.
911c2aa98e2SPeter Wemm **
912c2aa98e2SPeter Wemm **	Assuming all of these fail, we figure out something
913c2aa98e2SPeter Wemm **	ourselves.
914c2aa98e2SPeter Wemm **
915c2aa98e2SPeter Wemm **	Parameters:
916c2aa98e2SPeter Wemm **		from -- the person we would like to believe this message
917c2aa98e2SPeter Wemm **			is from, as specified on the command line.
918c2aa98e2SPeter Wemm **		e -- the envelope in which we would like the sender set.
919c2aa98e2SPeter Wemm **		delimptr -- if non-NULL, set to the location of the
920c2aa98e2SPeter Wemm **			trailing delimiter.
921c2aa98e2SPeter Wemm **		delimchar -- the character that will delimit the sender
922c2aa98e2SPeter Wemm **			address.
923c2aa98e2SPeter Wemm **		internal -- set if this address is coming from an internal
924c2aa98e2SPeter Wemm **			source such as an owner alias.
925c2aa98e2SPeter Wemm **
926c2aa98e2SPeter Wemm **	Returns:
927c2aa98e2SPeter Wemm **		none.
928c2aa98e2SPeter Wemm **
929c2aa98e2SPeter Wemm **	Side Effects:
930c2aa98e2SPeter Wemm **		sets sendmail's notion of who the from person is.
931c2aa98e2SPeter Wemm */
932c2aa98e2SPeter Wemm 
933c2aa98e2SPeter Wemm void
934c2aa98e2SPeter Wemm setsender(from, e, delimptr, delimchar, internal)
935c2aa98e2SPeter Wemm 	char *from;
936c2aa98e2SPeter Wemm 	register ENVELOPE *e;
937c2aa98e2SPeter Wemm 	char **delimptr;
938c2aa98e2SPeter Wemm 	int delimchar;
939c2aa98e2SPeter Wemm 	bool internal;
940c2aa98e2SPeter Wemm {
941c2aa98e2SPeter Wemm 	register char **pvp;
942c2aa98e2SPeter Wemm 	char *realname = NULL;
943c2aa98e2SPeter Wemm 	char *bp;
944c2aa98e2SPeter Wemm 	char buf[MAXNAME + 2];
945c2aa98e2SPeter Wemm 	char pvpbuf[PSBUFSIZE];
946c2aa98e2SPeter Wemm 	extern char *FullName;
947c2aa98e2SPeter Wemm 
948c2aa98e2SPeter Wemm 	if (tTd(45, 1))
94940266059SGregory Neil Shapiro 		sm_dprintf("setsender(%s)\n", from == NULL ? "" : from);
950c2aa98e2SPeter Wemm 
95113bd1963SGregory Neil Shapiro 	/* may be set from earlier calls */
95213bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'x', "");
95313bd1963SGregory Neil Shapiro 
954c2aa98e2SPeter Wemm 	/*
955c2aa98e2SPeter Wemm 	**  Figure out the real user executing us.
956c2aa98e2SPeter Wemm 	**	Username can return errno != 0 on non-errors.
957c2aa98e2SPeter Wemm 	*/
958c2aa98e2SPeter Wemm 
959c2aa98e2SPeter Wemm 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
960c2aa98e2SPeter Wemm 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
961c2aa98e2SPeter Wemm 		realname = from;
962c2aa98e2SPeter Wemm 	if (realname == NULL || realname[0] == '\0')
963c2aa98e2SPeter Wemm 		realname = username();
964c2aa98e2SPeter Wemm 
965c2aa98e2SPeter Wemm 	if (ConfigLevel < 2)
96640266059SGregory Neil Shapiro 		SuprErrs = true;
967c2aa98e2SPeter Wemm 
96840266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
96940266059SGregory Neil Shapiro 
97006f25ae9SGregory Neil Shapiro 	/* preset state for then clause in case from == NULL */
97106f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_BADADDR;
97206f25ae9SGregory Neil Shapiro 	e->e_from.q_flags = 0;
973c2aa98e2SPeter Wemm 	if (from == NULL ||
974c2aa98e2SPeter Wemm 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
97540266059SGregory Neil Shapiro 		      delimchar, delimptr, e, false) == NULL ||
97606f25ae9SGregory Neil Shapiro 	    QS_IS_BADADDR(e->e_from.q_state) ||
977c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == ProgMailer ||
978c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == FileMailer ||
979c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == InclMailer)
980c2aa98e2SPeter Wemm 	{
981c2aa98e2SPeter Wemm 		/* log garbage addresses for traceback */
982c2aa98e2SPeter Wemm 		if (from != NULL && LogLevel > 2)
983c2aa98e2SPeter Wemm 		{
984c2aa98e2SPeter Wemm 			char *p;
985c2aa98e2SPeter Wemm 			char ebuf[MAXNAME * 2 + 2];
986c2aa98e2SPeter Wemm 
987c2aa98e2SPeter Wemm 			p = macvalue('_', e);
988c2aa98e2SPeter Wemm 			if (p == NULL)
989c2aa98e2SPeter Wemm 			{
990c2aa98e2SPeter Wemm 				char *host = RealHostName;
991c2aa98e2SPeter Wemm 
992c2aa98e2SPeter Wemm 				if (host == NULL)
993c2aa98e2SPeter Wemm 					host = MyHostName;
99440266059SGregory Neil Shapiro 				(void) sm_snprintf(ebuf, sizeof ebuf,
99540266059SGregory Neil Shapiro 						   "%.*s@%.*s", MAXNAME,
99640266059SGregory Neil Shapiro 						   realname, MAXNAME, host);
997c2aa98e2SPeter Wemm 				p = ebuf;
998c2aa98e2SPeter Wemm 			}
999c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
100006f25ae9SGregory Neil Shapiro 				  "setsender: %s: invalid or unparsable, received from %s",
1001c2aa98e2SPeter Wemm 				  shortenstring(from, 83), p);
1002c2aa98e2SPeter Wemm 		}
1003c2aa98e2SPeter Wemm 		if (from != NULL)
1004c2aa98e2SPeter Wemm 		{
100506f25ae9SGregory Neil Shapiro 			if (!QS_IS_BADADDR(e->e_from.q_state))
1006c2aa98e2SPeter Wemm 			{
1007c2aa98e2SPeter Wemm 				/* it was a bogus mailer in the from addr */
1008c2aa98e2SPeter Wemm 				e->e_status = "5.1.7";
100906f25ae9SGregory Neil Shapiro 				usrerrenh(e->e_status,
101006f25ae9SGregory Neil Shapiro 					  "553 Invalid sender address");
1011c2aa98e2SPeter Wemm 			}
101240266059SGregory Neil Shapiro 			SuprErrs = true;
1013c2aa98e2SPeter Wemm 		}
1014c2aa98e2SPeter Wemm 		if (from == realname ||
101540266059SGregory Neil Shapiro 		    parseaddr(from = realname,
101640266059SGregory Neil Shapiro 			      &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ',
101740266059SGregory Neil Shapiro 			      NULL, e, false) == NULL)
1018c2aa98e2SPeter Wemm 		{
1019c2aa98e2SPeter Wemm 			char nbuf[100];
1020c2aa98e2SPeter Wemm 
102140266059SGregory Neil Shapiro 			SuprErrs = true;
1022c2aa98e2SPeter Wemm 			expand("\201n", nbuf, sizeof nbuf, e);
102340266059SGregory Neil Shapiro 			from = sm_rpool_strdup_x(e->e_rpool, nbuf);
102440266059SGregory Neil Shapiro 			if (parseaddr(from, &e->e_from, RF_COPYALL, ' ',
102540266059SGregory Neil Shapiro 				      NULL, e, false) == NULL &&
1026c2aa98e2SPeter Wemm 			    parseaddr(from = "postmaster", &e->e_from,
102740266059SGregory Neil Shapiro 				      RF_COPYALL, ' ', NULL, e, false) == NULL)
102806f25ae9SGregory Neil Shapiro 				syserr("553 5.3.0 setsender: can't even parse postmaster!");
1029c2aa98e2SPeter Wemm 		}
1030c2aa98e2SPeter Wemm 	}
1031c2aa98e2SPeter Wemm 	else
103240266059SGregory Neil Shapiro 		FromFlag = true;
103306f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_SENDER;
1034c2aa98e2SPeter Wemm 	if (tTd(45, 5))
1035c2aa98e2SPeter Wemm 	{
103640266059SGregory Neil Shapiro 		sm_dprintf("setsender: QS_SENDER ");
1037e92d3f3fSGregory Neil Shapiro 		printaddr(sm_debug_file(), &e->e_from, false);
1038c2aa98e2SPeter Wemm 	}
103940266059SGregory Neil Shapiro 	SuprErrs = false;
1040c2aa98e2SPeter Wemm 
1041c2aa98e2SPeter Wemm #if USERDB
1042c2aa98e2SPeter Wemm 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
1043c2aa98e2SPeter Wemm 	{
1044c2aa98e2SPeter Wemm 		register char *p;
1045c2aa98e2SPeter Wemm 
104640266059SGregory Neil Shapiro 		p = udbsender(e->e_from.q_user, e->e_rpool);
1047c2aa98e2SPeter Wemm 		if (p != NULL)
1048c2aa98e2SPeter Wemm 			from = p;
1049c2aa98e2SPeter Wemm 	}
1050c2aa98e2SPeter Wemm #endif /* USERDB */
1051c2aa98e2SPeter Wemm 
1052c2aa98e2SPeter Wemm 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
1053c2aa98e2SPeter Wemm 	{
105440266059SGregory Neil Shapiro 		SM_MBDB_T user;
105540266059SGregory Neil Shapiro 
1056c2aa98e2SPeter Wemm 		if (!internal)
1057c2aa98e2SPeter Wemm 		{
1058c2aa98e2SPeter Wemm 			/* if the user already given fullname don't redefine */
1059c2aa98e2SPeter Wemm 			if (FullName == NULL)
1060c2aa98e2SPeter Wemm 				FullName = macvalue('x', e);
1061605302a5SGregory Neil Shapiro 			if (FullName != NULL)
1062605302a5SGregory Neil Shapiro 			{
1063605302a5SGregory Neil Shapiro 				if (FullName[0] == '\0')
1064c2aa98e2SPeter Wemm 					FullName = NULL;
1065605302a5SGregory Neil Shapiro 				else
1066605302a5SGregory Neil Shapiro 					FullName = newstr(FullName);
1067605302a5SGregory Neil Shapiro 			}
1068c2aa98e2SPeter Wemm 		}
1069c2aa98e2SPeter Wemm 
1070c2aa98e2SPeter Wemm 		if (e->e_from.q_user[0] != '\0' &&
107140266059SGregory Neil Shapiro 		    sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK)
1072c2aa98e2SPeter Wemm 		{
1073c2aa98e2SPeter Wemm 			/*
1074c2aa98e2SPeter Wemm 			**  Process passwd file entry.
1075c2aa98e2SPeter Wemm 			*/
1076c2aa98e2SPeter Wemm 
1077c2aa98e2SPeter Wemm 			/* extract home directory */
107840266059SGregory Neil Shapiro 			if (*user.mbdb_homedir == '\0')
107942e5d165SGregory Neil Shapiro 				e->e_from.q_home = NULL;
108040266059SGregory Neil Shapiro 			else if (strcmp(user.mbdb_homedir, "/") == 0)
108140266059SGregory Neil Shapiro 				e->e_from.q_home = "";
1082c2aa98e2SPeter Wemm 			else
108340266059SGregory Neil Shapiro 				e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool,
108440266059SGregory Neil Shapiro 							user.mbdb_homedir);
108540266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home);
1086c2aa98e2SPeter Wemm 
1087c2aa98e2SPeter Wemm 			/* extract user and group id */
108840266059SGregory Neil Shapiro 			if (user.mbdb_uid != SM_NO_UID)
108940266059SGregory Neil Shapiro 			{
109040266059SGregory Neil Shapiro 				e->e_from.q_uid = user.mbdb_uid;
109140266059SGregory Neil Shapiro 				e->e_from.q_gid = user.mbdb_gid;
1092c2aa98e2SPeter Wemm 				e->e_from.q_flags |= QGOODUID;
109340266059SGregory Neil Shapiro 			}
1094c2aa98e2SPeter Wemm 
1095c2aa98e2SPeter Wemm 			/* extract full name from passwd file */
109640266059SGregory Neil Shapiro 			if (FullName == NULL && !internal &&
109740266059SGregory Neil Shapiro 			    user.mbdb_fullname[0] != '\0' &&
109840266059SGregory Neil Shapiro 			    strcmp(user.mbdb_name, e->e_from.q_user) == 0)
1099c2aa98e2SPeter Wemm 			{
110040266059SGregory Neil Shapiro 				FullName = newstr(user.mbdb_fullname);
1101c2aa98e2SPeter Wemm 			}
1102c2aa98e2SPeter Wemm 		}
1103c2aa98e2SPeter Wemm 		else
1104c2aa98e2SPeter Wemm 		{
110506f25ae9SGregory Neil Shapiro 			e->e_from.q_home = NULL;
1106c2aa98e2SPeter Wemm 		}
1107c2aa98e2SPeter Wemm 		if (FullName != NULL && !internal)
110813bd1963SGregory Neil Shapiro 			macdefine(&e->e_macro, A_TEMP, 'x', FullName);
1109c2aa98e2SPeter Wemm 	}
11102e43090eSPeter Wemm 	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
1111c2aa98e2SPeter Wemm 	{
1112c2aa98e2SPeter Wemm 		if (e->e_from.q_home == NULL)
1113c2aa98e2SPeter Wemm 		{
1114c2aa98e2SPeter Wemm 			e->e_from.q_home = getenv("HOME");
111542e5d165SGregory Neil Shapiro 			if (e->e_from.q_home != NULL)
111642e5d165SGregory Neil Shapiro 			{
111742e5d165SGregory Neil Shapiro 				if (*e->e_from.q_home == '\0')
111842e5d165SGregory Neil Shapiro 					e->e_from.q_home = NULL;
111942e5d165SGregory Neil Shapiro 				else if (strcmp(e->e_from.q_home, "/") == 0)
1120c2aa98e2SPeter Wemm 					e->e_from.q_home++;
1121c2aa98e2SPeter Wemm 			}
112242e5d165SGregory Neil Shapiro 		}
1123c2aa98e2SPeter Wemm 		e->e_from.q_uid = RealUid;
1124c2aa98e2SPeter Wemm 		e->e_from.q_gid = RealGid;
1125c2aa98e2SPeter Wemm 		e->e_from.q_flags |= QGOODUID;
1126c2aa98e2SPeter Wemm 	}
1127c2aa98e2SPeter Wemm 
1128c2aa98e2SPeter Wemm 	/*
1129c2aa98e2SPeter Wemm 	**  Rewrite the from person to dispose of possible implicit
1130c2aa98e2SPeter Wemm 	**	links in the net.
1131c2aa98e2SPeter Wemm 	*/
1132c2aa98e2SPeter Wemm 
1133e92d3f3fSGregory Neil Shapiro 	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL, false);
1134c2aa98e2SPeter Wemm 	if (pvp == NULL)
1135c2aa98e2SPeter Wemm 	{
1136c2aa98e2SPeter Wemm 		/* don't need to give error -- prescan did that already */
1137c2aa98e2SPeter Wemm 		if (LogLevel > 2)
1138c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
1139c2aa98e2SPeter Wemm 				  "cannot prescan from (%s)",
1140c2aa98e2SPeter Wemm 				  shortenstring(from, MAXSHORTSTR));
114140266059SGregory Neil Shapiro 		finis(true, true, ExitStat);
1142c2aa98e2SPeter Wemm 	}
114340266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 3, e);
114440266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 1, e);
114540266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 4, e);
114640266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
1147c2aa98e2SPeter Wemm 	bp = buf + 1;
1148c2aa98e2SPeter Wemm 	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
1149c2aa98e2SPeter Wemm 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
1150c2aa98e2SPeter Wemm 	{
1151c2aa98e2SPeter Wemm 		/* heuristic: route-addr: add angle brackets */
115240266059SGregory Neil Shapiro 		(void) sm_strlcat(bp, ">", sizeof buf - 1);
1153c2aa98e2SPeter Wemm 		*--bp = '<';
1154c2aa98e2SPeter Wemm 	}
115540266059SGregory Neil Shapiro 	e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp);
115640266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
1157c2aa98e2SPeter Wemm 
1158c2aa98e2SPeter Wemm 	/* save the domain spec if this mailer wants it */
1159c2aa98e2SPeter Wemm 	if (e->e_from.q_mailer != NULL &&
1160c2aa98e2SPeter Wemm 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
1161c2aa98e2SPeter Wemm 	{
1162c2aa98e2SPeter Wemm 		char **lastat;
1163c2aa98e2SPeter Wemm 
1164c2aa98e2SPeter Wemm 		/* get rid of any pesky angle brackets */
116540266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
116640266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 3, e);
116740266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 1, e);
116840266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 4, e);
116940266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
1170c2aa98e2SPeter Wemm 
1171c2aa98e2SPeter Wemm 		/* strip off to the last "@" sign */
1172c2aa98e2SPeter Wemm 		for (lastat = NULL; *pvp != NULL; pvp++)
1173e92d3f3fSGregory Neil Shapiro 		{
1174c2aa98e2SPeter Wemm 			if (strcmp(*pvp, "@") == 0)
1175c2aa98e2SPeter Wemm 				lastat = pvp;
1176e92d3f3fSGregory Neil Shapiro 		}
1177c2aa98e2SPeter Wemm 		if (lastat != NULL)
1178c2aa98e2SPeter Wemm 		{
117940266059SGregory Neil Shapiro 			e->e_fromdomain = copyplist(lastat, true, e->e_rpool);
1180c2aa98e2SPeter Wemm 			if (tTd(45, 3))
1181c2aa98e2SPeter Wemm 			{
118240266059SGregory Neil Shapiro 				sm_dprintf("Saving from domain: ");
1183e92d3f3fSGregory Neil Shapiro 				printav(sm_debug_file(), e->e_fromdomain);
1184c2aa98e2SPeter Wemm 			}
1185c2aa98e2SPeter Wemm 		}
1186c2aa98e2SPeter Wemm 	}
1187c2aa98e2SPeter Wemm }
118840266059SGregory Neil Shapiro /*
1189c2aa98e2SPeter Wemm **  PRINTENVFLAGS -- print envelope flags for debugging
1190c2aa98e2SPeter Wemm **
1191c2aa98e2SPeter Wemm **	Parameters:
1192c2aa98e2SPeter Wemm **		e -- the envelope with the flags to be printed.
1193c2aa98e2SPeter Wemm **
1194c2aa98e2SPeter Wemm **	Returns:
1195c2aa98e2SPeter Wemm **		none.
1196c2aa98e2SPeter Wemm */
1197c2aa98e2SPeter Wemm 
1198c2aa98e2SPeter Wemm struct eflags
1199c2aa98e2SPeter Wemm {
1200c2aa98e2SPeter Wemm 	char		*ef_name;
120140266059SGregory Neil Shapiro 	unsigned long	ef_bit;
1202c2aa98e2SPeter Wemm };
1203c2aa98e2SPeter Wemm 
120406f25ae9SGregory Neil Shapiro static struct eflags	EnvelopeFlags[] =
1205c2aa98e2SPeter Wemm {
1206c2aa98e2SPeter Wemm 	{ "OLDSTYLE",		EF_OLDSTYLE	},
1207c2aa98e2SPeter Wemm 	{ "INQUEUE",		EF_INQUEUE	},
1208c2aa98e2SPeter Wemm 	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
1209c2aa98e2SPeter Wemm 	{ "CLRQUEUE",		EF_CLRQUEUE	},
1210c2aa98e2SPeter Wemm 	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
1211c2aa98e2SPeter Wemm 	{ "FATALERRS",		EF_FATALERRS	},
1212c2aa98e2SPeter Wemm 	{ "DELETE_BCC",		EF_DELETE_BCC	},
1213c2aa98e2SPeter Wemm 	{ "RESPONSE",		EF_RESPONSE	},
1214c2aa98e2SPeter Wemm 	{ "RESENT",		EF_RESENT	},
1215c2aa98e2SPeter Wemm 	{ "VRFYONLY",		EF_VRFYONLY	},
1216c2aa98e2SPeter Wemm 	{ "WARNING",		EF_WARNING	},
1217c2aa98e2SPeter Wemm 	{ "QUEUERUN",		EF_QUEUERUN	},
1218c2aa98e2SPeter Wemm 	{ "GLOBALERRS",		EF_GLOBALERRS	},
1219c2aa98e2SPeter Wemm 	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
1220c2aa98e2SPeter Wemm 	{ "METOO",		EF_METOO	},
1221c2aa98e2SPeter Wemm 	{ "LOGSENDER",		EF_LOGSENDER	},
1222c2aa98e2SPeter Wemm 	{ "NORECEIPT",		EF_NORECEIPT	},
1223c2aa98e2SPeter Wemm 	{ "HAS8BIT",		EF_HAS8BIT	},
1224c2aa98e2SPeter Wemm 	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
1225c2aa98e2SPeter Wemm 	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
1226c2aa98e2SPeter Wemm 	{ "RET_PARAM",		EF_RET_PARAM	},
1227c2aa98e2SPeter Wemm 	{ "HAS_DF",		EF_HAS_DF	},
1228c2aa98e2SPeter Wemm 	{ "IS_MIME",		EF_IS_MIME	},
1229c2aa98e2SPeter Wemm 	{ "DONT_MIME",		EF_DONT_MIME	},
123040266059SGregory Neil Shapiro 	{ "DISCARD",		EF_DISCARD	},
123140266059SGregory Neil Shapiro 	{ "TOOBIG",		EF_TOOBIG	},
123240266059SGregory Neil Shapiro 	{ "SPLIT",		EF_SPLIT	},
123340266059SGregory Neil Shapiro 	{ "UNSAFE",		EF_UNSAFE	},
1234193538b7SGregory Neil Shapiro 	{ NULL,			0		}
1235c2aa98e2SPeter Wemm };
1236c2aa98e2SPeter Wemm 
1237c2aa98e2SPeter Wemm void
1238c2aa98e2SPeter Wemm printenvflags(e)
1239c2aa98e2SPeter Wemm 	register ENVELOPE *e;
1240c2aa98e2SPeter Wemm {
1241c2aa98e2SPeter Wemm 	register struct eflags *ef;
124240266059SGregory Neil Shapiro 	bool first = true;
1243c2aa98e2SPeter Wemm 
1244e92d3f3fSGregory Neil Shapiro 	sm_dprintf("%lx", e->e_flags);
1245c2aa98e2SPeter Wemm 	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
1246c2aa98e2SPeter Wemm 	{
1247c2aa98e2SPeter Wemm 		if (!bitset(ef->ef_bit, e->e_flags))
1248c2aa98e2SPeter Wemm 			continue;
1249c2aa98e2SPeter Wemm 		if (first)
1250e92d3f3fSGregory Neil Shapiro 			sm_dprintf("<%s", ef->ef_name);
1251c2aa98e2SPeter Wemm 		else
1252e92d3f3fSGregory Neil Shapiro 			sm_dprintf(",%s", ef->ef_name);
125340266059SGregory Neil Shapiro 		first = false;
1254c2aa98e2SPeter Wemm 	}
1255c2aa98e2SPeter Wemm 	if (!first)
1256e92d3f3fSGregory Neil Shapiro 		sm_dprintf(">\n");
1257c2aa98e2SPeter Wemm }
1258