xref: /freebsd/contrib/sendmail/src/envelope.c (revision d0cef73d)
1c2aa98e2SPeter Wemm /*
2d0cef73dSGregory Neil Shapiro  * Copyright (c) 1998-2003, 2006 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 
16d0cef73dSGregory Neil Shapiro SM_RCSID("@(#)$Id: envelope.c,v 8.302 2006/11/10 23:12:52 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 {
784e4196cbSGregory Neil Shapiro 	int sendmode;
794e4196cbSGregory Neil Shapiro 
8040266059SGregory Neil Shapiro 	/*
8140266059SGregory Neil Shapiro 	**  This code used to read:
8240266059SGregory Neil Shapiro 	**	if (e == parent && e->e_parent != NULL)
8340266059SGregory Neil Shapiro 	**		parent = e->e_parent;
8440266059SGregory Neil Shapiro 	**  So if e == parent && e->e_parent == NULL then we would
8540266059SGregory Neil Shapiro 	**  set e->e_parent = e, which creates a loop in the e_parent chain.
8640266059SGregory Neil Shapiro 	**  This meant macvalue() could go into an infinite loop.
8740266059SGregory Neil Shapiro 	*/
8840266059SGregory Neil Shapiro 
894e4196cbSGregory Neil Shapiro 	if (parent != NULL)
904e4196cbSGregory Neil Shapiro 		sendmode = parent->e_sendmode;
914e4196cbSGregory Neil Shapiro 	else
924e4196cbSGregory Neil Shapiro 		sendmode = DM_NOTSET;
934e4196cbSGregory Neil Shapiro 
9440266059SGregory Neil Shapiro 	if (e == parent)
95c2aa98e2SPeter Wemm 		parent = e->e_parent;
9640266059SGregory Neil Shapiro 	clearenvelope(e, true, rpool);
97c2aa98e2SPeter Wemm 	if (e == CurEnv)
9806f25ae9SGregory Neil Shapiro 		memmove((char *) &e->e_from,
9906f25ae9SGregory Neil Shapiro 			(char *) &NullAddress,
100d0cef73dSGregory Neil Shapiro 			sizeof(e->e_from));
101c2aa98e2SPeter Wemm 	else
10206f25ae9SGregory Neil Shapiro 		memmove((char *) &e->e_from,
10306f25ae9SGregory Neil Shapiro 			(char *) &CurEnv->e_from,
104d0cef73dSGregory Neil Shapiro 			sizeof(e->e_from));
105c2aa98e2SPeter Wemm 	e->e_parent = parent;
10606f25ae9SGregory Neil Shapiro 	assign_queueid(e);
107c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
108c2aa98e2SPeter Wemm 	if (parent != NULL)
10940266059SGregory Neil Shapiro 	{
110c2aa98e2SPeter Wemm 		e->e_msgpriority = parent->e_msgsize;
11140266059SGregory Neil Shapiro 		if (parent->e_quarmsg == NULL)
11240266059SGregory Neil Shapiro 		{
11340266059SGregory Neil Shapiro 			e->e_quarmsg = NULL;
11440266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM,
11540266059SGregory Neil Shapiro 				  macid("{quarantine}"), "");
11640266059SGregory Neil Shapiro 		}
11740266059SGregory Neil Shapiro 		else
11840266059SGregory Neil Shapiro 		{
11940266059SGregory Neil Shapiro 			e->e_quarmsg = sm_rpool_strdup_x(rpool,
12040266059SGregory Neil Shapiro 							 parent->e_quarmsg);
12140266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM,
12240266059SGregory Neil Shapiro 				  macid("{quarantine}"), e->e_quarmsg);
12340266059SGregory Neil Shapiro 		}
12440266059SGregory Neil Shapiro 	}
125c2aa98e2SPeter Wemm 	e->e_puthdr = putheader;
126c2aa98e2SPeter Wemm 	e->e_putbody = putbody;
127c2aa98e2SPeter Wemm 	if (CurEnv->e_xfp != NULL)
12840266059SGregory Neil Shapiro 		(void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT);
1294e4196cbSGregory Neil Shapiro 	if (sendmode != DM_NOTSET)
1304e4196cbSGregory Neil Shapiro 		e->e_sendmode = sendmode;
131c2aa98e2SPeter Wemm 
13206f25ae9SGregory Neil Shapiro 	return e;
133c2aa98e2SPeter Wemm }
13440266059SGregory Neil Shapiro 
13540266059SGregory Neil Shapiro /* values for msg_timeout, see also IS_* below for usage (bit layout) */
13640266059SGregory Neil Shapiro #define MSG_T_O		0x01	/* normal timeout */
13740266059SGregory Neil Shapiro #define MSG_T_O_NOW	0x02	/* NOW timeout */
13840266059SGregory Neil Shapiro #define MSG_NOT_BY	0x04	/* Deliver-By time exceeded, mode R */
13940266059SGregory Neil Shapiro #define MSG_WARN	0x10	/* normal queue warning */
14040266059SGregory Neil Shapiro #define MSG_WARN_BY	0x20	/* Deliver-By time exceeded, mode N */
14140266059SGregory Neil Shapiro 
14240266059SGregory Neil Shapiro #define IS_MSG_ERR(x)	(((x) & 0x0f) != 0)	/* return an error */
14340266059SGregory Neil Shapiro 
14440266059SGregory Neil Shapiro /* immediate return */
14540266059SGregory Neil Shapiro #define IS_IMM_RET(x)	(((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0)
14640266059SGregory Neil Shapiro #define IS_MSG_WARN(x)	(((x) & 0xf0) != 0)	/* return a warning */
14740266059SGregory Neil Shapiro 
14840266059SGregory Neil Shapiro /*
149c2aa98e2SPeter Wemm **  DROPENVELOPE -- deallocate an envelope.
150c2aa98e2SPeter Wemm **
151c2aa98e2SPeter Wemm **	Parameters:
152c2aa98e2SPeter Wemm **		e -- the envelope to deallocate.
153c2aa98e2SPeter Wemm **		fulldrop -- if set, do return receipts.
15440266059SGregory Neil Shapiro **		split -- if true, split by recipient if message is queued up
155c2aa98e2SPeter Wemm **
156c2aa98e2SPeter Wemm **	Returns:
157c2aa98e2SPeter Wemm **		none.
158c2aa98e2SPeter Wemm **
159c2aa98e2SPeter Wemm **	Side Effects:
160c2aa98e2SPeter Wemm **		housekeeping necessary to dispose of an envelope.
161c2aa98e2SPeter Wemm **		Unlocks this queue file.
162c2aa98e2SPeter Wemm */
163c2aa98e2SPeter Wemm 
164c2aa98e2SPeter Wemm void
16540266059SGregory Neil Shapiro dropenvelope(e, fulldrop, split)
166c2aa98e2SPeter Wemm 	register ENVELOPE *e;
167c2aa98e2SPeter Wemm 	bool fulldrop;
16840266059SGregory Neil Shapiro 	bool split;
169c2aa98e2SPeter Wemm {
17040266059SGregory Neil Shapiro 	bool panic = false;
17140266059SGregory Neil Shapiro 	bool queueit = false;
17240266059SGregory Neil Shapiro 	int msg_timeout = 0;
17340266059SGregory Neil Shapiro 	bool failure_return = false;
17440266059SGregory Neil Shapiro 	bool delay_return = false;
17540266059SGregory Neil Shapiro 	bool success_return = false;
17606f25ae9SGregory Neil Shapiro 	bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags);
17740266059SGregory Neil Shapiro 	bool done = false;
178c2aa98e2SPeter Wemm 	register ADDRESS *q;
179c2aa98e2SPeter Wemm 	char *id = e->e_id;
180193538b7SGregory Neil Shapiro 	time_t now;
181c2aa98e2SPeter Wemm 	char buf[MAXLINE];
182c2aa98e2SPeter Wemm 
183c2aa98e2SPeter Wemm 	if (tTd(50, 1))
184c2aa98e2SPeter Wemm 	{
18540266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope %p: id=", e);
186e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), e->e_id);
18740266059SGregory Neil Shapiro 		sm_dprintf(", flags=");
188c2aa98e2SPeter Wemm 		printenvflags(e);
189c2aa98e2SPeter Wemm 		if (tTd(50, 10))
190c2aa98e2SPeter Wemm 		{
19140266059SGregory Neil Shapiro 			sm_dprintf("sendq=");
192e92d3f3fSGregory Neil Shapiro 			printaddr(sm_debug_file(), e->e_sendqueue, true);
193c2aa98e2SPeter Wemm 		}
194c2aa98e2SPeter Wemm 	}
195c2aa98e2SPeter Wemm 
196c2aa98e2SPeter Wemm 	if (LogLevel > 84)
197c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, id,
19806f25ae9SGregory Neil Shapiro 			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
19940266059SGregory Neil Shapiro 			  e->e_flags, OpMode, (int) CurrentPid);
200c2aa98e2SPeter Wemm 
201c2aa98e2SPeter Wemm 	/* we must have an id to remove disk files */
202c2aa98e2SPeter Wemm 	if (id == NULL)
203c2aa98e2SPeter Wemm 		return;
204c2aa98e2SPeter Wemm 
205c2aa98e2SPeter Wemm 	/* if verify-only mode, we can skip most of this */
206c2aa98e2SPeter Wemm 	if (OpMode == MD_VERIFY)
207c2aa98e2SPeter Wemm 		goto simpledrop;
208c2aa98e2SPeter Wemm 
209c2aa98e2SPeter Wemm 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
210c2aa98e2SPeter Wemm 		logsender(e, NULL);
211c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_LOGSENDER;
212c2aa98e2SPeter Wemm 
213c2aa98e2SPeter Wemm 	/* post statistics */
214c2aa98e2SPeter Wemm 	poststats(StatFile);
215c2aa98e2SPeter Wemm 
216c2aa98e2SPeter Wemm 	/*
217c2aa98e2SPeter Wemm 	**  Extract state information from dregs of send list.
218c2aa98e2SPeter Wemm 	*/
219c2aa98e2SPeter Wemm 
220193538b7SGregory Neil Shapiro 	now = curtime();
2218774250cSGregory Neil Shapiro 	if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
22240266059SGregory Neil Shapiro 		msg_timeout = MSG_T_O;
22340266059SGregory Neil Shapiro 	if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 &&
22440266059SGregory Neil Shapiro 	    now >= e->e_ctime + e->e_deliver_by &&
22506f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags))
22606f25ae9SGregory Neil Shapiro 	{
22740266059SGregory Neil Shapiro 		msg_timeout = MSG_NOT_BY;
22840266059SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22940266059SGregory Neil Shapiro 	}
23040266059SGregory Neil Shapiro 	else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
23140266059SGregory Neil Shapiro 		 !bitset(EF_RESPONSE, e->e_flags))
23240266059SGregory Neil Shapiro 	{
23340266059SGregory Neil Shapiro 		msg_timeout = MSG_T_O_NOW;
23406f25ae9SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
23506f25ae9SGregory Neil Shapiro 	}
23606f25ae9SGregory Neil Shapiro 
237c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_QUEUERUN;
238c2aa98e2SPeter Wemm 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
239c2aa98e2SPeter Wemm 	{
24006f25ae9SGregory Neil Shapiro 		if (QS_IS_UNDELIVERED(q->q_state))
24140266059SGregory Neil Shapiro 			queueit = true;
242c2aa98e2SPeter Wemm 
243c2aa98e2SPeter Wemm 		/* see if a notification is needed */
244c2aa98e2SPeter Wemm 		if (bitset(QPINGONFAILURE, q->q_flags) &&
24540266059SGregory Neil Shapiro 		    ((IS_MSG_ERR(msg_timeout) &&
24640266059SGregory Neil Shapiro 		      QS_IS_UNDELIVERED(q->q_state)) ||
24706f25ae9SGregory Neil Shapiro 		     QS_IS_BADADDR(q->q_state) ||
24840266059SGregory Neil Shapiro 		     IS_IMM_RET(msg_timeout)))
249c2aa98e2SPeter Wemm 		{
25040266059SGregory Neil Shapiro 			failure_return = true;
25106f25ae9SGregory Neil Shapiro 			if (!done && q->q_owner == NULL &&
25206f25ae9SGregory Neil Shapiro 			    !emptyaddr(&e->e_from))
25306f25ae9SGregory Neil Shapiro 			{
254c2aa98e2SPeter Wemm 				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
255c2aa98e2SPeter Wemm 						  &e->e_errorqueue, 0, e);
25640266059SGregory Neil Shapiro 				done = true;
25706f25ae9SGregory Neil Shapiro 			}
258c2aa98e2SPeter Wemm 		}
25940266059SGregory Neil Shapiro 		else if ((bitset(QPINGONSUCCESS, q->q_flags) &&
26006f25ae9SGregory Neil Shapiro 			  ((QS_IS_SENT(q->q_state) &&
261c2aa98e2SPeter Wemm 			    bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
26240266059SGregory Neil Shapiro 			   bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) ||
26340266059SGregory Neil Shapiro 			  bitset(QBYTRACE, q->q_flags) ||
26440266059SGregory Neil Shapiro 			  bitset(QBYNRELAY, q->q_flags))
265c2aa98e2SPeter Wemm 		{
26640266059SGregory Neil Shapiro 			success_return = true;
267c2aa98e2SPeter Wemm 		}
268c2aa98e2SPeter Wemm 	}
269c2aa98e2SPeter Wemm 
270c2aa98e2SPeter Wemm 	if (e->e_class < 0)
271c2aa98e2SPeter Wemm 		e->e_flags |= EF_NO_BODY_RETN;
272c2aa98e2SPeter Wemm 
273c2aa98e2SPeter Wemm 	/*
274c2aa98e2SPeter Wemm 	**  See if the message timed out.
275c2aa98e2SPeter Wemm 	*/
276c2aa98e2SPeter Wemm 
277c2aa98e2SPeter Wemm 	if (!queueit)
27806f25ae9SGregory Neil Shapiro 		/* EMPTY */
279c2aa98e2SPeter Wemm 		/* nothing to do */ ;
28040266059SGregory Neil Shapiro 	else if (IS_MSG_ERR(msg_timeout))
281c2aa98e2SPeter Wemm 	{
282c2aa98e2SPeter Wemm 		if (failure_return)
283c2aa98e2SPeter Wemm 		{
28440266059SGregory Neil Shapiro 			if (msg_timeout == MSG_NOT_BY)
28540266059SGregory Neil Shapiro 			{
286d0cef73dSGregory Neil Shapiro 				(void) sm_snprintf(buf, sizeof(buf),
28740266059SGregory Neil Shapiro 					"delivery time expired %lds",
28840266059SGregory Neil Shapiro 					e->e_deliver_by);
28940266059SGregory Neil Shapiro 			}
29040266059SGregory Neil Shapiro 			else
29140266059SGregory Neil Shapiro 			{
292d0cef73dSGregory Neil Shapiro 				(void) sm_snprintf(buf, sizeof(buf),
29306f25ae9SGregory Neil Shapiro 					"Cannot send message for %s",
29440266059SGregory Neil Shapiro 					pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
29540266059SGregory Neil Shapiro 						false));
29640266059SGregory Neil Shapiro 			}
29740266059SGregory Neil Shapiro 
29840266059SGregory Neil Shapiro 			/* don't free, allocated from e_rpool */
29940266059SGregory Neil Shapiro 			e->e_message = sm_rpool_strdup_x(e->e_rpool, buf);
300c2aa98e2SPeter Wemm 			message(buf);
301c2aa98e2SPeter Wemm 			e->e_flags |= EF_CLRQUEUE;
302c2aa98e2SPeter Wemm 		}
30340266059SGregory Neil Shapiro 		if (msg_timeout == MSG_NOT_BY)
30440266059SGregory Neil Shapiro 		{
30540266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30640266059SGregory Neil Shapiro 				"Delivery time (%lds) expired\n",
30740266059SGregory Neil Shapiro 				e->e_deliver_by);
30840266059SGregory Neil Shapiro 		}
30940266059SGregory Neil Shapiro 		else
31040266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
31140266059SGregory Neil Shapiro 				"Message could not be delivered for %s\n",
31240266059SGregory Neil Shapiro 				pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
31340266059SGregory Neil Shapiro 					false));
31440266059SGregory Neil Shapiro 		(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
31540266059SGregory Neil Shapiro 			"Message will be deleted from queue\n");
316c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
317c2aa98e2SPeter Wemm 		{
31806f25ae9SGregory Neil Shapiro 			if (QS_IS_UNDELIVERED(q->q_state))
319c2aa98e2SPeter Wemm 			{
32006f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
32140266059SGregory Neil Shapiro 				if (msg_timeout == MSG_NOT_BY)
32240266059SGregory Neil Shapiro 					q->q_status = "5.4.7";
32340266059SGregory Neil Shapiro 				else
324c2aa98e2SPeter Wemm 					q->q_status = "4.4.7";
325c2aa98e2SPeter Wemm 			}
326c2aa98e2SPeter Wemm 		}
327c2aa98e2SPeter Wemm 	}
32840266059SGregory Neil Shapiro 	else
32940266059SGregory Neil Shapiro 	{
33040266059SGregory Neil Shapiro 		if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
33140266059SGregory Neil Shapiro 		    now >= e->e_ctime +
33240266059SGregory Neil Shapiro 				TimeOuts.to_q_warning[e->e_timeoutclass])
33340266059SGregory Neil Shapiro 			msg_timeout = MSG_WARN;
33440266059SGregory Neil Shapiro 		else if (IS_DLVR_NOTIFY(e) &&
33540266059SGregory Neil Shapiro 			 e->e_deliver_by > 0 &&
33640266059SGregory Neil Shapiro 			 now >= e->e_ctime + e->e_deliver_by)
33740266059SGregory Neil Shapiro 			msg_timeout = MSG_WARN_BY;
33840266059SGregory Neil Shapiro 
33940266059SGregory Neil Shapiro 		if (IS_MSG_WARN(msg_timeout))
340c2aa98e2SPeter Wemm 		{
341c2aa98e2SPeter Wemm 			if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
342c2aa98e2SPeter Wemm 			    e->e_class >= 0 &&
343c2aa98e2SPeter Wemm 			    e->e_from.q_paddr != NULL &&
344c2aa98e2SPeter Wemm 			    strcmp(e->e_from.q_paddr, "<>") != 0 &&
34540266059SGregory Neil Shapiro 			    sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
34640266059SGregory Neil Shapiro 			    (strlen(e->e_from.q_paddr) <= 8 ||
34740266059SGregory Neil Shapiro 			     sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8],
34840266059SGregory Neil Shapiro 					   "-request") != 0))
349c2aa98e2SPeter Wemm 			{
35040266059SGregory Neil Shapiro 				for (q = e->e_sendqueue; q != NULL;
35140266059SGregory Neil Shapiro 				     q = q->q_next)
352c2aa98e2SPeter Wemm 				{
35340266059SGregory Neil Shapiro 					if (QS_IS_UNDELIVERED(q->q_state)
35406f25ae9SGregory Neil Shapiro #if _FFR_NODELAYDSN_ON_HOLD
35540266059SGregory Neil Shapiro 					    && !bitnset(M_HOLD,
35640266059SGregory Neil Shapiro 							q->q_mailer->m_flags)
35706f25ae9SGregory Neil Shapiro #endif /* _FFR_NODELAYDSN_ON_HOLD */
35840266059SGregory Neil Shapiro 					   )
35940266059SGregory Neil Shapiro 					{
36040266059SGregory Neil Shapiro 						if (msg_timeout ==
36140266059SGregory Neil Shapiro 						    MSG_WARN_BY &&
36240266059SGregory Neil Shapiro 						    (bitset(QPINGONDELAY,
36340266059SGregory Neil Shapiro 							    q->q_flags) ||
36440266059SGregory Neil Shapiro 						    !bitset(QHASNOTIFY,
36540266059SGregory Neil Shapiro 							    q->q_flags))
36640266059SGregory Neil Shapiro 						   )
36740266059SGregory Neil Shapiro 						{
36840266059SGregory Neil Shapiro 							q->q_flags |= QBYNDELAY;
36940266059SGregory Neil Shapiro 							delay_return = true;
37040266059SGregory Neil Shapiro 						}
37140266059SGregory Neil Shapiro 						if (bitset(QPINGONDELAY,
37240266059SGregory Neil Shapiro 							   q->q_flags))
373c2aa98e2SPeter Wemm 						{
374c2aa98e2SPeter Wemm 							q->q_flags |= QDELAYED;
37540266059SGregory Neil Shapiro 							delay_return = true;
37640266059SGregory Neil Shapiro 						}
377c2aa98e2SPeter Wemm 					}
378c2aa98e2SPeter Wemm 				}
379c2aa98e2SPeter Wemm 			}
380c2aa98e2SPeter Wemm 			if (delay_return)
381c2aa98e2SPeter Wemm 			{
38240266059SGregory Neil Shapiro 				if (msg_timeout == MSG_WARN_BY)
38340266059SGregory Neil Shapiro 				{
384d0cef73dSGregory Neil Shapiro 					(void) sm_snprintf(buf, sizeof(buf),
38540266059SGregory Neil Shapiro 						"Warning: Delivery time (%lds) exceeded",
38640266059SGregory Neil Shapiro 						e->e_deliver_by);
38740266059SGregory Neil Shapiro 				}
38840266059SGregory Neil Shapiro 				else
389d0cef73dSGregory Neil Shapiro 					(void) sm_snprintf(buf, sizeof(buf),
390c2aa98e2SPeter Wemm 						"Warning: could not send message for past %s",
39140266059SGregory Neil Shapiro 						pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
39240266059SGregory Neil Shapiro 							false));
39340266059SGregory Neil Shapiro 
39440266059SGregory Neil Shapiro 				/* don't free, allocated from e_rpool */
39540266059SGregory Neil Shapiro 				e->e_message = sm_rpool_strdup_x(e->e_rpool,
39640266059SGregory Neil Shapiro 								 buf);
397c2aa98e2SPeter Wemm 				message(buf);
398c2aa98e2SPeter Wemm 				e->e_flags |= EF_WARNING;
399c2aa98e2SPeter Wemm 			}
40040266059SGregory Neil Shapiro 			if (msg_timeout == MSG_WARN_BY)
40140266059SGregory Neil Shapiro 			{
40240266059SGregory Neil Shapiro 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
40340266059SGregory Neil Shapiro 					"Warning: Delivery time (%lds) exceeded\n",
40440266059SGregory Neil Shapiro 					e->e_deliver_by);
40540266059SGregory Neil Shapiro 			}
40640266059SGregory Neil Shapiro 			else
40740266059SGregory Neil Shapiro 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
408c2aa98e2SPeter Wemm 					"Warning: message still undelivered after %s\n",
40940266059SGregory Neil Shapiro 					pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
41040266059SGregory Neil Shapiro 					     false));
41140266059SGregory Neil Shapiro 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
41240266059SGregory Neil Shapiro 				      "Will keep trying until message is %s old\n",
41340266059SGregory Neil Shapiro 				      pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
41440266059SGregory Neil Shapiro 					     false));
41540266059SGregory Neil Shapiro 		}
416c2aa98e2SPeter Wemm 	}
417c2aa98e2SPeter Wemm 
418c2aa98e2SPeter Wemm 	if (tTd(50, 2))
41940266059SGregory Neil Shapiro 		sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
420c2aa98e2SPeter Wemm 			failure_return, delay_return, success_return, queueit);
421c2aa98e2SPeter Wemm 
422c2aa98e2SPeter Wemm 	/*
423c2aa98e2SPeter Wemm 	**  If we had some fatal error, but no addresses are marked as
424c2aa98e2SPeter Wemm 	**  bad, mark them _all_ as bad.
425c2aa98e2SPeter Wemm 	*/
426c2aa98e2SPeter Wemm 
427c2aa98e2SPeter Wemm 	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
428c2aa98e2SPeter Wemm 	{
429c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
430c2aa98e2SPeter Wemm 		{
43106f25ae9SGregory Neil Shapiro 			if ((QS_IS_OK(q->q_state) ||
43206f25ae9SGregory Neil Shapiro 			     QS_IS_VERIFIED(q->q_state)) &&
433c2aa98e2SPeter Wemm 			    bitset(QPINGONFAILURE, q->q_flags))
434c2aa98e2SPeter Wemm 			{
43540266059SGregory Neil Shapiro 				failure_return = true;
43606f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
437c2aa98e2SPeter Wemm 			}
438c2aa98e2SPeter Wemm 		}
439c2aa98e2SPeter Wemm 	}
440c2aa98e2SPeter Wemm 
441c2aa98e2SPeter Wemm 	/*
442c2aa98e2SPeter Wemm 	**  Send back return receipts as requested.
443c2aa98e2SPeter Wemm 	*/
444c2aa98e2SPeter Wemm 
445c2aa98e2SPeter Wemm 	if (success_return && !failure_return && !delay_return && fulldrop &&
446c2aa98e2SPeter Wemm 	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
447c2aa98e2SPeter Wemm 	    strcmp(e->e_from.q_paddr, "<>") != 0)
448c2aa98e2SPeter Wemm 	{
449c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
450c2aa98e2SPeter Wemm 
451c2aa98e2SPeter Wemm 		if (tTd(50, 8))
45240266059SGregory Neil Shapiro 			sm_dprintf("dropenvelope(%s): sending return receipt\n",
45306f25ae9SGregory Neil Shapiro 				id);
454c2aa98e2SPeter Wemm 		e->e_flags |= EF_SENDRECEIPT;
455c2aa98e2SPeter Wemm 		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
456c2aa98e2SPeter Wemm 		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
457c2aa98e2SPeter Wemm 	}
458c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_SENDRECEIPT;
459c2aa98e2SPeter Wemm 
460c2aa98e2SPeter Wemm 	/*
461c2aa98e2SPeter Wemm 	**  Arrange to send error messages if there are fatal errors.
462c2aa98e2SPeter Wemm 	*/
463c2aa98e2SPeter Wemm 
464c2aa98e2SPeter Wemm 	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
465c2aa98e2SPeter Wemm 	{
466c2aa98e2SPeter Wemm 		if (tTd(50, 8))
46740266059SGregory Neil Shapiro 			sm_dprintf("dropenvelope(%s): saving mail\n", id);
46840266059SGregory Neil Shapiro 		panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
469c2aa98e2SPeter Wemm 	}
470c2aa98e2SPeter Wemm 
471c2aa98e2SPeter Wemm 	/*
472c2aa98e2SPeter Wemm 	**  Arrange to send warning messages to postmaster as requested.
473c2aa98e2SPeter Wemm 	*/
474c2aa98e2SPeter Wemm 
47506f25ae9SGregory Neil Shapiro 	if ((failure_return || pmnotify) &&
476c2aa98e2SPeter Wemm 	    PostMasterCopy != NULL &&
47706f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags) &&
47806f25ae9SGregory Neil Shapiro 	    e->e_class >= 0)
479c2aa98e2SPeter Wemm 	{
480c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
48106f25ae9SGregory Neil Shapiro 		char pcopy[MAXNAME];
48206f25ae9SGregory Neil Shapiro 
48306f25ae9SGregory Neil Shapiro 		if (failure_return)
48406f25ae9SGregory Neil Shapiro 		{
485d0cef73dSGregory Neil Shapiro 			expand(PostMasterCopy, pcopy, sizeof(pcopy), e);
486c2aa98e2SPeter Wemm 
487c2aa98e2SPeter Wemm 			if (tTd(50, 8))
48840266059SGregory Neil Shapiro 				sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
48906f25ae9SGregory Neil Shapiro 					id, pcopy);
49006f25ae9SGregory Neil Shapiro 			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
49106f25ae9SGregory Neil Shapiro 		}
49206f25ae9SGregory Neil Shapiro 		if (pmnotify)
49306f25ae9SGregory Neil Shapiro 			(void) sendtolist("postmaster", NULLADDR,
49406f25ae9SGregory Neil Shapiro 					  &rlist, 0, e);
49506f25ae9SGregory Neil Shapiro 		(void) returntosender(e->e_message, rlist,
49606f25ae9SGregory Neil Shapiro 				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
497c2aa98e2SPeter Wemm 	}
498c2aa98e2SPeter Wemm 
499c2aa98e2SPeter Wemm 	/*
500c2aa98e2SPeter Wemm 	**  Instantiate or deinstantiate the queue.
501c2aa98e2SPeter Wemm 	*/
502c2aa98e2SPeter Wemm 
503c2aa98e2SPeter Wemm simpledrop:
504c2aa98e2SPeter Wemm 	if (tTd(50, 8))
50540266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
506c2aa98e2SPeter Wemm 			id, queueit);
507c2aa98e2SPeter Wemm 	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
508c2aa98e2SPeter Wemm 	{
509c2aa98e2SPeter Wemm 		if (tTd(50, 1))
510c2aa98e2SPeter Wemm 		{
51140266059SGregory Neil Shapiro 			sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=",
512c2aa98e2SPeter Wemm 				e->e_id, queueit);
513c2aa98e2SPeter Wemm 			printenvflags(e);
514c2aa98e2SPeter Wemm 		}
51540266059SGregory Neil Shapiro 		if (!panic)
516af9557fdSGregory Neil Shapiro 		{
517af9557fdSGregory Neil Shapiro 			if (e->e_dfp != NULL)
518af9557fdSGregory Neil Shapiro 			{
519af9557fdSGregory Neil Shapiro 				(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
520af9557fdSGregory Neil Shapiro 				e->e_dfp = NULL;
521af9557fdSGregory Neil Shapiro 			}
52240266059SGregory Neil Shapiro 			(void) xunlink(queuename(e, DATAFL_LETTER));
523af9557fdSGregory Neil Shapiro 		}
52440266059SGregory Neil Shapiro 		if (panic && QueueMode == QM_LOST)
52540266059SGregory Neil Shapiro 		{
52640266059SGregory Neil Shapiro 			/*
52740266059SGregory Neil Shapiro 			**  leave the Qf file behind as
52840266059SGregory Neil Shapiro 			**  the delivery attempt failed.
52940266059SGregory Neil Shapiro 			*/
53040266059SGregory Neil Shapiro 
53140266059SGregory Neil Shapiro 			/* EMPTY */
53240266059SGregory Neil Shapiro 		}
53340266059SGregory Neil Shapiro 		else
53440266059SGregory Neil Shapiro 		if (xunlink(queuename(e, ANYQFL_LETTER)) == 0)
53540266059SGregory Neil Shapiro 		{
53640266059SGregory Neil Shapiro 			/* add to available space in filesystem */
53713d88268SGregory Neil Shapiro 			updfs(e, -1, panic ? 0 : -1, "dropenvelope");
53840266059SGregory Neil Shapiro 		}
539c2aa98e2SPeter Wemm 
54006f25ae9SGregory Neil Shapiro 		if (e->e_ntries > 0 && LogLevel > 9)
54106f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
54240266059SGregory Neil Shapiro 				  pintvl(curtime() - e->e_ctime, true),
54306f25ae9SGregory Neil Shapiro 				  e->e_ntries);
544c2aa98e2SPeter Wemm 	}
545c2aa98e2SPeter Wemm 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
546c2aa98e2SPeter Wemm 	{
54740266059SGregory Neil Shapiro 		if (!split)
54840266059SGregory Neil Shapiro 			queueup(e, false, true);
54940266059SGregory Neil Shapiro 		else
55040266059SGregory Neil Shapiro 		{
55140266059SGregory Neil Shapiro 			ENVELOPE *oldsib;
55240266059SGregory Neil Shapiro 			ENVELOPE *ee;
55340266059SGregory Neil Shapiro 
55440266059SGregory Neil Shapiro 			/*
55540266059SGregory Neil Shapiro 			**  Save old sibling and set it to NULL to avoid
55640266059SGregory Neil Shapiro 			**  queueing up the same envelopes again.
55740266059SGregory Neil Shapiro 			**  This requires that envelopes in that list have
55840266059SGregory Neil Shapiro 			**  been take care of before (or at some other place).
55940266059SGregory Neil Shapiro 			*/
56040266059SGregory Neil Shapiro 
56140266059SGregory Neil Shapiro 			oldsib = e->e_sibling;
56240266059SGregory Neil Shapiro 			e->e_sibling = NULL;
56340266059SGregory Neil Shapiro 			if (!split_by_recipient(e) &&
56440266059SGregory Neil Shapiro 			    bitset(EF_FATALERRS, e->e_flags))
56540266059SGregory Neil Shapiro 			{
56640266059SGregory Neil Shapiro 				syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d",
56740266059SGregory Neil Shapiro 					e->e_id, queuename(e, DATAFL_LETTER),
56894c01205SGregory Neil Shapiro 					(int) geteuid());
56940266059SGregory Neil Shapiro 			}
57040266059SGregory Neil Shapiro 			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
57140266059SGregory Neil Shapiro 				queueup(ee, false, true);
57240266059SGregory Neil Shapiro 			queueup(e, false, true);
57340266059SGregory Neil Shapiro 
57440266059SGregory Neil Shapiro 			/* clean up */
57540266059SGregory Neil Shapiro 			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
57640266059SGregory Neil Shapiro 			{
57740266059SGregory Neil Shapiro 				/* now unlock the job */
57840266059SGregory Neil Shapiro 				if (tTd(50, 8))
57940266059SGregory Neil Shapiro 					sm_dprintf("dropenvelope(%s): unlocking job\n",
58040266059SGregory Neil Shapiro 						   ee->e_id);
58140266059SGregory Neil Shapiro 				closexscript(ee);
58240266059SGregory Neil Shapiro 				unlockqueue(ee);
58340266059SGregory Neil Shapiro 
58440266059SGregory Neil Shapiro 				/* this envelope is marked unused */
58540266059SGregory Neil Shapiro 				if (ee->e_dfp != NULL)
58640266059SGregory Neil Shapiro 				{
58740266059SGregory Neil Shapiro 					(void) sm_io_close(ee->e_dfp,
58840266059SGregory Neil Shapiro 							   SM_TIME_DEFAULT);
58940266059SGregory Neil Shapiro 					ee->e_dfp = NULL;
59040266059SGregory Neil Shapiro 				}
59140266059SGregory Neil Shapiro 				ee->e_id = NULL;
59240266059SGregory Neil Shapiro 				ee->e_flags &= ~EF_HAS_DF;
59340266059SGregory Neil Shapiro 			}
59440266059SGregory Neil Shapiro 			e->e_sibling = oldsib;
59540266059SGregory Neil Shapiro 		}
596c2aa98e2SPeter Wemm 	}
597c2aa98e2SPeter Wemm 
598c2aa98e2SPeter Wemm 	/* now unlock the job */
599c2aa98e2SPeter Wemm 	if (tTd(50, 8))
60040266059SGregory Neil Shapiro 		sm_dprintf("dropenvelope(%s): unlocking job\n", id);
601c2aa98e2SPeter Wemm 	closexscript(e);
602c2aa98e2SPeter Wemm 	unlockqueue(e);
603c2aa98e2SPeter Wemm 
604c2aa98e2SPeter Wemm 	/* make sure that this envelope is marked unused */
605c2aa98e2SPeter Wemm 	if (e->e_dfp != NULL)
60640266059SGregory Neil Shapiro 	{
60740266059SGregory Neil Shapiro 		(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
608c2aa98e2SPeter Wemm 		e->e_dfp = NULL;
60940266059SGregory Neil Shapiro 	}
610c2aa98e2SPeter Wemm 	e->e_id = NULL;
611c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_HAS_DF;
612c2aa98e2SPeter Wemm }
61340266059SGregory Neil Shapiro /*
614c2aa98e2SPeter Wemm **  CLEARENVELOPE -- clear an envelope without unlocking
615c2aa98e2SPeter Wemm **
616c2aa98e2SPeter Wemm **	This is normally used by a child process to get a clean
617c2aa98e2SPeter Wemm **	envelope without disturbing the parent.
618c2aa98e2SPeter Wemm **
619c2aa98e2SPeter Wemm **	Parameters:
620c2aa98e2SPeter Wemm **		e -- the envelope to clear.
621c2aa98e2SPeter Wemm **		fullclear - if set, the current envelope is total
622c2aa98e2SPeter Wemm **			garbage and should be ignored; otherwise,
623c2aa98e2SPeter Wemm **			release any resources it may indicate.
62440266059SGregory Neil Shapiro **		rpool -- either NULL, or a pointer to a resource pool
62540266059SGregory Neil Shapiro **			from which envelope memory is allocated, and
62640266059SGregory Neil Shapiro **			to which envelope resources are attached.
627c2aa98e2SPeter Wemm **
628c2aa98e2SPeter Wemm **	Returns:
629c2aa98e2SPeter Wemm **		none.
630c2aa98e2SPeter Wemm **
631c2aa98e2SPeter Wemm **	Side Effects:
632c2aa98e2SPeter Wemm **		Closes files associated with the envelope.
633c2aa98e2SPeter Wemm **		Marks the envelope as unallocated.
634c2aa98e2SPeter Wemm */
635c2aa98e2SPeter Wemm 
636c2aa98e2SPeter Wemm void
63740266059SGregory Neil Shapiro clearenvelope(e, fullclear, rpool)
638c2aa98e2SPeter Wemm 	register ENVELOPE *e;
639c2aa98e2SPeter Wemm 	bool fullclear;
64040266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
641c2aa98e2SPeter Wemm {
642c2aa98e2SPeter Wemm 	register HDR *bh;
643c2aa98e2SPeter Wemm 	register HDR **nhp;
644c2aa98e2SPeter Wemm 	extern ENVELOPE BlankEnvelope;
64540266059SGregory Neil Shapiro 	char **p;
646c2aa98e2SPeter Wemm 
647c2aa98e2SPeter Wemm 	if (!fullclear)
648c2aa98e2SPeter Wemm 	{
649c2aa98e2SPeter Wemm 		/* clear out any file information */
650c2aa98e2SPeter Wemm 		if (e->e_xfp != NULL)
65140266059SGregory Neil Shapiro 			(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
652c2aa98e2SPeter Wemm 		if (e->e_dfp != NULL)
65340266059SGregory Neil Shapiro 			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
654c2aa98e2SPeter Wemm 		e->e_xfp = e->e_dfp = NULL;
655c2aa98e2SPeter Wemm 	}
656c2aa98e2SPeter Wemm 
65740266059SGregory Neil Shapiro 	/*
65840266059SGregory Neil Shapiro 	**  Copy BlankEnvelope into *e.
65940266059SGregory Neil Shapiro 	**  It is not safe to simply copy pointers to strings;
66040266059SGregory Neil Shapiro 	**  the strings themselves must be copied (or set to NULL).
66140266059SGregory Neil Shapiro 	**  The problem is that when we assign a new string value to
66240266059SGregory Neil Shapiro 	**  a member of BlankEnvelope, we free the old string.
66340266059SGregory Neil Shapiro 	**  We did not need to do this copying in sendmail 8.11 :-(
66440266059SGregory Neil Shapiro 	**  and it is a potential performance hit.  Reference counted
66540266059SGregory Neil Shapiro 	**  strings are one way out.
66640266059SGregory Neil Shapiro 	*/
66740266059SGregory Neil Shapiro 
66840266059SGregory Neil Shapiro 	*e = BlankEnvelope;
669c2aa98e2SPeter Wemm 	e->e_message = NULL;
67040266059SGregory Neil Shapiro 	e->e_qfletter = '\0';
67140266059SGregory Neil Shapiro 	e->e_quarmsg = NULL;
67240266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
67340266059SGregory Neil Shapiro 
67440266059SGregory Neil Shapiro 	/*
67540266059SGregory Neil Shapiro 	**  Copy the macro table.
67640266059SGregory Neil Shapiro 	**  We might be able to avoid this by zeroing the macro table
67740266059SGregory Neil Shapiro 	**  and always searching BlankEnvelope.e_macro after e->e_macro
67840266059SGregory Neil Shapiro 	**  in macvalue().
67940266059SGregory Neil Shapiro 	*/
68040266059SGregory Neil Shapiro 
68140266059SGregory Neil Shapiro 	for (p = &e->e_macro.mac_table[0];
68240266059SGregory Neil Shapiro 	     p <= &e->e_macro.mac_table[MAXMACROID];
68340266059SGregory Neil Shapiro 	     ++p)
68440266059SGregory Neil Shapiro 	{
68540266059SGregory Neil Shapiro 		if (*p != NULL)
68640266059SGregory Neil Shapiro 			*p = sm_rpool_strdup_x(rpool, *p);
68740266059SGregory Neil Shapiro 	}
68840266059SGregory Neil Shapiro 
68940266059SGregory Neil Shapiro 	/*
69040266059SGregory Neil Shapiro 	**  XXX There are many strings in the envelope structure
69140266059SGregory Neil Shapiro 	**  XXX that we are not attempting to copy here.
69240266059SGregory Neil Shapiro 	**  XXX Investigate this further.
69340266059SGregory Neil Shapiro 	*/
69440266059SGregory Neil Shapiro 
69540266059SGregory Neil Shapiro 	e->e_rpool = rpool;
69640266059SGregory Neil Shapiro 	e->e_macro.mac_rpool = rpool;
697c2aa98e2SPeter Wemm 	if (Verbose)
69806f25ae9SGregory Neil Shapiro 		set_delivery_mode(SM_DELIVER, e);
699c2aa98e2SPeter Wemm 	bh = BlankEnvelope.e_header;
700c2aa98e2SPeter Wemm 	nhp = &e->e_header;
701c2aa98e2SPeter Wemm 	while (bh != NULL)
702c2aa98e2SPeter Wemm 	{
703d0cef73dSGregory Neil Shapiro 		*nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof(*bh));
704d0cef73dSGregory Neil Shapiro 		memmove((char *) *nhp, (char *) bh, sizeof(*bh));
705c2aa98e2SPeter Wemm 		bh = bh->h_link;
706c2aa98e2SPeter Wemm 		nhp = &(*nhp)->h_link;
707c2aa98e2SPeter Wemm 	}
708c2aa98e2SPeter Wemm }
70940266059SGregory Neil Shapiro /*
710c2aa98e2SPeter Wemm **  INITSYS -- initialize instantiation of system
711c2aa98e2SPeter Wemm **
712c2aa98e2SPeter Wemm **	In Daemon mode, this is done in the child.
713c2aa98e2SPeter Wemm **
714c2aa98e2SPeter Wemm **	Parameters:
71506f25ae9SGregory Neil Shapiro **		e -- the envelope to use.
716c2aa98e2SPeter Wemm **
717c2aa98e2SPeter Wemm **	Returns:
718c2aa98e2SPeter Wemm **		none.
719c2aa98e2SPeter Wemm **
720c2aa98e2SPeter Wemm **	Side Effects:
721c2aa98e2SPeter Wemm **		Initializes the system macros, some global variables,
722c2aa98e2SPeter Wemm **		etc.  In particular, the current time in various
723c2aa98e2SPeter Wemm **		forms is set.
724c2aa98e2SPeter Wemm */
725c2aa98e2SPeter Wemm 
726c2aa98e2SPeter Wemm void
727c2aa98e2SPeter Wemm initsys(e)
728c2aa98e2SPeter Wemm 	register ENVELOPE *e;
729c2aa98e2SPeter Wemm {
73040266059SGregory Neil Shapiro 	char buf[10];
731c2aa98e2SPeter Wemm #ifdef TTYNAME
732c2aa98e2SPeter Wemm 	static char ybuf[60];			/* holds tty id */
733c2aa98e2SPeter Wemm 	register char *p;
734c2aa98e2SPeter Wemm 	extern char *ttyname();
735c2aa98e2SPeter Wemm #endif /* TTYNAME */
736c2aa98e2SPeter Wemm 
737c2aa98e2SPeter Wemm 	/*
738c2aa98e2SPeter Wemm 	**  Give this envelope a reality.
739c2aa98e2SPeter Wemm 	**	I.e., an id, a transcript, and a creation time.
74040266059SGregory Neil Shapiro 	**  We don't select the queue until all of the recipients are known.
741c2aa98e2SPeter Wemm 	*/
742c2aa98e2SPeter Wemm 
743c2aa98e2SPeter Wemm 	openxscript(e);
744c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
74540266059SGregory Neil Shapiro 	e->e_qfletter = '\0';
746c2aa98e2SPeter Wemm 
747c2aa98e2SPeter Wemm 	/*
748c2aa98e2SPeter Wemm 	**  Set OutChannel to something useful if stdout isn't it.
749c2aa98e2SPeter Wemm 	**	This arranges that any extra stuff the mailer produces
750c2aa98e2SPeter Wemm 	**	gets sent back to the user on error (because it is
751c2aa98e2SPeter Wemm 	**	tucked away in the transcript).
752c2aa98e2SPeter Wemm 	*/
753c2aa98e2SPeter Wemm 
754c2aa98e2SPeter Wemm 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
755c2aa98e2SPeter Wemm 	    e->e_xfp != NULL)
756c2aa98e2SPeter Wemm 		OutChannel = e->e_xfp;
757c2aa98e2SPeter Wemm 
758c2aa98e2SPeter Wemm 	/*
759c2aa98e2SPeter Wemm 	**  Set up some basic system macros.
760c2aa98e2SPeter Wemm 	*/
761c2aa98e2SPeter Wemm 
762c2aa98e2SPeter Wemm 	/* process id */
763d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof(buf), "%d", (int) CurrentPid);
76440266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'p', buf);
765c2aa98e2SPeter Wemm 
766c2aa98e2SPeter Wemm 	/* hop count */
767d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof(buf), "%d", e->e_hopcount);
76840266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'c', buf);
769c2aa98e2SPeter Wemm 
770c2aa98e2SPeter Wemm 	/* time as integer, unix time, arpa time */
771c2aa98e2SPeter Wemm 	settime(e);
772c2aa98e2SPeter Wemm 
77306f25ae9SGregory Neil Shapiro 	/* Load average */
77440266059SGregory Neil Shapiro 	sm_getla();
77506f25ae9SGregory Neil Shapiro 
776c2aa98e2SPeter Wemm #ifdef TTYNAME
777c2aa98e2SPeter Wemm 	/* tty name */
778c2aa98e2SPeter Wemm 	if (macvalue('y', e) == NULL)
779c2aa98e2SPeter Wemm 	{
780c2aa98e2SPeter Wemm 		p = ttyname(2);
781c2aa98e2SPeter Wemm 		if (p != NULL)
782c2aa98e2SPeter Wemm 		{
783c2aa98e2SPeter Wemm 			if (strrchr(p, '/') != NULL)
784c2aa98e2SPeter Wemm 				p = strrchr(p, '/') + 1;
785d0cef73dSGregory Neil Shapiro 			(void) sm_strlcpy(ybuf, sizeof(ybuf), p);
78640266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM, 'y', ybuf);
787c2aa98e2SPeter Wemm 		}
788c2aa98e2SPeter Wemm 	}
789c2aa98e2SPeter Wemm #endif /* TTYNAME */
790c2aa98e2SPeter Wemm }
79140266059SGregory Neil Shapiro /*
792c2aa98e2SPeter Wemm **  SETTIME -- set the current time.
793c2aa98e2SPeter Wemm **
794c2aa98e2SPeter Wemm **	Parameters:
79506f25ae9SGregory Neil Shapiro **		e -- the envelope in which the macros should be set.
796c2aa98e2SPeter Wemm **
797c2aa98e2SPeter Wemm **	Returns:
798c2aa98e2SPeter Wemm **		none.
799c2aa98e2SPeter Wemm **
800c2aa98e2SPeter Wemm **	Side Effects:
801c2aa98e2SPeter Wemm **		Sets the various time macros -- $a, $b, $d, $t.
802c2aa98e2SPeter Wemm */
803c2aa98e2SPeter Wemm 
804c2aa98e2SPeter Wemm void
805c2aa98e2SPeter Wemm settime(e)
806c2aa98e2SPeter Wemm 	register ENVELOPE *e;
807c2aa98e2SPeter Wemm {
808c2aa98e2SPeter Wemm 	register char *p;
809c2aa98e2SPeter Wemm 	auto time_t now;
81040266059SGregory Neil Shapiro 	char buf[30];
811c2aa98e2SPeter Wemm 	register struct tm *tm;
812c2aa98e2SPeter Wemm 
813c2aa98e2SPeter Wemm 	now = curtime();
814d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof(buf), "%ld", (long) now);
815e92d3f3fSGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf);
816c2aa98e2SPeter Wemm 	tm = gmtime(&now);
817d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d",
81840266059SGregory Neil Shapiro 			   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
81940266059SGregory Neil Shapiro 			   tm->tm_hour, tm->tm_min);
82040266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 't', buf);
821d0cef73dSGregory Neil Shapiro 	(void) sm_strlcpy(buf, ctime(&now), sizeof(buf));
82240266059SGregory Neil Shapiro 	p = strchr(buf, '\n');
823c2aa98e2SPeter Wemm 	if (p != NULL)
824c2aa98e2SPeter Wemm 		*p = '\0';
82540266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'd', buf);
82640266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf));
827c2aa98e2SPeter Wemm 	if (macvalue('a', e) == NULL)
82840266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e));
829c2aa98e2SPeter Wemm }
83040266059SGregory Neil Shapiro /*
831c2aa98e2SPeter Wemm **  OPENXSCRIPT -- Open transcript file
832c2aa98e2SPeter Wemm **
833c2aa98e2SPeter Wemm **	Creates a transcript file for possible eventual mailing or
834c2aa98e2SPeter Wemm **	sending back.
835c2aa98e2SPeter Wemm **
836c2aa98e2SPeter Wemm **	Parameters:
837c2aa98e2SPeter Wemm **		e -- the envelope to create the transcript in/for.
838c2aa98e2SPeter Wemm **
839c2aa98e2SPeter Wemm **	Returns:
840c2aa98e2SPeter Wemm **		none
841c2aa98e2SPeter Wemm **
842c2aa98e2SPeter Wemm **	Side Effects:
843c2aa98e2SPeter Wemm **		Creates the transcript file.
844c2aa98e2SPeter Wemm */
845c2aa98e2SPeter Wemm 
846c2aa98e2SPeter Wemm #ifndef O_APPEND
847c2aa98e2SPeter Wemm # define O_APPEND	0
84806f25ae9SGregory Neil Shapiro #endif /* ! O_APPEND */
849c2aa98e2SPeter Wemm 
850c2aa98e2SPeter Wemm void
851c2aa98e2SPeter Wemm openxscript(e)
852c2aa98e2SPeter Wemm 	register ENVELOPE *e;
853c2aa98e2SPeter Wemm {
854c2aa98e2SPeter Wemm 	register char *p;
855c2aa98e2SPeter Wemm 
856c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
857c2aa98e2SPeter Wemm 		return;
85806f25ae9SGregory Neil Shapiro 
85906f25ae9SGregory Neil Shapiro #if 0
86006f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
86106f25ae9SGregory Neil Shapiro 		syserr("openxscript: job not locked");
86206f25ae9SGregory Neil Shapiro #endif /* 0 */
86306f25ae9SGregory Neil Shapiro 
86440266059SGregory Neil Shapiro 	p = queuename(e, XSCRPT_LETTER);
86506f25ae9SGregory Neil Shapiro 	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
86606f25ae9SGregory Neil Shapiro 			  SFF_NOTEXCL|SFF_OPENASROOT);
86706f25ae9SGregory Neil Shapiro 
86806f25ae9SGregory Neil Shapiro 	if (e->e_xfp == NULL)
869c2aa98e2SPeter Wemm 	{
870c2aa98e2SPeter Wemm 		syserr("Can't create transcript file %s", p);
87140266059SGregory Neil Shapiro 		e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
87240266059SGregory Neil Shapiro 				      SM_PATH_DEVNULL, SM_IO_RDWR, NULL);
87306f25ae9SGregory Neil Shapiro 		if (e->e_xfp == NULL)
87440266059SGregory Neil Shapiro 			syserr("!Can't open %s", SM_PATH_DEVNULL);
875c2aa98e2SPeter Wemm 	}
87640266059SGregory Neil Shapiro 	(void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0);
877c2aa98e2SPeter Wemm 	if (tTd(46, 9))
878c2aa98e2SPeter Wemm 	{
87940266059SGregory Neil Shapiro 		sm_dprintf("openxscript(%s):\n  ", p);
88040266059SGregory Neil Shapiro 		dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true,
88140266059SGregory Neil Shapiro 		       false);
882c2aa98e2SPeter Wemm 	}
883c2aa98e2SPeter Wemm }
88440266059SGregory Neil Shapiro /*
885c2aa98e2SPeter Wemm **  CLOSEXSCRIPT -- close the transcript file.
886c2aa98e2SPeter Wemm **
887c2aa98e2SPeter Wemm **	Parameters:
888c2aa98e2SPeter Wemm **		e -- the envelope containing the transcript to close.
889c2aa98e2SPeter Wemm **
890c2aa98e2SPeter Wemm **	Returns:
891c2aa98e2SPeter Wemm **		none.
892c2aa98e2SPeter Wemm **
893c2aa98e2SPeter Wemm **	Side Effects:
894c2aa98e2SPeter Wemm **		none.
895c2aa98e2SPeter Wemm */
896c2aa98e2SPeter Wemm 
897c2aa98e2SPeter Wemm void
898c2aa98e2SPeter Wemm closexscript(e)
899c2aa98e2SPeter Wemm 	register ENVELOPE *e;
900c2aa98e2SPeter Wemm {
901c2aa98e2SPeter Wemm 	if (e->e_xfp == NULL)
902c2aa98e2SPeter Wemm 		return;
90306f25ae9SGregory Neil Shapiro #if 0
90406f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL)
90506f25ae9SGregory Neil Shapiro 		syserr("closexscript: job not locked");
90606f25ae9SGregory Neil Shapiro #endif /* 0 */
90740266059SGregory Neil Shapiro 	(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
908c2aa98e2SPeter Wemm 	e->e_xfp = NULL;
909c2aa98e2SPeter Wemm }
91040266059SGregory Neil Shapiro /*
911c2aa98e2SPeter Wemm **  SETSENDER -- set the person who this message is from
912c2aa98e2SPeter Wemm **
913c2aa98e2SPeter Wemm **	Under certain circumstances allow the user to say who
914c2aa98e2SPeter Wemm **	s/he is (using -f or -r).  These are:
915c2aa98e2SPeter Wemm **	1.  The user's uid is zero (root).
916c2aa98e2SPeter Wemm **	2.  The user's login name is in an approved list (typically
917c2aa98e2SPeter Wemm **	    from a network server).
918c2aa98e2SPeter Wemm **	3.  The address the user is trying to claim has a
919c2aa98e2SPeter Wemm **	    "!" character in it (since #2 doesn't do it for
920c2aa98e2SPeter Wemm **	    us if we are dialing out for UUCP).
921c2aa98e2SPeter Wemm **	A better check to replace #3 would be if the
922c2aa98e2SPeter Wemm **	effective uid is "UUCP" -- this would require me
923c2aa98e2SPeter Wemm **	to rewrite getpwent to "grab" uucp as it went by,
924c2aa98e2SPeter Wemm **	make getname more nasty, do another passwd file
925c2aa98e2SPeter Wemm **	scan, or compile the UID of "UUCP" into the code,
926c2aa98e2SPeter Wemm **	all of which are reprehensible.
927c2aa98e2SPeter Wemm **
928c2aa98e2SPeter Wemm **	Assuming all of these fail, we figure out something
929c2aa98e2SPeter Wemm **	ourselves.
930c2aa98e2SPeter Wemm **
931c2aa98e2SPeter Wemm **	Parameters:
932c2aa98e2SPeter Wemm **		from -- the person we would like to believe this message
933c2aa98e2SPeter Wemm **			is from, as specified on the command line.
934c2aa98e2SPeter Wemm **		e -- the envelope in which we would like the sender set.
935c2aa98e2SPeter Wemm **		delimptr -- if non-NULL, set to the location of the
936c2aa98e2SPeter Wemm **			trailing delimiter.
937c2aa98e2SPeter Wemm **		delimchar -- the character that will delimit the sender
938c2aa98e2SPeter Wemm **			address.
939c2aa98e2SPeter Wemm **		internal -- set if this address is coming from an internal
940c2aa98e2SPeter Wemm **			source such as an owner alias.
941c2aa98e2SPeter Wemm **
942c2aa98e2SPeter Wemm **	Returns:
943c2aa98e2SPeter Wemm **		none.
944c2aa98e2SPeter Wemm **
945c2aa98e2SPeter Wemm **	Side Effects:
946c2aa98e2SPeter Wemm **		sets sendmail's notion of who the from person is.
947c2aa98e2SPeter Wemm */
948c2aa98e2SPeter Wemm 
949c2aa98e2SPeter Wemm void
950c2aa98e2SPeter Wemm setsender(from, e, delimptr, delimchar, internal)
951c2aa98e2SPeter Wemm 	char *from;
952c2aa98e2SPeter Wemm 	register ENVELOPE *e;
953c2aa98e2SPeter Wemm 	char **delimptr;
954c2aa98e2SPeter Wemm 	int delimchar;
955c2aa98e2SPeter Wemm 	bool internal;
956c2aa98e2SPeter Wemm {
957c2aa98e2SPeter Wemm 	register char **pvp;
958c2aa98e2SPeter Wemm 	char *realname = NULL;
959c2aa98e2SPeter Wemm 	char *bp;
960c2aa98e2SPeter Wemm 	char buf[MAXNAME + 2];
961c2aa98e2SPeter Wemm 	char pvpbuf[PSBUFSIZE];
962c2aa98e2SPeter Wemm 	extern char *FullName;
963c2aa98e2SPeter Wemm 
964c2aa98e2SPeter Wemm 	if (tTd(45, 1))
96540266059SGregory Neil Shapiro 		sm_dprintf("setsender(%s)\n", from == NULL ? "" : from);
966c2aa98e2SPeter Wemm 
96713bd1963SGregory Neil Shapiro 	/* may be set from earlier calls */
96813bd1963SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'x', "");
96913bd1963SGregory Neil Shapiro 
970c2aa98e2SPeter Wemm 	/*
971c2aa98e2SPeter Wemm 	**  Figure out the real user executing us.
972c2aa98e2SPeter Wemm 	**	Username can return errno != 0 on non-errors.
973c2aa98e2SPeter Wemm 	*/
974c2aa98e2SPeter Wemm 
975c2aa98e2SPeter Wemm 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
976c2aa98e2SPeter Wemm 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
977c2aa98e2SPeter Wemm 		realname = from;
978c2aa98e2SPeter Wemm 	if (realname == NULL || realname[0] == '\0')
979c2aa98e2SPeter Wemm 		realname = username();
980c2aa98e2SPeter Wemm 
981c2aa98e2SPeter Wemm 	if (ConfigLevel < 2)
98240266059SGregory Neil Shapiro 		SuprErrs = true;
983c2aa98e2SPeter Wemm 
98440266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
98540266059SGregory Neil Shapiro 
98606f25ae9SGregory Neil Shapiro 	/* preset state for then clause in case from == NULL */
98706f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_BADADDR;
98806f25ae9SGregory Neil Shapiro 	e->e_from.q_flags = 0;
989c2aa98e2SPeter Wemm 	if (from == NULL ||
990c2aa98e2SPeter Wemm 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
99140266059SGregory Neil Shapiro 		      delimchar, delimptr, e, false) == NULL ||
99206f25ae9SGregory Neil Shapiro 	    QS_IS_BADADDR(e->e_from.q_state) ||
993c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == ProgMailer ||
994c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == FileMailer ||
995c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == InclMailer)
996c2aa98e2SPeter Wemm 	{
997c2aa98e2SPeter Wemm 		/* log garbage addresses for traceback */
998c2aa98e2SPeter Wemm 		if (from != NULL && LogLevel > 2)
999c2aa98e2SPeter Wemm 		{
1000c2aa98e2SPeter Wemm 			char *p;
1001c2aa98e2SPeter Wemm 			char ebuf[MAXNAME * 2 + 2];
1002c2aa98e2SPeter Wemm 
1003c2aa98e2SPeter Wemm 			p = macvalue('_', e);
1004c2aa98e2SPeter Wemm 			if (p == NULL)
1005c2aa98e2SPeter Wemm 			{
1006c2aa98e2SPeter Wemm 				char *host = RealHostName;
1007c2aa98e2SPeter Wemm 
1008c2aa98e2SPeter Wemm 				if (host == NULL)
1009c2aa98e2SPeter Wemm 					host = MyHostName;
1010d0cef73dSGregory Neil Shapiro 				(void) sm_snprintf(ebuf, sizeof(ebuf),
101140266059SGregory Neil Shapiro 						   "%.*s@%.*s", MAXNAME,
101240266059SGregory Neil Shapiro 						   realname, MAXNAME, host);
1013c2aa98e2SPeter Wemm 				p = ebuf;
1014c2aa98e2SPeter Wemm 			}
1015c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
101606f25ae9SGregory Neil Shapiro 				  "setsender: %s: invalid or unparsable, received from %s",
1017c2aa98e2SPeter Wemm 				  shortenstring(from, 83), p);
1018c2aa98e2SPeter Wemm 		}
1019c2aa98e2SPeter Wemm 		if (from != NULL)
1020c2aa98e2SPeter Wemm 		{
102106f25ae9SGregory Neil Shapiro 			if (!QS_IS_BADADDR(e->e_from.q_state))
1022c2aa98e2SPeter Wemm 			{
1023c2aa98e2SPeter Wemm 				/* it was a bogus mailer in the from addr */
1024c2aa98e2SPeter Wemm 				e->e_status = "5.1.7";
102506f25ae9SGregory Neil Shapiro 				usrerrenh(e->e_status,
102606f25ae9SGregory Neil Shapiro 					  "553 Invalid sender address");
1027c2aa98e2SPeter Wemm 			}
102840266059SGregory Neil Shapiro 			SuprErrs = true;
1029c2aa98e2SPeter Wemm 		}
1030c2aa98e2SPeter Wemm 		if (from == realname ||
103140266059SGregory Neil Shapiro 		    parseaddr(from = realname,
103240266059SGregory Neil Shapiro 			      &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ',
103340266059SGregory Neil Shapiro 			      NULL, e, false) == NULL)
1034c2aa98e2SPeter Wemm 		{
1035c2aa98e2SPeter Wemm 			char nbuf[100];
1036c2aa98e2SPeter Wemm 
103740266059SGregory Neil Shapiro 			SuprErrs = true;
1038d0cef73dSGregory Neil Shapiro 			expand("\201n", nbuf, sizeof(nbuf), e);
103940266059SGregory Neil Shapiro 			from = sm_rpool_strdup_x(e->e_rpool, nbuf);
104040266059SGregory Neil Shapiro 			if (parseaddr(from, &e->e_from, RF_COPYALL, ' ',
104140266059SGregory Neil Shapiro 				      NULL, e, false) == NULL &&
1042c2aa98e2SPeter Wemm 			    parseaddr(from = "postmaster", &e->e_from,
104340266059SGregory Neil Shapiro 				      RF_COPYALL, ' ', NULL, e, false) == NULL)
104406f25ae9SGregory Neil Shapiro 				syserr("553 5.3.0 setsender: can't even parse postmaster!");
1045c2aa98e2SPeter Wemm 		}
1046c2aa98e2SPeter Wemm 	}
1047c2aa98e2SPeter Wemm 	else
104840266059SGregory Neil Shapiro 		FromFlag = true;
104906f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_SENDER;
1050c2aa98e2SPeter Wemm 	if (tTd(45, 5))
1051c2aa98e2SPeter Wemm 	{
105240266059SGregory Neil Shapiro 		sm_dprintf("setsender: QS_SENDER ");
1053e92d3f3fSGregory Neil Shapiro 		printaddr(sm_debug_file(), &e->e_from, false);
1054c2aa98e2SPeter Wemm 	}
105540266059SGregory Neil Shapiro 	SuprErrs = false;
1056c2aa98e2SPeter Wemm 
1057c2aa98e2SPeter Wemm #if USERDB
1058c2aa98e2SPeter Wemm 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
1059c2aa98e2SPeter Wemm 	{
1060c2aa98e2SPeter Wemm 		register char *p;
1061c2aa98e2SPeter Wemm 
106240266059SGregory Neil Shapiro 		p = udbsender(e->e_from.q_user, e->e_rpool);
1063c2aa98e2SPeter Wemm 		if (p != NULL)
1064c2aa98e2SPeter Wemm 			from = p;
1065c2aa98e2SPeter Wemm 	}
1066c2aa98e2SPeter Wemm #endif /* USERDB */
1067c2aa98e2SPeter Wemm 
1068c2aa98e2SPeter Wemm 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
1069c2aa98e2SPeter Wemm 	{
107040266059SGregory Neil Shapiro 		SM_MBDB_T user;
107140266059SGregory Neil Shapiro 
1072c2aa98e2SPeter Wemm 		if (!internal)
1073c2aa98e2SPeter Wemm 		{
1074c2aa98e2SPeter Wemm 			/* if the user already given fullname don't redefine */
1075c2aa98e2SPeter Wemm 			if (FullName == NULL)
1076c2aa98e2SPeter Wemm 				FullName = macvalue('x', e);
1077605302a5SGregory Neil Shapiro 			if (FullName != NULL)
1078605302a5SGregory Neil Shapiro 			{
1079605302a5SGregory Neil Shapiro 				if (FullName[0] == '\0')
1080c2aa98e2SPeter Wemm 					FullName = NULL;
1081605302a5SGregory Neil Shapiro 				else
1082605302a5SGregory Neil Shapiro 					FullName = newstr(FullName);
1083605302a5SGregory Neil Shapiro 			}
1084c2aa98e2SPeter Wemm 		}
1085c2aa98e2SPeter Wemm 
1086c2aa98e2SPeter Wemm 		if (e->e_from.q_user[0] != '\0' &&
108740266059SGregory Neil Shapiro 		    sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK)
1088c2aa98e2SPeter Wemm 		{
1089c2aa98e2SPeter Wemm 			/*
1090c2aa98e2SPeter Wemm 			**  Process passwd file entry.
1091c2aa98e2SPeter Wemm 			*/
1092c2aa98e2SPeter Wemm 
1093c2aa98e2SPeter Wemm 			/* extract home directory */
109440266059SGregory Neil Shapiro 			if (*user.mbdb_homedir == '\0')
109542e5d165SGregory Neil Shapiro 				e->e_from.q_home = NULL;
109640266059SGregory Neil Shapiro 			else if (strcmp(user.mbdb_homedir, "/") == 0)
109740266059SGregory Neil Shapiro 				e->e_from.q_home = "";
1098c2aa98e2SPeter Wemm 			else
109940266059SGregory Neil Shapiro 				e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool,
110040266059SGregory Neil Shapiro 							user.mbdb_homedir);
110140266059SGregory Neil Shapiro 			macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home);
1102c2aa98e2SPeter Wemm 
1103c2aa98e2SPeter Wemm 			/* extract user and group id */
110440266059SGregory Neil Shapiro 			if (user.mbdb_uid != SM_NO_UID)
110540266059SGregory Neil Shapiro 			{
110640266059SGregory Neil Shapiro 				e->e_from.q_uid = user.mbdb_uid;
110740266059SGregory Neil Shapiro 				e->e_from.q_gid = user.mbdb_gid;
1108c2aa98e2SPeter Wemm 				e->e_from.q_flags |= QGOODUID;
110940266059SGregory Neil Shapiro 			}
1110c2aa98e2SPeter Wemm 
1111c2aa98e2SPeter Wemm 			/* extract full name from passwd file */
111240266059SGregory Neil Shapiro 			if (FullName == NULL && !internal &&
111340266059SGregory Neil Shapiro 			    user.mbdb_fullname[0] != '\0' &&
111440266059SGregory Neil Shapiro 			    strcmp(user.mbdb_name, e->e_from.q_user) == 0)
1115c2aa98e2SPeter Wemm 			{
111640266059SGregory Neil Shapiro 				FullName = newstr(user.mbdb_fullname);
1117c2aa98e2SPeter Wemm 			}
1118c2aa98e2SPeter Wemm 		}
1119c2aa98e2SPeter Wemm 		else
1120c2aa98e2SPeter Wemm 		{
112106f25ae9SGregory Neil Shapiro 			e->e_from.q_home = NULL;
1122c2aa98e2SPeter Wemm 		}
1123c2aa98e2SPeter Wemm 		if (FullName != NULL && !internal)
112413bd1963SGregory Neil Shapiro 			macdefine(&e->e_macro, A_TEMP, 'x', FullName);
1125c2aa98e2SPeter Wemm 	}
11262e43090eSPeter Wemm 	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
1127c2aa98e2SPeter Wemm 	{
1128c2aa98e2SPeter Wemm 		if (e->e_from.q_home == NULL)
1129c2aa98e2SPeter Wemm 		{
1130c2aa98e2SPeter Wemm 			e->e_from.q_home = getenv("HOME");
113142e5d165SGregory Neil Shapiro 			if (e->e_from.q_home != NULL)
113242e5d165SGregory Neil Shapiro 			{
113342e5d165SGregory Neil Shapiro 				if (*e->e_from.q_home == '\0')
113442e5d165SGregory Neil Shapiro 					e->e_from.q_home = NULL;
113542e5d165SGregory Neil Shapiro 				else if (strcmp(e->e_from.q_home, "/") == 0)
1136c2aa98e2SPeter Wemm 					e->e_from.q_home++;
1137c2aa98e2SPeter Wemm 			}
113842e5d165SGregory Neil Shapiro 		}
1139c2aa98e2SPeter Wemm 		e->e_from.q_uid = RealUid;
1140c2aa98e2SPeter Wemm 		e->e_from.q_gid = RealGid;
1141c2aa98e2SPeter Wemm 		e->e_from.q_flags |= QGOODUID;
1142c2aa98e2SPeter Wemm 	}
1143c2aa98e2SPeter Wemm 
1144c2aa98e2SPeter Wemm 	/*
1145c2aa98e2SPeter Wemm 	**  Rewrite the from person to dispose of possible implicit
1146c2aa98e2SPeter Wemm 	**	links in the net.
1147c2aa98e2SPeter Wemm 	*/
1148c2aa98e2SPeter Wemm 
1149d0cef73dSGregory Neil Shapiro 	pvp = prescan(from, delimchar, pvpbuf, sizeof(pvpbuf), NULL,
1150d0cef73dSGregory Neil Shapiro 			IntTokenTab, false);
1151c2aa98e2SPeter Wemm 	if (pvp == NULL)
1152c2aa98e2SPeter Wemm 	{
1153c2aa98e2SPeter Wemm 		/* don't need to give error -- prescan did that already */
1154c2aa98e2SPeter Wemm 		if (LogLevel > 2)
1155c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
1156c2aa98e2SPeter Wemm 				  "cannot prescan from (%s)",
1157c2aa98e2SPeter Wemm 				  shortenstring(from, MAXSHORTSTR));
115840266059SGregory Neil Shapiro 		finis(true, true, ExitStat);
1159c2aa98e2SPeter Wemm 	}
116040266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 3, e);
116140266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 1, e);
116240266059SGregory Neil Shapiro 	(void) REWRITE(pvp, 4, e);
116340266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
1164c2aa98e2SPeter Wemm 	bp = buf + 1;
1165d0cef73dSGregory Neil Shapiro 	cataddr(pvp, NULL, bp, sizeof(buf) - 2, '\0', false);
1166c2aa98e2SPeter Wemm 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
1167c2aa98e2SPeter Wemm 	{
1168c2aa98e2SPeter Wemm 		/* heuristic: route-addr: add angle brackets */
1169d0cef73dSGregory Neil Shapiro 		(void) sm_strlcat(bp, ">", sizeof(buf) - 1);
1170c2aa98e2SPeter Wemm 		*--bp = '<';
1171c2aa98e2SPeter Wemm 	}
117240266059SGregory Neil Shapiro 	e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp);
117340266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
1174c2aa98e2SPeter Wemm 
1175c2aa98e2SPeter Wemm 	/* save the domain spec if this mailer wants it */
1176c2aa98e2SPeter Wemm 	if (e->e_from.q_mailer != NULL &&
1177c2aa98e2SPeter Wemm 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
1178c2aa98e2SPeter Wemm 	{
1179c2aa98e2SPeter Wemm 		char **lastat;
1180c2aa98e2SPeter Wemm 
1181c2aa98e2SPeter Wemm 		/* get rid of any pesky angle brackets */
118240266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
118340266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 3, e);
118440266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 1, e);
118540266059SGregory Neil Shapiro 		(void) REWRITE(pvp, 4, e);
118640266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
1187c2aa98e2SPeter Wemm 
1188c2aa98e2SPeter Wemm 		/* strip off to the last "@" sign */
1189c2aa98e2SPeter Wemm 		for (lastat = NULL; *pvp != NULL; pvp++)
1190e92d3f3fSGregory Neil Shapiro 		{
1191c2aa98e2SPeter Wemm 			if (strcmp(*pvp, "@") == 0)
1192c2aa98e2SPeter Wemm 				lastat = pvp;
1193e92d3f3fSGregory Neil Shapiro 		}
1194c2aa98e2SPeter Wemm 		if (lastat != NULL)
1195c2aa98e2SPeter Wemm 		{
119640266059SGregory Neil Shapiro 			e->e_fromdomain = copyplist(lastat, true, e->e_rpool);
1197c2aa98e2SPeter Wemm 			if (tTd(45, 3))
1198c2aa98e2SPeter Wemm 			{
119940266059SGregory Neil Shapiro 				sm_dprintf("Saving from domain: ");
1200e92d3f3fSGregory Neil Shapiro 				printav(sm_debug_file(), e->e_fromdomain);
1201c2aa98e2SPeter Wemm 			}
1202c2aa98e2SPeter Wemm 		}
1203c2aa98e2SPeter Wemm 	}
1204c2aa98e2SPeter Wemm }
120540266059SGregory Neil Shapiro /*
1206c2aa98e2SPeter Wemm **  PRINTENVFLAGS -- print envelope flags for debugging
1207c2aa98e2SPeter Wemm **
1208c2aa98e2SPeter Wemm **	Parameters:
1209c2aa98e2SPeter Wemm **		e -- the envelope with the flags to be printed.
1210c2aa98e2SPeter Wemm **
1211c2aa98e2SPeter Wemm **	Returns:
1212c2aa98e2SPeter Wemm **		none.
1213c2aa98e2SPeter Wemm */
1214c2aa98e2SPeter Wemm 
1215c2aa98e2SPeter Wemm struct eflags
1216c2aa98e2SPeter Wemm {
1217c2aa98e2SPeter Wemm 	char		*ef_name;
121840266059SGregory Neil Shapiro 	unsigned long	ef_bit;
1219c2aa98e2SPeter Wemm };
1220c2aa98e2SPeter Wemm 
122106f25ae9SGregory Neil Shapiro static struct eflags	EnvelopeFlags[] =
1222c2aa98e2SPeter Wemm {
1223c2aa98e2SPeter Wemm 	{ "OLDSTYLE",		EF_OLDSTYLE	},
1224c2aa98e2SPeter Wemm 	{ "INQUEUE",		EF_INQUEUE	},
1225c2aa98e2SPeter Wemm 	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
1226c2aa98e2SPeter Wemm 	{ "CLRQUEUE",		EF_CLRQUEUE	},
1227c2aa98e2SPeter Wemm 	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
1228c2aa98e2SPeter Wemm 	{ "FATALERRS",		EF_FATALERRS	},
1229c2aa98e2SPeter Wemm 	{ "DELETE_BCC",		EF_DELETE_BCC	},
1230c2aa98e2SPeter Wemm 	{ "RESPONSE",		EF_RESPONSE	},
1231c2aa98e2SPeter Wemm 	{ "RESENT",		EF_RESENT	},
1232c2aa98e2SPeter Wemm 	{ "VRFYONLY",		EF_VRFYONLY	},
1233c2aa98e2SPeter Wemm 	{ "WARNING",		EF_WARNING	},
1234c2aa98e2SPeter Wemm 	{ "QUEUERUN",		EF_QUEUERUN	},
1235c2aa98e2SPeter Wemm 	{ "GLOBALERRS",		EF_GLOBALERRS	},
1236c2aa98e2SPeter Wemm 	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
1237c2aa98e2SPeter Wemm 	{ "METOO",		EF_METOO	},
1238c2aa98e2SPeter Wemm 	{ "LOGSENDER",		EF_LOGSENDER	},
1239c2aa98e2SPeter Wemm 	{ "NORECEIPT",		EF_NORECEIPT	},
1240c2aa98e2SPeter Wemm 	{ "HAS8BIT",		EF_HAS8BIT	},
1241c2aa98e2SPeter Wemm 	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
1242c2aa98e2SPeter Wemm 	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
1243c2aa98e2SPeter Wemm 	{ "RET_PARAM",		EF_RET_PARAM	},
1244c2aa98e2SPeter Wemm 	{ "HAS_DF",		EF_HAS_DF	},
1245c2aa98e2SPeter Wemm 	{ "IS_MIME",		EF_IS_MIME	},
1246c2aa98e2SPeter Wemm 	{ "DONT_MIME",		EF_DONT_MIME	},
124740266059SGregory Neil Shapiro 	{ "DISCARD",		EF_DISCARD	},
124840266059SGregory Neil Shapiro 	{ "TOOBIG",		EF_TOOBIG	},
124940266059SGregory Neil Shapiro 	{ "SPLIT",		EF_SPLIT	},
125040266059SGregory Neil Shapiro 	{ "UNSAFE",		EF_UNSAFE	},
1251193538b7SGregory Neil Shapiro 	{ NULL,			0		}
1252c2aa98e2SPeter Wemm };
1253c2aa98e2SPeter Wemm 
1254c2aa98e2SPeter Wemm void
1255c2aa98e2SPeter Wemm printenvflags(e)
1256c2aa98e2SPeter Wemm 	register ENVELOPE *e;
1257c2aa98e2SPeter Wemm {
1258c2aa98e2SPeter Wemm 	register struct eflags *ef;
125940266059SGregory Neil Shapiro 	bool first = true;
1260c2aa98e2SPeter Wemm 
1261e92d3f3fSGregory Neil Shapiro 	sm_dprintf("%lx", e->e_flags);
1262c2aa98e2SPeter Wemm 	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
1263c2aa98e2SPeter Wemm 	{
1264c2aa98e2SPeter Wemm 		if (!bitset(ef->ef_bit, e->e_flags))
1265c2aa98e2SPeter Wemm 			continue;
1266c2aa98e2SPeter Wemm 		if (first)
1267e92d3f3fSGregory Neil Shapiro 			sm_dprintf("<%s", ef->ef_name);
1268c2aa98e2SPeter Wemm 		else
1269e92d3f3fSGregory Neil Shapiro 			sm_dprintf(",%s", ef->ef_name);
127040266059SGregory Neil Shapiro 		first = false;
1271c2aa98e2SPeter Wemm 	}
1272c2aa98e2SPeter Wemm 	if (!first)
1273e92d3f3fSGregory Neil Shapiro 		sm_dprintf(">\n");
1274c2aa98e2SPeter Wemm }
1275