#!/usr/bin/perl -w
#------------------------------------------------------------------
# 
# Karma Copyright (C) 1999  Sean Hull <shull@pobox.com>
#
#   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.
#
#   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
#
#
#------------------------------------------------------------------
#
# karmactl
#
# start, stop, reload, status of running karmad daemon
#
#------------------------------------------------------------------

#
# current version
#
#$VERSION="0.9.0";
require 5.004;
use strict;
use Getopt::Std;
use IO::File;
use karma;

$main::KARMA_HOME = ".";
if (defined $ENV{KARMA_HOME}) {
    $main::KARMA_HOME = $ENV{KARMA_HOME};
}

#
# look in the path if all else fails...
#
$main::KARMA = "karmad";
#
# look for karmad in the main::KARMA_HOME
#
if ((defined $ENV{KARMA_HOME}) && 
    (-e "$ENV{KARMA_HOME}/karmad") &&
    (-x "$ENV{KARMA_HOME}/karmad")) {
    $main::KARMA = "$ENV{KARMA_HOME}/karmad";

# 
# look for it in the current directory
#
} elsif ((-e "./karmad") && (-x "./karmad")) {
    $main::KARMA = "./karmad";
}



$main::KARMA_FIFO_NAME = "$main::KARMA_HOME/.karmafifo";
$main::KARMA_PID_FILE = "$main::KARMA_HOME/.karma.pid";
$main::KARMA_DOC="$main::KARMA_HOME/doc_root";
$main::DEL_CMD = "/bin/rm";


#$main::opt_h = 0;
$main::opt_s = undef;
$main::opt_p = undef;
$main::opt_r = undef;
$main::opt_t = undef;
$main::opt_w = undef;
$main::opt_v = undef;
$main::opt_i = undef;
$main::opt_c = undef;
$main::opt_l = undef;
$main::opt_d = undef;
$main::opt_f = undef;
getopts('hspfrtwvi:k:l:c:d');

if (defined ($main::opt_w)) {
    print_warranty ();
}
if (defined ($main::opt_s)) {
    start_karma ();
}

#
# determine the process id if karma is already running
#
$main::KARMA_PID = 0;
if (defined ($main::opt_i)) {
    $main::KARMA_PID = $main::opt_i;
} else {
    $main::KARMA_PID = get_pid ();
}

if (defined ($main::opt_f)) {
    refresh_karma ();
}
if (defined ($main::opt_p)) {
    stop_karma ();
}
if (defined ($main::opt_r)) {
    reload_karma ();
}
if (defined ($main::opt_t)) {
    status_karma ();
}
if (defined ($main::opt_v)) {
    print_version ();
}
if (defined ($main::opt_d)) {
    if (defined $main::opt_k) {
	$main::KARMA_DOC=$main::opt_k;
    }
    cleanup_karma ();
}

print_help ();

#-----------------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------------
sub print_help () {
    print 
	"\n",
	" -h print help and exit\n",
	" -v print version and exit\n",
	" -f force a refresh of all service statuses\n",
	" -w print warranty and exit\n",
	" -s start karmad daemon\n",
	" -p stop karmad daemon\n",
	" -t print status of running karmad daemon\n",
	" -r reload karam.conf config file\n",
	" -i specify process id (if lock file is missing)\n",
	" -l specify logfile for karmad (ignored if not starting karmad)\n",
	" -c specify karma config file (ignored if not starting karmad)\n",
	" -k specify karma doc_root\n",
	" -d delete dynamically created karma files (karma.html, info/*.html)",
	"\n",
	"$0 [-h|-v|-w|-s|-p|-t|-r|-d] [-l file] [-c file] [-k dir]\n";
    exit;
}

#-----------------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------------
sub start_karma () {

    print ("Starting karma daemon");
 
    my $COMMAND = "$main::KARMA";
    if ($main::opt_l) {
	print ", logfile: $main::opt_l";
	$COMMAND .= " -l $main::opt_l";
    }
    if ($main::opt_c) {
	print ", config: $main::opt_c";
	$COMMAND .= " -c $main::opt_c";
    }
    if ($main::opt_k) {
	print ", doc_root: $main::opt_k";
	$COMMAND .= " -k $main::opt_k";
    }
    print "...\n";

#    $COMMAND .= " &";

#    my $pid = 0;
#    if ($pid = fork) {
#	system ($COMMAND);
#    } 

    system ($COMMAND);

    #
    # give karma messages a chance to print
    #
    sleep (1);

    exit;
}


#-----------------------------------------------------------------------
#
# get main::KARMA_PID from lock file, send kill signal (TERM)
#
#-----------------------------------------------------------------------
sub stop_karma () {

    if ($main::KARMA_PID > 0) {
	print ("Stopping karma daemon - pid:$main::KARMA_PID...\n");
	kill TERM => $main::KARMA_PID
	    or die ("Can't stop pid:$main::KARMA_PID - $!\n");
    } else {
	print
	    "Can't determine process id from pid file, use -i to \n",
	    "specify on the command line.\n";
    }
    exit;
}


#-----------------------------------------------------------------------
#
# give karmad the USR2 signal to make all service statuses refresh
#
#-----------------------------------------------------------------------
sub refresh_karma () {

    if ($main::KARMA_PID > 0) {
	print ("Refreshing karma service statuses pid:$main::KARMA_PID...\n");
	kill USR2 => $main::KARMA_PID
	    or die ("Can't refresh pid:$main::KARMA_PID - $!\n");
    } else {
	print
	    "Can't determine process id from pid file, use -i to \n",
	    "specify on the command line.\n";
    }
    exit;
}

#-----------------------------------------------------------------------
#
# get main::KARMA_PID from lock file, send USR1 signal
#
#-----------------------------------------------------------------------
sub status_karma () {

    my $line = "";
    if ($main::KARMA_PID > 0) {
#	print ("Getting status of karma daemon - pid:$main::KARMA_PID...\n");

	kill USR1 => $main::KARMA_PID
	    or die ("Can't get status of pid:$main::KARMA_PID - $!\n");

	open (FIFO, "<$main::KARMA_FIFO_NAME");
	while ($line = <FIFO>) {
	    
	    print ("$line");
	}
	close (FIFO);
    }    

    exit;
}


#-----------------------------------------------------------------------
#
# delete dynamically generated files in the karma doc_root directory
#
#-----------------------------------------------------------------------
sub cleanup_karma () {

    my $COMMAND = "";
    if (-d $main::KARMA_DOC) {
	if (-w $main::KARMA_DOC) {
	    $COMMAND = "$main::DEL_CMD $main::KARMA_DOC/karma.html";
	    system ($COMMAND);
	    $COMMAND = "$main::DEL_CMD $main::KARMA_DOC/info/*.html";
	    system ($COMMAND);
	} else {
	    print ("Cannot delete dynamic karma files: $main::KARMA_DOC\n");
	}
    } else {
	print ("Not a directory: $main::KARMA_DOC\n");
    }
    exit;
}



#-----------------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------------
sub reload_karma () {

    if ($main::KARMA_PID > 0) {
	print ("Reloading karma.conf config pid:$main::KARMA_PID...\n");
	kill HUP => $main::KARMA_PID
	    or die ("Can't reread config file pid:$main::KARMA_PID - $!\n");
    } else {
	print
	    "Can't determine process id from pid file, use -i to \n",
	    "specify it on the command line the command line.\n";
    }
    exit;
}

#-----------------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------------
sub get_pid () {

    my $line = undef;

    $main::KARMA_PID_file = new IO::File "<$main::KARMA_PID_FILE";
    if (defined ($main::KARMA_PID_FILE)) {
	$line = <$main::KARMA_PID_file>;
	close ($main::KARMA_PID_file);
	if (defined ($line)) {
	    chomp ($line);
	    $line =~ s/\N//g;
	    return $line;
	}
    } else {
	print ("Can't seem to open pid file: $main::KARMA_PID_FILE - $!\n");
    }
    return 0;
}
