diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-02-10 14:08:36 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-02-10 14:08:36 +0000 |
commit | a1871918823166cac9f0c12164ba27cb3b1f0c2c (patch) | |
tree | 7260d118aa5af6a8f006f9b2dac6cabde782db8c /gacopyz/gacopyz.c | |
parent | 455b645247bdc0f01239b2352a9d8f07f446024f (diff) | |
download | mailfromd-a1871918823166cac9f0c12164ba27cb3b1f0c2c.tar.gz mailfromd-a1871918823166cac9f0c12164ba27cb3b1f0c2c.tar.bz2 |
Merged HEAD from branches/gmach
git-svn-id: file:///svnroot/mailfromd/trunk@1612 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'gacopyz/gacopyz.c')
-rw-r--r-- | gacopyz/gacopyz.c | 629 |
1 files changed, 364 insertions, 265 deletions
diff --git a/gacopyz/gacopyz.c b/gacopyz/gacopyz.c index 4f066615..3cf919bd 100644 --- a/gacopyz/gacopyz.c +++ b/gacopyz/gacopyz.c @@ -1,5 +1,5 @@ /* This file is part of gacopyz. - Copyright (C) 2006, 2007 Sergey Poznyakoff + Copyright (C) 2006, 2007, 2008 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 @@ -16,13 +16,17 @@ #include <gacopyz_priv.h> -#define TRACE(conn,cmd,size,buf) do { \ - gacopyz_log(conn, SMI_LOG_DEBUG, \ - _("send header: size=%lu, cmd=%c"),\ - size, cmd); \ - gacopyz_logdump(conn, SMI_LOG_DEBUG, \ - _("send data"), buf, size); \ -} while (0) +#define TRACE(ctx,cmd,size,buf) do { \ + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_DEBUG)) { \ + gacopyz_log(SMI_LOG_DEBUG, _("send header: size=%lu, cmd=%c"),\ + size, cmd); \ + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_PROTO)) \ + gacopyz_logdump(SMI_LOG_PROTO, \ + _("send data"), buf, size); \ + else \ + gacopyz_log(SMI_LOG_DEBUG, _("send data")); \ + } \ + } while (0) int gacopyz_init(gacopyz_conn_t *pconn, struct smfiDesc *desc) @@ -34,7 +38,7 @@ gacopyz_init(gacopyz_conn_t *pconn, struct smfiDesc *desc) name = desc->xxfi_name ? desc->xxfi_name : "Unknown"; len = strlen(name); if (desc->xxfi_version != SMFI_VERSION) { - gacopyz_logmsg(SMI_LOG_ERR, + gacopyz_log(SMI_LOG_ERR, _("smfi_register: %s: version mismatch; " "application %d != implementation %d"), name, desc->xxfi_version, SMFI_VERSION); @@ -44,7 +48,7 @@ gacopyz_init(gacopyz_conn_t *pconn, struct smfiDesc *desc) conn = malloc(sizeof(*conn) + len + 1); if (!conn) { - gacopyz_logmsg(SMI_LOG_ERR, + gacopyz_log(SMI_LOG_ERR, "smfi_register: %s: %s", name, strerror(errno)); return MI_FAILURE; @@ -54,9 +58,10 @@ gacopyz_init(gacopyz_conn_t *pconn, struct smfiDesc *desc) conn->sd = -1; conn->master_timeout.tv_usec = 0; conn->master_timeout.tv_sec = 5; - conn->ctx_timeout.tv_usec = 0; - conn->ctx_timeout.tv_sec = GACOPYZ_TIMEOUT; - conn->logmask = SMI_DEFAULT_LOG_MASK; + conn->desc.ctx_timeout.tv_usec = 0; + conn->desc.ctx_timeout.tv_sec = GACOPYZ_TIMEOUT; + if (!conn->desc.logmask) + conn->desc.logmask = SMI_DEFAULT_LOG_MASK; conn->desc = *desc; conn->desc.xxfi_name = (char*)(conn + 1); strcpy(conn->desc.xxfi_name, name); @@ -73,42 +78,71 @@ gacopyz_free(gacopyz_conn_t conn) } } +static int +copy_part(const char *cstr, const char *p, char **pbuf) +{ + size_t len = p - cstr; + char *buf = malloc(len + 1); + if (!buf) { + free(buf); + return MI_FAILURE; + } + memcpy(buf, cstr, len); + buf[len] = 0; + *pbuf = buf; + return 0; +} + + +static int +parse_url(const char *proto, const char *cstr, char **pport, char **ppath) +{ + const char *p = strchr (cstr, ':'); + + if (!p) { + *pport = NULL; + *ppath = strdup(cstr); + return *ppath == NULL ? MI_FAILURE : 0; + } else if (copy_part(cstr, p, ppath)) + return MI_FAILURE; + else + cstr = p + 1; + *pport = strdup(cstr); + return *pport == NULL ? MI_FAILURE : 0; +} + int -gacopyz_parse_connection(const char *cstr, +gacopyz_parse_connection(const char *cstr, char **pproto, char **pport, char **ppath) { const char *p; - size_t len; p = strchr(cstr, ':'); if (!p) *pproto = NULL; else { - len = p - cstr; - *pproto = malloc(len + 1); - if (!*pproto) + char *proto; + if (copy_part(cstr, p, &proto)) return MI_FAILURE; - memcpy(*pproto, cstr, len); - (*pproto)[len] = 0; - cstr = p + 1; + if (cstr[0] == '/' && cstr[1] == '/') { + int rc = parse_url(proto, cstr + 2, pport, ppath); + if (rc) + free(proto); + else + *pproto = proto; + return rc; + } + *pproto = proto; } p = strchr(cstr, '@'); if (!p) *pport = NULL; - else { - len = p - cstr; - *pport = malloc(len + 1); - if (!*pport) { - free(*pproto); - return MI_FAILURE; - } - memcpy(*pport, cstr, len); - (*pport)[len] = 0; - + else if (copy_part(cstr, p, pport)) + return MI_FAILURE; + else cstr = p + 1; - } *ppath = strdup(cstr); if (!*ppath) { @@ -127,9 +161,9 @@ parse_connection(gacopyz_conn_t conn, char **pproto, char **pport, char **ppath) { int rc = gacopyz_parse_connection(cstr, pproto, pport, ppath); - if (rc) - gacopyz_log(conn, SMI_LOG_ERR, - "parse_connection: %s", strerror(ENOMEM)); + if (rc && GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + "parse_connection: %s", strerror(ENOMEM)); return rc; } @@ -138,10 +172,12 @@ static void cleanup_unix_socket(gacopyz_conn_t conn, void *data) { if (unlink(data) && errno != ENOENT) - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: %s: cannot unlink: %s"), - conn->desc.xxfi_name, (char*)data, - strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: %s: cannot unlink: %s"), + conn->desc.xxfi_name, (char*)data, + strerror(errno)); + free(data); } @@ -164,7 +200,8 @@ do_connect(gacopyz_conn_t conn, struct stat st; if (port) { - gacopyz_log(conn, SMI_LOG_ERR, + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, _("%s: invalid connection type: %s; " "port is meaningless for UNIX sockets"), conn->desc.xxfi_name, cstr); @@ -173,9 +210,10 @@ do_connect(gacopyz_conn_t conn, if (strlen(path) > sizeof addr.s_un.sun_path) { errno = EINVAL; - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: %s: UNIX socket name too long"), - conn->desc.xxfi_name, path); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: %s: UNIX socket name too long"), + conn->desc.xxfi_name, path); return -1; } @@ -188,22 +226,26 @@ do_connect(gacopyz_conn_t conn, conn->cleanup = cleanup_unix_socket; conn->cleanup_data = strdup(path); } else { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: %s: cannot stat socket: %s"), - conn->desc.xxfi_name, path, - strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: %s: cannot stat socket: %s"), + conn->desc.xxfi_name, path, + strerror(errno)); return -1; } } else { /* FIXME: Check permissions? */ if (!S_ISSOCK(st.st_mode)) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: %s: not a socket"), - conn->desc.xxfi_name, path); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: %s: not a socket"), + conn->desc.xxfi_name, + path); return -1; } if (rmsocket && unlink(path)) { - gacopyz_log(conn, SMI_LOG_ERR, + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, _("%s: %s: cannot unlink: %s"), conn->desc.xxfi_name, path, strerror(errno)); @@ -220,30 +262,35 @@ do_connect(gacopyz_conn_t conn, socklen = sizeof(addr.s_in); if (!port) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: invalid connection type: %s; " - "missing port number"), - conn->desc.xxfi_name, cstr); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: invalid connection type: %s; " + "missing port number"), + conn->desc.xxfi_name, cstr); return -1; } num = pnum = strtol(port, &p, 0); if (*p == 0) { if (num != pnum) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: invalid connection type: %s; " - "bad port number"), - conn->desc.xxfi_name, cstr); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: invalid connection type: " + "%s; bad port number"), + conn->desc.xxfi_name, + cstr); return -1; } pnum = htons(pnum); } else { struct servent *sp = getservbyname(port, "tcp"); if (!sp) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: invalid connection type: %s; " - "unknown port name"), - conn->desc.xxfi_name, cstr); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: invalid connection type: " + "%s; unknown port name"), + conn->desc.xxfi_name, + cstr); return -1; } pnum = sp->s_port; @@ -254,9 +301,11 @@ do_connect(gacopyz_conn_t conn, else { struct hostent *hp = gethostbyname(path); if (!hp) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: Unknown host name %s"), - conn->desc.xxfi_name, path); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: Unknown host name %s"), + conn->desc.xxfi_name, + path); return -1; } addr.sa.sa_family = hp->h_addrtype; @@ -267,33 +316,38 @@ do_connect(gacopyz_conn_t conn, break; default: - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: invalid connection type: %s; " - "unsupported address family"), - conn->desc.xxfi_name, cstr); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: invalid connection type: " + "%s; unsupported address family"), + conn->desc.xxfi_name, + cstr); return -1; } } } else { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: unsupported protocol: %s"), - conn->desc.xxfi_name, proto); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: unsupported protocol: %s"), + conn->desc.xxfi_name, proto); return -1; } fd = socket(addr.sa.sa_family, SOCK_STREAM, 0); if (fd == -1) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: Unable to create new socket: %s"), - conn->desc.xxfi_name, strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: Unable to create new socket: %s"), + conn->desc.xxfi_name, strerror(errno)); return -1; } if ((flags = fcntl(fd, F_GETFD, 0)) == -1 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: Cannot set close-on-exec: %s"), - conn->desc.xxfi_name, strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: Cannot set close-on-exec: %s"), + conn->desc.xxfi_name, strerror(errno)); close(fd); return -1; } @@ -301,25 +355,30 @@ do_connect(gacopyz_conn_t conn, if (addr.sa.sa_family != PF_UNIX && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)) == -1) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: set reuseaddr failed (%s)"), - conn->desc.xxfi_name, strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: set reuseaddr failed (%s)"), + conn->desc.xxfi_name, strerror(errno)); close(fd); return -1; } if (bind(fd, &addr.sa, socklen) < 0) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: Cannot bind to port %s: %s"), - conn->desc.xxfi_name, cstr, strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: Cannot bind to port %s: %s"), + conn->desc.xxfi_name, cstr, + strerror(errno)); close(fd); return -1; } if (listen(fd, backlog)) { - gacopyz_log(conn, SMI_LOG_ERR, - _("%s: Cannot listen on port %s: %s"), - conn->desc.xxfi_name, cstr, strerror(errno)); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: Cannot listen on port %s: %s"), + conn->desc.xxfi_name, cstr, + strerror(errno)); close(fd); return -1; } @@ -336,15 +395,16 @@ gacopyz_open(gacopyz_conn_t conn, const char *cstr, int backlog, int rmsocket) char *path; if (!conn) { - gacopyz_logmsg(SMI_LOG_ERR, + gacopyz_log(SMI_LOG_ERR, _("Empty or missing socket information")); errno = EINVAL; return MI_FAILURE; } - gacopyz_log(conn, SMI_LOG_DEBUG, - _("%s: opening listen socket on %s"), - conn->desc.xxfi_name, cstr); + if (GACOPYZ_CONN_LOG_MATCH(conn, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, + _("%s: opening listen socket on %s"), + conn->desc.xxfi_name, cstr); if (parse_connection(conn, cstr, &proto, &port, &path)) { errno = ENOENT; return MI_FAILURE; @@ -364,7 +424,7 @@ gacopyz_get_logmask(gacopyz_conn_t conn, int *mask) { if (!conn || !mask) return MI_FAILURE; - *mask = conn->logmask; + *mask = conn->desc.logmask; return MI_SUCCESS; } @@ -373,7 +433,7 @@ gacopyz_set_logmask(gacopyz_conn_t conn, int mask) { if (!conn) return MI_FAILURE; - conn->logmask = mask; + conn->desc.logmask = mask; return MI_SUCCESS; } @@ -434,7 +494,7 @@ gacopyz_set_ctx_timeout(gacopyz_conn_t conn, struct timeval *timeout) { if (!conn) return MI_FAILURE; - conn->ctx_timeout = *timeout; + conn->desc.ctx_timeout = *timeout; return MI_SUCCESS; } @@ -443,7 +503,7 @@ gacopyz_get_ctx_timeout(gacopyz_conn_t conn, struct timeval *timeout) { if (!conn) return MI_FAILURE; - *timeout = conn->ctx_timeout; + *timeout = conn->desc.ctx_timeout; return MI_SUCCESS; } @@ -478,14 +538,14 @@ ctx_read(SMFICTX *ctx, char *buf, size_t size) FD_SET(ctx->sd, &rset); FD_SET(ctx->sd, &xset); - to = ctx->conn->ctx_timeout; + to = ctx->desc->ctx_timeout; res = select(ctx->sd + 1, &rset, NULL, &xset, &to); if (res == 0) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: connection timed out"), - "ctx_read"); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: connection timed out"), + "ctx_read"); errno = ETIMEDOUT; rc = MI_FAILURE; break; @@ -496,10 +556,10 @@ ctx_read(SMFICTX *ctx, char *buf, size_t size) break; } else if (rc > 0) { if (FD_ISSET(ctx->sd, &xset)) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: exception on control fd"), - "ctx_read"); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: exception on control fd"), + "ctx_read"); rc = MI_FAILURE; break; } @@ -508,18 +568,18 @@ ctx_read(SMFICTX *ctx, char *buf, size_t size) res = read(ctx->sd, buf, size); if (res == -1) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: read failed: %s"), - "ctx_read", - strerror(errno)); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: read failed: %s"), + "ctx_read", + strerror(errno)); rc = MI_FAILURE; break; } else if (res == 0) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: end of file"), - "ctx_read"); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: end of file"), + "ctx_read"); rc = MI_FAILURE; break; } @@ -546,14 +606,14 @@ ctx_write(SMFICTX *ctx, char *buf, size_t size) FD_SET(ctx->sd, &wset); FD_SET(ctx->sd, &xset); - to = ctx->conn->ctx_timeout; + to = ctx->desc->ctx_timeout; res = select(ctx->sd + 1, NULL, &wset, &xset, &to); if (res == 0) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: connection timed out"), - "ctx_write"); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: connection timed out"), + "ctx_write"); errno = ETIMEDOUT; rc = MI_FAILURE; break; @@ -564,8 +624,8 @@ ctx_write(SMFICTX *ctx, char *buf, size_t size) break; } else if (rc > 0) { if (FD_ISSET(ctx->sd, &xset)) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, _("%s: exception on control fd"), "ctx_write"); rc = MI_FAILURE; @@ -576,18 +636,18 @@ ctx_write(SMFICTX *ctx, char *buf, size_t size) res = write(ctx->sd, buf, size); if (res == -1) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: write failed: %s"), - "ctx_write", - strerror(errno)); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: write failed: %s"), + "ctx_write", + strerror(errno)); rc = MI_FAILURE; break; } else if (res == 0) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, - _("%s: wrote 0 bytes"), - "ctx_write"); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: wrote 0 bytes"), + "ctx_write"); rc = MI_FAILURE; break; } @@ -622,24 +682,28 @@ get_command(SMFICTX *ctx, unsigned char *cmd, size_t *pcount, if (size + 1 > *psize) { char *p = realloc(*pbuf, size + 1); if (!p) { - gacopyz_log(ctx->conn, - SMI_LOG_ERR, "%s", strerror(errno)); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, "%s", + strerror(errno)); return MI_FAILURE; } *pbuf = p; *psize = size + 1; } - gacopyz_log(ctx->conn, SMI_LOG_DEBUG, - _("read header: size=%lu, cmd=%c"), - size, header.hdr.cmd); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, + _("read header: size=%lu, cmd=%c"), + size, header.hdr.cmd); if ((rc = ctx_read(ctx, *pbuf, size)) != MI_SUCCESS) return rc; (*pbuf)[size] = 0; - gacopyz_logdump(ctx->conn, SMI_LOG_DEBUG, - _("read data"), *pbuf, size); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_PROTO)) + gacopyz_logdump(SMI_LOG_PROTO, _("read data"), *pbuf, size); + else if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, _("read data")); *pcount = size; *cmd = header.hdr.cmd; return MI_SUCCESS; @@ -682,8 +746,8 @@ send_reply(SMFICTX *ctx, unsigned char cmd) case SMFIC_OPTNEG: { gacopyz_uint32_t v[3]; - v[0] = htonl(ctx->conn->desc.xxfi_version); - v[1] = htonl(ctx->conn->desc.xxfi_flags); + v[0] = htonl(ctx->desc->xxfi_version); + v[1] = htonl(ctx->desc->xxfi_flags); v[2] = htonl(ctx->flags); buf = (char*) v; bufsize = sizeof v; @@ -694,7 +758,7 @@ send_reply(SMFICTX *ctx, unsigned char cmd) break; } - TRACE(ctx->conn, cmd, bufsize, buf); + TRACE(ctx, cmd, bufsize, buf); header.hdr.size = htonl(bufsize + 1); header.hdr.cmd = cmd; @@ -789,8 +853,8 @@ convert_sfsistat(sfsistat stat) static state_ret_type shan_abort(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_abort) - ctx->conn->desc.xxfi_abort(ctx); + if (ctx->desc->xxfi_abort) + ctx->desc->xxfi_abort(ctx); return sret_noreply; } @@ -855,11 +919,11 @@ shan_macro(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_body(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_body) { + if (ctx->desc->xxfi_body) { *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_body(ctx, - arg->string.ptr, - arg->string.len)); + ctx->desc->xxfi_body(ctx, + arg->string.ptr, + arg->string.len)); } else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -875,7 +939,7 @@ shan_connect(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) unsigned short port = 0; *cmd = SMFIR_CONTINUE; - if (!ctx->conn->desc.xxfi_connect) + if (!ctx->desc->xxfi_connect) return sret_reply; memset(&sockaddr, 0, sizeof sockaddr); @@ -894,11 +958,12 @@ shan_connect(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) switch (family) { case SMFIA_UNIX: if (len >= sizeof sockaddr.sunix.sun_path) { - gacopyz_log(ctx->conn, SMI_LOG_ERR, - "%s: shan_connect: %s: %lu", - ctx->conn->desc.xxfi_name, - _("path too long"), - (unsigned long) len); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + "%s: shan_connect: %s: %lu", + ctx->desc->xxfi_name, + _("path too long"), + (unsigned long) len); return sret_abort; } strcpy(sockaddr.sunix.sun_path, s); @@ -908,10 +973,11 @@ shan_connect(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) case SMFIA_INET: if (inet_aton(s, (struct in_addr *) &sockaddr.sin.sin_addr) != 1) { - gacopyz_log(ctx->conn, SMI_LOG_ERR, - _("%s: shan_connect: inet_aton(%s) failed"), - ctx->conn->desc.xxfi_name, - s); + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: shan_connect: inet_aton(%s) failed"), + ctx->desc->xxfi_name, + s); return sret_abort; } sockaddr.sa.sa_family = AF_INET; @@ -920,35 +986,36 @@ shan_connect(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) case SMFIA_INET6: default: - gacopyz_log(ctx->conn, SMI_LOG_ERR, + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, _("%s: shan_connect: unknown family %d"), - ctx->conn->desc.xxfi_name, - family); + ctx->desc->xxfi_name, + family); return sret_abort; } } *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_connect(ctx, - arg->strings[0], - family != SMFIA_UNKNOWN ? - &sockaddr : NULL)); + ctx->desc->xxfi_connect(ctx, + arg->strings[0], + family != SMFIA_UNKNOWN ? + &sockaddr : NULL)); return sret_reply; } static state_ret_type shan_endm(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (arg->string.len && ctx->conn->desc.xxfi_body) { - sfsistat r = ctx->conn->desc.xxfi_body(ctx, - arg->string.ptr, - arg->string.len); + if (arg->string.len && ctx->desc->xxfi_body) { + sfsistat r = ctx->desc->xxfi_body(ctx, + arg->string.ptr, + arg->string.len); if (r != SMFIS_CONTINUE && send_reply(ctx, convert_sfsistat(r) != MI_SUCCESS)) return sret_abort; } - if (ctx->conn->desc.xxfi_eom) - *cmd = convert_sfsistat(ctx->conn->desc.xxfi_eom(ctx)); + if (ctx->desc->xxfi_eom) + *cmd = convert_sfsistat(ctx->desc->xxfi_eom(ctx)); else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -957,9 +1024,9 @@ shan_endm(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_helo(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_helo) + if (ctx->desc->xxfi_helo) *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_helo(ctx, arg->string.ptr)); + ctx->desc->xxfi_helo(ctx, arg->string.ptr)); else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -968,11 +1035,11 @@ shan_helo(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_header(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_header) + if (ctx->desc->xxfi_header) *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_header(ctx, - arg->strings[0], - arg->strings[1])); + ctx->desc->xxfi_header(ctx, + arg->strings[0], + arg->strings[1])); else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -981,9 +1048,9 @@ shan_header(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_mail(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_envfrom) { + if (ctx->desc->xxfi_envfrom) { *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_envfrom(ctx, arg->argv.v)); + ctx->desc->xxfi_envfrom(ctx, arg->argv.v)); } else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -994,24 +1061,27 @@ shan_optneg(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { gacopyz_uint32_t val; - if (arg->ints[0] < ctx->conn->desc.xxfi_version) { - gacopyz_log(ctx->conn, SMI_LOG_ERR, + if (arg->ints[0] < ctx->desc->xxfi_version) { + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, _("%s: shan_optneg: version mismatch; " "MTA: %ld < milter: %d"), - ctx->conn->desc.xxfi_name, - arg->ints[0], ctx->conn->desc.xxfi_version); + ctx->desc->xxfi_name, + arg->ints[0], + ctx->desc->xxfi_version); return sret_abort; } val = arg->ints[1]; if (!val) val = SMFI_V1_ACTS; - if ((val & ctx->conn->desc.xxfi_flags) != ctx->conn->desc.xxfi_flags) { - gacopyz_log(ctx->conn, SMI_LOG_ERR, - _("%s: shan_optneg: flags %#x do not match " - "actions requirements %#x"), - ctx->conn->desc.xxfi_name, val, - ctx->conn->desc.xxfi_flags); + if ((val & ctx->desc->xxfi_flags) != ctx->desc->xxfi_flags) { + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, + _("%s: shan_optneg: flags %#x do not match " + "actions requirements %#x"), + ctx->desc->xxfi_name, val, + ctx->desc->xxfi_flags); return sret_abort; } @@ -1019,11 +1089,12 @@ shan_optneg(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) if (!val) val = SMFI_V1_PROT; if ((val & ctx->flags) != ctx->flags) { - gacopyz_log(ctx->conn, SMI_LOG_ERR, + if (GACOPYZ_CTX_LOG_MATCH(ctx, SMI_LOG_ERR)) + gacopyz_log(SMI_LOG_ERR, _("%s: shan_optneg: flags %#x do not match " "protocol requirement %#x"), - ctx->conn->desc.xxfi_name, val, - ctx->flags); + ctx->desc->xxfi_name, val, + ctx->flags); return sret_abort; } *cmd = SMFIC_OPTNEG; @@ -1033,8 +1104,8 @@ shan_optneg(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_eoh(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_eoh) - *cmd = convert_sfsistat(ctx->conn->desc.xxfi_eoh(ctx)); + if (ctx->desc->xxfi_eoh) + *cmd = convert_sfsistat(ctx->desc->xxfi_eoh(ctx)); else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -1049,8 +1120,8 @@ shan_quit(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_data(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_data) - *cmd = convert_sfsistat(ctx->conn->desc.xxfi_data(ctx)); + if (ctx->desc->xxfi_data) + *cmd = convert_sfsistat(ctx->desc->xxfi_data(ctx)); else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -1059,9 +1130,9 @@ shan_data(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_rcpt(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_envrcpt) { + if (ctx->desc->xxfi_envrcpt) { *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_envrcpt(ctx, arg->argv.v)); + ctx->desc->xxfi_envrcpt(ctx, arg->argv.v)); } else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -1070,9 +1141,9 @@ shan_rcpt(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) static state_ret_type shan_unkn(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) { - if (ctx->conn->desc.xxfi_unknown) { + if (ctx->desc->xxfi_unknown) { *cmd = convert_sfsistat( - ctx->conn->desc.xxfi_unknown(ctx, arg->string.ptr)); + ctx->desc->xxfi_unknown(ctx, arg->string.ptr)); } else *cmd = SMFIR_CONTINUE; return sret_reply; @@ -1213,7 +1284,7 @@ arg_free(union state_arg *arg, enum state_arg_type type) #define STATE_NAME(st) ((st == st_none) ? "st_none" : state_name[st]) int -gacopyz_context_loop(gacopyz_conn_t conn, int fd) +gacopyz_context_loop(int fd, struct smfiDesc *desc) { int rc; char *buffer = NULL; @@ -1221,26 +1292,29 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) size_t size; unsigned char cmd; SMFICTX ctx; - int allow_unkn = conn->desc.xxfi_unknown != NULL; + int allow_unkn = desc->xxfi_unknown != NULL; enum state state = st_init; int stop = 0; + if (desc->xxfi_start) + desc->xxfi_start(); + memset(&ctx, 0, sizeof ctx); - ctx.conn = conn; + ctx.desc = desc; ctx.sd = fd; - if (!conn->desc.xxfi_connect) + if (!desc->xxfi_connect) ctx.flags |= SMFIP_NOCONNECT; - if (!conn->desc.xxfi_helo) + if (!desc->xxfi_helo) ctx.flags |= SMFIP_NOHELO; - if (!conn->desc.xxfi_envfrom) + if (!desc->xxfi_envfrom) ctx.flags |= SMFIP_NOMAIL; - if (!conn->desc.xxfi_envrcpt) + if (!desc->xxfi_envrcpt) ctx.flags |= SMFIP_NORCPT; - if (!conn->desc.xxfi_header) + if (!desc->xxfi_header) ctx.flags |= SMFIP_NOHDRS; - if (!conn->desc.xxfi_eoh) + if (!desc->xxfi_eoh) ctx.flags |= SMFIP_NOEOH; - if (!conn->desc.xxfi_body) + if (!desc->xxfi_body) ctx.flags |= SMFIP_NOBODY; /* Fix up the transition table */ @@ -1251,8 +1325,9 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) transtab[st_hdrs][st_skip] = !!(ctx.flags & SMFIP_NOHDRS); transtab[st_eohs][st_skip] = !!(ctx.flags & SMFIP_NOEOH); transtab[st_body][st_skip] = !!(ctx.flags & SMFIP_NOBODY); - - gacopyz_log(conn, SMI_LOG_DEBUG, _("Begin context loop")); + + if (GACOPYZ_DESC_LOG_MATCH(desc, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, _("Begin context loop")); while (!stop && (rc = get_command(&ctx, &cmd, &size, &buffer, &bufsize)) @@ -1263,12 +1338,14 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) struct state_disp *sd = find_disp(cmd, allow_unkn); if (sd == NULL) { - gacopyz_log(conn, SMI_LOG_ERR, - _("Unknown command: %c"), - cmd); - gacopyz_logdump(conn, SMI_LOG_ERR, - _("buffer"), - buffer, size); + if (GACOPYZ_DESC_LOG_MATCH(desc, SMI_LOG_ERR)) { + gacopyz_log(SMI_LOG_ERR, + _("Unknown command: %c"), + cmd); + gacopyz_logdump(SMI_LOG_ERR, + _("buffer"), + buffer, size); + } rc = MI_FAILURE; break; } @@ -1277,13 +1354,15 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) stop = sd->flags & CT_END; if (next_state != st_none && !trans_ok(state, next_state)) { - gacopyz_log(conn, SMI_LOG_DEBUG, - _("Transition from state %s to %s is " - "prohibited"), - STATE_NAME(state), - STATE_NAME(next_state)); - if (ST_IN_MAIL(state) && ctx.conn->desc.xxfi_abort) - ctx.conn->desc.xxfi_abort(&ctx); + if (GACOPYZ_DESC_LOG_MATCH(desc, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, + _("Transition from state %s to %s is " + "prohibited"), + STATE_NAME(state), + STATE_NAME(next_state)); + + if (ST_IN_MAIL(state) && desc->xxfi_abort) + desc->xxfi_abort(&ctx); /* Retry starting from HELO */ state = st_helo; @@ -1297,11 +1376,13 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) } if (parse_state_arg(&arg, sd->arg_type, buffer, size)) { - gacopyz_log(conn, SMI_LOG_ERR, - _("Argument parsing failed")); - gacopyz_logdump(conn, SMI_LOG_ERR, - _("buffer"), - buffer, size); + if (GACOPYZ_DESC_LOG_MATCH(desc, SMI_LOG_ERR)) { + gacopyz_log(SMI_LOG_ERR, + _("Argument parsing failed")); + gacopyz_logdump(SMI_LOG_ERR, + _("buffer"), + buffer, size); + } rc = MI_FAILURE; break; } @@ -1329,15 +1410,17 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) break; case sret_fail: - gacopyz_log(conn, SMI_LOG_DEBUG, - _("%s handler returned failure"), - sd->name); + if (GACOPYZ_DESC_LOG_MATCH(desc, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, + _("%s handler returned failure"), + sd->name); break; case sret_abort: - gacopyz_log(conn, SMI_LOG_DEBUG, - _("%s handler returned abort"), - sd->name); + if (GACOPYZ_DESC_LOG_MATCH(desc, SMI_LOG_DEBUG)) + gacopyz_log(SMI_LOG_DEBUG, + _("%s handler returned abort"), + sd->name); rc = MI_FAILURE; } @@ -1345,18 +1428,23 @@ gacopyz_context_loop(gacopyz_conn_t conn, int fd) break; } - ga |