diff options
Diffstat (limited to 'gacopyz/server.c')
-rw-r--r-- | gacopyz/server.c | 121 |
1 files changed, 114 insertions, 7 deletions
diff --git a/gacopyz/server.c b/gacopyz/server.c index a61836e8..e7cfa643 100644 --- a/gacopyz/server.c +++ b/gacopyz/server.c @@ -1,5 +1,5 @@ /* This file is part of gacopyz. - Copyright (C) 2007, 2008 Sergey Poznyakoff + Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -49,6 +49,7 @@ struct gacopyz_srv { unsigned long version; unsigned long acts; unsigned long proto; + char **req_macros[gacopyz_stage_max]; /* Required macros */ int (*cb_reply) (gacopyz_srv_t srv, int cmd, int rcmd, void *data); void *cb_data; @@ -279,6 +280,13 @@ gacopyz_srv_count_macros(gacopyz_srv_t srv, size_t *count) } +const char ** +gacopyz_srv_get_required_macros(gacopyz_srv_t srv, enum gacopyz_stage stage) +{ + return (const char **) srv->req_macros[stage]; +} + + struct timeval default_gacopyz_timeout[GACOPYZ_TO_COUNT] = { { GACOPYZ_WRITE_TIMEOUT, 0 }, @@ -612,7 +620,7 @@ gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr) } int -gacopyz_srv_set_version(gacopyz_srv_t srv, int version) +gacopyz_srv_set_version(gacopyz_srv_t srv, unsigned long version) { GACOPYZ_ASSERT(srv); @@ -621,7 +629,7 @@ gacopyz_srv_set_version(gacopyz_srv_t srv, int version) } int -gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto) +gacopyz_srv_set_protocol(gacopyz_srv_t srv, unsigned long proto) { GACOPYZ_ASSERT(srv); @@ -630,7 +638,7 @@ gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto) } int -gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts) +gacopyz_srv_set_actions(gacopyz_srv_t srv, unsigned long acts) { GACOPYZ_ASSERT(srv); @@ -638,15 +646,24 @@ gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts) return MI_SUCCESS; } - void gacopyz_srv_destroy(gacopyz_srv_t *p) { + int i; + gacopyz_srv_t srv = *p; gacopyz_srv_clear_macros(srv); free(srv->portspec); free(srv->id); free(srv->def); + for (i = 0; i < gacopyz_stage_max; i++) + if (srv->req_macros[i]) { + int j; + + for (j = 0; srv->req_macros[i][j]; j++) + free(srv->req_macros[i][j]); + free(srv->req_macros[i]); + } free(srv->buf); free(srv); *p = 0; @@ -860,6 +877,94 @@ gacopyz_srv_connect(gacopyz_srv_t srv) return MI_SUCCESS; } +#define ISWS(c) ((c) == ' ' || (c) == '\t') + +static void +parse_macros(gacopyz_srv_t srv, enum gacopyz_stage stage, char *buf) +{ + char *p; + char **argv; + size_t count; + + count = 0; + for (p = buf; *p;) { + while (*p && ISWS(*p)) + p++; + if (*p) { + count++; + while (*p && !ISWS(*p)) + p++; + } + } + if (count == 0) + return; + GACOPYZ_ALLOC(srv, argv = calloc(count + 1, sizeof(argv[0]))); + count = 0; + for (p = buf; *p;) { + while (*p && ISWS(*p)) + p++; + if (*p) { + size_t i; + char *str = p; + + for (i = 0; *p && !ISWS(*p); p++, i++) + ; + if (i > 0) { + char *newstr; + + if (*str == '{' && str[i-1] == '}') { + str++; + i -= 2; + } + GACOPYZ_ALLOC(srv, newstr = malloc(i + 1)); + memcpy(newstr, str, i); + newstr[i] = 0; + argv[count++] = newstr; + } + } + } + argv[count] = NULL; + srv->req_macros[stage] = argv; +} + + +static void +read_macros(gacopyz_srv_t srv) +{ + char *buf = srv->buf + 3 * sizeof(gacopyz_uint32_t); + size_t size = srv->bufsize - 3 * sizeof(gacopyz_uint32_t); + + while (size > sizeof(gacopyz_uint32_t)) { + gacopyz_uint32_t v; + unsigned n; + size_t len; + + memcpy (&v, buf, sizeof(gacopyz_uint32_t)); + n = ntohl(v); + if (n >= gacopyz_stage_max) { + gacopyz_io_log(&srv->iod, SMI_LOG_ERR, + _("received invalid stage number")); + break; + } + buf += sizeof(gacopyz_uint32_t); + size -= sizeof(gacopyz_uint32_t); + if (size == 0) + break; + len = strlen(buf) + 1; + if (len > size) { + gacopyz_io_log(&srv->iod, SMI_LOG_ERR, + _("invalid macro list")); + break; + } + gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG, + _("macros for stage \"%s\" (%d): %s"), + gacopyz_stage_name[n], n, buf); + parse_macros(srv, n, buf); + buf += len; + size -= len; + } +} + int gacopyz_srv_negotiate(gacopyz_srv_t srv) { @@ -927,6 +1032,10 @@ gacopyz_srv_negotiate(gacopyz_srv_t srv) return MI_FAILURE; } + if (milter_version > 3 + && srv->bufsize > 3 * sizeof(gacopyz_uint32_t)) + read_macros(srv); + srv->version = milter_version; srv->acts = milter_acts; srv->proto = milter_proto; @@ -1209,8 +1318,6 @@ gacopyz_srv_conn(gacopyz_srv_t srv, const char *hostname, struct sockaddr *sa) int gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain) { - int rc; - GACOPYZ_ASSERT(srv); if (srv->state == srv_msgproc) gacopyz_srv_abort(srv); |