diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index dab63d5e6286a77213032c54a36363f0a1902468..41b4bad0822902230f40301719b25210f0107a71 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -48,6 +48,7 @@
 #include "ini_file.h"
 #include "js_rtpool.h"
 #include "js_request.h"
+#include <jsdbgapi.h>
 
 #define DEFAULT_LOG_LEVEL	LOG_DEBUG	/* Display all LOG levels */
 #define DEFAULT_ERR_LOG_LVL	LOG_WARNING
@@ -55,6 +56,7 @@
 js_startup_t	startup;
 JSRuntime*	js_runtime;
 JSContext*	js_cx;
+JSObject*	js_script=NULL;
 JSObject*	js_glob;
 js_callback_t	cb;
 scfg_t		scfg;
@@ -81,6 +83,13 @@ BOOL		daemonize=FALSE;
 #endif
 char		orig_cwd[MAX_PATH+1];
 BOOL		debugger=FALSE;
+enum debug_action {
+	DEBUG_CONTINUE,
+	DEBUG_EXIT
+};
+
+static JSTrapStatus trap_handler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure);
+static enum debug_action debug_prompt(JSScript *script);
 
 void banner(FILE* fp)
 {
@@ -131,6 +140,7 @@ void usage(FILE* fp)
 		"\t-l             loop until intentionally terminated\n"
 		"\t-p             wait for keypress (pause) on exit\n"
 		"\t-!             wait for keypress (pause) on error\n"
+		"\t-D             debugs the script\n"
 		,JAVASCRIPT_MAX_BYTES
 		,JAVASCRIPT_CONTEXT_STACK
 		,JAVASCRIPT_TIME_LIMIT
@@ -423,7 +433,7 @@ js_writeln(JSContext *cx, uintN argc, jsval *arglist)
 }
 
 static JSBool
-js_printf(JSContext *cx, uintN argc, jsval *arglist)
+jse_printf(JSContext *cx, uintN argc, jsval *arglist)
 {
 	jsval *argv=JS_ARGV(cx, arglist);
 	char* p;
@@ -611,7 +621,7 @@ static jsSyncMethodSpec js_global_functions[] = {
     {"write",           js_write,           0},
     {"writeln",         js_writeln,         0},
     {"print",           js_writeln,         0},
-    {"printf",          js_printf,          1},	
+    {"printf",          jse_printf,          1},	
 	{"alert",			js_alert,			1},
 	{"prompt",			js_prompt,			1},
 	{"confirm",			js_confirm,			1},
@@ -763,6 +773,127 @@ static const char* js_ext(const char* fname)
 	return("");
 }
 
+/*
+ * This doesn't belong here and is done wrong...
+ * mcmlxxix should love it.
+ */
+static enum debug_action debug_prompt(JSScript *script)
+{
+	char	line[1024];
+
+	while(1) {
+		if(JS_IsExceptionPending(js_cx))
+			fputs("!", stdout);
+		fputs("JS> ", stdout);
+
+		if(fgets(line, sizeof(line), stdin)==NULL) {
+			fputs("Error readin input\n",stderr);
+			continue;
+		}
+		if(strncmp(line, "break ", 6)==0) {
+			ulong		linenum=strtoul(line+6, NULL, 10);
+			jsbytecode	*pc;
+			
+			if(linenum==ULONG_MAX) {
+				fputs("Unable to parse line number\n",stderr);
+				continue;
+			}
+			pc=JS_LineNumberToPC(js_cx, script, linenum);
+			if(pc==NULL) {
+				fprintf(stderr, "Unable to locate line %lu\n", linenum);
+				break;
+			}
+			if(!JS_SetTrap(js_cx, script, pc, trap_handler, JSVAL_VOID)) {
+				fprintf(stderr, "Unable to set breakpoint at line %lu\n",linenum);
+			}
+			continue;
+		}
+		if(strncmp(line, "r", 1)==0) {
+			return DEBUG_CONTINUE;
+		}
+		if(strncmp(line, "eval ", 5)==0 || 
+				strncmp(line, "e ", 2)==0
+				) {
+			jsval			ret;
+			JSStackFrame	*fp;
+			jsval			oldexcept;
+			BOOL			has_old=FALSE;
+			int				cmdlen=5;
+
+			if(line[1]==' ')
+				cmdlen=2;
+			if(JS_IsExceptionPending(js_cx)) {
+				if(JS_GetPendingException(js_cx, &oldexcept))
+					has_old=TRUE;
+				JS_ClearPendingException(js_cx);
+			}
+
+			fp=JS_GetScriptedCaller(js_cx, NULL);
+			if(!fp) {
+				if(has_old)
+					JS_SetPendingException(js_cx, oldexcept);
+				fputs("Unable to get frame pointer\n", stderr);
+				continue;
+			}
+			if(!JS_EvaluateInStackFrame(js_cx, fp, line+cmdlen, strlen(line)-cmdlen, "eval-d statement", 1, &ret)) {
+				if(JS_IsExceptionPending(js_cx)) {
+					JS_SetErrorReporter(js_cx, js_ErrorReporter);
+					JS_ReportPendingException(js_cx);
+					JS_ClearPendingException(js_cx);
+				}
+			}
+			else {
+				// TODO: Check ret...
+			}
+			if(has_old)
+				JS_SetPendingException(js_cx, oldexcept);
+			continue;
+		}
+		if(strncmp(line, "clear", 5)==0) {
+			JS_ClearPendingException(js_cx);
+			continue;
+		}
+		fputs("Unrecognized command:\n"
+			  "break ####       - Sets a breakpoint\n"
+			  "r                - Runs the script\n"
+			  "eval <statement> - eval() <statement> in the current frame\n"
+			  "e <statement>    - eval() <statement> in the current frame\n"
+			  "clear            - Clears pending exceptions (doesn't seem to help)\n"
+			  "\n",stderr);
+	}
+	return DEBUG_CONTINUE;
+}
+
+static JSTrapStatus trap_handler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure)
+{
+    JS_GC(cx);
+
+	fputs("Breakpoint reached\n",stdout);
+
+    switch(debug_prompt(script)) {
+		case DEBUG_CONTINUE:
+			return JSTRAP_CONTINUE;
+		case DEBUG_EXIT:
+			return JSTRAP_ERROR;
+	}
+	return JSTRAP_CONTINUE;
+}
+
+static JSTrapStatus throw_handler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure)
+{
+    JS_GC(cx);
+
+	fputs("Exception thrown\n",stdout);
+
+    switch(debug_prompt(script)) {
+		case DEBUG_CONTINUE:
+			return JSTRAP_CONTINUE;
+		case DEBUG_EXIT:
+			return JSTRAP_ERROR;
+	}
+	return JSTRAP_CONTINUE;
+}
+
 long js_exec(const char *fname, char** args)
 {
 	int			argc=0;
@@ -773,7 +904,6 @@ long js_exec(const char *fname, char** args)
 	size_t		len;
 	char*		js_buf=NULL;
 	size_t		js_buflen;
-	JSObject*	js_script=NULL;
 	JSString*	arg;
 	JSObject*	argv;
 	FILE*		fp=stdin;
@@ -884,7 +1014,11 @@ long js_exec(const char *fname, char** args)
 
 	js_PrepareToExecute(js_cx, js_glob, fname==NULL ? NULL : path, orig_cwd);
 	start=xp_timer();
-	JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
+	if((!debugger) || debug_prompt(JS_GetScriptFromObject(js_script))==DEBUG_CONTINUE) {
+		if(debugger)
+			JS_SetThrowHook(js_runtime, throw_handler, NULL);
+		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
+	}
 	JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
 	if(rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval)) {
 		char	*p;
@@ -951,10 +1085,6 @@ int parseLogLevel(const char* p)
 	return DEFAULT_LOG_LEVEL;
 }
 
-void debug_promopt()
-{
-}
-
 /*********************/
 /* Entry point (duh) */
 /*********************/
@@ -1189,6 +1319,8 @@ int main(int argc, char **argv, char** environ)
 		}
 		fprintf(statfp,"\n");
 
+		if(debugger)
+			JS_SetDebugMode(js_cx, JS_TRUE);
 		result=js_exec(module,&argv[argn]);
 		JS_RemoveObjectRoot(js_cx, &js_glob);
 		JS_ENDREQUEST(js_cx);