Use start_command() in git_connect() instead of explicit fork/exec.
The child process handling is delegated to start_command() and finish_command(). Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>maint
parent
98158e9cfd
commit
f364cb8823
99
connect.c
99
connect.c
|
@ -482,11 +482,12 @@ struct child_process *git_connect(int fd[2], char *url,
|
||||||
char *host, *path = url;
|
char *host, *path = url;
|
||||||
char *end;
|
char *end;
|
||||||
int c;
|
int c;
|
||||||
int pipefd[2][2];
|
|
||||||
struct child_process *conn;
|
struct child_process *conn;
|
||||||
enum protocol protocol = PROTO_LOCAL;
|
enum protocol protocol = PROTO_LOCAL;
|
||||||
int free_path = 0;
|
int free_path = 0;
|
||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
|
const char **arg;
|
||||||
|
struct strbuf cmd;
|
||||||
|
|
||||||
/* Without this we cannot rely on waitpid() to tell
|
/* Without this we cannot rely on waitpid() to tell
|
||||||
* what happened to our children.
|
* what happened to our children.
|
||||||
|
@ -572,59 +573,52 @@ struct child_process *git_connect(int fd[2], char *url,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
|
|
||||||
die("unable to create pipe pair for communication");
|
|
||||||
conn = xcalloc(1, sizeof(*conn));
|
conn = xcalloc(1, sizeof(*conn));
|
||||||
conn->pid = fork();
|
|
||||||
if (conn->pid < 0)
|
|
||||||
die("unable to fork");
|
|
||||||
if (!conn->pid) {
|
|
||||||
struct strbuf cmd;
|
|
||||||
|
|
||||||
strbuf_init(&cmd, MAX_CMD_LEN);
|
strbuf_init(&cmd, MAX_CMD_LEN);
|
||||||
strbuf_addstr(&cmd, prog);
|
strbuf_addstr(&cmd, prog);
|
||||||
strbuf_addch(&cmd, ' ');
|
strbuf_addch(&cmd, ' ');
|
||||||
sq_quote_buf(&cmd, path);
|
sq_quote_buf(&cmd, path);
|
||||||
if (cmd.len >= MAX_CMD_LEN)
|
if (cmd.len >= MAX_CMD_LEN)
|
||||||
die("command line too long");
|
die("command line too long");
|
||||||
|
|
||||||
dup2(pipefd[1][0], 0);
|
conn->in = conn->out = -1;
|
||||||
dup2(pipefd[0][1], 1);
|
conn->argv = arg = xcalloc(6, sizeof(*arg));
|
||||||
close(pipefd[0][0]);
|
if (protocol == PROTO_SSH) {
|
||||||
close(pipefd[0][1]);
|
const char *ssh = getenv("GIT_SSH");
|
||||||
close(pipefd[1][0]);
|
if (!ssh) ssh = "ssh";
|
||||||
close(pipefd[1][1]);
|
|
||||||
if (protocol == PROTO_SSH) {
|
|
||||||
const char *ssh, *ssh_basename;
|
|
||||||
ssh = getenv("GIT_SSH");
|
|
||||||
if (!ssh) ssh = "ssh";
|
|
||||||
ssh_basename = strrchr(ssh, '/');
|
|
||||||
if (!ssh_basename)
|
|
||||||
ssh_basename = ssh;
|
|
||||||
else
|
|
||||||
ssh_basename++;
|
|
||||||
|
|
||||||
if (!port)
|
*arg++ = ssh;
|
||||||
execlp(ssh, ssh_basename, host, cmd.buf, NULL);
|
if (port) {
|
||||||
else
|
*arg++ = "-p";
|
||||||
execlp(ssh, ssh_basename, "-p", port, host,
|
*arg++ = port;
|
||||||
cmd.buf, NULL);
|
|
||||||
}
|
}
|
||||||
else {
|
*arg++ = host;
|
||||||
unsetenv(ALTERNATE_DB_ENVIRONMENT);
|
|
||||||
unsetenv(DB_ENVIRONMENT);
|
|
||||||
unsetenv(GIT_DIR_ENVIRONMENT);
|
|
||||||
unsetenv(GIT_WORK_TREE_ENVIRONMENT);
|
|
||||||
unsetenv(GRAFT_ENVIRONMENT);
|
|
||||||
unsetenv(INDEX_ENVIRONMENT);
|
|
||||||
execlp("sh", "sh", "-c", cmd.buf, NULL);
|
|
||||||
}
|
|
||||||
die("exec failed");
|
|
||||||
}
|
}
|
||||||
fd[0] = pipefd[0][0];
|
else {
|
||||||
fd[1] = pipefd[1][1];
|
/* remove these from the environment */
|
||||||
close(pipefd[0][1]);
|
const char *env[] = {
|
||||||
close(pipefd[1][0]);
|
ALTERNATE_DB_ENVIRONMENT,
|
||||||
|
DB_ENVIRONMENT,
|
||||||
|
GIT_DIR_ENVIRONMENT,
|
||||||
|
GIT_WORK_TREE_ENVIRONMENT,
|
||||||
|
GRAFT_ENVIRONMENT,
|
||||||
|
INDEX_ENVIRONMENT,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
conn->env = env;
|
||||||
|
*arg++ = "sh";
|
||||||
|
*arg++ = "-c";
|
||||||
|
}
|
||||||
|
*arg++ = cmd.buf;
|
||||||
|
*arg = NULL;
|
||||||
|
|
||||||
|
if (start_command(conn))
|
||||||
|
die("unable to fork");
|
||||||
|
|
||||||
|
fd[0] = conn->out; /* read from child's stdout */
|
||||||
|
fd[1] = conn->in; /* write to child's stdin */
|
||||||
|
strbuf_release(&cmd);
|
||||||
if (free_path)
|
if (free_path)
|
||||||
free(path);
|
free(path);
|
||||||
return conn;
|
return conn;
|
||||||
|
@ -632,13 +626,12 @@ struct child_process *git_connect(int fd[2], char *url,
|
||||||
|
|
||||||
int finish_connect(struct child_process *conn)
|
int finish_connect(struct child_process *conn)
|
||||||
{
|
{
|
||||||
|
int code;
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (waitpid(conn->pid, NULL, 0) < 0) {
|
code = finish_command(conn);
|
||||||
if (errno != EINTR)
|
free(conn->argv);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free(conn);
|
free(conn);
|
||||||
return 0;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue