Provide a Windows-specific implementation of exec_program_v()
[git-cheetah.git] / common / exec.c
blobebca64cd9c755e7b24d1e19dab6d915ae5f774a3
1 #include "git-compat-util.h"
2 #include "cache.h"
4 #include "debug.h"
5 #include "systeminfo.h"
6 #include "exec.h"
8 #define MAX_PROCESSING_TIME (60 * 1000)
9 #define MAX_ARGS 32
11 /* copy from run-command.c */
12 static inline void close_pair(int fd[2])
14 close(fd[0]);
15 close(fd[1]);
18 int exec_program(const char *working_directory,
19 struct strbuf *output, struct strbuf *error_output,
20 int flags, ...)
22 va_list params;
23 const char *argv[MAX_ARGS];
24 char *arg;
25 int argc = 0;
27 va_start(params, flags);
28 do {
29 arg = va_arg(params, char*);
30 argv[argc++] = arg;
31 } while (argc < MAX_ARGS && arg);
32 va_end(params);
34 return exec_program_v(working_directory, output, error_output,
35 flags, argv);
38 /* see winexec.c for the Windows-specific implementation of exec_program_v() */
39 #ifndef _WIN32
40 int exec_program_v(const char *working_directory,
41 struct strbuf *output, struct strbuf *error_output,
42 int flags, const char **argv)
44 int fdout[2], fderr[2];
45 int s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
46 int devnull = -1;
48 pid_t pid;
49 int status = 0;
50 int ret;
52 reporter *debug = QUIETMODE & flags ? _debug_git : _debug_git_mbox;
54 if (!git_path()) {
55 debug("[ERROR] Could not find git path");
56 return -1;
59 if ((!output || !error_output) && !(DETACHMODE & flags))
60 devnull = open("/dev/null", O_WRONLY);
62 s1 = dup(1);
63 if (output) {
64 if (pipe(fdout) < 0) {
65 return -ERR_RUN_COMMAND_PIPE;
67 dup2(fdout[1], 1);
69 flags |= WAITMODE;
70 } else if (devnull >= 0) {
71 dup2(devnull, 1);
74 s2 = dup(2);
75 if (error_output) {
76 if (pipe(fderr) < 0) {
77 if (output)
78 close_pair(fdout);
79 return -ERR_RUN_COMMAND_PIPE;
81 dup2(fderr[1], 2);
83 flags |= WAITMODE;
84 } else if (devnull >= 0) {
85 dup2(devnull, 2);
87 if (devnull >= 0)
88 close(devnull);
90 pid = fork_process(argv[0], argv, working_directory);
92 if (s1 >= 0)
93 dup2(s1, 1), close(s1);
94 if (s2 >= 0)
95 dup2(s2, 2), close(s2);
97 if (pid < 0) {
98 if (output)
99 close_pair(fdout);
100 if (error_output)
101 close_pair(fderr);
102 return -ERR_RUN_COMMAND_FORK;
105 if (output)
106 close(fdout[1]);
107 if (error_output)
108 close(fderr[1]);
110 if (WAITMODE & flags) {
111 ret = wait_for_process(pid, MAX_PROCESSING_TIME,
112 &status);
113 if (ret) {
114 if (ret < 0) {
115 debug_git("[ERROR] wait_for_process failed (%d); "
116 "wd: %s; cmd: %s",
117 status,
118 working_directory,
119 argv[0]);
121 status = -1;
124 if (output) {
125 strbuf_read(output, fdout[0], 0);
126 debug_git("STDOUT:\r\n%s\r\n*** end of STDOUT ***\r\n", output->buf);
129 if (error_output) {
130 strbuf_read(error_output, fderr[0], 0);
131 debug_git("STDERR:\r\n%s\r\n*** end of STDERR ***\r\n", error_output->buf);
133 } else {
134 status = -ERR_RUN_COMMAND_WAITPID_NOEXIT;
135 debug_git("[ERROR] process timed out; "
136 "wd: %s; cmd: %s",
137 working_directory, argv[0]);
140 close_process(pid);
142 if (output)
143 close(fdout[0]);
144 if (error_output)
145 close(fderr[0]);
147 return status;
149 #endif