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