File Coverage

blib/lib/Net/Ping/External.pm
Criterion Covered Total %
statement 34 102 33.3
branch 10 38 26.3
condition 3 9 33.3
subroutine 7 23 30.4
pod 1 1 100.0
total 55 173 31.7


line stmt bran cond sub pod time code
1             package Net::Ping::External;
2            
3             # Author: Colin McMillen (colinm AT cpan.org)
4             # See also the CREDITS section in the POD below.
5             #
6             # Copyright (c) 2001-2003 Colin McMillen. All rights reserved. This
7             # program is free software; you may redistribute it and/or modify it
8             # under the same terms as Perl itself.
9             # Copyright (c) 2006-2014 Alexandr Ciornii
10            
11 1     1   1028 use strict;
  1         2  
  1         59  
12 1     1   4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $DEBUG $DEBUG_OUTPUT $LAST_OUTPUT $LAST_EXIT_CODE);
  1         1  
  1         132  
13 1     1   8 use Carp;
  1         6  
  1         137  
14 1     1   6140 use Socket qw(inet_ntoa);
  1         23915  
  1         4365  
15             require Exporter;
16            
17             $VERSION = "0.15";
18             @ISA = qw(Exporter);
19             @EXPORT = qw();
20             @EXPORT_OK = qw(ping);
21            
22             sub ping {
23             # Set up defaults & override defaults with parameters sent.
24 5     5 1 6281 my %args = (count => 1, size => 56, @_);
25            
26             # "host" and "hostname" are synonyms.
27 5 50       43 $args{host} = $args{hostname} if defined $args{hostname};
28            
29             # If we have an "ip" argument, convert it to a hostname and use that.
30 5 50       28 $args{host} = inet_ntoa($args{ip}) if defined $args{ip};
31            
32             # croak() if no hostname was provided.
33 5 50       35 croak("You must provide a hostname") unless defined $args{host};
34 5 100 66     63 $args{timeout} = 5 unless defined $args{timeout} && $args{timeout} > 0;
35            
36 5         154 my %dispatch =
37             (linux => \&_ping_linux,
38             mswin32 => \&_ping_win32,
39             cygwin => \&_ping_cygwin,
40             solaris => \&_ping_solaris,
41             bsdos => \&_ping_bsdos,
42             beos => \&_ping_beos,
43             hpux => \&_ping_hpux,
44             dec_osf => \&_ping_dec_osf,
45             bsd => \&_ping_bsd,
46             darwin => \&_ping_darwin,
47             openbsd => \&_ping_unix,
48             freebsd => \&_ping_freebsd,
49             midnightbsd => \&_ping_freebsd,
50             next => \&_ping_next,
51             unicosmk => \&_ping_unicosmk,
52             netbsd => \&_ping_netbsd,
53             irix => \&_ping_unix,
54             aix => \&_ping_aix,
55             svr5 => \&_ping_unix, #SCO OpenServer
56             );
57            
58 5         95 my $subref = $dispatch{lc $^O};
59            
60 5 50       17 croak("External ping not supported on your system") unless $subref;
61            
62 5         128 return $subref->(%args);
63             }
64            
65             # Win32 is the only system so far for which we actually need to parse the
66             # results of the system ping command.
67             sub _ping_win32 {
68 0     0   0 my %args = @_;
69 0         0 $args{timeout} *= 1000; # Win32 ping timeout is specified in milliseconds
70             #for each ping
71 0         0 my $command = "ping -l $args{size} -n $args{count} -w $args{timeout} $args{host}";
72 0 0       0 print "#$command\n" if $DEBUG;
73 0         0 my $result = `$command`;
74 0 0       0 $LAST_OUTPUT = $result if $DEBUG_OUTPUT;
75 0         0 $LAST_EXIT_CODE = $!;
76 0 0       0 return 1 if $result =~ /time.*ms/;
77 0 0       0 return 1 if $result =~ /TTL/;
78 0 0       0 return 1 if $result =~ /is alive/; # ppt (from CPAN) ping
79             # return 1 if $result !~ /\(100%/; # 100% packages lost
80 0         0 return 0;
81             }
82            
83             # Mac OS X 10.2 ping does not handle -w timeout now does it return a
84             # status code if it fails to ping (unless it cannot resolve the domain
85             # name)
86             # Thanks to Peter N. Lewis for this one.
87             sub _ping_darwin {
88 0     0   0 my %args = @_;
89 0         0 my $command = "ping -s $args{size} -c $args{count} $args{host}";
90 0         0 my $devnull = "/dev/null";
91 0         0 $command .= " 2>$devnull";
92 0 0       0 print "#$command\n" if $DEBUG;
93 0         0 my $result = `$command`;
94 0 0       0 $LAST_OUTPUT = $result if $DEBUG_OUTPUT;
95 0         0 $LAST_EXIT_CODE = $!;
96 0 0 0     0 return 1 if $result =~ /(\d+) packets received/ && $1 > 0;
97 0         0 return 0;
98             }
99            
100             # Generic subroutine to handle pinging using the system() function. Generally,
101             # UNIX-like systems return 0 on a successful ping and something else on
102             # failure. If the return value of running $command is equal to the value
103             # specified as $success, the ping succeeds. Otherwise, it fails.
104             sub _ping_system {
105 5     5   22 my ($command, # The ping command to run
106             $success, # What value the system ping command returns on success
107             ) = @_;
108 5         15 my $devnull = "/dev/null";
109 5         14 $command .= " 1>$devnull 2>$devnull";
110 5 50       18 print "#$command\n" if $DEBUG;
111 5         1123205 $LAST_EXIT_CODE = system($command);
112 5         101 my $exit_status = $LAST_EXIT_CODE >> 8;
113 5 100       1281 return 1 if $exit_status == $success;
114 1         179 return 0;
115             }
116            
117             # Below are all the systems on which _ping_system() has been tested
118             # and found OK.
119            
120             # Assumed OK for DEC OSF
121             sub _ping_dec_osf {
122 0     0   0 my %args = @_;
123 0         0 my $command = "ping -c $args{count} -s $args{size} -q -u $args{host}";
124 0         0 return _ping_system($command, 0);
125             }
126            
127             # Assumed OK for unicosmk
128             sub _ping_unicosmk {
129 0     0   0 my %args = @_;
130 0         0 my $command = "ping -s $args{size} -c $args{count} $args{host}";
131 0         0 return _ping_system($command, 0);
132             }
133            
134             # NeXTStep 3.3/sparc
135             sub _ping_next {
136 0     0   0 my %args = @_;
137 0         0 my $command = "ping $args{host} $args{size} $args{count}";
138 0         0 return _ping_system($command, 0);
139             }
140            
141             # Assumed OK for HP-UX.
142             sub _ping_hpux {
143 0     0   0 my %args = @_;
144 0         0 my $command = "ping $args{host} $args{size} $args{count}";
145 0         0 return _ping_system($command, 0);
146             }
147            
148             # Assumed OK for BSD/OS 4.
149             sub _ping_bsdos {
150 0     0   0 my %args = @_;
151 0         0 my $command = "ping -c $args{count} -s $args{size} $args{host}";
152 0         0 return _ping_system($command, 0);
153             }
154            
155             # Assumed OK for BeOS.
156             sub _ping_beos {
157 0     0   0 my %args = @_;
158 0         0 my $command = "ping -c $args{count} -s $args{size} $args{host}";
159 0         0 return _ping_system($command, 0);
160             }
161            
162             # Assumed OK for AIX
163             sub _ping_aix {
164 0     0   0 my %args = @_;
165 0         0 my $command = "ping -c $args{count} -s $args{size} -q $args{host}";
166 0         0 return _ping_system($command, 0);
167             }
168            
169             # OpenBSD 2.7 OK, IRIX 6.5 OK
170             # Assumed OK for NetBSD & FreeBSD, but needs testing
171             sub _ping_unix {
172 0     0   0 my %args = @_;
173 0         0 my $command = "ping -s $args{size} -c $args{count} -w $args{timeout} $args{host}";
174 0         0 return _ping_system($command, 0);
175             }
176            
177            
178             sub _locate_ping_netbsd {
179 0 0   0   0 return '/usr/sbin/ping' if (-x '/usr/sbin/ping');
180 0         0 return 'ping';
181             }
182            
183             sub _ping_netbsd {
184 0     0   0 my %args = @_;
185 0         0 my $command = _locate_ping_netbsd()." -s $args{size} -c $args{count} -w $args{timeout} $args{host}";
186 0         0 return _ping_system($command, 0);
187             }
188             #-s size -c count -w timeout
189             #http://netbsd.gw.com/cgi-bin/man-cgi?ping++NetBSD-current
190            
191             # Assumed OK for FreeBSD 3.4
192             # -s size option supported -- superuser only... fixme
193             sub _ping_bsd {
194 0     0   0 my %args = @_;
195 0         0 my $command = "ping -c $args{count} -q $args{hostname}";
196 0         0 return _ping_system($command, 0);
197             }
198            
199             # Debian 2.2 OK, RedHat 6.2 OK
200             # -s size option available to superuser... FIXME?
201             sub _ping_linux {
202 5     5   22 my %args = @_;
203 5         8 my $command;
204             #for next version
205 5 50 33     282 if (-e '/etc/redhat-release' || -e '/etc/SuSE-release') {
206 0         0 $command = "ping -c $args{count} -s $args{size} $args{host}";
207             } else {
208 5         30 $command = "ping -c $args{count} $args{host}";
209             }
210 5         22 return _ping_system($command, 0);
211             }
212            
213             # Solaris 2.6, 2.7 OK
214             sub _ping_solaris {
215 0     0     my %args = @_;
216 0           my $command = "ping -s $args{host} $args{size} $args{timeout}";
217 0           return _ping_system($command, 0);
218             }
219            
220             # FreeBSD. Tested OK for Freebsd 4.3
221             # -s size option supported -- superuser only... FIXME?
222             # -w timeout option for BSD replaced by -t
223             sub _ping_freebsd {
224 0     0     my %args = @_;
225 0           my $command = "ping -c $args{count} -t $args{timeout} $args{host}";
226 0           return _ping_system($command, 0);
227             }
228            
229             #No timeout
230             #Usage: ping [-dfqrv] host [packetsize [count [preload]]]
231             sub _ping_cygwin {
232 0     0     my $which_ping = `which ping`;
233 0 0         if (!$which_ping) {
234 0           return;
235             }
236 0 0         if ($which_ping =~ m#/cygdrive/\w/WINDOWS/SYSTEM32/ping#i) {
237 0           return _ping_win32(@_);
238             }
239 0           my %args = @_;
240 0           my $command = "ping $args{host} $args{size} $args{count}";
241 0           return _ping_system($command, 0);
242             }
243            
244             1;
245            
246             __END__