#!/pro/bin/perl
use Tk;
use Time::localtime;
$width = 80;
to_background ();
InitTop ();
MainLoop;
### ###########################################################################
sub to_background
{
setpriority $pid, $$, 20;
my $pid = fork;
if ($pid < 0) {
print STDERR "Unable to run in the background, cannot fork: $!\n";
exit $?;
}
$pid and exit 0;
} # to_background
sub InitTop
{
my $f;
chomp ($HOST = `hostname`);
$top = MainWindow->new (-cursor => "top_left_arrow", -name => "Top");
$top->title ("XTOP $HOST");
$top->bind ("<Key>q" => sub {$top->destroy});
$f = $top->Frame (-relief => "flat")->pack (-fill => "both", -side => "top");
$f->Label (-text => "System: $HOST")->pack (-fill => "both", -side => "left");
$sysdate = ctime (time);
$f->Label (-textvariable => \$sysdate)->pack (-fill => "both", -side => "right");
$f = $top->Frame (-relief => "flat")->pack (-fill => "both", -side => "top");
$sysload = "Load avarages: ";
$f->Label (-textvariable => \$sysload)->pack (-fill => "both", -side => "left");
$f = $top->Frame (-relief => "flat")->pack (-fill => "both", -side => "top");
$sysproc = "0 processes: 0 sleeping, 0 running, 0 zombies";
$f->Label (-textvariable => \$sysproc)->pack (-fill => "both", -side => "left");
%state = (
"0" => "nonexistent",
"A" => "active ",
"S" => "sleeping ",
"W" => "waiting ",
"R" => "running ",
"I" => "idle ",
"Z" => "terminated ",
"T" => "stopped ",
"X" => "growing ");
$ENV{UNIX95} = 1;
$pslist = $top->Scrolled ("ROText",
-scrollbars => "e",
-wrap => "none",
-height => 20,
-width => $width)->pack (
-expand => 1,
-fill => "both",
-side => "left");
$pslist->insert ("end", "PROcess list\n");
#$pslist->bind ("<Key>q" => sub {$top->destroy});
UpdateTop ();
$top->repeat (2000, \&UpdateTop);
} # InitTop
sub pslist
{
my $pcpu_ok = 1; # Got patched ps from hp (02 Mar 1999)
my @ps = $pcpu_ok
? `ps -e -otty,pid,user,pri,nice,state,vsz,time,pcpu,args`
: `ps -e -otty,pid,user,pri,nice,state,vsz,time,cpu,args`;
shift @ps; # Skip header, creating my own
# Not all unix flavours use the same -o syntax
my $hdr = " TTY PID USERNAME PRI NI STATE SIZE TIME \%CPU COMMAND\n";
my %cntproc = ();
# Positions are based on reformatted output
my @s = ( [ 52, 5], # %CPU
[ 39, 6], # SIZE
[ 45, 7], # TIME
[ 27, 2], # NICE
);
@ps = sort {
substr ($b, $s[0][0],$s[0][1]) <=> substr ($a, $s[0][0],$s[0][1]) ||
substr ($b, $s[1][0],$s[1][1]) <=> substr ($a, $s[1][0],$s[1][1]) ||
substr ($b, $s[2][0],$s[2][1]) cmp substr ($a, $s[2][0],$s[2][1]) ||
substr ($a, $s[3][0],$s[3][1]) <=> substr ($b, $s[3][0],$s[3][1]) ||
$a cmp $b;
} map {
s/^\s+//;
my @x = split m/\s+/, $_, 10;
$x[0] =~ s/\?/-/;
$cntproc{$x[5]}++;
$x[5] =~ s/(.)/$state{$1}/;
my @t = ((reverse split m/:/, $x[7]), 0, 0, 0);
$x[7] = sprintf ("%4d:%02d", $t[2] * 60 + $t[1], $t[0]);
$pcpu_ok and $x[8] *= 100.;
sprintf "%6s %6d %-8s %3d %2d %-.8s %6d%6s%5.1f %s", @x;
} @ps;
$sysproc = sprintf ("%d processes: %d sleeping, %d running, %d zombies",
scalar @ps, $cntproc{S}, $cntproc{R}, $cntproc{Z});
# unshift @ps, "0----+----1----+----2----+----3----+----4----+----5----+----6----+----7\n";
join "", $hdr, @ps;
} # pslist
sub ruptime
{
my $r;
($r = `rup localhost`) =~ s/.*l(oad.*\d)/L$1/;
# ($r = (grep m/^$HOST\b/, `ruptime`)[0]) =~
# s/.*load\s+(.*\d)\s*/Load avarage: $1/;
chomp $r;
$r;
} # ruptime
sub UpdateTop
{
$sysdate = ctime (time);
$sysload = ruptime;
$pslist->delete ("1.0", "end");
$pslist->insert ("end", &pslist);
} # UpdateTop