aboutsummaryrefslogtreecommitdiff
path: root/gacopyz
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-03-09 22:48:28 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-03-09 22:48:28 +0000
commitb9c5231e13acac4d23d119bf176ee952b9071fe9 (patch)
treec5cc3e281d40c4f0be8f08a6b63b8faa720ea46e /gacopyz
parent4a3b530ab2fb03e3a2d5db84a06d60ece2eafce9 (diff)
downloadmailfromd-b9c5231e13acac4d23d119bf176ee952b9071fe9.tar.gz
mailfromd-b9c5231e13acac4d23d119bf176ee952b9071fe9.tar.bz2
Update
git-svn-id: file:///svnroot/mailfromd/trunk@1284 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'gacopyz')
-rw-r--r--gacopyz/gacopyz.h52
-rw-r--r--gacopyz/gacopyz_priv.h5
-rw-r--r--gacopyz/server.c551
3 files changed, 420 insertions, 188 deletions
diff --git a/gacopyz/gacopyz.h b/gacopyz/gacopyz.h
index 5d46f5cb..90d3607f 100644
--- a/gacopyz/gacopyz.h
+++ b/gacopyz/gacopyz.h
@@ -311,24 +311,27 @@ void gacopyz_syslog_log_printer(int level, char *fmt, va_list ap);
/* Server */
typedef struct gacopyz_srv *gacopyz_srv_t;
-int gacopyz_srv_create(gacopyz_srv_t *p, unsigned logmask);
+int gacopyz_srv_create(gacopyz_srv_t *p, const char *name,
+ const char *portspec, unsigned logmask);
+int gacopyz_srv_create_X(gacopyz_srv_t *p, const char *spec, unsigned logmask);
+
void gacopyz_srv_destroy(gacopyz_srv_t *p);
int gacopyz_srv_find_macro (gacopyz_srv_t srv, const char *name,
const char **pval);
-int gacopyz_srv_define_macro (gacopyz_srv_t srv,
+void 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,
- int (*func) (const char *name,
- const char *value,
- void *data),
- void *data);
-int gacopyz_srv_count_macros (gacopyz_srv_t srv, size_t *count);
-int gacopyz_srv_connect (gacopyz_srv_t srv, const char *port);
+void gacopyz_srv_define_macro0 (gacopyz_srv_t srv,
+ const char *name, const char *value,
+ int overwrite);
+void gacopyz_srv_del_macro (gacopyz_srv_t srv, const char *name);
+void gacopyz_srv_clear_macros (gacopyz_srv_t srv);
+void gacopyz_srv_iterate_macros (gacopyz_srv_t srv,
+ int (*func) (const char *name,
+ const char *value,
+ void *data),
+ void *data);
+void gacopyz_srv_count_macros (gacopyz_srv_t srv, size_t *count);
+int gacopyz_srv_connect (gacopyz_srv_t srv);
int gacopyz_srv_init(gacopyz_srv_t srv);
int gacopyz_srv_helo (gacopyz_srv_t p, const char *domain);
@@ -338,23 +341,38 @@ int gacopyz_srv_header (gacopyz_srv_t p, char *name, char *value);
int gacopyz_srv_eoh (gacopyz_srv_t p);
int gacopyz_srv_body (gacopyz_srv_t p, unsigned char *str, size_t size);
-int gacopyz_srv_eom (gacopyz_srv_t p);
+int gacopyz_srv_eom (gacopyz_srv_t p, unsigned char *str, size_t size);
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);
+void gacopyz_srv_set_memerror(gacopyz_srv_t srv,
+ void (*memerror)(gacopyz_srv_t, const char *,
+ unsigned int));
+
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_all_timeouts(gacopyz_srv_t srv, struct timeval *tvp);
+#define GACOPYZ_WRITE_TIMEOUT 10
+#define GACOPYZ_READ_TIMEOUT 10
+#define GACOPYZ_EOM_TIMEOUT 300
+#define GACOPYZ_CONNECT_TIMEOUT 300
+
+#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
+
+void 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);
+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 046bf76d..9ec99ff2 100644
--- a/gacopyz/gacopyz_priv.h
+++ b/gacopyz/gacopyz_priv.h
@@ -75,11 +75,6 @@ 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;
diff --git a/gacopyz/server.c b/gacopyz/server.c
index c010127a..7f466f61 100644
--- a/gacopyz/server.c
+++ b/gacopyz/server.c
@@ -36,6 +36,8 @@ enum gacopyz_srv_state {
};
struct gacopyz_srv {
+ char *id; /* Server identifier (not used yet) */
+ char *portspec; /* Port spec */
struct gacopyz_iod iod;
enum gacopyz_srv_state state;
unsigned long flags;
@@ -44,7 +46,7 @@ struct gacopyz_srv {
size_t maxdefs;
gacopyz_uint32_t source_addr;
int onerror;
-
+ void (*memerror) (gacopyz_srv_t, const char *, unsigned int);
int version;
int acts;
int proto;
@@ -56,6 +58,29 @@ struct gacopyz_srv {
size_t resp_size;
};
+void
+default_memerror (gacopyz_srv_t srv, const char *file, unsigned int line)
+{
+ gacopyz_io_log(&srv->iod, SMI_LOG_FATAL,
+ "%s:%lu: Not enough memory",
+ file, line);
+ abort();
+}
+
+#define GACOPYZ_ASSERT(e) \
+ if (!(e)) { \
+ fprintf(stderr, "%s:%d: GACOPYZ usage error: assertion failed: %s\n", \
+ __FILE__, __LINE__, #e); \
+ abort(); \
+ }
+
+#define GACOPYZ_ALLOC(srv, expr) do \
+ if (!(expr)) { \
+ srv->memerror(srv, __FILE__, __LINE__); \
+ if (!(expr)) \
+ default_memerror(srv, __FILE__, __LINE__); \
+ } while (0)
+
static struct gacopyz_macro_def *
find_def(gacopyz_srv_t srv, const char *name, size_t len)
{
@@ -66,7 +91,7 @@ find_def(gacopyz_srv_t srv, const char *name, size_t len)
return NULL;
}
-static int
+static void
add_def(gacopyz_srv_t srv, const char *name, size_t len,
const char *value, int overwrite)
{
@@ -75,30 +100,21 @@ add_def(gacopyz_srv_t srv, const char *name, size_t len,
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,
- sizeof(srv->def[0]) * maxdefs);
- if (!def)
- return MI_FAILURE;
+ GACOPYZ_ALLOC(srv,
+ def = realloc(srv->def,
+ sizeof(srv->def[0]) * maxdefs));
srv->maxdefs = maxdefs;
srv->def = def;
}
def = srv->def + srv->ndefs++;
- def->name = malloc(len + 1);
- if (!def->name)
- return MI_FAILURE;
+ GACOPYZ_ALLOC(srv, def->name = malloc(len + 1));
memcpy(def->name, name, len);
def->name[len] = 0;
}
- def->value = strdup(value);
- if (!def->value)
- /* FIXME: Remove this entry from srv->dev */
- return MI_FAILURE;
- return MI_SUCCESS;
+ GACOPYZ_ALLOC(srv, def->value = strdup(value));
}
void
@@ -117,21 +133,15 @@ del_def(gacopyz_srv_t srv, const char *name, size_t len)
sizeof(srv->def[0]) *(srv->ndefs - (def - srv->def)));
}
-static int
+static void
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;
- }
+ char *p;
+ GACOPYZ_ALLOC(srv, p = realloc(srv->buf, size));
srv->buf = p;
srv->bufsize = size;
}
- return 0;
}
size_t
@@ -151,7 +161,7 @@ macro_size(gacopyz_srv_t srv)
return size;
}
-int
+void
srv_format_macros(gacopyz_srv_t srv, unsigned char cmd, size_t *psize)
{
size_t i;
@@ -159,8 +169,7 @@ srv_format_macros(gacopyz_srv_t srv, unsigned char cmd, size_t *psize)
size_t size = macro_size(srv) + 2;
struct gacopyz_macro_def *def;
- if (srv_ensure_space(srv, size))
- return MI_FAILURE;
+ srv_ensure_space(srv, size);
p = srv->buf;
*p++ = cmd;
@@ -183,7 +192,6 @@ srv_format_macros(gacopyz_srv_t srv, unsigned char cmd, size_t *psize)
}
*p = 0;
*psize = size;
- return MI_SUCCESS;
}
@@ -195,15 +203,13 @@ srv_format_macros(gacopyz_srv_t srv, unsigned char cmd, size_t *psize)
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;
+ GACOPYZ_ASSERT(srv);
GETNAMELEN(name, len);
def = find_def(srv, name, len);
@@ -214,56 +220,53 @@ gacopyz_srv_find_macro(gacopyz_srv_t srv, const char *name, const char **pval)
return MI_FAILURE;
}
-int
+void
gacopyz_srv_define_macro0(gacopyz_srv_t srv,
const char *name, const char *value,
int overwrite)
{
size_t len;
-
- if (!srv)
- return MI_FAILURE;
+
+ GACOPYZ_ASSERT(srv);
GETNAMELEN(name, len);
- return add_def(srv, name, len, value, overwrite);
+ add_def(srv, name, len, value, overwrite);
}
-int
+void
gacopyz_srv_define_macro(gacopyz_srv_t srv,
const char *name, const char *value)
{
- return gacopyz_srv_define_macro0(srv, name, value, 1);
+ gacopyz_srv_define_macro0(srv, name, value, 1);
}
-int
+void
gacopyz_srv_del_macro(gacopyz_srv_t srv, const char *name)
{
size_t len;
- if (!srv)
- return MI_FAILURE;
+
+ GACOPYZ_ASSERT(srv);
+
GETNAMELEN(name, len);
del_def(srv, name, len);
- return MI_SUCCESS;
}
-int
+void
gacopyz_srv_clear_macros(gacopyz_srv_t srv)
{
size_t i;
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
for (i = 0; i < srv->ndefs; i++) {
free(srv->def[i].name);
free(srv->def[i].value);
}
srv->ndefs = 0;
- return MI_SUCCESS;
}
-int
+void
gacopyz_srv_iterate_macros(gacopyz_srv_t srv,
int (*func)(const char *name, const char *value,
void *data),
@@ -271,55 +274,279 @@ gacopyz_srv_iterate_macros(gacopyz_srv_t srv,
{
size_t i;
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
for (i = 0; i < srv->ndefs; i++)
if (func(srv->def[i].name, srv->def[i].value, data))
break;
- return MI_SUCCESS;
}
-int
+void
gacopyz_srv_count_macros(gacopyz_srv_t srv, size_t *count)
{
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
*count = srv->ndefs;
- return MI_SUCCESS;
}
+struct timeval default_gacopyz_timeout[GACOPYZ_TO_COUNT] = {
+ { GACOPYZ_WRITE_TIMEOUT, 0 },
+ { GACOPYZ_READ_TIMEOUT, 0 },
+ { GACOPYZ_EOM_TIMEOUT, 0 },
+ { GACOPYZ_CONNECT_TIMEOUT, 0 }
+};
+
int
-gacopyz_srv_create(gacopyz_srv_t *p, unsigned logmask)
+gacopyz_srv_create(gacopyz_srv_t *p, const char *name,
+ const char *portspec, unsigned logmask)
{
int i;
gacopyz_srv_t srv = calloc(1, sizeof(*srv));
+
if (!srv)
return MI_FAILURE;
+ srv->id = strdup(name);
+ srv->portspec = strdup(portspec);
srv->iod.sd = -1;
srv->iod.logmask = logmask;
- /* 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;
- }
+ memcpy (srv->iod.timeout, default_gacopyz_timeout,
+ sizeof srv->iod.timeout);
+
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;
+ srv->memerror = default_memerror;
*p = srv;
return MI_SUCCESS;
}
+static int
+parse_X_spec (const char *spec, char *xspec, char **id, char **port,
+ struct timeval to[], int *onerr, int debug)
+{
+ char *p, *q;
+ int havef = 0, havet = 0;
+
+ p = strtok(xspec, ",");
+ if (!p) {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG, "%s: not a valid X spec",
+ spec);
+ return MI_FAILURE;
+ }
+ if (p[1] != '=') {
+ *id = p;
+ p = strtok(NULL, ",");
+ if (!p) {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec",
+ spec);
+ return MI_FAILURE;
+ }
+ }
+
+ do {
+ while (*p && isspace(*p))
+ p++;
+ if (!*p)
+ break;
+ if (p[1] != '=') {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "missing = near %s",
+ spec, p);
+ return MI_FAILURE;
+ }
+
+ switch (p[0]) {
+ case 'S':
+ if (*port) {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "duplicate field %s",
+ spec, p);
+ return MI_FAILURE;
+ }
+ *port = p + 2;
+ break;
+
+ case 'F':
+ if (havef) {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "duplicate field %s",
+ spec, p);
+ return MI_FAILURE;
+ }
+ havef = 1;
+ if (strlen (p) != 3) {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "invalid field %s",
+ spec, p);
+ return MI_FAILURE;
+ }
+ switch (p[2]) {
+ case 'R':
+ *onerr = SMFIR_REJECT;
+ break;
+
+ case 'T':
+ *onerr = SMFIR_TEMPFAIL;
+ break;
+
+ default:
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "invalid field %s",
+ spec, p);
+ return MI_FAILURE;
+ }
+ break;
+
+ case 'T':
+ if (havet) {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "duplicate field %s",
+ spec, p);
+ return MI_FAILURE;
+ }
+ havet = 1;
+
+ for (q = p + 2; *q; q++) {
+ int n;
+ unsigned long t;
+ char *ep;
+
+ switch (*q) {
+ case 'C':
+ n = GACOPYZ_TO_CONNECT;
+ break;
+
+ case 'S':
+ n = GACOPYZ_TO_WRITE;
+ break;
+
+ case 'R':
+ n = GACOPYZ_TO_READ;
+ break;
+
+ case 'E':
+ n = GACOPYZ_TO_EOM;
+ break;
+
+ default:
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "invalid T field near %s",
+ spec, q);
+ return MI_FAILURE;
+ }
+ if (*++q != ':') {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "invalid T field near %s",
+ spec, q);
+ return MI_FAILURE;
+ }
+ t = strtoul(++q, &ep, 0);
+ switch (*ep) {
+ case 0:
+ case ';':
+ break;
+ case 's':
+ ep++;
+ break;
+ case 'm':
+ t *= 60;
+ ep++;
+ break;
+ default:
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "invalid T field near %s",
+ spec, q);
+ return MI_FAILURE;
+ }
+
+ to[n].tv_sec = t;
+ to[n].tv_usec = 0;
+
+ q = ep;
+
+ if (*q == 0)
+ break;
+ else if (*q != ';') {
+ if (debug)
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "invalid delimiter near %s",
+ spec, q);
+ return MI_FAILURE;
+ }
+ }
+ }
+ } while (p = strtok(NULL, ","));
+ return MI_SUCCESS;
+}
+
int
-gacopyz_srv_onerror(gacopyz_srv_t srv, int code)
+gacopyz_srv_create_X(gacopyz_srv_t *p, const char *spec, unsigned logmask)
{
- if (!srv)
+ int rc;
+ char *xspec = strdup(spec);
+
+ char *id = "default";
+ char *port = NULL;
+ struct timeval to[GACOPYZ_TO_COUNT];
+ int onerr = SMFIR_CONTINUE;
+
+ memcpy(to, default_gacopyz_timeout, sizeof to);
+ if (parse_X_spec(spec, xspec, &id, &port, to, &onerr,
+ logmask & SMI_LOG_MASK(SMI_LOG_DEBUG)) == MI_FAILURE) {
+ free(xspec);
+ return MI_FAILURE;
+ }
+
+ if (!port) {
+ if (logmask & SMI_LOG_MASK(SMI_LOG_DEBUG))
+ gacopyz_logmsg(SMI_LOG_DEBUG,
+ "%s: not a valid X spec, "
+ "missing port",
+ spec);
+ free(xspec);
+ return MI_FAILURE;
+ }
+
+ rc = gacopyz_srv_create(p, id, port, logmask);
+ free(xspec);
+ if (rc)
return MI_FAILURE;
+ gacopyz_srv_set_all_timeouts(*p, to);
+ gacopyz_srv_onerror(*p, onerr);
+ return MI_SUCCESS;
+}
+
+int
+gacopyz_srv_onerror(gacopyz_srv_t srv, int code)
+{
+ GACOPYZ_ASSERT(srv);
+
switch (code) {
case SMFIR_CONTINUE:
case SMFIR_DISCARD:
@@ -332,19 +559,28 @@ gacopyz_srv_onerror(gacopyz_srv_t srv, int code)
return MI_FAILURE;
}
-int
+void
+gacopyz_srv_set_memerror(gacopyz_srv_t srv,
+ void (*memerror)(gacopyz_srv_t, const char *,
+ unsigned int))
+{
+ GACOPYZ_ASSERT(srv);
+ srv->memerror = memerror;
+}
+
+void
gacopyz_srv_set_all_timeouts(gacopyz_srv_t srv, struct timeval *tvp)
{
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
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)
+ GACOPYZ_ASSERT(srv);
+
+ if (n >= GACOPYZ_TO_COUNT)
return MI_FAILURE;
srv->iod.timeout[n] = *tvp;
return MI_SUCCESS;
@@ -362,8 +598,7 @@ gacopyz_srv_set_timeout_sec(gacopyz_srv_t srv, unsigned n, time_t t)
int
gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr)
{
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
srv->source_addr = htonl(addr);
return MI_SUCCESS;
@@ -372,8 +607,7 @@ gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr)
int
gacopyz_srv_set_version(gacopyz_srv_t srv, int version)
{
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
srv->version = version;
return MI_SUCCESS;
@@ -382,8 +616,7 @@ gacopyz_srv_set_version(gacopyz_srv_t srv, int version)
int
gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto)
{
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
srv->proto = proto;
return MI_SUCCESS;
@@ -392,8 +625,7 @@ gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto)
int
gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts)
{
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
srv->acts = acts;
return MI_SUCCESS;
@@ -405,6 +637,8 @@ gacopyz_srv_destroy(gacopyz_srv_t *p)
{
gacopyz_srv_t srv = *p;
gacopyz_srv_clear_macros(srv);
+ free(srv->portspec);
+ free(srv->id);
free(srv->def);
free(srv->buf);
free(srv);
@@ -412,8 +646,7 @@ gacopyz_srv_destroy(gacopyz_srv_t *p)
}
static int
-srv_connect(gacopyz_srv_t srv, const char *cstr,
- char *proto, char *port, char *path)
+srv_connect(gacopyz_srv_t srv, char *proto, char *port, char *path)
{
union {
struct sockaddr sa;
@@ -431,7 +664,7 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"invalid connection type: %s; "
"port is meaningless for UNIX sockets",
- cstr);
+ srv->portspec);
return -1;
}
@@ -474,7 +707,7 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"invalid connection type: %s; "
"missing port number",
- cstr);
+ srv->portspec);
return -1;
}
@@ -484,7 +717,7 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"invalid connection type: %s; "
"bad port number",
- cstr);
+ srv->portspec);
return -1;
}
pnum = htons(pnum);
@@ -494,7 +727,7 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"invalid connection type: %s; "
"unknown port name",
- cstr);
+ srv->portspec);
return -1;
}
pnum = sp->s_port;
@@ -521,7 +754,7 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"invalid connection type: %s; "
"unsupported address family",
- cstr);
+ srv->portspec);
return -1;
}
}
@@ -559,7 +792,7 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
if (connect(fd, &addr.sa, socklen)) {
gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
"Cannot connect to %s: %s",
- cstr, strerror(errno));
+ srv->portspec, strerror(errno));
close(fd);
return -1;
}
@@ -568,32 +801,23 @@ srv_connect(gacopyz_srv_t srv, const char *cstr,
}
int
-gacopyz_srv_connect(gacopyz_srv_t srv, const char *cstr)
+gacopyz_srv_connect(gacopyz_srv_t srv)
{
char *proto;
char *port;
char *path;
int rc;
- if (!srv) {
- gacopyz_logmsg(SMI_LOG_ERR,
- "empty or missing server information");
- errno = EINVAL;
- return MI_FAILURE;
- }
-
- gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
- "conecting to %s", cstr);
+ GACOPYZ_ASSERT(srv);
- rc = gacopyz_parse_connection(cstr, &proto, &port, &path);
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "conecting to %s", srv->portspec);
- if (rc) {
- gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
- "parse_connection: not enough memory");
- return MI_FAILURE;
- }
+ GACOPYZ_ALLOC(srv,
+ gacopyz_parse_connection(srv->portspec,
+ &proto, &port, &path)==0);
- srv->iod.sd = srv_connect(srv, cstr, proto, port, path);
+ srv->iod.sd = srv_connect(srv, proto, port, path);
free(proto);
free(port);
free(path);
@@ -610,8 +834,7 @@ gacopyz_srv_negotiate(gacopyz_srv_t srv)
size_t size;
unsigned char cmd;
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
ibuf[0] = htonl(srv->version);
ibuf[1] = htonl(srv->acts);
@@ -712,10 +935,10 @@ 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();
+ srv_ensure_space(srv,
+ strlen(reject_code) + 1
+ + sizeof(DEFREPLY));
+
strcpy(srv->buf, reject_code);
strcat(srv->buf, " ");
strcat(srv->buf, DEFREPLY);
@@ -726,8 +949,7 @@ 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;
+ srv_format_macros(srv, cmd, &size);
if (gacopyz_send_command(&srv->iod, SMFIC_MACRO,
srv->buf, size))
return MI_FAILURE;
@@ -774,6 +996,7 @@ gacopyz_srv_send_command(gacopyz_srv_t srv, unsigned char cmd,
cp->action, srv->buf);
srv->resp_ptr = srv->buf;
srv->resp_size = size;
+ srv->state = srv_disabled;
break;
case SMFIR_REJECT:
@@ -806,6 +1029,8 @@ gacopyz_srv_send_command(gacopyz_srv_t srv, unsigned char cmd,
gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
"action=%s, continue",
cp->action);
+ if (cmd == SMFIC_MAIL)
+ srv->state = srv_msgproc;
break;
default:
@@ -825,7 +1050,7 @@ gacopyz_srv_send_command(gacopyz_srv_t srv, unsigned char cmd,
gacopyz_io_log(&srv->iod, SMI_LOG_FATAL, \
"%s:%d: %s not implemented!!!", \
__FILE__, __LINE__, __FUNCTION__), \
- MI_FAILURE \
+ SMFIR_TEMPFAIL \
)
void
@@ -846,8 +1071,7 @@ gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain)
{
int rc;
- if (!srv)
- return MI_FAILURE;
+ GACOPYZ_ASSERT(srv);
if (srv->proto & SMFIP_NOHELO)
rc = SMFIR_CONTINUE;
else
@@ -856,7 +1080,7 @@ gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain)
return rc;
}
-static int
+static void
format_argv(gacopyz_srv_t srv, char **argv, char **buf, size_t *psize)
{
size_t len;
@@ -866,13 +1090,7 @@ format_argv(gacopyz_srv_t srv, char **argv, char **buf, size_t *psize)
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;
- }
+ GACOPYZ_ALLOC(srv, *buf = malloc(len));
for (p = *buf, ap = argv; *ap; ap++) {
size_t len = strlen(*ap) + 1;
@@ -881,7 +1099,6 @@ format_argv(gacopyz_srv_t srv, char **argv, char **buf, size_t *psize)
}
*p = 0;
*psize = len;
- return 0;
}
int
@@ -889,16 +1106,17 @@ gacopyz_srv_envfrom(gacopyz_srv_t srv, char **argv)
{
int rc;
- if (!srv)
- return MI_FAILURE;
- if (srv->proto & SMFIP_NOMAIL)
+ GACOPYZ_ASSERT(srv);
+ if (srv->state != srv_ready) {
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_envfrom: ignoring request; called in wrong state (%d)",
+ srv->state);
rc = SMFIR_CONTINUE;
- else {
+ } else {
size_t size;
char *buf;
- if (format_argv(srv, argv, &buf, &size))
- return MI_FAILURE;
+ format_argv(srv, argv, &buf, &size);
rc = gacopyz_srv_send_command(srv, SMFIC_MAIL, buf, size);
free (buf);
}
@@ -910,16 +1128,17 @@ gacopyz_srv_envrcpt(gacopyz_srv_t srv, char **argv)
{
int rc;
- if (!srv)
- return MI_FAILURE;
- if (srv->proto & SMFIP_NORCPT)
+ GACOPYZ_ASSERT(srv);
+ if (srv->state != srv_msgproc) {
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_envrcpt: ignoring request; called in wrong state (%d)",
+ srv->state);
rc = SMFIR_CONTINUE;
- else {
+ } else {
size_t size;
char *buf;
- if (format_argv(srv, argv, &buf, &size))
- return MI_FAILURE;
+ format_argv(srv, argv, &buf, &size);
rc = gacopyz_srv_send_command(srv, SMFIC_RCPT, buf, size);
free (buf);
}
@@ -930,25 +1149,21 @@ int
gacopyz_srv_header(gacopyz_srv_t srv, char *name, char *value)
{
int rc;
-
- if (!srv || !name || !value)
- return MI_FAILURE;
- if (srv->proto & SMFIP_NOHDRS)
+
+ GACOPYZ_ASSERT(srv && name && value);
+ if (srv->state != srv_msgproc) {
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_header: ignoring request; called in wrong state (%d)",
+ srv->state);
rc = SMFIR_CONTINUE;
- else {
+ } else {
size_t nlen, vlen, size;
char *buf;
nlen = strlen (name);
vlen = strlen (value);
size = nlen + vlen + 2;
- buf = malloc (size);
- if (!buf) {
- gacopyz_io_log(&srv->iod,
- SMI_LOG_FATAL,
- "Not enough memory");
- return MI_FAILURE;
- }
+ GACOPYZ_ALLOC(srv, buf = malloc (size));
memcpy (buf, name, nlen + 1);
memcpy (buf + nlen + 1, value, vlen + 1);
rc = gacopyz_srv_send_command(srv, SMFIC_HEADER, buf, size);
@@ -961,11 +1176,13 @@ int
gacopyz_srv_eoh(gacopyz_srv_t srv)
{
int rc;
- if (!srv)
- return MI_FAILURE;
- if (srv->proto & SMFIP_NOEOH)
+ GACOPYZ_ASSERT(srv);
+ if (srv->state != srv_msgproc) {
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_eoh: ignoring request; called in wrong state (%d)",
+ srv->state);
rc = SMFIR_CONTINUE;
- else
+ } else
rc = gacopyz_srv_send_command(srv, SMFIC_EOH, NULL, 0);
return rc;
}
@@ -974,26 +1191,35 @@ int
gacopyz_srv_body(gacopyz_srv_t srv, unsigned char *str, size_t size)
{
int rc;
- if (!srv)
- return MI_FAILURE;
- if (srv->proto & SMFIP_NOBODY)
+ GACOPYZ_ASSERT(srv);
+ if (srv->state != srv_msgproc) {
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_body: ignoring request; called in wrong state (%d)",
+ srv->state);
rc = SMFIR_CONTINUE;
- else
+ } else
rc = gacopyz_srv_send_command(srv, SMFIC_BODY, str, size);
return rc;
}
int
-gacopyz_srv_eom(gacopyz_srv_t srv)
+gacopyz_srv_eom(gacopyz_srv_t srv, unsigned char *chunk, size_t size)
{
- if (!srv)
- return MI_FAILURE;
- return gacopyz_srv_send_command(srv, SMFIC_BODYEOB, NULL, 0);
+ GACOPYZ_ASSERT(srv);
+ if (srv->state != srv_msgproc) {
+ gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
+ "gacopyz_srv_body: ignoring request; called in wrong state (%d)",
+ srv->state);
+ srv->state = srv_done;
+ return SMFIR_CONTINUE;
+ }
+ return gacopyz_srv_send_command(srv, SMFIC_BODYEOB, chunk, size);
}
int
gacopyz_srv_close(gacopyz_srv_t srv)
{
+ GACOPYZ_ASSERT(srv);
close (srv->iod.sd);
srv->state = srv_init;
return MI_SUCCESS;
@@ -1002,14 +1228,7 @@ gacopyz_srv_close(gacopyz_srv_t srv)
int
gacopyz_srv_data(gacopyz_srv_t srv)
{
- int rc;
-
- if (!srv)
- return MI_FAILURE;
- if (srv->proto & SMFIP_NODATA)
- rc = SMFIR_CONTINUE;
- else
- rc = gacopyz_srv_send_command(srv, SMFIC_DATA, NULL, 0);
- return rc;
+ GACOPYZ_ASSERT(srv);
+ return gacopyz_srv_send_command(srv, SMFIC_DATA, NULL, 0);
}

Return to:

Send suggestions and report system problems to the System administrator.