#
# <20190623.1242.23>
#
# Here we effort to find all the possible UNC connections in Xnix
#
# Return is a list of connections
#
#
# Note there is a *nix and a Windows version of this code.  The difference
# in the call being only in the name of the namespace. Of course the internals
# differ, else why have two.

# For what its worth, I have not found a reliable way to enumerate the servers
# on a network, especially now that the "browser" of SMB1 is deprecated.
# What we are going to do is enumberate the shares that the user has already
# configured his system to use. To do this we scan the "mtab", "fstab", and
# "autofs" tables looking for these. This is relatively fast so we can do it
# whenever. Found entries are put in the "passwordLocker" and that is to be
# scanned (by visting "volume") more often.

namespace eval findUNC {

  # here are some helpers for below
  
  # ipToNetBios takes an ip address and translates it to the NetBios name
  # but only if there is one. Otherwise, it returns nil i.e. {}
  # We use "nbtstat" to do the translation. This, of course, polls the owner
  # so this could take a while, especially if the device is offline or not
  # a NetBios server.
  # Most of the work here is decoding the returned info.
  
  # proc ipToNetBios {ip} {
  #   set raw [asyncExec nbtstat -A $ip]
  #   if {[regexp {\n([^<]*)<20>.*} $raw m name]} {
  #     return [string trim $name]
  #   }
  #   return {}
  # }

  proc fileNameGetParm {key string {noneIsM1 0}} {
    set st [split $string ,]
    set ind [lsearch -regexp $st "^${key}($|=.*)"]
    if {$ind < 0} {return [expr {$noneIsM1 ? -1 : {}}]}
    lassign [split [lindex $st $ind] =] nkey val
    return $val
  }
  proc getUandP {} {
    uplevel {
      set foundUser [fileNameGetParm "username" $foundOpts]
      set foundPw   [fileNameGetParm "password" $foundOpts]
      if {$foundUser != {}} {
	set cuser $foundUser
      }
      if {$cuser != {}} {
	set add $cuser@$add
      }
      if {$foundPw != {}} {
	# Lets trust the found password more than the one from our
	# tables...
	incr openPassword
	set pw $foundPw
      }
    }
  }
  # First we enumerate all we can find about CIFS files...
  proc enumCIFS {} {
    #return {}
    global config
    set openPassword 0
    set auto {}
    foreach file {/etc/mtab /etc/fstab} {
      set loc [file tail $file]
      set $loc {}
      if {[file readable $file]} {
	file stat $file what
	# we don't want to try to figure an executable and
	# 'file executable' only tells us if 'we' can execute it
	# oct 111 checks all three executable bits
	if {($what(mode) & "0x111") == 0} {
	  set $loc [split [read [open $file r]] \n]
	}
      array unset what
      }
    }
    set clist [concat $fstab $mtab]
    # we grab the autofs file name from mtab, we even allow for more than one
    set ent [lsearch -glob -all $mtab "*autofs*"]
    foreach idx $ent {
      set id [lindex $mtab $idx 0] 
      if {[file readable $id]} {
	set auto [concat $auto [split [read [open $id r]] \n]]
      }
    }
    set Ents [set result {}]
    # now build two lists, cifs and nfs mounts (nfs so we can share this code
    # with those that want that info as well...
    set combine [concat $fstab $mtab]
    foreach ent $combine {
      set ent [string trim $ent]
      if {[string index $ent 0] != "#" && [lindex $ent 2] in {cifs nfs}} {
	lappend Ents $ent
      }
    }
    # the autofs entries are a tad different, lets fix that...
    
    foreach autoEnt $auto {
      set autoEnt [string trim $autoEnt]
      if {[string index $autoEnt 0] in {\# {}} } {continue}
      frputs autoEnt
      lassign $autoEnt mp foundOpts location
      set foundType [fileNameGetParm "-fstype" $foundOpts]
      if {$foundType ni {nfs cifs}} {continue}
      lappend Ents [list [string range $location 1 end] $mp $foundType $foundOpts]
    }
    # Now we weed out the dups, and, possibly pick up more info on each
    # In the process we will build an nfs or a cifs url
    set foundPws 0
    frputs Ents' config(passwordLocker)'
    foreach ent $Ents {
      lassign $ent add mp type foundOpts
      set add [regsub {^//} $add {}]
      # This fixes nfs addresses to URL specs.
      set add [regsub {:} $add {/}]
      lassign [split $add @] cuser add
      if {$add == {}} {
	set add $cuser
	set cuser $::env(USER)
      }
      getUandP
      set id ${type}://$add
      set entH [lsearch -exact -index 0 $config(passwordLocker) $id]
      set ext [lassign [lindex $config(passwordLocker) $entH] idH pwH mpH]
      frputs id entH
      # if any of this is new, add it to the "passwordLocker"
      set config(passwordLocker) [lreplace $config(passwordLocker) \
				      $entH $entH \
				      [list $id \
					   [expr {$foundPw == {} ? $pwH : $foundPw}]\
					   $mp {*}$ext]]
    }
    return $openPassword
  }   
}

  
