#!/usr/bin/expect 

# Expect script to grab ifconfig interface throughput, second by second
# by jwbensley@gmail.com
# If you don't like it, fuck off.

#Long delay for those tricky hostnames

set timeout 60

# Prompt user for server host name/IP address, username, password, 
# path to `ifconfig`, interface to query (example: eth0), and query
# interval in seconds (default, 1)

send_user "Hostname: "
expect_user -re "(.*)\n"
set host $expect_out(1,string)

send_user "Username: "
expect_user -re "(.*)\n"
set user $expect_out(1,string)

# Don't show the password it is typed
stty -echo
send_user "Password: "
expect_user -re "(.*)\n"
set pass $expect_out(1,string)
send_user "\n"
stty echo

send_user "SSH port \[22\]: "
expect_user -re "(.*)\n"
set sshport $expect_out(1,string)
# Use 22 as the default SSH port if none is given
if { $sshport == "" } {
  set sshport 22
}

send_user "Path to 'ifconfig' \[\/sbin\/ifconfig\]: "
expect_user -re "(.*)\n"
set ifpath $expect_out(1,string)
# Use /sbin/ifconfig as the default path to ifconfig if none is given
if { $ifpath == "" } {
  set ifpath "/sbin/ifconfig"
}

send_user "Interface \[eth0\]: "
expect_user -re "(.*)\n"
set iface $expect_out(1,string)
# Use eth0 as the default interface if none is given
if { $iface == "" } {
  set iface "eth0"
}

send_user "Path to 'grep' \[\/bin\/grep\]: "
expect_user -re "(.*)\n"
set gpath $expect_out(1,string)
# Use /bin/grep as the default path to grep if none is given
if { $gpath == "" } {
  set gpath "/bin/grep"
}

set ifcmd "$ifpath $iface | $gpath bytes"

send_user "Interval in seconds \[1\]: "
expect_user -re "(.*)\n"
set delay $expect_out(1,string)
# Use 1 second as the default intrace polling intrval if no value is giving
if { $delay == "" } {
  set delay 1
}
send_user "\n"

#match_max 10000 # Pump up the match_max incase of large MOTD/Banners
# Connect to the host and login
spawn ssh $host -l $user -p $sshport
# Expect "assword:" as the 'p' in 'password' could be upper or lower case
expect "assword:"
send "$pass\r"
expect "$ "
puts ""

# From this point on we shall disable user output or they will see the "show int x"
# command output constantly
log_user 0

# Grab the current in/out bytes before we start the loop, to get a starting figure
send "$ifcmd\r"
expect "$ "

set ifbytes [open "ifbytes" "w"]
puts $ifbytes $expect_out(buffer)
close $ifbytes

set inbytesnow [exec grep "RX" ifbytes | cut -d : -f 2 | cut -d \  -f 1]
set outbytesnow [exec grep "RX" ifbytes | cut -d : -f 3 | cut -d \  -f 1]

set inbyteslast $inbytesnow
set outbyteslast $outbytesnow

# These variables will be presented at the end of the script when the below
# SIGINT handler is called
set totalinbytes 0
set totaloutbytes 0
set duration 0

# Here we will define a SIGINT handler, to catch the death of the script
# On exiting we shall pring out some session stats
proc sigint_handler {} {
  set inmegabytes [expr "$::totalinbytes" / 1000 / 1000]
  set outmegabytes [expr "$::totaloutbytes" / 1000 / 1000]
  puts "\nTotal duration $::duration seconds"
  puts "Total bytes received $::totalinbytes ($inmegabytes MBs)"
  puts "Total bytes sent $::totaloutbytes ($outmegabytes MBs)"
  puts "Average speed (bytes over duration)"
  set averagein [expr "$::totalinbytes" / "$::duration" / 1000 * 8]
  set averageout [expr "$::totaloutbytes" / "$::duration" / 1000 * 8]
  puts "In: $averagein Kbps \nOut: $averageout Kbps"
  exit
}
trap sigint_handler SIGINT

# Enter a continuous loop grabbing the number of bytes that
# have passed through an interface, each second.
# The different in this number each cycle, is essentially
# how much traffic this interface is pushing.

while { true } {
  send "$ifcmd\r"
  expect "$ "

  set ifbytes [open "ifbytes" "w"]
  puts $ifbytes $expect_out(buffer)
  close $ifbytes
  set inbytesnow [exec grep "RX" ifbytes | cut -d : -f 2 | cut -d \  -f 1]

  # Declare $diff outside of the if statements
  set diff 0

  if { $inbytesnow > $inbyteslast } {
    set diff [expr $inbytesnow - $inbyteslast]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $inbytesnow < $inbyteslast } {
    set diff [expr $inbyteslast - $inbytesnow]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $inbytesnow == $inbyteslast } {
    set diff 0
    set kbps 0
  }

  # Keep a tally of the total bytes received for a stats dump at the end
  set totalinbytes [expr "$totalinbytes" + "$diff"]

  set inbyteslast $inbytesnow
  set inkbps $kbps

  set outbytesnow [exec grep "RX" ifbytes | cut -d : -f 3 | cut -d \  -f 1]

  if { $outbytesnow > $outbyteslast } {
    set diff [expr $outbytesnow - $outbyteslast]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $outbytesnow < $outbyteslast } {
    set diff [expr $outbyteslast - $outbytesnow]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $outbytesnow == $outbyteslast } {
    set diff 0
    set kbps 0
  }

  # Keep a tally of the total bytes sent for a stats dump at the end
  set totaloutbytes [expr "$totaloutbytes" + "$diff"]

  set outbyteslast $outbytesnow
  set outkbps $kbps

  puts "Input: $inkbps Kbps Output: $outkbps Kbps\r"

  # Keep a record of the duration of this script for the stats dump at the end
  set duration [expr "$duration" + "$delay"]

  sleep $delay
}

