#!/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(){ 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