Example #1
0
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
{
#if defined(__QNX__)
	if (initialDirectory.empty())
	{
		/// use QNX's spawn system call which is more efficient than fork/exec.
		char** argv = new char*[args.size() + 2];
		int i = 0;
		argv[i++] = const_cast<char*>(command.c_str());
		for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) 
			argv[i++] = const_cast<char*>(it->c_str());
		argv[i] = NULL;
		struct inheritance inherit;
		std::memset(&inherit, 0, sizeof(inherit));
		inherit.flags = SPAWN_ALIGN_DEFAULT | SPAWN_CHECK_SCRIPT | SPAWN_SEARCH_PATH;
		int fdmap[3];
		fdmap[0] = inPipe  ? inPipe->readHandle()   : 0;
		fdmap[1] = outPipe ? outPipe->writeHandle() : 1;
		fdmap[2] = errPipe ? errPipe->writeHandle() : 2;
	
		char** envPtr = 0;
		std::vector<char> envChars;
		std::vector<char*> envPtrs;
		if (!env.empty())
		{
			envChars = getEnvironmentVariablesBuffer(env);
			envPtrs.reserve(env.size() + 1);
			char* p = &envChars[0];
			while (*p)
			{
				envPtrs.push_back(p);
				while (*p) ++p;
				++p;
			}
			envPtrs.push_back(0);
			envPtr = &envPtrs[0];
		}
	
		int pid = spawn(command.c_str(), 3, fdmap, &inherit, argv, envPtr);
		delete [] argv;
		if (pid == -1) 
			throw SystemException("cannot spawn", command);

		if (inPipe)  inPipe->close(Pipe::CLOSE_READ);
		if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
		if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
		return new ProcessHandleImpl(pid);
	}
	else
	{
		return launchByForkExecImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env);
	}
#else
	return launchByForkExecImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env);
#endif
}
ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
{
	int pid = fork();
	if (pid < 0)
	{
		throw SystemException("Cannot fork process for", command);		
	}
	else if (pid == 0)
	{
		if (!initialDirectory.empty())
		{
			if (chdir(initialDirectory.c_str()) != 0)
			{
				_exit(72);
			}
		}

		setEnvironmentVariables(env);

		// setup redirection
		if (inPipe)
		{
			dup2(inPipe->readHandle(), STDIN_FILENO);
			inPipe->close(Pipe::CLOSE_BOTH);
		}
		// outPipe and errPipe may be the same, so we dup first and close later
		if (outPipe) dup2(outPipe->writeHandle(), STDOUT_FILENO);
		if (errPipe) dup2(errPipe->writeHandle(), STDERR_FILENO);
		if (outPipe) outPipe->close(Pipe::CLOSE_BOTH);
		if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
		// close all open file descriptors other than stdin, stdout, stderr
		for (int i = 3; i < getdtablesize(); ++i)
			close(i);

		char** argv = new char*[args.size() + 2];
		int i = 0;
		argv[i++] = const_cast<char*>(command.c_str());
		for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) 
			argv[i++] = const_cast<char*>(it->c_str());
		argv[i] = NULL;
		execvp(command.c_str(), argv);
		_exit(72);
	}

	if (inPipe)  inPipe->close(Pipe::CLOSE_READ);
	if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
	if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
	return new ProcessHandleImpl(pid);
}
Example #3
0
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
{
	char** argv = new char*[args.size() + 2];
	int i = 0;
	argv[i++] = const_cast<char*>(command.c_str());
	for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) 
		argv[i++] = const_cast<char*>(it->c_str());
	argv[i] = NULL;
	try
	{
		int pid = vfork();
		if (pid < 0)
		{
			throw SystemException("Cannot fork process for", command);		
		}
		else if (pid == 0)
		{
			if (!initialDirectory.empty())
			{
				if (chdir(initialDirectory.c_str()) != 0)
				{
					std::stringstream str;
					str << "Cannot set initial directory to '" << initialDirectory << "' when forking process for";
					throw SystemException(str.str(), command);		
				}
			}
			setEnvironmentVariables(environment_variables);

			if (execvp(command.c_str(), argv) == -1)
				throw SystemException("Cannot execute command", command);
		}
		else 
		{
			delete [] argv;
			return new ProcessHandleImpl(pid);
		}
	}
	catch (...)
	{
		delete [] argv;
		throw;
	}
}