diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-01-11 21:25:11 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-01-11 21:25:11 +0000 |
commit | 0ea6c8adaa26d07fc8cf624baefb02416c7fc850 (patch) | |
tree | 41ee79c13ca25528b865b32655bd6f70d9bf810d | |
parent | 8f6eac030e298913170ab946ce607e77da18c8c3 (diff) | |
download | mailfromd-0ea6c8adaa26d07fc8cf624baefb02416c7fc850.tar.gz mailfromd-0ea6c8adaa26d07fc8cf624baefb02416c7fc850.tar.bz2 |
Update
git-svn-id: file:///svnroot/mailfromd/branches/gmach@1551 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | gacopyz/gacopyz.h | 2 | ||||
-rw-r--r-- | gacopyz/server.c | 56 | ||||
-rw-r--r-- | pmult/pmult.c | 219 |
4 files changed, 273 insertions, 7 deletions
@@ -1,5 +1,8 @@ 2008-01-11 Sergey Poznyakoff <gray@gnu.org.ua> + * pmult/pmult.c: Update + * gacopyz/gacopyz.h, gacopyz/server.c: Implement gacopyz_srv_conn. + * src/gram.y (parse_time_interval): Move to lib/parsetime.c. * src/mailfromd.h (parse_time_interval): Move to lib/libmf.h * lib/libmf.h (parse_time_interval): New proto. diff --git a/gacopyz/gacopyz.h b/gacopyz/gacopyz.h index 4c82183c..ec20ff9b 100644 --- a/gacopyz/gacopyz.h +++ b/gacopyz/gacopyz.h @@ -347,6 +347,8 @@ int gacopyz_srv_negotiate(gacopyz_srv_t srv); int gacopyz_srv_abort(gacopyz_srv_t srv); int gacopyz_srv_quit(gacopyz_srv_t srv); +int gacopyz_srv_conn(gacopyz_srv_t srv, const char *hostname, + struct sockaddr *sa); int gacopyz_srv_helo (gacopyz_srv_t p, const char *domain); int gacopyz_srv_envfrom (gacopyz_srv_t p, char **argv); int gacopyz_srv_envrcpt (gacopyz_srv_t p, char **argv); diff --git a/gacopyz/server.c b/gacopyz/server.c index e00517f1..36868b7f 100644 --- a/gacopyz/server.c +++ b/gacopyz/server.c @@ -1068,6 +1068,62 @@ gacopyz_srv_quit(gacopyz_srv_t srv) } int +gacopyz_srv_conn(gacopyz_srv_t srv, const char *hostname, struct sockaddr *sa) +{ + int rc; + milter_sockaddr_t *ps = (milter_sockaddr_t*)sa; + + GACOPYZ_ASSERT(srv); + if (srv->proto & SMFIP_NOCONNECT) + rc = SMFIR_CONTINUE; + else { + size_t hlen, vlen, size; + char *buf, *p, *q; + int code; + + hlen = strlen (hostname); + vlen = 3; + switch (ps->sa.sa_family) { + case AF_UNIX: + vlen += strlen (ps->sunix.sun_path); + code = SMFIA_UNIX; + break; + + case AF_INET: + vlen += 16; + code = SMFIA_INET; + break; + + default: + gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG, + _("%s: unknown family: %d"), + "gacopyz_srv_conn", + ps->sa.sa_family); + return SMFIR_CONTINUE; + } + + size = hlen + vlen + 2; + GACOPYZ_ALLOC(srv, buf = malloc (size)); + memcpy (buf, hostname, hlen + 1); + p = buf + hlen + 1; + *p++ = code; + switch (ps->sa.sa_family) { + case AF_UNIX: + strcpy (p, ps->sunix.sun_path); + break; + + case AF_INET: + q = inet_ntoa (ps->sin.sin_addr); + memcpy (p, q, 16); + } + + rc = gacopyz_srv_send_command(srv, SMFIC_CONNECT, buf, size); + free (buf); + } + return rc; +} + +int gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain) { int rc; diff --git a/pmult/pmult.c b/pmult/pmult.c index c106d849..cfd17288 100644 --- a/pmult/pmult.c +++ b/pmult/pmult.c @@ -13,6 +13,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ + #ifdef HAVE_CONFIG_H # include <config.h> #endif @@ -23,6 +24,7 @@ #include <mailutils/server.h> #include <mailutils/libargp.h> #include <sysexits.h> +#include <pthread.h> #include <gacopyz.h> #include "xalloc.h" #include "libmf.h" @@ -63,7 +65,6 @@ const char *package_bugreport = "<" PACKAGE_BUGREPORT ">"; #include "sm/pmfdef.h" #include "sm/pmfapi.h" - char *portspec; struct pmult_client @@ -75,7 +76,17 @@ struct pmult_client int logmask; }; -mu_list_t /* of gacopyz_srv_t */ client_list; +mu_list_t /* of struct pmult_client */ client_list; + +struct pmult_priv_data +{ + mu_list_t /* of gacopyz_srv_t */ srvlist; +}; + + +static pthread_mutex_t pmult_mutex = PTHREAD_MUTEX_INITIALIZER; +#define protect() pthread_mutex_lock (&pmult_mutex) +#define unprotect() pthread_mutex_unlock (&pmult_mutex) static int @@ -95,7 +106,7 @@ _cb_client_type (mu_debug_t debug, void *data, char *arg) } static int -cb_timeout(struct timeval *pt, mu_debug_t debug, char *arg) +cb_timeout (struct timeval *pt, mu_debug_t debug, char *arg) { const char *endp; time_t t; @@ -140,6 +151,68 @@ _cb_connect_timeout (mu_debug_t debug, void *data, char *arg) } static int +_cb_log_level (mu_debug_t debug, void *data, char *arg) +{ + struct pmult_client *clt = data; + int argc, i; + char **argv; + int rc; + + rc = mu_argcv_get_np (arg, strlen (arg), ",", NULL, 0, &argc, &argv, NULL); + if (rc) + { + mu_cfg_format_error (debug, MU_DEBUG_ERROR, + "mu_argcv_get: %s", mu_strerror (rc)); + return 1; + } + + for (i = 0; i < argc; i++) + { + char *p = argv[i]; + int lev; + int revert = 0; + int upto = 0; + + if (*p == '!') + { + p++; + revert = 1; + } + if (*p == '<') + { + p++; + upto = 1; + } + + lev = gacopyz_string_to_log_level (arg); + if (lev == -1) + { + mu_cfg_format_error (debug, MU_DEBUG_ERROR, + _("Invalid log level: %s"), arg); + return 1; + } + + if (revert) + { + if (upto) + clt->logmask &= ~SMI_LOG_UPTO (lev); + else + clt->logmask &= ~SMI_LOG_FROM (lev); + } + else + { + if (upto) + clt->logmask |= SMI_LOG_UPTO (lev); + else + clt->logmask |= SMI_LOG_FROM (lev); + } + } + + mu_argcv_free (argc, argv); + return 0; +} + +static int _cb_portspec (mu_debug_t debug, void *data, char *arg) { char **pptr = data, *ptr; @@ -200,6 +273,13 @@ struct mu_cfg_param client_cfg_param[] = { { "connect-timeout", mu_cfg_callback, NULL, 0, _cb_connect_timeout, N_("Set connect timeout."), N_("time") }, + { "log-level", mu_cfg_callback, NULL, 0, _cb_log_level, + N_("Set server log level. Arg is a list of items separated by commas or " + "whitespace. Each item is a log level optionally prefixed with `!' " + "to indicate `any level except this', or '<', meaning `all levels up " + "to and including this'. Log levels in order of decreasing priority " + "are: debug, info, warn, err, fatal."), + N_("arg: list") }, { NULL } }; @@ -211,6 +291,13 @@ struct mu_cfg_param pmult_cfg_param[] = { { NULL } }; +static void +pmult_client_free (struct pmult_client *clt) +{ + free (clt->name); + free (clt); +} + static int client_block_begin (mu_debug_t debug, char *name, void **section_data) { @@ -226,11 +313,16 @@ client_block_end (mu_debug_t debug, struct pmult_client *clt) gacopyz_srv_t gsrv; int rc = gacopyz_srv_create (&gsrv, clt->name, clt->url, clt->logmask); if (rc) - return 1; /* FIXME: error message */ + { + pmult_client_free (clt); + return 1; /* FIXME: error message */ + } + if (!client_list) { + gacopyz_srv_destroy (&gsrv); MU_ASSERT (mu_list_create (&client_list)); - mu_list_append (client_list, gsrv); + mu_list_append (client_list, clt); } return 0; } @@ -322,7 +414,66 @@ static struct argp argp = { NULL, NULL }; - + + +typedef int (*pmult_runfun_t) (pmse_ctx_P pmse_ctx, void *data); + +static int +pmult_runlist (struct pmult_priv_data *p, pmult_runfun_t runfun, + pmse_ctx_P pmse_ctx, void *data) +{ + int rc; + mu_iterator_t itr; + + protect (); + mu_list_get_iterator (p->srvlist, &itr); + unprotect (); + + for (mu_iterator_first (itr); !mu_iterator_is_done (itr); + mu_iterator_next (itr)) + { + gacopyz_srv_t gsrv; + + mu_iterator_current (itr, (void**)&gsrv); + protect (); + rc = runfun (pmse_ctx, data); + /* FIXME */ + unprotect (); + } + + protect (); + mu_iterator_destroy (&itr); + unprotect (); +} + +void +pmult_shutdown (pmse_ctx_P pmse_ctx, struct pmult_priv_data *p) +{ + mu_iterator_t itr; + + protect (); + mu_list_get_iterator (p->srvlist, &itr); + unprotect (); + + for (mu_iterator_first (itr); !mu_iterator_is_done (itr); + mu_iterator_next (itr)) + { + gacopyz_srv_t gsrv; + + mu_iterator_current (itr, (void**)&gsrv); + gacopyz_srv_quit (gsrv); + gacopyz_srv_close (gsrv); + gacopyz_srv_destroy (&gsrv); + } + protect (); + mu_iterator_destroy (&itr); + mu_list_destroy (&p->srvlist); + unprotect (); + + free (p); + sm_pmfi_set_ctx_se (pmse_ctx, NULL); +} + static void version (FILE *stream, struct argp_state *state) @@ -361,18 +512,70 @@ static sfsistat_T pmult_connect (pmse_ctx_P pmse_ctx, const char *hostname, sm_sockaddr_T *hostaddr) { + int rc; + mu_iterator_t itr; + struct pmult_priv_data *p; + + p = malloc (sizeof *p); + if (!p) + { + mu_error ("%s: accept", mu_strerror (ENOMEM)); + return SMTP_R_ACCEPT; + } + rc = mu_list_create (&p->srvlist); + if (rc) + { + mu_error ("mu_list_create: %s", mu_strerror (rc)); + free (p); + return SMTP_R_ACCEPT; + } + + protect (); + mu_list_get_iterator (client_list, &itr); + unprotect (); + + for (mu_iterator_first (itr); !mu_iterator_is_done (itr); + mu_iterator_next (itr)) + { + struct pmult_client *clt; + gacopyz_srv_t gsrv; + + mu_iterator_current (itr, (void**)&clt); + gacopyz_srv_create (&gsrv, clt->name, clt->url, clt->logmask); + gacopyz_srv_set_all_timeouts (gsrv, clt->timeout); + if (gacopyz_srv_connect (gsrv) != MI_SUCCESS) + { + mu_error (_("Failed to connect to %s (milter %s)"), + clt->url, clt->name); + gacopyz_srv_destroy (&gsrv); + } + gacopyz_srv_negotiate (gsrv); + protect (); + gacopyz_srv_conn (gsrv, hostname, &hostaddr->sa); + unprotect (); + mu_list_append (p->srvlist, gsrv); + } + + protect (); + mu_iterator_destroy (&itr); + unprotect (); + return SMTP_R_CONT; } static sm_ret_T pmult_close (pmse_ctx_P pmse_ctx) { + struct pmult_priv_data *p = sm_pmfi_get_ctx_se (pmse_ctx); + pmult_shutdown (pmse_ctx, p); return SM_SUCCESS; } static sfsistat_T pmult_helo (pmse_ctx_P pmse_ctx, const char *helohost, bool ehlo) { + struct pmult_priv_data *p = sm_pmfi_get_ctx_se (pmse_ctx); + return SMTP_R_CONT; } @@ -383,7 +586,7 @@ pmult_mail (pmse_ctx_P pmse_ctx, const char *mail, char **argv) } static sfsistat_T -pmult_rcpt(pmse_ctx_P pmse_ctx, const char *rcpt, char **argv) +pmult_rcpt (pmse_ctx_P pmse_ctx, const char *rcpt, char **argv) { return SMTP_R_CONT; } @@ -403,6 +606,8 @@ pmult_unknown (pmse_ctx_P pmse_ctx, const char *cmd) static sm_ret_T pmult_abort (pmse_ctx_P pmse_ctx) { + struct pmult_priv_data *p = sm_pmfi_get_ctx_se (pmse_ctx); + pmult_shutdown (pmse_ctx, p); return SM_SUCCESS; } |