/*-
* Copyright (c) 2002 Granch Ltd. All rigts reserved.
*
* All or some portions of this file are derived from material licensed
* to the Grahcn Ltd. and are reproduced herein with the permission of
* Granch Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE GRANCH LTD. AND THEIR CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author : Rashid N. Achilov E-Mail shelton@granch.ru
*
* @(#)parseconfig.c 0.97.3 (Granch Ltd.) 07/06/01
*/
/*------------------------------------------------------------------------
Kaspersky Anti-Virus mail filter, based on libmilter API
UNIX FreeBSD 4.6 version
Configuration file parsing subroutine
Call: void _KAV_milter_parse_config(char *cfgname);
When error is occured, this subroutine will stop program!
Max identifier length = 32 chars
Max decimal value length - 9 valuable digits
--------------------------------------------------------------------------*/
#include "kavmilter.h"
#include "externals.h"
#include "functions.h"
void _KAV_milter_parse_config(char *cfgname)
{
short int i, chparm, nochparm;
char *ids,*pos,*line,*buf,*bufx,*posix,*nafig,sig = 0;
char **pts;
int work,retcode = 0,bla;
struct stat sb;
// config_ent structures array, which describes parameters to parsing config
// file at whole. Contains fields Name - parameter name (up to 32 chars),
// Exit - processor's code, Valid - sing of validity parameter, HexMask -
// to properly setup a bit-field parameter (contains a mask, which will OR'ed
// with current signs byte, do not use to other types) and Which - address,
// which subroutine should place parameter value (void pointer!). All string
// variables should be (in structure) BEFORE all non-string (decimal, bool)
// variables!
struct config_ent paramConfig[] =
{
{ "ProgramName", PROGNAME, NULL, NULL, &_KAV_milter_config.progname },
{ "ProgramVersion", PROGVER, NULL, NULL, &_KAV_milter_config.progversion },
{ "SendmailPipe", STDCHAR, NULL, NULL, &_KAV_milter_config.sendmail_pipe },
{ "KAVPipe", STDCHAR, NULL, NULL, &_KAV_milter_config.KAV_pipe },
{ "PIDFile", STDCHAR, NULL, NULL, &_KAV_milter_config.pidfile },
{ "TempDirectory", STDCHAR, NULL, NULL, &_KAV_milter_config.temp_directory },
{ "KAVTimeout", STDINT, NULL, NULL, &_KAV_milter_config.KAV_timeout },
{ "SendmailTimeout", STDINT, NULL, NULL, &_KAV_milter_config.sendmail_timeout },
{ "DebugLevel", STDINT, NULL, NULL, &_KAV_milter_config.debug_level },
{ "DaemonMode", STDBOOL, NULL, 0x1, &_KAV_milter_config._idflags },
{ "InfectedAction", INFPARAM, NULL, NULL, &_KAV_milter_config._idflags },
{ "Null", NULL, NULL, NULL, NULL },
};
// Initial values to non-char parameters
_KAV_milter_config.KAV_timeout = 0;
_KAV_milter_config.sendmail_timeout = 0;
_KAV_milter_config.debug_level = 0;
// Detect quantity of parameters, quantity of string and non-string
// parameters to memory allocation
for(i = chparm = nochparm = 0; paramConfig[i].exit != NULL;i++)
if (paramConfig[i].exit == STDCHAR)
chparm++;
else
nochparm++;
// Allocate memory to config file string variables and local area
if ((_KAV_milter_config.progname =
(char *) calloc((MAXLEN * (chparm + MANDFIELDS)), 1))==NULL)
{
fprintf(stderr,"malloc error, out of memory : %s\n",strerror(errno));
_KAV_milter_close(EX_TEMPFAIL);
}
// Allocation memory to all local and string-variables-config-file areas
// Allocation done from 'ids' through 'nafig' and than all string-variables
// (if any).
for(i = 0, pts = &_KAV_milter_config.progversion,
bufx = _KAV_milter_config.progname + MAXLEN;
i < (chparm + MANDFIELDS - 1);i++, pts++, bufx += MAXLEN)
*pts = bufx;
_flags._alloc_config = OK;
// Allocating workspace
ids = (char *) malloc(MAXLEN + 2);
nafig = ids + MAXLEN;
// Open config file
if ((work = open(cfgname,O_RDONLY)) > 0)
{
stat(cfgname,&sb);
bufx = (char *) malloc(sb.st_size * 2);
buf = bufx + sb.st_size;
read(work,bufx,sb.st_size); // Fucked Feof()!
close(work);
// Now we drop lines with comment char at first position and strip spaces.
// After this procedure in output buffer lies only name=value pairs, separa-
// ted by '\n' char
if ((bla = readconfig('#',bufx,buf,sb.st_size)) == ERR)
{
fprintf(stderr,"cannot read configuration file %s\n",cfgname);
free(ids);
_KAV_milter_close(EX_TEMPFAIL);
}
// Reading filtered buffer line-by-line. Now we search '\n' char and at each
// loop round shift position on 1 greater than searched position. Loop stops
// when length filtered buffer will be exhausted.
for(line = buf;(line - buf) < bla;line = posix + 1,sig = NULL)
{
posix = strchr(line,'\n');
// Search '=' char and taking string BEFORE it as parameter name
pos = strchr(line,'=');
bzero(ids,32);
strncpy(ids, line, pos - line);
// Search in config file parameters array this parameter. Search stops when
// parameter will be found or parameters quantity will be expired. When
// search flag is on, search terminate immediately.
for(i = 0;(i < (chparm + nochparm)) && (!sig);i++)
if (!(strcmp(ids,paramConfig[i].name)))
{
switch(paramConfig[i].exit)
{
// Main loop. Switch by processor type. Processor type STDCHAR processed
// string value through copying it to address from configParam[i].which
// pointer. Length of copying string calculated as difference between
// '\n' char and '=' char (and less to 1). Processor type STDINT processed
// digital values in signed short int format (up to 32767) through storing
// to address in paramConfig[i].which pointer a value, started from '='
// (greather to 1).
case STDINT: if ((*(short *) paramConfig[i].which =
b_atoi(pos + 1, SSMAX)) >= NO)
sig = paramConfig[i].valid = OK;
else
paramConfig[i].valid = ERR;
continue;
case STDCHAR: strncpy(*((char **) paramConfig[i].which),
pos + 1,posix - pos - 1);
sig = paramConfig[i].valid = OK;
continue;
case STDBOOL: bzero(nafig,4);
strncpy(nafig,pos+1,posix-pos-1);
if (!strcasecmp(nafig,"YES"))
*((char *) paramConfig[i].which) ^=
paramConfig[i].hexmask;
sig = paramConfig[i].valid = OK;
continue;
case INFPARAM: bzero(nafig,8);
strncpy(nafig,pos+1,posix-pos-1);
if (!strcasecmp(nafig,"reject"))
*((char *) paramConfig[i].which) ^= 0x2;
else
*((char *) paramConfig[i].which) ^= 0x4;
sig = paramConfig[i].valid = OK;
continue;
default: fprintf(stderr,"unknown processor exit code %d\n",
paramConfig[i].exit);
free(ids);
_KAV_milter_close(EX_TEMPFAIL);
}
}
}
free(bufx);
// Check on validity parameters processing
for(i = 0;i < (chparm + nochparm);i++)
{
// Store mandatory fields, can missed in config file
if (!(strcmp(paramConfig[i].name,"ProgramName")))
{
strncpy(*((char **) paramConfig[i].which),
kavfilter.xxfi_name,strlen(kavfilter.xxfi_name));
paramConfig[i].valid = OK;
}
if (!(strcmp(paramConfig[i].name,"ProgramVersion")))
{
sprintf(*((char **) paramConfig[i].which),
"%1d.%2d.%1d",VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH);
paramConfig[i].valid = OK;
}
// Checkout all parsed fields
if (paramConfig[i].valid == NO)
{
fprintf(stderr,
"parameter %s invalid: %s\n",
paramConfig[i].name, (char *) paramConfig[i].which);
retcode = ERR;
}
}
// When errors in split config file were detected, stop processing
if (retcode == ERR)
{
fprintf(stderr,
"config file split error detected. %s aborted\n",progname);
free(ids);
_KAV_milter_close(EX_TEMPFAIL);
}
}
// Specified configuration file didn't found
else
{
fprintf(stderr,"opening file %s error: %s\n",cfgname,strerror(errno));
_KAV_milter_close(EX_TEMPFAIL);
}
// Free allocated workspace
free(ids);
}
syntax highlighted by Code2HTML, v. 0.9.1