home *** CD-ROM | disk | FTP | other *** search
/ Chip: Linux Special / CorelLinux_CHIP.iso / VMware / installer / old-install.pl next >
Encoding:
Perl Script  |  1999-11-10  |  69.4 KB  |  2,559 lines

  1. #!/usr/bin/perl -w
  2. # If your copy of perl is not in /usr/bin, please adjust the line above.
  3. #
  4. # Copyright (C) 1998, 1999 VMware, Inc.  All Rights Reserved.
  5. #
  6. # Host and site-specific installation for vmware.
  7. #
  8.  
  9. use strict;
  10.  
  11. my ($bindir,  $legacylibdir, $libdir, $mandir, $initdir);
  12. my ($default_bindir,  $default_libdir, $default_mandir,
  13.     $default_initdir, $modulesdir, $vmware_tmpdir,
  14.     $vmware_etc, $vmware_locations, $vmnet1,
  15.     %previousAnswer, %previousFileTime);
  16.  
  17. my $defaultroot = "/usr/local";
  18. my $net_ifc = "eth0";
  19.  
  20. $default_bindir =
  21.     defined($ENV{BINDIR})? $ENV{BINDIR} : "$defaultroot/bin";
  22.  
  23. $default_libdir =
  24.     defined($ENV{LIBDIR})? $ENV{LIBDIR} : "$defaultroot/lib/vmware";
  25.  
  26. $default_mandir =
  27.     defined($ENV{MANDIR})? $ENV{MANDIR} : "$defaultroot/man";
  28.  
  29. $default_initdir =
  30.     defined($ENV{INITDIR})? $ENV{INITDIR} :
  31.     -d "/etc/init.d" ? "/etc" : "/etc/rc.d";
  32.  
  33. $modulesdir = "/lib/modules";
  34. $vmware_tmpdir = "/tmp/vmware-tmp";
  35. $vmware_etc = "/etc/vmware";
  36. $vmware_locations = "$vmware_etc/locations";
  37. $vmnet1 = "vmnet1";            # host-only networking interface
  38.  
  39.  
  40. my $createdBuildDir = "";
  41.  
  42. my $header_dir = '';
  43.  
  44. my ($umask, $version, $smp);
  45.  
  46. my @programs = ("vmware", "vmware-wizard","vmnet-bridge",
  47.         "vmnet-sniffer", "vmnet-dhcpd",
  48.                 "vmware-loop", "vmware-mount.pl");
  49. my @libfiles = ();
  50.  
  51. # These are the files that users might change
  52. # and therefore should be backed up before an upgrade.
  53. # The name is the base name (excluding directory) of the
  54. # installed file.
  55.  
  56. my %backupable = (
  57.           "vmware", 1,    # collision: main binary and boot file
  58.           "config", 1,  # both in /etc/vmware and in $libdir
  59.           "vmnet0.conf", 1,
  60.           "vmnet1.conf", 1,
  61.           "vmnet2.conf", 1,
  62.           "vmnet3.conf", 1,
  63.           "vMbOgUs", 1
  64.           );
  65.           
  66. my @legacylibfiles = ("nvram");
  67. my $option;
  68.  
  69. my $verbose = 0;
  70.  
  71. # External helper programs
  72. my $pwd;
  73. my $uname;
  74. my $grep;
  75. my $rm;
  76. my $mknod;
  77. my $more;
  78. my $ldd;
  79. my $cat;
  80. my $lsmod;
  81. my $rmmod;
  82. my $insmod;
  83. my $modprobe;
  84. my $tar;
  85. my $ifconfig;
  86. #  Build tools
  87. my $ksyms;
  88. my $make;
  89. my $gcc;
  90.  
  91. # Emulate a simplified ls program for directories
  92. sub internal_ls {
  93.   my $dir = $_[0];
  94.   my @fn;
  95.  
  96.   opendir(LS, $dir);
  97.   @fn = grep(!/^\.\.?$/, readdir(LS));
  98.   closedir(LS);
  99.  
  100.   return @fn;
  101. }
  102.  
  103. # Contrary to a popular belief, 'which' is not always a shell builtin command.
  104. # So we can not trust it to determine the location of other binaries.
  105. # Moreover, SuSE 6.1's 'which' is unable to handle program names beginning with
  106. # a '/'...
  107. #
  108. # Return value is the complete path if found, or "" if not found
  109. sub internal_which {
  110.   my $bin = shift;
  111.  
  112.   if (substr($bin, 0, 1) eq '/') {
  113.     # Absolute name
  114.     if ((-f $bin) && (-x $bin)) {
  115.       return $bin;
  116.     }
  117.   } else {
  118.     # Relative name
  119.     my @paths;
  120.     my $path;
  121.  
  122.     if (index($bin, '/') == -1) {
  123.       # There is no other '/' in the name
  124.       @paths = split(':', $ENV{'PATH'});
  125.       foreach $path (@paths) {
  126.     my $fullbin;
  127.  
  128.     $fullbin = $path . '/' . $bin;
  129.     if ((-f $fullbin) && (-x $fullbin)) {
  130.       return $fullbin;
  131.     }
  132.       }
  133.     }
  134.   }
  135.  
  136.   return "";
  137. }
  138.  
  139. # Tell if the user is the super user
  140. sub is_root {
  141.   return $> == 0;
  142. }
  143.  
  144. # Execute the command passed as an argument
  145. # _without_ interpolating variables (Perl does it by default)
  146. sub direct_command {
  147.   return `$_[0]`;
  148. }
  149.  
  150. # Convert a string to its equivalent shell representation
  151. sub shell_string {
  152.   my $single_quoted = $_[0];
  153.  
  154.   $single_quoted =~ s/'/'"'"'/g;
  155.   # This comment is a fix for emacs's broken syntax-highlighting code --hpreg
  156.   return '\'' . $single_quoted . '\'';
  157. }
  158.  
  159. # Build a digital Linux kernel version number
  160. sub Kernel_MakeVersion {
  161.   my $version;
  162.   my $patchLevel;
  163.   my $subLevel;
  164.   ($version, $patchLevel, $subLevel) = @_;
  165.  
  166.   return $version * 65536 + $patchLevel * 256 + $subLevel;
  167. }
  168.  
  169. # Get a clean version number for the running Linux kernel
  170. # Return value is the list of:
  171. #  Complete human readable version
  172. #  Clean x.y.z human readable version
  173. #  Digital version (default result)
  174. sub Kernel_RunningVersion {
  175.   my $fullVersion;
  176.   my $version;
  177.   my $patchLevel;
  178.   my $subLevel;
  179.  
  180.   $fullVersion = direct_command(shell_string($uname) . ' -r');
  181.   chop($fullVersion);
  182.   ($version, $patchLevel, $subLevel) = split(/\./, $fullVersion);
  183.   # Clean the subLevel in case there is an extraversion
  184.   ($subLevel) = split(/[^0-9]/, $subLevel);
  185.  
  186.   return ($fullVersion, $version . '.' . $patchLevel . '.' . $subLevel, Kernel_MakeVersion($version, $patchLevel, $subLevel));
  187. }
  188.  
  189. # Prompts the user if a binary is not found
  190. # Return value is:
  191. #  "": the binary has not been found
  192. #  the binary name if it has been found
  193. sub DoesBinaryExist_Prompt {
  194.   my $bin;
  195.   my $ans;
  196.  
  197.   $bin = $_[0];
  198.   while (internal_which($bin) eq "") {
  199.     $ans = query("Setup is unable to find the " . $bin . " program on your machine. Do you want to specify the location of this program by hand?", "Y");
  200.     if ($ans !~ /^[yY]/) {
  201.       return "";
  202.     }
  203.  
  204.     $bin = query("What is the location of the " . $bin . " program on your machine?", "");
  205.   }
  206.   return $bin;
  207. }
  208.  
  209. # Set up the location of external helpers
  210. sub initialize_external_helpers {
  211.   $pwd = DoesBinaryExist_Prompt('pwd');
  212.   if ($pwd eq "") {
  213.     print STDERR "\nUnable to continue.\n";
  214.     exit(1);
  215.   }
  216.  
  217.   $uname = DoesBinaryExist_Prompt('uname');
  218.   if ($uname eq "") {
  219.     print STDERR "\nUnable to continue.\n";
  220.     exit(1);
  221.   }
  222.  
  223.   $grep = DoesBinaryExist_Prompt('grep');
  224.   if ($grep eq "") {
  225.     print STDERR "\nUnable to continue.\n";
  226.     exit(1);
  227.   }
  228.  
  229.   $rm = DoesBinaryExist_Prompt('rm');
  230.   if ($rm eq "") {
  231.     print STDERR "\nUnable to continue.\n";
  232.     exit(1);
  233.   }
  234.  
  235.   $mknod = DoesBinaryExist_Prompt('mknod');
  236.   if ($mknod eq "") {
  237.     print STDERR "\nUnable to continue.\n";
  238.     exit(1);
  239.   }
  240.  
  241.   $more = "";
  242.   if (defined($ENV{PAGER})) {
  243.     my @tokens;
  244.  
  245.     # The environment variable sometimes contains the pager name _followed by
  246.     # a few command line options_.
  247.     #
  248.     # Isolate the program name (we are certain it does not contain a
  249.     # whitespace) before dealing with it.
  250.     @tokens = split(' ', $ENV{PAGER});
  251.     $tokens[0] = DoesBinaryExist_Prompt($tokens[0]);
  252.     if (not ($tokens[0] eq "")) {
  253.       $more = join(' ', @tokens); # This is _already_ a shell string
  254.     }
  255.   }
  256.   if ($more eq "") {
  257.     $more = DoesBinaryExist_Prompt('more');
  258.     if ($more eq "") {
  259.       print STDERR "\nUnable to continue.\n";
  260.       exit(1);
  261.     }
  262.     $more = shell_string($more); # Save it as a shell string
  263.   }
  264.  
  265.   $ldd = DoesBinaryExist_Prompt('ldd');
  266.   if ($ldd eq "") {
  267.     print STDERR "\nUnable to continue.\n";
  268.     exit(1);
  269.   }
  270.  
  271.   $cat = DoesBinaryExist_Prompt('cat');
  272.   if ($cat eq "") {
  273.     print STDERR "\nUnable to continue.\n";
  274.     exit(1);
  275.   }
  276.  
  277.   $lsmod = DoesBinaryExist_Prompt('lsmod');
  278.   if ($lsmod eq "") {
  279.     print STDERR "\nUnable to continue.\n";
  280.     exit(1);
  281.   }
  282.  
  283.   $rmmod = DoesBinaryExist_Prompt('rmmod');
  284.   if ($rmmod eq "") {
  285.     print STDERR "\nUnable to continue.\n";
  286.     exit(1);
  287.   }
  288.  
  289.   $insmod = DoesBinaryExist_Prompt('insmod');
  290.   if ($insmod eq "") {
  291.     print STDERR "\nUnable to continue.\n";
  292.     exit(1);
  293.   }
  294.  
  295.   $modprobe = DoesBinaryExist_Prompt('modprobe');
  296.   if ($modprobe eq "") {
  297.     print STDERR "\nUnable to continue.\n";
  298.     exit(1);
  299.   }
  300.  
  301.   $tar = DoesBinaryExist_Prompt('tar');
  302.   if ($tar eq "") {
  303.     print STDERR "\nUnable to continue.\n";
  304.     exit(1);
  305.   }
  306.  
  307.   $ifconfig = DoesBinaryExist_Prompt('ifconfig');
  308.   if ($ifconfig eq "") {
  309.     print STDERR "\nUnable to continue.\n";
  310.     exit(1);
  311.   }
  312. }
  313.  
  314. ####
  315. ####  Don't you just hate having to read these damn things?  We do too,
  316. #### that's why we've put this in.  And we'll even force you to read it.
  317. ####
  318. sub Show_EULA {
  319.    print << "EOMARKETING";
  320.  
  321. You must read and accept the End User License Agreement to continue.
  322. Press return to display it.
  323. EOMARKETING
  324.  
  325. # The above message used to say:
  326. #
  327. #   You must read and accept the End User License Agreement to continue.
  328. #   Well, you must at least accept it.  Press return to display it.
  329. #
  330. # which is very cute, but I had to change it because we don't want
  331. # to give the impression we're not taking ourselves seriously.  Well,
  332. # at least not before the IPO.
  333.  
  334.    <STDIN>;
  335.    # $more is already a shell string
  336.    system($more . ' EULA');
  337.    REPLY: while (1) {
  338.        # Don't use standard query here, because people may
  339.        # be using <return> to scroll through the EULA.
  340.        my $reply;
  341.        print "Do you accept? (yes/no) ";
  342.        chop($reply = <STDIN>);
  343.        last REPLY if $reply =~ /^[Yy]$|^[Yy][Ee][Ss]$/;
  344.        die "\n### The installation is aborted.\n" .
  345.        "### Please try again when you are ready to accept.\n\n"
  346.            if $reply =~ /^[Nn]$|^[Nn][Oo]$/;
  347.        print "Please reply yes or no.\n";
  348.    }
  349.    print "Thank you.\n\n";
  350. }
  351.  
  352. sub message {
  353.   my $msg = shift;
  354.   if ($verbose) { 
  355.     print $msg;
  356.   }
  357. }
  358.  
  359. sub query {
  360.  
  361.     my ($message, $defaultreply) = @_;
  362.     my $reply;
  363.     my $optSpace = substr($message, -1) eq "\n" ? "" : " ";
  364.     if ($defaultreply ne "") {
  365.     print $message . $optSpace . "[" . $defaultreply . "] ";
  366.     } else {
  367.     print $message . $optSpace;
  368.     }
  369.        
  370.     chop($reply = <STDIN>);
  371.     $reply =~ s/^\s*//;            # Kill leading whitespace
  372.     $reply =~ s/\s*$//;            # Kill trailing whitespace
  373.     $reply = $defaultreply if $reply eq "";
  374.     return $reply;
  375. }
  376.  
  377. sub makeDirectory {
  378.  
  379.     my $path = $_[0];
  380.     my $slashpos;
  381.     my $head;
  382.     my $tail;
  383.  
  384.     if ("$path" eq "") {
  385.     return;
  386.     }
  387.  
  388.     if (not -d "$path") {
  389.     if (-e "$path") {
  390.         die "\n### $path exists but it is not a directory.\n";
  391.     } else {
  392.         $slashpos = rindex($path, "/");
  393.         $head = substr($path, 0, $slashpos);
  394.         makeDirectory($head);
  395.             Log("directory $path\n");
  396.         mkdir($path, 0755) or die "\n### Cannot create $path: $!.\n";
  397.     }
  398.     }
  399. }
  400.  
  401.  
  402. sub LogFile {
  403.     my $filename = shift;
  404.     my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
  405.           $atime, $mtime, $ctime) = stat($filename);
  406.     Log("file $filename $mtime\n");
  407. }
  408.     
  409.  
  410. sub Log { 
  411.   my $string = shift;
  412.   print LOCATIONS $string;
  413. }
  414.  
  415. sub OpenLog {
  416.   my $buildNr = "1.0 " . q$Name: build-364 $;
  417.   $buildNr =~ s/Name: //;
  418.   
  419.   if (!(-d $vmware_etc)) {
  420.     # We can't use makeDirectory here, because the fucntion wants to log,
  421.     # and the log file is not opened yet
  422.     mkdir($vmware_etc,0755) or die "\n### Cannot create $vmware_etc\n";
  423.   }
  424.   open(LOCATIONS,">$vmware_locations") or
  425.      die "\n### Cannot open $vmware_locations\n";
  426.  
  427.   #### page 110 of the book
  428.  
  429.   select((select(LOCATIONS), $| = 1)[0]);
  430.  
  431.   Log("VERSION $buildNr\n");
  432.   Log("directory $vmware_etc\n");
  433. }
  434.  
  435. sub checkDir {
  436.  
  437.     my ($dir, $option) = @_;
  438.     my $answer;
  439.  
  440.     message("checkDir $dir $option \n");
  441.     if ("$dir" !~ /^\//) {
  442.     chop($answer = direct_command(shell_string($pwd)));
  443.     $dir = $answer . "/" . $dir;
  444.     }
  445.  
  446.     if (not -d "$dir") {
  447.     if ($option eq "uninstall") {
  448.         warn "\n### $dir is not a valid directory.\n";
  449.     } else {
  450.         die "\n### $dir exists and is not a directory.\n" if -e "$dir";
  451.  
  452.         if ($option eq "default" ||
  453.         query("Directory $dir does not exist.\n" .
  454.               "Create it (including needed parent directories)?",
  455.               "yes") =~ /^[Yy]/) {
  456.         message("Making directory $dir\n");
  457.         makeDirectory($dir);
  458.         } else {
  459.               return 0;
  460.         }
  461.     }
  462.     }
  463.     return 1;
  464. }
  465.  
  466. # Set bindir, mandir, libdir and initdir.
  467. # Also check as early as possible if uninstallation is
  468. # required.
  469.  
  470.  
  471. sub Init {
  472.  
  473.   my $arg = $_[0];
  474.   my $operation;
  475.  
  476.   my $diroption = $arg =~ /uninstall$/ ? "uninstall" :
  477.       $arg eq "default" ? "default" : $arg;
  478.  
  479.   if ($arg eq "legacy") {
  480.     $diroption = "uninstall";
  481.     $operation = "legacy uninstallation";
  482.   } elsif ($arg eq "uninstall") { 
  483.     $operation = "uninstallation";
  484.   } else {
  485.     $operation = "installation";
  486.   }
  487.  
  488.  
  489.   ###
  490.   ### create a misc directory if not present
  491.   ###
  492.  
  493.   if (-d $modulesdir) {
  494.       if (-d "$modulesdir/preferred") { 
  495.       checkDir("$modulesdir/preferred/misc", $diroption);
  496.       } else { 
  497.       checkDir("$modulesdir/$version/misc", $diroption);
  498.       }
  499.   }
  500.   
  501.   
  502.   if ((! defined($ENV{BINDIR}) ||
  503.        ! defined($ENV{MANDIR}) ||
  504.        ! defined($ENV{LIBDIR}) ||
  505.        ! defined($ENV{INITDIR}))
  506.       && $arg eq "host") {
  507.     print << "EOM";
  508.     
  509.     The host installation requires the knowledge of the site
  510.     installation directories, even though no files will be
  511.     installed in those directories.
  512.  
  513. EOM
  514.   }
  515.  
  516.   while (1) { 
  517.     $bindir = defined($ENV{BINDIR}) ? $ENV{BINDIR} :
  518.       query("Enter binaries $operation directory:",
  519.         "$defaultroot/bin");
  520.     
  521.     if (checkDir($bindir, $diroption)) { 
  522.       last;
  523.     } else {
  524.       if (defined($ENV{BINDIR})) { 
  525.         undef $ENV{BINDIR};
  526.       }
  527.     }
  528.   }
  529.   
  530.   if ($arg ne "legacy") { 
  531.     Log("answer BINDIR $bindir\n");
  532.   }
  533.  
  534.   if ($arg eq "all") { 
  535.     print << "EOM";
  536.     Binaries installation directory is $bindir.
  537.     This is the location of the executables.
  538. EOM
  539.   }
  540.  
  541.   $defaultroot = substr($bindir, 0, rindex($bindir, "/"));
  542.   
  543.   if ($arg eq "legacy") { 
  544.     while (1) {
  545.       $legacylibdir = query("Enter legacy library $operation directory:",
  546.                 "$defaultroot/lib/vmx86");
  547.       
  548.       if (checkDir($legacylibdir, $diroption)) { 
  549.         last;
  550.       } else {
  551.         if (defined($ENV{LIBDIR})) { 
  552.           undef $ENV{LIBDIR};
  553.         }
  554.       }
  555.     } 
  556.   }
  557.  
  558.   while (1) { 
  559.     $libdir = defined($ENV{LIBDIR}) ? $ENV{LIBDIR} :
  560.       query("Enter $operation directory for library files:",
  561.             "$defaultroot/lib/vmware");
  562.     
  563.     message("user entered $libdir\n");
  564.     if (checkDir("$libdir", $diroption)) {
  565.       last;
  566.     } else {
  567.       if (defined($ENV{LIBDIR})) { 
  568.         undef $ENV{LIBDIR};
  569.       }
  570.     }
  571.   }
  572.  
  573.   if ($arg ne "legacy") { 
  574.     Log("answer LIBDIR $libdir\n");
  575.   }
  576.   
  577.   
  578.   if ($arg eq "all") {
  579.     print << "EOM";
  580.     Library installation directory is $libdir.
  581.     This is the location of the library files.
  582. EOM
  583.   }
  584.  
  585.   while (1) { 
  586.     $mandir = defined($ENV{MANDIR}) ? $ENV{MANDIR} :
  587.       query("Enter $operation directory for manual pages:",
  588.             "$defaultroot/man");
  589.     
  590.     message("user entered $mandir\n");
  591.     if (checkDir("$mandir/man1", $diroption)) {
  592.       last;
  593.     } else {
  594.       if (defined($ENV{MANDIR})) { 
  595.         undef $ENV{MANDIR};
  596.       }
  597.     }
  598.   }
  599.  
  600.   if ($arg ne "legacy") { 
  601.     Log("answer MANDIR $mandir\n");
  602.   }
  603.   
  604.   
  605.   if ($arg eq "all") {
  606.     print << "EOM";
  607.     Manual installation directory is $mandir.
  608.     This is the location of the manual pages.
  609. EOM
  610.   }
  611.  
  612.   while (1) { 
  613.     
  614.     $initdir = defined($ENV{INITDIR}) ? $ENV{INITDIR} :
  615.       query("Enter the top directory under which the init scripts reside.  " .
  616.         "It should contain\n" .
  617.             "init.d/, rc2.d/, rc3.d/, rc5.d/, and rc6.d/:",
  618.         "$default_initdir");
  619.     
  620.     if (checkDir("$initdir/init.d", $diroption) && 
  621.         checkDir("$initdir/rc2.d", $diroption) &&
  622.         checkDir("$initdir/rc3.d", $diroption) &&
  623.         checkDir("$initdir/rc5.d", $diroption) &&
  624.         checkDir("$initdir/rc6.d", $diroption)) { 
  625.       last;
  626.     } 
  627.   }  
  628.   
  629.   if ($arg ne "legacy") { 
  630.     Log("answer INITDIR $initdir\n");
  631.   }
  632.   
  633.   print << "EOM";
  634. The boot-time init script will be stored under $initdir.
  635. This is the location of the script that loads the vmware
  636. kernel modules on reboot.
  637. EOM
  638.  
  639. }
  640.  
  641. sub MakeBackup {
  642.     my ($file) = @_;
  643.     my $i;
  644.  
  645.     while (1) {
  646.       TRY:
  647.     for $i (1..99) {
  648.         if (! -e $file . ".old." . $i) {
  649.         rename($file, $file . ".old." . $i) or
  650.             warn "### Cannot rename $file to $file.old.$i: $!.\n";
  651.         print "File $file is backed up to $file.old.$i.\n";
  652.         return;
  653.         }
  654.     }
  655.     print << "EOM";
  656. You have too many backup copies of file $file.
  657. They are in the form $file.old.N, where N is a number.
  658. Please remove them, then press <RETURN>.
  659. EOM
  660.         <STDIN>;
  661.    }
  662. }
  663.  
  664.  
  665. sub Install {
  666.   my ($mode, $src, $dst) = @_;
  667.   my ($sh_bindir, $sh_initdir, $sh_vmware_etc, $sh_net_ifc);
  668.  
  669.   if (-e $dst) {
  670.       die "\n### File $dst should not exist.\n" .
  671.       "### Please remove it and try again.\n";
  672.   }
  673.  
  674.   open(SRC, "<$src") or die "\n### open: $src: $!.\n";
  675.   open(DST, ">$dst") or die "\n### open: $dst: $!.\n";
  676.   chmod $mode, $dst or die "\n### chmod $dst: $!.\n";
  677.  
  678.   if ($src =~ /\.dist$/) {        # Need to make changes to contents
  679.     $sh_bindir = shell_string($bindir);
  680.     $sh_initdir = shell_string($initdir);
  681.     $sh_vmware_etc = shell_string($vmware_etc);
  682.     $sh_net_ifc = shell_string($net_ifc);
  683.  
  684.     while(defined($_ = <SRC>)) {
  685.       s/%BINDIR%/$sh_bindir/g;
  686.       s/%INITDIR%/$sh_initdir/g;
  687.       s/%ETCDIR%/$sh_vmware_etc/g;
  688.       s/%NETWORKINTERFACE%/$sh_net_ifc/g;
  689.        
  690.       print DST $_;
  691.     }
  692.   } else {                # Just copy
  693.     while(defined($_ = <SRC>)) {
  694.       print DST $_;
  695.     }
  696.   }
  697.  
  698.   close(SRC);
  699.   close(DST);
  700.  
  701.   LogFile($dst);
  702. }
  703.  
  704. #
  705. # Identify the flavor of system we're installing on.
  706. #
  707. sub identifyPlatform {
  708.   my $issue = '/etc/issue';
  709.   my $system;
  710.  
  711.   # First use the accurate method that are intended to work reliably on recent
  712.   # distributions (if an FHS guy is listening, we really need a generic way to
  713.   # do this)
  714.   if (-e '/etc/debian_version') {
  715.     return 'debian';
  716.   }
  717.   if (-e '/etc/redhat-release') {
  718.     return 'redhat';
  719.   }
  720.   if (-e '/etc/SuSE-release') {
  721.     return 'suse';
  722.   }
  723.  
  724.   # Then use less accurate methods that should work even on old distributions,
  725.   # if people haven't customized their system too much
  726.   if (-e $issue) {
  727.     $system = direct_command(shell_string($grep) . ' -i ' . shell_string('red *hat') . " " . shell_string($issue)) && "redhat" ||
  728.       direct_command(shell_string($grep) . ' -i ' . shell_string('suse\|s\.u\.s\.e') . " " . shell_string($issue)) && "suse" ||
  729.     direct_command(shell_string($grep) . ' -i ' . shell_string('caldera') . " " . shell_string($issue)) && "caldera" ||
  730.       direct_command(shell_string($grep) . ' -i ' . shell_string('debian') . " " . shell_string($issue)) && "debian" ||
  731.         "unknown";
  732.   } else {
  733.     $system = "unknown";
  734.   }
  735.   return $system;
  736. }
  737.  
  738.  
  739. sub checkHostPlatform {
  740.   my($sysname, $f_release, $release, $d_release, $answer, $threecom);
  741.   
  742.   chop($sysname = direct_command(shell_string($uname) . ' -s'));
  743.   
  744.   if ($sysname ne "Linux") {
  745.     die "\n### You are not running Linux.\n" .
  746.       "### This version of the product is for Linux only.\n";
  747.   }
  748.  
  749.   ($f_release, $release, $d_release) = Kernel_RunningVersion();
  750.   if ($d_release < Kernel_MakeVersion(2, 0, 0)) {
  751.     die "\n### You are running Linux release $release.\n" .
  752.       "### This product only runs on 2.0 and later kernels.\n";
  753.   }
  754.  
  755.   $threecom = !(-e "/proc/ioports") || (direct_command(shell_string($grep) . ' -i ' . shell_string('3c90\|3c59') . ' /proc/ioports') ne "");
  756.   if ($threecom && ($d_release >= Kernel_MakeVersion(2, 0, 34)) && ($d_release <= Kernel_MakeVersion(2, 0, 35))) {
  757.     $answer =
  758.     query("The installation script has detected that you are\n" . 
  759.           "running Linux version $release possibly with a 3Com\n" .
  760.           "networking card.  Linux kernel versions 2.0.34 and 2.0.35\n" .
  761.           "have a bug in the 3Com driver that interacts badly with\n".
  762.           "this product.  Specifically, the real machine will\n".
  763.           "occasionally hang and will require a hard reset.\n" .
  764.           "This bug has been fixed in Linux 2.0.36.\n" .
  765.           "\n" .
  766.           "Do you want to continue the installation anyway?", "no");
  767.     ($answer =~ /^[yY]/) || exit(0);
  768.   }
  769. }
  770.  
  771.  
  772. sub BuildFailure {
  773.   my $base = shift;
  774.   my $driver_name = shift;
  775.  
  776.   print << "FATAL_VERSION";
  777.  
  778. The build of the kernel module $driver_name failed.
  779.  
  780. Please double check that $header_dir is the directory containing
  781. the header files for the currently running kernel version.
  782.  
  783. If you detect a mismatch, create a softlink and retry.
  784.  
  785. Please follow the following steps if you still have problems.
  786.  
  787. 1. untar '$base-only.tar'
  788. 2. cd into that directory
  789. 3a. On a UP kernel, type 'make'
  790. 3b  On an MP kernel, type 'make SUPPORT_SMP=1'
  791.  
  792. 4. If the compilation is successful, try installing the module:
  793.  
  794.     /sbin/insmod $base-<kernel version>
  795.  
  796. 5. If this step is successful, copy the module into the distribution directory
  797.    as $base-<kernel version>
  798.  
  799. Please file an incident report at http://www.vmware.com/support if you
  800. are still having problems. 
  801.  
  802. FATAL_VERSION
  803.     die "\n### Installation failed.\n";
  804. }
  805.  
  806.  
  807. ###  How brave are you?  This little uber-routine will try and automagically
  808. ### build the driver (and load it just to be sure).
  809. sub Build_Driver {
  810.   my ($base, $mod_base,$option) = @_;
  811.   my ($driver_name, $build_dir);
  812.   my $smp_string;
  813.  
  814.   #  Do this work in /tmp or TMPDIR b/c we need a local filsystem to avoid
  815.   # NFS vs. root permission problems.
  816.   $build_dir = defined($ENV{TMPDIR}) ? $ENV{TMPDIR} : "/tmp";
  817.  
  818.   die "\n### Cannot untar and build driver in $build_dir.  " .
  819.       "Please set \$TMPDIR.\n"
  820.      unless -d "$build_dir";
  821.   
  822.   $build_dir = "$build_dir/vmware-tmp";
  823.  
  824.   if (not -d "$build_dir") {
  825.     $createdBuildDir = $build_dir;
  826.     mkdir "$build_dir", 0700 or 
  827.        die "\n### Unable to create $build_dir: $!.\n";
  828.   }
  829.  
  830.   # Okay, let's see if we have a tarfile?
  831.   if (-r $base . '-only.tar') {
  832.     message('Extracting ' . $base . ' source from ' . $base . '-only.tar\n');
  833.     system(shell_string($tar) . ' -C ' . shell_string($build_dir) . ' -xf ' . shell_string($base . '-only.tar')) and warn "Unable to untar.\n";
  834.   }
  835.  
  836.   # Now let's see if we have source?
  837.   if (! -r $build_dir . '/' . $base . '-only/Makefile') {
  838.     die << "EOM";
  839.  
  840. Unable to find $base source.  Either copy $base-only.tar to the current
  841. directory from the distribution or untar it yourself into the current
  842. directory.  If your distribution did not contain $base source, please 
  843. contact http://www.vmware.com for information about obtaining a working 
  844. module.
  845.  
  846. EOM
  847.   }
  848.  
  849.   ####
  850.   #### we now support egcs 
  851.   ####
  852.   
  853.   if (0) { 
  854.     # Fail if gcc on this system is the EGCS compiler.
  855.     
  856.     if (direct_command(shell_string($gcc) . ' --version | ' . shell_string($grep) . ' -i egcs') ne "") {
  857.       die "\n### The default gcc on this system is EGCS, which is not\n" .
  858.         "### compatible with this software.\n";
  859.     }
  860.   }
  861.  
  862.   # Okay, now let's see how good we are.
  863.   $driver_name = $mod_base . $version;
  864.   if ($smp) {
  865.     $smp_string = ' ' . shell_string('SUPPORT_SMP=1');
  866.   } else {
  867.     $smp_string = '';
  868.   }
  869.  
  870.   message "Building the $base with multi-processor support\n";
  871.   system(shell_string($make) . ' -C ' . shell_string($build_dir . '/' . $base . '-only/') . ' auto-build' . $smp_string . ' ' . shell_string('HEADER_DIR=' . $header_dir)) and BuildFailure($base, $driver_name);
  872.   
  873.   # Did it work, did it work?
  874.   message "Verifying the build worked\n";
  875.   # Don't use the force flag: the module is supposed to perfectly load
  876.   if (Try_Insmod($driver_name, $build_dir, 0)) {
  877.     print "Build was successful: Driver name is $driver_name\n";
  878.   } else {
  879.     BuildFailure($base, $driver_name);
  880.   }
  881.  
  882.   return ($driver_name, $build_dir);
  883. }
  884.  
  885.  
  886.  
  887. sub Try_Insmod {
  888.   my $mod_name = shift;
  889.   my $path = shift;
  890.   my $force = shift;
  891.   my $retval;
  892.  
  893.   $retval = direct_command(shell_string($insmod) . ($force ? ' -f ' : ' ') . shell_string($path . '/' . $mod_name) . ' 2>&1');
  894.   if ($? != 0) {
  895.     print $retval;
  896.     if ($retval =~ /Device or resource busy/) {
  897.       die << "EOM";
  898.  
  899. ### Either you currently have a VM running, or another module is
  900. ### currently using the device number required by our device
  901. ### driver.  Please make certain all VM's are exited, and that
  902. ### you have either done an uninstall already or are doing an
  903. ### upgrade installation. If you still get this message, please
  904. ### contact http://www.vmware.com/support.
  905.  
  906. EOM
  907.     }
  908.     return 0;
  909.   } else {
  910.     system(shell_string($rmmod) . ' ' . shell_string($mod_name)) and 
  911.       warn "Able to load $mod_name, but not unload it!\n";
  912.     return 1;
  913.   }
  914. }
  915.  
  916. ###  This routine goes through a distribution directory and tries to find a
  917. ### vm* driver that it can successfully load, or else it tries to build
  918. ### one.  It returns the name of the file that contains a valid driver.  It
  919. ### gets passed the base of the module (vnet or driver)
  920.  
  921.  
  922. sub Find_Module {
  923.   my ($base,$option)   = @_;
  924.   my $mod_base;
  925.   my @options = ();
  926.   my ($ideal, $guess, $driver, $driver_path,$envVar);
  927.   
  928.   $mod_base = $base . ($smp ? '-smp-' : '-up-');
  929.  
  930.   $driver_path = ".";
  931.   $ideal = $mod_base . $version;
  932.   if (-r $ideal) {
  933.     message "Using ideal driver $ideal\n";
  934.     if (Try_Insmod($ideal, ".", -e '.' . $ideal . 'versioned')) {
  935.       message "Success!  Using $ideal.\n";
  936.       $driver = $ideal;
  937.     } else {
  938.       warn "Unable to use $ideal, please rebuild it locally\n";
  939.     }
  940.   } else {
  941.     print "No exact match for $ideal.  Checking for working alternatives.\n";
  942.     ($guess = $ideal) =~ s/.$//;
  943.     @options = glob("$guess?");
  944.     if ($#options == -1) {
  945.       warn "No alternatives found, please build a driver locally\n";
  946.     } else {
  947.       message "Identifying a match that works with this kernel " .
  948.         "(ignore any errors)\n";
  949.       foreach $guess (@options) {
  950.         ($driver = $guess and last) if Try_Insmod($guess, ".", -e '.' . $guess . 'versioned');
  951.       }
  952.     }
  953.   }
  954.   
  955.   if (defined($driver)) {
  956.     print "Module '$driver' detected to work correctly\n";
  957.   } else {
  958.     print "None of the prebuilt modules seems to work on this machine.\n";
  959.     $envVar = "BUILDR_$base";
  960.     message("ENV $envVar \n");
  961.  
  962.     if (defined($ENV{$envVar})) {
  963.       $_ = $ENV{$envVar};
  964.     } elsif ($option eq "default") { 
  965.       $_ = "yes";
  966.     } else { 
  967.       $_ = query("This script can try and build one for you." .
  968.          "  Would you like to try?", "yes");
  969.     }
  970.     
  971.     Log("answer $envVar $_\n");
  972.     
  973.     if (/^[Nn]/) {
  974.         die << "EOM";
  975.  
  976. ### Not building automatically.  To build by hand, please do the following:
  977. ###        
  978. ###     tar xf $base-only.tar
  979. ###     cd $base-only
  980. ###     make
  981. ###              
  982. ### and then verify that the module in
  983. ###             
  984. ###     $base-$version/$ideal
  985. ###                  
  986. ### will load.
  987.  
  988. EOM
  989.      } else {
  990.        if ($header_dir eq '') {
  991.      if (identifyPlatform() eq "debian") {
  992.        # Debian doesn't always put the headers of the running kernel as
  993.        # in /usr/src/linux/include
  994.        $header_dir = query("What is the directory containing the header files for the running kernel?", '/usr/src/linux/include');
  995.      } else {
  996.        $header_dir = '/usr/src/linux/include';
  997.      }
  998.        }
  999.  
  1000.        #
  1001.        # Let's be prepared to use build tools
  1002.        #
  1003.        $ksyms = DoesBinaryExist_Prompt('ksyms');
  1004.        if ($ksyms eq "") {
  1005.      print STDERR "\nUnable to continue.\n";
  1006.      exit(1);
  1007.        }
  1008.  
  1009.        $make = DoesBinaryExist_Prompt('make');
  1010.        if ($make eq "") {
  1011.      print STDERR "\nUnable to continue.\n";
  1012.      exit(1);
  1013.        }
  1014.  
  1015.        $gcc = DoesBinaryExist_Prompt('gcc');
  1016.        if ($gcc eq "") {
  1017.      print STDERR "\nUnable to continue.\n";
  1018.      exit(1);
  1019.        }
  1020.  
  1021.        #
  1022.        # If a 2.0 kernel, verify that it was built with CONFIG_UMISC 
  1023.        #
  1024.        if ($version =~ /^2[.]0[.]/) {
  1025.       if (open(KSYMS, shell_string($ksyms) . ' -a |')) {
  1026.           my $misc = 0;
  1027.           while (<KSYMS>) {
  1028.              if (/^[0-9a-fA-F]+[ \t]*misc_register/) {
  1029.             $misc |= 1;
  1030.          } elsif (/^[0-9a-fA-F]+[ \t]*misc_deregister/) {
  1031.             $misc |= 2;
  1032.          }
  1033.           }
  1034.           close(KSYMS);
  1035.           if ($misc != 3) {
  1036.           die << "EOF";
  1037.  
  1038. ### You appear to have a $version Linux kernel that was not
  1039. ### built with the CONFIG_UMISC configuration parameter set.
  1040. ### The VMware software will not operate without this facility.
  1041. ### Please update your kernel to include this facility and then
  1042. ### redo the installation procedure.
  1043.  
  1044. EOF
  1045.           }
  1046.       } else {
  1047.           print << "EOF";
  1048.  
  1049. You have a $version Linux kernel but the ksyms program does not seems to
  1050. accept the -a option to dump all the kernel symbols.  We were trying to
  1051. verify that your kernel is configured with CONFIG_UMISC set.  If it is not
  1052. then the VMware device drivers will not build and/or load correctly.  You
  1053. should check if your system is misconfigured. 
  1054.  
  1055. EOF
  1056.          query("Do you want to continue anyway? (yes/no)", "yes") =~
  1057.          /^[Nn]/ && die "\n### Unable to setup to build drivers.\n";
  1058.       }
  1059.        }
  1060.  
  1061.        #
  1062.        # Verify the include files that will be used to build the drivers
  1063.        # corresponds to the running kernel. 
  1064.        #
  1065.        my $tempFile = "/tmp/vm" . $$ . ".c";
  1066.        if (open(TMPC, '>' . $tempFile)) {
  1067.       my $pat = '@@VERSION@@';
  1068.       print TMPC << "EOF";
  1069. #include <linux/version.h>
  1070. $pat UTS_RELEASE
  1071. EOF
  1072.       close(TMPC);
  1073.           my $incVersion = direct_command(
  1074.                '(echo default:; echo '
  1075.              . shell_string("\t" . '$(CC) -E -I$(HEADER_DIR) ' . $tempFile)
  1076.              . ') | '
  1077.              . shell_string($make)
  1078.              . ' -f - '
  1079.              . shell_string('HEADER_DIR=' . $header_dir)
  1080.              . ' | '
  1081.              . shell_string($grep)
  1082.              . ' '
  1083.              . shell_string($pat)
  1084.              . ' 2>/dev/null'
  1085.           );
  1086.           unlink($tempFile);
  1087.       chop($incVersion);
  1088.       $incVersion =~ s/$pat ["]([^"]+).*/$1/;
  1089.       if ($incVersion ne $version) {
  1090.          die << "EOF";
  1091.  
  1092. ### Something is wrong with the system include files on
  1093. ### your machine!  The file <linux/version.h> is for a
  1094. ### $incVersion Linux system but you are running a $version
  1095. ### kernel.  This will not work for building the VMware device
  1096. ### drivers; you must have include files that match the version
  1097. ### of your operating system.
  1098.  
  1099. EOF
  1100.       }
  1101.        } else {
  1102.           print << "EOF";
  1103.  
  1104. Something went wrong and I was unable to create the temporary file
  1105. $tempFile that I need to verify your include files correspond to
  1106. the version of the operating system you are running.  Beware that
  1107. if these include files are for a different version of Linux that
  1108. the VMware device drivers may not build and most likely will not
  1109. load and/or run correctly on this machine.
  1110.  
  1111. EOF
  1112.          query("Do you want to continue anyway? (yes/no)", "yes")
  1113.          =~ /^[Nn]/ && die "\n### Unable to setup to build drivers.\n";
  1114.        }
  1115.  
  1116.  
  1117.        ($driver, $driver_path) = &Build_Driver($base, $mod_base,$option);
  1118.      }
  1119.   }
  1120.   
  1121.   return ($driver, $driver_path);
  1122. }
  1123.  
  1124. sub printFindPingHelp {
  1125.     print << "EOF";
  1126.  
  1127. The ping program sends ICMP echo messages to a specific host and
  1128. listens for replies.  We use it when probing for an available
  1129. subnet for host-only networking to identify networks that are
  1130. not reachable from your host machine.  ping is normally installed
  1131. on your system in a standard location such as /bin, but it might
  1132. be somewhere unexpected in which case you must specify the full
  1133. UNIX pathname for the program.  If you do not identify where this
  1134. program is located then we cannot automatically locate a network
  1135. number to use and you must manually specify how to setup the
  1136. host-only network.
  1137.  
  1138. EOF
  1139. }
  1140.  
  1141. sub findPing {
  1142.     my $answer;
  1143.     my $ping;
  1144.  
  1145.     # NB: add alternative locations for ping as needed
  1146.     $ping = "/bin/ping" if -e "/bin/ping";
  1147.     if ($ping eq "") {
  1148.     print "\n";
  1149.     print "Cannot locate the ping program in the expected locations.\n";
  1150.     do {
  1151.         $answer = query("What is the full pathname for the ping program" .
  1152.             "(e.g. /bin/ping)?", "");
  1153.         if (!(-e $answer)) {
  1154.         print "\nSorry that is not an executable program.\n";
  1155.         do {
  1156.             $answer = query("Try again? (yes/no/help)\n", "yes");
  1157.             printFindPingHelp() if $answer =~ /^[Hh]/;
  1158.             return ("") if $answer =~ /^[Nn]/;
  1159.         } until $answer =~ /^[Yy]/;
  1160.         } else {
  1161.         $ping = $answer;
  1162.         }
  1163.     } until $ping ne "";
  1164.     }
  1165.     return ($ping);
  1166. }
  1167.  
  1168. #
  1169. # Routine to generate an interfaces specification for smb.conf
  1170. # that lists each network interface on a Linux host that is
  1171. # marked "up".  We assume that ifconfig w/o any arguments will
  1172. # list all such interfaces.
  1173. #
  1174. # We also assume a bunch about the (convoluted) printing format of ifconfig.
  1175. # XXX Such asumptions are unfortunately wrong and break on my system with
  1176. # LANG=fr_FR
  1177. #
  1178. sub printSmbInterfaces {
  1179.     my @fields;
  1180.     my $_if = "";
  1181.     my $nif = 0;
  1182.     my (@ifs, %addrs, %masks);
  1183.  
  1184.     open(IFCONFIG, shell_string($ifconfig) . '|');
  1185.     while (<IFCONFIG>) {
  1186.     if (/^[a-zA-Z]/) {
  1187.         @fields = split(/[ ]+/);
  1188.         $_if = $fields[0];
  1189.         $ifs[$nif++] = $_if;
  1190.     } elsif (/inet addr/) {
  1191.         chop;
  1192.         ($addrs{$_if} = $_) =~ s/.*[iI]net [aA]ddr://;
  1193.         $addrs{$_if} =~ s/ .*//;
  1194.         ($masks{$_if} = $_) =~ s/.*[mM]ask://;
  1195.         $masks{$_if} =~ s/ .*//;
  1196.     }
  1197.     }
  1198.  
  1199.     my $s = "";
  1200.     my $sep = "";
  1201.     foreach $_if (@ifs) {
  1202.     if ($_if ne "" && $_if ne "lo") {
  1203.         my $mask = $masks{$_if};
  1204.         my @parts = split(/[.]/, $mask);
  1205.  
  1206.         my %map = (
  1207.         255, 8,
  1208.         254, 7,
  1209.         252, 6,
  1210.         248, 5,
  1211.         240, 4,
  1212.         224, 3,
  1213.         192, 2,
  1214.         128, 1,
  1215.         0,   0,
  1216.         );
  1217.         my $v;
  1218.         my $bits = 0;
  1219.  
  1220.         foreach $v (@parts) {
  1221.         $bits += $map{int($v)};
  1222.         }
  1223.         $s .= sprintf("%s%s/%d", $sep, $addrs{$_if}, $bits);
  1224.         $sep = " ";
  1225.     }
  1226.     }
  1227.     return $s;
  1228. }
  1229.  
  1230. sub doPing {
  1231.     my $ping = shift;
  1232.     my $addr = shift;
  1233.  
  1234.     #
  1235.     # Fork ping and set an alarm to go off in case the
  1236.     # program does not terminate (certain versions of
  1237.     # nettools apparently no longer timeout when waiting
  1238.     # for responses).
  1239.     #
  1240.     my $pid = fork;
  1241.     if ($pid == 0) {
  1242.     alarm(20);        # 2x ping's builtin timeout
  1243.     exec("$ping -n -c 2 $addr >/dev/null 2>&1");
  1244.     } elsif ($pid > 0) {
  1245.     if (waitpid($pid, 0) != -1) {
  1246.         if ($? == 14) {
  1247.         return 1;    # SIGALARM, assume no response
  1248.         } elsif ($? != 0x7e00) {
  1249.         return $?>>8;    # exit code from ping
  1250.         }
  1251.     }
  1252.     print "Something happened to $ping; assuming failure\n";
  1253.     } else {
  1254.     print "Cannot fork to start $ping program; assuming failure\n";
  1255.     }
  1256.     return 2;            # failure
  1257. }
  1258.  
  1259. sub probeForNetConfig {
  1260.     my $subnet;
  1261.     my $netmask = "255.255.255.0";    # XXX calculate dynamically
  1262.  
  1263.     message("\nProbing for an unused private network number:\n");
  1264.     my $ping = findPing();
  1265.     if ($ping ne "") {
  1266.     my $maxProbes = 100;
  1267.     my $maxPings = 10;
  1268.     #
  1269.     # Populate the table with potential addresses
  1270.     #
  1271.     my $i;
  1272.     my @nets;
  1273.     for ($i = 0; $i < 255; $i++) {
  1274.         $nets[2*$i]   = "192.168." . $i;
  1275.         $nets[2*$i+1] = "172.16."  . $i;
  1276.     }
  1277.     my $pings = 0;
  1278.     my $probes = 0;
  1279.     do {
  1280.         my $i = int(rand(2*255));
  1281.         if ($nets[$i] eq "") {
  1282.         next;
  1283.         }
  1284.         $subnet = $nets[$i];
  1285.         $nets[$i] = "";
  1286.         # by convention HOS is <net>.1
  1287.         my $probeAddress = $subnet . ".1";
  1288.         message("    ping $probeAddress...");
  1289.         #
  1290.         # ping exits with:
  1291.         #   1 if no replys
  1292.         #   2 if an error
  1293.         #   0 otherwise
  1294.         #
  1295.         my $status = doPing($ping, $probeAddress);
  1296.         if ($status == 1) {
  1297.         message("(no response)\n");
  1298.         print "Network number $subnet (netmask $netmask) " .
  1299.             "appears unused.\n";
  1300.         return ($probeAddress, $netmask);
  1301.         } elsif ($status == 2) {
  1302.         message("(error)\n");
  1303.         last;
  1304.         }
  1305.         message("(answered)\n");
  1306.         $pings++;
  1307.     } while ($pings < $maxPings && ++$probes < $maxProbes);
  1308.     }
  1309.     print << "EOF";
  1310.  
  1311. We were unable to locate an unused Class C subnet in the range
  1312. of private network numbers.  For each subnet that we tried we
  1313. received a response to our ICMP ping packets from a host at the
  1314. network address intended for assignment to this host machine.
  1315. Because no private subnet appears to be unused you will need to
  1316. explicitly specify a network number.
  1317.  
  1318. EOF
  1319.     return ("", "");
  1320. }
  1321.  
  1322. sub promptForNetConfig {
  1323.     my $hostaddr = "";
  1324.     my $netmask = "";
  1325.     my $answer;
  1326.  
  1327.     do {
  1328.     do {
  1329.         $answer = query("Host address (use a.b.c.d format)?", $hostaddr);
  1330.         if ($answer !~ /^[1-9][0-9]{0,2}([.][0-9]{1,3}){3}$/) {
  1331.         print << "EOF";
  1332.  
  1333. Not an acceptable host address.  Please specify a Class C network
  1334. or subnet; i.e. something of the form a.b.c.d where a,b,c, and d are
  1335. decimal numbers.  For example, 192.168.0.1 is a valid host address on
  1336. a private network.
  1337.  
  1338. EOF
  1339.         $answer = "";
  1340.         }
  1341.     } until $answer ne "";
  1342.     $hostaddr = $answer;
  1343.     $answer = "";
  1344.     do {
  1345.         $answer = query("Network mask (use a.b.c.d format)?", $netmask);
  1346.         if ($answer !~ /^[1-9][0-9]{0,2}([.][0-9]{1,3}){3}$/) {
  1347.             print << "EOF";
  1348.  
  1349. Sorry, that does not look like a valid netmask.  Please specify a mask
  1350. using the format a.b.c.d where a,b,c and d are decimal numbers.  For
  1351. example, if you specified a Class C network above then your netmask
  1352. would be 255.255.255.0.
  1353.  
  1354. EOF
  1355.         $answer = "";
  1356.         }
  1357.     } until $answer ne "";
  1358.     $netmask = $answer;
  1359.  
  1360.     $answer = query("Use address $hostaddr and mask $netmask? (yes/no)",
  1361.             "yes");
  1362.     } until $answer =~ /^[Yy]/;
  1363.     return ($hostaddr, $netmask);
  1364. }
  1365.  
  1366. sub writeDHCPConfigFile {
  1367.     my $hostaddr = shift;
  1368.     my $netmask = shift;
  1369.     my $net;
  1370.  
  1371.     ($net = $hostaddr) =~ s/[.][0-9]+$//;
  1372.  
  1373.     # XXX deal with open errors
  1374.     open(DHCPCONFIG, ">$vmware_etc/$vmnet1.conf");
  1375.     # XXX this would be a here document but perl keeps barfing on it
  1376.     my $handle = select(DHCPCONFIG);
  1377.     print << "EOF";
  1378. #
  1379. # Configuration file for ISC 2.0b6pl1 vmnet-dhcpd operating on $vmnet1.
  1380. #
  1381. # Beware, this file was generated by the VMware installation
  1382. # script.  If you modify it, it will be clobbered the next time
  1383. # you run the installation script (TO BE FIXED).
  1384. #
  1385. allow unknown-clients;
  1386. default-lease-time 1800;        # 30 minutes
  1387. max-lease-time 7200;            # 2 hours
  1388.  
  1389. subnet $net.0 netmask $netmask {
  1390.     range $net.128 $net.254;        # up to 126 VM's
  1391.     option domain-name-servers $hostaddr;    # by convention use HOS
  1392.     option broadcast-address $net.255;
  1393. }
  1394. EOF
  1395.     select($handle);
  1396.     close(DHCPCONFIG);
  1397.  
  1398.     Log("answer VNET_HOSTONLY_HOSTADDR $hostaddr\n");
  1399.     Log("answer VNET_HOSTONLY_NETMASK $netmask\n");
  1400.     LogFile("$vmware_etc/$vmnet1.conf");
  1401. }
  1402.  
  1403.  
  1404. sub printHostOnlyHelp {
  1405.     print << "EOF";
  1406.  
  1407. Virtual machines configured to use host-only networking are placed on
  1408. a virtual network that is confined to this host.  Virtual machines on
  1409. this network can communicate with each other and the host, but no one else.
  1410.  
  1411. To setup this host-only networking you need to select a network number
  1412. that is unreachable from the host.  We can automatically select this
  1413. number for you, or you can specify a network number that you want.
  1414.  
  1415. The automatic selection process works by testing a series of Class C
  1416. subnet numbers to see if they are reachable from the host.  The first
  1417. one that is unreachable is used.  The subnet numbers are chosen from the
  1418. private network numbers specified by the Internet Engineering Task Force
  1419. (IETF) in RFC 1918 (http://www.isi.edu/in-notes/rfc1918.txt).
  1420.  
  1421. Remember that the host-only network that virtual machines reside on
  1422. will not be accessible outside the host.  This means that it is ok to
  1423. use the same number on different systems so long as you do not enable
  1424. communication between these networks.
  1425.  
  1426. EOF
  1427. }
  1428.  
  1429. sub promptForHostOnlyNetworkConfig {
  1430.     my $hostaddr = "";
  1431.     my $netmask = "";
  1432.     my $firstTime = 1;
  1433.     my $answer;
  1434.  
  1435.     while ($hostaddr eq "" || $netmask eq "") {
  1436.     #
  1437.     # First ask if probing should be tried.
  1438.     #
  1439.     do {
  1440.         $answer = query("Probe for an unused network number? " .
  1441.                 "(yes/no/help)", "yes");
  1442.         if ($answer =~ /^[Yy]/) {
  1443.         ($hostaddr, $netmask) = probeForNetConfig();
  1444.         next;
  1445.         }
  1446.         printHostOnlyHelp() if $answer =~ /^[Hh]/;
  1447.     } until $answer =~ /^[Nn]/;
  1448.  
  1449.     #
  1450.     # No probing; ask if they want to hand config it.
  1451.     #
  1452.     do {
  1453.         $answer = query("Specify a host address? (yes/no/help)", "yes");
  1454.         if ($answer =~ /^[Yy]/) {
  1455.         ($hostaddr, $netmask) = promptForNetConfig();
  1456.         next;
  1457.         }
  1458.         printHostOnlyHelp() if $answer =~ /^[Hh]/;
  1459.     } until $answer =~ /^[Nn]/;
  1460.  
  1461.     #
  1462.     # Give them some help (the first time through the loop)
  1463.     # and then give them a chance to abort configuring host-only
  1464.     # networking.
  1465.     #
  1466.     if ($firstTime != 0 || $answer =~ /^Hh/) {
  1467.         $firstTime = 0;
  1468.         printHostOnlyHelp();
  1469.     } else {
  1470.         print << "EOM";
  1471.  
  1472. ### To configure host-only networking, you need to either probe
  1473. ### for an unused network number, or specify a host address.
  1474.  
  1475. EOM
  1476.         }
  1477.     $answer = query("Do you want to configure host-only networking? " .
  1478.             "(yes/no/help)", "yes");
  1479.     if ($answer =~ /^[Nn]/) {
  1480.         last;
  1481.     }
  1482.     printHostOnlyHelp() if $answer =~ /^[Hh]/;
  1483.     }
  1484.     return ($hostaddr, $netmask);
  1485. }
  1486.  
  1487. sub setupHostOnlyNetworkConfig {
  1488.     my $hostaddr = shift;
  1489.     my $netmask = shift;
  1490.     my $net;
  1491.  
  1492.     ($net = $hostaddr) =~ s/\.[0-9]+$//;
  1493.  
  1494.     print "\nConfiguring vmnet1 to use host address $hostaddr " .
  1495.     "and mask $netmask.\n";
  1496.  
  1497.     if (not defined($ENV{VNET_HOSTONLY})) {
  1498.     # don't print for an upgrade, only a clean install
  1499.     printISCCopyrightInfo();
  1500.     }
  1501.     #
  1502.     # 1. Setup the DHCP daemon:
  1503.     #    write a config file for the DHCP daemon
  1504.     #    setup a null leases file
  1505.     # 2. Configure the vnet1 interface (done by boot-time script).
  1506.     # 3. Add a route for vnet1 since it doesn't get done 
  1507.     #    when the interface is marked up (done by boot-time script).
  1508.     # 4. Record the net and mask in the global config file
  1509.     #    so the boot-time script will start DHCPD (done below).
  1510.     #
  1511.     # XXX save existing .conf and .leases files
  1512.     print "Creating $vmware_etc/$vmnet1.conf for vmnet-dhcpd\n"; 
  1513.     writeDHCPConfigFile($hostaddr, $netmask);
  1514.  
  1515.     print "Creating empty leases file $vmware_etc/$vmnet1.leases " .
  1516.     "for vmnet-dhcpd\n";
  1517.     # XXX deal with errors
  1518.     open(DHCPLEASES, ">$vmware_etc/$vmnet1.leases");
  1519.     close(DHCPLEASES);
  1520.     LogFile("$vmware_etc/$vmnet1.leases");
  1521.     # XXX also include backup file dhcpd creates
  1522.     Log("file $vmware_etc/$vmnet1.leases~\n");
  1523.  
  1524.     #
  1525.     # If the host looks to have dhcpd setup then check if
  1526.     # it's configured to ignore our subnet.  If not warn
  1527.     # them that they should do this or they may encounter
  1528.     # problems.
  1529.     #
  1530.     if (-f '/etc/dhcpd.conf' && direct_command(shell_string($grep) . ' -c ' . shell_string('^[ \t]*subnet[ \t]*' . $net . '\.0') . ' /etc/dhcpd.conf') eq "") {
  1531.         print << "EOF";
  1532.  
  1533. You appear to have dhcpd configured for normal use.  Beware that
  1534. you should modify the /etc/dhcpd.conf file to define the subnet
  1535. created for VMware's host-only network; otherwise dhcpd will fail
  1536. to run if it is started with the $vmnet1 network interface enabled.
  1537. A possible subnet configuration to add to dhcpd.conf is:
  1538.  
  1539. subnet $net.0 netmask $netmask {
  1540.     # note that no range is given so dhcpd will not try to
  1541.     # assign IP addresses; this must be done by vmnet-dhcpd
  1542. }
  1543.  
  1544. If you do not want to edit dhcpd.conf then you need to always start
  1545. the program with an explicit list of your network interfaces (leaving
  1546. out $vmnet1); e.g.
  1547.  
  1548. dhcpd eth0
  1549.  
  1550. Consult the dhcpd(8) and dhcpd.conf(5) manual pages for details.
  1551.  
  1552. EOF
  1553.     query("Hit return to continue:", "");
  1554.     }
  1555.  
  1556.     #
  1557.     # If the host looks to have samba setup then check if
  1558.     # it's configured to respond on our subnet.  If not then
  1559.     # warn them that they must list the interface explicitly
  1560.     # if they want to server VMs on the host-only subnet.
  1561.     #
  1562.     if (-f '/etc/smb.conf' && direct_command(shell_string($grep) . ' -c ' . shell_string('^[ \t]*interfaces[ \t]*=.*' . $net) . ' /etc/smb.conf') eq "") {
  1563.     my $interfaces = printSmbInterfaces;
  1564.         print << "EOF";
  1565.  
  1566. You appear to have Samba configured for normal use.  Note that
  1567. if you want to offer service to virtual machines running on the
  1568. host-only network that you must update your /etc/smb.conf file
  1569. to list the network interfaces on your system by adding the line:
  1570.  
  1571. interfaces = $interfaces $hostaddr/24
  1572.  
  1573. You may also need to update any related security controls you
  1574. might have setup such as the "hosts allow" specification.
  1575.  
  1576. Consult the smb.conf(5) manual page for more details.
  1577.  
  1578. EOF
  1579.     query("Hit return to continue:", "");
  1580.     }
  1581.     print "\n";
  1582. }
  1583.  
  1584. sub printISCCopyrightInfo() {
  1585.   # $more is already a shell string
  1586.   system($more . ' DHCP-COPYRIGHT');
  1587.   print "\n";
  1588.   query("Hit return to continue:", "");
  1589.   print "\n";
  1590. }
  1591.  
  1592.  
  1593. sub configureHostOnlyNetworking {
  1594.     my $hostaddr = "";
  1595.     my $netmask = "";
  1596.     my $answer;
  1597.  
  1598.     if (not defined($ENV{VNET_HOSTONLY})) {
  1599.     print "\n";
  1600.     do {
  1601.         $answer = query("Configure host-only networking support? " .
  1602.                 "(yes/no/help)", "yes");
  1603.         printHostOnlyHelp() if !($answer =~ /^[YyNn]/);
  1604.     } until $answer =~ /^[YyNn]/;
  1605.     if ($answer =~ /^[Yy]/) {
  1606.         ($hostaddr, $netmask) = promptForHostOnlyNetworkConfig();
  1607.         # check if user aborted at lower-level prompt
  1608.         $answer = "no" if ($hostaddr eq "" and $netmask eq "");
  1609.     }
  1610.     } else {
  1611.     $answer = $ENV{VNET_HOSTONLY};
  1612.     $hostaddr =
  1613.         defined($ENV{VNET_HOSTONLY_HOSTADDR}) ?
  1614.         $ENV{VNET_HOSTONLY_HOSTADDR} :
  1615.         defined($ENV{VNET_HOSTONLY_NETWORK}) ?
  1616.         $ENV{VNET_HOSTONLY_NETWORK} . ".1" : "";
  1617.     $netmask = defined($ENV{VNET_HOSTONLY_NETMASK}) ?
  1618.         $ENV{VNET_HOSTONLY_NETMASK} : "";
  1619.     }
  1620.     setupHostOnlyNetworkConfig($hostaddr, $netmask) if ($answer =~ /^[Yy]/);
  1621.     Log("answer VNET_HOSTONLY $answer\n");
  1622.     return ($hostaddr, $netmask);
  1623. }
  1624.  
  1625. sub ChooseNetworkInterface {
  1626.  
  1627.     my (@fields, $inf, @infs);
  1628.     my $ninfs = 0;
  1629.     my $question;
  1630.     my $previous = "";
  1631.     my $answer;
  1632.  
  1633.     # The -a is important because it lists all interfaces (not only those
  1634.     # which are up). The vmnet driver knows how to deal with down interfaces.
  1635.     open(IFCONFIG, shell_string($ifconfig) . ' -a |');
  1636.     while (<IFCONFIG>) {
  1637.     if (/^eth[0-9]/) {
  1638.         @fields = split(/[ ]+/);
  1639.         $inf = $fields[0];
  1640.         $infs[$ninfs++] = $inf;
  1641.     }
  1642.     }
  1643.     message('Found ' . $ninfs . ' ethernet interfaces: ' . join(' ', @infs));
  1644.  
  1645.     if ($ninfs > 1) {
  1646.     if (not defined($ENV{VNET_INTERFACE})) {
  1647.         print "\nYour computer has multiple network interfaces.\n";
  1648.         $question = "Please choose one of ";
  1649.         foreach $inf (@infs) {
  1650.         if ($previous ne "") {
  1651.             $question .= $previous . ", ";
  1652.         }
  1653.         $previous = $inf;
  1654.         }
  1655.         $question .= "or $previous: ";
  1656.  
  1657.         for (;;) {
  1658.         $answer = query($question, $infs[0]);
  1659.         if (grep(/$answer/, @infs)) {
  1660.             last;
  1661.         }
  1662.         }
  1663.     } else {
  1664.       $answer = $ENV{VNET_INTERFACE};
  1665.     }
  1666.     $net_ifc = $answer;
  1667.     }
  1668.     Log("answer VNET_INTERFACE $net_ifc\n")
  1669. }
  1670.  
  1671. sub Install_Module2 {
  1672.     my ($source, $dest, $destdir) = @_;
  1673.     if (-d $destdir) {
  1674.     -d "$destdir/misc"
  1675.         or mkdir "$destdir/misc", 0755
  1676.         or die "\n### Cannot create directory $destdir/misc: $!\n";
  1677.     &Install(0444, $source, "$destdir/misc/$dest");
  1678.     return 1;
  1679.     } else {
  1680.     return 0;
  1681.     }
  1682. }
  1683.  
  1684. sub Install_Module {
  1685.     my ($src, $dest, $dir) = @_;
  1686.     &Install_Module2($src, $dest, "$dir/preferred")
  1687.     or &Install_Module2($src, $dest, "$dir/$version")
  1688.         or die "\n### Unable to install kernel module $dest in either\n" .
  1689.         "### $dir/preferred or $dir/$version.\n\n";
  1690. }
  1691.  
  1692.  
  1693. # Install a pair of S/K startup scripts for a given runlevel
  1694. sub Install_StartupScript {
  1695.    my $level = $_[0];
  1696.  
  1697.    # Create the S symlink
  1698.    #
  1699.    # We use 90 because samba is at 91 and it didn't like it
  1700.    # when we used 99.
  1701.    #
  1702.    symlink "../init.d/vmware", $initdir . '/rc' . $level . '.d/S90vmware'
  1703.       or warn "### symlink ../init.d/vmware to $initdir/rc" . $level . ".d: $!.\n";
  1704.    LogFile($initdir . '/rc' . $level . '.d/S90vmware');
  1705.  
  1706.    # Create the K symlink
  1707.    #
  1708.    # Note: SuSE 6.0 handles startup scripts differently (I actually like it).
  1709.    # When entering a new runlevel, K* scripts of the _old_ runlevel are
  1710.    # executed instead of those of the new runlevel
  1711.    if (not (identifyPlatform() eq 'suse')) {
  1712.       # Kill the services in the reboot runlevel
  1713.       $level = 6;
  1714.    }
  1715.    symlink "../init.d/vmware", $initdir . '/rc' . $level . '.d/K08vmware'
  1716.       or warn "### symlink ../init.d/vmware to $initdir/rc" . $level . ".d: $!.\n";
  1717.    LogFile($initdir . '/rc' . $level . '.d/K08vmware');
  1718. }
  1719.  
  1720. sub DealWithVmppuser {
  1721.   my $option = shift;
  1722.   my ($f_release, $release, $d_release);
  1723.   my ($ppuser, $ppuser_src, $ppuser_path);
  1724.  
  1725.   ($f_release, $release, $d_release) = Kernel_RunningVersion();
  1726.  
  1727.   if ($d_release < Kernel_MakeVersion(2, 1, 127)) {
  1728.     print << "EOM";
  1729.  
  1730. Your machine appears to be running Linux version $release, and this
  1731. kernel can not provide VMware with Bidirectional Parallel Port support.
  1732. A fully-featured VMware requires Linux version 2.1.127 or higher.
  1733.  
  1734. Without this support, VMware will run flawlessly, but will lack the ability
  1735. to use parallel ports in a bidirectional way. This means that it is possible
  1736. that some parallel port devices (scanners, dongles, ...) will not work inside
  1737. a Virtual Machine.
  1738.  
  1739. EOM
  1740.    return;
  1741.   }  
  1742.  
  1743.   if ($d_release > Kernel_MakeVersion(2, 3, 9)) {
  1744.     print << "EOM";
  1745.  
  1746. Your machine appears to be running Linux version $release, and VMware does
  1747. not provide support for Bidirectional Parallel Ports for Linux version
  1748. 2.3.10 or higher yet.
  1749.  
  1750. Without this support, VMware will run flawlessly, but will lack the ability
  1751. to use parallel ports in a bidirectional way. This means that it is possible
  1752. that some parallel port devices (scanners, dongles, ...) will not work inside
  1753. a Virtual Machine.
  1754.  
  1755. EOM
  1756.    return;
  1757.   }  
  1758.   
  1759.   print "Finding an installable vmppuser module\n";
  1760.   #
  1761.   # The vmppuser module relies on the parport_pc and parport modules. Let's
  1762.   # make sure they are loaded before beginning our tests
  1763.   #
  1764.   if (system(shell_string($modprobe) . ' parport_pc') || system(shell_string($modprobe) . ' parport')) {
  1765.     print << "EOM";
  1766.  
  1767. This installation script is unable to load the parport_pc and parport modules
  1768. that are required by the vmppuser module. You may want to load them manually
  1769. before re-running this script.
  1770.  
  1771. Without this support, VMware will run flawlessly, but will lack the ability
  1772. to use parallel ports in a bidirectional way. This means that it is possible
  1773. that some parallel port devices (scanners, dongles, ...) will not work inside
  1774. a Virtual Machine.
  1775.  
  1776. EOM
  1777.   } else {
  1778.     ($ppuser_src, $ppuser_path) = Find_Module("vmppuser", $option);
  1779.     ($ppuser = $ppuser_src) =~ s/\./_/g;
  1780.     &Install_Module("$ppuser_path/$ppuser_src", "vmppuser", "$modulesdir");
  1781.     # Try to unload the modules. Failure is allowed because some other
  1782.     # process could be using them.
  1783.     system(shell_string($modprobe) . ' -r parport_pc');
  1784.     system(shell_string($modprobe) . ' -r parport');
  1785.   }
  1786. }
  1787.  
  1788. sub Host_Install {
  1789.   my $option = shift;
  1790.   my $networking;
  1791.   my $answer;
  1792.   my ($driver, $driver_src, $driver_path);
  1793.   my ($vnet, $vnet_src, $vnet_path);
  1794.   my $hostOnlyAddress;
  1795.   my $hostOnlyNetMask;
  1796.   my $i;
  1797.  
  1798.   checkHostPlatform();
  1799.   
  1800.   message("Installing host-specific files.\n");
  1801.     
  1802.   print "Finding an installable vmmon module\n"; 
  1803.   ($driver_src, $driver_path) = Find_Module("vmmon", $option);
  1804.   ($driver = $driver_src) =~ s/\./_/g;  
  1805.   &Install_Module("$driver_path/$driver_src", "vmmon", "$modulesdir");
  1806.   
  1807.   DealWithVmppuser($option);
  1808.  
  1809.   if (not $ENV{NETWORKING}) {
  1810.     if ($option eq "default") { 
  1811.       $answer = "yes";
  1812.     } else {
  1813.       $answer = query("Do you want to install vmnet (networking " .
  1814.                       "support for the VM)?", "yes");
  1815.     }
  1816.     $networking = ($answer =~ /^[yY]/);
  1817.     Log("answer NETWORKING $answer\n");
  1818.   } else {
  1819.     Log("answer NETWORKING $ENV{NETWORKING}\n");
  1820.     $networking = ($ENV{NETWORKING} =~ /^[yY]/);
  1821.   }
  1822.       
  1823.   if ($networking) {
  1824.     message("Installing networking support.\n");
  1825.     print "\nFinding an installable vmnet module\n";
  1826.     ($vnet_src, $vnet_path) = Find_Module("vmnet", $option);
  1827.     ($vnet = $vnet_src) =~ s/\./_/g;
  1828.     &Install_Module("$vnet_path/$vnet_src", "vmnet", "$modulesdir");
  1829.   } else {
  1830.     message("No networking support will be installed.\n");
  1831.   }
  1832.   
  1833.   message("/dev/vmmon\n");
  1834.   system(shell_string($mknod) . ' /dev/vmmon c 10 165') and die "\n### mknod /dev/vmmon: $!.\n";
  1835.   chmod 0600, "/dev/vmmon" or die "\n### chmod /dev/vmmon: $!.\n";
  1836.   LogFile("/dev/vmmon");
  1837.   
  1838.   # Create a bunch of parallel port devices if they don't exist yet
  1839.   message("/dev/parport*\n");
  1840.   $i = 0;
  1841.   for ($i = 0; $i < 4; $i++) {
  1842.     if (not (-e '/dev/parport' . $i)) {
  1843.       message('mknod /dev/parport' . $i . '\n');
  1844.       system(shell_string($mknod) . ' ' . shell_string('/dev/parport' . $i) . ' c 99 ' . shell_string($i)) and die "\n### mknod: $!.\n";
  1845.       chmod 0600, '/dev/parport' . $i or die "\n### chmod /dev/parport$i: $!.\n"; 
  1846.       LogFile('/dev/parport' . $i);
  1847.     }
  1848.   }
  1849.  
  1850.   if ($networking) {
  1851.     message("/dev/vmnet*\n");
  1852.     $i = 0;
  1853.     foreach $vnet ("/dev/vmnet0", "/dev/vmnet1",
  1854.            "/dev/vmnet2", "/dev/vmnet3") { 
  1855.       message("mknod $vnet\n");
  1856.       system(shell_string($mknod) . ' ' . shell_string($vnet) . ' c 119 ' . shell_string($i)) and die "\n### mknod: $!.\n";
  1857.       chmod 0600, $vnet or die "\n### chmod $vnet: $!.\n"; 
  1858.       LogFile("$vnet");
  1859.       $i++;
  1860.     }
  1861.  
  1862.     &ChooseNetworkInterface();
  1863.     message("$initdir/init.d/vmware\n");
  1864.  
  1865.     my $system = identifyPlatform();
  1866.     my $bootscript = "load-vmx86-" . $system . ".dist";
  1867.     if (! -f $bootscript) {
  1868.     # no platform-specific version, use default
  1869.     $bootscript = "load-vmx86.dist";
  1870.     }
  1871.     &Install(0555, $bootscript, "$initdir/init.d/vmware");
  1872.     
  1873.     ($hostOnlyAddress, $hostOnlyNetMask) = configureHostOnlyNetworking();
  1874.     
  1875.   } else {
  1876.     
  1877.     message("$initdir/init.d/vmware\n");
  1878.     &Install(0555, "load-vmx86-novmnet.dist", "$initdir/init.d/vmware");
  1879.     
  1880.     $hostOnlyAddress = "";
  1881.     $hostOnlyNetMask = "";
  1882.     
  1883.   }
  1884.  
  1885.   my ($unique, $level, $action) =
  1886.       split(/:/, direct_command(shell_string($grep) . ' ' . shell_string('^[ \t]*[^ \t#].*:initdefault') . ' /etc/inittab'));
  1887.   if (! defined($level) || $level !~ /[123456789]/) {
  1888.      Install_StartupScript(2);
  1889.      Install_StartupScript(3);
  1890.      Install_StartupScript(5);
  1891.   } else {
  1892.      Install_StartupScript($level);
  1893.   }
  1894.  
  1895.   ###
  1896.   ### write the config file
  1897.   ###
  1898.   open(CONFIGFILE,">$vmware_etc/config");
  1899.   print CONFIGFILE "vmware.fullpath = \"$bindir/vmware\"\n";
  1900.   print CONFIGFILE "wizard.fullpath = \"$bindir/vmware-wizard\"\n";
  1901.   print CONFIGFILE "dhcpd.fullpath = \"$bindir/vmnet-dhcpd\"\n";
  1902.   print CONFIGFILE "loop.fullpath = \"$bindir/vmware-loop\"\n";
  1903.   print CONFIGFILE "libdir = \"$libdir\"\n";
  1904.   
  1905.   if (defined($hostOnlyAddress) &&  $hostOnlyAddress ne "") { 
  1906.     print CONFIGFILE "vmnet1.HostOnlyAddress = \"$hostOnlyAddress\"\n";
  1907.     print CONFIGFILE "vmnet1.HostOnlyNetMask = \"$hostOnlyNetMask\"\n";
  1908.   }
  1909.   close(CONFIGFILE);
  1910.   
  1911.   LogFile("$vmware_etc/config");
  1912.   
  1913.   
  1914.   # Avoid reboot.
  1915.   message("Running $initdir/init.d/vmware start\n");
  1916.   system(shell_string($initdir . '/init.d/vmware') . ' start') and die "\n### vmware start: $!.\n";
  1917.   print "Installation successful \n";
  1918.   Log("Installation completed\n");
  1919. }
  1920.  
  1921.  
  1922. sub Legacy_Uninstall_vmx86 { 
  1923.   my @vmx86files = ("/dev/vmx86", "/dev/vnet0", "/dev/vnet1",
  1924.             "/dev/vnet2",  "/dev/vnet3", 
  1925.                     "$initdir/init.d/vmx86","$initdir/rc3.d/S99vmx86",
  1926.                     "$initdir/rc5.d/S99vmx86","$initdir/rc6.d/K08vmx86");
  1927.  
  1928.   my @vmmonfiles = ("/dev/vmmon", 
  1929.                     "/dev/vmnet0",  "/dev/vmnet1",
  1930.             "/dev/vmnet2",  "/dev/vmnet3", 
  1931.                     "$initdir/init.d/vmware",
  1932.                     "$initdir/rc3.d/S99vmware",
  1933.                     "$initdir/rc5.d/S99vmware",
  1934.                     "$initdir/rc6.d/K08vmware");
  1935.   
  1936.   my ($file,$oldlibdir);
  1937.  
  1938.  
  1939.  
  1940.   if (-e "/dev/vmx86") {
  1941.     ###
  1942.     ### host
  1943.     ###
  1944.     
  1945.     message("Running $initdir/init.d/vmx86 stop\n");
  1946.     system(shell_string($initdir . '/init.d/vmx86') . ' stop') if -x "$initdir/init.d/vmx86";
  1947.    
  1948.  
  1949.     foreach $file (@vmx86files) { 
  1950.       message("removing legacy $file\n");
  1951.       unlink $file;
  1952.     }
  1953.     
  1954.     message ("removing legacy modules \n");
  1955.     unlink <$modulesdir/preferred/misc/vmx86-*>;
  1956.     unlink <$modulesdir/preferred/misc/vnet-*>;
  1957.     unlink <$modulesdir/$version/misc/vmx86-*>;
  1958.     unlink <$modulesdir/$version/misc/vnet-*>;
  1959.     
  1960.     #### 
  1961.     #### site
  1962.     ####
  1963.     
  1964.     ($oldlibdir = $legacylibdir) =~ s/vmware/vmx86/;
  1965.     if (-d "$oldlibdir") {
  1966.       my @oldfiles = ("vmm","BIOS.ROM","nvram","config", "demo", "vmx86-test");
  1967.       foreach $file (@oldfiles) {
  1968.         message("$oldlibdir/$file\n");
  1969.         unlink "$oldlibdir/$file" or warn "unlink $oldlibdir/$file: $!.\n";
  1970.       }
  1971.       rmdir "$oldlibdir" or warn "Cannot remove $oldlibdir: $!.\n";
  1972.     }
  1973.     
  1974.     unlink "$bindir/vmx86" or warn "unlink $bindir/vmx86: $!.\n";
  1975.     message("$mandir/man1/vmx86.1 (Manual page)\n");
  1976.     unlink "$mandir/man1/vmx86.1" or warn "unlink $mandir/man1/vmx86.1: $!.\n";
  1977.     
  1978.   }
  1979.   
  1980.   if (-e "/dev/vmmon") {
  1981.     
  1982.     message("Running $initdir/init.d/vmware stop\n");
  1983.     system(shell_string($initdir . '/init.d/vmware') . ' stop') if -x "$initdir/init.d/vmware";
  1984.     
  1985.     foreach $file (@vmmonfiles) { 
  1986.       message("removing legacy $file\n");
  1987.       unlink $file;
  1988.     }
  1989.     
  1990.     message ("removing legacy modules \n");
  1991.     unlink <$modulesdir/preferred/misc/vmmon>;
  1992.     unlink <$modulesdir/preferred/misc/vmnet>;
  1993.     unlink <$modulesdir/$version/misc/vmmon>;
  1994.     unlink <$modulesdir/$version/misc/vmnet>;
  1995.     
  1996.     foreach $file ("vmware", "vmnet-bridge", "vmnet-sniffer") {
  1997.       message("$bindir/$file\n");
  1998.       unlink "$bindir/$file" or warn "unlink $bindir/$file: $!.\n";
  1999.     }
  2000.     
  2001.     
  2002.     foreach $file (@legacylibfiles) {
  2003.       message("$legacylibdir/$file\n");
  2004.       unlink "$legacylibdir/$file" or warn "unlink $legacylibdir/$file: $!.\n";
  2005.     }
  2006.     
  2007.     message("$legacylibdir/nvram (Default NVRAM image)\n");
  2008.     unlink "$legacylibdir/nvram" or warn "unlink $legacylibdir/nvram: $!.\n";
  2009.     
  2010.     message("$legacylibdir/config (Default site configuration)\n");
  2011.     unlink "$legacylibdir/config" or warn "unlink $legacylibdir/config: $!.\n";
  2012.     
  2013.     message("$mandir/man1/vmx86.1 (Manual page)\n");
  2014.     unlink "$mandir/man1/vmx86.1" or
  2015.     warn "unlink $mandir/man1/vmx86.1: $!.\n";
  2016.   }
  2017. }
  2018.  
  2019. sub Legacy_Uninstall { 
  2020.  
  2021.   my $answer = query("This script has detected host files from early" .
  2022.              " pre-releases. Delete them?", "yes");
  2023.  
  2024.   if ($answer !~ /^[Yy]/) {
  2025.     die "Bye!\n";
  2026.   }
  2027.  
  2028.   print << "EOT";
  2029.  
  2030. Previous versions of the installation script did not record the
  2031. location of the installed files.  
  2032.  
  2033. If you installed pre-release versions of vmx86 or vmware in
  2034. non-standard locations, you will need to remove these files by hand.
  2035.  
  2036. This legacy uninstall script will only run once. If it fails during 
  2037. this phase, legacy files will remain 
  2038.  
  2039. We apologize for the inconvenience.
  2040.  
  2041. Thank you. 
  2042.  
  2043.  
  2044. EOT
  2045.   
  2046.   Init("legacy");
  2047.   Legacy_Uninstall_vmx86();
  2048.   
  2049. }
  2050.  
  2051.  
  2052. sub ReadLocations { 
  2053.     open(LOCATIONS,$vmware_locations);
  2054.     while (<LOCATIONS>) { 
  2055.     if (/^answer (\S+) (\S+)/) {
  2056.         $previousAnswer{$1} = $2;
  2057.     } elsif (/^answer (\S+)/) {
  2058.         $previousAnswer{$1} = "";
  2059.     } elsif (/^file (\S+) (\S+)/) {
  2060.         $previousFileTime{$1} = $2;
  2061.     } elsif (/^file (\S+)/) {
  2062.         $previousFileTime{$1} = 0;
  2063.     }
  2064.     }
  2065. }
  2066.  
  2067.  
  2068. sub UnlinkOrRename {
  2069.     my ($file, $previousMtime) = @_;
  2070.     my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
  2071.     $atime, $mtime, $ctime) = stat($file);
  2072.  
  2073.     $file =~ /([^\/]*$)/;
  2074.  
  2075.     if (defined($backupable{$1}) && $mtime ne $previousMtime) {
  2076.     MakeBackup($file);
  2077.     } else {
  2078.     message("Unlinking $file\n");
  2079.     unlink $file or warn "unlink $file: $!.\n";
  2080.     }
  2081. }
  2082.  
  2083.  
  2084. sub Uninstall { 
  2085.   my ($dir, %dirs);
  2086.   
  2087.   message("Uninstall()\n");
  2088.  
  2089.   open(LOCATIONS, $vmware_locations);
  2090.  
  2091.   while (<LOCATIONS>) { 
  2092.  
  2093.     if (/^VERSION (.+)$/) {
  2094.       if (defined($1)) {
  2095.       print "Uninstalling VMware version $1\n";
  2096.       } else {
  2097.       print "Uninstalling VMware (unknown version)\n";
  2098.       }
  2099.     } elsif (/^file (\S+) (\S+)/) {
  2100.     &UnlinkOrRename($1, $2);
  2101.     } elsif (/^file (\S+)/) {
  2102.     &UnlinkOrRename($1, 0);
  2103.     } elsif (/^directory (\S+)/) {
  2104.       $dirs{$1} = $1;
  2105.     }
  2106.   }
  2107.       
  2108.   close(LOCATIONS); 
  2109.   unlink $vmware_locations or warn "Cannot remove $vmware_locations: $!.\n";
  2110.  
  2111.   # silently remove these to fix up bad intallers in the past
  2112.   unlink "/etc/rc.d/rc3.d/S99vmware";
  2113.   unlink "/etc/rc.d/rc5.d/S99vmware";
  2114.   
  2115.   foreach $dir (keys %dirs) { 
  2116.     message("Removing directory $dir\n");
  2117.     rmdir $dir or warn "rmdir $dir: $!.\n";
  2118.   } 
  2119. }
  2120.  
  2121.  
  2122. sub Site_Install {
  2123.   my $option = shift;
  2124.   my $file;
  2125.   my $shared = 0;
  2126.   my $answer;
  2127.   my %allfiles;
  2128.   my %basename;
  2129.   my $base;
  2130.   my @filelist;
  2131.  
  2132.   message("Installing site-specific files.\n");
  2133.   
  2134.   @filelist = @programs;
  2135.   push(@filelist, @libfiles);
  2136.  
  2137.   foreach $file (@filelist) { 
  2138.     if ($file eq "vmware") { 
  2139.       $allfiles{"$bindir/$file"} = 04555;
  2140.     } else {
  2141.       $allfiles{"$bindir/$file"} = 0555;
  2142.     }
  2143.     $basename{"$bindir/$file"} = $file;
  2144.   }
  2145.  
  2146.   $allfiles{"$mandir/man1/vmware.1"} = 0444;
  2147.   $basename{"$mandir/man1/vmware.1"} = "vmx86.1.dist";
  2148.   
  2149.   $allfiles{"$libdir/config"} = 0444;
  2150.   $basename{"$libdir/config"} = "site-config.dist";
  2151.   
  2152.   foreach $file (keys %allfiles) {
  2153.     message("$file\n");
  2154.     $shared = 0;
  2155.     if (-e "$file") {
  2156.       if ($option eq "default") {
  2157.         $shared = 1;
  2158.       } else {
  2159.         $answer = query("File $file already exists. Use it? (yes/no)", "yes");
  2160.         if ($answer =~ /^[Yy]/) {
  2161.           $shared = 1;
  2162.         }
  2163.       }
  2164.     }
  2165.     
  2166.     if (not $shared) { 
  2167.       my $base = $basename{$file};
  2168.       print "Installing $file\n";
  2169.       &Install($allfiles{$file}, $base, $file);
  2170.     }
  2171.   }
  2172.  
  2173.   ##
  2174.   ## Install help files.
  2175.   ##
  2176.   makeDirectory("$libdir/help");
  2177.   Log("directory $libdir/help\n");
  2178.   foreach $file (internal_ls('help')) {
  2179.     &Install(0444, "help/$file", "$libdir/help/$file");
  2180.   }
  2181.  
  2182.   ##
  2183.   ## Install X keymap files.
  2184.   ##
  2185.   makeDirectory("$libdir/xkeymap");
  2186.   Log("directory $libdir/xkeymap\n");
  2187.   foreach $file (internal_ls('xkeymap')) {
  2188.     &Install(0444, "xkeymap/$file", "$libdir/xkeymap/$file");
  2189.   }
  2190.  
  2191.   # Check for correct version of libraries.
  2192.  
  2193.   if (system(shell_string($ldd) . ' ' . shell_string($bindir . '/vmware') . ' | ' . shell_string($grep) . ' -q -i ' . shell_string('not found')) == 0) {
  2194.       print << "EOM";
  2195.  
  2196. The correct version of one or more libraries needed to run vmware
  2197. may be missing.  This is the output of "$ldd $bindir/vmware":
  2198.  
  2199. EOM
  2200.       system(shell_string($ldd) . ' ' . shell_string($bindir . '/vmware'));
  2201.       print << "EOM";
  2202.  
  2203. This script cannot tell for sure, but you may need to upgrade
  2204. libc5 to glibc before you can run vmware.
  2205.  
  2206. Hit return to continue.
  2207. EOM
  2208.     <STDIN>;
  2209.   }
  2210. }
  2211.  
  2212.  
  2213. sub Cleanup { 
  2214.   if ($createdBuildDir ne "") { 
  2215.     message("Removing $createdBuildDir\n");
  2216.     system(shell_string($rm) . ' -rf ' . shell_string($createdBuildDir));
  2217.   }
  2218. }
  2219.  
  2220.  
  2221. ################################################################
  2222. #                        Main                                  #
  2223. ################################################################
  2224.  
  2225. sub main {
  2226.  
  2227.     my ($option, $recursive) = @_;
  2228.     my $answer;
  2229.     my $initscript;
  2230.     my $dirty_suse;
  2231.     my $rpm;
  2232.       
  2233.     $dirty_suse = 0;
  2234.     
  2235.     ###
  2236.     ### legacy deinstall (previous releases)
  2237.     ###
  2238.     
  2239.     if (-d $vmware_tmpdir)  {
  2240.     print "VMware for Linux \n\n" . 
  2241.         "The previous installation of VMware was incomplete, or at " .
  2242.         "least the directory $vmware_tmpdir exists.\n\n";
  2243.       
  2244.       $answer =
  2245.       query("Would you like me to remove $vmware_tmpdir? (yes/no)", "no");
  2246.       if ($answer =~/^[Yy]/) { 
  2247.         system(shell_string($rm) . ' -rf ' . shell_string($vmware_tmpdir));
  2248.       } else { 
  2249.         die "\n### Please remove $vmware_tmpdir manually.\n";
  2250.       }
  2251.     }
  2252.     
  2253.     if (!(-d $vmware_etc) && (-e "/dev/vmx86" )) {
  2254.       Legacy_Uninstall();
  2255.       print << "LEGACY";
  2256.  
  2257. The uninstallation of the pre-beta software was successful. 
  2258. Please restart ./install.pl to install the new one.
  2259.  
  2260. LEGACY
  2261.       die "Thank you\n";
  2262.     }
  2263.     
  2264.     if (! $recursive && $option ne "default" && $option ne "-default") {
  2265.     print << "EOM";
  2266.  
  2267.  
  2268. --------------------------------------------
  2269.          VMware for Linux  installer 
  2270.  
  2271.     Copyright (C) 1998,1999 VMware, Inc.
  2272. --------------------------------------------
  2273.  
  2274. EOM
  2275.     }
  2276.  
  2277.     if ($option eq "uninstall" ||
  2278.         $option eq "upgrade") { 
  2279.       if (! -e $vmware_locations) { 
  2280.         die "\n### VMware is currently not installed.  " .
  2281.         "Cannot upgrade or uninstall.\n";
  2282.       }
  2283.       
  2284.       ReadLocations();
  2285.  
  2286.     } else { 
  2287.       ###
  2288.       ### Upgrade/Deinstall
  2289.       ###
  2290.       if (!$recursive && -e $vmware_locations) {
  2291.         
  2292.         ReadLocations();
  2293.  
  2294.         print "An existing distribution of VMware for Linux " .
  2295.         "has been detected.\n";
  2296.     if (defined($previousAnswer{BINDIR})) {
  2297.       print "The location of existing VMware binaries is: "
  2298.         . "$previousAnswer{BINDIR}\n";
  2299.     }
  2300.  
  2301.         if (defined($previousAnswer{NETWORKING}) && 
  2302.             $previousAnswer{NETWORKING} =~ /^[yY]/) { 
  2303.           print "Existing installation has networking enabled.\n";
  2304.         } else { 
  2305.           print "Existing installation has networking disabled.\n";
  2306.         }
  2307.         
  2308.         if (defined($previousAnswer{VNET_HOSTONLY}) && 
  2309.             $previousAnswer{VNET_HOSTONLY} =~ /^[yY]/) { 
  2310.           print "Existing installation has host-only networking enabled.\n";
  2311.         } else { 
  2312.           print "Existing installation has host-only networking disabled.\n";
  2313.         }
  2314.         print "\n";
  2315.         
  2316.         $answer = query("Would you like to upgrade VMware for Linux? (yes/no)",
  2317.             "yes");
  2318.  
  2319.         if ($answer =~/^[Yy]/) { 
  2320.           $option = "upgrade";
  2321.         } else { 
  2322.           $answer = query("Would you like to uninstall ".
  2323.               "VMware for Linux? (yes/no)","no");
  2324.  
  2325.           if ($answer =~/^[Yy]/) { 
  2326.             $option = "uninstall";
  2327.           } else { 
  2328.         die "\n### You need to choose between upgrading ".
  2329.         "and uninstalling.\n";
  2330.       }
  2331.         }
  2332.       }
  2333.     }
  2334.     
  2335.     print "\n";
  2336.     if (($option eq "upgrade" || $option eq "uninstall") &&
  2337.         -e $vmware_locations && 
  2338.         defined($previousAnswer{INITDIR})) {
  2339.       
  2340.       # SUSE RPM ALERT ON
  2341.  
  2342.       # Do not remove the previous comment and the next one. They are used by
  2343.       # our main Makefile to remove this section from the rpm installer to
  2344.       # avoid a deadlock.
  2345.  
  2346.       if (identifyPlatform() eq 'suse') {
  2347.     $rpm = DoesBinaryExist_Prompt('rpm');
  2348.     if ($rpm eq '') {
  2349.       print STDERR "\nUnable to continue.\n";
  2350.       exit(1);
  2351.     }
  2352.  
  2353.     if (   (not(direct_command(shell_string($rpm) . ' -q vmware-1.0.2-7 2> /dev/null') eq ''))
  2354.         || (not(direct_command(shell_string($rpm) . ' -q vmmodule-1.0.2-4 2> /dev/null') eq ''))) {
  2355.       # Arg, SuSE's dirty packages are installed
  2356.       $dirty_suse = 1;
  2357.       # Their INITDIR answer is complety bogus. Fix it.
  2358.           $previousAnswer{INITDIR} = '/etc/rc.d';
  2359.     }
  2360.       }
  2361.       # SUSE RPM ALERT OFF
  2362.       
  2363.       $initscript = "$previousAnswer{INITDIR}/init.d/vmware";
  2364.       message("Running $initscript stop.\n");
  2365.       if (-x "$initscript") { 
  2366.         if (system(shell_string($initscript) . ' stop')) { 
  2367.           die "\n### $initscript stop: failed.\n";
  2368.         }
  2369.       }
  2370.  
  2371.       # As of VMware 1.0.8 this case should be correctly handled
  2372.       # by the startup script and should trigger the previous test
  2373.       if (not (direct_command(shell_string($lsmod) . ' | ' . shell_string($grep) . ' ' . shell_string('^vmmon\|vmnet\|vmppuser')) eq "")) {
  2374.         die "\n### At least one VMware kerner module is still loaded.\n" .
  2375.           "### Cannot upgrade or uninstall.\n" .
  2376.           "### This can happen if you are running a VM.\n";
  2377.       }
  2378.       
  2379.       if ($dirty_suse == 1) {
  2380.     print << "EOSUSE";
  2381.  
  2382. This script has detected that you were running a SuSE distribution with
  2383. an old version of vmware (namely two packages: vmmodule-1.0.2-4 and
  2384. vmware-1.0.2-7) that interacts badly with this version.
  2385.  
  2386. This script is going to remove these packages.
  2387.  
  2388. Please do not re-install these specific packages with YaST or rpm in the
  2389. future.
  2390.  
  2391. Press return to proceed, or Control-C to abort and exit.
  2392. EOSUSE
  2393.         <STDIN>;
  2394.  
  2395.     system(shell_string($rpm) . ' -e vmware-1.0.2-7 2> /dev/null');
  2396.     system(shell_string($rpm) . ' -e vmmodule-1.0.2-4 2> /dev/null');
  2397.       } else {
  2398.     Uninstall();
  2399.       }
  2400.     }
  2401.     
  2402.     if ($recursive) { 
  2403.       return;
  2404.     }
  2405.     
  2406.     if ($option eq "uninstall") {
  2407.       print "Thank you for trying VMware. VMware is now uninstalled\n";
  2408.       exit 0;
  2409.     }
  2410.     
  2411.     
  2412.     ###
  2413.     ###
  2414.     ### 
  2415.     
  2416.     print "\n";
  2417.     while ($option eq "none") {
  2418.       $answer = query("Perform default installation? (yes/no/help)", "yes");
  2419.       if ($answer =~ /^[Yy]/) {
  2420.         $option = "default";
  2421.       } elsif ($answer =~ /^[Nn]/) {
  2422.         $option = "all";
  2423.       } else {
  2424.         print << "EOM";
  2425.  
  2426. If you answer YES, this script will install the executables
  2427. in $default_bindir, the library files in $default_libdir,
  2428. the manual pages in $default_mandir, and the boot-time
  2429. init scripts in $default_initdir.  
  2430. If these directories contain a previous installation, it will be 
  2431. uninstalled first. If these directories do not exist, they will be 
  2432. created. No questions will be asked, unless problems arise.
  2433.  
  2434. If you answer NO, this script will prompt for the names
  2435. of the installation directories (unless BINDIR, LIBDIR,
  2436. MANDIR, and INITDIR are set), and may ask further questions
  2437. to direct the installation.
  2438.  
  2439. Please answer yes or no, or type ^C to exit.
  2440.  
  2441. EOM
  2442.        }
  2443.     }
  2444.  
  2445.     if ($option =~ /^-/) {
  2446.       $option = substr($option, 1);
  2447.     }
  2448.     
  2449.     if ($option eq "default") {
  2450.       $ENV{BINDIR} = $default_bindir;
  2451.       $ENV{LIBDIR} = $default_libdir;
  2452.       $ENV{MANDIR} = $default_mandir;
  2453.       $ENV{INITDIR} = $default_initdir;
  2454.     } 
  2455.  
  2456.     if ($option eq "upgrade") { 
  2457.       foreach $answer ("BINDIR","LIBDIR","MANDIR","INITDIR","NETWORKING",
  2458.                        "BUILDR_vmmon","BUILDR_vmnet", "VNET_HOSTONLY", 
  2459.                        "VNET_HOSTONLY_NETWORK", "VNET_HOSTONLY_HOSTADDR",
  2460.                "VNET_HOSTONLY_NETMASK", "VNET_INTERFACE") { 
  2461.         if (defined($previousAnswer{$answer})) { 
  2462.           message("Upgrading $answer with $previousAnswer{$answer}\n");
  2463.           $ENV{$answer} = $previousAnswer{$answer};
  2464.         }
  2465.       }
  2466.     }
  2467.     
  2468.     
  2469.     if ($option eq "default" || 
  2470.         $option eq "all" || 
  2471.         $option eq "upgrade") { 
  2472.       &Show_EULA();
  2473.       OpenLog();
  2474.       &Init($option);
  2475.       &Site_Install($option);
  2476.       &Host_Install($option);
  2477.       close (LOCATIONS);
  2478.       &Cleanup();
  2479.       if (-e "PROMCONFIG") { 
  2480.         system(shell_string($cat) . ' PROMCONFIG >> ' . shell_string($vmware_etc . '/config'));
  2481.       }
  2482.  
  2483.       if (-e "PROMOCODE") {
  2484.         system(shell_string($cat) . ' PROMOCODE');
  2485.         print "Hit return to continue. ";
  2486.         <STDIN>;
  2487.       }
  2488.       
  2489.       print << "DONE";
  2490.  
  2491. To run vmware, exit from root, leave this distribution directory
  2492. and type '$bindir/vmware'.
  2493.  
  2494. For technical support, please visit our website at
  2495. http://www.vwmare.com/support and our newsgroups at
  2496. nntp://news.vmware.com
  2497.  
  2498. For software updates, please visit our website at
  2499. http://www.vmware.com/download
  2500.  
  2501. Enjoy,
  2502.    
  2503.     --the VMware team
  2504.  
  2505. DONE
  2506.  
  2507.     } else {
  2508.       
  2509.     die << "EOM"
  2510. $0: unknown argument $option.
  2511.  
  2512. Usage: $0 [MODE]
  2513. where MODE is one of:
  2514.  
  2515.     all             - install everything
  2516.     default         - quietly install everything in the default locations
  2517.     upgrade         - upgrade to a new version of VMware
  2518.     uninstall       - remove VMware all its associated files
  2519. EOM
  2520.    }
  2521. }
  2522.  
  2523.  
  2524. ###############
  2525. #             #
  2526. # Really Main #
  2527. #             #
  2528. ###############
  2529.  
  2530. if (not is_root()) {
  2531.   die "\n### You must be root to install the VMware software.\n";
  2532. }
  2533.  
  2534. # Force the path to reduce the risk of using "modified" external helpers
  2535. # If the user has a special system setup, he will be prompted for the
  2536. # proper location anyway
  2537. $ENV{'PATH'} = "/bin:/usr/bin:/sbin:/usr/sbin";
  2538.  
  2539. initialize_external_helpers();
  2540.  
  2541. $umask = umask 022;
  2542. $smp = (direct_command(shell_string($uname) . ' -v') =~ / SMP /) ? 1 : 0;
  2543. ($version) = Kernel_RunningVersion();
  2544.  
  2545. $option = shift;
  2546.  
  2547. if (defined($option) && $option eq "-v") {
  2548.   $verbose = 1;
  2549.   $option = shift;
  2550. }
  2551.  
  2552. $option = "none" unless defined($option);
  2553.  
  2554. main($option, 0);
  2555.  
  2556. cleanup:
  2557. umask $umask;
  2558.  
  2559.