The child process handling is delegated to start_command() and
finish_command().
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
---
connect.c | 108 ++++++++++++++++++++++++++++--------------------------------
1 files changed, 50 insertions(+), 58 deletions(-)
diff --git a/connect.c b/connect.c
index b156f92..21597bf 100644
--- a/connect.c
+++ b/connect.c
@@ -484,11 +484,15 @@ struct child_process *git_connect(int fd[2], char *url,
char *host, *path = url;
char *end;
int c;
- int pipefd[2][2];
struct child_process *conn;
enum protocol protocol = PROTO_LOCAL;
int free_path = 0;
char *port = NULL;
+ const char **arg;
+ char command[MAX_CMD_LEN];
+ char *posn = command;
+ int size = MAX_CMD_LEN;
+ int of = 0;
/* Without this we cannot rely on waitpid() to tell
* what happened to our children.
@@ -574,62 +578,51 @@ struct child_process *git_connect(int fd[2], char *url,
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->pid = fork();
- if (conn->pid < 0)
- die("unable to fork");
- if (!conn->pid) {
- 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]);
- close(pipefd[0][1]);
- close(pipefd[1][0]);
- 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)
- execlp(ssh, ssh_basename, host, command, NULL);
- else
- execlp(ssh, ssh_basename, "-p", port, host,
- command, NULL);
- }
- else {
- 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", command, NULL);
+ 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");
+
+ conn->in = conn->out = -1;
+ conn->argv = arg = xcalloc(6, sizeof(*arg));
+ if (protocol == PROTO_SSH) {
+ const char *ssh = getenv("GIT_SSH");
+ if (!ssh) ssh = "ssh";
+
+ *arg++ = ssh;
+ if (port) {
+ *arg++ = "-p";
+ *arg++ = port;
}
- die("exec failed");
+ *arg++ = host;
+ }
+ else {
+ /* remove these from the environment */
+ const char *env[] = {
+ ALTERNATE_DB_ENVIRONMENT,
+ DB_ENVIRONMENT,
+ GIT_DIR_ENVIRONMENT,
+ GIT_WORK_TREE_ENVIRONMENT,
+ GRAFT_ENVIRONMENT,
+ INDEX_ENVIRONMENT,
+ NULL
+ };
+ conn->env = env;
+ *arg++ = "sh";
+ *arg++ = "-c";
}
- fd[0] = pipefd[0][0];
- fd[1] = pipefd[1][1];
- close(pipefd[0][1]);
- close(pipefd[1][0]);
+ *arg++ = command;
+ *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 */
if (free_path)
free(path);
return conn;
@@ -637,13 +630,12 @@ struct child_process *git_connect(int fd[2], char *url,
int finish_connect(struct child_process *conn)
{
+ int code;
if (conn == NULL)
return 0;
- while (waitpid(conn->pid, NULL, 0) < 0) {
- if (errno != EINTR)
- return -1;
- }
+ code = finish_command(conn);
+ free(conn->argv);
free(conn);
- return 0;
+ return code;
}
--
1.5.3.3.1134.gee562
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html