JBoolean
JProgramAvailable
	(
	const JCharacter* programName
	)
{
	JString s;
	return JProgramAvailable(programName, &s);
}
JError
JExecute
	(
	const JCharacter*		argv[],
	const JSize				size,
	pid_t*					childPID,
	const JExecuteAction	toAction,
	int*					toFD,
	const JExecuteAction	origFromAction,
	int*					fromFD,
	const JExecuteAction	errAction,
	int*					errFD
	)
{
	assert( size > sizeof(JCharacter*) );
	assert( argv[ (size/sizeof(JCharacter*)) - 1 ] == NULL );

	const JExecuteAction fromAction =
		(origFromAction == kJForceNonblockingPipe ? kJCreatePipe : origFromAction);

	assert( toAction != kJTossOutput && toAction != kJAttachToFromFD &&
			toAction != kJForceNonblockingPipe );
	assert( fromAction != kJAttachToFromFD );
	assert( errAction != kJForceNonblockingPipe );

	assert( (toAction != kJCreatePipe && toAction != kJAttachToFD) ||
			toFD != NULL );
	assert( (fromAction != kJCreatePipe && fromAction != kJAttachToFD) ||
			fromFD != NULL );
	assert( (errAction != kJCreatePipe && errAction != kJAttachToFD) ||
			errFD != NULL );

	JString progName;
	if (!JProgramAvailable(argv[0], &progName))
		{
		return JProgramNotAvailable(argv[0]);
		}
	argv[0] = progName.GetCString();

	int fd[3][2];

	if (toAction == kJCreatePipe)
		{
		const JError err = JCreatePipe(fd[0]);
		if (!err.OK())
			{
			return err;
			}
		}

	if (fromAction == kJCreatePipe)
		{
		const JError err = JCreatePipe(fd[1]);
		if (!err.OK())
			{
			if (toAction == kJCreatePipe)
				{
				close(fd[0][0]);
				close(fd[0][1]);
				}
			return err;
			}
		}

	if (errAction == kJCreatePipe)
		{
		const JError err = JCreatePipe(fd[2]);
		if (!err.OK())
			{
			if (toAction == kJCreatePipe)
				{
				close(fd[0][0]);
				close(fd[0][1]);
				}
			if (fromAction == kJCreatePipe)
				{
				close(fd[1][0]);
				close(fd[1][1]);
				}
			return err;
			}
		}

	pid_t pid;
	const JError err = JThisProcess::Fork(&pid);
	if (!err.OK())
		{
		if (toAction == kJCreatePipe)
			{
			close(fd[0][0]);
			close(fd[0][1]);
			}
		if (fromAction == kJCreatePipe)
			{
			close(fd[1][0]);
			close(fd[1][1]);
			}
		if (errAction == kJCreatePipe)
			{
			close(fd[2][0]);
			close(fd[2][1]);
			}
		return err;
		}

	// child

	else if (pid == 0)
		{
		const int stdinFD = fileno(stdin);
		if (toAction == kJCreatePipe)
			{
			dup2(fd[0][0], stdinFD);
			close(fd[0][0]);
			close(fd[0][1]);
			}
		else if (toAction == kJAttachToFD)
			{
			dup2(*toFD, stdinFD);
			close(*toFD);
			}

		const int stdoutFD = fileno(stdout);
		if (fromAction == kJCreatePipe)
			{
			dup2(fd[1][1], stdoutFD);
			close(fd[1][0]);
			close(fd[1][1]);
			}
		else if (fromAction == kJAttachToFD)
			{
			dup2(*fromFD, stdoutFD);
			close(*fromFD);
			}
		else if (fromAction == kJTossOutput)
			{
			FILE* nullFile = fopen("/dev/null", "a");
			int nullfd     = fileno(nullFile);
			dup2(nullfd, stdoutFD);
			fclose(nullFile);
			}

		const int stderrFD = fileno(stderr);
		if (errAction == kJCreatePipe)
			{
			dup2(fd[2][1], stderrFD);
			close(fd[2][0]);
			close(fd[2][1]);
			}
		else if (errAction == kJAttachToFD)
			{
			dup2(*errFD, stderrFD);
			close(*errFD);
			}
		else if (errAction == kJTossOutput)
			{
			FILE* nullFile = fopen("/dev/null", "a");
			int nullfd     = fileno(nullFile);
			dup2(nullfd, stderrFD);
			fclose(nullFile);
			}
		else if (errAction == kJAttachToFromFD && fromAction != kJIgnoreConnection)
			{
			dup2(stdoutFD, stderrFD);
			}

		ACE_OS::execvp(argv[0], const_cast<char* const*>(argv));

		cerr << "Unable to run program \"" << argv[0] << '"' << endl;
		cerr << endl;
		cerr << "JExecute()::execvp() failed" << endl;
		cerr << "Errno value: " << jerrno() << endl;

		JThisProcess::Exit(1);
		return JNoError();
		}

	// parent

	else
		{
		if (origFromAction == kJForceNonblockingPipe)
			{
			pid_t pid2;
			const JError err2 = JThisProcess::Fork(&pid2);
			if (err2.OK() && pid2 == 0)
				{
				for (int i=0; i<150; i++)
					{
					JWait(0.1);

					int value = fcntl(fd[1][1], F_GETFL, 0);
					if (value & O_NONBLOCK)
						{
						cerr << "turning off nonblocking for cout: " << value << endl;
						fcntl(fd[1][1], F_SETFL, value & (~ O_NONBLOCK));
						}
					}

				JThisProcess::Exit(0);
				return JNoError();
				}

			JProcess* p = new JProcess(pid2);
			p->KillAtExit(kJTrue);
			}

		if (toAction == kJCreatePipe)
			{
			close(fd[0][0]);
			*toFD = fd[0][1];
			}
		if (fromAction == kJCreatePipe)
			{
			close(fd[1][1]);
			*fromFD = fd[1][0];
			}
		if (errAction == kJCreatePipe)
			{
			close(fd[2][1]);
			*errFD = fd[2][0];
			}

		if (childPID == NULL)
			{
			return JWaitForChild(pid);
			}
		else
			{
			*childPID = pid;
			return JNoError();
			}
		}
}
示例#3
0
JError
JRenameVCS
	(
	const JCharacter* oldFullName,
	const JCharacter* newFullName
	)
{
	if (!JNameUsed(oldFullName))
		{
		return JDirEntryDoesNotExist(oldFullName);
		}

	JString oldPath, newPath, name;
	JSplitPathAndName(newFullName, &newPath, &name);
	JSplitPathAndName(oldFullName, &oldPath, &name);	// must be second

	const JString origPath = JGetCurrentDirectory();
	if (JChangeDirectory(oldPath) != kJNoError)
		{
		return JAccessDenied(oldPath);
		}

	JVCSType type1    = JGetVCSType(oldPath);
	JVCSType type2    = JGetVCSType(newPath);
	JError err        = JNoError();
	JBoolean tryPlain = kJFalse;
	JString cmd;
	JProcess* p = NULL;
	if (type1 != type2)
		{
		tryPlain = kJTrue;
		}
	else if (type1 == kJSVNType || type1 == kJGitType)
		{
		if (type1 == kJSVNType)
			{
			cmd  = "svn mv --force ";
			cmd += JPrepArgForExec(oldFullName);
			cmd += " ";
			cmd += JPrepArgForExec(newFullName);
			}
		else if (type1 == kJGitType)
			{
			cmd  = "git mv -f ";
			cmd += JPrepArgForExec(name);
			cmd += " ";
			cmd += JPrepArgForExec(newFullName);
			}

		err = JProcess::Create(&p, cmd);
		if (err.OK())
			{
			p->WaitUntilFinished();
			}

		if (p != NULL && !p->SuccessfulFinish())
			{
			err      = JAccessDenied(oldFullName, newFullName);
			tryPlain = kJTrue;
			}
		}
	else if (type1 == kJUnknownVCSType)
		{
		tryPlain = kJTrue;
		}
	else
		{
		err = JUnsupportedVCS(oldFullName);
		}

	if (tryPlain && JProgramAvailable("mv"))
		{
		cmd  = "mv ";
		cmd += JPrepArgForExec(oldFullName);
		cmd += " ";
		cmd += JPrepArgForExec(newFullName);

		JSimpleProcess* p1;
		err = JSimpleProcess::Create(&p1, cmd);
		p   = p1;
		if (err.OK())
			{
			p->WaitUntilFinished();
			if (!p->SuccessfulFinish())
				{
				err = JAccessDenied(oldFullName, newFullName);
				}
			}
		}
	else if (tryPlain)
		{
		err = JRenameDirEntry(oldFullName, newFullName);
		}

	delete p;
	JChangeDirectory(origPath);
	return err;
}