#! /usr/bin/perl # $Id$ # Copyright (C) 2001 MandrakeSoft # Yves Duret # some code is Copyright: (C) 1999, Michael T. Babcock # # 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 lib qw(/usr/lib/libDrakX); use interactive; use standalone; use any; use my_gtk qw(:helpers :wrappers); # for i18n use POSIX; use Locale::GetText; setlocale (LC_ALL, ""); Locale::GetText::textdomain ("DrakConf"); import Locale::GetText I_; use MDK::Common; use Gtk; use Config; init Gtk; $::isInstall and die "Not supported during install.\n"; $::isEmbedded = ($::XID, $::CCPID) = "@ARGV" =~ /--embedded (\w+) (\w+)/; if ($::isEmbedded) { print "EMBED\n"; print "parent XID\t$::XID\n"; print "mcc pid\t$::CCPID\n"; } my $in = vnew interactive('su'); local $_ = join '', @ARGV; /-h/ and die sprintf( _("usage: logdrake [--version]\n")); /-version/ and die 'version: $Id$ '."\n"; my $h=`hostname -s`; chop($h); my $window = $::isEmbedded ? new Gtk::Plug ($::XID) : new Gtk::Window -toplevel; $window->signal_connect( delete_event => sub { $::isEmbedded ? kill(USR1, $::CCPID) : Gtk->exit(0) }); $window->set_title( _("logdrake") ); $window->set_policy(1, 1, 1); $window->border_width (5); ### menus definition # the menus are not shown # but they provides shiny shortcut like C-q my @menu_items = ( { path => _("/_File"), type => '' }, { path => _("/File/_New"), accelerator => _("N"), callback => \&print_hello }, { path => _("/File/_Open"), accelerator => _("O"), callback => \&print_hello }, { path => _("/File/_Save"), accelerator => _("S"), callback => \&print_hello }, { path => _("/File/Save _As") }, { path => _("/File/-"), type => '' }, { path => _("/File/_Quit"), accelerator => _("Q"), callback => sub { $::isEmbedded ? kill(USR1, $::CCPID) : Gtk->exit(0) } }, { path => _("/_Options"), type => '' }, { path => _("/Options/Test") }, { path => _("/_Help"), type => '' }, { path => _("/Help/_About...") } ); my $menubar = get_main_menu( $window ); ######### menus end ########## font and colors my $n = Gtk::Gdk::Font->fontset_load(_("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-*-*,*")); my $b = Gtk::Gdk::Font->fontset_load(_("-misc-fixed-bold-r-*-*-*-100-*-*-*-*-*-*,*")); my $white = my_gtk::gtkcolor(50400, 655, 20000); my $black = my_gtk::gtkcolor(0, 0, 0); my $red = my_gtk::gtkcolor(0xFFFF, 655, 655); my $green = my_gtk::gtkcolor(0x0, 0x9898,0x0); my $yellow = my_gtk::gtkcolor(0xFFFF, 0xD7D7, 0); my $blue = my_gtk::gtkcolor(655, 655, 0xFFFF); my $magenta = my_gtk::gtkcolor(0xFFFF, 655, 0xFFFF); my $purple = my_gtk::gtkcolor(0xA0A0, 0x2020, 0xF0F0); my $cyan = my_gtk::gtkcolor(0x0, 0x9898, 0x9898); my $darkgray = my_gtk::gtkcolor(0x2F2F, 0x4F4F, 0x4F4F); # Define global terms: # Define good notables: my @word_good=("starting\n", "Freeing", "Detected", "starting.", "accepted.\n", "authenticated.\n", "Ready", "active", "reloading", "saved;", "restarting", "ONLINE\n"); my @word_warn=("dangling", "closed.\n", "Assuming", "root", "root\n", "exiting\n", "missing", "Ignored", "adminalert:", "deleting", "OFFLINE\n"); my @word_bad=("bad"); my @word_note=("LOGIN", "DHCP_OFFER", "optimized", "reset:", "unloaded", "disconnected", "connect", "Successful", "registered\n"); my @line_good=("up", "DHCP_ACK", "Cleaned", "Initializing", "Starting", "success", "successfully", "alive", "found", "ONLINE\n"); my @line_warn=("warning:", "WARNING:", "invalid", "obsolete", "bad", "Password", "detected", "timeout", "timeout:", "attackalert:", "wrong", "Lame", "FAILED", "failing", "unknown", "obsolete", "stopped.\n", "terminating.", "disabled\n", "disabled", "Lost"); my @line_bad=("DENY", "lost", "shutting", "dead", "DHCP_NAK", "failure;", "Unable", "inactive", "terminating", "refused", "rejected", "down", "OFFLINE\n", "error\n", "ERROR\n", "ERROR:", "error", "ERROR", "error:", "failed:"); # Define specifics: my @daemons=("named"); # Now define what we want to use when: my $col_good = $green; my $col_warn = $yellow; my $col_bad = $red; my $col_note = $purple; my $col=$cyan; ######### font and colors end my %files = ( "auth" => { file => "/var/log/auth.log", desc => _("authentification") }, "user" => { file => "/var/log/user.log", desc => _("user") }, "auth" => { file => "/var/log/auth.log", desc => _("authentification") }, "syslog" => { file => "/var/log/syslog", desc => _("syslog") } ); # Create root tree my $tree = new Gtk::Tree(); my $leaf; my $root_dir; $tree->set_selection_mode('single'); $tree->set_view_mode('item'); fill_tree (""); # 1, gtkadd(new Gtk::Frame(_("Choose a file")), # gtkpack_(new Gtk::VBox(0,5), # 1, createScrolledWindow($tree), # 0, gtkpack(new Gtk::HBox(0,5), # gtksignal_connect(new Gtk::Button("syslog"), clicked => \&select_item, "/var/log/syslog"), # gtksignal_connect(new Gtk::Button("dmesg"), clicked => \&select_item, "/var/log/dmesg"), # gtksignal_connect(new Gtk::Button("user.log"), clicked => \&select_item, "/var/log/user.log") # ) # ) # ), #### far from window gtkadd($window, gtkpack_(new Gtk::VBox(0,5), 0, _("see your log"), 1, gtkadd(new Gtk::Frame(_("toi aussi choisi")), gtkpack__(new Gtk::VBox(0,5), gtkpack__(new Gtk::HBox(0,5), _("matching"), $e_yes = new Gtk::Entry(), _("not matching"), $e_no = new Gtk::Entry() ), _("tips: you can use OR"), gtkpack (new Gtk::VBox(0,5), map { ${"b_". $_} = new Gtk::CheckButton($files{$_}{desc}) } keys %files, ), gtksignal_connect(new Gtk::Button(_("search")), clicked => \&search) ) ), 1, gtkadd(new Gtk::Frame(_("Content of the file")), createScrolledWindow(my $log = new Gtk::Text(undef, undef)) ) ) ); $window->realize; $window->show_all(); Gtk->main_iteration while Gtk->events_pending; $::isEmbedded and kill USR2, $::CCPID; Gtk->main; #------------------------------------------------------------- # search functions #------------------------------------------------------------- sub search { $log->backward_delete($log->get_length()); $log->freeze(); foreach (keys %files) { parse_file($files{$_}{file}) if ${$::{"b_". $_}}->active }; $log->thaw(); } sub parse_file { my $file = $_[0]; $file =~ s/\.gz$//; my @all=catMaybeCompressed ($file); my $taille= @all +1; my $i=1; gtkadd(my $win_pb = new Gtk::Window(), gtkpack(new Gtk::VBox(5,0), _("please wait, parsing file: "). $files{$_}{desc}, my $pbar = new Gtk::ProgressBar() ) ); $win_pb->realize(); $win_pb->show_all(); my $ey= $e_yes->get_chars( 0, -1 ); my $en= $e_no->get_chars( 0, -1 ); $ey =~ s/ OR /\|/; foreach (@all) { if ($i % 10) { $pbar->update($i/$taille); Gtk->main_iteration while Gtk->events_pending; } if (($en eq "") and ($ey eq "")) { logcolorize($_) } else { if (/$ey/i and ($en eq "")) { logcolorize($_); } else { logcolorize($_) if (/$ey/i and (not /$en/i)); } } $i++; } $win_pb->destroy(); } #------------------------------------------------------------- # tree functions #------------------------------------------------------------- ### Subroutines sub fill_tree { my $root_dir = "/var/log/" . $_[0]; # Create root tree item widget $leaf = new_with_label Gtk::TreeItem( $root_dir ); $tree->append( $leaf ); $leaf->signal_connect( 'select', \&select_item, $root_dir ); $leaf->set_user_data( $root_dir ); # Create the subtree if (-d $root_dir) { my $subtree = new Gtk::Tree(); $leaf->set_subtree( $subtree ); $leaf->signal_connect( 'expand', \&expand_tree, $subtree ); $leaf->signal_connect( 'collapse', \&collapse_tree ); $leaf->expand(); } } sub change_tree { $leaf->destroy(); fill_tree (@_); $leaf->show(); } # Callback for expanding a tree - find subdirectories, files and add them to tree sub expand_tree { my ($item, $subtree) = @_; my ($dir_entry, $path, $item_new, $new_subtree); my $dir = $item->get_user_data(); chdir($dir); foreach $dir_entry ( <*> ) { $path = $dir . "/" . $dir_entry; $path =~ s|//|/|g; $item_new = new_with_label Gtk::TreeItem( $dir_entry ); $item_new->set_user_data($path); $item_new->signal_connect('select', \&select_item, $path ); $subtree->append($item_new); $item_new->show(); if (-d $path) { $new_subtree = new Gtk::Tree(); $item_new->set_subtree( $new_subtree ); $item_new->signal_connect('expand', \&expand_tree, $new_subtree); $item_new->signal_connect('collapse', \&collapse_tree); } } chdir( ".." ); } # Callback for collapsing a tree -- removes the subtree sub collapse_tree { my ($item) = @_; my $subtree = new Gtk::Tree(); $item->remove_subtree(); $item->set_subtree( $subtree ); $item->signal_connect( 'expand', \&expand_tree, $subtree ); } # Called whenever an item is clicked on the tree widget. sub select_item { my ($widget, $file) = @_; return if (-d $file); $log->backward_delete($log->get_length()); $log->freeze(); parse_file($file); $log->thaw(); } sub log_output { $log->insert($_[2],$_[0], undef,$_[1]); } ########################################################################################## sub logcolorize { # we get date & time if it is date & time (dmesg) s/(\D{3} .. \d\d:\d\d:\d\d )//; $timestamp=$1; @rec = split; log_output($cyan,$timestamp,$b); # date & time if any... log_output(($rec[0] eq $h) ? $blue : $col,"$rec[0] ",$b); # hostname if ($rec[1] eq "last") { log_output($green," last message repeated ",$n); log_output($green, $rec[4], $b); log_output($green," times\n",$n); return; } # Extract PID if present if ($rec[1] =~ /\[(\d+)\]\:/) { my($pid) = $1; $rec[1]=~s/\[$1\]\:// ; log_output ($green, $rec[1] ."[",$n); log_output ($black, $pid,$b); log_output ($green, "]: ",$n); } else { log_output($green, $rec[1] ." ",$n); } for ($therest=(2); $therest<=$#rec; $therest++) { $col=$cyan; # Check for keywords to highlight foreach (@word_good) { $col=$col_good if ($_ eq $rec[$therest]);} foreach (@word_warn) { $col=$col_warn if ($_ eq $rec[$therest]);} foreach (@word_bad) { $col=$col_bad if ($_ eq $rec[$therest]);} foreach (@word_note) { $col=$col_note if ($_ eq $rec[$therest]);} # Watch for words that indicate entire lines should be highlighted #foreach (@line_good) { $col=$col_good if ($_ eq $rec[$therest]);} #foreach (@line_warn) { $col=$col_warn if ($_ eq $rec[$therest]);} #foreach (@line_bad) { $col=$col_bad if ($_ eq $rec[$therest]);} log_output($col,"$rec[$therest] ",$n); } log_output($black,"\n",$n); } #------------------------------------------------------------- # menu callback functions #------------------------------------------------------------- sub print_hello { print( "mcdtg !\n" ); } sub get_main_menu { my ($window) = @_; my $accel_group = new Gtk::AccelGroup(); my $item_factory = new Gtk::ItemFactory( 'Gtk::MenuBar', '
', $accel_group ); $item_factory->create_items( @menu_items ); $window->add_accel_group( $accel_group ); return ( $item_factory->get_widget( '
' ) ); } sub create_dialog { my ($label, $c) = @_; my $ret = 0; my $dialog = new Gtk::Dialog; $dialog->signal_connect ( delete_event => sub {Gtk->main_quit();}); $dialog->set_title(_("logdrake")); $dialog->border_width(10); $dialog->vbox->pack_start(new Gtk::Label($label),1,1,0); my $button = new Gtk::Button _("OK"); $button->can_default(1); $button->signal_connect(clicked => sub { $ret=1; $dialog->destroy(); Gtk->main_quit(); }); $dialog->action_area->pack_start($button, 1, 1, 0); $button->grab_default; if ($c) { my $button2 = new Gtk::Button _("Cancel"); $button2->signal_connect(clicked => sub { $ret=0; $dialog->destroy(); Gtk->main_quit(); }); $button2->can_default(1); $dialog->action_area->pack_start($button2, 1, 1, 0); } $dialog->show_all; Gtk->main(); $ret; } sub destroy_window { my($widget, $windowref, $w2) = @_; $$windowref = undef; $w2 = undef if defined $w2; 0; } # log # $Log$ # Revision 1.12 2001/08/02 08:28:18 pablo # update pot file, s/ :/:/ for English text # # Revision 1.11 2001/08/01 19:06:05 yduret # pour boblack # # Revision 1.10 2001/08/01 17:30:21 yduret # added mapping.. # # Revision 1.9 2001/08/01 13:19:14 yduret # ask_many_from_list # # Revision 1.8 2001/07/19 13:24:54 pablo # updated Croatian file # # Revision 1.7 2001/07/16 16:48:21 yduret # update # # Revision 1.6 2001/07/03 19:40:48 pablo # updated Danish file, # i18n'd logdrake # # Revision 1.5 2001/07/03 08:54:43 yduret # powered by DrakX technologie # # Revision 1.4 2001/07/02 09:47:55 yduret # fix bug in regexp # # Revision 1.3 2001/06/29 16:14:01 yduret # great upgrade # # Revision 1.2 2001/06/28 10:50:27 yduret # full support of color # # Revision 1.1 2001/06/27 09:22:59 yduret # added it.. #