60b87f5867eaed8240d943b83dd7a5032ed5f89b
[git.git] / connect.c
1 #include "cache.h"
2 #include <sys/wait.h>
3
4 /*
5  * First, make it shell-safe.  We do this by just disallowing any
6  * special characters. Somebody who cares can do escaping and let
7  * through the rest. But since we're doing to feed this to ssh as
8  * a command line, we're going to be pretty damn anal for now.
9  */
10 static char *shell_safe(char *url)
11 {
12         char *n = url;
13         unsigned char c;
14         static const char flags[256] = {
15                 ['0'...'9'] = 1,
16                 ['a'...'z'] = 1,
17                 ['A'...'Z'] = 1,
18                 ['.'] = 1, ['/'] = 1,
19                 ['-'] = 1, ['+'] = 1,
20                 [':'] = 1
21         };
22
23         while ((c = *n++) != 0) {
24                 if (flags[c] != 1)
25                         die("I don't like '%c'. Sue me.", c);
26         }
27         return url;
28 }
29
30 /*
31  * Yeah, yeah, fixme. Need to pass in the heads etc.
32  */
33 int git_connect(int fd[2], char *url, const char *prog)
34 {
35         char command[1024];
36         const char *host, *path;
37         char *colon;
38         int pipefd[2][2];
39         pid_t pid;
40
41         url = shell_safe(url);
42         host = NULL;
43         path = url;
44         colon = strchr(url, ':');
45         if (colon) {
46                 *colon = 0;
47                 host = url;
48                 path = colon+1;
49         }
50         snprintf(command, sizeof(command), "%s %s", prog, path);
51         if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
52                 die("unable to create pipe pair for communication");
53         pid = fork();
54         if (!pid) {
55                 dup2(pipefd[1][0], 0);
56                 dup2(pipefd[0][1], 1);
57                 close(pipefd[0][0]);
58                 close(pipefd[0][1]);
59                 close(pipefd[1][0]);
60                 close(pipefd[1][1]);
61                 if (host)
62                         execlp("ssh", "ssh", host, command, NULL);
63                 else
64                         execlp("sh", "sh", "-c", command, NULL);
65                 die("exec failed");
66         }               
67         fd[0] = pipefd[0][0];
68         fd[1] = pipefd[1][1];
69         close(pipefd[0][1]);
70         close(pipefd[1][0]);
71         return pid;
72 }
73
74 int finish_connect(pid_t pid)
75 {
76         int ret;
77
78         for (;;) {
79                 ret = waitpid(pid, NULL, 0);
80                 if (!ret)
81                         break;
82                 if (errno != EINTR)
83                         break;
84         }
85         return ret;
86 }