#!/usr/bin/perl

use strict;
use lib '/etc/lilalo/';
use l3config;
use IO::Socket;
use POSIX qw(:sys_wait_h);

sub main;

main();

sub REAPER {
	1 until (-1 == waitpid(-1, WNOHANG));
	$SIG{CHLD} = \&REAPER;
}

sub process_was_killed
{
	# Здесь должна быть красивая процедура 
	# завершения демона
	unlink $Config{backend_pidfile};
	exit(0);
}

sub main {
	init_config();


	# Проверяем, возможно демон уже запущен
	# Если он работает, просто завершаемся
	if (open(PIDFILE, $Config{backend_pidfile})) {
		my $pid = <PIDFILE>;
		close(PIDFILE);
		if ( ! -e "/proc/$pid" || !`grep $Config{"l3-backend"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`) {
			print "Removing stale pidfile\n";
			unlink $Config{backend_pidfile}
				or die "Can't remove stale pidfile ". $Config{backend_pidfile}. " : $!";
		}
		else {
			print "l3-backend is already running\n";
			exit(0);
		}
	}

	# Уходим в background, если необходимо
	if ($Config{detach} =~ /^y/i) {
		#$Config{verbose} = "no";
		my $pid = fork;
		exit if $pid;
		die "Couldn't fork: $!" unless defined ($pid);

		open(PIDFILE, ">", $Config{backend_pidfile})
			or die "Can't open pidfile ". $Config{backend_pidfile}. " for wrting: $!";
		print PIDFILE $$;
		close(PIDFILE);

		for my $handle (*STDIN, *STDOUT, *STDERR) {
			open ($handle, "+<", "/dev/null")
				or die "can't reopen $handle to /dev/null: $!"
		}

		POSIX::setsid()
			or die "Can't start a new session: $!";

		$0 = $Config{"l3-backend"};
		
		$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
	}

	# Открываем сетевой сокет и слушаем
	my $server = IO::Socket::INET->new(
			LocalPort 	=> $Config{backend_port},
			Type		=> SOCK_STREAM,
			Reuse		=> 1,
			Listen		=> 10 );
	
	if (!$server) {
		die "Couldn't bind to socket ".$Config{backend_port}."\n";
	}

	$SIG{CHLD} = 'IGNORE';

	# При получении новых соединенений,
	# порождаем дочерние процессы
	while (my $client = $server->accept()) {
		my $pid;
		next if $pid = fork;
		die "fork: $!" unless defined $pid;

		# Это наш ответвлённый клиент
		close($server);

        my $saved_data = "";

		# Считываем данные и передаём их в точку получения
		open(OUT, ">>", $Config{"backend_datafile"});
		select OUT; $|=1;
		while(<$client>) {
			print OUT $_;
            $saved_data .= $_;
		}
		close(OUT);

            #open(LOG, ">>", "/tmp/l3-backend.log");
            #print LOG "Saved data:$saved_data\n";
            #close(LOG);

        while ($saved_data =~ m@<(session|command)>(.*)</\1>@sg) {

            #open(LOG, ">>", "/tmp/l3-backend.log");
            #print LOG "Found element $1\n";
            #close(LOG);
            
            my $element_name = $1;
            my $element = $2;
            if ($element =~ m@<l3cd>(.*?)</l3cd>@msg) {
# Обнаружен элемент l3cd
# Информация должна быть сохранена в соответствующий каталог
                my $l3cd = $1;
# Путь l3cd должен быть не пуст, 
# и в нём могут быть только символы латинского алфавита, цифры и знаки _ и -
                if ($l3cd && $l3cd =~ /^[a-zA-Z_\/0-9-]*/) {
                    system("mkdir -m 770 -p $Config{backend_datadir}/$l3cd");
                    if (open(OUT, ">>", $Config{"backend_datadir"}."/$l3cd/data.xml")) {
                        print OUT "<$element_name>".$element."</$element_name>";
                        close(OUT);
                    };
                }
            }
        }
	} 
	continue {
		# Наш родитель
		close ($client);
	}
}