Annotation of sbbs/sbbs3/jsexec.c, revision 1.1

1.1     ! root        1: /* jsexec.c */
        !             2: 
        !             3: /* Execute a Synchronet JavaScript module from the command-line */
        !             4: 
        !             5: /* $Id: jsexec.c,v 1.75 2004/12/09 08:07:13 rswindell Exp $ */
        !             6: 
        !             7: /****************************************************************************
        !             8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
        !             9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
        !            10:  *                                                                                                                                                     *
        !            11:  * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html         *
        !            12:  *                                                                                                                                                     *
        !            13:  * This program is free software; you can redistribute it and/or                       *
        !            14:  * modify it under the terms of the GNU General Public License                         *
        !            15:  * as published by the Free Software Foundation; either version 2                      *
        !            16:  * of the License, or (at your option) any later version.                                      *
        !            17:  * See the GNU General Public License for more details: gpl.txt or                     *
        !            18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
        !            19:  *                                                                                                                                                     *
        !            20:  * Anonymous FTP access to the most recent released source is available at     *
        !            21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
        !            22:  *                                                                                                                                                     *
        !            23:  * Anonymous CVS access to the development source and modification history     *
        !            24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
        !            25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
        !            26:  *     (just hit return, no password is necessary)                                                     *
        !            27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
        !            28:  *                                                                                                                                                     *
        !            29:  * For Synchronet coding style and modification guidelines, see                                *
        !            30:  * http://www.synchro.net/source.html                                                                          *
        !            31:  *                                                                                                                                                     *
        !            32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
        !            33:  * format) via e-mail to [email protected]                                                                      *
        !            34:  *                                                                                                                                                     *
        !            35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
        !            36:  ****************************************************************************/
        !            37: 
        !            38: #ifndef JAVASCRIPT
        !            39: #define JAVASCRIPT
        !            40: #endif
        !            41: 
        !            42: #ifdef __unix__
        !            43: #include <signal.h>
        !            44: #endif
        !            45: 
        !            46: #include "sbbs.h"
        !            47: 
        !            48: #define DEFAULT_LOG_MASK       0xff    /* Display all LOG levels */
        !            49: #define DEFAULT_ERR_LOG_LVL    LOG_WARNING
        !            50: 
        !            51: JSRuntime*     js_runtime;
        !            52: JSContext*     js_cx;
        !            53: JSObject*      js_glob;
        !            54: js_branch_t    branch;
        !            55: scfg_t         scfg;
        !            56: ulong          js_max_bytes=JAVASCRIPT_MAX_BYTES;
        !            57: ulong          js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
        !            58: FILE*          confp;
        !            59: FILE*          errfp;
        !            60: FILE*          nulfp;
        !            61: FILE*          statfp;
        !            62: char           revision[16];
        !            63: char*          host_name=NULL;
        !            64: char           host_name_buf[128];
        !            65: BOOL           pause_on_exit=FALSE;
        !            66: BOOL           pause_on_error=FALSE;
        !            67: BOOL           terminated=FALSE;
        !            68: DWORD          log_mask=DEFAULT_LOG_MASK;
        !            69: int            err_level=DEFAULT_ERR_LOG_LVL;
        !            70: 
        !            71: void banner(FILE* fp)
        !            72: {
        !            73:        fprintf(fp,"\nJSexec v%s%c-%s (rev %s) - "
        !            74:                "Execute Synchronet JavaScript Module\n"
        !            75:                ,VERSION,REVISION
        !            76:                ,PLATFORM_DESC
        !            77:                ,revision
        !            78:                );
        !            79: }
        !            80: 
        !            81: void usage(FILE* fp)
        !            82: {
        !            83:        banner(fp);
        !            84: 
        !            85:        fprintf(fp,"\nusage: jsexec [-opts] [path]module[.js] [args]\n"
        !            86:                "\navailable opts:\n\n"
        !            87:                "\t-c<ctrl_dir>   specify path to Synchronet CTRL directory\n"
        !            88:                "\t-m<bytes>      set maximum heap size (default=%u bytes)\n"
        !            89:                "\t-s<bytes>      set context stack size (default=%u bytes)\n"
        !            90:                "\t-b<limit>      set branch limit (default=%u, 0=unlimited)\n"
        !            91:                "\t-y<interval>   set yield interval (default=%u, 0=never)\n"
        !            92:                "\t-g<interval>   set garbage collection interval (default=%u, 0=never)\n"
        !            93:                "\t-h[hostname]   use local or specified host name (instead of SCFG value)\n"
        !            94:                "\t-L<mask>       set log level mask (default=0x%x)\n"
        !            95:                "\t-E<level>      set error log level threshold (default=%d)\n"
        !            96:                "\t-a             append instead of overwriting message output files\n"
        !            97:                "\t-e<filename>   send error messages to file in addition to stderr\n"
        !            98:                "\t-o<filename>   send console messages to file instead of stdout\n"
        !            99:                "\t-n             send status messages to %s instead of stderr\n"
        !           100:                "\t-q             send console messages to %s instead of stdout\n"
        !           101:                "\t-x             disable auto-termination on local abort signal\n"
        !           102:                "\t-l             loop until intentionally terminated\n"
        !           103:                "\t-p             wait for keypress (pause) on exit\n"
        !           104:                "\t-!             wait for keypress (pause) on error\n"
        !           105:                ,JAVASCRIPT_MAX_BYTES
        !           106:                ,JAVASCRIPT_CONTEXT_STACK
        !           107:                ,JAVASCRIPT_BRANCH_LIMIT
        !           108:                ,JAVASCRIPT_YIELD_INTERVAL
        !           109:                ,JAVASCRIPT_GC_INTERVAL
        !           110:                ,DEFAULT_LOG_MASK
        !           111:                ,DEFAULT_ERR_LOG_LVL
        !           112:                ,_PATH_DEVNULL
        !           113:                ,_PATH_DEVNULL
        !           114:                );
        !           115: }
        !           116: 
        !           117: /* Log printf */
        !           118: int lprintf(int level, char *fmt, ...)
        !           119: {
        !           120:        va_list argptr;
        !           121:        char sbuf[1024];
        !           122:        int ret=0;
        !           123: 
        !           124:        if(!(log_mask&(1<<level)))
        !           125:                return(0);
        !           126: 
        !           127:     va_start(argptr,fmt);
        !           128:     vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
        !           129:        sbuf[sizeof(sbuf)-1]=0;
        !           130:     va_end(argptr);
        !           131:        if(level<=err_level)
        !           132:                ret=fprintf(errfp,"%s",sbuf);
        !           133:        if(level>err_level || (errfp!=stderr && errfp!=confp))
        !           134:                ret=fprintf(confp,"%s",sbuf);
        !           135:     return(ret);
        !           136: }
        !           137: 
        !           138: #if defined(_WINSOCKAPI_)
        !           139: 
        !           140: WSADATA WSAData;
        !           141: #define SOCKLIB_DESC WSAData.szDescription
        !           142: static BOOL WSAInitialized=FALSE;
        !           143: 
        !           144: static BOOL winsock_startup(void)
        !           145: {
        !           146:        int             status;             /* Status Code */
        !           147: 
        !           148:     if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0) {
        !           149: /*             fprintf(statfp,"%s %s\n",WSAData.szDescription, WSAData.szSystemStatus); */
        !           150:                WSAInitialized=TRUE;
        !           151:                return(TRUE);
        !           152:        }
        !           153: 
        !           154:     lprintf(LOG_ERR,"!WinSock startup ERROR %d\n", status);
        !           155:        return(FALSE);
        !           156: }
        !           157: 
        !           158: #else /* No WINSOCK */
        !           159: 
        !           160: #define winsock_startup()      (TRUE)
        !           161: #define SOCKLIB_DESC NULL
        !           162: 
        !           163: #endif
        !           164: 
        !           165: void bail(int code)
        !           166: {
        !           167: 
        !           168: #if defined(_WINSOCKAPI_)
        !           169:        if(WSAInitialized && WSACleanup()!=0) 
        !           170:                lprintf(LOG_ERR,"!WSACleanup ERROR %d\n",ERROR_VALUE);
        !           171: #endif
        !           172: 
        !           173:        if(pause_on_exit || (code && pause_on_error)) {
        !           174:                fprintf(statfp,"\nHit enter to continue...");
        !           175:                getchar();
        !           176:        }
        !           177: 
        !           178:        if(code)
        !           179:                fprintf(statfp,"\nReturning error code: %d\n",code);
        !           180:        exit(code);
        !           181: }
        !           182: 
        !           183: static JSBool
        !           184: js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           185: {
        !           186:     uintN              i=0;
        !           187:        int32           level=LOG_INFO;
        !           188:     JSString*  str=NULL;
        !           189: 
        !           190:        if(JSVAL_IS_NUMBER(argv[i]))
        !           191:                JS_ValueToInt32(cx,argv[i++],&level);
        !           192: 
        !           193:        for(; i<argc; i++) {
        !           194:                if((str=JS_ValueToString(cx, argv[i]))==NULL)
        !           195:                        return(JS_FALSE);
        !           196:                lprintf(level,"%s",JS_GetStringBytes(str));
        !           197:        }
        !           198:        if(argc)
        !           199:                lprintf(level,"\n");
        !           200: 
        !           201:        if(str==NULL)
        !           202:                *rval = JSVAL_VOID;
        !           203:        else
        !           204:                *rval = STRING_TO_JSVAL(str);
        !           205: 
        !           206:     return(JS_TRUE);
        !           207: }
        !           208: 
        !           209: static JSBool
        !           210: js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           211: {
        !           212:        char*   buf;
        !           213:        int             rd;
        !           214:        int32   len=128;
        !           215: 
        !           216:        *rval = JSVAL_VOID;
        !           217: 
        !           218:        if(argc)
        !           219:                JS_ValueToInt32(cx,argv[0],&len);
        !           220:        if((buf=malloc(len))==NULL)
        !           221:                return(JS_TRUE);
        !           222: 
        !           223:        rd=fread(buf,sizeof(char),len,stdin);
        !           224: 
        !           225:        if(rd>=0)
        !           226:                *rval = STRING_TO_JSVAL(JS_NewStringCopyN(cx,buf,rd));
        !           227: 
        !           228:        free(buf);
        !           229:     return(JS_TRUE);
        !           230: }
        !           231: 
        !           232: static JSBool
        !           233: js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           234: {
        !           235:        char*   buf;
        !           236:        char*   p;
        !           237:        int32   len=128;
        !           238: 
        !           239:        *rval = JSVAL_VOID;
        !           240: 
        !           241:        if(argc)
        !           242:                JS_ValueToInt32(cx,argv[0],&len);
        !           243:        if((buf=malloc(len+1))==NULL)
        !           244:                return(JS_TRUE);
        !           245: 
        !           246:        p=fgets(buf,len+1,stdin);
        !           247: 
        !           248:        if(p!=NULL)
        !           249:                *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,truncnl(p)));
        !           250: 
        !           251:        free(buf);
        !           252:     return(JS_TRUE);
        !           253: }
        !           254: 
        !           255: 
        !           256: static JSBool
        !           257: js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           258: {
        !           259:     uintN              i;
        !           260:     JSString*  str=NULL;
        !           261: 
        !           262:     for (i = 0; i < argc; i++) {
        !           263:                if((str=JS_ValueToString(cx, argv[i]))==NULL)
        !           264:                    return(JS_FALSE);
        !           265:                fprintf(confp,"%s",JS_GetStringBytes(str));
        !           266:        }
        !           267: 
        !           268:        if(str==NULL)
        !           269:                *rval = JSVAL_VOID;
        !           270:        else
        !           271:                *rval = STRING_TO_JSVAL(str);
        !           272:     return(JS_TRUE);
        !           273: }
        !           274: 
        !           275: static JSBool
        !           276: js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           277: {
        !           278:        if(!js_write(cx,obj,argc,argv,rval))
        !           279:                return(JS_FALSE);
        !           280: 
        !           281:        fprintf(confp,"\n");
        !           282:     return(JS_TRUE);
        !           283: }
        !           284: 
        !           285: static JSBool
        !           286: js_printf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           287: {
        !           288:        char*           p;
        !           289:     uintN              i;
        !           290:        JSString *      fmt;
        !           291:     JSString * str;
        !           292:        va_list         arglist[64];
        !           293: 
        !           294:        if((fmt = JS_ValueToString(cx, argv[0]))==NULL)
        !           295:                return(JS_FALSE);
        !           296: 
        !           297:        memset(arglist,0,sizeof(arglist));      // Initialize arglist to NULLs
        !           298: 
        !           299:     for (i = 1; i < argc && i<sizeof(arglist)/sizeof(arglist[0]); i++) {
        !           300:                if(JSVAL_IS_DOUBLE(argv[i]))
        !           301:                        arglist[i-1]=(char*)(unsigned long)*JSVAL_TO_DOUBLE(argv[i]);
        !           302:                else if(JSVAL_IS_INT(argv[i]))
        !           303:                        arglist[i-1]=(char *)JSVAL_TO_INT(argv[i]);
        !           304:                else {
        !           305:                        if((str=JS_ValueToString(cx, argv[i]))==NULL) {
        !           306:                                JS_ReportError(cx,"JS_ValueToString failed");
        !           307:                            return(JS_FALSE);
        !           308:                        }
        !           309:                        arglist[i-1]=JS_GetStringBytes(str);
        !           310:                }
        !           311:        }
        !           312:        
        !           313:        if((p=JS_vsmprintf(JS_GetStringBytes(fmt),(char*)arglist))==NULL)
        !           314:                return(JS_FALSE);
        !           315: 
        !           316:        fprintf(confp,"%s",p);
        !           317: 
        !           318:        *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, p));
        !           319: 
        !           320:        JS_smprintf_free(p);
        !           321: 
        !           322:     return(JS_TRUE);
        !           323: }
        !           324: 
        !           325: static JSBool
        !           326: js_alert(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           327: {
        !           328:     JSString * str;
        !           329: 
        !           330:        if((str=JS_ValueToString(cx, argv[0]))==NULL)
        !           331:            return(JS_FALSE);
        !           332: 
        !           333:        fprintf(confp,"!%s\n",JS_GetStringBytes(str));
        !           334: 
        !           335:        *rval = JSVAL_VOID;
        !           336:     return(JS_TRUE);
        !           337: }
        !           338: 
        !           339: static JSBool
        !           340: js_confirm(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           341: {
        !           342:     JSString * str;
        !           343: 
        !           344:        if((str=JS_ValueToString(cx, argv[0]))==NULL)
        !           345:            return(JS_FALSE);
        !           346: 
        !           347:        printf("%s (Y/N)?", JS_GetStringBytes(str));
        !           348: 
        !           349:        *rval = BOOLEAN_TO_JSVAL(FALSE);
        !           350:        return(JS_TRUE);
        !           351: }
        !           352: 
        !           353: static JSBool
        !           354: js_prompt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           355: {
        !           356:        char            instr[81];
        !           357:     JSString * prompt;
        !           358:     JSString * str;
        !           359: 
        !           360:        if(!JSVAL_IS_VOID(argv[0])) {
        !           361:                if((prompt=JS_ValueToString(cx, argv[0]))==NULL)
        !           362:                        return(JS_FALSE);
        !           363:                fprintf(confp,"%s: ",JS_GetStringBytes(prompt));
        !           364:        }
        !           365: 
        !           366:        if(argc>1) {
        !           367:                if((str=JS_ValueToString(cx, argv[1]))==NULL)
        !           368:                    return(JS_FALSE);
        !           369:                SAFECOPY(instr,JS_GetStringBytes(str));
        !           370:        } else
        !           371:                instr[0]=0;
        !           372: 
        !           373:        if(!fgets(instr,sizeof(instr),stdin)) {
        !           374:                *rval = JSVAL_VOID;
        !           375:                return(JS_TRUE);
        !           376:        }
        !           377: 
        !           378:        if((str=JS_NewStringCopyZ(cx, instr))==NULL)
        !           379:            return(JS_FALSE);
        !           380: 
        !           381:        *rval = STRING_TO_JSVAL(str);
        !           382:     return(JS_TRUE);
        !           383: }
        !           384: 
        !           385: static JSBool
        !           386: js_chdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           387: {
        !           388:        char*           p;
        !           389: 
        !           390:        if((p=JS_GetStringBytes(JS_ValueToString(cx, argv[0])))==NULL) {
        !           391:                *rval = INT_TO_JSVAL(-1);
        !           392:                return(JS_TRUE);
        !           393:        }
        !           394: 
        !           395:        *rval = BOOLEAN_TO_JSVAL(chdir(p)==0);
        !           396:        return(JS_TRUE);
        !           397: }
        !           398: 
        !           399: static JSBool
        !           400: js_putenv(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           401: {
        !           402:        char*           p;
        !           403: 
        !           404:        if((p=JS_GetStringBytes(JS_ValueToString(cx, argv[0])))==NULL) {
        !           405:                *rval = INT_TO_JSVAL(-1);
        !           406:                return(JS_TRUE);
        !           407:        }
        !           408: 
        !           409:        *rval = BOOLEAN_TO_JSVAL(putenv(p)==0);
        !           410:        return(JS_TRUE);
        !           411: }
        !           412: 
        !           413: static jsSyncMethodSpec js_global_functions[] = {
        !           414:        {"log",                         js_log,                         1},
        !           415:        {"read",                        js_read,            1},
        !           416:        {"readln",                      js_readln,          1},
        !           417:     {"write",           js_write,           0},
        !           418:     {"writeln",         js_writeln,         0},
        !           419:     {"print",           js_writeln,         0},
        !           420:     {"printf",          js_printf,          1},        
        !           421:        {"alert",                       js_alert,                       1},
        !           422:        {"prompt",                      js_prompt,                      1},
        !           423:        {"confirm",                     js_confirm,                     1},
        !           424:        {"chdir",                       js_chdir,                       1},
        !           425:        {"putenv",                      js_putenv,                      1},
        !           426:     {0}
        !           427: };
        !           428: 
        !           429: static void
        !           430: js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
        !           431: {
        !           432:        char    line[64];
        !           433:        char    file[MAX_PATH+1];
        !           434:        const char*     warning;
        !           435: 
        !           436:        if(report==NULL) {
        !           437:                lprintf(LOG_ERR,"!JavaScript: %s\n", message);
        !           438:                return;
        !           439:     }
        !           440: 
        !           441:        if(report->filename)
        !           442:                sprintf(file," %s",report->filename);
        !           443:        else
        !           444:                file[0]=0;
        !           445: 
        !           446:        if(report->lineno)
        !           447:                sprintf(line," line %d",report->lineno);
        !           448:        else
        !           449:                line[0]=0;
        !           450: 
        !           451:        if(JSREPORT_IS_WARNING(report->flags)) {
        !           452:                if(JSREPORT_IS_STRICT(report->flags))
        !           453:                        warning="strict warning";
        !           454:                else
        !           455:                        warning="warning";
        !           456:        } else
        !           457:                warning="";
        !           458: 
        !           459:        lprintf(LOG_ERR,"!JavaScript %s%s%s: %s\n",warning,file,line,message);
        !           460: }
        !           461: 
        !           462: static JSBool
        !           463: js_BranchCallback(JSContext *cx, JSScript *script)
        !           464: {
        !           465:     return(js_CommonBranchCallback(cx,&branch));
        !           466: }
        !           467: 
        !           468: static BOOL js_CreateEnvObject(JSContext* cx, JSObject* glob, char** env)
        !           469: {
        !           470:        char            name[256];
        !           471:        char*           val;
        !           472:        uint            i;
        !           473:        JSObject*       js_env;
        !           474: 
        !           475:        if((js_env=JS_NewObject(js_cx, NULL, NULL, glob))==NULL)
        !           476:                return(FALSE);
        !           477: 
        !           478:        if(!JS_DefineProperty(cx, glob, "env", OBJECT_TO_JSVAL(js_env)
        !           479:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
        !           480:                return(FALSE);
        !           481: 
        !           482:        for(i=0;env[i]!=NULL;i++) {
        !           483:                SAFECOPY(name,env[i]);
        !           484:                truncstr(name,"=");
        !           485:                val=strchr(env[i],'=');
        !           486:                if(val==NULL)
        !           487:                        val="";
        !           488:                else
        !           489:                        val++;
        !           490:                if(!JS_DefineProperty(cx, js_env, name, STRING_TO_JSVAL(JS_NewStringCopyZ(cx,val))
        !           491:                        ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
        !           492:                        return(FALSE);
        !           493:        }
        !           494: 
        !           495:        return(TRUE);
        !           496: }
        !           497: 
        !           498: static BOOL js_init(char** environ)
        !           499: {
        !           500:        fprintf(statfp,"%s\n",(char *)JS_GetImplementationVersion());
        !           501: 
        !           502:        fprintf(statfp,"JavaScript: Creating runtime: %lu bytes\n"
        !           503:                ,js_max_bytes);
        !           504: 
        !           505:        if((js_runtime = JS_NewRuntime(js_max_bytes))==NULL)
        !           506:                return(FALSE);
        !           507: 
        !           508:        fprintf(statfp,"JavaScript: Initializing context (stack: %lu bytes)\n"
        !           509:                ,js_cx_stack);
        !           510: 
        !           511:     if((js_cx = JS_NewContext(js_runtime, js_cx_stack))==NULL)
        !           512:                return(FALSE);
        !           513: 
        !           514:        JS_SetErrorReporter(js_cx, js_ErrorReporter);
        !           515: 
        !           516:        /* Global Object */
        !           517:        if((js_glob=js_CreateCommonObjects(js_cx, &scfg, NULL, js_global_functions
        !           518:                ,time(NULL), host_name, SOCKLIB_DESC    /* system */
        !           519:                ,&branch                                                                /* js */
        !           520:                ,NULL,INVALID_SOCKET                                    /* client */
        !           521:                ,NULL                                                                   /* server */
        !           522:                ))==NULL)
        !           523:                return(FALSE);
        !           524: 
        !           525:        /* Environment Object (associative array) */
        !           526:        if(!js_CreateEnvObject(js_cx, js_glob, environ))
        !           527:                return(FALSE);
        !           528: 
        !           529:        return(TRUE);
        !           530: }
        !           531: 
        !           532: static const char* js_ext(const char* fname)
        !           533: {
        !           534:        if(strchr(fname,'.')==NULL)
        !           535:                return(".js");
        !           536:        return("");
        !           537: }
        !           538: 
        !           539: long js_exec(const char *fname, char** args)
        !           540: {
        !           541:        int                     argc=0;
        !           542:        uint            line_no;
        !           543:        char            path[MAX_PATH+1];
        !           544:        char            line[1024];
        !           545:        char            compiler[32];
        !           546:        char            rev_detail[256];
        !           547:        size_t          len;
        !           548:        char*           js_buf=NULL;
        !           549:        size_t          js_buflen;
        !           550:        JSScript*       js_script=NULL;
        !           551:        JSString*       arg;
        !           552:        JSObject*       argv;
        !           553:        FILE*           fp=stdin;
        !           554:        jsval           val;
        !           555:        jsval           rval=JSVAL_VOID;
        !           556:        int32           result=0;
        !           557:        
        !           558:        if(fname!=NULL) {
        !           559:                if(strcspn(fname,"/\\")==strlen(fname)) {
        !           560:                        sprintf(path,"%s%s%s",scfg.mods_dir,fname,js_ext(fname));
        !           561:                        if(scfg.mods_dir[0]==0 || !fexistcase(path))
        !           562:                                sprintf(path,"%s%s%s",scfg.exec_dir,fname,js_ext(fname));
        !           563:                } else
        !           564:                        SAFECOPY(path,fname);
        !           565: 
        !           566:                if(!fexistcase(path)) {
        !           567:                        lprintf(LOG_ERR,"!Module file (%s) doesn't exist\n",path);
        !           568:                        return(-1); 
        !           569:                }
        !           570: 
        !           571:                if((fp=fopen(path,"r"))==NULL) {
        !           572:                        lprintf(LOG_ERR,"!Error %d (%s) opening %s\n",errno,STRERROR(errno),path);
        !           573:                        return(-1);
        !           574:                }
        !           575:        }
        !           576:        JS_ClearPendingException(js_cx);
        !           577: 
        !           578: 
        !           579:        argv=JS_NewArrayObject(js_cx, 0, NULL);
        !           580:        JS_DefineProperty(js_cx, js_glob, "argv", OBJECT_TO_JSVAL(argv)
        !           581:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           582: 
        !           583:        for(argc=0;args[argc];argc++) {
        !           584:                arg = JS_NewStringCopyZ(js_cx, args[argc]);
        !           585:                if(arg==NULL)
        !           586:                        break;
        !           587:                val=STRING_TO_JSVAL(arg);
        !           588:                if(!JS_SetElement(js_cx, argv, argc, &val))
        !           589:                        break;
        !           590:        }
        !           591:        JS_DefineProperty(js_cx, js_glob, "argc", INT_TO_JSVAL(argc)
        !           592:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           593: 
        !           594:        JS_DefineProperty(js_cx, js_glob, "jsexec_revision"
        !           595:                ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,revision))
        !           596:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           597: 
        !           598:        DESCRIBE_COMPILER(compiler);
        !           599: 
        !           600:        sprintf(rev_detail,"JSexec %s%s  "
        !           601:                "Compiled %s %s with %s"
        !           602:                ,revision
        !           603: #ifdef _DEBUG
        !           604:                ," Debug"
        !           605: #else
        !           606:                ,""
        !           607: #endif
        !           608:                ,__DATE__, __TIME__, compiler
        !           609:                );
        !           610: 
        !           611:        JS_DefineProperty(js_cx, js_glob, "jsexec_revision_detail"
        !           612:                ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,rev_detail))
        !           613:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           614: 
        !           615:        JS_SetBranchCallback(js_cx, js_BranchCallback);
        !           616: 
        !           617:        if(fp==stdin)    /* Using stdin for script source */
        !           618:                SAFECOPY(path,"stdin");
        !           619: 
        !           620:        fprintf(statfp,"Reading script from %s\n",path);
        !           621:        line_no=0;
        !           622:        js_buflen=0;
        !           623:        while(!feof(fp)) {
        !           624:                if(!fgets(line,sizeof(line),fp))
        !           625:                        break;
        !           626:                line_no++;
        !           627: #if defined(__unix__)  /* Support Unix Shell Scripts that start with #!/path/to/jsexec */
        !           628:                if(line_no==1 && strncmp(line,"#!",2)==0)
        !           629:                        strcpy(line,"\n");      /* To keep line count correct */
        !           630: #endif
        !           631:                len=strlen(line);
        !           632:                if((js_buf=realloc(js_buf,js_buflen+len))==NULL) {
        !           633:                        lprintf(LOG_ERR,"!Error allocating %u bytes of memory\n"
        !           634:                                ,js_buflen+len);
        !           635:                        return(-1);
        !           636:                }
        !           637:                memcpy(js_buf+js_buflen,line,len);
        !           638:                js_buflen+=len;
        !           639:        }
        !           640:        if(fp!=NULL && fp!=stdin)
        !           641:                fclose(fp);
        !           642: 
        !           643:        if((js_script=JS_CompileScript(js_cx, js_glob, js_buf, js_buflen, fname==NULL ? NULL : path, 1))==NULL) {
        !           644:                lprintf(LOG_ERR,"!Error compiling script from %s\n",path);
        !           645:                return(-1);
        !           646:        }
        !           647:        JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
        !           648: 
        !           649:        JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
        !           650: 
        !           651:        if(rval!=JSVAL_VOID) {
        !           652:                fprintf(statfp,"Using JavaScript exit_code: %s\n",JS_GetStringBytes(JS_ValueToString(js_cx,rval)));
        !           653:                JS_ValueToInt32(js_cx,rval,&result);
        !           654:        }
        !           655: 
        !           656:        JS_DestroyScript(js_cx, js_script);
        !           657: 
        !           658:        JS_GC(js_cx);
        !           659: 
        !           660:        if(js_buf!=NULL)
        !           661:                free(js_buf);
        !           662: 
        !           663:        return(result);
        !           664: }
        !           665: 
        !           666: void break_handler(int type)
        !           667: {
        !           668:        fprintf(statfp,"\n-> Terminated Locally (signal: %d)\n",type);
        !           669:        terminated=TRUE;
        !           670: }
        !           671: 
        !           672: #if defined(_WIN32)
        !           673: BOOL WINAPI ControlHandler(DWORD CtrlType)
        !           674: {
        !           675:        break_handler((int)CtrlType);
        !           676:        return TRUE;
        !           677: }
        !           678: #endif
        !           679: 
        !           680: /*********************/
        !           681: /* Entry point (duh) */
        !           682: /*********************/
        !           683: int main(int argc, char **argv, char** environ)
        !           684: {
        !           685:        char    error[512];
        !           686:        char*   module=NULL;
        !           687:        char*   p;
        !           688:        char*   omode="w";
        !           689:        int             argn;
        !           690:        long    result;
        !           691:        BOOL    loop=FALSE;
        !           692: 
        !           693:        confp=stdout;
        !           694:        errfp=stderr;
        !           695:        if((nulfp=fopen(_PATH_DEVNULL,"w+"))==NULL) {
        !           696:                perror(_PATH_DEVNULL);
        !           697:                bail(-1);
        !           698:        }
        !           699:        if(isatty(fileno(stderr)))
        !           700:                statfp=stderr;
        !           701:        else    /* if redirected, don't send status messages to stderr */
        !           702:                statfp=nulfp;
        !           703: 
        !           704:        branch.limit=JAVASCRIPT_BRANCH_LIMIT;
        !           705:        branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
        !           706:        branch.gc_interval=JAVASCRIPT_GC_INTERVAL;
        !           707:        branch.terminated=&terminated;
        !           708:        branch.auto_terminate=TRUE;
        !           709: 
        !           710:        sscanf("$Revision: 1.75 $", "%*s %s", revision);
        !           711: 
        !           712:        memset(&scfg,0,sizeof(scfg));
        !           713:        scfg.size=sizeof(scfg);
        !           714: 
        !           715:        if(!winsock_startup())
        !           716:                bail(2);
        !           717: 
        !           718:        for(argn=1;argn<argc && module==NULL;argn++) {
        !           719:                if(argv[argn][0]=='-') {
        !           720:                        p=argv[argn]+2;
        !           721:                        switch(argv[argn][1]) {
        !           722:                                case 'a':
        !           723:                                        omode="a";
        !           724:                                        break;
        !           725:                                case 'm':
        !           726:                                        if(*p==0) p=argv[++argn];
        !           727:                                        js_max_bytes=strtoul(p,NULL,0);
        !           728:                                        break;
        !           729:                                case 's':
        !           730:                                        if(*p==0) p=argv[++argn];
        !           731:                                        js_cx_stack=strtoul(p,NULL,0);
        !           732:                                        break;
        !           733:                                case 'b':
        !           734:                                        if(*p==0) p=argv[++argn];
        !           735:                                        branch.limit=strtoul(p,NULL,0);
        !           736:                                        break;
        !           737:                                case 'y':
        !           738:                                        if(*p==0) p=argv[++argn];
        !           739:                                        branch.yield_interval=strtoul(p,NULL,0);
        !           740:                                        break;
        !           741:                                case 'g':
        !           742:                                        if(*p==0) p=argv[++argn];
        !           743:                                        branch.gc_interval=strtoul(p,NULL,0);
        !           744:                                        break;
        !           745:                                case 'h':
        !           746:                                        if(*p==0)
        !           747:                                                gethostname(host_name=host_name_buf,sizeof(host_name_buf));
        !           748:                                        else
        !           749:                                                host_name=p;
        !           750:                                        break;
        !           751:                                case 'L':
        !           752:                                        if(*p==0) p=argv[++argn];
        !           753:                                        log_mask=strtol(p,NULL,0);
        !           754:                                        break;
        !           755:                                case 'E':
        !           756:                                        if(*p==0) p=argv[++argn];
        !           757:                                        err_level=strtol(p,NULL,0);
        !           758:                                        break;
        !           759:                                case 'e':
        !           760:                                        if(*p==0) p=argv[++argn];
        !           761:                                        if((errfp=fopen(p,omode))==NULL) {
        !           762:                                                perror(p);
        !           763:                                                bail(1);
        !           764:                                        }
        !           765:                                        break;
        !           766:                                case 'o':
        !           767:                                        if(*p==0) p=argv[++argn];
        !           768:                                        if((confp=fopen(p,omode))==NULL) {
        !           769:                                                perror(p);
        !           770:                                                bail(1);
        !           771:                                        }
        !           772:                                        break;
        !           773:                                case 'q':
        !           774:                                        confp=nulfp;
        !           775:                                        break;
        !           776:                                case 'n':
        !           777:                                        statfp=nulfp;
        !           778:                                        break;
        !           779:                                case 'x':
        !           780:                                        branch.auto_terminate=FALSE;
        !           781:                                        break;
        !           782:                                case 'l':
        !           783:                                        loop=TRUE;
        !           784:                                        break;
        !           785:                                case 'p':
        !           786:                                        pause_on_exit=TRUE;
        !           787:                                        break;
        !           788:                                case '!':
        !           789:                                        pause_on_error=TRUE;
        !           790:                                        break;
        !           791:                                case 'c':
        !           792:                                        if(*p==0) p=argv[++argn];
        !           793:                                        SAFECOPY(scfg.ctrl_dir,p);
        !           794:                                        break;
        !           795:                                default:
        !           796:                                        fprintf(errfp,"\n!Unsupported option: %s\n",argv[argn]);
        !           797:                                case '?':
        !           798:                                        usage(errfp);
        !           799:                                        bail(1);
        !           800:                        }
        !           801:                        continue;
        !           802:                }
        !           803:                module=argv[argn];
        !           804:        }
        !           805: 
        !           806:        if(scfg.ctrl_dir[0]==0) {
        !           807:                if((p=getenv("SBBSCTRL"))==NULL) {
        !           808:                        lprintf(LOG_ERR,"\nSBBSCTRL environment variable not set and -c option not specified.\n");
        !           809:                        lprintf(LOG_ERR,"\nExample: SET SBBSCTRL=/sbbs/ctrl\n");
        !           810:                        lprintf(LOG_ERR,"\n     or: %s -c /sbbs/ctrl [module]\n",argv[0]);
        !           811:                        bail(1)        !           812:                }
        !           813:                SAFECOPY(scfg.ctrl_dir,p);
        !           814:        }       
        !           815: 
        !           816:        if(module==NULL && isatty(fileno(stdin))) {
        !           817:                lprintf(LOG_ERR,"\n!Module name not specified\n");
        !           818:                usage(errfp);
        !           819:                bail(1)        !           820:        }
        !           821: 
        !           822:        banner(statfp);
        !           823: 
        !           824:        if(chdir(scfg.ctrl_dir)!=0)
        !           825:                lprintf(LOG_ERR,"!ERROR changing directory to: %s", scfg.ctrl_dir);
        !           826: 
        !           827:        fprintf(statfp,"\nLoading configuration files from %s\n",scfg.ctrl_dir);
        !           828:        if(!load_cfg(&scfg,NULL,TRUE,error)) {
        !           829:                lprintf(LOG_ERR,"!ERROR loading configuration files: %s\n",error);
        !           830:                bail(1);
        !           831:        }
        !           832:        prep_dir(scfg.data_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
        !           833: 
        !           834:        if(host_name==NULL)
        !           835:                host_name=scfg.sys_inetaddr;
        !           836: 
        !           837:        if(!(scfg.sys_misc&SM_LOCAL_TZ))
        !           838:                putenv("TZ=UTC0");
        !           839: 
        !           840:        /* Don't cache error log */
        !           841:        setvbuf(errfp,NULL,_IONBF,0);
        !           842: 
        !           843:        /* Install Ctrl-C/Break signal handler here */
        !           844: #if defined(_WIN32)
        !           845:        SetConsoleCtrlHandler(ControlHandler, TRUE /* Add */);
        !           846: #elif defined(__unix__)
        !           847:        signal(SIGQUIT,break_handler);
        !           848:        signal(SIGINT,break_handler);
        !           849:        signal(SIGTERM,break_handler);
        !           850: 
        !           851:        /* Don't die on SIGPIPE or SIGHUP */
        !           852:        signal(SIGPIPE,SIG_IGN);
        !           853:        signal(SIGHUP,SIG_IGN);
        !           854: #endif
        !           855: 
        !           856:        do {
        !           857: 
        !           858:                if(!js_init(environ)) {
        !           859:                        lprintf(LOG_ERR,"!JavaScript initialization failure\n");
        !           860:                        bail(1);
        !           861:                }
        !           862:                fprintf(statfp,"\n");
        !           863: 
        !           864:                result=js_exec(module,&argv[argn]);
        !           865: 
        !           866:                fprintf(statfp,"\n");
        !           867:                fprintf(statfp,"JavaScript: Destroying context\n");
        !           868:                JS_DestroyContext(js_cx);
        !           869:                fprintf(statfp,"JavaScript: Destroying runtime\n");
        !           870:                JS_DestroyRuntime(js_runtime);  
        !           871: 
        !           872:        } while(loop && !terminated);
        !           873: 
        !           874:        bail(result);
        !           875: 
        !           876:        return(-1);     /* never gets here */
        !           877: }
        !           878: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.