diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-03-09 22:48:28 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-03-09 22:48:28 +0000 |
commit | b9c5231e13acac4d23d119bf176ee952b9071fe9 (patch) | |
tree | c5cc3e281d40c4f0be8f08a6b63b8faa720ea46e /gacopyz | |
parent | 4a3b530ab2fb03e3a2d5db84a06d60ece2eafce9 (diff) | |
download | mailfromd-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.h | 52 | ||||
-rw-r--r-- | gacopyz/gacopyz_priv.h | 5 | ||||
-rw-r--r-- | gacopyz/server.c | 551 |
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); } |