package System;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

#  $Name: bld21_017 $ 
#  $Id: System.pm,v 1.14 2005/03/16 00:03:50 kdesai Exp $

use Debug;
use strict 'vars';
use vars qw($AUTOLOAD %AUTO @SAVE $SOL_IP); 
use Util;
#use Time::Zone;


sub logger {
  my($class, $prio, $mess) = @_;
  `/usr/bin/logger -p $prio "$mess"`;
}

use vars qw($ERR);

sub getDevicePassword {
  my($class, $dev, $type) = @_;

  $type = "array" if (!$type);
  my ($pass, $err);
  $ERR = "";

  if ($dev->{telnet} eq "_BLANK_") {
     $pass = "";
  } elsif ($dev->{telnet}) {
     if ($dev->{telnet} =~ /^\%\d/) { # in case it's an old asci encoded passord
       $pass = Util->decode($dev->{telnet});
     } else {
       require MIME::Base64;
       $pass = MIME::Base64::decode($dev->{telnet});
     }

  } else {
     $pass = System->getPassword($type);
     if (!$pass) {
       $ERR = "No password defined for this device. ($dev->{key})";
     }
  }
  return $pass;
}


#       System->setPassword("guest", "password");
#   encoded : leave encoded
# print System->getPassword("guest");

sub getPassword {
  my($class, $arg, $encoded) = @_;
  require MIME::Base64;
  my ($renv) = PDM::ConfigFile->read();

  my $pass = $renv->{"telnet_$arg"};

  return $encoded ? $pass : MIME::Base64::decode($pass);
}

# arg is the filename, like 'array'
sub setPassword {
  my($class, $arg, $pass) = @_;
  require MIME::Base64;

  my ($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();
  
  $renv->{"telnet_$arg"} = MIME::Base64::encode($pass);

  PDM::ConfigFile->write($renv, $devs, $hosts, $notifs);
}

sub rotate {
  my($class, $file, $max, $last) = @_;
  my $renv = System->get_renv();
  $max = $max || $renv->{max_event_file_size} || 2;
  $last = $last || 9;
  my($x);

  my $size = (stat($file))[7];
  if ($size > ($max * 1000000) ) {
     for ($x=$last; $x >= 2; $x--) {
         if (-f "$file.$x") {
            rename "$file.$x", "$file." . ($x+1);
         }
     }
     rename $file, "$file.2";
  }
}

sub solution_ip {
  return $SOL_IP if ($SOL_IP);

  open(O, "/opt/SUNWsespfw/repository");
  my($l);
  while ($l = <O>) {
    chop($l);
    if ($l =~ /WanIPAddr\:(.+)/) {
       $SOL_IP = $1; last;
    }
  }
  close(O);
  return $SOL_IP;
}

use vars qw ($CNT);

sub writeQ {
  my($class, $q) = @_;
  $CNT++;
  require Data::Dumper;
  my $dump = Data::Dumper::Dumper($q);

  my $file = "/tmp/writeQ." . time . ".$$.$CNT";

  open(W, ">$file");
  print W $dump;
  close(W);

  return $file;
}

sub readQ {
  my($class, $file) = @_;
  my $VAR1 = {};

  open(O, $file); my @lines = <O>; close(O);
  unlink $file;
  eval "@lines";
  return $VAR1;
}


  

sub logHash {
  my($class, $hash, $file, $type) = @_;

  open(OO, ">>" . System->get_home() . "/DATA/$file.log");
  my $today = Util->get_today();

  foreach my $ad (keys %$hash) {
     my $cnt = $hash->{$ad};
     print OO "$today\t$type\t$ad\tcnt=$cnt\n";   
  }
  close(OO);
}

sub logHash2 {
  my($class, $hash, $file, $type) = @_;

  open(OO, ">>" . System->get_home() . "/DATA/$file.log");
  my $today = Util->get_today();

  foreach my $ad (keys %$hash) {
     my $e = $hash->{$ad};
     foreach my $tg (keys %$e) {
        my $cnt = $e->{$tg};
        print OO "$today\t$type\t$ad\t$tg\tcnt=$cnt\n";   
     }
  }
  close(OO);
}


sub comma_format {
  my($class, $val) = @_;
  my($out, $l);
  $out = $val;
  $l = length($out);
  if ($l > 9) {
     $out = substr($out,0,$l-9) . "," . substr($out,$l-9,3) . "," .
            substr($out,$l-6,3) . "," . substr($out, $l-3);
  } elsif ($l > 6) {
     $out = substr($out,0,$l-6) . "," .
            substr($out,$l-6,3) . "," . substr($out,$l-3);
  } elsif ($l > 3) {
     $out = substr($out,0,$l-3) . "," . substr($out,$l-3);
  }
  return $out;
}




sub home_dir {
  my($class) = @_;
  return "/opt/SUNWstade";
}

# $version = System->get_se_version();
# $version = '2.0.2a1'

sub get_se_version {
  my($class, $all) = @_;
  my($rev, $ass) = System->read_release($all);
  return $rev;
}

sub read_release {
 my($class, $all) = @_;
 my($l, $build, $ass);

#  System1
 if (-x "/usr/bin/iam") {
   open(O, "/usr/bin/iam|");
   while ($l = <O>) {
     if ($l =~ /Version:\s+(.*)/) {
        $build = $1;
     } elsif ($l =~ /Build Date:\s+(.*)/) {
        $ass = $1;
     }
   }
   close(O);
   return($build,$ass);
 }

# Indy
 if (-f "/opt/SUNWsesp/bin/sp_version.file") {
   open(O, "/opt/SUNWsesp/bin/sp_version.file");
   my $l = <O>;
   close(O);
   return $l if ($all);
   my ($tem, $ver) = split (/\s+/, $l);
   return ($ver, 'NA');
 }

# Maserati Midrange
 if (-f "/etc/release") {
   open(O, "/etc/release");
   my($l);
   while ($l = <O>) {
     if ($l =~ /Build (\d+)/) {
       $build = $1;
     } elsif ($l =~ /Assembled (.*)/) {
       $ass = $1;
     }
   }
   close(O);
   return($build, $ass);
 }
 return ();
}



sub findProcess {
  my($class, $pro) = @_;

  my $ps = "/usr/bin/ps";
  my $grep = "/usr/bin/grep";
  open(O, "$ps -ef| $grep \"$pro\" | $grep -v grep|");
  my @l = <O>; close(O);
  return \@l;
}

  
sub newPngName {
  my($class) = @_;

  my $rem = $ENV{REMOTE_USER} || $ENV{REMOTE_ADDR}; 
  $rem =~ s/\./_/g;
  my $t =  "$rem." . (time % 100) . ".png";
  my $D = System->get_home() . "/DATA/Web";
  mkdir $D,0777 if (!-d $D);
  my $F = "$D/$t";
  if (wantarray) {
    return ($t, $F);
  } else {
    return $t;
  }
}

sub newPngName2 {
  my($class, $ws, $user) = @_;

  my $t =  "$user." . (time % 100) . ".png";
  my $D =  $ws . "/tmp";
  mkdir $D,0777 if (!-d $D);
  my $F = "$D/$t";
  if (wantarray) {
    return ($t, $F);
  } else {
    return $t;
  }
}

use vars qw( $PATH %COMM %COUNTERS);
$PATH = "/bin:/usr/bin:/usr/sbin:/bin";

#
#  System->counter("discovery", "ZERO");
#  System->counter("discovery", 1);
#  System->counter("discovery");
#
sub counter {
  my($class, $tag, $inc) = @_;
  
  if ($inc eq "ZERO") {
     $COUNTERS{$tag} = 0;

  } elsif ($inc) {
     $COUNTERS{$tag} += $inc;
  }
  return $COUNTERS{$tag};
}
sub getConfigPort {
  my($class,$home) = @_;
  $home = "/opt/SUNWstade" if (!$home);

  my $port = 7654;
  if (open(O, "$home/DATA/SECURE")) {
     $port = <O>;
     close(O);
     return $port =~ /\d+/ ? ($port+0) : 7443;
  } 

  open(O,"$home/System/config");
  my($l);
  while ($l = <O>) {
      if ($l =~ /GSV_PORT=(\d+)/) {
         $port = $1;
         last;
      }
  }
  close(O);
  return $port;
}

# $vers = System->getPackageInfo("diag244", "SUNWsecfg", "VERSION", "REV=(.*)" ); # returns REV
# $vers = System->getPackageInfo("","SUNWsecfg", "VERSION");  # returns line
# field = '_ALL_' return a hash

sub getPackageInfo {
  my($class, $host, $package,  $field, $pat) = @_;

  $field = "VERSION" if (!$field);

  my $program = "pkginfo -l $package";
  my $renv = System->get_renv();

  my($err, $com, $rc);
  if (!$host || $host eq $renv->{hostname}) {
    ($err, $com) = Util->run_command("/usr/bin/$program", "test",60);
    return undef if ($err || "@$com" =~ /ERROR/);
  } else {
    ($err, $rc) = Util::Http->runit($host, "/sbin/$program", 70);
    return undef if ($err || $rc =~ /ERROR/);
    my @L = split(/\n/, $rc);
    $com = \@L;
  }
  
  if ($field eq "_ALL_") {
    my %VAL;
    foreach my $l (@$com) {
       if ($l =~ /\s+(\w+):\s+(.*)/) {
          $VAL{$1} = $2;
       }
    }
    return \%VAL;
  }
     
  foreach my $l (@$com) {
     if ($l =~ /\s+$field:\s+(.*)/) {
        my $val = $1;
        if ($pat) {
           if ($val =~ /$pat/) {
              return $1;
           } else {
              return undef;
           }
        } else {
           return $val;
        }
     }
  }
}

sub get_breakFile {
  my($q) = @_;
  my $l;
  my $file = $q->{file};
  my $prefix = $q->{prefix} || "PATCHFILE";
  my($DIR) = System->get_home() ;
  my $cnt;
  if (open(O, "$DIR/DATA/$file")) {
    while ($l = <O>) {
      if ($l =~ /^#$prefix (.*)/) {
         close(W) if ($file);
         $cnt++;
         $file = $1;
         open(W, ">$DIR/$file.new");
      } else {
         print W $l if ($file);
      }
    }
    close(W);
    close(O);
  }
  print "OK files=$cnt\n";
}




sub isRoot {
  my $user_id = $>;
  if ($user_id != 0) {
     return 0;
  }
  return 1;
}

sub srs_time {
  my($class) = @_;

require Date::Format;

  my($o) =  tz_local_offset();

  $o = sprintf("%+03d%02d", int($o / 3600), abs(int($o % 3600)));
  my($s) = Date::Format::time2str('%Y%m%d.%H%M%S', time, 'GMT') . substr($o,0,3);
  return $s;
}


sub appletHeader {
  my($class, $app, $offx, $off)  = @_;

  my $ox;
  if (index($offx, "%") >= 0) {
    chop($offx);
    $ox = "* 0.$offx - 25";
  } else {
    $ox = "- $offx";
  }
  my $o =<<EOF;
 <script language=JavaScript>
  var a_width;
  var a_height;
  if (navigator.appName.indexOf("Netscape") != -1) {
      a_width = window.innerWidth $ox;
      a_height = window.innerHeight- $off;
  } else {
      a_width = window.document.body.offsetWidth $ox;
      a_height = window.document.body.offsetHeight - $off;
  }
  var s = '<applet $app height=' +a_height+ ' width=' +a_width + ' MAYSCRIPT>';
  window.document.writeln(s);
  window.document.writeln('');
  </script>
EOF

 return $o;

}


#
# runs only once then returns the cache value
#
sub run_command {
  my($com) = @_;
  my(@a, $dir, $val);

  return $COMM{$com} if $COMM{$com};

  my($ix)   = index($com, " ");
  my($com0) = ($ix >= 0)? substr($com, 0,$ix) : $com;

  if (substr($com,0,1) eq "/") {
     if (-x "$com0") {
        $val = `$dir/$com`;
        chop($val);
        $COMM{$com} = $val;
        return $val;
     } else {
        return undef;
     }
  }
    
  @a = split(/:/, $PATH);
  foreach $dir (@a) {
     if (-x "$dir/$com0") {
        $val = `$dir/$com`;
        chop($val);
        $COMM{$com} = $val;
        return $val;
     }
  }
  
  return undef;
}

sub grep {
  my($class, $file, $pat) = @_;
  my($l, $ret);

  open(O, $file);
  while ($l = <O>) {
    chop($l);
    if ($l =~ /$pat/) {
      $ret .= "| " if ($ret);
      $ret .= $l;
    }
  }
  close(O);
  return $ret;
}
  

sub get_service_port {
  my($class, $service) = @_;
  my($sport);
  my($x) = `/usr/bin/grep $service /etc/services`;
  if ($x) {
    $x =~ /$service\s+(\d+)/;
    $sport = $1;
  }
  return $sport;
}


# return rack name or hostname
sub serverName {

  my $renv = System->get_renv();
  if ($renv->{solution} eq "N") {
     return $renv->{hostname};
  } else {
     my $pre = $renv->{solution_model} || uc($renv->{solution});
     return "$pre." . System->hostid();
  }
}

sub find_command {
  my($class, $com) = @_;
  my(@a) = split(/:/, $PATH);
  foreach my $dir (@a) {
      return "$dir/$com" if (-x "$dir/$com");
  }
  Debug->err(ERROR => "Cannot find command $com");
  return "echo ";
}
         
sub host_type {
  my($class, $hostname) = @_;
  my($type);
  my $cmd = System->get_home() . "/snmp/bin/snmpget";
  my $mibdir = System->get_home() . "/snmp/share/snmp/mibs";
  my $opt = "-v1 -cpublic -t10 -r0 -M$mibdir -mall " . System->snmpopt();
  my($ans) = run_command("$cmd $opt $hostname sysDescr.0 2>/dev/null");

  if (!$ans) {
     return "";
  } else {
    my(@a) = split(/\s*=\s*/, $ans);
    $a[1] =~ s/Sun SNMP Agent,//;
    $type = Util->ltrim($a[1]);

    if (substr($type,0,1) eq "\"") {
       $type = substr($type,1,-1);
    }
    return $type;
  }

}

sub bitMode {
  my($class) = @_;
  my($bit);
  if (-x "/usr/bin/isainfo") {
     $bit = run_command('isainfo -b') || 'UNKNOWN';
     return $bit;
  } else {
     return "32";
  }
}
     

#    .       system boot  Apr 12 09:42

sub lastReboot {
  my($class) = @_;

  my $x = run_command('who -b');
  $x =~ /system boot (.*)/;
  $x = Util->trim($1);
  my ($m, $d, $h) = split(/\s/, $x);

  $m = $Util::MTH{$m};
  my $boot = sprintf("%2.2d-%2.2d %s:00", $m, $d, $h);

  my $today = Util->today("YMDH");
  my $today1 = substr($today, 5);

  if ($boot > $today1) {
     my $year = substr($today,0,4) - 1;
     return sprintf("%4.4d-", $year) . $boot
  } else {
     return substr($today,0,5) . $boot;
  }
  
}

# ifconfig -a
# lo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1
#        inet 127.0.0.1 netmask ff000000 
# dmfe0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
#       inet 172.20.67.235 netmask ffff0000 broadcast 172.20.255.255
#       ether 0:3:ba:6:1b:38 

sub ifconfigs {
  my($class, $id, $name) = @_;
  my @O;
  my ($err, $L) = Util->run_command("/usr/sbin/ifconfig -a","ifc", 15);

  my($last, $inlast, $in, $last_val, $l);

  foreach $l (@$L) {
     if ($l =~ /^(\w+): /) {
        $in = $1;
     }
     if ($in && ($l =~ /\s+inet ([\w\.\,\:]+)/)) {
        push(@O, [$in, $1]);
        $in = 0;
     }
  }
  return \@O;
}

sub ifconfig {
  my($class, $id, $name) = @_;
  $name = "inet" if (!$name);
  my ($err, $L) = Util->run_command("/usr/sbin/ifconfig -a", "ifc", 15);

  my($last, $inlast, $in, $last_val, $l);

  foreach $l (@$L) {
     if ($l =~ /^$id: /) {
        $in = 1;
     } elsif ($l =~ /^(\w+): /) {
        $last = "$l\n";
        $last_val = $1;
        $inlast = 1;
     }  elsif ($inlast) {
        $last .= "$l\n";
     }
     if ($in && ($l =~ /$name ([\w\.\,\:]+)/)) {
         return $1;
     }
  }
  if ($id eq "LAST" && $last) {
    my @L = split(/\n/, $last);
    foreach $l (@L) {
      if ($l =~ /$name ([^\s]+)/) {
         if (wantarray) {
           return($1, $last_val);
         } else {
           return $1;
         }
      }
    }
  }
  return undef;
}

sub os_version {
  my($class) = @_;
  my($os_version);

  return run_command('uname -r') || 'UNKNOWN';
}
sub os_version_dot {
  my($class) = @_;
  my($os_version);

  $os_version = run_command('uname -r') || 'UNKNOWN';
  my($sol, $dot) = split(/\./,$os_version);
  return $dot;
}
  
sub hostid {
  my($class) = @_;
  my $renv = System->get_renv();
  if (System->get_testMode() && $renv->{test_hostid}) {
     return $renv->{test_hostid} ;
  }
  return  run_command('hostid') || 'UNKNOWN';
}


sub hostinfo {
  my($class) = @_;
  return  run_command('uname -a') || 'UNKNOWN';
}

sub shortHostname {
  my($class) = @_;
  my($h) = run_command('uname -n') || 'UNKNOWN';
  my $i = index($h, ".");
  if ($i > 0) {
     return substr($h,0,$i);
  } else {
     return $h;
  }
}

sub pwd {
  my($class) = @_;
  my $n = $0;
  if (substr($n,0,1) eq ".") {
     my($h) = run_command('pwd');
     return $h;
  } else {
     my $ix = rindex($n, "/");
     return substr($n,0,$ix);
  }
}

#
# return hostname + lc(domainname)
# if fails: shorten the domainname and try again
# unless domain does not work, then stays short
#
sub hostname {
  my($class, $skip_domain) = @_;

  my $renv = System->get_renv();
  my($h) = run_command('uname -n') || 'UNKNOWN';

  my $i = index($h, ".");

  if ($skip_domain || $renv->{skip_domain} ) {
     return $i > 0 ? substr($h,0,$i) : $h;
  }

  if ($i > 0) {
     return substr($h,0,$i) . lc(substr($h,$i));
  } else {
     my $domain = lc(run_command('domainname'));
     if ($domain) {
        my $full = "$h.$domain";
        if (gethostbyname($full)) {
           return $full;
        } else {
           my $i2 = index($domain, ".");
           if ($i2 > 0) {
              $full = $h . substr($domain, $i2);
              if (gethostbyname($full)) {
                return $full;
              }
           }
        }
     }
     return $h;
  }
}

sub platform {
  my($class) = @_;
  return run_command('uname -m') || 'UNKNOWN';
}

#
# sub snmpopt()
# This subroutine is used to set the options based on the SNMP package
# used by StorADE.  The UCD-snmp package (SPARC) uses options -Os while the
# NET-SNMP package (x86) requires -OQs to deliver equivalent text string output.
# The default case will assume UCD SNMP is used and test specifically for NET-SNMP.
#
sub snmpopt {
  my($class) = @_;
  my $home = System->get_home() || "/opt/SUNWstade";
  my $ver = run_command ( "$home/snmp/bin/snmpget -V 2>&1" );
  my $opt = ( substr ($ver, 0, 3) eq "NET" ) ? "-OQs" : "-Os" ;
  return  $opt;
}


sub os {
  my($class) = @_;

  return run_command('uname -s') || 'UNKNOWN';
}

sub model {
  my($class) = @_;
  my $model;
  my $opt = $^O eq "linux" ? "" : "-i";

  $model = run_command("uname $opt") || 'UNKNOWN';

  # Check for a 420R machine
  my $temp_model = run_command('/usr/platform/sun4u/sbin/prtdiag');
  if($temp_model =~ /Sun Enterprise 420R/){
      $model = "420R";
  }
    
  return $model;

}

sub memory {
  my($class) = @_;
  my($x, $mem);
  $x = run_command('prtconf -v');
  $x =~ /Memory size: (\d+)\s/;
  $mem = $1 || "UNKNOWN";
  return $mem;
}

sub swap {
  my($class) = @_;
  my($swap, $x);
  $x = run_command(System->get_home() . "/bin/swap.sh");
  $x =~ /SWAP: (\d+) total/;
  $swap = $1 || "UNKNOWN";
  return $swap;
}

sub cpus {
  my($class) = @_;
  my(@x) = split(/\n/, run_command('psrinfo'));
  return $#x + 1;
}



  
sub find_executable {
  my($class, $bin) = @_;
  my($dir);

  my($home) = System->get_home();

  my(@a) = split(/:/, "/usr/sbin:/usr/bin:/bin:$home/bin");
  foreach $dir (@a) {
     if (-x "$dir/$bin") {
        return "$dir/$bin";
     }
  }
  return undef;
}


sub find_luxadm {
  my($class) = @_;
  my($dir);

  my($home) = System->get_home();

  my(@a) = split(/:/, "/usr/sbin:/usr/bin:/bin:$home/bin");
  foreach $dir (@a) {
     if (-x "$dir/luxadm") {
        return "$dir/luxadm";
     }
  }
}

sub find_disk_inquiry {
  my($class) = @_;
  my(@a, $dir);

  my($home) = System->get_home();

  @a = split(/:/, "$home/bin:/opt/STORtools:/usr/bin:/bin");
  foreach $dir (@a) {
     if (-x "$dir/luxadm") {
        return "$dir/luxadm";
     }
  }
}

sub domain0 {
  my($class) = @_;
  return run_command('domainname');
}

sub domain {
  my($class) = @_;
  my $do;
#  require Net::Domain;
#  return Net::Domain::hostdomain();

  $do = run_command('domainname');
  my $ix = index($do, ".");
  if ($ix > 0) {
     return substr($do,$ix+1);
  }
  return "";
}

sub host_domain {
  my($class) = @_;
  require Net::Domain;
  return Net::Domain::hostfqdn();
}

# inet addr:10.10.10.10  Bcast:10.10.255.255  Mask:255.255.0.0

#/opt/SUNWstade/bin: /usr/sbin/ifconfig -a
#lo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1
#        inet 127.0.0.1 netmask ff000000 
#dmfe0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
#        inet 172.20.32.87 netmask ffffff00 broadcast 172.20.32.255
#        ether 0:3:ba:b:d1:71 
#dmfe1: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 3
#        inet 192.168.0.2 netmask ffffff00 broadcast 192.168.0.255
#        ether 0:3:ba:b:d1:71 


sub local_ip {
  my($class, $skip) = @_;
  my($if, @a, $x, $i, $ip);

  if ($class->os() =~ /Linux/) {
    @a = `/sbin/ifconfig -a`;
    for ($x = 0; $x <= $#a; $x++) {
       if ($a[$x] =~ /inet addr\:(.*) Bcast\:/) {
          return $1;
       }
    }
    return "Unknown";
  }
  @a = `/usr/sbin/ifconfig -a`;
     
  for ($x = 1; $x <= $#a; $x++) {
     $i = $a[$x];
     if ($i =~ /inet ([^s]+) / ) {
       $ip = $1;
       if ($ip ne "127.0.0.1") {
         return $ip;
       }
    }    
  }
  return undef;
}




sub get_hba {
  my($class) = @_ ;
  my($hba, $sbus, $pci) ;

#  chomp( $sbus = `/usr/sbin/prtconf -D | grep "SUNW,socal"` );
#  chomp( $pci = `/usr/sbin/prtconf -pv | grep "vendor-id:  00001077"` );

  if ($pci) {
     $hba = "P";
  } elsif ($sbus)  {
     $hba = "S";
  } else {
     $hba = "S";
  }
  return $hba;


}

sub readModules {
  my($class, $dir, $skip, $prefix) = @_;
  my($d0, @mods, $d);

  if (opendir(O, System->get_home . "/lib/$dir")) {
    while ($d0 = readdir(O)) {
       next if (substr($d0,-3) ne ".pm");
       $d = substr($d0, 0, -3);
       next if ($skip && $d eq $skip);
       next if ($prefix && substr($d,0,length($prefix)) ne $prefix);
       push(@mods, $d);
    }
    closedir(O);
    return @mods;
  } else {
    return ();
  }
}

# This function updates the array of file(s) in the packaging software database.
# It assumes the files belong to either the SUNWstade or SUNWstads package and
# will update the packaging software database for these packages only.
sub updateInstalledFiles {
  my($class, @files) = @_;
  my $PKGINST;
  my $Flag;

  # Check which package is installed.
  if (!system("/usr/bin/pkginfo SUNWstade >/dev/null 2>&1")) {
     $PKGINST = SUNWstade;
  }
  elsif (!system("/usr/bin/pkginfo SUNWstads >/dev/null 2>&1")) {
     $PKGINST = SUNWstads;
  }

  # Update the file(s) in the packaging software database
  if ($PKGINST) {
    foreach my $f (@files) {
      if (-f $f && -e $f) {
        my $mode = sprintf "%4o", (stat($f))[2] & 07777;
        my $owner = getpwuid ((stat($f))[4]);
        my $group = getgrgid ((stat($f))[5]);
        system("/usr/sbin/installf $PKGINST $f f $mode $owner $group");
        $Flag = 1;
      }
    }
    system("/usr/sbin/installf -f $PKGINST") if $Flag;
  }
}

# This function unlinks the array of file(s) from the system and from the
# packaging software database. It assumes the files belong to either the
# SUNWstade or SUNWstads package and will remove them from the packaging
# software database for these packages only.

sub unlinkInstalledFiles {
  my($class, @files) = @_;
  my $PKGINST;
  my $Flag;

  # Check which package is installed.
  if (!system("/usr/bin/pkginfo SUNWstade >/dev/null 2>&1")) {
     $PKGINST = SUNWstade;
  }
  elsif (!system("/usr/bin/pkginfo SUNWstads >/dev/null 2>&1")) {
     $PKGINST = SUNWstads;
  }

  # Remove the file(s) from the packaging software database
  if ($PKGINST) {
    foreach my $f (@files) {
      if (-f $f && -e $f) {
        system("/usr/sbin/removef $PKGINST $f >/dev/null");
        unlink $f;
        $Flag = 1;
      }
    }
    system("/usr/sbin/removef -f $PKGINST") if $Flag;
  }
}

#########################
# ENVIRONMENT
# save variables
#########################


sub AUTOLOAD {
  my($class, $val) = @_;
  my($key);

  if ($AUTOLOAD =~ /::set_(.*)/ ) {
       $key = $1;
       $AUTO{$key} = $val;
       return $val;
  } elsif ($AUTOLOAD =~ /::get_(.*)/ ) {
       $key = $1;
       if (!defined($AUTO{$key})) {
           print "get_$key not defined in System->get\n" if ($Debug::LEVEL > 3);
       }
       return $AUTO{$key};
  } else {
       return undef;
  }
}

1;
