improve DSN handling somewhat + some bug fixes
[unix-history] / usr / src / usr.sbin / sendmail / src / deliver.c
CommitLineData
d185cb11 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
31de980b
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 */
d185cb11
DF
8
9#ifndef lint
d51d925d 10static char sccsid[] = "@(#)deliver.c 8.114 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
d185cb11 12
97543758 13#include "sendmail.h"
7b6e7aee
KB
14#include <netdb.h>
15#include <errno.h>
efe7f723 16#if NAMED_BIND
f28c9fe2 17#include <resolv.h>
8e5c6745
EA
18
19extern int h_errno;
35af2f06 20#endif
b3cbe40f 21
965c2488
EA
22extern char SmtpError[];
23
b3cbe40f 24/*
6acfa498 25** SENDALL -- actually send all the messages.
b3cbe40f 26**
b3cbe40f 27** Parameters:
6acfa498
EA
28** e -- the envelope to send.
29** mode -- the delivery mode to use. If SM_DEFAULT, use
30** the current e->e_sendmode.
b3cbe40f
EA
31**
32** Returns:
6acfa498 33** none.
b3cbe40f
EA
34**
35** Side Effects:
6acfa498
EA
36** Scans the send lists and sends everything it finds.
37** Delivers any appropriate error messages.
38** If we are running in a non-interactive mode, takes the
39** appropriate action.
b3cbe40f
EA
40*/
41
6acfa498
EA
42sendall(e, mode)
43 ENVELOPE *e;
44 char mode;
b3cbe40f 45{
6acfa498
EA
46 register ADDRESS *q;
47 char *owner;
48 int otherowners;
959cf51d 49 bool announcequeueup;
11024b4c
EA
50 bool oldverbose = Verbose;
51 int pid;
891a4792 52 char *qid;
1d303d98
EA
53 int pid;
54#ifdef LOCKF
55 struct flock lfd;
56#endif
b3cbe40f 57
d4f6a25e
EA
58 /*
59 ** If we have had global, fatal errors, don't bother sending
60 ** the message at all if we are in SMTP mode. Local errors
61 ** (e.g., a single address failing) will still cause the other
62 ** addresses to be sent.
63 */
64
198d9e9c
EA
65 if (bitset(EF_FATALERRS, e->e_flags) &&
66 (OpMode == MD_SMTP || OpMode == MD_DAEMON))
004a2b9c 67 {
004a2b9c
EA
68 e->e_flags |= EF_CLRQUEUE;
69 return;
70 }
71
6acfa498 72 /* determine actual delivery mode */
fc826a82 73 CurrentLA = getla();
6acfa498
EA
74 if (mode == SM_DEFAULT)
75 {
6acfa498
EA
76 mode = e->e_sendmode;
77 if (mode != SM_VERIFY &&
78 shouldqueue(e->e_msgpriority, e->e_ctime))
79 mode = SM_QUEUE;
959cf51d 80 announcequeueup = mode == SM_QUEUE;
f28c9fe2 81 }
959cf51d
EA
82 else
83 announcequeueup = FALSE;
3135d20c 84
6acfa498 85 if (tTd(13, 1))
3135d20c 86 {
b5618bbc
EA
87 printf("\n===== SENDALL: mode %c, id %s, e_from ",
88 mode, e->e_id);
6acfa498
EA
89 printaddr(&e->e_from, FALSE);
90 printf("sendqueue:\n");
91 printaddr(e->e_sendqueue, TRUE);
3135d20c
EA
92 }
93
a530c75f 94 /*
6acfa498
EA
95 ** Do any preprocessing necessary for the mode we are running.
96 ** Check to make sure the hop count is reasonable.
97 ** Delete sends to the sender in mailing lists.
a530c75f
EA
98 */
99
6acfa498 100 CurEnv = e;
a530c75f 101
6acfa498 102 if (e->e_hopcount > MaxHopCount)
779597d8 103 {
6acfa498 104 errno = 0;
ec33213e 105 e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE;
b8b715bc 106 syserr("554 too many hops %d (%d max): from %s via %s, to %s",
6acfa498 107 e->e_hopcount, MaxHopCount, e->e_from.q_paddr,
389c0d5e
EA
108 RealHostName == NULL ? "localhost" : RealHostName,
109 e->e_sendqueue->q_paddr);
6acfa498 110 return;
779597d8 111 }
b3cbe40f 112
2eb74b19
EA
113 /*
114 ** Do sender deletion.
115 **
116 ** If the sender has the QQUEUEUP flag set, skip this.
117 ** This can happen if the name server is hosed when you
118 ** are trying to send mail. The result is that the sender
119 ** is instantiated in the queue as a recipient.
120 */
121
80ec5253
EA
122 if (!bitset(EF_METOO, e->e_flags) &&
123 !bitset(QQUEUEUP, e->e_from.q_flags))
b3cbe40f 124 {
6acfa498 125 if (tTd(13, 5))
779597d8 126 {
6acfa498
EA
127 printf("sendall: QDONTSEND ");
128 printaddr(&e->e_from, FALSE);
779597d8 129 }
6acfa498 130 e->e_from.q_flags |= QDONTSEND;
f8c2f9fd 131 (void) recipient(&e->e_from, &e->e_sendqueue, 0, e);
b3cbe40f 132 }
e6b0a75b 133
1d303d98
EA
134# ifdef QUEUE
135 if ((mode == SM_QUEUE || mode == SM_FORK ||
136 (mode != SM_VERIFY && SuperSafe)) &&
137 !bitset(EF_INQUEUE, e->e_flags))
138 {
139 /* be sure everything is instantiated in the queue */
140 queueup(e, TRUE, mode == SM_QUEUE);
141 }
142#endif /* QUEUE */
143
144 switch (mode)
145 {
146 case SM_VERIFY:
147 Verbose = TRUE;
148 break;
149
150 case SM_QUEUE:
151 queueonly:
152 e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
153 return;
154
155 case SM_FORK:
156 if (e->e_xfp != NULL)
157 (void) fflush(e->e_xfp);
158
159# ifdef LOCKF
160 /*
161 ** Since lockf has the interesting semantic that the
162 ** lock is lost when we fork, we have to risk losing
163 ** the lock here by closing before the fork, and then
164 ** trying to get it back in the child.
165 */
166
167 if (e->e_lockfp != NULL)
168 {
169 (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp");
170 e->e_lockfp = NULL;
171 }
172# endif /* LOCKF */
173
174 pid = fork();
175 if (pid < 0)
176 {
177 goto queueonly;
178 }
179 else if (pid > 0)
180 {
181 /* be sure we leave the temp files to our child */
182 e->e_id = e->e_df = NULL;
183# ifndef LOCKF
184 if (e->e_lockfp != NULL)
185 {
186 (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp");
187 e->e_lockfp = NULL;
188 }
189# endif
190
191 /* close any random open files in the envelope */
192 if (e->e_dfp != NULL)
193 {
194 (void) xfclose(e->e_dfp, "sendenvelope", "dfp");
195 e->e_dfp = NULL;
196 }
197 if (e->e_xfp != NULL)
198 {
199 (void) xfclose(e->e_xfp, "sendenvelope", "xfp");
200 e->e_xfp = NULL;
201 }
202 return;
203 }
204
205 /* double fork to avoid zombies */
206 if (fork() > 0)
207 exit(EX_OK);
208
209 /* be sure we are immune from the terminal */
210 disconnect(FALSE, e);
211
212# ifdef LOCKF
213 /*
214 ** Now try to get our lock back.
215 */
216
217 lfd.l_type = F_WRLCK;
218 lfd.l_whence = lfd.l_start = lfd.l_len = 0;
219 e->e_lockfp = fopen(queuename(e, 'q'), "r+");
220 if (e->e_lockfp == NULL ||
221 fcntl(fileno(e->e_lockfp), F_SETLK, &lfd) < 0)
222 {
223 /* oops.... lost it */
224 if (tTd(13, 1))
225 printf("sendenvelope: %s lost lock: lockfp=%x, %s\n",
226 e->e_id, e->e_lockfp, errstring(errno));
227
228# ifdef LOG
229 if (LogLevel > 29)
230 syslog(LOG_NOTICE, "%s: lost lock: %m",
231 e->e_id);
232# endif /* LOG */
233 exit(EX_OK);
234 }
235# endif /* LOCKF */
236
237 /*
238 ** Close any cached connections.
239 **
240 ** We don't send the QUIT protocol because the parent
241 ** still knows about the connection.
242 **
243 ** This should only happen when delivering an error
244 ** message.
245 */
246
247 mci_flush(FALSE, NULL);
248
249 break;
250 }
251
252 /*
253 ** If we haven't fully expanded aliases, do it now
254 */
255
256 if (bitset(EF_VRFYONLY, e->e_flags))
257 {
258 e->e_flags &= ~EF_VRFYONLY;
259 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
260 {
261 extern ADDRESS *recipient();
262
263 if (bitset(QVERIFIED, q->q_flags))
264 recipient(q, &e->e_sendqueue, e);
265 }
266 }
267
1ab402f2 268 /*
6acfa498
EA
269 ** Handle alias owners.
270 **
271 ** We scan up the q_alias chain looking for owners.
272 ** We discard owners that are the same as the return path.
b3cbe40f
EA
273 */
274
6acfa498 275 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
b3cbe40f 276 {
6acfa498 277 register struct address *a;
779597d8 278
6acfa498 279 for (a = q; a != NULL && a->q_owner == NULL; a = a->q_alias)
779597d8 280 continue;
6acfa498
EA
281 if (a != NULL)
282 q->q_owner = a->q_owner;
283
284 if (q->q_owner != NULL &&
285 !bitset(QDONTSEND, q->q_flags) &&
286 strcmp(q->q_owner, e->e_from.q_paddr) == 0)
287 q->q_owner = NULL;
288 }
289
290 owner = "";
291 otherowners = 1;
292 while (owner != NULL && otherowners > 0)
293 {
294 owner = NULL;
295 otherowners = 0;
1bf7c76b 296
6acfa498 297 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
78bbbc48 298 {
6acfa498
EA
299 if (bitset(QDONTSEND, q->q_flags))
300 continue;
779597d8 301
6acfa498
EA
302 if (q->q_owner != NULL)
303 {
304 if (owner == NULL)
305 owner = q->q_owner;
306 else if (owner != q->q_owner)
307 {
308 if (strcmp(owner, q->q_owner) == 0)
309 {
310 /* make future comparisons cheap */
311 q->q_owner = owner;
312 }
313 else
314 {
315 otherowners++;
316 }
317 owner = q->q_owner;
318 }
319 }
320 else
321 {
322 otherowners++;
323 }
779597d8
EA
324 }
325
6acfa498 326 if (owner != NULL && otherowners > 0)
b3cbe40f 327 {
04f6f6a9 328 register ENVELOPE *ee;
6acfa498
EA
329 extern HDR *copyheader();
330 extern ADDRESS *copyqueue();
779597d8 331
6acfa498
EA
332 /*
333 ** Split this envelope into two.
334 */
74c5fe7c 335
6acfa498
EA
336 ee = (ENVELOPE *) xalloc(sizeof(ENVELOPE));
337 *ee = *e;
338 ee->e_id = NULL;
339 (void) queuename(ee, '\0');
0df76d69 340
6acfa498
EA
341 if (tTd(13, 1))
342 printf("sendall: split %s into %s\n",
343 e->e_id, ee->e_id);
779597d8 344
6acfa498
EA
345 ee->e_header = copyheader(e->e_header);
346 ee->e_sendqueue = copyqueue(e->e_sendqueue);
347 ee->e_errorqueue = copyqueue(e->e_errorqueue);
5b4215a7
EA
348 ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS|EF_SENDRECEIPT);
349 ee->e_flags |= EF_NORECEIPT;
6acfa498
EA
350 setsender(owner, ee, NULL, TRUE);
351 if (tTd(13, 5))
352 {
353 printf("sendall(split): QDONTSEND ");
354 printaddr(&ee->e_from, FALSE);
355 }
356 ee->e_from.q_flags |= QDONTSEND;
357 ee->e_dfp = NULL;
358 ee->e_xfp = NULL;
6acfa498
EA
359 ee->e_df = NULL;
360 ee->e_errormode = EM_MAIL;
6acfa498
EA
361
362 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
363 if (q->q_owner == owner)
0cf862de 364 {
6acfa498 365 q->q_flags |= QDONTSEND;
0cf862de
EA
366 q->q_flags &= ~QQUEUEUP;
367 }
6acfa498
EA
368 for (q = ee->e_sendqueue; q != NULL; q = q->q_next)
369 if (q->q_owner != owner)
0cf862de 370 {
6acfa498 371 q->q_flags |= QDONTSEND;
0cf862de
EA
372 q->q_flags &= ~QQUEUEUP;
373 }
e6b0a75b 374
6acfa498 375 if (e->e_df != NULL && mode != SM_VERIFY)
e6b0a75b 376 {
6acfa498 377 ee->e_dfp = NULL;
f4318163
EA
378 ee->e_df = queuename(ee, 'd');
379 ee->e_df = newstr(ee->e_df);
6acfa498
EA
380 if (link(e->e_df, ee->e_df) < 0)
381 {
382 syserr("sendall: link(%s, %s)",
383 e->e_df, ee->e_df);
384 }
e6b0a75b 385 }
6acfa498
EA
386#ifdef LOG
387 if (LogLevel > 4)
9cc11aa8
EA
388 syslog(LOG_INFO, "%s: clone %s, owner=%s",
389 ee->e_id, e->e_id, owner);
6acfa498 390#endif
04f6f6a9
EA
391 CurEnv = ee;
392 sendenvelope(ee, mode, announcequeueup);
393 dropenvelope(ee);
779597d8 394 }
b3cbe40f
EA
395 }
396
04f6f6a9
EA
397 /*
398 ** Split off envelopes have been sent -- now send original
399 */
400
6acfa498 401 if (owner != NULL)
e6b0a75b 402 {
6acfa498
EA
403 setsender(owner, e, NULL, TRUE);
404 if (tTd(13, 5))
405 {
406 printf("sendall(owner): QDONTSEND ");
407 printaddr(&e->e_from, FALSE);
408 }
409 e->e_from.q_flags |= QDONTSEND;
410 e->e_errormode = EM_MAIL;
5b4215a7 411 e->e_flags |= EF_NORECEIPT;
e6b0a75b 412 }
1ef61b9f 413
11024b4c
EA
414 bool oldverbose = Verbose;
415
416 if (splitenv != NULL)
417 {
418 if (tTd(13, 1))
419 {
420 printf("\nsendall: Split queue; remaining queue:\n");
421 printaddr(e->e_sendqueue, TRUE);
422 }
423
424 for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
425 {
426 CurEnv = ee;
427 if (mode != SM_VERIFY)
428 openxscript(ee);
429 sendenvelope(ee, mode);
430 dropenvelope(ee);
431 }
432
433 CurEnv = e;
434 }
435 sendenvelope(e, mode);
436 Verbose = oldverbose;
6acfa498
EA
437}
438
11024b4c 439sendenvelope(e, mode)
6acfa498
EA
440 register ENVELOPE *e;
441 char mode;
442{
6acfa498 443 register ADDRESS *q;
11024b4c 444 char *qf;
11024b4c
EA
445 bool didany;
446
447 /*
448 ** If we have had global, fatal errors, don't bother sending
449 ** the message at all if we are in SMTP mode. Local errors
450 ** (e.g., a single address failing) will still cause the other
451 ** addresses to be sent.
452 */
453
454 if (bitset(EF_FATALERRS, e->e_flags) &&
455 (OpMode == MD_SMTP || OpMode == MD_DAEMON))
456 {
457 e->e_flags |= EF_CLRQUEUE;
458 return;
459 }
f2e44ded 460
ed45aae1 461 /*
6acfa498 462 ** Run through the list and send everything.
0fc3fb21
EA
463 **
464 ** Set EF_GLOBALERRS so that error messages during delivery
465 ** result in returned mail.
ed45aae1
EA
466 */
467
6acfa498 468 e->e_nsent = 0;
0fc3fb21 469 e->e_flags |= EF_GLOBALERRS;
f009d24b 470 didany = FALSE;
69c74bb8 471
69c74bb8 472 /* now run through the queue */
6acfa498 473 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
f2e44ded 474 {
f9fbda25
EA
475#ifdef XDEBUG
476 char wbuf[MAXNAME + 20];
477
478 (void) sprintf(wbuf, "sendall(%s)", q->q_paddr);
479 checkfd012(wbuf);
480#endif
6acfa498 481 if (mode == SM_VERIFY)
1627a785 482 {
6acfa498
EA
483 e->e_to = q->q_paddr;
484 if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
d1c234d8 485 {
58057ca3
EA
486 if (q->q_host != NULL && q->q_host[0] != '\0')
487 message("deliverable: mailer %s, host %s, user %s",
488 q->q_mailer->m_name,
489 q->q_host,
490 q->q_user);
491 else
492 message("deliverable: mailer %s, user %s",
493 q->q_mailer->m_name,
494 q->q_user);
d1c234d8 495 }
6acfa498
EA
496 }
497 else if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
498 {
499# ifdef QUEUE
500 /*
501 ** Checkpoint the send list every few addresses
502 */
503
504 if (e->e_nsent >= CheckpointInterval)
505 {
506 queueup(e, TRUE, FALSE);
507 e->e_nsent = 0;
508 }
509# endif /* QUEUE */
510 (void) deliver(e, q);
f009d24b 511 didany = TRUE;
1627a785 512 }
f2e44ded 513 }
f009d24b
EA
514 if (didany)
515 {
516 e->e_dtime = curtime();
517 e->e_ntries++;
518 }
f2e44ded 519
f9fbda25
EA
520#ifdef XDEBUG
521 checkfd012("end of sendenvelope");
522#endif
523
6acfa498
EA
524 if (mode == SM_FORK)
525 finis();
779597d8
EA
526}
527\f/*
6acfa498
EA
528** DOFORK -- do a fork, retrying a couple of times on failure.
529**
530** This MUST be a macro, since after a vfork we are running
531** two processes on the same stack!!!
b9e44c3d
EA
532**
533** Parameters:
6acfa498 534** none.
b9e44c3d
EA
535**
536** Returns:
6acfa498 537** From a macro??? You've got to be kidding!
b9e44c3d
EA
538**
539** Side Effects:
6acfa498
EA
540** Modifies the ==> LOCAL <== variable 'pid', leaving:
541** pid of child in parent, zero in child.
542** -1 on unrecoverable error.
543**
544** Notes:
545** I'm awfully sorry this looks so awful. That's
546** vfork for you.....
b9e44c3d
EA
547*/
548
6acfa498 549# define NFORKTRIES 5
140717b5
EA
550
551# ifndef FORK
552# define FORK fork
553# endif
67e64653
EA
554
555# define DOFORK(fORKfN) \
556{\
557 register int i;\
558\
11e32817 559 for (i = NFORKTRIES; --i >= 0; )\
67e64653
EA
560 {\
561 pid = fORKfN();\
562 if (pid >= 0)\
563 break;\
11e32817 564 if (i > 0)\
901911f8 565 sleep((unsigned) NFORKTRIES - i);\
67e64653
EA
566 }\
567}
568\f/*
2cf55cb7
EA
569** DOFORK -- simple fork interface to DOFORK.
570**
571** Parameters:
572** none.
573**
574** Returns:
575** pid of child in parent.
576** zero in child.
577** -1 on error.
578**
579** Side Effects:
580** returns twice, once in parent and once in child.
581*/
582
583dofork()
584{
585 register int pid;
586
587 DOFORK(fork);
588 return (pid);
589}
590\f/*
6acfa498 591** DELIVER -- Deliver a message to a list of addresses.
e6b0a75b 592**
6acfa498
EA
593** This routine delivers to everyone on the same host as the
594** user on the head of the list. It is clever about mailers
595** that don't handle multiple users. It is NOT guaranteed
596** that it will deliver to all these addresses however -- so
597** deliver should be called once for each address on the
598** list.
e6b0a75b
EA
599**
600** Parameters:
6acfa498
EA
601** e -- the envelope to deliver.
602** firstto -- head of the address list to deliver to.
e6b0a75b
EA
603**
604** Returns:
6acfa498
EA
605** zero -- successfully delivered.
606** else -- some failure, see ExitStat for more info.
e6b0a75b
EA
607**
608** Side Effects:
6acfa498 609** The standard input is passed off to someone.
e6b0a75b
EA
610*/
611
6acfa498 612deliver(e, firstto)
30eab7ca 613 register ENVELOPE *e;
6acfa498 614 ADDRESS *firstto;
e6b0a75b 615{
6acfa498
EA
616 char *host; /* host being sent to */
617 char *user; /* user being sent to */
618 char **pvp;
619 register char **mvp;
620 register char *p;
621 register MAILER *m; /* mailer for this recipient */
622 ADDRESS *ctladdr;
623 register MCI *mci;
624 register ADDRESS *to = firstto;
625 bool clever = FALSE; /* running user smtp to this mailer */
626 ADDRESS *tochain = NULL; /* chain of users in this mailer call */
627 int rcode; /* response code */
628 char *firstsig; /* signature of firstto */
629 int pid;
630 char *curhost;
631 int mpvect[2];
632 int rpvect[2];
633 char *pv[MAXPV+1];
634 char tobuf[TOBUFSIZE]; /* text line of to people */
635 char buf[MAXNAME];
636 char rpathbuf[MAXNAME]; /* translated return path */
637 extern int checkcompat();
e6b0a75b 638
6acfa498
EA
639 errno = 0;
640 if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
641 return (0);
2ae0e0ed 642
efe7f723 643#if NAMED_BIND
6acfa498 644 /* unless interactive, try twice, over a minute */
198d9e9c
EA
645 if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
646 {
6acfa498
EA
647 _res.retrans = 30;
648 _res.retry = 2;
649 }
650#endif
1ab402f2 651
6acfa498
EA
652 m = to->q_mailer;
653 host = to->q_host;
654 CurEnv = e; /* just in case */
0992263e 655 e->e_statmsg = NULL;
fe3849ea 656 SmtpError[0] = '\0';
6acfa498
EA
657
658 if (tTd(10, 1))
116d2937
EA
659 printf("\n--deliver, id=%s, mailer=%s, host=`%s', first user=`%s'\n",
660 e->e_id, m->m_name, host, to->q_user);
35f14050
EA
661 if (tTd(10, 100))
662 printopenfds(FALSE);
6acfa498
EA
663
664 /*
665 ** If this mailer is expensive, and if we don't want to make
666 ** connections now, just mark these addresses and return.
667 ** This is useful if we want to batch connections to
668 ** reduce load. This will cause the messages to be
669 ** queued up, and a daemon will come along to send the
670 ** messages later.
671 ** This should be on a per-mailer basis.
672 */
673
6b951123 674 if (NoConnect && bitnset(M_EXPENSIVE, m->m_flags) && !Verbose)
e6b0a75b 675 {
6acfa498
EA
676 for (; to != NULL; to = to->q_next)
677 {
678 if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) ||
679 to->q_mailer != m)
680 continue;
c069e0df 681 to->q_flags |= QQUEUEUP;
6acfa498
EA
682 e->e_to = to->q_paddr;
683 message("queued");
684 if (LogLevel > 8)
5c18c358 685 logdelivery(m, NULL, "queued", NULL, e);
6acfa498
EA
686 }
687 e->e_to = NULL;
688 return (0);
689 }
690
691 /*
692 ** Do initial argv setup.
693 ** Insert the mailer name. Notice that $x expansion is
694 ** NOT done on the mailer name. Then, if the mailer has
695 ** a picky -f flag, we insert it as appropriate. This
696 ** code does not check for 'pv' overflow; this places a
697 ** manifest lower limit of 4 for MAXPV.
698 ** The from address rewrite is expected to make
699 ** the address relative to the other end.
700 */
701
702 /* rewrite from address, using rewriting rules */
9e43a19e 703 rcode = EX_OK;
295b05c5
EA
704 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
705 p = e->e_sender;
706 else
707 p = e->e_from.q_paddr;
708 (void) strcpy(rpathbuf, remotename(p, m,
9e43a19e
EA
709 RF_SENDERADDR|RF_CANONICAL,
710 &rcode, e));
6acfa498
EA
711 define('g', rpathbuf, e); /* translated return path */
712 define('h', host, e); /* to host */
713 Errors = 0;
714 pvp = pv;
715 *pvp++ = m->m_argv[0];
716
717 /* insert -f or -r flag as appropriate */
718 if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags)))
719 {
720 if (bitnset(M_FOPT, m->m_flags))
721 *pvp++ = "-f";
722 else
723 *pvp++ = "-r";
724 *pvp++ = newstr(rpathbuf);
725 }
726
727 /*
728 ** Append the other fixed parts of the argv. These run
729 ** up to the first entry containing "$u". There can only
730 ** be one of these, and there are only a few more slots
731 ** in the pv after it.
732 */
733
734 for (mvp = m->m_argv; (p = *++mvp) != NULL; )
735 {
736 /* can't use strchr here because of sign extension problems */
737 while (*p != '\0')
738 {
739 if ((*p++ & 0377) == MACROEXPAND)
740 {
741 if (*p == 'u')
742 break;
743 }
744 }
745
746 if (*p != '\0')
747 break;
748
749 /* this entry is safe -- go ahead and process it */
750 expand(*mvp, buf, &buf[sizeof buf - 1], e);
751 *pvp++ = newstr(buf);
752 if (pvp >= &pv[MAXPV - 3])
753 {
754 syserr("554 Too many parameters to %s before $u", pv[0]);
755 return (-1);
756 }
757 }
758
759 /*
760 ** If we have no substitution for the user name in the argument
761 ** list, we know that we must supply the names otherwise -- and
762 ** SMTP is the answer!!
763 */
764
765 if (*mvp == NULL)
766 {
767 /* running SMTP */
768# ifdef SMTP
769 clever = TRUE;
770 *pvp = NULL;
771# else /* SMTP */
772 /* oops! we don't implement SMTP */
fe3849ea 773 syserr("554 SMTP style mailer not implemented");
7338e3d4 774 return (EX_SOFTWARE);
6acfa498 775# endif /* SMTP */
e6b0a75b 776 }
1ab402f2 777
6acfa498
EA
778 /*
779 ** At this point *mvp points to the argument with $u. We
780 ** run through our address list and append all the addresses
781 ** we can. If we run out of space, do not fret! We can
782 ** always send another copy later.
783 */
784
785 tobuf[0] = '\0';
786 e->e_to = tobuf;
787 ctladdr = NULL;
788 firstsig = hostsignature(firstto->q_mailer, firstto->q_host, e);
789 for (; to != NULL; to = to->q_next)
e6b0a75b 790 {
6acfa498
EA
791 /* avoid sending multiple recipients to dumb mailers */
792 if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags))
793 break;
30eab7ca 794
6acfa498
EA
795 /* if already sent or not for this host, don't send */
796 if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) ||
797 to->q_mailer != firstto->q_mailer ||
798 strcmp(hostsignature(to->q_mailer, to->q_host, e), firstsig) != 0)
799 continue;
800
801 /* avoid overflowing tobuf */
802 if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2))
803 break;
804
805 if (tTd(10, 1))
30eab7ca 806 {
6acfa498
EA
807 printf("\nsend to ");
808 printaddr(to, FALSE);
809 }
30eab7ca 810
6acfa498 811 /* compute effective uid/gid when sending */
2bade550 812 if (bitnset(M_RUNASRCPT, to->q_mailer->m_flags))
c8de5c6d 813 ctladdr = getctladdr(to);
6acfa498
EA
814
815 user = to->q_user;
816 e->e_to = to->q_paddr;
817 if (tTd(10, 5))
818 {
819 printf("deliver: QDONTSEND ");
820 printaddr(to, FALSE);
30eab7ca 821 }
6acfa498 822 to->q_flags |= QDONTSEND;
30eab7ca 823
6acfa498
EA
824 /*
825 ** Check to see that these people are allowed to
826 ** talk to each other.
827 */
828
829 if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
830 {
2bade550 831 e->e_flags |= EF_NORETURN;
6acfa498 832 usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
5c18c358 833 giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, e);
6acfa498
EA
834 continue;
835 }
fdcfa6b8
EA
836#if NAMED_BIND
837 h_errno = 0;
838#endif
6acfa498
EA
839 rcode = checkcompat(to, e);
840 if (rcode != EX_OK)
841 {
fd57f063 842 markfailure(e, to, rcode);
5c18c358 843 giveresponse(rcode, m, NULL, ctladdr, e);
6acfa498
EA
844 continue;
845 }
846
847 /*
848 ** Strip quote bits from names if the mailer is dumb
849 ** about them.
850 */
851
852 if (bitnset(M_STRIPQ, m->m_flags))
853 {
854 stripquotes(user);
855 stripquotes(host);
856 }
857
858 /* hack attack -- delivermail compatibility */
859 if (m == ProgMailer && *user == '|')
860 user++;
861
862 /*
863 ** If an error message has already been given, don't
864 ** bother to send to this address.
865 **
866 ** >>>>>>>>>> This clause assumes that the local mailer
867 ** >> NOTE >> cannot do any further aliasing; that
868 ** >>>>>>>>>> function is subsumed by sendmail.
869 */
870
871 if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
872 continue;
873
874 /* save statistics.... */
875 markstats(e, to);
876
877 /*
878 ** See if this user name is "special".
879 ** If the user name has a slash in it, assume that this
880 ** is a file -- send it off without further ado. Note
881 ** that this type of addresses is not processed along
882 ** with the others, so we fudge on the To person.
883 */
884
885 if (m == FileMailer)
886 {
1bf9f503
EA
887 rcode = mailfile(user, ctladdr, e);
888 giveresponse(rcode, m, NULL, ctladdr, e);
f8c2f9fd 889 e->e_nsent++;
6acfa498 890 if (rcode == EX_OK)
f8c2f9fd 891 {
6acfa498 892 to->q_flags |= QSENT;
f8c2f9fd
EA
893 if (bitnset(M_LOCALMAILER, m->m_flags) &&
894 (e->e_receiptto != NULL ||
895 bitset(QPINGONSUCCESS, to->q_flags)))
896 {
897 to->q_flags |= QREPORT;
898 fprintf(e->e_xfp, "%s... Successfully delivered\n",
899 to->q_paddr);
900 }
901 }
68d9129a 902 to->q_statdate = curtime();
6acfa498
EA
903 continue;
904 }
905
906 /*
907 ** Address is verified -- add this user to mailer
908 ** argv, and add it to the print list of recipients.
909 */
910
911 /* link together the chain of recipients */
912 to->q_tchain = tochain;
913 tochain = to;
914
915 /* create list of users for error messages */
916 (void) strcat(tobuf, ",");
917 (void) strcat(tobuf, to->q_paddr);
918 define('u', user, e); /* to user */
ce4c39a9
EA
919 p = to->q_home;
920 if (p == NULL && ctladdr != NULL)
921 p = ctladdr->q_home;
922 define('z', p, e); /* user's home */
6acfa498
EA
923
924 /*
925 ** Expand out this user into argument list.
926 */
927
928 if (!clever)
929 {
930 expand(*mvp, buf, &buf[sizeof buf - 1], e);
931 *pvp++ = newstr(buf);
932 if (pvp >= &pv[MAXPV - 2])
933 {
934 /* allow some space for trailing parms */
935 break;
936 }
937 }
e6b0a75b 938 }
1ab402f2 939
6acfa498
EA
940 /* see if any addresses still exist */
941 if (tobuf[0] == '\0')
942 {
943 define('g', (char *) NULL, e);
944 return (0);
945 }
946
947 /* print out messages as full list */
948 e->e_to = tobuf + 1;
949
950 /*
951 ** Fill out any parameters after the $u parameter.
952 */
953
954 while (!clever && *++mvp != NULL)
955 {
956 expand(*mvp, buf, &buf[sizeof buf - 1], e);
957 *pvp++ = newstr(buf);
958 if (pvp >= &pv[MAXPV])
959 syserr("554 deliver: pv overflow after $u for %s", pv[0]);
960 }
961 *pvp++ = NULL;
962
963 /*
964 ** Call the mailer.
965 ** The argument vector gets built, pipes
966 ** are created as necessary, and we fork & exec as
967 ** appropriate.
968 ** If we are running SMTP, we just need to clean up.
969 */
e6b0a75b 970
c8de5c6d 971 /*XXX this seems a bit wierd */
a773ed15
EA
972 if (ctladdr == NULL && m != ProgMailer &&
973 bitset(QGOODUID, e->e_from.q_flags))
c8de5c6d
EA
974 ctladdr = &e->e_from;
975
efe7f723 976#if NAMED_BIND
6acfa498
EA
977 if (ConfigLevel < 2)
978 _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */
979#endif
779597d8 980
9678c96d 981 if (tTd(11, 1))
b3cbe40f 982 {
857afefe 983 printf("openmailer:");
6acfa498 984 printav(pv);
b3cbe40f 985 }
d829793b 986 errno = 0;
fdcfa6b8
EA
987#if NAMED_BIND
988 h_errno = 0;
989#endif
779597d8 990
57c97d4a
EA
991 CurHostName = m->m_mailer;
992
1ab402f2
EA
993 /*
994 ** Deal with the special case of mail handled through an IPC
995 ** connection.
996 ** In this case we don't actually fork. We must be
997 ** running SMTP for this to work. We will return a
998 ** zero pid to indicate that we are running IPC.
5463e94d 999 ** We also handle a debug version that just talks to stdin/out.
1ab402f2
EA
1000 */
1001
6acfa498 1002 curhost = NULL;
649a3283 1003 SmtpPhase = NULL;
fe3849ea 1004 mci = NULL;
6acfa498 1005
061a3d08
EA
1006#ifdef XDEBUG
1007 {
1008 char wbuf[MAXLINE];
1009
1010 /* make absolutely certain 0, 1, and 2 are in use */
1011 sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name);
1012 checkfd012(wbuf);
1013 }
1014#endif
1015
e3c84ea8
EA
1016 /* check for 8-bit available */
1017 if (bitset(EF_HAS8BIT, e->e_flags) &&
1018 bitnset(M_7BITS, m->m_flags) &&
1019 !bitset(MM_MIME8BIT, MimeMode))
1020 {
1021 usrerr("554 Cannot send 8-bit data to 7-bit destination");
1022 rcode = EX_DATAERR;
1023 goto give_up;
1024 }
1025
5463e94d
EA
1026 /* check for Local Person Communication -- not for mortals!!! */
1027 if (strcmp(m->m_mailer, "[LPC]") == 0)
1028 {
f2e44ded 1029 mci = (MCI *) xalloc(sizeof *mci);
3eb4fac4 1030 bzero((char *) mci, sizeof *mci);
2ae0e0ed
EA
1031 mci->mci_in = stdin;
1032 mci->mci_out = stdout;
f2e44ded 1033 mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
e62e1144 1034 mci->mci_mailer = m;
5463e94d 1035 }
f2e44ded
EA
1036 else if (strcmp(m->m_mailer, "[IPC]") == 0 ||
1037 strcmp(m->m_mailer, "[TCP]") == 0)
1ab402f2 1038 {
140717b5 1039#ifdef DAEMON
7e70d3c8 1040 register int i;
f7eb07a3 1041 register u_short port;
1ab402f2 1042
7bdee402
EA
1043 if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0')
1044 {
1045 syserr("null host name for %s mailer", m->m_mailer);
1046 rcode = EX_CONFIG;
1047 goto give_up;
1048 }
1049
6acfa498
EA
1050 CurHostName = pv[1];
1051 curhost = hostsignature(m, pv[1], e);
f2e44ded 1052
f2b8376e
EA
1053 if (curhost == NULL || curhost[0] == '\0')
1054 {
7bdee402 1055 syserr("null host signature for %s", pv[1]);
37750f57 1056 rcode = EX_CONFIG;
6acfa498 1057 goto give_up;
f2b8376e
EA
1058 }
1059
1ab402f2 1060 if (!clever)
f2b8376e 1061 {
b6edea3d 1062 syserr("554 non-clever IPC");
fe3849ea 1063 rcode = EX_CONFIG;
6acfa498 1064 goto give_up;
f2b8376e 1065 }
6acfa498
EA
1066 if (pv[2] != NULL)
1067 port = atoi(pv[2]);
e2d7c32a 1068 else
f7eb07a3 1069 port = 0;
6acfa498 1070tryhost:
7e70d3c8 1071 while (*curhost != '\0')
e2abd3be 1072 {
7e70d3c8 1073 register char *p;
2388926b 1074 static char hostbuf[MAXNAME];
7e70d3c8
EA
1075
1076 /* pull the next host from the signature */
1077 p = strchr(curhost, ':');
1078 if (p == NULL)
1079 p = &curhost[strlen(curhost)];
fe3849ea
EA
1080 if (p == curhost)
1081 {
1082 syserr("deliver: null host name in signature");
7c40218a 1083 curhost++;
fe3849ea
EA
1084 continue;
1085 }
7e70d3c8
EA
1086 strncpy(hostbuf, curhost, p - curhost);
1087 hostbuf[p - curhost] = '\0';
1088 if (*p != '\0')
1089 p++;
1090 curhost = p;
1091
8657d05f 1092 /* see if we already know that this host is fried */
7e70d3c8
EA
1093 CurHostName = hostbuf;
1094 mci = mci_get(hostbuf, m);
f2e44ded 1095 if (mci->mci_state != MCIS_CLOSED)
237bda52
EA
1096 {
1097 if (tTd(11, 1))
1098 {
1099 printf("openmailer: ");
deff97fd 1100 mci_dump(mci, FALSE);
237bda52 1101 }
322eceee 1102 CurHostName = mci->mci_host;
5f14cfca
EA
1103 message("Using cached connection to %s via %s...",
1104 hostbuf, m->m_name);
6acfa498 1105 break;
237bda52 1106 }
e62e1144 1107 mci->mci_mailer = m;
f2e44ded
EA
1108 if (mci->mci_exitstat != EX_OK)
1109 continue;
1110
1111 /* try the connection */
7e70d3c8 1112 setproctitle("%s %s: %s", e->e_id, hostbuf, "user open");
5f14cfca 1113 message("Connecting to %s via %s...",
7e70d3c8
EA
1114 hostbuf, m->m_name);
1115 i = makeconnection(hostbuf, port, mci,
f2e44ded
EA
1116 bitnset(M_SECURE_PORT, m->m_flags));
1117 mci->mci_exitstat = i;
1118 mci->mci_errno = errno;
efe7f723 1119#if NAMED_BIND
8e5c6745
EA
1120 mci->mci_herrno = h_errno;
1121#endif
f2e44ded 1122 if (i == EX_OK)
e2abd3be 1123 {
f2e44ded
EA
1124 mci->mci_state = MCIS_OPENING;
1125 mci_cache(mci);
8e5c6745
EA
1126 if (TrafficLogFile != NULL)
1127 fprintf(TrafficLogFile, "%05d == CONNECT %s\n",
1128 getpid(), hostbuf);
f2e44ded 1129 break;
e2abd3be 1130 }
f2e44ded
EA
1131 else if (tTd(11, 1))
1132 printf("openmailer: makeconnection => stat=%d, errno=%d\n",
1133 i, errno);
1134
2ae0e0ed
EA
1135 /* enter status of this host */
1136 setstat(i);
fe3849ea
EA
1137
1138 /* should print some message here for -v mode */
1139 }
1140 if (mci == NULL)
1141 {
1142 syserr("deliver: no host name");
1143 rcode = EX_OSERR;
1144 goto give_up;
1ea752a1 1145 }
3eb4fac4 1146 mci->mci_pid = 0;
f2e44ded 1147#else /* no DAEMON */
b6edea3d 1148 syserr("554 openmailer: no IPC");
237bda52
EA
1149 if (tTd(11, 1))
1150 printf("openmailer: NULL\n");
fe3849ea
EA
1151 rcode = EX_UNAVAILABLE;
1152 goto give_up;
f2e44ded 1153#endif /* DAEMON */
1ab402f2 1154 }
f2e44ded 1155 else
b3cbe40f 1156 {
c1dc4fb9
EA
1157 /* flush any expired connections */
1158 (void) mci_scan(NULL);
1159
1160 /* announce the connection to verbose listeners */
5f14cfca
EA
1161 if (host == NULL || host[0] == '\0')
1162 message("Connecting to %s...", m->m_name);
1163 else
1164 message("Connecting to %s via %s...", host, m->m_name);
8e5c6745 1165 if (TrafficLogFile != NULL)
4a101ce5 1166 {
8e5c6745 1167 char **av;
f22c6db0 1168
8e5c6745
EA
1169 fprintf(TrafficLogFile, "%05d === EXEC", getpid());
1170 for (av = pv; *av != NULL; av++)
1171 fprintf(TrafficLogFile, " %s", *av);
1172 fprintf(TrafficLogFile, "\n");
4a101ce5
EA
1173 }
1174
f2e44ded
EA
1175 /* create a pipe to shove the mail through */
1176 if (pipe(mpvect) < 0)
1177 {
f22c6db0
EA
1178 syserr("%s... openmailer(%s): pipe (to mailer)",
1179 e->e_to, m->m_name);
237bda52
EA
1180 if (tTd(11, 1))
1181 printf("openmailer: NULL\n");
6acfa498
EA
1182 rcode = EX_OSERR;
1183 goto give_up;
f2e44ded 1184 }
e6b0a75b 1185
f2e44ded
EA
1186 /* if this mailer speaks smtp, create a return pipe */
1187 if (clever && pipe(rpvect) < 0)
1188 {
f22c6db0
EA
1189 syserr("%s... openmailer(%s): pipe (from mailer)",
1190 e->e_to, m->m_name);
f2e44ded
EA
1191 (void) close(mpvect[0]);
1192 (void) close(mpvect[1]);
237bda52
EA
1193 if (tTd(11, 1))
1194 printf("openmailer: NULL\n");
6acfa498
EA
1195 rcode = EX_OSERR;
1196 goto give_up;
f2e44ded 1197 }
e6b0a75b 1198
f2e44ded
EA
1199 /*
1200 ** Actually fork the mailer process.
1201 ** DOFORK is clever about retrying.
1202 **
1203 ** Dispose of SIGCHLD signal catchers that may be laying
1204 ** around so that endmail will get it.
1205 */
1ab402f2 1206
f2e44ded
EA
1207 if (e->e_xfp != NULL)
1208 (void) fflush(e->e_xfp); /* for debugging */
1209 (void) fflush(stdout);
1cc8903f 1210# ifdef SIGCHLD
39270cfd 1211 (void) setsignal(SIGCHLD, SIG_DFL);
f3d8f6d6 1212# endif /* SIGCHLD */
f2e44ded
EA
1213 DOFORK(FORK);
1214 /* pid is set by DOFORK */
1215 if (pid < 0)
e6b0a75b 1216 {
f2e44ded 1217 /* failure */
f22c6db0
EA
1218 syserr("%s... openmailer(%s): cannot fork",
1219 e->e_to, m->m_name);
f2e44ded
EA
1220 (void) close(mpvect[0]);
1221 (void) close(mpvect[1]);
1222 if (clever)
1223 {
1224 (void) close(rpvect[0]);
1225 (void) close(rpvect[1]);
1226 }
237bda52
EA
1227 if (tTd(11, 1))
1228 printf("openmailer: NULL\n");
6acfa498
EA
1229 rcode = EX_OSERR;
1230 goto give_up;
e6b0a75b 1231 }
f2e44ded
EA
1232 else if (pid == 0)
1233 {
1234 int i;
f62b79ae 1235 int saveerrno;
8381386b
EA
1236 char **ep;
1237 char *env[MAXUSERENVIRON];
1238 extern char **environ;
f2e44ded 1239 extern int DtableSize;
f2ba91d2 1240
f2e44ded 1241 /* child -- set up input & exec mailer */
39270cfd
EA
1242 (void) setsignal(SIGINT, SIG_IGN);
1243 (void) setsignal(SIGHUP, SIG_IGN);
1244 (void) setsignal(SIGTERM, SIG_DFL);
49086753 1245
8d6e073f 1246 /* reset user and group */
1ff27f9b
EA
1247 if (bitnset(M_SPECIFIC_UID, m->m_flags))
1248 {
1249 (void) setgid(m->m_gid);
1250 (void) setuid(m->m_uid);
1251 }
f5195abb
EA
1252 else if (ctladdr != NULL && ctladdr->q_uid != 0)
1253 {
1254 (void) initgroups(ctladdr->q_ruser?
1255 ctladdr->q_ruser: ctladdr->q_user,
1256 ctladdr->q_gid);
1257 (void) setgid(ctladdr->q_gid);
1258 (void) setuid(ctladdr->q_uid);
1259 }
1ff27f9b 1260 else
8d6e073f 1261 {
f5195abb
EA
1262 (void) initgroups(DefUser, DefGid);
1263 if (m->m_gid == 0)
94d9df0e 1264 (void) setgid(DefGid);
f5195abb
EA
1265 else
1266 (void) setgid(m->m_gid);
1267 if (m->m_uid == 0)
8d6e073f 1268 (void) setuid(DefUid);
8d6e073f 1269 else
f5195abb 1270 (void) setuid(m->m_uid);
8d6e073f
EA
1271 }
1272
1273 if (tTd(11, 2))
1274 printf("openmailer: running as r/euid=%d/%d\n",
1275 getuid(), geteuid());
1276
6f5db107
EA
1277 /* move into some "safe" directory */
1278 if (m->m_execdir != NULL)
1279 {
1280 char *p, *q;
1281 char buf[MAXLINE];
1282
1283 for (p = m->m_execdir; p != NULL; p = q)
1284 {
1285 q = strchr(p, ':');
1286 if (q != NULL)
1287 *q = '\0';
1288 expand(p, buf, &buf[sizeof buf] - 1, e);
1289 if (q != NULL)
1290 *q++ = ':';
1291 if (tTd(11, 20))
1292 printf("openmailer: trydir %s\n",
1293 buf);
1294 if (buf[0] != '\0' && chdir(buf) >= 0)
1295 break;
1296 }
1297 }
1298
f2e44ded
EA
1299 /* arrange to filter std & diag output of command */
1300 if (clever)
1301 {
1302 (void) close(rpvect[0]);
4a101ce5
EA
1303 if (dup2(rpvect[1], STDOUT_FILENO) < 0)
1304 {
f22c6db0
EA
1305 syserr("%s... openmailer(%s): cannot dup pipe %d for stdout",
1306 e->e_to, m->m_name, rpvect[1]);
4a101ce5
EA
1307 _exit(EX_OSERR);
1308 }
f2e44ded
EA
1309 (void) close(rpvect[1]);
1310 }
52f56f58
EA
1311 else if (OpMode == MD_SMTP || OpMode == MD_DAEMON ||
1312 HoldErrs || DisConnected)
f2e44ded
EA
1313 {
1314 /* put mailer output in transcript */
4a101ce5
EA
1315 if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0)
1316 {
f22c6db0
EA
1317 syserr("%s... openmailer(%s): cannot dup xscript %d for stdout",
1318 e->e_to, m->m_name,
4a101ce5
EA
1319 fileno(e->e_xfp));
1320 _exit(EX_OSERR);
1321 }
1322 }
1323 if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
1324 {
f22c6db0
EA
1325 syserr("%s... openmailer(%s): cannot dup stdout for stderr",
1326 e->e_to, m->m_name);
4a101ce5 1327 _exit(EX_OSERR);
f2e44ded 1328 }
49086753 1329
f2e44ded
EA
1330 /* arrange to get standard input */
1331 (void) close(mpvect[1]);
d74803dd 1332 if (dup2(mpvect[0], STDIN_FILENO) < 0)
208e82d2 1333 {
f22c6db0
EA
1334 syserr("%s... openmailer(%s): cannot dup pipe %d for stdin",
1335 e->e_to, m->m_name, mpvect[0]);
f2e44ded 1336 _exit(EX_OSERR);
208e82d2 1337 }
f2e44ded 1338 (void) close(mpvect[0]);
7338e3d4 1339
f2e44ded
EA
1340 /* arrange for all the files to be closed */
1341 for (i = 3; i < DtableSize; i++)
1342 {
1343 register int j;
8d6e073f 1344
f2e44ded 1345 if ((j = fcntl(i, F_GETFD, 0)) != -1)
8d6e073f 1346 (void) fcntl(i, F_SETFD, j | 1);
f2e44ded 1347 }
1ab402f2 1348
33cbaada
EA
1349 /*
1350 ** Set up the mailer environment
7c593b58 1351 ** _FORCE_MAIL_LOCAL_ is DG-UX equiv of -d flag.
33cbaada
EA
1352 ** TZ is timezone information.
1353 ** SYSTYPE is Apollo software sys type (required).
1354 ** ISP is Apollo hardware system type (required).
1355 */
1356
8381386b
EA
1357 i = 0;
1358 env[i++] = "AGENT=sendmail";
7c593b58 1359 env[i++] = "_FORCE_MAIL_LOCAL_=yes";
8381386b
EA
1360 for (ep = environ; *ep != NULL; ep++)
1361 {
33cbaada
EA
1362 if (strncmp(*ep, "TZ=", 3) == 0 ||
1363 strncmp(*ep, "ISP=", 4) == 0 ||
1364 strncmp(*ep, "SYSTYPE=", 8) == 0)
8381386b
EA
1365 env[i++] = *ep;
1366 }
7c593b58 1367 env[i] = NULL;
8381386b 1368
53d9380f
EA
1369 /* run disconnected from terminal */
1370 (void) setsid();
1371
f2e44ded 1372 /* try to execute the mailer */
6acfa498 1373 execve(m->m_mailer, pv, env);
f62b79ae 1374 saveerrno = errno;
f2e44ded 1375 syserr("Cannot exec %s", m->m_mailer);
2bade550
EA
1376 if (bitnset(M_LOCALMAILER, m->m_flags) ||
1377 transienterror(saveerrno))
55b12947 1378 _exit(EX_OSERR);
f2e44ded
EA
1379 _exit(EX_UNAVAILABLE);
1380 }
1381
1382 /*
1383 ** Set up return value.
1384 */
1385
1386 mci = (MCI *) xalloc(sizeof *mci);
3eb4fac4 1387 bzero((char *) mci, sizeof *mci);
f2e44ded
EA
1388 mci->mci_mailer = m;
1389 mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
3eb4fac4 1390 mci->mci_pid = pid;
f2e44ded
EA
1391 (void) close(mpvect[0]);
1392 mci->mci_out = fdopen(mpvect[1], "w");
e9d81da2
EA
1393 if (mci->mci_out == NULL)
1394 {
1395 syserr("deliver: cannot create mailer output channel, fd=%d",
1396 mpvect[1]);
1397 (void) close(mpvect[1]);
1398 if (clever)
1399 {
1400 (void) close(rpvect[0]);
1401 (void) close(rpvect[1]);
1402 }
1403 rcode = EX_OSERR;
1404 goto give_up;
1405 }
f2e44ded
EA
1406 if (clever)
1407 {
1408 (void) close(rpvect[1]);
1409 mci->mci_in = fdopen(rpvect[0], "r");
e9d81da2
EA
1410 if (mci->mci_in == NULL)
1411 {
1412 syserr("deliver: cannot create mailer input channel, fd=%d",
1413 mpvect[1]);
1414 (void) close(rpvect[0]);
1415 fclose(mci->mci_out);
1416 mci->mci_out = NULL;
1417 rcode = EX_OSERR;
1418 goto give_up;
1419 }
f2e44ded
EA
1420 }
1421 else
1422 {
1423 mci->mci_flags |= MCIF_TEMP;
1424 mci->mci_in = NULL;
4287d84d 1425 }
b3cbe40f
EA
1426 }
1427
6acfa498
EA
1428 /*
1429 ** If we are in SMTP opening state, send initial protocol.
1430 */
1431
1432 if (clever && mci->mci_state != MCIS_CLOSED)
1433 {
1434 smtpinit(m, mci, e);
1435 }
f900f13b
EA
1436
1437 if (bitset(EF_HAS8BIT, e->e_flags) && bitnset(M_7BITS, m->m_flags))
1438 mci->mci_flags |= MCIF_CVT8TO7;
1439 else
1440 mci->mci_flags &= ~MCIF_CVT8TO7;
1441
6acfa498
EA
1442 if (tTd(11, 1))
1443 {
1444 printf("openmailer: ");
deff97fd 1445 mci_dump(mci, FALSE);
6acfa498
EA
1446 }
1447
1448 if (mci->mci_state != MCIS_OPEN)
1449 {
1450 /* couldn't open the mailer */
1451 rcode = mci->mci_exitstat;
1452 errno = mci->mci_errno;
efe7f723 1453#if NAMED_BIND
8e5c6745
EA
1454 h_errno = mci->mci_herrno;
1455#endif
6acfa498
EA
1456 if (rcode == EX_OK)
1457 {
1458 /* shouldn't happen */
1459 syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s",
1460 rcode, mci->mci_state, firstsig);
1461 rcode = EX_SOFTWARE;
1462 }
95203269 1463 else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0')
e80c91fc
EA
1464 {
1465 /* try next MX site */
1466 goto tryhost;
1467 }
6acfa498
EA
1468 }
1469 else if (!clever)
1470 {
1471 /*
1472 ** Format and send message.
1473 */
1474
23fafb99 1475 putfromline(mci, e);
a579cea5
EA
1476 (*e->e_puthdr)(mci, e->e_header, e, 0);
1477 (*e->e_putbody)(mci, e, NULL, 0);
6acfa498
EA
1478
1479 /* get the exit status */
1480 rcode = endmailer(mci, e, pv);
1481 }
1482 else
1483#ifdef SMTP
1484 {
1485 /*
1486 ** Send the MAIL FROM: protocol
1487 */
1488
1489 rcode = smtpmailfrom(m, mci, e);
1490 if (rcode == EX_OK)
1491 {
1492 register char *t = tobuf;
1493 register int i;
1494
1495 /* send the recipient list */
1496 tobuf[0] = '\0';
1497 for (to = tochain; to != NULL; to = to->q_tchain)
1498 {
1499 e->e_to = to->q_paddr;
1500 if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
1501 {
1502 markfailure(e, to, i);
5c18c358 1503 giveresponse(i, m, mci, ctladdr, e);
6acfa498
EA
1504 }
1505 else
1506 {
1507 *t++ = ',';
1508 for (p = to->q_paddr; *p; *t++ = *p++)
1509 continue;
51d3cbf1 1510 *t = '\0';
6acfa498
EA
1511 }
1512 }
1513
1514 /* now send the data */
1515 if (tobuf[0] == '\0')
1516 {
1517 rcode = EX_OK;
1518 e->e_to = NULL;
1519 if (bitset(MCIF_CACHED, mci->mci_flags))
1520 smtprset(m, mci, e);
1521 }
1522 else
1523 {
1524 e->e_to = tobuf + 1;
1525 rcode = smtpdata(m, mci, e);
1526 }
1527
1528 /* now close the connection */
1529 if (!bitset(MCIF_CACHED, mci->mci_flags))
1530 smtpquit(m, mci, e);
1531 }
95203269 1532 if (rcode != EX_OK && curhost != NULL && *curhost != '\0')
6acfa498
EA
1533 {
1534 /* try next MX site */
1535 goto tryhost;
1536 }
1537 }
1538#else /* not SMTP */
1539 {
1540 syserr("554 deliver: need SMTP compiled to use clever mailer");
1541 rcode = EX_CONFIG;
1542 goto give_up;
1543 }
1544#endif /* SMTP */
efe7f723 1545#if NAMED_BIND
6acfa498
EA
1546 if (ConfigLevel < 2)
1547 _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */
1548#endif
1549
1550 /* arrange a return receipt if requested */
fe3849ea
EA
1551 if (rcode == EX_OK && e->e_receiptto != NULL &&
1552 bitnset(M_LOCALMAILER, m->m_flags))
6acfa498
EA
1553 {
1554 e->e_flags |= EF_SENDRECEIPT;
1555 /* do we want to send back more info? */
1556 }
1557
1558 /*
1559 ** Do final status disposal.
1560 ** We check for something in tobuf for the SMTP case.
1561 ** If we got a temporary failure, arrange to queue the
1562 ** addressees.
1563 */
1564
1565 give_up:
1566 if (tobuf[0] != '\0')
5c18c358 1567 giveresponse(rcode, m, mci, ctladdr, e);
6acfa498
EA
1568 for (to = tochain; to != NULL; to = to->q_tchain)
1569 {
1570 if (rcode != EX_OK)
1571 markfailure(e, to, rcode);
1572 else
1573 {
1574 to->q_flags |= QSENT;
f8c2f9fd 1575 to->q_statdate = curtime();
6acfa498 1576 e->e_nsent++;
68d9129a
EA
1577 if (bitnset(M_LOCALMAILER, m->m_flags) &&
1578 (e->e_receiptto != NULL ||
1579 bitset(QPINGONSUCCESS, to->q_flags)))
fe3849ea 1580 {
68d9129a 1581 to->q_flags |= QREPORT;
fe3849ea
EA
1582 fprintf(e->e_xfp, "%s... Successfully delivered\n",
1583 to->q_paddr);
1584 }
6acfa498
EA
1585 }
1586 }
1587
1588 /*
1589 ** Restore state and return.
1590 */
1591
061a3d08
EA
1592#ifdef XDEBUG
1593 {
1594 char wbuf[MAXLINE];
1595
1596 /* make absolutely certain 0, 1, and 2 are in use */
164f3011
EA
1597 sprintf(wbuf, "%s... end of deliver(%s)",
1598 e->e_to == NULL ? "NO-TO-LIST" : e->e_to,
1599 m->m_name);
061a3d08
EA
1600 checkfd012(wbuf);
1601 }
1602#endif
1603
6acfa498
EA
1604 errno = 0;
1605 define('g', (char *) NULL, e);
1606 return (rcode);
1607}
1608\f/*
1609** MARKFAILURE -- mark a failure on a specific address.
1610**
1611** Parameters:
1612** e -- the envelope we are sending.
1613** q -- the address to mark.
1614** rcode -- the code signifying the particular failure.
1615**
1616** Returns:
1617** none.
1618**
1619** Side Effects:
1620** marks the address (and possibly the envelope) with the
1621** failure so that an error will be returned or
1622** the message will be queued, as appropriate.
1623*/
1624
1625markfailure(e, q, rcode)
1626 register ENVELOPE *e;
1627 register ADDRESS *q;
1628 int rcode;
1629{
1630 char buf[MAXLINE];
6acfa498 1631
26c2fd9b
EA
1632 switch (rcode)
1633 {
1634 case EX_OK:
1635 break;
1636
1637 case EX_TEMPFAIL:
1638 case EX_IOERR:
1639 case EX_OSERR:
6acfa498 1640 q->q_flags |= QQUEUEUP;
26c2fd9b
EA
1641 break;
1642
1643 default:
8e5c6745 1644 q->q_flags |= QBADADDR;
26c2fd9b
EA
1645 break;
1646 }
68d9129a
EA
1647 q->q_statdate = curtime();
1648 q->q_statmta = newstr(CurHostName);
6acfa498
EA
1649}
1650\f/*
1651** ENDMAILER -- Wait for mailer to terminate.
1652**
1653** We should never get fatal errors (e.g., segmentation
1654** violation), so we report those specially. For other
1655** errors, we choose a status message (into statmsg),
1656** and if it represents an error, we print it.
1657**
1658** Parameters:
1659** pid -- pid of mailer.
1660** e -- the current envelope.
1661** pv -- the parameter vector that invoked the mailer
1662** (for error messages).
1663**
1664** Returns:
1665** exit code of mailer.
1666**
1667** Side Effects:
1668** none.
1669*/
1670
1671endmailer(mci, e, pv)
1672 register MCI *mci;
1673 register ENVELOPE *e;
1674 char **pv;
1675{
1676 int st;
1677
1678 /* close any connections */
1679 if (mci->mci_in != NULL)
14809fd5 1680 (void) xfclose(mci->mci_in, mci->mci_mailer->m_name, "mci_in");
6acfa498 1681 if (mci->mci_out != NULL)
14809fd5 1682 (void) xfclose(mci->mci_out, mci->mci_mailer->m_name, "mci_out");
6acfa498
EA
1683 mci->mci_in = mci->mci_out = NULL;
1684 mci->mci_state = MCIS_CLOSED;
49086753 1685
6acfa498
EA
1686 /* in the IPC case there is nothing to wait for */
1687 if (mci->mci_pid == 0)
1688 return (EX_OK);
1689
1690 /* wait for the mailer process to die and collect status */
1691 st = waitfor(mci->mci_pid);
1692 if (st == -1)
b3cbe40f 1693 {
6acfa498
EA
1694 syserr("endmailer %s: wait", pv[0]);
1695 return (EX_SOFTWARE);
2ae0e0ed 1696 }
6acfa498 1697
e3791bb6 1698 if (WIFEXITED(st))
237bda52 1699 {
e3791bb6
EA
1700 /* normal death -- return status */
1701 return (WEXITSTATUS(st));
1702 }
6acfa498 1703
e3791bb6 1704 /* it died a horrid death */
0baa9aea
EA
1705 syserr("451 mailer %s died with signal %o",
1706 mci->mci_mailer->m_name, st);
6acfa498 1707
e3791bb6 1708 /* log the arguments */
c1e6eba2 1709 if (pv != NULL && e->e_xfp != NULL)
e3791bb6
EA
1710 {
1711 register char **av;
6acfa498 1712
e3791bb6
EA
1713 fprintf(e->e_xfp, "Arguments:");
1714 for (av = pv; *av != NULL; av++)
1715 fprintf(e->e_xfp, " %s", *av);
1716 fprintf(e->e_xfp, "\n");
237bda52 1717 }
e6b0a75b 1718
e3791bb6
EA
1719 ExitStat = EX_TEMPFAIL;
1720 return (EX_TEMPFAIL);
b3cbe40f
EA
1721}
1722\f/*
1723** GIVERESPONSE -- Interpret an error response from a mailer
1724**
1725** Parameters:
1726** stat -- the status code from the mailer (high byte
1727** only; core dumps must have been taken care of
1728** already).
c0ae0b24
EA
1729** m -- the mailer info for this mailer.
1730** mci -- the mailer connection info -- can be NULL if the
1731** response is given before the connection is made.
5c18c358
EA
1732** ctladdr -- the controlling address for the recipient
1733** address(es).
c0ae0b24 1734** e -- the current envelope.
b3cbe40f
EA
1735**
1736** Returns:
29871fef 1737** none.
b3cbe40f
EA
1738**
1739** Side Effects:
d916f0ca 1740** Errors may be incremented.
b3cbe40f 1741** ExitStat may be set.
b3cbe40f
EA
1742*/
1743
5c18c358 1744giveresponse(stat, m, mci, ctladdr, e)
b3cbe40f 1745 int stat;
7338e3d4 1746 register MAILER *m;
c0ae0b24 1747 register MCI *mci;
5c18c358 1748 ADDRESS *ctladdr;
baa0c390 1749 ENVELOPE *e;
b3cbe40f 1750{
c51d6c4c 1751 register const char *statmsg;
b3cbe40f
EA
1752 extern char *SysExMsg[];
1753 register int i;
a0c75a49 1754 extern int N_SysEx;
baa0c390 1755 char buf[MAXLINE];
b3cbe40f 1756
74c5fe7c
EA
1757 /*
1758 ** Compute status message from code.
1759 */
1760
b3cbe40f 1761 i = stat - EX__BASE;
7338e3d4 1762 if (stat == 0)
4a101ce5 1763 {
7338e3d4 1764 statmsg = "250 Sent";
988a20e2 1765 if (e->e_statmsg != NULL)
4a101ce5 1766 {
988a20e2 1767 (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg);
4a101ce5
EA
1768 statmsg = buf;
1769 }
1770 }
7338e3d4
EA
1771 else if (i < 0 || i > N_SysEx)
1772 {
1773 (void) sprintf(buf, "554 unknown mailer error %d", stat);
1774 stat = EX_UNAVAILABLE;
1775 statmsg = buf;
1776 }
baa0c390
EA
1777 else if (stat == EX_TEMPFAIL)
1778 {
2388926b 1779 (void) strcpy(buf, SysExMsg[i] + 1);
efe7f723 1780#if NAMED_BIND
88d7486c 1781 if (h_errno == TRY_AGAIN)
92f2b65e 1782 statmsg = errstring(h_errno+E_DNSBASE);
46f6ec52 1783 else
a0c75a49 1784#endif
46f6ec52 1785 {
88d7486c 1786 if (errno != 0)
88d7486c 1787 statmsg = errstring(errno);
88d7486c
MAN
1788 else
1789 {
46f6ec52 1790#ifdef SMTP
88d7486c 1791 statmsg = SmtpError;
f3d8f6d6 1792#else /* SMTP */
88d7486c 1793 statmsg = NULL;
f3d8f6d6 1794#endif /* SMTP */
88d7486c 1795 }
46f6ec52
EA
1796 }
1797 if (statmsg != NULL && statmsg[0] != '\0')
1798 {
e41c463e 1799 (void) strcat(buf, ": ");
46f6ec52 1800 (void) strcat(buf, statmsg);
baa0c390 1801 }
baa0c390
EA
1802 statmsg = buf;
1803 }
efe7f723 1804#if NAMED_BIND
8e5c6745
EA
1805 else if (stat == EX_NOHOST && h_errno != 0)
1806 {
92f2b65e 1807 statmsg = errstring(h_errno + E_DNSBASE);
1fd465b3 1808 (void) sprintf(buf, "%s (%s)", SysExMsg[i] + 1, statmsg);
8e5c6745
EA
1809 statmsg = buf;
1810 }
1811#endif
b3cbe40f 1812 else
46f6ec52 1813 {
b3cbe40f 1814 statmsg = SysExMsg[i];
2388926b
EA
1815 if (*statmsg++ == ':')
1816 {
1817 (void) sprintf(buf, "%s: %s", statmsg, errstring(errno));
1818 statmsg = buf;
1819 }
46f6ec52 1820 }
7338e3d4
EA
1821
1822 /*
1823 ** Print the message as appropriate
1824 */
1825
baa0c390 1826 if (stat == EX_OK || stat == EX_TEMPFAIL)
fe3849ea
EA
1827 {
1828 extern char MsgBuf[];
1829
b10e0325 1830 message("%s", &statmsg[4]);
fe3849ea
EA
1831 if (stat == EX_TEMPFAIL && e->e_xfp != NULL)
1832 fprintf(e->e_xfp, "%s\n", &MsgBuf[4]);
1833 }
b3cbe40f
EA
1834 else
1835 {
1fd465b3
EA
1836 char mbuf[8];
1837
d916f0ca 1838 Errors++;
1fd465b3
EA
1839 sprintf(mbuf, "%.3s %%s", statmsg);
1840 usrerr(mbuf, &statmsg[4]);
b3cbe40f
EA
1841 }
1842
1843 /*
1844 ** Final cleanup.
1845 ** Log a record of the transaction. Compute the new
1846 ** ExitStat -- if we already had an error, stick with
1847 ** that.
1848 */
1849
68f7099c 1850 if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))
5c18c358 1851 logdelivery(m, mci, &statmsg[4], ctladdr, e);
96476cab 1852
ed3d2b02
EA
1853 if (tTd(11, 2))
1854 printf("giveresponse: stat=%d, e->e_message=%s\n",
7ad0fe38 1855 stat, e->e_message == NULL ? "<NULL>" : e->e_message);
ed3d2b02 1856
ed45aae1
EA
1857 if (stat != EX_TEMPFAIL)
1858 setstat(stat);
f2a96b27 1859 if (stat != EX_OK && (stat != EX_TEMPFAIL || e->e_message == NULL))
baa0c390
EA
1860 {
1861 if (e->e_message != NULL)
1862 free(e->e_message);
1863 e->e_message = newstr(&statmsg[4]);
1864 }
e4602f52 1865 errno = 0;
efe7f723 1866#if NAMED_BIND
88d7486c 1867 h_errno = 0;
a0c75a49 1868#endif
b3cbe40f
EA
1869}
1870\f/*
fe033a8f
EA
1871** LOGDELIVERY -- log the delivery in the system log
1872**
eaad1064
EA
1873** Care is taken to avoid logging lines that are too long, because
1874** some versions of syslog have an unfortunate proclivity for core
1875** dumping. This is a hack, to be sure, that is at best empirical.
1876**
fe033a8f 1877** Parameters:
c0ae0b24
EA
1878** m -- the mailer info. Can be NULL for initial queue.
1879** mci -- the mailer connection info -- can be NULL if the
1880** log is occuring when no connection is active.
1881** stat -- the message to print for the status.
5c18c358 1882** ctladdr -- the controlling address for the to list.
c0ae0b24 1883** e -- the current envelope.
fe033a8f
EA
1884**
1885** Returns:
1886** none
1887**
1888** Side Effects:
1889** none
1890*/
1891
5c18c358 1892logdelivery(m, mci, stat, ctladdr, e)
c0ae0b24
EA
1893 MAILER *m;
1894 register MCI *mci;
fe033a8f 1895 char *stat;
5c18c358 1896 ADDRESS *ctladdr;
f2e44ded 1897 register ENVELOPE *e;
fe033a8f 1898{
fc93dffb 1899# ifdef LOG
5c18c358 1900 register char *bp;
eaad1064
EA
1901 register char *p;
1902 int l;
ef71c549 1903 char buf[512];
fe033a8f 1904
2bbc90ee 1905# if (SYSLOG_BUFSIZE) >= 256
5c18c358
EA
1906 bp = buf;
1907 if (ctladdr != NULL)
1908 {
1909 strcpy(bp, ", ctladdr=");
ab88ddec 1910 strcat(bp, shortenstring(ctladdr->q_paddr, 83));
5c18c358
EA
1911 bp += strlen(bp);
1912 if (bitset(QGOODUID, ctladdr->q_flags))
1913 {
1914 (void) sprintf(bp, " (%d/%d)",
1915 ctladdr->q_uid, ctladdr->q_gid);
1916 bp += strlen(bp);
1917 }
1918 }
1919
1920 (void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
1921 bp += strlen(bp);
c0ae0b24 1922
4e82a943 1923 if (m != NULL)
9b95d94a 1924 {
5c18c358
EA
1925 (void) strcpy(bp, ", mailer=");
1926 (void) strcat(bp, m->m_name);
1927 bp += strlen(bp);
9b95d94a 1928 }
4e82a943
EA
1929
1930 if (mci != NULL && mci->mci_host != NULL)
9b95d94a 1931 {
9b95d94a 1932# ifdef DAEMON
3341995c 1933 extern SOCKADDR CurHostAddr;
4e82a943
EA
1934# endif
1935
5c18c358
EA
1936 (void) strcpy(bp, ", relay=");
1937 (void) strcat(bp, mci->mci_host);
9b95d94a 1938
4e82a943 1939# ifdef DAEMON
d285c43b 1940 (void) strcat(bp, " [");
5c18c358 1941 (void) strcat(bp, anynet_ntoa(&CurHostAddr));
d285c43b 1942 (void) strcat(bp, "]");
9b95d94a 1943# endif
9b95d94a 1944 }
8fbbb079 1945 else if (strcmp(stat, "queued") != 0)
4e82a943
EA
1946 {
1947 char *p = macvalue('h', e);
fc93dffb 1948
4e82a943
EA
1949 if (p != NULL && p[0] != '\0')
1950 {
5c18c358
EA
1951 (void) strcpy(bp, ", relay=");
1952 (void) strcat(bp, p);
4e82a943
EA
1953 }
1954 }
95203269 1955 bp += strlen(bp);
eaad1064 1956
2bbc90ee
EA
1957#define STATLEN (((SYSLOG_BUFSIZE) - 100) / 4)
1958#if (STATLEN) < 63
1959# undef STATLEN
1960# define STATLEN 63
1961#endif
1962#if (STATLEN) > 203
1963# undef STATLEN
1964# define STATLEN 203
1965#endif
1966
1967 if ((bp - buf) > (sizeof buf - ((STATLEN) + 20)))
eaad1064
EA
1968 {
1969 /* desperation move -- truncate data */
2bbc90ee 1970 bp = buf + sizeof buf - ((STATLEN) + 17);
eaad1064
EA
1971 strcpy(bp, "...");
1972 bp += 3;
1973 }
1974
1975 (void) strcpy(bp, ", stat=");
1976 bp += strlen(bp);
2bbc90ee
EA
1977
1978 (void) strcpy(bp, shortenstring(stat, (STATLEN)));
ef71c549 1979
eaad1064
EA
1980 l = SYSLOG_BUFSIZE - 100 - strlen(buf);
1981 p = e->e_to;
1982 while (strlen(p) >= l)
1983 {
1984 register char *q = strchr(p + l, ',');
1985
58e480ef 1986 if (q == NULL)
eaad1064
EA
1987 break;
1988 syslog(LOG_INFO, "%s: to=%.*s [more]%s",
1989 e->e_id, ++q - p, p, buf);
1990 p = q;
1991 }
1992 syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf);
2bbc90ee
EA
1993
1994# else /* we have a very short log buffer size */
1995
ec33213e 1996 l = SYSLOG_BUFSIZE - 85;
2bbc90ee
EA
1997 p = e->e_to;
1998 while (strlen(p) >= l)
1999 {
2000 register char *q = strchr(p + l, ',');
2001
2002 if (q == NULL)
2003 break;
2004 syslog(LOG_INFO, "%s: to=%.*s [more]",
2005 e->e_id, ++q - p, p);
2006 p = q;
2007 }
2008 syslog(LOG_INFO, "%s: to=%s", e->e_id, p);
2009
2010 if (ctladdr != NULL)
2011 {
2012 bp = buf;
2013 strcpy(buf, "ctladdr=");
2014 bp += strlen(buf);
2015 strcpy(bp, shortenstring(ctladdr->q_paddr, 83));
2016 bp += strlen(buf);
2017 if (bitset(QGOODUID, ctladdr->q_flags))
2018 {
2019 (void) sprintf(bp, " (%d/%d)",
2020 ctladdr->q_uid, ctladdr->q_gid);
2021 bp += strlen(bp);
2022 }
2023 syslog(LOG_INFO, "%s: %s", e->e_id, buf);
2024 }
3e05a82f
EA
2025 bp = buf;
2026 sprintf(bp, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
2027 bp += strlen(bp);
2bbc90ee
EA
2028
2029 if (m != NULL)
3e05a82f
EA
2030 {
2031 sprintf(bp, ", mailer=%s", m->m_name);
2032 bp += strlen(bp);
2033 }
e5b0f01f 2034 syslog(LOG_INFO, "%s: %s", e->e_id, buf);
2bbc90ee 2035
e5b0f01f 2036 buf[0] = '\0';
2bbc90ee
EA
2037 if (mci != NULL && mci->mci_host != NULL)
2038 {
2039# ifdef DAEMON
2040 extern SOCKADDR CurHostAddr;
2041# endif
2042
2c5b66fc 2043 sprintf(buf, "relay=%s", mci->mci_host);
2bbc90ee
EA
2044
2045# ifdef DAEMON
e5b0f01f
EA
2046 (void) strcat(buf, " [");
2047 (void) strcat(buf, anynet_ntoa(&CurHostAddr));
2048 (void) strcat(buf, "]");
2bbc90ee 2049# endif
2bbc90ee 2050 }
8fbbb079 2051 else if (strcmp(stat, "queued") != 0)
2bbc90ee
EA
2052 {
2053 char *p = macvalue('h', e);
2054
2055 if (p != NULL && p[0] != '\0')
2c5b66fc 2056 sprintf(buf, "relay=%s", p);
2bbc90ee 2057 }
e5b0f01f
EA
2058 if (buf[0] != '\0')
2059 syslog(LOG_INFO, "%s: %s", e->e_id, buf);
2bbc90ee 2060
2bbc90ee
EA
2061 syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63));
2062# endif /* short log buffer */
f3d8f6d6 2063# endif /* LOG */
fe033a8f
EA
2064}
2065\f/*
dd1fe05b 2066** PUTFROMLINE -- output a UNIX-style from line (or whatever)
b3cbe40f 2067**
3c567393
EA
2068** then passes the rest of the message through. If we have
2069** managed to extract a date already, use that; otherwise,
2070** use the current date/time.
b3cbe40f 2071**
a73ae8ac
EA
2072** One of the ugliest hacks seen by human eyes is contained herein:
2073** UUCP wants those stupid "remote from <host>" lines. Why oh why
2074** does a well-meaning programmer such as myself have to deal with
2075** this kind of antique garbage????
dd1fe05b 2076**
b3cbe40f 2077** Parameters:
23fafb99
EA
2078** mci -- the connection information.
2079** e -- the envelope.
b3cbe40f
EA
2080**
2081** Returns:
dd1fe05b 2082** none
b3cbe40f
EA
2083**
2084** Side Effects:
dd1fe05b 2085** outputs some text to fp.
b3cbe40f
EA
2086*/
2087
23fafb99
EA
2088putfromline(mci, e)
2089 register MCI *mci;
f2e44ded 2090 ENVELOPE *e;
b3cbe40f 2091{
2bee003d 2092 char *template = "\201l\n";
dd1fe05b 2093 char buf[MAXLINE];
3c567393 2094 extern char SentDate[];
b3cbe40f 2095
23fafb99 2096 if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
dd1fe05b 2097 return;
74c5fe7c 2098
884a20cb 2099# ifdef UGLYUUCP
23fafb99 2100 if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags))
79bd7c07 2101 {
9aecbdbe
EA
2102 char *bang;
2103 char xbuf[MAXLINE];
79bd7c07 2104
bc854e30 2105 expand("\201g", buf, &buf[sizeof buf - 1], e);
f3d8f6d6 2106 bang = strchr(buf, '!');
dd1fe05b 2107 if (bang == NULL)
1673be04
EA
2108 {
2109 errno = 0;
2110 syserr("554 No ! in UUCP From address! (%s given)", buf);
2111 }
dd1fe05b 2112 else
7338e3d4 2113 {
9aecbdbe 2114 *bang++ = '\0';
2bee003d 2115 (void) sprintf(xbuf, "From %s \201d remote from %s\n", bang, buf);
9aecbdbe 2116 template = xbuf;
7338e3d4 2117 }
79bd7c07 2118 }
f3d8f6d6 2119# endif /* UGLYUUCP */
f2e44ded 2120 expand(template, buf, &buf[sizeof buf - 1], e);
23fafb99 2121 putline(buf, mci);
79bd7c07
EA
2122}
2123\f/*
6acfa498 2124** PUTBODY -- put the body of a message.
cbdb7357
EA
2125**
2126** Parameters:
23fafb99 2127** mci -- the connection information.
6acfa498 2128** e -- the envelope to put out.
2f6a8a78
EA
2129** separator -- if non-NULL, a message separator that must
2130** not be permitted in the resulting message.
a579cea5 2131** flags -- to modify the behaviour.
cbdb7357
EA
2132**
2133** Returns:
2134** none.
2135**
2136** Side Effects:
6acfa498 2137** The message is written onto fp.
cbdb7357
EA
2138*/
2139
0d721ffb
EA
2140/* values for output state variable */
2141#define OS_HEAD 0 /* at beginning of line */
2142#define OS_CR 1 /* read a carriage return */
2143#define OS_INLINE 2 /* putting rest of line */
2144
a579cea5 2145putbody(mci, e, separator, flags)
23fafb99 2146 register MCI *mci;
6acfa498 2147 register ENVELOPE *e;
2f6a8a78 2148 char *separator;
a579cea5 2149 int flags;
cbdb7357 2150{
6acfa498 2151 char buf[MAXLINE];
cbdb7357 2152
3c7fe765 2153 /*
6acfa498 2154 ** Output the body of the message
3c7fe765
EA
2155 */
2156
cd37f61d
EA
2157 if (e->e_dfp == NULL && e->e_df != NULL)
2158 {
2159 e->e_dfp = fopen(e->e_df, "r");
2160 if (e->e_dfp == NULL)
2161 syserr("putbody: Cannot open %s for %s from %s",
2162 e->e_df, e->e_to, e->e_from.q_paddr);
2163 }
6acfa498 2164 if (e->e_dfp == NULL)
7338e3d4 2165 {
cd37f61d 2166 if (bitset(MCIF_INHEADER, mci->mci_flags))
78bbbc48 2167 {
cd37f61d
EA
2168 putline("", mci);
2169 mci->mci_flags &= ~MCIF_INHEADER;
c23930c0 2170 }
cd37f61d
EA
2171 putline("<<< No Message Collected >>>", mci);
2172 goto endofmessage;
84daea29 2173 }
cd37f61d 2174 if (e->e_dfino == (ino_t) 0)
f009d24b
EA
2175 {
2176 struct stat stbuf;
2177
2178 if (fstat(fileno(e->e_dfp), &stbuf) < 0)
2179 e->e_dfino = -1;
2180 else
bb4fde22
EA
2181 {
2182 e->e_dfdev = stbuf.st_dev;
f009d24b 2183 e->e_dfino = stbuf.st_ino;
bb4fde22 2184 }
f009d24b 2185 }
0d721ffb 2186 rewind(e->e_dfp);
c23930c0 2187
0d721ffb
EA
2188 if (bitset(MCIF_CVT8TO7, mci->mci_flags))
2189 {
bb4fde22
EA
2190 /*
2191 ** Do 8 to 7 bit MIME conversion.
2192 */
2193
2194 /* make sure it looks like a MIME message */
0d721ffb
EA
2195 if (hvalue("MIME-Version", e->e_header) == NULL)
2196 putline("MIME-Version: 1.0", mci);
bb4fde22 2197
bb4fde22 2198 if (hvalue("Content-Type", e->e_header) == NULL)
a50ac3e2 2199 {
a50ac3e2 2200 sprintf(buf, "Content-Type: text/plain; charset=%s",
3caf3b1f 2201 defcharset(e));
a50ac3e2
EA
2202 putline(buf, mci);
2203 }
bb4fde22
EA
2204
2205 /* now do the hard work */
0d721ffb
EA
2206 mime8to7(mci, e->e_header, e, NULL);
2207 }
2208 else
2209 {
2210 int ostate;
2211 register char *bp;
2212 register char *pbp;
2213 register int c;
2214 int padc;
2215 char *buflim;
2216 int pos;
2217 char peekbuf[10];
2218
2219 /* we can pass it through unmodified */
2220 if (bitset(MCIF_INHEADER, mci->mci_flags))
c23930c0 2221 {
0d721ffb
EA
2222 putline("", mci);
2223 mci->mci_flags &= ~MCIF_INHEADER;
c23930c0 2224 }
0d721ffb
EA
2225
2226 /* determine end of buffer; allow for short mailer lines */
2227 buflim = &buf[sizeof buf - 1];
098e8e2c
EA
2228 if (mci->mci_mailer->m_linelimit > 0 &&
2229 mci->mci_mailer->m_linelimit < sizeof buf - 1)
0d721ffb
EA
2230 buflim = &buf[mci->mci_mailer->m_linelimit - 1];
2231
2232 /* copy temp file to output with mapping */
2233 ostate = OS_HEAD;
2234 bp = buf;
2235 pbp = peekbuf;
2236 while (!ferror(mci->mci_out))
84daea29 2237 {
0d721ffb
EA
2238 register char *xp;
2239
2240 if (pbp > peekbuf)
2241 c = *--pbp;
2242 else if ((c = fgetc(e->e_dfp)) == EOF)
2243 break;
2244 if (bitset(MCIF_7BIT, mci->mci_flags))
2245 c &= 0x7f;
2246 switch (ostate)
2f6a8a78 2247 {
0d721ffb
EA
2248 case OS_HEAD:
2249 if (c != '\r' && c != '\n' && bp < buflim)
2250 {
2251 *bp++ = c;
2252 break;
2253 }
2254
2255 /* check beginning of line for special cases */
2256 *bp = '\0';
2257 pos = 0;
2258 padc = EOF;
c23930c0
EA
2259 if (buf[0] == 'F' &&
2260 bitnset(M_ESCFROM, mci->mci_mailer->m_flags) &&
2261 strncmp(buf, "From ", 5) == 0)
0d721ffb
EA
2262 {
2263 padc = '>';
2264 }
c23930c0
EA
2265 if (buf[0] == '-' && buf[1] == '-' &&
2266 separator != NULL)
2267 {
2268 /* possible separator */
2269 int sl = strlen(separator);
2f6a8a78 2270
c23930c0 2271 if (strncmp(&buf[2], separator, sl) == 0)
0d721ffb 2272 padc = ' ';
c23930c0 2273 }
0d721ffb
EA
2274 if (buf[0] == '.' &&
2275 bitnset(M_XDOT, mci->mci_mailer->m_flags))
2276 {
2277 padc = '.';
2278 }
2279
2280 /* now copy out saved line */
2281 if (TrafficLogFile != NULL)
2282 {
2283 fprintf(TrafficLogFile, "%05d >>> ", getpid());
2284 if (padc != EOF)
2285 fputc(padc, TrafficLogFile);
2286 for (xp = buf; xp < bp; xp++)
2287 fputc(*xp, TrafficLogFile);
2288 if (c == '\n')
2289 fputs(mci->mci_mailer->m_eol,
2290 TrafficLogFile);
2291 }
2292 if (padc != EOF)
2293 {
2294 fputc(padc, mci->mci_out);
2295 pos++;
2296 }
2297 for (xp = buf; xp < bp; xp++)
2298 fputc(*xp, mci->mci_out);
2299 if (c == '\n')
2300 {
2301 fputs(mci->mci_mailer->m_eol,
2302 mci->mci_out);
2303 pos = 0;
2304 }
2305 else
2306 {
2307 pos += bp - buf;
a4041586
EA
2308 if (c != '\r')
2309 *pbp++ = c;
0d721ffb
EA
2310 }
2311 bp = buf;
2312
2313 /* determine next state */
2314 if (c == '\n')
2315 ostate = OS_HEAD;
2316 else if (c == '\r')
2317 ostate = OS_CR;
2318 else
2319 ostate = OS_INLINE;
2320 continue;
2321
2322 case OS_CR:
2323 if (c == '\n')
2324 {
2325 /* got CRLF */
2326 fputs(mci->mci_mailer->m_eol, mci->mci_out);
2327 if (TrafficLogFile != NULL)
2328 {
2329 fputs(mci->mci_mailer->m_eol,
2330 TrafficLogFile);
2331 }
2332 ostate = OS_HEAD;
2333 continue;
2334 }
2335
2336 /* had a naked carriage return */
2337 *pbp++ = c;
2338 c = '\r';
68e6bb99 2339 goto putch;
0d721ffb
EA
2340
2341 case OS_INLINE:
2342 if (c == '\r')
2343 {
2344 ostate = OS_CR;
2345 continue;
2346 }
68e6bb99 2347putch:
098e8e2c
EA
2348 if (mci->mci_mailer->m_linelimit > 0 &&
2349 pos > mci->mci_mailer->m_linelimit &&
0d721ffb
EA
2350 c != '\n')
2351 {
2352 putc('!', mci->mci_out);
2353 fputs(mci->mci_mailer->m_eol, mci->mci_out);
2354 if (TrafficLogFile != NULL)
2355 {
2356 fprintf(TrafficLogFile, "!%s",
2357 mci->mci_mailer->m_eol);
2358 }
2359 ostate = OS_HEAD;
2360 *pbp++ = c;
2361 continue;
2362 }
2363 if (TrafficLogFile != NULL)
2364 fputc(c, TrafficLogFile);
2365 putc(c, mci->mci_out);
2366 pos++;
a4041586 2367 ostate = c == '\n' ? OS_HEAD : OS_INLINE;
0d721ffb 2368 break;
2f6a8a78 2369 }
84daea29 2370 }
0d721ffb 2371 }
84daea29 2372
0d721ffb
EA
2373 if (ferror(e->e_dfp))
2374 {
2375 syserr("putbody: %s: read error", e->e_df);
2376 ExitStat = EX_IOERR;
baa2b877 2377 }
75f95954 2378
0d721ffb 2379endofmessage:
1537ac22 2380 /* some mailers want extra blank line at end of message */
23fafb99
EA
2381 if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) &&
2382 buf[0] != '\0' && buf[0] != '\n')
2383 putline("", mci);
1537ac22 2384
23fafb99
EA
2385 (void) fflush(mci->mci_out);
2386 if (ferror(mci->mci_out) && errno != EPIPE)
84daea29 2387 {
6acfa498
EA
2388 syserr("putbody: write error");
2389 ExitStat = EX_IOERR;
84daea29 2390 }
6acfa498 2391 errno = 0;
bc854e30 2392}
6acfa498
EA
2393\f/*
2394** MAILFILE -- Send a message to a file.
2395**
2396** If the file has the setuid/setgid bits set, but NO execute
2397** bits, sendmail will try to become the owner of that file
2398** rather than the real user. Obviously, this only works if
2399** sendmail runs as root.
2400**
2401** This could be done as a subordinate mailer, except that it
2402** is used implicitly to save messages in ~/dead.letter. We
2403** view this as being sufficiently important as to include it
2404** here. For example, if the system is dying, we shouldn't have
2405** to create another process plus some pipes to save the message.
2406**
2407** Parameters:
2408** filename -- the name of the file to send to.
2409** ctladdr -- the controlling address header -- includes
2410** the userid/groupid to be when sending.
2411**
2412** Returns:
2413** The exit code associated with the operation.
2414**
2415** Side Effects:
2416** none.
2417*/
bc854e30 2418
6acfa498
EA
2419mailfile(filename, ctladdr, e)
2420 char *filename;
2421 ADDRESS *ctladdr;
bc854e30 2422 register ENVELOPE *e;
bc854e30 2423{
6acfa498
EA
2424 register FILE *f;
2425 register int pid;
2426 int mode;
84daea29 2427
831d7357
EA
2428 if (tTd(11, 1))
2429 {
2430 printf("mailfile %s\n ctladdr=", filename);
2431 printaddr(ctladdr, FALSE);
2432 }
2433
8e5c6745
EA
2434 if (e->e_xfp != NULL)
2435 fflush(e->e_xfp);
2436
6acfa498
EA
2437 /*
2438 ** Fork so we can change permissions here.
2439 ** Note that we MUST use fork, not vfork, because of
2440 ** the complications of calling subroutines, etc.
2441 */
2442
2443 DOFORK(fork);
2444
2445 if (pid < 0)
2446 return (EX_OSERR);
2447 else if (pid == 0)
75f95954 2448 {
6acfa498
EA
2449 /* child -- actually write to file */
2450 struct stat stb;
23fafb99 2451 MCI mcibuf;
75f95954 2452
39270cfd
EA
2453 (void) setsignal(SIGINT, SIG_DFL);
2454 (void) setsignal(SIGHUP, SIG_DFL);
2455 (void) setsignal(SIGTERM, SIG_DFL);
6acfa498 2456 (void) umask(OldUmask);
75f95954 2457
6acfa498 2458 if (stat(filename, &stb) < 0)
6f7f4e2c 2459 stb.st_mode = FileMode;
6acfa498 2460 mode = stb.st_mode;
07800f98 2461
6acfa498
EA
2462 /* limit the errors to those actually caused in the child */
2463 errno = 0;
2464 ExitStat = EX_OK;
07800f98 2465
6acfa498
EA
2466 if (bitset(0111, stb.st_mode))
2467 exit(EX_CANTCREAT);
0419e00c 2468 if (ctladdr != NULL)
07800f98 2469 {
6acfa498
EA
2470 /* ignore setuid and setgid bits */
2471 mode &= ~(S_ISGID|S_ISUID);
07800f98 2472 }
07800f98 2473
6acfa498
EA
2474 /* we have to open the dfile BEFORE setuid */
2475 if (e->e_dfp == NULL && e->e_df != NULL)
813d8709 2476 {
6acfa498
EA
2477 e->e_dfp = fopen(e->e_df, "r");
2478 if (e->e_dfp == NULL)
78bbbc48 2479 {
6acfa498 2480 syserr("mailfile: Cannot open %s for %s from %s",
80ec5253 2481 e->e_df, e->e_to, e->e_from.q_paddr);
78bbbc48 2482 }
6acfa498 2483 }
78bbbc48 2484
6acfa498
EA
2485 if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0)
2486 {
0c35b842 2487 if (ctladdr != NULL && ctladdr->q_uid != 0)
6acfa498
EA
2488 (void) initgroups(ctladdr->q_ruser ?
2489 ctladdr->q_ruser : ctladdr->q_user,
2490 ctladdr->q_gid);
0c35b842
EA
2491 else if (FileMailer != NULL && FileMailer->m_gid != 0)
2492 (void) initgroups(DefUser, FileMailer->m_gid);
2493 else
2494 (void) initgroups(DefUser, DefGid);
813d8709 2495 }
6acfa498 2496 if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0)
4ae3ff58 2497 {
0c35b842 2498 if (ctladdr != NULL && ctladdr->q_uid != 0)
6acfa498 2499 (void) setuid(ctladdr->q_uid);
0c35b842
EA
2500 else if (FileMailer != NULL && FileMailer->m_uid != 0)
2501 (void) setuid(FileMailer->m_uid);
2502 else
2503 (void) setuid(DefUid);
4ae3ff58 2504 }
6acfa498
EA
2505 FileName = filename;
2506 LineNumber = 0;
6f7f4e2c 2507 f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode);
6acfa498 2508 if (f == NULL)
cbdb7357 2509 {
6814f197 2510 message("554 cannot open: %s", errstring(errno));
6acfa498 2511 exit(EX_CANTCREAT);
cbdb7357 2512 }
8dcff118 2513
23fafb99
EA
2514 bzero(&mcibuf, sizeof mcibuf);
2515 mcibuf.mci_mailer = FileMailer;
2516 mcibuf.mci_out = f;
2517 if (bitnset(M_7BITS, FileMailer->m_flags))
2518 mcibuf.mci_flags |= MCIF_7BIT;
2519
2520 putfromline(&mcibuf, e);
a579cea5
EA
2521 (*e->e_puthdr)(&mcibuf, e->e_header, e, 0);
2522 (*e->e_putbody)(&mcibuf, e, NULL, 0);
23fafb99 2523 putline("\n", &mcibuf);
6acfa498
EA
2524 if (ferror(f))
2525 {
6814f197 2526 message("451 I/O error: %s", errstring(errno));
6acfa498 2527 setstat(EX_IOERR);
8dcff118 2528 }
6acfa498
EA
2529 (void) xfclose(f, "mailfile", filename);
2530 (void) fflush(stdout);
3c7fe765 2531
6acfa498
EA
2532 /* reset ISUID & ISGID bits for paranoid systems */
2533 (void) chmod(filename, (int) stb.st_mode);
2534 exit(ExitStat);
2535 /*NOTREACHED*/
bc854e30 2536 }
6acfa498 2537 else
3c7fe765 2538 {
6acfa498
EA
2539 /* parent -- wait for exit status */
2540 int st;
bc854e30 2541
6acfa498 2542 st = waitfor(pid);
e3791bb6
EA
2543 if (WIFEXITED(st))
2544 return (WEXITSTATUS(st));
6acfa498 2545 else
6814f197
EA
2546 {
2547 syserr("child died on signal %d", st);
e3791bb6 2548 return (EX_UNAVAILABLE);
6814f197 2549 }
6acfa498 2550 /*NOTREACHED*/
3c7fe765
EA
2551 }
2552}
7e70d3c8
EA
2553\f/*
2554** HOSTSIGNATURE -- return the "signature" for a host.
2555**
2556** The signature describes how we are going to send this -- it
2557** can be just the hostname (for non-Internet hosts) or can be
2558** an ordered list of MX hosts.
2559**
2560** Parameters:
2561** m -- the mailer describing this host.
2562** host -- the host name.
2563** e -- the current envelope.
2564**
2565** Returns:
2566** The signature for this host.
2567**
2568** Side Effects:
2569** Can tweak the symbol table.
2570*/
2571
2572char *
2573hostsignature(m, host, e)
2574 register MAILER *m;
2575 char *host;
2576 ENVELOPE *e;
2577{
2578 register char *p;
2579 register STAB *s;
2580 int i;
2581 int len;
efe7f723 2582#if NAMED_BIND
7e70d3c8
EA
2583 int nmx;
2584 auto int rcode;
db113c28
EA
2585 char *hp;
2586 char *endp;
c8f4bc0b 2587 int oldoptions;
7e70d3c8 2588 char *mxhosts[MAXMXHOSTS + 1];
7e70d3c8
EA
2589#endif
2590
2591 /*
2592 ** Check to see if this uses IPC -- if not, it can't have MX records.
2593 */
2594
2595 p = m->m_mailer;
2596 if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0)
2597 {
2598 /* just an ordinary mailer */
2599 return host;
2600 }
2601
7e70d3c8
EA
2602 /*
2603 ** Look it up in the symbol table.
2604 */
2605
2606 s = stab(host, ST_HOSTSIG, ST_ENTER);
2607 if (s->s_hostsig != NULL)
2608 return s->s_hostsig;
2609
2610 /*
2611 ** Not already there -- create a signature.
2612 */
2613
efe7f723 2614#if NAMED_BIND
c8f4bc0b
EA
2615 if (ConfigLevel < 2)
2616 {
2617 oldoptions = _res.options;
2618 _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */
2619 }
2620
db113c28 2621 for (hp = host; hp != NULL; hp = endp)
7e70d3c8 2622 {
db113c28
EA
2623 endp = strchr(hp, ':');
2624 if (endp != NULL)
2625 *endp = '\0';
7e70d3c8 2626
c3577cd6 2627 nmx = getmxrr(hp, mxhosts, TRUE, &rcode);
7e70d3c8 2628
db113c28
EA
2629 if (nmx <= 0)
2630 {
2631 register MCI *mci;
7e70d3c8 2632
db113c28
EA
2633 /* update the connection info for this host */
2634 mci = mci_get(hp, m);
2635 mci->mci_exitstat = rcode;
2636 mci->mci_errno = errno;
efe7f723 2637#if NAMED_BIND
8e5c6745
EA
2638 mci->mci_herrno = h_errno;
2639#endif
db113c28
EA
2640
2641 /* and return the original host name as the signature */
2642 nmx = 1;
2643 mxhosts[0] = hp;
2644 }
2645
2646 len = 0;
2647 for (i = 0; i < nmx; i++)
2648 {
2649 len += strlen(mxhosts[i]) + 1;
2650 }
2651 if (s->s_hostsig != NULL)
2652 len += strlen(s->s_hostsig) + 1;
2653 p = xalloc(len);
2654 if (s->s_hostsig != NULL)
2655 {
2656 (void) strcpy(p, s->s_hostsig);
2657 free(s->s_hostsig);
2658 s->s_hostsig = p;
2659 p += strlen(p);
7e70d3c8 2660 *p++ = ':';
db113c28
EA
2661 }
2662 else
2663 s->s_hostsig = p;
2664 for (i = 0; i < nmx; i++)
2665 {
2666 if (i != 0)
2667 *p++ = ':';
2668 strcpy(p, mxhosts[i]);
2669 p += strlen(p);
2670 }
2671 if (endp != NULL)
2672 *endp++ = ':';
7e70d3c8
EA
2673 }
2674 makelower(s->s_hostsig);
c8f4bc0b
EA
2675 if (ConfigLevel < 2)
2676 _res.options = oldoptions;
7e70d3c8
EA
2677#else
2678 /* not using BIND -- the signature is just the host name */
2679 s->s_hostsig = host;
2680#endif
2681 if (tTd(17, 1))
2682 printf("hostsignature(%s) = %s\n", host, s->s_hostsig);
2683 return s->s_hostsig;
2684}
68d9129a
EA
2685\f/*
2686** SETSTATUS -- set the address status for return messages
2687**
2688** Parameters:
2689** a -- the address to set.
2690** msg -- the text of the message, which must be in standard
2691** SMTP form (3 digits, a space, and a message).
2692**
2693** Returns:
2694** none.
2695*/
2696
2697setstatus(a, msg)
2698 register ADDRESS *a;
2699 char *msg;
2700{
2701 char buf[MAXLINE];
2702
d51d925d
EA
2703 if (a->q_rstatus != NULL)
2704 free(a->q_rstatus);
68d9129a
EA
2705 if (strlen(msg) > 4)
2706 {
2707 register char *p, *q;
2708 int parenlev = 0;
2709
2710 strncpy(buf, msg, 4);
2711 p = &buf[4];
2712 *p++ = '(';
ad36a408 2713 for (q = &msg[4]; *q != '\0'; q++)
68d9129a
EA
2714 {
2715 switch (*q)
2716 {
2717 case '(':
2718 parenlev++;
2719 break;
2720
2721 case ')':
2722 if (parenlev > 0)
2723 parenlev--;
2724 else
2725 *p++ = '\\';
2726 break;
2727 }
2728 *p++ = *q;
2729 }
2730 while (parenlev-- >= 0)
2731 *p++ = ')';
2732 *p++ = '\0';
2733 msg = buf;
2734 }
d51d925d 2735 a->q_rstatus = newstr(msg);
68d9129a 2736}