Make Slackware detection more specific, add OsChooser.pm
This commit is contained in:
parent
10833cd9be
commit
8c79fcdd11
225
OsChooser.pm
Executable file
225
OsChooser.pm
Executable file
@ -0,0 +1,225 @@
|
||||
#!/usr/local/bin/perl -w
|
||||
use strict;
|
||||
# Detect the operating system and version.
|
||||
|
||||
package OsChooser;
|
||||
|
||||
# Package scoped for mapping short names to long "proper" names
|
||||
my %NAMES_TO_REAL;
|
||||
|
||||
# main
|
||||
sub main {
|
||||
if ($#ARGV < 1) { die "Usage: $0 os_list.txt outfile [0|1|2|3] [issue]\n"; }
|
||||
my ($oslist, $out, $auto, $issue) = @ARGV;
|
||||
return write_file($out, oschooser($oslist, $auto, $issue));
|
||||
}
|
||||
main() unless caller(); # make it testable and usable as a library
|
||||
|
||||
$| = 1;
|
||||
|
||||
sub oschooser {
|
||||
my ($oslist, $auto, $issue) = @_;
|
||||
my $ver_ref;
|
||||
|
||||
my ($list_ref, $names_ref) = parse_patterns($oslist);
|
||||
|
||||
if ($auto && ($ver_ref = auto_detect($oslist, $issue, $list_ref, $names_ref))) {
|
||||
return ($ver_ref->[2], $ver_ref->[3], $ver_ref->[0], $ver_ref->[1]);
|
||||
}
|
||||
elsif (!$auto || ($auto == 3 && have_tty()) || $auto == 2) {
|
||||
$ver_ref = ask_user($names_ref, $list_ref);
|
||||
return ($ver_ref->[2], $ver_ref->[3], $ver_ref->[0], $ver_ref->[1]);
|
||||
}
|
||||
else {
|
||||
print "Failed to detect operating system\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Return a reference to a pre-parsed list array, and a ref to a names array
|
||||
sub parse_patterns {
|
||||
my ($oslist) = @_;
|
||||
my @list;
|
||||
my @names;
|
||||
my %donename;
|
||||
# Parse the patterns file
|
||||
open(OS, "<$oslist") || die "failed to open $oslist : $!";
|
||||
while(<OS>) {
|
||||
chop;
|
||||
if (/^([^\t]+)\t+([^\t]+)\t+([^\t]+)\t+([^\t]+)\t*(.*)$/) {
|
||||
push(@list, [ $1, $2, $3, $4, $5 ]);
|
||||
push(@names, $1) if (!$donename{$1}++);
|
||||
$NAMES_TO_REAL{$1} ||= $3;
|
||||
}
|
||||
}
|
||||
close(OS);
|
||||
return (\@list, \@names);
|
||||
}
|
||||
|
||||
# auto_detect($oslist, $issue)
|
||||
# Returns detected OS details in a hash ref
|
||||
sub auto_detect {
|
||||
my ($oslist, $issue, $list_ref) = @_;
|
||||
my $ver_ref;
|
||||
my @list = @$list_ref;
|
||||
|
||||
# Try to guess the OS name and version
|
||||
my $etc_issue;
|
||||
my $uname = `uname -a`;
|
||||
|
||||
if ($issue) {
|
||||
$etc_issue = `cat $issue`;
|
||||
$uname = $etc_issue; # Strangely, I think this will work fine.
|
||||
}
|
||||
elsif (-r "/etc/.issue") {
|
||||
$etc_issue = `cat /etc/.issue`;
|
||||
}
|
||||
elsif (-r "/etc/issue") {
|
||||
$etc_issue = `cat /etc/issue`;
|
||||
}
|
||||
|
||||
foreach my $o_ref (@list) {
|
||||
if ($issue && $o_ref->[4]) {
|
||||
$o_ref->[4] =~ s#cat [/a-zA-Z\-\s]*\s2#cat $issue 2#g;
|
||||
} # Testable, but this regex substitution is dumb.XXX
|
||||
local $^W = 0; # Disable warnings for evals, which may have undefined vars
|
||||
if ($o_ref->[4] && eval "$o_ref->[4]") {
|
||||
# Got a match! Resolve the versions
|
||||
print "$o_ref->[4]\n";
|
||||
$ver_ref = $o_ref;
|
||||
if ($ver_ref->[1] =~ /\$/) {
|
||||
$ver_ref->[1] = eval "($o_ref->[4]); $ver_ref->[1]";
|
||||
}
|
||||
if ($ver_ref->[3] =~ /\$/) {
|
||||
$ver_ref->[3] = eval "($o_ref->[4]); $ver_ref->[3]";
|
||||
}
|
||||
last;
|
||||
}
|
||||
if ($@) {
|
||||
print STDERR "Error parsing $o_ref->[4]\n";
|
||||
}
|
||||
}
|
||||
return $ver_ref;
|
||||
}
|
||||
|
||||
sub ask_user {
|
||||
my ($names_ref, $list_ref) = @_;
|
||||
my @names = @$names_ref;
|
||||
my @list = @$list_ref;
|
||||
my $vnum;
|
||||
my $osnum;
|
||||
# ask for the operating system name ourselves
|
||||
my $dashes = "-" x 75;
|
||||
print <<EOF;
|
||||
For Webmin to work properly, it needs to know which operating system
|
||||
type and version you are running. Please select your system type by
|
||||
entering the number next to it from the list below
|
||||
$dashes
|
||||
EOF
|
||||
{
|
||||
my $i;
|
||||
for($i=0; $i<@names; $i++) {
|
||||
printf " %2d) %-20.20s ", $i+1, $names[$i];
|
||||
print "\n" if ($i%3 == 2);
|
||||
}
|
||||
print "\n" if ($i%3);
|
||||
}
|
||||
print $dashes,"\n";
|
||||
print "Operating system: ";
|
||||
chop($osnum = <STDIN>);
|
||||
if ($osnum !~ /^\d+$/) {
|
||||
print "ERROR: You must enter the number next to your operating\n";
|
||||
print "system, not its name or version number.\n\n";
|
||||
exit 9;
|
||||
}
|
||||
if ($osnum < 1 || $osnum > @names) {
|
||||
print "ERROR: $osnum is not a valid operating system number.\n\n";
|
||||
exit 10;
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Ask for the operating system version
|
||||
my $name = $names[$osnum-1];
|
||||
print <<EOF;
|
||||
Please enter the version of $name you are running
|
||||
EOF
|
||||
print "Version: ";
|
||||
chop($vnum = <STDIN>);
|
||||
if ($vnum !~ /^\S+$/) {
|
||||
print "ERROR: An operating system number cannot contain\n\n";
|
||||
print "spaces. It must be like 2.1 or ES4.0.\n";
|
||||
exit 10;
|
||||
}
|
||||
print "\n";
|
||||
return [ $name, $vnum,
|
||||
$NAMES_TO_REAL{$name}, $vnum ];
|
||||
}
|
||||
|
||||
# write_file($out, $os_type, $os_version, $real_os_type, $real_os_version)
|
||||
# Write the name, version and real name and version to a file
|
||||
sub write_file {
|
||||
my ($out, $os_type, $os_version, $real_os_type, $real_os_version) = @_;
|
||||
open(OUT, ">$out") or die "Failed to open $out for writing.";
|
||||
print OUT "os_type='",$os_type,"'\n";
|
||||
print OUT "os_version='",$os_version,"'\n";
|
||||
print OUT "real_os_type='",$real_os_type,"'\n";
|
||||
print OUT "real_os_version='",$real_os_version,"'\n";
|
||||
return close(OUT);
|
||||
}
|
||||
|
||||
sub have_tty
|
||||
{
|
||||
# Do we have a tty?
|
||||
my $rv = system("tty >/dev/null 2>&1");
|
||||
if ($?) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 OsChooser.pm
|
||||
|
||||
Attempt to detect operating system and version, or ask the user to select
|
||||
from a list. Works from the command line, for usage from shell scripts,
|
||||
or as a library for use within Perl scripts.
|
||||
|
||||
=head2 COMMAND LINE USE
|
||||
|
||||
OsChooser.pm os_list.txt outfile [auto] [issue]
|
||||
|
||||
Where "auto" can be the following values:
|
||||
|
||||
=over 4
|
||||
|
||||
=item 0
|
||||
|
||||
always ask user
|
||||
|
||||
=item 1
|
||||
|
||||
automatic, give up if fails
|
||||
|
||||
=item 2
|
||||
|
||||
automatic, ask user if fails
|
||||
|
||||
=item 3
|
||||
|
||||
automatic, ask user if fails and if a TTY
|
||||
|
||||
=back
|
||||
|
||||
=head2 SYNOPSIS
|
||||
|
||||
use OsChooser;
|
||||
my ($os_type, $version, $real_os_type, $real_os_version) =
|
||||
OsChooser->oschooser("os_list.txt", "outfile", $auto, [$issue]);
|
||||
|
||||
=cut
|
||||
|
@ -52,7 +52,7 @@ White Dwarf Linux 2.1.0 slackware-linux 8.1 `cat /tmp/wd/version 2>/dev/null` =
|
||||
Slamd64 Linux $1 slackware-linux 11.1 `cat /etc/slamd64-version 2>/dev/null` =~ /\s([0-9\.]+)/
|
||||
|
||||
# Slackware Linux
|
||||
Slackware Linux $1 slackware-linux $1 `cat /etc/slackware-version 2>/dev/null` =~ /([0-9\.]+)/
|
||||
Slackware Linux $1 slackware-linux $1 `cat /etc/slackware-version 2>/dev/null` =~ /Slackware ([0-9\.]+)/i
|
||||
|
||||
# Debian clones
|
||||
Xandros Linux 2.0 debian-linux 3.0 $etc_issue =~ /Xandros.*\s2\.0/i
|
||||
|
Loading…
x
Reference in New Issue
Block a user