#!/usr/bin/perl -I/usr/local/sauron
#
# status -- utlity to query/modify system status
#
# Copyright (c) Michal Kostenec <kostenec@civ.zcu.cz> 2013-2014.
# Copyright (c) Timo Kokkonen <tjko@iki.fi>  2001-2003.
# $Id: status,v 1.30 2008/08/25 07:02:58 tjko Exp $
#
require 5;
use Getopt::Long;
use Sauron::DB;
use Sauron::Util;
use Sauron::BackEnd;
use Sauron::Sauron;
require Sauron::CGIutil;
require Sauron::UtilDhcp;
require Sauron::UtilZone;
require CGI;
require Net::DNS;
require Net::IP;

load_config();

##############################################

$argcount=@ARGV;

$result = GetOptions("cgi-enable","cgi-disable=s","help|h","pending:s",
		     "quiet","versions","config");

if ($opt_help || not $result) {
  print "syntax: $0 [options]\n\n",
    "options:\n",
    " --help                       display this help\n",
    " --pending                    display number of hosts pending\n",
    " --pending=<servername>       display pending hosts for a server\n\n",
    " --cgi-disable='message'      disable CGI interface\n",
    " --cgi-enable                 enable CGI interface\n",
    " --versions                   display module versions\n",
    " --config                     display current configuration values\n",
    " --quiet                      no verbose output\n";
  print "\n" if ($opt_help || $opt_cgi_enable); # to get rid of warnings :)
  exit(0);
}

if ($opt_versions) {
  print "Sauron: ",sauron_version(),"\n\n";

  print "CGI: ",$CGI::VERSION,"\n";
  print "Digest::MD5: ",$Digest::MD5::VERSION,"\n";
  print "Pg: ",$Pg::VERSION,"\n" if ($Pg::VERSION);
  print "DBI: ",$DBI::VERSION,"\n" if ($DBI::VERSION);
  print "Net::DNS: ",$Net::DNS::VERSION,"\n";
  print "Net::IP: ",$Net::IP::VERSION,"\n";
  print "Net::Netmask: ",$Net::Netmask::VERSION,"\n\n";

  print "Sauron::Sauron: ",($Sauron::Sauron::VERSION =~ /,v\s+(\S+)\s/),"\n";
  print "Sauron::BackEnd: ",($Sauron::BackEnd::VERSION =~ /,v\s+(\S+)\s/),"\n";
  print "Sauron::CGIutil: ",($Sauron::CGIutil::VERSION =~ /,v\s+(\S+)\s/),"\n";
  print "Sauron::DB: ",($Sauron::DB::VERSION =~ /,v\s+(\S+)\s/),"\n";
  print "Sauron::Util: ",($Sauron::Util::VERSION =~ /,v\s+(\S+)\s/),"\n";
  print "Sauron::UtilDhcp: ",($Sauron::UtilDhcp::VERSION =~ /,v\s+(\S+)\s/),
        "\n";
  print "Sauron::UtilZone: ",($Sauron::UtilZone::VERSION =~ /,v\s+(\S+)\s/),
        "\n\n";


  my @modules = ( 'Sauron::CGI::Utils',
		  'Sauron::CGI::Servers',
		  'Sauron::CGI::Zones',
		  'Sauron::CGI::Hosts',
		  'Sauron::CGI::Nets',
		  'Sauron::CGI::Groups',
		  'Sauron::CGI::Templates',
		  'Sauron::CGI::Login' );
  my $i;
  for $i (0..$#modules) {
    print "$modules[$i]: ";
    eval "require $modules[$i];";
    if ($@) {
      print "failed to load this module!\n";
    } else {
      my $ver;
      eval '$ver = $'.$modules[$i].'::VERSION;';
      print "",($ver =~ /,v\s+(\S+)\s/) , "\n";
    }
  }


  print "\n";
}

if ($opt_config) {
  print "{CONFIG_FILE=$CONFIG_FILE}\n";
  print_config();
}

exit if ($opt_versions || $opt_config);

$db_ok = db_connect2();

$VER=sauron_version();
$DBVER=sauron_db_version();
$dbversion=get_db_version() if ($db_ok);

fatal("Missing database version (empty database?)") if ($dbversion =~ /ERROR/);


if ($argcount < 1 && (! $opt_quiet)) {
  print "Sauron v$VER status\n\n";
  printf "Database connection:   %s\n", ($db_ok?"OK":"ERROR");
  exit unless ($db_ok);
  printf "Database version:      %s\t%s\n", $dbversion,
    ($dbversion < $DBVER ? "Database version too old ($DBVER required)!":'');
}

exit unless ($db_ok);

get_server_list(-1,\%servers_h,\@servers);

if (defined $opt_pending) {
  unless ($opt_pending) {
    # check all servers...

    unless ($opt_quiet) {
      print "Pending changes modifications:\n\n",
	    "Server                                             Hosts Zones\n",
	    "------------------------------------------------   ----- -----\n";
    }
    for $i (0..$#servers) {
      $serverid=$servers[$i];
      next if ($serverid < 0);
      $server=$servers_h{$serverid};
      get_server($serverid,\%server);
      $lastrun=($server{lastrun} > 0 ? $server{lastrun} : 0);

      $modifiedserver=( ($server{cdate} > $server{lastrun}) ||
			($server{mdate} > $server{lastrun}) ? 1 : 0);
      db_query("SELECT COUNT(id) FROM zones WHERE server=$serverid AND " .
	       "(cdate > $lastrun OR mdate > $lastrun)",\@q);
      $modifiedzones=$q[0][0];

      db_query("SELECT COUNT(id) FROM zones " .
	       "WHERE server=$serverid AND rdate > serial_date",\@q);
      $removedhosts=($q[0][0] > 0 ? $q[0][0] : 0);
      db_query("SELECT COUNT(h.id) FROM hosts h, zones z " .
	       "WHERE z.server=$serverid AND h.zone=z.id " .
	       " AND (h.mdate > z.serial_date OR h.cdate > z.serial_date);",
	       \@q);
      next if ($opt_quiet && $q[0][0] < 1 && $removedhosts==0 &&
	       $modifiedzones==0 && $modifiedserver==0);
      printf "%-50s %5d %5d %s\n",substr($server,0,50),$q[0][0]+$removedhosts,
	      $modifiedzones,($modifiedserver ? 'server' : '');
    }
    exit;
  }


  # check specific server only...

  $totalcount=0;
  $serverid=get_server_id($opt_pending);
  fatal("cannot find server '$opt_pending'") unless ($serverid > 0);
  get_server($serverid,\%server);
  $lastrun=$server{lastrun};
  $modifiedserver=( ($server{cdate} > $server{lastrun}) ||
		    ($server{mdate} > $server{lastrun}) ? 1 : 0);
  print "Pending modifications for server: $opt_pending (id=$serverid)\n"
    unless ($opt_quiet);
  print "Server record modified.\n" if ($modifiedserver && not $opt_quiet);
  $totalcount+=1 if ($modifiedserver);

  $zones=get_zone_list($serverid,'M','');
  for $i (0..$#{$zones}) {
    $zoneid=$$zones[$i][1];

    db_query("SELECT serial_date,rdate,cdate,mdate " .
	     "FROM zones WHERE id=$zoneid",\@q);
    $removedhosts=($q[0][1] > 0 && ($q[0][1] > $q[0][0]) ? $q[0][1] : 0);
    $zonemodified=($q[0][2] > 0 && ($q[0][2] > $lastrun) ? $q[0][2] : 0);
    $zonemodified=$q[0][3] if ($q[0][3] > 0 && ($q[0][3] > $lastrun));

    db_query("SELECT h.domain,h.cdate,h.mdate,h.cuser,h.muser " .
	     "FROM hosts h, zones z " .
	     "WHERE z.id=$zoneid AND h.zone=z.id " .
	     " AND (h.mdate > z.serial_date OR h.cdate > z.serial_date) " .
	     "ORDER BY h.domain;",\@q);
    $count=@q;
    next unless ($count > 0 || $removedhosts > 0 || $zonemodified > 0);
    $totalcount+=$count;
    $totalcount+=1 if ($removedhosts > 0);
    $totalcount+=1 if ($zonemodified > 0);
    next if ($opt_quiet);
    print "Zone: $$zones[$i][0] ($count)\n";

    printf "%-30s %6s  %-20s  %s\n",
           '<zone changes>','Edit',localtime($zonemodified).'',''
	     if ($zonemodified > 0);
    printf "%-30s %6s  %-20s  %s\n",
           '<removed host(s)>','Delete',localtime($removedhosts).'',''
	     if ($removedhosts > 0);

    for $j (0..$#q) {
      if ($q[$j][1] > $q[$j][2]) {
	$date=localtime($q[$j][1]); $user=$q[$j][3]; $mode='Create';
      } else {
	$date=localtime($q[$j][2]); $user=$q[$j][4]; $mode='Modify';
      }
      printf "%-30s %6s  %-20s  %s\n",$q[$j][0],$mode,$date,$user;
    }
  }

  exit(($totalcount > 0 ? 2 : 0));
}



if (defined $opt_cgi_enable) {
  db_exec("DELETE FROM settings WHERE setting='cgi_disable';");
  undef @q;
  db_query("SELECT value FROM settings WHERE setting='cgi_disable';",\@q);
  if (@q > 0) {
    print STDERR "Cannot enable CGI interface!\n";
    exit(1);
  }
  print "CGI interface successfully enabled\n";
  exit;
}

if ($opt_cgi_disable) {
  $msg=$opt_cgi_disable;
  if ($msg =~ /^\s*$/) {
    print "CGI disable requires message\n";
    exit;
  }
  $msg=db_encode_str($msg);
  undef @q;
  db_query("SELECT value FROM settings WHERE setting='cgi_disable';",\@q);
  if (@q > 0) {
    $res=db_exec("UPDATE settings SET value='$msg' WHERE setting='cgi_disable';");
  } else {
    $res=db_exec("INSERT INTO settings (setting,value) " .
		 "VALUES('cgi_disable',$msg);");
  }
  print "CGI interface successfully disabled.\n";
  exit;
}


undef @q;
db_query("SELECT value FROM settings WHERE setting='cgi_disable';",\@q);

unless ($opt_quiet) {
  printf "CGI interface:         %s\n",
    ($q[0][0] ne '' ? "Disabled ($q[0][0])":"Enabled");

  print "\n";
}


unless (@servers > 1) {
  print "No servers found in database!\n";
  exit;
}

$USER_TIMEOUT=3600 unless ($USER_TIMEOUT > 0);
$timeout=$USER_TIMEOUT;

get_who_list(\@who,$timeout);

if (@who > 0) {
  printf("%-8s %-22s %-39s %-6s %s\n",'USER','NAME','FROM','IDLE','LOGIN')
    unless ($opt_quiet);

  for $i(0..$#who) {
    printf("%-8s %-22s %-39s %-6s %s\n",
	   $who[$i][0],$who[$i][1],$who[$i][2],$who[$i][3],$who[$i][4]);
  }
} else {
  print "No users currently logged in.\n";
}

print "\n";
exit(0);

# eof


