1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)envelope.c	8.47 (Berkeley) 11/22/94";
11 #endif /* not lint */
12 
13 #include "sendmail.h"
14 #include <pwd.h>
15 
16 /*
17 **  NEWENVELOPE -- allocate a new envelope
18 **
19 **	Supports inheritance.
20 **
21 **	Parameters:
22 **		e -- the new envelope to fill in.
23 **		parent -- the envelope to be the parent of e.
24 **
25 **	Returns:
26 **		e.
27 **
28 **	Side Effects:
29 **		none.
30 */
31 
32 ENVELOPE *
33 newenvelope(e, parent)
34 	register ENVELOPE *e;
35 	register ENVELOPE *parent;
36 {
37 	extern putheader(), putbody();
38 	extern ENVELOPE BlankEnvelope;
39 
40 	if (e == parent && e->e_parent != NULL)
41 		parent = e->e_parent;
42 	clearenvelope(e, TRUE);
43 	if (e == CurEnv)
44 		bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from);
45 	else
46 		bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
47 	e->e_parent = parent;
48 	e->e_ctime = curtime();
49 	if (parent != NULL)
50 		e->e_msgpriority = parent->e_msgsize;
51 	e->e_puthdr = putheader;
52 	e->e_putbody = putbody;
53 	if (CurEnv->e_xfp != NULL)
54 		(void) fflush(CurEnv->e_xfp);
55 
56 	return (e);
57 }
58 /*
59 **  DROPENVELOPE -- deallocate an envelope.
60 **
61 **	Parameters:
62 **		e -- the envelope to deallocate.
63 **
64 **	Returns:
65 **		none.
66 **
67 **	Side Effects:
68 **		housekeeping necessary to dispose of an envelope.
69 **		Unlocks this queue file.
70 */
71 
72 void
73 dropenvelope(e)
74 	register ENVELOPE *e;
75 {
76 	bool queueit = FALSE;
77 	bool failure_return = FALSE;
78 	bool success_return = FALSE;
79 	register ADDRESS *q;
80 	char *id = e->e_id;
81 	bool return_no, return_yes;
82 	char buf[MAXLINE];
83 
84 	if (tTd(50, 1))
85 	{
86 		printf("dropenvelope %x: id=", e);
87 		xputs(e->e_id);
88 		printf(", flags=0x%x\n", e->e_flags);
89 		if (tTd(50, 10))
90 		{
91 			printf("sendq=");
92 			printaddr(e->e_sendqueue, TRUE);
93 		}
94 	}
95 
96 	/* we must have an id to remove disk files */
97 	if (id == NULL)
98 		return;
99 
100 #ifdef LOG
101 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
102 		logsender(e, NULL);
103 	if (LogLevel > 84)
104 		syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=0x%x, pid=%d",
105 				  id, e->e_flags, getpid());
106 #endif /* LOG */
107 	e->e_flags &= ~EF_LOGSENDER;
108 
109 	/* post statistics */
110 	poststats(StatFile);
111 
112 	/*
113 	**  Extract state information from dregs of send list.
114 	*/
115 
116 	e->e_flags &= ~EF_QUEUERUN;
117 	return_no = return_yes = FALSE;
118 	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
119 	{
120 		if (bitset(QQUEUEUP, q->q_flags))
121 			queueit = TRUE;
122 
123 		/* see if a notification is needed */
124 		if (e->e_df != NULL &&
125 		    bitset(QBADADDR, q->q_flags) &&
126 		    bitset(QPINGONFAILURE, q->q_flags))
127 		{
128 			failure_return = TRUE;
129 			if (q->q_owner == NULL && !emptyaddr(&e->e_from))
130 				(void) sendtolist(e->e_from.q_paddr, NULL,
131 						  &e->e_errorqueue, 0, e);
132 		}
133 		else if (bitset(QSENT, q->q_flags) &&
134 		    bitnset(M_LOCALMAILER, q->q_mailer->m_flags) &&
135 		    bitset(QPINGONSUCCESS, q->q_flags))
136 		{
137 			success_return = TRUE;
138 		}
139 		else if (bitset(QRELAYED, q->q_flags))
140 		{
141 			success_return = TRUE;
142 		}
143 		else
144 			continue;
145 
146 		/* common code for error returns and return receipts */
147 
148 		/* test for returning the body */
149 		if (bitset(QHAS_RET_PARAM, q->q_flags))
150 		{
151 			if (bitset(QRET_HDRS, q->q_flags))
152 				return_no = TRUE;
153 			else
154 				return_yes = TRUE;
155 		}
156 	}
157 	if (return_no && !return_yes)
158 		e->e_flags |= EF_NORETURN;
159 
160 	/*
161 	**  See if the message timed out.
162 	*/
163 
164 	if (!queueit)
165 		/* nothing to do */ ;
166 	else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
167 	{
168 		(void) sprintf(buf, "Cannot send message for %s",
169 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
170 		if (e->e_message != NULL)
171 			free(e->e_message);
172 		e->e_message = newstr(buf);
173 		message(buf);
174 		e->e_flags |= EF_CLRQUEUE;
175 		failure_return = TRUE;
176 		fprintf(e->e_xfp, "Message could not be delivered for %s\n",
177 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
178 		fprintf(e->e_xfp, "Message will be deleted from queue\n");
179 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
180 		{
181 			if (bitset(QQUEUEUP, q->q_flags))
182 				q->q_flags |= QBADADDR;
183 		}
184 	}
185 	else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
186 	    curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
187 	{
188 		bool delay_return = FALSE;
189 
190 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
191 		{
192 			if (bitset(QQUEUEUP, q->q_flags) &&
193 			    bitset(QPINGONDELAY, q->q_flags))
194 			{
195 				q->q_flags |= QREPORT;
196 				delay_return = TRUE;
197 			}
198 		}
199 		if (delay_return &&
200 		    !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
201 		    e->e_class >= 0 &&
202 		    strcmp(e->e_from.q_paddr, "<>") != 0 &&
203 		    strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
204 		    (strlen(e->e_from.q_paddr) <= 8 ||
205 		     strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
206 		{
207 			(void) sprintf(buf,
208 				"Warning: cannot send message for %s",
209 				pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
210 			if (e->e_message != NULL)
211 				free(e->e_message);
212 			e->e_message = newstr(buf);
213 			message(buf);
214 			e->e_flags |= EF_WARNING;
215 			failure_return = TRUE;
216 		}
217 		fprintf(e->e_xfp,
218 			"Warning: message still undelivered after %s\n",
219 			pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
220 		fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
221 			pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
222 	}
223 
224 	if (tTd(50, 2))
225 		printf("failure_return=%d success_return=%d queueit=%d\n",
226 			failure_return, success_return, queueit);
227 
228 	/*
229 	**  Send back return receipts as requested.
230 	*/
231 
232 /*
233 	if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)
234 	    && !bitset(PRIV_NORECEIPTS, PrivacyFlags))
235 */
236 	if (e->e_receiptto == NULL)
237 		e->e_receiptto = e->e_from.q_paddr;
238 	if (success_return && !failure_return &&
239 	    strcmp(e->e_receiptto, "<>") != 0)
240 	{
241 		auto ADDRESS *rlist = NULL;
242 
243 		e->e_flags |= EF_SENDRECEIPT;
244 		(void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e);
245 		(void) returntosender("Return receipt", rlist, return_yes, e);
246 	}
247 	e->e_flags &= ~EF_SENDRECEIPT;
248 
249 	/*
250 	**  Arrange to send error messages if there are fatal errors.
251 	*/
252 
253 	if (failure_return && e->e_errormode != EM_QUIET)
254 		savemail(e, return_yes || (!return_no && e->e_class >= 0));
255 
256 	/*
257 	**  Arrange to send warning messages to postmaster as requested.
258 	*/
259 
260 	if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL &&
261 	    !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0)
262 	{
263 		auto ADDRESS *rlist = NULL;
264 
265 		(void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
266 		(void) returntosender(e->e_message, rlist, FALSE, e);
267 	}
268 
269 	/*
270 	**  Instantiate or deinstantiate the queue.
271 	*/
272 
273 	if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
274 	    bitset(EF_CLRQUEUE, e->e_flags))
275 	{
276 		if (tTd(50, 1))
277 			printf("\n===== Dropping [dq]f%s (queueit=%d, e_flags=%x) =====\n\n",
278 				e->e_id, queueit, e->e_flags);
279 		if (e->e_df != NULL)
280 			xunlink(e->e_df);
281 		xunlink(queuename(e, 'q'));
282 
283 #ifdef LOG
284 		if (LogLevel > 10)
285 			syslog(LOG_INFO, "%s: done", id);
286 #endif
287 	}
288 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
289 	{
290 #ifdef QUEUE
291 		queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE);
292 #else /* QUEUE */
293 		syserr("554 dropenvelope: queueup");
294 #endif /* QUEUE */
295 	}
296 
297 	/* now unlock the job */
298 	closexscript(e);
299 	unlockqueue(e);
300 
301 	/* make sure that this envelope is marked unused */
302 	if (e->e_dfp != NULL)
303 		(void) xfclose(e->e_dfp, "dropenvelope", e->e_df);
304 	e->e_dfp = NULL;
305 	e->e_id = e->e_df = NULL;
306 }
307 /*
308 **  CLEARENVELOPE -- clear an envelope without unlocking
309 **
310 **	This is normally used by a child process to get a clean
311 **	envelope without disturbing the parent.
312 **
313 **	Parameters:
314 **		e -- the envelope to clear.
315 **		fullclear - if set, the current envelope is total
316 **			garbage and should be ignored; otherwise,
317 **			release any resources it may indicate.
318 **
319 **	Returns:
320 **		none.
321 **
322 **	Side Effects:
323 **		Closes files associated with the envelope.
324 **		Marks the envelope as unallocated.
325 */
326 
327 void
328 clearenvelope(e, fullclear)
329 	register ENVELOPE *e;
330 	bool fullclear;
331 {
332 	register HDR *bh;
333 	register HDR **nhp;
334 	extern ENVELOPE BlankEnvelope;
335 
336 	if (!fullclear)
337 	{
338 		/* clear out any file information */
339 		if (e->e_xfp != NULL)
340 			(void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
341 		if (e->e_dfp != NULL)
342 			(void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df);
343 		e->e_xfp = e->e_dfp = NULL;
344 	}
345 
346 	/* now clear out the data */
347 	STRUCTCOPY(BlankEnvelope, *e);
348 	if (Verbose)
349 		e->e_sendmode = SM_DELIVER;
350 	bh = BlankEnvelope.e_header;
351 	nhp = &e->e_header;
352 	while (bh != NULL)
353 	{
354 		*nhp = (HDR *) xalloc(sizeof *bh);
355 		bcopy((char *) bh, (char *) *nhp, sizeof *bh);
356 		bh = bh->h_link;
357 		nhp = &(*nhp)->h_link;
358 	}
359 }
360 /*
361 **  INITSYS -- initialize instantiation of system
362 **
363 **	In Daemon mode, this is done in the child.
364 **
365 **	Parameters:
366 **		none.
367 **
368 **	Returns:
369 **		none.
370 **
371 **	Side Effects:
372 **		Initializes the system macros, some global variables,
373 **		etc.  In particular, the current time in various
374 **		forms is set.
375 */
376 
377 void
378 initsys(e)
379 	register ENVELOPE *e;
380 {
381 	char cbuf[5];				/* holds hop count */
382 	char pbuf[10];				/* holds pid */
383 #ifdef TTYNAME
384 	static char ybuf[60];			/* holds tty id */
385 	register char *p;
386 #endif /* TTYNAME */
387 	extern char *ttyname();
388 	extern void settime();
389 	extern char Version[];
390 
391 	/*
392 	**  Give this envelope a reality.
393 	**	I.e., an id, a transcript, and a creation time.
394 	*/
395 
396 	openxscript(e);
397 	e->e_ctime = curtime();
398 
399 	/*
400 	**  Set OutChannel to something useful if stdout isn't it.
401 	**	This arranges that any extra stuff the mailer produces
402 	**	gets sent back to the user on error (because it is
403 	**	tucked away in the transcript).
404 	*/
405 
406 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
407 	    e->e_xfp != NULL)
408 		OutChannel = e->e_xfp;
409 
410 	/*
411 	**  Set up some basic system macros.
412 	*/
413 
414 	/* process id */
415 	(void) sprintf(pbuf, "%d", getpid());
416 	define('p', newstr(pbuf), e);
417 
418 	/* hop count */
419 	(void) sprintf(cbuf, "%d", e->e_hopcount);
420 	define('c', newstr(cbuf), e);
421 
422 	/* time as integer, unix time, arpa time */
423 	settime(e);
424 
425 #ifdef TTYNAME
426 	/* tty name */
427 	if (macvalue('y', e) == NULL)
428 	{
429 		p = ttyname(2);
430 		if (p != NULL)
431 		{
432 			if (strrchr(p, '/') != NULL)
433 				p = strrchr(p, '/') + 1;
434 			(void) strcpy(ybuf, p);
435 			define('y', ybuf, e);
436 		}
437 	}
438 #endif /* TTYNAME */
439 }
440 /*
441 **  SETTIME -- set the current time.
442 **
443 **	Parameters:
444 **		none.
445 **
446 **	Returns:
447 **		none.
448 **
449 **	Side Effects:
450 **		Sets the various time macros -- $a, $b, $d, $t.
451 */
452 
453 void
454 settime(e)
455 	register ENVELOPE *e;
456 {
457 	register char *p;
458 	auto time_t now;
459 	char tbuf[20];				/* holds "current" time */
460 	char dbuf[30];				/* holds ctime(tbuf) */
461 	register struct tm *tm;
462 	extern char *arpadate();
463 	extern struct tm *gmtime();
464 
465 	now = curtime();
466 	tm = gmtime(&now);
467 	(void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
468 			tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
469 	define('t', newstr(tbuf), e);
470 	(void) strcpy(dbuf, ctime(&now));
471 	p = strchr(dbuf, '\n');
472 	if (p != NULL)
473 		*p = '\0';
474 	define('d', newstr(dbuf), e);
475 	p = arpadate(dbuf);
476 	p = newstr(p);
477 	if (macvalue('a', e) == NULL)
478 		define('a', p, e);
479 	define('b', p, e);
480 }
481 /*
482 **  OPENXSCRIPT -- Open transcript file
483 **
484 **	Creates a transcript file for possible eventual mailing or
485 **	sending back.
486 **
487 **	Parameters:
488 **		e -- the envelope to create the transcript in/for.
489 **
490 **	Returns:
491 **		none
492 **
493 **	Side Effects:
494 **		Creates the transcript file.
495 */
496 
497 #ifndef O_APPEND
498 #define O_APPEND	0
499 #endif
500 
501 void
502 openxscript(e)
503 	register ENVELOPE *e;
504 {
505 	register char *p;
506 	int fd;
507 
508 	if (e->e_xfp != NULL)
509 		return;
510 	p = queuename(e, 'x');
511 	fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
512 	if (fd < 0)
513 	{
514 		syserr("Can't create transcript file %s", p);
515 		fd = open("/dev/null", O_WRONLY, 0644);
516 		if (fd < 0)
517 			syserr("!Can't open /dev/null");
518 	}
519 	e->e_xfp = fdopen(fd, "w");
520 	if (e->e_xfp == NULL)
521 	{
522 		syserr("!Can't create transcript stream %s", p);
523 	}
524 	if (tTd(46, 9))
525 	{
526 		printf("openxscript(%s):\n  ", p);
527 		dumpfd(fileno(e->e_xfp), TRUE, FALSE);
528 	}
529 }
530 /*
531 **  CLOSEXSCRIPT -- close the transcript file.
532 **
533 **	Parameters:
534 **		e -- the envelope containing the transcript to close.
535 **
536 **	Returns:
537 **		none.
538 **
539 **	Side Effects:
540 **		none.
541 */
542 
543 void
544 closexscript(e)
545 	register ENVELOPE *e;
546 {
547 	if (e->e_xfp == NULL)
548 		return;
549 	(void) xfclose(e->e_xfp, "closexscript", e->e_id);
550 	e->e_xfp = NULL;
551 }
552 /*
553 **  SETSENDER -- set the person who this message is from
554 **
555 **	Under certain circumstances allow the user to say who
556 **	s/he is (using -f or -r).  These are:
557 **	1.  The user's uid is zero (root).
558 **	2.  The user's login name is in an approved list (typically
559 **	    from a network server).
560 **	3.  The address the user is trying to claim has a
561 **	    "!" character in it (since #2 doesn't do it for
562 **	    us if we are dialing out for UUCP).
563 **	A better check to replace #3 would be if the
564 **	effective uid is "UUCP" -- this would require me
565 **	to rewrite getpwent to "grab" uucp as it went by,
566 **	make getname more nasty, do another passwd file
567 **	scan, or compile the UID of "UUCP" into the code,
568 **	all of which are reprehensible.
569 **
570 **	Assuming all of these fail, we figure out something
571 **	ourselves.
572 **
573 **	Parameters:
574 **		from -- the person we would like to believe this message
575 **			is from, as specified on the command line.
576 **		e -- the envelope in which we would like the sender set.
577 **		delimptr -- if non-NULL, set to the location of the
578 **			trailing delimiter.
579 **		internal -- set if this address is coming from an internal
580 **			source such as an owner alias.
581 **
582 **	Returns:
583 **		none.
584 **
585 **	Side Effects:
586 **		sets sendmail's notion of who the from person is.
587 */
588 
589 void
590 setsender(from, e, delimptr, internal)
591 	char *from;
592 	register ENVELOPE *e;
593 	char **delimptr;
594 	bool internal;
595 {
596 	register char **pvp;
597 	char *realname = NULL;
598 	register struct passwd *pw;
599 	char delimchar;
600 	char *bp;
601 	char buf[MAXNAME + 2];
602 	char pvpbuf[PSBUFSIZE];
603 	extern struct passwd *getpwnam();
604 	extern char *FullName;
605 
606 	if (tTd(45, 1))
607 		printf("setsender(%s)\n", from == NULL ? "" : from);
608 
609 	/*
610 	**  Figure out the real user executing us.
611 	**	Username can return errno != 0 on non-errors.
612 	*/
613 
614 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
615 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
616 		realname = from;
617 	if (realname == NULL || realname[0] == '\0')
618 		realname = username();
619 
620 	if (ConfigLevel < 2)
621 		SuprErrs = TRUE;
622 
623 	delimchar = internal ? '\0' : ' ';
624 	e->e_from.q_flags = QBADADDR;
625 	if (from == NULL ||
626 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
627 		      delimchar, delimptr, e) == NULL ||
628 	    bitset(QBADADDR, e->e_from.q_flags) ||
629 	    e->e_from.q_mailer == ProgMailer ||
630 	    e->e_from.q_mailer == FileMailer ||
631 	    e->e_from.q_mailer == InclMailer)
632 	{
633 		/* log garbage addresses for traceback */
634 # ifdef LOG
635 		if (from != NULL && LogLevel > 2)
636 		{
637 			char *p;
638 			char ebuf[MAXNAME * 2 + 2];
639 
640 			p = macvalue('_', e);
641 			if (p == NULL)
642 			{
643 				char *host = RealHostName;
644 				if (host == NULL)
645 					host = MyHostName;
646 				(void) sprintf(ebuf, "%s@%s", realname, host);
647 				p = ebuf;
648 			}
649 			syslog(LOG_NOTICE,
650 				"setsender: %s: invalid or unparseable, received from %s",
651 				shortenstring(from, 83), p);
652 		}
653 # endif /* LOG */
654 		if (from != NULL)
655 		{
656 			if (!bitset(QBADADDR, e->e_from.q_flags))
657 			{
658 				/* it was a bogus mailer in the from addr */
659 				usrerr("553 Invalid sender address");
660 			}
661 			SuprErrs = TRUE;
662 		}
663 		if (from == realname ||
664 		    parseaddr(from = newstr(realname), &e->e_from,
665 			      RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
666 		{
667 			char nbuf[100];
668 
669 			SuprErrs = TRUE;
670 			expand("\201n", nbuf, &nbuf[sizeof nbuf], e);
671 			if (parseaddr(from = newstr(nbuf), &e->e_from,
672 				      RF_COPYALL, ' ', NULL, e) == NULL &&
673 			    parseaddr(from = "postmaster", &e->e_from,
674 			    	      RF_COPYALL, ' ', NULL, e) == NULL)
675 				syserr("553 setsender: can't even parse postmaster!");
676 		}
677 	}
678 	else
679 		FromFlag = TRUE;
680 	e->e_from.q_flags |= QDONTSEND;
681 	if (tTd(45, 5))
682 	{
683 		printf("setsender: QDONTSEND ");
684 		printaddr(&e->e_from, FALSE);
685 	}
686 	SuprErrs = FALSE;
687 
688 # ifdef USERDB
689 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
690 	{
691 		register char *p;
692 		extern char *udbsender();
693 
694 		p = udbsender(e->e_from.q_user);
695 		if (p != NULL)
696 			from = p;
697 	}
698 # endif /* USERDB */
699 
700 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
701 	{
702 		if (!internal)
703 		{
704 			/* if the user already given fullname don't redefine */
705 			if (FullName == NULL)
706 				FullName = macvalue('x', e);
707 			if (FullName != NULL && FullName[0] == '\0')
708 				FullName = NULL;
709 		}
710 
711 		if ((pw = getpwnam(e->e_from.q_user)) != NULL)
712 		{
713 			/*
714 			**  Process passwd file entry.
715 			*/
716 
717 			/* extract home directory */
718 			if (strcmp(pw->pw_dir, "/") == 0)
719 				e->e_from.q_home = newstr("");
720 			else
721 				e->e_from.q_home = newstr(pw->pw_dir);
722 			define('z', e->e_from.q_home, e);
723 
724 			/* extract user and group id */
725 			e->e_from.q_uid = pw->pw_uid;
726 			e->e_from.q_gid = pw->pw_gid;
727 			e->e_from.q_flags |= QGOODUID;
728 
729 			/* extract full name from passwd file */
730 			if (FullName == NULL && pw->pw_gecos != NULL &&
731 			    strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
732 			    !internal)
733 			{
734 				buildfname(pw->pw_gecos, e->e_from.q_user, buf);
735 				if (buf[0] != '\0')
736 					FullName = newstr(buf);
737 			}
738 		}
739 		if (FullName != NULL && !internal)
740 			define('x', FullName, e);
741 	}
742 	else if (!internal && OpMode != MD_DAEMON)
743 	{
744 		if (e->e_from.q_home == NULL)
745 		{
746 			e->e_from.q_home = getenv("HOME");
747 			if (e->e_from.q_home != NULL &&
748 			    strcmp(e->e_from.q_home, "/") == 0)
749 				e->e_from.q_home++;
750 		}
751 		e->e_from.q_uid = RealUid;
752 		e->e_from.q_gid = RealGid;
753 		e->e_from.q_flags |= QGOODUID;
754 	}
755 
756 	/*
757 	**  Rewrite the from person to dispose of possible implicit
758 	**	links in the net.
759 	*/
760 
761 	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL);
762 	if (pvp == NULL)
763 	{
764 		/* don't need to give error -- prescan did that already */
765 # ifdef LOG
766 		if (LogLevel > 2)
767 			syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
768 # endif
769 		finis();
770 	}
771 /*
772 	(void) rewrite(pvp, 3, 0, e);
773 	(void) rewrite(pvp, 1, 0, e);
774 	(void) rewrite(pvp, 4, 0, e);
775 */
776 	bp = buf + 1;
777 	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
778 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
779 	{
780 		/* heuristic: route-addr: add angle brackets */
781 		strcat(bp, ">");
782 		*--bp = '<';
783 	}
784 	e->e_sender = newstr(bp);
785 	define('f', e->e_sender, e);
786 
787 	/* save the domain spec if this mailer wants it */
788 	if (e->e_from.q_mailer != NULL &&
789 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
790 	{
791 		extern char **copyplist();
792 
793 		while (*pvp != NULL && strcmp(*pvp, "@") != 0)
794 			pvp++;
795 		if (*pvp != NULL)
796 			e->e_fromdomain = copyplist(pvp, TRUE);
797 	}
798 }
799