1#include "cache.h"2#include "rsh.h"3#include "refs.h"45#include <string.h>67static unsigned char local_version = 1;8static unsigned char remote_version = 0;910static int verbose = 0;1112static 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);2728if (verbose)29fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1));3031remote = 0;3233if (!has_sha1_file(sha1)) {34fprintf(stderr, "git-ssh-push: could not find %s\n",35sha1_to_hex(sha1));36remote = -1;37}3839write(fd_out, &remote, 1);4041if (remote < 0)42return 0;4344return write_sha1_to_fd(fd_out, sha1);45}4647static 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}5455static 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]);6667if (verbose)68fprintf(stderr, "Serving %s\n", ref);6970if (get_ref_sha1(ref, sha1))71remote = -1;72write(fd_out, &remote, 1);73if (remote)74return 0;75write(fd_out, sha1, 20);76return 0;77}787980static 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}9899static const char *ssh_push_usage =100"git-ssh-push [-c] [-t] [-a] [-w ref] commit-id url";101102int 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];111112while (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;125126if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))127return 1;128129service(fd_in, fd_out);130return 0;131}