From 7acadb708ea1f794ef206e6c94ac73e67a510b50 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Sun, 20 Jan 2019 05:25:20 +0000
Subject: [PATCH] The "stdio" File objects (stdin, stdout, stderr) did not work
 on Windows, because the stdout FILE* is a different address in jsexec than it
 is in sbbs.dll (where the actual File I/O operations occurred). Refactored by
 passing the stdio file descriptor (and open mode) to js_CreateFileObject
 rather than the FILE* and using fdopen() to get a FILE* associated with the
 descriptor. stdout.write() now works, for example.

---
 src/sbbs3/js_file.c   | 7 +++++--
 src/sbbs3/js_global.c | 6 +++---
 src/sbbs3/jsexec.c    | 6 +++---
 src/sbbs3/sbbs.h      | 2 +-
 4 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c
index 13f24d2846..84edf63061 100644
--- a/src/sbbs3/js_file.c
+++ b/src/sbbs3/js_file.c
@@ -3015,10 +3015,14 @@ JSObject* DLLCALL js_CreateFileClass(JSContext* cx, JSObject* parent)
 	return(obj);
 }
 
-JSObject* DLLCALL js_CreateFileObject(JSContext* cx, JSObject* parent, char *name, FILE* fp)
+JSObject* DLLCALL js_CreateFileObject(JSContext* cx, JSObject* parent, char *name, int fd, const char* mode)
 {
 	JSObject* obj;
 	private_t*	p;
+	FILE* fp = fdopen(fd, mode);
+
+	if(fp == NULL)
+		return NULL;
 
 	obj = JS_DefineObject(cx, parent, name, &js_file_class, NULL
 		,JSPROP_ENUMERATE|JSPROP_READONLY);
@@ -3037,7 +3041,6 @@ JSObject* DLLCALL js_CreateFileObject(JSContext* cx, JSObject* parent, char *nam
 		dbprintf(TRUE, p, "JS_SetPrivate failed");
 		return(NULL);
 	}
-
 	dbprintf(FALSE, p, "object created");
 
 	return(obj);
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index d1bb065b82..1fdd748b05 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -398,11 +398,11 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 		if (JS_HasProperty(cx, obj, "console", &success) && success)
 			js_CreateConsoleObject(bg->cx, bg->obj);
 		if (JS_HasProperty(cx, obj, "stdin", &success) && success)
-			js_CreateFileObject(bg->cx, bg->obj, "stdin", stdin);
+			js_CreateFileObject(bg->cx, bg->obj, "stdin", STDIN_FILENO, "r");
 		if (JS_HasProperty(cx, obj, "stdout", &success) && success)
-			js_CreateFileObject(bg->cx, bg->obj, "stdout", stdout);
+			js_CreateFileObject(bg->cx, bg->obj, "stdout", STDOUT_FILENO, "w");
 		if (JS_HasProperty(cx, obj, "stderr", &success) && success)
-			js_CreateFileObject(bg->cx, bg->obj, "stderr", stderr);
+			js_CreateFileObject(bg->cx, bg->obj, "stderr", STDERR_FILENO, "w");
 		JS_SetContextPrivate(bg->cx, bg);
 
 		exec_cx = bg->cx;
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 66c5289ba6..d3e45b8501 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -856,17 +856,17 @@ static BOOL js_init(char** env)
 	}
 
 	/* STDIO objects */
-	if(!js_CreateFileObject(js_cx, js_glob, "stdout", stdout)) {
+	if(!js_CreateFileObject(js_cx, js_glob, "stdout", STDOUT_FILENO, "w")) {
 		JS_ENDREQUEST(js_cx);
 		return(FALSE);
 	}
 
-	if(!js_CreateFileObject(js_cx, js_glob, "stdin", stdin)) {
+	if(!js_CreateFileObject(js_cx, js_glob, "stdin", STDIN_FILENO, "r")) {
 		JS_ENDREQUEST(js_cx);
 		return(FALSE);
 	}
 
-	if(!js_CreateFileObject(js_cx, js_glob, "stderr", stderr)) {
+	if(!js_CreateFileObject(js_cx, js_glob, "stderr", STDERR_FILENO, "w")) {
 		JS_ENDREQUEST(js_cx);
 		return(FALSE);
 	}
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 19bc9a3cec..983636d4fa 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -1336,7 +1336,7 @@ extern "C" {
 
 	/* js_file.c */
 	DLLEXPORT JSObject* DLLCALL js_CreateFileClass(JSContext* cx, JSObject* parent);
-	DLLEXPORT JSObject* DLLCALL js_CreateFileObject(JSContext* cx, JSObject* parent, char *name, FILE* fp);
+	DLLEXPORT JSObject* DLLCALL js_CreateFileObject(JSContext* cx, JSObject* parent, char *name, int fd, const char* mode);
 
 	/* js_sprintf.c */
 	DLLEXPORT char*		DLLCALL js_sprintf(JSContext* cx, uint argn, unsigned argc, jsval *argv);
-- 
GitLab