X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/ed554bc5e4201344d7eaad78263566e79428759c..fd88f5c5678c80ff5e338adc372d28a52ad20530:/usr/src/usr.sbin/sendmail/src/deliver.c diff --git a/usr/src/usr.sbin/sendmail/src/deliver.c b/usr/src/usr.sbin/sendmail/src/deliver.c index 42661221e5..88286d0281 100644 --- a/usr/src/usr.sbin/sendmail/src/deliver.c +++ b/usr/src/usr.sbin/sendmail/src/deliver.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,14 +33,12 @@ */ #ifndef lint -static char sccsid[] = "@(#)deliver.c 8.82 (Berkeley) 4/18/94"; +static char sccsid[] = "@(#)deliver.c 8.160 (Berkeley) 6/21/95"; #endif /* not lint */ #include "sendmail.h" -#include #include #if NAMED_BIND -#include #include extern int h_errno; @@ -66,6 +64,7 @@ extern char SmtpError[]; ** appropriate action. */ +void sendall(e, mode) ENVELOPE *e; char mode; @@ -75,7 +74,10 @@ sendall(e, mode) int otherowners; register ENVELOPE *ee; ENVELOPE *splitenv = NULL; - bool announcequeueup; + bool oldverbose = Verbose; + bool somedeliveries = FALSE; + int pid; + extern void sendenvelope(); /* ** If we have had global, fatal errors, don't bother sending @@ -99,16 +101,17 @@ sendall(e, mode) if (mode != SM_VERIFY && shouldqueue(e->e_msgpriority, e->e_ctime)) mode = SM_QUEUE; - announcequeueup = mode == SM_QUEUE; } - else - announcequeueup = FALSE; if (tTd(13, 1)) { + extern void printenvflags(); + printf("\n===== SENDALL: mode %c, id %s, e_from ", mode, e->e_id); printaddr(&e->e_from, FALSE); + printf("\te_flags = "); + printenvflags(e); printf("sendqueue:\n"); printaddr(e->e_sendqueue, TRUE); } @@ -124,11 +127,13 @@ sendall(e, mode) if (e->e_hopcount > MaxHopCount) { errno = 0; + queueup(e, TRUE, mode == SM_QUEUE); e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE; - syserr("554 too many hops %d (%d max): from %s via %s, to %s", + syserr("554 Too many hops %d (%d max): from %s via %s, to %s", e->e_hopcount, MaxHopCount, e->e_from.q_paddr, RealHostName == NULL ? "localhost" : RealHostName, e->e_sendqueue->q_paddr); + e->e_sendqueue->q_status = "5.4.6"; return; } @@ -150,7 +155,7 @@ sendall(e, mode) printaddr(&e->e_from, FALSE); } e->e_from.q_flags |= QDONTSEND; - (void) recipient(&e->e_from, &e->e_sendqueue, e); + (void) recipient(&e->e_from, &e->e_sendqueue, 0, e); } /* @@ -209,6 +214,34 @@ sendall(e, mode) { otherowners++; } + + /* + ** If this mailer is expensive, and if we don't + ** want to make connections now, just mark these + ** addresses and return. This is useful if we + ** want to batch connections to reduce load. This + ** will cause the messages to be queued up, and a + ** daemon will come along to send the messages later. + */ + + if (bitset(QBADADDR|QQUEUEUP, q->q_flags)) + continue; + if (NoConnect && !Verbose && + bitnset(M_EXPENSIVE, q->q_mailer->m_flags)) + { + q->q_flags |= QQUEUEUP; + e->e_to = q->q_paddr; + message("queued"); + if (LogLevel > 8) + logdelivery(q->q_mailer, NULL, + "queued", NULL, + (time_t) 0, e); + e->e_to = NULL; + } + else + { + somedeliveries = TRUE; + } } if (owner != NULL && otherowners > 0) @@ -232,7 +265,7 @@ sendall(e, mode) ee->e_header = copyheader(e->e_header); ee->e_sendqueue = copyqueue(e->e_sendqueue); ee->e_errorqueue = copyqueue(e->e_errorqueue); - ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS|EF_SENDRECEIPT); + ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS|EF_SENDRECEIPT|EF_RET_PARAM); ee->e_flags |= EF_NORECEIPT; setsender(owner, ee, NULL, TRUE); if (tTd(13, 5)) @@ -243,33 +276,44 @@ sendall(e, mode) ee->e_from.q_flags |= QDONTSEND; ee->e_dfp = NULL; ee->e_xfp = NULL; - ee->e_df = NULL; ee->e_errormode = EM_MAIL; ee->e_sibling = splitenv; splitenv = ee; for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { if (q->q_owner == owner) { q->q_flags |= QDONTSEND; q->q_flags &= ~QQUEUEUP; } + } for (q = ee->e_sendqueue; q != NULL; q = q->q_next) + { if (q->q_owner != owner) { q->q_flags |= QDONTSEND; q->q_flags &= ~QQUEUEUP; } + else + { + /* clear DSN parameters */ + q->q_flags &= ~(QHASNOTIFY|QPINGONSUCCESS); + q->q_flags |= QPINGONFAILURE|QPINGONDELAY; + } + } - if (e->e_df != NULL && mode != SM_VERIFY) + if (mode != SM_VERIFY && bitset(EF_HAS_DF, e->e_flags)) { + char df1buf[20], df2buf[20]; + ee->e_dfp = NULL; - ee->e_df = queuename(ee, 'd'); - ee->e_df = newstr(ee->e_df); - if (link(e->e_df, ee->e_df) < 0) + strcpy(df1buf, queuename(e, 'd')); + strcpy(df2buf, queuename(ee, 'd')); + if (link(df1buf, df2buf) < 0) { syserr("sendall: link(%s, %s)", - e->e_df, ee->e_df); + df1buf, df2buf); } } #ifdef LOG @@ -293,65 +337,26 @@ sendall(e, mode) e->e_flags |= EF_NORECEIPT; } + /* if nothing to be delivered, just queue up everything */ + if (!somedeliveries && mode != SM_QUEUE && mode != SM_VERIFY) + mode = SM_QUEUE; + # ifdef QUEUE if ((mode == SM_QUEUE || mode == SM_FORK || (mode != SM_VERIFY && SuperSafe)) && !bitset(EF_INQUEUE, e->e_flags)) { /* be sure everything is instantiated in the queue */ - queueup(e, TRUE, announcequeueup); + queueup(e, TRUE, mode == SM_QUEUE); for (ee = splitenv; ee != NULL; ee = ee->e_sibling) - queueup(ee, TRUE, announcequeueup); + queueup(ee, TRUE, mode == SM_QUEUE); } #endif /* QUEUE */ - if (splitenv != NULL) - { - if (tTd(13, 1)) - { - printf("\nsendall: Split queue; remaining queue:\n"); - printaddr(e->e_sendqueue, TRUE); - } - - for (ee = splitenv; ee != NULL; ee = ee->e_sibling) - { - CurEnv = ee; - if (mode != SM_VERIFY) - openxscript(ee); - sendenvelope(ee, mode); - dropenvelope(ee); - } - - CurEnv = e; - } - sendenvelope(e, mode); -} - -sendenvelope(e, mode) - register ENVELOPE *e; - char mode; -{ - bool oldverbose; - int pid; - register ADDRESS *q; - char *qf; - char *id; - /* - ** If we have had global, fatal errors, don't bother sending - ** the message at all if we are in SMTP mode. Local errors - ** (e.g., a single address failing) will still cause the other - ** addresses to be sent. + ** If we belong in background, fork now. */ - if (bitset(EF_FATALERRS, e->e_flags) && - (OpMode == MD_SMTP || OpMode == MD_DAEMON)) - { - e->e_flags |= EF_CLRQUEUE; - return; - } - - oldverbose = Verbose; switch (mode) { case SM_VERIFY: @@ -360,7 +365,8 @@ sendenvelope(e, mode) case SM_QUEUE: queueonly: - e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; + if (e->e_nrcpts > 0) + e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; return; case SM_FORK: @@ -375,15 +381,17 @@ sendenvelope(e, mode) ** then restart from scratch in the child. */ - /* save id for future use */ - id = e->e_id; + { + /* save id for future use */ + char *qid = e->e_id; - /* now drop the envelope in the parent */ - e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; - dropenvelope(e); + /* now drop the envelope in the parent */ + e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; + dropenvelope(e); - /* and reacquire in the child */ - (void) dowork(id, TRUE, FALSE, e); + /* and reacquire in the child */ + (void) dowork(qid, TRUE, FALSE, e); + } return; @@ -399,15 +407,16 @@ sendenvelope(e, mode) /* be sure we leave the temp files to our child */ /* can't call unlockqueue to avoid unlink of xfp */ if (e->e_lockfp != NULL) - (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); + (void) xfclose(e->e_lockfp, "sendenvelope lockfp", e->e_id); e->e_lockfp = NULL; /* close any random open files in the envelope */ closexscript(e); if (e->e_dfp != NULL) - (void) xfclose(e->e_dfp, "sendenvelope", e->e_df); + (void) xfclose(e->e_dfp, "sendenvelope dfp", e->e_id); e->e_dfp = NULL; - e->e_id = e->e_df = NULL; + e->e_id = NULL; + e->e_flags &= ~EF_HAS_DF; /* catch intermediate zombie */ (void) waitfor(pid); @@ -446,6 +455,51 @@ sendenvelope(e, mode) break; } + if (splitenv != NULL) + { + if (tTd(13, 1)) + { + printf("\nsendall: Split queue; remaining queue:\n"); + printaddr(e->e_sendqueue, TRUE); + } + + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + CurEnv = ee; + if (mode != SM_VERIFY) + openxscript(ee); + sendenvelope(ee, mode); + dropenvelope(ee); + } + + CurEnv = e; + } + sendenvelope(e, mode); + Verbose = oldverbose; +} + +void +sendenvelope(e, mode) + register ENVELOPE *e; + char mode; +{ + register ADDRESS *q; + bool didany; + + /* + ** If we have had global, fatal errors, don't bother sending + ** the message at all if we are in SMTP mode. Local errors + ** (e.g., a single address failing) will still cause the other + ** addresses to be sent. + */ + + if (bitset(EF_FATALERRS, e->e_flags) && + (OpMode == MD_SMTP || OpMode == MD_DAEMON)) + { + e->e_flags |= EF_CLRQUEUE; + return; + } + /* ** Run through the list and send everything. ** @@ -455,11 +509,12 @@ sendenvelope(e, mode) e->e_nsent = 0; e->e_flags |= EF_GLOBALERRS; + didany = FALSE; /* now run through the queue */ for (q = e->e_sendqueue; q != NULL; q = q->q_next) { -#ifdef XDEBUG +#if XDEBUG char wbuf[MAXNAME + 20]; (void) sprintf(wbuf, "sendall(%s)", q->q_paddr); @@ -495,11 +550,16 @@ sendenvelope(e, mode) } # endif /* QUEUE */ (void) deliver(e, q); + didany = TRUE; } } - Verbose = oldverbose; + if (didany) + { + e->e_dtime = curtime(); + e->e_ntries++; + } -#ifdef XDEBUG +#if XDEBUG checkfd012("end of sendenvelope"); #endif @@ -562,9 +622,10 @@ sendenvelope(e, mode) ** returns twice, once in parent and once in child. */ +int dofork() { - register int pid; + register int pid = -1; DOFORK(fork); return (pid); @@ -591,6 +652,7 @@ dofork() ** The standard input is passed off to someone. */ +int deliver(e, firstto) register ENVELOPE *e; ADDRESS *firstto; @@ -605,18 +667,20 @@ deliver(e, firstto) register MCI *mci; register ADDRESS *to = firstto; bool clever = FALSE; /* running user smtp to this mailer */ - ADDRESS *tochain = NULL; /* chain of users in this mailer call */ + ADDRESS *tochain = NULL; /* users chain in this mailer call */ int rcode; /* response code */ char *firstsig; /* signature of firstto */ - int pid; + int pid = -1; char *curhost; + time_t xstart; int mpvect[2]; int rpvect[2]; char *pv[MAXPV+1]; char tobuf[TOBUFSIZE]; /* text line of to people */ - char buf[MAXNAME]; - char rpathbuf[MAXNAME]; /* translated return path */ + char buf[MAXNAME + 1]; + char rpathbuf[MAXNAME + 1]; /* translated return path */ extern int checkcompat(); + extern void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int)); errno = 0; if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags)) @@ -636,6 +700,7 @@ deliver(e, firstto) CurEnv = e; /* just in case */ e->e_statmsg = NULL; SmtpError[0] = '\0'; + xstart = curtime(); if (tTd(10, 1)) printf("\n--deliver, id=%s, mailer=%s, host=`%s', first user=`%s'\n", @@ -643,33 +708,6 @@ deliver(e, firstto) if (tTd(10, 100)) printopenfds(FALSE); - /* - ** If this mailer is expensive, and if we don't want to make - ** connections now, just mark these addresses and return. - ** This is useful if we want to batch connections to - ** reduce load. This will cause the messages to be - ** queued up, and a daemon will come along to send the - ** messages later. - ** This should be on a per-mailer basis. - */ - - if (NoConnect && bitnset(M_EXPENSIVE, m->m_flags) && !Verbose) - { - for (; to != NULL; to = to->q_next) - { - if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || - to->q_mailer != m) - continue; - to->q_flags |= QQUEUEUP; - e->e_to = to->q_paddr; - message("queued"); - if (LogLevel > 8) - logdelivery(m, NULL, "queued", NULL, e); - } - e->e_to = NULL; - return (0); - } - /* ** Do initial argv setup. ** Insert the mailer name. Notice that $x expansion is @@ -683,7 +721,11 @@ deliver(e, firstto) /* rewrite from address, using rewriting rules */ rcode = EX_OK; - (void) strcpy(rpathbuf, remotename(e->e_from.q_paddr, m, + if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) + p = e->e_sender; + else + p = e->e_from.q_paddr; + (void) strcpy(rpathbuf, remotename(p, m, RF_SENDERADDR|RF_CANONICAL, &rcode, e)); define('g', rpathbuf, e); /* translated return path */ @@ -725,7 +767,7 @@ deliver(e, firstto) break; /* this entry is safe -- go ahead and process it */ - expand(*mvp, buf, &buf[sizeof buf - 1], e); + expand(*mvp, buf, sizeof buf, e); *pvp++ = newstr(buf); if (pvp >= &pv[MAXPV - 3]) { @@ -787,11 +829,15 @@ deliver(e, firstto) } /* compute effective uid/gid when sending */ - /* XXX perhaps this should be to->q_mailer != LocalMailer ?? */ - /* XXX perhaps it should be a mailer flag? */ - if (to->q_mailer == ProgMailer || to->q_mailer == FileMailer) + if (bitnset(M_RUNASRCPT, to->q_mailer->m_flags)) ctladdr = getctladdr(to); + if (tTd(10, 2)) + { + printf("ctladdr="); + printaddr(ctladdr, FALSE); + } + user = to->q_user; e->e_to = to->q_paddr; if (tTd(10, 5)) @@ -808,16 +854,20 @@ deliver(e, firstto) if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) { - NoReturn = TRUE; + e->e_flags |= EF_NO_BODY_RETN; + to->q_status = "5.2.3"; usrerr("552 Message is too large; %ld bytes max", m->m_maxsize); - giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, e); + giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e); continue; } +#if NAMED_BIND + h_errno = 0; +#endif rcode = checkcompat(to, e); if (rcode != EX_OK) { - markfailure(e, to, rcode); - giveresponse(rcode, m, NULL, ctladdr, e); + markfailure(e, to, NULL, rcode); + giveresponse(rcode, m, NULL, ctladdr, xstart, e); continue; } @@ -859,12 +909,25 @@ deliver(e, firstto) ** with the others, so we fudge on the To person. */ - if (m == FileMailer) + if (strcmp(m->m_mailer, "[FILE]") == 0) { - rcode = mailfile(user, ctladdr, e); - giveresponse(rcode, m, NULL, ctladdr, e); + rcode = mailfile(user, ctladdr, SFF_CREAT, e); + giveresponse(rcode, m, NULL, ctladdr, xstart, e); + e->e_nsent++; if (rcode == EX_OK) + { to->q_flags |= QSENT; + if (bitnset(M_LOCALMAILER, m->m_flags) && + (e->e_receiptto != NULL || + bitset(QPINGONSUCCESS, to->q_flags))) + { + to->q_flags |= QDELIVERED; + to->q_status = "2.1.5"; + fprintf(e->e_xfp, "%s... Successfully delivered\n", + to->q_paddr); + } + } + to->q_statdate = curtime(); continue; } @@ -892,7 +955,7 @@ deliver(e, firstto) if (!clever) { - expand(*mvp, buf, &buf[sizeof buf - 1], e); + expand(*mvp, buf, sizeof buf, e); *pvp++ = newstr(buf); if (pvp >= &pv[MAXPV - 2]) { @@ -918,7 +981,7 @@ deliver(e, firstto) while (!clever && *++mvp != NULL) { - expand(*mvp, buf, &buf[sizeof buf - 1], e); + expand(*mvp, buf, sizeof buf, e); *pvp++ = newstr(buf); if (pvp >= &pv[MAXPV]) syserr("554 deliver: pv overflow after $u for %s", pv[0]); @@ -934,7 +997,7 @@ deliver(e, firstto) */ /*XXX this seems a bit wierd */ - if (ctladdr == NULL && m != ProgMailer && + if (ctladdr == NULL && m != ProgMailer && m != FileMailer && bitset(QGOODUID, e->e_from.q_flags)) ctladdr = &e->e_from; @@ -949,8 +1012,11 @@ deliver(e, firstto) printav(pv); } errno = 0; +#if NAMED_BIND + h_errno = 0; +#endif - CurHostName = m->m_mailer; + CurHostName = NULL; /* ** Deal with the special case of mail handled through an IPC @@ -965,7 +1031,7 @@ deliver(e, firstto) SmtpPhase = NULL; mci = NULL; -#ifdef XDEBUG +#if XDEBUG { char wbuf[MAXLINE]; @@ -975,6 +1041,18 @@ deliver(e, firstto) } #endif + /* check for 8-bit available */ + if (bitset(EF_HAS8BIT, e->e_flags) && + bitnset(M_7BITS, m->m_flags) && + (!bitset(MM_MIME8BIT, MimeMode) || + bitset(EF_DONT_MIME, e->e_flags))) + { + usrerr("554 Cannot send 8-bit data to 7-bit destination"); + rcode = EX_DATAERR; + e->e_status = "5.6.3"; + goto give_up; + } + /* check for Local Person Communication -- not for mortals!!! */ if (strcmp(m->m_mailer, "[LPC]") == 0) { @@ -990,7 +1068,7 @@ deliver(e, firstto) { #ifdef DAEMON register int i; - register u_short port; + register u_short port = 0; if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0') { @@ -1005,7 +1083,7 @@ deliver(e, firstto) if (curhost == NULL || curhost[0] == '\0') { syserr("null host signature for %s", pv[1]); - rcode = EX_OSERR; + rcode = EX_CONFIG; goto give_up; } @@ -1016,14 +1094,23 @@ deliver(e, firstto) goto give_up; } if (pv[2] != NULL) - port = atoi(pv[2]); - else - port = 0; + { + port = htons(atoi(pv[2])); + if (port == 0) + { + struct servent *sp = getservbyname(pv[2], "tcp"); + + if (sp == NULL) + syserr("Service %s unknown", pv[2]); + else + port = sp->s_port; + } + } tryhost: while (*curhost != '\0') { register char *p; - static char hostbuf[MAXNAME]; + static char hostbuf[MAXNAME + 1]; /* pull the next host from the signature */ p = strchr(curhost, ':'); @@ -1052,6 +1139,8 @@ tryhost: mci_dump(mci, FALSE); } CurHostName = mci->mci_host; + message("Using cached connection to %s via %s...", + hostbuf, m->m_name); break; } mci->mci_mailer = m; @@ -1060,7 +1149,7 @@ tryhost: /* try the connection */ setproctitle("%s %s: %s", e->e_id, hostbuf, "user open"); - message("Connecting to %s (%s)...", + message("Connecting to %s via %s...", hostbuf, m->m_name); i = makeconnection(hostbuf, port, mci, bitnset(M_SECURE_PORT, m->m_flags)); @@ -1104,6 +1193,14 @@ tryhost: } else { + /* flush any expired connections */ + (void) mci_scan(NULL); + + /* announce the connection to verbose listeners */ + if (host == NULL || host[0] == '\0') + message("Connecting to %s...", m->m_name); + else + message("Connecting to %s via %s...", host, m->m_name); if (TrafficLogFile != NULL) { char **av; @@ -1175,33 +1272,59 @@ tryhost: { int i; int saveerrno; - char **ep; - char *env[MAXUSERENVIRON]; - extern char **environ; + struct stat stb; extern int DtableSize; + if (e->e_lockfp != NULL) + (void) close(fileno(e->e_lockfp)); + /* child -- set up input & exec mailer */ (void) setsignal(SIGINT, SIG_IGN); (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGTERM, SIG_DFL); - /* reset user and group */ - if (!bitnset(M_RESTR, m->m_flags)) + if (m != FileMailer || stat(tochain->q_user, &stb) < 0) + stb.st_mode = 0; + + /* tweak niceness */ + if (m->m_nice != 0) + nice(m->m_nice); + + /* reset group id */ + if (bitnset(M_SPECIFIC_UID, m->m_flags)) + (void) setgid(m->m_gid); + else if (bitset(S_ISGID, stb.st_mode)) + (void) setgid(stb.st_gid); + else if (ctladdr != NULL && ctladdr->q_gid != 0) { - if (ctladdr == NULL || ctladdr->q_uid == 0) - { - (void) initgroups(DefUser, DefGid); + (void) initgroups(ctladdr->q_ruser? + ctladdr->q_ruser: ctladdr->q_user, + ctladdr->q_gid); + (void) setgid(ctladdr->q_gid); + } + else + { + (void) initgroups(DefUser, DefGid); + if (m->m_gid == 0) (void) setgid(DefGid); + else + (void) setgid(m->m_gid); + } + + /* reset user id */ + endpwent(); + if (bitnset(M_SPECIFIC_UID, m->m_flags)) + (void) setuid(m->m_uid); + else if (bitset(S_ISUID, stb.st_mode)) + (void) setuid(stb.st_uid); + else if (ctladdr != NULL && ctladdr->q_uid != 0) + (void) setuid(ctladdr->q_uid); + else + { + if (m->m_uid == 0) (void) setuid(DefUid); - } else - { - (void) initgroups(ctladdr->q_ruser? - ctladdr->q_ruser: ctladdr->q_user, - ctladdr->q_gid); - (void) setgid(ctladdr->q_gid); - (void) setuid(ctladdr->q_uid); - } + (void) setuid(m->m_uid); } if (tTd(11, 2)) @@ -1212,14 +1335,14 @@ tryhost: if (m->m_execdir != NULL) { char *p, *q; - char buf[MAXLINE]; + char buf[MAXLINE + 1]; for (p = m->m_execdir; p != NULL; p = q) { q = strchr(p, ':'); if (q != NULL) *q = '\0'; - expand(p, buf, &buf[sizeof buf] - 1, e); + expand(p, buf, sizeof buf, e); if (q != NULL) *q++ = ':'; if (tTd(11, 20)) @@ -1280,32 +1403,15 @@ tryhost: (void) fcntl(i, F_SETFD, j | 1); } - /* - ** Set up the mailer environment - ** TZ is timezone information. - ** SYSTYPE is Apollo software sys type (required). - ** ISP is Apollo hardware system type (required). - */ - - i = 0; - env[i++] = "AGENT=sendmail"; - for (ep = environ; *ep != NULL; ep++) - { - if (strncmp(*ep, "TZ=", 3) == 0 || - strncmp(*ep, "ISP=", 4) == 0 || - strncmp(*ep, "SYSTYPE=", 8) == 0) - env[i++] = *ep; - } - env[i++] = NULL; - /* run disconnected from terminal */ (void) setsid(); /* try to execute the mailer */ - execve(m->m_mailer, pv, env); + execve(m->m_mailer, (ARGV_T) pv, (ARGV_T) UserEnviron); saveerrno = errno; syserr("Cannot exec %s", m->m_mailer); - if (m == LocalMailer || transienterror(saveerrno)) + if (bitnset(M_LOCALMAILER, m->m_flags) || + transienterror(saveerrno)) _exit(EX_OSERR); _exit(EX_UNAVAILABLE); } @@ -1364,6 +1470,12 @@ tryhost: { smtpinit(m, mci, e); } + + if (bitset(EF_HAS8BIT, e->e_flags) && bitnset(M_7BITS, m->m_flags)) + mci->mci_flags |= MCIF_CVT8TO7; + else + mci->mci_flags &= ~MCIF_CVT8TO7; + if (tTd(11, 1)) { printf("openmailer: "); @@ -1385,7 +1497,7 @@ tryhost: rcode, mci->mci_state, firstsig); rcode = EX_SOFTWARE; } - else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0') + else if (curhost != NULL && *curhost != '\0') { /* try next MX site */ goto tryhost; @@ -1398,8 +1510,7 @@ tryhost: */ putfromline(mci, e); - (*e->e_puthdr)(mci, e); - putline("\n", mci); + (*e->e_puthdr)(mci, e->e_header, e); (*e->e_putbody)(mci, e, NULL); /* get the exit status */ @@ -1425,8 +1536,8 @@ tryhost: e->e_to = to->q_paddr; if ((i = smtprcpt(to, m, mci, e)) != EX_OK) { - markfailure(e, to, i); - giveresponse(i, m, mci, ctladdr, e); + markfailure(e, to, mci, i); + giveresponse(i, m, mci, ctladdr, xstart, e); } else { @@ -1490,21 +1601,33 @@ tryhost: give_up: if (tobuf[0] != '\0') - giveresponse(rcode, m, mci, ctladdr, e); + giveresponse(rcode, m, mci, ctladdr, xstart, e); for (to = tochain; to != NULL; to = to->q_tchain) { if (rcode != EX_OK) - markfailure(e, to, rcode); - else + markfailure(e, to, mci, rcode); + else if (!bitset(QBADADDR|QQUEUEUP, to->q_flags)) { to->q_flags |= QSENT; + to->q_statdate = curtime(); e->e_nsent++; - if (e->e_receiptto != NULL && - bitnset(M_LOCALMAILER, m->m_flags)) + if (bitnset(M_LOCALMAILER, m->m_flags) && + (e->e_receiptto != NULL || + bitset(QPINGONSUCCESS, to->q_flags))) { + to->q_flags |= QDELIVERED; + to->q_status = "2.1.5"; fprintf(e->e_xfp, "%s... Successfully delivered\n", to->q_paddr); } + else if (bitset(QPINGONSUCCESS, to->q_flags) && + bitset(QPRIMARY, to->q_flags) && + !bitset(MCIF_DSN, mci->mci_flags)) + { + to->q_flags |= QRELAYED; + fprintf(e->e_xfp, "%s... relayed; expect no further notifications\n", + to->q_paddr); + } } } @@ -1512,7 +1635,7 @@ tryhost: ** Restore state and return. */ -#ifdef XDEBUG +#if XDEBUG { char wbuf[MAXLINE]; @@ -1534,6 +1657,7 @@ tryhost: ** Parameters: ** e -- the envelope we are sending. ** q -- the address to mark. +** mci -- mailer connection information. ** rcode -- the code signifying the particular failure. ** ** Returns: @@ -1545,12 +1669,14 @@ tryhost: ** the message will be queued, as appropriate. */ -markfailure(e, q, rcode) +void +markfailure(e, q, mci, rcode) register ENVELOPE *e; register ADDRESS *q; + register MCI *mci; int rcode; { - char buf[MAXLINE]; + char *stat = NULL; switch (rcode) { @@ -1567,6 +1693,69 @@ markfailure(e, q, rcode) q->q_flags |= QBADADDR; break; } + + /* find most specific error code possible */ + if (q->q_status == NULL && mci != NULL) + q->q_status = mci->mci_status; + if (q->q_status == NULL) + q->q_status = e->e_status; + if (q->q_status == NULL) + { + switch (rcode) + { + case EX_USAGE: + stat = "5.5.4"; + break; + + case EX_DATAERR: + stat = "5.5.2"; + break; + + case EX_NOUSER: + stat = "5.1.1"; + break; + + case EX_NOHOST: + stat = "5.1.2"; + break; + + case EX_NOINPUT: + case EX_CANTCREAT: + case EX_NOPERM: + stat = "5.3.0"; + break; + + case EX_UNAVAILABLE: + case EX_SOFTWARE: + case EX_OSFILE: + case EX_PROTOCOL: + case EX_CONFIG: + stat = "5.5.0"; + break; + + case EX_OSERR: + case EX_IOERR: + stat = "4.5.0"; + break; + + case EX_TEMPFAIL: + stat = "4.2.0"; + break; + } + if (stat != NULL) + q->q_status = stat; + } + + q->q_statdate = curtime(); + if (CurHostName != NULL && CurHostName[0] != '\0') + q->q_statmta = newstr(CurHostName); + if (rcode != EX_OK && q->q_rstatus == NULL) + { + char buf[30]; + + (void) sprintf(buf, "%d", rcode); + q->q_rstatus = newstr(buf); + } } /* ** ENDMAILER -- Wait for mailer to terminate. @@ -1589,6 +1778,7 @@ markfailure(e, q, rcode) ** none. */ +int endmailer(mci, e, pv) register MCI *mci; register ENVELOPE *e; @@ -1652,6 +1842,8 @@ endmailer(mci, e, pv) ** response is given before the connection is made. ** ctladdr -- the controlling address for the recipient ** address(es). +** xstart -- the transaction start time, for computing +** transaction delays. ** e -- the current envelope. ** ** Returns: @@ -1662,11 +1854,13 @@ endmailer(mci, e, pv) ** ExitStat may be set. */ -giveresponse(stat, m, mci, ctladdr, e) +void +giveresponse(stat, m, mci, ctladdr, xstart, e) int stat; register MAILER *m; register MCI *mci; ADDRESS *ctladdr; + time_t xstart; ENVELOPE *e; { register const char *statmsg; @@ -1726,7 +1920,7 @@ giveresponse(stat, m, mci, ctladdr, e) else if (stat == EX_NOHOST && h_errno != 0) { statmsg = errstring(h_errno + E_DNSBASE); - (void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg); + (void) sprintf(buf, "%s (%s)", SysExMsg[i] + 1, statmsg); statmsg = buf; } #endif @@ -1754,8 +1948,11 @@ giveresponse(stat, m, mci, ctladdr, e) } else { + char mbuf[8]; + Errors++; - usrerr(statmsg, errstring(errno)); + sprintf(mbuf, "%.3s %%s", statmsg); + usrerr(mbuf, &statmsg[4]); } /* @@ -1766,11 +1963,11 @@ giveresponse(stat, m, mci, ctladdr, e) */ if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6)) - logdelivery(m, mci, &statmsg[4], ctladdr, e); + logdelivery(m, mci, &statmsg[4], ctladdr, xstart, e); if (tTd(11, 2)) printf("giveresponse: stat=%d, e->e_message=%s\n", - stat, e->e_message); + stat, e->e_message == NULL ? "" : e->e_message); if (stat != EX_TEMPFAIL) setstat(stat); @@ -1798,6 +1995,8 @@ giveresponse(stat, m, mci, ctladdr, e) ** log is occuring when no connection is active. ** stat -- the message to print for the status. ** ctladdr -- the controlling address for the to list. +** xstart -- the transaction start time, used for +** computing transaction delay. ** e -- the current envelope. ** ** Returns: @@ -1807,11 +2006,13 @@ giveresponse(stat, m, mci, ctladdr, e) ** none */ -logdelivery(m, mci, stat, ctladdr, e) +void +logdelivery(m, mci, stat, ctladdr, xstart, e) MAILER *m; register MCI *mci; - char *stat; + const char *stat; ADDRESS *ctladdr; + time_t xstart; register ENVELOPE *e; { # ifdef LOG @@ -1835,9 +2036,15 @@ logdelivery(m, mci, stat, ctladdr, e) } } - (void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); + sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); bp += strlen(bp); + if (xstart != (time_t) 0) + { + sprintf(bp, ", xdelay=%s", pintvl(curtime() - xstart, TRUE)); + bp += strlen(bp); + } + if (m != NULL) { (void) strcpy(bp, ", mailer="); @@ -1897,7 +2104,7 @@ logdelivery(m, mci, stat, ctladdr, e) l = SYSLOG_BUFSIZE - 100 - strlen(buf); p = e->e_to; - while (strlen(p) >= l) + while (strlen(p) >= (SIZE_T) l) { register char *q = strchr(p + l, ','); @@ -1943,6 +2150,11 @@ logdelivery(m, mci, stat, ctladdr, e) bp = buf; sprintf(bp, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); bp += strlen(bp); + if (xstart != (time_t) 0) + { + sprintf(bp, ", xdelay=%s", pintvl(curtime() - xstart, TRUE)); + bp += strlen(bp); + } if (m != NULL) { @@ -2001,6 +2213,7 @@ logdelivery(m, mci, stat, ctladdr, e) ** outputs some text to fp. */ +void putfromline(mci, e) register MCI *mci; ENVELOPE *e; @@ -2011,13 +2224,12 @@ putfromline(mci, e) if (bitnset(M_NHDR, mci->mci_mailer->m_flags)) return; -# ifdef UGLYUUCP if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags)) { char *bang; char xbuf[MAXLINE]; - expand("\201g", buf, &buf[sizeof buf - 1], e); + expand("\201g", buf, sizeof buf, e); bang = strchr(buf, '!'); if (bang == NULL) { @@ -2031,9 +2243,8 @@ putfromline(mci, e) template = xbuf; } } -# endif /* UGLYUUCP */ - expand(template, buf, &buf[sizeof buf - 1], e); - putline(buf, mci); + expand(template, buf, sizeof buf, e); + putxline(buf, mci, PXLF_NOTHINGSPECIAL); } /* ** PUTBODY -- put the body of a message. @@ -2051,6 +2262,12 @@ putfromline(mci, e) ** The message is written onto fp. */ +/* values for output state variable */ +#define OS_HEAD 0 /* at beginning of line */ +#define OS_CR 1 /* read a carriage return */ +#define OS_INLINE 2 /* putting rest of line */ + +void putbody(mci, e, separator) register MCI *mci; register ENVELOPE *e; @@ -2062,45 +2279,236 @@ putbody(mci, e, separator) ** Output the body of the message */ + if (e->e_dfp == NULL && bitset(EF_HAS_DF, e->e_flags)) + { + char *df = queuename(e, 'd'); + + e->e_dfp = fopen(df, "r"); + if (e->e_dfp == NULL) + syserr("putbody: Cannot open %s for %s from %s", + df, e->e_to, e->e_from.q_paddr); + } if (e->e_dfp == NULL) { - if (e->e_df != NULL) + if (bitset(MCIF_INHEADER, mci->mci_flags)) { - e->e_dfp = fopen(e->e_df, "r"); - if (e->e_dfp == NULL) - syserr("putbody: Cannot open %s for %s from %s", - e->e_df, e->e_to, e->e_from.q_paddr); + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; } - else - putline("<<< No Message Collected >>>", mci); + putline("<<< No Message Collected >>>", mci); + goto endofmessage; } - if (e->e_dfp != NULL) + if (e->e_dfino == (ino_t) 0) { - rewind(e->e_dfp); - while (!ferror(mci->mci_out) && fgets(buf, sizeof buf, e->e_dfp) != NULL) + struct stat stbuf; + + if (fstat(fileno(e->e_dfp), &stbuf) < 0) + e->e_dfino = -1; + else { - if (buf[0] == 'F' && - bitnset(M_ESCFROM, mci->mci_mailer->m_flags) && - strncmp(buf, "From ", 5) == 0) - (void) putc('>', mci->mci_out); - if (buf[0] == '-' && buf[1] == '-' && separator != NULL) - { - /* possible separator */ - int sl = strlen(separator); + e->e_dfdev = stbuf.st_dev; + e->e_dfino = stbuf.st_ino; + } + } + rewind(e->e_dfp); - if (strncmp(&buf[2], separator, sl) == 0) - (void) putc(' ', mci->mci_out); - } +#if MIME8TO7 + if (bitset(MCIF_CVT8TO7, mci->mci_flags)) + { + char *boundaries[MAXMIMENESTING + 1]; + + /* + ** Do 8 to 7 bit MIME conversion. + */ + + /* make sure it looks like a MIME message */ + if (hvalue("MIME-Version", e->e_header) == NULL) + putline("MIME-Version: 1.0", mci); + + if (hvalue("Content-Type", e->e_header) == NULL) + { + sprintf(buf, "Content-Type: text/plain; charset=%s", + defcharset(e)); putline(buf, mci); } - if (ferror(e->e_dfp)) + /* now do the hard work */ + boundaries[0] = NULL; + mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER); + } + else +#endif + { + int ostate; + register char *bp; + register char *pbp; + register int c; + int padc; + char *buflim; + int pos = 0; + char peekbuf[10]; + + /* we can pass it through unmodified */ + if (bitset(MCIF_INHEADER, mci->mci_flags)) + { + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; + } + + /* determine end of buffer; allow for short mailer lines */ + buflim = &buf[sizeof buf - 1]; + if (mci->mci_mailer->m_linelimit > 0 && + mci->mci_mailer->m_linelimit < sizeof buf - 1) + buflim = &buf[mci->mci_mailer->m_linelimit - 1]; + + /* copy temp file to output with mapping */ + ostate = OS_HEAD; + bp = buf; + pbp = peekbuf; + while (!ferror(mci->mci_out)) { - syserr("putbody: %s: read error", e->e_df); - ExitStat = EX_IOERR; + register char *xp; + + if (pbp > peekbuf) + c = *--pbp; + else if ((c = getc(e->e_dfp)) == EOF) + break; + if (bitset(MCIF_7BIT, mci->mci_flags)) + c &= 0x7f; + switch (ostate) + { + case OS_HEAD: + if (c != '\r' && c != '\n' && bp < buflim) + { + *bp++ = c; + break; + } + + /* check beginning of line for special cases */ + *bp = '\0'; + pos = 0; + padc = EOF; + if (buf[0] == 'F' && + bitnset(M_ESCFROM, mci->mci_mailer->m_flags) && + strncmp(buf, "From ", 5) == 0) + { + padc = '>'; + } + if (buf[0] == '-' && buf[1] == '-' && + separator != NULL) + { + /* possible separator */ + int sl = strlen(separator); + + if (strncmp(&buf[2], separator, sl) == 0) + padc = ' '; + } + if (buf[0] == '.' && + bitnset(M_XDOT, mci->mci_mailer->m_flags)) + { + padc = '.'; + } + + /* now copy out saved line */ + if (TrafficLogFile != NULL) + { + fprintf(TrafficLogFile, "%05d >>> ", getpid()); + if (padc != EOF) + putc(padc, TrafficLogFile); + for (xp = buf; xp < bp; xp++) + putc(*xp, TrafficLogFile); + if (c == '\n') + fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + } + if (padc != EOF) + { + putc(padc, mci->mci_out); + pos++; + } + for (xp = buf; xp < bp; xp++) + putc(*xp, mci->mci_out); + if (c == '\n') + { + fputs(mci->mci_mailer->m_eol, + mci->mci_out); + pos = 0; + } + else + { + pos += bp - buf; + if (c != '\r') + *pbp++ = c; + } + bp = buf; + + /* determine next state */ + if (c == '\n') + ostate = OS_HEAD; + else if (c == '\r') + ostate = OS_CR; + else + ostate = OS_INLINE; + continue; + + case OS_CR: + if (c == '\n') + { + /* got CRLF */ + fputs(mci->mci_mailer->m_eol, mci->mci_out); + if (TrafficLogFile != NULL) + { + fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + } + ostate = OS_HEAD; + continue; + } + + /* had a naked carriage return */ + *pbp++ = c; + c = '\r'; + goto putch; + + case OS_INLINE: + if (c == '\r') + { + ostate = OS_CR; + continue; + } +putch: + if (mci->mci_mailer->m_linelimit > 0 && + pos > mci->mci_mailer->m_linelimit && + c != '\n') + { + putc('!', mci->mci_out); + fputs(mci->mci_mailer->m_eol, mci->mci_out); + if (TrafficLogFile != NULL) + { + fprintf(TrafficLogFile, "!%s", + mci->mci_mailer->m_eol); + } + ostate = OS_HEAD; + *pbp++ = c; + continue; + } + if (TrafficLogFile != NULL) + putc(c, TrafficLogFile); + putc(c, mci->mci_out); + pos++; + ostate = c == '\n' ? OS_HEAD : OS_INLINE; + break; + } } } + if (ferror(e->e_dfp)) + { + syserr("putbody: df%s: read error", e->e_id); + ExitStat = EX_IOERR; + } + +endofmessage: /* some mailers want extra blank line at end of message */ if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) && buf[0] != '\0' && buf[0] != '\n') @@ -2132,6 +2540,8 @@ putbody(mci, e, separator) ** filename -- the name of the file to send to. ** ctladdr -- the controlling address header -- includes ** the userid/groupid to be when sending. +** sfflags -- flags for opening. +** e -- the current envelope. ** ** Returns: ** The exit code associated with the operation. @@ -2140,13 +2550,15 @@ putbody(mci, e, separator) ** none. */ -mailfile(filename, ctladdr, e) +int +mailfile(filename, ctladdr, sfflags, e) char *filename; ADDRESS *ctladdr; + int sfflags; register ENVELOPE *e; { register FILE *f; - register int pid; + register int pid = -1; int mode; if (tTd(11, 1)) @@ -2172,63 +2584,133 @@ mailfile(filename, ctladdr, e) { /* child -- actually write to file */ struct stat stb; + struct stat fsb; MCI mcibuf; + int oflags = O_WRONLY|O_APPEND; + + if (e->e_lockfp != NULL) + (void) close(fileno(e->e_lockfp)); (void) setsignal(SIGINT, SIG_DFL); (void) setsignal(SIGHUP, SIG_DFL); (void) setsignal(SIGTERM, SIG_DFL); (void) umask(OldUmask); + e->e_to = filename; + ExitStat = EX_OK; +#ifdef HASLSTAT + if ((SafeFileEnv != NULL ? lstat(filename, &stb) + : stat(filename, &stb)) < 0) +#else if (stat(filename, &stb) < 0) +#endif + { stb.st_mode = FileMode; + oflags |= O_CREAT|O_EXCL; + } + else if (bitset(0111, stb.st_mode) || stb.st_nlink != 1 || + (SafeFileEnv != NULL && !S_ISREG(stb.st_mode))) + exit(EX_CANTCREAT); mode = stb.st_mode; /* limit the errors to those actually caused in the child */ errno = 0; ExitStat = EX_OK; - if (bitset(0111, stb.st_mode)) - exit(EX_CANTCREAT); - if (ctladdr != NULL) + if (ctladdr != NULL || bitset(SFF_RUNASREALUID, sfflags)) { /* ignore setuid and setgid bits */ mode &= ~(S_ISGID|S_ISUID); } /* we have to open the dfile BEFORE setuid */ - if (e->e_dfp == NULL && e->e_df != NULL) + if (e->e_dfp == NULL && bitset(EF_HAS_DF, e->e_flags)) { - e->e_dfp = fopen(e->e_df, "r"); + char *df = queuename(e, 'd'); + + e->e_dfp = fopen(df, "r"); if (e->e_dfp == NULL) { syserr("mailfile: Cannot open %s for %s from %s", - e->e_df, e->e_to, e->e_from.q_paddr); + df, e->e_to, e->e_from.q_paddr); } } - if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) + if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0') { - if (ctladdr == NULL || ctladdr->q_uid == 0) + int i; + + if (chroot(SafeFileEnv) < 0) { - (void) initgroups(DefUser, DefGid); + syserr("mailfile: Cannot chroot(%s)", + SafeFileEnv); + exit(EX_CANTCREAT); + } + i = strlen(SafeFileEnv); + if (strncmp(SafeFileEnv, filename, i) == 0) + filename += i; + } + if (chdir("/") < 0) + syserr("mailfile: cannot chdir(/)"); + + /* select a new user to run as */ + if (!bitset(SFF_RUNASREALUID, sfflags)) + { + if (bitset(S_ISUID, mode)) + { + RealUserName = NULL; + RealUid = stb.st_uid; + } + else if (ctladdr != NULL && ctladdr->q_uid != 0) + { + if (ctladdr->q_ruser != NULL) + RealUserName = ctladdr->q_ruser; + else + RealUserName = ctladdr->q_user; + RealUid = ctladdr->q_uid; + } + else if (FileMailer != NULL && FileMailer->m_uid != 0) + { + RealUserName = DefUser; + RealUid = FileMailer->m_uid; } else { - (void) initgroups(ctladdr->q_ruser ? - ctladdr->q_ruser : ctladdr->q_user, - ctladdr->q_gid); + RealUserName = DefUser; + RealUid = DefUid; } + + /* select a new group to run as */ + if (bitset(S_ISGID, mode)) + RealGid = stb.st_gid; + else if (ctladdr != NULL && ctladdr->q_uid != 0) + RealGid = ctladdr->q_gid; + else if (FileMailer != NULL && FileMailer->m_gid != 0) + RealGid = FileMailer->m_gid; + else + RealGid = DefGid; } - if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) + + /* last ditch */ + if (!bitset(SFF_ROOTOK, sfflags)) { - if (ctladdr == NULL || ctladdr->q_uid == 0) - (void) setuid(DefUid); - else - (void) setuid(ctladdr->q_uid); + if (RealUid == 0) + RealUid = DefUid; + if (RealGid == 0) + RealGid = DefGid; } - FileName = filename; - LineNumber = 0; - f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode); + + /* now set the group and user ids */ + endpwent(); + if (RealUserName != NULL) + (void) initgroups(RealUserName, RealGid); + else + (void) setgid(RealGid); + (void) setuid(RealUid); + + sfflags |= SFF_NOPATHCHECK; + sfflags &= ~SFF_OPENASROOT; + f = safefopen(filename, oflags, FileMode, sfflags); if (f == NULL) { message("554 cannot open: %s", errstring(errno)); @@ -2242,8 +2724,7 @@ mailfile(filename, ctladdr, e) mcibuf.mci_flags |= MCIF_7BIT; putfromline(&mcibuf, e); - (*e->e_puthdr)(&mcibuf, e); - putline("\n", &mcibuf); + (*e->e_puthdr)(&mcibuf, e->e_header, e); (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); if (ferror(f)) @@ -2309,7 +2790,7 @@ hostsignature(m, host, e) auto int rcode; char *hp; char *endp; - int oldoptions; + int oldoptions = _res.options; char *mxhosts[MAXMXHOSTS + 1]; #endif @@ -2338,10 +2819,7 @@ hostsignature(m, host, e) #if NAMED_BIND if (ConfigLevel < 2) - { - oldoptions = _res.options; _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ - } for (hp = host; hp != NULL; hp = endp) { @@ -2359,9 +2837,7 @@ hostsignature(m, host, e) mci = mci_get(hp, m); mci->mci_exitstat = rcode; mci->mci_errno = errno; -#if NAMED_BIND mci->mci_herrno = h_errno; -#endif /* and return the original host name as the signature */ nmx = 1;