#!/usr/bin/perl
use strict;
use warnings;

use IO::Handle;
use Socket;
use POSIX qw(setsid);

# Process-Namen für /etc/init.d/functions erkennbar machen
$0 =~ s/^.*\///;

my $logfile = "/dev/null";
if (($ARGV[0] eq "-l") && $ARGV[1]) { $logfile = $ARGV[1]; }

&daemonize ();

# Mit INADDR_ANY läuft der Server auf allen IP Adressen des Hosts
use constant LISTEN_ADDRESS => INADDR_ANY;

# Port-Nummer auf der der Server läuft
use constant DAYTIME_PORT => '13';

# TCP Protokollnummer ermitteln
my $protocol = getprotobyname ('tcp');

# Handler für STRG+C bestimmen
my $quit = 0;
$SIG{'INT'} = sub { warn "Daytime beenden...\n"; $quit = 1; };

# Socket-Endpunkt einrichten
socket (SOCK, AF_INET, SOCK_STREAM, $protocol) || die "Socketerstellung fehlgeschlagen: $!";
setsockopt (SOCK, SOL_SOCKET, SO_REUSEADDR, 0) || die "Konnte SO_REUSEADDR nicht setzen: $!";
my $my_addr = sockaddr_in (DAYTIME_PORT, LISTEN_ADDRESS);
bind (SOCK, $my_addr) || die "Konnte Server nicht binden: $!";
listen (SOCK, SOMAXCONN) || die "listen ist fehlgeschlagen: $!";

my $daytime = localtime ();
warn "[$daytime]\tDaytime-Server wartet auf Verbindung...\n";

while (!$quit) {
	
	# Verbindung akzeptieren
	next unless my $remote_addr = accept (SESSION, SOCK);

	# Client identifizieren
	my ($port, $connect_addr) = sockaddr_in ($remote_addr);

	# Pufferung deaktivieren
	SESSION->autoflush (1);

	# Das Datum wird gesendet
	$daytime = localtime ();
	print SESSION "$daytime\n" || warn "[$daytime]\tVerbindung von ".inet_ntoa ($connect_addr).":".$port." abgebrochen.\n";

	# Verbindung beenden
	close (SESSION);
	warn "[$daytime]\tVerbindung von ".inet_ntoa ($connect_addr).":".$port." erfolgreich beendet.\n";
}

# Socket-Endpunkt schließen
close (SOCK);
$daytime = localtime ();
warn "[$daytime]\tDaytime geschlossen.\n";

exit;

sub daemonize {
	chdir '/'			or die "Can't chdir to /: $!";
	open STDIN, '/dev/null'		or die "Can't read /dev/null: $!";
	open STDOUT, '>>/dev/null'	or die "Can't write to /dev/null: $!";
	open STDERR, '>>'.$logfile	or die "Can't write to $logfile: $!";
	(my $pid = fork) && exit;
	setsid				or die "Can't start a new session: $!";
	umask 0;
}
