#!/var/mwt/bin/svc/php
<?php
/**
Logger - general purpose logger, with autorotate capability
Version 0.1
Copyright (C) 2003 Greg MacLellan
Aug 12/2003

greg at mtechsolutions dot ca

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/copyleft/gpl.html


This program takes input from STDIN, and writes it to a specified file.

For example:

logger 4 /var/log/mylogfile


Will log STDIN to /var/log/mylogfile. Every day, it will archive yesterday's
log to /var/log/mylogfile.1, and the day before to /var/log/mylogfile.2, etc,
up to the number specified. The oldest files will get deleted.

Note that it's ok if there is a log file missing, however, if you have a .8,
and only have 7 specified on the command line (ie, you change the number of
days), it will not touch the .8 file anymore.

Sending the process HUP will make it re-open the log file, and sending TERM
will do a graceful shutdown.

Real use:

./somedaemon | logger 7 /var/log/somedaemon



I wrote this program as a quick hack to make syslog-style logs that rotate
themselves with no external crontab or configuration needed. Feel free to
improve and/or make changes, as it's licened under the GPL. If you find bugs,
either fix them and send me a patch, or
let me know and I'll see if I can fix it.


- Greg

*/


declare(ticks=1);

define("DATE_FORMAT""M d H:i:s");
define("DEBUG"0);

/*** Function definitions ***/

function signal_handler($signo) {
    global 
$lh$logfile;

    switch (
$signo) {
        case 
SIGHUP:
            
//reopen file
            
fwrite(STDOUT"caught SIGHUP, reopening log file\n");
            
fclose($lh);
            
$lh fopen($logfile"a");
        break;
        case 
SIGTERM:
            
//shut down
            
fwrite(STDOUT"caught SIGTERM, shutting down\n");
            
fclose($lh);
            exit(
0);
        break;
    }
}

/** returns a "day stamp" .. number of days since jan 1 1970 gmt
 */
function unixdays($date) {
    
// (date + timezone-offset) / seconds-in-a-day
    
return floor( ($date+date("Z")) / 86400 );
}

function 
rotate($fileprefix$days) {
    if (
file_exists($fileprefix.".".$days)) {
        
// delete oldest
        
fwrite(STDOUT"deleting ".$fileprefix.".".$days."\n");
        
unlink($fileprefix.".".$days);
    }

    for (
$i $days-1$i >= 0$i--) {
        
debug($i);
        
//(if $i = 0, then it means just $fileprefix)
        
$old $fileprefix.(($i>0) ? ".".$i "");
        
$new $fileprefix.".".($i+1);

        if (
file_exists($old)) {
            
// rename it
            
fwrite(STDOUT"renaming ".$old." to ".$new."\n");
            
rename($old$new);
        }
    }
}

function 
debug($text) {
    if (
DEBUG != 0) {
        
fwrite(STDOUT"::DEBUG:: ".$text."\n");
    }
}

/*** Main code ***/

pcntl_signal(SIGTERM"signal_handler"); // set signal handlers
pcntl_signal(SIGHUP"signal_handler");

// parse days commmand-line arg
if (!isset($_SERVER["argv"][1]) || !is_numeric($_SERVER["argv"][1])) {
    
showHelp();
    exit(
255);
}
$days $_SERVER["argv"][1];

// parse filename command-line arg
if (!isset($_SERVER["argv"][2])) {
    
showHelp();
    exit(
255);
}
$logfile $_SERVER["argv"][2];

if (
file_exists($logfile)) {
    
debug("filetime ".date("r"filemtime($logfile)));
    
debug("unixdays ".unixdays(filemtime($logfile)));
    
debug("unixdays now ".unixdays(time()) );
    if (
unixdays(filemtime($logfile)) != unixdays(time())) {
        
// rotate files before we start to write
        
debug("rotating files");
        
rotate($logfile$days);
    }
}

$lastwrite time();

// open the log file
$lh fopen($logfile"a");
while (
$data fgets(STDIN,1024)) {
    if (
strlen($data) > 1) {
        
$time time();

        
// check if we need to rotate files
        
if (unixdays($lastwrite) != unixdays(time())) {
            
// rotate
            
rotate($logfile$days);
        }

        
$lastwrite time();
        
fwrite($lhdate(DATE_FORMAT,$time)." ".$data);
    }
}
fclose($lh);

?>