1 #include "git-compat-util.h"
2 #include "spawn-pipe.h"
5 static char *lookup_prog(const char *dir
, const char *cmd
, int tryexe
)
8 snprintf(path
, sizeof(path
), "%s/%s.exe", dir
, cmd
);
10 if (tryexe
&& access(path
, 0) == 0)
12 path
[strlen(path
)-4] = '\0';
13 if (access(path
, 0) == 0)
19 * Splits the PATH into parts.
21 char **get_path_split()
23 char *p
, **path
, *envpath
= getenv("PATH");
26 if (!envpath
|| !*envpath
)
29 envpath
= xstrdup(envpath
);
35 if (*dir
) { /* not earlier, catches series of ; */
42 path
= xmalloc((n
+1)*sizeof(char*));
47 path
[i
++] = xstrdup(p
);
57 void free_path_split(char **path
)
69 * Determines the absolute path of cmd using the the split path in path.
70 * If cmd contains a slash or backslash, no lookup is performed.
72 static char *path_lookup(const char *cmd
, char **path
)
76 int len
= strlen(cmd
);
77 int tryexe
= len
< 4 || strcasecmp(cmd
+len
-4, ".exe");
79 if (strchr(cmd
, '/') || strchr(cmd
, '\\'))
83 prog
= lookup_prog(*p
++, cmd
, tryexe
);
86 prog
= lookup_prog(".", cmd
, tryexe
);
94 /* cmd specifies the command to invoke.
95 * argv specifies its arguments; argv[0] will be replaced by the basename of cmd.
96 * env specifies the environment.
97 * pin and pout specify pipes; the read end of pin is made the standard input
98 * of the spawned process, and the write end of pout is mad the standard output.
99 * The respective unused ends of the pipes are closed both in the parent
100 * process as well as in the child process.
101 * Anyone of pin or pout can be NULL, or any one of the ends can be -1 to
102 * indicate that no processing shall occur.
104 int spawnvpe_pipe(const char *cmd
, const char **argv
, const char **env
,
105 int pin
[], int pout
[])
108 char **path
= get_path_split();
110 pid_t pid
= spawnvppe_pipe(cmd
, argv
, env
, path
, pin
, pout
);
112 free_path_split(path
);
114 pid_t pid
= spawnvppe_pipe(cmd
, argv
, env
, NULL
, pin
, pout
);
119 int spawnvppe_pipe(const char *cmd
, const char **argv
, const char **env
,
121 int pin
[], int pout
[])
123 const char *cmd_basename
= strrchr(cmd
, '/');
127 int s0
= -1, s1
= -1, argc
;
129 const char **qargv
, *interpr
;
132 cmd_basename
= strrchr(cmd
, '\\');
139 argv
[0] = cmd_basename
;
144 die("unable to fork");
167 if (pin
&& pin
[0] >= 0)
169 if (pout
&& pout
[1] >= 1)
187 prog
= path_lookup(cmd
, path
);
188 interpr
= parse_interpreter(prog
);
190 for (argc
= 0; argv
[argc
];) argc
++;
191 qargv
= xmalloc((argc
+2)*sizeof(char*));
193 quote_argv(qargv
, argv
);
194 pid
= spawnve(_P_NOWAIT
, prog
, qargv
, (const char**) env
);
198 quote_argv(&qargv
[1], argv
);
199 pid
= spawnvpe(_P_NOWAIT
, interpr
, qargv
, env
);
202 free(qargv
); /* TODO: quoted args should be freed, too */
218 const char **copy_environ()
220 return copy_env( (const char**)environ
);
223 const char **copy_env(const char **env
)
227 for (s
= env
; *s
; s
++)
229 s
= xmalloc(n
*sizeof(const char *));
230 memcpy(s
, env
, n
*sizeof(const char *));
234 void env_unsetenv(const char **env
, const char *name
)
241 for (src
= dst
= 0; env
[src
]; ++src
) {
243 enln
= strlen(env
[src
]);
245 /* might match, and can test for '=' safely */
246 if (0 == strncmp (env
[src
], name
, nmln
)
247 && '=' == env
[src
][nmln
])
248 /* matches, so skip */