misc foo
[zanchey/dispense2.git] / sql-edition / servers / LATClient.py
1 from socket import *
2 from select import select
3 from os import popen4
4 from time import sleep
5
6 LATCP_SOCKET = '/var/run/latlogin'
7
8 LAT_VERSION = '1.21'
9 LATCP_CMD_VERSION = 8
10 LATCP_CMD_TERMINALSESSION = 26
11 LATCP_CMD_ERRORMSG = 99
12
13 class LATClientException(Exception): pass
14
15 def read_for_a_bit(rfh):
16         message = ''
17         while 1:
18                 r = select([rfh], [], [], 5.0)[0]
19                 if r:
20                         message = message + rfh.read(1)
21                 else:
22                         break
23         print "Received message: ", repr(message)
24         return message
25
26 def write_expecting_echo(rfh, wfh, message):
27         print "Writing message:", repr(message)
28         while len(message) > 0:
29                 wfh.write(message[0])
30                 wfh.flush()
31                 echo = rfh.read(1)
32                 if echo != message[0]:
33                         print "Gah, expected echo when writing", message[0]
34                 message = message[1:]
35         print "  --> Sent and echoed."
36
37 class LATClient:
38         def __init__(self, service = None, node = None, port = None,
39                      localport = None, password = None, is_queued = False,
40                      server_name = '', connect_password='', priv_password=''):
41
42                 self.server_name = server_name
43                 self.connect_password = connect_password
44                 self.priv_password = priv_password
45                 
46                 self.sock = socket(AF_UNIX, SOCK_STREAM, 0);
47                 self.sock.connect(LATCP_SOCKET)
48                 self.send_msg(LATCP_CMD_VERSION, LAT_VERSION+'\000')
49                 (cmd, msg) = self.read_reply()
50                 if service == None: service = ''
51                 if node == None: node = ''
52                 if port == None: port = ''
53                 if localport == None: localport = ''
54                 if password == None: password = ''
55                 if is_queued == True:
56                         is_queued = 1
57                 else:
58                         is_queued = 0
59                 self.send_msg(LATCP_CMD_TERMINALSESSION, '%c%c%s%c%s%c%s%c%s%c%s' % \
60                         (is_queued,
61                          len(service), service,
62                          len(node), node,
63                          len(port), port,
64                          len(localport), localport,
65                          len(password), password
66                          ))
67                 (cmd, msg) = self.read_reply()
68                 if ord(cmd) == LATCP_CMD_ERRORMSG:
69                         raise LATClientException(msg)
70
71                 self.rfh = self.sock.makefile('r')
72                 self.wfh = self.sock.makefile('w')
73
74                 r = select([self.rfh], [], [], 2.0)[0]
75                 if r:
76                         l = self.rfh.readline()
77                         if l.find('Service in use') >= 0:
78                                 print "Service in use, apparently: restarting DEC server"
79                                 self.reboot_server()
80
81         def __del__(self):
82                 try:
83                         self.sock.close()
84                         self.sock.shutdown(2)
85                 except:
86                         pass
87                 del self.sock
88
89         def send_msg(self, cmd, msg):
90                 self.sock.send('%c%c%c%s'%(cmd, len(msg)/256, len(msg)%256, msg))
91
92         def reboot_server(self):
93                 self.sock.shutdown(2)
94                 self.sock.close()
95                 mopw, mopr = popen4('/usr/sbin/moprc '+self.server_name)
96                 write_expecting_echo(mopr, mopw, '\n')
97                 read_for_a_bit(mopr)
98                 write_expecting_echo(mopr, mopw, self.connect_password+'\n')
99                 read_for_a_bit(mopr)
100                 write_expecting_echo(mopr, mopw, 'grim reaper\n')
101                 read_for_a_bit(mopr)
102                 write_expecting_echo(mopr, mopw, 'set priv\n')
103                 read_for_a_bit(mopr)
104                 write_expecting_echo(mopr, mopw, self.priv_password+'\n')
105                 read_for_a_bit(mopr)
106                 write_expecting_echo(mopr, mopw, 'init del 0\n')
107                 read_for_a_bit(mopr)
108                 mopr.close()
109                 mopw.close()
110                 print
111                 print "Waiting 10 seconds for DEC server to come back to life..."
112                 sleep(10)
113                 print "Rightyo, back to vending!"
114                 print
115                 raise LATClientException('needed to reboot server')
116
117         def read_reply(self):
118                 head = self.sock.recv(3)
119                 if len(head) != 3:
120                         raise LATClientException('Short LAT packet')
121                 cmd = head[0]
122                 length = ord(head[1])*256 + ord(head[2])
123                 msg = self.sock.recv(length)
124                 if cmd == LATCP_CMD_ERRORMSG:
125                         raise LATClientException('Received LAT error: %s'%msg)
126                 return (cmd, msg)
127         
128         def get_fh(self):
129                 return (self.rfh, self.wfh)

UCC git Repository :: git.ucc.asn.au