#!/usr/bin/perl
# failoverd - master failover script to control things.
# $Source: /cvs/failoverd/failoverd,v $
# $Revision: 1.18 $ 
# $Date: 1999/06/03 22:32:34 $

use strict;
use Failover;
use Net::Daemon;
use Net::Ping; # for plip information

## fork
my $pid;
unless ( $pid = fork) {
  unless (fork) {

$0 = "failoverd (server)";

logger("failoverd booting as $type");
logger("failoverd listening on port $tcp_port"); # port to connect to for 
						 # failures

if ( $type eq "master" ) {
   server();
   notify();
   spawn(); # in Failover.pm
   ping();
 } elsif ( $type eq "slave" ) {
   kill_kids(); # stop any current watchd processes...see module
   server();
   ping();
 }

sub ping {

## keepalive for the private interface.
my $pid;
unless ( $pid = fork) {
  unless (fork) {
 $0 = "failoverd (ping)"; 
     my $ping_host;

     if ( $type eq "master" ) {
	$ping_host = $secondary;	
     } else { 
	$ping_host = $primary;
     } # if

  my $ping_obj = Net::Ping->new("icmp");
  logger("Keepalive set on @{$plip_int}[0] to $ping_host");  
  while ( $ping_obj ) {
	$ping_obj->ping($ping_host);

	sleep($plip_hbeat);
	pliptimer($plip_timer,$plip_interface,@{$plip_int}[1]);
	@{$plip_int}->[1]++;

		if ( @{$plip_int}->[1] >= 10 ) {
                      if ( $verbose eq "yes" ) {
			logger("keepalive to $ping_host"); }
		        @{$plip_int}->[1] = 0;	
		}
     } # while
   } #unless
   exit(0);
 } #unless
  waitpid($pid,0);
} # sub ping

sub server {
######
my ( $server, $connection );

package FailoverD;

use vars qw($VERSION @ISA $success);
 
use Failover;
$VERSION = '0.01';
@ISA = qw(Net::Daemon); # to inherit from Net::Daemon

sub Version ($) { 'FailoverD Server, $VERSION'; }

 sub Options ($) {
	my($self) = @_;
 	 my($options) = $self->SUPER::Options();
	  $options;
	} # options

# Treat command line option in the constructor
 sub new ($$;$) {
	my($class, $attr, $args) = @_;
	 my($self) = $class->SUPER::new($attr, $args);
	  $self;
     } # new

 sub Run ($) {
	my($self) = @_;
	my($line, $sock);
	$sock = $self->{'socket'};
	while (1) {
		if (!defined($line = $sock->getline())) {
		  if ($sock->error()) {
			$self->Error("Client connection error %s",
				$sock->error());
		  } # if sock
		  $sock->close();
		  return;
		} # if !defined

	 $line =~ s/\s+$//; # Remove CRLF

		if ( $line eq "quit" ) {
			print $sock "Quit\n";
			$sock->close();
		} # if line eq quit

  chomp ($line);
  if ( $verbose eq "yes" ) {
     logger("checking credentials with $line"); }
  Failover::check_secret("$line");
   if ( $authstatus == 0 ) {
      if ( $verbose eq "yes" ) {
         Failover::logger("auth accepted"); 
       }
      $success = "true";
      next;
    } elsif ( $success eq "true" && ( $line eq "fail") ) {
       Failover::logger("failoverd  request to take over[1]");
       print $sock "Failing\n";
       $sock->close;
       Failover::spawn();
    } elsif ( $type eq "master" ) {
       Failover::logger("Attempt to down master denied: we are the master");
       $sock->close();
    } elsif ( $success eq "true" && ( $line eq "mresume") ) {
       Failover::logger("failoverd  request to halt interfaces.");
       Failover::logger("failoverd  master is booting[mresume]");
       system("$failover_prog", "stop");
       kill_kids();
    } else {
       Failover::logger("FAILED login attempt");
       $sock->close();
       undef $line;
    }
   }
  } # if line eq fail
 } # while (1)

  package main;
  my $server = FailoverD->new({   'pidfile' => 'none',
				  'localport' => $tcp_port }, \@ARGV);
  $server->Bind();
  } # unless pid = fork
} # unless (fork)
