#!/bin/sh
#  -*- tcl -*-
# Executing wish #\
exec wish "$0" "$@"

#######################################################################
#
# SecPanel - Graphical user interface for managing ssh-connections
#
# Copyright (C) 2000 Steffen Leich <leich@wiwi.uni-marburg.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#######################################################################

#######################################################################
#
# This is version 0.22 of SecPanel
#
# If you want to give any feedback about the program please send it to
# Steffen Leich <leich@wiwi.uni-marburg.de>
# Information about the program can be found on
# http://www2.wiwi.uni-marburg.de/~leich/soft/secpanel
#
#######################################################################

# The dir for the libs and helper-apps
set libdir "[file dirname [info script]]/../lib/secpanel"

global imgs
global che46; 
global sites; 

#################################
# USER DEFINED PROCEDURES
#
proc init {argc argv} {
    global env sites configs
    set secpaneldir "$env(HOME)/.secpanel"
    if {! [file exists $secpaneldir]} {
	puts "Creating my config-dir $secpaneldir (chmod 700)..."
	file mkdir $secpaneldir
	exec chmod 700 $secpaneldir
    }

    if {! [file exists "$secpaneldir/default.profile"]} {
	puts "Creating my default-profile $secpaneldir/default.profile ..."
	set dpf [open "$secpaneldir/default.profile" w]
	puts $dpf " #\n # SecPanel-Pofile\n # Do not edit, use SecPanel instead\n #\n set title \"Default Profile\"\n set host \"\"\n set user \"\"\n set port \"22\"\n set command \"\"\n set identity \"\"\n set agentforward \"0\"\n set x11forward \"0\"\n set nopriv \"0\"\n set verbose \"0\"\n set quiet \"0\"\n set fork \"0\"\n set gateway \"0\"\n set compress \"0\"\n set algo \"idea\"\n set compressval \"6\"\n set lfs \"\""
	close $dpf
    }

    set sitefile "$env(HOME)/.secpanel/sites"
    if [file exists $sitefile] {
	set sf [open $sitefile r]
	while {[gets $sf line] > 0} {
	    set els [split $line #]
	    set sites([lindex $els 0]) "[lindex $els 1]#[lindex $els 2]"
	}
	close $sf
    }
    
    set configfile "$env(HOME)/.secpanel/config"
    if [file exists $configfile] {
	source $configfile
	initconfigs
    } else {
	initconfigs
    }
    
}

# Set the initial global configs if nothing is set
proc initconfigs {} {
    global configs
    if {! [info exists configs(sshbin)] } {
	set configs(sshbin) ssh
    }
    if {! [info exists configs(keygenbin)] } {
	set configs(keygenbin) ssh-keygen
    }
    if {! [info exists configs(agentbin)] } {
	set configs(agentbin) ssh-agent
    }
    if {! [info exists configs(addbin)] } {
	set configs(addbin) ssh-add
    }
    if {! [info exists configs(askpassbin)] } {
	set configs(askpassbin) askpass
    }
    if {! [info exists configs(xtermbin)] } {
	set configs(xtermbin) xterm
    }
}

init $argc $argv

# Browse to select the programs for the global configs
proc browsebin {which} {
    global widget
    choosefile $widget([set which]ent) "/usr/"
}

# Saving the global settings
proc save_globals {} {
    global widget env configs
    set conffile [open "$env(HOME)/.secpanel/config" w]
    foreach f {ssh keygen agent add askpass xterm} {
	puts $conffile "set configs([set f]bin) \"[$widget([set f]ent) get]\""
	set configs([set f]bin) [$widget([set f]ent) get]
    }
    close $conffile
    showstatus "Global configs saved"
}

proc updateDistLabel {} {
    .top17.fra35.fra17.lab39 config -text \
	    "Dist. to [.top17.fra35.fra17.cpd29.01 get active] as\
	    [.top17.fra35.fra17.fra17.01 get active]"
}

# inserting the binaries locations
proc browseprog {mode} {
    global widget
    choosefile $widget([set mode]ent) /usr
}

# bernahme der Forward-Eintrge aus den Eingabefeldern in die Liste
proc {add_forw} {} {
    global widget
    set lfin [$widget(lfin) get]
    set lfout [$widget(lfout) get]

    if {$lfin != "" && $lfout != ""} {
	$widget(lforwards) insert end "$lfin -> $lfout"
	$widget(lfin) delete 0 end
	$widget(lfout) delete 0 end
	focus $widget(lfin)
    }
}

# Umswitchen zwischen Panels im Hauptfenster
proc changetab {mode} {
    foreach f {21 35 44 46} {
	if {[grid info .top17.fra[set f]] != ""} {
	    grid remove .top17.fra[set f]
	}
    }
    array set frames {connect 46 terminal 44 key 35 ssh 21 scp 18}
    
    grid .top17.fra$frames($mode) -in .top17 \
	    -column 0 -row 1 -columnspan 1 -rowspan 1 \
	    -ipadx 2 -ipady 2 -padx 2 -pady 2 -sticky nesw
    showstatus ""
}

# Allgemeine Aufnahme aus tk_getOpenFile-Dialog in einen Entry
proc choosefile {entry startdir} {
    set choice [tk_getOpenFile -initialdir $startdir]
    if {$choice != ""} {
	$entry delete 0 end
	$entry insert 0 $choice
    } else {
	return
    }
}

# Update of the Lists for distributing keys
proc clear_distmenu {} {
    global env widget sites

    $widget(keydisthost) delete 0 end
    $widget(keydistuser) delete 0 end

    set disthosts [list]
    set distusers [list]

    foreach s [array names sites] {
	set he [lindex [split $sites($s) '#'] 0]
	set ue [lindex [split $sites($s) '#'] 1]
	set hfound 0
	set ufound 0

	foreach hd $disthosts {
	    if {$he == $hd} {
		set hfound 1
		break
	    }
	}
	if {$hfound != 1} {
	    lappend disthosts $he
	}

	foreach ud $distusers {
	    if {$ue == $ud} {
		set ufound 1
		break
	    }
	}
	if {$ufound != 1} {
	    lappend distusers $ue
	}
    }

    set profiles [glob -nocomplain "$env(HOME)/.secpanel/*.profile"]
    foreach prof $profiles {
	if {[file rootname [file tail $prof]] == "default"} {
	    continue
	}
	source $prof

	set he $host
	set ue $user
	set hfound 0
	set ufound 0

	foreach hd $disthosts {
	    if {$he == $hd} {
		set hfound 1
		break
	    }
	}
	if {$hfound != 1} {
	    lappend disthosts $he
	}

	foreach ud $distusers {
	    if {$ue == $ud} {
		set ufound 1
		break
	    }
	}
	if {$ufound != 1} {
	    lappend distusers $ue
	}
    }

    foreach hent $disthosts {
	$widget(keydisthost) insert end $hent
    }
    foreach uent $distusers {
	$widget(keydistuser) insert end $uent
    }
}

proc {clear_prmenu} {} {
    global env widget
    $widget(profiles) delete 0 end
    foreach prof [glob -nocomplain "$env(HOME)/.secpanel/*.profile"] {
	$widget(profiles) insert end "[file rootname [file tail $prof]]"
    }
}

proc {clear_profiles} {} {
    global env widget agentforward x11forward nopriv lfs verbose quiet fork gateway compress algo compressval

    foreach b {agentforward x11forward nopriv  verbose quiet fork gateway compress} {
	set [set b] 0
    }
    
    set algo "idea"
    set compressval 6

    foreach e {host command title identity user port profile} {
	$widget([set e]ent) delete 0 end
    }
    
    if [info exists lfs] {
	unset lfs
    }

    $widget(userent) insert 0 "$env(USER)"
    $widget(portent) insert 0 "22"

    if {[winfo exists .top43]} {
	Window destroy .top43
	local_forwardings 1
    }
}

# Connection
proc connect {mode} {
    global widget sites env configs libdir

    if {$mode == "def"} {
	if {[$widget(defsites) index end] > 0} {
	    source "$env(HOME)/.secpanel/default.profile"
	    set actconn [$widget(defsites) get active]
	    set host [lindex [split $sites($actconn) #] 0]
	    set user [lindex [split $sites($actconn) #] 1]
	    set title $actconn
	} else {
	    showmessage "No conncections available, please use \"New\""
	    return
	}
    }

    if {$mode == "spec"} {
	if {[$widget(specsites) index end] > 0} {
	    set actconn [retprof [$widget(specsites) get active]]
	    source "$env(HOME)/.secpanel/$actconn.profile"
	} else {
	    showmessage "No conncections available, please use \"New\""
	    return
	}
    }

    if {$lfs != ""} {
	foreach lf $lfs {
	    append lf_tag  " -L [lindex [split $lf :] 0]:$host:[lindex [split $lf :] 1] "
	}
    } else {
	set lf_tag " "
    }

    if {$user != ""} {
	set user_tag "-l $user "
    } else {
	set user_tag " "
    }
    
    if {$port == 22 || $port == ""} {
	set port_tag " "
    } else {
	set port_tag "-p $port "
    }
    
    if {$algo != "idea" || $algo == ""} {
	set algo_tag "-c $algo "
    } else {
	set algo_tag " "
    }
    
    if {$identity != ""} {
	set ident_tag "-i $identity "
    } else {
	set ident_tag " "
    }
    
    if {$command != ""} {
	set command_tag "$command"
    } else {
	set command_tag ""
    }
    
    if $compress {
	set compressval_tag "-o CompressionLevel=$compressval "
    } else {
	set compressval_tag " "
    }
    
    array set bools {
	"agentforward" "-a" \
		"x11forward" "-x" \
		"nopriv" "-P"  "verbose" "-v" \
		"quiet" "-q" \
		"fork" "-f" \
		"gateway" "-g" \
		"compress" "-C"
    }
    
    foreach f {agentforward x11forward nopriv verbose \
	    quiet fork gateway compress } {
	if [set $f] {
	    set [set f]_tag "$bools($f) "
	} else {
	    set [set f]_tag " "
	}
    }

    set actstring "exec $configs(xtermbin) -T \"SSH Connection - $title\" \
	    -e $libdir/secpanel.wait \"$configs(sshbin) $user_tag \
	    $agentforward_tag $x11forward_tag $port_tag $algo_tag \
	    $ident_tag $nopriv_tag $verbose_tag $quiet_tag \
	    $fork_tag $gateway_tag $compress_tag $compressval_tag \
	    $lf_tag $host $command_tag\" &"
    
    eval $actstring
}

proc {defsiteupdate} {} {
    global widget sites
    $widget(defsites) delete 0 end
    foreach s [array names sites] {
	$widget(defsites) insert end $s
    }
}

proc {del_forw} {} {
    global widget
    if {[selection own] == $widget(lforwards)} {
	$widget(lforwards) delete active
    } else {
	showmessage "No local forward selected"
    }
    selection clear
}

# Display confirms
proc showconfirm {text} {
    if {[tk_messageBox -title "SecPanel Confirmation" \
	    -message $text -type yesno -parent .top17 \
	    -icon warning -default no] == "yes"} {
	return 1
    } else {
	return 0
    }    
}

# Display messages
proc showmessage {text} {
    tk_messageBox -title "SecPanel Message" \
	    -message $text -type ok -parent .top17 \
	    -icon info
}


# Delete one connection
proc delconn mode {
    global widget env sites
    switch -exact $mode {
	def {
	    if {[selection own] == $widget(defsites)} {
		set actentry [$widget(defsites) get active]
		if {[showconfirm "Delete $actentry?"] == 1} {
		    unset sites($actentry)	    
		    set sitefile [open "$env(HOME)/.secpanel/sites" w]
		    foreach s [array names sites] {
			puts $sitefile "$s#$sites($s)"
		    }
		    close $sitefile
		    defsiteupdate
		    clear_distmenu
		    selection clear
		} else {
		    return
		}
	    } else {
		showmessage "No entry selected"
	    }
	}
	spec {
	    if {[selection own] == $widget(specsites)} {
		set actentry [$widget(specsites) get active]
		set delprof [retprof $actentry]
		if {$delprof == "default"} {
		    showmessage "You may not delete the default profile"
		    return
		} else {
		    if {[showconfirm "Delete $actentry?"] == 1} {
			file delete "$env(HOME)/.secpanel/$delprof.profile"
			specsiteupdate
			clear_prmenu
			clear_distmenu
			selection clear
		    } else {
			return
		    }
		}    
	    } else {
		showmessage "No entry selected"
	    }
	}
    }
}

# Delete one profile from the specedit-panel
proc delete_profile {} {
    global env widget
    set act [$widget(profileent) get]
    if {$act == ""} {
	showmessage "To delete a profile first load it"
	return
    }
    if {$act == "default"} {
	showmessage "You may not delete the default profile"
	return
    }
    if {[showconfirm "Delete $act?"] == 1} {
	file delete "$env(HOME)/.secpanel/$act.profile"
	clear_prmenu
	clear_profiles
	specsiteupdate
	clear_distmenu
    }
}

# Distribute public-keys to remote hosts
proc distkey {} {
    global env widget libdir configs

    set user [$widget(keydistuser) get active]

    if {$user == ""} {
	set user $env(USER)
    }

    set host [$widget(keydisthost) get active]
    set identfile [$widget(keydistkey) get]

    if {$identfile == ""} {
	showmessage "No key for distribution selected"
	return
    }
    
    exec xterm -title "SecPanel Key-Distribution" \
	    -e $libdir/secpanel.dist $host $user $identfile $configs(sshbin) &
}

# Management of the known_hosts (kostkeys)
proc hostkey {mode} {
    global env widget
    set khfile "$env(HOME)/.ssh/known_hosts"
    switch -exact $mode {
	edit {
	    if [file exists $khfile] {
		Window show .top50
		$widget(knownhosts) delete 0 end
		set hosts [open $khfile r]
		while {[gets $hosts line] > 0} {
		    $widget(knownhosts) insert end [lindex [split $line] 0]
		}
		close $hosts
		return
	    } else {
		showmessage "No $khfile found"
		return
	    }
	}
	view {
	    set actk [$widget(knownhosts) get active]
	    if [file exists $khfile] {
		Window show .top19
		set hosts [open $khfile r]
		while {[gets $hosts line] > 0} {
		    set kparts [split $line]
		    if {[lindex $kparts 0] == $actk} {
			$widget(viewkey) delete 1.0 end
			$widget(viewkey) insert end "[lindex $kparts 1] [lindex $kparts 2] [lindex $kparts 3]"
			break
		    }
		}
		close $hosts
		return
	    }
	}
	delete {
	    if {[selection own] != $widget(knownhosts)} {
		showmessage "No key selected!"
		return
	    }
	    set actk [$widget(knownhosts) get active]
	    if {[showconfirm "Delete $actk?"] == 1} {
		if [file exists $khfile] {
		    set hosts [open $khfile r]
		    # read lines
		    while {[gets $hosts line] > 0} {
			lappend klines $line
		    }
		    close $hosts
		    
		    # write lines
		    set hosts [open $khfile w]
		    foreach line $klines {
			set kparts [split $line]
			if {[lindex $kparts 0] != $actk} {
			    puts $hosts "[lindex $kparts 0] \
				    [lindex $kparts 1] [lindex $kparts 2] \
				    [lindex $kparts 3]"
			}
		    }
		    close $hosts
		    hostkey edit
		    selection clear
		    return
		}
	    } else {
		return
	    }
	}
    }
}

proc {insprot} {mode} {
    global widget
    $widget(lfout) delete 0 end
    $widget(lfout) insert 0 $mode
}

# Managing the keypair on the local host
proc keygen {mode} {
    global env widget configs pwtextmode libdir

    if {[$widget(identpath) get] == ""} {
	set kf "$env(HOME)/.ssh/identity"
    } else {
	set kf [$widget(identpath) get]
    }
    
    switch -exact $mode {
	gen {
	    # possible ways of giving the user a new key:
	    # - dialog incl. new passwords is a problem because listed in ps
	    # - complete textmode in an xshell most secure
	    # - dialog for file, password etc. and execute by expect
	    set actstring "exec $configs(xtermbin) -T \"SecPanel ssh-keygen\" \
		    -e $libdir/secpanel.wait \"$configs(keygenbin) -f $kf\" &"
	    eval $actstring
	}
	1 {
	    if {[$widget(identpath) get] == ""} {
		if {! [file exist $env(HOME)/.ssh/identity]} {
		    showmessage "No key given and\n$env(HOME)/.ssh/identity not found"
		    return
		} else {
		    set kf "$env(HOME)/.ssh/identity"
		}
	    } else {
		set kf [$widget(identpath) get]
	    }
	    if [set pwtextmode] {
		set actstring "exec $configs(xtermbin) -T \"SecPanel - \
			change password for $kf\" \
			-e $libdir/secpanel.wait \"$configs(keygenbin) -p -f $kf\" &"
		eval $actstring
	    } else {		
		Window show .top20
		$widget(proplabel) config -text $kf
	    }
	}
	chpwd {
	    set oldp [.top20.fra21.ent26 get]
	    set newp1 [.top20.fra21.ent30 get]
	    set newp2 [.top20.fra21.ent31 get]

	    if {$newp1 != $newp2} {
		showmessage "New password and repeated new password don't match"
		return
	    }

	    if [catch {exec $configs(keygenbin) -p -f $kf \
		    -P $oldp -N $newp1} err] {
		showmessage $err
		return
	    }
	    Window destroy .top20
	}
	chpath {
	    choosefile $widget(identpath) $env(HOME)/.ssh
	}
    }
}

proc load_profile {mode} {
    global env widget agentforward x11forward nopriv \
	    verbose quiet fork gateway compress algo compressval lfs
    if {$mode == "ssh"} {
	set act [$widget(profiles) get active]
    } elseif {$mode == "connects"} {
	set act [retprof [$widget(specsites) get active]]
    }

    source $env(HOME)/.secpanel/$act.profile

    foreach f {title host user port command identity} {
	$widget([set f]ent) delete 0 end
	$widget([set f]ent) insert 0 [set $f]
    }

    $widget(profileent) delete 0 end
    $widget(profileent) insert 0 $act

    if {[winfo exists .top43]} {
	Window destroy .top43
	local_forwardings 1
    }
}

proc local_forwardings {mode} {
    global widget lfs
    switch -exact $mode {
	1 {
	    if [winfo exists .top43] {
		return
	    }
	    Window show .top43
	    if [info exists lfs] {
		foreach lf $lfs {
		    if [regsub : $lf { -> } out] {
			$widget(lforwards) insert end $out
		    }
		}
	    }
	}
    }
}

# Control the SSH-Agent
proc manage_agent {mode} {
    global env widget configs
    switch -exact $mode {
	launch {
	    # If agent exists, use it (anyway the xterms would use it)
	    if {[info exists env(SSH_AGENT_PID)] && [info exists env(SSH_AUTH_SOCK)]} {
		puts "Agent exists"
	    } else {
		puts "No agent found"
	    }

	    # Start ssh-agent and read envs
	    set agentout [open "| $configs(agentbin) -c" r]
	    while {[gets $agentout line] > 0} {
		if [string match "setenv SSH*" $line] {
		    set env([lindex [split $line] 1]) [string trimright [lindex [split $line] 2] \;]
		}
	    }
	    close $agentout
	    $widget(statusagent) config -text "Agent active" -bg green -fg black
	}
	kill {
	    if {[showconfirm "Kill SSH-agent?"] == 1} {
		exec $configs(agentbin) -k
		# Envs are to be killed explicitly
		unset env(SSH_AGENT_PID)
		unset env(SSH_AUTH_SOCK)
		$widget(statusagent) config -text "No Agent" -bg red -fg white
		$widget(idents) delete 0 end
	    } else {
		return
	    }
	}
	addident {
	    set fname [tk_getOpenFile -initialdir "$env(HOME)/.ssh/"]
	    if {$fname != ""} {
		catch {exec $configs(addbin) $fname < /dev/null} err
		if [string match "Bad key file*" $err] {
		    showmessage "Bad key file"
		    return
		}
		set found 0
		foreach ent [$widget(idents) get 0 end] {
		    if {$ent == $fname} {
			set found 1
			break
		    }
		}
		if {! $found} {
		    $widget(idents) insert end $fname
		}
	    } else {
		return
	    }
	}
	remident {
	    if {[selection own] != $widget(idents)} {
		showmessage "No Identity selected"
		return
	    } else {
		catch {exec $configs(addbin) -d [$widget(idents) get active]}
		$widget(idents) delete active
	    }
	}
    }
}

# General handling of one entries state by clicking a checkbox
proc managestate {checkbox entry} {
    global widget compress
    if {$compress} {
	$widget(comprlev) config -state normal
    } else {
	$widget(comprlev) config -state disabled
    }
}

# Adding one default connection
proc newconn {mode state} {
    global widget env sites
    switch -exact $mode {
	def {
	    switch -exact $state {
		1 {
		    Window show .top40
		    $widget(newuser) insert 0 $env(USER)
		    grab .top40
		}
		2 {
		    set newtit [$widget(newtit) get]
		    set newaddr [$widget(newaddr) get]
		    set newuser [$widget(newuser) get]
		    
		    if {$newtit != "" && $newaddr != ""} {
			set sites($newtit) "$newaddr#$newuser"
			
			set sitefile [open "$env(HOME)/.secpanel/sites" w]
			foreach s [array names sites] {
			    puts $sitefile "$s#$sites($s)"
			}
			close $sitefile
			
			defsiteupdate
			clear_distmenu
			
			Window destroy .top40
		    } else {
			showmessage "Please enter address and title"
		    }
		}
	    }
	}
	spec {
	    changetab ssh
	    clear_profiles
	}
    }
}

# Switch to edit-mode of one connection (defs and specs)
proc propconn {spec mode} {
    global widget env sites
    switch -exact $spec {
	def {
	    switch -exact $mode {
		1 {
		    if {[$widget(defsites) index end] > 0} {
			set act [$widget(defsites) get active]
			Window show .top40
			$widget(newtit) insert 0 $act
			$widget(newaddr) insert 0 [lindex [split $sites($act) #] 0]
			$widget(newuser) insert 0 [lindex [split $sites($act) #] 1]
			.top40.fra45.but47 config -command "propconn def 2"
			grab .top40
		    } else {
			showmessage "No conncections available, please use \"New\""
			return
		    }
		}
		2 {
		    unset sites([$widget(defsites) get active])
		    newconn def 2
		}
	    }
	}
	spec {
	    if {[$widget(specsites) index end] > 0} {
		changetab ssh
		load_profile connects
	    } else {
		showmessage "No conncections available, please use \"New\""
		return
	    }
	}
    }
}

# return profile-file by title in spec-list
proc {retprof} {tit} {
    global env
    foreach f [glob -nocomplain "$env(HOME)/.secpanel/*.profile"] {
	source $f
	if {$title == $tit} {
	    return "[file rootname [file tail $f]]"
	}
    }
}

proc {save_forwards} {mode} {
    global widget lfs
    set lfs [list]
    foreach line [$widget(lforwards) get 0 end] {
	if [regsub { -> } $line : out] {
	    lappend lfs $out
	}
    }
    Window destroy .top43
}

proc {save_profile} {} {
    global env widget agentforward x11forward  nopriv verbose \
	    quiet fork gateway compress algo compressval lfs

    set prname [$widget(profileent) get]
    if {$prname == ""} {
	showmessage "Enter a name for the profile"
	return
    }

    set title [$widget(titleent) get]
    set host [$widget(hostent) get]
    set user [$widget(userent) get]
    set port [$widget(portent) get]
    set command [$widget(commandent) get]
    
    if {$prname == "default"} {
	if {$title != "Default Profile" || $host != "" \
		|| $user != "" || $command != ""} {
	    showmessage "You may not enter host, user or command for the \
		    default profile and you may not change the title"
	    return
	}
    } else {
	if {$title == "" || $host == ""} {
	    showmessage "You must enter at least host and title"
	    return
	}
    }
    
    set identity [$widget(identityent) get]

    set prfile [open "$env(HOME)/.secpanel/$prname.profile" w]
    
    puts $prfile "#\n# SecPanel-Pofile\n# Do not edit, use SecPanel instead\n#"
    
    foreach ent {title host user port command identity} {
	puts $prfile "set [set ent] \"[set $ent]\""
    }
    foreach bool {agentforward x11forward nopriv verbose \
	    quiet fork gateway compress } {
	if [set $bool] {
	    puts $prfile "set [set bool] \"[set $bool]\""
	} else {
	    puts $prfile "set [set bool] \"[set $bool]\""
	}
    }
    foreach sel {algo compressval} {
	puts $prfile "set [set sel] \"[set $sel]\""
    }

    if [info exists lfs] {
	puts $prfile "set lfs \"$lfs\""
    } else {
	puts $prfile "set lfs \"\""
    }

    close $prfile

    specsiteupdate    
    clear_prmenu
    clear_profiles
    clear_distmenu
}

proc seldistkey {} {
    global env widget
    set ftypes {
	{{Public keys} {.pub}}
	{{All files} *}
    }
    $widget(keydistkey) delete 0 end
    $widget(keydistkey) insert 0 \
	    [tk_getOpenFile -initialdir "$env(HOME)/.ssh"  -filetypes $ftypes]
}

# Selection of the connections Identity
proc select_ident {} {
    global env widget
    choosefile $widget(identityent) $env(HOME)/.ssh
}

# Show one manual page
proc showman {man} {
    global configs
    exec $configs(xtermbin) -e man $man &
}

proc specsiteupdate {} {
    global widget env
    $widget(specsites) delete 0 end
    set profiles [glob -nocomplain "$env(HOME)/.secpanel/*.profile"]
    foreach prof $profiles {
	if {[file rootname [file tail $prof]] == "default"} {
	    continue
	}
	source $prof
	$widget(specsites) insert end $title
    }
}

# with single click in connect-lists show some data about profile
proc showstatus {text} {
    global widget
    $widget(status) config -text $text
}

proc main {argc argv} {
    global widget sites env configs libdir
    clear_prmenu
    clear_profiles
    defsiteupdate
    specsiteupdate
    clear_distmenu
    foreach f {ssh keygen agent add askpass xterm} {
	$widget([set f]ent) insert 0 "$configs([set f]bin)"
    }
    foreach b {connects keys profiles configs} {
	$widget([set b]but) config -image \
		[image create photo -file $libdir/images/[set b].gif]
    }
}

source $libdir/gui.tcl
