1#!/usr/local/bin/perl
2# oschooser.pl
3# Read the list of operating systems and ask the user to choose
4# an OS and version
5# auto param: 0 = always ask user
6#	      1 = automatic, give up if fails
7#	      2 = automatic, ask user if fails
8#             3 = automatic, ask user if fails and if a TTY
9
10$| = 1;
11
12($oslist, $out, $auto) = @ARGV;
13open(OS, "<".$oslist) || die "failed to open $oslist : $!";
14while(<OS>) {
15	chop;
16	if (/^([^\t]+)\t+([^\t]+)\t+([^\t]+)\t+([^\t]+)\t*(.*)$/) {
17		push(@list, [ $1, $2, $3, $4, $5 ]);
18		push(@names, $1) if (!$donename{$1}++);
19		$names_to_real{$1} ||= $3;
20		}
21	}
22close(OS);
23
24if ($auto) {
25	# Try to guess the OS name and version
26	if (-r "/etc/.issue") {
27		$etc_issue = `cat /etc/.issue`;
28		}
29	elsif (-r "/etc/issue") {
30		$etc_issue = `cat /etc/issue`;
31		}
32	if (-r "/etc/os-release") {
33		$os_release = `cat /etc/os-release`;
34		}
35	if (&has_command('uname')) {
36		$uname = `uname -a 2>/dev/null`;
37		}
38	foreach $o (@list) {
39		if ("$^O" =~ /MSWin32/ && "$o->[2]" !~ /windows/) {
40			next;
41		}
42		if ($o->[4] && eval "$o->[4]") {
43			# Got a match! Resolve the versions
44			$ver = $o;
45			if ($ver->[1] =~ /\$/) {
46				$ver->[1] = eval "($o->[4]); $ver->[1]";
47				}
48			if ($ver->[3] =~ /\$/) {
49				$ver->[3] = eval "($o->[4]); $ver->[3]";
50				}
51			last;
52			}
53		if ($@) {
54			print STDERR "Error parsing $o->[4]\n";
55			}
56		}
57
58	if (!$ver) {
59		if ($auto == 1) {
60			# Failed .. give up
61			print "Failed to detect operating system\n";
62			exit 1;
63			}
64		elsif ($auto == 3) {
65			# Do we have a tty?
66			local $rv = system("tty >/dev/null 2>&1");
67			if ($?) {
68				print "Failed to detect operating system\n";
69				exit 1;
70				}
71			else {
72				$auto = 0;
73				}
74			}
75		else {
76			# Ask the user
77			$auto = 0;
78			}
79		}
80	}
81
82if (!$auto) {
83	if (0 && &has_command("dialog")) {
84		# call the dialog command to ask for the OS (disabled for now)
85		$cmd = "dialog --menu \"Please select your operating system type from the list below\" 20 60 12";
86		for($i=0; $i<@names; $i++) {
87			$cmd .= " ".($i+1)." '$names[$i]'";
88			}
89		$tmp_base = $ENV{'tempdir'} || "/tmp/.webmin";
90		$temp = "$tmp_base/dialog.out";
91		system("$cmd 2>$temp");
92		$osnum = `cat $temp`;
93		$osnum = int($osnum);
94		if (!$osnum) {
95			#unlink($temp);
96			print "ERROR: No operating system selected\n\n";
97			exit 9;
98			}
99
100		# call the dialog command to ask for the version
101		$name = $names[$osnum-1];
102		@vers = grep { $_->[0] eq $name } @list;
103		$cmd = "dialog --menu \"Please select your operating system's version from the list below\" 20 60 12";
104		for($i=0; $i<@vers; $i++) {
105			$cmd .= " ".($i+1)." '$name $vers[$i]->[1]'";
106			}
107		system("$cmd 2>$temp");
108		$vnum = `cat $temp`;
109		$vnum = int($vnum);
110		unlink($temp);
111		if (!$vnum) {
112			print "ERROR: No operating system version selected\n\n";
113			exit 9;
114			}
115		$ver = $vers[$vnum-1];
116		}
117	else {
118		# ask for the operating system name ourselves
119		$dashes = "-" x 75;
120		print <<EOF;
121For Webmin to work properly, it needs to know which operating system
122type and version you are running. Please select your system type by
123entering the number next to it from the list below
124$dashes
125EOF
126		for($i=0; $i<@names; $i++) {
127			printf " %2d) %-20.20s ", $i+1, $names[$i];
128			print "\n" if ($i%3 == 2);
129			}
130		print "\n" if ($i%3);
131		print $dashes,"\n";
132		print "Operating system: ";
133		chop($osnum = <STDIN>);
134		if ($osnum !~ /^\d+$/) {
135			print "ERROR: You must enter the number next to your operating\n";
136			print "system, not its name or version number.\n\n";
137			exit 9;
138			}
139		if ($osnum < 1 || $osnum > @names) {
140			print "ERROR: $osnum is not a valid operating system number.\n\n";
141			exit 10;
142			}
143		print "\n";
144
145		# Ask for the operating system version
146		$name = $names[$osnum-1];
147		print <<EOF;
148Please enter the version of $name you are running
149EOF
150		print "Version: ";
151		chop($vnum = <STDIN>);
152		if ($vnum !~ /^\S+$/) {
153			print "ERROR: An operating system number cannot contain\n\n";
154			print "spaces. It must be like 2.1 or ES4.0.\n";
155			exit 10;
156			}
157		print "\n";
158		$ver = [ $name, $vnum,
159			  $names_to_real{$name}, $vnum ];
160		}
161	}
162
163# Write the name, version and real name and version to a file
164open(OUT, ">$out");
165print OUT "os_type='",$ver->[2],"'\n";
166print OUT "os_version='",$ver->[3],"'\n";
167print OUT "real_os_type='",$ver->[0],"'\n";
168print OUT "real_os_version='",$ver->[1],"'\n";
169close(OUT);
170
171# has_command(command)
172# Returns the full path if some command is in the path, undef if not
173sub has_command
174{
175local($d);
176if (!$_[0]) { return undef; }
177local $rv = undef;
178if ($_[0] =~ /^\//) {
179	$rv = (-x $_[0]) ? $_[0] : undef;
180	}
181else {
182	foreach $d (split(/:/ , $ENV{PATH})) {
183		if (-x "$d/$_[0]") { $rv = "$d/$_[0]"; last; }
184		}
185	}
186return $rv;
187}
188
189
190