| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
## XrtUtils.pm is a sub-module of Graph.pm. It has all the subroutines |
|
2
|
|
|
|
|
|
|
## needed for the Xrt3d part of the package. |
|
3
|
|
|
|
|
|
|
## |
|
4
|
|
|
|
|
|
|
## $Id: XrtUtils.pm,v 1.13 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::XrtUtils; |
|
41
|
4
|
|
|
4
|
|
21
|
use Exporter (); |
|
|
4
|
|
|
|
|
9
|
|
|
|
4
|
|
|
|
|
300
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
|
44
|
|
|
|
|
|
|
@EXPORT = qw(); |
|
45
|
|
|
|
|
|
|
%EXPORT_TAGS = (UTILS => [qw(&_set_xrtpaths &_set_ldpath &_print_matrix |
|
46
|
|
|
|
|
|
|
&_print_array &_verify_ticks &_exec_xrt3d &_exec_xrt2d |
|
47
|
|
|
|
|
|
|
&_exec_netpbm &_exec_xvfb &_try_port &_convert_raster |
|
48
|
|
|
|
|
|
|
&_childpid_dead &_transfer_file)], |
|
49
|
|
|
|
|
|
|
); |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Exporter::export_ok_tags('UTILS'); |
|
52
|
|
|
|
|
|
|
|
|
53
|
4
|
|
|
4
|
|
21
|
use Carp; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
275
|
|
|
54
|
4
|
|
|
4
|
|
50
|
use POSIX ":sys_wait_h"; # for waitpid() |
|
|
4
|
|
|
|
|
7
|
|
|
|
4
|
|
|
|
|
1460
|
|
|
55
|
4
|
|
|
4
|
|
790
|
use Chart::Graph::Utils qw(:UTILS); |
|
|
4
|
|
|
|
|
9
|
|
|
|
4
|
|
|
|
|
4535
|
|
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
$cvs_Id = '$Id: XrtUtils.pm,v 1.13 2006/06/07 21:09:33 emile Exp $'; |
|
58
|
|
|
|
|
|
|
$cvs_Author = '$Author: emile $'; |
|
59
|
|
|
|
|
|
|
$cvs_Name = '$Name: $'; |
|
60
|
|
|
|
|
|
|
$cvs_Revision = '$Revision: 1.13 $'; |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
$VERSION = 3.2; |
|
63
|
|
|
|
|
|
|
|
|
64
|
4
|
|
|
4
|
|
24
|
use strict; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
144
|
|
|
65
|
4
|
|
|
4
|
|
23
|
use File::Basename; |
|
|
4
|
|
|
|
|
6
|
|
|
|
4
|
|
|
|
|
902
|
|
|
66
|
|
|
|
|
|
|
|
|
67
|
4
|
|
|
4
|
|
23
|
use vars qw($xrt2d $xrt3d); |
|
|
4
|
|
|
|
|
7
|
|
|
|
4
|
|
|
|
|
10956
|
|
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# |
|
70
|
|
|
|
|
|
|
# Subroutine: set_converterpaths() |
|
71
|
|
|
|
|
|
|
# |
|
72
|
|
|
|
|
|
|
# Description: set paths for converter programs in particular. This |
|
73
|
|
|
|
|
|
|
# subroutine can take one or two arguments and tests if |
|
74
|
|
|
|
|
|
|
# the required converter programs are indeed available |
|
75
|
|
|
|
|
|
|
# for the choosen method to convert a file from one |
|
76
|
|
|
|
|
|
|
# graphics format to another. |
|
77
|
|
|
|
|
|
|
# |
|
78
|
|
|
|
|
|
|
sub _set_converterpaths { |
|
79
|
0
|
|
|
0
|
|
0
|
my @converters = @_; |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# Loop through the list of converter seeing which are available |
|
82
|
0
|
|
|
|
|
0
|
foreach my $converter (@converters) { |
|
83
|
0
|
0
|
|
|
|
0
|
if (not -x $$converter) { |
|
84
|
0
|
0
|
|
|
|
0
|
if (not $$converter = _get_path($$converter)) { |
|
85
|
0
|
|
|
|
|
0
|
return(0); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
} |
|
89
|
0
|
|
|
|
|
0
|
return(1); |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# |
|
93
|
|
|
|
|
|
|
# Subroutine: _convert_raster($plot_file, $output_file) |
|
94
|
|
|
|
|
|
|
# |
|
95
|
|
|
|
|
|
|
# Description: A subroutine to over see the conversion process from |
|
96
|
|
|
|
|
|
|
# one raster graphic format to another. It will try |
|
97
|
|
|
|
|
|
|
# ImageMagick convert first and if that fails try Netpbm |
|
98
|
|
|
|
|
|
|
# utilities if they are available in that format. |
|
99
|
|
|
|
|
|
|
# |
|
100
|
|
|
|
|
|
|
sub _convert_raster { |
|
101
|
0
|
|
|
0
|
|
0
|
my $FORMAT = shift; |
|
102
|
0
|
|
|
|
|
0
|
my $plot_file = shift; |
|
103
|
0
|
|
|
|
|
0
|
my $output_file = shift; |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# First try ImageMagick as it is more robust and simpler |
|
106
|
0
|
0
|
|
|
|
0
|
if (_set_converterpaths(\$convert)) { |
|
107
|
0
|
0
|
|
|
|
0
|
if (_exec_convert($convert, $FORMAT, $plot_file, $output_file)) { |
|
108
|
0
|
|
|
|
|
0
|
return(1); |
|
109
|
|
|
|
|
|
|
} else { |
|
110
|
0
|
|
|
|
|
0
|
carp "Attempt to use ImageMagick failed, will try Netpbm." |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
} else { |
|
113
|
0
|
|
|
|
|
0
|
carp "No ImageMagick found, will try Netpbm." |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
0
|
0
|
|
|
|
0
|
if ($FORMAT eq 'GIF') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
0
|
_try_netpbm_combo($xwdtopnm, $ppmtogif, $plot_file, $output_file); |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
elsif ($FORMAT eq 'JPG') { |
|
120
|
0
|
|
|
|
|
0
|
_try_netpbm_combo($xwdtopnm, $ppmtojpg, $plot_file, $output_file); |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
elsif ($FORMAT eq 'PNG') { |
|
123
|
0
|
|
|
|
|
0
|
_try_netpbm_combo($xwdtopnm, $pnmtopng, $plot_file, $output_file); |
|
124
|
|
|
|
|
|
|
} else { |
|
125
|
0
|
|
|
|
|
0
|
carp "Untrapped raster image format - XrtUtils.pm internal error"; |
|
126
|
0
|
|
|
|
|
0
|
return(0); |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# |
|
131
|
|
|
|
|
|
|
# Subroutine _try_netpbm_combo($xwdtopbm, pbmtotarget, $xwd_file, $target_file) |
|
132
|
|
|
|
|
|
|
# |
|
133
|
|
|
|
|
|
|
# |
|
134
|
|
|
|
|
|
|
# Description: Contains the logic for testing if a combination of |
|
135
|
|
|
|
|
|
|
# netpbm programs can be accessed and executed to perform |
|
136
|
|
|
|
|
|
|
# the desired conversion. If not, it produces the |
|
137
|
|
|
|
|
|
|
# appropriate error messages. Basically, it saves a |
|
138
|
|
|
|
|
|
|
# batch of conditional statements that would otherwise be |
|
139
|
|
|
|
|
|
|
# repeated. |
|
140
|
|
|
|
|
|
|
# |
|
141
|
|
|
|
|
|
|
sub _try_netpbm_combo { |
|
142
|
0
|
|
|
0
|
|
0
|
my ($xwdtopbm, $pbmtotarget, $xwd_file, $target_file) = @_; |
|
143
|
|
|
|
|
|
|
|
|
144
|
0
|
0
|
|
|
|
0
|
if (_set_converterpaths(\$xwdtopbm, \$pbmtotarget)) { |
|
145
|
0
|
0
|
|
|
|
0
|
if (_exec_netpbm($xwdtopbm, $pbmtotarget, $xwd_file, $target_file)) { |
|
146
|
0
|
|
|
|
|
0
|
return(1); |
|
147
|
|
|
|
|
|
|
} else { |
|
148
|
0
|
|
|
|
|
0
|
carp "Failure to execute any suitable image " . |
|
149
|
|
|
|
|
|
|
"converters for create file: $target_file"; |
|
150
|
0
|
|
|
|
|
0
|
return(0); |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
} else { |
|
153
|
0
|
|
|
|
|
0
|
carp "Unable to find any suitable image converters to " . |
|
154
|
|
|
|
|
|
|
"create file: $target_file"; |
|
155
|
0
|
|
|
|
|
0
|
return(0); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# |
|
160
|
|
|
|
|
|
|
# Subroutine: set_xrtpaths() |
|
161
|
|
|
|
|
|
|
# |
|
162
|
|
|
|
|
|
|
# Description: set paths for external programs required by xrt() |
|
163
|
|
|
|
|
|
|
# if they are not defined already |
|
164
|
|
|
|
|
|
|
# |
|
165
|
|
|
|
|
|
|
sub _set_xrtpaths { |
|
166
|
|
|
|
|
|
|
|
|
167
|
6
|
|
|
6
|
|
11
|
my $xrtver = shift; |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
|
|
171
|
6
|
50
|
|
|
|
17
|
if (defined($xrtver)) { |
|
172
|
6
|
100
|
|
|
|
16
|
if ($xrtver eq "xrt2d") { |
|
173
|
2
|
50
|
|
|
|
7
|
if (not $Chart::Graph::xrt2d = _get_path("xrt2d")) { |
|
174
|
2
|
|
|
|
|
8
|
return 0; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
4
|
50
|
|
|
|
9
|
if ($xrtver eq "xrt3d") { |
|
179
|
4
|
50
|
|
|
|
11
|
if (not $Chart::Graph::xrt3d = _get_path("xrt3d")) { |
|
180
|
4
|
|
|
|
|
19
|
return 0; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
0
|
0
|
|
|
|
0
|
if (not defined($xwdtopnm)) { |
|
186
|
0
|
0
|
|
|
|
0
|
if (!($xwdtopnm = _get_path("xwdtopnm"))) { |
|
187
|
0
|
|
|
|
|
0
|
return 0; |
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
0
|
0
|
|
|
|
0
|
if (not defined($xvfb)) { |
|
192
|
0
|
0
|
|
|
|
0
|
if (not $xvfb = _get_path("Xvfb")) { |
|
193
|
0
|
|
|
|
|
0
|
return 0; |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# make sure /usr/dt/lib is in the library path |
|
198
|
0
|
|
|
|
|
0
|
_set_ldpath("/usr/dt/lib"); |
|
199
|
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
0
|
return 1; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# |
|
204
|
|
|
|
|
|
|
# Subroutine: set_ldpath() |
|
205
|
|
|
|
|
|
|
# |
|
206
|
|
|
|
|
|
|
# Description: Xvfb has trouble finding libMrm, so we have to add |
|
207
|
|
|
|
|
|
|
# /usr/dt/lib to LD_LIBRARY_PATH |
|
208
|
|
|
|
|
|
|
# |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub _set_ldpath { |
|
211
|
1
|
|
|
1
|
|
3
|
my ($libpath) = @_; |
|
212
|
|
|
|
|
|
|
|
|
213
|
1
|
50
|
|
|
|
5
|
if (not defined($ENV{LD_LIBRARY_PATH})) { |
|
214
|
1
|
|
|
|
|
7
|
$ENV{LD_LIBRARY_PATH} = "$libpath"; |
|
215
|
1
|
|
|
|
|
3
|
return 1; |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
|
my @ldpath = split (/:/, $ENV{LD_LIBRARY_PATH}); |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# make sure library path isn't already defined |
|
221
|
0
|
|
|
|
|
|
foreach my $i(@ldpath){ |
|
222
|
0
|
0
|
|
|
|
|
if ($i eq $libpath) { |
|
223
|
0
|
|
|
|
|
|
return 1; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# add library path to LD_LIBRARY_PATH |
|
228
|
0
|
|
|
|
|
|
$ENV{LD_LIBRARY_PATH} = "$libpath:$ENV{LD_LIBRARY_PATH}"; |
|
229
|
0
|
|
|
|
|
|
return 1; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# |
|
233
|
|
|
|
|
|
|
# Subroutine: print_matrix() |
|
234
|
|
|
|
|
|
|
# |
|
235
|
|
|
|
|
|
|
# Description: print out all the elements |
|
236
|
|
|
|
|
|
|
# in a X by Y matrix, row by row |
|
237
|
|
|
|
|
|
|
# |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub _print_matrix { |
|
240
|
0
|
|
|
0
|
|
|
my ($handle, @matrix) = @_; |
|
241
|
|
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
|
foreach my $row (@matrix){ |
|
243
|
0
|
|
|
|
|
|
foreach my $i (@{$row}){ |
|
|
0
|
|
|
|
|
|
|
|
244
|
0
|
|
|
|
|
|
print $handle "$i\t"; |
|
245
|
|
|
|
|
|
|
} |
|
246
|
0
|
|
|
|
|
|
print $handle "\n"; |
|
247
|
|
|
|
|
|
|
} |
|
248
|
0
|
|
|
|
|
|
return 1; |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# |
|
253
|
|
|
|
|
|
|
# Subroutine: _transfer_file($handle, $data_filename) |
|
254
|
|
|
|
|
|
|
# |
|
255
|
|
|
|
|
|
|
# Description: open file $data_filename. Read the contents |
|
256
|
|
|
|
|
|
|
# and write it into the command file tab delimited. Don't |
|
257
|
|
|
|
|
|
|
# assume data was tab delimited to be safe. |
|
258
|
|
|
|
|
|
|
# |
|
259
|
|
|
|
|
|
|
sub _transfer_file { |
|
260
|
0
|
|
|
0
|
|
|
my $handle = shift; |
|
261
|
0
|
|
|
|
|
|
my $data_filename = shift; |
|
262
|
0
|
|
|
|
|
|
my $data; |
|
263
|
|
|
|
|
|
|
my @elements; |
|
264
|
|
|
|
|
|
|
|
|
265
|
0
|
0
|
|
|
|
|
unless(open(DATAHDL, $data_filename)) { |
|
266
|
0
|
|
|
|
|
|
carp "Unable to open data file: $data_filename for reading"; |
|
267
|
0
|
|
|
|
|
|
return(0); |
|
268
|
|
|
|
|
|
|
} |
|
269
|
0
|
|
|
|
|
|
while (defined($data = )) { |
|
270
|
0
|
|
|
|
|
|
chomp($data); |
|
271
|
0
|
|
|
|
|
|
@elements = split(/\s+/, $data); |
|
272
|
0
|
|
|
|
|
|
foreach my $element (@elements) { |
|
273
|
0
|
|
|
|
|
|
print $handle $element, "\t"; |
|
274
|
|
|
|
|
|
|
} |
|
275
|
0
|
|
|
|
|
|
print $handle "\n"; |
|
276
|
|
|
|
|
|
|
} |
|
277
|
0
|
0
|
|
|
|
|
unless(close(DATAHDL)) { |
|
278
|
0
|
|
|
|
|
|
carp "Unable to close data file: $data_filename after reading"; |
|
279
|
|
|
|
|
|
|
} |
|
280
|
0
|
|
|
|
|
|
return(1); |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# |
|
284
|
|
|
|
|
|
|
# Subroutine: print_array() |
|
285
|
|
|
|
|
|
|
# |
|
286
|
|
|
|
|
|
|
# Description: print out each element of array, one per line |
|
287
|
|
|
|
|
|
|
# |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _print_array { |
|
290
|
0
|
|
|
0
|
|
|
my ($handle, @array) = @_; |
|
291
|
0
|
|
|
|
|
|
my $i; |
|
292
|
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
|
foreach $i (@array) { |
|
294
|
0
|
|
|
|
|
|
print $handle "$i\n"; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
0
|
|
|
|
|
|
return 1; |
|
297
|
|
|
|
|
|
|
} |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# |
|
300
|
|
|
|
|
|
|
# Subroutine: verify_ticks(); |
|
301
|
|
|
|
|
|
|
# |
|
302
|
|
|
|
|
|
|
# Description: check that the number of tick labels is the same |
|
303
|
|
|
|
|
|
|
# as the number of xy rows and columns. we can only have |
|
304
|
|
|
|
|
|
|
# as many ticks as the number of rows or columns |
|
305
|
|
|
|
|
|
|
# we make this subroutine so that the calling subroutine |
|
306
|
|
|
|
|
|
|
# is kept cleaner. |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub _verify_ticks { |
|
309
|
0
|
|
|
0
|
|
|
my ($cnt, $ticks_ref) = @_; |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# if no ticks are given then just |
|
312
|
|
|
|
|
|
|
# give the xrt binary "1, 2,..." |
|
313
|
0
|
0
|
|
|
|
|
if (not defined($ticks_ref)) { |
|
314
|
0
|
|
|
|
|
|
my @def_ticks; |
|
315
|
0
|
|
|
|
|
|
for (my $i = 0; $i < $cnt; $i++) { |
|
316
|
0
|
|
|
|
|
|
$def_ticks[$i] = $i + 1; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
0
|
|
|
|
|
|
$ticks_ref = \@def_ticks; |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
0
|
|
|
|
|
|
my $tick_cnt = @{$ticks_ref}; |
|
|
0
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
|
|
323
|
0
|
0
|
|
|
|
|
if ($cnt ne $tick_cnt){ |
|
324
|
0
|
|
|
|
|
|
carp "number of tick labels must equal the number of xy rows and columns"; |
|
325
|
0
|
|
|
|
|
|
return 0; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
0
|
|
|
|
|
|
return 1; |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# |
|
331
|
|
|
|
|
|
|
# Subroutine: exec_xrt3d() |
|
332
|
|
|
|
|
|
|
# |
|
333
|
|
|
|
|
|
|
# Description: execute the xrt3d program on the command file. |
|
334
|
|
|
|
|
|
|
# xrt3d generates a xwd file. |
|
335
|
|
|
|
|
|
|
# |
|
336
|
|
|
|
|
|
|
sub _exec_xrt3d { |
|
337
|
0
|
|
|
0
|
|
|
my ($command_file) = @_; |
|
338
|
0
|
|
|
|
|
|
my ($output); |
|
339
|
0
|
|
|
|
|
|
my ($childpid, $port); |
|
340
|
0
|
|
|
|
|
|
my $display_env = $ENV{DISPLAY}; |
|
341
|
0
|
|
|
|
|
|
my $status; |
|
342
|
|
|
|
|
|
|
|
|
343
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::use_xvfb) { |
|
344
|
|
|
|
|
|
|
# start the virtual X server |
|
345
|
0
|
|
|
|
|
|
($childpid, $port) = _exec_xvfb(); |
|
346
|
0
|
|
|
|
|
|
$status = system("$Chart::Graph::xrt3d -display :$port.0 < $command_file"); |
|
347
|
|
|
|
|
|
|
} else { |
|
348
|
|
|
|
|
|
|
# use the local X server |
|
349
|
|
|
|
|
|
|
# warning: colors might be messed up |
|
350
|
|
|
|
|
|
|
# depending on your current setup |
|
351
|
0
|
|
|
|
|
|
$status = system("$Chart::Graph::xrt3d -display $display_env < $command_file"); |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
#my $status = system("$xrt -display :$port.0 < $command_file"); |
|
355
|
0
|
0
|
|
|
|
|
if (not _chk_status($status)) { |
|
356
|
0
|
|
|
|
|
|
return 0; |
|
357
|
|
|
|
|
|
|
} |
|
358
|
|
|
|
|
|
|
|
|
359
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::use_xvfb) { |
|
360
|
0
|
|
|
|
|
|
kill('KILL', $childpid); |
|
361
|
|
|
|
|
|
|
} |
|
362
|
|
|
|
|
|
|
|
|
363
|
0
|
|
|
|
|
|
return 1; |
|
364
|
|
|
|
|
|
|
} |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# |
|
367
|
|
|
|
|
|
|
# Subroutine: exec_xrt2d() |
|
368
|
|
|
|
|
|
|
# |
|
369
|
|
|
|
|
|
|
# Description: execute the xrt2d program on the command file. |
|
370
|
|
|
|
|
|
|
# xrt2d generates a xwd file. |
|
371
|
|
|
|
|
|
|
# |
|
372
|
|
|
|
|
|
|
sub _exec_xrt2d { |
|
373
|
0
|
|
|
0
|
|
|
my ($command_file, $options) = @_; |
|
374
|
0
|
|
|
|
|
|
my ($output); |
|
375
|
0
|
|
|
|
|
|
my ($childpid, $port); |
|
376
|
0
|
|
|
|
|
|
my $display_env = $ENV{DISPLAY}; |
|
377
|
0
|
|
|
|
|
|
my $status; |
|
378
|
|
|
|
|
|
|
|
|
379
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::use_xvfb) { |
|
380
|
|
|
|
|
|
|
# start the virtual X server |
|
381
|
0
|
|
|
|
|
|
($childpid, $port) = _exec_xvfb(); |
|
382
|
0
|
|
|
|
|
|
printf STDERR "\tXRT is $Chart::Graph::xrt2d\n"; |
|
383
|
0
|
|
|
|
|
|
my $status = system("$Chart::Graph::xrt2d -display ipn:$port.0 < $command_file $options"); |
|
384
|
|
|
|
|
|
|
} else { |
|
385
|
|
|
|
|
|
|
# use the local X server |
|
386
|
|
|
|
|
|
|
# warning: colors might be messed up |
|
387
|
|
|
|
|
|
|
# depending on your current setup |
|
388
|
0
|
|
|
|
|
|
$status = system("$Chart::Graph::xrt2d -display $display_env < $command_file $options"); |
|
389
|
|
|
|
|
|
|
} |
|
390
|
|
|
|
|
|
|
|
|
391
|
0
|
0
|
|
|
|
|
if (not _chk_status($status)) { |
|
392
|
0
|
|
|
|
|
|
return 0; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::use_xvfb) { |
|
396
|
0
|
|
|
|
|
|
kill('KILL', $childpid); |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
|
|
399
|
0
|
|
|
|
|
|
return 1; |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# |
|
403
|
|
|
|
|
|
|
# Subroutine: exec_convert |
|
404
|
|
|
|
|
|
|
# |
|
405
|
|
|
|
|
|
|
# |
|
406
|
|
|
|
|
|
|
# Description: Use the Imagemagick 'convert' utility to convert the xwd |
|
407
|
|
|
|
|
|
|
# file into any one of the other common raster image |
|
408
|
|
|
|
|
|
|
# formats used commonly in web page production. |
|
409
|
|
|
|
|
|
|
# |
|
410
|
|
|
|
|
|
|
sub _exec_convert { |
|
411
|
0
|
|
|
0
|
|
|
my ($convert, $FORMAT, $xwd_file, $target_file) = @_; |
|
412
|
0
|
|
|
|
|
|
my ($status); |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
|
|
415
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::debug) { |
|
416
|
0
|
|
|
|
|
|
$status = system(join('', "$convert -verbose $xwd_file ", |
|
417
|
|
|
|
|
|
|
$FORMAT, ":$target_file")); |
|
418
|
|
|
|
|
|
|
} else { |
|
419
|
0
|
|
|
|
|
|
$status = system(join('', "( $convert $xwd_file ", $FORMAT, |
|
420
|
|
|
|
|
|
|
":$target_file; ) 2> /dev/null")); |
|
421
|
|
|
|
|
|
|
} |
|
422
|
|
|
|
|
|
|
|
|
423
|
0
|
0
|
|
|
|
|
if (not _chk_status($status)) { |
|
424
|
0
|
|
|
|
|
|
return 0; |
|
425
|
|
|
|
|
|
|
} |
|
426
|
0
|
|
|
|
|
|
return 1; |
|
427
|
|
|
|
|
|
|
} |
|
428
|
|
|
|
|
|
|
# |
|
429
|
|
|
|
|
|
|
# Subroutine: _exec_netpbm |
|
430
|
|
|
|
|
|
|
# |
|
431
|
|
|
|
|
|
|
# |
|
432
|
|
|
|
|
|
|
# Description: Convert a raster image using the older utilities now |
|
433
|
|
|
|
|
|
|
# collected under the name 'netpbm.' Note that not all |
|
434
|
|
|
|
|
|
|
# conversions are commonly included wiht all UNIX |
|
435
|
|
|
|
|
|
|
# distributions so that while older conversions such as |
|
436
|
|
|
|
|
|
|
# 'xwd' -> 'gif' are likely to work, others such as |
|
437
|
|
|
|
|
|
|
# conversions to 'png' may not without downloading new |
|
438
|
|
|
|
|
|
|
# software. |
|
439
|
|
|
|
|
|
|
# |
|
440
|
|
|
|
|
|
|
# The conversion strategy always involves a pipe from the |
|
441
|
|
|
|
|
|
|
# X-windows 'xwd' format to some sort 'pbm' format and |
|
442
|
|
|
|
|
|
|
# then from that universal format into the target format. |
|
443
|
|
|
|
|
|
|
# For this reason, it is more prone to machine |
|
444
|
|
|
|
|
|
|
# architecture issues and other errors. |
|
445
|
|
|
|
|
|
|
# |
|
446
|
|
|
|
|
|
|
sub _exec_netpbm { |
|
447
|
0
|
|
|
0
|
|
|
my ($xwdtopbm, $pbmtotarget, $xwd_file, $target_file) = @_; |
|
448
|
0
|
|
|
|
|
|
my ($status); |
|
449
|
|
|
|
|
|
|
|
|
450
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::debug) { |
|
451
|
0
|
|
|
|
|
|
$status = system("$xwdtopbm $xwd_file | $pbmtotarget > $target_file"); |
|
452
|
|
|
|
|
|
|
} else { |
|
453
|
0
|
|
|
|
|
|
$status = system(join('', "( $xwdtopbm -quiet $xwd_file | ", |
|
454
|
|
|
|
|
|
|
"$pbmtotarget -quiet > $target_file; ) ", |
|
455
|
|
|
|
|
|
|
"2> /dev/null")); |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
|
|
458
|
0
|
0
|
|
|
|
|
if (not _chk_status($status)) { |
|
459
|
0
|
|
|
|
|
|
return 0; |
|
460
|
|
|
|
|
|
|
} |
|
461
|
0
|
|
|
|
|
|
return 1; |
|
462
|
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
# |
|
465
|
|
|
|
|
|
|
# Subroutine: exec_xvfb() |
|
466
|
|
|
|
|
|
|
# |
|
467
|
|
|
|
|
|
|
# Description: this starts the vitualX server(X is required by xrt, so |
|
468
|
|
|
|
|
|
|
# we fake out xrt with Xvfb, for speed and compatability) |
|
469
|
|
|
|
|
|
|
# |
|
470
|
|
|
|
|
|
|
# |
|
471
|
|
|
|
|
|
|
sub _exec_xvfb { |
|
472
|
0
|
|
|
0
|
|
|
my $port = 99; |
|
473
|
0
|
|
|
|
|
|
my $childpid; |
|
474
|
0
|
|
|
|
|
|
my $sleep_time = 1; |
|
475
|
0
|
|
|
|
|
|
my $try_count = 0; |
|
476
|
0
|
|
|
|
|
|
my $trialnumber; |
|
477
|
|
|
|
|
|
|
my $childpid_status; |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# starting with port 100, we try to start |
|
480
|
|
|
|
|
|
|
# the virtual server until we find an open port |
|
481
|
|
|
|
|
|
|
# because of the nature of the virtual x server |
|
482
|
|
|
|
|
|
|
# we use, in order to know if we have found an |
|
483
|
|
|
|
|
|
|
# open port, we have to sleep. |
|
484
|
|
|
|
|
|
|
# we check the pid of the virtual x process we started |
|
485
|
|
|
|
|
|
|
# and see if it died or not. |
|
486
|
|
|
|
|
|
|
|
|
487
|
0
|
|
|
|
|
|
while ($childpid_status = _childpid_dead($childpid)) { |
|
488
|
0
|
|
|
|
|
|
$port++; |
|
489
|
0
|
|
|
|
|
|
$try_count++; |
|
490
|
0
|
0
|
|
|
|
|
if ($try_count > 10) { |
|
491
|
0
|
|
|
|
|
|
die "Error: Failed too many times\n"; |
|
492
|
|
|
|
|
|
|
} |
|
493
|
0
|
|
|
|
|
|
$trialnumber = _number_to_eng($try_count); |
|
494
|
0
|
0
|
|
|
|
|
print STDERR "*** $trialnumber try ***" unless (not $Chart::Graph::debug); |
|
495
|
0
|
|
|
|
|
|
$childpid = _try_port($port); |
|
496
|
0
|
|
|
|
|
|
sleep($sleep_time); |
|
497
|
|
|
|
|
|
|
} |
|
498
|
0
|
0
|
|
|
|
|
print STDERR " SUCCESS!!!\n" unless (not $Chart::Graph::debug); |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
# save the childpid so we can stop the virtual server later |
|
501
|
|
|
|
|
|
|
# save the $port so we can tell xrt where the virtual server is. |
|
502
|
0
|
|
|
|
|
|
return ($childpid, $port); |
|
503
|
|
|
|
|
|
|
} |
|
504
|
|
|
|
|
|
|
# |
|
505
|
|
|
|
|
|
|
# Subroutine: try_port(); |
|
506
|
|
|
|
|
|
|
# |
|
507
|
|
|
|
|
|
|
# Description: will try to start Xvfb on specified port |
|
508
|
|
|
|
|
|
|
sub _try_port { |
|
509
|
|
|
|
|
|
|
|
|
510
|
0
|
|
|
0
|
|
|
my ($port) = @_; |
|
511
|
0
|
|
|
|
|
|
my ($childpid); |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
#fork a process |
|
514
|
0
|
0
|
|
|
|
|
if (not defined($childpid = fork())){ |
|
|
|
0
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
# the fork failed |
|
516
|
0
|
|
|
|
|
|
carp "cannot fork: $!"; |
|
517
|
0
|
|
|
|
|
|
return 0; |
|
518
|
|
|
|
|
|
|
} elsif ($childpid == 0) { |
|
519
|
|
|
|
|
|
|
# we are in the child process |
|
520
|
0
|
0
|
|
|
|
|
if ($Chart::Graph::debug) { |
|
521
|
0
|
0
|
|
|
|
|
if (not exec "$xvfb :$port") { |
|
522
|
0
|
|
|
|
|
|
die "can't do $xvfb :$port: $!\n"; |
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
} |
|
525
|
|
|
|
|
|
|
else { |
|
526
|
0
|
0
|
|
|
|
|
if (not exec "$xvfb :$port 2> /dev/null") { |
|
527
|
0
|
|
|
|
|
|
die "can't do $xvfb :$port 2> /dev/null: $!\n"; |
|
528
|
|
|
|
|
|
|
} |
|
529
|
|
|
|
|
|
|
} |
|
530
|
|
|
|
|
|
|
|
|
531
|
0
|
|
|
|
|
|
die "should never reach here\n"; |
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
} else { |
|
534
|
|
|
|
|
|
|
# we are in the parent, return the childpid |
|
535
|
|
|
|
|
|
|
# so we can kill it later. |
|
536
|
0
|
|
|
|
|
|
return $childpid; |
|
537
|
|
|
|
|
|
|
} |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
} |
|
540
|
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
# |
|
542
|
|
|
|
|
|
|
# Subroutine: childpid_dead |
|
543
|
|
|
|
|
|
|
# |
|
544
|
|
|
|
|
|
|
# Description: check to see if a PID has died or not |
|
545
|
|
|
|
|
|
|
# |
|
546
|
|
|
|
|
|
|
# |
|
547
|
|
|
|
|
|
|
sub _childpid_dead { |
|
548
|
0
|
|
|
0
|
|
|
my ($childpid) = @_; |
|
549
|
|
|
|
|
|
|
|
|
550
|
0
|
0
|
|
|
|
|
if (not defined($childpid)) { |
|
551
|
0
|
|
|
|
|
|
return 1; |
|
552
|
|
|
|
|
|
|
} |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# WNOHANG: waitpid() will not suspend execution of |
|
555
|
|
|
|
|
|
|
# the calling process if status is not |
|
556
|
|
|
|
|
|
|
# immediately available for one of the |
|
557
|
|
|
|
|
|
|
# child processes specified by pid. |
|
558
|
0
|
|
|
|
|
|
return waitpid($childpid, &WNOHANG); |
|
559
|
|
|
|
|
|
|
} |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
1; |