]> asedeno.scripts.mit.edu Git - git.git/blobdiff - run-command.c
Windows: Implement start_command().
[git.git] / run-command.c
index 44100a749b09439121073e32e7a3143b54185d31..dd8b7751ceed0870c086f61766fecd50d4d1b176 100644 (file)
@@ -65,21 +65,8 @@ int start_command(struct child_process *cmd)
                cmd->err = fderr[0];
        }
 
+#ifndef __MINGW32__
        cmd->pid = fork();
-       if (cmd->pid < 0) {
-               if (need_in)
-                       close_pair(fdin);
-               else if (cmd->in)
-                       close(cmd->in);
-               if (need_out)
-                       close_pair(fdout);
-               else if (cmd->out)
-                       close(cmd->out);
-               if (need_err)
-                       close_pair(fderr);
-               return -ERR_RUN_COMMAND_FORK;
-       }
-
        if (!cmd->pid) {
                if (cmd->no_stdin)
                        dup_devnull(0);
@@ -128,6 +115,88 @@ int start_command(struct child_process *cmd)
                }
                die("exec %s failed.", cmd->argv[0]);
        }
+#else
+       int s0 = -1, s1 = -1, s2 = -1;  /* backups of stdin, stdout, stderr */
+       const char *sargv0 = cmd->argv[0];
+       char **env = environ;
+       struct strbuf git_cmd;
+
+       if (cmd->no_stdin) {
+               s0 = dup(0);
+               dup_devnull(0);
+       } else if (need_in) {
+               s0 = dup(0);
+               dup2(fdin[0], 0);
+       } else if (cmd->in) {
+               s0 = dup(0);
+               dup2(cmd->in, 0);
+       }
+
+       if (cmd->no_stderr) {
+               s2 = dup(2);
+               dup_devnull(2);
+       } else if (need_err) {
+               s2 = dup(2);
+               dup2(fderr[1], 2);
+       }
+
+       if (cmd->no_stdout) {
+               s1 = dup(1);
+               dup_devnull(1);
+       } else if (cmd->stdout_to_stderr) {
+               s1 = dup(1);
+               dup2(2, 1);
+       } else if (need_out) {
+               s1 = dup(1);
+               dup2(fdout[1], 1);
+       } else if (cmd->out > 1) {
+               s1 = dup(1);
+               dup2(cmd->out, 1);
+       }
+
+       if (cmd->dir)
+               die("chdir in start_command() not implemented");
+       if (cmd->env) {
+               env = copy_environ();
+               for (; *cmd->env; cmd->env++)
+                       env = env_setenv(env, *cmd->env);
+       }
+
+       if (cmd->git_cmd) {
+               strbuf_init(&git_cmd, 0);
+               strbuf_addf(&git_cmd, "git-%s", cmd->argv[0]);
+               cmd->argv[0] = git_cmd.buf;
+       }
+
+       cmd->pid = spawnvpe(_P_NOWAIT, cmd->argv[0], cmd->argv, (const char **)env);
+
+       if (cmd->env)
+               free_environ(env);
+       if (cmd->git_cmd)
+               strbuf_release(&git_cmd);
+
+       cmd->argv[0] = sargv0;
+       if (s0 >= 0)
+               dup2(s0, 0), close(s0);
+       if (s1 >= 0)
+               dup2(s1, 1), close(s1);
+       if (s2 >= 0)
+               dup2(s2, 2), close(s2);
+#endif
+
+       if (cmd->pid < 0) {
+               if (need_in)
+                       close_pair(fdin);
+               else if (cmd->in)
+                       close(cmd->in);
+               if (need_out)
+                       close_pair(fdout);
+               else if (cmd->out)
+                       close(cmd->out);
+               if (need_err)
+                       close_pair(fderr);
+               return -ERR_RUN_COMMAND_FORK;
+       }
 
        if (need_in)
                close(fdin[0]);