Exemplo n.º 1
0
static int jsi_FSRenameProc(Jsi_Interp *interp, Jsi_Value *src, Jsi_Value *dest) {
    const char *zSrc = Jsi_ValueToString(interp, src, NULL);
    const char *zDest = Jsi_ValueToString(interp, dest, NULL);
    Jsi_DString dStr = {}, eStr = {};
    if (*zSrc == '~')
        zSrc = jsi_TildePath(interp, zSrc, &dStr);
    if (*zDest == '~')
        zDest = jsi_TildePath(interp, zDest, &eStr);
    int rc = rename(zSrc, zDest);
    Jsi_DSFree(&dStr);
    Jsi_DSFree(&eStr);
    return rc;
}
Exemplo n.º 2
0
static char *get_inputline(int istty, char *prompt)
{
    char *res;
#ifdef HAVE_READLINE
    if (istty) {
        res = readline(prompt);
        if (res && *res) add_history(res);
        return res;
    }
#endif
    int done = 0;
    char bbuf[BUFSIZ];
    Jsi_DString dStr = {};
    if (istty)
        fputs(prompt, stdout);
    fflush(stdout);
    while (!done) { /* Read a line. */
        bbuf[0] = 0;
        if (fgets(bbuf, sizeof(bbuf), stdin) == NULL)
            return NULL;
        Jsi_DSAppend(&dStr, bbuf, NULL);
        if (strlen(bbuf) < (sizeof(bbuf)-1) || bbuf[sizeof(bbuf)-1] == '\n')
            break;
    }
    res = strdup(Jsi_DSValue(&dStr));
    Jsi_DSFree(&dStr);
    return res;
}
Exemplo n.º 3
0
Jsi_Obj *jsi_UserObjFromName(Jsi_Interp *interp, const char *name)
{
    if (*name != '#')
        return NULL;
    char *cp = strrchr(name, '_');
    if (cp==0 || !*cp)
        return NULL;
    int id = atoi(cp+1);
    Jsi_DString dStr = {};
    Jsi_DSAppendLen(&dStr, name+1, cp-name-1);
    Jsi_HashEntry *hPtr = Jsi_HashEntryFind(interp->userdataTbl, Jsi_DSValue(&dStr));
    Jsi_DSFree(&dStr);

    UserObjReg *rdata = Jsi_HashValueGet(hPtr);
    if (!rdata)
        return NULL;
    Jsi_Hash *tPtr = rdata->hashPtr;
    if (tPtr==0)
        return NULL;

    hPtr = Jsi_HashEntryFind(tPtr, (void*)id);
    if (!hPtr)
        return NULL;
    return Jsi_HashValueGet(hPtr);
}
Exemplo n.º 4
0
static int JsiCleanupChildren(Jsi_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId, Jsi_DString *dStr, Jsi_DString *cStr, int *code)
{
    struct WaitInfoTable *table = jsi_ExecCmdData(interp);
    int result = JSI_OK;
    int i, exitCode = 256;
    char buf[1000];
    Jsi_DString sStr;
    Jsi_DSInit(&sStr);
    for (i = 0; i < numPids; i++) {
        int waitStatus = 0;
        if (cStr) {
            if (i==0)
                Jsi_DSAppend(cStr, (Jsi_DSLength(cStr)>1?", ":""), "children: [", NULL);
            else
                Jsi_DSAppend(&sStr, ", ", NULL);
        }
        if (JsiWaitForProcess(table, pidPtr[i], &waitStatus) != JSI_BAD_PID) {
            //  if (JsiCheckWaitStatus(interp, pidPtr[i], waitStatus, dStr?&sStr:0) != JSI_OK) 
            //result = JSI_ERROR;  // TODO: we don't error out on non-zero return code. Find way to return it.
            int es = WEXITSTATUS(waitStatus);
            if (WIFEXITED(waitStatus)) {
                if (i==0)
                    exitCode = es;
                else if (es>exitCode)
                    exitCode = es;
            }
            if (cStr) {
                pidtype pid = pidPtr[i];
                if (WIFEXITED(waitStatus))
                    sprintf(buf, "{type:\"exit\", pid:%ld, exitCode:%d}", (long)pid, es);
                else 
                    sprintf(buf, "{type:\"%s\", pid:%ld, signal: %d}",
                        (WIFSIGNALED(waitStatus) ? "killed" : "suspended"), (long)pid, WTERMSIG(waitStatus));
                Jsi_DSAppend(&sStr, buf, NULL);
            }
        }
    }
    if (i>0 && cStr) {
        if (exitCode != 256)
            sprintf(buf, ", exitCode: %d", exitCode);
        Jsi_DSAppend(cStr, Jsi_DSValue(&sStr), "]", buf, NULL);
    }
    Jsi_DSFree(&sStr);
    Jsi_Free(pidPtr);

    /*
     * Read the standard error file.  If there's anything there,
     * then add the file's contents to the result
     * string.
     */
    if (errorId != JSI_BAD_FD) {
        JsiRewindFd(errorId);
        if (JsiAppendStreamToString(interp, errorId, dStr) != JSI_OK) {
            result = JSI_ERROR;
        }
    }
    *code = exitCode;
    return result;
}
Exemplo n.º 5
0
static int FilePwdCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr)
{
    Jsi_DString dStr = {};
    Jsi_ValueMakeString(interp, *ret, Jsi_Strdup(Jsi_GetCwd(interp, &dStr)));
    Jsi_DSFree(&dStr);
    return JSI_OK;
}
Exemplo n.º 6
0
static int jsi_FSLinkProc(Jsi_Interp *interp, Jsi_Value* path, Jsi_Value *toPath, int linkType) {
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    const char *toPtr = Jsi_ValueToString(interp, toPath, NULL);
    Jsi_DString dStr = {}, eStr = {};
    int rc;
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    if (*toPtr == '~')
        toPtr = jsi_TildePath(interp, toPtr, &eStr);
    if (linkType != 0)
        rc = link(pathPtr, toPtr);
    else
        rc = symlink(pathPtr, toPtr);
    Jsi_DSFree(&dStr);
    Jsi_DSFree(&eStr);
    return rc;
}
Exemplo n.º 7
0
void Jsi_DString_SelfTest() {
    {
        Jsi_DString d1 = {}, d2 = {"Here is"};
        Jsi_DSAppend(&d2 ," your score: ", NULL);
        Jsi_DSPrintf(&d2, " -> %d/%d", 99, 100);
        char *cp = Jsi_DSValue(&d2);
        puts(cp);     // "Here is your score: -> 99/100"
        Jsi_DSAppend(&d1, cp, NULL);
        Jsi_DSFree(&d1);  Jsi_DSFree(&d2);
    }
    {
        Jsi_DString d = {};;
        Jsi_DSPrintf(&d , "%0300d", 1); // Malloc
        Jsi_DSSetLength(&d, 0);
        Jsi_DSPrintf(&d , "%0300d", 1); // No-malloc
        Jsi_DSFree(&d);
        Jsi_DSPrintf(&d , "%0300d", 1); // Malloc
        Jsi_DSFree(&d);
    }
    {
        Jsi_DString d;
        Jsi_DSInit(&d);
        Jsi_DSAppend(&d , " some stuff: ", NULL);
        Jsi_DSFree(&d);
    }
    {
        JSI_DSTRING_VAR(dPtr,301);
        Jsi_DSPrintf(dPtr , "%0300d", 1); // No-malloc
        Jsi_DSSetLength(dPtr, 0);
        Jsi_DSPrintf(dPtr , "%0300d", 1); // No-malloc
        Jsi_DSFree(dPtr);
        Jsi_DSPrintf(dPtr , "%0400d", 1); // Malloc
        Jsi_DSFree(dPtr);
    }
}
Exemplo n.º 8
0
static int jsi_FSStatProc(Jsi_Interp *interp, Jsi_Value* path, Jsi_StatBuf *buf) {
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    int rc = stat(pathPtr, buf);
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 9
0
static int jsi_FSRemoveProc(Jsi_Interp *interp, Jsi_Value* path, int flags) {
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    int rc = remove(pathPtr);
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 10
0
static int jsi_FSReadlinkProc(Jsi_Interp *interp, Jsi_Value *path, char *buf, int size) {
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    int rc = readlink(pathPtr, buf, size);
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 11
0
static int jsi_FSAccessProc(Jsi_Interp *interp, Jsi_Value* path, int mode) {
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    int rc = access(pathPtr, mode);
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 12
0
int jsi_FSScandirProc(Jsi_Interp *interp, Jsi_Value *path, Jsi_Dirent ***namelist,
   int (*filter)(const Jsi_Dirent *), int (*compar)(const Jsi_Dirent **, const Jsi_Dirent**))
{
    const char *dirname = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*dirname == '~')
        dirname = jsi_TildePath(interp, dirname, &dStr);
    int rc = scandir(dirname, namelist, filter, compar);
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 13
0
static int jsi_FSLstatProc(Jsi_Interp *interp, Jsi_Value* path, Jsi_StatBuf *buf) {
#ifdef __WIN32
    return jsi_FSStatProc(interp, path, buf);
#else
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    int rc = lstat(pathPtr, buf);
    Jsi_DSFree(&dStr);
    return rc;
#endif
}
Exemplo n.º 14
0
static int jsi_FSChmodProc(Jsi_Interp *interp, Jsi_Value* path, int mode) {
#ifdef __WIN32
    return -1;
#else
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);
    int rc = chmod(pathPtr, mode);
    Jsi_DSFree(&dStr);
    return rc;
#endif
}
Exemplo n.º 15
0
/* Simple implementation of exec with system().  Returns return code.
 * The system() call *may* do command line redirection, etc.
 * The standard output is not available.
 * Can't redirect filehandles.
 */
int Jsi_SysExecCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_DString *rStr)
{
    int i, j, len, rc = 0;
    Jsi_DString dStr, eStr;
    len = Jsi_ValueGetLength(interp, args);
    Jsi_DSInit(rStr);
    if (len<=0)
        return 0;
    Jsi_DSInit(&dStr);
#ifdef __WIN32
    Jsi_DSAppendLen(&dStr, "\"", 1);
#endif
    for (i=0; i<len; i++) {
        Jsi_Value *v = Jsi_ValueArrayIndex(interp, args, i);
        const char *arg = Jsi_ValueGetDString(interp, v, &eStr, 0);
        if (i>1)
        Jsi_DSAppendLen(&dStr, " ", 1);
        if (strpbrk(arg, "\\\" ") == NULL) {
            Jsi_DSAppend(&dStr, arg, NULL);
        } else {
            Jsi_DSAppendLen(&dStr, "\"", 1);
            for (j = 0; j < len; j++) {
                if (arg[j] == '\\' || arg[j] == '"') {
                    Jsi_DSAppendLen(&dStr, "\\", 1);
                }
                Jsi_DSAppendLen(&dStr, &arg[j], 1);
            }
            Jsi_DSAppendLen(&dStr, "\"", 1);
        }
        Jsi_DSFree(&eStr);

    }
#ifdef __WIN32
    Jsi_DSAppendLen(&dStr, "\"", 1);
#endif
    rc = system(Jsi_DSValue(&dStr));
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 16
0
static int jsi_FSCreateDirectoryProc(Jsi_Interp *interp, Jsi_Value* path) {
    const char *pathPtr = Jsi_ValueToString(interp, path, NULL);
    Jsi_DString dStr = {};
    int rc;
    if (*pathPtr == '~')
        pathPtr = jsi_TildePath(interp, pathPtr, &dStr);

#ifdef __WIN32
    rc = mkdir(pathPtr);
#else
    rc = mkdir(pathPtr, 0666);
#endif
    Jsi_DSFree(&dStr);
    return rc;
}
Exemplo n.º 17
0
void Jsi_Puts(Jsi_Interp* interp, Jsi_Value *v, int flags)
{
    int quote = (flags&JSI_OUTPUT_QUOTE);
    int iserr = (flags&JSI_OUTPUT_STDERR);
    Jsi_DString dStr = {};
    const char *cp = Jsi_ValueString(interp, v, 0);
    if (cp) {
        fprintf((iserr?stderr:stdout),"%s", cp);
        return;
    }
    Jsi_DSInit(&dStr);
    Jsi_ValueGetDString(interp, v, &dStr, quote);
    fprintf((iserr?stderr:stdout),"%s",Jsi_DSValue(&dStr));
    Jsi_DSFree(&dStr);
    return;
}
Exemplo n.º 18
0
/**
 * Apply the printf-like format in fmtObjPtr with the given arguments.
 *
 * Returns a new object with zero reference count if OK, or NULL on error.
 */
int Jsi_FormatString(Jsi_Interp *interp, Jsi_Value *args, Jsi_DString *dStr)
{
    const char *span, *format, *formatEnd, *msg;
    int numBytes = 0, argIndex = 1, gotXpg = 0, gotSequential = 0, argCnt;
    static const char * const mixedXPG =
        "cannot mix \"%\" and \"%n$\" conversion specifiers";
    static const char * const badIndex[2] = {
        "not enough arguments for all format specifiers",
        "\"%n$\" argument index out of range"
    };
    int formatLen;
    Jsi_Value *v;
    
    /* A single buffer is used to store numeric fields (with sprintf())
     * This buffer is allocated/reallocated as necessary
     */
    char stat_buf[100], *num_buffer = stat_buf;
    int num_buffer_size = sizeof(stat_buf);
    argCnt = Jsi_ValueGetLength(interp, args);

    if (argCnt<1) {
        msg = "missing format";
        goto errorMsg;
    }
    format = Jsi_ValueArrayIndexToStr(interp, args,0, &formatLen);
    
    span = format;
    formatEnd = format + formatLen;
    Jsi_DSInit(dStr);

    while (format != formatEnd) {
        char *end;
        int gotMinus, sawFlag;
        int gotPrecision, useShort, useLong;
        long width, precision;
        int newXpg;
        int ch;
        int step;
        int doubleType;
        char pad = ' ';
        char spec[2*JSI_INTEGER_SPACE + 12];
        char *p;

        int formatted_chars;
        int formatted_bytes;
        const char *formatted_buf = NULL;

        step = jsi_utf8_tounicode(format, &ch);
        format += step;
        if (ch != '%') {
            numBytes += step;
            continue;
        }
        if (numBytes) {
            Jsi_DSAppendLen(dStr, span, numBytes);
            numBytes = 0;
        }

        /*
         * Saw a % : process the format specifier.
         *
         * Step 0. Handle special case of escaped format marker (i.e., %%).
         */

        step = jsi_utf8_tounicode(format, &ch);
        if (ch == '%') {
            span = format;
            numBytes = step;
            format += step;
            continue;
        }

        /*
         * Step 1. XPG3 position specifier
         */

        newXpg = 0;
        if (isdigit(ch)) {
            int position = strtoul(format, &end, 10);
            if (*end == '$') {
                newXpg = 1;
                argIndex = position - 1;
                format = end + 1;
                step = jsi_utf8_tounicode(format, &ch);
            }
        }
        if (newXpg) {
            if (gotSequential) {
                msg = mixedXPG;
                goto errorMsg;
            }
            gotXpg = 1;
        } else {
            if (gotXpg) {
                msg = mixedXPG;
                goto errorMsg;
            }
            gotSequential = 1;
        }
        if ((argIndex < 0) || (argIndex >= argCnt)) {
            msg = badIndex[gotXpg];
            goto errorMsg;
        }

        /*
         * Step 2. Set of flags. Also build up the sprintf spec.
         */
        p = spec;
        *p++ = '%';

        gotMinus = 0;
        sawFlag = 1;
        do {
            switch (ch) {
            case '-':
                gotMinus = 1;
                break;
            case '0':
                pad = ch;
                break;
            case ' ':
            case '+':
            case '#':
                break;
            default:
                sawFlag = 0;
                continue;
            }
            *p++ = ch;
            format += step;
            step = jsi_utf8_tounicode(format, &ch);
        } while (sawFlag);

        /*
         * Step 3. Minimum field width.
         */

        width = 0;
        if (isdigit(ch)) {
            width = strtoul(format, &end, 10);
            format = end;
            step = jsi_utf8_tounicode(format, &ch);
        } else if (ch == '*') {
            if (argIndex >= argCnt - 1) {
                msg = badIndex[gotXpg];
                goto errorMsg;
            }
            v = Jsi_ValueArrayIndex(interp, args, argIndex);
            if (Jsi_GetLongFromValue(interp, v, &width) != JSI_OK) {
                goto error;
            }
            if (width < 0) {
                width = -width;
                if (!gotMinus) {
                    *p++ = '-';
                    gotMinus = 1;
                }
            }
            argIndex++;
            format += step;
            step = jsi_utf8_tounicode(format, &ch);
        }

        /*
         * Step 4. Precision.
         */

        gotPrecision = precision = 0;
        if (ch == '.') {
            gotPrecision = 1;
            format += step;
            step = jsi_utf8_tounicode(format, &ch);
        }
        if (isdigit(ch)) {
            precision = strtoul(format, &end, 10);
            format = end;
            step = jsi_utf8_tounicode(format, &ch);
        } else if (ch == '*') {
            if (argIndex >= argCnt - 1) {
                msg = badIndex[gotXpg];
                goto errorMsg;
            }
            v = Jsi_ValueArrayIndex(interp, args, argIndex);
            if (Jsi_GetLongFromValue(interp, v, &precision) != JSI_OK) {
                goto error;
            }

            /*
             * TODO: Check this truncation logic.
             */

            if (precision < 0) {
                precision = 0;
            }
            argIndex++;
            format += step;
            step = jsi_utf8_tounicode(format, &ch);
        }

        /*
         * Step 5. Length modifier.
         */

        useShort = 0;
        useLong = 0;
        if (ch == 'h') {
            useShort = 1;
            format += step;
            step = jsi_utf8_tounicode(format, &ch);
        } else if (ch == 'l') {
            useLong = 1;
            format += step;
            step = jsi_utf8_tounicode(format, &ch);
            if (ch == 'l') {
                format += step;
                step = jsi_utf8_tounicode(format, &ch);
            }
        }

        format += step;
        span = format;

        /*
         * Step 6. The actual conversion character.
         */

        if (ch == 'i') {
            ch = 'd';
        }

        doubleType = 0;

        /* Each valid conversion will set:
         * formatted_buf   - the result to be added
         * formatted_chars - the length of formatted_buf in characters
         * formatted_bytes - the length of formatted_buf in bytes
         */
        switch (ch) {
        case '\0':
            msg = "format string ended in middle of field specifier";
            goto errorMsg;
        case 's': {
            v = Jsi_ValueArrayIndex(interp, args, argIndex);
            if (Jsi_GetStringFromValue(interp, v, &formatted_buf) != JSI_OK)
                goto error;
            formatted_bytes = 
            formatted_chars = Jsi_Strlen(formatted_buf);
            if (gotPrecision && (precision < formatted_chars)) {
                /* Need to build a (null terminated) truncated string */
                formatted_chars = precision;
                formatted_bytes = jsi_utf8_index(formatted_buf, precision);
            }
            break;
        }
        case 'c': {
            Jsi_Wide code;

            v = Jsi_ValueArrayIndex(interp, args, argIndex);
            if (Jsi_GetWideFromValue(interp, v, &code) != JSI_OK) {
                goto error;
            }
            /* Just store the value in the 'spec' buffer */
            formatted_bytes = jsi_utf8_fromunicode(spec, code);
            formatted_buf = spec;
            formatted_chars = 1;
            break;
        }

        case 'e':
        case 'E':
        case 'f':
        case 'g':
        case 'G':
            doubleType = 1;
            /* fall through */
        case 'd':
        case 'u':
        case 'o':
        case 'x':
        case 'X': {
            Jsi_Wide w;
            Jsi_Number d;
            int length;

            /* Fill in the width and precision */
            if (width) {
                p += sprintf(p, "%ld", width);
            }
            if (gotPrecision) {
                p += sprintf(p, ".%ld", precision);
            }

            /* Now the modifier, and get the actual value here */
            if (doubleType) {
                v = Jsi_ValueArrayIndex(interp, args, argIndex);
                if (Jsi_GetDoubleFromValue(interp, v, &d) != JSI_OK) {
                    goto error;
                }
                length = MAX_FLOAT_WIDTH;
            }
            else {
                v = Jsi_ValueArrayIndex(interp, args, argIndex);
                if (Jsi_GetWideFromValue(interp, v, &w) != JSI_OK) {
                    goto error;
                }
                length = JSI_INTEGER_SPACE;
                if (useShort) {
                    *p++ = 'h';
                    if (ch == 'd') {
                        w = (short)w;
                    }
                    else {
                        w = (unsigned short)w;
                    }
                }
                else {
                    *p++ = 'l';
#ifdef HAVE_LONG_LONG
                    if (useLong && sizeof(long long) == sizeof(Jsi_Wide)) {
                        *p++ = 'l';
                    }
#endif
                }
            }

            *p++ = (char) ch;
            *p = '\0';

            /* Adjust length for width and precision */
            if (width > length) {
                length = width;
            }
            if (gotPrecision) {
                length += precision;
            }

            /* Increase the size of the buffer if needed */
            if (num_buffer_size < length + 1) {
                num_buffer_size = length + 1;
                num_buffer = Jsi_Realloc((num_buffer==stat_buf?NULL:num_buffer), num_buffer_size);
            }

            if (doubleType) {
                snprintf(num_buffer, length + 1, spec, d);
            }
            else {
                formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
            }
            formatted_chars = formatted_bytes = strlen(num_buffer);
            formatted_buf = num_buffer;
            break;
        }

        default: {
            /* Just reuse the 'spec' buffer */
            spec[0] = ch;
            spec[1] = '\0';
            Jsi_LogError("bad field specifier \"%s\"", spec);
            goto error;
        }
        }

        if (!gotMinus) {
            while (formatted_chars < width) {
                Jsi_DSAppendLen(dStr, &pad, 1);
                formatted_chars++;
            }
        }

        Jsi_DSAppendLen(dStr, formatted_buf, formatted_bytes);

        while (formatted_chars < width) {
            Jsi_DSAppendLen(dStr, &pad, 1);
            formatted_chars++;
        }

        argIndex += gotSequential;
    }
    if (numBytes) {
        Jsi_DSAppendLen(dStr, span, numBytes);
    }

    if (num_buffer!=stat_buf)
        Jsi_Free(num_buffer);
    return JSI_OK;

errorMsg:
    Jsi_LogError("%s", msg);
error:
    Jsi_DSFree(dStr);
    if (num_buffer!=stat_buf)
        Jsi_Free(num_buffer);
    return JSI_ERROR;
}
Exemplo n.º 19
0
int main(int argc, char **argv)
{
    int rc = JSI_OK, jsFound = 0;
    Jsi_Interp* interp = Jsi_InterpCreate(NULL, argc, argv, 0);
    Jsi_InterpOnDelete(interp, &InterpDelete);

#ifndef NO_JAZ
    /* Mount zip at end of executable */
    Jsi_Value *v = Jsi_Executable(interp);
    const char *exeFile = Jsi_ValueString(interp, v, NULL);
    if (argc != 2 || Jsi_Strcmp(argv[1], "--nozvfs")) {
        rc = Jsi_ExecZip(interp, exeFile, JSI_ZVFS_DIR, &jsFound);
        if (rc >= 0) {
            if (!jsFound) {
#if (!defined(JSI_OMIT_FILESYS)) && (!defined(JSI_OMIT_ZVFS))
                fprintf(stderr, "warning: no main.jsi or jsiIndex.jsi\n");
#endif
            }
            if (deleted)
                exit(exitCode);
            else if (rc != JSI_OK) {
                fprintf(stderr, "Error\n");
                exit(1);
            }
        }
    }
#endif

#ifdef USER_EXTENSION
    extern int USER_EXTENSION(Jsi_Interp *interp);
    if (USER_EXTENSION (interp) != JSI_OK) {
        fprintf(stderr, "extension load failed");
        exit(1);
    }
#endif
    Jsi_ShiftArgs(interp);
    if (argc == 1) {
        rc = Jsi_Interactive(interp, JSI_OUTPUT_QUOTE|JSI_OUTPUT_NEWLINES);
    } else {
        if (argc == 2 && (Jsi_Strcmp(argv[1], "--help")==0 || Jsi_Strcmp(argv[1], "-h" )==0)) {
            puts("usage: jsi ?--help | -e SCRIPT | FILE arg arg ...?");
            exit(0);
        }
        if (argc == 2 && (Jsi_Strcmp(argv[1], "--version")==0 || Jsi_Strcmp(argv[1], "-v" )==0)) {
            char str[200] = "\n";
            Jsi_Channel chan = Jsi_Open(interp, Jsi_ValueNewStringKey(interp, "/zvfs/lib/sourceid.txt"), "r");
            if (chan)
                Jsi_Read(chan, str, sizeof(str));
            printf("%d.%d.%d (%" JSI_NUMGFMT ") %s", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE, Jsi_Version(), str);
            exit(0);
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--invoke")==0 || Jsi_Strcmp(argv[1], "-i" )==0)) {
            Jsi_DString dStr = {};
            Jsi_DSAppend(&dStr, "jsi_invokeCmd(\"", argv[2], "\",console.args.slice(1));", NULL);
            rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
            Jsi_DSFree(&dStr);
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);
        else {
            Jsi_Value *vf = NULL;
            const char *ext = strrchr(argv[1], '.');
            /* Support running "main.jsi" from a zip file. */
            if (ext && (strcmp(ext,".zip")==0 ||strcmp(ext,".jsz")==0 ) ) {
                rc = Jsi_ExecZip(interp, argv[1], NULL, &jsFound);
                if (rc<0) {
                    fprintf(stderr, "zip mount failed\n");
                    exit(1);
                }
                if (!(jsFound&JSI_ZIP_MAIN)) {
                    fprintf(stderr, "main.jsi not found\n");
                    exit(1);
                }
            } else {
                if (argc>1)
                    vf = Jsi_ValueNewStringKey(interp, argv[1]);
                rc = Jsi_EvalFile(interp, vf, JSI_EVAL_ARGV0|JSI_EVAL_INDEX);
            }
        }
        if (deleted)
            exit(exitCode);
        if (rc == 0) {
            /* Skip output from an ending semicolon which evaluates to undefined */
            Jsi_Value *ret = Jsi_ReturnValue(interp);
            if (!Jsi_ValueIsType(interp, ret, JSI_VT_UNDEF)) {
                Jsi_DString dStr = {};
                fputs(Jsi_ValueGetDString(interp, ret, &dStr, 0), stdout);
                Jsi_DSFree(&dStr);
                fputs("\n", stdout);
            }
        } else
            fputs("ERROR\n", stderr);

    }
    if (!deleted)
        Jsi_InterpDelete(interp);
    return rc;
}
Exemplo n.º 20
0
static pidtype
JsiStartWinProcess(Jsi_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
{
    STARTUPINFO startInfo;
    PROCESS_INFORMATION procInfo;
    HANDLE hProcess, h;
    char execPath[MAX_PATH];
    char *originalName;
    pidtype pid = JSI_BAD_PID;
    char *cmdLineStr;

    if (JsiWinFindExecutable(argv[0], execPath) < 0) {
        return JSI_BAD_PID;
    }
    originalName = argv[0];
    argv[0] = execPath;

    hProcess = GetCurrentProcess();
    Jsi_DString dStr;
    cmdLineStr = JsiWinBuildCommandLine(interp, argv, &dStr);

    /*
     * STARTF_USESTDHANDLES must be used to pass handles to child process.
     * Using SetStdHandle() and/or dup2() only works when a console mode
     * parent process is spawning an attached console mode child process.
     */

    ZeroMemory(&startInfo, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);
    startInfo.dwFlags   = STARTF_USESTDHANDLES;
    startInfo.hStdInput = INVALID_HANDLE_VALUE;
    startInfo.hStdOutput= INVALID_HANDLE_VALUE;
    startInfo.hStdError = INVALID_HANDLE_VALUE;

    /*
     * Duplicate all the handles which will be passed off as stdin, stdout
     * and stderr of the child process. The duplicate handles are set to
     * be inheritable, so the child process can use them.
     */
    if (inputId == JSI_BAD_FD) {
        if (CreatePipe(&startInfo.hStdInput, &h, JsiStdSecAttrs(), 0) != FALSE) {
            CloseHandle(h);
        }
    } else {
        DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput,
                0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdInput == JSI_BAD_FD) {
        goto end;
    }

    if (outputId == JSI_BAD_FD) {
        startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,
                JsiStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    } else {
        DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput,
                0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdOutput == JSI_BAD_FD) {
        goto end;
    }

    if (errorId == JSI_BAD_FD) {
        /*
         * If handle was not set, errors should be sent to an infinitely
         * deep sink.
         */

        startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,
                JsiStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    } else {
        DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError,
                0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdError == JSI_BAD_FD) {
        goto end;
    }

    if (!CreateProcess(NULL, cmdLineStr, NULL, NULL, TRUE,
            0, env, NULL, &startInfo, &procInfo)) {
        goto end;
    }

    /*
     * "When an application spawns a process repeatedly, a new thread
     * instance will be created for each process but the previous
     * instances may not be cleaned up.  This results in a significant
     * virtual memory loss each time the process is spawned.  If there
     * is a WaitForInputIdle() call between CreateProcess() and
     * CloseHandle(), the problem does not occur." PSS ID Number: Q124121
     */

    WaitForInputIdle(procInfo.hProcess, 5000);
    CloseHandle(procInfo.hThread);

    pid = procInfo.hProcess;

    end:
    Jsi_DSFree(&dStr);
    if (startInfo.hStdInput != JSI_BAD_FD) {
        CloseHandle(startInfo.hStdInput);
    }
    if (startInfo.hStdOutput != JSI_BAD_FD) {
        CloseHandle(startInfo.hStdOutput);
    }
    if (startInfo.hStdError != JSI_BAD_FD) {
        CloseHandle(startInfo.hStdError);
    }
    return pid;
}
Exemplo n.º 21
0
/* Collect and execute code from stdin.  The first byte of flags are passed to Jsi_ValueGetDString(). */
int Jsi_Interactive(Jsi_Interp* interp, int flags) {
    int rc = 0, done = 0, len, quote = (flags & 0xff), istty = 1;
    char *prompt = "# ", *buf;
    Jsi_DString dStr;
    Jsi_DSInit(&dStr);
#ifndef __WIN32
    istty = isatty(fileno(stdin));
#else
    istty = _isatty(_fileno(stdin));
#endif
#ifdef HAVE_READLINE
    Jsi_DString dHist = {};
    char *hist = NULL;
    if(interp->noreadline == 0 && !interp->parent)
    {
        hist = Jsi_NormalPath(interp, "~/.jsish_history", &dHist);
        if (hist)
            read_history(hist);
    }
#endif
    interp->level++;
    while (done==0 && interp->exited==0) {
        buf = get_inputline(istty, prompt);
        if (buf) {
          Jsi_DSAppend(&dStr, buf, NULL);
          free(buf);
        } else {
          done = 1;
        }
        len = Jsi_DSLength(&dStr);
        if (done && len == 0)
            break;
        buf = Jsi_DSValue(&dStr);
        if (done == 0 && (!balanced(buf))) {
            prompt = "> ";
            if (len<5)
                break;
            continue;
        }
        prompt = "# ";
        while ((len = Jsi_Strlen(buf))>0 && (isspace(buf[len-1])))
            buf[len-1] = 0;
        if (buf[0] == 0)
            continue;
        /* Convenience: add semicolon to "var" statements (required by parser). */
        if (strncmp(buf,"var ", 4) == 0 && strchr(buf, '\n')==NULL && strchr(buf, ';')==NULL)
            strcat(buf, ";");
        rc = Jsi_EvalString(interp, buf, JSI_EVAL_RETURN);
        if (interp->exited)
            break;
        if (rc == 0) {
             if (interp->ret.vt != JSI_VT_UNDEF || interp->noUndef==0) {
                Jsi_DString eStr = {};
                fputs(Jsi_ValueGetDString(interp,&interp->ret, &eStr, quote), stdout);
                Jsi_DSFree(&eStr);
                fputs("\n", stdout);
             }
        } else if (!interp->exited) {
            fputs("ERROR\n", stderr);
        }
        Jsi_DSSetLength(&dStr, 0);
        len = 0;
    }
    interp->level--;
#ifdef HAVE_READLINE
    if (hist) {
        stifle_history(100);
        write_history(hist);
    }
    Jsi_DSFree(&dHist);
#endif
    Jsi_DSFree(&dStr);
    if (interp->exited && interp->level <= 0)
    {
        rc = interp->exitCode;
        Jsi_InterpDelete(interp);
    }
    return rc;
}
Exemplo n.º 22
0
/* Lookup a name, eg.  "a[b].c  a.b.c  a[b][c]  a.b[c]  a["b"].c  a[1].c  */
Jsi_Value *Jsi_NameLookup(Jsi_Interp *interp, const char *name)
{
    int cnt = 0, len, isq;
    char *nam = (char*)name, *cp, *cp2, *ocp, *kstr;
    Jsi_Value *v = NULL, tv = VALINIT, nv = VALINIT, key = VALINIT;
    Jsi_DString dStr = {};
    cp2 = strchr(nam,'[');
    cp = strchr(nam, '.');
    if (cp2 && (cp==0 || cp2<cp))
        cp = cp2;
    if (!cp)
        return Jsi_VarLookup(interp, nam);
    Jsi_DSSetLength(&dStr, 0);
    Jsi_DSAppendLen(&dStr, nam, cp-nam);
    v = Jsi_VarLookup(interp, Jsi_DSValue(&dStr));
    if (!v)
        goto bail;
    while (cnt++ < 1000) {
        ocp = cp;
        nam = cp+1;
        isq = 0;
        if (*cp == '[') {
            cp = FindEndB(cp+1); /* handle [] in strings. */
            if (!cp) goto bail;
            len = cp-nam;
            cp++;
            if (len>=2 && ((nam[0] == '\"' && nam[len-1] == '\"') || (nam[0] == '\'' && nam[len-1] == '\''))) {
                nam += 1;
                len -= 2;
                isq = 1;
            }
        } else if (*cp == '.') {
            cp2 = strchr(nam,'[');
            cp = strchr(nam, '.');
            if (cp2 && (cp==0 || cp2<cp))
                cp = cp2;
            len = (cp ? cp-nam : strlen(nam));
        } else {
            goto bail;
        }
        Jsi_DSSetLength(&dStr, 0);
        Jsi_DSAppendLen(&dStr, nam, len);
        kstr = Jsi_DSValue(&dStr);
        if (*ocp == '[' && isq == 0 && isdigit(kstr[0]) && Jsi_ValueIsArray(interp, v)) {
            int nn;
            if (Jsi_GetInt(interp, kstr, &nn, 0) != JSI_OK)
                goto bail;
            v = Jsi_ValueArrayIndex(interp, v, nn);
            if (!v)
                goto bail;
        } else if (*ocp == '[' && isq == 0) {
            Jsi_Value *kv = Jsi_VarLookup(interp, kstr);
            if (!kv)
                goto bail;
            jsi_ValueSubscriptLen(interp, v, kv, &nv, 1);
            goto keyon;
        } else {
            Jsi_ValueMakeStringKey(interp, &key, kstr); 
            jsi_ValueSubscriptLen(interp, v, &key, &nv, 1);
keyon:
            if (nv.vt == JSI_VT_UNDEF)
                goto bail;
            else {
                tv = nv;
                v = &tv;
            }
        }
        if (cp == 0 || *cp == 0) break;
    }
    //Jsi_ValueReset(interp, &ret);
    Jsi_DSFree(&dStr);
    if (v && v == &tv) {
        v = Jsi_ValueNew(interp);
        *v = tv;
    }
    return v;
bail:
    Jsi_DSFree(&dStr);
    return NULL;
}