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