Alien-Gnuplot
view release on metacpan or search on metacpan
lib/Alien/Gnuplot.pm view on Meta::CPAN
sub load_gnuplot {
my ($class) = @_;
$class ||= __PACKAGE__;
my $exec_path = $class->exe;
$class->check_gnuplot($exec_path);
}
sub check_gnuplot {
my $exec_path = pop @_;
unless(-x $exec_path) {
die q{
Alien::Gnuplot: no executable gnuplot found! If you have gnuplot,
you can put its exact location in your GNUPLOT_BINARY environment
variable or make sure your PATH contains it. If you do not have
gnuplot, you can reinstall Alien::Gnuplot (and its installation
script will try to install gnuplot) or get it yourself from L<https://gnuplot.sourceforge.net/>.
};
}
##############################
# Execute the executable to make sure it's really gnuplot, and parse
# out its reported version. This is complicated by gnuplot's shenanigans
# with STDOUT and STDERR, so we fork and redirect everything to a file.
# The parent process gives the daughter 2 seconds to report progress, then
# kills it dead.
my($pid);
my ($undef, $file) = tempfile();
# Create command file
open FOO, ">${file}_gzinta";
print FOO "show version\nset terminal\n\n\n\n\n\n\n\n\n\nprint \"CcColors\"\nshow colornames\n\n\n\n\n\n\n\nprint \"FfFinished\"\nexit\n";
close FOO;
if($^O =~ /MSWin32/i) {
if( $exec_path =~ m/([\"\*\?\<\>\|])/ ) {
die "Alien::Gnuplot: Invalid character '$1' in path to gnuplot -- I give up" ;
}
# Microsoft Windows sucks at IPC (and many other things), so
# use "system" instead of civilized fork/exec.
# This leaves us vulnerable to gnuplot itself hanging, but
# sidesteps the problem of waitpid hanging on Strawberry Perl.
open FOO, ">&STDOUT";
open BAR, ">&STDERR";
open STDOUT,">$file";
open STDERR,">$file";
system(qq{"$exec_path" < ${file}_gzinta});
open STDOUT,">&FOO";
open STDERR,">&BAR";
close FOO;
close BAR;
} else {
$pid = fork();
if(defined($pid)) {
if(!$pid) {
# daughter
open BAR, ">&STDERR"; # preserve stderr
eval {
open STDOUT, ">$file";
open STDERR, ">&STDOUT";
open STDIN, "<${file}_gzinta";
seek STDIN, 0, SEEK_SET;
no warnings;
exec($exec_path);
print BAR "Execution of $exec_path failed!\n";
exit(1);
};
print STDERR "Alien::Gnuplot: Unknown problems spawning '$exec_path' to probe gnuplot.\n";
exit(2); # there was a problem!
} else {
# parent
# Assume we're more POSIX-compliant...
if($DEBUG) { print "waiting for pid $pid (up to 20 iterations of 100ms)"; flush STDOUT; }
for (1..20) {
if($DEBUG) { print "."; flush STDOUT; }
if(waitpid($pid,WNOHANG)) {
$pid=0;
last;
}
usleep(1e5);
}
if($DEBUG) { print "\n"; flush STDOUT; }
if($pid) {
if( $DEBUG) { print "gnuplot didn't complete. Killing it dead...\n"; flush STDOUT; }
kill 9,$pid; # zap
waitpid($pid,0); # reap
}
} #end of parent case
} else {
# fork returned undef - error.
die "Alien::Gnuplot: Couldn't fork to test gnuplot! ($@)\n";
}
}
##############################
# Read what gnuplot had to say, and clean up our mess...
open FOO, "<$file";
my @lines = <FOO>;
close FOO;
unlink $file;
unlink $file."_gzinta";
##############################
# Whew. Now parse out the 'GNUPLOT' and version number...
my $lines = join("", map { chomp $_; $_} @lines);
$lines =~ s/\s+G N U P L O T\s*// or die qq{
Alien::Gnuplot: the executable '$exec_path' appears not to be gnuplot,
or perhaps there was a problem running it. You can remove it or set
your GNUPLOT_BINARY variable to an actual gnuplot.
Raw output from Gnuplot:
$lines
};
$lines =~ m/Version (\d+\.\d+) (patchlevel (\d+))?/ or die qq{
Alien::Gnuplot: the executable file $exec_path claims to be gnuplot, but
( run in 2.181 seconds using v1.01-cache-2.11-cpan-d06a3f9ecfd )