#!/usr/bin/perl -s
package Flog;
local($V, %opts, %FILES);
$V = "0.02";
use sigtrap 'handler' => \&Flog::handler, "normal-signals";
$SIG{__DIE__} = \&Flog::handler;

#import switches... and undef them in main
foreach (qw(c d g o u)){
    $a = "main::$_";
    $opts{$_} = ${$a};
    undef ${$a}; }

open(DEBUG, ($opts{d} != 1 ? $opts{d} : ">/dev/tty8")) if $opts{d};
_init();

while(<STDIN>){
    print DEBUG if $opts{d};
    &main::flog(); }


sub become {
    my $user  = shift();
    my $group = shift();
    my $ret   = 0;
    
    unless( $user =~ /^\d*$/ ){
	$user  = (getpwnam($user))[2]; }
    unless( $group =~ /^\d*$/ ){
	$group = (getgrnam($group))[2]; }
    $ret += $user  && ($> = $user)  == $user  ? 1 : 0;
    $ret += $group && ($) = $group) == $group ? 2 : 0;
    return $ret;
}

sub debug {
    return unless $Flog::opts{d};
    my %level = (
		 0=>"notice",
		 1=>"error",
		 2=>"crit." );
    printf Flog::DEBUG "[%s] [$level{$_[0]}] $_[1]", scalar localtime(time);
}

sub fh {
    debug(0, fileno($_[0]), " $_[0] = $FILES{$_[0]} -> $FILES{$_[0]}->[0]\n");
    unless( fileno($_[0]) ){
	open($_[0], $FILES{$_[0]}->[0]) || $opts{d} &&
	    debug(1, "Unable to open $FILES{$_[0]}->[0]: $!\n");
	if( $FILES{$_}->[1] ){
	    select($_);
	    $|=1 }
    }
    return $_[0];
}

sub handler {
    my $SIG = shift();
    if( $SIG eq "HUP" ){
	debug(0, "SIGHUP received. Attempting to restart($$)\n");
	map(close($_), keys %main::FILES);
	_init(); }
    if($SIG =~ /TERM|DIE|INT/ ){
	Flog::debug(0, "caught SIG$SIG, shutting down\n");
	map(close($_), keys %main::FILES);
	exit 0; }
}

sub _init {
#    &become($opts{u}||undef, $opts{g}||undef);
    package main;
    do $Flog::opts{c};
    if( $@ ){
	Flog::debug(2, "clogger $V($$) configuration compilation failed -- exiting\n");
	exit 0}
    else{
	Flog::debug(0, "clogger $V($$) configured -- resuming normal operations\n"); }
}

sub init {
    my $pkg = (caller())[0];

    #Make flog aware of the files
    foreach my $key ( keys %{"${pkg}::FILES"} ){
        $FILES{"{$pkg}::{$key}"} = ${"${pkg}::FILES"}{$key}; }

    unless( $opts{o} ){
	debug(0, "clogger $V($$) Pre-opening %%FILES for $pkg\n");
	map(&fh($_), keys %FILES);
	select(STDOUT); }
    else{
	debug(0, "clogger $V($$) NOT pre-opening %%FILES for $pkg\n"); }
    *{"${pkg}::printFlog"} = \&Flog::printFlog;
}

sub printFlog {
    my $pkg = (caller())[0];

    print { &Flog::fh("{$pkg}::{$_[0]}") } $_;
    $_[1] && close({ "${pkg}}::$_[0]" });
}

__DATA__
-u & -g options to setuid and setgid !! :-) better security...
ESP. if multi vhosts with multi flog processes
