File Coverage

blib/lib/Chart/Graph/Utils.pm
Criterion Covered Total %
statement 71 94 75.5
branch 15 30 50.0
condition 2 6 33.3
subroutine 14 16 87.5
pod n/a
total 102 146 69.8


line stmt bran cond sub pod time code
1             ## Graph.pm is a graphing package that supports on-the-fly graphing
2             ## from the gnuplot, xrt, and xmgrace graphing packages.
3             ##
4             ## $Id: Utils.pm,v 1.24 2006/06/07 21:09:33 emile Exp $ $Name: $
5             ##
6             ## This software product is developed by Michael Young and David Moore,
7             ## and copyrighted(C) 1998 by the University of California, San Diego
8             ## (UCSD), with all rights reserved. UCSD administers the CAIDA grant,
9             ## NCR-9711092, under which part of this code was developed.
10             ##
11             ## There is no charge for this software. You can redistribute it and/or
12             ## modify it under the terms of the GNU General Public License, v. 2 dated
13             ## June 1991 which is incorporated by reference herein. This software is
14             ## distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF MERCHANTABILITY
15             ## OR FITNESS FOR A PARTICULAR PURPOSE or that the use of it will not
16             ## infringe on any third party's intellectual property rights.
17             ##
18             ## You should have received a copy of the GNU GPL along with this program.
19             ##
20             ##
21             ## IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY
22             ## PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
23             ## DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS
24             ## SOFTWARE, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF
25             ## THE POSSIBILITY OF SUCH DAMAGE.
26             ##
27             ## THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE
28             ## UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
29             ## SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. THE UNIVERSITY
30             ## OF CALIFORNIA MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES
31             ## OF ANY KIND, EITHER IMPLIED OR EXPRESS, INCLUDING, BUT NOT LIMITED
32             ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
33             ## PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE
34             ## ANY PATENT, TRADEMARK OR OTHER RIGHTS.
35             ##
36             ##
37             ## Contact: graph-dev@caida.org
38             ##
39             ##
40             package Chart::Graph::Utils;
41 4     4   21 use Exporter ();
  4         8  
  4         333  
42              
43             @ISA = qw(Exporter);
44             %EXPORT_TAGS = (UTILS => [qw($gnuplot $xmgrace $convert $ppmtogif
45             $xwdtopnm $xrt $xvfb $ppmtojpg $pnmtopng
46             $use_xvfb
47             $tmpcount
48             &_make_tmpdir &_cleanup_tmpdir &_get_path
49             &_chk_status &_mesh_opts &_make_tmpfile
50             &_number_to_eng)],
51              
52             # variables that user may set
53             USER => [qw($gnuplot $convert $xmgrace $ppmtogif $pnmtopng
54             $ppmtojpg $xwdtopnm $xrt $xvfb
55             $use_xvfb)]
56             );
57              
58             # add symbols from tags into @EXPORT_OK
59             Exporter::export_ok_tags('UTILS');
60              
61 4     4   25 use Carp; # for carp() and croak()
  4         6  
  4         425  
62 4     4   20 use File::Path; # for rmtree()
  4         6  
  4         407  
63              
64             $cvs_Id = '$Id: Utils.pm,v 1.24 2006/06/07 21:09:33 emile Exp $';
65             $cvs_Author = '$Author: emile $';
66             $cvs_Name = '$Name: $';
67             $cvs_Revision = '$Revision: 1.24 $';
68              
69             $VERSION = 3.2;
70              
71 4     4   19 use strict;
  4         8  
  4         170  
72              
73             # default don't use xvfb by default, use their own display environment
74 4     4   20 use vars qw($use_xvfb);
  4         6  
  4         1792  
75             $use_xvfb = 0;
76              
77             # hold paths to programs
78             # user may choose to set paths to these programs
79             # if paths are not set then we will attempt to search
80             # PATH for the programs
81 4     4   25 use vars qw($gnuplot $xvfb $convert $xwdtopnm $ppmtogif $ppmtojpg $pnmtopng);
  4         6  
  4         953  
82             # Store names of converters programs until either user sets path or
83             # path is automatically assigned to these variables. These will be overridden
84             # by users if another path is desired.
85             $convert = "convert";
86             $xwdtopnm = "xwdtopnm";
87             $ppmtogif = "ppmtogif";
88             $ppmtojpg = "ppmtojpeg";
89             $pnmtopng = "pnmtopng";
90              
91             #
92             # remove tmp files in case program exits abnormally
93             #
94             END {
95 4     4   1269 _cleanup_tmpdir();
96             }
97              
98             #
99             # remove tmp files in case of a signal interrupt (ctrl-C)
100             #
101             $SIG{INT} = \&_handle_sigint;
102             #$SIG{INT} = 'DEFAULT';
103              
104             #
105             # general purpose global variables
106             #
107              
108 4     4   21 use vars qw($tmpcount $tmpdir @clean_tmpdirs);
  4         8  
  4         4981  
109             $tmpcount = 0; # used to create unique tmp filenames
110             @clean_tmpdirs = (); # Storage for every tmp directory to be eventually
111             # removed.
112              
113             #
114             #
115             # general purpose subroutines - these are subroutines shared across
116             # all packages
117             #
118              
119             #
120             # Subroutine: make_tmpdir()
121             #
122             # Description: creates temporary dir for storage
123             # of temporary files with read, write,
124             # and execute for user and group
125             sub _make_tmpdir {
126 57     57   161 my $package = shift;
127 57 50       221 die 'Too many arguments\n' if @_;
128              
129 57         470 my $PID = $$;
130 57 50       1437 if (not defined($ENV{TMPDIR})) {
131 57         1511 while(-d "/tmp/Graph$package$PID") {$PID++ }
  0         0  
132 57         944 $tmpdir = "/tmp/Graph$package$PID";
133             } else {
134 0         0 while(-d "/tmp/Graph$package$PID") {$PID++ }
  0         0  
135 0         0 $tmpdir = "$ENV{TMPDIR}/Graph$package$$";
136             }
137              
138 57 50       10941 if (not mkdir($tmpdir, 0770)) {
139 0         0 croak "could not make temporary directory: `$tmpdir'";
140 0         0 $tmpdir = undef;
141             }
142              
143             # Add directory to list of directories to remove
144 57         1124 push @clean_tmpdirs, $tmpdir;
145 57         203 return $tmpdir;
146             }
147              
148             #
149             # Subroutine: cleanup_tmpdir()
150             #
151             # Description: remove the tmp dir we created for
152             # tmp files
153              
154             sub _cleanup_tmpdir {
155              
156 60     60   285 my $count = 1; # Convenience variable for comments.
157              
158             # Loop through every temporary directory created and either
159             # report to the user it was created or remove the tree structure.
160 60         777 foreach my $tmp_dir (@clean_tmpdirs) {
161 1249 50 66     52814 if ($Chart::Graph::save_tmpfiles) {
    100          
162 0 0 0     0 if (defined($tmp_dir) and -d $tmp_dir ) {
163 0         0 print "Set $count of tmp files are in $tmp_dir\n";
164             }
165             } elsif (defined($tmp_dir) and -d $tmp_dir ) {
166             # remove directory and associated files.
167 57 50       85324 unless ( rmtree ($tmp_dir, 0, 1) ) {
168 0         0 carp "Unable to successfully remove set $count of " .
169             "temporary files";
170             } # Careful not to change permissions but not unlink files.
171             }
172 1249         5713 $count++;
173             }
174             }
175              
176             #
177             # Subroutine: make_tmpfile()
178             # Description: create temporary filenames with unique extensions
179             #
180             #
181             sub _make_tmpfile {
182 113     113   674 my ($file, $ext) = @_;
183 113         327 $tmpcount++;
184 113 100       284 if (not defined($ext)) {
    50          
185 106         316 $ext = "";
186             } elsif ($ext ne "") {
187 7         16 $ext = ".$ext"
188             };
189 113         4177 return "$tmpdir/$file.$tmpcount$ext";
190             }
191              
192             #
193             # Subroutine: get_path()
194             #
195             # Description: searches PATH for specified program given as arg
196             #
197             #
198             #
199             #
200             sub _get_path {
201 9     9   18 my ($exe) = @_;
202 9         59 my @path = split (/:/, $ENV{PATH});
203 9         16 my $program;
204            
205 9         21 foreach my $i(@path){
206 63         100 $program = "$i/$exe";
207 63 50       1104 if (-x $program) {
208 0         0 return $program;
209             }
210             }
211              
212 9         3060 carp "program not found in search path: $exe";
213 9         83 return 0;
214             }
215              
216             #
217             # Subroutine: chk_status
218             #
219             # Description: checks the exit status of system() calls for errors
220             #
221             #
222             sub _chk_status {
223 51     51   200 my ($status) = @_;
224 51 100       563 if ($status) {
225 47         1035 my $exit_value = $? >> 8;
226 47         220 my $signal_num = $? & 127;
227 47         125 my $dumped_core = $? & 128;
228 47         58126 carp "exit value = $exit_value\nsignal number = $signal_num\ndumped core = $dumped_core\n";
229 47         564 return 0;
230             }
231 4         84 return 1;
232             }
233              
234             #
235             # Subroutine: mesh_opts
236             #
237             # Description: merges user and default option for
238             # gnuplot and or xrt options
239             #
240              
241             sub _mesh_opts {
242 107     107   383 my ($user_opts_ref, $default_opts_ref) = @_;
243 107         158 my %user_opts = %{$user_opts_ref};
  107         1456  
244 107         194 my %default_opts = %{$default_opts_ref};
  107         2436  
245 107         307 my %opts;
246              
247             # check user opts against defaults and mesh
248             # the basic algorithm here is to override the
249             # the default options against the ones that
250             # the user has passed in.
251 107         624 while (my ($key, $value) = each %default_opts) {
252 1584 100       4258 if (exists($user_opts{$key})) {
253 222         407 $opts{$key} = $user_opts{$key};
254 222         752 delete $user_opts{$key}; # remove options
255             # that are matching
256             } else {
257 1362         7262 $opts{$key} = $default_opts{$key};
258             }
259             }
260            
261             # any left over options in the table are unknown
262             # if the user passes in illegal options then we
263             # warn them with an error message but still
264             # proceed.
265 107         575 while (my ($key, $value) = each %user_opts) {
266 0         0 carp "unknown option: $key";
267             }
268            
269 107         4709 return %opts;
270             }
271              
272              
273             #
274             # Subroutine: _number_to_eng
275             #
276             # Description: returns the correct suffix for
277             # numerics, ie, 1st, 2nd, 3rd, 4th..
278             #
279              
280             sub _number_to_eng {
281 0     0     my $number = shift @_;
282 0           my $retval;
283              
284 0 0         if ($number == 1) {
    0          
    0          
285 0           $retval = $number . "st";
286             } elsif ($number == 2) {
287 0           $retval = $number . "nd";
288             } elsif ($number == 3) {
289 0           $retval = $number . "rd";
290             } else {
291 0           $retval = $number . "th";
292             }
293              
294 0           return $retval;
295             }
296              
297             #
298             # Subroutine: _handle_sigint
299             #
300             # Description: cleans up if ctrl c detected
301             #
302             #
303              
304             sub _handle_sigint {
305 0     0     warn "\nSIGINT detected: tmp files cleaned up\n";
306 0           _cleanup_tmpdir();
307 0           $SIG{INT} = 'DEFAULT';
308 0           exit;
309            
310             }
311              
312             1;