1 #include "git-compat-util.h"
2 #include "spawn-pipe.h"
7 static char *lookup_prog(const char *dir
, const char *cmd
, int tryexe
)
10 snprintf(path
, sizeof(path
), "%s/%s.exe", dir
, cmd
);
12 if (tryexe
&& access(path
, 0) == 0)
14 path
[strlen(path
)-4] = '\0';
15 if (access(path
, 0) == 0)
21 * Splits the PATH into parts.
23 char **get_path_split()
25 char *p
, **path
, *envpath
= getenv("PATH");
28 if (!envpath
|| !*envpath
)
31 envpath
= xstrdup(envpath
);
37 if (*dir
) { /* not earlier, catches series of ; */
44 path
= xmalloc((n
+1)*sizeof(char*));
49 path
[i
++] = xstrdup(p
);
59 void free_path_split(char **path
)
71 * Determines the absolute path of cmd using the the split path in path.
72 * If cmd contains a slash or backslash, no lookup is performed.
74 static char *path_lookup(const char *cmd
, char **path
)
78 int len
= strlen(cmd
);
79 int tryexe
= len
< 4 || strcasecmp(cmd
+len
-4, ".exe");
81 if (strchr(cmd
, '/') || strchr(cmd
, '\\'))
85 prog
= lookup_prog(*p
++, cmd
, tryexe
);
88 prog
= lookup_prog(".", cmd
, tryexe
);
96 /* cmd specifies the command to invoke.
97 * argv specifies its arguments; argv[0] will be replaced by the basename of cmd.
98 * env specifies the environment.
99 * pin and pout specify pipes; the read end of pin is made the standard input
100 * of the spawned process, and the write end of pout is mad the standard output.
101 * The respective unused ends of the pipes are closed both in the parent
102 * process as well as in the child process.
103 * Anyone of pin or pout can be NULL, or any one of the ends can be -1 to
104 * indicate that no processing shall occur.
106 int spawnvpe_pipe(const char *cmd
, const char **argv
, const char **env
,
107 int pin
[], int pout
[])
109 char **path
= get_path_split();
111 pid_t pid
= spawnvppe_pipe(cmd
, argv
, env
, path
, pin
, pout
);
113 free_path_split(path
);
118 int spawnvppe_pipe(const char *cmd
, const char **argv
, const char **env
,
120 int pin
[], int pout
[])
122 const char *cmd_basename
= strrchr(cmd
, '/');
126 int s0
= -1, s1
= -1, argc
;
128 const char **qargv
, *interpr
;
131 cmd_basename
= strrchr(cmd
, '\\');
138 argv
[0] = cmd_basename
;
143 die("unable to fork");
166 if (pin
&& pin
[0] >= 0)
168 if (pout
&& pout
[1] >= 1)
186 prog
= path_lookup(cmd
, path
);
187 interpr
= parse_interpreter(prog
);
189 for (argc
= 0; argv
[argc
];) argc
++;
190 qargv
= xmalloc((argc
+2)*sizeof(char*));
192 quote_argv(qargv
, argv
);
193 pid
= spawnve(_P_NOWAIT
, prog
, qargv
, env
);
197 quote_argv(&qargv
[1], argv
);
198 pid
= spawnvpe(_P_NOWAIT
, interpr
, qargv
, env
);
202 die("unable to run %s", cmd
);
204 free(qargv
); /* TODO: quoted args should be freed, too */
220 const char **copy_environ()
222 return copy_env(environ
);
225 const char **copy_env(const char **env
)
229 for (s
= env
; *s
; s
++)
231 s
= xmalloc(n
*sizeof(const char *));
232 memcpy(s
, env
, n
*sizeof(const char *));
236 void env_unsetenv(const char **env
, const char *name
)
243 for (src
= dst
= 0; env
[src
]; ++src
) {
245 enln
= strlen(env
[src
]);
247 /* might match, and can test for '=' safely */
248 if (0 == strncmp (env
[src
], name
, nmln
)
249 && '=' == env
[src
][nmln
])
250 /* matches, so skip */