Skip to content
Snippets Groups Projects
echocfg.c 59.5 KiB
Newer Older
rswindell's avatar
rswindell committed
							}
rswindell's avatar
rswindell committed
							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"
							"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));
							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));
rswindell's avatar
rswindell committed

rswindell's avatar
rswindell committed
				j=0;
				while(1) {
					uifc.helpbuf=
rswindell's avatar
rswindell committed
	"~ EchoMail Settings ~\r\n"
	"\r\n"
rswindell's avatar
rswindell committed
	"`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"
rswindell's avatar
rswindell committed
	"`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"
rswindell's avatar
rswindell committed
	"`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"
rswindell's avatar
rswindell committed
	"    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"
	"`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"
rswindell's avatar
rswindell committed
	"`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"
rswindell's avatar
rswindell committed
	"`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"
rswindell's avatar
rswindell committed
	"    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"
rswindell's avatar
rswindell committed
	"    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"
rswindell's avatar
rswindell committed
	"`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"
rswindell's avatar
rswindell committed
	"    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"
	;

rswindell's avatar
rswindell committed
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s", "Area Manager",cfg.areamgr);
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%luK","Maximum Packet Size"
						,cfg.maxpktsize/1024UL);
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%luK","Maximum Bundle Size"
						,cfg.maxbdlsize/1024UL);
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Secure Operation"
						,cfg.secure_echomail ? "Yes":"No");
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%-3.3s","Notify Users of Received EchoMail"
						,cfg.echomail_notify ? "Yes":"No");
rswindell's avatar
rswindell committed
					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%s","Circular Path Detection"
						,cfg.check_path ? "Enabled" : "Disabled");
rswindell's avatar
rswindell committed
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Outbound Bundle Attachments"
						,cfg.trunc_bundles ? "Truncate" : "Delete");
					if(cfg.zone_blind)
						sprintf(str,"Zones 1-%u", cfg.zone_blind_threshold);
					else
						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));
					else
						strcpy(str, "None");
					snprintf(opt[i++],MAX_OPLN-1,"%-45.45s%s","Maximum Age of Imported EchoMail", str);
rswindell's avatar
rswindell committed
					opt[i][0]=0;
					j=uifc.list(WIN_ACT|WIN_RHT|WIN_BOT,0,0,64,&j,0,"EchoMail Settings",opt);
rswindell's avatar
rswindell committed
				uifc.helpbuf=
				"~ Area Manager ~\r\n\r\n"
				"User to notify of AreaFix activity and errors.\r\n";
							uifc.input(WIN_MID|WIN_BOT|WIN_SAV,0,0,"Area Manager (user name or alias)"
								,cfg.areamgr
								,LEN_ALIAS,K_EDIT);
rswindell's avatar
rswindell committed

rswindell's avatar
rswindell committed
				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";
							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);
							cfg.maxpktsize=atol(str);
rswindell's avatar
rswindell committed

rswindell's avatar
rswindell committed
				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";
							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);
							cfg.maxbdlsize=atol(str);
rswindell's avatar
rswindell committed
							k = !cfg.secure_echomail;
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
								,"Secure Operation",uifcYesNoOpts)) {
								case 0:	cfg.secure_echomail = true;		break;
								case 1:	cfg.secure_echomail = false;	break;
							}
							k = !cfg.echomail_notify;
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
								,"Notify Users",uifcYesNoOpts)) {
								case 0:	cfg.echomail_notify = true;		break;
								case 1:	cfg.echomail_notify = false;	break;
							}
							break;
						case 5:
rswindell's avatar
rswindell committed
							k = !cfg.convert_tear;
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
								,"Convert Tear Lines",uifcYesNoOpts)) {
								case 0:	cfg.convert_tear = true;	break;
								case 1:	cfg.convert_tear = false;	break;
							}
rswindell's avatar
rswindell committed
							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;
							}
rswindell's avatar
rswindell committed
							k = !cfg.strip_lf;
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
								,"Strip Line Feeds",uifcYesNoOpts)) {
								case 0:	cfg.strip_lf = true;	break;
								case 1:	cfg.strip_lf = false;	break;
							}
rswindell's avatar
rswindell committed
							k = !cfg.check_path;
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
								,"Circular Path Detection",uifcYesNoOpts)) {
								case 0:	cfg.check_path = true;	break;
								case 1:	cfg.check_path = false;	break;
							}
rswindell's avatar
rswindell committed
						{
							k = cfg.trunc_bundles;
							char* opt[] = {"Delete after Sent", "Truncate after Sent", NULL };
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
								,"Outbound Bundles",opt)) {
								case 0:	cfg.trunc_bundles = false;	break;
								case 1:	cfg.trunc_bundles = true;	break;
							}
rswindell's avatar
rswindell committed
						}
rswindell's avatar
rswindell committed
							k = !cfg.zone_blind;
							switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0,"Zone Blind",uifcYesNoOpts)) {
								case 0:
									cfg.zone_blind = true;
									uifc.helpbuf=
									"Zone Blind Threshold";
									sprintf(str,"%u",cfg.zone_blind_threshold);
									if(uifc.input(WIN_MID|WIN_SAV,0,0
										,"Zone Blind Threshold (highest zone in the blind range)"
										, str, 5, K_EDIT|K_NUMBER) >= 0)
										cfg.zone_blind_threshold = (uint16_t)atol(str);
									break;
								case 1:
									cfg.zone_blind = false;
									break;
							}
rswindell's avatar
rswindell committed
							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"
							"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));
							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));
rswindell's avatar
rswindell committed

rswindell's avatar
rswindell committed

			case 3:	/* Archive Types */
rswindell's avatar
rswindell committed
					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"
	"The corresponding archive programs are sometimes referred to as `packers`."
	;
					for(u=0;u<cfg.arcdefs;u++)
rswindell's avatar
rswindell committed
						snprintf(opt[u],MAX_OPLN-1,"%-30.30s",cfg.arcdef[u].name);
					int mode = WIN_SAV | WIN_INS | WIN_DEL | WIN_ACT | WIN_GET 
						| 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);
					if(i==-1)
						break;
					if((i&MSK_ON)==MSK_INS) {
						i&=MSK_OFF;
						str[0]=0;
	uifc.helpbuf=
rswindell's avatar
rswindell committed
	"~ Archive Type ~\r\n\r\n"
	"This is the identifying name of the archiving program (packer).\r\n";
						if(uifc.input(WIN_MID,0,0
rswindell's avatar
rswindell committed
							,"Archive Type",str,25,K_EDIT|K_UPPER)<1)
						if((cfg.arcdef=(arcdef_t *)realloc(cfg.arcdef
							,sizeof(arcdef_t)*(cfg.arcdefs+1)))==NULL) {
							printf("\nMemory Allocation Error\n");
						for(j=cfg.arcdefs;j>i;j--)
							memcpy(&cfg.arcdef[j],&cfg.arcdef[j-1]
								,sizeof(arcdef_t));
							strcpy(cfg.arcdef[j].name
								,cfg.arcdef[j-1].name);
						cfg.arcdefs++;
						memset(&cfg.arcdef[i],0,sizeof(arcdef_t));
						strcpy(cfg.arcdef[i].name,str);
					if((i&MSK_ON)==MSK_DEL || (i&MSK_ON) == MSK_CUT) {
						int msk = i&MSK_ON;
						if(msk == MSK_CUT)
							memcpy(&savarcdef, &cfg.arcdef[i], sizeof(arcdef_t));
						cfg.arcdefs--;
						if(cfg.arcdefs<=0) {
							cfg.arcdefs=0;
						for(u=i;u<cfg.arcdefs;u++)
							memcpy(&cfg.arcdef[u],&cfg.arcdef[u+1]
								,sizeof(arcdef_t));
						if((cfg.arcdef=(arcdef_t *)realloc(cfg.arcdef
							,sizeof(arcdef_t)*(cfg.arcdefs)))==NULL) {
							printf("\nMemory Allocation Error\n");
					if((i&MSK_ON)==MSK_GET) {
						i&=MSK_OFF;
						memcpy(&savarcdef,&cfg.arcdef[i],sizeof(arcdef_t));
					if((i&MSK_ON)==MSK_PUT) {
						i&=MSK_OFF;
						memcpy(&cfg.arcdef[i],&savarcdef,sizeof(arcdef_t));
rswindell's avatar
rswindell committed
						uifc.helpbuf=
	"Archive Type and Program configuration";
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Archive Type"
							,cfg.arcdef[i].name);
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Signature"
							,cfg.arcdef[i].hexid);
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %u","Signature Offset"
							,cfg.arcdef[i].byteloc);
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Pack Command Line"
							,cfg.arcdef[i].pack);
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Unpack Command Line"
							,cfg.arcdef[i].unpack);
						opt[j][0]=0;
rswindell's avatar
rswindell committed
						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);
						if(k==-1)
							break;
						switch(k) {
							case 0:
rswindell's avatar
rswindell committed
								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"
								"of archive file (e.g. `zip`, `arc`, etc.)."
								;
								uifc.input(WIN_MID|WIN_SAV,0,0
rswindell's avatar
rswindell committed
									,"Archive Type"
									,cfg.arcdef[i].name,sizeof(cfg.arcdef[i].name)-1
									,K_EDIT|K_UPPER);
								break;
							case 1:
rswindell's avatar
rswindell committed
								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"
								"program to extract (unarchive) inbound EchoMail bundle files."
								;
								uifc.input(WIN_MID|WIN_SAV,0,0
rswindell's avatar
rswindell committed
									,"Archive Signature"
									,cfg.arcdef[i].hexid,sizeof(cfg.arcdef[i].hexid)-1
									,K_EDIT|K_UPPER);
								break;
							case 2:
rswindell's avatar
rswindell committed
								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"
								"(unarchive) inbound EchoMail bundle files."
								;
								sprintf(str,"%u",cfg.arcdef[i].byteloc);
rswindell's avatar
rswindell committed
								if(uifc.input(WIN_MID|WIN_SAV,0,0
									,"Archive Signature Offset",str,5
									,K_NUMBER|K_EDIT) > 0)
									cfg.arcdef[i].byteloc=atoi(str);
rswindell's avatar
rswindell committed
								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"
								;
								uifc.input(WIN_MID|WIN_SAV,0,0
rswindell's avatar
rswindell committed
									,"Pack Command Line"
									,cfg.arcdef[i].pack,sizeof(cfg.arcdef[i].pack)-1
rswindell's avatar
rswindell committed
								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"
								;
								uifc.input(WIN_MID|WIN_SAV,0,0
rswindell's avatar
rswindell committed
									,"Unpack Command Line"
									,cfg.arcdef[i].unpack,sizeof(cfg.arcdef[i].unpack)-1
rswindell's avatar
rswindell committed

			case 7:
rswindell's avatar
rswindell committed
	"~ 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";
					for(u=0;u<cfg.listcfgs;u++)
rswindell's avatar
rswindell committed
						snprintf(opt[u],MAX_OPLN-1,"%s",cfg.listcfg[u].listpath);
					int mode = WIN_SAV | WIN_INS | WIN_DEL | WIN_ACT | WIN_GET 
						| 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);
					if((i&MSK_ON)==MSK_INS) {
						i&=MSK_OFF;
						str[0]=0;
	uifc.helpbuf=
rswindell's avatar
rswindell committed
	"~ EchoList ~\r\n\r\n"
	"This is the path and filename of the echolist file you wish\r\n"
	"to add.\r\n";
						if(uifc.input(WIN_MID|WIN_SAV,0,0
rswindell's avatar
rswindell committed
							,"EchoList Path/Name",str,50,K_EDIT)<1)
						if((cfg.listcfg=(echolist_t *)realloc(cfg.listcfg
							,sizeof(echolist_t)*(cfg.listcfgs+1)))==NULL) {
							printf("\nMemory Allocation Error\n");
						for(j=cfg.listcfgs;j>i;j--)
							memcpy(&cfg.listcfg[j],&cfg.listcfg[j-1]
								,sizeof(echolist_t));
						cfg.listcfgs++;
						memset(&cfg.listcfg[i],0,sizeof(echolist_t));
						strcpy(cfg.listcfg[i].listpath,str);
					if((i&MSK_ON)==MSK_DEL || (i&MSK_ON) == MSK_CUT) {
						int msk = i&MSK_ON;
						if(msk == MSK_CUT)
							memcpy(&savlistcfg, &cfg.listcfg[i], sizeof(echolist_t));
						cfg.listcfgs--;
						if(cfg.listcfgs<=0) {
							cfg.listcfgs=0;
						for(u=i;u<cfg.listcfgs;u++)
							memcpy(&cfg.listcfg[u],&cfg.listcfg[u+1]
								,sizeof(echolist_t));
						if((cfg.listcfg=(echolist_t *)realloc(cfg.listcfg
							,sizeof(echolist_t)*(cfg.listcfgs)))==NULL) {
							printf("\nMemory Allocation Error\n");
					if((i&MSK_ON)==MSK_GET) {
						i&=MSK_OFF;
						memcpy(&savlistcfg,&cfg.listcfg[i],sizeof(echolist_t));
					if((i&MSK_ON)==MSK_PUT) {
						i&=MSK_OFF;
						memcpy(&cfg.listcfg[i],&savlistcfg,sizeof(echolist_t));
rswindell's avatar
rswindell committed
						uifc.helpbuf=
						"Configuring an Additional EchoList"
						;
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","EchoList Path/Name"
							,cfg.listcfg[i].listpath);
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Hub Address"
							,(cfg.listcfg[i].hub.zone) ?
							 faddrtoa(&cfg.listcfg[i].hub) : "None");
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Forward Password"
							,(cfg.listcfg[i].password[0]) ?
							 cfg.listcfg[i].password : "None");
rswindell's avatar
rswindell committed
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","Forward Requests"
							,cfg.listcfg[i].forward ? "Yes" : "No");
						snprintf(opt[j++],MAX_OPLN-1,"%-30.30s %s","AreaFix Keys"
rswindell's avatar
rswindell committed
							,strListCombine(cfg.listcfg[i].keys, str, sizeof(str), ","));
rswindell's avatar
rswindell committed
						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);
rswindell's avatar
rswindell committed
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"EchoList Path/Name"
									,cfg.listcfg[i].listpath,sizeof(cfg.listcfg[i].listpath)-1
									,K_EDIT);
rswindell's avatar
rswindell committed
								if(cfg.listcfg[i].hub.zone)
									strcpy(str,faddrtoa(&cfg.listcfg[i].hub));
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Hub Address",str
									,25,K_EDIT);
								if(str[0])
rswindell's avatar
rswindell committed
									cfg.listcfg[i].hub=atofaddr(str);
rswindell's avatar
rswindell committed
									memset(&cfg.listcfg[i].hub,0
										,sizeof(faddr_t));
								break;
							case 2:
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Password to use when forwarding requests"
rswindell's avatar
rswindell committed
									,cfg.listcfg[i].password,sizeof(cfg.listcfg[i].password)-1
									,K_EDIT|K_UPPER);
rswindell's avatar
rswindell committed
								cfg.listcfg[i].forward = !cfg.listcfg[i].forward;
								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";
rswindell's avatar
rswindell committed
									for(u=0; cfg.listcfg[i].keys!=NULL && cfg.listcfg[i].keys[u] != NULL;u++)
										strcpy(opt[u],cfg.listcfg[i].keys[u]);
									x=uifc.list(WIN_SAV|WIN_INS|WIN_DEL|WIN_ACT|
										WIN_XTR|WIN_INSACT|WIN_DELACT|WIN_RHT
										,0,0,0,&x,0,"AreaFix keys",opt);
									if(x==-1)
										break;
									if((x&MSK_ON)==MSK_INS) {
										x&=MSK_OFF;
										str[0]=0;
										if(uifc.input(WIN_MID|WIN_SAV,0,0
											,"AreaFix Keys",str,SBBSECHO_MAX_KEY_LEN
											,K_EDIT|K_UPPER)<1)
											continue;
rswindell's avatar
rswindell committed
										strListInsert(&cfg.listcfg[i].keys,str,x);
									if((x&MSK_ON)==MSK_DEL) {
										x&=MSK_OFF;
rswindell's avatar
rswindell committed
										strListRemove(&cfg.listcfg[i].keys,x);
rswindell's avatar
rswindell committed
									SAFECOPY(str,cfg.listcfg[i].keys[x]);
										uifc.input(WIN_MID|WIN_SAV,0,0,"AreaFix Keys"
rswindell's avatar
rswindell committed
											,str,SBBSECHO_MAX_KEY_LEN,K_EDIT|K_UPPER);
										strListReplace(cfg.listcfg[i].keys,x,str);
rswindell's avatar
rswindell committed
			case 8:
				if(!sbbsecho_write_ini(&cfg))
					uifc.msg("Error saving configuration file");
				else {
					orig_cfg = cfg;
					uifc.changes = FALSE;
rswindell's avatar
rswindell committed
				break;
			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";
					i=0;
					strcpy(opt[0],"Yes");
					strcpy(opt[1],"No");
					opt[2][0]=0;
					i=uifc.list(WIN_MID,0,0,0,&i,0,"Save Config File",opt);
					if(i==-1) break;
					if(i) {uifc.bail(); exit(0);}
					if(!sbbsecho_write_ini(&cfg))
						uifc.msg("Error saving configuration file");