#! /bin/bash

# ADSL menu interface

# Copyright 2006 Andrew McGill and Intoweb Pty Ltd
# May be distributed under terms of the GPL, version 2 or later
ID='$Id: adslmenu,v 1.5 2006/07/11 11:09:43 andrewm Exp $'
VERSION=$( echo "$ID" | cut -f "3" -d " " )

DIALOG="dialog --clear"
CHOICE=$HOME/.dialog-stuff

function pause()
{
	echo -ne "Press Enter to return to the menu ..."
	read -t 600 STUFF || echo 
}

function domenu()
{
$DIALOG 2> $CHOICE \
	--menu "adslmenu revision $VERSION" 20 60 10 \
	"status"	"View status" \
	"log"		"Show log messages (unprocessed)" \
	"reconfig"	"Enter new user name and password" \
	"stop"		"Stop the ADSL connection" \
	"start"		"Start the ADSL connection" \

CHOSEN="`cat $CHOICE`"
echo
echo
case "$CHOSEN" in
	[a-z]*) 	$0 "$CHOSEN"; pause;;
	*)		exit 0 ;;
esac
}

# inputbox  
function inputbox()
{
       $DIALOG --inputbox "$1" 20 60 "$2" < /dev/tty 2>&1 >/dev/tty
}

function do_reconfig()
{

	PPPOECONF=/etc/ppp/pppoe.conf

	ALT=/etc/sysconfig/network-scripts/ifcfg-ppp0
	[ -f $ALT ] && PPPOECONF=$ALT

	if [ "$1" ] ; then
		USER="$1"
	else
		# Interactive edit
		source $PPPOECONF 2>/dev/null
		USER=$(	inputbox "Username: the user name for your ADSL account" \
			"$USER" )
	fi

	if [ "$2" ] ; then
		PASSWD="$2" 
	else
		# Interactive edit
		# Get old password
		eval "PASSWD=`awk '/'$USER'/ { print $3 ; exit; }' /etc/ppp/pap-secrets`"
		PASSWD=$(inputbox "Password: the password for your ADSL account" \
			   "$PASSWD" )
		if [ "$PASSWD" = "" ] ; then
			echo "There is no old password to use, sorry"
			exit
		fi
	fi

	# Set user name in /etc/ppp/pppoe.conf
	perl -p -i -e '
		$user='\'"$USER"\'';
		s/^\s*USER=.*/USER="$user"/
		' $PPPOECONF

	# Remove old password and set new one in /etc/ppp/pap-secrets
	perl -p -i -e '
		$user='\'"$USER"\'';
		$passwd='\'"$PASSWD"\'';
		s/^"?$user.*// && s/^\n//;
		' /etc/ppp/pap-secrets 
	perl -e '  # of course, we could use echo instead ...
		$user='\'"$USER"\'';
		$passwd='\'"$PASSWD"\'';
		print "\"$user\"\t*\t\"$passwd\"\n";
		' >> /etc/ppp/pap-secrets
	echo
	echo "I've modified $PPPOECONF and /etc/ppp/pap-secrets."
	echo "Your account is (user) $USER (password) $PASSWD"
	echo "You MUST restart the ADSL connection for the new settings to take effect."
}


function do_logview()
{
< /var/log/messages grep 'pppd\|pppoe\|adsl' | tail -25
}

# List the ppp devices, 
# e.g.
#   ppp0 (165.165.33.31) 413921-tx/12415-rx
function list_ppp_devices()
{
	ifconfig | perl -n -e '
		BEGIN {
			$prefix="'"$1"'";
		}
		if (m/^$/) { $dev=""; }
		elsif (m/^lo/) { next; }
		elsif (m/^(\S+)/) { $dev=$1; }
		if (m/inet addr: *([0-9.]*)/ && $dev ne "" ) { $ip=$1; }
		if (m/TX bytes: *([0-9.]*)/ && $dev ne "" ) {
			$tx=$1;
		}
		if (m/RX bytes: *([0-9.]*)/ && $dev ne "" ) {
			$rx=$1;
			$data=$tx + $rx;
			if ($data > 1024*1024) {
				$data=sprintf("%.1fMb",$data/1024/1024);
			}
			elsif ($data > 1024) {
				$data=sprintf("%.1fkb",$data/1024);
			}
			$note="";
			if ($dev =~ m/^eth/) {
				$stat=qx{ethtool $dev 2>&1 };
				if ($stat =~ m/Link detected: no/) {
					$note="CABLE DISCONNECTED";
				}
			}
			print "$prefix$dev ($ip) $data $note\n";
			$dev = "";
		}
		END {
			if ($tx eq "") {
				print "No active ppp device\n";
			}
		}
	'
}

function my_pidof()
{
	ps -e | awk '($4 == "'"$1"'") { print $1 }' | grep .
}

function parse_adsl_log()
{
	MESSAGES=/var/log/messages
	if [ ! -r $MESSAGES -a -r messages ] ; then MESSAGES=messages; fi
	perl -n -e < $MESSAGES '
		BEGIN {
			$prefix="'"$1"'";
		}
		if (m/^(\S+\s+\d+ [\d+:]*)/) { $now = $1; } else { next; }
		s/Input\/output/IO/;
		if (m/ (pppd|pppoe)\[\d+\]: (.*)/) {
			$prog=$1;
			$msg = $2;
			if ($prog eq "pppd" && $msg =~ m/Exit/) {
				# PPPD exit - print the summary::
				print "$prefix$now $data$time$lastoe$last\n";
				$data="";
				$time="";
				$last="";
				$lastoe="";
			}
			if ($msg =~ m/Connection terminated/) { next; }
			elsif ($msg =~ m/PADS: Service-Name/) { next; }
			elsif ($msg =~ m/PPP session is \d/) { next; }
			elsif ($msg =~ m/Connect: ppp\d/) { $last=""; next; }
			elsif ($msg =~ m/Modem hangup/) { next; } # we always hangup
			elsif ($msg =~ m/Sent PADT/) { next; } # we always send PADT
			elsif ($msg =~ m/Script .* finished/) { next; }
			elsif ($msg =~ m/Connect time ([\d.]*) *min/) {
				$min=$1;
				$time=sprintf(
					"%dh%02d.%02d ",
					$min/60,
					$min % 60,
					60*($min-int($min)) );
			}
			elsif ($msg =~ m/Sent (\d+) bytes.*?(\d+) bytes/) { 
				$data=$1 + $2;
				if ($data > 1024*1024) {
					$data=sprintf("%.1fMb",$data/1024/1024);
				}
				elsif ($data > 1024) {
					$data=sprintf("%.1fkb",$data/1024);
				}
				$data = "$data ";
			}
			elsif ($msg =~ m/Session \d+ terminated[ -]*(.*)/) { $lastoe="$1 "; }
			elsif ($msg =~ m/read \(asyncReadFromPPP\): Session \d+: (.*)/) { $lastoe="$1 "; }
			elsif ($msg =~ m/(.*)Session \d+(.*): /) { $lastoe="$1$2 "; }
			else { 
				if ($prog eq "pppd") {
					$last = $msg;
				}
				else {
					$lastoe = "$msg ";
				}
			}
		}
	'
}

function check_gateway()
{
PREFIX="$1"
{
route -n | awk '($1 == "0.0.0.0") { print $2, "Default gateway"; }'
echo 196.43.1.11       SAIX DNS server
echo ping.ledge.co.za  International link
} | while read GW INFO ; do
	perl -e '
		$gw="'"$GW"'";
		$prefix="'"$PREFIX"'";
		$info="'"$INFO"'";
		print "$prefix$gw: ";
		$ping = qx{ ping -c 1 -w 2 $gw 2>&1 };
		$loss=100;
		$rx=0;
		if ($ping =~ m/(\d+) received/) { $rx=$1; }
		if ($ping =~ m/(\d+)% packet loss/) { $loss=$1; }
		if ($rx==0 && $loss==100) {
			# Try to work out the reason
			if ($ping =~ m/Unreachable/i) {
				print "FAILED - unreachable";
			}
			elsif ($ping =~ m/no route/i) {
				print "FAILED - no route";
			}
			elsif ($ping =~ m/unknown host/i) {
				print "FAILED - DNS failure";
			}
			elsif ($ping =~ m/Time to live/i) {
				print "FAILED - TTL exceeded";
			}
			else {
				print "FAILED - timeout";
			}
		}
		else {
			print "OK";
		}
		print "  ($info)\n";
	'
done

}

function do_status()
{
echo "Most recent connections:"
parse_adsl_log "  " | tail -4 | tac
echo "Active network devices:"
# ifconfig
#    ppp (ip address, bytes tx, bytes rx)
list_ppp_devices "  "
echo "Processes:"
#    adsl-connect (number of times, start time)
#    pppd (number of times, start time)
#    pppoe (number of times, start time)
echo "  adsl-connect:" `my_pidof adsl-connect || echo missing`
echo "  pppd:" `my_pidof pppd || echo missing`
echo "  pppoe:" `my_pidof pppoe || echo missing`
echo "Network tests:"
check_gateway "  "
}

case "$1" in 
    "")		while true; do domenu ; done ;;
    status)	do_status ;;
    log)	do_logview ;;
    reconfig)	do_reconfig $2 $3 ;;
    stop)	poff dsl-provider; adsl-stop ; sleep 10 ;;
    start)	pon dsl-provider; adsl-start ;;
    *)
  	echo "Usage $0 [command]"
	echo "Commands:"
	echo "  status        View status"
	echo "  log           Show log messages (unprocessed)"
	echo "  reconfig      set new user and password"
	echo "  stop          Stop the ADSL connection"
	echo "  start         Start the ADSL connection" 
	echo "  (default)     show a menu"
	echo "This is adslmenu revision $VERSION"
	;;
esac


exit
# Tests
# Processes running:
#    adsl-connect (number of times, start time)
#    pppd (number of times, start time)
#    pppoe (number of times, start time)
# ifconfig
#    ppp (ip address, bytes tx, bytes rx)
# tests
#    DNS resolution
#    ping (default gw, SAIX DNS, ping.ledge.co.za)
# processed log:
#    last exit status/message of pppd (date)
#    last exit status/message of pppoe (date)
