xref: /freebsd/contrib/sendmail/src/envelope.c (revision 06f25ae9f1d6020a600a10f713046203d1a82570)
1c2aa98e2SPeter Wemm /*
206f25ae9SGregory Neil Shapiro  * Copyright (c) 1998-2000 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 
14c2aa98e2SPeter Wemm #ifndef lint
1506f25ae9SGregory Neil Shapiro static char id[] = "@(#)$Id: envelope.c,v 8.180.14.3 2000/06/29 05:30:23 gshapiro Exp $";
1606f25ae9SGregory Neil Shapiro #endif /* ! lint */
17c2aa98e2SPeter Wemm 
1806f25ae9SGregory Neil Shapiro #include <sendmail.h>
1906f25ae9SGregory Neil Shapiro 
20c2aa98e2SPeter Wemm 
21c2aa98e2SPeter Wemm /*
22c2aa98e2SPeter Wemm **  NEWENVELOPE -- allocate a new envelope
23c2aa98e2SPeter Wemm **
24c2aa98e2SPeter Wemm **	Supports inheritance.
25c2aa98e2SPeter Wemm **
26c2aa98e2SPeter Wemm **	Parameters:
27c2aa98e2SPeter Wemm **		e -- the new envelope to fill in.
28c2aa98e2SPeter Wemm **		parent -- the envelope to be the parent of e.
29c2aa98e2SPeter Wemm **
30c2aa98e2SPeter Wemm **	Returns:
31c2aa98e2SPeter Wemm **		e.
32c2aa98e2SPeter Wemm **
33c2aa98e2SPeter Wemm **	Side Effects:
34c2aa98e2SPeter Wemm **		none.
35c2aa98e2SPeter Wemm */
36c2aa98e2SPeter Wemm 
37c2aa98e2SPeter Wemm ENVELOPE *
38c2aa98e2SPeter Wemm newenvelope(e, parent)
39c2aa98e2SPeter Wemm 	register ENVELOPE *e;
40c2aa98e2SPeter Wemm 	register ENVELOPE *parent;
41c2aa98e2SPeter Wemm {
42c2aa98e2SPeter Wemm 	if (e == parent && e->e_parent != NULL)
43c2aa98e2SPeter Wemm 		parent = e->e_parent;
44c2aa98e2SPeter Wemm 	clearenvelope(e, TRUE);
45c2aa98e2SPeter Wemm 	if (e == CurEnv)
4606f25ae9SGregory Neil Shapiro 		memmove((char *) &e->e_from,
4706f25ae9SGregory Neil Shapiro 			(char *) &NullAddress,
4806f25ae9SGregory Neil Shapiro 			sizeof e->e_from);
49c2aa98e2SPeter Wemm 	else
5006f25ae9SGregory Neil Shapiro 		memmove((char *) &e->e_from,
5106f25ae9SGregory Neil Shapiro 			(char *) &CurEnv->e_from,
5206f25ae9SGregory Neil Shapiro 			sizeof e->e_from);
53c2aa98e2SPeter Wemm 	e->e_parent = parent;
5406f25ae9SGregory Neil Shapiro 	assign_queueid(e);
55c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
56c2aa98e2SPeter Wemm 	if (parent != NULL)
57c2aa98e2SPeter Wemm 		e->e_msgpriority = parent->e_msgsize;
58c2aa98e2SPeter Wemm 	e->e_puthdr = putheader;
59c2aa98e2SPeter Wemm 	e->e_putbody = putbody;
60c2aa98e2SPeter Wemm 	if (CurEnv->e_xfp != NULL)
61c2aa98e2SPeter Wemm 		(void) fflush(CurEnv->e_xfp);
62c2aa98e2SPeter Wemm 
6306f25ae9SGregory Neil Shapiro 	return e;
64c2aa98e2SPeter Wemm }
65c2aa98e2SPeter Wemm /*
66c2aa98e2SPeter Wemm **  DROPENVELOPE -- deallocate an envelope.
67c2aa98e2SPeter Wemm **
68c2aa98e2SPeter Wemm **	Parameters:
69c2aa98e2SPeter Wemm **		e -- the envelope to deallocate.
70c2aa98e2SPeter Wemm **		fulldrop -- if set, do return receipts.
71c2aa98e2SPeter Wemm **
72c2aa98e2SPeter Wemm **	Returns:
73c2aa98e2SPeter Wemm **		none.
74c2aa98e2SPeter Wemm **
75c2aa98e2SPeter Wemm **	Side Effects:
76c2aa98e2SPeter Wemm **		housekeeping necessary to dispose of an envelope.
77c2aa98e2SPeter Wemm **		Unlocks this queue file.
78c2aa98e2SPeter Wemm */
79c2aa98e2SPeter Wemm 
80c2aa98e2SPeter Wemm void
81c2aa98e2SPeter Wemm dropenvelope(e, fulldrop)
82c2aa98e2SPeter Wemm 	register ENVELOPE *e;
83c2aa98e2SPeter Wemm 	bool fulldrop;
84c2aa98e2SPeter Wemm {
85c2aa98e2SPeter Wemm 	bool queueit = FALSE;
86c2aa98e2SPeter Wemm 	bool message_timeout = FALSE;
87c2aa98e2SPeter Wemm 	bool failure_return = FALSE;
88c2aa98e2SPeter Wemm 	bool delay_return = FALSE;
89c2aa98e2SPeter Wemm 	bool success_return = FALSE;
9006f25ae9SGregory Neil Shapiro 	bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags);
9106f25ae9SGregory Neil Shapiro 	bool done = FALSE;
92c2aa98e2SPeter Wemm 	register ADDRESS *q;
93c2aa98e2SPeter Wemm 	char *id = e->e_id;
94c2aa98e2SPeter Wemm 	char buf[MAXLINE];
95c2aa98e2SPeter Wemm 
96c2aa98e2SPeter Wemm 	if (tTd(50, 1))
97c2aa98e2SPeter Wemm 	{
9806f25ae9SGregory Neil Shapiro 		dprintf("dropenvelope %lx: id=", (u_long) e);
99c2aa98e2SPeter Wemm 		xputs(e->e_id);
10006f25ae9SGregory Neil Shapiro 		dprintf(", flags=");
101c2aa98e2SPeter Wemm 		printenvflags(e);
102c2aa98e2SPeter Wemm 		if (tTd(50, 10))
103c2aa98e2SPeter Wemm 		{
10406f25ae9SGregory Neil Shapiro 			dprintf("sendq=");
105c2aa98e2SPeter Wemm 			printaddr(e->e_sendqueue, TRUE);
106c2aa98e2SPeter Wemm 		}
107c2aa98e2SPeter Wemm 	}
108c2aa98e2SPeter Wemm 
109c2aa98e2SPeter Wemm 	if (LogLevel > 84)
110c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, id,
11106f25ae9SGregory Neil Shapiro 			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
112c2aa98e2SPeter Wemm 			  e->e_flags, OpMode, getpid());
113c2aa98e2SPeter Wemm 
114c2aa98e2SPeter Wemm 	/* we must have an id to remove disk files */
115c2aa98e2SPeter Wemm 	if (id == NULL)
116c2aa98e2SPeter Wemm 		return;
117c2aa98e2SPeter Wemm 
118c2aa98e2SPeter Wemm 	/* if verify-only mode, we can skip most of this */
119c2aa98e2SPeter Wemm 	if (OpMode == MD_VERIFY)
120c2aa98e2SPeter Wemm 		goto simpledrop;
121c2aa98e2SPeter Wemm 
122c2aa98e2SPeter Wemm 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
123c2aa98e2SPeter Wemm 		logsender(e, NULL);
124c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_LOGSENDER;
125c2aa98e2SPeter Wemm 
126c2aa98e2SPeter Wemm 	/* post statistics */
127c2aa98e2SPeter Wemm 	poststats(StatFile);
128c2aa98e2SPeter Wemm 
129c2aa98e2SPeter Wemm 	/*
130c2aa98e2SPeter Wemm 	**  Extract state information from dregs of send list.
131c2aa98e2SPeter Wemm 	*/
132c2aa98e2SPeter Wemm 
133c2aa98e2SPeter Wemm 	if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
134c2aa98e2SPeter Wemm 		message_timeout = TRUE;
135c2aa98e2SPeter Wemm 
13606f25ae9SGregory Neil Shapiro 	if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
13706f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags))
13806f25ae9SGregory Neil Shapiro 	{
13906f25ae9SGregory Neil Shapiro 		message_timeout = TRUE;
14006f25ae9SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
14106f25ae9SGregory Neil Shapiro 	}
14206f25ae9SGregory Neil Shapiro 
143c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_QUEUERUN;
144c2aa98e2SPeter Wemm 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
145c2aa98e2SPeter Wemm 	{
14606f25ae9SGregory Neil Shapiro 		if (QS_IS_UNDELIVERED(q->q_state))
147c2aa98e2SPeter Wemm 			queueit = TRUE;
148c2aa98e2SPeter Wemm 
149c2aa98e2SPeter Wemm 		/* see if a notification is needed */
150c2aa98e2SPeter Wemm 		if (bitset(QPINGONFAILURE, q->q_flags) &&
15106f25ae9SGregory Neil Shapiro 		    ((message_timeout && QS_IS_QUEUEUP(q->q_state)) ||
15206f25ae9SGregory Neil Shapiro 		     QS_IS_BADADDR(q->q_state) ||
15306f25ae9SGregory Neil Shapiro 		     (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
15406f25ae9SGregory Neil Shapiro 		      !bitset(EF_RESPONSE, e->e_flags))))
15506f25ae9SGregory Neil Shapiro 
156c2aa98e2SPeter Wemm 		{
157c2aa98e2SPeter Wemm 			failure_return = TRUE;
15806f25ae9SGregory Neil Shapiro 			if (!done && q->q_owner == NULL &&
15906f25ae9SGregory Neil Shapiro 			    !emptyaddr(&e->e_from))
16006f25ae9SGregory Neil Shapiro 			{
161c2aa98e2SPeter Wemm 				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
162c2aa98e2SPeter Wemm 						  &e->e_errorqueue, 0, e);
16306f25ae9SGregory Neil Shapiro 				done = TRUE;
16406f25ae9SGregory Neil Shapiro 			}
165c2aa98e2SPeter Wemm 		}
166c2aa98e2SPeter Wemm 		else if (bitset(QPINGONSUCCESS, q->q_flags) &&
16706f25ae9SGregory Neil Shapiro 			 ((QS_IS_SENT(q->q_state) &&
168c2aa98e2SPeter Wemm 			   bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
169c2aa98e2SPeter Wemm 			  bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags)))
170c2aa98e2SPeter Wemm 		{
171c2aa98e2SPeter Wemm 			success_return = TRUE;
172c2aa98e2SPeter Wemm 		}
173c2aa98e2SPeter Wemm 	}
174c2aa98e2SPeter Wemm 
175c2aa98e2SPeter Wemm 	if (e->e_class < 0)
176c2aa98e2SPeter Wemm 		e->e_flags |= EF_NO_BODY_RETN;
177c2aa98e2SPeter Wemm 
178c2aa98e2SPeter Wemm 	/*
179c2aa98e2SPeter Wemm 	**  See if the message timed out.
180c2aa98e2SPeter Wemm 	*/
181c2aa98e2SPeter Wemm 
182c2aa98e2SPeter Wemm 	if (!queueit)
18306f25ae9SGregory Neil Shapiro 		/* EMPTY */
184c2aa98e2SPeter Wemm 		/* nothing to do */ ;
185c2aa98e2SPeter Wemm 	else if (message_timeout)
186c2aa98e2SPeter Wemm 	{
187c2aa98e2SPeter Wemm 		if (failure_return)
188c2aa98e2SPeter Wemm 		{
189c2aa98e2SPeter Wemm 			(void) snprintf(buf, sizeof buf,
19006f25ae9SGregory Neil Shapiro 					"Cannot send message for %s",
191c2aa98e2SPeter Wemm 					pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
192c2aa98e2SPeter Wemm 			if (e->e_message != NULL)
193c2aa98e2SPeter Wemm 				free(e->e_message);
194c2aa98e2SPeter Wemm 			e->e_message = newstr(buf);
195c2aa98e2SPeter Wemm 			message(buf);
196c2aa98e2SPeter Wemm 			e->e_flags |= EF_CLRQUEUE;
197c2aa98e2SPeter Wemm 		}
198c2aa98e2SPeter Wemm 		fprintf(e->e_xfp, "Message could not be delivered for %s\n",
199c2aa98e2SPeter Wemm 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
200c2aa98e2SPeter Wemm 		fprintf(e->e_xfp, "Message will be deleted from queue\n");
201c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
202c2aa98e2SPeter Wemm 		{
20306f25ae9SGregory Neil Shapiro 			if (QS_IS_UNDELIVERED(q->q_state))
204c2aa98e2SPeter Wemm 			{
20506f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
206c2aa98e2SPeter Wemm 				q->q_status = "4.4.7";
207c2aa98e2SPeter Wemm 			}
208c2aa98e2SPeter Wemm 		}
209c2aa98e2SPeter Wemm 	}
210c2aa98e2SPeter Wemm 	else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
211c2aa98e2SPeter Wemm 	    curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
212c2aa98e2SPeter Wemm 	{
213c2aa98e2SPeter Wemm 		if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
214c2aa98e2SPeter Wemm 		    e->e_class >= 0 &&
215c2aa98e2SPeter Wemm 		    e->e_from.q_paddr != NULL &&
216c2aa98e2SPeter Wemm 		    strcmp(e->e_from.q_paddr, "<>") != 0 &&
217c2aa98e2SPeter Wemm 		    strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
218c2aa98e2SPeter Wemm 		    (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 ||
219c2aa98e2SPeter Wemm 		     strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
220c2aa98e2SPeter Wemm 		{
221c2aa98e2SPeter Wemm 			for (q = e->e_sendqueue; q != NULL; q = q->q_next)
222c2aa98e2SPeter Wemm 			{
22306f25ae9SGregory Neil Shapiro 				if (QS_IS_QUEUEUP(q->q_state) &&
22406f25ae9SGregory Neil Shapiro #if _FFR_NODELAYDSN_ON_HOLD
22506f25ae9SGregory Neil Shapiro 				    !bitnset(M_HOLD, q->q_mailer->m_flags) &&
22606f25ae9SGregory Neil Shapiro #endif /* _FFR_NODELAYDSN_ON_HOLD */
227c2aa98e2SPeter Wemm 				    bitset(QPINGONDELAY, q->q_flags))
228c2aa98e2SPeter Wemm 				{
229c2aa98e2SPeter Wemm 					q->q_flags |= QDELAYED;
230c2aa98e2SPeter Wemm 					delay_return = TRUE;
231c2aa98e2SPeter Wemm 				}
232c2aa98e2SPeter Wemm 			}
233c2aa98e2SPeter Wemm 		}
234c2aa98e2SPeter Wemm 		if (delay_return)
235c2aa98e2SPeter Wemm 		{
236c2aa98e2SPeter Wemm 			(void) snprintf(buf, sizeof buf,
237c2aa98e2SPeter Wemm 				"Warning: could not send message for past %s",
238c2aa98e2SPeter Wemm 				pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
239c2aa98e2SPeter Wemm 			if (e->e_message != NULL)
240c2aa98e2SPeter Wemm 				free(e->e_message);
241c2aa98e2SPeter Wemm 			e->e_message = newstr(buf);
242c2aa98e2SPeter Wemm 			message(buf);
243c2aa98e2SPeter Wemm 			e->e_flags |= EF_WARNING;
244c2aa98e2SPeter Wemm 		}
245c2aa98e2SPeter Wemm 		fprintf(e->e_xfp,
246c2aa98e2SPeter Wemm 			"Warning: message still undelivered after %s\n",
247c2aa98e2SPeter Wemm 			pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
248c2aa98e2SPeter Wemm 		fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
249c2aa98e2SPeter Wemm 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
250c2aa98e2SPeter Wemm 	}
251c2aa98e2SPeter Wemm 
252c2aa98e2SPeter Wemm 	if (tTd(50, 2))
25306f25ae9SGregory Neil Shapiro 		dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
254c2aa98e2SPeter Wemm 			failure_return, delay_return, success_return, queueit);
255c2aa98e2SPeter Wemm 
256c2aa98e2SPeter Wemm 	/*
257c2aa98e2SPeter Wemm 	**  If we had some fatal error, but no addresses are marked as
258c2aa98e2SPeter Wemm 	**  bad, mark them _all_ as bad.
259c2aa98e2SPeter Wemm 	*/
260c2aa98e2SPeter Wemm 
261c2aa98e2SPeter Wemm 	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
262c2aa98e2SPeter Wemm 	{
263c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
264c2aa98e2SPeter Wemm 		{
26506f25ae9SGregory Neil Shapiro 			if ((QS_IS_OK(q->q_state) ||
26606f25ae9SGregory Neil Shapiro 			     QS_IS_VERIFIED(q->q_state)) &&
267c2aa98e2SPeter Wemm 			    bitset(QPINGONFAILURE, q->q_flags))
268c2aa98e2SPeter Wemm 			{
269c2aa98e2SPeter Wemm 				failure_return = TRUE;
27006f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
271c2aa98e2SPeter Wemm 			}
272c2aa98e2SPeter Wemm 		}
273c2aa98e2SPeter Wemm 	}
274c2aa98e2SPeter Wemm 
275c2aa98e2SPeter Wemm 	/*
276c2aa98e2SPeter Wemm 	**  Send back return receipts as requested.
277c2aa98e2SPeter Wemm 	*/
278c2aa98e2SPeter Wemm 
279c2aa98e2SPeter Wemm 	if (success_return && !failure_return && !delay_return && fulldrop &&
280c2aa98e2SPeter Wemm 	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
281c2aa98e2SPeter Wemm 	    strcmp(e->e_from.q_paddr, "<>") != 0)
282c2aa98e2SPeter Wemm 	{
283c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
284c2aa98e2SPeter Wemm 
285c2aa98e2SPeter Wemm 		if (tTd(50, 8))
28606f25ae9SGregory Neil Shapiro 			dprintf("dropenvelope(%s): sending return receipt\n",
28706f25ae9SGregory Neil Shapiro 				id);
288c2aa98e2SPeter Wemm 		e->e_flags |= EF_SENDRECEIPT;
289c2aa98e2SPeter Wemm 		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
290c2aa98e2SPeter Wemm 		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
291c2aa98e2SPeter Wemm 	}
292c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_SENDRECEIPT;
293c2aa98e2SPeter Wemm 
294c2aa98e2SPeter Wemm 	/*
295c2aa98e2SPeter Wemm 	**  Arrange to send error messages if there are fatal errors.
296c2aa98e2SPeter Wemm 	*/
297c2aa98e2SPeter Wemm 
298c2aa98e2SPeter Wemm 	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
299c2aa98e2SPeter Wemm 	{
300c2aa98e2SPeter Wemm 		if (tTd(50, 8))
30106f25ae9SGregory Neil Shapiro 			dprintf("dropenvelope(%s): saving mail\n", id);
302c2aa98e2SPeter Wemm 		savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
303c2aa98e2SPeter Wemm 	}
304c2aa98e2SPeter Wemm 
305c2aa98e2SPeter Wemm 	/*
306c2aa98e2SPeter Wemm 	**  Arrange to send warning messages to postmaster as requested.
307c2aa98e2SPeter Wemm 	*/
308c2aa98e2SPeter Wemm 
30906f25ae9SGregory Neil Shapiro 	if ((failure_return || pmnotify) &&
310c2aa98e2SPeter Wemm 	    PostMasterCopy != NULL &&
31106f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags) &&
31206f25ae9SGregory Neil Shapiro 	    e->e_class >= 0)
313c2aa98e2SPeter Wemm 	{
314c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
31506f25ae9SGregory Neil Shapiro 		char pcopy[MAXNAME];
31606f25ae9SGregory Neil Shapiro 
31706f25ae9SGregory Neil Shapiro 		if (failure_return)
31806f25ae9SGregory Neil Shapiro 		{
31906f25ae9SGregory Neil Shapiro 			expand(PostMasterCopy, pcopy, sizeof pcopy, e);
320c2aa98e2SPeter Wemm 
321c2aa98e2SPeter Wemm 			if (tTd(50, 8))
32206f25ae9SGregory Neil Shapiro 				dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
32306f25ae9SGregory Neil Shapiro 					id, pcopy);
32406f25ae9SGregory Neil Shapiro 			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
32506f25ae9SGregory Neil Shapiro 		}
32606f25ae9SGregory Neil Shapiro 		if (pmnotify)
32706f25ae9SGregory Neil Shapiro 			(void) sendtolist("postmaster", NULLADDR,
32806f25ae9SGregory Neil Shapiro 					  &rlist, 0, e);
32906f25ae9SGregory Neil Shapiro 		(void) returntosender(e->e_message, rlist,
33006f25ae9SGregory Neil Shapiro 				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
331c2aa98e2SPeter Wemm 	}
332c2aa98e2SPeter Wemm 
333c2aa98e2SPeter Wemm 	/*
334c2aa98e2SPeter Wemm 	**  Instantiate or deinstantiate the queue.
335c2aa98e2SPeter Wemm 	*/
336c2aa98e2SPeter Wemm 
337c2aa98e2SPeter Wemm simpledrop:
338c2aa98e2SPeter Wemm 	if (tTd(50, 8))
33906f25ae9SGregory Neil Shapiro 		dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
340c2aa98e2SPeter Wemm 			id, queueit);
341c2aa98e2SPeter Wemm 	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
342c2aa98e2SPeter Wemm 	{
343c2aa98e2SPeter Wemm 		if (tTd(50, 1))
344c2aa98e2SPeter Wemm 		{
34506f25ae9SGregory Neil Shapiro 			dprintf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=",
346c2aa98e2SPeter Wemm 				e->e_id, queueit);
347c2aa98e2SPeter Wemm 			printenvflags(e);
348c2aa98e2SPeter Wemm 		}
349c2aa98e2SPeter Wemm 		xunlink(queuename(e, 'd'));
350c2aa98e2SPeter Wemm 		xunlink(queuename(e, 'q'));
351c2aa98e2SPeter Wemm 
35206f25ae9SGregory Neil Shapiro 		if (e->e_ntries > 0 && LogLevel > 9)
35306f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
35406f25ae9SGregory Neil Shapiro 				  pintvl(curtime() - e->e_ctime, TRUE),
35506f25ae9SGregory Neil Shapiro 				  e->e_ntries);
356c2aa98e2SPeter Wemm 	}
357c2aa98e2SPeter Wemm 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
358c2aa98e2SPeter Wemm 	{
359c2aa98e2SPeter Wemm #if QUEUE
360c2aa98e2SPeter Wemm 		queueup(e, FALSE);
361c2aa98e2SPeter Wemm #else /* QUEUE */
36206f25ae9SGregory Neil Shapiro 		syserr("554 5.3.0 dropenvelope: queueup");
363c2aa98e2SPeter Wemm #endif /* QUEUE */
364c2aa98e2SPeter Wemm 	}
365c2aa98e2SPeter Wemm 
366c2aa98e2SPeter Wemm 	/* now unlock the job */
367c2aa98e2SPeter Wemm 	if (tTd(50, 8))
36806f25ae9SGregory Neil Shapiro 		dprintf("dropenvelope(%s): unlocking job\n", id);
369c2aa98e2SPeter Wemm 	closexscript(e);
370c2aa98e2SPeter Wemm 	unlockqueue(e);
371c2aa98e2SPeter Wemm 
372c2aa98e2SPeter Wemm 	/* make sure that this envelope is marked unused */
373c2aa98e2SPeter Wemm 	if (e->e_dfp != NULL)
37406f25ae9SGregory Neil Shapiro 		(void) bfclose(e->e_dfp);
375c2aa98e2SPeter Wemm 	e->e_dfp = NULL;
376c2aa98e2SPeter Wemm 	e->e_id = NULL;
377c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_HAS_DF;
378c2aa98e2SPeter Wemm }
379c2aa98e2SPeter Wemm /*
380c2aa98e2SPeter Wemm **  CLEARENVELOPE -- clear an envelope without unlocking
381c2aa98e2SPeter Wemm **
382c2aa98e2SPeter Wemm **	This is normally used by a child process to get a clean
383c2aa98e2SPeter Wemm **	envelope without disturbing the parent.
384c2aa98e2SPeter Wemm **
385c2aa98e2SPeter Wemm **	Parameters:
386c2aa98e2SPeter Wemm **		e -- the envelope to clear.
387c2aa98e2SPeter Wemm **		fullclear - if set, the current envelope is total
388c2aa98e2SPeter Wemm **			garbage and should be ignored; otherwise,
389c2aa98e2SPeter Wemm **			release any resources it may indicate.
390c2aa98e2SPeter Wemm **
391c2aa98e2SPeter Wemm **	Returns:
392c2aa98e2SPeter Wemm **		none.
393c2aa98e2SPeter Wemm **
394c2aa98e2SPeter Wemm **	Side Effects:
395c2aa98e2SPeter Wemm **		Closes files associated with the envelope.
396c2aa98e2SPeter Wemm **		Marks the envelope as unallocated.
397c2aa98e2SPeter Wemm */
398c2aa98e2SPeter Wemm 
399c2aa98e2SPeter Wemm void
400c2aa98e2SPeter Wemm clearenvelope(e, fullclear)
401c2aa98e2SPeter Wemm 	register ENVELOPE *e;
402c2aa98e2SPeter Wemm 	bool fullclear;
403c2aa98e2SPeter Wemm {
404c2aa98e2SPeter Wemm 	register HDR *bh;
405c2aa98e2SPeter Wemm 	register HDR **nhp;
406c2aa98e2SPeter Wemm 	extern ENVELOPE BlankEnvelope;
407c2aa98e2SPeter Wemm 
408c2aa98e2SPeter Wemm 	if (!fullclear)
409c2aa98e2SPeter Wemm 	{
410c2aa98e2SPeter Wemm 		/* clear out any file information */
411c2aa98e2SPeter Wemm 		if (e->e_xfp != NULL)
41206f25ae9SGregory Neil Shapiro 			(void) bfclose(e->e_xfp);
413c2aa98e2SPeter Wemm 		if (e->e_dfp != NULL)
41406f25ae9SGregory Neil Shapiro 			(void) bfclose(e->e_dfp);
415c2aa98e2SPeter Wemm 		e->e_xfp = e->e_dfp = NULL;
416c2aa98e2SPeter Wemm 	}
417c2aa98e2SPeter Wemm 
418c2aa98e2SPeter Wemm 	/* now clear out the data */
419c2aa98e2SPeter Wemm 	STRUCTCOPY(BlankEnvelope, *e);
420c2aa98e2SPeter Wemm 	e->e_message = NULL;
421c2aa98e2SPeter Wemm 	if (Verbose)
42206f25ae9SGregory Neil Shapiro 		set_delivery_mode(SM_DELIVER, e);
423c2aa98e2SPeter Wemm 	bh = BlankEnvelope.e_header;
424c2aa98e2SPeter Wemm 	nhp = &e->e_header;
425c2aa98e2SPeter Wemm 	while (bh != NULL)
426c2aa98e2SPeter Wemm 	{
427c2aa98e2SPeter Wemm 		*nhp = (HDR *) xalloc(sizeof *bh);
42806f25ae9SGregory Neil Shapiro 		memmove((char *) *nhp, (char *) bh, sizeof *bh);
429c2aa98e2SPeter Wemm 		bh = bh->h_link;
430c2aa98e2SPeter Wemm 		nhp = &(*nhp)->h_link;
431c2aa98e2SPeter Wemm 	}
432c2aa98e2SPeter Wemm }
433c2aa98e2SPeter Wemm /*
434c2aa98e2SPeter Wemm **  INITSYS -- initialize instantiation of system
435c2aa98e2SPeter Wemm **
436c2aa98e2SPeter Wemm **	In Daemon mode, this is done in the child.
437c2aa98e2SPeter Wemm **
438c2aa98e2SPeter Wemm **	Parameters:
43906f25ae9SGregory Neil Shapiro **		e -- the envelope to use.
440c2aa98e2SPeter Wemm **
441c2aa98e2SPeter Wemm **	Returns:
442c2aa98e2SPeter Wemm **		none.
443c2aa98e2SPeter Wemm **
444c2aa98e2SPeter Wemm **	Side Effects:
445c2aa98e2SPeter Wemm **		Initializes the system macros, some global variables,
446c2aa98e2SPeter Wemm **		etc.  In particular, the current time in various
447c2aa98e2SPeter Wemm **		forms is set.
448c2aa98e2SPeter Wemm */
449c2aa98e2SPeter Wemm 
450c2aa98e2SPeter Wemm void
451c2aa98e2SPeter Wemm initsys(e)
452c2aa98e2SPeter Wemm 	register ENVELOPE *e;
453c2aa98e2SPeter Wemm {
454c2aa98e2SPeter Wemm 	char cbuf[5];				/* holds hop count */
455c2aa98e2SPeter Wemm 	char pbuf[10];				/* holds pid */
456c2aa98e2SPeter Wemm #ifdef TTYNAME
457c2aa98e2SPeter Wemm 	static char ybuf[60];			/* holds tty id */
458c2aa98e2SPeter Wemm 	register char *p;
459c2aa98e2SPeter Wemm 	extern char *ttyname();
460c2aa98e2SPeter Wemm #endif /* TTYNAME */
461c2aa98e2SPeter Wemm 
462c2aa98e2SPeter Wemm 	/*
463c2aa98e2SPeter Wemm 	**  Give this envelope a reality.
464c2aa98e2SPeter Wemm 	**	I.e., an id, a transcript, and a creation time.
465c2aa98e2SPeter Wemm 	*/
466c2aa98e2SPeter Wemm 
46706f25ae9SGregory Neil Shapiro 	setnewqueue(e);
468c2aa98e2SPeter Wemm 	openxscript(e);
469c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
47006f25ae9SGregory Neil Shapiro #if _FFR_QUEUEDELAY
47106f25ae9SGregory Neil Shapiro 	e->e_queuealg = QueueAlg;
47206f25ae9SGregory Neil Shapiro 	e->e_queuedelay = QueueInitDelay;
47306f25ae9SGregory Neil Shapiro #endif /* _FFR_QUEUEDELAY */
474c2aa98e2SPeter Wemm 
475c2aa98e2SPeter Wemm 	/*
476c2aa98e2SPeter Wemm 	**  Set OutChannel to something useful if stdout isn't it.
477c2aa98e2SPeter Wemm 	**	This arranges that any extra stuff the mailer produces
478c2aa98e2SPeter Wemm 	**	gets sent back to the user on error (because it is
479c2aa98e2SPeter Wemm 	**	tucked away in the transcript).
480c2aa98e2SPeter Wemm 	*/
481c2aa98e2SPeter Wemm 
482c2aa98e2SPeter Wemm 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
483c2aa98e2SPeter Wemm 	    e->e_xfp != NULL)
484c2aa98e2SPeter Wemm 		OutChannel = e->e_xfp;
485c2aa98e2SPeter Wemm 
486c2aa98e2SPeter Wemm 	/*
487c2aa98e2SPeter Wemm 	**  Set up some basic system macros.
488c2aa98e2SPeter Wemm 	*/
489c2aa98e2SPeter Wemm 
490c2aa98e2SPeter Wemm 	/* process id */
49106f25ae9SGregory Neil Shapiro 	(void) snprintf(pbuf, sizeof pbuf, "%d", (int) getpid());
492c2aa98e2SPeter Wemm 	define('p', newstr(pbuf), e);
493c2aa98e2SPeter Wemm 
494c2aa98e2SPeter Wemm 	/* hop count */
495c2aa98e2SPeter Wemm 	(void) snprintf(cbuf, sizeof cbuf, "%d", e->e_hopcount);
496c2aa98e2SPeter Wemm 	define('c', newstr(cbuf), e);
497c2aa98e2SPeter Wemm 
498c2aa98e2SPeter Wemm 	/* time as integer, unix time, arpa time */
499c2aa98e2SPeter Wemm 	settime(e);
500c2aa98e2SPeter Wemm 
50106f25ae9SGregory Neil Shapiro 	/* Load average */
50206f25ae9SGregory Neil Shapiro 	(void)sm_getla(e);
50306f25ae9SGregory Neil Shapiro 
504c2aa98e2SPeter Wemm #ifdef TTYNAME
505c2aa98e2SPeter Wemm 	/* tty name */
506c2aa98e2SPeter Wemm 	if (macvalue('y', e) == NULL)
507c2aa98e2SPeter Wemm 	{
508c2aa98e2SPeter Wemm 		p = ttyname(2);
509c2aa98e2SPeter Wemm 		if (p != NULL)
510c2aa98e2SPeter Wemm 		{
511c2aa98e2SPeter Wemm 			if (strrchr(p, '/') != NULL)
512c2aa98e2SPeter Wemm 				p = strrchr(p, '/') + 1;
513c2aa98e2SPeter Wemm 			snprintf(ybuf, sizeof ybuf, "%s", p);
514c2aa98e2SPeter Wemm 			define('y', ybuf, e);
515c2aa98e2SPeter Wemm 		}
516c2aa98e2SPeter Wemm 	}
517c2aa98e2SPeter Wemm #endif /* TTYNAME */
518c2aa98e2SPeter Wemm }
519c2aa98e2SPeter Wemm /*
520c2aa98e2SPeter Wemm **  SETTIME -- set the current time.
521c2aa98e2SPeter Wemm **
522c2aa98e2SPeter Wemm **	Parameters:
52306f25ae9SGregory Neil Shapiro **		e -- the envelope in which the macros should be set.
524c2aa98e2SPeter Wemm **
525c2aa98e2SPeter Wemm **	Returns:
526c2aa98e2SPeter Wemm **		none.
527c2aa98e2SPeter Wemm **
528c2aa98e2SPeter Wemm **	Side Effects:
529c2aa98e2SPeter Wemm **		Sets the various time macros -- $a, $b, $d, $t.
530c2aa98e2SPeter Wemm */
531c2aa98e2SPeter Wemm 
532c2aa98e2SPeter Wemm void
533c2aa98e2SPeter Wemm settime(e)
534c2aa98e2SPeter Wemm 	register ENVELOPE *e;
535c2aa98e2SPeter Wemm {
536c2aa98e2SPeter Wemm 	register char *p;
537c2aa98e2SPeter Wemm 	auto time_t now;
538c2aa98e2SPeter Wemm 	char tbuf[20];				/* holds "current" time */
539c2aa98e2SPeter Wemm 	char dbuf[30];				/* holds ctime(tbuf) */
540c2aa98e2SPeter Wemm 	register struct tm *tm;
541c2aa98e2SPeter Wemm 
542c2aa98e2SPeter Wemm 	now = curtime();
543c2aa98e2SPeter Wemm 	tm = gmtime(&now);
544c2aa98e2SPeter Wemm 	(void) snprintf(tbuf, sizeof tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
545c2aa98e2SPeter Wemm 			tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
546c2aa98e2SPeter Wemm 	define('t', newstr(tbuf), e);
54706f25ae9SGregory Neil Shapiro 	(void) strlcpy(dbuf, ctime(&now), sizeof dbuf);
548c2aa98e2SPeter Wemm 	p = strchr(dbuf, '\n');
549c2aa98e2SPeter Wemm 	if (p != NULL)
550c2aa98e2SPeter Wemm 		*p = '\0';
551c2aa98e2SPeter Wemm 	define('d', newstr(dbuf), e);
552c2aa98e2SPeter Wemm 	p = arpadate(dbuf);
553c2aa98e2SPeter Wemm 	p = newstr(p);
554c2aa98e2SPeter Wemm 	if (macvalue('a', e) == NULL)
555c2aa98e2SPeter Wemm 		define('a', p, e);
556c2aa98e2SPeter Wemm 	define('b', p, e);
557c2aa98e2SPeter Wemm }
558c2aa98e2SPeter Wemm /*
559c2aa98e2SPeter Wemm **  OPENXSCRIPT -- Open transcript file
560c2aa98e2SPeter Wemm **
561c2aa98e2SPeter Wemm **	Creates a transcript file for possible eventual mailing or
562c2aa98e2SPeter Wemm **	sending back.
563c2aa98e2SPeter Wemm **
564c2aa98e2SPeter Wemm **	Parameters:
565c2aa98e2SPeter Wemm **		e -- the envelope to create the transcript in/for.
566c2aa98e2SPeter Wemm **
567c2aa98e2SPeter Wemm **	Returns:
568c2aa98e2SPeter Wemm **		none
569c2aa98e2SPeter Wemm **
570c2aa98e2SPeter Wemm **	Side Effects:
571c2aa98e2SPeter Wemm **		Creates the transcript file.
572c2aa98e2SPeter Wemm */
573c2aa98e2SPeter Wemm 
574c2aa98e2SPeter Wemm #ifndef O_APPEND
575c2aa98e2SPeter Wemm # define O_APPEND	0
57606f25ae9SGregory Neil Shapiro #endif /* ! O_APPEND */
577c2aa98e2SPeter Wemm 
578c2aa98e2SPeter Wemm void
579c2aa98e2SPeter Wemm openxscript(e)
580c2aa98e2SPeter Wemm 	register ENVELOPE *e;
581c2aa98e2SPeter Wemm {
582c2aa98e2SPeter Wemm 	register char *p;
583c2aa98e2SPeter Wemm 
584c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
585c2aa98e2SPeter Wemm 		return;
58606f25ae9SGregory Neil Shapiro 
58706f25ae9SGregory Neil Shapiro #if 0
58806f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
58906f25ae9SGregory Neil Shapiro 		syserr("openxscript: job not locked");
59006f25ae9SGregory Neil Shapiro #endif /* 0 */
59106f25ae9SGregory Neil Shapiro 
592c2aa98e2SPeter Wemm 	p = queuename(e, 'x');
59306f25ae9SGregory Neil Shapiro 	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
59406f25ae9SGregory Neil Shapiro 			  SFF_NOTEXCL|SFF_OPENASROOT);
59506f25ae9SGregory Neil Shapiro 
59606f25ae9SGregory Neil Shapiro 	if (e->e_xfp == NULL)
597c2aa98e2SPeter Wemm 	{
598c2aa98e2SPeter Wemm 		syserr("Can't create transcript file %s", p);
59906f25ae9SGregory Neil Shapiro 		e->e_xfp = fopen("/dev/null", "r+");
60006f25ae9SGregory Neil Shapiro 		if (e->e_xfp == NULL)
601c2aa98e2SPeter Wemm 			syserr("!Can't open /dev/null");
602c2aa98e2SPeter Wemm 	}
60306f25ae9SGregory Neil Shapiro #if HASSETVBUF
60406f25ae9SGregory Neil Shapiro 	(void) setvbuf(e->e_xfp, NULL, _IOLBF, 0);
60506f25ae9SGregory Neil Shapiro #else /* HASSETVBUF */
60606f25ae9SGregory Neil Shapiro 	(void) setlinebuf(e->e_xfp);
60706f25ae9SGregory Neil Shapiro #endif /* HASSETVBUF */
608c2aa98e2SPeter Wemm 	if (tTd(46, 9))
609c2aa98e2SPeter Wemm 	{
61006f25ae9SGregory Neil Shapiro 		dprintf("openxscript(%s):\n  ", p);
611c2aa98e2SPeter Wemm 		dumpfd(fileno(e->e_xfp), TRUE, FALSE);
612c2aa98e2SPeter Wemm 	}
613c2aa98e2SPeter Wemm }
614c2aa98e2SPeter Wemm /*
615c2aa98e2SPeter Wemm **  CLOSEXSCRIPT -- close the transcript file.
616c2aa98e2SPeter Wemm **
617c2aa98e2SPeter Wemm **	Parameters:
618c2aa98e2SPeter Wemm **		e -- the envelope containing the transcript to close.
619c2aa98e2SPeter Wemm **
620c2aa98e2SPeter Wemm **	Returns:
621c2aa98e2SPeter Wemm **		none.
622c2aa98e2SPeter Wemm **
623c2aa98e2SPeter Wemm **	Side Effects:
624c2aa98e2SPeter Wemm **		none.
625c2aa98e2SPeter Wemm */
626c2aa98e2SPeter Wemm 
627c2aa98e2SPeter Wemm void
628c2aa98e2SPeter Wemm closexscript(e)
629c2aa98e2SPeter Wemm 	register ENVELOPE *e;
630c2aa98e2SPeter Wemm {
631c2aa98e2SPeter Wemm 	if (e->e_xfp == NULL)
632c2aa98e2SPeter Wemm 		return;
63306f25ae9SGregory Neil Shapiro #if 0
63406f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL)
63506f25ae9SGregory Neil Shapiro 		syserr("closexscript: job not locked");
63606f25ae9SGregory Neil Shapiro #endif /* 0 */
63706f25ae9SGregory Neil Shapiro 	(void) bfclose(e->e_xfp);
638c2aa98e2SPeter Wemm 	e->e_xfp = NULL;
639c2aa98e2SPeter Wemm }
640c2aa98e2SPeter Wemm /*
641c2aa98e2SPeter Wemm **  SETSENDER -- set the person who this message is from
642c2aa98e2SPeter Wemm **
643c2aa98e2SPeter Wemm **	Under certain circumstances allow the user to say who
644c2aa98e2SPeter Wemm **	s/he is (using -f or -r).  These are:
645c2aa98e2SPeter Wemm **	1.  The user's uid is zero (root).
646c2aa98e2SPeter Wemm **	2.  The user's login name is in an approved list (typically
647c2aa98e2SPeter Wemm **	    from a network server).
648c2aa98e2SPeter Wemm **	3.  The address the user is trying to claim has a
649c2aa98e2SPeter Wemm **	    "!" character in it (since #2 doesn't do it for
650c2aa98e2SPeter Wemm **	    us if we are dialing out for UUCP).
651c2aa98e2SPeter Wemm **	A better check to replace #3 would be if the
652c2aa98e2SPeter Wemm **	effective uid is "UUCP" -- this would require me
653c2aa98e2SPeter Wemm **	to rewrite getpwent to "grab" uucp as it went by,
654c2aa98e2SPeter Wemm **	make getname more nasty, do another passwd file
655c2aa98e2SPeter Wemm **	scan, or compile the UID of "UUCP" into the code,
656c2aa98e2SPeter Wemm **	all of which are reprehensible.
657c2aa98e2SPeter Wemm **
658c2aa98e2SPeter Wemm **	Assuming all of these fail, we figure out something
659c2aa98e2SPeter Wemm **	ourselves.
660c2aa98e2SPeter Wemm **
661c2aa98e2SPeter Wemm **	Parameters:
662c2aa98e2SPeter Wemm **		from -- the person we would like to believe this message
663c2aa98e2SPeter Wemm **			is from, as specified on the command line.
664c2aa98e2SPeter Wemm **		e -- the envelope in which we would like the sender set.
665c2aa98e2SPeter Wemm **		delimptr -- if non-NULL, set to the location of the
666c2aa98e2SPeter Wemm **			trailing delimiter.
667c2aa98e2SPeter Wemm **		delimchar -- the character that will delimit the sender
668c2aa98e2SPeter Wemm **			address.
669c2aa98e2SPeter Wemm **		internal -- set if this address is coming from an internal
670c2aa98e2SPeter Wemm **			source such as an owner alias.
671c2aa98e2SPeter Wemm **
672c2aa98e2SPeter Wemm **	Returns:
673c2aa98e2SPeter Wemm **		none.
674c2aa98e2SPeter Wemm **
675c2aa98e2SPeter Wemm **	Side Effects:
676c2aa98e2SPeter Wemm **		sets sendmail's notion of who the from person is.
677c2aa98e2SPeter Wemm */
678c2aa98e2SPeter Wemm 
679c2aa98e2SPeter Wemm void
680c2aa98e2SPeter Wemm setsender(from, e, delimptr, delimchar, internal)
681c2aa98e2SPeter Wemm 	char *from;
682c2aa98e2SPeter Wemm 	register ENVELOPE *e;
683c2aa98e2SPeter Wemm 	char **delimptr;
684c2aa98e2SPeter Wemm 	int delimchar;
685c2aa98e2SPeter Wemm 	bool internal;
686c2aa98e2SPeter Wemm {
687c2aa98e2SPeter Wemm 	register char **pvp;
688c2aa98e2SPeter Wemm 	char *realname = NULL;
689c2aa98e2SPeter Wemm 	register struct passwd *pw;
690c2aa98e2SPeter Wemm 	char *bp;
691c2aa98e2SPeter Wemm 	char buf[MAXNAME + 2];
692c2aa98e2SPeter Wemm 	char pvpbuf[PSBUFSIZE];
693c2aa98e2SPeter Wemm 	extern char *FullName;
694c2aa98e2SPeter Wemm 
695c2aa98e2SPeter Wemm 	if (tTd(45, 1))
69606f25ae9SGregory Neil Shapiro 		dprintf("setsender(%s)\n", from == NULL ? "" : from);
697c2aa98e2SPeter Wemm 
698c2aa98e2SPeter Wemm 	/*
699c2aa98e2SPeter Wemm 	**  Figure out the real user executing us.
700c2aa98e2SPeter Wemm 	**	Username can return errno != 0 on non-errors.
701c2aa98e2SPeter Wemm 	*/
702c2aa98e2SPeter Wemm 
703c2aa98e2SPeter Wemm 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
704c2aa98e2SPeter Wemm 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
705c2aa98e2SPeter Wemm 		realname = from;
706c2aa98e2SPeter Wemm 	if (realname == NULL || realname[0] == '\0')
707c2aa98e2SPeter Wemm 		realname = username();
708c2aa98e2SPeter Wemm 
709c2aa98e2SPeter Wemm 	if (ConfigLevel < 2)
710c2aa98e2SPeter Wemm 		SuprErrs = TRUE;
711c2aa98e2SPeter Wemm 
71206f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
71306f25ae9SGregory Neil Shapiro 	define(macid("{addr_type}", NULL), "e s", e);
71406f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
71506f25ae9SGregory Neil Shapiro 	/* preset state for then clause in case from == NULL */
71606f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_BADADDR;
71706f25ae9SGregory Neil Shapiro 	e->e_from.q_flags = 0;
718c2aa98e2SPeter Wemm 	if (from == NULL ||
719c2aa98e2SPeter Wemm 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
720c2aa98e2SPeter Wemm 		      delimchar, delimptr, e) == NULL ||
72106f25ae9SGregory Neil Shapiro 	    QS_IS_BADADDR(e->e_from.q_state) ||
722c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == ProgMailer ||
723c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == FileMailer ||
724c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == InclMailer)
725c2aa98e2SPeter Wemm 	{
726c2aa98e2SPeter Wemm 		/* log garbage addresses for traceback */
727c2aa98e2SPeter Wemm 		if (from != NULL && LogLevel > 2)
728c2aa98e2SPeter Wemm 		{
729c2aa98e2SPeter Wemm 			char *p;
730c2aa98e2SPeter Wemm 			char ebuf[MAXNAME * 2 + 2];
731c2aa98e2SPeter Wemm 
732c2aa98e2SPeter Wemm 			p = macvalue('_', e);
733c2aa98e2SPeter Wemm 			if (p == NULL)
734c2aa98e2SPeter Wemm 			{
735c2aa98e2SPeter Wemm 				char *host = RealHostName;
736c2aa98e2SPeter Wemm 
737c2aa98e2SPeter Wemm 				if (host == NULL)
738c2aa98e2SPeter Wemm 					host = MyHostName;
739c2aa98e2SPeter Wemm 				(void) snprintf(ebuf, sizeof ebuf, "%.*s@%.*s",
740c2aa98e2SPeter Wemm 					MAXNAME, realname,
741c2aa98e2SPeter Wemm 					MAXNAME, host);
742c2aa98e2SPeter Wemm 				p = ebuf;
743c2aa98e2SPeter Wemm 			}
744c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
74506f25ae9SGregory Neil Shapiro 				  "setsender: %s: invalid or unparsable, received from %s",
746c2aa98e2SPeter Wemm 				  shortenstring(from, 83), p);
747c2aa98e2SPeter Wemm 		}
748c2aa98e2SPeter Wemm 		if (from != NULL)
749c2aa98e2SPeter Wemm 		{
75006f25ae9SGregory Neil Shapiro 			if (!QS_IS_BADADDR(e->e_from.q_state))
751c2aa98e2SPeter Wemm 			{
752c2aa98e2SPeter Wemm 				/* it was a bogus mailer in the from addr */
753c2aa98e2SPeter Wemm 				e->e_status = "5.1.7";
75406f25ae9SGregory Neil Shapiro 				usrerrenh(e->e_status,
75506f25ae9SGregory Neil Shapiro 					  "553 Invalid sender address");
756c2aa98e2SPeter Wemm 			}
757c2aa98e2SPeter Wemm 			SuprErrs = TRUE;
758c2aa98e2SPeter Wemm 		}
759c2aa98e2SPeter Wemm 		if (from == realname ||
760c2aa98e2SPeter Wemm 		    parseaddr(from = newstr(realname), &e->e_from,
761c2aa98e2SPeter Wemm 			      RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
762c2aa98e2SPeter Wemm 		{
763c2aa98e2SPeter Wemm 			char nbuf[100];
764c2aa98e2SPeter Wemm 
765c2aa98e2SPeter Wemm 			SuprErrs = TRUE;
766c2aa98e2SPeter Wemm 			expand("\201n", nbuf, sizeof nbuf, e);
767c2aa98e2SPeter Wemm 			if (parseaddr(from = newstr(nbuf), &e->e_from,
768c2aa98e2SPeter Wemm 				      RF_COPYALL, ' ', NULL, e) == NULL &&
769c2aa98e2SPeter Wemm 			    parseaddr(from = "postmaster", &e->e_from,
770c2aa98e2SPeter Wemm 				      RF_COPYALL, ' ', NULL, e) == NULL)
77106f25ae9SGregory Neil Shapiro 				syserr("553 5.3.0 setsender: can't even parse postmaster!");
772c2aa98e2SPeter Wemm 		}
773c2aa98e2SPeter Wemm 	}
774c2aa98e2SPeter Wemm 	else
775c2aa98e2SPeter Wemm 		FromFlag = TRUE;
77606f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_SENDER;
777c2aa98e2SPeter Wemm 	if (tTd(45, 5))
778c2aa98e2SPeter Wemm 	{
77906f25ae9SGregory Neil Shapiro 		dprintf("setsender: QS_SENDER ");
780c2aa98e2SPeter Wemm 		printaddr(&e->e_from, FALSE);
781c2aa98e2SPeter Wemm 	}
782c2aa98e2SPeter Wemm 	SuprErrs = FALSE;
783c2aa98e2SPeter Wemm 
784c2aa98e2SPeter Wemm #if USERDB
785c2aa98e2SPeter Wemm 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
786c2aa98e2SPeter Wemm 	{
787c2aa98e2SPeter Wemm 		register char *p;
788c2aa98e2SPeter Wemm 
789c2aa98e2SPeter Wemm 		p = udbsender(e->e_from.q_user);
790c2aa98e2SPeter Wemm 		if (p != NULL)
791c2aa98e2SPeter Wemm 			from = p;
792c2aa98e2SPeter Wemm 	}
793c2aa98e2SPeter Wemm #endif /* USERDB */
794c2aa98e2SPeter Wemm 
795c2aa98e2SPeter Wemm 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
796c2aa98e2SPeter Wemm 	{
797c2aa98e2SPeter Wemm 		if (!internal)
798c2aa98e2SPeter Wemm 		{
799c2aa98e2SPeter Wemm 			/* if the user already given fullname don't redefine */
800c2aa98e2SPeter Wemm 			if (FullName == NULL)
801c2aa98e2SPeter Wemm 				FullName = macvalue('x', e);
802c2aa98e2SPeter Wemm 			if (FullName != NULL && FullName[0] == '\0')
803c2aa98e2SPeter Wemm 				FullName = NULL;
804c2aa98e2SPeter Wemm 		}
805c2aa98e2SPeter Wemm 
806c2aa98e2SPeter Wemm 		if (e->e_from.q_user[0] != '\0' &&
807c2aa98e2SPeter Wemm 		    (pw = sm_getpwnam(e->e_from.q_user)) != NULL)
808c2aa98e2SPeter Wemm 		{
809c2aa98e2SPeter Wemm 			/*
810c2aa98e2SPeter Wemm 			**  Process passwd file entry.
811c2aa98e2SPeter Wemm 			*/
812c2aa98e2SPeter Wemm 
813c2aa98e2SPeter Wemm 			/* extract home directory */
814c2aa98e2SPeter Wemm 			if (strcmp(pw->pw_dir, "/") == 0)
815c2aa98e2SPeter Wemm 				e->e_from.q_home = newstr("");
816c2aa98e2SPeter Wemm 			else
817c2aa98e2SPeter Wemm 				e->e_from.q_home = newstr(pw->pw_dir);
818c2aa98e2SPeter Wemm 			define('z', e->e_from.q_home, e);
819c2aa98e2SPeter Wemm 
820c2aa98e2SPeter Wemm 			/* extract user and group id */
821c2aa98e2SPeter Wemm 			e->e_from.q_uid = pw->pw_uid;
822c2aa98e2SPeter Wemm 			e->e_from.q_gid = pw->pw_gid;
823c2aa98e2SPeter Wemm 			e->e_from.q_flags |= QGOODUID;
824c2aa98e2SPeter Wemm 
825c2aa98e2SPeter Wemm 			/* extract full name from passwd file */
826c2aa98e2SPeter Wemm 			if (FullName == NULL && pw->pw_gecos != NULL &&
827c2aa98e2SPeter Wemm 			    strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
828c2aa98e2SPeter Wemm 			    !internal)
829c2aa98e2SPeter Wemm 			{
830c2aa98e2SPeter Wemm 				buildfname(pw->pw_gecos, e->e_from.q_user, buf, sizeof buf);
831c2aa98e2SPeter Wemm 				if (buf[0] != '\0')
832c2aa98e2SPeter Wemm 					FullName = newstr(buf);
833c2aa98e2SPeter Wemm 			}
834c2aa98e2SPeter Wemm 		}
835c2aa98e2SPeter Wemm 		else
836c2aa98e2SPeter Wemm 		{
83706f25ae9SGregory Neil Shapiro 			e->e_from.q_home = NULL;
838c2aa98e2SPeter Wemm 		}
839c2aa98e2SPeter Wemm 		if (FullName != NULL && !internal)
840c2aa98e2SPeter Wemm 			define('x', FullName, e);
841c2aa98e2SPeter Wemm 	}
8422e43090eSPeter Wemm 	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
843c2aa98e2SPeter Wemm 	{
844c2aa98e2SPeter Wemm 		if (e->e_from.q_home == NULL)
845c2aa98e2SPeter Wemm 		{
846c2aa98e2SPeter Wemm 			e->e_from.q_home = getenv("HOME");
847c2aa98e2SPeter Wemm 			if (e->e_from.q_home != NULL &&
848c2aa98e2SPeter Wemm 			    strcmp(e->e_from.q_home, "/") == 0)
849c2aa98e2SPeter Wemm 				e->e_from.q_home++;
850c2aa98e2SPeter Wemm 		}
851c2aa98e2SPeter Wemm 		e->e_from.q_uid = RealUid;
852c2aa98e2SPeter Wemm 		e->e_from.q_gid = RealGid;
853c2aa98e2SPeter Wemm 		e->e_from.q_flags |= QGOODUID;
854c2aa98e2SPeter Wemm 	}
855c2aa98e2SPeter Wemm 
856c2aa98e2SPeter Wemm 	/*
857c2aa98e2SPeter Wemm 	**  Rewrite the from person to dispose of possible implicit
858c2aa98e2SPeter Wemm 	**	links in the net.
859c2aa98e2SPeter Wemm 	*/
860c2aa98e2SPeter Wemm 
861c2aa98e2SPeter Wemm 	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL);
862c2aa98e2SPeter Wemm 	if (pvp == NULL)
863c2aa98e2SPeter Wemm 	{
864c2aa98e2SPeter Wemm 		/* don't need to give error -- prescan did that already */
865c2aa98e2SPeter Wemm 		if (LogLevel > 2)
866c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
867c2aa98e2SPeter Wemm 				  "cannot prescan from (%s)",
868c2aa98e2SPeter Wemm 				  shortenstring(from, MAXSHORTSTR));
869065a643dSPeter Wemm 		finis(TRUE, ExitStat);
870c2aa98e2SPeter Wemm 	}
871c2aa98e2SPeter Wemm 	(void) rewrite(pvp, 3, 0, e);
872c2aa98e2SPeter Wemm 	(void) rewrite(pvp, 1, 0, e);
873c2aa98e2SPeter Wemm 	(void) rewrite(pvp, 4, 0, e);
87406f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
87506f25ae9SGregory Neil Shapiro 	define(macid("{addr_type}", NULL), NULL, e);
87606f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
877c2aa98e2SPeter Wemm 	bp = buf + 1;
878c2aa98e2SPeter Wemm 	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
879c2aa98e2SPeter Wemm 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
880c2aa98e2SPeter Wemm 	{
881c2aa98e2SPeter Wemm 		/* heuristic: route-addr: add angle brackets */
88206f25ae9SGregory Neil Shapiro 		(void) strlcat(bp, ">", sizeof buf - 1);
883c2aa98e2SPeter Wemm 		*--bp = '<';
884c2aa98e2SPeter Wemm 	}
885c2aa98e2SPeter Wemm 	e->e_sender = newstr(bp);
886c2aa98e2SPeter Wemm 	define('f', e->e_sender, e);
887c2aa98e2SPeter Wemm 
888c2aa98e2SPeter Wemm 	/* save the domain spec if this mailer wants it */
889c2aa98e2SPeter Wemm 	if (e->e_from.q_mailer != NULL &&
890c2aa98e2SPeter Wemm 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
891c2aa98e2SPeter Wemm 	{
892c2aa98e2SPeter Wemm 		char **lastat;
893c2aa98e2SPeter Wemm 
894c2aa98e2SPeter Wemm 		/* get rid of any pesky angle brackets */
89506f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
89606f25ae9SGregory Neil Shapiro 		define(macid("{addr_type}", NULL), "e s", e);
89706f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
898c2aa98e2SPeter Wemm 		(void) rewrite(pvp, 3, 0, e);
899c2aa98e2SPeter Wemm 		(void) rewrite(pvp, 1, 0, e);
900c2aa98e2SPeter Wemm 		(void) rewrite(pvp, 4, 0, e);
90106f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
90206f25ae9SGregory Neil Shapiro 		define(macid("{addr_type}", NULL), NULL, e);
90306f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
904c2aa98e2SPeter Wemm 
905c2aa98e2SPeter Wemm 		/* strip off to the last "@" sign */
906c2aa98e2SPeter Wemm 		for (lastat = NULL; *pvp != NULL; pvp++)
907c2aa98e2SPeter Wemm 			if (strcmp(*pvp, "@") == 0)
908c2aa98e2SPeter Wemm 				lastat = pvp;
909c2aa98e2SPeter Wemm 		if (lastat != NULL)
910c2aa98e2SPeter Wemm 		{
911c2aa98e2SPeter Wemm 			e->e_fromdomain = copyplist(lastat, TRUE);
912c2aa98e2SPeter Wemm 			if (tTd(45, 3))
913c2aa98e2SPeter Wemm 			{
91406f25ae9SGregory Neil Shapiro 				dprintf("Saving from domain: ");
915c2aa98e2SPeter Wemm 				printav(e->e_fromdomain);
916c2aa98e2SPeter Wemm 			}
917c2aa98e2SPeter Wemm 		}
918c2aa98e2SPeter Wemm 	}
919c2aa98e2SPeter Wemm }
920c2aa98e2SPeter Wemm /*
921c2aa98e2SPeter Wemm **  PRINTENVFLAGS -- print envelope flags for debugging
922c2aa98e2SPeter Wemm **
923c2aa98e2SPeter Wemm **	Parameters:
924c2aa98e2SPeter Wemm **		e -- the envelope with the flags to be printed.
925c2aa98e2SPeter Wemm **
926c2aa98e2SPeter Wemm **	Returns:
927c2aa98e2SPeter Wemm **		none.
928c2aa98e2SPeter Wemm */
929c2aa98e2SPeter Wemm 
930c2aa98e2SPeter Wemm struct eflags
931c2aa98e2SPeter Wemm {
932c2aa98e2SPeter Wemm 	char	*ef_name;
933c2aa98e2SPeter Wemm 	u_long	ef_bit;
934c2aa98e2SPeter Wemm };
935c2aa98e2SPeter Wemm 
93606f25ae9SGregory Neil Shapiro static struct eflags	EnvelopeFlags[] =
937c2aa98e2SPeter Wemm {
938c2aa98e2SPeter Wemm 	{ "OLDSTYLE",		EF_OLDSTYLE	},
939c2aa98e2SPeter Wemm 	{ "INQUEUE",		EF_INQUEUE	},
940c2aa98e2SPeter Wemm 	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
941c2aa98e2SPeter Wemm 	{ "CLRQUEUE",		EF_CLRQUEUE	},
942c2aa98e2SPeter Wemm 	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
943c2aa98e2SPeter Wemm 	{ "FATALERRS",		EF_FATALERRS	},
944c2aa98e2SPeter Wemm 	{ "DELETE_BCC",		EF_DELETE_BCC	},
945c2aa98e2SPeter Wemm 	{ "RESPONSE",		EF_RESPONSE	},
946c2aa98e2SPeter Wemm 	{ "RESENT",		EF_RESENT	},
947c2aa98e2SPeter Wemm 	{ "VRFYONLY",		EF_VRFYONLY	},
948c2aa98e2SPeter Wemm 	{ "WARNING",		EF_WARNING	},
949c2aa98e2SPeter Wemm 	{ "QUEUERUN",		EF_QUEUERUN	},
950c2aa98e2SPeter Wemm 	{ "GLOBALERRS",		EF_GLOBALERRS	},
951c2aa98e2SPeter Wemm 	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
952c2aa98e2SPeter Wemm 	{ "METOO",		EF_METOO	},
953c2aa98e2SPeter Wemm 	{ "LOGSENDER",		EF_LOGSENDER	},
954c2aa98e2SPeter Wemm 	{ "NORECEIPT",		EF_NORECEIPT	},
955c2aa98e2SPeter Wemm 	{ "HAS8BIT",		EF_HAS8BIT	},
956c2aa98e2SPeter Wemm 	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
957c2aa98e2SPeter Wemm 	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
958c2aa98e2SPeter Wemm 	{ "RET_PARAM",		EF_RET_PARAM	},
959c2aa98e2SPeter Wemm 	{ "HAS_DF",		EF_HAS_DF	},
960c2aa98e2SPeter Wemm 	{ "IS_MIME",		EF_IS_MIME	},
961c2aa98e2SPeter Wemm 	{ "DONT_MIME",		EF_DONT_MIME	},
962c2aa98e2SPeter Wemm 	{ NULL }
963c2aa98e2SPeter Wemm };
964c2aa98e2SPeter Wemm 
965c2aa98e2SPeter Wemm void
966c2aa98e2SPeter Wemm printenvflags(e)
967c2aa98e2SPeter Wemm 	register ENVELOPE *e;
968c2aa98e2SPeter Wemm {
969c2aa98e2SPeter Wemm 	register struct eflags *ef;
970c2aa98e2SPeter Wemm 	bool first = TRUE;
971c2aa98e2SPeter Wemm 
972c2aa98e2SPeter Wemm 	printf("%lx", e->e_flags);
973c2aa98e2SPeter Wemm 	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
974c2aa98e2SPeter Wemm 	{
975c2aa98e2SPeter Wemm 		if (!bitset(ef->ef_bit, e->e_flags))
976c2aa98e2SPeter Wemm 			continue;
977c2aa98e2SPeter Wemm 		if (first)
978c2aa98e2SPeter Wemm 			printf("<%s", ef->ef_name);
979c2aa98e2SPeter Wemm 		else
980c2aa98e2SPeter Wemm 			printf(",%s", ef->ef_name);
981c2aa98e2SPeter Wemm 		first = FALSE;
982c2aa98e2SPeter Wemm 	}
983c2aa98e2SPeter Wemm 	if (!first)
984c2aa98e2SPeter Wemm 		printf(">\n");
985c2aa98e2SPeter Wemm }
986