Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

sbbs_ini.c 47.4 KB
Newer Older
1
/* Synchronet initialization (.ini) file routines */
2 3 4 5 6

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

22 23
#define STARTUP_INI_BITDESC_TABLES

24
#include "sockwrap.h"
deuce's avatar
deuce committed
25 26
#include <string.h>	/* strchr, memset */

27
#include "sbbs_ini.h"
28
#include "dirwrap.h"	/* backslash */
29
#include "sbbsdefs.h"	/* JAVASCRIPT_* macros */
30 31

static const char*	nulstr="";
32
static const char*  strAutoStart="AutoStart";
33 34
static const char*  strCtrlDirectory="CtrlDirectory";
static const char*  strTempDirectory="TempDirectory";
rswindell's avatar
rswindell committed
35
static const char*	strOptions="Options";
36 37
static const char*	strOutgoing4="OutboundInterface";
static const char*	strOutgoing6="OutboundV6Interface";
deuce's avatar
deuce committed
38
static const char*	strInterfaces="Interface";
39 40 41
static const char*	strPort="Port";
static const char*	strMaxClients="MaxClients";
static const char*	strMaxInactivity="MaxInactivity";
42
static const char*	strMaxConConn="MaxConcurrentConnections";
rswindell's avatar
rswindell committed
43
static const char*	strHostName="HostName";
44
static const char*	strLogLevel="LogLevel";
45 46
static const char*	strBindRetryCount="BindRetryCount";
static const char*	strBindRetryDelay="BindRetryDelay";
47 48
static const char*	strAnswerSound="AnswerSound";
static const char*	strHangupSound="HangupSound";
49 50
static const char*	strLoginSound="LoginSound";
static const char*	strLogoutSound="LogoutSound";
51
static const char*	strHackAttemptSound="HackAttemptSound";
52 53 54
static const char*	strLoginAttemptDelay="LoginAttemptDelay";
static const char*	strLoginAttemptThrottle="LoginAttemptThrottle";
static const char*	strLoginAttemptHackThreshold="LoginAttemptHackThreshold";
rswindell's avatar
rswindell committed
55 56
static const char*	strLoginAttemptTempBanThreshold="LoginAttemptTempBanThreshold";
static const char*	strLoginAttemptTempBanDuration="LoginAttemptTempBanDuration";
57
static const char*	strLoginAttemptFilterThreshold="LoginAttemptFilterThreshold";
58
static const char*	strJavaScriptMaxBytes		="JavaScriptMaxBytes";
59
static const char*	strJavaScriptTimeLimit		="JavaScriptTimeLimit";
60 61
static const char*	strJavaScriptGcInterval		="JavaScriptGcInterval";
static const char*	strJavaScriptYieldInterval	="JavaScriptYieldInterval";
62
static const char*	strJavaScriptLoadPath		="JavaScriptLoadPath";
63
static const char*	strJavaScriptOptions		="JavaScriptOptions";
64
static const char*	strSemFileCheckFrequency	="SemFileCheckFrequency";
65
static const char*	strIniFileName				="iniFileName";
66

rswindell's avatar
rswindell committed
67 68 69
#define DEFAULT_LOG_LEVEL				LOG_DEBUG
#define DEFAULT_BIND_RETRY_COUNT		2
#define DEFAULT_BIND_RETRY_DELAY		15
70

71
void sbbs_get_ini_fname(char* ini_file, char* ctrl_dir, char* pHostName)
72
{
73
	/* pHostName is no longer used since iniFileName calls gethostname() itself */
74

75 76
#if defined(_WINSOCKAPI_)	 
	WSADATA WSAData;	 
77
    (void)WSAStartup(MAKEWORD(1,1), &WSAData); /* req'd for gethostname */	 
78 79
#endif	 

80
#if defined(__unix__) && defined(PREFIX)
81 82 83
	sprintf(ini_file,PREFIX"/etc/sbbs.ini");
	if(fexistcase(ini_file))
		return;
84
#endif
85
	iniFileName(ini_file,MAX_PATH,ctrl_dir,"sbbs.ini");
86 87 88 89

#if defined(_WINSOCKAPI_)	 
	WSACleanup();	 
#endif
90
}
91

92 93 94
static BOOL iniSetStringWithGlobalDefault(str_list_t* lp, const char* section, const char* key
	,const char* value, const char* global_value, ini_style_t* style)
{
95
	if(value != global_value && strcmp(value, global_value) == 0) {
96 97 98 99 100 101
		iniRemoveKey(lp, section, key);
		return iniKeyExists(*lp, section, key) == FALSE;
	}
	return iniSetString(lp, section, key, value, style) != NULL;
}

102
static void sbbs_fix_js_settings(js_startup_t* js)
103 104 105 106 107
{
	/* Some sanity checking here */
	if(js->max_bytes==0)	js->max_bytes=JAVASCRIPT_MAX_BYTES;
}

108 109
void sbbs_get_js_settings(
	 str_list_t list
110 111 112 113
	,const char* section
	,js_startup_t* js
	,js_startup_t* defaults)
{
114 115
	char	value[INI_MAX_VALUE_LEN];
    char*   p;
116

117
	js->max_bytes		= (ulong)iniGetBytes(list,section,strJavaScriptMaxBytes		,/* unit: */1,defaults->max_bytes);
118
	js->time_limit		= iniGetInteger(list,section,strJavaScriptTimeLimit		,defaults->time_limit);
119 120
	js->gc_interval		= iniGetInteger(list,section,strJavaScriptGcInterval	,defaults->gc_interval);
	js->yield_interval	= iniGetInteger(list,section,strJavaScriptYieldInterval	,defaults->yield_interval);
121
	js->options			= iniGetBitField(list, section, strJavaScriptOptions	,js_options, defaults->options);
122

rswindell's avatar
rswindell committed
123
	/* Get JavaScriptLoadPath, use default if key is missing, use blank if key value is blank */
124 125 126 127 128
    if((p=iniGetExistingString(list, section, strJavaScriptLoadPath, nulstr, value)) == NULL) {
		if(defaults!=js)
			SAFECOPY(js->load_path, defaults->load_path);
	} else
        SAFECOPY(js->load_path, p);
129

130
	sbbs_fix_js_settings(js);
131 132 133 134 135 136 137 138 139 140
}

BOOL sbbs_set_js_settings(
	 str_list_t* lp
	,const char* section
	,js_startup_t* js
	,js_startup_t* defaults
	,ini_style_t* style)
{
	BOOL	failure=FALSE;
141 142
	js_startup_t global_defaults = {
			 JAVASCRIPT_MAX_BYTES
143
			,JAVASCRIPT_TIME_LIMIT
144 145
			,JAVASCRIPT_GC_INTERVAL
			,JAVASCRIPT_YIELD_INTERVAL
146
			,JAVASCRIPT_OPTIONS
147
            ,JAVASCRIPT_LOAD_PATH
148
		};
149
	SAFECOPY(global_defaults.load_path, JAVASCRIPT_LOAD_PATH);
150 151 152

	if(defaults==NULL)
		defaults=&global_defaults;
153

154 155
	sbbs_fix_js_settings(js);

156
	if(js->max_bytes==defaults->max_bytes)
157
		iniRemoveValue(lp,section,strJavaScriptMaxBytes);
158
	else
159
		failure|=iniSetBytes(lp,section,strJavaScriptMaxBytes,/*unit: */1, js->max_bytes,style)==NULL;
160

161 162
	if(js->time_limit==defaults->time_limit)
		iniRemoveValue(lp,section,strJavaScriptTimeLimit);
163
	else
164
		failure|=iniSetInteger(lp,section,strJavaScriptTimeLimit,js->time_limit,style)==NULL;
165 166

	if(js->gc_interval==defaults->gc_interval)
167
		iniRemoveValue(lp,section,strJavaScriptGcInterval);
168 169 170
	else 
		failure|=iniSetInteger(lp,section,strJavaScriptGcInterval,js->gc_interval,style)==NULL;

171 172 173 174 175
	if(js->yield_interval==defaults->yield_interval)
		iniRemoveValue(lp,section,strJavaScriptYieldInterval);
	else 
		failure|=iniSetInteger(lp,section,strJavaScriptYieldInterval,js->yield_interval,style)==NULL;

176 177
	if(strcmp(js->load_path,defaults->load_path)==0)
		iniRemoveKey(lp,section,strJavaScriptLoadPath);
178
	else
179
		failure|=iniSetString(lp,section,strJavaScriptLoadPath,js->load_path,style)==NULL;
180

181 182 183
	return(!failure);
}

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
void sbbs_get_sound_settings(str_list_t list, const char* section, struct startup_sound_settings* sound
	,struct startup_sound_settings* defaults)
{
	char	value[INI_MAX_VALUE_LEN];
    char*   p;

	if((p = iniGetString(list, section, strAnswerSound, defaults->answer, value)) != NULL && *p != '\0')
        SAFECOPY(sound->answer, value);

	if((p = iniGetString(list, section, strLoginSound, defaults->login, value)) != NULL && *p != '\0')
        SAFECOPY(sound->login, value);

	if((p = iniGetString(list, section, strLogoutSound, defaults->logout, value)) != NULL && *p != '\0')
        SAFECOPY(sound->logout, value);

	if((p = iniGetString(list, section, strHangupSound, defaults->hangup, value)) != NULL && *p != '\0')
        SAFECOPY(sound->hangup, value);

	if((p = iniGetString(list, section, strHackAttemptSound, defaults->hack, value)) != NULL && *p != '\0')
        SAFECOPY(sound->hack, value);
}

BOOL sbbs_set_sound_settings(
	 str_list_t* lp
	,const char* section
	,struct startup_sound_settings* sound
	,struct startup_sound_settings* defaults
	,ini_style_t* style)
{
	if(!iniSetStringWithGlobalDefault(lp ,section, strAnswerSound, sound->answer, defaults->answer, style))
		return FALSE;
	if(!iniSetStringWithGlobalDefault(lp, section, strLoginSound, sound->login, defaults->login, style))
		return FALSE;
	if(!iniSetStringWithGlobalDefault(lp, section, strLogoutSound, sound->logout, defaults->logout, style))
		return FALSE;
	if(!iniSetStringWithGlobalDefault(lp, section, strHangupSound, sound->hangup, defaults->logout, style))
		return FALSE;
	if(!iniSetStringWithGlobalDefault(lp, section, strHackAttemptSound, sound->hack, defaults->hack, style))
		return FALSE;
	return TRUE;
}

rswindell's avatar
rswindell committed
226 227 228 229 230 231 232 233
static struct login_attempt_settings get_login_attempt_settings(str_list_t list, const char* section, global_startup_t* global)
{
	struct login_attempt_settings settings;

	settings.delay				=iniGetInteger(list,section,strLoginAttemptDelay			,global == NULL ? 5000 : global->login_attempt.delay);
	settings.throttle			=iniGetInteger(list,section,strLoginAttemptThrottle			,global == NULL ? 1000 : global->login_attempt.throttle);
	settings.hack_threshold		=iniGetInteger(list,section,strLoginAttemptHackThreshold	,global == NULL ? 10 : global->login_attempt.hack_threshold);
	settings.tempban_threshold	=iniGetInteger(list,section,strLoginAttemptTempBanThreshold	,global == NULL ? 20 : global->login_attempt.tempban_threshold);
234
	settings.tempban_duration	=(ulong)iniGetDuration(list,section,strLoginAttemptTempBanDuration	,global == NULL ? (10*60) : global->login_attempt.tempban_duration);
rswindell's avatar
rswindell committed
235 236 237 238 239 240 241 242 243 244
	settings.filter_threshold	=iniGetInteger(list,section,strLoginAttemptFilterThreshold	,global == NULL ? 0 : global->login_attempt.filter_threshold);
	return settings;
}

static void set_login_attempt_settings(str_list_t* lp, const char* section, struct login_attempt_settings settings, ini_style_t style)
{
	iniSetInteger(lp,section,strLoginAttemptDelay,settings.delay,&style);
	iniSetInteger(lp,section,strLoginAttemptThrottle,settings.throttle,&style);
	iniSetInteger(lp,section,strLoginAttemptHackThreshold,settings.hack_threshold,&style);
	iniSetInteger(lp,section,strLoginAttemptTempBanThreshold,settings.tempban_threshold,&style);
245
	iniSetDuration(lp,section,strLoginAttemptTempBanDuration,settings.tempban_duration,&style);
rswindell's avatar
rswindell committed
246 247 248
	iniSetInteger(lp,section,strLoginAttemptFilterThreshold,settings.filter_threshold,&style);
}

249
static void get_ini_globals(str_list_t list, global_startup_t* global)
rswindell's avatar
rswindell committed
250 251
{
	const char* section = "Global";
252
	char		value[INI_MAX_VALUE_LEN];
253
	char*		p;
rswindell's avatar
rswindell committed
254
	struct in6_addr	wildcard6 = {{{0}}};
rswindell's avatar
rswindell committed
255

256
	p=iniGetString(list,section,strCtrlDirectory,nulstr,value);
257
	if(*p) {
258
	    SAFECOPY(global->ctrl_dir,value);
259
		backslash(global->ctrl_dir);
260
    }
rswindell's avatar
rswindell committed
261

262
	p=iniGetString(list,section,strTempDirectory,nulstr,value);
263
	if(*p) {
264
	    SAFECOPY(global->temp_dir,value);
265
		backslash(global->temp_dir);
266
    }
rswindell's avatar
rswindell committed
267

268
	p=iniGetString(list,section,strHostName,nulstr,value);
269
	if(*p)
270
        SAFECOPY(global->host_name,value);
rswindell's avatar
rswindell committed
271

272
	global->sem_chk_freq=iniGetShortInt(list,section,strSemFileCheckFrequency,DEFAULT_SEM_CHK_FREQ);
273 274
	iniFreeStringList(global->interfaces);
	global->interfaces=iniGetStringList(list,section,strInterfaces, ",", "0.0.0.0,::");
deuce's avatar
deuce committed
275 276
	global->outgoing4.s_addr=iniGetIpAddress(list,section,strOutgoing4,0);
	global->outgoing6=iniGetIp6Address(list,section,strOutgoing6,wildcard6);
277
	global->log_level=iniGetLogLevel(list,section,strLogLevel,DEFAULT_LOG_LEVEL);
278 279
	global->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,DEFAULT_BIND_RETRY_COUNT);
	global->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,DEFAULT_BIND_RETRY_DELAY);
rswindell's avatar
rswindell committed
280
	global->login_attempt = get_login_attempt_settings(list, section, NULL);
281

282 283
	/* Setup default values here */
	global->js.max_bytes		= JAVASCRIPT_MAX_BYTES;
284
	global->js.time_limit		= JAVASCRIPT_TIME_LIMIT;
285 286
	global->js.gc_interval		= JAVASCRIPT_GC_INTERVAL;
	global->js.yield_interval	= JAVASCRIPT_YIELD_INTERVAL;
287
	global->js.options			= JAVASCRIPT_OPTIONS;
288
    SAFECOPY(global->js.load_path, JAVASCRIPT_LOAD_PATH);
289

290
	sbbs_get_js_settings(list, section, &global->js, &global->js);
291
	sbbs_get_sound_settings(list, section, &global->sound, &global->sound);
rswindell's avatar
rswindell committed
292 293 294
}


295 296
void sbbs_read_ini(
	 FILE*					fp
297
	,const char*			ini_fname
298
	,global_startup_t*		global
299 300 301 302
	,BOOL*					run_bbs
	,bbs_startup_t*			bbs
	,BOOL*					run_ftp
	,ftp_startup_t*			ftp
303 304
	,BOOL*					run_web
	,web_startup_t*			web
305 306 307 308 309 310 311
	,BOOL*					run_mail		
	,mail_startup_t*		mail
	,BOOL*					run_services
	,services_startup_t*	services
	)
{
	const char*	section;
312
	const char* default_term_ansi;
313
#if defined(__linux__) || defined(__FreeBSD__)
314
	const char*	default_dosemu_path;
315
#if defined(__linux__)
316
	const char*	default_dosemuconf_path;
317
#endif
318
#endif
319
	char		value[INI_MAX_VALUE_LEN];
320
	str_list_t	list;
321
	global_startup_t global_buf;
rswindell's avatar
rswindell committed
322
	struct in6_addr	wildcard6 = {{{0}}};
323
	char		*global_interfaces;
324

325 326
	if(global==NULL) {
		memset(&global_buf,0,sizeof(global_buf));
327
		global=&global_buf;
328
	}
329

330 331 332
	list=iniReadFile(fp);

	get_ini_globals(list, global);
333 334 335 336

	if(global->ctrl_dir[0]) {
		if(bbs!=NULL)		SAFECOPY(bbs->ctrl_dir,global->ctrl_dir);
		if(ftp!=NULL)		SAFECOPY(ftp->ctrl_dir,global->ctrl_dir);
rswindell's avatar
rswindell committed
337
		if(web!=NULL)		SAFECOPY(web->ctrl_dir,global->ctrl_dir);
338 339
		if(mail!=NULL)		SAFECOPY(mail->ctrl_dir,global->ctrl_dir);
		if(services!=NULL)	SAFECOPY(services->ctrl_dir,global->ctrl_dir);
340
	}
deuce's avatar
deuce committed
341

342 343 344 345 346 347 348 349
	if(ini_fname!=NULL && ini_fname[0]) {
		if(bbs!=NULL)		SAFECOPY(bbs->ini_fname, ini_fname);
		if(ftp!=NULL)		SAFECOPY(ftp->ini_fname, ini_fname);
		if(web!=NULL)		SAFECOPY(web->ini_fname, ini_fname);
		if(mail!=NULL)		SAFECOPY(mail->ini_fname, ini_fname);
		if(services!=NULL)	SAFECOPY(services->ini_fname, ini_fname);
	}

350 351
	global_interfaces = strListCombine(global->interfaces, NULL, 16384, ",");

352
	/***********************************************************************/
353
	section = "BBS";
354

355
	if(run_bbs!=NULL)
356
		*run_bbs=iniGetBool(list,section,strAutoStart,TRUE);
357

358
	if(bbs!=NULL) {
359

deuce's avatar
deuce committed
360 361 362 363 364
		bbs->outgoing4.s_addr
			=iniGetIpAddress(list,section,strOutgoing4,global->outgoing4.s_addr);
		bbs->outgoing6
			=iniGetIp6Address(list,section,strOutgoing6,global->outgoing6);

365
		bbs->telnet_port
366
			=iniGetShortInt(list,section,"TelnetPort",IPPORT_TELNET);
367 368 369
		iniFreeStringList(bbs->telnet_interfaces);
		bbs->telnet_interfaces
			=iniGetStringList(list,section,"TelnetInterface",",",global_interfaces);
370 371

		bbs->rlogin_port
372
			=iniGetShortInt(list,section,"RLoginPort",513);
373 374 375
		iniFreeStringList(bbs->rlogin_interfaces);
		bbs->rlogin_interfaces
			=iniGetStringList(list,section,"RLoginInterface",",",global_interfaces);
376

rswindell's avatar
rswindell committed
377 378 379 380 381
		bbs->pet40_port
			=iniGetShortInt(list,section,"Pet40Port",64);
		bbs->pet80_port
			=iniGetShortInt(list,section,"Pet80Port",128);

382 383
		bbs->ssh_port
			=iniGetShortInt(list,section,"SSHPort",22);
384 385
		bbs->ssh_connect_timeout
			=iniGetShortInt(list,section,"SSHConnectTimeout",10);
386 387 388
		iniFreeStringList(bbs->ssh_interfaces);
		bbs->ssh_interfaces
			=iniGetStringList(list,section,"SSHInterface",",",global_interfaces);
389

390
		bbs->first_node
391
			=iniGetShortInt(list,section,"FirstNode",1);
392
		bbs->last_node
393
			=iniGetShortInt(list,section,"LastNode",4);
394 395

		bbs->outbuf_highwater_mark
396 397 398 399 400 401 402
			=iniGetShortInt(list,section,"OutbufHighwaterMark"
#ifdef TCP_MAXSEG	/* Auto-tune if possible.  Would this be defined here? */
			,0
#else
			,1024
#endif
			);
403
		bbs->outbuf_drain_timeout
404
			=iniGetShortInt(list,section,"OutbufDrainTimeout",10);
405

406
		bbs->sem_chk_freq
407
			=iniGetShortInt(list,section,strSemFileCheckFrequency,global->sem_chk_freq);
408

409
		/* JavaScript operating parameters */
410
		sbbs_get_js_settings(list, section, &bbs->js, &global->js);
411 412

		SAFECOPY(bbs->host_name
413
			,iniGetString(list,section,strHostName,global->host_name,value));
414

rswindell's avatar
rswindell committed
415
		SAFECOPY(bbs->temp_dir
416
			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
rswindell's avatar
rswindell committed
417

418 419 420 421 422 423 424 425
		/* Set default terminal type to "stock" termcap closest to "ansi-bbs" */
	#if defined(__FreeBSD__)
		default_term_ansi="cons25";
	#else
		default_term_ansi="pc3";
	#endif

		SAFECOPY(bbs->xtrn_term_ansi
426
			,iniGetString(list,section,"ExternalTermANSI",default_term_ansi,value));
427
		SAFECOPY(bbs->xtrn_term_dumb
428
			,iniGetString(list,section,"ExternalTermDumb","dumb",value));
429

430
	#if defined(__linux__) || defined(__FreeBSD__)
431
	#if defined(__FreeBSD__)
432
		default_dosemu_path="/usr/local/bin/doscmd";
433 434
	#else
		default_dosemu_path="/usr/bin/dosemu.bin";
435
		default_dosemuconf_path="";
436

437 438 439
		SAFECOPY(bbs->dosemuconf_path
			,iniGetString(list,section,"DOSemuConfPath",default_dosemuconf_path,value));			
	#endif
440
		bbs->usedosemu=iniGetBool(list,section,"UseDOSemu",TRUE);
441
		SAFECOPY(bbs->dosemu_path
442
			,iniGetString(list,section,"DOSemuPath",default_dosemu_path,value));
443
	#endif
444

445
		sbbs_get_sound_settings(list, section, &bbs->sound, &global->sound);
446

447 448
		bbs->log_level
			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
449
		bbs->options
450
			=iniGetBitField(list,section,strOptions,bbs_options
451
				,BBS_OPT_XTRN_MINIMIZED);
452

453 454
		bbs->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count);
		bbs->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
rswindell's avatar
rswindell committed
455 456

		bbs->login_attempt = get_login_attempt_settings(list, section, global);
457
		bbs->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
458
	}
459 460

	/***********************************************************************/
461
	section = "FTP";
462

463
	if(run_ftp!=NULL)
464
		*run_ftp=iniGetBool(list,section,strAutoStart,TRUE);
465

466
	if(ftp!=NULL) {
467

deuce's avatar
deuce committed
468 469 470 471
		ftp->outgoing4.s_addr
			=iniGetIpAddress(list,section,strOutgoing4,global->outgoing4.s_addr);
		ftp->outgoing6
			=iniGetIp6Address(list,section,strOutgoing6,global->outgoing6);
472
		ftp->port
473
			=iniGetShortInt(list,section,strPort,IPPORT_FTP);
474 475 476
		iniFreeStringList(ftp->interfaces);
		ftp->interfaces
			=iniGetStringList(list,section,strInterfaces,",",global_interfaces);
477
		ftp->max_clients
478
			=iniGetShortInt(list,section,strMaxClients,FTP_DEFAULT_MAX_CLIENTS);
479
		ftp->max_inactivity
480
			=iniGetShortInt(list,section,strMaxInactivity,FTP_DEFAULT_MAX_INACTIVITY);	/* seconds */
481
		ftp->qwk_timeout
482
			=iniGetShortInt(list,section,"QwkTimeout",FTP_DEFAULT_QWK_TIMEOUT);		/* seconds */
483
		ftp->sem_chk_freq
484
			=iniGetShortInt(list,section,strSemFileCheckFrequency,global->sem_chk_freq);
485 486 487 488
		ftp->min_fsize
			=iniGetBytes(list,section,"MinFileSize",1,0);
		ftp->max_fsize
			=iniGetBytes(list,section,"MaxFileSize",1,0);
489

490
		/* Passive transfer settings (for stupid firewalls/NATs) */
deuce's avatar
deuce committed
491
		ftp->pasv_ip_addr.s_addr
492
			=iniGetIpAddress(list,section,"PasvIpAddress",0);
deuce's avatar
deuce committed
493 494
		ftp->pasv_ip6_addr
			=iniGetIp6Address(list,section,"PasvIp6Address",wildcard6);
495
		ftp->pasv_port_low
496
			=iniGetShortInt(list,section,"PasvPortLow",IPPORT_RESERVED);
497
		ftp->pasv_port_high
498
			=iniGetShortInt(list,section,"PasvPortHigh",0xffff);
499

500
		SAFECOPY(ftp->host_name
501
			,iniGetString(list,section,strHostName,global->host_name,value));
502 503

		SAFECOPY(ftp->index_file_name
504
			,iniGetString(list,section,"IndexFileName","00index",value));
505

506
		sbbs_get_sound_settings(list, section, &ftp->sound, &global->sound);
507

508
		SAFECOPY(ftp->temp_dir
509
			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
510

511 512
		ftp->log_level
			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
513
		ftp->options
514
			=iniGetBitField(list,section,strOptions,ftp_options
515
				,FTP_OPT_INDEX_FILE | FTP_OPT_ALLOW_QWK);
516

517 518
		ftp->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count);
		ftp->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
rswindell's avatar
rswindell committed
519
		ftp->login_attempt = get_login_attempt_settings(list, section, global);
520
		ftp->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
521
	}
522 523

	/***********************************************************************/
524
	section = "Mail";
525

526
	if(run_mail!=NULL)
527
		*run_mail=iniGetBool(list,section,strAutoStart,TRUE);
528

529
	if(mail!=NULL) {
530

531 532
		iniFreeStringList(mail->interfaces);
		mail->interfaces
533
			=iniGetStringList(list,section,strInterfaces,",",global_interfaces);
deuce's avatar
deuce committed
534 535 536 537
		mail->outgoing4.s_addr
			=iniGetIpAddress(list,section,strOutgoing4,global->outgoing4.s_addr);
		mail->outgoing6
			=iniGetIp6Address(list,section,strOutgoing6,global->outgoing6);
538
		mail->smtp_port
539
			=iniGetShortInt(list,section,"SMTPPort",IPPORT_SMTP);
540 541
		mail->submission_port
			=iniGetShortInt(list,section,"SubmissionPort",IPPORT_SUBMISSION);
542
		mail->submissions_port
543
			=iniGetShortInt(list,section,"TLSSubmissionPort",IPPORT_SUBMISSIONS);
544 545 546
		iniFreeStringList(mail->pop3_interfaces);
		mail->pop3_interfaces
			=iniGetStringList(list,section,"POP3Interface",",",global_interfaces);
547
		mail->pop3_port
548
			=iniGetShortInt(list,section,"POP3Port",IPPORT_POP3);
549
		mail->pop3s_port
550
			=iniGetShortInt(list,section,"TLSPOP3Port",IPPORT_POP3S);
551
		mail->relay_port
552
			=iniGetShortInt(list,section,"RelayPort",IPPORT_SMTP);
553
		mail->max_clients
554
			=iniGetShortInt(list,section,strMaxClients,MAIL_DEFAULT_MAX_CLIENTS);
555
		mail->max_inactivity
556
			=iniGetShortInt(list,section,strMaxInactivity,MAIL_DEFAULT_MAX_INACTIVITY);		/* seconds */
557
		mail->max_delivery_attempts
558
			=iniGetShortInt(list,section,"MaxDeliveryAttempts",MAIL_DEFAULT_MAX_DELIVERY_ATTEMPTS);
559
		mail->rescan_frequency
560
			=iniGetShortInt(list,section,"RescanFrequency",MAIL_DEFAULT_RESCAN_FREQUENCY);	/* 60 minutes */
561
		mail->sem_chk_freq
562
			=iniGetShortInt(list,section,strSemFileCheckFrequency,global->sem_chk_freq);
563
		mail->lines_per_yield
564
			=iniGetShortInt(list,section,"LinesPerYield",MAIL_DEFAULT_LINES_PER_YIELD);
565
		mail->max_recipients
566
			=iniGetShortInt(list,section,"MaxRecipients",MAIL_DEFAULT_MAX_RECIPIENTS);
567
		mail->max_msg_size
568
			=(DWORD)iniGetBytes(list,section,"MaxMsgSize",/* units: */1,MAIL_DEFAULT_MAX_MSG_SIZE);
rswindell's avatar
rswindell committed
569
		mail->max_msgs_waiting
570
			=iniGetInteger(list,section,"MaxMsgsWaiting",MAIL_DEFAULT_MAX_MSGS_WAITING);
571
		mail->connect_timeout
572
			=iniGetInteger(list,section,"ConnectTimeout",MAIL_DEFAULT_CONNECT_TIMEOUT);
573 574

		SAFECOPY(mail->host_name
575
			,iniGetString(list,section,strHostName,global->host_name,value));
576

rswindell's avatar
rswindell committed
577
		SAFECOPY(mail->temp_dir
578
			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
rswindell's avatar
rswindell committed
579

580
		SAFECOPY(mail->relay_server
581
			,iniGetString(list,section,"RelayServer",nulstr,value));
582
		SAFECOPY(mail->relay_user
583
			,iniGetString(list,section,"RelayUsername",nulstr,value));
584
		SAFECOPY(mail->relay_pass
585
			,iniGetString(list,section,"RelayPassword",nulstr,value));
586

587
		SAFECOPY(mail->dns_server
588
			,iniGetString(list,section,"DNSServer",nulstr,value));
589 590

		SAFECOPY(mail->default_user
591
			,iniGetString(list,section,"DefaultUser",nulstr,value));
592 593

		SAFECOPY(mail->dnsbl_hdr
594
			,iniGetString(list,section,"DNSBlacklistHeader","X-DNSBL",value));
595
		SAFECOPY(mail->dnsbl_tag
596
			,iniGetString(list,section,"DNSBlacklistSubject","SPAM",value));
597 598

		SAFECOPY(mail->pop3_sound
599
			,iniGetString(list,section,"POP3Sound",nulstr,value));
600
		SAFECOPY(mail->inbound_sound
601
			,iniGetString(list,section,"InboundSound",nulstr,value));
602
		SAFECOPY(mail->outbound_sound
603
			,iniGetString(list,section,"OutboundSound",nulstr,value));
604
		sbbs_get_sound_settings(list, section, &mail->sound, &global->sound);
605

606 607 608 609 610
		SAFECOPY(mail->newmail_notice
			,iniGetString(list,section,"NewMailNotice","%.0s\1n\1mNew e-mail from \1h%s \1n<\1h%s\1n>\r\n", value));
		SAFECOPY(mail->forward_notice
			,iniGetString(list,section,"ForwardNotice","\1n\1mand it was automatically forwarded to: \1h%s\1n\r\n", value));
	
611
		/* JavaScript Operating Parameters */
612
		sbbs_get_js_settings(list, section, &mail->js, &global->js);
613

614 615
		mail->log_level
			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
616
		mail->options
617
			=iniGetBitField(list,section,strOptions,mail_options
618
				,MAIL_OPT_ALLOW_POP3);
619

620 621
		mail->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count);
		mail->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
rswindell's avatar
rswindell committed
622
		mail->login_attempt = get_login_attempt_settings(list, section, global);
623
		mail->max_concurrent_connections = iniGetInteger(list, section, strMaxConConn, 0);
624
	}
625 626

	/***********************************************************************/
627
	section = "Services";
628

629
	if(run_services!=NULL)
630
		*run_services=iniGetBool(list,section,strAutoStart,TRUE);
631

632
	if(services!=NULL) {
633

634 635 636
		iniFreeStringList(services->interfaces);
		services->interfaces
			=iniGetStringList(list,section,strInterfaces,",",global_interfaces);
deuce's avatar
deuce committed
637 638 639 640
		services->outgoing4.s_addr
			=iniGetIpAddress(list,section,strOutgoing4,global->outgoing4.s_addr);
		services->outgoing6
			=iniGetIp6Address(list,section,strOutgoing6,global->outgoing6);
641

642
		services->sem_chk_freq
643
			=iniGetShortInt(list,section,strSemFileCheckFrequency,global->sem_chk_freq);
644

645
		/* JavaScript operating parameters */
646
		sbbs_get_js_settings(list, section, &services->js, &global->js);
647

648
		SAFECOPY(services->host_name
649
			,iniGetString(list,section,strHostName,global->host_name,value));
650

rswindell's avatar
rswindell committed
651
		SAFECOPY(services->temp_dir
652
			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
rswindell's avatar
rswindell committed
653

654
		SAFECOPY(services->services_ini
Rob Swindell's avatar
Rob Swindell committed
655
			,iniGetString(list, section, strIniFileName, "services.ini", value));
656

657
		sbbs_get_sound_settings(list, section, &services->sound, &global->sound);
658

659 660
		services->log_level
			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
661
		services->options
662
			=iniGetBitField(list,section,strOptions,service_options
663
				,BBS_OPT_NO_HOST_LOOKUP);
664

665 666
		services->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count);
		services->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay);
rswindell's avatar
rswindell committed
667
		services->login_attempt = get_login_attempt_settings(list, section, global);
668
	}
669

670
	/***********************************************************************/
671
	section = "Web";
672

673
	if(run_web!=NULL)
674
		*run_web=iniGetBool(list,section,strAutoStart,FALSE);
675

676
	if(web!=NULL) {
677

678 679 680 681 682 683
		iniFreeStringList(web->interfaces);
		web->interfaces
			=iniGetStringList(list,section,strInterfaces,",",global_interfaces);
		iniFreeStringList(web->tls_interfaces);
		web->tls_interfaces
			=iniGetStringList(list,section,"TLSInterface",",",global_interfaces);
684
		web->port