###
### Copyright 2000-2007 University of Illinois Board of Trustees
### All rights reserved.
###
### PSGConf::Util - utility functions for psgconf
###
### Campus Information Technologies and Educational Services
### University of Illinois at Urbana-Champaign
###
package PSGConf::Util;
use strict;
use File::Find;
use Net::hostent;
use POSIX;
use Socket;
our @ISA = qw(Exporter);
our @EXPORT = qw(
get_addrs
platform_name
);
###############################################################################
### _expand_tokens - Generic method to expand tokens of the form
### %{directive} to their value, only really works
### with String/Integer data types.
###############################################################################
sub _expand_tokens
{
my ($psgconf, $text) = @_;
my ($start_idx, $newtext, $end_idx, $token, $val);
$start_idx = 0;
$newtext = $text;
while ($start_idx != -1)
{
$start_idx = index($text, "%{", $start_idx);
next
if ($start_idx == -1);
$end_idx = index($text, "}", $start_idx);
$token = substr($text, $start_idx + 2,
$end_idx - $start_idx - 2);
$val = $psgconf->data_obj($token)->get();
$token = "%{" . $token . "}";
$newtext =~ s/$token/$val/g;
$start_idx = $end_idx;
}
return $newtext;
}
###############################################################################
### get_addrs(FQDN) - get all IP addresses associated with FQDN
###############################################################################
sub get_addrs
{
my ($psgconf, $fqdn) = @_;
my ($hent, @res);
### First see if we have the IP address from our configs
if ( defined $psgconf->data_obj('host_addrs')->find($fqdn) ) {
@res = $psgconf->data_obj('host_addrs')->find($fqdn);
} else {
### Now check to make sure we do not have a host_alias set either
map {
if ( defined $psgconf->data_obj('host_aliases')->find($_)->{$fqdn} ) {
if ( defined $psgconf->data_obj('host_addrs')->find($_) ) {
@res = $psgconf->data_obj('host_addrs')->find($_);
### Save new name to look up in DNS
} else {
$fqdn = $_;
}
}
} keys %{$psgconf->data_obj('host_aliases')->get()};
if ( ! scalar @res ) {
if ($hent = gethostbyname($fqdn)) {
@res = sort map { inet_ntoa($_) } @{$hent->addr_list};
}
}
}
die "unknown host \"$fqdn\""
if (! scalar @res);
return @res;
}
###############################################################################
### RunCommand(command) - Run a command using system(3).
###############################################################################
sub RunCommand
{
my ($cmd, $nowarn) = @_;
my ($rc);
if (($rc=system($cmd))) {
### OK, so the program was killed by a signal.
if ( WIFSIGNALED($?) ) {
warn "\t!!! command '$cmd' terminated on signal "
. WTERMSIG($?)
. ($? & 128)? ", with": ", without"
. " coredump\n"
if ( ! $nowarn );
$rc= WTERMSIG($?);
### Otherwise we had some other error...
} elsif ( $rc || WIFEXITED($?) ) {
warn "\t!!! command '$cmd' failed: $!\n"
if ( ! $nowarn );
$rc = WEXITSTATUS($?);
}
}
return $rc;
}
###############################################################################
### platform_name() - return platform name for current host
###############################################################################
sub platform_name
{
my ($sysname, $nodename, $release, $version, $machine);
my ($platform, @suffixes);
($sysname, $nodename, $release, $version, $machine) = POSIX::uname();
if ($sysname eq 'AIX')
{
my $os_level;
$os_level = `oslevel`;
chomp($os_level);
$os_level =~ s/^(\d+\.\d+\.\d+)\.\d+$/$1/;
$platform = "rs6000-aix$os_level";
}
elsif ($sysname eq 'HP-UX')
{
### assume pa, since we can't get at _SC_CPU_VERSION
$release =~ s/^[^\d]+//;
$platform = "pa-hpux$release";
}
elsif ($sysname =~ m/^IRIX.*/)
{
### assume mips, since we don't have an interface to sysinfo()
$platform = "mips-irix$release";
}
elsif ($sysname eq 'Linux')
{
### only save the first two digits of the kernel version
$release =~ s/^(\d+\.\d+)\..*$/$1/;
$platform = (($machine =~ m/^i\d86$/) ? 'ix86' : $machine);
### set the other arches we can support (i686 will support
### i386 to i686 as well athlon).
if ( $platform eq 'ix86' ) {
my ($x);
grep (/i([3-9])86/o && ($x=$1), $machine);
for (my($i) = 3; $i <= $x; $i++) {
push @suffixes, "i${i}86";
}
### FIXME. Need to add the athlon arch tag
### for those systems (output of uname -p).
} elsif ( $platform eq 'x86_64' ) {
push @suffixes, ( 'x86_64', 'i386' );
} else {
push @suffixes, $platform;
}
$platform .= "-linux$release";
if ( -f '/etc/redhat-release' ) {
my ($distro, $x);
if (open (FP, '/etc/redhat-release')) {
$distro=<FP>;
close FP;
chomp $distro;
if ( $distro =~ /Fedora Core/o ) {
$x="fc-";
} elsif ( $distro =~ /Red Hat Enterprise Linux ([^ ]*)/o ) {
$x="rhel-$1-";
} elsif ( $distro =~ /Red Hat Linux/o ) {
$x="rhl-";
}
if ( length $x ) {
$x .= $1
if ( $distro =~ / release ([0-9\.]+)/o );
$x .= '.' . $1
if ( $distro =~ / Update ([0-9]+)/o );
$platform .= "-$x";
}
}
}
}
elsif ($sysname eq 'FreeBSD')
{
### only save the major number of the kernel version
$release =~ s/^(\d+)\..*$/$1/;
$platform = (($machine =~ m/^i\d86$/) ? 'ix86' : $machine);
$platform .= "-freebsd$release";
}
elsif ($sysname eq 'SunOS')
{
my $bits;
$platform = (($machine eq 'i86pc') ? 'ix86' : $machine);
my ($maj, $min) = split (/\./, $release);
$platform .= '-' . (($maj >= 5) ? 'solaris' : 'sunos' . $maj . '.');
$platform .= '2.'
if ($min <= 6);
$platform .= $min;
### set 32-bit vs 64-bit suffix
$bits = `isainfo -b`;
chomp($bits);
@suffixes = ("${bits}bit");
}
elsif ($sysname eq 'Darwin')
{
$platform = (($machine eq 'Power Macintosh') ? 'powerpc' : $machine);
$platform .= "-darwin$release";
}
return ($platform, @suffixes);
}
###############################################################################
### documentation
###############################################################################
1;
__END__
=head1 NAME
PSGConf::Util - Extra Utility functions for PSGConf Modules.
=head1 SYNOPSIS
use PSGConf::Util;
=head1 DESCRIPTION
The B<PSGConf::Util> module defines the following useful methods:
=over 4
=item get_addrs($psgconf, $fqdn)
This will return a B<PSGConf::Data::List> of IP Addresses for the
host $fqdn.
=item platform_name()
Returns the architechture name of the system psgconf is running on.
=item RunCommand($cmd, $nowarn)
Creates a consistant look and feel for running external commands
within L<PSGConf>. If $nowarn is set, it will not print out any
error messages on failures. Returns the status code of the command
run.
=back
It also defines the following internal methods:
=over 4
=item _expand_tokens($psgconf, $text)
Converts any form of %{directive} within the $text string to the
value that is return from $psgconf->data_obj('directive')->get().
Mainly works well with B<PSGConf::Data::Boolean>, B<PSGConf::Data::Enum>
B<PSGConf::Data::Integer> and B<PSGConf::Data::String> directives.
=back
=head1 SEE ALSO
L<perl>
L<PSGConf>
=cut
syntax highlighted by Code2HTML, v. 0.9.1