xref: /freebsd/contrib/sendmail/src/envelope.c (revision 193538b7)
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
15193538b7SGregory Neil Shapiro static char id[] = "@(#)$Id: envelope.c,v 8.180.14.6 2000/11/30 00:39:46 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;
94193538b7SGregory Neil Shapiro 	time_t now;
95c2aa98e2SPeter Wemm 	char buf[MAXLINE];
96c2aa98e2SPeter Wemm 
97c2aa98e2SPeter Wemm 	if (tTd(50, 1))
98c2aa98e2SPeter Wemm 	{
9906f25ae9SGregory Neil Shapiro 		dprintf("dropenvelope %lx: id=", (u_long) e);
100c2aa98e2SPeter Wemm 		xputs(e->e_id);
10106f25ae9SGregory Neil Shapiro 		dprintf(", flags=");
102c2aa98e2SPeter Wemm 		printenvflags(e);
103c2aa98e2SPeter Wemm 		if (tTd(50, 10))
104c2aa98e2SPeter Wemm 		{
10506f25ae9SGregory Neil Shapiro 			dprintf("sendq=");
106c2aa98e2SPeter Wemm 			printaddr(e->e_sendqueue, TRUE);
107c2aa98e2SPeter Wemm 		}
108c2aa98e2SPeter Wemm 	}
109c2aa98e2SPeter Wemm 
110c2aa98e2SPeter Wemm 	if (LogLevel > 84)
111c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, id,
11206f25ae9SGregory Neil Shapiro 			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
113c2aa98e2SPeter Wemm 			  e->e_flags, OpMode, getpid());
114c2aa98e2SPeter Wemm 
115c2aa98e2SPeter Wemm 	/* we must have an id to remove disk files */
116c2aa98e2SPeter Wemm 	if (id == NULL)
117c2aa98e2SPeter Wemm 		return;
118c2aa98e2SPeter Wemm 
119c2aa98e2SPeter Wemm 	/* if verify-only mode, we can skip most of this */
120c2aa98e2SPeter Wemm 	if (OpMode == MD_VERIFY)
121c2aa98e2SPeter Wemm 		goto simpledrop;
122c2aa98e2SPeter Wemm 
123c2aa98e2SPeter Wemm 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
124c2aa98e2SPeter Wemm 		logsender(e, NULL);
125c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_LOGSENDER;
126c2aa98e2SPeter Wemm 
127c2aa98e2SPeter Wemm 	/* post statistics */
128c2aa98e2SPeter Wemm 	poststats(StatFile);
129c2aa98e2SPeter Wemm 
130c2aa98e2SPeter Wemm 	/*
131c2aa98e2SPeter Wemm 	**  Extract state information from dregs of send list.
132c2aa98e2SPeter Wemm 	*/
133c2aa98e2SPeter Wemm 
134193538b7SGregory Neil Shapiro 	now = curtime();
135193538b7SGregory Neil Shapiro 	if (now > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
136c2aa98e2SPeter Wemm 		message_timeout = TRUE;
137c2aa98e2SPeter Wemm 
13806f25ae9SGregory Neil Shapiro 	if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
13906f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags))
14006f25ae9SGregory Neil Shapiro 	{
14106f25ae9SGregory Neil Shapiro 		message_timeout = TRUE;
14206f25ae9SGregory Neil Shapiro 		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
14306f25ae9SGregory Neil Shapiro 	}
14406f25ae9SGregory Neil Shapiro 
145c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_QUEUERUN;
146c2aa98e2SPeter Wemm 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
147c2aa98e2SPeter Wemm 	{
14806f25ae9SGregory Neil Shapiro 		if (QS_IS_UNDELIVERED(q->q_state))
149c2aa98e2SPeter Wemm 			queueit = TRUE;
150c2aa98e2SPeter Wemm 
151c2aa98e2SPeter Wemm 		/* see if a notification is needed */
152c2aa98e2SPeter Wemm 		if (bitset(QPINGONFAILURE, q->q_flags) &&
15306f25ae9SGregory Neil Shapiro 		    ((message_timeout && QS_IS_QUEUEUP(q->q_state)) ||
15406f25ae9SGregory Neil Shapiro 		     QS_IS_BADADDR(q->q_state) ||
15506f25ae9SGregory Neil Shapiro 		     (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
15606f25ae9SGregory Neil Shapiro 		      !bitset(EF_RESPONSE, e->e_flags))))
15706f25ae9SGregory Neil Shapiro 
158c2aa98e2SPeter Wemm 		{
159c2aa98e2SPeter Wemm 			failure_return = TRUE;
16006f25ae9SGregory Neil Shapiro 			if (!done && q->q_owner == NULL &&
16106f25ae9SGregory Neil Shapiro 			    !emptyaddr(&e->e_from))
16206f25ae9SGregory Neil Shapiro 			{
163c2aa98e2SPeter Wemm 				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
164c2aa98e2SPeter Wemm 						  &e->e_errorqueue, 0, e);
16506f25ae9SGregory Neil Shapiro 				done = TRUE;
16606f25ae9SGregory Neil Shapiro 			}
167c2aa98e2SPeter Wemm 		}
168c2aa98e2SPeter Wemm 		else if (bitset(QPINGONSUCCESS, q->q_flags) &&
16906f25ae9SGregory Neil Shapiro 			 ((QS_IS_SENT(q->q_state) &&
170c2aa98e2SPeter Wemm 			   bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
171c2aa98e2SPeter Wemm 			  bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags)))
172c2aa98e2SPeter Wemm 		{
173c2aa98e2SPeter Wemm 			success_return = TRUE;
174c2aa98e2SPeter Wemm 		}
175c2aa98e2SPeter Wemm 	}
176c2aa98e2SPeter Wemm 
177c2aa98e2SPeter Wemm 	if (e->e_class < 0)
178c2aa98e2SPeter Wemm 		e->e_flags |= EF_NO_BODY_RETN;
179c2aa98e2SPeter Wemm 
180c2aa98e2SPeter Wemm 	/*
181c2aa98e2SPeter Wemm 	**  See if the message timed out.
182c2aa98e2SPeter Wemm 	*/
183c2aa98e2SPeter Wemm 
184c2aa98e2SPeter Wemm 	if (!queueit)
18506f25ae9SGregory Neil Shapiro 		/* EMPTY */
186c2aa98e2SPeter Wemm 		/* nothing to do */ ;
187c2aa98e2SPeter Wemm 	else if (message_timeout)
188c2aa98e2SPeter Wemm 	{
189c2aa98e2SPeter Wemm 		if (failure_return)
190c2aa98e2SPeter Wemm 		{
191c2aa98e2SPeter Wemm 			(void) snprintf(buf, sizeof buf,
19206f25ae9SGregory Neil Shapiro 					"Cannot send message for %s",
193c2aa98e2SPeter Wemm 					pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
194c2aa98e2SPeter Wemm 			if (e->e_message != NULL)
195c2aa98e2SPeter Wemm 				free(e->e_message);
196c2aa98e2SPeter Wemm 			e->e_message = newstr(buf);
197c2aa98e2SPeter Wemm 			message(buf);
198c2aa98e2SPeter Wemm 			e->e_flags |= EF_CLRQUEUE;
199c2aa98e2SPeter Wemm 		}
200c2aa98e2SPeter Wemm 		fprintf(e->e_xfp, "Message could not be delivered for %s\n",
201c2aa98e2SPeter Wemm 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
202c2aa98e2SPeter Wemm 		fprintf(e->e_xfp, "Message will be deleted from queue\n");
203c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
204c2aa98e2SPeter Wemm 		{
20506f25ae9SGregory Neil Shapiro 			if (QS_IS_UNDELIVERED(q->q_state))
206c2aa98e2SPeter Wemm 			{
20706f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
208c2aa98e2SPeter Wemm 				q->q_status = "4.4.7";
209c2aa98e2SPeter Wemm 			}
210c2aa98e2SPeter Wemm 		}
211c2aa98e2SPeter Wemm 	}
212c2aa98e2SPeter Wemm 	else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
213193538b7SGregory Neil Shapiro 		 now > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
214c2aa98e2SPeter Wemm 	{
215c2aa98e2SPeter Wemm 		if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
216c2aa98e2SPeter Wemm 		    e->e_class >= 0 &&
217c2aa98e2SPeter Wemm 		    e->e_from.q_paddr != NULL &&
218c2aa98e2SPeter Wemm 		    strcmp(e->e_from.q_paddr, "<>") != 0 &&
219c2aa98e2SPeter Wemm 		    strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
220c2aa98e2SPeter Wemm 		    (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 ||
221c2aa98e2SPeter Wemm 		     strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
222c2aa98e2SPeter Wemm 		{
223c2aa98e2SPeter Wemm 			for (q = e->e_sendqueue; q != NULL; q = q->q_next)
224c2aa98e2SPeter Wemm 			{
22506f25ae9SGregory Neil Shapiro 				if (QS_IS_QUEUEUP(q->q_state) &&
22606f25ae9SGregory Neil Shapiro #if _FFR_NODELAYDSN_ON_HOLD
22706f25ae9SGregory Neil Shapiro 				    !bitnset(M_HOLD, q->q_mailer->m_flags) &&
22806f25ae9SGregory Neil Shapiro #endif /* _FFR_NODELAYDSN_ON_HOLD */
229c2aa98e2SPeter Wemm 				    bitset(QPINGONDELAY, q->q_flags))
230c2aa98e2SPeter Wemm 				{
231c2aa98e2SPeter Wemm 					q->q_flags |= QDELAYED;
232c2aa98e2SPeter Wemm 					delay_return = TRUE;
233c2aa98e2SPeter Wemm 				}
234c2aa98e2SPeter Wemm 			}
235c2aa98e2SPeter Wemm 		}
236c2aa98e2SPeter Wemm 		if (delay_return)
237c2aa98e2SPeter Wemm 		{
238c2aa98e2SPeter Wemm 			(void) snprintf(buf, sizeof buf,
239c2aa98e2SPeter Wemm 				"Warning: could not send message for past %s",
240c2aa98e2SPeter Wemm 				pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
241c2aa98e2SPeter Wemm 			if (e->e_message != NULL)
242c2aa98e2SPeter Wemm 				free(e->e_message);
243c2aa98e2SPeter Wemm 			e->e_message = newstr(buf);
244c2aa98e2SPeter Wemm 			message(buf);
245c2aa98e2SPeter Wemm 			e->e_flags |= EF_WARNING;
246c2aa98e2SPeter Wemm 		}
247c2aa98e2SPeter Wemm 		fprintf(e->e_xfp,
248c2aa98e2SPeter Wemm 			"Warning: message still undelivered after %s\n",
249c2aa98e2SPeter Wemm 			pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
250c2aa98e2SPeter Wemm 		fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
251c2aa98e2SPeter Wemm 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
252c2aa98e2SPeter Wemm 	}
253c2aa98e2SPeter Wemm 
254c2aa98e2SPeter Wemm 	if (tTd(50, 2))
25506f25ae9SGregory Neil Shapiro 		dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
256c2aa98e2SPeter Wemm 			failure_return, delay_return, success_return, queueit);
257c2aa98e2SPeter Wemm 
258c2aa98e2SPeter Wemm 	/*
259c2aa98e2SPeter Wemm 	**  If we had some fatal error, but no addresses are marked as
260c2aa98e2SPeter Wemm 	**  bad, mark them _all_ as bad.
261c2aa98e2SPeter Wemm 	*/
262c2aa98e2SPeter Wemm 
263c2aa98e2SPeter Wemm 	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
264c2aa98e2SPeter Wemm 	{
265c2aa98e2SPeter Wemm 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
266c2aa98e2SPeter Wemm 		{
26706f25ae9SGregory Neil Shapiro 			if ((QS_IS_OK(q->q_state) ||
26806f25ae9SGregory Neil Shapiro 			     QS_IS_VERIFIED(q->q_state)) &&
269c2aa98e2SPeter Wemm 			    bitset(QPINGONFAILURE, q->q_flags))
270c2aa98e2SPeter Wemm 			{
271c2aa98e2SPeter Wemm 				failure_return = TRUE;
27206f25ae9SGregory Neil Shapiro 				q->q_state = QS_BADADDR;
273c2aa98e2SPeter Wemm 			}
274c2aa98e2SPeter Wemm 		}
275c2aa98e2SPeter Wemm 	}
276c2aa98e2SPeter Wemm 
277c2aa98e2SPeter Wemm 	/*
278c2aa98e2SPeter Wemm 	**  Send back return receipts as requested.
279c2aa98e2SPeter Wemm 	*/
280c2aa98e2SPeter Wemm 
281c2aa98e2SPeter Wemm 	if (success_return && !failure_return && !delay_return && fulldrop &&
282c2aa98e2SPeter Wemm 	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
283c2aa98e2SPeter Wemm 	    strcmp(e->e_from.q_paddr, "<>") != 0)
284c2aa98e2SPeter Wemm 	{
285c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
286c2aa98e2SPeter Wemm 
287c2aa98e2SPeter Wemm 		if (tTd(50, 8))
28806f25ae9SGregory Neil Shapiro 			dprintf("dropenvelope(%s): sending return receipt\n",
28906f25ae9SGregory Neil Shapiro 				id);
290c2aa98e2SPeter Wemm 		e->e_flags |= EF_SENDRECEIPT;
291c2aa98e2SPeter Wemm 		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
292c2aa98e2SPeter Wemm 		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
293c2aa98e2SPeter Wemm 	}
294c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_SENDRECEIPT;
295c2aa98e2SPeter Wemm 
296c2aa98e2SPeter Wemm 	/*
297c2aa98e2SPeter Wemm 	**  Arrange to send error messages if there are fatal errors.
298c2aa98e2SPeter Wemm 	*/
299c2aa98e2SPeter Wemm 
300c2aa98e2SPeter Wemm 	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
301c2aa98e2SPeter Wemm 	{
302c2aa98e2SPeter Wemm 		if (tTd(50, 8))
30306f25ae9SGregory Neil Shapiro 			dprintf("dropenvelope(%s): saving mail\n", id);
304c2aa98e2SPeter Wemm 		savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
305c2aa98e2SPeter Wemm 	}
306c2aa98e2SPeter Wemm 
307c2aa98e2SPeter Wemm 	/*
308c2aa98e2SPeter Wemm 	**  Arrange to send warning messages to postmaster as requested.
309c2aa98e2SPeter Wemm 	*/
310c2aa98e2SPeter Wemm 
31106f25ae9SGregory Neil Shapiro 	if ((failure_return || pmnotify) &&
312c2aa98e2SPeter Wemm 	    PostMasterCopy != NULL &&
31306f25ae9SGregory Neil Shapiro 	    !bitset(EF_RESPONSE, e->e_flags) &&
31406f25ae9SGregory Neil Shapiro 	    e->e_class >= 0)
315c2aa98e2SPeter Wemm 	{
316c2aa98e2SPeter Wemm 		auto ADDRESS *rlist = NULL;
31706f25ae9SGregory Neil Shapiro 		char pcopy[MAXNAME];
31806f25ae9SGregory Neil Shapiro 
31906f25ae9SGregory Neil Shapiro 		if (failure_return)
32006f25ae9SGregory Neil Shapiro 		{
32106f25ae9SGregory Neil Shapiro 			expand(PostMasterCopy, pcopy, sizeof pcopy, e);
322c2aa98e2SPeter Wemm 
323c2aa98e2SPeter Wemm 			if (tTd(50, 8))
32406f25ae9SGregory Neil Shapiro 				dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
32506f25ae9SGregory Neil Shapiro 					id, pcopy);
32606f25ae9SGregory Neil Shapiro 			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
32706f25ae9SGregory Neil Shapiro 		}
32806f25ae9SGregory Neil Shapiro 		if (pmnotify)
32906f25ae9SGregory Neil Shapiro 			(void) sendtolist("postmaster", NULLADDR,
33006f25ae9SGregory Neil Shapiro 					  &rlist, 0, e);
33106f25ae9SGregory Neil Shapiro 		(void) returntosender(e->e_message, rlist,
33206f25ae9SGregory Neil Shapiro 				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
333c2aa98e2SPeter Wemm 	}
334c2aa98e2SPeter Wemm 
335c2aa98e2SPeter Wemm 	/*
336c2aa98e2SPeter Wemm 	**  Instantiate or deinstantiate the queue.
337c2aa98e2SPeter Wemm 	*/
338c2aa98e2SPeter Wemm 
339c2aa98e2SPeter Wemm simpledrop:
340c2aa98e2SPeter Wemm 	if (tTd(50, 8))
34106f25ae9SGregory Neil Shapiro 		dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
342c2aa98e2SPeter Wemm 			id, queueit);
343c2aa98e2SPeter Wemm 	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
344c2aa98e2SPeter Wemm 	{
345c2aa98e2SPeter Wemm 		if (tTd(50, 1))
346c2aa98e2SPeter Wemm 		{
34706f25ae9SGregory Neil Shapiro 			dprintf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=",
348c2aa98e2SPeter Wemm 				e->e_id, queueit);
349c2aa98e2SPeter Wemm 			printenvflags(e);
350c2aa98e2SPeter Wemm 		}
351c2aa98e2SPeter Wemm 		xunlink(queuename(e, 'd'));
352c2aa98e2SPeter Wemm 		xunlink(queuename(e, 'q'));
353c2aa98e2SPeter Wemm 
35406f25ae9SGregory Neil Shapiro 		if (e->e_ntries > 0 && LogLevel > 9)
35506f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
35606f25ae9SGregory Neil Shapiro 				  pintvl(curtime() - e->e_ctime, TRUE),
35706f25ae9SGregory Neil Shapiro 				  e->e_ntries);
358c2aa98e2SPeter Wemm 	}
359c2aa98e2SPeter Wemm 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
360c2aa98e2SPeter Wemm 	{
361c2aa98e2SPeter Wemm #if QUEUE
362c2aa98e2SPeter Wemm 		queueup(e, FALSE);
363c2aa98e2SPeter Wemm #else /* QUEUE */
36406f25ae9SGregory Neil Shapiro 		syserr("554 5.3.0 dropenvelope: queueup");
365c2aa98e2SPeter Wemm #endif /* QUEUE */
366c2aa98e2SPeter Wemm 	}
367c2aa98e2SPeter Wemm 
368c2aa98e2SPeter Wemm 	/* now unlock the job */
369c2aa98e2SPeter Wemm 	if (tTd(50, 8))
37006f25ae9SGregory Neil Shapiro 		dprintf("dropenvelope(%s): unlocking job\n", id);
371c2aa98e2SPeter Wemm 	closexscript(e);
372c2aa98e2SPeter Wemm 	unlockqueue(e);
373c2aa98e2SPeter Wemm 
374c2aa98e2SPeter Wemm 	/* make sure that this envelope is marked unused */
375c2aa98e2SPeter Wemm 	if (e->e_dfp != NULL)
37606f25ae9SGregory Neil Shapiro 		(void) bfclose(e->e_dfp);
377c2aa98e2SPeter Wemm 	e->e_dfp = NULL;
378c2aa98e2SPeter Wemm 	e->e_id = NULL;
379c2aa98e2SPeter Wemm 	e->e_flags &= ~EF_HAS_DF;
380c2aa98e2SPeter Wemm }
381c2aa98e2SPeter Wemm /*
382c2aa98e2SPeter Wemm **  CLEARENVELOPE -- clear an envelope without unlocking
383c2aa98e2SPeter Wemm **
384c2aa98e2SPeter Wemm **	This is normally used by a child process to get a clean
385c2aa98e2SPeter Wemm **	envelope without disturbing the parent.
386c2aa98e2SPeter Wemm **
387c2aa98e2SPeter Wemm **	Parameters:
388c2aa98e2SPeter Wemm **		e -- the envelope to clear.
389c2aa98e2SPeter Wemm **		fullclear - if set, the current envelope is total
390c2aa98e2SPeter Wemm **			garbage and should be ignored; otherwise,
391c2aa98e2SPeter Wemm **			release any resources it may indicate.
392c2aa98e2SPeter Wemm **
393c2aa98e2SPeter Wemm **	Returns:
394c2aa98e2SPeter Wemm **		none.
395c2aa98e2SPeter Wemm **
396c2aa98e2SPeter Wemm **	Side Effects:
397c2aa98e2SPeter Wemm **		Closes files associated with the envelope.
398c2aa98e2SPeter Wemm **		Marks the envelope as unallocated.
399c2aa98e2SPeter Wemm */
400c2aa98e2SPeter Wemm 
401c2aa98e2SPeter Wemm void
402c2aa98e2SPeter Wemm clearenvelope(e, fullclear)
403c2aa98e2SPeter Wemm 	register ENVELOPE *e;
404c2aa98e2SPeter Wemm 	bool fullclear;
405c2aa98e2SPeter Wemm {
406c2aa98e2SPeter Wemm 	register HDR *bh;
407c2aa98e2SPeter Wemm 	register HDR **nhp;
408c2aa98e2SPeter Wemm 	extern ENVELOPE BlankEnvelope;
409c2aa98e2SPeter Wemm 
410c2aa98e2SPeter Wemm 	if (!fullclear)
411c2aa98e2SPeter Wemm 	{
412c2aa98e2SPeter Wemm 		/* clear out any file information */
413c2aa98e2SPeter Wemm 		if (e->e_xfp != NULL)
41406f25ae9SGregory Neil Shapiro 			(void) bfclose(e->e_xfp);
415c2aa98e2SPeter Wemm 		if (e->e_dfp != NULL)
41606f25ae9SGregory Neil Shapiro 			(void) bfclose(e->e_dfp);
417c2aa98e2SPeter Wemm 		e->e_xfp = e->e_dfp = NULL;
418c2aa98e2SPeter Wemm 	}
419c2aa98e2SPeter Wemm 
420c2aa98e2SPeter Wemm 	/* now clear out the data */
421c2aa98e2SPeter Wemm 	STRUCTCOPY(BlankEnvelope, *e);
422c2aa98e2SPeter Wemm 	e->e_message = NULL;
423c2aa98e2SPeter Wemm 	if (Verbose)
42406f25ae9SGregory Neil Shapiro 		set_delivery_mode(SM_DELIVER, e);
425c2aa98e2SPeter Wemm 	bh = BlankEnvelope.e_header;
426c2aa98e2SPeter Wemm 	nhp = &e->e_header;
427c2aa98e2SPeter Wemm 	while (bh != NULL)
428c2aa98e2SPeter Wemm 	{
429c2aa98e2SPeter Wemm 		*nhp = (HDR *) xalloc(sizeof *bh);
43006f25ae9SGregory Neil Shapiro 		memmove((char *) *nhp, (char *) bh, sizeof *bh);
431c2aa98e2SPeter Wemm 		bh = bh->h_link;
432c2aa98e2SPeter Wemm 		nhp = &(*nhp)->h_link;
433c2aa98e2SPeter Wemm 	}
434c2aa98e2SPeter Wemm }
435c2aa98e2SPeter Wemm /*
436c2aa98e2SPeter Wemm **  INITSYS -- initialize instantiation of system
437c2aa98e2SPeter Wemm **
438c2aa98e2SPeter Wemm **	In Daemon mode, this is done in the child.
439c2aa98e2SPeter Wemm **
440c2aa98e2SPeter Wemm **	Parameters:
44106f25ae9SGregory Neil Shapiro **		e -- the envelope to use.
442c2aa98e2SPeter Wemm **
443c2aa98e2SPeter Wemm **	Returns:
444c2aa98e2SPeter Wemm **		none.
445c2aa98e2SPeter Wemm **
446c2aa98e2SPeter Wemm **	Side Effects:
447c2aa98e2SPeter Wemm **		Initializes the system macros, some global variables,
448c2aa98e2SPeter Wemm **		etc.  In particular, the current time in various
449c2aa98e2SPeter Wemm **		forms is set.
450c2aa98e2SPeter Wemm */
451c2aa98e2SPeter Wemm 
452c2aa98e2SPeter Wemm void
453c2aa98e2SPeter Wemm initsys(e)
454c2aa98e2SPeter Wemm 	register ENVELOPE *e;
455c2aa98e2SPeter Wemm {
456c2aa98e2SPeter Wemm 	char cbuf[5];				/* holds hop count */
457c2aa98e2SPeter Wemm 	char pbuf[10];				/* holds pid */
458c2aa98e2SPeter Wemm #ifdef TTYNAME
459c2aa98e2SPeter Wemm 	static char ybuf[60];			/* holds tty id */
460c2aa98e2SPeter Wemm 	register char *p;
461c2aa98e2SPeter Wemm 	extern char *ttyname();
462c2aa98e2SPeter Wemm #endif /* TTYNAME */
463c2aa98e2SPeter Wemm 
464c2aa98e2SPeter Wemm 	/*
465c2aa98e2SPeter Wemm 	**  Give this envelope a reality.
466c2aa98e2SPeter Wemm 	**	I.e., an id, a transcript, and a creation time.
467c2aa98e2SPeter Wemm 	*/
468c2aa98e2SPeter Wemm 
46906f25ae9SGregory Neil Shapiro 	setnewqueue(e);
470c2aa98e2SPeter Wemm 	openxscript(e);
471c2aa98e2SPeter Wemm 	e->e_ctime = curtime();
47206f25ae9SGregory Neil Shapiro #if _FFR_QUEUEDELAY
47306f25ae9SGregory Neil Shapiro 	e->e_queuealg = QueueAlg;
47406f25ae9SGregory Neil Shapiro 	e->e_queuedelay = QueueInitDelay;
47506f25ae9SGregory Neil Shapiro #endif /* _FFR_QUEUEDELAY */
476c2aa98e2SPeter Wemm 
477c2aa98e2SPeter Wemm 	/*
478c2aa98e2SPeter Wemm 	**  Set OutChannel to something useful if stdout isn't it.
479c2aa98e2SPeter Wemm 	**	This arranges that any extra stuff the mailer produces
480c2aa98e2SPeter Wemm 	**	gets sent back to the user on error (because it is
481c2aa98e2SPeter Wemm 	**	tucked away in the transcript).
482c2aa98e2SPeter Wemm 	*/
483c2aa98e2SPeter Wemm 
484c2aa98e2SPeter Wemm 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
485c2aa98e2SPeter Wemm 	    e->e_xfp != NULL)
486c2aa98e2SPeter Wemm 		OutChannel = e->e_xfp;
487c2aa98e2SPeter Wemm 
488c2aa98e2SPeter Wemm 	/*
489c2aa98e2SPeter Wemm 	**  Set up some basic system macros.
490c2aa98e2SPeter Wemm 	*/
491c2aa98e2SPeter Wemm 
492c2aa98e2SPeter Wemm 	/* process id */
49306f25ae9SGregory Neil Shapiro 	(void) snprintf(pbuf, sizeof pbuf, "%d", (int) getpid());
494c2aa98e2SPeter Wemm 	define('p', newstr(pbuf), e);
495c2aa98e2SPeter Wemm 
496c2aa98e2SPeter Wemm 	/* hop count */
497c2aa98e2SPeter Wemm 	(void) snprintf(cbuf, sizeof cbuf, "%d", e->e_hopcount);
498c2aa98e2SPeter Wemm 	define('c', newstr(cbuf), e);
499c2aa98e2SPeter Wemm 
500c2aa98e2SPeter Wemm 	/* time as integer, unix time, arpa time */
501c2aa98e2SPeter Wemm 	settime(e);
502c2aa98e2SPeter Wemm 
50306f25ae9SGregory Neil Shapiro 	/* Load average */
50406f25ae9SGregory Neil Shapiro 	(void)sm_getla(e);
50506f25ae9SGregory Neil Shapiro 
506c2aa98e2SPeter Wemm #ifdef TTYNAME
507c2aa98e2SPeter Wemm 	/* tty name */
508c2aa98e2SPeter Wemm 	if (macvalue('y', e) == NULL)
509c2aa98e2SPeter Wemm 	{
510c2aa98e2SPeter Wemm 		p = ttyname(2);
511c2aa98e2SPeter Wemm 		if (p != NULL)
512c2aa98e2SPeter Wemm 		{
513c2aa98e2SPeter Wemm 			if (strrchr(p, '/') != NULL)
514c2aa98e2SPeter Wemm 				p = strrchr(p, '/') + 1;
515c2aa98e2SPeter Wemm 			snprintf(ybuf, sizeof ybuf, "%s", p);
516c2aa98e2SPeter Wemm 			define('y', ybuf, e);
517c2aa98e2SPeter Wemm 		}
518c2aa98e2SPeter Wemm 	}
519c2aa98e2SPeter Wemm #endif /* TTYNAME */
520c2aa98e2SPeter Wemm }
521c2aa98e2SPeter Wemm /*
522c2aa98e2SPeter Wemm **  SETTIME -- set the current time.
523c2aa98e2SPeter Wemm **
524c2aa98e2SPeter Wemm **	Parameters:
52506f25ae9SGregory Neil Shapiro **		e -- the envelope in which the macros should be set.
526c2aa98e2SPeter Wemm **
527c2aa98e2SPeter Wemm **	Returns:
528c2aa98e2SPeter Wemm **		none.
529c2aa98e2SPeter Wemm **
530c2aa98e2SPeter Wemm **	Side Effects:
531c2aa98e2SPeter Wemm **		Sets the various time macros -- $a, $b, $d, $t.
532c2aa98e2SPeter Wemm */
533c2aa98e2SPeter Wemm 
534c2aa98e2SPeter Wemm void
535c2aa98e2SPeter Wemm settime(e)
536c2aa98e2SPeter Wemm 	register ENVELOPE *e;
537c2aa98e2SPeter Wemm {
538c2aa98e2SPeter Wemm 	register char *p;
539c2aa98e2SPeter Wemm 	auto time_t now;
540c2aa98e2SPeter Wemm 	char tbuf[20];				/* holds "current" time */
541c2aa98e2SPeter Wemm 	char dbuf[30];				/* holds ctime(tbuf) */
542c2aa98e2SPeter Wemm 	register struct tm *tm;
543c2aa98e2SPeter Wemm 
544c2aa98e2SPeter Wemm 	now = curtime();
545c2aa98e2SPeter Wemm 	tm = gmtime(&now);
546c2aa98e2SPeter Wemm 	(void) snprintf(tbuf, sizeof tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
547c2aa98e2SPeter Wemm 			tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
548c2aa98e2SPeter Wemm 	define('t', newstr(tbuf), e);
54906f25ae9SGregory Neil Shapiro 	(void) strlcpy(dbuf, ctime(&now), sizeof dbuf);
550c2aa98e2SPeter Wemm 	p = strchr(dbuf, '\n');
551c2aa98e2SPeter Wemm 	if (p != NULL)
552c2aa98e2SPeter Wemm 		*p = '\0';
553c2aa98e2SPeter Wemm 	define('d', newstr(dbuf), e);
554c2aa98e2SPeter Wemm 	p = arpadate(dbuf);
555c2aa98e2SPeter Wemm 	p = newstr(p);
556c2aa98e2SPeter Wemm 	if (macvalue('a', e) == NULL)
557c2aa98e2SPeter Wemm 		define('a', p, e);
558c2aa98e2SPeter Wemm 	define('b', p, e);
559c2aa98e2SPeter Wemm }
560c2aa98e2SPeter Wemm /*
561c2aa98e2SPeter Wemm **  OPENXSCRIPT -- Open transcript file
562c2aa98e2SPeter Wemm **
563c2aa98e2SPeter Wemm **	Creates a transcript file for possible eventual mailing or
564c2aa98e2SPeter Wemm **	sending back.
565c2aa98e2SPeter Wemm **
566c2aa98e2SPeter Wemm **	Parameters:
567c2aa98e2SPeter Wemm **		e -- the envelope to create the transcript in/for.
568c2aa98e2SPeter Wemm **
569c2aa98e2SPeter Wemm **	Returns:
570c2aa98e2SPeter Wemm **		none
571c2aa98e2SPeter Wemm **
572c2aa98e2SPeter Wemm **	Side Effects:
573c2aa98e2SPeter Wemm **		Creates the transcript file.
574c2aa98e2SPeter Wemm */
575c2aa98e2SPeter Wemm 
576c2aa98e2SPeter Wemm #ifndef O_APPEND
577c2aa98e2SPeter Wemm # define O_APPEND	0
57806f25ae9SGregory Neil Shapiro #endif /* ! O_APPEND */
579c2aa98e2SPeter Wemm 
580c2aa98e2SPeter Wemm void
581c2aa98e2SPeter Wemm openxscript(e)
582c2aa98e2SPeter Wemm 	register ENVELOPE *e;
583c2aa98e2SPeter Wemm {
584c2aa98e2SPeter Wemm 	register char *p;
585c2aa98e2SPeter Wemm 
586c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
587c2aa98e2SPeter Wemm 		return;
58806f25ae9SGregory Neil Shapiro 
58906f25ae9SGregory Neil Shapiro #if 0
59006f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
59106f25ae9SGregory Neil Shapiro 		syserr("openxscript: job not locked");
59206f25ae9SGregory Neil Shapiro #endif /* 0 */
59306f25ae9SGregory Neil Shapiro 
594c2aa98e2SPeter Wemm 	p = queuename(e, 'x');
59506f25ae9SGregory Neil Shapiro 	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
59606f25ae9SGregory Neil Shapiro 			  SFF_NOTEXCL|SFF_OPENASROOT);
59706f25ae9SGregory Neil Shapiro 
59806f25ae9SGregory Neil Shapiro 	if (e->e_xfp == NULL)
599c2aa98e2SPeter Wemm 	{
600c2aa98e2SPeter Wemm 		syserr("Can't create transcript file %s", p);
60106f25ae9SGregory Neil Shapiro 		e->e_xfp = fopen("/dev/null", "r+");
60206f25ae9SGregory Neil Shapiro 		if (e->e_xfp == NULL)
603c2aa98e2SPeter Wemm 			syserr("!Can't open /dev/null");
604c2aa98e2SPeter Wemm 	}
60506f25ae9SGregory Neil Shapiro #if HASSETVBUF
60606f25ae9SGregory Neil Shapiro 	(void) setvbuf(e->e_xfp, NULL, _IOLBF, 0);
60706f25ae9SGregory Neil Shapiro #else /* HASSETVBUF */
60806f25ae9SGregory Neil Shapiro 	(void) setlinebuf(e->e_xfp);
60906f25ae9SGregory Neil Shapiro #endif /* HASSETVBUF */
610c2aa98e2SPeter Wemm 	if (tTd(46, 9))
611c2aa98e2SPeter Wemm 	{
61206f25ae9SGregory Neil Shapiro 		dprintf("openxscript(%s):\n  ", p);
613c2aa98e2SPeter Wemm 		dumpfd(fileno(e->e_xfp), TRUE, FALSE);
614c2aa98e2SPeter Wemm 	}
615c2aa98e2SPeter Wemm }
616c2aa98e2SPeter Wemm /*
617c2aa98e2SPeter Wemm **  CLOSEXSCRIPT -- close the transcript file.
618c2aa98e2SPeter Wemm **
619c2aa98e2SPeter Wemm **	Parameters:
620c2aa98e2SPeter Wemm **		e -- the envelope containing the transcript to close.
621c2aa98e2SPeter Wemm **
622c2aa98e2SPeter Wemm **	Returns:
623c2aa98e2SPeter Wemm **		none.
624c2aa98e2SPeter Wemm **
625c2aa98e2SPeter Wemm **	Side Effects:
626c2aa98e2SPeter Wemm **		none.
627c2aa98e2SPeter Wemm */
628c2aa98e2SPeter Wemm 
629c2aa98e2SPeter Wemm void
630c2aa98e2SPeter Wemm closexscript(e)
631c2aa98e2SPeter Wemm 	register ENVELOPE *e;
632c2aa98e2SPeter Wemm {
633c2aa98e2SPeter Wemm 	if (e->e_xfp == NULL)
634c2aa98e2SPeter Wemm 		return;
63506f25ae9SGregory Neil Shapiro #if 0
63606f25ae9SGregory Neil Shapiro 	if (e->e_lockfp == NULL)
63706f25ae9SGregory Neil Shapiro 		syserr("closexscript: job not locked");
63806f25ae9SGregory Neil Shapiro #endif /* 0 */
63906f25ae9SGregory Neil Shapiro 	(void) bfclose(e->e_xfp);
640c2aa98e2SPeter Wemm 	e->e_xfp = NULL;
641c2aa98e2SPeter Wemm }
642c2aa98e2SPeter Wemm /*
643c2aa98e2SPeter Wemm **  SETSENDER -- set the person who this message is from
644c2aa98e2SPeter Wemm **
645c2aa98e2SPeter Wemm **	Under certain circumstances allow the user to say who
646c2aa98e2SPeter Wemm **	s/he is (using -f or -r).  These are:
647c2aa98e2SPeter Wemm **	1.  The user's uid is zero (root).
648c2aa98e2SPeter Wemm **	2.  The user's login name is in an approved list (typically
649c2aa98e2SPeter Wemm **	    from a network server).
650c2aa98e2SPeter Wemm **	3.  The address the user is trying to claim has a
651c2aa98e2SPeter Wemm **	    "!" character in it (since #2 doesn't do it for
652c2aa98e2SPeter Wemm **	    us if we are dialing out for UUCP).
653c2aa98e2SPeter Wemm **	A better check to replace #3 would be if the
654c2aa98e2SPeter Wemm **	effective uid is "UUCP" -- this would require me
655c2aa98e2SPeter Wemm **	to rewrite getpwent to "grab" uucp as it went by,
656c2aa98e2SPeter Wemm **	make getname more nasty, do another passwd file
657c2aa98e2SPeter Wemm **	scan, or compile the UID of "UUCP" into the code,
658c2aa98e2SPeter Wemm **	all of which are reprehensible.
659c2aa98e2SPeter Wemm **
660c2aa98e2SPeter Wemm **	Assuming all of these fail, we figure out something
661c2aa98e2SPeter Wemm **	ourselves.
662c2aa98e2SPeter Wemm **
663c2aa98e2SPeter Wemm **	Parameters:
664c2aa98e2SPeter Wemm **		from -- the person we would like to believe this message
665c2aa98e2SPeter Wemm **			is from, as specified on the command line.
666c2aa98e2SPeter Wemm **		e -- the envelope in which we would like the sender set.
667c2aa98e2SPeter Wemm **		delimptr -- if non-NULL, set to the location of the
668c2aa98e2SPeter Wemm **			trailing delimiter.
669c2aa98e2SPeter Wemm **		delimchar -- the character that will delimit the sender
670c2aa98e2SPeter Wemm **			address.
671c2aa98e2SPeter Wemm **		internal -- set if this address is coming from an internal
672c2aa98e2SPeter Wemm **			source such as an owner alias.
673c2aa98e2SPeter Wemm **
674c2aa98e2SPeter Wemm **	Returns:
675c2aa98e2SPeter Wemm **		none.
676c2aa98e2SPeter Wemm **
677c2aa98e2SPeter Wemm **	Side Effects:
678c2aa98e2SPeter Wemm **		sets sendmail's notion of who the from person is.
679c2aa98e2SPeter Wemm */
680c2aa98e2SPeter Wemm 
681c2aa98e2SPeter Wemm void
682c2aa98e2SPeter Wemm setsender(from, e, delimptr, delimchar, internal)
683c2aa98e2SPeter Wemm 	char *from;
684c2aa98e2SPeter Wemm 	register ENVELOPE *e;
685c2aa98e2SPeter Wemm 	char **delimptr;
686c2aa98e2SPeter Wemm 	int delimchar;
687c2aa98e2SPeter Wemm 	bool internal;
688c2aa98e2SPeter Wemm {
689c2aa98e2SPeter Wemm 	register char **pvp;
690c2aa98e2SPeter Wemm 	char *realname = NULL;
691c2aa98e2SPeter Wemm 	register struct passwd *pw;
692c2aa98e2SPeter Wemm 	char *bp;
693c2aa98e2SPeter Wemm 	char buf[MAXNAME + 2];
694c2aa98e2SPeter Wemm 	char pvpbuf[PSBUFSIZE];
695c2aa98e2SPeter Wemm 	extern char *FullName;
696c2aa98e2SPeter Wemm 
697c2aa98e2SPeter Wemm 	if (tTd(45, 1))
69806f25ae9SGregory Neil Shapiro 		dprintf("setsender(%s)\n", from == NULL ? "" : from);
699c2aa98e2SPeter Wemm 
700c2aa98e2SPeter Wemm 	/*
701c2aa98e2SPeter Wemm 	**  Figure out the real user executing us.
702c2aa98e2SPeter Wemm 	**	Username can return errno != 0 on non-errors.
703c2aa98e2SPeter Wemm 	*/
704c2aa98e2SPeter Wemm 
705c2aa98e2SPeter Wemm 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
706c2aa98e2SPeter Wemm 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
707c2aa98e2SPeter Wemm 		realname = from;
708c2aa98e2SPeter Wemm 	if (realname == NULL || realname[0] == '\0')
709c2aa98e2SPeter Wemm 		realname = username();
710c2aa98e2SPeter Wemm 
711c2aa98e2SPeter Wemm 	if (ConfigLevel < 2)
712c2aa98e2SPeter Wemm 		SuprErrs = TRUE;
713c2aa98e2SPeter Wemm 
71406f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
71506f25ae9SGregory Neil Shapiro 	define(macid("{addr_type}", NULL), "e s", e);
71606f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
71706f25ae9SGregory Neil Shapiro 	/* preset state for then clause in case from == NULL */
71806f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_BADADDR;
71906f25ae9SGregory Neil Shapiro 	e->e_from.q_flags = 0;
720c2aa98e2SPeter Wemm 	if (from == NULL ||
721c2aa98e2SPeter Wemm 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
722c2aa98e2SPeter Wemm 		      delimchar, delimptr, e) == NULL ||
72306f25ae9SGregory Neil Shapiro 	    QS_IS_BADADDR(e->e_from.q_state) ||
724c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == ProgMailer ||
725c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == FileMailer ||
726c2aa98e2SPeter Wemm 	    e->e_from.q_mailer == InclMailer)
727c2aa98e2SPeter Wemm 	{
728c2aa98e2SPeter Wemm 		/* log garbage addresses for traceback */
729c2aa98e2SPeter Wemm 		if (from != NULL && LogLevel > 2)
730c2aa98e2SPeter Wemm 		{
731c2aa98e2SPeter Wemm 			char *p;
732c2aa98e2SPeter Wemm 			char ebuf[MAXNAME * 2 + 2];
733c2aa98e2SPeter Wemm 
734c2aa98e2SPeter Wemm 			p = macvalue('_', e);
735c2aa98e2SPeter Wemm 			if (p == NULL)
736c2aa98e2SPeter Wemm 			{
737c2aa98e2SPeter Wemm 				char *host = RealHostName;
738c2aa98e2SPeter Wemm 
739c2aa98e2SPeter Wemm 				if (host == NULL)
740c2aa98e2SPeter Wemm 					host = MyHostName;
741c2aa98e2SPeter Wemm 				(void) snprintf(ebuf, sizeof ebuf, "%.*s@%.*s",
742c2aa98e2SPeter Wemm 					MAXNAME, realname,
743c2aa98e2SPeter Wemm 					MAXNAME, host);
744c2aa98e2SPeter Wemm 				p = ebuf;
745c2aa98e2SPeter Wemm 			}
746c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
74706f25ae9SGregory Neil Shapiro 				  "setsender: %s: invalid or unparsable, received from %s",
748c2aa98e2SPeter Wemm 				  shortenstring(from, 83), p);
749c2aa98e2SPeter Wemm 		}
750c2aa98e2SPeter Wemm 		if (from != NULL)
751c2aa98e2SPeter Wemm 		{
75206f25ae9SGregory Neil Shapiro 			if (!QS_IS_BADADDR(e->e_from.q_state))
753c2aa98e2SPeter Wemm 			{
754c2aa98e2SPeter Wemm 				/* it was a bogus mailer in the from addr */
755c2aa98e2SPeter Wemm 				e->e_status = "5.1.7";
75606f25ae9SGregory Neil Shapiro 				usrerrenh(e->e_status,
75706f25ae9SGregory Neil Shapiro 					  "553 Invalid sender address");
758c2aa98e2SPeter Wemm 			}
759c2aa98e2SPeter Wemm 			SuprErrs = TRUE;
760c2aa98e2SPeter Wemm 		}
761c2aa98e2SPeter Wemm 		if (from == realname ||
762c2aa98e2SPeter Wemm 		    parseaddr(from = newstr(realname), &e->e_from,
763c2aa98e2SPeter Wemm 			      RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
764c2aa98e2SPeter Wemm 		{
765c2aa98e2SPeter Wemm 			char nbuf[100];
766c2aa98e2SPeter Wemm 
767c2aa98e2SPeter Wemm 			SuprErrs = TRUE;
768c2aa98e2SPeter Wemm 			expand("\201n", nbuf, sizeof nbuf, e);
769c2aa98e2SPeter Wemm 			if (parseaddr(from = newstr(nbuf), &e->e_from,
770c2aa98e2SPeter Wemm 				      RF_COPYALL, ' ', NULL, e) == NULL &&
771c2aa98e2SPeter Wemm 			    parseaddr(from = "postmaster", &e->e_from,
772c2aa98e2SPeter Wemm 				      RF_COPYALL, ' ', NULL, e) == NULL)
77306f25ae9SGregory Neil Shapiro 				syserr("553 5.3.0 setsender: can't even parse postmaster!");
774c2aa98e2SPeter Wemm 		}
775c2aa98e2SPeter Wemm 	}
776c2aa98e2SPeter Wemm 	else
777c2aa98e2SPeter Wemm 		FromFlag = TRUE;
77806f25ae9SGregory Neil Shapiro 	e->e_from.q_state = QS_SENDER;
779c2aa98e2SPeter Wemm 	if (tTd(45, 5))
780c2aa98e2SPeter Wemm 	{
78106f25ae9SGregory Neil Shapiro 		dprintf("setsender: QS_SENDER ");
782c2aa98e2SPeter Wemm 		printaddr(&e->e_from, FALSE);
783c2aa98e2SPeter Wemm 	}
784c2aa98e2SPeter Wemm 	SuprErrs = FALSE;
785c2aa98e2SPeter Wemm 
786c2aa98e2SPeter Wemm #if USERDB
787c2aa98e2SPeter Wemm 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
788c2aa98e2SPeter Wemm 	{
789c2aa98e2SPeter Wemm 		register char *p;
790c2aa98e2SPeter Wemm 
791c2aa98e2SPeter Wemm 		p = udbsender(e->e_from.q_user);
792c2aa98e2SPeter Wemm 		if (p != NULL)
793c2aa98e2SPeter Wemm 			from = p;
794c2aa98e2SPeter Wemm 	}
795c2aa98e2SPeter Wemm #endif /* USERDB */
796c2aa98e2SPeter Wemm 
797c2aa98e2SPeter Wemm 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
798c2aa98e2SPeter Wemm 	{
799c2aa98e2SPeter Wemm 		if (!internal)
800c2aa98e2SPeter Wemm 		{
801c2aa98e2SPeter Wemm 			/* if the user already given fullname don't redefine */
802c2aa98e2SPeter Wemm 			if (FullName == NULL)
803c2aa98e2SPeter Wemm 				FullName = macvalue('x', e);
804c2aa98e2SPeter Wemm 			if (FullName != NULL && FullName[0] == '\0')
805c2aa98e2SPeter Wemm 				FullName = NULL;
806c2aa98e2SPeter Wemm 		}
807c2aa98e2SPeter Wemm 
808c2aa98e2SPeter Wemm 		if (e->e_from.q_user[0] != '\0' &&
809c2aa98e2SPeter Wemm 		    (pw = sm_getpwnam(e->e_from.q_user)) != NULL)
810c2aa98e2SPeter Wemm 		{
811c2aa98e2SPeter Wemm 			/*
812c2aa98e2SPeter Wemm 			**  Process passwd file entry.
813c2aa98e2SPeter Wemm 			*/
814c2aa98e2SPeter Wemm 
815c2aa98e2SPeter Wemm 			/* extract home directory */
81642e5d165SGregory Neil Shapiro 			if (*pw->pw_dir == '\0')
81742e5d165SGregory Neil Shapiro 				e->e_from.q_home = NULL;
81842e5d165SGregory Neil Shapiro 			else if (strcmp(pw->pw_dir, "/") == 0)
819c2aa98e2SPeter Wemm 				e->e_from.q_home = newstr("");
820c2aa98e2SPeter Wemm 			else
821c2aa98e2SPeter Wemm 				e->e_from.q_home = newstr(pw->pw_dir);
822c2aa98e2SPeter Wemm 			define('z', e->e_from.q_home, e);
823c2aa98e2SPeter Wemm 
824c2aa98e2SPeter Wemm 			/* extract user and group id */
825c2aa98e2SPeter Wemm 			e->e_from.q_uid = pw->pw_uid;
826c2aa98e2SPeter Wemm 			e->e_from.q_gid = pw->pw_gid;
827c2aa98e2SPeter Wemm 			e->e_from.q_flags |= QGOODUID;
828c2aa98e2SPeter Wemm 
829c2aa98e2SPeter Wemm 			/* extract full name from passwd file */
830c2aa98e2SPeter Wemm 			if (FullName == NULL && pw->pw_gecos != NULL &&
831c2aa98e2SPeter Wemm 			    strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
832c2aa98e2SPeter Wemm 			    !internal)
833c2aa98e2SPeter Wemm 			{
834c2aa98e2SPeter Wemm 				buildfname(pw->pw_gecos, e->e_from.q_user, buf, sizeof buf);
835c2aa98e2SPeter Wemm 				if (buf[0] != '\0')
836c2aa98e2SPeter Wemm 					FullName = newstr(buf);
837c2aa98e2SPeter Wemm 			}
838c2aa98e2SPeter Wemm 		}
839c2aa98e2SPeter Wemm 		else
840c2aa98e2SPeter Wemm 		{
84106f25ae9SGregory Neil Shapiro 			e->e_from.q_home = NULL;
842c2aa98e2SPeter Wemm 		}
843c2aa98e2SPeter Wemm 		if (FullName != NULL && !internal)
844c2aa98e2SPeter Wemm 			define('x', FullName, e);
845c2aa98e2SPeter Wemm 	}
8462e43090eSPeter Wemm 	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
847c2aa98e2SPeter Wemm 	{
848c2aa98e2SPeter Wemm 		if (e->e_from.q_home == NULL)
849c2aa98e2SPeter Wemm 		{
850c2aa98e2SPeter Wemm 			e->e_from.q_home = getenv("HOME");
85142e5d165SGregory Neil Shapiro 			if (e->e_from.q_home != NULL)
85242e5d165SGregory Neil Shapiro 			{
85342e5d165SGregory Neil Shapiro 				if (*e->e_from.q_home == '\0')
85442e5d165SGregory Neil Shapiro 					e->e_from.q_home = NULL;
85542e5d165SGregory Neil Shapiro 				else if (strcmp(e->e_from.q_home, "/") == 0)
856c2aa98e2SPeter Wemm 					e->e_from.q_home++;
857c2aa98e2SPeter Wemm 			}
85842e5d165SGregory Neil Shapiro 		}
859c2aa98e2SPeter Wemm 		e->e_from.q_uid = RealUid;
860c2aa98e2SPeter Wemm 		e->e_from.q_gid = RealGid;
861c2aa98e2SPeter Wemm 		e->e_from.q_flags |= QGOODUID;
862c2aa98e2SPeter Wemm 	}
863c2aa98e2SPeter Wemm 
864c2aa98e2SPeter Wemm 	/*
865c2aa98e2SPeter Wemm 	**  Rewrite the from person to dispose of possible implicit
866c2aa98e2SPeter Wemm 	**	links in the net.
867c2aa98e2SPeter Wemm 	*/
868c2aa98e2SPeter Wemm 
869c2aa98e2SPeter Wemm 	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL);
870c2aa98e2SPeter Wemm 	if (pvp == NULL)
871c2aa98e2SPeter Wemm 	{
872c2aa98e2SPeter Wemm 		/* don't need to give error -- prescan did that already */
873c2aa98e2SPeter Wemm 		if (LogLevel > 2)
874c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, e->e_id,
875c2aa98e2SPeter Wemm 				  "cannot prescan from (%s)",
876c2aa98e2SPeter Wemm 				  shortenstring(from, MAXSHORTSTR));
877065a643dSPeter Wemm 		finis(TRUE, ExitStat);
878c2aa98e2SPeter Wemm 	}
879c2aa98e2SPeter Wemm 	(void) rewrite(pvp, 3, 0, e);
880c2aa98e2SPeter Wemm 	(void) rewrite(pvp, 1, 0, e);
881c2aa98e2SPeter Wemm 	(void) rewrite(pvp, 4, 0, e);
88206f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
88306f25ae9SGregory Neil Shapiro 	define(macid("{addr_type}", NULL), NULL, e);
88406f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
885c2aa98e2SPeter Wemm 	bp = buf + 1;
886c2aa98e2SPeter Wemm 	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
887c2aa98e2SPeter Wemm 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
888c2aa98e2SPeter Wemm 	{
889c2aa98e2SPeter Wemm 		/* heuristic: route-addr: add angle brackets */
89006f25ae9SGregory Neil Shapiro 		(void) strlcat(bp, ">", sizeof buf - 1);
891c2aa98e2SPeter Wemm 		*--bp = '<';
892c2aa98e2SPeter Wemm 	}
893c2aa98e2SPeter Wemm 	e->e_sender = newstr(bp);
894c2aa98e2SPeter Wemm 	define('f', e->e_sender, e);
895c2aa98e2SPeter Wemm 
896c2aa98e2SPeter Wemm 	/* save the domain spec if this mailer wants it */
897c2aa98e2SPeter Wemm 	if (e->e_from.q_mailer != NULL &&
898c2aa98e2SPeter Wemm 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
899c2aa98e2SPeter Wemm 	{
900c2aa98e2SPeter Wemm 		char **lastat;
901c2aa98e2SPeter Wemm 
902c2aa98e2SPeter Wemm 		/* get rid of any pesky angle brackets */
90306f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
90406f25ae9SGregory Neil Shapiro 		define(macid("{addr_type}", NULL), "e s", e);
90506f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
906c2aa98e2SPeter Wemm 		(void) rewrite(pvp, 3, 0, e);
907c2aa98e2SPeter Wemm 		(void) rewrite(pvp, 1, 0, e);
908c2aa98e2SPeter Wemm 		(void) rewrite(pvp, 4, 0, e);
90906f25ae9SGregory Neil Shapiro #if _FFR_ADDR_TYPE
91006f25ae9SGregory Neil Shapiro 		define(macid("{addr_type}", NULL), NULL, e);
91106f25ae9SGregory Neil Shapiro #endif /* _FFR_ADDR_TYPE */
912c2aa98e2SPeter Wemm 
913c2aa98e2SPeter Wemm 		/* strip off to the last "@" sign */
914c2aa98e2SPeter Wemm 		for (lastat = NULL; *pvp != NULL; pvp++)
915c2aa98e2SPeter Wemm 			if (strcmp(*pvp, "@") == 0)
916c2aa98e2SPeter Wemm 				lastat = pvp;
917c2aa98e2SPeter Wemm 		if (lastat != NULL)
918c2aa98e2SPeter Wemm 		{
919c2aa98e2SPeter Wemm 			e->e_fromdomain = copyplist(lastat, TRUE);
920c2aa98e2SPeter Wemm 			if (tTd(45, 3))
921c2aa98e2SPeter Wemm 			{
92206f25ae9SGregory Neil Shapiro 				dprintf("Saving from domain: ");
923c2aa98e2SPeter Wemm 				printav(e->e_fromdomain);
924c2aa98e2SPeter Wemm 			}
925c2aa98e2SPeter Wemm 		}
926c2aa98e2SPeter Wemm 	}
927c2aa98e2SPeter Wemm }
928c2aa98e2SPeter Wemm /*
929c2aa98e2SPeter Wemm **  PRINTENVFLAGS -- print envelope flags for debugging
930c2aa98e2SPeter Wemm **
931c2aa98e2SPeter Wemm **	Parameters:
932c2aa98e2SPeter Wemm **		e -- the envelope with the flags to be printed.
933c2aa98e2SPeter Wemm **
934c2aa98e2SPeter Wemm **	Returns:
935c2aa98e2SPeter Wemm **		none.
936c2aa98e2SPeter Wemm */
937c2aa98e2SPeter Wemm 
938c2aa98e2SPeter Wemm struct eflags
939c2aa98e2SPeter Wemm {
940c2aa98e2SPeter Wemm 	char	*ef_name;
941c2aa98e2SPeter Wemm 	u_long	ef_bit;
942c2aa98e2SPeter Wemm };
943c2aa98e2SPeter Wemm 
94406f25ae9SGregory Neil Shapiro static struct eflags	EnvelopeFlags[] =
945c2aa98e2SPeter Wemm {
946c2aa98e2SPeter Wemm 	{ "OLDSTYLE",		EF_OLDSTYLE	},
947c2aa98e2SPeter Wemm 	{ "INQUEUE",		EF_INQUEUE	},
948c2aa98e2SPeter Wemm 	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
949c2aa98e2SPeter Wemm 	{ "CLRQUEUE",		EF_CLRQUEUE	},
950c2aa98e2SPeter Wemm 	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
951c2aa98e2SPeter Wemm 	{ "FATALERRS",		EF_FATALERRS	},
952c2aa98e2SPeter Wemm 	{ "DELETE_BCC",		EF_DELETE_BCC	},
953c2aa98e2SPeter Wemm 	{ "RESPONSE",		EF_RESPONSE	},
954c2aa98e2SPeter Wemm 	{ "RESENT",		EF_RESENT	},
955c2aa98e2SPeter Wemm 	{ "VRFYONLY",		EF_VRFYONLY	},
956c2aa98e2SPeter Wemm 	{ "WARNING",		EF_WARNING	},
957c2aa98e2SPeter Wemm 	{ "QUEUERUN",		EF_QUEUERUN	},
958c2aa98e2SPeter Wemm 	{ "GLOBALERRS",		EF_GLOBALERRS	},
959c2aa98e2SPeter Wemm 	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
960c2aa98e2SPeter Wemm 	{ "METOO",		EF_METOO	},
961c2aa98e2SPeter Wemm 	{ "LOGSENDER",		EF_LOGSENDER	},
962c2aa98e2SPeter Wemm 	{ "NORECEIPT",		EF_NORECEIPT	},
963c2aa98e2SPeter Wemm 	{ "HAS8BIT",		EF_HAS8BIT	},
964c2aa98e2SPeter Wemm 	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
965c2aa98e2SPeter Wemm 	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
966c2aa98e2SPeter Wemm 	{ "RET_PARAM",		EF_RET_PARAM	},
967c2aa98e2SPeter Wemm 	{ "HAS_DF",		EF_HAS_DF	},
968c2aa98e2SPeter Wemm 	{ "IS_MIME",		EF_IS_MIME	},
969c2aa98e2SPeter Wemm 	{ "DONT_MIME",		EF_DONT_MIME	},
970193538b7SGregory Neil Shapiro 	{ NULL,			0		}
971c2aa98e2SPeter Wemm };
972c2aa98e2SPeter Wemm 
973c2aa98e2SPeter Wemm void
974c2aa98e2SPeter Wemm printenvflags(e)
975c2aa98e2SPeter Wemm 	register ENVELOPE *e;
976c2aa98e2SPeter Wemm {
977c2aa98e2SPeter Wemm 	register struct eflags *ef;
978c2aa98e2SPeter Wemm 	bool first = TRUE;
979c2aa98e2SPeter Wemm 
980c2aa98e2SPeter Wemm 	printf("%lx", e->e_flags);
981c2aa98e2SPeter Wemm 	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
982c2aa98e2SPeter Wemm 	{
983c2aa98e2SPeter Wemm 		if (!bitset(ef->ef_bit, e->e_flags))
984c2aa98e2SPeter Wemm 			continue;
985c2aa98e2SPeter Wemm 		if (first)
986c2aa98e2SPeter Wemm 			printf("<%s", ef->ef_name);
987c2aa98e2SPeter Wemm 		else
988c2aa98e2SPeter Wemm 			printf(",%s", ef->ef_name);
989c2aa98e2SPeter Wemm 		first = FALSE;
990c2aa98e2SPeter Wemm 	}
991c2aa98e2SPeter Wemm 	if (!first)
992c2aa98e2SPeter Wemm 		printf(">\n");
993c2aa98e2SPeter Wemm }
994