summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/savemail.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/savemail.c')
-rw-r--r--contrib/sendmail/src/savemail.c622
1 files changed, 350 insertions, 272 deletions
diff --git a/contrib/sendmail/src/savemail.c b/contrib/sendmail/src/savemail.c
index fb7f8fd..c7fe609 100644
--- a/contrib/sendmail/src/savemail.c
+++ b/contrib/sendmail/src/savemail.c
@@ -11,12 +11,9 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: savemail.c,v 8.212.4.13 2001/05/03 17:24:15 gshapiro Exp $";
-#endif /* ! lint */
-
#include <sendmail.h>
+SM_RCSID("@(#)$Id: savemail.c,v 8.297 2001/12/28 22:32:19 ca Exp $")
static void errbody __P((MCI *, ENVELOPE *, char *));
static bool pruneroute __P((char *));
@@ -31,11 +28,12 @@ static bool pruneroute __P((char *));
**
** Parameters:
** e -- the envelope containing the message in error.
-** sendbody -- if TRUE, also send back the body of the
+** sendbody -- if true, also send back the body of the
** message; otherwise just send the header.
**
** Returns:
-** none
+** true if savemail panic'ed, (i.e., the data file should
+** be preserved by dropenvelope())
**
** Side Effects:
** Saves the letter, by writing or mailing it back to the
@@ -53,14 +51,13 @@ static bool pruneroute __P((char *));
#define ESM_PANIC 6 /* call loseqfile() */
#define ESM_DONE 7 /* message is successfully delivered */
-
-void
+bool
savemail(e, sendbody)
register ENVELOPE *e;
bool sendbody;
{
- register struct passwd *pw;
- register FILE *fp;
+ register SM_FILE_T *fp;
+ bool panic = false;
int state;
auto ADDRESS *q = NULL;
register char *p;
@@ -68,19 +65,21 @@ savemail(e, sendbody)
int flags;
long sff;
char buf[MAXLINE + 1];
+ SM_MBDB_T user;
+
if (tTd(6, 1))
{
- dprintf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=",
+ sm_dprintf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=",
e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id,
ExitStat);
- printaddr(&e->e_from, FALSE);
+ printaddr(&e->e_from, false);
}
if (e->e_id == NULL)
{
/* can't return a message with no id */
- return;
+ return panic;
}
/*
@@ -92,10 +91,11 @@ savemail(e, sendbody)
{
e->e_sender = "Postmaster";
if (parseaddr(e->e_sender, &e->e_from,
- RF_COPYPARSE|RF_SENDERADDR, '\0', NULL, e) == NULL)
+ RF_COPYPARSE|RF_SENDERADDR,
+ '\0', NULL, e, false) == NULL)
{
syserr("553 5.3.5 Cannot parse Postmaster!");
- finis(TRUE, EX_SOFTWARE);
+ finis(true, true, EX_SOFTWARE);
}
}
e->e_to = NULL;
@@ -135,10 +135,10 @@ savemail(e, sendbody)
case EM_QUIET:
/* no need to return anything at all */
- return;
+ return panic;
default:
- syserr("554 5.3.0 savemail: bogus errormode x%x\n",
+ syserr("554 5.3.0 savemail: bogus errormode x%x",
e->e_errormode);
state = ESM_MAIL;
break;
@@ -151,7 +151,7 @@ savemail(e, sendbody)
bitset(EF_RESPONSE, e->e_parent->e_flags))
{
/* got an error sending a response -- can it */
- return;
+ return panic;
}
state = ESM_POSTMASTER;
}
@@ -159,7 +159,7 @@ savemail(e, sendbody)
while (state != ESM_DONE)
{
if (tTd(6, 5))
- dprintf(" state %d\n", state);
+ sm_dprintf(" state %d\n", state);
switch (state)
{
@@ -178,29 +178,41 @@ savemail(e, sendbody)
*/
p = ttypath();
- if (p == NULL || freopen(p, "w", stdout) == NULL)
+ if (p == NULL || sm_io_reopen(SmFtStdio,
+ SM_TIME_DEFAULT,
+ p, SM_IO_WRONLY, NULL,
+ smioout) == NULL)
{
state = ESM_MAIL;
break;
}
expand("\201n", buf, sizeof buf, e);
- printf("\r\nMessage from %s...\r\n", buf);
- printf("Errors occurred while sending mail.\r\n");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\r\nMessage from %s...\r\n", buf);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Errors occurred while sending mail.\r\n");
if (e->e_xfp != NULL)
{
(void) bfrewind(e->e_xfp);
- printf("Transcript follows:\r\n");
- while (fgets(buf, sizeof buf, e->e_xfp) != NULL &&
- !ferror(stdout))
- (void) fputs(buf, stdout);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Transcript follows:\r\n");
+ while (sm_io_fgets(e->e_xfp, SM_TIME_DEFAULT,
+ buf, sizeof buf) != NULL &&
+ !sm_io_error(smioout))
+ (void) sm_io_fputs(smioout,
+ SM_TIME_DEFAULT,
+ buf);
}
else
{
- syserr("Cannot open %s", queuename(e, 'x'));
- printf("Transcript of session is unavailable.\r\n");
+ syserr("Cannot open %s",
+ queuename(e, XSCRPT_LETTER));
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Transcript of session is unavailable.\r\n");
}
- printf("Original message will be saved in dead.letter.\r\n");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Original message will be saved in dead.letter.\r\n");
state = ESM_DEADLETTER;
break;
@@ -225,32 +237,23 @@ savemail(e, sendbody)
if (ExitStat == EX_CONFIG || ExitStat == EX_SOFTWARE)
{
- (void) sendtolist("postmaster",
- NULLADDR, &e->e_errorqueue, 0, e);
+ (void) sendtolist("postmaster", NULLADDR,
+ &e->e_errorqueue, 0, e);
}
if (!emptyaddr(&e->e_from))
{
char from[TOBUFSIZE];
- if (strlen(e->e_from.q_paddr) >= sizeof from)
+ if (sm_strlcpy(from, e->e_from.q_paddr,
+ sizeof from) >= sizeof from)
{
state = ESM_POSTMASTER;
break;
}
- (void) strlcpy(from, e->e_from.q_paddr,
- sizeof from);
- if (!DontPruneRoutes && pruneroute(from))
- {
- ADDRESS *a;
-
- for (a = e->e_errorqueue; a != NULL;
- a = a->q_next)
- {
- if (sameaddr(a, &e->e_from))
- a->q_state = QS_DUPLICATE;
- }
- }
+ if (!DontPruneRoutes)
+ (void) pruneroute(from);
+
(void) sendtolist(from, NULLADDR,
&e->e_errorqueue, 0, e);
}
@@ -297,6 +300,17 @@ savemail(e, sendbody)
q = NULL;
expand(DoubleBounceAddr, buf, sizeof buf, e);
+
+ /*
+ ** Just drop it on the floor if DoubleBounceAddr
+ ** expands to an empty string.
+ */
+
+ if (*buf == '\0')
+ {
+ state = ESM_DONE;
+ break;
+ }
if (sendtolist(buf, NULLADDR, &q, 0, e) <= 0)
{
syserr("553 5.3.0 cannot parse %s!", buf);
@@ -332,9 +346,10 @@ savemail(e, sendbody)
{
if (e->e_from.q_home != NULL)
p = e->e_from.q_home;
- else if ((pw = sm_getpwnam(e->e_from.q_user)) != NULL &&
- *pw->pw_dir != '\0')
- p = pw->pw_dir;
+ else if (sm_mbdb_lookup(e->e_from.q_user, &user)
+ == EX_OK &&
+ *user.mbdb_homedir != '\0')
+ p = user.mbdb_homedir;
}
if (p == NULL || e->e_dfp == NULL)
{
@@ -344,11 +359,11 @@ savemail(e, sendbody)
}
/* we have a home directory; write dead.letter */
- define('z', p, e);
+ macdefine(&e->e_macro, A_TEMP, 'z', p);
/* get the sender for the UnixFromLine */
p = macvalue('g', e);
- define('g', e->e_sender, e);
+ macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
expand("\201z/dead.letter", buf, sizeof buf, e);
sff = SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
@@ -365,11 +380,11 @@ savemail(e, sendbody)
if (Verbose > 0)
message("Saved message in %s", buf);
Verbose = oldverb;
- define('g', p, e);
+ macdefine(&e->e_macro, A_PERM, 'g', p);
state = ESM_DONE;
break;
}
- define('g', p, e);
+ macdefine(&e->e_macro, A_PERM, 'g', p);
state = ESM_MAIL;
break;
@@ -409,15 +424,15 @@ savemail(e, sendbody)
/* get the sender for the UnixFromLine */
p = macvalue('g', e);
- define('g', e->e_sender, e);
+ macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
putfromline(&mcibuf, e);
(*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER);
(*e->e_putbody)(&mcibuf, e, NULL);
- putline("\n", &mcibuf);
- (void) fflush(fp);
- if (ferror(fp) ||
- fclose(fp) < 0)
+ putline("\n", &mcibuf); /* XXX EOL from FileMailer? */
+ (void) sm_io_flush(fp, SM_TIME_DEFAULT);
+ if (sm_io_error(fp) ||
+ sm_io_close(fp, SM_TIME_DEFAULT) < 0)
state = ESM_PANIC;
else
{
@@ -435,23 +450,26 @@ savemail(e, sendbody)
DeadLetterDrop);
state = ESM_DONE;
}
- define('g', p, e);
+ macdefine(&e->e_macro, A_PERM, 'g', p);
break;
default:
syserr("554 5.3.5 savemail: unknown state %d", state);
-
/* FALLTHROUGH */
case ESM_PANIC:
/* leave the locked queue & transcript files around */
loseqfile(e, "savemail panic");
+ panic = true;
errno = 0;
- syserr("!554 savemail: cannot save rejected email anywhere");
+ syserr("554 savemail: cannot save rejected email anywhere");
+ state = ESM_DONE;
+ break;
}
}
+ return panic;
}
- /*
+/*
** RETURNTOSENDER -- return a message to the sender with an error.
**
** Parameters:
@@ -468,12 +486,11 @@ savemail(e, sendbody)
** else -- some error.
**
** Side Effects:
-** Returns the current message to the sender via
-** mail.
+** Returns the current message to the sender via mail.
*/
#define MAXRETURNS 6 /* max depth of returning messages */
-#define ERRORFUDGE 100 /* nominal size of error message text */
+#define ERRORFUDGE 1024 /* nominal size of error message text */
int
returntosender(msg, returnq, flags, e)
@@ -498,13 +515,13 @@ returntosender(msg, returnq, flags, e)
if (tTd(6, 1))
{
- dprintf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%lx, returnq=",
- msg, returndepth, (u_long) e);
- printaddr(returnq, TRUE);
+ sm_dprintf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%p, returnq=",
+ msg, returndepth, e);
+ printaddr(returnq, true);
if (tTd(6, 20))
{
- dprintf("Sendq=");
- printaddr(e->e_sendqueue, TRUE);
+ sm_dprintf("Sendq=");
+ printaddr(e->e_sendqueue, true);
}
}
@@ -518,32 +535,32 @@ returntosender(msg, returnq, flags, e)
return 0;
}
- define('g', e->e_sender, e);
- define('u', NULL, e);
+ macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
+ macdefine(&e->e_macro, A_PERM, 'u', NULL);
/* initialize error envelope */
- ee = newenvelope(&errenvelope, e);
- define('a', "\201b", ee);
- define('r', "", ee);
- define('s', "localhost", ee);
- define('_', "localhost", ee);
+ ee = newenvelope(&errenvelope, e, sm_rpool_new_x(NULL));
+ macdefine(&ee->e_macro, A_PERM, 'a', "\201b");
+ macdefine(&ee->e_macro, A_PERM, 'r', "");
+ macdefine(&ee->e_macro, A_PERM, 's', "localhost");
+ macdefine(&ee->e_macro, A_PERM, '_', "localhost");
#if SASL
- define(macid("{auth_type}", NULL), "", ee);
- define(macid("{auth_authen}", NULL), "", ee);
- define(macid("{auth_author}", NULL), "", ee);
- define(macid("{auth_ssf}", NULL), "", ee);
+ macdefine(&ee->e_macro, A_PERM, macid("{auth_type}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{auth_authen}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{auth_author}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{auth_ssf}"), "");
#endif /* SASL */
#if STARTTLS
- define(macid("{cert_issuer}", NULL), "", ee);
- define(macid("{cert_subject}", NULL), "", ee);
- define(macid("{cipher_bits}", NULL), "", ee);
- define(macid("{cipher}", NULL), "", ee);
- define(macid("{tls_version}", NULL), "", ee);
- define(macid("{verify}", NULL), "", ee);
+ macdefine(&ee->e_macro, A_PERM, macid("{cert_issuer}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{cert_subject}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{cipher_bits}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{cipher}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{tls_version}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{verify}"), "");
# if _FFR_TLS_1
- define(macid("{alg_bits}", NULL), "", ee);
- define(macid("{cn_issuer}", NULL), "", ee);
- define(macid("{cn_subject}", NULL), "", ee);
+ macdefine(&ee->e_macro, A_PERM, macid("{alg_bits}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{cn_issuer}"), "");
+ macdefine(&ee->e_macro, A_PERM, macid("{cn_subject}"), "");
# endif /* _FFR_TLS_1 */
#endif /* STARTTLS */
@@ -567,12 +584,21 @@ returntosender(msg, returnq, flags, e)
}
ee->e_sendqueue = returnq;
- ee->e_msgsize = ERRORFUDGE;
+ ee->e_msgsize = 0;
if (bitset(RTSF_SEND_BODY, flags) &&
!bitset(PRIV_NOBODYRETN, PrivacyFlags))
- ee->e_msgsize += e->e_msgsize;
+ ee->e_msgsize = ERRORFUDGE + e->e_msgsize;
else
ee->e_flags |= EF_NO_BODY_RETN;
+
+ if (!setnewqueue(ee))
+ {
+ syserr("554 5.3.0 returntosender: cannot select queue for %s",
+ returnq->q_paddr);
+ ExitStat = EX_UNAVAILABLE;
+ returndepth--;
+ return -1;
+ }
initsys(ee);
#if NAMED_BIND
@@ -591,7 +617,7 @@ returntosender(msg, returnq, flags, e)
ee->e_nrcpts++;
if (q->q_alias == NULL)
- addheader("To", q->q_paddr, 0, &ee->e_header);
+ addheader("To", q->q_paddr, 0, ee);
}
if (LogLevel > 5)
@@ -604,72 +630,69 @@ returntosender(msg, returnq, flags, e)
p = "postmaster notify";
else
p = "DSN";
- sm_syslog(LOG_INFO, e->e_id,
- "%s: %s: %s",
+ sm_syslog(LOG_INFO, e->e_id, "%s: %s: %s",
ee->e_id, p, shortenstring(msg, MAXSHORTSTR));
}
if (SendMIMEErrors)
{
- addheader("MIME-Version", "1.0", 0, &ee->e_header);
-
- (void) snprintf(buf, sizeof buf, "%s.%ld/%.100s",
- ee->e_id, (long) curtime(), MyHostName);
- ee->e_msgboundary = newstr(buf);
- (void) snprintf(buf, sizeof buf,
+ addheader("MIME-Version", "1.0", 0, ee);
+ (void) sm_snprintf(buf, sizeof buf, "%s.%ld/%.100s",
+ ee->e_id, (long)curtime(), MyHostName);
+ ee->e_msgboundary = sm_rpool_strdup_x(ee->e_rpool, buf);
+ (void) sm_snprintf(buf, sizeof buf,
#if DSN
"multipart/report; report-type=delivery-status;\n\tboundary=\"%s\"",
#else /* DSN */
"multipart/mixed; boundary=\"%s\"",
#endif /* DSN */
ee->e_msgboundary);
- addheader("Content-Type", buf, 0, &ee->e_header);
+ addheader("Content-Type", buf, 0, ee);
p = hvalue("Content-Transfer-Encoding", e->e_header);
- if (p != NULL && strcasecmp(p, "binary") != 0)
+ if (p != NULL && sm_strcasecmp(p, "binary") != 0)
p = NULL;
if (p == NULL && bitset(EF_HAS8BIT, e->e_flags))
p = "8bit";
if (p != NULL)
- addheader("Content-Transfer-Encoding",
- p, 0, &ee->e_header);
+ addheader("Content-Transfer-Encoding", p, 0, ee);
}
if (strncmp(msg, "Warning:", 8) == 0)
{
- addheader("Subject", msg, 0, &ee->e_header);
+ addheader("Subject", msg, 0, ee);
p = "warning-timeout";
}
else if (strncmp(msg, "Postmaster warning:", 19) == 0)
{
- addheader("Subject", msg, 0, &ee->e_header);
+ addheader("Subject", msg, 0, ee);
p = "postmaster-warning";
}
else if (strcmp(msg, "Return receipt") == 0)
{
- addheader("Subject", msg, 0, &ee->e_header);
+ addheader("Subject", msg, 0, ee);
p = "return-receipt";
}
else if (bitset(RTSF_PM_BOUNCE, flags))
{
- snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Postmaster notify: see transcript for details");
- addheader("Subject", buf, 0, &ee->e_header);
+ addheader("Subject", buf, 0, ee);
p = "postmaster-notification";
}
else
{
- snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Returned mail: see transcript for details");
- addheader("Subject", buf, 0, &ee->e_header);
+ addheader("Subject", buf, 0, ee);
p = "failure";
}
- (void) snprintf(buf, sizeof buf, "auto-generated (%s)", p);
- addheader("Auto-Submitted", buf, 0, &ee->e_header);
+ (void) sm_snprintf(buf, sizeof buf, "auto-generated (%s)", p);
+ addheader("Auto-Submitted", buf, 0, ee);
/* fake up an address header for the from person */
expand("\201n", buf, sizeof buf, e);
if (parseaddr(buf, &ee->e_from,
- RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL)
+ RF_COPYALL|RF_SENDERADDR, '\0', NULL, e, false) == NULL)
{
syserr("553 5.3.5 Can't parse myself!");
ExitStat = EX_SOFTWARE;
@@ -682,18 +705,19 @@ returntosender(msg, returnq, flags, e)
/* push state into submessage */
CurEnv = ee;
- define('f', "\201n", ee);
- define('x', "Mail Delivery Subsystem", ee);
- eatheader(ee, TRUE);
+ macdefine(&ee->e_macro, A_PERM, 'f', "\201n");
+ macdefine(&ee->e_macro, A_PERM, 'x', "Mail Delivery Subsystem");
+ eatheader(ee, true, true);
/* mark statistics */
- markstats(ee, NULLADDR, FALSE);
+ markstats(ee, NULLADDR, STATS_NORMAL);
/* actually deliver the error message */
sendall(ee, SM_DELIVER);
/* restore state */
- dropenvelope(ee, TRUE);
+ dropenvelope(ee, true, false);
+ sm_rpool_free(ee->e_rpool);
CurEnv = oldcur;
returndepth--;
@@ -708,7 +732,7 @@ returntosender(msg, returnq, flags, e)
}
return -1;
}
- /*
+/*
** ERRBODY -- output the body of an error message.
**
** Typically this is a copy of the transcript plus a copy of the
@@ -717,7 +741,7 @@ returntosender(msg, returnq, flags, e)
** Parameters:
** mci -- the mailer connection information.
** e -- the envelope we are working in.
-** separator -- any possible MIME separator.
+** separator -- any possible MIME separator (unused).
**
** Returns:
** none
@@ -737,9 +761,10 @@ errbody(mci, e, separator)
bool sendbody;
bool pm_notify;
int save_errno;
- register FILE *xfile;
+ register SM_FILE_T *xfile;
char *p;
register ADDRESS *q = NULL;
+ char actual[MAXLINE];
char buf[MAXLINE];
if (bitset(MCIF_INHEADER, mci->mci_flags))
@@ -762,7 +787,7 @@ errbody(mci, e, separator)
{
putline("This is a MIME-encapsulated message", mci);
putline("", mci);
- (void) snprintf(buf, sizeof buf, "--%s", e->e_msgboundary);
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "--", e->e_msgboundary);
putline(buf, mci);
putline("", mci);
}
@@ -771,10 +796,10 @@ errbody(mci, e, separator)
** Output introductory information.
*/
- pm_notify = FALSE;
+ pm_notify = false;
p = hvalue("subject", e->e_header);
if (p != NULL && strncmp(p, "Postmaster ", 11) == 0)
- pm_notify = TRUE;
+ pm_notify = true;
else
{
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
@@ -796,8 +821,9 @@ errbody(mci, e, separator)
mci);
putline("", mci);
}
- snprintf(buf, sizeof buf, "The original message was received at %s",
- arpadate(ctime(&e->e_parent->e_ctime)));
+ (void) sm_snprintf(buf, sizeof buf,
+ "The original message was received at %s",
+ arpadate(ctime(&e->e_parent->e_ctime)));
putline(buf, mci);
expand("from \201_", buf, sizeof buf, e->e_parent);
putline(buf, mci);
@@ -805,7 +831,8 @@ errbody(mci, e, separator)
/* include id in postmaster copies */
if (pm_notify && e->e_parent->e_id != NULL)
{
- snprintf(buf, sizeof buf, "with id %s", e->e_parent->e_id);
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "with id ",
+ e->e_parent->e_id);
putline(buf, mci);
}
putline("", mci);
@@ -829,13 +856,14 @@ errbody(mci, e, separator)
xfile = safefopen(ErrMsgFile, O_RDONLY, 0444, sff);
if (xfile != NULL)
{
- while (fgets(buf, sizeof buf, xfile) != NULL)
+ while (sm_io_fgets(xfile, SM_TIME_DEFAULT, buf,
+ sizeof buf) != NULL)
{
translate_dollars(buf);
expand(buf, buf, sizeof buf, e);
putline(buf, mci);
}
- (void) fclose(xfile);
+ (void) sm_io_close(xfile, SM_TIME_DEFAULT);
putline("\n", mci);
}
}
@@ -851,7 +879,8 @@ errbody(mci, e, separator)
** Output message introduction
*/
- printheader = TRUE;
+ /* permanent fatal errors */
+ printheader = true;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
if (!QS_IS_BADADDR(q->q_state) ||
@@ -862,35 +891,39 @@ errbody(mci, e, separator)
{
putline(" ----- The following addresses had permanent fatal errors -----",
mci);
- printheader = FALSE;
+ printheader = false;
}
- snprintf(buf, sizeof buf, "%s",
- shortenstring(q->q_paddr, MAXSHORTSTR));
+ (void) sm_strlcpy(buf, shortenstring(q->q_paddr, MAXSHORTSTR),
+ sizeof buf);
putline(buf, mci);
if (q->q_rstatus != NULL)
{
- snprintf(buf, sizeof buf, " (reason: %s)",
- shortenstring(exitstat(q->q_rstatus),
- MAXSHORTSTR));
+ (void) sm_snprintf(buf, sizeof buf,
+ " (reason: %s)",
+ shortenstring(exitstat(q->q_rstatus),
+ MAXSHORTSTR));
putline(buf, mci);
}
if (q->q_alias != NULL)
{
- snprintf(buf, sizeof buf, " (expanded from: %s)",
- shortenstring(q->q_alias->q_paddr,
- MAXSHORTSTR));
+ (void) sm_snprintf(buf, sizeof buf,
+ " (expanded from: %s)",
+ shortenstring(q->q_alias->q_paddr,
+ MAXSHORTSTR));
putline(buf, mci);
}
}
if (!printheader)
putline("", mci);
- printheader = TRUE;
+ /* transient non-fatal errors */
+ printheader = true;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
if (QS_IS_BADADDR(q->q_state) ||
!bitset(QPRIMARY, q->q_flags) ||
+ !bitset(QBYNDELAY, q->q_flags) ||
!bitset(QDELAYED, q->q_flags))
continue;
@@ -898,30 +931,37 @@ errbody(mci, e, separator)
{
putline(" ----- The following addresses had transient non-fatal errors -----",
mci);
- printheader = FALSE;
+ printheader = false;
}
- snprintf(buf, sizeof buf, "%s",
- shortenstring(q->q_paddr, MAXSHORTSTR));
+ (void) sm_strlcpy(buf, shortenstring(q->q_paddr, MAXSHORTSTR),
+ sizeof buf);
putline(buf, mci);
if (q->q_alias != NULL)
{
- snprintf(buf, sizeof buf, " (expanded from: %s)",
- shortenstring(q->q_alias->q_paddr,
- MAXSHORTSTR));
+ (void) sm_snprintf(buf, sizeof buf,
+ " (expanded from: %s)",
+ shortenstring(q->q_alias->q_paddr,
+ MAXSHORTSTR));
putline(buf, mci);
}
}
if (!printheader)
putline("", mci);
- printheader = TRUE;
+ /* successful delivery notifications */
+ printheader = true;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
if (QS_IS_BADADDR(q->q_state) ||
!bitset(QPRIMARY, q->q_flags) ||
+ bitset(QBYNDELAY, q->q_flags) ||
bitset(QDELAYED, q->q_flags))
continue;
+ else if (bitset(QBYNRELAY, q->q_flags))
+ p = "Deliver-By notify: relayed";
+ else if (bitset(QBYTRACE, q->q_flags))
+ p = "Deliver-By trace: relayed";
else if (!bitset(QPINGONSUCCESS, q->q_flags))
continue;
else if (bitset(QRELAYED, q->q_flags))
@@ -942,17 +982,18 @@ errbody(mci, e, separator)
{
putline(" ----- The following addresses had successful delivery notifications -----",
mci);
- printheader = FALSE;
+ printheader = false;
}
- snprintf(buf, sizeof buf, "%s (%s)",
+ (void) sm_snprintf(buf, sizeof buf, "%s (%s)",
shortenstring(q->q_paddr, MAXSHORTSTR), p);
putline(buf, mci);
if (q->q_alias != NULL)
{
- snprintf(buf, sizeof buf, " (expanded from: %s)",
- shortenstring(q->q_alias->q_paddr,
- MAXSHORTSTR));
+ (void) sm_snprintf(buf, sizeof buf,
+ " (expanded from: %s)",
+ shortenstring(q->q_alias->q_paddr,
+ MAXSHORTSTR));
putline(buf, mci);
}
}
@@ -963,7 +1004,7 @@ errbody(mci, e, separator)
** Output transcript of errors
*/
- (void) fflush(stdout);
+ (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
if (e->e_parent->e_xfp == NULL)
{
putline(" ----- Transcript of session is unavailable -----\n",
@@ -971,16 +1012,17 @@ errbody(mci, e, separator)
}
else
{
- printheader = TRUE;
+ printheader = true;
(void) bfrewind(e->e_parent->e_xfp);
if (e->e_xfp != NULL)
- (void) fflush(e->e_xfp);
- while (fgets(buf, sizeof buf, e->e_parent->e_xfp) != NULL)
+ (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT);
+ while (sm_io_fgets(e->e_parent->e_xfp, SM_TIME_DEFAULT, buf,
+ sizeof buf) != NULL)
{
if (printheader)
putline(" ----- Transcript of session follows -----\n",
mci);
- printheader = FALSE;
+ printheader = false;
putline(buf, mci);
}
}
@@ -993,10 +1035,8 @@ errbody(mci, e, separator)
if (e->e_msgboundary != NULL)
{
- time_t now = curtime();
-
putline("", mci);
- (void) snprintf(buf, sizeof buf, "--%s", e->e_msgboundary);
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "--", e->e_msgboundary);
putline(buf, mci);
putline("Content-Type: message/delivery-status", mci);
putline("", mci);
@@ -1008,15 +1048,15 @@ errbody(mci, e, separator)
/* original envelope id from MAIL FROM: line */
if (e->e_parent->e_envid != NULL)
{
- (void) snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Original-Envelope-Id: %.800s",
xuntextify(e->e_parent->e_envid));
putline(buf, mci);
}
/* Reporting-MTA: is us (required) */
- (void) snprintf(buf, sizeof buf, "Reporting-MTA: dns; %.800s",
- MyHostName);
+ (void) sm_snprintf(buf, sizeof buf,
+ "Reporting-MTA: dns; %.800s", MyHostName);
putline(buf, mci);
/* DSN-Gateway: not relevant since we are not translating */
@@ -1028,24 +1068,35 @@ errbody(mci, e, separator)
if (e->e_parent->e_from.q_mailer == NULL ||
(p = e->e_parent->e_from.q_mailer->m_mtatype) == NULL)
p = "dns";
- (void) snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Received-From-MTA: %s; %.800s",
p, RealHostName);
putline(buf, mci);
}
/* Arrival-Date: -- when it arrived here */
- (void) snprintf(buf, sizeof buf, "Arrival-Date: %s",
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "Arrival-Date: ",
arpadate(ctime(&e->e_parent->e_ctime)));
putline(buf, mci);
+ /* Deliver-By-Date: -- when it should have been delivered */
+ if (IS_DLVR_BY(e->e_parent))
+ {
+ time_t dbyd;
+
+ dbyd = e->e_parent->e_ctime + e->e_parent->e_deliver_by;
+ (void) sm_strlcpyn(buf, sizeof buf, 2,
+ "Deliver-By-Date: ",
+ arpadate(ctime(&dbyd)));
+ putline(buf, mci);
+ }
+
/*
** Output per-address information.
*/
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
- register ADDRESS *r;
char *action;
if (QS_IS_BADADDR(q->q_state))
@@ -1071,6 +1122,12 @@ errbody(mci, e, separator)
action = "expanded (to multi-recipient alias)";
else if (bitset(QDELAYED, q->q_flags))
action = "delayed";
+ else if (bitset(QBYTRACE, q->q_flags))
+ action = "relayed (Deliver-By trace mode)";
+ else if (bitset(QBYNDELAY, q->q_flags))
+ action = "delayed (Deliver-By notify mode)";
+ else if (bitset(QBYNRELAY, q->q_flags))
+ action = "relayed (Deliver-By notify mode)";
else
continue;
@@ -1079,63 +1136,15 @@ errbody(mci, e, separator)
/* Original-Recipient: -- passed from on high */
if (q->q_orcpt != NULL)
{
- (void) snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Original-Recipient: %.800s",
q->q_orcpt);
putline(buf, mci);
}
- /* Final-Recipient: -- the name from the RCPT command */
- p = e->e_parent->e_from.q_mailer->m_addrtype;
- if (p == NULL)
- p = "rfc822";
- for (r = q; r->q_alias != NULL; r = r->q_alias)
- continue;
- if (strcasecmp(p, "rfc822") != 0)
- {
- (void) snprintf(buf, sizeof buf,
- "Final-Recipient: %s; %.800s",
- r->q_mailer->m_addrtype,
- r->q_user);
- }
- else if (strchr(r->q_user, '@') != NULL)
- {
- (void) snprintf(buf, sizeof buf,
- "Final-Recipient: %s; %.800s",
- p, r->q_user);
- }
- else if (strchr(r->q_paddr, '@') != NULL)
- {
- char *qp;
- bool b;
-
- qp = r->q_paddr;
- /* strip brackets from address */
- b = FALSE;
- if (*qp == '<')
- {
- b = qp[strlen(qp) - 1] == '>';
- if (b)
- qp[strlen(qp) - 1] = '\0';
- qp++;
- }
- (void) snprintf(buf, sizeof buf,
- "Final-Recipient: %s; %.800s",
- p, qp);
- /* undo damage */
- if (b)
- qp[strlen(qp)] = '>';
- }
- else
- {
- (void) snprintf(buf, sizeof buf,
- "Final-Recipient: %s; %.700s@%.100s",
- p, r->q_user, MyHostName);
- }
- putline(buf, mci);
-
- /* X-Actual-Recipient: -- the real problem address */
- if (r != q && q->q_user[0] != '\0')
+ /* Figure out actual recipient */
+ actual[0] = '\0';
+ if (q->q_user[0] != '\0')
{
if (q->q_mailer != NULL &&
q->q_mailer->m_addrtype != NULL)
@@ -1143,25 +1152,59 @@ errbody(mci, e, separator)
else
p = "rfc822";
- if (strcasecmp(p, "rfc822") == 0 &&
+ if (sm_strcasecmp(p, "rfc822") == 0 &&
strchr(q->q_user, '@') == NULL)
{
- (void) snprintf(buf, sizeof buf,
- "X-Actual-Recipient: %s; %.700s@%.100s",
- p, q->q_user,
- MyHostName);
+ (void) sm_snprintf(actual,
+ sizeof actual,
+ "%s; %.700s@%.100s",
+ p, q->q_user,
+ MyHostName);
}
else
{
- (void) snprintf(buf, sizeof buf,
- "X-Actual-Recipient: %s; %.800s",
- p, q->q_user);
+ (void) sm_snprintf(actual,
+ sizeof actual,
+ "%s; %.800s",
+ p, q->q_user);
}
+ }
+
+ /* Final-Recipient: -- the name from the RCPT command */
+ if (q->q_finalrcpt == NULL)
+ {
+ /* should never happen */
+ sm_syslog(LOG_ERR, e->e_id,
+ "returntosender: q_finalrcpt is NULL");
+
+ /* try to fall back to the actual recipient */
+ if (actual[0] != '\0')
+ q->q_finalrcpt = sm_rpool_strdup_x(e->e_rpool,
+ actual);
+ }
+
+ if (q->q_finalrcpt != NULL)
+ {
+ (void) sm_snprintf(buf, sizeof buf,
+ "Final-Recipient: %s",
+ q->q_finalrcpt);
+ putline(buf, mci);
+ }
+
+ /* X-Actual-Recipient: -- the real problem address */
+ if (actual[0] != '\0' &&
+ q->q_finalrcpt != NULL &&
+ strcmp(actual, q->q_finalrcpt) != 0)
+ {
+ (void) sm_snprintf(buf, sizeof buf,
+ "X-Actual-Recipient: %s",
+ actual);
putline(buf, mci);
}
/* Action: -- what happened? */
- snprintf(buf, sizeof buf, "Action: %s", action);
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "Action: ",
+ action);
putline(buf, mci);
/* Status: -- what _really_ happened? */
@@ -1173,7 +1216,7 @@ errbody(mci, e, separator)
p = "4.0.0";
else
p = "2.0.0";
- snprintf(buf, sizeof buf, "Status: %s", p);
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "Status: ", p);
putline(buf, mci);
/* Remote-MTA: -- who was I talking to? */
@@ -1182,7 +1225,7 @@ errbody(mci, e, separator)
if (q->q_mailer == NULL ||
(p = q->q_mailer->m_mtatype) == NULL)
p = "dns";
- (void) snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Remote-MTA: %s; %.800s",
p, q->q_statmta);
p = &buf[strlen(buf) - 1];
@@ -1197,7 +1240,7 @@ errbody(mci, e, separator)
p = q->q_mailer->m_diagtype;
if (p == NULL)
p = "smtp";
- (void) snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Diagnostic-Code: %s; %.800s",
p, q->q_rstatus);
putline(buf, mci);
@@ -1205,9 +1248,9 @@ errbody(mci, e, separator)
/* Last-Attempt-Date: -- fine granularity */
if (q->q_statdate == (time_t) 0L)
- q->q_statdate = now;
- (void) snprintf(buf, sizeof buf,
- "Last-Attempt-Date: %s",
+ q->q_statdate = curtime();
+ (void) sm_strlcpyn(buf, sizeof buf, 2,
+ "Last-Attempt-Date: ",
arpadate(ctime(&q->q_statdate)));
putline(buf, mci);
@@ -1218,8 +1261,8 @@ errbody(mci, e, separator)
xdate = e->e_parent->e_ctime +
TimeOuts.to_q_return[e->e_parent->e_timeoutclass];
- snprintf(buf, sizeof buf,
- "Will-Retry-Until: %s",
+ (void) sm_strlcpyn(buf, sizeof buf, 2,
+ "Will-Retry-Until: ",
arpadate(ctime(&xdate)));
putline(buf, mci);
}
@@ -1246,25 +1289,25 @@ errbody(mci, e, separator)
}
else
{
- (void) snprintf(buf, sizeof buf, "--%s",
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "--",
e->e_msgboundary);
putline(buf, mci);
- (void) snprintf(buf, sizeof buf, "Content-Type: %s",
+ (void) sm_strlcpyn(buf, sizeof buf, 2, "Content-Type: ",
sendbody ? "message/rfc822"
: "text/rfc822-headers");
putline(buf, mci);
p = hvalue("Content-Transfer-Encoding",
e->e_parent->e_header);
- if (p != NULL && strcasecmp(p, "binary") != 0)
+ if (p != NULL && sm_strcasecmp(p, "binary") != 0)
p = NULL;
if (p == NULL &&
bitset(EF_HAS8BIT, e->e_parent->e_flags))
p = "8bit";
if (p != NULL)
{
- (void) snprintf(buf, sizeof buf,
+ (void) sm_snprintf(buf, sizeof buf,
"Content-Transfer-Encoding: %s",
p);
putline(buf, mci);
@@ -1290,11 +1333,12 @@ errbody(mci, e, separator)
if (e->e_msgboundary != NULL)
{
putline("", mci);
- (void) snprintf(buf, sizeof buf, "--%s--", e->e_msgboundary);
+ (void) sm_strlcpyn(buf, sizeof buf, 3, "--", e->e_msgboundary,
+ "--");
putline(buf, mci);
}
putline("", mci);
- (void) fflush(mci->mci_out);
+ (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT);
/*
** Cleanup and exit
@@ -1303,7 +1347,7 @@ errbody(mci, e, separator)
if (errno != 0)
syserr("errbody: I/O error");
}
- /*
+/*
** SMTPTODSN -- convert SMTP to DSN status code
**
** Parameters:
@@ -1311,6 +1355,11 @@ errbody(mci, e, separator)
**
** Returns:
** The DSN version of the status code.
+**
+** Storage Management:
+** smtptodsn() returns a pointer to a character string literal,
+** which will remain valid forever, and thus does not need to
+** be copied. Current code relies on this property.
*/
char *
@@ -1368,7 +1417,7 @@ smtptodsn(smtpstat)
return "4.0.0";
return "5.0.0";
}
- /*
+/*
** XTEXTIFY -- take regular text and turn it into DSN-style xtext
**
** Parameters:
@@ -1405,6 +1454,11 @@ xtextify(t, taboo)
nbogus++;
l++;
}
+ if (nbogus < 0)
+ {
+ /* since nbogus is ssize_t and wrapped, 2 * size_t would wrap */
+ syserr("!xtextify string too long");
+ }
if (nbogus == 0)
return t;
l += nbogus * 2 + 1;
@@ -1413,8 +1467,8 @@ xtextify(t, taboo)
if (l > bplen)
{
if (bp != NULL)
- sm_free(bp);
- bp = xalloc(l);
+ sm_free(bp); /* XXX */
+ bp = sm_pmalloc_x(l);
bplen = l;
}
@@ -1437,7 +1491,7 @@ xtextify(t, taboo)
*p = '\0';
return bp;
}
- /*
+/*
** XUNTEXTIFY -- take xtext and turn it into plain text
**
** Parameters:
@@ -1466,7 +1520,7 @@ xuntextify(t)
if (l > bplen)
{
if (bp != NULL)
- sm_free(bp);
+ sm_free(bp); /* XXX */
bp = xalloc(l);
bplen = l;
}
@@ -1517,7 +1571,7 @@ xuntextify(t)
*p = '\0';
return bp;
}
- /*
+/*
** XTEXTOK -- check if a string is legal xtext
**
** Xtext is used in Delivery Status Notifications. The spec was
@@ -1528,8 +1582,8 @@ xuntextify(t)
** s -- the string to check.
**
** Returns:
-** TRUE -- if 's' is legal xtext.
-** FALSE -- if it has any illegal characters in it.
+** true -- if 's' is legal xtext.
+** false -- if it has any illegal characters in it.
*/
bool
@@ -1544,17 +1598,17 @@ xtextok(s)
{
c = *s++;
if (!isascii(c) || !isxdigit(c))
- return FALSE;
+ return false;
c = *s++;
if (!isascii(c) || !isxdigit(c))
- return FALSE;
+ return false;
}
else if (c < '!' || c > '~' || c == '=')
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
- /*
+/*
** PRUNEROUTE -- prune an RFC-822 source route
**
** Trims down a source route to the last internet-registered hop.
@@ -1564,8 +1618,8 @@ xtextok(s)
** addr -- the address
**
** Returns:
-** TRUE -- address was modified
-** FALSE -- address could not be pruned
+** true -- address was modified
+** false -- address could not be pruned
**
** Side Effects:
** modifies addr in-place
@@ -1578,6 +1632,7 @@ pruneroute(addr)
#if NAMED_BIND
char *start, *at, *comma;
char c;
+ int braclev;
int rcode;
int i;
char hostbuf[BUFSIZ];
@@ -1585,37 +1640,60 @@ pruneroute(addr)
/* check to see if this is really a route-addr */
if (*addr != '<' || addr[1] != '@' || addr[strlen(addr) - 1] != '>')
- return FALSE;
- start = strchr(addr, ':');
+ return false;
+
+ /*
+ ** Can't simply find the first ':' is the address might be in the
+ ** form: "<@[IPv6:::1]:user@host>" and the first ':' in inside
+ ** the IPv6 address.
+ */
+
+ start = addr;
+ braclev = 0;
+ while (*start != '\0')
+ {
+ if (*start == ':' && braclev <= 0)
+ break;
+ else if (*start == '[')
+ braclev++;
+ else if (*start == ']' && braclev > 0)
+ braclev--;
+ start++;
+ }
+ if (braclev > 0 || *start != ':')
+ return false;
+
at = strrchr(addr, '@');
- if (start == NULL || at == NULL || at < start)
- return FALSE;
+ if (at == NULL || at < start)
+ return false;
/* slice off the angle brackets */
i = strlen(at + 1);
- if (i >= (SIZE_T) sizeof hostbuf)
- return FALSE;
- (void) strlcpy(hostbuf, at + 1, sizeof hostbuf);
+ if (i >= sizeof hostbuf)
+ return false;
+ (void) sm_strlcpy(hostbuf, at + 1, sizeof hostbuf);
hostbuf[i - 1] = '\0';
- while (start)
+ while (start != NULL)
{
- if (getmxrr(hostbuf, mxhosts, NULL, FALSE, &rcode) > 0)
+ if (getmxrr(hostbuf, mxhosts, NULL, false,
+ &rcode, true, NULL) > 0)
{
- (void) strlcpy(addr + 1, start + 1, strlen(addr) - 1);
- return TRUE;
+ (void) sm_strlcpy(addr + 1, start + 1,
+ strlen(addr) - 1);
+ return true;
}
c = *start;
*start = '\0';
comma = strrchr(addr, ',');
if (comma != NULL && comma[1] == '@' &&
- strlen(comma + 2) < (SIZE_T) sizeof hostbuf)
- (void) strlcpy(hostbuf, comma + 2, sizeof hostbuf);
+ strlen(comma + 2) < sizeof hostbuf)
+ (void) sm_strlcpy(hostbuf, comma + 2, sizeof hostbuf);
else
comma = NULL;
*start = c;
start = comma;
}
#endif /* NAMED_BIND */
- return FALSE;
+ return false;
}
OpenPOWER on IntegriCloud