From 1decdc695b3cab1b5ee98c867534bea3daef51d0 Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Sun, 30 Aug 2020 13:28:08 -0700
Subject: [PATCH] External program "use shell" option can be used to use a new
 JS context

Rather than introduce yet-another-external-program/config flag to enable
the "new JS run-time/context" per invocation of any particular JS command,
I'm using the XTRN/EX_SH ("Use Shell") option as it had no function for
JavaScript command-lines and the concept is similar.

So if you want to invoke a JS external program/timed-event in its own
"sandbox", enable the "Use Shell / New Context" option for that
program/command in SCFG. There may be performance penalties when running
JS mods in this way, but you get the benefit of isolating one JS module
from all others, if/when necessary.
---
 src/sbbs3/exec.cpp        |  9 ++-----
 src/sbbs3/sbbs.h          |  2 +-
 src/sbbs3/scfg/scfgxtrn.c | 51 +++++++++++++++++++++------------------
 src/sbbs3/xtrn.cpp        |  6 +++--
 src/sbbs3/xtrn_sec.cpp    |  2 +-
 5 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index 58f3d751de..770aabcc37 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -732,13 +732,9 @@ long sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* sco
 	return(result);
 }
 
-// Execute a JS Module in its own runtime and context
-// Experimental and currently broken
-long sbbs_t::js_execmodule(const char *cmd, long mode, const char* startup_dir)
+// Execute a JS Module in its own temporary JS runtime and context
+long sbbs_t::js_execxtrn(const char *cmd, const char* startup_dir)
 {
-	if(!(mode&EX_JS_CX))
-		return js_execfile(cmd, startup_dir);
-
 	JSRuntime* js_runtime;
 	JSObject* js_glob;
 	JSContext* js_cx = js_init(&js_runtime, &js_glob, "XtrnModule");
@@ -748,7 +744,6 @@ long sbbs_t::js_execmodule(const char *cmd, long mode, const char* startup_dir)
 	JS_RemoveObjectRoot(js_cx, &js_glob);
 	JS_ENDREQUEST(js_cx);
 	JS_DestroyContext(js_cx);
-	lprintf(LOG_DEBUG,"JavaScript: Destroying runtime");
 	jsrt_Release(js_runtime);
 	return result;
 }
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 6dac20350f..d5cc3fcea3 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -407,7 +407,7 @@ public:
 	JSObject*		js_hotkey_glob;
 	js_callback_t	js_callback;
 	long			js_execfile(const char *fname, const char* startup_dir, JSObject* scope = NULL, JSContext* cx = NULL, JSObject* glob = NULL);
-	long			js_execmodule(const char *fname, long mode, const char* startup_dir);
+	long			js_execxtrn(const char *fname, const char* startup_dir);
 	JSContext*		js_init(JSRuntime**, JSObject**, const char* desc);
 	void			js_cleanup(void);
 	bool			js_create_user_objects(JSContext*, JSObject* glob);
diff --git a/src/sbbs3/scfg/scfgxtrn.c b/src/sbbs3/scfg/scfgxtrn.c
index 3aaaaa9d0e..93e038c27b 100644
--- a/src/sbbs3/scfg/scfgxtrn.c
+++ b/src/sbbs3/scfg/scfgxtrn.c
@@ -40,6 +40,21 @@
 char *daystr(char days);
 static void hotkey_cfg(void);
 
+static char* use_shell_opt = "Use Shell / New Context";
+static char* use_shell_help =
+	"`Use System Shell or New JavaScript Context to Execute:`\n"
+	"\n"
+	"If this command-line requires the system command shell to execute\n"
+	"(e.g. uses pipes/redirection or invokes a Unix shell script or\n"
+	"DOS/Windows batch/command file), then set this option to ~Yes~.\n"
+	"\n"
+	"If this command-line is invoking a Synchronet JavaScript module\n"
+	"(e.g. it begins with a '`?`' character), then setting this option to ~Yes~\n"
+	"will enable the creation and initialization of a new JavaScript run-time\n"
+	"context for it to execute within, for every invocation."
+	;
+static char* use_shell_prompt = "Use System Shell or New JavaScript Context to Execute";
+
 #define CUT_XTRNSEC_NUM	USHRT_MAX
 
 static bool new_timed_event(unsigned new_event_num)
@@ -509,7 +524,7 @@ void tevents_cfg()
 				,cfg.event[i]->misc&EVENT_FORCE ? "Yes":"No");
 			sprintf(opt[k++],"%-32.32s%s","Native Executable"
 				,cfg.event[i]->misc&EX_NATIVE ? "Yes" : "No");
-			sprintf(opt[k++],"%-32.32s%s","Use Shell to Execute"
+			sprintf(opt[k++],"%-32.32s%s",use_shell_opt
 				,cfg.event[i]->misc&XTRN_SH ? "Yes" : "No");
 			sprintf(opt[k++],"%-32.32s%s","Background Execution"
 				,cfg.event[i]->misc&EX_BG ? "Yes" : "No");
@@ -798,14 +813,9 @@ void tevents_cfg()
 
 				case 12:
 					k=(cfg.event[i]->misc&XTRN_SH) ? 0:1;
-					uifc.helpbuf=
-						"`Use Shell to Execute Command:`\n"
-						"\n"
-						"If this command-line requires the system command shell to execute (Unix\n"
-						"shell script or DOS/Windows batch/command file), set this option to ~Yes~.\n"
-					;
+					uifc.helpbuf = use_shell_help;
 					k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
-						,"Use System Command Shell",uifcYesNoOpts);
+						,use_shell_prompt, uifcYesNoOpts);
 					if(!k && !(cfg.event[i]->misc&XTRN_SH)) {
 						cfg.event[i]->misc|=XTRN_SH;
 						uifc.changes=TRUE;
@@ -1006,7 +1016,7 @@ void xtrn_cfg(uint section)
 					==(XTRN_STDIO|XTRN_NOECHO) ? ", No Echo" : nulstr);
 			sprintf(opt[k++],"%-27.27s%s","Native Executable"
 				,cfg.xtrn[i]->misc&XTRN_NATIVE ? "Yes" : "No");
-			sprintf(opt[k++],"%-27.27s%s","Use Shell to Execute"
+			sprintf(opt[k++],"%-27.27s%s",use_shell_opt
 				,cfg.xtrn[i]->misc&XTRN_SH ? "Yes" : "No");
 			sprintf(opt[k++],"%-27.27s%s","Modify User Data"
 				,cfg.xtrn[i]->misc&MODUSERDAT ? "Yes" : "No");
@@ -1055,6 +1065,9 @@ void xtrn_cfg(uint section)
 				"`Online Program Configuration:`\n"
 				"\n"
 				"This menu is for configuring the selected online program.\n"
+				"\n"
+				"For detailed instructions for configuring BBS doors, see\n"
+				"`http://wiki.synchro.net/howto:door:index`"
 			;
 			switch(uifc.list(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&opt_dflt,&sub_bar,cfg.xtrn[i]->name
 				,opt)) {
@@ -1266,14 +1279,9 @@ void xtrn_cfg(uint section)
 					break;
 				case 11:
 					k=(cfg.xtrn[i]->misc&XTRN_SH) ? 0:1;
-					uifc.helpbuf=
-						"`Use Shell to Execute Command:`\n"
-						"\n"
-						"If this command-line requires the system command shell to execute, (Unix\n"
-						"shell script or DOS batch file), set this option to ~Yes~.\n"
-					;
+					uifc.helpbuf = use_shell_help;
 					k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
-						,"Use Shell",uifcYesNoOpts);
+						,use_shell_prompt,uifcYesNoOpts);
 					if(!k && !(cfg.xtrn[i]->misc&XTRN_SH)) {
 						cfg.xtrn[i]->misc|=XTRN_SH;
 						uifc.changes=TRUE; 
@@ -1667,7 +1675,7 @@ void xedit_cfg()
 					==(XTRN_STDIO|WWIVCOLOR) ? ", WWIV Color" : nulstr);
 			sprintf(opt[k++],"%-32.32s%s","Native Executable"
 				,cfg.xedit[i]->misc&XTRN_NATIVE ? "Yes" : "No");
-			sprintf(opt[k++],"%-32.32s%s","Use Shell to Execute"
+			sprintf(opt[k++],"%-32.32s%s",use_shell_opt
 				,cfg.xedit[i]->misc&XTRN_SH ? "Yes" : "No");
 			sprintf(opt[k++],"%-32.32s%s","Record Terminal Width"
 				,cfg.xedit[i]->misc&SAVECOLUMNS ? "Yes" : "No");
@@ -1852,14 +1860,9 @@ void xedit_cfg()
 					break;
 				case 6:
 					k=(cfg.xedit[i]->misc&XTRN_SH) ? 0:1;
-					uifc.helpbuf=
-						"`Use Shell to Execute Command:`\n"
-						"\n"
-						"If this command-line requires the system command shell to execute, (Unix \n"
-						"shell script or DOS batch file), set this option to ~Yes~.\n"
-					;
+					uifc.helpbuf = use_shell_help;
 					k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
-						,"Use Shell",uifcYesNoOpts);
+						,use_shell_prompt, uifcYesNoOpts);
 					if(!k && !(cfg.xedit[i]->misc&XTRN_SH)) {
 						cfg.xedit[i]->misc|=XTRN_SH;
 						uifc.changes=TRUE; 
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index ea154a9d2f..ea5cbc37a4 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -264,8 +264,10 @@ static bool native_executable(scfg_t* cfg, const char* cmdline, long mode)
 		return(exec_bin(cmdline+1,&main_csi,startup_dir))
 #ifdef JAVASCRIPT
 	#define XTRN_LOADABLE_JS_MODULE(cmdline,mode,startup_dir)	\
-	if(cmdline[0]=='?') 	/* JavaScript */				\
-		return(js_execmodule(cmdline+1,mode,startup_dir))
+	if(cmdline[0]=='?' && (mode&EX_SH))						\
+		return(js_execxtrn(cmdline+1, startup_dir))			\
+	if(cmdline[0]=='?')										\
+		return(js_execfile(cmdline+1,startup_dir))
 #else
 	#define XTRN_LOADABLE_JS_MODULE
 #endif
diff --git a/src/sbbs3/xtrn_sec.cpp b/src/sbbs3/xtrn_sec.cpp
index 2d9cd9fd0c..473f801190 100644
--- a/src/sbbs3/xtrn_sec.cpp
+++ b/src/sbbs3/xtrn_sec.cpp
@@ -1598,7 +1598,7 @@ bool sbbs_t::exec_xtrn(uint xtrnnum)
 		mode|=EX_STDIO;
 	else if(cfg.xtrn[xtrnnum]->misc&XTRN_CONIO)
 		mode|=EX_CONIO;
-	mode|=(cfg.xtrn[xtrnnum]->misc&(XTRN_CHKTIME|XTRN_NATIVE|XTRN_NOECHO|WWIVCOLOR|XTRN_JS_CX));
+	mode|=(cfg.xtrn[xtrnnum]->misc&(XTRN_CHKTIME|XTRN_NATIVE|XTRN_NOECHO|WWIVCOLOR));
 	if(cfg.xtrn[xtrnnum]->misc&MODUSERDAT) {		/* Delete MODUSER.DAT */
 		SAFEPRINTF(str,"%sMODUSER.DAT",dropdir);	/* if for some weird  */
 		removecase(str);							/* reason it's there  */
-- 
GitLab