#!/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 tclsh $0 ${1+"$@"}

set ::ExitCode(OK)                     0
set ::ExitCode(USAGE)                  1
set ::ExitCode(SHORT)                  2
set ::ExitCode(LDCG_CONFIG)            3
set ::ExitCode(LDAS_OUTGOING)          4
set ::ExitCode(INVALID_PROGRAM)        5
set ::ExitCode(NO_AGENT)               6
set ::ExitCode(STARTUP)                7
set ::ExitCode(MANAGER_RUNNING)        8
set ::ExitCode(ROOT_PRIV)              9
set ::ExitCode(NO_MANAGER_PID)        10
set ::ExitCode(MANAGER_ON_WRONG_HOST) 11

set ::LDCG_ROOT /ldas
set ::LDAS_ROOT /ldas
set ::LDAS_OUTGOING_ROOT /ldas_outgoing
set ::TOP           $::LDAS_OUTGOING_ROOT/managerAPI
set ::SSH_AGENT_MGR $::LDAS_ROOT/bin/ssh-agent-mgr
set ::AGENT_FILE    $::LDAS_OUTGOING_ROOT/managerAPI/.ldas-agent

if { [info exists ::env(SMF_FMRI)] } {
    # Started by Solaris' Service Management Facility
    set ::SMF 1
} else {
    set ::SMF 0
}
proc Usage { } {
    puts stderr "Usage: runLDAS <key>"
    exit $::ExitCode(USAGE)
}

proc puterr { ExitCode Message } {
    puts stderr "runLDAS: $Message"
    exit $ExitCode
}

proc source_rsc { Resources } {
     foreach file $Resources {
        if { [ file exists $::LDAS_OUTGOING_ROOT/$file ] } {
           source $::LDAS_OUTGOING_ROOT/$file
        } elseif { [ file exists $::LDAS_ROOT/$file ] } {
           source $::LDAS_ROOT/$file
        }
     }   
}

proc attach_to_agent { args } {
    set agent $::SSH_AGENT_MGR
    set agent_opts "--shell=tclsh --agent-file=$::AGENT_FILE"
    set command "$agent $agent_opts \$action 2> /dev/null"
    set action check
    if { [ catch {   
        set agent_env [ eval exec [subst $command] ]
    } err ] } {
	# Try just adding keys
	set action addkeys
        if { [ catch {
	    set agent_env [ eval exec [subst $command] ]
        } err ] } {
	    set action restart
	    # Attempt to start the agent
	    if { [ catch {
		set agent_env [ eval exec [subst $command] ]
	    } err ] } {
		set action stop
		eval exec [subst $command]
		set err "Unable to connect to the ssh-agent"
		puterr $::ExitCode(NO_AGENT) $err
	    }
	}
    }
    eval $agent_env
}

proc get_manager_pid { args } {
     foreach line [ split [ exec /bin/ps -Ao pid,fname ] '\n' ] {
        if { [ regexp {managerA} $line match ] } {
	      if { [ info exists manager_pid ] } {
	         if { [ lindex $line 0 ] < $manager_pid } {
		       set manager_pid [ lindex $line 0 ]
	         }
	      } else {
	         set manager_pid [ lindex $line 0 ]
	      }
        }
     }

     if { ! [ info exists manager_pid ] } {
	 set err "Unable to determine manager pid, check manager log"
	 puterr $::ExitCode(NO_MANAGER_PID) $err
     }

     puts stderr "runLDAS: manager pid is $manager_pid"
}

proc validate_host { args } {
    #--------------------------------------------------------------------
    # Make sure the host for the mananager api has been declared
    #--------------------------------------------------------------------
    if { ! [ info exists ::MANAGER_API_HOST ] } {
	puterr $::ExitCode(MANAGER_ON_WRONG_HOST) "::MANAGER_API_HOST is unset"
    }
    #--------------------------------------------------------------------
    # Gather information about the network devices connected to ths host
    #--------------------------------------------------------------------
    if { [ catch {
        set interfaces [ list ]
        if { [ file executable /usr/sbin/ifconfig ] } {
	    catch { ::exec /usr/sbin/ifconfig -a } data
        } elseif { [ file executable /sbin/ifconfig ] } {
	    catch { ::exec /sbin/ifconfig -a } data
        } else {
	    return -code error "can't find 'ifconfig' executable!"
        }
        set fid [ open /etc/hosts r ]
        set hostdata [ read $fid [ file size /etc/hosts ] ]
        ::close $fid
        foreach line [ split $hostdata "\n" ] {
	    array set hosts \
		[ list [ lindex $line 0 ] [ lrange $line 1 end ] ]
        }   
        foreach line [ split $data "\n" ] {
	    regexp {^(lo |[a-z]+\d+)} $line -> if
	    set if [ string trim $if ]
	    if { [ regexp {^\s+inet\s+(?:addr:)?(\S+)} $line -> ip ] } {
		if { [ info exists hosts($ip) ] } {
		    lappend interfaces [ list $if $ip $hosts($ip) ]
		} else {
		    lappend interfaces [ list $if $ip dhcp ]
		}
	    }
        }
    } err ] } {
	puterr $::ExitCode(MANAGER_ON_WRONG_HOST) $err
    }
    #--------------------------------------------------------------------
    # Search network devices for one that is ::MANAGER_API_HOST
    #--------------------------------------------------------------------
    foreach interface $interfaces {
	foreach [ list iname ip aliases ] $interface { break }
	foreach alias $aliases {
	    if { [ string match $alias $::MANAGER_API_HOST ] } {
		#--------------------------------------------------------
		# Leave since an interface has been found
		#--------------------------------------------------------
		return
	    }
	}
    }
    #--------------------------------------------------------------------
    # Did not find host
    #--------------------------------------------------------------------
    puterr $::ExitCode(MANAGER_ON_WRONG_HOST) "This host has no interface known as $::MANAGER_API_HOST"
}

#------------------------------------------------------------------------
# This script will start LDAS
#------------------------------------------------------------------------
if { [ llength $argv ] != 1 } { Usage }

if { [ string length [ lindex $argv 0 ] ] < 3 } {
    set err "Manager key must be at least 3 characters"
    puterr $::ExitCode(SHORT) $err
}

#------------------------------------------------------------------------
# Check for $::LDAS_OUTGOING_ROOT
#------------------------------------------------------------------------
if { ! [ file isdirectory $::LDAS_OUTGOING_ROOT ] } {
   set err "LDAS runtime home directory $::LDAS_OUTGOING_ROOT"
   append err " does not exist!!"
   puterr $::ExitCode(LDAS_OUTGOING_ROOT) $err        
}

#------------------------------------------------------------------------
# Check the LDCG_ROOT installation
#------------------------------------------------------------------------
if { ! [ file isdirectory $LDCG_ROOT ]     || \
     ! [ file isdirectory $LDCG_ROOT/bin ] || \
     ! [ file isdirectory $LDCG_ROOT/lib ] } {
    puts "$LDCG_ROOT is not properly configured."
    puts "$LDCG_ROOT should contain third-party software"
    puts "required to build and run LDAS."
    exit $::ExitCode(LDCG_CONFIG)
}

#------------------------------------------------------------------------
# Check priveleges
#------------------------------------------------------------------------
if { [ regexp {root} [ exec id 2> /dev/null ] match ] } {
    set err "LDAS should NEVER be run with root privileges."
    puterr $::ExitCode(ROOT_PRIV) $err
}

#------------------------------------------------------------------------
# Attach to an ssh shell
#------------------------------------------------------------------------
if { ! $::SMF } {
    attach_to_agent
}

#------------------------------------------------------------------------
# Check for lock files
#------------------------------------------------------------------------
foreach line [ exec /bin/ls -a $::TOP ] {
    set lock_pat {^\.manager\.([0-9]+)\.lock$} 
    if { [ regexp $lock_pat $line -> ::LOCKPID ] } {
	set ::LOCK $line
	break
    }
}

if { [ info exists ::LOCK ] } {
    #--------------------------------------------------------------------
    # Check if a process with the pid is running
    #--------------------------------------------------------------------
    if { ! [ catch {
       exec kill -0 $::LOCKPID >>& /dev/null
    } err ] } {
        set err "Manager API lock file exists ($::TOP/${::LOCK})."
        puterr $::ExitCode(MANAGER_RUNNING) $err 
    }
    #--------------------------------------------------------------------
    # Remove the lock file since there is no process
    #--------------------------------------------------------------------
    file delete -force $::TOP/$LOCK
}

#------------------------------------------------------------------------
# Find a working nohup
#------------------------------------------------------------------------
foreach nohup { /bin/nohup /usr/bin/nohup } {
    if { [ file executable $nohup ] } {
	set ::NOHUP $nohup
	break
    }
}
if { ! [ info exist ::NOHUP ] } {
    set err "Unable to find a usable nohup program"
    puterr $::ExitCode(INVALID_PROGRAM) $err
}

#------------------------------------------------------------------------
# Source in Resource variables
#------------------------------------------------------------------------
source_rsc [ list bin/LDASapi.rsc LDASapi.rsc managerAPI/LDASmanager.rsc ]

validate_host
#------------------------------------------------------------------------
# Log the KEY where the managerAPI will pick it up and remove the
#   file
#------------------------------------------------------------------------
cd $::TOP
set    fid [ open ".. " w   ]
puts  $fid [ lindex $argv 0 ]
close $fid

#------------------------------------------------------------------------
# Start the managerAPI
#------------------------------------------------------------------------
if { ! [ info exists ::EXTRA_ENV ] } {
    set ::EXTRA_ENV [ list ]
}
puts "DEBUG: EXTRA_ENV: $EXTRA_ENV"
if { ! [ info exists ::GLOBUS_LOCATION ] } {
    set ::GLOBUS_LIB  [ list ]
} else {
    set ::GLOBUS_LIB "$::GLOBUS_LOCATION/lib"
    set env(GLOBUS_LOCATION) $::GLOBUS_LOCATION
}

if { [ info exists ::LD_LIBRARY_PATH ] } {
    set ::LD_LIBRARY_PATH $::LD_LIBRARY_PATH:$::LDAS_ROOT/lib:$::LDCG_ROOT/lib:$::GLOBUS_LIB
} else {
    set ::LD_LIBRARY_PATH $::LDAS_ROOT/lib:$::LDCG_ROOT/lib:$::GLOBUS_LIB
}

set cmd "exec /usr/bin/env \
    LD_LIBRARY_PATH=$::LD_LIBRARY_PATH \
    PATH=$::LDAS_ROOT/bin:$::LDCG_ROOT/bin:/bin:/usr/bin \
    RUNDIR=$::LDAS_OUTGOING_ROOT \
    HOST=$::MANAGER_API_HOST"
regsub -all -- {\$} $::EXTRA_ENV {\\\\\$} ::EXTRA_ENV
foreach ev $::EXTRA_ENV {
    switch -regexp -- $ev {
        {[$].} { }
        {.*}   { append cmd " $ev" }
    }
}

;## support ::LD_PRELOAD_64 for 64 bit tclglobus
if { ! [ info exists ::LD_PRELOAD_64 ] } {
    set ::LD_PRELOAD_64  [ list ]
} else {
    set new_ld_preload [ list ]
    foreach file $::LD_PRELOAD_64 {
	if { ! [ file exist $file ] } {
	    puts "removing file $file from LD_PRELOAD_64($::LD_PRELOAD_64)"
	} else {
	    lappend new_ld_preload $file
	}
    }
    set ::LD_PRELOAD_64 $new_ld_preload
}

append cmd " \"LD_PRELOAD_64=$::LD_PRELOAD_64\"" 
append cmd " $::NOHUP managerAPI >& manager.log"
if { ! $::SMF } {
    append cmd " &"
}
puts $cmd
if { [ catch { eval $cmd } err ] } {
    set err "Unable to start managerAPI: $err"
    puterr $::ExitCode(STARTUP) $err
}

#------------------------------------------------------------------------
# Give it some time to start, and get the manager's process i.d.
#------------------------------------------------------------------------
after 2000
get_manager_pid
exit 0
