#!/bin/bash

# the script shows periodically updated network traffic for a given device
# eth0 if no device specified
#
# my_format function is taken from 
# http://www.bralug.de/wiki/Runden_und_Formatieren_von_Zahlen_in_der_bash
#
# original version:
# http://www.downtown-dmz.de/download/iffoo
#
# this modded version:
# http://d1sturbed.org/iffoo
#
# last modified on 18 07 2008
# Changelog:
# 18 07 2008
# added compact modus, just add "-c"

INTERFACE=${1-"eth0"}
SLEEP="2"
COMPACT=0

function my_format () 
{
    # 1.Uebergabeparameter ist die Zahl
    zahl=$1
    # Vorsatzzeichen und Teiler bestimmen
    if [ $zahl -gt 999999999 ] ; then 
	t=1000000000
	e=G
    else
	if [ $zahl -gt 999999 ] ; then
	    t=1000000
	    e=M
	else
	    if [ $zahl -gt 999 ] ; then
		t=1000
		e=K
	    else    
		# gleich ausgeben, es muss nichts formatiert werden
		printf "%5d\033[0m" $zahl
		return
	    fi
	fi
    fi
    # Runden und ganzzahligen Teil berechnen
    z1=$((($zahl+($t/20))/$t))
    # Rest auf eine Stelle berechnen
    z2=$(((($zahl+($t/20))%$t)/($t/10)))
    # und ausgeben
    if [ $COMPACT -ne 1 ]; then
    	printf "%3d.%1d\033[0m %s" $z1 $z2 $e
    else
    	printf "%3d.%1d\033[0m%s" $z1 $z2 $e
    fi
    return
}

function getIP() {
        ip=`/sbin/ifconfig $1 | awk 'NR==2 {  split($2, out, ":"); print out[2]; }'`
	if [ "x$ip" == "x" ]; then
		echo -n "IP not set"
	else
        	echo -n $ip
	fi
}


function output () {
	#verantwortlich fuer die ausgabe der einzelnen interfaces
	if [ $COMPACT -ne 1 ]; then
		echo -n "$1: "
		getIP $1
		echo -en "\n\n Rx:\033[1;32m "
		my_format $2
		echo -e "Byte/s"
		echo -en " Tx:\033[1;34m "
		my_format $3
		echo -e "Byte/s\n"
	else
		echo -ne "$1:\t"
		getIP $1
		echo -ne "\trx:\t\033[1;32m\t"
		my_format $2
		echo -ne "\ttx:\t\033[1;34m\t"
		my_format $3
	fi
}

#liest die rx bytes aus und gibt sie nach stdin aus
function getRX() {
	rx=$(awk '/'$1'/ {  split($1, out, ":"); if(out[2]=="") print $2; else print out[2] }' /proc/net/dev)
	echo $rx
}

#liest die tx bytes aus und gibt sie nach stdin aus
function getTX() {
	tx=$(awk '/'$1'/ {  split($1, out, ":"); if(out[2]=="") print $10; else print $9 }' /proc/net/dev)
	echo $tx
}

#holt sich von ifconfig die geuppten interfaces und vergleicht sie mit einem uebergebenem interface
#gibt 0 zurueck wenn das interface nicht up ist
function isUp() {
	upped_ifs=`/sbin/ifconfig | awk '/^[a-z]/ { print $1 }'`
	for myif in $upped_ifs; do
		if [ $myif = $1 ]; then
			return 1
		fi
	done
	return 0
}

#pruefen ob mehr als ein parameter oder "-a" uebergeben wurde
#um die ausgabe fuer mehrere interfaces anzupassen
if [ "x$1" = "x-a" -o ${#@} -gt 1 ]; then
	echo $@ | grep "\-c" >& /dev/null
	if [ $? -eq 0 ]; then
		COMPACT=1
	fi
	#wenn -a uebergeben wurde alle interfaces auslesen und in die liste aller interfaces schreiben
	all_ifs=`awk -F":" 'NR>2 { print $1 }' /proc/net/dev`
	#wenn eine liste mit mehreren interfaces uebergeben wurde diese als liste mit interfaces setzen
	if [ ${#@} -gt 1 -a $COMPACT -ne 1 ]; then
		all_ifs=$@
	fi
	#zaehler fuer unser array
	i=0
	for INTERFACE in $all_ifs; do
		#pruefen ob das aktuelle interface up ist
		isUp $INTERFACE
		#wenns up ist rein in unser array mit den aktiven devices
		if [ $? -eq 1 ]; then
			#interfacename
			face[$i]=$INTERFACE
			#rxbytes holen
			rxlast[$i]=`getRX $INTERFACE`
			#txbytes holen
			txlast[$i]=`getTX $INTERFACE`
			#i inkrementieren ;)
			i=$((i+1))
		fi
	done
	#i dekrementieren ;)
	i=$((i-1))
	#ein wenig warten um informationen zu bekommen um die geschwindigkeit auszulesen
	echo "waiting"
	sleep $SLEEP
	clear
	#benchmark, wenn die whileschleife schnell genug abgearbeitet ist koennen wir mit unseren ausgaben
	#anfangen ohne gefahr zu laufen das die maschine diese garnicht so schnell berechnen kann
	while [ true ]; do
		#alle interfaces durchlaufen
		for j in `seq 0 $i`; do
			#holen tx/rx
			rxact[$j]=`getRX ${face[$j]}`
			txact[$j]=`getTX ${face[$j]}`
			#rechnen, versteh ich nich so wirklich, aber okay ;)
			rxrate[$j]=$(((${rxact[$j]}-${rxlast[$j]})/$SLEEP))
			txrate[$j]=$(((${txact[$j]}-${txlast[$j]})/$SLEEP))
			#eine variable in eine andere schreiben
			rxlast[$j]=${rxact[$j]}
			txlast[$j]=${txact[$j]}
			#ausgebs0rn
			output ${face[$j]} ${rxrate[$j]} ${txrate[$j]}
    			if [ $COMPACT -eq 1 ]; then
				echo 
			fi
		done
		#man kann prozesse mit CTRL+C beenden, das wird hier kaltbluetig ausgenutzt
    		if [ $COMPACT -ne 1 ]; then
			echo -ne "\nPress CTRL + C to stop"
		fi
		sleep $SLEEP	
		clear
	done
else
	#das gleiche fuer ein interface ;)
	if [ "$INTERFACE" == "-c" ]; then
		COMPACT=1
		INTERFACE="eth0"
	fi
	isUp $INTERFACE
	if [ $? -eq 0 ]; then
		echo $INTERFACE not up
		exit 0;
	fi
	rxlast=`getRX $INTERFACE`
	txlast=`getTX $INTERFACE`
	clear
	echo "waiting"
	sleep $SLEEP
	clear
	while [ true ]; do
		if [ -z "$rxlast" -o -z "$txlast" ]; then
			echo $INTERFACE does not exist
			break;
		fi
		rxact=`getRX $INTERFACE`
		txact=`getTX $INTERFACE`
		rxrate=$((($rxact-$rxlast)/$SLEEP))
		txrate=$((($txact-$txlast)/$SLEEP))
		rxlast=$rxact
		txlast=$txact
		output $INTERFACE $rxrate $txrate
    		if [ $COMPACT -ne 1 ]; then
			echo -ne "\nPress CTRL + C to stop"
		fi
		sleep $SLEEP	
		clear
	done
fi
