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