#!/bin/sh
#\
#exec wish "$0" "$@"

# Copyright (C) 2001 MBARI
# Author: Kent Headley
# MBARI provides this documentation and code "as is", with no warranty,
# express or implied, of its quality or consistency. It is provided without
# support and without obligation on the part of the Monterey Bay Aquarium
# Research Institute to assist in its use, correction, modification, or
# enhancement. This information should not be published or distributed to
# third parties without specific written permission from MBARI.
#
# tinySvr.tcl
# Listens for connections on port 8004 (by default)
# Accepts commands to update data display
# Reports success/failure
#

set Revision(tinySvr) {$RCSfile: oasiss.tcl,v $ $Revision: 1.1 $}

###########################################################################
# serverOpen {channel addr port} --
#  This is called when the server receives a connection request.
# Arguments:
#     channel:	The channel identifier assigned to the new socket 
#                 connection
# 	addr:		The IP address of the system that requested the
#			connection
#	port:		The socket port assigned to the new connection.
#
# Results:
#	Sets a fileevent to be entered when input becomes available 
#	on the channel.
#
#     no Return value.
# 

proc serverOpen {channel addr port} {
    catch {
	global sock
	#puts "channel: $channel - from Address: $addr  Port: $port"

	set sock $channel
    }
}

###########################################################################
# sendPrompt {channel} --
# Sends a prompt to a channel.
# Arguments:
#	channel:	The channel for output
#
# Results:
#	A prompt is sent to the output channel.  
#	Errors are ignored.

proc sendPrompt {channel} {
    catch {
	puts $channel "tinySvr OK"
	flush $channel
    }
}

###########################################################################
# sendLine {channel text} --
# Sends a prompt to a channel.
# Arguments:
#	channel:	The channel for output
#	text:		The data to transmit.
#
# Results:
#	A string is sent to the output channel.  
#	Errors are ignored.

proc sendLine {channel text} {
    catch {
	puts $channel $text
	flush $channel

    }
}


###########################################################################
# savevalues {} --
#   Saves the contents of the variable values.
#   
# Arguments:
#	*none*
# Results:
#	A file "values.tcl" is created.
#
#	File creation errors are reported on stdout, but not reported
#	to the calling routine.
#
proc savevalues {} {
    global values errorInfo

    set fail [catch {open "values.tcl" "w"} outfl]
    if {$fail} {
	puts "FAILED TO OPEN values.tcl."
	puts "$outfl"
	puts "$errorInfo"
	return

    }

    foreach name [array names values] {
	puts $outfl "set values($name) $values($name)"
    }

    close $outfl
}

###########################################################################
# Mainline Code starts here.
#

puts "\n\nOASIS Monitor server launched [clock format [clock seconds]]\n"

set svrPort 8004

#
# Set up a server to listen on port svrPort 
#

set svrSock [socket -server serverOpen $svrPort]

#
# Set done flag to not done, loop on this, to be set when an 
#   "exit" command is received.
#

set done 0

#
# Loop until an EXIT command is received.
#
while {!$done} {

    #
    # Wait for a socket connection
    #
    set sock o
    vwait sock

    # A socket connection has been made.  

    #
    # Read commands until the socket is closed.
    #
       while {![eof $sock]} {
	sendPrompt $sock
	set catchme [catch {set len [gets $sock inputLine]}]
	if {$catchme != 0} {break}	
	#
	# The TCL socket sends carriage-return/line feed pair at the 
	# end of a line, but reads either a <CR> or <NL> as a line terminator, 
	# leaving an empty line to be read on the next read.  If this line is
	# empty, just discard it, and continue.
	#
	if {$len <= 2} {
	    continue
	}

	#
	# Input has been received.  Display the time and input line
	#  for debugging and tracking purposes.
	#
	#puts "[clock format [clock seconds]]: $inputLine"
	puts "[clock format [clock seconds]]"

	#
	# Convert to a list for simple parsing.
	#
	set inputLst [split $inputLine ","]
	set cmd [string tolower [lindex $inputLst 0]]

	#
	# Assume success
	#

	set fail 0

	#
	# parse the command
	#

	#
	# Check that there is something close to the proper number
	#   of fields.
	# All commands except "Exit" take more than 3 arguments.
	# 
	if {[llength $inputLst] >= 3} {
	    set type [string tolower [lindex $inputLst 1]]
	    set cardno [lindex $inputLst 2]
	    set ioPort [lindex $inputLst 3]
	} {
	    if {[string match "exit" $cmd]} {
		set done 1
		break
	    } {
		set type "Error"
		set cardno ""
		set ioPort ""
		set fail 1

	    }
	}

	#
	# If fail is still 0, then we've got a mostly correct command.
	# Parse the command field, and call the appropriate subcommand.
	#
	if {!$fail} {
	    switch [lindex $inputLst 0] {
	    "status" {
		puts "received status"
		}
	    "display" {
		puts "received display"
		}
	    "exec" {
		puts ""
                puts [eval exec $type]
		puts ""
		}

	    default {
		    # Unrecognized command.
		puts "received unknown command"
		    set fail 9
		}
	    }
	}

	if {$fail} {
	    puts "FAIL: $fail"
	    if {[info exists err]} {
		puts "ERR: $err"
		set err [lindex [split $err] 2]
	    } {
		set err $fail
	    }
	    set output "fail,$cmd,$err"
	} {
	    set output "reply,$cmd"
	}

	sendLine $sock $output
    }
    #
    # The conversation is done, close the socket.
    #
    close $sock

}
#
# We got an exit command, close the server and quit
close $svrSock
exit
