package INSTALL::os; use INSTALL::common; ############################################################################### # Use %Details as a hash which maps attributes of an OS to its attribute name. ############################################################################### # %Details; BEGIN { %Details = ( # OS specific variables os => "Unknown", # These are the values that marketing people use for the OS. os_name => "Unknown", os_version => "Unknown", ostag => "Unknown", hardware => "Unknown", processor => "Unknown", processor_count => "Unknown", processor_speed => "Indeterminate", release => "Unknown", shlib_extensions => [ "Unknown" ], ## Note: The array reference shall refer to an array which is ordered ## such that the first entry is the 'prefered' shared library ## extension. default_shell => "Unknown", package_formats => "Unknown", libpath_variable => "Unknown", disabled_mountpoints => [ "Unknown" ], ## List of mount points which are known to be remote / read-only. # OS inspecific variables perl => "Unknown", perl_binary => "Unknown", perl_include => "Unknown", default_runlevel => "Unknown", # Only valid on Linux systems. distribution => "Unknown", distribution_flavor => "Unknown", distribution_version => "Unknown" ); @supported_OS = ( "Linux", "SunOS", "AIX", "HP-UX" ); } # set up the path before any other operation. &INSTALL::common::path_append("/usr/bin","/usr/sbin","/usr/local/bin"); ############################################################################### my (@supported_OS,%function_map); my $CONST_PreviouslySeen; sub detect_default_runlevel { open(INITTAB,") { if (/([0-9]):initdefault/) { $default_runlevel = $1; last; } } close(INITTAB); ($default_runlevel =~ /[0-9]+/) || die "Unable to determine default run-level."; return($default_runlevel); } sub detect_sunos { $Details{os} = "SunOS"; $Details{os_name} = "Solaris"; $Details{libpath_variable} = "LD_LIBRARY_PATH"; $Details{shlib_extensions} = ["so"]; $Details{package_formats} = ["PKG_DIR","TAR"]; if ( -x "/bin/ksh" ) { $Details{default_shell} = "/bin/ksh"; } else { $Details{default_shell} = "/bin/sh"; } my @unameX = split(/\n/,`uname -X`); foreach(@unameX) { if (/Release\s+=\s+(([0-9]\.?)+)$/) { $Details{release} = $1; } elsif (/NumCPU\s+=\s+([0-9]+)/) { $Details{processor_count} = $1; } } my @psrinfoV = split(/\n/,`psrinfo -v`); foreach(@psrinfoV) { if (/([0-9]+) mhz/i) { $Details{processor_speed} = $1; } } if (not $Details{processor_count}) { $Details{processor_count} = 1; } if (not $Details{release}) { $Details{release} = `uname -r`; } if ($Details{release} !~ /^5\./) { return(error("Unsupported OS release is $Details{release} being used.")); } else { $Details{ostag} = "sunos5"; } if ($Details{release} =~ /5.([0-9]+)/) { my $minor_version = $1; if ($minor_version <= 6) { # 2.6, et al. $Details{os_version} = $Details{release} - 3.0; } else { $Details{os_version} = $minor_version; } } # -p on Solaris returns the processor type. $Details{hardware} = $Details{processor} = `uname -p`; unless ($Details{hardware} =~ /sparc/i) { return(error("Unsupported Solaris machine series '$hardware' being used.")); } my @disabled_mountpoints; my @mount_points = split(/\n/,`/usr/sbin/mount`); foreach(@mount_points) { m@^\s*(\S+)\s+on\s+\S+\s+(\S+)\s+on@ || next; my $mount_point = $1; my @mount_flags = split(m@/@,$2); my $writable; my $remote; foreach(@mount_flags) { if (/write/) { $writable = 1; } elsif (/remote/) { $remote = 1; last; } } if ((not $writable) || $remote) { push @disabled_mountpoints,$mount_point; } } $Details{disabled_mountpoints} = [ @disabled_mountpoints ]; return(1); } sub detect_aix { $Details{os_name} = $Details{os} = "AIX"; $Details{libpath_variable} = "LIBPATH"; $Details{shlib_extensions} = ["so","a"]; $Details{package_formats} = ["TAR","BFF"]; if ( -x "/bin/ksh" ) { $Details{default_shell} = "/bin/ksh"; } else { $Details{default_shell} = "/bin/sh"; } $Details{hardware} = $Details{processor} = "rs6000"; my @processor_lines = split(/\n/,`lscfg | grep proc`); $Details{processor_count} = scalar(@processor_lines); my $os_v=`uname -v`; chomp $os_v; my $os_r=`uname -r`; chomp $os_r; $Details{os_version} = $Details{release} = "$os_v.$os_r"; if ($Details{release} !~ /4\.3/) { return(error("Unsupported OS release is $Details{release} being used.")); } else { $Details{ostag} = "aix4"; } my @pmcycles = split(/\n/,`pmcycles`); foreach(@pmcycles) { if (/([0-9]+) mhz/i) { $Details{processor_speed} = $1; } } my @disabled_mountpoints; my @mount_points = split(/\n/,`/usr/sbin/mount`); foreach(@mount_points) { m@^\s*/\S*\s+(/\S*)\s+(\S+)\s+(.*)@ || next; my $mount_point = $1; my $mount_type = $2; my @mount_flags = split(/,/,$3); my $disabled; # Read-only? foreach(@mount_flags) { if (/\s*ro\s*/) { $disabled = 1; } } # Remote filesystem? $disabled |= ($mount_type =~ m@(nfs|afs)@); if ($disabled) { push @disabled_mountpoints,$mount_point; } } $Details{disabled_mountpoints} = [ @disabled_mountpoints ]; return(1); } sub detect_hpux { $Details{os_name} = $Details{os} = "HP-UX"; $Details{libpath_variable} = "SHLIB_PATH"; $Details{shlib_extensions} = ["sl"]; $Details{package_formats} = ["TAR"]; if ( -x "/bin/ksh" ) { $Details{default_shell} = "/bin/ksh"; } else { $Details{default_shell} = "/bin/sh"; } my $CPU_PA_RISC1_0 = 0x20B ; # ChiliSoft does NOT support this arch. my $CPU_PA_RISC1_1 = 210 ; # HP PA-RISC 1.1 my $CPU_PA_RISC1_2 = 211 ; # HP PA-RISC 1.2 my $CPU_PA_RISC2_0 = 214 ; # HP PA-RISC 2.0 my $CPU_PA_RISC_MAX = 0x2FF ; $Details{hardware} = undef ; my $cpu_version = sprintf("%x",`getconf CPU_VERSION 2>/dev/null`); if ($cpu_version == $CPU_PA_RISC_2_0) { $Details{hardware} = "PA_RISC2.0" ; $Details{processor} = "PA_RISC" ; } elsif (($cpu_version >= $CPU_PA_RISC_1_1) && ($cpu_version < $CPU_PA_RISC_MAX)) { $Details{hardware} = $Details{processor} = "PA_RISC" ; } $Details{processor_count} = undef ; $! = 0 ; # initialize the error value ; $Details{processor_count} = syscall(315,1,0,0) ; unless ($Details{processor_count}) { error("mpctl system call returned with the following error - $!") ; $Details{processor_count} = `(ioscan -kCprocessor | grep processor | wc -l) 2> /dev/null` ; } # Unable to successfully detect. start guessing. if (! $Details{hardware} || ! $Details{processor_count}) { $hardware = `model`; if ($hardware =~ m@^\s*(9000)\s*/\s*([^/]*)\s*/\s*(\S*)\s*$@) { # / / [U|D|Q] $Details{hardware} = $Details{processor} = "$1-$2"; if ($hardware =~ /U/) { $Details{processor_count} = "1"; } elsif ($hardware =~ /(D|A)/) { $Details{processor_count} = "2"; } elsif ($hardware =~ /Q/) { $Details{processor_count} = "4"; } } else { error("Unsupported HP-UX machine series being used."); return undef; } } my @speed = `(echo "itick_per_usec/D" | adb -k /stand/vmunix /dev/kmem) 2>/dev/null` ; foreach (@speed) { if (/^\s*itick_per_usec\s*:\s*(\d+)$/) { $Details{processor_speed} = $1 ; last ; } } $Details{os_version} = $Details{release} = `uname -r`; if ($Details{release} =~ /[AB]\.11*/) { $Details{ostag} = "ux11"; } else { error("Unsupported OS release is being used."); return undef; } my @disabled_mountpoints; my @mount_points = split(/\n/,`/usr/sbin/mount -p`); foreach(@mount_points) { m@^\s*\S+\s+(/\S*)\s+(\S+)\s+(.*)@ || next; my $mount_point = $1; my $mount_type = $2; my $mount_flags = $3; my $disabled; # Read-only? foreach(@mount_flags) { if (/\s*ro\s*/) { $disabled = 1; } } # Remote filesystem? $disabled |= ($mount_type =~ m@(nfs|afs)@); if ($disabled) { push @disabled_mountpoints,$mount_point; } } $Details{disabled_mountpoints} = [ @disabled_mountpoints ]; return(1); } sub detect_linux { $Details{os_name} = $Details{os} = "Linux"; $Details{libpath_variable} = "LD_LIBRARY_PATH"; $Details{shlib_extensions} = ["so"]; &INSTALL::common::path_append("/bin","/sbin"); if ( -x "/bin/ksh" ) { $Details{default_shell} = "/bin/ksh"; } else { $Details{default_shell} = "/bin/sh"; } local *CPUINFO; if (open(CPUINFO,") { chomp $info_line; if ($info_line =~ /^processor/) { $Details{processor_count}++; } elsif ($info_line =~ /^cpu MHz\s*:\s*([0-9.]+)/) { $Details{processor_speed} = $1; } } close(CPUINFO); } $Details{os_version} = `uname -r`; $Details{os_version} =~ /([0-9\.]+)/; $Details{release} = $1; $Details{ostag} = lc($Details{os}) . substr($Details{release},0,1); $Details{hardware} = `uname -m`; if ($Details{hardware} !~ /i[x3456]86/) { return(error("Unsupported Linux hardware `$Details{hardware}`.")); } else { # Correct for naming conventions $Details{hardware} = "ia32"; } $Details{processor} = $Details{hardware}; my @disabled_mountpoints; my @mount_points = split(/\n/,`/bin/mount`); foreach(@mount_points) { m@^\s*\S*\s+on\s+(/\S*)\s+type\s+(\S+)\s+(.*)@ || next; my $mount_point = $1; my $mount_type = $2; my $mount_flags = $3; $mount_flags =~ s@[()]@@g; my $disabled; # Read-only? foreach(@mount_flags) { if (/\s*ro\s*/) { $disabled = 1; } } # Remote filesystem? $disabled |= ($mount_type =~ m@(nfs|afs)@); if ($disabled) { push @disabled_mountpoints,$mount_point; } } $Details{disabled_mountpoints} = [ @disabled_mountpoints ]; DISTRIBUTION: while(1) { if (-e "/etc/mandrake-release") { $Details{distribution} = "Mandrake"; $Details{distribution_flavor} = "RedHat"; my $redhat; if (open(MANDRAKE,"; $line =~ s/[^0-9]*([0-9]+\.[0-9]+).*/$1/; $mandrake = $line; if ($mandrake =~ /[0-9]+/) { $Details{distribution_version} = $mandrake; } } $Details{package_formats} = ["RPM"]; last DISTRIBUTION; } if (-e "/etc/redhat-release") { $Details{distribution} = "RedHat"; $Details{distribution_flavor} = "RedHat"; my $redhat; if (open(REDHAT,"; $line =~ s/[^0-9]*([0-9]+\.[0-9]+).*/$1/; $redhat = $line; if ($redhat =~ /[0-9]+/) { $Details{distribution_version} = $redhat; } } $Details{package_formats} = ["RPM"]; last DISTRIBUTION; } if (-e "/etc/cobalt-release") { $Details{distribution} = "Cobalt"; $Details{distribution_flavor} = "RedHat"; my $cobalt; if (open(COBALT,"; $line =~ s/[^0-9]*([0-9]+\.[0-9]+).*/$1/; $cobalt = $line; if ($cobalt =~ /[0-9]+/) { $Details{distribution_version} = $cobalt; } } $Details{package_formats} = ["RPM","PKG"]; last DISTRIBUTION; } if (-e "/etc/slackware-version") { $Details{distribution} = "Slackware"; $Details{distribution_flavor} = "Slackware"; my $slackware; if (open(SLACKWARE,"; $line =~ s/[^0-9]*([0-9]+(\.[0-9]+)*).*/$1/; $slackware = $line; if ($slackware =~ /[0-9]+/) { $Details{distribution_version} = $slackware; } } $Details{package_formats} = ["TAR"]; last DISTRIBUTION; } if (-e "/etc/SuSE-release") { $Details{distribution} = "SuSE"; $Details{distribution_flavor} = "SuSE"; my $SuSE; if (open(SUSE,") { if (/VERSION\s+=\s+(\d.*)/) { $SuSE = $1; } } if ($SuSE =~ /[0-9]+/) { $Details{distribution_version} = $SuSE; } } $Details{package_formats} = ["RPM"]; last DISTRIBUTION; } if (-e "/etc/debian_version") { $Details{distribution} = "Debian"; $Details{distribution_flavor} = "Debian"; my $debian; if (open(DEBIAN,"; $line =~ s/[^0-9]*([0-9]+\.[0-9]+).*/$1/; $debian = $line; if ($debian =~ /[0-9]+/) { $Details{distribution_version} = $debian; } } $Details{package_formats} = ["DEB"]; last DISTRIBUTION; } if (-e "/etc/turbolinux-release") { $Details{distribution} = "TurboLinux"; $Details{distribution_flavor} = "RedHat"; my $turbolinux; if (open(TURBOLINUX,"; $line =~ s/[^0-9]*([0-9]+\.[0-9]+).*/$1/; $turbolinux = $line; if ($turbolinux =~ /[0-9]+/) { $Details{distribution_version} = $turbolinux; } } $Details{package_formats} = ["RPM"]; last DISTRIBUTION; } die "Unable to determine distribution."; } return(1); } sub encode_names { my @names = @_; # Remove any non-supported symbols from the name. if (wantarray) { return(map { s/[^A-Za-z0-9_]//g; $_; } @names); } else { ($#names == 0) || die "Cannot return list to scalar."; $names[0] =~ s/[^A-Za-z0-9_]//g; return($names[0]); } } #============================================================================== # User functions #============================================================================== sub detect { ($#_ < 0) || die "Invalid number of arguments."; if (not $CONST_PreviouslySeen) { my $encoded_os = encode_names(lc(`uname -s`)); my $function = "detect_$encoded_os"; my $result; if (defined &$function) { $result = &$function; $CONST_PreviouslySeen = 1; } if ($result) { $Details{default_runlevel} = detect_default_runlevel; # Equivalent to common safe_chomp, but needs to be used before # common can be defined. %Details = map { ((not ref($_)) && chomp $_); $_ } %Details; if (wantarray) { return(%Details); } else { return(1); } } else { if (wantarray) { return(); } else { return(undef); } } } } BEGIN { detect || die "Unable to detect OS specifics."; } 1;