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.48 (Berkeley) 11/28/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 	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
240 	    strcmp(e->e_receiptto, "<>") != 0)
241 	{
242 		auto ADDRESS *rlist = NULL;
243 
244 		e->e_flags |= EF_SENDRECEIPT;
245 		(void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e);
246 		(void) returntosender("Return receipt", rlist, return_yes, e);
247 	}
248 	e->e_flags &= ~EF_SENDRECEIPT;
249 
250 	/*
251 	**  Arrange to send error messages if there are fatal errors.
252 	*/
253 
254 	if (failure_return && e->e_errormode != EM_QUIET)
255 		savemail(e, return_yes || (!return_no && e->e_class >= 0));
256 
257 	/*
258 	**  Arrange to send warning messages to postmaster as requested.
259 	*/
260 
261 	if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL &&
262 	    !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0)
263 	{
264 		auto ADDRESS *rlist = NULL;
265 
266 		(void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
267 		(void) returntosender(e->e_message, rlist, FALSE, e);
268 	}
269 
270 	/*
271 	**  Instantiate or deinstantiate the queue.
272 	*/
273 
274 	if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
275 	    bitset(EF_CLRQUEUE, e->e_flags))
276 	{
277 		if (tTd(50, 1))
278 			printf("\n===== Dropping [dq]f%s (queueit=%d, e_flags=%x) =====\n\n",
279 				e->e_id, queueit, e->e_flags);
280 		if (e->e_df != NULL)
281 			xunlink(e->e_df);
282 		xunlink(queuename(e, 'q'));
283 
284 #ifdef LOG
285 		if (LogLevel > 10)
286 			syslog(LOG_INFO, "%s: done", id);
287 #endif
288 	}
289 	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
290 	{
291 #ifdef QUEUE
292 		queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE);
293 #else /* QUEUE */
294 		syserr("554 dropenvelope: queueup");
295 #endif /* QUEUE */
296 	}
297 
298 	/* now unlock the job */
299 	closexscript(e);
300 	unlockqueue(e);
301 
302 	/* make sure that this envelope is marked unused */
303 	if (e->e_dfp != NULL)
304 		(void) xfclose(e->e_dfp, "dropenvelope", e->e_df);
305 	e->e_dfp = NULL;
306 	e->e_id = e->e_df = NULL;
307 }
308 /*
309 **  CLEARENVELOPE -- clear an envelope without unlocking
310 **
311 **	This is normally used by a child process to get a clean
312 **	envelope without disturbing the parent.
313 **
314 **	Parameters:
315 **		e -- the envelope to clear.
316 **		fullclear - if set, the current envelope is total
317 **			garbage and should be ignored; otherwise,
318 **			release any resources it may indicate.
319 **
320 **	Returns:
321 **		none.
322 **
323 **	Side Effects:
324 **		Closes files associated with the envelope.
325 **		Marks the envelope as unallocated.
326 */
327 
328 void
329 clearenvelope(e, fullclear)
330 	register ENVELOPE *e;
331 	bool fullclear;
332 {
333 	register HDR *bh;
334 	register HDR **nhp;
335 	extern ENVELOPE BlankEnvelope;
336 
337 	if (!fullclear)
338 	{
339 		/* clear out any file information */
340 		if (e->e_xfp != NULL)
341 			(void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
342 		if (e->e_dfp != NULL)
343 			(void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df);
344 		e->e_xfp = e->e_dfp = NULL;
345 	}
346 
347 	/* now clear out the data */
348 	STRUCTCOPY(BlankEnvelope, *e);
349 	if (Verbose)
350 		e->e_sendmode = SM_DELIVER;
351 	bh = BlankEnvelope.e_header;
352 	nhp = &e->e_header;
353 	while (bh != NULL)
354 	{
355 		*nhp = (HDR *) xalloc(sizeof *bh);
356 		bcopy((char *) bh, (char *) *nhp, sizeof *bh);
357 		bh = bh->h_link;
358 		nhp = &(*nhp)->h_link;
359 	}
360 }
361 /*
362 **  INITSYS -- initialize instantiation of system
363 **
364 **	In Daemon mode, this is done in the child.
365 **
366 **	Parameters:
367 **		none.
368 **
369 **	Returns:
370 **		none.
371 **
372 **	Side Effects:
373 **		Initializes the system macros, some global variables,
374 **		etc.  In particular, the current time in various
375 **		forms is set.
376 */
377 
378 void
379 initsys(e)
380 	register ENVELOPE *e;
381 {
382 	char cbuf[5];				/* holds hop count */
383 	char pbuf[10];				/* holds pid */
384 #ifdef TTYNAME
385 	static char ybuf[60];			/* holds tty id */
386 	register char *p;
387 #endif /* TTYNAME */
388 	extern char *ttyname();
389 	extern void settime();
390 	extern char Version[];
391 
392 	/*
393 	**  Give this envelope a reality.
394 	**	I.e., an id, a transcript, and a creation time.
395 	*/
396 
397 	openxscript(e);
398 	e->e_ctime = curtime();
399 
400 	/*
401 	**  Set OutChannel to something useful if stdout isn't it.
402 	**	This arranges that any extra stuff the mailer produces
403 	**	gets sent back to the user on error (because it is
404 	**	tucked away in the transcript).
405 	*/
406 
407 	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
408 	    e->e_xfp != NULL)
409 		OutChannel = e->e_xfp;
410 
411 	/*
412 	**  Set up some basic system macros.
413 	*/
414 
415 	/* process id */
416 	(void) sprintf(pbuf, "%d", getpid());
417 	define('p', newstr(pbuf), e);
418 
419 	/* hop count */
420 	(void) sprintf(cbuf, "%d", e->e_hopcount);
421 	define('c', newstr(cbuf), e);
422 
423 	/* time as integer, unix time, arpa time */
424 	settime(e);
425 
426 #ifdef TTYNAME
427 	/* tty name */
428 	if (macvalue('y', e) == NULL)
429 	{
430 		p = ttyname(2);
431 		if (p != NULL)
432 		{
433 			if (strrchr(p, '/') != NULL)
434 				p = strrchr(p, '/') + 1;
435 			(void) strcpy(ybuf, p);
436 			define('y', ybuf, e);
437 		}
438 	}
439 #endif /* TTYNAME */
440 }
441 /*
442 **  SETTIME -- set the current time.
443 **
444 **	Parameters:
445 **		none.
446 **
447 **	Returns:
448 **		none.
449 **
450 **	Side Effects:
451 **		Sets the various time macros -- $a, $b, $d, $t.
452 */
453 
454 void
455 settime(e)
456 	register ENVELOPE *e;
457 {
458 	register char *p;
459 	auto time_t now;
460 	char tbuf[20];				/* holds "current" time */
461 	char dbuf[30];				/* holds ctime(tbuf) */
462 	register struct tm *tm;
463 	extern char *arpadate();
464 	extern struct tm *gmtime();
465 
466 	now = curtime();
467 	tm = gmtime(&now);
468 	(void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
469 			tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
470 	define('t', newstr(tbuf), e);
471 	(void) strcpy(dbuf, ctime(&now));
472 	p = strchr(dbuf, '\n');
473 	if (p != NULL)
474 		*p = '\0';
475 	define('d', newstr(dbuf), e);
476 	p = arpadate(dbuf);
477 	p = newstr(p);
478 	if (macvalue('a', e) == NULL)
479 		define('a', p, e);
480 	define('b', p, e);
481 }
482 /*
483 **  OPENXSCRIPT -- Open transcript file
484 **
485 **	Creates a transcript file for possible eventual mailing or
486 **	sending back.
487 **
488 **	Parameters:
489 **		e -- the envelope to create the transcript in/for.
490 **
491 **	Returns:
492 **		none
493 **
494 **	Side Effects:
495 **		Creates the transcript file.
496 */
497 
498 #ifndef O_APPEND
499 #define O_APPEND	0
500 #endif
501 
502 void
503 openxscript(e)
504 	register ENVELOPE *e;
505 {
506 	register char *p;
507 	int fd;
508 
509 	if (e->e_xfp != NULL)
510 		return;
511 	p = queuename(e, 'x');
512 	fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
513 	if (fd < 0)
514 	{
515 		syserr("Can't create transcript file %s", p);
516 		fd = open("/dev/null", O_WRONLY, 0644);
517 		if (fd < 0)
518 			syserr("!Can't open /dev/null");
519 	}
520 	e->e_xfp = fdopen(fd, "w");
521 	if (e->e_xfp == NULL)
522 	{
523 		syserr("!Can't create transcript stream %s", p);
524 	}
525 	if (tTd(46, 9))
526 	{
527 		printf("openxscript(%s):\n  ", p);
528 		dumpfd(fileno(e->e_xfp), TRUE, FALSE);
529 	}
530 }
531 /*
532 **  CLOSEXSCRIPT -- close the transcript file.
533 **
534 **	Parameters:
535 **		e -- the envelope containing the transcript to close.
536 **
537 **	Returns:
538 **		none.
539 **
540 **	Side Effects:
541 **		none.
542 */
543 
544 void
545 closexscript(e)
546 	register ENVELOPE *e;
547 {
548 	if (e->e_xfp == NULL)
549 		return;
550 	(void) xfclose(e->e_xfp, "closexscript", e->e_id);
551 	e->e_xfp = NULL;
552 }
553 /*
554 **  SETSENDER -- set the person who this message is from
555 **
556 **	Under certain circumstances allow the user to say who
557 **	s/he is (using -f or -r).  These are:
558 **	1.  The user's uid is zero (root).
559 **	2.  The user's login name is in an approved list (typically
560 **	    from a network server).
561 **	3.  The address the user is trying to claim has a
562 **	    "!" character in it (since #2 doesn't do it for
563 **	    us if we are dialing out for UUCP).
564 **	A better check to replace #3 would be if the
565 **	effective uid is "UUCP" -- this would require me
566 **	to rewrite getpwent to "grab" uucp as it went by,
567 **	make getname more nasty, do another passwd file
568 **	scan, or compile the UID of "UUCP" into the code,
569 **	all of which are reprehensible.
570 **
571 **	Assuming all of these fail, we figure out something
572 **	ourselves.
573 **
574 **	Parameters:
575 **		from -- the person we would like to believe this message
576 **			is from, as specified on the command line.
577 **		e -- the envelope in which we would like the sender set.
578 **		delimptr -- if non-NULL, set to the location of the
579 **			trailing delimiter.
580 **		internal -- set if this address is coming from an internal
581 **			source such as an owner alias.
582 **
583 **	Returns:
584 **		none.
585 **
586 **	Side Effects:
587 **		sets sendmail's notion of who the from person is.
588 */
589 
590 void
591 setsender(from, e, delimptr, internal)
592 	char *from;
593 	register ENVELOPE *e;
594 	char **delimptr;
595 	bool internal;
596 {
597 	register char **pvp;
598 	char *realname = NULL;
599 	register struct passwd *pw;
600 	char delimchar;
601 	char *bp;
602 	char buf[MAXNAME + 2];
603 	char pvpbuf[PSBUFSIZE];
604 	extern struct passwd *getpwnam();
605 	extern char *FullName;
606 
607 	if (tTd(45, 1))
608 		printf("setsender(%s)\n", from == NULL ? "" : from);
609 
610 	/*
611 	**  Figure out the real user executing us.
612 	**	Username can return errno != 0 on non-errors.
613 	*/
614 
615 	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
616 	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
617 		realname = from;
618 	if (realname == NULL || realname[0] == '\0')
619 		realname = username();
620 
621 	if (ConfigLevel < 2)
622 		SuprErrs = TRUE;
623 
624 	delimchar = internal ? '\0' : ' ';
625 	e->e_from.q_flags = QBADADDR;
626 	if (from == NULL ||
627 	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
628 		      delimchar, delimptr, e) == NULL ||
629 	    bitset(QBADADDR, e->e_from.q_flags) ||
630 	    e->e_from.q_mailer == ProgMailer ||
631 	    e->e_from.q_mailer == FileMailer ||
632 	    e->e_from.q_mailer == InclMailer)
633 	{
634 		/* log garbage addresses for traceback */
635 # ifdef LOG
636 		if (from != NULL && LogLevel > 2)
637 		{
638 			char *p;
639 			char ebuf[MAXNAME * 2 + 2];
640 
641 			p = macvalue('_', e);
642 			if (p == NULL)
643 			{
644 				char *host = RealHostName;
645 				if (host == NULL)
646 					host = MyHostName;
647 				(void) sprintf(ebuf, "%s@%s", realname, host);
648 				p = ebuf;
649 			}
650 			syslog(LOG_NOTICE,
651 				"setsender: %s: invalid or unparseable, received from %s",
652 				shortenstring(from, 83), p);
653 		}
654 # endif /* LOG */
655 		if (from != NULL)
656 		{
657 			if (!bitset(QBADADDR, e->e_from.q_flags))
658 			{
659 				/* it was a bogus mailer in the from addr */
660 				usrerr("553 Invalid sender address");
661 			}
662 			SuprErrs = TRUE;
663 		}
664 		if (from == realname ||
665 		    parseaddr(from = newstr(realname), &e->e_from,
666 			      RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
667 		{
668 			char nbuf[100];
669 
670 			SuprErrs = TRUE;
671 			expand("\201n", nbuf, &nbuf[sizeof nbuf], e);
672 			if (parseaddr(from = newstr(nbuf), &e->e_from,
673 				      RF_COPYALL, ' ', NULL, e) == NULL &&
674 			    parseaddr(from = "postmaster", &e->e_from,
675 			    	      RF_COPYALL, ' ', NULL, e) == NULL)
676 				syserr("553 setsender: can't even parse postmaster!");
677 		}
678 	}
679 	else
680 		FromFlag = TRUE;
681 	e->e_from.q_flags |= QDONTSEND;
682 	if (tTd(45, 5))
683 	{
684 		printf("setsender: QDONTSEND ");
685 		printaddr(&e->e_from, FALSE);
686 	}
687 	SuprErrs = FALSE;
688 
689 # ifdef USERDB
690 	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
691 	{
692 		register char *p;
693 		extern char *udbsender();
694 
695 		p = udbsender(e->e_from.q_user);
696 		if (p != NULL)
697 			from = p;
698 	}
699 # endif /* USERDB */
700 
701 	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
702 	{
703 		if (!internal)
704 		{
705 			/* if the user already given fullname don't redefine */
706 			if (FullName == NULL)
707 				FullName = macvalue('x', e);
708 			if (FullName != NULL && FullName[0] == '\0')
709 				FullName = NULL;
710 		}
711 
712 		if ((pw = getpwnam(e->e_from.q_user)) != NULL)
713 		{
714 			/*
715 			**  Process passwd file entry.
716 			*/
717 
718 			/* extract home directory */
719 			if (strcmp(pw->pw_dir, "/") == 0)
720 				e->e_from.q_home = newstr("");
721 			else
722 				e->e_from.q_home = newstr(pw->pw_dir);
723 			define('z', e->e_from.q_home, e);
724 
725 			/* extract user and group id */
726 			e->e_from.q_uid = pw->pw_uid;
727 			e->e_from.q_gid = pw->pw_gid;
728 			e->e_from.q_flags |= QGOODUID;
729 
730 			/* extract full name from passwd file */
731 			if (FullName == NULL && pw->pw_gecos != NULL &&
732 			    strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
733 			    !internal)
734 			{
735 				buildfname(pw->pw_gecos, e->e_from.q_user, buf);
736 				if (buf[0] != '\0')
737 					FullName = newstr(buf);
738 			}
739 		}
740 		if (FullName != NULL && !internal)
741 			define('x', FullName, e);
742 	}
743 	else if (!internal && OpMode != MD_DAEMON)
744 	{
745 		if (e->e_from.q_home == NULL)
746 		{
747 			e->e_from.q_home = getenv("HOME");
748 			if (e->e_from.q_home != NULL &&
749 			    strcmp(e->e_from.q_home, "/") == 0)
750 				e->e_from.q_home++;
751 		}
752 		e->e_from.q_uid = RealUid;
753 		e->e_from.q_gid = RealGid;
754 		e->e_from.q_flags |= QGOODUID;
755 	}
756 
757 	/*
758 	**  Rewrite the from person to dispose of possible implicit
759 	**	links in the net.
760 	*/
761 
762 	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL);
763 	if (pvp == NULL)
764 	{
765 		/* don't need to give error -- prescan did that already */
766 # ifdef LOG
767 		if (LogLevel > 2)
768 			syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
769 # endif
770 		finis();
771 	}
772 /*
773 	(void) rewrite(pvp, 3, 0, e);
774 	(void) rewrite(pvp, 1, 0, e);
775 	(void) rewrite(pvp, 4, 0, e);
776 */
777 	bp = buf + 1;
778 	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
779 	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
780 	{
781 		/* heuristic: route-addr: add angle brackets */
782 		strcat(bp, ">");
783 		*--bp = '<';
784 	}
785 	e->e_sender = newstr(bp);
786 	define('f', e->e_sender, e);
787 
788 	/* save the domain spec if this mailer wants it */
789 	if (e->e_from.q_mailer != NULL &&
790 	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
791 	{
792 		extern char **copyplist();
793 
794 		while (*pvp != NULL && strcmp(*pvp, "@") != 0)
795 			pvp++;
796 		if (*pvp != NULL)
797 			e->e_fromdomain = copyplist(pvp, TRUE);
798 	}
799 }
800