#---------------------------------------------------------------------------
package Solaris::Procfs::Process;
# Copyright (c) 1999,2000 John Nolan. All rights reserved.
# This program is free software. You may modify and/or
# distribute it under the same terms as Perl itself.
# This copyright notice must remain attached to the file.
#
# You can run this file through either pod2text, pod2man or
# pod2html to produce pretty documentation in text, manpage or
# html file format (these utilities are part of the
# Perl 5 distribution).
use vars qw($VERSION @ISA $AUTOLOAD);
use vars qw($DISPATCHER $NON_OWNER_FUNCTION_LIST $FUNCTION_LIST $DEBUG);
use vars qw(%DEFAULTPARAMS);
use Carp;
use strict;
require Exporter;
*VERSION = *Solaris::Procfs::VERSION;
*DEBUG = *Solaris::Procfs::DEBUG;
@ISA = qw();
%DEFAULTPARAMS = (
autoupdate => 0,
);
#-------------------------------------------------------------
# Dispatch hash, used by the AUTOLOAD function of
# Solaris::Procfs::Process, to send method calls
# directly to the corresponding method in Solaris::Procfs.
#
$DISPATCHER = {
# Dispatch to perl functions
#
'root' => \&Solaris::Procfs::root,
'cwd' => \&Solaris::Procfs::cwd,
'fd' => \&Solaris::Procfs::fd,
'writectl' => \&Solaris::Procfs::writectl,
# Dispatch to XS functions directly
#
'auxv' => \&Solaris::Procfs::_auxv,
'lpsinfo' => \&Solaris::Procfs::_lpsinfo,
'lstatus' => \&Solaris::Procfs::_lstatus,
'lusage' => \&Solaris::Procfs::_lusage,
'lwp' => \&Solaris::Procfs::_lwp,
'map' => \&Solaris::Procfs::_map,
'xmap' => \&Solaris::Procfs::_xmap,
'prcred' => \&Solaris::Procfs::_prcred,
'psinfo' => \&Solaris::Procfs::_psinfo,
'rmap' => \&Solaris::Procfs::_rmap,
'sigact' => \&Solaris::Procfs::_sigact,
'status' => \&Solaris::Procfs::_status,
'usage' => \&Solaris::Procfs::_usage,
};
$FUNCTION_LIST = {
'root' => '',
'cwd' => '',
'fd' => '',
'auxv' => '',
'lpsinfo' => '',
'lstatus' => '',
'lusage' => '',
'lwp' => '',
'map' => '',
'xmap' => '',
'prcred' => '',
'psinfo' => '',
'rmap' => '',
'sigact' => '',
'status' => '',
'usage' => '',
};
$NON_OWNER_FUNCTION_LIST = {
'lpsinfo' => '',
'lusage' => '',
'lwp' => '',
'psinfo' => '',
'usage' => '',
};
foreach (keys %$DISPATCHER) {
$DISPATCHER->{"Solaris::Procfs::Process::$_"} = $DISPATCHER->{$_};
}
#-------------------------------------------------------------
#
sub DELETE {
my ($self, $index) = @_;
print STDERR (caller 0)[3], ": \$index is $index\n"
if $DEBUG >= 2;
# Can't remove the pid element
#
return if $index eq 'pid';
return delete $self->{$index};
}
#-------------------------------------------------------------
#
sub EXISTS {
my ($self, $index) = @_;
print STDERR (caller 0)[3], ": \$index is $index\n"
if $DEBUG >= 2;
if (exists $self->{$index}) {
return 1;
} elsif ($self->FETCH($index)) {
return 1;
}
return;
}
#-------------------------------------------------------------
#
sub STORE {
my ($self, $index, $val) = @_;
# Can't modify the pid element, if it's there.
# It can only be defined at the time the hash is created.
#
return if $index eq 'pid';
print STDERR (caller 0)[3], ": \$index is $index, \$val is $val\n"
if $DEBUG >= 2;
return $self->{$index};
}
#-------------------------------------------------------------
#
sub NEXTKEY {
my ($self) = @_;
print STDERR (caller 0)[3], ": \n"
if $DEBUG >= 2;
return each %{ $self };
}
#-------------------------------------------------------------
#
sub FIRSTKEY {
my ($self) = @_;
print STDERR (caller 0)[3], ": \n"
if $DEBUG >= 2;
keys %{ $self };
return each %{ $self };
}
#-------------------------------------------------------------
#
sub DESTROY {
my ($self) = @_;
print STDERR (caller 0)[3], ": \$self is $self\n"
if $DEBUG >= 2;
}
#-------------------------------------------------------------
#
sub CLEAR {
my ($self) = @_;
print STDERR (caller 0)[3], ": \$self is $self\n"
if $DEBUG >= 2;
}
#-------------------------------------------------------------
#
sub new {
my $proto = shift;
my $pid = shift;
my $class = ref($proto) || $proto;
print STDERR (caller 0)[3], ": Creating object for pid $pid\n"
if $DEBUG >= 2;
return unless
defined $pid and
not ref($pid) and
$pid =~ /^\d+$/ and
-d "/proc/$pid"
;
my $self = { };
tie %$self, $class, $pid, @_;
bless $self, $class;
print STDERR (caller 0)[3], ": ", join(" ", keys %$self),"\n\n"
if $DEBUG >= 2;
return $self;
}
#-------------------------------------------------------------
#
sub TIEHASH {
my $pkg = shift;
my $pid = shift;
my %temp = (%DEFAULTPARAMS, @_);
$temp{ pid } = $pid ;
my $psinfo = Solaris::Procfs::psinfo($pid);
# If we own the process or if we are root, then pre-define all
# the available files. Otherwise, just the owner's files.
#
my $available_procfiles = $psinfo->{pr_euid} == $< || $< == 0
? $FUNCTION_LIST
: $NON_OWNER_FUNCTION_LIST
;
print STDERR (caller 0)[3], ": Adding elements to object...\n"
if $DEBUG >= 2;
print STDERR (caller 0)[3], ": ", join(" ", keys %$available_procfiles),"\n\n"
if $DEBUG >= 2;
%temp = ( %temp, %$available_procfiles );
my $self = \%temp;
$self->{available_procfiles} = $available_procfiles;
$self->{psinfo} = $psinfo;
print STDERR (caller 0)[3], ": \$self is $self, \$pkg is $pkg, \$pid is $pid\n"
if $DEBUG >= 2;
return (bless $self, $pkg);
}
#-------------------------------------------------------------
#
sub FETCH {
my ($self, $index) = @_;
return unless defined $index;
print STDERR (caller 0)[3], ": Read \$index $index, \$self->{pid} is $self->{pid}\n"
if $DEBUG >= 2;
if ($index eq "pid") {
print STDERR (caller 0)[3], ": Returning \$self->{$index} : $self->{$index}\n"
if $DEBUG >= 2;
return $self->{$index};
} elsif ( exists $DISPATCHER->{$index} ) {
if ( exists $self->{$index} and $self->{$index} ne '' and not $self->{autoupdate}) {
print STDERR (caller 0)[3], ": Returning cached results\n"
if $DEBUG >= 2;
return $self->{$index};
} elsif ( -d "/proc/$self->{pid}" ) {
print STDERR (caller 0)[3], ": Delegating to function $index\n"
if $DEBUG >= 2;
if (exists $self->{available_procfiles}->{$index}) {
$self->{$index} = &{ $DISPATCHER->{$index} }( $self->{pid} ) ;
return $self->{$index};
} else {
delete $self->{$index};
return &{ $DISPATCHER->{$index} }( $self->{pid} ) ;
}
} else { # if not -d "/proc/$self->{pid}"
print STDERR (caller 0)[3], ": No such process as $self->{pid}\n"
if $DEBUG >= 2;
return; ## If the process no longer exists under /proc
}
} elsif ( exists $self->{$index} ) { # and $DISPATCHER->{$index} does not exist
return $self->{$index};
} else {
print STDERR (caller 0)[3], ": No such function or element as $index\n"
if $DEBUG >= 2;
return; ## If the user requested a function not in Procfs
}
}
#-------------------------------------------------------------
#
sub AUTOLOAD {
my $self = shift;
print STDERR (caller 0)[3], ": Want function $AUTOLOAD\n"
if $DEBUG >= 2;
if (exists $DISPATCHER->{$AUTOLOAD} ) {
unless (defined $self and ref($self) eq "Solaris::Procfs::Process") {
# You can't call Solaris::Procfs::Process::psinfo
# or any other function directly. (Even though you can call
# Solaris::Procfs::psinfo and friends.)
#
carp "$AUTOLOAD: Must be called as a method, not as a class function";
return;
}
print STDERR (caller 0)[3], ": Delegating to function $AUTOLOAD\n"
if $DEBUG >= 2;
# my $temp = &{ $DISPATCHER->{$AUTOLOAD} }( $self->{pid}, @_ );
# return $temp;
return &{ $DISPATCHER->{$AUTOLOAD} }( $self->{pid}, @_ );
} else {
carp (
(caller 0)[3] .
": Attempt to invoke nonexistant function $AUTOLOAD\n"
);
return;
}
}
1;