head	1.8;
access;
symbols;
locks
	mohlerb:1.8; strict;
comment	@# @;


1.8
date	2000.04.10.17.27.14;	author mohlerb;	state Exp;
branches;
next	1.7;

1.7
date	2000.04.06.14.07.11;	author mohlerb;	state Exp;
branches;
next	1.6;

1.6
date	2000.04.04.02.36.00;	author mohlerb;	state Exp;
branches;
next	1.5;

1.5
date	2000.03.02.22.03.03;	author mohlerb;	state Exp;
branches;
next	1.4;

1.4
date	2000.02.09.23.44.18;	author mohlerb;	state Exp;
branches;
next	1.3;

1.3
date	2000.02.04.00.14.32;	author mohlerb;	state Exp;
branches;
next	1.2;

1.2
date	2000.02.03.23.22.02;	author mohlerb;	state Exp;
branches;
next	1.1;

1.1
date	2000.01.12.18.08.20;	author mohlerb;	state Exp;
branches;
next	;


desc
@operating system specific routines for BSD
Original source Copyright (C) 2000 Frank Crawford (frank@@ansto.gov.au)
@


1.8
log
@changes from Bruce Mohler including:
replaced calls to ReturnArray with either ReturnArrayFile or
ReturnArrayExec; also removed references to ReturnArrayGlob
@
text
@package BSD;

# BSD.pm - these are operating system specific routines for BSD
#
# Rules for these subroutines:
# 
#	1.  These subroutines can be called in any order except
#	    for Initialize${OSName}.  That will always be called
#	    before any others.
#	2.  These subroutines can be called in any order...
# 
# ==============================================================
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 
# 2 of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be 
# useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.
# 
# Original source:
#	Copyright (c) 1999, 2000 Frank Crawford
#	Based upon code by Bruce W. Mohler
# 
# Contributed source:
#	Copyright (c) 2000 Martin Andrews
#	Copyright (c) 2000 Bruce W. Mohler
# 
# ==============================================================
# 
# $Header: /export/home/mohlerb/syssumm/remote/RCS/BSD.pm,v 1.7 2000/04/06 14:07:11 mohlerb Exp mohlerb $
# 
# $Revision: 1.7 $
#
# $Log: BSD.pm,v $
# Revision 1.7  2000/04/06 14:07:11  mohlerb
# changes from Frank Crawford including:
# a fix for BSD.pm, to cater for the fact that "/etc/netstart"
# is a shell script, and hence an executable, but also contains
# the necessary data as shell variables; also had to fix the
# test for a router, if it came back with no match, and exclude
# the "sw" network interfaces (they are for swIPE, i.e. some form
# of IPSec pseudo-device)
#
# Revision 1.6  2000/04/04 02:36:00  mohlerb
# changes from Frank Crawford including:
# fix typo in ReturnSwapBSD function
#
# Revision 1.5  2000/03/02 22:03:03  mohlerb
# changes from Frank Crawford including:
# deleting the use of syslog and getting the swap function to work
#
# Revision 1.4  2000/02/09 23:44:18  mohlerb
# changes from Bruce Mohler including:
# cleaned up ReturnServices by moving function to common.pm
# and having it be driven by a @@Services array in syssumm.pl;
# note also the option at the end of the Initialize<OS> function
# where you can add OS-specific services that you wish to have
# monitored
#
# Revision 1.3  2000/02/04 00:14:32  mohlerb
# changes from Bruce Mohler including:
# implemented ReturnServices to return all of the Running*
# functions as a multiple value field
#
# Revision 1.2  2000/02/03 23:22:02  mohlerb
# changes from Martin Andrews including:
# IRIX, Linux, and SunOS now report swap file sizes, stubs added
# to other OS modules
#
# Revision 1.1  2000/01/12 18:08:20  mohlerb
# Initial revision
#

use Sys::Hostname;
use common;

require Exporter;
@@ISA = qw(Exporter);
###########################################################################
# the following sub-routines (&) are variables ($) will be 
# visible in a program using this module...
@@EXPORT = qw(
	&InitializeBSD
);
# 
# Note that you do not need to export the Return* subroutine
# names since they are being called by reference.
# 
###########################################################################

###########################################################################
# Public Global Variables (must be declared above)
###########################################################################


###########################################################################
# Private Global Variables
###########################################################################

# parts of OS version - filled in by InitializeBSD()
$OSVersion = "";
$OSVersionMajor = "";
$OSVersionMinor = "";

# where commands are located			standard args
# CUSTOMIZE
$AmdCommand = "/usr/sbin/amd";
$DfCommand = "/bin/df";				$LocalFileSystems = "-t ufs";
						$NFSFileSystems = "-t nfs";
$DiskinfoCommand = "";				# filled in below
$DomainnameCommand = "/sbin/domainname";
$HostIdCommand = "/usr/bin/hostid";
$IfconfigCommand = "/sbin/ifconfig";		$IfconfigArgs = "-a";
$IOStatCommand = "/usr/sbin/iostat";
$MountdCommand = "/sbin/mountd";
$NetstatCommand = "/usr/bin/netstat";		$InterfaceArgs = "-i";
$NfsdCommand = "/sbin/nfsd";
$PsCommand = "/bin/ps";				$PsArgs = "-alx";
$SendmailCommand = "/usr/sbin/sendmail";
$SwapCommand = "/usr/sbin/pstat";		$SwapArgs = "-s";
$SysCtlCommand = "/sbin/sysctl";		$SysCtlLicenseUsers = "-n kern.license_users";
						$SysCtlHardware = "-a hw";
$UnameCommand = "/usr/bin/uname";

# where files are located
# CUSTOMIZE
$ExportsPath = "/etc/exports";
$InetdConfPath = "/etc/inetd.conf";
$NameserverConfPath = "/etc/named.conf";
$NetConfPath = "/etc/netstart";			$DefaultRouterTag = "defroute";
$PatchLogPath = "/var/db/install.log";
$PatchSysLogPath = "/sys/PATCHLOG";
$PrintcapPath = "/etc/printcap";
$ResolvConfPath = "/etc/resolv.conf";

$SubroutineSuffix = "";

# device path patterns - filled in by InitializeBSD()
$DiskNamePattern = "";
$TapeNamePattern = "";

$NameServerPattern = "named";
$NfsdCommandPattern = "nfsd";
$SysCtlMaxMemPattern = "hw.physmem";
$SysCtlNCpuPattern = "hw.ncpu";
$SysCtlMachinePattern = "hw.machine";
$SysCtlModelPattern = "hw.model";


###########################################################################
# Subroutines
###########################################################################

# 
# This subroutine is called before any others.  It's
# reason for existence is to plug in the references to
# subroutines below to actually generate the information.
# 

sub InitializeBSD ()
{
	print "InitializeBSD()...\n" if $main::Debug;

	# initialize $SubroutineSuffix...
	WhatVersionOfBSD();

	# we need the nodename for later on...
	$main::NodeName = hostname();
	print "\tNodeName is $main::NodeName\n" if $main::Debug;

	# Set the blocksize for future disk functions (e.g. df).
	$ENV{'BLOCKSIZE'} = '1024';

# 	# fill in different file and command paths

	# plug in appropriate subroutines
 	$main::Routines{General}{Vendor} = \&ReturnVendorBSD;
 	$main::Routines{General}{Model} = \&ReturnModelBSD;
 	$main::Routines{General}{HostId} = \&ReturnHostIdBSD;

 	$main::Routines{Hardware}{Processors} = \&ReturnProcessorsBSD;
 	$main::Routines{Hardware}{Memory} = \&ReturnMemoryBSD;
 	$main::Routines{Hardware}{Disks} = \&ReturnDisksBSD;
 	$main::Routines{Hardware}{Tapes} = \&ReturnTapesBSD;
 	$main::Routines{Hardware}{StorageManager} = \&ReturnStorageManagerBSD;
 	$main::Routines{Hardware}{Eeprom} = \&ReturnEepromBSD;

 	$main::Routines{Network}{DomainName} = \&ReturnDomainNameBSD;
 	$main::Routines{Network}{DefaultRouter} = \&ReturnDefaultRouterBSD;
 	$main::Routines{Network}{NameServer} = \&ReturnNameServerBSD;
 	$main::Routines{Network}{IPAddress} = \&ReturnIPAddressBSD;
 	$main::Routines{Network}{SubnetMask} = \&ReturnSubnetMaskBSD;
 	$main::Routines{Network}{NetworkInterfaces} = \&ReturnNetworkInterfacesBSD;

 	$main::Routines{Software}{OsName} = \&ReturnOsNameBSD;
 	$main::Routines{Software}{OsVersion} = \&ReturnOsVersionBSD;
 	$main::Routines{Software}{NbrOfLicenses} = \&ReturnNbrOfLicensesBSD;
 	$main::Routines{Software}{Patches} = \&ReturnPatchesBSD;
 	$main::Routines{Software}{Printers} = \&ReturnPrintersBSD;
 	$main::Routines{Software}{Services} = \&ReturnServices;
 	$main::Routines{Software}{IPAddressResolution} = \&ReturnIPAddressResolutionBSD;
 	$main::Routines{Software}{GraphicalUserInterface} = \&ReturnGraphicalUserInterfaceBSD;
 	$main::Routines{Software}{FontServer} = \&ReturnFontServerBSD;
 	$main::Routines{Software}{Fstab} = \&ReturnFstab;
 	$main::Routines{Software}{LocalFileSystems} = \&ReturnLocalFileSystemsBSD;
 	$main::Routines{Software}{RemoteFileSystems} = \&ReturnRemoteFileSystemsBSD;
 	$main::Routines{Software}{ExportedFileSystems} = \&ReturnExportedFileSystemsBSD;
	$main::Routines{Software}{Swap} = \&ReturnSwapBSD;

	# if you have OS-specific services, add them here
	# push @@main::Services, "Local-Service";

	RemoveLocalExclusions();

	return;
}


###########################################################################
# Global
###########################################################################


sub WhatVersionOfBSD
{
	print "WhatVersionOfBSD()...\n" if $main::Debug;

	$OSVersion = `$UnameCommand -r`;
	chomp($OSVersion);

	( $OSVersionMajor, $OSVersionMinor ) = split(/\./, $OSVersion, 2);
	print "\tMajor OS version is $OSVersionMajor...\n" if $main::Debug;
	print "\tMinor OS version is $OSVersionMinor...\n" if $main::Debug;

	$SubroutineSuffix = $OSVersionMajor;

	return;
}


###########################################################################
# General
###########################################################################

sub ReturnVendorBSD ($)
{	my $Subcategory = shift;

 	my $Vendor = `$UnameCommand -v`;
 	chomp($Vendor);
	$Vendor = (split(' ', $Vendor))[0];

	return ( $Vendor );
}


sub ReturnModelBSD ($)
{	my $Subcategory = shift;

 	my $Model = `$UnameCommand -m`;
 	chomp($Model);

	return ( $Model );
}


sub ReturnHostIdBSD ($)
{	my $Subcategory = shift;

 	my $IdNbr = `$HostIdCommand`;
 	chomp($IdNbr);

	return ( $IdNbr );
}


###########################################################################
# Hardware
###########################################################################

# Expand this list.
%ProcessorTypes = ( 'i386' => 'Intel' );

sub ReturnProcessorsBSD ($)
{	my $Subcategory = shift;
	my @@Processors = ( );
	# XXX Could get this from dmesg.
	my $ProcessorSpeed = "speed unknown";

 	my $NumProcessors = SearchFileForPattern("$SysCtlCommand $SysCtlHardware", $SysCtlNCpuPattern, 2);
	my $ProcessorType = SearchFileForPattern("$SysCtlCommand $SysCtlHardware", $SysCtlMachinePattern, 2);
	my $ProcessorModel = SearchFileForPattern("$SysCtlCommand $SysCtlHardware", $SysCtlModelPattern, 2);

	$ProcessorType = $ProcessorTypes{$ProcessorType}
		if defined($ProcessorTypes{$ProcessorType});
	for $cnt (0 .. ($NumProcessors - 1)) {
		push @@Processors, "processor $cnt $ProcessorType $ProcessorModel $ProcessorSpeed";
	}

	my @@Response = ForceMultipleResponses(\@@Processors);

	return @@Response;
}


sub ReturnMemoryBSD ($)
{	my $Subcategory = shift;

# 	# how much memory?
 	my $Memory = SearchFileForPattern("$SysCtlCommand $SysCtlHardware", $SysCtlMaxMemPattern, 2);	# In bytes
 	$Memory = int ( $Memory / (1024 * 1024) );
 	$Memory = "$Memory" . "MB";

	return ( $Memory );
}


%DiskTypes = (
	'sd'	=> 'SCSI Disk',
	'sr'	=> 'Removable (probably CD-ROM)',
	'wd'	=> 'ST-506/IDE Disk',
);

sub ReturnDisksBSD ($)
{	my $Subcategory = shift;
	my @@Controllers = ( );
	my $ControllerNbr = -1;
	my $CurrentController = -1;
	my @@Response = ( );

	# XXX - This is a very rough first cut, use dmesg/disksetup for more info.
	my @@IOStatText = ReturnArrayExec($IOStatCommand);
	foreach $Device (split(/\s+/, $IOStatText[0])) {
		next unless $Device;
		next if $Device =~ /tty|%|cpu/;
		my $DiskType;
		($DiskType = $Device) =~ s/\d+$//;
		$DiskType = $DiskTypes{$DiskType}
			if defined($DiskTypes{$DiskType});
		push @@Response, "$Device type=$DiskType";
	}
	
	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnTapesBSD ($)
{	my $Subcategory = shift;
	my @@Controllers = ( );
	my $ControllerNbr = -1;
	my $CurrentController = -1;
	my @@Response = ( );

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnStorageManagerBSD ($)
{	my $Subcategory = shift;
	my @@Response = ();

	push @@Response, "Not Applicable (yet)";

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnEepromBSD ($)
{	my $Subcategory = shift;
	my $Eeprom = "";

	# XXX - this is a stub routine to be filled in later...

	return ( $Eeprom );
}


###########################################################################
# Network
###########################################################################

sub ReturnDomainNameBSD ($)
{	my $Subcategory = shift;

	return ReturnDomainName($Subcategory, $ResolvConfPath);
}


sub ReturnDefaultRouterBSD ($)
{	my $Subcategory = shift;

	my $DefaultRouter = SearchFileForTagValue($NetConfPath, $DefaultRouterTag, "File");
	if ($DefaultRouter eq $NotFound or $DefaultRouter eq "") {
		$DefaultRouter = "";
	}
	else {
		$DefaultRouter = IPtoFQDN($DefaultRouter);
	}

	return ( $DefaultRouter );
}


sub ReturnNameServerBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );

	my @@ResolvConfText = ReturnArrayFile($ResolvConfPath);
	if ( scalar(@@ResolvConfText) < 1 ) {
		push @@Response, "None";
	}
	else {
		foreach $Line (@@ResolvConfText) {
			# find the first line with "nameserver" in it?
			if ( $Line =~ /^nameserver\s+([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
				my $NameServerIP = $1;
				# do we recognize this nameserver?
				my $NameServerFQDN = IPtoFQDN($NameServerIP);
				push @@Response, $NameServerFQDN;
				next;
			}
		}
	}

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnIPAddressBSD ($)
{	my $Subcategory = shift;

 	# Returns the IP address associated with "$main::nodename"
 	# The "default" IP address. This subroutine will be used  
 	# if Bruce decides to implement this function in syssumm.pl 
 	my @@Addresses = (gethostbyname $main::NodeName)[4];         
 	my ($a, $b, $c, $d) = unpack('C4', $Addresses[0]);
 	$IPAddress = "$a." . "$b." . "$c." . "$d" ;

	return ( $IPAddress );
}


sub ReturnSubnetMaskBSD ($)
{	my $Subcategory = shift;

 	# Returns netmask associated with the "default" IP address
 	# This subroutine will be used if Bruce decides to implement
 	# this function in syssumm.pl
 	my $SubnetMask = "";       
 	my $IPAddress = ReturnIPAddressBSD($Subcategory);
 	my @@Interfaces = ReturnNetworkInterfacesBSD($Subcategory);
 
 	# find interface corresponding to "default" IP
 	# and get netmask from it
 	foreach $Line (@@Interfaces) {
 		next unless ( $Line =~ /$IPAddress/ ); 
 		if ( $Line =~ /netmask=(\S+)/ ) {      
 			$SubnetMask = $1;
 		}
 	}

	return ($SubnetMask);
}     


sub ReturnNetworkInterfacesBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );
	my %Seen = ( );			# keys are interface name, value is type

	print "ReturnNetworkInterfacesLinux()...\n" if $main::Debug;

	# search for interfaces in netstat output
	if ( -x $NetstatCommand ) {
		my @@NetstatOutput = ReturnArrayExec("$NetstatCommand $InterfaceArgs");
		foreach $Line ( @@NetstatOutput ) {
			next if ( $Line =~ /^(lo|ppp|sl|pif|sw)/ );	# skip loopback device
			next unless ( $Line =~ /^((\w+)\d)\*?\s/ );
			my $Iface = $1;                 # name of interface found
			my $IfaceDevice = $2;

			# don't add interface if it's already been
			# found somewhere else
			next if defined ( $Seen{$Iface} );

			$Seen{$Iface} = $IfaceDevice; 
		}
	}

	# search for interfaces in ifconfig output
	if ( -x $IfconfigCommand ) {
		my @@IfconfigOutput = ReturnArrayExec("$IfconfigCommand $IfconfigArgs");
		foreach $Line ( @@IfconfigOutput ) {
	
			next if ( $Line =~ /^(lo|ppp|sl|pif|sw)/ );	# skip loopback device

			next unless ( $Line =~ /^((\w+)\d):/ );

			my $Iface = $1;			# name of interface found
			my $IfaceDevice = $2;


			# don't add interface if it's already been
			# found somewhere else
			next if defined ( $Seen{$Iface} );
	
			$Seen{$Iface} = $IfaceDevice;
		}
	}

	# details on found interfaces
	foreach $Interface ( keys %Seen ) {
		my $Response = AddNetInfo($Interface, $Seen{$Interface});
		push @@Response, $Response if ( $Response);
	}

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub AddNetInfo ($$)
{	my $NetworkInterfaceName = shift;	# interface descriptor like 'eth0'
	my $NICDevice = shift;			# Specific device. Like: '3COM 3c905'

	print "AddNetInfo($NetworkInterfaceName, $NICDevice)...\n" if $main::Debug;

	# use ifconfig to get the rest of the information
	my @@IfconfigText = ReturnArrayExec("$IfconfigCommand $NetworkInterfaceName");

	my $MACAddress = "";
	my $IPAddress = "";
	my $BroadcastMask = "";
	my $NetMask = "";
	my $NICType = "unknown";

	# assume that there could be multiple fields on each line...
	foreach $Line (@@IfconfigText) {
		# pick up the hardware address
		if ( $Line =~ /link [^:]* (\w+:\w+:\w+:\w+:\w+:\w+)/ ) {
			$MACAddress = $1;
			$MACAddress =~ s/\b(\w)\b/0$1/g
		}
		# grab the IP address
		if ( $Line =~ /inet (\d+\.\d+\.\d+\.\d+)/ ) {
			$IPAddress = $1;
		}
		# grab the broadcast mask
		if ( $Line =~ /broadcast (\d+\.\d+\.\d+\.\d+)/ ) {
			$BroadcastMask = $1;
		}
		# grab the netmask
		if ( $Line =~ /netmask (\d+\.\d+\.\d+\.\d+)/ ) {
			$NetMask = $1;
		}
		# get device type
		if ( $Line =~ /link type (\S+) / ) {
			$NICType = $1;   
		}
		# defaults to "unknown" - see above
	}

	my $NICDescription = 
		"$NetworkInterfaceName type=$NICType device=$NICDevice macaddr=$MACAddress " .
		"ip=$IPAddress netmask=$NetMask broadcast=$BroadcastMask ";

	return $NICDescription;
}


###########################################################################
# Software
###########################################################################

sub ReturnOsNameBSD ($)
{	my $Subcategory = shift;

 	my $OsName = `$UnameCommand -s`;
 	chomp($OsName);

	return ( $OsName );
}


sub ReturnOsVersionBSD ($)
{	my $Subcategory = shift;

	return ( "$OSVersion" );
}


sub ReturnNbrOfLicensesBSD ($)
{	my $Subcategory = shift;

 	my $NbrOfLicenses = 0;

	if (-x $SysCtlCommand) {
		$NbrOfLicenses = `$SysCtlCommand $SysCtlLicenseUsers`;
		chomp($NbrOfLicenses);
	}
	$NbrOfLicenses = "unlimited" unless $NbrOfLicenses;

	return ( $NbrOfLicenses );
}


sub ReturnPatchesBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );

	# This is probably very BSD/OS specific.
	my $Version;
	my %PatchList = ( );

	($Version = $OSVersion) =~ tr/.//d;
	my @@PatchListText = ReturnArrayFile($PatchLogPath);
	push @@PatchListText, ReturnArrayFile($PatchSysLogPath);

	foreach $Line (@@PatchListText) {
		next unless $Line =~ /^patch (M$Version-\d+)\.(\S+) /;
		$PatchList{$1}->{$2}++;
	}
 
	my $PatchVersion;
	foreach $PatchVersion (sort keys %PatchList) {
		my $PatchDescription = join(',', sort keys %{$PatchList{$PatchVersion}});
		push @@Response, "$PatchVersion desc=\"$PatchDescription\"";
	}

 	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnRunningLpschedBSD ($)
{	my $Subcategory = shift;
	my @@Responses = ( );

	# XXX comment out as necessary
	my $Response = ReturnRunningSysvLp($Subcategory, $PsCommand, $PsArgs);
	push @@Responses, $Response if $Response =~ /Yes/;
	$Response = ReturnRunningBSDLpr($Subcategory, $PsCommand, $PsArgs);
	push @@Responses, $Response if $Response =~ /Yes/;
	$Response = ReturnRunningLPRng($Subcategory);
	push @@Responses, $Response if $Response =~ /Yes/;

	# concatenate the final responses as necessary
	my $FinalResponse = "";
	foreach $Response (@@Responses) {
		if ( $FinalResponse eq "" ) {
			$FinalResponse = $Response;
		}
		else {
			$FinalResponse = "$FinalResponse, $Response";
		}
	}

	return ($FinalResponse);
}


sub ReturnPrintersBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );

	# 
	# This function assumes a fairly "standard" format
	# for the printcap file like:
	#	# a comment
	#	lp|dj:\
	#		:sd=/var/spool/lpd/dj:\
	#		:mx#0:\
	#		:lp=/dev/lp0:\
	#		:sh:
	# 
	# One field per line.
	# 

	my @@Printcap = ReturnArrayFile("$PrintcapPath");
	my $Name = "";
	my $System = "";
	my $Queue = "";
	foreach $Line (@@Printcap) {
		next if $Line =~ /^#/;		# bypass comments

		# clean up the line
		chomp($Line);
		$Line =~ s/^[\s]+//;		# no leading spaces
		$Line =~ s/\\$//;		# trailing backslash

		next if ( $Line eq "" );	# bypass blank lines

		print "$Line\n" if $Debug;

		# printer line
		if ( $Line =~ /^\w+/ ) {
			# if anything left from previous printer
			# push it onto @@Response
			if ( $Name ) {
				my $Location = FormatPrinterLocation($System, $Queue);
				my $PrinterLine = "$Name prints to $Location";
				push @@Response, $PrinterLine;
				$Name = "";
				$System = "";
				$Queue = "";
			}

			# extract the name(s) of the printer(s)
			$Line =~ /^(.*):/;
			$Name = $1;
			$Name =~ s/\|/,/g;

			next;
		}

		# bypass fields we know we don't care about
		next if ( $Line =~ /^:[a-z][a-z]#/ );
		next if ( $Line =~ /^:[a-z][a-z]:/ );

		# fields
		if ( $Line =~ /^:/ ) {
			# extract the field label
			$Line =~ /^:([a-z][a-z])=(.*):/;
			my $Label = $1;
			if ( $Label eq "lp" ) {		# local printer
				$Queue = "local";
			}
			elsif ( $Label eq "rm" ) {	# remote server
				$System = $2;
			}
			elsif ( $Label eq "rp" ) {	# remote printer
				$Queue = $2;
			}

			next;
		}

		# ignore anything else...
	}
	if ( $Name ) {
		my $Location = FormatPrinterLocation($System, $Queue);
		my $PrinterLine = "$Name prints to $Location";
		push @@Response, $PrinterLine;
	}
	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub FormatPrinterLocation ($$)
{	my $System = shift;
	my $Queue = shift;

	if ( $System ) {			# remote print queue
		return "queue $Queue on $System";
	}
	else {					# local print queue
		return "$Queue queue";
	}
}


# 
# Note that this subroutine has a side-effect of setting
# a global variable in main:: called EmailAvailable if
# sendmail is running...
# 

sub ReturnRunningSendmailBSD ($)
{	my $Subcategory = shift;

	my $Sendmail = ( ( -f "$SendmailCommand" ) ? "Yes" : "No" );

	# side-effect
	$main::EmailAvailable = ( $Sendmail eq "Yes" );

	return ( $Sendmail );
}


sub ReturnRunningNFSBSD ($)
{	my $Subcategory = shift;

	my $NFSState = "";
	my $NFSServer = "";
	if ( -f $NfsdCommand and -f $ExportsPath ) {
		my @@Exports = ReturnArrayFile("$ExportsPath");
		$NFSServer = grep(m:^/:, @@Exports);
		# 
		# We can get here if nothing is exported
		# from this machine...  let's see if 
		# the server is running...
		# 
		if ( $NFSServer eq "" ) {
			print "\tNothing exported...\n" if $main::Debug;
			my @@PsText = ReturnArrayExec("$PsCommand $PsArgs");
			print "\tSearching ps output for $NfsdCommandPattern...\n" if $main::Debug;
			foreach $Line (@@PsText) {
				print "\t\t$Line\n" if $main::Debug;
				if ( $Line =~ /$NfsdCommandPattern/ ) {
					$NFSServer = "Yes";
					last;
				}
			}
		}
	}
	print "\tNFSServer is $NFSServer\n" if $main::Debug;
	my $NFSClient = ( -f $MountdCommand );
	print "\tNFSClient is $NFSClient\n" if $main::Debug;
	if ( $NFSServer and $NFSClient) {
		$NFSState = "Yes, both server and client";
	}
	elsif ( $NFSServer ) {
		$NFSState = "Yes, server only";
	}
	elsif ( $NFSClient ) {
		$NFSState = "Yes, client only";
	}
	else {
		$NFSState = "No";
	}

	return ( $NFSState );
}


sub ReturnRunningAutomountBSD ($)
{	my $Subcategory = shift;

	my $Automount = ( ( -f "$AmdCommand" ) ? "Yes" : "No" );

	return ( $Automount );
}


sub ReturnRunningNISBSD ($)
{	my $Subcategory = shift;

	# XXX Lets defer this for now

	return ( "No" );
}


sub ReturnRunningNameserverBSD ($)
{	my $Subcategory = shift;
	my $NameserverString = "No";
	my @@NameserverConfArray = ();
	my $Line = "";
	my $Zone = "";
	my $Type = "";
	my %ZoneHash;

	my @@RunningProcs = ReturnArrayExec("$PsCommand $PsArgs");
	if (grep {m,$NameServerPattern,} @@RunningProcs) {

		print("Found nameserver\n") if $main::Debug;

		$NameserverString = "Yes";
		# Now try to get some more info from nameserver conf file
		if ( -r "$NameserverConfPath" ) {

			print("Found $NameserverConfPath\n") if $main::Debug;

			@@NameserverConfArray = ReturnArrayFile($NameserverConfPath);
			foreach $Line ( @@NameserverConfArray ) {

				# named.conf stores relevent data like this
				#
				# //
				# // a caching only nameserver config
				# //
				# zone "." {
				#         type hint;
				#         file "named.ca";
				# };
				#

				next if $Line =~ /^\/\//;  # skip comment Lines

				# Look for zone and type info
				if ( $Line =~ /zone\s+\"(.+)\"/ ) {
					$Zone = $1;
				} elsif ( $Line =~ /type\s+(\w+)/ ) {
					$Type = $1;
				}

				# skip reverse lookup and first undefined entry
				if ( ($Zone =~ /in-addr\.arpa/)  || ($Zone eq "") ) {
					next;
				}

				# if zone is ., it's going to be a caching server?
				if ( $Zone eq "." ) {
					$Zone = "n/a";
				}

				# if type is hint, it's a caching server only
				if ( $Type eq "hint" ) {
					$Type = "Caching";
				}

				$ZoneHash{"$Zone"} = $Type;

			}

			# Append hash data to return string
			foreach $key ( keys %ZoneHash ) {
				$NameserverString .= ", Domain=$key, Type=$ZoneHash{$key}";
			}

		}
	}

	return ( $NameserverString );
}


sub ReturnIPAddressResolutionBSD ($)
{	my $Subcategory = shift;

 	my $IPAddressResolution = "/etc/hosts";
 	if ( -f $ResolvConfPath ) {
 		$IPAddressResolution = "DNS";
 	}

	return ( $IPAddressResolution );
}


sub ReturnRunningSambaBSD ($)
{	my $Subcategory = shift;

	return ReturnRunningSamba($Subcategory, $PsCommand, $PsArgs, $InetdConfPath);
}


sub ReturnGraphicalUserInterfaceBSD ($)
{	my $Subcategory = shift;

	# XXX Lets defer this for now

	return ( "X11R6" );
}


sub ReturnFontServerBSD ($)
{	my $Subcategory = shift;

	# XXX Lets defer this for now

	return ( "No" );
}


sub ReturnLocalFileSystemsBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );

 	my @@DfText = ReturnArrayExec("$DfCommand $LocalFileSystems");
 
 	my $PreviousLine = "";
 	$Suffix = 0;
 	foreach $Line (@@DfText) {
 
 		# bypass the header line
 		next if $Line =~ /^Filesystem/;
 		# bypass any cdrom drives or remote file systems
 		next if $Line =~ /cdrom/;
 		next if $Line =~ /^[\w]/;
 
 		# partial line?
 		if ( $PreviousLine ) {
 			$Line = $PreviousLine . $Line;
 			$PreviousLine = "";
 		}
 
 		# clean and split line
 		$Line =~ s/[\s]+/ /g;
 		my @@DfFields = split(/ /, $Line);
 
 		# partial line?
 		if ( scalar(@@DfFields) < 2 ) {
 			$PreviousLine = $Line;
 			# go get the rest of it
 			next;
 		}
 
 		# calc size in MB
 		my $Size = sprintf("%.1fMB", ( $DfFields[1] / 1024 ) );
 
 		push @@Response, "$DfFields[5] mount=$DfFields[0] size=$Size sat=$DfFields[4]";
 	}

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnRemoteFileSystemsBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );

 	my @@DfText = ReturnArrayExec("$DfCommand $NFSFileSystems");
 
 	my $PreviousLine = "";
 	$Suffix = 0;
 	foreach $Line (@@DfText) {
 
 		# bypass the header line
 		next if $Line =~ /^Filesystem/;
 		# bypass any cdrom drives or local file systems
 		next if $Line =~ /cdrom/;
 		next if $Line =~ /^\//;
 
 		# partial line?
 		if ( $PreviousLine ) {
 			$Line = $PreviousLine . $Line;
 			$PreviousLine = "";
 		}
 
 		# clean and split line
 		$Line =~ s/[\s]+/ /g;
 		my @@DfFields = split(/ /, $Line);
 
 		# partial line?
 		if ( scalar(@@DfFields) < 2 ) {
 			$PreviousLine = $Line;
 			# go get the rest of it
 			next;
 		}
 
 		# calc size in MB
 		my $Size = sprintf("%.1f", ( $DfFields[1] / 1024 ) );
 
 		my ( $RemoteSystem, $RemoteFileSystem ) = split(':', $DfFields[0]);
 		push @@Response, "$DfFields[5] remote=$RemoteSystem mount=$RemoteFileSystem size=$Size sat=$DfFields[4]";
 	}

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnExportedFileSystemsBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );

	@@Exportslist = ReturnArrayFile("$ExportsPath");
	foreach $Line (@@Exportslist) {
		next if ($Line =~ /^\s*$/);
		next if ($Line =~ /^#/);
		push @@Response, "$Line";
	}

	if ( scalar(@@Response) < 1 ) {
		push @@Response, "No exports - not an NFS Server";
	}

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


sub ReturnSwapBSD ($)
{	my $Subcategory = shift;
	my $Blocks = "Unknown";

	my @@SwapText = ReturnArrayExec("$SwapCommand $SwapArgs");

	foreach $Line (@@SwapText) {
		$Blocks = $1 if $Line =~ /allocated out of (\d+) /;
	}
	$Blocks = ((int ( $Blocks / 1024 )) . "MB") if $Blocks > 0;

	return $Blocks;
}


sub ReturnRunningAccountingBSD ($)
{	my $Subcategory = shift;

	# XXX Lets defer this for now

	return ( "Unknown" );
}


###########################################################################
# End of BSD.pm
###########################################################################

1;

@


1.7
log
@changes from Frank Crawford including:
a fix for BSD.pm, to cater for the fact that "/etc/netstart"
is a shell script, and hence an executable, but also contains
the necessary data as shell variables; also had to fix the
test for a router, if it came back with no match, and exclude
the "sw" network interfaces (they are for swIPE, i.e. some form
of IPSec pseudo-device)
@
text
@d33 1
a33 1
# $Header: /export/home/mohlerb/syssumm/remote/RCS/BSD.pm,v 1.6 2000/04/04 02:36:00 mohlerb Exp mohlerb $
d35 1
a35 1
# $Revision: 1.6 $
d38 9
d334 1
a334 1
	my @@IOStatText = ReturnArray($IOStatCommand);
d416 1
a416 1
	my @@ResolvConfText = ReturnArray($ResolvConfPath);
d485 1
a485 1
		my @@NetstatOutput = ReturnArray("$NetstatCommand $InterfaceArgs");
d502 1
a502 1
		my @@IfconfigOutput = ReturnArray("$IfconfigCommand $IfconfigArgs");
d540 1
a540 1
	my @@IfconfigText = ReturnArray("$IfconfigCommand $NetworkInterfaceName");
d627 2
a628 2
	my @@PatchListText = ReturnArray($PatchLogPath);
	push @@PatchListText, ReturnArray($PatchSysLogPath);
d691 1
a691 1
	my @@Printcap = ReturnArray("$PrintcapPath");
d800 1
a800 1
		my @@Exports = ReturnArray("$ExportsPath");
d809 1
a809 1
			my @@PsText = ReturnArray("$PsCommand $PsArgs");
d867 1
a867 1
	my @@RunningProcs = ReturnArray("$PsCommand $PsArgs");
d878 1
a878 1
			@@NameserverConfArray = ReturnArray($NameserverConfPath);
d973 1
a973 1
 	my @@DfText = ReturnArray("$DfCommand $LocalFileSystems");
d1018 1
a1018 1
 	my @@DfText = ReturnArray("$DfCommand $NFSFileSystems");
d1064 1
a1064 1
	@@Exportslist = ReturnArray("$ExportsPath");
d1085 1
a1085 1
	my @@SwapText = ReturnArray("$SwapCommand $SwapArgs");
@


1.6
log
@changes from Frank Crawford including:
fix typo in ReturnSwapBSD function
@
text
@d33 1
a33 1
# $Header: /export/home/mohlerb/src/perl/syssumm/remote/RCS/BSD.pm,v 1.5 2000/03/02 22:03:03 mohlerb Exp mohlerb $
d35 1
a35 1
# $Revision: 1.5 $
d38 4
d391 7
a397 2
 	my $DefaultRouter = SearchFileForTagValue($NetConfPath, $DefaultRouterTag);
	$DefaultRouter = IPtoFQDN($DefaultRouter);
d478 1
a478 1
			next if ( $Line =~ /^(lo|ppp|sl|pif)/ );        # skip loopback device
d496 1
a496 1
			next if ( $Line =~ /^(lo|ppp|sl|pif)/ );	# skip loopback device
@


1.5
log
@changes from Frank Crawford including:
deleting the use of syslog and getting the swap function to work
@
text
@d33 1
a33 1
# $Header: /export/home/mohlerb/src/perl/syssumm/remote/RCS/BSD.pm,v 1.4 2000/02/09 23:44:18 mohlerb Exp mohlerb $
d35 1
a35 1
# $Revision: 1.4 $
d38 4
d1074 1
a1074 1
	Return $Blocks;
@


1.4
log
@changes from Bruce Mohler including:
cleaned up ReturnServices by moving function to common.pm
and having it be driven by a @@Services array in syssumm.pl;
note also the option at the end of the Initialize<OS> function
where you can add OS-specific services that you wish to have
monitored
@
text
@d28 2
a29 1
#	Copyright (c) 1999, 2000 <author)
d33 1
a33 1
# $Header: /export/home/mohlerb/src/perl/syssumm/remote/RCS/BSD.pm,v 1.3 2000/02/04 00:14:32 mohlerb Exp mohlerb $
d35 1
a35 1
# $Revision: 1.3 $
d38 8
a96 1
$DmesgCommand = "/sbin/dmesg";
d102 1
d106 1
a106 1
$SwapCommand = "";
a120 1
$SyslogConfPath = "/etc/syslog.conf";
a121 1
$SyslogPath = "";
a156 3
	$SyslogPath = LocateTheSyslogPath($SyslogConfPath);
	print "\tSyslogPath is $SyslogPath\n" if $main::Debug;

d177 1
a177 1
 	$main::Routines{Network}{IpAddress} = \&ReturnIpAddressBSD;
d187 1
a187 1
 	$main::Routines{Software}{IpAddressResolution} = \&ReturnIpAddressResolutionBSD;
d417 1
a417 1
sub ReturnIpAddressBSD
d431 1
a431 1
sub ReturnSubnetMaskBSD
d438 1
a438 1
 	my $IpAddress = ReturnIpAddressBSD($Subcategory);
d444 1
a444 1
 		next unless ( $Line =~ /$IpAddress/ ); 
d461 8
a468 3
	# search for interfaces in the syslog log
	my @@SyslogText = ReturnArray("$SyslogPath");
	foreach $Line ( @@SyslogText ) {
d470 1
a470 9
		# we're looking for patterns like "de0: address 08:00:2b:e6:c6:b3"
		#de0 at pci0 iobase 0xf080 irq 11: DC21040 [10Mb/s] pass 2.4
		if ( $Line =~ /^((\w+)\d): address \w+:\w+:\w+:\w+:\w+:\w+/ ) {

			# map regexp variables to something more mnemonic
			my $Iface = $1;		# name of interface found
			my $IfaceDevice = $2;	# type of device like "3COM 3c905"

			# don't add interface to has if it's already been 
d474 1
a474 1
			$Seen{$Iface} = $IfaceDevice;
a477 22
	# search for interfaces in dmesg output
	if ( -x $DmesgCommand ) {
		my @@DmesgOutput = ReturnArray("$DmesgCommand");
		foreach $Line ( @@DmesgOutput ) {
	
			# we're looking for patterns like "de0: address 08:00:2b:e6:c6:b3"
			#de0 at pci0 iobase 0xf080 irq 11: DC21040 [10Mb/s] pass 2.4
			if ( $Line =~ /^((\w+)\d): address \w+:\w+:\w+:\w+:\w+:\w+/ ) {
	
				# map regexp variables to something more mnemonic
				my $Iface = $1;		# name of interface found
				my $IfaceDevice = $2;	# type of device like "3COM 3c905"
	
				# don't add interface to has if it's already been 
				# found somewhere else
				next if defined ( $Seen{$Iface} );
	
				$Seen{$Iface} = $IfaceDevice;
			}
		}
	}

d488 1
a488 3
			my $IfaceDevice = $2;		# This info not in 
							# ifconfig value is 
							# passed to AddNetInfo()
d491 1
a491 1
			# don't add interface to has if it's already been 
d772 1
a772 1
sub ReturnRunningNfsBSD ($)
d910 1
a910 1
sub ReturnIpAddressResolutionBSD ($)
d1061 1
d1063 1
a1063 5
	#
	# XXX - This is a dummy routine
	# 
	# The value of $SwapCommand needs to be initialized above.
	# 
d1065 6
a1070 1
	ReturnSwap($Subcategory, "$SwapCommand");
@


1.3
log
@changes from Bruce Mohler including:
implemented ReturnServices to return all of the Running*
functions as a multiple value field
@
text
@d32 1
a32 1
# $Header: /export/home/mohlerb/src/perl/syssumm/remote/RCS/BSD.pm,v 1.2 2000/02/03 23:22:02 mohlerb Exp mohlerb $
d34 1
a34 1
# $Revision: 1.2 $
d37 5
d182 1
a182 1
 	$main::Routines{Software}{Services} = \&ReturnServicesBSD;
d192 3
a776 28
sub ReturnServicesBSD ($)
{	my $Subcategory = shift;
	my @@Response = ( );
	my $Response = "";

 	$Response = ReturnRunningLpschedBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningSendmailBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningNfsBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningAutomountBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningNisBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningNameserverBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningSambaBSD($Subcategory);
	push @@Response, $Response;
 	$Response = ReturnRunningAccountingBSD($Subcategory);
	push @@Response, $Response;

	@@Response = ForceMultipleResponses(\@@Response);

	return @@Response;
}


d850 1
a850 1
sub ReturnRunningNisBSD ($)
d1100 1
a1100 1
	return ( "No" );
@


1.2
log
@changes from Martin Andrews including:
IRIX, Linux, and SunOS now report swap file sizes, stubs added
to other OS modules
@
text
@d32 1
a32 1
# $Header: /export/home/mohlerb/src/perl/syssumm/remote/RCS/BSD.pm,v 1.1 2000/01/12 18:08:20 mohlerb Exp mohlerb $
d34 1
a34 1
# $Revision: 1.1 $
d37 5
a175 1
 	$main::Routines{Software}{RunningLpsched} = \&ReturnRunningLpschedBSD;
d177 1
a177 5
 	$main::Routines{Software}{RunningSendmail} = \&ReturnRunningSendmailBSD;
 	$main::Routines{Software}{RunningNfs} = \&ReturnRunningNfsBSD;
 	$main::Routines{Software}{RunningAutomount} = \&ReturnRunningAutomountBSD;
 	$main::Routines{Software}{RunningNis} = \&ReturnRunningNisBSD;
 	$main::Routines{Software}{RunningNameserver} = \&ReturnRunningNameserverBSD;
a178 1
 	$main::Routines{Software}{RunningSamba} = \&ReturnRunningSambaBSD;
a185 1
 	$main::Routines{Software}{RunningAccounting} = \&ReturnRunningAccountingBSD;
d768 28
@


1.1
log
@Initial revision
@
text
@d32 1
a32 1
# $Header$
d34 1
a34 1
# $Revision$
d36 4
a39 1
# $Log$
d87 1
d186 1
d341 2
d1075 13
@
