ossp-pkg/lmtp2nntp/lmtp2nntp_config.c
1.18
/*
** Copyright (c) 2001-2002 The OSSP Project <http://www.ossp.org/>
** Copyright (c) 2001-2002 Cable & Wireless Deutschland <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/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_config.c: config handling
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
/* third party (included) */
#include "lmtp2nntp_argz.h"
/* third party (linked in) */
#include "str.h"
#include "val.h"
#include "popt.h"
#include "l2.h"
/* library version check (compile-time) */
#define STR_VERSION_HEX_REQ 0x009206
#define STR_VERSION_STR_REQ "0.9.6"
#ifdef STR_VERSION_HEX
#if STR_VERSION_HEX < STR_VERSION_HEX_REQ
#error "require a newer version of OSSP Str"
#endif
#endif
/* own headers */
#include "lmtp2nntp_global.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_DMALLOC_H) && defined(DMALLOC)
#include "dmalloc.h"
#endif
#include "lmtp2nntp_option.h"
#include "lmtp2nntp_config.h"
#include "lmtp2nntp_lmtp.h"
#include "lmtp2nntp_nntp.h"
#include "lmtp2nntp_msg.h"
#include "fixme.h"
#define _LMTP2NNTP_VERSION_C_AS_HEADER_
#include "lmtp2nntp_version.c"
#undef _LMTP2NNTP_VERSION_C_AS_HEADER_
#ifndef FALSE
#define FALSE (1 != 1)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#ifndef NUL
#define NUL '\0'
#endif
static l2_result_t
formatter_prefix(l2_context_t *_ctx, const char id, const char *param,
char *bufptr, size_t bufsize, size_t *buflen, va_list *ap)
{
lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx->vp;
if ((ctx->msg != NULL) && (ctx->msg->cpFid != NULL)) {
sprintf(bufptr, "%s: ", ctx->msg->cpFid);
*buflen = strlen(bufptr);
}
else
*buflen = 0;
return L2_OK;
}
static l2_result_t
formatter_errno(l2_context_t *_ctx, const char id, const char *param,
char *bufptr, size_t bufsize, size_t *buflen, va_list *ap)
{
sprintf(bufptr, "(%d) %s", errno, strerror(errno));
*buflen = strlen(bufptr);
return L2_OK;
}
void config_context(lmtp2nntp_t *ctx)
{
ex_t ex;
optionval_t *ov;
//char *cp;
int rc;
/* create L2 environment */
if (l2_env_create(&ctx->l2_env) != L2_OK) {
fprintf(stderr, "%s:Error: failed to create L2 environment\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (l2_env_formatter(ctx->l2_env, 'P', formatter_prefix, &ctx->ctx) != L2_OK) {
fprintf(stderr, "%s:Error: logging failed to register prefix formatter\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (l2_env_formatter(ctx->l2_env, 'D', l2_util_fmt_dump, NULL) != L2_OK) {
fprintf(stderr, "%s:Error: logging failed to register dump formatter\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (l2_env_formatter(ctx->l2_env, 'S', l2_util_fmt_string, NULL) != L2_OK) {
fprintf(stderr, "%s:Error: logging failed to register string formatter\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (l2_env_formatter(ctx->l2_env, 'm', formatter_errno, NULL) != L2_OK) {
fprintf(stderr, "%s:Error: logging failed to register errno formatter\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (val_get(ctx->val, "option.l2spec", &ov) != VAL_OK) {
fprintf(stderr, "%s:Error: (internal) config did not register 'l2spec' option\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (ov->data.s != NULL) {
if ((rc = l2_spec(&ctx->l2, ctx->l2_env, ov->data.s)) != L2_OK) {
fprintf(stderr, "%s:Error: logging failed to create stream\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (l2_channel_levels(ctx->l2, L2_LEVEL_ALL, L2_LEVEL_NONE) != L2_OK) { /* FIXME should this globalmask and flushmask be user-configurable? */
fprintf(stderr, "%s:Error: logging failed to set global logging level\n", ctx->progname);
CU(ERR_EXECUTION);
}
if (l2_channel_open(ctx->l2) != L2_OK) {
fprintf(stderr, "%s:Error: logging failed to open channel stream\n", ctx->progname);
CU(ERR_EXECUTION);
}
}
/* from this point on logging is up and running and fprintf(stderr, ...)
* should not be used in the remainder of the program flow.
*/
log1(ctx, NOTICE, "startup, version %s", lmtp2nntp_version.v_gnu);
/* --childsmax SINGLE */
try {
if ( (val_get(ctx->val, "option.childsmax", &ov) != VAL_OK)
|| (ov->ndata != 1)
|| (ov->data.s == NULL)
) throw(0,0,0);
log1(ctx, TRACE, "--childsmax = \"%s\"", ov->data.s);
if ((ctx->option_childsmax = atoi(ov->data.s)) <= 0) {
log1(ctx, ERROR, "number (%d) out of range for option --childsmax\n", ctx->option_childsmax);
throw(0,0,0);
}
}
catch (ex) {
log1(ctx, ERROR, "caught class %s\n", ex.ex_class == NULL ? "N/A" : (char *)ex.ex_class );
log1(ctx, ERROR, "caught object %s\n", ex.ex_object == NULL ? "N/A" : (char *)ex.ex_object);
log1(ctx, ERROR, "caught value %s\n", ex.ex_value == NULL ? "N/A" : (char *)ex.ex_value );
rethrow;
}
/* --daemonize FLAG */
try {
if ( (val_get(ctx->val, "option.daemonize", &ov) != VAL_OK)
|| (ov->ndata != 1)
|| (ov->data.f != 1)
) throw(0,0,0);
log1(ctx, TRACE, "--daemonize = %d", ov->data.f);
ctx->option_daemon = TRUE;
}
catch (ex)
rethrow;
/* --kill FLAG */
try {
if ( (val_get(ctx->val, "option.kill", &ov) != VAL_OK)
|| (ov->ndata != 1)
|| (ov->data.f != 1)
) throw(0,0,0);
log1(ctx, TRACE, "--kill = %d", ov->data.f);
ctx->option_killflag = TRUE;
}
catch (ex)
rethrow;
/* --pidfile SINGLE */
try {
if ( (val_get(ctx->val, "option.pidfile", &ov) != VAL_OK)
|| (ov->ndata != 1)
|| (ov->data.s == NULL)
) throw(0,0,0);
log1(ctx, TRACE, "--pidfile = \"%s\"", ov->data.s);
ctx->option_pidfile = ov->data.s;
}
catch (ex)
rethrow;
/* --acl MULTI */
try {
int i;
char *cp;
struct acl *acl;
if ( (val_get(ctx->val, "option.acl", &ov) != VAL_OK)
|| ((ov->ndata >= 1) && (ov->data.m == NULL))
) throw(0,0,0);
for (i = 0; i < ov->ndata; i++)
log2(ctx, TRACE, "--acl[%d] = \"%s\"", i, (ov->data.m)[i]);
log1(ctx, DEBUG, "ov->ndata = %d", ov->ndata);
if ((acl = (struct acl *)malloc(ov->ndata * sizeof(struct acl))) == NULL) throw(0,0,0);
for (i = 0; i < ov->ndata; i++) {
cp = (ov->data.m)[i];
log2(ctx, DEBUG, "cp = (data.m)[%d] = \"%s\"", i, cp);
//ctx->option_acl[ctx->option_aclc].acl = strdup(cp);
}
}
catch (ex)
rethrow;
#if 0
if (argz_create_sep(optarg, ',', &azACL, &asACL) != 0)
CU(ERR_EXECUTION);
cp = NULL;
while ((cp = argz_next(azACL, asACL, cp)) != NULL) {
if (ctx->option_aclc >= MAXACLS) {
fprintf(stderr, "%s:Error: Too many ACL (%d) using option -a\n", ctx->progname, ctx->option_aclc);
CU(ERR_EXECUTION);
}
ctx->option_acl[ctx->option_aclc].acl = strdup(cp);
if (cp[0] == '!') {
ctx->option_acl[ctx->option_aclc].not = TRUE;
cpAddr = strdup(cp+1);
}
else {
cpAddr = strdup(cp);
}
if ((cpPrefixLen = strrchr(cpAddr, '/')) != NULL)
*cpPrefixLen++ = NUL;
else
cpPrefixLen = "-1";
ctx->option_acl[ctx->option_aclc].prefixlen = atoi(cpPrefixLen);
if ((rc = sa_addr_create(&ctx->option_acl[ctx->option_aclc].saa)) != SA_OK) {
fprintf(stderr, "%s:Error: Creating address failed for -a option (%d)\n",
ctx->progname, rc);
}
if ((rc = sa_addr_u2a(ctx->option_acl[ctx->option_aclc].saa, "inet://%s:0", cpAddr)) != SA_OK) {
fprintf(stderr, "%s:Error: Parsing host address failed for \"%s:0\" (%d)\n",
ctx->progname, cpAddr, rc);
CU(ERR_EXECUTION);
}
ctx->option_aclc++;
free(cpAddr);
}
free(azACL);
#endif
CUS:
return;
}