home *** CD-ROM | disk | FTP | other *** search
/ ftp.sberbank.sumy.ua / 2014.11.ftp.sberbank.sumy.ua.tar / ftp.sberbank.sumy.ua / incoming / sxtech / upgrade.pl < prev    next >
Perl Script  |  2014-08-29  |  60KB  |  2,904 lines

  1. #!/usr/bin/perl -w
  2. #
  3. # $Revision: #18 $
  4. #
  5. # upgrade - perform upgrade to latest firmware revision
  6. #
  7.  
  8. use    Carp;
  9. use    IO::Handle;
  10. use    File::Basename;
  11.  
  12. require "getopts.pl";
  13. require "stat.pl";
  14.  
  15. $pres_eq_conf    = 1;
  16. $pres_en_conf    = 1;
  17. $pres_sw_conf    = 1;
  18. $no_preserve    = 0;
  19.  
  20. $set_use_ssl    = 0;
  21.  
  22. $logfile    = "./upgrade.log";
  23. $dbgfile    = "./upgrade.dbg";
  24. $inputfile    = "/var/tmp/eq_upgrade.in";
  25. $outputfile    = "/var/log/eq_upgrade.log";
  26.  
  27. $vers        = "8.6.0";        # product version #
  28.  
  29. $oslevel    = 0;
  30. $disk           = "";
  31. $slice_old      = 1;
  32. $slice_new      = 2;
  33. $slice_xtra     = 0;            # extra slice always allocated
  34.  
  35. #
  36. # We will now try to make this the same as the layout used in the
  37. # PXE installs:
  38. #    All sizes are expressed in 512 byte blocks!
  39. #
  40. #    {DISK}s1-1=ufs     503808 /        0
  41. #
  42. #
  43. $root_size    =  503808;    # 512 byte sectors
  44. $swap_size    =   10240;    # vestigeal
  45. $usr_size    =       0;    # 512 byte sectors
  46. $tmp_size    =       0;    # 512 byte sectors
  47. $var_size    =       0;    # 512 byte sectors (at least)
  48. $size           = $root_size + $swap_size + $var_size + $tmp_size + $usr_size;
  49. $opt_R        = 0;        # reset after botched attempt
  50. $opt_r          = 0;            # Auto reboot if set (don't ask).
  51. $opt_b        = 0;        # batch mode
  52. $opt_k          = 0;            # load test4QA key
  53. $opt_e        = 0;        # preserve /eqsupport/.ssh/
  54. $opt_l        = 0;        # preserve license files only with -C option. 
  55. $opt_S          = 0;        # install SNMP?
  56. $opt_G          = 0;        # GUI mode
  57.  
  58. local *DBG;
  59.  
  60. @mp = ("/");                # mount points
  61.  
  62. %slice_map = ();
  63.  
  64. @mp_x = ();                # extra mount points
  65.  
  66. %slice_map_x = ();
  67.  
  68. %bits_map = (
  69.          '/'    => "./root.tgz",
  70.          );
  71. %fdisk = ();
  72. %label = ();
  73.  
  74. #
  75. # Preserving old version information 
  76. #
  77.  
  78. sub previous {
  79.     system "rm -rf /.master/var/eq/eq.previous";
  80.     system "cp /.master/var/eq/eq.conf  /.master/var/eq/eq.previous";
  81.     system "rm -rf /version/eq.previous";
  82.     system "cp /.version/eq  /.version/eq.previous";
  83. }
  84.  
  85. %xlate = (
  86.       '/etc/hosts'        => '/var/etc/hosts',
  87.       '/etc/group'        => '/var/etc/group',
  88.       '/etc/resolv.conf'    => '/var/etc/resolv.conf',
  89.       '/etc/ntp.conf'    => '/var/etc/ntp.conf',
  90.       '/etc/syslog.conf'    => '/var/etc/syslog.conf',
  91.       '/etc/ntp.drift'      => '/var/etc/ntp.drift',
  92.       '/etc/localtime'    => '/var/etc/localtime',
  93.       '/etc/ipfw.conf'    => '/var/eq/ipfw.conf',
  94.       '/etc/eq.conf'    => '/.master/var/eq/eq.conf',
  95.       '/etc/tac_client.conf'=> '/.master/var/eq/tac_client.conf',
  96.       '/etc/eq.previous'    => '/.master/var/eq/eq.previous',
  97.       '/etc/switch.conf'    => '/var/eq/switch.conf',
  98.       '/etc/envoy.conf'    => '/var/eq/envoy.conf',
  99.       '/etc/natd.conf'      => '/var/eq/natd.conf',
  100.       '/eq.previous'    => '/.version/eq.previous',
  101.       '/usr/local/www/cgi-bin/users'
  102.       => '/var/eq/users',
  103.       );
  104.  
  105. #
  106. # Determine whether to get our answer from STDIN, or from our
  107. # file
  108.  
  109. sub get_answer {
  110.     my $ans = "x";
  111.  
  112.     if ($opt_G) {
  113.         while($ans eq "x") {
  114.             open (EQ_IN_FILE, $inputfile);
  115.             chop($ans = <EQ_IN_FILE>);
  116.             close EQ_IN_FILE;
  117.             sleep 1;
  118.         }
  119.         open (EQ_IN_FILE, ">" . $inputfile);
  120.         print EQ_IN_FILE "x\n";
  121.         close EQ_IN_FILE;
  122.     }
  123.     else {
  124.         chop($ans = <STDIN>);
  125.     }
  126.     return($ans);
  127. }
  128.  
  129. sub curr_vers {
  130.     my $vers; 
  131.  
  132.     if (-f "/.version/eq") {
  133.         open IN, "< /.version/eq" or die;
  134.         while (<IN>) {
  135.         chop;
  136.  
  137.         if (/^EQVERS=(\d.*)$/) {
  138.         $vers = $1;
  139.         }
  140.     }
  141.     } else {
  142.         $vers = "0";
  143.     }
  144.  
  145.     return $vers;
  146. }
  147.  
  148.  
  149. #
  150. # dummy - ensure we don't get warning messages
  151. #
  152.  
  153. sub dummy {
  154.     print $disk . $slice_old . $slice_new;
  155.     print $opt_R;
  156.     print $size;
  157.     print $ST_MODE + $ST_GID + $ST_UID;
  158. }
  159.  
  160. #
  161. # usage - print usage info
  162. #
  163.  
  164. sub usage {
  165.     print "usage: upgrade [-R]\n";
  166.  
  167.     exit 1;
  168. }
  169.  
  170. #
  171. # dbg - print an informational message
  172. #
  173.  
  174. sub dbg {
  175.     my $arg = shift;
  176.  
  177.     print DBG "$arg\n";
  178. }
  179.  
  180. #
  181. # dbg_save - save the debug file
  182. #
  183.  
  184. sub dbg_save {
  185.     my $now = time();
  186.  
  187.     &sis("gzip --best < $dbgfile > /.version/upgrade.dbg.$now.gz");
  188. }
  189.  
  190. #
  191. # note - print an informational message
  192. #
  193.  
  194. sub note {
  195.     my $arg = shift;
  196.  
  197.     &dbg("$arg");
  198.  
  199.     print "$arg\n";
  200. }
  201.  
  202. #
  203. # cark - cark it
  204. #
  205.  
  206. sub cark {
  207.     my $arg = shift;
  208.  
  209.     &dbg("cark: $arg");
  210.  
  211.     &dbg_save;
  212.     
  213.     ¬e("**** Fatal error.");
  214.     ¬e("**** Please contact Coyote Point customer support.");
  215.     ¬e("**** Please provide the contents of $dbgfile.");
  216.  
  217.     if ($opt_r) {
  218.     print "NOTE: This system is currently in an intermediate state.";
  219.     print "It must be rebooted to return it to a stable state.";
  220.     print "Because the upgrade did *NOT* succeed, the current version";
  221.     print "will start when the system is rebooted.";
  222.     }
  223.     die "$arg";
  224. }
  225.  
  226. #
  227. # dbg_hash - print an informational message
  228. #
  229.  
  230. sub dbg_hash {
  231.     my $ref = shift;
  232.  
  233.     return unless defined  %$ref;
  234.  
  235.     foreach $k (sort keys %$ref) {
  236.     print DBG "$k $ref->{$k}\n";
  237.     }
  238. }
  239.  
  240. #
  241. # dbg_array - print an informational message
  242. #
  243.  
  244. sub dbg_array {
  245.     my $ref = shift;
  246.     my $siz = @$ref;
  247.  
  248.     for ($i = 0; $i < $siz; ++$i) {
  249.     print DBG "$ref->[$i]\n";
  250.     }
  251. }
  252.  
  253. #
  254. # sis - perform `system' function and croak if non-zero result.
  255. #
  256.  
  257. sub sis {
  258.     my $arg = shift or &cark("");
  259.  
  260.     &dbg("sis: $arg");
  261.  
  262.     #
  263.     # This is perl-ass-backwards, if you can imagine what that is.
  264.     #
  265.     system $arg and sleep 1 and &cark("\n");
  266. }
  267.  
  268. #
  269. # vsis - verbosely perform system function (sort of)
  270. #
  271.  
  272. sub vsis {
  273.     local *FH;
  274.     local *TTY;
  275.     my $success = 0;
  276.     my $last = '';
  277.  
  278.     my $arg = shift or &cark("");
  279.     my @rot = ('/', '-', '\\', '|');
  280.     my @rat = ('o', '.', 'o', '0');
  281.     my @spc = ('    ', '-   ', ' -  ', '  - ', '   -');
  282.     my $i = 0;
  283.     my $j = 0;
  284.     my $k = 0;
  285.     my $s = 0;
  286.  
  287.     return &sis($arg) unless !$opt_b;
  288.  
  289.     if (!$opt_G) {
  290.         open TTY, ">/dev/tty" or die;
  291.         select((select(TTY), $| = 1)[0]);
  292.     }    
  293.     open FH, "sh -c '". $arg ."' && echo '>>>success<<<' 2>&1 |" or die;
  294.     select((select(FH), $| = 1)[0]);
  295.  
  296.  
  297.     my $rin = '';
  298.     my $ein = '';
  299.     my $rout;
  300.     my $eout;
  301.  
  302.     vec($rin, fileno(FH), 1) = 1;
  303.  
  304.     $ein = $rin;
  305.  
  306.     my $eof  = 0;
  307.     my $off  = 0;
  308.     my $toss = '';
  309.  
  310.     while (!$eof && !$success) {
  311.         my ($n, $t) = select($rout=$rin, undef, $eout=$ein, 0.05);
  312.  
  313.         $eof = vec($eout, fileno(FH), 1);
  314.  
  315.         if (!$eof && vec($rout, fileno(FH), 1)) {
  316.             if (length($toss) > 128) {
  317.                 $off  = 128;
  318.                 $toss = substr($toss, -$off);
  319.             }
  320.  
  321.             my $cc = sysread(FH, $toss, 1024, $off);
  322.  
  323.             if ($cc) {
  324.                 $last = $toss;
  325.             } else {
  326.                 $eof = 1;
  327.             }
  328.         }
  329.  
  330.         if (!$opt_G) {
  331.         print TTY "\rW$rat[$i]rking$spc[$j]$rot[$k]";
  332.         }    
  333.  
  334.     if ($s == 0) {
  335.         ($i = 0, $s = 1) unless ++$i <= $#rat;
  336.     }
  337.     if ($s == 1) {
  338.         ($j = 0, $s = 2) unless ++$j <= $#spc;
  339.     }
  340.     if ($s == 2) {
  341.         ($k = 0) unless ++$k <= $#rot;
  342.         $s = 0;
  343.     }
  344.  
  345.     if ($toss =~ />>>success<<</) {
  346.         $success = 1;
  347.         print "\rsuccess!                                         \n";
  348.     }
  349.     }
  350.  
  351.     print "\r                         \r$last" unless $success;
  352.  
  353.     close FH;
  354.     if (!$opt_G) {
  355.         close TTY;
  356.         select(STDOUT); $| = 1;
  357.     }    
  358.  
  359.     print "\n";
  360. }
  361.  
  362. sub do_mounts {
  363.  
  364.     foreach $mp (@mp) {
  365.     sis "mount $slice_map{$mp} /mnt/$mp";
  366.     }
  367.     foreach $mp (@mp_x) {
  368.     sis "mount $slice_map_x{$mp} /mnt/$mp";
  369.     }
  370. }
  371.  
  372. sub undo_mounts {
  373.  
  374.     foreach $mp (reverse @mp_x) {
  375.     my $mnt = "$slice_map_x{$mp}";
  376.  
  377.     foreach (`mount`) {
  378.         if (/^$mnt/) {
  379.         sis "umount $mnt";
  380.         }
  381.     }
  382.     }
  383.  
  384.     foreach $mp (reverse @mp) {
  385.     my $mnt = "$slice_map{$mp}";
  386.  
  387.     foreach (`mount`) {
  388.         if (/^$mnt/) {
  389.         sis "umount $mnt";
  390.         }
  391.     }
  392.     }
  393. }
  394.  
  395. #
  396. # root_disk - determine the disk to root with
  397. #
  398.  
  399. sub root_disk {
  400.  
  401.     foreach (`df /`) {
  402.     if (m:^/dev/(\D+\d)s(\d)[a-f]\s:) {
  403.         &dbg("root disk: $1:$2");
  404.         $disk  = $1;
  405.         $slice_old = $2;
  406.  
  407.         return;
  408.     }
  409.     }
  410.  
  411.     &cark("Cannot determine disk type.\n");
  412. }
  413.  
  414. #
  415. # sync_disk - sync the in-core view of the slices with the on-disk.
  416. #
  417.  
  418. sub sync_disk {
  419.     local *FH;
  420.  
  421.     open FH, "./disk $disk 2>&1 |" or die;
  422.  
  423.     while (<FH>) {
  424.     chop;
  425.     &dbg("pre: $_");
  426.     }
  427.  
  428.     close FH;
  429.  
  430.     open FH, "./disk -S $disk 2>&1 |" or die;
  431.  
  432.     while (<FH>) {
  433.     chop;
  434.     &dbg("post: $_");
  435.  
  436.     &cark("$_\n") if (/ioctl/);
  437.     }
  438.  
  439.     close FH;
  440. }
  441.  
  442. #
  443. # fdisk_reset - reset the %fdisk cache
  444. #
  445.  
  446. sub fdisk_reset {
  447.     local $d = shift || die;
  448.     local *FH;
  449.  
  450.     &dbg("fdisk_reset $d");
  451.  
  452.     %fdisk = ();
  453.  
  454.     open FH, "fdisk -s $d |";
  455.  
  456.     $_ = <FH>;
  457.     chop;
  458.  
  459.     my @zot = split;
  460.  
  461.     @fdisk{'cyl', 'hd', 'sec'} = @zot[1, 3, 5];
  462.  
  463.     $_ = <FH>;
  464.  
  465.     while (<FH>) {
  466.     chop;
  467.  
  468.     @zot = split;
  469.  
  470.     &cark("invalid input: $_") unless m/^\s+(\d+):/;
  471.  
  472.     $fdisk{$1} = ();
  473.     @{$fdisk{$1}}{'start', 'size', 'type', 'flags'} = @zot[1..4];
  474.     }
  475.  
  476.     close FH;
  477.  
  478.     #
  479.     # debug
  480.     #
  481.  
  482.     foreach $p (1..4) {
  483.         next unless defined $fdisk{$p};
  484.  
  485.         foreach $k (keys %{$fdisk{$p}}) {
  486.             &dbg("$p: $k $fdisk{$p}->{$k}");
  487.         }
  488.     }
  489. }
  490.  
  491. #
  492. # disklabel_reset - reset the %label cache
  493. #
  494.  
  495. sub disklabel_reset {
  496.     local $d = shift || die;
  497.     local $s = shift || die
  498.     local *FH;
  499.  
  500.     &dbg("disklabel_reset $d $s");
  501.  
  502.     %label = ();
  503.  
  504.     open FH, "disklabel ${d}s${s} |";
  505.  
  506.     while (<FH>) {
  507.     @zot = split;
  508.  
  509.     if ($#zot >= 4 && $zot[0] =~ /^([abcdefgh]):/) {
  510.         $label{$1}->{'size'}   = $zot[1];
  511.         $label{$1}->{'fstype'} = $zot[3];
  512.     }
  513.     }
  514.  
  515.     close FH;
  516. }
  517.  
  518. #
  519. # slice_4_inuse - predicate
  520. #
  521.  
  522. sub slice_4_inuse {
  523.     local *FH;
  524.  
  525.     open FH, "swapinfo|";
  526.  
  527.     while (<FH>) {
  528.     if (m:^/dev/r${disk}s4:) {
  529.         close FH;
  530.         return 1;
  531.     }
  532.     }
  533.  
  534.     close FH;
  535.  
  536.     open FH, "mount|";
  537.  
  538.     while (<FH>) {
  539.     if (m:^/dev/${disk}s4:) {
  540.         close FH;
  541.         return 1;
  542.     }
  543.     }
  544.  
  545.     close FH;
  546.  
  547.     open FH, "</etc/rc.conf";
  548.  
  549.     while (<FH>) {
  550.     if (m:^dumpdev=.*/dev/${disk}s4:) {
  551.         close FH;
  552.         return 1;
  553.     }
  554.     }
  555.  
  556.     return 0;
  557. }
  558.  
  559. #
  560. # reclaim_space - reclaim space on $disk
  561. #
  562.  
  563. sub reclaim_space {
  564.     local $d = shift;
  565.     local $p = shift;
  566.     local *FH;
  567.  
  568.     &dbg("reclaim($d, $p)");
  569.  
  570.     if ($p == 4 && &slice_4_inuse()) {
  571.     &cark("**** Cannot delete slice 4.\n");
  572.     }
  573.  
  574.     open FH, "| fdisk -f - $d" or die;
  575.  
  576.     print FH "p $p 0 0 0\n";
  577.  
  578.     close FH;
  579.  
  580.     &sync_disk($d);
  581.     &fdisk_reset($d);
  582. }
  583.  
  584. #
  585. # current_slice - return current slice used
  586. #
  587.  
  588. sub current_slice {
  589.  
  590.     #
  591.     # XXX: this is bogus as the 0x80 has been seen to be set
  592.     # XXX: on more than one partition at a time.
  593.     #
  594.  
  595.     foreach (1..3) {
  596.     next unless defined $fdisk{$_};
  597.     next unless oct($fdisk{$_}->{'type'}) == 165;
  598.     next unless oct($fdisk{$_}->{'flags'}) & 0x80;
  599.  
  600.     &dbg("current slice = $_");
  601.  
  602.     return $_;
  603.     }
  604.  
  605.     &cark("no current slice\n");
  606. }
  607.  
  608. #
  609. # free_space - return the amount of free space for a given FDISK slice
  610. #
  611.  
  612. sub free_space {
  613.     my $p = shift || die;
  614.     my $start = 0;
  615.     my $end   = $fdisk{'cyl'} * $fdisk{'hd'} * $fdisk{'sec'};
  616.  
  617.     &dbg("free_space $p - start=$start end=$end");
  618.  
  619.     return 0 unless !defined($fdisk{$p});
  620.  
  621.     foreach $i (1..4) {
  622.     next unless defined $fdisk{$i};
  623.  
  624.     if ($i < $p) {
  625.         #
  626.         # allocated partition prior to the one of interest.
  627.         #
  628.  
  629.         $start = $fdisk{$i}->{'start'} + $fdisk{$i}->{'size'};
  630.  
  631.         &dbg("free_space $i start=$start");
  632.     } elsif ($p < $i) {
  633.         #
  634.         # allocated partition past the one of interest.
  635.         #
  636.  
  637.         $start = $fdisk{$i}->{'start'} - $start;
  638.  
  639.         &dbg("free_space $i start=$start");
  640.  
  641.         return $start;
  642.     } else {
  643.         #
  644.         # allocated partition is the one of interest.
  645.         #
  646.  
  647.         &cark("not reached\n");
  648.     }
  649.     }
  650.  
  651.     my $space = $end - $start;
  652.     &dbg("free_space $space");
  653.  
  654.     return $space;
  655. }
  656.  
  657. #
  658. # next_slice - return a slice to use for the next install
  659. #
  660.  
  661. sub next_slice {
  662.     my $need = shift || die;
  663.     my $blk = 0;
  664.  
  665.     foreach $i (1..3) {
  666.     next unless $slice_old != $i;
  667.  
  668.     &dbg("next_slice $need = $i") unless free_space($i) < $need;
  669.  
  670.     return $i unless free_space($i) < $need;
  671.     }
  672.  
  673.     &dbg("no next slice");
  674.  
  675.     return 0;
  676. }
  677.  
  678. #
  679. # lm_check - check with license manager
  680. #
  681.  
  682. sub lm_check {
  683.     my $once = shift;
  684.     my $prod = "";
  685.     local *LM;
  686.     my %opts = ();
  687.     my %lic  = ();
  688.  
  689.     open LM, "./lm -? 2>&1 |" or &cark("$!\n");
  690.  
  691.     while (<LM>) {
  692.     foreach $c (['V', 'I', 'S', 'p', 'f', 'r', 'v']) {
  693.         $opts{$c} = $c if /^\s+-$c/;
  694.     }
  695.     }
  696.  
  697.     close LM;
  698.  
  699.     open LM, "./lm -p 2>&1 |" or &cark("$!\n");
  700.  
  701.     while (<LM>) {
  702.     if (/^(e[23456789]50)/) {
  703.         $prod = $1;
  704.     }
  705.     }
  706.  
  707.     close LM;
  708.     if ($prod) {
  709.     open LM, "./lm -Z 2>&1 |" or &cark("$!\n");
  710.  
  711.     #
  712.     # If we are licensed, we abuse the fact that the last license
  713.     # spat out by the debug (-Z) reflects the licensed capability.
  714.     #
  715.     # In the future, we will use the new '-E' option which spits out perl
  716.     #
  717.  
  718.     my $state = 0;
  719.  
  720.     while (<LM>) {
  721.         if ($state == 0 && /^license {/) {
  722.         $state = 1;
  723.         }
  724.         if ($state == 1 && /^}$/) {
  725.         $state = 2;
  726.         }
  727.         if ($state == 2 && /^license {/) {
  728.         $state = 1;
  729.         %lic = ();
  730.         }
  731.         if ($state == 1) {
  732.             next unless /\s+(\S+)\s+=\s+(.*)$/;
  733.             $lic{$1} = $2;
  734.             $lic{$1} =~ s/["';'"]//g;
  735.         }
  736.         }
  737.  
  738.         close LM;
  739.  
  740.         &cark("") unless $state == 2;
  741.  
  742.         #
  743.         # Ensure version locked.  If not, that is the same as failure.
  744.         #
  745.  
  746.         if (!defined $lic{'eq_vers'}) {
  747.         note "**** Cannot upgrade with non-version locked license.";
  748.  
  749.         if (!$once) {
  750.             note "**** Attempting to get new license.";
  751.             sis "./lm -f -r -U";
  752.             &lm_check(1);
  753.             return;
  754.         } else {
  755.             &cark("**** Licensing problems.\n");
  756.         }
  757.         }
  758.  
  759.  
  760.         # The license is valid if:
  761.         # either the major number is equal and the
  762.         # minor number of the "allowed" is greater than
  763.         # or equal to the "actual"     
  764.         #                 or
  765.         # the major number of the "allowed" is greater
  766.         # than the major number of the actual
  767.         
  768.  
  769.         my ($maj1, $min1, $junk1) = split(/\./,$lic{'eq_vers'},3);
  770.         my ($maj2, $min2, $junk2) = split(/\./,$vers,3);
  771.         
  772.         if (($maj1 eq $maj2 && $min1 ge $min2) ||
  773.         ($maj1 gt $maj2)) {
  774.         return;
  775.         }
  776.  
  777.         note "**** Need new license for version $vers.";
  778.     } else {
  779.         note "**** Need license for version $vers.";
  780.     }
  781.  
  782.     if (-f "/var/eq/licenses/recent") {
  783.         sis "cd /var/eq/licenses"
  784.         . " && mv recent recent.$lic{'eq_vers'}";
  785.     }
  786.  
  787.     open LM, "./lm -f -r -U 2>&1 |" or die;
  788.  
  789.     while (<LM>) {
  790.         #
  791.         # expecting nothing output, so anything must be error message.
  792.         #
  793.  
  794.         chop;
  795.         &cark("$_\n");
  796.     }
  797.  
  798.     close LM;
  799.  
  800.     open LM, "./lm -p 2>&1 |" or die;
  801.  
  802.     while (<LM>) {
  803.         &cark("Not licensed.\n") unless /^e[23456789]50/;
  804.     }
  805.  
  806.     close LM;
  807.     }
  808.  
  809. #
  810. # zoneupdate - update zoneinfo
  811. #
  812.  
  813.     sub zoneupdate {
  814.     my $vers;
  815.     my %md5hash;
  816.     my $md5;
  817.     my $file;
  818.     my $localmd5;
  819.     local *IN;
  820.  
  821.     if (-f "/.version/eq") {
  822.         open IN, "< /.version/eq" or die;
  823.         while (<IN>) {
  824.         chop;
  825.  
  826.         if (/^EQVERS=(\d.*)$/) {
  827.             $vers = $1;
  828.         }
  829.         }
  830.     } else {
  831.         $vers = "0";
  832.     }
  833.  
  834.     close IN;
  835.  
  836.     open IN, "< ./zonehash";
  837.     while (<IN>) {
  838.         chop;
  839.  
  840.         /^(.*?) (.*?)$/;
  841.         $md5hash{$2} = $1;
  842.     }
  843.  
  844.     close IN;
  845.  
  846.     $localmd5 = 0;
  847.  
  848.     if ($vers lt "7.2.3g") {
  849.         $localmd5 = `md5 -q /.master/var/etc/localtime`;
  850.         chop($localmd5);
  851.  
  852.         if ($md5hash{$localmd5}) {
  853.         print "Your localtime has been changed. If your timezone is ";
  854.         print "within the United States,\nyou will notice that your ";
  855.         print "system is updated for the new Daylight Savings time\n";
  856.         print "rules.\n";
  857.         $file = $md5hash{$localmd5};
  858.  
  859.         system("cp /mnt/$file /mnt/.master/var/etc/localtime");
  860.         }
  861.     }
  862.     }
  863.  
  864.     sub verscheck {
  865.     my $vers;
  866.     my $live;
  867.  
  868.     $live = 0;
  869.  
  870.     if (-f "/.version/eq") {
  871.         open IN, "< /.version/eq" or die;
  872.         while (<IN>) {
  873.         chop;
  874.  
  875.         if (/^EQVERS=(\d.*)$/) {
  876.             $vers = $1;
  877.         }
  878.         }
  879.     } else {
  880.         $vers = "0";
  881.     }
  882.  
  883.     if ($vers lt "8.5.1") {
  884.         die("You must be running Version 8.5.1 to upgrade to Version 8.6.\n".
  885.             "Please upgrade your system to the latest 8.5.1 image and try again.");
  886.     }
  887.  
  888.     close IN;
  889.  
  890.     open IN, "./lm -h -U 2>&1 |" or &cark("$!\n");
  891.  
  892.     while (<IN>) {
  893.         if (/^(e[2346]50)gx-?|(e[23456]50)si-?|(ex1[78]50)-?|(vmware)-?/) {
  894.         $live = 1;
  895.         }    
  896.     }
  897.     &cark("This upgrade is not valid on your hardware platform.  Please contact Coyote Point Support.") unless $live == 1;
  898.     }
  899.  
  900. #
  901. # setup - perform necessary setup.
  902. #
  903.  
  904.     sub setup {
  905.  
  906.     #
  907.     # cleanup any old unsaved kernel dump info
  908.     #
  909.     system "/sbin/savecore -c >/dev/null 2>&1";
  910.  
  911.     open DBG, ">> $dbgfile";
  912.  
  913.     &root_disk;
  914.     &fdisk_reset($disk);
  915.  
  916.     my $tot = $fdisk{'cyl'} * $fdisk{'hd'} * $fdisk{'sec'};
  917.  
  918.     note "root disk: $disk, root slice $slice_old, capacity $tot sectors";
  919.  
  920.     $slice_xtra = 4 unless $tot < 15625000;    # 8Gig in sectors.
  921.  
  922.     #
  923.     # Determine if we are upgrading from 2.2.8 or newer.
  924.     #
  925.  
  926.     chop($oslevel = `uname -r`);
  927.     chop($opsys = `uname -s`);
  928.  
  929.     if ($oslevel =~ /^[23][.]/) {
  930.         #
  931.         # Ancient.
  932.         #
  933.  
  934.         &cark("Cannot upgrade from 2.2.8 to 7.1.0");
  935.     } elsif ($oslevel =~ /^4[.][789]/) {
  936.         #
  937.         # Slightly newer.
  938.         #
  939.         
  940.         $oslevel   = 4;
  941.  
  942.         &kluges;
  943.     } elsif ($oslevel =~ /^4[.]1[01]/) {
  944.         $oslevel   = 4;
  945.     } elsif ($opsys =~ /^EQ\/OS/) {
  946.         $oslevel   = 4;
  947.     } else {
  948.         &cark("Unsupported OS level: $oslevel\n");
  949.     }
  950.  
  951.     chdir "/usr/l7up" or &cark("$!\n");
  952.  
  953.     if ($opt_G) {
  954.             open(STDOUT, '>>'.$outputfile ) or die $!;
  955.             open(STDERR, '>>'.$outputfile ) or die $!;
  956.     }    
  957.         else {    
  958.           open(STDOUT, "| tee -a $logfile") or &cark("$!\n");  
  959.         open(STDERR, ">&STDOUT") or &cark("$!\n");
  960.         }
  961.         select(STDOUT); $| = 1;
  962.         select(STDERR); $| = 1;
  963.  
  964.     #
  965.     # show current level (debug assist)
  966.     #
  967.  
  968.     open IN, "./lm -v |" or die;
  969.     map { ¬e("lm: $_") } <IN>;
  970.     close IN;
  971.  
  972.     #
  973.     # show current mounts in debug log
  974.     #
  975.  
  976.     open IN, "/sbin/mount |" or die;
  977.     map { &dbg($_) } <IN>;
  978.     close IN;
  979.  
  980.     open IN, "/sbin/fdisk -s $disk |" or die;
  981.     map { &dbg($_) } <IN>;
  982.     close IN;
  983.  
  984.     #
  985.     # Give up if there is more than one active partition.
  986.     #
  987.  
  988.     my $count = 0;
  989.  
  990.     foreach $s (1..4) {
  991.         next unless defined($fdisk{$s});
  992.         next unless (oct($fdisk{$s}->{'flags'}) & 0x80);
  993.         $count++;
  994.     }
  995.  
  996.     &cark("No active partition.\n") unless $count > 0;
  997. #    &cark("Too many active partitions: $count.\n") unless $count == 1;
  998.     }
  999.  
  1000. #
  1001. # lsmash - smash out sym links
  1002. #
  1003.     sub lsmash {
  1004.     local $f = shift;
  1005.     local $m = "";
  1006.  
  1007.     foreach $c (split('/', $f)) {
  1008.         $m .= "/$c";
  1009.         if (-l "/mnt/$m") {
  1010.         $m = readlink "/mnt/$m";
  1011.         }
  1012.     }
  1013.  
  1014.     &dbg("lsmash: $f -> $m");
  1015.  
  1016.     return $m;
  1017.     }
  1018.  
  1019. #
  1020. # unshad - unshadow
  1021. #
  1022.  
  1023.     sub __unshad {
  1024.     local $f = shift;
  1025.     local $m = "/.master$f";
  1026.  
  1027.     return $m unless !-f "/mnt$m";
  1028.     return $m unless !-d dirname("/mnt$m");
  1029.     return $f
  1030.     }
  1031.  
  1032.     sub unshad {
  1033.     local $f = shift;
  1034.         local $s = &__unshad($f);
  1035.  
  1036.     &dbg("unshad: $f -> $s");
  1037.     
  1038.     return $s;
  1039.     }
  1040.  
  1041.     sub xlate {
  1042.     local $f = shift;
  1043.  
  1044.     &dbg("xlate: $f -> $xlate{$f}") unless !defined($xlate{$f});
  1045.     
  1046.     return $xlate{$f} unless !defined($xlate{$f});
  1047.  
  1048.     return $f;
  1049.     }
  1050.  
  1051. #
  1052. # preserve - preserve old version of file
  1053. #
  1054.  
  1055.     sub preserve {
  1056.     local $f = shift;
  1057.     local $m = "/mnt" . &unshad(&lsmash(&xlate($f)));
  1058.     local @inode;
  1059.  
  1060.     $f = readlink $f unless ! -l $f;
  1061.     $f = &xlate($f)  unless   -f $f;
  1062.     
  1063.     note "  ** preserve $f";
  1064.  
  1065.     if (-f "$f") {
  1066.         if (-f "$m") {
  1067.         @inode = stat("$m");
  1068.  
  1069.         rename "$m", "${m}.dist";
  1070.         } else {
  1071.         @inode = stat("$f");
  1072.         }
  1073.  
  1074.         if ($f ne $m) {
  1075.             sis "cp $f $m";
  1076.         }
  1077.         
  1078.         chown $inode[$ST_UID], $inode[$ST_GID], "$m";
  1079.         chmod $inode[$ST_MODE], "$m";
  1080.     }
  1081.     }
  1082.  
  1083. #
  1084. # d_preserve - preserve old contents of directory (not recursive)
  1085. #
  1086.  
  1087.     sub d_preserve {
  1088.     local $d = shift;
  1089.     local $f;
  1090.     local @inode;
  1091.  
  1092.  
  1093.     if (-d "$d") {
  1094.         local *DP;
  1095.  
  1096.         sis "mkdir -p /mnt/$d";
  1097.  
  1098.         note "  ** preserve $d/";
  1099.  
  1100.         opendir(DP, $d) || &cark("$!\n");
  1101.  
  1102.         foreach $f (grep { -f "$d/$_" } readdir(DP)) {
  1103.         preserve "$d/$f";
  1104.         }
  1105.  
  1106.         closedir DP;
  1107.     }
  1108.     }
  1109.  
  1110.     sub new_fstab {
  1111.     local *OUT;
  1112.     my $slice = $slice_map{'/'};
  1113.  
  1114.     note "**** new fstab";
  1115.  
  1116.     unlink "/mnt/etc/fstab";
  1117.  
  1118.     open OUT, ">/mnt/etc/fstab" or &cark("$!\n");
  1119.  
  1120.     if ($slice_xtra) {
  1121.         local $xx = "b    none    swap    sw    0 0";
  1122.  
  1123.         print OUT "/dev/${disk}s$slice_xtra" . "${xx}\n";
  1124.         &dbg(     "/dev/${disk}s$slice_xtra" . "${xx}");
  1125.  
  1126.         &disklabel_reset($disk, $slice_xtra);
  1127.     }
  1128.     if ($slice_xtra && $label{'a'}->{'size'} > 4000000
  1129.         && $label{'a'}->{'fstype'} =~ "4.2BSD") {
  1130.         #
  1131.         # If there is an 'a' partition, we will attempt to use this as
  1132.         # /var/crash
  1133.         #
  1134.         local $xx = "a    /var/crash    ufs    rw    2 2";
  1135.  
  1136.         print OUT "/dev/${disk}s$slice_xtra" . "${xx}\n";
  1137.         &dbg(     "/dev/${disk}s$slice_xtra" . "${xx}");
  1138.     }
  1139.     if ($slice_xtra && $label{'b'}->{'size'} > 4000000
  1140.         && $label{'b'}->{'fstype'} =~ "swap") {
  1141.         #
  1142.         # If there is a 'b' partition, we will attempt to use this as
  1143.         # dump device
  1144.         #
  1145.  
  1146.         sis 'echo dumpdev="/dev/${disk}s${slice_xtra}b"'
  1147.         . '>> /mnt/.master/var/etc/rc.conf';
  1148.     }
  1149.  
  1150.     print OUT "$slice    /    ufs    ro    1 1\n";
  1151.     &dbg(     "$slice    /    ufs    ro    1 1");
  1152.  
  1153.     close OUT;
  1154.     }
  1155.  
  1156.     sub check_gx {
  1157.     my $rc;
  1158.     open IN, "./lm -h -U 2>&1 |" or &cark("$!\n");
  1159.  
  1160.     while (<IN>) {
  1161.         if (/^(e[346]50)gx-?/) {
  1162.             $rc = 1;
  1163.         }    
  1164.         else {
  1165.             $rc = 0;
  1166.         }
  1167.     }
  1168.     close IN;
  1169.     return $rc;
  1170.     }
  1171.  
  1172.     sub munge_rc_conf {
  1173.     local *IN;
  1174.     local *OT;
  1175.  
  1176.     my %conf = ();
  1177.     my @lval = ();
  1178.  
  1179.     #
  1180.     # Determine {DISK} and {NET0} and {NET1} from existing rc.conf
  1181.     #
  1182.     my $net0 = "fxp0";
  1183.     my $net1 = "fxp1";
  1184.     my $vlan1 = "";
  1185.     my $agr0 = "";
  1186.     my $agrport0 = "";
  1187.     my $agrport1 = "";
  1188.     my $nix  = 0;
  1189.     my $dump = '';
  1190.     my $vlanif1 = 0;
  1191.  
  1192.     #
  1193.     # As part of NTP modification we will need two more extra
  1194.     # variable which are not part of earlier rc.conf into new
  1195.     #
  1196.     my $ntpd = "xntpd_enable";
  1197.     my $ntpf = "xntpd_flags";
  1198.     my $routes = "static_routes";
  1199.  
  1200.     open IN, "< /etc/rc.conf" or &cark("$!\n");
  1201.  
  1202.     while (<IN>) {
  1203.         if (/^EQ_IF_0=(.*)$/) {
  1204.  
  1205.         $net0 = $1;
  1206.         $net0 =~ s/^(["''"])(.*)\1/$2/;
  1207.  
  1208.         &dbg("net0 = $net0");
  1209.         
  1210.         $nix |= 1;
  1211.         } elsif (/^EQ_IF_1=(.*)$/) {
  1212.  
  1213.         $net1 = $1;
  1214.         $net1 =~ s/^(["''"])(.*)\1/$2/;
  1215.  
  1216.         &dbg("net1 = $net1");
  1217.         
  1218.         $nix |= 2;
  1219.         } elsif (/^EQ_VLIF_0=(.*)$/) {
  1220.  
  1221.         $vlan1 = $1;
  1222.         $vlan1 =~ s/^(["''"])(.*)\1/$2/;
  1223.  
  1224.         &dbg("vlan1 = $vlan1");
  1225.         
  1226.         $nix |= 2;
  1227.         } elsif (/^EQ_AGRIF_0=(.*)$/) {
  1228.  
  1229.         $agr0 = $1;
  1230.         $agr0 =~ s/^(["''"])(.*)\1/$2/;
  1231.  
  1232.         &dbg("agr0 = $agr0");
  1233.         
  1234.         $nix |= 2;
  1235.         } elsif (/^EQ_AGRPORT_0=(.*)$/) {
  1236.  
  1237.         $agrport0 = $1;
  1238.         $agrport0 =~ s/^(["''"])(.*)\1/$2/;
  1239.  
  1240.         &dbg("agrport0 = $agrport0");
  1241.         
  1242.         $nix |= 2;
  1243.         } elsif (/^EQ_AGRPORT_1=(.*)$/) {
  1244.  
  1245.         $agrport1 = $1;
  1246.         $agrport1 =~ s/^(["''"])(.*)\1/$2/;
  1247.  
  1248.         &dbg("agrport1 = $agrport1");
  1249.         
  1250.         $nix |= 2;
  1251.         } elsif (/-r ([^ ]*) .* [.] \1/) {
  1252.         &dbg("source $1");
  1253.  
  1254.         close IN;
  1255.         open IN, "<$1";
  1256.         }
  1257.     }
  1258.  
  1259.     close IN;
  1260.  
  1261.     my $rc = check_gx();
  1262.     if (($rc == 1) && ($agr0 eq '')) {
  1263.         $vlan1 = "vlan1";
  1264.         $agr0 = "agr0";
  1265.         $agrport0 = "em0";
  1266.         $agrport1 = "em1";
  1267.     }
  1268.  
  1269.     if ($nix != 3) {
  1270.         #
  1271.         # not the newer format.  Look for old style.
  1272.         #
  1273.  
  1274.         $nix = 0;
  1275.  
  1276.         open IN, "</etc/rc.conf" or &cark("$!\n");
  1277.  
  1278.         while (<IN>) {
  1279.         if (/^ifconfig_lo0=/) {
  1280.             ;
  1281.         } elsif (/^ifconfig_([^_=0-9]*0)=(.*)$/) {
  1282.  
  1283.             $net0 = $1;
  1284.  
  1285.             &dbg("net0 = $net0");
  1286.             
  1287.             $nix |= 1;
  1288.         } elsif (/^ifconfig_([^_=0-9]*1)=(.*)$/) {
  1289.  
  1290.             $net1 = $1;
  1291.  
  1292.             &dbg("net1 = $net1");
  1293.             
  1294.             $nix |= 2;
  1295.         } elsif (/^dumpdev=(.*)$/) {
  1296.             if ($1 eq '"/dev/da0s4b"') {
  1297.             $dump = $1;
  1298.             }
  1299.         }
  1300.         }
  1301.  
  1302.         close IN;
  1303.     }
  1304.  
  1305.     &cark("Cannot determine {NET0} and {NET1}\n") unless $nix == 3;
  1306.  
  1307.     #
  1308.     # Expand the template out
  1309.     #
  1310.  
  1311.     open IN, "< ./etc.rc.conf.tmpl" || &cark("$!");
  1312.     open OT, "> /mnt/etc/rc.conf"   || &cark("$!");
  1313.  
  1314.     while (<IN>) {
  1315.         next if /^{DUMPDEV}/;
  1316.         if ($dump eq '' && (/^dumpdev/ || /^savecore_flags/)) {
  1317.         next;
  1318.         }
  1319.  
  1320.         s/{DISK}/$disk/g;
  1321.         s/{NET0}/$net0/g;
  1322.         s/{NET1}/$net1/g;
  1323.         s/{VLAN1}/$vlan1/g;
  1324.         s/{AGR0}/$agr0/g;
  1325.         s/{AGRPORT0}/$agrport0/g;
  1326.         s/{AGRPORT1}/$agrport1/g;
  1327.  
  1328.         if (/^(\S+)=(.*)/) {
  1329.         push @lval, $1;
  1330.         }
  1331.  
  1332.         print OT;
  1333.     }
  1334.  
  1335.     close OT;
  1336.     close IN;
  1337.         
  1338.     #
  1339.     # Everything below this point preserves existing pieces of the
  1340.     # configuration, which we don't want sometimes.
  1341.     #
  1342.  
  1343.     if ($no_preserve == 0) {
  1344.  
  1345.         #
  1346.         # Push NTPD variable into lval
  1347.         #
  1348.         push @lval, $ntpd;
  1349.         push @lval, $ntpf;
  1350.         push @lval, $routes;
  1351.  
  1352.         #
  1353.         # Now that that has been accomplished, we need to determine what
  1354.         # modifications to the old need to be migrated to the new.
  1355.         #
  1356.  
  1357.         open IN, "< /etc/rc.conf" or &cark("$!\n");
  1358.  
  1359.         #
  1360.         # Look for entries we wish to preserve and add them to %conf
  1361.         #
  1362.         
  1363.         while (<IN>) {
  1364.         if (/-r ([^ ]*) .* [.] \1/) {
  1365.             &dbg("source $1");
  1366.  
  1367.             close IN;
  1368.             open IN, "< $1";
  1369.         } elsif (/^(\S+)=(.*)/) {
  1370.             if (grep(/$1/, @lval)) {
  1371.             next if $1 =~ "network_interfaces";
  1372.             #
  1373.             # It is in the new conf (@lval) so we
  1374.             # snarf a copy.
  1375.             #
  1376.             $conf{$1} = $2;
  1377.  
  1378.             &dbg("conf[$1] = $2");
  1379.             } elsif (/(ifconfig_[^=]+)=(.*)/) {
  1380.             next if $1 =~ "ifconfig_lo0";
  1381.  
  1382.             #
  1383.             # Try to preserve non-conflicting ifconfigs.
  1384.             # These might be aliases.
  1385.             #
  1386.  
  1387.             $conf{$1} = $2;
  1388.  
  1389.             &dbg("conf[$1] = $conf{$1}");
  1390.                  if ($1 eq "ifconfig_vlan1") {
  1391.                     $vlanif1 = 1;
  1392.             }
  1393.             } elsif (/(route_[^=]+)=(.*)/) {
  1394.             #
  1395.             # Preserve static routes list
  1396.             #
  1397.             $conf{$1} = $2;
  1398.             } else {
  1399.             &dbg("old conf: $_");
  1400.             }
  1401.         }
  1402.         }
  1403.  
  1404.         close IN;
  1405.         if ($vlanif1 == 0) {
  1406.         $ifconfig1 = "ifconfig_" . $net0;
  1407.         $ifconfig2 = "ifconfig_" . $vlan1;
  1408.         &dbg("Adding $ifconfig2");
  1409.              $conf{$ifconfig2} = $conf{$ifconfig1};
  1410.         }
  1411.  
  1412.         &dbg("lval");
  1413.         &dbg_array(\@lval);
  1414.         &dbg("conf");
  1415.         &dbg_hash(\%conf);
  1416.         
  1417.         #
  1418.         # Add to %fnoc some potentially new entries
  1419.         #
  1420.  
  1421.         my %fnoc = ();
  1422.  
  1423.         if ($slice_xtra) {
  1424.         $fnoc{'dumpdev'} = '"/dev/' . "${disk}s${slice_xtra}" . 'e"';
  1425.         sis "cd /mnt/.master/dev && ./MAKEDEV ${disk}s${slice_xtra}e";
  1426.         }
  1427.  
  1428.         #
  1429.         # Run thru the new rc.conf, preserving those entries we wish to preserve.
  1430.         #
  1431.  
  1432.         my $new_conf = "/mnt/.master/var/etc/rc.conf-eq";
  1433.  
  1434.         open IN, "< /mnt/etc/rc.conf" or &cark("$!\n");
  1435.         open OT, "> ${new_conf}.new" or &cark("$!\n");
  1436.  
  1437.         my $discard = 1;
  1438.         my %seen = ();
  1439.  
  1440.       line:
  1441.         while (<IN>) {
  1442.         my $hash = '#';
  1443.  
  1444.         next line if ($discard and /^$hash/);
  1445.  
  1446.         &dbg("_ = $_");
  1447.  
  1448.         if (/-r ([^ ]*) .* [.] \1/) {
  1449.             &dbg("source $1");
  1450.  
  1451.             close IN;
  1452.             open IN, "< /mnt/.master/$1" or &cark("$!\n");
  1453.  
  1454.             $discard = 0;
  1455.  
  1456.             next line;
  1457.         }
  1458.  
  1459.         foreach $k (keys %conf) {
  1460.             if (/^($k)=(.*)/) {
  1461.             &dbg("conf: $k '$2' :: '$conf{$k}'");
  1462.  
  1463.             if ($2 ne $conf{$k}) {
  1464.                 note "  ** updating rc.conf entry:\n\t$k=$conf{$k}";
  1465.                 print OT "$k=$conf{$k}\n";
  1466.             }
  1467.             delete $conf{$k};
  1468.  
  1469.             next line;
  1470.             }
  1471.         }
  1472.  
  1473.         foreach $k (keys %fnoc) {
  1474.             if (/^($k)=(.*)/) {
  1475.             if ($2 ne $fnoc{$k}) {
  1476.                 note "  ** updating rc.conf entry:\n\t$k=$fnoc{$k}";
  1477.                 print OT "$k=$fnoc{$k}\n";
  1478.             }
  1479.  
  1480.             delete $fnoc{$k};
  1481.  
  1482.             next line;
  1483.             }
  1484.         }
  1485.  
  1486.         #
  1487.         # Not overridden.
  1488.         #
  1489.         print OT $_;
  1490.         }
  1491.         
  1492.         &dbg("conf remains");
  1493.         &dbg_hash(\%conf);
  1494.         &dbg("fnoc remains");
  1495.         &dbg_hash(\%fnoc);
  1496.  
  1497.         #
  1498.         # Anything remaining will be new entries which we append.
  1499.         #
  1500.  
  1501.         my $once = 0;
  1502.  
  1503.         foreach $k (keys %conf) {
  1504.         if (!$once++) {
  1505.             note "  ** preserving rc.conf entry:";
  1506.         }
  1507.         note "\t$k=$conf{$k}";
  1508.         print OT "$k=$conf{$k}\n";
  1509.         }
  1510.  
  1511.         foreach $k (keys %fnoc) {
  1512.         if (!$once++) {
  1513.             note "  ** preserving /etc/rc.conf entry:";
  1514.         }
  1515.         note "\t$k=$fnoc{$k}";
  1516.         print OT "$k=$fnoc{$k}\n";
  1517.         }
  1518.  
  1519.         close OT;
  1520.         close IN;
  1521.  
  1522.         #
  1523.         # Commit to the new one.
  1524.         #
  1525.  
  1526.         sis "cp ${new_conf}.new .";
  1527.         sis "mv ${new_conf}.new ${new_conf}";
  1528.     } #if no)preserve is 0
  1529.     }
  1530.  
  1531. #
  1532. # support_hacks - hacks for support
  1533. #
  1534.  
  1535.     sub support_hacks {
  1536.     local *DIR;
  1537.     my $dir = "/usr/local/etc/rc.d";
  1538.  
  1539.     opendir DIR, $dir or return;
  1540.  
  1541.     my @contents =
  1542.         map "$dir/$_",
  1543.         sort grep /_eq_support\.sh$/,
  1544.         readdir DIR;
  1545.  
  1546.     closedir DIR;
  1547.  
  1548.     foreach (@contents) {
  1549.         preserve $_;
  1550.  
  1551.         chmod '0644', "/mnt/$_";
  1552.  
  1553.         note "**** disabling execute on $_";
  1554.     }
  1555.     }
  1556.  
  1557.     sub chg_snmpd {
  1558.     local *PWE;
  1559.     local *PWD;
  1560.  
  1561.     my $OLD = "/var/eq/snmpd.cnf";
  1562.     my $NEW = "/var/eq/snmpd.cnf.new";
  1563.     my $need_change = 0;
  1564.  
  1565.     if (!-f "$OLD") {
  1566.         note "No snmpd.cnf\n";
  1567.         return;
  1568.     }
  1569.     open PWD, "<$OLD";
  1570.  
  1571. # Checking if we need to rewrite the file
  1572.     while (<PWD>) {
  1573.         if (/^\s*sysObjectID/) {
  1574.         my $new = $_;
  1575.         my @all = split(" ", $new);
  1576.         if ($all[1] eq "0.0") {
  1577.             $need_change = 1;
  1578.         }
  1579.         }
  1580.     }
  1581.  
  1582.     close PWD;
  1583.     if ($need_change != 1) {
  1584.         return;
  1585.     }
  1586.  
  1587.     open PWE, ">$NEW";
  1588.     open PWD, "<$OLD";
  1589.  
  1590.     while (<PWD>) {
  1591.         if (/^\s*sysObjectID/) {
  1592.         my $correct_line  = "sysObjectID 1.3.6.1.4.1.24427.2.2.2.1\n";
  1593.         print PWE "$correct_line";
  1594.         } else {
  1595.         print PWE;
  1596.         }
  1597.     }
  1598.     close PWD;
  1599.     close PWE;
  1600.  
  1601. #saving old file in /var/eq/snmpd.cnf.OLD
  1602.     rename "$OLD", "$OLD.OLD";
  1603.     rename "$NEW", "$OLD";
  1604.     }
  1605.  
  1606.     sub munge_users {
  1607.     local *PWD;
  1608.     local *PWE;
  1609.     my %users = ();
  1610.  
  1611.     my $mve = "/mnt/.master/var/eq";
  1612.     open PWD, "</var/eq/users";
  1613.  
  1614.     while (<PWD>) {
  1615.         if (/^\#/) {
  1616.         } elsif (/^(touch|look):/) {
  1617.         my $posterity = $_;
  1618.         my ($user, $p) = split(/:/);
  1619.         $users{$user} = $posterity;
  1620.         }
  1621.     }
  1622.  
  1623.     close PWD;
  1624.  
  1625.     open PWD, "<$mve/eq.conf";
  1626.     open PWE, ">$mve/eq.conf.new";
  1627.  
  1628.     while (<PWD>) {
  1629.         print PWE;
  1630.     }
  1631.  
  1632.     close PWD;
  1633.  
  1634.     foreach $user (keys %users) {
  1635.         my ($_user, $_p) = split(/[:\n]/, $users{$user});
  1636.         print PWE "\nuser $_user {\n";
  1637.         print PWE "  desc                 = \"user $_user\";\n";
  1638.         print PWE "  password             = \"$_p\";\n";
  1639.         if ($_user eq "touch") {
  1640.         print PWE "  change               = \"all, global\";\n}\n";
  1641.         } else {
  1642.         print PWE "  read                 = \"all, global\";\n}\n";
  1643.         }
  1644.     }
  1645.  
  1646.     close PWE;
  1647.     rename "$mve/eq.conf", "$mve/eq.conf.OLD";
  1648.     rename "$mve/eq.conf.new", "$mve/eq.conf";
  1649.     }
  1650.  
  1651.     sub ask_migrate_failover {
  1652.  
  1653.     if ($opt_G) {
  1654.         print "\nDo you wish to preserve failover configuration? [y/n]\n";
  1655.         }
  1656.     while (1) {
  1657.         my $ans;
  1658.         if (!$opt_G) {
  1659.              print "\nDo you wish to preserve failover configuration? [y/n]";
  1660.         }    
  1661.  
  1662.         if ($opt_b) {
  1663.         print "Y\n";
  1664.         return 1;
  1665.         }
  1666.  
  1667.         $ans = &get_answer;
  1668.  
  1669.         return 1 if ($ans =~ /^[Yy]/);
  1670.         return 0 if ($ans =~ /^[Nn]/);
  1671.     }
  1672.     }
  1673.  
  1674.     sub munge_master_passwd {
  1675.     local *PWD;
  1676.     local *PWE;
  1677.     my %users = ();
  1678.  
  1679.     my $mve = "/mnt/.master/var/etc";
  1680.     open PWD, "</var/etc/master.passwd";
  1681.  
  1682.     while (<PWD>) {
  1683.         if (/^\#/) {
  1684.         } elsif (/^(toor|daemon|operator|bin|games|news|man):/) {
  1685.         } elsif (/^(uucp|xten|pop|nobody|l7up|cpsup):/) {
  1686.         } else {
  1687.         my $posterity = $_;
  1688.         my ($user, $p, $u, $g, $x, $y, $z, $n, $d, $s) = split(/:/);
  1689.         $users{$user} = $posterity;
  1690.         }
  1691.     }
  1692.  
  1693.     close PWD;
  1694.  
  1695.     open PWD, "<$mve/master.passwd";
  1696.     open PWE, ">$mve/master.passwd.new";
  1697.  
  1698.     while (<PWD>) {
  1699.         my ($user, $p, $u, $g, $x, $y, $z, $n, $d, $s) = split(/:/);
  1700.  
  1701.         if (/^\#/) {
  1702.         print PWE;
  1703.         } elsif (defined($users{$user})) {
  1704.         my ($_user, $_p, $_u, $_g, $_x, $_y, $_z, $_d, $_s)
  1705.             = split(/:/, $users{$user});
  1706.  
  1707.         #
  1708.         # user exists in new system -- migrate passwd.
  1709.         #
  1710.  
  1711.         print PWE "$user:$_p:$u:$g:$x:$y:$z:$n:$d:$s";
  1712.  
  1713.         delete $users{$user};
  1714.         } else {
  1715.         print PWE;
  1716.         }
  1717.     }
  1718.  
  1719.     close PWD;
  1720.  
  1721.     foreach $user (keys %users) {
  1722.         my ($_user, $p, $u, $g, $x, $y, $z, $n, $d, $s)
  1723.         = split(/:/, $users{$user});
  1724.  
  1725.         note "*=*=*=* NOT migrating user $user.";
  1726.     }
  1727.  
  1728.     close PWE;
  1729.     
  1730.     rename "$mve/master.passwd" , "$mve/master.passwd.OLD";
  1731.     
  1732.     sis "pwd_mkdb -p -d $mve $mve/master.passwd.new";
  1733.     
  1734.     }
  1735.  
  1736.     sub keep_loghosts {
  1737.         my @oldfile;
  1738.         my $line;
  1739.         my $loghost = 0;
  1740.         my $OSC;
  1741.         my $NSC;
  1742.         my @tmpsc = ();
  1743.         my $already = 0;
  1744.         open OSC, "< /etc/syslog.conf";
  1745.         @oldfile = <OSC>;
  1746.         open NSC, "< /mnt/.master/var/etc/syslog.conf";
  1747.         foreach $line (@oldfile) {
  1748.         chomp($line);
  1749.             if ($line =~ /^\*\.\*.*@.*/) {
  1750.                 $loghost = $line;
  1751.                 last;
  1752.             }
  1753.         }
  1754.         while ($line = <NSC>) {
  1755.             chomp($line);
  1756.         # match only the commented-out example!
  1757.             if (!$already && ($line =~ /^#\*\.\*.*@/) && $loghost) {
  1758.                 push @tmpsc, $loghost;
  1759.                 $already = 1;
  1760.             } else {
  1761.                 push @tmpsc, $line;
  1762.             }
  1763.         }
  1764.         close OSC;
  1765.         close NSC;
  1766.         open NSC, "> /mnt/.master/var/etc/syslog.conf";
  1767.         foreach $line (@tmpsc) {
  1768.             print NSC "$line\n";
  1769.         }
  1770.     close NSC;
  1771.     }
  1772.  
  1773. #
  1774. # phase3 -
  1775. #
  1776.  
  1777.     sub phase3 {
  1778.  
  1779.     #
  1780.     # cleanup /var/crash and clear savecore flag.
  1781.     #
  1782.  
  1783.     system "rm -f /var/crash/*.core";
  1784.     system "rm -f /var/crash/kernel.*";
  1785.     system "rm -f /var/crash/vmcore.*";
  1786.     system "/sbin/savecore -c 2>/dev/null";
  1787.  
  1788.     &new_fstab;
  1789.  
  1790.     # We have to be careful with rc_conf since
  1791.     # it contains hardware-specific information that can't be 
  1792.     # fixed during an upgrade.
  1793.     # We go and pull in the hardware-specific information in munge_rc_conf, 
  1794.     # and then
  1795.     # skip the rest of the function if we're returning the system to defaults.
  1796.     &munge_rc_conf;
  1797.  
  1798.     if ($no_preserve == 0) {
  1799.         &munge_master_passwd;
  1800.         &keep_loghosts;
  1801.  
  1802.         #
  1803.         # Preserve the newer machine's SSH host key(s) if present.
  1804.         # Old machines will get a new one automatically on first boot
  1805.         # of new system.
  1806.         #
  1807.  
  1808.         my @ssh = (
  1809.                'ssh_host_dsa_key',
  1810.                'ssh_host_dsa_key.pub',
  1811.                'ssh_host_key',
  1812.                'ssh_host_key.pub',
  1813.                'ssh_host_rsa_key',
  1814.                'ssh_host_rsa_key.pub',);
  1815.  
  1816.         foreach $f (@ssh) {
  1817.         preserve "/etc/ssh/$f";
  1818.         }
  1819.  
  1820.         if ($opt_k) {
  1821.         preserve "/usr/home/cpsup/.ssh/authorized_keys";    
  1822.         }
  1823.         
  1824.         if ($opt_e) {
  1825.         preserve "/usr/home/eqsupport/.ssh/authorized_keys";    
  1826.         }    
  1827.         
  1828.         if ($pres_eq_conf == 1) {
  1829.  
  1830.         preserve "/etc/eq.conf";
  1831.  
  1832.         if ($set_use_ssl == 1) {
  1833.             system "/usr/l7up/convert_default -i/mnt/.master/var/eq/eq.conf -v ".
  1834.                 "use_ssl_only -d \!use_ssl_only -o /mnt/.master/var/eq/eq.conf";
  1835.         }
  1836.  
  1837.         my $running_vers = &curr_vers();
  1838.                 #
  1839.                 # The translate_85_86 program takes the contents of the running system's
  1840.             # eq.conf, rc.conf-eq and switch.conf and creates a new eq.conf that is 
  1841.             # compatible with 8.6
  1842.                 #
  1843.             print "migrating network configurations.\n";
  1844.            sis "/usr/l7up/./translate_85_86 -i /mnt/.master/var/eq/eq.conf -p /mnt/.master/var/eq/eq.conf";
  1845.         } else {
  1846.         system "rm -rf /mnt/.master/var/eq/eq.conf";
  1847.         system "touch /mnt/.master/var/eq/eq.conf";
  1848.         print "eq.conf not preserved.\n";
  1849.         }
  1850.               
  1851.             if ($pres_en_conf == 1) {
  1852.                 preserve "/etc/envoy.conf";
  1853.             } else {
  1854.                 system "rm -rf /mnt/.master/var/eq/envoy.conf";
  1855.                 system "touch /mnt/.master/var/eq/envoy.conf";
  1856.                 print "envoy.conf not preserved.\n";
  1857.             }
  1858.  
  1859.         if ($pres_sw_conf == 1) {
  1860.         preserve "/etc/switch.conf";
  1861.         } else {
  1862.         system "rm -rf /mnt/.master/var/eq/switch.conf";
  1863.         system "touch /mnt/.master/var/eq/switch.conf";
  1864.         print "switch.conf not preserved.\n";
  1865.         }
  1866.         preserve "/etc/natd.conf";
  1867.         preserve "/etc/resolv.conf";
  1868.         preserve "/etc/ntp.conf";
  1869.         #preserve "/etc/syslog.conf";    # Now we preserve only lines with @.
  1870.         preserve "/etc/ntp.drift";
  1871.         preserve "/etc/hosts";
  1872.         preserve "/etc/ipfw.conf";
  1873.         preserve "/etc/localtime";
  1874.         preserve "/etc/eq.previous";
  1875.         preserve "/eq.previous";
  1876.         preserve "/etc/tac_client.conf";
  1877.  
  1878.         #
  1879.         # Need to preserve the cluster certificates.
  1880.         #
  1881.  
  1882.         if (-d "/var/eq/ssl") {
  1883.         sis "find /var/eq/ssl -print | cpio -pdumL /mnt/.master/";
  1884.         }
  1885.  
  1886.         #
  1887.         # Need to preserve the certificate and the key for equalizer if we
  1888.         # have one else create it
  1889.         #
  1890.         if (-d "/var/eq/eqssl") {
  1891.         sis "find /var/eq/eqssl -print | cpio -pdumL /mnt/.master/";
  1892.         } else {
  1893.         sis "mkdir -p /mnt/.master/var/eq/eqssl"; 
  1894.         }
  1895.         #
  1896.         # Need to preserve the SKS
  1897.         #
  1898.         if (-d "/var/eq/sks") {
  1899.         sis "find /var/eq/sks -print | cpio -pdumL /mnt/.master/";
  1900.         }
  1901.  
  1902.         #
  1903.         # Need to preserve any licenses
  1904.         #
  1905.  
  1906.         d_preserve "/var/eq/licenses";
  1907.  
  1908.         #
  1909.         # Need to preserve any responders.
  1910.         #
  1911.  
  1912.         if (-d "/var/eq/responder") {
  1913.         sis "find /var/eq/responder -print | cpio -pdumL /mnt/.master/";
  1914.         }
  1915.     } 
  1916.  
  1917.     #
  1918.     # Preserve license files only while upgrade with default configuration.
  1919.     #
  1920.     if ($opt_C && $opt_l) {
  1921.         d_preserve "/var/eq/licenses";
  1922.     }
  1923.  
  1924.     if ($opt_S) {
  1925.         note " ** install SNMP ";
  1926.  
  1927.         sis "tar zxf ./snmp.tgz -C /mnt 2>/usr/l7up/tar.out";
  1928.  
  1929.         if ($no_preserve == 0) {
  1930.         &chg_snmpd;
  1931.         preserve "/var/eq/snmpd.cnf";
  1932.         preserve "/var/eq/traps.cnf";
  1933.         }
  1934.     }
  1935.  
  1936.     #
  1937.     # Execute any additional version-specific upgrade script
  1938.     #
  1939.  
  1940.     sis "./upgrade.$vers.pl -p 2" if -x "./upgrade.$vers.pl";
  1941.  
  1942.     #
  1943.     # If desired, attempt to migrate failover config
  1944.     # fo_migrate will leave the interface disable flag
  1945.     # set, so we use perl to yank it out. 
  1946.     #
  1947.     if ($no_preserve == 0) {
  1948.         if((-f "/etc/eq.static") && (-f "/etc/eq.conf")) {
  1949.         if (ask_migrate_failover()) {
  1950.             sis "./fo_migrate -i/etc/eq.static"
  1951.             . " -o/mnt/.master/var/eq/eq.conf -c/etc/eq.conf";
  1952.             sis "perl -pi -e 's/^.*if_flag.*//' /mnt/.master/var/eq/eq.conf";
  1953.         }
  1954.         }
  1955.  
  1956.         #
  1957.         # If desired, attempt to migrate user config
  1958.         #
  1959.  
  1960.         if((-f "/var/eq/users")) {
  1961.         &munge_users;
  1962.         }
  1963.     }
  1964.  
  1965.     #
  1966.     # Last step here is to check for any EQ support hacks and
  1967.     # copy them and disable the execue bits on them
  1968.     #
  1969.  
  1970.     &support_hacks();
  1971.  
  1972.     #
  1973.     # save copies of debug and log to new filesystem.
  1974.     #
  1975.  
  1976.     if (-f $logfile && -f $dbgfile && -d "/mnt/usr/home/cpsup") {
  1977.         select((select(DBG), $| = 1)[0]);
  1978.         sis "cp $logfile $dbgfile /mnt/usr/home/cpsup";
  1979.         sis "cd /mnt/usr/home/cpsup && tar zcvf upginfo.tgz upgrade.???";
  1980.         sis "cd /mnt/usr/home/cpsup && rm upgrade.???";
  1981.     }
  1982.  
  1983.     sis "sync";
  1984.     sis "sync";
  1985.     sis "sync";
  1986.     sis "sync";
  1987.     sis "sync";
  1988.  
  1989.     }
  1990.  
  1991. #
  1992. # slice_new - perform the DOS type disk partitioning
  1993. #
  1994.  
  1995.     sub slice_new {
  1996.     local *FH;
  1997.  
  1998.     &cark("Partition $slice_new is in use.\n")
  1999.         unless !defined($fdisk{$slice_new});
  2000.  
  2001.     #
  2002.     # create new slice
  2003.     #
  2004.     note "**** Create $size sized FreeBSD partition.";
  2005.  
  2006.     &dbg("slice_new slice=$slice_new size=$size");
  2007.     &dbg("fdisk -f -");
  2008.  
  2009.     open FH, "|fdisk -f -";
  2010.  
  2011.     if ($slice_new == 1) {
  2012.         $size -= 63;
  2013.  
  2014.         print FH "p 1 165 63 $size\n";
  2015.     } else {
  2016.         my $prev = $slice_new - 1;
  2017.         my $start;
  2018.  
  2019.         if ($slice_xtra) {
  2020.         #
  2021.         # Adjust this so that it nestles up against slice 4.
  2022.         #
  2023.  
  2024.         $start  = $fdisk{4}->{'start'} - $size;
  2025.         } else {
  2026.         $start = $fdisk{'cyl'} * $fdisk{'hd'} * $fdisk{'sec'} - $size;
  2027.         }
  2028.  
  2029.         #
  2030.         # Except that it needs to be bootable with all the
  2031.         # crufty BIOSes out there.
  2032.         #
  2033.  
  2034.         my $spc = $fdisk{'hd'} * $fdisk{'sec'};    # sectors per cylinder
  2035.         my $low = $fdisk{$prev}->{'start'} + $fdisk{$prev}->{'size'};
  2036.  
  2037.         $low = $spc * (int(($low - 1) / $spc) + 1); # round up
  2038.  
  2039.         while ($start > $low && int($start / $spc) > 1023) {
  2040.         #
  2041.         # This is silly, but we are seeking back by cylinders
  2042.         # until we get to a bootable one or we overlap the
  2043.         # $prev.
  2044.         #
  2045.  
  2046.         $start -= $spc;
  2047.         }
  2048.  
  2049.         if ($start / $spc >= 1024) {
  2050.         &cark("******** MAY NOT BE BOOTABLE");
  2051.         }
  2052.  
  2053.         &dbg(    "p $slice_new 165 $start $size");
  2054.         print FH "p $slice_new 165 $start $size\n";
  2055.     }
  2056.     close FH;
  2057.  
  2058.     &sync_disk($disk);
  2059.  
  2060.     #
  2061.     # Verify that slice was created, and record the actual size
  2062.     #
  2063.  
  2064.     &fdisk_reset($disk);
  2065.  
  2066.     note "Created FDISK partition $slice_new of size"
  2067.         . " $fdisk{$slice_new}->{'size'}.";
  2068.  
  2069.     #
  2070.     # fdisk tends to make them smaller at times.  The root size is now the
  2071.     # entire size, so adjust.
  2072.     #
  2073.  
  2074.     $root_size = $fdisk{$slice_new}->{'size'};
  2075.  
  2076.     note "Created FDISK partition $slice_new of size"
  2077.         . " $fdisk{$slice_new}->{'size'}.";
  2078.     }
  2079.  
  2080.     sub disklabel {
  2081.     local *FH;
  2082.     local *OUT;
  2083.     my %label = ();
  2084.     my $resid = 0;
  2085.  
  2086.     $label{'c:size'} = $fdisk{$slice_new}->{'size'};
  2087.  
  2088.     my $bpc = $fdisk{'hd'} * $fdisk{'sec'};
  2089.  
  2090.     unlink "/tmp/l7upd";
  2091.     open OUT, ">/tmp/l7upd";
  2092.  
  2093.     print OUT "type: ESDI\n";
  2094.     print OUT "disk: ${disk}s$slice_new\n";
  2095.     print OUT "label: l7upgrade\n";
  2096.     print OUT "flags:\n";
  2097.     print OUT "bytes/sector: 512\n";
  2098.     print OUT "sectors/track: $fdisk{'sec'}\n";
  2099.     print OUT "tracks/cylinder: $fdisk{'hd'}\n";
  2100.     print OUT "sectors/cylinder: $bpc\n";
  2101.     print OUT "cylinders: $fdisk{'hd'}\n";
  2102.     print OUT "sectors/unit: $fdisk{$slice_new}->{'size'}\n";
  2103.     print OUT "rpm: 3600\n";
  2104.     print OUT "interleave: 1\n";
  2105.     print OUT "trackskew: 0\n";
  2106.     print OUT "cylinderskew: 0\n";
  2107.     print OUT "headswitch: 0\n";
  2108.     print OUT "track-to-track seek: 0\n";
  2109.     print OUT "drivedata: 0 \n";
  2110.  
  2111.     print OUT "3 partitions:\n";
  2112.  
  2113.     #
  2114.     # layout the space
  2115.     #
  2116.  
  2117.     $resid = $label{'c:size'};
  2118.  
  2119.     $label{'a:size'} = $root_size;
  2120.     $label{'a:offs'} = 0;
  2121.  
  2122.     $resid -= $label{'a:size'};
  2123.  
  2124.     $label{'b:size'} = $swap_size;    # vestigeal
  2125.     $label{'b:offs'} = $label{'a:size'} + $label{'a:offs'};
  2126.  
  2127.     $resid -= $label{'b:size'};
  2128.  
  2129.     &dbg("disklabel: %label");
  2130.     &dbg_hash(\%label);
  2131.  
  2132.     print OUT "a: $label{'a:size'} $label{'a:offs'} 4.2BSD 0 0 0\n";
  2133.     print OUT "c: $label{'c:size'} 0                unused 0 0\n";
  2134.  
  2135.     close OUT;
  2136.  
  2137.     #
  2138.     # Install this disklabel
  2139.     #
  2140.  
  2141.     note "**** installing new disk label on ${disk}s$slice_new";
  2142.     sis "dd if=/dev/zero of=/dev/${disk}s$slice_new bs=1b count=1";
  2143.     sis "disklabel -R -r ${disk}s$slice_new /tmp/l7upd";
  2144.  
  2145.     #
  2146.     # create filesystems
  2147.     #
  2148.  
  2149.     sis "cd /dev; ./MAKEDEV ${disk}s${slice_new}a";
  2150.  
  2151.     foreach $mp (@mp) {
  2152.         my $newfs_opts = "";
  2153.         my $rdev = $slice_map{$mp};
  2154.  
  2155.         $rdev =~ s:/dev/:/dev/r:;
  2156.  
  2157.         # $newfs_opts = "-O " if $mp eq "/";
  2158.  
  2159.         sis "rm -f /tmp/rstmode*";
  2160.         sis "rm -f /tmp/rstdir*";
  2161.         note "****";
  2162.         note "**** create filesystem for $mp";
  2163.         note "****";
  2164.         sis "newfs $newfs_opts $rdev";
  2165.         sis "mkdir -p /mnt/$mp";
  2166.         sis "touch /mnt/$mp/failed";
  2167.     }
  2168.     }
  2169.  
  2170.     sub restore {
  2171.  
  2172.     note "****";
  2173.  
  2174.     #
  2175.     # it is much easier now.
  2176.     #
  2177.  
  2178.     system "fsck  $slice_map{'/'}";
  2179.     sis "mount -o async $slice_map{'/'} /mnt/";
  2180.     &cark("failed to mount  '/'\n") if -f "/mnt/failed";
  2181.  
  2182.     note "**** extract bits for '/'";
  2183.  
  2184.     vsis "gzcat $bits_map{'/'} | (cd /mnt/ && tar xvSpf -) 2>/usr/l7up/tar.out";
  2185.  
  2186.     sis "sync; sync; sync or swim;";
  2187.  
  2188.     #
  2189.     # Ensure we have correct /dev entries.
  2190.     #
  2191.  
  2192.     sis "cd /mnt/dev; ./MAKEDEV ${disk}s${slice_new}a";
  2193.     sis "cd /mnt/dev; ./MAKEDEV ${disk}s${slice_xtra}a" unless !$slice_xtra;
  2194.  
  2195.     #
  2196.     # Install boot blocks
  2197.     #
  2198.  
  2199.     note "**** install boot blocks";
  2200.  
  2201.     if (-x "/usr/sbin/chroot") {
  2202.         sis "chroot /mnt boot0cfg  -B $disk";
  2203.         sis "chroot /mnt disklabel -B ${disk}s$slice_new";
  2204.     } else {
  2205.         sis "boot0cfg  -B $disk";
  2206.         sis "disklabel -B ${disk}s$slice_new";
  2207.     }
  2208.     }
  2209.  
  2210. #
  2211. # md5_check - check md5 checksum
  2212. #
  2213.  
  2214.     sub md5_check {
  2215.     my $what    = shift or &cark("");
  2216.     my $desired = shift or &cark("");
  2217.     my $sum;
  2218.  
  2219.     chop($sum = `md5 $what`);
  2220.  
  2221.     $sum =~ s/.* = //;
  2222.  
  2223.     $sum eq $desired;
  2224.     }
  2225.  
  2226. #
  2227. # md5_verify - verify md5 checksum
  2228. #
  2229.  
  2230.     sub md5_verify {
  2231.     my $what    = shift or &cark("");
  2232.     my $desired = shift or &cark("");
  2233.  
  2234.     &cark("$what: md5 mismatch.\n") unless md5_check($what, $desired);
  2235.     }
  2236.  
  2237. #
  2238. # bom_check - verify files match the BoM
  2239. #
  2240.  
  2241.     sub bom_check {
  2242.     my $bom = shift;
  2243.     local *BOM;
  2244.  
  2245.     open BOM, "<$bom" or &cark("$!: $bom\n");
  2246.  
  2247.     while (<BOM>) {
  2248.         chop;
  2249.  
  2250.         if (/^\# EQVERS=([^:]+)/) {
  2251.         my $v = $1;
  2252.  
  2253.         &cark("Version mismatch: $vers != $v\n") unless $v eq $vers;
  2254.  
  2255.         next;
  2256.         }
  2257.  
  2258.         if (/^md5 /) {
  2259.         my ($ign, $md5, $uid, $gid, $mode, $path) = split;
  2260.  
  2261.         # note "verifying file $path";
  2262.  
  2263.         &cark("missing $path\n") unless -f $path;
  2264.  
  2265.         md5_verify($path, $md5);
  2266.         } elsif (/^exe (.*)$/) {
  2267.         my $todo = $1;
  2268.         } else {
  2269.         warn "unexpected BoM entry: $_\n";
  2270.         }
  2271.     }
  2272.  
  2273.     close BOM;
  2274.     }
  2275.  
  2276.     sub badger {
  2277.  
  2278.     print "System reboot is required.";
  2279.         if ($opt_G) {
  2280.             print "\nReboot now? [y/n]\n";
  2281.     }    
  2282.     while (1) {
  2283.         my $ans;
  2284.             if (!$opt_G) {
  2285.             print "\nReboot now? [y/n]";
  2286.         }    
  2287.  
  2288.         if ($opt_b) {
  2289.         print "YES\n";
  2290.         return 1;
  2291.         }
  2292.         $ans = &get_answer;
  2293.  
  2294.         return  if ($ans =~ /^[Yy]/);
  2295.         if ($ans =~ /^[Nn]/) {
  2296.         printf "Aborting reboot.\n";
  2297.             exit(0); 
  2298.         }    
  2299.     }
  2300.     }
  2301.  
  2302. # Check the version level to see if we have the version of switchd
  2303. # (8.5.0g or later) that supports quiesce
  2304. #
  2305.     sub switchd_verscheck {
  2306.     my $vers;
  2307.     my $rc;
  2308.  
  2309.  
  2310.     if (-f "/.version/eq") {
  2311.         open IN, "< /.version/eq" or die;
  2312.         while (<IN>) {
  2313.         chop;
  2314.  
  2315.         if (/^EQVERS=(\d.*)$/) {
  2316.             $vers = $1;
  2317.         }
  2318.         }
  2319.     } else {
  2320.         $vers = "0";
  2321.     }
  2322.  
  2323.     if ($vers lt "8.5.0g") {
  2324.         $rc = 1;
  2325.     }
  2326.     else {
  2327.         $rc = 0;
  2328.     }
  2329.  
  2330.     close IN;
  2331.     return $rc;
  2332.     }
  2333.  
  2334. #
  2335. # switch_firmware
  2336. #    
  2337.     sub switch_firmware {
  2338.     my $reboot = 0;
  2339.     my $ans=0;
  2340.      
  2341.     if ($opt_F) {
  2342.         sleep 1;
  2343.             print "WARNING: THIS MAY TAKE UP TO 5 MINUTES. YOU\n";
  2344.             print "MUST NOT POWER CYCLE THE SYSTEM DURING THIS\n";
  2345.             print "TIME, OR INTERRUPT THIS PROCESS IN ANY\n";
  2346.             print "OTHER WAY!\n";
  2347.             print "[If you are using the GUI, click 'Show Details'\n";
  2348.             print "to follow the progress of the upgrade.]\n";
  2349.             print "\n";
  2350.         print "Do you acknowledge this warning? [y/y]\n";
  2351.         $ans = &get_answer;
  2352.         system "/usr/local/sbin/switchd -Q";
  2353.         sleep 5;
  2354.         select(STDOUT); $| = 1;
  2355.         system("/usr/l7up/swconfig -S -N -X 'fw guiflash ./cp301.bin '");
  2356.         if (($? == 0)) {
  2357.             $reboot = 1;
  2358.         }
  2359.         else {
  2360.             print "Firmware remains at previous version.\n";
  2361.             print "Software upgrade will continue.\n";
  2362.             $reboot = 0;
  2363.         }    
  2364.     }    
  2365.     return $reboot;
  2366.     }    
  2367.  
  2368. #
  2369. # cert_check - checking for sibd & GUI certificate file.
  2370. #
  2371.     sub cert_check {
  2372.     if ($opt_G) {
  2373.         system "/bin/sh /usr/l7up/regen_sslkeys -G /var/tmp/eq_upgrade.in";
  2374.     } else {
  2375.         system "/bin/sh /usr/l7up/regen_sslkeys";
  2376.     }
  2377.     if (($?)) {
  2378.         print "********************************************************\n";
  2379.         ¬e("**Certificate check failed\n");
  2380.         ¬e("**** Please contact Coyote Point customer support.");
  2381.         die ("Aborting upgrade");
  2382.     }
  2383.     }
  2384.  
  2385. #
  2386. # If this is a system running version < 8.6, check for 
  2387. # network misconfiguration. See bug #3275
  2388. # Subroutine returns zero if everything is cool and
  2389. # no corrective action is required. Returns 1 if we need
  2390. # to do a "-C" upgrade 
  2391. #
  2392.  
  2393. sub check_for_invalid_net_config {
  2394.  
  2395.     my $trouble = 0;
  2396.  
  2397. #
  2398. # Find the value of EQ_IF_0 & EQ_IF_1 in /etc/rc.conf
  2399. #
  2400.  
  2401.     open IN, "< /etc/rc.conf" or &cark("$!\n");
  2402.  
  2403.     while (<IN>) {
  2404.     if (/^EQ_IF_0=(.*)$/) {
  2405.  
  2406.         $net0 = $1;
  2407.         $net0 =~ s/^(["''"])(.*)\1/$2/;
  2408.  
  2409.         &dbg("net0 = $net0");
  2410.         
  2411.     } elsif (/^EQ_IF_1=(.*)$/) {
  2412.  
  2413.         $net1 = $1;
  2414.         $net1 =~ s/^(["''"])(.*)\1/$2/;
  2415.  
  2416.         &dbg("net1 = $net1");
  2417.     }
  2418.     }
  2419.  
  2420. #
  2421. # Check to see if ifconfig_$net0 is populated
  2422. # but ifconfig_$net1 is blank
  2423. #
  2424.  
  2425.     open IN, "< /var/etc/rc.conf-eq" or &cark("$!\n");
  2426.     $ifcfg0 = " ";
  2427.     $ifcfg1 = " ";
  2428.  
  2429.     while (<IN>) {
  2430.     if (/^ifconfig_$net0=(.*)$/) {
  2431.  
  2432.         $ifcfg0 = $1;
  2433.         $ifcfg0 =~ s/^(["''"])(.*)\1/$2/;
  2434.  
  2435.         &dbg("ifcfg0 = $ifcfg0");
  2436.         
  2437.     } elsif (/^ifconfig_$net1=(.*)$/) {
  2438.  
  2439.         $ifcfg1 = $1;
  2440.         $ifcfg1 =~ s/^(["''"])(.*)\1/$2/;
  2441.  
  2442.         &dbg("ifcfg1 = $ifcfg1");
  2443.         
  2444.     }
  2445.     }
  2446.  
  2447. #
  2448. # It is possible to see ifconfig_xx0='' or ifconfig_xx0='inet  netmask  '
  2449. # we only want ifconfig_xx0='inet ###.###.###.### netmask ###.###.###.###'
  2450. #
  2451.  
  2452.     if ($ifcfg0 =~ m/^\s*inet\s*[\d\.]+\s*netmask\s*[\d\.]/) {
  2453.     &dbg("ifcfg0 was true\n");
  2454.     } else {
  2455.     $ifcfg0 = 0;
  2456.     } 
  2457.  
  2458.     if ($ifcfg1 =~ m/^\s*inet\s*[\d\.]+\s*netmask\s*[\d\.]/) {
  2459.     &dbg("ifcfg1 was true\n");
  2460.     } else {
  2461.     $ifcfg1 = 0;
  2462.     } 
  2463.  
  2464.     my $running_vers = &curr_vers();
  2465.     if (($running_vers lt "8.6.0") && ($ifcfg0 && !$ifcfg1)) {
  2466.  
  2467.     $trouble = 1;
  2468.  
  2469.     print "\n\n";
  2470.     print "*****************************************************************************\n";
  2471.     print "* You are upgrading this system to Version 8.6.\n"; 
  2472.     print "* The upgrade process has determined that you have an IP address configured\n";
  2473.     print "* on the Equalizer external interface, but none on the internal interface.\n";
  2474.  
  2475.     if ($opt_G) {
  2476.         print "* This is not a supported configuration. You will need to correct\n";
  2477.         print "* the network misconfiguration and retry the upgrade.\n";
  2478.         print "*****************************************************************************\n";
  2479.         die ("Upgrade terminated\n");
  2480.     }
  2481.  
  2482.  
  2483.     print "* This is not a supported configuration. You may either exit the upgrade and\n";
  2484.     print "* correct the network misconfiguration, or you may delete the entire existing\n";
  2485.     print "* configuration.\n";
  2486.     print "*****************************************************************************\n\n";
  2487.  
  2488.     $valid_ans = 0;
  2489.     while ($valid_ans == 0) {
  2490.  
  2491.         print "Do you wish to abort(a) the upgrade or\n";
  2492.         print "delete(d) the existing configuration? [a/d]: ";
  2493.  
  2494.         my $ans;
  2495.         $ans = &get_answer;
  2496.         if ($ans =~ /^[Aa]/) {
  2497.         die ("Upgrade terminated");
  2498.         } elsif ($ans =~ /^[Dd]/) {
  2499.         print "Continuing upgrade.\n";
  2500.         $valid_ans++;
  2501.         } else {
  2502.         print "ERROR: You did not enter a valid response.\n\n";
  2503.         }
  2504.     }
  2505.     }
  2506.  
  2507.     return $trouble;
  2508. }
  2509.   
  2510. #    
  2511. # main
  2512. #    
  2513.     sub main {
  2514.         my $reboot = 0;
  2515.     &Getopts('RbkeSCrGFl');
  2516.  
  2517.     if ($opt_C) {
  2518.         my $rusure;
  2519.         print "**************************************************************\n";
  2520.         print "WARNING: You have specified for the upgrade script\n";
  2521.         print "to clear the system configuration and revert to defaults\n";
  2522.         print "Are you absolutely SURE that you would like to continue? [y/n]\n";
  2523.         $rusure = &get_answer;
  2524.         if ($rusure =~ /^[Nn]/) {
  2525.         die("Aborting upgrade.");
  2526.         } else {
  2527.         print "****************************************************************\n";
  2528.         print "WARNING: Please re-confirm: your Equalizer will not be\n";
  2529.         print "accessible except by serial, and any configuration will be lost.\n";
  2530.         print "Are you sure you want to continue? [y/n]\n";
  2531.             if ($opt_G) {
  2532.             print "\n";
  2533.             }    
  2534.             $rusure = &get_answer;
  2535.         if ($rusure =~ /^[Yy]/) { 
  2536.             $no_preserve = $opt_C;
  2537.         } else {
  2538.             die("You did not type \"y\". Aborting upgrade.");
  2539.         }
  2540.         }
  2541.     }
  2542.  
  2543.         #
  2544.         # Save STDOUT and STDERR before we "tee" up so we can restore
  2545.         # console output for the switch firmware update
  2546.         #
  2547.     open(OLDOUT, ">&STDOUT");
  2548.         open(OLDERR, ">&STDERR");
  2549.         #
  2550.         # This is just so we don't get any annoying "used only once" 
  2551.         # messages...
  2552.         #
  2553.     stat OLDOUT;
  2554.     stat OLDERR;
  2555.     
  2556.     &previous;
  2557.     &setup;
  2558.     &verscheck;
  2559.     &bom_check("./BoM");
  2560.  
  2561.     &lm_check(0);
  2562.  
  2563.     # sibd & gui Certificate checks
  2564.     &cert_check;
  2565.  
  2566.     # See comments at head if called function
  2567.         # no need to perform this check if -C was specified
  2568.     if ($no_preserve || &check_for_invalid_net_config) {
  2569.         $no_preserve = 1;
  2570.     }
  2571.  
  2572.     #
  2573.     # Check whether the OLD configuration can be parsed with the
  2574.     # NEW parser.
  2575.     #
  2576.     if ($no_preserve == 0) {
  2577.         if((-f "/.master/var/eq/eq.conf")) {
  2578.  
  2579.         my $running_vers = &curr_vers();
  2580.         if ($running_vers lt "8.6.0") {
  2581.             #
  2582.             # convert use_ssl_only flag for failover 
  2583.             #
  2584.             print "\n\nYou are upgrading this system to Version 8.6. If you will be using this\n"; 
  2585.             print "system in a failover configuration with an Equalizer that is running\n";
  2586.             print "Version 8.5, then you must disable the \"use ssl only\" flag on the 8.6\n";
  2587.             print "system.\n";
  2588.             print "Would you like the upgrade script to disable this option for you now? [y/n]\n";
  2589.             my $ans;
  2590.             $ans = &get_answer;
  2591.             if ($ans =~ /^[Yy]/) {
  2592.             $set_use_ssl = 1;
  2593.             }
  2594.         }
  2595.  
  2596.         print "\n\nConverting default for once_only...\n";
  2597.         system "/usr/l7up/convert_default -i/.master/var/eq/eq.conf -v ".
  2598.             "once_only -d once_only -o /.master/var/eq/eq.conf";
  2599.         if (($? == 0)) {
  2600.             print "\nConversion done.\n";
  2601.         }
  2602.  
  2603.         print "\n\nChecking configuration with new version's parser...\n";
  2604.         system "/usr/l7up/parse_config -i/.master/var/eq/eq.conf -U";
  2605.         if (($? == 512)) {
  2606.             $cfgcount = 0;
  2607.                     while ($cfgcount == 0) {
  2608.                         print "Do you wish to continue(c) or abort(a) the upgrade? [c/a]:";
  2609.                         my $ans;
  2610.                         $ans = &get_answer;
  2611.                         if ($ans =~ /^[Aa]/) {
  2612.                 die ("Aborting upgrade");
  2613.                         } elsif ($ans =~ /^[Cc]/) {
  2614.                             print "Continue upgrade.\n";
  2615.                             $cfgcount++;
  2616.                         } else {
  2617.                             print "ERROR: You did not enter a valid response.  Please try again. \n";
  2618.                         }
  2619.                     }
  2620.         }
  2621.          elsif (($?)) {
  2622.             print "***********************************************************************\n";
  2623.             print "Configuration parse FAILED\n\n";
  2624.             print "You have the following options:\n".
  2625.             "  (k)eep the current configuration file\n".
  2626.             "     - Continue the upgrade using the current configuration file.\n".
  2627.             "     - Edit the file after the system boots to fix the above errors.\n".
  2628.             "  (d)elete the current configuration\n".
  2629.             "     - Delete all clusters, servers, VLANs, user logins, etc.\n".
  2630.             "     - After reboot, you must log in using the serial console and\n".
  2631.             "     - use the eqadmin utility to configure the network and logins.\n".
  2632.             "  (a)bort the upgrade\n".
  2633.             "     - Exit to the command line now to edit the configuration file\n".
  2634.             "       and restart the upgrade.\n\n".
  2635.             "If you need assistance editing your configuration file, please note the\n".
  2636.             "errors above and contact support\@coyotepoint.com.\n";
  2637.             print "***********************************************************************\n";
  2638.             $cfgcount = 0;
  2639.             while ($cfgcount == 0) {
  2640.             print "\nDo you wish to keep(k) or delete(d) your configuration, or abort(a)\n".
  2641.                "the upgrade? [k/d/a]\n";
  2642.                     if ($opt_G) {
  2643.                     print "\n";
  2644.                     }    
  2645.             my $ans;
  2646.             if ($opt_b) {
  2647.                 print "k\n";
  2648.                 return 1;
  2649.             }
  2650.             
  2651.             $ans = &get_answer;
  2652.             if ($ans =~ /^[Dd]/) {
  2653.                 print "Are you sure you would like to delete the configuration file? [y/n] \n";
  2654.                         if ($opt_G) {
  2655.                         print "\n";
  2656.                         }    
  2657.                 $ans = &get_answer;
  2658.                 if ($ans =~ /^[Yy]/) {
  2659.                 $pres_eq_conf = 0;
  2660.                 $cfgcount++;
  2661.                 } else {
  2662.                 print "ERROR: You did not Enter \"y\".  Try again.\n";
  2663.                 }
  2664.             } elsif ($ans =~ /^[Kk]/) {
  2665.                 print "Keeping configuration.\n";
  2666.                 $cfgcount++;
  2667.             } elsif ($ans =~ /^[Aa]/) {
  2668.                 die ("Aborting upgrade");
  2669.             } else {
  2670.                 print "ERROR: You did not enter a valid response.  Please try again. \n";
  2671.             }
  2672.             
  2673.             }
  2674.             
  2675.         } else {
  2676.             print " SUCCESS\n\n";
  2677.         }   
  2678.         
  2679.         } else {
  2680.         print "Configuration file not found -- not checking configuration.\n";
  2681.         }
  2682.  
  2683.         if((-f "/.master/var/eq/envoy.conf")) {
  2684.         print "\n\nChecking envoy configuration with new version's parser...\n";
  2685.         system "/usr/l7up/envoy_parse_config -i /.master/var/eq/envoy.conf";
  2686.         if (($?)) {
  2687.             print "***********************************************************************\n";
  2688.             print "Envoy configuration parse FAILED\n\n";
  2689.             print "You have the following options:\n".
  2690.             "  (k)eep the current configuration file\n".
  2691.             "     - Continue the upgrade using the current configuration file.\n".
  2692.             "     - Edit the file after the system boots to fix the above errors.\n".
  2693.             "  (d)elete the current Envoy configuration\n".
  2694.             "     - All geo clusters, sites, and Envoy parameters are deleted.\n".
  2695.             "     - The cluster, server and networking configuration is unchanged.\n".
  2696.             "  (a)bort the upgrade\n".
  2697.             "     - Exit to the command line now to edit the configuration file\n".
  2698.             "       and restart the upgrade.\n\n".
  2699.             "If you need assistance editing your configuration file, please note the\n".
  2700.             "errors above and contact support\@coyotepoint.com\n";
  2701.             print "***********************************************************************\n";
  2702.             $cfgcount = 0;
  2703.             while ($cfgcount == 0) {
  2704.             print "\nDo you wish to keep(k) or delete(d) your Envoy configuration, or\n".
  2705.             "abort(a) the upgrade? [k/d/a]\n";
  2706.                     if ($opt_G) {
  2707.                     print "\n";
  2708.                     }    
  2709.             my $ans;
  2710.             if ($opt_b) {
  2711.                 print "k\n";
  2712.                 return 1;
  2713.             }
  2714.             
  2715.             $ans = &get_answer;
  2716.             if ($ans =~ /^[Dd]/) {
  2717.                 print "Are you sure you would like to delete the configuration file? [y/n] \n";
  2718.                         if ($opt_G) {
  2719.                         print "\n";
  2720.                         }    
  2721.                 $ans = &get_answer;
  2722.                 if ($ans =~ /^[Yy]/) {
  2723.                 $pres_en_conf = 0;
  2724.                 $cfgcount++;
  2725.                 } else {
  2726.                 print "ERROR: You did not Enter \"y\".  Try again.\n";
  2727.                 }
  2728.             } elsif ($ans =~ /^[Kk]/) {
  2729.                 print "Keeping configuration.\n";
  2730.                 $cfgcount++;
  2731.             } elsif ($ans =~ /^[Aa]/) {
  2732.                 die ("Aborting upgrade");
  2733.             } else {
  2734.                 print "ERROR: You did not enter a valid response.  Please try again. \n";
  2735.             }
  2736.             }
  2737.             
  2738.         } else {
  2739.             print " SUCCESS\n\n";
  2740.         }   
  2741.         
  2742.         } else {
  2743.         print "Envoy configuration file not found -- not checking configuration.\n";
  2744.         }
  2745.  
  2746. #
  2747. # In Version 8.6 and above, we no longer use switch.conf. 
  2748. # And, in that case, there is no reason to parse_config it        
  2749. #
  2750.     }
  2751.  
  2752.     #
  2753.     # Ruthlessly delete non-active slices.
  2754.     #
  2755.  
  2756.     foreach $s (1..3) {
  2757.         next unless ($s != $slice_old);
  2758.         next unless defined($fdisk{$s});
  2759.  
  2760.         &reclaim_space($disk, $s);
  2761.     }
  2762.  
  2763.     my $spc  = $fdisk{'hd'} * $fdisk{'sec'};    # sectors per cylinder
  2764.     my $i    = 0;
  2765.     my ($r, $v, $u) = ($root_size, $var_size, $usr_size);
  2766.  
  2767.     $slice_new = 0;
  2768.  
  2769.     while (!$slice_new) {
  2770.         #
  2771.         # Try hard to fit in.  Various buggy prior upgrades
  2772.         # left strange partitions which are slightly "too small".
  2773.         # Try reducing our demands.
  2774.         #
  2775.  
  2776.         $root_size = $spc * int($r / $spc) - $i * $spc;
  2777.         $var_size  = 0;
  2778.         $usr_size  = 0;
  2779.         $swap_size = 0;
  2780.         $tmp_size  = 0;
  2781.  
  2782.         $size      = ($root_size + $swap_size + $var_size
  2783.               + $tmp_size + $usr_size);
  2784.  
  2785.         if ($root_size < (3 * $r) / 4) {
  2786.         &cark("Insufficient space.\n");
  2787.         }
  2788.  
  2789.         note "**** trying root $root_size";
  2790.  
  2791.         $slice_new = next_slice($size);
  2792.  
  2793.         ++$i;    # sic.
  2794.     }
  2795.  
  2796.     %slice_map = (
  2797.               '/'        => "/dev/${disk}s$slice_new" . "a",
  2798.               );
  2799.     #
  2800.     # Ensure that there are /dev entries
  2801.     #
  2802.  
  2803.     sis "cd /dev; ./MAKEDEV ${disk}s$slice_new";
  2804.     sis "cd /dev; ./MAKEDEV ${disk}s$slice_new" . "c";
  2805.  
  2806.         # creating ntp.drift file
  2807.     sis "touch /var/etc/ntp.drift";
  2808.  
  2809.     &slice_new;
  2810.     &disklabel;
  2811.     &restore;
  2812.     &phase3;
  2813.  
  2814.     # if this is a kontron box, create a kernel configuration file
  2815.     # disabling syscons
  2816.  
  2817.     chop($systype = `./lm -h -U`);
  2818.  
  2819.     if ($systype =~ /^classic-1U/) {
  2820.         note "disabling syscons device";
  2821.         open FH, "| cat > /mnt/boot/kernel.conf" or die;
  2822.         print FH "disable sc0\n";
  2823.         print FH "quit\n";
  2824.         close FH;
  2825.     } 
  2826.  
  2827.     # Fix up timezone stuff.
  2828.     &zoneupdate;
  2829.  
  2830.     # Fix up boot time tunables
  2831.     system "/bin/sh /usr/l7up/tune.sh /mnt";
  2832.  
  2833.     &undo_mounts;
  2834.     note "";
  2835.  
  2836.     #
  2837.     # Assuming this all worked, arrange to boot to new partition
  2838.     #
  2839.  
  2840.     sis "boot0cfg -o packet -s$slice_new $disk";
  2841.     &dbg_save;
  2842.  
  2843.         if (!$opt_G) {
  2844.             #
  2845.             # Restore output to console because we want to see the progress 
  2846.             # of the switch firmware update
  2847.             #    
  2848.         close(STDERR);
  2849.             close(STDOUT);
  2850.             open(STDOUT, ">&OLDOUT");
  2851.             open(STDERR, ">&OLDERR");
  2852.             select(STDOUT); $| = 1;
  2853.             select(STDERR); $| = 1;
  2854.     }
  2855.     
  2856.     #
  2857.     # Check switch firmware level and update if necessary
  2858.     #
  2859.     if ($opt_F) {
  2860.         $reboot = &switch_firmware;
  2861.     }    
  2862.  
  2863.     if (($opt_r) or ($reboot)) {
  2864.         print "Performing automatic reboot.\n";
  2865.         print "System will reboot with new version.\n";
  2866.         sleep 1;
  2867.     } else {
  2868.         &badger;
  2869.     }
  2870.  
  2871.     #
  2872.     # Now redo what we undid
  2873.     #
  2874.     if ($opt_G) {
  2875.             open(STDOUT, '>>'.$outputfile ) or die $!;
  2876.             open(STDERR, '>>'.$outputfile ) or die $!;
  2877.     }    
  2878.         else {    
  2879.           open(STDOUT, "| tee -a $logfile") or &cark("$!\n");  
  2880.         open(STDERR, ">&STDOUT") or &cark("$!\n");
  2881.         }
  2882.         select(STDOUT); $| = 1;
  2883.         select(STDERR); $| = 1;
  2884.  
  2885.     sis "shutdown -r now";
  2886.  
  2887.     1;
  2888.     if ($opt_G) {
  2889.             close STDOUT;
  2890.     }    
  2891.     }
  2892.  
  2893. #
  2894. # kluges for migration from 7.1.0 f/s layout to 7.2.0 f/s layout.
  2895. #
  2896.  
  2897.     sub kluges {
  2898.     sis "mkdir -p /.master/var/eq/licenses";
  2899.     sis "touch /.master/.LOCK";
  2900.     }
  2901.  
  2902.     &main;
  2903.