Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://GFS-6.0.0-7.src.rpm:1084957/gfs-build.tar.gz  info  downloads

Makefile0100600000745200074520000000406410052451420012050 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################
SHELL=/bin/bash

LINUX_DIR=linux
ifeq ($(hugemem),y)
LINUX_DIR=linuxhugemem
endif
ifeq ($(smp),y)
LINUX_DIR=linuxsmp
endif

include checkout_date.mk

all:
	cd ${LINUX_DIR} && ${MAKE} modules
	cd bedrock && ${MAKE} all
	cd GFS && ${MAKE} all
	cd gnbd && ${MAKE} all
	cd gulm && ${MAKE} all
clean:
	rm -f *~
	cd ${LINUX_DIR} && ${MAKE} clean
	cd GFS && ${MAKE} clean
	cd gnbd && ${MAKE} clean
	cd gulm && ${MAKE} clean
	cd bedrock && ${MAKE} clean

install:
	cd ${LINUX_DIR} && ${MAKE} modules_install
	cd GFS && ${MAKE} install
	cd gnbd && ${MAKE} install
	cd gulm && ${MAKE} install
	cd bedrock && ${MAKE} install

deinstall uninstall:
	cd GFS && ${MAKE} uninstall
	cd gnbd && ${MAKE} uninstall
	cd gulm && ${MAKE} uninstall
	cd bedrock && ${MAKE} uninstall

distclean:
	rm -rf linux*
	cd GFS && ${MAKE} distclean
	cd gnbd && ${MAKE} distclean
	cd gulm && ${MAKE} distclean
	cd bedrock && ${MAKE} distclean

srpm:
	echo "CO_DATE=\"`date`\"" > checkout_date.mk
	make srpm_real

srpm_real:
	echo "Checking out GFS"
	cvs export -r RHEL3 -D ${CO_DATE} GFS
	echo "Checking out gnbd"
	cvs export -r RHEL3 -D ${CO_DATE} gnbd
	echo "Checking out gulm"
	cvs export -r RHEL3 -D ${CO_DATE} gulm
	echo "Checking out bedrock"
	cvs export -r RHEL3 -D ${CO_DATE} bedrock
	echo "Building src rpm"
	tar -zcvf gfs-build.tar.gz Makefile checkout_date.mk bedrock GFS gulm gnbd
	rpmbuild -bs gfs-build.spec --define "_sourcedir `pwd`" --define "_srcrpmdir `pwd`"
	rm -rf *gz *~ #*#

srpm_clean:
	rm -rf *gz GFS gnbd gulm bedrock *~ *rpm #*# 

checkout_date.mk0100600000745200074520000000004710073325702013546 0ustar  alewisalewisCO_DATE="Thu Jul  8 15:17:06 CDT 2004"
bedrock/0040700000745200074520000000000010073325704012026 5ustar  alewisalewisbedrock/init.d/0040700000745200074520000000000010073325704013213 5ustar  alewisalewisbedrock/init.d/ccsd0100700000745200074520000000451110054411614014046 0ustar  alewisalewis#!/bin/bash
#
# ccsd   start/stop ccsd
#
# chkconfig: 345 20 80
# description: Starts and stops the ccsd specified by $CCS_ARCHIVE \
#              in /etc/sysconfig/gfs
#
#	       
### BEGIN INIT INFO
# Provides: 
### END INIT INFO

. /etc/init.d/functions
[ -f /etc/sysconfig/gfs ] && . /etc/sysconfig/gfs

# attempt to autodetect a CCA device.  If a single CCA device is found
# CCS_ARCHIVE will be set to that device and return 0.  If more than
# one device is found, autodetect() will not set CCS_ARCHIVE and will 
# return 1
# XXX: Should this also scan for cca files in /etc/sysconfig?
autodetect()
{
	ccadevs=$( pool_tool -s | awk '/CCA device /{print $1}' | xargs -r )
	[ -z "$ccadevs" ] && return 1

	match=""
	for dev in $ccadevs
	do
		if [ -z "$match" ]
		then
			match=$dev
		else
			return 1
		fi
	done

	CCS_ARCHIVE=$match
	return 0
}


get_clustername()
{
	clustername=$(ccs_read string cluster.ccs cluster/name 2>/dev/null)
}

start()
{
	echo -n "Starting ccsd:"
	# verify that CCS_ARCHIVE is defineddd
	if [ -z "$CCS_ARCHIVE" ]
	then
		if ! autodetect 
		then
			echo "CCS_ARCHIVE not specified in /etc/sysconfig/gfs" >&2
			return 1
		fi
	fi

	# determine if ccsd needs the '-f' '-d' or '-s' option
	if [ -b "$CCS_ARCHIVE" ]
	then
		ccs_type="-d"
	elif [ -f "$CCS_ARCHIVE" ]
	then
		ccs_type="-f"
	else
		ccs_type="-s"
	fi	

	# start ccsd
	if ccsd $ccs_type $CCS_ARCHIVE &>/dev/null
	then

		# verify that ccsd has infact started
		for sec in $(seq 1 10) 
		do
			sleep 1 
			if get_clustername
			then
				echo -n " clustername = $clustername"
				success
				echo 
				return 0
			fi
		done
	fi

	failure
	echo
	return 1
}

stop()
{
	echo -n "Stopping ccsd:"
	for sec in $(seq 1 10) 
	do
		if get_clustername
		then
			# get the pid of ccsd from /var/run/sistina/ccsd.pid
			# and break if the file is not there
			[ -r /var/run/sistina/ccsd.pid ] || break

			pid=$(cat /var/run/sistina/ccsd.pid )
			kill $pid
			
			sleep 1 
		else
			success
			echo
			return 0
		fi
	done
	failure
	echo
	return 1
}

rtrn=1

# See how we were called.
case "$1" in
  start)
	start
	rtrn=$?
	[ $rtrn = 0 ] && touch /var/lock/subsys/ccsd
	;;

  stop)
	stop
	rtrn=$?
	[ $rtrn = 0 ] && rm -f /var/lock/subsys/ccsd
	;;

  restart)
	$0 stop
	$0 start 
	rtrn=$?
	;;

  status)
	status ccsd
	rtrn=0
	;;

  *)
	echo $"Usage: $0 {start|stop|restart|status}"
	;;
esac

exit $rtrn
bedrock/init.d/Makefile0100600000745200074520000000164310041575211014651 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

TARGET= ccsd

UNINSTALL=${top_srcdir}/scripts/uninstall.pl

top_srcdir=..

include ${top_srcdir}/make/defines.mk

copytobin:

clean:

install:
	install -d ${DESTDIR}/etc/init.d
	install ${TARGET} ${DESTDIR}/etc/init.d

uninstall:
	${UNINSTALL} ${TARGET} ${DESTDIR}/etc/init.d
bedrock/fence/0040700000745200074520000000000010073325704013106 5ustar  alewisalewisbedrock/fence/agents/0040700000745200074520000000000010073325704014367 5ustar  alewisalewisbedrock/fence/agents/egenera/0040700000745200074520000000000010073325704015775 5ustar  alewisalewisbedrock/fence/agents/egenera/Makefile0100600000745200074520000000260710046014736017441 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

SOURCE= fence_egenera.pl
TARGET= fence_egenera

top_srcdir=../../..
include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: $(TARGET)

fence_egenera: fence_egenera.pl
	: > $(TARGET)
	awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE) >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/fence_release.cf perl FENCE_RELEASE_NAME >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf perl SISTINA_COPYRIGHT >> $(TARGET)
	echo "\$$BUILD_DATE=\"(built `date`)\";" >> $(TARGET)
	awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
	chmod +x $(TARGET)

copytobin: ${TARGET}
	cp ${TARGET} ${top_srcdir}/bin/${TARGET}

clean:
	rm -f $(TARGET)
bedrock/fence/agents/egenera/fence_egenera.pl0100700000745200074520000001701710055145621021104 0ustar  alewisalewis#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

use Getopt::Std;
use IPC::Open3;

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and 
# "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="";
$SISTINA_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;

$esh="/opt/panmgr/bin/esh";

sub usage 
{
	print "Usage:\n";
	print "\n";
	print "$pname [options]\n";
	print "\n";
	print "Options:\n";
	print "  -c <string>      cserver\n";
	print "  -h               help\n";
	print "  -l <string>      lpan\n";
	print "  -o <string>      Action: reboot (default), off, on or status\n";
	print "  -p <string>      pserver\n";
	print "  -q               quiet mode\n";
	print "  -V               version\n";
	
	exit 0;
}

sub fail
{
	($msg)=@_;
	print $msg."\n" unless defined $opt_q;
	$t->close if defined $t;
	exit 1;
}

sub fail_usage
{
	($msg)=@_;
	print STDERR $msg."\n" if $msg;
	print STDERR "Please use '-h' for usage.\n";
	exit 1;
}


sub version
{
	print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
	print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );

	exit 0;
}

if (@ARGV > 0) 
{
	getopts("c:hl:o:p:qV") || fail_usage ;

	usage if defined $opt_h;
	version if defined $opt_V;

	fail_usage "Unkown parameter." if (@ARGV > 0);

	$cserv  = $opt_c if defined $opt_c;
	$lpan   = $opt_l if defined $opt_l;
	$pserv  = $opt_p if defined $opt_p;
	$action = $opt_o if defined $opt_o;
} 
else 
{
	get_options_stdin();
} 

$action = "reboot" unless defined $action;

fail "failed: no cserver defined" unless defined $cserv;
fail "failed: no lpan defined" unless defined $lpan;
fail "failed: no pserver defined" unless defined $pserv;

fail "failed: unrecognised action: $action"
	unless $action =~ /^(off|on|reboot|status|pblade)$/i;

sub get_options_stdin
{
	my $opt;
	my $line = 0;
	while( defined($in = <>) )
	{
		$_ = $in;
		chomp;

		# strip leading and trailing whitespace
		s/^\s*//;
		s/\s*$//;

		# skip comments
		next if /^#/;

	        $line+=1;
		$opt=$_;
		next unless $opt;

		($name,$val)=split /\s*=\s*/, $opt;

		if ( $name eq "" )
		{
			print STDERR "parse error: illegal name in option $line\n";
			exit 2;
		} 

		elsif ($name eq "agent" )
		{
			# DO NOTHING -- this field is used by fenced 
		}

		elsif ($name eq "cserver" ) 
		{
			$cserv = $val;
		} 

		elsif ($name eq "lpan" ) 
		{
			$lpan = $val;
		} 

		elsif ($name eq "pserver" ) 
		{
			$pserv = $val;
		} 

		elsif ($name eq "action" ) 
		{
			$action = $val;
		} 

		elsif ($name eq "esh" ) 
		{
			$esh = $val;
		} 

		# FIXME should we do more error checking?  
		# Excess name/vals will be eaten for now
		else 
		{
			fail "parse error: unknown option \"$opt\"";
		}
	}
}

# _pserver_query_field -- query the state of the pBlade or Status field
# and return it's value in $_.  
# Return 0 on success, or non-zero on error
sub _pserver_query_field
{
	my ($field,$junk) = @_;

	if ($field ne "pBlade" && $field ne "Status")
	{
		$_="Error _pserver_query_field: unknown field of type '$field'";
		return 1;
	}

	my $val;

	my $cmd = "ssh $cserv $esh pserver $lpan/$pserv";
	my $pid = open3 (\*WTR, \*RDR,\*RDR, $cmd)
		or die "error open3(): $!";

	while(<RDR>)
	{
		chomp;
		my $line = $_;
		my @fields = split /\s+/,$line;

		if ($fields[0] eq "Error:")
		{
			$val=$line;
			print "Debug ERROR: $val\n";
			last;
		}
		elsif ($fields[0] eq $pserv)
		{
			if ( $field eq "Status" ) 
			{
				$val=$fields[1];
			}
			elsif ($field eq "pBlade" )
			{
				# grrr... Status can be "Shutting down"
				if ($fields[1] ne "Shutting")
				{
					$val=$fields[3];
				}
				else
				{
					$val=$fields[4];
				}
			}
		}
	}

	close WTR;
	close RDR;
	
	waitpid $pid,0;
	my $rtrn = $?>>8;
	$_=$val if defined $val;
	return $rtrn;
}

# return the pBlade of an lpan/pserver in $_.  
# Return 0 on success or non=zero on error
sub pserver_pblade
{
	_pserver_query_field "pBlade";
}

# return the Status of an lpan/pserver in $_.  
# Return 0 on success or non=zero on error
sub pserver_status
{
	_pserver_query_field "Status";
}

# boot an lpan/pserver.  
# Return 0  if the status is "Booted" or "Booting" or non-zero on failure.
# Continue checking the value until the status is "Boot" or "Booting" or
# until a timeout of 120 seconds has been reached.
sub pserver_boot
{
	my $rtrn=1;

	# It seems it can take a while for a pBlade to 
	# boot sometimes.  We shall wait for 120 seconds
	# before giving up on a node returning failure
	for (my $trys=0; $trys<120; $trys++)
	{
		last if (pserver_status != 0);

		my $status = $_;
		if ( $status eq "Booted"  || $status eq "Booting")
		{
			$rtrn=0;
			last;
		}

		if(pserver_pblade)
		{
			die "error getting pBlade info";
		}

		# Is there any harm in sending this command multiple times?
		my $cmd = "ssh $cserv $esh blade -b $_";
		my $pid = open3 (\*WTR, \*RDR,\*RDR, $cmd)
			or die "error open3(): $!";

		close WTR;
		close RDR;

		waitpid $pid,0;
		$rtrn = $?>>8;

		sleep 1;
	}
	return $rtrn;
}

# boot an lpan/pserver.  
# Return 0  if the status is "Shutdown" or non-zero on failure.
# Continue checking the value until the status is "Shutdown" or
# until a timeout of 20 seconds has been reached.
sub pserver_shutdown
{
	my $rtrn=1;
	for (my $trys=0; $trys<20; $trys++)
	{
		last if (pserver_status != 0);

		my $status = $_;
		if (/^Shutdown/)
		{
			$rtrn=0;
			last;
		}
		elsif (/^Shutting/)
		{
			# We are already in the process of shutting down.
			# do I need to do anything here?  
			# We'll just wait for now
		}
		else
		{
			if (pserver_pblade)
			{
				die "error getting pBlade info: $_";
			}

			# is there any harm in sending this command multiple 
			# times?
			my $cmd = "ssh $cserv $esh blade -s $_";
			my $pid = open3 (\*WTR, \*RDR,\*RDR, $cmd)
				or die "error open3(): $!";

			close WTR;
			close RDR;

			waitpid $pid,0;
			$rtrn = $?>>8;
		}

		sleep 1;
	}
	return $rtrn;
}


$_=$action;
if (/^status$/i)
{
	if (pserver_status==0)
	{
		print "$lpan/$pserv is $_\n" unless defined $opt_q;
		exit 0;
	}
	else
	{
		fail "failed to get status of $lpan/$pserv: $_";
	}
}
elsif (/^pblade$/i)
{
	if (pserver_pblade==0)
	{
		print "$lpan/$pserv is $_\n" unless defined $opt_q;
		exit 0;
	}
	else
	{
		fail "failed to get pblade of $lpan/$pserv: $_";
	}
}
elsif (/^off$/i)
{
	if (pserver_shutdown==0)
	{
		print "success: $lpan/$pserv has been shutdown\n" 
			unless defined $opt_q;
		exit 0;
	}
	else
	{
		fail "failed to shutdown $lpan/$pserv";
	}
}
elsif (/^on$/i)
{
	if (pserver_boot==0)
	{
		print "success: $lpan/$pserv has been turned on\n" 
			unless defined $opt_q;
		exit 0;
	}
	else
	{
		fail "failed to turn on $lpan/$pserv";
	}
}
elsif (/^reboot$/i)
{
	if (pserver_shutdown!=0)
	{
		fail "failed to shutdown $lpan/$pserv";
	}

	if (pserver_boot==0)
	{
		print "success: $lpan/$pserv has been rebooted\n" 
			unless defined $opt_q;
		exit 0;
	}
	else
	{
		fail "failed to turn on $lpan/$pserv";
	}
}
else
{
	die "unknown action: $action";
}
bedrock/fence/agents/cpint/0040700000745200074520000000000010073325704015504 5ustar  alewisalewisbedrock/fence/agents/cpint/fence_cpint.pl0100700000745200074520000000702210015057456020321 0ustar  alewisalewis#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

use Getopt::Std;

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;

$comm_prog = "hcp";

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and
# "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="";
$SISTINA_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION


sub usage
{
    print "Usage:\n";  
    print "\n";
    print "$pname [options]\n";
    print "\n";
    print "Options:\n";
    print "  -h               usage\n";
    print "  -u <string>      userid of the virtual machine to fence\n";
    print "  -q               quiet mode\n";
    print "  -V               Version\n";

    exit 0;
}

sub fail
{
  ($msg)=@_;
  print "failed: " . $msg . "\n" unless defined $opt_q;
  exit 1;
}

sub fail_usage
{
  ($msg)=@_q;
  print stderr $msg."\n" if $msg;
  print stderr "Please use '-h' for usage.\n";
  exit 1;
}

sub version
{
  print "$pname $GFS_RELEASE_NAME $BUILD_DATE\n";
  print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );

  exit 0;
}

sub get_options_stdin
{
    my $opt;
    my $line = 0;
    while( defined($in = <>) )
    {
        $_ = $in;
	      chomp;

        # strip leading and trailing whitespace
        s/^\s*//;
        s/\s*$//;

        # skip comments
        next if /^#/;

	      $line+=1;
        $opt=$_;
        next unless $opt;

	      ($name,$val)=split /\s*=\s*/, $opt;

	      if ( $name eq "" )
        {
           print stderr "parse error: illegal name in option $line\n";
           exit 2;
        }

	      # DO NOTHING -- this field is used by fenced or stomithd
        elsif ($name eq "agent" ) { }

	      # FIXME -- depricated.  use "userid" and "password" instead.
        elsif ($name eq "fm" )
        {
            (my $dummy,$opt_u,$opt_p) = split /\s+/,$val;
	          print STDERR "Depricated \"fm\" entry detected.  refer to man page.\n";
        }

        # FIXME -- depreicated residue of old fencing system
      	elsif ($name eq "name" ) { }

	      elsif ($name eq "userid" )
        {
            $opt_u = $val;
        }

	else
        {
           print stderr "parse error: unknown option \"$opt\"\n";
           #> exit 2;
        }
    }
}

if (@ARGV > 0){
    getopts("hqu:V") || fail_usage;
    usage if defined $opt_h;
    version if defined $opt_V;

    fail_usage "Unkown parameter." if (@ARGV > 0);

    fail_usage "No '-u' flag specified." unless defined $opt_u;
} else {
    get_options_stdin();

    fail "no userid" unless defined $opt_u;
}

$ret_val = system("$comm_prog send cp $opt_u logoff > /dev/null 2>&1") >> 8;
fail "$comm_prog failed ($ret_val)" unless ($ret_val == 0 || $ret_val == 45);
$ret_val = system("$comm_prog send cp $opt_u > /dev/null 2>&1") >> 8;
fail "$userid isn't logged off. $comm_prog return ($ret_val)" unless ($ret_val == 45);

print "success: booted userid $opt_u\n" unless defined $opt_q;
exit 0;
bedrock/fence/agents/cpint/Makefile0100600000745200074520000000257210015057456017153 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

SOURCE= fence_cpint.pl
TARGET= fence_cpint

top_srcdir=../../..
include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: $(TARGET)

$(TARGET): $(SOURCE)
	: > $(TARGET)
	awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE) >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/fence_release.cf perl FENCE_RELEASE_NAME >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf perl SISTINA_COPYRIGHT >> $(TARGET)
	echo "\$$BUILD_DATE=\"(built `date`)\";" >> $(TARGET)
	awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
	chmod +x $(TARGET)

copytobin: ${TARGET}
	cp ${TARGET} ${top_srcdir}/bin/${TARGET}

clean:
	rm -f $(TARGET)


bedrock/fence/agents/zvm/0040700000745200074520000000000010073325704015203 5ustar  alewisalewisbedrock/fence/agents/zvm/Makefile0100600000745200074520000000256610015057457016656 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

SOURCE= fence_zvm.pl
TARGET= fence_zvm

top_srcdir=../../..
include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: $(TARGET)

$(TARGET): $(SOURCE)
	: > $(TARGET)
	awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE) >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/fence_release.cf perl FENCE_RELEASE_NAME >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf perl SISTINA_COPYRIGHT >> $(TARGET)
	echo "\$$BUILD_DATE=\"(built `date`)\";" >> $(TARGET)
	awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
	chmod +x $(TARGET)

copytobin: ${TARGET}
	cp ${TARGET} ${top_srcdir}/bin/${TARGET}

clean:
	rm -f $(TARGET)


bedrock/fence/agents/zvm/fence_zvm.pl0100700000745200074520000001612410015057457017523 0ustar  alewisalewis#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

use Getopt::Std;
use IPC::Open2;

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and
# "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="";
$SISTINA_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION


$comm_program = s3270;
$debug = 0;
$max_loops = 10;

sub usage
{
    print "Usage:\n";  
    print "\n";
    print "$pname [options]\n";
    print "\n";
    print "Options:\n";
    print "  -a <ip>          IP address or hostname of the physical s390\n";
    print "  -h               usage\n";
    print "  -u <string>      userid of the virtual machine to fence\n";
    print "  -p <string>      Password\n"; 
    print "  -q               quiet mode\n";
    print "  -r <devnum>      ipl device <devnum>\n";
    print "  -V               Version\n";

    exit 0;
}

sub fail
{
  ($msg)=@_;
  print "failed: " . $msg . "\n" unless defined $opt_q;
  exit 1;
}

sub fail_usage
{
  ($msg)=@_;
  print stderr $msg."\n" if $msg;
  print stderr "Please use '-h' for usage.\n";
  exit 1;
}

sub version
{
  print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
  print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );

  exit 0;
}


sub do_read
{
    my($line);

    $line = <READ_H>;

    if ($debug)
    {
	my($l) = ($line);
	$l =~ s/\n//;
	print "read:  $l\n";
    }
    
    return $line;
}

sub do_write
{
    my($line) = @_;

    if ($debug)
    {
	my($l) = ($line);
	$l =~ s/\n//;
	print "write:  $l\n";	
    }

    print WRITE_H $line;
}


sub look_for
{
    my ($text, $found);
    $found = 0;
    ($text) = @_;
    &do_write("ascii\n");
    while(1){
	$_ = &do_read;
	last unless (/^data:/);
	$found = 1 if (/$text/);
    } 
    $_ = &do_read; 
    fail "error while looking for string '$text'." unless (/ok/);
    return $found;
}

sub in_cp_read_state
{
    my ($prev);
    $_ = "";
    &do_write("ascii\n");
    while (1){
	$prev = $_;
	$_ = &do_read;
	last unless (/^data:/);
    }
    $_ = &do_read;
    fail "error while looking for machine state." unless (/ok/);
    return 1 if ($prev =~ /CP READ/i);
    return 0;
}

sub send_wait
{ 
    &do_write("wait\n");
    $_ = &do_read;
    $_ = &do_read;
    if (/ok/){
	return 1;
    }
    return 0;
}

sub send_string
{
    my ($cmd);
    ($cmd) = @_;
    &do_write('string "' . $cmd . '\n"' . "\n");
    $_ = &do_read;
    $_ = &do_read;
    if (/ok/){
	return send_wait;
    }
    return 0;
}

sub send_cmd
{
    my ($cmd);
    ($cmd) = @_;
    &do_write($cmd . "\n");
    $_ = &do_read;
    $_ = &do_read;
    if (/ok/){
	return send_wait;
    }
    return 0;
}

sub wait_for_response
{
    my ($pass, $failure, $msg, $found, $loops);
    $loops = 0;
    $found = 0;
    ($pass, $failure, $msg) = @_;
    while (1){
      $loops = $loops + 1;
      fail "timed out waiting for '$pass'" if ($loops > $max_loops);
      &do_write("ascii\n");
      while(1){
        $_ = &do_read;
        chomp;
        last unless (/^data:/);
        $found = 1 if (/$pass/);
        if ($failure){
          fail("$msg '$_'") if (/$failure/);
        }
      }
      $_ = &do_read;
      fail "wait for response failed '$_'" unless (/ok/);
      last if $found;
      sleep 1;
    }
    return 0;
}

sub check_response
{
    ($action) = @_;
    $_ = &do_read;
    $_ = &do_read;
    fail "$action failed." unless (/ok/);
}

sub get_options_stdin
{
    my $opt;
    my $line = 0;
    while( defined($in = <>) )
    {
        $_ = $in;
	      chomp;

        # strip leading and trailing whitespace
        s/^\s*//;
        s/\s*$//;

        # skip comments
        next if /^#/;

	      $line+=1;
        $opt=$_;
        next unless $opt;

	      ($name,$val)=split /\s*=\s*/, $opt;

	      if ( $name eq "" )
        {
           print stderr "parse error: illegal name in option $line\n";
           exit 2;
        }

	      # DO NOTHING -- this field is used by fenced or stomithd
        elsif ($name eq "agent" ) { }

	      # FIXME -- depricated.  use "userid" and "password" instead.
        elsif ($name eq "fm" )
        {
            (my $dummy,$opt_u,$opt_p) = split /\s+/,$val;
	          print STDERR "Depricated \"fm\" entry detected.  refer to man page.\n";
        }

	      elsif ($name eq "ipaddr" )
        {
            $opt_a = $val;
        }

        elsif ($name eq "ipl" )
        {
            $opt_r = $val;
        }

        # FIXME -- depreicated residue of old fencing system
      	elsif ($name eq "name" ) { }

	      elsif ($name eq "passwd" )
        {
            $opt_p = $val;
        }
	      elsif ($name eq "userid" )
        {
            $opt_u = $val;
        }

	else
        {
           print stderr "parse error: unknown option \"$opt\"\n";
           #> exit 2;
        }
    }
}

if (@ARGV > 0){
    getopts("a:hp:qr:u:V") || fail_usage;
    usage if defined $opt_h;
    version if defined $opt_V;

    fail_usage "Unkown parameter." if (@ARGV > 0);

    fail_usage "No '-a' flag specified." unless defined $opt_a;
    fail_usage "No '-p' flag specified." unless defined $opt_p;
    fail_usage "No '-u' flag specified." unless defined $opt_u;

} else {
    get_options_stdin();

    fail "no IP address" unless defined $opt_a;
    fail "no userid" unless defined $opt_u;
    fail "no password" unless defined $opt_p;
}

$pid = open2(READ_H, WRITE_H, "$comm_program 2>&1");
&do_write("connect $opt_a\n");
$_ = &do_read;
unless (/^U U U/){
    chomp;
    fail "communication program failed with '$_'.";
}
$_ = &do_read;
fail "couldn't connect to $opt_a." unless(/ok/);
send_wait or fail "couldn't start 3270 session on $opt_a.";
send_cmd "enter" or fail "couldn't reach logon prompt.";
look_for "Enter one of the following commands:" or fail "doesn't look like a login prompt\n";
send_string "logon $opt_u $opt_p norun here" or fail "couldn't login";
send_cmd "clear" or fail "couldn't send the clear command.";
send_string "#cp query userid";
wait_for_response(uc($opt_u),"Enter one of the following commands:", "logon failed");
fail "machine not in CP READ state" unless in_cp_read_state;
if (defined $opt_r){
    send_string "ipl $opt_r" or fail "couldn't send reboot command";
} else {
    send_string "stop" or fail "couldn't send stop command\n";
}
fail "command failed" if look_for "Unknown CP command";
if (defined $opt_r && !in_cp_read_state){
    send_string "#cp disc";
} else {
    &do_write("disconnect\n");
}
&do_write("quit\n");

print "success: booted userid $opt_u\n" unless defined $opt_q;

exit 0;
bedrock/fence/agents/rackswitch/0040700000745200074520000000000010073325704016531 5ustar  alewisalewisbedrock/fence/agents/rackswitch/do_rack.h0100600000745200074520000000073510012362641020302 0ustar  alewisalewis
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>

#include <sys/socket.h>
#include <sys/types.h>

#include <linux/net.h>
#include <linux/fs.h>
#include <linux/socket.h>
/*#include <linux/in.h>*/
#include <arpa/inet.h>

#include <signal.h>

#include "fence_release.cf"
#include "copyright.cf"

#define SA struct sockaddr


#define MAXBUF 1200

#define DID_SUCCESS 0
#define DID_FAILURE 1 

bedrock/fence/agents/rackswitch/Makefile0100600000745200074520000000210510015057456020170 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

TARGET= fence_rackswitch

SOURCE= do_rack.c

top_srcdir=../../..

ccs_libdir=${top_srcdir}/ccs/lib

INCLUDE= -I${top_srcdir}/include -I${top_srcdir}/config


include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: ${TARGET}

fence_rackswitch: ${SOURCE:.c=.o}
	${CC} ${CFLAGS} ${LDFLAGS} ${SOURCE:.c=.o} ${LOADLIBES} ${LDLIBS} -o $@

copytobin: all
	cp ${TARGET} ${top_srcdir}/bin


clean:
	rm -f *.o ${TARGET} *~

bedrock/fence/agents/rackswitch/do_rack.c0100600000745200074520000004327510015057456020313 0ustar  alewisalewis/******************************************************************************
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
**  
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/
#include "do_rack.h"

char *pname = "fence_rack";

int quiet_flag = 0;
int verbose_flag = 0;
int debug_flag = 0;

char ipaddr[256];
char portnumber[256];
char username[256];
char password[256];
char arg[256];
char name[256];

char readbuf[MAXBUF];
char writebuf[MAXBUF];
int sock;

char op_login = 0x7e; 	        /* 126*/ 
char op_action = 0x66;	        /* 102 */
char ack_login = 0x7D;	        /* 125 */

char action_idle = 0x00;
char action_reset = 0x01;
char action_off = 0x02;
char action_offon = 0x03;

char configuration_request = 0x5b;   /* 91 */
char config_reply = 0x5c;            /* 92 */
char config_general = 0x01;
char config_section1 = 0x02;
char config_section2 = 0x03;
char config_section3 = 0x04;

char message_status = 0x65;         /* 101 */

char login_deny = 0xFF;          

int time_out = 60;

void ignore_message_status(void);
int wait_frame(char);

/*
 * scan input, waiting for a given frame
 */
int wait_frame(char frame_id)
{
  int read_more = 1;
  int success = 0;
  int n;
  char target = frame_id;

  if(debug_flag){printf("%s: Looking for frametype 0x%.2x\n",name,target);}
  read_more = 1;
  while(read_more){
    n = read(sock,readbuf,1);
    if(debug_flag){printf("%s: Found frametype 0x%.2x\n",name,readbuf[0]);}
    if(readbuf[0] == target){
      read_more = 0;
      success = 1;
    }
    else{
      if(readbuf[0] == message_status){
	ignore_message_status();
	read_more = 1;
      }
      else{
	if(debug_flag){printf("%s: Got unexpected frame from switch\n",name);}
	read_more = 0;
	success = 0;
      }
    }
  }
  return(success);
}  

void ignore_message_status(void)
{
  int n,i;
  int read_more = 1;
  int number_of_temp;
  int number_of_config_mobo;
    
  if(debug_flag){printf("%s: Ignoring message-status\n",name);}
  read_more=1;
  while(read_more){
    n = read(sock,readbuf,1); /* status */
    if(n == 1)
      read_more = 0;
  }

  read_more = 1;
  while(read_more){         /* Date & time */
    n = read(sock,readbuf,1);
    if(readbuf[0] == '\0'){
      read_more = 0;
    }
    else{
      read_more = 1;
    }
  }
   
  read_more = 1;
  number_of_temp = 0;
  n = read(sock,readbuf,1); /* Temprature Input count */
  number_of_temp = (int)readbuf[0];
  
  for(i=0;i<number_of_temp;i++){
    read_more = 1;
    while(read_more){
      n = read(sock,readbuf,1); /* Temprature input ID */
      n = read(sock,readbuf,8); /* Temprature Value, Fahrenheit */
      n = read(sock,readbuf,8); /* Temprature Vaule, Celcius */
      n = read(sock,readbuf,1); /* Temprature Alarm */
    }
  }
  number_of_config_mobo = 0;
  for(i=4;i>0;i--){
    read_more = 1;	
    while(read_more){
      n=read(sock,readbuf,1);
      if(n == 1){
	read_more = 0;
	number_of_config_mobo = number_of_config_mobo + (int)(readbuf[0]<<(8*(i-1)));
      }
    }
  }
  for(i=0;i<number_of_config_mobo;i++){
    n = read(sock,readbuf,4); /* Motherboard ID */
    n = read(sock,readbuf,1); /* Motherboard status */
  }
}



void print_usage(void)
{
  printf("Usage:\n");
  printf("\n");
  printf("%s [options]\n"
         "\n"
         "Options:\n"
         "  -h               usage\n"
	 "  -a <ip>          IP address for RackSwitch\n"
	 "  -n <dec num>     Physical plug number on RackSwitch\n"
	 "  -l <string>      Username\n"
	 "  -p <string>      Password\n"
	 "  -v               Verbose\n"
	 "  -q               Quiet\n"
         "  -V               Version information\n", pname);
}



void get_options(int argc, char **argv)
{
  int c;
  char *value;

  if (argc > 1){  
    /*
     * Command line input
     */
    while ((c = getopt(argc, argv, "ha:n:l:p:vqVd")) != -1)
      {
	switch(c)
	  {
	  case 'h':
	    print_usage();
	    exit(DID_SUCCESS);
	
	  case 'a':
	    strncpy(ipaddr,optarg,254);
	    break;

	  case 'n':
	    strncpy(portnumber,optarg,254);
	    break;

	  case 'l':
	    strncpy(username,optarg,254);	
	    break;

	  case 'p':
	    strncpy(password,optarg,254);
	    break;

	  case 'v':
	    verbose_flag = 1;
	    break;

	  case 'q':
	    quiet_flag = 1;
	    break;

	  case 'd':
	    debug_flag = 1;
	    break;

	  case 'V':
	    printf("%s %s (built %s %s)\n", pname, FENCE_RELEASE_NAME,
		   __DATE__, __TIME__);
	    printf("%s\n", SISTINA_COPYRIGHT);
	    exit(DID_SUCCESS);
	    break;

	  case ':':
	  case '?':
	    fprintf(stderr, "Please use '-h' for usage.\n");
	    exit(DID_FAILURE);
	    break;

	  default:
	    fprintf(stderr, "Bad programmer! You forgot to catch the %c flag\n", c);
	    exit(DID_FAILURE);
	    break;

	  }
      }
    strcpy(name, pname);
  }
  else{
    errno = 0;
    while(fgets(arg, 256, stdin) != NULL){    
 if( (value = strchr(arg, '\n')) == NULL){
        fprintf(stderr, "line too long: '%s'\n", arg);
	exit(DID_FAILURE);
      }
      *value = 0;
      if( (value = strchr(arg, '=')) == NULL){
        fprintf(stderr, "invalid input: '%s'\n", arg);
	exit(DID_FAILURE); 
      }   
      *value = 0;
      value++;
    /*  bahfuck. "agent" is not passed to us anyway
     *  if (!strcmp(arg, "agent")){
      *  strcpy(name, value);
       * pname = name;
      *}
      */
      strcpy(name, pname);
      if (!strcmp(arg, "ipaddr"))
        strcpy(ipaddr, value);
      
      if (!strcmp(arg, "portnumber"))
        strcpy(portnumber, value);
      
      if (!strcmp(arg, "username"))
        strcpy(username, value);
      
      if (!strcmp(arg, "password"))
        strcpy(password, value);
    }
    errno = 0;
    
  }
}

static void sig_alarm(int sig)
{
 if(!quiet_flag){
   fprintf(stderr,"failed: %s: Timeout, nothing happened for %d seconds.\n", pname, time_out);
   fprintf(stderr,"failed: %s: Perhaps you should inspect the RackSwitch at %s\n",pname,ipaddr);
 }
 exit(DID_FAILURE);	
}


int main(int argc, char **argv)
{
  int n,i,j,pnumb;
  int ip_portnumber = 1025;
  char boardnum = 0x00;
  /*char number_of_action = 0x01;*/
  int number_of_config_mobo = 0;
  int number_of_section_config_mobo = 0;
  int exit_status= 0;
  int success_off = 0;
  /*int success_on = 0;*/
  int read_more = 1;
  struct sockaddr_in rackaddr; 
  
  /*char mobo_enabled = 0x01;*/
  /*char mobo_default_status = 0x00;*/
  /*char mobo_output_status = 0x00;*/
  int this_mobo = 0;
  /*int mobo_id = 0;*/
  /*int our_mobo = 0;*/
  int number_of_temp = 0;

  memset(arg, 0, 256);
  memset(name, 0, 256);
  memset(ipaddr, 0, 256);
  memset(portnumber,0,256);
  memset(username,0,256);
  memset(password,0,256);

  /*
   * Ensure that we always get out of the fencing agent
   * even if things get fucked up and we get no replies
   */
  signal(SIGALRM, &sig_alarm);
  alarm(time_out);
  get_options(argc, argv);

  if(name[0] == '\0')
  {
    if(!quiet_flag)
      fprintf(stderr,"failed: no name for this program\n");
    exit(DID_FAILURE);
  }
  
  if(ipaddr[0] == '\0')
  {
    if(!quiet_flag)
      fprintf(stderr,"failed: %s, no IP address given\n",name);
    exit(DID_FAILURE);
  }
  if (portnumber[0] == '\0')
  {
    if(!quiet_flag)
      fprintf(stderr,"failed: %s, no portnumber given\n",name);
    exit(DID_FAILURE);
  }
  if (username[0] == '\0')
  {
    if(!quiet_flag)
      fprintf(stderr,"failed: %s, no username given\n",name);
    exit(DID_FAILURE);
  }

  if (password[0] == '\0')
  {
    if(!quiet_flag)
      fprintf(stderr,"failed: %s, no password given\n",name);
    exit(DID_FAILURE);
  }
  /*
   * Port number given to us as a string.
   * Does the number make sense?
   */
  pnumb = 0;
  for(n=0;(portnumber[n]!='\0');n++){
    if((portnumber[n] < 48) || (portnumber[n] > 57)){
      if(!quiet_flag)
	fprintf(stderr,"failed: %s, invalid port number\n",name);
      exit(1);
    }
    pnumb = ((pnumb * 10) + ((int)(portnumber[n]) - 48));
  }
  /*
   * what section of the rack is this port part of?
   * The switch has 4 "subsections", called boardnum here
   */
  if((pnumb > 0) && (pnumb < 47))
    boardnum = 0x02;
  if((pnumb > 46) && (pnumb < 94))
    boardnum = 0x03;
  if((pnumb > 93) && (pnumb < 137))
    boardnum = 0x04;
  if((pnumb < 1) || (pnumb> 136)){
    boardnum = 0x00;
    if(!quiet_flag)
      fprintf(stderr,"failed: %s, the portnumber given is not in the range [1 - 136]\n",name);
    exit(DID_FAILURE);
  } 
  /*********************************************
   ***
   *** set up TCP connection to the rackswitch
   ***
   ********************************************/
  if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0){
    fprintf(stderr,"failed: %s: socket error, %s\n",name,strerror(errno));
    exit(DID_FAILURE);
  }
  
  bzero(&rackaddr,sizeof(rackaddr));
  rackaddr.sin_family = AF_INET;
  rackaddr.sin_port = htons(ip_portnumber);

  if(inet_pton(AF_INET,ipaddr,&rackaddr.sin_addr) <= 0){
    fprintf(stderr,"failed: %s: inet_pton error\n", name);
  }
 
  if(connect(sock,(SA *) &rackaddr,sizeof(rackaddr)) < 0){
    fprintf(stderr,"failed: %s: connect error to %s, %s\n", name, ipaddr,strerror(errno));
    exit(DID_FAILURE);
  }
  /**********************************************
   ***
   ***	Send Login Frame
   ***
   *********************************************/
  writebuf[0] = op_login;
   
  for(n=0;n<=(strlen(username));n++){
    writebuf[sizeof(char)+n] = username[n];
  }
  writebuf[sizeof(char)+(strlen(username))+1] ='\n';
   
  for(n=0;n<=(strlen(password))+1;n++){
    writebuf[sizeof(char)+strlen(username)+1+n] = password[n];
  }
  writebuf[sizeof(char)+(strlen(username))+1+(strlen(password))+1] ='\n';
     
  write(sock,writebuf,sizeof(char)+strlen(username)+strlen(password)+2);
   
  /********************************************
   ***
   ***	Read Login Reply
   ***
   *******************************************/
 if(wait_frame(ack_login)){
   n=read(sock,readbuf,1);
   if(readbuf[0] == login_deny){
     if(!quiet_flag){fprintf(stderr,"failed: %s: Not able to log into RackSwitch\n",name);}
     exit(DID_FAILURE);
   }
   else{
     if(verbose_flag){printf("%s: Successfully logged into RackSwitch\n",name);}
   }
  }

 /********************************************
  ***
  ***	Send Configuration Request Message
  ***
  *******************************************/
 
 writebuf[0] = configuration_request;
 writebuf[1] = config_general;
 write(sock,writebuf,2*(sizeof(char)));

 /********************************************
   ***
   ***	Read General Configuration Message
   ***
   *******************************************/

 if(wait_frame(config_reply)){
   n = read(sock,readbuf,1);
   if(readbuf[0] == config_general){

     /* Configuration Status, one byte */
     n = read(sock,readbuf,1);
     
     /* Switch description, string */
     read_more = 1;
     while(read_more){         
       n = read(sock,readbuf,1);
       if(readbuf[0] == '\0'){
	 read_more = 0;
       }
       else{
	 read_more = 1;
       }
     }
     
     /* Serial number, string */
     read_more = 1;
     while(read_more){
       n = read(sock,readbuf,1);
       if(readbuf[0] == '\0'){
	 read_more = 0;
       }
       else{
	 read_more = 1;
       }
     }

       	  /* Version number, string */
     read_more = 1;
     while(read_more){
       n = read(sock,readbuf,1);
       if(readbuf[0] == '\0'){
	 read_more = 0;
       }
       else{
	 read_more = 1;
       }
     }

     /* number of configured temps, 1 byte */
     number_of_temp = 0; 
     n = read(sock,readbuf,1);
     number_of_temp = (int)readbuf[0];
     
     for(i=0;i<number_of_temp;i++){

       /* Temprature description, string */
       read_more = 1;
       while(read_more){ 
	 read_more = 1;
	 while(read_more){         
	   n = read(sock,readbuf,1);
	   if(readbuf[0] == '\0'){
	     read_more = 0;
	   }
	   else{
	     read_more = 1;
	   }
	 }
       }
       
       n = read(sock,readbuf,1); /* Temprature input ID */
       n = read(sock,readbuf,1); /* Tempratue unit */
       n = read(sock,readbuf,8); /* Temprature HI alarm */
       n = read(sock,readbuf,8); /* Temprature LO alarm */
       n = read(sock,readbuf,1); /* Temprature HI Alarm */
       n = read(sock,readbuf,1); /* Temprature LO Alarm */
       n = read(sock,readbuf,1); /* Temprature Alarm email */
     }
     /* Number of configured motherboards */
     number_of_config_mobo = 0;
     for(i=4;i>0;i--){
       read_more = 1;	
       while(read_more){
	 n=read(sock,readbuf,1);
	 if(n == 1){
	   read_more = 0;
	   number_of_config_mobo = number_of_config_mobo + (int)(readbuf[0]<<(8*(i-1)));
	 }
       }
     }
     /*
      * make sure the motherboard we are asked to turn of is configured
      */
     if(pnumb > number_of_config_mobo){
       if(!quiet_flag){
	 fprintf(stderr,"failed: %s asked to reboot port %d, but there are only %d ports configured\n",name,pnumb,number_of_config_mobo);
	 exit(DID_FAILURE);
       }
     }
     n = read(sock,readbuf,1); /* email alarms */
     n = read(sock,readbuf,4); /* email alarm delay */

     /* email addresses, string */
     read_more = 1;
     while(read_more){         
       n = read(sock,readbuf,1);
       if(readbuf[0] == '\0'){
	 read_more = 0;
       }
       else{
	 read_more = 1;
       }
     }
     
     n = read(sock,readbuf,4); /* reset action duration */
     n = read(sock,readbuf,4); /* power off action duration */
     n = read(sock,readbuf,4); /* power on action duration */
   }
   else{
     if(debug_flag){fprintf(stderr,"failed: %s: Did not receive general configuration frame when requested\n",name);}
     exit(DID_FAILURE);
   }
 }
 else{
   if(debug_flag){fprintf(stderr,"failed: %s: Did not receive configuration frame when requested\n",name);}
   exit(DID_FAILURE);
 }



 /******************************************
  ***
  ***	Send Action packet to switch
  ***	Off/On port <portnum>
  ***
  *****************************************/
 memset(writebuf,0,sizeof(writebuf));
 writebuf[0] = op_action; 
 writebuf[1] = (char)(number_of_config_mobo >> 24);
 writebuf[2] = (char)(number_of_config_mobo >> 16);
 writebuf[3] = (char)(number_of_config_mobo >> 8);
 writebuf[4] = (char)(number_of_config_mobo);
 
 writebuf[(pnumb*5)+0] = (char)(pnumb >> 24);
 writebuf[(pnumb*5)+1] = (char)(pnumb >> 16);
 writebuf[(pnumb*5)+2] = (char)(pnumb >> 8);
 writebuf[(pnumb*5)+3] = (char)(pnumb);
 writebuf[(pnumb*5)+4] = action_offon;

 write(sock,writebuf,(pnumb*5)+5);
 if(verbose_flag){
   printf("%s: sending action frame to switch:\n",name);
   for(i=0;i<(pnumb*5)+5;i++) 
     printf("0x%.2x ",writebuf[i]);
   printf("\n");
 }

  /******************************************
   ***
   ***	Send Configuration Request packet to switch
   ***
   *****************************************/
 memset(writebuf,0,sizeof(writebuf));
 writebuf[0] = configuration_request;
 writebuf[1] = boardnum;
 
 write(sock,writebuf,2*(sizeof(char)));
 if(verbose_flag){
   printf("%s: sending Request Configuration Frame from switch:\n",name);
   printf("0x%.2x 0x%.2x\n",writebuf[0],writebuf[1]);
 }

 /*******************************************
  ***
  ***	Read Switch Status Message
  ***
  ******************************************/
 while(success_off == 0){
   if(debug_flag){
     printf("%s: Status does not indicate port %d being rebooted. Looking again\n",name,pnumb);}
   if(wait_frame(message_status)){
     n = read(sock,readbuf,1); /* Rackswitch status */
     
     read_more = 1;
     while(read_more){         /* Date & time */
       n = read(sock,readbuf,1);
       if(readbuf[0] == '\0'){
	 read_more = 0;
       }
       else{
	 read_more = 1;
       }
     }
     number_of_temp = 0;
     n = read(sock,readbuf,1);
     number_of_temp = readbuf[0];
     for(i=0;i<number_of_temp;i++){
       read_more = 1;
       while(read_more){
	 n = read(sock,readbuf,1); /* Temprature input ID */
	 n = read(sock,readbuf,8); /* Temprature Value, Fahrenheit */
	 n = read(sock,readbuf,8); /* Temprature Vaule, Celcius */
	 n = read(sock,readbuf,1); /* Temprature Alarm */
       }
     }
     
     /* number of motherboards, 4 byte */
     number_of_section_config_mobo = 0;
     for(i=4;i>0;i--){
       read_more = 1;	
       while(read_more){
	 n=read(sock,readbuf,1);
	 if(n == 1){
	   read_more = 0;
	   number_of_section_config_mobo = number_of_section_config_mobo + (int)(readbuf[0]<<(8*(i-1)));
	 }
       }
     }
     
     for(i=0;i<number_of_section_config_mobo;i++){
       
       this_mobo = 0;
       for(j=4;j>0;j--){
	 read_more = 1;	
	 while(read_more){
	   n=read(sock,readbuf,1);
	   if(n == 1){
	     read_more = 0;
	     this_mobo = this_mobo + (int)(readbuf[0]<<(8*(j-1)));
	   }
	 }
       }
       if(debug_flag){printf("%s: port %d is currently ",name,this_mobo);}
       n = read(sock,readbuf,1); /* Motherboard status */
       if(debug_flag){printf("0x%.2x\n",readbuf[0]);}
       if((pnumb == this_mobo) && ((readbuf[0] == 0x02)||(readbuf[0] == 0x03))){
	 success_off = 1;
	 if(verbose_flag){printf("%s: Status shows port %d being rebooted\n",name,this_mobo);}
       }
     } /* end number_of_section_mobo loop */
     if(!success_off){
       if(verbose_flag){printf("%s: Status shows port %d NOT being rebooted, asking for status again\n",name,pnumb);}
     }
   }
   else{
     if(debug_flag){fprintf(stderr,"%s: Did not receive Switch Status Message\n",name);}
     exit(DID_FAILURE);
   }
 }


 if(success_off){
	 if(!quiet_flag){	
   printf("success: %s: successfully told RackSwitch to reboot port %d\n",name,pnumb);
	 }   
   alarm(0);
   exit_status = DID_SUCCESS;
 }
 return(exit_status);
}
/* And that is it. There is no more.
 * Maybe there  should be more?
 * Or maybe not?
 * But there is no more
 */
bedrock/fence/agents/vixel/0040700000745200074520000000000010073325704015516 5ustar  alewisalewisbedrock/fence/agents/vixel/fence_vixel.pl0100700000745200074520000001045310015057457020350 0ustar  alewisalewis#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

use Getopt::Std;
use Net::Telnet ();

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and
# "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="";
$SISTINA_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION


sub usage 
{
    print "Usage:\n\n"; 
    print "$pname [options]\n\n";
    print "Options:\n";
    print "  -a <ip>          IP address or hostname of switch\n";
    print "  -h               Usage\n";
    print "  -n <num>         Port number to disable\n";
    print "  -p <string>      Password for login\n";
    print "  -V               version\n\n";

    exit 0;
}

sub fail
{
  ($msg) = @_;
  print $msg."\n" unless defined $opt_q;
  $t->close if defined $t;
  exit 1;
}

sub fail_usage
{
  ($msg) = @_;
  print STDERR $msg."\n" if $msg;
  print STDERR "Please use '-h' for usage.\n";
  exit 1;
}

sub version
{
  print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
  print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );

  exit 0;
}

if (@ARGV > 0) {
    getopts("a:hn:p:V") || fail_usage ;

    usage if defined $opt_h;
    version if defined $opt_V;

    fail_usage "Unknown parameter." if (@ARGV > 0);

    fail_usage "No '-a' flag specified." unless defined $opt_a;
    fail_usage "No '-p' flag specified." unless defined $opt_p;
    fail_usage "No '-n' flag specified." unless defined $opt_n;

} else {
    get_options_stdin();

    fail "failed: no IP address for the Vixel." unless defined $opt_a;
    fail "failed: no password provided." unless defined $opt_p;
    fail "failed: no port number specified." unless defined $opt_n;
}

#
# Set up and log in
#

$t = new Net::Telnet;

$t->open($opt_a);

$t->waitfor('/assword:/');

$t->print($opt_p);

($out, $match)= $t->waitfor(Match => '/\>/', Match => '/assword:/');

if ($match =~ /assword:/) {
  fail "failed: incorrect password\n";
} elsif ( $match !~ />/ ) {
  fail "failed: timed out waiting for prompt\n";
}
 
$t->print("config");

$t->waitfor('/\(config\)\>/');

$t->print("zone");

$t->waitfor('/\(config\/zone\)\>/');

#
# Do the command
#

$cmd = "config $opt_n \"\"";
$t->print($cmd);

$t->waitfor('/\(config\/zone\)\>/');

$t->print("apply");

($text, $match) = $t->waitfor('/\>/');
if ($text !~ /[Oo][Kk]/) {
  fail "failed: error from switch\n";
}

$t->print("exit");

print "success: zonedisable $opt_n\n";
exit 0;


sub get_options_stdin
{
    my $opt;
    my $line = 0;

    while( defined($in = <>) )
    {   
        $_ = $in;
	chomp;
        
        # strip leading and trailing whitespace
        s/^\s*//;
        s/\s*$//;

        # skip comments
        next if /^#/;

        $line+=1;
        $opt=$_;
        next unless $opt;

        ($name,$val)=split /\s*=\s*/, $opt;

        if ( $name eq "" ) {
           print("parse error: illegal name in option $line\n");
           exit 2;
        } 

        # DO NOTHING -- this field is used by fenced
	elsif ($name eq "agent" ) { }

	# FIXME -- depricated.  use "port" instead.
	elsif ($name eq "fm" ) {
            (my $dummy,$opt_n) = split /\s+/,$val;
	    print STDERR "Depricated \"fm\" entry detected.  refer to man page.\n";
        } 

	elsif ($name eq "ipaddr" ) 
	{
            $opt_a = $val;
        } 

	elsif ($name eq "name" ) { }

        elsif ($name eq "passwd" ) 
	{
            $opt_p = $val;
        } 

        elsif ($name eq "port" ) 
	{
            $opt_n = $val;
        } 

        # FIXME should we do more error checking?
        # Excess name/vals will be eaten for now
	else 
	{
           fail "parse error: unknown option: $opt";
           #> exit 2;
        }
    }
}

bedrock/fence/agents/vixel/Makefile0100600000745200074520000000257210015057457017166 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

SOURCE= fence_vixel.pl
TARGET= fence_vixel

top_srcdir=../../..
include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: $(TARGET)

$(TARGET): $(SOURCE)
	: > $(TARGET)
	awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE) >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/fence_release.cf perl FENCE_RELEASE_NAME >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf perl SISTINA_COPYRIGHT >> $(TARGET)
	echo "\$$BUILD_DATE=\"(built `date`)\";" >> $(TARGET)
	awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
	chmod +x $(TARGET)

copytobin: ${TARGET}
	cp ${TARGET} ${top_srcdir}/bin/${TARGET}

clean:
	rm -f $(TARGET)


bedrock/fence/agents/rib/0040700000745200074520000000000010073325704015143 5ustar  alewisalewisbedrock/fence/agents/rib/fence_rib.pl0100700000745200074520000003520510015057457017424 0ustar  alewisalewis#!/usr/bin/perl 
$|=1;


use IO::Socket;
use IO::Select;
use IPC::Open3;
use Getopt::Std;

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and 
# "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="v5.2.0 \"Lrrr\"";
$SISTINA_COPYRIGHT=("Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
$SISTINA_COPYRIGHT=("Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
$SISTINA_COPYRIGHT=("
$SISTINA_COPYRIGHT=("This copyrighted material is made available to anyone wishing to use,
$SISTINA_COPYRIGHT=("modify, copy, or redistribute it subject to the terms and conditions
$SISTINA_COPYRIGHT=("of the GNU General Public License v.2.
$BUILD_DATE="(built Fri Jul 25 06:10:15 PDT 2003)";
#END_VERSION_GENERATION

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;


################################################################################
sub usage 
{
    print "Usage:\n";
    print "\n";
    print "$pname [options]\n";
    print "\n";
    print "Options:\n";
    print "  -a <ip>          IP address or hostname of RILOE card\n";
    print "  -h               usage\n";
    print "  -l <name>        Login name\n";
    print "  -n <num>         local port for stunnel (default 8888)\n";
    print "  -o <string>      Action: reboot (default), off, on or status\n";
    print "  -p <string>      Login password\n";
    print "  -q               quiet mode\n";
    print "  -V               version\n";
    print "  -v               verbose\n";
    exit 0;
}


sub diedie
{
    if (defined $stunnel_pid)
    {
       kill 9, $stunnel_pid;
       waitpid $stunnel_pid,0;
    }
    print STDERR "@_";
    exit 1;
}

sub sendsock
{
	my ($sock, $msg, $junk) = @_;

	print $sock $msg;
	if ($verbose)
	{
		chomp $msg;
		print "SEND: $msg\n" 
	}
}


# This will slurp up all the data on the socket.  If nothing is available after 10 seconds, the
# function will return all the data that has been read so far.  If $mode is defined, the function
# will return immediately following the initial packet terminator "<END_RIBCL/>"  The RILOE has
# a nasty timing issue.  The header packet must be sent, a reply recived and then the command
# packet needs to be sent before the riloe times out the command.  This takes on the order
# of seconds.  If the command times out, the connection through stunnel is broken.
#
# FIXME -- this feels like a kludge.  There has to be a better way to make this work.
#
sub receive_response
{
    my ($sock,$mode) = @_;
    $mode = 0 unless defined $mode;
    my $count=0;

    my $buffer = "";

    my $selector = IO::Select->new();
    $selector->add($sock);

    while (@ready = $selector->can_read(10))
    {
        my $buf;
        my $rd = sysread $sock, $buf, 512;

        diedie "sysread error: $!\n" if (!defined $rd);

    	print "READ:($rd,$mode) $buf\n" if ($verbose); 

        last unless ($rd);

        $buffer="$buffer$buf"; 

	last if ( $buffer =~ /<END_RIBCL\/>$/mi && $mode==1 );
    }
    return $buffer;
}


sub chld_reaper
{
    if (waitpid($stunnel_pid, WNOHANG))
    {
        my $status = $?;
        print "REAPER: status $status on $stunnel_pid\n" if ($verbose);

        if ($status != 0 )
        {
            print STDERR "stunnel error\n" ;
    	    close_stunnel();
            exit 1;
	}
    }
}

sub pipe_reaper
{
    print STDERR "pipe error\n" ;
    kill 9, $stunnel_pid;
    waitpid($stunnel_pid, WNOHANG);
    close_stunnel();
    exit 1;
}

sub open_stunnel()
{
    if ( $stunnel_version == 3 )
    {
        # create an SSL tunnel.  By default, stunnel will background itself.
        # specying -f keeps it in the forground and makes it easy to identify and kill
        # later.  
        $cmd = "stunnel -d localhost:$localport -r $hostname -c -f ";
    }
    elsif ( $stunnel_version == 4 )
    {
        $cmd = "stunnel /dev/stdin";
    }
    else 
    {
        die "unkown stunnel version\n"; 
    }

    
    
    print "cmd: $cmd\n" if ($verbose);

    $stunnel_pid = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, $cmd);

    $SIG{CHLD} = \&chld_reaper;
    $SIG{PIPE} = \&pipe_reaper;
    if ( $stunnel_version == 4 )
    {
        print CMD_IN  "foreground = yes\n";
        print CMD_IN  "client     = yes\n";
        print CMD_IN  "debug      = 7\n";
        print CMD_IN  "[443]\n";
        print CMD_IN  "accept     = $localport\n";
        print CMD_IN  "connect    = $hostname\n";
        close CMD_IN;
    }

    # give stunnel some time to startup.
     sleep 2;

}


sub close_stunnel()
{
    # clean up stunnel
    $SIG{CHLD}= 'DEFAULT';
    kill 9, "$stunnel_pid";

    $selector = IO::Select->new();
    $selector->add(*CMD_ERR, *CMD_OUT);

    while (@ready = $selector->can_read) 
    {
        foreach $fh (@ready) 
        {
            if (fileno($fh) == fileno(CMD_ERR)) 
            {
		# FIXME -- icky blocking read
                my $line = <CMD_ERR>;
                print "stunnel STDERR: $line" if ($verbose && defined $line);
            }
            else 
            {
		# FIXME -- icky blocking read
                my $line = <CMD_OUT>;
                print "stunnel STDOUT: $line" if ($verbose && defined $line);
            }
            $selector->remove($fh) if eof($fh);
        }
    }

    close(CMD_IN);
    close(CMD_OUT);
    close(CMD_ERR);

    waitpid $stunnel_pid,0;
}
sub open_socket()
{
    printf "Creating an ssl stunnel from localhost:$localport to $hostname\n" if $verbose;
    $socket = IO::Socket::INET->new(PeerAddr => 'localhost',
    				    PeerPort => $localport,
    				    Proto    => 'tcp',
				    Type	 => SOCK_STREAM) 
        or diedie "Can't connect to localhost:$localport: $@\n";

    return $socket;
}


sub power_off
{
    my $response = set_power_state ("N");
    my @response = split /\n/,$response;
    foreach my $line (@response)
    {
        if ($line =~ /MESSAGE='(.*)'/)
        {
            my $msg = $1;
            if ($msg eq "No error") 
            { 
                $agent_status = 0;
                next; 
            }
	    elsif ($msg eq "Host power is already OFF.")
            {
                $agent_status = 0;
                print "warning: $msg\n" unless defined $quiet;
            }
            else
            {
                $agent_status = 1;
                print STDERR "error: $msg\n";
            }
        }
    }

    return $agent_status;
}


sub power_on
{
    my $response = set_power_state ("Y");
    my @response = split /\n/,$response;
    foreach my $line (@response)
    {

        if ($line =~ /MESSAGE='(.*)'/)
        {
            my $msg = $1;
            if ($msg eq "No error") 
            { 
                $agent_status = 0;
                next; 
            }
	    elsif ($msg eq "Host power is already ON.")
            {
                $agent_status = 0;
                print "warning: $msg\n" unless defined $quiet;
            }
            else
            {
                $agent_status = 1;
                print STDERR "error: $msg\n";
            }
        }
    }

    return $agent_status;
}

sub power_status
{
    my $response = get_power_state ();
    my @response = split /\n/,$response;
    foreach my $line (@response)
    {
        if ($line =~ /MESSAGE='(.*)'/)
        {
            my $msg = $1;
            if ($msg eq "No error") 
            { 
                $agent_status = 0;
                next; 
            }
            else
            {
                $agent_status = 1;
                print STDERR "error: $msg\n";
            }
        }
        elsif ($line =~ /HOST POWER=\"(.*)\"/)
        {
           $agent_status = 0;
           print "power is $1\n";
        }

    }

    return $agent_status;
}

sub set_power_state
{
    my $state = shift;
    my $response = "";

    if (!defined $state || ( $state ne "Y" && $state ne "N") )
    {
        diedie "illegal state\n";
    }

    $socket = open_socket;

    sendsock $socket, "<?xml version=\"1.0\"?>\r\n";
    $response = receive_response($socket,1);

    #> printf "Closed because no more answers\n" if ($verbose && !defined($answer));

    print "Sending power-o".(($state eq "Y")?"n":"ff")."\n" if ($verbose);

    sendsock $socket, "<RIBCL VERSION=\"1.2\">\n";
    sendsock $socket, "    <LOGIN USER_LOGIN = \"$username\" PASSWORD = \"$passwd\">\n";
    sendsock $socket, "        <SERVER_INFO MODE = \"write\">\n";
    sendsock $socket, "            <SET_HOST_POWER HOST_POWER = \"$state\"/>\n";
    sendsock $socket, "        </SERVER_INFO>\n";
    sendsock $socket, "    </LOGIN>\n";
    sendsock $socket, "</RIBCL>\n";

    $response = receive_response($socket);

    print "Closing connection\n" if ($verbose);
    close($socket);

    return $response;
}

sub get_power_state
{
    my $response = "";

    $socket = open_socket;

    sendsock $socket, "<?xml version=\"1.0\"?>\r\n";
    $response = receive_response($socket,1);

    #> printf "Closed because no more answers\n" if ($verbose && !defined($answer));

    print "Sending get-status\n" if ($verbose);

    sendsock $socket, "<RIBCL VERSION=\"1.2\">\n";
    sendsock $socket, "    <LOGIN USER_LOGIN = \"$username\" PASSWORD = \"$passwd\">\n";
    sendsock $socket, "        <SERVER_INFO MODE = \"read\">\n";
    sendsock $socket, "            <GET_HOST_POWER_STATUS/>\n";
    sendsock $socket, "        </SERVER_INFO>\n";
    sendsock $socket, "    </LOGIN>\n";
    sendsock $socket, "</RIBCL>\n";

    $response = receive_response($socket);

    print "Closing connection\n" if ($verbose);
    close($socket);
    
    return $response;
}

sub fail
{
    ($msg)=@_;
    print $msg unless defined $quiet;
    exit 1;
}


sub get_options_stdin
{
    my $opt;
    my $line = 0;
    while( defined($in = <>) )
    {
        $_ = $in;

        chomp;

        # strip leading and trailing whitespace
        s/^\s*//;
        s/\s*$//;

        # skip comments
        next if /^#/;

        $line+=1;
        $opt=$_;
        next unless $opt;

        ($name,$val)=split /\s*=\s*/, $opt;

        if ( $name eq "" )
        {
           print STDERR "parse error: illegal name in option $line\n";
           exit 2;
        }

        elsif ($name eq "action" )
        {
            $action = $val;
        }

        # DO NOTHING -- this field is used by fenced or stomithd
        elsif ($name eq "agent" ) { }

        # FIXME -- depricated.  use "hostname" instead.
        elsif ($name eq "fm" )
        {
            (my $dummy,$hostname) = split /\s+/,$val;
            print STDERR "Depricated \"fm\" entry detected.  refer to man page.\n";
        }

        elsif ($name eq "hostname" )
        {
            $hostname = $val;
        }
        elsif ($name eq "localport" )
        {
            $localport = $val;
	}
        elsif ($name eq "login" )
        {
            $username = $val;
        }

	# FIXME -- depreicated residue of old fencing system
        elsif ($name eq "name" ) { }

        elsif ($name eq "passwd" )
        {
            $passwd = $val;
        }
        elsif ($name eq "verbose" )
        {
            $verbose = $val;
        }

        # FIXME should we do more error checking?  
        # Excess name/vals will be eaten for now
        else
        {
           fail "parse error: unknown option \"$opt\"\n";
           #> exit 2;
        }
    }
}

sub fail_usage
{
    ($msg)=@_;
    print STDERR $msg if $msg;
    print STDERR "Please use '-h' for usage.\n";
    exit 1;
}


sub version
{
  print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
  print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );

  exit 0;
}

# get stunnel version.  version 3.x of stunnel uses "-V" to print the version
# where as version 4.x uses "-version".  We must handle both cases to deal with
# stunnel's brokeness.
#open VER,"stunnel -V |" or 
sub get_stunnel_version
{
	$stunnel_pid = open3 (*CMD_IN,*CMD_OUT,*CMD_OUT,"stunnel -V") or
		die "open3 error: $!";

	while (<CMD_OUT>) 
	{
		if ($_ =~ /^stunnel (\d+)\..* on .*/)
		{
			$stunnel_version = $1;
		}
	}
	close CMD_IN;
	close CMD_OUT;
	$status = waitpid ($stunnel_pid,0);

	if ( $status != 0 )
	{
		$stunnel_pid = open3 (*CMD_IN,*CMD_OUT,*CMD_OUT,"stunnel -version") or
			die "open3 error: $!";
		while (<CMD_OUT>) 
		{
			if ($_ =~ /^stunnel (\d+)\..* on .*/)
			{
				$stunnel_version = $1;
			}
		}
		close CMD_IN;
		close CMD_OUT;
		$status = waitpid ($stunnel_pid,0);
	}
}


################################################################################
# MAIN

# since we might be running tcsh and not a real shell where we can
# divert stderr, we'll just use sh.  hopefully it's really bash.
$_ = system "sh -c 'which stunnel > /dev/null 2>&1'";
diedie "stunnel not found\n" if $_;


$stunnel_version = 0;
get_stunnel_version();

$action = "reboot";

if (@ARGV > 0) {
   getopts("a:hl:n:o:p:qvV") || fail_usage ;

   usage if defined $opt_h;
   version if defined $opt_V;

   fail_usage "Unkown parameter." if (@ARGV > 0);

   fail_usage "No '-a' flag specified." unless defined $opt_a;
   $hostname = $opt_a;

   fail_usage "No '-l' flag specified." unless defined $opt_l;
   $username = $opt_l;

   fail_usage "No '-p' flag specified." unless defined $opt_p;
   $passwd   = $opt_p;

   $action = $opt_o if defined $opt_o;
   fail_usage "Unrecognised action '$action' for '-o' flag"
      unless $action=~ /^(off|on|reboot|status)$/;

   $localport = $opt_n if defined $opt_n;

   $quiet = 1 if defined $opt_q;

   $verbose = 1 if defined $opt_v;

} else {
   get_options_stdin();

   fail "no host\n" unless defined $hostname;
   fail "no login name\n" unless defined $username;
   fail "no password\n" unless defined $passwd;

   fail "unrecognised action: $action\n"
      unless $action=~ /^(off|on|reboot|status)$/;
}

$localport = 8888 unless defined ($localport);
$hostname = "$hostname:443" unless ($hostname =~ /:/);

#> $msg = "<?xml version=\"1.0\"?>\r\n";
$agent_status = -1;


### Setup stunnel from localhost:$localport to $hostname ($hostname can be in hostname:port format)
open_stunnel;

#foreach my $sig (keys %SIG) { $SIG{$sig} = sub {print "*** SIGNAL $sig DETECTED ***\n"}; }



foreach ($action)
{
    /on/ and do 
    {
        power_on;
    };

    /off/ and do 
    {
        power_off;
    };

    /reboot/ and do 
    {
        power_off;
        diedie "unexpected error\n" if ($agent_status < 0);

	$agent_status = -1;
        power_on;
        diedie "unexpected error\n" if ($agent_status < 0);
    };

    /status/ and do 
    {
        power_status;
    };

}

close_stunnel();

# $agent_status should have been set at this point.  die to avoid false success.
diedie "unexpected error\n" if ($agent_status < 0);

if ($agent_status == 0)
{
    print "success\n" unless defined $quiet;
    exit 0
}
else
{
    print "failure\n" unless defined $quiet;
    exit 1
}


################################################################################
bedrock/fence/agents/rib/Makefile0100600000745200074520000000256410015057457016614 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

SOURCE= fence_rib.pl
TARGET= fence_rib

top_srcdir=../../..
include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: $(TARGET)

fence_rib: $(SOURCE)
	: > $(TARGET)
	awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE) >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/fence_release.cf perl FENCE_RELEASE_NAME >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf perl SISTINA_COPYRIGHT >> $(TARGET)
	echo "\$$BUILD_DATE=\"(built `date`)\";" >> $(TARGET)
	awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
	chmod +x $(TARGET)

copytobin: ${TARGET}
	cp ${TARGET} ${top_srcdir}/bin/${TARGET}

clean:
	rm -f $(TARGET)
bedrock/fence/agents/manual/0040700000745200074520000000000010073325704015644 5ustar  alewisalewisbedrock/fence/agents/manual/Makefile0100600000745200074520000000237410015057456017313 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

TARGET= fence_manual fence_ack_manual

fence_manual_SOURCE= manual.c
fence_ack_manual_SOURCE= ack.c
	
top_srcdir=../../..


INCLUDE= -I${top_srcdir}/include -I${top_srcdir}/config


include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: ${TARGET}

fence_manual: ${fence_manual_SOURCE:.c=.o}
	${CC} ${CFLAGS} ${LDFLAGS} ${fence_manual_SOURCE:.c=.o} ${LOADLIBES} ${LDLIBS} -o $@

fence_ack_manual: ${fence_ack_manual_SOURCE:.c=.o}
	${CC} ${CFLAGS} ${LDFLAGS} ${fence_ack_manual_SOURCE:.c=.o} ${LOADLIBES} ${LDLIBS} -o $@

copytobin: all
	cp ${TARGET} ${top_srcdir}/bin

clean:
	rm -f *.o ${TARGET}
bedrock/fence/agents/manual/ack.c0100600000745200074520000000627410015057456016560 0ustar  alewisalewis/******************************************************************************
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
**  
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "fence_release.cf"
#include "copyright.cf"

char *pname = NULL;

int quiet_flag = 0;
int override_flag = 0;

void print_usage(void)
{
  printf("Usage:\n");
  printf("\n");
  printf("%s [options]\n"
         "\n"
         "Options:\n"
         "  -h               usage\n"
	 "  -O               override\n"
	 "  -s <ip>          IP address of machine which was manually fenced\n"
         "  -V               Version information\n", pname);
}


int main(int argc, char **argv)
{
  int error, fd;
  char line[256];
  char *ipaddr = NULL;
  char response[3];
  int c;

  memset(line, 0, 256);

  pname = argv[0];
    
  while ((c = getopt(argc, argv, "hOs:qV")) != -1)
  {
    switch(c)
    {
    case 'h':
      print_usage();
      exit(0);
	
    case 'O':
      override_flag = 1;
      break;

    case 's':
      ipaddr = optarg;
      break;

    case 'q':
      quiet_flag = 1;
      break;

    case 'V':
      printf("%s %s (built %s %s)\n", pname, FENCE_RELEASE_NAME,
                __DATE__, __TIME__);
      printf("%s\n", SISTINA_COPYRIGHT);
      exit(0);
      break;

    case ':':
    case '?':
      fprintf(stderr, "Please use '-h' for usage.\n");
      exit(1);
      break;

    default:
      fprintf(stderr, "Bad programmer! You forgot to catch the %c flag\n", c);
      exit(1);
      break;

    }
  }

  if (!ipaddr)
  {
    if(!quiet_flag)
      print_usage();
    exit(1);
  }

  if(!override_flag)
  {
    printf("\nWarning:  If the machine with IP address \"%s\" has not been\n"
   	   "manually fenced (i.e. power cycled or disconnected from all\n"
	   "storage devices) the GFS file system may become corrupted and all\n"
	   "its data unrecoverable!  Please verify that the above IP address\n"
	   "correctly matches the machine you just rebooted (or disconnected).\n", 
	   ipaddr);

    printf("\nAre you certain you want to continue? [yN] ");
    scanf("%s", response);

    if (tolower(response[0] != 'y'))
    {
      printf("%s operation canceled.\n", pname);
      exit(1);
    }
  }

  fd = open("/tmp/fence_manual.fifo", O_WRONLY | O_NONBLOCK);
  if (fd < 0)
  {
    perror("can't open /tmp/fence_manual.fifo");
    exit(1);
  }

  sprintf(line, "meatware ok\n");

  error = write(fd, line, 256);
  if (error < 0)
  {
    perror("can't write to /tmp/fence_manual.fifo");
    exit(1);
  }
    
  if(!quiet_flag)
    printf("done\n");

  return(0);
}


bedrock/fence/agents/manual/manual.c0100600000745200074520000001170510015057456017272 0ustar  alewisalewis/******************************************************************************
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
**  
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <syslog.h>

#include "fence_release.cf"
#include "copyright.cf"

char *pname = NULL;

char args[256];
char name[256];
char ipaddr[256];
char path[256];
char fname[256];

int quiet_flag = 0;

void print_usage(void)
{
  printf("Usage:\n");
  printf("\n");
  printf("%s [options]\n"
         "\n"
         "Options:\n"
	 "  -h               usage\n"
	 "  -q               quiet\n"
	 "  -s <ip>          IP address of machine to fence\n"
	 "  -V               Version\n",pname);
}


void get_options(int argc, char **argv)
{
  int c, rv;
  char *curr;
  char *rest;
  char *value;

  if (argc > 1)
  {        
    while ((c = getopt(argc, argv, "hs:p:qV")) != -1)
    {
      switch(c)
      {
      case 'h':
        print_usage();
        exit(0);
	
      case 's':
        strcpy(ipaddr, optarg);
        break;

      case 'q':
        quiet_flag = 1;
        break;

      case 'p':
        strcpy(path, optarg);
        break;

      case 'V':
        printf("%s %s (built %s %s)\n", pname, FENCE_RELEASE_NAME,
               __DATE__, __TIME__);
        printf("%s\n", SISTINA_COPYRIGHT);
        exit(0);
        break;
  
      case ':':    
      case '?':
        fprintf(stderr, "Please use '-h' for usage.\n");
        exit(1);
        break;

      default:
        fprintf(stderr, "Bad programmer! You forgot to catch the %c flag\n", c);
        exit(1);
        break;

      }
    }
  }
  
  else
  {
    if ((rv = read(0, args, 255)) < 0)
    {
      if(!quiet_flag)
        printf("failed: no input\n");
      exit(1);
    }
    curr = args;
    while ((rest = strchr(curr, '\n')) != NULL){
      *rest = 0;
      rest++;
      if ((value = strchr(curr, '=')) == NULL){
	printf("failed: invalid input\n");
	exit(1);
      }
      *value = 0;
      value++;
      if (!strcmp(curr, "agent")){
	strcpy(name, value);
        pname = name;
      }
      if (!strcmp(curr, "ipaddr"))
	strcpy(ipaddr, value);
      curr = rest;
    }
  }

  if (!strlen(path))
      strcpy(path, "tmp");
}



int main(int argc, char **argv)
{
  int error, fd, lfd;
  char line[256], *mw, *ok;
  struct flock lock;


  openlog("fence_manual", 0, LOG_DAEMON);

  memset(args, 0, 256);
  memset(name, 0, 256);
  memset(ipaddr, 0, 256);
  memset(path, 0, 256);
  memset(fname, 0, 256);

  pname = argv[0];

  get_options(argc, argv);

  if (ipaddr[0] == 0)
  {
    if(!quiet_flag)
      printf("failed: %s no IP addr\n", name);
    exit(1);
  }


  /* Serialize multiple fence_manual's by locking a lock file */

  memset(fname, 0, 256);
  sprintf(fname, "/%s/fence_manual.lock", path);
  lfd = open(fname, O_WRONLY | O_CREAT,
             (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
  if (lfd < 0)
  {
    if (!quiet_flag)
      printf("failed: %s %s lockfile open error\n", pname, ipaddr);
    exit(1);
  }

  lock.l_type = F_WRLCK;
  lock.l_start = 0;
  lock.l_whence = SEEK_SET;
  lock.l_len = 0;

  error = fcntl(lfd, F_SETLKW, &lock);
  if (error < 0)
  {
    if (!quiet_flag)
      printf("failed: fcntl errno %d\n", errno);
    exit(1);
  }


  /* It's our turn to use the fifo */

  syslog(LOG_CRIT, "Node %s requires hard reset.  Run \"fence_ack_manual -s %s\""
                   " after power cycling the machine.\n", 
                   ipaddr, ipaddr);

  umask(0);
  memset(fname, 0, 256);
  sprintf(fname, "/%s/fence_manual.fifo", path);
  error = mkfifo(fname, (S_IRUSR | S_IWUSR));
  if (error && errno != EEXIST)
  {
    if (!quiet_flag)
      printf("failed: %s mkfifo error\n", pname);
    exit(1);
  }

  fd = open(fname, O_RDONLY);
  if (fd < 0)
  {
    if (!quiet_flag)
      printf("failed: %s %s open error\n", pname, ipaddr);
    exit(1);
  }


  /* Get result from ack_manual */

  memset(line, 0, 256);
  error = read(fd, line, 256);
  if (error < 0)
  {
    if(!quiet_flag)
      printf("failed: %s %s read error\n", pname, ipaddr);
    exit(1);
  }


  mw = strstr(line, "meatware");
  ok = strstr(line, "ok");

  if (!mw || !ok)
  {
    if(!quiet_flag)
      printf("failed: %s %s improper message\n", pname, ipaddr);
    exit(1);
  }

  if(!quiet_flag)
    printf("success: %s %s\n", pname, ipaddr);
  unlink("/tmp/fence_manual.fifo");
  return 0;
}


bedrock/fence/agents/baytech/0040700000745200074520000000000010073325704016006 5ustar  alewisalewisbedrock/fence/agents/baytech/Makefile0100600000745200074520000000256610015057456017460 0ustar  alewisalewis###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

SOURCE= fence_XXX.pl
TARGET= fence_XXX

top_srcdir=../../..
include ${top_srcdir}/make/defines.mk
include ${top_srcdir}/make/flags.mk

all: $(TARGET)

$(TARGET): $(SOURCE)
	: > $(TARGET)
	awk "{print}(\$$1 ~ /#BEGIN_VERSION_GENERATION/){exit 0}" $(SOURCE) >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/fence_release.cf perl FENCE_RELEASE_NAME >> $(TARGET)
	${top_srcdir}/scripts/define2var ${top_srcdir}/config/copyright.cf perl SISTINA_COPYRIGHT >> $(TARGET)
	echo "\$$BUILD_DATE=\"(built `date`)\";" >> $(TARGET)
	awk -v p=0 "(\$$1 ~ /#END_VERSION_GENERATION/){p = 1} {if(p==1)print}" $(SOURCE) >> $(TARGET)
	chmod +x $(TARGET)

copytobin: ${TARGET}
	cp ${TARGET} ${top_srcdir}/bin/${TARGET}

clean:
	rm -f $(TARGET)


bedrock/fence/agents/baytech/fence_baytech.pl0100700000745200074520000003515610015057456021136 0ustar  alewisalewis#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##  
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################

# This fencing agent is written for the Baytech RPC27-20nc in conjunction with
# a Cyclades terminal server.  The Cyclades TS exports the RPC's serial port
# via a Telnet interface.  Other interfaces, such as SSH, are possible.  
# However, this script relys upon the assumption that Telnet is used.  Future
# features to this agent would allow the agent to work with a mulitude of 
# different communication protocols such as Telnet, SSH or Kermit.
#
# The other assumption that is made is that Outlet names do not end in space.
# The name "Foo" and "Foo    " are identical when the RPC prints them with
# the status command.

use Net::Telnet;
use Getopt::Std;

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and 
# "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="";
$SISTINA_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;


sub rpc_error 
{
	if (defined $error_message && $error_message ne "")
	{
		chomp $error_message;
		die "$error_message\n";
	}
	else
	{
		die "read timed-out\n"
	}
}

sub usage 
{

    print "Usage:\n";
    print "\n";
    print "$pname [options]\n";
    print "\n";
    print "Options:\n";
    print " -a host        host to connect to\n";
    print " -D             debugging output\n";
    print " -h             usage\n";
    print " -l string      user name\n";
    print " -o string      action: On,Off,Status or Reboot (default)\n";
    print " -n string      outlet name\n";
    print " -p string      password\n";
    print " -V             version\n";

    exit 0;
}

sub fail
{
  ($msg)=@_;
  print $msg."\n" unless defined $quiet;
  $t->close if defined $t;
  exit 1;
}

sub fail_usage
{
  ($msg)=@_;
  print STDERR $msg."\n" if $msg;
  print STDERR "Please use '-h' for usage.\n";
  exit 1;
}

sub version
{
  print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
  print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );

  exit 0;
}

# Get operating paramters, either with getopts or from STDIN
sub get_options
{
   $action = "Reboot";
   if (@ARGV > 0) {
      getopts("n:l:p:o:a:VhD") || fail_usage ;

      usage if defined $opt_h;
      version if defined $opt_V;

      fail_usage "Unkown parameter." if (@ARGV > 0);

   } else {
      get_options_stdin();
   } 

   fail "failed: must specify hostname" unless defined $opt_a;
   $host=$opt_a;
   $port=23 unless ($opt_a =~ /:/);

   $action = $opt_o if defined $opt_o;
   fail "failed: unrecognised action: $action"
         unless $action=~ /^(Off|On|Reboot|status)$/i;
   
   fail "failed: no outletname" unless defined $opt_n;
   $outlet = $opt_n;

   $debug=$opt_D if defined $opt_D;
   $quiet=$opt_q if defined $opt_q;
   $user=$opt_l if defined $opt_l;
   $passwd=$opt_p if defined $opt_p;

   if(defined $passwd && !defined $user)
   {
      fail "failed: password given without username";
   }
}

# Get options from STDIN
sub get_options_stdin
{
    my $opt;
    my $line = 0;
    while( defined($in = <>) )
    {
	$_ = $in;
        chomp;

	# strip leading and trailing whitespace
        s/^\s*//;
        s/\s*$//;

	# skip comments
	next if /^#/;

        $line+=1;
        $opt=$_;
	next unless $opt;

	($name,$val)=split /\s*=\s*/, $opt;

	if ( $name eq "" )
	{
	   print STDERR "parse error: illegal name in option $line\n";
	   exit 2;
	} 

        # DO NOTHING -- this field is used by fenced 
	elsif ($name eq "agent" ) { } 

	elsif ($name eq "host" ) 
	{
	    $opt_a = $val;
	} 

	elsif ($name eq "login" ) 
	{
	    $opt_l = $val;
	} 

	elsif ($name eq "passwd" ) 
	{
	    $opt_p = $val;
	} 

	elsif ($name eq "action" ) 
	{
	    $opt_o = $val;
	} 

	elsif ($name eq "outlet" ) 
	{
	    $opt_n = $val;
	} 

	else 
	{
	   fail "parse error: unknown option \"$opt\"";
	}
    }
}

# Get a bunch of lines.  The newlines must terminate complete lines.
sub getlines
{
	my $data=$t->get();
	return undef unless defined $data;
	my @chars = split //,$data;
	my @lines;
	my $line="";

	for (my $i=0;$i<@chars;$i++)
	{
		$line = $line.$chars[$i];
		next unless $chars[$i] eq "\n";
		$lines[@lines] = $line;
		$line = "";
	}
	$lines[@lines] = $line unless $line eq "";

	return @lines;
}

# Fill the global input buffer of lines read.  All lines are terminated with
# a newline.  If a line is not terminated, the next call to fill buffer will
# append the last line of the input buffer with the first line that it gets from
# getlines()
sub fill_buffer
{
	my @lines = getlines();
	return undef unless @lines;

	if(@buffer)
	{
		if ( $buffer[$#buffer]=~/\n/) { }
		else
		{
			$buffer[$#buffer] = $buffer[$#buffer].$lines[0];
			shift @lines;
		}
	}

	foreach (@lines) 
	{ 
		push @buffer,$_;
	}
}



#
# ($p_index,@data) = get_match @patterns;
#
# searches the input buffers for the patterns specified by the regeps in 
# @patterns, when a match is found, all the lines through the matched 
# pattern line are removed from the global input buffer and returned in the
# array @data.  The index into @patterns for the matching pattern is also
# returned.
sub get_match
{
	my (@patterns) = @_;
	$b_index = 0 unless defined $b_index;

	fill_buffer() unless defined @buffer;

	for(;;)
	{
		for(my $bi=$b_index; $bi<@buffer; $bi++)
		{
			for(my $pat=0; $pat<@patterns; $pat++)
			{
				if($buffer[$bi] =~ /$patterns[$pat]/)
				{
					$b_index = 0;
					my @rtrn = splice(@buffer,0,$bi);
					shift @buffer;
				
					if($debug)
					{
						foreach (@rtrn) { print $_ }
						print "$patterns[$pat] ";
					}
					
					return ($pat,@rtrn);
				}
			}
			$b_index = $bi;
		}

		fill_buffer();
	}
}

#
# ($bt_num,$bt_name,$bt_state,$bt_locked) = parse_status $outlet,@data;
#
# This parses the data @data and searches for an outlet named $outlet.
# The data will be in the form:
# 
#   Average Power:    0 Watts        Apparent Power:   17 VA
# 
#   True RMS Voltage: 120.0 Volts
# 
#   True RMS Current:   0.1 Amps     Maximum Detected:   0.2 Amps     
# 
#   Internal Temperature:  19.5 C
# 
#   Outlet Circuit Breaker: Good
# 
#    1)...Outlet  1       : Off           2)...Outlet  2       : Off          
#    3)...Outlet  3       : On            4)...Outlet  4       : On           
#    5)...Outlet  5       : On            6)...Outlet  6       : On           
#    7)...Outlet  7       : On            8)...Outlet  8       : On           
#    9)...Outlet  9       : On           10)...Outlet 10       : On           
#   11)...Outlet 11       : On           12)...Outlet 12       : On           
#   13)...Outlet 13       : On           14)...Outlet 14       : On           
#   15)...Outlet 15       : On           16)...Outlet 16       : On           
#   17)...Outlet 17       : On           18)...Outlet 18       : On           
#   19)...Outlet 19       : On           20)...Outlet 20       : On    Locked 
#
sub parse_status
{
	my $outlet = shift;
	my @data = @_;

	my $bt_num="";
	my $bt_name="";
	my $bt_state="";
	my $bt_locked="";

	# Verify that the Outlet name exists
	foreach my $line (@data)
	{
		next unless $line =~ /^[ 12][0-9]\)\.\.\./;

		my @entries = split /([ 12][0-9])\)\.\.\./,$line;
	
		foreach my $entry (@entries)
		{
			next if $entry eq "";
			
			if($entry =~ /^([ 12][0-9])$/)
			{
				$bt_num = $1;
			}
			elsif($entry =~ /^(.{15}) : (On|Off)(.*)/)
			{
	
				$bt_name = $1;
				$bt_state = $2;
				$bt_locked = $3;
	
				$_ = $bt_name;
				s/\s*$//;
				$bt_name = $_;
	
				$_ = $bt_locked;
				s/\s*$//;
				$bt_locked = $_;
	
				last if ($bt_name eq $outlet);
	
				$bt_name = "";
				next;
			}
			else
			{
				die "parse error: $entry";
			}
		}
		last if ($bt_name ne "");
	}
	
	if ($bt_name eq "")
	{
		$bt_num=undef;
		$bt_name=undef;
		$bt_state=undef;
		$bt_locked=undef;
	}

	return ($bt_num,$bt_name,$bt_state,$bt_locked);
}

##########################################################################
#
# Main

get_options;


if (defined $port)
{
	$t = new Net::Telnet(Host=>$host, Port=>$port) or 
		die "Unable to connect to $host:$port: ".($!?$!:$_)."\n";
}
else
{
	$t = new Net::Telnet(Host=>$host) or 
		die "Unable to connect to $host: ".($!?$!:$_)."\n";
}



#> DEBUG $t->dump_log("LOG");

$t->print("\n");

my @patterns;
$prompt_user="^Enter user name:";
$prompt_pass="^Enter Password:";
$prompt_cmd="^RPC-27>";
$prompt_confirm_yn="^.*\\(Y/N\\)\\?";

$patterns[0]=$prompt_user;
$patterns[1]=$prompt_pass;
$patterns[2]=$prompt_cmd;
$patterns[3]=$prompt_confirm_yn;

my $p_index;
my @data;

my $bt_num="";
my $bt_name="";
my $bt_state="";
my $bt_locked="";
my $exit=1;

($p_index,@data) = get_match @patterns;

#
# Set errmode after first get_match.  This allows for more descriptive errors
# when handling unexpected error conditions
#
$t->errmode(\&rpc_error);

# At this point, the username is unknown.  We'll just
# pass in an empty passwd so that we can get back to the 
# login prompt.  
#
# FIXME
# If this is the third login failure for this switch, an
# additional newline will need to be made sent.  This script
# does not handle that case at this time.  This will cause
# a timeout on read and cause this to fail.  Rerunning the
# script ought to work though.
if ($patterns[$p_index] eq $prompt_pass)
{
	$t->print("\n");
	($p_index,@data) = get_match @patterns;
}

# Enter user name:
#
# Depending how the RPC is configured, a user name may not be required.
# We will only deal with usernames if prompted.  
#
# If there is no user/passwd given as a parameter, but the switch
# expects one, rather than just fail, we will first try to
# get the switch in a known state 
my $warn_user="yes";
my $warn_passwd="yes";

$error_message = "Invalid user/password";

for (my $retrys=0; $patterns[$p_index] eq $prompt_user ; $retrys++)
{
	$warn_passwd = "yes";
	if(defined $user)
	{
		$t->print("$user\n");
		$warn_user = "no";
	}
	else
	{
		$t->print("\n");

	}
	($p_index,@data) = get_match @patterns;

	# Enter Password:
	#
	# Users don't have to have passwords either.  We will only check
	# that the user specified a password if we were prompted by the
	# RPC.
	if ($patterns[$p_index] eq $prompt_pass)
	{
		if(defined $passwd)
		{
			$t->print("$passwd\n");
			$warn_passwd = "no";
		}
		else
		{
			$t->print("\n");
		}

		($p_index,@data) = get_match @patterns;
	}


	#
	# If a valid user name is given, but not a valid password, we
	# will loop forever unless we limit the number of retries
	#
	# set the user to "" so we stop entering a valid username and
	# force the login proccess to fail
	#
	if ($retrys>2)
	{
		$user = "";
	}
	elsif ($retrys>10)
	{
		die "maximum retry count exceeded\n";
	}
}

#
# reset errmode to die()
#
$t->errmode("die");

# all through with the login/passwd.  If we see any other prompt it is an 
# error.
if ($patterns[$p_index] ne $prompt_cmd)
{
	$t->print("\n");
	die "bad state: '$patterns[$p_index]'";
}

if (defined $user && ($warn_user eq "yes"))
{
	warn "warning: user parameter ignored\n";
}

if (defined $passwd && ($warn_passwd eq "yes"))
{
	warn "warning: passwd parameter ignored\n";
}




# We are now logged in, no need for these patterns.  We'll strip these
# so that we don't have to keep searching for patterns that shouldn't
# appear.
shift @patterns;
shift @patterns;

# Get the current status of a particular outlet.  Explicitly pass
# the status command in case the RPC is not configured to report the
# status on each command completion.
$t->print("status\n");
($p_index,@data) = get_match @patterns;
($bt_num,$bt_name,$bt_state,$bt_locked) = parse_status $outlet,@data;

if (!defined $bt_name )
{
	# We have problems if there is not outlet named $outlet
	print "Outlet \'$outlet\' not found\n";
	$exit=1;
}
elsif ($action =~ /status/i)
{
	print "Outlet '$bt_name' is $bt_state and is ".
		(($bt_locked eq "")?"not ":"")."Locked\n";
	$exit=0;
}
elsif ($bt_locked ne "")
{
	# Report an error if an outlet is locked since we can't actually 
	# issue commands on a Locked outlet.  This will prevent false
	# successes.
	print "Outlet '$bt_name' is Locked\n";
	$exit=1;
}
elsif (($action =~ /on/i && $bt_state eq "On") ||
	($action =~ /off/i && $bt_state eq "Off") )
{
	# No need to issue the on/off command since we are already in 
	# the desired state
	print "Outlet '$bt_name' is already $bt_state\n";
	$exit=0;
}
elsif ($action =~ /o(n|ff)/i)
{
	# On/Off command
	$t->print("$action $bt_num\n");
	($p_index,@data) = get_match @patterns;
	
	# Confirmation prompting maybe enabled in the switch.  If it is,
	# we enter 'Y' for yes.
	if ($patterns[$p_index] eq $prompt_confirm_yn)
	{
		$t->print("y\n");
		($p_index,@data) = get_match @patterns;
	}

	$t->print("status\n");
	($p_index,@data) = get_match @patterns;

	($bt_num,$bt_name,$bt_state,$bt_locked) = parse_status $outlet,@data;
	
	if ($bt_state =~ /$action/i)
	{
		print "success: outlet='$outlet' action='$action'\n";
		$exit=0;
	}
	else
	{	
		print "fail: outlet='$outlet' action='$action'\n";
		$exit=1;
	}
}
elsif ($action =~ /reboot/i)
{
	# Reboot command
	$t->print("$action $bt_num\n");
	($p_index,@data) = get_match @patterns;
	
	# Confirmation prompting maybe enabled in the switch.  If it is,
	# we enter 'Y' for yes.
	if ($patterns[$p_index] eq $prompt_confirm_yn)
	{
		$t->print("y\n");
		($p_index,@data) = get_match @patterns;
	}

	# The reboot command is annoying.  It reports that the outlet will
 	# reboot in 9 seconds.  Then it has a countdown timer.  We first
	# look for the "Rebooting... 9" message, then we parse the remaining
	# output to verify that it reaches 0 without skipping anything.
	my $pass=0;
	foreach (@data)
	{
		chomp;
		my $line = $_;

		# There is a countdown timer that prints a number, then sleeps a 
		# second, then prints a backspace and then another number
		#
		# /^Rebooting\.\.\. 9\b8\b7\b6\b5\b4\b3\b2\b1\b0\b$/
		if($line =~/^Rebooting\.\.\..*0[\b]$/)
		{
			$pass=1;
			last;
		}
	}

	if ($pass)
	{
		print "success: outlet='$outlet' action='$action'\n";
		$exit=0;
	}
	else
	{
		print "fail: outlet='$outlet' action='$action'\n";
		$exit=1;
	}
}
else
{
	die "bad state";
}

# Clean up.  If we don't tell it to logout, then anybody else can log onto 
# the serial port and have access to the switch without authentication (when 
# enabled)
$t->print("logout\n");
$t->close;
exit $exit;