if (!flags)
return 1;
- if (len > 45 || memcmp(name, "refs/", 5))
+ if (len < 5 || memcmp(name, "refs/", 5))
return 0;
/* Skip the "refs/" part */
if (len != name_len + 41) {
if (server_capabilities)
free(server_capabilities);
- server_capabilities = strdup(name + name_len + 1);
+ server_capabilities = xstrdup(name + name_len + 1);
}
if (!check_ref(name, name_len, flags))
close(pipefd[1][0]);
}
+#define MAX_CMD_LEN 1024
+
/*
- * Yeah, yeah, fixme. Need to pass in the heads etc.
+ * This returns 0 if the transport protocol does not need fork(2),
+ * or a process id if it does. Once done, finish the connection
+ * with finish_connect() with the value returned from this function
+ * (it is safe to call finish_connect() with 0 to support the former
+ * case).
+ *
+ * Does not return a negative value on error; it just dies.
*/
-int git_connect(int fd[2], char *url, const char *prog)
+pid_t git_connect(int fd[2], char *url, const char *prog)
{
- char command[1024];
char *host, *path = url;
char *end;
int c;
if (path[1] == '~')
path++;
else {
- path = strdup(ptr);
+ path = xstrdup(ptr);
free_path = 1;
}
/* These underlying connection commands die() if they
* cannot connect.
*/
- char *target_host = strdup(host);
+ char *target_host = xstrdup(host);
if (git_use_proxy(host))
git_proxy_connect(fd, host);
else
if (pid < 0)
die("unable to fork");
if (!pid) {
- snprintf(command, sizeof(command), "%s %s", prog,
- sq_quote(path));
+ char command[MAX_CMD_LEN];
+ char *posn = command;
+ int size = MAX_CMD_LEN;
+ int of = 0;
+
+ of |= add_to_string(&posn, &size, prog, 0);
+ of |= add_to_string(&posn, &size, " ", 0);
+ of |= add_to_string(&posn, &size, path, 1);
+
+ if (of)
+ die("command line too long");
+
dup2(pipefd[1][0], 0);
dup2(pipefd[0][1], 1);
close(pipefd[0][0]);
int finish_connect(pid_t pid)
{
+ if (pid == 0)
+ return 0;
+
while (waitpid(pid, NULL, 0) < 0) {
if (errno != EINTR)
return -1;