#!/usr/local/bin/wish8.4
#
#  TkDeviceView.tcl  (c) vfom 13.05.2002
# 
#  Need UCD-SNMP package installed.
#
package require msgcat
package require BLT
set snmpget_prog	"/usr/local/bin/snmpget -OQu -v 1 -c"
set snmpwalk_prog	"/usr/local/bin/snmpwalk -OQu -v 1 -c"
#
set ::host	  [ lindex $argv 0 ]
set ::community	  [ lindex $argv 1 ]
#
#
set askForHost_exitFlag 0
set askForInterface_exitFlag 0
set snmp_exitFlag ""
set tmpSnmp ""
set errSnmp ""


proc GetSysInfo { h c } {

    set x3 ""
    catch { eval  blt::bgexec ::snmp_exitFlag -output ::tmpSnmp -error ::errSnmp \
	$::snmpget_prog $::community $::host \
	RFC1213-MIB::system.sysDescr.0 RFC1213-MIB::system.sysName.0 RFC1213-MIB::system.sysUpTime.0 RFC1213-MIB::system.sysLocation.0 RFC1213-MIB::system.sysContact.0
    }
    if { [string match $::tmpSnmp "" ] } {
	tk_dialog .snmpError [msgcat::mc "SNMPget Error"] \
	    "Can't retriev SNMP data from \"$::host\": $::errSnmp" \
	    error 0 [msgcat::mc "Approve" ]
    } else {
	foreach str [ split $::tmpSnmp "\n" ] {
	    set x [ split $str "="]
	    set x1 [lindex $x 0] 
	    set x2 [lindex $x 1] 
#	    if { [regexp $ifnam  $x2 ] } {
#		regsub {interfaces\.ifTable\.ifEntry\.ifDescr\.} $x1 {} x3 
#	    }
	    set x3 [ concat $x3 "\n" $x2]
	}
    }
#    return $x3
    return $::tmpSnmp
}

proc GetIfIndexByName { ifnam } {
    set x3 ""
    catch { eval  blt::bgexec ::snmp_exitFlag -output ::tmpSnmp -error ::errSnmp \
	$::snmpwalk_prog $::community $::host interfaces.ifTable.ifEntry.ifDescr
    }
    if { [string match $::tmpSnmp "" ] } {
	tk_dialog .snmpError [msgcat::mc "SNMPget Error"] \
	    "Can't retriev SNMP data from \"$::host\": $::errSnmp" \
	    error 0 [msgcat::mc "Approve" ]
    } else {
	foreach str [ split $::tmpSnmp "\n" ] {
	    set x [ split $str "="]
	    set x1 [lindex $x 0] 
	    set x2 [lindex $x 1] 
	    if { [regexp $ifnam  $x2 ] } {
		regsub {interfaces\.ifTable\.ifEntry\.ifDescr\.} $x1 {} x3 
	    }
	}
    }
    return $x3
}
#
proc GetIfList { } {
    set tmp_list [ list ]
    catch { eval  blt::bgexec ::snmp_exitFlag -output ::tmpSnmp -error ::errSnmp \
	$::snmpwalk_prog $::community $::host interfaces.ifTable.ifEntry.ifDescr
    }
    if { [string match $::tmpSnmp "" ] } {
	tk_dialog .snmpError [msgcat::mc "SNMPget Error"] \
	    "Can't retriev SNMP data from \"$::host\": $::errSnmp" \
	    error 0 [msgcat::mc "Approve"] 
    } else {
	foreach str [ split $::tmpSnmp "\n" ] {
	    lappend tmp_list [string trim [ lindex [split $str "=" ] 1 ]]
	}
    }
    return $tmp_list
}
#
proc AskForHost { } {

    set w .askForHost

    if {[ winfo exists $w ]} then  {
	raise $w ;
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "Host and community"]
    wm withdraw $w

    set we $w.entryFrame
    frame $we
    pack $we -side top
    label $we.lhst -text [msgcat::mc "Host:" ]
    entry $we.ehst -width 16
    $we.ehst insert 0 $::host
    label $we.lcomm -text [msgcat::mc "Community:"]
    entry $we.ecomm -width 16
    $we.ecomm insert 0 $::community
    
    pack $we.lhst $we.ehst $we.lcomm $we.ecomm -padx 5 -pady 5
         	
    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text "Ok" -command {
	set ::host [.askForHost.entryFrame.ehst get ]
	set ::community [.askForHost.entryFrame.ecomm get ]	
	set ::askForHost_exitFlag 1
    }
    button $wb.cancel -text [msgcat::mc "Cancel"] -command "set ::askForHost_exitFlag 2"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5
    bind $w <Return> "$wb.ok invoke"
    focus $we.ehst
    
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    wm deiconify $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $wb.ok

    tkwait variable ::askForHost_exitFlag

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    if { $::askForHost_exitFlag == 2 } {
	destroy .
	exit
    }
    return  
}
#
proc AskForInterface {} {
    set w .askForInterface
    if {[ winfo exists $w ]} then  {
	raise $w ;
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "Select interface"]
    wm withdraw $w

    set f $w.entryFrame
    frame $f
    pack $f -side top -padx 5 -pady 5 -expand on -fill both
    grid rowconfig	$f 0 -weight 1 -minsize 0
    grid columnconfig   $f 0 -weight 1 -minsize 0
	
    listbox $f.sl -width 32 -height 16 -selectmode single \
	-yscrollcommand "$f.sy set"
    scrollbar $f.sy -command "$f.sl yview"
    grid $f.sl -in $f -row 0 -column 0 -sticky news
    grid $f.sy -in $f -row 0 -column 1 -sticky news         
    
    foreach i [ lsort [ GetIfList ] ] { $f.sl insert end $i }
    	
    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text [msgcat::mc "Ok"] -command "set ::askForInterface_exitFlag 1"
    button $wb.cancel -text [msgcat::mc "Cancel"] -command "set ::askForInterface_exitFlag 2"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5
    bind $w <Return> "$wb.ok invoke"
    focus $f.sl
    
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    wm deiconify $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $wb.ok
    set sel ""

    tkwait variable ::askForInterface_exitFlag
    set ind [ $f.sl curselection ] 
    if { $ind !="" } { 
	set sel [$f.sl get [ $f.sl curselection ] ]
    }

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return  $sel
}
#
proc showAbout {} {
    global appName appVersion v_about
    set w .about
    set v_about ""
    if [winfo exists $w ] {
	raise $w
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "$appName: About"]
#
    set f $w.label
        
    frame $f
    pack $f -side top -expand on -fill both
    label $f.l1 -text "$appName"
    label $f.l2 -text "version $appVersion"
    label $f.l3 -text "Made by vfom (vfom@narod.ru)"
    label $f.l4 -text "Web Site: http://vfom.narod.ru/TkNetmon"
    pack $f.l1 $f.l2 $f.l3 $f.l4 -padx 10 -pady 10

#
    set f $w.buttons
    frame $f
    pack $f -side bottom
    button $f.ok -text "Ok" -command "set v_about ''"
    pack $f.ok -padx 10 -pady 10
#
    wm withdraw $w
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]
    wm geom $w +$x+$y
    wm deiconify $w
    raise $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $w.buttons.ok

    tkwait variable v_about

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return 
}

###########################################################
# Main 
#
set appName	"TkDeviceView"
set appVersion	"0.1"
set ::app_path [ file dirname [info script]]
msgcat::mcload [file join $app_path ".." "locale"]
msgcat::mcload [file join $app_path "locale"]
#
#
menu .menu -tearoff 0 
set m .menu.host
menu $m -tearoff 0
.menu add cascade -label [msgcat::mc "Host"] -menu $m
$m add command -label [msgcat::mc "Interfaces"] \
    -command { exec [file join $app_path TkSnmpTable.tcl ] $::host $::community interfaces.ifTable & }
$m add command -label [msgcat::mc "Routes"] \
    -command { exec [file join $app_path TkSnmpTable.tcl ] $::host $::community ip.ipRouteTable & }
$m add command -label [msgcat::mc "ARP cache"] \
    -command { exec [file join $app_path TkSnmpTable.tcl ] $::host $::community at.atTable & }
$m add command -label [msgcat::mc "IP addresses"] \
    -command { exec [file join $app_path TkSnmpTable.tcl ] $::host $::community ip.ipAddrTable & }
$m add separator
$m add command -label [msgcat::mc "Quit"] -command "destroy ."
#
set m .menu.interface
menu $m -tearoff 0
.menu add cascade -label [msgcat::mc "Interface"] -menu $m
$m add command -label [msgcat::mc "Port stat"]  \
    -command { exec [file join $app_path TkIfUtil.tcl ] \
	$::host $::community [GetIfIndexByName [ AskForInterface ]] & }
#
set m .menu.help

menu $m -tearoff 0
.menu add cascade -label [msgcat::mc "Help"] -menu $m
$m add command -label [msgcat::mc "About"]  \
    -command showAbout
#
. configure -menu .menu
#

text .t   
pack .t -padx 5 -pady 5 -expand on -fill both 
.t insert 0.0 [ GetSysInfo $::host $::community]
.t configure -state disable

bind . <F10> "destroy ."
bind . <Alt-F4> "destroy ."

while { [string equal $::host ""] || [string equal $::community ""] } {
    AskForHost    
    if  { [string equal $::host ""] || [string equal $::community ""] } { 
	tk_dialog .argError [msgcat::mc "ShowIfTable Error"] \
	    [msgcat::mc "Can't retriev SNMP data: no host name or community specified"] \
	    error 0 [msgcat::mc "Approve"] 
    }
}
#
