source: server/common/oursrc/execsys/gitproxy.pl @ 851

Last change on this file since 851 was 851, checked in by andersk, 16 years ago
Check the right message length.
  • Property svn:executable set to *
File size: 3.4 KB
Line 
1#!/usr/bin/perl
2#
3# gitproxy: Wrapper around git daemon for Git virtual hosting.
4# version 1.0, released 2008-10-08
5# Copyright © 2008 Anders Kaseorg <andersk@mit.edu>
6#
7# This program is free software; you can redistribute it and/or
8# modify it under the terms of the GNU General Public License
9# as published by the Free Software Foundation; either version 2
10# of the License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21use strict;
22use warnings;
23use IPC::Open2;
24use Errno qw(EINTR);
25
26# Receive the first message from the client, and parse out the URL.
27my $host;
28my $msg = '';
29for (;;) {
30    my $n = sysread(STDIN, my $buf, 4096);
31    next if $n < 0 and $! == EINTR;
32    $n >= 0 or die "$0: read: $!";
33    $n > 0 or die "$0: unexpected message from client";
34    $msg .= $buf;
35    my $len;
36    if (($len) = $msg =~ m/^([[:xdigit:]]{4})/ and length($msg) >= hex($len)) {
37        foreach (split("\0", $')) {
38            last if ($host) = m/^host=(.*)$/;
39        }
40        last if defined($host);
41        die "$0: no host found in client message";
42    } elsif ($msg !~ m/^[[:xdigit:]]{0,3}$/) {
43        die "$0: unexpected message from client";
44    }
45}
46
47# Now start the real git daemon based on the URL.
48open2(\*IN, \*OUT, '/usr/local/sbin/ldapize.pl', "git://$host/") or die "$0: open: $!";
49
50# Finally, go into a select loop to transfer the remaining data
51# (STDIN -> OUT, IN -> STDOUT), including the client's message to git daemon.
52my ($cbuf, $sbuf) = ($msg, '');
53my ($rin, $win, $ein) = ('', '', '');
54my ($stdout, $out, $stdin, $in) = (fileno(STDOUT), fileno(OUT), fileno(STDIN), fileno(IN));
55vec($win, $stdout, 1) = 0;
56vec($win, $out, 1) = 1;
57vec($rin, $stdin, 1) = 0;
58vec($rin, $in, 1) = 1;
59while (vec($win, $stdout, 1) or vec($win, $out, 1) or
60       vec($rin, $stdin, 1) or vec($rin, $in, 1)) {
61    my $n = select(my $rout = $rin, my $wout = $win, my $eout = $ein, undef);
62    next if $n < 0 and $! == EINTR;
63    $n >= 0 or die "select: $!";
64    if (vec($rout, $stdin, 1)) {
65        my $n = sysread(STDIN, $cbuf, 4096);
66        next if $n < 0 and $! == EINTR;
67        $n >= 0 or die "read: $!";
68        vec($rin, $stdin, 1) = 0;
69        vec($win, $out, 1) = 1;
70    } elsif (vec($rout, $in, 1)) {
71        my $n = sysread(IN, $sbuf, 4096);
72        next if $n < 0 and $! == EINTR;
73        $n >= 0 or die "read: $!";
74        vec($rin, $in, 1) = 0;
75        vec($win, $stdout, 1) = 1;
76    } elsif (vec($wout, $stdout, 1) && $sbuf ne '') {
77        my $n = syswrite(STDOUT, $sbuf);
78        next if $n < 0 and $! == EINTR;
79        $n >= 0 or die "write: $!";
80        $sbuf = substr($sbuf, $n);
81        if ($sbuf eq '') {
82            vec($win, $stdout, 1) = 0;
83            vec($rin, $in, 1) = 1;
84        }
85    } elsif (vec($wout, $stdout, 1)) {
86        vec($win, $stdout, 1) = 0;
87        close(STDOUT) or die "close: $!";
88        close(IN) or die "close: $!";
89    } elsif (vec($wout, $out, 1) && $cbuf ne '') {
90        my $n = syswrite(OUT, $cbuf);
91        next if $n < 0 and $! == EINTR;
92        $n >= 0 or die "write: $!";
93        $cbuf = substr($cbuf, $n);
94        if ($cbuf eq '') {
95            vec($win, $out, 1) = 0;
96            vec($rin, $stdin, 1) = 1;
97        }
98    } elsif (vec($wout, $out, 1)) {
99        vec($win, $out, 1) = 0;
100        close(OUT) or die "close: $!";
101        close(STDIN) or die "close: $!";
102    }
103}
Note: See TracBrowser for help on using the repository browser.