Subversion Repositories camp_sysinfo_client (old)

Rev

Blame | Last modification | View Log | RSS feed

#! /usr/bin/perl -w

# sysinfo.pl
# Author: R. W. Rodolico
# Operating System: Win32
# Primary client portion of sysinfo system. Will collect information about its current
# host and create a report containing the information. This report can then be processed
# by process_sysinfo.pl on the collection computer.
# output file consists of a key/value pair, with the key in square brackets, example:
#  [tag]value
# where tag is the name of the function we are looking at (hostname, report date, cpu type)
# and value is the associated value.
# Also has multi line key/values, which are in the form
#   [tag]
#   value1
#   value2
#   [another tag (or end of file)]
# where value1 and value2 are considered attributes of tag. This is used where there are multiple
# values for a function, such as for installed packages, IP Addresses, hardware lists, and
# disk partitions.

#use strict;
#use warnings;
#no warnings qw(uninitialized);
use Win32::SystemInfo;
use Win32::DriveInfo;
#Optional:  Change the delimiter to '/' to eliminate all of the extra backslashes
use Win32::TieRegistry (Delimiter =>  "/");
use Mail::Sendmail;

# Following are global variables overridden if configuration file exists
my $APPLICATION_ROOT;
my $client_name;
my $CUSTOM_PACKAGE_FINDER ;
my @directoriesToWatch;
# only required if reports are sent from process_sysinfo.pl. Not the norm.
my $iMailResults = 1; # if 0 (false), ignore following variables
my $mailTo;
my $mailCC;
my $mailBCC;
my $mailServer;
my $mailServerPort;
my $mailFrom;
my $mailSubject;

my $VERSION = '1.3.3 win32';

sub getSystemTime {
   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
                                                localtime(time);
   return sprintf('%4d%02d%02d%02d%02d%02d',$year+1900,$mon+1,$mday,$hour,$min,$sec);
}

sub loadConfigurationFile {
   my $configuration_file = shift;
   unless ( $configuration_file ) { # They didn't give us a configuration filename
      # figure out the configuration filename as the base file name, with .conf on the end
      use File::Basename;
      use Cwd qw(realpath);
      my $path = realpath($0); # get my real path
      my($filename, $directories, $suffix) = fileparse($path,('.pl')); # break filename apart
      $configuration_file = $directories . $filename . '.conf'; # add the .conf
   }
   open CONFFILE, "<$configuration_file" or die "Can not open configuration file $configuration_file";
   my $confFileContents = join( '', <CONFFILE> );
   close CONFFILE;
   return $confFileContents;
}

sub cleanUpString {
   my $value = shift;
   if ($value) {
      $value =~ s/[^[:print:]]+//g;
   } else {
      $value = '';
   }
   return $value;
}

sub buildNetworkLine {
   my ($connection,$ip,$subnet,$gateway,$domain) = @_;
   $connection = &cleanUpString($connection);
   $ip = &cleanUpString($ip);
   $subnet = &cleanUpString($subnet);
   $gateway = &cleanUpString($gateway);
   $domain = &cleanUpString($domain);
   my $line = "$connection\t$ip\t$subnet\t$gateway\t$domain";
   return $line;
}
sub getNetworkInformation {
   my $ipInfo =  `ipconfig`;
   #print $ipInfo;
   my @ipInfo = split( "\n",$ipInfo );
   chomp @ipInfo;
   my @info = ();
   my $connection = '';
   my $ip = '';
   my $domain = '';
   my $subnet_mask = '';
   my $gateway = '';
   while (my $line = shift @ipInfo) {
      if ( $line =~ m/ethernet adapter.*connection +(\d+)/i ) {
         if ($connection) {
            push @info,&buildNetworkLine($connection,$ip,$subnet_mask,$gateway,$domain);
         }
         $connection = $1;
         $ip = '';
         $domain = '';
         $subnet_mask = '';
         $gateway = '';
      } elsif ( $line =~ m/dns suffix.+\: *(.*)/i ) {
         $domain = $1;
      } elsif ( $line =~ m/ip address.+\: *(.*)/i ) {
         $ip = $1;
      } elsif ( $line =~ m/subnet mask.+\: *(.*)/i ) {
         $subnet_mask = $1;
      } elsif ( $line =~ m/default gateway.+\: *(.*)/i ) {
         $gateway = $1;
      }
   }
   push @info,&buildNetworkLine($connection,$ip,$subnet_mask,$gateway,$domain);
   return "[Network Information]\n" . join( "\n",@info ) . "\n";
}


sub getUptime {
   my $string = `net statistics server`;
#   my @string = split("\n",$string);
   my $hostName;
   my $lastReboot;
#   while ($string = shift @string) {
      if ($string =~ m/Server Statistics for \\\\(.*)/) {
         $hostName = $1;
      }
      if ($string =~ m/Statistics since(.*)/) {
         $lastReboot = $1;
      }
#   }
   return ($hostName,$lastReboot);
}

sub getSystemInformation {
   my @returnValue;
   # get memory info
   my %hash = (TotalPhys => 0);
   use warnings;
   no warnings qw(all);
   if (Win32::SystemInfo::MemoryStatus(%hash) ) {
      push @returnValue,'[memory]' . $hash{'TotalPhys'};
   }
   my %phash;
   Win32::SystemInfo::ProcessorInfo(%phash);
#   for (my $i = 0; $i < $phash{NumProcessors}; $i++) {
#   print "Speed of processor $i: " . $phash{"Processor$i"}{MHZ} . "MHz";
#   }
   push @returnValue,'[num_cpu]   ' . $phash{'NumProcessors'};
   push @returnValue,'[cpu_speed]' . $phash{"Processor0"}{'MHZ'};
   push @returnValue,'[cpu_type]' . $phash{"Processor0"}{'ProcessorName'} . '-' . $phash{"Processor0"}{'VendorIdentifier'};
   push @returnValue,'[cpu_sub]' . $phash{"Processor0"}{'Identifier'};
     #      for (my $i = 0; $i < $hash{NumProcessors}; $i++) {
      #         $outputData{"Processor $i"}{'Identifier'} = $hash{"Processor$i"}{'Identifier'};
      #         $outputData{"Processor $i"}{'Speed'} = $hash{"Processor$i"}{'MHZ'};
      #         $outputData{"Processor $i"}{'Vendor ID'} = $hash{"Processor$i"}{'VendorIdentifier'};
      #         $outputData{"Processor $i"}{'Name'} = $hash{"Processor$i"}{'ProcessorName'};
      #      }
#   } # if
   use warnings qw(all);
   #@returnValue .= '[kernel]' . qx(uname -r);
   my ($hostname,$lastReboot) = &getUptime;
   push @returnValue,"[hostname]$hostname";

   push @returnValue,"[boot]$lastReboot";
   return join( "\n",@returnValue) . "\n";
}


sub getDistributionInformation {
   my ($MajorVersion, $MinorVersion, $BuildNumber, $PlatformId, $BuildStr) = Win32::DriveInfo::GetVersionEx ( );
   my $returnValue = '';
   $returnValue .= "[os_name]Windows\n";
   $returnValue .= '[os_version]' . $MajorVersion . '.' . $MinorVersion . "\n";
   $returnValue .= '[distro_description]' . $PlatformId . "\n";
   $returnValue .= '[distro_release]' . $BuildNumber . "\n";
   $returnValue .= '[distro_codename]' . $BuildStr . "\n";
   return $returnValue;
}

sub getDrives {
   my @info;
   my $STANDARD_DRIVE_TYPE = 3; # standard hard drive partition, see Win32::DriveInfo documentation for more info
   my @drives = Win32::DriveInfo::DrivesInUse ( );
   foreach my $drive ( @drives ) {
      if ( Win32::DriveInfo::DriveType ( $drive ) == $STANDARD_DRIVE_TYPE ) {
         my ($SectorsPerCluster,
              $BytesPerSector,
              $NumberOfFreeClusters,
              $TotalNumberOfClusters,
              $FreeBytesAvailableToCaller,
              $TotalNumberOfBytes,
              $TotalNumberOfFreeBytes) = Win32::DriveInfo::DriveSpace($drive);
         my ($VolumeName,
               $VolumeSerialNumber,
               $MaximumComponentLength,
               $FileSystemName,
               @attr) = Win32::DriveInfo::VolumeInfo ( $drive );
         # convert to kilobytes
         $TotalNumberOfBytes /= 1024;
         $TotalNumberOfFreeBytes /= 1024;
         $usedSpace = $TotalNumberOfBytes - $TotalNumberOfFreeBytes;
         push @info,"$drive\t$FileSystemName\t$TotalNumberOfBytes\t$usedSpace";
      }
   }
   return "[Disk Info]\n" . join("\n",@info) . "\n";
}

sub getPackagesInstalled {
   use strict;
   use warnings;
   no warnings qw(uninitialized);
   #%apps will have a list of applications
   my @apps;
   #$softKey points to the Uninstall key that has
   #the Add/Remove Programs information
   my $softKey = $Registry-> {"HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Uninstall"};
   #Sort and iterate through the keys under Uninstall
   foreach(keys %{$softKey}){
      #Append the key and DisplayName to the Uninstall key
      #Set the result as a key in the %apps hash
      #This also removes any duplicate entries
      my $name = $softKey-> {"$_/DisplayName"};
      next unless $name;
      my $version = $softKey->{"$_/DisplayVersion"};
      unless ( $version ) {
         if ( $softKey->{"$_/VersionMajor"} ) {
            $version = $softKey->{"$_/VersionMajor"} . '.' .  $softKey->{"$_/VersionMinor"};
         } elsif ( $softKey->{"$_/InstallDate"} ) {
            $version = $softKey->{"$_/InstallDate"};
         } else {
            $version = 'UNK';
         }
      }
      push @apps, "$name\t$version";
   }
   return "[Packages Installed]\n" . join ("\n", @apps) . "\n";
}

sub getHardware {
   my @hardwareList;
   my $Registry;
   use Win32::TieRegistry 0.20 (
        TiedRef => \$Registry,  Delimiter => "/",  ArrayValues => 0,
        SplitMultis => 1,  AllowLoad => 1,
        qw( REG_SZ REG_EXPAND_SZ REG_DWORD REG_BINARY REG_MULTI_SZ
            KEY_READ ),
    );
   my $machKey= $Registry->Open( "HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/PCI", {Access=>KEY_READ(),Delimiter=>"/"} )
      or  die "Can't open PCI key: $^E\n";
   foreach my $subkey ($machKey->SubKeyNames) {
      my $thisVendor = $machKey->Open($subkey);
      foreach my $device ($thisVendor->SubKeyNames) {
         my $thisDevice = $thisVendor->Open($device);
         push @hardwareList,$thisDevice->GetValue( "DeviceDesc" ) . "\t" . $thisDevice->GetValue( "LocationInformation" );
      }
   }
   return "[PCI Info]\n" . join("\n",@hardwareList) . "\n";
}

sub sendResults {
   $mail{'message'} = shift;
   if (sendmail %mail) {
      print "Mail sent OK.\n"
   } else {
     print "Error sending mail: $Mail::Sendmail::error \n"
   }
   print "\n\$Mail::Sendmail::log says:\n", $Mail::Sendmail::log;
}


my $result;
if (@ARGV) {
   $result = join("\n", @ARGV) . "\n\n";
}

eval( &loadConfigurationFile ); # load the configuration file
# parameters are assumed to override configuration file details. If we have parameters
# they are of the form varname=value, where value is the new value to assign to varname
# the command has a dollar sign prepended (for the variable) and a semi-colon appended
# to create a command that may be executed by eval. Thus, this must be a single line
# no embedded spaces parameter.
#while ($parameter = shift ) {
#   eval ( '$' . $parameter . ';');
#}



$result .= "[sysinfo version]$VERSION\n";
$result .= '[report date]' . &getSystemTime . "\n";
$result .= "[client name]$client_name\n";
$result .= &getDistributionInformation();
$result .= &getSystemInformation();
$result .= &getNetworkInformation();
$result .= &getDrives();
$result .= &getHardware();
$result .=  &getPackagesInstalled();
&sendResults($result);
exit 1;