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 * Determines the absolute path of cmd based on the PATH environment variable.
22 * If cmd contains a slash or backslash, no lookup is performed.
24 static char *path_lookup(const char *cmd
)
26 char *p
, *envpath
= getenv("PATH");
28 int len
= strlen(cmd
);
29 int tryexe
= len
< 4 || strcasecmp(cmd
+len
-4, ".exe");
31 if (strchr(cmd
, '/') || strchr(cmd
, '\\') ||
32 !envpath
|| !*envpath
)
34 envpath
= xstrdup(envpath
);
41 prog
= lookup_prog(dir
, cmd
, tryexe
);
45 prog
= lookup_prog(".", cmd
, tryexe
);
53 /* cmd specifies the command to invoke.
54 * argv specifies its arguments; argv[0] will be replaced by the basename of cmd.
55 * env specifies the environment.
56 * pin and pout specify pipes; the read end of pin is made the standard input
57 * of the spawned process, and the write end of pout is mad the standard output.
58 * The respective unused ends of the pipes are closed both in the parent
59 * process as well as in the child process.
60 * Anyone of pin or pout can be NULL, or any one of the ends can be -1 to
61 * indicate that no processing shall occur.
63 int spawnvpe_pipe(const char *cmd
, const char **argv
, const char **env
,
64 int pin
[], int pout
[])
66 const char *cmd_basename
= strrchr(cmd
, '/');
70 int s0
= -1, s1
= -1, argc
;
72 const char **qargv
, *interpr
;
75 cmd_basename
= strrchr(cmd
, '\\');
82 argv
[0] = cmd_basename
;
87 die("unable to fork");
110 if (pin
&& pin
[0] >= 0)
112 if (pout
&& pout
[1] >= 1)
130 prog
= path_lookup(cmd
);
131 interpr
= parse_interpreter(prog
);
133 for (argc
= 0; argv
[argc
];) argc
++;
134 qargv
= xmalloc((argc
+2)*sizeof(char*));
136 quote_argv(qargv
, argv
);
137 pid
= spawnve(_P_NOWAIT
, prog
, qargv
, env
);
141 quote_argv(&qargv
[1], argv
);
142 pid
= spawnvpe(_P_NOWAIT
, interpr
, qargv
, env
);
146 die("unable to run %s", cmd
);
148 free(qargv
); /* TODO: quoted args should be freed, too */
164 const char **copy_environ()
166 return copy_env(environ
);
169 const char **copy_env(const char **env
)
173 for (s
= env
; *s
; s
++)
175 s
= xmalloc(n
*sizeof(const char *));
176 memcpy(s
, env
, n
*sizeof(const char *));
180 void env_unsetenv(const char **env
, const char *name
)
187 for (src
= dst
= 0; env
[src
]; ++src
) {
189 enln
= strlen(env
[src
]);
191 /* might match, and can test for '=' safely */
192 if (0 == strncmp (env
[src
], name
, nmln
)
193 && '=' == env
[src
][nmln
])
194 /* matches, so skip */