Handle hostnames with upper-case letters
[webmin.git] / setup.pl
1 #!/usr/bin/perl
2 # setup.pl
3 # This script should be run after the webmin archive is unpacked, in order
4 # to setup the various config files
5
6 use POSIX;
7 use Socket;
8
9 # Find install directory
10 $ENV{'LANG'} = '';
11 $0 =~ s/\\/\//g;
12 if ($0 =~ /^(.*)\//) {
13         chdir($1);
14         }
15 $wadir = getcwd();
16 $wadir =~ s/\\/\//g;    # always use / separator on windows
17 $srcdir = $wadir;
18 open(VERSION, "$wadir/version") ||
19         &errorexit("Cannot find the Webmin install directory");
20 chop($ver = <VERSION>);
21 close(VERSION);
22
23 print "***********************************************************************\n";
24 print "*            Welcome to the Webmin setup script, version $ver        *\n";
25 print "***********************************************************************\n";
26 print "Webmin is a web-based interface that allows Unix-like operating\n";
27 print "systems and common Unix services to be easily administered.\n";
28 print "\n";
29
30 # Only root can run this
31 if ($< != 0) {
32         &errorexit("The Webmin install script must be run as root");
33         }
34
35 # Use the supplied destination directory, if any
36 if ($ARGV[0]) {
37         $wadir = $ARGV[0];
38         $wadir =~ s/\\/\//g;    # always use / separator on windows
39         print "Installing Webmin from $srcdir to $wadir ...\n";
40         if (!-d $wadir) {
41                 mkdir($wadir, 0755) || &errorexit("Failed to create $wadir");
42                 }
43         else {
44                 # Make sure dest dir is not in use
45                 @files = grep { !/rpmsave/ } &files_in_dir($wadir);
46                 if (@files && !-r "$wadir/setup.pl") {
47                         &errorexit("Installation directory $wadir contains other files");
48                         }
49                 }
50         }
51 else {
52         print "Installing Webmin in $wadir ...\n"
53         }
54
55 # Work out perl library path
56 $ENV{'PERLLIB'} = $wadir;
57 if ($ENV{'perllib'}) {
58         $ENV{'PERLLIB'} .= ":".$ENV{'perllib'};
59         }
60
61 # Validate source directory
62 @allmods = map { s/\/module.info$//; $_ } glob("*/module.info");
63 if (!@allmods) {
64         &errorexit("ERROR: Failed to get module list");
65         }
66 $allmods = join(" ", @allmods);
67 print "\n";
68
69 chdir($wadir);
70
71 # Load package-defined variable overrides
72 if (-r "$srcdir/setup-pre.pl") {
73         require "$srcdir/setup-pre.pl";
74         }
75
76 # Ask for webmin config directory
77 print "***********************************************************************\n";
78 print "Webmin uses separate directories for configuration files and log files.\n";
79 print "Unless you want to run multiple versions of Webmin at the same time\n";
80 print "you can just accept the defaults.\n";
81 print "\n";
82 print "Config file directory [/etc/webmin]: ";
83 if ($ENV{'config_directory'}) {
84         $config_directory = $ENV{'config_directory'};
85         }
86 else {
87         chop($config_directory = <STDIN>);
88         }
89 $config_directory ||= "/etc/webmin";
90 $config_directory =~ s/\\/\//g;
91 if ($config_directory !~ /^([a-z]:)?\//i) {
92         &errorexit("Config directory must be an absolute path");
93         }
94 if (!-d $config_directory) {
95         mkdir($config_directory, 0755) ||
96                 &errorexit("Failed to create directory $config_directory");
97         }
98 if (-r "$config_directory/config") {
99         print "Found existing Webmin configuration in $config_directory\n";
100         print "\n";
101         $upgrading=1
102         }
103
104 # We can now load the main Webmin library
105 $ENV{'WEBMIN_CONFIG'} = $config_directory;
106 $ENV{'WEBMIN_VAR'} = "/var/webmin";     # not really used
107 require "$wadir/web-lib.pl";
108
109 # Check if upgrading from an old version
110 if ($upgrading) {
111         print "\n";
112
113         # Get current var path
114         open(VAR, "$config_directory/var-path");
115         chop($var_dir = <VAR>);
116         $var_directory = $var_dir;
117         close(VAR);
118
119         # Force creation if non-existant
120         mkdir($var_dir, 0755);
121
122         # Get current perl path
123         $perl = &get_perl_path();
124
125         # Get old os name and version
126         &read_file("$config_directory/config", \%gconfig);
127         $os_type = $gconfig{'os_type'};
128         $os_version = $gconfig{'os_version'};
129         $real_os_type = $gconfig{'real_os_type'};
130         $real_os_version = $gconfig{'real_os_version'};
131         &get_miniserv_config(\%miniserv);
132         $oldwadir = $miniserv{'root'};
133         $path_separator = $gconfig{'os_type'} eq 'windows' ? ';' : ':';
134
135         if (!$miniserv{'inetd'}) {
136                 # Stop old version
137                 if ($os_type eq "windows") {
138                         system("$config_directory/stop.bat >/dev/null 2>&1");
139                         }
140                 else {
141                         system("$config_directory/stop >/dev/null 2>&1");
142                         }
143                 }
144
145         # Copy files to target directory
146         &copy_to_wadir();
147
148         # Update ACLs
149         system("$perl ".&quote_path("$wadir/newmods.pl")." $config_directory $allmods");
150
151         # Update miniserv.conf with new root directory and mime types file
152         $miniserv{'root'} = $wadir;
153         $miniserv{'mimetypes'} = "$wadir/mime.types";
154         &put_miniserv_config(\%miniserv);
155
156         # Check for third-party modules in old version
157         if ($wadir ne $oldwadir) {
158                 print "Checking for third-party modules ..\n";
159                 if ($ENV{'webmin_upgrade"'}) {
160                         $autothird = 1;
161                         }
162                 system("$perl ".&quote_path("$wadir/thirdparty.pl")." ".&quote_path($wadir)." ".&quote_path($oldwadir)." $autothird");
163                 print "..done\n";
164                 print "\n";
165                 }
166
167         # Remove old cache of module infos
168         unlink("$config_directory/module.infos.cache");
169         }
170 else {
171         # Config directory exists .. make sure it is not in use
172         @files = grep { !/rpmsave/ } &files_in_dir($config_directory);
173         if (@files && $config_directory ne "/etc/webmin") {
174                 &errorexit("Config directory $config_directory is not empty");
175                 }
176
177         # Ask for log directory
178         print "Log file directory [/var/webmin]: ";
179         if ($ENV{'var_dir'}) {
180                 $var_dir = $ENV{'var_dir'};
181                 }
182         else {
183                 chop($var_dir = <STDIN>);
184                 }
185         $var_dir ||= "/var/webmin";
186         $var_dir =~ s/\\/\//g;
187         $var_directory = $var_dir;
188         if ($var_dir !~ /^([a-z]:)?\//i) {
189                 &errorexit("Log file directory must be an absolute path");
190                 }
191         if ($var_dir eq "/" || $var_dir =~ /^[a-z]:\/$/) {
192                 &errorexit("Log directory cannot be /");
193                 }
194         if (!-d $var_dir) {
195                 mkdir($var_dir, 0755) ||
196                         &errorexit("Failed to create directory $var_dir");
197                 }
198         print "\n";
199
200         # No need to ask where Perl is, because we already have it!
201         $perl = &has_command($^X) || $^X;
202         if (!-x $perl) {
203                 &errorexit("Failed to find Perl at $perl");
204                 }
205         if ($] < 5.002) {
206                 &errorexit("Detected old perl version. Webmin requires perl 5.002 or better to run");
207                 }
208         print "Perl seems to be installed ok\n";
209         print "\n";
210
211         # Ask for operating system type
212         print "***********************************************************************\n";
213         $autoos = $ENV{'autoos'} || 2;
214         $temp = &tempname();
215         $ex = system("$perl ".&quote_path("$srcdir/oschooser.pl")." ".&quote_path("$srcdir/os_list.txt")." $temp $autoos");
216         exit($ex) if ($ex);
217         &read_env_file($temp, \%osinfo);
218         $os_type = $osinfo{'os_type'};
219         $os_version = $osinfo{'os_version'};
220         $real_os_type = $osinfo{'real_os_type'};
221         $real_os_version = $osinfo{'real_os_version'};
222         $gconfig{'os_type'} = $os_type;
223         $gconfig{'os_version'} = $os_version;
224         $gconfig{'real_os_type'} = $real_os_type;
225         $gconfig{'real_os_version'} = $real_os_version;
226         $path_separator = $gconfig{'os_type'} eq 'windows' ? ';' : ':';
227         unlink($temp);
228         print "Operating system name:    $real_os_type\n";
229         print "Operating system version: $real_os_version\n";
230         print "\n";
231
232         if ($os_type eq "windows") {
233                 # Check Windows dependencies
234                 if (!&has_command("process.exe")) {
235                         &errorexit("The command process.exe must be installed to run Webmin on Windows");
236                         }
237                 eval "use Win32::Daemon";
238                 if ($@) {
239                         &errorexit("The Perl module Win32::Daemon must be installed to run Webmin on Windows");
240                         }
241                 }
242
243         # Ask for web server port, name and password
244         print "***********************************************************************\n";
245         print "Webmin uses its own password protected web server to provide access\n";
246         print "to the administration programs. The setup script needs to know :\n";
247         print " - What port to run the web server on. There must not be another\n";
248         print "   web server already using this port.\n";
249         print " - The login name required to access the web server.\n";
250         print " - The password required to access the web server.\n";
251         print " - If the webserver should use SSL (if your system supports it).\n";
252         print " - Whether to start webmin at boot time.\n";
253         print "\n";
254         print "Web server port (default 10000): ";
255         if ($ENV{'port'}) {
256                 $port = $ENV{'port'};
257                 }
258         else {
259                 chop($port = <STDIN>);
260                 }
261         $port ||= 10000;
262         if ($port < 1 || $port > 65535) {
263                 &errorexit("$port is not a valid port number");
264                 }
265         socket(FOO, PF_INET, SOCK_STREAM, getprotobyname("tcp"));
266         setsockopt(FOO, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
267         bind(FOO, pack_sockaddr_in($port, INADDR_ANY)) ||
268                 &errorexit("TCP port $port is already in use by another program");
269         close(FOO);
270
271         print "Login name (default admin): ";
272         if ($ENV{'login'}) {
273                 $login = $ENV{'login'};
274                 }
275         else {
276                 chop($login = <STDIN>);
277                 }
278         $login ||= "admin";
279         if ($login =~ /:/) {
280                 &errorexit("Username contains a : character");
281                 }
282         if ($login =~ /\s/) {
283                 &errorexit("Username contains a space");
284                 }
285         if ($login eq "webmin") {
286                 &errorexit("Username 'webmin' is reserved for internal use");
287                 }
288         print "Login password: ";
289         if ($ENV{'password'}) {
290                 $password = $ENV{'password'};
291                 }
292         elsif ($ENV{'crypt'}) {
293                 $crypt = $ENV{'crypt'};
294                 }
295         else {
296                 chop($password = <STDIN>);
297                 print "Password again: ";
298                 chop($password2 = <STDIN>);
299                 if ($password ne $password2) {
300                         &errorexit("Passwords don't match");
301                         }
302                 if ($password =~ /:/) {
303                         &errorexit("Password contains a : character");
304                         }
305                 }
306
307         # Ask the user if SSL should be used
308         if ($ENV{'ssl'} ne '') {
309                 $ssl = $ENV{'ssl'};
310                 }
311         else {
312                 $ssl = 0;
313                 eval "use Net::SSLeay";
314                 if (!$@) {
315                         print "Use SSL (y/n): ";
316                         chop($sslyn = <STDIN>);
317                         if ($sslyn =~ /^y/i) {
318                                 $ssl = 1;
319                                 }
320                         }
321                 else {
322                         print "The Perl SSLeay library is not installed. SSL not available.\n"
323                         }
324                 }
325
326         # Don't use SSL if missing Net::SSLeay
327         if ($ssl) {
328                 eval "use Net::SSLeay";
329                 if ($@) {
330                         $ssl = 0;
331                         }
332                 }
333
334         # Ask whether to run at boot time
335         if ($ENV{'atboot'}) {
336                 $atboot = $ENV{'atboot'};
337                 }
338         else {
339                 $atboot = 0;
340                 print "Start Webmin at boot time (y/n): ";
341                 chop($atbootyn = <STDIN>);
342                 if ($atbootyn =~ /^y/i) {
343                         $atboot = 1;
344                         }
345                 }
346         $makeboot = $atboot;
347
348         # Copy files to target directory
349         print "***********************************************************************\n";
350         &copy_to_wadir();
351
352         # Create webserver config file
353         open(PERL, ">$config_directory/perl-path");
354         print PERL $perl,"\n";
355         close(PERL);
356         open(VAR, ">$config_directory/var-path");
357         print VAR $var_dir,"\n";
358         close(VAR);
359
360         print "Creating web server config files..";
361         $ufile = "$config_directory/miniserv.users";
362         $kfile = "$config_directory/miniserv.pem";
363         %miniserv = (   'port' => $port,
364                         'root' => $wadir,
365                         'mimetypes' => "$wadir/mime.types",
366                         'addtype_cgi' => 'internal/cgi',
367                         'realm' => 'Webmin Server',
368                         'logfile' => "$var_dir/miniserv.log",
369                         'errorlog' => "$var_dir/miniserv.error",
370                         'pidfile' => "$var_dir/miniserv.pid",
371                         'logtime' => 168,
372                         'ppath' => $ppath,
373                         'ssl' => $ssl,
374                         'env_WEBMIN_CONFIG' => $config_directory,
375                         'env_WEBMIN_VAR' => $var_dir,
376                         'atboot' => $atboot,
377                         'logout' => "$config_directory/logout-flag",
378                         'listen' => 10000,
379                         'denyfile' => "\\.pl\$",
380                         'log' => 1,
381                         'blockhost_failures' => 5,
382                         'blockhost_time' => 60,
383                         'syslog' => $os_type eq 'windows' ? 0 : 1,
384                         'userfile' => $ufile,
385                         'keyfile' => $kfile,
386                         'preload' => 'main=web-lib-funcs.pl',
387                          );
388         if ($ENV{'allow'}) {
389                 $miniserv{'allow'} = $ENV{'allow'};
390                 }
391         if ($ENV{'session'} eq '') {
392                 $miniserv{'session'} = $os_type eq 'windows' ? 0 : 1;
393                 }
394         else {
395                 $miniserv{'session'} = $ENV{'session'};
396                 }
397         if ($os_type eq 'windows') {
398                 $miniserv{'no_pam'} = 1;
399                 }
400         elsif ($ENV{'pam'}) {
401                 $miniserv{'pam'} = $ENV{'pam'};
402                 }
403         if ($os_type eq 'windows') {
404                 $miniserv{'nofork'} = 1;
405                 $miniserv{'restartflag'} = "$var_dir/restart.flag";
406                 $miniserv{'reloadflag'} = "$var_dir/reload.flag";
407                 $miniserv{'forkcgis'} = 1;      # Avoid memory leaks
408                 }
409         &put_miniserv_config(\%miniserv);
410
411         # Test MD5 password encryption
412         if (&unix_crypt("test", "\\$1\\$A9wB3O18\\$zaZgqrEmb9VNltWTL454R/") eq "\\$1\\$A9wB3O18\\$zaZgqrEmb9VNltWTL454R/") {
413                 $md5pass = 1;
414                 }
415
416         # Create users file
417         open(UFILE, ">$ufile");
418         if ($crypt) {
419                 print UFILE "$login:$crypt:0\n";
420                 }
421         elsif ($md5pass) {
422                 print UFILE $login,":",&unix_crypt($password, "\$1\$XXXXXXXX"),"\n";
423                 }
424         else {
425                 print UFILE $login,":",&unix_crypt($password, "XX"),"\n";
426                 }
427         close(UFILE);
428         chmod(0600, $ufile);
429
430         # Generate cert
431         if (system("openssl version >/dev/null 2>&1") == 0) {
432                 # We can generate a new SSL key for this host
433                 $host = &get_system_hostname();
434                 $cert = &tempname();
435                 $key = &tempname();
436                 open(SSL, "| openssl req -newkey rsa:512 -x509 -nodes -out $cert -keyout $key -days 1825 >/dev/null 2>&1");
437                 print SSL ".\n";
438                 print SSL ".\n";
439                 print SSL ".\n";
440                 print SSL "Webmin Webserver on $host\n";
441                 print SSL ".\n";
442                 print SSL "*\n";
443                 print SSL "root\@$host\n";
444                 $ok = close(SSL);
445                 if (!$?) {
446                         open(CERTIN, $cert);
447                         open(KEYIN, $key);
448                         open(OUT, ">$kfile");
449                         while(<CERTIN>) {
450                                 print OUT $_;
451                                 }
452                         while(<KEYIN>) {
453                                 print OUT $_;
454                                 }
455                         close(CERTIN);
456                         close(KEYIN);
457                         close(OUT);
458                         }
459                 unlink($cert, $key);
460                 }
461         if (!-r $kfile) {
462                 # Fall back to the built-in key
463                 &copy_source_dest("$wadir/miniserv.pem", $kfile);
464                 }
465         chmod(0600, $kfile);
466         print "..done\n";
467         print "\n";
468
469         print "Creating access control file..\n";
470         $afile = "$config_directory/webmin.acl";
471         open(AFILE, ">$afile");
472         if ($ENV{'defaultmods'}) {
473                 print AFILE "$login: $ENV{'defaultmods'}\n";
474                 }
475         else {
476                 print AFILE "$login: $allmods\n";
477                 }
478         close(AFILE);
479         chmod(0600, $afile);
480         print "..done\n";
481         print "\n";
482
483         if ($login ne "root" && $login ne "admin") {
484                 # Allow use of RPC by this user
485                 open(ACL, ">$config_directory/$login.acl");
486                 print ACL "rpc=1\n";
487                 close(ACL);
488                 }
489         }
490
491 if (!$ENV{'noperlpath"'} && $os_type ne 'windows') {
492         print "Inserting path to perl into scripts..\n";
493         system("(find ".&quote_path($wadir)." -name '*.cgi' -print ; find ".&quote_path($wadir)." -name '*.pl' -print) | $perl ".&quote_path("$wadir/perlpath.pl")." $perl -");
494         print "..done\n";
495         print "\n";
496         }
497
498 print "Creating start and stop scripts..\n";
499 if ($os_type eq "windows") {
500         open(START, ">>$config_directory/start.bat");
501         print START "$perl \"$wadir/miniserv.pl\" $config_directory/miniserv.conf\n";
502         close(START);
503         $start_cmd = "sc start ".($ENV{'bootscript'} || "webmin");
504
505         open(STOP, ">>$config_directory/stop.bat");
506         print STOP "echo Not implemented\n";
507         close(STOP);
508         }
509 else {
510         open(START, ">$config_directory/start");
511         print START "#!/bin/sh\n";
512         print START "echo Starting Webmin server in $wadir\n";
513         print START "trap '' 1\n";
514         print START "LANG=\n";
515         print START "export LANG\n";
516         print START "unset PERLIO\n";
517         print START "export PERLIO\n";
518         print START "PERLLIB=$perllib\n";
519         print START "export PERLLIB\n";
520         if ($os_type eq "hpux") {
521                 print START "exec '$wadir/miniserv.pl' $config_directory/miniserv.conf &\n";
522                 }
523         else {
524                 print START "exec '$wadir/miniserv.pl' $config_directory/miniserv.conf\n";
525                 }
526         close(START);
527         $start_cmd = "$config_directory/start";
528
529         open(STOP, ">$config_directory/stop");
530         print STOP "#!/bin/sh\n";
531         print STOP "echo Stopping Webmin server in $wadir\n";
532         print STOP "pidfile=\`grep \"^pidfile=\" $config_directory/miniserv.conf | sed -e 's/pidfile=//g'\`\n";
533         print STOP "kill \`cat \$pidfile\`\n";
534         close(STOP);
535
536         open(RESTART, ">$config_directory/restart");
537         print RESTART "#!/bin/sh\n";
538         print RESTART "$config_directory/stop && $config_directory/start\n";
539         close(RESTART);
540
541         chmod(0755, "$config_directory/start", "$config_directory/stop",
542                     "$config_directory/restart");
543         }
544 print "..done\n";
545 print "\n";
546
547 if ($upgrading) {
548         print "Updating config files..\n";
549         }
550 else {
551         print "Copying config files..\n";
552         }
553 system("$perl ".&quote_path("$wadir/copyconfig.pl")." ".&quote_path("$os_type/$real_os_type")." ".&quote_path("$os_version/$real_os_version")." ".&quote_path($wadir)." ".$config_directory." \"\" ".$allmods);
554 if (!$upgrading) {
555         # Store the OS and version
556         &read_file("$config_directory/config", \%gconfig);
557         $gconfig{'os_type'} = $os_type;
558         $gconfig{'os_version'} = $os_version;
559         $gconfig{'real_os_type'} = $real_os_type;
560         $gconfig{'real_os_version'} = $real_os_version;
561         $gconfig{'log'} = 1;
562         &write_file("$config_directory/config", \%gconfig);
563         }
564 open(VER, ">$config_directory/version");
565 print VER $ver,"\n";
566 close(VER);
567 print "..done\n";
568 print "\n";
569
570 # Set passwd_ fields in miniserv.conf from global config
571 &get_miniserv_config(\%miniserv);
572 foreach $field ("passwd_file", "passwd_uindex", "passwd_pindex", "passwd_cindex", "passwd_mindex") {
573         if ($gconfig{$field}) {
574                 $miniserv{$field} = $gconfig{$field};
575                 }
576         }
577 if (!defined($miniserv{'passwd_mode'})) {
578         $miniserv{'passwd_mode'} = 0;
579         }
580
581 # If Perl crypt supports MD5, then make it the default
582 if ($md5pass) {
583         $gconfig{'md5pass'} = 1;
584         }
585
586 # Set a special theme if none was set before
587 if ($ENV{'theme'}) {
588         $theme = $ENV{'theme'};
589         }
590 elsif (open(THEME, "$wadir/defaulttheme")) {
591         chop($theme = <THEME>);
592         close(THEME);
593         }
594 if ($theme && -d "$wadir/$theme") {
595         $gconfig{'theme'} = $theme;
596         $miniserv{'preroot'} = $theme;
597         }
598
599 # Set the product field in the global config
600 $gconfig{'product'} ||= "webmin";
601
602 if ($makeboot) {
603         print "Configuring Webmin to start at boot time..\n";
604         chdir("$wadir/init");
605         system("$perl ".&quote_path("$wadir/init/atboot.pl")." ".$ENV{'bootscript'});
606         print "..done\n";
607         print "\n";
608         }
609
610
611 # If password delays are not specifically disabled, enable them
612 if (!defined($miniserv{'passdelay'}) && $os_type ne 'windows') {
613         $miniserv{'passdelay'} = 1;
614         }
615
616 # Save configs
617 &put_miniserv_config(\%miniserv);
618 &write_file("$config_directory/config", \%gconfig);
619
620 if (!$ENV{'nouninstall'} && $os_type ne "windows") {
621         print "Creating uninstall script $config_directory/uninstall.sh ..\n";
622         open(UN, ">$config_directory/uninstall.sh");
623         print UN <<EOF;
624 #!/bin/sh
625 printf "Are you sure you want to uninstall Webmin? (y/n) : "
626 read answer
627 printf "\n"
628 if [ "\$answer" = "y" ]; then
629         $config_directory/stop
630         echo "Running uninstall scripts .."
631         (cd "$wadir" ; WEBMIN_CONFIG=$config_directory WEBMIN_VAR=$var_dir LANG= "$wadir/run-uninstalls.pl")
632         echo "Deleting $wadir .."
633         rm -rf "$wadir"
634         echo "Deleting $config_directory .."
635         rm -rf "$config_directory"
636         echo "Done!"
637 fi
638 EOF
639         chmod(0755, "$config_directory/uninstall.sh");
640         print "..done\n";
641         print "\n";
642         }
643
644 if ($os_type ne "windows") {
645         print "Changing ownership and permissions ..\n";
646         system("chown -R root $config_directory");
647         system("chgrp -R bin $config_directory");
648         system("chmod -R og-rw $config_directory");
649         system("chmod 755 $config_directory/{sendmail,qmailadmin,postfix}*/config >/dev/null 2>&1");
650         system("chmod 755 $config_directory/{sendmail,qmailadmin,postfix}*/autoreply.pl >/dev/null 2>&1");
651         system("chmod 755 $config_directory/{sendmail,qmailadmin,postfix}*/filter.pl >/dev/null 2>&1");
652         system("chmod 755 $config_directory/squid*/squid-auth.pl >/dev/null 2>&1");
653         system("chmod 755 $config_directory/squid*/users >/dev/null 2>&1");
654         system("chmod 755 $config_directory/cron*/range.pl >/dev/null 2>&1");
655         system("chmod +r $config_directory/version");
656         if (!$ENV{'nochown'}) {
657                 system("chown -R root \"$wadir\"");
658                 system("chgrp -R bin \"$wadir\"");
659                 system("chmod -R og-w \"$wadir\"");
660                 system("chmod -R a+rx \"$wadir\"");
661                 }
662         if ($var_dir ne "/var") {
663                 system("chown -R root $var_dir");
664                 system("chgrp -R bin $var_dir");
665                 system("chmod -R og-rwx $var_dir");
666                 }
667         print "..done\n";
668         print "\n";
669         }
670
671 # Save target directory if one was specified
672 if ($wadir ne $srcdir) {
673         open(INSTALL, ">$config_directory/install-dir");
674         print INSTALL $wadir,"\n";
675         close(INSTALL);
676         }
677 else {
678         unlink("$config_directory/install-dir");
679         }
680
681 if (!$ENV{'nopostinstall'}) {
682         print "Running postinstall scripts ..\n";
683         chdir($wadir);
684         system("$perl ".&quote_path("$wadir/run-postinstalls.pl"));
685         print "..done\n";
686         print "\n";
687         }
688
689 # Run package-defined post-install script
690 if (-r "$srcdir/setup-post.pl") {
691         require "$srcdir/setup-post.pl";
692         }
693
694 if (!$ENV{'nostart'}) {
695         if (!$miniserv{'inetd'}) {
696                 print "Attempting to start Webmin mini web server..\n";
697                 $ex = system($start_cmd);
698                 if ($ex) {
699                         &errorexit("Failed to start web server!");
700                         }
701                 print "..done\n";
702                 print "\n";
703                 }
704
705         print "***********************************************************************\n";
706         print "Webmin has been installed and started successfully. Use your web\n";
707         print "browser to go to\n";
708         print "\n";
709         $host = &get_system_hostname();
710         if ($ssl) {
711                 print "  https://$host:$miniserv{'port'}/\n";
712                 }
713         else {
714                 print "  http://$host:$miniserv{'port'}/\n";
715                 }
716         print "\n";
717         print "and login with the name and password you entered previously.\n";
718         print "\n";
719         if ($ssl) {
720                 print "Because Webmin uses SSL for encryption only, the certificate\n";
721                 print "it uses is not signed by one of the recognized CAs such as\n";
722                 print "Verisign. When you first connect to the Webmin server, your\n";
723                 print "browser will ask you if you want to accept the certificate\n";
724                 print "presented, as it does not recognize the CA. Say yes.\n";
725                 print "\n";
726                 }
727         }
728
729 if ($oldwadir ne $wadir && $upgrading && !$ENV{'deletedold'}) {
730         print "The directory from the previous version of Webmin\n";
731         print "   $oldwadir\n";
732         print "Can now be safely deleted to free up disk space, assuming\n";
733         print "that all third-party modules have been copied to the new\n";
734         print "version.\n";
735         print "\n";
736         }
737
738 sub errorexit
739 {
740 print "ERROR: ",@_,"\n";
741 print "\n";
742 exit(1);
743 }
744
745 sub copy_to_wadir
746 {
747 if ($wadir ne $srcdir) {
748         print "Copying files to $wadir ..\n";
749         if (&has_command("tar")) {
750                 # Unix tar exists
751                 system("cd ".&quote_path($srcdir)." && tar cf - . | (cd ".&quote_path($wadir)." ; tar xf -)");
752                 }
753         else {
754                 # Looks like Windows .. use xcopy command
755                 system("xcopy \"$srcdir\" \"$wadir\" /Y /E /I");
756                 }
757         print "..done\n";
758         print "\n";
759         }
760 }
761
762 sub files_in_dir
763 {
764 opendir(DIR, $_[0]);
765 local @rv = grep { $_ ne "." && $_ ne ".." } readdir(DIR);
766 closedir(DIR);
767 return @rv;
768 }
769