aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes8
-rw-r--r--MANIFEST8
-rw-r--r--MANIFEST.SKIP63
-rw-r--r--Makefile.PL7
-rwxr-xr-xnetsnmp-sendmail-setup563
-rw-r--r--sendmail.pl211
6 files changed, 751 insertions, 109 deletions
diff --git a/Changes b/Changes
index a2a3c88..1f2388a 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,11 @@
+0.97 2023-11-15
+
+* Don't bail out if mailq or mailstats fails.
+
+0.96 2021-02-13
+
+* Change bugtracker address.
+
0.95 2016-10-04
* Add README, improve meta-data
diff --git a/MANIFEST b/MANIFEST
index 20e2baa..cb1246c 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,12 +1,12 @@
Changes
+install-mib.pl
LICENSE
Makefile.PL
MANIFEST This list of files
+MANIFEST.SKIP
+netsnmp-sendmail-setup
README
-Sendmail.pm
SENDMAIL-STATS.txt
-install-mib.pl
Sendmail.mib2c
sendmail.pl
-META.yml Module YAML meta-data (added by MakeMaker)
-META.json Module JSON meta-data (added by MakeMaker)
+Sendmail.pm
diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP
new file mode 100644
index 0000000..58696be
--- /dev/null
+++ b/MANIFEST.SKIP
@@ -0,0 +1,63 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+\bSCCS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\B\.gitignore\b
+\b_darcs\b
+\B\.cvsignore$
+
+# Avoid VMS specific MakeMaker generated files
+\bDescrip.MMS$
+\bDESCRIP.MMS$
+\bdescrip.mms$
+
+# Avoid Makemaker generated and utility files.
+\bMANIFEST\.bak
+\bMakefile$
+\bblib/
+\bMakeMaker-\d
+\bpm_to_blib\.ts$
+\bpm_to_blib$
+\bblibdirs\.ts$ # 6.18 through 6.25 generated this
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build/
+\bBuild.bat$
+\bBuild.COM$
+\bBUILD.COM$
+\bbuild.com$
+
+# Avoid temp and backup files.
+~$
+\.old$
+\#$
+\b\.#
+\.bak$
+\.tmp$
+\.#
+\.rej$
+
+# Avoid OS-specific files/dirs
+# Mac OSX metadata
+\B\.DS_Store
+# Mac OSX SMB mount metadata files
+\B\._
+
+# Avoid Devel::Cover and Devel::CoverX::Covered files.
+\bcover_db\b
+\bcovered\b
+
+# Avoid MYMETA files
+^MYMETA\.
+
+^debug.sh
+^tmp
+^buildreq
+^\.emacs\.*
+
+\.tar$
+\.tar\.gz$
diff --git a/Makefile.PL b/Makefile.PL
index 5645635..b9cef16 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -1,5 +1,5 @@
# SNMP Sendmail Statistics Module -*- perl -*-
-# Copyright (C) 2015, 2016 Sergey Poznyakoff <gray@gnu.org>
+# Copyright (C) 2015, 2016, 2019 Sergey Poznyakoff <gray@gnu.org>
#
# 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
@@ -28,6 +28,7 @@ WriteMakefile(
'PM' => {
'Sendmail.pm' => '$(INST_LIBDIR)/Sendmail.pm'
},
+ 'EXE_FILES' => [ 'netsnmp-sendmail-setup' ],
'PREREQ_PM' => { 'NetSNMP::OID' => 0,
'NetSNMP::agent' => 0,
'NetSNMP::ASN' => 0 },
@@ -40,6 +41,10 @@ WriteMakefile(
url => 'git://git.gnu.org.ua/netsnmp-sendmail.git',
web => 'http://git.gnu.org.ua/cgit/netsnmp-sendmail.git/',
},
+ bugtracker => {
+ web => 'https://puszcza.gnu.org.ua/bugs/?group=netsnmp-sendmail',
+ mailto => 'gray+netsnmp-sendmail@gnu.org.ua'
+ }
},
provides => Module::Metadata->provides(version => '2', dir => '.')
}
diff --git a/netsnmp-sendmail-setup b/netsnmp-sendmail-setup
new file mode 100755
index 0000000..53f5b21
--- /dev/null
+++ b/netsnmp-sendmail-setup
@@ -0,0 +1,563 @@
+#!/bin/sh
+#! -*-perl-*-
+# This file is part of NetSNMP::Sendmail
+# Copyright (C) 2019-2020 Sergey Poznyakoff <gray@gnu.org>
+#
+# 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 3, 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, see <http://www.gnu.org/licenses/>.
+eval 'exec perl -x -wS $0 ${1+"$@"}'
+ if 0;
+
+use strict;
+use warnings;
+use File::Temp;
+use File::Basename;
+use IPC::Cmd qw(can_run);
+use POSIX qw(strftime);
+use Fcntl;
+use Getopt::Long qw(:config gnu_getopt no_ignore_case require_order);
+use Pod::Usage;
+
+sub addts {
+ my $fd = shift;
+ print $fd "# Line added by $0 at "
+ . strftime("%Y-%m-%dT%H:%M:%S", localtime)
+ . "\n";
+}
+
+my $my_ts_rx = qr{^# Line added by $0 at };
+
+use constant {
+ EX_OK => 0, # Success
+ EX_UNCHANGED => 1, # Files not changed
+ EX_FATAL => 2, # Fatal error
+ EX_USAGE => 64 # Usage error
+};
+
+use constant {
+ CMD_SETUP => 0,
+ CMD_REMOVE => 1
+};
+
+my $suppress_level = 0;
+my $dry_run;
+my @updated_services;
+
+use constant {
+ L_INFO => 0,
+ L_NOTICE => 1,
+ L_WARN => 2,
+ L_ERR => 3
+};
+
+use constant MAX_SUPPRESS_LEVEL => L_WARN;
+
+sub printlog {
+ my $level = shift;
+ if ($suppress_level <= $level) {
+ my $fh = (($level >= L_WARN) ? \*STDERR : \*STDOUT);
+ print $fh "$0: ".join(' ',@_)."\n";
+ }
+}
+
+my @restart_commands = (
+ [qw(systemctl restart $service)],
+ [qw(service $service restart)],
+ [qw(/etc/init.d/$service restart)],
+ [qw(/etc/rc.d/$service restart)],
+);
+my %restart_override;
+
+sub restart_service {
+ my $service = shift;
+
+ my $cmd = $restart_override{$service};
+ return if $cmd && $cmd eq 'no';
+
+ printlog(L_NOTICE, "restarting $service");
+ return if $dry_run;
+
+ if ($cmd) {
+ printlog(L_NOTICE, "running $cmd");
+ system($cmd);
+ } else {
+ foreach $cmd (@restart_commands) {
+ my @c = map { s/\$service/$service/g; $_ } @$cmd;
+ if (can_run($c[0])) {
+ printlog(L_NOTICE, "running @c");
+ system(@c);
+ return if ($? == 0);
+ }
+ }
+ }
+}
+
+sub file_replace {
+ my ($file, $newfile) = @_;
+ my $bk = "$file~";
+ unlink $bk if -e $bk;
+ rename $file, $bk or die "can't rename $file to $bk: $!";
+ unless (rename $newfile, $file) {
+ printlog(L_WARN,
+ "can't rename $newfile to $file: $!; restoring from backup");
+ unless (rename $bk, $file) {
+ printlog(L_ERR, "failed to rename $bk to $file: $!");
+ exit(EX_FATAL);
+ }
+ }
+}
+
+sub file_remline {
+ my ($file, $fd, $line, $endline) = @_;
+ $endline //= $line;
+ printlog(L_NOTICE,
+ ($endline == $line) ? "editing $file: removing line $line"
+ : "editing $file: removing lines $line-$endline");
+ return if $dry_run;
+ my $ofd = File::Temp->new(DIR => dirname($file), UNLINK => $dry_run);
+ seek($fd, 0, SEEK_SET) or die "seek $file: $!";
+ my $ln = 0;
+ while (<$fd>) {
+ $ln++;
+ next if ($line <= $ln && $ln <= $endline);
+ print $ofd $_;
+ }
+ close $ofd;
+ close $fd;
+ file_replace($file, $ofd->filename);
+}
+
+sub scan_snmpd_conf {
+ my ($file, $fd) = @_;
+
+ my $line = 0;
+ my $comline;
+ my $insert_line;
+
+ while (<$fd>) {
+ ++$line;
+ chomp;
+ s/^\s+//;
+
+ if (/$my_ts_rx/) {
+ $comline = $line;
+ next;
+ }
+
+ if (/^perl\s+use\s+NetSNMP::Sendmail/) {
+ if ($comline && $comline + 1 == $line) {
+ return (1, $comline, $line);
+ } else {
+ return (1, $line);
+ }
+ }
+
+ if (/^perl\s+use/) {
+ $insert_line = $line;
+ }
+ }
+ return (0, $insert_line || $line + 1);
+}
+
+sub update_snmpd_conf {
+ my ($ifile, $ifd, $insert_line, $stmt) = @_;
+
+ seek($ifd, 0, SEEK_SET) or die "seek: $!";
+ my $ofd = File::Temp->new(DIR => dirname($ifile), UNLINK => $dry_run);
+ my $line = 0;
+ while (<$ifd>) {
+ chomp;
+ ++$line;
+ if ($insert_line && $line == $insert_line) {
+ printlog(L_NOTICE, "editing $ifile (line $line)");
+ addts $ofd;
+ print $ofd "$stmt\n";
+ $insert_line = undef;
+ }
+ print $ofd "$_\n";
+ }
+ if ($insert_line) {
+ printlog(L_NOTICE, "editing $ifile (append)");
+ addts $ofd;
+ print $ofd "$stmt\n";
+ }
+ close $ofd;
+ file_replace($ifile, $ofd->filename) unless ($dry_run);
+}
+
+sub edit_snmpd_conf {
+ my ($command, $name, $stmt) = @_;
+ my $u = umask(077);
+ if (open(my $fd, '<', $name)) {
+ my ($found, $line, $endline) = scan_snmpd_conf($name, $fd);
+ if ($command == CMD_SETUP) {
+ if ($found) {
+ printlog(L_INFO, "$name:".($endline ? $endline : $line).": NetSNMP::Sendmail already enabled");
+ } else {
+ update_snmpd_conf($name, $fd, $line, $stmt);
+ push @updated_services, 'snmpd';
+ }
+ } elsif ($found) {
+ file_remline($name, $fd, $line, $endline);
+ push @updated_services, 'snmpd';
+ }
+ close $fd;
+ } else {
+ printlog(L_ERR, "can't open $name: $!");
+ exit(EX_FATAL);
+ }
+ umask($u);
+}
+
+sub check_file {
+ my $file = shift;
+ if (-f $file) {
+ if (! -r $file) {
+ printlog(L_ERR, "$file is not readable");
+ exit(EX_FATAL);
+ }
+ } else {
+ printlog(L_ERR, "$file does not exist");
+ exit(EX_FATAL);
+ }
+}
+
+# Check if NetSNMP::Sendmail is available.
+# To avoid namespace contamination, do it in a subprocess.
+# The module requires SmtpAgent.pm, whic spits out lots of messages
+# to STDERR when loaded outside of snmpd, so first redirect stderr
+# to /dev/null.
+sub check_module {
+ my $pid = fork();
+ die "fork failed" unless defined $pid;
+ if ($pid == 0) {
+ open(STDERR, '>', '/dev/null');
+ require NetSNMP::Sendmail;
+ exit 0;
+ }
+ wait;
+ if ($?) {
+ printlog(L_ERR, "NetSNMP::Sendmail doesn't seem to be installed");
+ exit(EX_FATAL);
+ }
+}
+
+sub scan_sendmail_mc {
+ my $fd = shift;
+ my $name;
+ my $last_nl;
+ my $comline;
+ my $line = 0;
+ while (<$fd>) {
+ $line++;
+ $last_nl = chomp;
+ s/^\s+//;
+
+ if (/$my_ts_rx/) {
+ $comline = $line;
+ next;
+ }
+ if (/^define\(\s*`?STATUS_FILE'?\s*,\s*`?(.+?)'?\s*\)/) {
+ $name = $1;
+ last
+ }
+ }
+
+ return ($name, $last_nl,
+ ($comline && $comline + 1 == $line) ? ($comline, $line) : ($line));
+}
+
+sub edit_sendmail_mc {
+ my ($command, $file, $default_statfile) = @_;
+ if (open(my $fd, '+<', $file)) {
+ my $need_make;
+ my ($statfile, $last_nl, $line, $endline) = scan_sendmail_mc($fd);
+ if ($command == CMD_SETUP) {
+ if ($statfile) {
+ printlog(L_INFO,
+ "$file:".($endline ? $endline : $line).
+ ": status file $statfile already enabled");
+ } else {
+ $statfile = $default_statfile;
+ printlog(L_NOTICE, "editing $file");
+ unless ($dry_run) {
+ seek($fd, 0, SEEK_END) or die "seek: $!";
+ print $fd "\n" unless $last_nl;
+ addts $fd;
+ print $fd "define(`STATUS_FILE', `$statfile')\n";
+ }
+ push @updated_services, 'sendmail';
+ $need_make = !$dry_run;
+ }
+
+ if (-f $statfile) {
+ printlog(L_INFO, "$statfile exists");
+ } else {
+ printlog(L_NOTICE, "creating $statfile");
+ unless ($dry_run) {
+ if (open($fd, '>', $statfile)) {
+ close($fd);
+ } else {
+ warn "failed to create $statfile: $!";
+ }
+ }
+ }
+ } elsif ($statfile) {
+ if ($endline) {
+ file_remline($file, $fd, $line, $endline);
+ push @updated_services, 'sendmail';
+ $need_make = !$dry_run;
+ } else {
+ printlog(L_INFO,
+ "$file:$line: retaining status file setup: not configured by $0");
+ }
+ }
+ close $fd;
+
+ if ($need_make) {
+ my $sendmail_dir = dirname($file);
+ printlog(L_NOTICE, "running make in $sendmail_dir");
+ system("make "
+ . ($dry_run ? '-n ' : '')
+ . "-C $sendmail_dir");
+ }
+ } else {
+ printlog(L_ERR, "can't open $file: $!");
+ exit(EX_FATAL);
+ }
+}
+
+# Main
+my $snmpd_conf = '/etc/snmp/snmpd.conf';
+my $sendmail_mc = '/etc/mail/sendmail.mc';
+my $sendmail_statfile = '/etc/mail/sendmail.st';
+my $sendmail_bindir;
+
+my $command = CMD_SETUP;
+
+GetOptions('quiet|q+' => \$suppress_level,
+ 'dry-run|n' => \$dry_run,
+ 'status-file=s' => \$sendmail_statfile,
+ 'bindir=s' => \$sendmail_bindir,
+ 'restart=s' => sub {
+ my ($name,$cmd) = split /=/, $_[1], 2;
+ $restart_override{$name} = $cmd;
+ },
+ 'configure' => sub { $command = CMD_SETUP },
+ 'deconfigure' => sub { $command = CMD_REMOVE },
+ 'help' => sub {
+ pod2usage(-exitstatus => EX_OK, -verbose => 2);
+ },
+ 'usage' => sub {
+ pod2usage(-exitstatus => EX_OK, -verbose => 0);
+ }
+) or pod2usage(-exitstatus => EX_USAGE, -verbose => 0, -output => \*STDERR);
+
+pod2usage(-exitstatus => EX_USAGE, -verbose => 0, -output => \*STDERR)
+ if @ARGV;
+
+if ($suppress_level > MAX_SUPPRESS_LEVEL) {
+ $suppress_level = MAX_SUPPRESS_LEVEL;
+}
+
+check_module;
+check_file($snmpd_conf);
+check_file($sendmail_mc);
+check_file('/etc/mail/Makefile');
+
+unless ($sendmail_bindir) {
+ if (-d "/usr/lib/sm.bin") {
+ $sendmail_bindir = "/usr/lib/sm.bin";
+ }
+}
+
+my $stmt = 'perl use NetSNMP::Sendmail';
+if ($sendmail_bindir) {
+ $stmt .= ' qw(:config bindir /usr/lib/sm.bin)';
+}
+$stmt .= ';';
+
+edit_sendmail_mc($command, $sendmail_mc, $sendmail_statfile);
+edit_snmpd_conf($command, $snmpd_conf, $stmt);
+
+map { restart_service($_) } @updated_services;
+
+exit(@updated_services ? EX_OK : EX_UNCHANGED);
+
+__END__
+=head1 NAME
+
+netsnmp-sendmail-setup - sets up Sendmail monitoring via SNMP
+
+=head1 SYNOPSIS
+
+B<netsnmp-sendmail-setup>
+[B<-nq>]
+[B<--bindir=I<DIR>>]
+[B<--configure>]
+[B<--deconfigure>]
+[B<--dry-run>]
+[B<--status-file=I<FILE>>]
+[B<--quiet>]
+[B<--restart=I<service>=I<command>>]
+
+B<netsnmp-sendmail-setup> B<--help> | B<--usage>
+
+=head1 DESCRIPTION
+
+Sets up B<sendmail> and B<snmpd> for obtaining Sendmail statistics via
+SNMP. First, it checks whether the Sendmail configuration source
+F</etc/mail/sendmail.mc> contains the B<STATUS_FILE> clause and adds it
+if not. Then, it creates the status file and runs B<make> in the F</etc/mail>
+directory. Finally, the file F</etc/snmp/snmpd.conf> is scanned for the
+B<perl use NetSNMP::Sendmail> statement. It is added if not already present.
+Each added configuration line is preceded by a comment stating that it
+was added by the script.
+
+When run with the B<--deconfigure> option, the reverse operation is
+performed. The B<NetSNMP::Sendmail> configuration statement is removed
+from the snmpd configuration unconditionally. The B<STATUS_FILE> clause
+is removed from F</etc/mail/sendmail.mc> only if it is preceded by the
+B<netsnmp-sendmail-setup> comment marker. The status file itself is
+never removed.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--bindir=I<DIR>>
+
+Some installations place Sendmail binaries in a separate directory, which
+is not included in the B<$PATH> environment variable. Use this option to
+inform B<NetSNMP::Sendmail> about this.
+
+Notice for the users of Debian-based systems: the F</usr/lib/sm.bin>
+directory is picked up automatically.
+
+=item B<--configure>
+
+A no-op option included for symmetry with B<--deconfigure>.
+
+=item B<--deconfigure>
+
+Remove the configuration statements previously added to the snmdp and
+sendmail configuration files.
+
+=item B<-n>, B<--dry-run>
+
+Dry run mode. Don't modify any files, just print what would have been done
+and exit with the appropriate error code (see B<EXIT STATUS> section).
+
+Use the B<--quiet> option to control the amount of data printed.
+
+=item B<-q>, B<--quiet>
+
+Quiet mode. When used once, suppresses informative output. When used twice,
+suppresses both informative output and notification messages about modified
+files.
+
+=item B<--restart=I<service>=I<command>>
+
+Use I<command> to restart system service I<service> (either B<snmpd> or
+B<sendmail>). Use B<--restart=I<service>=no> to skip restarting this
+particular I<service>.
+
+In the absence of this option, B<netsnmp-sendmail-setup> uses the first
+available command from the following list:
+
+ systemctl restart $service
+ service $service restart
+ /etc/init.d/$service restart
+ /etc/rc.d/$service restart
+
+=item B<--status-file=I<FILE>>
+
+Name of the Sendmail status file to use when generating the
+B<define(STATUS_FILE)> statement in the Sendmail configuration file.
+
+=item B<--help>
+
+Displays short help message.
+
+=item B<--usage>
+
+Displaye short usage message.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=item F</etc/mail/Makefile>
+
+This file is supposed to recreate the B<sendmail.cf> file from B<sendmail.mc>
+if no special goal is given.
+
+=item F</etc/snmp/snmpd.conf>
+
+Default B<snmpd> configuration file. This file must exist.
+
+=item F</etc/mail/sendmail.mc>
+
+Default source file for creating B<sendmail.cf>.
+
+=item F</etc/mail/sendmail.st>
+
+Default statistics file to use. Can be changed using the B<--status-file>
+option.
+
+=item F</usr/lib/sm.bin>
+
+Default directory for Sendmail binaries on Debian-based installations. If
+exists, it will be used in the B<NetSNMP::Sendmail> configuration.
+
+This can be changed using the B<--bindir> command line option.
+
+=back
+
+=head1 EXIT STATUS
+
+=over 4
+
+=item B<0>
+
+Success.
+
+=item B<1>
+
+Success, no modification was necessary.
+
+=item B<2>
+
+Fatal error occurred.
+
+=item B<64>
+
+Command line usage error.
+
+=back
+
+=head1 SEE ALSO
+
+B<NetSNMP::Sendmail>(3).
+
+=head1 BUGS
+
+The Sendmail configuration directory and the name of the B<snmpd>
+configuration file are hardcoded.
+
+The command relies on B<make -C /etc/mail> to create F<sendmail.cf> from
+F<sendmail.mc>.
+
+=cut
diff --git a/sendmail.pl b/sendmail.pl
index e5e8df4..a1795a8 100644
--- a/sendmail.pl
+++ b/sendmail.pl
@@ -20,8 +20,8 @@ NetSNMP::Sendmail - NetSNMP plugin for Sendmail statistics
=head1 SYNOPSIS
-B<perl use NetSNMP::Sendmail qw (:config bindir /usr/bin/sm.bin);>
-
+B<perl use NetSNMP::Sendmail qw (:config bindir /usr/bin/sm.bin);>
+
=head1 DESCRIPTION
A perl plugin for B<net-snmp> that provides access to Sendmail
@@ -51,7 +51,7 @@ passed as a hash to the B<Configure> function, or passed with the
B<use> statement following the B<:config> marker. The following
options are defined:
-=over 4
+=over 4
=item B<bindir>
@@ -63,30 +63,30 @@ using B<mailq> and B<mailstats> keywords.
=item B<cf>
Absolute name of the Sendmail configuaration file. Defaults to
-F</etc/mail/sendmail.cf>.
-
+F</etc/mail/sendmail.cf>.
+
=item B<mailstats>
-Name of the B<mailstats> binary. Default is B<mailstats>.
-
+Name of the B<mailstats> binary. Default is B<mailstats>.
+
=item B<mailq>
-Name of the B<mailq> binary. Default is B<mailq>.
-
+Name of the B<mailq> binary. Default is B<mailq>.
+
=item B<mailstats_ttl>
Time in seconds during which the result of the recent invocation of
B<mailstats>(8) is cached. Default is 10.
-
+
=item B<mailq_ttl>
Time in seconds during which the result of the recent invocation of
B<mailq>(1) is cached. Default is 10.
-=back
+=back
=head2 OIDS
-
+
The MIB is defined in file SENDMAIL-STATS.txt, which is distributed along
with this module. The following OIDs are defined:
@@ -106,101 +106,101 @@ the following elements (I<N> stands for the row index):
=item B<queueName.>I<N>
Name of the queue group.
-
+
=item B<queueDirectory.>I<N>
Queue directory.
-
-=item B<queueMessages.>I<N>
-Number of messages in that queue group.
-
-=back
-
+=item B<queueMessages.>I<N>
+
+Number of messages in that queue group.
+
+=back
+
=item B<mailerTable>
This OID provides a conceptual table of mailers with the corresponding
statistics. Each row has the following elements (I<N> stands for the
row index):
-=over 4
-
+=over 4
+
=item B<mailerName.>I<N>
Name of the mailer, as set in its definition in F<sendmail.cf>.
-
+
=item B<mailerMessagesFrom.>I<N>
-Number of outgoing messages sent using this mailer.
-
+Number of outgoing messages sent using this mailer.
+
=item B<mailerKBytesFrom.>I<N>
Number of kilobytes in outgoing messages sent using this mailer.
-
+
=item B<mailerMessagesTo.>I<N>
Number of messages received using this mailer.
-
+
=item B<mailerKBytesTo.>I<N>
Number of kilobytes in messages received using this mailer.
-
+
=item B<mailerMessagesRejected.>I<N>
-Number of messages rejected by this mailer.
-
+Number of messages rejected by this mailer.
+
=item B<mailerMessagesDiscarded.>I<N>
-Number of messages discarded by this mailer.
-
+Number of messages discarded by this mailer.
+
=item B<mailerMessagesQuarantined.>I<N>
Number of messages put in quarantine by this mailer.
-
+
=back
-
+
=item B<totalMessagesFrom.0>
Total number of outgoing messages.
-
+
=item B<totalKBytesFrom.0>
Total number of outgoing kilobytes.
-
+
=item B<totalMessagesTo.0>
Total number of incoming messages.
-
+
=item B<totalKBytesTo.0>
Total number of incoming kilobytes.
-
+
=item B<totalMessagesRejected.0>
Total number of rejected messages.
-
+
=item B<totalMessagesDiscarded.0>
Total number of discarded messages.
-
+
=item B<totalMessagesQuarantined.0>
Total number of messages put in quarantine.
-
+
=item B<connectionMessagesFrom.0>
Number of messages sent over TCP connections.
-
+
=item B<connectionMessagesTo.0>
Number of messages received over TCP connections.
-
+
=item B<connectionMessagesRejected.0>
Number of messages that arrived over TCP connections and were rejected.
-=back
+=back
=head1 SEE ALSO
@@ -213,11 +213,11 @@ GPLv3+: GNU GPL version 3 or later, see
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
-
+
=head1 AUTHOR
-Sergey Poznyakoff <gray@gnu.org>.
-
+Sergey Poznyakoff <gray@gnu.org>.
+
=cut
package NetSNMP::Sendmail;
@@ -226,7 +226,7 @@ use strict;
use warnings;
use feature 'state';
use NetSNMP::agent::Support;
-use NetSNMP::agent (':all');
+use NetSNMP::agent (':all');
use NetSNMP::ASN (':all');
use Carp;
@@ -235,7 +235,7 @@ use Data::Dumper;
require Exporter;
our @ISA = qw(Exporter);
-our $VERSION = "0.95";
+our $VERSION = "0.97";
our @EXPORT_OK = qw(&Configure);
@@ -253,7 +253,7 @@ my %config = (
mailstats_ttl => \$ttl{mailstats},
mailq => \$mailq_bin,
mailstats => \$mailstats_bin,
- cf => \$sendmail_cf,
+ cf => \$sendmail_cf,
bindir => sub {
$mailq_bin = "$_[1]/$mailq_bin" if $mailq_bin !~ m#^/#;
$mailstats_bin = "$_[1]/$mailstats_bin" if $mailstats_bin !~ m#^/#;
@@ -324,7 +324,7 @@ sub readcf {
my $name = $1;
# Collect parameters. So far only P is actially used.
my %h = map { if (/([a-zA-Z])[^=]*=(.+)/) {
- if (exists($qopt{$1})) {
+ if (exists($qopt{$1})) {
$qopt{$1} => $2;
} else {
()
@@ -332,7 +332,7 @@ sub readcf {
} else {
()
}
- } split /,\s*/, $2;
+ } split /,\s*/, $2;
if (exists($h{queueDirectory})) {
my $dir = $h{queueDirectory};
delete $h{$dir};
@@ -356,25 +356,27 @@ sub queue_stats {
my $now = time();
return %tmp if $now - $timestamp{mailq} < $ttl{mailq};
$timestamp{mailq} = $now;
- %tmp = ();
}
- open(my $fd, '-|', $mailq_bin)
- or die "can't run $mailq_bin: $!";
- while (<$fd>) {
- chomp;
- if (/^(^\S+) is empty/) {
- push @{$tmp{q}}, { queueName => $qgroup{$1}{queueName} || "",
- queueDirectory => $1,
- queueMessages => 0 };
- } elsif (/^\s*(\S+) \((\d+) requests\)/) {
- push @{$tmp{q}}, { queueName => $qgroup{$1}{queueName} || "",
- queueDirectory => $1,
- queueMessages => $2 };
- } elsif (/Total requests:\s+(\d+)\s*$/) {
- $tmp{total} = $1
+ %tmp = ();
+ if (open(my $fd, '-|', $mailq_bin)) {
+ while (<$fd>) {
+ chomp;
+ if (/^(^\S+) is empty/) {
+ push @{$tmp{q}}, { queueName => $qgroup{$1}{queueName} || "",
+ queueDirectory => $1,
+ queueMessages => 0 };
+ } elsif (/^\s*(\S+) \((\d+) requests\)/) {
+ push @{$tmp{q}}, { queueName => $qgroup{$1}{queueName} || "",
+ queueDirectory => $1,
+ queueMessages => $2 };
+ } elsif (/Total requests:\s+(\d+)\s*$/) {
+ $tmp{total} = $1
+ }
}
+ close($fd);
+ } else {
+ warn "can't run $mailq_bin: $!";
}
- close($fd);
return %tmp;
}
@@ -387,45 +389,47 @@ sub mailer_stats {
$timestamp{mailstats} = $now;
%mstats = ();
- debug("calling $mailstats_bin");
- open(my $fd, '-|', "$mailstats_bin -P")
- or die "can't run $mailstats_bin: $!";
- my $line = 0;
+ debug("calling $mailstats_bin");
+ if (open(my $fd, '-|', "$mailstats_bin -P")) {
+ my $line = 0;
- while (<$fd>) {
- ++$line;
+ while (<$fd>) {
+ ++$line;
+
+ next if $line == 1;
- next if $line == 1;
-
- s/^\s+//;
+ s/^\s+//;
# msgsfr bytes_from msgsto bytes_to msgsrej msgsdis msgsqur Mailer
- my @a = split /\s+/;
- if ($a[0] eq 'T') {
- @{$mstats{totals}}{('totalMessagesFrom',
- 'totalKBytesFrom',
- 'totalMessagesTo',
- 'totalKBytesTo',
- 'totalMessagesRejected',
- 'totalMessagesDiscarded',
- 'totalMessagesQuarantined')} = @a[1..7];
- } elsif ($a[0] eq 'C') {
- @{$mstats{conn}}{('connectionMessagesFrom',
- 'connectionMessagesTo',
- 'connectionMessagesRejected')} = @a[1..3];
- } else {
- my %h;
- @h{('mailerMessagesFrom',
- 'mailerKBytesFrom',
- 'mailerMessagesTo',
- 'mailerKBytesTo',
- 'mailerMessagesRejected',
- 'mailerMessagesDiscarded',
- 'mailerMessagesQuarantined',
- 'mailerName')} = @a[1..8];
- push @{$mstats{mailer}}, \%h;
+ my @a = split /\s+/;
+ if ($a[0] eq 'T') {
+ @{$mstats{totals}}{('totalMessagesFrom',
+ 'totalKBytesFrom',
+ 'totalMessagesTo',
+ 'totalKBytesTo',
+ 'totalMessagesRejected',
+ 'totalMessagesDiscarded',
+ 'totalMessagesQuarantined')} = @a[1..7];
+ } elsif ($a[0] eq 'C') {
+ @{$mstats{conn}}{('connectionMessagesFrom',
+ 'connectionMessagesTo',
+ 'connectionMessagesRejected')} = @a[1..3];
+ } else {
+ my %h;
+ @h{('mailerMessagesFrom',
+ 'mailerKBytesFrom',
+ 'mailerMessagesTo',
+ 'mailerKBytesTo',
+ 'mailerMessagesRejected',
+ 'mailerMessagesDiscarded',
+ 'mailerMessagesQuarantined',
+ 'mailerName')} = @a[1..8];
+ push @{$mstats{mailer}}, \%h;
+ }
}
+ close($fd);
+ } else {
+ warn "can't run $mailstats_bin: $!";
}
- close($fd);
return %mstats;
}
@@ -452,7 +456,7 @@ sub check_queueTable {
sub next_queueTable {
my ($len, $oid) = @_;
-
+
my $idx = getOidElement($oid, $len);
my %qstats = queue_stats();
++$idx;
@@ -478,7 +482,7 @@ sub check_mailerTable {
sub next_mailerTable {
my ($len, $oid) = @_;
-
+
my $idx = getOidElement($oid, $len);
my %mstats = mailer_stats();
@@ -500,4 +504,3 @@ sub connection_table_get {
my %mstats = mailer_stats();
return $mstats{conn}->{$name};
}
-

Return to:

Send suggestions and report system problems to the System administrator.