#!/usr/bin/perl # Monitor # Copyright (C) 1999 MandrakeSoft (damien@mandrakesoft.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. use Gtk; use lib qw(/usr/lib/libDrakX); use interactive; use standalone; use my_gtk qw(:helpers :wrappers); #-use Data::Dumper; use common; use strict; use network::netconnect; use network::tools; use MDK::Common::Globals "network", qw($in $prefix $connect_file $disconnect_file $connect_prog); if ("@ARGV" =~ /--help|-h/) { print q(Network & Internet connection and monitoring application --defaultintf interface : show this interface by default --connect : connect to internet if not already connected --disconnect : disconnect to internet if already connected --force : used with (dis)connect : force (dis)connection. --status : returns 1 if connected 0 otherwise, then exit. --quiet : don't be interactive. To be used with (dis)connect. ); exit(0); } if ("@ARGV" =~ /--status/) { print connected(); exit(0) } my $force = "@ARGV" =~ /--force/; my $quiet = "@ARGV" =~ /--quiet/; my $connect = "@ARGV" =~ /--connect/; my $disconnect = "@ARGV" =~ /--disconnect/; my ($default_intf) = "@ARGV" =~ /--defaultintf (\w+)/; if ($force) { $connect and system("/etc/sysconfig/network-scripts/net_cnx_up &"); $disconnect and system("/etc/sysconfig/network-scripts/net_cnx_down &"); $connect = $disconnect = 0; } $quiet and exit(0); init Gtk; my $in = 'interactive'->vnew('su', 'default'); $::isEmbedded = ($::XID, $::CCPID) = "@ARGV" =~ /--embedded (\w+) (\w+)/; my $window1 = $::isEmbedded ? new Gtk::Plug ($::XID) : new Gtk::Window -toplevel; $window1->signal_connect ( delete_event => sub { Gtk->exit(0); }); $window1->set_position(1); $window1->set_title(_("Network Monitoring")); $window1->set_policy(1, 1, 1); $window1->set_border_width(5); #$::isEmbedded or $window1->set_usize(580, 320); my $colorr = my_gtk::gtkcolor(50400, 655, 20000); my $colort = my_gtk::gtkcolor(55400, 55400, 655); my $colora = my_gtk::gtkcolor(655, 50400, 655); my $isconnected=-1; my @interfaces; my $monitor = {}; my $netcnx = {}; my $netc = {}; my $intf = {}; my $c_time = 0; my $ct_tag; my $style= new Gtk::Style; $style->font(Gtk::Gdk::Font->fontset_load("-adobe-times-medium-r-normal-*-12-*-75-75-p-*-iso8859-*,*-r-*")); network::netconnect::load_conf($netcnx, $netc, $intf); network::netconnect::read_net_conf('', $netcnx, $netc); my $combo1 = new Gtk::Combo; $combo1->set_popdown_strings (network::netconnect::get_profiles() ); $combo1->entry->set_text($netcnx->{PROFILE} ? $netcnx->{PROFILE} : "default"); $combo1->entry->set_editable(0); MDK::Common::Globals::init( in => $in, prefix => '', connect_file => "/etc/sysconfig/network-scripts/net_cnx_up", disconnect_file => "/etc/sysconfig/network-scripts/net_cnx_down", connect_prog => "/etc/sysconfig/network-scripts/net_cnx_pg" ); gtkadd($window1, gtkpack_(new Gtk::VBox(0,5), 0, _("Network Monitoring"), 1, gtkpack_(new Gtk::HBox(0,5), 1, my $notebook = new Gtk::Notebook, 0, gtkpack_(new Gtk::VBox(0,5), 0, gtkadd(gtkset_shadow_type(new Gtk::Frame(_("Settings")), 'etched_out'), gtkpack__(gtkset_border_width(new Gtk::VBox(0,5),5), gtkpack__(new Gtk::HBox(0,0), _("Connection type: "), my $label_cnx_type = new Gtk::Label("")), gtkpack__(new Gtk::HBox(0,0), _("Profile "), $combo1) ) ), 1, gtkadd(gtkset_shadow_type(new Gtk::Frame(_("Statistics")), 'etched_out'), gtkpack__(new Gtk::VBox(0,0), create_packtable({ col_spacings => 1, row_spacings => 1}, [ "", "instantaneous" , "average"], [ _("Sending Speed:"), my $label_st = new Gtk::Label(""), my $label_sta=new Gtk::Label("na")], [ _("Receiving Speed:"),my $label_sr= new Gtk::Label(""), my $label_sra=new Gtk::Label("na")], ), gtkpack__(new Gtk::HBox(0,0), " "._("Connection Time: "), my $label_ct = new Gtk::Label("")), ) ), 0, gtkpack_(new Gtk::HBox(0,5), 1, gtksignal_connect(my $button_connect = gtkset_sensitive(new Gtk::Button(), 0), clicked => \&connection), 0, new Gtk::VSeparator, 0, gtkpack(new Gtk::VBox(0,5), gtksignal_connect(new Gtk::Button(_("Logs")), clicked => sub { -e "/usr/sbin/logdrake" ? system('/usr/sbin/logdrake --file=/var/log/messages &') : system('/usr/X11R6/bin/xvt -e "tail -f /var/log/messages " &') }), gtksignal_connect(my $button_close = new Gtk::Button(_("Close")), clicked => sub { Gtk->exit(0) }), ) ) ) ), 0, my $statusbar = new Gtk::Statusbar ) ); $window1->show_all; $window1->realize; $combo1->entry->signal_connect( 'changed', sub { network::netconnect::set_profile($netcnx, $combo1->entry->get_text()); network::netconnect::load_conf($netcnx, $netc, $intf); network::netconnect::set_net_conf($netcnx, $netc, $intf); network::netconnect::read_net_conf('', $netcnx, $netc); }); my $gct = new Gtk::Gdk::GC($window1->window); $gct->set_foreground($colort); my $gcr = new Gtk::Gdk::GC($window1->window); $gcr->set_foreground($colorr); my $gca = new Gtk::Gdk::GC($window1->window); $gca->set_foreground($colora); my ($pix_c_map, $pix_c_mask) = gtkcreate_png("net_c.png"); my ($pix_d_map, $pix_d_mask) = gtkcreate_png("net_d.png"); my ($pix_u_map, $pix_u_mask) = gtkcreate_png("net_u.png"); $button_connect->add(gtkpack__(new Gtk::VBox(0,3), my $pix_c = new Gtk::Pixmap($pix_u_map, $pix_u_mask), my $label_c = new Gtk::Label(_("Wait please")) )); $statusbar->push(1, _("Wait please, testing your connection...")); $window1->show_all(); #$window1->set_policy (1, 1, 1); my $time_tag = Gtk->timeout_add(1000, \&rescan); my $time_tag2 = Gtk->timeout_add(5000, \&update); update(); rescan(); while ($isconnected == -1) { Gtk->main_iteration while Gtk->events_pending; } connection() if ($connect && !$isconnected || $disconnect && $isconnected); Gtk->main; Gtk->exit(0); my $during_connection; sub connection { $during_connection = 1; my $isconnected2 = $isconnected; $button_connect->set_sensitive(0); $button_close->set_sensitive(0); $statusbar->pop(1); $statusbar->push(1, $isconnected2 ? _("Disconnecting from Internet ") : _("Connecting to Internet ")); if(!$isconnected2) { $c_time = time(); $ct_tag = Gtk->timeout_add(1000, sub { my ($sec,$min,$hour) = gmtime(time() - $c_time); my $e = sprintf ("%02d:%02d:%02d", $hour, $min, $sec); $label_ct->set($e); 1; }); } else { Gtk->timeout_remove($ct_tag) } my $nb_point=1; my $tag = Gtk->timeout_add(100, sub { $statusbar->pop(1); $statusbar->push(1, ($isconnected2 ? _("Disconnecting from Internet ") : _("Connecting to Internet ")) . join('', map { "." } (1..$nb_point))); $nb_point++; 1; }); my $netc = {}; my $tag2 = Gtk->timeout_add(10000, sub { Gtk->timeout_remove($tag); $statusbar->pop(1); $statusbar->push(1, $isconnected2 ? ( $isconnected ? _("Disconnection from Internet failed.") : _("Disconnection from Internet complete.")) : ( $isconnected ? _("Connection complete.") : _("Connection failed.\nVerify your configuration in the Mandrake Control Center.")) ); my $tag3 = Gtk->timeout_add(10000, sub { $statusbar->pop(1); $statusbar->push(1, $isconnected ? _("Connected") : _("Not connected")); 0; }); $button_connect->set_sensitive(1); $button_close->set_sensitive(1); undef $during_connection; 0; }); Gtk->main_iteration while Gtk->events_pending; $tag2 = Gtk->timeout_add(1000, sub { system( $isconnected2 ? "/etc/sysconfig/network-scripts/net_cnx_down &" : "/etc/sysconfig/network-scripts/net_cnx_up &"); 0; }); } sub rescan { get_val(); foreach(@interfaces) { my $intf = $_; my $recv = $monitor->{$intf}{val}->[0]; my $transmit = $monitor->{$intf}{val}->[8]; my $refr = $monitor->{$intf}{referencer}; my $reft = $monitor->{$intf}{referencet}; $monitor->{sr} += $recv - $refr; $monitor->{st} += $transmit - $reft; $monitor->{$intf}{recva} += $recv - $refr; $monitor->{$intf}{recvan}++; if ($monitor->{$intf}{recvan} > 9) { push(@{$monitor->{$intf}{stack_ra}}, $monitor->{$intf}{recva}/10); $monitor->{$intf}{recva} = $monitor->{$intf}{recvan} = 0; } else { push(@{$monitor->{$intf}{stack_ra}}, -1) } shift @{$monitor->{$intf}{stack_ra}} if @{$monitor->{$intf}{stack_ra}} > 250; push(@{$monitor->{$intf}{stack_r}}, $recv - $refr); shift @{$monitor->{$intf}{stack_r}} if @{$monitor->{$intf}{stack_r}} > 250; $monitor->{$intf}{labelr}->set(formatXiB($recv - $monitor->{$intf}{initialr})); $monitor->{$intf}{referencer} = $recv; $monitor->{$intf}{transmita} += $transmit - $reft; $monitor->{$intf}{transmitan}++; if ($monitor->{$intf}{transmitan} > 9) { push(@{$monitor->{$intf}{stack_ta}}, $monitor->{$intf}{transmita}/10); $monitor->{$intf}{transmita} = $monitor->{$intf}{transmitan} = 0; } else { push(@{$monitor->{$intf}{stack_ta}}, -1) } shift @{$monitor->{$intf}{stack_ta}} if @{$monitor->{$intf}{stack_ta}} > 250; push(@{$monitor->{$intf}{stack_t}}, $transmit - $reft); shift @{$monitor->{$intf}{stack_t}} if @{$monitor->{$intf}{stack_t}} > 250; $monitor->{$intf}{labelt}->set(formatXiB($transmit - $monitor->{$intf}{initialt})); $monitor->{$intf}{referencet} = $transmit; draw_monitor($monitor->{$intf}); } $label_sr->set(formatXiB($monitor->{sr}) . "/s"); $label_st->set(formatXiB($monitor->{st}) . "/s"); $monitor->{sra} += $monitor->{sr}; $monitor->{sta} += $monitor->{st}; $monitor->{nba} ++; if($monitor->{nba} > 9) { $label_sra->set(formatXiB($monitor->{sra}/10) . "/s"); $label_sta->set(formatXiB($monitor->{sta}/10) . "/s"); $monitor->{sra} = 0; $monitor->{sta} = 0; $monitor->{nba} = 0; } $label_cnx_type->set($netcnx->{type}); $monitor->{$_} = 0 foreach ('sr', 'st'); 1; } sub get_val { my @ret; my $a = cat_("/proc/net/dev"); $a =~ s/^.*?\n.*?\n//; $a =~ s/^\s*lo:.*?\n//; my @line = split(/\n/, $a); foreach(@line) { s/\s*(\w*)://; my $intf=$1; push (@ret,$intf); $monitor->{$intf}{val} = [split()]; $monitor->{$intf}{intf} = $intf; } @ret; } sub change_color { my ($color) = @_; my $window = new Gtk::Window -toplevel; my $doit; $window->signal_connect ( delete_event => sub { Gtk->main_quit() }); $window->set_position(1); $window->set_title(_("Color configuration")); $window->set_border_width(5); gtkadd(gtkset_modal($window,1), gtkpack_(new Gtk::VBox(0,5), 1, my $colorsel = new Gtk::ColorSelection, 0, gtkadd(gtkset_layout(new Gtk::HButtonBox, -end), gtksignal_connect(new Gtk::Button(_("OK")), clicked => sub { $doit=1; Gtk->main_quit() }), gtksignal_connect(new Gtk::Button(_("Cancel")), clicked => sub { Gtk->main_quit() }), ) ) ); $colorsel->set_color($color->red()/65535, $color->green()/65535, $color->blue()/65535, $color->pixel()); $window->show_all(); Gtk->main; $window->destroy(); $doit or return $color; my (@color) = $colorsel->get_color(); my_gtk::gtkcolor($color[0]*65535, $color[1]*65535, $color[2]*65535); } my $scale; sub update { connected_bg(\$isconnected); my @intfs = get_val(); if($combo1->entry->get_text ne ($netcnx->{PROFILE} ? $netcnx->{PROFILE} : "default")) { $combo1->entry->set_text($netcnx->{PROFILE} ? $netcnx->{PROFILE} : "default"); } foreach(@intfs) { my $intf = $_; if(!member($intf,@interfaces)) { $default_intf = $intf; $monitor->{$intf}{initialr} = $monitor->{$intf}{val}->[0]; $monitor->{$intf}{initialt} = $monitor->{$intf}{val}->[8]; $monitor->{$intf}{darea} = new Gtk::DrawingArea(); $monitor->{$intf}{darea}->set_events(["pointer_motion_mask"]); $notebook->append_page(gtkshow(my $page = gtkpack_(new Gtk::VBox(0,0), 0, gtkpack__(gtkset_border_width(new Gtk::HBox(0,0), 5), gtksize($monitor->{$intf}{darea},300, 150)), 0, gtkpack_(new Gtk::HBox(0,0), 1, gtkpack__(new Gtk::VBox(0,0), gtkpack__(gtkset_border_width(new Gtk::HBox(0,5), 5), gtksignal_connect(my $button_t = gtkset_relief(new Gtk::Button(), 'none'), clicked => sub { $colort = change_color($colort); $gct->set_foreground($colort); $_[0]->draw(undef); }), _("sent: "), $monitor->{$intf}{labelt} = new Gtk::Label("0")), gtkpack__(gtkset_border_width(new Gtk::HBox(0,5), 5), gtksignal_connect(my $button_r = gtkset_relief(new Gtk::Button(), 'none'), clicked => sub { $colorr = change_color($colorr); $gcr->set_foreground($colorr); $_[0]->draw(undef); }), _("received: "), $monitor->{$intf}{labelr} = new Gtk::Label("0")), gtkpack__(gtkset_border_width(new Gtk::HBox(0,5), 5), gtksignal_connect(my $button_a = gtkset_relief(new Gtk::Button(), 'none'), clicked => sub { $colora = change_color($colora); $gca->set_foreground($colora); $_[0]->draw(undef); }), _("average")) ), 0, gtkpack__(gtkset_border_width(new Gtk::VBox(0,0), 5), gtkadd(gtkset_shadow_type(new Gtk::Frame(_("Local measure")), 'etched_out'), gtkpack__(gtkset_border_width(new Gtk::VBox(0,0), 5), gtkpack__(new Gtk::HBox(0,0), _('sent: '), my $measure_t = new Gtk::Label("0") ), gtkpack__(new Gtk::HBox(0,0), _('received: '), my $measure_r = new Gtk::Label("0") ) ) ) ) ) )), new Gtk::Label($intf)); foreach my $i ([$button_t, $gct],[$button_r, $gcr],[$button_a, $gca]) { $i->[0]->add(gtksignal_connect(gtkshow(gtksize(gtkset_usize(new Gtk::DrawingArea(), 10, 10), 10, 10)), expose_event => sub{ $_[0]->window->draw_rectangle ($i->[1], 1, 0, 0, 10, 10)} )); } $notebook->set_page($notebook->page_num($page)); $monitor->{$intf}{page}=($notebook->page_num($page)); $monitor->{$intf}{pixmap_db} = new Gtk::Gdk::Pixmap($monitor->{$intf}{darea}->window, 300, 150); $monitor->{$intf}{referencer} = $monitor->{$intf}{val}->[0]; $monitor->{$intf}{referencet} = $monitor->{$intf}{val}->[8]; $monitor->{$intf}{pixmap_db}->draw_rectangle ($monitor->{$intf}{darea}->style->black_gc, 1, 0, 0, 300, 150); $monitor->{$intf}{darea}->signal_connect( motion_notify_event => sub { my ($w, $e) = @_; my $x = $e->{'x'} - 50; my $y = $e->{'y'}; my $received = $x >= 0 ? $monitor->{$intf}{stack_r}[$x] : 0; my $transmitted = $x >= 0 ? $monitor->{$intf}{stack_t}[$x] : 0; my $type; $y * $scale / 150 < $transmitted and $type = _('transmitted'); (150 - $y) * $scale / 150 < $received and $type = _('received'); $measure_r->set(formatXiB($received)); $measure_t->set(formatXiB($transmitted)); }); $monitor->{$intf}{darea}->signal_connect( expose_event => sub { $monitor->{$intf}{darea}->window->draw_pixmap ($monitor->{$intf}{darea}->style->bg_gc('normal'), $monitor->{$intf}{pixmap_db}, 0, 0, 0, 0, 300, 150); }); } } foreach(@interfaces) { my $intf = $_; if(!member($intf,@intfs)) { $notebook->remove_page($monitor->{$intf}{page}); } } @interfaces = @intfs; my $netc={}; if ($isconnected != -1 && !$during_connection) { $button_connect->set_sensitive(1); $label_c->set($isconnected ? _("Disconnect") : _("Connect")); $statusbar->pop(1); $statusbar->push(1, $isconnected ? _("Connected") : _("Not connected")); $isconnected ? $pix_c->set($pix_c_map, $pix_c_mask) : $pix_c->set($pix_d_map, $pix_d_mask); } if (!(-e $connect_file && -e $disconnect_file)) { $button_connect->set_sensitive(0); $label_c->set("No internet connection configured"); } 1; } sub draw_monitor { my ($o) = @_; defined $o->{darea} or return; $o->{pixmap_db}->draw_rectangle ($o->{darea}->style->black_gc, 1, 0, 0, 300, 150); my $maxr = 0; foreach (@{$o->{stack_r}}) { $maxr = $_ if $_>$maxr } my $maxt = 0; foreach (@{$o->{stack_t}}) { $maxt = $_ if $_>$maxt } my $ech = $maxr + $maxt; $ech == 0 and $ech = 1; $scale = $ech; my $step=49; foreach (@{$o->{stack_t}}) { $o->{pixmap_db}->draw_rectangle($gct, 1, $step, 0, 1, $_*150/$ech); $step++; } $step=49; my ($av1, $av2, $last_a); foreach (@{$o->{stack_ta}}) { if($_ != -1) { if( !defined $av1) { $av1 = $_ } else { defined $av2 or $av2 = $_ } if ($av1 && $av2) { $o->{pixmap_db}->draw_line($gca, $step-15, $av1*150/$ech, $step-5, $av2*150/$ech); $av1 = $av2; undef $av2; $last_a = $step-50; } } $step++; } $step=49; foreach (@{$o->{stack_r}}) { $o->{pixmap_db}->draw_rectangle($gcr, 1, $step, 151-$_*150/$ech, 1, $_*150/$ech); $step++; } $step=49; ($av1, $av2) = undef; foreach (@{$o->{stack_ra}}) { if($_ != -1) { if(!defined $av1) { $av1 = $_ } else { defined $av2 or $av2 = $_ } if ((defined $av1) && (defined $av2)) { $o->{pixmap_db}->draw_line($gca, $step-15, 151-$av1*150/$ech, $step-5, 151-$av2*150/$ech); $av1 = $av2; undef $av2; } } $step++; } my $switch = 1; my $gcl = new Gtk::Gdk::GC($o->{darea}->window); $gcl->set_foreground($o->{darea}->window->get_colormap->color_white()); $gcl->set_line_attributes (1, 'on-off-dash', 'not-last', 'round'); for (my $i = 30;$i<=120;$i+=30) { $o->{pixmap_db}->draw_line($gcl, 50, $i, 300, $i); my ($gc2, $text); my ($dif1, $dif2); if ($last_a) { $dif1 = abs(150-@{$o->{stack_ra}}[$last_a]*150/$ech - $i); $dif2 = abs(@{$o->{stack_ta}}[$last_a]*150/$ech - $i); } else { $dif1 = abs(150-@{$o->{stack_r}}[@{$o->{stack_r}}-1]*150/$ech - $i); $dif2 = abs(@{$o->{stack_t}}[@{$o->{stack_t}}-1]*150/$ech - $i); } if ($dif1 < $dif2) { $text = formatXiB((150-$i)*$ech/150); $gc2=$gcr; my $x_l=5; if ($i > 30 && $switch) { $o->{pixmap_db}->draw_line($gct, $x_l, 0, $x_l, $i-30); $o->{pixmap_db}->draw_line($gct, $x_l-1, 0, $x_l-1, $i-30); $o->{pixmap_db}->draw_line($gct, $x_l+1, 0, $x_l+1, $i-30); $o->{pixmap_db}->draw_polygon($gct, 1, $x_l-4, $i-30, $x_l+5, $i-30, $x_l, $i-25); } if ($switch) { $o->{pixmap_db}->draw_line($gcr, $x_l, 150, $x_l, $i); $o->{pixmap_db}->draw_line($gcr, $x_l-1, 150, $x_l-1, $i); $o->{pixmap_db}->draw_line($gcr, $x_l+1, 150, $x_l+1, $i); $o->{pixmap_db}->draw_polygon($gcr, 1, $x_l-5, $i, $x_l+5, $i, $x_l, $i-6); } undef $switch; } else { $text = formatXiB($i*$ech/150); $gc2=$gct; } my $w = $style->font->string_width($text); $o->{pixmap_db}->draw_string($style->font, $gc2, 45-$w, $i+5, ($text) ); } $o->{darea}->draw(undef); }