Exemple #1
0
/*
 *  Public routine to set the error message. Caller MUST NOT free.
 */
char *ejsGetErrorMsg(Ejs *ejs, int withStack)
{
    EjsVar      *message, *stack, *error;
    cchar       *name;
    char        *buf;

    if (ejs->flags & EJS_FLAG_EMPTY) {
        return "";
    }

    error = (EjsVar*) ejs->exception;
    message = stack = 0;
    name = 0;

    if (error) {
        name = error->type->qname.name;
        if (ejsIsA(ejs, error, ejs->errorType)) {
            message = ejsGetProperty(ejs, error, ES_Error_message);
            stack = ejsGetProperty(ejs, error, ES_Error_stack);

        } else if (ejsIsString(error)) {
            name = "Error";
            message = error;

        } else if (ejsIsNumber(error)) {
            name = "Error";
            message = error;
            
        } else if (error == (EjsVar*) ejs->stopIterationType) {
            name = "StopIteration";
            message = (EjsVar*) ejsCreateString(ejs, "Uncaught StopIteration exception");
        }
    }
    if (!withStack) {
        stack = 0;
    }

    if (stack && ejsIsString(stack) && message && ejsIsString(message)){
        buf = mprAsprintf(ejs, -1, "%s Exception: %s\nStack:\n%s", name, ((EjsString*) message)->value, 
            ((EjsString*) stack)->value);

    } else if (message && ejsIsString(message)){
        buf = mprAsprintf(ejs, -1, "%s: %s", name, ((EjsString*) message)->value);

    } else if (message && ejsIsNumber(message)){
        buf = mprAsprintf(ejs, -1, "%s: %d", name, ((EjsNumber*) message)->value);
        
    } else {
        if (error) {
            buf = mprStrdup(ejs, "Unknown exception object type");
        } else {
            buf = mprStrdup(ejs, "");
        }
    }
    mprFree(ejs->errorMsg);
    ejs->errorMsg = buf;
    return buf;
}
Exemple #2
0
static int makeChannel(MprCmd *cmd, int index)
{
    MprCmdFile      *file;
    static int      tempSeed = 0;

    file = &cmd->files[index];

    file->name = mprAsprintf(cmd, -1, "/pipe/%s_%d_%d", BLD_PRODUCT, taskIdSelf(), tempSeed++);

    if (pipeDevCreate(file->name, 5, MPR_BUFSIZE) < 0) {
        mprError(cmd, "Can't create pipes to run %s", cmd->program);
        return MPR_ERR_CANT_OPEN;
    }
    
    /*
     *  Open the server end of the pipe. MPR_CMD_STDIN is from the client's perspective.
     */
    if (index == MPR_CMD_STDIN) {
        file->fd = open(file->name, O_WRONLY, 0644);
    } else {
        file->fd = open(file->name, O_RDONLY, 0644);
    }
    if (file->fd < 0) {
        mprError(cmd, "Can't create stdio pipes. Err %d", mprGetOsError());
        return MPR_ERR_CANT_CREATE;
    }
    return 0;
}
Exemple #3
0
static EjsVar *castVar(Ejs *ejs, EjsVar *vp, EjsType *toType)
{
    EjsString   *result;
    char        *buf;

    buf = mprAsprintf(ejs, -1, "[object %s]", vp->type->qname.name);
    result = ejsCreateString(ejs, buf);
    mprFree(buf);
    return (EjsVar*) result;
}
Exemple #4
0
/*
 *  Output a parse message
 */ 
static void xmlError(MprXml *xp, char *fmt, ...)
{
    va_list     args;
    char        *buf;

    mprAssert(fmt);

    va_start(args, fmt);
    buf = mprVasprintf(xp, MPR_MAX_STRING, fmt, args);
    va_end(args);

    mprFree(xp->errMsg);
    xp->errMsg = mprAsprintf(xp, MPR_MAX_STRING, "XML error: %s\nAt line %d\n", buf, xp->lineNumber);
    mprFree(buf);
}
Exemple #5
0
static EjsVar *castError(Ejs *ejs, EjsError *vp, EjsType *type)
{
    EjsVar      *sp;
    char        *buf;

    switch (type->id) {

    case ES_Boolean:
        return (EjsVar*) ejsCreateBoolean(ejs, 1);

    case ES_String:
        if ((buf = mprAsprintf(ejs, -1,
                "%s Exception: %s\nStack:\n%s\n", vp->obj.var.type->qname.name, vp->message, vp->stack)) == NULL) {
            ejsThrowMemoryError(ejs);
        }
        sp = (EjsVar*) ejsCreateString(ejs, buf);
        mprFree(buf);
        return sp;

    default:
        ejsThrowTypeError(ejs, "Unknown type");
        return 0;
    }
}
Exemple #6
0
static char *resolveUrl(MprHttp *http, cchar *url)
{
    if (*url == '/') {
        if (host) {
            if (mprStrcmpAnyCaseCount(host, "http://", 7) != 0 && mprStrcmpAnyCaseCount(host, "https://", 8) != 0) {
                return mprAsprintf(http, -1, "http://%s%s", host, url);
            } else {
                return mprAsprintf(http, -1, "%s%s", host, url);
            }
        } else {
            return mprAsprintf(http, -1, "http://127.0.0.1%s", url);
        }
    } 
    if (mprStrcmpAnyCaseCount(url, "http://", 7) != 0 && mprStrcmpAnyCaseCount(url, "https://", 8) != 0) {
        if (*url == ':' && isPort(&url[1])) {
            return mprAsprintf(http, -1, "http://127.0.0.1%s", url);
        } else if (isPort(url)) {
            return mprAsprintf(http, -1, "http://127.0.0.1:%s", url);
        } else {
            return mprAsprintf(http, -1, "http://%s", url);
        }
    }
    return mprStrdup(http, url);
}
Exemple #7
0
static void reportFailure(MaConn *conn, int code, cchar *fmt, va_list args)
{
    MaResponse  *resp;
    MaRequest   *req;
    cchar       *url, *status;
    char        *emsg, *msg, *filename;

    mprAssert(fmt);
    
    if (conn->requestFailed) {
        return;
    }
    conn->requestFailed = 1;
    if (fmt == 0) {
        fmt = "";
    }
    req = conn->request;
    resp = conn->response;
    maDontCacheResponse(conn);

    msg = mprVasprintf(conn, MA_BUFSIZE, fmt, args);

    if (resp == 0 || req == 0) {
        mprLog(conn, 2, "\"%s\", code %d: %s.", mprGetHttpCodeString(conn, code), code, msg);

    } else {
        resp->code = code;
        filename = resp->filename ? resp->filename : 0;
        /* 711 is a custom error used by the test suite. */
        if (code != 711) {
            mprLog(resp, 2, "Error: \"%s\", code %d for URI \"%s\", file \"%s\": %s.", 
                mprGetHttpCodeString(conn, code), code, req->url ? req->url : "", filename ? filename : "", msg);
        }
        /*
         *  Use an error document rather than standard error boilerplate.
         */
        if (req->location) {
            url = maLookupErrorDocument(req->location, code);
            if (url && *url) {
                maRedirect(conn, 302, url);
                mprFree(msg);
                return;
            }
        }

        /*
         *  If the headers have already been filled, this alternate response body will be ignored.
         */
        if (resp->altBody == 0) {
            status = mprGetHttpCodeString(conn, code);
            /*
             *  For security, escape the message
             */
            emsg = mprEscapeHtml(resp, msg);
            resp->altBody = mprAsprintf(resp, -1, 
                "<!DOCTYPE html>\r\n"
                "<html><head><title>Document Error: %s</title></head>\r\n"
                "<body><h2>Access Error: %d -- %s</h2>\r\n<p>%s</p>\r\n</body>\r\n</html>\r\n",
                status, code, status, emsg);
        }
        resp->flags |= MA_RESP_NO_BODY;
    }
    mprFree(msg);
}
Exemple #8
0
static void runPhp(MaQueue *q)
{
    MaConn              *conn;
    MaRequest           *req;
    MaResponse          *resp;
    MaPhp               *php;
    FILE                *fp;
    char                shebang[MPR_MAX_STRING];
    zend_file_handle    file_handle;

    TSRMLS_FETCH();

    conn = q->conn;
    req = conn->request;
    resp = conn->response;
    php = q->queueData;

    maPutForService(q, maCreateHeaderPacket(q), 0);

    /*
     *  Set the request context
     */
    zend_first_try {
        php->var_array = 0;
        SG(server_context) = conn;
        if (req->user) {
            SG(request_info).auth_user = estrdup(req->user);
        }
        if (req->password) {
            SG(request_info).auth_password = estrdup(req->password);
        }
        if (req->authType && req->authDetails) {
            SG(request_info).auth_digest = estrdup(mprAsprintf(req, -1, "%s %s", req->authType, req->authDetails));
        }
        SG(request_info).auth_password = req->password;
        SG(request_info).content_type = req->mimeType;
        SG(request_info).content_length = req->length;
        SG(sapi_headers).http_response_code = MPR_HTTP_CODE_OK;
        SG(request_info).path_translated = resp->filename;
        SG(request_info).query_string = req->parsedUri->query;
        SG(request_info).request_method = req->methodName;
        SG(request_info).request_uri = req->url;

        /*
         *  Workaround on MAC OS X where the SIGPROF is given to the wrong thread
         */
        PG(max_input_time) = -1;
        EG(timeout_seconds) = 0;

        /* The readPostData callback may be invoked during startup */
        php_request_startup(TSRMLS_C);
        CG(zend_lineno) = 0;

    } zend_catch {
        mprError(q, "Can't start PHP request");
        zend_try {
            php_request_shutdown(0);
        } zend_end_try();
        maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR, "PHP initialization failed");
        return;
    } zend_end_try();


    /*
     *  Execute the script file
     */
    file_handle.filename = resp->filename;
    file_handle.free_filename = 0;
    file_handle.opened_path = 0;

#if LOAD_FROM_FILE
    file_handle.type = ZEND_HANDLE_FILENAME;
#else
    file_handle.type = ZEND_HANDLE_FP;
    if ((fp = fopen(resp->filename, "r")) == NULL) {
        maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR,  "PHP can't open script");
        return;
    }
    /*
        Check for shebang and skip
     */
    file_handle.handle.fp = fp;
    shebang[0] = '\0';
    if (fgets(shebang, sizeof(shebang), file_handle.handle.fp) != 0) {
        if (shebang[0] != '#' || shebang[1] != '!') {
            fseek(fp, 0L, SEEK_SET);
        }
    }
#endif

    zend_try {
        php_execute_script(&file_handle TSRMLS_CC);
        if (!SG(headers_sent)) {
            sapi_send_headers(TSRMLS_C);
        }
    } zend_catch {
        php_request_shutdown(0);
        maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR,  "PHP script execution failed");
        return;
    } zend_end_try();

    zend_try {
        php_request_shutdown(0);
    } zend_end_try();

    maPutForService(q, maCreateEndPacket(q), 1);
}
Exemple #9
0
/*
 *  Format a fully qualified URI
 */
char *mprFormatUri(MprCtx ctx, cchar *scheme, cchar *host, int port, cchar *path, cchar *query)
{
    char    portBuf[16], *uri;
    cchar   *portDelim, *pathDelim, *queryDelim;
    int     defaultPort, len;

    len = 0;

    if (scheme == 0 || *scheme == '\0') {
        scheme = "http";
    }
    len += (int) strlen(scheme) + 3;                            /* Add 3 for "://" */

    defaultPort = (strcmp(scheme, "http") == 0) ? 80 : 443;

    if (host == 0 || *host == '\0') {
        host = "localhost";
    }

    /*
     *  Hosts with integral port specifiers override
     */
    if (strchr(host, ':')) {
        portDelim = 0;
    } else {
        if (port != defaultPort) {
            mprItoa(portBuf, sizeof(portBuf), port, 10);
            portDelim = ":";
        } else {
            portBuf[0] = '\0';
            portDelim = "";
        }
        len += (int) strlen(portBuf) + (int) strlen(portDelim);
    }
    len += (int) strlen(host);

    if (path) {
        pathDelim = (*path == '/') ? "" :  "/";
    } else {
        pathDelim = "/";
        path = "";
    }
    len += (int) strlen(path) + (int) strlen(pathDelim);

    if (query && *query) {
        queryDelim = "?";
    } else {
        queryDelim = query = "";
    }
    len += (int) strlen(query) + (int) strlen(queryDelim);
    len += 1;                                               /* Add one for the null */

    uri = mprAlloc(ctx, len);
    if (uri == 0) {
        return 0;
    }

    if (portDelim) {
        uri = mprAsprintf(ctx, len, "%s://%s%s%s%s%s%s%s", scheme, host, portDelim, portBuf, pathDelim, 
            path, queryDelim, query);
    } else {
        uri = mprAsprintf(ctx, len, "%s://%s%s%s%s%s", scheme, host, pathDelim, path, queryDelim, query);
    }
    if (uri == 0) {
        return 0;
    }
    return uri;
}
Exemple #10
0
/*
 *  Format the stack backtrace
 */
char *ejsFormatStack(Ejs *ejs, EjsError *error)
{
    EjsType         *type;
    EjsFrame        *fp;
    cchar           *typeName, *functionName, *line, *typeSep, *codeSep;
    char            *backtrace, *traceLine;
    int             level, len, oldFlags;

    mprAssert(ejs);

    backtrace = 0;
    len = 0;
    level = 0;

    /*
     *  Pretend to be the compiler so we can access function frame names
     */
    oldFlags = ejs->flags;
    ejs->flags |= EJS_FLAG_COMPILER;

    for (fp = ejs->state->fp; fp; fp = fp->caller) {

        typeName = "";
        functionName = "global";

        if (fp->currentLine == 0) {
            line = "";
        } else {
            for (line = fp->currentLine; *line && isspace((int) *line); line++) {
                ;
            }
        }
        if (fp) {
            if (fp->function.owner && fp->function.slotNum >= 0) {
                functionName = ejsGetPropertyName(ejs, fp->function.owner, fp->function.slotNum).name;
            }
            if (ejsIsType(fp->function.owner)) {
                type = (EjsType*) fp->function.owner;
                if (type) {
                    typeName = type->qname.name;
                }
            }
        }
        typeSep = (*typeName) ? "." : "";
        codeSep = (*line) ? "->" : "";

        if (error && backtrace == 0) {
            error->filename = mprStrdup(error, fp->filename);
            error->lineNumber = fp->lineNumber;
        }
        if ((traceLine = mprAsprintf(ejs, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n",
                level++, fp->filename ? fp->filename : "script", typeName, typeSep, functionName,
                fp->lineNumber, codeSep, line)) == NULL) {
            break;
        }
        backtrace = (char*) mprRealloc(ejs, backtrace, len + (int) strlen(traceLine) + 1);
        if (backtrace == 0) {
            return 0;
        }
        memcpy(&backtrace[len], traceLine, strlen(traceLine) + 1);
        len += (int) strlen(traceLine);
        mprFree(traceLine);
    }
    ejs->flags = oldFlags;
    if (error) {
        error->stack = backtrace;
    }
    return backtrace;
}
Exemple #11
0
static bool parseArgs(Mpr *mpr, int argc, char **argv)
{
    char    *argp, *key, *value;
    int     i, setWorkers;

    setWorkers = 0;

    for (nextArg = 1; nextArg < argc; nextArg++) {
        argp = argv[nextArg];
        if (*argp != '-') {
            break;
        }

        if (strcmp(argp, "--benchmark") == 0 || strcmp(argp, "-b") == 0) {
            benchmark++;

        } else if (strcmp(argp, "--chunk") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                chunkSize = argv[++nextArg];
                i = atoi(chunkSize);
                if (i < 0) {
                    mprError(mpr, "Bad chunksize %d", i);
                    return 0;
                }
            }

        } else if (strcmp(argp, "--continue") == 0) {
            continueOnErrors++;

        } else if (strcmp(argp, "--cookie") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                mprAddItem(headers, mprCreateKeyPair(headers, "Cookie", argv[++nextArg]));
            }

        } else if (strcmp(argp, "--debug") == 0 || strcmp(argp, "-D") == 0 || strcmp(argp, "--debugger") == 0) {
            mprSetDebugMode(mpr, 1);
            retries = 0;

        } else if (strcmp(argp, "--delete") == 0) {
            method = "DELETE";

        } else if (strcmp(argp, "--form") == 0 || strcmp(argp, "-f") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                if (formData == 0) {
                    formData = mprCreateList(mpr);
                }
                addFormVars(mpr, argv[++nextArg]);
            }

        } else if (strcmp(argp, "--header") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                key = argv[++nextArg];
                if ((value = strchr(key, ':')) == 0) {
                    mprError(mpr, "Bad header format. Must be \"key: value\"");
                    return 0;
                }
                *value++ = '\0';
                while (isspace((int) *value)) {
                    value++;
                }
                mprAddItem(headers, mprCreateKeyPair(headers, key, value));
            }

        } else if (strcmp(argp, "--host") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                host = argv[++nextArg];
            }

        } else if (strcmp(argp, "--http") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                httpVersion = atoi(argv[++nextArg]);
            }

        } else if (strcmp(argp, "--iterations") == 0 || strcmp(argp, "-i") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                iterations = atoi(argv[++nextArg]);
            }

        } else if (strcmp(argp, "--log") == 0 || strcmp(argp, "-l") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                startLogging(mpr, argv[++nextArg]);
            }

        } else if (strcmp(argp, "--method") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                method = argv[++nextArg];
            }

        } else if (strcmp(argp, "--noout") == 0 || strcmp(argp, "-n") == 0  ||
                   strcmp(argp, "--quiet") == 0 || strcmp(argp, "-q") == 0) {
            noout++;

        } else if (strcmp(argp, "--nofollow") == 0) {
            nofollow++;

        } else if (strcmp(argp, "--password") == 0 || strcmp(argp, "-p") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                password = argv[++nextArg];
            }

        } else if (strcmp(argp, "--post") == 0) {
            method = "POST";

        } else if (strcmp(argp, "--printable") == 0) {
            printable++;

        } else if (strcmp(argp, "--put") == 0) {
            method = "PUT";

        } else if (strcmp(argp, "--range") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                if (ranges == 0) {
                    ranges = mprAsprintf(mpr, -1, "bytes=%s", argv[++nextArg]);
                } else {
                    ranges = mprStrcat(mpr, -1, ranges, ",", argv[++nextArg], NULL);
                }
            }
            
        } else if (strcmp(argp, "--retries") == 0 || strcmp(argp, "-r") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                retries = atoi(argv[++nextArg]);
            }
            
        } else if (strcmp(argp, "--sequence") == 0) {
            sequence++;

        } else if (strcmp(argp, "--showCode") == 0 || strcmp(argp, "--showStatus") == 0) {
            showCode++;

        } else if (strcmp(argp, "--show") == 0 || strcmp(argp, "--showHeaders") == 0) {
            showHeaders++;

        } else if (strcmp(argp, "--single") == 0 || strcmp(argp, "-s") == 0) {
            singleStep++;

        } else if (strcmp(argp, "--threads") == 0 || strcmp(argp, "-t") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                loadThreads = atoi(argv[++nextArg]);
            }

        } else if (strcmp(argp, "--timeout") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                timeout = atoi(argv[++nextArg]) * 1000;
            }

        } else if (strcmp(argp, "--upload") == 0 || strcmp(argp, "-u") == 0) {
            upload++;

        } else if (strcmp(argp, "--user") == 0 || strcmp(argp, "--username") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                username = argv[++nextArg];
            }

        } else if (strcmp(argp, "--verbose") == 0 || strcmp(argp, "-v") == 0) {
            verbose++;

        } else if (strcmp(argp, "--workerTheads") == 0 || strcmp(argp, "-w") == 0) {
            if (nextArg >= argc) {
                return 0;
            } else {
                workers = atoi(argv[++nextArg]);
            }
            setWorkers++;

        } else {
            return 0;
            break;
        }
    }
    if (argc == nextArg) {
        return 0;
    }
    argc = argc - nextArg;
    argv = &argv[nextArg];
    target = argv[argc - 1];
    argc--;
    if (argc > 0) {
        /*
         *  Files present on command line
         */
        fileData = mprCreateList(mpr);
        for (i = 0; i < argc; i++) {
            mprAddItem(fileData, argv[i]);
        }
    }
    if (!setWorkers) {
        workers = loadThreads + 2;
    }
    if (method == 0) {
        if (upload || formData) {
            method = "POST";
        } else if (fileData) {
            method = "PUT";
        } else {
            method = "GET";
        }
    }
    return 1;
}
Exemple #12
0
/*
 *  Sanitize args. Convert "/" to "\" and converting '\r' and '\n' to spaces, quote all args and put the program as argv[0].
 */
static int sanitizeArgs(MprCmd *cmd, int argc, char **argv, char **env)
{
#if VXWORKS
    cmd->argv = argv;
    cmd->argc = argc;
    cmd->env = 0;
#endif
#if BLD_UNIX_LIKE
    char    *cp;
    int     index, i, hasPath, hasLibPath;

    cmd->argv = argv;
    cmd->argc = argc;
    cmd->env = 0;

    if (env) {
        for (i = 0; env && env[i]; i++) {
            mprLog(cmd, 6, "cmd: env[%d]: %s", i, env[i]);
        }
        if ((cmd->env = mprAlloc(cmd, (i + 3) * (int) sizeof(char*))) == NULL) {
            return MPR_ERR_NO_MEMORY;
        }
        hasPath = hasLibPath = 0;
        for (index = i = 0; env && env[i]; i++) {
            mprLog(cmd, 6, "cmd: env[%d]: %s", i, env[i]);
            if (strncmp(env[i], "PATH=", 5) == 0) {
                hasPath++;
            } else if  (strncmp(env[i], LD_LIBRARY_PATH "=", 16) == 0) {
                hasLibPath++;
            }
            cmd->env[index++] = env[i];
        }

        /*
         *  Add PATH and LD_LIBRARY_PATH 
         */
        if (!hasPath && (cp = getenv("PATH")) != 0) {
            cmd->env[index++] = mprAsprintf(cmd, -1, "PATH=%s", cp);
        }
        if (!hasLibPath && (cp = getenv(LD_LIBRARY_PATH)) != 0) {
            cmd->env[index++] = mprAsprintf(cmd, -1, "%s=%s", LD_LIBRARY_PATH, cp);
        }
        cmd->env[index++] = '\0';
        for (i = 0; i < argc; i++) {
            mprLog(cmd, 4, "cmd: arg[%d]: %s", i, argv[i]);
        }
        for (i = 0; cmd->env[i]; i++) {
            mprLog(cmd, 4, "cmd: env[%d]: %s", i, cmd->env[i]);
        }
    }
#endif

#if BLD_WIN_LIKE
    char    *program, *SYSTEMROOT, **ep, **ap, *destp, *cp, *progBuf, *localArgv[2], *saveArg0, *PATH, *endp;
    int     i, len, hasPath, hasSystemRoot;

    mprAssert(argc > 0 && argv[0] != NULL);

    cmd->argv = argv;
    cmd->argc = argc;

    program = argv[0];
    progBuf = mprAlloc(cmd, (int) strlen(program) * 2 + 1);
    strcpy(progBuf, program);
    program = progBuf;

    for (cp = program; *cp; cp++) {
        if (*cp == '/') {
            *cp = '\\';
        } else if (*cp == '\r' || *cp == '\n') {
            *cp = ' ';
        }
    }
    if (*program == '\"') {
        if ((cp = strrchr(++program, '"')) != 0) {
            *cp = '\0';
        }
    }

    if (argv == 0) {
        argv = localArgv;
        argv[1] = 0;
        saveArg0 = program;
    } else {
        saveArg0 = argv[0];
    }
    /*
     *  Set argv[0] to the program name while creating the command line. Restore later
     */
    argv[0] = program;

    /*
     *  Determine the command line length and arg count
     */
    argc = 0;
    for (len = 0, ap = argv; *ap; ap++) {
        len += (int) strlen(*ap) + 1 + 2;         /* Space and possible quotes */
        argc++;
    }
    cmd->command = (char*) mprAlloc(cmd, len + 1);
    cmd->command[len] = '\0';
    
    /*
     *  Add quotes to all args that have spaces in them including "program"
     */
    destp = cmd->command;
    for (ap = &argv[0]; *ap; ) {
        cp = *ap;
        if ((strchr(cp, ' ') != 0) && cp[0] != '\"') {
            *destp++ = '\"';
            strcpy(destp, cp);
            destp += strlen(cp);
            *destp++ = '\"';
        } else {
            strcpy(destp, cp);
            destp += strlen(cp);
        }
        if (*++ap) {
            *destp++ = ' ';
        }
    }
    *destp = '\0';
    argv[0] = saveArg0;

    for (i = 0; i < argc; i++) {
        mprLog(cmd, 4, "cmd: arg[%d]: %s", i, argv[i]);
    }

    /*
     *  Now work on the environment. Windows has a block of null separated strings with a trailing null.
     */
    cmd->env = 0;
    if (env) {
        for (hasSystemRoot =  hasPath = len = 0, ep = env; ep && *ep; ep++) {
            len += (int) strlen(*ep) + 1;
            if (strncmp(*ep, "PATH=", 5) == 0) {
                hasPath++;
            } else if (strncmp(*ep, "SYSTEMROOT=", 11) == 0) {
                hasSystemRoot++;
            }
        }
        if (!hasSystemRoot && (SYSTEMROOT = getenv("SYSTEMROOT")) != 0) {
            len += 11 + (int) strlen(SYSTEMROOT) + 1;
        }
        if (!hasPath && (PATH = getenv("PATH")) != 0) {
            len += 5 + (int) strlen(PATH) + 1;
        }
        len += 2;       /* Windows requires 2 nulls for the block end */

        destp = (char*) mprAlloc(cmd, len);
        endp = &destp[len];
        cmd->env = (char**) destp;
        for (ep = env; ep && *ep; ep++) {
            mprLog(cmd, 4, "cmd: env[%d]: %s", i, *ep);
            strcpy(destp, *ep);
            mprLog(cmd, 7, "cmd: Set env variable: %s", destp);
            destp += strlen(*ep) + 1;
        }
        if (!hasSystemRoot) {
            mprSprintf(destp, endp - destp - 1, "SYSTEMROOT=%s", SYSTEMROOT);
            destp += 12 + strlen(SYSTEMROOT);
        }
        if (!hasPath) {
            mprSprintf(destp, endp - destp - 1, "PATH=%s", PATH);
            destp += 6 + strlen(PATH);
        }
        *destp++ = '\0';
        *destp++ = '\0';                        /* Windows requires two nulls */
        mprAssert(destp <= endp);
#if TEST
        for (cp = (char*) cmd->env; *cp; cp++) {
            print("ENV %s\n", cp);
            cp += strlen(cp);
        }
#endif
    }
#endif /* BLD_WIN_LIKE */
    return 0;
}
Exemple #13
0
/*
 *  This routine runs a command and waits for its completion. Stdoutput and Stderr are returned in *out and *err 
 *  respectively. The command returns the exit status of the command.
 *  Valid flags are:
 *      MPR_CMD_NEW_SESSION     Create a new session on Unix
 *      MPR_CMD_SHOW            Show the commands window on Windows
 *      MPR_CMD_IN              Connect to stdin
 */
int mprRunCmdV(MprCmd *cmd, int argc, char **argv, char **out, char **err, int flags)
{
    int     rc, status;

    if (err) {
        *err = 0;
        flags |= MPR_CMD_ERR;
    } else {
        flags &= ~MPR_CMD_ERR;
    }
    if (out) {
        *out = 0;
        flags |= MPR_CMD_OUT;
    } else {
        flags &= ~MPR_CMD_OUT;
    }

    if (flags & MPR_CMD_OUT) {
        mprFree(cmd->stdoutBuf);
        cmd->stdoutBuf = mprCreateBuf(cmd, MPR_BUFSIZE, -1);
    }
    if (flags & MPR_CMD_ERR) {
        mprFree(cmd->stderrBuf);
        cmd->stderrBuf = mprCreateBuf(cmd, MPR_BUFSIZE, -1);
    }
    mprSetCmdCallback(cmd, cmdCallback, NULL);
    lock(cmd);

    rc = mprStartCmd(cmd, argc, argv, NULL, flags);

    /*
     *  Close the pipe connected to the client's stdin
     */
    if (cmd->files[MPR_CMD_STDIN].fd >= 0) {
        mprCloseCmdFd(cmd, MPR_CMD_STDIN);
    }
    if (rc < 0) {
        if (err) {
            if (rc == MPR_ERR_CANT_ACCESS) {
                *err = mprAsprintf(cmd, -1, "Can't access command %s", cmd->program);
            } else if (MPR_ERR_CANT_OPEN) {
                *err = mprAsprintf(cmd, -1, "Can't open standard I/O for command %s", cmd->program);
            } else if (rc == MPR_ERR_CANT_CREATE) {
                *err = mprAsprintf(cmd, -1, "Can't create process for %s", cmd->program);
            }
        }
        unlock(cmd);
        return rc;
    }
    if (cmd->flags & MPR_CMD_DETACH) {
        unlock(cmd);
        return 0;
    }
    unlock(cmd);
    if (mprWaitForCmd(cmd, -1) < 0) {
        return MPR_ERR_NOT_READY;
    }
    lock(cmd);

    if (mprGetCmdExitStatus(cmd, &status) < 0) {
        unlock(cmd);
        return MPR_ERR;
    }
    if (err && flags & MPR_CMD_ERR) {
        mprAddNullToBuf(cmd->stderrBuf);
        *err = mprGetBufStart(cmd->stderrBuf);
    }
    if (out && flags & MPR_CMD_OUT) {
        mprAddNullToBuf(cmd->stdoutBuf);
        *out = mprGetBufStart(cmd->stdoutBuf);
    }
    unlock(cmd);
    return status;
}
Exemple #14
0
static int makeChannel(MprCmd *cmd, int index)
{
    SECURITY_ATTRIBUTES clientAtt, serverAtt, *att;
    HANDLE              readHandle, writeHandle;
    MprCmdFile          *file;
    MprTime             now;
    char                *pipeBuf;
    int                 openMode, pipeMode, readFd, writeFd;
    static int          tempSeed = 0;

    memset(&clientAtt, 0, sizeof(clientAtt));
    clientAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
    clientAtt.bInheritHandle = 1;

    /*
     *  Server fds are not inherited by the child
     */
    memset(&serverAtt, 0, sizeof(serverAtt));
    serverAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
    serverAtt.bInheritHandle = 0;

    file = &cmd->files[index];
    now = ((int) mprGetTime(cmd) & 0xFFFF) % 64000;

    pipeBuf = mprAsprintf(cmd, -1, "\\\\.\\pipe\\MPR_%d_%d_%d.tmp", getpid(), (int) now, ++tempSeed);

    /*
     *  Pipes are always inbound. The file below is outbound. we swap whether the client or server
     *  inherits the pipe or file. MPR_CMD_STDIN is the clients input pipe.
     *  Pipes are blocking since both ends share the same blocking mode. Client must be blocking.
     */
    openMode = PIPE_ACCESS_INBOUND;
    pipeMode = 0;

    att = (index == MPR_CMD_STDIN) ? &clientAtt : &serverAtt;
    readHandle = CreateNamedPipe(pipeBuf, openMode, pipeMode, 1, 0, 256 * 1024, 1, att);
    if (readHandle == INVALID_HANDLE_VALUE) {
        mprError(cmd, "Can't create stdio pipes %s. Err %d\n", pipeBuf, mprGetOsError());
        return MPR_ERR_CANT_CREATE;
    }
    readFd = (int) (int64) _open_osfhandle((long) readHandle, 0);

    att = (index == MPR_CMD_STDIN) ? &serverAtt: &clientAtt;
    writeHandle = CreateFile(pipeBuf, GENERIC_WRITE, 0, att, OPEN_EXISTING, openMode, 0);
    writeFd = (int) _open_osfhandle((long) writeHandle, 0);

    if (readFd < 0 || writeFd < 0) {
        mprError(cmd, "Can't create stdio pipes %s. Err %d\n", pipeBuf, mprGetOsError());
        return MPR_ERR_CANT_CREATE;
    }
    if (index == MPR_CMD_STDIN) {
        file->clientFd = readFd;
        file->fd = writeFd;
        file->handle = writeHandle;
    } else {
        file->clientFd = writeFd;
        file->fd = readFd;
        file->handle = readHandle;
    }
    mprFree(pipeBuf);
    return 0;
}
Exemple #15
0
/*
 *  function Worker(script: String = null, options: Object = null)
 *
 *  Script is optional. If supplied, the script is run immediately by a worker thread. This call
 *  does not block. Options are: search and name.
 */
static EjsVar *workerConstructor(Ejs *ejs, EjsWorker *worker, int argc, EjsVar **argv)
{
    Ejs             *wejs;
    EjsVar          *options, *value;
    EjsName         qname;
    EjsWorker       *self;
    cchar           *search, *name;

    worker->ejs = ejs;
    worker->state = EJS_WORKER_BEGIN;

    options = (argc == 2) ? (EjsVar*) argv[1]: NULL;
    name = 0;

    search = ejs->ejsPath;
    if (options) {
        value = ejsGetPropertyByName(ejs, options, ejsName(&qname, "", "search"));
        if (ejsIsString(value)) {
            search = ejsGetString(value);
        }
        value = ejsGetPropertyByName(ejs, options, ejsName(&qname, "", "name"));
        if (ejsIsString(value)) {
            name = ejsGetString(value);
        }
    }

    if (name) {
        worker->name = mprStrdup(worker, name);
    } else {
        worker->name = mprAsprintf(worker, -1, "worker-%d", mprGetListCount(ejs->workers));
    }

    /*
     *  Create a new interpreter and an "inside" worker object and pair it with the current "outside" worker.
     */
    wejs = ejsCreate(ejs->service, NULL, search, 0);
    if (wejs == 0) {
        ejsThrowMemoryError(ejs);
        return 0;
    }
    worker->pair = self = ejsCreateWorker(wejs);
    self->state = EJS_WORKER_BEGIN;
    self->ejs = wejs;
    self->inside = 1;
    self->pair = worker;
    self->name = mprStrcat(self, -1, "inside-", worker->name, NULL);

    ejsSetProperty(ejs,  (EjsVar*) worker, ES_ejs_sys_Worker_name, (EjsVar*) ejsCreateString(ejs, self->name));
    ejsSetProperty(wejs, (EjsVar*) self,   ES_ejs_sys_Worker_name, (EjsVar*) ejsCreateString(wejs, self->name));
    ejsSetProperty(wejs, wejs->global, ES_ejs_sys_worker_self, (EjsVar*) self);

    /*
     *  Workers have a dedicated namespace to enable viewing of the worker globals (self, onmessage, postMessage...)
     */
    ejsDefineReservedNamespace(wejs, wejs->globalBlock, 0, EJS_WORKER_NAMESPACE);

    /*
     *  Make the inside worker permanent so we don't need to worry about whether worker->pair->ejs is valid
     */
    self->obj.var.permanent = 1;
    
    if (argc > 0 && ejsIsPath(argv[0])) {
        addWorker(ejs, worker);
        worker->scriptFile = mprStrdup(worker, ((EjsPath*) argv[0])->path);
        worker->state = EJS_WORKER_STARTED;
        worker->obj.var.permanent = 1;
        if (mprStartWorker(ejs, (MprWorkerProc) workerMain, (void*) worker, MPR_NORMAL_PRIORITY) < 0) {
            ejsThrowStateError(ejs, "Can't start worker");
            worker->obj.var.permanent = 0;
            return 0;
        }
    }
    return (EjsVar*) worker;
}