Commit | Line | Data |
---|---|---|
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 | 10 | static 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 | ||
32 | ENVELOPE * | |
fda58daa | 33 | newenvelope(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 | 72 | void |
c6f91078 EA |
73 | dropenvelope(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 | 316 | void |
66ba9834 | 317 | clearenvelope(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 | 366 | void |
a4076aed EA |
367 | initsys(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 | 442 | void |
a4076aed EA |
443 | settime(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 | 490 | void |
c6f91078 EA |
491 | openxscript(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 | 532 | void |
bcf74f25 EA |
533 | closexscript(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 | 578 | void |
4a2da288 | 579 | setsender(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 | } |