#!/usr/bin/perl -w

# Source: @RPM_PACKAGE_VERSION@-@RPM_PACKAGE_RELEASE@

BEGIN { unshift(@INC,($ENV{'POPHOME'}||'@POPHOME@').'/lib')
            unless $ENV{'KUNDE_NO_PERLPATH'};
      }

use utf8;
use warnings;
use strict;
use Cf qw($LOGDIR);
use Dbase::Globals;
use Errno;
use Fcntl qw(O_CREAT O_EXCL O_WRONLY);
use File::Path qw(mkpath);
use Socket;
use Umlaut qw(binmodus);

umask 007;
binmodus(\*STDIN);

$/="";
$|=1;
my $data = <STDIN>; die "No connect\n" unless defined $data;
my %hdr;

foreach my $line(split(/\n/,$data)) {
	my($hdr,$text)=split(/\s+/,$line,2);
	$text =~ s#/#_#g if defined $text;
	$hdr{lc($hdr)} = $text;
}

unless($hdr{'host'}) {
	my $res = getpeername(fileno(STDIN));
	my ($port, $iaddr) = unpack_sockaddr_in($res);
	$hdr{'host'} = gethostbyaddr($iaddr, AF_INET);
}
unless($hdr{'host'}) {
	print "Kein Rechnername bekannt!\n";
	exit(1);
}

my $fn   = "$LOGDIR/incoming/" . ( delete $hdr{host} ) . '/';
my $time = delete $hdr{time} || time;
my $fnx  = delete $hdr{file};
my $size = delete $hdr{size};
foreach my $key(sort keys %hdr) {
	$fn .= defined $hdr{$key} ? "${key}_$hdr{$key}/" : "$key/";
}
$fn .= "$fnx/" if defined $fnx;

mkpath($fn);

my $fntmp;
while(1) {
	# Strenggenommen ist die nächste Zeile überflüssig
	next if -f "$fn.$time" or -f "$fn$time";

	if(sysopen LOG, $fntmp = "$fn.$time", O_CREAT|O_EXCL|O_WRONLY) {
		last unless -f "$fn$time"; # race condition?
		close LOG;
		unlink "$fn.$time";
		next;
	}
	next if $!{EEXIST};
	print "Konnte Logdatei '$fntmp' nicht zum Schreiben öffnen: $!\n";
	exit 1;
} continue {
	$time++;
}
$fn .= $time;

binmodus(\*LOG);

my $len = 0;

while(my $len1 = read(STDIN,$data,8192)) {
	print LOG $data or do {
	    print "Konnte Log '$fntmp' nicht schreiben (nach $len bytes): $!\n";
	    unlink $fntmp;
	    exit 1;
	};
	$len += $len1;
}
close LOG or do {
	    print "Konnte Log '$fntmp' nicht schreiben (nach $len bytes): $!\n";
	    unlink $fntmp;
	    exit 1;
};
if($size and $size != $len) {
	print "Erwarte $size Bytes, bekomme $len ??\n";
	unlink $fntmp;
	exit 1;
}

rename($fntmp,$fn) or do {
	    print "Konnte Log '$fn' nicht umbenennen: $!\n";
	    unlink "$fn.tmp";
	    exit 1;
};
print "OK\n$len bytes\n";
exit 0;

__END__

=head1 Name

logserver -- Speichert Logdateien ab

=head1 Zusammenfassung

	logserver 

wird via inetd gestartet.

=head1 Beschreibung

Der Logserver liest Daten der Form

key1 wert
key2 wert2

DATENDATENDATEN

von stdin (normalerweise ein Socket) und speichert sie ab. Bei 100%igem
Erfolg schreibt er 'OK' und eine Statusmeldung, ansonsten passiert
effektiv nichts und er schreibt eine Fehlermeldung.

Das Ziel des Logs ist
C<I<LOGDIR>/host_I<HOSTNAME>/key1_wert/key2_wert2/I<FILE>/I<TIME>>.

=head2 Keys

Die folgenden Schlüsselwörter haben eine spezielle Bedeutung:

=over 4

=item C<size>

Größe der folgenden Datei.

Am Dateiende muß der Sender den Socket sendeseitig schließen. 
Stimmt die Größe nicht mit dem anfangs gesendeten Wert überein, wird
ein Fehler gemeldet und die Datei nicht abgespeichert.

=item C<host>

Quellrechner (I<HOST>). Default: Via Nameserver aus der IP-Adresse des
Rechners, von dem die Daten kommen.

=item C<time>

Timestamp (I<TIME>). Default: aktuelle Zeit (unixtime).

=item C<file>

Dateiname (I<FILE>). Default: Leer.

=back

=head1 Daten

Der Logserver greift auf folgende Datenbestände zu:

=head2 C</etc/pop.conf>

Konfigurationsvariablen:

=over 4

=item C<LOGDIR>

Basisverzeichnis für die Logdateien.

=back

=head1 ToDo

Hmmm...

=cut

