コード例 #1
0
ファイル: ejsException.c プロジェクト: jsjohnst/ejscript
/*
 *  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 = "Details";
            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)){
        mprAllocSprintf(ejs, &buf, 0, "%s Exception: %s\nStack:\n%s", name, ((EjsString*) message)->value, 
            ((EjsString*) stack)->value);

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

    } else {
        if (error) {
            buf = mprStrdup(ejs, "Unknown exception object type");
        } else {
            buf = mprStrdup(ejs, "");
        }
    }

    mprFree(ejs->errorMsg);
    ejs->errorMsg = buf;

    return buf;
}
コード例 #2
0
ファイル: miniMpr.c プロジェクト: Marvin-Lee/libwmiclient
void mprBreakpoint(const char *file, int line, const char *cond)
{
	char *buf;
	mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", 
					file, line, cond);
	ejs_exception(buf);
}
コード例 #3
0
ファイル: os.cpp プロジェクト: linbc/appweb2-win
void mprSetModuleSearchPath(char *dirs)
{
	char	full[MPR_MAX_FNAME], native[MPR_MAX_FNAME];
	char	*oldPath, sep, *np, *tok, *newPath, *searchPath, *cp;
	int		len, modified;

	mprAssert(dirs && *dirs);

	oldPath = getenv("PATH");
	mprAssert(oldPath);

	if (oldPath == 0 || dirs == 0) {
		return;
	}

	/*
	 *	Prepare to tokenize the search path
	 */
	searchPath = mprStrdup(dirs);
	sep = strchr(searchPath, '"') ? '"' : ' ';
	for (cp = searchPath; *cp; cp++) {
		if (*cp == sep) {
			*cp = '\001';
		}
	}

	len = mprAllocSprintf(&newPath, -1, "PATH=%s", oldPath);
	mprAssert(len > 0);

	np = mprStrTok(searchPath, "\001\n", &tok);
	for (modified = 0; np; ) {
		mprGetFullPathName(full, sizeof(full), np);
		mprGetNativePathName(native, sizeof(native), full);

		//	TODO - this should really do a case insensitive scan
		if ((cp = strstr(oldPath, native)) != 0) {
			cp = &oldPath[strlen(native)];
			if (*cp == ';' || *cp == '\0') {
				np = mprStrTok(0, "\001\n", &tok);
				continue;
			}
		}

		len = mprReallocStrcat(&newPath, -1, len, ";", native, 0);
		mprAssert(len >= 0);
		np = mprStrTok(0, "\001\n", &tok);
		modified = 1;
	}
	if (modified) {
		mprLog(7, "Set %s\n", newPath);

		if (putenv(newPath) < 0) {
			mprAssert(0);
		}
	}

	mprFree(searchPath);
	mprFree(newPath);
}
コード例 #4
0
ファイル: ejsException.c プロジェクト: jsjohnst/ejscript
/*
 *  Format the stack backtrace
 */
char *ejsFormatStack(Ejs *ejs)
{
    EjsFrame        *frame;
    EjsType         *type;
    EjsFunction     *fun;
    cchar           *typeName, *functionName, *line, *typeSep, *codeSep;
    char            *backtrace, *traceLine;
    int             level, len;

    mprAssert(ejs);

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

    for (frame = ejs->frame; frame; frame = frame->caller) {

        if (frame->currentLine == 0) {
            line = "";
        } else {
            for (line = frame->currentLine; *line && isspace((int) *line); line++) {
                ;
            }
        }

        typeName = "";
        functionName = "global";

        fun = &frame->function;
        if (fun) {
            if (fun->owner) {
                functionName = ejsGetPropertyName(ejs, fun->owner, fun->slotNum).name;
            }
            if (ejsIsType(fun->owner)) {
                type = (EjsType*) fun->owner;
                if (type) {
                    typeName = type->qname.name;
                }
            }
        }
        typeSep = (*typeName) ? "." : "";
        codeSep = (*line) ? "->" : "";

        if (mprAllocSprintf(ejs, &traceLine, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n",
                level++, frame->fileName ? frame->fileName : "script", typeName, typeSep, functionName,
                frame->lineNumber, codeSep, line) < 0) {
            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);
    }
    return backtrace;
}
コード例 #5
0
ファイル: ejsVar.c プロジェクト: jsjohnst/ejscript
static EjsVar *castVar(Ejs *ejs, EjsVar *vp, EjsType *toType)
{
    EjsString   *result;
    char        *buf;

    /*
     *  TODO - should support cast to Boolean and Number
     */
    mprAllocSprintf(ejs, &buf, 0, "[object %s]", vp->type->qname.name);
    result = ejsCreateString(ejs, buf);
    mprFree(buf);
    return (EjsVar*) result;

}
コード例 #6
0
ファイル: pipeline.c プロジェクト: jsjohnst/appweb
static void setEnv(MaConn *conn)
{
    MaRequest       *req;
    MaResponse      *resp;
    MaStage         *handler;
    MprFileInfo     *info;

    req = conn->request;
    resp = conn->response;
    handler = resp->handler;

    setPathInfo(conn);

    if (resp->extension == 0) {
        resp->extension = getExtension(conn);
    }
    if (resp->filename == 0) {
        resp->filename = makeFilename(conn, req->alias, req->url, 1);
    }

    if ((resp->mimeType = (char*) maLookupMimeType(conn->host, resp->extension)) == 0) {
        resp->mimeType = (char*) "text/html";
    }

    if (!(resp->handler->flags & MA_STAGE_VIRTUAL)) {
        /*
         *  Define an Etag for physical entities. Redo the file info if not valid now that extra path has been removed.
         */
        info = &resp->fileInfo;
        if (!info->valid) {
            mprGetFileInfo(conn, resp->filename, info);
        }
        if (info->valid) {
            mprAllocSprintf(resp, &resp->etag, -1, "%x-%Lx-%Lx", info->inode, info->size, info->mtime);
        }
    }

    if (handler->flags & MA_STAGE_FORM_VARS) {
        req->formVars = mprCreateHash(req, MA_VAR_HASH_SIZE);
        if (req->parsedUri->query) {
            maAddFormVars(conn, req->parsedUri->query, (int) strlen(req->parsedUri->query));
        }
    }
    if (handler->flags & MA_STAGE_ENV_VARS) {
        maCreateEnvVars(conn);
    }
}
コード例 #7
0
ファイル: appweb.cpp プロジェクト: embedthis/appweb-2
static int configureViaFile()
{
	char	*path;

	mprAllocSprintf(&path, MPR_MAX_FNAME, "%s/%s", serverRoot, configFile);
	mprLog(MPR_CONFIG, "Using configuration file: \n"
		"                       \"%s\"\n", path);

	//
	//	Configure the http service and hosts specified in the config file.
	//
	if (server->configure(path) < 0) {
		mprError(MPR_L, MPR_USER, "Can't configure server using %s", path);
		mprFree(path);
		return MPR_ERR_CANT_INITIALIZE;
	}
	mprFree(path);
	return 0;
}
コード例 #8
0
ファイル: esp.c プロジェクト: embedthis/appweb-2
static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg)
{
	EspParse	parse;
	char		path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME];
	char		*incBuf, *incText;
	int			state, tid, len, rc, maxScriptSize, incSize;

	mprAssert(ep);
	mprAssert(jsBuf);
	mprAssert(input);

	rc = 0;
	len = 0;
	state = ESP_STATE_BEGIN;
	if (errMsg) {
		*errMsg = 0;
	}

	memset(&parse, 0, sizeof(parse));
	parse.token = (char*) mprMalloc(ESP_TOK_INCR);
	if (parse.token == 0) {
		return MPR_ERR_CANT_ALLOCATE;
	}
	parse.token[0] = '\0';
	parse.tokLen = ESP_TOK_INCR;
	parse.endp = &parse.token[parse.tokLen - 1];
	parse.tokp = parse.token;
	parse.inBuf = input;
	parse.inp = parse.inBuf;

	maxScriptSize = esp->maxScriptSize;

	tid = getEspToken(state, &parse);
	while (tid != ESP_TOK_EOF && len >= 0) {

		switch (tid) {
		default:
		case ESP_TOK_ERR:
			mprFree(parse.token);
			return MPR_ERR_BAD_SYNTAX;
			
		case ESP_TOK_LITERAL:
			len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, 
				"write(\"", parse.token, "\");\n", (void*) 0);
			break;

		case ESP_TOK_ATAT:
			/*
			 *	Trick to get undefined variables to evaluate to "".
			 *	Catenate with "" to cause toString to run. 
			 */
			len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, 
				"write(\"\" + ", parse.token, ");\n", (void*) 0);
			break;

		case ESP_TOK_EQUALS:
			len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, 
				"write(\"\" + ", parse.token, ");\n", (void*) 0);
			state = ESP_STATE_IN_ESP_TAG;
			break;

		case ESP_TOK_START_ESP:
			state = ESP_STATE_IN_ESP_TAG;
			tid = getEspToken(state, &parse);
			while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF && 
					tid != ESP_TOK_END_ESP && len >= 0) {
				len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, 
					parse.token, (void*) 0);
				tid = getEspToken(state, &parse);
			}
			state = ESP_STATE_BEGIN;
			break;

		case ESP_TOK_END_ESP:
			state = ESP_STATE_BEGIN;
			break;

		case ESP_TOK_INCLUDE:
			if (parse.token[0] == '/') {
				mprStrcpy(incPath, sizeof(incPath), parse.token);
			} else {
				mprGetDirName(dir, sizeof(dir), ep->uri);
				mprSprintf(incPath, sizeof(incPath), "%s/%s", 
					dir, parse.token);
			}
			if (esp->mapToStorage(ep->requestHandle, path, sizeof(path),
					incPath, 0) < 0) {
				mprAllocSprintf(errMsg, MPR_MAX_STRING, 
					"Can't find include file: %s", path);
				rc = MPR_ERR_CANT_OPEN;
				break;
			}
			if (esp->readFile(ep->requestHandle, &incText, &incSize, 
					path) < 0) {
				mprAllocSprintf(errMsg, MPR_MAX_STRING, 
					"Can't read include file: %s", path);
				rc = MPR_ERR_CANT_READ;
				break;
			}
			incText[incSize] = '\0';

			/*
			 *	Recurse and process the include script
			 */
			incBuf = 0;
			if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) {
				mprFree(incText);
				mprFree(parse.token);
				return rc;
			}

			len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, 
				(void*) 0);
			mprFree(incText);
			mprFree(incBuf);
			state = ESP_STATE_IN_ESP_TAG;
			break;
		}
		tid = getEspToken(state, &parse);
	}
	mprFree(parse.token);
	if (len < 0) {
		mprAllocSprintf(errMsg, MPR_MAX_STRING, 
			"Script token is too big in %s.\nConfigured maximum is %d.", 
			path, maxScriptSize);
		return MPR_ERR_WONT_FIT;
	}
	return rc;
}
コード例 #9
0
ファイル: appweb.cpp プロジェクト: embedthis/appweb-2
static int configureViaApi()
{
	MaHostAddress 	*address;
	MaHost			*host;
	MprList			*listens;
	MaListen		*lp;
	MprHashTable	*hostAddresses;
	MaDir			*dir;
	MaAlias			*ap;
	MaLocation		*loc;
	char			*cp, *docRootPath;
	char			addrBuf[MPR_MAX_IP_ADDR_PORT], pathBuf[MPR_MAX_FNAME];
	int				port;

	mprLog(MPR_CONFIG, "Configuration via Command Line\n");

#if BLD_FEATURE_ROMFS
	mprLog(MPR_CONFIG, "Server Root \"%s\" in ROM\n", serverRoot);
	docRootPath = mprStrdup(docRoot);
#else
	//
	//	Set the document root. Is relative to the server root unless an absolute path is used.
	//	
#if WIN
	if (*docRoot != '/' && docRoot[1] != ':' && docRoot[2] != '/') 
#elif WINCE
	if (*docRoot != '\\' && docRoot != '/')
#else
	if (*docRoot != '/')
#endif
	{
        if (*docRoot) {
            mprAllocSprintf(&docRootPath, MPR_MAX_FNAME, "%s/%s", serverRoot, docRoot);
        } else {
            docRootPath = mprStrdup(serverRoot);
        }
	} else {
		docRootPath = mprStrdup(docRoot);
	}
#endif // BLD_FEATURE_ROMFS

	mprLog(MPR_CONFIG, "Document Root \"%s\"\n", docRootPath);

	//
	//	Setup the listening addresses. If only a port is specified, listen on
	//	all interfaces. If only the IP address is specified without a port,
	//	then default to port 80. IF autoScan is on, scan for a free port
	//	starting from the base address.
	//
	listens = server->getListens();

	port = MA_SERVER_DEFAULT_PORT_NUM;
	if ((cp = strchr(ipAddr, ':')) != 0) {
		*cp++ = '\0';
		port = atoi(cp);
		if (port <= 0 || port > 65535) {
			mprError(MPR_L, MPR_USER, "Bad listen port number %d", port);
			return MPR_ERR_BAD_SYNTAX;
		}
		if (autoScan) {
			port = findFreePort(ipAddr, port);
		}
		listens->insert(new MaListen(ipAddr, port, 0));

	} else {
		if (isdigit((uchar) *ipAddr) && strchr(ipAddr, '.') == 0) {
			port = atoi(ipAddr);
			if (port <= 0 || port > 65535) {
				mprError(MPR_L, MPR_USER, "Bad listen port number %d", port);
				return MPR_ERR_BAD_SYNTAX;
			}
			if (autoScan) {
				port = findFreePort("", port);
			}
			listens->insert(new MaListen("", port));

		} else {
			if (autoScan) {
				port = findFreePort(ipAddr, MA_SERVER_DEFAULT_PORT_NUM);
			}
			listens->insert(new MaListen(ipAddr, port));
		}
	}
	mprFree(ipAddr);
	ipAddr = 0;

	host = server->newHost(docRootPath);
	if (host == 0) {
		return MPR_ERR_CANT_OPEN;
	}

	//
	//	Add the default server listening addresses to the HostAddress hash.
	//	FUTURE -- this should be moved into newHost
	//
	hostAddresses = server->getHostAddresses();
	lp = (MaListen*) listens->getFirst();
	while (lp) {
		mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", lp->getIpAddr(), 
			lp->getPort());
		address = (MaHostAddress*) hostAddresses->lookup(addrBuf);
		if (address == 0) {
			address = new MaHostAddress(addrBuf);
			hostAddresses->insert(address);
		}
		mprLog(MPR_CONFIG, "Listening for HTTP on %s\n", addrBuf);
		address->insertVhost(new MaVhost(host));
		lp = (MaListen*) listens->getNext(lp);
		mprFree(ipAddr);
		ipAddr = mprStrdup(addrBuf);
	}

	//
	//	Setup a module search path that works for production and developement.
	//
#if BLD_FEATURE_DLL
	char	searchPath[MPR_MAX_FNAME];
	mprSprintf(searchPath, sizeof(searchPath), 
			"./lib ../lib ../lib/modules ../../lib ../../lib/modules %s/lib", BLD_PREFIX);
	host->setModuleDirs(searchPath);
#endif

	//
	//	Load all possible modules
	//
#if BLD_FEATURE_AUTH_MODULE
	//
	//	Handler must be added first to authorize all requests.
	//
	if (server->loadModule("auth") == 0) {
		host->addHandler("authHandler", "");
	}
#endif
#if BLD_FEATURE_UPLOAD_MODULE
	//
	//	Must be after auth and before ESP, EGI.
	//
	if (server->loadModule("upload") == 0) {
		host->addHandler("uploadHandler", "");
	}
#endif
#if BLD_FEATURE_CGI_MODULE
	if (server->loadModule("cgi") == 0) {
		host->addHandler("cgiHandler", ".cgi .cgi-nph .bat .cmd .pl .py");
	}
#endif
#if BLD_FEATURE_EGI_MODULE
	if (server->loadModule("egi") == 0) {
		host->addHandler("egiHandler", ".egi");
	}
#endif
#if BLD_FEATURE_ESP_MODULE
	if (server->loadModule("esp") == 0) {
		host->addHandler("espHandler", ".esp .asp");
	}
#endif
#if BLD_FEATURE_C_API_MODULE
	server->loadModule("capi");
#endif
#if BLD_FEATURE_GACOMPAT_MODULE
	server->loadModule("compat");
#endif
#if BLD_FEATURE_SSL_MODULE
	server->loadModule("ssl");
#endif
	//
	//	Only load one of matrixSsl / openssl
	//
#if BLD_FEATURE_OPENSSL_MODULE
	server->loadModule("openSsl");
#elif BLD_FEATURE_MATRIXSSL_MODULE
	server->loadModule("matrixSsl");
#endif
#if BLD_FEATURE_PHP5_MODULE
	if (server->loadModule("php5") == 0) {
		host->addHandler("php5Handler", ".php");
	}
#endif
#if BLD_FEATURE_COPY_MODULE
	//
	//	Handler must be added last to be the catch all
	//
	if (server->loadModule("copy") == 0) {
		host->addHandler("copyHandler", "");
	}
#endif

	//
	//	Create the top level directory
	//
	dir = new MaDir(host);
	dir->setPath(docRootPath);
	host->insertDir(dir);

	//
	//	Add cgi-bin
	//
	mprSprintf(pathBuf, sizeof(pathBuf), "%s/cgi-bin", serverRoot);
	ap = new MaAlias("/cgi-bin/", pathBuf);
	mprLog(4, "ScriptAlias \"/cgi-bin/\":\n\t\t\t\"%s\"\n", pathBuf);
	host->insertAlias(ap);
	loc = new MaLocation(dir->getAuth());
	loc->setPrefix("/cgi-bin/");
	loc->setHandler("cgiHandler");
	host->insertLocation(loc);

	mprFree(docRootPath);
	return 0;
}
コード例 #10
0
ファイル: ejsAppweb.c プロジェクト: jsjohnst/appweb
static int parseUrl(MaConn *conn)
{
    EjsWeb          *web;
    EjsWebControl   *control;
    MaRequest       *req;
    MaResponse      *resp;
    MaAlias         *alias;
    MaLocation      *location;
    char            *baseDir, *cp, *url, *baseUrl;
    int             flags, locFlags;

    resp = conn->response;
    req = conn->request;
    alias = req->alias;
    location = req->location;
    locFlags = location->flags;
    url = req->url;
    
    flags = 0;
    if (locFlags & MA_LOC_APP_DIR) {
        flags |= EJS_WEB_FLAG_APP;
        mprAllocSprintf(resp, &baseDir, -1, "%s%s", alias->filename, &req->url[alias->prefixLen]);
        if ((cp = strchr(&baseDir[strlen(alias->filename) + 1], '/')) != 0) {
            *cp = '\0';
        }
        mprAllocSprintf(resp, &baseUrl, -1, "%s%s", alias->prefix, &req->url[alias->prefixLen]);
        if ((cp = strchr(&baseUrl[alias->prefixLen + 1], '/')) != 0) {
            *cp = '\0';
        }
        if (*url) {
            /* Step over the directory and app name */
            while (*++url != '/') ;
            if (*url) {
                while (*++url != '/') ;
            }
        }
            
    } else {
        if (locFlags & MA_LOC_APP) {
            flags |= EJS_WEB_FLAG_APP;
        }
        baseDir = alias->filename;
        if (alias->prefixLen > 0) {
            /* Step over the application name (same as alias prefix) */
            url = &url[alias->prefixLen];
            if (*url != '/' && url[-1] == '/') {
                url--;
            }
        }
        baseUrl = alias->prefix;
    }
    
    if (location->flags & MA_LOC_BROWSER) {
        flags |= EJS_WEB_FLAG_BROWSER_ERRORS;
    }
    if (location->flags & MA_LOC_AUTO_SESSION) {
        flags |= EJS_WEB_FLAG_SESSION;
    }

    control = conn->http->ejsHandler->stageData;
    web = ejsCreateWebRequest(req, control, conn, baseUrl, url, baseDir, flags);
    if (web == 0) {
        maFailRequest(conn, MPR_HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't create Ejs web object for %s", req->url);
        return EJS_ERR;
    }
    resp->handlerData = web;

    return 0;
}
コード例 #11
0
ファイル: cgiHandler.cpp プロジェクト: embedthis/appweb-2
int MaCgiHandler::run(MaRequest *rq)
{
	MprVar		*vp, *variables;
	char		**argv, **envv, **ep, *fileName, *baseName;
	int			i, index, argc, numItems;

	if (rq->getFlags() & MPR_HTTP_POST_REQUEST && rq->getRemainingContent() > 0) {
		//
		//	When all the post data is received the run method will be recalled
		//	by the postData method.
		//
		return MPR_HTTP_HANDLER_FINISHED_PROCESSING;
	}

	argv = 0;
	variables = 0;
	argc = 0;

	hitCount++;
	rq->setResponseCode(200);
	rq->setHeaderFlags(MPR_HTTP_DONT_CACHE, 0);
	rq->insertDataStream(rq->getDynBuf());

	//
	//	Build the commmand line arguments
	//
	argc = 1;									// argv[0] == programName
	buildArgs(&argc, &argv, cmd, rq);
	fileName = argv[0];

	rq->setResponseMimeType("text/html");

	baseName = mprGetBaseName(fileName);
	if (strncmp(baseName, "nph-", 4) == 0) {
		cgiFlags |= MPR_CGI_NON_PARSED_HEADER;
	}
	if (strlen(baseName) > 4 && 
			strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0) {
		cgiFlags |= MPR_CGI_NON_PARSED_HEADER;
	}

	//
	//	Build environment variables
	//
	variables = rq->getVariables();
	numItems = rq->getNumEnvProperties() + 1;

	//
	//	Export the PATH and LD_LIBRARY_PATH also if Unix
	//
#if BLD_HOST_UNIX
	numItems += 2;
#endif
	envv = (char**) mprMalloc((numItems + 1) * sizeof(char*));

	index = 0;
	for (i = 0; i < MA_HTTP_OBJ_MAX; i++) {
		if (variables[i].type == MPR_TYPE_OBJECT) {
			vp = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA);
			while (vp) {
				mprAllocSprintf(&envv[index], MPR_HTTP_MAX_HEADER, "%s=%s", 
					vp->name, vp->string);
				index++;
				vp = mprGetNextProperty(&variables[i], vp, MPR_ENUM_DATA);
			}
		}
	}

#if BLD_HOST_UNIX
{
	char	*cp;
	if ((cp = getenv("PATH")) != 0) {
		mprAllocSprintf(&envv[index++], MPR_MAX_FNAME, "PATH=%s", cp);
	}
	if ((cp = getenv("LD_LIBRARY_PATH")) != 0) {
		mprAllocSprintf(&envv[index++], MPR_MAX_FNAME, "LD_LIBRARY_PATH=%s", cp);
	}
}
#endif
    mprAllocSprintf(&envv[index++], MPR_MAX_FNAME, "REDIRECT_STATUS=302");

	envv[index] = 0;
	mprAssert(index <= numItems);

	mprLog(4, log, "%d: running program: %s\n", rq->getFd(), fileName);

	if (cmd->start(fileName, argv, envv, cgiOutputData, (void*) rq, 
			MPR_CMD_CHDIR) < 0) {
		rq->requestError(503, "Can't run CGI process: %s, URI %s",
			rq->getScriptName(), rq->getOriginalUri());
		rq->finishRequest();
		goto exit;
	}

exit:
	for (i = 0; i < argc; i++) {
		mprFree(argv[i]);
	}
	for (ep = envv; *ep; ep++) {
		mprFree(*ep);
	}
	mprFree(argv);
	mprFree(envv);

	return MPR_HTTP_HANDLER_FINISHED_PROCESSING;
}