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