ffa896349b64c0162033aecdbf4321ccf799c905
[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                 read_for_a_bit(mopr)
97                 write_expecting_echo(mopr, mopw, '\n')
98                 read_for_a_bit(mopr)
99                 write_expecting_echo(mopr, mopw, self.connect_password+'\n')
100                 read_for_a_bit(mopr)
101                 write_expecting_echo(mopr, mopw, 'grim reaper\n')
102                 read_for_a_bit(mopr)
103                 write_expecting_echo(mopr, mopw, 'set priv\n')
104                 read_for_a_bit(mopr)
105                 write_expecting_echo(mopr, mopw, self.priv_password+'\n')
106                 read_for_a_bit(mopr)
107                 write_expecting_echo(mopr, mopw, 'init del 0\n')
108                 read_for_a_bit(mopr)
109                 mopr.close()
110                 mopw.close()
111                 print
112                 print "Waiting 10 seconds for DEC server to come back to life..."
113                 sleep(10)
114                 print "Rightyo, back to vending!"
115                 print
116                 raise LATClientException('needed to reboot server')
117
118         def read_reply(self):
119                 head = self.sock.recv(3)
120                 if len(head) != 3:
121                         raise LATClientException('Short LAT packet')
122                 cmd = head[0]
123                 length = ord(head[1])*256 + ord(head[2])
124                 msg = self.sock.recv(length)
125                 if cmd == LATCP_CMD_ERRORMSG:
126                         raise LATClientException('Received LAT error: %s'%msg)
127                 return (cmd, msg)
128         
129         def get_fh(self):
130                 return (self.rfh, self.wfh)

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