# This is a work in progress! # NOT FOR THE FAINT OF HEART # Multi-process multi-host log with distributed configuration # In this example # Jon and Tom both get their own logs and config files # CGI accesses receive thier own log # Images get their own log # Everything else is logged to the usual place # Current Caveats # -u likely cannot be used, since flog needs to setuid # (which washes out to be roughly the same...) perhaps -g as well # you should read man Safe # User logs should: preexist, not be opened for clobber else may be owned by user running flog (root)... #add 3rd option to FILES to decide what user to open as? (this req's forking in flog itself :-( use Safe; sub spawn; my($user, $comparment, %OENV); my %FILES= ( IMAGES=>[">>/var/log/httpd/images.log"], TOM=>[">>/home/tom/access.log"], JON=>[">>/home/jon/access.log"], CGI=>[">>/var/log/httpd/cgi.log"], CATCH=>[">>/var/log/httpd/access.log"] ); %OENV=%ENV; undef %ENV; foreach $user ( qw(tom dick harry) ){ #Sandbox the user $compartment{$user} = new Safe $user; die($compartment); $compartment{$user}->rdo("~$user/.flog.pl"); #Make flog aware of the files foreach $key ( keys %{$user::FILES} ){ $FILES{"{$user}::{$key}"} = ${$user::FILES}{$key}; } } %ENV=%OENV; sub flog{ print CGI if m% /cgi-bin/%; if( m%tom\.com$% ){ return spawn sub { &flog::become("tom", "tom"); $compartment{"tom"}->reval("&flog()"); }} if( m%dick\.org$% ){ return spawn sub { &flog::become("dick", "friend"); $compartment{"dick"}->reval("&flog()"); }} if( m%harry\.net$% ){ return spawn sub { &flog::become("harry"); $compartment{"harry"}->reval("&flog()"); }} # Return if you do not wish to duplicate data across logs print CATCH; } #Straight from perlipc sub REAPER { wait; $SIG{CHLD} = \&REAPER; # loathe sysV } $SIG{CHLD} = \&REAPER; sub spawn { my $coderef = shift; unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') { die("usage: spawn CODEREF"); } my $pid; if (!defined($pid = fork)) { return; } elsif ($pid) { return; } # I'm the parent # else I'm the child -- go spawn #open(STDIN, "<&Client") || die "can't dup client to stdin"; #open(STDOUT, ">&Client") || die "can't dup client to stdout"; ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr"; exit &$coderef(); } 1;