diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index 4d0599845614710fb31fe029f2d589e3216bbffe..9d3b8bd8472225633a0c92a705bd11b86767edba 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -560,7 +560,7 @@ static const char* js_ext(const char* fname)
 	return("");
 }
 
-long sbbs_t::js_execfile(const char *cmd)
+long sbbs_t::js_execfile(const char *cmd, const char* startup_dir)
 {
 	ulong		stack_frame;
 	char*		p;
@@ -573,7 +573,6 @@ long sbbs_t::js_execfile(const char *cmd)
 	JSScript*	js_script=NULL;
 	jsval		rval;
 	int32		result=0;
-	BOOL		auto_terminate = js_branch.auto_terminate;
 	JSRuntime	*old_runtime=js_runtime;
 	JSContext	*old_context=js_cx;
 	JSObject	*old_glob=js_glob;
@@ -600,9 +599,13 @@ long sbbs_t::js_execfile(const char *cmd)
 	fname=cmdline;
 
 	if(strcspn(fname,"/\\")==strlen(fname)) {
-		SAFEPRINTF3(path,"%s%s%s",cfg.mods_dir,fname,js_ext(fname));
-		if(cfg.mods_dir[0]==0 || !fexistcase(path))
-			SAFEPRINTF3(path,"%s%s%s",cfg.exec_dir,fname,js_ext(fname));
+		if(startup_dir!=NULL && *startup_dir)
+			SAFEPRINTF3(path,"%s%s%s",startup_dir,fname,js_ext(fname));
+		if(!fexistcase(path)) {
+			SAFEPRINTF3(path,"%s%s%s",cfg.mods_dir,fname,js_ext(fname));
+			if(cfg.mods_dir[0]==0 || !fexistcase(path))
+				SAFEPRINTF3(path,"%s%s%s",cfg.exec_dir,fname,js_ext(fname));
+		}
 	} else
 		SAFECOPY(path,fname);
 
@@ -661,7 +664,7 @@ long sbbs_t::js_execfile(const char *cmd)
 
 	JS_SetBranchCallback(js_cx, js_BranchCallback);
 
-	js_PrepareToExecute(js_cx, js_glob, path);
+	js_PrepareToExecute(js_cx, js_glob, path, startup_dir);
 	JS_ExecuteScript(js_cx, js_scope, js_script, &rval);
 
 	JS_GetProperty(js_cx, js_scope, "exit_code", &rval);
@@ -680,9 +683,6 @@ long sbbs_t::js_execfile(const char *cmd)
 
 	JS_ENDREQUEST(js_cx);
 
-	// Restore saved auto_terminate state
-	js_branch.auto_terminate = auto_terminate;
-
 reset_js:
 	js_cleanup(client_name);
 	js_runtime=old_runtime;
@@ -696,7 +696,7 @@ reset_js:
 #endif
 
 /* Important change as of Nov-16-2006, 'cmdline' may contain args */
-long sbbs_t::exec_bin(const char *cmdline, csi_t *csi)
+long sbbs_t::exec_bin(const char *cmdline, csi_t *csi, const char* startup_dir)
 {
     char    str[MAX_PATH+1];
 	char	mod[MAX_PATH+1];
@@ -718,11 +718,16 @@ long sbbs_t::exec_bin(const char *cmdline, csi_t *csi)
 
 #ifdef JAVASCRIPT
 	if((p=getfext(mod))!=NULL && stricmp(p,".js")==0)
-		return(js_execfile(cmdline));
+		return(js_execfile(cmdline, startup_dir));
+	if(p==NULL && startup_dir!=NULL && *startup_dir) {
+		SAFEPRINTF2(str,"%s%s.js", startup_dir, mod);
+		if(fexistcase(str))
+			return(js_execfile(cmdline, startup_dir));
+	}
 	if(cfg.mods_dir[0]) {
 		SAFEPRINTF2(str,"%s%s.js",cfg.mods_dir,mod);
 		if(fexistcase(str)) 
-			return(js_execfile(cmdline));
+			return(js_execfile(cmdline, startup_dir));
 	}
 #endif
 
@@ -736,7 +741,7 @@ long sbbs_t::exec_bin(const char *cmdline, csi_t *csi)
 #ifdef JAVASCRIPT
 		SAFEPRINTF2(str,"%s%s.js",cfg.exec_dir,mod);
 		if(fexistcase(str)) 
-			return(js_execfile(cmdline));
+			return(js_execfile(cmdline, startup_dir));
 #endif
 
 		SAFEPRINTF2(str,"%s%s",cfg.exec_dir,modname);
@@ -1276,7 +1281,7 @@ int sbbs_t::exec(csi_t *csi)
 					exec_xtrn(i);
 				break;
 			case CS_EXEC_BIN:
-				exec_bin(cmdstr((char*)csi->ip,path,csi->str,(char*)buf),csi);
+				exec_bin(cmdstr((char*)csi->ip,path,csi->str,(char*)buf),csi,/* startup_dir: */NULL);
 				break;
 			case CS_YES_NO:
 				csi->logic=!yesno(cmdstr((char*)csi->ip,path,csi->str,(char*)buf));
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 74798b3893fdd0ac097eb539f4ffcb3447e19ab2..35b106944608890d61f48041b149ac0441f5f138 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -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 2009 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2010 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				*
@@ -1011,7 +1011,7 @@ BOOL js_generate_index(JSContext* js_cx, JSObject* parent,
 			break;
 		}
 
-		js_PrepareToExecute(js_cx, parent, spath);
+		js_PrepareToExecute(js_cx, parent, spath, /* startup_dir: */NULL);
 		if((success=JS_ExecuteScript(js_cx, parent, js_script, &rval))!=TRUE) {
 			lprintf(LOG_ERR,"%04d !JavaScript FAILED to execute script (%s)",sock,spath);
 			break;
diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c
index 736122e140df2d938ef1d8b384198e0856a9d873..b6d1e56629ce98daada7dc9444b7d38bdfbbb523 100644
--- a/src/sbbs3/js_internal.c
+++ b/src/sbbs3/js_internal.c
@@ -486,7 +486,7 @@ JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_
 	return(obj);
 }
 
-void DLLCALL js_PrepareToExecute(JSContext *cx, JSObject *obj, const char *filename)
+void DLLCALL js_PrepareToExecute(JSContext *cx, JSObject *obj, const char *filename, const char* startup_dir)
 {
 	JSString*	str;
 	jsval		val;
@@ -511,5 +511,10 @@ void DLLCALL js_PrepareToExecute(JSContext *cx, JSObject *obj, const char *filen
 				JS_DefineProperty(cx, js, "exec_dir", STRING_TO_JSVAL(str)
 					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
 		}
+		if(startup_dir==NULL)
+			startup_dir="";
+		if((str=JS_NewStringCopyZ(cx, startup_dir)) != NULL)
+			JS_DefineProperty(cx, js, "startup_dir", STRING_TO_JSVAL(str)
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
 	}
 }
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 732b12e9da70ceb9ce8e4cfa3b2f91c2453a1fdf..cadf0fa8ed09686714e50120bbd2ad087533afdf 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -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 2009 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2010 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				*
@@ -39,8 +39,6 @@
 #define JAVASCRIPT
 #endif
 
-#include <unistd.h>						// getcwd()
-
 #ifdef __unix__
 #include <signal.h>
 #endif
@@ -82,95 +80,6 @@ BOOL		daemonize=FALSE;
 #endif
 char		orig_cwd[MAX_PATH+1];
 
-enum {
-	 JSEXEC_ORIG_CWD		/* cwd at program start */
-};
-
-#ifdef BUILD_JSDOCS
-	static char* jsexec_prop_desc[] = {
-	 "Current working directory at program start"
-	,NULL
-	};
-#endif
-
-static JSBool jsexec_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-	return(JS_FALSE);
-}
-
-static JSBool jsexec_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-	jsint		tiny;
-	JSString*	js_str;
-
-    tiny = JSVAL_TO_INT(id);
-
-	switch(tiny) {
-		case JSEXEC_ORIG_CWD:
-			if((js_str=JS_NewStringCopyZ(cx, orig_cwd))==NULL)
-				return(JS_FALSE);
-			*vp = STRING_TO_JSVAL(js_str);
-			break;
-	}
-
-	return(JS_TRUE);
-}
-
-#define JSEXEC_PROP_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY
-
-static jsSyncPropertySpec jsexec_properties[] = {
-/*		 name				,tinyid					,flags,					ver	*/
-
-	{	"orig_cwd"			,JSEXEC_ORIG_CWD 		,JSEXEC_ORIG_CWD,		315},
-	{0}
-};
-
-static JSBool jsexec_resolve(JSContext *cx, JSObject *obj, jsval id)
-{
-	char*			name=NULL;
-
-	if(id != JSVAL_NULL)
-		name=JS_GetStringBytes(JSVAL_TO_STRING(id));
-
-	return(js_SyncResolve(cx, obj, name, jsexec_properties, NULL, NULL, 0));
-}
-
-static JSBool jsexec_enumerate(JSContext *cx, JSObject *obj)
-{
-	return(jsexec_resolve(cx, obj, JSVAL_NULL));
-}
-
-static JSClass jsexec_class = {
-     "JSExec"				/* name			*/
-    ,JSCLASS_HAS_PRIVATE	/* flags		*/
-	,JS_PropertyStub		/* addProperty	*/
-	,JS_PropertyStub		/* delProperty	*/
-	,jsexec_get				/* getProperty	*/
-	,jsexec_set				/* setProperty	*/
-	,jsexec_enumerate		/* enumerate	*/
-	,jsexec_resolve			/* resolve		*/
-	,JS_ConvertStub			/* convert		*/
-	,JS_FinalizeStub		/* finalize		*/
-};
-
-JSObject* DLLCALL js_CreateExecObject(JSContext* cx, JSObject* parent, char* name)
-{
-	JSObject*	obj;
-
-	obj = JS_DefineObject(cx, parent, name, &jsexec_class, NULL
-		,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-	if(obj==NULL)
-		return(NULL);
-
-#ifdef BUILD_JSDOCS
-	js_DescribeSyncObject(cx,obj,"Represents a JSExec instance",315);
-	js_CreateArrayOfStrings(cx, obj, "_property_desc_list", jsexec_prop_desc, JSPROP_READONLY);
-#endif
-
-	return(obj);
-}
-
 void banner(FILE* fp)
 {
 	fprintf(fp,"\nJSexec v%s%c-%s (rev %s)%s - "
@@ -899,7 +808,7 @@ long js_exec(const char *fname, char** args)
 			,path
 			,diff);
 
-	js_PrepareToExecute(js_cx, js_glob, fname==NULL ? NULL : path);
+	js_PrepareToExecute(js_cx, js_glob, fname==NULL ? NULL : path, orig_cwd);
 	start=xp_timer();
 	JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
 	JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 282461045f8c645e7ea20cae3cd3026d601d38b6..d2f731c41bc1f4efb33837b477b45901fbc95c68 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -1816,7 +1816,7 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 		} else {
 			lprintf(LOG_DEBUG,"%04d %s Executing: %s"
 				,sock, log_prefix, cmdline);
-			if((js_script=JS_CompileFile(*js_cx, js_scope, path)) != NULL)
+			if((js_script=JS_CompileFile(*js_cx, js_scope, path, /* startup_dir: */NULL)) != NULL)
 				js_PrepareToExecute(*js_cx, js_scope, path);
 		}
 		if(js_script==NULL)
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 5b2b45162c3a0b89b2a3e1a82f9f278ab65539e9..743602ea5fc4c27410d7110680a24d621718254f 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -230,7 +230,7 @@ public:
 	JSContext*	js_cx;
 	JSObject*	js_glob;
 	js_branch_t	js_branch;
-	long		js_execfile(const char *fname);
+	long		js_execfile(const char *fname, const char* startup_dir);
 	bool		js_init(ulong* stack_frame);
 	void		js_cleanup(const char* node);
 	void		js_create_user_objects(void);
@@ -395,7 +395,7 @@ public:
 	int		exec_net(csi_t *csi);
 	int		exec_msg(csi_t *csi);
 	int		exec_file(csi_t *csi);
-	long	exec_bin(const char *mod, csi_t *csi);
+	long	exec_bin(const char *mod, csi_t *csi, const char* startup_dir);
 	void	clearvars(csi_t *bin);
 	void	freevars(csi_t *bin);
 	char**	getstrvar(csi_t *bin, int32_t name);
@@ -1024,7 +1024,7 @@ extern "C" {
 	DLLEXPORT JSObject* DLLCALL js_CreateInternalJsObject(JSContext*, JSObject* parent, js_branch_t*, js_startup_t*);
 	DLLEXPORT JSBool	DLLCALL js_CommonBranchCallback(JSContext*, js_branch_t*);
 	DLLEXPORT void		DLLCALL js_EvalOnExit(JSContext*, JSObject*, js_branch_t*);
-	DLLEXPORT void		DLLCALL	js_PrepareToExecute(JSContext*, JSObject*, const char *filename);
+	DLLEXPORT void		DLLCALL	js_PrepareToExecute(JSContext*, JSObject*, const char *filename, const char* startup_dir);
 
 	/* js_system.c */
 	DLLEXPORT JSObject* DLLCALL js_CreateSystemObject(JSContext* cx, JSObject* parent
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index cd32289255631216e43f4368a092f36f90a04876..bade89078cec23c3725dbd7c8664029ded8f5b83 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -1187,7 +1187,7 @@ static void js_service_thread(void* arg)
 	if(js_script==NULL) 
 		lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile script (%s)",socket,spath);
 	else  {
-		js_PrepareToExecute(js_cx, js_glob, spath);
+		js_PrepareToExecute(js_cx, js_glob, spath, /* startup_dir */NULL);
 		JS_SetBranchCallback(js_cx, js_BranchCallback);
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
 		js_EvalOnExit(js_cx, js_glob, &service_client.branch);
@@ -1294,7 +1294,7 @@ static void js_static_service_thread(void* arg)
 			break;
 		}
 
-		js_PrepareToExecute(js_cx, js_glob, spath);
+		js_PrepareToExecute(js_cx, js_glob, spath, /* startup_dir */NULL);
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
 		js_EvalOnExit(js_cx, js_glob, &service_client.branch);
 		JS_DestroyScript(js_cx, js_script);
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 9dd0f90df7fee1a454dc0812641bd14fae58b41f..92ad44a7e0a1c22012b2c57514099e3a2fe83130 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -4619,7 +4619,7 @@ static BOOL exec_ssjs(http_session_t* session, char* script)  {
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Executing script: %s",session->socket,script);
 		start=xp_timer();
-		js_PrepareToExecute(session->js_cx, session->js_glob, script);
+		js_PrepareToExecute(session->js_cx, session->js_glob, script, /* startup_dir */NULL);
 		JS_ExecuteScript(session->js_cx, session->js_glob, js_script, &rval);
 		js_EvalOnExit(session->js_cx, session->js_glob, &session->js_branch);
 		lprintf(LOG_DEBUG,"%04d JavaScript: Done executing script: %s (%.2Lf seconds)"
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index 4105502aa387481251b60cd95d897107c88eeb54..30684016043c75926a3fe27baae441778a68748b 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -279,13 +279,13 @@ static bool native_executable(scfg_t* cfg, const char* cmdline, long mode)
     return(i<cfg->total_natvpgms);
 }
 
-#define XTRN_LOADABLE_MODULE								\
+#define XTRN_LOADABLE_MODULE(cmdline,startup_dir)			\
 	if(cmdline[0]=='*')		/* Baja module or JavaScript */	\
-		return(exec_bin(cmdline+1,&main_csi))				
+		return(exec_bin(cmdline+1,&main_csi,startup_dir))				
 #ifdef JAVASCRIPT
-	#define XTRN_LOADABLE_JS_MODULE							\
+	#define XTRN_LOADABLE_JS_MODULE(cmdline,startup_dir)	\
 	if(cmdline[0]=='?') 	/* JavaScript */				\
-		return(js_execfile(cmdline+1))						
+		return(js_execfile(cmdline+1,startup_dir))						
 #else
 	#define XTRN_LOADABLE_JS_MODULE
 #endif
@@ -409,8 +409,8 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 		return -1;
 	}
 
-	XTRN_LOADABLE_MODULE;
-	XTRN_LOADABLE_JS_MODULE;
+	XTRN_LOADABLE_MODULE(cmdline,startup_dir);
+	XTRN_LOADABLE_JS_MODULE(cmdline,startup_dir);
 
 	attr(cfg.color[clr_external]);		/* setup default attributes */
 
@@ -1324,8 +1324,8 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 	if(startup_dir==NULL)
 		startup_dir=nulstr;
 
-	XTRN_LOADABLE_MODULE;
-	XTRN_LOADABLE_JS_MODULE;
+	XTRN_LOADABLE_MODULE(cmdline,startup_dir);
+	XTRN_LOADABLE_JS_MODULE(cmdline,startup_dir);
 
 	attr(cfg.color[clr_external]);  /* setup default attributes */