X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=run-command.c;h=0d95340833aa999ecee58ad70c1c61a832fcdf38;hb=628511a5883fa809e86b34ebc147ac62eb214458;hp=ac314a5a8d96d74a36dd2f274707204142e84b7b;hpb=cd03eebbfdae712bd4a10d6b393980a8137ce305;p=git.git diff --git a/run-command.c b/run-command.c index ac314a5a8..0d9534083 100644 --- a/run-command.c +++ b/run-command.c @@ -75,7 +75,7 @@ fail_pipe: trace_argv_printf(cmd->argv, "trace: run_command:"); -#ifndef __MINGW32__ +#ifndef WIN32 fflush(NULL); cmd->pid = fork(); if (!cmd->pid) { @@ -94,6 +94,9 @@ fail_pipe: else if (need_err) { dup2(fderr[1], 2); close_pair(fderr); + } else if (cmd->err > 1) { + dup2(cmd->err, 2); + close(cmd->err); } if (cmd->no_stdout) @@ -134,6 +137,7 @@ fail_pipe: error("cannot fork() for %s: %s", cmd->argv[0], strerror(failed_errno = errno)); #else +{ int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */ const char **sargv = cmd->argv; char **env = environ; @@ -155,6 +159,9 @@ fail_pipe: } else if (need_err) { s2 = dup(2); dup2(fderr[1], 2); + } else if (cmd->err > 2) { + s2 = dup(2); + dup2(cmd->err, 2); } if (cmd->no_stdout) { @@ -197,6 +204,7 @@ fail_pipe: dup2(s1, 1), close(s1); if (s2 >= 0) dup2(s2, 2), close(s2); +} #endif if (cmd->pid < 0) { @@ -226,6 +234,8 @@ fail_pipe: if (need_err) close(fderr[1]); + else if (cmd->err) + close(cmd->err); return 0; } @@ -313,52 +323,109 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const return run_command(&cmd); } -#ifdef __MINGW32__ -static __stdcall unsigned run_thread(void *data) +#ifdef WIN32 +static unsigned __stdcall run_thread(void *data) { struct async *async = data; - return async->proc(async->fd_for_proc, async->data); + return async->proc(async->proc_in, async->proc_out, async->data); } #endif int start_async(struct async *async) { - int pipe_out[2]; + int need_in, need_out; + int fdin[2], fdout[2]; + int proc_in, proc_out; + + need_in = async->in < 0; + if (need_in) { + if (pipe(fdin) < 0) { + if (async->out > 0) + close(async->out); + return error("cannot create pipe: %s", strerror(errno)); + } + async->in = fdin[1]; + } + + need_out = async->out < 0; + if (need_out) { + if (pipe(fdout) < 0) { + if (need_in) + close_pair(fdin); + else if (async->in) + close(async->in); + return error("cannot create pipe: %s", strerror(errno)); + } + async->out = fdout[0]; + } + + if (need_in) + proc_in = fdin[0]; + else if (async->in) + proc_in = async->in; + else + proc_in = -1; - if (pipe(pipe_out) < 0) - return error("cannot create pipe: %s", strerror(errno)); - async->out = pipe_out[0]; + if (need_out) + proc_out = fdout[1]; + else if (async->out) + proc_out = async->out; + else + proc_out = -1; -#ifndef __MINGW32__ +#ifndef WIN32 /* Flush stdio before fork() to avoid cloning buffers */ fflush(NULL); async->pid = fork(); if (async->pid < 0) { error("fork (async) failed: %s", strerror(errno)); - close_pair(pipe_out); - return -1; + goto error; } if (!async->pid) { - close(pipe_out[0]); - exit(!!async->proc(pipe_out[1], async->data)); + if (need_in) + close(fdin[1]); + if (need_out) + close(fdout[0]); + exit(!!async->proc(proc_in, proc_out, async->data)); } - close(pipe_out[1]); + + if (need_in) + close(fdin[0]); + else if (async->in) + close(async->in); + + if (need_out) + close(fdout[1]); + else if (async->out) + close(async->out); #else - async->fd_for_proc = pipe_out[1]; + async->proc_in = proc_in; + async->proc_out = proc_out; async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL); if (!async->tid) { error("cannot create thread: %s", strerror(errno)); - close_pair(pipe_out); - return -1; + goto error; } #endif return 0; + +error: + if (need_in) + close_pair(fdin); + else if (async->in) + close(async->in); + + if (need_out) + close_pair(fdout); + else if (async->out) + close(async->out); + return -1; } int finish_async(struct async *async) { -#ifndef __MINGW32__ +#ifndef WIN32 int ret = wait_or_whine(async->pid, "child process", 0); #else DWORD ret = 0;