You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
998 lines
25 KiB
C
998 lines
25 KiB
C
/*
|
|
* binkleyforce -- unix FTN mailer project
|
|
*
|
|
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "confread.h"
|
|
#include "logger.h"
|
|
#include "util.h"
|
|
#include "outbound.h" /* Required only for ``proc_filebox()'' */
|
|
|
|
struct tab_options {
|
|
const char *keystr;
|
|
unsigned long value_no;
|
|
unsigned long value_yes;
|
|
} options[] = {
|
|
{ "Zmodem", OPTIONS_NO_ZMODEM, 0 },
|
|
{ "ZedZap", OPTIONS_NO_ZEDZAP, 0 },
|
|
{ "DirZap", OPTIONS_NO_DIRZAP, 0 },
|
|
{ "Janus", OPTIONS_NO_JANUS, 0 },
|
|
{ "Hydra", OPTIONS_NO_HYDRA, 0 },
|
|
{ "BinkP", OPTIONS_NO_BINKP, 0 },
|
|
{ "TCP", OPTIONS_NO_TCP, 0 },
|
|
{ "Chat", OPTIONS_NO_CHAT, 0 },
|
|
{ "FTS1", OPTIONS_NO_FTS1, 0 },
|
|
{ "YooHoo", OPTIONS_NO_YOOHOO, 0 },
|
|
{ "EMSI", OPTIONS_NO_EMSI, 0 },
|
|
{ "EMSI-II", OPTIONS_NO_EMSI_II, 0 },
|
|
{ "Freqs", OPTIONS_NO_FREQS, 0 },
|
|
{ "MailOnly", 0, OPTIONS_MAILONLY },
|
|
{ "HoldXT" , 0, OPTIONS_HOLDXT },
|
|
{ "HoldReq", 0, OPTIONS_HOLDREQ },
|
|
{ "HoldAll", 0, OPTIONS_HOLDALL },
|
|
{ "HoldHold", 0, OPTIONS_HOLDHOLD },
|
|
{ "PickUp", OPTIONS_NO_PICKUP, 0 },
|
|
{ "RH1", OPTIONS_NO_RH1, 0 },
|
|
{ "Intro", OPTIONS_NO_INTRO, 0 },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
struct tab_resptypes {
|
|
const char *str;
|
|
int value;
|
|
int retv;
|
|
} resptypes[] = {
|
|
{ "Connect", RESPTYPE_CONNECT, 0 },
|
|
{ "Busy", RESPTYPE_BUSY, 11 },
|
|
{ "Nocarrier", RESPTYPE_NOCARRIER, 12 },
|
|
{ "Nodialtone", RESPTYPE_NODIALTONE, 13 },
|
|
{ "Noanswer", RESPTYPE_NOANSWER, 14 },
|
|
{ "Error", RESPTYPE_ERROR, 15 },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
#define CONF_KEY(name, type) { #name, type, NULL, cf_##name }
|
|
#define CONF_END() { NULL, 0, NULL, 0 }
|
|
|
|
s_conf_entry bforce_config[BFORCE_NUMBER_OF_KEYWORDS+1] = {
|
|
CONF_KEY(address, CT_ADDRESS),
|
|
CONF_KEY(amiga_outbound_directory, CT_PATH),
|
|
CONF_KEY(binkp_timeout, CT_NUMBER),
|
|
CONF_KEY(daemon_circle, CT_NUMBER),
|
|
CONF_KEY(daemon_circle_crash, CT_NUMBER),
|
|
CONF_KEY(daemon_circle_direct, CT_NUMBER),
|
|
CONF_KEY(daemon_circle_immed, CT_NUMBER),
|
|
CONF_KEY(daemon_circle_modem, CT_NUMBER),
|
|
CONF_KEY(daemon_circle_normal, CT_NUMBER),
|
|
CONF_KEY(daemon_circle_rescan, CT_NUMBER),
|
|
CONF_KEY(daemon_maxclients_modem, CT_NUMBER),
|
|
CONF_KEY(daemon_maxclients_tcpip, CT_NUMBER),
|
|
CONF_KEY(daemon_pid_file, CT_STRING),
|
|
CONF_KEY(delay_files_recv, CT_STRING),
|
|
CONF_KEY(delay_files_send, CT_STRING),
|
|
CONF_KEY(disable_aka_matching, CT_BOOLEAN),
|
|
CONF_KEY(domain, CT_DOMAIN),
|
|
CONF_KEY(emsi_FR_time, CT_STRING),
|
|
CONF_KEY(emsi_OH_time, CT_STRING),
|
|
CONF_KEY(emsi_slave_sends_nak, CT_BOOLEAN),
|
|
CONF_KEY(filebox, CT_FILEBOX),
|
|
CONF_KEY(filebox_directory, CT_PATH),
|
|
CONF_KEY(flags, CT_STRING),
|
|
CONF_KEY(flo_translate, CT_TRANSLATE),
|
|
CONF_KEY(freq_alias_list, CT_STRING),
|
|
CONF_KEY(freq_dir_list, CT_STRING),
|
|
CONF_KEY(freq_ignore_masks, CT_STRING),
|
|
CONF_KEY(freq_limit_number, CT_NUMBER),
|
|
CONF_KEY(freq_limit_size, CT_NUMBER),
|
|
CONF_KEY(freq_limit_time, CT_NUMBER),
|
|
CONF_KEY(freq_min_speed, CT_NUMBER),
|
|
CONF_KEY(freq_srif_command, CT_STRING),
|
|
CONF_KEY(hide_our_aka, CT_ADDRESS),
|
|
CONF_KEY(history_file, CT_STRING),
|
|
CONF_KEY(hydra_options, CT_OPTIONS),
|
|
CONF_KEY(hydra_mincps_recv, CT_CONNLIST),
|
|
CONF_KEY(hydra_mincps_send, CT_CONNLIST),
|
|
CONF_KEY(hydra_tx_window, CT_NUMBER),
|
|
CONF_KEY(hydra_rx_window, CT_NUMBER),
|
|
CONF_KEY(inbound_directory, CT_PATH),
|
|
CONF_KEY(location, CT_STRING),
|
|
CONF_KEY(log_file, CT_STRING),
|
|
CONF_KEY(log_file_daemon, CT_STRING),
|
|
CONF_KEY(max_speed, CT_NUMBER),
|
|
CONF_KEY(maxtries, CT_TRIES),
|
|
CONF_KEY(maxtries_nodial, CT_TRIES),
|
|
CONF_KEY(maxtries_noansw, CT_TRIES),
|
|
CONF_KEY(maxtries_noconn, CT_TRIES),
|
|
CONF_KEY(maxtries_hshake, CT_TRIES),
|
|
CONF_KEY(maxtries_sessions, CT_TRIES),
|
|
CONF_KEY(min_cps_recv, CT_NUMBER),
|
|
CONF_KEY(min_cps_send, CT_NUMBER),
|
|
CONF_KEY(min_cps_time, CT_NUMBER),
|
|
CONF_KEY(min_free_space, CT_NUMBER),
|
|
CONF_KEY(min_speed_in, CT_NUMBER),
|
|
CONF_KEY(min_speed_out, CT_NUMBER),
|
|
CONF_KEY(mode_netmail, CT_FILEMODE),
|
|
CONF_KEY(mode_arcmail, CT_FILEMODE),
|
|
CONF_KEY(mode_request, CT_FILEMODE),
|
|
CONF_KEY(mode_ticfile, CT_FILEMODE),
|
|
CONF_KEY(mode_default, CT_FILEMODE),
|
|
CONF_KEY(modem_can_send_break, CT_BOOLEAN),
|
|
CONF_KEY(modem_dial_prefix, CT_STRING),
|
|
CONF_KEY(modem_dial_suffix, CT_STRING),
|
|
CONF_KEY(modem_dial_response, CT_DIALRESP),
|
|
CONF_KEY(modem_hangup_command, CT_STRING),
|
|
CONF_KEY(modem_port, CT_MODEMPORT),
|
|
CONF_KEY(modem_reset_command, CT_STRING),
|
|
CONF_KEY(modem_stat_command, CT_STRING),
|
|
CONF_KEY(nodelist, CT_NODELIST),
|
|
CONF_KEY(nodelist_directory, CT_PATH),
|
|
CONF_KEY(nodial_flag, CT_STRING),
|
|
CONF_KEY(override, CT_OVERRIDE),
|
|
CONF_KEY(options, CT_OPTIONS),
|
|
CONF_KEY(outbound_directory, CT_PATH),
|
|
CONF_KEY(password, CT_PASSWORD),
|
|
CONF_KEY(phone, CT_STRING),
|
|
CONF_KEY(phone_translate, CT_TRANSLATE),
|
|
CONF_KEY(recode_file_in, CT_STRING),
|
|
CONF_KEY(recode_file_out, CT_STRING),
|
|
CONF_KEY(recode_intro_in, CT_STRING),
|
|
CONF_KEY(recv_buffer_size, CT_NUMBER),
|
|
CONF_KEY(rescan_delay, CT_NUMBER),
|
|
CONF_KEY(run_after_handshake, CT_STRING),
|
|
CONF_KEY(run_after_session, CT_STRING),
|
|
CONF_KEY(session_limit_in, CT_NUMBER),
|
|
CONF_KEY(session_limit_out, CT_NUMBER),
|
|
CONF_KEY(skip_files_recv, CT_STRING),
|
|
CONF_KEY(status_directory, CT_PATH),
|
|
CONF_KEY(system_name, CT_STRING),
|
|
CONF_KEY(sysop_name, CT_STRING),
|
|
CONF_KEY(uucp_lock_directory, CT_PATH),
|
|
CONF_KEY(wait_carrier_in, CT_NUMBER),
|
|
CONF_KEY(wait_carrier_out, CT_NUMBER),
|
|
CONF_KEY(zmodem_mincps_recv, CT_CONNLIST),
|
|
CONF_KEY(zmodem_mincps_send, CT_CONNLIST),
|
|
CONF_KEY(zmodem_send_dummy_pkt, CT_BOOLEAN),
|
|
CONF_KEY(zmodem_skip_by_pos, CT_BOOLEAN),
|
|
CONF_KEY(zmodem_start_block_size, CT_NUMBER),
|
|
CONF_KEY(zmodem_tx_window, CT_NUMBER),
|
|
CONF_KEY(nomail_flag, CT_STRING),
|
|
CONF_KEY(bind_ip, CT_STRING),
|
|
#ifdef USE_SYSLOG
|
|
CONF_KEY(syslog_facility, CT_NUMBER),
|
|
#endif
|
|
#ifdef DEBUG
|
|
CONF_KEY(debug_file, CT_STRING),
|
|
CONF_KEY(debug_level, CT_DEBLEVEL),
|
|
#endif
|
|
CONF_END()
|
|
};
|
|
|
|
static int proc_override(s_override *dest, char *value);
|
|
static int proc_options(s_options *options, char *value);
|
|
static int proc_string(s_string *dest, char *value);
|
|
static int proc_number(s_number *dest, char *value);
|
|
static int proc_filemode(s_filemode *dest, char *value);
|
|
static int proc_boolean(s_boolean *dest, char *value);
|
|
static int proc_address(s_falist *dest, char *value);
|
|
static int proc_nodelist(s_falist *dest, char *value);
|
|
static int proc_modemport(s_modemport *dest, char *value);
|
|
static int proc_domain(s_domain *dest, char *value);
|
|
static int proc_password(s_falist *dest, char *value);
|
|
static int proc_path(s_string *dest, char *value);
|
|
static int proc_dialresp(s_dialresp *dest, char *value);
|
|
static int proc_translate(s_translate *dest, char *value);
|
|
static int proc_speeddep(s_connlist *dest, char *value);
|
|
static int proc_tries(s_tries *dest, char *value);
|
|
#ifdef DEBUG
|
|
static int proc_debuglevel(s_number *dest, char *value);
|
|
#endif
|
|
static int proc_filebox(s_filebox *dest, char *value);
|
|
|
|
static int append_config_entry(s_conf_entry *conf_ent, s_cval_entry *cval_entry)
|
|
{
|
|
s_cval_entry **ptrl;
|
|
|
|
for( ptrl = &conf_ent->data; *ptrl; ptrl = &(*ptrl)->next );
|
|
|
|
*ptrl = (s_cval_entry *)xmalloc(sizeof(s_cval_entry));
|
|
memcpy(*ptrl, cval_entry, sizeof(s_cval_entry));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int proc_configline(const char *k, const char *e, const char *v)
|
|
{
|
|
s_cval_entry temp_value;
|
|
int rc = PROC_RC_ABORT;
|
|
int i;
|
|
char *copy;
|
|
|
|
ASSERT(k != NULL && v != NULL );
|
|
|
|
DEB((D_CONFIG, "conf_proc: key \"%s\" expr \"%s\" value \"%s\"",
|
|
k, e, v));
|
|
|
|
copy = xstrcpy(v);
|
|
|
|
for( i = 0; bforce_config[i].name; i++ )
|
|
if( !strcmp(bforce_config[i].name, k) )
|
|
break;
|
|
|
|
if( bforce_config[i].name )
|
|
{
|
|
/*
|
|
* Make all changes in temp_value structure
|
|
*/
|
|
memset(&temp_value, '\0', sizeof(s_cval_entry));
|
|
|
|
switch(bforce_config[i].type) {
|
|
case CT_ADDRESS:
|
|
rc = proc_address(&temp_value.d.falist, copy);
|
|
break;
|
|
case CT_BOOLEAN:
|
|
rc = proc_boolean(&temp_value.d.boolean, copy);
|
|
break;
|
|
case CT_CONNLIST:
|
|
rc = proc_speeddep(&temp_value.d.connlist, copy);
|
|
break;
|
|
case CT_DIALRESP:
|
|
rc = proc_dialresp(&temp_value.d.dialresp, copy);
|
|
break;
|
|
case CT_DOMAIN:
|
|
rc = proc_domain(&temp_value.d.domain, copy);
|
|
break;
|
|
case CT_FILEMODE:
|
|
rc = proc_filemode(&temp_value.d.filemode, copy);
|
|
break;
|
|
case CT_MODEMPORT:
|
|
rc = proc_modemport(&temp_value.d.modemport, copy);
|
|
break;
|
|
case CT_NODELIST:
|
|
rc = proc_nodelist(&temp_value.d.falist, copy);
|
|
break;
|
|
case CT_NUMBER:
|
|
rc = proc_number(&temp_value.d.number, copy);
|
|
break;
|
|
case CT_OPTIONS:
|
|
rc = proc_options(&temp_value.d.options, copy);
|
|
break;
|
|
case CT_OVERRIDE:
|
|
rc = proc_override(&temp_value.d.override, copy);
|
|
break;
|
|
case CT_PATH:
|
|
rc = proc_path(&temp_value.d.string, copy);
|
|
break;
|
|
case CT_PASSWORD:
|
|
rc = proc_password(&temp_value.d.falist, copy);
|
|
break;
|
|
case CT_STRING:
|
|
rc = proc_string(&temp_value.d.string, copy);
|
|
break;
|
|
case CT_TRANSLATE:
|
|
rc = proc_translate(&temp_value.d.translate, copy);
|
|
break;
|
|
case CT_TRIES:
|
|
rc = proc_tries(&temp_value.d.tries, copy);
|
|
break;
|
|
#ifdef DEBUG
|
|
case CT_DEBLEVEL:
|
|
rc = proc_debuglevel(&temp_value.d.number, copy);
|
|
break;
|
|
#endif
|
|
case CT_FILEBOX:
|
|
rc = proc_filebox(&temp_value.d.filebox, copy);
|
|
break;
|
|
default:
|
|
log("internal error, unknown keyword type = %d",
|
|
bforce_config[i].type);
|
|
ASSERT(0);
|
|
}
|
|
|
|
if( rc == PROC_RC_OK || rc == PROC_RC_WARN )
|
|
{
|
|
if( e && *e )
|
|
{
|
|
temp_value.expr.expr = xstrcpy(e);
|
|
temp_value.expr.error = 0;
|
|
}
|
|
append_config_entry(&bforce_config[i], &temp_value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
log("unknown keyword \"%s\"", k);
|
|
rc = PROC_RC_IGNORE;
|
|
}
|
|
|
|
free(copy);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Line format: Override <Address> <Overrides..> [Hidden <Overrides>]
|
|
*/
|
|
static int proc_override(s_override *dest, char *value)
|
|
{
|
|
s_override **p = &dest;
|
|
s_faddr addr;
|
|
int rc = PROC_RC_OK;
|
|
char *key = NULL;
|
|
char *arg = NULL;
|
|
char *n = NULL;
|
|
char *p_addr = NULL;
|
|
bool neednew = FALSE;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_addr = string_token(value, &n, NULL, 0);
|
|
if( p_addr == NULL || *p_addr == '\0' || ftn_addrparse(&addr, p_addr, FALSE) )
|
|
return(PROC_RC_IGNORE);
|
|
|
|
memset(dest, '\0', sizeof(s_override));
|
|
dest->addr = addr;
|
|
|
|
while( key || (key = string_token(NULL, &n, NULL, 1)) )
|
|
{
|
|
if( (arg = string_token(NULL, &n, NULL, 1)) == NULL || *arg == '\0' )
|
|
{
|
|
log("no argument(s) for override \"%s\"", key);
|
|
if( rc < PROC_RC_WARN )
|
|
rc = PROC_RC_WARN;
|
|
break;
|
|
}
|
|
|
|
if( neednew )
|
|
{
|
|
(*p) = (s_override*)xmalloc(sizeof(s_override));
|
|
memset(*p, '\0', sizeof(s_override));
|
|
(*p)->addr = addr;
|
|
neednew = FALSE;
|
|
}
|
|
|
|
if( strcasecmp(key, "phone") == 0 )
|
|
{
|
|
if( (*p)->sPhone )
|
|
free((*p)->sPhone);
|
|
(*p)->sPhone = xstrcpy(arg);
|
|
key = NULL;
|
|
}
|
|
else if( strcasecmp(key, "ipaddr") == 0 )
|
|
{
|
|
if( (*p)->sIpaddr )
|
|
free((*p)->sIpaddr);
|
|
(*p)->sIpaddr = xstrcpy(arg);
|
|
key = NULL;
|
|
}
|
|
else if( strcasecmp(key, "worktime") == 0 )
|
|
{
|
|
if( timevec_parse_list(&((*p)->worktime), arg) == -1 )
|
|
{
|
|
log("invalid work time \"%s\"", arg);
|
|
if( rc < PROC_RC_WARN )
|
|
rc = PROC_RC_WARN;
|
|
}
|
|
key = NULL;
|
|
}
|
|
else if( strcasecmp(key, "freqtime") == 0 )
|
|
{
|
|
if( timevec_parse_list(&((*p)->freqtime), arg) == -1 )
|
|
{
|
|
log("invalid freq time \"%s\"", arg);
|
|
if( rc < PROC_RC_WARN )
|
|
rc = PROC_RC_WARN;
|
|
}
|
|
key = NULL;
|
|
}
|
|
else if( strcasecmp(key, "flags") == 0 )
|
|
{
|
|
if( (*p)->sFlags )
|
|
free((*p)->sFlags);
|
|
(*p)->sFlags = xstrcpy(arg);
|
|
key = NULL;
|
|
}
|
|
else if( strcasecmp(key, "hidden") == 0 )
|
|
{
|
|
neednew = TRUE;
|
|
p = &((*p)->hidden);
|
|
key = arg;
|
|
}
|
|
else
|
|
{
|
|
log("unknown keyword \"%s\" in override", key);
|
|
if( rc < PROC_RC_WARN )
|
|
rc = PROC_RC_WARN;
|
|
key = arg;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
/*
|
|
* Line format: Options <options..>
|
|
*/
|
|
static int proc_options(s_options *dest, char *value)
|
|
{
|
|
int i, rc = PROC_RC_OK;
|
|
char *key = NULL, *n = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
for( key = string_token(value, &n, NULL, 0); key;
|
|
key = string_token(NULL, &n, NULL, 0) )
|
|
{
|
|
for( i = 0; options[i].keystr; i++ )
|
|
{
|
|
if( strcasecmp(key, options[i].keystr) == 0 )
|
|
{
|
|
if( options[i].value_no )
|
|
{
|
|
dest->value &= ~options[i].value_no;
|
|
dest->mask |= options[i].value_no;
|
|
}
|
|
if( options[i].value_yes )
|
|
{
|
|
dest->value |= options[i].value_yes;
|
|
dest->mask |= options[i].value_yes;
|
|
}
|
|
#ifdef DEBUG
|
|
if( options[i].value_no == 0 && options[i].value_yes == 0 )
|
|
ASSERT_MSG();
|
|
#endif
|
|
break;
|
|
}
|
|
else if( (strncasecmp(key, "no", 2) == 0
|
|
&& strcasecmp(key+2, options[i].keystr) == 0)
|
|
|| (*key == '!'
|
|
&& strcasecmp(key+1, options[i].keystr) == 0) )
|
|
{
|
|
if( options[i].value_no )
|
|
{
|
|
dest->value |= options[i].value_no;
|
|
dest->mask |= options[i].value_no;
|
|
}
|
|
if( options[i].value_yes )
|
|
{
|
|
dest->value &= ~options[i].value_yes;
|
|
dest->mask |= options[i].value_yes;
|
|
}
|
|
#ifdef DEBUG
|
|
if( !options[i].value_no && !options[i].value_yes )
|
|
ASSERT_MSG();
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !options[i].keystr )
|
|
{
|
|
log("unknown option \"%s\"", key);
|
|
if( rc < PROC_RC_WARN )
|
|
rc = PROC_RC_WARN;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Any value>
|
|
*/
|
|
static int proc_string(s_string *dest, char *value)
|
|
{
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
dest->str = xstrcpy(value);
|
|
|
|
return PROC_RC_OK;
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Number>
|
|
*/
|
|
static int proc_number(s_number *dest, char *value)
|
|
{
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
if( !ISDEC(value) )
|
|
{
|
|
log("value \"%s\" isn't numeric", value);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
dest->num = atol(value);
|
|
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Octal permissions>
|
|
*/
|
|
static int proc_filemode(s_filemode *dest, char *value)
|
|
{
|
|
int rc = PROC_RC_OK;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
if( !ISOCT(value) )
|
|
{
|
|
log("value \"%s\" isn't octal number", value);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
sscanf(value, "%o", (unsigned int *)&dest->mode);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Yes|No|True|False>
|
|
*/
|
|
static int proc_boolean(s_boolean *dest, char *value)
|
|
{
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
if( !strcasecmp(value, "yes")
|
|
|| !strcasecmp(value, "true") )
|
|
{
|
|
dest->istrue = 1;
|
|
return(PROC_RC_OK);
|
|
}
|
|
else if( !strcasecmp(value, "no")
|
|
|| !strcasecmp(value, "false") )
|
|
{
|
|
dest->istrue = 0;
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
log("unexpected argument \"%s\", must be \"Yes\" or \"No\"", value);
|
|
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <FTN address|Inet address>
|
|
*/
|
|
static int proc_address(s_falist *dest, char *value)
|
|
{
|
|
s_faddr addr;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
if( ftn_addrparse(&addr, value, FALSE) )
|
|
{
|
|
log("can't parse address \"%s\"", value);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
dest->addr = addr;
|
|
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <File name> <Address>
|
|
*/
|
|
static int proc_nodelist(s_falist *dest, char *value)
|
|
{
|
|
s_faddr addr;
|
|
char *n = NULL;
|
|
char *p_name = NULL;
|
|
char *p_addr = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_name = string_token(value, &n, NULL, 1);
|
|
p_addr = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_name && *p_name && p_addr && *p_addr )
|
|
{
|
|
if( ftn_addrparse(&addr, p_addr, TRUE) == 0 )
|
|
{
|
|
dest->addr = addr;
|
|
dest->what = xstrcpy(p_name);
|
|
return(PROC_RC_OK);
|
|
}
|
|
else
|
|
{
|
|
log("can't parse address \"%s\"", p_addr);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
}
|
|
|
|
log("incorrect nodelist specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <domain> <path> <zone>
|
|
*/
|
|
static int proc_domain(s_domain *dest, char *value)
|
|
{
|
|
char *n = NULL;
|
|
char *p_domn = NULL;
|
|
char *p_path = NULL;
|
|
char *p_zone = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_domn = string_token(value, &n, NULL, 1);
|
|
p_path = string_token(NULL, &n, NULL, 1);
|
|
p_zone = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_domn && *p_domn && p_path && *p_path && p_zone && *p_zone )
|
|
{
|
|
if( ISDEC(p_zone) )
|
|
{
|
|
dest->domain = xstrcpy(p_domn);
|
|
dest->zone = atoi(p_zone);
|
|
if( p_path[strlen(p_path)-1] == DIRSEPCHR )
|
|
dest->path = xstrcpy(p_path);
|
|
else
|
|
dest->path = string_concat(p_path, DIRSEPSTR, NULL);
|
|
return(PROC_RC_OK);
|
|
}
|
|
else
|
|
{
|
|
log("zone isn't numeric value in domain specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
}
|
|
|
|
log("incorrect domain specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <port>[:<lockspeed>]
|
|
*/
|
|
static int proc_modemport(s_modemport *dest, char *value)
|
|
{
|
|
char *p_speed = NULL;
|
|
long speed = 0;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_speed = strrchr(value, ':');
|
|
|
|
if( p_speed ) {
|
|
if( ISDEC(p_speed+1) )
|
|
{
|
|
p_speed[0] = '\0';
|
|
speed = atol(p_speed+1);
|
|
}
|
|
else
|
|
{
|
|
log("incorrect modem port \"%s\": bad lock speed", value);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
}
|
|
|
|
dest->name = xstrcpy(value);
|
|
dest->speed = speed;
|
|
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Address> <Password>
|
|
*/
|
|
static int proc_password(s_falist *dest, char *value)
|
|
{
|
|
s_faddr addr;
|
|
char *n = NULL;
|
|
char *p_addr = NULL;
|
|
char *p_passwd = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_addr = string_token(value, &n, NULL, 1);
|
|
p_passwd = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_addr && *p_addr && p_passwd && *p_passwd )
|
|
{
|
|
if( ftn_addrparse(&addr, p_addr, FALSE) == 0 )
|
|
{
|
|
dest->addr = addr;
|
|
dest->what = xstrcpy(p_passwd);
|
|
return(PROC_RC_OK);
|
|
}
|
|
else
|
|
{
|
|
log("can't parse address \"%s\"", value);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
}
|
|
|
|
log("incorrect password specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Path>
|
|
*/
|
|
static int proc_path(s_string *dest, char *value)
|
|
{
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
if( value[strlen(value)-1] == DIRSEPCHR )
|
|
dest->str = xstrcpy(value);
|
|
else
|
|
dest->str = string_concat(value, DIRSEPSTR, NULL);
|
|
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <<String1[:RC]> [String2[:RC]] ..>
|
|
*/
|
|
static int proc_dialresp(s_dialresp *dest, char *value)
|
|
{
|
|
int i;
|
|
char *n = NULL;
|
|
char *p_mstr = NULL;
|
|
char *p_type = NULL;
|
|
char *p_retv = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_mstr = string_token(value, &n, NULL, 1);
|
|
p_type = string_token(NULL, &n, NULL, 1);
|
|
p_retv = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_mstr && *p_mstr && p_type && *p_type )
|
|
{
|
|
if( p_retv && !ISDEC(p_retv) )
|
|
{
|
|
log("return code isn't numeric in modem response specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
for( i = 0; resptypes[i].str; i++ )
|
|
if( strcasecmp(p_type, resptypes[i].str) == 0 )
|
|
break;
|
|
|
|
if( resptypes[i].str )
|
|
{
|
|
dest->mstr = xstrcpy(p_mstr);
|
|
dest->type = resptypes[i].value;
|
|
dest->retv = p_retv ? atoi(p_retv) : resptypes[i].retv;
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
log("unknown response type \"%s\"", p_type);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
log("incorrect modem response specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Search value> <Replace value>
|
|
*/
|
|
static int proc_translate(s_translate *dest, char *value)
|
|
{
|
|
char *n = NULL;
|
|
char *p_find = NULL;
|
|
char *p_repl = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_find = string_token(value, &n, NULL, 1);
|
|
p_repl = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_find && *p_find )
|
|
{
|
|
dest->find = xstrcpy(p_find);
|
|
if( p_repl )
|
|
dest->repl = xstrcpy(p_repl);
|
|
return(PROC_RC_OK);
|
|
}
|
|
|
|
log("incorrect translation rule specification");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Connect speed> <Number>
|
|
*/
|
|
static int proc_speeddep(s_connlist *dest, char *value)
|
|
{
|
|
char *n = NULL;
|
|
char *p_speed = NULL;
|
|
char *p_value = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_speed = string_token(value, &n, NULL, 1);
|
|
p_value = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_speed && *p_speed && p_value && *p_value )
|
|
{
|
|
if( ISDEC(p_speed) && ISDEC(p_value) )
|
|
{
|
|
dest->speed = atoi(p_speed);
|
|
dest->value = atoi(p_value);
|
|
return(PROC_RC_OK);
|
|
}
|
|
log("non-numeric value \"%s\" or \"%s\"", p_speed, p_value);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
log("incorrect speed dependent config string");
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: <Keyword> <Tries number> [<Action> <Action argument(s)>]
|
|
*/
|
|
static int proc_tries(s_tries *dest, char *value)
|
|
{
|
|
int rc = PROC_RC_OK;
|
|
char *n = NULL;
|
|
char *p_tries = NULL;
|
|
char *p_action = NULL;
|
|
char *p_arg = NULL;
|
|
int action = TRIES_ACTION_UNDIALABLE;
|
|
int arg = 0;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_tries = string_token(value, &n, NULL, 0);
|
|
p_action = string_token(NULL, &n, NULL, 0);
|
|
p_arg = string_token(NULL, &n, NULL, 0);
|
|
|
|
if( p_tries && *p_tries && ISDEC(p_tries) )
|
|
{
|
|
if( p_action && *p_action )
|
|
{
|
|
if( strcasecmp(p_action, "undialable") == 0 )
|
|
{
|
|
if( p_arg && *p_arg )
|
|
{
|
|
log("no argument needed for action 'undialable'");
|
|
rc = PROC_RC_WARN;
|
|
}
|
|
action = TRIES_ACTION_UNDIALABLE;
|
|
arg = 0;
|
|
}
|
|
else if( strcasecmp(p_action, "hold") == 0 )
|
|
{
|
|
if( p_arg && *p_arg && !ISDEC(p_arg) )
|
|
{
|
|
log("non-numeric argument for action 'hold'");
|
|
return PROC_RC_IGNORE;
|
|
}
|
|
else if( p_arg == NULL )
|
|
{
|
|
log("no argument for action 'hold'");
|
|
return PROC_RC_IGNORE;
|
|
}
|
|
action = TRIES_ACTION_HOLDSYSTEM;
|
|
arg = atoi(p_arg);
|
|
}
|
|
else if( strcasecmp(p_action, "holdall") == 0 )
|
|
{
|
|
if( p_arg && *p_arg && !ISDEC(p_arg) )
|
|
{
|
|
log("non-numeric argument for action 'holdall'");
|
|
return PROC_RC_IGNORE;
|
|
}
|
|
else if( p_arg == NULL )
|
|
{
|
|
log("no argument for action 'holdall'");
|
|
return PROC_RC_IGNORE;
|
|
}
|
|
action = TRIES_ACTION_HOLDALL;
|
|
arg = atoi(p_arg);
|
|
}
|
|
else
|
|
{
|
|
log("unknown action '%s'", p_action);
|
|
return PROC_RC_IGNORE;
|
|
}
|
|
}
|
|
dest->tries = atoi(p_tries);
|
|
dest->action = action;
|
|
dest->arg = arg;
|
|
return(rc);
|
|
}
|
|
|
|
log("non-numeric tries number \"%s\"", p_tries);
|
|
return(PROC_RC_IGNORE);
|
|
}
|
|
|
|
/*
|
|
* Line format: DebugLevel <Level> [<Level>]..
|
|
*/
|
|
#ifdef DEBUG
|
|
static int proc_debuglevel(s_number *dest, char *value)
|
|
{
|
|
int rc = PROC_RC_OK;
|
|
long deblevel = 0L;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
if( debug_parsestring(value, &deblevel) ) rc = PROC_RC_WARN;
|
|
|
|
dest->num = deblevel;
|
|
|
|
return(rc);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Line format: <Keyword> <Directory> <Address>
|
|
*/
|
|
static int proc_filebox(s_filebox *dest, char *value)
|
|
{
|
|
s_faddr addr;
|
|
char *n = NULL;
|
|
char *p_path = NULL;
|
|
char *p_addr = NULL;
|
|
char *p_flav = NULL;
|
|
|
|
ASSERT(dest != NULL && value != NULL);
|
|
|
|
p_path = string_token(value, &n, NULL, 1);
|
|
p_addr = string_token(NULL, &n, NULL, 1);
|
|
p_flav = string_token(NULL, &n, NULL, 1);
|
|
|
|
if( p_path && *p_path && p_addr && *p_addr )
|
|
{
|
|
if( ftn_addrparse(&addr, p_addr, TRUE) == 0 )
|
|
{
|
|
int flavor = FLAVOR_HOLD;
|
|
int rc = PROC_RC_OK;
|
|
|
|
if( !is_directory(p_path) )
|
|
{
|
|
log("filebox directory \"%s\" doesn't exist", p_path);
|
|
rc = PROC_RC_WARN;
|
|
}
|
|
if( p_flav && *p_flav )
|
|
{
|
|
if( strcasecmp(p_flav, "hold") == 0 )
|
|
flavor = FLAVOR_HOLD;
|
|
else if( strcasecmp(p_flav, "normal") == 0 )
|
|
flavor = FLAVOR_NORMAL;
|
|
else if( strcasecmp(p_flav, "crash") == 0 )
|
|
flavor = FLAVOR_CRASH;
|
|
else if( strcasecmp(p_flav, "immediate") == 0 )
|
|
flavor = FLAVOR_IMMED;
|
|
else
|
|
{
|
|
log("unknown filebox flavor \"%s\"", p_flav);
|
|
rc = PROC_RC_WARN;
|
|
}
|
|
}
|
|
dest->addr = addr;
|
|
if( p_path[strlen(p_path)-1] == DIRSEPCHR )
|
|
dest->path = xstrcpy(p_path);
|
|
else
|
|
dest->path = string_concat(p_path, DIRSEPSTR, NULL);
|
|
dest->flavor = flavor;
|
|
return rc;
|
|
}
|
|
else
|
|
{
|
|
log("can't parse address \"%s\"", p_addr);
|
|
return PROC_RC_IGNORE;
|
|
}
|
|
}
|
|
|
|
log("incorrect filebox specification");
|
|
return PROC_RC_IGNORE;
|
|
}
|