summaryrefslogtreecommitdiff
path: root/git-daemon
diff options
context:
space:
mode:
authorTony Finch <dot@dotat.at>2010-03-30 20:14:55 +0000
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>2010-05-22 15:54:41 +0100
commit18c4999f61d703d687b3c96e419ec9f4d81541fe (patch)
tree62c48ee5639410e5fe8283dfd7c7e36b5d008942 /git-daemon
parent08e30b5e72511f4d6b026b40ab3125ae05c81868 (diff)
downloaduserv-utils-18c4999f61d703d687b3c96e419ec9f4d81541fe.tar.gz
git-daemon: overhaul configuration and add the userv service script
Use a perl namespace to hold the userv variables that are set by the git-daemon-urlmap script(s).
Diffstat (limited to 'git-daemon')
-rwxr-xr-xgit-daemon/git-daemon-service.pl54
-rw-r--r--git-daemon/git-daemon-urlmap.pl33
-rwxr-xr-xgit-daemon/git-daemon.pl63
-rw-r--r--git-daemon/git-upload-pack13
4 files changed, 112 insertions, 51 deletions
diff --git a/git-daemon/git-daemon-service.pl b/git-daemon/git-daemon-service.pl
new file mode 100755
index 0000000..ec4b7e1
--- /dev/null
+++ b/git-daemon/git-daemon-service.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+#
+# userv-git-daemon service script
+#
+# This was written by Tony Finch <dot@dotat.at>
+# You may do anything with it, at your own risk.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+use strict;
+use warnings;
+
+use Sys::Syslog;
+
+my $service = $ENV{"USERV_SERVICE"};
+$service =~ s|^git-||;
+
+${$cf::{$_}} = $ENV{"USERV_U_$_"}
+ for grep s/^USERV_U_//, keys %ENV;
+
+openlog 'userv-git-daemon/$service', 'pid', 'daemon';
+
+sub cf::fail {
+ syslog 'err', "$cf::client @_";
+ exit;
+}
+
+package cf;
+
+our $check_repo = 1;
+our $check_export = 0;
+our ($dir,$repo,$client);
+$_ = our $uri;
+for my $cf (@ARGV) {
+ do $cf;
+}
+
+fail "no repository configured for $uri" unless defined $repo;
+fail "no directory configured for $uri" unless defined $dir;
+
+my $home = (getpwuid $<)[7];
+$dir = "$home/$dir" if $dir =~ m|^[^/]|
+ or $dir =~ s|^~/||;
+$dir = "$dir/$repo";
+
+fail "bad repository in $uri"
+ if $check_repo and $repo !~ /^[0-9A-Za-z._-]+[.]git$/;
+fail "repository not exported for $uri"
+ if $check_export and not -e "$dir/git-daemon-export-ok";
+
+my @cmd = ('git', $service, '--strict', '--timeout=30', $dir);
+no warnings; # suppress errors to stderr
+exec @cmd or fail "exec @cmd: $!";
+
+# end
diff --git a/git-daemon/git-daemon-urlmap.pl b/git-daemon/git-daemon-urlmap.pl
index 5f587be..61c376c 100644
--- a/git-daemon/git-daemon-urlmap.pl
+++ b/git-daemon/git-daemon-urlmap.pl
@@ -1,20 +1,27 @@
-# Configuration file for the userv git daemon.
+# Example configuration file for the userv git daemon.
#
# This was written by Tony Finch <dot@dotat.at>
# You may do anything with it, at your own risk.
# http://creativecommons.org/publicdomain/zero/1.0/
-use warnings;
-use strict;
-
-my $g = qr{[0-9a-z_-]+[.]git};
-my $u = qr{[0-9a-z]+};
-
-return "~fanf/public-git/$1", "fanf" if m{^git://dotat[.]at/($g)$};
-return "/u2/git-repos$1", "webmaster" if m{^git://git[.]chiark[.]greenend[.]org[.]uk/($g)$};
-return "~$1/public-git/$2", "$1" if m{^git://git[.]chiark[.]greenend[.]org[.]uk/~($u)/($g)$};
-return "~$1/cabal-git/$2", "$1" if m{^git://cabal[.]greenend[.]org[.]uk/~($u)/($g)$};
-
-return;
+if ($host eq 'git.chiark.greenend.org.uk') {
+ if ($path =~ m{^~([^/]*)/(.*)}) {
+ $user = $1;
+ $dir = 'public-git';
+ $repo = $2;
+ } else {
+ $user = 'webmaster';
+ $dir = '/u2/git-repos';
+ $repo = $path;
+ }
+} elsif (m{^git://cabal[.]greenend[.]org[.]uk/~([^/]*)/(.*)$}) {
+ $user = $1;
+ $dir = 'cabal-git';
+ $repo = $2;
+} elsif ($host eq 'dotat.at') {
+ $user = 'fanf';
+ $dir = 'public-git';
+ $repo = $path;
+}
# end
diff --git a/git-daemon/git-daemon.pl b/git-daemon/git-daemon.pl
index efb45b1..74942a0 100755
--- a/git-daemon/git-daemon.pl
+++ b/git-daemon/git-daemon.pl
@@ -15,22 +15,21 @@ use Sys::Syslog;
sub ntoa {
my $sockaddr = shift;
- if (defined $sockaddr) {
- my ($port,$addr) = sockaddr_in $sockaddr;
- $addr = inet_ntoa $addr;
- return ($addr,$port,"[$addr]:$port");
- } else {
- return (undef,undef,"[?.?.?.?]:?");
- }
+ return ('[?.?.?.?]:?') unless defined $sockaddr;
+ my ($port,$addr) = sockaddr_in $sockaddr;
+ $addr = inet_ntoa $addr;
+ return ("[$addr]:$port",$addr,$port);
+}
+{
+ package cf;
+ our ($client,$client_addr,$client_port) = ::ntoa(getpeername(STDIN));
+ our ($server,$server_addr,$server_port) = ::ntoa(getsockname(STDIN));
}
-
-my ($client_addr,$client_port,$client) = ntoa getpeername STDIN;
-my ($server_addr,$server_port,$server) = ntoa getsockname STDIN;
openlog 'userv-git-daemon', 'pid', 'daemon';
sub fail {
- syslog 'err', "$client @_";
+ syslog 'err', "$cf::client @_";
exit;
}
@@ -44,7 +43,6 @@ sub xread {
fail "short read: expected $length bytes, got " . length $buffer
if defined $ret and $ret == 0;
fail "read: $!" if not defined $ret and $! != EINTR and $! != EAGAIN;
- $ret = 0 if not defined $ret;
}
alarm 0;
return $buffer;
@@ -53,38 +51,27 @@ sub xread {
my $len_hex = xread 4;
fail "non-hex packet length" unless $len_hex =~ m{^[0-9a-fA-F]{4}$};
my $line = xread hex $len_hex;
-unless ($line =~ m{^(git-[a-z-]+) ([!-~]+)\0host=([!-~]+)\0$}) {
- $line =~ s/[^ -~]+/ /g;
+if ($line =~ m{^(git-[a-z-]+) ([!-~]+)\0host=([!-~]+)\0$}) {
+ package cf;
+ our ($service,$path,$host) = ($1,$2,$3);
+ $path =~ s|^/*||;
+ our $uri = $_ = "git://$host/$path";
+} else {
+ $line =~ s|[^ -~]+| |g;
fail "could not parse \"$line\""
}
-my ($service,$path,$host) = ($1,$2,3);
-$path =~ s|^/*||;
-my $uri = $_ = "git://$host/$path";
-my $user;
for my $cf (@ARGV) {
- my ($r,$u) = do $cf;
- $user = $u if defined $u;
+ package cf;
+ our ($user,$dir,$repo);
+ do $cf;
}
-fail "no user configured for $uri" unless defined $user;
-syslog 'info', "$client userv $user $service $uri";
-
-my %vars = (
- REQUEST_SERVICE => $service,
- REQUEST_HOST => $host,
- REQUEST_PATH => $path,
- REQUEST_URI => $uri,
- CLIENT => $client,
- CLIENT_ADDR => $client_addr,
- CLIENT_PORT => $client_port,
- SERVER => $server,
- SERVER_ADDR => $server_addr,
- SERVER_PORT => $server_port,
-);
-my @opts = map "-D$_=$vars{$_}", grep defined $vars{$_}, sort keys %vars;
+fail "no user configured for $cf::uri" unless defined $cf::user;
+syslog 'info', "$cf::client $cf::service $cf::uri";
+my @opts = map "-D$_=${$cf::{$_}}", grep defined ${$cf::{$_}}, sort keys %cf::;
+my @cmd = ('userv', @opts, $cf::user, $cf::service);
no warnings; # suppress errors to stderr
-exec 'userv', @opts, $user, $service
- or fail "exec userv @opts $user $service: $!";
+exec @cmd or fail "exec @cmd: $!";
# end
diff --git a/git-daemon/git-upload-pack b/git-daemon/git-upload-pack
new file mode 100644
index 0000000..39a2994
--- /dev/null
+++ b/git-daemon/git-upload-pack
@@ -0,0 +1,13 @@
+# userv configuration for git-daemon git-upload-pack service
+#
+# This was written by Tony Finch <dot@dotat.at>
+# You may do anything with it, at your own risk.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+if ( grep service-user-shell /etc/shells
+ & glob calling-user git
+ )
+ reset
+ errors-to-syslog daemon error
+ execute /usr/local/lib/userv/git-daemon-service /etc/userv/git-daemon-urlmap.pl .userv/git-daemon-urlmap.pl
+fi