aboutsummaryrefslogtreecommitdiff
path: root/gacopyz/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'gacopyz/server.c')
-rw-r--r--gacopyz/server.c121
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);

Return to:

Send suggestions and report system problems to the System administrator.