ref: 1cd7d1dc7454536fdce66e87a5a78cead95ce03d
parent: 29bce68c99b7d73cf9b7956a797e8f2e737d8684
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Aug 30 21:46:05 EDT 2020
git/{fetch,send}: add hjgit (tlsclient -a) protocol hjgit://dialstr/repo/path will connect to a plan 9 git server running behind tlsclient -a; this allows us to have authenticated pushes with a plan 9 host.
--- a/fetch.c
+++ b/fetch.c
@@ -254,9 +254,7 @@
void
main(int argc, char **argv)
{
- char proto[Nproto], host[Nhost], port[Nport];
- char repo[Nrepo], path[Npath];
- int r, pfd;
+ int pfd;
Conn c;
ARGBEGIN{
@@ -271,25 +269,13 @@
if(argc != 1)
usage();
- r = -1;
if(mkoutpath(packtmp) == -1)
sysfatal("could not create %s: %r", packtmp);
if((pfd = create(packtmp, ORDWR, 0644)) == -1)
sysfatal("could not create %s: %r", packtmp);
- if(parseuri(argv[0], proto, host, port, path, repo) == -1)
- sysfatal("bad uri %s", argv[0]);
- if(strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0)
- r = dialssh(&c, host, port, path, "upload");
- else if(strcmp(proto, "git") == 0)
- r = dialgit(&c, host, port, path, "upload");
- else if(strcmp(proto, "http") == 0 || strcmp(proto, "https") == 0)
- r = dialhttp(&c, host, port, path, "upload");
- else
- sysfatal("unknown protocol %s", proto);
-
- if(r == -1)
- sysfatal("could not dial %s:%s: %r", proto, host);
+ if(gitconnect(&c, argv[0]) == -1)
+ sysfatal("could not dial %s: %r", argv[0]);
if(fetchpack(&c, pfd, packtmp) == -1)
sysfatal("fetch failed: %r");
closeconn(&c);
--- a/git.h
+++ b/git.h
@@ -23,13 +23,6 @@
Pathmax = 512,
Hashsz = 20,
Pktmax = 65536,
-
- Nproto = 16,
- Nport = 16,
- Nhost = 256,
- Npath = 128,
- Nrepo = 64,
- Nbranch = 32,
};
enum {
@@ -51,7 +44,8 @@
};
enum {
- ConnRaw,
+ ConnGit,
+ ConnGit9,
ConnSsh,
ConnHttp,
};
@@ -274,11 +268,8 @@
int readpkt(Conn*, char*, int);
int writepkt(Conn*, char*, int);
int flushpkt(Conn*);
-int parseuri(char *, char *, char *, char *, char *, char *);
void initconn(Conn*, int, int);
-int dialssh(Conn*, char *, char *, char *, char *);
-int dialgit(Conn*, char *, char *, char *, char *);
-int dialhttp(Conn*, char *, char *, char *, char *);
+int gitconnect(Conn *, char *);
int readphase(Conn *);
int writephase(Conn *);
void closeconn(Conn *);
--- a/proto.c
+++ b/proto.c
@@ -7,6 +7,15 @@
#define Contenthdr "headers Content-Type: application/x-git-%s-pack-request"
#define Accepthdr "headers Accept: application/x-git-%s-pack-result"
+enum {
+ Nproto = 16,
+ Nport = 16,
+ Nhost = 256,
+ Npath = 128,
+ Nrepo = 64,
+ Nbranch = 32,
+};
+
int chattygit;
int
@@ -78,7 +87,7 @@
}
-int
+static int
parseuri(char *uri, char *proto, char *host, char *port, char *path, char *repo)
{
char *s, *p, *q;
@@ -138,7 +147,7 @@
return 0;
}
-int
+static int
webclone(Conn *c, char *url)
{
char buf[16];
@@ -167,7 +176,7 @@
return -1;
}
-int
+static int
webopen(Conn *c, char *file, int mode)
{
char path[128];
@@ -179,7 +188,7 @@
return fd;
}
-int
+static int
issmarthttp(Conn *c, char *direction)
{
char buf[Pktmax+1], svc[128];
@@ -200,7 +209,7 @@
return 0;
}
-int
+static int
dialhttp(Conn *c, char *host, char *port, char *path, char *direction)
{
char *geturl, *suff, *hsep, *psep;
@@ -230,7 +239,7 @@
return 0;
}
-int
+static int
dialssh(Conn *c, char *host, char *, char *path, char *direction)
{
int pid, pfd[2];
@@ -254,18 +263,59 @@
c->type = ConnSsh;
c->rfd = pfd[1];
c->wfd = dup(pfd[1], -1);
- return 0;
}
- return -1;
+ return 0;
}
-int
+static int
+dialhjgit(Conn *c, char *host, char *port, char *path, char *direction)
+{
+ char *ds, *p, *e, cmd[512];
+ int pid, pfd[2];
+
+ if((ds = netmkaddr(host, "tcp", port)) == nil)
+ return -1;
+ if(pipe(pfd) == -1)
+ sysfatal("unable to open pipe: %r");
+ pid = fork();
+ if(pid == -1)
+ sysfatal("unable to fork");
+ if(pid == 0){
+ close(pfd[1]);
+ dup(pfd[0], 0);
+ dup(pfd[0], 1);
+ if(chattygit)
+ fprint(2, "exec tlsclient -a %s\n", ds);
+ execl("/bin/tlsclient", "tlsclient", "-a", ds, nil);
+ sysfatal("exec: %r");
+ }else{
+ close(pfd[0]);
+ p = cmd;
+ e = cmd + sizeof(cmd);
+ p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
+ p = seprint(p + 1, e, "host=%s", host);
+ c->type = ConnGit9;
+ c->rfd = pfd[1];
+ c->wfd = dup(pfd[1], -1);
+ if(writepkt(c, cmd, p - cmd + 1) == -1){
+ fprint(2, "failed to write message\n");
+ close(c->rfd);
+ close(c->wfd);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static int
dialgit(Conn *c, char *host, char *port, char *path, char *direction)
{
char *ds, *p, *e, cmd[512];
int fd;
- ds = netmkaddr(host, "tcp", port);
+ if((ds = netmkaddr(host, "tcp", port)) == nil)
+ return -1;
if(chattygit)
fprint(2, "dial %s git-%s-pack %s\n", ds, direction, path);
fd = dial(ds, nil, nil, nil);
@@ -275,7 +325,7 @@
e = cmd + sizeof(cmd);
p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
p = seprint(p + 1, e, "host=%s", host);
- c->type = ConnRaw;
+ c->type = ConnGit;
c->rfd = fd;
c->wfd = dup(fd, -1);
if(writepkt(c, cmd, p - cmd + 1) == -1){
@@ -289,12 +339,36 @@
void
initconn(Conn *c, int rd, int wr)
{
- c->type = ConnRaw;
+ c->type = ConnGit;
c->rfd = rd;
c->wfd = wr;
}
int
+gitconnect(Conn *c, char *uri)
+{
+ char proto[Nproto], host[Nhost], port[Nport];
+ char repo[Nrepo], path[Npath];
+
+ if(parseuri(uri, proto, host, port, path, repo) == -1){
+ werrstr("bad uri %s", uri);
+ return -1;
+ }
+
+ memset(c, 0, sizeof(Conn));
+ if(strcmp(proto, "ssh") == 0)
+ return dialssh(c, host, port, path, "receive");
+ else if(strcmp(proto, "git") == 0)
+ return dialgit(c, host, port, path, "receive");
+ else if(strcmp(proto, "hjgit") == 0)
+ return dialhjgit(c, host, port, path, "receive");
+ else if(strcmp(proto, "http") == 0 || strcmp(proto, "https") == 0)
+ return dialhttp(c, host, port, path, "receive");
+ werrstr("unknown protocol %s", proto);
+ return -1;
+}
+
+int
writephase(Conn *c)
{
char hdr[128];
@@ -344,8 +418,9 @@
close(c->rfd);
close(c->wfd);
switch(c->type){
- case ConnRaw:
+ case ConnGit:
break;
+ case ConnGit9:
case ConnSsh:
free(wait());
break;
--- a/send.c
+++ b/send.c
@@ -413,11 +413,8 @@
void
main(int argc, char **argv)
{
- char proto[Nproto], host[Nhost], port[Nport];
- char repo[Nrepo], path[Npath];
char *br;
Conn c;
- int r;
ARGBEGIN{
default:
@@ -454,21 +451,8 @@
gitinit();
if(argc != 1)
usage();
- r = -1;
- if(parseuri(argv[0], proto, host, port, path, repo) == -1)
- sysfatal("bad uri %s", argv[0]);
-
- if(strcmp(proto, "ssh") == 0)
- r = dialssh(&c, host, port, path, "receive");
- else if(strcmp(proto, "git") == 0)
- r = dialgit(&c, host, port, path, "receive");
- else if(strcmp(proto, "http") == 0 || strcmp(proto, "https") == 0)
- r = dialhttp(&c, host, port, path, "receive");
- else
- sysfatal("unknown protocol %s", proto);
-
- if(r == -1)
- sysfatal("could not dial %s:%s: %r", proto, host);
+ if(gitconnect(&c, argv[0]) == -1)
+ sysfatal("git connect: %s: %r", argv[0]);
if(sendpack(&c) == -1)
sysfatal("send failed: %r");
closeconn(&c);