1#include "cache.h"
2#include "rsh.h"
3#include "refs.h"
45
#include <string.h>
67
static unsigned char local_version = 1;
8static unsigned char remote_version = 0;
910
static int verbose = 0;
1112
static int serve_object(int fd_in, int fd_out) {
13ssize_t size;
14unsigned char sha1[20];
15signed char remote;
16int posn = 0;
17do {
18size = read(fd_in, sha1 + posn, 20 - posn);
19if (size < 0) {
20perror("git-ssh-push: read ");
21return -1;
22}
23if (!size)
24return -1;
25posn += size;
26} while (posn < 20);
2728
if (verbose)
29fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1));
3031
remote = 0;
3233
if (!has_sha1_file(sha1)) {
34fprintf(stderr, "git-ssh-push: could not find %s\n",
35sha1_to_hex(sha1));
36remote = -1;
37}
3839
write(fd_out, &remote, 1);
4041
if (remote < 0)
42return 0;
4344
return write_sha1_to_fd(fd_out, sha1);
45}
4647
static int serve_version(int fd_in, int fd_out)
48{
49if (read(fd_in, &remote_version, 1) < 1)
50return -1;
51write(fd_out, &local_version, 1);
52return 0;
53}
5455
static int serve_ref(int fd_in, int fd_out)
56{
57char ref[PATH_MAX];
58unsigned char sha1[20];
59int posn = 0;
60signed char remote = 0;
61do {
62if (read(fd_in, ref + posn, 1) < 1)
63return -1;
64posn++;
65} while (ref[posn - 1]);
6667
if (verbose)
68fprintf(stderr, "Serving %s\n", ref);
6970
if (get_ref_sha1(ref, sha1))
71remote = -1;
72write(fd_out, &remote, 1);
73if (remote)
74return 0;
75write(fd_out, sha1, 20);
76return 0;
77}
7879
80
static void service(int fd_in, int fd_out) {
81char type;
82int retval;
83do {
84retval = read(fd_in, &type, 1);
85if (retval < 1) {
86if (retval < 0)
87perror("git-ssh-push: read ");
88return;
89}
90if (type == 'v' && serve_version(fd_in, fd_out))
91return;
92if (type == 'o' && serve_object(fd_in, fd_out))
93return;
94if (type == 'r' && serve_ref(fd_in, fd_out))
95return;
96} while (1);
97}
9899
static const char *ssh_push_usage =
100"git-ssh-push [-c] [-t] [-a] [-w ref] commit-id url";
101102
int main(int argc, char **argv)
103{
104int arg = 1;
105char *commit_id;
106char *url;
107int fd_in, fd_out;
108const char *prog = getenv("GIT_SSH_PULL") ? : "git-ssh-pull";
109unsigned char sha1[20];
110char hex[41];
111112
while (arg < argc && argv[arg][0] == '-') {
113if (argv[arg][1] == 'w')
114arg++;
115arg++;
116}
117if (argc < arg + 2)
118usage(ssh_push_usage);
119commit_id = argv[arg];
120url = argv[arg + 1];
121if (get_sha1(commit_id, sha1))
122usage(ssh_push_usage);
123memcpy(hex, sha1_to_hex(sha1), sizeof(hex));
124argv[arg] = hex;
125126
if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))
127return 1;
128129
service(fd_in, fd_out);
130return 0;
131}