From b8ce6208441f2a4a128d0310851a13bae1f9954c Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Thu, 21 Apr 2005 06:44:38 +0000
Subject: [PATCH] Using js_startup_t for the JS startup parameters for all
 servers/services. Created sbbs_read_js_settings() and sbbs_set_js_settings()
 to read and write all settings to/from .ini files in a modular fashion. This
 is a precursor to implementing support for JavaScriptThreadStack (limit)
 support for all JS-enabled servers and services (working around the ircd
 bug).

---
 src/sbbs3/ftpsrvr.c  |  12 +--
 src/sbbs3/ftpsrvr.h  |   7 +-
 src/sbbs3/mailsrvr.c |  12 +--
 src/sbbs3/mailsrvr.h |   7 +-
 src/sbbs3/main.cpp   |  20 ++--
 src/sbbs3/sbbs_ini.c | 212 ++++++++++++++++---------------------------
 src/sbbs3/sbbs_ini.h |  22 +++--
 src/sbbs3/services.c |  34 +++----
 src/sbbs3/services.h |   8 +-
 src/sbbs3/startup.h  |  19 ++--
 src/sbbs3/websrvr.c  |  18 ++--
 src/sbbs3/websrvr.h  |  12 +--
 12 files changed, 164 insertions(+), 219 deletions(-)

diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index bcd89c06fd..ef4a2e9bca 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -483,9 +483,9 @@ js_initcx(JSRuntime* runtime, SOCKET sock, JSObject** glob, JSObject** ftp)
 	BOOL		success=FALSE;
 
 	lprintf(LOG_DEBUG,"%04d JavaScript: Initializing context (stack: %lu bytes)"
-		,sock,startup->js_cx_stack);
+		,sock,startup->js.cx_stack);
 
-    if((js_cx = JS_NewContext(runtime, startup->js_cx_stack))==NULL)
+    if((js_cx = JS_NewContext(runtime, startup->js.cx_stack))==NULL)
 		return(NULL);
 
 	lprintf(LOG_DEBUG,"%04d JavaScript: Context created",sock);
@@ -3794,9 +3794,9 @@ static void ctrl_thread(void* arg)
 				}
 				if(js_runtime == NULL) {
 					lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes"
-						,sock,startup->js_max_bytes);
+						,sock,startup->js.max_bytes);
 
-					if((js_runtime = JS_NewRuntime(startup->js_max_bytes))==NULL) {
+					if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL) {
 						lprintf(LOG_ERR,"%04d !ERROR creating JavaScript runtime",sock);
 						sockprintf(sock,"451 Error creating JavaScript runtime");
 						filepos=0;
@@ -4543,8 +4543,8 @@ void DLLCALL ftp_server(void* arg)
 	else
 		startup->options|=FTP_OPT_NO_JAVASCRIPT;
 #ifdef JAVASCRIPT
-	if(startup->js_max_bytes==0)			startup->js_max_bytes=JAVASCRIPT_MAX_BYTES;
-	if(startup->js_cx_stack==0)				startup->js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
+	if(startup->js.max_bytes==0)			startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
+	if(startup->js.cx_stack==0)				startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
 
 	sprintf(js_server_props.version,"%s %s",FTP_SERVER,revision);
 	js_server_props.version_detail=ftp_ver();
diff --git a/src/sbbs3/ftpsrvr.h b/src/sbbs3/ftpsrvr.h
index 32443a01f8..72559d8580 100644
--- a/src/sbbs3/ftpsrvr.h
+++ b/src/sbbs3/ftpsrvr.h
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -50,8 +50,6 @@ typedef struct {
 	WORD	sem_chk_freq;		/* semaphore file checking frequency (in seconds) */
     DWORD   interface_addr;
     DWORD	options;			/* See FTP_OPT definitions */
-    DWORD	js_max_bytes;
-	DWORD	js_cx_stack;
 
 	void*	cbdata;				/* Private data passed to callbacks */ 
 
@@ -86,6 +84,9 @@ typedef struct {
 	uint	bind_retry_count;		/* Number of times to retry bind() calls */
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 
+	/* JavaScript operating parameters */
+	js_startup_t js;
+
 } ftp_startup_t;
 
 /* startup options that requires re-initialization/recycle when changed */
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 3c6c22d661..941959dbef 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -1504,15 +1504,15 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user
 	do {
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes\n"
-			,sock, startup->js_max_bytes);
+			,sock, startup->js.max_bytes);
 
-		if((js_runtime = JS_NewRuntime(startup->js_max_bytes))==NULL)
+		if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL)
 			break;
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Initializing context (stack: %lu bytes)\n"
-			,sock, startup->js_cx_stack);
+			,sock, startup->js.cx_stack);
 
-		if((js_cx = JS_NewContext(js_runtime, startup->js_cx_stack))==NULL)
+		if((js_cx = JS_NewContext(js_runtime, startup->js.cx_stack))==NULL)
 			break;
 
 		JS_SetErrorReporter(js_cx, js_ErrorReporter);
@@ -3991,8 +3991,8 @@ void DLLCALL mail_server(void* arg)
 	if(startup->sem_chk_freq==0)			startup->sem_chk_freq=2;
 
 #ifdef JAVASCRIPT
-	if(startup->js_max_bytes==0)			startup->js_max_bytes=JAVASCRIPT_MAX_BYTES;
-	if(startup->js_cx_stack==0)				startup->js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
+	if(startup->js.max_bytes==0)			startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
+	if(startup->js.cx_stack==0)				startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
 #endif
 
 	uptime=0;
diff --git a/src/sbbs3/mailsrvr.h b/src/sbbs3/mailsrvr.h
index e5f9f959b3..9fca2c168d 100644
--- a/src/sbbs3/mailsrvr.h
+++ b/src/sbbs3/mailsrvr.h
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -57,8 +57,6 @@ typedef struct {
     DWORD   interface_addr;
     DWORD	options;			/* See MAIL_OPT definitions */
     DWORD	max_msg_size;
-    DWORD	js_max_bytes;
-	DWORD	js_cx_stack;
 
 	void*	cbdata;				/* Private data passed to callbacks */ 
 
@@ -102,6 +100,9 @@ typedef struct {
 	char	relay_user[128];
 	char	relay_pass[128];
 
+	/* JavaScript operating parameters */
+	js_startup_t js;
+
 } mail_startup_t;
 
 /* startup options that requires re-initialization/recycle when changed */
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 6f365e1608..8a506819d9 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -870,21 +870,21 @@ bool sbbs_t::js_init()
     	strcpy(node,client_name);
 
 	lprintf(LOG_DEBUG,"%s JavaScript: Creating runtime: %lu bytes"
-		,node,startup->js_max_bytes);
+		,node,startup->js.max_bytes);
 
-	if((js_runtime = JS_NewRuntime(startup->js_max_bytes))==NULL)
+	if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL)
 		return(false);
 
 	lprintf(LOG_DEBUG,"%s JavaScript: Initializing context (stack: %lu bytes)"
-		,node,startup->js_cx_stack);
+		,node,startup->js.cx_stack);
 
-    if((js_cx = JS_NewContext(js_runtime, startup->js_cx_stack))==NULL)
+    if((js_cx = JS_NewContext(js_runtime, startup->js.cx_stack))==NULL)
 		return(false);
 	
 	memset(&js_branch,0,sizeof(js_branch));
-	js_branch.limit = startup->js_branch_limit;
-	js_branch.gc_interval = startup->js_gc_interval;
-	js_branch.yield_interval = startup->js_yield_interval;
+	js_branch.limit = startup->js.branch_limit;
+	js_branch.gc_interval = startup->js.gc_interval;
+	js_branch.yield_interval = startup->js.yield_interval;
 	js_branch.terminated = &terminated;
 	js_branch.auto_terminate = TRUE;
 
@@ -3751,8 +3751,8 @@ void DLLCALL bbs_thread(void* arg)
 	if(startup->rlogin_port==0)				startup->rlogin_port=513;
 	if(startup->xtrn_polls_before_yield==0)	startup->xtrn_polls_before_yield=10;
 #ifdef JAVASCRIPT
-	if(startup->js_max_bytes==0)			startup->js_max_bytes=JAVASCRIPT_MAX_BYTES;
-	if(startup->js_cx_stack==0)				startup->js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
+	if(startup->js.max_bytes==0)			startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
+	if(startup->js.cx_stack==0)				startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
 #endif
 	if(startup->outbuf_drain_timeout==0)	startup->outbuf_drain_timeout=10;
 	if(startup->sem_chk_freq==0)			startup->sem_chk_freq=2;
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index 5091abf121..f418025a90 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -50,6 +50,13 @@ static const char*	strHostName="HostName";
 static const char*	strLogMask="LogMask";
 static const char*	strBindRetryCount="BindRetryCount";
 static const char*	strBindRetryDelay="BindRetryDelay";
+static const char*	strJavaScriptMaxBytes		="JavaScriptMaxBytes";
+static const char*	strJavaScriptContextStack	="JavaScriptContextStack";
+static const char*	strJavaScriptThreadStack	="JavaScriptThreadStack";
+static const char*	strJavaScriptBranchLimit	="JavaScriptBranchLimit";
+static const char*	strJavaScriptGcInterval		="JavaScriptGcInterval";
+static const char*	strJavaScriptYieldInterval	="JavaScriptYieldInterval";
+static const char*	strSemFileCheckFrequency	="SemFileCheckFrequency";
 
 #if defined(SBBSNTSVCS) && 0	/* sbbs_ini.obj is shared with sbbs.exe (!) */
 	#define DEFAULT_LOG_MASK		0x3f	/* EMERG|ALERT|CRIT|ERR|WARNING|NOTICE */
@@ -100,6 +107,57 @@ void sbbs_get_ini_fname(char* ini_file, char* ctrl_dir, char* pHostName)
 	iniFileName(ini_file,MAX_PATH,ctrl_dir,"startup.ini");
 }
 
+void sbbs_read_js_settings(
+	 FILE* fp
+	,const char* section
+	,js_startup_t* js
+	,js_startup_t* defaults)
+{
+	js->max_bytes		= iniReadInteger(fp,section,strJavaScriptMaxBytes		,defaults->max_bytes);
+	js->cx_stack		= iniReadInteger(fp,section,strJavaScriptContextStack	,defaults->cx_stack);
+	js->thread_stack	= iniReadInteger(fp,section,strJavaScriptThreadStack	,defaults->thread_stack);
+	js->branch_limit	= iniReadInteger(fp,section,strJavaScriptBranchLimit	,defaults->branch_limit);
+	js->gc_interval		= iniReadInteger(fp,section,strJavaScriptGcInterval		,defaults->gc_interval);
+	js->yield_interval	= iniReadInteger(fp,section,strJavaScriptYieldInterval	,defaults->yield_interval);
+}
+
+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;
+
+	if(js->max_bytes==defaults->max_bytes)
+		failure|=iniRemoveValue(lp,section,strJavaScriptMaxBytes);
+	else
+		failure|=iniSetInteger(lp,section,strJavaScriptMaxBytes,js->max_bytes,style)==NULL;
+
+	if(js->cx_stack==defaults->cx_stack)
+		failure|=iniRemoveValue(lp,section,strJavaScriptContextStack);
+	else 
+		failure|=iniSetInteger(lp,section,strJavaScriptContextStack,js->cx_stack,style)==NULL;
+
+	if(js->thread_stack==defaults->thread_stack)
+		failure|=iniRemoveValue(lp,section,strJavaScriptThreadStack);
+	else 
+		failure|=iniSetInteger(lp,section,strJavaScriptThreadStack,js->thread_stack,style)==NULL;
+
+	if(js->branch_limit==defaults->branch_limit)
+		failure|=iniRemoveValue(lp,section,strJavaScriptBranchLimit);
+	else
+		failure|=iniSetInteger(lp,section,strJavaScriptBranchLimit,js->branch_limit,style)==NULL;
+
+	if(js->gc_interval==defaults->gc_interval)
+		failure|=iniRemoveValue(lp,section,strJavaScriptGcInterval);
+	else 
+		failure|=iniSetInteger(lp,section,strJavaScriptGcInterval,js->gc_interval,style)==NULL;
+
+	return(!failure);
+}
+
 static void read_ini_globals(FILE* fp, global_startup_t* global)
 {
 	const char* section = "Global";
@@ -132,11 +190,16 @@ static void read_ini_globals(FILE* fp, global_startup_t* global)
 	global->bind_retry_count=iniReadInteger(fp,section,strBindRetryCount,DEFAULT_BIND_RETRY_COUNT);
 	global->bind_retry_delay=iniReadInteger(fp,section,strBindRetryDelay,DEFAULT_BIND_RETRY_DELAY);
 
-	global->js.max_bytes		= iniReadInteger(fp,section,strJavaScriptMaxBytes		,JAVASCRIPT_MAX_BYTES);
-	global->js.cx_stack			= iniReadInteger(fp,section,strJavaScriptContextStack	,JAVASCRIPT_CONTEXT_STACK);
-	global->js.branch_limit		= iniReadInteger(fp,section,strJavaScriptBranchLimit	,JAVASCRIPT_BRANCH_LIMIT);
-	global->js.gc_interval		= iniReadInteger(fp,section,strJavaScriptGcInterval		,JAVASCRIPT_GC_INTERVAL);
-	global->js.yield_interval	= iniReadInteger(fp,section,strJavaScriptYieldInterval	,JAVASCRIPT_YIELD_INTERVAL);
+	/* Setup default values here */
+	global->js.max_bytes		= JAVASCRIPT_MAX_BYTES;
+	global->js.cx_stack			= JAVASCRIPT_CONTEXT_STACK;
+	global->js.thread_stack		= JAVASCRIPT_THREAD_STACK;
+	global->js.branch_limit		= JAVASCRIPT_BRANCH_LIMIT;
+	global->js.gc_interval		= JAVASCRIPT_GC_INTERVAL;
+	global->js.yield_interval	= JAVASCRIPT_YIELD_INTERVAL;
+
+	/* Read .ini values here */
+	sbbs_read_js_settings(fp, section, &global->js, &global->js);
 }
 
 
@@ -218,16 +281,7 @@ void sbbs_read_ini(
 			=iniReadInteger(fp,section,"ExternalYield",10);
 
 		/* JavaScript operating parameters */
-		bbs->js_max_bytes
-			=iniReadInteger(fp,section,strJavaScriptMaxBytes		,global->js.max_bytes);
-		bbs->js_cx_stack
-			=iniReadInteger(fp,section,strJavaScriptContextStack	,global->js.cx_stack);
-		bbs->js_branch_limit
-			=iniReadInteger(fp,section,strJavaScriptBranchLimit	,global->js.branch_limit);
-		bbs->js_gc_interval
-			=iniReadInteger(fp,section,strJavaScriptGcInterval	,global->js.gc_interval);
-		bbs->js_yield_interval
-			=iniReadInteger(fp,section,strJavaScriptYieldInterval,global->js.yield_interval);
+		sbbs_read_js_settings(fp, section, &bbs->js, &global->js);
 
 		SAFECOPY(bbs->host_name
 			,iniReadString(fp,section,strHostName,global->host_name,value));
@@ -293,10 +347,7 @@ void sbbs_read_ini(
 			=iniReadShortInt(fp,section,strSemFileCheckFrequency,global->sem_chk_freq);
 
 		/* JavaScript Operating Parameters */
-		ftp->js_max_bytes
-			=iniReadInteger(fp,section,strJavaScriptMaxBytes		,global->js.max_bytes);
-		ftp->js_cx_stack
-			=iniReadInteger(fp,section,strJavaScriptContextStack	,global->js.cx_stack);
+		sbbs_read_js_settings(fp, section, &ftp->js, &global->js);
 
 		SAFECOPY(ftp->host_name
 			,iniReadString(fp,section,strHostName,global->host_name,value));
@@ -393,10 +444,7 @@ void sbbs_read_ini(
 			,iniReadString(fp,section,"OutboundSound",nulstr,value));
 
 		/* JavaScript Operating Parameters */
-		mail->js_max_bytes
-			=iniReadInteger(fp,section,strJavaScriptMaxBytes		,global->js.max_bytes);
-		mail->js_cx_stack
-			=iniReadInteger(fp,section,strJavaScriptContextStack	,global->js.cx_stack);
+		sbbs_read_js_settings(fp, section, &mail->js, &global->js);
 
 		mail->log_mask
 			=iniReadBitField(fp,section,strLogMask,log_mask_bits,global->log_mask);
@@ -422,17 +470,8 @@ void sbbs_read_ini(
 		services->sem_chk_freq
 			=iniReadShortInt(fp,section,strSemFileCheckFrequency,global->sem_chk_freq);
 
-		/* Configurable JavaScript default parameters */
-		services->js_max_bytes
-			=iniReadInteger(fp,section,strJavaScriptMaxBytes		,global->js.max_bytes);
-		services->js_cx_stack
-			=iniReadInteger(fp,section,strJavaScriptContextStack	,global->js.cx_stack);
-		services->js_branch_limit
-			=iniReadInteger(fp,section,strJavaScriptBranchLimit	,global->js.branch_limit);
-		services->js_gc_interval
-			=iniReadInteger(fp,section,strJavaScriptGcInterval	,global->js.gc_interval);
-		services->js_yield_interval
-			=iniReadInteger(fp,section,strJavaScriptYieldInterval,global->js.yield_interval);
+		/* JavaScript operating parameters */
+		sbbs_read_js_settings(fp, section, &services->js, &global->js);
 
 		SAFECOPY(services->host_name
 			,iniReadString(fp,section,strHostName,global->host_name,value));
@@ -474,17 +513,8 @@ void sbbs_read_ini(
 		web->sem_chk_freq
 			=iniReadShortInt(fp,section,strSemFileCheckFrequency,global->sem_chk_freq);
 
-		/* JavaScript Operating Parameters */
-		web->js_max_bytes
-			=iniReadInteger(fp,section,strJavaScriptMaxBytes		,global->js.max_bytes);
-		web->js_cx_stack
-			=iniReadInteger(fp,section,strJavaScriptContextStack	,global->js.cx_stack);
-		web->js_branch_limit
-			=iniReadInteger(fp,section,strJavaScriptBranchLimit		,global->js.branch_limit);
-		web->js_gc_interval
-			=iniReadInteger(fp,section,strJavaScriptGcInterval		,global->js.gc_interval);
-		web->js_yield_interval
-			=iniReadInteger(fp,section,strJavaScriptYieldInterval	,global->js.yield_interval);
+		/* JavaScript operating parameters */
+		sbbs_read_js_settings(fp, section, &web->js, &global->js);
 
 		SAFECOPY(web->host_name
 			,iniReadString(fp,section,strHostName,global->host_name,value));
@@ -686,30 +716,7 @@ BOOL sbbs_write_ini(
 			break;
 
 		/* JavaScript operating parameters */
-		
-		if(bbs->js_max_bytes==global->js.max_bytes)
-			iniRemoveValue(lp,section,strJavaScriptMaxBytes);
-		else if(!iniSetInteger(lp,section,strJavaScriptMaxBytes		,bbs->js_max_bytes,&style))
-			break;
-
-		if(bbs->js_cx_stack==global->js.cx_stack)
-			iniRemoveValue(lp,section,strJavaScriptContextStack);
-		else if(!iniSetInteger(lp,section,strJavaScriptContextStack	,bbs->js_cx_stack,&style))
-			break;
-
-		if(bbs->js_branch_limit==global->js.branch_limit)
-			iniRemoveValue(lp,section,strJavaScriptBranchLimit);
-		else if(!iniSetInteger(lp,section,strJavaScriptBranchLimit	,bbs->js_branch_limit,&style))
-			break;
-
-		if(bbs->js_gc_interval==global->js.gc_interval)
-			iniRemoveValue(lp,section,strJavaScriptGcInterval);
-		else if(!iniSetInteger(lp,section,strJavaScriptGcInterval	,bbs->js_gc_interval,&style))
-			break;
-
-		if(bbs->js_yield_interval==global->js.yield_interval)
-			iniRemoveValue(lp,section,strJavaScriptYieldInterval);
-		else if(!iniSetInteger(lp,section,strJavaScriptYieldInterval,bbs->js_yield_interval,&style))
+		if(!sbbs_set_js_settings(lp,section,&bbs->js,&global->js,&style))
 			break;
 
 		if(strcmp(bbs->host_name,global->host_name)==0
@@ -780,15 +787,7 @@ BOOL sbbs_write_ini(
 			break;
 
 		/* JavaScript Operating Parameters */
-		
-		if(ftp->js_max_bytes==global->js.max_bytes)
-			iniRemoveValue(lp,section,strJavaScriptMaxBytes);
-		else if(!iniSetInteger(lp,section,strJavaScriptMaxBytes		,ftp->js_max_bytes,&style))
-			break;
-
-		if(ftp->js_cx_stack==global->js.cx_stack)
-			iniRemoveValue(lp,section,strJavaScriptContextStack);
-		else if(!iniSetInteger(lp,section,strJavaScriptContextStack	,ftp->js_cx_stack,&style))
+		if(!sbbs_set_js_settings(lp,section,&ftp->js,&global->js,&style))
 			break;
 
 		if(strcmp(ftp->host_name,global->host_name)==0
@@ -910,14 +909,7 @@ BOOL sbbs_write_ini(
 			break;
 
 		/* JavaScript Operating Parameters */
-		if(mail->js_max_bytes==global->js.max_bytes)
-			iniRemoveValue(lp,section,strJavaScriptMaxBytes);
-		else if(!iniSetInteger(lp,section,strJavaScriptMaxBytes		,mail->js_max_bytes,&style))
-			break;
-
-		if(mail->js_cx_stack==global->js.cx_stack)
-			iniRemoveValue(lp,section,strJavaScriptContextStack);
-		else if(!iniSetInteger(lp,section,strJavaScriptContextStack	,mail->js_cx_stack,&style))
+		if(!sbbs_set_js_settings(lp,section,&mail->js,&global->js,&style))
 			break;
 
 		if(!iniSetBitField(lp,section,strOptions,mail_options,mail->options,&style))
@@ -957,29 +949,7 @@ BOOL sbbs_write_ini(
 			break;
 
 		/* Configurable JavaScript default parameters */
-		if(services->js_max_bytes==global->js.max_bytes)
-			iniRemoveValue(lp,section,strJavaScriptMaxBytes);
-		else if(!iniSetInteger(lp,section,strJavaScriptMaxBytes		,services->js_max_bytes,&style))
-			break;
-
-		if(services->js_cx_stack==global->js.cx_stack)
-			iniRemoveValue(lp,section,strJavaScriptContextStack);
-		else if(!iniSetInteger(lp,section,strJavaScriptContextStack	,services->js_cx_stack,&style))
-			break;
-
-		if(services->js_branch_limit==global->js.branch_limit)
-			iniRemoveValue(lp,section,strJavaScriptBranchLimit);
-		else if(!iniSetInteger(lp,section,strJavaScriptBranchLimit	,services->js_branch_limit,&style))
-			break;
-
-		if(services->js_gc_interval==global->js.gc_interval)
-			iniRemoveValue(lp,section,strJavaScriptGcInterval);
-		else if(!iniSetInteger(lp,section,strJavaScriptGcInterval	,services->js_gc_interval,&style))
-			break;
-
-		if(services->js_yield_interval==global->js.yield_interval)
-			iniRemoveValue(lp,section,strJavaScriptYieldInterval);
-		else if(!iniSetInteger(lp,section,strJavaScriptYieldInterval	,services->js_yield_interval,&style))
+		if(!sbbs_set_js_settings(lp,section,&services->js,&global->js,&style))
 			break;
 
 		if(strcmp(services->host_name,global->host_name)==0
@@ -1042,29 +1012,7 @@ BOOL sbbs_write_ini(
 			break;
 
 		/* JavaScript Operating Parameters */
-		if(web->js_max_bytes==global->js.max_bytes)
-			iniRemoveValue(lp,section,strJavaScriptMaxBytes);
-		else if(!iniSetInteger(lp,section,strJavaScriptMaxBytes		,web->js_max_bytes,&style))
-			break;
-
-		if(web->js_cx_stack==global->js.cx_stack)
-			iniRemoveValue(lp,section,strJavaScriptContextStack);
-		else if(!iniSetInteger(lp,section,strJavaScriptContextStack	,web->js_cx_stack,&style))
-			break;
-
-		if(web->js_branch_limit==global->js.branch_limit)
-			iniRemoveValue(lp,section,strJavaScriptBranchLimit);
-		else if(!iniSetInteger(lp,section,strJavaScriptBranchLimit	,web->js_branch_limit,&style))
-			break;
-
-		if(web->js_gc_interval==global->js.gc_interval)
-			iniRemoveValue(lp,section,strJavaScriptGcInterval);
-		else if(!iniSetInteger(lp,section,strJavaScriptGcInterval	,web->js_gc_interval,&style))
-			break;
-
-		if(web->js_yield_interval==global->js.yield_interval)
-			iniRemoveValue(lp,section,strJavaScriptYieldInterval);
-		else if(!iniSetInteger(lp,section,strJavaScriptYieldInterval,web->js_yield_interval,&style))
+		if(!sbbs_set_js_settings(lp,section,&web->js,&global->js,&style))
 			break;
 
 		if(strcmp(web->host_name,global->host_name)==0
diff --git a/src/sbbs3/sbbs_ini.h b/src/sbbs3/sbbs_ini.h
index 81838a4884..5112af11a9 100644
--- a/src/sbbs3/sbbs_ini.h
+++ b/src/sbbs3/sbbs_ini.h
@@ -46,13 +46,6 @@
 #include "ini_file.h"
 #include "scfgdefs.h"   /* scfg_t */
 
-#define strJavaScriptMaxBytes		"JavaScriptMaxBytes"
-#define strJavaScriptContextStack	"JavaScriptContextStack"
-#define strJavaScriptBranchLimit	"JavaScriptBranchLimit"
-#define strJavaScriptGcInterval		"JavaScriptGcInterval"
-#define strJavaScriptYieldInterval	"JavaScriptYieldInterval"
-#define strSemFileCheckFrequency	"SemFileCheckFrequency"
-
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -78,6 +71,21 @@ void sbbs_read_ini(
 	,services_startup_t*	services_startup
 	);
 
+void sbbs_read_js_settings(
+	 FILE* fp
+	,const char* section
+	,js_startup_t* js
+	,js_startup_t* defaults
+	);
+
+BOOL sbbs_set_js_settings(
+	 str_list_t* list
+	,const char* section
+	,js_startup_t* js
+	,js_startup_t* defaults
+	,ini_style_t*
+	);
+
 BOOL sbbs_write_ini(
 	 FILE*					fp
     ,scfg_t*                cfg
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 1e53bfb567..2b5cbf6631 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -97,11 +97,7 @@ typedef struct {
 	DWORD	options;
 	int		listen_backlog;
 	DWORD	stack_size;
-    DWORD	js_max_bytes;
-	DWORD	js_cx_stack;
-	DWORD	js_branch_limit;
-	DWORD	js_yield_interval;
-	DWORD	js_gc_interval;
+	js_startup_t	js;
 	js_server_props_t js_server_props;
 	/* These are run-time state and stat vars */
 	DWORD	clients;
@@ -776,7 +772,7 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 	JSObject*	server;
 	BOOL		success=FALSE;
 
-    if((js_cx = JS_NewContext(js_runtime, service_client->service->js_cx_stack))==NULL)
+    if((js_cx = JS_NewContext(js_runtime, service_client->service->js.cx_stack))==NULL)
 		return(NULL);
 
     JS_SetErrorReporter(js_cx, js_ErrorReporter);
@@ -1044,7 +1040,7 @@ static void js_service_thread(void* arg)
 	/* Initialize client display */
 	client_on(socket,&client,FALSE /* update */);
 
-	if((js_runtime=JS_NewRuntime(service->js_max_bytes))==NULL
+	if((js_runtime=JS_NewRuntime(service->js.max_bytes))==NULL
 		|| (js_cx=js_initcx(js_runtime,socket,&service_client,&js_glob))==NULL) {
 		lprintf(LOG_ERR,"%04d !%s ERROR initializing JavaScript context"
 			,socket,service->protocol);
@@ -1150,13 +1146,13 @@ static void js_static_service_thread(void* arg)
 	memset(&service_client,0,sizeof(service_client));
 	service_client.socket = service->socket;
 	service_client.service = service;
-	service_client.branch.limit = service->js_branch_limit;
-	service_client.branch.gc_interval = service->js_gc_interval;
-	service_client.branch.yield_interval = service->js_yield_interval;
+	service_client.branch.limit = service->js.branch_limit;
+	service_client.branch.gc_interval = service->js.gc_interval;
+	service_client.branch.yield_interval = service->js.yield_interval;
 	service_client.branch.terminated = &service->terminated;
 	service_client.branch.auto_terminate = TRUE;
 
-	if((js_runtime=JS_NewRuntime(service->js_max_bytes))==NULL) {
+	if((js_runtime=JS_NewRuntime(service->js.max_bytes))==NULL) {
 		lprintf(LOG_ERR,"%04d !%s ERROR initializing JavaScript runtime"
 			,service->socket,service->protocol);
 		close_socket(service->socket);
@@ -1453,11 +1449,7 @@ static service_t* read_services_ini(service_t* service, DWORD* services)
 		SAFECOPY(serv.cmd,iniReadString(fp,sec_list[i],"Command","",cmd));
 
 		/* JavaScript operating parameters */
-		serv.js_max_bytes=iniReadInteger(fp,sec_list[i]		,strJavaScriptMaxBytes		,startup->js_max_bytes);
-		serv.js_cx_stack=iniReadInteger(fp,sec_list[i]		,strJavaScriptContextStack	,startup->js_cx_stack);
-		serv.js_branch_limit=iniReadInteger(fp,sec_list[i]	,strJavaScriptBranchLimit	,startup->js_branch_limit);
-		serv.js_gc_interval=iniReadInteger(fp,sec_list[i]	,strJavaScriptGcInterval	,startup->js_gc_interval);
-		serv.js_yield_interval=iniReadInteger(fp,sec_list[i]	,strJavaScriptYieldInterval	,startup->js_yield_interval);
+		sbbs_read_js_settings(fp, sec_list[i], &serv.js, &startup->js);
 
 		for(j=0;j<*services;j++)
 			if(service[j].interface_addr==serv.interface_addr && service[j].port==serv.port
@@ -1592,8 +1584,8 @@ void DLLCALL services_thread(void* arg)
 
 	/* Setup intelligent defaults */
 	if(startup->sem_chk_freq==0)			startup->sem_chk_freq=2;
-	if(startup->js_max_bytes==0)			startup->js_max_bytes=JAVASCRIPT_MAX_BYTES;
-	if(startup->js_cx_stack==0)				startup->js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
+	if(startup->js.max_bytes==0)			startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
+	if(startup->js.cx_stack==0)				startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
 
 	uptime=0;
 	served=0;
@@ -2023,9 +2015,9 @@ void DLLCALL services_thread(void* arg)
 				client->service->clients++;		/* this should be mutually exclusive */
 				client->udp_buf=udp_buf;
 				client->udp_len=udp_len;
-				client->branch.limit			= service[i].js_branch_limit;
-				client->branch.gc_interval		= service[i].js_gc_interval;
-				client->branch.yield_interval	= service[i].js_yield_interval;
+				client->branch.limit			= service[i].js.branch_limit;
+				client->branch.gc_interval		= service[i].js.gc_interval;
+				client->branch.yield_interval	= service[i].js.yield_interval;
 				client->branch.terminated		= &client->service->terminated;
 				client->branch.auto_terminate	= TRUE;
 
diff --git a/src/sbbs3/services.h b/src/sbbs3/services.h
index 00afb15059..0bc2796e8a 100644
--- a/src/sbbs3/services.h
+++ b/src/sbbs3/services.h
@@ -45,11 +45,6 @@ typedef struct {
 	DWORD	size;				/* sizeof(bbs_struct_t) */
     DWORD   interface_addr;
     DWORD	options;			/* See BBS_OPT definitions */
-    DWORD	js_max_bytes;
-	DWORD	js_cx_stack;
-	DWORD	js_branch_limit;
-	DWORD	js_yield_interval;
-	DWORD	js_gc_interval;
 	WORD	sem_chk_freq;			/* semaphore file checking frequency (in seconds) */
 
 	void*	cbdata;					/* Private data passed to callbacks */ 
@@ -81,6 +76,9 @@ typedef struct {
 	uint	bind_retry_count;		/* Number of times to retry bind() calls */
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 
+	/* JavaScript operating parameters */
+	js_startup_t js;
+
 } services_startup_t;
 
 #if 0
diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h
index 363db88374..55f47954e1 100644
--- a/src/sbbs3/startup.h
+++ b/src/sbbs3/startup.h
@@ -46,11 +46,12 @@
 #include "sbbsdefs.h"	/* LOG_* (syslog.h) values */
 
 typedef struct {
-	ulong	max_bytes;
-	ulong	cx_stack;
-	ulong	branch_limit;
-	ulong	gc_interval;
-	ulong	yield_interval;
+	ulong	max_bytes;		/* max allocated bytes before garbage collection */
+	ulong	cx_stack;		/* bytes for script execution stack */
+	ulong	thread_stack;	/* limit of stack size for native execution thread */
+	ulong	branch_limit;	/* maximum number of branches (for infinite loop detection) */
+	ulong	gc_interval;	/* number of branches between garbage collection attempts */
+	ulong	yield_interval;	/* number of branches between time-slice yields */
 } js_startup_t;
 
 typedef struct {
@@ -81,11 +82,6 @@ typedef struct {
     DWORD	options;			/* See BBS_OPT definitions */
     DWORD	rlogin_interface;
     DWORD	xtrn_polls_before_yield;
-    DWORD	js_max_bytes;
-	DWORD	js_cx_stack;
-	DWORD	js_branch_limit;
-	DWORD	js_yield_interval;
-	DWORD	js_gc_interval;
     RingBuf** node_spybuf;			/* Spy output buffer (each node)	*/
     RingBuf** node_inbuf;			/* User input buffer (each node)	*/
     sem_t**	node_spysem;			/* Spy output semaphore (each node)	*/
@@ -123,6 +119,9 @@ typedef struct {
 	uint	bind_retry_count;		/* Number of times to retry bind() calls */
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 
+	/* JavaScript operating parameters */
+	js_startup_t js;
+
 } bbs_startup_t;
 
 /* startup options that requires re-initialization/recycle when changed */
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 36276b2fd1..c67d4e6e96 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -2959,9 +2959,9 @@ js_initcx(http_session_t *session)
 	JSContext*	js_cx;
 
 	lprintf(LOG_INFO,"%04d JavaScript: Initializing context (stack: %lu bytes)"
-		,session->socket,startup->js_cx_stack);
+		,session->socket,startup->js.cx_stack);
 
-    if((js_cx = JS_NewContext(session->js_runtime, startup->js_cx_stack))==NULL)
+    if((js_cx = JS_NewContext(session->js_runtime, startup->js.cx_stack))==NULL)
 		return(NULL);
 
 	lprintf(LOG_INFO,"%04d JavaScript: Context created",session->socket);
@@ -2995,9 +2995,9 @@ static BOOL js_setup(http_session_t* session)
 
 	if(session->js_runtime == NULL) {
 		lprintf(LOG_INFO,"%04d JavaScript: Creating runtime: %lu bytes"
-			,session->socket,startup->js_max_bytes);
+			,session->socket,startup->js.max_bytes);
 
-		if((session->js_runtime=JS_NewRuntime(startup->js_max_bytes))==NULL) {
+		if((session->js_runtime=JS_NewRuntime(startup->js.max_bytes))==NULL) {
 			lprintf(LOG_ERR,"%04d !ERROR creating JavaScript runtime",session->socket);
 			return(FALSE);
 		}
@@ -3569,8 +3569,8 @@ void DLLCALL web_server(void* arg)
 	if(startup->max_inactivity==0) 			startup->max_inactivity=120; /* seconds */
 	if(startup->max_cgi_inactivity==0) 		startup->max_cgi_inactivity=120; /* seconds */
 	if(startup->sem_chk_freq==0)			startup->sem_chk_freq=2; /* seconds */
-	if(startup->js_max_bytes==0)			startup->js_max_bytes=JAVASCRIPT_MAX_BYTES;
-	if(startup->js_cx_stack==0)				startup->js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
+	if(startup->js.max_bytes==0)			startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
+	if(startup->js.cx_stack==0)				startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
 	if(startup->ssjs_ext[0]==0)				SAFECOPY(startup->ssjs_ext,".ssjs");
 	if(startup->js_ext[0]==0)				SAFECOPY(startup->js_ext,".bbs");
 
@@ -3876,9 +3876,9 @@ void DLLCALL web_server(void* arg)
    			session->socket=client_socket;
 			session->js_branch.auto_terminate=TRUE;
 			session->js_branch.terminated=&terminate_server;
-			session->js_branch.limit=startup->js_branch_limit;
-			session->js_branch.gc_interval=startup->js_gc_interval;
-			session->js_branch.yield_interval=startup->js_yield_interval;
+			session->js_branch.limit=startup->js.branch_limit;
+			session->js_branch.gc_interval=startup->js.gc_interval;
+			session->js_branch.yield_interval=startup->js.yield_interval;
 
 			_beginthread(http_session_thread, 0, session);
 			served++;
diff --git a/src/sbbs3/websrvr.h b/src/sbbs3/websrvr.h
index f1f2ea8a77..55064b2582 100644
--- a/src/sbbs3/websrvr.h
+++ b/src/sbbs3/websrvr.h
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -51,12 +51,7 @@ typedef struct {
 	WORD	sem_chk_freq;		/* semaphore file checking frequency (in seconds) */
     DWORD   interface_addr;
     DWORD	options;
-    DWORD	js_max_bytes;
-	DWORD	js_cx_stack;
-	DWORD	js_branch_limit;
-	DWORD	js_yield_interval;
-	DWORD	js_gc_interval;
-
+	
 	void*	cbdata;				/* Private data passed to callbacks */ 
 
 	/* Callbacks (NULL if unused) */
@@ -96,6 +91,9 @@ typedef struct {
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 	char	default_cgi_content[128];
 
+	/* JavaScript operating parameters */
+	js_startup_t js;
+
 } web_startup_t;
 
 #if defined(STARTUP_INIT_FIELD_TABLES)
-- 
GitLab