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
[])
110 char **path
= get_path_split();
112 pid_t pid
= spawnvppe_pipe(cmd
, argv
, env
, path
, pin
, pout
);
114 free_path_split(path
);
116 pid_t pid
= spawnvppe_pipe(cmd
, argv
, env
, NULL
, pin
, pout
);
121 int spawnvppe_pipe(const char *cmd
, const char **argv
, const char **env
,
123 int pin
[], int pout
[])
125 const char *cmd_basename
= strrchr(cmd
, '/');
126 const char *argv0
= argv
[0];
130 int s0
= -1, s1
= -1, argc
;
132 const char **qargv
, *interpr
;
135 cmd_basename
= strrchr(cmd
, '\\');
142 argv
[0] = cmd_basename
;
147 die("unable to fork");
170 if (pin
&& pin
[0] >= 0)
172 if (pout
&& pout
[1] >= 1)
190 prog
= path_lookup(cmd
, path
);
191 interpr
= parse_interpreter(prog
);
193 for (argc
= 0; argv
[argc
];) argc
++;
194 qargv
= xmalloc((argc
+3)*sizeof(char*));
196 quote_argv(qargv
, argv
);
197 pid
= spawnve(_P_NOWAIT
, prog
, qargv
, env
);
199 if (!strcmp(interpr
, "sh")) {
203 memcpy(&qargv
[2], argv
, (argc
+1)*sizeof(char*));
204 pid
= spawnve_git_cmd(qargv
, NULL
, NULL
, env
);
208 quote_argv(&qargv
[1], argv
);
209 pid
= spawnvpe(_P_NOWAIT
, interpr
, qargv
, env
);
213 free(qargv
); /* TODO: quoted args should be freed, too */
231 const char **copy_environ()
233 return copy_env(environ
);
236 const char **copy_env(const char **env
)
240 for (s
= env
; *s
; s
++)
242 s
= xmalloc(n
*sizeof(const char *));
243 memcpy(s
, env
, n
*sizeof(const char *));
247 void env_unsetenv(const char **env
, const char *name
)
254 for (src
= dst
= 0; env
[src
]; ++src
) {
256 enln
= strlen(env
[src
]);
258 /* might match, and can test for '=' safely */
259 if (0 == strncmp (env
[src
], name
, nmln
)
260 && '=' == env
[src
][nmln
])
261 /* matches, so skip */