#!/usr/local/bin/python

import os, string, sys
import ExpectPy
if ExpectPy.re_type == 're':
  _digits_re = r'\d'
elif ExpectPy.re_type == 'tclre':
  _digits_re = '[0-9]'
#ExpectPy.settings.internal = 1

try:
  Exception
  class Unreachable(Exception):
    pass
  class MissingPacket(Exception):
    pass
except NameError:
  Unreachable = 'Ping.unreachable'
  MissingPacket = 'Ping.missingpacket'

class Ping:
  if ExpectPy.re_type is None:
    raise SystemExit, 'Regular expression support is required'
  icmp_seq_patt = '.*icmp_seq=(%s+). time=(%s+). ms\r\n' % \
    (_digits_re, _digits_re)
  unreachable_patt = 'ICMP Host Unreachable .*\r\n for icmp.*\r\n'
  bytes_re = 'PING * data bytes\r\n'

  timeout = 2
  if sys.platform == 'sunos5':
    program = '/usr/sbin/ping'
    progarg = '-s'
  elif sys.platform == 'aix4':
    program = '/etc/ping'
    progarg = ''
  else:
    program = 'ping'
    progarg = '-s'

  def __init__(self, hostname):
    self.host = hostname
    progname = os.path.basename(self.program)
    if self.progarg:
      id = ExpectPy.spawn(self.program, progname, self.progarg, self.host)
    else:
      id = ExpectPy.spawn(self.program, progname, self.host)
    try:
      rc = id.expect(
        (ExpectPy.GLOB, self.bytes_re, 0),
        (ExpectPy.EXACT, "ping: unknown host %s\r\n" % hostname, 1)
      )
      if rc == 1:
        raise ValueError, "Unknown host: %s" % hostname
    except ExpectPy.timeout:
      pass
    except EOFError:
      id.close()
      raise SystemError, "Program not started correctly"

    self.icmp_seq_re = ExpectPy.compile(self.icmp_seq_patt)
    self.unreachable = ExpectPy.compile(self.unreachable_patt)
    self.spawn = id
    self.clear()

  def __del__(self):
    self.close()
  def close(self):
    try:
      self.spawn.close()
    except:
      pass

  def clear(self):
    self.last = -1
    self.number = 0
    self.total = 0
    self.trtt = 0L
    self.time = 0

  def fileno(self):
    return self.spawn.fileno()

  def next(self):
    ExpectPy.settings.timeout = self.timeout
    try:
      info = self.spawn.expect(
        # (ExpectPy.GLOB, self.bytes_re, 1), # ignore this clause
        (ExpectPy.COMPILED, self.icmp_seq_re, self.packet),
        (ExpectPy.COMPILED, self.unreachable, self.cant_reach),
      )

    except ExpectPy.timeout:
      return
    else:
      self.total = self.total + 1
      return info

  def packet(self, line, match=None):
    if ExpectPy.re_type == 're':
      num, time = match.group(1, 2)
    else:
      num, time = match[1], match[2]
    num, time = string.atoi(num), string.atoi(time)
    last, self.last = self.last, num
    self.number, self.time = self.number + 1, time
    self.trtt = self.trtt + time
    if num != (last + 1):
      raise MissingPacket
    return num, time

  def cant_reach(self, line, match=None):
    raise Unreachable

  def droprate(self):
    "Percentage rate of packets dropped."
    return int((self.total * 100) / self.number)

  def ave(self):
    "Average round-trip time."
    return int(self.trtt / self.number)

def _test():
  ping = Ping('localhost')
  while 1:
    num, time = ping.next()
    if time == None:
      pass # ignore
    else:
      print num, time, ping.ave()

if __name__ == '__main__':
  try:
    _test()
  except KeyboardInterrupt:
    pass

