#include <h/netsec.h>
#include <sys/socket.h>
+#include "sbr/base64.h"
/*
* This module implements an interface to SendMail very similar
static int sm_addrs = 0;
static int sm_child = NOTOK;
static int sm_debug = 0;
-static int sm_nl = TRUE;
+static bool sm_nl = true;
static int sm_verbose = 0;
static netsec_context *nsc = NULL;
const char *);
static int rclient (char *, char *, char **);
-static int sm_ierror (const char *fmt, ...);
+static int sm_ierror (const char *fmt, ...) CHECK_PRINTF(1, 2);
static int sm_nerror (char *);
-static int smtalk (int time, char *fmt, ...);
+static int smtalk (int time, char *fmt, ...) CHECK_PRINTF(2, 3);
static int sm_wstream (char *, int);
static int smhear (void);
-static char *EHLOset (char *);
+static char *EHLOset (char *) PURE;
static int sm_sasl_callback(enum sasl_message_type, unsigned const char *,
unsigned int, unsigned char **, unsigned int *,
- char **);
+ void *, char **);
int
sm_init (char *client, char *server, char *port, int watch, int verbose,
char *errstr, *chosen_server;
if (watch)
- verbose = TRUE;
+ verbose = true;
sm_verbose = verbose;
sm_debug = debug;
if (sasl) {
if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback,
- &errstr) != OK)
+ NULL, &errstr) != OK)
return sm_nerror(errstr);
}
char *vec[15], *errstr;
if (watch)
- verbose = TRUE;
+ verbose = true;
sm_verbose = verbose;
sm_debug = debug;
if (sasl) {
if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback,
- &errstr) != OK)
+ NULL, &errstr) != OK)
return sm_nerror(errstr);
}
return sm_ierror ("no pipes");
}
- for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++)
- sleep (5);
-
+ sm_child = fork();
switch (sm_child) {
case NOTOK:
close (pdo[0]);
execvp (sendmail, vec);
fprintf (stderr, "unable to exec ");
perror (sendmail);
- _exit (-1); /* NOTREACHED */
+ _exit(1); /* NOTREACHED */
default:
SIGNAL (SIGPIPE, SIG_IGN);
close (pdi[1]);
close (pdo[0]);
- netsec_set_fd(nsc, pdi[i], pdo[1]);
+ netsec_set_fd(nsc, pdi[0], pdo[1]);
netsec_set_timeout(nsc, SM_OPEN);
result = smhear ();
switch (result) {
{
switch (smtalk (SM_DATA, "DATA")) {
case 354:
- sm_nl = TRUE;
+ sm_nl = true;
return RP_OK;
case 451:
int
sm_wtxt (char *buffer, int len)
{
- int result;
+ int result, snoopstate;
+
+ if ((snoopstate = netsec_get_snoop(nsc)))
+ netsec_set_snoop(nsc, 0);
result = sm_wstream (buffer, len);
- return (result == NOTOK ? RP_BHST : RP_OK);
+ netsec_set_snoop(nsc, snoopstate);
+ return result == NOTOK ? RP_BHST : RP_OK;
}
int
sm_wtend (void)
{
- if (sm_wstream ((char *) NULL, 0) == NOTOK)
+ int snoopstate;
+
+ if ((snoopstate = netsec_get_snoop(nsc)))
+ netsec_set_snoop(nsc, 0);
+
+ if (sm_wstream(NULL, 0) == NOTOK)
return RP_BHST;
+ /*
+ * Because snoop output now happens at flush time, if we are using snoop
+ * we force an extra flush here. While this introduces some extra network
+ * traffic, we're only doing it when snoop is in effect so I think it's
+ * reasonable.
+ */
+
+ if (snoopstate) {
+ char *errstr;
+ if (netsec_flush(nsc, &errstr) != OK) {
+ sm_nerror(errstr);
+ return RP_BHST;
+ }
+ netsec_set_snoop(nsc, snoopstate);
+ }
+
switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) {
case 250:
case 251:
status = OK;
}
- return (status ? RP_BHST : RP_OK);
+ return status ? RP_BHST : RP_OK;
}
for (bp = buffer; bp && len > 0; bp++, len--) {
switch (*bp) {
case '\n':
- sm_nl = TRUE;
+ sm_nl = true;
if (netsec_write(nsc, "\r", 1, &errstr) != OK) {
sm_nerror(errstr);
return NOTOK;
/* FALLTHRU */
default:
- sm_nl = FALSE;
+ sm_nl = false;
}
if (netsec_write(nsc, bp, 1, &errstr) != OK) {
sm_nerror(errstr);
static int
smhear (void)
{
- int i, code, cont, more;
+ int i, code;
+ bool cont, more;
size_t buflen, rc;
unsigned char *bp;
char *rp;
rp = sm_reply.text;
rc = sizeof(sm_reply.text) - 1;
- for (more = FALSE; (buffer = netsec_readline(nsc, &buflen,
+ for (more = false; (buffer = netsec_readline(nsc, &buflen,
&errstr)) != NULL ; ) {
if (doingEHLO
for (; buflen > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, buflen--)
continue;
- cont = FALSE;
+ cont = false;
code = atoi ((char *) bp);
bp += 3, buflen -= 3;
for (; buflen > 0 && isspace (*bp); bp++, buflen--)
continue;
if (buflen > 0 && *bp == '-') {
- cont = TRUE;
+ cont = true;
bp++, buflen--;
for (; buflen > 0 && isspace (*bp); bp++, buflen--)
continue;
if (more) {
if (code != sm_reply.code || cont)
continue;
- more = FALSE;
+ more = false;
} else {
sm_reply.code = code;
more = cont;
}
}
- return 0;
+ return NULL;
}
/*
static int
sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
unsigned int indatalen, unsigned char **outdata,
- unsigned int *outdatalen, char **errstr)
+ unsigned int *outdatalen, void *context, char **errstr)
{
int rc, snoopoffset;
char *mech, *line;
size_t len;
+ NMH_UNUSED(context);
switch (mtype) {
case NETSEC_SASL_START:
snoopoffset = 6 + strlen(mech);
rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data);
free(b64data);
- netsec_set_snoop_callback(nsc, NULL, NULL);
} else {
rc = netsec_printf(nsc, errstr, "AUTH %s\r\n", mech);
}
- if (rc != OK)
+ if (rc != OK) {
+ netsec_set_snoop_callback(nsc, NULL, NULL);
return NOTOK;
+ }
+
+ rc = netsec_flush(nsc, errstr);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
- if (netsec_flush(nsc, errstr) != OK)
+ if (rc != OK)
return NOTOK;
break;
writeBase64raw(indata, indatalen, b64data);
netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL);
rc = netsec_printf(nsc, errstr, "%s\r\n", b64data);
- netsec_set_snoop_callback(nsc, NULL, NULL);
free(b64data);
}
if (rc != OK)
return NOTOK;
- if (netsec_flush(nsc, errstr) != OK)
+ rc = netsec_flush(nsc, errstr);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
+
+ if (rc != OK)
return NOTOK;
break;