aboutsummaryrefslogtreecommitdiff
path: root/gacopyz
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-03-08 23:32:04 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-03-08 23:32:04 +0000
commitf340b89d4722df3bce8a5bef92ab3b5f76241868 (patch)
tree5b105c54d0feba10adcc885152803f8ad601095a /gacopyz
parentdc86c84d43e819bcdfd5b2b69a9db486f56b4e16 (diff)
downloadmailfromd-f340b89d4722df3bce8a5bef92ab3b5f76241868.tar.gz
mailfromd-f340b89d4722df3bce8a5bef92ab3b5f76241868.tar.bz2
Implement mail from and rcpt to
git-svn-id: file:///svnroot/mailfromd/trunk@1282 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'gacopyz')
-rw-r--r--gacopyz/gacopyz.h24
-rw-r--r--gacopyz/gacopyz_priv.h12
-rw-r--r--gacopyz/io.c8
-rw-r--r--gacopyz/log.c15
-rw-r--r--gacopyz/server.c439
5 files changed, 443 insertions, 55 deletions
diff --git a/gacopyz/gacopyz.h b/gacopyz/gacopyz.h
index 251810bd..5d46f5cb 100644
--- a/gacopyz/gacopyz.h
+++ b/gacopyz/gacopyz.h
@@ -292,17 +292,17 @@ void *gacopyz_getpriv (SMFICTX *ctx);
/* Logging (extensions) */
#define GACOPYZ_VBUFSIZE 69
-size_t gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], char *buf,
+size_t gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], const char *buf,
size_t size);
void gacopyz_log(gacopyz_conn_t conn, int level, char *fmt, ...);
void gacopyz_io_log(gacopyz_iod_t iod, int level, char *fmt, ...);
void gacopyz_logmsg(int level, char *fmt, ...);
-void _gacopyz_logdump(int logmask, int level, char *pfx, char *buf,
+void _gacopyz_logdump(int logmask, int level, const char *pfx, const char *buf,
size_t size);
-void gacopyz_logdump(gacopyz_conn_t conn, int level, char *pfx,
- char *buf, size_t size);
-void gacopyz_io_logdump(gacopyz_iod_t iod, int level, char *pfx,
- char *buf, size_t size);
+void gacopyz_logdump(gacopyz_conn_t conn, int level, const char *pfx,
+ const char *buf, size_t size);
+void gacopyz_io_logdump(gacopyz_iod_t iod, int level, const char *pfx,
+ const char *buf, size_t size);
void gacopyz_set_logger(void (*)(int, char *, va_list));
void gacopyz_stderr_log_printer(int level, char *fmt, va_list ap);
@@ -317,6 +317,9 @@ int gacopyz_srv_find_macro (gacopyz_srv_t srv, const char *name,
const char **pval);
int gacopyz_srv_define_macro (gacopyz_srv_t srv,
const char *name, const char *value);
+int gacopyz_srv_define_macro0 (gacopyz_srv_t srv,
+ const char *name, const char *value,
+ int overwrite);
int gacopyz_srv_del_macro (gacopyz_srv_t srv, const char *name);
int gacopyz_srv_clear_macros (gacopyz_srv_t srv);
int gacopyz_srv_iterate_macros (gacopyz_srv_t srv,
@@ -340,11 +343,18 @@ int gacopyz_srv_abort (gacopyz_srv_t p);
int gacopyz_srv_close (gacopyz_srv_t p);
int gacopyz_srv_data (gacopyz_srv_t p);
+int gacopyz_srv_onerror(gacopyz_srv_t srv, int code);
int gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr);
int gacopyz_srv_set_version(gacopyz_srv_t srv, int version);
int gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto);
int gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts);
-int gacopyz_srv_set_timeout(gacopyz_srv_t srv, time_t t);
+
+int gacopyz_srv_set_all_timeouts(gacopyz_srv_t srv, struct timeval *tvp);
+int gacopyz_srv_set_timeout(gacopyz_srv_t srv, unsigned n,
+ struct timeval *tvp);
+int gacopyz_srv_set_timeout_sec(gacopyz_srv_t srv, unsigned n, time_t t);
+
+void gacopyz_srv_reply (gacopyz_srv_t srv, char **msg, size_t *size);
#ifdef __cplusplus
}
diff --git a/gacopyz/gacopyz_priv.h b/gacopyz/gacopyz_priv.h
index 19d72468..54bc4fcf 100644
--- a/gacopyz/gacopyz_priv.h
+++ b/gacopyz/gacopyz_priv.h
@@ -72,15 +72,21 @@ typedef unsigned long gacopyz_uint32_t;
void (*__gacopyz_log_printer)(int, char *, va_list);
+#define GACOPYZ_TO_WRITE 0 /* Timeout for sending information */
+#define GACOPYZ_TO_READ 1 /* Timeout waiting for a response */
+#define GACOPYZ_TO_EOM 2 /* Timeout for ACK/NAK to EOM */
+#define GACOPYZ_TO_CONNECT 3 /* Timeout for connect() */
+#define GACOPYZ_TO_COUNT 4
+
struct gacopyz_iod {
int sd;
- struct timeval timeout;
+ struct timeval timeout[GACOPYZ_TO_COUNT];
int logmask;
};
int _gacopyz_read (gacopyz_iod_t iod, char *buf, size_t size);
-int _gacopyz_write(gacopyz_iod_t iod, char *buf, size_t size);
+int _gacopyz_write(gacopyz_iod_t iod, const char *buf, size_t size);
int gacopyz_send_command(gacopyz_iod_t iod,
- int cmd, void *data, size_t size);
+ int cmd, const void *data, size_t size);
int gacopyz_read_command(gacopyz_iod_t iod, unsigned char *cmd,
size_t *pcount, char **pbuf, size_t *psize);
diff --git a/gacopyz/io.c b/gacopyz/io.c
index 29cdb390..d258800c 100644
--- a/gacopyz/io.c
+++ b/gacopyz/io.c
@@ -34,7 +34,7 @@ _gacopyz_read (gacopyz_iod_t iod, char *buf, size_t size)
FD_SET(iod->sd, &rset);
FD_SET(iod->sd, &xset);
- to = iod->timeout;
+ to = iod->timeout[GACOPYZ_TO_READ];
res = select(iod->sd + 1, &rset, NULL, &xset, &to);
if (res == 0) {
@@ -84,7 +84,7 @@ _gacopyz_read (gacopyz_iod_t iod, char *buf, size_t size)
}
int
-_gacopyz_write(gacopyz_iod_t iod, char *buf, size_t size)
+_gacopyz_write(gacopyz_iod_t iod, const char *buf, size_t size)
{
int rc = MI_SUCCESS;
@@ -99,7 +99,7 @@ _gacopyz_write(gacopyz_iod_t iod, char *buf, size_t size)
FD_SET(iod->sd, &wset);
FD_SET(iod->sd, &xset);
- to = iod->timeout;
+ to = iod->timeout[GACOPYZ_TO_READ];
res = select(iod->sd + 1, NULL, &wset, &xset, &to);
if (res == 0) {
@@ -157,7 +157,7 @@ union header {
};
int
-gacopyz_send_command(gacopyz_iod_t iod, int cmd, void *data, size_t size)
+gacopyz_send_command(gacopyz_iod_t iod, int cmd, const void *data, size_t size)
{
int rc;
union header header;
diff --git a/gacopyz/log.c b/gacopyz/log.c
index 43eae63e..05144568 100644
--- a/gacopyz/log.c
+++ b/gacopyz/log.c
@@ -95,7 +95,7 @@ gacopyz_io_log(gacopyz_iod_t iod, int level, char *fmt, ...)
}
size_t
-gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], char *buf, size_t size)
+gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], const char *buf, size_t size)
{
char *p = vbuf;
char *q = vbuf + 51;
@@ -105,7 +105,7 @@ gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], char *buf, size_t size)
for (i = 0; i < 16; i++) {
unsigned c;
if (j < size) {
- c = *(unsigned char*)buf++;
+ c = *(const unsigned char*)buf++;
j++;
} else
c = 0;
@@ -124,7 +124,8 @@ gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], char *buf, size_t size)
}
void
-_gacopyz_logdump(int logmask, int level, char *pfx, char *buf, size_t size)
+_gacopyz_logdump(int logmask, int level, const char *pfx,
+ const char *buf, size_t size)
{
if (logmask & SMI_LOG_MASK(level)) {
char vbuf[GACOPYZ_VBUFSIZE];
@@ -139,15 +140,15 @@ _gacopyz_logdump(int logmask, int level, char *pfx, char *buf, size_t size)
}
void
-gacopyz_logdump(gacopyz_conn_t conn, int level, char *pfx,
- char *buf, size_t size)
+gacopyz_logdump(gacopyz_conn_t conn, int level, const char *pfx,
+ const char *buf, size_t size)
{
return _gacopyz_logdump(conn->logmask, level, pfx, buf, size);
}
void
-gacopyz_io_logdump(gacopyz_iod_t iod, int level, char *pfx,
- char *buf, size_t size)
+gacopyz_io_logdump(gacopyz_iod_t iod, int level, const char *pfx,
+ const char *buf, size_t size)
{
return _gacopyz_logdump(iod->logmask, level, pfx, buf, size);
}
diff --git a/gacopyz/server.c b/gacopyz/server.c
index 944952a3..0b6c2aaa 100644
--- a/gacopyz/server.c
+++ b/gacopyz/server.c
@@ -25,9 +25,14 @@ struct gacopyz_macro_def {
};
enum gacopyz_srv_state {
- srv_init,
- srv_connected,
- srv_ready
+ srv_init, /* Initialized but not connected */
+ srv_connected, /* Initialized and connected to the client */
+ srv_ready, /* Ready for processing requests */
+ srv_msgproc, /* Processing a message */
+ srv_done, /* Finished processing a message */
+ srv_closed, /* Finished and closed */
+ srv_disabled, /* Disabled for any further requests */
+ srv_error, /* Some error ocurred */
};
struct gacopyz_srv {
@@ -38,32 +43,41 @@ struct gacopyz_srv {
size_t ndefs;
size_t maxdefs;
gacopyz_uint32_t source_addr;
+ int onerror;
+
int version;
int acts;
int proto;
char *buf;
size_t bufsize;
+
+ char *resp_ptr;
+ size_t resp_size;
};
static struct gacopyz_macro_def *
-find_def(gacopyz_srv_t srv, const char *name)
+find_def(gacopyz_srv_t srv, const char *name, size_t len)
{
size_t i;
for (i = 0; i < srv->ndefs; i++)
- if (strcmp(srv->def[i].name, name) == 0)
+ if (strncmp(srv->def[i].name, name, len) == 0)
return &srv->def[i];
return NULL;
}
static int
-add_def(gacopyz_srv_t srv, const char *name, const char *value)
+add_def(gacopyz_srv_t srv, const char *name, size_t len,
+ const char *value, int overwrite)
{
struct gacopyz_macro_def *def;
- if (def = find_def(srv, name))
- free(def->value);
- else {
+ if (def = find_def(srv, name, len)) {
+ if (overwrite)
+ free(def->value);
+ else
+ return MI_SUCCESS;
+ } else {
if (srv->ndefs == srv->maxdefs) {
size_t maxdefs = srv->maxdefs + 64;
def = realloc(srv->def,
@@ -74,19 +88,23 @@ add_def(gacopyz_srv_t srv, const char *name, const char *value)
srv->def = def;
}
def = srv->def + srv->ndefs++;
- def->name = strdup(name);
+ def->name = malloc(len + 1);
+ if (!def->name)
+ return MI_FAILURE;
+ memcpy(def->name, name, len);
+ def->name[len] = 0;
}
def->value = strdup(value);
- if (!def->name || !def->value)
+ if (!def->value)
/* FIXME: Remove this entry from srv->dev */
return MI_FAILURE;
return MI_SUCCESS;
}
void
-del_def(gacopyz_srv_t srv, const char *name)
+del_def(gacopyz_srv_t srv, const char *name, size_t len)
{
- struct gacopyz_macro_def *def = find_def(srv, name);
+ struct gacopyz_macro_def *def = find_def(srv, name, len);
size_t n;
if (!def)
@@ -98,17 +116,97 @@ del_def(gacopyz_srv_t srv, const char *name)
memmove(def, def + 1,
sizeof(srv->def[0]) *(srv->ndefs - (def - srv->def)));
}
+
+static int
+srv_ensure_space(gacopyz_srv_t srv, size_t size)
+{
+ if (size > srv->bufsize) {
+ char *p = realloc(srv->buf, size);
+ if (!p) {
+ gacopyz_io_log(&srv->iod,
+ SMI_LOG_FATAL,
+ "Not enough memory");
+ return 1;
+ }
+ srv->buf = p;
+ srv->bufsize = size;
+ }
+ return 0;
+}
+
+size_t
+macro_size(gacopyz_srv_t srv)
+{
+ size_t i;
+ size_t size = 0;
+ struct gacopyz_macro_def *def;
+
+ for (i = 0, def = srv->def; i < srv->ndefs; i++, def++) {
+ size_t len = strlen(def->name);
+ size += len;
+ if (len > 1 && def->name[0] != '{')
+ size += 2; /* for {} */
+ size += 1 + strlen (def->value) + 1;
+ }
+ return size;
+}
+
+int
+srv_format_macros(gacopyz_srv_t srv, unsigned char cmd, size_t *psize)
+{
+ size_t i;
+ char *p;
+ size_t size = macro_size(srv) + 2;
+ struct gacopyz_macro_def *def;
+
+ if (srv_ensure_space(srv, size))
+ return MI_FAILURE;
+
+ p = srv->buf;
+ *p++ = cmd;
+ for (i = 0, def = srv->def; i < srv->ndefs; i++, def++) {
+ size_t len = strlen(def->name);
+ if (len > 1 && def->name[0] != '{') {
+ *p++ = '{';
+ memcpy(p, def->name, len);
+ p += len;
+ *p++ = '}';
+ *p++ = 0;
+ } else {
+ len++;
+ memcpy(p, def->name, len);
+ p += len;
+ }
+ len = strlen(def->value) + 1;
+ memcpy(p, def->value, len);
+ p += len;
+ }
+ *p = 0;
+ *psize = size;
+ return MI_SUCCESS;
+}
+
+#define GETNAMELEN(name, len) \
+ len = strlen(name); \
+ if (name[0] == '{' && name[len-1] == '}') { \
+ name++; \
+ len -= 2; \
+ }
+
+
int
gacopyz_srv_find_macro(gacopyz_srv_t srv, const char *name, const char **pval)
{
struct gacopyz_macro_def *def;
-
+ size_t len;
+
if (!srv)
return MI_FAILURE;
-
- def = find_def(srv, name);
+
+ GETNAMELEN(name, len);
+ def = find_def(srv, name, len);
if (def) {
*pval = def->value;
return MI_SUCCESS;
@@ -117,20 +215,35 @@ gacopyz_srv_find_macro(gacopyz_srv_t srv, const char *name, const char **pval)
}
int
-gacopyz_srv_define_macro(gacopyz_srv_t srv,
- const char *name, const char *value)
+gacopyz_srv_define_macro0(gacopyz_srv_t srv,
+ const char *name, const char *value,
+ int overwrite)
{
+ size_t len;
+
if (!srv)
return MI_FAILURE;
- return add_def(srv, name, value);
+
+ GETNAMELEN(name, len);
+
+ return add_def(srv, name, len, value, overwrite);
+}
+
+int
+gacopyz_srv_define_macro(gacopyz_srv_t srv,
+ const char *name, const char *value)
+{
+ return gacopyz_srv_define_macro0(srv, name, value, 1);
}
int
gacopyz_srv_del_macro(gacopyz_srv_t srv, const char *name)
{
+ size_t len;
if (!srv)
return MI_FAILURE;
- del_def(srv, name);
+ GETNAMELEN(name, len);
+ del_def(srv, name, len);
return MI_SUCCESS;
}
@@ -181,15 +294,20 @@ gacopyz_srv_count_macros(gacopyz_srv_t srv, size_t *count)
int
gacopyz_srv_create(gacopyz_srv_t *p, unsigned logmask)
{
+ int i;
gacopyz_srv_t srv = calloc(1, sizeof(*srv));
if (!srv)
return MI_FAILURE;
srv->iod.sd = -1;
srv->iod.logmask = logmask;
- srv->iod.timeout.tv_usec = 0;
- srv->iod.timeout.tv_sec = 5;
+ /* FIXME Set default timeouts */
+ for (i = 0; i < GACOPYZ_TO_COUNT; i++) {
+ srv->iod.timeout[i].tv_usec = 0;
+ srv->iod.timeout[i].tv_sec = 5;
+ }
srv->state = srv_init;
srv->source_addr = INADDR_ANY;
+ srv->onerror = SMFIR_TEMPFAIL;
srv->version = SMFI_VERSION;
srv->proto = SMFI_V2_PROT;
srv->acts = SMFI_V2_ACTS;
@@ -198,15 +316,49 @@ gacopyz_srv_create(gacopyz_srv_t *p, unsigned logmask)
}
int
-gacopyz_srv_set_timeout(gacopyz_srv_t srv, time_t t)
+gacopyz_srv_onerror(gacopyz_srv_t srv, int code)
+{
+ if (!srv)
+ return MI_FAILURE;
+ switch (code) {
+ case SMFIR_CONTINUE:
+ case SMFIR_DISCARD:
+ case SMFIR_REJECT:
+ case SMFIR_TEMPFAIL:
+ case SMFIR_SHUTDOWN:
+ srv->onerror = code;
+ return MI_SUCCESS;
+ }
+ return MI_FAILURE;
+}
+
+int
+gacopyz_srv_set_all_timeouts(gacopyz_srv_t srv, struct timeval *tvp)
{
if (!srv)
return MI_FAILURE;
- srv->iod.timeout.tv_usec = 0;
- srv->iod.timeout.tv_sec = t;
+ memcpy(srv->iod.timeout, tvp, sizeof srv->iod.timeout);
return MI_SUCCESS;
}
-
+
+int
+gacopyz_srv_set_timeout(gacopyz_srv_t srv, unsigned n, struct timeval *tvp)
+{
+ if (!srv || n >= GACOPYZ_TO_COUNT)
+ return MI_FAILURE;
+ srv->iod.timeout[n] = *tvp;
+ return MI_SUCCESS;
+}
+
+int
+gacopyz_srv_set_timeout_sec(gacopyz_srv_t srv, unsigned n, time_t t)
+{
+ struct timeval tv;
+ tv.tv_usec = 0;
+ tv.tv_sec = t;
+ return gacopyz_srv_set_timeout(srv, n, &tv);
+}
+
int
gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr)
{
@@ -521,44 +673,261 @@ gacopyz_srv_negotiate(gacopyz_srv_t srv)
return MI_SUCCESS;
}
+static struct command_assoc {
+ unsigned char cmd;
+ int pflag;
+ const char *action;
+ const char *code;
+} command_tab[] = {
+ { SMFIC_CONNECT, SMFIP_NOCONNECT, "connect", "554" },
+ { SMFIC_HELO, SMFIP_NOHELO, "helo", "550" },
+ { SMFIC_MAIL, SMFIP_NOMAIL, "mail", "550 5.7.1" },
+ { SMFIC_RCPT, SMFIP_NORCPT, "rcpt", "550 5.7.1" },
+ { SMFIC_HEADER, SMFIP_NOHDRS, "header", "550 5.7.1" },
+ { SMFIC_BODY, SMFIP_NOBODY, "body", "554 5.7.1" },
+ { SMFIC_EOH, SMFIP_NOEOH, "eoh", "550 5.7.1" },
+ { SMFIC_UNKNOWN, SMFIP_NOUNKNOWN, "unknown", "550 5.7.1" },
+ { SMFIC_DATA, SMFIP_NODATA, "data", "550 5.7.1" },
+ { 0, 0, "default", "550 5.7.1" }
+};
+
+static struct command_assoc *
+find_cmd_assoc(unsigned char cmd)
+{
+ struct command_assoc *cp;
+ for (cp = command_tab; cp->cmd; cp++)
+ if (cp->cmd == cmd)
+ break;
+ return cp;
+}
+
+#define is_rfc822_reject_code(s) \
+ (((s)[0] == '4' || (s)[0] == '5') \
+ && isascii((s)[1]) && isdigit((s)[1]) \
+ && isascii((s)[2]) && isdigit((s)[2]))
+
+#define DEFREPLY "Command rejected"
+
+static void
+verify_reply(gacopyz_srv_t srv, size_t size, const char *reject_code)
+{
+ if (size < 3 || !is_rfc822_reject_code(srv->buf)) {
+ if (srv_ensure_space(srv,
+ strlen(reject_code) + 1
+ + sizeof(DEFREPLY)))
+ abort();
+ strcpy(srv->buf, reject_code);
+ strcat(srv->buf, " ");
+ strcat(srv->buf, DEFREPLY);
+ }
+}
+
+int
+gacopyz_srv_send_macros(gacopyz_srv_t srv, unsigned char cmd)
+{
+ size_t size;
+ if (srv_format_macros(srv, cmd, &size))
+ return MI_FAILURE;
+ if (gacopyz_send_command(&srv->iod, SMFIC_MACRO,
+ srv->buf, size))
+ return MI_FAILURE;
+ return MI_SUCCESS;
+}
+
+int
+gacopyz_srv_send_command(gacopyz_srv_t srv, unsigned char cmd,
+ const void *data, size_t datasize)
+{
+ unsigned char rcmd;
+ size_t size;
+ struct command_assoc *cp;
+
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_send_command: size=%lu, cmd=%c",
+ datasize, cmd);
+
+ cp = find_cmd_assoc(cmd);
+
+ srv->resp_ptr = NULL;
+ srv->resp_size = 0;
+ if (cp->pflag && (srv->proto & cp->pflag))
+ return SMFIR_CONTINUE;
+
+ if (gacopyz_srv_send_macros(srv, cmd))
+ return srv->onerror;
+
+ if (gacopyz_send_command(&srv->iod, cmd, data, datasize))
+ return srv->onerror;
+
+ if (cmd == SMFIC_HEADER && (srv->proto & SMFIP_NOHREPL))
+ return SMFIR_CONTINUE;
+
+ if (gacopyz_read_command(&srv->iod, &rcmd, &size,
+ &srv->buf, &srv->bufsize))
+ return srv->onerror;
+
+ switch (rcmd) {
+ case SMFIR_REPLYCODE:
+ verify_reply(srv, size, cp->code);
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, reject=%s",
+ cp->action, srv->buf);
+ srv->resp_ptr = srv->buf;
+ srv->resp_size = size;
+ break;
+
+ case SMFIR_REJECT:
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, reject",
+ cp->action);
+ break;
+
+ case SMFIR_DISCARD:
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, discard",
+ cp->action);
+ srv->state = srv_disabled;
+ break;
+
+ case SMFIR_TEMPFAIL:
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, tempfail",
+ cp->action);
+ break;
+
+ case SMFIR_ACCEPT:
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, accept",
+ cp->action);
+ srv->state = srv_disabled;
+ break;
+
+ case SMFIR_CONTINUE:
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "action=%s, continue",
+ cp->action);
+ break;
+
+ default:
+ gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
+ "action=%s, bogus response=%c",
+ cp->action, rcmd);
+ /*FIXME: Change to error state */
+ srv->state = srv_error;
+ rcmd = srv->onerror;
+ break;
+ }
+
+ return rcmd;
+}
+
+#define not_implemented(srv) ( \
+ gacopyz_io_log(&srv->iod, SMI_LOG_FATAL, \
+ "%s:%d: %s not implemented!!!", \
+ __FILE__, __LINE__, __FUNCTION__), \
+ MI_FAILURE \
+)
+
+void
+gacopyz_srv_reply (gacopyz_srv_t srv, char **msg, size_t *size)
+{
+ *msg = srv->resp_ptr;
+ *size = srv->resp_size;
+}
+
int
gacopyz_srv_abort(gacopyz_srv_t srv)
{
+ return not_implemented(srv);
}
int
-gacopyz_srv_helo(gacopyz_srv_t p, const char *domain)
+gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain)
{
+ return gacopyz_srv_send_command(srv, SMFIC_HELO,
+ domain, strlen(domain) + 1);
}
+static int
+format_argv(gacopyz_srv_t srv, char **argv, char **buf, size_t *psize)
+{
+ size_t len;
+ char **ap;
+ char *p;
+
+ for (len = 1, ap = argv; *ap; ap++)
+ len += strlen(*ap) + 1;
+
+ *buf = malloc(len);
+ if (!*buf) {
+ gacopyz_io_log(&srv->iod,
+ SMI_LOG_FATAL,
+ "Not enough memory");
+ return 1;
+ }
+
+ for (p = *buf, ap = argv; *ap; ap++) {
+ size_t len = strlen(*ap) + 1;
+ memcpy(p, *ap, len);
+ p += len;
+ }
+ *p = 0;
+ *psize = len;
+ return 0;
+}
+
int
-gacopyz_srv_envfrom(gacopyz_srv_t p, char **argv)
+gacopyz_srv_envfrom(gacopyz_srv_t srv, char **argv)
{
+ int rc;
+ size_t size;
+ char *buf;
+ if (!srv)
+ return MI_FAILURE;
+ if (format_argv(srv, argv, &buf, &size))
+ return MI_FAILURE;
+ rc = gacopyz_srv_send_command(srv, SMFIC_MAIL, buf, size);
+ free (buf);
+ return rc;
}
int
-gacopyz_srv_envrcpt(gacopyz_srv_t p, char **argv)
+gacopyz_srv_envrcpt(gacopyz_srv_t srv, char **argv)
{
+ int rc;
+ size_t size;
+ char *buf;
+ if (!srv)
+ return MI_FAILURE;
+ if (format_argv(srv, argv, &buf, &size))
+ return MI_FAILURE;
+ rc = gacopyz_srv_send_command(srv, SMFIC_RCPT, buf, size);
+ free (buf);
+ return rc;
}
int
-gacopyz_srv_header(gacopyz_srv_t p, char *name, char *value)
+gacopyz_srv_header(gacopyz_srv_t srv, char *name, char *value)
{
+ return not_implemented(srv);
}
int
-gacopyz_srv_eoh(gacopyz_srv_t p)
+gacopyz_srv_eoh(gacopyz_srv_t srv)
{
+ return not_implemented(srv);
}
int
-gacopyz_srv_body(gacopyz_srv_t p, unsigned char *str, size_t size)
+gacopyz_srv_body(gacopyz_srv_t srv, unsigned char *str, size_t size)
{
+ return not_implemented(srv);
}
int
-gacopyz_srv_eom(gacopyz_srv_t p)
+gacopyz_srv_eom(gacopyz_srv_t srv)
{
+ return not_implemented(srv);
}
int
@@ -566,10 +935,12 @@ gacopyz_srv_close(gacopyz_srv_t srv)
{
close (srv->iod.sd);
srv->state = srv_init;
+ return MI_SUCCESS;
}
int
-gacopyz_srv_data(gacopyz_srv_t p)
+gacopyz_srv_data(gacopyz_srv_t srv)
{
+ return not_implemented(srv);
}

Return to:

Send suggestions and report system problems to the System administrator.