Пример #1
0
void ejsLexRestoreInputState(Ejs *ep, EjsInput *state)
{
	EjsInput	*ip;
	int			i;

	mprAssert(ep);
	mprAssert(state);

	ip = ep->input;
	mprAssert(ip);

	ip->tokbuf = state->tokbuf;
	ip->tokServp = state->tokServp;
	ip->tokEndp = state->tokEndp;
	ip->tokSize = state->tokSize;

	ip->script = state->script;
	ip->scriptServp = state->scriptServp;
	ip->scriptSize = state->scriptSize;

	ip->putBackIndex = state->putBackIndex;
	for (i = 0; i < ip->putBackIndex; i++) {
		mprFree(ip->putBack[i].token);
		ip->putBack[i].id = state->putBack[i].id;
		ip->putBack[i].token = mprStrdup(state->putBack[i].token);
	}

	mprFree(ip->line);
	ip->line = mprMalloc(state->lineLength);
	mprStrcpy(ip->line, state->lineLength, state->line);

	ip->lineColumn = state->lineColumn;
	ip->lineNumber = state->lineNumber;
	ip->lineLength = state->lineLength;
}
Пример #2
0
int MprBuf::grow()
{
	uchar	*newbuf;

	if (maxsize >= 0 && buflen >= maxsize) {
		return 0;
	}
	if (growBy < 0) {
		//
		//	User supplied buffer
		//
		return 0;
	}

	newbuf = (uchar*) mprMalloc(buflen + growBy);
	if (buf) {
		memcpy(newbuf, buf, buflen);
		mprFree(buf);
	}

	buflen += growBy;
	end = newbuf + (end - buf);
	start = newbuf + (start - buf);
	buf = newbuf;
	endbuf = &buf[buflen];

	//
	//	Increase growBy to reduce overhead
	//
	growBy *= 2;
	return 1;
}
Пример #3
0
void ejsLexSaveInputState(Ejs *ep, EjsInput *state)
{
	EjsInput	*ip;
	int			i;

	mprAssert(ep);

	ip = ep->input;
	mprAssert(ip);

	*state = *ip;

	for (i = 0; i < ip->putBackIndex; i++) {
		state->putBack[i].token = mprStrdup(ip->putBack[i].token);
		state->putBack[i].id = ip->putBack[i].id;
	}
	for (; i < EJS_TOKEN_STACK; i++) {
		state->putBack[i].token = 0;
	}

	state->line = mprMalloc(ip->lineLength);
	mprStrcpy(state->line, ip->lineLength, ip->line);

	state->lineColumn = ip->lineColumn;
	state->lineNumber = ip->lineNumber;
	state->lineLength = ip->lineLength;
}
Пример #4
0
static DynLock *sslCreateDynLock(const char *file, int line)
{
	DynLock		*dl;

	dl = (DynLock*) mprMalloc(sizeof(DynLock));
	dl->mutex = new MprMutex();
	return dl;
}
Пример #5
0
int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args)
{
	char	*buf;
	int		count;

	buf = mprMalloc(maxSize + 1);
	count = mtVsprintf(buf, maxSize, fmt, args);
	*msgbuf = buf;
	return count;
}
Пример #6
0
MprArray *mprCreateArray()
{
	MprArray	*array;
	int			size;

	array = (MprArray*) mprMalloc(sizeof(MprArray));
	if (array == 0) {
		return 0;
	}
	memset(array, 0, sizeof(MprArray));

	size = MPR_ARRAY_INCR * sizeof(void*);
	array->handles = (void**) mprMalloc(size);
	if (array->handles == 0) {
		mprFree(array);
		return 0;
	}
	memset(array->handles, 0, size);
	array->max = MPR_ARRAY_INCR;
	array->used = 0;
	return array;
}
Пример #7
0
int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...)
{
	va_list	args;
	char	*buf;
	int		count;

	va_start(args, fmt);
	buf = mprMalloc(maxSize + 1);
	count = mtVsprintf(buf, maxSize, fmt, args);
	*msgbuf = buf;
	va_end(args);
	return count;
}
Пример #8
0
////////////////////////////////////////////////////////////////////////////////
//
//	This is called from Http::start after all the modules are loaded.
//	The code here is global for this handler and is not required per handler
//	instance.
//
int MaOpenSslModule::start()
{
	RandBuf		randBuf;
	static int	once = 0;

	//
	//	Depending on the order in the configuration file, we will get called 
	//	by the module mechanism and by OpenSslConfig::start(). But we only 
	//	want to run once.
	//
	if (once++ > 0) {
		return 0;
	}
	randBuf.pid = getpid();
	randBuf.time = (int) time(0);
	randBuf.msec = (int) mprGetTime(0);
	RAND_seed((void*) &randBuf, sizeof(randBuf));

#if SOLARIS || LINUX || MACOSX || FREEBSD
	mprLog(6, "OpenSsl: Before calling RAND_load_file\n");
	RAND_load_file("/dev/urandom", 256);
	mprLog(6, "OpenSsl: After calling RAND_load_file\n");
#endif

#if BLD_FEATURE_MULTITHREAD
	numLocks = CRYPTO_num_locks();
	locks = (MprMutex**) mprMalloc(numLocks * sizeof(MprMutex*));
	for (int i = 0; i < numLocks; i++) {
		locks[i] = new MprMutex();
	}
	CRYPTO_set_id_callback(sslThreadId);
	CRYPTO_set_locking_callback(sslStaticLock);

	CRYPTO_set_dynlock_create_callback(sslCreateDynLock);
	CRYPTO_set_dynlock_destroy_callback(sslDestroyDynLock);
	CRYPTO_set_dynlock_lock_callback(sslDynLock);
#endif

#if WIN
	// _fmode=_O_BINARY;
	//	CRYPTO_malloc_init();
	//	SSLC_add_all_algorithms();
#else
	OpenSSL_add_all_algorithms();
#endif

	SSL_library_init();
	return 0;
}
Пример #9
0
int ejsLexOpenScript(Ejs *ep, char *script)
{
	EjsInput	*ip;

	mprAssert(ep);
	mprAssert(script);

	if ((ip = mprMalloc(sizeof(EjsInput))) == NULL) {
		return -1;
	}
	memset(ip, 0, sizeof(*ip));
	ip->next = ep->input;
	ep->input = ip;
	ip->procName = ep->proc?ep->proc->procName:NULL;

/*
 *	Create the parse token buffer and script buffer
 */
	ip->tokbuf = mprMalloc(EJS_PARSE_INCR);
	ip->tokSize = EJS_PARSE_INCR; 
	ip->tokServp = ip->tokbuf;
	ip->tokEndp = ip->tokbuf;

	ip->script = mprStrdup(script);
	ip->scriptSize = strlen(script);
	ip->scriptServp = ip->script;

	ip->lineNumber = 1;
	ip->lineLength = 0;
	ip->lineColumn = 0;
	ip->line = NULL;

	ip->putBackIndex = -1;

	return 0;
}
Пример #10
0
void MprBuf::setBuf(int initialSize, int max)
{
	mprAssert(initialSize > 0);
	if (buf && growBy > 0) {
		mprFree(buf);
	}
	buf = (uchar*) mprMalloc(initialSize);
	growBy = initialSize;
	maxsize = max;
	buflen = initialSize;
	endbuf = &buf[buflen];
	start = buf;
	end = buf;
	*start = '\0';
}
Пример #11
0
int mprReadRegistry(char *key, char *name, char **buf, int max)
{
	HKEY		top, h;
	char		*value;
	ulong		type, size;

	mprAssert(key && *key);
	mprAssert(buf);

	//
	//	Get the registry hive
	// 
	if ((key = getHive(key, &top)) == 0) {
		return MPR_ERR_CANT_ACCESS;
	}

	if (RegOpenKeyEx(top, key, 0, KEY_READ, &h) != ERROR_SUCCESS) {
		return MPR_ERR_CANT_ACCESS;
	}

	//
	//	Get the type
	// 
	if (RegQueryValueEx(h, name, 0, &type, 0, &size) != ERROR_SUCCESS) {
		RegCloseKey(h);
		return MPR_ERR_CANT_READ;
	}
	if (type != REG_SZ && type != REG_EXPAND_SZ) {
		RegCloseKey(h);
		return MPR_ERR_BAD_TYPE;
	}

	value = (char*) mprMalloc(size);
	if ((int) size > max) {
		RegCloseKey(h);
		return MPR_ERR_WONT_FIT;
	}
	if (RegQueryValueEx(h, name, 0, &type, (uchar*) value, &size) != 
			ERROR_SUCCESS) {
		delete value;
		RegCloseKey(h);
		return MPR_ERR_CANT_READ;
	}

    RegCloseKey(h);
	*buf = value;
	return 0;
}
Пример #12
0
int MprCmd::start(char *program, char **argv, char **envp, 
	MprCmdProc completionFn, void *fnData, int userFlags)
{
	PROCESS_INFORMATION	procInfo;
	STARTUPINFO			startInfo;
	char				dirBuf[MPR_MAX_FNAME], *systemRoot;
	char				*envBuf, **ep, *cmdBuf, **ap, *destp, *cp, *dir, *key;
	char				progBuf[MPR_MAX_STRING], *localArgv[2], *saveArg0;
	int					argc, len, inheritFiles;

	mprAssert(program);
	mprAssert(argv);

	reset();

	flags |= (userFlags & MPR_CMD_USER_FLAGS);
	exitStatus = -1;

	mprStrcpy(progBuf, sizeof(progBuf), program);
	progBuf[sizeof(progBuf) - 1] = '\0';
	program = progBuf;

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

	saveArg0 = argv[0];
	if (argv == 0) {
		argv = localArgv;
		argv[1] = 0;
	}
	argv[0] = program;

	//
	//	Determine the command line length and arg count
	//
	argc = 0;
	for (len = 0, ap = argv; *ap; ap++) {
		len += strlen(*ap) + 1 + 2;			// Space and possible quotes
		argc++;
	}
	cmdBuf = (char*) mprMalloc(len + 1);
	cmdBuf[len] = '\0';
	
	//
	//	Add quotes to all args that have spaces in them including "program"
	//
	destp = cmdBuf;
	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';
	mprAssert((int) strlen(destp) < (len - 1));
	mprAssert(cmdBuf[len] == '\0');
	argv[0] = saveArg0;

	envBuf = 0;
	if (envp) {
		for (len = 0, ep = envp; *ep; ep++) {
			len += strlen(*ep) + 1;
		}

		key = "SYSTEMROOT";
		systemRoot = getenv(key);
		if (systemRoot) {
			len += strlen(key) + 1 + strlen(systemRoot) + 1;
		}

		envBuf = (char*) mprMalloc(len + 2);		// Win requires two nulls
		destp = envBuf;
		for (ep = envp; *ep; ep++) {
			strcpy(destp, *ep);
			mprLog(6, log, "Set CGI variable: %s\n", destp);
			destp += strlen(*ep) + 1;
		}

		strcpy(destp, key);
		destp += strlen(key);
		*destp++ = '=';
		strcpy(destp, systemRoot);
		destp += strlen(systemRoot) + 1;

		*destp++ = '\0';
		*destp++ = '\0';						// WIN requires two nulls
	}
	
	memset(&startInfo, 0, sizeof(startInfo));
	startInfo.cb = sizeof(startInfo);

    startInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	if (flags & MPR_CMD_SHOW) {
		startInfo.wShowWindow = SW_SHOW;
	} else {
		startInfo.wShowWindow = SW_HIDE;
	}

	//
	//	CMD_OUT is stdin for the client. CMD_IN is stdout for the client
	//
	if (files.clientFd[MPR_CMD_OUT] > 0) {
		startInfo.hStdInput = 
			(HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_OUT]);
	}
	if (files.clientFd[MPR_CMD_IN] > 0) {
		startInfo.hStdOutput = 
			(HANDLE)_get_osfhandle(files.clientFd[MPR_CMD_IN]);
	}
#if UNUSED
	if (files.clientFd[MPR_CMD_ERR] > 0) {
		startInfo.hStdError = 
			(HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_ERR]);
	}
#endif

#if UNUSED
	SECURITY_ATTRIBUTES	secAtt;
	memset(&secAtt, 0, sizeof(secAtt));
	secAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
	secAtt.bInheritHandle = TRUE;
#endif

	if (userFlags & MPR_CMD_CHDIR) {
		if (cwd) {
			dir = cwd;
		} else {
			mprGetDirName(dirBuf, sizeof(dirBuf), argv[0]);
			dir = dirBuf;
		}
	} else {
		dir = 0;
	}

	inheritFiles = (flags & MPR_CMD_STDIO_MADE) ? 1 : 0;
	flags &= ~(MPR_CMD_STDIO_MADE);

	mprLog(5, log, "Running: %s\n", cmdBuf); 

	if (! CreateProcess(0, cmdBuf, 0, 0, inheritFiles, CREATE_NEW_CONSOLE,
			envBuf, dir, &startInfo, &procInfo)) {
		mprError(MPR_L, MPR_LOG, "Can't create process: %s, %d", 
			cmdBuf, mprGetOsError());
		return MPR_ERR_CANT_CREATE;
	}
	process = (int) procInfo.hProcess;

	//
	//	Wait for the child to initialize
	//
	WaitForInputIdle((HANDLE) process, 1000);

	if (procInfo.hThread != 0)  {
		CloseHandle(procInfo.hThread);
	}

	mprFree(cmdBuf);
	mprFree(envBuf);

	cmdDoneProc = completionFn;
	data = fnData;

	if (flags & MPR_CMD_DETACHED) {
		CloseHandle((HANDLE) process);
		process = 0;

	} else if (userFlags & MPR_CMD_WAIT) {
		waitForChild(INT_MAX);
		if (getExitCode() < 0) {
			return MPR_ERR_BAD_STATE;
		}
		return exitStatus;

	} else {
		mprGetMpr()->cmdService->startWatcher();
	}


	return 0;
}
Пример #13
0
static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, 
	const char *delim, const char *src, va_list args)
{
	va_list		ap;
	char		*dest, *dp;
	const char *str;
	int			sepLen, addBytes, required;

	mprAssert(destp);
	mprAssert(destMax > 0);
	mprAssert(src);

	dest = *destp;
	sepLen = (delim) ? strlen(delim) : 0;

	va_copy(ap, args);
	addBytes = 0;
	str = src;
	while (str) {
		addBytes += strlen(str) + sepLen;
		str = va_arg(ap, const char*);
	}
	va_end(ap);

	if (existingLen > 0) {
		addBytes += sepLen;
	}
	required = existingLen + addBytes + 1;
	if (required >= destMax) {
		mprAssert(0);
		return MPR_ERR_WONT_FIT;
	}

	if (alloc) {
		if (dest == 0) {
			dest = (char*) mprMalloc(required);
		} else {
			dest = (char*) mprRealloc(dest, required);
		}
	} else {
		dest = (char*) *destp;
	}

	dp = &dest[existingLen];
	if (delim) {
		strcpy(dp, delim);
		dp += sepLen;
	}

	if (addBytes > 0) {
		va_copy(ap, args);
		str = src;
		while (str) {
			strcpy(dp, str);
			dp += strlen(str);
			str = va_arg(ap, char*);
			if (delim && str) {
				strcpy(dp, delim);
				dp += sepLen;
			}
		}
		va_end(ap);
	} else if (dest == 0) {
Пример #14
0
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;
}
Пример #15
0
//
//	Algorithm originally in the GoAhead WebServer.
//
int MaUrl::parse(char *url)
{
	char	*tok, *cp, *portStr, *last_delim, *hostbuf, *portbuf;
	char 	*htmlExt = "html";
	int		c, len, ulen;

	mprAssert(url && *url);

	if (parsedUrlBuf) {
		mprFree(parsedUrlBuf);
	}

	ulen = strlen(url);

	//
	//	Allocate a single buffer to hold all the cracked fields.
	//	Store host, port and url strings (3 nulls).
	//
	len = ulen * 2 + MAX_PORT_LEN + 3;
	parsedUrlBuf = (char*) mprMalloc(len * sizeof(char));
	portbuf = &parsedUrlBuf[len - MAX_PORT_LEN - 1];
	hostbuf = &parsedUrlBuf[ulen+1];
	strcpy(parsedUrlBuf, url);
	url = parsedUrlBuf;

	//
	//	Defaults for missing ULR fields
	//
	strcpy(portbuf, "80");
	portStr = portbuf;
	uri = "/";
	proto = "http";
	host = "localhost";
	query = "";
	ext = htmlExt;

	if (strncmp(url, "http://", 7) == 0) {
		tok = &url[7];
		tok[-3] = '\0';
		proto = url;
		host = tok;
		for (cp = tok; *cp; cp++) {
			if (*cp == '/') {
				break;
			}
			if (*cp == ':') {
				*cp++ = '\0';
				portStr = cp;
				tok = cp;
			}
		}
		if ((cp = strchr(tok, '/')) != NULL) {
			c = *cp;
			*cp = '\0';
			mprStrcpy(hostbuf, ulen + 1, host);
			mprStrcpy(portbuf, MAX_PORT_LEN, portStr);
			*cp = c;
			host = hostbuf;
			portStr = portbuf;
			uri = cp;
			tok = cp;
		}

	} else {
		uri = url;
		tok = url;
	}

	//
	//	Split off the query string.
	//
	if ((cp = strchr(tok, '?')) != NULL) {
		*cp++ = '\0';
		query = cp;
		uri = tok;
		tok = query;
	}

	//
	//	Split off fragment identifier.
	// 
	if ((cp = strchr(tok, '#')) != NULL) {
		*cp++ = '\0';
		if (*query == 0) {
			uri = tok;
		}
	}

	//
	//	FUTURE -- this logic could be improved
	//
	if ((cp = strrchr(uri, '.')) != NULL) {
		if ((last_delim = strrchr(uri, '/')) != NULL) {
			if (last_delim > cp) {
				ext = htmlExt;
			} else {
				ext = cp + 1;
#if WIN
				mprStrLower(ext);
#endif
			}
		} else {
			ext = cp + 1;
#if WIN
			mprStrLower(ext);
#endif
		}
	} else {
		if (uri[strlen(uri) - 1] == '/') {
			ext = htmlExt;
		}
	}

	port = atoi(portStr);
	return 0;
}
Пример #16
0
struct hostent *mprGetHostByName(char *name)
{
	Mpr				*mpr;
	struct hostent	*hp;

	mpr = mprGetMpr();
	hp = new hostent;
	memset(hp, 0, sizeof(struct hostent));

	mpr->lock();

#if VXWORKS
	struct in_addr inaddr;
	inaddr.s_addr = (ulong) hostGetByName(name);
	if (inaddr.s_addr < 0) {
		mpr->unlock();
		mprAssert(0);
		return 0;
	}
	hp->h_addrtype = AF_INET;
	hp->h_length = sizeof(int);
	hp->h_name = mprStrdup(name);
	hp->h_addr_list = 0;
	hp->h_aliases = 0;

	hp->h_addr_list = new char*[2];
	hp->h_addr_list[0] = (char *) mprMalloc(sizeof(struct in_addr));
	memcpy(&hp->h_addr_list[0], &inaddr, hp->h_length);
	hp->h_addr_list[1] = 0;

#else
	struct hostent	*ip;
	int				count, i;

	#undef gethostbyname
	ip = gethostbyname(name);
	if (ip == 0) {
		mpr->unlock();
		return 0;
	}
	hp->h_addrtype = ip->h_addrtype;
	hp->h_length = ip->h_length;
	hp->h_name = mprStrdup(ip->h_name);
	hp->h_addr_list = 0;
	hp->h_aliases = 0;

	for (count = 0; ip->h_addr_list[count] != 0; ) {
		count++;
	}
	if (count > 0) {
		count++;
		hp->h_addr_list = new char*[count];
		for (i = 0; ip->h_addr_list[i] != 0; i++) {
			memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length);
		}
		hp->h_addr_list[i] = 0;
	}

	for (count = 0; ip->h_aliases[count] != 0; ) {
		count++;
	}
	if (count > 0) {
		count++;
		hp->h_aliases = new char*[count];
		for (i = 0; ip->h_aliases[i] != 0; i++) {
			hp->h_aliases[i] = mprStrdup(ip->h_aliases[i]);
		}
		hp->h_aliases[i] = 0;
	}
#endif
	mpr->unlock();
	return hp;
}
Пример #17
0
EspRequest *espCreateRequest(EspHandle webServerRequestHandle, char *uri, 
	MprVar *variables)
{
	EspRequest	*ep;
	MprVar		*global;
#if BLD_FEATURE_LEGACY_API
	MprVar		*np;
	char		keyBuf[ESP_MAX_HEADER];
	int			i;
#endif

	mprAssert(variables);

	ep = (EspRequest*)mprMalloc(sizeof(EspRequest));
	if (ep == 0) {
		return 0;
	}
	memset(ep, 0, sizeof(EspRequest));
	ep->requestHandle = webServerRequestHandle;
	ep->esp = esp;
	ep->uri = mprStrdup(uri);
	ep->docPath = 0;
	ep->variables = variables;
	
	/*
 	 *	The handle passed to ejsOpenEngine is passed to every C function 
	 *	called by JavaScript.
	 */
	ep->eid = ejsOpenEngine((EjsHandle) ep, (EjsHandle) webServerRequestHandle);
	if (ep->eid < 0) {
		mprFree(ep);
		return 0;
	}

	/*
	 *	All these copies and SetProperties will only copy references 
	 *	They will increments the object ref counts.
	 */
	mprCopyVar(&variables[ESP_GLOBAL_OBJ], ejsGetGlobalObject(ep->eid), 
		MPR_SHALLOW_COPY);
	mprCopyVar(&variables[ESP_LOCAL_OBJ], ejsGetLocalObject(ep->eid), 
		MPR_SHALLOW_COPY);

	global = &variables[ESP_GLOBAL_OBJ];
	mprCreateProperty(global, "application", &variables[ESP_APPLICATION_OBJ]);
	mprCreateProperty(global, "cookies", &variables[ESP_COOKIES_OBJ]);
	mprCreateProperty(global, "files", &variables[ESP_FILES_OBJ]);
	mprCreateProperty(global, "form", &variables[ESP_FORM_OBJ]);
	mprCreateProperty(global, "headers", &variables[ESP_HEADERS_OBJ]);
	mprCreateProperty(global, "request", &variables[ESP_REQUEST_OBJ]);

	//
	//	FUTURE -- could server be shared across all requests for a given host
	//	and be made read-only.
	//
	mprCreateProperty(global, "server", &variables[ESP_SERVER_OBJ]);

#if BLD_FEATURE_SESSION
	mprCreateProperty(global, "session", &variables[ESP_SESSION_OBJ]);
#endif

#if BLD_FEATURE_LEGACY_API
	/*
	 *	DEPRECATED: 2.0
	 *	Define variables as globals. headers[] are prefixed with "HTTP_".
 	 *	NOTE: MaRequest::setVar does not copy into globals, whereas espSetVar
	 *	does if legacy_api is defined. So variables pre-defined by MaRequest 
 	 *	must be copied here into globals[].
	 *
	 *	NOTE: if a variable is in session[] and in form[], the form[] will
	 *	override being later in the variables[] list. Use mprSetProperty 
	 *	instead of mprCreateProperty to cover for this case.
	 */
	for (i = 0; i < ESP_OBJ_MAX; i++) {
		if (i == ESP_GLOBAL_OBJ || i == ESP_LOCAL_OBJ) {
			continue;
		}
		if (variables[i].type != MPR_TYPE_OBJECT) {
			continue;
		}
		np = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA);
		while (np) {
			if (i == ESP_HEADERS_OBJ) {
				mprSprintf(keyBuf, sizeof(keyBuf) - 1, "HTTP_%s", np->name);
				mprSetProperty(global, keyBuf, np);
			} else {
				mprSetProperty(global, np->name, np);
			}
			np = mprGetNextProperty(&variables[i], np, MPR_ENUM_DATA);
		}
	}
#endif
	return ep;
}
Пример #18
0
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;
}
Пример #19
0
static int fetch(MaClient *client, char *method, char *url, char *data, int len)
{
	struct stat	sbuf;
	FILE		*fp;
	MaUrl		*parsedUrl;
	char		*header, *content, *diffBuf, *msg;
	char		path[MPR_MAX_PATH], dir[MPR_MAX_PATH], urlBuf[MPR_HTTP_MAX_URL];
	char		tmp[MPR_MAX_PATH];
	int			i, code, rc, contentLen, mark, elapsed, c;

	fp = 0;

	lock();
	fetchCount++;
	unlock();

	if (url == 0) {
		return MPR_ERR_BAD_ARGS;
	}
	if (*url == '/') {
		mprSprintf(urlBuf, sizeof(urlBuf), "http://127.0.0.1%s", url);
		url = urlBuf;
	} else if ((strstr(url, "http://")) == 0) {
		mprSprintf(urlBuf, sizeof(urlBuf), "http://%s", url);
		url = urlBuf;
	}
	mprLog(MPR_DEBUG, tMod, "fetch: %s %s\n", method, url);
	mark = mprGetTime(0);

	if (mprStrCmpAnyCase(method, "GET") == 0) {
		rc = client->getRequest(url);

	} else if (mprStrCmpAnyCase(method, "HEAD") == 0) {
		rc = client->headRequest(url);

	} else if (mprStrCmpAnyCase(method, "OPTIONS") == 0) {
		rc = client->optionsRequest(url);

	} else if (mprStrCmpAnyCase(method, "POST") == 0) {
		rc = client->postRequest(url, data, len);

	} else if (mprStrCmpAnyCase(method, "TRACE") == 0) {
		rc = client->traceRequest(url);
	}

	if (rc < 0) {
		return MPR_ERR_CANT_OPEN;
	}

	code = client->getResponseCode();
	content = client->getResponseContent(&contentLen);
	header = client->getResponseHeader();
	msg = client->getResponseMessage();

	elapsed = mprGetTime(0) - mark;

	if (code == 200 || code == 302) {
		mprLog(6, tMod, "Response code %d, content len %d, header: \n%s\n", 
			code, contentLen, header);
	} else {
		mprLog(2, tMod, "Response code %d, content len %d, header: \n%s\n%s", 
			code, contentLen, header, content);
		mprError(MPR_L, MPR_USER, "Can't retrieve \"%s\" (%d), %s",
			url, code, msg);
		return MPR_ERR_CANT_READ;
	}

	if (cmpDir) {
		client->getParsedUrl(&parsedUrl);
		mprSprintf(path, sizeof(path), "%s%s", cmpDir, parsedUrl->uri);
		if (path[strlen(path) - 1] == '/') {
			path[strlen(path) - 1] = '\0';
		}
		if (stat(path, &sbuf) < 0) {
			mprError(MPR_L, MPR_USER, "Can't access %s", path);
			return MPR_ERR_CANT_ACCESS;
		}
		if (sbuf.st_mode & S_IFDIR) {
			strcpy(tmp, path);
			mprSprintf(path, sizeof(path), "%s/_DEFAULT_.html", tmp);
		}
		if (stat(path, &sbuf) < 0) {
			mprError(MPR_L, MPR_USER, "Can't access %s", path);
			return MPR_ERR_CANT_ACCESS;
		}
		if ((int) sbuf.st_size != contentLen) {
			mprError(MPR_L, MPR_USER, "Failed comparison for %s"
				"ContentLen %d, size %d\n", url, contentLen, sbuf.st_size);
			return MPR_ERR_CANT_ACCESS;
		}
		if ((fp = fopen(path, "r" MPR_BINARY)) == 0) {
			mprError(MPR_L, MPR_USER, "Can't open %s", path);
			return MPR_ERR_CANT_OPEN;
		}
		diffBuf = (char*) mprMalloc(contentLen);
		if ((int) fread(diffBuf, 1, contentLen, fp) != contentLen) {
			mprError(MPR_L, MPR_USER, "Can't read content from %s", path);
			return MPR_ERR_CANT_READ;
		}
		for (i = 0; i < contentLen; i++) {
			if (diffBuf[i] != content[i]) {
				mprError(MPR_L, MPR_USER, "Failed comparison for %s"
					"At byte %d: %x vs %x\n", i, 
					(uchar) diffBuf[i], (uchar) content[i]);
				return MPR_ERR_GENERAL;
			}
		}
		fclose(fp);
		mprFree(diffBuf);
	}

	if (writeDir) {
		client->getParsedUrl(&parsedUrl);
		mprSprintf(path, sizeof(path), "%s%s", writeDir, parsedUrl->uri);
		if (path[strlen(path) - 1] == '/') {
			path[strlen(path) - 1] = '\0';
		}
		mprGetDirName(dir, sizeof(dir), path);
		mprMakeDir(dir);
		if (stat(path, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) {
			strcpy(tmp, path);
			mprSprintf(path, sizeof(path), "%s/_DEFAULT_.html", tmp);
		}

		if ((fp = fopen(path, "w" MPR_BINARY)) == 0) {
			mprError(MPR_L, MPR_USER, "Can't open %s", path);
			return MPR_ERR_CANT_OPEN;
		}
		
		if (outputHeader) {
			if (fputs(header, fp) != EOF) {
				mprError(MPR_L, MPR_USER, "Can't write header to %s", path);
				return MPR_ERR_CANT_WRITE;
			}
			fputc('\n', fp);
		}
		if ((int) fwrite(content, 1, contentLen, fp) != contentLen) {
			mprError(MPR_L, MPR_USER, "Can't write content to %s", path);
			return MPR_ERR_CANT_WRITE;
		}
		fclose(fp);
	}

	lock();
	if (trace) {
		if (strstr(url, "http://") != 0) {
			url += 7;
		}
		if ((fetchCount % 100) == 1) {
			if (fetchCount == 1 || (fetchCount % 2500) == 1) {
				if (fetchCount > 1) {
					mprPrintf("\n");
				}
				mprPrintf(
					"   Count   Fd  Thread   Op  Code   Bytes  Time Url\n");
			}
			mprPrintf("%8d %4d %7s %4s %5d %7d %5.2f %s\n", fetchCount - 1,
				client->getFd(), 
#if BLD_FEATURE_MULTITHREAD
				mprGetCurrentThreadName(),
#else
				"",
#endif
				method, code, contentLen, elapsed / 1000.0, url);
		}
	}
	if (outputHeader) {
		mprPrintf("%s\n", header);
	}
	if (!quietMode) {
		for (i = 0; i < contentLen; i++) {
			if (!isprint((uchar) content[i]) && content[i] != '\n' && content[i] != '\r' && content[i] != '\t') {
				break;
			}
		}
		if (contentLen > 0) {
			if (i != contentLen && 0) {
				mprPrintf("Content has non-printable data\n");
			} else {
				// mprPrintf("Length of content %d\n", contentLen);
				for (i = 0; i < contentLen; i++) {
					c = (uchar) content[i];
					if (isprint((uchar) c) || isspace((uchar) c)) {
						putchar(content[i]);
					} else {
						mprPrintf("0x%x", c);
					}
				}
				fflush(stdout);
			}
		}
	}
	unlock();

	if (singleStep) {
		mprPrintf("Pause: ");
		read(0, (char*) &rc, 1);
	}

	return 0;
}
Пример #20
0
int MprTestSession::setupTests(MprTestResult *result, Mpr *mpr, int argc, 
	char *argv[], char *switches)
{
	char			switchBuf[80];
	char			*programName, *argp;
	int				errflg, c, i, l;
#if BLD_FEATURE_LOG
	char			*logSpec;
#endif

	this->mpr = mpr;
	programName = mprGetBaseName(argv[0]);
	errflg = 0;
#if BLD_FEATURE_LOG
	logSpec = "stdout:1";
	logger = new MprLogToFile();
#endif

	switchBuf[0] = '\0';
	mprStrcat(switchBuf, sizeof(switchBuf), 0, "cDeg:i:l:n:msT:t:v?", 
		switches, (void*) 0);
	MprCmdLine	cmdLine(argc, argv, switchBuf);

	while ((c = cmdLine.next(&argp)) != EOF) {
		switch(c) {
		case 'c':
			result->setContinueOnFailures(1);
			break;

		case 'D':
			mprSetDebugMode(1);
			result->setDebugOnFailures(1);
			break;

		case 'e':
			needEventsThread = 1;
			break;

		case 'g':
			testGroups->parse(argp);
			break;

		case 'i':
			iterations = atoi(argp);
			break;

		case 'l':
#if BLD_FEATURE_LOG
			logSpec = argp;
#endif
			break;

		case 'n':
			l = atoi(argp);
			if (l == 0) {
				sessionLevel = MPR_BASIC;
			} else if (l == 1) {
				sessionLevel = MPR_THOROUGH;
			} else {
				sessionLevel = MPR_DEDICATED;
			}
			break;

		case 'm':
			mprRequestMemStats(1);
			break;

		case 's':
			result->setSingleStep(1);
			break;

		case 't':
			i = atoi(argp);
			if (i <= 0 || i > 100) {
				mprFprintf(MPR_STDERR, "%s: Bad number of threads (0-100)\n", 
					programName);
				exit(2);
			
			}
#if BLD_FEATURE_MULTITHREAD
			numThreads = i;
#endif
			break;

		case 'T':
#if BLD_FEATURE_MULTITHREAD
			poolThreads = atoi(argp);
#endif
			break;

		case 'v':
			verbose++;
			break;

		default:
			//
			//	Ignore args we don't understand
			//
			break;

		case '?':
			errflg++;
			break;
		}
	}
	if (errflg) {
		mprFprintf(MPR_STDERR, 
			"usage: %s [-cDemsv] [-g groups] [-i iterations] "
			"[-l logSpec] [-n testLevel] [-T poolThreads] [-t threads]\n", 
			programName);
		exit(2);
	}

#if !BLD_FEATURE_MULTITHREAD
	needEventsThread = 0;
#endif

#if BLD_FEATURE_LOG
	mpr->addListener(logger);
	mpr->setLogSpec(logSpec);
#endif

	initSignals();

	this->argc = argc;
	this->argv = argv;
	this->firstArg = cmdLine.firstArg();

#if BLD_FEATURE_MULTITHREAD
	mpr->setMaxPoolThreads(poolThreads);
#endif
	if (mpr->start(needEventsThread ? MPR_SERVICE_THREAD : 0) < 0) {
		return MPR_ERR_CANT_INITIALIZE;
	}

	result->adjustThreadCount(numThreads);
	result->setVerbosity(verbose);
	if (result->getListenerCount() == 0) {
		result->addListener(new MprTestListener("__default__"));
	}

	if (verbose) {
		mprFprintf(MPR_STDOUT, 
			"Testing: iterations %d, threads %d, pool %d, service thread %d\n", 
			iterations, numThreads, poolThreads, needEventsThread);
	}

	//
	//	Use current session object for the main thread
	//
	sessions = (MprTestSession**) mprMalloc(sizeof(MprTestSession*) * 
		numThreads);
	sessions[0] = this;
	if (sessions[0]->initializeClasses(result) < 0) {
		exit(3);
	}

#if BLD_FEATURE_MULTITHREAD
	//
	//	Now clone this session object for all other threads
	//
	for (i = 1; i < numThreads; i++) {
		char tName[64];
		sessions[i] = this->newSession();
		sessions[i]->setResult(result);
		sessions[i]->cloneSettings(this);
		mprSprintf(tName, sizeof(tName), "test.%d", i);
	}
#endif
	return 0;
}
Пример #21
0
int MprCmd::start(char *program, char **argv, char **envp, MprCmdProc fn, 
	void *fnData, int userFlags)
{
	PROCESS_INFORMATION	procInfo;
	STARTUPINFO			startInfo;
	char				dirBuf[MPR_MAX_FNAME];
	char				*envBuf, **ep, *cmdBuf, **ap, *destp, *cp, *dir;
	char				progBuf[MPR_MAX_STRING], *localArgv[2], *saveArg0;
	int					argc, i, len, inheritFiles;

	mprAssert(program);
	mprAssert(argv);

	flags &= ~(MPR_CMD_WAITED | MPR_CMD_RUNNING);
	flags |= (userFlags & MPR_CMD_USER_FLAGS);
	exitStatus = -1;

	mprStrcpy(progBuf, sizeof(progBuf), program);
	progBuf[sizeof(progBuf) - 1] = '\0';
	program = progBuf;

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

	saveArg0 = argv[0];
	if (argv == 0) {
		argv = localArgv;
		argv[1] = 0;
	}
	argv[0] = program;

	//
	//	Determine the command line length and arg count
	//
	argc = 0;
	for (len = 0, ap = argv; *ap; ap++) {
		len += strlen(*ap) + 1 + 2;			// Space and possible quotes
		argc++;
	}
	cmdBuf = (char*) mprMalloc(len + 1);
	cmdBuf[len] = '\0';
	
	//
	//	Add quotes to all args that have spaces in them including "program"
	//
	destp = cmdBuf;
	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';
	mprAssert((int) strlen(destp) < (len - 1));
	mprAssert(cmdBuf[len] == '\0');
	argv[0] = saveArg0;

	envBuf = 0;
	if (envp) {
		for (len = 0, ep = envp; *ep; ep++) {
			len += strlen(*ep) + 1;
		}
		envBuf = (char*) mprMalloc(len + 2);		// Win requires two nulls
		destp = envBuf;
		for (ep = envp; *ep; ep++) {
			strcpy(destp, *ep);
			mprLog(6, log, "Set CGI variable: %s\n", destp);
			destp += strlen(*ep) + 1;
		}
		*destp++ = '\0';
		*destp++ = '\0';						// WIN requires two nulls
	}
	
	memset(&startInfo, 0, sizeof(startInfo));
	startInfo.cb = sizeof(startInfo);

    startInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	if (flags & MPR_CMD_SHOW) {
		startInfo.wShowWindow = SW_SHOW;
	} else {
		startInfo.wShowWindow = SW_HIDE;
	}

	if (files.clientFd[MPR_CMD_IN] > 0) {
		startInfo.hStdInput = 
			(HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_IN]);
	}
	if (files.clientFd[MPR_CMD_OUT] > 0) {
		startInfo.hStdOutput = 
			(HANDLE)_get_osfhandle(files.clientFd[MPR_CMD_OUT]);
	}
	if (files.clientFd[MPR_CMD_ERR] > 0) {
		startInfo.hStdError = 
			(HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_ERR]);
	}

#if UNUSED
	SECURITY_ATTRIBUTES	secAtt;
	memset(&secAtt, 0, sizeof(secAtt));
	secAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
	secAtt.bInheritHandle = TRUE;
#endif

	if (userFlags & MPR_CMD_CHDIR) {
		if (cwd) {
			dir = cwd;
		} else {
			mprGetDirName(dirBuf, sizeof(dirBuf), argv[0]);
			dir = dirBuf;
		}
	} else {
		dir = 0;
	}

	inheritFiles = (flags & MPR_CMD_STDIO_MADE) ? 1 : 0;

	mprLog(5, log, "Running: %s\n", cmdBuf); 

	if (! CreateProcess(0, cmdBuf, 0, 0, inheritFiles, CREATE_NEW_CONSOLE,
			envBuf, dir, &startInfo, &procInfo)) {
		mprError(MPR_L, MPR_LOG, "Can't create process: %s, %d", 
			cmdBuf, mprGetOsError());
		return MPR_ERR_CANT_CREATE;
	}

	handle = (long) procInfo.hProcess;
	pid = procInfo.dwProcessId;

	if (procInfo.hThread != 0)  {
		CloseHandle(procInfo.hThread);
	}
	for (i = 0; i < MPR_CMD_MAX_FD; i++) {
		if (files.clientFd[i] >= 0) {
			close(files.clientFd[i]);
			files.clientFd[i] = -1;
		}
	}
	if (cmdBuf) {
		mprFree(cmdBuf);
	}
	if (envBuf) {
		mprFree(envBuf);
	}

	if (userFlags & MPR_CMD_WAIT) {
		waitForChild(INT_MAX);
		for (i = 0; i < MPR_CMD_MAX_FD; i++) {
			if (files.serverFd[i] >= 0) {
				close(files.serverFd[i]);
				files.serverFd[i] = -1;
			}
		}
		return exitStatus;
	}

	lock();
	outputDataProc = fn;
	data = fnData;
	flags |= MPR_CMD_RUNNING;

	if (1 || ! mpr->getAsyncSelectMode()) {
		timer = new MprTimer(MPR_TIMEOUT_CMD_WAIT, 
			singleThreadedOutputData, (void*) this);
#if FUTURE
		//
		//	Want non blocking reads if we are in single-threaded mode.
		//	Can't use this yet as we are holding a Request lock and so blocking
		//	in a read stops everything. Need proper Async I/O in windows.
		//
		if (mprGetMpr()->poolService->getMaxPoolThreads() == 0) {
		} else {
			task = new MprTask(multiThreadedOutputData, (void*) this);
			task->start();
		}
#endif
	}
	unlock();

	return 0;
}