]>
Commit | Line | Data |
---|---|---|
f7192598 LT |
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 | } |