#
# A sysmon library in python
# Ryan Tucker <rtucker@ttgcitn.com>, 22May97
#

import socket
import string

# Exceptions raised when bad things happen.
error_bad = 'sysmonlib.error_bad'	# 444
error_proto = 'sysmonlib.error_proto'	# anything really whacked

# Port used by sysmond
sysmon_port = 1345

# carriage return/newline
CRLF = '\r\n'

class sysmon:

	# Initialize an instance.  Arguments:
	# host: Hostname
	# port: Port to connect to (default is standard port)
	def __init__(self, host, port = sysmon_port):
		self.host = host
		self.port = port
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.sock.connect(self.host, self.port)
		self.file = self.sock.makefile('rb')
		self.debugging = 0
		self.welcome = self.getresp()

	# Get response from server.  Stuffed by __init__().
	def getwelcome(self):
		if self.debugging: print '*welcome*', `self.welcome`
		return self.welcome

	# Set debugging level.
	# 0: no debugging, 1: print commands/responses, 2: print everything
	def set_debuglevel(self, level):
		self.debugging = level
	debug = set_debuglevel

	# Send one line to the server.  Append CRLF.
	def putline(self, line):
		line = line + CRLF
		if self.debugging > 1: print '*put*', `line`
		self.sock.send(line)

	# Send one command through putline.
	def putcmd(self, line):
		if self.debugging: print '*cmd*', `line`
		self.putline(line)

	# get a line from the server -- raise EOFError if connection closed
        def getline(self):
                line = self.file.readline()
                if self.debugging > 1:
                        print '*get*', `line`
                if not line: raise EOFError
                if line[-2:] == CRLF: line = line[:-2]
                elif line[-1:] in CRLF: line = line[:-1]
                return line

        # get a response from the server.
        # Raise various errors if the response indicates an error
        def getresp(self):
                resp = self.getline()
                if self.debugging: print '*resp*', `resp`
                c = resp[:1]
                if c == '4':
                        raise error_bad, resp
                if c not in '123':
                        raise error_proto, resp
                return resp

        # get a response plus following text from the server.
        # Raise various errors if the response indicates an error
        def getlongresp(self):
#                resp = self.getresp()
#                if resp[:3] not in LONGRESP:
#                        raise error_reply, resp
                list = []
                while 1:
                        line = self.getline()
                        if line == '333':
                                break
                        list.append(line)
                return list

        # send a command and get the response
        def shortcmd(self, line):
                self.putcmd(line)
                return self.getresp()

        # send a command and get the response plus following text
        def longcmd(self, line):
                self.putcmd(line)
                return self.getlongresp()

	# parse a STAT command
	# format: hostname:type:port:lastcheck:downct:contacted:deathtime
	# ex: crasher2:5:119:4:22:1:864282574
	def statparse(self, resp):
		outages = []
		for i in resp:
			parts = string.split(i, ':')
			outages.append(parts)
		return outages

	# process a STAT command
	def statcmd(self, line):
		resp = self.longcmd(line)
		return self.statparse(resp)

	# send a STAT command
	def stat(self):
		return self.statcmd('STAT')

	# process a QUIT command
	def quit(self):
		resp = self.shortcmd('QUIT')
		self.file.close()
		self.sock.close()
		del self.file, self.sock
		return resp
















