diff --git a/src/sbbs3/echocfg.c b/src/sbbs3/echocfg.c
index 9a1337908f819842613ea277850485583f4b6fb8..a0bee7c38f3d35a57f71246705066beff1ce49b3 100644
--- a/src/sbbs3/echocfg.c
+++ b/src/sbbs3/echocfg.c
@@ -65,6 +65,144 @@ void bail(int code)
 static char* logLevelStringList[] 
 	= {"Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debugging", NULL};
 
+void global_settings(void)
+{
+	static int global_opt;
+
+	while(1) {
+		int i = 0;
+		char str[128];
+		char duration[64];
+		sprintf(opt[i++], "%-25s %s", "Mailer Type"
+			,cfg.flo_mailer ? "Binkley/FLO":"ArcMail/Attach");
+		sprintf(opt[i++], "%-25s %s", "Log Level", logLevelStringList[cfg.log_level]);
+		sprintf(opt[i++], "%-25s %s", "Log Timestamp Format", cfg.logtime);
+		sprintf(opt[i++], "%-25s %s", "Strict Packet Passwords", cfg.strict_packet_passwords ? "Enabled" : "Disabled");
+		sprintf(opt[i++], "%-25s %s", "Use FTN Domain/Zone Map", cfg.use_ftn_domains ? "Enabled" : "Disabled");
+		sprintf(opt[i++], "%-25s %s", "BSY Mutex File Timeout", duration_to_vstr(cfg.bsy_timeout, duration, sizeof(duration)));
+		sprintf(opt[i++], "%-25s %s", "BSO Lock Attempt Delay", duration_to_vstr(cfg.bso_lock_delay, duration, sizeof(duration)));
+		sprintf(opt[i++], "%-25s %u", "BSO Lock Attempt Limit", cfg.bso_lock_attempts);
+		sprintf(opt[i++], "%-25s %u", "Config File Backups", cfg.cfgfile_backups);
+		opt[i][0] = 0;
+		uifc.helpbuf=
+			"~ 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 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 Timestmap 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"
+			"`Use FTN Domain/Zone Map`, when enabled, uses the configuration file\n"
+			"    `ctrl/ftn_domains.ini` to determine the mapping between FTN domains\n"
+			"    and FTN zones and the relevant BSO outbound directory.\n"
+			"    Default: Disabled\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"
+			"`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 SBBSecho Config and SBBSecho AreaFix.\n"
+			;
+
+		int key = uifc.list(WIN_BOT|WIN_L2R|WIN_ACT|WIN_SAV, 0, 0, 0, &global_opt,0, "Global Settings", opt);
+
+		switch(key) {
+
+			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`.";
+				int i = cfg.log_level;
+				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;
+				break;
+
+			case 2:
+				uifc.input(WIN_MID|WIN_SAV,0,0
+					,"Log Timestamp Format", cfg.logtime, sizeof(cfg.logtime)-1, K_EDIT);
+				break;
+
+			case 3:
+				cfg.strict_packet_passwords = !cfg.strict_packet_passwords;
+				break;
+
+			case 4:
+				cfg.use_ftn_domains = !cfg.use_ftn_domains;
+				break;
+
+			case 5:
+				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;
+
+			case 6:
+				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;
+
+			case 7:
+				sprintf(str, "%u", cfg.bso_lock_attempts);
+				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum BSO Lock Attempts", str, 5, K_EDIT|K_NUMBER) > 0)
+					cfg.bso_lock_attempts = atoi(str);
+				break;
+
+			case 8:
+				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;
+		}
+	}
+}
+
 int main(int argc, char **argv)
 {
 	char str[256],*p;
@@ -91,7 +229,7 @@ int main(int argc, char **argv)
 		if(argv[i][0]=='-')
 			switch(toupper(argv[i][1])) {
                 case 'D':
-					printf("NOTICE: The -d option is deprecated, use -id instead\r\n");
+					printf("NOTICE: The -d option is deprecated, use -id instead\n");
 					SLEEP(2000);
                     door_mode=TRUE;
                     break;
@@ -110,7 +248,7 @@ int main(int argc, char **argv)
 							ciolib_mode=CIOLIB_MODE_CURSES;
 							break;
 						case 0:
-							printf("NOTICE: The -i option is deprecated, use -if instead\r\n");
+							printf("NOTICE: The -i option is deprecated, use -if instead\n");
 							SLEEP(2000);
 						case 'F':
 							ciolib_mode=CIOLIB_MODE_CURSES_IBM;
@@ -142,24 +280,24 @@ int main(int argc, char **argv)
                     break;
                 default:
 					USAGE:
-                    printf("\nusage: echocfg [path/to/sbbsecho.ini] [options]"
+                    printf("usage: echocfg [path/to/sbbsecho.ini] [options]"
                         "\n\noptions:\n\n"
-						"-k  =  keyboard mode only (no mouse support)\r\n"
-                        "-c  =  force color mode\r\n"
-						"-m  =  force monochrome mode\r\n"
-                        "-e# =  set escape delay to #msec\r\n"
-						"-iX =  set interface mode to X (default=auto) where X is one of:\r\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"
 #ifdef __unix__
-						"       X = X11 mode\r\n"
-						"       C = Curses mode\r\n"
-						"       F = Curses mode with forced IBM charset\r\n"
+						"       X = X11 mode\n"
+						"       C = Curses mode\n"
+						"       F = Curses mode with forced IBM charset\n"
 #else
-						"       W = Win32 native mode\r\n"
+						"       W = Win32 native mode\n"
 #endif
-						"       A = ANSI mode\r\n"
-						"       D = standard input/output/door mode\r\n"
-                        "-v# =  set video mode to # (default=auto)\r\n"
-                        "-l# =  set screen lines to # (default=auto-detect)\r\n"
+						"       A = ANSI mode\n"
+						"       D = standard input/output/door mode\n"
+                        "-v# =  set video mode to # (default=auto)\n"
+                        "-l# =  set screen lines to # (default=auto-detect)\n"
                         );
         			exit(0);
 		}
@@ -227,94 +365,79 @@ int main(int argc, char **argv)
 		p=getfname(cfg.cfgfile);
 	uifc.printf(uifc.scrn_width-(strlen(p)+1),1,uifc.bclr|(uifc.cclr<<4),p);
 
+	/* 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 archive_opt = 0;
+	int echolist_opt = 0;
 	dflt=0;
 	while(1) {
 		if(memcmp(&cfg, &orig_cfg, sizeof(cfg)) != 0)
 			uifc.changes = TRUE;
 		uifc.helpbuf=
-	"~ SBBSecho Configuration ~\r\n\r\n"
-	"This program allows you to easily configure the Synchronet BBS\r\n"
-	"FidoNet-style EchoMail program known as `SBBSecho`.  Alternatively, you\r\n"
-	"may edit the SBBSecho configuration file (e.g. `ctrl/sbbsecho.ini`) using\r\n"
-	"an ASCII/plain-text editor.\r\n"
-	"\r\n"
-	"For detailed documentation, see `http://wiki.synchro.net/util:sbbsecho`\r\n"
-	"\r\n"
-	"`Mailer Type` should normally be set to `Binkley/FLO` to enable SBBSecho's\r\n"
-	"\"Binkley-Style Outbound\" operating mode (a.k.a. `BSO` or `FLO` mode).\r\n"
-	"If you are using an `Attach`, `ArcMail`, or `FrontDoor` style FidoNet\r\n"
-	"mailer, then set this setting to `ArcMail/Attach`, but know that most\r\n"
-	"modern FidoNet mailers are Binkley-Style and therefore that mode of\r\n"
-	"operation in SBBSecho is more widely tested and supported.\r\n"
-	"\r\n"
-	"`Log Level` should normally be set to `Informational` but if you're\r\n"
-	"experiencing problems with SBBSecho and would like more verbose log\r\n"
-	"output, set this to `Debugging`. If you want less verbose logging,\r\n"
-	"set to higher-severity levels to reduce the number of log messages.\r\n"
-	"\r\n"
-	"The `Linked Nodes` sub-menu is where you configure your FidoNet-style\r\n"
-	"links: other FidoNet-style nodes/systems you directly connect with.\r\n"
-	"\r\n"
-	"The `Archive Types` sub-menu is where you configure your archive\r\n"
-	"programs (a.k.a. \"packers\") used for the packing and unpacking of\r\n"
-	"EchoMail bundle files (usually in 'zip' format).\r\n"
-	"\r\n"
-	"The `NetMail Settings` sub-menu is where you configure NetMail-specific\r\n"
-	"settings.\r\n"
-	"\r\n"
-	"The `EchoMail Settings` sub-menu is where you configure EchoMail-specific\r\n"
-	"settings.\r\n"
-	"\r\n"
-	"The `Paths and Filenames` sub-menu is where you configure your system's\r\n"
-	"directory and file paths used by SBBSecho.\r\n"
-	"\r\n"
-	"The `Additional EchoLists` sub-menu is for configuring additional\r\n"
-	"(optional) lists of FidoNet-style message areas in `BACKBONE.NA` format.\r\n"
-	"These lists, if configured, are used in addition to your main\r\n"
+	"~ SBBSecho Configuration ~\n\n"
+	"This program allows you to easily configure the Synchronet BBS\n"
+	"FidoNet-style EchoMail program known as `SBBSecho`.  Alternatively, you\n"
+	"may edit the SBBSecho configuration file (e.g. `ctrl/sbbsecho.ini`) using\n"
+	"an ASCII/plain-text editor.\n"
+	"\n"
+	"For detailed documentation, see `http://wiki.synchro.net/util:sbbsecho`\n"
+	"\n"
+	"The `Global Settings` sub-menu is where SBBSecho configuration settings\n"
+	"are located which are neither NetMail nor EchoMail specific, but more\n"
+	"general to the operation of SBBSecho.\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 'zip' 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 `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 AreaFix/AreaMgr operations."
 	;
 		i=0;
-		sprintf(opt[i++],"%-25s %s","Mailer Type"
-			,cfg.flo_mailer ? "Binkley/FLO":"ArcMail/Attach");
-		sprintf(opt[i++],"%-25s %s","Log Level",logLevelStringList[cfg.log_level]);
+		sprintf(opt[i++],"Global Settings...");
 		sprintf(opt[i++],"Linked Nodes...");
 		sprintf(opt[i++],"Archive Types...");
 		sprintf(opt[i++],"NetMail Settings...");
 		sprintf(opt[i++],"EchoMail Settings...");
 		sprintf(opt[i++],"Paths and Filenames...");
-		sprintf(opt[i++],"Additional EchoLists...");
+		sprintf(opt[i++],"EchoLists...");
 		if(uifc.changes)
 			snprintf(opt[i++],MAX_OPLN-1,"Save Changes to %s", getfname(cfg.cfgfile));
 		opt[i][0]=0;
-		switch(uifc.list(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,45,&dflt,0
+		switch(uifc.list(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,0,&dflt,0
 			,"Configure SBBSecho",opt)) {
 
 			case 0:
-				cfg.flo_mailer = !cfg.flo_mailer;
+				global_settings();
 				break;
 
 			case 1:
-	uifc.helpbuf=
-	"~ Log Level ~\r\n"
-	"\r\n"
-	"Select the minimum severity of log entries to be logged to the log file.\r\n"
-	"The default/normal setting is `Informational`.";
-				j=cfg.log_level;
-				i=uifc.list(WIN_MID,0,0,0,&j,0,"Log Level",logLevelStringList);
-				if(i>=0 && i<=LOG_DEBUG)
-					cfg.log_level=i;
-				break;
-
-
-			case 2:
 				i=0;
 				while(1) {
 					uifc.helpbuf=
-	"~ Linked Nodes ~\r\n\r\n"
-	"From this menu you can configure the settings for your linked\r\n"
-	"FidoNet-style nodes (uplinks and downlinks).\r\n"
-	"\r\n"
-	"A single node configuration can represent one node or a collection\r\n"
+	"~ Linked Nodes ~\n\n"
+	"From this menu you can configure the settings for your linked\n"
+	"FidoNet-style nodes (uplinks and downlinks).\n"
+	"\n"
+	"A single node configuration can represent one node or a collection\n"
 	"of nodes, by using the `ALL` wildcard word."
 	;
 
@@ -327,7 +450,7 @@ int main(int argc, char **argv)
 						| WIN_INSACT | WIN_DELACT | WIN_XTR;
 					if (savnodecfg.addr.zone)
 						mode |= WIN_PUT;
-					i=uifc.list(mode,0,0,0,&i,0,"Linked Nodes",opt);
+					i=uifc.list(mode,0,0,0,&node_opt,0,"Linked Nodes",opt);
 					if(i==-1)
 						break;
 					int msk = i&MSK_ON;
@@ -335,8 +458,10 @@ int main(int argc, char **argv)
 					if (msk == MSK_INS) {
 						str[0]=0;
 	uifc.helpbuf=
-	"~ Address ~\r\n\r\n"
-	"This is the FidoNet style address of the node you wish to add (4D).\r\n";
+	"~ Address ~\n\n"
+	"This is the FidoNet style address of the node you wish to add (3D or 4D).\n"
+	"The `ALL` wildcard may be usd for portions of the address.\n"
+	;
 						if(uifc.input(WIN_MID|WIN_SAV,0,0
 							,"Node Address (ALL wildcard allowed)",str
 							,25,K_EDIT)<1)
@@ -386,73 +511,78 @@ int main(int argc, char **argv)
 					}
 					while(1) {
 	uifc.helpbuf=
-	"~ Linked Node Settings ~\r\n\r\n"
-	"These are the settings available for each configured node:\r\n"
-	"\r\n"
-	"`Address` is the FidoNet-style address in the Zone:Net/Node (3D) or\r\n"
-	"Zone:Net/Node.Point (4D) format. The wildcard word '`ALL`' may be used\r\n"
-	"in place of one of the fields to create a node configuration which\r\n"
-	"will apply to *all* nodes matching that address pattern.\r\n"
-	"e.g. '`1:ALL`' matches all nodes within FidoNet Zone 1.\r\n"
-	"\r\n"
-	"`Comment` is a note to yourself about this node. Setting this to the\r\n"
-	"user or sysop name corresponding with the configured node can be\r\n"
-	"a helpful reminder to yourself later.\r\n"
-	"\r\n"
-	"`Archive Type` is the name of an archive type corresponding with one of\r\n"
-	"your configured archive types or '`None`'.  This archive type will\r\n"
-	"be used when creating EchoMail bundles or if `None`, raw/uncompressed\r\n"
-	"EchoMail packets will be sent to this node.\r\n"
-	"This setting may be managed by the node using NetMail/AreaFix requests.\r\n"
-	"\r\n"
-	"`Packet Type` is the type of outbound packet generated for this node.\r\n"
-	"Incoming packet types are automatically detected from among the list\r\n"
-	"of supported packet types (`2`, `2.2`, `2e`, and `2+`).\r\n"
-	"The default outbound packet type is `Type-2+`.\r\n"
-	"\r\n"
-	"`Packet Password` is an optional password that may be added to outbound\r\n"
-	"packets for this node.  Incoming packets from this node must also have\r\n"
-	"the same password value if this password is configured (not blank).\r\n"
-	"Packet passwords are case insensitive.\r\n"
-	"This setting may be managed by the node using NetMail/AreaFix requests.\r\n"
-	"\r\n"
-	"`TIC File Password` is an optional password that may be configured here\r\n"
-	"(and in your `sbbsecho.ini` file) for use by `ticket.js` when creating\r\n"
-	"or authenticating `.TIC` files.\r\n"
-	"This setting may be managed by the node using NetMail/AreaFix requests.\r\n"
-	"\r\n"
-	"`AreaFix Password` is an optional password used to enable AreaFix\r\n"
-	"NetMail requests (remote Area Management) from this node.\r\n"
-	"AreaFix Passwords are case insensitive.\r\n"
-	"This setting may be managed by the node using NetMail/AreaFix requests.\r\n"
-	"\r\n"
-	"`AreaFix Keys` is a list of keys which enable AreaFix access to one or\r\n"
-	"more Additional EchoLists.\r\n"
-	"\r\n"
-	"`Status` is the default mode for sending mail to this node: `Normal`, `Hold`\r\n"
-	"(wait for pickup) or `Crash` (immediate).\r\n"
-	"\r\n"
-	"`Direct` determines whether to connect to this node directly (whenever\r\n"
-	"possible) when sending mail to this node.\r\n"
-	"\r\n"
-	"`Passive` is used to temporarily disable the packing and sending of\r\n"
-	"EchoMail for a node.  The opposite of Passive is `Active`.\r\n"
-	"This setting may be managed by the node using NetMail/AreaFix requests.\r\n"
-	"\r\n"
-	"`Send Notify List` is used to flag nodes that you want notified via\r\n"
-	"NetMail of their current AreaFix settings whenever SBBSecho is run\r\n"
-	"with the '`G`' option.\r\n"
-	"\r\n"
-	"`Route To` is only used in Binkley-Style Outbound (BSO/FLO) operating\r\n"
-	"mode and is used to set the FidoNet address to route mail for this node.\r\n"
-	"\r\n"
-	"`Inbox Directory` is only used in BSO operating mode and is an optional\r\n"
-	"alternate directory to search for incoming files from this node (e.g.\r\n"
-	"used in combination with BinkD's ibox setting).\r\n"
-	"\r\n"
-	"`Outbox Directory` is only used in BSO operating mode and is an optional\r\n"
-	"alternate directory to place outbound files for this node (e.g. used\r\n"
-	"in combination with BinkD's obox setting).\r\n"
+	"~ Linked Node Settings ~\n"
+	"\n"
+	"`Address` is the FidoNet-style address in the Zone:Net/Node (3D) or\n"
+	"    Zone:Net/Node.Point (4D) format. The wildcard word '`ALL`' may be used\n"
+	"    in place of one of the fields to create a node configuration which\n"
+	"    will apply to *all* nodes matching that address pattern.\n"
+	"    e.g. '`1:ALL`' matches all nodes within FidoNet Zone 1.\n"
+	"\n"
+	"`Comment` is a note to yourself about this node. Setting this to the\n"
+	"    user or sysop name corresponding with the configured node can be\n"
+	"    a helpful reminder to yourself later.\n"
+	"\n"
+	"`Archive Type` is the name of an archive type corresponding with one of\n"
+	"    your configured archive types or '`None`'.  This archive type will\n"
+	"    be used when creating EchoMail bundles or if `None`, raw/uncompressed\n"
+	"    EchoMail packets will be sent to this node.\n"
+	"    This setting may be managed by the node using AreaFix requests.\n"
+	"\n"
+	"`Packet Type` is the type of outbound packet generated for this node.\n"
+	"    Incoming packet types are automatically detected from among the list\n"
+	"    of supported packet types (`2`, `2.2`, `2e`, and `2+`).\n"
+	"    The default outbound packet type is `2+`.\n"
+	"\n"
+	"`Packet Password` is an optional password that may be added to outbound\n"
+	"    packets for this node.  Incoming packet passwords are compared with\n"
+	"    this password value.  If this password is blank/empty and `Strict\n"
+	"    Packet Passwords` are enabled, then incoming packets from this node\n"
+	"    must also have no password.  Packet passwords are case insensitive.\n"
+	"    This setting may be managed by the node using AreaFix requests.\n"
+	"\n"
+	"`TIC File Password` is an optional password that may be configured here\n"
+	"    (and in your `sbbsecho.ini` file) for use by `ticket.js` when creating\n"
+	"    or authenticating `.TIC` files.\n"
+	"    This setting may be managed by the node using AreaFix requests.\n"
+	"\n"
+	"`AreaFix Password` is an optional password used to enable AreaFix\n"
+	"    NetMail requests (Remote Area Management) from this node.\n"
+	"    AreaFix Passwords are case insensitive.\n"
+	"    This setting may be managed by the node using AreaFix requests.\n"
+	"\n"
+	"`AreaFix Keys` is a list of keys which enable AreaFix access to one or\n"
+	"    more additional EchoLists.\n"
+	"\n"
+	"`Status` is the default mode for sending mail to this node: `Normal`, `Hold`\n"
+	"    (wait for pickup) or `Crash` (immediate).\n"
+	"\n"
+	"`Direct` determines whether to connect to this node directly (whenever\n"
+	"    possible) when sending mail to this node.\n"
+	"\n"
+	"`Passive` is used to temporarily disable (pause) the packing and sending\n"
+	"    of EchoMail for this node.  The opposite of Passive is `Active`.\n"
+	"    This setting may be managed by the node using AreaFix requests.\n"
+	"\n"
+	"`Send Notify List` is used to flag nodes that you want notified via\n"
+	"    NetMail of their current AreaFix settings whenever SBBSecho is run\n"
+	"    with the '`G`' option.\n"
+	"\n"
+	"`Uplink for Message Groups` is an optional list of Message Groups (short\n"
+	"    names) for which this node is a hub/uplink for your system.  This\n"
+	"    setting is used in combination with the `Auto Add Sub-boards` feature\n"
+	"    to auto-link hubs with the newly added areas in your Area File.\n"
+	"\n"
+	"`Route To` is only used in Binkley-Style Outbound (BSO/FLO) operating\n"
+	"    mode and is used to set the FTN address to route mail for this node.\n"
+	"\n"
+	"`Inbox Directory` is only used in BSO operating mode and is an optional\n"
+	"    alternate directory to search for incoming files from this node\n"
+	"    (e.g. used in combination with BinkD's ibox setting).\n"
+	"\n"
+	"`Outbox Directory` is only used in BSO operating mode and is an optional\n"
+	"    alternate directory to place outbound files for this node (e.g. used\n"
+	"    in combination with BinkD's obox setting).\n"
 	;
 						j=0;
 						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Address"
@@ -480,6 +610,8 @@ int main(int argc, char **argv)
 							,cfg.nodecfg[i].passive ? "Yes":"No");
 						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Send Notify List"
 							,cfg.nodecfg[i].send_notify ? "Yes" : "No");
+						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Uplink for Message Groups"
+							,strListCombine(cfg.nodecfg[i].grphub,str,sizeof(str),","));
 						if(cfg.flo_mailer) {
 							snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Route To"
 								,cfg.nodecfg[i].route.zone
@@ -492,14 +624,14 @@ int main(int argc, char **argv)
 						opt[j][0]=0;
 						SAFEPRINTF(str, "Linked Node - %s"
 							,cfg.nodecfg[i].comment[0] ? cfg.nodecfg[i].comment : faddrtoa(&cfg.nodecfg[i].addr));
-						k=uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,60,&nodeop,0,str,opt);
+						k=uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&nodeop,0,str,opt);
 						if(k==-1)
 							break;
 						switch(k) {
 							case 0:
 	uifc.helpbuf=
-	"~ Address ~\r\n\r\n"
-	"This is the FidoNet style address of this linked node.\r\n";
+	"~ Address ~\n\n"
+	"This is the FidoNet style address of this linked node.\n";
 								strcpy(str,faddrtoa(&cfg.nodecfg[i].addr));
 								if(uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Node Address (ALL wildcard allowed)",str
@@ -508,9 +640,9 @@ int main(int argc, char **argv)
 								break;
 							case 1:
 	uifc.helpbuf=
-	"~ Comment ~\r\n\r\n"
-	"This is an optional comment for the node (e.g. the sysop's name).\r\n"
-	"This is used for informational purposes only.\r\n";
+	"~ Comment ~\n\n"
+	"This is an optional comment for the node (e.g. the sysop's name).\n"
+	"This is used for informational purposes only.\n";
 								uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Comment"
 									,cfg.nodecfg[i].comment,sizeof(cfg.nodecfg[i].comment)-1
@@ -518,9 +650,9 @@ int main(int argc, char **argv)
 								break;
 							case 2:
 	uifc.helpbuf=
-	"~ Archive Type ~\r\n\r\n"
-	"This is the archive type that will be used for compressing packets\r\n"
-	"into archive bundles for this node.\r\n";
+	"~ Archive Type ~\n\n"
+	"This is the archive type that will be used for compressing packets\n"
+	"into archive bundles for this node.\n";
 								int cur=cfg.arcdefs;
 								for(u=0;u<cfg.arcdefs;u++) {
 									if(cfg.nodecfg[i].archive == &cfg.arcdef[u])
@@ -541,14 +673,14 @@ int main(int argc, char **argv)
 								break;
 							case 3:
 	uifc.helpbuf=
-	"~ Packet Type ~\r\n\r\n"
-	"This is the packet header type that will be used in mail packets\r\n"
-	"created for this node.  SBBSecho defaults to creating `Type-2+` packets.\r\n"
-	"\r\n"
-	"`Type-2  ` packets are defined in FTS-0001.16 (Stone Age)\r\n"
-	"`Type-2e ` packets are defined in FSC-0039.04 (Sometimes called 2+)\r\n"
-	"`Type-2+ ` packets are defined in FSC-0048.02 (4D address support)\r\n"
-	"`Type-2.2` packets are defined in FSC-0045.01 (5D address support)\r\n"
+	"~ Packet Type ~\n\n"
+	"This is the packet header type that will be used in mail packets\n"
+	"created for this node.  SBBSecho defaults to creating `Type-2+` packets.\n"
+	"\n"
+	"`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"
 	;
 								j=cfg.nodecfg[i].pkt_type;
 								k=uifc.list(WIN_RHT|WIN_SAV,0,0,0,&j,0,"Packet Type"
@@ -560,9 +692,9 @@ int main(int argc, char **argv)
 								break;
 							case 4:
 	uifc.helpbuf=
-	"~ Packet Password ~\r\n\r\n"
-	"This is an optional password that SBBSecho will place into packets\r\n"
-	"destined for this node.\r\n";
+	"~ Packet Password ~\n\n"
+	"This is an optional password that SBBSecho will place into packets\n"
+	"destined for this node.\n";
 								uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Packet Password (optional)"
 									,cfg.nodecfg[i].pktpwd,sizeof(cfg.nodecfg[i].pktpwd)-1
@@ -570,9 +702,9 @@ int main(int argc, char **argv)
 								break;
 							case 5:
 	uifc.helpbuf=
-	"~ TIC File Password ~\r\n\r\n"
-	"This is an optional password that ticket.js will use for creating\r\n"
-	"and authenticating `.TIC` files to/from this node.\r\n";
+	"~ TIC File Password ~\n\n"
+	"This is an optional password that ticket.js will use for creating\n"
+	"and authenticating `.TIC` files to/from this node.\n";
 								uifc.input(WIN_MID|WIN_SAV,0,0
 									,"TIC File Password (optional)"
 									,cfg.nodecfg[i].ticpwd,sizeof(cfg.nodecfg[i].ticpwd)-1
@@ -580,9 +712,9 @@ int main(int argc, char **argv)
 								break;
 							case 6:
 	uifc.helpbuf=
-	"~ AreaFix Password ~\r\n\r\n"
-	"This is the password that will be used by this node when doing remote\r\n"
-	"AreaManager / AreaFix functions.\r\n";
+	"~ AreaFix Password ~\n\n"
+	"This is the password that will be used by this node when doing remote\n"
+	"AreaManager / AreaFix functions.\n";
 								uifc.input(WIN_MID|WIN_SAV,0,0
 									,"AreaFix Password"
 									,cfg.nodecfg[i].password,sizeof(cfg.nodecfg[i].password)-1
@@ -590,9 +722,9 @@ int main(int argc, char **argv)
 								break;
 							case 7:
 	uifc.helpbuf=
-	"~ AreaFix Keys ~\r\n\r\n"
-	"These are a named-keys to be given to this node allowing access to one or\r\n"
-	"more of the configured `Additional Echolists`\r\n";
+	"~ AreaFix Keys ~\n\n"
+	"These are a named-keys to be given to this node allowing access to one or\n"
+	"more of the configured `EchoLists`\n";
 								while(1) {
 									for(j=0; cfg.nodecfg[i].keys!=NULL && cfg.nodecfg[i].keys[j]!=NULL ;j++)
 										strcpy(opt[j],cfg.nodecfg[i].keys[j]);
@@ -605,7 +737,7 @@ int main(int argc, char **argv)
 									if((k&MSK_ON)==MSK_INS) {
 										k&=MSK_OFF;
 										if(uifc.input(WIN_MID|WIN_SAV,0,0
-											,"AreaFix Keys",str,SBBSECHO_MAX_KEY_LEN
+											,"AreaFix Key",str,SBBSECHO_MAX_KEY_LEN
 											,K_UPPER)<1)
 											continue;
 										strListInsert(&cfg.nodecfg[i].keys, str, k);
@@ -629,8 +761,8 @@ int main(int argc, char **argv)
 								break;
 							case 8:
 	uifc.helpbuf=
-	"~ Mail Status ~\r\n\r\n"
-	"Set the mail status for this node: `Normal`, `Hold`, or `Crash`.\r\n";
+	"~ Mail Status ~\n\n"
+	"Set the mail status for this node: `Normal`, `Hold`, or `Crash`.\n";
 								j=cfg.nodecfg[i].status;
 								k=uifc.list(WIN_RHT|WIN_SAV,0,0,0,&j,0,"Mail Status"
 									,mailStatusStringList);
@@ -667,13 +799,57 @@ int main(int argc, char **argv)
 								break;
 							case 12:
 	uifc.helpbuf=
-	"~ Route To ~\r\n\r\n"
-	"When using a BSO/FLO type mailer, this is the Fido address to route mail\r\n"
-	"for this node(s) to.\r\n"
-	"\r\n"
-	"This option is normally only used with wildcard type node entries\r\n"
-	"(e.g. `ALL`, or `1:ALL`, `2:ALL`, etc.) and is used to route non-direct\r\n"
-	"NetMail packets to your uplink node (hub).\r\n";
+	"~ Uplink for Message Groups ~\n\n"
+	"These are Message Group short names (as configured in SCFG) for which\n"
+	"this linked-node is your system's uplink (hub).\n"
+	"\n"
+	"Use of this setting allows your hub to be automatically linked with new\n"
+	"areas when new Sub-boards (within a listed group) are auto-added to the\n"
+	"Area File."
+	;
+								while(1) {
+									for(j=0; cfg.nodecfg[i].grphub!=NULL && cfg.nodecfg[i].grphub[j]!=NULL ;j++)
+										strcpy(opt[j],cfg.nodecfg[i].grphub[j]);
+									opt[j][0]=0;
+									k=uifc.list(WIN_SAV|WIN_INS|WIN_DEL|WIN_ACT|
+										WIN_XTR|WIN_INSACT|WIN_DELACT|WIN_RHT
+										,0,0,0,&k,0,"Uplink for Message Groups",opt);
+									if(k==-1)
+										break;
+									if((k&MSK_ON)==MSK_INS) {
+										k&=MSK_OFF;
+										if(uifc.input(WIN_MID|WIN_SAV,0,0
+											,"Message Group (short name)",str,LEN_GSNAME
+											,/* kmode: */0) < 1)
+											continue;
+										strListInsert(&cfg.nodecfg[i].grphub, str, k);
+										uifc.changes=TRUE;
+										continue; 
+									}
+
+									if((k&MSK_ON)==MSK_DEL) {
+										k&=MSK_OFF;
+										strListRemove(&cfg.nodecfg[i].grphub, k);
+										uifc.changes=TRUE;
+										continue; 
+									}
+									SAFECOPY(str,cfg.nodecfg[i].grphub[k]);
+									uifc.input(WIN_MID|WIN_SAV,0,0,"Message Group (short name)"
+										,str,LEN_GSNAME,K_EDIT|K_UPPER);
+									strListReplace(cfg.nodecfg[i].grphub, k, str);
+									uifc.changes=TRUE;
+									continue; 
+								}
+								break;
+							case 13:
+	uifc.helpbuf=
+	"~ Route To ~\n\n"
+	"When using a BSO/FLO type mailer, this is the Fido address to route mail\n"
+	"for this node(s) to.\n"
+	"\n"
+	"This option is normally only used with wildcard type node entries\n"
+	"(e.g. `ALL`, or `1:ALL`, `2:ALL`, etc.) and is used to route non-direct\n"
+	"NetMail packets to your uplink node (hub).\n";
 								strcpy(str,faddrtoa(&cfg.nodecfg[i].route));
 								if(uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Node Address to Route To",str
@@ -685,12 +861,12 @@ int main(int argc, char **argv)
 									uifc.changes=TRUE;
 								}
 								break;
-							case 13:
+							case 14:
 								uifc.input(WIN_MID|WIN_SAV,0,0,"Inbound FileBox Directory"
 									,cfg.nodecfg[i].inbox, sizeof(cfg.nodecfg[i].inbox)-1
 									,K_EDIT);
 								break;
-							case 14:
+							case 15:
 								uifc.input(WIN_MID|WIN_SAV,0,0,"Outbound FileBox Directory"
 									,cfg.nodecfg[i].outbox, sizeof(cfg.nodecfg[i].outbox)-1
 									,K_EDIT);
@@ -700,216 +876,250 @@ int main(int argc, char **argv)
 				}
 				break;
 
-			case 6:	/* Paths and Filenames... */
+			case 5:	/* Paths and Filenames... */
 				j=0;
 				while(1) {
 					i=0;
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Non-secure Inbound Directory"
-						,cfg.inbound);
+						,cfg.inbound[0] ? cfg.inbound : DEFAULT_INBOUND);
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Secure Inbound Directory"
-						,cfg.secure_inbound[0] ? cfg.secure_inbound : "<None>");
+						,cfg.secure_inbound[0] ? cfg.secure_inbound : DEFAULT_SECURE_INBOUND);
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Outbound Directory"
-						,cfg.outbound);
+						,cfg.outbound[0] ? cfg.outbound : DEFAULT_OUTBOUND);
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Area File"
-						,cfg.areafile);
+						,cfg.areafile[0] ? cfg.areafile : DEFAULT_AREA_FILE);
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Bad Area File"
-						,cfg.badareafile);
+						,cfg.badareafile[0] ? cfg.badareafile : DEFAULT_BAD_AREA_FILE);
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Log File"
-						,cfg.logfile[0] ? cfg.logfile
-						: "SCFG->data/sbbsecho.log");
+						,cfg.logfile[0] ? cfg.logfile : DEFAULT_LOG_FILE);
+					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Echo Statistics File"
+						,cfg.echostats[0] ? cfg.echostats : DEFAULT_ECHOSTATS_FILE);
 					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Temporary File Directory"
-						,cfg.temp_dir[0] ? cfg.temp_dir
-						: "../temp/sbbsecho");
+						,cfg.temp_dir[0] ? cfg.temp_dir	: DEFAULT_TEMP_DIR);
+					snprintf(opt[i++],MAX_OPLN-1,"%-30.30s %s","Outgoing Semaphore File"
+						,cfg.outgoing_sem);
 					opt[i][0]=0;
 					uifc.helpbuf=
-						"~ Paths and Filenames ~\r\n\r\n"
-						"From this menu you can configure the paths that SBBSecho will use\r\n"
-						"when importing, exporting and logging.\r\n";
-					j=uifc.list(WIN_MID|WIN_ACT,0,0,60,&j,0
+						"~ Paths and Filenames ~\n\n"
+						"From this menu you can configure the paths and filenames that SBBSecho\n"
+						"will use during its operation (e.g. importing and exporting messages).\n";
+					j=uifc.list(WIN_BOT|WIN_L2R|WIN_ACT|WIN_SAV,0,0,0,&path_opt,0
 						,"Paths and Filenames",opt);
 					if(j==-1)
 						break;
 					switch(j) {
 						case 0:
 	uifc.helpbuf=
-	"~ Non-secure Inbound Directory ~\r\n\r\n"
-	"This is the path where your FTN mailer stores, and where SBBSecho will\r\n"
-	"look for, incoming files (potentially including message bundles and\r\n"
-	"packets) from unauthenticated (non-secure) mailer sessions."
+	"~ Non-secure Inbound Directory ~\n\n"
+	"This is the path where your FTN mailer stores, and where SBBSecho will\n"
+	"look for, incoming files (potentially including message bundles and\n"
+	"packets) from unauthenticated (non-secure) mailer sessions.\n"
+	"\n"
+	"Default value is `" DEFAULT_INBOUND "`."
 	;
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Non-secure Inbound Directory"
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Non-secure Inbound Directory"
 								,cfg.inbound,sizeof(cfg.inbound)-1
 								,K_EDIT);
 							break;
 
 						case 1:
 	uifc.helpbuf=
-	"~ Secure Inbound Directory ~\r\n\r\n"
-	"This is the path where your FTN mailer stores, and where SBBSecho will\r\n"
-	"look for, incoming message bundles and packets for `Secure` (password\r\n"
-	"protected) sessions.";
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Secure Inbound Directory"
+	"~ Secure Inbound Directory ~\n\n"
+	"This is the path where your FTN mailer stores, and where SBBSecho will\n"
+	"look for, incoming message bundles and packets for `Secure` (password\n"
+	"protected) sessions.\n"
+	"\n"
+	"Default value is `" DEFAULT_SECURE_INBOUND "`."
+	;
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Secure Inbound Directory"
 								,cfg.secure_inbound,sizeof(cfg.secure_inbound)-1
 								,K_EDIT);
 							break;
 
 						case 2:
 	uifc.helpbuf=
-	"~ Outbound Directory ~\r\n\r\n"
-	"This is the path where your FTN mailer will look for, and where SBBSecho\r\n"
-	"will place, outgoing message bundles and packets.\r\n"
-	"\r\n"
-	"In Binkley-Style Outbound mode, this serves as the base directory\r\n"
+	"~ Outbound Directory ~\n\n"
+	"This is the path where your FTN mailer will look for, and where SBBSecho\n"
+	"will place, outgoing message bundles and packets.\n"
+	"\n"
+	"In Binkley-Style Outbound mode, this serves as the base directory\n"
 	"name for special foreign zone and point destination nodes as well."
+	"\n"
+	"Default value is `" DEFAULT_OUTBOUND "`."
 	;
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Outbound Directory"
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Outbound Directory"
 								,cfg.outbound,sizeof(cfg.outbound)-1
 								,K_EDIT);
 							break;
 
 						case 3:
 	uifc.helpbuf=
-	"~ Area File ~\r\n\r\n"
-	"This is the path of the file SBBSecho will use as your primary\r\n"
-	"list of FidoNet-style message areas (default is `data/areas.bbs`).\r\n"
-	"\r\n"
-	"Each line in the file defines an FTN message area (echo) of the format:\r\n"
-	"\r\n"
-	"   <`code`> <`tag`> [[`link`] [`link`] [...]]\r\n"
-	"\r\n"
-	"Each field is separated by one or more white-space characters:\r\n"
-	"\r\n"
-	"   `<code>` is the Synchronet `internal code` for the local sub-board\r\n"
-	"   `<tag>`  is the network's agreed-upon `echo tag` for the message area\r\n"
-	"   `[link]` is an `FTN address` to send and receive messages for this area\r\n"
-	"          (there may be many linked nodes for each area)\r\n"
-	"          (often your FTN hub may be the only linked node)\r\n"
-	"\r\n"
-	"Example Area Line:\r\n"
-	"\r\n"
-	"   `FIDO_BBS_CARN    BBS_CARNIVAL                        1:218/700`\r\n"
-	"\r\n"
-	"Notes:\r\n"
-	"\r\n"
-	" `*` Only the `<code>` and `<tag>` fields are required\r\n"
-	" `*` The `<code>` and `<tag>` fields are case in-sensitive\r\n"
-	" `*` The `[link]` fields must be 2D, 3D, or 4D FidoNet-style node addresses\r\n"
-	" `*` The '`<`' and '`>`', '`[`' and '`]`' characters are not part of the syntax\r\n"
-	" `*` Lines beginning with a semicolon (`;`) are ignored (i.e. comments)\r\n"
-	" `*` Leading white-space characters are ignored\r\n"
-	" `*` Blank lines are ignored\r\n"
-	" `*` This file may be import/exported to/from your `Message Areas` in `SCFG`\r\n"
-	" `*` This file may be remotely modified by authorized nodes using `AreaFix`\r\n"
+	"~ Area File ~\n\n"
+	"This is the path of the file SBBSecho will use as your primary\n"
+	"list of FidoNet-style message areas (default is `data/areas.bbs`).\n"
+	"\n"
+	"Each line in the file defines an FTN message area (echo) of the format:\n"
+	"\n"
+	"   <`code`> <`tag`> [[`link`] [`link`] [...]]\n"
+	"\n"
+	"Each field is separated by one or more white-space characters:\n"
+	"\n"
+	"   `<code>` is the Synchronet `internal code` for the local sub-board\n"
+	"   `<tag>`  is the network's agreed-upon `echo tag` for the message area\n"
+	"   `[link]` is an `FTN address` to send and receive messages for this area\n"
+	"          (there may be many linked nodes for each area)\n"
+	"          (often your FTN uplink/hub may be the only linked node)\n"
+	"\n"
+	"Example Area Line:\n"
+	"\n"
+	"   `FIDO_BBS_CARN    BBS_CARNIVAL                        1:218/700`\n"
+	"\n"
+	"Notes:\n"
+	"\n"
+	" `*` Only the `<code>` and `<tag>` fields are required\n"
+	" `*` The `<code>` and `<tag>` fields are case in-sensitive\n"
+	" `*` The `[link]` fields must be 2D, 3D, or 4D FidoNet-style node addresses\n"
+	" `*` The '`<`' and '`>`', '`[`' and '`]`' characters are not part of the syntax\n"
+	" `*` Lines beginning with a semicolon (`;`) are ignored (i.e. comments)\n"
+	" `*` Leading white-space characters are ignored\n"
+	" `*` Blank lines are ignored\n"
+	" `*` A `<tag>` value of `*` indicates a `bad echo` (unknown) area\n"
+	" `*` A `<code>` value of `P` indicates a pass-through message area\n"
+	" `*` This file may be import/exported to/from your `Message Areas` in `SCFG`\n"
+	" `*` This file may be remotely modified by authorized nodes using `AreaFix`\n"
+	"\n"
+	"Default value is `" DEFAULT_AREA_FILE "`."
 	;
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Area File"
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Area File"
 								,cfg.areafile,sizeof(cfg.areafile)-1
 								,K_EDIT);
 							break;
 
 						case 4:
 	uifc.helpbuf=
-	"~ Bad Area File ~\r\n\r\n"
-	"This is the path of the file SBBSecho will use to record the names\r\n"
-	"(echo tags) and descriptions of FTN message areas (echoes) that your\r\n"
-	"system has received EchoMail for, but does not carry locally. The\r\n"
-	"default path/filename is `data/badareas.lst`.\r\n"
-	"\r\n"
-	"Notes:\r\n"
-	"\r\n"
-	" `*` The descriptions of the areas will only be included if the\r\n"
-	"   corresponding echo tags can be located in one of your configured\r\n"
-	"   `Additional EchoLists`.\r\n"
-	"\r\n"
-	" `*` The format of the file is the same as `BACKBONE.NA` and suitable for\r\n"
-	"   importing into a Synchronet Message Group using `SCFG`.\r\n"
-	"\r\n"
-	" `*` SBBSecho will automatically sort and maintain this list, removing\r\n"
-	"   areas if they are added to your configuration (`SCFG->Message Areas`\r\n"
-	"   and `Area File`).\r\n"
+	"~ Bad Area File ~\n\n"
+	"This is the path of the file SBBSecho will use to record the names\n"
+	"(echo tags) and descriptions of FTN message areas (echoes) that your\n"
+	"system has received EchoMail for, but does not carry locally. The\n"
+	"default path/filename is `" DEFAULT_BAD_AREA_FILE "`.\n"
+	"\n"
+	"Notes:\n"
+	"\n"
+	" `*` The descriptions of the areas will only be included if the\n"
+	"   corresponding echo tags can be located in one of your configured\n"
+	"   `EchoLists`.\n"
+	"\n"
+	" `*` The format of the file is the same as `BACKBONE.NA` and suitable for\n"
+	"   importing into a Synchronet Message Group using `SCFG`.\n"
+	"\n"
+	" `*` SBBSecho will automatically sort and maintain this list, removing\n"
+	"   areas if they are added to your configuration (`SCFG->Message Areas`)\n"
+	"   and your `Area File`.\n"
 	;
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Bad Area File"
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Bad Area File"
 								,cfg.badareafile,sizeof(cfg.badareafile)-1
 								,K_EDIT);
 							break;
 
 						case 5:
 	uifc.helpbuf=
-	"~ Log File ~\r\n\r\n"
-	"This is the path of the file SBBSecho will use to log information each time\r\n"
-	"it is run (default is `data/sbbsecho.log`)."
+	"~ Log File ~\n\n"
+	"This is the path of the file SBBSecho will use to log information each\n"
+	"time it is run (default is `" DEFAULT_LOG_FILE "`)."
 	;
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Log File"
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Log File"
 								,cfg.logfile,sizeof(cfg.logfile)-1
 								,K_EDIT);
 							break; 
 
 						case 6:
 	uifc.helpbuf=
-	"~ Temporary File Directory ~\r\n\r\n"
-	"This is the directory where SBBSecho will store temporary files that\r\n"
-	"it creates and uses during its run-time.\r\n"
-	"(default is `../temp/sbbsecho`)."
+	"~ EchoStats File ~\n\n"
+	"This is the path of the file SBBSecho will use to track statistics for\n"
+	"EchoMail message areas (default is `" DEFAULT_ECHOSTATS_FILE "`)."
+	;
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"EchoStats File"
+								,cfg.echostats,sizeof(cfg.echostats)-1
+								,K_EDIT);
+							break; 
+
+						case 7:
+	uifc.helpbuf=
+	"~ Temporary File Directory ~\n\n"
+	"This is the directory where SBBSecho will store temporary files that\n"
+	"it creates and uses during its run-time (default is `" DEFAULT_TEMP_DIR "`)."
 	;
-							uifc.input(WIN_MID|WIN_SAV,0,0,"Temp Dir"
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Temp Dir"
 								,cfg.temp_dir,sizeof(cfg.temp_dir)-1
 								,K_EDIT);
 							break; 
+
+						case 8:
+	uifc.helpbuf=
+	"~ Outgoing Semaphore File ~\n\n"
+	"This is an optional file to create/touch whenever there are new outbound\n"
+	"files created or updated by SBBSecho."
+	;
+							uifc.input(WIN_L2R|WIN_SAV,0,0,"Outgoing Sem File"
+								,cfg.outgoing_sem,sizeof(cfg.outgoing_sem)-1
+								,K_EDIT);
+							break; 
 					} 
 				}
 				break;
 
-			case 4:	/* NetMail Settings */
+			case 3:	/* NetMail Settings */
 				j=0;
 				while(1) {
 					uifc.helpbuf=
-	"~ NetMail Settings ~\r\n"
-	"\r\n"
-	"`Sysop Aliases` is a comma-separated list of names by which the sysop\r\n"
-	"    (user #1) may receive NetMail messages, in addition to the alias\r\n"
-	"    and real name associated with their BBS user account.\r\n"
-	"    This setting defaults to just '`SYSOP`'.\r\n"
-	"\r\n"
-    "`Default Recipient` is the name of the user account you wish to receive\r\n"
-	"    inbound NetMail messages that have been addressed to an unrecognized\r\n"
-	"    user name or alias.\r\n"
-	"\r\n"
-	"`Fuzzy Zone Operation` when set to `Yes`, if SBBSecho receives an inbound\r\n"
-	"    netmail with no international zone information, it will compare the\r\n"
-	"    net/node of the destination to the net/node information in your AKAs\r\n"
-	"    and assume the zone of a matching AKA.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Kill/Ignore Empty NetMail Messages` will instruct SBBSecho to simply\r\n"
-	"    discard (not import or export) NetMail messages without any body.\r\n"
-	"    This setting defaults to `Yes`.\r\n"
-	"\r\n"
-	"`Delete Processed NetMail Messages` will instruct SBBSecho to delete\r\n"
-	"    NetMail messages/files after they have been sent or imported.\r\n"
-	"    When set to `No`, SBBSecho will mark them as Sent or Received instead.\r\n"
-	"    This setting defaults to `Yes`.\r\n"
-	"\r\n"
-	"`Ignore NetMail Destination Address` will instruct SBBSecho to treat\r\n"
-	"    all NetMail as though it is destined for one of your systems's FTN\r\n"
-	"    addresses (AKAs) and potentially import it.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Ignore Netmail 'Sent' Attribute` will instruct SBBSecho to export\r\n"
-	"    NetMail messages even when their 'Sent' attribute flag is set.\r\n"
-	"    This setting `should not` be set to `Yes` when `Delete NetMail` is\r\n"
-	"    disabled.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Ignore Netmail 'Received' Attribute` will instruct SBBSecho to import\r\n"
-	"    NetMail messages even when their 'Received' attribute flag is set.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Ignore NetMail 'Local' Attribute` will instruct SBBSecho to import\r\n"
-	"    NetMail messages even when their 'Local' attribute flag is set.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Maximum Age of Imported NetMail` allows you to optionally set an age\r\n"
-	"    limit (in days) of NetMail messages that may be imported.\r\n"
-	"    This setting defaults to `None` (no maximum age).\r\n"
+	"~ NetMail Settings ~\n"
+	"\n"
+	"`Sysop Aliases` is a comma-separated list of names by which the sysop\n"
+	"    (user #1) may receive NetMail messages, in addition to the alias\n"
+	"    and real name associated with their BBS user account.\n"
+	"    This setting defaults to just '`SYSOP`'.\n"
+	"\n"
+    "`Default Recipient` is the name of the user account you wish to receive\n"
+	"    inbound NetMail messages that have been addressed to an unrecognized\n"
+	"    user name or alias.\n"
+	"\n"
+	"`Fuzzy Zone Operation` when set to `Yes`, if SBBSecho receives an inbound\n"
+	"    netmail with no international zone information, it will compare the\n"
+	"    net/node of the destination to the net/node information in your AKAs\n"
+	"    and assume the zone of a matching AKA.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Kill/Ignore Empty NetMail Messages` will instruct SBBSecho to simply\n"
+	"    discard (not import or export) NetMail messages without any body.\n"
+	"    This setting defaults to `Yes`.\n"
+	"\n"
+	"`Delete Processed NetMail Messages` will instruct SBBSecho to delete\n"
+	"    NetMail messages/files after they have been sent or imported.\n"
+	"    When set to `No`, SBBSecho will mark them as Sent or Received instead.\n"
+	"    This setting defaults to `Yes`.\n"
+	"\n"
+	"`Ignore NetMail Destination Address` will instruct SBBSecho to treat\n"
+	"    all NetMail as though it is destined for one of your systems's FTN\n"
+	"    addresses (AKAs) and potentially import it.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Ignore Netmail 'Sent' Attribute` will instruct SBBSecho to export\n"
+	"    NetMail messages even when their 'Sent' attribute flag is set.\n"
+	"    This setting `should not` be set to `Yes` when `Delete NetMail` is\n"
+	"    disabled.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Ignore Netmail 'Received' Attribute` will instruct SBBSecho to import\n"
+	"    NetMail messages even when their 'Received' attribute flag is set.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Ignore NetMail 'Local' Attribute` will instruct SBBSecho to import\n"
+	"    NetMail messages even when their 'Local' attribute flag is set.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Maximum Age of Imported NetMail` allows you to optionally set an age\n"
+	"    limit of NetMail messages that may be imported.\n"
+	"    This setting defaults to `None` (no maximum age).\n"
 ;
 					i=0;
 					strListCombine(cfg.sysop_alias_list, sysop_aliases, sizeof(sysop_aliases)-1, ",");
@@ -931,22 +1141,22 @@ int main(int argc, char **argv)
 					snprintf(opt[i++],MAX_OPLN-1,"%-40.40s%-3.3s","Ignore NetMail 'Local' Attribute"
 						,cfg.ignore_netmail_local_attr ? "Yes" : "No");
 					if(cfg.max_netmail_age)
-						sprintf(str,"%1.0f days", cfg.max_netmail_age / (24.0*60.0*60.0));
+						duration_to_vstr(cfg.max_netmail_age, str, sizeof(str));
 					else
 						strcpy(str, "None");
 					snprintf(opt[i++],MAX_OPLN-1,"%-40.40s%s","Maximum Age of Imported NetMail"	, str);
 					opt[i][0]=0;
-					j=uifc.list(WIN_ACT,0,0,60,&j,0,"NetMail Settings",opt);
+					j=uifc.list(WIN_ACT|WIN_SAV,0,0,0,&netmail_opt,0,"NetMail Settings",opt);
 					if(j==-1)
 						break;
 					switch(j) {
 						case 0:
 							uifc.helpbuf=
-							"~ Sysop Aliases ~\r\n\r\n"
-							"This is a comma-separated list of additional `To` names that the sysop\r\n"
-							"(user #1) can receive netmail by. When specifying multiple aliases,\r\n"
-							"they must be separated by a single comma and no extra white-space\r\n"
-							"(e.g. \"SYSOP,COORDINATOR\"). The default value is just `SYSOP`.\r\n";
+							"~ Sysop Aliases ~\n\n"
+							"This is a comma-separated list of additional `To` names that the sysop\n"
+							"(user #1) can receive netmail by. When specifying multiple aliases,\n"
+							"they must be separated by a single comma and no extra white-space\n"
+							"(e.g. \"SYSOP,COORDINATOR\"). The default value is just `SYSOP`.\n";
 							if(uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Sysop Aliases (comma separated)"
 								,sysop_aliases
 								,sizeof(sysop_aliases)-1,K_EDIT|K_UPPER) >= 0) {
@@ -1017,82 +1227,98 @@ int main(int argc, char **argv)
 							break;
 						case 9:
 							uifc.helpbuf=
-							"~ Maximum Age of Imported NetMail ~\r\n\r\n"
-							"Maximum age (in days) of NetMail that may be imported. The age is based\r\n"
-							"on the date supplied in the message header and may be incorrect in some\r\n"
-							"conditions (e.g. erroneous software or incorrect system date).\r\n"
+							"~ Maximum Age of Imported NetMail ~\n\n"
+							"Maximum age of NetMail that may be imported. The age is based\n"
+							"on the date supplied in the message header and may be incorrect in some\n"
+							"conditions (e.g. erroneous software or incorrect system date).\n"
 							"Set this value to `0` to disable this feature (no maximum age imposed)."
 							;
 							if(cfg.max_netmail_age)
-								sprintf(str,"%1.0f", cfg.max_netmail_age / (24.0*60.0*60.0));
+								duration_to_vstr(cfg.max_netmail_age, str, sizeof(str));
 							else
 								strcpy(str, "None");
-							if(uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Maximum NetMail Age (in Days)"
-								,str, 5, K_EDIT) >= 0)
-								cfg.max_netmail_age = (long) (strtod(str, NULL) * (24.0*60.0*60.0));
+							if(uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Maximum NetMail Age"
+								,str, 10, K_EDIT) >= 0)
+								cfg.max_netmail_age = (ulong)parse_duration(str);
 							break;
 
 					} 
 				}
 				break;
 
-			case 5:	/* EchoMail Settings */
+			case 4:	/* EchoMail Settings */
 				j=0;
 				while(1) {
 					uifc.helpbuf=
-	"~ EchoMail Settings ~\r\n"
-	"\r\n"
-	"`Area Manager` is the BBS user name or alias to notify (via email) of\r\n"
-	"    AreaFix activities and errors.  This setting defaults to `SYSOP`.\r\n"
-	"\r\n"
-	"`Maximum Packet Size` is the largest packet file size that SBBSecho will\r\n"
-	"    normally create (in bytes).\r\n"
-	"    This settings defaults to `250K` (250 Kilobytes, or 256,000 bytes).\r\n"
-	"\r\n"
-	"`Maximum Bundle Size` is the largest bundle file size that SBBSecho will\r\n"
-	"    normally create (in bytes).\r\n"
-	"    This settings defaults to `250K` (250 Kilobytes, or 256,000 bytes).\r\n"
-	"\r\n"
-	"`Secure Operation` tells SBBSecho to check the Area File (e.g. areas.bbs)\r\n"
-	"    to insure that the packet origin (FTN address) of EchoMail messages\r\n"
-	"    is already linked to the EchoMail area where the message was posted.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Notify Users of Received EchoMail` tells SBBSecho to send telegrams\r\n"
-	"    (short messages) to BBS users when EchoMail addressed to their name\r\n"
-	"    or alias has been imported into a message base that the user has\r\n"
-	"    access to read.\r\n"
-	"\r\n"
-	"`Convert Existing Tear Lines` tells SBBSecho to convert any tear lines\r\n"
-	"    (`---`) existing in the message text to `===`.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Allow Nodes to Add Areas from Area File` when set to `Yes` allows linked\r\n"
-	"    nodes to add areas listed in your Area File (e.g. `areas.bbs`).\r\n"
-	"    This setting defaults to `Yes`.\r\n"
-	"\r\n"
-	"`Strip Line Feeds From Outgoing Messages` when set to `Yes` instructs\r\n"
-	"    SBBSecho to remove any line-feed (ASCII 10) characters from the body\r\n"
-	"    text of messages being exported to FidoNet EchoMail.\r\n"
-	"    This setting defaults to `No`.\r\n"
-	"\r\n"
-	"`Circular Path Detection` when `Enabled` will cause SBBSecho, during\r\n"
-	"    EchoMail import, to check the PATH kludge lines for any of the\r\n"
-	"    system's AKAs and if found (indicating a message loop), not import\r\n"
-	"    the message.\r\n"
-	"\r\n"
-	"`Outbound Bundle Attachments` may be either `Deleted` (killed) or `Truncated`\r\n"
-	"    (changed to 0-bytes in length) after being sent by your mailer.\r\n"
-	"\r\n"
-	"`Zone Blind SEEN-BY and PATH Lines` when `Enabled` will cause SBBSecho\r\n"
-	"    to assume that node numbers are not duplicated across zones and\r\n"
-	"    that a net/node combination in either of these Kludge lines should\r\n"
-	"    be used to identify a specific node regardless of which zone that\r\n"
-	"    node is located (thus breaking the rules of FidoNet 3D addressing).\r\n"
-	"\r\n"
-	"`Maximum Age of Imported EchoMail` allows you to optionally set an age\r\n"
-	"    limit (in days) of EchoMail messages that may be imported.\r\n"
-	"    This setting defaults to `60` (60 days).\r\n"
+	"~ EchoMail Settings ~\n"
+	"\n"
+	"`Area Manager` is the BBS user name or alias to notify (via email) of\n"
+	"    AreaFix activities and errors.  This setting defaults to `SYSOP`.\n"
+	"\n"
+	"`Maximum Packet Size` is the largest packet file size that SBBSecho will\n"
+	"    normally create (in bytes).\n"
+	"    This settings defaults to `250K` (250 Kilobytes, or 256,000 bytes).\n"
+	"\n"
+	"`Maximum Bundle Size` is the largest bundle file size that SBBSecho will\n"
+	"    normally create (in bytes).\n"
+	"    This settings defaults to `250K` (250 Kilobytes, or 256,000 bytes).\n"
+	"\n"
+	"`Secure Operation` tells SBBSecho to check the Area File (e.g. areas.bbs)\n"
+	"    to insure that the packet origin (FTN address) of EchoMail messages\n"
+	"    is already linked to the EchoMail area where the message was posted.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Notify Users of Received EchoMail` tells SBBSecho to send telegrams\n"
+	"    (short messages) to BBS users when EchoMail addressed to their name\n"
+	"    or alias has been imported into a message base that the user has\n"
+	"    access to read.\n"
+	"\n"
+	"`Convert Existing Tear Lines` tells SBBSecho to convert any tear lines\n"
+	"    (`---`) existing in the message text to `===`.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Strip Line Feeds From Outgoing Messages` when set to `Yes` instructs\n"
+	"    SBBSecho to remove any line-feed (ASCII 10) characters from the body\n"
+	"    text of messages being exported to FidoNet EchoMail.\n"
+	"    This setting defaults to `No`.\n"
+	"\n"
+	"`Automatically Add New Subs to Area File`, when set to `Yes`, enables\n"
+	"    SBBSecho to detect newly added Sub-boards in any Message Groups that\n"
+	"    are listed with a `Linked Node` as their hub/uplink and add those\n"
+	"    Sub-boards as new areas in your Area File.\n"
+	"\n"
+	"`Allow Nodes to Add Areas from Area File` when set to `Yes` allows linked\n"
+	"    nodes to add areas listed in your Area File (e.g. `areas.bbs`).\n"
+	"    When set to `No`, only areas found in one or more `EchoLists` may be\n"
+	"    added via AreaFix, provided the linked node has access.\n"
+	"    This setting defaults to `Yes`.\n"
+	"\n"
+	"`Maximum Backups to Maintain of Area File` defines the number of backup\n"
+	"    versions SBBSecho will maintain of your Area File (e.g. `areas.bbs`).\n"
+	"\n"
+	"`Circular Path Detection` when `Enabled` will cause SBBSecho, during\n"
+	"    EchoMail import, to check the PATH kludge lines for any of the\n"
+	"    system's AKAs and if found (indicating a message loop), not import\n"
+	"    the message.\n"
+	"\n"
+	"`Relay Filtered Messages` controls whether or not incoming messages that\n"
+	"    have been filtered (e.g. due to maximum message age restrictions)\n"
+	"    are to be forwarded to downlinks.\n"
+	"\n"
+	"`Outbound Bundle Attachments` may be either `Deleted` (killed) or `Truncated`\n"
+	"    (changed to 0-bytes in length) after being sent by your mailer.\n"
+	"    This only controls the bundle prefix that is written to the FLO\n"
+	"    files (`#` for truncate, `^` for delete).\n"
+	"\n"
+	"`Zone Blind SEEN-BY and PATH Lines` when `Enabled` will cause SBBSecho\n"
+	"    to assume that node numbers are not duplicated across zones and\n"
+	"    that a net/node combination in either of these Kludge lines should\n"
+	"    be used to identify a specific node regardless of which zone that\n"
+	"    node is located (thus breaking the rules of FidoNet 3D addressing).\n"
+	"\n"
+	"`Maximum Age of Imported EchoMail` allows you to optionally set an age\n"
+	"    limit of EchoMail messages that may be imported.\n"
+	"    This setting defaults to `60 days`.\n"
 	;
 
 					i=0;
@@ -1107,12 +1333,18 @@ int main(int argc, char **argv)
 						,cfg.echomail_notify ? "Yes":"No");
 					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Convert Existing Tear Lines"
 						,cfg.convert_tear ? "Yes":"No");
-					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Allow Nodes to Add Areas "
-						"from Area File",cfg.add_from_echolists_only ?"No":"Yes");
 					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Strip Line Feeds "
 						"from Outgoing Messages",cfg.strip_lf ? "Yes":"No");
+					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Automatically Add New Subs "
+						"to Area File",cfg.auto_add_subs ? "Yes":"No");
+					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Allow Nodes to Add Areas "
+						"from Area File",cfg.add_from_echolists_only ? "No":"Yes");
+					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%u","Maximum Backups to Maintain of Area File"
+						,cfg.areafile_backups);
 					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Circular Path Detection"
 						,cfg.check_path ? "Enabled" : "Disabled");
+					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Relay Filtered Messages"
+						,cfg.relay_filtered_msgs ? "Yes" : "No");
 					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Outbound Bundle Attachments"
 						,cfg.trunc_bundles ? "Truncate" : "Delete");
 					if(cfg.zone_blind)
@@ -1121,19 +1353,19 @@ int main(int argc, char **argv)
 						strcpy(str,"Disabled");
 					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Zone Blind SEEN-BY and PATH Lines", str);
 					if(cfg.max_echomail_age)
-						sprintf(str,"%1.0f days", ((float)cfg.max_echomail_age) / (24.0*60.0*60.0));
+						duration_to_vstr(cfg.max_echomail_age, str, sizeof(str));
 					else
 						strcpy(str, "None");
 					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Maximum Age of Imported EchoMail", str);
 					opt[i][0]=0;
-					j=uifc.list(WIN_ACT|WIN_RHT|WIN_BOT,0,0,64,&j,0,"EchoMail Settings",opt);
+					j=uifc.list(WIN_ACT|WIN_MID|WIN_SAV,0,0,0,&echomail_opt,0,"EchoMail Settings",opt);
 					if(j==-1)
 						break;
 					switch(j) {
 						case 0:
 				uifc.helpbuf=
-				"~ Area Manager ~\r\n\r\n"
-				"User to notify of AreaFix activity and errors.\r\n";
+				"~ Area Manager ~\n\n"
+				"User to notify of AreaFix activity and errors.\n";
 							uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Area Manager (user name or alias)"
 								,cfg.areamgr
 								,LEN_ALIAS,K_EDIT);
@@ -1141,9 +1373,9 @@ int main(int argc, char **argv)
 
 						case 1:
 				uifc.helpbuf=
-				"~ Maximum Packet Size ~\r\n\r\n"
-				"This is the maximum file size that SBBSecho will create when placing\r\n"
-				"outgoing messages into packets.  The default max size is 250 Kilobytes.\r\n";
+				"~ Maximum Packet Size ~\n\n"
+				"This is the maximum file size that SBBSecho will create when placing\n"
+				"outgoing messages into packets.  The default max size is 250 Kilobytes.\n";
 							sprintf(str,"%lu",cfg.maxpktsize);
 							uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Maximum Packet Size (in Bytes)",str
 								,9,K_EDIT|K_NUMBER);
@@ -1152,9 +1384,9 @@ int main(int argc, char **argv)
 
 						case 2:
 				uifc.helpbuf=
-				"~ Maximum Bundle Size ~\r\n\r\n"
-				"This is the maximum file size that SBBSecho will create when placing\r\n"
-				"outgoing packets into bundles.  The default max size is 250 Kilobytes.\r\n";
+				"~ Maximum Bundle Size ~\n\n"
+				"This is the maximum file size that SBBSecho will create when placing\n"
+				"outgoing packets into bundles.  The default max size is 250 Kilobytes.\n";
 							sprintf(str,"%lu",cfg.maxbdlsize);
 							uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Maximum Bundle Size (in Bytes)",str
 								,9,K_EDIT|K_NUMBER);
@@ -1185,14 +1417,6 @@ int main(int argc, char **argv)
 							}
 							break;
 						case 6:
-							k = cfg.add_from_echolists_only;
-							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
-								,"Allow Add from Area File",uifcYesNoOpts)) {
-								case 0:	cfg.add_from_echolists_only = false;	break;
-								case 1:	cfg.add_from_echolists_only = true;		break;
-							}
-							break;
-						case 7:
 							k = !cfg.strip_lf;
 							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
 								,"Strip Line Feeds",uifcYesNoOpts)) {
@@ -1200,7 +1424,29 @@ int main(int argc, char **argv)
 								case 1:	cfg.strip_lf = false;	break;
 							}
 							break;
+						case 7:
+							k = !cfg.auto_add_subs;
+							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
+								,"Automatically Add New Sub-boards to Area File",uifcYesNoOpts)) {
+								case 0:	cfg.auto_add_subs = true;	break;
+								case 1:	cfg.auto_add_subs = false;	break;
+							}
+							break;
 						case 8:
+							k = cfg.add_from_echolists_only;
+							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
+								,"Allow AreaFix-Add from Area File",uifcYesNoOpts)) {
+								case 0:	cfg.add_from_echolists_only = false;	break;
+								case 1:	cfg.add_from_echolists_only = true;		break;
+							}
+							break;
+						case 9:
+							sprintf(str, "%u", cfg.areafile_backups);
+							if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Total Area File Backups to Maintain"
+								,str, 5, K_EDIT|K_NUMBER) >= 0)
+								cfg.areafile_backups = atoi(str);
+							break;
+						case 10:
 							k = !cfg.check_path;
 							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
 								,"Circular Path Detection",uifcYesNoOpts)) {
@@ -1208,7 +1454,15 @@ int main(int argc, char **argv)
 								case 1:	cfg.check_path = false;	break;
 							}
 							break;
-						case 9:
+						case 11:
+							k = !cfg.check_path;
+							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
+								,"Relay Filtered EchoMail Messages",uifcYesNoOpts)) {
+								case 0:	cfg.relay_filtered_msgs = true;		break;
+								case 1:	cfg.relay_filtered_msgs = false;	break;
+							}
+							break;
+						case 12:
 						{
 							k = cfg.trunc_bundles;
 							char* opt[] = {"Delete after Sent", "Truncate after Sent", NULL };
@@ -1219,7 +1473,7 @@ int main(int argc, char **argv)
 							}
 							break;
 						}
-						case 10:
+						case 13:
 							k = !cfg.zone_blind;
 							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Zone Blind",uifcYesNoOpts)) {
 								case 0:
@@ -1237,36 +1491,36 @@ int main(int argc, char **argv)
 									break;
 							}
 							break;
-						case 11:
+						case 14:
 							uifc.helpbuf=
-							"~ Maximum Age of Imported EchoMail ~\r\n\r\n"
-							"Maximum age (in days) of EchoMail that may be imported. The age is based\r\n"
-							"on the date supplied in the message header and may be incorrect in some\r\n"
-							"conditions (e.g. erroneous software or incorrect system date).\r\n"
+							"~ Maximum Age of Imported EchoMail ~\n\n"
+							"Maximum age of EchoMail that may be imported. The age is based\n"
+							"on the date supplied in the message header and may be incorrect in some\n"
+							"conditions (e.g. erroneous software or incorrect system date).\n"
 							"Set this value to `0` to disable this feature (no maximum age imposed)."
 							;
 							if(cfg.max_echomail_age)
-								sprintf(str,"%1.0f", cfg.max_echomail_age / (24.0*60.0*60.0));
+								duration_to_vstr(cfg.max_echomail_age, str, sizeof(str));
 							else
 								strcpy(str, "None");
-							if(uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Maximum EchoMail Age (in Days)"
-								,str, 5, K_EDIT) >= 0)
-								cfg.max_echomail_age = (long) (strtod(str, NULL) * (24.0*60.0*60.0));
+							if(uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Maximum EchoMail Age"
+								,str, 10, K_EDIT) >= 0)
+								cfg.max_echomail_age = (ulong)parse_duration(str);
 							break;
 
 					} 
 				}
 				break;
 
-			case 3:	/* Archive Types */
+			case 2:	/* Archive Types */
 				i=0;
 				while(1) {
 					uifc.helpbuf=
-	"~ Archive Types ~\r\n\r\n"
-	"These are the archive file types that have been configured along with\r\n"
-	"their corresponding archive programs and command-lines for the packing\r\n"
-	"and unpacking of EchoMail bundle files.\r\n"
-	"\r\n"
+	"~ Archive Types ~\n\n"
+	"These are the archive file types that have been configured along with\n"
+	"their corresponding archive programs and command-lines for the packing\n"
+	"and unpacking of EchoMail bundle files.\n"
+	"\n"
 	"The corresponding archive programs are sometimes referred to as `packers`."
 	;
 					for(u=0;u<cfg.arcdefs;u++)
@@ -1276,7 +1530,7 @@ int main(int argc, char **argv)
 						| WIN_INSACT | WIN_DELACT | WIN_XTR;
 					if(savarcdef.name[0])
 						mode |= WIN_PUT;
-					i=uifc.list(mode,0,0,0,&i,0,"Archive Types",opt);
+					i=uifc.list(mode,0,0,0,&archive_opt,0,"Archive Types",opt);
 					if(i==-1)
 						break;
 					int msk = i & MSK_ON;
@@ -1284,8 +1538,8 @@ int main(int argc, char **argv)
 					if (msk == MSK_INS) {
 						str[0]=0;
 	uifc.helpbuf=
-	"~ Archive Type ~\r\n\r\n"
-	"This is the identifying name of the archiving program (packer).\r\n";
+	"~ Archive Type ~\n\n"
+	"This is the identifying name of the archiving program (packer).\n";
 						if(uifc.input(WIN_MID,0,0
 							,"Archive Type",str,25,K_EDIT|K_UPPER)<1)
 							continue;
@@ -1349,15 +1603,15 @@ int main(int argc, char **argv)
 							,cfg.arcdef[i].unpack);
 						opt[j][0]=0;
 						SAFEPRINTF(str,"Archive Type - %s", cfg.arcdef[i].name);
-						k=uifc.list(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,0,0,60,&packop,0,str,opt);
+						k=uifc.list(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,0,0,0,&packop,0,str,opt);
 						if(k==-1)
 							break;
 						switch(k) {
 							case 0:
 								uifc.helpbuf=
-								"~ Archive Type ~\r\n\r\n"
-								"This is the identifying name of the archive file type. Usually this name\r\n"
-								"corresponds with the common file extension or suffix denoting this type\r\n"
+								"~ Archive Type ~\n\n"
+								"This is the identifying name of the archive file type. Usually this name\n"
+								"corresponds with the common file extension or suffix denoting this type\n"
 								"of archive file (e.g. `zip`, `arc`, etc.)."
 								;
 								uifc.input(WIN_MID|WIN_SAV,0,0
@@ -1367,10 +1621,10 @@ int main(int argc, char **argv)
 								break;
 							case 1:
 								uifc.helpbuf=
-								"~ Archive Signature ~\r\n\r\n"
-								"This is the identifying signature of the archive file format (in\r\n"
-								"hexadecimal notation).  This signature is used in combination with the\r\n"
-								"Archive `Signature Offset` for the automatic detection of proper archive\r\n"
+								"~ Archive Signature ~\n\n"
+								"This is the identifying signature of the archive file format (in\n"
+								"hexadecimal notation).  This signature is used in combination with the\n"
+								"Archive `Signature Offset` for the automatic detection of proper archive\n"
 								"program to extract (unarchive) inbound EchoMail bundle files."
 								;
 								uifc.input(WIN_MID|WIN_SAV,0,0
@@ -1380,10 +1634,10 @@ int main(int argc, char **argv)
 								break;
 							case 2:
 								uifc.helpbuf=
-								"~ Archive Signature Offset ~\r\n\r\n"
-								"This is the byte-offset of the identifying signature of the archive file\r\n"
-								"format.  This offset is used in combination with the Archive `Signature`\r\n"
-								"for the automatic detection of proper archive program to extract\r\n"
+								"~ Archive Signature Offset ~\n\n"
+								"This is the byte-offset of the identifying signature of the archive file\n"
+								"format.  This offset is used in combination with the Archive `Signature`\n"
+								"for the automatic detection of proper archive program to extract\n"
 								"(unarchive) inbound EchoMail bundle files."
 								;
 								sprintf(str,"%u",cfg.arcdef[i].byteloc);
@@ -1394,22 +1648,22 @@ int main(int argc, char **argv)
 								break;
 							case 3:
 								uifc.helpbuf=
-								"~ Pack Command Line ~\r\n\r\n"
-								"This is the command-line to execute to create an archive file of the\r\n"
-								"selected type.  The following command-line specifiers may be used for\r\n"
-								"dynamic variable replacement:\r\n"
-								"\r\n"
-								"  `%f`  The path/filename of the archive file to be created\r\n"
-								"  `%s`  The path/filename of the file(s) to be added to the archive\r\n"
-								"  `%!`  The Synchronet `exec` directory\r\n"
-								"  `%@`  The Synchronet `exec` directory only for non-Unix systems\r\n"
-								"  `%.`  Blank for Unix systems, '`.exe`' otherwise\r\n"
-								"  `%?`  The current platform description (e.g. 'linux', 'win32')\r\n"
-								"  `%j`  The Synchronet `data` directory\r\n"
-								"  `%k`  The Synchronet `ctrl` directory\r\n"
-								"  `%o`  The configured system operator name\r\n"
-								"  `%q`  The configured system QWK-ID\r\n"
-								"  `%g`  The configured temporary file directory\r\n"
+								"~ Pack Command Line ~\n\n"
+								"This is the command-line to execute to create an archive file of the\n"
+								"selected type.  The following command-line specifiers may be used for\n"
+								"dynamic variable replacement:\n"
+								"\n"
+								"  `%f`  The path/filename of the archive file to be created\n"
+								"  `%s`  The path/filename of the file(s) to be added to the archive\n"
+								"  `%!`  The Synchronet `exec` directory\n"
+								"  `%@`  The Synchronet `exec` directory only for non-Unix systems\n"
+								"  `%.`  Blank for Unix systems, '`.exe`' otherwise\n"
+								"  `%?`  The current platform description (e.g. 'linux', 'win32')\n"
+								"  `%j`  The Synchronet `data` directory\n"
+								"  `%k`  The Synchronet `ctrl` directory\n"
+								"  `%o`  The configured system operator name\n"
+								"  `%q`  The configured system QWK-ID\n"
+								"  `%g`  The configured temporary file directory\n"
 								;
 								uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Pack Command Line"
@@ -1418,22 +1672,22 @@ int main(int argc, char **argv)
 								break;
 							case 4:
 								uifc.helpbuf=
-								"~ Unpack Command Line ~\r\n\r\n"
-								"This is the command-line to execute to extract an archive file of the\r\n"
-								"selected type.  The following command-line specifiers may be used for\r\n"
-								"dynamic variable replacement:\r\n"
-								"\r\n"
-								"  `%f`  The path/filename of the archive file to be extracted\r\n"
-								"  `%s`  The path/filename of the file(s) to extracted from the archive\r\n"
-								"  `%!`  The Synchronet `exec` directory\r\n"
-								"  `%@`  The Synchronet `exec` directory only for non-Unix systems\r\n"
-								"  `%.`  Blank for Unix systems, '`.exe`' otherwise\r\n"
-								"  `%?`  The current platform description (e.g. 'linux', 'win32')\r\n"
-								"  `%j`  The Synchronet `data` directory\r\n"
-								"  `%k`  The Synchronet `ctrl` directory\r\n"
-								"  `%o`  The configured system operator name\r\n"
-								"  `%q`  The configured system QWK-ID\r\n"
-								"  `%g`  The configured temporary file directory\r\n"
+								"~ Unpack Command Line ~\n\n"
+								"This is the command-line to execute to extract an archive file of the\n"
+								"selected type.  The following command-line specifiers may be used for\n"
+								"dynamic variable replacement:\n"
+								"\n"
+								"  `%f`  The path/filename of the archive file to be extracted\n"
+								"  `%s`  The path/filename of the file(s) to extracted from the archive\n"
+								"  `%!`  The Synchronet `exec` directory\n"
+								"  `%@`  The Synchronet `exec` directory only for non-Unix systems\n"
+								"  `%.`  Blank for Unix systems, '`.exe`' otherwise\n"
+								"  `%?`  The current platform description (e.g. 'linux', 'win32')\n"
+								"  `%j`  The Synchronet `data` directory\n"
+								"  `%k`  The Synchronet `ctrl` directory\n"
+								"  `%o`  The configured system operator name\n"
+								"  `%q`  The configured system QWK-ID\n"
+								"  `%g`  The configured temporary file directory\n"
 								;
 								uifc.input(WIN_MID|WIN_SAV,0,0
 									,"Unpack Command Line"
@@ -1445,12 +1699,12 @@ int main(int argc, char **argv)
 				}
 				break;
 
-			case 7:
+			case 6:
 	uifc.helpbuf=
-	"~ Additional EchoLists ~\r\n\r\n"
-	"This feature allows you to specify lists of echoes, in `BACKBONE.NA`\r\n"
-	"format, which are utilized in `addition` to your Area File (e.g. \r\n"
-	"`areas.bbs`) for advanced AreaFix (Area Management) operations.\r\n";
+	"~ EchoLists ~\n\n"
+	"This feature allows you to specify lists of echoes, in `BACKBONE.NA`\n"
+	"format, which are utilized in `addition` to your Area File (e.g. \n"
+	"`areas.bbs`) for advanced AreaFix (Area Management) operations.\n";
 				i=0;
 				while(1) {
 					for(u=0;u<cfg.listcfgs;u++)
@@ -1460,7 +1714,7 @@ int main(int argc, char **argv)
 						| WIN_INSACT | WIN_DELACT | WIN_XTR;
 					if(savlistcfg.listpath[0])
 						mode |= WIN_PUT;
-					i=uifc.list(mode,0,0,0,&i,0,"Additional EchoLists",opt);
+					i=uifc.list(mode,0,0,0,&echolist_opt,0,"EchoLists",opt);
 					if(i==-1)
 						break;
 					int msk = i&MSK_ON;
@@ -1468,9 +1722,9 @@ int main(int argc, char **argv)
 					if (msk == MSK_INS) {
 						str[0]=0;
 	uifc.helpbuf=
-	"~ EchoList ~\r\n\r\n"
-	"This is the path and filename of the echolist file you wish\r\n"
-	"to add.\r\n";
+	"~ EchoList ~\n\n"
+	"This is the path and filename of the echolist file you wish\n"
+	"to add.\n";
 						if(uifc.input(WIN_MID|WIN_SAV,0,0
 							,"EchoList Path/Name",str,50,K_EDIT)<1)
 							continue;
@@ -1519,7 +1773,7 @@ int main(int argc, char **argv)
 					while(1) {
 						j=0;
 						uifc.helpbuf=
-						"Configuring an Additional EchoList"
+						"Configuring an EchoList"
 						;
 						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","EchoList Path/Name"
 							,cfg.listcfg[i].listpath);
@@ -1534,8 +1788,8 @@ int main(int argc, char **argv)
 						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","AreaFix Keys"
 							,strListCombine(cfg.listcfg[i].keys, str, sizeof(str), ","));
 						opt[j][0]=0;
-						SAFEPRINTF(str, "Additional EchoList - %s", getfname(cfg.listcfg[i].listpath));
-						k=uifc.list(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,0,0,60,&listop,0,str,opt);
+						SAFEPRINTF(str, "EchoList - %s", getfname(cfg.listcfg[i].listpath));
+						k=uifc.list(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,0,0,0,&listop,0,str,opt);
 						if(k==-1)
 							break;
 						switch(k) {
@@ -1570,9 +1824,9 @@ int main(int argc, char **argv)
 								break;
 							case 4:
 								uifc.helpbuf=
-								"~ AreaFix Keys ~\r\n\r\n"
-								"These keys determine which linked nodes have access to the current\r\n"
-								"echolist file via AreaFix requests (e.g. query, add, remove).\r\n";
+								"~ AreaFix Keys ~\n\n"
+								"These keys determine which linked nodes have access to the current\n"
+								"echolist file via AreaFix requests (e.g. query, add, remove).\n";
 								while(1) {
 									for(u=0; cfg.listcfg[i].keys!=NULL && cfg.listcfg[i].keys[u] != NULL;u++)
 										strcpy(opt[u],cfg.listcfg[i].keys[u]);
@@ -1586,7 +1840,7 @@ int main(int argc, char **argv)
 										x&=MSK_OFF;
 										str[0]=0;
 										if(uifc.input(WIN_MID|WIN_SAV,0,0
-											,"AreaFix Keys",str,SBBSECHO_MAX_KEY_LEN
+											,"AreaFix Key",str,SBBSECHO_MAX_KEY_LEN
 											,K_EDIT|K_UPPER)<1)
 											continue;
 										strListInsert(&cfg.listcfg[i].keys,str,x);
@@ -1610,7 +1864,7 @@ int main(int argc, char **argv)
 				}
 				break;
 
-			case 8:
+			case 7:
 				if(!sbbsecho_write_ini(&cfg))
 					uifc.msg("Error saving configuration file");
 				else {
@@ -1621,9 +1875,9 @@ int main(int argc, char **argv)
 			case -1:
 				if(uifc.changes) {
 		uifc.helpbuf=
-		"~ Save Configuration File ~\r\n\r\n"
-		"Select `Yes` to save the config file, `No` to quit without saving,\r\n"
-		"or hit ~ ESC ~ to go back to the menu.\r\n\r\n";
+		"~ Save Configuration File ~\n\n"
+		"Select `Yes` to save the config file, `No` to quit without saving,\n"
+		"or hit ~ ESC ~ to go back to the menu.\n\n";
 					i=0;
 					strcpy(opt[0],"Yes");
 					strcpy(opt[1],"No");
diff --git a/src/sbbs3/rechocfg.c b/src/sbbs3/rechocfg.c
index d6373a3afc574d771bdccb7eec6363b52ff0cf9b..f724f821a5fb863856f2f3530df65043f137464e 100644
--- a/src/sbbs3/rechocfg.c
+++ b/src/sbbs3/rechocfg.c
@@ -226,6 +226,8 @@ void get_default_echocfg(sbbsecho_cfg_t* cfg)
 	cfg->relay_filtered_msgs		= false;
 	cfg->umask						= 077;
 	cfg->areafile_backups			= 100;
+	cfg->cfgfile_backups			= 100;
+	cfg->auto_add_subs				= true;
 }
 
 char* pktTypeStringList[] = {"2+", "2e", "2.2", "2", NULL};		// Must match enum pkt_type
@@ -248,15 +250,15 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	/* Global/root section: */
 	/************************/
 	iniFreeStringList(cfg->sysop_alias_list);
-	SAFECOPY(cfg->inbound		, iniGetString(ini, ROOT_SECTION, "Inbound",		"../fido/nonsecure", value));
-	SAFECOPY(cfg->secure_inbound, iniGetString(ini, ROOT_SECTION, "SecureInbound", "../fido/inbound", value));
-	SAFECOPY(cfg->outbound		, iniGetString(ini, ROOT_SECTION, "Outbound",		"../fido/outbound", value));
-	SAFECOPY(cfg->areafile		, iniGetString(ini, ROOT_SECTION, "AreaFile",		"../data/areas.bbs", value));
-	SAFECOPY(cfg->badareafile	, iniGetString(ini, ROOT_SECTION, "BadAreaFile",	"../data/badareas.lst", value));
-	SAFECOPY(cfg->echostats		, iniGetString(ini, ROOT_SECTION, "EchoStats", "../data/echostats.ini", value));
-	SAFECOPY(cfg->logfile		, iniGetString(ini, ROOT_SECTION, "LogFile",		"../data/sbbsecho.log", value));
-	SAFECOPY(cfg->logtime		, iniGetString(ini, ROOT_SECTION, "LogTimeFormat",	"%Y-%m-%d %H:%M:%S", value));
-	SAFECOPY(cfg->temp_dir		, iniGetString(ini, ROOT_SECTION, "TempDirectory",	"../temp/sbbsecho", value));
+	SAFECOPY(cfg->inbound		, iniGetString(ini, ROOT_SECTION, "Inbound"			,DEFAULT_INBOUND		, value));
+	SAFECOPY(cfg->secure_inbound, iniGetString(ini, ROOT_SECTION, "SecureInbound"	,DEFAULT_SECURE_INBOUND	, value));
+	SAFECOPY(cfg->outbound		, iniGetString(ini, ROOT_SECTION, "Outbound"		,DEFAULT_OUTBOUND		, value));
+	SAFECOPY(cfg->areafile		, iniGetString(ini, ROOT_SECTION, "AreaFile"		,DEFAULT_AREA_FILE		, value));
+	SAFECOPY(cfg->badareafile	, iniGetString(ini, ROOT_SECTION, "BadAreaFile"		,DEFAULT_BAD_AREA_FILE	, value));
+	SAFECOPY(cfg->echostats		, iniGetString(ini, ROOT_SECTION, "EchoStats"		,DEFAULT_ECHOSTATS_FILE	, value));
+	SAFECOPY(cfg->logfile		, iniGetString(ini, ROOT_SECTION, "LogFile"			,DEFAULT_LOG_FILE		, value));
+	SAFECOPY(cfg->logtime		, iniGetString(ini, ROOT_SECTION, "LogTimeFormat"	,DEFAULT_LOG_TIME_FMT	, value));
+	SAFECOPY(cfg->temp_dir		, iniGetString(ini, ROOT_SECTION, "TempDirectory"	,DEFAULT_TEMP_DIR		, value));
 	SAFECOPY(cfg->outgoing_sem	, iniGetString(ini, ROOT_SECTION, "OutgoingSemaphore",	"", value));
 	cfg->log_level				= iniGetLogLevel(ini, ROOT_SECTION, "LogLevel", cfg->log_level);
 	cfg->strip_lf				= iniGetBool(ini, ROOT_SECTION, "StripLineFeeds", cfg->strip_lf);
@@ -269,6 +271,7 @@ bool sbbsecho_read_ini(sbbsecho_cfg_t* cfg)
 	cfg->relay_filtered_msgs	= iniGetBool(ini, ROOT_SECTION, "RelayFilteredMsgs", cfg->relay_filtered_msgs);
 	cfg->umask					= iniGetInteger(ini, ROOT_SECTION, "umask", cfg->umask);
 	cfg->areafile_backups		= iniGetInteger(ini, ROOT_SECTION, "AreaFileBackups", cfg->areafile_backups);
+	cfg->cfgfile_backups		= iniGetInteger(ini, ROOT_SECTION, "CfgFileBackups", cfg->cfgfile_backups);
 
 	/* EchoMail options: */
 	cfg->maxbdlsize				= (ulong)iniGetBytes(ini, ROOT_SECTION, "BundleSize", 1, cfg->maxbdlsize);
@@ -462,6 +465,9 @@ bool sbbsecho_write_ini(sbbsecho_cfg_t* cfg)
 	FILE* fp;
 	str_list_t	ini;
 
+	if(cfg->cfgfile_backups)
+		backup(cfg->cfgfile, cfg->cfgfile_backups, /* ren: */false);
+
 	if((fp=iniOpenFile(cfg->cfgfile, /* create: */true))==NULL)
 		return false;
 	ini = iniReadFile(fp);
@@ -477,6 +483,7 @@ bool sbbsecho_write_ini(sbbsecho_cfg_t* cfg)
 	iniSetString(&ini,		ROOT_SECTION, "Outbound"				,cfg->outbound					,NULL);
 	iniSetString(&ini,		ROOT_SECTION, "AreaFile"				,cfg->areafile					,NULL);
 	iniSetInteger(&ini,		ROOT_SECTION, "AreaFileBackups"			,cfg->areafile_backups			,NULL);
+	iniSetInteger(&ini,		ROOT_SECTION, "CfgFileBackups"			,cfg->cfgfile_backups			,NULL);
 	iniSetString(&ini,		ROOT_SECTION, "BadAreaFile"				,cfg->badareafile				,NULL);
 	iniSetString(&ini,		ROOT_SECTION, "EchoStats"				,cfg->echostats					,NULL);
 	if(cfg->logfile[0])
diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c
index ebc9d9e9a9a6046e7f957b64a0355c38158aba4f..faf77476d6e8a00959d4c861c6d51ecc1dcf67d2 100644
--- a/src/sbbs3/sbbsecho.c
+++ b/src/sbbs3/sbbsecho.c
@@ -1766,6 +1766,10 @@ bool alter_config(fidoaddr_t addr, const char* key, const char* value)
 {
 	FILE* fp;
 
+	static ulong alterations;
+	if(alterations++ == 0)
+		backup(cfg.cfgfile, cfg.cfgfile_backups, /* ren: */false);
+
 	if((fp=iniOpenFile(cfg.cfgfile, false)) == NULL) {
 		lprintf(LOG_ERR, "ERROR %d (%s) opening %s for altering configuration of node %s"
 			,errno, strerror(errno), cfg.cfgfile, smb_faddrtoa(&addr, NULL));
diff --git a/src/sbbs3/sbbsecho.h b/src/sbbs3/sbbsecho.h
index 19150711934abf3b789e6b77644edc91d78363d7..c82028af230138c3bd17a5b25343a6c3413a84f0 100644
--- a/src/sbbs3/sbbsecho.h
+++ b/src/sbbs3/sbbsecho.h
@@ -42,10 +42,20 @@
 #include "fidodefs.h"
 
 #define SBBSECHO_VERSION_MAJOR		3
-#define SBBSECHO_VERSION_MINOR		1
+#define SBBSECHO_VERSION_MINOR		2
 
 #define SBBSECHO_PRODUCT_CODE		0x12FF	/* from http://ftsc.org/docs/ftscprod.013 */
 
+#define DEFAULT_INBOUND				"../fido/nonsecure"
+#define DEFAULT_SECURE_INBOUND		"../fido/inbound"
+#define DEFAULT_OUTBOUND			"../fido/outbound"
+#define DEFAULT_AREA_FILE			"../data/areas.bbs"
+#define DEFAULT_BAD_AREA_FILE		"../data/badareas.lst"
+#define DEFAULT_ECHOSTATS_FILE		"../data/echostats.ini"
+#define DEFAULT_LOG_FILE			"../data/sbbsecho.log"
+#define DEFAULT_LOG_TIME_FMT		"%Y-%m-%d %H:%M:%S"
+#define DEFAULT_TEMP_DIR			"../temp/sbbsecho"
+
 enum mail_status {
 	 MAIL_STATUS_NORMAL
 	,MAIL_STATUS_HOLD
@@ -140,8 +150,9 @@ typedef struct {
 	char		logfile[MAX_PATH+1];	/* LOG path/filename */
 	char		logtime[64];			/* format of log timestamp */
 	char		cfgfile[MAX_PATH+1];	/* Configuration path/filename */
+	uint		cfgfile_backups;		/* Number of backups to keep of cfg file */
 	char		temp_dir[MAX_PATH+1];	/* Temporary file directory */
-	char		outgoing_sem[MAX_PATH+1];	/* Semaphore file to creat when there's outgoing data */
+	char		outgoing_sem[MAX_PATH+1];	/* Semaphore file to create/touch when there's outgoing data */
 	str_list_t	sysop_alias_list;		/* List of sysop aliases */
 	ulong		maxpktsize				/* Maximum size for packets */
 			   ,maxbdlsize;				/* Maximum size for bundles */