Factor fork()/exec() work into a spawn() like function.
[git/mingw.git] / spawn-pipe.c
blobfc179c8cdc972949663274df7ca761392be0c898
1 #include "git-compat-util.h"
2 #include "spawn-pipe.h"
4 extern char **environ;
6 /* cmd specifies the command to invoke.
7 * argv specifies its arguments; argv[0] will be replaced by the basename of cmd.
8 * env specifies the environment.
9 * pin and pout specify pipes; the read end of pin is made the standard input
10 * of the spawned process, and the write end of pout is mad the standard output.
11 * The respective unused ends of the pipes are closed both in the parent
12 * process as well as in the child process.
13 * Anyone of pin or pout can be NULL, or any one of the ends can be -1 to
14 * indicate that no processing shall occur.
16 int spawnvpe_pipe(const char *cmd, const char **argv, const char **env,
17 int pin[], int pout[])
19 const char *cmd_basename = strrchr(cmd, '/');
20 pid_t pid;
22 #ifdef __MINGW32__
23 int s0 = -1, s1 = -1, argc;
24 const char **qargv;
25 extern void quote_argv(const char **dst, const char **src);
27 if (!cmd_basename)
28 cmd_basename = strrchr(cmd, '\\');
29 #endif
31 if (!cmd_basename)
32 cmd_basename = cmd;
33 else
34 cmd_basename++;
35 argv[0] = cmd_basename;
37 #ifndef __MINGW32__
38 pid = fork();
39 if (pid < 0)
40 die("unable to fork");
41 if (!pid) {
42 if (pin) {
43 if (pin[0] >= 0) {
44 dup2(pin[0], 0);
45 close(pin[0]);
47 if (pin[1] >= 0)
48 close(pin[1]);
50 if (pout) {
51 if (pout[1] >= 0) {
52 dup2(pout[1], 1);
53 close(pout[1]);
55 if (pout[0] >= 0)
56 close(pout[0]);
58 environ = env;
59 execvp(cmd, argv);
60 die("exec failed");
63 if (pin && pin[0] >= 0)
64 close(pin[0]);
65 if (pout && pout[1] >= 1)
66 close(pout[1]);
67 #else
68 if (pin) {
69 if (pin[0] >= 0) {
70 s0 = dup(0);
71 dup2(pin[0], 0);
72 close(pin[0]);
75 if (pout) {
76 if (pout[1] >= 0) {
77 s1 = dup(1);
78 dup2(pout[1], 1);
79 close(pout[1]);
83 for (argc = 0; argv[argc];) argc++;
84 qargv = xmalloc((argc+2)*sizeof(char*));
85 quote_argv(qargv, argv);
87 pid = spawnvpe(_P_NOWAIT, cmd, qargv, env);
89 free(qargv); /* TODO: quoted args should be freed, too */
91 if (s0 >= 0) {
92 dup2(s0, 0);
93 close(s0);
95 if (s1 >= 0) {
96 dup2(s1, 1);
97 close(s1);
99 #endif
101 return pid;
104 const char **copy_environ()
106 return copy_env(environ);
109 const char **copy_env(const char **env)
111 const char **s;
112 int n = 1;
113 for (s = env; *s; s++)
114 n++;
115 s = xmalloc(n*sizeof(const char *));
116 memcpy(s, env, n*sizeof(const char *));
117 return s;
120 void env_unsetenv(const char **env, const char *name)
122 int src, dst;
123 size_t nmln;
125 nmln = strlen(name);
127 for (src = dst = 0; env[src]; ++src) {
128 size_t enln;
129 enln = strlen(env[src]);
130 if (enln > nmln) {
131 /* might match, and can test for '=' safely */
132 if (0 == strncmp (env[src], name, nmln)
133 && '=' == env[src][nmln])
134 /* matches, so skip */
135 continue;
137 env[dst] = env[src];
138 ++dst;
140 env[dst] = NULL;