/*
**  OSSP lmtp2nntp - Mail to News Gateway
**  Copyright (c) 2002-2003 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2002-2003 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2002-2003 Cable & Wireless Germany <http://www.cw.com/de/>
**
**  This file is part of OSSP lmtp2nntp, an LMTP speaking local
**  mailer which forwards mails as Usenet news articles via NNTP.
**  It can be found at http://www.ossp.org/pkg/tool/lmtp2nntp/.
**
**  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 the Free Software Foundation; either version
**  2.0 of the License, or (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**  General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this file; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
**  USA, or contact the OSSP project <ossp@ossp.org>.
**
**  lmtp2nntp_l2.c: var logging channel for l2
*/

#include <stdarg.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_DMALLOC_H) && defined(WITH_DMALLOC)
#include "dmalloc.h"
#endif
#include "lmtp2nntp_common.h"

/* declare private channel configuration */
typedef struct {
    var_t *var;
} l2_ch_var_t;

/* create channel */
static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch)
{
    l2_ch_var_t *cfg;

    /* allocate private channel configuration */
    if ((cfg = (l2_ch_var_t *)malloc(sizeof(l2_ch_var_t))) == NULL)
        return L2_ERR_MEM;

    /* initialize configuration with reasonable defaults */
    cfg->var = NULL;

    /* link private channel configuration into channel context */
    ctx->vp = cfg;

    return L2_OK;
}

/* configure channel */
static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap)
{
    l2_ch_var_t *cfg;

    /* parameter checks */
    if ((cfg = (l2_ch_var_t *)ctx->vp) == NULL)
        return L2_ERR_ARG;

    /* special parameter parsing */
    if ((cfg->var = (var_t *)va_arg(ap, void *)) == NULL)
        return L2_ERR_ARG;

    return L2_OK;
}

/* write to channel */
static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch,
                              l2_level_t level, const char *buf, size_t buf_size)
{
    l2_ch_var_t *cfg;
    l2_channel_t *downstream;
    l2_result_t rv;
    var_rc_t var_rc;
    char *buf2 = NULL;
    size_t buf2_size;

    /* parameter checks */
    if ((cfg = (l2_ch_var_t *)ctx->vp) == NULL)
        return L2_ERR_ARG;
    if (cfg->var == NULL)
        return L2_ERR_ARG;

    /* expand variables */
    if ((var_rc = var_expand(cfg->var, buf, buf_size, &buf2, &buf2_size, FALSE)) != VAR_OK) {
        return L2_ERR_USE;
    }

    /* push data downstream */
    downstream = NULL;
    while ((rv = l2_channel_downstream(ch, &downstream)) == L2_OK)
        if ((rv = l2_channel_write(downstream, level, buf2, buf2_size)) != L2_OK)
            break;

    if (buf2 != NULL)
        free(buf2);

    return rv;
}

/* destroy channel */
static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch)
{
    l2_ch_var_t *cfg = (l2_ch_var_t *)ctx->vp;

    /* destroy channel configuration */
    free(cfg);

    return L2_OK_PASS;
}

/* exported channel handler structure */
l2_handler_t l2_handler_var = {
    "lmtp2nntp-l2var",
    L2_CHANNEL_FILTER,
    hook_create,
    hook_configure,
    NULL,
    hook_write,
    NULL,
    NULL,
    hook_destroy
};

