aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-06-18 12:41:32 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-06-18 12:41:32 +0300
commitfb0cd0f84d0ecfba0c5a5b0045eee0ede0477a0e (patch)
tree30229f5483a036ffc3c21e429d7caa94587e1478
parente30ddffa198dedeed50c1d9e2bbb98cabbec2eae (diff)
downloadnetsnmp-sendmail-fb0cd0f84d0ecfba0c5a5b0045eee0ede0477a0e.tar.gz
netsnmp-sendmail-fb0cd0f84d0ecfba0c5a5b0045eee0ede0477a0e.tar.bz2
Update netsnmp-sendmail-setup
* netsnmp-sendmail-setup: Add --deconfigure option: remove previosly added configuration statements.
-rwxr-xr-xnetsnmp-sendmail-setup213
1 files changed, 153 insertions, 60 deletions
diff --git a/netsnmp-sendmail-setup b/netsnmp-sendmail-setup
index 86e8002..5e49ad6 100755
--- a/netsnmp-sendmail-setup
+++ b/netsnmp-sendmail-setup
@@ -1,7 +1,7 @@
1#!/bin/sh 1#!/bin/sh
2#! -*-perl-*- 2#! -*-perl-*-
3# This file is part of NetSNMP::Sendmail 3# This file is part of NetSNMP::Sendmail
4# Copyright (C) 2019 Sergey Poznyakoff <gray@gnu.org> 4# Copyright (C) 2019-2020 Sergey Poznyakoff <gray@gnu.org>
5# 5#
6# This program is free software; you can redistribute it and/or modify 6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by 7# it under the terms of the GNU General Public License as published by
@@ -35,6 +35,8 @@ sub addts {
35 . "\n"; 35 . "\n";
36} 36}
37 37
38my $my_ts_rx = qr{^# Line added by $0 at };
39
38use constant { 40use constant {
39 EX_OK => 0, # Success 41 EX_OK => 0, # Success
40 EX_UNCHANGED => 1, # Files not changed 42 EX_UNCHANGED => 1, # Files not changed
@@ -42,9 +44,13 @@ use constant {
42 EX_USAGE => 64 # Usage error 44 EX_USAGE => 64 # Usage error
43}; 45};
44 46
47use constant {
48 CMD_SETUP => 0,
49 CMD_REMOVE => 1
50};
51
45my $suppress_level = 0; 52my $suppress_level = 0;
46my $dry_run; 53my $dry_run;
47my $changed = 0;
48my @updated_services; 54my @updated_services;
49 55
50use constant { 56use constant {
@@ -54,7 +60,7 @@ use constant {
54 L_ERR => 3 60 L_ERR => 3
55}; 61};
56 62
57use constant MAX_SUPPRESS_LEVEL => L_NOTICE; 63use constant MAX_SUPPRESS_LEVEL => L_WARN;
58 64
59sub printlog { 65sub printlog {
60 my $level = shift; 66 my $level = shift;
@@ -96,6 +102,41 @@ sub restart_service {
96 } 102 }
97} 103}
98 104
105sub file_replace {
106 my ($file, $newfile) = @_;
107 my $bk = "$file~";
108 unlink $bk if -e $bk;
109 rename $file, $bk or die "can't rename $file to $bk: $!";
110 unless (rename $newfile, $file) {
111 printlog(L_WARN,
112 "can't rename $newfile to $file: $!; restoring from backup");
113 unless (rename $bk, $file) {
114 printlog(L_ERR, "failed to rename $bk to $file: $!");
115 exit(EX_FATAL);
116 }
117 }
118}
119
120sub file_remline {
121 my ($file, $fd, $line, $endline) = @_;
122 $endline //= $line;
123 printlog(L_NOTICE,
124 ($endline == $line) ? "editing $file: removing line $line"
125 : "editing $file: removing lines $line-$endline");
126 return if $dry_run;
127 my $ofd = File::Temp->new(DIR => dirname($file), UNLINK => $dry_run);
128 seek($fd, 0, SEEK_SET) or die "seek $file: $!";
129 my $ln = 0;
130 while (<$fd>) {
131 $ln++;
132 next if ($line <= $ln && $ln <= $endline);
133 print $ofd $_;
134 }
135 close $ofd;
136 close $fd;
137 file_replace($file, $ofd->filename);
138}
139
99sub scan_snmpd_conf { 140sub scan_snmpd_conf {
100 my ($file, $fd) = @_; 141 my ($file, $fd) = @_;
101 142
@@ -107,15 +148,25 @@ sub scan_snmpd_conf {
107 ++$line; 148 ++$line;
108 chomp; 149 chomp;
109 s/^\s+//; 150 s/^\s+//;
151
152 if (/$my_ts_rx/) {
153 $comline = $line;
154 next;
155 }
156
110 if (/^perl\s+use\s+NetSNMP::Sendmail/) { 157 if (/^perl\s+use\s+NetSNMP::Sendmail/) {
111 printlog(L_INFO, "$file:$line: NetSNMP::Sendmail already enabled"); 158 if ($comline && $comline + 1 == $line) {
112 return; 159 return (1, $comline, $line);
160 } else {
161 return (1, $line);
162 }
113 } 163 }
164
114 if (/^perl\s+use/) { 165 if (/^perl\s+use/) {
115 $insert_line = $line; 166 $insert_line = $line;
116 } 167 }
117 } 168 }
118 return $insert_line || $line + 1; 169 return (0, $insert_line || $line + 1);
119} 170}
120 171
121sub update_snmpd_conf { 172sub update_snmpd_conf {
@@ -140,30 +191,25 @@ sub update_snmpd_conf {
140 addts $ofd; 191 addts $ofd;
141 print $ofd "$stmt\n"; 192 print $ofd "$stmt\n";
142 } 193 }
143 $changed++; 194 close $ofd;
144 return $ofd; 195 file_replace($ifile, $ofd->filename) unless ($dry_run);
145} 196}
146 197
147sub edit_snmpd_conf { 198sub edit_snmpd_conf {
148 my ($name, $stmt) = @_; 199 my ($command, $name, $stmt) = @_;
149 my $u = umask(077); 200 my $u = umask(077);
150 if (open(my $fd, '<', $name)) { 201 if (open(my $fd, '<', $name)) {
151 if (defined(my $insert_line = scan_snmpd_conf($name, $fd))) { 202 my ($found, $line, $endline) = scan_snmpd_conf($name, $fd);
152 my $fh = update_snmpd_conf($name, $fd, $insert_line, $stmt); 203 if ($command == CMD_SETUP) {
153 unless ($dry_run) { 204 if ($found) {
154 my $bk = "$name~"; 205 printlog(L_INFO, "$name:".($endline ? $endline : $line).": NetSNMP::Sendmail already enabled");
155 unlink $bk if -e $bk; 206 } else {
156 rename $name, $bk or die "can't rename $name to $bk: $!"; 207 update_snmpd_conf($name, $fd, $line, $stmt);
157 unless (rename $fh->filename, $name) { 208 push @updated_services, 'snmpd';
158 printlog(L_WARN,
159 "can't rename ".$fh->filename." to $name: $!; restoring from backup");
160 unless (rename $bk, $name) {
161 printlog(L_ERR, "failed to rename $bk to $name: $!");
162 exit(EX_FATAL);
163 }
164 }
165 } 209 }
166 push @updated_services, 'snmpd'; 210 } elsif ($found) {
211 file_remline($name, $fd, $line, $endline);
212 push @updated_services, 'snmpd';
167 } 213 }
168 close $fd; 214 close $fd;
169 } else { 215 } else {
@@ -210,50 +256,73 @@ sub scan_sendmail_mc {
210 my $fd = shift; 256 my $fd = shift;
211 my $name; 257 my $name;
212 my $last_nl; 258 my $last_nl;
259 my $comline;
260 my $line = 0;
213 while (<$fd>) { 261 while (<$fd>) {
262 $line++;
214 $last_nl = chomp; 263 $last_nl = chomp;
215 s/^\s+//; 264 s/^\s+//;
265
266 if (/$my_ts_rx/) {
267 $comline = $line;
268 next;
269 }
216 if (/^define\(\s*`?STATUS_FILE'?\s*,\s*`?(.+?)'?\s*\)/) { 270 if (/^define\(\s*`?STATUS_FILE'?\s*,\s*`?(.+?)'?\s*\)/) {
217 $name = $1; 271 $name = $1;
272 last
218 } 273 }
219 } 274 }
220 return ($name, $last_nl); 275
276 return ($name, $last_nl,
277 ($comline && $comline + 1 == $line) ? ($comline, $line) : ($line));
221} 278}
222 279
223sub edit_sendmail_mc { 280sub edit_sendmail_mc {
224 my $file = shift; 281 my ($command, $file, $default_statfile) = @_;
225 if (open(my $fd, '+<', $file)) { 282 if (open(my $fd, '+<', $file)) {
226 my $need_make; 283 my $need_make;
227 my ($statfile, $last_nl) = scan_sendmail_mc($fd); 284 my ($statfile, $last_nl, $line, $endline) = scan_sendmail_mc($fd);
228 if ($statfile) { 285 if ($command == CMD_SETUP) {
229 printlog(L_INFO, "status file $statfile"); 286 if ($statfile) {
230 } else { 287 printlog(L_INFO,
231 $statfile = shift; 288 "$file:".($endline ? $endline : $line).
232 printlog(L_NOTICE, "editing $file"); 289 ": status file $statfile already enabled");
233 unless ($dry_run) { 290 } else {
234 seek($fd, 0, SEEK_END) or die "seek: $!"; 291 $statfile = $default_statfile;
235 print $fd "\n" unless $last_nl; 292 printlog(L_NOTICE, "editing $file");
236 addts $fd; 293 unless ($dry_run) {
237 print $fd "define(`STATUS_FILE', `$statfile')\n"; 294 seek($fd, 0, SEEK_END) or die "seek: $!";
295 print $fd "\n" unless $last_nl;
296 addts $fd;
297 print $fd "define(`STATUS_FILE', `$statfile')\n";
298 }
299 push @updated_services, 'sendmail';
300 $need_make = !$dry_run;
238 } 301 }
239 push @updated_services, 'sendmail';
240 $need_make = 1;
241 $changed++;
242 }
243 close $fd;
244 302
245 if (-f $statfile) { 303 if (-f $statfile) {
246 printlog(L_INFO, "$statfile exists"); 304 printlog(L_INFO, "$statfile exists");
247 } else { 305 } else {
248 printlog(L_NOTICE, "creating $statfile"); 306 printlog(L_NOTICE, "creating $statfile");
249 unless ($dry_run) { 307 unless ($dry_run) {
250 if (open($fd, '>', $statfile)) { 308 if (open($fd, '>', $statfile)) {
251 close($fd); 309 close($fd);
252 } else { 310 } else {
253 warn "failed to create $statfile: $!"; 311 warn "failed to create $statfile: $!";
312 }
254 } 313 }
255 } 314 }
315 } elsif ($statfile) {
316 if ($endline) {
317 file_remline($file, $fd, $line, $endline);
318 push @updated_services, 'sendmail';
319 $need_make = !$dry_run;
320 } else {
321 printlog(L_INFO,
322 "$file:$line: retaining status file setup: not configured by $0");
323 }
256 } 324 }
325 close $fd;
257 326
258 if ($need_make) { 327 if ($need_make) {
259 my $sendmail_dir = dirname($file); 328 my $sendmail_dir = dirname($file);
@@ -274,14 +343,18 @@ my $sendmail_mc = '/etc/mail/sendmail.mc';
274my $sendmail_statfile = '/etc/mail/sendmail.st'; 343my $sendmail_statfile = '/etc/mail/sendmail.st';
275my $sendmail_bindir; 344my $sendmail_bindir;
276 345
346my $command = CMD_SETUP;
347
277GetOptions('quiet|q+' => \$suppress_level, 348GetOptions('quiet|q+' => \$suppress_level,
278 'dry-run|n' => \$dry_run, 349 'dry-run|n' => \$dry_run,
279 'status-file=s' => \$sendmail_statfile, 350 'status-file=s' => \$sendmail_statfile,
280 'bindir=s' => \$sendmail_bindir, 351 'bindir=s' => \$sendmail_bindir,
281 'restart=s' => sub { 352 'restart=s' => sub {
282 my ($name,$command) = split /=/, $_[1], 2; 353 my ($name,$cmd) = split /=/, $_[1], 2;
283 $restart_override{$name} = $command; 354 $restart_override{$name} = $cmd;
284 }, 355 },
356 'configure' => sub { $command = CMD_SETUP },
357 'deconfigure' => sub { $command = CMD_REMOVE },
285 'help' => sub { 358 'help' => sub {
286 pod2usage(-exitstatus => EX_OK, -verbose => 2); 359 pod2usage(-exitstatus => EX_OK, -verbose => 2);
287 }, 360 },
@@ -298,9 +371,9 @@ if ($suppress_level > MAX_SUPPRESS_LEVEL) {
298} 371}
299 372
300check_module; 373check_module;
301check_file $snmpd_conf; 374check_file($snmpd_conf);
302check_file $sendmail_mc; 375check_file($sendmail_mc);
303check_file '/etc/mail/Makefile'; 376check_file('/etc/mail/Makefile');
304 377
305unless ($sendmail_bindir) { 378unless ($sendmail_bindir) {
306 if (-d "/usr/lib/sm.bin") { 379 if (-d "/usr/lib/sm.bin") {
@@ -314,12 +387,12 @@ if ($sendmail_bindir) {
314} 387}
315$stmt .= ';'; 388$stmt .= ';';
316 389
317edit_sendmail_mc($sendmail_mc, $sendmail_statfile); 390edit_sendmail_mc($command, $sendmail_mc, $sendmail_statfile);
318edit_snmpd_conf($snmpd_conf, $stmt); 391edit_snmpd_conf($command, $snmpd_conf, $stmt);
319 392
320map { restart_service($_) } @updated_services; 393map { restart_service($_) } @updated_services;
321 394
322exit($changed ? EX_OK : EX_UNCHANGED); 395exit(@updated_services ? EX_OK : EX_UNCHANGED);
323 396
324__END__ 397__END__
325=head1 NAME 398=head1 NAME
@@ -331,11 +404,13 @@ netsnmp-sendmail-setup - sets up Sendmail monitoring via SNMP
331B<netsnmp-sendmail-setup> 404B<netsnmp-sendmail-setup>
332[B<-nq>] 405[B<-nq>]
333[B<--bindir=I<DIR>>] 406[B<--bindir=I<DIR>>]
407[B<--configure>]
408[B<--deconfigure>]
334[B<--dry-run>] 409[B<--dry-run>]
335[B<--status-file=I<FILE>>] 410[B<--status-file=I<FILE>>]
336[B<--quiet>] 411[B<--quiet>]
337[B<--restart=I<service>=I<command>>] 412[B<--restart=I<service>=I<command>>]
338 413
339B<netsnmp-sendmail-setup> B<--help> | B<--usage> 414B<netsnmp-sendmail-setup> B<--help> | B<--usage>
340 415
341=head1 DESCRIPTION 416=head1 DESCRIPTION
@@ -346,6 +421,15 @@ F</etc/mail/sendmail.mc> contains the B<STATUS_FILE> clause and adds it
346if not. Then, it creates the status file and runs B<make> in the F</etc/mail> 421if not. Then, it creates the status file and runs B<make> in the F</etc/mail>
347directory. Finally, the file F</etc/snmp/snmpd.conf> is scanned for the 422directory. Finally, the file F</etc/snmp/snmpd.conf> is scanned for the
348B<perl use NetSNMP::Sendmail> statement. It is added if not already present. 423B<perl use NetSNMP::Sendmail> statement. It is added if not already present.
424Each added configuration line is preceded by a comment stating that it
425was added by the script.
426
427When run with the B<--deconfigure> option, the reverse operation is
428performed. The B<NetSNMP::Sendmail> configuration statement is removed
429from the snmpd configuration unconditionally. The B<STATUS_FILE> clause
430is removed from F</etc/mail/sendmail.mc> only if it is preceded by the
431B<netsnmp-sendmail-setup> comment marker. The status file itself is
432never removed.
349 433
350=head1 OPTIONS 434=head1 OPTIONS
351 435
@@ -360,6 +444,15 @@ inform B<NetSNMP::Sendmail> about this.
360Notice for the users of Debian-based systems: the F</usr/lib/sm.bin> 444Notice for the users of Debian-based systems: the F</usr/lib/sm.bin>
361directory is picked up automatically. 445directory is picked up automatically.
362 446
447=item B<--configure>
448
449A no-op option included for symmetry with B<--deconfigure>.
450
451=item B<--deconfigure>
452
453Remove the configuration statements previously added to the snmdp and
454sendmail configuration files.
455
363=item B<-n>, B<--dry-run> 456=item B<-n>, B<--dry-run>
364 457
365Dry run mode. Don't modify any files, just print what would have been done 458Dry run mode. Don't modify any files, just print what would have been done

Return to:

Send suggestions and report system problems to the System administrator.