chiark / gitweb /
git-daemon: overhaul configuration and add the userv service script
authorTony Finch <dot@dotat.at>
Tue, 30 Mar 2010 20:14:55 +0000 (20:14 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 22 May 2010 14:54:41 +0000 (15:54 +0100)
Use a perl namespace to hold the userv variables that are set
by the git-daemon-urlmap script(s).

git-daemon/git-daemon-service.pl [new file with mode: 0755]
git-daemon/git-daemon-urlmap.pl
git-daemon/git-daemon.pl
git-daemon/git-upload-pack [new file with mode: 0644]

diff --git a/git-daemon/git-daemon-service.pl b/git-daemon/git-daemon-service.pl
new file mode 100755 (executable)
index 0000000..ec4b7e1
--- /dev/null
@@ -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
index 5f587be08647bf1a034f94eb9f645dcfb152330d..61c376cbe9328f4dfc340acb63e825ffa4350202 100644 (file)
@@ -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
index efb45b121491ea810a8321e65b680aed358d212d..74942a0e7c9caedd36c3d98fe523610560ea159a 100755 (executable)
@@ -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 (file)
index 0000000..39a2994
--- /dev/null
@@ -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