Annotation of sbbs/src/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.109 2006/09/15 21:12:53 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 2006 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 "ciolib.h"
        !            47: 
        !            48: #include "sbbs.h"
        !            49: 
        !            50: #define DEFAULT_LOG_LEVEL      LOG_DEBUG       /* Display all LOG levels */
        !            51: #define DEFAULT_ERR_LOG_LVL    LOG_WARNING
        !            52: 
        !            53: JSRuntime*     js_runtime;
        !            54: JSContext*     js_cx;
        !            55: JSObject*      js_glob;
        !            56: js_branch_t    branch;
        !            57: scfg_t         scfg;
        !            58: ulong          js_max_bytes=JAVASCRIPT_MAX_BYTES;
        !            59: ulong          js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
        !            60: ulong          stack_limit=JAVASCRIPT_THREAD_STACK;
        !            61: FILE*          confp;
        !            62: FILE*          errfp;
        !            63: FILE*          nulfp;
        !            64: FILE*          statfp;
        !            65: char           revision[16];
        !            66: char           compiler[32];
        !            67: char*          host_name=NULL;
        !            68: char           host_name_buf[128];
        !            69: BOOL           pause_on_exit=FALSE;
        !            70: BOOL           pause_on_error=FALSE;
        !            71: BOOL           terminated=FALSE;
        !            72: BOOL           recycled;
        !            73: int                    log_level=DEFAULT_LOG_LEVEL;
        !            74: int            err_level=DEFAULT_ERR_LOG_LVL;
        !            75: pthread_mutex_t output_mutex;
        !            76: #if defined(__unix__)
        !            77: BOOL           daemonize=FALSE;
        !            78: #endif
        !            79: 
        !            80: void banner(FILE* fp)
        !            81: {
        !            82:        fprintf(fp,"\nJSexec v%s%c-%s (rev %s)%s - "
        !            83:                "Execute Synchronet JavaScript Module\n"
        !            84:                ,VERSION,REVISION
        !            85:                ,PLATFORM_DESC
        !            86:                ,revision
        !            87: #ifdef _DEBUG
        !            88:                ," Debug"
        !            89: #else
        !            90:                ,""
        !            91: #endif
        !            92:                );
        !            93: 
        !            94:        fprintf(fp, "Compiled %s %s with %s\n"
        !            95:                ,__DATE__, __TIME__, compiler);
        !            96: }
        !            97: 
        !            98: void usage(FILE* fp)
        !            99: {
        !           100:        banner(fp);
        !           101: 
        !           102:        fprintf(fp,"\nusage: jsexec [-opts] [path]module[.js] [args]\n"
        !           103:                "\navailable opts:\n\n"
        !           104:                "\t-c<ctrl_dir>   specify path to Synchronet CTRL directory\n"
        !           105: #if defined(__unix__)
        !           106:                "\t-d             run in background (daemonize)\n"
        !           107: #endif
        !           108:                "\t-m<bytes>      set maximum heap size (default=%u bytes)\n"
        !           109:                "\t-s<bytes>      set context stack size (default=%u bytes)\n"
        !           110:                "\t-S<bytes>      set thread stack limit (default=%u, 0=unlimited)\n"
        !           111:                "\t-b<limit>      set branch limit (default=%u, 0=unlimited)\n"
        !           112:                "\t-y<interval>   set yield interval (default=%u, 0=never)\n"
        !           113:                "\t-g<interval>   set garbage collection interval (default=%u, 0=never)\n"
        !           114:                "\t-h[hostname]   use local or specified host name (instead of SCFG value)\n"
        !           115:                "\t-L<level>      set log level (default=%u)\n"
        !           116:                "\t-E<level>      set error log level threshold (default=%d)\n"
        !           117:                "\t-f             use non-buffered stream for console messages\n"
        !           118:                "\t-a             append instead of overwriting message output files\n"
        !           119:                "\t-e<filename>   send error messages to file in addition to stderr\n"
        !           120:                "\t-o<filename>   send console messages to file instead of stdout\n"
        !           121:                "\t-n             send status messages to %s instead of stderr\n"
        !           122:                "\t-q             send console messages to %s instead of stdout\n"
        !           123:                "\t-v             display version details and exit\n"
        !           124:                "\t-x             disable auto-termination on local abort signal\n"
        !           125:                "\t-l             loop until intentionally terminated\n"
        !           126:                "\t-p             wait for keypress (pause) on exit\n"
        !           127:                "\t-!             wait for keypress (pause) on error\n"
        !           128:                ,JAVASCRIPT_MAX_BYTES
        !           129:                ,JAVASCRIPT_CONTEXT_STACK
        !           130:                ,JAVASCRIPT_THREAD_STACK
        !           131:                ,JAVASCRIPT_BRANCH_LIMIT
        !           132:                ,JAVASCRIPT_YIELD_INTERVAL
        !           133:                ,JAVASCRIPT_GC_INTERVAL
        !           134:                ,DEFAULT_LOG_LEVEL
        !           135:                ,DEFAULT_ERR_LOG_LVL
        !           136:                ,_PATH_DEVNULL
        !           137:                ,_PATH_DEVNULL
        !           138:                );
        !           139: }
        !           140: 
        !           141: int mfprintf(FILE* fp, char *fmt, ...)
        !           142: {
        !           143:        va_list argptr;
        !           144:        char sbuf[1024];
        !           145:        int ret=0;
        !           146: 
        !           147:     va_start(argptr,fmt);
        !           148:     ret=vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
        !           149:        sbuf[sizeof(sbuf)-1]=0;
        !           150:     va_end(argptr);
        !           151: 
        !           152:        /* Mutex-protect stdout/stderr */
        !           153:        pthread_mutex_lock(&output_mutex);
        !           154: 
        !           155:        ret = fprintf(fp, "%s\n", sbuf);
        !           156: 
        !           157:        pthread_mutex_unlock(&output_mutex);
        !           158:     return(ret);
        !           159: }
        !           160: 
        !           161: /* Log printf */
        !           162: int lprintf(int level, char *fmt, ...)
        !           163: {
        !           164:        va_list argptr;
        !           165:        char sbuf[1024];
        !           166:        int ret=0;
        !           167: 
        !           168:        if(level > log_level)
        !           169:                return(0);
        !           170: 
        !           171:     va_start(argptr,fmt);
        !           172:     ret=vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
        !           173:        sbuf[sizeof(sbuf)-1]=0;
        !           174:     va_end(argptr);
        !           175: #if defined(__unix__)
        !           176:        if(daemonize) {
        !           177:                syslog(level,"%s",sbuf);
        !           178:                return(ret);
        !           179:        }
        !           180: #endif
        !           181: 
        !           182:        /* Mutex-protect stdout/stderr */
        !           183:        pthread_mutex_lock(&output_mutex);
        !           184: 
        !           185:        if(level<=err_level) {
        !           186:                ret=fprintf(errfp,"%s\n",sbuf);
        !           187:                if(errfp!=stderr && confp!=stdout)
        !           188:                        ret=fprintf(statfp,"%s\n",sbuf);
        !           189:        }
        !           190:        if(level>err_level || errfp!=stderr)
        !           191:                ret=fprintf(confp,"%s\n",sbuf);
        !           192: 
        !           193:        pthread_mutex_unlock(&output_mutex);
        !           194:     return(ret);
        !           195: }
        !           196: 
        !           197: #if defined(__unix__) && defined(NEEDS_DAEMON)
        !           198: /****************************************************************************/
        !           199: /* Daemonizes the process                                                   */
        !           200: /****************************************************************************/
        !           201: int
        !           202: daemon(int nochdir, int noclose)
        !           203: {
        !           204:     int fd;
        !           205: 
        !           206:     switch (fork()) {
        !           207:     case -1:
        !           208:         return (-1);
        !           209:     case 0:
        !           210:         break;
        !           211:     default:
        !           212:         _exit(0);
        !           213:     }
        !           214: 
        !           215:     if (setsid() == -1)
        !           216:         return (-1);
        !           217: 
        !           218:     if (!nochdir)
        !           219:         (void)chdir("/");
        !           220: 
        !           221:     if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
        !           222:         (void)dup2(fd, STDIN_FILENO);
        !           223:         (void)dup2(fd, STDOUT_FILENO);
        !           224:         (void)dup2(fd, STDERR_FILENO);
        !           225:         if (fd > 2)
        !           226:             (void)close(fd);
        !           227:     }
        !           228:     return (0);
        !           229: }
        !           230: #endif
        !           231: 
        !           232: #if defined(_WINSOCKAPI_)
        !           233: 
        !           234: WSADATA WSAData;
        !           235: #define SOCKLIB_DESC WSAData.szDescription
        !           236: static BOOL WSAInitialized=FALSE;
        !           237: 
        !           238: static BOOL winsock_startup(void)
        !           239: {
        !           240:        int             status;             /* Status Code */
        !           241: 
        !           242:     if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0) {
        !           243: /*             fprintf(statfp,"%s %s\n",WSAData.szDescription, WSAData.szSystemStatus); */
        !           244:                WSAInitialized=TRUE;
        !           245:                return(TRUE);
        !           246:        }
        !           247: 
        !           248:     lprintf(LOG_ERR,"!WinSock startup ERROR %d", status);
        !           249:        return(FALSE);
        !           250: }
        !           251: 
        !           252: #else /* No WINSOCK */
        !           253: 
        !           254: #define winsock_startup()      (TRUE)
        !           255: #define SOCKLIB_DESC NULL
        !           256: 
        !           257: #endif
        !           258: 
        !           259: void bail(int code)
        !           260: {
        !           261: 
        !           262: #if defined(_WINSOCKAPI_)
        !           263:        if(WSAInitialized && WSACleanup()!=0) 
        !           264:                lprintf(LOG_ERR,"!WSACleanup ERROR %d",ERROR_VALUE);
        !           265: #endif
        !           266: 
        !           267:        if(pause_on_exit || (code && pause_on_error)) {
        !           268:                fprintf(statfp,"\nHit enter to continue...");
        !           269:                getchar();
        !           270:        }
        !           271: 
        !           272:        if(code)
        !           273:                fprintf(statfp,"\nReturning error code: %d\n",code);
        !           274:        exit(code);
        !           275: }
        !           276: 
        !           277: static JSBool
        !           278: js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           279: {
        !           280:     uintN              i=0;
        !           281:        int32           level=LOG_INFO;
        !           282:     JSString*  str=NULL;
        !           283: 
        !           284:        if(argc > 1 && JSVAL_IS_NUMBER(argv[i]))
        !           285:                JS_ValueToInt32(cx,argv[i++],&level);
        !           286: 
        !           287:        for(; i<argc; i++) {
        !           288:                if((str=JS_ValueToString(cx, argv[i]))==NULL)
        !           289:                        return(JS_FALSE);
        !           290:                lprintf(level,"%s",JS_GetStringBytes(str));
        !           291:        }
        !           292: 
        !           293:        if(str==NULL)
        !           294:                *rval = JSVAL_VOID;
        !           295:        else
        !           296:                *rval = STRING_TO_JSVAL(str);
        !           297: 
        !           298:     return(JS_TRUE);
        !           299: }
        !           300: 
        !           301: static JSBool
        !           302: js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           303: {
        !           304:        char*   buf;
        !           305:        int             rd;
        !           306:        int32   len=128;
        !           307: 
        !           308:        if(argc)
        !           309:                JS_ValueToInt32(cx,argv[0],&len);
        !           310:        if((buf=alloca(len))==NULL)
        !           311:                return(JS_TRUE);
        !           312: 
        !           313:        rd=fread(buf,sizeof(char),len,stdin);
        !           314: 
        !           315:        if(rd>=0)
        !           316:                *rval = STRING_TO_JSVAL(JS_NewStringCopyN(cx,buf,rd));
        !           317: 
        !           318:     return(JS_TRUE);
        !           319: }
        !           320: 
        !           321: static JSBool
        !           322: js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           323: {
        !           324:        char*   buf;
        !           325:        char*   p;
        !           326:        int32   len=128;
        !           327: 
        !           328:        if(argc)
        !           329:                JS_ValueToInt32(cx,argv[0],&len);
        !           330:        if((buf=alloca(len+1))==NULL)
        !           331:                return(JS_TRUE);
        !           332: 
        !           333:        p=fgets(buf,len+1,stdin);
        !           334: 
        !           335:        if(p!=NULL)
        !           336:                *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,truncnl(p)));
        !           337: 
        !           338:     return(JS_TRUE);
        !           339: }
        !           340: 
        !           341: 
        !           342: static JSBool
        !           343: js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           344: {
        !           345:     uintN              i;
        !           346:     JSString*  str=NULL;
        !           347: 
        !           348:     for (i = 0; i < argc; i++) {
        !           349:                if((str=JS_ValueToString(cx, argv[i]))==NULL)
        !           350:                    return(JS_FALSE);
        !           351:                fprintf(confp,"%s",JS_GetStringBytes(str));
        !           352:        }
        !           353: 
        !           354:        if(str==NULL)
        !           355:                *rval = JSVAL_VOID;
        !           356:        else
        !           357:                *rval = STRING_TO_JSVAL(str);
        !           358:     return(JS_TRUE);
        !           359: }
        !           360: 
        !           361: static JSBool
        !           362: js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           363: {
        !           364:        if(!js_write(cx,obj,argc,argv,rval))
        !           365:                return(JS_FALSE);
        !           366: 
        !           367:        fprintf(confp,"\n");
        !           368:     return(JS_TRUE);
        !           369: }
        !           370: 
        !           371: static JSBool
        !           372: js_printf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           373: {
        !           374:        char* p;
        !           375: 
        !           376:        if((p = js_sprintf(cx, 0, argc, argv))==NULL) {
        !           377:                JS_ReportError(cx,"js_sprintf failed");
        !           378:                return(JS_FALSE);
        !           379:        }
        !           380: 
        !           381:        fprintf(confp,"%s",p);
        !           382: 
        !           383:        *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, p));
        !           384: 
        !           385:        js_sprintf_free(p);
        !           386: 
        !           387:     return(JS_TRUE);
        !           388: }
        !           389: 
        !           390: static JSBool
        !           391: js_alert(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           392: {
        !           393:     JSString * str;
        !           394: 
        !           395:        if((str=JS_ValueToString(cx, argv[0]))==NULL)
        !           396:            return(JS_FALSE);
        !           397: 
        !           398:        fprintf(confp,"!%s\n",JS_GetStringBytes(str));
        !           399: 
        !           400:        *rval = argv[0];
        !           401: 
        !           402:     return(JS_TRUE);
        !           403: }
        !           404: 
        !           405: static JSBool
        !           406: js_confirm(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           407: {
        !           408:     JSString * str;
        !           409: 
        !           410:        if((str=JS_ValueToString(cx, argv[0]))==NULL)
        !           411:            return(JS_FALSE);
        !           412: 
        !           413:        printf("%s (Y/N)?", JS_GetStringBytes(str));
        !           414: 
        !           415:        *rval = BOOLEAN_TO_JSVAL(FALSE);
        !           416:        return(JS_TRUE);
        !           417: }
        !           418: 
        !           419: static JSBool
        !           420: js_prompt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           421: {
        !           422:        char            instr[81];
        !           423:     JSString * prompt;
        !           424:     JSString * str;
        !           425: 
        !           426:        if(!JSVAL_IS_VOID(argv[0])) {
        !           427:                if((prompt=JS_ValueToString(cx, argv[0]))==NULL)
        !           428:                        return(JS_FALSE);
        !           429:                fprintf(confp,"%s: ",JS_GetStringBytes(prompt));
        !           430:        }
        !           431: 
        !           432:        if(argc>1) {
        !           433:                if((str=JS_ValueToString(cx, argv[1]))==NULL)
        !           434:                    return(JS_FALSE);
        !           435:                SAFECOPY(instr,JS_GetStringBytes(str));
        !           436:        } else
        !           437:                instr[0]=0;
        !           438: 
        !           439:        if(!fgets(instr,sizeof(instr),stdin))
        !           440:                return(JS_TRUE);
        !           441: 
        !           442:        if((str=JS_NewStringCopyZ(cx, truncnl(instr)))==NULL)
        !           443:            return(JS_FALSE);
        !           444: 
        !           445:        *rval = STRING_TO_JSVAL(str);
        !           446:     return(JS_TRUE);
        !           447: }
        !           448: 
        !           449: static JSBool
        !           450: js_chdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           451: {
        !           452:        char*           p;
        !           453: 
        !           454:        if((p=JS_GetStringBytes(JS_ValueToString(cx, argv[0])))==NULL) {
        !           455:                *rval = INT_TO_JSVAL(-1);
        !           456:                return(JS_TRUE);
        !           457:        }
        !           458: 
        !           459:        *rval = BOOLEAN_TO_JSVAL(chdir(p)==0);
        !           460:        return(JS_TRUE);
        !           461: }
        !           462: 
        !           463: static JSBool
        !           464: js_putenv(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           465: {
        !           466:        char*           p;
        !           467: 
        !           468:        if((p=JS_GetStringBytes(JS_ValueToString(cx, argv[0])))==NULL) {
        !           469:                *rval = INT_TO_JSVAL(-1);
        !           470:                return(JS_TRUE);
        !           471:        }
        !           472: 
        !           473:        *rval = BOOLEAN_TO_JSVAL(putenv(p)==0);
        !           474:        return(JS_TRUE);
        !           475: }
        !           476: 
        !           477: static jsSyncMethodSpec js_global_functions[] = {
        !           478:        {"log",                         js_log,                         1},
        !           479:        {"read",                        js_read,            1},
        !           480:        {"readln",                      js_readln,          1},
        !           481:     {"write",           js_write,           0},
        !           482:     {"writeln",         js_writeln,         0},
        !           483:     {"print",           js_writeln,         0},
        !           484:     {"printf",          js_printf,          1},        
        !           485:        {"alert",                       js_alert,                       1},
        !           486:        {"prompt",                      js_prompt,                      1},
        !           487:        {"confirm",                     js_confirm,                     1},
        !           488:        {"chdir",                       js_chdir,                       1},
        !           489:        {"putenv",                      js_putenv,                      1},
        !           490:     {0}
        !           491: };
        !           492: 
        !           493: static void
        !           494: js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
        !           495: {
        !           496:        char    line[64];
        !           497:        char    file[MAX_PATH+1];
        !           498:        const char*     warning;
        !           499: 
        !           500:        if(report==NULL) {
        !           501:                lprintf(LOG_ERR,"!JavaScript: %s", message);
        !           502:                return;
        !           503:     }
        !           504: 
        !           505:        if(report->filename)
        !           506:                sprintf(file," %s",report->filename);
        !           507:        else
        !           508:                file[0]=0;
        !           509: 
        !           510:        if(report->lineno)
        !           511:                sprintf(line," line %d",report->lineno);
        !           512:        else
        !           513:                line[0]=0;
        !           514: 
        !           515:        if(JSREPORT_IS_WARNING(report->flags)) {
        !           516:                if(JSREPORT_IS_STRICT(report->flags))
        !           517:                        warning="strict warning";
        !           518:                else
        !           519:                        warning="warning";
        !           520:        } else
        !           521:                warning="";
        !           522: 
        !           523:        lprintf(LOG_ERR,"!JavaScript %s%s%s: %s",warning,file,line,message);
        !           524: }
        !           525: 
        !           526: static JSBool
        !           527: js_BranchCallback(JSContext *cx, JSScript *script)
        !           528: {
        !           529:     return(js_CommonBranchCallback(cx,&branch));
        !           530: }
        !           531: 
        !           532: static BOOL js_CreateEnvObject(JSContext* cx, JSObject* glob, char** env)
        !           533: {
        !           534:        char            name[256];
        !           535:        char*           val;
        !           536:        uint            i;
        !           537:        JSObject*       js_env;
        !           538: 
        !           539:        if((js_env=JS_NewObject(js_cx, NULL, NULL, glob))==NULL)
        !           540:                return(FALSE);
        !           541: 
        !           542:        if(!JS_DefineProperty(cx, glob, "env", OBJECT_TO_JSVAL(js_env)
        !           543:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
        !           544:                return(FALSE);
        !           545: 
        !           546:        for(i=0;env[i]!=NULL;i++) {
        !           547:                SAFECOPY(name,env[i]);
        !           548:                truncstr(name,"=");
        !           549:                val=strchr(env[i],'=');
        !           550:                if(val==NULL)
        !           551:                        val="";
        !           552:                else
        !           553:                        val++;
        !           554:                if(!JS_DefineProperty(cx, js_env, name, STRING_TO_JSVAL(JS_NewStringCopyZ(cx,val))
        !           555:                        ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
        !           556:                        return(FALSE);
        !           557:        }
        !           558: 
        !           559:        return(TRUE);
        !           560: }
        !           561: 
        !           562: static BOOL js_init(char** environ)
        !           563: {
        !           564:        fprintf(statfp,"%s\n",(char *)JS_GetImplementationVersion());
        !           565: 
        !           566:        fprintf(statfp,"JavaScript: Creating runtime: %lu bytes\n"
        !           567:                ,js_max_bytes);
        !           568: 
        !           569:        if((js_runtime = JS_NewRuntime(js_max_bytes))==NULL)
        !           570:                return(FALSE);
        !           571: 
        !           572:        fprintf(statfp,"JavaScript: Initializing context (stack: %lu bytes)\n"
        !           573:                ,js_cx_stack);
        !           574: 
        !           575:     if((js_cx = JS_NewContext(js_runtime, js_cx_stack))==NULL)
        !           576:                return(FALSE);
        !           577: 
        !           578:        if(stack_limit)
        !           579:                fprintf(statfp,"JavaScript: Thread stack limit: %lu bytes\n"
        !           580:                        ,stack_limit);
        !           581: 
        !           582:        JS_SetErrorReporter(js_cx, js_ErrorReporter);
        !           583: 
        !           584:        /* Global Object */
        !           585:        if((js_glob=js_CreateCommonObjects(js_cx, &scfg, NULL, js_global_functions
        !           586:                ,time(NULL), host_name, SOCKLIB_DESC    /* system */
        !           587:                ,&branch                                                                /* js */
        !           588:                ,NULL,INVALID_SOCKET                                    /* client */
        !           589:                ,NULL                                                                   /* server */
        !           590:                ))==NULL)
        !           591:                return(FALSE);
        !           592: 
        !           593:        /* Environment Object (associative array) */
        !           594:        if(!js_CreateEnvObject(js_cx, js_glob, environ))
        !           595:                return(FALSE);
        !           596: 
        !           597:        if(js_CreateUifcObject(js_cx, js_glob)==NULL)
        !           598:                return(FALSE);
        !           599: 
        !           600:        return(TRUE);
        !           601: }
        !           602: 
        !           603: static const char* js_ext(const char* fname)
        !           604: {
        !           605:        if(strchr(fname,'.')==NULL)
        !           606:                return(".js");
        !           607:        return("");
        !           608: }
        !           609: 
        !           610: long js_exec(const char *fname, char** args)
        !           611: {
        !           612:        ulong           stack_frame;
        !           613:        int                     argc=0;
        !           614:        uint            line_no;
        !           615:        char            path[MAX_PATH+1];
        !           616:        char            line[1024];
        !           617:        char            rev_detail[256];
        !           618:        size_t          len;
        !           619:        char*           js_buf=NULL;
        !           620:        size_t          js_buflen;
        !           621:        JSScript*       js_script=NULL;
        !           622:        JSString*       arg;
        !           623:        JSObject*       argv;
        !           624:        FILE*           fp=stdin;
        !           625:        jsval           val;
        !           626:        jsval           rval=JSVAL_VOID;
        !           627:        int32           result=0;
        !           628:        long double     start;
        !           629:        long double     diff;
        !           630:        
        !           631:        if(fname!=NULL) {
        !           632:                if(strcspn(fname,"/\\")==strlen(fname)) {
        !           633:                        sprintf(path,"%s%s%s",scfg.mods_dir,fname,js_ext(fname));
        !           634:                        if(scfg.mods_dir[0]==0 || !fexistcase(path))
        !           635:                                sprintf(path,"%s%s%s",scfg.exec_dir,fname,js_ext(fname));
        !           636:                } else
        !           637:                        SAFECOPY(path,fname);
        !           638: 
        !           639:                if(!fexistcase(path)) {
        !           640:                        lprintf(LOG_ERR,"!Module file (%s) doesn't exist",path);
        !           641:                        return(-1); 
        !           642:                }
        !           643: 
        !           644:                if((fp=fopen(path,"r"))==NULL) {
        !           645:                        lprintf(LOG_ERR,"!Error %d (%s) opening %s",errno,STRERROR(errno),path);
        !           646:                        return(-1);
        !           647:                }
        !           648:        }
        !           649:        JS_ClearPendingException(js_cx);
        !           650: 
        !           651:        if(stack_limit) {
        !           652: #if JS_STACK_GROWTH_DIRECTION > 0
        !           653:                stack_frame=((ulong)&stack_frame)+stack_limit;
        !           654: #else
        !           655:                stack_frame=((ulong)&stack_frame)-stack_limit;
        !           656: #endif
        !           657:                JS_SetThreadStackLimit(js_cx, stack_frame);
        !           658:        }
        !           659: 
        !           660:        argv=JS_NewArrayObject(js_cx, 0, NULL);
        !           661:        JS_DefineProperty(js_cx, js_glob, "argv", OBJECT_TO_JSVAL(argv)
        !           662:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           663: 
        !           664:        for(argc=0;args[argc];argc++) {
        !           665:                arg = JS_NewStringCopyZ(js_cx, args[argc]);
        !           666:                if(arg==NULL)
        !           667:                        break;
        !           668:                val=STRING_TO_JSVAL(arg);
        !           669:                if(!JS_SetElement(js_cx, argv, argc, &val))
        !           670:                        break;
        !           671:        }
        !           672:        JS_DefineProperty(js_cx, js_glob, "argc", INT_TO_JSVAL(argc)
        !           673:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           674: 
        !           675:        JS_DefineProperty(js_cx, js_glob, "jsexec_revision"
        !           676:                ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,revision))
        !           677:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           678: 
        !           679:        sprintf(rev_detail,"JSexec %s%s  "
        !           680:                "Compiled %s %s with %s"
        !           681:                ,revision
        !           682: #ifdef _DEBUG
        !           683:                ," Debug"
        !           684: #else
        !           685:                ,""
        !           686: #endif
        !           687:                ,__DATE__, __TIME__, compiler
        !           688:                );
        !           689: 
        !           690:        JS_DefineProperty(js_cx, js_glob, "jsexec_revision_detail"
        !           691:                ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,rev_detail))
        !           692:                ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
        !           693: 
        !           694:        branch.terminated=&terminated;
        !           695: 
        !           696:        JS_SetBranchCallback(js_cx, js_BranchCallback);
        !           697: 
        !           698:        if(fp==stdin)    /* Using stdin for script source */
        !           699:                SAFECOPY(path,"stdin");
        !           700: 
        !           701:        fprintf(statfp,"Reading script from %s\n",path);
        !           702:        line_no=0;
        !           703:        js_buflen=0;
        !           704:        while(!feof(fp)) {
        !           705:                if(!fgets(line,sizeof(line),fp))
        !           706:                        break;
        !           707:                line_no++;
        !           708: #if defined(__unix__)  /* Support Unix Shell Scripts that start with #!/path/to/jsexec */
        !           709:                if(line_no==1 && strncmp(line,"#!",2)==0)
        !           710:                        strcpy(line,"\n");      /* To keep line count correct */
        !           711: #endif
        !           712:                len=strlen(line);
        !           713:                if((js_buf=realloc(js_buf,js_buflen+len))==NULL) {
        !           714:                        lprintf(LOG_ERR,"!Error allocating %u bytes of memory"
        !           715:                                ,js_buflen+len);
        !           716:                        return(-1);
        !           717:                }
        !           718:                memcpy(js_buf+js_buflen,line,len);
        !           719:                js_buflen+=len;
        !           720:        }
        !           721:        if(fp!=NULL && fp!=stdin)
        !           722:                fclose(fp);
        !           723: 
        !           724:        start=xp_timer();
        !           725:        if((js_script=JS_CompileScript(js_cx, js_glob, js_buf, js_buflen, fname==NULL ? NULL : path, 1))==NULL) {
        !           726:                lprintf(LOG_ERR,"!Error compiling script from %s",path);
        !           727:                return(-1);
        !           728:        }
        !           729:        if((diff=xp_timer()-start) > 0)
        !           730:                mfprintf(statfp,"%s compiled in %.2Lf seconds"
        !           731:                        ,path
        !           732:                        ,diff);
        !           733: 
        !           734:        start=xp_timer();
        !           735:        JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
        !           736:        js_EvalOnExit(js_cx, js_glob, &branch);
        !           737: 
        !           738:        if((diff=xp_timer()-start) > 0)
        !           739:                mfprintf(statfp,"%s executed in %.2Lf seconds"
        !           740:                        ,path
        !           741:                        ,diff);
        !           742: 
        !           743:        JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
        !           744: 
        !           745:        if(rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval)) {
        !           746:                mfprintf(statfp,"Using JavaScript exit_code: %s",JS_GetStringBytes(JS_ValueToString(js_cx,rval)));
        !           747:                JS_ValueToInt32(js_cx,rval,&result);
        !           748:        }
        !           749: 
        !           750:        JS_DestroyScript(js_cx, js_script);
        !           751: 
        !           752:        JS_GC(js_cx);
        !           753: 
        !           754:        if(js_buf!=NULL)
        !           755:                free(js_buf);
        !           756: 
        !           757:        return(result);
        !           758: }
        !           759: 
        !           760: void break_handler(int type)
        !           761: {
        !           762:        lprintf(LOG_NOTICE,"\n-> Terminated Locally (signal: %d)",type);
        !           763:        terminated=TRUE;
        !           764: }
        !           765: 
        !           766: void recycle_handler(int type)
        !           767: {
        !           768:        lprintf(LOG_NOTICE,"\n-> Recycled Locally (signal: %d)",type);
        !           769:        recycled=TRUE;
        !           770:        branch.terminated=&recycled;
        !           771: }
        !           772: 
        !           773: 
        !           774: #if defined(_WIN32)
        !           775: BOOL WINAPI ControlHandler(DWORD CtrlType)
        !           776: {
        !           777:        break_handler((int)CtrlType);
        !           778:        return TRUE;
        !           779: }
        !           780: #endif
        !           781: 
        !           782: /*********************/
        !           783: /* Entry point (duh) */
        !           784: /*********************/
        !           785: int main(int argc, char **argv, char** environ)
        !           786: {
        !           787:        char    error[512];
        !           788:        char*   module=NULL;
        !           789:        char*   p;
        !           790:        char*   omode="w";
        !           791:        int             argn;
        !           792:        long    result;
        !           793:        ulong   exec_count=0;
        !           794:        BOOL    loop=FALSE;
        !           795:        BOOL    nonbuffered_con=FALSE;
        !           796: 
        !           797:        confp=stdout;
        !           798:        errfp=stderr;
        !           799:        if((nulfp=fopen(_PATH_DEVNULL,"w+"))==NULL) {
        !           800:                perror(_PATH_DEVNULL);
        !           801:                bail(-1);
        !           802:        }
        !           803:        if(isatty(fileno(stderr)))
        !           804:                statfp=stderr;
        !           805:        else    /* if redirected, don't send status messages to stderr */
        !           806:                statfp=nulfp;
        !           807: 
        !           808:        branch.limit=JAVASCRIPT_BRANCH_LIMIT;
        !           809:        branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
        !           810:        branch.gc_interval=JAVASCRIPT_GC_INTERVAL;
        !           811:        branch.auto_terminate=TRUE;
        !           812: 
        !           813:        sscanf("$Revision: 1.109 $", "%*s %s", revision);
        !           814:        DESCRIBE_COMPILER(compiler);
        !           815: 
        !           816:        memset(&scfg,0,sizeof(scfg));
        !           817:        scfg.size=sizeof(scfg);
        !           818: 
        !           819:        if(!winsock_startup())
        !           820:                bail(2);
        !           821: 
        !           822:        for(argn=1;argn<argc && module==NULL;argn++) {
        !           823:                if(argv[argn][0]=='-') {
        !           824:                        p=argv[argn]+2;
        !           825:                        switch(argv[argn][1]) {
        !           826:                                case 'a':
        !           827:                                        omode="a";
        !           828:                                        break;
        !           829:                                case 'f':
        !           830:                                        nonbuffered_con=TRUE;
        !           831:                                        break;
        !           832:                                case 'm':
        !           833:                                        if(*p==0) p=argv[++argn];
        !           834:                                        js_max_bytes=strtoul(p,NULL,0);
        !           835:                                        break;
        !           836:                                case 's':
        !           837:                                        if(*p==0) p=argv[++argn];
        !           838:                                        js_cx_stack=strtoul(p,NULL,0);
        !           839:                                        break;
        !           840:                                case 'S':
        !           841:                                        if(*p==0) p=argv[++argn];
        !           842:                                        stack_limit=strtoul(p,NULL,0);
        !           843:                                        break;
        !           844:                                case 'b':
        !           845:                                        if(*p==0) p=argv[++argn];
        !           846:                                        branch.limit=strtoul(p,NULL,0);
        !           847:                                        break;
        !           848:                                case 'y':
        !           849:                                        if(*p==0) p=argv[++argn];
        !           850:                                        branch.yield_interval=strtoul(p,NULL,0);
        !           851:                                        break;
        !           852:                                case 'g':
        !           853:                                        if(*p==0) p=argv[++argn];
        !           854:                                        branch.gc_interval=strtoul(p,NULL,0);
        !           855:                                        break;
        !           856:                                case 'h':
        !           857:                                        if(*p==0)
        !           858:                                                gethostname(host_name=host_name_buf,sizeof(host_name_buf));
        !           859:                                        else
        !           860:                                                host_name=p;
        !           861:                                        break;
        !           862:                                case 'L':
        !           863:                                        if(*p==0) p=argv[++argn];
        !           864:                                        log_level=strtol(p,NULL,0);
        !           865:                                        break;
        !           866:                                case 'E':
        !           867:                                        if(*p==0) p=argv[++argn];
        !           868:                                        err_level=strtol(p,NULL,0);
        !           869:                                        break;
        !           870:                                case 'e':
        !           871:                                        if(*p==0) p=argv[++argn];
        !           872:                                        if((errfp=fopen(p,omode))==NULL) {
        !           873:                                                perror(p);
        !           874:                                                bail(1);
        !           875:                                        }
        !           876:                                        break;
        !           877:                                case 'o':
        !           878:                                        if(*p==0) p=argv[++argn];
        !           879:                                        if((confp=fopen(p,omode))==NULL) {
        !           880:                                                perror(p);
        !           881:                                                bail(1);
        !           882:                                        }
        !           883:                                        break;
        !           884:                                case 'q':
        !           885:                                        confp=nulfp;
        !           886:                                        break;
        !           887:                                case 'n':
        !           888:                                        statfp=nulfp;
        !           889:                                        break;
        !           890:                                case 'x':
        !           891:                                        branch.auto_terminate=FALSE;
        !           892:                                        break;
        !           893:                                case 'l':
        !           894:                                        loop=TRUE;
        !           895:                                        break;
        !           896:                                case 'p':
        !           897:                                        pause_on_exit=TRUE;
        !           898:                                        break;
        !           899:                                case '!':
        !           900:                                        pause_on_error=TRUE;
        !           901:                                        break;
        !           902:                                case 'c':
        !           903:                                        if(*p==0) p=argv[++argn];
        !           904:                                        SAFECOPY(scfg.ctrl_dir,p);
        !           905:                                        break;
        !           906:                                case 'v':
        !           907:                                        banner(statfp);
        !           908:                                        fprintf(statfp,"%s\n",(char *)JS_GetImplementationVersion());
        !           909:                                        bail(0);
        !           910: #if defined(__unix__)
        !           911:                                case 'd':
        !           912:                                        daemonize=TRUE;
        !           913:                                        break;
        !           914: #endif
        !           915:                                default:
        !           916:                                        fprintf(errfp,"\n!Unsupported option: %s\n",argv[argn]);
        !           917:                                case '?':
        !           918:                                        usage(errfp);
        !           919:                                        bail(1);
        !           920:                        }
        !           921:                        continue;
        !           922:                }
        !           923:                module=argv[argn];
        !           924:        }
        !           925: 
        !           926:        if(scfg.ctrl_dir[0]==0) {
        !           927:                if((p=getenv("SBBSCTRL"))==NULL) {
        !           928:                        fprintf(errfp,"\nSBBSCTRL environment variable not set and -c option not specified.\n");
        !           929:                        fprintf(errfp,"\nExample: SET SBBSCTRL=/sbbs/ctrl\n");
        !           930:                        fprintf(errfp,"\n     or: %s -c /sbbs/ctrl [module]\n",argv[0]);
        !           931:                        bail(1)        !           932:                }
        !           933:                SAFECOPY(scfg.ctrl_dir,p);
        !           934:        }       
        !           935: 
        !           936:        if(module==NULL && isatty(fileno(stdin))) {
        !           937:                fprintf(errfp,"\n!Module name not specified\n");
        !           938:                usage(errfp);
        !           939:                bail(1)        !           940:        }
        !           941: 
        !           942:        banner(statfp);
        !           943: 
        !           944:        if(chdir(scfg.ctrl_dir)!=0)
        !           945:                fprintf(errfp,"!ERROR changing directory to: %s\n", scfg.ctrl_dir);
        !           946: 
        !           947:        fprintf(statfp,"\nLoading configuration files from %s\n",scfg.ctrl_dir);
        !           948:        if(!load_cfg(&scfg,NULL,TRUE,error)) {
        !           949:                fprintf(errfp,"!ERROR loading configuration files: %s\n",error);
        !           950:                bail(1);
        !           951:        }
        !           952:        SAFECOPY(scfg.temp_dir,"../temp");
        !           953:        prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
        !           954: 
        !           955:        if(host_name==NULL)
        !           956:                host_name=scfg.sys_inetaddr;
        !           957: 
        !           958:        if(!(scfg.sys_misc&SM_LOCAL_TZ))
        !           959:                putenv("TZ=UTC0");
        !           960: 
        !           961: #if defined(__unix__)
        !           962:        if(daemonize) {
        !           963:                fprintf(statfp,"\nRunning as daemon\n");
        !           964:                if(daemon(TRUE,FALSE))  { /* Daemonize, DON'T switch to / and DO close descriptors */
        !           965:                        fprintf(statfp,"!ERROR %d running as daemon\n",errno);
        !           966:                        daemonize=FALSE;
        !           967:                }
        !           968:        }
        !           969: #endif
        !           970: 
        !           971:        /* Don't cache error log */
        !           972:        setvbuf(errfp,NULL,_IONBF,0);
        !           973: 
        !           974:        if(nonbuffered_con)
        !           975:                setvbuf(confp,NULL,_IONBF,0);
        !           976: 
        !           977:        /* Seed random number generator */
        !           978:        sbbs_srand();
        !           979: 
        !           980:        /* Install Ctrl-C/Break signal handler here */
        !           981: #if defined(_WIN32)
        !           982:        SetConsoleCtrlHandler(ControlHandler, TRUE /* Add */);
        !           983: #elif defined(__unix__)
        !           984:        signal(SIGQUIT,break_handler);
        !           985:        signal(SIGINT,break_handler);
        !           986:        signal(SIGTERM,break_handler);
        !           987: 
        !           988:        signal(SIGHUP,recycle_handler);
        !           989: 
        !           990:        /* Don't die on SIGPIPE  */
        !           991:        signal(SIGPIPE,SIG_IGN);
        !           992: #endif
        !           993: 
        !           994:        pthread_mutex_init(&output_mutex,NULL);
        !           995: 
        !           996:        do {
        !           997: 
        !           998:                if(exec_count++)
        !           999:                        lprintf(LOG_INFO,"\nRe-running: %s", module);
        !          1000: 
        !          1001:                recycled=FALSE;
        !          1002: 
        !          1003:                if(!js_init(environ)) {
        !          1004:                        lprintf(LOG_ERR,"!JavaScript initialization failure");
        !          1005:                        bail(1);
        !          1006:                }
        !          1007:                fprintf(statfp,"\n");
        !          1008: 
        !          1009:                result=js_exec(module,&argv[argn]);
        !          1010: 
        !          1011:                if(result)
        !          1012:                        lprintf(LOG_ERR,"!Module set exit_code: %ld", result);
        !          1013: 
        !          1014:                fprintf(statfp,"\n");
        !          1015:                fprintf(statfp,"JavaScript: Destroying context\n");
        !          1016:                JS_DestroyContext(js_cx);
        !          1017:                fprintf(statfp,"JavaScript: Destroying runtime\n");
        !          1018:                JS_DestroyRuntime(js_runtime);  
        !          1019: 
        !          1020:        } while((recycled || loop) && !terminated);
        !          1021: 
        !          1022:        bail(result);
        !          1023: 
        !          1024:        return(-1);     /* never gets here */
        !          1025: }
        !          1026: 

unix.superglobalmegacorp.com

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