diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c index 3b81c83b4d778e0f26264654fd717783cb527e8a..1603b15ed6f1d352360b72c6728d0a2e0ac3276c 100644 --- a/src/sbbs3/jsexec.c +++ b/src/sbbs3/jsexec.c @@ -1,6 +1,6 @@ /* jsexec.c */ -/* Execute a Synchronet JavaScript from the command-line */ +/* Execute a Synchronet JavaScript module from the command-line */ /* $Id$ */ @@ -45,11 +45,22 @@ JSObject* js_glob; ulong js_loop=0; scfg_t scfg; ulong js_max_bytes=JAVASCRIPT_MAX_BYTES; +ulong js_context_stack=JAVASCRIPT_CONTEXT_STACK; +FILE* confp=stdout; +FILE* errfp=stderr; -char *usage="\nusage: jsexec [-opts] module[.js] [args]\n" - "\navailable opts:" - "\n" - ; +void usage(FILE* fp) +{ + fprintf(fp,"\nusage: jsexec [-opts] [path]module[.js] [args]\n" + "\navailable opts:\n\n" + "\t-m <bytes> set maximum heap size (default: %lu bytes)\n" + "\t-s <bytes> set context stack size (default: %lu bytes)\n" + "\t-t <filename> send console output to stdout and filename\n" + "\t-e send error message to stdout instead of stderr\n" + ,JAVASCRIPT_MAX_BYTES + ,JAVASCRIPT_CONTEXT_STACK + ); +} static JSBool js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) @@ -197,7 +208,7 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) const char* warning; if(report==NULL) { - fprintf(stderr,"!JavaScript: %s", message); + fprintf(errfp,"!JavaScript: %s", message); return; } @@ -219,7 +230,7 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) } else warning=""; - fprintf(stderr,"!JavaScript %s%s%s: %s",warning,file,line,message); + fprintf(errfp,"!JavaScript %s%s%s: %s",warning,file,line,message); } static JSBool @@ -251,18 +262,48 @@ js_BranchCallback(JSContext *cx, JSScript *script) return(JS_TRUE); } +static BOOL js_CreateEnvObject(JSContext* cx, JSObject* glob, char** env) +{ + char name[256]; + char* val; + uint i; + JSObject* js_env; + + if((js_env=JS_NewObject(js_cx, NULL, NULL, glob))==NULL) + return(FALSE); + + for(i=0;env[i]!=NULL;i++) { + SAFECOPY(name,env[i]); + truncstr(name,"="); + val=strchr(env[i],'='); + if(val==NULL) + val=""; + else + val++; + if(!JS_DefineProperty(cx, js_env, name, STRING_TO_JSVAL(JS_NewStringCopyZ(cx,val)) + ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE)) + return(FALSE); + } + + if(!JS_DefineProperty(cx, glob, "env", OBJECT_TO_JSVAL(js_env) + ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE)) + return(FALSE); + + return(TRUE); +} + static BOOL js_init(void) { - fprintf(stderr,"JavaScript: Creating runtime: %lu bytes\n" + fprintf(errfp,"JavaScript: Creating runtime: %lu bytes\n" ,js_max_bytes); if((js_runtime = JS_NewRuntime(js_max_bytes))==NULL) return(FALSE); - fprintf(stderr,"JavaScript: Initializing context (stack: %lu bytes)\n" + fprintf(errfp,"JavaScript: Initializing context (stack: %lu bytes)\n" ,JAVASCRIPT_CONTEXT_STACK); - if((js_cx = JS_NewContext(js_runtime, JAVASCRIPT_CONTEXT_STACK))==NULL) + if((js_cx = JS_NewContext(js_runtime, js_context_stack))==NULL) return(FALSE); JS_SetErrorReporter(js_cx, js_ErrorReporter); @@ -295,6 +336,10 @@ static BOOL js_init(void) if(!js_CreateUserObjects(js_cx, js_glob, &scfg, NULL, NULL, NULL)) return(FALSE); + /* Environment Object (associative array) */ + if(!js_CreateEnvObject(js_cx, js_glob, environ)) + return(FALSE); + return(TRUE); } @@ -320,14 +365,14 @@ long js_exec(const char *fname, char** args) strcat(path,".js"); if(!fexistcase(path)) { - fprintf(stderr,"!Module file (%s) doesn't exist\n",path); + fprintf(errfp,"!Module file (%s) doesn't exist\n",path); return(-1); } js_scope=JS_NewObject(js_cx, NULL, NULL, js_glob); if(js_scope==NULL) { - fprintf(stderr,"!Error creating JS scope\n"); + fprintf(errfp,"!Error creating JS scope\n"); return(-1); } @@ -347,7 +392,7 @@ long js_exec(const char *fname, char** args) ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE); if((js_script=JS_CompileFile(js_cx, js_scope, path))==NULL) { - fprintf(stderr,"!Error executing %s\n",fname); + fprintf(errfp,"!Error executing %s\n",fname); return(-1); } @@ -369,36 +414,25 @@ long js_exec(const char *fname, char** args) /*********************/ int main(int argc, char **argv) { - char error[512]; - char revision[16]; - char* module=NULL; - char* p; + char error[512]; + char revision[16]; + char* module=NULL; + char* p; + int argn; sscanf("$Revision$", "%*s %s", revision); - fprintf(stderr,"\nJSexec v%s%c-%s (rev %s) - " - "Execute Synchronet JavaScript Modules\n" + fprintf(errfp,"\nJSexec v%s%c-%s (rev %s) - " + "Execute Synchronet JavaScript Module\n" ,VERSION,REVISION ,PLATFORM_DESC ,revision ); - if(argc<2) { - fprintf(stderr,usage); - return(1); - } - - module=argv[1]; - - if(module==NULL) { - fprintf(stderr,usage); - return(1); - } - p=getenv("SBBSCTRL"); if(p==NULL) { - fprintf(stderr,"\nSBBSCTRL environment variable not set.\n"); - fprintf(stderr,"\nExample: SET SBBSCTRL=/sbbs/ctrl\n"); + fprintf(errfp,"\nSBBSCTRL environment variable not set.\n"); + fprintf(errfp,"\nExample: SET SBBSCTRL=/sbbs/ctrl\n"); exit(1); } @@ -406,12 +440,38 @@ int main(int argc, char **argv) scfg.size=sizeof(scfg); SAFECOPY(scfg.ctrl_dir,p); + for(argn=1;argn<argc;argn++) { + if(argv[argn][0]=='-') { + switch(argv[argn][1]) { + case 'm': + js_max_bytes=strtoul(argv[++argn],NULL,0); + break; + case 's': + js_context_stack=strtoul(argv[++argn],NULL,0); + break; + case 'e': + errfp=stdout; + break; + default: + usage(errfp); + return(1); + } + continue; + } + module=argv[argn]; + } + + if(module==NULL) { + usage(errfp); + return(1); + } + if(chdir(scfg.ctrl_dir)!=0) - fprintf(stderr,"!ERROR changing directory to: %s", scfg.ctrl_dir); + fprintf(errfp,"!ERROR changing directory to: %s", scfg.ctrl_dir); printf("\nLoading configuration files from %s\n",scfg.ctrl_dir); if(!load_cfg(&scfg,NULL,TRUE,error)) { - fprintf(stderr,"!ERROR loading configuration files: %s\n",error); + fprintf(errfp,"!ERROR loading configuration files: %s\n",error); exit(1); } prep_dir(scfg.data_dir, scfg.temp_dir, sizeof(scfg.temp_dir)); @@ -419,9 +479,12 @@ int main(int argc, char **argv) if(!(scfg.sys_misc&SM_LOCAL_TZ)) putenv("TZ=UTC0"); - if(!js_init()) + if(!js_init()) { + fprintf(errfp,"!JavaScript initialization failure\n"); return(1); + } + printf("\n"); - return(js_exec(module,&argv[2])); + return(js_exec(module,&argv[argn])); }