static rpmjs rpmjsI(void) /*@globals _rpmjsI @*/ /*@modifies _rpmjsI @*/ { if (_rpmjsI == NULL) { #if defined(WITH_GPSEE) gpsee_verbosity(0); /* XXX hack around syslog(3) in GPSEE */ #endif _rpmjsI = rpmjsNew(NULL, 0); } RPMJSDBG(0, (stderr, "<== %s() _rpmjsI %p\n", __FUNCTION__, _rpmjsI)); return _rpmjsI; }
void gpsee_setVerbosity(signed int newValue) { gpsee_verbosity(-1 * gpsee_verbosity(0)); gpsee_verbosity(newValue); }
/** Error Reporter for Spidermonkey. Used to report warnings and * uncaught exceptions. */ void gpsee_errorReporter(JSContext *cx, const char *message, JSErrorReport *report) { const char *ctmp; char er_filename[64]; char er_exception[16]; char er_warning[16]; char er_number[16]; char er_lineno[16]; char er_charno[16]; char er_pfx[64]; gpsee_runtime_t *grt = JS_GetRuntimePrivate(JS_GetRuntime(cx)); int printOnTTY = 0; if (grt->errorReport == er_none) return; if (!report) { gpsee_log(cx, GLOG_NOTICE, "JS error from unknown source: %s\n", message); return; } /* Conditionally ignore reported warnings. */ if (JSREPORT_IS_WARNING(report->flags)) { if (grt->errorReport & er_noWarnings) return; if (cfg_bool_value(cfg, "gpsee_report_warnings") == cfg_false) return; if (gpsee_verbosity(0) >= GPSEE_WARNING_OUTPUT_VERBOSITY) printOnTTY = 1 && gpsee_isatty(STDERR_FILENO); } else if (gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) printOnTTY = 1 && gpsee_isatty(STDERR_FILENO); if (report->filename) { const char *bn = strrchr(report->filename, '/'); if (bn) bn += 1; else bn = report->filename; snprintf(er_filename, sizeof(er_filename), "in %s ", bn); } else er_filename[0] = (char)0; if (report->lineno) snprintf(er_lineno, sizeof(er_lineno), "line %u ", report->lineno); else er_lineno[0] = (char)0; if (report->tokenptr && report->linebuf) snprintf(er_charno, sizeof(er_charno), "ch %ld ", (long int)(report->tokenptr - report->linebuf)); else er_charno[0] = (char)0; er_warning[0] = (char)0; if (JSREPORT_IS_EXCEPTION(report->flags)) { snprintf(er_exception, sizeof(er_exception), "exception "); if (!grt->exitType) grt->exitType = et_exception; } else { er_exception[0] = (char)0; if (JSREPORT_IS_WARNING(report->flags)) snprintf(er_warning, sizeof(er_warning), "%swarning ", (JSREPORT_IS_STRICT(report->flags) ? "strict " : "")); } if (report->errorNumber) snprintf(er_number, sizeof(er_number), "#%i ", report->errorNumber); else er_number[0] = (char)0; snprintf(er_pfx, sizeof(er_pfx), "JS %s%s%s%s" "%s" "%s%s%s" "-", er_warning, er_exception, ((er_exception[0] || er_warning[0]) ? "" : "error "), er_number, /* error 69 */ er_filename, /* in myprog.js */ ((er_lineno[0] || er_charno[0]) ? "at " :""), er_lineno, er_charno /* at line 12, ch 34 */ ); /* embedded newlines -- log each separately */ while ((ctmp = strchr(message, '\n')) != 0) { char log_message[strlen(message)]; ctmp++; strncpy(log_message, message, ctmp-message); log_message[ctmp - message] = (char)0; output_message(cx, grt, er_pfx, log_message, report, printOnTTY); message = ctmp; memset(er_pfx, ' ', strlen(er_pfx)); er_pfx[0] = '|'; } output_message(cx, grt, er_pfx, message, report, printOnTTY); }
rpmRC rpmjsRunFile(rpmjs js, const char * fn, char *const * Iargv, const char ** resultp) { rpmRC rc = RPMRC_FAIL; if (js == NULL) js = rpmjsI(); if (fn != NULL) { #if defined(WITH_GPSEE) gpsee_interpreter_t * I = js->I; FILE * fp = rpmjsOpenFile(js, fn, resultp); if (fp == NULL) { I->grt->exitType = et_execFailure; /* XXX FIXME: strerror in *resultp */ goto exit; } #ifdef NOTYET /* XXX FIXME */ processInlineFlags(js, fp, &verbosity); gpsee_setVerbosity(verbosity); #endif /* Just compile and exit? */ if (F_ISSET(js->flags, NOEXEC)) { JSScript *script = NULL; JSObject *scrobj = NULL; if (!gpsee_compileScript(I->cx, fn, fp, NULL, &script, I->realm->globalObject, &scrobj)) { I->grt->exitType = et_exception; /* XXX FIXME: isatty(3) */ gpsee_reportUncaughtException(I->cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } else { I->grt->exitType = et_finished; rc = RPMRC_OK; } } else { char *const * Ienviron = NULL; if (F_ISSET(js->flags, ALLOW)) { #if defined(__APPLE__) Ienviron = (char *const *) _NSGetEnviron(); #else Ienviron = environ; #endif } I->grt->exitType = et_execFailure; if (gpsee_runProgramModule(I->cx, fn, NULL, fp, Iargv, Ienviron) == JS_FALSE) { int code = gpsee_getExceptionExitCode(I->cx); if (code >= 0) { I->grt->exitType = et_requested; I->grt->exitCode = code; /* XXX FIXME: format and return code in *resultp. */ /* XXX hack tp get code into rc -> ec by negating */ rc = -code; } else if (JS_IsExceptionPending(I->cx)) { /* XXX FIXME: isatty(3) */ gpsee_reportUncaughtException(I->cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } } else { I->grt->exitType = et_finished; rc = RPMRC_OK; } } fclose(fp); fp = NULL; #endif /* WITH_GPSEE */ } #if defined(WITH_GPSEE) exit: #endif /* WITH_GPSEE */ RPMJSDBG(0, (stderr, "<== %s(%p,%s) rc %d |%s|\n", __FUNCTION__, js, fn, rc, (resultp ? *resultp :""))); return rc; }
PRIntn prmain(PRIntn argc, char **argv) { void *stackBasePtr; gpsee_interpreter_t *jsi; /* Handle describing a GPSEE/JavaScript Interpreter */ gpsee_realm_t *realm; /* Interpreter's primordial realm */ JSContext *cx; /* A context in realm */ const char *scriptCode = NULL; /* String with JavaScript program in it */ const char *scriptFilename = NULL; /* Filename with JavaScript program in it */ char * const *script_argv; /* Becomes arguments array in JS program */ char * const *script_environ = NULL; /* Environment to pass to script */ char *flags = malloc(8); /* Flags found on command line */ int noRunScript = 0; /* !0 = compile but do not run */ int fiArg = 0; int skipSheBang = 0; int exitCode; int verbosity; /* Verbosity to use before flags are processed */ #ifdef GPSEE_DEBUGGER JSDContext *jsdc; #endif #if defined(__SURELYNX__) permanent_pool = apr_initRuntime(); #endif gpsee_setVerbosity(isatty(STDERR_FILENO) ? GSR_PREPROGRAM_TTY_VERBOSITY : GSR_PREPROGRAM_NOTTY_VERBOSITY); gpsee_openlog(gpsee_basename(argv[0])); /* Print usage and exit if no arguments were given */ if (argc < 2) usage(argv[0]); flags[0] = (char)0; fiArg = findFileToInterpret(argc, argv); if (fiArg == 0) /* Not a script file interpreter (shebang) */ { int c; char *flag_p = flags; while ((c = getopt(argc, argv, whenSureLynx("D:r:","") "v:c:hHnf:F:aCRxSUWdeJz")) != -1) { switch(c) { #if defined(__SURELYNX__) case 'D': redirect_output(permanent_pool, optarg); break; case 'r': /* handled by cfg_openfile() */ break; #endif case 'c': scriptCode = optarg; break; case 'h': usage(argv[0]); break; case 'H': moreHelp(argv[0]); break; case 'n': noRunScript = 1; break; case 'F': skipSheBang = 1; case 'f': scriptFilename = optarg; break; case 'a': case 'C': case 'd': case 'e': case 'J': case 'S': case 'R': case 'U': case 'W': case 'x': case 'z': { char *flags_storage = realloc(flags, (flag_p - flags) + 1 + 1); if (flags_storage != flags) { flag_p = (flag_p - flags) + flags_storage; flags = flags_storage; } *flag_p++ = c; *flag_p = '\0'; } break; case '?': { char buf[32]; snprintf(buf, sizeof(buf), "Invalid option: %c\n", optopt); fatal(buf); } case ':': { char buf[32]; snprintf(buf, sizeof(buf), "Missing parameter to option '%c'\n", optopt); fatal(buf); } } } /* getopt wend */ /* Create the script's argument vector with the script name as arguments[0] */ { char **nc_script_argv = malloc(sizeof(argv[0]) * (2 + (argc - optind))); nc_script_argv[0] = (char *)scriptFilename; memcpy(nc_script_argv + 1, argv + optind, sizeof(argv[0]) * ((1 + argc) - optind)); script_argv = nc_script_argv; } *flag_p = (char)0; } else { scriptFilename = argv[fiArg]; if (fiArg == 2) { if (argv[1][0] != '-') fatal("Invalid syntax for file-interpreter flags! (Must begin with '-')"); flags = realloc(flags, strlen(argv[1]) + 1); strcpy(flags, argv[1] + 1); } /* This is a file interpreter; script_argv is correct at offset fiArg. */ script_argv = argv + fiArg; } if (strchr(flags, 'a')) { #if defined(GPSEE_DARWIN_SYSTEM) script_environ = (char * const *)_NSGetEnviron(); #else extern char **environ; script_environ = (char * const *)environ; #endif } loadRuntimeConfig(scriptFilename, flags, argc, argv); if (strchr(flags, 'U') || (cfg_bool_value(cfg, "gpsee_force_no_utf8_c_strings") == cfg_true) || getenv("GPSEE_NO_UTF8_C_STRINGS")) { JS_DestroyRuntime(JS_NewRuntime(1024)); putenv((char *)"GPSEE_NO_UTF8_C_STRINGS=1"); } jsi = gpsee_createInterpreter(); realm = jsi->realm; cx = jsi->cx; #if defined(GPSEE_DEBUGGER) jsdc = gpsee_initDebugger(cx, realm, DEBUGGER_JS); #endif gpsee_setThreadStackLimit(cx, &stackBasePtr, strtol(cfg_default_value(cfg, "gpsee_thread_stack_limit_bytes", "0x80000"), NULL, 0)); processFlags(cx, flags, &verbosity); free(flags); #if defined(__SURELYNX__) sl_set_debugLevel(gpsee_verbosity(0)); /* enableTerminalLogs(permanent_pool, gpsee_verbosity(0) > 0, NULL); */ #else if (verbosity < GSR_MIN_TTY_VERBOSITY && isatty(STDERR_FILENO)) verbosity = GSR_MIN_TTY_VERBOSITY; #endif if (gpsee_verbosity(0) < verbosity) gpsee_setVerbosity(verbosity); /* Run JavaScript specified with -c */ if (scriptCode) { jsval v; if (JS_EvaluateScript(cx, realm->globalObject, scriptCode, strlen(scriptCode), "command_line", 1, &v) == JS_FALSE) { v = JSVAL_NULL; goto out; } v = JSVAL_NULL; } if ((argv[0][0] == '/') #if defined(SYSTEM_GSR) && (strcmp(argv[0], SYSTEM_GSR) != 0) #endif && cfg_bool_value(cfg, "no_gsr_preload_script") != cfg_true) { char preloadScriptFilename[FILENAME_MAX]; char mydir[FILENAME_MAX]; int i; jsi->grt->exitType = et_unknown; i = snprintf(preloadScriptFilename, sizeof(preloadScriptFilename), "%s/.%s_preload", gpsee_dirname(argv[0], mydir, sizeof(mydir)), gpsee_basename(argv[0])); if ((i == 0) || (i == (sizeof(preloadScriptFilename) -1))) gpsee_log(cx, GLOG_EMERG, PRODUCT_SHORTNAME ": Unable to create preload script filename!"); else errno = 0; if (access(preloadScriptFilename, F_OK) == 0) { jsval v; JSScript *script; JSObject *scrobj; if (!gpsee_compileScript(cx, preloadScriptFilename, NULL, NULL, &script, realm->globalObject, &scrobj)) { jsi->grt->exitType = et_compileFailure; gpsee_log(cx, GLOG_EMERG, PRODUCT_SHORTNAME ": Unable to compile preload script '%s'", preloadScriptFilename); goto out; } if (!script || !scrobj) goto out; if (!noRunScript) { JS_AddNamedObjectRoot(cx, &scrobj, "preload_scrobj"); jsi->grt->exitType = et_execFailure; if (JS_ExecuteScript(cx, realm->globalObject, script, &v) == JS_TRUE) jsi->grt->exitType = et_finished; else jsi->grt->exitType = et_exception; JS_RemoveObjectRoot(cx, &scrobj); v = JSVAL_NULL; } } if (jsi->grt->exitType & et_errorMask) goto out; } /* Setup for main-script running -- cancel preprogram verbosity and use our own error reporting system in gsr that does not use error reporter */ gpsee_setVerbosity(verbosity); JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT); if (!scriptFilename) { if (!scriptCode) /* Command-line options did not include code to run */ usage(argv[0]); if (jsi->grt->exitType == et_unknown) jsi->grt->exitType = et_finished; } else { FILE *scriptFile = openScriptFile(cx, scriptFilename, skipSheBang || (fiArg != 0)); if (!scriptFile) { gpsee_log(cx, GLOG_NOTICE, PRODUCT_SHORTNAME ": Unable to open' script '%s'! (%m)", scriptFilename); jsi->grt->exitType = et_compileFailure; goto out; } processInlineFlags(cx, scriptFile, &verbosity); gpsee_setVerbosity(verbosity); /* Just compile and exit? */ if (noRunScript) { JSScript *script; JSObject *scrobj; if (!gpsee_compileScript(cx, scriptFilename, scriptFile, NULL, &script, realm->globalObject, &scrobj)) { jsi->grt->exitType = et_exception; gpsee_reportUncaughtException(cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } else { jsi->grt->exitType = et_finished; } } else /* noRunScript is false; run the program */ { jsi->grt->exitType = et_execFailure; if (gpsee_runProgramModule(cx, scriptFilename, NULL, scriptFile, script_argv, script_environ) == JS_TRUE) { jsi->grt->exitType = et_finished; } else { int code; code = gpsee_getExceptionExitCode(cx); if (code >= 0) /** e.g. throw 6 */ { jsi->grt->exitType = et_requested; jsi->grt->exitCode = code; } else { if (JS_IsExceptionPending(cx)) { jsi->grt->exitType = et_exception; gpsee_reportUncaughtException(cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } } } } fclose(scriptFile); goto out; } out: #ifdef GPSEE_DEBUGGER gpsee_finiDebugger(jsdc); #endif if (jsi->grt->exitType & et_successMask) { exitCode = jsi->grt->exitCode; } else { const char *reason; exitCode = 1; switch(jsi->grt->exitType) { case et_successMask: case et_errorMask: case et_requested: case et_finished: case et_dummy: default: GPSEE_NOT_REACHED("impossible"); reason = NULL; /* quell compiler warning below */ break; case et_execFailure: reason = "execFailure - probable native module error, returning JS_FALSE without setting exception"; break; case et_compileFailure: reason = "script could not be compiled"; break; case et_unknown: reason = "unknown - probable native module error, returning JS_FALSE without setting exception"; break; case et_exception: reason = NULL; break; } if (reason) { gpsee_log(cx, GLOG_NOTICE, "Unexpected interpreter shutdown: %s (%m)", reason); if (gpsee_verbosity(0) == 0) { /* not gpsee_ */ fprintf(stderr, "*** Unexpected interpreter shutdown: %s", reason); if (errno) fprintf(stderr, " (%s)\n", strerror(errno)); else fputs("\n", stderr); } } } gpsee_destroyInterpreter(jsi); JS_ShutDown(); return exitCode; }