#!/usr/local/bin/tclsh
global env gv

if {![info exists env(ECLIPSE)]} {
	if {[file exists $env(HOME)/ECLIPSE]} {
		set env(ECLIPSE) $env(HOME)/ECLIPSE
	} elseif {[file exists /opt/ECLIPSE]} {
		set env(ECLIPSE) /opt/ECLIPSE
	} elseif {[file exists /apps/ECLIPSE]} {
		set env(ECLIPSE) /apps/ECLIPSE
	} elseif {[file exists /usr/local/ECLIPSE]} {
		set env(ECLIPSE) /usr/local/ECLIPSE
	} else {
		puts stdout "Please define the ECLIPSE environment variable"
		exit 1
	}
}

##### Find the OS we are running under
if {![info exists env(OS)]} {
	if {$tcl_platform(os)=="SunOS"} {
		if {[lindex [split $tcl_platform(osVersion) "."] 0]==4} {
			set env(OS) SunOS
		} else {
			set env(OS) SOLARIS
		}
	} elseif {$tcl_platform(os)=="AIX"} {
		catch {exec uname -v} res
		if {[lindex [split $res] 0]=="4"} {
			set env(OS) AIX4
		} else {
			set env(OS) AIX
		}
	} else {
		set env(OS) $tcl_platform(os)
	}
}

############################################################################
#	Procedures
############################################################################

proc sendstat { message } {
	global env gv

	foreach line $gv(monitors) {
		set host [lindex $line 0]
		set port [lindex $line 1]
		puts -nonewline stdout "Sending to $host on port $port ... "
		if {[catch {socket $host $port} fp]} {
			catch {exec logger -t ECLIPSE -p daemon.warning Could not contact $host on port $port} junk
			puts stdout "FAILED"
			continue
		}

		fconfigure $fp -buffering line
		puts $fp $message
		catch "close $fp" junk

		puts stdout "OK"
	}

	return
}

proc fileage { field value args } {
	global env gv

	if {$field!="atime" && $field!="ctime" && $field!="mtime"} {
		return [list ERROR "Invalid field specified"]
	}
	regsub -all {[^0-9]} $value {} value
	if {$value==""} {return [list ERROR "No value specified"]}
	if {[llength $args]<1} {return [list ERROR "No file spec specified"]}

	set now [clock seconds]
	set total 0
	foreach arg $args {
		foreach file [glob -nocomplain $arg] {
			if {[catch {file stat $file statvar} res]} {continue}
			if {$field=="atime"} {
				set temp [expr $now - $statvar(atime)]
			} elseif {$field=="ctime"} {
				set temp [expr $now - $statvar(ctime)]
			} else {
				set temp [expr $now - $statvar(atime)]
			}
			if {$temp>=$value} {incr total}
		}
	}
	return $total
}

proc filecount { args } {
	global env gv

	if {[llength $args]<1} {return [list ERROR "Blank file spec"]}

	set total 0
	foreach arg $args {
		set total [expr $total + [llength [glob -nocomplain $arg]]]
	}
	return $total
}

proc diskfree { {dir ""} } {
	global env gv

	if {$dir==""} {return [list ERROR "Blank directory"]}

	if {$env(OS)=="AIX"} {
		if {[catch {exec df $dir | tail -1} res]} {return [list ERROR $res]}
		return [lindex $res 2]
	} elseif {$env(OS)=="AIX4"} {
		if {[catch {exec df -k $dir | tail -1} res]} {return [list ERROR $res]}
		return [lindex $res 2]
	} elseif {$env(OS)=="SunOS"} {
		if {[catch {exec df $dir | tail -1} res]} {return [list ERROR $res]}
		return [lindex $res 3]
	} else {
		if {[catch {exec df -k $dir | tail -1} res]} {return [list ERROR $res]}
		return [lindex $res 3]
	}
}

proc uptime { {field ""} } {
	global env gv

	if {$field==""} {return [list ERROR "Blank field"]}

	if {[catch {exec uptime} res]} {
		return [list ERROR $res]
	}
	set res [join [lrange [split $res ","] 2 end]]
	regsub -all {[^.0-9]} $res { } res

	if {$field=="users"} {
		return [lindex $res 0]
	} elseif {$field=="cpu5"} {
		return [lindex $res 1]
	} elseif {$field=="cpu10"} {
		return [lindex $res 2]
	} elseif {$field=="cpu15"} {
		return [lindex $res 3]
	} else {
		return [list ERROR "Invalid field $field"]
	}
}

proc ping { host {nping 1} } {
	global env gv

	regsub -all {[^0-9]} $nping {} nping
	if {$nping=="" || $nping<1} {set nping 1}

	if {$env(OS)=="SunOS" || $env(OS)=="SOLARIS"} {
		catch {exec ping -s $host 64 $nping} res
	} else {
		catch {exec ping -c $nping $host} res
	}
	set value ERROR
	regexp {([0-9+]) packets received} $res trash value
	return $value
}

proc connect { port args } {
	global env gv

	if {$port==""} {return [list ERROR "Port number missing"]}
	if {[llength $args]<1} {return [list ERROR "No hosts specified"]}

	set total 0
	foreach host $args {
		if {![catch {socket $host $port} fp]} {
			close $fp
			incr total
		}
	}
	return $total
}

proc processlist { } {
	global env gv

	if {$env(OS)=="SOLARIS"} {
		if {[catch {exec /usr/ucb/ps ax} res]} {return [list ERROR $res]}
	} elseif {$env(OS)=="Linux"} {
		if {[catch {exec /bin/ps ax} res]} {return [list ERROR $res]}
	} else {
		if {[catch {exec /usr/bin/ps ax} res]} {return [list ERROR $res]}
	}

	regsub -all {[ 	]+} $res { } res

	foreach name [array names gv process:*] {unset $gv($name)}

	set res [split $res "\n"]
	set i 0
	foreach line $res {
		set fields [string trim [split $line]]
		if {[lindex $fields 0]=="PID"} {continue}
		set gv(process:$i) [join [lrange $fields 4 end]]
		incr i
	}
	set gv(processcount) $i
	return $gv(processcount)
}

proc process { {name ""} } {
	global env gv

	if {$name==""} {return [list ERROR "Blank process name"]}

	set total 0
	for {set i 0} {$i<$gv(processcount)} {incr i} {
		if {[regexp $name $gv(process:$i)]} { incr total }
	}
	return $total
}

proc printcheck { {queue ""} } {
	global env gv

	if {$env(OS)=="SunOS"} {
		if {$queue==""} {
			if {[catch {exec lpc stat} res]} {return [list ERROR $res]}
		} else {
			if {[catch {exec lpc stat $queue} res]} {return [list ERROR $res]}
		}
	} elseif {$env(OS)=="AIX" || $env(OS)=="AIX4"} {
		if {$queue==""} {
			if {[catch {exec lpstat | tail +3} res]} {return [list ERROR $res]}
			foreach line [split $res "\n"] {
				if {[string trim $line]==""} {continue}
			}
		} else {
			if {[catch {exec lpstat -p$queue | tail +3} res]} {return [list ERROR $res]}
			foreach line [split $res "\n"] {
				if {[string trim $line]==""} {continue}
			}
		}
	}
	return
}

##########################################################################
#	Main Program
##########################################################################

set gv(client)	[string tolower [info hostname]]
set gv(client.short)	[string tolower [lindex [split [info hostname] "."] 0]]
set gv(commandlist) [list fileage filecount diskfree uptime process connect ping]
set gv(complist) [list "=" "!=" "<" ">" "<=" ">="]


#
#	Default the stuff that must be in the config file
#
set gv(monitors)	{}
set gv(monitor)		{}

set configfile [lindex $argv 0]
if {"x$configfile"!="x" && [file exists $configfile]} {
	source $configfile
} elseif {[file exists /etc/eclipse.conf]} {
	source /etc/eclipse.conf
} elseif {[file exists $env(ECLIPSE)/etc/config.$gv(client)]} {
	source $env(ECLIPSE)/etc/config.$gv(client)
} elseif {[file exists $env(ECLIPSE)/etc/config.$gv(client.short)]} {
	source $env(ECLIPSE)/etc/config.$gv(client.short)
} elseif {[file exists $env(ECLIPSE)/etc/config]} {
	source $env(ECLIPSE)/etc/config
} else {
	puts stdout "Could not find a config file"
	exit 1
}

if {[llength $gv(monitors)]<1} {
	puts stdout "No servers defined...please check the config file"
	exit 1
}

if {[llength $gv(monitor)]<1} {
	puts stdout "Nothing to monitor...please check the config file"
	exit 1
}

if {[lindex [processlist] 0]=="ERROR"} {
	puts stdout "Could not generate process listing"
	exit 1
}

set message {}
foreach line $gv(monitor) {
	set label [lindex $line 0]
	set command [lindex $line 1]
	set helpurl [lindex $line 2]
	set comname [lindex [split $command] 0]
	if {[lsearch $gv(commandlist) $comname]<0} {
		set alarm "ERROR"
		set result "Invalid command"
	} else {
		if {[catch {eval $command} res]} {
			set alarm "ERROR"
		} elseif {[lindex $res 0]=="ERROR"} {
			set alarm "ERROR"
			set result [lindex $res 1]
		} else {
			set result [lindex $res 0]
			set alarm "green"
			foreach field [lrange $line 3 end] {
				set color [lindex $field 0]
				set comp [lindex $field 1]
				if {[lsearch $gv(complist) $comp]<0} {
					set alarm "ERROR"
					set result "Invalid comparasin operator"
					break
				}
				set value [string trim [lindex $field 2]]
				if {$comp=="=" && $result==$value} {
					set alarm $color
				} elseif {$comp=="!=" && $result!=$value} {
					set alarm $color
				} elseif {$comp=="<" && $result<$value} {
					set alarm $color
				} elseif {$comp==">" && $result>$value} {
					set alarm $color
				} elseif {$comp=="<=" && $result<=$value} {
					set alarm $color
				} elseif {$comp==">=" && $result>=$value} {
					set alarm $color
				}
			}
		}
	}
	puts stdout "$alarm - $label ( $command = $result )"
	set output [list $gv(client) [clock seconds] $alarm $label $command $result]
	foreach field [lrange $line 2 end] {lappend output $field}
	lappend message $output
}

sendstat $message

exit 0
