The git suite may not be in PATH (and thus programs such as git-send-pack could not exec git-rev-list). Thus there is a need for logic that will locate these programs. Modifying PATH is not desirable as it result in behavior differing from the user's intentions, as we may end up prepending "/usr/bin" to PATH. - git C programs will use exec*_git_cmd() APIs to exec sub-commands. - exec*_git_cmd() will execute a git program by searching for it in the following directories: 1. --exec-path (as used by "git") 2. The GIT_EXEC_PATH environment variable. 3. $(gitexecdir) as set in Makefile (default value $(bindir)). - git wrapper will modify PATH as before to enable shell scripts to invoke "git-foo" commands. Ideally, shell scripts should use the git wrapper to become independent of PATH, and then modifying PATH will not be necessary. [jc: with minor updates after a brief review.] Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com> Signed-off-by: Junio C Hamano <junkio@cox.net>
		
			
				
	
	
		
			75 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			75 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "cache.h"
 | 
						|
#include "run-command.h"
 | 
						|
#include <sys/wait.h>
 | 
						|
#include "exec_cmd.h"
 | 
						|
 | 
						|
int run_command_v_opt(int argc, char **argv, int flags)
 | 
						|
{
 | 
						|
	pid_t pid = fork();
 | 
						|
 | 
						|
	if (pid < 0)
 | 
						|
		return -ERR_RUN_COMMAND_FORK;
 | 
						|
	if (!pid) {
 | 
						|
		if (flags & RUN_COMMAND_NO_STDIO) {
 | 
						|
			int fd = open("/dev/null", O_RDWR);
 | 
						|
			dup2(fd, 0);
 | 
						|
			dup2(fd, 1);
 | 
						|
			close(fd);
 | 
						|
		}
 | 
						|
		if (flags & RUN_GIT_CMD) {
 | 
						|
			execv_git_cmd(argv);
 | 
						|
		} else {
 | 
						|
			execvp(argv[0], (char *const*) argv);
 | 
						|
		}
 | 
						|
		die("exec %s failed.", argv[0]);
 | 
						|
	}
 | 
						|
	for (;;) {
 | 
						|
		int status, code;
 | 
						|
		int retval = waitpid(pid, &status, 0);
 | 
						|
 | 
						|
		if (retval < 0) {
 | 
						|
			if (errno == EINTR)
 | 
						|
				continue;
 | 
						|
			error("waitpid failed (%s)", strerror(retval));
 | 
						|
			return -ERR_RUN_COMMAND_WAITPID;
 | 
						|
		}
 | 
						|
		if (retval != pid)
 | 
						|
			return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
 | 
						|
		if (WIFSIGNALED(status))
 | 
						|
			return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
 | 
						|
 | 
						|
		if (!WIFEXITED(status))
 | 
						|
			return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
 | 
						|
		code = WEXITSTATUS(status);
 | 
						|
		if (code)
 | 
						|
			return -code;
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int run_command_v(int argc, char **argv)
 | 
						|
{
 | 
						|
	return run_command_v_opt(argc, argv, 0);
 | 
						|
}
 | 
						|
 | 
						|
int run_command(const char *cmd, ...)
 | 
						|
{
 | 
						|
	int argc;
 | 
						|
	char *argv[MAX_RUN_COMMAND_ARGS];
 | 
						|
	const char *arg;
 | 
						|
	va_list param;
 | 
						|
 | 
						|
	va_start(param, cmd);
 | 
						|
	argv[0] = (char*) cmd;
 | 
						|
	argc = 1;
 | 
						|
	while (argc < MAX_RUN_COMMAND_ARGS) {
 | 
						|
		arg = argv[argc++] = va_arg(param, char *);
 | 
						|
		if (!arg)
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	va_end(param);
 | 
						|
	if (MAX_RUN_COMMAND_ARGS <= argc)
 | 
						|
		return error("too many args to run %s", cmd);
 | 
						|
	return run_command_v_opt(argc, argv, 0);
 | 
						|
}
 |