xref: /freebsd/contrib/sendmail/src/envelope.c (revision 13bd19636bde9fea5821698cb77c32edee6a9ac9)
1c2aa98e2SPeter Wemm /*
2605302a5SGregory Neil Shapiro  * Copyright (c) 1998-2002 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 
1613bd1963SGregory Neil Shapiro SM_RCSID("@(#)$Id: envelope.c,v 8.282.2.2 2002/12/04 15:44:08 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 _FFR_QUARANTINE
10540266059SGregory Neil Shapiro 		if (parent->e_quarmsg == NULL)
10640266059SGregory Neil Shapiro 		{
10740266059SGregory Neil Shapiro 			e->e_quarmsg = NULL;
10840266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM,
10940266059SGregory Neil Shapiro 				  macid("{quarantine}"), "");
11040266059SGregory Neil Shapiro 		}
11140266059SGregory Neil Shapiro 		else
11240266059SGregory Neil Shapiro 		{
11340266059SGregory Neil Shapiro 			e->e_quarmsg = sm_rpool_strdup_x(rpool,
11440266059SGregory Neil Shapiro 							 parent->e_quarmsg);
11540266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM,
11640266059SGregory Neil Shapiro 				  macid("{quarantine}"), e->e_quarmsg);
11740266059SGregory Neil Shapiro 		}
11840266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */
11940266059SGregory Neil Shapiro 	}
120c2aa98e2SPeter Wemm 	e->e_puthdr = putheader;
121c2aa98e2SPeter Wemm 	e->e_putbody = putbody;
122c2aa98e2SPeter Wemm 	if (CurEnv->e_xfp != NULL)
12340266059SGregory Neil Shapiro 		(void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT);
124c2aa98e2SPeter Wemm 
12506f25ae9SGregory Neil Shapiro 	return e;
126c2aa98e2SPeter Wemm }
12740266059SGregory Neil Shapiro 
12840266059SGregory Neil Shapiro /* values for msg_timeout, see also IS_* below for usage (bit layout) */
12940266059SGregory Neil Shapiro #define MSG_T_O		0x01	/* normal timeout */
13040266059SGregory Neil Shapiro #define MSG_T_O_NOW	0x02	/* NOW timeout */
13140266059SGregory Neil Shapiro #define MSG_NOT_BY	0x04	/* Deliver-By time exceeded, mode R */
13240266059SGregory Neil Shapiro #define MSG_WARN	0x10	/* normal queue warning */
13340266059SGregory Neil Shapiro #define MSG_WARN_BY	0x20	/* Deliver-By time exceeded, mode N */
13440266059SGregory Neil Shapiro 
13540266059SGregory Neil Shapiro #define IS_MSG_ERR(x)	(((x) & 0x0f) != 0)	/* return an error */
13640266059SGregory Neil Shapiro 
13740266059SGregory Neil Shapiro /* immediate return */
13840266059SGregory Neil Shapiro #define IS_IMM_RET(x)	(((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0)
13940266059SGregory Neil Shapiro #define IS_MSG_WARN(x)	(((x) & 0xf0) != 0)	/* return a warning */
14040266059SGregory Neil Shapiro 
14140266059SGregory Neil Shapiro /*
142c2aa98e2SPeter Wemm **  DROPENVELOPE -- deallocate an envelope.
143c2aa98e2SPeter Wemm **
144c2aa98e2SPeter Wemm **	Parameters:
145c2aa98e2SPeter Wemm **		e -- the envelope to deallocate.
146c2aa98e2SPeter Wemm **		fulldrop -- if set, do return receipts.
14740266059SGregory Neil Shapiro **		split -- if true, split by recipient if message is queued up
148c2aa98e2SPeter Wemm **
149c2aa98e2SPeter Wemm **	Returns:
150c2aa98e2SPeter Wemm **		none.
151c2aa98e2SPeter Wemm **
152c2aa98e2SPeter Wemm **	Side Effects:
153c2aa98e2SPeter Wemm **		housekeeping necessary to dispose of an envelope.
154c2aa98e2SPeter Wemm **		Unlocks this queue file.
155c2aa98e2SPeter Wemm */
156c2aa98e2SPeter Wemm 
157c2aa98e2SPeter Wemm void
15840266059SGregory Neil Shapiro dropenvelope(e, fulldrop, split)
159c2aa98e2SPeter Wemm 	register ENVELOPE *e;
160c2aa98e2SPeter Wemm 	bool fulldrop;
16140266059SGregory Neil Shapiro 	bool split;
162c2aa98e2SPeter Wemm {
16340266059SGregory Neil Shapiro 	bool panic = false;
16440266059SGregory Neil Shapiro 	bool queueit = false;
16540266059SGregory Neil Shapiro 	int msg_timeout = 0;
16640266059SGregory Neil Shapiro 	bool failure_return = false;
16740266059SGregory Neil Shapiro 	bool delay_return = false;
16840266059SGregory Neil Shapiro 	bool success_return = false;
16906f25ae9SGregory Neil Shapiro 	bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags);
17040266059SGregory Neil Shapiro 	bool done = false;
171c2aa98e2SPeter Wemm 	register ADDRESS *q;
172c2aa98e2SPeter Wemm 	char *id = e->e_id;
173193538b7SGregory Neil Shapiro 	time_t now;
174c2aa98e2SPeter Wemm 	char buf[MAXLINE];
175c2aa98e2SPeter Wemm 
176c2aa98e2SPeter Wemm 	if (tTd(50, 1))
177c2aa98e2SPeter Wemm 	{
17840266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope %p: id=", e);
179c2aa98e2SPeter Wemm 		xputs(e->e_id);
18040266059SGregory Neil Shapiro 		sm_dprintf(", flags=");
181c2aa98e2SPeter Wemm 		printenvflags(e);
182c2aa98e2SPeter Wemm 		if (tTd(50, 10))
183c2aa98e2SPeter Wemm 		{
18440266059SGregory Neil Shapiro 			sm_dprintf("sendq=");
18540266059SGregory Neil Shapiro 			printaddr(e->e_sendqueue, true);
186c2aa98e2SPeter Wemm 		}
187c2aa98e2SPeter Wemm 	}
188c2aa98e2SPeter Wemm 
189c2aa98e2SPeter Wemm 	if (LogLevel > 84)
190c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, id,
19106f25ae9SGregory Neil Shapiro 			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
19240266059SGregory Neil Shapiro 			  e->e_flags, OpMode, (int) CurrentPid);
193c2aa98e2SPeter Wemm 
194c2aa98e2SPeter Wemm 	/* we must have an id to remove disk files */
195c2aa98e2SPeter Wemm 	if (id == NULL)
196c2aa98e2SPeter Wemm 		return;
197c2aa98e2SPeter Wemm 
198c2aa98e2SPeter Wemm 	/* if verify-only mode, we can skip most of this */
199c2aa98e2SPeter Wemm 	if (OpMode == MD_VERIFY)
200c2aa98e2SPeter Wemm 		goto simpledrop;
201c2aa98e2SPeter Wemm 
202c2aa98e2SPeter Wemm 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
203c2aa98e2SPeter Wemm 		logsender(e, NULL);
204c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_LOGSENDER;
205c2aa98e2SPeter Wemm 
206c2aa98e2SPeter Wemm 	/* post statistics */
207c2aa98e2SPeter Wemm 	poststats(StatFile);
208c2aa98e2SPeter Wemm 
209c2aa98e2SPeter Wemm 	/*
210c2aa98e2SPeter Wemm 	**  Extract state information from dregs of send list.
211c2aa98e2SPeter Wemm 	*/
212c2aa98e2SPeter Wemm 
213193538b7SGregory Neil Shapiro 	now = curtime();
2148774250cSGregory Neil Shapiro 	if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
21540266059SGregory Neil Shapiro 		msg_timeout = MSG_T_O;
21640266059SGregory Neil Shapiro 	if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 &&
21740266059SGregory Neil Shapiro 	    now >= e->e_ctime + e->e_deliver_by &&
21806f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags))
21906f25ae9SGregory Neil Shapiro 	{
22040266059SGregory Neil Shapiro 		msg_timeout = MSG_NOT_BY;
22140266059SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22240266059SGregory Neil Shapiro 	}
22340266059SGregory Neil Shapiro 	else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
22440266059SGregory Neil Shapiro 		 !bitset(EF_RESPONSE, e->e_flags))
22540266059SGregory Neil Shapiro 	{
22640266059SGregory Neil Shapiro 		msg_timeout = MSG_T_O_NOW;
22706f25ae9SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22806f25ae9SGregory Neil Shapiro 	}
22906f25ae9SGregory Neil Shapiro 
230c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_QUEUERUN;
231c2aa98e2SPeter Wemm 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
232c2aa98e2SPeter Wemm 	{
23306f25ae9SGregory Neil Shapiro 		if (QS_IS_UNDELIVERED(q->q_state))
23440266059SGregory Neil Shapiro 			queueit = true;
235c2aa98e2SPeter Wemm 
236c2aa98e2SPeter Wemm 		/* see if a notification is needed */
237c2aa98e2SPeter Wemm 		if (bitset(QPINGONFAILURE, q->q_flags) &&
23840266059SGregory Neil Shapiro 		    ((IS_MSG_ERR(msg_timeout) &&
23940266059SGregory Neil Shapiro 		      QS_IS_UNDELIVERED(q->q_state)) ||
24006f25ae9SGregory Neil Shapiro 		     QS_IS_BADADDR(q->q_state) ||
24140266059SGregory Neil Shapiro 		     IS_IMM_RET(msg_timeout)))
242c2aa98e2SPeter Wemm 		{
24340266059SGregory Neil Shapiro 			failure_return = true;
24406f25ae9SGregory Neil Shapiro 			if (!done && q->q_owner == NULL &&
24506f25ae9SGregory Neil Shapiro 			    !emptyaddr(&e->e_from))
24606f25ae9SGregory Neil Shapiro 			{
247c2aa98e2SPeter Wemm 				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
248c2aa98e2SPeter Wemm 						  &e->e_errorqueue, 0, e);
24940266059SGregory Neil Shapiro 				done = true;
25006f25ae9SGregory Neil Shapiro 			}
251c2aa98e2SPeter Wemm 		}
25240266059SGregory Neil Shapiro 		else if ((bitset(QPINGONSUCCESS, q->q_flags) &&
25306f25ae9SGregory Neil Shapiro 			  ((QS_IS_SENT(q->q_state) &&
254c2aa98e2SPeter Wemm 			    bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
25540266059SGregory Neil Shapiro 			   bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) ||
25640266059SGregory Neil Shapiro 			  bitset(QBYTRACE, q->q_flags) ||
25740266059SGregory Neil Shapiro 			  bitset(QBYNRELAY, q->q_flags))
258c2aa98e2SPeter Wemm 		{
25940266059SGregory Neil Shapiro 			success_return = true;
260c2aa98e2SPeter Wemm 		}
261c2aa98e2SPeter Wemm 	}
262c2aa98e2SPeter Wemm 
263c2aa98e2SPeter Wemm 	if (e->e_class < 0)
264c2aa98e2SPeter Wemm 		e->e_flags |= EF_NO_BODY_RETN;
265c2aa98e2SPeter Wemm 
266c2aa98e2SPeter Wemm 	/*
267c2aa98e2SPeter Wemm 	**  See if the message timed out.
268c2aa98e2SPeter Wemm 	*/
269c2aa98e2SPeter Wemm 
270c2aa98e2SPeter Wemm 	if (!queueit)
27106f25ae9SGregory Neil Shapiro 		/* EMPTY */
272c2aa98e2SPeter Wemm 		/* nothing to do */ ;
27340266059SGregory Neil Shapiro 	else if (IS_MSG_ERR(msg_timeout))
274c2aa98e2SPeter Wemm 	{
275c2aa98e2SPeter Wemm 		if (failure_return)
276c2aa98e2SPeter Wemm 		{
27740266059SGregory Neil Shapiro 			if (msg_timeout == MSG_NOT_BY)
27840266059SGregory Neil Shapiro 			{
27940266059SGregory Neil Shapiro 				(void) sm_snprintf(buf, sizeof buf,
28040266059SGregory Neil Shapiro 					"delivery time expired %lds",
28140266059SGregory Neil Shapiro 					e->e_deliver_by);
28240266059SGregory Neil Shapiro 			}
28340266059SGregory Neil Shapiro 			else
28440266059SGregory Neil Shapiro 			{
28540266059SGregory Neil Shapiro 				(void) sm_snprintf(buf, sizeof buf,
28606f25ae9SGregory Neil Shapiro 					"Cannot send message for %s",
28740266059SGregory Neil Shapiro 					pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
28840266059SGregory Neil Shapiro 						false));
28940266059SGregory Neil Shapiro 			}
29040266059SGregory Neil Shapiro 
29140266059SGregory Neil Shapiro 			/* don't free, allocated from e_rpool */
29240266059SGregory Neil Shapiro 			e->e_message = sm_rpool_strdup_x(e->e_rpool, buf);
293c2aa98e2SPeter Wemm 			message(buf);
294c2aa98e2SPeter Wemm 			e->e_flags |= EF_CLRQUEUE;
295c2aa98e2SPeter Wemm 		}
29640266059SGregory Neil Shapiro 		if (msg_timeout == MSG_NOT_BY)
29740266059SGregory Neil Shapiro 		{
29840266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
29940266059SGregory Neil Shapiro 				"Delivery time (%lds) expired\n",
30040266059SGregory Neil Shapiro 				e->e_deliver_by);
30140266059SGregory Neil Shapiro 		}
30240266059SGregory Neil Shapiro 		else
30340266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30440266059SGregory Neil Shapiro 				"Message could not be delivered for %s\n",
30540266059SGregory Neil Shapiro 				pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
30640266059SGregory Neil Shapiro 					false));
30740266059SGregory Neil Shapiro 		(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30840266059SGregory Neil Shapiro 			"Message will be deleted from queue\n");
309c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
310c2aa98e2SPeter Wemm 		{
31106f25ae9SGregory Neil Shapiro 			if (QS_IS_UNDELIVERED(q->q_state))
312c2aa98e2SPeter Wemm 			{
31306f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
31440266059SGregory Neil Shapiro 				if (msg_timeout == MSG_NOT_BY)
31540266059SGregory Neil Shapiro 					q->q_status = "5.4.7";
31640266059SGregory Neil Shapiro 				else
317c2aa98e2SPeter Wemm 					q->q_status = "4.4.7";
318c2aa98e2SPeter Wemm 			}
319c2aa98e2SPeter Wemm 		}
320c2aa98e2SPeter Wemm 	}
32140266059SGregory Neil Shapiro 	else
32240266059SGregory Neil Shapiro 	{
32340266059SGregory Neil Shapiro 		if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
32440266059SGregory Neil Shapiro 		    now >= e->e_ctime +
32540266059SGregory Neil Shapiro 				TimeOuts.to_q_warning[e->e_timeoutclass])
32640266059SGregory Neil Shapiro 			msg_timeout = MSG_WARN;
32740266059SGregory Neil Shapiro 		else if (IS_DLVR_NOTIFY(e) &&
32840266059SGregory Neil Shapiro 			 e->e_deliver_by > 0 &&
32940266059SGregory Neil Shapiro 			 now >= e->e_ctime + e->e_deliver_by)
33040266059SGregory Neil Shapiro 			msg_timeout = MSG_WARN_BY;
33140266059SGregory Neil Shapiro 
33240266059SGregory Neil Shapiro 		if (IS_MSG_WARN(msg_timeout))
333c2aa98e2SPeter Wemm 		{
334c2aa98e2SPeter Wemm 			if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
335c2aa98e2SPeter Wemm 			    e->e_class >= 0 &&
336c2aa98e2SPeter Wemm 			    e->e_from.q_paddr != NULL &&
337c2aa98e2SPeter Wemm 			    strcmp(e->e_from.q_paddr, "<>") != 0 &&
33840266059SGregory Neil Shapiro 			    sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
33940266059SGregory Neil Shapiro 			    (strlen(e->e_from.q_paddr) <= 8 ||
34040266059SGregory Neil Shapiro 			     sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8],
34140266059SGregory Neil Shapiro 					   "-request") != 0))
342c2aa98e2SPeter Wemm 			{
34340266059SGregory Neil Shapiro 				for (q = e->e_sendqueue; q != NULL;
34440266059SGregory Neil Shapiro 				     q = q->q_next)
345c2aa98e2SPeter Wemm 				{
34640266059SGregory Neil Shapiro 					if (QS_IS_UNDELIVERED(q->q_state)
34706f25ae9SGregory Neil Shapiro #if _FFR_NODELAYDSN_ON_HOLD
34840266059SGregory Neil Shapiro 					    && !bitnset(M_HOLD,
34940266059SGregory Neil Shapiro 							q->q_mailer->m_flags)
35006f25ae9SGregory Neil Shapiro #endif /* _FFR_NODELAYDSN_ON_HOLD */
35140266059SGregory Neil Shapiro 					   )
35240266059SGregory Neil Shapiro 					{
35340266059SGregory Neil Shapiro 						if (msg_timeout ==
35440266059SGregory Neil Shapiro 						    MSG_WARN_BY &&
35540266059SGregory Neil Shapiro 						    (bitset(QPINGONDELAY,
35640266059SGregory Neil Shapiro 							    q->q_flags) ||
35740266059SGregory Neil Shapiro 						    !bitset(QHASNOTIFY,
35840266059SGregory Neil Shapiro 							    q->q_flags))
35940266059SGregory Neil Shapiro 						   )
36040266059SGregory Neil Shapiro 						{
36140266059SGregory Neil Shapiro 							q->q_flags |= QBYNDELAY;
36240266059SGregory Neil Shapiro 							delay_return = true;
36340266059SGregory Neil Shapiro 						}
36440266059SGregory Neil Shapiro 						if (bitset(QPINGONDELAY,
36540266059SGregory Neil Shapiro 							   q->q_flags))
366c2aa98e2SPeter Wemm 						{
367c2aa98e2SPeter Wemm 							q->q_flags |= QDELAYED;
36840266059SGregory Neil Shapiro 							delay_return = true;
36940266059SGregory Neil Shapiro 						}
370c2aa98e2SPeter Wemm 					}
371c2aa98e2SPeter Wemm 				}
372c2aa98e2SPeter Wemm 			}
373c2aa98e2SPeter Wemm 			if (delay_return)
374c2aa98e2SPeter Wemm 			{
37540266059SGregory Neil Shapiro 				if (msg_timeout == MSG_WARN_BY)
37640266059SGregory Neil Shapiro 				{
37740266059SGregory Neil Shapiro 					(void) sm_snprintf(buf, sizeof buf,
37840266059SGregory Neil Shapiro 						"Warning: Delivery time (%lds) exceeded",
37940266059SGregory Neil Shapiro 						e->e_deliver_by);
38040266059SGregory Neil Shapiro 				}
38140266059SGregory Neil Shapiro 				else
38240266059SGregory Neil Shapiro 					(void) sm_snprintf(buf, sizeof buf,
383c2aa98e2SPeter Wemm 						"Warning: could not send message for past %s",
38440266059SGregory Neil Shapiro 						pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
38540266059SGregory Neil Shapiro 							false));
38640266059SGregory Neil Shapiro 
38740266059SGregory Neil Shapiro 				/* don't free, allocated from e_rpool */
38840266059SGregory Neil Shapiro 				e->e_message = sm_rpool_strdup_x(e->e_rpool,
38940266059SGregory Neil Shapiro 								 buf);
390c2aa98e2SPeter Wemm 				message(buf);
391c2aa98e2SPeter Wemm 				e->e_flags |= EF_WARNING;
392c2aa98e2SPeter Wemm 			}
39340266059SGregory Neil Shapiro 			if (msg_timeout == MSG_WARN_BY)
39440266059SGregory Neil Shapiro 			{
39540266059SGregory Neil Shapiro 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
39640266059SGregory Neil Shapiro 					"Warning: Delivery time (%lds) exceeded\n",
39740266059SGregory Neil Shapiro 					e->e_deliver_by);
39840266059SGregory Neil Shapiro 			}
39940266059SGregory Neil Shapiro 			else
40040266059SGregory Neil Shapiro 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
401c2aa98e2SPeter Wemm 					"Warning: message still undelivered after %s\n",
40240266059SGregory Neil Shapiro 					pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
40340266059SGregory Neil Shapiro 					     false));
40440266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
40540266059SGregory Neil Shapiro 				      "Will keep trying until message is %s old\n",
40640266059SGregory Neil Shapiro 				      pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
40740266059SGregory Neil Shapiro 					     false));
40840266059SGregory Neil Shapiro 		}
409c2aa98e2SPeter Wemm 	}
410c2aa98e2SPeter Wemm 
411c2aa98e2SPeter Wemm 	if (tTd(50, 2))
41240266059SGregory Neil Shapiro 		sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
413c2aa98e2SPeter Wemm 			failure_return, delay_return, success_return, queueit);
414c2aa98e2SPeter Wemm 
415c2aa98e2SPeter Wemm 	/*
416c2aa98e2SPeter Wemm 	**  If we had some fatal error, but no addresses are marked as
417c2aa98e2SPeter Wemm 	**  bad, mark them _all_ as bad.
418c2aa98e2SPeter Wemm 	*/
419c2aa98e2SPeter Wemm 
420c2aa98e2SPeter Wemm 	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
421c2aa98e2SPeter Wemm 	{
422c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
423c2aa98e2SPeter Wemm 		{
42406f25ae9SGregory Neil Shapiro 			if ((QS_IS_OK(q->q_state) ||
42506f25ae9SGregory Neil Shapiro 			     QS_IS_VERIFIED(q->q_state)) &&
426c2aa98e2SPeter Wemm 			    bitset(QPINGONFAILURE, q->q_flags))
427c2aa98e2SPeter Wemm 			{
42840266059SGregory Neil Shapiro 				failure_return = true;
42906f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
430c2aa98e2SPeter Wemm 			}
431c2aa98e2SPeter Wemm 		}
432c2aa98e2SPeter Wemm 	}
433c2aa98e2SPeter Wemm 
434c2aa98e2SPeter Wemm 	/*
435c2aa98e2SPeter Wemm 	**  Send back return receipts as requested.
436c2aa98e2SPeter Wemm 	*/
437c2aa98e2SPeter Wemm 
438c2aa98e2SPeter Wemm 	if (success_return && !failure_return && !delay_return && fulldrop &&
439c2aa98e2SPeter Wemm 	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
440c2aa98e2SPeter Wemm 	    strcmp(e->e_from.q_paddr, "<>") != 0)
441c2aa98e2SPeter Wemm 	{
442c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
443c2aa98e2SPeter Wemm 
444c2aa98e2SPeter Wemm 		if (tTd(50, 8))
44540266059SGregory Neil Shapiro 			sm_dprintf("dropenvelope(%s): sending return receipt\n",
44606f25ae9SGregory Neil Shapiro 				id);
447c2aa98e2SPeter Wemm 		e->e_flags |= EF_SENDRECEIPT;
448c2aa98e2SPeter Wemm 		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
449c2aa98e2SPeter Wemm 		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
450c2aa98e2SPeter Wemm 	}
451c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_SENDRECEIPT;
452c2aa98e2SPeter Wemm 
453c2aa98e2SPeter Wemm 	/*
454c2aa98e2SPeter Wemm 	**  Arrange to send error messages if there are fatal errors.
455c2aa98e2SPeter Wemm 	*/
456c2aa98e2SPeter Wemm 
457c2aa98e2SPeter Wemm 	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
458c2aa98e2SPeter Wemm 	{
459c2aa98e2SPeter Wemm 		if (tTd(50, 8))
46040266059SGregory Neil Shapiro 			sm_dprintf("dropenvelope(%s): saving mail\n", id);
46140266059SGregory Neil Shapiro 		panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
462c2aa98e2SPeter Wemm 	}
463c2aa98e2SPeter Wemm 
464c2aa98e2SPeter Wemm 	/*
465c2aa98e2SPeter Wemm 	**  Arrange to send warning messages to postmaster as requested.
466c2aa98e2SPeter Wemm 	*/
467c2aa98e2SPeter Wemm 
46806f25ae9SGregory Neil Shapiro 	if ((failure_return || pmnotify) &&
469c2aa98e2SPeter Wemm 	    PostMasterCopy != NULL &&
47006f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags) &&
47106f25ae9SGregory Neil Shapiro 	    e->e_class >= 0)
472c2aa98e2SPeter Wemm 	{
473c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
47406f25ae9SGregory Neil Shapiro 		char pcopy[MAXNAME];
47506f25ae9SGregory Neil Shapiro 
47606f25ae9SGregory Neil Shapiro 		if (failure_return)
47706f25ae9SGregory Neil Shapiro 		{
47806f25ae9SGregory Neil Shapiro 			expand(PostMasterCopy, pcopy, sizeof pcopy, e);
479c2aa98e2SPeter Wemm 
480c2aa98e2SPeter Wemm 			if (tTd(50, 8))
48140266059SGregory Neil Shapiro 				sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
48206f25ae9SGregory Neil Shapiro 					id, pcopy);
48306f25ae9SGregory Neil Shapiro 			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
48406f25ae9SGregory Neil Shapiro 		}
48506f25ae9SGregory Neil Shapiro 		if (pmnotify)
48606f25ae9SGregory Neil Shapiro 			(void) sendtolist("postmaster", NULLADDR,
48706f25ae9SGregory Neil Shapiro 					  &rlist, 0, e);
48806f25ae9SGregory Neil Shapiro 		(void) returntosender(e->e_message, rlist,
48906f25ae9SGregory Neil Shapiro 				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
490c2aa98e2SPeter Wemm 	}
491c2aa98e2SPeter Wemm 
492c2aa98e2SPeter Wemm 	/*
493c2aa98e2SPeter Wemm 	**  Instantiate or deinstantiate the queue.
494c2aa98e2SPeter Wemm 	*/
495c2aa98e2SPeter Wemm 
496c2aa98e2SPeter Wemm simpledrop:
497c2aa98e2SPeter Wemm 	if (tTd(50, 8))
49840266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
499c2aa98e2SPeter Wemm 			id, queueit);
500c2aa98e2SPeter Wemm 	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
501c2aa98e2SPeter Wemm 	{
502c2aa98e2SPeter Wemm 		if (tTd(50, 1))
503c2aa98e2SPeter Wemm 		{
50440266059SGregory Neil Shapiro 			sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=",
505c2aa98e2SPeter Wemm 				e->e_id, queueit);
506c2aa98e2SPeter Wemm 			printenvflags(e);
507c2aa98e2SPeter Wemm 		}
50840266059SGregory Neil Shapiro 		if (!panic)
50940266059SGregory Neil Shapiro 			(void) xunlink(queuename(e, DATAFL_LETTER));
51040266059SGregory Neil Shapiro #if _FFR_QUARANTINE
51140266059SGregory Neil Shapiro 		if (panic && QueueMode == QM_LOST)
51240266059SGregory Neil Shapiro 		{
51340266059SGregory Neil Shapiro 			/*
51440266059SGregory Neil Shapiro 			**  leave the Qf file behind as
51540266059SGregory Neil Shapiro 			**  the delivery attempt failed.
51640266059SGregory Neil Shapiro 			*/
51740266059SGregory Neil Shapiro 
51840266059SGregory Neil Shapiro 			/* EMPTY */
51940266059SGregory Neil Shapiro 		}
52040266059SGregory Neil Shapiro 		else
52140266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */
52240266059SGregory Neil Shapiro 		if (xunlink(queuename(e, ANYQFL_LETTER)) == 0)
52340266059SGregory Neil Shapiro 		{
52440266059SGregory Neil Shapiro 			/* add to available space in filesystem */
52540266059SGregory Neil Shapiro 			updfs(e, true, !panic);
52640266059SGregory Neil Shapiro 		}
527c2aa98e2SPeter Wemm 
52806f25ae9SGregory Neil Shapiro 		if (e->e_ntries > 0 && LogLevel > 9)
52906f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
53040266059SGregory Neil Shapiro 				  pintvl(curtime() - e->e_ctime, true),
53106f25ae9SGregory Neil Shapiro 				  e->e_ntries);
532c2aa98e2SPeter Wemm 	}
533c2aa98e2SPeter Wemm 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
534c2aa98e2SPeter Wemm 	{
53540266059SGregory Neil Shapiro 		if (!split)
53640266059SGregory Neil Shapiro 			queueup(e, false, true);
53740266059SGregory Neil Shapiro 		else
53840266059SGregory Neil Shapiro 		{
53940266059SGregory Neil Shapiro 			ENVELOPE *oldsib;
54040266059SGregory Neil Shapiro 			ENVELOPE *ee;
54140266059SGregory Neil Shapiro 
54240266059SGregory Neil Shapiro 			/*
54340266059SGregory Neil Shapiro 			**  Save old sibling and set it to NULL to avoid
54440266059SGregory Neil Shapiro 			**  queueing up the same envelopes again.
54540266059SGregory Neil Shapiro 			**  This requires that envelopes in that list have
54640266059SGregory Neil Shapiro 			**  been take care of before (or at some other place).
54740266059SGregory Neil Shapiro 			*/
54840266059SGregory Neil Shapiro 
54940266059SGregory Neil Shapiro 			oldsib = e->e_sibling;
55040266059SGregory Neil Shapiro 			e->e_sibling = NULL;
55140266059SGregory Neil Shapiro 			if (!split_by_recipient(e) &&
55240266059SGregory Neil Shapiro 			    bitset(EF_FATALERRS, e->e_flags))
55340266059SGregory Neil Shapiro 			{
55440266059SGregory Neil Shapiro 				syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d",
55540266059SGregory Neil Shapiro 					e->e_id, queuename(e, DATAFL_LETTER),
55694c01205SGregory Neil Shapiro 					(int) geteuid());
55740266059SGregory Neil Shapiro 			}
55840266059SGregory Neil Shapiro 			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
55940266059SGregory Neil Shapiro 				queueup(ee, false, true);
56040266059SGregory Neil Shapiro 			queueup(e, false, true);
56140266059SGregory Neil Shapiro 
56240266059SGregory Neil Shapiro 			/* clean up */
56340266059SGregory Neil Shapiro 			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
56440266059SGregory Neil Shapiro 			{
56540266059SGregory Neil Shapiro 				/* now unlock the job */
56640266059SGregory Neil Shapiro 				if (tTd(50, 8))
56740266059SGregory Neil Shapiro 					sm_dprintf("dropenvelope(%s): unlocking job\n",
56840266059SGregory Neil Shapiro 						   ee->e_id);
56940266059SGregory Neil Shapiro 				closexscript(ee);
57040266059SGregory Neil Shapiro 				unlockqueue(ee);
57140266059SGregory Neil Shapiro 
57240266059SGregory Neil Shapiro 				/* this envelope is marked unused */
57340266059SGregory Neil Shapiro 				if (ee->e_dfp != NULL)
57440266059SGregory Neil Shapiro 				{
57540266059SGregory Neil Shapiro 					(void) sm_io_close(ee->e_dfp,
57640266059SGregory Neil Shapiro 							   SM_TIME_DEFAULT);
57740266059SGregory Neil Shapiro 					ee->e_dfp = NULL;
57840266059SGregory Neil Shapiro 				}
57940266059SGregory Neil Shapiro 				ee->e_id = NULL;
58040266059SGregory Neil Shapiro 				ee->e_flags &= ~EF_HAS_DF;
58140266059SGregory Neil Shapiro 			}
58240266059SGregory Neil Shapiro 			e->e_sibling = oldsib;
58340266059SGregory Neil Shapiro 		}
584c2aa98e2SPeter Wemm 	}
585c2aa98e2SPeter Wemm 
586c2aa98e2SPeter Wemm 	/* now unlock the job */
587c2aa98e2SPeter Wemm 	if (tTd(50, 8))
58840266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope(%s): unlocking job\n", id);
589c2aa98e2SPeter Wemm 	closexscript(e);
590c2aa98e2SPeter Wemm 	unlockqueue(e);
591c2aa98e2SPeter Wemm 
592c2aa98e2SPeter Wemm 	/* make sure that this envelope is marked unused */
593c2aa98e2SPeter Wemm 	if (e->e_dfp != NULL)
59440266059SGregory Neil Shapiro 	{
59540266059SGregory Neil Shapiro 		(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
596c2aa98e2SPeter Wemm 		e->e_dfp = NULL;
59740266059SGregory Neil Shapiro 	}
598c2aa98e2SPeter Wemm 	e->e_id = NULL;
599c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_HAS_DF;
600c2aa98e2SPeter Wemm }
60140266059SGregory Neil Shapiro /*
602c2aa98e2SPeter Wemm **  CLEARENVELOPE -- clear an envelope without unlocking
603c2aa98e2SPeter Wemm **
604c2aa98e2SPeter Wemm **	This is normally used by a child process to get a clean
605c2aa98e2SPeter Wemm **	envelope without disturbing the parent.
606c2aa98e2SPeter Wemm **
607c2aa98e2SPeter Wemm **	Parameters:
608c2aa98e2SPeter Wemm **		e -- the envelope to clear.
609c2aa98e2SPeter Wemm **		fullclear - if set, the current envelope is total
610c2aa98e2SPeter Wemm **			garbage and should be ignored; otherwise,
611c2aa98e2SPeter Wemm **			release any resources it may indicate.
61240266059SGregory Neil Shapiro **		rpool -- either NULL, or a pointer to a resource pool
61340266059SGregory Neil Shapiro **			from which envelope memory is allocated, and
61440266059SGregory Neil Shapiro **			to which envelope resources are attached.
615c2aa98e2SPeter Wemm **
616c2aa98e2SPeter Wemm **	Returns:
617c2aa98e2SPeter Wemm **		none.
618c2aa98e2SPeter Wemm **
619c2aa98e2SPeter Wemm **	Side Effects:
620c2aa98e2SPeter Wemm **		Closes files associated with the envelope.
621c2aa98e2SPeter Wemm **		Marks the envelope as unallocated.
622c2aa98e2SPeter Wemm */
623c2aa98e2SPeter Wemm 
624c2aa98e2SPeter Wemm void
62540266059SGregory Neil Shapiro clearenvelope(e, fullclear, rpool)
626c2aa98e2SPeter Wemm 	register ENVELOPE *e;
627c2aa98e2SPeter Wemm 	bool fullclear;
62840266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
629c2aa98e2SPeter Wemm {
630c2aa98e2SPeter Wemm 	register HDR *bh;
631c2aa98e2SPeter Wemm 	register HDR **nhp;
632c2aa98e2SPeter Wemm 	extern ENVELOPE BlankEnvelope;
63340266059SGregory Neil Shapiro 	char **p;
634c2aa98e2SPeter Wemm 
635c2aa98e2SPeter Wemm 	if (!fullclear)
636c2aa98e2SPeter Wemm 	{
637c2aa98e2SPeter Wemm 		/* clear out any file information */
638c2aa98e2SPeter Wemm 		if (e->e_xfp != NULL)
63940266059SGregory Neil Shapiro 			(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
640c2aa98e2SPeter Wemm 		if (e->e_dfp != NULL)
64140266059SGregory Neil Shapiro 			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
642c2aa98e2SPeter Wemm 		e->e_xfp = e->e_dfp = NULL;
643c2aa98e2SPeter Wemm 	}
644c2aa98e2SPeter Wemm 
64540266059SGregory Neil Shapiro 	/*
64640266059SGregory Neil Shapiro 	**  Copy BlankEnvelope into *e.
64740266059SGregory Neil Shapiro 	**  It is not safe to simply copy pointers to strings;
64840266059SGregory Neil Shapiro 	**  the strings themselves must be copied (or set to NULL).
64940266059SGregory Neil Shapiro 	**  The problem is that when we assign a new string value to
65040266059SGregory Neil Shapiro 	**  a member of BlankEnvelope, we free the old string.
65140266059SGregory Neil Shapiro 	**  We did not need to do this copying in sendmail 8.11 :-(
65240266059SGregory Neil Shapiro 	**  and it is a potential performance hit.  Reference counted
65340266059SGregory Neil Shapiro 	**  strings are one way out.
65440266059SGregory Neil Shapiro 	*/
65540266059SGregory Neil Shapiro 
65640266059SGregory Neil Shapiro 	*e = BlankEnvelope;
657c2aa98e2SPeter Wemm 	e->e_message = NULL;
65840266059SGregory Neil Shapiro #if _FFR_QUARANTINE
65940266059SGregory Neil Shapiro 	e->e_qfletter = '\0';
66040266059SGregory Neil Shapiro 	e->e_quarmsg = NULL;
66140266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
66240266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */
66340266059SGregory Neil Shapiro 
66440266059SGregory Neil Shapiro 	/*
66540266059SGregory Neil Shapiro 	**  Copy the macro table.
66640266059SGregory Neil Shapiro 	**  We might be able to avoid this by zeroing the macro table
66740266059SGregory Neil Shapiro 	**  and always searching BlankEnvelope.e_macro after e->e_macro
66840266059SGregory Neil Shapiro 	**  in macvalue().
66940266059SGregory Neil Shapiro 	*/
67040266059SGregory Neil Shapiro 
67140266059SGregory Neil Shapiro 	for (p = &e->e_macro.mac_table[0];
67240266059SGregory Neil Shapiro 	     p <= &e->e_macro.mac_table[MAXMACROID];
67340266059SGregory Neil Shapiro 	     ++p)
67440266059SGregory Neil Shapiro 	{
67540266059SGregory Neil Shapiro 		if (*p != NULL)
67640266059SGregory Neil Shapiro 			*p = sm_rpool_strdup_x(rpool, *p);
67740266059SGregory Neil Shapiro 	}
67840266059SGregory Neil Shapiro 
67940266059SGregory Neil Shapiro 	/*
68040266059SGregory Neil Shapiro 	**  XXX There are many strings in the envelope structure
68140266059SGregory Neil Shapiro 	**  XXX that we are not attempting to copy here.
68240266059SGregory Neil Shapiro 	**  XXX Investigate this further.
68340266059SGregory Neil Shapiro 	*/
68440266059SGregory Neil Shapiro 
68540266059SGregory Neil Shapiro 	e->e_rpool = rpool;
68640266059SGregory Neil Shapiro 	e->e_macro.mac_rpool = rpool;
687c2aa98e2SPeter Wemm 	if (Verbose)
68806f25ae9SGregory Neil Shapiro 		set_delivery_mode(SM_DELIVER, e);
689c2aa98e2SPeter Wemm 	bh = BlankEnvelope.e_header;
690c2aa98e2SPeter Wemm 	nhp = &e->e_header;
691c2aa98e2SPeter Wemm 	while (bh != NULL)
692c2aa98e2SPeter Wemm 	{
69340266059SGregory Neil Shapiro 		*nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof *bh);
69406f25ae9SGregory Neil Shapiro 		memmove((char *) *nhp, (char *) bh, sizeof *bh);
695c2aa98e2SPeter Wemm 		bh = bh->h_link;
696c2aa98e2SPeter Wemm 		nhp = &(*nhp)->h_link;
697c2aa98e2SPeter Wemm 	}
698c2aa98e2SPeter Wemm }
69940266059SGregory Neil Shapiro /*
700c2aa98e2SPeter Wemm **  INITSYS -- initialize instantiation of system
701c2aa98e2SPeter Wemm **
702c2aa98e2SPeter Wemm **	In Daemon mode, this is done in the child.
703c2aa98e2SPeter Wemm **
704c2aa98e2SPeter Wemm **	Parameters:
70506f25ae9SGregory Neil Shapiro **		e -- the envelope to use.
706c2aa98e2SPeter Wemm **
707c2aa98e2SPeter Wemm **	Returns:
708c2aa98e2SPeter Wemm **		none.
709c2aa98e2SPeter Wemm **
710c2aa98e2SPeter Wemm **	Side Effects:
711c2aa98e2SPeter Wemm **		Initializes the system macros, some global variables,
712c2aa98e2SPeter Wemm **		etc.  In particular, the current time in various
713c2aa98e2SPeter Wemm **		forms is set.
714c2aa98e2SPeter Wemm */
715c2aa98e2SPeter Wemm 
716c2aa98e2SPeter Wemm void
717c2aa98e2SPeter Wemm initsys(e)
718c2aa98e2SPeter Wemm 	register ENVELOPE *e;
719c2aa98e2SPeter Wemm {
72040266059SGregory Neil Shapiro 	char buf[10];
721c2aa98e2SPeter Wemm #ifdef TTYNAME
722c2aa98e2SPeter Wemm 	static char ybuf[60];			/* holds tty id */
723c2aa98e2SPeter Wemm 	register char *p;
724c2aa98e2SPeter Wemm 	extern char *ttyname();
725c2aa98e2SPeter Wemm #endif /* TTYNAME */
726c2aa98e2SPeter Wemm 
727c2aa98e2SPeter Wemm 	/*
728c2aa98e2SPeter Wemm 	**  Give this envelope a reality.
729c2aa98e2SPeter Wemm 	**	I.e., an id, a transcript, and a creation time.
73040266059SGregory Neil Shapiro 	**  We don't select the queue until all of the recipients are known.
731c2aa98e2SPeter Wemm 	*/
732c2aa98e2SPeter Wemm 
733c2aa98e2SPeter Wemm 	openxscript(e);
734c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
73540266059SGregory Neil Shapiro #if _FFR_QUARANTINE
73640266059SGregory Neil Shapiro 	e->e_qfletter = '\0';
73740266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */
73806f25ae9SGregory Neil Shapiro #if _FFR_QUEUEDELAY
73906f25ae9SGregory Neil Shapiro 	e->e_queuealg = QueueAlg;
74006f25ae9SGregory Neil Shapiro 	e->e_queuedelay = QueueInitDelay;
74106f25ae9SGregory Neil Shapiro #endif /* _FFR_QUEUEDELAY */
742c2aa98e2SPeter Wemm 
743c2aa98e2SPeter Wemm 	/*
744c2aa98e2SPeter Wemm 	**  Set OutChannel to something useful if stdout isn't it.
745c2aa98e2SPeter Wemm 	**	This arranges that any extra stuff the mailer produces
746c2aa98e2SPeter Wemm 	**	gets sent back to the user on error (because it is
747c2aa98e2SPeter Wemm 	**	tucked away in the transcript).
748c2aa98e2SPeter Wemm 	*/
749c2aa98e2SPeter Wemm 
750c2aa98e2SPeter Wemm 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
751c2aa98e2SPeter Wemm 	    e->e_xfp != NULL)
752c2aa98e2SPeter Wemm 		OutChannel = e->e_xfp;
753c2aa98e2SPeter Wemm 
754c2aa98e2SPeter Wemm 	/*
755c2aa98e2SPeter Wemm 	**  Set up some basic system macros.
756c2aa98e2SPeter Wemm 	*/
757c2aa98e2SPeter Wemm 
758c2aa98e2SPeter Wemm 	/* process id */
75940266059SGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%d", (int) CurrentPid);
76040266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'p', buf);
761c2aa98e2SPeter Wemm 
762c2aa98e2SPeter Wemm 	/* hop count */
76340266059SGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount);
76440266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'c', buf);
765c2aa98e2SPeter Wemm 
766c2aa98e2SPeter Wemm 	/* time as integer, unix time, arpa time */
767c2aa98e2SPeter Wemm 	settime(e);
768c2aa98e2SPeter Wemm 
76906f25ae9SGregory Neil Shapiro 	/* Load average */
77040266059SGregory Neil Shapiro 	sm_getla();
77106f25ae9SGregory Neil Shapiro 
772c2aa98e2SPeter Wemm #ifdef TTYNAME
773c2aa98e2SPeter Wemm 	/* tty name */
774c2aa98e2SPeter Wemm 	if (macvalue('y', e) == NULL)
775c2aa98e2SPeter Wemm 	{
776c2aa98e2SPeter Wemm 		p = ttyname(2);
777c2aa98e2SPeter Wemm 		if (p != NULL)
778c2aa98e2SPeter Wemm 		{
779c2aa98e2SPeter Wemm 			if (strrchr(p, '/') != NULL)
780c2aa98e2SPeter Wemm 				p = strrchr(p, '/') + 1;
78140266059SGregory Neil Shapiro 			(void) sm_strlcpy(ybuf, sizeof ybuf, p);
78240266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM, 'y', ybuf);
783c2aa98e2SPeter Wemm 		}
784c2aa98e2SPeter Wemm 	}
785c2aa98e2SPeter Wemm #endif /* TTYNAME */
786c2aa98e2SPeter Wemm }
78740266059SGregory Neil Shapiro /*
788c2aa98e2SPeter Wemm **  SETTIME -- set the current time.
789c2aa98e2SPeter Wemm **
790c2aa98e2SPeter Wemm **	Parameters:
79106f25ae9SGregory Neil Shapiro **		e -- the envelope in which the macros should be set.
792c2aa98e2SPeter Wemm **
793c2aa98e2SPeter Wemm **	Returns:
794c2aa98e2SPeter Wemm **		none.
795c2aa98e2SPeter Wemm **
796c2aa98e2SPeter Wemm **	Side Effects:
797c2aa98e2SPeter Wemm **		Sets the various time macros -- $a, $b, $d, $t.
798c2aa98e2SPeter Wemm */
799c2aa98e2SPeter Wemm 
800c2aa98e2SPeter Wemm void
801c2aa98e2SPeter Wemm settime(e)
802c2aa98e2SPeter Wemm 	register ENVELOPE *e;
803c2aa98e2SPeter Wemm {
804c2aa98e2SPeter Wemm 	register char *p;
805c2aa98e2SPeter Wemm 	auto time_t now;
80640266059SGregory Neil Shapiro 	char buf[30];
807c2aa98e2SPeter Wemm 	register struct tm *tm;
808c2aa98e2SPeter Wemm 
809c2aa98e2SPeter Wemm 	now = curtime();
810c2aa98e2SPeter Wemm 	tm = gmtime(&now);
81140266059SGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof buf, "%04d%02d%02d%02d%02d",
81240266059SGregory Neil Shapiro 			   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
81340266059SGregory Neil Shapiro 			   tm->tm_hour, tm->tm_min);
81440266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 't', buf);
81540266059SGregory Neil Shapiro 	(void) sm_strlcpy(buf, ctime(&now), sizeof buf);
81640266059SGregory Neil Shapiro 	p = strchr(buf, '\n');
817c2aa98e2SPeter Wemm 	if (p != NULL)
818c2aa98e2SPeter Wemm 		*p = '\0';
81940266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'd', buf);
82040266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf));
821c2aa98e2SPeter Wemm 	if (macvalue('a', e) == NULL)
82240266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e));
823c2aa98e2SPeter Wemm }
82440266059SGregory Neil Shapiro /*
825c2aa98e2SPeter Wemm **  OPENXSCRIPT -- Open transcript file
826c2aa98e2SPeter Wemm **
827c2aa98e2SPeter Wemm **	Creates a transcript file for possible eventual mailing or
828c2aa98e2SPeter Wemm **	sending back.
829c2aa98e2SPeter Wemm **
830c2aa98e2SPeter Wemm **	Parameters:
831c2aa98e2SPeter Wemm **		e -- the envelope to create the transcript in/for.
832c2aa98e2SPeter Wemm **
833c2aa98e2SPeter Wemm **	Returns:
834c2aa98e2SPeter Wemm **		none
835c2aa98e2SPeter Wemm **
836c2aa98e2SPeter Wemm **	Side Effects:
837c2aa98e2SPeter Wemm **		Creates the transcript file.
838c2aa98e2SPeter Wemm */
839c2aa98e2SPeter Wemm 
840c2aa98e2SPeter Wemm #ifndef O_APPEND
841c2aa98e2SPeter Wemm # define O_APPEND	0
84206f25ae9SGregory Neil Shapiro #endif /* ! O_APPEND */
843c2aa98e2SPeter Wemm 
844c2aa98e2SPeter Wemm void
845c2aa98e2SPeter Wemm openxscript(e)
846c2aa98e2SPeter Wemm 	register ENVELOPE *e;
847c2aa98e2SPeter Wemm {
848c2aa98e2SPeter Wemm 	register char *p;
849c2aa98e2SPeter Wemm 
850c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
851c2aa98e2SPeter Wemm 		return;
85206f25ae9SGregory Neil Shapiro 
85306f25ae9SGregory Neil Shapiro #if 0
85406f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
85506f25ae9SGregory Neil Shapiro 		syserr("openxscript: job not locked");
85606f25ae9SGregory Neil Shapiro #endif /* 0 */
85706f25ae9SGregory Neil Shapiro 
85840266059SGregory Neil Shapiro 	p = queuename(e, XSCRPT_LETTER);
85906f25ae9SGregory Neil Shapiro 	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
86006f25ae9SGregory Neil Shapiro 			  SFF_NOTEXCL|SFF_OPENASROOT);
86106f25ae9SGregory Neil Shapiro 
86206f25ae9SGregory Neil Shapiro 	if (e->e_xfp == NULL)
863c2aa98e2SPeter Wemm 	{
864c2aa98e2SPeter Wemm 		syserr("Can't create transcript file %s", p);
86540266059SGregory Neil Shapiro 		e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
86640266059SGregory Neil Shapiro 				      SM_PATH_DEVNULL, SM_IO_RDWR, NULL);
86706f25ae9SGregory Neil Shapiro 		if (e->e_xfp == NULL)
86840266059SGregory Neil Shapiro 			syserr("!Can't open %s", SM_PATH_DEVNULL);
869c2aa98e2SPeter Wemm 	}
87040266059SGregory Neil Shapiro 	(void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0);
871c2aa98e2SPeter Wemm 	if (tTd(46, 9))
872c2aa98e2SPeter Wemm 	{
87340266059SGregory Neil Shapiro 		sm_dprintf("openxscript(%s):\n  ", p);
87440266059SGregory Neil Shapiro 		dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true,
87540266059SGregory Neil Shapiro 		       false);
876c2aa98e2SPeter Wemm 	}
877c2aa98e2SPeter Wemm }
87840266059SGregory Neil Shapiro /*
879c2aa98e2SPeter Wemm **  CLOSEXSCRIPT -- close the transcript file.
880c2aa98e2SPeter Wemm **
881c2aa98e2SPeter Wemm **	Parameters:
882c2aa98e2SPeter Wemm **		e -- the envelope containing the transcript to close.
883c2aa98e2SPeter Wemm **
884c2aa98e2SPeter Wemm **	Returns:
885c2aa98e2SPeter Wemm **		none.
886c2aa98e2SPeter Wemm **
887c2aa98e2SPeter Wemm **	Side Effects:
888c2aa98e2SPeter Wemm **		none.
889c2aa98e2SPeter Wemm */
890c2aa98e2SPeter Wemm 
891c2aa98e2SPeter Wemm void
892c2aa98e2SPeter Wemm closexscript(e)
893c2aa98e2SPeter Wemm 	register ENVELOPE *e;
894c2aa98e2SPeter Wemm {
895c2aa98e2SPeter Wemm 	if (e->e_xfp == NULL)
896c2aa98e2SPeter Wemm 		return;
89706f25ae9SGregory Neil Shapiro #if 0
89806f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL)
89906f25ae9SGregory Neil Shapiro 		syserr("closexscript: job not locked");
90006f25ae9SGregory Neil Shapiro #endif /* 0 */
90140266059SGregory Neil Shapiro 	(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
902c2aa98e2SPeter Wemm 	e->e_xfp = NULL;
903c2aa98e2SPeter Wemm }
90440266059SGregory Neil Shapiro /*
905c2aa98e2SPeter Wemm **  SETSENDER -- set the person who this message is from
906c2aa98e2SPeter Wemm **
907c2aa98e2SPeter Wemm **	Under certain circumstances allow the user to say who
908c2aa98e2SPeter Wemm **	s/he is (using -f or -r).  These are:
909c2aa98e2SPeter Wemm **	1.  The user's uid is zero (root).
910c2aa98e2SPeter Wemm **	2.  The user's login name is in an approved list (typically
911c2aa98e2SPeter Wemm **	    from a network server).
912c2aa98e2SPeter Wemm **	3.  The address the user is trying to claim has a
913c2aa98e2SPeter Wemm **	    "!" character in it (since #2 doesn't do it for
914c2aa98e2SPeter Wemm **	    us if we are dialing out for UUCP).
915c2aa98e2SPeter Wemm **	A better check to replace #3 would be if the
916c2aa98e2SPeter Wemm **	effective uid is "UUCP" -- this would require me
917c2aa98e2SPeter Wemm **	to rewrite getpwent to "grab" uucp as it went by,
918c2aa98e2SPeter Wemm **	make getname more nasty, do another passwd file
919c2aa98e2SPeter Wemm **	scan, or compile the UID of "UUCP" into the code,
920c2aa98e2SPeter Wemm **	all of which are reprehensible.
921c2aa98e2SPeter Wemm **
922c2aa98e2SPeter Wemm **	Assuming all of these fail, we figure out something
923c2aa98e2SPeter Wemm **	ourselves.
924c2aa98e2SPeter Wemm **
925c2aa98e2SPeter Wemm **	Parameters:
926c2aa98e2SPeter Wemm **		from -- the person we would like to believe this message
927c2aa98e2SPeter Wemm **			is from, as specified on the command line.
928c2aa98e2SPeter Wemm **		e -- the envelope in which we would like the sender set.
929c2aa98e2SPeter Wemm **		delimptr -- if non-NULL, set to the location of the
930c2aa98e2SPeter Wemm **			trailing delimiter.
931c2aa98e2SPeter Wemm **		delimchar -- the character that will delimit the sender
932c2aa98e2SPeter Wemm **			address.
933c2aa98e2SPeter Wemm **		internal -- set if this address is coming from an internal
934c2aa98e2SPeter Wemm **			source such as an owner alias.
935c2aa98e2SPeter Wemm **
936c2aa98e2SPeter Wemm **	Returns:
937c2aa98e2SPeter Wemm **		none.
938c2aa98e2SPeter Wemm **
939c2aa98e2SPeter Wemm **	Side Effects:
940c2aa98e2SPeter Wemm **		sets sendmail's notion of who the from person is.
941c2aa98e2SPeter Wemm */
942c2aa98e2SPeter Wemm 
943c2aa98e2SPeter Wemm void
944c2aa98e2SPeter Wemm setsender(from, e, delimptr, delimchar, internal)
945c2aa98e2SPeter Wemm 	char *from;
946c2aa98e2SPeter Wemm 	register ENVELOPE *e;
947c2aa98e2SPeter Wemm 	char **delimptr;
948c2aa98e2SPeter Wemm 	int delimchar;
949c2aa98e2SPeter Wemm 	bool internal;
950c2aa98e2SPeter Wemm {
951c2aa98e2SPeter Wemm 	register char **pvp;
952c2aa98e2SPeter Wemm 	char *realname = NULL;
953c2aa98e2SPeter Wemm 	char *bp;
954c2aa98e2SPeter Wemm 	char buf[MAXNAME + 2];
955c2aa98e2SPeter Wemm 	char pvpbuf[PSBUFSIZE];
956c2aa98e2SPeter Wemm 	extern char *FullName;
957c2aa98e2SPeter Wemm 
958c2aa98e2SPeter Wemm 	if (tTd(45, 1))
95940266059SGregory Neil Shapiro 		sm_dprintf("setsender(%s)\n", from == NULL ? "" : from);
960c2aa98e2SPeter Wemm 
96113bd1963SGregory Neil Shapiro 	/* may be set from earlier calls */
96213bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'x', "");
96313bd1963SGregory Neil Shapiro 
964c2aa98e2SPeter Wemm 	/*
965c2aa98e2SPeter Wemm 	**  Figure out the real user executing us.
966c2aa98e2SPeter Wemm 	**	Username can return errno != 0 on non-errors.
967c2aa98e2SPeter Wemm 	*/
968c2aa98e2SPeter Wemm 
969c2aa98e2SPeter Wemm 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
970c2aa98e2SPeter Wemm 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
971c2aa98e2SPeter Wemm 		realname = from;
972c2aa98e2SPeter Wemm 	if (realname == NULL || realname[0] == '\0')
973c2aa98e2SPeter Wemm 		realname = username();
974c2aa98e2SPeter Wemm 
975c2aa98e2SPeter Wemm 	if (ConfigLevel < 2)
97640266059SGregory Neil Shapiro 		SuprErrs = true;
977c2aa98e2SPeter Wemm 
97840266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
97940266059SGregory Neil Shapiro 
98006f25ae9SGregory Neil Shapiro 	/* preset state for then clause in case from == NULL */
98106f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_BADADDR;
98206f25ae9SGregory Neil Shapiro 	e->e_from.q_flags = 0;
983c2aa98e2SPeter Wemm 	if (from == NULL ||
984c2aa98e2SPeter Wemm 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
98540266059SGregory Neil Shapiro 		      delimchar, delimptr, e, false) == NULL ||
98606f25ae9SGregory Neil Shapiro 	    QS_IS_BADADDR(e->e_from.q_state) ||
987c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == ProgMailer ||
988c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == FileMailer ||
989c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == InclMailer)
990c2aa98e2SPeter Wemm 	{
991c2aa98e2SPeter Wemm 		/* log garbage addresses for traceback */
992c2aa98e2SPeter Wemm 		if (from != NULL && LogLevel > 2)
993c2aa98e2SPeter Wemm 		{
994c2aa98e2SPeter Wemm 			char *p;
995c2aa98e2SPeter Wemm 			char ebuf[MAXNAME * 2 + 2];
996c2aa98e2SPeter Wemm 
997c2aa98e2SPeter Wemm 			p = macvalue('_', e);
998c2aa98e2SPeter Wemm 			if (p == NULL)
999c2aa98e2SPeter Wemm 			{
1000c2aa98e2SPeter Wemm 				char *host = RealHostName;
1001c2aa98e2SPeter Wemm 
1002c2aa98e2SPeter Wemm 				if (host == NULL)
1003c2aa98e2SPeter Wemm 					host = MyHostName;
100440266059SGregory Neil Shapiro 				(void) sm_snprintf(ebuf, sizeof ebuf,
100540266059SGregory Neil Shapiro 						   "%.*s@%.*s", MAXNAME,
100640266059SGregory Neil Shapiro 						   realname, MAXNAME, host);
1007c2aa98e2SPeter Wemm 				p = ebuf;
1008c2aa98e2SPeter Wemm 			}
1009c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
101006f25ae9SGregory Neil Shapiro 				  "setsender: %s: invalid or unparsable, received from %s",
1011c2aa98e2SPeter Wemm 				  shortenstring(from, 83), p);
1012c2aa98e2SPeter Wemm 		}
1013c2aa98e2SPeter Wemm 		if (from != NULL)
1014c2aa98e2SPeter Wemm 		{
101506f25ae9SGregory Neil Shapiro 			if (!QS_IS_BADADDR(e->e_from.q_state))
1016c2aa98e2SPeter Wemm 			{
1017c2aa98e2SPeter Wemm 				/* it was a bogus mailer in the from addr */
1018c2aa98e2SPeter Wemm 				e->e_status = "5.1.7";
101906f25ae9SGregory Neil Shapiro 				usrerrenh(e->e_status,
102006f25ae9SGregory Neil Shapiro 					  "553 Invalid sender address");
1021c2aa98e2SPeter Wemm 			}
102240266059SGregory Neil Shapiro 			SuprErrs = true;
1023c2aa98e2SPeter Wemm 		}
1024c2aa98e2SPeter Wemm 		if (from == realname ||
102540266059SGregory Neil Shapiro 		    parseaddr(from = realname,
102640266059SGregory Neil Shapiro 			      &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ',
102740266059SGregory Neil Shapiro 			      NULL, e, false) == NULL)
1028c2aa98e2SPeter Wemm 		{
1029c2aa98e2SPeter Wemm 			char nbuf[100];
1030c2aa98e2SPeter Wemm 
103140266059SGregory Neil Shapiro 			SuprErrs = true;
1032c2aa98e2SPeter Wemm 			expand("\201n", nbuf, sizeof nbuf, e);
103340266059SGregory Neil Shapiro 			from = sm_rpool_strdup_x(e->e_rpool, nbuf);
103440266059SGregory Neil Shapiro 			if (parseaddr(from, &e->e_from, RF_COPYALL, ' ',
103540266059SGregory Neil Shapiro 				      NULL, e, false) == NULL &&
1036c2aa98e2SPeter Wemm 			    parseaddr(from = "postmaster", &e->e_from,
103740266059SGregory Neil Shapiro 				      RF_COPYALL, ' ', NULL, e, false) == NULL)
103806f25ae9SGregory Neil Shapiro 				syserr("553 5.3.0 setsender: can't even parse postmaster!");
1039c2aa98e2SPeter Wemm 		}
1040c2aa98e2SPeter Wemm 	}
1041c2aa98e2SPeter Wemm 	else
104240266059SGregory Neil Shapiro 		FromFlag = true;
104306f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_SENDER;
1044c2aa98e2SPeter Wemm 	if (tTd(45, 5))
1045c2aa98e2SPeter Wemm 	{
104640266059SGregory Neil Shapiro 		sm_dprintf("setsender: QS_SENDER ");
104740266059SGregory Neil Shapiro 		printaddr(&e->e_from, false);
1048c2aa98e2SPeter Wemm 	}
104940266059SGregory Neil Shapiro 	SuprErrs = false;
1050c2aa98e2SPeter Wemm 
1051c2aa98e2SPeter Wemm #if USERDB
1052c2aa98e2SPeter Wemm 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
1053c2aa98e2SPeter Wemm 	{
1054c2aa98e2SPeter Wemm 		register char *p;
1055c2aa98e2SPeter Wemm 
105640266059SGregory Neil Shapiro 		p = udbsender(e->e_from.q_user, e->e_rpool);
1057c2aa98e2SPeter Wemm 		if (p != NULL)
1058c2aa98e2SPeter Wemm 			from = p;
1059c2aa98e2SPeter Wemm 	}
1060c2aa98e2SPeter Wemm #endif /* USERDB */
1061c2aa98e2SPeter Wemm 
1062c2aa98e2SPeter Wemm 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
1063c2aa98e2SPeter Wemm 	{
106440266059SGregory Neil Shapiro 		SM_MBDB_T user;
106540266059SGregory Neil Shapiro 
1066c2aa98e2SPeter Wemm 		if (!internal)
1067c2aa98e2SPeter Wemm 		{
1068c2aa98e2SPeter Wemm 			/* if the user already given fullname don't redefine */
1069c2aa98e2SPeter Wemm 			if (FullName == NULL)
1070c2aa98e2SPeter Wemm 				FullName = macvalue('x', e);
1071605302a5SGregory Neil Shapiro 			if (FullName != NULL)
1072605302a5SGregory Neil Shapiro 			{
1073605302a5SGregory Neil Shapiro 				if (FullName[0] == '\0')
1074c2aa98e2SPeter Wemm 					FullName = NULL;
1075605302a5SGregory Neil Shapiro 				else
1076605302a5SGregory Neil Shapiro 					FullName = newstr(FullName);
1077605302a5SGregory Neil Shapiro 			}
1078c2aa98e2SPeter Wemm 		}
1079c2aa98e2SPeter Wemm 
1080c2aa98e2SPeter Wemm 		if (e->e_from.q_user[0] != '\0' &&
108140266059SGregory Neil Shapiro 		    sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK)
1082c2aa98e2SPeter Wemm 		{
1083c2aa98e2SPeter Wemm 			/*
1084c2aa98e2SPeter Wemm 			**  Process passwd file entry.
1085c2aa98e2SPeter Wemm 			*/
1086c2aa98e2SPeter Wemm 
1087c2aa98e2SPeter Wemm 			/* extract home directory */
108840266059SGregory Neil Shapiro 			if (*user.mbdb_homedir == '\0')
108942e5d165SGregory Neil Shapiro 				e->e_from.q_home = NULL;
109040266059SGregory Neil Shapiro 			else if (strcmp(user.mbdb_homedir, "/") == 0)
109140266059SGregory Neil Shapiro 				e->e_from.q_home = "";
1092c2aa98e2SPeter Wemm 			else
109340266059SGregory Neil Shapiro 				e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool,
109440266059SGregory Neil Shapiro 							user.mbdb_homedir);
109540266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home);
1096c2aa98e2SPeter Wemm 
1097c2aa98e2SPeter Wemm 			/* extract user and group id */
109840266059SGregory Neil Shapiro 			if (user.mbdb_uid != SM_NO_UID)
109940266059SGregory Neil Shapiro 			{
110040266059SGregory Neil Shapiro 				e->e_from.q_uid = user.mbdb_uid;
110140266059SGregory Neil Shapiro 				e->e_from.q_gid = user.mbdb_gid;
1102c2aa98e2SPeter Wemm 				e->e_from.q_flags |= QGOODUID;
110340266059SGregory Neil Shapiro 			}
1104c2aa98e2SPeter Wemm 
1105c2aa98e2SPeter Wemm 			/* extract full name from passwd file */
110640266059SGregory Neil Shapiro 			if (FullName == NULL && !internal &&
110740266059SGregory Neil Shapiro 			    user.mbdb_fullname[0] != '\0' &&
110840266059SGregory Neil Shapiro 			    strcmp(user.mbdb_name, e->e_from.q_user) == 0)
1109c2aa98e2SPeter Wemm 			{
111040266059SGregory Neil Shapiro 				FullName = newstr(user.mbdb_fullname);
1111c2aa98e2SPeter Wemm 			}
1112c2aa98e2SPeter Wemm 		}
1113c2aa98e2SPeter Wemm 		else
1114c2aa98e2SPeter Wemm 		{
111506f25ae9SGregory Neil Shapiro 			e->e_from.q_home = NULL;
1116c2aa98e2SPeter Wemm 		}
1117c2aa98e2SPeter Wemm 		if (FullName != NULL && !internal)
111813bd1963SGregory Neil Shapiro 			macdefine(&e->e_macro, A_TEMP, 'x', FullName);
1119c2aa98e2SPeter Wemm 	}
11202e43090eSPeter Wemm 	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
1121c2aa98e2SPeter Wemm 	{
1122c2aa98e2SPeter Wemm 		if (e->e_from.q_home == NULL)
1123c2aa98e2SPeter Wemm 		{
1124c2aa98e2SPeter Wemm 			e->e_from.q_home = getenv("HOME");
112542e5d165SGregory Neil Shapiro 			if (e->e_from.q_home != NULL)
112642e5d165SGregory Neil Shapiro 			{
112742e5d165SGregory Neil Shapiro 				if (*e->e_from.q_home == '\0')
112842e5d165SGregory Neil Shapiro 					e->e_from.q_home = NULL;
112942e5d165SGregory Neil Shapiro 				else if (strcmp(e->e_from.q_home, "/") == 0)
1130c2aa98e2SPeter Wemm 					e->e_from.q_home++;
1131c2aa98e2SPeter Wemm 			}
113242e5d165SGregory Neil Shapiro 		}
1133c2aa98e2SPeter Wemm 		e->e_from.q_uid = RealUid;
1134c2aa98e2SPeter Wemm 		e->e_from.q_gid = RealGid;
1135c2aa98e2SPeter Wemm 		e->e_from.q_flags |= QGOODUID;
1136c2aa98e2SPeter Wemm 	}
1137c2aa98e2SPeter Wemm 
1138c2aa98e2SPeter Wemm 	/*
1139c2aa98e2SPeter Wemm 	**  Rewrite the from person to dispose of possible implicit
1140c2aa98e2SPeter Wemm 	**	links in the net.
1141c2aa98e2SPeter Wemm 	*/
1142c2aa98e2SPeter Wemm 
1143c2aa98e2SPeter Wemm 	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL);
1144c2aa98e2SPeter Wemm 	if (pvp == NULL)
1145c2aa98e2SPeter Wemm 	{
1146c2aa98e2SPeter Wemm 		/* don't need to give error -- prescan did that already */
1147c2aa98e2SPeter Wemm 		if (LogLevel > 2)
1148c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
1149c2aa98e2SPeter Wemm 				  "cannot prescan from (%s)",
1150c2aa98e2SPeter Wemm 				  shortenstring(from, MAXSHORTSTR));
115140266059SGregory Neil Shapiro 		finis(true, true, ExitStat);
1152c2aa98e2SPeter Wemm 	}
115340266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 3, e);
115440266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 1, e);
115540266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 4, e);
115640266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
1157c2aa98e2SPeter Wemm 	bp = buf + 1;
1158c2aa98e2SPeter Wemm 	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
1159c2aa98e2SPeter Wemm 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
1160c2aa98e2SPeter Wemm 	{
1161c2aa98e2SPeter Wemm 		/* heuristic: route-addr: add angle brackets */
116240266059SGregory Neil Shapiro 		(void) sm_strlcat(bp, ">", sizeof buf - 1);
1163c2aa98e2SPeter Wemm 		*--bp = '<';
1164c2aa98e2SPeter Wemm 	}
116540266059SGregory Neil Shapiro 	e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp);
116640266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
1167c2aa98e2SPeter Wemm 
1168c2aa98e2SPeter Wemm 	/* save the domain spec if this mailer wants it */
1169c2aa98e2SPeter Wemm 	if (e->e_from.q_mailer != NULL &&
1170c2aa98e2SPeter Wemm 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
1171c2aa98e2SPeter Wemm 	{
1172c2aa98e2SPeter Wemm 		char **lastat;
1173c2aa98e2SPeter Wemm 
1174c2aa98e2SPeter Wemm 		/* get rid of any pesky angle brackets */
117540266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
117640266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 3, e);
117740266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 1, e);
117840266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 4, e);
117940266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
1180c2aa98e2SPeter Wemm 
1181c2aa98e2SPeter Wemm 		/* strip off to the last "@" sign */
1182c2aa98e2SPeter Wemm 		for (lastat = NULL; *pvp != NULL; pvp++)
1183c2aa98e2SPeter Wemm 			if (strcmp(*pvp, "@") == 0)
1184c2aa98e2SPeter Wemm 				lastat = pvp;
1185c2aa98e2SPeter Wemm 		if (lastat != NULL)
1186c2aa98e2SPeter Wemm 		{
118740266059SGregory Neil Shapiro 			e->e_fromdomain = copyplist(lastat, true, e->e_rpool);
1188c2aa98e2SPeter Wemm 			if (tTd(45, 3))
1189c2aa98e2SPeter Wemm 			{
119040266059SGregory Neil Shapiro 				sm_dprintf("Saving from domain: ");
1191c2aa98e2SPeter Wemm 				printav(e->e_fromdomain);
1192c2aa98e2SPeter Wemm 			}
1193c2aa98e2SPeter Wemm 		}
1194c2aa98e2SPeter Wemm 	}
1195c2aa98e2SPeter Wemm }
119640266059SGregory Neil Shapiro /*
1197c2aa98e2SPeter Wemm **  PRINTENVFLAGS -- print envelope flags for debugging
1198c2aa98e2SPeter Wemm **
1199c2aa98e2SPeter Wemm **	Parameters:
1200c2aa98e2SPeter Wemm **		e -- the envelope with the flags to be printed.
1201c2aa98e2SPeter Wemm **
1202c2aa98e2SPeter Wemm **	Returns:
1203c2aa98e2SPeter Wemm **		none.
1204c2aa98e2SPeter Wemm */
1205c2aa98e2SPeter Wemm 
1206c2aa98e2SPeter Wemm struct eflags
1207c2aa98e2SPeter Wemm {
1208c2aa98e2SPeter Wemm 	char		*ef_name;
120940266059SGregory Neil Shapiro 	unsigned long	ef_bit;
1210c2aa98e2SPeter Wemm };
1211c2aa98e2SPeter Wemm 
121206f25ae9SGregory Neil Shapiro static struct eflags	EnvelopeFlags[] =
1213c2aa98e2SPeter Wemm {
1214c2aa98e2SPeter Wemm 	{ "OLDSTYLE",		EF_OLDSTYLE	},
1215c2aa98e2SPeter Wemm 	{ "INQUEUE",		EF_INQUEUE	},
1216c2aa98e2SPeter Wemm 	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
1217c2aa98e2SPeter Wemm 	{ "CLRQUEUE",		EF_CLRQUEUE	},
1218c2aa98e2SPeter Wemm 	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
1219c2aa98e2SPeter Wemm 	{ "FATALERRS",		EF_FATALERRS	},
1220c2aa98e2SPeter Wemm 	{ "DELETE_BCC",		EF_DELETE_BCC	},
1221c2aa98e2SPeter Wemm 	{ "RESPONSE",		EF_RESPONSE	},
1222c2aa98e2SPeter Wemm 	{ "RESENT",		EF_RESENT	},
1223c2aa98e2SPeter Wemm 	{ "VRFYONLY",		EF_VRFYONLY	},
1224c2aa98e2SPeter Wemm 	{ "WARNING",		EF_WARNING	},
1225c2aa98e2SPeter Wemm 	{ "QUEUERUN",		EF_QUEUERUN	},
1226c2aa98e2SPeter Wemm 	{ "GLOBALERRS",		EF_GLOBALERRS	},
1227c2aa98e2SPeter Wemm 	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
1228c2aa98e2SPeter Wemm 	{ "METOO",		EF_METOO	},
1229c2aa98e2SPeter Wemm 	{ "LOGSENDER",		EF_LOGSENDER	},
1230c2aa98e2SPeter Wemm 	{ "NORECEIPT",		EF_NORECEIPT	},
1231c2aa98e2SPeter Wemm 	{ "HAS8BIT",		EF_HAS8BIT	},
1232c2aa98e2SPeter Wemm 	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
1233c2aa98e2SPeter Wemm 	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
1234c2aa98e2SPeter Wemm 	{ "RET_PARAM",		EF_RET_PARAM	},
1235c2aa98e2SPeter Wemm 	{ "HAS_DF",		EF_HAS_DF	},
1236c2aa98e2SPeter Wemm 	{ "IS_MIME",		EF_IS_MIME	},
1237c2aa98e2SPeter Wemm 	{ "DONT_MIME",		EF_DONT_MIME	},
123840266059SGregory Neil Shapiro 	{ "DISCARD",		EF_DISCARD	},
123940266059SGregory Neil Shapiro 	{ "TOOBIG",		EF_TOOBIG	},
124040266059SGregory Neil Shapiro 	{ "SPLIT",		EF_SPLIT	},
124140266059SGregory Neil Shapiro 	{ "UNSAFE",		EF_UNSAFE	},
1242193538b7SGregory Neil Shapiro 	{ NULL,			0		}
1243c2aa98e2SPeter Wemm };
1244c2aa98e2SPeter Wemm 
1245c2aa98e2SPeter Wemm void
1246c2aa98e2SPeter Wemm printenvflags(e)
1247c2aa98e2SPeter Wemm 	register ENVELOPE *e;
1248c2aa98e2SPeter Wemm {
1249c2aa98e2SPeter Wemm 	register struct eflags *ef;
125040266059SGregory Neil Shapiro 	bool first = true;
1251c2aa98e2SPeter Wemm 
125240266059SGregory Neil Shapiro 	(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%lx", e->e_flags);
1253c2aa98e2SPeter Wemm 	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
1254c2aa98e2SPeter Wemm 	{
1255c2aa98e2SPeter Wemm 		if (!bitset(ef->ef_bit, e->e_flags))
1256c2aa98e2SPeter Wemm 			continue;
1257c2aa98e2SPeter Wemm 		if (first)
125840266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "<%s",
125940266059SGregory Neil Shapiro 					     ef->ef_name);
1260c2aa98e2SPeter Wemm 		else
126140266059SGregory Neil Shapiro 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ",%s",
126240266059SGregory Neil Shapiro 					     ef->ef_name);
126340266059SGregory Neil Shapiro 		first = false;
1264c2aa98e2SPeter Wemm 	}
1265c2aa98e2SPeter Wemm 	if (!first)
126640266059SGregory Neil Shapiro 		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">\n");
1267c2aa98e2SPeter Wemm }
1268