#!/bin/sh
# -*- mode: tcl -*-
# ALL the continued lines following this one are interpreted
# by the bourne shell and ignored by Tcl, which picks up
# execution after the exec line.\
exec `which tclsh` "$0" ${1+"$@"}

set ::ExitCode(OK)		0
set ::ExitCode(USER)		1
set ::ExitCode(NO_AGENT)	2

set ::LDAS_ROOT "/ldas"
set ::LDAS_OUTGOING_ROOT "/ldas_outgoing"
set SSH_AGENT_MGR "$::LDAS_ROOT/bin/ssh-agent-mgr"
set AGENT_FILE "${LDAS_OUTGOING_ROOT}/managerAPI/.ldas-agent"
set ::LDAS_PS ${::LDAS_ROOT}/bin/ldas-processes

if { [ file executable "[file dirname $argv0]/ssh-agent-mgr" ] } {
    set SSH_AGENT_MGR "[file dirname $argv0]/ssh-agent-mgr"
}

proc pute { ExitCode Message } {
    puts stderr $Message
    exit $ExitCode
}

proc NodeCompare { a b } {
    set asearch [ lindex $a 1 ]
    set bsearch [ lindex $b 1 ]
    set res [ string compare $asearch $bsearch ]
    if { $res != 0 } {
	return $res
    }
    set apid [ lindex $a 0 ]
    set bpid [ lindex $b 0 ]
    if { $apid == $bpid } {
	return 0
    } elseif { $apid < $bpid } {
	return -1
    }
    return 1
}

proc rps { Host User Processes } {
    set ssh_host ""
    set rsh_cmd ""
    if { [ llength $Host ] == 2 } {
	set ssh_host [ lindex $Host 0 ]
	set rsh_host [ lindex $Host 1 ]
    } else {
	set ssh_host [ lindex $Host 0 ]
	set rsh_host [ lindex $Host 0 ]
    }
    if { ! [ string match $ssh_host $rsh_host ] } {
	set rsh_cmd "rsh $rsh_host"
    }
    upvar $Processes retval
    if { [ info exists retval ] } {
	# Ensure we are always working with an empty list
	unset retval
    }
    if [ catch { set processes [ exec ssh $ssh_host $rsh_cmd ${::LDAS_PS} -o pid,user,args ] } err ] {
	# :TODO: Need to do something more intelligent than just return
	# :TODO:  an empty string
	puts stderr $err
	return ""
    }
    unset err
    set pattern {([^/]*/|)tclsh[ \t]}
    set test_scripts {(pipeloop|looptool)}
    foreach line [ split $processes '\n' ] {
	catch {
	    regexp {^[ \t]*([0-9]+)[ \t]+([A-Za-z0-9]+)[ \t]+(.*)$} $line -> \
		pid user cmd
	    if { $pid == [ pid ] } {
		# Exclude ourselves from the list
		continue
	    }
	    if { [ string match $User $::env(USER) ] } {
		# Processes to exclude as the 'ldas' user
		if { ! [ string match $User $user ] ||
		     [ regexp -- $test_scripts $line match ] } {
		    continue
		}
		set retval($pid) [ list $user $cmd ]
	    } else {
		# Processes to exclude as the 'search' user
		if { ! [ regexp $User $user match ] } {
		    continue
		}
		set retval($pid) [ list $user $cmd ]
	    }
	}
	if { [ info exists err ] } {
	    puts "DEBUG: err: $err"
	    unset err
	}
    }
}

#------------------------------------------------------------------------
# Make sure that this program is run by the owner of the AGENT file
# :TODO: Allow for other user than ldas
#------------------------------------------------------------------------
if { ! [ string match ldas $::env(USER) ] } {
	pute $::ExitCode(USER) "This program must be run as user 'ldas'"
}
#------------------------------------------------------------------------
# Get information about the the ssh-agent
#------------------------------------------------------------------------
if { [ catch {set ::agent_env [ exec $::SSH_AGENT_MGR --shell=tclsh --agent-file=$::AGENT_FILE check 2> /dev/null ] } err ] } {
    # Attempt to add keys to the agent
    if { [ catch {set ::agent_env [ exec $::SSH_AGENT_MGR --shell=tclsh --agent-file=$::AGENT_FILE addkeys 2> /dev/null ] } err ] } {
	# Attempt to start the agent
	if { [ catch {set ::agent_env [ exec $::SSH_AGENT_MGR --shell=tclsh --agent-file=$::AGENT_FILE restart 2> /dev/null ] } err ] } {
	    pute $::ExitCode(NO_AGENT) "Unable to connect to the ssh-agent"
	    exec $::SSH_AGENT_MGR --shell=tclsh --agent-file=$::AGENT_FILE stop 2> /dev/null
	}
    }
}
eval $::agent_env
#------------------------------------------------------------------------
# Check all hosts associated with the various APIs
#------------------------------------------------------------------------
source $LDAS_OUTGOING_ROOT/LDASapi.rsc
if { [ info exists ::Hosts ] } {
    unset ::Hosts
}
foreach api $::API_LIST {
    set api_name  "::[string toupper $api]_API_HOST"
    if { [info exists $::api_name] } {
	set ::Hosts([ set $api_name ]) [ set $api_name ]
    }
}
foreach host [ array names ::Hosts ] {
    puts "Querying: $host"
    rps $host $::env(USER) processes
    foreach cmd [ lsort -integer [ array names processes ] ] {
	puts [ format "%6d %-10s %s" $cmd \
		   [ lindex $processes($cmd) 0 ] \
		   [ lindex $processes($cmd) 1 ] ]
    }
}
#------------------------------------------------------------------------
# Check for processes started by search users
#------------------------------------------------------------------------
if { [expr [lsearch -exact $::API_LIST mpi ] >= 0] \
	 && [info exists ::MPI_API_HOST] } {
    source $LDAS_OUTGOING_ROOT/mpiAPI/LDASmpi.rsc
    if { [ info exists ::NODENAMES ] } {
	foreach node $::NODENAMES {
	    set node_list($node) $node
	}
	foreach node [ lsort [ array names ::node_list ] ] {
	    puts "Querying Node: $node"
	    rps [ list $::MPI_API_HOST $node ] search processes
	    set node_ps [ list ]
	    foreach cmd [ array names processes ] {
		lappend node_ps [ concat $cmd $processes($cmd) ]
	    }
	    set node_ps [ lsort -command NodeCompare $node_ps ]
	    foreach cmd $node_ps {
		puts [ format "%6d %-10s %s" \
			   [ lindex $cmd 0 ] [ lindex $cmd 1 ] [ lindex $cmd 2 ] ]
	    }
	}
    }
} ;# if [info exists MPI_API_HOST]
