File Coverage

blib/lib/Mon/Protocol.pm
Criterion Covered Total %
statement 9 131 6.8
branch 0 32 0.0
condition 0 17 0.0
subroutine 3 16 18.7
pod 10 10 100.0
total 22 206 10.6


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Mon::Protocol - Methods for parsing / dumping a protocol block
4              
5             =head1 SYNOPSIS
6              
7             use Mon::Protocol;
8              
9             =head1 DESCRIPTION
10              
11              
12             =head1 METHODS
13              
14             =over 4
15              
16             =item new
17              
18             Creates a new object. A hash can be supplied which sets the
19             default values. An example which contains all of the variables
20             that you can initialize:
21              
22             $c = new Mon::Protocol;
23              
24             =item dump_data
25              
26             Returns the current internal structure as a string dump suitable for passing
27             to C.
28              
29             =item C
30              
31             Parses a command block (from begin_block to end_block), as generated by
32             dump_data.
33              
34             =item C(I)
35              
36             Sets or returns the type of the current command block. See @TYPES for valid
37             type codes.
38              
39             In the future, it is possible that this module will perform additional
40             checking based on the type, for now it is left to the application to interpret
41             this.
42              
43             =item C
44              
45             Returns an array containing all section names within the block.
46              
47             =item C(I)
48              
49             Returns a hash containing the key/value pairs of the specific section.
50              
51             =item C(I)
52              
53             Completely removes the specified section from the block.
54              
55             =item C(I,I<$hash_ref>)
56              
57             Adds the key/value pairs in the hash to the specified section.
58              
59             $foo->add_to_section("_hostgroup", { "ns1.baz.com" -> "ok" });
60              
61             =item C(I,I<$key>)
62              
63             Deletes the key/value pair from the section.
64              
65             $foo->delete_from_section("_hostgroup", "ns1.baz.com");
66              
67             =item C
68              
69             Should any of the functions return an error (-1), this function can be used to
70             retrieve a more elaborate error message and to reset the internal error state.
71              
72             =back
73              
74             =cut
75             #
76             # Perl module for parsing / dumping a mon protocol block
77             #
78             # $Id: Protocol.pm 1.3 Thu, 11 Jan 2001 08:42:17 -0800 trockij $
79             #
80             # Copyright (C) 1999 Lars Marowsky-Brée
81             #
82             # This program is free software; you can redistribute it and/or modify
83             # it under the terms of the GNU General Public License as published by
84             # the Free Software Foundation; either version 2 of the License, or
85             # (at your option) any later version.
86             #
87             # This program is distributed in the hope that it will be useful,
88             # but WITHOUT ANY WARRANTY; without even the implied warranty of
89             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90             # GNU General Public License for more details.
91             #
92             # You should have received a copy of the GNU General Public License
93             # along with this program; if not, write to the Free Software
94             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
95             #
96             #
97              
98             package Mon::Protocol;
99             require Exporter;
100             require 5.004;
101 1     1   1472 use IO::File;
  1         12141  
  1         193  
102 1     1   1087 use Socket;
  1         4410  
  1         681  
103 1     1   988 use Text::ParseWords;
  1         1447  
  1         1666  
104              
105             sub new;
106             sub dump_data;
107             sub parse_data;
108             sub type;
109             sub get_section;
110             sub get_section_list;
111             sub add_to_section;
112             sub delete_section;
113             sub delete_from_section;
114             sub error;
115             sub DESTROY;
116             sub _esc_str;
117             sub _un_esc_str;
118              
119             @ISA = qw(Exporter);
120             @EXPORT_OK = qw($VERSION @);
121              
122             $VERSION = "0.11";
123              
124             @TYPES = qw(cmd_monitor cmd_alert cmd_logger res_monitor res_alert res_logger);
125              
126             sub new {
127 0     0 1   my $proto = shift;
128 0   0       my $class = ref($proto) || $proto;
129 0           my $self = {};
130 0           my %vars = @_;
131              
132 0   0       $self->{'type'} = $vars{'type'} || "UNKNOWN";
133            
134 0           bless ($self, $class);
135 0           return $self;
136             }
137              
138              
139             sub dump_data {
140 0     0 1   my ($self) = shift;
141              
142 0           my ($tmp);
143              
144 0           $tmp.="begin_block=".$self->{'type'}."\n";
145              
146 0           my ($section);
147 0           foreach $section (sort keys %{$self->{'data'}}) {
  0            
148 0           $tmp.="begin=".$section."\n";
149              
150 0           my ($key,$data);
151              
152 0           while ( ($key,$data) = each %{$self->{'data'}->{$section}} ) {
  0            
153 0           $tmp .= "$key=". _esc_str ($data) . "\n";
154             }
155 0           $tmp.="end=".$section."\n";
156            
157             }
158            
159 0           $tmp.="end_block=".$self->{'type'}."\n";
160              
161 0           return $tmp;
162             }
163              
164              
165             sub parse_data {
166 0     0 1   my ($self) = shift;
167            
168 0           my ($raw) = @_;
169 0           my (@l) = split(/\n/o,$raw);
170            
171 0           my ($l,%tmp,$type);
172              
173 0           $l = shift @l;
174              
175 0 0         if ($l =~ /^begin_block=(\S+)$/oi) {
176 0           $type = lc($1);
177             } else {
178 0           $self->{'error'} = "No begin_block found";
179 0           return -1;
180             }
181            
182 0           my ($section,$in_section) = ("",0);
183 0           LINE: while ($l = shift @l) {
184 0 0         next if ($l =~ /^\s*$/o);
185 0 0         if ($in_section == 0) {
186 0 0         if ($l =~ /^begin=(\S+)$/oi) {
    0          
187 0           $section = lc($1);
188 0           $in_section = 1;
189             } elsif ($l =~ /^end_block=(\S+)$/oi) {
190 0 0         if (lc($1) eq $type) {
191 0           $in_section = -1;
192 0           last LINE;
193             } else {
194 0           $self->{'error'} = "end_block does not match begin.";
195 0           return -1;
196             }
197             } else {
198 0           $self->{'error'} = "Garbled input at global level.";
199 0           return -1;
200             }
201             } else {
202 0 0         if ($l =~ /^end=(\S+)$/oi) {
203 0 0         if (lc($1) eq $section) {
204 0           $in_section = 0;
205 0           $section = "";
206 0           next LINE;
207             } else {
208 0           $self->{'error'} = "end section does not match begin.";
209 0           return -1;
210             }
211             }
212            
213 0           my ($key,$value);
214            
215 0 0         if (($key,$value) = $l =~ /^([^=]+)=(.*)/o) {
216 0           $key = lc($key);
217 0           $tmp{$section}{$key} = _un_esc_str ($value);
218             } else {
219 0           $self->{'error'} = "Garbled input at section level: $l";
220 0           return -1;
221             }
222             }
223            
224             }
225            
226 0           $self->{'type'} = $type;
227 0           %{$self->{'data'}} = %tmp;
  0            
228            
229 0           return 0;
230             }
231              
232             sub type {
233 0     0 1   my ($self) = shift;
234              
235 0 0         if (@_) {
236 0           my ($type) = lc(shift);
237              
238 0 0         if (grep($_ eq $type,@TYPES)) {
239 0           $self->{'type'} = $type;
240             } else {
241 0           $self->{'type'} = "UNKNOWN";
242 0           $self->{'error'} = "Unknown type supplied.";
243 0           return -1;
244             }
245             }
246              
247 0           return $self->{'type'};
248             }
249              
250             sub get_section {
251 0     0 1   my ($self) = shift;
252 0           my ($section) = lc(shift);
253            
254 0 0         if (defined($self->{'data'}->{$section})) {
255 0           return %{$self->{'data'}->{$section}};
  0            
256             } else {
257 0           $self->{'error'} = "$section: No such section.";
258 0           return -1;
259             }
260             }
261              
262             sub get_section_list {
263 0     0 1   my ($self) = shift;
264 0           return sort keys %{$self->{'data'}};
  0            
265             }
266              
267             sub add_to_section {
268 0     0 1   my ($self) = shift;
269            
270 0           my $section = lc(shift);
271 0           my ($rdata) = @_;
272            
273 0           my ($key,$value);
274 0           while ( ($key,$value) = each %$rdata) {
275 0           $key = lc($key);
276 0           $self->{'data'}->{$section}->{$key} = $value;
277             }
278            
279 0           return 1;
280             }
281              
282             sub delete_section {
283 0     0 1   my ($self) = shift;
284 0           my ($section) = lc(shift);
285            
286 0 0         if (defined($self->{'data'}->{$section})) {
287 0           delete $self->{'data'}->{$section};
288 0           return 0;
289             } else {
290 0           $self->{'error'} = "$section: No such section.";
291 0           return -1;
292             }
293             }
294              
295             sub delete_from_section {
296 0     0 1   my ($self) = shift;
297 0           my ($section) = lc(shift);
298 0           my ($key) = lc(shift);
299            
300 0 0         if (defined($self->{'data'}->{$section}->{$key})) {
301 0           delete $self->{'data'}->{$section}->{$key};
302 0           return 0;
303             } else {
304 0           $self->{'error'} = "$section/$key: No such key in section.";
305 0           return -1;
306             }
307             }
308              
309             sub error {
310 0     0 1   my ($self) = shift;
311 0           my $err = $self->{'error'};
312 0           $self->{'error'}= "";
313 0           return $err;
314             }
315              
316             sub DESTROY {
317 0     0     my $self = shift;
318             }
319              
320              
321             #
322             # convert a string to a hex-escaped string, returning
323             # the escaped string.
324             #
325             # $str is the string to be escaped
326             # if $inquotes is true, backslashes are doubled, making
327             # the escaped string suitable to be enclosed in
328             # single quotes and later passed to Text::quotewords.
329             # For example, var='quoted value'
330             #
331             sub _esc_str {
332 0     0     my $str = shift;
333 0           my $inquotes = shift;
334              
335 0           my $escstr = "";
336              
337 0           for (my $i = 0; $i < length ($str); $i++)
338             {
339 0           my $c = substr ($str, $i, 1);
340              
341 0 0 0       if (ord ($c) < 32 ||
    0 0        
      0        
      0        
342             ord ($c) > 126 ||
343             $c eq "\"" ||
344             $c eq "\'")
345             {
346 0           $c = sprintf ("\\%02x", ord($c));
347             }
348             elsif ($inquotes && $c eq "\\")
349             {
350 0           $c = "\\\\";
351             }
352              
353 0           $escstr .= $c;
354             }
355              
356 0           $escstr;
357             }
358              
359              
360             #
361             # convert a hex-escaped string into an unescaped string,
362             # returning the unescaped string
363             #
364             sub _un_esc_str {
365 0     0     my $str = shift;
366              
367 0           $str =~ s{\\([0-9a-f]{2})}{chr(hex($1))}eg;
  0            
368              
369 0           $str;
370             }
371              
372             1;
373