Newer
Older
/* FidoNet configuration utility */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* 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. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
/* Portions written by Allen Christiansen 1994-1996 */
/* XPDEV Headers */
#include "gen_defs.h"
#define __COLORS
#include "ciolib.h"
#include "ciolib.h"
#include "sbbsecho.h"
#include "sockwrap.h"
#include "str_util.h"
#include "getctrl.h"
#include "git_branch.h"
#include "git_hash.h"
sbbsecho_cfg_t cfg;
uifcapi_t uifc;
int ciolib_mode = CIOLIB_MODE_AUTO;
enum text_modes video_mode = LCD80X25;
uifc.bail();

rswindell
committed
/* These correlate with the LOG_* definitions in syslog.h/gen_defs.h */
= {"Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debugging", NULL};
#define PACKET_TYPE_HELP_TEXT \
"`Type-2 ` packets are defined in FTS-0001.16 (Stone Age)\n" \
"`Type-2e ` packets are defined in FSC-0039.04 (Sometimes called 2+)\n" \
"`Type-2+ ` packets are defined in FSC-0048.02 (4D address support)\n" \
"`Type-2.2` packets are defined in FSC-0045.01 (5D address support)\n" \
while (1) {
int i = 0;
sprintf(opt[i++], "%-30s %s", "Mailer Type"
, cfg.flo_mailer ? "Binkley/FLO":"ArcMail/Attach");
sprintf(opt[i++], "%-30s %s", "Log Level", logLevelStringList[cfg.log_level]);
sprintf(opt[i++], "%-30s %s", "Log Timestamp Format", cfg.logtime);
if (cfg.max_log_size) {
SAFEPRINTF2(str, "%s bytes, keep %lu"
, byte_count_to_str(cfg.max_log_size, tmp, sizeof(tmp))
, cfg.max_logs_kept);
} else {
SAFECOPY(str, "Unlimited");
}
sprintf(opt[i++], "%-30s %s", "Maximum Log File Size", str);
sprintf(opt[i++], "%-30s %s", "Strict Packet Passwords", cfg.strict_packet_passwords ? "Enabled" : "Disabled");
sprintf(opt[i++], "%-30s %u", "Config File Backups", cfg.cfgfile_backups);
sprintf(opt[i++], "%-30s %s bytes", "Minimum Free Disk Space"
, byte_count_to_str(cfg.min_free_diskspace, str, sizeof(str)));
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %-3.3s", "Strip Incoming Soft CRs "
, cfg.strip_soft_cr ? "Yes":"No");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %-3.3s", "Strip Outgoing Line Feeds "
, cfg.strip_lf ? "Yes":"No");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %-3.3s", "Auto-detect UTF-8 Messages "
, cfg.auto_utf8 ? "Yes":"No");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %-3.3s", "Use Outboxes for Mail Files "
, cfg.use_outboxes ? "Yes":"No");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %-3.3s", "Sort Linked Node List "
, cfg.sort_nodelist ? "Yes":"No");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %-3.3s", "Delete Processed Packets"
, cfg.delete_packets ? "Yes":"No");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %s", "Incoming Bad Packets"
, cfg.delete_bad_packets ? "Deleted" : cfg.verbose_bad_packet_names ? "Renamed *.reason.bad" : "Renamed *.bad");
snprintf(opt[i++], MAX_OPLN - 1, "%-30s %s", "Default Packet Type", pktTypeStringList[cfg.default_packet_type]);
sprintf(opt[i++], "%-30s %s", "BSY Mutex File Timeout", duration_to_vstr(cfg.bsy_timeout, duration, sizeof(duration)));
sprintf(opt[i++], "%-30s %s", "BSO Lock Attempt Delay", duration_to_vstr(cfg.bso_lock_delay, duration, sizeof(duration)));
sprintf(opt[i++], "%-30s %lu", "BSO Lock Attempt Limit", cfg.bso_lock_attempts);
sprintf(opt[i++], "%-30s %s", "BinkP Capabilities", cfg.binkp_caps);
sprintf(opt[i++], "%-30s %s", "BinkP Sysop Name", cfg.binkp_sysop);
sprintf(opt[i++], "%-30s %s", "BinkP Authentication", cfg.binkp_plainAuthOnly ? "Plain Only" : "Plain or CRAM-MD5");
sprintf(opt[i++], "%-30s %s", "BinkP Encryption", !cfg.binkp_plainTextOnly && !cfg.binkp_plainAuthOnly ? "Supported" : "Unsupported");
}
"~ Global Settings ~\n"
"\n"
"`Mailer Type` should normally be set to `Binkley/FLO` to enable SBBSecho's\n"
" \"Binkley-Style Outbound\" operating mode (a.k.a. `BSO` or `FLO` mode).\n"
" If you are using an `Attach`, `ArcMail`, or `FrontDoor` style FidoNet\n"
" mailer, then set this setting to `ArcMail/Attach`, but know that most\n"
" modern FidoNet mailers are Binkley-Style and therefore that mode of\n"
" operation in SBBSecho is much more widely tested and supported.\n"
"\n"
"`Log Level` should normally be set to `Informational` but if you're\n"
" experiencing problems with SBBSecho and would like more verbose log\n"
" output, set this to `Debugging`. If you want less verbose logging,\n"
" set to higher-severity levels to reduce the number of log messages.\n"
"\n"
"`Log Timestamp Format` defines the format of the date/time-stamps added\n"
" along with each log message to the log file (e.g. sbbsecho.log).\n"
" The timestamp format is defined using standard C `strftime` notation.\n"
" The default format is: `" DEFAULT_LOG_TIME_FMT "`\n"
" For SBBSecho v2 timestamp format, use `%m/%d/%y %H:%M:%S`\n"
"\n"
"`Strict Packet Passwords`, when enabled, requires that Packet Passwords\n"
" must match the password for the linked node from which the packet\n"
" was received, even if that linked node has no password configured.\n"
" If you wish to revert to the SBBSecho v2 behavior with less strict\n"
" enforcement of matching packet passwords, disable this option.\n"
" Default: Enabled\n"
"\n"
"`Config File Backups` determines the number of automatic backups of your\n"
" SBBSecho configuration file (e.g. `sbbsecho.ini`) that will be\n"
" maintained by FidoNet Config (`echocfg`) and SBBSecho AreaManager.\n"
"\n"
"`Minimum Free Disk Space` determines the minimum amount of free disk\n"
" space for SBBSecho to run. SBBSecho will just exit with an error\n"
" message (and an error level of 1) if the minimum amount of free\n"
" space is not found in directories into which SBBSecho may write.\n"
"\n"
"`Strip Incoming Soft CRs` instructs SBBSecho to remove any \"Soft\"\n"
" Carriage Return (ASCII 141) characters from the text of `imported`\n"
" EchoMail and NetMail messages.\n"
"\n"
"`Strip Outgoing Line Feeds` instructs SBBSecho to remove any Line Feed\n"
" (ASCII 10) characters from the body text of `exported` EchoMail and\n"
" NetMail messages.\n"
"\n"
"`Auto-detect UTF-8 Messages` instructs SBBSecho to treat incoming\n"
" messages which lack a CHRS/CHARSET control line and contain valid\n"
" UTF-8 character sequences in the message text, as UTF-8 encoded\n"
" messages.\n"
"\n"
"`Use Outboxes for Mail Files` instructs SBBSecho to place outbound\n"
" NetMail and EchoMail files into the configured `Outbox Directory`\n"
" of the relevant linked node. If the linked node has no configured\n"
" outbox, then outbound mail files for that node are placed in the\n"
" normal outbound directory hierarchy. The BinkIT mailer will\n"
" send files from configured outboxes in addition to the normal\n"
" outbound directories, even when this option is set to `No`.\n"
"\n"
"`Sort Linked Node List` instructs SBBSecho to sort the list of linked\n"
" nodes (in sbbsecho.ini) both when reading and writing the file.\n"
"\n"
"`Delete Processed Packets` instructs SBBSecho to delete packet files\n"
" after they've been imported (as one would normally expect).\n"
"\n"
"`Incoming Bad Packets` can be `Deleted` or `Renamed` (*.bad) and optionally\n"
" include the `reason` in the renamed packet filename (the default).\n"
"`Default Packet Type` is the type of packets that SBBSecho will generate\n"
" by default (i.e. for newly created and un-linked destination nodes).\n"
"\n"
"`BSY Mutex File Timeout` determines the maximum age of an existing\n"
" mutex file (`*.bsy`) before SBBSecho will act as though the mutex\n"
" file was not present. This setting applies to the global\n"
" `sbbsecho.bsy` file as well as the BSO lock (`*.bsy`) files for\n"
" individual nodes.\n"
" Default: 12 hours\n"
"\n"
"`BSO Lock Attempt Delay` determines the amount of time between BSO\n"
" node lock attempts (via `*.bsy` files in the relevant outbound\n"
" directory).\n"
" Default: 10 seconds\n"
"\n"
"`BSO Lock Attempt Limit` determines the maximum number of BSO node lock\n"
" attempts before SBBSecho will give-up and move on to another node\n"
" to process mail. This value multiplied by the `BSO Lock Attempt\n"
" Delay` should be much less than the `BSY Mutex File Timeout` value.\n"
" Default: 60 attempts\n"
"\n"
"`BinkP Capabilities` may be used to over-ride the default BinkP node\n"
" capabilities sent during a `BinkIT` mailer session (via the NDL\n"
" command). Default capabilities value is '115200,TCP,BINKP'\n"
"\n"
"`BinkP Sysop` may be used to over-ride the default BinkP sysop name\n"
" sent during a `BinkIT` mailer session (via the ZYZ command).\n"
" Default sysop name is that set in `SCFG->System->Operator`\n"
"\n"
"`BinkP Authentication` may be set to `Plain Only` if you wish to disable\n"
" CRAM-MD5 authentication for both inbound and outbound sessions.\n"
" Note: CRAM-MD5 authentication is required for encrypted sessions.\n"
" Default: Plain or CRAM-MD5\n"
"\n"
"`BinkP Encryption` may be set to `Supported` (the default) only when\n"
" BinkP Authentication is set to Plain or CRAM-MD5.\n"
" Default: Supported\n"
int key = uifc.list(WIN_ACT | WIN_SAV, 0, 0, 0, &global_opt, &global_bar, "Global Settings", opt);
case -1:
return;
case 0:
cfg.flo_mailer = !cfg.flo_mailer;
break;
case 1:
uifc.helpbuf =
"~ Log Level ~\n"
"\n"
"Select the minimum severity of log entries to be logged to the log file.\n"
"The default/normal setting is `Informational`.";
i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Log Level", logLevelStringList);
if (i >= 0 && i <= LOG_DEBUG)
cfg.log_level = i;
uifc.input(WIN_MID | WIN_SAV, 0, 0
, "Log Timestamp Format", cfg.logtime, sizeof(cfg.logtime) - 1, K_EDIT);
byte_count_to_str(cfg.max_log_size, str, sizeof(str));
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Maximum Log File Size (in bytes, 0=unlimited)", str, 10, K_EDIT | K_UPPER) > 0) {
cfg.max_log_size = parse_byte_count(str, 1);
if (cfg.max_log_size) {
SAFEPRINTF(str, "%lu", cfg.max_logs_kept);
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Maximum Number of old Log Files to Keep", str, 5, K_EDIT | K_NUMBER) > 0)
cfg.max_logs_kept = strtoul(str, NULL, 10);
}
}
cfg.strict_packet_passwords = !cfg.strict_packet_passwords;
break;
case 5:
sprintf(str, "%u", cfg.cfgfile_backups);
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Configuration File Backups", str, 5, K_EDIT | K_NUMBER) > 0)
cfg.cfgfile_backups = atoi(str);
break;
byte_count_to_str(cfg.min_free_diskspace, str, sizeof(str));
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Minimum Free Disk Space (in bytes)", str, 10, K_EDIT | K_UPPER) > 0)
cfg.min_free_diskspace = parse_byte_count(str, 1);
break;
{
int k = !cfg.strip_soft_cr;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Strip Soft Carriage Returns from Incoming Messages", uifcYesNoOpts)) {
case 0: cfg.strip_soft_cr = true; break;
case 1: cfg.strip_soft_cr = false; break;
}
break;
}
{
int k = !cfg.strip_lf;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Strip Line Feeds from Outgoing Messages", uifcYesNoOpts)) {
case 0: cfg.strip_lf = true; break;
case 1: cfg.strip_lf = false; break;
}
break;
}
{
int k = !cfg.auto_utf8;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Auto-detect incoming UTF-8 encoded messages", uifcYesNoOpts)) {
case 0: cfg.auto_utf8 = true; break;
case 1: cfg.auto_utf8 = false; break;
}
break;
}
{
int k = !cfg.use_outboxes;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Use Outboxes for Outbound NetMail and EchoMail", uifcYesNoOpts)) {
case 0: cfg.use_outboxes = true; break;
case 1: cfg.use_outboxes = false; break;
}
break;
}
{
int k = !cfg.sort_nodelist;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Sort List of Linked Nodes", uifcYesNoOpts)) {
case 0: cfg.sort_nodelist = true; break;
case 1: cfg.sort_nodelist = false; break;
}
break;
}
case 12:
{
int k = !cfg.delete_packets;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Delete Incoming Processed Packets (.pkt files)", uifcYesNoOpts)) {
case 0: cfg.delete_packets = true; break;
case 1: cfg.delete_packets = false; break;
}
break;
}
case 13:
{
int k = !cfg.delete_bad_packets;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Delete Bad Incoming Packets (.pkt files) When Detected", uifcYesNoOpts)) {
case 0: cfg.delete_bad_packets = true;
case 1: cfg.delete_bad_packets = false;
int k = !cfg.verbose_bad_packet_names;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Include Reason in Renamed Bad Packet Filenames", uifcYesNoOpts)) {
case 0: cfg.verbose_bad_packet_names = true; break;
case 1: cfg.verbose_bad_packet_names = false; break;
}
break;
}
case 14:
"~ Default Packet Type ~\n\n"
"This is the packet header type that will be used in mail packets\n"
"by default (for newly created and un-linked nodes).\n"
"\n"
PACKET_TYPE_HELP_TEXT
"\n"
"The suggested default packet type is `Type-2+`.\n"
;
int k = cfg.default_packet_type;
k = uifc.list(WIN_RHT | WIN_SAV, 0, 0, 0, &k, 0, "Packet Type", pktTypeStringList);
if (k < 0)
cfg.default_packet_type = k;
uifc.changes = TRUE;
duration_to_vstr(cfg.bsy_timeout, duration, sizeof(duration));
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "BSY Mutex File Timeout", duration, 10, K_EDIT) > 0)
cfg.bsy_timeout = (ulong)parse_duration(duration);
break;
duration_to_vstr(cfg.bso_lock_delay, duration, sizeof(duration));
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Delay Between BSO Lock Attempts", duration, 10, K_EDIT) > 0)
cfg.bso_lock_delay = (ulong)parse_duration(duration);
break;
sprintf(str, "%lu", cfg.bso_lock_attempts);
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Maximum BSO Lock Attempts", str, 5, K_EDIT | K_NUMBER) > 0)
uifc.input(WIN_MID | WIN_SAV, 0, 0
, "BinkP Capabilities (BinkIT)", cfg.binkp_caps, sizeof(cfg.binkp_caps) - 1, K_EDIT);
break;
uifc.input(WIN_MID | WIN_SAV, 0, 0
, "BinkP Sysop Name (BinkIT)", cfg.binkp_sysop, sizeof(cfg.binkp_sysop) - 1, K_EDIT);
break;
{
int k = !cfg.binkp_plainAuthOnly;
strcpy(opt[0], "Plain-Password Only");
strcpy(opt[1], "Plain-Password or CRAM-MD5");
opt[2][0] = 0;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "BinkP Authentication", opt)) {
case 0:
cfg.binkp_plainAuthOnly = true;
break;
case 1:
cfg.binkp_plainAuthOnly = false;
break;
}
break;
}
if (cfg.binkp_plainAuthOnly) {
uifc.msg("CRAM-MD5 authentication/encryption has been disabled globally");
break;
}
int k = cfg.binkp_plainTextOnly;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "BinkP Encryption Supported", uifcYesNoOpts)) {
case 0:
cfg.binkp_plainTextOnly = false;
break;
case 1:
cfg.binkp_plainTextOnly = true;
break;
}
break;
}
static bool new_node(unsigned new_nodenum)
{
nodecfg_t* nodecfg = realloc(cfg.nodecfg, sizeof(nodecfg_t) * (cfg.nodecfgs + 1));
return false;
cfg.nodecfg = nodecfg;
for (unsigned int i = cfg.nodecfgs; i > new_nodenum; i--)
memcpy(&cfg.nodecfg[i], &cfg.nodecfg[i - 1], sizeof(nodecfg_t));
cfg.nodecfgs++;
memset(&cfg.nodecfg[new_nodenum], 0, sizeof(nodecfg_t));
cfg.nodecfg[new_nodenum].binkp_allowPlainText = true;
cfg.nodecfg[new_nodenum].binkp_port = IPPORT_BINKP;
cfg.nodecfg[new_nodenum].pkt_type = cfg.default_packet_type;
return true;
}
static bool new_arcdef(unsigned new_arcnum)
{
arcdef_t * arcdef = realloc(cfg.arcdef, sizeof(arcdef_t) * (cfg.arcdefs + 1));
return false;
cfg.arcdef = arcdef;
for (unsigned j = cfg.arcdefs; j > new_arcnum; j--)
memcpy(&cfg.arcdef[j], &cfg.arcdef[j - 1], sizeof(arcdef_t));
cfg.arcdefs++;
memset(&cfg.arcdef[new_arcnum], 0, sizeof(arcdef_t));
return true;
}
static bool new_list(unsigned new_listnum)
{
echolist_t *listcfg = realloc(cfg.listcfg, sizeof(echolist_t) * (cfg.listcfgs + 1));
return false;
cfg.listcfg = listcfg;
for (unsigned j = cfg.listcfgs; j > new_listnum; j--)
memcpy(&cfg.listcfg[j], &cfg.listcfg[j - 1], sizeof(echolist_t));
cfg.listcfgs++;
memset(&cfg.listcfg[new_listnum], 0, sizeof(echolist_t));
return true;
}
static bool new_domain(unsigned new_domnum)
{
struct fido_domain* new_list = realloc(cfg.domain_list, sizeof(struct fido_domain) * (cfg.domain_count + 1));
return false;
cfg.domain_list = new_list;
for (unsigned i = cfg.domain_count; i > new_domnum; i--)
memcpy(&cfg.domain_list[i], &cfg.domain_list[i - 1], sizeof(struct fido_domain));
cfg.domain_count++;
memset(&cfg.domain_list[new_domnum], 0, sizeof(struct fido_domain));
return true;
}
static bool new_robot(unsigned new_botnum)
{
struct robot* new_list = realloc(cfg.robot_list, sizeof(struct robot) * (cfg.robot_count + 1));
return false;
cfg.robot_list = new_list;
for (unsigned i = cfg.robot_count; i > new_botnum; i--)
memcpy(&cfg.robot_list[i], &cfg.robot_list[i - 1], sizeof(struct robot));
cfg.robot_count++;
memset(&cfg.robot_list[new_botnum], 0, sizeof(struct robot));
return true;
}
static char* int_list(int* list, unsigned count)
{
static char str[128];
str[0] = 0;
for (unsigned i = 0; i < count; i++) {
if (i)
sprintf(str + strlen(str), ",%d", *(list + i));
else
sprintf(str, "%d", *list);
}
return str;
}
void binkp_settings(nodecfg_t* node)
{
while (1) {
char str[128];
int i = 0;
sprintf(opt[i++], "%-20s %s", "Host", node->binkp_host);
sprintf(opt[i++], "%-20s %u", "Port", node->binkp_port);
sprintf(opt[i++], "%-20s %s", "Poll", node->binkp_poll ? "Yes" : "No");
char* auth = "Plain Only";
char* crypt = "Unsupported";
if (!cfg.binkp_plainAuthOnly && !node->binkp_plainAuthOnly) {
if (!cfg.binkp_plainTextOnly)
crypt = node->binkp_allowPlainText ? "Supported" : "Required";
if (node->binkp_allowPlainAuth)
auth = "Plain or CRAM-MD5";
else
auth = "CRAM-MD5 Only";
}
sprintf(opt[i++], "%-20s %s", "Authentication", auth);
sprintf(opt[i++], "%-20s %s", "Encryption", crypt);
sprintf(opt[i++], "%-20s %s", "Implicit TLS", node->binkp_tls ? "Yes" : "No");
sprintf(opt[i++], "%-20s %s", "Source Address", node->binkp_src);
char title[128];
SAFEPRINTF(title, "%s BinkP Settings", faddrtoa(&node->addr));
"~ BinkP Settings ~\n"
"\nThese settings are used by the Synchronet `BinkIT` BinkP/BSO mailer.\n"
"\n"
"`Host` defines the TCP/IP address or host name with which to connect for\n"
" sessions with this linked node. If the host is not set, then a\n"
" DNS-based look-up will be attempted (e.g. the IP address for\n"
" `1:103/705` would be looked-up via host name `f705.n103.z1.binkp.net`).\n"
" Nodelist-based look-ups are also supported.\n"
"\n"
"`Port` defines the TCP port used by this linked node for BinkP sessions.\n"
" The default BinkP TCP port is `24554`.\n"
"\n"
"`Poll` defines whether or not to periodically poll this linked node.\n"
"\n"
"`Authentication` determines what types of authentication will be supported\n"
" during both inbound and outbound sessions with this linked node.\n"
" The supported BinkP-auth methods are `Plain-Password` and `CRAM-MD5`.\n"
" Note: For `incoming` connections, CRAM-MD5 will be supported unless\n"
" CRAM-MD5 authentication has been `globally` disabled.\n"
"\n"
"`Encryption` determines whether unencrypted data transfers will be\n"
" supported or required when communicating with this linked node.\n"
" With this setting set to `Required`, ~only~ BinkD-style-encrypted BinkP\n"
" sessions will be supported.\n"
" CRAM-MD5 authentication `must` be used when encrypting BinkP sessions.\n"
"\n"
"`Implicit TLS` defines whether or not to use `BINKPS` when connecting\n"
" (outbound) with this linked node.\n"
"\n"
"`Source Address` allows you to override the source FTN address used\n"
" with outgoing BinkP mailer sessions with this linked node.\n"
" Normally, this setting is left blank (not set).\n"
;
int k = uifc.list(WIN_RHT | WIN_BOT | WIN_SAV | WIN_ACT, 0, 0, 0, &cur, 0, title, opt);
if (k < 0)
break;
case 0:
uifc.input(WIN_MID | WIN_SAV, 0, 0
, "Host name or IP address", node->binkp_host, sizeof(node->binkp_host) - 1, K_EDIT);
break;
case 1:
sprintf(str, "%u", node->binkp_port);
if (uifc.input(WIN_MID | WIN_SAV, 0, 0
, "TCP Port Number (e.g. 24554)", str, 5, K_EDIT | K_NUMBER) > 0) {
node->binkp_port = atoi(str);
uifc.changes = TRUE;
}
break;
case 2:
k = !node->binkp_poll;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Poll This Node Periodically for Inbound Files/Mail", uifcYesNoOpts)) {
case 0: node->binkp_poll = true; uifc.changes = TRUE; break;
case 1: node->binkp_poll = false; uifc.changes = TRUE; break;
}
break;
case 3:
if (cfg.binkp_plainAuthOnly) {
uifc.msg("CRAM-MD5 authentication/ has been disabled globally");
break;
}
k = node->binkp_plainAuthOnly ? 0 : (1 + !node->binkp_allowPlainAuth);
strcpy(opt[0], "Plain-Password Only");
strcpy(opt[1], "Plain-Password or CRAM-MD5");
strcpy(opt[2], "CRAM-MD5 Only");
opt[3][0] = 0;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Authentication", opt)) {
case 0:
node->binkp_plainAuthOnly = true;
node->binkp_allowPlainAuth = true;
node->binkp_allowPlainText = true;
break;
case 1:
node->binkp_allowPlainAuth = true;
node->binkp_plainAuthOnly = false;
node->binkp_allowPlainText = true;
break;
case 2:
node->binkp_allowPlainAuth = false;
node->binkp_plainAuthOnly = false;
break;
}
break;
case 4:
if (cfg.binkp_plainTextOnly) {
uifc.msg("BinkP encryption has been disabled globally");
break;
}
if (cfg.binkp_plainAuthOnly) {
uifc.msg("CRAM-MD5 authentication/encryption has been disabled globally");
break;
}
k = !node->binkp_allowPlainText;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Allow Plain-Text (Unencrypted) Sessions", uifcYesNoOpts)) {
case 0:
node->binkp_allowPlainText = true;
node->binkp_allowPlainAuth = true;
break;
case 1:
node->binkp_allowPlainText = false;
node->binkp_allowPlainAuth = false;
node->binkp_plainAuthOnly = false;
break;
}
break;
case 5:
k = !node->binkp_tls;
switch (uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &k, 0
, "Use BINKPS (Implicit TLS) Connections with This Node", uifcYesNoOpts)) {
case 0: node->binkp_tls = true; uifc.changes = TRUE; break;
case 1: node->binkp_tls = false; uifc.changes = TRUE; break;
}
break;
case 6:
uifc.helpbuf =
"~ Source Address ~\n\n"
"This is the FidoNet style address to use as the source address when\n"
"conducting BinkP sessions with this linked node.";
uifc.input(WIN_MID | WIN_SAV, 0, 0
, "Source Node Address (optional)"
, node->binkp_src
, sizeof(node->binkp_src) - 1, K_EDIT);
break;
}
}
}
#ifdef _WIN32
#define printf cprintf
#endif
void banner()
{
DESCRIBE_COMPILER(compiler);
printf("\nSynchronet FidoNet Configuration Version %u.%02u " COPYRIGHT_NOTICE
"\n\n", SBBSECHO_VERSION_MAJOR, SBBSECHO_VERSION_MINOR);
printf("Compiled %s/%s %s with %s\n", GIT_BRANCH, GIT_HASH, GIT_DATE, compiler);
void read_echocfg_ini()
{
char path[MAX_PATH + 1];
snprintf(path, sizeof path, "%s/echocfg.ini", get_ctrl_dir(/* warn: */ false));
if (!fexist(path))
snprintf(path, sizeof path, "%s/uifc.ini", get_ctrl_dir(/* warn: */ false));
read_uifc_ini(path, &uifc, &ciolib_mode, &video_mode);
}
int main(int argc, char **argv)
{
char str[256], *p;
int i, j, k, x, dflt, nodeop = 0, nodeopbar = 0, packop = 0, listop = 0;
echolist_t savlistcfg;
nodecfg_t savnodecfg;
arcdef_t savarcdef;
struct fido_domain savedomain;
struct robot saverobot = {
BOOL door_mode = FALSE;
unsigned int u;
char sysop_aliases[256];
sbbsecho_cfg_t orig_cfg;
ZERO_VAR(savlistcfg);
ZERO_VAR(savnodecfg);
ZERO_VAR(savarcdef);
ZERO_VAR(savedomain);
#if defined(_WIN32)
cio_api.options |= CONIO_OPT_DISABLE_CLOSE;
#else
banner();
#endif
read_echocfg_ini();
memset(&cfg, 0, sizeof(cfg));
str[0] = 0;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-insert") == 0) {

Rob Swindell
committed
uifc.insert_mode = TRUE;
continue;
}
if (argv[i][0] == '-')
switch (toupper(argv[i][1])) {
case 'D':
printf("NOTICE: The -d option is deprecated, use -id instead\n");
door_mode = TRUE;
break;
case 'L':
uifc.scrn_len = atoi(argv[i] + 2);
break;
case 'E':
uifc.esc_delay = atoi(argv[i] + 2);
break;
case 'I':
switch (toupper(argv[i][2])) {
ciolib_mode = CIOLIB_MODE_ANSI;
ciolib_mode = CIOLIB_MODE_CURSES;
printf("NOTICE: The -i option is deprecated, use -if instead\n");
ciolib_mode = CIOLIB_MODE_CURSES_IBM;
ciolib_mode = CIOLIB_MODE_CURSES_ASCII;
ciolib_mode = CIOLIB_MODE_X;
ciolib_mode = CIOLIB_MODE_CONIO;
case 'G':
switch (toupper(argv[i][3])) {
case 0:
case 'W':
ciolib_mode = CIOLIB_MODE_GDI;
break;
case 'F':
ciolib_mode = CIOLIB_MODE_GDI_FULLSCREEN;
break;
}
break;
#endif
door_mode = TRUE;
break;
case 'K': /* Keyboard-only mode (no mouse support) */
uifc.mode |= UIFC_NOMOUSE;
break;
case 'M': /* Monochrome mode */
uifc.mode |= UIFC_MONO;
break;
case 'C':
uifc.mode |= UIFC_COLOR;
break;
case 'V':
video_mode = atoi(argv[i] + 2);
break;
case 'S':
ciolib_initial_scaling = strtod(argv[i] + 2, NULL);
break;
uifc.size = sizeof(uifc);
uifc.mode |= UIFC_NOMOUSE;
initciolib(CIOLIB_MODE_CONIO);
uifcini32(&uifc);
banner();
#endif
printf("\nusage: echocfg [path/to/sbbsecho.ini] [options]"
"\n\noptions:\n\n"
"-k keyboard mode only (no mouse support)\n"
"-c force color mode\n"
"-m force monochrome mode\n"
"-e# set escape delay to #msec\n"
"-iX set interface mode to X (default=auto) where X is one of:\n"
" X = X11 mode\n"
" C = Curses mode\n"
" F = Curses mode with forced IBM charset\n"
" I = Curses mode with forced ASCII charset\n"
" W = Win32 console mode\n"
" G = Win32 graphics mode\n"
" GF = Win32 graphics mode, full screen\n"
" A = ANSI mode\n"
" D = standard input/output/door mode\n"
"-v# set video mode to # (default=%u)\n"
"-l# set window lines to # (default=auto-detect)\n"
"-s# set window scaling factor to # (default=1.0)\n"
, video_mode
);
#ifdef _WIN32
printf("\nHit a key to close...");
getch();
#undef printf
#endif
SAFECOPY(str, argv[i]);
if (str[0] == 0) {
SAFECOPY(cfg.cfgfile, get_ctrl_dir(/* warn: */ true));
backslash(cfg.cfgfile);
SAFECAT(cfg.cfgfile, "sbbsecho.ini");
} else {
SAFECOPY(cfg.cfgfile, str);
if (!sbbsecho_read_ini(&cfg)) {
fprintf(stderr, "ERROR %d (%s) reading %s\n", errno, strerror(errno), cfg.cfgfile);
exit(1);
}
orig_cfg = cfg;
if ((opt = (char **)malloc(sizeof(char *) * 1000)) == NULL) {
puts("memory allocation error\n");
for (i = 0; i < 1000; i++)
if ((opt[i] = (char *)malloc(MAX_OPLN + 1)) == NULL) {
puts("memory allocation error\n");
uifc.size = sizeof(uifc);
if (!door_mode) {
ciolib_initial_mode = video_mode;
i = initciolib(ciolib_mode);
if (i != 0) {
printf("ciolib library init returned error %d\n", i);
exit(1);
ciolib_settitle("Synchronet FidoNet Configuration");
i = uifcini32(&uifc); /* curses/conio/X/ANSI */
i = uifcinix(&uifc); /* stdio */
if (i != 0) {
printf("uifc library init returned error %d\n", i);
exit(1);
}
sprintf(str, "Synchronet FidoNet Config v%u.%02u", SBBSECHO_VERSION_MAJOR, SBBSECHO_VERSION_MINOR);
p = cfg.cfgfile;
if (strlen(p) + strlen(str) + 4 > uifc.scrn_width)
p = getfname(cfg.cfgfile);
uifc.printf(uifc.scrn_width - (strlen(p) + 1), 1, uifc.bclr | (uifc.cclr << 4), p);
if (cfg.used_include && uifc.deny("%s uses !include, continue read only", getfname(p))) {
uifc.pop("Exiting");
uifc.bail();
exit(0);
}
/* Remember current menu item selections using these vars: */
int netmail_opt = 0;
int echomail_opt = 0;
int path_opt = 0;
int node_opt = 0;
int node_bar = 0;
int domain_opt = 0;
int robot_opt = 0;
int robot_bar = 0;
dflt = 0;
while (1) {
if (memcmp(&cfg, &orig_cfg, sizeof(cfg)) != 0)
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
uifc.helpbuf =
"~ FidoNet Configuration ~\n\n"
"This program allows you to easily configure the Synchronet BBS\n"
"FidoNet-style EchoMail program known as `SBBSecho` and the FidoNet/BinkP\n"
"mailer known as `BinkIT`. Alternatively, you may edit the configuration\n"
"file (e.g. `ctrl/sbbsecho.ini`) using an ASCII/plain-text editor.\n"
"\n"
"For detailed documentation, see `http://wiki.synchro.net/util:sbbsecho`\n"
" and `http://wiki.synchro.net/module:binkit`\n"
"\n"
"The `Global Settings` sub-menu is where FidoNet configuration settings\n"
"are located which are neither NetMail nor EchoMail specific, but more\n"
"general to the operation of the tosser (SBBSecho) and mailer (BinkIT).\n"
"\n"
"The `Linked Nodes` sub-menu is where you configure your FidoNet-style\n"
"links: other FidoNet-style nodes/systems you regularly connect with\n"
"to exchange mail/files.\n"
"\n"
"The `Archive Types` sub-menu is where you configure your archive\n"
"programs (a.k.a. \"packers\") used for the packing and unpacking of\n"
"EchoMail bundle files (usually in 'PKZIP' format).\n"
"\n"
"The `NetMail Settings` sub-menu is where you configure settings specific\n"
"to NetMail (private one-on-one networked mail).\n"
"\n"
"The `EchoMail Settings` sub-menu is where you configure settings specific\n"
"to EchoMail (public group discussions in topical message areas, echoes).\n"
"\n"
"The `Paths and Filenames` sub-menu is where you configure your system's\n"
"directory and file paths used by SBBSecho.\n"
"\n"
"The `Robots` sub-menu is where NetMail Robots (e.g. TickFix) are\n"
"configured.\n"
"\n"
"The `Domains` sub-menu is where FidoNet-style domains (the '@domain'\n"
"of 5D FTN addresses) are mapped to zone numbers, DNS suffixes, NodeLists\n"
"and BSO root directories for use by the BinkIT mailer.\n"
"\n"
"The `EchoLists` sub-menu is for configuring additional (optional)\n"
"lists of FidoNet-style message areas (echoes) in `BACKBONE.NA` file\n"
"format. These lists, if configured, are used in addition to your main\n"
"`Area File` (e.g. areas.bbs) for advanced AreaManager/AreaFix operations."
;
i = 0;
sprintf(opt[i++], "Global Settings");
sprintf(opt[i++], "Linked Nodes");