#!/usr/bin/perl -w
#
# File: diskmond
#
# Purpose: diskmond checks every 60 seconds to make sure that the disk
#          utilization for the partition that holds the psad "fwdata"
#          file is not beyond a threshold that the administrator
#          defines.
#
# Author: Michael B. Rash (mbr@cipherdyne.com)
#
# Credits:  (see the CREDITS file)
#
# Version: 1.0.0-pre1
#
# Copyright (C) 1999-2002 Michael B. Rash (mbr@cipherdyne.com)
#
# License (GNU Public License):
#
#    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.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
#    USA
#
#########################################################################
#
# $Id: diskmond,v 1.5 2002/09/24 02:06:20 mbr Exp $
#

use Psad;
use File::stat;
use POSIX 'setsid';
use Getopt::Long 'GetOptions';
use strict;

### establish the default path to the config file (can be
### over-ridden with the -c <file> command line option.
my $CONFIG_FILE = '/etc/psad/psad.conf';

### handle command line arguments
die " @@@ Specify the path to the psad.conf file with \"-c <file>\".\n\n" unless (GetOptions (
    'config=s' => \$CONFIG_FILE
));

### read in the configuration file
my ($Config_href, $Cmds_href) = &Psad::buildconf($CONFIG_FILE);

### make sure the configuration is complete
&check_config();

my %Config = %$Config_href;
my %Cmds   = %$Cmds_href;
my $Archive_files_aref = $Config{'ARCHIVE_FILES'};

### Check to make sure the commands specified in the config section
### are in the right place, and attempt to correct automatically if not.
&Psad::check_commands(\%Cmds);

&Psad::unique_pid($Config{'DISKMOND_PID_FILE'});

### install WARN and DIE handlers
$SIG{'__WARN__'} = \&Psad::warn_handler;
$SIG{'__DIE__'}  = \&Psad::die_handler;

my $pid = fork;
exit if $pid;
die "@@@@@  $0: Couldn't fork: $!" unless defined($pid);
POSIX::setsid() or die "@@@@@  $0: Can't start a new session: $!\n";

### write the pid to the pid file
&Psad::writepid($Config{'DISKMOND_PID_FILE'});

### initialize partition usage
my $usage = 0;

my $config_mtime = stat($CONFIG_FILE)->mtime;
#====================== main =======================
### main loop
for (;;) {
    ### See if we need to import any changed config variables
    &check_import_config(\$config_mtime, $CONFIG_FILE);

    $usage = &get_usage();
    if ($usage >= $Config{'MAX_DISK_PERCENTAGE'}) {   ### Check to see if we need to start archiving
        &archive();
    }
    sleep $Config{'DISKMOND_CHECK_INTERVAL'};  ### check disk usage every $CHECK_INTERVAL seconds
}
exit 0;
#===================== end main ====================

sub get_usage() {
    my @df_data = `$Cmds{'df'} $Config{'PSAD_DIR'}`;
    my ($prcnt) = ($df_data[$#df_data] =~ /(\d+)%/);
    return $prcnt;
}
sub archive() {
    for my $file (@$Archive_files_aref) {
        system "$Cmds{'tail'} -200 $file > ${file}.bak";
        ### leave the file in place, but remove all of the data from it
        open F, "> $file";
        close F;
    }
    return;
}
sub check_import_config() {
    my ($mtime_ref, $file) = @_;
    my $mtime_tmp = stat($file)->mtime;
    if ($mtime_tmp != $$mtime_ref) {  ### the file was modified, so import

        ($Config_href, $Cmds_href) = &Psad::buildconf($file);

        ### make sure the configuration is complete
        &check_config();

        %Config = %$Config_href;
        %Cmds   = %$Cmds_href;
        $$mtime_ref = $mtime_tmp;
    }
    return;
}
sub check_config() {
    my @required_vars = qw(
        PSAD_LOGFILE FW_DATA DISKMOND_CHECK_INTERVAL
        MAX_DISK_PERCENTAGE ARCHIVE_FILES
        DISKMOND_PID_FILE
    );
    &Psad::validate_config($CONFIG_FILE, \@required_vars, $Config_href);
    return;
}
