#!/usr/bin/expectk -f
#
# xsmb is a Tcl/Tk -based browser for CIFS(SMB), Common Internet File System.
# Copyright (C) 1999 Jorma Korpisalo
#
#   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# contact author :
#   email :
#     jkorpisa@ratol.fi
#   address :
#     Jorma Korpisalo
#     Seminaarinkatu 2 as 209
#     92100 Raahe
#     Finland
#
# xsmb home page at http://www.ratol.fi/~jkorpisa/xsmb.html
#
#
# xsmb uses following programs (found in samba suite) :
# - smbclient
# - nmblookup
# - smbmount
# - smbumount
#
# --------------------------------------------------------------------------------



# Changes since 0.2.2 :
#
# 0.3.1 - added option -W <wgroup> to smbclient -L calls. This makes
#         things work as they should ..
#
# 0.3.0 - xsmb now checks ALL master browser candidates shown by
#         'nmblookup -M -S <WGROUP>' for machine list. This should make things
#         work smoother in an unstable environment where master browser is not
#         always the same.
#       - several bugfixes
#
# 0.2.1 - fixed password bug. xsmb didn't use password given in main window if
#         default password was given.
#       - added one more access error handling
#
# 0.2.2 - changed the handling of smbclient output (different on newer versions of samba)










# program version
set version "0.3.1"

# default wg
set own_WG ""

# list of manually added local workgroups
set list_of_addwgs ""
# number of additional workgroups
set number_of_addwgs 0

set username ""
set password ""

# client's netbios name
set clientname ""

set smb_timeout 10
set show_license yes

# save passwords to a file (/home/$USER/.xsmb/passwords)
# not implemented yet
set save_pwd_file no

# status of samba window
# 0 = list of workgroups
# 1 = list of computers
# 2 = list of shares
# 3 = list of directories in share
# 4-n = list of subdirectories
set smbwin_status "0"

set used_wgroup ""
set used_master_ip ""
set used_master_name ""
set used_machine_name ""
set used_machine_ip ""

set used_directory ""
set used_subdir_path ""
set used_subdirectory ""
set subdir_list ""
set number_of_subdirs ""

set used_sambawindow_listing ""

# regexp's used by expect
#
# master browser's name (nmblookup)
set master_name_pattern "\t(\[^ ]*) *<00>"
#
# begin of hostlist
# this on older samba versions
#set hostlist_start "This machine has a browse list:\r\n\r\n\tServer               Comment\r\n\t---------            -------\r\n"
# this on samba 2.0.0B3
set hostlist_start "\tServer               Comment\r\n\t---------            -------\r\n"
#
# computer's netbios name and comment from hostlist
# set hostlist_pattern "\t?(\[^ \r]*) *(\[^\r]*)\r\n"
set hostlist_pattern "\t?((\[^ \r]| \[^ \r])*) *(\[^\r]*)\r\n"
#
# begin of sharelist
set sharelist_start "\tSharename      Type      Comment\r\n\t---------      ----      -------\r\n"
#
# begin of wglist
set workgroups_start "\tWorkgroup            Master\r\n\t---------            -------\r\n"
#
# wg and master's name from wglist
set workgrouplist_pattern "\t?((\[^ \r]| \[^ \r])*) *(\[^\r]*)\r\n"
#
# dir, type & comment from sharelist
#set share_list_pattern "\t?(\[^ \r\n]*) *(\[^ \r\n]*) *(\[^\r\n]*)\r\n"
#set share_list_pattern {\t?([^ ]([^ ]| [^ ])*) +([^ ]+) ([^ ]([^ ]| [^ ])*)}
set share_list_pattern "\t?((\[^ \r\n]| \[^ \r\n])*) *(\[^ \r\n]*) *(\[^\r\n]*)\r\n"
#
# start of dirlist
set dir_list_start_pattern "..                                  D"
# directory's inners
set dir_pattern {  ([^ ]([^ ]| [^ ])*)     +([^ ]*) +([0-9]+) +(........................)}


# present local dir
set used_local_directory ""
# candidate for new local dir
set new_used_local_directory ""

set share_to_be_mounted ""
set list_of_mounted_shares {}
set number_of_mounted_shares "0"

# char "\"
set dir_ch "\x5c"

# configuration
set O_clientname ""
set O_smb_timeout "5"
set O_show_license "yes"
set O_save_pwd_file "yes"
set O_file_size_type "B"
set O_show_timestamp "no"
set O_default_password ""
set O_use_default_password "no"
set O_confirm_quit "yes"
set O_own_WG ""
set O_to_lowercase "no"

# used to stop directory copy
set copy_or_not_to_copy "y\r"

# file size reported
# B = as bytes
# other = kilobytes
set file_size_type "B"

# show timestamp with dirs/files
set show_timestamp "no"

# default password
set default_password ""

# use default passwd or not
set use_default_password "no"

# if shares mounted, ask this anyway
set confirm_quit "yes"

# test host with nmblookup before getting sharelist ?
set do_we_test_host "yes"

# test master browser with nmblookup before getting hostlist ?
set do_we_test_wg "yes"

# workgroup found with "find wg"
set spes_wg "no"

# use master browser's IP when getting hostlist
set use_master_ip "yes"

set help_type ""

# IP addresses of found master browser candidates
set used_master_ip_addresses ""
# netbios names of found master browser candidates
set used_master_names ""
# number of found master browsers
set number_of_masters 0


# draw main window
#
proc draw_window {} {
global version
# windowmanager settings
wm minsize . 640 480
wm title . "xsmb $version"

#tk_focusFollowsMouse

# top frame
frame .top -bd 1
pack .top -side top -fill both -expand no -pady 3

  # help menu
  menubutton .top.button_help -menu .top.button_help.menu -bd 1 -width 4 -text "help"
  pack .top.button_help -side right
  menu .top.button_help.menu -tearoff false
  .top.button_help.menu add command -label {main help} -command {
    .top.button_help configure -state disabled
    show_help "mainhelp"
    }
  .top.button_help.menu add command -label {FAQ} -command {
    .top.button_help configure -state disabled
    show_help "faq"
    }
  .top.button_help.menu add command -label {About} -command {
    .top.button_help configure -state disabled
    show_help "about"
    }

  # File-menu
  menubutton .top.button_file -menu .top.button_file.menu -bd 1 -width 5 -text "File"
  pack .top.button_file -side left
  menu .top.button_file.menu -tearoff false
  .top.button_file.menu add command -label {Configuration} -command options
  .top.button_file.menu add command -label {Clone window} -command clone_xsmb
  .top.button_file.menu add separator
  .top.button_file.menu add command -label {Quit} -command {
    if { $number_of_mounted_shares > 0 } { quit } else {
      if { $confirm_quit == "yes" } { quit } else { destroy . }
      }
    }

  # Tools-menu
  menubutton .top.button_tools -menu .top.button_tools.menu -bd 1 -width 4 -text "Tools"
  pack .top.button_tools -side left
  menu .top.button_tools.menu -tearoff false
  .top.button_tools.menu add command -label {Add local workgroup} -command add_workgroups
  .top.button_tools.menu add command -label {Find remote workgroup} -command specify_wg
  .top.button_tools.menu add command -label {Find computer} -command specify_host

frame .bottom
pack .bottom -side bottom -fill both -expand yes

# left side (local dir)
  frame .bottom.left
  pack .bottom.left -side left -fill both -expand no

  # text "new dir" & entry
    frame .bottom.left.localdir
    pack .bottom.left.localdir -side top -fill both -expand no
      label .bottom.left.localdir.dirlabel -text "New dir :"
      pack .bottom.left.localdir.dirlabel -side left
      entry .bottom.left.localdir.localdir -relief sunken -textvariable new_used_local_directory -width 20
      pack .bottom.left.localdir.localdir -side left
      bind .bottom.left.localdir.localdir <Return> { change_localdir }

  # buttons used with local dir/files
    frame .bottom.left.buttons
    pack .bottom.left.buttons -side top -fill both -expand no
    # refresh local dir
      button .bottom.left.buttons.button_refresh -bd 1 -width 3 -text "R"
      pack .bottom.left.buttons.button_refresh -side left
    # parent dir
      button .bottom.left.buttons.button_parent -bd 1 -width 3 -text "Up"
      pack .bottom.left.buttons.button_parent -side left
    # copy from local to network
      button .bottom.left.buttons.button_copy -bd 1 -width 3 -text "cp"
      pack .bottom.left.buttons.button_copy -side left
    # delete local files/dirs
      button .bottom.left.buttons.button_delete -bd 1 -width 3 -text "rm"
      pack .bottom.left.buttons.button_delete -side left

  # infolines
    frame .bottom.left.infolineframe
    pack .bottom.left.infolineframe
      text .bottom.left.infolineframe.infoline -width 30 -height 2 -state disabled -relief groove -bd 1
      pack .bottom.left.infolineframe.infoline -side top -fill both -expand no
      
  # inners of local dir
    frame .bottom.left.dirbox
    pack .bottom.left.dirbox -side top -fill both -expand yes
      listbox .bottom.left.dirbox.nodelist -width 30 -height 20 -selectmode extended
      pack .bottom.left.dirbox.nodelist -side left -fill both -expand yes

# middle (not used)
  frame .bottom.center
  pack .bottom.center -side left -fill both -expand no

# right side (network)
  frame .bottom.right
  pack .bottom.right -side right -fill both -expand yes

  # username & password fields
    frame .bottom.right.top
    pack .bottom.right.top -side top -fill both -expand no
		
    # text "username"
      label .bottom.right.top.usernamelabel -text "username :"
    # username
      entry .bottom.right.top.username -relief sunken -textvariable username -width 10
    # text "password"
      label .bottom.right.top.passwordlabel -text "password :"
    # password
      entry .bottom.right.top.password -relief sunken -textvariable password -width 10 -show "*"
      pack .bottom.right.top.usernamelabel .bottom.right.top.username -side left -padx 1m
      pack .bottom.right.top.passwordlabel .bottom.right.top.password -side left -padx 1m

  # buttons, infolines, samba-window
    frame .bottom.right.bottom
    pack .bottom.right.bottom -side bottom -fill both -expand y
    
    # buttons used with samba-window
      frame .bottom.right.bottom.buttons
      pack .bottom.right.bottom.buttons -side top -fill both -expand n

      # parent status
        button .bottom.right.bottom.buttons.button_parent -bd 1 -width 3 -text "Up" -command {
	  parent_smbwindow 
          }
      # refresh
        button .bottom.right.bottom.buttons.button_refresh -bd 1 -width 3 -text "R" -command { refresh_smbwindow "" }
        pack .bottom.right.bottom.buttons.button_refresh -side left
	pack .bottom.right.bottom.buttons.button_parent -side left
      # copy from network to local
        button .bottom.right.bottom.buttons.button_copy -bd 1 -width 3 -text "cp" -command {
          set index [.bottom.right.bottom.sambawindow.smb curselection]
          if {$index != ""} {
            set rivi [lindex $used_sambawindow_listing $index]
            if { $rivi != "" } {
              if {$smbwin_status > 2 } {
                copy_to_local $rivi
                }
              }
            }
          }
        pack .bottom.right.bottom.buttons.button_copy -side left

      # delete from network
        button .bottom.right.bottom.buttons.button_delete -bd 1 -width 3 -text "rm"
        pack .bottom.right.bottom.buttons.button_delete -side left

      # mount network shares
        button .bottom.right.bottom.buttons.mountbutton -bd 1 -width 4 -text "mnt" -command {
          set index [.bottom.right.bottom.sambawindow.smb curselection]
          if {$index != ""} {
            set rivi [lindex $used_sambawindow_listing $index]
            if { $rivi != "" } {
              if {$smbwin_status == "2" } {
                if { $rivi != "list_of_hosts" } {
                  mount_share $rivi
                  }
                }
              }
            }
          }
        pack .bottom.right.bottom.buttons.mountbutton -side left

      # unmount mounted dirs
        button .bottom.right.bottom.buttons.button_umount -bd 1 -width 4 -text "umnt" -command {
          if { $number_of_mounted_shares != "0" } {
            umount_shares
            }
          }
        pack .bottom.right.bottom.buttons.button_umount -side left

    # infolines
      frame .bottom.right.bottom.infolineframe
      pack .bottom.right.bottom.infolineframe -side top -fill both -expand n
        text .bottom.right.bottom.infolineframe.infoline -width 50 -height 3 -state disabled -relief groove -bd 1
        pack .bottom.right.bottom.infolineframe.infoline -side top -fill both -expand no

    # samba-window
      frame .bottom.right.bottom.sambawindow
      pack .bottom.right.bottom.sambawindow -side top -fill both -expand y
      # scrollbars
        scrollbar .bottom.right.bottom.sambawindow.scrollvert -orient vertical -width 10 -command ".bottom.right.bottom.sambawindow.smb yview"
        scrollbar .bottom.right.bottom.sambawindow.scrollhoriz -orient horizontal -width 10 -command ".bottom.right.bottom.sambawindow.smb xview"
        pack .bottom.right.bottom.sambawindow.scrollvert -side right -fill y
        pack .bottom.right.bottom.sambawindow.scrollhoriz -side bottom -fill x
      # inners of network
        listbox .bottom.right.bottom.sambawindow.smb -width 50 -height 20 -selectmode extended \
          -yscrollcommand ".bottom.right.bottom.sambawindow.scrollvert set" \
          -xscrollcommand ".bottom.right.bottom.sambawindow.scrollhoriz set"
        pack .bottom.right.bottom.sambawindow.smb -side bottom -fill both -expand yes

      # bind left mousebutton double-click
        bind .bottom.right.bottom.sambawindow.smb <Double-1> {
          set index [.bottom.right.bottom.sambawindow.smb curselection]
          if {$index != ""} {
            #set rivi [lindex [.bottom.right.bottom.sambawindow.smb get $index] 0]
            set rivi [lindex $used_sambawindow_listing $index]
            if { $rivi == "list_of_workgroups" } { parent_smbwindow
              } elseif { $rivi == "list_of_hosts" } { parent_smbwindow
              } elseif { $rivi == "/.." } { parent_smbwindow
              } else { refresh_smbwindow $rivi
              }
            }
          }
}





# quit xsmb
#
proc quit {} {
  global list_of_mounted_shares number_of_mounted_shares
  .top.button_file configure -state disabled
  toplevel .quit
  wm title .quit "quit program"
  frame .quit.infoframe
  pack .quit.infoframe -side top -fill both -expand yes
    text .quit.infoline -width 40 -height 3 -state disabled -relief groove -borderwidth 3
    pack .quit.infoline -side top -fill both -expand no
  frame .quit.buttonsframe
  pack .quit.buttonsframe -side top -pady 3
    button .quit.buttonsframe.quitbutton -bd 1 -width 8 -text "quit" -command { destroy . }
    pack .quit.buttonsframe.quitbutton -side left -anchor w
    button .quit.buttonsframe.cancelbutton -bd 1 -width 8 -text "cancel" -command {
      .top.button_file configure -state normal
      destroy .quit
      }
    pack .quit.buttonsframe.cancelbutton -side left -anchor w
  .quit.infoline configure -state normal
  if { $number_of_mounted_shares > 0 } {
    .quit.infoline insert end "You still have some mounted\ndirectories! If you quit\nnow, you have to unmount them manually!"
  } else {
    .quit.infoline insert end "Are you sure you want to quit ?"
  }
  .quit.infoline configure -state disabled
}


# disable few buttons
#
proc disable_buttons {} {
  .bottom.right.bottom.buttons.button_refresh configure -state disabled
  .bottom.right.bottom.buttons.button_copy configure -state disabled
  .bottom.right.bottom.buttons.button_delete configure -state disabled
  .bottom.right.bottom.buttons.button_parent configure -state disabled
  .bottom.right.bottom.buttons.mountbutton configure -state disabled
  .top.button_file configure -state disabled
  .top.button_tools configure -state disabled
}

# enable some
#
proc enable_buttons {} {
  global smbwin_status
  .bottom.right.bottom.buttons.button_refresh configure -state normal
  .top.button_file configure -state normal
  .top.button_tools configure -state normal
  if { $smbwin_status > 0 } {
    .bottom.right.bottom.buttons.button_parent configure -state normal
  } else {
    .bottom.right.bottom.buttons.button_parent configure -state disabled
  }
  if { $smbwin_status == 2 } {
    .bottom.right.bottom.buttons.mountbutton configure -state normal
  } else {
    .bottom.right.bottom.buttons.mountbutton configure -state disabled
  }
  if { $smbwin_status > 2 } {
    .bottom.right.bottom.buttons.button_copy configure -state normal
    .bottom.right.bottom.buttons.button_delete configure -state normal
  }
}


# Refresh samba window based on parameter (selected by left mouse button double-click)
# If no parameter given, just update
#
proc refresh_smbwindow { rivi } {
  global smbwin_status do_we_test_host spes_wg
  global used_wgroup used_machine_name
  disable_buttons

  # if no param given then just update
  if { $rivi == "" } then {
    if { $smbwin_status == "0" } {
        set spes_wg "no"
        list_workgroups
      } elseif { $smbwin_status == "1" } {
        # if used wg = "", then what's been last done is :
        # - listed shares from computer found by "find computer"
	# OR
        # - listed hostlist from remote workgroup (found with "find wg")
        #   this checked with spes_wg (yes or no)
        if { $used_wgroup == "" } {
            if { $spes_wg == "no" } {
                set smbwin_status 0
                list_workgroups
              } else {
                list_machines ""
              }
          } else {
            list_machines ""
          }
      } elseif { $smbwin_status == "2" } {
        list_shares ""
      } else {
        list_directory ""
	}

  # It seems like user double clicked on sumthin, let's do something based on status.
  # If status :
  # - 0 it's now list of wg's, next let's list computers
  # - 1 it's now list of computers, next let's list shares
  # - 2 it's now list of shares, next let's list subdirectories
  #
  } else {
      if { $smbwin_status == "0" } {
        set used_wgroup $rivi
        list_machines $rivi
      } elseif { $smbwin_status == "1" } {
        list_shares $rivi
      } else {
        # check if first char in string is "/", then it's directory
        # if status = 2, list of shares now and straight to listing ..
        if { $smbwin_status == "2" } {
	    list_directory $rivi
	  } else {
            if { [string index $rivi 0] == "/" } {
              # rip "/"
              set rivi [string trimleft $rivi "/"]
              if { $rivi == ".." } {
                  parent_smbwindow
                } else {
                  list_directory $rivi
                }
	      }
	  }
	}
    }
  enable_buttons
  # enable quitbutton (because disabled at startup)
  .top.button_file configure -state normal
}




proc parent_smbwindow {} {
  global smbwin_status used_subdir_path
  global number_of_subdirs dir_ch used_subdirectory
  global subdir_list do_we_test_wg do_we_test_host spes_wg
  
          if { $smbwin_status != "0" } {
            if { $smbwin_status > 5 } {
	      set used_subdir_path [string trimright $used_subdir_path $used_subdirectory]
	      set used_subdir_path [string trimright $used_subdir_path $dir_ch]
              set number_of_subdirs [expr $number_of_subdirs -1]
              set used_subdirectory [lindex $subdir_list $number_of_subdirs]
              set subdir_list [lreplace $subdir_list $number_of_subdirs $number_of_subdirs]
            } elseif { $smbwin_status == 5 } {
	      set used_subdir_path [string trimright $used_subdir_path $used_subdirectory]
	      set used_subdir_path [string trimright $used_subdir_path $dir_ch]
              set number_of_subdirs 0
              set used_subdirectory [lindex $subdir_list 0]
              set subdir_list ""
            } elseif { $smbwin_status == 4 } {
              set used_subdirectory ""
              set used_subdir_path ""
              set number_of_subdirs 0
              set subdir_list ""
            } elseif { $smbwin_status == 3 } {
              set used_directory ""
              set used_subdirectory ""
              set used_subdir_path ""
              set number_of_subdirs 0
              set subdir_list ""
            } elseif { $smbwin_status == 2 } {
              # set do_we_test_host "yes"
            } elseif { $smbwin_status == 1 } {
              set spes_wg "no"
              set do_we_test_wg "yes"
              set do_we_test_host "yes"
	    }
            set smbwin_status [expr $smbwin_status-1]
            refresh_smbwindow ""
            }
}


# Clear samba window and list workgroups
# 1. check $own_WG
# 2. ask other workgroups from own_WG's master browser
#
proc list_workgroups {} {
  global own_WG list_of_addwgs number_of_addwgs
  clear_smbwindow
  write_sambainfo "Checking workgroups, please wait ..."
  if { $own_WG != "" } {
    check_wgroup $own_WG
    check_other_wgroups $own_WG
  }
  if { $number_of_addwgs > 0 } {
    foreach index $list_of_addwgs {
      if { [lsearch -exact $list_of_addwgs $index] != -1 } {
        check_wgroup $index
        }
      }
    }
  write_sambainfo "Workgroups :"
}


# Search workgroup given in parameter
# If found, list it
#
proc check_wgroup { wgroup } {
  global used_sambawindow_listing smb_timeout
  spawn nmblookup -M -S $wgroup
  set id $spawn_id
  set timeout $smb_timeout
  expect {
    -i $id "<00>" {
      # if wg already in list, don't
      if { [lsearch -exact $used_sambawindow_listing $wgroup] == -1 } {
        .bottom.right.bottom.sambawindow.smb insert end "$wgroup"
        set used_sambawindow_listing [linsert $used_sambawindow_listing end $wgroup]
        }
      }
    -i $id timeout { close -i $id }
  }
  wait -i $id
}


# check workgroup (given as param) and ask master for other workgroups, and check them
#
proc check_other_wgroups { wgroup } {
  global master_name_pattern smb_timeout
  global used_master_ip used_master_name
  global used_sambawindow_listing smb_timeout
  global workgroups_start workgrouplist_pattern
  global used_sambawindow_listing

  # first, get master's name & IP
  set master_ip_pattern "\n(\[^ ]*) $wgroup"
  spawn nmblookup -M -S $wgroup
  set id $spawn_id
  set timeout $smb_timeout
  expect {
   -i $id failed {
       set  used_master_ip ""; set used_master_name ""
          }
   -i $id -indices -re $master_ip_pattern {
       # strange things happen, 127.0.0.1 as master ...
       if { $expect_out(1,string) != "127.0.0.1" } { set used_master_ip $expect_out(1,string) }
       exp_continue
          }
   -i $id -indices -re $master_name_pattern {
       set used_master_name $expect_out(1,string)
          }
   -i $id timeout { close -i $id }
       }
  wait -i $id
  # if master found, ask other workgroups from it and check them
  if { $used_master_name != "" } {
    spawn smbclient -L $used_master_name -W $wgroup -I $used_master_ip -U%
    set id $spawn_id
    set timeout $smb_timeout
    expect {
      -i $id "error " {}
      -i $id timeout { close -i $id }
      -i $id $workgroups_start {
        expect {
          -i $id -indices -re $workgrouplist_pattern {
            if { $expect_out(1,string) != "" } {
              # if wg already listed, don't check
              if { [lsearch -exact $used_sambawindow_listing $expect_out(1,string)] == -1 } {
                check_wgroup $expect_out(1,string)
                }
              exp_continue
              }
            }
          }
        }
      }
      wait -i $id
    }
}





# List computers in workgroup (given as param)
# If none given, just update list
# First check if workgroup exists and get master browser's name & IP
#
proc list_machines { wgroup } {
  global smbwin_status used_wgroup
  global used_master_ip used_master_name
  global hostlist_start hostlist_pattern
  global used_sambawindow_listing
  global smb_timeout do_we_test_wg spes_wg
  global use_master_ip
  global workgroups_start

  # nmblookup -M -S wgroup can give more than one master IP, and the first one
  # is NOT ALWAYS the right one.
  global used_master_ip_addresses used_master_names number_of_masters
    
  clear_smbwindow
  .bottom.right.bottom.sambawindow.smb insert end "<List of workgroups>"
  set used_sambawindow_listing [linsert $used_sambawindow_listing end "list_of_workgroups"]
  
  # status = list of computers
  set smbwin_status "1"

  if { $spes_wg == "no" } {
      # if wgroup given as proc parameter, let's check that
      if { $wgroup != "" } { set used_wgroup $wgroup }
      write_sambainfo "Checking workgroup $used_wgroup, please wait ..."
    } else {
      write_sambainfo "Checking spesific workgroup, please wait ..."
    }

  # if normal local wg, then get master's name & IP
  if { $spes_wg == "no" } { test_workgroup }

  # if master found, get hostlist
  if { [lindex $used_master_names 0] == "" } {
    write_sambainfo "Workgroup $used_wgroup not available !\nMaster browser not found."
    return 0
    }

  set idx_num 0
  set hostlist_success 0
  
  # for every master candidate
  #
  foreach idx $used_master_names {
    set used_master_ip [lindex $used_master_ip_addresses $idx_num]
    set used_master_name $idx
    if { $hostlist_success == 0 } {
      if { $spes_wg != "no" } {
        write_sambainfo "Checking workgroup $used_wgroup from master $used_master_name, please wait ..."
        }
      if { [get_hostlist] != "no" } {
        set hostlist_success 1
	}
      }
    incr idx_num
    }

  # if not, then not.
  if { $hostlist_success == 0 } {
    write_sambainfo "Error: master browser(s) didn't give hostlist.\nYou could try refresh button."
    }
}



# get hostlist, a subroutine for list_machines proc
# this gets the hostlist
proc get_hostlist { } {

global use_master_ip used_master_name used_master_ip
global smb_timeout used_wgroup hostlist_start
global hostlist_pattern used_sambawindow_listing

  set hostlist_started "no"
  if { $use_master_ip == "yes" } {
      spawn smbclient -L $used_master_name -W $used_wgroup -I $used_master_ip -U%
    } else {
      spawn smbclient -L $used_master_name -W $used_wgroup -U%
    }
  set id $spawn_id
  set timeout $smb_timeout
  expect {
    -i $id "error " {
      write_sambainfo "Error reading hostlist from workgroup $used_wgroup"
      }
    -i $id "Called name not present" {
      write_sambainfo "Master browser $used_master_name not responding.\nYou could try unsetting the parameter\n'use master IP' from configuration."
      }
    -i $id Password: {
      exp_send "\r"
      exp_continue
      }
    -i $id timeout {
      write_sambainfo "Error reading hostlist from workgroup $used_wgroup,\ntimeout detected!"
      }
    -i $id $hostlist_start {
      if { $used_wgroup != "" } {
          write_sambainfo "Hosts in workgroup $used_wgroup :"
          set hostlist_started "yes"
        } else {
          write_sambainfo "Hosts in spesific workgroup (master browser\n$used_master_name, $used_master_ip)"
          set hostlist_started "yes"
        }
      expect {
        -i $id -indices -re $hostlist_pattern {
          if { $expect_out(1,string)!="" } {
            set used_sambawindow_listing [linsert $used_sambawindow_listing end $expect_out(1,string)]
            if { $expect_out(3,string) == "" } {
                .bottom.right.bottom.sambawindow.smb insert end "$expect_out(1,string)"
                exp_continue
              } else {
                set comment [change_aeaeoeoe $expect_out(3,string)]
                .bottom.right.bottom.sambawindow.smb insert end "$expect_out(1,string) ($comment)"
                exp_continue
	      }
            }
          }
        }
      }
    }
  wait -i $id

  return $hostlist_started
}


# List shares from host (given as param)
# - check if alive (with nmblookup)
# - shares with smbclient
#
proc list_shares { masiina } {
  global smbwin_status used_machine_name used_machine_ip
  global used_wgroup password username
  global sharelist_start share_list_pattern
  global used_sambawindow_listing
  global smb_timeout do_we_test_host
  global use_default_password default_password spes_wg
  if { $masiina != "" } { set used_machine_name $masiina }
  set smbwin_status "2"
  set shares_count "0"
  clear_smbwindow
  .bottom.right.bottom.sambawindow.smb insert end "<List of hosts>"
  set used_sambawindow_listing [linsert $used_sambawindow_listing end "list_of_hosts"]

  if { $used_machine_name != "" } {
      write_sambainfo "Checking $used_machine_name, please wait .."
    } else {
      write_sambainfo "Checking $used_machine_ip, please wait .."
      solve_hostname_from_ip
      if { $used_machine_name == "" } { set used_machine_ip "nope" }
    }

  # test network host
  if { $do_we_test_host == "yes" } { test_host }

  # if default password given, use it
  if { $password != "" } {
      set listshares_password $password
    } else {
      if { $use_default_password == "yes" } {
        if { $default_password != "" } {
          set listshares_password $default_password
          }
        } else {
          set listshares_password ""
        }
      }

  if { $spes_wg == "yes" } { set used_machine_ip "" }

  # If alive, get list of shared dirs
  # If username given, use it
  if { $used_machine_ip != "nope" } {
    set dirlist_status ""
    if { $used_machine_ip == "" } {
        if { $username == "" } {
          spawn smbclient -L $used_machine_name
          } else {
          spawn smbclient -L $used_machine_name -U $username
          }
      } else {
        if { $username == "" } {
          spawn smbclient -L $used_machine_name -I $used_machine_ip
          } else {
          spawn smbclient -L $used_machine_name -I $used_machine_ip -U $username
          }
      }
    set id $spawn_id
    set timeout $smb_timeout
    expect {
      -i $id Password: {
        write_sambainfo "Sending password to host $used_machine_name"
        set dirlist_status "sending_password"
        exp_send "$listshares_password\r"
        exp_continue
        }
      -i $id ERRbadpw {
        write_sambainfo "Host $used_machine_name wrong username and/or password!"
        set dirlist_status "error"
        }
      -i $id ERRnoaccess {
        write_sambainfo "Host $used_machine_name access denied\nWrong username and/or password ?"
        set dirlist_status "error"
        }
      -i $id ERRaccess {
        write_sambainfo "Host $used_machine_name access denied\nWrong username and/or password ?"
        set dirlist_status "error"
        }
      -i $id "Called name not present" {
        write_sambainfo "Host $used_machine_name not available."
        set dirlist_status "error"
        }
      -i $id "Unknown host" {
        write_sambainfo "Host $used_machine_name not available."
        set dirlist_status "error"
        }
      -i $id timeout {
        write_sambainfo "Timeout checking host $used_machine_name!"
        set dirlist_status "error"
        close -i $id
        }
      -i $id $sharelist_start {
        set dirlist_status "success"
        write_sambainfo "Directories on host $used_machine_name :"
        set shares_count "1"
        expect {
          -i $id -indices -re $share_list_pattern {
            if { $expect_out(3,string)=="Disk"} {
              set used_sambawindow_listing [linsert $used_sambawindow_listing end $expect_out(1,string)]
              if { $expect_out(4,string) == "" } {
                set dirikka [change_aeaeoeoe $expect_out(1,string)]
                .bottom.right.bottom.sambawindow.smb insert end "$dirikka"
		} else {
                set dirikka [change_aeaeoeoe $expect_out(1,string)]
                set comment [change_aeaeoeoe $expect_out(4,string)]
                .bottom.right.bottom.sambawindow.smb insert end "$dirikka  ($comment)"
		}
              set shares_count [expr $shares_count+1]
              }
            if { $expect_out(1,string)=="" } {
              } else {
                exp_continue }
            }
          }
        }
      }
  wait -i $id
  if { $dirlist_status == "sending_password" } {
    write_sambainfo "Host $used_machine_name is not responding\nto password, perhaps wrong password ?"
    }
  }
  if { $shares_count == "1" } {
    write_sambainfo "Host $used_machine_name has no shared directories"
  }
}





# List contents of shared directories
#
proc list_directory { dir_to_list } {
  global used_machine_name used_machine_ip
  global username password
  global dir_list_start_pattern
  global dir_pattern
  global dir_ch
  global smbwin_status
  global used_directory
  global used_subdirectory
  global used_subdir_path
  global subdir_list
  global number_of_subdirs
  global used_sambawindow_listing
  global smb_timeout
  global file_size_type
  global show_timestamp
  global use_default_password default_password
  
  # if param given
  if { $dir_to_list != "" } {
    # status 2 (list of shares): let's check share given in param
    if { $smbwin_status == 2 } {
        set used_directory $dir_to_list
        set used_subdir_path ""
        set used_subdirectory ""
        set subdir_list ""
        set number_of_subdirs 0
    # status => 3 
      } else {
        # if subdir = ""
        if { $used_subdirectory == "" } {
	    set used_subdir_path $dir_ch$dir_to_list
            set used_subdirectory $dir_to_list
          } else {
            # add new subdir to list of subdirs
            set subdir_list [ linsert $subdir_list $number_of_subdirs $used_subdirectory]
            set number_of_subdirs [expr $number_of_subdirs +1]
            set used_subdir_path $used_subdir_path$dir_ch$dir_to_list
            set used_subdirectory $dir_to_list
          }
      }
    set smbwin_status [expr $smbwin_status +1]
    }

  # If default password is defined, use it

  if { $password != "" } {
      set listdir_password $password
    } else {
      if { $use_default_password == "yes" } {
        if { $default_password != "" } {
          set listdir_password $default_password
          }
        } else {
          set listdir_password ""
        }
      }

  clear_smbwindow
  set used_sambawindow_listing [linsert $used_sambawindow_listing end "/.."]
  .bottom.right.bottom.sambawindow.smb insert end "/.."

  set dirlist_status ""

  set used_directory [change_toascii $used_directory]
  set timeout $smb_timeout
  if { $used_subdir_path == "" } {
    set dirikka [change_aeaeoeoe $used_directory]
    write_sambainfo "Reading directory $dirikka from\nhost $used_machine_name, please wait .."
    if { $used_machine_ip == "" } {
        if { $username == "" } {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -c ls
        } else {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -U $username -c ls
        }
      } else {
        if { $username == "" } {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -I $used_machine_ip -c ls
        } else {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -I $used_machine_ip -U $username -c ls
        }
      }
  } else {
    set dirikka $used_directory$used_subdir_path
    set dirikka [change_aeaeoeoe $dirikka]
    write_sambainfo "Reading directory $used_directory$used_subdir_path from host $used_machine_name, please wait .."
    set commandline "cd \"$used_subdir_path\" ; ls"
    if { $used_machine_ip == "" } {
        if { $username == "" } {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -c $commandline
        } else {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -U $username -c $commandline
        }
      } else {
        if { $username == "" } {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -I $used_machine_ip -c $commandline
        } else {
          spawn smbclient \\\\$used_machine_name\\$used_directory $listdir_password -I $used_machine_ip -U $username -c $commandline
        }
      }
  }
  set id $spawn_id
  set timeout $smb_timeout
  expect {
    -i $id Password: {
      write_sambainfo "Sending password to host $used_machine_name"
      exp_send "$listdir_password\r"
      exp_continue
      }
    -i $id ERRnoaccess {
      write_sambainfo "Access denied. Perhaps wrong\nusername and/or password ?"
      set dirlist_status "error"
      }
    -i $id ERRaccess {
      write_sambainfo "Access denied. Perhaps wrong\nusername and/or password ?"
      set dirlist_status "error"
      }
    -i $id ERRinvnetname {
      write_sambainfo "Invalid network name in tree connect. Perhaps wrong\nsharename, username or password?"
      set dirlist_status "error"
      }
    -i $id ERRbadpw {
      set dirikka [change_aeaeoeoe $used_directory]
      write_sambainfo "Directory $dirikka from host $used_machine_name :\nwrong username and/or password!"
      set dirlist_status "error"
      }
    -i $id ERRbadpath {
      set dirikka $used_directory$used_subdir_path
      set dirikka [change_aeaeoeoe $dirikka]
      write_sambainfo "Invalid directory $dirikka\non host $used_machine_name"
      set dirlist_status "error"
      }
    -i $id "Called name not present" {
      write_sambainfo "host $used_machine_name not available at the moment"
      set dirlist_status "error"
      }
    -i $id timeout {
      set dirikka $used_directory$used_subdir_path
      set dirikka [change_aeaeoeoe $dirikka]
      write_sambainfo "Timeout reading directory $dirikka\non host $used_machine_name!"
      set dirlist_status "error"
      close -i $id
      }
    -i $id -indices -re $dir_pattern {
       if { [string first "D" $expect_out(3,string)] != -1 } {
          if { $expect_out(1,string) != "." } {
            if { $expect_out(1,string) != ".." } {
              set dirikka [change_aeaeoeoe $expect_out(1,string)]
              set used_sambawindow_listing [linsert $used_sambawindow_listing end "/$expect_out(1,string)"]
              set time_report ""
              if { $show_timestamp == "yes" } { set time_report $expect_out(5,string) }
              .bottom.right.bottom.sambawindow.smb insert end "/$dirikka $time_report"
              }
            }
        } else {
          set filename [change_aeaeoeoe $expect_out(1,string)]
          set used_sambawindow_listing [linsert $used_sambawindow_listing end $expect_out(1,string)]
          if { $file_size_type == "B" } {
              set size_to_report "$expect_out(4,string) bytes"
          } else {
              set size_to_report "[expr $expect_out(4,string)/1024] kB"
          }
          if { $show_timestamp == "yes" } {
              set time_report $expect_out(5,string)
            } else {
              set time_report ""
            }
          .bottom.right.bottom.sambawindow.smb insert end "$filename ($size_to_report) $time_report"
	}
      if { $expect_out(1,string)=="" } {
        } else {
          exp_continue }
      }
    }
  wait -i $id
  if { $dirlist_status == "" } {
    set dirikka $used_directory$used_subdir_path
    set dirikka [change_aeaeoeoe $dirikka]
    write_sambainfo "Directory $dirikka \non host $used_machine_name :"
  }
}
  




# Mount shared directories
#
proc mount_share { share } {
  global used_machine_name used_machine_ip
  global username password
  global share_to_be_mounted
  global clientname number_of_mounted_shares list_of_mounted_shares
  global smb_timeout
    
  .bottom.right.bottom.buttons.mountbutton configure -state disabled
  .bottom.right.bottom.buttons.button_umount configure -state disabled  
  .bottom.right.bottom.buttons.button_refresh configure -state disabled
  .bottom.right.bottom.buttons.button_parent configure -state disabled

  set mount_local_directory ""
  set result ""
  set share_to_be_mounted "$share"
  set mount_username ""
  set mount_password ""

  set save_pwd "no"
  
  set use_clientname ""
  
  toplevel .mount_askdir_window
  wm title .mount_askdir_window "Mount network share"

  label .mount_askdir_window.label_mountdir -text "Enter local directory for mounting network share"
  pack .mount_askdir_window.label_mountdir -side top

  frame .mount_askdir_window.dirframe
  pack .mount_askdir_window.dirframe -side top
    #button .mount_askdir_window.dirframe.button_browse -width 8 -text "browse"
    #pack .mount_askdir_window.dirframe.button_browse -side left
    entry .mount_askdir_window.dirframe.dirtomount -relief sunken -textvariable mount_local_directory -width 30
    pack .mount_askdir_window.dirframe.dirtomount -side top

  frame .mount_askdir_window.buttonframe
  pack .mount_askdir_window.buttonframe -side top

    button .mount_askdir_window.buttonframe.button_createdir -bd 1 -width 8 -text "create dir" -command {
      .mount_askdir_window.infoframe.infoline configure -state normal
      .mount_askdir_window.infoframe.infoline delete 1.0 end
      set result [make_localdirectory $mount_local_directory]
      if { $result != "" } {
        .mount_askdir_window.infoframe.infoline insert end "Cannot make directory $mount_local_directory :\n$result"
        } else {
        .mount_askdir_window.infoframe.infoline insert end "Succesfully created directory\n$mount_local_directory"
        }
      .mount_askdir_window.infoframe.infoline configure -state disabled
      }
    pack .mount_askdir_window.buttonframe.button_createdir -side left

    # do the mount
    button .mount_askdir_window.buttonframe.button_mount -bd 1 -width 8 -text "MOUNT!" -command {
      .mount_askdir_window.buttonframe.button_mount configure -state disabled
      .mount_askdir_window.lowbuttonframe.button_close configure -state disabled
      .mount_askdir_window.infoframe.infoline configure -state normal
      .mount_askdir_window.infoframe.infoline delete 1.0 end
      .mount_askdir_window.infoframe.infoline insert end "Trying to mount, please wait ..."
      .mount_askdir_window.infoframe.infoline configure -state disabled

      set mount_status ""

      if { $mount_username == "" } {
        if { $mount_password == "" } {
	  spawn smbmount //$used_machine_name/$share_to_be_mounted $mount_local_directory -I $used_machine_ip -C
          } else {
	  spawn smbmount //$used_machine_name/$share_to_be_mounted $mount_local_directory -I $used_machine_ip -P $mount_password -C
          }
	} else {
	if { $mount_password == "" } {
	  spawn smbmount //$used_machine_name/$share_to_be_mounted $mount_local_directory -I $used_machine_ip -U $mount_username -C
          } else {
	  spawn smbmount //$used_machine_name/$share_to_be_mounted $mount_local_directory -I $used_machine_ip -U $mount_username -P $mount_password -C
          }
	}
      set id $spawn_id
      set timeout $smb_timeout
      expect {
        -i $id "assword" {
          write_mountinfo "This network share needs a password.\nTrying to send plain enter as password."
          exp_send "$mount_password\r"
          exp_continue
	  }
        -i $id "smbmount must be installed suid root" {
          write_mountinfo "Mount error. smbmount and smbumount must be\ninstalled suid root!"
          set mount_status "error"
	  }
        -i $id "Invalid argument" {
          write_mountinfo "Mount error. Perhaps wrong/missing password\nand/or username ?"
          set mount_status "error"
	  }
        -i $id "Device or resource busy" {
          write_mountinfo "Mount error. Some resource already\nmounted on this local directory\nor directory not empty ?"
          set mount_status "error"
	  }
	-i $id "could not find mount point" {
          write_mountinfo "Mount-point directory not found!"
          set mount_status "error"
	  }
        -i $id "Operation not permitted" {
          write_mountinfo "Mount not permitted. Directory owned by\nsome other user ?"
          set mount_status "error"
	  }
        -i $id timeout {
          write_mountinfo "Cannot mount, timeout detected!"
          set mount_status "error"
          close -i $id
          }
        }
        wait -i $id
        if { $mount_status == "" } {
          write_mountinfo "Succesfully mounted share $share_to_be_mounted\nfrom host $used_machine_name to local directory\n$mount_local_directory"
          set list_of_mounted_shares [linsert $list_of_mounted_shares $number_of_mounted_shares $mount_local_directory]
          set number_of_mounted_shares [expr $number_of_mounted_shares +1]
          }
      .mount_askdir_window.buttonframe.button_mount configure -state normal
      .mount_askdir_window.lowbuttonframe.button_close configure -state normal
      }
    pack .mount_askdir_window.buttonframe.button_mount -side left

  frame .mount_askdir_window.checkbuttonsframe
  pack .mount_askdir_window.checkbuttonsframe -side top
    checkbutton .mount_askdir_window.checkbuttonsframe.save_pwd -text "Save password" -variable save_pwd -onvalue "yes" -offvalue "no"
    pack .mount_askdir_window.checkbuttonsframe.save_pwd -anchor w
    #checkbutton .mount_askdir_window.checkbuttonsframe.use_clientname -text "Use netbios name of client" -variable use_clientname -onvalue " -c $clientname" -offvalue ""
    #pack .mount_askdir_window.checkbuttonsframe.use_clientname -anchor w
    #checkbutton .mount_askdir_window.checkbuttonsframe.uppercase_passwd -text "Don't convert password to uppercase" -variable convert_passwd -onvalue " -C" -offvalue ""
    #pack .mount_askdir_window.checkbuttonsframe.uppercase_passwd -anchor w
    # checkbutton .mount_askdir_window.checkbuttonsframe.dontusepwd -text "Do not use any password" -variable dont_use_password -onvalue "-n" -offvalue ""
    # pack .mount_askdir_window.checkbuttonsframe.dontusepwd -anchor w
    
  frame .mount_askdir_window.optionsentryframe
  pack .mount_askdir_window.optionsentryframe -side top
      label .mount_askdir_window.optionsentryframe.mntuser_label -text "Username :"
      pack .mount_askdir_window.optionsentryframe.mntuser_label -side left
      entry .mount_askdir_window.optionsentryframe.mntuser -relief sunken -textvariable mount_username -width 10
      pack .mount_askdir_window.optionsentryframe.mntuser -side left
      label .mount_askdir_window.optionsentryframe.mntpwd_label -text "Password :"
      pack .mount_askdir_window.optionsentryframe.mntpwd_label -side left
      entry .mount_askdir_window.optionsentryframe.mntpwd -relief sunken -textvariable mount_password -width 10 -show "*"
      pack .mount_askdir_window.optionsentryframe.mntpwd -side left

  frame .mount_askdir_window.infoframe
  pack .mount_askdir_window.infoframe -side top
    label .mount_askdir_window.infoframe.label_status -text "status :"
    pack .mount_askdir_window.infoframe.label_status -side top
    text .mount_askdir_window.infoframe.infoline -width 50 -height 3 -state disabled
    pack .mount_askdir_window.infoframe.infoline -side top -fill both -expand no

  frame .mount_askdir_window.lowbuttonframe
  pack .mount_askdir_window.lowbuttonframe -side top
    button .mount_askdir_window.lowbuttonframe.button_help -bd 1 -width 8 -text "help"
    pack .mount_askdir_window.lowbuttonframe.button_help -side left
    button .mount_askdir_window.lowbuttonframe.button_close -bd 1 -width 8 -text "close" -command {
      if { $save_pwd == "no" } {
        set mount_password ""
	}
      .bottom.right.bottom.buttons.mountbutton configure -state normal
      .bottom.right.bottom.buttons.button_refresh configure -state normal
      .bottom.right.bottom.buttons.button_parent configure -state normal
      if { $number_of_mounted_shares > 0 } { .bottom.right.bottom.buttons.button_umount configure -state normal }
      destroy .mount_askdir_window
      }
    pack .mount_askdir_window.lowbuttonframe.button_close -side left

  if { $share == "" } {
      write_mountinfo "No shared directory given !"
    } else {
      write_mountinfo "Preparing to mount share $share\nfrom host $used_machine_name"
      }
}




# Unmount mounted directories
#
proc umount_shares {} {
  global list_of_mounted_shares number_of_mounted_shares
  global smb_timeout smbwin_status
  
  .bottom.right.bottom.buttons.mountbutton configure -state disabled
  .bottom.right.bottom.buttons.button_umount configure -state disabled  
  .bottom.right.bottom.buttons.button_refresh configure -state disabled
  .bottom.right.bottom.buttons.button_parent configure -state disabled

  toplevel .umount_window
  wm title .umount_window "Umount network shares"
  frame .umount_window.infoframe
  pack .umount_window.infoframe -side top
    label .umount_window.infoframe.label_status -text "status :"
    pack .umount_window.infoframe.label_status -side top
    text .umount_window.infoframe.infoline -width 50 -height 3 -relief groove -state disabled
    pack .umount_window.infoframe.infoline -side top -fill both -expand no

  frame .umount_window.listboxframe
  pack .umount_window.listboxframe -side top

    scrollbar .umount_window.listboxframe.scrollvert -orient vertical -command ".umount_window.listboxframe.umount_list yview"
    scrollbar .umount_window.listboxframe.scrollhoriz -orient horizontal -command ".umount_window.listboxframe.umount_list xview"
    pack .umount_window.listboxframe.scrollvert -side right -fill y
    pack .umount_window.listboxframe.scrollhoriz -side bottom -fill x

    listbox .umount_window.listboxframe.umount_list -width 50 -height 20 -selectmode extended \
      -yscrollcommand ".umount_window.listboxframe.scrollvert set" \
      -xscrollcommand ".umount_window.listboxframe.scrollhoriz set"
    pack .umount_window.listboxframe.umount_list -side bottom -fill both -expand yes

  frame .umount_window.lowbuttonframe
  pack .umount_window.lowbuttonframe -side top
    button .umount_window.lowbuttonframe.button_umount -bd 1 -width 8 -text "umount" -command {
      set index [.umount_window.listboxframe.umount_list curselection]
      if { $index != "" } {
        set share_to_be_umounted [lindex $list_of_mounted_shares $index]
        write_umountinfo "Trying to umount network share from\ndirectory $share_to_be_umounted,\nplease wait ..."
        set umount_status ""
        spawn smbumount $share_to_be_umounted
        set id $spawn_id
        set timeout $smb_timeout
        expect {
          -i $id "probably not smb-filesystem" {
            write_umountinfo "Directory $share_to_be_umounted\npropably doesn't contain smb-filesystem!\nPerhaps some other process has umounted it already ?"
            set umount_status "error"
            }
          -i $id "smbumount must be installed suid root" {
            write_umountinfo "Unmount error. smbmount and smbumount must be\ninstalled suid root!"
            set umount_status "error"
	    }
          -i $id "No such file or directory" {
            write_umountinfo "Directory $share_to_be_umounted\nnot found. Umounted & deleted by some other\nprocess, perhaps ?"
            set umount_status "error"
            }
          -i $id "You are not allowed to umount" {
            write_umountinfo "You are not allowed to umount directory\n$share_to_be_umounted.\nCheck your permissions and try again."
            set umount_status "error"
            }
          -i $id "Device or resource busy" {
            write_umountinfo "Resource is busy. Some other process\nusing mounted directory ?"
            set umount_status "error"
            }
          -i $id timeout {
            write_umountinfo "Cannot umount, timeout detected!"
            set umount_status "error"
            close -i $id
            }
          }
        wait -i $id
        if { $umount_status == "" } {
          write_umountinfo "Succesfully umounted directory\n$share_to_be_umounted"
          set list_of_mounted_shares [lreplace $list_of_mounted_shares $index $index]
          set number_of_mounted_shares [expr $number_of_mounted_shares -1]
          if { $number_of_mounted_shares == 0 } { .bottom.right.bottom.buttons.button_umount configure -state disabled }
          .umount_window.listboxframe.umount_list delete 0 end
          foreach i $list_of_mounted_shares {
            .umount_window.listboxframe.umount_list insert end $i
            }
          }
        }
      }
    pack .umount_window.lowbuttonframe.button_umount -side left
    button .umount_window.lowbuttonframe.button_help -bd 1 -width 8 -text "help"
    pack .umount_window.lowbuttonframe.button_help -side left
    button .umount_window.lowbuttonframe.button_close -bd 1 -width 8 -text "close" -command {
      .bottom.right.bottom.buttons.mountbutton configure -state disabled
      if { $smbwin_status == 2 } {
          .bottom.right.bottom.buttons.mountbutton configure -state normal
        } else {
          .bottom.right.bottom.buttons.mountbutton configure -state disabled
        }
      if { $number_of_mounted_shares > 0 } {
        .bottom.right.bottom.buttons.button_umount configure -state normal
        }
      if { $smbwin_status > 0 } { .bottom.right.bottom.buttons.button_parent configure -state normal }
      .bottom.right.bottom.buttons.button_refresh configure -state normal
      destroy .umount_window
      }
    pack .umount_window.lowbuttonframe.button_close -side left

  write_umountinfo "List of directories where shares are mounted :\nTo umount a directory, select one and\nclick 'umount'"
  .umount_window.listboxframe.umount_list delete 0 end
  foreach i $list_of_mounted_shares {
    .umount_window.listboxframe.umount_list insert end $i
    }
}




# Add local workgroups
#
proc add_workgroups {} {
  global number_of_addwgs list_of_addwgs
  set new_wg ""
  toplevel .other_wgs
  wm title .other_wgs "Add local workgroups"
  frame .other_wgs.top
  pack .other_wgs.top -side top
    label .other_wgs.top.wglabel -text "Workgroup :"
    # password
    entry .other_wgs.top.wg -relief sunken -textvariable new_wg -width 20
    pack .other_wgs.top.wglabel .other_wgs.top.wg -side left
  frame .other_wgs.left
  pack .other_wgs.left -side left
    frame .other_wgs.left.listboxframe
    pack .other_wgs.left.listboxframe -side top

      scrollbar .other_wgs.left.listboxframe.scrollvert -orient vertical -width 10 -command ".other_wgs.left.listboxframe.wg_list yview"
      scrollbar .other_wgs.left.listboxframe.scrollhoriz -orient horizontal -width 10 -command ".other_wgs.left.listboxframe.wg_list xview"
      pack .other_wgs.left.listboxframe.scrollvert -side right -fill y
      pack .other_wgs.left.listboxframe.scrollhoriz -side bottom -fill x

      listbox .other_wgs.left.listboxframe.wg_list -width 20 -height 10 -selectmode extended \
        -yscrollcommand ".other_wgs.left.listboxframe.scrollvert set" \
        -xscrollcommand ".other_wgs.left.listboxframe.scrollhoriz set"
      pack .other_wgs.left.listboxframe.wg_list -side bottom -fill both -expand yes
  frame .other_wgs.right
  pack .other_wgs.right -side right
    button .other_wgs.right.button_add -bd 1 -width 8 -text "add" -command {
      if { $new_wg != "" } {
        set new_wg [string toupper $new_wg]
        set list_of_addwgs [linsert $list_of_addwgs $number_of_addwgs $new_wg]
        set number_of_addwgs [expr $number_of_addwgs +1]
        .other_wgs.left.listboxframe.wg_list insert end $new_wg
        .other_wgs.right.button_del configure -state normal
        }
      }
    pack .other_wgs.right.button_add -side top
    button .other_wgs.right.button_del -bd 1 -width 8 -text "remove" -command {
      set index [.other_wgs.left.listboxframe.wg_list curselection]
      if {$index != ""} {
        set list_of_addwgs [lreplace $list_of_addwgs $index $index]
        .other_wgs.left.listboxframe.wg_list delete $index
        set number_of_addwgs [expr $number_of_addwgs -1]
        if { $number_of_addwgs == 0 } { .other_wgs.right.button_del configure -state disabled }
        }
      }
    pack .other_wgs.right.button_del -side top
    button .other_wgs.right.button_help -bd 1 -width 8 -text "help" -command {
      .other_wgs.right.button_close configure -state disabled
      show_help "addwghelp"
      }
    pack .other_wgs.right.button_help -side top
    button .other_wgs.right.button_close -bd 1 -width 8 -text "close" -command {
      .top.button_tools configure -state normal
      .top.button_help configure -state normal
      destroy .other_wgs
      }
    pack .other_wgs.right.button_close -side top
  if { $number_of_addwgs > 0 } {
    .other_wgs.right.button_del configure -state normal
    foreach index $list_of_addwgs { .other_wgs.left.listboxframe.wg_list insert end $index }
    } else { .other_wgs.right.button_del configure -state disabled }
  .other_wgs.top.wg delete 0 end
  .top.button_tools configure -state disabled
  .top.button_help configure -state disabled
}


# copy from network to local hd
#
proc copy_to_local { stuff_to_copy } {
  global used_directory used_local_directory used_subdir_path
  global used_machine_name used_machine_ip
  global username password
  global copy_or_not_to_copy
  global smb_timeout spes_wg
  global use_default_password default_password

  if { $spes_wg == "no" } { test_host }

  if { $used_machine_ip != "nope" } {
  .bottom.right.bottom.buttons.button_refresh configure -state disabled
  .bottom.right.bottom.buttons.button_copy configure -state disabled
  .bottom.right.bottom.buttons.button_delete configure -state disabled
  .bottom.right.bottom.buttons.button_parent configure -state disabled
  set copy_or_not_to_copy "y\r"
  set aeae_stuff_to_copy [change_aeaeoeoe $stuff_to_copy]

  # if default password defined, use it
  set copy_password $password
  if { $use_default_password == "yes" } {
    if { $default_password != "" } {
      set copy_password $default_password
      }
    }

  if { [string index $stuff_to_copy 0] == "/" } {
      set copy_type "dir"
      # rip "/"
      set stuff_to_copy [string trimleft $stuff_to_copy "/"]
      write_sambainfo "Trying to copy directory $aeae_stuff_to_copy from host $used_machine_name, please wait .."
      set dirget_status 0
      if { $used_subdir_path == "" } {
        set cmdline "archive 0 ; lcd \"$used_local_directory\" ; recurse ; mget \"$stuff_to_copy\""
        if { $used_machine_ip == "" } {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -U $username -c $cmdline
              }
          } else {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -U $username -c $cmdline
              }
          }
        } else {
        set cmdline "archive 0 ; lcd \"$used_local_directory\" ; recurse ; cd \"$used_subdir_path\" ; mget \"$stuff_to_copy\""
        if { $used_machine_ip == "" } {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $password -U $username -c $cmdline
              }
          } else {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -U $username -c $cmdline
              }
          }
        }
        set id $spawn_id
        #set timeout $smb_timeout
        expect {
          -i $id "ERRbadfile" {
            write_sambainfo "Error copying directory $aeae_stuff_to_copy from host $used_machine_name. File/dir not found! Copy cancelled."
            set copy_or_not_to_copy "n\r"
            close -i $id
            }
          -i $id "ERRbadpw" {
            write_sambainfo "Error copying directory $aeae_stuff_to_copy from host $used_machine_name. Wrong username and/or password !"
            set copy_or_not_to_copy "n\r"
            close -i $id
            }
          -i $id "ERRnoaccess" { 
            write_sambainfo "Error copying directory $aeae_stuff_to_copy from host $used_machine_name. Access denied! Copy cancelled."
            set copy_or_not_to_copy "n\r"
            close -i $id
            }
          -i $id "Failed to read" {
            write_sambainfo "Error: failed to read !"
            close -i $id
            }
          #-i $id timeout {
          #  if { $dirget_status == 0 } { 
          #    write_sambainfo "Error : timeout copying directory $aeae_stuff_to_copy from host $used_machine_name"
          #    close -i $id
          #    }
          #  } else {
          #  exp_continue
          #  }
          -i $id "getting file" {
            exp_continue
            }
          -i $id "Get file" {
            if { $dirget_status == 0 } {
              write_sambainfo "Copying directory $aeae_stuff_to_copy, please wait ..."
              cancel_copy
              set dirget_status 1
              }
            exp_send $copy_or_not_to_copy
            exp_continue
            }
          -i $id "Get directory" {
            if { $dirget_status == 0 } {
              write_sambainfo "Copying directory $aeae_stuff_to_copy, please wait ..."
              cancel_copy
              set dirget_status 1
              }
            exp_send $copy_or_not_to_copy
            exp_continue
            }
          }
        wait -i $id
        if { $dirget_status == 1 } {
          if { $copy_or_not_to_copy == "n\r" } {
              write_sambainfo "Copy cancelled!"
            } else {
              destroy .copy_window
              write_sambainfo "Directory $aeae_stuff_to_copy from host $used_machine_name copied succesfully!"
            }
          }
    } else {
      set copy_type "file"
      write_sambainfo "Trying to copy file $aeae_stuff_to_copy, please wait .."
      if { $used_subdir_path == "" } {
        set cmdline "archive 0 ; lcd \"$used_local_directory\" ; mget \"$stuff_to_copy\""
        if { $used_machine_ip == "" } {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -U $username -c $cmdline
              }
          } else {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -U $username -c $cmdline
              }
          }
        } else {
        set cmdline "archive 0 ; lcd \"$used_local_directory\" ; cd \"$used_subdir_path\" ; mget \"$stuff_to_copy\""
        if { $used_machine_ip == "" } {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -U $username -c $cmdline
              }
          } else {
            if { $username == "" } {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -c $cmdline
              } else {
                spawn smbclient \\\\$used_machine_name\\$used_directory $copy_password -I $used_machine_ip -U $username -c $cmdline
              }
          }
        }
      set fileget_status 0
      set id $spawn_id
      set timeout $smb_timeout
      expect {
          -i $id "ERRbadfile" {
            write_sambainfo "File $aeae_stuff_to_copy \nnot found!"
            close -i $id
            }
          -i $id "ERRnoaccess" {
            write_sambainfo "File $aeae_stuff_to_copy \naccess denied!"
            close -i $id
            }
          -i $id "ERRbadpw" {
            write_sambainfo "Error copying file $aeae_stuff_to_copy from host $used_machine_name. Wrong username and/or password !"
            close -i $id
            }
          -i $id timeout {
            if { $fileget_status == 0 } {
              write_sambainfo "Error : timeout copying file $aeae_stuff_to_copy from host $used_machine_name"
              close -i $id
              }
            }
          -i $id "getting file" {
            write_sambainfo "File $aeae_stuff_to_copy \ncopied succesfully!"
            }
          -i $id "Get file" {
            set fileget_status 1
            write_sambainfo "Copying file $aeae_stuff_to_copy"
            exp_send $copy_or_not_to_copy
            exp_continue
            }
          }
      wait -i $id
      if { $fileget_status == 1 } { write_sambainfo "File $aeae_stuff_to_copy \ncopied succesfully!" }
      }
  }
  .bottom.right.bottom.buttons.button_refresh configure -state normal
  .bottom.right.bottom.buttons.button_copy configure -state normal
  .bottom.right.bottom.buttons.button_delete configure -state normal
  .bottom.right.bottom.buttons.button_parent configure -state normal
}


# cancel-copy-window
#
proc cancel_copy {} {
  global copy_or_not_to_copy
  toplevel .copy_window
  wm title .copy_window "cancel copy ?"
  text .copy_window.infoline -width 30 -height 3 -state disabled -relief groove
  pack .copy_window.infoline -side top -fill both -expand no -pady 2
  button .copy_window.killahbutton -bd 1 -width 10 -text "STOP!" -command {
    write_sambainfo "Copy cancelled!"
    set copy_or_not_to_copy "n\r"
    destroy .copy_window
    }
  pack .copy_window.killahbutton -side left
  .copy_window.infoline configure -state normal
  .copy_window.infoline delete 1.0 end
  .copy_window.infoline insert end "Copy in progress"
  .copy_window.infoline configure -state disabled
}





proc make_localdirectory { dirikka } {
  set reply ""
  spawn mkdir $dirikka
  set id $spawn_id
  expect {
    -i $id "Permission denied" { set reply "Permission denied" }
    -i $id "File exists" { set reply "file or directory exists" }
    -i $id "No such file or directory" { set reply "No such file or directory" }
    }
  wait -i $id
  return $reply
}




# Configuration
#
proc options {} {
  global options_savefile
  global O_show_timestamp show_timestamp
  global O_show_license show_license  
  global O_clientname clientname
  global O_smb_timeout smb_timeout
  global O_save_pwd_file save_pwd_file
  global O_file_size_type file_size_type
  global O_use_default_password use_default_password
  global O_default_password default_password
  global O_confirm_quit confirm_quit
  global O_own_WG own_WG
  global O_use_master_ip use_master_ip
  set O_clientname "$clientname"
  set O_smb_timeout "$smb_timeout"
  set O_save_pwd_file "$save_pwd_file"
  set O_show_license "$show_license"
  set O_file_size_type "$file_size_type"
  set O_show_timestamp "$show_timestamp"
  set O_default_password "$default_password"
  set O_use_default_password "$use_default_password"
  set O_confirm_quit "$confirm_quit"
  set O_own_WG "$own_WG"
  set O_use_master_ip "$use_master_ip"
  .top.button_help configure -state disabled
  toplevel .options
  wm title .options "xsmb configuration"

  # home workgroup
  frame .options.wgroup
  pack .options.wgroup -side top -pady 2
    label .options.wgroup.own_WG_label -text "Own workgroup :"
    pack .options.wgroup.own_WG_label -side top
    entry .options.wgroup.own_WG -relief sunken -textvariable O_own_WG -width 20
    pack .options.wgroup.own_WG -side top
  # netbios clientname
  frame .options.nbclname
  pack .options.nbclname -side top -pady 2
    label .options.nbclname.clientname_label -text "Client's netbios name (if needed) :"
    pack .options.nbclname.clientname_label -side top
    entry .options.nbclname.clientname -relief sunken -textvariable O_clientname -width 20
    pack .options.nbclname.clientname -side top
  frame .options.timeout
  pack .options.timeout -side top -pady 2
    label .options.timeout.timeout_label -text "Timeout for samba operations (sec):"
    pack .options.timeout.timeout_label -side top
    entry .options.timeout.timeoutnum -relief sunken -textvariable O_smb_timeout -width 3
    pack .options.timeout.timeoutnum -side top
  frame .options.checkbuttonsframe
  pack .options.checkbuttonsframe -pady 2
    checkbutton .options.checkbuttonsframe.show_license -text "Show license at startup" -variable O_show_license -onvalue "yes" -offvalue "no"
    pack .options.checkbuttonsframe.show_license -anchor w
    #checkbutton .options.checkbuttonsframe.save_pwd_file -text "Save passwords to file" -variable O_save_pwd_file -onvalue "yes" -offvalue "no"
    #pack .options.checkbuttonsframe.save_pwd_file -anchor w
    checkbutton .options.checkbuttonsframe.file_size_type -text "Show file size in kilobytes" -variable O_file_size_type -onvalue "k" -offvalue "B"
    pack .options.checkbuttonsframe.file_size_type -anchor w
    checkbutton .options.checkbuttonsframe.showtime -text "Show timestamps" -variable O_show_timestamp -onvalue "yes" -offvalue "no"
    pack .options.checkbuttonsframe.showtime -anchor w
    checkbutton .options.checkbuttonsframe.usemip -text "Use master IP" -variable O_use_master_ip -onvalue "yes" -offvalue "no"
    pack .options.checkbuttonsframe.usemip -anchor w
    checkbutton .options.checkbuttonsframe.usedefpwd -text "Use default password" -variable O_use_default_password -onvalue "yes" -offvalue "no"
    pack .options.checkbuttonsframe.usedefpwd -anchor w
    label .options.checkbuttonsframe.defpwd_label -text "Default password :"
    pack .options.checkbuttonsframe.defpwd_label -side top
    entry .options.checkbuttonsframe.defpwd -relief sunken -textvariable O_default_password -width 10 -show "*"
    pack .options.checkbuttonsframe.defpwd -side top
    checkbutton .options.checkbuttonsframe.confirmquit -text "Confirm quit" -variable O_confirm_quit -onvalue "yes" -offvalue "no"
    pack .options.checkbuttonsframe.confirmquit -anchor w
  frame .options.closebuttons
  pack .options.closebuttons -side top -pady 3 -padx 2
    button .options.closebuttons.okbutton -bd 1 -width 5 -text "Ok" -command {
      set clientname "$O_clientname"
      set smb_timeout "$O_smb_timeout"
      set show_license "$O_show_license"
      set save_pwd_file "$O_save_pwd_file"
      set file_size_type "$O_file_size_type"
      set show_timestamp "$O_show_timestamp"
      set use_default_password "$O_use_default_password"
      set default_password "$O_default_password"
      set confirm_quit "$O_confirm_quit"
      set own_WG [string toupper $O_own_WG]
      set use_master_ip "$O_use_master_ip"
      .top.button_file configure -state normal
      .top.button_help configure -state normal
      destroy .options
      }
    pack .options.closebuttons.okbutton -side left
    button .options.closebuttons.notbutton -bd 1 -width 5 -text "Cancel" -command {
      .top.button_file configure -state normal
      .top.button_help configure -state normal
      destroy .options
      }
    pack .options.closebuttons.notbutton -side left
    button .options.closebuttons.save -bd 1 -width 5 -text "Save" -command {
      set savefile [open $options_savefile w 0600]
      puts $savefile "license $O_show_license"
      puts $savefile "timeout $O_smb_timeout"
      puts $savefile "clientn $O_clientname"
      puts $savefile "savepwd $O_save_pwd_file"
      puts $savefile "filesiz $O_file_size_type"
      puts $savefile "shwtime $O_show_timestamp"
      puts $savefile "usedpwd $O_use_default_password"
      puts $savefile "defpass $O_default_password"
      puts $savefile "conquit $O_confirm_quit"
      set O_own_WG [string toupper $O_own_WG]
      puts $savefile "ownWG $O_own_WG"
      puts $savefile "usemip $O_use_master_ip"
      close $savefile
      set clientname "$O_clientname"
      set smb_timeout "$O_smb_timeout"
      set show_license "$O_show_license"
      set save_pwd_file "$O_save_pwd_file"
      set file_size_type "$O_file_size_type"
      set show_timestamp "$O_show_timestamp"
      set use_default_password "$O_use_default_password"
      set default_password "$O_default_password"
      set confirm_quit "$O_confirm_quit"
      set own_WG "$O_own_WG"
      set use_master_ip "$O_use_master_ip"
      .options.infoframe.infoline configure -state normal
      .options.infoframe.infoline delete 1.0 end
      .options.infoframe.infoline insert end "Configuration saved."
      .options.infoframe.infoline configure -state disabled
      }
    pack .options.closebuttons.save -side left
    button .options.closebuttons.helpbutton -bd 1 -width 5 -text "Help" -command {
      .top.button_help configure -state disabled
      .options.closebuttons.okbutton configure -state disabled
      .options.closebuttons.notbutton configure -state disabled
      .options.closebuttons.save configure -state disabled
      .options.closebuttons.helpbutton configure -state disabled
      show_help "confhelp"
      }
    pack .options.closebuttons.helpbutton -side left
  frame .options.infoframe
  pack .options.infoframe -side top
    text .options.infoframe.infoline -width 30 -height 1 -state disabled -relief groove
    pack .options.infoframe.infoline -side top -fill both -expand no -pady 2
  .top.button_file configure -state disabled
}


# Test if network computer responds
# if, solve IP address
# if not, not
# no timeout needed here, 'cause this doesn't actually wait anything
#
proc test_host {} {
  global used_machine_name
  global used_machine_ip
  set nmblookup_ip_pattern "\n(\[^ ]*) $used_machine_name"
  spawn nmblookup $used_machine_name
  set id $spawn_id
  expect {
    -i $id failed {
      set used_machine_ip "nope"
      write_sambainfo "Host $used_machine_name not available."
      }
    -i $id -indices -re $nmblookup_ip_pattern {
      set used_machine_ip $expect_out(1,string)
      }
  }
  wait -i $id
}


# Test workgroup with nmblookup
# - if found, set master browser's name & IP
#
proc test_workgroup {} {
  global used_wgroup smb_timeout
  global master_name_pattern
  global used_master_ip used_master_name

  #koekytt v0.3.0:aan
  global used_master_ip_addresses used_master_names number_of_masters
  set used_master_ip_addresses ""
  set used_master_names ""
  set number_of_masters 0

  set master_IP_candidate_list ""
    
  # haetaan enste vain master ehdokkaiden IP-osotteet listaan $master_IP_candidate_list
  #
  set master_ip_pattern "\n(\[^ ]*) $used_wgroup"
  spawn nmblookup -M -S $used_wgroup
  set id $spawn_id
  set timeout $smb_timeout
  expect {
    -i $id failed {
      set used_master_ip ""; set used_master_name ""
      }
    -i $id -indices -re $master_ip_pattern {
      if { $expect_out(1,string) != "127.0.0.1" } {
       set master_IP_candidate_list [linsert $master_IP_candidate_list $number_of_masters $expect_out(1,string)]
       }
      exp_continue
      }
    -i $id timeout { close -i $id }
    }
  wait -i $id

  # seuraavaksi haetaan IP-osotteita vastaavat netbios nimet listaan $used_master_names
  # ja samalla IP-osotteet listaan $used_master_ip_addresses
  #
  foreach idx $master_IP_candidate_list {
    spawn nmblookup -A $idx
    set id $spawn_id
    set timeout $smb_timeout
    expect {
      -i $id -indices -re $master_name_pattern {
        set used_master_names [linsert $used_master_names $number_of_masters $expect_out(1,string)]
        set used_master_ip_addresses [linsert $used_master_ip_addresses $number_of_masters $idx]
        incr number_of_masters
        }
      -i $id timeout { close -i $id }
      }
    wait -i $id
    }
}


# Find computer
#
proc specify_host {} {
  global smbwin_status used_machine_name used_machine_ip
  global used_wgroup password username
  global do_we_test_host spes_wg
  set test_hostname ""
  set test_hostip ""
  toplevel .spechost
  wm title .spechost "Find computer"
  frame .spechost.entries
  pack .spechost.entries -side top -padx 20 -pady 2
    label .spechost.entries.hostname_label -text "NetBIOS name :"
    pack .spechost.entries.hostname_label -side top
    entry .spechost.entries.hostname -relief sunken -textvariable test_hostname -width 20
    pack .spechost.entries.hostname -side top
    label .spechost.entries.hostip_label -text "IP address :"
    pack .spechost.entries.hostip_label -side top
    entry .spechost.entries.hostip -relief sunken -textvariable test_hostip -width 20
    pack .spechost.entries.hostip -side top
  frame .spechost.buttons
  pack .spechost.buttons -side top -padx 2 -pady 2
    button .spechost.buttons.tryit_button -bd 1 -width 5 -text "Find" -command {
      if { $test_hostname != "" | $test_hostip != "" } {
        destroy .spechost
        set used_machine_name $test_hostname
        set used_machine_ip $test_hostip
        set do_we_test_host "no"
        set spes_wg "no"
        list_shares $used_machine_name
        enable_buttons
          .top.button_tools configure -state normal
        }
      }
    pack .spechost.buttons.tryit_button -side left
    button .spechost.buttons.cancel_button -bd 1 -width 5 -text "Cancel" -command {
      .top.button_tools configure -state normal
      destroy .spechost
      }
    pack .spechost.buttons.cancel_button -side left
  .top.button_tools configure -state disabled
}


# Find workgroup
#
proc specify_wg {} {
  global smbwin_status used_machine_name used_machine_ip
  global used_wgroup password username
  global do_we_test_host do_we_test_wg
  global used_master_name used_master_ip spes_wg
  set test_mastername ""
  set test_masterip ""
  toplevel .specwg
  wm title .specwg "try spesific workgroup"
  frame .specwg.entries
  pack .specwg.entries -side top -padx 20 -pady 2
    label .specwg.entries.hostname_label -text "NetBIOS name of Master Browser :"
    pack .specwg.entries.hostname_label -side top
    entry .specwg.entries.hostname -relief sunken -textvariable test_mastername -width 20
    pack .specwg.entries.hostname -side top
    label .specwg.entries.hostip_label -text "Master Browser's IP address :"
    pack .specwg.entries.hostip_label -side top
    entry .specwg.entries.hostip -relief sunken -textvariable test_masterip -width 20
    pack .specwg.entries.hostip -side top
  frame .specwg.buttons
  pack .specwg.buttons -side top -padx 2 -pady 2
    button .specwg.buttons.tryit_button -bd 1 -width 5 -text "Try it!" -command {
      if { $test_mastername != "" } {
        destroy .specwg
        set used_wgroup ""
        set used_master_name $test_mastername
        set used_master_ip $test_masterip
        set do_we_test_host "no"
        set do_we_test_wg "no"
        set spes_wg "yes"
        list_machines ""
        enable_buttons
        .top.button_tools configure -state normal
        }
      }
    pack .specwg.buttons.tryit_button -side left
    button .specwg.buttons.cancel_button -bd 1 -width 5 -text "cancel" -command {
      .top.button_tools configure -state normal
      destroy .specwg
      }
    pack .specwg.buttons.cancel_button -side left
    .top.button_tools configure -state disabled
}


# this solves netbios name based on IP address
# (nmblookup -A ip)
#
proc solve_hostname_from_ip {} {
  global used_machine_name used_machine_ip
  global master_name_pattern smb_timeout
  spawn nmblookup -A $used_machine_ip
  set id $spawn_id
  set timeout $smb_timeout
  expect {
   -i $id -indices -re $master_name_pattern { set used_machine_name $expect_out(1,string) }
   -i $id timeout { close -i $id }
       }
  wait -i $id
}


# Clone xsmb window. Could be more sophisticated, on future versions perhaps ...
# this assumes that program name really is "xsmb"
#
proc clone_xsmb {} {
  global argv
  exec xsmb &
}


# Clear samba-window and list
#
proc clear_smbwindow {} {
  global used_sambawindow_listing
  .bottom.right.bottom.sambawindow.smb delete 0 end
  set used_sambawindow_listing ""
}


# Clear & write infoline in mount window
#
proc write_mountinfo { stuff } {
  .mount_askdir_window.infoframe.infoline configure -state normal
  .mount_askdir_window.infoframe.infoline delete 1.0 end
  .mount_askdir_window.infoframe.infoline insert end "$stuff"
  .mount_askdir_window.infoframe.infoline configure -state disabled
}


# Clear & write infoline in unmount window
#
proc write_umountinfo { stuff } {
  .umount_window.infoframe.infoline configure -state normal
  .umount_window.infoframe.infoline delete 1.0 end
  .umount_window.infoframe.infoline insert end "$stuff"
  .umount_window.infoframe.infoline configure -state disabled
}


# Clear & write infoline in main window (samba-side infoline)
#
proc write_sambainfo { stuff } {
  .bottom.right.bottom.infolineframe.infoline configure -state normal
  .bottom.right.bottom.infolineframe.infoline delete 1.0 end
  .bottom.right.bottom.infolineframe.infoline insert end "$stuff"
  .bottom.right.bottom.infolineframe.infoline configure -state disabled
}


# Change local directory
#
proc change_localdir {} {
  global used_local_directory
  global new_used_local_directory
  .bottom.left.dirbox.nodelist delete 0 end
  .bottom.left.dirbox.nodelist insert end "$new_used_local_directory"
  set used_local_directory $new_used_local_directory
}


# refresh localdir-window
#
proc refresh_localdirwindow {} {
}


# This changes from string given as parameter :
# - 84h -> 
# - 94h -> 
# - 86h -> 
# - 8eh -> 
# - 99h -> 
# - 8fh -> 
# and returns the resulted string
#
proc change_aeaeoeoe { take_this } {
  set return_string [change_char $take_this "\x84" ""]
  set return_string [change_char $return_string "\x94" ""]
  set return_string [change_char $return_string "\x86" ""]
  set return_string [change_char $return_string "\x8e" ""]
  set return_string [change_char $return_string "\x99" ""]
  set return_string [change_char $return_string "\x8f" ""]
  return $return_string
}
proc change_char { in_string replace_this with_this } {
  set return_string $in_string
  while { [string first $replace_this $return_string] != -1 } {
    set char_index [string first $replace_this $return_string]
    set return_string "[string range $return_string 0 [expr $char_index -1]]$with_this[string range $return_string [expr $char_index +1] end]"
    }
  return $return_string
}
#
# and this the opposite
#
proc change_toascii { take_this } {
  set return_string [change_char $take_this "" "\x84"]
  set return_string [change_char $return_string "" "\x94"]
  set return_string [change_char $return_string "" "\x86"]
  set return_string [change_char $return_string "" "\x8e"]
  set return_string [change_char $return_string "" "\x99"]
  set return_string [change_char $return_string "" "\x8f"]
  return $return_string
}


# help window, based on given parameter
#
proc show_help { type_of_help } {
  global help_type version
  set helptitle(confhelp) "Configuration help"
  set helptitle(mainhelp) "Main window help"
  set helptitle(addwghelp) "Add workgroups help"
  set helptitle(faq) "F.A.Q."
  set helptitle(about) "About xsmb"
  set help_type $type_of_help
  .top.button_file configure -state disabled
  .top.button_tools configure -state disabled
  toplevel .$help_type
  wm title .$help_type $helptitle($help_type)
  frame .$help_type.textwin
  pack .$help_type.textwin -side top -expand yes
    scrollbar .$help_type.textwin.scrly -orient vertical -width 10 -command ".$help_type.textwin.helptext yview"
    pack .$help_type.textwin.scrly -side right -fill y -expand yes
    text .$help_type.textwin.helptext -wrap word -yscrollcommand ".$help_type.textwin.scrly set"
    pack .$help_type.textwin.helptext -side top -expand yes
  frame .$help_type.buttonframe
  pack .$help_type.buttonframe -side top -expand no
    button .$help_type.buttonframe.closebutton -bd 1 -width 10 -text "Close" -command {
       if { $help_type == "confhelp" } {
           .options.closebuttons.okbutton configure -state normal
           .options.closebuttons.notbutton configure -state normal
           .options.closebuttons.save configure -state normal
           .options.closebuttons.helpbutton configure -state normal
           .top.button_help configure -state normal
       } elseif { $help_type == "addwghelp" } {
           .other_wgs.right.button_close configure -state normal
       } elseif { $help_type == "mainhelp" } {
           .top.button_help configure -state normal
       } elseif { $help_type == "faq" } {
           .top.button_help configure -state normal
       } elseif { $help_type == "about" } {
           .top.button_help configure -state normal
       }
        .top.button_file configure -state normal
        .top.button_tools configure -state normal
        destroy .$help_type
     }
    pack .$help_type.buttonframe.closebutton -side left
  if { $help_type == "confhelp" } {
    .$help_type.textwin.helptext configure -state normal
    .$help_type.textwin.helptext insert end "Default workgroup :\n"
    .$help_type.textwin.helptext insert end "===================\n\n"
    .$help_type.textwin.helptext insert end "This is mandatory, since xsmb starts looking with one "
    .$help_type.textwin.helptext insert end "workgroup, which is this. Default workgroup can be defined "
    .$help_type.textwin.helptext insert end "here or as command line option :\n"
    .$help_type.textwin.helptext insert end "    xsmb -dwg <workgroup>\n"
    .$help_type.textwin.helptext insert end "    xsmb --default-workgroup <workgroup>\n"
    .$help_type.textwin.helptext insert end "If given as command line option, overrides default workgroup "
    .$help_type.textwin.helptext insert end "found in configuration file (if any)\n\n\n"
    .$help_type.textwin.helptext insert end "Client's netbios name :\n"
    .$help_type.textwin.helptext insert end "=======================\n\n"
    .$help_type.textwin.helptext insert end "When contacting remote hosts this is given as your "
    .$help_type.textwin.helptext insert end "computer's netbios name. This might not be necessary, so "
    .$help_type.textwin.helptext insert end "if you can operate without it, you don't have to define it.\n\n\n"
    .$help_type.textwin.helptext insert end "Samba timeout :\n"
    .$help_type.textwin.helptext insert end "===============\n\n"
    .$help_type.textwin.helptext insert end "This is timeout in seconds to use with samba commands "
    .$help_type.textwin.helptext insert end "'smbclient' and 'nmblookup'. If your network is loaded "
    .$help_type.textwin.helptext insert end "or otherwise slow, it would make sense to increase this. "
    .$help_type.textwin.helptext insert end "Default is 10 seconds.\n\n\n"
    .$help_type.textwin.helptext insert end "Show license at startup :\n"
    .$help_type.textwin.helptext insert end "=========================\n\n"
    .$help_type.textwin.helptext insert end "Uncheck this to prevent GPL license to pop up every time "
    .$help_type.textwin.helptext insert end "you start xsmb.\n\n\n"
    #.$help_type.textwin.helptext insert end "Save passwords to file :\n"
    #.$help_type.textwin.helptext insert end "========================\n\n"
    #.$help_type.textwin.helptext insert end "Select this if you want host/share -spesific passwords to "
    #.$help_type.textwin.helptext insert end "be saved to file, so that xsmb remembers them on future "
    #.$help_type.textwin.helptext insert end "sessions. The file will have read permissions only for "
    #.$help_type.textwin.helptext insert end "the user who started xsmb, so this should be safe.\n\n\n"
    .$help_type.textwin.helptext insert end "Show file size in kilobytes :\n"
    .$help_type.textwin.helptext insert end "=============================\n\n"
    .$help_type.textwin.helptext insert end "With this option, all file sizes are shown as kilobytes "
    .$help_type.textwin.helptext insert end "(normally bytes)\n\n\n"
    .$help_type.textwin.helptext insert end "Show timestamps :\n"
    .$help_type.textwin.helptext insert end "=================\n\n"
    .$help_type.textwin.helptext insert end "If selected, with files and directories are shown the "
    .$help_type.textwin.helptext insert end "time stamp (Tue Sep 29 10:27:02 1998, for example)\n\n\n"
    .$help_type.textwin.helptext insert end "Use default password & Default password :\n"
    .$help_type.textwin.helptext insert end "=========================================\n\n"
    .$help_type.textwin.helptext insert end "This can be used as default password if no password is "
    .$help_type.textwin.helptext insert end "given in the main window and remote host demands it. "
    .$help_type.textwin.helptext insert end "This is useful if several hosts use the same password.\n\n\n"
    .$help_type.textwin.helptext insert end "Confirm quit :\n"
    .$help_type.textwin.helptext insert end "==============\n\n"
    .$help_type.textwin.helptext insert end "Check this if you don't want to have the 'Are you sure you "
    .$help_type.textwin.helptext insert end "want to quit?' checkbox when quitting xsmb. If remote "
    .$help_type.textwin.helptext insert end "directories are still mounted, this won't have any effect, "
    .$help_type.textwin.helptext insert end "the confirm box will still be displayed.\n\n\n"
    .$help_type.textwin.helptext insert end "OK button :\n"
    .$help_type.textwin.helptext insert end "===========\n\n"
    .$help_type.textwin.helptext insert end "With OK the changes you made will be remembered through this "
    .$help_type.textwin.helptext insert end "session, but will not be saved to file. If you want permanent "
    .$help_type.textwin.helptext insert end "changes, see 'Save button'\n\n\n"
    .$help_type.textwin.helptext insert end "Save button :\n"
    .$help_type.textwin.helptext insert end "=============\n\n"
    .$help_type.textwin.helptext insert end "This saves current configuration to a file '.xsmb.configuration' "
    .$help_type.textwin.helptext insert end "in user's home directory, so that xsmb can load them when "
    .$help_type.textwin.helptext insert end "started next time.\n\n\n"
    .$help_type.textwin.helptext configure -state disabled
    } elseif { $help_type == "mainhelp" } {
    .$help_type.textwin.helptext configure -state normal
    .$help_type.textwin.helptext insert end "Menu buttons :\n"
    .$help_type.textwin.helptext insert end "==============\n\n"
    .$help_type.textwin.helptext insert end "File menu :\n"
    .$help_type.textwin.helptext insert end "'Configuration' - this will start the configuration window\n"
    .$help_type.textwin.helptext insert end "'Clone window' - starts another xsmb program\n"
    .$help_type.textwin.helptext insert end "'Quit' - quits xsmb\n\n"
    .$help_type.textwin.helptext insert end "Tools menu :\n\n"
    .$help_type.textwin.helptext insert end "'Add local workgroup' - you can manually add names of workgroups to "
    .$help_type.textwin.helptext insert end "search, in case your default workgroup's master browser doesn't "
    .$help_type.textwin.helptext insert end "find them. These must be on your local network, i.e. workgroups in foreign "
    .$help_type.textwin.helptext insert end "networks cannot be added (or can be added, but probably not found). "
    .$help_type.textwin.helptext insert end "However, remote network browsing is possible if both local and remote network has "
    .$help_type.textwin.helptext insert end "samba server as master browser and 'remote announce' & 'remote browse sync' "
    .$help_type.textwin.helptext insert end "options configured.\n\n"
    .$help_type.textwin.helptext insert end "'Find remote workgroup' - with this you can try to locate workgroups "
    .$help_type.textwin.helptext insert end "in remote networks. You need to know the name and IP of master browser of "
    .$help_type.textwin.helptext insert end "that workgroup to make this work. Also you need to add the domainname of remote "
    .$help_type.textwin.helptext insert end "network to file /etc/resolv.conf, line 'search domain remote_domain'.\n\n"
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end "'Find computer' - with this you can access one spesific host (on local or remote "
    .$help_type.textwin.helptext insert end "network). Host's netbios name and/or IP address must "
    .$help_type.textwin.helptext insert end "be given. This is also useful if your master browser didn't "
    .$help_type.textwin.helptext insert end "list certain host you want to access (host just booted up etc.)\n\n\n"
    .$help_type.textwin.helptext insert end "Window sections :\n"
    .$help_type.textwin.helptext insert end "=================\n\n"
    .$help_type.textwin.helptext insert end "xsmb main window is divided into 3 sections;\n"
    .$help_type.textwin.helptext insert end "- upper buttonframe which contains menubuttons\n"
    .$help_type.textwin.helptext insert end "- on the left side local hd directory and it's listing\n"
    .$help_type.textwin.helptext insert end "- right side where network workgroups, hosts and their shared "
    .$help_type.textwin.helptext insert end "directories are shown\n\n\n"
    .$help_type.textwin.helptext insert end "Usage :\n"
    .$help_type.textwin.helptext insert end "=========\n\n"
    .$help_type.textwin.helptext insert end "When xsmb starts, it first lists available workgroups. You can "
    .$help_type.textwin.helptext insert end "access them (and following hosts & directories) by double clicking them with left mousebutton. "
    .$help_type.textwin.helptext insert end "Between this listing and buttons is an info window, where you can see what xsmb is currently "
    .$help_type.textwin.helptext insert end "doing (and possible error messages).\n\n"
    .$help_type.textwin.helptext insert end "Meaning of buttons above the info window :\n"
    .$help_type.textwin.helptext insert end "'R' - refresh (= try again) network window. Especially useful when, for example, "
    .$help_type.textwin.helptext insert end "password or username is wrong. After typing the right password and "
    .$help_type.textwin.helptext insert end "username, you can try again with refresh button. Also useful when "
    .$help_type.textwin.helptext insert end "getting network timeouts etc.\n"
    .$help_type.textwin.helptext insert end "'Up' - this shows the 'parent' situation of network window, etc. "
    .$help_type.textwin.helptext insert end "parent directory or from shares to hostlist or from hostlist to "
    .$help_type.textwin.helptext insert end "list of workgroups.\n"
    .$help_type.textwin.helptext insert end "'cp' - this copies selected directory/file from remote host to local directory.\n"
    .$help_type.textwin.helptext insert end "'rm' - this deletes selected directory/file from remote host (not implemented yet).\n"
    .$help_type.textwin.helptext insert end "'mnt' - xsmb includes a mount tool. You can mount network "
    .$help_type.textwin.helptext insert end "shares, for use with other programs for example. xsmb keeps a list "
    .$help_type.textwin.helptext insert end "of mounted shares, and you can unmount them when they are not needed.\n"
    .$help_type.textwin.helptext insert end "'umnt' - with this you can unmount mounted network shares.\n\n"
    .$help_type.textwin.helptext insert end "Username and password fields :\n"
    .$help_type.textwin.helptext insert end "The 'username' and 'password' are used when connecting remote "
    .$help_type.textwin.helptext insert end "hosts. If remote host needs username and/or password, they should "
    .$help_type.textwin.helptext insert end "be given here.\n"
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext configure -state disabled
    } elseif { $help_type == "addwghelp" } {
    .$help_type.textwin.helptext configure -state normal
    .$help_type.textwin.helptext insert end "You can add local workgroups by typing the name of the workgroup "
    .$help_type.textwin.helptext insert end "in 'Workgroup: ' field and pressing the 'add' button.\n\n"
    .$help_type.textwin.helptext insert end "With 'remove' button you can remove selected workgroups.\n\n"
    .$help_type.textwin.helptext insert end "xsmb tries to search these workgroups every time it lists available "
    .$help_type.textwin.helptext insert end "workgroups."
    .$help_type.textwin.helptext configure -state disabled
    } elseif { $help_type == "faq" } {
    .$help_type.textwin.helptext configure -state normal
    .$help_type.textwin.helptext insert end "Frequently asked questions\n"
    .$help_type.textwin.helptext insert end "==========================\n\n"
    .$help_type.textwin.helptext insert end "Q. I started xsmb and the infoline says 'Workgroups :' but "
    .$help_type.textwin.helptext insert end "there are no workgroups listed. What's up ?\n"
    .$help_type.textwin.helptext insert end "A. There's several reasons for this to happen:\n"
    .$help_type.textwin.helptext insert end "1. Check that you have samba installed. xsmb needs programs 'smbclient' "
    .$help_type.textwin.helptext insert end "'nmblookup', 'smbmount' and 'smbumount' to be in your path, so "
    .$help_type.textwin.helptext insert end "check that also. 2. You have to have at least one default "
    .$help_type.textwin.helptext insert end "workgroup defined. This can be defined in configuration window ('file-configuration') "
    .$help_type.textwin.helptext insert end "or as command line option. 3. It might happen that there's no master "
    .$help_type.textwin.helptext insert end "browser for your default workgroup available at the moment. "
    .$help_type.textwin.helptext insert end "If you have more than one workgroup in your network, try adding those "
    .$help_type.textwin.helptext insert end "in 'tools-add workgroup'.\n\n"
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end "Q. I can't mount any shares ?? I have a directory where to mount, it's empty and "
    .$help_type.textwin.helptext insert end "the permissions for that directory are correct.\n"
    .$help_type.textwin.helptext insert end "A. You probably don't have smbmount and smbumount suid root, "
    .$help_type.textwin.helptext insert end "so ask your system administrator to do that.\n"
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext configure -state disabled
    } elseif { $help_type == "about" } {
    .$help_type.textwin.helptext configure -state normal
    .$help_type.textwin.helptext insert end "xsmb $version\n\n"
    .$help_type.textwin.helptext insert end "Copyright (C) Jorma Korpisalo 1998\n"
    .$help_type.textwin.helptext insert end "email: jkorpisa@ratol.fi\n\n"
    .$help_type.textwin.helptext insert end "xsmb home page at http://www.ratol.fi/~jkorpisa/xsmb.html\n"
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext insert end ""
    .$help_type.textwin.helptext configure -state disabled
    }

}


# Show GNU GPL
#
proc show_GNU_GPL {} {
  global version
  .top.button_help configure -state disabled
  .top.button_tools configure -state disabled
  toplevel .gnugpl_window
  wm title .gnugpl_window "GNU GENERAL PUBLIC LICENSE"
  frame .gnugpl_window.textwin
  pack .gnugpl_window.textwin -side top
    scrollbar .gnugpl_window.textwin.scrly -orient vertical -command ".gnugpl_window.textwin.gpltext yview"
    pack .gnugpl_window.textwin.scrly -side right -fill y
    text .gnugpl_window.textwin.gpltext -wrap word -yscrollcommand ".gnugpl_window.textwin.scrly set"
    pack .gnugpl_window.textwin.gpltext -side top -expand yes
  frame .gnugpl_window.buttonframe
  pack .gnugpl_window.buttonframe -side top
    button .gnugpl_window.buttonframe.agreebutton -bd 1 -width 10 -text "Agree" -command {
      destroy .gnugpl_window
      .top.button_help configure -state normal
      .top.button_tools configure -state normal
      # pivitetn smb tiedot
      refresh_smbwindow ""
      # katotaan paikallinen hakemisto
      CheckLocalDirectory
      }
    button .gnugpl_window.buttonframe.disagreebutton -bd 1 -width 10 -text "Disagree" -command { destroy . }
    pack .gnugpl_window.buttonframe.agreebutton -side left
    pack .gnugpl_window.buttonframe.disagreebutton -side left
  .gnugpl_window.textwin.gpltext configure -state normal
  .gnugpl_window.textwin.gpltext insert end "xsmb $version Copyright (C) Jorma Korpisalo 1998\n"
  .gnugpl_window.textwin.gpltext insert end "xsmb if free software. Terms and conditions for copying, distribution and modification follow:\n\n"
  .gnugpl_window.textwin.gpltext insert end "                    GNU GENERAL PUBLIC LICENSE\n"
  .gnugpl_window.textwin.gpltext insert end "   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n"  
  .gnugpl_window.textwin.gpltext insert end "  0. This License applies to any program or other work which contains "
  .gnugpl_window.textwin.gpltext insert end "a notice placed by the copyright holder saying it may be distributed "
  .gnugpl_window.textwin.gpltext insert end "under the terms of this General Public License.  The \"Program\", below, "
  .gnugpl_window.textwin.gpltext insert end "refers to any such program or work, and a \"work based on the Program\" "
  .gnugpl_window.textwin.gpltext insert end "means either the Program or any derivative work under copyright law: "
  .gnugpl_window.textwin.gpltext insert end "that is to say, a work containing the Program or a portion of it, "
  .gnugpl_window.textwin.gpltext insert end "either verbatim or with modifications and/or translated into another "
  .gnugpl_window.textwin.gpltext insert end "language.  (Hereinafter, translation is included without limitation in "
  .gnugpl_window.textwin.gpltext insert end "the term \"modification\".)  Each licensee is addressed as \"you\".\n\n"
  .gnugpl_window.textwin.gpltext insert end "Activities other than copying, distribution and modification are not "
  .gnugpl_window.textwin.gpltext insert end "covered by this License; they are outside its scope.  The act of "
  .gnugpl_window.textwin.gpltext insert end "running the Program is not restricted, and the output from the Program "
  .gnugpl_window.textwin.gpltext insert end "is covered only if its contents constitute a work based on the "
  .gnugpl_window.textwin.gpltext insert end "Program (independent of having been made by running the Program). "
  .gnugpl_window.textwin.gpltext insert end "Whether that is true depends on what the Program does.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  1. You may copy and distribute verbatim copies of the Program's\n"
  .gnugpl_window.textwin.gpltext insert end "source code as you receive it, in any medium, provided that you\n"
  .gnugpl_window.textwin.gpltext insert end "conspicuously and appropriately publish on each copy an appropriate\n"
  .gnugpl_window.textwin.gpltext insert end "copyright notice and disclaimer of warranty; keep intact all the\n"
  .gnugpl_window.textwin.gpltext insert end "notices that refer to this License and to the absence of any warranty;\n"
  .gnugpl_window.textwin.gpltext insert end "and give any other recipients of the Program a copy of this License\n"
  .gnugpl_window.textwin.gpltext insert end "along with the Program.\n\n"
  .gnugpl_window.textwin.gpltext insert end "You may charge a fee for the physical act of transferring a copy, and\n"
  .gnugpl_window.textwin.gpltext insert end "you may at your option offer warranty protection in exchange for a fee.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  2. You may modify your copy or copies of the Program or any portion\n"
  .gnugpl_window.textwin.gpltext insert end "of it, thus forming a work based on the Program, and copy and\n"
  .gnugpl_window.textwin.gpltext insert end "distribute such modifications or work under the terms of Section 1\n"
  .gnugpl_window.textwin.gpltext insert end "above, provided that you also meet all of these conditions:\n\n"
  .gnugpl_window.textwin.gpltext insert end "    a) You must cause the modified files to carry prominent notices\n"
  .gnugpl_window.textwin.gpltext insert end "    stating that you changed the files and the date of any change.\n\n"
  .gnugpl_window.textwin.gpltext insert end "    b) You must cause any work that you distribute or publish, that in\n"
  .gnugpl_window.textwin.gpltext insert end "    whole or in part contains or is derived from the Program or any\n"
  .gnugpl_window.textwin.gpltext insert end "    part thereof, to be licensed as a whole at no charge to all third\n"
  .gnugpl_window.textwin.gpltext insert end "    parties under the terms of this License.\n\n"
  .gnugpl_window.textwin.gpltext insert end "    c) If the modified program normally reads commands interactively\n"
  .gnugpl_window.textwin.gpltext insert end "    when run, you must cause it, when started running for such\n"
  .gnugpl_window.textwin.gpltext insert end "    interactive use in the most ordinary way, to print or display an\n"
  .gnugpl_window.textwin.gpltext insert end "    announcement including an appropriate copyright notice and a\n"
  .gnugpl_window.textwin.gpltext insert end "    notice that there is no warranty (or else, saying that you provide\n"
  .gnugpl_window.textwin.gpltext insert end "    a warranty) and that users may redistribute the program under\n"
  .gnugpl_window.textwin.gpltext insert end "    these conditions, and telling the user how to view a copy of this\n"
  .gnugpl_window.textwin.gpltext insert end "    License.  (Exception: if the Program itself is interactive but\n"
  .gnugpl_window.textwin.gpltext insert end "    does not normally print such an announcement, your work based on\n"
  .gnugpl_window.textwin.gpltext insert end "    the Program is not required to print an announcement.)\n"
  .gnugpl_window.textwin.gpltext insert end "These requirements apply to the modified work as a whole.  If\n"
  .gnugpl_window.textwin.gpltext insert end "identifiable sections of that work are not derived from the Program,\n"
  .gnugpl_window.textwin.gpltext insert end "and can be reasonably considered independent and separate works in\n"
  .gnugpl_window.textwin.gpltext insert end "themselves, then this License, and its terms, do not apply to those\n"
  .gnugpl_window.textwin.gpltext insert end "sections when you distribute them as separate works.  But when you\n"
  .gnugpl_window.textwin.gpltext insert end "distribute the same sections as part of a whole which is a work based\n"
  .gnugpl_window.textwin.gpltext insert end "on the Program, the distribution of the whole must be on the terms of\n"
  .gnugpl_window.textwin.gpltext insert end "this License, whose permissions for other licensees extend to the\n"
  .gnugpl_window.textwin.gpltext insert end "entire whole, and thus to each and every part regardless of who wrote it.\n\n"
  .gnugpl_window.textwin.gpltext insert end "Thus, it is not the intent of this section to claim rights or contest\n"
  .gnugpl_window.textwin.gpltext insert end "your rights to work written entirely by you; rather, the intent is to\n"
  .gnugpl_window.textwin.gpltext insert end "exercise the right to control the distribution of derivative or\n"
  .gnugpl_window.textwin.gpltext insert end "collective works based on the Program.\n\n"
  .gnugpl_window.textwin.gpltext insert end "In addition, mere aggregation of another work not based on the Program\n"
  .gnugpl_window.textwin.gpltext insert end "with the Program (or with a work based on the Program) on a volume of\n"
  .gnugpl_window.textwin.gpltext insert end "a storage or distribution medium does not bring the other work under\n"
  .gnugpl_window.textwin.gpltext insert end "the scope of this License.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  3. You may copy and distribute the Program (or a work based on it,\n"
  .gnugpl_window.textwin.gpltext insert end "under Section 2) in object code or executable form under the terms of\n"
  .gnugpl_window.textwin.gpltext insert end "Sections 1 and 2 above provided that you also do one of the following:\n\n"
  .gnugpl_window.textwin.gpltext insert end "    a) Accompany it with the complete corresponding machine-readable\n"
  .gnugpl_window.textwin.gpltext insert end "    source code, which must be distributed under the terms of Sections\n"
  .gnugpl_window.textwin.gpltext insert end "    1 and 2 above on a medium customarily used for software interchange; or,\n"
  .gnugpl_window.textwin.gpltext insert end "    b) Accompany it with a written offer, valid for at least three\n"
  .gnugpl_window.textwin.gpltext insert end "    years, to give any third party, for a charge no more than your\n"
  .gnugpl_window.textwin.gpltext insert end "    cost of physically performing source distribution, a complete\n"
  .gnugpl_window.textwin.gpltext insert end "    machine-readable copy of the corresponding source code, to be\n"
  .gnugpl_window.textwin.gpltext insert end "    distributed under the terms of Sections 1 and 2 above on a medium\n"
  .gnugpl_window.textwin.gpltext insert end "    customarily used for software interchange; or,\n\n"
  .gnugpl_window.textwin.gpltext insert end "    c) Accompany it with the information you received as to the offer\n"
  .gnugpl_window.textwin.gpltext insert end "    to distribute corresponding source code.  (This alternative is\n"
  .gnugpl_window.textwin.gpltext insert end "    allowed only for noncommercial distribution and only if you\n"
  .gnugpl_window.textwin.gpltext insert end "    received the program in object code or executable form with such\n"
  .gnugpl_window.textwin.gpltext insert end "    an offer, in accord with Subsection b above.)\n\n"
  .gnugpl_window.textwin.gpltext insert end "The source code for a work means the preferred form of the work for\n"
  .gnugpl_window.textwin.gpltext insert end "making modifications to it.  For an executable work, complete source\n"
  .gnugpl_window.textwin.gpltext insert end "code means all the source code for all modules it contains, plus any\n"
  .gnugpl_window.textwin.gpltext insert end "associated interface definition files, plus the scripts used to\n"
  .gnugpl_window.textwin.gpltext insert end "control compilation and installation of the executable.  However, as a\n"
  .gnugpl_window.textwin.gpltext insert end "special exception, the source code distributed need not include\n"
  .gnugpl_window.textwin.gpltext insert end "anything that is normally distributed (in either source or binary\n"
  .gnugpl_window.textwin.gpltext insert end "form) with the major components (compiler, kernel, and so on) of the\n"
  .gnugpl_window.textwin.gpltext insert end "operating system on which the executable runs, unless that component\n"
  .gnugpl_window.textwin.gpltext insert end "itself accompanies the executable.\n\n"
  .gnugpl_window.textwin.gpltext insert end "If distribution of executable or object code is made by offering\n"
  .gnugpl_window.textwin.gpltext insert end "access to copy from a designated place, then offering equivalent\n"
  .gnugpl_window.textwin.gpltext insert end "access to copy the source code from the same place counts as\n"
  .gnugpl_window.textwin.gpltext insert end "distribution of the source code, even though third parties are not\n"
  .gnugpl_window.textwin.gpltext insert end "compelled to copy the source along with the object code.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  4. You may not copy, modify, sublicense, or distribute the Program\n"
  .gnugpl_window.textwin.gpltext insert end "except as expressly provided under this License.  Any attempt\n"
  .gnugpl_window.textwin.gpltext insert end "otherwise to copy, modify, sublicense or distribute the Program is\n"
  .gnugpl_window.textwin.gpltext insert end "void, and will automatically terminate your rights under this License.\n"
  .gnugpl_window.textwin.gpltext insert end "However, parties who have received copies, or rights, from you under\n"
  .gnugpl_window.textwin.gpltext insert end "this License will not have their licenses terminated so long as such\n"
  .gnugpl_window.textwin.gpltext insert end "parties remain in full compliance.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  5. You are not required to accept this License, since you have not\n"
  .gnugpl_window.textwin.gpltext insert end "signed it.  However, nothing else grants you permission to modify or\n"
  .gnugpl_window.textwin.gpltext insert end "distribute the Program or its derivative works.  These actions are\n"
  .gnugpl_window.textwin.gpltext insert end "prohibited by law if you do not accept this License.  Therefore, by\n"
  .gnugpl_window.textwin.gpltext insert end "modifying or distributing the Program (or any work based on the\n"
  .gnugpl_window.textwin.gpltext insert end "Program), you indicate your acceptance of this License to do so, and\n"
  .gnugpl_window.textwin.gpltext insert end "all its terms and conditions for copying, distributing or modifying\n"
  .gnugpl_window.textwin.gpltext insert end "the Program or works based on it.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  6. Each time you redistribute the Program (or any work based on the\n"
  .gnugpl_window.textwin.gpltext insert end "Program), the recipient automatically receives a license from the\n"
  .gnugpl_window.textwin.gpltext insert end "original licensor to copy, distribute or modify the Program subject to\n"
  .gnugpl_window.textwin.gpltext insert end "these terms and conditions.  You may not impose any further\n"
  .gnugpl_window.textwin.gpltext insert end "restrictions on the recipients' exercise of the rights granted herein.\n"
  .gnugpl_window.textwin.gpltext insert end "You are not responsible for enforcing compliance by third parties to\n"
  .gnugpl_window.textwin.gpltext insert end "this License.\n"
  .gnugpl_window.textwin.gpltext insert end "  7. If, as a consequence of a court judgment or allegation of patent\n"
  .gnugpl_window.textwin.gpltext insert end "infringement or for any other reason (not limited to patent issues),\n"
  .gnugpl_window.textwin.gpltext insert end "conditions are imposed on you (whether by court order, agreement or\n"
  .gnugpl_window.textwin.gpltext insert end "otherwise) that contradict the conditions of this License, they do not\n"
  .gnugpl_window.textwin.gpltext insert end "excuse you from the conditions of this License.  If you cannot\n"
  .gnugpl_window.textwin.gpltext insert end "distribute so as to satisfy simultaneously your obligations under this\n"
  .gnugpl_window.textwin.gpltext insert end "License and any other pertinent obligations, then as a consequence you\n"
  .gnugpl_window.textwin.gpltext insert end "may not distribute the Program at all.  For example, if a patent\n"
  .gnugpl_window.textwin.gpltext insert end "license would not permit royalty-free redistribution of the Program by\n"
  .gnugpl_window.textwin.gpltext insert end "all those who receive copies directly or indirectly through you, then\n"
  .gnugpl_window.textwin.gpltext insert end "the only way you could satisfy both it and this License would be to\n"
  .gnugpl_window.textwin.gpltext insert end "refrain entirely from distribution of the Program.\n\n"
  .gnugpl_window.textwin.gpltext insert end "If any portion of this section is held invalid or unenforceable under\n"
  .gnugpl_window.textwin.gpltext insert end "any particular circumstance, the balance of the section is intended to\n"
  .gnugpl_window.textwin.gpltext insert end "apply and the section as a whole is intended to apply in other\n"
  .gnugpl_window.textwin.gpltext insert end "circumstances.\n\n"
  .gnugpl_window.textwin.gpltext insert end "It is not the purpose of this section to induce you to infringe any\n"
  .gnugpl_window.textwin.gpltext insert end "patents or other property right claims or to contest validity of any\n"
  .gnugpl_window.textwin.gpltext insert end "such claims; this section has the sole purpose of protecting the\n"
  .gnugpl_window.textwin.gpltext insert end "integrity of the free software distribution system, which is\n"
  .gnugpl_window.textwin.gpltext insert end "implemented by public license practices.  Many people have made\n"
  .gnugpl_window.textwin.gpltext insert end "generous contributions to the wide range of software distributed\n"
  .gnugpl_window.textwin.gpltext insert end "through that system in reliance on consistent application of that\n"
  .gnugpl_window.textwin.gpltext insert end "system; it is up to the author/donor to decide if he or she is willing\n"
  .gnugpl_window.textwin.gpltext insert end "to distribute software through any other system and a licensee cannot\n"
  .gnugpl_window.textwin.gpltext insert end "impose that choice.\n\n"
  .gnugpl_window.textwin.gpltext insert end "This section is intended to make thoroughly clear what is believed to\n"
  .gnugpl_window.textwin.gpltext insert end "be a consequence of the rest of this License.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  8. If the distribution and/or use of the Program is restricted in\n"
  .gnugpl_window.textwin.gpltext insert end "certain countries either by patents or by copyrighted interfaces, the\n"
  .gnugpl_window.textwin.gpltext insert end "original copyright holder who places the Program under this License\n"
  .gnugpl_window.textwin.gpltext insert end "may add an explicit geographical distribution limitation excluding\n"
  .gnugpl_window.textwin.gpltext insert end "those countries, so that distribution is permitted only in or among\n"
  .gnugpl_window.textwin.gpltext insert end "countries not thus excluded.  In such case, this License incorporates\n"
  .gnugpl_window.textwin.gpltext insert end "the limitation as if written in the body of this License.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  9. The Free Software Foundation may publish revised and/or new versions\n"
  .gnugpl_window.textwin.gpltext insert end "of the General Public License from time to time.  Such new versions will\n"
  .gnugpl_window.textwin.gpltext insert end "be similar in spirit to the present version, but may differ in detail to\n"
  .gnugpl_window.textwin.gpltext insert end "address new problems or concerns.\n\n"
  .gnugpl_window.textwin.gpltext insert end "Each version is given a distinguishing version number.  If the Program\n"
  .gnugpl_window.textwin.gpltext insert end "specifies a version number of this License which applies to it and \"any\n"
  .gnugpl_window.textwin.gpltext insert end "later version\", you have the option of following the terms and conditions\n"
  .gnugpl_window.textwin.gpltext insert end "either of that version or of any later version published by the Free\n"
  .gnugpl_window.textwin.gpltext insert end "Software Foundation.  If the Program does not specify a version number of\n"
  .gnugpl_window.textwin.gpltext insert end "this License, you may choose any version ever published by the Free Software\n"
  .gnugpl_window.textwin.gpltext insert end "Foundation.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  10. If you wish to incorporate parts of the Program into other free\n"
  .gnugpl_window.textwin.gpltext insert end "programs whose distribution conditions are different, write to the author\n"
  .gnugpl_window.textwin.gpltext insert end "to ask for permission.  For software which is copyrighted by the Free\n"
  .gnugpl_window.textwin.gpltext insert end "Software Foundation, write to the Free Software Foundation; we sometimes\n"
  .gnugpl_window.textwin.gpltext insert end "make exceptions for this.  Our decision will be guided by the two goals\n"
  .gnugpl_window.textwin.gpltext insert end "of preserving the free status of all derivatives of our free software and\n"
  .gnugpl_window.textwin.gpltext insert end "of promoting the sharing and reuse of software generally.\n\n"
  .gnugpl_window.textwin.gpltext insert end "                            NO WARRANTY\n\n"
  .gnugpl_window.textwin.gpltext insert end "  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
  .gnugpl_window.textwin.gpltext insert end "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
  .gnugpl_window.textwin.gpltext insert end "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
  .gnugpl_window.textwin.gpltext insert end "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
  .gnugpl_window.textwin.gpltext insert end "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
  .gnugpl_window.textwin.gpltext insert end "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
  .gnugpl_window.textwin.gpltext insert end "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
  .gnugpl_window.textwin.gpltext insert end "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
  .gnugpl_window.textwin.gpltext insert end "REPAIR OR CORRECTION.\n\n"
  .gnugpl_window.textwin.gpltext insert end "  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
  .gnugpl_window.textwin.gpltext insert end "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
  .gnugpl_window.textwin.gpltext insert end "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
  .gnugpl_window.textwin.gpltext insert end "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
  .gnugpl_window.textwin.gpltext insert end "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
  .gnugpl_window.textwin.gpltext insert end "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
  .gnugpl_window.textwin.gpltext insert end "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
  .gnugpl_window.textwin.gpltext insert end "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
  .gnugpl_window.textwin.gpltext insert end "POSSIBILITY OF SUCH DAMAGES.\n\n"
  .gnugpl_window.textwin.gpltext configure -state disabled
}
  

# Command line parms
#
proc CheckParameters {} {
  global argv own_WG
  if { [lindex $argv 0] != "" } {
    set wg_index [lsearch -exact $argv "--default-workgroup"]
    set wg_index2 [lsearch -exact $argv "-dwg"]
    set index -1
    if {$wg_index != -1} { set index $wg_index }
    if {$wg_index2 != -1} { set index $wg_index2 }
    if { $index != -1 } {
      set def_wg [lindex $argv [expr $index +1]]
      if { $def_wg != "" } {
          set own_WG [string toupper $def_wg]
        }
      }
    }
}


# Set savefile names
#
proc CheckUser {} {
  global program_user options_savefile passwords_savefile env
  set options_savefile "$env(HOME)/.xsmb.configuration"
  set passwords_savefile "$env(HOME)/.xsmb.passwords"
}


# Load configuration
#
proc LoadConfiguration {} {
  global options_savefile show_timestamp
  global show_license smb_timeout clientname save_pwd_file file_size_type
  global default_password use_default_password
  global confirm_quit use_master_ip
  global own_WG to_lowercase
  catch {
    set savefile [open $options_savefile r]
    while { ![eof $savefile] } {
      set sfi [gets $savefile]
      if { [lindex $sfi 0] == "license" } { set show_license [lindex $sfi 1] }
      if { [lindex $sfi 0] == "timeout" } { set smb_timeout [lindex $sfi 1] }
      if { [lindex $sfi 0] == "clientn" } { set clientname [lindex $sfi 1] }
      if { [lindex $sfi 0] == "savepwd" } { set save_pwd_file [lindex $sfi 1] }
      if { [lindex $sfi 0] == "filesiz" } { set file_size_type [lindex $sfi 1] }
      if { [lindex $sfi 0] == "shwtime" } { set show_timestamp [lindex $sfi 1] }
      if { [lindex $sfi 0] == "usedpwd" } { set use_default_password [lindex $sfi 1] }
      if { [lindex $sfi 0] == "defpass" } { set default_password [lindex $sfi 1] }
      if { [lindex $sfi 0] == "conquit" } { set confirm_quit [lindex $sfi 1] }
      if { [lindex $sfi 0] == "ownWG" } { set own_WG [lindex $sfi 1] }
      if { [lindex $sfi 0] == "usemip" } { set use_master_ip [lindex $sfi 1] }
      }
    close $savefile
  }
}


proc CheckLocalDirectory {} {
  global used_local_directory new_used_local_directory env
  set used_local_directory $env(HOME)
  .bottom.left.localdir.localdir insert 1 $used_local_directory
  #set new_used_local_directory $used_local_directory
  refresh_localdirwindow
}


# ===============================================================================

# Start here


draw_window
CheckUser
LoadConfiguration

# command line args
CheckParameters

.bottom.right.bottom.buttons.button_copy configure -state disabled
.bottom.right.bottom.buttons.button_delete configure -state disabled
.bottom.right.bottom.buttons.button_parent configure -state disabled
.bottom.right.bottom.buttons.mountbutton configure -state disabled
.bottom.right.bottom.buttons.button_umount configure -state disabled
.bottom.left.buttons.button_refresh configure -state disabled
.bottom.left.buttons.button_parent configure -state disabled
.bottom.left.buttons.button_copy configure -state disabled
.bottom.left.buttons.button_delete configure -state disabled
#.top.button_addwg configure -state disabled
#.top.button_help configure -state disabled
.top.button_file configure -state disabled

if { $show_license == "yes" } {
    .top.button_file configure -state disabled
    show_GNU_GPL
  } else {
    refresh_smbwindow ""
    CheckLocalDirectory
  }
