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