From: Ian Jackson Date: Sat, 22 May 2010 18:13:43 +0000 (+0100) Subject: Changes to make it appear to work on chiark X-Git-Tag: userv/0.6.1~91 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=userv-utils.git;a=commitdiff_plain;h=70b9d2e0dbecb8fe1e2045a1752465cd35885bb0 Changes to make it appear to work on chiark --- diff --git a/git-daemon/Makefile b/git-daemon/Makefile index 2d24274..1a18f66 100644 --- a/git-daemon/Makefile +++ b/git-daemon/Makefile @@ -9,14 +9,14 @@ include ../settings.make TARGETS= git-upload-pack inetd.conf git-daemon git-service -SUBSTVARS= libuserv etcuserv +SUBSTVARS= libuserv etcuserv varlog all: $(TARGETS) -sedscript: Makefile +sedscript: Makefile read-urlmap echo >$@.new '$(foreach f, $(SUBSTVARS), s,@$f@,$($f),g; )' echo >>$@.new '/@@READ_URLMAP@@/c\' - perl >>$@.new -pe 's/$$/\\/' >$@.new -pe 's/\\/\\\\/g; s/$$/\\/' [/] [] - matching requests will be handled by - and unless overridden by handled by - serving subdirectories of - - multi-user [/] - matching requests are only those those next - path element starts with ~. The - request will be handled by and unless - overridden by will be handled by - serving subdirectories of - ( must be a relative path) - - repo-regexp - For per-user service. Subrepos must match this - regexp, which must contain a single matching - group which is the filesystem pathname inside - the . The default is (Tcl syntax): - repo-regexp {^(\w[-+._0-9A-Za-z]*)$} - - [no-]require-git-daemon-export-ok - For per-user service. Default is no-. - -Last match, or last setting, wins. -s may start with ~ +See "git-urlmap" for syntax description and an example. ---------------------------------------------- diff --git a/git-daemon/chiark-urlmap b/git-daemon/chiark-urlmap deleted file mode 100644 index 09e2a11..0000000 --- a/git-daemon/chiark-urlmap +++ /dev/null @@ -1,5 +0,0 @@ - -single-user dotat.at fanf dotat-git -multi-user git.chiark.greenend.org.uk public-git -multi-user cabal.greenend.org.uk cabal-git -single-user git.chiark.greenend.org.uk webmaster /u2/git-repos diff --git a/git-daemon/git-daemon.in b/git-daemon/git-daemon.in index 8fe8ca1..1b1b540 100755 --- a/git-daemon/git-daemon.in +++ b/git-daemon/git-daemon.in @@ -13,6 +13,13 @@ use POSIX; use Socket; use Sys::Syslog; +BEGIN { + if ($ARGV[0] =~ s/^-L//) { + my $logfile= shift @ARGV; + open STDERR, ">> $logfile" or die $!; + } +} + sub ntoa { my $sockaddr = shift; return ('(local)') unless defined $sockaddr; @@ -24,6 +31,9 @@ our ($client,$client_addr,$client_port) = ntoa getpeername STDIN; our ($server,$server_addr,$server_port) = ntoa getsockname STDIN; our ($service,$specpath,$spechost); +printf STDERR "%s [$$] %s %s\n", + strftime("%Y-%m-%d %H:%M:%S %Z", localtime), $server, $client; + openlog 'userv-git-daemon', 'pid', 'daemon'; sub fail { syslog 'err', "$client @_"; exit } @@ -52,20 +62,25 @@ unless (($service,$specpath,$spechost) = $line =~ @@READ_URLMAP@@ -fail "No mapping for $uri" unless defined $serve_user; -syslog 'notice', "$client $service $serve_user $uri"; +fail "No global mapping for $uri" unless defined $serve_user; -my ($hn,$ha,$at,$naddrs,@addrs) = gethostbyname $host; -die "hostname/address mismatch ($spechost $server_addr)" unless grep { +my ($hn,$ha,$at,$naddrs,@addrs) = gethostbyname $spechost; +fail "hostname/address mismatch ($spechost $server_addr)" unless grep { $server_addr eq inet_ntoa $_ } @addrs; -my @opts = map "-D$_=${$::{$_}}", - qw(service path host - client client_addr client_port - server server_addr server_port); +our @opts; + +push @opts, "-D$_=${$::{$_}}" + for qw(service specpath spechost + client client_addr client_port + server server_addr server_port); + +fail "no user $serve_user" unless getpwnam($serve_user); + +syslog 'notice', "$client $service $uri $serve_user"; -my @cmd = ('userv', '-t300', @opts, $user, $service); +my @cmd = ('userv', '-t300', @opts, $serve_user, $service); no warnings; # suppress errors to stderr exec @cmd or fail "exec userv: $!"; diff --git a/git-daemon/git-service.in b/git-daemon/git-service.in index 43ff340..75e64d5 100755 --- a/git-daemon/git-service.in +++ b/git-daemon/git-service.in @@ -9,30 +9,33 @@ use strict; use warnings; +use POSIX; use Sys::Syslog; our ($client,$service,$specpath,$spechost,@opts); ${$::{$_}} = $ENV{"USERV_U_$_"} - for qw(service path host) + for qw(service specpath spechost client); -openlog "userv-$service", 'pid', 'daemon'; +openlog "userv-$service:$ENV{USER}", 'pid', 'daemon'; sub fail { syslog 'err', "$client @_"; exit } @@READ_URLMAP@@ -fail "No mapping for $uri ($ENV{USERV_USER})" unless defined $serve_user; +fail "No user $ENV{USER} mapping for $uri" unless defined $serve_user; -$1 = undef; -fail "Bad subdirectory $serve_dir" unless $serve_dir =~ m/$repo_regexp/o; -our $dir = $1; +$serve_dir = "$ENV{HOME}/$serve_dir" unless $serve_dir =~ m|^/|; -$dir = "$ENV{HOME}/$dir" unless $dir =~ m|^/|; +fail "Bad subdirectory $serve_repo" unless $serve_repo =~ m/$repo_regexp/o; +fail "bad config - repo-regexp does not capture" unless defined $1; +my $sani_repo= $1; -$dir = "$dir/$repo" if defined $repo; -$path = $check_export ? "$dir/git-daemon-export-ok" : $dir; +my $dir = $serve_dir.(length $sani_repo ? "/$sani_repo" : ''); + +my $path = $check_export ? "$dir/git-daemon-export-ok" : $dir; fail "$! $path" unless -e $path; -syslog 'notice', "$client $dir"; + +syslog 'notice', "$client $uri $dir"; @opts = qw( --strict ) if @opts == 0 and $service eq 'git-upload-pack'; diff --git a/git-daemon/git-urlmap b/git-daemon/git-urlmap new file mode 100644 index 0000000..10aaed2 --- /dev/null +++ b/git-daemon/git-urlmap @@ -0,0 +1,35 @@ +# Each line is one of: +# +# single-user [/] [] +# matching requests will be handled by +# and unless overridden by handled by +# serving subdirectories of +# +# multi-user [/] +# matching requests are only those those next +# path element starts with ~. The +# request will be handled by and unless +# overridden by will be handled by +# serving subdirectories of +# ( must be a relative path) +# +# repo-regexp +# For per-user service. Subrepos must match this +# regexp, which must contain a single matching +# group which is the filesystem pathname inside +# the . The default is (Tcl syntax): +# repo-regexp {^(\w[-+._0-9A-Za-z]*)$} +# +# [no-]require-git-daemon-export-ok +# For per-user service. Default is no-. +# +# Last match, or last setting, wins. +# s may start with ~ + +# here is an example, taken from chiark: +# +# single-user dotat.at fanf dotat-git +# single-user git.chiark.greenend.org.uk webmaster /u2/git-repos +# +# multi-user cabal.greenend.org.uk cabal-git +# multi-user git.chiark.greenend.org.uk public-git diff --git a/git-daemon/inetd.conf.in b/git-daemon/inetd.conf.in index a40382d..11bf717 100644 --- a/git-daemon/inetd.conf.in +++ b/git-daemon/inetd.conf.in @@ -1,2 +1,2 @@ # Example inetd.conf line for the userv git daemon. -git stream tcp nowait git @libuserv@/git-daemon git-daemon @etcuserv@/git-urlmap +git stream tcp nowait git /usr/sbin/tcpd @libuserv@/git-daemon -L@varlog@/git/userv-git-daemon.log @etcuserv@/git-urlmap diff --git a/git-daemon/read-urlmap b/git-daemon/read-urlmap index 6ae3237..0fd760f 100644 --- a/git-daemon/read-urlmap +++ b/git-daemon/read-urlmap @@ -18,51 +18,73 @@ # $repo_regexp # $require_exportok -die "no config" unless @ARGV; - sub remain_path ($) { # return value matches {( / [^/]+ )+}x - my ($p) = @_; - return "/$specpath" if !defined $p; - return "" if $p eq $specpath; - return substr($specpath,length($p)) - if substr($specpath,0,length($p)+1) eq "$p/"; + my ($vsubpath) = @_; + syslog 'debug', sprintf "DEBUG remain_path %s $specpath", + (defined $vsubpath ? $vsubpath : ''); + return "/$specpath" if !defined $vsubpath; + return "" if $vsubpath eq $specpath; + return substr($specpath,length($vsubpath)) + if substr($specpath,0,length($vsubpath)+1) eq "$vsubpath/"; return undef; } -die unless length $specpath; +fail "no config ??" unless @ARGV; +fail "no specpath ??" unless length $specpath; our $uri = "git://$spechost/$specpath"; -our $repo_regexp= '^/*(\\w[-+._0-9A-Za-z]*)$'; +our $repo_regexp= '^/*(\\w[-+._0-9A-Za-z]*)$'; # stupid emacs '; our $check_export= 0; +our ($serve_user, $serve_dir, $serve_repo); + +sub fexists ($) { + my ($f) = @_; + if (stat $f) { + -f _ or fail "bad config $_ - not a file"; + return 1; + } else { + $!==&ENOENT or fail "bad config $_ - could not stat: $!"; + return 0; + } +} + +@ARGV = grep { fexists($_) } @ARGV; + while (<>) { + s/^\s*//; s/\s+$//; next unless m/\S/; next if m/^\#/; if (m{^ single-user \s+ (\S+?) (/\S*)? \s+ (\S+) (?: \s+ (\S+) )? $ }x) { - my ($h,$p,$u,$d) = ($1,$2,$3,$4); - next unless $h ne $host; - $serve_repo= remain_path($p); + my ($h,$v,$u,$d) = ($1,$2,$3,$4); + next unless $h eq $spechost; + $serve_repo= remain_path($v); next unless defined $serve_repo; $serve_user= $u; $serve_dir= $d; + syslog 'debug', "DEBUG $ARGV:$. match". + " $serve_user $serve_dir $serve_repo"; } elsif (m{^ multi-user \s+ (\S+?) (/\S*)? \s+ (\S+) $ }x) { - my ($h,$p,$d) = ($1,$2,$3); - next unless $1 ne $host; - $serve_repo= remain_path($p); - next unless defined $serv_repo; - next unless $serve_repo =~ s{ ^/\~( [a-z][-+_0-9a-z] )/$ }{ / }xi; - $serve_user= $u; + my ($h,$v,$d) = ($1,$2,$3); + next unless $1 eq $spechost; + $serve_repo= remain_path($v); + next unless defined $serve_repo; + syslog 'debug', "DEBUG $ARGV:$. perhaps $serve_repo"; + next unless $serve_repo =~ s{ ^/\~( [a-z][-+_0-9a-z]* )/ }{/}xi; + $serve_user= $1; $serve_dir= $d; + syslog 'debug', "DEBUG $ARGV:$. match". + " $serve_user $serve_dir $serve_repo"; } elsif (m{^ repo-regexp \s+ (\S.*) $ }x) { $repo_regexp= $1; } elsif (m{^ (no-)?require-git-daemon-export-ok $ }x) { $check_export= !defined $1; } else { - die "bad config"; + fail "config syntax error at $ARGV:$."; } } diff --git a/settings.make b/settings.make index bd9313c..c74afc2 100644 --- a/settings.make +++ b/settings.make @@ -30,6 +30,7 @@ docdir= $(sharedir)/doc libuserv= $(libdir)/userv shareuserv= $(sharedir)/userv +varlog= $(vardir)/log varlib= $(vardir)/lib varlibuserv= $(varlib)/userv