echocfg.c 43.7 KB
Newer Older
1
/* echocfg.c */
2

3
4
5
6
7
8
9
10
/* SBBSecho configuration utility 											*/

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright 2015 Rob Swindell - http://www.synchro.net/copyright.html		*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/
37
38
39

/* Portions written by Allen Christiansen 1994-1996 						*/

40
#include <stdio.h>
41

42
#undef JAVASCRIPT
43

rswindell's avatar
rswindell committed
44
45
46
/* XPDEV Headers */
#include "gen_defs.h"

47
48
#define __COLORS
#include "ciolib.h"
49
50
#include "uifc.h"
#include "sbbs.h"
51
52
53
54
#include "sbbsecho.h"

char **opt;

55
56
/* Declaration removed... why?  ToDo */
/* void uifc.bail(int code); */
57
58
59
60
61
62
63
64
65
int main();

long misc=0;
config_t cfg;

unsigned _stklen=16000;

uifcapi_t uifc;

66
67
68
void bail(int code)
{

69
70
	if(uifc.bail!=NULL)
		uifc.bail();
71
72
73
74
75
76
77
	exit(code);
}

/****************************************************************************/
/* Returns an ASCII string for FidoNet address 'addr'                       */
/****************************************************************************/
char *wcfaddrtoa(faddr_t* addr)
78
{
79
80
    static char str[25];
	char tmp[25];
81

82
	str[0]=0;
83
84
	if(addr->zone==0xffff)
		strcpy(str,"ALL");
85
	else if(addr->zone) {
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
		sprintf(str,"%u:",addr->zone);
		if(addr->net==0xffff)
			strcat(str,"ALL");
		else {
			sprintf(tmp,"%u/",addr->net);
			strcat(str,tmp);
			if(addr->node==0xffff)
				strcat(str,"ALL");
			else {
				sprintf(tmp,"%u",addr->node);
				strcat(str,tmp);
				if(addr->point==0xffff)
					strcat(str,".ALL");
				else if(addr->point) {
					sprintf(tmp,".%u",addr->point);
					strcat(str,tmp); 
				} 
			} 
		} 
	}
	return(str);
107
}
108

109
110
111
/* These correlate with the LOG_* definitions in syslog.h/gen_defs.h */
static char* logLevelStringList[] 
	= {"Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debugging", NULL};
112
113
114
115

int main(int argc, char **argv)
{
	char str[256],*p;
rswindell's avatar
rswindell committed
116
	int i,j,k,x,dflt,nodeop=0;
117
118
119
120
	FILE *stream;
	echolist_t savlistcfg;
	nodecfg_t savnodecfg;
	arcdef_t savarcdef;
121
	BOOL door_mode=FALSE;
122
	int		ciolib_mode=CIOLIB_MODE_AUTO;
123
	unsigned int u, u2;
124

125
126
	fprintf(stderr,"\nSBBSecho Configuration  Version %u.%02u  Copyright %s "
		"Rob Swindell\n\n",SBBSECHO_VERSION_MAJOR, SBBSECHO_VERSION_MINOR, __DATE__+7);
127

128
	memset(&cfg,0,sizeof(config_t));
129
130
131
132
	str[0]=0;
	for(i=1;i<argc;i++) {
		if(argv[i][0]=='-')
			switch(toupper(argv[i][1])) {
133
                case 'D':
134
					printf("NOTICE: The -d option is deprecated, use -id instead\r\n");
135
136
137
138
139
140
141
142
143
					SLEEP(2000);
                    door_mode=TRUE;
                    break;
                case 'L':
                    uifc.scrn_len=atoi(argv[i]+2);
                    break;
                case 'E':
                    uifc.esc_delay=atoi(argv[i]+2);
                    break;
144
				case 'I':
145
146
147
148
149
150
151
152
					switch(toupper(argv[i][2])) {
						case 'A':
							ciolib_mode=CIOLIB_MODE_ANSI;
							break;
						case 'C':
							ciolib_mode=CIOLIB_MODE_CURSES;
							break;
						case 0:
153
							printf("NOTICE: The -i option is deprecated, use -if instead\r\n");
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
							SLEEP(2000);
						case 'F':
							ciolib_mode=CIOLIB_MODE_CURSES_IBM;
							break;
						case 'X':
							ciolib_mode=CIOLIB_MODE_X;
							break;
						case 'W':
							ciolib_mode=CIOLIB_MODE_CONIO;
							break;
						case 'D':
		                    door_mode=TRUE;
		                    break;
						default:
							goto USAGE;
					}
170
171
172
173
174
175
176
					break;
		        case 'M':   /* Monochrome mode */
        			uifc.mode|=UIFC_MONO;
                    break;
                case 'C':
        			uifc.mode|=UIFC_COLOR;
                    break;
177
178
                case 'V':
                    textmode(atoi(argv[i]+2));
179
                    break;
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
                default:
					USAGE:
                    printf("\nusage: echocfg [ctrl_dir] [options]"
                        "\n\noptions:\n\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"
#ifdef __unix__
						"       X = X11 mode\r\n"
						"       C = Curses mode\r\n"
						"       F = Curses mode with forced IBM charset\r\n"
#else
						"       W = Win32 native mode\r\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"
                        );
        			exit(0);
201
202
203
204
205
		}
		else
			strcpy(str,argv[1]);
	}
	if(str[0]==0) {
206
207
208
209
210
211
212
213
214
215
216
217
		p=getenv("SBBSCTRL");
		if(!p) {
			p=getenv("SBBSNODE");
			if(!p) {
				printf("usage: echocfg [cfg_file]\n");
				exit(1); }
			strcpy(str,p);
			backslash(str);
			strcat(str,"../ctrl/sbbsecho.cfg"); }
		else {
			strcpy(str,p);
			backslash(str);
218
219
220
			strcat(str,"sbbsecho.cfg"); 
		} 
	}
221
	strcpy(cfg.cfgfile,str);
222

223
	read_echo_cfg();
224

225
	// savnum=0;
deuce's avatar
deuce committed
226
	if((opt=(char **)malloc(sizeof(char *)*300))==NULL) {
227
228
		uifc.bail();
		puts("memory allocation error\n");
229
230
		exit(1); 
	}
231
	for(i=0;i<300;i++)
deuce's avatar
deuce committed
232
		if((opt[i]=(char *)malloc(MAX_OPLN))==NULL) {
233
234
	      	uifc.bail();
			puts("memory allocation error\n");
235
236
			exit(1); 
		}
237
	uifc.size=sizeof(uifc);
238
239
240
241
242
243
244
245
	if(!door_mode) {
		i=initciolib(ciolib_mode);
		if(i!=0) {
    		printf("ciolib library init returned error %d\n",i);
    		exit(1);
		}
    	i=uifcini32(&uifc);  /* curses/conio/X/ANSI */
	}
246
	else
247
    	i=uifcinix(&uifc);  /* stdio */
248
249
250
251
252
253

	if(i!=0) {
		printf("uifc library init returned error %d\n",i);
		exit(1);
	}

254
	sprintf(str,"SBBSecho Configuration v%u.%02u",SBBSECHO_VERSION_MAJOR, SBBSECHO_VERSION_MINOR);
255
	uifc.scrn(str);
256

257
258
259
	dflt=0;
	while(1) {
		uifc.helpbuf=
260
	"~ SBBSecho Configuration ~\r\n\r\n"
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
	"Move through the various options using the arrow keys.  Select the\r\n"
	"highlighted options by pressing ENTER.\r\n\r\n";
		i=0;
		sprintf(opt[i++],"%-30.30s %s","Mailer Type"
			,misc&FLO_MAILER ? "Binkley/FLO":"FrontDoor/Attach");
		sprintf(opt[i++],"%-30.30s %luK","Maximum Packet Size"
			,cfg.maxpktsize/1024UL);
		sprintf(opt[i++],"%-30.30s %luK","Maximum Bundle Size"
			,cfg.maxbdlsize/1024UL);
		if(cfg.notify)
			sprintf(str,"User #%u",cfg.notify);
		else
			strcpy(str,"Disabled");
		sprintf(opt[i++],"%-30.30s %s","Areafix Failure Notification",str);
		sprintf(opt[i++],"Nodes...");
		sprintf(opt[i++],"Paths...");
277
		sprintf(opt[i++],"%-30.30s %s","Log Level",logLevelStringList[cfg.log_level]);
278
279
280
281
		sprintf(opt[i++],"Log Options...");
		sprintf(opt[i++],"Toggle Options...");
		sprintf(opt[i++],"Archive Programs...");
		sprintf(opt[i++],"Additional Echo Lists...");
rswindell's avatar
rswindell committed
282
		opt[i][0]=0;
283
284
		switch(uifc.list(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,52,&dflt,0
		,cfg.cfgfile,opt)) {
285

286
287
288
			case 0:
				misc^=FLO_MAILER;
				break;
289

290
291
			case 1:
	uifc.helpbuf=
292
	"~ Maximum Packet Size ~\r\n\r\n"
293
294
295
296
297
298
299
	"This is the maximum file size that SBBSecho will create when placing\r\n"
	"outgoing messages into packets.  The default size is 250k.\r\n";
				sprintf(str,"%lu",cfg.maxpktsize);
				uifc.input(WIN_MID|WIN_BOT,0,0,"Maximum Packet Size",str
					,9,K_EDIT|K_NUMBER);
				cfg.maxpktsize=atol(str);
				break;
300

301
302
			case 2:
	uifc.helpbuf=
303
	"~ Maximum Bundle Size ~\r\n\r\n"
304
305
306
307
308
309
310
	"This is the maximum file size that SBBSecho will create when placing\r\n"
	"outgoing packets into bundles.  The default size is 250k.\r\n";
				sprintf(str,"%lu",cfg.maxbdlsize);
				uifc.input(WIN_MID|WIN_BOT,0,0,"Maximum Bundle Size",str
					,9,K_EDIT|K_NUMBER);
				cfg.maxbdlsize=atol(str);
				break;
311

312
313
			case 3:
	uifc.helpbuf=
314
	"~ Areafix Failure Notification ~\r\n\r\n"
315
316
317
318
319
320
321
322
	"Setting this option to a user number (usually #1), enables the\r\n"
	"automatic notification of that user, via e-mail, of failed areafix\r\n"
	"attempts. Setting this option to 0, disables this feature.\r\n";
				sprintf(str,"%u",cfg.notify);
				uifc.input(WIN_MID|WIN_BOT,0,0,"Areafix Notification User Number",str
					,5,K_EDIT|K_NUMBER);
				cfg.notify=atoi(str);
				break;
323

324
325
			case 4:
	uifc.helpbuf=
326
	"~ Nodes... ~\r\n\r\n"
327
328
329
330
	"From this menu you can configure the area manager options for your\r\n"
	"uplink nodes.\r\n";
				i=0;
				while(1) {
331
332
333
					for(u=0;u<cfg.nodecfgs;u++)
						strcpy(opt[u],wcfaddrtoa(&cfg.nodecfg[u].faddr));
					opt[u][0]=0;
334
335
336
337
338
339
340
341
342
					i=uifc.list(WIN_ORG|WIN_INS|WIN_DEL|WIN_ACT|WIN_GET|WIN_PUT
						|WIN_INSACT|WIN_DELACT|WIN_XTR
						,0,0,0,&i,0,"Nodes",opt);
					if(i==-1)
						break;
					if((i&MSK_ON)==MSK_INS) {
						i&=MSK_OFF;
						str[0]=0;
	uifc.helpbuf=
343
	"~ Address ~\r\n\r\n"
344
345
346
347
348
	"This is the FidoNet style address of the node you wish to add\r\n";
						if(uifc.input(WIN_MID,0,0
							,"Node Address (ALL wildcard allowed)",str
							,25,K_EDIT)<1)
							continue;
deuce's avatar
deuce committed
349
						if((cfg.nodecfg=(nodecfg_t *)realloc(cfg.nodecfg
350
351
352
353
354
355
356
357
358
359
							,sizeof(nodecfg_t)*(cfg.nodecfgs+1)))==NULL) {
							printf("\nMemory Allocation Error\n");
							exit(1); }
						for(j=cfg.nodecfgs;j>i;j--)
							memcpy(&cfg.nodecfg[j],&cfg.nodecfg[j-1]
								,sizeof(nodecfg_t));
						cfg.nodecfgs++;
						memset(&cfg.nodecfg[i],0,sizeof(nodecfg_t));
						cfg.nodecfg[i].faddr=atofaddr(str);
						continue; }
360

361
362
363
364
365
366
					if((i&MSK_ON)==MSK_DEL) {
						i&=MSK_OFF;
						cfg.nodecfgs--;
						if(cfg.nodecfgs<=0) {
							cfg.nodecfgs=0;
							continue; }
367
368
						for(u=i;u<cfg.nodecfgs;u++)
							memcpy(&cfg.nodecfg[u],&cfg.nodecfg[u+1]
369
								,sizeof(nodecfg_t));
deuce's avatar
deuce committed
370
						if((cfg.nodecfg=(nodecfg_t *)realloc(cfg.nodecfg
371
372
373
							,sizeof(nodecfg_t)*(cfg.nodecfgs)))==NULL) {
							printf("\nMemory Allocation Error\n");
							exit(1); }
374
						continue; }
375
376
377
378
379
380
381
382
383
384
					if((i&MSK_ON)==MSK_GET) {
						i&=MSK_OFF;
						memcpy(&savnodecfg,&cfg.nodecfg[i],sizeof(nodecfg_t));
						continue; }
					if((i&MSK_ON)==MSK_PUT) {
						i&=MSK_OFF;
						memcpy(&cfg.nodecfg[i],&savnodecfg,sizeof(nodecfg_t));
						continue; }
					while(1) {
	uifc.helpbuf=
385
	"~ Node Options ~\r\n\r\n"
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
	"These are the configurable options available for this node.\r\n";
						j=0;
						sprintf(opt[j++],"%-20.20s %s","Address"
							,wcfaddrtoa(&cfg.nodecfg[i].faddr));
						sprintf(opt[j++],"%-20.20s %s","Archive Type"
							,cfg.nodecfg[i].arctype>cfg.arcdefs ?
							"None":cfg.arcdef[cfg.nodecfg[i].arctype].name);
						sprintf(opt[j++],"%-20.20s %s","Packet Type"
							,cfg.nodecfg[i].pkt_type==PKT_TWO ? "2"
							:cfg.nodecfg[i].pkt_type==PKT_TWO_TWO ? "2.2":"2+");
						sprintf(opt[j++],"%-20.20s %s","Packet Password"
							,cfg.nodecfg[i].pktpwd);
						sprintf(opt[j++],"%-20.20s %s","Areafix Password"
							,cfg.nodecfg[i].password);
						str[0]=0;
						for(k=0;k<cfg.nodecfg[i].numflags;k++) {
							strcat(str,cfg.nodecfg[i].flag[k].flag);
							strcat(str," "); }
						sprintf(opt[j++],"%-20.20s %s","Areafix Flags",str);
						sprintf(opt[j++],"%-20.20s %s","Status"
							,cfg.nodecfg[i].attr&ATTR_CRASH ? "Crash"
							:cfg.nodecfg[i].attr&ATTR_HOLD ? "Hold" : "None");
						sprintf(opt[j++],"%-20.20s %s","Direct"
							,cfg.nodecfg[i].attr&ATTR_DIRECT ? "Yes":"No");
						sprintf(opt[j++],"%-20.20s %s","Passive"
							,cfg.nodecfg[i].attr&ATTR_PASSIVE ? "Yes":"No");
						sprintf(opt[j++],"%-20.20s %s","Send Notify List"
							,cfg.nodecfg[i].attr&SEND_NOTIFY ? "Yes" : "No");
						if(misc&FLO_MAILER)
							sprintf(opt[j++],"%-20.20s %s","Route To"
								,cfg.nodecfg[i].route.zone
								? wcfaddrtoa(&cfg.nodecfg[i].route) : "Disabled");
						opt[j][0]=0;
						k=uifc.list(WIN_MID|WIN_ACT,0,0,40,&nodeop,0
							,wcfaddrtoa(&cfg.nodecfg[i].faddr),opt);
						if(k==-1)
							break;
						switch(k) {
							case 0:
	uifc.helpbuf=
426
	"~ Address ~\r\n\r\n"
427
428
429
430
431
432
433
434
435
	"This is the FidoNet style address of this node.\r\n";
								strcpy(str,wcfaddrtoa(&cfg.nodecfg[i].faddr));
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Node Address (ALL wildcard allowed)",str
									,25,K_EDIT|K_UPPER);
								cfg.nodecfg[i].faddr=atofaddr(str);
								break;
							case 1:
	uifc.helpbuf=
436
	"~ Archive Type ~\r\n\r\n"
437
438
	"This is the compression type that will be used for compressing packets\r\n"
	"to and decompressing packets from this node.\r\n";
439
440
441
442
443
444
445
								for(u=0;u<cfg.arcdefs;u++)
									strcpy(opt[u],cfg.arcdef[u].name);
								strcpy(opt[u++],"None");
								opt[u][0]=0;
								if(cfg.nodecfg[i].arctype<u)
									u=cfg.nodecfg[i].arctype;
								k=uifc.list(WIN_RHT|WIN_SAV,0,0,0,&u,0
446
447
448
									,"Archive Type",opt);
								if(k==-1)
									break;
449
								if((unsigned)k>=cfg.arcdefs)
450
451
452
453
454
455
									cfg.nodecfg[i].arctype=0xffff;
								else
									cfg.nodecfg[i].arctype=k;
								break;
							case 2:
	uifc.helpbuf=
456
	"~ Packet Type ~\r\n\r\n"
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
	"This is the packet header type that will be used in mail packets to\r\n"
	"this node.  SBBSecho defaults to using type 2.2.\r\n";
								j=0;
								strcpy(opt[j++],"2+");
								strcpy(opt[j++],"2.2");
								strcpy(opt[j++],"2");
								opt[j][0]=0;
								j=cfg.nodecfg[i].pkt_type;
								k=uifc.list(WIN_RHT|WIN_SAV,0,0,0,&j,0,"Packet Type"
									,opt);
								if(k==-1)
									break;
								cfg.nodecfg[i].pkt_type=k;
								break;
							case 3:
	uifc.helpbuf=
473
	"~ Packet Password ~\r\n\r\n"
474
475
476
477
478
479
480
481
	"This is an optional password that SBBSecho will place into packets\r\n"
	"destined for this node.\r\n";
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Packet Password (optional)"
									,cfg.nodecfg[i].pktpwd,8,K_EDIT|K_UPPER);
								break;
							case 4:
	uifc.helpbuf=
482
	"~ Areafix Password ~\r\n\r\n"
483
484
485
486
487
488
489
490
	"This is the password that will be used by this node when doing remote\r\n"
	"areamanager functions.\r\n";
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Areafix Password"
									,cfg.nodecfg[i].password,8,K_EDIT|K_UPPER);
								break;
							case 5:
	uifc.helpbuf=
491
	"~ Areafix Flag ~\r\n\r\n"
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
	"This is a flag to to be given to this node allowing access to one or\r\n"
	"more of the configured echo lists\r\n";
								while(1) {
									for(j=0;j<cfg.nodecfg[i].numflags;j++)
										strcpy(opt[j],cfg.nodecfg[i].flag[j].flag);
									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,"Areafix Flags",opt);
									if(k==-1)
										break;
									if((k&MSK_ON)==MSK_INS) {
										k&=MSK_OFF;
										str[0]=0;
										if(uifc.input(WIN_MID|WIN_SAV,0,0
											,"Areafix Flag",str,4
											,K_EDIT|K_UPPER)<1)
											continue;
										if((cfg.nodecfg[i].flag=(flag_t *)
deuce's avatar
deuce committed
511
											realloc(cfg.nodecfg[i].flag
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
											,sizeof(flag_t)*
											(cfg.nodecfg[i].numflags+1)))==NULL) {
											printf("\nMemory Allocation Error\n");
											exit(1); }
										for(j=cfg.nodecfg[i].numflags;j>i;j--)
											memcpy(&cfg.nodecfg[i].flag[j]
												,&cfg.nodecfg[i].flag[j-1]
												,sizeof(flag_t));
										cfg.nodecfg[i].numflags++;
										memset(&cfg.nodecfg[i].flag[k].flag
											,0,sizeof(flag_t));
										strcpy(cfg.nodecfg[i].flag[k].flag,str);
										continue; }

									if((k&MSK_ON)==MSK_DEL) {
										k&=MSK_OFF;
										cfg.nodecfg[i].numflags--;
										if(cfg.nodecfg[i].numflags<=0) {
											cfg.nodecfg[i].numflags=0;
											continue; }
										for(j=k;j<cfg.nodecfg[i].numflags;j++)
											strcpy(cfg.nodecfg[i].flag[j].flag
												,cfg.nodecfg[i].flag[j+1].flag);
										if((cfg.nodecfg[i].flag=(flag_t *)
deuce's avatar
deuce committed
536
											realloc(cfg.nodecfg[i].flag
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
											,sizeof(flag_t)*
											(cfg.nodecfg[i].numflags)))==NULL) {
											printf("\nMemory Allocation Error\n");
											exit(1); }
										continue; }
									strcpy(str,cfg.nodecfg[i].flag[k].flag);
									uifc.input(WIN_MID|WIN_SAV,0,0,"Areafix Flag"
										,str,4,K_EDIT|K_UPPER);
									strcpy(cfg.nodecfg[i].flag[k].flag,str);
									continue; }
								break;
							case 6:
								if(cfg.nodecfg[i].attr&ATTR_CRASH) {
									cfg.nodecfg[i].attr^=ATTR_CRASH;
									cfg.nodecfg[i].attr|=ATTR_HOLD;
									break; }
								if(cfg.nodecfg[i].attr&ATTR_HOLD) {
									cfg.nodecfg[i].attr^=ATTR_HOLD;
									break; }
								cfg.nodecfg[i].attr|=ATTR_CRASH;
								break;
							case 7:
								cfg.nodecfg[i].attr^=ATTR_DIRECT;
								break;
							case 8:
								cfg.nodecfg[i].attr^=ATTR_PASSIVE;
								break;
							case 9:
								cfg.nodecfg[i].attr^=SEND_NOTIFY;
								break;
							case 10:
	uifc.helpbuf=
569
	"~ Route To ~\r\n\r\n"
570
571
572
573
574
575
	"When using a FLO type mailer, this is an fido address to route mail\r\n"
	"for this node 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 (hub).\r\n";
576
577
578
579
580
581
								strcpy(str,wcfaddrtoa(&cfg.nodecfg[i].route));
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Node Address to Route To",str
									,25,K_EDIT);
									if(str[0])
										cfg.nodecfg[i].route=atofaddr(str);
582
583
									else
										cfg.nodecfg[i].route.zone=0;
584
585
586
587
588
589
								break;
								} } }
				break;

			case 5:
	uifc.helpbuf=
590
	"~ Paths... ~\r\n\r\n"
591
592
593
	"From this menu you can configure the paths that SBBSecho will use\r\n"
	"when importing and exporting.\r\n";
				j=0;
594
				while(1) {
595
596
597
598
599
600
601
602
603
604
605
606
607
					i=0;
					sprintf(opt[i++],"%-30.30s %s","Inbound Directory"
						,cfg.inbound[0] ? cfg.inbound : "<Specified in SCFG>");
					sprintf(opt[i++],"%-30.30s %s","Secure Inbound (optional)"
						,cfg.secure[0] ? cfg.secure : "None Specified");
					sprintf(opt[i++],"%-30.30s %s","Outbound Directory"
						,cfg.outbound);
					sprintf(opt[i++],"%-30.30s %s","Area File"
						,cfg.areafile[0] ? cfg.areafile
						: "SCFG->data/areas.bbs");
					sprintf(opt[i++],"%-30.30s %s","Log File"
						,cfg.logfile[0] ? cfg.logfile
						: "SCFG->data/sbbsecho.log");
rswindell's avatar
rswindell committed
608
					opt[i][0]=0;
609
610
611
					j=uifc.list(WIN_MID|WIN_ACT,0,0,60,&j,0
						,"Paths and Filenames",opt);
					if(j==-1)
612
						break;
613
					switch(j) {
614
						case 0:
615
	uifc.helpbuf=
616
	"~ Inbound Directory ~\r\n\r\n"
617
618
619
620
621
	"This is the complete path (drive and directory) where your front\r\n"
	"end mailer stores, and where SBBSecho will look for, incoming message\r\n"
	"bundles and packets.";
							uifc.input(WIN_MID|WIN_SAV,0,0,"Inbound",cfg.inbound
								,50,K_EDIT);
622
							break;
623

624
						case 1:
625
	uifc.helpbuf=
626
	"~ Secure Inbound Directory ~\r\n\r\n"
627
628
629
630
631
	"This is the complete path (drive and directory) where your front\r\n"
	"end mailer stores, and where SBBSecho will look for, incoming message\r\n"
	"bundles and packets for SECURE sessions.";
							uifc.input(WIN_MID|WIN_SAV,0,0,"Secure Inbound",cfg.secure
								,50,K_EDIT);
632
							break;
633

634
						case 2:
635
	uifc.helpbuf=
636
	"~ Outbound Directory ~\r\n\r\n"
637
638
639
640
641
	"This is the complete path (drive and directory) where your front\r\n"
	"end mailer will look for, and where SBBSecho will place, outgoing\r\n"
	"message bundles and packets.";
							uifc.input(WIN_MID|WIN_SAV,0,0,"Outbound",cfg.outbound
								,50,K_EDIT);
642
							break;
643

644
						case 3:
645
	uifc.helpbuf=
646
	"~ Area File ~\r\n\r\n"
647
648
649
650
	"This is the complete path (drive, directory, and filename) of the\r\n"
	"file SBBSecho will use as your AREAS.BBS file.";
							uifc.input(WIN_MID|WIN_SAV,0,0,"Areafile",cfg.areafile
								,50,K_EDIT);
651
							break;
652

653
						case 4:
654
	uifc.helpbuf=
655
	"~ Log File ~\r\n\r\n"
656
657
658
659
660
661
662
663
	"This is the complete path (drive, directory, and filename) of the\r\n"
	"file SBBSecho will use to log information each time it is run.";
							uifc.input(WIN_MID|WIN_SAV,0,0,"Logfile",cfg.logfile
								,50,K_EDIT);
							break; } }
				break;
			case 6:
	uifc.helpbuf=
664
665
666
667
668
669
670
671
672
673
	"~ Log Level ~\r\n"
	"\r\n"
	"Select the minimum severity of log entries to be logged to the log file.";
				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 7:
	uifc.helpbuf=
674
	"~ Log Options ~\r\n"
675
676
	"\r\n"
	"Each loggable item can be toggled off or on from this menu. You must run\r\n"
677
	"`SBBSecho` with the `/L` command line option for any of these items to be\r\n"
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
	"logged.";
				j=0;
				while(1) {
					i=0;
					strcpy(opt[i++],"ALL");
					strcpy(opt[i++],"NONE");
					strcpy(opt[i++],"DEFAULT");
					sprintf(opt[i++],"%-35.35s%-3.3s","Ignored NetMail Messages"
						,cfg.log&LOG_IGNORED ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","NetMail for Unknown Users"
						,cfg.log&LOG_UNKNOWN ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Areafix NetMail Messages"
						,cfg.log&LOG_AREAFIX ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Imported NetMail Messages"
						,cfg.log&LOG_IMPORTED ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Packing Out-bound NetMail"
						,cfg.log&LOG_PACKING ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Routing Out-bound NetMail"
						,cfg.log&LOG_ROUTING ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","In-bound Packet Information"
						,cfg.log&LOG_PACKETS ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","In-bound Security Violations"
700
						,cfg.log&LOG_SECURE ? "Yes":"No");
701
702
703
704
705
706
707
708
709
710
711
712
					sprintf(opt[i++],"%-35.35s%-3.3s","In-bound Grunged Messages"
						,cfg.log&LOG_GRUNGED ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Disallowed Private EchoMail"
						,cfg.log&LOG_PRIVATE ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Circular EchoMail Messages"
						,cfg.log&LOG_CIRCULAR ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Duplicate EchoMail Messages"
						,cfg.log&LOG_DUPES ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Area Totals"
						,cfg.log&LOG_AREA_TOTALS ? "Yes":"No");
					sprintf(opt[i++],"%-35.35s%-3.3s","Over-All Totals"
						,cfg.log&LOG_TOTALS ? "Yes":"No");
rswindell's avatar
rswindell committed
713
					opt[i][0]=0;
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
					j=uifc.list(0,0,0,43,&j,0,"Log Options",opt);
					if(j==-1)
						break;
					switch(j) {
						case 0:
							cfg.log=~0L;
							break;
						case 1:
							cfg.log=0;
							break;
						case 2:
							cfg.log=LOG_DEFAULTS;
							break;
						case 3:
							cfg.log^=LOG_IGNORED;
							break;
						case 4:
							cfg.log^=LOG_UNKNOWN;
732
733
							break;
						case 5:
734
							cfg.log^=LOG_AREAFIX;
735
736
							break;
						case 6:
737
							cfg.log^=LOG_IMPORTED;
738
739
							break;
						case 7:
740
							cfg.log^=LOG_PACKING;
741
742
							break;
						case 8:
743
							cfg.log^=LOG_ROUTING;
744
745
							break;
						case 9:
746
							cfg.log^=LOG_PACKETS;
747
748
							break;
						case 10:
749
							cfg.log^=LOG_SECURE;
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
							break;
						case 11:
							cfg.log^=LOG_GRUNGED;
							break;
						case 12:
							cfg.log^=LOG_PRIVATE;
							break;
						case 13:
							cfg.log^=LOG_CIRCULAR;
							break;
						case 14:
							cfg.log^=LOG_DUPES;
							break;
						case 15:
							cfg.log^=LOG_AREA_TOTALS;
							break;
						case 16:
							cfg.log^=LOG_TOTALS;
							break; } }
				break;
770
771


772
			case 8:
773
	uifc.helpbuf=
774
	"`Secure Operation` tells SBBSecho to check the AREAS.BBS file to insure\r\n"
775
	"    that the packet origin exists there as well as check the password of\r\n"
776
777
	"    that node (if configured).\r\n"
	"\r\n"
778
	"`Convert Existing Tear Lines` tells SBBSecho to convert any tear lines\r\n"
779
780
781
	"    (`---`) existing in the message text to to `===`.\r\n"
	"\r\n"
	"`Fuzzy Zone Operation` when set to `Yes`, if SBBSecho receives an inbound\r\n"
782
783
	"    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"
784
785
	"    and assume the zone of a matching AKA.\r\n"
	"\r\n"
786
	"`Store PATH/SEEN-BY/Unkown Kludge Lines in Message Base` allows you to\r\n"
787
	"    determine whether or not SBBSecho will store this information from\r\n"
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
	"    incoming messages in the Synchronet message base (for debugging).\r\n"
	"\r\n"
	"`Allow Nodes to Add Areas in the AREAS.BBS List` when set to `Yes` allows\r\n"
	"    uplinks to add areas listed in the AREAS.BBS file\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"
	"\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"
	"\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"
	"`Forward Circular Messages To Links` is only valid when `Circular Path\r\n"
	"    Detection` is enabled. When set to `No`, SBBSecho will discard\r\n"
	"    the circular/looped message and not forward to any linked nodes.\r\n"
	"\r\n"
	"`Bundle Attachments` may be either `Killed` (deleted) or `Truncated` (set\r\n"
	"    to 0-bytes in length).\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";
817
				j=0;
818
				while(1) {
819
820
821
					i=0;
					sprintf(opt[i++],"%-50.50s%-3.3s","Secure Operation"
						,misc&SECURE ? "Yes":"No");
822
823
					sprintf(opt[i++],"%-50.50s%-3.3s","Convert Existing Tear Lines"
						,misc&CONVERT_TEAR ? "Yes":"No");
824
825
826
827
828
829
830
831
832
833
					sprintf(opt[i++],"%-50.50s%-3.3s","Fuzzy Zone Operation"
						,misc&FUZZY_ZONE ? "Yes":"No");
					sprintf(opt[i++],"%-50.50s%-3.3s","Store PATH Lines in "
						"Message Base",misc&STORE_SEENBY ? "Yes":"No");
					sprintf(opt[i++],"%-50.50s%-3.3s","Store SEEN-BY Lines in "
						"Message Base",misc&STORE_PATH ? "Yes":"No");
					sprintf(opt[i++],"%-50.50s%-3.3s","Store Unknown Kludge Lines "
						"in Message Base",misc&STORE_KLUDGE ? "Yes":"No");
					sprintf(opt[i++],"%-50.50s%-3.3s","Allow Nodes to Add Areas "
						"in the AREAS.BBS List",misc&ELIST_ONLY?"No":"Yes");
834
835
					sprintf(opt[i++],"%-50.50s%-3.3s","Strip Line Feeds "
						"From Outgoing Messages",misc&STRIP_LF ? "Yes":"No");
836
837
					sprintf(opt[i++],"%-50.50s%-3.3s","Kill/Ignore Empty NetMail "
						"Messages",misc&KILL_EMPTY_MAIL ? "Yes":"No");
838
839
					sprintf(opt[i++],"%-50.50s%s","Circular Path Detection"
						,cfg.check_path ? "Enabled" : "Disabled");
840
841
					sprintf(opt[i++],"%-50.50s%s","Forward Circular Messages to Links"
						,cfg.check_path ? (cfg.fwd_circular ? "Yes" : "No") : "N/A");
842
843
					sprintf(opt[i++],"%-50.50s%s","Bundle Attachments"
						,misc&TRUNC_BUNDLES ? "Truncate" : "Kill");
844
845
					sprintf(opt[i++],"%-50.50s%s","Zone Blind SEEN-BY and PATH Lines"
						,cfg.zone_blind ? "Enabled" : "Disabled");
rswindell's avatar
rswindell committed
846
					opt[i][0]=0;
847
					j=uifc.list(0,0,0,65,&j,0,"Toggle Options",opt);
848
					if(j==-1)
849
						break;
850
					switch(j) {
851
						case 0:
852
							misc^=SECURE;
853
854
							break;
						case 1:
855
							misc^=CONVERT_TEAR;
856
							break;
857
						case 2:
858
							misc^=FUZZY_ZONE;
859
860
							break;
						case 3:
861
862
							misc^=STORE_SEENBY;
							break;
863
						case 4:
864
865
866
867
868
869
870
871
872
							misc^=STORE_PATH;
							break;
						case 5:
							misc^=STORE_KLUDGE;
							break;
						case 6:
							misc^=ELIST_ONLY;
							break;
						case 7:
873
874
875
							misc^=STRIP_LF;
							break;
						case 8:
876
							misc^=KILL_EMPTY_MAIL;
877
							break;
878
						case 9:
879
880
881
							cfg.check_path=!cfg.check_path;
							break;
						case 10:
882
							cfg.fwd_circular=!cfg.fwd_circular;
883
							break;
884
						case 11:
885
886
887
							misc^=TRUNC_BUNDLES;
							break;
						case 12:
888
889
							cfg.zone_blind=!cfg.zone_blind;
							break;
890
891
					} 
				}
892
				break;
893
			case 9:
894
	uifc.helpbuf=
895
	"~ Archive Programs ~\r\n\r\n"
896
897
898
899
	"These are the archiving programs (types) which are available for\r\n"
	"compressing outgoing packets.\r\n";
				i=0;
				while(1) {
900
901
902
					for(u=0;u<cfg.arcdefs;u++)
						sprintf(opt[u],"%-30.30s",cfg.arcdef[u].name);
					opt[u][0]=0;
903
904
905
906
907
908
909
910
911
					i=uifc.list(WIN_ORG|WIN_INS|WIN_DEL|WIN_ACT|WIN_GET|WIN_PUT
						|WIN_INSACT|WIN_DELACT|WIN_XTR
						,0,0,0,&i,0,"Archive Programs",opt);
					if(i==-1)
						break;
					if((i&MSK_ON)==MSK_INS) {
						i&=MSK_OFF;
						str[0]=0;
	uifc.helpbuf=
912
	"~ Packer Name ~\r\n\r\n"
913
914
915
916
	"This is the identifying name of the archiving program\r\n";
						if(uifc.input(WIN_MID,0,0
							,"Packer Name",str,25,K_EDIT|K_UPPER)<1)
							continue;
deuce's avatar
deuce committed
917
						if((cfg.arcdef=(arcdef_t *)realloc(cfg.arcdef
918
919
920
921
922
923
924
925
926
927
928
929
							,sizeof(arcdef_t)*(cfg.arcdefs+1)))==NULL) {
							printf("\nMemory Allocation Error\n");
							exit(1); }
						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);
						continue; }
930

931
932
933
934
935
936
					if((i&MSK_ON)==MSK_DEL) {
						i&=MSK_OFF;
						cfg.arcdefs--;
						if(cfg.arcdefs<=0) {
							cfg.arcdefs=0;
							continue; }
937
938
						for(u=i;u<cfg.arcdefs;u++)
							memcpy(&cfg.arcdef[u],&cfg.arcdef[u+1]
939
								,sizeof(arcdef_t));
deuce's avatar
deuce committed
940
						if((cfg.arcdef=(arcdef_t *)realloc(cfg.arcdef
941
942
943
944
945
946
947
							,sizeof(arcdef_t)*(cfg.arcdefs)))==NULL) {
							printf("\nMemory Allocation Error\n");
							exit(1); }
						continue; }
					if((i&MSK_ON)==MSK_GET) {
						i&=MSK_OFF;
						memcpy(&savarcdef,&cfg.arcdef[i],sizeof(arcdef_t));
948
						continue; }
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
					if((i&MSK_ON)==MSK_PUT) {
						i&=MSK_OFF;
						memcpy(&cfg.arcdef[i],&savarcdef,sizeof(arcdef_t));
						continue; }
					while(1) {
						j=0;
						sprintf(opt[j++],"%-20.20s %s","Packer Name"
							,cfg.arcdef[i].name);
						sprintf(opt[j++],"%-20.20s %s","Hexadecimal ID"
							,cfg.arcdef[i].hexid);
						sprintf(opt[j++],"%-20.20s %u","Offset to Hex ID"
							,cfg.arcdef[i].byteloc);
						sprintf(opt[j++],"%-20.20s %s","Pack Command Line"
							,cfg.arcdef[i].pack);
						sprintf(opt[j++],"%-20.20s %s","Unpack Command Line"
							,cfg.arcdef[i].unpack);
						opt[j][0]=0;
						sprintf(str,"%.30s",cfg.arcdef[i].name);
						k=uifc.list(WIN_MID|WIN_ACT,0,0,60,&nodeop,0,str,opt);
						if(k==-1)
							break;
						switch(k) {
							case 0:
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Packer Name",cfg.arcdef[i].name,25
									,K_EDIT|K_UPPER);
								break;
							case 1:
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Hexadecimal ID",cfg.arcdef[i].hexid,25
									,K_EDIT|K_UPPER);
								break;
							case 2:
								sprintf(str,"%u",cfg.arcdef[i].byteloc);
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Offset to Hex ID",str,5
									,K_NUMBER|K_EDIT);
								cfg.arcdef[i].byteloc=atoi(str);
								break;
							case 3:
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Pack Command Line",cfg.arcdef[i].pack,50
									,K_EDIT);
								break;
							case 4:
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Unpack Command Line",cfg.arcdef[i].unpack,50
									,K_EDIT);
								break;
								} } }
				break;
1000
			case 10:
1001
	uifc.helpbuf=
1002
	"~ Additional Echo Lists ~\r\n\r\n"
1003
1004
1005
	"This feature allows you to specify echo lists (in addition to your\r\n"
	"AREAS.BBS file) for SBBSecho to search for area add requests.\r\n";
				i=0;
1006
				while(1) {
1007
1008
1009
					for(u=0;u<cfg.listcfgs;u++)
						sprintf(opt[u],"%-50.50s",cfg.listcfg[u].listpath);
					opt[u][0]=0;
1010
1011
1012
1013
					i=uifc.list(WIN_ORG|WIN_INS|WIN_DEL|WIN_ACT|WIN_GET|WIN_PUT
						|WIN_INSACT|WIN_DELACT|WIN_XTR
						,0,0,0,&i,0,"Additional Echo Lists",opt);
					if(i==-1)
1014
						break;
1015
1016
1017
1018
					if((i&MSK_ON)==MSK_INS) {
						i&=MSK_OFF;
						str[0]=0;
	uifc.helpbuf=
1019
	"~ Echo List ~\r\n\r\n"
1020
1021
1022
1023
1024
	"This is the path and filename of the echo list file you wish\r\n"
	"to add.\r\n";
						if(uifc.input(WIN_MID|WIN_SAV,0,0
							,"Echo List Path/Name",str,50,K_EDIT)<1)
							continue;
deuce's avatar
deuce committed
1025
						if((cfg.listcfg=(echolist_t *)realloc(cfg.listcfg
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
							,sizeof(echolist_t)*(cfg.listcfgs+1)))==NULL) {
							printf("\nMemory Allocation Error\n");
							exit(1); }
						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);
						continue; }

					if((i&MSK_ON)==MSK_DEL) {
						i&=MSK_OFF;
						cfg.listcfgs--;
						if(cfg.listcfgs<=0) {
							cfg.listcfgs=0;
							continue; }
1043
1044
						for(u=i;u<cfg.listcfgs;u++)
							memcpy(&cfg.listcfg[u],&cfg.listcfg[u+1]
1045
								,sizeof(echolist_t));
deuce's avatar
deuce committed
1046
						if((cfg.listcfg=(echolist_t *)realloc(cfg.listcfg
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
							,sizeof(echolist_t)*(cfg.listcfgs)))==NULL) {
							printf("\nMemory Allocation Error\n");
							exit(1); }
						continue; }
					if((i&MSK_ON)==MSK_GET) {
						i&=MSK_OFF;
						memcpy(&savlistcfg,&cfg.listcfg[i],sizeof(echolist_t));
						continue; }
					if((i&MSK_ON)==MSK_PUT) {
						i&=MSK_OFF;
						memcpy(&cfg.listcfg[i],&savlistcfg,sizeof(echolist_t));
						continue; }
					while(1) {
						j=0;
						sprintf(opt[j++],"%-20.20s %.19s","Echo List Path/Name"
							,cfg.listcfg[i].listpath);
						sprintf(opt[j++],"%-20.20s %s","Hub Address"
							,(cfg.listcfg[i].forward.zone) ?
							 wcfaddrtoa(&cfg.listcfg[i].forward) : "None");
						sprintf(opt[j++],"%-20.20s %s","Forward Password"
							,(cfg.listcfg[i].password[0]) ?
							 cfg.listcfg[i].password : "None");
						sprintf(opt[j++],"%-20.20s %s","Forward Requests"
							,(cfg.listcfg[i].misc&NOFWD) ? "No" : "Yes");
						str[0]=0;
1072
1073
						for(u=0;u<cfg.listcfg[i].numflags;u++) {
							strcat(str,cfg.listcfg[i].flag[u].flag);
1074
1075
1076
1077
1078
							strcat(str," "); }
						sprintf(opt[j++],"%-20.20s %s","Echo List Flags",str);
						opt[j][0]=0;
						k=uifc.list(WIN_MID|WIN_ACT,0,0,60,&nodeop,0,"Echo List",opt);
						if(k==-1)
1079
							break;
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
						switch(k) {
							case 0:
								strcpy(str,cfg.listcfg[i].listpath);
								if(uifc.input(WIN_MID|WIN_SAV,0,0
									,"Echo List Path/Name",str,50
									,K_EDIT)<1)
									continue;
								strcpy(cfg.listcfg[i].listpath,str);
								break;
							case 1:
								if(cfg.listcfg[i].forward.zone)
									strcpy(str,wcfaddrtoa(&cfg.listcfg[i].forward));
								else
1093
									str[0]=0;
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Hub Address",str
									,25,K_EDIT);
								if(str[0])
									cfg.listcfg[i].forward=atofaddr(str);
								else
									memset(&cfg.listcfg[i].forward,0
										,sizeof(faddr_t));
								break;
							case 2:
								uifc.input(WIN_MID|WIN_SAV,0,0
									,"Password to use when forwarding requests"
									,cfg.listcfg[i].password,25,K_EDIT|K_UPPER);
								break;
							case 3:
								cfg.listcfg[i].misc^=NOFWD;
								if(cfg.listcfg[i].misc&NOFWD)
									cfg.listcfg[i].password[0]=0;
								break;
							case 4:
								while(1) {
1115
1116
1117
									for(u=0;u<cfg.listcfg[i].numflags;u++)
										strcpy(opt[u],cfg.listcfg[i].flag[u].flag);
									opt[u][0]=0;
1118
1119
1120
1121
1122
1123
1124
1125
1126
									x=uifc.list(WIN_SAV|WIN_INS|WIN_DEL|WIN_ACT|
										WIN_XTR|WIN_INSACT|WIN_DELACT|WIN_RHT
										,0,0,0,&x,0,"Echo List Flags",opt);
									if(x==-1)
										break;
									if((x&MSK_ON)==MSK_INS) {
										x&=MSK_OFF;
										str[0]=0;
	uifc.helpbuf=
1127
	"~ Echo List Flag ~\r\n\r\n"
1128
1129
1130
1131
1132
1133
1134
	"These flags determine which nodes have access to the current\r\n"
	"echolist file\r\n";
										if(uifc.input(WIN_MID|WIN_SAV,0,0
											,"Echo List Flag",str,4
											,K_EDIT|K_UPPER)<1)
											continue;
										if((cfg.listcfg[i].flag=(flag_t *)
deuce's avatar
deuce committed
1135
											realloc(cfg.listcfg[i].flag
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
											,sizeof(flag_t)*
											(cfg.listcfg[i].numflags+1)))==NULL) {
											printf("\nMemory Allocation Error\n");
											exit(1); }
										for(j=cfg.listcfg[i].numflags;j>x;j--)
											memcpy(&cfg.listcfg[i].flag[j]
												,&cfg.listcfg[i].flag[j-1]
												,sizeof(flag_t));
										cfg.listcfg[i].numflags++;
										memset(&cfg.listcfg[i].flag[x].flag
											,0,sizeof(flag_t));
										strcpy(cfg.listcfg[i].flag[x].flag,str);
										continue; }
1149

1150
1151
1152
1153
1154
1155
									if((x&MSK_ON)==MSK_DEL) {
										x&=MSK_OFF;
										cfg.listcfg[i].numflags--;
										if(cfg.listcfg[i].numflags<=0) {
											cfg.listcfg[i].numflags=0;
											continue; }
1156
1157
1158
										for(u=x;u<cfg.listcfg[i].numflags;u++)
											strcpy(cfg.listcfg[i].flag[u].flag
												,cfg.listcfg[i].flag[u+1].flag);
1159
										if((cfg.listcfg[i].flag=(flag_t *)
deuce's avatar
deuce committed
1160
											realloc(cfg.listcfg[i].flag
1161
1162
1163
1164
											,sizeof(flag_t)*
											(cfg.listcfg[i].numflags)))==NULL) {
											printf("\nMemory Allocation Error\n");
											exit(1); }
1165
										continue; }
1166
1167
									strcpy(str,cfg.listcfg[i].flag[x].flag);
	uifc.helpbuf=
1168
	"~ Echo List Flag ~\r\n\r\n"
1169
1170
1171
1172
1173
1174
1175
1176
1177
	"These flags determine which nodes have access to the current\r\n"
	"echolist file\r\n";
										uifc.input(WIN_MID|WIN_SAV,0,0,"Echo List Flag"
											,str,4,K_EDIT|K_UPPER);
										strcpy(cfg.listcfg[i].flag[x].flag,str);
										continue; }
								break;
								} } }
				break;
1178

1179
1180
			case -1:
	uifc.helpbuf=
1181
1182
1183
	"~ 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";
1184
1185
1186
1187
1188
1189
1190
				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);}
1191
				if((stream=fnopen(NULL,cfg.cfgfile,O_CREAT|O_TRUNC|O_WRONLY|O_TEXT))==NULL) {
1192
1193
1194
					uifc.bail();
					printf("Error %d opening %s\n",errno,cfg.cfgfile);
					exit(1); 
1195
				}
1196
1197
				if(!cfg.check_path)
					fprintf(stream,"NOPATHCHECK\n");
1198
1199
				if(!cfg.fwd_circular)
					fprintf(stream,"NOCIRCULARFWD\n");
1200
1201
1202
1203
1204
1205
				if(cfg.zone_blind) {
					fprintf(stream,"ZONE_BLIND");
					if(cfg.zone_blind_threshold != 0xffff)
						fprintf(stream," %u", cfg.zone_blind_threshold);
					fprintf(stream,"\n");
				}
1206
1207
				if(cfg.notify)
					fprintf(stream,"NOTIFY %u\n",cfg.notify);
1208
1209
				if(misc&CONVERT_TEAR)
					fprintf(stream,"CONVERT_TEAR\n");
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
				if(misc&SECURE)
					fprintf(stream,"SECURE_ECHOMAIL\n");
				if(misc&KILL_EMPTY_MAIL)
					fprintf(stream,"KILL_EMPTY\n");
				if(misc&STORE_SEENBY)
					fprintf(stream,"STORE_SEENBY\n");
				if(misc&STORE_PATH)
					fprintf(stream,"STORE_PATH\n");
				if(misc&STORE_KLUDGE)
					fprintf(stream,"STORE_KLUDGE\n");
				if(misc&FUZZY_ZONE)
					fprintf(stream,"FUZZY_ZONE\n");
				if(misc&FLO_MAILER)
					fprintf(stream,"FLO_MAILER\n");
				if(misc&ELIST_ONLY)
					fprintf(stream,"ELIST_ONLY\n");
1226
1227
				if(misc&STRIP_LF)
					fprintf(stream,"STRIP_LF\n");
1228
1229
				if(misc&TRUNC_BUNDLES)
					fprintf(stream,"TRUNC_BUNDLES\n");
1230

1231
				fprintf(stream,"SYSOP_ALIAS %s\n", cfg.sysop_alias);
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
				if(cfg.areafile[0])
					fprintf(stream,"AREAFILE %s\n",cfg.areafile);
				if(cfg.logfile[0])
					fprintf(stream,"LOGFILE %s\n",cfg.logfile);
				if(cfg.log!=LOG_DEFAULTS) {
					if(cfg.log==0xffffffffUL)
						fprintf(stream,"LOG ALL\n");
					else if(cfg.log==0L)
						fprintf(stream,"LOG NONE\n");
					else
						fprintf(stream,"LOG %08lX\n",cfg.log); }
deuce's avatar
deuce committed
1243
				fprintf(stream,"LOG_LEVEL %lu\n",cfg.log_level);
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
				if(cfg.inbound[0])
					fprintf(stream,"INBOUND %s\n",cfg.inbound);
				if(cfg.secure[0])
					fprintf(stream,"SECURE_INBOUND %s\n",cfg.secure);
				if(cfg.outbound[0])
					fprintf(stream,"OUTBOUND %s\n",cfg.outbound);
				if(cfg.maxbdlsize!=DFLT_BDL_SIZE)
					fprintf(stream,"ARCSIZE %lu\n",cfg.maxbdlsize);
				if(cfg.maxpktsize!=DFLT_PKT_SIZE)
					fprintf(stream,"PKTSIZE %lu\n",cfg.maxpktsize);
1254
1255
				for(u=j=0;u<cfg.nodecfgs;u++)
					if(cfg.nodecfg[u].attr&SEND_NOTIFY) {
1256
						if(!j) fprintf(stream,"SEND_NOTIFY");
1257
						fprintf(stream," %s",wcfaddrtoa(&cfg.nodecfg[u].faddr));
1258
1259
						j++; }
				if(j) fprintf(stream,"\n");
1260
1261
				for(u=j=0;u<cfg.nodecfgs;u++)
					if(cfg.nodecfg[u].attr&ATTR_HOLD) {
1262
						if(!j) fprintf(stream,"HOLD");
1263
						fprintf(stream," %s",wcfaddrtoa(&cfg.nodecfg[u].faddr));
1264
1265
						j++; }
				if(j) fprintf(stream,"\n