#!/usr/bin/perl -w 

use strict;
use Tk;
use Tk::ProgressBar;
use Tk::LabEntry;
use OPS::Common;
use GTop;
use Env qw(HOSTNAME);

# Function Prototypes
sub init_vars();
sub create_window();
sub create_menu();
sub create_cpu_frame();
sub create_memory_frame();
sub create_swap_frame();
sub create_network_frame();
sub update_information();
sub get_cpu_info();
sub check_cpu();
sub check_memory();
sub check_swap();
sub check_network();
sub display_histograms();
sub display_filesys();
sub handle_errors();
sub create_histogram_frame();
sub update_histogram();
sub modify_main_window_geometry();
sub get_filesys_info();

# Signal Handlers
$SIG{__WARN__} = \&handle_errors;
$SIG{__DIE__} = \&handle_errors;

# Main code segment
{
    init_vars();

    background_process();

    create_window();
    create_menu();
    create_cpu_frame();
    create_memory_frame();
    create_swap_frame();
    create_network_frame();
    create_histogram_frame();
    update_information();

    MainLoop;

    exit;
}

sub handle_errors() {
    print stack_trace();
    return;
}

sub create_window() {
    $main::window = MainWindow->new;
    $main::window->CmdLine();
    $main::window->title("GUI Systems Monitor - $main::server");
    $main::window->resizable(0,1);
    $main::window->geometry($main::geometry);
    return;
}

sub create_menu() {
    $main::menuframe = $main::window->Frame(-relief => 'ridge', -borderwidth => 2);
    $main::menuframe->pack(-side => 'top', -anchor => 'n', -expand => 0, -fill => 'x');
    $main::menuframe->Button(-text => "CPU", -command => sub { check_cpu(); })->pack(-side => 'left', -padx => 5);
    $main::menuframe->Button(-text => "Memory", -command => sub { check_memory(); })->pack(-side => 'left', -padx => 5);
    $main::menuframe->Button(-text => "Swap", -command => sub { check_swap(); })->pack(-side => 'left', -padx => 5);
    $main::menuframe->Button(-text => "Network", -command => sub { check_network(); })->pack(-side => 'left', -padx => 5);
    $main::menuframe->Button(-text => "Histograms", -command => sub { display_histograms(); })->pack(-side => 'left', -padx => 5);
    $main::menuframe->Button(-text => "Filesystems", -command => sub { display_filesys(); })->pack(-side => 'left', -padx => 5);
    $main::menuframe->Button(-text => "Exit", -command => sub { exit; })->pack(-side => 'right', -padx => 5);
    return;
}

sub create_cpu_frame() {
    my $row = 1;
    my $col = 0;
    my $stick = 'nes';
    my $label;
    my @colors;
    $main::cpuframe = $main::window->Frame(-height => 208, -relief => 'ridge', -borderwidth => 3);
    $main::cpuframe->pack(-side => 'top', -anchor => 'n', -expand => 0, -fill => 'x');
    $main::cpuframe->Label(-justify => 'center', -text => 'CPU Information', -foreground => 'red')->grid(-row => 0,
                           -column => 0, -columnspan => 2);  
    
    foreach ( qw/ tasks procs user nice sys idle / ) {
        if    ( $_ eq "user" )  { $label = "% User:"; @colors = qw ( 0 green 80 yellow 90 red ); }
        elsif ( $_ eq "nice" )  { $label = "% Nice:"; @colors = qw ( 0 green 80 yellow 90 red ); }
        elsif ( $_ eq "sys" )   { $label = "% System:"; @colors = qw (0 green 80 yellow 90 red ); }
        elsif ( $_ eq "idle" )  { $label = "% Idle:"; @colors = qw ( 0 green ); }
        elsif ( $_ eq "tasks" ) { $label = "Processes:"; }
        elsif ( $_ eq "procs" ) { $label = "Active:"; $stick = 'nws'; $row = $row - 1; $col = $col + 1; }
        $main::cpuframe->LabEntry(-textvariable => \$main::cpu_hash{$_},
                                  -label => "$label", -width => 5, -state => 'disabled',
                                  -labelPack => [-side => 'left'])->grid(-row => $row,
                                  -column => $col, -sticky => $stick, -padx => 5, -pady => 2);
        if ( $_ ne "tasks" and $_ ne "procs" ) {
            my %colors = @colors;
            $main::cpuframe->ProgressBar(-variable => \$main::cpu_hash{$_},
                                         -width => 20, -length => 500, -anchor => 'w', -blocks => 100,
                                         -colors => [ %colors ])->grid(-row => $row,
                                         -column => 1, -sticky => 'nsw', -pady => 2);
        }
        if ( $_ eq "procs" ) { $col = 0; $stick = 'nes'; }
        $row = $row + 1;
    }
    $main::cpuframe->LabEntry(-textvariable => \$main::mem_hash{pctu},
                              -label => "Memory Used:", -width => 5, -state => 'disabled',
                              -labelPack => [-side => 'left'])->grid(-row => $row,
                              -column => $col, -sticky => $stick, -padx => 5, -pady => 2);
    $main::cpuframe->ProgressBar(-variable => \$main::mem_hash{pctu},
                                 -width => 20, -length => 500, -anchor => 'w', -blocks => 100,
                                 -colors => [0, 'green', 80, 'yellow', 90, 'red'])->grid(-row => $row,
                                 -column => 1, -sticky => 'nsw', -pady => 2);
    
    $row = $row + 1;
    $main::cpuframe->LabEntry(-textvariable => \$main::swap_hash{pctu},
                              -label => "Swap Used:", -width => 5, -state => 'disabled',
                              -labelPack => [-side => 'left'])->grid(-row => $row,
                              -column => $col, -sticky => $stick, -padx => 5, -pady => 2);
    $main::cpuframe->ProgressBar(-variable => \$main::swap_hash{pctu},
                                 -width => 20, -length => 500, -anchor => 'w', -blocks => 100,
                                 -colors => [0, 'green', 80, 'yellow', 90, 'red'])->grid(-row => $row,
                                 -column => 1, -sticky => 'nsw', -pady => 2);
    return;
}

sub create_memory_frame() {
    my $col = 0;
    my $row = 1;
    my $label;
    $main::memoryframe = $main::window->Frame(-height => 104, -relief => 'ridge', -borderwidth => 3);
    $main::memoryframe->pack(-side => 'top', -anchor => 'n', -expand => 0, -fill => 'x');
    $main::memoryframe->Label(-justify => 'center', -text => 'Memory Information', -foreground => 'blue')->grid(-row => 0, 
                              -column => 0, -columnspan => 3);

    foreach ( qw/ total used free shared buffer cached user locked / ) {
        if    ( $_ eq "total" ) { $label = "Total:"; $row = 1; $col = 0; }
        elsif ( $_ eq "used" )  { $label = "Used:"; $row = 2; $col = 0; }
        elsif ( $_ eq "free" )  { $label = "Free:"; $row = 3; $col = 0; }
        elsif ( $_ eq "shared" )  { $label = "Shared:"; $row = 1; $col = 1; }
        elsif ( $_ eq "buffer" )  { $label = "Buffer:"; $row = 2; $col = 1; }
        elsif ( $_ eq "cached" )  { $label = "Cache:"; $row = 3; $col = 1; }
        elsif ( $_ eq "user" )  { $label = "User:"; $row = 1; $col = 2; }
        elsif ( $_ eq "locked" )  { $label = "Locked:"; $row = 2; $col = 2; }
        $main::memoryframe->LabEntry(-textvariable => \$main::mem_hash{$_},
                                     -label => "$label", -width => 15, -state => 'disabled',
                                     -labelPack => [-side => 'left'])->grid(-row => $row,
                                     -column=> $col, -sticky => 'nes', -padx => 20, -pady => 2);
    }
    my ( $columns, $rows ) = $main::memoryframe->gridSize();
    for ( my $i = 0; $i < $columns; $i++ ) { $main::memoryframe->gridColumnconfigure($i, -weight => 1, -pad => 10); }
    return;
}

sub create_swap_frame() {
    my $col;
    my $row;
    my $label;
    $main::swapframe = $main::window->Frame(-height => 78, relief => 'ridge', -borderwidth => 3);
    $main::swapframe->pack(-side => 'top', -anchor => 'n', -expand => 0, -fill => 'x');
    $main::swapframe->Label(-justify => 'center', -text => 'Swap Information', -foreground => 'orange')->grid(-row => 0, -column => 0,
                              -columnspan => 3);
    
    foreach ( qw/ total used free pagein pageout / ) {
        if    ( $_ eq "total" ) { $label = "Total:"; $row = 1; $col = 0; }
        elsif ( $_ eq "used" )  { $label = "Used:"; $row = 1; $col = 1; }
        elsif ( $_ eq "free" )  { $label = "Free:"; $row = 1; $col = 2; }
        elsif ( $_ eq "pagein" ) { $label = "Page In:"; $row = 2; $col = 0; }
        elsif ( $_ eq "pageout" ) { $label = "Page Out:"; $row = 2; $col = 1; }
        $main::swapframe->LabEntry(-textvariable => \$main::swap_hash{$_},
                                   -label => "$label", -width => 15, -state => 'disabled',
                                   -labelPack => [-side => 'left'])->grid(-row => $row,
                                   -column=> $col, -sticky => 'nes', -pady => 2, -padx => 20);
    }
    my ( $columns, $rows ) = $main::swapframe->gridSize();
    for ( my $i = 0; $i < $columns; $i++ ) { $main::swapframe->gridColumnconfigure($i, -weight => 1); }
    return;
}

sub create_network_frame() {
    my $row;
    my $col;
    my $width;
    my $label;
    $main::networkframe = $main::window->Frame(-height => 104, -relief => 'ridge', -borderwidth => 3);
    $main::networkframe->pack(-side => 'top', -anchor => 'n', -expand => 0, -fill => 'x');
    $main::networkframe->Label(-justify => 'center', -text => 'Network Information')->grid(-row => 0, -column => 0, -columnspan => 4);

    $main::networkframe->LabEntry(-textvariable => \$main::network_interface,
                                  -label => "Interface:", -width => 8, -state => 'disabled',
                                  -labelPack => [-side => 'left'])->grid(-row => 1, -column => 0, -sticky => 'nes', -pady => 2);
 
    foreach ( qw/ collisions packets_total packets_in packets_out bytes_total bytes_in bytes_out errors_total errors_in errors_out/) {
        if    ( $_ eq "collisions" )    { $row = 2; $col = 0; $label = "Collisions:"; $width = 8; }
        elsif ( $_ eq "packets_total" ) { $row = 1; $col = 1; $label = "Total Packets:"; $width = 16; }
        elsif ( $_ eq "packets_in" )    { $row = 2; $col = 1; $label = "Packets Inbound:"; $width = 16; }
        elsif ( $_ eq "packets_out" )   { $row = 3; $col = 1; $label = "Total Outbound:"; $width = 16; }
        elsif ( $_ eq "bytes_total" )   { $row = 1; $col = 2; $label = "Total Bytes:"; $width = 16; }
        elsif ( $_ eq "bytes_in" )      { $row = 2; $col = 2; $label = "Bytes Inbound:"; $width = 16; }
        elsif ( $_ eq "bytes_out" )     { $row = 3; $col = 2; $label = "Bytes Outbound:"; $width = 16; }
        elsif ( $_ eq "errors_total" )  { $row = 1; $col = 3; $label = "Total Errors:"; $width = 8; }
        elsif ( $_ eq "errors_in" )     { $row = 2; $col = 3; $label = "Errors Inbound:"; $width = 8; }
        elsif ( $_ eq "errors_out" )    { $row = 3; $col = 3; $label = "Errors Outbound:"; $width = 8; }
        $main::networkframe->LabEntry(-textvariable => \$main::net_hash{$_},
                                      -label => "$label", -width => $width, -state => 'disabled',
                                      -labelPack => [-side => 'left'])->grid(-row => $row,
                                      -column=> $col, -sticky => 'nes', -pady => 2);
    }
    my ( $columns, $rows ) = $main::networkframe->gridSize();
    for ( my $i = 0; $i < $columns; $i++ ) { $main::networkframe->gridColumnconfigure($i, -weight => 1); }
    return;
}

sub create_histogram_frame() {
    $main::histogram_frame = $main::window->Frame(-height => 132, -relief => 'ridge', -borderwidth => 3);
    $main::histogram_frame->pack(-side => 'top', -anchor => 'n', -expand => 0, -fill => 'x');
    $main::cpu_hist = $main::histogram_frame->Canvas(-relief => 'ridge', -height => 120, -width => 300,  
                                                     -borderwidth => 2)->pack(-side => 'left', -anchor => 'center');
    $main::cpu_hist->createLine(0,100,300,100);
    $main::cpu_hist->createText(150,108, -text =>'CPU Histogram', -anchor => 'center');

    $main::mem_hist = $main::histogram_frame->Canvas(-relief => 'ridge', -height => 120, -width => 300,
                                                     -borderwidth => 2)->pack(-side => 'left', -anchor => 'center');
    $main::mem_hist->createLine(0,100,300,100);
    $main::mem_hist->createText(150,108, -text =>'Memory Histogram', -anchor => 'center');

    $main::swap_hist = $main::histogram_frame->Canvas(-relief => 'ridge', -height => 120, -width => 300,
                                                     -borderwidth => 2)->pack(-side => 'left', -anchor => 'center');
    $main::swap_hist->createLine(0,100,300,100);
    $main::swap_hist->createText(150,108, -text =>'Swap Histogram', -anchor => 'center');
    return;
}


sub get_cpu_info() {
    my $cpu = $main::gtop->cpu;
    my %cpu_hash = ();
    foreach ( qw/ total user nice sys idle / ) { $cpu_hash{$_} = $cpu->$_; }
    return %cpu_hash;
}

sub update_information() {
    my $cpu = $main::gtop->cpu;
    my $load = $main::gtop->loadavg;
    my %cpu_hash = get_cpu_info();
    foreach ( qw/ user nice sys idle / ) {
       my $div = $cpu_hash{total} - $main::cpu_history{total};
       if ( $div > 0 ) {
           my $value = ( ( $cpu_hash{$_} - $main::cpu_history{$_} ) * 100 ) / ( $div );
           $main::cpu_hash{$_} = sprintf("%.2f",$value);
       }
    }
    $main::cpu_hash{tasks} = $load->nr_tasks;
    $main::cpu_hash{procs} = $load->nr_running;
    %main::cpu_history = %cpu_hash;
    
    my $mem = $main::gtop->mem;
    foreach ( @main::mem_items ) { $main::mem_hash{$_} = $mem->$_; }
    my $average = ( $main::mem_hash{used} * 100 ) / $main::mem_hash{total};
    foreach ( @main::mem_items ) { $main::mem_hash{$_} = add_comma($main::mem_hash{$_}); }
    $main::mem_hash{pctu} = sprintf("%.2f",$average);

    my $swap = $main::gtop->swap;
    foreach ( @main::swap_items ) { $main::swap_hash{$_} = $swap->$_; }
    $average = ( $main::swap_hash{used} * 100 ) / $main::swap_hash{total};
    foreach ( @main::swap_items ) { $main::swap_hash{$_} = add_comma($main::swap_hash{$_}); }
    $main::swap_hash{pctu} = sprintf("%.2f",$average);

    my $network = $main::gtop->netload($main::network_interface);
    foreach ( @main::net_items ) { $main::net_hash{$_} = add_comma($network->$_); }

    if ( Exists($main::histogram_frame) ) { update_histogram(); }

    $main::window->after($main::refresh_rate, \&update_information);
    return;
}

sub update_histogram() {
    if ( @main::cpu_hist > 100 )  { shift @main::cpu_hist; }
    if ( @main::mem_hist > 100 )  { shift @main::mem_hist; }
    if ( @main::swap_hist > 100 ) { shift @main::swap_hist; }

    my $cpu = 100 - $main::cpu_hash{idle};
    push (@main::cpu_hist,$cpu);
    push (@main::mem_hist,$main::mem_hash{pctu});
    push (@main::swap_hist,$main::swap_hash{pctu});

    my @cpu_points = ();
    my @mem_points = ();
    my @swap_points = ();

    push (@cpu_points,0);
    push (@cpu_points,100);
    push (@mem_points,0);
    push (@mem_points,100);
    push (@swap_points,0);
    push (@swap_points,100);

    my $ctr = 1;
    my $xpos;
    foreach (@main::cpu_hist) {
        my $val = 100 - $_;
        $xpos = $ctr * 3;
        push (@cpu_points,$xpos);
        push (@cpu_points,$val);
        $ctr = $ctr + 1;
    }
    push (@cpu_points,$xpos);
    push (@cpu_points,100);

    $ctr = 1;
    foreach (@main::mem_hist) {
        my $val = 100 - $_;
        $xpos = $ctr * 3;
        push (@mem_points,$xpos);
        push (@mem_points,$val);
        $ctr = $ctr + 1;
    }
    push (@mem_points,$xpos);
    push (@mem_points,100);

    $ctr = 1;
    foreach (@main::swap_hist) {
        my $val = 100 - $_;
        $xpos = $ctr * 3;
        push (@swap_points,$xpos);
        push (@swap_points,$val);
        $ctr = $ctr + 1;
    }
    push (@swap_points,$xpos);
    push (@swap_points,100);

    if ( Exists($main::cpu_hist) )  { $main::cpu_hist->delete('cpupoly'); 
                                      $main::cpu_hist->createPolygon(@cpu_points, -tags => 'cpupoly', -fill => 'red'); }
    if ( Exists($main::mem_hist) )  { $main::mem_hist->delete('mempoly'); 
                                      $main::mem_hist->createPolygon(@mem_points, -tags => 'mempoly', -fill => 'blue'); }
    if ( Exists($main::swap_hist) ) { $main::swap_hist->delete('swappoly'); 
                                      $main::swap_hist->createPolygon(@swap_points, -tags => 'swappoly', -fill => 'orange'); }
        
    return;
}

sub init_vars() {
    $main::xdim = "920";
    $main::ydim = "660";
    $main::xoff = "120";
    $main::yoff = "100";
    $main::geometry = $main::xdim . "x" . $main::ydim . "+" . $main::xoff . "+" . $main::yoff;
    $main::gtop = GTop->new;
    $main::refresh_rate = 3000;
    $main::network_interface = "eth0";
    $main::server = $HOSTNAME;
    @main::swap_items = qw( total used free pagein pageout );
    @main::mem_items = qw( total used free shared buffer cached user locked );
    @main::net_items = qw( mtu packets_in packets_out packets_total bytes_in bytes_out bytes_total errors_in errors_out errors_total collisions );
    %main::cpu_hash = ();
    %main::net_hash = ();
    @main::cpu_hist = ();
    @main::mem_hist = ();
    @main::swap_hist = ();
    %main::cpu_history = get_cpu_info();
    
    return;
}

sub check_cpu() {
    if ( Exists($main::cpuframe) ) { my $fheight = $main::cpuframe->height();
                                     my $height = $main::window->height();
                                     $main::ydim = $height - $fheight;
                                     $main::cpuframe->destroy();
                                     modify_main_window_geometry(); }
    else                           { create_cpu_frame(); 
                                     my $fheight = $main::cpuframe->reqheight();
                                     my $height = $main::window->height();
                                     $main::ydim = $height + $fheight;
                                     modify_main_window_geometry(); }
    return;
}

sub check_memory() {
    if ( Exists($main::memoryframe) ) { my $fheight = $main::memoryframe->height(); 
                                        my $height = $main::window->height();
                                        $main::ydim = $height - $fheight;
                                        $main::memoryframe->destroy();
                                        modify_main_window_geometry(); }
    else                              { create_memory_frame(); 
                                        my $fheight = $main::memoryframe->reqheight();
                                        my $height = $main::window->height();
                                        $main::ydim = $height + $fheight;
                                        modify_main_window_geometry(); }
    return;
}

sub check_swap() {
    if ( Exists($main::swapframe) ) { my $fheight = $main::swapframe->height();
                                      my $height = $main::window->height();
                                      $main::ydim = $height - $fheight;
                                      $main::swapframe->destroy(); 
                                      modify_main_window_geometry(); }
    else                            { create_swap_frame(); 
                                      my $fheight = $main::swapframe->reqheight();
                                      my $height = $main::window->height();
                                      $main::ydim = $height + $fheight;
                                      modify_main_window_geometry(); }
    return;
}

sub check_network() {
    if ( Exists($main::networkframe) ) { my $fheight = $main::networkframe->height();
                                         my $height = $main::window->height();
                                         $main::ydim = $height - $fheight;
                                         $main::networkframe->destroy(); 
                                         modify_main_window_geometry(); }
    else                               { create_network_frame(); 
                                         my $fheight = $main::networkframe->reqheight();
                                         my $height = $main::window->height();
                                         $main::ydim = $height + $fheight;
                                         modify_main_window_geometry(); }
    return;
}

sub display_histograms() {
    if ( Exists($main::histogram_frame) ) { my $fheight = $main::histogram_frame->height();
                                            my $height = $main::window->height();
                                            $main::ydim = $height - $fheight;
                                            $main::histogram_frame->destroy(); 
                                            modify_main_window_geometry(); }
    else                                  { create_histogram_frame();
                                            my $fheight = $main::histogram_frame->reqheight();
                                            my $height = $main::window->height();
                                            $main::ydim = $height + $fheight;
                                            modify_main_window_geometry(); }
    return;
}

sub modify_main_window_geometry() {
    $main::geometry = $main::xdim . "x" . $main::ydim;
    $main::window->geometry($main::geometry); 
    return;
}

sub get_filesys_info() {
    my @fsara = ();
    my ($mountlist, $entries) = $main::gtop->mountlist(1);
    my $number = $mountlist->number;
    my $i = 0;  
    while ( $i < $number ) {
        my $device = $entries->devname($i);
        my $mountpt = $entries->mountdir($i);
        my $mnttype = $entries->type($i);

        my $fsusage = $main::gtop->fsusage($mountpt);
        my $blocks = $fsusage->blocks;
        my $bfree = $fsusage->bfree;
        my $bavail = $fsusage->bavail;
        my $files = $fsusage->files;
        my $ffree = $fsusage->ffree;
        my $fsavg = 0;
        if ( $blocks > 0 ) { $fsavg = ( ( $bavail * 100 ) / $blocks ); }
        else               { $fsavg = 0; }

        my $araval = "$mountpt $device $mnttype $blocks $bfree $bavail $fsavg $files $ffree";
        push (@fsara,$araval);

        $i = $i + 1;
    }
    return @fsara;
}

sub display_filesys() {
    my @filesys = get_filesys_info();
    my $row = 1;

    $main::filesys_window = $main::window->Toplevel();
    $main::filesys_window->title("Filesystem Usage");
    $main::filesys_frame = $main::filesys_window->Frame(-relief => 'ridge')->pack(-side => 'top');

    $main::filesys_frame->Label(-text => "Mount Point", -anchor => 'w', -width => 30, 
                                -relief => 'groove')->grid(-sticky => 'nsew', -row => 0, -column => 0, -padx => 3);
    $main::filesys_frame->Label(-text => "Device", -anchor => 'w', -width => 25,
                                -relief => 'groove')->grid(-sticky => 'nsew', -row => 0, -column => 1, -padx => 3);
    $main::filesys_frame->Label(-text => "Filesytem Type", -anchor => 'w', -width => 15,
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 2, -padx => 3);
    $main::filesys_frame->Label(-text => "Total Blocks", -anchor => 'w', -width => 18, 
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 3, -padx => 3);
    $main::filesys_frame->Label(-text => "Blocks Free", -anchor => 'w', -width => 18, 
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 4, -padx => 3);
    $main::filesys_frame->Label(-text => "Blocks Available", -anchor => 'w', -width => 18,
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 5, -padx => 3);
    $main::filesys_frame->Label(-text => "Number Of Files", -anchor => 'w', -width => 18, 
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 6, -padx => 3);
    $main::filesys_frame->Label(-text => "Files Free", -anchor => 'w', -width => 18, 
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 7, -padx => 3);
    $main::filesys_frame->Label(-text => "Percent Free", -anchor => 'w', -width => 15, 
                                -relief => 'groove')->grid(-sticky => 'w', -row => 0, -column => 8, -padx => 3);


    foreach (@filesys) {
        my ($mountpt,$device,$mnttype,$blocks,$bfree,$bavail,$fsavg,$files,$ffree) = (split);
        $fsavg = sprintf("%.2f",$fsavg);
        $blocks = add_comma($blocks);
        $bfree = add_comma($bfree);
        $bavail = add_comma($bavail);
        $files = add_comma($files);
        $ffree = add_comma($ffree);
        $main::filesys_frame->Label(-text => "$mountpt", -anchor => 'w', -justify => 'left', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 0, -padx => 3);
        $main::filesys_frame->Label(-text => "$device", -anchor => 'w', -justify => 'left', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 1, -padx => 3);
        $main::filesys_frame->Label(-text => "$mnttype", -anchor => 'w', -justify => 'left', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 2, -padx => 3);
        $main::filesys_frame->Label(-text => "$blocks", -anchor => 'e', -justify => 'right', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 3, -padx => 3);
        $main::filesys_frame->Label(-text => "$bfree", -anchor => 'e', -justify => 'right', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 4, -padx => 3);
        $main::filesys_frame->Label(-text => "$bavail", -anchor => 'e', -justify => 'right', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 5, -padx => 3);
        $main::filesys_frame->Label(-text => "$files", -anchor => 'e', -justify => 'right', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 6, -padx => 3);
        $main::filesys_frame->Label(-text => "$ffree", -anchor => 'e', -justify => 'right', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 7, -padx => 3);
        $main::filesys_frame->Label(-text => "$fsavg", -anchor => 'e', -justify => 'right', 
                                    -borderwidth => 1, -relief => 'groove')->grid(-sticky => 'nsew', 
                                    -row => $row, -column => 8, -padx => 3);
        $row = $row + 1;
    }
    my ( $columns, $rows ) = $main::filesys_frame->gridSize();
    for ( my $i = 0; $i < $columns; $i++ ) { $main::filesys_frame->gridColumnconfigure($i, -weight => 0); }
    return;
}
