introduce platform independent fork_process function
[git-cheetah/kirill.git] / common / exec.c
blob1825bd5e45e36631bd2c79720efff0e32f1641b7
1 #include "cache.h"
3 #include "debug.h"
4 #include "systeminfo.h"
5 #include "exec.h"
7 #define MAX_PROCESSING_TIME (60 * 1000)
8 #define MAX_ARGS 32
10 /* copy from run-command.c */
11 static inline void close_pair(int fd[2])
13 close(fd[0]);
14 close(fd[1]);
17 int exec_program(const char *working_directory,
18 struct strbuf *output, struct strbuf *error_output,
19 int flags, ...)
21 int fdout[2], fderr[2];
22 int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
24 va_list params;
25 const char *argv[MAX_ARGS];
26 char *arg;
27 int argc = 0;
29 pid_t pid;
30 DWORD status = 0;
32 reporter *debug = QUIETMODE & flags ? debug_git : debug_git_mbox;
34 if (!git_path()) {
35 debug("[ERROR] Could not find git path");
36 return -1;
39 if (output) {
40 if (pipe(fdout) < 0) {
41 return -ERR_RUN_COMMAND_PIPE;
43 s1 = dup(1);
44 dup2(fdout[1], 1);
46 flags |= WAITMODE;
49 if (error_output) {
50 if (pipe(fderr) < 0) {
51 if (output)
52 close_pair(fdout);
53 return -ERR_RUN_COMMAND_PIPE;
55 s2 = dup(2);
56 dup2(fderr[1], 2);
58 flags |= WAITMODE;
61 va_start(params, flags);
62 do {
63 arg = va_arg(params, char*);
64 argv[argc++] = arg;
65 } while (argc < MAX_ARGS && arg);
66 va_end(params);
68 pid = fork_process(argv[0], argv, working_directory);
70 if (s1 >= 0)
71 dup2(s1, 1), close(s1);
72 if (s2 >= 0)
73 dup2(s2, 2), close(s2);
75 if (pid < 0) {
76 if (output)
77 close_pair(fdout);
78 if (error_output)
79 close_pair(fderr);
80 return -ERR_RUN_COMMAND_FORK;
83 if (output)
84 close(fdout[1]);
85 if (error_output)
86 close(fderr[1]);
88 if (WAITMODE & flags) {
89 if (WAIT_OBJECT_0 == WaitForSingleObject((HANDLE)pid,
90 MAX_PROCESSING_TIME)) {
91 if (GetExitCodeProcess((HANDLE)pid, &status))
92 debug_git("Exit code: %d", status);
93 else {
94 /* play safe, and return total failure */
95 status = -1;
96 debug_git("[ERROR] GetExitCode failed (%d); "
97 "wd: %s; cmd: %s",
98 GetLastError(),
99 working_directory,
100 argv[0]);
103 if (output) {
104 strbuf_read(output, fdout[0], 0);
105 debug_git("STDOUT:\r\n%s\r\n*** end of STDOUT ***\r\n", output->buf);
108 if (error_output) {
109 strbuf_read(error_output, fderr[0], 0);
110 debug_git("STDERR:\r\n%s\r\n*** end of STDERR ***\r\n", error_output->buf);
112 } else {
113 status = -ERR_RUN_COMMAND_WAITPID_NOEXIT;
114 debug_git("[ERROR] process timed out; "
115 "wd: %s; cmd: %s",
116 working_directory, argv[0]);
120 if (output)
121 close(fdout[0]);
122 if (error_output)
123 close(fderr[0]);
125 return status;