1#include "cache.h"
2#include "pkt-line.h"
3
4static const char send_pack_usage[] = "git-send-pack [--exec=other] destination [heads]*";
5
6static const char *exec = "git-receive-pack";
7
8static int send_pack(int in, int out)
9{
10 for (;;) {
11 static char buffer[1000];
12 int len;
13
14 len = packet_read_line(in, buffer, sizeof(buffer));
15 if (len > 0) {
16 write(2, buffer, len);
17 continue;
18 }
19 break;
20 }
21 packet_flush(out);
22 close(out);
23 return 0;
24}
25
26/*
27 * First, make it shell-safe. We do this by just disallowing any
28 * special characters. Somebody who cares can do escaping and let
29 * through the rest. But since we're doing to feed this to ssh as
30 * a command line, we're going to be pretty damn anal for now.
31 */
32static char *shell_safe(char *url)
33{
34 char *n = url;
35 unsigned char c;
36 static const char flags[256] = {
37 ['0'...'9'] = 1,
38 ['a'...'z'] = 1,
39 ['A'...'Z'] = 1,
40 ['.'] = 1, ['/'] = 1,
41 ['-'] = 1, ['+'] = 1,
42 [':'] = 1
43 };
44
45 while ((c = *n++) != 0) {
46 if (flags[c] != 1)
47 die("I don't like '%c'. Sue me.", c);
48 }
49 return url;
50}
51
52/*
53 * Yeah, yeah, fixme. Need to pass in the heads etc.
54 */
55static int setup_connection(int fd[2], char *url, char **heads)
56{
57 char command[1024];
58 const char *host, *path;
59 char *colon;
60 int pipefd[2][2];
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", exec, path);
72 if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
73 die("unable to create pipe pair for communication");
74 if (!fork()) {
75 dup2(pipefd[1][0], 0);
76 dup2(pipefd[0][1], 1);
77 close(pipefd[0][0]);
78 close(pipefd[0][1]);
79 close(pipefd[1][0]);
80 close(pipefd[1][1]);
81 if (host)
82 execlp("ssh", "ssh", host, command, NULL);
83 else
84 execlp("sh", "sh", "-c", command, NULL);
85 die("exec failed");
86 }
87 fd[0] = pipefd[0][0];
88 fd[1] = pipefd[1][1];
89 close(pipefd[0][1]);
90 close(pipefd[1][0]);
91 return 0;
92}
93
94int main(int argc, char **argv)
95{
96 int i, nr_heads = 0;
97 char *dest = NULL;
98 char **heads = NULL;
99 int fd[2];
100
101 argv++;
102 for (i = 1; i < argc; i++) {
103 char *arg = *argv++;
104
105 if (*arg == '-') {
106 if (!strncmp(arg, "--exec=", 7)) {
107 exec = arg + 7;
108 continue;
109 }
110 usage(send_pack_usage);
111 }
112 dest = arg;
113 heads = argv;
114 nr_heads = argc - i -1;
115 break;
116 }
117 if (!dest)
118 usage(send_pack_usage);
119 if (setup_connection(fd, dest, heads))
120 return 1;
121 return send_pack(fd[0], fd[1]);
122}