#!/usr/bin/ruby1.8
#
# NAME
#   multi-ping - IPv4 and IPv6 ping tool
#
# SYNOPSIS
#  multi-ping  [ -h | --help ] [-m | --manual] hostname1
#
# OPTIONS
#
#  -h, --help              Show a help message, and exit.
#
#  -m, --manual            Show this manual, and exit.
#
#  -v, --verbose           Show verbose errors
#
# ABOUT
#
#  The multi-ping tool is designed to be IPv4/IPv6-agnostic ping tool,
# which removes the need to know if you're pinging an IPv4 host or an
# IPv6 host.
#
#  The tool works by resolving the hostname specified upon the command line,
# and invoking "ping" or "ping6" upon the result - using the correct one for
# the address which has been returned.
#
# AUTHOR
#
#  Steve Kemp  <steve@bytemark.co.uk>
#


require 'getoptlong'
require 'socket'



#
#  Options set by the command-line.  These are all global.
#
$help   = false
$manual = false

opts = GetoptLong.new(
                      [ '--help',   '-h', GetoptLong::NO_ARGUMENT ],
                      [ '--manual', '-m', GetoptLong::NO_ARGUMENT ] )

begin
  opts.each do |opt,arg|
    case opt
    when '--help'
      $help = true
    when '--manual'
      $manual = true
    end
  end
rescue => err
  # any errors, show the help
  warn err.to_s
  $help = true
end


#
# CAUTION! Here be quality kode.
#
if $manual or $help

  # Open the file, stripping the shebang line
  lines = File.open(__FILE__){|fh| fh.readlines}[1..-1]

  found_synopsis = false

  lines.each do |line|

    line.chomp!
    break if line.empty?

    if $help and !found_synopsis
      found_synopsis = (line =~ /^#\s+SYNOPSIS\s*$/)
      next
    end

    puts line[2..-1].to_s

    break if $help and found_synopsis and line =~ /^#\s*$/

  end

  exit 0
end




#
#  Get the address to ping.
#
hostname = ARGV.shift

#
#  If we have no host then abort
#
if ( hostname.nil? )
  puts "Usage: #{$0} hostname"
  exit 1
end


#
#  The IP we'll deal with
#
ip = nil


#
#  Lookup the IP, catching any exception
#
begin
  Socket.getaddrinfo(hostname, 'echo').each do |a|
    ip = a[3]
  end
rescue SocketError
  puts "Failed to resolve: #{hostname}"
  exit 1
end


#
#  Was the result an IPv4 address?
#
if ( ip =~ /^([0-9]+).([0-9]+).([0-9]+).([0-9]+)$/ )

  #
  #  If so invoke "ping"
  #
  if ( system( "ping -c 1 #{ip} 2>/dev/null >/dev/null" ) == true )
    puts "#{hostname} alive."
    exit 0
  else
    puts "ping4 failed - #{hostname} [#{ip}]"
    exit 1
  end
elsif ( ip =~ /2001/ )

  #
  #  Was the result an IPv6 address?
  #
  if ( system( "ping6 -c 1 -w1 #{ip} 2>/dev/null >/dev/null" ) == true )
    puts "#{hostname} alive."
    exit 0
  else
    puts "ping6 failed - #{hostname} [#{ip}]"
    exit 1
  end
end


#
#  All done.
#