#!/usr/bin/perl -w # # The contents of this file are subject to the Mozilla Public # License Version 1.1 (the "License"); you may not use this file # except in compliance with the License. You may obtain a copy of # the License at http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or # implied. See the License for the specific language governing # rights and limitations under the License. # # The Original Code is the Bugzilla Status Bot # # The Initial Developer of the Original Code is David D. Miller. # Portions developed by David D. Miller are Copyright (C) 2002-3 # David D. Miller. All Rights Reserved. # # Contributor(s): David Miller # Mark Smith # use strict; use Net::IRC; use POSIX "sys_wait_h"; use Term::ANSIColor qw/ :constants /; use Data::Dumper; use Time::HiRes qw(usleep nanosleep); use Config::Simple; # # Get configuration file. # my $viviviConf = new Config::Simple("/etc/vivivi/vivivi.conf") or die "Missing configuration file."; print "Configuration file loaded.\n"; # # Create the IRC and Connection objects # my $version = "BZBot v1.3 - Modified for use with Nagios."; my $irc = new Net::IRC; my $channel = $viviviConf->param("irc.channel"); #open IPADDR, "; #chomp ($ipaddr); #close IPADDR; # CONFIG: point this where your Nagios configuration files live my $nagioslog = $viviviConf->param("nagios.log"); my $nagioscmd = $viviviConf->param("nagios.cmd"); open NAGIOS, "<$nagioslog" or die "failed to open $nagioslog: $!\n"; seek NAGIOS, 0, 2; # seek to end my @cmdqueue = (); my %ignore = (); my $ACKCT = 0; my @ACKS; my $FLOOD_MAX = 5; my $USLEEP_TIME = 1000000; print "Creating connection to IRC server...\n"; my $conn; while (!$conn) { # CONFIG: you have to tell us where to get on IRC $conn = $irc->newconn(Server => $viviviConf->param("irc.server"), Port => $viviviConf->param("irc.port"), SSL => $viviviConf->param("irc.ssl"), Nick => $viviviConf->param("irc.nick"), Ircname => $viviviConf->param("irc.name"), Username => $viviviConf->param("irc.username")) or print "Redialing...\n"; sleep 1; } print "Connection created.\n"; $conn->debug(1); my $laststat = time; my $identified_to_nickserv = 0; $::tagueule = 0; # # Handler subs # # What to do when the bot successfully connects. sub on_connect { my $self = shift; $identified_to_nickserv = 1; print "Joining $channel...\n"; # FIXME: this is broken right now. when this is re-added, it has to happen # before we try to join channels. #print "Identifying to NickServ...\n"; $self->privmsg('nickserv', "identify ".$viviviConf->param("irc.password")); # $self->privmsg('nickserv',"VERIFY REGISTER vivivi kwvxbsmjjiam"); # CONFIG: channels you want us to announce to ... $self->join($channel); #$self->join("#status"); } # Handles some messages you get when you connect sub on_init { my ($self, $event) = @_; my (@args) = ($event->args); shift (@args); print "*** @args\n"; } # What to do when someone leaves a channel the bot is on. sub on_part { my ($self, $event) = @_; my ($channel) = ($event->to)[0]; printf "*** %s has left channel %s\n", $event->nick, $channel; } # What to do when someone joins a channel the bot is on. sub on_join { my ($self, $event) = @_; my ($channel) = ($event->to)[0]; my ($nick, $userhost) = ($event->nick, $event->userhost); printf "*** %s (%s) has joined channel %s\n", $nick, $userhost, $channel; &refresh (); } # What to do when we receive a private PRIVMSG. sub on_msg { my ($self, $event) = @_; my ($nick) = $event->nick; my ($arg) = ($event->args); print "*$nick* ", ($event->args), "\n"; if ($arg =~ /Go away/i) { # Tell him to leave, and he does. $self->quit("Yow!!"); exit 0; # CONFIG: if you don't change this, anybody can restart your IRC bot at will # if they've seen this ... } elsif ($arg =~ /restart ya dope/) { $self->quit("Regrouping"); exec $0; } else { $self->privmsg($nick, "Yo!"); } } # What to do when we receive channel text. sub on_public { my ($self, $event) = @_; my @to = $event->to; my ($nick, $mynick) = ($event->nick, $self->nick); my ($arg) = ($event->args); # Note that $event->to() returns a list (or arrayref, in scalar # context) of the message's recipients, since there can easily be # more than one. # FIXME: the logging gets spammy ... do we actually want to log to stdout? print "<$nick> $arg\n"; $mynick =~ s/\[/\\[/g; $mynick =~ s/\]/\\]/g; print "My nick: $mynick\n"; if ($arg =~ /^$mynick[,: ]/i || $arg =~ /^!/ ) { if ($arg =~ /^(?:$mynick[,: ]|!)\s*ignore (.+)\s*$/i) { $ignore{$1} = 1; $self->privmsg([ @to ], "$nick: ok, ignoring notifications about $1"); } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*ignore$/i) { if (keys %ignore) { foreach my $i (keys %ignore) { $self->privmsg([ @to ], "$nick: ignoring $i"); } $self->privmsg([ @to ], "$nick: end of list"); } else { $self->privmsg([ @to ], "$nick: I'm not currently ignoring any notifications"); } } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*unignore (.+)\s*$/i) { if (!exists($ignore{$1})) { $self->privmsg([ @to ], "$nick: notifications about $1 weren't being ignored anyway."); } else { delete $ignore{$1}; $self->privmsg([ @to ], "$nick: ok, notifications about $1 no longer being ignored."); } } elsif ($arg =~ /^(?:$mynick[,: ]|!)+(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$/) { open CMDPIPE,">",$nagioscmd; my ( $host, $svc ) = @{ $ACKS[$1] || [ undef, undef ] }; if ( defined $host && defined $svc ) { $self->privmsg([ @to ], "$nick: ok, acknowledgment (if any) for $host:$svc has been added."); printf CMDPIPE "[%lu] ACKNOWLEDGE_SVC_PROBLEM;%s;%s;1;1;1;%s;%s\n",time(),$host,$svc,$nick,$2; } elsif ( defined $host ) { printf CMDPIPE "[%lu] ACKNOWLEDGE_HOST_PROBLEM;%s;1;1;1;%s;%s\n",time(),$host,$nick,$2; } close CMDPIPE; } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*ack ([^:]+):([^:]+)\s*$/) { open CMDPIPE,">",$nagioscmd; printf CMDPIPE "[%lu] ACKNOWLEDGE_HOST_PROBLEM;%s;1;1;1;%s;%s\n",time(),$1,$nick,$2; close CMDPIPE; } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*ack ([^:]+):([^:]+):([^:]+)\s*$/) { open CMDPIPE,">",$nagioscmd; printf CMDPIPE "[%lu] ACKNOWLEDGE_SVC_PROBLEM;%s;%s;1;1;1;%s;%s\n",time(),$1,$2,$nick,$3; close CMDPIPE; } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*unack (\d+)$/) { open CMDPIPE,">",$nagioscmd; my ( $host, $svc ) = @{ $ACKS[$1] || [ undef, undef ] }; if ( defined $host && defined $svc ) { printf CMDPIPE "[%lu] REMOVE_SVC_ACKNOWLEDGEMENT;%s;%s\n",time(),$host,$svc; $self->privmsg([ @to ], "$nick: ok, acknowledgment (if any) for $host:$svc has been removed."); } elsif ( defined $host ) { printf CMDPIPE "[%lu] REMOVE_HOST_ACKNOWLEDGEMENT;%s\n",time(),$host; $self->privmsg([ @to ], "$nick: ok, acknowledgment (if any) for $host has been removed."); } close CMDPIPE; } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*unack ([^:]+)\s*$/) { open CMDPIPE,">",$nagioscmd; printf CMDPIPE "[%lu] REMOVE_HOST_ACKNOWLEDGEMENT;%s\n",time(),$1; close CMDPIPE; $self->privmsg([ @to ], "$nick: ok, acknowledgment (if any) for $1 has been removed."); } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*unack ([^:]+):([^:]+)\s*$/) { open CMDPIPE,">",$nagioscmd; printf CMDPIPE "[%lu] REMOVE_SVC_ACKNOWLEDGEMENT;%s;%s\n",time(),$1,$2; close CMDPIPE; $self->privmsg([ @to ], "$nick: ok, acknowledgment (if any) for $1:$2 has been removed."); } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*status\s*$/) { my @lines = (); open CMDPIPE,"-|","/usr/sbin/icingastats -m -d NUMSVCWARN,NUMSVCCRIT,NUMSVCUNKN"; while () { chomp; push @lines, $_; } close CMDPIPE; my @prefix = ( 'Warn', 'Critical', 'Unknown' ); my $i = 0; foreach my $line (@lines) { $self->privmsg([ @to ], "$nick: ".$prefix[$i++].": $line"); } } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*help/i) { $self->privmsg([ @to ], "$nick: You're right, I need help!"); $self->privmsg([ @to ], "$nick: supported commands: ignore, unignore, ack, unack, chut, list, refresh, recheck, help"); } elsif ($arg =~ /(?:hey|hi|hello|yo)(?:\.|,|\!|\s_)/i) { $self->privmsg([ @to ], "Yo, $nick!"); } elsif ($arg =~ /(?:$mynick[,: ]|!)\s*ta\s*g(:?ueu|o)le/i || $arg =~ /(?:$mynick[,: ]|!)\s*chut/i || $arg =~ /(?:$mynick[,: ]|!)\s*sieste/i ) { if ( $::tagueule == 0 ) { $self->privmsg([ @to ], "$nick: d'accord je la ferme :-("); $::tagueule = 1; $self->nick('vivivi[zzz]'); } else { $self->privmsg([ @to ], "$nick: je reviens et je ne suis pas content !"); $::tagueule = 0; &adjust_nick ( $conn ); } } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*list\s*$/) { &refresh (); my $msg; if( scalar @ACKS == 0 or scalar @ACKS == 1) { $msg = "%d probleme enregistre"; } else { $msg = "%d problemes enregistres"; } $conn->privmsg([ @to ], sprintf ( $msg, ( scalar @ACKS )) ); my $id = 0; if ( scalar @ACKS > $FLOOD_MAX ) { my %resume; foreach ( @ACKS ) { my ( $host, $svc, $state, $content ) = @$_; $resume { "$svc|$state" } = '' if ! $resume { "$svc|$state" }; $resume { "$svc|$state" } .= ", $host"; } print Dumper %resume; if ( scalar keys %resume <= $FLOOD_MAX ) { foreach ( keys %resume ) { /(.*)\|(.*)/; my $svc = $1; my $state = $2; my $msg = $resume { $_ }; $msg =~ s/^, //; $msg = sprintf ( "[%02d] %s: %s %s %s", ($id++), $svc, $msg, ( index( $msg, ',' ) > -1 ? 'are' : 'is' ), $state ); usleep ( $USLEEP_TIME ); $conn->privmsg([ @to ], $msg); } } else { my @megaresume; foreach ( keys %resume ) { /(.*)\|(.*)/; my $svc = $1; my $state = $2; my @count = $resume { $_ } =~ /,/g; push @megaresume, sprintf ( "%s (%d)", $svc, scalar ( @count ) ); } my $msg = join ", ", @megaresume; usleep ( $USLEEP_TIME ); $conn->privmsg([ @to ], $msg); } } else { foreach ( @ACKS ) { my ( $host, $svc, $state, $content ) = @$_; my $msg = sprintf ( "[%02d] %s:%s is %s: %s", ($id++), $host, $svc, $state, $content ); usleep ( $USLEEP_TIME ); $conn->privmsg([ @to ], $msg); } } } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*refresh\s*$/) { &refresh (); my $msg; if( scalar @ACKS == 0 or scalar @ACKS == 1) { $msg = "%d probleme enregistre"; } else { $msg = "%d problemes enregistres"; } $conn->privmsg([ @to ], sprintf ( $msg, ( scalar @ACKS )) ); } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*recheck:?\s*(\d*)$/) { if ( $ACKS[$1] ) { my ( $host, $svc ) = @{ $ACKS[$1] || [ undef, undef ] }; open CMDPIPE,">",$nagioscmd; printf CMDPIPE "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n",time(),$host,$svc,time(); printf "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n",time(),$host,$svc,time(); close CMDPIPE; usleep ( $USLEEP_TIME ); $conn->privmsg([ @to ], sprintf ( "Recheck forcé pour %s: %s", $host, $svc ) ); &refresh (); my $msg; if( scalar @ACKS == 0 or scalar @ACKS == 1) { $msg = "%d probleme enregistre"; } else { $msg = "%d problemes enregistres"; } usleep ( $USLEEP_TIME ); $conn->privmsg([ @to ], sprintf ( $msg, ( scalar @ACKS )) ); } else { $conn->privmsg([ @to ], sprintf ( "ID inconnu: %d", $1 ) ); } } elsif ($arg =~ /^(?:$mynick[,: ]|!)\s*recheck:?\s*all$/) { #recheck all &refresh (); my $msg; if( scalar @ACKS == 0 or scalar @ACKS == 1) { $msg = "%d probleme enregistre"; } else { $msg = "%d problemes enregistres"; } $conn->privmsg([ @to ], sprintf ( $msg, ( scalar @ACKS )) ); for my $i ( 0..(@ACKS-1) ) { next unless($ACKS[$i]); my ( $host, $svc ) = @{ $ACKS[$i] || [ undef, undef ] };; open CMDPIPE,">",$nagioscmd; printf CMDPIPE "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n",time(),$host,$svc,time(); printf "[%lu] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%lu\n",time(),$host,$svc,time(); close CMDPIPE; # if ( scalar @ACKS <= $FLOOD_MAX ) # { # usleep ( $USLEEP_TIME ); # $conn->privmsg([ @to ], sprintf ( "Recheck forcé pour ack : %s du host %s: %s", $i, $host, $svc ) ); # } } if ( scalar @ACKS > $FLOOD_MAX ) { usleep ( $USLEEP_TIME ); $conn->privmsg([ @to ], sprintf ( "%d rechecks forcés", scalar @ACKS ) ); } } else { $self->privmsg([ @to ], "Yo!"); } } } # Prints the names of people in a channel when we enter. sub on_names { my ($self, $event) = @_; my (@list, $channel) = ($event->args); # eat yer heart out, mjd! # splice() only works on real arrays. Sigh. ($channel, @list) = splice @list, 2; print "Users on $channel: @list\n"; } sub on_ping { my ($self, $event) = @_; $self->sl("PONG " . join(' ', ($event->args))); } sub on_pong { my ($self, $event) = @_; # don't really need to do anything, just update the time. } # Yells about incoming CTCP PINGs. sub on_ctcpping { my ($self, $event) = @_; my $nick = $event->nick; $self->ctcp_reply($nick, join (' ', ($event->args))); print "*** CTCP PING request from $nick received\n"; } # Yells about incoming CTCP VERSIONs. sub on_ctcpversion { my ($self, $event) = @_; my $nick = $event->nick; $self->ctcp_reply($nick, join (' ', ($event->args, $version))); print "*** CTCP VERSION request from $nick received\n"; } # Gives lag results for outgoing PINGs. sub on_ping_reply { my ($self, $event) = @_; my ($args) = ($event->args)[1]; my ($nick) = $event->nick; $args = time - $args; print "*** CTCP PING reply from $nick: $args sec.\n"; } # Change our nick if someone stole it. sub on_nick_taken { my ($self) = shift; my ($nick,$num) = $self->nick =~ /^(.+)(\d+)?$/; $num ||= 0; $self->nick($nick . ($num + 1)); } # Display formatted CTCP ACTIONs. sub on_action { my ($self, $event) = @_; my ($nick, @args) = ($event->nick, $event->args); print "* $nick @args\n"; } # Reconnect to the server when we die. sub on_disconnect { my ($self, $event) = @_; print "Disconnected from ", $event->from(), " (", ($event->args())[0], "). Attempting to reconnect...\n"; $identified_to_nickserv = 0; while (!$self->connected) { $self->connect(); if (!$self->connected) { print "Redialing...\n" } } } # Look at the topic for a channel you join. sub on_topic { } sub on_notice { my ($self, $event) = @_; my @args = $event->args(); # FIXME: the nickserv path is broken ... if ((lc($event->nick) eq "nickserv") && ($args[0] =~ "nickname is registered")) { # print "Identifying to NickServ...\n"; # $self->privmsg('nickserv',"identify xxx"); } # FIXME: the nickserv path is broken ... if ((lc($event->nick) eq "nickserv") && ($args[0] =~ "You are now identified")) { #nickserv identification successful, so let's join channels. $identified_to_nickserv = 1; print "Joining channels...\n"; # CONFIG: channels that should be joined go here. $self->join($channel); } } sub ackable { my ( $host, $svc, $state, $msg ) = @_; return '' unless $state eq 'WARNING' || $state eq 'CRITICAL' || $state eq 'UNKNOWN' || $state eq 'DOWN'; my $id = $ACKCT++ % 100; $ACKS[$id] = [ $host, $svc, $state, $msg ]; return sprintf( '[%02d] ', $id ); } sub refresh { $ACKCT=0; @ACKS=(); open FILE, '/var/lib/icinga/status.dat' or die $!; while ( ) { if ( /^servicestatus/ ) { my %keys; do { $_ = ; chomp; $keys{$1} = $2 if ( /\s*([^=]*)=([^=]*)/ ); } while ( $_ && ! /^}/ ); my @states = ( 'OK', 'WARNING', 'CRITICAL', 'UNKNOWN' ); $ACKS[$ACKCT++] = [ $keys{'host_name'}, $keys{'service_description'}, $states[$keys{'current_state'}], $keys{'plugin_output'} ] if $keys{'current_state'} > 0; } } close FILE; } print "Installing handler routines..."; $conn->add_global_handler('ping', \&on_ping); $conn->add_global_handler('pong', \&on_pong); $conn->add_handler('cping', \&on_ctcpping); $conn->add_handler('crping', \&on_ping_reply); $conn->add_handler('cversion', \&on_ctcpversion); $conn->add_handler('msg', \&on_msg); $conn->add_handler('public', \&on_public); $conn->add_handler('caction', \&on_action); $conn->add_handler('join', \&on_join); $conn->add_handler('part', \&on_part); #$conn->add_handler('topic', \&on_topic); $conn->add_handler('notopic', \&on_topic); $conn->add_handler('notice', \&on_notice); $conn->add_global_handler([ 251,252,253,254,302,255 ], \&on_init); $conn->add_global_handler('disconnect', \&on_disconnect); $conn->add_global_handler(376, \&on_connect); $conn->add_global_handler(433, \&on_nick_taken); $conn->add_global_handler(353, \&on_names); print " done.\n"; my %C = ( W => "\x0315", B => "\x032", G => "\x033", R => "\x034", O => "\x037", C => "\x0311", Y => "\x038", N => "\x0315", ); my $state_to_color = { OK => $C{G}, WARNING => $C{Y}, CRITICAL => $C{R}, UNKNOWN => $C{C}, }; print "starting...\n"; my %renot; # { "host" or "host:service" => time_last_notification } while (1) { $irc->do_one_loop(); if ($identified_to_nickserv) { # CONFIG: change where we announce stuff here my @channels = ($channel); while (defined (my $line = )) { print $line; chomp($line); next if $::tagueule; if ($line =~ /^\[\d+\] (HOST|SERVICE) NOTIFICATION: (.+)$/) { my ($type, $msg) = ($1, $2); my ($who, $host, $service, $state, $how, $output); if ($type eq "HOST") { ($who, $host, $state, $how, $output) = split(";",$msg,5); next if exists $renot{$host} && $renot{$host} >= time() - 5; $renot{$host} = time(); my $id = ackable($host,undef,$state,$output); $msg = $state_to_color->{$state} . "$id$host is $state: $output"; &adjust_nick ( $conn ); } else { ($who, $host, $service, $state, $how, $output) = split(";",$msg,6); next if exists $renot{"$host:$service"} && $renot{"$host:$service"} >= time() - 5; $renot{"$host:$service"} = time(); my $id = ackable($host,$service,$state,$output); $output =~ s/^\s*CRITICAL\s*:\s//gi; $output =~ s/^\s*WARNING\s*:\s//gi; $output =~ s/^\s*OK\s*:\s//gi; $msg = $state_to_color->{$state} . "$id$host:$service is $state: $output"; &adjust_nick ( $conn ); } $service ||= ""; # alerts can be separated by who they're for (which group is getting it) #if ($who eq "mark") { push @channels, "#dw_ops", "#dw_work" } if ((!grep { $_ eq "$host:$service" } keys %ignore) && (!grep { $_ eq "$host" } keys %ignore)) { $conn->privmsg($_,"$msg") foreach @channels; } #[1310493492] EXTERNAL COMMAND: SCHEDULE_HOST_DOWNTIME;gearmanworker-gearmanworker3;1310492897;1310500097;1;0;28800;stumble.barr;rebooting } elsif ($line =~ /EXTERNAL COMMAND: SCHEDULE_HOST_DOWNTIME;(.+?);(\d+);(\d+);\d+;\d+;\d+;(.+?);(.+)$/) { my $ns = $3 - $2; $conn->privmsg($_, "Downtime (${ns}s) scheduled for host $1 by $4: $5") foreach @channels; } elsif ($line =~ /EXTERNAL COMMAND: SCHEDULE_SVC_DOWNTIME;(.+?);(.+?);(\d+);(\d+);\d+;\d+;\d+;(.+?);(.+)$/) { my $ns = $4 - $3; $conn->privmsg($_, "Downtime (${ns}s) scheduled for service $1: $2 by $5: $6") foreach @channels; } elsif ($line =~ /EXTERNAL COMMAND: (EN|DIS)ABLE_HOST_(SVC_)?NOTIFICATIONS;(.+)$/) { my $type = $2 ? 'All service' : 'Host'; my $verb = $1 eq 'EN' ? "$C{G}enabled$C{N}" : "$C{R}disabled$C{N}"; $conn->privmsg($_, "$type notifications $verb: $C{O}$3") foreach @channels; } elsif ($line =~ /EXTERNAL COMMAND: (EN|DIS)ABLE_(SVC_)?NOTIFICATIONS;(.+?);(.+)$/) { my $verb = $1 eq 'EN' ? "$C{G}enabled$C{N}" : "$C{R}disabled$C{N}"; $conn->privmsg($_, "Service notifications $verb on $C{O}$3$C{N}: $C{O}$4") foreach @channels; } elsif ($line =~ /HOST DOWNTIME ALERT: (.+?);(.+?);/) { my $vb = { CANCELLED => 'been manually removed from', STOPPED => 'exited from', STARTED => 'entered' }->{$2}; $conn->privmsg($_, "Host $C{O}$1$C{N} has $vb scheduled downtime.") foreach @channels; } elsif ($line =~ /SERVICE DOWNTIME ALERT: (.+?);(.+?);(.+?);/) { my $vb = { CANCELLED => 'been manually removed from', STOPPED => 'exited from', STARTED => 'entered' }->{$3}; $conn->privmsg($_, "Service $C{O}$1$C{N}: $C{O}$2$C{N} has $vb scheduled downtime.") foreach @channels; } } if ((time - $laststat) > 30) { # we don't want to constantly stat the file or we'll hammer the disk. # keep it to once every 30 seconds. Here we compare the inode of the # file we have open and the file at the path we're expecting and see # if they match. If they don't, then the log has been rotated, so we # close and reopen it to pick up the new logfile. We also only do it # if we don't read a line from the file, so that way we make sure # actually gotten to the end of the current file before we check for # a rotation. $laststat = time; if ((stat NAGIOS)[1] != (stat $nagioslog)[1]) { close NAGIOS; open NAGIOS, "<$nagioslog"; } &adjust_nick ( $conn ); } } } sub adjust_nick { my ( $conn ) = @_; open CMDPIPE,"-|","/usr/sbin/icingastats -m -d NUMSVCWARN,NUMSVCCRIT,NUMSVCUNKN"; my $count = 0; while () { $count += $_; } close CMDPIPE; if ( $::tagueule ) { $conn->nick('vivivi[zzz]'); } elsif ( $count > 0 ) { $conn->nick(sprintf('vivivi[%d]', $count)); } else { $conn->nick('vivivi'); } }