diff options
Diffstat (limited to 'perl-install/standalone/logdrake')
| -rwxr-xr-x | perl-install/standalone/logdrake | 584 | 
1 files changed, 314 insertions, 270 deletions
diff --git a/perl-install/standalone/logdrake b/perl-install/standalone/logdrake index 448d4c978..562d91144 100755 --- a/perl-install/standalone/logdrake +++ b/perl-install/standalone/logdrake @@ -1,8 +1,7 @@  #! /usr/bin/perl -# $Id$ -# Copyright (C) 2001-2002 MandrakeSoft -# Yves Duret <yduret at mandrakesoft.com> +# Copyright (C) 2001-2008 Mandriva +# Yves Duret <yduret at mandriva.com>  # some code is Copyright: (C) 1999, Michael T. Babcock <mikebabcock@pobox.com>  #  # This program is free software; you can redistribute it and/or modify @@ -24,106 +23,86 @@  use strict;  use lib qw(/usr/lib/libDrakX);  use standalone;     #- warning, standalone must be loaded very first, for 'explanations' +use c;  use common;  use interactive; -use ugtk2 qw(:wrappers :helpers :create); +use do_pkgs; +use mygtk3 qw(gtknew); #- do not import gtkadd which conflicts with ugtk3 version +use ugtk3 qw(:create :dialogs :helpers :wrappers); -$::isInstall and die "Not supported during install.\n"; +$ugtk3::wm_icon = "/usr/share/mcc/themes/default/logdrake-mdk.png"; +my $in = 'interactive'->vnew('su'); -my $in = 'interactive'->vnew('su', 'default'); -my $cron_hourly = "/etc/cron.hourly/logdrake_service"; +my ($isExplain, $Explain, $isFile, $File, $isWord, $Word);  #- parse arguments list.  foreach (@ARGV) { -    /^--explain=(.*)$/ and do { $::isExplain = ($::Explain) = $1; $::isFile = 1; $::File = "/var/log/explanations"; next }; -    /^--file=(.*)$/ and do { $::isFile = ($::File) = $1; next }; -    /^--word=(.*)$/ and do { $::isWord = ($::Word) = $1; next }; +    /^--explain=(.*)$/ and do { $isExplain = ($Explain) = $1; $isFile = 1; $File = "/var/log/explanations"; next }; +    /^--file=(.*)$/ and do { $isFile = ($File) = $1; next }; +    /^--word=(.*)$/ and do { $isWord = ($Word) = $1; next };      /^--alert$/ and do { alert_config(); quit() };  } -$::isTail = 1 if $::isFile; -$| = 1 if $::isTail; +if (!$::testing) { +   do_pkgs_standalone->new($in)->ensure_is_installed("syslog-daemon", "/etc/systemd/system/syslog.service") or exit(0); +} + +my $isTail = $isFile; +$| = 1 if $isTail;  my $h = chomp_(`hostname -s`); -my $my_win = ugtk2->new('logdrake'); +$ugtk3::wm_icon = "logdrake"; +my $explain_title = N("%s Tools Logs", N("Mageia")); +my $my_win = ugtk3->new($isExplain ? $explain_title : N("Logs")); +  unless ($::isEmbedded) { -    $my_win->{rwindow}->set_title(N("logdrake"));      $my_win->{window}->set_border_width(5); -    #$my_win->{rwindow}->set_policy(1, 1, 1);      #$my_win->{window}->set_default_size(540,460);  }  $my_win->{window}->signal_connect(delete_event => \&quit); -my $cal = gtkset_sensitive(new Gtk2::Calendar(), 0); +my $cal = gtkset_sensitive(Gtk3::Calendar->new, 0);  my $mday = (localtime(time()))[3];  $cal->select_day($mday);  my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);  my $cal_mode = 0; -my $cal_butt = gtksignal_connect(new Gtk2::CheckButton(N("Show only for the selected day")), clicked => sub { $cal_mode = !$cal_mode; gtkset_sensitive($cal,$cal_mode) }); +my $cal_butt = gtksignal_connect(Gtk3::CheckButton->new(N("Show only for the selected day")), clicked => sub { $cal_mode = !$cal_mode; gtkset_sensitive($cal,$cal_mode) });  ### menus definition  # the menus are not shown -# but they provides shiny shortcut like C-q -my @menu_items = ( -		  { path => N("/_File"), type => '<Branch>' }, -		  { path => N("/File/_New"), accelerator => N("<control>N") }, -		  { path => N("/File/_Open"), accelerator => N("<control>O") }, -		  { path => N("/File/_Save"), accelerator => N("<control>S"), callback => \&save }, -		  { path => N("/File/Save _As") }, -		  { path => N("/File/-"),type => '<Separator>' }, -		  { path => N("/File/_Quit"), accelerator => N("<control>Q"), callback => \&quit }, -		  { path => N("/_Options"), type => '<Branch>' }, -		  { path => N("/Options/Test") }, -		  { path => N("/_Help"),type => '<LastBranch>' }, -		  { path => N("/Help/_About...") }  -		 ); -my $menubar = create_factory_menu($my_win->{rwindow}, @menu_items) unless $::isEmbedded; +# but they provides shiny shortcut like C-q (Broken: FIXME) +if ($::isEmbedded) { +	my $ui = gtknew('UIManager', actions => [ +                   # [name, stock_id, value, label, accelerator, tooltip, callback] +                   [ 'FileMenu',        undef, N("_File") ], +                   [ 'Save', undef, N("_Quit"), N("<control>S"), undef, \&save ], +                   [ 'Quit', undef, N("_Quit"), N("<control>Q"), undef, \&quit ], +               ], +               string => qq(<ui> +  <menubar name='MenuBar'> +    <menu action='FileMenu'> +      <menuitem action='Save'/> +      <menuitem action='Quit'/> +    </menu> +  </menubar> +</ui>)); +	$my_win->{rwindow}->add_accel_group($ui->get_accel_group); +}  ######### menus end  ########## font and colors -my %n = ('font' => ''); # Gtk2::Pango::FontDescription->from_string('Serif 12');#Gtk2::Gdk::Font->fontset_load(N("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-*-*,*")); -my %b = ('font' => 'Bold'); #Gtk2::Pango::FontDescription->from_string('Serif Bold 12');#Gtk2::Gdk::Font->fontset_load(N("-misc-fixed-bold-r-*-*-*-100-*-*-*-*-*-*,*")); - -#$black    = "\033[30m"; -#$red      = "\033[31m"; -#$green    = "\033[32m"; -#$yellow   = "\033[33m"; -#$blue     = "\033[34m"; -#$magenta  = "\033[35m"; -#$purple   = "\033[35m"; -#$cyan     = "\033[36m"; -#$white    = "\033[37m"; -#$darkgray = "\033[30m"; -#$col_norm =             "\033[00m"; -#$col_background =       "\033[07m"; -#$col_brighten =         "\033[01m"; -#$col_underline =        "\033[04m"; -#$col_blink =            "\033[05m"; - -my $white    = gtkcolor(50400, 655, 20000); -my $black    = gtkcolor(0, 0, 0); -my $red      = gtkcolor(0xFFFF, 655, 655); -my $green    = gtkcolor(0x0, 0x9898,0x0); -my $yellow   = gtkcolor(0xFFFF, 0xD7D7, 0); -my $blue     = gtkcolor(655, 655, 0xFFFF); -my $magenta  = gtkcolor(0xFFFF, 655, 0xFFFF); -my $purple   = gtkcolor(0xA0A0, 0x2020, 0xF0F0); -my $cyan     = gtkcolor(0x0, 0x9898, 0x9898); -my $darkgray = 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_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"); +#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:");  # Now define what we want to use when:  my $col_good = 'green4'; @@ -135,143 +114,149 @@ my $col = 'darkcyan';  ######### font and colors end  my %files = ( -	     "auth" => { file => "/var/log/auth.log", desc => N("Authentication") }, -	     "user" => { file => "/var/log/user.log", desc => N("User") }, -	     "messages" => { file => "/var/log/messages", desc => N("Messages") }, -	     "syslog" => { file => "/var/log/syslog", desc => N("Syslog") }, -	     "explanations" => { file => "/var/log/explanations", desc => N("Mandrake Tools Explanation") } +	     "auth" => { file => "/var/log/auth.log", desc => N("_:this is the auth.log log file\nAuthentication") }, +	     "user" => { file => "/var/log/user.log", desc => N("_:this is the user.log log file\nUser") }, +	     "messages" => { file => "/var/log/messages", desc => N("_:this is the /var/log/messages log file\nMessages") }, +	     "syslog" => { file => "/var/log/syslog", desc => N("_:this is the /var/log/syslog log file\nSyslog") }, +	     "explanations" => { file => "/var/log/explanations", desc => $explain_title }  ); -my $yy = gtkset_sensitive(gtksignal_connect(new Gtk2::Button(N("search")) , clicked => \&search),0); -my $log_text = new Gtk2::TextView; -$log_text->set_property('editable', 0); +my $yy = gtkset_sensitive(gtksignal_connect(Gtk3::Button->new(N("search")) , clicked => \&search),0); + +my $log_text = gtktext_insert(Gtk3::TextView->new, [ [ '' ] ]); -my $log_buf = $log_text->get_buffer(); +my $log_buf = $log_text->get_buffer;  my $refcount_search;  #### far from window  my %toggle;  gtkadd($my_win->{window}, -       gtkpack_(new Gtk2::VBox(0,0), -		if_(!$::isExplain && !$::isEmbedded, 0, N("A tool to monitor your logs")), -		if_(!$::isFile, 0, gtkadd(new Gtk2::Frame(N("Settings")), -					  gtkpack__(new Gtk2::VBox(0,2), -						    gtkpack__(new Gtk2::VBox(0,2), +       gtkpack_(Gtk3::VBox->new(0,0), +		if_(!$::isEmbedded, 0, gtknew('Title1', label => N("A tool to monitor your logs"))), +		if_(!$isFile, 0, gtkpack__(Gtk3::VBox->new(0,2), +                                     gtknew('Title2', label => N("Settings")),  							      # N("Show lines"), -							      gtkpack__(new Gtk2::HBox(0,0), -									" " . N("matching") . " ", my $e_yes = new Gtk2::Entry(), -									" " . N("but not matching") . " ", my $e_no = new Gtk2::Entry() -									) -							      ), -						    gtkpack_(new Gtk2::HBox(0,0), -							     1, gtkadd(gtkset_border_width(new Gtk2::Frame(N("Choose file")),2), -								       gtkpack(gtkset_border_width(Gtk2::VBox->new(0,0),0), -										map { $toggle{$_} = gtksignal_connect(new Gtk2::CheckButton($files{$_}{desc}),  +							      gtkpack__(Gtk3::HBox->new(0,0), +									" " . N("Matching") . " ", my $e_yes = Gtk3::Entry->new, +									" " . N("but not matching") . " ", my $e_no = Gtk3::Entry->new +									), +						    gtkpack_(Gtk3::HBox->new(0,0), +							     1, gtkadd(gtkset_border_width(Gtk3::Frame->new(N("Choose file")),2), +								       gtkpack(gtkset_border_width(Gtk3::VBox->new(0,0),0), +										map { $toggle{$_} = gtksignal_connect(Gtk3::CheckButton->new($files{$_}{desc}),   														      clicked => sub {  															  $refcount_search++;  -															  gtkset_sensitive($yy,$refcount_search); -														      }) } keys %files, +															  gtkset_sensitive($yy, $refcount_search); +                                                                         }); +                                                        $toggle{$_}->set_sensitive(0) if !-f $files{$_}{file}; +                                                        $toggle{$_}; +                                                    } sort keys %files,  										)  								       ), -							     0, gtkadd(gtkset_border_width(new Gtk2::Frame(N("Calendar")),2), -								       gtkpack__(gtkset_border_width(new Gtk2::VBox(0,0),5), +							     0, gtkadd(gtkset_border_width(Gtk3::Frame->new(N("Calendar")),2), +								       gtkpack__(gtkset_border_width(Gtk3::VBox->new(0,0),5),  										 $cal_butt, $cal  										 )  								       )  							     ),  						    $yy,  						    ) -					  )  		    ), -		!$::isExplain ? (1, gtkadd(new Gtk2::Frame(N("Content of the file")), -					   create_scrolled_window($log_text) -					   )) : (1, create_scrolled_window($log_text)), -		if_(!$::isExplain, 0, gtkadd(gtkset_border_width(gtkset_layout(Gtk2::HButtonBox->new, 'end'), 5), -					      if_(!$::isFile, gtksignal_connect(new Gtk2::Button(N("Mail alert")),  -										clicked => sub { eval { alert_config() };   -												 if ($@ =~ /wizcancel/) { -												     $::Wizard_no_previous = 1; -												     $::Wizard_no_cancel = 1; -												     $::WizardWindow->destroy if defined $::WizardWindow; -												     undef $::WizardWindow; -												 } })), -					      gtksignal_connect(new Gtk2::Button(N("Save")), clicked => \&save), -					      gtksignal_connect(new Gtk2::Button($::isEmbedded ? N("Cancel") : N("Quit")), clicked => \&quit) +		!$isExplain ? (0, gtknew('Title2', label => N("Content of the file")), +					   1, create_scrolled_window($log_text) +					   ) : (1, create_scrolled_window($log_text)), +		0, gtkadd(gtkset_border_width(gtkset_layout(Gtk3::HButtonBox->new, 'end'), 5), +					      if_(!$isFile, gtksignal_connect(Gtk3::Button->new(N("Mail alert")),  +										clicked => sub {  +                                                      eval { alert_config() }; +                                                      my $err = $@; +                                                      $::WizardWindow->destroy if defined $::WizardWindow; +                                                      undef $::WizardWindow; +                                                      if ($err && $err !~ /wizcancel/) { +                                                          err_dialog(N("Error"), N("The alert wizard has failed unexpectedly:") +                                                                     . "\n\n" . $err); +                                                      } +                                                  })), +					      gtksignal_connect(Gtk3::Button->new(N("Save")), clicked => \&save), +					      gtksignal_connect(Gtk3::Button->new($::isEmbedded ? N("Cancel") : N("Quit")), clicked => \&quit)  					      ) -		    )  		)         ); -$::isFile and gtkset_size_request($log_text, 400, 500); +$isFile && !$::isEmbedded and gtkset_size_request($log_text, 400, 500); -$my_win->{window}->realize; -$my_win->{window}->show_all(); -search() if $::isFile; -kill 'USR2', $::CCPID if $::isEmbedded; # special case because logdrake is also embedded for logs +$my_win->{window}->show_all; +search() if $isFile;  $my_win->main; -sub quit { ugtk2->exit(0) } +sub quit() { ugtk3->exit(0) }  #-------------------------------------------------------------  # search functions  #------------------------------------------------------------- -sub search { -#    gtk_text_buffer_delete(); -#BUG    $log_text->backward_delete($log_text->get_length()); #BUG -#BUG    $log_text->freeze(); -    if ($::isFile) { -	parse_file($::File); +sub search() { +    my $window = $log_text->get_window('widget'); +    return if !$window; +    $window->freeze_updates; +    $log_buf->set_text(''); +    if ($isFile) { +	parse_file($File, $File);      } else {  	foreach (keys %files) { -	    parse_file($files{$_}{file}) if $toggle{$_}->active; +	    parse_file($files{$_}{file}, $files{$_}{desc}) if $toggle{$_}->get_active;  	}      } -#BUG    $log_text->thaw(); -    $log_text->show(); +    $window->thaw_updates; +    $log_text->show;      gtkflush();  } -local *F; +my $timer; + +my @logs; + +my $F;  sub parse_file { -  my ($file) = @_;#$_[0]; +  my ($file, $descr) = @_;    $file =~ s/\.gz$//;    my ($pbar, $win_pb); -  unless ($::isEmbedded) { -      gtkadd($win_pb = gtkset_modal(new Gtk2::Window('toplevel'), 1), -             gtkpack(new Gtk2::VBox(2,0), -                     new Gtk2::Label(" " . N("please wait, parsing file: %s", $files{$_}{desc}) . " "), -                     $pbar = new Gtk2::ProgressBar() +  unless ($::isEmbedded && $isExplain) { +      local $::main_window = $my_win->{real_window}; +      gtkadd($win_pb = gtkset_modal(Gtk3::Window->new('toplevel'), 1), +             gtkpack(Gtk3::VBox->new(2,0), +                     Gtk3::Label->new(" " . N("please wait, parsing file: %s", $descr) . " "), +                     $pbar = Gtk3::ProgressBar->new                       )               ); -      $win_pb->set_transient_for($my_win->{rwindow}); -      $win_pb->set_modal(1); +      $win_pb->set_transient_for($my_win->{real_window});        $win_pb->set_position('center'); -      $win_pb->realize(); -      $win_pb->show_all(); +      $win_pb->realize; +      $win_pb->show_all; +      gtkflush();    }    my $ey = $e_yes->get_chars(0, -1);    my $en = $e_no->get_chars(0, -1); -  $ey =~ s/ OR /\|/; +  $ey =~ s/ OR /|/;    $ey =~ s/^\*$//;    $en =~ s/^\*$/.*/; -  $ey = $ey . $::Word if $::isWord; +  $ey = $ey . $Word if $isWord;    if ($cal_mode) { -      my (undef, $month, $day) = $cal->get_date(); -      $ey = $months[$month]."\\s{1,2}$day\\s.*$ey.*\n"; +      my (undef, $month, $day) = $cal->get_date; +      $ey = $months[$month] . "\\s{1,2}$day\\s.*$ey.*\n";    } -  my @all = catMaybeCompressed($file); +  my @all = -e $file ? catMaybeCompressed($file) : N("Sorry, log file isn't available!"); -  if ($::isExplain) { +  if ($isExplain) {        my (@t, $t);        while (@all) {  	  $t = pop @all;  	  next if $t =~ /logdrake/; -	  last if $t !~ /$::Explain/; +	  last if $t !~ /$Explain/;  	  push @t, $t;        }        @all = reverse @t; @@ -279,64 +264,79 @@ sub parse_file {    my $taille = @all;    my $i = 0; +  my $test; +  if ($en && !$ey) { +      $test = sub { $_[0] !~ /$en/ }; +  } elsif ($ey && !$en) { +      $test = sub { $_[0] =~ /$ey/ }; +  } else { +      $test = sub { $_[0] =~ /$ey/ && $_[0] !~ /$en/ }; +  } +    foreach (@all) {        $i++; -      if (!$::isEmbedded && $i % 10) {  +      if ($pbar && $i % 10) {   	  $pbar->set_fraction($i/$taille); -	  gtkflush(); +       $win_pb->get_window->process_updates(1); # no gtkflush() because we do not want to refresh the TextView        } -      if ($en eq "" and /$ey/i)     { logcolorize($_); next } -      if (!  /$en/i and /$ey/i)     { logcolorize($_); next } -      if (!  /$en/i and $ey eq "")  { logcolorize($_); next } +      logcolorize($_) if $test->($_);    } -  $win_pb->destroy() unless $::isEmbedded; - -  if ($::isTail) { -      close F; -      open F, $file or die "E: $!"; -      local $_; -      while (<F>) {}; #to prevent to output the file twice.. -#      $log_text->set_point($log_text->get_length()); -      my $timer = Gtk2->timeout_add(1000, \&input_callback); +  $win_pb->destroy if !$::isEmbedded || !$isExplain; + +  if ($isTail) { +      close $F if $F; +      if (open $F, $file) { +          local $_; +          while (<$F>) {}       #to prevent to output the file twice.. +          #      $log_text->set_point($log_text->get_length()); +          $timer ||= Glib::Timeout->add(1000, sub { +                                            logcolorize($_) while <$F>; +                                            seek $F, 0, 1; +                                        }); +      } else { +          my $error = $!; +          my $string = chomp_(`LC_ALL=C date '+%b %d %T'`) . " " . +            N("Error while opening \"%s\" log file: %s\n", $file, $error); +          # `` return non utf8 and concat of non utf8 & utf8 is non utf8: +          c::set_tagged_utf8($string); +          logcolorize($string); +      }    }      -} - -sub input_callback  { -    logcolorize($_) while <F>; -    seek F, 0, 1; +  insert_text_n_scroll();  }  ##########################################################################################  sub logcolorize { - +    my ($string) = @_;      # we get date & time if it is date & time (dmesg) -    s/(\D{3} .. (\d\d:\d\d:\d\d ))//; -    my $timestamp = $::isExplain ? $2 : $1; -    my @rec = split; +    $string =~ s/(\D{3} .. (\d\d:\d\d:\d\d ))//; +    my $timestamp = $isExplain ? $2 : $1; +    my @rec = split(/\s/, $string); +    @rec = map { c::set_tagged_utf8($_); $_ } @rec if utf8::is_utf8($string); -    log_output($timestamp,  { %b, 'foreground' => 'darkcyan' }); # date & time if any... +    log_output($timestamp,  'Bold', 'darkcyan'); # date & time if any...      # BUG: $col hasn't yet be reseted -    $::isExplain or log_output("$rec[0] ",  { %b, 'foreground' => $rec[0] eq $h ? 'blue' : $col });  # hostname +    $isExplain or log_output("$rec[0] ",  'Bold', $rec[0] eq $h ? 'blue' : $col);  # hostname      if ($rec[1] eq "last") { -	log_output(" last message repeated ",  { %n, 'foreground' => 'green' }); -	log_output($rec[4],  { %b, 'foreground' => 'green' }); -	log_output(" times\n",  { %n, 'foreground' => 'green' }); +	log_output(" last message repeated ",  undef, 'green'); +	log_output($rec[4],  'Bold', 'green'); +	log_output(" times\n",  undef, 'green');  	return;      }      # Extract PID if present -    if ($rec[1] =~ /\[(\d+)\]\:/) { -	my ($pid) = $1; -	$rec[1] =~ s/\[$1\]\://; -	log_output($rec[1] . "[",  { %n, 'foreground' => 'green' }); -	log_output($pid,  { %b, 'foreground' => 'black' }); -	log_output("]: ",  { %n, 'foreground' => 'green' }); +    if ($rec[1] =~ /\[(\d+)\]:/) { +	my $pid = $1; +	$rec[1] =~ s/\[$1\]://; +	log_output($rec[1] . "[",  undef, 'green'); +	log_output($pid,  'Bold', 'black'); +	log_output("]: ",  undef, 'green');      }      else { -	log_output($rec[1] . " ",  { %n, 'foreground' => 'green' }); +	log_output($rec[1] . " ",  undef, 'green');      }      foreach my $therest (2 .. $#rec) { @@ -353,16 +353,25 @@ sub logcolorize {   	#foreach (@line_warn) { $col = $col_warn if $_ eq $rec[$therest] }  	#foreach (@line_bad)  { $col = $col_bad  if $_ eq $rec[$therest] } -	log_output("$rec[$therest] ",  { %n, 'foreground' => $col }); +	log_output("$rec[$therest] ", undef, $col);      } -    log_output("\n",  { %n, 'foreground' => 'black' }); +    log_output("\n",  undef, 'black'); +    insert_text_n_scroll() if $isExplain;  } -#    log_output (Gtk2::TextView, [ [ ... ] ]) +#    log_output (Gtk3::TextView, [ [ ... ] ])  sub log_output { -    gtktext_append($log_text, [ \@_ ]); -#    $log_buf->insert($buf->get_end_iter(), @_, -1); +    my ($text, $font, $col) = @_; +    my $tag = join('', $font, $col); +    push @logs, [ $text, $tag ]; +    $log_buf->{tags}{$tag} ||= { foreground => $col }; # if_($font, font => $font),  +} + +sub insert_text_n_scroll() { +    ugtk3::gtktext_insert($log_text, \@logs, append => 1); +    $log_text->scroll_to_iter($log_buf->get_end_iter, 0, 1, 0.5, 0.5); +    undef @logs;  } @@ -370,34 +379,16 @@ sub log_output {  # mail/sms alert  #------------------------------------------------------------- -sub alert_config { +sub alert_config() { +    local $::isEmbedded = 0; +    undef $::WizardTable; +    undef $::WizardWindow; +    my $conffile = "/etc/sysconfig/mail_alert"; +    my %options = getVarsFromSh($conffile); +    $options{LOAD} ||= 3; +    $options{MAIL} ||= "root"; +    $options{SMTP} ||= "localhost"; -    $::isWizard = 1; -    $::Wizard_pix_up = "wiz_logdrake.png";    # FIXME -    $::Wizard_title = N("Mail alert"); -     -    my $cron = q(#!/usr/bin/perl -# generated by logdrake -use MDK::Common; -my $r = "*** ". chomp_(`date`) . " ***\n"; - -); - -my $initdir = "/etc/init.d"; - -    my ($load, $email, $smtp);  -    $load = 3; - -  begin: -    $::Wizard_finished = 0; -    $::Wizard_no_previous = 1; -    $in->ask_okcancel(N("Mail alert configuration"), -                      N("Welcome to the mail configuration utility.\n\nHere, you'll be able to set up the alert system.\n"), -		      1) or quit(); - -  step_service: -    undef $::Wizard_no_previous; -    undef $::Wizard_finished;      my $service = {  		  httpd => N("Apache World Wide Web Server"),   		  bind => N("Domain Name Resolver"), @@ -408,69 +399,120 @@ my $initdir = "/etc/init.d";  		  webmin => N("Webmin Service"),  		  xinetd => N("Xinetd Service")  		 }; -    my @installed_d; -    foreach my $serv (keys %$service) { -	-e "$initdir/$serv" && push @installed_d, $serv; -    } -   -    $in->ask_from(N("service setting"), -		  N("You will receive an alert if one of the selected services is no longer running"), -		  [ map { { label => $_, val => \${ $_ }, type => "bool", text => $service->{$_} } } @installed_d -		  ]) or goto begin; - -    $cron .= "#- check services\n"; -    my $r; -    foreach (@installed_d) { -	$r .= "Service $_ ($service->{$_} is not running\n" unless -e "/var/lock/subsys/$_"; -#	$cron .= "$r" if ${ $_ }; # take a look at this, don't know what is done here    -    } +    my @installed_d = grep { -e "/etc/init.d/$_" } sort keys %$service; +    my %services_to_check = map { $_ => 1 } split(':', $options{SERVICES}); -  step_load: -    undef $::Wizard_finished; -    $in->ask_from(N("load setting"), -		  N("You will receive an alert if the load is higher than this value"), -		  [ -		   { label => "load ", val => \$load, type => 'range', min => 1, max => 50 }, -		  ]) or goto step_service; +    $::isWizard = 1; +    my $mode; +    my $cron_file = "/etc/cron.hourly/logdrake_service"; +    my %modes = ( +                   configure => N("Configure the mail alert system"), +                   disable =>  N("Stop the mail alert system"), +                  ); +    require wizards; +    my $wiz = wizards->new({ +               defaultimage => "logdrake.png", +               name => N("Mail alert"), +               pages => { +                         welcome => { +                                     name => N("Mail alert configuration") . "\n\n" . +                                     N("Welcome to the mail configuration utility.\n\nHere, you'll be able to set up the alert system.\n"), +                                     no_back => 1, +                                     data => [ +                                              { val => \$mode, label => N("What do you want to do?"), +                                                list => [ keys %modes ], format => sub { $modes{$_[0]} },  }, +                                              ], + +                                     post => sub { $mode eq 'configure' ? 'services' : 'stop' }, +                                    }, +                         services => { +                                      name => N("Services settings") . "\n\n" . +                                      N("You will receive an alert if one of the selected services is no longer running"), +                                      data => [ map { { label => $_, val => \$services_to_check{$_},  +                                                          type => "bool", text => $service->{$_} } } @installed_d ], +                                      next => "load", +                                     }, +                         load => { +                                  #PO- Here "load" is a noun; that is load refers to the system/CPU) load +                                  name => N("Load setting") . "\n\n" . +                                  N("You will receive an alert if the load is higher than this value"), +                                  data => [ { label => N("_: load here is a noun, the load of the system\nLoad"),  +                                              val => \$options{LOAD}, type => 'range', min => 1, max => 50 } ], +                                  next => "email", +                                 }, +                         email => { +                                   name => N("Alert configuration") . "\n\n" . +                                   N("Please enter your email address below ") . "\n" . +                                   N("and enter the name (or the IP) of the SMTP server you wish to use"), +                                   data => [ +                                            { label => N("Email address"), val => \$options{MAIL} }, +                                            { label => N("Email server"), val => \$options{SMTP} }, +                                           ], +                                   complete => sub { +                                       if ($options{MAIL} !~ /[\w.-]*\@[\w.-]/ && !member($options{MAIL}, map { $_->[0] } list_passwd())) { +                                           err_dialog(N("Error"), N("\"%s\" neither is a valid email nor is an existing local user!", +                                                                          $options{MAIL})); +                                           return 1; +                                       } +                                       if (member($options{MAIL}, map { $_->[0] } list_passwd()) && $options{SMP} !~ /localhost/) { +                                           err_dialog(N("Error"), N("\"%s\" is a local user, but you did not select a local smtp, so you must use a complete email address!", $options{MAIL})); +                                           return 1; +                                       } +                                   }, +                                   next => "end", +                                  }, +                         end => { +                                 name => N("Congratulations") . "\n\n" . N("The wizard successfully configured the mail alert."),  +                                 end => 1, +                                 no_back => 1, +                                }, +                         stop => { +                                  pre => sub { eval { rm_rf($cron_file) } }, +                                  name => N("Congratulations") . "\n\n" . N("The wizard successfully disabled the mail alert."),  +                                  end => 1, +                                  no_back => 1, +                                }, +                        }, +              }); +    $wiz->process($in); +    return if $mode eq 'disable'; +     +    $options{SERVICES} = join ':', grep { $services_to_check{$_} } sort keys %services_to_check; + +    use Data::Dumper; +    output_with_perm $cron_file, 0755, q(#!/usr/bin/perl +# generated by logdrake +use MDK::Common; +my $r; +my %options = getVarsFromSh("/etc/sysconfig/mail_alert"); + +#- check services +my ) . Data::Dumper->Dump([ $service ], [qw(*services)]) . q( +foreach (split(':', $options{SERVICES})) { +    next unless $services{$_}; +    $r .= "Service $_ ($services{$_} is not running)\\n" unless -e "/var/lock/subsys/$_"; +} -    $cron .= sprintf(<<'EOF', $load);  #- load  my ($load) = split ' ', first(cat_("/proc/loadavg")); -$r .= "Load is huge: $load\n" if $load > %s; - -EOF -     -  step_output: -#    $::Wizard_no_previous = 1; -    $::Wizard_finished = 1; -    $in->ask_from(N("alert configuration"), -		  N("Please enter your email address below "), -		  [ -		   { label => "" }, -		   { label => "Email", val => \$email }, -		  ]) or goto step_load; - -    $cron .= q(#- report it - -$email = ) . "'$email';\n\n"; - -	$cron .= q( -local *F; -open F, '|/usr/sbin/sendmail -oi -t'; - -print F -q(Subject: logdrake Mail Alert -From: root@localhost -To: ), "$email\n"; -print F $r; +$r .= "Load is huge: $load\n" if $load > $options{LOAD}; + +#- report it +if ($r) { +    use Mail::Mailer; +    my $mailer = Mail::Mailer->new('smtp', Server => $options{SMTP}); +    $mailer->open({ From    => 'root@localhost', +                    To      => $options{MAIL}, +                    Subject => "DrakLog Mail Alert", +                  }) +      or die "Cannot open: $!\n"; +    print $mailer $r; +    $mailer->close; +}  # EOF); -	output $cron_hourly, $cron; -	chmod 0755, $cron_hourly; +    setVarsInSh($conffile, \%options); -    print "whole cron is ****** $cron *******\n"; -     -    undef $::isWizard;       if (defined $::WizardWindow) {  	$::WizardWindow->destroy;  	undef $::WizardWindow; @@ -483,8 +525,10 @@ print F $r;  #------------------------------------------------------------- -sub save { +sub save() {      $::isWizard = 0; -    $yy = $in->ask_file(N("Save as.."), "/root") or return; -    output($yy, $log_text->get_chars(0, $log_text->get_length())); +    my $y = $in->ask_filename({ title => N("Save as.."), directory => "/root", save => 1 }) or return; +    my $buf = $log_text->get_buffer; +    my ($start, $end) = $buf->get_bounds; +    output($y, $buf->get_text($start, $end, 0));  }  | 
