]>
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, | |
60 | [':'] = 1 | |
61 | }; | |
62 | ||
63 | while ((c = *n++) != 0) { | |
64 | if (flags[c] != 1) | |
65 | die("I don't like '%c'. Sue me.", c); | |
66 | } | |
67 | return url; | |
68 | } | |
69 | ||
70 | /* | |
71 | * Yeah, yeah, fixme. Need to pass in the heads etc. | |
72 | */ | |
73 | int git_connect(int fd[2], char *url, const char *prog) | |
74 | { | |
75 | char command[1024]; | |
76 | const char *host, *path; | |
77 | char *colon; | |
78 | int pipefd[2][2]; | |
79 | pid_t pid; | |
80 | ||
81 | url = shell_safe(url); | |
82 | host = NULL; | |
83 | path = url; | |
84 | colon = strchr(url, ':'); | |
85 | if (colon) { | |
86 | *colon = 0; | |
87 | host = url; | |
88 | path = colon+1; | |
89 | } | |
90 | snprintf(command, sizeof(command), "%s %s", prog, path); | |
91 | if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) | |
92 | die("unable to create pipe pair for communication"); | |
93 | pid = fork(); | |
94 | if (!pid) { | |
95 | dup2(pipefd[1][0], 0); | |
96 | dup2(pipefd[0][1], 1); | |
97 | close(pipefd[0][0]); | |
98 | close(pipefd[0][1]); | |
99 | close(pipefd[1][0]); | |
100 | close(pipefd[1][1]); | |
101 | if (host) | |
102 | execlp("ssh", "ssh", host, command, NULL); | |
103 | else | |
104 | execlp("sh", "sh", "-c", command, NULL); | |
105 | die("exec failed"); | |
106 | } | |
107 | fd[0] = pipefd[0][0]; | |
108 | fd[1] = pipefd[1][1]; | |
109 | close(pipefd[0][1]); | |
110 | close(pipefd[1][0]); | |
111 | return pid; | |
112 | } | |
113 | ||
114 | int finish_connect(pid_t pid) | |
115 | { | |
116 | int ret; | |
117 | ||
118 | for (;;) { | |
119 | ret = waitpid(pid, NULL, 0); | |
120 | if (!ret) | |
121 | break; | |
122 | if (errno != EINTR) | |
123 | break; | |
124 | } | |
125 | return ret; | |
126 | } |