|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Eric P. Allman ! 3: * Copyright (c) 1988 Regents of the University of California. ! 4: * All rights reserved. ! 5: * ! 6: * Redistribution and use in source and binary forms are permitted ! 7: * provided that the above copyright notice and this paragraph are ! 8: * duplicated in all such forms and that any documentation, ! 9: * advertising materials, and other materials related to such ! 10: * distribution and use acknowledge that the software was developed ! 11: * by the University of California, Berkeley. The name of the ! 12: * University may not be used to endorse or promote products derived ! 13: * from this software without specific prior written permission. ! 14: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 15: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 16: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 17: */ ! 18: ! 19: #ifndef lint ! 20: static char sccsid[] = "@(#)deliver.c 5.22 (Berkeley) 6/30/88"; ! 21: #endif /* not lint */ ! 22: ! 23: #include <sendmail.h> ! 24: #include <sys/signal.h> ! 25: #include <sys/stat.h> ! 26: #include <sys/ioctl.h> ! 27: #include <netdb.h> ! 28: #include <errno.h> ! 29: #include <arpa/nameser.h> ! 30: #include <resolv.h> ! 31: ! 32: /* ! 33: ** DELIVER -- Deliver a message to a list of addresses. ! 34: ** ! 35: ** This routine delivers to everyone on the same host as the ! 36: ** user on the head of the list. It is clever about mailers ! 37: ** that don't handle multiple users. It is NOT guaranteed ! 38: ** that it will deliver to all these addresses however -- so ! 39: ** deliver should be called once for each address on the ! 40: ** list. ! 41: ** ! 42: ** Parameters: ! 43: ** e -- the envelope to deliver. ! 44: ** firstto -- head of the address list to deliver to. ! 45: ** ! 46: ** Returns: ! 47: ** zero -- successfully delivered. ! 48: ** else -- some failure, see ExitStat for more info. ! 49: ** ! 50: ** Side Effects: ! 51: ** The standard input is passed off to someone. ! 52: */ ! 53: ! 54: deliver(e, firstto) ! 55: register ENVELOPE *e; ! 56: ADDRESS *firstto; ! 57: { ! 58: char *host; /* host being sent to */ ! 59: char *user; /* user being sent to */ ! 60: char **pvp; ! 61: register char **mvp; ! 62: register char *p; ! 63: register MAILER *m; /* mailer for this recipient */ ! 64: ADDRESS *ctladdr; ! 65: register ADDRESS *to = firstto; ! 66: bool clever = FALSE; /* running user smtp to this mailer */ ! 67: ADDRESS *tochain = NULL; /* chain of users in this mailer call */ ! 68: int rcode; /* response code */ ! 69: char *pv[MAXPV+1]; ! 70: char tobuf[MAXLINE-50]; /* text line of to people */ ! 71: char buf[MAXNAME]; ! 72: char tfrombuf[MAXNAME]; /* translated from person */ ! 73: extern bool checkcompat(); ! 74: extern ADDRESS *getctladdr(); ! 75: extern char *remotename(); ! 76: ! 77: errno = 0; ! 78: if (bitset(QDONTSEND, to->q_flags)) ! 79: return (0); ! 80: ! 81: /* unless interactive, try twice, over a minute */ ! 82: if (OpMode == MD_DAEMON || OpMode == MD_SMTP) { ! 83: _res.retrans = 30; ! 84: _res.retry = 2; ! 85: } ! 86: ! 87: m = to->q_mailer; ! 88: host = to->q_host; ! 89: ! 90: # ifdef DEBUG ! 91: if (tTd(10, 1)) ! 92: printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", ! 93: m->m_mno, host, to->q_user); ! 94: # endif DEBUG ! 95: ! 96: /* ! 97: ** If this mailer is expensive, and if we don't want to make ! 98: ** connections now, just mark these addresses and return. ! 99: ** This is useful if we want to batch connections to ! 100: ** reduce load. This will cause the messages to be ! 101: ** queued up, and a daemon will come along to send the ! 102: ** messages later. ! 103: ** This should be on a per-mailer basis. ! 104: */ ! 105: ! 106: if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) && ! 107: !Verbose) ! 108: { ! 109: for (; to != NULL; to = to->q_next) ! 110: { ! 111: if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m) ! 112: continue; ! 113: to->q_flags |= QQUEUEUP|QDONTSEND; ! 114: e->e_to = to->q_paddr; ! 115: message(Arpa_Info, "queued"); ! 116: if (LogLevel > 4) ! 117: logdelivery("queued"); ! 118: } ! 119: e->e_to = NULL; ! 120: return (0); ! 121: } ! 122: ! 123: /* ! 124: ** Do initial argv setup. ! 125: ** Insert the mailer name. Notice that $x expansion is ! 126: ** NOT done on the mailer name. Then, if the mailer has ! 127: ** a picky -f flag, we insert it as appropriate. This ! 128: ** code does not check for 'pv' overflow; this places a ! 129: ** manifest lower limit of 4 for MAXPV. ! 130: ** The from address rewrite is expected to make ! 131: ** the address relative to the other end. ! 132: */ ! 133: ! 134: /* rewrite from address, using rewriting rules */ ! 135: expand("\001f", buf, &buf[sizeof buf - 1], e); ! 136: (void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE)); ! 137: ! 138: define('g', tfrombuf, e); /* translated sender address */ ! 139: define('h', host, e); /* to host */ ! 140: Errors = 0; ! 141: pvp = pv; ! 142: *pvp++ = m->m_argv[0]; ! 143: ! 144: /* insert -f or -r flag as appropriate */ ! 145: if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) ! 146: { ! 147: if (bitnset(M_FOPT, m->m_flags)) ! 148: *pvp++ = "-f"; ! 149: else ! 150: *pvp++ = "-r"; ! 151: expand("\001g", buf, &buf[sizeof buf - 1], e); ! 152: *pvp++ = newstr(buf); ! 153: } ! 154: ! 155: /* ! 156: ** Append the other fixed parts of the argv. These run ! 157: ** up to the first entry containing "$u". There can only ! 158: ** be one of these, and there are only a few more slots ! 159: ** in the pv after it. ! 160: */ ! 161: ! 162: for (mvp = m->m_argv; (p = *++mvp) != NULL; ) ! 163: { ! 164: while ((p = index(p, '\001')) != NULL) ! 165: if (*++p == 'u') ! 166: break; ! 167: if (p != NULL) ! 168: break; ! 169: ! 170: /* this entry is safe -- go ahead and process it */ ! 171: expand(*mvp, buf, &buf[sizeof buf - 1], e); ! 172: *pvp++ = newstr(buf); ! 173: if (pvp >= &pv[MAXPV - 3]) ! 174: { ! 175: syserr("Too many parameters to %s before $u", pv[0]); ! 176: return (-1); ! 177: } ! 178: } ! 179: ! 180: /* ! 181: ** If we have no substitution for the user name in the argument ! 182: ** list, we know that we must supply the names otherwise -- and ! 183: ** SMTP is the answer!! ! 184: */ ! 185: ! 186: if (*mvp == NULL) ! 187: { ! 188: /* running SMTP */ ! 189: # ifdef SMTP ! 190: clever = TRUE; ! 191: *pvp = NULL; ! 192: # else SMTP ! 193: /* oops! we don't implement SMTP */ ! 194: syserr("SMTP style mailer"); ! 195: return (EX_SOFTWARE); ! 196: # endif SMTP ! 197: } ! 198: ! 199: /* ! 200: ** At this point *mvp points to the argument with $u. We ! 201: ** run through our address list and append all the addresses ! 202: ** we can. If we run out of space, do not fret! We can ! 203: ** always send another copy later. ! 204: */ ! 205: ! 206: tobuf[0] = '\0'; ! 207: e->e_to = tobuf; ! 208: ctladdr = NULL; ! 209: for (; to != NULL; to = to->q_next) ! 210: { ! 211: /* avoid sending multiple recipients to dumb mailers */ ! 212: if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) ! 213: break; ! 214: ! 215: /* if already sent or not for this host, don't send */ ! 216: if (bitset(QDONTSEND, to->q_flags) || ! 217: strcmp(to->q_host, host) != 0 || ! 218: to->q_mailer != firstto->q_mailer) ! 219: continue; ! 220: ! 221: /* avoid overflowing tobuf */ ! 222: if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0) ! 223: break; ! 224: ! 225: # ifdef DEBUG ! 226: if (tTd(10, 1)) ! 227: { ! 228: printf("\nsend to "); ! 229: printaddr(to, FALSE); ! 230: } ! 231: # endif DEBUG ! 232: ! 233: /* compute effective uid/gid when sending */ ! 234: if (to->q_mailer == ProgMailer) ! 235: ctladdr = getctladdr(to); ! 236: ! 237: user = to->q_user; ! 238: e->e_to = to->q_paddr; ! 239: to->q_flags |= QDONTSEND; ! 240: ! 241: /* ! 242: ** Check to see that these people are allowed to ! 243: ** talk to each other. ! 244: */ ! 245: ! 246: if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) ! 247: { ! 248: NoReturn = TRUE; ! 249: usrerr("Message is too large; %ld bytes max", m->m_maxsize); ! 250: giveresponse(EX_UNAVAILABLE, m, e); ! 251: continue; ! 252: } ! 253: if (!checkcompat(to)) ! 254: { ! 255: giveresponse(EX_UNAVAILABLE, m, e); ! 256: continue; ! 257: } ! 258: ! 259: /* ! 260: ** Strip quote bits from names if the mailer is dumb ! 261: ** about them. ! 262: */ ! 263: ! 264: if (bitnset(M_STRIPQ, m->m_flags)) ! 265: { ! 266: stripquotes(user, TRUE); ! 267: stripquotes(host, TRUE); ! 268: } ! 269: else ! 270: { ! 271: stripquotes(user, FALSE); ! 272: stripquotes(host, FALSE); ! 273: } ! 274: ! 275: /* hack attack -- delivermail compatibility */ ! 276: if (m == ProgMailer && *user == '|') ! 277: user++; ! 278: ! 279: /* ! 280: ** If an error message has already been given, don't ! 281: ** bother to send to this address. ! 282: ** ! 283: ** >>>>>>>>>> This clause assumes that the local mailer ! 284: ** >> NOTE >> cannot do any further aliasing; that ! 285: ** >>>>>>>>>> function is subsumed by sendmail. ! 286: */ ! 287: ! 288: if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) ! 289: continue; ! 290: ! 291: /* save statistics.... */ ! 292: markstats(e, to); ! 293: ! 294: /* ! 295: ** See if this user name is "special". ! 296: ** If the user name has a slash in it, assume that this ! 297: ** is a file -- send it off without further ado. Note ! 298: ** that this type of addresses is not processed along ! 299: ** with the others, so we fudge on the To person. ! 300: */ ! 301: ! 302: if (m == LocalMailer) ! 303: { ! 304: if (user[0] == '/') ! 305: { ! 306: rcode = mailfile(user, getctladdr(to)); ! 307: giveresponse(rcode, m, e); ! 308: continue; ! 309: } ! 310: } ! 311: ! 312: /* ! 313: ** Address is verified -- add this user to mailer ! 314: ** argv, and add it to the print list of recipients. ! 315: */ ! 316: ! 317: /* link together the chain of recipients */ ! 318: to->q_tchain = tochain; ! 319: tochain = to; ! 320: ! 321: /* create list of users for error messages */ ! 322: (void) strcat(tobuf, ","); ! 323: (void) strcat(tobuf, to->q_paddr); ! 324: define('u', user, e); /* to user */ ! 325: define('z', to->q_home, e); /* user's home */ ! 326: ! 327: /* ! 328: ** Expand out this user into argument list. ! 329: */ ! 330: ! 331: if (!clever) ! 332: { ! 333: expand(*mvp, buf, &buf[sizeof buf - 1], e); ! 334: *pvp++ = newstr(buf); ! 335: if (pvp >= &pv[MAXPV - 2]) ! 336: { ! 337: /* allow some space for trailing parms */ ! 338: break; ! 339: } ! 340: } ! 341: } ! 342: ! 343: /* see if any addresses still exist */ ! 344: if (tobuf[0] == '\0') ! 345: { ! 346: define('g', (char *) NULL, e); ! 347: return (0); ! 348: } ! 349: ! 350: /* print out messages as full list */ ! 351: e->e_to = tobuf + 1; ! 352: ! 353: /* ! 354: ** Fill out any parameters after the $u parameter. ! 355: */ ! 356: ! 357: while (!clever && *++mvp != NULL) ! 358: { ! 359: expand(*mvp, buf, &buf[sizeof buf - 1], e); ! 360: *pvp++ = newstr(buf); ! 361: if (pvp >= &pv[MAXPV]) ! 362: syserr("deliver: pv overflow after $u for %s", pv[0]); ! 363: } ! 364: *pvp++ = NULL; ! 365: ! 366: /* ! 367: ** Call the mailer. ! 368: ** The argument vector gets built, pipes ! 369: ** are created as necessary, and we fork & exec as ! 370: ** appropriate. ! 371: ** If we are running SMTP, we just need to clean up. ! 372: */ ! 373: ! 374: if (ctladdr == NULL) ! 375: ctladdr = &e->e_from; ! 376: _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ ! 377: #ifdef SMTP ! 378: if (clever) { ! 379: expand("\001w", buf, &buf[sizeof(buf) - 1], e); ! 380: rcode = EX_OK; ! 381: if (host[0] == '[') { ! 382: Nmx = 1; ! 383: MxHosts[0] = host; ! 384: } else ! 385: Nmx = getmxrr(host, MxHosts, buf, &rcode); ! 386: if (Nmx >= 0) { ! 387: message(Arpa_Info, "Connecting to %s (%s)...", ! 388: MxHosts[0], m->m_name); ! 389: if ((rcode = smtpinit(m, pv)) == EX_OK) { ! 390: /* send the recipient list */ ! 391: tobuf[0] = '\0'; ! 392: for (to = tochain; to; to = to->q_tchain) { ! 393: register int i; ! 394: register char *t = tobuf; ! 395: ! 396: e->e_to = to->q_paddr; ! 397: if ((i = smtprcpt(to, m)) != EX_OK) { ! 398: markfailure(e, to, i); ! 399: giveresponse(i, m, e); ! 400: } ! 401: else { ! 402: *t++ = ','; ! 403: for (p = to->q_paddr; *p; *t++ = *p++); ! 404: } ! 405: } ! 406: ! 407: /* now send the data */ ! 408: if (tobuf[0] == '\0') ! 409: e->e_to = NULL; ! 410: else { ! 411: e->e_to = tobuf + 1; ! 412: rcode = smtpdata(m, e); ! 413: } ! 414: ! 415: /* now close the connection */ ! 416: smtpquit(m); ! 417: } ! 418: } ! 419: } ! 420: else ! 421: #endif /* SMTP */ ! 422: { ! 423: message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name); ! 424: rcode = sendoff(e, m, pv, ctladdr); ! 425: } ! 426: _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ ! 427: ! 428: /* ! 429: ** Do final status disposal. ! 430: ** We check for something in tobuf for the SMTP case. ! 431: ** If we got a temporary failure, arrange to queue the ! 432: ** addressees. ! 433: */ ! 434: ! 435: if (tobuf[0] != '\0') ! 436: giveresponse(rcode, m, e); ! 437: if (rcode != EX_OK) ! 438: for (to = tochain; to != NULL; to = to->q_tchain) ! 439: markfailure(e, to, rcode); ! 440: ! 441: errno = 0; ! 442: define('g', (char *) NULL, e); ! 443: return (rcode); ! 444: } ! 445: /* ! 446: ** MARKFAILURE -- mark a failure on a specific address. ! 447: ** ! 448: ** Parameters: ! 449: ** e -- the envelope we are sending. ! 450: ** q -- the address to mark. ! 451: ** rcode -- the code signifying the particular failure. ! 452: ** ! 453: ** Returns: ! 454: ** none. ! 455: ** ! 456: ** Side Effects: ! 457: ** marks the address (and possibly the envelope) with the ! 458: ** failure so that an error will be returned or ! 459: ** the message will be queued, as appropriate. ! 460: */ ! 461: ! 462: markfailure(e, q, rcode) ! 463: register ENVELOPE *e; ! 464: register ADDRESS *q; ! 465: int rcode; ! 466: { ! 467: if (rcode == EX_OK) ! 468: return; ! 469: else if (rcode != EX_TEMPFAIL) ! 470: q->q_flags |= QBADADDR; ! 471: else if (curtime() > e->e_ctime + TimeOut) ! 472: { ! 473: extern char *pintvl(); ! 474: char buf[MAXLINE]; ! 475: ! 476: if (!bitset(EF_TIMEOUT, e->e_flags)) ! 477: { ! 478: (void) sprintf(buf, "Cannot send message for %s", ! 479: pintvl(TimeOut, FALSE)); ! 480: if (e->e_message != NULL) ! 481: free(e->e_message); ! 482: e->e_message = newstr(buf); ! 483: message(Arpa_Info, buf); ! 484: } ! 485: q->q_flags |= QBADADDR; ! 486: e->e_flags |= EF_TIMEOUT; ! 487: } ! 488: else ! 489: q->q_flags |= QQUEUEUP; ! 490: } ! 491: /* ! 492: ** DOFORK -- do a fork, retrying a couple of times on failure. ! 493: ** ! 494: ** This MUST be a macro, since after a vfork we are running ! 495: ** two processes on the same stack!!! ! 496: ** ! 497: ** Parameters: ! 498: ** none. ! 499: ** ! 500: ** Returns: ! 501: ** From a macro??? You've got to be kidding! ! 502: ** ! 503: ** Side Effects: ! 504: ** Modifies the ==> LOCAL <== variable 'pid', leaving: ! 505: ** pid of child in parent, zero in child. ! 506: ** -1 on unrecoverable error. ! 507: ** ! 508: ** Notes: ! 509: ** I'm awfully sorry this looks so awful. That's ! 510: ** vfork for you..... ! 511: */ ! 512: ! 513: # define NFORKTRIES 5 ! 514: # ifdef VMUNIX ! 515: # define XFORK vfork ! 516: # else VMUNIX ! 517: # define XFORK fork ! 518: # endif VMUNIX ! 519: ! 520: # define DOFORK(fORKfN) \ ! 521: {\ ! 522: register int i;\ ! 523: \ ! 524: for (i = NFORKTRIES; --i >= 0; )\ ! 525: {\ ! 526: pid = fORKfN();\ ! 527: if (pid >= 0)\ ! 528: break;\ ! 529: if (i > 0)\ ! 530: sleep((unsigned) NFORKTRIES - i);\ ! 531: }\ ! 532: } ! 533: /* ! 534: ** DOFORK -- simple fork interface to DOFORK. ! 535: ** ! 536: ** Parameters: ! 537: ** none. ! 538: ** ! 539: ** Returns: ! 540: ** pid of child in parent. ! 541: ** zero in child. ! 542: ** -1 on error. ! 543: ** ! 544: ** Side Effects: ! 545: ** returns twice, once in parent and once in child. ! 546: */ ! 547: ! 548: dofork() ! 549: { ! 550: register int pid; ! 551: ! 552: DOFORK(fork); ! 553: return (pid); ! 554: } ! 555: /* ! 556: ** SENDOFF -- send off call to mailer & collect response. ! 557: ** ! 558: ** Parameters: ! 559: ** e -- the envelope to mail. ! 560: ** m -- mailer descriptor. ! 561: ** pvp -- parameter vector to send to it. ! 562: ** ctladdr -- an address pointer controlling the ! 563: ** user/groupid etc. of the mailer. ! 564: ** ! 565: ** Returns: ! 566: ** exit status of mailer. ! 567: ** ! 568: ** Side Effects: ! 569: ** none. ! 570: */ ! 571: static ! 572: sendoff(e, m, pvp, ctladdr) ! 573: register ENVELOPE *e; ! 574: MAILER *m; ! 575: char **pvp; ! 576: ADDRESS *ctladdr; ! 577: { ! 578: auto FILE *mfile; ! 579: auto FILE *rfile; ! 580: register int i; ! 581: int pid; ! 582: ! 583: /* ! 584: ** Create connection to mailer. ! 585: */ ! 586: ! 587: pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile); ! 588: if (pid < 0) ! 589: return (-1); ! 590: ! 591: /* ! 592: ** Format and send message. ! 593: */ ! 594: ! 595: putfromline(mfile, m); ! 596: (*e->e_puthdr)(mfile, m, e); ! 597: putline("\n", mfile, m); ! 598: (*e->e_putbody)(mfile, m, e); ! 599: (void) fclose(mfile); ! 600: ! 601: i = endmailer(pid, pvp[0]); ! 602: ! 603: /* arrange a return receipt if requested */ ! 604: if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags)) ! 605: { ! 606: e->e_flags |= EF_SENDRECEIPT; ! 607: /* do we want to send back more info? */ ! 608: } ! 609: ! 610: return (i); ! 611: } ! 612: /* ! 613: ** ENDMAILER -- Wait for mailer to terminate. ! 614: ** ! 615: ** We should never get fatal errors (e.g., segmentation ! 616: ** violation), so we report those specially. For other ! 617: ** errors, we choose a status message (into statmsg), ! 618: ** and if it represents an error, we print it. ! 619: ** ! 620: ** Parameters: ! 621: ** pid -- pid of mailer. ! 622: ** name -- name of mailer (for error messages). ! 623: ** ! 624: ** Returns: ! 625: ** exit code of mailer. ! 626: ** ! 627: ** Side Effects: ! 628: ** none. ! 629: */ ! 630: ! 631: endmailer(pid, name) ! 632: int pid; ! 633: char *name; ! 634: { ! 635: int st; ! 636: ! 637: /* in the IPC case there is nothing to wait for */ ! 638: if (pid == 0) ! 639: return (EX_OK); ! 640: ! 641: /* wait for the mailer process to die and collect status */ ! 642: st = waitfor(pid); ! 643: if (st == -1) ! 644: { ! 645: syserr("endmailer %s: wait", name); ! 646: return (EX_SOFTWARE); ! 647: } ! 648: ! 649: /* see if it died a horrid death */ ! 650: if ((st & 0377) != 0) ! 651: { ! 652: syserr("mailer %s died with signal %o", name, st); ! 653: ExitStat = EX_TEMPFAIL; ! 654: return (EX_TEMPFAIL); ! 655: } ! 656: ! 657: /* normal death -- return status */ ! 658: st = (st >> 8) & 0377; ! 659: return (st); ! 660: } ! 661: /* ! 662: ** OPENMAILER -- open connection to mailer. ! 663: ** ! 664: ** Parameters: ! 665: ** m -- mailer descriptor. ! 666: ** pvp -- parameter vector to pass to mailer. ! 667: ** ctladdr -- controlling address for user. ! 668: ** clever -- create a full duplex connection. ! 669: ** pmfile -- pointer to mfile (to mailer) connection. ! 670: ** prfile -- pointer to rfile (from mailer) connection. ! 671: ** ! 672: ** Returns: ! 673: ** pid of mailer ( > 0 ). ! 674: ** -1 on error. ! 675: ** zero on an IPC connection. ! 676: ** ! 677: ** Side Effects: ! 678: ** creates a mailer in a subprocess. ! 679: */ ! 680: ! 681: openmailer(m, pvp, ctladdr, clever, pmfile, prfile) ! 682: MAILER *m; ! 683: char **pvp; ! 684: ADDRESS *ctladdr; ! 685: bool clever; ! 686: FILE **pmfile; ! 687: FILE **prfile; ! 688: { ! 689: int pid; ! 690: int mpvect[2]; ! 691: int rpvect[2]; ! 692: FILE *mfile; ! 693: FILE *rfile; ! 694: extern FILE *fdopen(); ! 695: ! 696: # ifdef DEBUG ! 697: if (tTd(11, 1)) ! 698: { ! 699: printf("openmailer:"); ! 700: printav(pvp); ! 701: } ! 702: # endif DEBUG ! 703: errno = 0; ! 704: ! 705: CurHostName = m->m_mailer; ! 706: ! 707: /* ! 708: ** Deal with the special case of mail handled through an IPC ! 709: ** connection. ! 710: ** In this case we don't actually fork. We must be ! 711: ** running SMTP for this to work. We will return a ! 712: ** zero pid to indicate that we are running IPC. ! 713: ** We also handle a debug version that just talks to stdin/out. ! 714: */ ! 715: ! 716: #ifdef DEBUG ! 717: /* check for Local Person Communication -- not for mortals!!! */ ! 718: if (strcmp(m->m_mailer, "[LPC]") == 0) ! 719: { ! 720: *pmfile = stdout; ! 721: *prfile = stdin; ! 722: return (0); ! 723: } ! 724: #endif DEBUG ! 725: ! 726: if (strcmp(m->m_mailer, "[IPC]") == 0) ! 727: { ! 728: #ifdef HOSTINFO ! 729: register STAB *st; ! 730: extern STAB *stab(); ! 731: #endif HOSTINFO ! 732: #ifdef DAEMON ! 733: register int i, j; ! 734: register u_short port; ! 735: ! 736: CurHostName = pvp[1]; ! 737: if (!clever) ! 738: syserr("non-clever IPC"); ! 739: if (pvp[2] != NULL) ! 740: port = atoi(pvp[2]); ! 741: else ! 742: port = 0; ! 743: for (j = 0; j < Nmx; j++) ! 744: { ! 745: CurHostName = MxHosts[j]; ! 746: #ifdef HOSTINFO ! 747: /* see if we have already determined that this host is fried */ ! 748: st = stab(MxHosts[j], ST_HOST, ST_FIND); ! 749: if (st == NULL || st->s_host.ho_exitstat == EX_OK) { ! 750: if (j > 1) ! 751: message(Arpa_Info, ! 752: "Connecting to %s (%s)...", ! 753: MxHosts[j], m->m_name); ! 754: i = makeconnection(MxHosts[j], port, pmfile, prfile); ! 755: } ! 756: else ! 757: { ! 758: i = st->s_host.ho_exitstat; ! 759: errno = st->s_host.ho_errno; ! 760: } ! 761: #else HOSTINFO ! 762: i = makeconnection(MxHosts[j], port, pmfile, prfile); ! 763: #endif HOSTINFO ! 764: if (i != EX_OK) ! 765: { ! 766: #ifdef HOSTINFO ! 767: /* enter status of this host */ ! 768: if (st == NULL) ! 769: st = stab(MxHosts[j], ST_HOST, ST_ENTER); ! 770: st->s_host.ho_exitstat = i; ! 771: st->s_host.ho_errno = errno; ! 772: #endif HOSTINFO ! 773: ExitStat = i; ! 774: continue; ! 775: } ! 776: else ! 777: return (0); ! 778: } ! 779: return (-1); ! 780: #else DAEMON ! 781: syserr("openmailer: no IPC"); ! 782: return (-1); ! 783: #endif DAEMON ! 784: } ! 785: ! 786: /* create a pipe to shove the mail through */ ! 787: if (pipe(mpvect) < 0) ! 788: { ! 789: syserr("openmailer: pipe (to mailer)"); ! 790: return (-1); ! 791: } ! 792: ! 793: #ifdef SMTP ! 794: /* if this mailer speaks smtp, create a return pipe */ ! 795: if (clever && pipe(rpvect) < 0) ! 796: { ! 797: syserr("openmailer: pipe (from mailer)"); ! 798: (void) close(mpvect[0]); ! 799: (void) close(mpvect[1]); ! 800: return (-1); ! 801: } ! 802: #endif SMTP ! 803: ! 804: /* ! 805: ** Actually fork the mailer process. ! 806: ** DOFORK is clever about retrying. ! 807: ** ! 808: ** Dispose of SIGCHLD signal catchers that may be laying ! 809: ** around so that endmail will get it. ! 810: */ ! 811: ! 812: if (CurEnv->e_xfp != NULL) ! 813: (void) fflush(CurEnv->e_xfp); /* for debugging */ ! 814: (void) fflush(stdout); ! 815: # ifdef SIGCHLD ! 816: (void) signal(SIGCHLD, SIG_DFL); ! 817: # endif SIGCHLD ! 818: DOFORK(XFORK); ! 819: /* pid is set by DOFORK */ ! 820: if (pid < 0) ! 821: { ! 822: /* failure */ ! 823: syserr("openmailer: cannot fork"); ! 824: (void) close(mpvect[0]); ! 825: (void) close(mpvect[1]); ! 826: #ifdef SMTP ! 827: if (clever) ! 828: { ! 829: (void) close(rpvect[0]); ! 830: (void) close(rpvect[1]); ! 831: } ! 832: #endif SMTP ! 833: return (-1); ! 834: } ! 835: else if (pid == 0) ! 836: { ! 837: int i; ! 838: extern int DtableSize; ! 839: ! 840: /* child -- set up input & exec mailer */ ! 841: /* make diagnostic output be standard output */ ! 842: (void) signal(SIGINT, SIG_IGN); ! 843: (void) signal(SIGHUP, SIG_IGN); ! 844: (void) signal(SIGTERM, SIG_DFL); ! 845: ! 846: /* arrange to filter standard & diag output of command */ ! 847: if (clever) ! 848: { ! 849: (void) close(rpvect[0]); ! 850: (void) close(1); ! 851: (void) dup(rpvect[1]); ! 852: (void) close(rpvect[1]); ! 853: } ! 854: else if (OpMode == MD_SMTP || HoldErrs) ! 855: { ! 856: /* put mailer output in transcript */ ! 857: (void) close(1); ! 858: (void) dup(fileno(CurEnv->e_xfp)); ! 859: } ! 860: (void) close(2); ! 861: (void) dup(1); ! 862: ! 863: /* arrange to get standard input */ ! 864: (void) close(mpvect[1]); ! 865: (void) close(0); ! 866: if (dup(mpvect[0]) < 0) ! 867: { ! 868: syserr("Cannot dup to zero!"); ! 869: _exit(EX_OSERR); ! 870: } ! 871: (void) close(mpvect[0]); ! 872: if (!bitnset(M_RESTR, m->m_flags)) ! 873: { ! 874: if (ctladdr == NULL || ctladdr->q_uid == 0) ! 875: { ! 876: (void) setgid(DefGid); ! 877: (void) setuid(DefUid); ! 878: } ! 879: else ! 880: { ! 881: (void) setgid(ctladdr->q_gid); ! 882: (void) setuid(ctladdr->q_uid); ! 883: } ! 884: } ! 885: ! 886: /* arrange for all the files to be closed */ ! 887: for (i = 3; i < DtableSize; i++) ! 888: (void) ioctl(i, FIOCLEX, 0); ! 889: ! 890: /* try to execute the mailer */ ! 891: execve(m->m_mailer, pvp, UserEnviron); ! 892: syserr("Cannot exec %s", m->m_mailer); ! 893: if (m == LocalMailer || errno == EIO || errno == EAGAIN || ! 894: errno == ENOMEM || errno == EPROCLIM) ! 895: _exit(EX_TEMPFAIL); ! 896: else ! 897: _exit(EX_UNAVAILABLE); ! 898: } ! 899: ! 900: /* ! 901: ** Set up return value. ! 902: */ ! 903: ! 904: (void) close(mpvect[0]); ! 905: mfile = fdopen(mpvect[1], "w"); ! 906: if (clever) ! 907: { ! 908: (void) close(rpvect[1]); ! 909: rfile = fdopen(rpvect[0], "r"); ! 910: } ! 911: ! 912: *pmfile = mfile; ! 913: *prfile = rfile; ! 914: ! 915: return (pid); ! 916: } ! 917: /* ! 918: ** GIVERESPONSE -- Interpret an error response from a mailer ! 919: ** ! 920: ** Parameters: ! 921: ** stat -- the status code from the mailer (high byte ! 922: ** only; core dumps must have been taken care of ! 923: ** already). ! 924: ** m -- the mailer descriptor for this mailer. ! 925: ** ! 926: ** Returns: ! 927: ** none. ! 928: ** ! 929: ** Side Effects: ! 930: ** Errors may be incremented. ! 931: ** ExitStat may be set. ! 932: */ ! 933: ! 934: giveresponse(stat, m, e) ! 935: int stat; ! 936: register MAILER *m; ! 937: ENVELOPE *e; ! 938: { ! 939: register char *statmsg; ! 940: extern char *SysExMsg[]; ! 941: register int i; ! 942: extern int N_SysEx, h_errno; ! 943: char buf[MAXLINE]; ! 944: ! 945: #ifdef lint ! 946: if (m == NULL) ! 947: return; ! 948: #endif lint ! 949: ! 950: /* ! 951: ** Compute status message from code. ! 952: */ ! 953: ! 954: i = stat - EX__BASE; ! 955: if (stat == 0) ! 956: statmsg = "250 Sent"; ! 957: else if (i < 0 || i > N_SysEx) ! 958: { ! 959: (void) sprintf(buf, "554 unknown mailer error %d", stat); ! 960: stat = EX_UNAVAILABLE; ! 961: statmsg = buf; ! 962: } ! 963: else if (stat == EX_TEMPFAIL) ! 964: { ! 965: (void) strcpy(buf, SysExMsg[i]); ! 966: if (h_errno == TRY_AGAIN) ! 967: { ! 968: extern char *errstring(); ! 969: ! 970: statmsg = errstring(h_errno+MAX_ERRNO); ! 971: } ! 972: else ! 973: { ! 974: if (errno != 0) ! 975: { ! 976: extern char *errstring(); ! 977: ! 978: statmsg = errstring(errno); ! 979: } ! 980: else ! 981: { ! 982: #ifdef SMTP ! 983: extern char SmtpError[]; ! 984: ! 985: statmsg = SmtpError; ! 986: #else SMTP ! 987: statmsg = NULL; ! 988: #endif SMTP ! 989: } ! 990: } ! 991: if (statmsg != NULL && statmsg[0] != '\0') ! 992: { ! 993: (void) strcat(buf, ": "); ! 994: (void) strcat(buf, statmsg); ! 995: } ! 996: statmsg = buf; ! 997: } ! 998: else ! 999: { ! 1000: statmsg = SysExMsg[i]; ! 1001: } ! 1002: ! 1003: /* ! 1004: ** Print the message as appropriate ! 1005: */ ! 1006: ! 1007: if (stat == EX_OK || stat == EX_TEMPFAIL) ! 1008: message(Arpa_Info, &statmsg[4]); ! 1009: else ! 1010: { ! 1011: Errors++; ! 1012: usrerr(statmsg); ! 1013: } ! 1014: ! 1015: /* ! 1016: ** Final cleanup. ! 1017: ** Log a record of the transaction. Compute the new ! 1018: ** ExitStat -- if we already had an error, stick with ! 1019: ** that. ! 1020: */ ! 1021: ! 1022: if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2)) ! 1023: logdelivery(&statmsg[4]); ! 1024: ! 1025: if (stat != EX_TEMPFAIL) ! 1026: setstat(stat); ! 1027: if (stat != EX_OK) ! 1028: { ! 1029: if (e->e_message != NULL) ! 1030: free(e->e_message); ! 1031: e->e_message = newstr(&statmsg[4]); ! 1032: } ! 1033: errno = 0; ! 1034: h_errno = 0; ! 1035: } ! 1036: /* ! 1037: ** LOGDELIVERY -- log the delivery in the system log ! 1038: ** ! 1039: ** Parameters: ! 1040: ** stat -- the message to print for the status ! 1041: ** ! 1042: ** Returns: ! 1043: ** none ! 1044: ** ! 1045: ** Side Effects: ! 1046: ** none ! 1047: */ ! 1048: ! 1049: logdelivery(stat) ! 1050: char *stat; ! 1051: { ! 1052: extern char *pintvl(); ! 1053: ! 1054: # ifdef LOG ! 1055: syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id, ! 1056: CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat); ! 1057: # endif LOG ! 1058: } ! 1059: /* ! 1060: ** PUTFROMLINE -- output a UNIX-style from line (or whatever) ! 1061: ** ! 1062: ** This can be made an arbitrary message separator by changing $l ! 1063: ** ! 1064: ** One of the ugliest hacks seen by human eyes is contained herein: ! 1065: ** UUCP wants those stupid "remote from <host>" lines. Why oh why ! 1066: ** does a well-meaning programmer such as myself have to deal with ! 1067: ** this kind of antique garbage???? ! 1068: ** ! 1069: ** Parameters: ! 1070: ** fp -- the file to output to. ! 1071: ** m -- the mailer describing this entry. ! 1072: ** ! 1073: ** Returns: ! 1074: ** none ! 1075: ** ! 1076: ** Side Effects: ! 1077: ** outputs some text to fp. ! 1078: */ ! 1079: ! 1080: putfromline(fp, m) ! 1081: register FILE *fp; ! 1082: register MAILER *m; ! 1083: { ! 1084: char *template = "\001l\n"; ! 1085: char buf[MAXLINE]; ! 1086: ! 1087: if (bitnset(M_NHDR, m->m_flags)) ! 1088: return; ! 1089: ! 1090: # ifdef UGLYUUCP ! 1091: if (bitnset(M_UGLYUUCP, m->m_flags)) ! 1092: { ! 1093: char *bang; ! 1094: char xbuf[MAXLINE]; ! 1095: ! 1096: expand("\001g", buf, &buf[sizeof buf - 1], CurEnv); ! 1097: bang = index(buf, '!'); ! 1098: if (bang == NULL) ! 1099: syserr("No ! in UUCP! (%s)", buf); ! 1100: else ! 1101: { ! 1102: *bang++ = '\0'; ! 1103: (void) sprintf(xbuf, "From %s \001d remote from %s\n", bang, buf); ! 1104: template = xbuf; ! 1105: } ! 1106: } ! 1107: # endif UGLYUUCP ! 1108: expand(template, buf, &buf[sizeof buf - 1], CurEnv); ! 1109: putline(buf, fp, m); ! 1110: } ! 1111: /* ! 1112: ** PUTBODY -- put the body of a message. ! 1113: ** ! 1114: ** Parameters: ! 1115: ** fp -- file to output onto. ! 1116: ** m -- a mailer descriptor to control output format. ! 1117: ** e -- the envelope to put out. ! 1118: ** ! 1119: ** Returns: ! 1120: ** none. ! 1121: ** ! 1122: ** Side Effects: ! 1123: ** The message is written onto fp. ! 1124: */ ! 1125: ! 1126: putbody(fp, m, e) ! 1127: FILE *fp; ! 1128: MAILER *m; ! 1129: register ENVELOPE *e; ! 1130: { ! 1131: char buf[MAXLINE]; ! 1132: ! 1133: /* ! 1134: ** Output the body of the message ! 1135: */ ! 1136: ! 1137: if (e->e_dfp == NULL) ! 1138: { ! 1139: if (e->e_df != NULL) ! 1140: { ! 1141: e->e_dfp = fopen(e->e_df, "r"); ! 1142: if (e->e_dfp == NULL) ! 1143: syserr("Cannot open %s", e->e_df); ! 1144: } ! 1145: else ! 1146: putline("<<< No Message Collected >>>", fp, m); ! 1147: } ! 1148: if (e->e_dfp != NULL) ! 1149: { ! 1150: rewind(e->e_dfp); ! 1151: while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) ! 1152: { ! 1153: if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && ! 1154: strncmp(buf, "From", 4) == 0) ! 1155: (void) putc('>', fp); ! 1156: putline(buf, fp, m); ! 1157: } ! 1158: ! 1159: if (ferror(e->e_dfp)) ! 1160: { ! 1161: syserr("putbody: read error"); ! 1162: ExitStat = EX_IOERR; ! 1163: } ! 1164: } ! 1165: ! 1166: (void) fflush(fp); ! 1167: if (ferror(fp) && errno != EPIPE) ! 1168: { ! 1169: syserr("putbody: write error"); ! 1170: ExitStat = EX_IOERR; ! 1171: } ! 1172: errno = 0; ! 1173: } ! 1174: /* ! 1175: ** MAILFILE -- Send a message to a file. ! 1176: ** ! 1177: ** If the file has the setuid/setgid bits set, but NO execute ! 1178: ** bits, sendmail will try to become the owner of that file ! 1179: ** rather than the real user. Obviously, this only works if ! 1180: ** sendmail runs as root. ! 1181: ** ! 1182: ** This could be done as a subordinate mailer, except that it ! 1183: ** is used implicitly to save messages in ~/dead.letter. We ! 1184: ** view this as being sufficiently important as to include it ! 1185: ** here. For example, if the system is dying, we shouldn't have ! 1186: ** to create another process plus some pipes to save the message. ! 1187: ** ! 1188: ** Parameters: ! 1189: ** filename -- the name of the file to send to. ! 1190: ** ctladdr -- the controlling address header -- includes ! 1191: ** the userid/groupid to be when sending. ! 1192: ** ! 1193: ** Returns: ! 1194: ** The exit code associated with the operation. ! 1195: ** ! 1196: ** Side Effects: ! 1197: ** none. ! 1198: */ ! 1199: ! 1200: mailfile(filename, ctladdr) ! 1201: char *filename; ! 1202: ADDRESS *ctladdr; ! 1203: { ! 1204: register FILE *f; ! 1205: register int pid; ! 1206: ! 1207: /* ! 1208: ** Fork so we can change permissions here. ! 1209: ** Note that we MUST use fork, not vfork, because of ! 1210: ** the complications of calling subroutines, etc. ! 1211: */ ! 1212: ! 1213: DOFORK(fork); ! 1214: ! 1215: if (pid < 0) ! 1216: return (EX_OSERR); ! 1217: else if (pid == 0) ! 1218: { ! 1219: /* child -- actually write to file */ ! 1220: struct stat stb; ! 1221: ! 1222: (void) signal(SIGINT, SIG_DFL); ! 1223: (void) signal(SIGHUP, SIG_DFL); ! 1224: (void) signal(SIGTERM, SIG_DFL); ! 1225: (void) umask(OldUmask); ! 1226: if (stat(filename, &stb) < 0) ! 1227: { ! 1228: errno = 0; ! 1229: stb.st_mode = 0666; ! 1230: } ! 1231: if (bitset(0111, stb.st_mode)) ! 1232: exit(EX_CANTCREAT); ! 1233: if (ctladdr == NULL) ! 1234: ctladdr = &CurEnv->e_from; ! 1235: if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0) ! 1236: { ! 1237: if (ctladdr->q_uid == 0) ! 1238: (void) setgid(DefGid); ! 1239: else ! 1240: (void) setgid(ctladdr->q_gid); ! 1241: } ! 1242: if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0) ! 1243: { ! 1244: if (ctladdr->q_uid == 0) ! 1245: (void) setuid(DefUid); ! 1246: else ! 1247: (void) setuid(ctladdr->q_uid); ! 1248: } ! 1249: f = dfopen(filename, "a"); ! 1250: if (f == NULL) ! 1251: exit(EX_CANTCREAT); ! 1252: ! 1253: putfromline(f, ProgMailer); ! 1254: (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv); ! 1255: putline("\n", f, ProgMailer); ! 1256: (*CurEnv->e_putbody)(f, ProgMailer, CurEnv); ! 1257: putline("\n", f, ProgMailer); ! 1258: (void) fclose(f); ! 1259: (void) fflush(stdout); ! 1260: ! 1261: /* reset ISUID & ISGID bits for paranoid systems */ ! 1262: (void) chmod(filename, (int) stb.st_mode); ! 1263: exit(EX_OK); ! 1264: /*NOTREACHED*/ ! 1265: } ! 1266: else ! 1267: { ! 1268: /* parent -- wait for exit status */ ! 1269: int st; ! 1270: ! 1271: st = waitfor(pid); ! 1272: if ((st & 0377) != 0) ! 1273: return (EX_UNAVAILABLE); ! 1274: else ! 1275: return ((st >> 8) & 0377); ! 1276: } ! 1277: } ! 1278: /* ! 1279: ** SENDALL -- actually send all the messages. ! 1280: ** ! 1281: ** Parameters: ! 1282: ** e -- the envelope to send. ! 1283: ** mode -- the delivery mode to use. If SM_DEFAULT, use ! 1284: ** the current SendMode. ! 1285: ** ! 1286: ** Returns: ! 1287: ** none. ! 1288: ** ! 1289: ** Side Effects: ! 1290: ** Scans the send lists and sends everything it finds. ! 1291: ** Delivers any appropriate error messages. ! 1292: ** If we are running in a non-interactive mode, takes the ! 1293: ** appropriate action. ! 1294: */ ! 1295: ! 1296: sendall(e, mode) ! 1297: ENVELOPE *e; ! 1298: char mode; ! 1299: { ! 1300: register ADDRESS *q; ! 1301: bool oldverbose; ! 1302: int pid; ! 1303: ! 1304: /* determine actual delivery mode */ ! 1305: if (mode == SM_DEFAULT) ! 1306: { ! 1307: extern bool shouldqueue(); ! 1308: ! 1309: if (shouldqueue(e->e_msgpriority)) ! 1310: mode = SM_QUEUE; ! 1311: else ! 1312: mode = SendMode; ! 1313: } ! 1314: ! 1315: #ifdef DEBUG ! 1316: if (tTd(13, 1)) ! 1317: { ! 1318: printf("\nSENDALL: mode %c, sendqueue:\n", mode); ! 1319: printaddr(e->e_sendqueue, TRUE); ! 1320: } ! 1321: #endif DEBUG ! 1322: ! 1323: /* ! 1324: ** Do any preprocessing necessary for the mode we are running. ! 1325: ** Check to make sure the hop count is reasonable. ! 1326: ** Delete sends to the sender in mailing lists. ! 1327: */ ! 1328: ! 1329: CurEnv = e; ! 1330: ! 1331: if (e->e_hopcount > MAXHOP) ! 1332: { ! 1333: syserr("sendall: too many hops (%d max)", MAXHOP); ! 1334: return; ! 1335: } ! 1336: ! 1337: if (!MeToo) ! 1338: { ! 1339: extern ADDRESS *recipient(); ! 1340: ! 1341: e->e_from.q_flags |= QDONTSEND; ! 1342: (void) recipient(&e->e_from, &e->e_sendqueue); ! 1343: } ! 1344: ! 1345: # ifdef QUEUE ! 1346: if ((mode == SM_QUEUE || mode == SM_FORK || ! 1347: (mode != SM_VERIFY && SuperSafe)) && ! 1348: !bitset(EF_INQUEUE, e->e_flags)) ! 1349: queueup(e, TRUE, mode == SM_QUEUE); ! 1350: #endif QUEUE ! 1351: ! 1352: oldverbose = Verbose; ! 1353: switch (mode) ! 1354: { ! 1355: case SM_VERIFY: ! 1356: Verbose = TRUE; ! 1357: break; ! 1358: ! 1359: case SM_QUEUE: ! 1360: e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; ! 1361: return; ! 1362: ! 1363: case SM_FORK: ! 1364: if (e->e_xfp != NULL) ! 1365: (void) fflush(e->e_xfp); ! 1366: pid = fork(); ! 1367: if (pid < 0) ! 1368: { ! 1369: mode = SM_DELIVER; ! 1370: break; ! 1371: } ! 1372: else if (pid > 0) ! 1373: { ! 1374: /* be sure we leave the temp files to our child */ ! 1375: e->e_id = e->e_df = NULL; ! 1376: return; ! 1377: } ! 1378: ! 1379: /* double fork to avoid zombies */ ! 1380: if (fork() > 0) ! 1381: exit(EX_OK); ! 1382: ! 1383: /* be sure we are immune from the terminal */ ! 1384: disconnect(FALSE); ! 1385: ! 1386: break; ! 1387: } ! 1388: ! 1389: /* ! 1390: ** Run through the list and send everything. ! 1391: */ ! 1392: ! 1393: for (q = e->e_sendqueue; q != NULL; q = q->q_next) ! 1394: { ! 1395: if (mode == SM_VERIFY) ! 1396: { ! 1397: e->e_to = q->q_paddr; ! 1398: if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) ! 1399: message(Arpa_Info, "deliverable"); ! 1400: } ! 1401: else ! 1402: (void) deliver(e, q); ! 1403: } ! 1404: Verbose = oldverbose; ! 1405: ! 1406: /* ! 1407: ** Now run through and check for errors. ! 1408: */ ! 1409: ! 1410: if (mode == SM_VERIFY) ! 1411: return; ! 1412: ! 1413: for (q = e->e_sendqueue; q != NULL; q = q->q_next) ! 1414: { ! 1415: register ADDRESS *qq; ! 1416: ! 1417: # ifdef DEBUG ! 1418: if (tTd(13, 3)) ! 1419: { ! 1420: printf("Checking "); ! 1421: printaddr(q, FALSE); ! 1422: } ! 1423: # endif DEBUG ! 1424: ! 1425: /* only send errors if the message failed */ ! 1426: if (!bitset(QBADADDR, q->q_flags)) ! 1427: continue; ! 1428: ! 1429: /* we have an address that failed -- find the parent */ ! 1430: for (qq = q; qq != NULL; qq = qq->q_alias) ! 1431: { ! 1432: char obuf[MAXNAME + 6]; ! 1433: extern char *aliaslookup(); ! 1434: ! 1435: /* we can only have owners for local addresses */ ! 1436: if (!bitnset(M_LOCAL, qq->q_mailer->m_flags)) ! 1437: continue; ! 1438: ! 1439: /* see if the owner list exists */ ! 1440: (void) strcpy(obuf, "owner-"); ! 1441: if (strncmp(qq->q_user, "owner-", 6) == 0) ! 1442: (void) strcat(obuf, "owner"); ! 1443: else ! 1444: (void) strcat(obuf, qq->q_user); ! 1445: if (aliaslookup(obuf) == NULL) ! 1446: continue; ! 1447: ! 1448: # ifdef DEBUG ! 1449: if (tTd(13, 4)) ! 1450: printf("Errors to %s\n", obuf); ! 1451: # endif DEBUG ! 1452: ! 1453: /* owner list exists -- add it to the error queue */ ! 1454: sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue); ! 1455: ErrorMode = EM_MAIL; ! 1456: break; ! 1457: } ! 1458: ! 1459: /* if we did not find an owner, send to the sender */ ! 1460: if (qq == NULL && bitset(QBADADDR, q->q_flags)) ! 1461: sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue); ! 1462: } ! 1463: ! 1464: if (mode == SM_FORK) ! 1465: finis(); ! 1466: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.