#ifndef _DW_OPTIONS_C
#define _DW_OPTIONS_C

/*--------------------------------------------------------------------------
 *  Copyright (c) 2001-2004 Igor Daniloff. 
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at this directory.
 *------------------------------------------------------------------------*/
 
#ifndef lint
static const char rcsid[] = "$Id: dw_options.c,v 1.116.2.2 2009/11/10 11:39:29 akorkov Exp $";
#endif
#define OKD(a) //printLib( DW_LL_ERROR, "ok - %d",a)
#if defined(__UNIX_DW)
#include <unistd.h>
#endif /* UNIX */
#include <sys/types.h>
#include <sys/stat.h>
#if defined(DW_SENDMAIL)
#include <sys/time.h>
#endif /* SENDMAIL */
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#if defined(__UNIX_DW)
#include <pwd.h>
#if !defined(EMX_DW)
#include <sysexits.h>
#endif /* not EMX */
#endif /* UNIX */
#if defined(DW_SENDMAIL)
#include "md5.h"
#include "libmilter/mfapi.h"
#endif /* SENDMAIL */
#include "dwc_conf.h"
#include "dwc_macro.h"
#if defined(__UNIX_DW)
#include "dwc_err.h"
#include "dwc_lib.h"
#endif /* UNIX */
#if defined(__WIN32_DW)
#include <direct.h>
#include "dw_winlib.h"
#endif /* WIN32 */
#include "dwc_scan.h"
#include "dw_options.h"
#if !defined(DW_SAMBA)
#include "dw_mail.h"
#include "dw_mailsend.h"
#endif /* not SAMBA */
#include "dw_util.h"
#if defined(DW_SAMBA)
typedef unsigned int uint32;
//included from addons/md5
#include "md5.h"
#endif


#if !defined(DW_SAMBA)
#include "dw_files.h"

#define HELP_PARAM_1    "-?"
#define HELP_PARAM_2    "-h"
#define HELP_PARAM_3    "--help"
#define CONF_PARAM      "--conf="
#define VER_PARAM       "--version"
#define DEBUG_PARAM     "--debug"
#if !defined(__WIN32_DW)
#define CHECK_PARAM     "--check_only"
#define USER_PARAM      "--check_user="
#endif /* not WIN32 */
#endif /* not SAMBA */

#if defined(DW_COURIER)
#define PROG_NAME                   "drweb-courier"
#define PROG_FULLNAME               "Dr.Web(R) Filter for courier-mta"
#define PROG_NOTE                   "Note: filter will been started by Courier-MTA automatically after install"
#define CONF_FNAME                  "drweb_courier.conf"
#endif /* COURIER */

#if defined(DW_SENDMAIL)
#define PROG_NAME                   "drweb-smf"
#define PROG_FULLNAME               "Dr.Web(R) Filter for sendmail"
#define PROG_NOTE                   ""
#define CONF_FNAME                  "drweb_smf.conf"
#endif /* SENDMAIL */

#if defined(DW_CGP)
#define PROG_FULLNAME               "Dr.Web(R) Plug-in for CommuniGate Pro"
#define PROG_NOTE                   "Note: plug-in will been started by CommuniGate Pro automatically"
#if defined(__UNIX_DW)
#define PROG_NAME                   "drweb-cgp"
#define CONF_FNAME                  "drweb_cgp.conf"
#endif /* UNIX */
#if defined(__WIN32_DW)
#define PROG_NAME                   "drweb-cgp.exe"
#define CONF_FNAME                  "DrWeb\\etc\\drweb_cgp.conf"
#endif /* WIN32 */
#endif /* CGP */

#if defined(DW_MIO)
#define PROG_NAME                   "drweb-mio"
#define PROG_FULLNAME               "Dr.Web(R) Plug-in for Mobico MIO Server"
#define PROG_NOTE                   "Note: plug-in will been started by MIO automatically"
#define CONF_FNAME                  "drweb_mio.conf"
#endif /* MIO */

#if defined(DW_ZMAILER)
#define PROG_NAME                   "drweb-zmailer"
#define PROG_FULLNAME               "Dr.Web(R) Filter for zmailer"
#define PROG_NOTE                   "Note: filter will been started by ZMailer automatically"
#define CONF_FNAME                  "drweb_zmailer.conf"
#endif /* ZMAILER */

#if defined(DW_QMAIL)
#define PROG_NAME                   "qmail-queue"
#define PROG_FULLNAME               "Dr.Web(R) Filter for qmail"
#define PROG_NOTE                   "Note: filter will been started by QMail system automatically after install"
#define CONF_FNAME                  "drweb_qmail.conf"
#endif /* QMAIL */

#if defined(DW_POSTFIX)
#define PROG_NAME                   "drweb-postfix"
#define PROG_FULLNAME               "Dr.Web(R) Filter for postfix"
#define PROG_NOTE                   "Note: filter will been started by Postfix system automatically after install"
#define CONF_FNAME                  "drweb_postfix.conf"
#endif /* POSTFIX */

#if defined(DW_EXIM)
#define PROG_NAME                   "drweb-exim"
#define PROG_FULLNAME               "Dr.Web(R) Filter for exim"
#define PROG_NOTE                   "Note: filter will been started by Exim system automatically after install"
#define CONF_FNAME                  "drweb_exim.conf"
#endif /* EXIM */

#if defined(DW_SAMBA)
#define PROG_NAME                   "drweb-samba"
#define PROG_FULLNAME               "Dr.Web(R) VFS Filter for Samba"
#define PROG_NOTE                   "Note: this is a shared library object"
#define CONF_FNAME                  "smb_spider.conf"
#endif /* SAMBA */

#if defined(__UNIX_DW)
#if !defined(EMX_DW)
#if defined(__NETBSD_LAYOUT__)
#define OS_SPEC_CONFNAME            "/usr/pkg/etc/drweb/"CONF_FNAME
#else  /* __NETBSD_LAYOUT__ */
#if defined(FreeBSD_DW)
#define OS_SPEC_CONFNAME            "/usr/local/etc/drweb/"CONF_FNAME
#else /* FreeBSD */
#define OS_SPEC_CONFNAME            "/opt/drweb/"CONF_FNAME
#endif /* FreeBSD */
#endif /* __NETBSD_LAYOUT__ */
#else /* EMX */
#define OS_SPEC_CONFNAME            "/emx/opt/drweb/etc/"CONF_FNAME
#endif /* EMX */
#define FHS_SPEC_CONFNAME           "/etc/drweb/"CONF_FNAME
#endif /* UNIX */

#if !defined(SMFI_DRWEB_PATCHED)
#define LOCKED_LIST                 FALSE
#else /* SMFI_DRWEB_PATCHED */
#define LOCKED_LIST                 TRUE
#endif /* SMFI_DRWEB_PATCHED */

#define TAG_NULL        "\000"
#define TAG_UNKNOWN     "?"
#define TAG_PASS        "P"
#define TAG_QUARANTINE  "Q"
#define TAG_REJECT      "R"
#if !defined(DW_MIO)
#if defined(DW_HAVE_DISCARD)
#define TAG_DISCARD     "D"
#else /* not HAVE_DISCARD */
#define TAG_DISCARD     TAG_UNKNOWN
#endif /* HAVE_DISCARD */
#if defined(__UNIX_DW)
#define TAG_CURE        "C"
#define TAG_DELETE      "L"
#endif /* UNIX */
#if defined(__WIN32_DW)
#define TAG_CURE        TAG_UNKNOWN
#define TAG_DELETE      TAG_UNKNOWN
#endif /* WIN32 */
#define TAG_ERROR       TAG_UNKNOWN
#if !defined(DW_SAMBA)
#define TAG_REDIRECT    "F"
#define TAG_CONTINUE    "U"
#define TAG_TEMPFAIL    "T"
#else /* SAMBA */
#define TAG_RENAME      "M"
#endif /* not SAMBA */
#else /* MIO */
#define TAG_ERROR       "E"
#define TAG_CONTINUE    TAG_UNKNOWN
#define TAG_DISCARD     TAG_UNKNOWN
#define TAG_TEMPFAIL    TAG_UNKNOWN
#define TAG_REDIRECT    TAG_UNKNOWN
#define TAG_CURE        TAG_UNKNOWN
#define TAG_DELETE      TAG_UNKNOWN
#endif /* not MIO */

#if !defined(DW_SAMBA)
#if !defined(DW_MIO)
#define SET_EMPTYFROM     TAG_REJECT""TAG_DISCARD""TAG_CONTINUE""TAG_NULL
#if defined(__UNIX_DW)
#define SET_CURE_FAIL               TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_INCURABLE               TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_DELETE""TAG_NULL
#endif /* UNIX */
#endif /* MIO */
#if defined(__UNIX_DW)
#define SET_FILTER_REJECT           TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#endif /* UNIX */
#define SET_INFECTED                TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_DELETE""TAG_CURE""TAG_NULL
#define SET_ADWARE        TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_DIALER        TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_JOKE          TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_RISKWARE      TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_HACKTOOL      TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_SUSPICIOUS    TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_DISCARD""TAG_QUARANTINE""TAG_NULL
#define SET_ARCHIVE_RES   TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_QUARANTINE""TAG_NULL
#define SET_SKIPOBJ       TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_QUARANTINE""TAG_NULL
#define SET_SCANERR       TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_TEMPFAIL""TAG_QUARANTINE""TAG_NULL
#define SET_PROCERR       TAG_PASS""TAG_REJECT""TAG_REDIRECT""TAG_ERROR""TAG_TEMPFAIL""TAG_QUARANTINE""TAG_NULL
#define SET_LICENSE       TAG_PASS""TAG_REJECT""TAG_TEMPFAIL""TAG_NULL
#else /* SAMBA */
#define SET_ARCHIVE       TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_INFECTED                TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_CURE""TAG_NULL
#define SET_INCURABLE               TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_CURE_FAIL               TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_ADWARE        TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_DIALER        TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_JOKE          TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_RISKWARE      TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_HACKTOOL      TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_SUSPICIOUS    TAG_PASS""TAG_REJECT""TAG_QUARANTINE""TAG_RENAME""TAG_DISCARD""TAG_NULL
#define SET_SCANERR       TAG_PASS""TAG_REJECT""TAG_NULL
#define SET_PROCERR       TAG_PASS""TAG_REJECT""TAG_NULL
#define SET_SKIPOBJ       TAG_PASS""TAG_REJECT""TAG_NULL
#define SET_ARCHIVE_RES   TAG_PASS""TAG_REJECT""TAG_NULL
#define SET_LICENSE       TAG_PASS""TAG_REJECT""TAG_NULL
#endif /* not SAMBA */

#define ACT_CMP( a, v, t, s )  ( ( (0 == DWC_strncasecmp( (a), (v), strlen((v)) ))\
                                   && (strstr((s),(t)) != NULL) ) ? TRUE : FALSE )

#if !defined(DW_SAMBA)
dwc_sls_t          FilenameModes[] = {
        { "Std",    DW_NAME_STD },
#if !defined(__WIN32_DW)
        { "Tai",    DW_NAME_TAI },
#if !defined(EMX_DW)
        { "Rand48", DW_NAME_RAND48 },
#endif /* not EMX */
#endif /* not WIN */
        END_SLS_LINE };

#if !defined(DW_MIO)
dwc_sls_t           DenyModes[] = {
        { "byAll",    DW_DM_ALL },
        { "byOne",    DW_DM_ONE },
        { "bySender", DW_DM_SENDER },
        { "bySenderAndOneRecipient", DW_DM_SENDER_AND_ONE_RCPT },
        { "byOneRecipient", DW_DM_ONE_RCPT },
        { "byAllRecipients", DW_DM_ALL_RCPTS },
        END_SLS_LINE };
#endif /* MIO */

#endif /* not SAMBA */

#if defined(DW_SAMBA)        
dwc_sls_t           ScanModes[] = {
        { "onRead",       DW_SM_ON_READ },
        { "onWrite",      DW_SM_ON_WRITE },
        { "onReadWrite",  DW_SM_ON_ACCESS },
        { "onAccess",     DW_SM_ON_ACCESS },
        END_SLS_LINE };
#endif /* SAMBA */        

#if !defined(DW_SAMBA)
static dwc_bool_t have_mailbomb_section, have_archive_section, have_rule_section, have_agent_section, have_license_section, have_malware_section;
#if !defined(DW_MIO)    
static dwc_bool_t have_curednotify_section;
#endif /* not MIO */
#endif /* SAMBA */

#if defined(DW_SENDMAIL)
static dwc_bool_t dw_generate_hash_string( dwc_string_t salt, dwc_hash_t hstr );
#endif /* SENDMAIL */
#if !defined(DW_SAMBA)            
static dwc_void_t dw_show_version( const char *progname );
static dwc_void_t dw_show_usage( const char *progname );
static dwc_void_t dw_show_actions( dwcf_action_opt_t *opt );
static dwc_bool_t dw_set_mailaddr( dwc_string_t str, dwc_string_t * maddr );
#endif /* not SAMBA */
static dwc_bool_t dw_set_action( const char* str, const char* set, dwc_action_t* act );

#if !defined(DW_SAMBA)            
/* ----------------------------------------------------------------------- */
static dwc_void_t dw_show_version( const char *progname )
{
    if( !progname ) 
    {
        progname = PROG_NAME;
    }
    printf("\n%s - %s %s\n\n", progname, PROG_FULLNAME, DW_VERSION );
    exit(0);
}

/* ----------------------------------------------------------------------- */
static dwc_void_t dw_show_usage( const char *progname )
{
    if( !progname ) 
    {
        progname = PROG_NAME;
    }
#if defined(DW_PIPE)
    printf("\nUsage : %s [options] -f<sender> -- <recipients>\n", progname);
#else 
    printf("\nUsage : %s [options]\n", progname);
#endif /* PIPE */    
    printf("%s - scans mail for viruses\n\n", PROG_FULLNAME);
    printf("Options:\n");
    printf("\t%s, %s, %s - show this help and exit\n", HELP_PARAM_1, HELP_PARAM_2, HELP_PARAM_3);
    printf("\t%s - show filter version and exit\n", VER_PARAM);
#if defined(__UNIX_DW)
#if !defined(DW_QMAIL)    
    printf("\t%s<username> - user account used for check (works only with %s option)\n", USER_PARAM, CHECK_PARAM );
#endif /* QMAIL */    
#if defined(DW_SENDMAIL)
    printf("\t  (FilterAccount parameter from configuration file will been ignored\n");
#endif /* SENDMAIL */    
    printf("\t%s - perform configuration check and exit\n", CHECK_PARAM );
    printf("\t%s - set very verbose output in check mode\n", DEBUG_PARAM );
#if defined(DW_QMAIL) || defined(DW_ZMAILER) || defined(DW_COURIER)
    printf("\nConf file must be present in one of location:\n");     
#else /* not (QMAIL or ZMAILER or COURIER) */    
    printf("\t%s<pathname> - specify full pathname to configuration file\n", CONF_PARAM );
    printf("\nIf full pathname to conf file are not specified, then there is searched in:\n"); 
#endif /* QMAIL or ZMAILER or COURIER */    
    printf(" "FHS_SPEC_CONFNAME"\n");
    printf(" "OS_SPEC_CONFNAME"\n");
    printf("\n"PROG_NOTE"\n");
    printf("\n\nATTENTION:\n THIS VERSION IS NOT COMPATIBLE WITH DrWEB DAEMON VERSIONS LESS THAT 4.33 !!!\n");
#endif /* UNIX */
#if defined(__WIN32_DW) && defined(DW_CGP)
    printf("\t%s<pathname> - specify full pathname to configuration file\n", CONF_PARAM );
    printf("\nIf full pathname to conf file are not specified, then there is searched in:\n"); 
    printf(" $CommuniGateProBaseDir\\"CONF_FNAME"\n");
    printf("\n"PROG_NOTE"\n");
#endif /* WIN32 and CGP */
    exit(EX_USAGE);
}
#endif /* not SAMBA */

/*-------------------------------------------------------------------------*/
#define GET_STR_FROM_PARAM( str, param )\
BEGIN_MACRO\
    if( strlen( argv[i] ) > clen )\
    {\
        (str) = DWC_Strdup( argv[i] + clen );\
        if( !(str) )\
        {\
            printLib( DW_LL_ERROR, "conf: %s(%d) no memory", __FILE__, __LINE__ );\
            return FALSE;\
        }\
    } else {\
        printLib( DW_LL_ERROR, "conf: misformatted " param " option" );\
        return FALSE;\
    }\
END_MACRO    

/*-------------------------------------------------------------------------*/
dwc_void_t dw_show_actions( dwcf_action_opt_t *opt )
{
    printLib( DW_LL_VERBOSE, "load_settings: action on license limitations = %s", dw_get_action(opt->on_license_error) );
    printLib( DW_LL_VERBOSE, "load_settings: action on infected = %s", dw_get_action(opt->on_infected) );
#if defined(__UNIX_DW)
#if !defined(DW_MIO)
    printLib( DW_LL_VERBOSE, "load_settings: action on incurable = %s", dw_get_action(opt->on_incurable) );
#if !defined(DW_SAMBA)
    printLib( DW_LL_VERBOSE, "load_settings: action on curing fail = %s", dw_get_action(opt->on_cure_fail) );
#endif /* SAMBA */
#endif /* not MIO */
#endif /* UNIX */
    printLib( DW_LL_VERBOSE, "load_settings: action on suspicious = %s", dw_get_action(opt->on_suspicious) );
    printLib( DW_LL_VERBOSE, "load_settings: action on advertizing software (adware) = %s", dw_get_action(opt->on_adware) );
    printLib( DW_LL_VERBOSE, "load_settings: action on dialers = %s", dw_get_action(opt->on_dialer) );
    printLib( DW_LL_VERBOSE, "load_settings: action on jokes, hoaxes = %s", dw_get_action(opt->on_joke) );
    printLib( DW_LL_VERBOSE, "load_settings: action on potentially dangerous software (riskware) = %s", dw_get_action(opt->on_riskware) );
    printLib( DW_LL_VERBOSE, "load_settings: action on intrusion tools (hacktools) = %s", dw_get_action(opt->on_hacktool) );
#if !defined(DW_SAMBA)
#if defined(__UNIX_DW)
    printLib( DW_LL_VERBOSE, "load_settings: action on rule filter alert = %s", dw_get_action(opt->on_hre_filter_reject) );
#endif /* UNIX */
#if !defined(DW_MIO)
    printLib( DW_LL_VERBOSE, "load_settings: action on empty from = %s", dw_get_action(opt->on_empty_from) );
#endif /* MIO */
#endif /* SAMBA */
    printLib( DW_LL_VERBOSE, "load_settings: action on skipped = %s", dw_get_action(opt->on_skip) );
    printLib( DW_LL_VERBOSE, "load_settings: action on archive restrictions = %s", dw_get_action(opt->on_archive_restriction) );
    printLib( DW_LL_VERBOSE, "load_settings: action on scanning error = %s", dw_get_action(opt->on_scan_error) );
    printLib( DW_LL_VERBOSE, "load_settings: action on processing error = %s", dw_get_action(opt->on_proc_error) );
}                

/*-------------------------------------------------------------------------*/
#ifdef DW_SAMBA
/*
 * this function is analog of dw_load_settings() 
 * interface has not changed on the future for other compinents
 */
dwc_bool_t dw_load_settings_agent ( int _argc, char *_argv[], dw_filter_settings_t *opt )
{
#if defined(DW_PIPE)
    char            *ptrc = NULL;
    unsigned long    msg_size = 0;
#endif /* PIPE */
#if !defined(DW_SAMBA)
    size_t           clen;
    int              i;
    dwc_string_t     user = NULL;
    dwc_bool_t       test_mode = FALSE;
#endif /* not SAMBA */    
    int              retcode;    
    char *           agent_address = NULL;
    dwc_conf_task_t  conf[] = {
#if defined(__UNIX_DW)
      DWC_CONF_TASK( "DaemonCommunication", &opt->comm, (dwc_section_reader_t)read_comm_opt_agent, free_comm_opt, FALSE ),
#endif /* UNIX */
#if defined(__WIN32_DW)
        DWC_CONF_TASK( "Engine", &opt->engine, read_engine_opt, free_engine_opt, FALSE ),
#endif /* WIN32 */
      DWC_CONF_TASK( "Scanning", &opt->scan,(dwc_section_reader_t)read_scan_opt_agent, free_scan_opt, FALSE ),
      DWC_CONF_TASK( "Logging", &opt->log,(dwc_section_reader_t)read_log_opt_agent, free_log_opt, FALSE ),
#if defined(DW_SAMBA)        
      DWC_CONF_TASK( "Actions", &opt->action,(dwc_section_reader_t)read_action_opt_agent, free_action_opt, FALSE ),
#else /* not SAMBA */
        DWC_CONF_TASK( "Actions", &opt->postscan.actions, read_action_opt, free_action_opt, FALSE ),
        DWC_CONF_TASK( "VirusNotifications", &opt->postscan.virus_notify, read_notify_opt, free_notify_opt, FALSE ),
        DWC_CONF_TASK( "SkipNotifications", &opt->postscan.skip_notify, read_notify_opt, free_notify_opt, FALSE ),
        DWC_CONF_TASK( "MailbombNotifications", &opt->postscan.archive_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "ArchiveRestrictionNotifications", &opt->postscan.archive_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "ErrorNotifications", &opt->postscan.error_notify, read_notify_opt, free_notify_opt, FALSE ),
        DWC_CONF_TASK( "LicenseLimitNotifications", &opt->postscan.license_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "MalwareNotifications", &opt->postscan.malware_notify, read_notify_opt, free_notify_opt, TRUE ),
#if !defined(DW_MIO)
        DWC_CONF_TASK( "CuredNotifications", &opt->postscan.cured_notify, read_notify_opt, free_notify_opt, TRUE ),
#endif /* not MIO */        
#if defined(__UNIX_DW)
        DWC_CONF_TASK( "RuleFilterNotifications", &opt->postscan.rule_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "Agent", &opt->agent, read_agent_opt, free_agent_opt, TRUE ),
#endif /* UNIX */
        DWC_CONF_TASK( "Mailer", &opt->submit, read_submit_opt, free_submit_opt, FALSE ),
#if defined(DW_SENDMAIL)
        DWC_CONF_TASK( "NotificationOptions", &opt->postscan, read_notopt_opt, free_notopt_opt, FALSE ),
#endif /* SENDMAIL */
#endif /* SAMBA */        
        DWC_CONF_ENDTASK };        
  
#if !defined(DW_SAMBA)
    /* most verbose mode for load settings */    
    have_mailbomb_section = FALSE;
    have_archive_section = FALSE;
    have_rule_section = FALSE;
    have_license_section = FALSE;
    have_malware_section = FALSE;
#if !defined(DW_MIO)    
    have_curednotify_section = FALSE;
#endif /* DW_MIO */
    outputLib( "console", DW_LL_INFO, 0, 0, PROG_NAME );
        
#endif /* not SAMBA */    
    if (_argc == 1)
      {
	if (strlen(*_argv) > 0)
	  {
	    agent_address = (char *) malloc (strlen(*_argv));
	    strcpy(agent_address,*_argv);
	  }
      }
    else
      {
	printLib(DW_LL_ERROR,"(load settings) cannot parse address %s", *_argv);
	return FALSE;
      }
 /* try search defaults */

#if !defined(DW_SAMBA) 
#if defined(__UNIX_DW)
#if !defined(DW_SENDMAIL) 
    if( test_mode )
    {
        if( !dw_set_user( user ) )
            return FALSE;
    }
#endif /* SENDMAIL */
    if( !test_mode )
    {
        outputLib( NULL, DW_LL_ALERT, LOG_MAIL, LOG_INFO, PROG_NAME );
    }
#endif /* UNIX */
#if defined(__WIN32_DW)
    outputLib( "console", DW_LL_ERROR, 0, 0, PROG_NAME );
#endif /* WIN32 */
#if defined(DW_SENDMAIL) || defined(DW_CGP) || defined(DW_COURIER) 
    printLib( DW_LL_ALERT, "conf: configuration will be loaded from %s", agent_address );
#else /* not SENDMAIL and not CGP and not COURIER */
    printLib( DW_LL_INFO, "conf: configuration will be loaded from %s", agent_address );
#endif /* not SENDMAIL and not CGP and not COURIER */
#else /* SAMBA */  
    outputLib( NULL, DW_LL_ALERT, LOG_DAEMON, LOG_INFO, "drweb_samba" ); // initialized in drweb_samba.c
#endif /* SAMBA */

    memset( opt, 0, sizeof( *opt ) );     
    retcode = read_conf_agent( agent_address, conf );
    DWC_Free( agent_address );

    if( retcode < 0 )
    {
        printLib( DW_LL_ERROR, "conf: configuration loading has been failed" );
        return FALSE;
    }

#if defined(__UNIX_DW)
    opt->scan.use_tcp_nodelay = opt->comm.use_tcp_nodelay;
#endif /* UNIX */
#if !defined(DW_SAMBA) 
#if !defined(__WIN32_DW)
    if( !have_rule_section )
    {
#if !defined(DW_MIO)
        opt->postscan.rule_notify.to_sender = FALSE;
        opt->postscan.rule_notify.to_rcpts = FALSE;
        opt->postscan.rule_notify.to_admin = FALSE;
        opt->postscan.rule_notify.sender_template = NULL;
        opt->postscan.rule_notify.rcpts_template = NULL;
        opt->postscan.rule_notify.admin_template = NULL;
#else /* MIO */
        opt->postscan.rule_notify.notify_template = NULL;
#endif /* not MIO */
    }
#if !defined(DW_MIO)
    if( !have_curednotify_section )
    {
        opt->postscan.cured_notify.to_sender = FALSE;
        opt->postscan.cured_notify.to_rcpts = FALSE;
        opt->postscan.cured_notify.to_admin = FALSE;
        opt->postscan.cured_notify.sender_template = NULL;
        opt->postscan.cured_notify.rcpts_template = NULL;
        opt->postscan.cured_notify.admin_template = NULL;
    }
#endif /* not MIO */
    if( !have_license_section )
    {
#if !defined(DW_MIO)
        opt->postscan.license_notify.to_sender = FALSE;
        opt->postscan.license_notify.to_rcpts = FALSE;
        opt->postscan.license_notify.to_admin = FALSE;
        opt->postscan.license_notify.sender_template = NULL;
        opt->postscan.license_notify.rcpts_template = NULL;
        opt->postscan.license_notify.admin_template = NULL;
#else /* MIO */
        opt->postscan.license_notify.notify_template = NULL;
#endif /* not MIO */
    }
    if( !have_malware_section )
    {
#if !defined(DW_MIO)
        opt->postscan.malware_notify.to_sender = FALSE;
        opt->postscan.malware_notify.to_rcpts = FALSE;
        opt->postscan.malware_notify.to_admin = FALSE;
        opt->postscan.malware_notify.sender_template = NULL;
        opt->postscan.malware_notify.rcpts_template = NULL;
        opt->postscan.malware_notify.admin_template = NULL;
#else /* MIO */
        opt->postscan.malware_notify.notify_template = NULL;
#endif /* not MIO */
    }
    if( !have_agent_section )
    {
        opt->agent.addr = NULL;
    }
    if( !have_mailbomb_section && !have_archive_section )
    {
        printLib( DW_LL_ERROR, "conf: [ArchiveRestrictionNotifications] section missed, init configuration failed" );
        return FALSE;
    }
#endif /* not WIN32 */
    if( !test_mode )
    {               
#if defined(__UNIX_DW)
        outputLib( NULL, opt->log.level, opt->log.sl_facility, opt->log.sl_priority, PROG_NAME );
#if defined(DW_PIPE)    
        if( 0 == msg_size )
        {
            printLib( DW_LL_DEBUG, "drweb_pipe: -s option has not been specified" );
        }
        else if( ULONG_MAX == msg_size )
        {
            printLib( DW_LL_ALERT, "drweb_pipe: invalid message size %s has been passed, ignore them", ptrc );
        }
        else if( opt->scan.ram_spool )
        {
        
            if( msg_size < opt->scan.ram_threshold )
            {
                DWC_Free( opt->scan.spool.tf_path );
                opt->scan.spool.tf_path = DWC_Strdup(opt->scan.ram_spool);
                if( !opt->scan.spool.tf_path )
                {
                    printLib( DW_LL_ERROR, "drweb-pipe: no memory for spool changing" );
                    return FALSE;
                }
                printLib( DW_LL_VERBOSE, "drweb_pipe: RamSpool(%s) would been used for this message", opt->scan.spool.tf_path );            
            }
            else
            {
                printLib( DW_LL_DEBUG, "drweb_pipe: Spool(%s) would been used for this message", opt->scan.spool.tf_path );
            }
        }
        else
        {
            printLib( DW_LL_ALERT, "drweb_pipe: you specify -s option but RamSpool was not specified - use Spool(%s)", opt->scan.spool.tf_path );
        }
#endif /* PIPE */                
#endif /* UNIX */
#if defined(__WIN32_DW)
        /* logfile name has been set in winlib_init */
        outputLib( NULL, opt->log.level, 0, 0, PROG_NAME );
        if( !dw_winlib_init(opt) )
        {
            printLib( DW_LL_ERROR, "drweb-cgp: cannot init DrWeb Antivirus Engine." );
            dw_winlib_done();
            return FALSE;
        }
#endif /* WIN32 */
        dw_show_actions( &opt->postscan.actions );
    }
    else
    {
#if defined(DW_SENDMAIL)
        if( !dw_set_user( user ) )
        {
            exit( EX_SOFTWARE );
        }
#endif /* SENDMAIL */
        dw_show_actions( &opt->postscan.actions );
        retcode = dw_check_settings( opt, FALSE );
        free_conf( conf );
        exit( retcode ? 0 : EX_CONFIG );
    }
#if !defined(DW_MIO)
    print_user_list( opt->scan.users, opt->log.level );
    print_maddr_list( opt->postscan.actions.non_notified_addresses, opt->log.level );
    print_virus_list( opt->postscan.actions.non_notified_viruses, opt->log.level );
#endif /* MIO */
#else /* SAMBA */
    outputLib( NULL, opt->log.level, opt->log.sl_facility, opt->log.sl_priority, "drweb_samba" );
    dw_show_actions( &opt->action );
#endif /* not SAMBA */    
    return TRUE;
}
#endif /* DW_SAMBA */
dwc_bool_t dw_load_settings ( int argc, char *argv[], dw_filter_settings_t *opt )
{
#if defined(DW_PIPE)
    char            *ptrc = NULL;
    unsigned long    msg_size = 0;
#endif /* PIPE */
#if !defined(DW_SAMBA)
    size_t           clen;
    int              i;
    dwc_string_t     user = NULL;
    dwc_bool_t       test_mode = FALSE;
#endif /* not SAMBA */    
    int              retcode;    
    dwc_path_t       conf_filename = NULL;
    dwc_conf_task_t  conf[] = {
#if defined(__UNIX_DW)
        DWC_CONF_TASK( "DaemonCommunication", &opt->comm, read_comm_opt, free_comm_opt, FALSE ),
#endif /* UNIX */
#if defined(__WIN32_DW)
        DWC_CONF_TASK( "Engine", &opt->engine, read_engine_opt, free_engine_opt, FALSE ),
#endif /* WIN32 */
        DWC_CONF_TASK( "Scanning", &opt->scan, read_scan_opt, free_scan_opt, FALSE ),
        DWC_CONF_TASK( "Logging", &opt->log, read_log_opt, free_log_opt, FALSE ),
#if defined(DW_SAMBA)        
        DWC_CONF_TASK( "Actions", &opt->action, read_action_opt, free_action_opt, FALSE ),
#else /* not SAMBA */
        DWC_CONF_TASK( "Actions", &opt->postscan.actions, read_action_opt, free_action_opt, FALSE ),
        DWC_CONF_TASK( "VirusNotifications", &opt->postscan.virus_notify, read_notify_opt, free_notify_opt, FALSE ),
        DWC_CONF_TASK( "SkipNotifications", &opt->postscan.skip_notify, read_notify_opt, free_notify_opt, FALSE ),
        DWC_CONF_TASK( "MailbombNotifications", &opt->postscan.archive_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "ArchiveRestrictionNotifications", &opt->postscan.archive_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "ErrorNotifications", &opt->postscan.error_notify, read_notify_opt, free_notify_opt, FALSE ),
        DWC_CONF_TASK( "LicenseLimitNotifications", &opt->postscan.license_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "MalwareNotifications", &opt->postscan.malware_notify, read_notify_opt, free_notify_opt, TRUE ),
#if !defined(DW_MIO)
        DWC_CONF_TASK( "CuredNotifications", &opt->postscan.cured_notify, read_notify_opt, free_notify_opt, TRUE ),
#endif /* not MIO */        
#if defined(__UNIX_DW)
        DWC_CONF_TASK( "RuleFilterNotifications", &opt->postscan.rule_notify, read_notify_opt, free_notify_opt, TRUE ),
        DWC_CONF_TASK( "Agent", &opt->agent, read_agent_opt, free_agent_opt, TRUE ),
#endif /* UNIX */
        DWC_CONF_TASK( "Mailer", &opt->submit, read_submit_opt, free_submit_opt, FALSE ),
#if defined(DW_SENDMAIL)
        DWC_CONF_TASK( "NotificationOptions", &opt->postscan, read_notopt_opt, free_notopt_opt, FALSE ),
#endif /* SENDMAIL */
#endif /* SAMBA */        
        DWC_CONF_ENDTASK };        
    
#if !defined(DW_SAMBA)
    /* most verbose mode for load settings */    
    have_mailbomb_section = FALSE;
    have_archive_section = FALSE;
    have_rule_section = FALSE;
    have_license_section = FALSE;
    have_malware_section = FALSE;
#if !defined(DW_MIO)    
    have_curednotify_section = FALSE;
#endif /* DW_MIO */
    outputLib( "console", DW_LL_INFO, 0, 0, PROG_NAME );
    if( argc > 1 )
    {
        for( i = 1; i < argc; i++ )
        {
            if( (strncmp( argv[i], HELP_PARAM_1, strlen(HELP_PARAM_1) ) == 0)
                ||
                (strncmp( argv[i], HELP_PARAM_2, strlen(HELP_PARAM_2) ) == 0)
                ||
                (strncmp( argv[i], HELP_PARAM_3, strlen(HELP_PARAM_3) ) == 0) )
            {
                dw_show_usage( argv[0] );
                /* never returns */
            }
            if( strncmp( argv[i], VER_PARAM, strlen(VER_PARAM) ) == 0 )
            {
                dw_show_version( argv[0] );
                /* never returns */
            }
            clen = strlen( CONF_PARAM );
            if( strncmp( argv[i], CONF_PARAM, clen ) == 0 )
            {
                GET_STR_FROM_PARAM( conf_filename, CONF_PARAM"<filename>" );                
                continue;
            }
            clen = strlen( DEBUG_PARAM );
            if( strncmp( argv[i], DEBUG_PARAM, clen ) == 0 )
            {
                outputLib( "console", DW_LL_DEBUG, 0, 0, PROG_NAME );
                continue;
            }
#if !defined(__WIN32_DW)
            clen = strlen( CHECK_PARAM );
            if( strncmp( argv[i], CHECK_PARAM, clen ) == 0 )
            {
                test_mode = TRUE;
                continue;
            }
            clen = strlen( USER_PARAM );
            if( strncmp( argv[i], USER_PARAM, clen ) == 0 )
            {
                GET_STR_FROM_PARAM( user, USER_PARAM"<username>" );                
                continue;
            }
#endif /* not WIN32 */
#if defined(DW_PIPE)
            if( strncmp( argv[i], "-s", 2 ) == 0 )
            {
                if( strlen( argv[i] ) > 2 )
                {
                    ptrc = argv[i];
                    ptrc += 2;
                }
                else
                {
                    ++i;
                    ptrc = argv[i];
                }
                msg_size = strtoul( ptrc, NULL, 10 );
                continue;
            }    
            if( strncmp( argv[i], "-f", 2 ) == 0 )
            {
                /* check default paths */
                break;
            }
#endif /* PIPE */
            printLib( DW_LL_ERROR, "conf: unknown option %s", argv[i] );
            return FALSE;
        }
    }    
#endif /* not SAMBA */    
    /* try search defaults */
    if( !conf_filename )
    {
#if defined(__UNIX_DW)
        conf_filename = DWC_Strdup( FHS_SPEC_CONFNAME );
        if( conf_filename )
        {
            if( 0 == access_file( conf_filename, R_OK ) )
            {
                goto load_conf;
            }
            printLib( DW_LL_VERBOSE, "conf: configuration file %s is not accessable - %s", conf_filename, stdlib_error(errno) );
        }
        else
        {
            printLib( DW_LL_DEBUG, "conf: name of configuration file was not defined" );
        }
        DWC_Free( conf_filename );
        conf_filename = DWC_Strdup( OS_SPEC_CONFNAME );

        if (argc == 1)
        {
            if (argv && strlen(*argv) > 0)
            {
                DWC_Free( conf_filename );
                conf_filename = DWC_Strdup(*argv);
            }
        }

        printLib( DW_LL_ERROR, "conf: filename '%s'", conf_filename);

#endif /* UNIX */
#if defined(__WIN32_DW) && defined(DW_CGP)
        conf_filename = _tgetcwd( NULL, MAX_PATH + 1 );
        if( !conf_filename )
        {
            printLib( DW_LL_VERBOSE, "conf: get current directory failed - %s", stdlib_error(errno) );
            return FALSE;
        }
        _tcsncat( conf_filename, _T("\\"), MAX_PATH );
        _tcsncat( conf_filename, _T(CONF_FNAME), MAX_PATH );
        conf_filename[MAX_PATH] = _T(NULLCHAR); // paranoya is a life
#endif /* WIN32 and CGP */
        if( conf_filename )
        {
            if( 0 == access_file( conf_filename, R_OK ) )
            {
                goto load_conf;
            }
            printLib( DW_LL_VERBOSE, "conf: configuration file %s is not accessable - %s", conf_filename, stdlib_error(errno) );
        }
        else
        {
            printLib( DW_LL_DEBUG, "conf: name of configuration file was not defined" );
        }

        DWC_Free( conf_filename );
#if !defined(DW_SAMBA)        
        printf( "%s: configuration file not found\nTry run with %s for more information.\n", argv[0], HELP_PARAM_3 );
#else /* SAMBA */        
        printLib( DW_LL_ERROR, "conf: a configuration file was not found" );
#endif        
        return FALSE;
    }
 load_conf:
#if !defined(DW_SAMBA) 
#if defined(__UNIX_DW)
#if !defined(DW_SENDMAIL) 
    if( test_mode )
    {
        if( !dw_set_user( user ) )
            return FALSE;
    }
#endif /* SENDMAIL */
    if( !test_mode )
    {
        outputLib( NULL, DW_LL_ALERT, LOG_MAIL, LOG_INFO, PROG_NAME );
    }
#endif /* UNIX */
#if defined(__WIN32_DW)
    outputLib( "console", DW_LL_ERROR, 0, 0, PROG_NAME );
#endif /* WIN32 */
#if defined(DW_SENDMAIL) || defined(DW_CGP) || defined(DW_COURIER) 
    printLib( DW_LL_ALERT, "conf: configuration will be loaded from %s", conf_filename );
#else /* not SENDMAIL and not CGP and not COURIER */
    printLib( DW_LL_INFO, "conf: configuration will be loaded from %s", conf_filename );
#endif /* not SENDMAIL and not CGP and not COURIER */
#else /* SAMBA */  
    outputLib( NULL, DW_LL_ALERT, LOG_DAEMON, LOG_INFO, "drweb_samba" );
#endif /* SAMBA */
    memset( opt, 0, sizeof( *opt ) );    
    retcode = read_conf( conf_filename, conf );
    DWC_Free( conf_filename );
    if( retcode < 0 )
    {
        printLib( DW_LL_ERROR, "conf: configuration loading has been failed" );
        return FALSE;
    }
#if defined(__UNIX_DW)
    opt->scan.use_tcp_nodelay = opt->comm.use_tcp_nodelay;
#endif /* UNIX */
#if !defined(DW_SAMBA) 
#if !defined(__WIN32_DW)
    if( !have_rule_section )
    {
#if !defined(DW_MIO)
        opt->postscan.rule_notify.to_sender = FALSE;
        opt->postscan.rule_notify.to_rcpts = FALSE;
        opt->postscan.rule_notify.to_admin = FALSE;
        opt->postscan.rule_notify.sender_template = NULL;
        opt->postscan.rule_notify.rcpts_template = NULL;
        opt->postscan.rule_notify.admin_template = NULL;
#else /* MIO */
        opt->postscan.rule_notify.notify_template = NULL;
#endif /* not MIO */
    }
#if !defined(DW_MIO)
    if( !have_curednotify_section )
    {
        opt->postscan.cured_notify.to_sender = FALSE;
        opt->postscan.cured_notify.to_rcpts = FALSE;
        opt->postscan.cured_notify.to_admin = FALSE;
        opt->postscan.cured_notify.sender_template = NULL;
        opt->postscan.cured_notify.rcpts_template = NULL;
        opt->postscan.cured_notify.admin_template = NULL;
    }
#endif /* not MIO */
    if( !have_license_section )
    {
#if !defined(DW_MIO)
        opt->postscan.license_notify.to_sender = FALSE;
        opt->postscan.license_notify.to_rcpts = FALSE;
        opt->postscan.license_notify.to_admin = FALSE;
        opt->postscan.license_notify.sender_template = NULL;
        opt->postscan.license_notify.rcpts_template = NULL;
        opt->postscan.license_notify.admin_template = NULL;
#else /* MIO */
        opt->postscan.license_notify.notify_template = NULL;
#endif /* not MIO */
    }
    if( !have_malware_section )
    {
#if !defined(DW_MIO)
        opt->postscan.malware_notify.to_sender = FALSE;
        opt->postscan.malware_notify.to_rcpts = FALSE;
        opt->postscan.malware_notify.to_admin = FALSE;
        opt->postscan.malware_notify.sender_template = NULL;
        opt->postscan.malware_notify.rcpts_template = NULL;
        opt->postscan.malware_notify.admin_template = NULL;
#else /* MIO */
        opt->postscan.malware_notify.notify_template = NULL;
#endif /* not MIO */
    }
    if( !have_agent_section )
    {
        opt->agent.addr = NULL;
    }
    if( !have_mailbomb_section && !have_archive_section )
    {
        printLib( DW_LL_ERROR, "conf: [ArchiveRestrictionNotifications] section missed, init configuration failed" );
        return FALSE;
    }
#endif /* not WIN32 */
    if( !test_mode )
    {               
#if defined(__UNIX_DW)
        outputLib( NULL, opt->log.level, opt->log.sl_facility, opt->log.sl_priority, PROG_NAME );
#if defined(DW_PIPE)    
        if( 0 == msg_size )
        {
            printLib( DW_LL_DEBUG, "drweb_pipe: -s option has not been specified" );
        }
        else if( ULONG_MAX == msg_size )
        {
            printLib( DW_LL_ALERT, "drweb_pipe: invalid message size %s has been passed, ignore them", ptrc );
        }
        else if( opt->scan.ram_spool )
        {
        
            if( msg_size < opt->scan.ram_threshold )
            {
                DWC_Free( opt->scan.spool.tf_path );
                opt->scan.spool.tf_path = DWC_Strdup(opt->scan.ram_spool);
                if( !opt->scan.spool.tf_path )
                {
                    printLib( DW_LL_ERROR, "drweb-pipe: no memory for spool changing" );
                    return FALSE;
                }
                printLib( DW_LL_VERBOSE, "drweb_pipe: RamSpool(%s) would been used for this message", opt->scan.spool.tf_path );            
            }
            else
            {
                printLib( DW_LL_DEBUG, "drweb_pipe: Spool(%s) would been used for this message", opt->scan.spool.tf_path );
            }
        }
        else
        {
            printLib( DW_LL_ALERT, "drweb_pipe: you specify -s option but RamSpool was not specified - use Spool(%s)", opt->scan.spool.tf_path );
        }
#endif /* PIPE */                
#endif /* UNIX */
#if defined(__WIN32_DW)
        /* logfile name has been set in winlib_init */
        outputLib( NULL, opt->log.level, 0, 0, PROG_NAME );
        if( !dw_winlib_init(opt) )
        {
            printLib( DW_LL_ERROR, "drweb-cgp: cannot init DrWeb Antivirus Engine." );
            dw_winlib_done();
            return FALSE;
        }
#endif /* WIN32 */
        dw_show_actions( &opt->postscan.actions );
    }
    else
    {
#if defined(DW_SENDMAIL)
        if( !dw_set_user( user ) )
        {
            exit( EX_SOFTWARE );
        }
#endif /* SENDMAIL */
        dw_show_actions( &opt->postscan.actions );
        retcode = dw_check_settings( opt, FALSE );
        free_conf( conf );
        exit( retcode ? 0 : EX_CONFIG );
    }
#if !defined(DW_MIO)
    print_user_list( opt->scan.users, opt->log.level );
    print_maddr_list( opt->postscan.actions.non_notified_addresses, opt->log.level );
    print_virus_list( opt->postscan.actions.non_notified_viruses, opt->log.level );
#endif /* MIO */
#else /* SAMBA */
    outputLib( NULL, opt->log.level, opt->log.sl_facility, opt->log.sl_priority, "drweb_samba" );
    dw_show_actions( &opt->action );
#endif /* not SAMBA */    
    return TRUE;
}

#if !defined(DW_SAMBA)
/* ---------------------------------------------------------------------- */
#if !defined(DW_MIO)
#define TEST_NOTIFY_FILES( not, case )\
BEGIN_MACRO\
    if( (not).to_sender && (dw_check_read((not).sender_template) == -1) )\
    {\
        printLib( DW_LL_ERROR, "check_conf: test for sender template in "case" case - failed" );\
        return FALSE;\
    }\
    if( (not).to_admin && (dw_check_read((not).admin_template) == -1) )\
    {\
        printLib( DW_LL_ERROR, "check_conf: test for administrator template in "case" case - failed" );\
        return FALSE;\
    }\
    if( (not).to_rcpts && (dw_check_read((not).rcpts_template) == -1) )\
    {\
        printLib( DW_LL_ERROR, "check_conf: test for recipients template in "case" case - failed" );\
        return FALSE;\
    }\
END_MACRO    
#else /* MIO */
#define TEST_NOTIFY_FILES( not, case )\
BEGIN_MACRO\
    if( dw_check_read((not).notify_template) == -1 )\
    {\
        printLib( DW_LL_ERROR, "check_conf: test for notify template in "case" case - failed" );\
        return FALSE;\
    }\
END_MACRO    
#endif /* not MIO */

#if !defined(DW_MIO)        
/* ---------------------------------------------------------------------- */
#define TEST_APPEND_STRING( bp, sl )\
BEGIN_MACRO\
    if( strlen((bp)) > 0 )\
    {\
        if( !dw_multistring_add( (sl), (bp) ) )\
        {\
            dw_e_delete( e );\
            dw_multistring_delete( re );\
            printLib( DW_LL_ERROR, "check_conf: cannot add string <%s> to test report", bp );\
            printLib( DW_LL_ERROR, "check_conf: mail submit test - failed" );\
            return FALSE;\
        }\
    }\
END_MACRO    
#endif /* not MIO */

/* ---------------------------------------------------------------------- */
dwc_bool_t dw_check_settings ( dw_filter_settings_t *opt, dwc_bool_t lib_inited )
{
#if !defined(DW_MIO)
    dwc_string_t        tmp = NULL;
    dwc_envelope_t      e = NULL;
    dwc_multistring_t   re = NULL;
    dwc_string_t        report = NULL;
#endif /* not MIO */
#if !defined(DW_HAVE_SPOOL) && defined(__UNIX_DW)
    int                 libcode;
    int                 totals = 0;
    char*               bases = NULL;
#endif /* not HAVE_SPOOL and UNIX */

#if defined(__UNIX_DW)    
    if( !lib_inited
        &&
        !dw_init_lib( &opt->comm ) )
        return FALSE;
    
    if( !dw_check_version() )
        return FALSE;
#endif /* UNIX */
    if( ( (opt->postscan.actions.on_infected == DW_ACT_QUARANTINE)
          ||
#if defined(DW_HAVE_SPOOL)          
          (opt->postscan.actions.on_incurable == DW_ACT_QUARANTINE)
          ||
#endif /* HAVE_SPOOL */          
          (opt->postscan.actions.on_suspicious == DW_ACT_QUARANTINE)
          ||
#if defined(__UNIX_DW)
          (opt->postscan.actions.on_hre_filter_reject == DW_ACT_QUARANTINE)
          ||
#endif /* UNIX */
          (opt->postscan.actions.on_archive_restriction == DW_ACT_QUARANTINE)
          ||
          (opt->postscan.actions.on_proc_error == DW_ACT_QUARANTINE)
          ||
          (opt->postscan.actions.on_scan_error == DW_ACT_QUARANTINE)
          ||
          (opt->postscan.actions.on_skip == DW_ACT_QUARANTINE) )
        &&
        !opt->postscan.actions.quarantine.tf_path )
    {
        printLib( DW_LL_ERROR, "check_conf: you want to use 'quarantine', but not specify quarantine directory" );
        return FALSE;
    }
#if defined(DW_HAVE_SPOOL)
    else if( (opt->postscan.actions.on_infected == DW_ACT_CURE)
             &&
             !opt->scan.local )
    {
        printLib( DW_LL_ERROR, "check_conf: you cannot use 'cure' in non-local mode" );
        return FALSE;
    }
    if( opt->postscan.actions.quarantine.tf_path )
    {
        printLib( DW_LL_INFO, "check_conf: quarantine test - started" );
        if( dw_check_quarantine( &opt->scan.spool, &opt->postscan.actions.quarantine, opt->scan.local, opt->scan.prefix_path, opt->scan.strip_path ) < 0 )
        {
            printLib( DW_LL_ERROR, "check_conf: quarantine test - failed" );
            return FALSE;
        }
        printLib( DW_LL_INFO, "check_conf: quarantine test - passed" );
    }
    else
    {
        printLib( DW_LL_INFO, "check_conf: spool test - started" );
        if( dw_check_spool( &opt->scan.spool, opt->scan.local, opt->scan.prefix_path, opt->scan.strip_path ) < 0 )
        {
            printLib( DW_LL_ERROR, "check_conf: spool test - failed" );
            return FALSE;
        }
        printLib( DW_LL_INFO, "check_conf: spool test - passed" );
    }
#else /* not HAVE_SPOOL */
#if defined(__UNIX_DW)
    /*
     * Just try connect to daemon to get virus bases,
     * if we cannot check test file (filter has not the spool) 
     */    
    libcode = getBases( &bases, &totals );
    DWC_Free( bases );
    if( libcode != DWL_NOERROR )
    {
        printLib( DW_LL_ERROR, "check_conf: cannot retrieve virusdefinition bases from daemon (error: %d)", libcode );
        return FALSE;
    }    
    if( totals == 0 )
    {
        printLib( DW_LL_ALERT, "check_conf: WARNING: daemon reports that 0 virus definition bases has been loaded" );
    }
#endif /* UNIX */
#endif /* HAVE_SPOOL */    
    TEST_NOTIFY_FILES( opt->postscan.virus_notify, "virus" );
    TEST_NOTIFY_FILES( opt->postscan.error_notify, "error" );
    TEST_NOTIFY_FILES( opt->postscan.skip_notify, "skip object" );
    TEST_NOTIFY_FILES( opt->postscan.archive_notify, "archive restriction" );
#if !defined(DW_MIO)
#if !defined(DW_POSTFIX) && !defined(DW_EXIM) && !defined(DW_QMAIL)
    if( opt->postscan.virus_notify.to_admin
        ||
        opt->postscan.skip_notify.to_admin
        ||
        opt->postscan.error_notify.to_admin
        ||
        opt->postscan.archive_notify.to_admin )
#endif /* not POSTFIX and not EXIM and not QMAIL */        
    {
        printLib( DW_LL_INFO, "check_conf: mail submit test - started" );
        e = dw_e_create( opt->postscan.actions.filter_mail );
        if( !e )
        {
            printLib( DW_LL_ERROR, "check_conf: mail submit test - failed (no memory)" );
            return FALSE;
        }
        if( !dw_e_add_rcpt( e, opt->postscan.actions.admin_mail ) )
        {
            dw_e_delete( e );
            printLib( DW_LL_ERROR, "check_conf: mail submit test - failed" );
            return FALSE;
        }
        re = dw_multistring_create( opt->scan.report_size );
        if( !re )
        {
            dw_e_delete( e );
            printLib( DW_LL_ERROR, "check_conf: mail submit test - failed (no memory)" );
            return FALSE;
        }
        TEST_APPEND_STRING( "From: \"DrWeb-DAEMON\" <", re );
        TEST_APPEND_STRING( dw_e_get_from(e), re );
        TEST_APPEND_STRING( ">\r\nTo: \"Administrator\" <", re );        
        dw_multistring_rewind(dw_e_get_rcpts(e), DW_SD_FORWARD);
        tmp = dw_multistring_getnext(dw_e_get_rcpts(e));
        TEST_APPEND_STRING( tmp, re );
        TEST_APPEND_STRING( ">\r\nSubject: Test DrWeb Mail Filter\r\n", re );
#if defined(DW_SENDMAIL)
        if( opt->postscan.fast_notify )
        {
            TEST_APPEND_STRING( DRWEB_HASH_FULLHEADER, re );
            TEST_APPEND_STRING( opt->postscan.secure_hash, re );
            TEST_APPEND_STRING( "\r\n", re );
        }
#endif /* SENDMAIL */        
        TEST_APPEND_STRING( "\r\nDear Administrator,\r\n\r\nThis is a test message was created by Dr.WEB mail filter.\r\n\r\nhttp://www.drweb.com\r\n", re );
        report = dw_multistring_concat( re, DW_SD_FORWARD );
        dw_multistring_delete( re );
        if( !report )
        {
            dw_e_delete( e );
            printLib( DW_LL_ERROR, "check_conf: mail submit test - failed (no memory)" );
            return FALSE;
        }
        if( !dw_send_mail( e, NULL, 0, report, strlen(report), &opt->submit ) )
        {
            dw_e_delete( e );
            DWC_Free( report );
            printLib( DW_LL_ERROR, "check_conf: mail submit test - failed" );
            return FALSE;
        }        
        dw_e_delete( e );
        DWC_Free( report );
#if defined(DW_SENDMAIL) && !defined(EMX_DW)
        printLib( DW_LL_INFO, "check_conf: mail submit test - possible passed" );
#else /* not SENDMAIL or EMX */
        printLib( DW_LL_INFO, "check_conf: mail submit test - passed" );
#endif /* SENDMAIL and not EMX */        
    }
#endif /* MIO */
#if defined(__UNIX_DW)
    if( !lib_inited )
    {
        cleanupLib();
    }
#endif /* UNIX */
#if defined(__WIN32_DW)
    dw_winlib_done();
#endif /* WIN32 */
    return TRUE;
}
#endif /* not SAMBA */

#if defined(DW_SAMBA)
/* ---------------------------------------------------------------------- */
dwc_bool_t dw_file_md5( char * filename, unsigned char * hash )
{
    struct MD5Context ctx;
    FILE * fp = NULL;
    const int buffer_size = 1024;
    unsigned char buffer[buffer_size];
    int bytes_read;

    if ((filename == NULL) || (*filename == '\0')) 
	goto md5sum_error;
    
    printLib(DW_LL_DEBUG, "(dw_file_md5) filename = %s", filename);
    fp = fopen(filename,"r");
  
    if (fp == NULL)
    {
	printLib( DW_LL_ERROR, "(dw_file_md5) cannot open file = %s (%s)", filename, strerror(errno));
	goto md5sum_error;
    }

    MD5Init( &ctx );

    /* main circle of reading file */  
    while ( !feof(fp) )
    {
	bytes_read = fread(buffer, sizeof(char), buffer_size, fp);
	if (bytes_read > 0)
	{
	    printLib(DW_LL_DEBUG, "bytes_read = %d", bytes_read);
	    MD5Update( &ctx, buffer, bytes_read );
	}
    }
    
    MD5Final( hash, &ctx );
    printLib(DW_LL_DEBUG, "(dw_file_md5) hash=%s", (char *)hash);

    if (fp) fclose(fp);
    return TRUE;

md5sum_error:
    if (fp) fclose(fp);
    *hash='\0';
    return FALSE;
}
#endif /* DW_SAMBA */

#if defined(DW_SENDMAIL)
/* ---------------------------------------------------------------------- */
static dwc_bool_t dw_generate_hash_string( dwc_string_t salt, dwc_hash_t hstr )
{
    struct MD5Context  ctx;
    struct timeval     tod;
    pid_t              pid;
    unsigned int       tmp, i;
    unsigned char      rhash[16];
    
    EXIT_IF_1PARAM( !salt, "hash:", return FALSE );
    if( gettimeofday( &tod, NULL ) < 0 )
    {
        printLib( DW_LL_ERROR, "hash: cannot get time of day" );
        return FALSE;
    }
    pid = getpid();
    MD5Init( &ctx );
    MD5Update( &ctx, (char*) &tod.tv_sec, sizeof(tod.tv_sec) );
    MD5Update( &ctx, (char*) &tod.tv_usec, sizeof(tod.tv_usec) );
    MD5Update( &ctx, (char*) &pid, sizeof(pid) );
    MD5Update( &ctx, salt, strlen(salt) );
    MD5Final( rhash, &ctx );
    for( i = 0; i < 16; ++i )
    {
        tmp = rhash[i];
        snprintf( &hstr[2*i], 3, "%02x", tmp );
    }
    return TRUE;
}
#endif /* SENDMAIL */

#if !defined(DW_SAMBA)
/*-------------------------------------------------------------------------*/
static dwc_bool_t dw_set_mailaddr( dwc_string_t str, dwc_string_t * maddr )
{    
    dwc_length_t    len;
    
    EXIT_IF_2PARAM( !maddr, !str, "conf:", return FALSE );    
    if( strrchr( str, '>' ) == NULL )
    {
        len = strlen(str) + 3;
        *maddr = DWC_Malloc( dwc_string_t, len ); /* asv : <> + zero */
        if( *maddr )
        {
            snprintf( *maddr, len, "<%s>", str );
            (*maddr)[len-1] = NULLCHAR;
        }
    }
    else
    {   
        *maddr = DWC_Strdup( str );
    }
    if( *maddr )
    {
        return TRUE;
    }
    else
    {
        printLib( DW_LL_ERROR, "conf: no memory for mail address" );
        return FALSE;
    }
}
#endif /* not SAMBA */

/*-------------------------------------------------------------------------*/
dwc_string_t dw_get_action( dwc_action_t action )
{
    switch( action )
    {
        case DW_ACT_PASS: 
            return TAG_PASS;
        case DW_ACT_REJECT: 
            return TAG_REJECT;
        case DW_ACT_QUARANTINE: 
            return TAG_QUARANTINE;
#if !defined(DW_MIO)
#if !defined(__WIN32_DW)
        case DW_ACT_DELETE:         
            return TAG_DELETE;
        case DW_ACT_CURE:         
            return TAG_CURE;
#endif /* WIN32 */
        case DW_ACT_DISCARD: 
            return TAG_DISCARD;
#if !defined(DW_SAMBA)   
        case DW_ACT_REDIRECT: 
            return TAG_REDIRECT;
        case DW_ACT_CONTINUE: 
            return TAG_CONTINUE;
        case DW_ACT_TEMPFAIL: 
            return TAG_TEMPFAIL;
#else /* SAMBA */            
        case DW_ACT_RENAME: 
            return TAG_RENAME;
#endif /* not SAMBA */            
#else /* MIO */
        case DW_ACT_ERROR:
            return TAG_ERROR;
#endif /* MIO */            
        default: 
            return TAG_UNKNOWN;
    }
}

/*-------------------------------------------------------------------------*/
dwc_bool_t dw_set_action( const char* str, const char* set, dwc_action_t* act )
{
    EXIT_IF_3PARAM( !str, !set, !act, "conf:", return FALSE );
    printLib( DW_LL_DEBUG, "conf: action=%s, set=%s", str, set );
    if( ACT_CMP( str, "pass", TAG_PASS, set ) )
    {
        *act = DW_ACT_PASS;
        return TRUE;
    }
    else if( ACT_CMP( str, "reject", TAG_REJECT, set ) )
    {
        *act = DW_ACT_REJECT;
        return TRUE;
    }
    else if( ACT_CMP( str, "quarantine", TAG_QUARANTINE, set ) )
    {
        *act = DW_ACT_QUARANTINE;
        return TRUE;
    }
#if !defined(DW_MIO)
#if !defined(__WIN32_DW)
    else if( ACT_CMP( str, "cure", TAG_CURE, set ) )
    {
        *act = DW_ACT_CURE;
        return TRUE;
    }
    else if( ACT_CMP( str, "remove", TAG_DELETE, set ) )
    {
        *act = DW_ACT_DELETE;
        return TRUE;
    }
#endif /* WIN32 */
    else if( ACT_CMP( str, "discard", TAG_DISCARD, set ) )
    {
        *act = DW_ACT_DISCARD;
        return TRUE;
    }
#if !defined(DW_SAMBA)    
    else if( ACT_CMP( str, "redirect", TAG_REDIRECT, set ) )
    {
        *act = DW_ACT_REDIRECT;
        return TRUE;
    }
    else if( ACT_CMP( str, "continue", TAG_CONTINUE, set ) )
    {
        *act = DW_ACT_CONTINUE;
        return TRUE;
    }
    else if( ACT_CMP( str, "tempfail", TAG_TEMPFAIL, set ) )
    {
        *act = DW_ACT_TEMPFAIL;
        return TRUE;
    }
#else /* SAMBA */
    else if( ACT_CMP( str, "rename", TAG_RENAME, set ) )
    {
        *act = DW_ACT_RENAME;
        return TRUE;
    }
#endif /* not SAMBA */    
#else /* MIO */
    else if( ACT_CMP( str, "error", TAG_ERROR, set ) )
    {
        *act = DW_ACT_ERROR;
        return TRUE;
    }    
#endif /* MIO */    
    return FALSE;
}

/* /////////////////////////////////////////////////////////////////////// */
/*               PARSERS OF CONFIGURATION FILE SECTIONS                    */
/* /////////////////////////////////////////////////////////////////////// */
#if defined(__UNIX_DW)
/*-------------------------------------------------------------------------*/
#ifdef DW_SAMBA
dwc_bool_t read_comm_opt_agent ( char * _buf_fs, int *pline, const char *sec, void *pdata )
{
    dwcf_comm_opt_t *pcomm = (dwcf_comm_opt_t*) pdata;
    dwc_conf_set_t  comopt[] = {
        DWC_CONF_STRING_LIST( "Address", pcomm->addr ),
        DWC_CONF_BOOL( "Cache", pcomm->cache, FALSE ),
        DWC_CONF_INT( "Timeout", pcomm->timeout, 0 ),
        DWC_CONF_BOOL( "UseTcpNodelay", pcomm->use_tcp_nodelay, FALSE ),
        DWC_CONF_ENDLINE };
        
    if( read_section_agent( _buf_fs, pline, sec, comopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
    if( dw_multistring_count( pcomm->addr ) < 1 )
    {
        printLib( DW_LL_ERROR, "read section %s: no daemon addresses specified", sec );        
        goto error_exit;
    }
#if defined(DW_PIPE) || defined(DW_QMAIL)
        /* asv: cache is useless for postfix, exim and qmail,
           because filter instance will been loaded at each message.
           Hack: for pid: family, see dwc_addrlist.c: dwc_addrlist_add():
                else if( !cache && (ENOENT == errno) ) 
        */
    pcomm->cache = FALSE;
#endif /* PIPE or QMAIL */    
    return TRUE;

  error_exit:
    free_comm_opt( sec, pdata );
    return FALSE;
}
#endif /* DW_SAMBA */
/*-------------------------------------------------------------------------*/
dwc_bool_t read_comm_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_comm_opt_t *pcomm = (dwcf_comm_opt_t*) pdata;
    dwc_conf_set_t  comopt[] = {
        DWC_CONF_STRING_LIST( "Address", pcomm->addr ),
        DWC_CONF_BOOL( "Cache", pcomm->cache, FALSE ),
        DWC_CONF_INT( "Timeout", pcomm->timeout, 0 ),
        DWC_CONF_BOOL( "UseTcpNodelay", pcomm->use_tcp_nodelay, FALSE ),
        DWC_CONF_ENDLINE };
        
    if( read_section( fs, pline, sec, comopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
    if( dw_multistring_count( pcomm->addr ) < 1 )
    {
        printLib( DW_LL_ERROR, "read section %s: no daemon addresses specified", sec );        
        goto error_exit;
    }
#if defined(DW_PIPE) || defined(DW_QMAIL)
        /* asv: cache is useless for postfix, exim and qmail,
           because filter instance will been loaded at each message.
           Hack: for pid: family, see dwc_addrlist.c: dwc_addrlist_add():
                else if( !cache && (ENOENT == errno) ) 
        */
    pcomm->cache = FALSE;
#endif /* PIPE or QMAIL */    
    return TRUE;

  error_exit:
    free_comm_opt( sec, pdata );
    return FALSE;
}

/*-------------------------------------------------------------------------*/
void free_comm_opt ( const char *sec, void *pdata )
{
    dwcf_comm_opt_t *pcomm = (dwcf_comm_opt_t*) pdata;

    dw_multistring_delete( pcomm->addr );
}
#endif /* UNIX */

#if defined(__WIN32_DW)
/*-------------------------------------------------------------------------*/
dwc_bool_t read_engine_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_engine_opt_t *peng = (dwcf_engine_opt_t*) pdata;
    dwc_conf_set_t  comopt[] = {
        DWC_CONF_STRING( "EnginePath", peng->engine_dir, NULL ),
        DWC_CONF_STRING( "VirusBases", peng->bases_dir, NULL ),
        DWC_CONF_STRING( "TempDir", peng->tmp_dir, NULL ),
        DWC_CONF_STRING( "MailAddressesList", peng->email_file, NULL ),
        DWC_CONF_STRING_LIST( "Key", peng->keyfiles ),
        DWC_CONF_INT( "UpdateTimeout", peng->update_timeout, 300 ),
        DWC_CONF_COUNT( "MaxLoadEngines", peng->maxload_engines, 10 ),
        DWC_CONF_COUNT( "PreLoadEngines", peng->preload_engines, 1 ),
        DWC_CONF_INT( "FreeEngineTimeout", peng->unload_timeout, 120 ),
        DWC_CONF_ENDLINE };
        
    if( read_section( fs, pline, sec, comopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
    if( !DW_HAVE_A_PATH(peng->engine_dir) )
    {
        DWC_Free(peng->engine_dir);
    }
    if( !DW_HAVE_A_PATH(peng->bases_dir) )
    {
        DWC_Free(peng->bases_dir);
    }
    if( !DW_HAVE_A_PATH(peng->tmp_dir) )
    {
        DWC_Free(peng->tmp_dir);
    }
    if( !DW_HAVE_A_PATH(peng->email_file) )
    {
        DWC_Free(peng->email_file);
    }
    return TRUE;
}

/*-------------------------------------------------------------------------*/
void free_engine_opt ( const char *sec, void *pdata )
{
    dwcf_engine_opt_t *peng = (dwcf_engine_opt_t*) pdata;

    DWC_Free(peng->email_file);
    DWC_Free(peng->engine_dir);
    DWC_Free(peng->bases_dir);
    DWC_Free(peng->tmp_dir);
    dw_multistring_delete(peng->keyfiles);
}
#endif /* WIN32 */
#ifdef DW_SAMBA
dwc_bool_t read_scan_opt_agent ( char * _buf_fs, int *pline, const char *sec, void *pdata )
{
    dwcf_scan_opt_t *pscan = (dwcf_scan_opt_t*) pdata;
#if !defined(DW_SAMBA)
#if !defined(DW_MIO)
    dwc_string_t     str_deny;
#endif /* MIO */    
    dwc_bool_t       need_report, need_stats;
#if defined(__UNIX_DW)
    dwc_bool_t       need_hre;
#endif /* UNIX */
#else /* SAMBA */    
    dwc_string_t     str_mode;
    dwc_count_t      strp_pref;
    dwc_string_t     path_pref;
#endif /* SAMBA */    
#if defined(DW_HAVE_SPOOL)
    dwc_count_t      spool_acc;
    char            *str_snaming;
#endif /* HAVE_SPOOL */    
    dwc_conf_set_t   scanopt[] = {
        DWC_CONF_BOOL( "HeuristicAnalysis", pscan->heuristic, FALSE ),
#if defined(DW_SAMBA)        
        DWC_CONF_COUNT( "StripPrefix", strp_pref, 0 ),
        DWC_CONF_STRING( "PathPrefix", path_pref, NULL ),
#endif /* SAMBA */
#if defined(__UNIX_DW)
        DWC_CONF_COUNT( "StripPath", pscan->strip_path, 0 ),
        DWC_CONF_STRING( "PrefixPath", pscan->prefix_path, NULL ),
#endif /* UNIX */
#if !defined(DW_SAMBA)        
        DWC_CONF_BOOL( "IncludeReport", need_report, TRUE ),
        DWC_CONF_BOOL( "IncludeStats", need_stats, TRUE ),
        DWC_CONF_COUNT( "ReportMaxSize", pscan->report_size, 4096 ),
#if defined(__UNIX_DW)
        DWC_CONF_BOOL( "RuleFilter", pscan->hre_filter, FALSE ),
        DWC_CONF_BOOL( "SpamFilter", need_hre, FALSE ),
#endif /* UNIX */
#if defined(__WIN32_DW)
        DWC_CONF_INT( "ScanTimeout", pscan->scan_timeout, 30 ),
        DWC_CONF_BOOL( "CheckArchives", pscan->check_arx, FALSE ),
        DWC_CONF_COUNT( "MaxFileSizeToExtract", pscan->max_file_size, 0 ),
        DWC_CONF_COUNT( "MaxCompressionRatio", pscan->max_compression, 0 ),
        DWC_CONF_COUNT( "MaxArchiveLevel", pscan->max_arx_level, 16 ),
#endif /* WIN32 */
#if !defined(DW_MIO)        
        DWC_CONF_STRING( "DenyList", pscan->users_file, NULL ),
        DWC_CONF_STRING( "DenyMode", str_deny, NULL ),
        DWC_CONF_BOOL( "DenyByDefault", pscan->deny_by_default, FALSE ),
#endif /* not MIO */        
#if defined(DW_HAVE_SPOOL)
        DWC_CONF_STRING( "Spool", pscan->spool.tf_path, NULL ),
        DWC_CONF_STRING( "SpoolFilenamesPrefix", pscan->spool.tf_prefix, "drweb.tmp." ),
        DWC_CONF_STRING( "SpoolFilenamesMode", str_snaming, "Std" ),
        DWC_CONF_OCTAL( "SpoolFilesMode", spool_acc, 0600 ),
#if defined(DW_PIPE)
        DWC_CONF_STRING( "RamSpool", pscan->ram_spool, NULL ),
        DWC_CONF_COUNT( "RamThreshold", pscan->ram_threshold, 0 ),
#endif /* PIPE */        
#endif /* HAVE_SPOOL */        
#if defined(DW_SENDMAIL)
        DWC_CONF_STRING( "FilterAccount", pscan->account, NULL ),
        DWC_CONF_BOOL(  "RunForeground", pscan->stay_fg, FALSE ),
        DWC_CONF_BOOL(  "AddXHeaders", pscan->add_headers, FALSE ),
	DWC_CONF_BOOL(  "CanChangeBody", pscan->can_change_body, TRUE ),
        DWC_CONF_BOOL(  "AddXAntispamHeader", pscan->add_antispam_headers, FALSE ),
	DWC_CONF_BOOL(  "AddXAntispamCause", pscan->add_antispam_cause, FALSE ),
#endif /* SENDMAIL */
#else /* SAMBA */
        DWC_CONF_COUNT( "MaxFileSizeToScan", pscan->max_size_to_scan, 0 ),
        DWC_CONF_STRING( "ScanMode", str_mode, "onReadWrite" ),
	DWC_CONF_BOOL( "RewriteDataBase", pscan->rewrite_data_base , TRUE),
	DWC_CONF_COUNT( "BlockedCacheSize", pscan->blocked_cache_size , 4096),
	DWC_CONF_COUNT( "AllowedCacheSize", pscan->allowed_cache_size , 4096),
#endif /* not SAMBA */
        DWC_CONF_BOOL( "LocalScan", pscan->local, TRUE ),
        DWC_CONF_ENDLINE };
     
#if !defined(DW_MIO) && !defined(DW_SAMBA)
    pscan->users = NULL;
#endif /* not MIO and not SAMBA */
    if( read_section_agent( _buf_fs, pline, sec, scanopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
#if defined(DW_SAMBA)
    pscan->max_size_to_scan <<= 10; /* size specified in KBytes */
    if( strp_pref > 0 )
    {
        if( pscan->strip_path > 0 )
        {
            printLib( DW_LL_ERROR, "read section %s: you cannot use StripPath and StripPrefix (obsolete) together", sec );
            goto error_exit;
        }
        else
        {
            printLib( DW_LL_ALERT, "read section %s: use StripPath = StripPrefix, please update you smb_spider.conf", sec );
            pscan->strip_path = strp_pref;
        }
    }
    if( path_pref )
    {
        if( pscan->prefix_path )
        {
            printLib( DW_LL_ERROR, "read section %s: you cannot use PrefixPath and PathPrefix (obsolete) together", sec );
            goto error_exit;
        }
        else
        {
            printLib( DW_LL_ALERT, "read section %s: use StripPath = StripPrefix, please update you smb_spider.conf", sec );
            pscan->prefix_path = DWC_Strdup(path_pref);
            DWC_Free(path_pref);
            if( !pscan->prefix_path )
            {
                printLib( DW_LL_ERROR, "read section %s: no memory for PathPrefix", sec );
                goto error_exit;
            }
        }
    }
    if( !dw_set_slproperty( str_mode, &pscan->scan_mode, ScanModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported scan mode %s specified", sec, str_mode );
        goto error_exit;
    }
    DWC_Free( str_mode );
    DWC_Free( path_pref );
#else /* not SAMBA */
#if defined(__UNIX_DW)
    pscan->hre_filter |= need_hre;
#endif /* UNIX */
#if defined(__WIN32_DW)
    pscan->local = TRUE;
#endif /* WIN32 */
#if defined(DW_HAVE_SPOOL)
    if( !pscan->spool.tf_path )
    {
        printLib( DW_LL_ERROR, "read section %s: spool directory not specified", sec );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    pscan->spool.tf_access = spool_acc & (S_IRWXU | S_IRWXG | S_IRWXO);
    if( !dw_bm_contain( pscan->spool.tf_access, (S_IRUSR | S_IRGRP | S_IROTH) ) )
    {
        printLib( DW_LL_ERROR, "read section %s: access mask %#o is invalid", sec, spool_acc );
        goto error_exit;
    }
#endif /* UNIX */
    if( !dw_set_slproperty( str_snaming, &pscan->spool.tf_naming, FilenameModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid naming mode %s", sec, str_snaming );
        goto error_exit;
    }
#if defined(DW_PIPE)
    if( pscan->ram_spool
        &&
        (0 == pscan->ram_threshold) )
    {
        printLib( DW_LL_ERROR, "read section %s: if you want use RamSpool you must specify RamThreshold", sec, str_snaming );
        goto error_exit;
    }
#endif /* PIPE */    
#endif /* HAVE_SPOOL */    
#if !defined(DW_MIO)    
    pscan->users = NULL;
    if( DW_HAVE_A_PATH(pscan->users_file) )
    {
        pscan->users = create_user_list( pscan->users_file, LOCKED_LIST );
        if( !pscan->users )
        {
            goto error_exit;
        }
    }   
    if( str_deny )
    {
        if( !dw_set_slproperty( str_deny, &pscan->deny_mode, DenyModes ) )
        {
            printLib( DW_LL_ERROR, "read section %s: invalid deny mode %s", sec, str_deny );
            goto error_exit;
        }
    }
    else
    {
        printLib( DW_LL_ALERT, "read section %s: DenyMode doesnt specified - set default byAll", sec );
        pscan->deny_mode = DW_DM_ALL;
    }
#endif /* MIO */    
    dw_bs_empty( pscan->report_options );
    if( need_report )
    {
        dw_bs_add( pscan->report_options, DRWEBD_RETURN_REPORT );       
    }
    if( need_stats )
    {
        dw_bs_add( pscan->report_options, DRWEBD_RETURN_CODES );       
    }
#if !defined(DW_MIO)
    DWC_Free( str_deny );
#if defined(DW_HAVE_SPOOL)
    DWC_Free( str_snaming );
#endif /* HAVE_SPOOL */
#endif /* MIO */    
#endif /* SAMBA */    
    return TRUE;

#if !defined(DW_MIO)
  error_exit:    
#if defined(DW_HAVE_SPOOL)
    DWC_Free( str_snaming );
#endif /* HAVE_SPOOL */
#if !defined(DW_SAMBA) 
    DWC_Free( str_deny );
#else /* SAMBA */
    DWC_Free( str_mode );
    DWC_Free( path_pref );
#endif /* not SAMBA */    
    free_scan_opt( sec, pdata );
    return FALSE;
#endif /* MIO */    
}
#endif /* DW_SAMBA */
/*-------------------------------------------------------------------------*/
dwc_bool_t read_scan_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_scan_opt_t *pscan = (dwcf_scan_opt_t*) pdata;
#if !defined(DW_SAMBA)
#if !defined(DW_MIO)
    dwc_string_t     str_deny;
#endif /* MIO */    
    dwc_bool_t       need_report, need_stats;
#if defined(__UNIX_DW)
    dwc_bool_t       need_hre;
#endif /* UNIX */
#else /* SAMBA */    
    dwc_string_t     str_mode;
    dwc_count_t      strp_pref;
    dwc_string_t     path_pref;
#endif /* SAMBA */    
#if defined(DW_HAVE_SPOOL)
    dwc_count_t      spool_acc;
    char            *str_snaming;
#endif /* HAVE_SPOOL */    
    dwc_conf_set_t   scanopt[] = {
        DWC_CONF_BOOL( "HeuristicAnalysis", pscan->heuristic, FALSE ),
#if defined(DW_SAMBA)        
        DWC_CONF_COUNT( "StripPrefix", strp_pref, 0 ),
        DWC_CONF_STRING( "PathPrefix", path_pref, NULL ),
#endif /* SAMBA */
#if defined(__UNIX_DW)
        DWC_CONF_COUNT( "StripPath", pscan->strip_path, 0 ),
        DWC_CONF_STRING( "PrefixPath", pscan->prefix_path, NULL ),
#endif /* UNIX */
#if !defined(DW_SAMBA)        
        DWC_CONF_BOOL( "IncludeReport", need_report, TRUE ),
        DWC_CONF_BOOL( "IncludeStats", need_stats, TRUE ),
        DWC_CONF_COUNT( "ReportMaxSize", pscan->report_size, 4096 ),
#if defined(__UNIX_DW)
        DWC_CONF_BOOL( "RuleFilter", pscan->hre_filter, FALSE ),
        DWC_CONF_BOOL( "SpamFilter", need_hre, FALSE ),
#endif /* UNIX */
#if defined(__WIN32_DW)
        DWC_CONF_INT( "ScanTimeout", pscan->scan_timeout, 30 ),
        DWC_CONF_BOOL( "CheckArchives", pscan->check_arx, FALSE ),
        DWC_CONF_COUNT( "MaxFileSizeToExtract", pscan->max_file_size, 0 ),
        DWC_CONF_COUNT( "MaxCompressionRatio", pscan->max_compression, 0 ),
        DWC_CONF_COUNT( "MaxArchiveLevel", pscan->max_arx_level, 16 ),
#endif /* WIN32 */
#if !defined(DW_MIO)        
        DWC_CONF_STRING( "DenyList", pscan->users_file, NULL ),
        DWC_CONF_STRING( "DenyMode", str_deny, NULL ),
        DWC_CONF_BOOL( "DenyByDefault", pscan->deny_by_default, FALSE ),
#endif /* not MIO */        
#if defined(DW_HAVE_SPOOL)
        DWC_CONF_STRING( "Spool", pscan->spool.tf_path, NULL ),
        DWC_CONF_STRING( "SpoolFilenamesPrefix", pscan->spool.tf_prefix, "drweb.tmp." ),
        DWC_CONF_STRING( "SpoolFilenamesMode", str_snaming, "Std" ),
        DWC_CONF_OCTAL( "SpoolFilesMode", spool_acc, 0600 ),
#if defined(DW_PIPE)
        DWC_CONF_STRING( "RamSpool", pscan->ram_spool, NULL ),
        DWC_CONF_COUNT( "RamThreshold", pscan->ram_threshold, 0 ),
#endif /* PIPE */        
#endif /* HAVE_SPOOL */        
#if defined(DW_SENDMAIL)
        DWC_CONF_STRING( "FilterAccount", pscan->account, NULL ),
        DWC_CONF_BOOL(  "RunForeground", pscan->stay_fg, FALSE ),
        DWC_CONF_BOOL(  "AddXHeaders", pscan->add_headers, FALSE ),
	DWC_CONF_BOOL(  "CanChangeBody", pscan->can_change_body, TRUE ),
        DWC_CONF_BOOL(  "AddXAntispamHeader", pscan->add_antispam_headers, FALSE ),
	DWC_CONF_BOOL(  "AddXAntispamCause", pscan->add_antispam_cause, FALSE ),
#endif /* SENDMAIL */
#else /* SAMBA */
        DWC_CONF_COUNT( "MaxFileSizeToScan", pscan->max_size_to_scan, 0 ),
        DWC_CONF_STRING( "ScanMode", str_mode, "onReadWrite" ),
	DWC_CONF_BOOL( "RewriteDataBase", pscan->rewrite_data_base , TRUE),
        DWC_CONF_COUNT( "BlockedCacheSize", pscan->blocked_cache_size , 4096),
	DWC_CONF_COUNT( "AllowedCacheSize", pscan->allowed_cache_size , 4096),
#endif /* not SAMBA */
        DWC_CONF_BOOL( "LocalScan", pscan->local, TRUE ),
        DWC_CONF_ENDLINE };
     
#if !defined(DW_MIO) && !defined(DW_SAMBA)
    pscan->users = NULL;
#endif /* not MIO and not SAMBA */
    if( read_section( fs, pline, sec, scanopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
#if defined(DW_SAMBA)
    pscan->max_size_to_scan <<= 10; /* size specified in KBytes */
    if( strp_pref > 0 )
    {
        if( pscan->strip_path > 0 )
        {
            printLib( DW_LL_ERROR, "read section %s: you cannot use StripPath and StripPrefix (obsolete) together", sec );
            goto error_exit;
        }
        else
        {
            printLib( DW_LL_ALERT, "read section %s: use StripPath = StripPrefix, please update you smb_spider.conf", sec );
            pscan->strip_path = strp_pref;
        }
    }
    if( path_pref )
    {
        if( pscan->prefix_path )
        {
            printLib( DW_LL_ERROR, "read section %s: you cannot use PrefixPath and PathPrefix (obsolete) together", sec );
            goto error_exit;
        }
        else
        {
            printLib( DW_LL_ALERT, "read section %s: use StripPath = StripPrefix, please update you smb_spider.conf", sec );
            pscan->prefix_path = DWC_Strdup(path_pref);
            DWC_Free(path_pref);
            if( !pscan->prefix_path )
            {
                printLib( DW_LL_ERROR, "read section %s: no memory for PathPrefix", sec );
                goto error_exit;
            }
        }
    }
    if( !dw_set_slproperty( str_mode, &pscan->scan_mode, ScanModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported scan mode %s specified", sec, str_mode );
        goto error_exit;
    }
    DWC_Free( str_mode );
    DWC_Free( path_pref );
#else /* not SAMBA */
#if defined(__UNIX_DW)
    pscan->hre_filter |= need_hre;
#endif /* UNIX */
#if defined(__WIN32_DW)
    pscan->local = TRUE;
#endif /* WIN32 */
#if defined(DW_HAVE_SPOOL)
    if( !pscan->spool.tf_path )
    {
        printLib( DW_LL_ERROR, "read section %s: spool directory not specified", sec );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    pscan->spool.tf_access = spool_acc & (S_IRWXU | S_IRWXG | S_IRWXO);
    if( !dw_bm_contain( pscan->spool.tf_access, (S_IRUSR | S_IRGRP | S_IROTH) ) )
    {
        printLib( DW_LL_ERROR, "read section %s: access mask %#o is invalid", sec, spool_acc );
        goto error_exit;
    }
#endif /* UNIX */
    if( !dw_set_slproperty( str_snaming, &pscan->spool.tf_naming, FilenameModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid naming mode %s", sec, str_snaming );
        goto error_exit;
    }
#if defined(DW_PIPE)
    if( pscan->ram_spool
        &&
        (0 == pscan->ram_threshold) )
    {
        printLib( DW_LL_ERROR, "read section %s: if you want use RamSpool you must specify RamThreshold", sec, str_snaming );
        goto error_exit;
    }
#endif /* PIPE */    
#endif /* HAVE_SPOOL */    
#if !defined(DW_MIO)    
    pscan->users = NULL;
    if( DW_HAVE_A_PATH(pscan->users_file) )
    {
        pscan->users = create_user_list( pscan->users_file, LOCKED_LIST );
        if( !pscan->users )
        {
            goto error_exit;
        }
    }   
    if( str_deny )
    {
        if( !dw_set_slproperty( str_deny, &pscan->deny_mode, DenyModes ) )
        {
            printLib( DW_LL_ERROR, "read section %s: invalid deny mode %s", sec, str_deny );
            goto error_exit;
        }
    }
    else
    {
        printLib( DW_LL_ALERT, "read section %s: DenyMode doesnt specified - set default byAll", sec );
        pscan->deny_mode = DW_DM_ALL;
    }
#endif /* MIO */    
    dw_bs_empty( pscan->report_options );
    if( need_report )
    {
        dw_bs_add( pscan->report_options, DRWEBD_RETURN_REPORT );       
    }
    if( need_stats )
    {
        dw_bs_add( pscan->report_options, DRWEBD_RETURN_CODES );       
    }
#if !defined(DW_MIO)
    DWC_Free( str_deny );
#if defined(DW_HAVE_SPOOL)
    DWC_Free( str_snaming );
#endif /* HAVE_SPOOL */
#endif /* MIO */    
#endif /* SAMBA */    
    return TRUE;

#if !defined(DW_MIO)
  error_exit:    
#if defined(DW_HAVE_SPOOL)
    DWC_Free( str_snaming );
#endif /* HAVE_SPOOL */
#if !defined(DW_SAMBA) 
    DWC_Free( str_deny );
#else /* SAMBA */
    DWC_Free( str_mode );
    DWC_Free( path_pref );
#endif /* not SAMBA */    
    free_scan_opt( sec, pdata );
    return FALSE;
#endif /* MIO */    
}

/*-------------------------------------------------------------------------*/
void free_scan_opt ( const char *sec, void *pdata )
{
    dwcf_scan_opt_t *pscan = (dwcf_scan_opt_t*) pdata;

#if defined(__UNIX_DW)
    DWC_Free( pscan->prefix_path );
#endif /* UNIX */
#if !defined(DW_SAMBA)
#if !defined(DW_MIO)
    DWC_Free( pscan->users_file );
    delete_user_list( pscan->users );
#endif /* not MIO */
#endif /* not SAMBA */
#if defined(DW_HAVE_SPOOL)    
    DWC_Free( pscan->spool.tf_path );
    DWC_Free( pscan->spool.tf_prefix );
#if defined(DW_SENDMAIL)    
    DWC_Free( pscan->account );
#endif /* SENDMAIL */    
#endif /* HAVE_SPOOL */    
}

/*-------------------------------------------------------------------------*/
#define OPT_ONE_OF( one, bak, name, oldname, def )\
BEGIN_MACRO\
    if( (one) && (bak) )\
    {\
        printLib( DW_LL_ERROR, "read section %s: "oldname" is obsoleted by "name", cannot be used together", sec );\
        goto error_exit;\
    }\
    if( !(one) )\
    {\
        if( !(bak) )\
        {\
            (one) = DWC_Strdup( def );\
            if( !(one) )\
            {\
                printLib( DW_LL_ERROR, "read section %s: no memory for "name" value", sec );\
                goto error_exit;\
            }\
        } else {\
            (one) = DWC_Strdup( (bak) );\
            if( !(one) )\
            {\
                printLib( DW_LL_ERROR, "read section %s: no memory for "name" value", sec );\
                goto error_exit;\
            }\
        }\
    }\
END_MACRO    

/*-------------------------------------------------------------------------*/
#ifdef DW_SAMBA
dwc_bool_t read_action_opt_agent ( char * _buf_fs, int *pline, const char *sec, void *pdata )
{
    dwcf_action_opt_t *pact = (dwcf_action_opt_t*) pdata;
    dwc_bool_t         ret = FALSE;
#if !defined(DW_SAMBA)    
#if !defined(DW_MIO)
    char              *str_filter;
    char              *str_redirect;
    char              *str_empty;
#endif /* not MIO */
    char              *str_qnaming;
    char              *str_admin;
#if defined(__UNIX_DW)
    char              *str_spam;
    char              *str_hre;
#endif /* UNIX */
#else /* SAMBA */
    char              *str_arc;
#endif /* not SAMBA */    
#if defined(__UNIX_DW)
    dwc_count_t        qua_acc;
#if !defined(DW_MIO) 
    char              *str_incu;
    char              *str_incu_old;
    char              *str_cufa;
#endif /* MIO */      
    char              *str_bomb;
#endif /* UNIX */
    char              *str_license;
    char              *str_infect;
    char              *str_susp;
    char              *str_adw;
    char              *str_dlr;
    char              *str_jok;
    char              *str_rsk;
    char              *str_hck;
    char              *str_skip;
    char              *str_arx_res;
    char              *str_scanerr;
    char              *str_clierr;
    dwc_conf_set_t     actopt[] = {
#if defined(__UNIX_DW)        
#if !defined(DW_MIO)
        DWC_CONF_STRING( "Incurable", str_incu, "quarantine" ),
        DWC_CONF_STRING( "Incureable", str_incu_old, NULL ),
        DWC_CONF_STRING( "CureFail", str_cufa, "quarantine" ),
#endif /* not MIO */
#endif /* UNIX */
        DWC_CONF_STRING( "LicenseLimit", str_license, "pass" ),
        DWC_CONF_STRING( "Infected", str_infect, "quarantine" ),
        DWC_CONF_STRING( "Suspicious", str_susp, "quarantine" ),
        DWC_CONF_STRING( "Adware", str_adw, "quarantine" ),
        DWC_CONF_STRING( "Dialers", str_dlr, "quarantine" ),
        DWC_CONF_STRING( "Jokes", str_jok, "quarantine" ),
        DWC_CONF_STRING( "Riskware", str_rsk, "quarantine" ),
        DWC_CONF_STRING( "Hacktools", str_hck, "quarantine" ),
        DWC_CONF_STRING( "SkipObject", str_skip, "reject" ),
        DWC_CONF_STRING( "Quarantine", pact->quarantine.tf_path, NULL ),
#if defined(__UNIX_DW)
        DWC_CONF_OCTAL(  "QuarantineFilesMode", qua_acc, 0600 ),
        DWC_CONF_STRING( "MailbombObject", str_bomb, NULL ),
#endif /* UNIX */
        DWC_CONF_STRING( "ArchiveRestriction", str_arx_res, "pass" ),
        DWC_CONF_BOOL(   "UseCustomReply", pact->custom_reply, FALSE ),
        DWC_CONF_STRING( "ReplyInfected", pact->reply_infected, "DrWeb Antivirus: Message is rejected because it contains a virus(es)." ),
        DWC_CONF_STRING( "ReplyRuleFilter", pact->reply_rule_filter, "DrWeb Antivirus: Message is rejected by headers rule filter." ),
        DWC_CONF_STRING( "ReplyEmptyFrom", pact->reply_empty_from, "DrWeb Antivirus: Messages from <> are blocked by administrator." ),
        DWC_CONF_STRING( "ReplySuspicious", pact->reply_suspicious, "DrWeb Antivirus: Message is rejected because it contains a suspicious content." ),
        DWC_CONF_STRING( "ReplyMalware", pact->reply_malware, "DrWeb Antivirus: Message is rejected because it contains malware." ),
        DWC_CONF_STRING( "ReplySkipObject", pact->reply_skip, "DrWeb Antivirus: Message is rejected because it cannot be checked." ),
        DWC_CONF_STRING( "ReplyArchiveRestriction", pact->reply_archive, "DrWeb Antivirus: Message is rejected because it contains archive which violates restrictions." ),
        DWC_CONF_STRING( "ReplyError", pact->reply_error, "DrWeb Antivirus: Message is rejected due to software error." ),
#if !defined(DW_SAMBA)        
        DWC_CONF_STRING( "ProcessingErrors", str_clierr, "quarantine" ),
        DWC_CONF_STRING( "ScanningErrors", str_scanerr, "quarantine" ),
#if defined(__UNIX_DW)
        DWC_CONF_STRING( "SpamFilterAlert", str_spam, NULL ),
        DWC_CONF_STRING( "RuleFilterAlert", str_hre, NULL ),
#endif /* UNIX */
#if !defined(DW_MIO)
#if defined(DW_CGP) || defined(DW_EXIM) || defined(DW_QMAIL)
        DWC_CONF_BOOL(   "PassEmptyFromIfNoDaemon", pact->pass_empty_from_if_no_daemon, FALSE ),
#endif /* CGP or EXIM */
        DWC_CONF_STRING( "EmptyFrom", str_empty, "continue" ),
        DWC_CONF_STRING( "FilterMail", str_filter, NULL ),        
        DWC_CONF_STRING( "RedirectMail", str_redirect, NULL ),        
        DWC_CONF_STRING( "UnnotificableAddressesList", pact->non_notified_addresses_file, NULL ),        
        DWC_CONF_STRING( "UnnotificableVirusesList", pact->non_notified_viruses_file, NULL ),        
#endif /* not MIO */        
#if defined(__WIN32_DW)
        DWC_CONF_BOOL(   "OnUpdateNotify", pact->on_reload_notify, TRUE ),
        DWC_CONF_BOOL(   "OnStopNotify", pact->on_stop_notify, TRUE ),
#endif /* WIN32 */
        DWC_CONF_STRING( "AdminMail", str_admin, "postmaster" ),
        DWC_CONF_STRING( "QuarantineFilenamesPrefix", pact->quarantine.tf_prefix, "drweb.quarantine." ),
        DWC_CONF_STRING( "QuarantineFilenamesMode", str_qnaming, "Std" ),
#else /* SAMBA */        
        DWC_CONF_STRING( "ProcessingErrors", str_clierr, "reject" ),
        DWC_CONF_STRING( "ScanningErrors", str_scanerr, "reject" ),
        DWC_CONF_STRING( "Archives", str_arc, "reject" ),
        DWC_CONF_STRING( "AdminAddress", pact->admin_addr, NULL ),
        DWC_CONF_BOOL(   "SendNotifyToUser", pact->notify_to_user, FALSE ),
        DWC_CONF_BOOL(   "SendNotifyToAdmin", pact->notify_to_admin, FALSE ),
        DWC_CONF_STRING( "ShellScriptForBlockedFile", pact->script, NULL ),
#endif /* not SAMBA */        
        DWC_CONF_ENDLINE };

    if( read_section_agent( _buf_fs, pline, sec, actopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
#if defined(__UNIX_DW)
#if !defined(DW_MIO)
    OPT_ONE_OF( str_incu, str_incu_old, "Incurable", "Incureable", "quarantine" );    
#endif /* MIO */    
    OPT_ONE_OF( str_arx_res, str_bomb, "ArchiveRestriction", "MailbombObject", "reject" );    
#endif /* UNIX */
#if !defined(DW_SAMBA)    
#if defined(__UNIX_DW)
    OPT_ONE_OF( str_hre, str_spam, "RuleFilterAlert", "SpamFilterAlert", "quarantine" );
#endif /* UNIX */
#if defined(DW_HAVE_SPOOL)
    pact->move_to_quarantine = TRUE;
#else /* not HAVE_SPOOL */
    pact->move_to_quarantine = FALSE;    
#endif /* HAVE_SPOOL */
#if !defined(DW_MIO)
    pact->non_notified_viruses = NULL;    
    pact->non_notified_addresses = NULL;    
    if( DW_HAVE_A_PATH(pact->non_notified_addresses_file) )
    {
        pact->non_notified_addresses = create_maddr_list( pact->non_notified_addresses_file, LOCKED_LIST );
        if( !pact->non_notified_addresses )
        {
            goto error_exit;
        }        
    }
    if( DW_HAVE_A_PATH(pact->non_notified_viruses_file) )
    {
        pact->non_notified_viruses = create_virus_list( pact->non_notified_viruses_file, LOCKED_LIST );
        if( !pact->non_notified_viruses )
        {
            goto error_exit;
        }        
    }
    pact->filter_mail = NULL;
    pact->redirect_mail = NULL;
    if( str_redirect )
    {
        if( !dw_set_mailaddr( str_redirect, &pact->redirect_mail ) )
        {
            printLib( DW_LL_ERROR, "read section %s: not specified redirection mail address", sec );
            goto error_exit;
        }
    }
    else
    {
        printLib( DW_LL_ALERT, "read section %s: you do not specify redirect address, infected message would not been redirected", sec );
    }
    if( !dw_set_mailaddr( str_filter, &pact->filter_mail ) )
    {
        printLib( DW_LL_ERROR, "read section %s: not specified filter mail address", sec );
        goto error_exit;
    }
#endif /* not MIO */    
    pact->admin_mail = NULL;
    if( !dw_set_mailaddr( str_admin, &pact->admin_mail ) )
    {
        printLib( DW_LL_ERROR, "read section %s: not specified administrator mail address", sec );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    if( !dw_set_action( str_hre, SET_FILTER_REJECT, &pact->on_hre_filter_reject ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on rule filter", sec, str_hre );
        goto error_exit;
    }   
#endif /* UNIX */
#if !defined(DW_MIO)
    if( !dw_set_action( str_empty, SET_EMPTYFROM, &pact->on_empty_from ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on empty From:", sec, str_empty );
        goto error_exit;
    }   
#endif /* MIO */
    if( !dw_set_slproperty( str_qnaming, &pact->quarantine.tf_naming, FilenameModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid naming mode %s", sec, str_qnaming );
        goto error_exit;
    }
#else /* SAMBA */
    if( !dw_set_action( str_arc, SET_ARCHIVE, &pact->on_archive ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on archives", sec, str_arc );
        goto error_exit;
    }
    if( pact->notify_to_admin && !pact->admin_addr )
    {
        printLib( DW_LL_ERROR, "read section %s: you want sent notifications to admin, but does not specify admin address", sec );
        goto error_exit;
    }
#endif /* SAMBA */
    if( pact->quarantine.tf_path )
    {
#if defined(__UNIX_DW)
        pact->quarantine.tf_access = qua_acc & (S_IRWXU | S_IRWXG | S_IRWXO);
        if( !dw_bm_contain( pact->quarantine.tf_access, (S_IRUSR | S_IRGRP | S_IROTH) ) )
        {
            printLib( DW_LL_ERROR, "read section %s: access mask %#o is invalid", sec, qua_acc );
            goto error_exit;
        }
#endif /* UNIX */
#if defined(__WIN32_DW)
        pact->quarantine.tf_access = 0;
#endif /* WIN32 */
    }
    else
    {
        printLib( DW_LL_ALERT, "read section %s: you do not specify quarantine directory, infected message would not been storied", sec );
    }
#if defined(__UNIX_DW)
#if !defined(DW_MIO)
    if( !dw_set_action( str_cufa, SET_CURE_FAIL, &pact->on_cure_fail ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on cure fail", sec, str_cufa );
        goto error_exit;
    }
    if( !dw_set_action( str_incu, SET_INCURABLE, &pact->on_incurable ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on incurable", sec, str_incu );
        goto error_exit;
    }
#endif /* MIO */    
#endif /* UNIX */
    if( !dw_set_action( str_license, SET_LICENSE, &pact->on_license_error ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on license limit", sec, str_license );
        goto error_exit;
    }
    if( !dw_set_action( str_infect, SET_INFECTED, &pact->on_infected ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on virus", sec, str_infect );
        goto error_exit;
    }
    if( !dw_set_action( str_susp, SET_SUSPICIOUS, &pact->on_suspicious ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on suspicious", sec, str_susp );
        goto error_exit;
    }       
    if( !dw_set_action( str_adw, SET_ADWARE, &pact->on_adware ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on adware", sec, str_adw );
        goto error_exit;
    }       
    if( !dw_set_action( str_dlr, SET_DIALER, &pact->on_dialer ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on dialers", sec, str_dlr );
        goto error_exit;
    }       
    if( !dw_set_action( str_jok, SET_JOKE, &pact->on_joke ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on jokes", sec, str_jok );
        goto error_exit;
    }       
    if( !dw_set_action( str_rsk, SET_RISKWARE, &pact->on_riskware ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on riskware", sec, str_rsk );
        goto error_exit;
    }       
    if( !dw_set_action( str_hck, SET_HACKTOOL, &pact->on_hacktool ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on intrusion tools (hacktool)", sec, str_hck );
        goto error_exit;
    }       
    if( !dw_set_action( str_skip, SET_SKIPOBJ, &pact->on_skip ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on skip object", sec, str_skip );
        goto error_exit;
    }
    if( !dw_set_action( str_arx_res, SET_ARCHIVE_RES, &pact->on_archive_restriction ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on mailbomb", sec, str_arx_res );
        goto error_exit;
    }
    if( !dw_set_action( str_scanerr, SET_SCANERR, &pact->on_scan_error ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on scanning errors", sec, str_scanerr );
        goto error_exit;
    }
    if( !dw_set_action( str_clierr, SET_PROCERR, &pact->on_proc_error ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on processing errors", sec, str_clierr );
        goto error_exit;
    }
    ret = TRUE;
  error_exit:
#if !defined(DW_SAMBA)  
    if( !ret )
    {
        free_action_opt( sec, pdata );
    }
#endif /* SAMBA */


#if !defined(DW_SAMBA)
#if !defined(DW_MIO)
    DWC_Free( str_filter );
    DWC_Free( str_redirect );
    DWC_Free( str_empty );    
    DWC_Free( str_qnaming );
#endif /* MIO */
    DWC_Free( str_admin );
#if defined(__UNIX_DW)
    DWC_Free( str_spam );   
    DWC_Free( str_hre );   
#endif /* UNIX */
#else /* SAMBA */
    //    DWC_Free( str_arc );
#endif /* not SAMBA */    
#if defined(__UNIX_DW)
#if !defined(DW_MIO)    
    //    DWC_Free( str_incu );   
    //DWC_Free( str_cufa );   
#endif /* not MIO */  
    DWC_Free( str_bomb );   
#endif /* UNIX */
    //DWC_Free( str_license );    
    //DWC_Free( str_infect );    
    //    DWC_Free( str_susp );
    //DWC_Free( str_adw );
    //DWC_Free( str_dlr );
    //DWC_Free( str_jok );
    //DWC_Free( str_rsk );
    //DWC_Free( str_hck );
    //DWC_Free( str_skip );   
    //DWC_Free( str_arx_res );   
    //DWC_Free( str_scanerr );   
    //DWC_Free( str_clierr );   
    return ret;     
}
#endif /* DW_SAMBA */
/*-------------------------------------------------------------------------*/
dwc_bool_t read_action_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_action_opt_t *pact = (dwcf_action_opt_t*) pdata;
    dwc_bool_t         ret = FALSE;
#if !defined(DW_SAMBA)    
#if !defined(DW_MIO)
    char              *str_filter;
    char              *str_redirect;
    char              *str_empty;
#endif /* not MIO */
    char              *str_qnaming;
    char              *str_admin;
#if defined(__UNIX_DW)
    char              *str_spam;
    char              *str_hre;
#endif /* UNIX */
#else /* SAMBA */
    char              *str_arc;
#endif /* not SAMBA */    
#if defined(__UNIX_DW)
    dwc_count_t        qua_acc;
#if !defined(DW_MIO) 
    char              *str_incu;
    char              *str_incu_old;
    char              *str_cufa;
#endif /* MIO */      
    char              *str_bomb;
#endif /* UNIX */
    char              *str_license;
    char              *str_infect;
    char              *str_susp;
    char              *str_adw;
    char              *str_dlr;
    char              *str_jok;
    char              *str_rsk;
    char              *str_hck;
    char              *str_skip;
    char              *str_arx_res;
    char              *str_scanerr;
    char              *str_clierr;
    dwc_conf_set_t     actopt[] = {
#if defined(__UNIX_DW)        
#if !defined(DW_MIO)
        DWC_CONF_STRING( "Incurable", str_incu, NULL ),
        DWC_CONF_STRING( "Incureable", str_incu_old, NULL ),
        DWC_CONF_STRING( "CureFail", str_cufa, "quarantine" ),
#endif /* not MIO */
#endif /* UNIX */
        DWC_CONF_STRING( "LicenseLimit", str_license, "pass" ),
        DWC_CONF_STRING( "Infected", str_infect, "quarantine" ),
        DWC_CONF_STRING( "Suspicious", str_susp, "quarantine" ),
        DWC_CONF_STRING( "Adware", str_adw, "quarantine" ),
        DWC_CONF_STRING( "Dialers", str_dlr, "quarantine" ),
        DWC_CONF_STRING( "Jokes", str_jok, "quarantine" ),
        DWC_CONF_STRING( "Riskware", str_rsk, "quarantine" ),
        DWC_CONF_STRING( "Hacktools", str_hck, "quarantine" ),
        DWC_CONF_STRING( "SkipObject", str_skip, "reject" ),
        DWC_CONF_STRING( "Quarantine", pact->quarantine.tf_path, NULL ),
#if defined(__UNIX_DW)
        DWC_CONF_OCTAL(  "QuarantineFilesMode", qua_acc, 0600 ),
        DWC_CONF_STRING( "MailbombObject", str_bomb, NULL ),
#endif /* UNIX */
        DWC_CONF_STRING( "ArchiveRestriction", str_arx_res, "pass" ),
        DWC_CONF_BOOL(   "UseCustomReply", pact->custom_reply, FALSE ),
        DWC_CONF_STRING( "ReplyInfected", pact->reply_infected, "DrWeb Antivirus: Message is rejected because it contains a virus(es)." ),
        DWC_CONF_STRING( "ReplyRuleFilter", pact->reply_rule_filter, "DrWeb Antivirus: Message is rejected by headers rule filter." ),
        DWC_CONF_STRING( "ReplyEmptyFrom", pact->reply_empty_from, "DrWeb Antivirus: Messages from <> are blocked by administrator." ),
        DWC_CONF_STRING( "ReplySuspicious", pact->reply_suspicious, "DrWeb Antivirus: Message is rejected because it contains a suspicious content." ),
        DWC_CONF_STRING( "ReplyMalware", pact->reply_malware, "DrWeb Antivirus: Message is rejected because it contains malware." ),
        DWC_CONF_STRING( "ReplySkipObject", pact->reply_skip, "DrWeb Antivirus: Message is rejected because it cannot be checked." ),
        DWC_CONF_STRING( "ReplyArchiveRestriction", pact->reply_archive, "DrWeb Antivirus: Message is rejected because it contains archive which violates restrictions." ),
        DWC_CONF_STRING( "ReplyError", pact->reply_error, "DrWeb Antivirus: Message is rejected due to software error." ),
#if !defined(DW_SAMBA)        
        DWC_CONF_STRING( "ProcessingErrors", str_clierr, "quarantine" ),
        DWC_CONF_STRING( "ScanningErrors", str_scanerr, "quarantine" ),
#if defined(__UNIX_DW)
        DWC_CONF_STRING( "SpamFilterAlert", str_spam, NULL ),
        DWC_CONF_STRING( "RuleFilterAlert", str_hre, NULL ),
#endif /* UNIX */
#if !defined(DW_MIO)
#if defined(DW_CGP) || defined(DW_EXIM) || defined(DW_QMAIL)
        DWC_CONF_BOOL(   "PassEmptyFromIfNoDaemon", pact->pass_empty_from_if_no_daemon, FALSE ),
#endif /* CGP or EXIM */
        DWC_CONF_STRING( "EmptyFrom", str_empty, "continue" ),
        DWC_CONF_STRING( "FilterMail", str_filter, NULL ),        
        DWC_CONF_STRING( "RedirectMail", str_redirect, NULL ),        
        DWC_CONF_STRING( "UnnotificableAddressesList", pact->non_notified_addresses_file, NULL ),        
        DWC_CONF_STRING( "UnnotificableVirusesList", pact->non_notified_viruses_file, NULL ),        
#endif /* not MIO */        
#if defined(__WIN32_DW)
        DWC_CONF_BOOL(   "OnUpdateNotify", pact->on_reload_notify, TRUE ),
        DWC_CONF_BOOL(   "OnStopNotify", pact->on_stop_notify, TRUE ),
#endif /* WIN32 */
        DWC_CONF_STRING( "AdminMail", str_admin, "postmaster" ),
        DWC_CONF_STRING( "QuarantineFilenamesPrefix", pact->quarantine.tf_prefix, "drweb.quarantine." ),
        DWC_CONF_STRING( "QuarantineFilenamesMode", str_qnaming, "Std" ),
#else /* SAMBA */        
        DWC_CONF_STRING( "ProcessingErrors", str_clierr, "reject" ),
        DWC_CONF_STRING( "ScanningErrors", str_scanerr, "reject" ),
        DWC_CONF_STRING( "Archives", str_arc, "reject" ),
        DWC_CONF_STRING( "AdminAddress", pact->admin_addr, NULL ),
        DWC_CONF_BOOL(   "SendNotifyToUser", pact->notify_to_user, FALSE ),
        DWC_CONF_BOOL(   "SendNotifyToAdmin", pact->notify_to_admin, FALSE ),
        DWC_CONF_STRING( "ShellScriptForBlockedFile", pact->script, NULL ),
#endif /* not SAMBA */        
        DWC_CONF_ENDLINE };

    if( read_section( fs, pline, sec, actopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
#if defined(__UNIX_DW)
#if !defined(DW_MIO)
    OPT_ONE_OF( str_incu, str_incu_old, "Incurable", "Incureable", "quarantine" );    
#endif /* MIO */    
    OPT_ONE_OF( str_arx_res, str_bomb, "ArchiveRestriction", "MailbombObject", "reject" );    
#endif /* UNIX */
#if !defined(DW_SAMBA)    
#if defined(__UNIX_DW)
    OPT_ONE_OF( str_hre, str_spam, "RuleFilterAlert", "SpamFilterAlert", "quarantine" );
#endif /* UNIX */
#if defined(DW_HAVE_SPOOL)
    pact->move_to_quarantine = TRUE;
#else /* not HAVE_SPOOL */
    pact->move_to_quarantine = FALSE;    
#endif /* HAVE_SPOOL */
#if !defined(DW_MIO)
    pact->non_notified_viruses = NULL;    
    pact->non_notified_addresses = NULL;    
    if( DW_HAVE_A_PATH(pact->non_notified_addresses_file) )
    {
        pact->non_notified_addresses = create_maddr_list( pact->non_notified_addresses_file, LOCKED_LIST );
        if( !pact->non_notified_addresses )
        {
            goto error_exit;
        }        
    }
    if( DW_HAVE_A_PATH(pact->non_notified_viruses_file) )
    {
        pact->non_notified_viruses = create_virus_list( pact->non_notified_viruses_file, LOCKED_LIST );
        if( !pact->non_notified_viruses )
        {
            goto error_exit;
        }        
    }
    pact->filter_mail = NULL;
    pact->redirect_mail = NULL;
    if( str_redirect )
    {
        if( !dw_set_mailaddr( str_redirect, &pact->redirect_mail ) )
        {
            printLib( DW_LL_ERROR, "read section %s: not specified redirection mail address", sec );
            goto error_exit;
        }
    }
    else
    {
        printLib( DW_LL_ALERT, "read section %s: you do not specify redirect address, infected message would not been redirected", sec );
    }
    if( !dw_set_mailaddr( str_filter, &pact->filter_mail ) )
    {
        printLib( DW_LL_ERROR, "read section %s: not specified filter mail address", sec );
        goto error_exit;
    }
#endif /* not MIO */    
    pact->admin_mail = NULL;
    if( !dw_set_mailaddr( str_admin, &pact->admin_mail ) )
    {
        printLib( DW_LL_ERROR, "read section %s: not specified administrator mail address", sec );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    if( !dw_set_action( str_hre, SET_FILTER_REJECT, &pact->on_hre_filter_reject ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on rule filter", sec, str_hre );
        goto error_exit;
    }   
#endif /* UNIX */
#if !defined(DW_MIO)
    if( !dw_set_action( str_empty, SET_EMPTYFROM, &pact->on_empty_from ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on empty From:", sec, str_empty );
        goto error_exit;
    }   
#endif /* MIO */
    if( !dw_set_slproperty( str_qnaming, &pact->quarantine.tf_naming, FilenameModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid naming mode %s", sec, str_qnaming );
        goto error_exit;
    }
#else /* SAMBA */
    if( !dw_set_action( str_arc, SET_ARCHIVE, &pact->on_archive ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on archives", sec, str_arc );
        goto error_exit;
    }
    if( pact->notify_to_admin && !pact->admin_addr )
    {
        printLib( DW_LL_ERROR, "read section %s: you want sent notifications to admin, but does not specify admin address", sec );
        goto error_exit;
    }
#endif /* SAMBA */    
    if( pact->quarantine.tf_path )
    {
#if defined(__UNIX_DW)
        pact->quarantine.tf_access = qua_acc & (S_IRWXU | S_IRWXG | S_IRWXO);
        if( !dw_bm_contain( pact->quarantine.tf_access, (S_IRUSR | S_IRGRP | S_IROTH) ) )
        {
            printLib( DW_LL_ERROR, "read section %s: access mask %#o is invalid", sec, qua_acc );
            goto error_exit;
        }
#endif /* UNIX */
#if defined(__WIN32_DW)
        pact->quarantine.tf_access = 0;
#endif /* WIN32 */
    }
    else
    {
        printLib( DW_LL_ALERT, "read section %s: you do not specify quarantine directory, infected message would not been storied", sec );
    }
#if defined(__UNIX_DW)
#if !defined(DW_MIO)
    if( !dw_set_action( str_cufa, SET_CURE_FAIL, &pact->on_cure_fail ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on cure fail", sec, str_cufa );
        goto error_exit;
    }
    if( !dw_set_action( str_incu, SET_INCURABLE, &pact->on_incurable ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on incurable", sec, str_incu );
        goto error_exit;
    }
#endif /* MIO */    
#endif /* UNIX */
    if( !dw_set_action( str_license, SET_LICENSE, &pact->on_license_error ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on license limit", sec, str_license );
        goto error_exit;
    }
    if( !dw_set_action( str_infect, SET_INFECTED, &pact->on_infected ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on virus", sec, str_infect );
        goto error_exit;
    }
    if( !dw_set_action( str_susp, SET_SUSPICIOUS, &pact->on_suspicious ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on suspicious", sec, str_susp );
        goto error_exit;
    }       
    if( !dw_set_action( str_adw, SET_ADWARE, &pact->on_adware ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on adware", sec, str_adw );
        goto error_exit;
    }       
    if( !dw_set_action( str_dlr, SET_DIALER, &pact->on_dialer ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on dialers", sec, str_dlr );
        goto error_exit;
    }       
    if( !dw_set_action( str_jok, SET_JOKE, &pact->on_joke ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on jokes", sec, str_jok );
        goto error_exit;
    }       
    if( !dw_set_action( str_rsk, SET_RISKWARE, &pact->on_riskware ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on riskware", sec, str_rsk );
        goto error_exit;
    }       
    if( !dw_set_action( str_hck, SET_HACKTOOL, &pact->on_hacktool ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on intrusion tools (hacktool)", sec, str_hck );
        goto error_exit;
    }       
    if( !dw_set_action( str_skip, SET_SKIPOBJ, &pact->on_skip ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on skip object", sec, str_skip );
        goto error_exit;
    }
    if( !dw_set_action( str_arx_res, SET_ARCHIVE_RES, &pact->on_archive_restriction ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on mailbomb", sec, str_arx_res );
        goto error_exit;
    }
    if( !dw_set_action( str_scanerr, SET_SCANERR, &pact->on_scan_error ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on scanning errors", sec, str_scanerr );
        goto error_exit;
    }
    if( !dw_set_action( str_clierr, SET_PROCERR, &pact->on_proc_error ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid action %s on processing errors", sec, str_clierr );
        goto error_exit;
    }
    ret = TRUE;
  error_exit:
#if !defined(DW_SAMBA)  
    if( !ret )
    {
        free_action_opt( sec, pdata );
    }
#endif /* SAMBA */    
#if !defined(DW_SAMBA)
#if !defined(DW_MIO)
    DWC_Free( str_filter );
    DWC_Free( str_redirect );
    DWC_Free( str_empty );    
    DWC_Free( str_qnaming );
#endif /* MIO */
    DWC_Free( str_admin );
#if defined(__UNIX_DW)
    DWC_Free( str_spam );   
    DWC_Free( str_hre );   
#endif /* UNIX */
#else /* SAMBA */
    DWC_Free( str_arc );
#endif /* not SAMBA */    
#if defined(__UNIX_DW)
#if !defined(DW_MIO)    
    DWC_Free( str_incu );   
    DWC_Free( str_cufa );   
#endif /* not MIO */  
    DWC_Free( str_bomb );   
#endif /* UNIX */
    DWC_Free( str_license );    
    DWC_Free( str_infect );    
    DWC_Free( str_susp );
    DWC_Free( str_adw );
    DWC_Free( str_dlr );
    DWC_Free( str_jok );
    DWC_Free( str_rsk );
    DWC_Free( str_hck );
    DWC_Free( str_skip );   
    DWC_Free( str_arx_res );   
    DWC_Free( str_scanerr );   
    DWC_Free( str_clierr );   
    return ret;     
}

/*-------------------------------------------------------------------------*/
void free_action_opt ( const char *sec, void *pdata )
{
#if !defined(DW_SAMBA)
    dwcf_action_opt_t *pact = (dwcf_action_opt_t*) pdata;

#if !defined(DW_MIO)
    delete_virus_list( pact->non_notified_viruses );
    delete_maddr_list( pact->non_notified_addresses );
    DWC_Free( pact->non_notified_viruses_file );
    DWC_Free( pact->non_notified_addresses_file );
    DWC_Free( pact->filter_mail );
    DWC_Free( pact->redirect_mail );      
#if defined(DW_SENDMAIL)
    DWC_Free( pact->reply_infected );
    DWC_Free( pact->reply_rule_filter );
    DWC_Free( pact->reply_empty_from );
    DWC_Free( pact->reply_suspicious );
    DWC_Free( pact->reply_malware );
    DWC_Free( pact->reply_skip );
    DWC_Free( pact->reply_archive );
    DWC_Free( pact->reply_error );
#endif /* SENDMAIL */
#endif /* not MIO */    
    DWC_Free( pact->admin_mail );
    DWC_Free( pact->quarantine.tf_path );              
    DWC_Free( pact->quarantine.tf_prefix );              
#endif /* not SAMBA */    
}

#if defined(DW_SENDMAIL)
/*-------------------------------------------------------------------------*/
dwc_bool_t read_notopt_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_postscan_opt_t *ppost = (dwcf_postscan_opt_t*) pdata;
    dwc_string_t         salt;
    dwc_conf_set_t       notopt[] = {
        DWC_CONF_BOOL( "FastNotify", ppost->fast_notify , FALSE ),
        DWC_CONF_STRING( "NotifyHashSalt", salt, NULL ),
        DWC_CONF_ENDLINE };
        
    if( read_section( fs, pline, sec, notopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
    if( ppost->fast_notify )
    {
        if( !salt )
        {
            printLib( DW_LL_ERROR, "read section %s: you should specify NotifyHashSalt if use FastNotify", sec );
            return FALSE;            
        }         
        ppost->secure_hash[0] = NULLCHAR;   
        if( !dw_generate_hash_string( salt, ppost->secure_hash ) )
        {            
            printLib( DW_LL_ERROR, "read section %s: could not generate secure hash", sec );
            DWC_Free( salt );
            return FALSE;
        }
    }
    DWC_Free( salt );
    return TRUE;
}
/*-------------------------------------------------------------------------*/
void free_notopt_opt ( const char *sec, void *pdata )
{
}
#endif /* SENDMAIL */

#if !defined(DW_SAMBA)
/*-------------------------------------------------------------------------*/
dwc_bool_t read_notify_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_notify_opt_t *pnot = (dwcf_notify_opt_t*) pdata;
    dwc_conf_set_t  notopt[] = {
#if !defined(DW_MIO)    
        DWC_CONF_BOOL( "SenderNotify", pnot->to_sender , FALSE ),
        DWC_CONF_BOOL( "AdminNotify", pnot->to_admin , FALSE ),
        DWC_CONF_BOOL( "RcptsNotify", pnot->to_rcpts , FALSE ),
        DWC_CONF_STRING( "RcptsTemplate", pnot->rcpts_template, NULL ),
        DWC_CONF_STRING( "AdminTemplate", pnot->admin_template, NULL ),
        DWC_CONF_STRING( "SenderTemplate", pnot->sender_template, NULL ),
#else /* MIO */
        DWC_CONF_STRING( "Template", pnot->notify_template, NULL ),
#endif /* not MIO */        
        DWC_CONF_ENDLINE };

    if( 0 == DWC_strncasecmp( sec, "CuredNotifications", strlen("CuredNotifications") ) )
    {
#if !defined(DW_MIO)    
        have_curednotify_section = TRUE;
#else
        printLib( DW_LL_ALERT, "read section %s: MIO should not have this section", sec );
        return TRUE;
#endif    
    }
    if( 0 == DWC_strncasecmp( sec, "MalwareNotifications", strlen("MalwareNotifications") ) )
    {
        have_malware_section = TRUE;
    }
    if( 0 == DWC_strncasecmp( sec, "LicenseLimitNotifications", strlen("LicenseLimitNotifications") ) )
    {
        have_license_section = TRUE;
    }
    if( 0 == DWC_strncasecmp( sec, "RuleFilterNotifications", strlen("RuleFilterNotifications") ) )
    {
        have_rule_section = TRUE;
    }
    if( 0 == DWC_strncasecmp( sec, "MailbombNotifications", strlen("MailbombNotifications") ) )
    {
        if( have_archive_section )
        {
            printLib( DW_LL_ERROR, "read section %s: is obsoleted by ArchiveRestrictionNotifications, cannot be used together", sec );
            return FALSE;
        }
        have_mailbomb_section = TRUE;
    }
    if( 0 == DWC_strncasecmp( sec, "ArchiveRestrictionNotifications", strlen("ArchiveRestrictionNotifications") ) )
    {
        if( have_mailbomb_section )
        {
            printLib( DW_LL_ERROR, "read section %s: obsolete MailbombNotifications, cannot be used together", sec );
            return FALSE;
        }
        have_archive_section = TRUE;
    }
    if( read_section( fs, pline, sec, notopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
#if !defined(DW_MIO)
    if( !pnot->sender_template && pnot->to_sender )
    {
        printLib( DW_LL_ERROR, "read section %s: you should specify filename with message template for sender", sec );
        goto error_exit;
    }
    if( !pnot->admin_template && pnot->to_admin )
    {
        printLib( DW_LL_ERROR, "read section %s: you should specify filename with message template for administrator", sec );
        goto error_exit;
    }
    if( !pnot->rcpts_template && pnot->to_rcpts )
    {
        printLib( DW_LL_ERROR, "read section %s: you should specify filename with message template for recipients", sec );
        goto error_exit;
    }
#else /* MIO */
    if( !pnot->notify_template )
    {
        printLib( DW_LL_ERROR, "read section %s: you should specify filename with message template for sender", sec );
        goto error_exit;
    }
#endif /* MIO */
    return TRUE;
    
  error_exit:
    free_notify_opt( sec, pdata );
    return FALSE;
}

/*-------------------------------------------------------------------------*/
void free_notify_opt ( const char *sec, void *pdata )
{
    dwcf_notify_opt_t *pnot = (dwcf_notify_opt_t*) pdata;

#if !defined(DW_MIO)    
    DWC_Free( pnot->sender_template );
    DWC_Free( pnot->admin_template );
    DWC_Free( pnot->rcpts_template );
#else /* MIO */
    DWC_Free( pnot->notify_template );
#endif /* not MIO */
}
#endif /* not SAMBA */
/*-------------------------------------------------------------------------*/
#ifdef DW_SAMBA
dwc_bool_t read_log_opt_agent ( char * _buf_fs, int *pline, const char *sec, void *pdata )
{
    dwcf_log_opt_t *plog = (dwcf_log_opt_t*) pdata;
#if defined(__UNIX_DW)
    char           *slf;
    char           *slp;   
#endif /* UNIX */
#if defined(__WIN32_DW)
    struct stat     st;
#endif /* WIN32 */
    char           *ll;
    dwc_bool_t      exitst = FALSE;
    dwc_conf_set_t  logopt[] = {
        DWC_CONF_STRING( "Level", ll, "Quiet" ),
#if defined(__UNIX_DW)
#if defined(DW_HAVE_SPOOL)
        DWC_CONF_BOOL( "DebugSpool", plog->debug_spool, FALSE ),
#endif /* HAVE_SPOOL */
#if defined(DW_SAMBA)
        DWC_CONF_STRING( "SyslogFacility", slf, "Daemon" ),
#else /* not SAMBA */
        DWC_CONF_STRING( "SyslogFacility", slf, "Mail" ),
#endif /* SAMBA */
        DWC_CONF_STRING( "SyslogPriority", slp, "Info" ),        
#endif /* UNIX */
#if defined(__WIN32_DW)
        DWC_CONF_STRING( "LogFilename", plog->filename, "drweb_cgp.log" ),        
        DWC_CONF_BOOL( "LogScanned", plog->log_scanned, TRUE ),
        DWC_CONF_COUNT( "MaxLogSize", plog->max_size, 0 ),
#endif /* WIN32 */
        DWC_CONF_ENDLINE };
        
    if( read_section_agent( _buf_fs, pline, sec, logopt, '=', ',' ) < 0 )
    {
        goto error_exit;
    }          
    if( !dw_set_slproperty( ll, &plog->level, LogLevels ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported log level %s specified", sec, ll );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    if( !dw_set_slproperty( slf, &plog->sl_facility, SyslogFacilities ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported syslog facility %s specified", sec, slf );
        goto error_exit;
    }
    if( !dw_set_slproperty( slp, &plog->sl_priority, SyslogPriorities ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported syslog priority %s specified", sec, slp );
        goto error_exit;
    }
#endif /* UNIX */
#if defined(__WIN32_DW)
    if( DW_HAVE_A_PATH(plog->filename) )
    {
        if( (stat( plog->filename, &st ) == 0)
            &&
            (access_file( plog->filename, W_OK ) != 0) )
        {
            printLib( DW_LL_ERROR, "read section %s: logfile %s is not accessible for writing", sec, plog->filename );
            goto error_exit;
        }
    }
    else
    {
        printLib( DW_LL_ERROR, "read section %s: you must specify log filename", sec );
        goto error_exit;
    }
#endif /* WIN32 */    
    exitst = TRUE;
  error_exit:    
    if( !exitst )
        free_log_opt( sec, pdata );
#if defined(__UNIX_DW)
    DWC_Free( slf );
    DWC_Free( slp );
#endif /* UNIX */
    DWC_Free( ll );
    return exitst;
}
#endif /* DW_SAMBA */
/*-------------------------------------------------------------------------*/
dwc_bool_t read_log_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_log_opt_t *plog = (dwcf_log_opt_t*) pdata;
#if defined(__UNIX_DW)
    char           *slf;
    char           *slp;   
#endif /* UNIX */
#if defined(__WIN32_DW)
    struct stat     st;
#endif /* WIN32 */
    char           *ll;
    dwc_bool_t      exitst = FALSE;
    dwc_conf_set_t  logopt[] = {
        DWC_CONF_STRING( "Level", ll, "Quiet" ),
#if defined(__UNIX_DW)
#if defined(DW_HAVE_SPOOL)
        DWC_CONF_BOOL( "DebugSpool", plog->debug_spool, FALSE ),
#endif /* HAVE_SPOOL */
#if defined(DW_SAMBA)
        DWC_CONF_STRING( "SyslogFacility", slf, "Daemon" ),
#else /* not SAMBA */
        DWC_CONF_STRING( "SyslogFacility", slf, "Mail" ),
#endif /* SAMBA */
        DWC_CONF_STRING( "SyslogPriority", slp, "Info" ),        
#endif /* UNIX */
#if defined(__WIN32_DW)
        DWC_CONF_STRING( "LogFilename", plog->filename, "drweb_cgp.log" ),        
        DWC_CONF_BOOL( "LogScanned", plog->log_scanned, TRUE ),
        DWC_CONF_COUNT( "MaxLogSize", plog->max_size, 0 ),
#endif /* WIN32 */
        DWC_CONF_ENDLINE };
        
    if( read_section( fs, pline, sec, logopt, '=', ',' ) < 0 )
    {
        goto error_exit;
    }          
    if( !dw_set_slproperty( ll, &plog->level, LogLevels ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported log level %s specified", sec, ll );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    if( !dw_set_slproperty( slf, &plog->sl_facility, SyslogFacilities ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported syslog facility %s specified", sec, slf );
        goto error_exit;
    }
    if( !dw_set_slproperty( slp, &plog->sl_priority, SyslogPriorities ) )
    {
        printLib( DW_LL_ERROR, "read section %s: unsupported syslog priority %s specified", sec, slp );
        goto error_exit;
    }
#endif /* UNIX */
#if defined(__WIN32_DW)
    if( DW_HAVE_A_PATH(plog->filename) )
    {
        if( (stat( plog->filename, &st ) == 0)
            &&
            (access_file( plog->filename, W_OK ) != 0) )
        {
            printLib( DW_LL_ERROR, "read section %s: logfile %s is not accessible for writing", sec, plog->filename );
            goto error_exit;
        }
    }
    else
    {
        printLib( DW_LL_ERROR, "read section %s: you must specify log filename", sec );
        goto error_exit;
    }
#endif /* WIN32 */    
    exitst = TRUE;
  error_exit:    
    if( !exitst )
        free_log_opt( sec, pdata );
#if defined(__UNIX_DW)
    DWC_Free( slf );
    DWC_Free( slp );
#endif /* UNIX */
    DWC_Free( ll );
    return exitst;
}
/*-------------------------------------------------------------------------*/
void free_log_opt ( const char *sec, void *pdata )
{
#if defined(__WIN32_DW)
    dwcf_log_opt_t *plog = (dwcf_log_opt_t*) pdata;

    DWC_Free( plog->filename );
#endif /* WIN32 */
}

#if !defined(DW_SAMBA)
/*-------------------------------------------------------------------------*/
#if defined(DW_MIO)
#define CHECK_SUBMITTER        NOP
#else /* not MIO */
#if !defined(DW_CGP)
#define CHECK_SUBMITTER                                                                                                   \
BEGIN_MACRO                                                                                                               \
    if( !pms->submitter )                                                                                                 \
    {                                                                                                                     \
        printLib( DW_LL_ERROR, "read section %s: sendmail program not specified", sec );                           \
        goto error_exit;                                                                                                  \
    }                                                                                                                     \
END_MACRO
#else /* CGP */
#define CHECK_SUBMITTER                                                                                                   \
BEGIN_MACRO                                                                                                               \
    if( !pms->submitting.tf_path )                                                                                        \
    {                                                                                                                     \
        printLib( DW_LL_ERROR, "read section %s: Submitted directory not specified", sec );                        \
        goto error_exit;                                                                                                  \
    }                                                                                                                     \
END_MACRO
#endif /* not CGP */
#endif /* not MIO */

/*-------------------------------------------------------------------------*/
#define CHECK_MAILER( m )                                                                                                 \
BEGIN_MACRO                                                                                                               \
    if( !pms->mailer )                                                                                                    \
    {                                                                                                                     \
        printLib( DW_LL_ERROR, "read section %s: this filter work with "#m", but mailer not specified", sec );     \
        goto error_exit;\
    }                                                                                                                     \
    CHECK_SUBMITTER;                                                                                                      \
    if( 0 != DWC_strncasecmp( pms->mailer, m, strlen(m)) )                                                                \
    {                                                                                                                     \
        printLib( DW_LL_ERROR, "read section %s: this filter work with "#m", but conf file for %s mailer", sec, pms->mailer ); \
        goto error_exit;                                                                                                  \
    }                                                                                                                     \
END_MACRO

/*-------------------------------------------------------------------------*/
dwc_bool_t read_submit_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_submit_opt_t *pms = (dwcf_submit_opt_t*) pdata;
#if defined(DW_COURIER)
    dwc_length_t       len;
#endif /* COURIER */
#if defined(DW_CGP)
    char*              str_naming;
#endif /* CGP */
#if defined(__UNIX_DW)
#if defined(DW_COURIER) || defined(DW_CGP) 
    dwc_count_t        access;
#endif /* COURIER or CGP */    
#endif /* UNIX */
    dwc_conf_set_t  msopt[] = {
        DWC_CONF_STRING( "MailSystem", pms->mailer, NULL ),
#if !defined(DW_CGP)
#if !defined(DW_MIO)
        DWC_CONF_STRING( "Sendmail", pms->submitter, NULL ),
        DWC_CONF_STRING( "SendmailArgs", pms->submit_args, NULL ),
#endif /* not MIO */        
#else /* CGP */
        DWC_CONF_STRING( "SubmitDir", pms->submitting.tf_path, NULL ),
        DWC_CONF_STRING( "SubmitFilenamesPrefix", pms->submitting.tf_prefix, "drweb_submit_" ),
        DWC_CONF_STRING( "SubmitFilenamesMode", str_naming, "Std" ),
#if defined(__UNIX_DW)
        DWC_CONF_OCTAL(  "SubmitFilesMode", access, 0600 ),
#endif /* UNIX */
#endif /* not CGP */        
#if defined(DW_SENDMAIL)        
        DWC_CONF_STRING( "MilterAddress", pms->milter.addr, NULL ),
        DWC_CONF_INT( "MilterTimeout", pms->milter.timeout, 7210 ),
        DWC_CONF_INT( "MilterPendedConnections", pms->milter.backlog, 128 ),
        DWC_CONF_INT( "MilterDebugLevel", pms->milter.dbg_level, 0 ),
#endif /* SENDMAIL */        
#if defined(DW_COURIER)
        DWC_CONF_STRING( "CourierBaseDir", pms->courier.basedir, NULL ),
        DWC_CONF_STRING( "CourierSocketDir", pms->courier.socketdir, NULL ),
        DWC_CONF_INT( "FilterPendedConnections", pms->courier.backlog, 32 ),
        DWC_CONF_OCTAL( "FilterSocketAccess", access, 0660 ),
#endif /* COURIER */        
#if defined(DW_ZMAILER)
        DWC_CONF_COUNT( "FilterInterfaceVersion", pms->interface_version, 0 ),
#endif /* ZMAILER */
#if defined(DW_QMAIL)    
        DWC_CONF_STRING( "QmailQueue", pms->qmail_queue, NULL ),
#endif /* QMAIL */        
        DWC_CONF_ENDLINE };
        
    if( read_section( fs, pline, sec, msopt, '=', ',' ) < 0 )
    {
        return FALSE;
    }

#if defined(DW_CGP)
    CHECK_MAILER( "CommuniGatePro" );
    if( !dw_set_slproperty( str_naming, &pms->submitting.tf_naming, FilenameModes ) )
    {
        printLib( DW_LL_ERROR, "read section %s: invalid naming mode %s", sec, str_naming );
        goto error_exit;
    }
#if defined(__UNIX_DW)
    pms->submitting.tf_access = access & (S_IRWXU | S_IRWXG | S_IRWXO);
    if( !dw_bm_contain( pms->submitting.tf_access, (S_IRUSR | S_IRGRP | S_IROTH) ) )
    {
        printLib( DW_LL_ERROR, "read section %s: access mask %#o is invalid", sec, access );
        goto error_exit;
    }
#endif /* UNIX */
#if defined(__WIN32_DW)
    pms->submitting.tf_access = 0;
#endif /* WIN32 */
    DWC_Free(str_naming);
#endif /* CGP */

#if defined(DW_ZMAILER)
    CHECK_MAILER( "ZMailer" );
#endif /* ZMAILER */

#if defined(DW_MIO)
    pms->submitter = NULL;
    pms->submit_args = NULL;
    CHECK_MAILER( "Mobico" );
#endif /* ZMAILER */

#if defined(DW_SENDMAIL)    
    CHECK_MAILER( "Sendmail" );
    if( !pms->milter.addr )
    {
        printLib( DW_LL_ERROR, "read section %s: you must specify Milter address from sendmail.cf", sec );
        goto error_exit;
    }
#endif /* SENDMAIL */

#if defined(DW_POSTFIX)    
    CHECK_MAILER( "Postfix" );
#endif /* PIPE */

#if defined(DW_EXIM)    
    CHECK_MAILER( "Exim" );
#endif /* PIPE */

#if defined(DW_QMAIL)    
    CHECK_MAILER( "QMail" );
    if( !pms->qmail_queue )
    {
        printLib( DW_LL_ERROR, "read section %s: you must specify original qmail-queue binary", sec );
        goto error_exit;
    }
#endif /* QMAIL */    

#if defined(DW_COURIER)
#define COURIER_DEFAULT_SOCKET_PATH  "/var/allfilters"
    CHECK_MAILER( "CourierMTA" );
    if( !pms->courier.basedir )
    {
        printLib( DW_LL_ERROR, "read section %s: you must specify CourierMTA base directory", sec );
        goto error_exit;
    }
    if( !pms->courier.socketdir )
    {
        len = strlen(pms->courier.basedir) + strlen(COURIER_DEFAULT_SOCKET_PATH) + 2;
        pms->courier.socketdir = DWC_Malloc( dwc_path_t, len );
        if( !pms->courier.socketdir )   
        {
            printLib( DW_LL_ERROR, "read section %s: no memory for default Courier socket directory", sec );
            goto error_exit;
        }
        snprintf( pms->courier.socketdir, len, "%s%s", pms->courier.basedir, COURIER_DEFAULT_SOCKET_PATH );
        printLib( DW_LL_ALERT, "read section %s: you should use CourierSocketDir option, while set default socket dir to %s", sec, pms->courier.socketdir );
    }
    pms->courier.access = access;
    if( !dw_bm_contain( pms->courier.access, (S_IRWXU | S_IRWXG | S_IRWXO) ) )
    {
        printLib( DW_LL_ERROR, "read section %s: access mask %#o is invalid", sec, pms->courier.access );
        goto error_exit;
    }
    pms->courier.socket_fd = INVALID_UNIX_SOCKET;
#endif /* COURIER */

    return TRUE; 
 error_exit:
#if defined(DW_CGP)
    DWC_Free(str_naming);
#endif /* CGP */
    free_submit_opt( sec, pdata );
    return FALSE;
}

/*-------------------------------------------------------------------------*/
void free_submit_opt ( const char *sec, void *pdata )
{
    dwcf_submit_opt_t *pms = (dwcf_submit_opt_t*) pdata;

    DWC_Free( pms->mailer );
#if defined(DW_SENDMAIL) || defined(DW_COURIER)
    DWC_Free( pms->ctl_address );
#endif /* SENDMAIL or COURIER */
#if !defined(DW_CGP)
    DWC_Free( pms->submitter );
    DWC_Free( pms->submit_args );
#endif /* not CGP */
#if defined(DW_CGP)
    DWC_Free( pms->submitting.tf_path );
    DWC_Free( pms->submitting.tf_prefix );
#endif /* CGP */    
#if defined(DW_QMAIL)    
    DWC_Free( pms->qmail_queue );
#endif /* QMAIL */    
#if defined(DW_COURIER)
    DWC_Free( pms->courier.basedir );
#endif /* COURIER */
#if defined(DW_SENDMAIL)
    DWC_Free( pms->milter.addr );
#endif /* SENDMAIL */    
}

#if defined(__UNIX_DW)
/*-------------------------------------------------------------------------*/
dwc_bool_t read_agent_opt ( FILE *fs, int *pline, const char *sec, void *pdata )
{
    dwcf_agent_opt_t *pa = (dwcf_agent_opt_t*) pdata;
    dwc_conf_set_t    agent_opt[] = {
        DWC_CONF_STRING( "Address", pa->addr, NULL ),
        DWC_CONF_COUNT( "Timeout", pa->timeout, 10 ),        
        DWC_CONF_ENDLINE };

    if( read_section( fs, pline, sec, agent_opt, '=', ',' ) < 0 )
    {
        return FALSE;
    }
    if( !pa->addr )
    {
        printLib( DW_LL_VERBOSE, "read section %s: address for statistic server not defined", sec );
    }
    have_agent_section = TRUE;
#if defined(DW_SENDMAIL) || defined(DW_CGP) || defined(DW_ZMAILER) || defined(DW_COURIER) || defined(DW_MIO)
    pa->ipc_locker = INVALID_MUTEX;
    pa->ipc = INVALID_IPC;
#endif /* SENDMAIL or CGP or ZMAILER or COURIER or MIO */
    return TRUE;
}
/*-------------------------------------------------------------------------*/
void free_agent_opt ( const char *sec, void *pdata )
{
    dwcf_agent_opt_t *pa = (dwcf_agent_opt_t*) pdata;

    DWC_Free(pa->addr);    
}

#endif /* UNIX */
#endif /* not SAMBA */

#endif /* _DW_OPTIONS_H */
