#!/usr/local/bin/wish -f
# NOTE: requires tcl 7.4 and tk 4.0
#
# tkppp - a graphical interface to control a PPP connection.
#
# Copyright 1995  Eric Jeschke (jeschke@cs.indiana.edu)
#
# All rights reserved.  Permission to use, copy, modify, and distribute
# this software and its documentation for any non commercial purposes and
# without fee is hereby granted, provided that the above copyright
# notice appear in all copies. No warranty is provided or implied.
# 
# I disclaim all warranties with regard to this software, including all
# implied warranties of merchantability and fitness. In no event shall I
# be liable for any special, indirect or consequential damages or any
# damages whatsoever resulting from loss of use, data or profits,
# whether in an action of contract, negligence or other tortuous action,
# arising out of or in connection with the use or performance of this
# software.
#
# Comments, bugfixes, patches welcome...
#
# RCS Version Info:
set rcsid "\$Id$"

#
# CHANGES CREDIT
#   - Show IP address used (jmmadiso@iupui.edu)
#

##############################################################
#                      System variables                      #
##############################################################
#
# These are the bitmaps that show the status of the PPP link.
#
#set bitmaps       @/usr/local/lib/tkppp
set bitmaps       @.
set pppup_bitmap  $bitmaps/arrup
set pppdn_bitmap  $bitmaps/arrdown

# See tkppprc for a description of these settings...
set ppp_on           {/usr/sbin/ppp-on}
set ppp_off          {/usr/sbin/ppp-off}
set wait_interval    90
set check_interval   10
set auto_minimize    0
set auto_maximize    1
set auto_ping        0
set auto_retry       0
set auto_reconnect   0
set ping_interval    160
set ping_command     {ping -c 1 $ipaddr >& /dev/null}
set show_hostname    0
set show_elapsed     1
set logfile_path     /dev/null

##############################################################
#                      Widget Resources                      #
##############################################################
#
# Common resources.
# --- Class ---
option add *activeBorderWidth		0		widgetDefault
option add *highlightThickness		0		widgetDefault
option add *insertBorderWidth		1		widgetDefault
option add *tearOff 			false		widgetDefault
option add *Button*cursor:		hand2		widgetDefault
option add *Entry.font			7x13		widgetDefault
option add *Menu.font		-Adobe-Helvetica-Medium-R-Normal--*-120-* \
							widgetDefault
option add *Menubutton.font	-Adobe-Helvetica-Bold-R-Normal--*-120-* \
							widgetDefault
option add *Text.font			8x13		widgetDefault
option add *Checkbutton.relief		flat		widgetDefault
option add *Checkbutton.font	-Adobe-Helvetica-Medium-R-Normal--*-120-* \
							widgetDefault
option add *Label.font		-Adobe-Helvetica-Medium-R-Normal--*-120-* \
							widgetDefault

# --- Specific ---
option add *ipaddr.font			9x15
option add *caption.font	-Adobe-Helvetica-Medium-R-Normal--*-120-* \
							widgetDefault
option add *msg.font		-Adobe-Helvetica-Bold-R-Normal--*-140-* \
							widgetDefault

# Color resources
if {[winfo depth .] >= 8} {
# --- Class ---
  option add *background		navajowhite3	widgetDefault
  option add *activeBackground		navajowhite1	widgetDefault
  option add *activeForeground		orangered	widgetDefault
  option add *Frame.background		navajowhite3	widgetDefault
  option add *Entry.background		navajowhite2	widgetDefault
  option add *Label.background		navajowhite3	widgetDefault
  option add *Menu.background		navajowhite2	widgetDefault
  option add *Menubutton.background	navajoWhite3	widgetDefault
  option add *Scrollbar.background	gray70		widgetDefault
  option add *Scrollbar.foreground	gray		widgetDefault
  option add *Text.background		navajowhite2	widgetDefault

# --- Specific ---
  option add *ipaddr.background		navajowhite2	widgetDefault
  option add *bitmap.background		navajowhite2	widgetDefault
  option add *msg.background		navajowhite3	widgetDefault
}

#---------- Edit below at your own risk! ------------

set aboutmsg {
tkppp v1.4
Copyright 1995
Eric Jeschke

Please send bug reports (details!), enhancements, patches,
comments, etc. to: jeschke@cs.indiana.edu

Thanks for using tkppp!
}

set linkstatus    -1
set wait_flag      1
set wait_count     0
set wait_id        0
set start_time     0
set debug          0
set statusmsg     {Initializing...}
set logformat     "%-18.18s  %-8.8s  %6.6s %6.6s  %6.6s  %s"
# ppp status info
set rerr           0
set terr           0

proc quit {} {
    destroy .
}

proc restart {} {
    global argv0
    set geom [wm geometry .]
    exec $argv0 -g $geom &
    destroy .
}

proc status {msg} {
    global debug
    .status.msg delete 0 1000
    .status.msg insert end $msg
    if {$debug} {puts stdout $msg}
    update
}

proc tmpstatus {msg sec} {
    status $msg
    after [expr {$sec * 1000}] setstatus
}

proc newstatus {msg} {
    global statusmsg
    status [set statusmsg $msg]
}

proc about {} {
    global aboutmsg
    tk_dialog .about "tkppp" $aboutmsg info 0 OK
}

proc pppinfo {} {
    global linkstatus rerr terr start_time show_elapsed log
    if {!$linkstatus} {
        catch {exec cat /proc/net/dev | grep ppp0:} pppinfo
        scan $pppinfo "%s %d %d %d %d %d %d %d %d %d %d %d" \
           junk rpak rerr rdrop rfifo rfr tpak terr tdrop tfifo tcoll tcar
        set log(errors) [expr {$rerr + $terr}]

        # Get the elapsed time connected.
        set time [exec date +%s]
        set diff [expr {$time - $start_time}]
        set hrs  [format "%02d" [expr {int ($diff / 3600)}]]
        set tmp  [expr {$diff % 3600}]
        set mins [format "%02d" [expr {round (($tmp / 60.0) + 0.5)}]]
        set log(elapsed) "$hrs:$mins"

        # Calculate cost of connection so far.
        if {[info commands conn_cost] != {}} {
            catch {
                set tmp [conn_cost $hrs $mins]
                set log(cost) [format "%2.2f" $tmp]
            }
        } else {set log(cost) 0}

        if {$show_elapsed} {
            set rerr $log(elapsed)
            set terr $log(cost)
        }
    }
}

proc setstatus {} {
    global linkstatus statusmsg ipaddr show_hostname log
    if {$linkstatus} {
        set statusmsg "PPP is DOWN"
    } else {
        set statusmsg "PPP is UP"
        # Get IP address used.
#        set ipaddr 0.0.0.0
#        while {$ipaddr == "0.0.0.0"} {
            catch {exec ifconfig | grep inet.\*P-t-P} tmp
            regexp {^.*P-t-P:([0-9\.]+).*$} $tmp dummy ipaddr
            set log(host) $ipaddr
#        }
        set statusmsg "Connected to $ipaddr"

        if {$show_hostname} {
            # Get IP name used.
            if [catch {exec nslookup $ipaddr | grep Name\:} tmp] {
                tmpstatus "\[nslookup error\]" 4
            } else {
                regexp {^.*Name:\ +([^\ ]+).*$} $tmp dummy ipname
                set statusmsg $ipname
                set log(host) $ipname
            }
        }
    }
    status $statusmsg
}

proc ppp-stat {flag id} {
    global linkstatus check_interval auto_minimize auto_maximize \
            pppup_bitmap pppdn_bitmap ipaddr show_hostname debug \
            wait_flag wait_count wait_id auto_reconnect statusmsg \
            start_time log

    if {$debug} {
       puts stdout "ppp_stat: f:$flag i:$id l:$linkstatus w:$wait_flag"
    }
    # Check status of PPP link: 0=up, 1=down 
    set oldstatus $linkstatus
#    set linkstatus [catch {exec ps augx | grep pppd | grep -vq grep}]
    set linkstatus [catch {exec ifconfig | grep ppp0} result]
    if {$oldstatus != $linkstatus} {
        if {!$linkstatus} {
            .top.bitmap config -bitmap $pppup_bitmap
            wm iconbitmap . $pppup_bitmap
            setstatus
            if {$auto_minimize} {wm iconify .}
            set wait_flag 0
            set start_time [exec date +%s]
            set log(start) [exec date {+%x %X}]
        } else {
            .top.bitmap config -bitmap $pppdn_bitmap
            wm iconbitmap . $pppdn_bitmap
            log-session
            setstatus
            if {$auto_maximize} {wm deiconify .}
            if {!$wait_flag && $auto_reconnect} {
                ppp-on
                newstatus "Link downed--Reconnecting ..."
            } else {set wait_flag 0}
        }
    }
    if {$flag} {
        pppinfo
        after [expr {$check_interval * 1000}] ppp-stat $flag $id
        return
    }
    if {$wait_flag && ($wait_id == $id)} {
        after 1000 ppp-stat 0 $id
        incr wait_count -1
        status "$statusmsg $wait_count"
    }
}

proc ping {} {
    global linkstatus ipaddr auto_ping ping_command \
         ping_interval wait_flag
    if {!$linkstatus && !$wait_flag && $auto_ping} {
        catch {eval "exec $ping_command"}
    }
    after [expr {$ping_interval * 1000}] ping
}

proc log-session {} {
    global log logformat logfile_path
    if {![file exists $logfile_path]} {
        set fd [open $logfile_path w]
        puts $fd [format $logformat Date User Total Cost Errors Host]
        close $fd
    }
    catch {
        set fd [open $logfile_path a]
        puts $fd [format $logformat $log(start) $log(user) $log(elapsed) \
                                    $log(cost)  $log(errors) $log(host) ]
        close $fd
    }
}

proc wait-status {flag opfl} {
    global wait_flag wait_count wait_id wait_interval linkstatus \
           auto_retry debug
    if {$debug} {puts stdout "wait-status: $flag $opfl"}
    set wait_flag $flag
    if {$flag} {
        set wait_count $wait_interval
        incr wait_id
        after [expr {$wait_interval * 1000}] "wait-status 0 $opfl"
        ppp-stat 0 $wait_id
    } else {
        set wait_count 0
        setstatus
        if {$linkstatus && $opfl && $auto_retry} {
            ppp-on
            newstatus "Connection failed--Retrying ..."
        }
    }
}

proc ppp-on {} {
    global ppp_on ppp_pid
    newstatus "Starting PPP..."
    if [catch {eval "exec $ppp_on &"} ppp_pid] {
        error $ppp_pid
    }
    wait-status 1 1
}

proc ppp-off {} {
    global ppp_off
    newstatus "Terminating PPP..."
    if [catch {eval "exec $ppp_off &"} errtxt] {
        error $errtxt
    }
    wait-status 1 0
}

proc ppp-abort {} {
    global ppp_pid
    newstatus "Aborting PPP..."
    exec kill -9 $ppp_pid
}

proc ppp-toggle {} {
    global linkstatus
    if {$linkstatus} ppp-on else ppp-off
}

proc toggleflag {var} {
    upvar $var flag
    set flag [expr {$flag ^ 1}]
    if {$flag} {set stat ON} else {set stat OFF}
    tmpstatus "$var is $stat" 2
}

proc toggle-time {} {
    global show_elapsed
    set w .top.data.addr
    if {$show_elapsed} {
        $w.lrerr config -text "Time:"
        $w.lterr config -text "Cost: $"
    } else {
        $w.lrerr config -text "RxErrs:"
        $w.lterr config -text "TxErrs:"
    }
}

proc addmenu {hdr lbl cmd} {
    set w .menu.$hdr
    $w.m add command -label $lbl -command $cmd
}

proc addscript {lbl cmd} {
    addmenu pgms $lbl $cmd
}

proc createwindow {} {
    global pppdn_bitmap auto_minimize auto_maximize show_hostname \
           show_elapsed auto_ping auto_retry wait_count rerr terr

    . config -bg [option get . background Toplevel]

    frame .menu -relief raised -borderwidth 1
    pack .menu -side top -fill x

    set w .menu.ppp
    menubutton $w -text "PPP" -menu $w.m
    menu $w.m
    $w.m add command -label "On"  -command ppp-on
    $w.m add command -label "Off" -command ppp-off
#    $w.m add command -label "Abort" -command ppp-abort
    $w.m add sep
    $w.m add command -label "Restart" -command restart
    $w.m add command -label "Exit" -command quit

    set w .menu.options
    menubutton $w -text "Options" -menu .menu.options.m
    menu $w.m
    $w.m add check -label "Show Hostname" -variable show_hostname \
                   -command setstatus
    $w.m add check -label "Show Elapsed" -variable show_elapsed \
	    -command { toggle-time; pppinfo }
    $w.m add check -label "Auto Minimize" -variable auto_minimize
    $w.m add check -label "Auto Maximize" -variable auto_maximize
    $w.m add check -label "Auto Retry"    -variable auto_retry
    $w.m add check -label "Auto Reconnect" -variable auto_reconnect
    $w.m add check -label "Auto Ping"     -variable auto_ping

    set w .menu.pgms
    menubutton $w -text "Run" -menu .menu.pgms.m
    menu $w.m

    set w .menu.help
    menubutton $w -text "Help" -menu .menu.help.m
    menu $w.m
    $w.m add sep
    $w.m add command -label "About" -command about

    set w .menu
    pack $w.ppp $w.options $w.pgms -side left
    pack $w.help -side right
    tk_menuBar $w $w.ppp $w.options $w.pgms $w.help

    set w .top
    frame $w
    button $w.bitmap -bitmap $pppdn_bitmap -cursor hand2 \
                     -command ppp-toggle

    frame .top.data
    set w .top.data.cbox
    frame $w
    checkbutton $w.ar -text "Retry"     -variable auto_retry
    checkbutton $w.ac -text "Reconnect" -variable auto_reconnect
    checkbutton $w.ap -text "Ping"      -variable auto_ping
    pack $w.ar $w.ac $w.ap -side left -pady 0 -fill x -expand no
    pack $w -side top

    set w .top.data.addr
    frame $w
    label $w.lrerr  -text "Time:"
    entry $w.ererr  -relief ridge -border 2 -width 5 -textvariable rerr
    pack $w.lrerr $w.ererr -side left -expand no
    label $w.lterr  -text "Cost: $"
    entry $w.eterr  -relief ridge -border 2 -width 5 -textvariable terr
    pack $w.lterr $w.eterr -side left -expand no
    pack $w -side top -pady 2 -fill x -expand no

    pack .top.bitmap -side left  -pady 6 -padx 8 -expand no
    pack .top.data   -side right -fill x -pady 2 -padx 8 -expand no
    pack .top -side top -fill x -expand no

    frame .status
    entry .status.msg -text "PPP Status" -relief flat
    pack .status.msg -side top -padx 4 -fill x -expand no
    pack .status -side top -fill x -expand yes

    wm minsize . 10 10
    wm title . tkppp  
    wm iconname . PPP
    wm iconbitmap . $pppdn_bitmap
    bind . <Q> quit
    bind . <Control-R> restart
    bind . <o> ppp-on
    bind . <f> ppp-off
    bind . <k> ppp-abort
    bind . <l> log-session
    bind . <r> "toggleflag auto_retry"
    bind . <c> "toggleflag auto_reconnect"
    bind . <p> "toggleflag auto_ping"
    bind . <i> {wm iconify .}
    bind . <s> setstatus
    tk_bindForTraversal .
}

##############################################################
#                        Main program                        #
##############################################################

createwindow
catch {source $env(HOME)/.tkppprc}
status $statusmsg
toggle-time
update
set log(user) [exec whoami]
ppp-stat 1 0
ping
